gma500: Only fiddle with clock gating on PSB
[deliverable/linux.git] / drivers / staging / gma500 / psb_powermgmt.c
CommitLineData
0867b421 1/**************************************************************************
de64ac92 2 * Copyright (c) 2009-2011, Intel Corporation.
0867b421 3 * All Rights Reserved.
de64ac92 4 *
0867b421
AC
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>
c3460fd3
AC
27 * Massively reworked
28 * Alan Cox <alan@linux.intel.com>
0867b421
AC
29 */
30#include "psb_powermgmt.h"
31#include "psb_drv.h"
c3460fd3 32#include "psb_reg.h"
0867b421 33#include "psb_intel_reg.h"
a897854c
AC
34#include "mdfld_output.h"
35#include "mdfld_dsi_output.h"
0867b421
AC
36#include <linux/mutex.h>
37#include <linux/pm_runtime.h>
a897854c
AC
38#include <asm/intel_scu_ipc.h>
39
40/* IPC message and command defines used to enable/disable mipi panel voltages */
41#define IPC_MSG_PANEL_ON_OFF 0xE9
42#define IPC_CMD_PANEL_ON 1
43#define IPC_CMD_PANEL_OFF 0
0867b421 44
0867b421 45static struct mutex power_mutex;
0867b421 46
c3460fd3
AC
47/**
48 * gma_power_init - initialise power manager
49 * @dev: our device
0867b421 50 *
c3460fd3 51 * Set up for power management tracking of our hardware.
0867b421 52 */
c3460fd3 53void gma_power_init(struct drm_device *dev)
0867b421 54{
c3460fd3 55 struct drm_psb_private *dev_priv = dev->dev_private;
0867b421 56
a897854c
AC
57 /* FIXME: need to sort out fetching apm_reg for both platforms ?? */
58
0867b421
AC
59 dev_priv->apm_base = dev_priv->apm_reg & 0xffff;
60 dev_priv->ospm_base &= 0xffff;
61
c3460fd3
AC
62 dev_priv->display_power = true; /* We start active */
63 dev_priv->display_count = 0; /* Currently no users */
64 dev_priv->suspended = false; /* And not suspended */
0867b421 65 mutex_init(&power_mutex);
c3460fd3 66
bcc70a64 67 if (!IS_MRST(dev) && !IS_MFLD(dev)) {
c3460fd3
AC
68 /* FIXME: wants further review */
69 u32 gating = PSB_RSGX32(PSB_CR_CLKGATECTL);
70 /* Disable 2D clock gating */
71 gating &= ~3;
72 gating |= 1;
73 PSB_WSGX32(gating, PSB_CR_CLKGATECTL);
74 PSB_RSGX32(PSB_CR_CLKGATECTL);
75 }
0867b421
AC
76}
77
c3460fd3
AC
78/**
79 * gma_power_uninit - end power manager
80 * @dev: device to end for
0867b421 81 *
c3460fd3 82 * Undo the effects of gma_power_init
0867b421 83 */
c3460fd3 84void gma_power_uninit(struct drm_device *dev)
0867b421
AC
85{
86 mutex_destroy(&power_mutex);
c3460fd3
AC
87 pm_runtime_disable(&dev->pdev->dev);
88 pm_runtime_set_suspended(&dev->pdev->dev);
0867b421
AC
89}
90
91
c3460fd3
AC
92/**
93 * save_display_registers - save registers lost on suspend
94 * @dev: our DRM device
0867b421 95 *
c3460fd3
AC
96 * Save the state we need in order to be able to restore the interface
97 * upon resume from suspend
0867b421
AC
98 */
99static int save_display_registers(struct drm_device *dev)
100{
101 struct drm_psb_private *dev_priv = dev->dev_private;
c3460fd3
AC
102 struct drm_crtc *crtc;
103 struct drm_connector *connector;
0867b421
AC
104
105 /* Display arbitration control + watermarks */
106 dev_priv->saveDSPARB = PSB_RVDC32(DSPARB);
107 dev_priv->saveDSPFW1 = PSB_RVDC32(DSPFW1);
108 dev_priv->saveDSPFW2 = PSB_RVDC32(DSPFW2);
109 dev_priv->saveDSPFW3 = PSB_RVDC32(DSPFW3);
110 dev_priv->saveDSPFW4 = PSB_RVDC32(DSPFW4);
111 dev_priv->saveDSPFW5 = PSB_RVDC32(DSPFW5);
112 dev_priv->saveDSPFW6 = PSB_RVDC32(DSPFW6);
113 dev_priv->saveCHICKENBIT = PSB_RVDC32(DSPCHICKENBIT);
114
c3460fd3 115 /* Save crtc and output state */
0867b421
AC
116 mutex_lock(&dev->mode_config.mutex);
117 list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
c3460fd3 118 if (drm_helper_crtc_in_use(crtc))
0867b421 119 crtc->funcs->save(crtc);
0867b421 120 }
5352161f 121
c3460fd3 122 list_for_each_entry(connector, &dev->mode_config.connector_list, head)
0867b421 123 connector->funcs->save(connector);
0867b421 124
c3460fd3 125 mutex_unlock(&dev->mode_config.mutex);
0867b421
AC
126 return 0;
127}
128
c3460fd3
AC
129/**
130 * restore_display_registers - restore lost register state
131 * @dev: our DRM device
0867b421 132 *
c3460fd3 133 * Restore register state that was lost during suspend and resume.
0867b421
AC
134 */
135static int restore_display_registers(struct drm_device *dev)
136{
137 struct drm_psb_private *dev_priv = dev->dev_private;
c3460fd3
AC
138 struct drm_crtc *crtc;
139 struct drm_connector *connector;
0867b421
AC
140
141 /* Display arbitration + watermarks */
142 PSB_WVDC32(dev_priv->saveDSPARB, DSPARB);
143 PSB_WVDC32(dev_priv->saveDSPFW1, DSPFW1);
144 PSB_WVDC32(dev_priv->saveDSPFW2, DSPFW2);
145 PSB_WVDC32(dev_priv->saveDSPFW3, DSPFW3);
146 PSB_WVDC32(dev_priv->saveDSPFW4, DSPFW4);
147 PSB_WVDC32(dev_priv->saveDSPFW5, DSPFW5);
148 PSB_WVDC32(dev_priv->saveDSPFW6, DSPFW6);
149 PSB_WVDC32(dev_priv->saveCHICKENBIT, DSPCHICKENBIT);
150
151 /*make sure VGA plane is off. it initializes to on after reset!*/
152 PSB_WVDC32(0x80000000, VGACNTRL);
153
154 mutex_lock(&dev->mode_config.mutex);
c3460fd3
AC
155 list_for_each_entry(crtc, &dev->mode_config.crtc_list, head)
156 if (drm_helper_crtc_in_use(crtc))
0867b421 157 crtc->funcs->restore(crtc);
0867b421 158
c3460fd3
AC
159 list_for_each_entry(connector, &dev->mode_config.connector_list, head)
160 connector->funcs->restore(connector);
0867b421 161
c3460fd3 162 mutex_unlock(&dev->mode_config.mutex);
0867b421
AC
163 return 0;
164}
c3460fd3 165
a897854c
AC
166/**
167 * mdfld_save_display_registers - save registers for pipe
168 * @dev: our device
169 * @pipe: pipe to save
170 *
171 * Save the pipe state of the device before we power it off. Keep everything
172 * we need to put it back again
173 */
174static int mdfld_save_display_registers(struct drm_device *dev, int pipe)
175{
176 struct drm_psb_private *dev_priv = dev->dev_private;
177 int i;
178
179 /* register */
180 u32 dpll_reg = MRST_DPLL_A;
181 u32 fp_reg = MRST_FPA0;
182 u32 pipeconf_reg = PIPEACONF;
183 u32 htot_reg = HTOTAL_A;
184 u32 hblank_reg = HBLANK_A;
185 u32 hsync_reg = HSYNC_A;
186 u32 vtot_reg = VTOTAL_A;
187 u32 vblank_reg = VBLANK_A;
188 u32 vsync_reg = VSYNC_A;
189 u32 pipesrc_reg = PIPEASRC;
190 u32 dspstride_reg = DSPASTRIDE;
191 u32 dsplinoff_reg = DSPALINOFF;
192 u32 dsptileoff_reg = DSPATILEOFF;
193 u32 dspsize_reg = DSPASIZE;
194 u32 dsppos_reg = DSPAPOS;
195 u32 dspsurf_reg = DSPASURF;
196 u32 mipi_reg = MIPI;
197 u32 dspcntr_reg = DSPACNTR;
198 u32 dspstatus_reg = PIPEASTAT;
199 u32 palette_reg = PALETTE_A;
200
201 /* pointer to values */
202 u32 *dpll_val = &dev_priv->saveDPLL_A;
203 u32 *fp_val = &dev_priv->saveFPA0;
204 u32 *pipeconf_val = &dev_priv->savePIPEACONF;
205 u32 *htot_val = &dev_priv->saveHTOTAL_A;
206 u32 *hblank_val = &dev_priv->saveHBLANK_A;
207 u32 *hsync_val = &dev_priv->saveHSYNC_A;
208 u32 *vtot_val = &dev_priv->saveVTOTAL_A;
209 u32 *vblank_val = &dev_priv->saveVBLANK_A;
210 u32 *vsync_val = &dev_priv->saveVSYNC_A;
211 u32 *pipesrc_val = &dev_priv->savePIPEASRC;
212 u32 *dspstride_val = &dev_priv->saveDSPASTRIDE;
213 u32 *dsplinoff_val = &dev_priv->saveDSPALINOFF;
214 u32 *dsptileoff_val = &dev_priv->saveDSPATILEOFF;
215 u32 *dspsize_val = &dev_priv->saveDSPASIZE;
216 u32 *dsppos_val = &dev_priv->saveDSPAPOS;
217 u32 *dspsurf_val = &dev_priv->saveDSPASURF;
218 u32 *mipi_val = &dev_priv->saveMIPI;
219 u32 *dspcntr_val = &dev_priv->saveDSPACNTR;
220 u32 *dspstatus_val = &dev_priv->saveDSPASTATUS;
221 u32 *palette_val = dev_priv->save_palette_a;
222
223 switch (pipe) {
224 case 0:
225 break;
226 case 1:
227 /* register */
228 dpll_reg = MDFLD_DPLL_B;
229 fp_reg = MDFLD_DPLL_DIV0;
230 pipeconf_reg = PIPEBCONF;
231 htot_reg = HTOTAL_B;
232 hblank_reg = HBLANK_B;
233 hsync_reg = HSYNC_B;
234 vtot_reg = VTOTAL_B;
235 vblank_reg = VBLANK_B;
236 vsync_reg = VSYNC_B;
237 pipesrc_reg = PIPEBSRC;
238 dspstride_reg = DSPBSTRIDE;
239 dsplinoff_reg = DSPBLINOFF;
240 dsptileoff_reg = DSPBTILEOFF;
241 dspsize_reg = DSPBSIZE;
242 dsppos_reg = DSPBPOS;
243 dspsurf_reg = DSPBSURF;
244 dspcntr_reg = DSPBCNTR;
245 dspstatus_reg = PIPEBSTAT;
246 palette_reg = PALETTE_B;
247
248 /* values */
249 dpll_val = &dev_priv->saveDPLL_B;
250 fp_val = &dev_priv->saveFPB0;
251 pipeconf_val = &dev_priv->savePIPEBCONF;
252 htot_val = &dev_priv->saveHTOTAL_B;
253 hblank_val = &dev_priv->saveHBLANK_B;
254 hsync_val = &dev_priv->saveHSYNC_B;
255 vtot_val = &dev_priv->saveVTOTAL_B;
256 vblank_val = &dev_priv->saveVBLANK_B;
257 vsync_val = &dev_priv->saveVSYNC_B;
258 pipesrc_val = &dev_priv->savePIPEBSRC;
259 dspstride_val = &dev_priv->saveDSPBSTRIDE;
260 dsplinoff_val = &dev_priv->saveDSPBLINOFF;
261 dsptileoff_val = &dev_priv->saveDSPBTILEOFF;
262 dspsize_val = &dev_priv->saveDSPBSIZE;
263 dsppos_val = &dev_priv->saveDSPBPOS;
264 dspsurf_val = &dev_priv->saveDSPBSURF;
265 dspcntr_val = &dev_priv->saveDSPBCNTR;
266 dspstatus_val = &dev_priv->saveDSPBSTATUS;
267 palette_val = dev_priv->save_palette_b;
268 break;
269 case 2:
270 /* register */
271 pipeconf_reg = PIPECCONF;
272 htot_reg = HTOTAL_C;
273 hblank_reg = HBLANK_C;
274 hsync_reg = HSYNC_C;
275 vtot_reg = VTOTAL_C;
276 vblank_reg = VBLANK_C;
277 vsync_reg = VSYNC_C;
278 pipesrc_reg = PIPECSRC;
279 dspstride_reg = DSPCSTRIDE;
280 dsplinoff_reg = DSPCLINOFF;
281 dsptileoff_reg = DSPCTILEOFF;
282 dspsize_reg = DSPCSIZE;
283 dsppos_reg = DSPCPOS;
284 dspsurf_reg = DSPCSURF;
285 mipi_reg = MIPI_C;
286 dspcntr_reg = DSPCCNTR;
287 dspstatus_reg = PIPECSTAT;
288 palette_reg = PALETTE_C;
289
290 /* pointer to values */
291 pipeconf_val = &dev_priv->savePIPECCONF;
292 htot_val = &dev_priv->saveHTOTAL_C;
293 hblank_val = &dev_priv->saveHBLANK_C;
294 hsync_val = &dev_priv->saveHSYNC_C;
295 vtot_val = &dev_priv->saveVTOTAL_C;
296 vblank_val = &dev_priv->saveVBLANK_C;
297 vsync_val = &dev_priv->saveVSYNC_C;
298 pipesrc_val = &dev_priv->savePIPECSRC;
299 dspstride_val = &dev_priv->saveDSPCSTRIDE;
300 dsplinoff_val = &dev_priv->saveDSPCLINOFF;
301 dsptileoff_val = &dev_priv->saveDSPCTILEOFF;
302 dspsize_val = &dev_priv->saveDSPCSIZE;
303 dsppos_val = &dev_priv->saveDSPCPOS;
304 dspsurf_val = &dev_priv->saveDSPCSURF;
305 mipi_val = &dev_priv->saveMIPI_C;
306 dspcntr_val = &dev_priv->saveDSPCCNTR;
307 dspstatus_val = &dev_priv->saveDSPCSTATUS;
308 palette_val = dev_priv->save_palette_c;
309 break;
310 default:
311 DRM_ERROR("%s, invalid pipe number.\n", __func__);
312 return -EINVAL;
313 }
314
315 /* Pipe & plane A info */
316 *dpll_val = PSB_RVDC32(dpll_reg);
317 *fp_val = PSB_RVDC32(fp_reg);
318 *pipeconf_val = PSB_RVDC32(pipeconf_reg);
319 *htot_val = PSB_RVDC32(htot_reg);
320 *hblank_val = PSB_RVDC32(hblank_reg);
321 *hsync_val = PSB_RVDC32(hsync_reg);
322 *vtot_val = PSB_RVDC32(vtot_reg);
323 *vblank_val = PSB_RVDC32(vblank_reg);
324 *vsync_val = PSB_RVDC32(vsync_reg);
325 *pipesrc_val = PSB_RVDC32(pipesrc_reg);
326 *dspstride_val = PSB_RVDC32(dspstride_reg);
327 *dsplinoff_val = PSB_RVDC32(dsplinoff_reg);
328 *dsptileoff_val = PSB_RVDC32(dsptileoff_reg);
329 *dspsize_val = PSB_RVDC32(dspsize_reg);
330 *dsppos_val = PSB_RVDC32(dsppos_reg);
331 *dspsurf_val = PSB_RVDC32(dspsurf_reg);
332 *dspcntr_val = PSB_RVDC32(dspcntr_reg);
333 *dspstatus_val = PSB_RVDC32(dspstatus_reg);
334
335 /*save palette (gamma) */
336 for (i = 0; i < 256; i++)
337 palette_val[i] = PSB_RVDC32(palette_reg + (i<<2));
338
339 if (pipe == 1) {
340 dev_priv->savePFIT_CONTROL = PSB_RVDC32(PFIT_CONTROL);
341 dev_priv->savePFIT_PGM_RATIOS = PSB_RVDC32(PFIT_PGM_RATIOS);
342 dev_priv->saveHDMIPHYMISCCTL = PSB_RVDC32(HDMIPHYMISCCTL);
343 dev_priv->saveHDMIB_CONTROL = PSB_RVDC32(HDMIB_CONTROL);
344 return 0;
345 }
346 *mipi_val = PSB_RVDC32(mipi_reg);
347 return 0;
348}
349
350/**
351 * mdfld_save_cursor_overlay_registers - save cursor overlay info
352 * @dev: our device
353 *
354 * Save the cursor and overlay register state
355 */
356static int mdfld_save_cursor_overlay_registers(struct drm_device *dev)
357{
358 struct drm_psb_private *dev_priv = dev->dev_private;
359
360 /* Save cursor regs */
361 dev_priv->saveDSPACURSOR_CTRL = PSB_RVDC32(CURACNTR);
362 dev_priv->saveDSPACURSOR_BASE = PSB_RVDC32(CURABASE);
363 dev_priv->saveDSPACURSOR_POS = PSB_RVDC32(CURAPOS);
364
365 dev_priv->saveDSPBCURSOR_CTRL = PSB_RVDC32(CURBCNTR);
366 dev_priv->saveDSPBCURSOR_BASE = PSB_RVDC32(CURBBASE);
367 dev_priv->saveDSPBCURSOR_POS = PSB_RVDC32(CURBPOS);
368
369 dev_priv->saveDSPCCURSOR_CTRL = PSB_RVDC32(CURCCNTR);
370 dev_priv->saveDSPCCURSOR_BASE = PSB_RVDC32(CURCBASE);
371 dev_priv->saveDSPCCURSOR_POS = PSB_RVDC32(CURCPOS);
372
373 /* HW overlay */
374 dev_priv->saveOV_OVADD = PSB_RVDC32(OV_OVADD);
375 dev_priv->saveOV_OGAMC0 = PSB_RVDC32(OV_OGAMC0);
376 dev_priv->saveOV_OGAMC1 = PSB_RVDC32(OV_OGAMC1);
377 dev_priv->saveOV_OGAMC2 = PSB_RVDC32(OV_OGAMC2);
378 dev_priv->saveOV_OGAMC3 = PSB_RVDC32(OV_OGAMC3);
379 dev_priv->saveOV_OGAMC4 = PSB_RVDC32(OV_OGAMC4);
380 dev_priv->saveOV_OGAMC5 = PSB_RVDC32(OV_OGAMC5);
381
382 dev_priv->saveOV_OVADD_C = PSB_RVDC32(OV_OVADD + OV_C_OFFSET);
383 dev_priv->saveOV_OGAMC0_C = PSB_RVDC32(OV_OGAMC0 + OV_C_OFFSET);
384 dev_priv->saveOV_OGAMC1_C = PSB_RVDC32(OV_OGAMC1 + OV_C_OFFSET);
385 dev_priv->saveOV_OGAMC2_C = PSB_RVDC32(OV_OGAMC2 + OV_C_OFFSET);
386 dev_priv->saveOV_OGAMC3_C = PSB_RVDC32(OV_OGAMC3 + OV_C_OFFSET);
387 dev_priv->saveOV_OGAMC4_C = PSB_RVDC32(OV_OGAMC4 + OV_C_OFFSET);
388 dev_priv->saveOV_OGAMC5_C = PSB_RVDC32(OV_OGAMC5 + OV_C_OFFSET);
389
390 return 0;
391}
392/*
393 * mdfld_restore_display_registers - restore the state of a pipe
394 * @dev: our device
395 * @pipe: the pipe to restore
396 *
397 * Restore the state of a pipe to that which was saved by the register save
398 * functions.
399 */
400static int mdfld_restore_display_registers(struct drm_device *dev, int pipe)
401{
402 /* To get panel out of ULPS mode */
403 struct drm_psb_private *dev_priv = dev->dev_private;
404 struct mdfld_dsi_config *dsi_config = NULL;
405 u32 i = 0;
406 u32 dpll = 0;
407 u32 timeout = 0;
408 u32 reg_offset = 0;
409
410 /* register */
411 u32 dpll_reg = MRST_DPLL_A;
412 u32 fp_reg = MRST_FPA0;
413 u32 pipeconf_reg = PIPEACONF;
414 u32 htot_reg = HTOTAL_A;
415 u32 hblank_reg = HBLANK_A;
416 u32 hsync_reg = HSYNC_A;
417 u32 vtot_reg = VTOTAL_A;
418 u32 vblank_reg = VBLANK_A;
419 u32 vsync_reg = VSYNC_A;
420 u32 pipesrc_reg = PIPEASRC;
421 u32 dspstride_reg = DSPASTRIDE;
422 u32 dsplinoff_reg = DSPALINOFF;
423 u32 dsptileoff_reg = DSPATILEOFF;
424 u32 dspsize_reg = DSPASIZE;
425 u32 dsppos_reg = DSPAPOS;
426 u32 dspsurf_reg = DSPASURF;
427 u32 dspstatus_reg = PIPEASTAT;
428 u32 mipi_reg = MIPI;
429 u32 dspcntr_reg = DSPACNTR;
430 u32 palette_reg = PALETTE_A;
431
432 /* values */
433 u32 dpll_val = dev_priv->saveDPLL_A & ~DPLL_VCO_ENABLE;
434 u32 fp_val = dev_priv->saveFPA0;
435 u32 pipeconf_val = dev_priv->savePIPEACONF;
436 u32 htot_val = dev_priv->saveHTOTAL_A;
437 u32 hblank_val = dev_priv->saveHBLANK_A;
438 u32 hsync_val = dev_priv->saveHSYNC_A;
439 u32 vtot_val = dev_priv->saveVTOTAL_A;
440 u32 vblank_val = dev_priv->saveVBLANK_A;
441 u32 vsync_val = dev_priv->saveVSYNC_A;
442 u32 pipesrc_val = dev_priv->savePIPEASRC;
443 u32 dspstride_val = dev_priv->saveDSPASTRIDE;
444 u32 dsplinoff_val = dev_priv->saveDSPALINOFF;
445 u32 dsptileoff_val = dev_priv->saveDSPATILEOFF;
446 u32 dspsize_val = dev_priv->saveDSPASIZE;
447 u32 dsppos_val = dev_priv->saveDSPAPOS;
448 u32 dspsurf_val = dev_priv->saveDSPASURF;
449 u32 dspstatus_val = dev_priv->saveDSPASTATUS;
450 u32 mipi_val = dev_priv->saveMIPI;
451 u32 dspcntr_val = dev_priv->saveDSPACNTR;
452 u32 *palette_val = dev_priv->save_palette_a;
453
454 switch (pipe) {
455 case 0:
456 dsi_config = dev_priv->dsi_configs[0];
457 break;
458 case 1:
459 /* register */
460 dpll_reg = MDFLD_DPLL_B;
461 fp_reg = MDFLD_DPLL_DIV0;
462 pipeconf_reg = PIPEBCONF;
463 htot_reg = HTOTAL_B;
464 hblank_reg = HBLANK_B;
465 hsync_reg = HSYNC_B;
466 vtot_reg = VTOTAL_B;
467 vblank_reg = VBLANK_B;
468 vsync_reg = VSYNC_B;
469 pipesrc_reg = PIPEBSRC;
470 dspstride_reg = DSPBSTRIDE;
471 dsplinoff_reg = DSPBLINOFF;
472 dsptileoff_reg = DSPBTILEOFF;
473 dspsize_reg = DSPBSIZE;
474 dsppos_reg = DSPBPOS;
475 dspsurf_reg = DSPBSURF;
476 dspcntr_reg = DSPBCNTR;
477 palette_reg = PALETTE_B;
478 dspstatus_reg = PIPEBSTAT;
479
480 /* values */
481 dpll_val = dev_priv->saveDPLL_B & ~DPLL_VCO_ENABLE;
482 fp_val = dev_priv->saveFPB0;
483 pipeconf_val = dev_priv->savePIPEBCONF;
484 htot_val = dev_priv->saveHTOTAL_B;
485 hblank_val = dev_priv->saveHBLANK_B;
486 hsync_val = dev_priv->saveHSYNC_B;
487 vtot_val = dev_priv->saveVTOTAL_B;
488 vblank_val = dev_priv->saveVBLANK_B;
489 vsync_val = dev_priv->saveVSYNC_B;
490 pipesrc_val = dev_priv->savePIPEBSRC;
491 dspstride_val = dev_priv->saveDSPBSTRIDE;
492 dsplinoff_val = dev_priv->saveDSPBLINOFF;
493 dsptileoff_val = dev_priv->saveDSPBTILEOFF;
494 dspsize_val = dev_priv->saveDSPBSIZE;
495 dsppos_val = dev_priv->saveDSPBPOS;
496 dspsurf_val = dev_priv->saveDSPBSURF;
497 dspcntr_val = dev_priv->saveDSPBCNTR;
498 dspstatus_val = dev_priv->saveDSPBSTATUS;
499 palette_val = dev_priv->save_palette_b;
500 break;
501 case 2:
502 reg_offset = MIPIC_REG_OFFSET;
503
504 /* register */
505 pipeconf_reg = PIPECCONF;
506 htot_reg = HTOTAL_C;
507 hblank_reg = HBLANK_C;
508 hsync_reg = HSYNC_C;
509 vtot_reg = VTOTAL_C;
510 vblank_reg = VBLANK_C;
511 vsync_reg = VSYNC_C;
512 pipesrc_reg = PIPECSRC;
513 dspstride_reg = DSPCSTRIDE;
514 dsplinoff_reg = DSPCLINOFF;
515 dsptileoff_reg = DSPCTILEOFF;
516 dspsize_reg = DSPCSIZE;
517 dsppos_reg = DSPCPOS;
518 dspsurf_reg = DSPCSURF;
519 mipi_reg = MIPI_C;
520 dspcntr_reg = DSPCCNTR;
521 palette_reg = PALETTE_C;
522 dspstatus_reg = PIPECSTAT;
523
524 /* values */
525 pipeconf_val = dev_priv->savePIPECCONF;
526 htot_val = dev_priv->saveHTOTAL_C;
527 hblank_val = dev_priv->saveHBLANK_C;
528 hsync_val = dev_priv->saveHSYNC_C;
529 vtot_val = dev_priv->saveVTOTAL_C;
530 vblank_val = dev_priv->saveVBLANK_C;
531 vsync_val = dev_priv->saveVSYNC_C;
532 pipesrc_val = dev_priv->savePIPECSRC;
533 dspstride_val = dev_priv->saveDSPCSTRIDE;
534 dsplinoff_val = dev_priv->saveDSPCLINOFF;
535 dsptileoff_val = dev_priv->saveDSPCTILEOFF;
536 dspsize_val = dev_priv->saveDSPCSIZE;
537 dsppos_val = dev_priv->saveDSPCPOS;
538 dspsurf_val = dev_priv->saveDSPCSURF;
539 dspstatus_val = dev_priv->saveDSPCSTATUS;
540 mipi_val = dev_priv->saveMIPI_C;
541 dspcntr_val = dev_priv->saveDSPCCNTR;
542 palette_val = dev_priv->save_palette_c;
543
544 dsi_config = dev_priv->dsi_configs[1];
545 break;
546 default:
547 DRM_ERROR("%s, invalid pipe number.\n", __func__);
548 return -EINVAL;
549 }
550
551 /* Make sure VGA plane is off. it initializes to on after reset!*/
552 PSB_WVDC32(0x80000000, VGACNTRL);
553 if (pipe == 1) {
554 PSB_WVDC32(dpll_val & ~DPLL_VCO_ENABLE, dpll_reg);
555 PSB_RVDC32(dpll_reg);
556
557 PSB_WVDC32(fp_val, fp_reg);
558 } else {
559 dpll = PSB_RVDC32(dpll_reg);
560
561 if (!(dpll & DPLL_VCO_ENABLE)) {
562
563 /* When ungating power of DPLL, needs to wait 0.5us before enable the VCO */
564 if (dpll & MDFLD_PWR_GATE_EN) {
565 dpll &= ~MDFLD_PWR_GATE_EN;
566 PSB_WVDC32(dpll, dpll_reg);
567 udelay(500); /* FIXME: 1 ? */
568 }
569
570 PSB_WVDC32(fp_val, fp_reg);
571 PSB_WVDC32(dpll_val, dpll_reg);
572 /* FIXME_MDFLD PO - change 500 to 1 after PO */
573 udelay(500);
574
575 dpll_val |= DPLL_VCO_ENABLE;
576 PSB_WVDC32(dpll_val, dpll_reg);
577 PSB_RVDC32(dpll_reg);
578
579 /* wait for DSI PLL to lock */
580 while ((timeout < 20000) && !(PSB_RVDC32(pipeconf_reg) & PIPECONF_DSIPLL_LOCK)) {
581 udelay(150);
582 timeout++;
583 }
584
585 if (timeout == 20000) {
586 DRM_ERROR("%s, can't lock DSIPLL.\n",
587 __func__);
588 return -EINVAL;
589 }
590 }
591 }
592 /* Restore mode */
593 PSB_WVDC32(htot_val, htot_reg);
594 PSB_WVDC32(hblank_val, hblank_reg);
595 PSB_WVDC32(hsync_val, hsync_reg);
596 PSB_WVDC32(vtot_val, vtot_reg);
597 PSB_WVDC32(vblank_val, vblank_reg);
598 PSB_WVDC32(vsync_val, vsync_reg);
599 PSB_WVDC32(pipesrc_val, pipesrc_reg);
600 PSB_WVDC32(dspstatus_val, dspstatus_reg);
601
602 /* Set up the plane */
603 PSB_WVDC32(dspstride_val, dspstride_reg);
604 PSB_WVDC32(dsplinoff_val, dsplinoff_reg);
605 PSB_WVDC32(dsptileoff_val, dsptileoff_reg);
606 PSB_WVDC32(dspsize_val, dspsize_reg);
607 PSB_WVDC32(dsppos_val, dsppos_reg);
608 PSB_WVDC32(dspsurf_val, dspsurf_reg);
609
610 if (pipe == 1) {
611 PSB_WVDC32(dev_priv->savePFIT_CONTROL, PFIT_CONTROL);
612 PSB_WVDC32(dev_priv->savePFIT_PGM_RATIOS, PFIT_PGM_RATIOS);
613 PSB_WVDC32(dev_priv->saveHDMIPHYMISCCTL, HDMIPHYMISCCTL);
614 PSB_WVDC32(dev_priv->saveHDMIB_CONTROL, HDMIB_CONTROL);
615
616 } else {
617 /* Set up pipe related registers */
618 PSB_WVDC32(mipi_val, mipi_reg);
619 /* Setup MIPI adapter + MIPI IP registers */
620 mdfld_dsi_controller_init(dsi_config, pipe);
621 msleep(20);
622 }
623 /* Enable the plane */
624 PSB_WVDC32(dspcntr_val, dspcntr_reg);
625 msleep(20);
626 /* Enable the pipe */
627 PSB_WVDC32(pipeconf_val, pipeconf_reg);
628
629 for (i = 0; i < 256; i++)
630 PSB_WVDC32(palette_val[i], palette_reg + (i<<2));
631 if (pipe == 1)
632 return 0;
633 if (IS_MFLD(dev) && !mdfld_panel_dpi(dev))
634 mdfld_enable_te(dev, pipe);
635 return 0;
636}
637
638/**
639 * mdfld_restore_cursor_overlay_registers - restore cursor
640 * @dev: our device
641 *
642 * Restore the cursor and overlay state that was saved earlier
643 */
644static int mdfld_restore_cursor_overlay_registers(struct drm_device *dev)
645{
646 struct drm_psb_private *dev_priv = dev->dev_private;
647
648 /* Enable Cursor A */
649 PSB_WVDC32(dev_priv->saveDSPACURSOR_CTRL, CURACNTR);
650 PSB_WVDC32(dev_priv->saveDSPACURSOR_POS, CURAPOS);
651 PSB_WVDC32(dev_priv->saveDSPACURSOR_BASE, CURABASE);
652
653 PSB_WVDC32(dev_priv->saveDSPBCURSOR_CTRL, CURBCNTR);
654 PSB_WVDC32(dev_priv->saveDSPBCURSOR_POS, CURBPOS);
655 PSB_WVDC32(dev_priv->saveDSPBCURSOR_BASE, CURBBASE);
656
657 PSB_WVDC32(dev_priv->saveDSPCCURSOR_CTRL, CURCCNTR);
658 PSB_WVDC32(dev_priv->saveDSPCCURSOR_POS, CURCPOS);
659 PSB_WVDC32(dev_priv->saveDSPCCURSOR_BASE, CURCBASE);
660
661 /* Restore HW overlay */
662 PSB_WVDC32(dev_priv->saveOV_OVADD, OV_OVADD);
663 PSB_WVDC32(dev_priv->saveOV_OGAMC0, OV_OGAMC0);
664 PSB_WVDC32(dev_priv->saveOV_OGAMC1, OV_OGAMC1);
665 PSB_WVDC32(dev_priv->saveOV_OGAMC2, OV_OGAMC2);
666 PSB_WVDC32(dev_priv->saveOV_OGAMC3, OV_OGAMC3);
667 PSB_WVDC32(dev_priv->saveOV_OGAMC4, OV_OGAMC4);
668 PSB_WVDC32(dev_priv->saveOV_OGAMC5, OV_OGAMC5);
669
670 PSB_WVDC32(dev_priv->saveOV_OVADD_C, OV_OVADD + OV_C_OFFSET);
671 PSB_WVDC32(dev_priv->saveOV_OGAMC0_C, OV_OGAMC0 + OV_C_OFFSET);
672 PSB_WVDC32(dev_priv->saveOV_OGAMC1_C, OV_OGAMC1 + OV_C_OFFSET);
673 PSB_WVDC32(dev_priv->saveOV_OGAMC2_C, OV_OGAMC2 + OV_C_OFFSET);
674 PSB_WVDC32(dev_priv->saveOV_OGAMC3_C, OV_OGAMC3 + OV_C_OFFSET);
675 PSB_WVDC32(dev_priv->saveOV_OGAMC4_C, OV_OGAMC4 + OV_C_OFFSET);
676 PSB_WVDC32(dev_priv->saveOV_OGAMC5_C, OV_OGAMC5 + OV_C_OFFSET);
677
678 return 0;
679}
680
c3460fd3
AC
681/**
682 * power_down - power down the display island
683 * @dev: our DRM device
0867b421 684 *
c3460fd3 685 * Power down the display interface of our device
0867b421 686 */
c3460fd3 687static void power_down(struct drm_device *dev)
0867b421
AC
688{
689 struct drm_psb_private *dev_priv = dev->dev_private;
c3460fd3
AC
690 u32 pwr_mask ;
691 u32 pwr_sts;
0867b421 692
c3460fd3
AC
693 if (IS_MRST(dev)) {
694 pwr_mask = PSB_PWRGT_DISPLAY_MASK;
695 outl(pwr_mask, dev_priv->ospm_base + PSB_PM_SSC);
0867b421 696
c3460fd3
AC
697 while (true) {
698 pwr_sts = inl(dev_priv->ospm_base + PSB_PM_SSS);
699 if ((pwr_sts & pwr_mask) == pwr_mask)
700 break;
701 else
702 udelay(10);
703 }
704 dev_priv->display_power = false;
705 }
706}
707
708
709/**
710 * gma_suspend_display - suspend the display logic
711 * @dev: our DRM device
712 *
713 * Suspend the display logic of the graphics interface
a897854c
AC
714 *
715 * FIXME: This ought to be replaced by a dev_priv-> ops interface
716 * where the various platforms register their save/restore methods
717 * and keep them in their own support files.
c3460fd3
AC
718 */
719static void gma_suspend_display(struct drm_device *dev)
720{
721 struct drm_psb_private *dev_priv = dev->dev_private;
722 int pp_stat;
723
724 if (dev_priv->suspended)
0867b421
AC
725 return;
726
a897854c
AC
727 if (IS_MFLD(dev)) {
728 /* FIXME: We need to shut down panels here if using them
729 and once the right bits are merged */
730 mdfld_save_cursor_overlay_registers(dev);
731 mdfld_save_display_registers(dev, 0);
732 mdfld_save_display_registers(dev, 0);
733 mdfld_save_display_registers(dev, 2);
734 mdfld_save_display_registers(dev, 1);
735 mdfld_disable_crtc(dev, 0);
736 mdfld_disable_crtc(dev, 2);
737 mdfld_disable_crtc(dev, 1);
0867b421 738 } else {
a897854c
AC
739 save_display_registers(dev);
740
741 if (dev_priv->iLVDS_enable) {
742 /*shutdown the panel*/
743 PSB_WVDC32(0, PP_CONTROL);
744
745 do {
746 pp_stat = PSB_RVDC32(PP_STATUS);
747 } while (pp_stat & 0x80000000);
748
749 /* Turn off the plane */
750 PSB_WVDC32(0x58000000, DSPACNTR);
751 PSB_WVDC32(0, DSPASURF);/*trigger the plane disable*/
752 /* Wait ~4 ticks */
753 msleep(4);
754
755 /* Turn off pipe */
756 PSB_WVDC32(0x0, PIPEACONF);
757 /* Wait ~8 ticks */
758 msleep(8);
759
760 /* Turn off PLLs */
761 PSB_WVDC32(0, MRST_DPLL_A);
762 } else {
763 PSB_WVDC32(DPI_SHUT_DOWN, DPI_CONTROL_REG);
764 PSB_WVDC32(0x0, PIPEACONF);
765 PSB_WVDC32(0x2faf0000, BLC_PWM_CTL);
766 while (REG_READ(0x70008) & 0x40000000)
767 cpu_relax();
768 while ((PSB_RVDC32(GEN_FIFO_STAT_REG) & DPI_FIFO_EMPTY)
769 != DPI_FIFO_EMPTY)
770 cpu_relax();
771 PSB_WVDC32(0, DEVICE_READY_REG);
772 /* Turn off panel power */
773#ifdef CONFIG_X86_MRST
774 intel_scu_ipc_simple_command(IPC_MSG_PANEL_ON_OFF,
775 IPC_CMD_PANEL_OFF);
776#endif
777 }
0867b421 778 }
c3460fd3 779 power_down(dev);
0867b421
AC
780}
781
782/*
c3460fd3 783 * power_up
0867b421 784 *
c3460fd3 785 * Description: Restore power to the specified island(s) (powergating)
0867b421 786 */
c3460fd3
AC
787static void power_up(struct drm_device *dev)
788{
789 struct drm_psb_private *dev_priv = dev->dev_private;
790 u32 pwr_mask = PSB_PWRGT_DISPLAY_MASK;
791 u32 pwr_sts, pwr_cnt;
792
793 if (IS_MRST(dev)) {
794 pwr_cnt = inl(dev_priv->ospm_base + PSB_PM_SSC);
795 pwr_cnt &= ~pwr_mask;
796 outl(pwr_cnt, (dev_priv->ospm_base + PSB_PM_SSC));
797
798 while (true) {
799 pwr_sts = inl(dev_priv->ospm_base + PSB_PM_SSS);
800 if ((pwr_sts & pwr_mask) == 0)
801 break;
802 else
803 udelay(10);
804 }
805 }
806 dev_priv->suspended = false;
807 dev_priv->display_power = true;
808}
809
810/**
811 * gma_resume_display - resume display side logic
812 *
813 * Resume the display hardware restoring state and enabling
814 * as necessary.
815 */
816static void gma_resume_display(struct pci_dev *pdev)
0867b421
AC
817{
818 struct drm_device *dev = pci_get_drvdata(pdev);
819 struct drm_psb_private *dev_priv = dev->dev_private;
0867b421 820
c3460fd3 821 if (dev_priv->suspended == false)
0867b421
AC
822 return;
823
824 /* turn on the display power island */
c3460fd3 825 power_up(dev);
0867b421 826
6a62730c 827 PSB_WVDC32(dev_priv->pge_ctl | _PSB_PGETBL_ENABLED, PSB_PGETBL_CTL);
0867b421 828 pci_write_config_word(pdev, PSB_GMCH_CTRL,
6a62730c 829 dev_priv->gmch_ctrl | _PSB_GMCH_ENABLED);
0867b421
AC
830
831 /* Don't reinitialize the GTT as it is unnecessary. The gtt is
832 * stored in memory so it will automatically be restored. All
833 * we need to do is restore the PGETBL_CTL which we already do
834 * above.
835 */
836 /*psb_gtt_init(dev_priv->pg, 1);*/
a897854c
AC
837 if (IS_MFLD(dev)) {
838 mdfld_restore_display_registers(dev, 1);
839 mdfld_restore_display_registers(dev, 0);
840 mdfld_restore_display_registers(dev, 2);
841 mdfld_restore_cursor_overlay_registers(dev);
842 } else if (IS_MRST(dev)) {
843 if (!dev_priv->iLVDS_enable) {
844#ifdef CONFIG_X86_MRST
845 intel_scu_ipc_simple_command(IPC_MSG_PANEL_ON_OFF,
846 IPC_CMD_PANEL_ON);
847 /* FIXME: can we avoid this delay ? */
848 msleep(2000); /* wait 2 seconds */
849#endif
850 }
851 }
0867b421
AC
852 restore_display_registers(dev);
853}
854
c3460fd3
AC
855/**
856 * gma_suspend_pci - suspend PCI side
857 * @pdev: PCI device
0867b421 858 *
c3460fd3 859 * Perform the suspend processing on our PCI device state
0867b421 860 */
c3460fd3 861static void gma_suspend_pci(struct pci_dev *pdev)
0867b421
AC
862{
863 struct drm_device *dev = pci_get_drvdata(pdev);
864 struct drm_psb_private *dev_priv = dev->dev_private;
865 int bsm, vbt;
866
c3460fd3 867 if (dev_priv->suspended)
0867b421
AC
868 return;
869
0867b421
AC
870 pci_save_state(pdev);
871 pci_read_config_dword(pdev, 0x5C, &bsm);
872 dev_priv->saveBSM = bsm;
873 pci_read_config_dword(pdev, 0xFC, &vbt);
874 dev_priv->saveVBT = vbt;
875 pci_read_config_dword(pdev, PSB_PCIx_MSI_ADDR_LOC, &dev_priv->msi_addr);
876 pci_read_config_dword(pdev, PSB_PCIx_MSI_DATA_LOC, &dev_priv->msi_data);
877
878 pci_disable_device(pdev);
879 pci_set_power_state(pdev, PCI_D3hot);
880
c3460fd3 881 dev_priv->suspended = true;
0867b421
AC
882}
883
c3460fd3
AC
884/**
885 * gma_resume_pci - resume helper
886 * @dev: our PCI device
0867b421 887 *
c3460fd3
AC
888 * Perform the resume processing on our PCI device state - rewrite
889 * register state and re-enable the PCI device
0867b421 890 */
c3460fd3 891static bool gma_resume_pci(struct pci_dev *pdev)
0867b421
AC
892{
893 struct drm_device *dev = pci_get_drvdata(pdev);
894 struct drm_psb_private *dev_priv = dev->dev_private;
c3460fd3 895 int ret;
0867b421 896
c3460fd3 897 if (!dev_priv->suspended)
0867b421
AC
898 return true;
899
0867b421
AC
900 pci_set_power_state(pdev, PCI_D0);
901 pci_restore_state(pdev);
902 pci_write_config_dword(pdev, 0x5c, dev_priv->saveBSM);
903 pci_write_config_dword(pdev, 0xFC, dev_priv->saveVBT);
904 /* retoring MSI address and data in PCIx space */
905 pci_write_config_dword(pdev, PSB_PCIx_MSI_ADDR_LOC, dev_priv->msi_addr);
906 pci_write_config_dword(pdev, PSB_PCIx_MSI_DATA_LOC, dev_priv->msi_data);
907 ret = pci_enable_device(pdev);
908
909 if (ret != 0)
c3460fd3 910 dev_err(&pdev->dev, "pci_enable failed: %d\n", ret);
0867b421 911 else
c3460fd3
AC
912 dev_priv->suspended = false;
913 return !dev_priv->suspended;
0867b421
AC
914}
915
c3460fd3
AC
916/**
917 * gma_power_suspend - bus callback for suspend
918 * @pdev: our PCI device
919 * @state: suspend type
0867b421 920 *
c3460fd3
AC
921 * Called back by the PCI layer during a suspend of the system. We
922 * perform the necessary shut down steps and save enough state that
923 * we can undo this when resume is called.
0867b421 924 */
c3460fd3 925int gma_power_suspend(struct pci_dev *pdev, pm_message_t state)
0867b421 926{
c3460fd3
AC
927 struct drm_device *dev = pci_get_drvdata(pdev);
928 struct drm_psb_private *dev_priv = dev->dev_private;
0867b421 929
c3460fd3
AC
930 mutex_lock(&power_mutex);
931 if (!dev_priv->suspended) {
932 if (dev_priv->display_count) {
933 mutex_unlock(&power_mutex);
934 return -EBUSY;
0867b421 935 }
c3460fd3
AC
936 psb_irq_uninstall(dev);
937 gma_suspend_display(dev);
938 gma_suspend_pci(pdev);
0867b421 939 }
c3460fd3 940 mutex_unlock(&power_mutex);
0867b421
AC
941 return 0;
942}
943
944
c3460fd3
AC
945/**
946 * gma_power_resume - resume power
947 * @pdev: PCI device
0867b421 948 *
c3460fd3 949 * Resume the PCI side of the graphics and then the displays
0867b421 950 */
c3460fd3 951int gma_power_resume(struct pci_dev *pdev)
0867b421 952{
c3460fd3 953 struct drm_device *dev = pci_get_drvdata(pdev);
0867b421 954
c3460fd3
AC
955 mutex_lock(&power_mutex);
956 gma_resume_pci(pdev);
957 gma_resume_display(pdev);
958 psb_irq_preinstall(dev);
959 psb_irq_postinstall(dev);
960 mutex_unlock(&power_mutex);
961 return 0;
0867b421
AC
962}
963
964
c3460fd3
AC
965
966/**
967 * gma_power_is_on - returne true if power is on
968 * @dev: our DRM device
0867b421 969 *
c3460fd3 970 * Returns true if the display island power is on at this moment
0867b421 971 */
c3460fd3 972bool gma_power_is_on(struct drm_device *dev)
0867b421 973{
c3460fd3
AC
974 struct drm_psb_private *dev_priv = dev->dev_private;
975 return dev_priv->display_power;
0867b421
AC
976}
977
c3460fd3
AC
978
979/**
980 * gma_power_begin - begin requiring power
981 * @dev: our DRM device
982 * @force_on: true to force power on
0867b421 983 *
c3460fd3
AC
984 * Begin an action that requires the display power island is enabled.
985 * We refcount the islands.
5352161f 986 *
c3460fd3 987 * FIXME: locking
0867b421 988 */
c3460fd3 989bool gma_power_begin(struct drm_device *dev, bool force_on)
0867b421 990{
c3460fd3
AC
991 struct drm_psb_private *dev_priv = dev->dev_private;
992 int ret;
0867b421 993
c3460fd3
AC
994 /* Power already on ? */
995 if (dev_priv->display_power) {
996 dev_priv->display_count++;
997 pm_runtime_get(&dev->pdev->dev);
998 return true;
0867b421 999 }
c3460fd3
AC
1000 if (force_on == false)
1001 return false;
1002
1003 /* Ok power up needed */
1004 ret = gma_resume_pci(dev->pdev);
1005 if (ret == 0) {
1006 psb_irq_preinstall(dev);
1007 psb_irq_postinstall(dev);
1008 pm_runtime_get(&dev->pdev->dev);
1009 dev_priv->display_count++;
1010 return true;
0867b421 1011 }
c3460fd3 1012 return false;
0867b421
AC
1013}
1014
1015
c3460fd3
AC
1016/**
1017 * gma_power_end - end use of power
1018 * @dev: Our DRM device
0867b421 1019 *
c3460fd3
AC
1020 * Indicate that one of our gma_power_begin() requested periods when
1021 * the diplay island power is needed has completed.
0867b421 1022 */
c3460fd3 1023void gma_power_end(struct drm_device *dev)
0867b421 1024{
c3460fd3
AC
1025 struct drm_psb_private *dev_priv = dev->dev_private;
1026 dev_priv->display_count--;
1027 WARN_ON(dev_priv->display_count < 0);
1028 pm_runtime_put(&dev->pdev->dev);
0867b421
AC
1029}
1030
1031int psb_runtime_suspend(struct device *dev)
1032{
c3460fd3
AC
1033 static pm_message_t dummy;
1034 return gma_power_suspend(to_pci_dev(dev), dummy);
0867b421
AC
1035}
1036
1037int psb_runtime_resume(struct device *dev)
1038{
1039 return 0;
1040}
1041
1042int psb_runtime_idle(struct device *dev)
1043{
c3460fd3
AC
1044 struct drm_device *drmdev = pci_get_drvdata(to_pci_dev(dev));
1045 struct drm_psb_private *dev_priv = drmdev->dev_private;
1046 if (dev_priv->display_count)
0867b421 1047 return 0;
c3460fd3
AC
1048 else
1049 return 1;
0867b421
AC
1050}
1051
This page took 0.123852 seconds and 5 git commands to generate.