cdv: continue synching up with updated reference code
[firefly-linux-kernel-4.4.55.git] / drivers / gpu / drm / 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 "psb_drv.h"
21 #include "mid_bios.h"
22 #include "mdfld_output.h"
23 #include "mdfld_dsi_output.h"
24 #include "tc35876x-dsi-lvds.h"
25
26 #include <asm/intel_scu_ipc.h>
27
28 #ifdef CONFIG_BACKLIGHT_CLASS_DEVICE
29
30 #define MRST_BLC_MAX_PWM_REG_FREQ           0xFFFF
31 #define BLC_PWM_PRECISION_FACTOR 100    /* 10000000 */
32 #define BLC_PWM_FREQ_CALC_CONSTANT 32
33 #define MHz 1000000
34 #define BRIGHTNESS_MIN_LEVEL 1
35 #define BRIGHTNESS_MAX_LEVEL 100
36 #define BRIGHTNESS_MASK 0xFF
37 #define BLC_POLARITY_NORMAL 0
38 #define BLC_POLARITY_INVERSE 1
39 #define BLC_ADJUSTMENT_MAX 100
40
41 #define MDFLD_BLC_PWM_PRECISION_FACTOR    10
42 #define MDFLD_BLC_MAX_PWM_REG_FREQ        0xFFFE
43 #define MDFLD_BLC_MIN_PWM_REG_FREQ        0x2
44
45 #define MDFLD_BACKLIGHT_PWM_POLARITY_BIT_CLEAR (0xFFFE)
46 #define MDFLD_BACKLIGHT_PWM_CTL_SHIFT   (16)
47
48 static struct backlight_device *mdfld_backlight_device;
49
50 int mdfld_set_brightness(struct backlight_device *bd)
51 {
52         struct drm_device *dev =
53                 (struct drm_device *)bl_get_data(mdfld_backlight_device);
54         struct drm_psb_private *dev_priv = dev->dev_private;
55         int level = bd->props.brightness;
56
57         DRM_DEBUG_DRIVER("backlight level set to %d\n", level);
58
59         /* Perform value bounds checking */
60         if (level < BRIGHTNESS_MIN_LEVEL)
61                 level = BRIGHTNESS_MIN_LEVEL;
62
63         if (gma_power_begin(dev, false)) {
64                 u32 adjusted_level = 0;
65
66                 /*
67                  * Adjust the backlight level with the percent in
68                  * dev_priv->blc_adj2
69                  */
70                 adjusted_level = level * dev_priv->blc_adj2;
71                 adjusted_level = adjusted_level / BLC_ADJUSTMENT_MAX;
72                 dev_priv->brightness_adjusted = adjusted_level;
73
74                 if (mdfld_get_panel_type(dev, 0) == TC35876X) {
75                         if (dev_priv->dpi_panel_on[0] ||
76                                         dev_priv->dpi_panel_on[2])
77                                 tc35876x_brightness_control(dev,
78                                                 dev_priv->brightness_adjusted);
79                 } else {
80                         if (dev_priv->dpi_panel_on[0])
81                                 mdfld_dsi_brightness_control(dev, 0,
82                                                 dev_priv->brightness_adjusted);
83                 }
84
85                 if (dev_priv->dpi_panel_on[2])
86                         mdfld_dsi_brightness_control(dev, 2,
87                                         dev_priv->brightness_adjusted);
88                 gma_power_end(dev);
89         }
90
91         /* cache the brightness for later use */
92         dev_priv->brightness = level;
93         return 0;
94 }
95
96 static int mdfld_get_brightness(struct backlight_device *bd)
97 {
98         struct drm_device *dev =
99                 (struct drm_device *)bl_get_data(mdfld_backlight_device);
100         struct drm_psb_private *dev_priv = dev->dev_private;
101
102         DRM_DEBUG_DRIVER("brightness = 0x%x \n", dev_priv->brightness);
103
104         /* return locally cached var instead of HW read (due to DPST etc.) */
105         return dev_priv->brightness;
106 }
107
108 static const struct backlight_ops mdfld_ops = {
109         .get_brightness = mdfld_get_brightness,
110         .update_status  = mdfld_set_brightness,
111 };
112
113 static int device_backlight_init(struct drm_device *dev)
114 {
115         struct drm_psb_private *dev_priv = (struct drm_psb_private *)
116                 dev->dev_private;
117
118         dev_priv->blc_adj1 = BLC_ADJUSTMENT_MAX;
119         dev_priv->blc_adj2 = BLC_ADJUSTMENT_MAX;
120
121         return 0;
122 }
123
124 static int mdfld_backlight_init(struct drm_device *dev)
125 {
126         struct backlight_properties props;
127         int ret = 0;
128
129         memset(&props, 0, sizeof(struct backlight_properties));
130         props.max_brightness = BRIGHTNESS_MAX_LEVEL;
131         props.type = BACKLIGHT_PLATFORM;
132         mdfld_backlight_device = backlight_device_register("mdfld-bl",
133                                 NULL, (void *)dev, &mdfld_ops, &props);
134
135         if (IS_ERR(mdfld_backlight_device))
136                 return PTR_ERR(mdfld_backlight_device);
137
138         ret = device_backlight_init(dev);
139         if (ret)
140                 return ret;
141
142         mdfld_backlight_device->props.brightness = BRIGHTNESS_MAX_LEVEL;
143         mdfld_backlight_device->props.max_brightness = BRIGHTNESS_MAX_LEVEL;
144         backlight_update_status(mdfld_backlight_device);
145         return 0;
146 }
147 #endif
148
149 struct backlight_device *mdfld_get_backlight_device(void)
150 {
151 #ifdef CONFIG_BACKLIGHT_CLASS_DEVICE
152         return mdfld_backlight_device;
153 #else
154         return NULL;
155 #endif
156 }
157
158 /*
159  * mdfld_save_display_registers
160  *
161  * Description: We are going to suspend so save current display
162  * register state.
163  *
164  * Notes: FIXME_JLIU7 need to add the support for DPI MIPI & HDMI audio
165  */
166 static int mdfld_save_display_registers(struct drm_device *dev, int pipe)
167 {
168         struct drm_psb_private *dev_priv = dev->dev_private;
169         struct medfield_state *regs = &dev_priv->regs.mdfld;
170         int i;
171
172         /* register */
173         u32 dpll_reg = MRST_DPLL_A;
174         u32 fp_reg = MRST_FPA0;
175         u32 pipeconf_reg = PIPEACONF;
176         u32 htot_reg = HTOTAL_A;
177         u32 hblank_reg = HBLANK_A;
178         u32 hsync_reg = HSYNC_A;
179         u32 vtot_reg = VTOTAL_A;
180         u32 vblank_reg = VBLANK_A;
181         u32 vsync_reg = VSYNC_A;
182         u32 pipesrc_reg = PIPEASRC;
183         u32 dspstride_reg = DSPASTRIDE;
184         u32 dsplinoff_reg = DSPALINOFF;
185         u32 dsptileoff_reg = DSPATILEOFF;
186         u32 dspsize_reg = DSPASIZE;
187         u32 dsppos_reg = DSPAPOS;
188         u32 dspsurf_reg = DSPASURF;
189         u32 mipi_reg = MIPI;
190         u32 dspcntr_reg = DSPACNTR;
191         u32 dspstatus_reg = PIPEASTAT;
192         u32 palette_reg = PALETTE_A;
193
194         /* pointer to values */
195         u32 *dpll_val = &regs->saveDPLL_A;
196         u32 *fp_val = &regs->saveFPA0;
197         u32 *pipeconf_val = &regs->savePIPEACONF;
198         u32 *htot_val = &regs->saveHTOTAL_A;
199         u32 *hblank_val = &regs->saveHBLANK_A;
200         u32 *hsync_val = &regs->saveHSYNC_A;
201         u32 *vtot_val = &regs->saveVTOTAL_A;
202         u32 *vblank_val = &regs->saveVBLANK_A;
203         u32 *vsync_val = &regs->saveVSYNC_A;
204         u32 *pipesrc_val = &regs->savePIPEASRC;
205         u32 *dspstride_val = &regs->saveDSPASTRIDE;
206         u32 *dsplinoff_val = &regs->saveDSPALINOFF;
207         u32 *dsptileoff_val = &regs->saveDSPATILEOFF;
208         u32 *dspsize_val = &regs->saveDSPASIZE;
209         u32 *dsppos_val = &regs->saveDSPAPOS;
210         u32 *dspsurf_val = &regs->saveDSPASURF;
211         u32 *mipi_val = &regs->saveMIPI;
212         u32 *dspcntr_val = &regs->saveDSPACNTR;
213         u32 *dspstatus_val = &regs->saveDSPASTATUS;
214         u32 *palette_val = regs->save_palette_a;
215
216         switch (pipe) {
217         case 0:
218                 break;
219         case 1:
220                 /* regester */
221                 dpll_reg = MDFLD_DPLL_B;
222                 fp_reg = MDFLD_DPLL_DIV0;
223                 pipeconf_reg = PIPEBCONF;
224                 htot_reg = HTOTAL_B;
225                 hblank_reg = HBLANK_B;
226                 hsync_reg = HSYNC_B;
227                 vtot_reg = VTOTAL_B;
228                 vblank_reg = VBLANK_B;
229                 vsync_reg = VSYNC_B;
230                 pipesrc_reg = PIPEBSRC;
231                 dspstride_reg = DSPBSTRIDE;
232                 dsplinoff_reg = DSPBLINOFF;
233                 dsptileoff_reg = DSPBTILEOFF;
234                 dspsize_reg = DSPBSIZE;
235                 dsppos_reg = DSPBPOS;
236                 dspsurf_reg = DSPBSURF;
237                 dspcntr_reg = DSPBCNTR;
238                 dspstatus_reg = PIPEBSTAT;
239                 palette_reg = PALETTE_B;
240
241                 /* values */
242                 dpll_val = &regs->saveDPLL_B;
243                 fp_val = &regs->saveFPB0;
244                 pipeconf_val = &regs->savePIPEBCONF;
245                 htot_val = &regs->saveHTOTAL_B;
246                 hblank_val = &regs->saveHBLANK_B;
247                 hsync_val = &regs->saveHSYNC_B;
248                 vtot_val = &regs->saveVTOTAL_B;
249                 vblank_val = &regs->saveVBLANK_B;
250                 vsync_val = &regs->saveVSYNC_B;
251                 pipesrc_val = &regs->savePIPEBSRC;
252                 dspstride_val = &regs->saveDSPBSTRIDE;
253                 dsplinoff_val = &regs->saveDSPBLINOFF;
254                 dsptileoff_val = &regs->saveDSPBTILEOFF;
255                 dspsize_val = &regs->saveDSPBSIZE;
256                 dsppos_val = &regs->saveDSPBPOS;
257                 dspsurf_val = &regs->saveDSPBSURF;
258                 dspcntr_val = &regs->saveDSPBCNTR;
259                 dspstatus_val = &regs->saveDSPBSTATUS;
260                 palette_val = regs->save_palette_b;
261                 break;
262         case 2:
263                 /* register */
264                 pipeconf_reg = PIPECCONF;
265                 htot_reg = HTOTAL_C;
266                 hblank_reg = HBLANK_C;
267                 hsync_reg = HSYNC_C;
268                 vtot_reg = VTOTAL_C;
269                 vblank_reg = VBLANK_C;
270                 vsync_reg = VSYNC_C;
271                 pipesrc_reg = PIPECSRC;
272                 dspstride_reg = DSPCSTRIDE;
273                 dsplinoff_reg = DSPCLINOFF;
274                 dsptileoff_reg = DSPCTILEOFF;
275                 dspsize_reg = DSPCSIZE;
276                 dsppos_reg = DSPCPOS;
277                 dspsurf_reg = DSPCSURF;
278                 mipi_reg = MIPI_C;
279                 dspcntr_reg = DSPCCNTR;
280                 dspstatus_reg = PIPECSTAT;
281                 palette_reg = PALETTE_C;
282
283                 /* pointer to values */
284                 pipeconf_val = &regs->savePIPECCONF;
285                 htot_val = &regs->saveHTOTAL_C;
286                 hblank_val = &regs->saveHBLANK_C;
287                 hsync_val = &regs->saveHSYNC_C;
288                 vtot_val = &regs->saveVTOTAL_C;
289                 vblank_val = &regs->saveVBLANK_C;
290                 vsync_val = &regs->saveVSYNC_C;
291                 pipesrc_val = &regs->savePIPECSRC;
292                 dspstride_val = &regs->saveDSPCSTRIDE;
293                 dsplinoff_val = &regs->saveDSPCLINOFF;
294                 dsptileoff_val = &regs->saveDSPCTILEOFF;
295                 dspsize_val = &regs->saveDSPCSIZE;
296                 dsppos_val = &regs->saveDSPCPOS;
297                 dspsurf_val = &regs->saveDSPCSURF;
298                 mipi_val = &regs->saveMIPI_C;
299                 dspcntr_val = &regs->saveDSPCCNTR;
300                 dspstatus_val = &regs->saveDSPCSTATUS;
301                 palette_val = regs->save_palette_c;
302                 break;
303         default:
304                 DRM_ERROR("%s, invalid pipe number.\n", __func__);
305                 return -EINVAL;
306         }
307
308         /* Pipe & plane A info */
309         *dpll_val = PSB_RVDC32(dpll_reg);
310         *fp_val = PSB_RVDC32(fp_reg);
311         *pipeconf_val = PSB_RVDC32(pipeconf_reg);
312         *htot_val = PSB_RVDC32(htot_reg);
313         *hblank_val = PSB_RVDC32(hblank_reg);
314         *hsync_val = PSB_RVDC32(hsync_reg);
315         *vtot_val = PSB_RVDC32(vtot_reg);
316         *vblank_val = PSB_RVDC32(vblank_reg);
317         *vsync_val = PSB_RVDC32(vsync_reg);
318         *pipesrc_val = PSB_RVDC32(pipesrc_reg);
319         *dspstride_val = PSB_RVDC32(dspstride_reg);
320         *dsplinoff_val = PSB_RVDC32(dsplinoff_reg);
321         *dsptileoff_val = PSB_RVDC32(dsptileoff_reg);
322         *dspsize_val = PSB_RVDC32(dspsize_reg);
323         *dsppos_val = PSB_RVDC32(dsppos_reg);
324         *dspsurf_val = PSB_RVDC32(dspsurf_reg);
325         *dspcntr_val = PSB_RVDC32(dspcntr_reg);
326         *dspstatus_val = PSB_RVDC32(dspstatus_reg);
327
328         /*save palette (gamma) */
329         for (i = 0; i < 256; i++)
330                 palette_val[i] = PSB_RVDC32(palette_reg + (i << 2));
331
332         if (pipe == 1) {
333                 regs->savePFIT_CONTROL = PSB_RVDC32(PFIT_CONTROL);
334                 regs->savePFIT_PGM_RATIOS = PSB_RVDC32(PFIT_PGM_RATIOS);
335
336                 regs->saveHDMIPHYMISCCTL = PSB_RVDC32(HDMIPHYMISCCTL);
337                 regs->saveHDMIB_CONTROL = PSB_RVDC32(HDMIB_CONTROL);
338                 return 0;
339         }
340
341         *mipi_val = PSB_RVDC32(mipi_reg);
342         return 0;
343 }
344
345 /*
346  * mdfld_restore_display_registers
347  *
348  * Description: We are going to resume so restore display register state.
349  *
350  * Notes: FIXME_JLIU7 need to add the support for DPI MIPI & HDMI audio
351  */
352 static int mdfld_restore_display_registers(struct drm_device *dev, int pipe)
353 {
354         /* To get  panel out of ULPS mode. */
355         u32 temp = 0;
356         u32 device_ready_reg = DEVICE_READY_REG;
357         struct drm_psb_private *dev_priv = dev->dev_private;
358         struct mdfld_dsi_config *dsi_config = NULL;
359         struct medfield_state *regs = &dev_priv->regs.mdfld;
360         u32 i = 0;
361         u32 dpll = 0;
362         u32 timeout = 0;
363
364         /* regester */
365         u32 dpll_reg = MRST_DPLL_A;
366         u32 fp_reg = MRST_FPA0;
367         u32 pipeconf_reg = PIPEACONF;
368         u32 htot_reg = HTOTAL_A;
369         u32 hblank_reg = HBLANK_A;
370         u32 hsync_reg = HSYNC_A;
371         u32 vtot_reg = VTOTAL_A;
372         u32 vblank_reg = VBLANK_A;
373         u32 vsync_reg = VSYNC_A;
374         u32 pipesrc_reg = PIPEASRC;
375         u32 dspstride_reg = DSPASTRIDE;
376         u32 dsplinoff_reg = DSPALINOFF;
377         u32 dsptileoff_reg = DSPATILEOFF;
378         u32 dspsize_reg = DSPASIZE;
379         u32 dsppos_reg = DSPAPOS;
380         u32 dspsurf_reg = DSPASURF;
381         u32 dspstatus_reg = PIPEASTAT;
382         u32 mipi_reg = MIPI;
383         u32 dspcntr_reg = DSPACNTR;
384         u32 palette_reg = PALETTE_A;
385
386         /* values */
387         u32 dpll_val = regs->saveDPLL_A & ~DPLL_VCO_ENABLE;
388         u32 fp_val = regs->saveFPA0;
389         u32 pipeconf_val = regs->savePIPEACONF;
390         u32 htot_val = regs->saveHTOTAL_A;
391         u32 hblank_val = regs->saveHBLANK_A;
392         u32 hsync_val = regs->saveHSYNC_A;
393         u32 vtot_val = regs->saveVTOTAL_A;
394         u32 vblank_val = regs->saveVBLANK_A;
395         u32 vsync_val = regs->saveVSYNC_A;
396         u32 pipesrc_val = regs->savePIPEASRC;
397         u32 dspstride_val = regs->saveDSPASTRIDE;
398         u32 dsplinoff_val = regs->saveDSPALINOFF;
399         u32 dsptileoff_val = regs->saveDSPATILEOFF;
400         u32 dspsize_val = regs->saveDSPASIZE;
401         u32 dsppos_val = regs->saveDSPAPOS;
402         u32 dspsurf_val = regs->saveDSPASURF;
403         u32 dspstatus_val = regs->saveDSPASTATUS;
404         u32 mipi_val = regs->saveMIPI;
405         u32 dspcntr_val = regs->saveDSPACNTR;
406         u32 *palette_val = regs->save_palette_a;
407
408         switch (pipe) {
409         case 0:
410                 dsi_config = dev_priv->dsi_configs[0];
411                 break;
412         case 1:
413                 /* regester */
414                 dpll_reg = MDFLD_DPLL_B;
415                 fp_reg = MDFLD_DPLL_DIV0;
416                 pipeconf_reg = PIPEBCONF;
417                 htot_reg = HTOTAL_B;
418                 hblank_reg = HBLANK_B;
419                 hsync_reg = HSYNC_B;
420                 vtot_reg = VTOTAL_B;
421                 vblank_reg = VBLANK_B;
422                 vsync_reg = VSYNC_B;
423                 pipesrc_reg = PIPEBSRC;
424                 dspstride_reg = DSPBSTRIDE;
425                 dsplinoff_reg = DSPBLINOFF;
426                 dsptileoff_reg = DSPBTILEOFF;
427                 dspsize_reg = DSPBSIZE;
428                 dsppos_reg = DSPBPOS;
429                 dspsurf_reg = DSPBSURF;
430                 dspcntr_reg = DSPBCNTR;
431                 dspstatus_reg = PIPEBSTAT;
432                 palette_reg = PALETTE_B;
433
434                 /* values */
435                 dpll_val = regs->saveDPLL_B & ~DPLL_VCO_ENABLE;
436                 fp_val = regs->saveFPB0;
437                 pipeconf_val = regs->savePIPEBCONF;
438                 htot_val = regs->saveHTOTAL_B;
439                 hblank_val = regs->saveHBLANK_B;
440                 hsync_val = regs->saveHSYNC_B;
441                 vtot_val = regs->saveVTOTAL_B;
442                 vblank_val = regs->saveVBLANK_B;
443                 vsync_val = regs->saveVSYNC_B;
444                 pipesrc_val = regs->savePIPEBSRC;
445                 dspstride_val = regs->saveDSPBSTRIDE;
446                 dsplinoff_val = regs->saveDSPBLINOFF;
447                 dsptileoff_val = regs->saveDSPBTILEOFF;
448                 dspsize_val = regs->saveDSPBSIZE;
449                 dsppos_val = regs->saveDSPBPOS;
450                 dspsurf_val = regs->saveDSPBSURF;
451                 dspcntr_val = regs->saveDSPBCNTR;
452                 dspstatus_val = regs->saveDSPBSTATUS;
453                 palette_val = regs->save_palette_b;
454                 break;
455         case 2:
456                 /* regester */
457                 pipeconf_reg = PIPECCONF;
458                 htot_reg = HTOTAL_C;
459                 hblank_reg = HBLANK_C;
460                 hsync_reg = HSYNC_C;
461                 vtot_reg = VTOTAL_C;
462                 vblank_reg = VBLANK_C;
463                 vsync_reg = VSYNC_C;
464                 pipesrc_reg = PIPECSRC;
465                 dspstride_reg = DSPCSTRIDE;
466                 dsplinoff_reg = DSPCLINOFF;
467                 dsptileoff_reg = DSPCTILEOFF;
468                 dspsize_reg = DSPCSIZE;
469                 dsppos_reg = DSPCPOS;
470                 dspsurf_reg = DSPCSURF;
471                 mipi_reg = MIPI_C;
472                 dspcntr_reg = DSPCCNTR;
473                 dspstatus_reg = PIPECSTAT;
474                 palette_reg = PALETTE_C;
475
476                 /* values */
477                 pipeconf_val = regs->savePIPECCONF;
478                 htot_val = regs->saveHTOTAL_C;
479                 hblank_val = regs->saveHBLANK_C;
480                 hsync_val = regs->saveHSYNC_C;
481                 vtot_val = regs->saveVTOTAL_C;
482                 vblank_val = regs->saveVBLANK_C;
483                 vsync_val = regs->saveVSYNC_C;
484                 pipesrc_val = regs->savePIPECSRC;
485                 dspstride_val = regs->saveDSPCSTRIDE;
486                 dsplinoff_val = regs->saveDSPCLINOFF;
487                 dsptileoff_val = regs->saveDSPCTILEOFF;
488                 dspsize_val = regs->saveDSPCSIZE;
489                 dsppos_val = regs->saveDSPCPOS;
490                 dspsurf_val = regs->saveDSPCSURF;
491                 mipi_val = regs->saveMIPI_C;
492                 dspcntr_val = regs->saveDSPCCNTR;
493                 dspstatus_val = regs->saveDSPCSTATUS;
494                 palette_val = regs->save_palette_c;
495
496                 dsi_config = dev_priv->dsi_configs[1];
497                 break;
498         default:
499                 DRM_ERROR("%s, invalid pipe number.\n", __func__);
500                 return -EINVAL;
501         }
502
503         /*make sure VGA plane is off. it initializes to on after reset!*/
504         PSB_WVDC32(0x80000000, VGACNTRL);
505
506         if (pipe == 1) {
507                 PSB_WVDC32(dpll_val & ~DPLL_VCO_ENABLE, dpll_reg);
508                 PSB_RVDC32(dpll_reg);
509
510                 PSB_WVDC32(fp_val, fp_reg);
511         } else {
512
513                 dpll = PSB_RVDC32(dpll_reg);
514
515                 if (!(dpll & DPLL_VCO_ENABLE)) {
516
517                         /* When ungating power of DPLL, needs to wait 0.5us
518                            before enable the VCO */
519                         if (dpll & MDFLD_PWR_GATE_EN) {
520                                 dpll &= ~MDFLD_PWR_GATE_EN;
521                                 PSB_WVDC32(dpll, dpll_reg);
522                                 /* FIXME_MDFLD PO - change 500 to 1 after PO */
523                                 udelay(500);
524                         }
525
526                         PSB_WVDC32(fp_val, fp_reg);
527                         PSB_WVDC32(dpll_val, dpll_reg);
528                         /* FIXME_MDFLD PO - change 500 to 1 after PO */
529                         udelay(500);
530
531                         dpll_val |= DPLL_VCO_ENABLE;
532                         PSB_WVDC32(dpll_val, dpll_reg);
533                         PSB_RVDC32(dpll_reg);
534
535                         /* wait for DSI PLL to lock */
536                         while (timeout < 20000 &&
537                           !(PSB_RVDC32(pipeconf_reg) & PIPECONF_DSIPLL_LOCK)) {
538                                 udelay(150);
539                                 timeout++;
540                         }
541
542                         if (timeout == 20000) {
543                                 DRM_ERROR("%s, can't lock DSIPLL.\n",
544                                                                 __func__);
545                                 return -EINVAL;
546                         }
547                 }
548         }
549         /* Restore mode */
550         PSB_WVDC32(htot_val, htot_reg);
551         PSB_WVDC32(hblank_val, hblank_reg);
552         PSB_WVDC32(hsync_val, hsync_reg);
553         PSB_WVDC32(vtot_val, vtot_reg);
554         PSB_WVDC32(vblank_val, vblank_reg);
555         PSB_WVDC32(vsync_val, vsync_reg);
556         PSB_WVDC32(pipesrc_val, pipesrc_reg);
557         PSB_WVDC32(dspstatus_val, dspstatus_reg);
558
559         /*set up the plane*/
560         PSB_WVDC32(dspstride_val, dspstride_reg);
561         PSB_WVDC32(dsplinoff_val, dsplinoff_reg);
562         PSB_WVDC32(dsptileoff_val, dsptileoff_reg);
563         PSB_WVDC32(dspsize_val, dspsize_reg);
564         PSB_WVDC32(dsppos_val, dsppos_reg);
565         PSB_WVDC32(dspsurf_val, dspsurf_reg);
566
567         if (pipe == 1) {
568                 /* restore palette (gamma) */
569                 /*DRM_UDELAY(50000); */
570                 for (i = 0; i < 256; i++)
571                         PSB_WVDC32(palette_val[i], palette_reg + (i << 2));
572
573                 PSB_WVDC32(regs->savePFIT_CONTROL, PFIT_CONTROL);
574                 PSB_WVDC32(regs->savePFIT_PGM_RATIOS, PFIT_PGM_RATIOS);
575
576                 /*TODO: resume HDMI port */
577
578                 /*TODO: resume pipe*/
579
580                 /*enable the plane*/
581                 PSB_WVDC32(dspcntr_val & ~DISPLAY_PLANE_ENABLE, dspcntr_reg);
582
583                 return 0;
584         }
585
586         /*set up pipe related registers*/
587         PSB_WVDC32(mipi_val, mipi_reg);
588
589         /*setup MIPI adapter + MIPI IP registers*/
590         if (dsi_config)
591                 mdfld_dsi_controller_init(dsi_config, pipe);
592
593         if (in_atomic() || in_interrupt())
594                 mdelay(20);
595         else
596                 msleep(20);
597
598         /*enable the plane*/
599         PSB_WVDC32(dspcntr_val, dspcntr_reg);
600
601         if (in_atomic() || in_interrupt())
602                 mdelay(20);
603         else
604                 msleep(20);
605
606         /* LP Hold Release */
607         temp = REG_READ(mipi_reg);
608         temp |= LP_OUTPUT_HOLD_RELEASE;
609         REG_WRITE(mipi_reg, temp);
610         mdelay(1);
611
612
613         /* Set DSI host to exit from Utra Low Power State */
614         temp = REG_READ(device_ready_reg);
615         temp &= ~ULPS_MASK;
616         temp |= 0x3;
617         temp |= EXIT_ULPS_DEV_READY;
618         REG_WRITE(device_ready_reg, temp);
619         mdelay(1);
620
621         temp = REG_READ(device_ready_reg);
622         temp &= ~ULPS_MASK;
623         temp |= EXITING_ULPS;
624         REG_WRITE(device_ready_reg, temp);
625         mdelay(1);
626
627         /*enable the pipe*/
628         PSB_WVDC32(pipeconf_val, pipeconf_reg);
629
630         /* restore palette (gamma) */
631         /*DRM_UDELAY(50000); */
632         for (i = 0; i < 256; i++)
633                 PSB_WVDC32(palette_val[i], palette_reg + (i << 2));
634
635         return 0;
636 }
637
638 static int mdfld_save_registers(struct drm_device *dev)
639 {
640         /* mdfld_save_cursor_overlay_registers(dev); */
641         mdfld_save_display_registers(dev, 0);
642         mdfld_save_display_registers(dev, 2);
643         mdfld_disable_crtc(dev, 0);
644         mdfld_disable_crtc(dev, 2);
645
646         return 0;
647 }
648
649 static int mdfld_restore_registers(struct drm_device *dev)
650 {
651         mdfld_restore_display_registers(dev, 2);
652         mdfld_restore_display_registers(dev, 0);
653         /* mdfld_restore_cursor_overlay_registers(dev); */
654
655         return 0;
656 }
657
658 static int mdfld_power_down(struct drm_device *dev)
659 {
660         /* FIXME */
661         return 0;
662 }
663
664 static int mdfld_power_up(struct drm_device *dev)
665 {
666         /* FIXME */
667         return 0;
668 }
669
670 const struct psb_ops mdfld_chip_ops = {
671         .name = "mdfld",
672         .accel_2d = 0,
673         .pipes = 3,
674         .crtcs = 3,
675         .lvds_mask = (1 << 1);
676         .hdmi_mask = (1 << 1);
677         .sgx_offset = MRST_SGX_OFFSET,
678
679         .chip_setup = mid_chip_setup,
680         .crtc_helper = &mdfld_helper_funcs,
681         .crtc_funcs = &psb_intel_crtc_funcs,
682
683         .output_init = mdfld_output_init,
684
685 #ifdef CONFIG_BACKLIGHT_CLASS_DEVICE
686         .backlight_init = mdfld_backlight_init,
687 #endif
688
689         .save_regs = mdfld_save_registers,
690         .restore_regs = mdfld_restore_registers,
691         .power_down = mdfld_power_down,
692         .power_up = mdfld_power_up,
693 };