TMD 6x10: fixes to OTC side of the MCG display panel code merge
[platform/kernel/kernel-mfld-blackbay.git] / drivers / staging / mrst / drv / psb_powermgmt.c
1 /**************************************************************************
2  * Copyright (c) 2009, Intel Corporation.
3  * All Rights Reserved.
4
5  * Permission is hereby granted, free of charge, to any person obtaining a
6  * copy of this software and associated documentation files (the "Software"),
7  * to deal in the Software without restriction, including without limitation
8  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9  * and/or sell copies of the Software, and to permit persons to whom the
10  * Software is furnished to do so, subject to the following conditions:
11  *
12  * The above copyright notice and this permission notice (including the next
13  * paragraph) shall be included in all copies or substantial portions of the
14  * Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
19  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22  * SOFTWARE.
23  *
24  * Authors:
25  *    Benjamin Defnet <benjamin.r.defnet@intel.com>
26  *    Rajesh Poornachandran <rajesh.poornachandran@intel.com>
27  *
28  */
29 #include "psb_powermgmt.h"
30 #include "psb_drv.h"
31 #include "psb_intel_reg.h"
32 #include "psb_msvdx.h"
33 #include "pnw_topaz.h"
34 #include "mdfld_gl3.h"
35 #include "pvr_trace_cmd.h"
36
37 #include <linux/mutex.h>
38 #include <linux/intel_mid_pm.h>
39 #include "mdfld_dsi_dbi.h"
40 #include "mdfld_dsi_dbi_dpu.h"
41 #include <asm/intel_scu_ipc.h>
42
43 #undef OSPM_GFX_DPK
44
45 struct drm_device *gpDrmDevice = NULL;
46 static struct mutex g_ospm_mutex;
47 static int g_hw_power_status_mask;
48 static atomic_t g_display_access_count;
49 static atomic_t g_graphics_access_count;
50 static atomic_t g_videoenc_access_count;
51 static atomic_t g_videodec_access_count;
52
53 void ospm_power_island_up(int hw_islands);
54 void ospm_power_island_down(int hw_islands);
55 static bool gbSuspended = false;
56 static int psb_runtime_hdmi_audio_suspend(struct drm_device *drm_dev);
57
58 #if 1
59 static int ospm_runtime_check_msvdx_hw_busy(struct drm_device *dev)
60 {
61         struct drm_psb_private *dev_priv = dev->dev_private;
62         struct msvdx_private *msvdx_priv = dev_priv->msvdx_private;
63         int ret = 1;
64
65         if (!ospm_power_is_hw_on(OSPM_VIDEO_DEC_ISLAND)) {
66                 //printk(KERN_ALERT "%s VIDEO DEC HW is not on\n", __func__);
67                 ret = -1;
68                 goto out;
69         }
70
71         msvdx_priv->msvdx_hw_busy = REG_READ(0x20D0) & (0x1 << 9);
72         if (psb_check_msvdx_idle(dev)) {
73                 //printk(KERN_ALERT "%s video decode hw busy\n", __func__);
74                 ret = 1;
75         } else {
76                 //printk(KERN_ALERT "%s video decode hw idle\n", __func__);
77                 ret = 0;
78         }
79 out:
80         return ret;
81 }
82
83 static int ospm_runtime_check_topaz_hw_busy(struct drm_device *dev)
84 {
85         //struct drm_psb_private *dev_priv = dev->dev_private;
86         //struct topaz_private *topaz_priv = dev_priv->topaz_private;
87         int ret = 1;
88
89         if (!ospm_power_is_hw_on(OSPM_VIDEO_ENC_ISLAND)) {
90                 //printk(KERN_ALERT "%s VIDEO ENC HW is not on\n", __func__);
91                 ret = -1;
92                 goto out;
93         }
94
95         //topaz_priv->topaz_hw_busy = REG_READ(0x20D0) & (0x1 << 11);
96
97         if (pnw_check_topaz_idle(dev)) {
98                 //printk(KERN_ALERT "%s video encode hw busy %d\n", __func__,
99                 //       topaz_priv->topaz_hw_busy);
100                 ret = 1;
101         } else {
102                 //printk(KERN_ALERT "%s video encode hw idle\n", __func__);
103                 ret = 0;
104         }
105 out:
106         return ret;
107 }
108
109 static int ospm_runtime_pm_msvdx_suspend(struct drm_device *dev)
110 {
111         int ret = 0;
112         struct drm_psb_private *dev_priv = dev->dev_private;
113         struct msvdx_private *msvdx_priv = dev_priv->msvdx_private;
114
115         //printk(KERN_ALERT "enter %s\n", __func__);
116
117         if (!ospm_power_is_hw_on(OSPM_VIDEO_DEC_ISLAND)) {
118                 //printk(KERN_ALERT "%s VIDEO DEC HW is not on\n", __func__);
119                 goto out;
120         }
121
122         if (atomic_read(&g_videodec_access_count)) {
123                 //printk(KERN_ALERT "%s videodec access count exit\n", __func__);
124                 ret = -1;
125                 goto out;
126         }
127
128         msvdx_priv->msvdx_hw_busy = REG_READ(0x20D0) & (0x1 << 9);
129         if (psb_check_msvdx_idle(dev)) {
130                 //printk(KERN_ALERT "%s video decode hw busy exit\n", __func__);
131                 ret = -2;
132                 goto out;
133         }
134
135         MSVDX_NEW_PMSTATE(dev, msvdx_priv, PSB_PMSTATE_POWERDOWN);
136         psb_irq_uninstall_islands(dev, OSPM_VIDEO_DEC_ISLAND);
137         psb_msvdx_save_context(dev);
138         ospm_power_island_down(OSPM_VIDEO_DEC_ISLAND);
139         //printk(KERN_ALERT "%s done\n", __func__);
140 out:
141         return ret;
142 }
143
144 static int ospm_runtime_pm_msvdx_resume(struct drm_device *dev)
145 {
146         struct drm_psb_private *dev_priv = dev->dev_private;
147         struct msvdx_private *msvdx_priv = dev_priv->msvdx_private;
148
149         //printk(KERN_ALERT "ospm_runtime_pm_msvdx_resume\n");
150
151         MSVDX_NEW_PMSTATE(dev, msvdx_priv, PSB_PMSTATE_POWERUP);
152
153         psb_msvdx_restore_context(dev);
154
155         return 0;
156 }
157
158 static int ospm_runtime_pm_topaz_suspend(struct drm_device *dev)
159 {
160         int ret = 0;
161         struct drm_psb_private *dev_priv = dev->dev_private;
162         struct pnw_topaz_private *pnw_topaz_priv = dev_priv->topaz_private;
163         struct psb_video_ctx *pos, *n;
164         int encode_ctx = 0, encode_running = 0;
165
166         //printk(KERN_ALERT "enter %s\n", __func__);
167         list_for_each_entry_safe(pos, n, &dev_priv->video_ctx, head) {
168                 int entrypoint = pos->ctx_type & 0xff;
169                 if (entrypoint == VAEntrypointEncSlice ||
170                     entrypoint == VAEntrypointEncPicture) {
171                         encode_ctx = 1;
172                         break;
173                 }
174         }
175
176         /* have encode context, but not started, or is just closed */
177         if (encode_ctx && dev_priv->topaz_ctx)
178                 encode_running = 1;
179
180         if (encode_ctx)
181                 PSB_DEBUG_PM("Topaz: has encode context, running=%d\n",
182                              encode_running);
183         else
184                 PSB_DEBUG_PM("Topaz: no encode context\n");
185
186         if (!ospm_power_is_hw_on(OSPM_VIDEO_ENC_ISLAND)) {
187                 //printk(KERN_ALERT "%s VIDEO ENC HW is not on\n", __func__);
188                 goto out;
189         }
190
191         if (atomic_read(&g_videoenc_access_count)) {
192                 //printk(KERN_ALERT "%s videoenc access count exit\n", __func__);
193                 ret = -1;
194                 goto out;
195         }
196
197         if (pnw_check_topaz_idle(dev)) {
198                 //printk(KERN_ALERT "%s video encode hw busy exit\n", __func__);
199                 ret = -2;
200                 goto out;
201         }
202
203         psb_irq_uninstall_islands(dev, OSPM_VIDEO_ENC_ISLAND);
204
205         if (encode_running) /* has encode session running */
206                 pnw_topaz_save_mtx_state(dev);
207         PNW_TOPAZ_NEW_PMSTATE(dev, pnw_topaz_priv, PSB_PMSTATE_POWERDOWN);
208
209         ospm_power_island_down(OSPM_VIDEO_ENC_ISLAND);
210         //printk(KERN_ALERT "%s done\n", __func__);
211 out:
212         return ret;
213 }
214
215 static int ospm_runtime_pm_topaz_resume(struct drm_device *dev)
216 {
217         struct drm_psb_private *dev_priv = dev->dev_private;
218         struct pnw_topaz_private *pnw_topaz_priv = dev_priv->topaz_private;
219         struct psb_video_ctx *pos, *n;
220         int encode_ctx = 0, encode_running = 0;
221
222         //printk(KERN_ALERT "ospm_runtime_pm_topaz_resume\n");
223         list_for_each_entry_safe(pos, n, &dev_priv->video_ctx, head) {
224                 int entrypoint = pos->ctx_type & 0xff;
225                 if (entrypoint == VAEntrypointEncSlice ||
226                     entrypoint == VAEntrypointEncPicture) {
227                         encode_ctx = 1;
228                         break;
229                 }
230         }
231
232         /* have encode context, but not started, or is just closed */
233         if (encode_ctx && dev_priv->topaz_ctx)
234                 encode_running = 1;
235
236         if (encode_ctx)
237                 PSB_DEBUG_PM("Topaz: has encode context, running=%d\n",
238                              encode_running);
239         else
240                 PSB_DEBUG_PM("Topaz: no encode running\n");
241
242         if (encode_running) { /* has encode session running */
243                 psb_irq_uninstall_islands(dev, OSPM_VIDEO_ENC_ISLAND);
244                 pnw_topaz_restore_mtx_state(dev);
245         }
246         PNW_TOPAZ_NEW_PMSTATE(dev, pnw_topaz_priv, PSB_PMSTATE_POWERUP);
247
248         return 0;
249 }
250 #endif
251
252 #ifdef FIX_OSPM_POWER_DOWN
253 void ospm_apm_power_down_msvdx(struct drm_device *dev)
254 {
255         return;
256         mutex_lock(&g_ospm_mutex);
257
258         if (atomic_read(&g_videodec_access_count))
259                 goto out;
260         if (psb_check_msvdx_idle(dev))
261                 goto out;
262
263         psb_msvdx_save_context(dev);
264 #ifdef FIXME_MRST_VIDEO_DEC
265         ospm_power_island_down(OSPM_VIDEO_DEC_ISLAND);
266 #endif
267 out:
268         mutex_unlock(&g_ospm_mutex);
269         return;
270 }
271
272 void ospm_apm_power_down_topaz(struct drm_device *dev)
273 {
274         return; /* todo for OSPM */
275
276         mutex_lock(&g_ospm_mutex);
277
278         if (atomic_read(&g_videoenc_access_count))
279                 goto out;
280         if (lnc_check_topaz_idle(dev))
281                 goto out;
282
283         lnc_topaz_save_mtx_state(dev);
284         ospm_power_island_down(OSPM_VIDEO_ENC_ISLAND);
285 out:
286         mutex_unlock(&g_ospm_mutex);
287         return;
288 }
289 #else
290 void ospm_apm_power_down_msvdx(struct drm_device *dev)
291 {
292         struct drm_psb_private *dev_priv = dev->dev_private;
293         struct msvdx_private *msvdx_priv = dev_priv->msvdx_private;
294
295         mutex_lock(&g_ospm_mutex);
296         if (!ospm_power_is_hw_on(OSPM_VIDEO_DEC_ISLAND))
297                 goto out;
298
299         if (atomic_read(&g_videodec_access_count))
300                 goto out;
301         if (psb_check_msvdx_idle(dev))
302                 goto out;
303
304         psb_msvdx_save_context(dev);
305         ospm_power_island_down(OSPM_VIDEO_DEC_ISLAND);
306         MSVDX_NEW_PMSTATE(dev, msvdx_priv, PSB_PMSTATE_POWERDOWN);
307 out:
308         mutex_unlock(&g_ospm_mutex);
309         return;
310 }
311
312 void ospm_apm_power_down_topaz(struct drm_device *dev)
313 {
314         struct drm_psb_private *dev_priv = dev->dev_private;
315         struct pnw_topaz_private *pnw_topaz_priv = dev_priv->topaz_private;
316
317         mutex_lock(&g_ospm_mutex);
318
319         if (!ospm_power_is_hw_on(OSPM_VIDEO_ENC_ISLAND))
320                 goto out;
321         if (atomic_read(&g_videoenc_access_count))
322                 goto out;
323         if (pnw_check_topaz_idle(dev))
324                 goto out;
325
326         psb_irq_uninstall_islands(dev, OSPM_VIDEO_ENC_ISLAND);
327         pnw_topaz_save_mtx_state(dev);
328         PNW_TOPAZ_NEW_PMSTATE(dev, pnw_topaz_priv, PSB_PMSTATE_POWERDOWN);
329
330         ospm_power_island_down(OSPM_VIDEO_ENC_ISLAND);
331 out:
332         mutex_unlock(&g_ospm_mutex);
333         return;
334 }
335 #endif
336
337 #ifdef CONFIG_EARLYSUSPEND
338 /*
339  * REVISIT: The early suspend and late resume handlers should not call
340  * pm_runtime_put() and pm_runtime_get_sync() directly, but rather the DPMS
341  * handlers should do it.
342  */
343 static void gfx_early_suspend(struct early_suspend *es)
344 {
345         struct drm_psb_private *dev_priv =
346                 container_of(es, struct drm_psb_private, early_suspend);
347         struct drm_device *dev = dev_priv->dev;
348         struct drm_encoder *encoder;
349
350         dev_dbg(&dev->pdev->dev, "%s\n", __func__);
351         dev_priv->hdmi_audio_busy =
352                         psb_runtime_hdmi_audio_suspend(dev) == -EBUSY;
353
354         mutex_lock(&dev->mode_config.mutex);
355         list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
356                 struct drm_encoder_helper_funcs *ehf = encoder->helper_private;
357                 if (drm_helper_encoder_in_use(encoder) && ehf && ehf->dpms
358 #ifndef JIRA_ANDROID-1553
359         /*
360          * Local MIPI fails to turn back on from a DPMS off/on cycle if
361          * HDMI audio returns busy to disallow system suspend.
362          * Once ANDROID-1553 is fixed, the expectation is to turn off
363          * MIPI but keep display island on if there is active audio
364          * playback over HDMI.
365          * Refer Jira bug# Android-1553 for more details.
366          */
367                         && !dev_priv->hdmi_audio_busy
368 #endif
369                 )
370                         ehf->dpms(encoder, DRM_MODE_DPMS_OFF);
371         }
372         mutex_unlock(&dev->mode_config.mutex);
373
374         pm_runtime_put(&dev->pdev->dev);
375 }
376
377 static void gfx_late_resume(struct early_suspend *es)
378 {
379         struct drm_psb_private *dev_priv =
380                 container_of(es, struct drm_psb_private, early_suspend);
381         struct drm_device *dev = dev_priv->dev;
382         struct drm_encoder *encoder;
383
384         dev_dbg(&dev->pdev->dev, "%s\n", __func__);
385
386         pm_runtime_get_sync(&dev->pdev->dev);
387
388         mutex_lock(&dev->mode_config.mutex);
389         list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
390                 struct drm_encoder_helper_funcs *ehf = encoder->helper_private;
391
392                 if (drm_helper_encoder_in_use(encoder) && ehf && ehf->mode_set
393                     && ehf->dpms
394 #ifndef JIRA_ANDROID-1553
395         /*
396           Local MIPI fails to turn back on from a DPMS off/on cycle if HDMI
397           audio returns busy to disallow system suspend.
398           Once ANDROID-1553 is fixed, the expectation is to turn off MIPI but
399           keep display island on if there is active audio playback over HDMI
400           Refer Jira bug# Android-1553 for more details.
401         */
402                         && !(dev_priv->hdmi_audio_busy)
403 #endif
404                 ) {
405                         struct drm_crtc *crtc = encoder->crtc;
406
407                         if (crtc)
408                                 ehf->mode_set(encoder,
409                                               &crtc->mode,
410                                               &crtc->hwmode);
411                         ehf->dpms(encoder, DRM_MODE_DPMS_ON);
412                 }
413         }
414         mutex_unlock(&dev->mode_config.mutex);
415 }
416 #endif
417
418 static inline unsigned long palette_reg(int pipe, int idx)
419 {
420         return PSB_PALETTE(pipe) + (idx << 2);
421 }
422
423 /*
424  * mdfld_save_pipe_registers
425  *
426  * Description: We are going to suspend so save current display
427  * register state.
428  *
429  * Notes: FIXME_JLIU7 need to add the support for DPI MIPI & HDMI audio
430  */
431 static int mdfld_save_pipe_registers(struct drm_device *dev, int pipe)
432 {
433 #if 0
434         struct drm_psb_private *dev_priv = dev->dev_private;
435         struct psb_pipe_regs *pr = &dev_priv->pipe_regs[pipe];
436         int i;
437
438         PSB_DEBUG_ENTRY("\n");
439
440         switch (pipe) {
441         case 0:
442                 pr->pll_ctrl = PSB_RVDC32(PSB_DSI_PLL_CTRL);
443                 pr->pll_div = PSB_RVDC32(PSB_DSI_PLL_DIV_M1);
444                 pr->mipi_ctrl = PSB_RVDC32(MIPI_PORT_CONTROL(pipe));
445                 break;
446         case 1:
447                 pr->pll_ctrl = PSB_RVDC32(PSB_DPLL_CTRL);
448                 pr->pll_div = PSB_RVDC32(PSB_DPLL_DIV0);
449                 dev_priv->savePFIT_CONTROL = PSB_RVDC32(PFIT_CONTROL);
450                 dev_priv->savePFIT_PGM_RATIOS = PSB_RVDC32(PFIT_PGM_RATIOS);
451                 dev_priv->saveHDMIPHYMISCCTL = PSB_RVDC32(HDMIPHYMISCCTL);
452                 dev_priv->saveHDMIB_CONTROL = PSB_RVDC32(HDMIB_CONTROL);
453                 break;
454         case 2:
455                 pr->mipi_ctrl = PSB_RVDC32(MIPI_PORT_CONTROL(pipe));
456                 break;
457         default:
458                 DRM_ERROR("%s, invalid pipe number. \n", __FUNCTION__);
459                 return -EINVAL;
460         }
461
462         /* Pipe & plane A info */
463         pr->pipe_conf = PSB_RVDC32(PSB_PIPECONF(pipe));
464         pr->dsp_cntr = PSB_RVDC32(PSB_DSPCNTR(pipe));
465
466         pr->htotal              = PSB_RVDC32(PSB_HTOTAL(pipe));
467         pr->hblank              = PSB_RVDC32(PSB_HBLANK(pipe));
468         pr->hsync               = PSB_RVDC32(PSB_HSYNC(pipe));
469         pr->vtotal              = PSB_RVDC32(PSB_VTOTAL(pipe));
470         pr->vblank              = PSB_RVDC32(PSB_VBLANK(pipe));
471         pr->vsync               = PSB_RVDC32(PSB_VSYNC(pipe));
472         pr->src                 = PSB_RVDC32(PSB_PIPESRC(pipe));
473         pr->dsp_stride          = PSB_RVDC32(PSB_DSPSTRIDE(pipe));
474         pr->dsp_line_offs       = PSB_RVDC32(PSB_DSPLINOFF(pipe));
475         pr->dsp_tile_offs       = PSB_RVDC32(PSB_DSPTILEOFF(pipe));
476         pr->dsp_size            = PSB_RVDC32(PSB_DSPSIZE(pipe));
477         pr->dsp_pos             = PSB_RVDC32(PSB_DSPPOS(pipe));
478         pr->dsp_surf            = PSB_RVDC32(PSB_DSPSURF(pipe));
479         pr->dsp_status          = PSB_RVDC32(PSB_PIPESTAT(pipe));
480
481         /*save palette (gamma) */
482         for (i = 0; i < ARRAY_SIZE(pr->palette); i++)
483                 pr->palette[i] = PSB_RVDC32(palette_reg(pipe, i));
484 #endif
485         return 0;
486 }
487 /*
488  * mdfld_save_cursor_overlay_registers
489  *
490  * Description: We are going to suspend so save current cursor and overlay display
491  * register state.
492  */
493 static int mdfld_save_cursor_overlay_registers(struct drm_device *dev)
494 {
495         struct drm_psb_private *dev_priv = dev->dev_private;
496         int i;
497
498         /*save cursor regs*/
499         dev_priv->saveDSPACURSOR_CTRL = PSB_RVDC32(CURACNTR);
500         dev_priv->saveDSPACURSOR_BASE = PSB_RVDC32(CURABASE);
501         dev_priv->saveDSPACURSOR_POS = PSB_RVDC32(CURAPOS);
502
503         dev_priv->saveDSPBCURSOR_CTRL = PSB_RVDC32(CURBCNTR);
504         dev_priv->saveDSPBCURSOR_BASE = PSB_RVDC32(CURBBASE);
505         dev_priv->saveDSPBCURSOR_POS = PSB_RVDC32(CURBPOS);
506
507         dev_priv->saveDSPCCURSOR_CTRL = PSB_RVDC32(CURCCNTR);
508         dev_priv->saveDSPCCURSOR_BASE = PSB_RVDC32(CURCBASE);
509         dev_priv->saveDSPCCURSOR_POS = PSB_RVDC32(CURCPOS);
510
511         /* HW overlay */
512         for (i = 0; i < ARRAY_SIZE(dev_priv->overlays); i++)
513                 mdfld_overlay_suspend(dev_priv->overlays[i]);
514
515         return 0;
516 }
517 /*
518  * mdfld_restore_pipe_registers
519  *
520  * Description: We are going to resume so restore display register state.
521  *
522  * Notes: FIXME_JLIU7 need to add the support for DPI MIPI & HDMI audio
523  */
524 static int mdfld_restore_pipe_registers(struct drm_device *dev, int pipe)
525 {
526 #if 0
527         //to get  panel out of ULPS mode.
528         u32 temp = 0;
529         struct drm_psb_private *dev_priv = dev->dev_private;
530         struct psb_pipe_regs *pr = &dev_priv->pipe_regs[pipe];
531         struct mdfld_dsi_dbi_output * dsi_output = dev_priv->dbi_output;
532         struct mdfld_dsi_config * dsi_config = NULL;
533         u32 i = 0;
534         u32 dpll = 0;
535         u32 dpll_reg = 0;
536         u32 pll_div_reg = 0;
537         u32 dpll_val;
538
539         PSB_DEBUG_ENTRY("\n");
540
541         switch (pipe) {
542         case 0:
543                 dpll_reg = PSB_DSI_PLL_CTRL;
544                 pll_div_reg = PSB_DSI_PLL_DIV_M1;
545                 dsi_config = dev_priv->dsi_configs[0];
546                 break;
547         case 1:
548                 dpll_reg = PSB_DPLL_CTRL;
549                 pll_div_reg = PSB_DPLL_DIV0;
550                 break;
551         case 2:
552                 dsi_output = dev_priv->dbi_output2;
553                 dsi_config = dev_priv->dsi_configs[1];
554                 break;
555         default:
556                 DRM_ERROR("%s, invalid pipe number. \n", __FUNCTION__);
557                 return -EINVAL;
558         }
559
560         dpll_val = pr->pll_ctrl & ~DPLL_VCO_ENABLE;
561
562         /*make sure VGA plane is off. it initializes to on after reset!*/
563         PSB_WVDC32(0x80000000, VGACNTRL);
564
565         switch (pipe) {
566         case 1:
567                 PSB_WVDC32(dpll_val & ~DPLL_VCO_ENABLE, dpll_reg);
568                 PSB_RVDC32(dpll_reg);
569                 PSB_WVDC32(pr->pll_div, pll_div_reg);
570                 break;
571
572         case 0:
573                 dpll = PSB_RVDC32(dpll_reg);
574
575                 if (!(dpll & DPLL_VCO_ENABLE)) {
576                         /* When ungating power of DPLL, needs to wait 0.5us before enable the VCO */
577                         if (dpll & MDFLD_PWR_GATE_EN) {
578                                 dpll &= ~MDFLD_PWR_GATE_EN;
579                                 PSB_WVDC32(dpll, dpll_reg);
580                                 /* FIXME_MDFLD PO - change 500 to 1 after PO */
581                                 udelay(500);
582                         }
583
584                         PSB_WVDC32(pr->pll_div, pll_div_reg);
585                         PSB_WVDC32(dpll_val, dpll_reg);
586                         /* FIXME_MDFLD PO - change 500 to 1 after PO */
587                         udelay(500);
588
589                         dpll_val |= DPLL_VCO_ENABLE;
590                         PSB_WVDC32(dpll_val, dpll_reg);
591                         PSB_RVDC32(dpll_reg);
592
593                         if (REG_FLAG_WAIT_SET(PSB_PIPECONF(pipe),
594                                               PIPECONF_DSIPLL_LOCK)) {
595                                 DRM_ERROR("%s, can't lock DSIPLL.\n", __func__);
596                                 return -EINVAL;
597                         }
598                 }
599                 break;
600         }
601
602         PSB_WVDC32(pr->htotal,          PSB_HTOTAL(pipe));
603         PSB_WVDC32(pr->hblank,          PSB_HBLANK(pipe));
604         PSB_WVDC32(pr->hsync,           PSB_HSYNC(pipe));
605         PSB_WVDC32(pr->vtotal,          PSB_VTOTAL(pipe));
606         PSB_WVDC32(pr->vblank,          PSB_VBLANK(pipe));
607         PSB_WVDC32(pr->vsync,           PSB_VSYNC(pipe));
608         PSB_WVDC32(pr->src,             PSB_PIPESRC(pipe));
609         PSB_WVDC32(pr->dsp_status,      PSB_PIPESTAT(pipe));
610         PSB_WVDC32(pr->dsp_stride,      PSB_DSPSTRIDE(pipe));
611         PSB_WVDC32(pr->dsp_line_offs,   PSB_DSPLINOFF(pipe));
612         PSB_WVDC32(pr->dsp_tile_offs,   PSB_DSPTILEOFF(pipe));
613         PSB_WVDC32(pr->dsp_size,        PSB_DSPSIZE(pipe));
614         PSB_WVDC32(pr->dsp_pos,         PSB_DSPPOS(pipe));
615         PSB_WVDC32(pr->dsp_surf,        PSB_DSPSURF(pipe));
616
617         if (pipe == 1) {
618                 /* restore palette (gamma) */
619                 /*DRM_UDELAY(50000); */
620                 for (i = 0; i < ARRAY_SIZE(pr->palette); i++)
621                         PSB_WVDC32(pr->palette[i], palette_reg(pipe, i));
622
623                 PSB_WVDC32(dev_priv->savePFIT_CONTROL, PFIT_CONTROL);
624                 PSB_WVDC32(dev_priv->savePFIT_PGM_RATIOS, PFIT_PGM_RATIOS);
625
626                 /*TODO: resume HDMI port */
627
628                 /*TODO: resume pipe*/
629
630                 /*enable the plane*/
631                 PSB_WVDC32(pr->dsp_cntr & ~DISPLAY_PLANE_ENABLE,
632                            PSB_DSPCNTR(pipe));
633
634                 return 0;
635         }
636
637         /*set up pipe related registers*/
638         PSB_WVDC32(pr->mipi_ctrl, MIPI_PORT_CONTROL(pipe));
639
640         /*setup MIPI adapter + MIPI IP registers*/
641         if (dsi_config)
642                 mdfld_dsi_controller_init(dsi_config, pipe);
643
644         if (in_atomic() || in_interrupt())
645                 mdelay(20);
646         else
647                 msleep(20);
648
649         /*enable the plane*/
650         PSB_WVDC32(pr->dsp_cntr, PSB_DSPCNTR(pipe));
651
652         if (in_atomic() || in_interrupt())
653                 mdelay(20);
654         else
655                 msleep(20);
656
657         /* LP Hold Release */
658         temp = REG_READ(MIPI_PORT_CONTROL(pipe));
659         temp |= LP_OUTPUT_HOLD_RELEASE;
660         REG_WRITE(MIPI_PORT_CONTROL(pipe), temp);
661         mdelay(1);
662
663         if (pipe == PSB_PIPE_A) {
664                 /* Set DSI host to exit from Utra Low Power State */
665                 temp = REG_READ(MIPI_DEVICE_READY_REG(pipe));
666                 temp &= ~ULPS_MASK;
667                 temp |= 0x3;
668                 temp |= EXIT_ULPS_DEV_READY;
669                 REG_WRITE(MIPI_DEVICE_READY_REG(pipe), temp);
670                 mdelay(1);
671
672                 temp = REG_READ(MIPI_DEVICE_READY_REG(pipe));
673                 temp &= ~ULPS_MASK;
674                 temp |= EXITING_ULPS;
675                 REG_WRITE(MIPI_DEVICE_READY_REG(pipe), temp);
676                 mdelay(1);
677         }
678
679         /*enable the pipe*/
680         PSB_WVDC32(pr->pipe_conf, PSB_PIPECONF(pipe));
681
682         /* restore palette (gamma) */
683         /*DRM_UDELAY(50000); */
684         for (i = 0; i < ARRAY_SIZE(pr->palette); i++)
685                 PSB_WVDC32(pr->palette[i], palette_reg(pipe, i));
686 #endif
687         return 0;
688 }
689
690 /*
691  * mdfld_restore_cursor_overlay_registers
692  *
693  * Description: We are going to resume so restore cursor and overlay register state.
694  */
695 static int mdfld_restore_cursor_overlay_registers(struct drm_device *dev)
696 {
697         struct drm_psb_private *dev_priv = dev->dev_private;
698         int i;
699
700         /*Enable Cursor A*/
701         PSB_WVDC32(dev_priv->saveDSPACURSOR_CTRL, CURACNTR);
702         PSB_WVDC32(dev_priv->saveDSPACURSOR_POS, CURAPOS);
703         PSB_WVDC32(dev_priv->saveDSPACURSOR_BASE, CURABASE);
704
705         PSB_WVDC32(dev_priv->saveDSPBCURSOR_CTRL, CURBCNTR);
706         PSB_WVDC32(dev_priv->saveDSPBCURSOR_POS, CURBPOS);
707         PSB_WVDC32(dev_priv->saveDSPBCURSOR_BASE, CURBBASE);
708
709         PSB_WVDC32(dev_priv->saveDSPCCURSOR_CTRL, CURCCNTR);
710         PSB_WVDC32(dev_priv->saveDSPCCURSOR_POS, CURCPOS);
711         PSB_WVDC32(dev_priv->saveDSPCCURSOR_BASE, CURCBASE);
712
713         for (i = 0; i < ARRAY_SIZE(dev_priv->overlays); i++)
714                 mdfld_overlay_resume(dev_priv->overlays[i]);
715
716         return 0;
717 }
718
719 /*
720  * powermgmt_suspend_display
721  *
722  * Description: Suspend the display hardware saving state and disabling
723  * as necessary.
724  */
725 static void ospm_suspend_display(struct drm_device *dev)
726 {
727         struct drm_psb_private *dev_priv = dev->dev_private;
728         //to put panel into ULPS mode.
729         u32 temp = 0;
730         u32 device_ready_reg = DEVICE_READY_REG;
731         u32 mipi_reg = MIPI;
732
733 #ifdef OSPM_GFX_DPK
734         printk(KERN_ALERT "%s \n", __func__);
735 #endif
736         if (!(g_hw_power_status_mask & OSPM_DISPLAY_ISLAND))
737                 return;
738
739         mdfld_save_cursor_overlay_registers(dev);
740
741         mdfld_save_pipe_registers(dev, 0);
742         mdfld_save_pipe_registers(dev, 2);
743         android_hdmi_save_display_registers(dev);
744         /* save the gunit register controlling write-combining */
745         dev_priv->savePERF_MODE = PSB_RVDC32(MRST_PERF_MODE);
746
747         mdfld_disable_crtc(dev, 0);
748         mdfld_disable_crtc(dev, 2);
749         android_disable_hdmi(dev);
750
751         /* Put the panel in ULPS mode for S0ix. */
752         temp = REG_READ(device_ready_reg);
753         temp &= ~ULPS_MASK;
754         temp |= ENTERING_ULPS;
755         REG_WRITE(device_ready_reg, temp);
756
757         //LP Hold
758         temp = REG_READ(mipi_reg);
759         temp &= ~LP_OUTPUT_HOLD;
760         REG_WRITE(mipi_reg, temp);
761         mdelay(1);
762
763         ospm_power_island_down(OSPM_DISPLAY_ISLAND);
764 }
765
766 /*
767  * ospm_resume_display
768  *
769  * Description: Resume the display hardware restoring state and enabling
770  * as necessary.
771  */
772 static void ospm_resume_display(struct drm_device *drm_dev)
773 {
774         struct drm_psb_private *dev_priv = drm_dev->dev_private;
775         struct psb_gtt *pg = dev_priv->pg;
776
777 #ifdef OSPM_GFX_DPK
778         printk(KERN_ALERT "%s \n", __func__);
779 #endif
780         if (g_hw_power_status_mask & OSPM_DISPLAY_ISLAND)
781                 return;
782
783         /* turn on the display power island */
784         ospm_power_island_up(OSPM_DISPLAY_ISLAND);
785
786         PSB_WVDC32(pg->pge_ctl | _PSB_PGETBL_ENABLED, PSB_PGETBL_CTL);
787         pci_write_config_word(drm_dev->pdev, PSB_GMCH_CTRL,
788                               pg->gmch_ctrl | _PSB_GMCH_ENABLED);
789
790         /* Don't reinitialize the GTT as it is unnecessary.  The gtt is
791          * stored in memory so it will automatically be restored.  All
792          * we need to do is restore the PGETBL_CTL which we already do
793          * above.
794          */
795         /*psb_gtt_init(dev_priv->pg, 1);*/
796
797         /* restore gunit register controlling write-combining */
798         PSB_WVDC32(dev_priv->savePERF_MODE, MRST_PERF_MODE);
799         android_hdmi_restore_and_enable_display(drm_dev);
800         mdfld_restore_pipe_registers(drm_dev, 0);
801         mdfld_restore_pipe_registers(drm_dev, 2);
802         mdfld_restore_cursor_overlay_registers(drm_dev);
803 }
804
805 static void pvrcmd_device_power(unsigned type, enum pvr_trcmd_device dev)
806 {
807         struct pvr_trcmd_power *p;
808         if (in_interrupt())
809                 p = pvr_trcmd_reserve(type, 0, "irq", sizeof *p);
810         else
811                 p = pvr_trcmd_reserve(type, task_tgid_nr(current),
812                                 current->comm, sizeof *p);
813         p->dev = dev;
814         pvr_trcmd_commit(p);
815 }
816
817 /*
818  * ospm_suspend_pci
819  *
820  * Description: Suspend the pci device saving state and disabling
821  * as necessary.
822  */
823 static void ospm_suspend_pci(struct pci_dev *pdev)
824 {
825         struct drm_device *dev = pci_get_drvdata(pdev);
826         struct drm_psb_private *dev_priv = dev->dev_private;
827
828         if (gbSuspended)
829                 return;
830
831 #ifdef OSPM_GFX_DPK
832         printk(KERN_ALERT "ospm_suspend_pci\n");
833 #endif
834
835 #ifdef CONFIG_MDFD_GL3
836         gl3_invalidate();
837 #endif
838         pvrcmd_device_power(PVR_TRCMD_SUSPEND, PVR_TRCMD_DEVICE_PCI);
839         /* Power off GL3 after all GFX sub-systems are powered off. */
840         ospm_power_island_down(OSPM_GL3_CACHE_ISLAND);
841
842         pci_read_config_dword(pdev, 0x5C, &dev_priv->saveBSM);
843         pci_read_config_dword(pdev, 0xFC, &dev_priv->saveVBT);
844         pci_read_config_dword(pdev, PSB_PCIx_MSI_ADDR_LOC, &dev_priv->msi_addr);
845         pci_read_config_dword(pdev, PSB_PCIx_MSI_DATA_LOC, &dev_priv->msi_data);
846
847         gbSuspended = true;
848 }
849
850 /*
851  * ospm_resume_pci
852  *
853  * Description: Resume the pci device restoring state and enabling
854  * as necessary.
855  */
856 static bool ospm_resume_pci(struct pci_dev *pdev)
857 {
858         struct drm_device *dev = pci_get_drvdata(pdev);
859         struct drm_psb_private *dev_priv = dev->dev_private;
860
861         if (!gbSuspended)
862                 return true;
863
864 #ifdef OSPM_GFX_DPK
865         printk(KERN_ALERT "ospm_resume_pci\n");
866 #endif
867         pvrcmd_device_power(PVR_TRCMD_RESUME, PVR_TRCMD_DEVICE_PCI);
868
869         pci_write_config_dword(pdev, 0x5c, dev_priv->saveBSM);
870         pci_write_config_dword(pdev, 0xFC, dev_priv->saveVBT);
871         pci_write_config_dword(pdev, PSB_PCIx_MSI_ADDR_LOC, dev_priv->msi_addr);
872         pci_write_config_dword(pdev, PSB_PCIx_MSI_DATA_LOC, dev_priv->msi_data);
873
874         gbSuspended = false;
875
876 #ifdef CONFIG_MDFD_GL3
877         /* Powerup GL3 - can be used by any GFX-sub-system. */
878         ospm_power_island_up(OSPM_GL3_CACHE_ISLAND);
879 #endif
880
881         return true;
882 }
883
884 /*
885  * ospm_power_suspend
886  *
887  * Description: OSPM is telling our driver to suspend so save state
888  * and power down all hardware.
889  */
890 int ospm_power_suspend(struct device *dev)
891 {
892         struct pci_dev *pdev = to_pci_dev(dev);
893         struct drm_device *drm_dev = pci_get_drvdata(pdev);
894         int ret = 0;
895         int graphics_access_count;
896         int videoenc_access_count;
897         int videodec_access_count;
898         int display_access_count;
899         bool suspend_pci = true;
900
901         mutex_lock(&g_ospm_mutex);
902
903         if (gbSuspended)
904                 goto out;
905
906         graphics_access_count = atomic_read(&g_graphics_access_count);
907         videoenc_access_count = atomic_read(&g_videoenc_access_count);
908         videodec_access_count = atomic_read(&g_videodec_access_count);
909         display_access_count = atomic_read(&g_display_access_count);
910
911         if (graphics_access_count || videoenc_access_count ||
912                 videodec_access_count || display_access_count) {
913                 ret = -EBUSY;
914
915                 printk(KERN_ALERT "%s: device busy: graphics %d videoenc %d videodec %d display %d\n",
916                         __func__, graphics_access_count, videoenc_access_count,
917                         videodec_access_count, display_access_count);
918                 goto out;
919         }
920
921         psb_irq_uninstall_islands(drm_dev, OSPM_DISPLAY_ISLAND);
922         ospm_suspend_display(drm_dev);
923
924         /* FIXME: video driver support for Linux Runtime PM */
925         if (ospm_runtime_pm_msvdx_suspend(drm_dev))
926                 suspend_pci = false;
927
928         if (ospm_runtime_pm_topaz_suspend(drm_dev))
929                 suspend_pci = false;
930
931         if (suspend_pci)
932                 ospm_suspend_pci(pdev);
933         /*
934          * REVISIT: else pci is not suspended but this happily returns success
935          * status?!
936          */
937
938         pci_save_state(pdev);
939         pci_set_power_state(pdev, PCI_D3hot);
940 out:
941         mutex_unlock(&g_ospm_mutex);
942         return ret;
943 }
944
945 /* The PMU/P-Unit driver has different island definitions */
946 static int to_pmu_islands(int reg_type, int islands)
947 {
948         int ret = 0;
949
950         if (reg_type == APM_REG_TYPE) {
951                 if (islands & OSPM_GRAPHICS_ISLAND)
952                         ret |= APM_GRAPHICS_ISLAND;
953                 if (islands & OSPM_VIDEO_DEC_ISLAND)
954                         ret |= APM_VIDEO_DEC_ISLAND;
955                 if (islands & OSPM_VIDEO_ENC_ISLAND)
956                         ret |= APM_VIDEO_ENC_ISLAND;
957                 if (islands & OSPM_GL3_CACHE_ISLAND)
958                         ret |= APM_GL3_CACHE_ISLAND;
959         } else if (reg_type == OSPM_REG_TYPE) {
960                 if (islands & OSPM_DISPLAY_ISLAND)
961                         ret |= OSPM_DISPLAY_A_ISLAND | OSPM_DISPLAY_B_ISLAND |
962                                 OSPM_DISPLAY_C_ISLAND | OSPM_MIPI_ISLAND;
963         }
964
965         return ret;
966 }
967
968 static int ospm_set_power_state(int state_type, int islands)
969 {
970         int pmu_islands;
971
972         pmu_islands = to_pmu_islands(APM_REG_TYPE, islands);
973         if (pmu_islands)
974                 pmu_nc_set_power_state(pmu_islands, state_type, APM_REG_TYPE);
975
976         pmu_islands = to_pmu_islands(OSPM_REG_TYPE, islands);
977         if (pmu_islands)
978                 pmu_nc_set_power_state(pmu_islands, state_type, OSPM_REG_TYPE);
979
980         return 0;
981 }
982
983 /*
984  * ospm_power_island_up
985  *
986  * Description: Restore power to the specified island(s) (powergating)
987  */
988 void ospm_power_island_up(int islands)
989 {
990 #ifndef CONFIG_MDFD_GL3
991         islands &= ~OSPM_GL3_CACHE_ISLAND;
992 #endif
993
994         if (islands & OSPM_GRAPHICS_ISLAND)
995                 pvrcmd_device_power(PVR_TRCMD_RESUME, PVR_TRCMD_DEVICE_SGX);
996
997         if (islands & OSPM_DISPLAY_ISLAND)
998                 pvrcmd_device_power(PVR_TRCMD_RESUME, PVR_TRCMD_DEVICE_DISPC);
999
1000         ospm_set_power_state(OSPM_ISLAND_UP, islands);
1001
1002         g_hw_power_status_mask |= islands;
1003 }
1004
1005 /*
1006  * ospm_power_island_down
1007  *
1008  * Description: Cut power to the specified island(s) (powergating)
1009  */
1010 void ospm_power_island_down(int islands)
1011 {
1012         g_hw_power_status_mask &= ~islands;
1013
1014         if (islands & OSPM_GRAPHICS_ISLAND)
1015                 pvrcmd_device_power(PVR_TRCMD_SUSPEND, PVR_TRCMD_DEVICE_SGX);
1016
1017         if (islands & OSPM_DISPLAY_ISLAND)
1018                 pvrcmd_device_power(PVR_TRCMD_SUSPEND, PVR_TRCMD_DEVICE_DISPC);
1019
1020         ospm_set_power_state(OSPM_ISLAND_DOWN, islands);
1021 }
1022
1023 /*
1024  * ospm_power_resume
1025  */
1026 int ospm_power_resume(struct device *dev)
1027 {
1028         struct pci_dev *pdev = to_pci_dev(dev);
1029         struct drm_device *drm_dev = pci_get_drvdata(pdev);
1030
1031         mutex_lock(&g_ospm_mutex);
1032
1033 #ifdef OSPM_GFX_DPK
1034         printk(KERN_ALERT "OSPM_GFX_DPK: ospm_power_resume \n");
1035 #endif
1036
1037         ospm_resume_pci(pdev);
1038
1039         pci_set_power_state(pdev, PCI_D0);
1040         pci_restore_state(pdev);
1041         ospm_resume_display(drm_dev);
1042         psb_irq_preinstall_islands(drm_dev, OSPM_DISPLAY_ISLAND);
1043         psb_irq_postinstall_islands(drm_dev, OSPM_DISPLAY_ISLAND);
1044
1045         mutex_unlock(&g_ospm_mutex);
1046
1047         return 0;
1048 }
1049
1050 /*
1051  * ospm_power_is_hw_on
1052  *
1053  * Description: do an instantaneous check for if the specified islands
1054  * are on.  Only use this in cases where you know the g_state_change_mutex
1055  * is already held such as in irq install/uninstall.  Otherwise, use
1056  * ospm_power_using_hw_begin().
1057  */
1058 bool ospm_power_is_hw_on(int hw_islands)
1059 {
1060         return ((g_hw_power_status_mask & hw_islands) == hw_islands) ? true : false;
1061 }
1062
1063 bool ospm_power_using_hw_begin_atomic(int hw_island)
1064 {
1065         struct drm_device *drm_dev = gpDrmDevice; /* FIXME: Pass as parameter */
1066
1067         /* fail if island is off, no can do in atomic context  */
1068         if (!(g_hw_power_status_mask & hw_island))
1069                 return false;
1070
1071         pm_runtime_get(&drm_dev->pdev->dev);
1072
1073         switch (hw_island) {
1074         case OSPM_GRAPHICS_ISLAND:
1075                 atomic_inc(&g_graphics_access_count);
1076                 break;
1077         case OSPM_VIDEO_ENC_ISLAND:
1078                 atomic_inc(&g_videoenc_access_count);
1079                 break;
1080         case OSPM_VIDEO_DEC_ISLAND:
1081                 atomic_inc(&g_videodec_access_count);
1082                 break;
1083         case OSPM_DISPLAY_ISLAND:
1084                 atomic_inc(&g_display_access_count);
1085                 break;
1086         }
1087
1088         return true;
1089 }
1090
1091 /*
1092  * ospm_power_using_hw_begin
1093  *
1094  * Description: Notify PowerMgmt module that you will be accessing the
1095  * specified island's hw so don't power it off.  If force_on is true,
1096  * this will power on the specified island if it is off.
1097  * Otherwise, this will return false and the caller is expected to not
1098  * access the hw.
1099  *
1100  * NOTE *** If this is called from and interrupt handler or other atomic
1101  * context, then it will return false if we are in the middle of a
1102  * power state transition and the caller will be expected to handle that
1103  * even if force_on is set to true.
1104  */
1105 bool ospm_power_using_hw_begin(int hw_island, bool force_on)
1106 {
1107         struct drm_device *drm_dev = gpDrmDevice; /* FIXME: Pass as parameter */
1108         bool ret = true;
1109
1110         WARN(in_interrupt() || in_atomic(), "%s called in atomic context\n",
1111                 __func__);
1112
1113         /* no force, increase count if island on, otherwise fail */
1114         if (!force_on)
1115                 return ospm_power_using_hw_begin_atomic(hw_island);
1116
1117         /* note: the runtime pm resume callback takes g_ospm_mutex */
1118         pm_runtime_get_sync(&drm_dev->pdev->dev);
1119
1120         mutex_lock(&g_ospm_mutex);
1121
1122         /* our job here is done if island is already on */
1123         if (g_hw_power_status_mask & hw_island)
1124                 goto increase_count;
1125
1126         switch (hw_island) {
1127         case OSPM_DISPLAY_ISLAND:
1128                 ospm_resume_display(drm_dev);
1129                 psb_irq_preinstall_islands(drm_dev, OSPM_DISPLAY_ISLAND);
1130                 psb_irq_postinstall_islands(drm_dev, OSPM_DISPLAY_ISLAND);
1131                 break;
1132
1133         case OSPM_GRAPHICS_ISLAND:
1134                 ospm_power_island_up(OSPM_GRAPHICS_ISLAND);
1135                 psb_irq_preinstall_islands(drm_dev, OSPM_GRAPHICS_ISLAND);
1136                 psb_irq_postinstall_islands(drm_dev, OSPM_GRAPHICS_ISLAND);
1137                 break;
1138
1139         case OSPM_VIDEO_DEC_ISLAND:
1140                 WARN_ON(!ospm_power_is_hw_on(OSPM_DISPLAY_ISLAND));
1141
1142                 ospm_power_island_up(OSPM_VIDEO_DEC_ISLAND);
1143                 ospm_runtime_pm_msvdx_resume(drm_dev);
1144                 psb_irq_preinstall_islands(drm_dev, OSPM_VIDEO_DEC_ISLAND);
1145                 psb_irq_postinstall_islands(drm_dev, OSPM_VIDEO_DEC_ISLAND);
1146                 break;
1147
1148         case OSPM_VIDEO_ENC_ISLAND:
1149                 WARN_ON(!ospm_power_is_hw_on(OSPM_DISPLAY_ISLAND));
1150
1151                 ospm_power_island_up(OSPM_VIDEO_ENC_ISLAND);
1152                 ospm_runtime_pm_topaz_resume(drm_dev);
1153                 psb_irq_preinstall_islands(drm_dev, OSPM_VIDEO_ENC_ISLAND);
1154                 psb_irq_postinstall_islands(drm_dev, OSPM_VIDEO_ENC_ISLAND);
1155                 break;
1156
1157         default:
1158                 BUG();
1159         }
1160
1161 increase_count:
1162         switch (hw_island) {
1163         case OSPM_GRAPHICS_ISLAND:
1164                 atomic_inc(&g_graphics_access_count);
1165                 break;
1166         case OSPM_VIDEO_ENC_ISLAND:
1167                 atomic_inc(&g_videoenc_access_count);
1168                 break;
1169         case OSPM_VIDEO_DEC_ISLAND:
1170                 atomic_inc(&g_videodec_access_count);
1171                 break;
1172         case OSPM_DISPLAY_ISLAND:
1173                 atomic_inc(&g_display_access_count);
1174                 break;
1175         }
1176
1177         mutex_unlock(&g_ospm_mutex);
1178
1179         return ret;
1180 }
1181
1182
1183 /*
1184  * ospm_power_using_hw_end
1185  *
1186  * Description: Notify PowerMgmt module that you are done accessing the
1187  * specified island's hw so feel free to power it off.  Note that this
1188  * function doesn't actually power off the islands.
1189  */
1190 void ospm_power_using_hw_end(int hw_island)
1191 {
1192         struct drm_device *drm_dev = gpDrmDevice; /* FIXME: Pass as parameter */
1193
1194         switch (hw_island) {
1195         case OSPM_GRAPHICS_ISLAND:
1196                 atomic_dec(&g_graphics_access_count);
1197                 break;
1198         case OSPM_VIDEO_ENC_ISLAND:
1199                 atomic_dec(&g_videoenc_access_count);
1200                 break;
1201         case OSPM_VIDEO_DEC_ISLAND:
1202                 atomic_dec(&g_videodec_access_count);
1203                 break;
1204         case OSPM_DISPLAY_ISLAND:
1205                 atomic_dec(&g_display_access_count);
1206                 break;
1207         }
1208
1209         pm_runtime_put(&drm_dev->pdev->dev);
1210
1211         WARN_ON(atomic_read(&g_graphics_access_count) < 0);
1212         WARN_ON(atomic_read(&g_videoenc_access_count) < 0);
1213         WARN_ON(atomic_read(&g_videodec_access_count) < 0);
1214         WARN_ON(atomic_read(&g_display_access_count) < 0);
1215 }
1216
1217 #ifdef CONFIG_SND_INTELMID_HDMI_AUDIO
1218 static int psb_runtime_hdmi_audio_suspend(struct drm_device *drm_dev)
1219 {
1220         struct drm_psb_private *dev_priv = drm_dev->dev_private;
1221         pm_event_t pm_event = {0};
1222         int r;
1223
1224         if (!dev_priv->had_pvt_data)
1225                 return 0;
1226
1227         r = dev_priv->had_interface->suspend(dev_priv->had_pvt_data, pm_event);
1228
1229         return r ? -EBUSY : 0;
1230 }
1231
1232 static void psb_runtime_hdmi_audio_resume(struct drm_device *drm_dev)
1233 {
1234         struct drm_psb_private *dev_priv = drm_dev->dev_private;
1235
1236         if (dev_priv->had_pvt_data)
1237                 dev_priv->had_interface->resume(dev_priv->had_pvt_data);
1238 }
1239 #else
1240 static inline int psb_runtime_hdmi_audio_suspend(struct drm_device *drm_dev)
1241 {
1242         return 0;
1243 }
1244 static inline void psb_runtime_hdmi_audio_resume(struct drm_device *drm_dev)
1245 {
1246 }
1247 #endif
1248
1249 int psb_runtime_idle(struct device *dev)
1250 {
1251         struct pci_dev *pdev = to_pci_dev(dev);
1252         struct drm_device *drm_dev = pci_get_drvdata(pdev);
1253         struct drm_psb_private *dev_priv = drm_dev->dev_private;
1254
1255         if (dev_priv->dpi_panel_on || dev_priv->dpi_panel_on2 ||
1256             atomic_read(&g_graphics_access_count) ||
1257             atomic_read(&g_videoenc_access_count) ||
1258             atomic_read(&g_videodec_access_count) ||
1259             atomic_read(&g_display_access_count) ||
1260             ospm_runtime_check_msvdx_hw_busy(drm_dev) == 1 ||
1261             ospm_runtime_check_topaz_hw_busy(drm_dev) == 1 ||
1262             dev_priv->hdmi_audio_busy) {
1263
1264 #ifdef OSPM_GFX_DPK
1265                 dev_dbg(&drm_dev->pdev->dev,
1266                         "%s: GFX: %d VEC: %d VED: %d DC: %d\n",
1267                         __func__,
1268                         atomic_read(&g_graphics_access_count),
1269                         atomic_read(&g_videoenc_access_count),
1270                         atomic_read(&g_videodec_access_count),
1271                         atomic_read(&g_display_access_count));
1272 #endif
1273
1274                 return -EBUSY;
1275         }
1276
1277         return 0;
1278 }
1279
1280 int psb_runtime_suspend(struct device *dev)
1281 {
1282         struct pci_dev *pdev = to_pci_dev(dev);
1283         struct drm_device *drm_dev = pci_get_drvdata(pdev);
1284         int r;
1285
1286 #ifdef OSPM_GFX_DPK
1287         dev_dbg(&drm_dev->pdev->dev, "%s\n", __func__);
1288 #endif
1289
1290         r = psb_runtime_idle(dev);
1291         if (r)
1292                 return r;
1293
1294         /* REVISIT: if ospm_power_suspend fails, do what with hdmi audio? */
1295
1296         return ospm_power_suspend(dev);
1297 }
1298
1299 int psb_runtime_resume(struct device *dev)
1300 {
1301         struct pci_dev *pdev = to_pci_dev(dev);
1302         struct drm_device *drm_dev = pci_get_drvdata(pdev);
1303
1304         ospm_power_resume(dev);
1305         psb_runtime_hdmi_audio_resume(drm_dev);
1306
1307         return 0;
1308 }
1309
1310 /*
1311  * ospm_power_init
1312  *
1313  * Description: Initialize this ospm power management module
1314  */
1315 void ospm_power_init(struct drm_device *dev)
1316 {
1317         struct drm_psb_private *dev_priv = dev->dev_private;
1318
1319         gpDrmDevice = dev;
1320
1321         dev_priv->apm_base = MDFLD_MSG_READ32(PSB_PUNIT_PORT, PSB_APMBA) &
1322                 0xffff;
1323
1324         mutex_init(&g_ospm_mutex);
1325
1326         /* Specify the islands to keep powered up at boot */
1327         g_hw_power_status_mask = OSPM_ALL_ISLANDS;
1328 #ifndef CONFIG_MDFD_GL3
1329         g_hw_power_status_mask &= ~OSPM_GL3_CACHE_ISLAND;
1330 #endif
1331
1332         /* Set power island states according to g_hw_power_status_mask */
1333         ospm_set_power_state(OSPM_ISLAND_UP, g_hw_power_status_mask);
1334         ospm_set_power_state(OSPM_ISLAND_DOWN,
1335                         OSPM_ALL_ISLANDS ^ g_hw_power_status_mask);
1336
1337         atomic_set(&g_display_access_count, 0);
1338         atomic_set(&g_graphics_access_count, 0);
1339         atomic_set(&g_videoenc_access_count, 0);
1340         atomic_set(&g_videodec_access_count, 0);
1341
1342 #ifdef CONFIG_EARLYSUSPEND
1343         dev_priv->early_suspend.suspend = gfx_early_suspend;
1344         dev_priv->early_suspend.resume = gfx_late_resume;
1345         dev_priv->early_suspend.level = EARLY_SUSPEND_LEVEL_STOP_DRAWING;
1346         register_early_suspend(&dev_priv->early_suspend);
1347 #endif
1348
1349         /* Runtime PM for PCI drivers. */
1350         pm_runtime_put_noidle(&dev->pdev->dev);
1351 }
1352
1353 /*
1354  * ospm_power_uninit
1355  *
1356  * Description: Uninitialize this ospm power management module
1357  */
1358 void ospm_power_uninit(struct drm_device *drm_dev)
1359 {
1360         /* Runtime PM for PCI drivers. */
1361         pm_runtime_get_noresume(&drm_dev->pdev->dev);
1362
1363         mutex_destroy(&g_ospm_mutex);
1364 }