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
48static struct backlight_device *mdfld_backlight_device;
49
50int 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
96static 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
108static const struct backlight_ops mdfld_ops = {
109	.get_brightness = mdfld_get_brightness,
110	.update_status  = mdfld_set_brightness,
111};
112
113static 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
124static 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
149struct 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 */
166static 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 */
352static 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
638static 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
649static 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
658static int mdfld_power_down(struct drm_device *dev)
659{
660	/* FIXME */
661	return 0;
662}
663
664static int mdfld_power_up(struct drm_device *dev)
665{
666	/* FIXME */
667	return 0;
668}
669
670const 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