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 
mdfld_set_brightness(struct backlight_device * bd)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 
mdfld_get_brightness(struct backlight_device * bd)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 
device_backlight_init(struct drm_device * dev)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 
mdfld_backlight_init(struct drm_device * dev)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 
mdfld_get_backlight_device(void)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  */
mdfld_save_display_registers(struct drm_device * dev,int pipe)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  */
mdfld_restore_display_registers(struct drm_device * dev,int pipe)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 
mdfld_save_registers(struct drm_device * dev)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 
mdfld_restore_registers(struct drm_device * dev)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 
mdfld_power_down(struct drm_device * dev)658 static int mdfld_power_down(struct drm_device *dev)
659 {
660 	/* FIXME */
661 	return 0;
662 }
663 
mdfld_power_up(struct drm_device * dev)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 	.sgx_offset = MRST_SGX_OFFSET,
676 
677 	.chip_setup = mid_chip_setup,
678 	.crtc_helper = &mdfld_helper_funcs,
679 	.crtc_funcs = &psb_intel_crtc_funcs,
680 
681 	.output_init = mdfld_output_init,
682 
683 #ifdef CONFIG_BACKLIGHT_CLASS_DEVICE
684 	.backlight_init = mdfld_backlight_init,
685 #endif
686 
687 	.save_regs = mdfld_save_registers,
688 	.restore_regs = mdfld_restore_registers,
689 	.power_down = mdfld_power_down,
690 	.power_up = mdfld_power_up,
691 };
692