gma500: udelay(20000) it too long again
[pandora-kernel.git] / drivers / staging / gma500 / mdfld_device.c
1 /**************************************************************************
2  * Copyright (c) 2011, Intel Corporation.
3  * All Rights Reserved.
4  *
5  * This program is free software; you can redistribute it and/or modify it
6  * under the terms and conditions of the GNU General Public License,
7  * version 2, as published by the Free Software Foundation.
8  *
9  * This program is distributed in the hope it will be useful, but WITHOUT
10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
12  * more details.
13  *
14  * You should have received a copy of the GNU General Public License along with
15  * this program; if not, write to the Free Software Foundation, Inc.,
16  * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
17  *
18  **************************************************************************/
19
20 #include <linux/backlight.h>
21 #include <drm/drmP.h>
22 #include <drm/drm.h>
23 #include "psb_reg.h"
24 #include "psb_intel_reg.h"
25 #include "psb_drm.h"
26 #include "psb_drv.h"
27 #include "mdfld_output.h"
28 #include "mdfld_dsi_output.h"
29 #include "mid_bios.h"
30
31 /*
32  *      Provide the Medfield specific backlight management
33  */
34
35 #ifdef CONFIG_BACKLIGHT_CLASS_DEVICE
36
37 static int mdfld_brightness;
38 struct backlight_device *mdfld_backlight_device;
39
40 static int mfld_set_brightness(struct backlight_device *bd)
41 {
42         struct drm_device *dev = bl_get_data(mdfld_backlight_device);
43         struct drm_psb_private *dev_priv = dev->dev_private;
44         int level = bd->props.brightness;
45
46         /* Percentage 1-100% being valid */
47         if (level < 1)
48                 level = 1;
49
50         if (gma_power_begin(dev, 0)) {
51                 /* Calculate and set the brightness value */
52                 u32 adjusted_level;
53
54                 /* Adjust the backlight level with the percent in
55                  * dev_priv->blc_adj2;
56                  */
57                 adjusted_level = level * dev_priv->blc_adj2;
58                 adjusted_level = adjusted_level / 100;
59 #if 0
60 #ifndef CONFIG_MDFLD_DSI_DPU
61                 if(!(dev_priv->dsr_fb_update & MDFLD_DSR_MIPI_CONTROL) && 
62                         (dev_priv->dbi_panel_on || dev_priv->dbi_panel_on2)){
63                         mdfld_dsi_dbi_exit_dsr(dev,MDFLD_DSR_MIPI_CONTROL, 0, 0);
64                         dev_dbg(dev->dev, "Out of DSR before set brightness to %d.\n",adjusted_level);
65                 }
66 #endif
67                 mdfld_dsi_brightness_control(dev, 0, adjusted_level);
68
69                 if ((dev_priv->dbi_panel_on2) || (dev_priv->dpi_panel_on2))
70                         mdfld_dsi_brightness_control(dev, 2, adjusted_level);
71 #endif
72                 gma_power_end(dev);
73         }
74         mdfld_brightness = level;
75         return 0;
76 }
77
78 int psb_get_brightness(struct backlight_device *bd)
79 {
80         /* return locally cached var instead of HW read (due to DPST etc.) */
81         /* FIXME: ideally return actual value in case firmware fiddled with
82            it */
83         return mdfld_brightness;
84 }
85
86 static const struct backlight_ops mfld_ops = {
87         .get_brightness = psb_get_brightness,
88         .update_status  = mfld_set_brightness,
89 };
90
91 static int mdfld_backlight_init(struct drm_device *dev)
92 {
93         struct drm_psb_private *dev_priv = dev->dev_private;
94         struct backlight_properties props;
95         memset(&props, 0, sizeof(struct backlight_properties));
96         props.max_brightness = 100;
97         props.type = BACKLIGHT_PLATFORM;
98
99         mdfld_backlight_device = backlight_device_register("mfld-bl",
100                                         NULL, (void *)dev, &mfld_ops, &props);
101                                         
102         if (IS_ERR(mdfld_backlight_device))
103                 return PTR_ERR(mdfld_backlight_device);
104
105         dev_priv->blc_adj1 = 100;
106         dev_priv->blc_adj2 = 100;
107         mdfld_backlight_device->props.brightness = 100;
108         mdfld_backlight_device->props.max_brightness = 100;
109         backlight_update_status(mdfld_backlight_device);
110         dev_priv->backlight_device = mdfld_backlight_device;
111         return 0;
112 }
113
114 #endif
115
116 /*
117  *      Provide the Medfield specific chip logic and low level methods for
118  *      power management.
119  */
120
121 static void mdfld_init_pm(struct drm_device *dev)
122 {
123         /* No work needed here yet */
124 }
125
126 /**
127  * mdfld_save_display_registers -       save registers for pipe
128  * @dev: our device
129  * @pipe: pipe to save
130  *
131  * Save the pipe state of the device before we power it off. Keep everything
132  * we need to put it back again
133  */
134 static int mdfld_save_display_registers(struct drm_device *dev, int pipe)
135 {
136         struct drm_psb_private *dev_priv = dev->dev_private;
137         int i;
138
139         /* register */
140         u32 dpll_reg = MRST_DPLL_A;
141         u32 fp_reg = MRST_FPA0;
142         u32 pipeconf_reg = PIPEACONF;
143         u32 htot_reg = HTOTAL_A;
144         u32 hblank_reg = HBLANK_A;
145         u32 hsync_reg = HSYNC_A;
146         u32 vtot_reg = VTOTAL_A;
147         u32 vblank_reg = VBLANK_A;
148         u32 vsync_reg = VSYNC_A;
149         u32 pipesrc_reg = PIPEASRC;
150         u32 dspstride_reg = DSPASTRIDE;
151         u32 dsplinoff_reg = DSPALINOFF;
152         u32 dsptileoff_reg = DSPATILEOFF;
153         u32 dspsize_reg = DSPASIZE;
154         u32 dsppos_reg = DSPAPOS;
155         u32 dspsurf_reg = DSPASURF;
156         u32 mipi_reg = MIPI;
157         u32 dspcntr_reg = DSPACNTR;
158         u32 dspstatus_reg = PIPEASTAT;
159         u32 palette_reg = PALETTE_A;
160
161         /* pointer to values */
162         u32 *dpll_val = &dev_priv->saveDPLL_A;
163         u32 *fp_val = &dev_priv->saveFPA0;
164         u32 *pipeconf_val = &dev_priv->savePIPEACONF;
165         u32 *htot_val = &dev_priv->saveHTOTAL_A;
166         u32 *hblank_val = &dev_priv->saveHBLANK_A;
167         u32 *hsync_val = &dev_priv->saveHSYNC_A;
168         u32 *vtot_val = &dev_priv->saveVTOTAL_A;
169         u32 *vblank_val = &dev_priv->saveVBLANK_A;
170         u32 *vsync_val = &dev_priv->saveVSYNC_A;
171         u32 *pipesrc_val = &dev_priv->savePIPEASRC;
172         u32 *dspstride_val = &dev_priv->saveDSPASTRIDE;
173         u32 *dsplinoff_val = &dev_priv->saveDSPALINOFF;
174         u32 *dsptileoff_val = &dev_priv->saveDSPATILEOFF;
175         u32 *dspsize_val = &dev_priv->saveDSPASIZE;
176         u32 *dsppos_val = &dev_priv->saveDSPAPOS;
177         u32 *dspsurf_val = &dev_priv->saveDSPASURF;
178         u32 *mipi_val = &dev_priv->saveMIPI;
179         u32 *dspcntr_val = &dev_priv->saveDSPACNTR;
180         u32 *dspstatus_val = &dev_priv->saveDSPASTATUS;
181         u32 *palette_val = dev_priv->save_palette_a;
182
183         switch (pipe) {
184         case 0:
185                 break;
186         case 1:
187                 /* register */
188                 dpll_reg = MDFLD_DPLL_B;
189                 fp_reg = MDFLD_DPLL_DIV0;
190                 pipeconf_reg = PIPEBCONF;
191                 htot_reg = HTOTAL_B;
192                 hblank_reg = HBLANK_B;
193                 hsync_reg = HSYNC_B;
194                 vtot_reg = VTOTAL_B;
195                 vblank_reg = VBLANK_B;
196                 vsync_reg = VSYNC_B;
197                 pipesrc_reg = PIPEBSRC;
198                 dspstride_reg = DSPBSTRIDE;
199                 dsplinoff_reg = DSPBLINOFF;
200                 dsptileoff_reg = DSPBTILEOFF;
201                 dspsize_reg = DSPBSIZE;
202                 dsppos_reg = DSPBPOS;
203                 dspsurf_reg = DSPBSURF;
204                 dspcntr_reg = DSPBCNTR;
205                 dspstatus_reg = PIPEBSTAT;
206                 palette_reg = PALETTE_B;
207
208                 /* values */
209                 dpll_val = &dev_priv->saveDPLL_B;
210                 fp_val = &dev_priv->saveFPB0;
211                 pipeconf_val = &dev_priv->savePIPEBCONF;
212                 htot_val = &dev_priv->saveHTOTAL_B;
213                 hblank_val = &dev_priv->saveHBLANK_B;
214                 hsync_val = &dev_priv->saveHSYNC_B;
215                 vtot_val = &dev_priv->saveVTOTAL_B;
216                 vblank_val = &dev_priv->saveVBLANK_B;
217                 vsync_val = &dev_priv->saveVSYNC_B;
218                 pipesrc_val = &dev_priv->savePIPEBSRC;
219                 dspstride_val = &dev_priv->saveDSPBSTRIDE;
220                 dsplinoff_val = &dev_priv->saveDSPBLINOFF;
221                 dsptileoff_val = &dev_priv->saveDSPBTILEOFF;
222                 dspsize_val = &dev_priv->saveDSPBSIZE;
223                 dsppos_val = &dev_priv->saveDSPBPOS;
224                 dspsurf_val = &dev_priv->saveDSPBSURF;
225                 dspcntr_val = &dev_priv->saveDSPBCNTR;
226                 dspstatus_val = &dev_priv->saveDSPBSTATUS;
227                 palette_val = dev_priv->save_palette_b;
228                 break;
229         case 2:
230                 /* register */
231                 pipeconf_reg = PIPECCONF;
232                 htot_reg = HTOTAL_C;
233                 hblank_reg = HBLANK_C;
234                 hsync_reg = HSYNC_C;
235                 vtot_reg = VTOTAL_C;
236                 vblank_reg = VBLANK_C;
237                 vsync_reg = VSYNC_C;
238                 pipesrc_reg = PIPECSRC;
239                 dspstride_reg = DSPCSTRIDE;
240                 dsplinoff_reg = DSPCLINOFF;
241                 dsptileoff_reg = DSPCTILEOFF;
242                 dspsize_reg = DSPCSIZE;
243                 dsppos_reg = DSPCPOS;
244                 dspsurf_reg = DSPCSURF;
245                 mipi_reg = MIPI_C;
246                 dspcntr_reg = DSPCCNTR;
247                 dspstatus_reg = PIPECSTAT;
248                 palette_reg = PALETTE_C;
249
250                 /* pointer to values */
251                 pipeconf_val = &dev_priv->savePIPECCONF;
252                 htot_val = &dev_priv->saveHTOTAL_C;
253                 hblank_val = &dev_priv->saveHBLANK_C;
254                 hsync_val = &dev_priv->saveHSYNC_C;
255                 vtot_val = &dev_priv->saveVTOTAL_C;
256                 vblank_val = &dev_priv->saveVBLANK_C;
257                 vsync_val = &dev_priv->saveVSYNC_C;
258                 pipesrc_val = &dev_priv->savePIPECSRC;
259                 dspstride_val = &dev_priv->saveDSPCSTRIDE;
260                 dsplinoff_val = &dev_priv->saveDSPCLINOFF;
261                 dsptileoff_val = &dev_priv->saveDSPCTILEOFF;
262                 dspsize_val = &dev_priv->saveDSPCSIZE;
263                 dsppos_val = &dev_priv->saveDSPCPOS;
264                 dspsurf_val = &dev_priv->saveDSPCSURF;
265                 mipi_val = &dev_priv->saveMIPI_C;
266                 dspcntr_val = &dev_priv->saveDSPCCNTR;
267                 dspstatus_val = &dev_priv->saveDSPCSTATUS;
268                 palette_val = dev_priv->save_palette_c;
269                 break;
270         default:
271                 DRM_ERROR("%s, invalid pipe number.\n", __func__);
272                 return -EINVAL;
273         }
274
275         /* Pipe & plane A info */
276         *dpll_val = PSB_RVDC32(dpll_reg);
277         *fp_val = PSB_RVDC32(fp_reg);
278         *pipeconf_val = PSB_RVDC32(pipeconf_reg);
279         *htot_val = PSB_RVDC32(htot_reg);
280         *hblank_val = PSB_RVDC32(hblank_reg);
281         *hsync_val = PSB_RVDC32(hsync_reg);
282         *vtot_val = PSB_RVDC32(vtot_reg);
283         *vblank_val = PSB_RVDC32(vblank_reg);
284         *vsync_val = PSB_RVDC32(vsync_reg);
285         *pipesrc_val = PSB_RVDC32(pipesrc_reg);
286         *dspstride_val = PSB_RVDC32(dspstride_reg);
287         *dsplinoff_val = PSB_RVDC32(dsplinoff_reg);
288         *dsptileoff_val = PSB_RVDC32(dsptileoff_reg);
289         *dspsize_val = PSB_RVDC32(dspsize_reg);
290         *dsppos_val = PSB_RVDC32(dsppos_reg);
291         *dspsurf_val = PSB_RVDC32(dspsurf_reg);
292         *dspcntr_val = PSB_RVDC32(dspcntr_reg);
293         *dspstatus_val = PSB_RVDC32(dspstatus_reg);
294
295         /*save palette (gamma) */
296         for (i = 0; i < 256; i++)
297                 palette_val[i] = PSB_RVDC32(palette_reg + (i<<2));
298
299         if (pipe == 1) {
300                 dev_priv->savePFIT_CONTROL = PSB_RVDC32(PFIT_CONTROL);
301                 dev_priv->savePFIT_PGM_RATIOS = PSB_RVDC32(PFIT_PGM_RATIOS);
302                 dev_priv->saveHDMIPHYMISCCTL = PSB_RVDC32(HDMIPHYMISCCTL);
303                 dev_priv->saveHDMIB_CONTROL = PSB_RVDC32(HDMIB_CONTROL);
304                 return 0;
305         }
306         *mipi_val = PSB_RVDC32(mipi_reg);
307         return 0;
308 }
309
310 /**
311  * mdfld_save_cursor_overlay_registers  -       save cursor overlay info
312  * @dev: our device
313  *
314  * Save the cursor and overlay register state
315  */
316 static int mdfld_save_cursor_overlay_registers(struct drm_device *dev)
317 {
318         struct drm_psb_private *dev_priv = dev->dev_private;
319
320         /* Save cursor regs */
321         dev_priv->saveDSPACURSOR_CTRL = PSB_RVDC32(CURACNTR);
322         dev_priv->saveDSPACURSOR_BASE = PSB_RVDC32(CURABASE);
323         dev_priv->saveDSPACURSOR_POS = PSB_RVDC32(CURAPOS);
324
325         dev_priv->saveDSPBCURSOR_CTRL = PSB_RVDC32(CURBCNTR);
326         dev_priv->saveDSPBCURSOR_BASE = PSB_RVDC32(CURBBASE);
327         dev_priv->saveDSPBCURSOR_POS = PSB_RVDC32(CURBPOS);
328
329         dev_priv->saveDSPCCURSOR_CTRL = PSB_RVDC32(CURCCNTR);
330         dev_priv->saveDSPCCURSOR_BASE = PSB_RVDC32(CURCBASE);
331         dev_priv->saveDSPCCURSOR_POS = PSB_RVDC32(CURCPOS);
332
333         /* HW overlay */
334         dev_priv->saveOV_OVADD = PSB_RVDC32(OV_OVADD);
335         dev_priv->saveOV_OGAMC0 = PSB_RVDC32(OV_OGAMC0);
336         dev_priv->saveOV_OGAMC1 = PSB_RVDC32(OV_OGAMC1);
337         dev_priv->saveOV_OGAMC2 = PSB_RVDC32(OV_OGAMC2);
338         dev_priv->saveOV_OGAMC3 = PSB_RVDC32(OV_OGAMC3);
339         dev_priv->saveOV_OGAMC4 = PSB_RVDC32(OV_OGAMC4);
340         dev_priv->saveOV_OGAMC5 = PSB_RVDC32(OV_OGAMC5);
341
342         dev_priv->saveOV_OVADD_C = PSB_RVDC32(OV_OVADD + OV_C_OFFSET);
343         dev_priv->saveOV_OGAMC0_C = PSB_RVDC32(OV_OGAMC0 + OV_C_OFFSET);
344         dev_priv->saveOV_OGAMC1_C = PSB_RVDC32(OV_OGAMC1 + OV_C_OFFSET);
345         dev_priv->saveOV_OGAMC2_C = PSB_RVDC32(OV_OGAMC2 + OV_C_OFFSET);
346         dev_priv->saveOV_OGAMC3_C = PSB_RVDC32(OV_OGAMC3 + OV_C_OFFSET);
347         dev_priv->saveOV_OGAMC4_C = PSB_RVDC32(OV_OGAMC4 + OV_C_OFFSET);
348         dev_priv->saveOV_OGAMC5_C = PSB_RVDC32(OV_OGAMC5 + OV_C_OFFSET);
349
350         return 0;
351 }
352 /*
353  * mdfld_restore_display_registers      -       restore the state of a pipe
354  * @dev: our device
355  * @pipe: the pipe to restore
356  *
357  * Restore the state of a pipe to that which was saved by the register save
358  * functions.
359  */
360 static int mdfld_restore_display_registers(struct drm_device *dev, int pipe)
361 {
362         /* To get  panel out of ULPS mode */
363         struct drm_psb_private *dev_priv = dev->dev_private;
364         struct mdfld_dsi_config *dsi_config = NULL;
365         u32 i = 0;
366         u32 dpll = 0;
367         u32 timeout = 0;
368         u32 reg_offset = 0;
369
370         /* register */
371         u32 dpll_reg = MRST_DPLL_A;
372         u32 fp_reg = MRST_FPA0;
373         u32 pipeconf_reg = PIPEACONF;
374         u32 htot_reg = HTOTAL_A;
375         u32 hblank_reg = HBLANK_A;
376         u32 hsync_reg = HSYNC_A;
377         u32 vtot_reg = VTOTAL_A;
378         u32 vblank_reg = VBLANK_A;
379         u32 vsync_reg = VSYNC_A;
380         u32 pipesrc_reg = PIPEASRC;
381         u32 dspstride_reg = DSPASTRIDE;
382         u32 dsplinoff_reg = DSPALINOFF;
383         u32 dsptileoff_reg = DSPATILEOFF;
384         u32 dspsize_reg = DSPASIZE;
385         u32 dsppos_reg = DSPAPOS;
386         u32 dspsurf_reg = DSPASURF;
387         u32 dspstatus_reg = PIPEASTAT;
388         u32 mipi_reg = MIPI;
389         u32 dspcntr_reg = DSPACNTR;
390         u32 palette_reg = PALETTE_A;
391
392         /* values */
393         u32 dpll_val = dev_priv->saveDPLL_A & ~DPLL_VCO_ENABLE;
394         u32 fp_val = dev_priv->saveFPA0;
395         u32 pipeconf_val = dev_priv->savePIPEACONF;
396         u32 htot_val = dev_priv->saveHTOTAL_A;
397         u32 hblank_val = dev_priv->saveHBLANK_A;
398         u32 hsync_val = dev_priv->saveHSYNC_A;
399         u32 vtot_val = dev_priv->saveVTOTAL_A;
400         u32 vblank_val = dev_priv->saveVBLANK_A;
401         u32 vsync_val = dev_priv->saveVSYNC_A;
402         u32 pipesrc_val = dev_priv->savePIPEASRC;
403         u32 dspstride_val = dev_priv->saveDSPASTRIDE;
404         u32 dsplinoff_val = dev_priv->saveDSPALINOFF;
405         u32 dsptileoff_val = dev_priv->saveDSPATILEOFF;
406         u32 dspsize_val = dev_priv->saveDSPASIZE;
407         u32 dsppos_val = dev_priv->saveDSPAPOS;
408         u32 dspsurf_val = dev_priv->saveDSPASURF;
409         u32 dspstatus_val = dev_priv->saveDSPASTATUS;
410         u32 mipi_val = dev_priv->saveMIPI;
411         u32 dspcntr_val = dev_priv->saveDSPACNTR;
412         u32 *palette_val = dev_priv->save_palette_a;
413
414         switch (pipe) {
415         case 0:
416                 dsi_config = dev_priv->dsi_configs[0];
417                 break;
418         case 1:
419                 /* register */
420                 dpll_reg = MDFLD_DPLL_B;
421                 fp_reg = MDFLD_DPLL_DIV0;
422                 pipeconf_reg = PIPEBCONF;
423                 htot_reg = HTOTAL_B;
424                 hblank_reg = HBLANK_B;
425                 hsync_reg = HSYNC_B;
426                 vtot_reg = VTOTAL_B;
427                 vblank_reg = VBLANK_B;
428                 vsync_reg = VSYNC_B;
429                 pipesrc_reg = PIPEBSRC;
430                 dspstride_reg = DSPBSTRIDE;
431                 dsplinoff_reg = DSPBLINOFF;
432                 dsptileoff_reg = DSPBTILEOFF;
433                 dspsize_reg = DSPBSIZE;
434                 dsppos_reg = DSPBPOS;
435                 dspsurf_reg = DSPBSURF;
436                 dspcntr_reg = DSPBCNTR;
437                 palette_reg = PALETTE_B;
438                 dspstatus_reg = PIPEBSTAT;
439
440                 /* values */
441                 dpll_val = dev_priv->saveDPLL_B & ~DPLL_VCO_ENABLE;
442                 fp_val = dev_priv->saveFPB0;
443                 pipeconf_val = dev_priv->savePIPEBCONF;
444                 htot_val = dev_priv->saveHTOTAL_B;
445                 hblank_val = dev_priv->saveHBLANK_B;
446                 hsync_val = dev_priv->saveHSYNC_B;
447                 vtot_val = dev_priv->saveVTOTAL_B;
448                 vblank_val = dev_priv->saveVBLANK_B;
449                 vsync_val = dev_priv->saveVSYNC_B;
450                 pipesrc_val = dev_priv->savePIPEBSRC;
451                 dspstride_val = dev_priv->saveDSPBSTRIDE;
452                 dsplinoff_val = dev_priv->saveDSPBLINOFF;
453                 dsptileoff_val = dev_priv->saveDSPBTILEOFF;
454                 dspsize_val = dev_priv->saveDSPBSIZE;
455                 dsppos_val = dev_priv->saveDSPBPOS;
456                 dspsurf_val = dev_priv->saveDSPBSURF;
457                 dspcntr_val = dev_priv->saveDSPBCNTR;
458                 dspstatus_val = dev_priv->saveDSPBSTATUS;
459                 palette_val = dev_priv->save_palette_b;
460                 break;
461         case 2:
462                 reg_offset = MIPIC_REG_OFFSET;
463
464                 /* register */
465                 pipeconf_reg = PIPECCONF;
466                 htot_reg = HTOTAL_C;
467                 hblank_reg = HBLANK_C;
468                 hsync_reg = HSYNC_C;
469                 vtot_reg = VTOTAL_C;
470                 vblank_reg = VBLANK_C;
471                 vsync_reg = VSYNC_C;
472                 pipesrc_reg = PIPECSRC;
473                 dspstride_reg = DSPCSTRIDE;
474                 dsplinoff_reg = DSPCLINOFF;
475                 dsptileoff_reg = DSPCTILEOFF;
476                 dspsize_reg = DSPCSIZE;
477                 dsppos_reg = DSPCPOS;
478                 dspsurf_reg = DSPCSURF;
479                 mipi_reg = MIPI_C;
480                 dspcntr_reg = DSPCCNTR;
481                 palette_reg = PALETTE_C;
482                 dspstatus_reg = PIPECSTAT;
483
484                 /* values */
485                 pipeconf_val = dev_priv->savePIPECCONF;
486                 htot_val = dev_priv->saveHTOTAL_C;
487                 hblank_val = dev_priv->saveHBLANK_C;
488                 hsync_val = dev_priv->saveHSYNC_C;
489                 vtot_val = dev_priv->saveVTOTAL_C;
490                 vblank_val = dev_priv->saveVBLANK_C;
491                 vsync_val = dev_priv->saveVSYNC_C;
492                 pipesrc_val = dev_priv->savePIPECSRC;
493                 dspstride_val = dev_priv->saveDSPCSTRIDE;
494                 dsplinoff_val = dev_priv->saveDSPCLINOFF;
495                 dsptileoff_val = dev_priv->saveDSPCTILEOFF;
496                 dspsize_val = dev_priv->saveDSPCSIZE;
497                 dsppos_val = dev_priv->saveDSPCPOS;
498                 dspsurf_val = dev_priv->saveDSPCSURF;
499                 dspstatus_val = dev_priv->saveDSPCSTATUS;
500                 mipi_val = dev_priv->saveMIPI_C;
501                 dspcntr_val = dev_priv->saveDSPCCNTR;
502                 palette_val = dev_priv->save_palette_c;
503
504                 dsi_config = dev_priv->dsi_configs[1];
505                 break;
506         default:
507                 DRM_ERROR("%s, invalid pipe number.\n", __func__);
508                 return -EINVAL;
509         }
510
511         /* Make sure VGA plane is off. it initializes to on after reset!*/
512         PSB_WVDC32(0x80000000, VGACNTRL);
513         if (pipe == 1) {
514                 PSB_WVDC32(dpll_val & ~DPLL_VCO_ENABLE, dpll_reg);
515                 PSB_RVDC32(dpll_reg);
516
517                 PSB_WVDC32(fp_val, fp_reg);
518         } else {
519                 dpll = PSB_RVDC32(dpll_reg);
520
521                 if (!(dpll & DPLL_VCO_ENABLE)) {
522
523                         /* When ungating power of DPLL, needs to wait 0.5us before enable the VCO */
524                         if (dpll & MDFLD_PWR_GATE_EN) {
525                                 dpll &= ~MDFLD_PWR_GATE_EN;
526                                 PSB_WVDC32(dpll, dpll_reg);
527                                 udelay(500);    /* FIXME: 1 ? */
528                         }
529
530                         PSB_WVDC32(fp_val, fp_reg);
531                         PSB_WVDC32(dpll_val, dpll_reg);
532                         /* FIXME_MDFLD PO - change 500 to 1 after PO */
533                         udelay(500);
534
535                         dpll_val |= DPLL_VCO_ENABLE;
536                         PSB_WVDC32(dpll_val, dpll_reg);
537                         PSB_RVDC32(dpll_reg);
538
539                         /* wait for DSI PLL to lock */
540                         while ((timeout < 20000) && !(PSB_RVDC32(pipeconf_reg) & PIPECONF_DSIPLL_LOCK)) {
541                                 udelay(150);
542                                 timeout++;
543                         }
544
545                         if (timeout == 20000) {
546                                 DRM_ERROR("%s, can't lock DSIPLL.\n",
547                                                         __func__);
548                                 return -EINVAL;
549                         }
550                 }
551         }
552         /* Restore mode */
553         PSB_WVDC32(htot_val, htot_reg);
554         PSB_WVDC32(hblank_val, hblank_reg);
555         PSB_WVDC32(hsync_val, hsync_reg);
556         PSB_WVDC32(vtot_val, vtot_reg);
557         PSB_WVDC32(vblank_val, vblank_reg);
558         PSB_WVDC32(vsync_val, vsync_reg);
559         PSB_WVDC32(pipesrc_val, pipesrc_reg);
560         PSB_WVDC32(dspstatus_val, dspstatus_reg);
561
562         /* Set up the plane */
563         PSB_WVDC32(dspstride_val, dspstride_reg);
564         PSB_WVDC32(dsplinoff_val, dsplinoff_reg);
565         PSB_WVDC32(dsptileoff_val, dsptileoff_reg);
566         PSB_WVDC32(dspsize_val, dspsize_reg);
567         PSB_WVDC32(dsppos_val, dsppos_reg);
568         PSB_WVDC32(dspsurf_val, dspsurf_reg);
569
570         if (pipe == 1) {
571                 PSB_WVDC32(dev_priv->savePFIT_CONTROL, PFIT_CONTROL);
572                 PSB_WVDC32(dev_priv->savePFIT_PGM_RATIOS, PFIT_PGM_RATIOS);
573                 PSB_WVDC32(dev_priv->saveHDMIPHYMISCCTL, HDMIPHYMISCCTL);
574                 PSB_WVDC32(dev_priv->saveHDMIB_CONTROL, HDMIB_CONTROL);
575
576         } else {
577                 /* Set up pipe related registers */
578                 PSB_WVDC32(mipi_val, mipi_reg);
579                 /* Setup MIPI adapter + MIPI IP registers */
580                 mdfld_dsi_controller_init(dsi_config, pipe);
581                 msleep(20);
582         }
583         /* Enable the plane */
584         PSB_WVDC32(dspcntr_val, dspcntr_reg);
585         msleep(20);
586         /* Enable the pipe */
587         PSB_WVDC32(pipeconf_val, pipeconf_reg);
588
589         for (i = 0; i < 256; i++)
590                 PSB_WVDC32(palette_val[i], palette_reg + (i<<2));
591         if (pipe == 1)
592                 return 0;
593         if (!mdfld_panel_dpi(dev))
594                 mdfld_enable_te(dev, pipe);
595         return 0;
596 }
597
598 /**
599  * mdfld_restore_cursor_overlay_registers       -       restore cursor
600  * @dev: our device
601  *
602  * Restore the cursor and overlay state that was saved earlier
603  */
604 static int mdfld_restore_cursor_overlay_registers(struct drm_device *dev)
605 {
606         struct drm_psb_private *dev_priv = dev->dev_private;
607
608         /* Enable Cursor A */
609         PSB_WVDC32(dev_priv->saveDSPACURSOR_CTRL, CURACNTR);
610         PSB_WVDC32(dev_priv->saveDSPACURSOR_POS, CURAPOS);
611         PSB_WVDC32(dev_priv->saveDSPACURSOR_BASE, CURABASE);
612
613         PSB_WVDC32(dev_priv->saveDSPBCURSOR_CTRL, CURBCNTR);
614         PSB_WVDC32(dev_priv->saveDSPBCURSOR_POS, CURBPOS);
615         PSB_WVDC32(dev_priv->saveDSPBCURSOR_BASE, CURBBASE);
616
617         PSB_WVDC32(dev_priv->saveDSPCCURSOR_CTRL, CURCCNTR);
618         PSB_WVDC32(dev_priv->saveDSPCCURSOR_POS, CURCPOS);
619         PSB_WVDC32(dev_priv->saveDSPCCURSOR_BASE, CURCBASE);
620
621         /* Restore HW overlay */
622         PSB_WVDC32(dev_priv->saveOV_OVADD, OV_OVADD);
623         PSB_WVDC32(dev_priv->saveOV_OGAMC0, OV_OGAMC0);
624         PSB_WVDC32(dev_priv->saveOV_OGAMC1, OV_OGAMC1);
625         PSB_WVDC32(dev_priv->saveOV_OGAMC2, OV_OGAMC2);
626         PSB_WVDC32(dev_priv->saveOV_OGAMC3, OV_OGAMC3);
627         PSB_WVDC32(dev_priv->saveOV_OGAMC4, OV_OGAMC4);
628         PSB_WVDC32(dev_priv->saveOV_OGAMC5, OV_OGAMC5);
629
630         PSB_WVDC32(dev_priv->saveOV_OVADD_C, OV_OVADD + OV_C_OFFSET);
631         PSB_WVDC32(dev_priv->saveOV_OGAMC0_C, OV_OGAMC0 + OV_C_OFFSET);
632         PSB_WVDC32(dev_priv->saveOV_OGAMC1_C, OV_OGAMC1 + OV_C_OFFSET);
633         PSB_WVDC32(dev_priv->saveOV_OGAMC2_C, OV_OGAMC2 + OV_C_OFFSET);
634         PSB_WVDC32(dev_priv->saveOV_OGAMC3_C, OV_OGAMC3 + OV_C_OFFSET);
635         PSB_WVDC32(dev_priv->saveOV_OGAMC4_C, OV_OGAMC4 + OV_C_OFFSET);
636         PSB_WVDC32(dev_priv->saveOV_OGAMC5_C, OV_OGAMC5 + OV_C_OFFSET);
637
638         return 0;
639 }
640
641 /**
642  *      mdfld_save_display_registers    -       save registers lost on suspend
643  *      @dev: our DRM device
644  *
645  *      Save the state we need in order to be able to restore the interface
646  *      upon resume from suspend
647  */
648 static int mdfld_save_registers(struct drm_device *dev)
649 {
650         /* FIXME: We need to shut down panels here if using them
651            and once the right bits are merged */
652         mdfld_save_cursor_overlay_registers(dev);
653         mdfld_save_display_registers(dev, 0);
654         mdfld_save_display_registers(dev, 0);
655         mdfld_save_display_registers(dev, 2);
656         mdfld_save_display_registers(dev, 1);
657         mdfld_disable_crtc(dev, 0);
658         mdfld_disable_crtc(dev, 2);
659         mdfld_disable_crtc(dev, 1);
660         return 0;
661 }
662
663 /**
664  *      mdfld_restore_display_registers -       restore lost register state
665  *      @dev: our DRM device
666  *
667  *      Restore register state that was lost during suspend and resume.
668  */
669 static int mdfld_restore_registers(struct drm_device *dev)
670 {
671         mdfld_restore_display_registers(dev, 1);
672         mdfld_restore_display_registers(dev, 0);
673         mdfld_restore_display_registers(dev, 2);
674         mdfld_restore_cursor_overlay_registers(dev);
675         return 0;
676 }
677
678 static int mdfld_power_down(struct drm_device *dev)
679 {
680         /* FIXME */
681         return 0;
682 }
683
684 static int mdfld_power_up(struct drm_device *dev)
685 {
686         /* FIXME */
687         return 0;
688 }
689
690 const struct psb_ops mdfld_chip_ops = {
691         .name = "Medfield",
692         .accel_2d = 0,
693         .pipes = 3,
694         .crtcs = 2,
695         .sgx_offset = MRST_SGX_OFFSET,
696
697         .chip_setup = mid_chip_setup,
698
699         .crtc_helper = &mdfld_helper_funcs,
700         .crtc_funcs = &mdfld_intel_crtc_funcs,
701
702         .output_init = mdfld_output_init,
703
704 #ifdef CONFIG_BACKLIGHT_CLASS_DEVICE
705         .backlight_init = mdfld_backlight_init,
706 #endif
707
708         .init_pm = mdfld_init_pm,
709         .save_regs = mdfld_save_registers,
710         .restore_regs = mdfld_restore_registers,
711         .power_down = mdfld_power_down,
712         .power_up = mdfld_power_up,
713 };
714