1 /*
2  * Copyright © 2010 Intel Corporation
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a
5  * copy of this software and associated documentation files (the "Software"),
6  * to deal in the Software without restriction, including without limitation
7  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8  * and/or sell copies of the Software, and to permit persons to whom the
9  * Software is furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice (including the next
12  * paragraph) shall be included in all copies or substantial portions of the
13  * Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21  * DEALINGS IN THE SOFTWARE.
22  *
23  * Authors:
24  *	Li Peng <peng.li@intel.com>
25  */
26 
27 #include <drm/drmP.h>
28 #include <drm/drm.h>
29 #include "psb_intel_drv.h"
30 #include "psb_intel_reg.h"
31 #include "psb_drv.h"
32 
33 #define HDMI_READ(reg)		readl(hdmi_dev->regs + (reg))
34 #define HDMI_WRITE(reg, val)	writel(val, hdmi_dev->regs + (reg))
35 
36 #define HDMI_HCR	0x1000
37 #define HCR_ENABLE_HDCP		(1 << 5)
38 #define HCR_ENABLE_AUDIO	(1 << 2)
39 #define HCR_ENABLE_PIXEL	(1 << 1)
40 #define HCR_ENABLE_TMDS		(1 << 0)
41 
42 #define HDMI_HICR	0x1004
43 #define HDMI_HSR	0x1008
44 #define HDMI_HISR	0x100C
45 #define HDMI_DETECT_HDP		(1 << 0)
46 
47 #define HDMI_VIDEO_REG	0x3000
48 #define HDMI_UNIT_EN		(1 << 7)
49 #define HDMI_MODE_OUTPUT	(1 << 0)
50 #define HDMI_HBLANK_A	0x3100
51 
52 #define HDMI_AUDIO_CTRL	0x4000
53 #define HDMI_ENABLE_AUDIO	(1 << 0)
54 
55 #define PCH_HTOTAL_B	0x3100
56 #define PCH_HBLANK_B	0x3104
57 #define PCH_HSYNC_B	0x3108
58 #define PCH_VTOTAL_B	0x310C
59 #define PCH_VBLANK_B	0x3110
60 #define PCH_VSYNC_B	0x3114
61 #define PCH_PIPEBSRC	0x311C
62 
63 #define PCH_PIPEB_DSL	0x3800
64 #define PCH_PIPEB_SLC	0x3804
65 #define PCH_PIPEBCONF	0x3808
66 #define PCH_PIPEBSTAT	0x3824
67 
68 #define CDVO_DFT	0x5000
69 #define CDVO_SLEWRATE	0x5004
70 #define CDVO_STRENGTH	0x5008
71 #define CDVO_RCOMP	0x500C
72 
73 #define DPLL_CTRL       0x6000
74 #define DPLL_PDIV_SHIFT		16
75 #define DPLL_PDIV_MASK		(0xf << 16)
76 #define DPLL_PWRDN		(1 << 4)
77 #define DPLL_RESET		(1 << 3)
78 #define DPLL_FASTEN		(1 << 2)
79 #define DPLL_ENSTAT		(1 << 1)
80 #define DPLL_DITHEN		(1 << 0)
81 
82 #define DPLL_DIV_CTRL   0x6004
83 #define DPLL_CLKF_MASK		0xffffffc0
84 #define DPLL_CLKR_MASK		(0x3f)
85 
86 #define DPLL_CLK_ENABLE 0x6008
87 #define DPLL_EN_DISP		(1 << 31)
88 #define DPLL_SEL_HDMI		(1 << 8)
89 #define DPLL_EN_HDMI		(1 << 1)
90 #define DPLL_EN_VGA		(1 << 0)
91 
92 #define DPLL_ADJUST     0x600C
93 #define DPLL_STATUS     0x6010
94 #define DPLL_UPDATE     0x6014
95 #define DPLL_DFT        0x6020
96 
97 struct intel_range {
98 	int	min, max;
99 };
100 
101 struct oaktrail_hdmi_limit {
102 	struct intel_range vco, np, nr, nf;
103 };
104 
105 struct oaktrail_hdmi_clock {
106 	int np;
107 	int nr;
108 	int nf;
109 	int dot;
110 };
111 
112 #define VCO_MIN		320000
113 #define VCO_MAX		1650000
114 #define	NP_MIN		1
115 #define	NP_MAX		15
116 #define	NR_MIN		1
117 #define	NR_MAX		64
118 #define NF_MIN		2
119 #define NF_MAX		4095
120 
121 static const struct oaktrail_hdmi_limit oaktrail_hdmi_limit = {
122 	.vco = { .min = VCO_MIN,		.max = VCO_MAX },
123 	.np  = { .min = NP_MIN,			.max = NP_MAX  },
124 	.nr  = { .min = NR_MIN,			.max = NR_MAX  },
125 	.nf  = { .min = NF_MIN,			.max = NF_MAX  },
126 };
127 
oaktrail_hdmi_audio_enable(struct drm_device * dev)128 static void oaktrail_hdmi_audio_enable(struct drm_device *dev)
129 {
130 	struct drm_psb_private *dev_priv = dev->dev_private;
131 	struct oaktrail_hdmi_dev *hdmi_dev = dev_priv->hdmi_priv;
132 
133 	HDMI_WRITE(HDMI_HCR, 0x67);
134 	HDMI_READ(HDMI_HCR);
135 
136 	HDMI_WRITE(0x51a8, 0x10);
137 	HDMI_READ(0x51a8);
138 
139 	HDMI_WRITE(HDMI_AUDIO_CTRL, 0x1);
140 	HDMI_READ(HDMI_AUDIO_CTRL);
141 }
142 
oaktrail_hdmi_audio_disable(struct drm_device * dev)143 static void oaktrail_hdmi_audio_disable(struct drm_device *dev)
144 {
145 	struct drm_psb_private *dev_priv = dev->dev_private;
146 	struct oaktrail_hdmi_dev *hdmi_dev = dev_priv->hdmi_priv;
147 
148 	HDMI_WRITE(0x51a8, 0x0);
149 	HDMI_READ(0x51a8);
150 
151 	HDMI_WRITE(HDMI_AUDIO_CTRL, 0x0);
152 	HDMI_READ(HDMI_AUDIO_CTRL);
153 
154 	HDMI_WRITE(HDMI_HCR, 0x47);
155 	HDMI_READ(HDMI_HCR);
156 }
157 
oaktrail_hdmi_dpms(struct drm_encoder * encoder,int mode)158 static void oaktrail_hdmi_dpms(struct drm_encoder *encoder, int mode)
159 {
160 	static int dpms_mode = -1;
161 
162 	struct drm_device *dev = encoder->dev;
163 	struct drm_psb_private *dev_priv = dev->dev_private;
164 	struct oaktrail_hdmi_dev *hdmi_dev = dev_priv->hdmi_priv;
165 	u32 temp;
166 
167 	if (dpms_mode == mode)
168 		return;
169 
170 	if (mode != DRM_MODE_DPMS_ON)
171 		temp = 0x0;
172 	else
173 		temp = 0x99;
174 
175 	dpms_mode = mode;
176 	HDMI_WRITE(HDMI_VIDEO_REG, temp);
177 }
178 
oaktrail_hdmi_mode_valid(struct drm_connector * connector,struct drm_display_mode * mode)179 static int oaktrail_hdmi_mode_valid(struct drm_connector *connector,
180 				struct drm_display_mode *mode)
181 {
182 	struct drm_psb_private *dev_priv = connector->dev->dev_private;
183 	if (mode->clock > 165000)
184 		return MODE_CLOCK_HIGH;
185 	if (mode->clock < 20000)
186 		return MODE_CLOCK_LOW;
187 
188 	if (mode->flags & DRM_MODE_FLAG_DBLSCAN)
189 		return MODE_NO_DBLESCAN;
190 
191 	/* We assume worst case scenario of 32 bpp here, since we don't know */
192 	if ((ALIGN(mode->hdisplay * 4, 64) * mode->vdisplay) >
193 	    dev_priv->vram_stolen_size)
194 		return MODE_MEM;
195 
196 	return MODE_OK;
197 }
198 
oaktrail_hdmi_mode_fixup(struct drm_encoder * encoder,struct drm_display_mode * mode,struct drm_display_mode * adjusted_mode)199 static bool oaktrail_hdmi_mode_fixup(struct drm_encoder *encoder,
200 				 struct drm_display_mode *mode,
201 				 struct drm_display_mode *adjusted_mode)
202 {
203 	return true;
204 }
205 
206 static enum drm_connector_status
oaktrail_hdmi_detect(struct drm_connector * connector,bool force)207 oaktrail_hdmi_detect(struct drm_connector *connector, bool force)
208 {
209 	enum drm_connector_status status;
210 	struct drm_device *dev = connector->dev;
211 	struct drm_psb_private *dev_priv = dev->dev_private;
212 	struct oaktrail_hdmi_dev *hdmi_dev = dev_priv->hdmi_priv;
213 	u32 temp;
214 
215 	temp = HDMI_READ(HDMI_HSR);
216 	DRM_DEBUG_KMS("HDMI_HSR %x\n", temp);
217 
218 	if ((temp & HDMI_DETECT_HDP) != 0)
219 		status = connector_status_connected;
220 	else
221 		status = connector_status_disconnected;
222 
223 	return status;
224 }
225 
226 static const unsigned char raw_edid[] = {
227 	0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x10, 0xac, 0x2f, 0xa0,
228 	0x53, 0x55, 0x33, 0x30, 0x16, 0x13, 0x01, 0x03, 0x0e, 0x3a, 0x24, 0x78,
229 	0xea, 0xe9, 0xf5, 0xac, 0x51, 0x30, 0xb4, 0x25, 0x11, 0x50, 0x54, 0xa5,
230 	0x4b, 0x00, 0x81, 0x80, 0xa9, 0x40, 0x71, 0x4f, 0xb3, 0x00, 0x01, 0x01,
231 	0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x28, 0x3c, 0x80, 0xa0, 0x70, 0xb0,
232 	0x23, 0x40, 0x30, 0x20, 0x36, 0x00, 0x46, 0x6c, 0x21, 0x00, 0x00, 0x1a,
233 	0x00, 0x00, 0x00, 0xff, 0x00, 0x47, 0x4e, 0x37, 0x32, 0x31, 0x39, 0x35,
234 	0x52, 0x30, 0x33, 0x55, 0x53, 0x0a, 0x00, 0x00, 0x00, 0xfc, 0x00, 0x44,
235 	0x45, 0x4c, 0x4c, 0x20, 0x32, 0x37, 0x30, 0x39, 0x57, 0x0a, 0x20, 0x20,
236 	0x00, 0x00, 0x00, 0xfd, 0x00, 0x38, 0x4c, 0x1e, 0x53, 0x11, 0x00, 0x0a,
237 	0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x00, 0x8d
238 };
239 
oaktrail_hdmi_get_modes(struct drm_connector * connector)240 static int oaktrail_hdmi_get_modes(struct drm_connector *connector)
241 {
242 	struct drm_device *dev = connector->dev;
243 	struct drm_psb_private *dev_priv = dev->dev_private;
244 	struct i2c_adapter *i2c_adap;
245 	struct edid *edid;
246 	struct drm_display_mode *mode, *t;
247 	int i = 0, ret = 0;
248 
249 	i2c_adap = i2c_get_adapter(3);
250 	if (i2c_adap == NULL) {
251 		DRM_ERROR("No ddc adapter available!\n");
252 		edid = (struct edid *)raw_edid;
253 	} else {
254 		edid = (struct edid *)raw_edid;
255 		/* FIXME ? edid = drm_get_edid(connector, i2c_adap); */
256 	}
257 
258 	if (edid) {
259 		drm_mode_connector_update_edid_property(connector, edid);
260 		ret = drm_add_edid_modes(connector, edid);
261 		connector->display_info.raw_edid = NULL;
262 	}
263 
264 	/*
265 	 * prune modes that require frame buffer bigger than stolen mem
266 	 */
267 	list_for_each_entry_safe(mode, t, &connector->probed_modes, head) {
268 		if ((mode->hdisplay * mode->vdisplay * 4) >= dev_priv->vram_stolen_size) {
269 			i++;
270 			drm_mode_remove(connector, mode);
271 		}
272 	}
273 	return ret - i;
274 }
275 
oaktrail_hdmi_mode_set(struct drm_encoder * encoder,struct drm_display_mode * mode,struct drm_display_mode * adjusted_mode)276 static void oaktrail_hdmi_mode_set(struct drm_encoder *encoder,
277 			       struct drm_display_mode *mode,
278 			       struct drm_display_mode *adjusted_mode)
279 {
280 	struct drm_device *dev = encoder->dev;
281 
282 	oaktrail_hdmi_audio_enable(dev);
283 	return;
284 }
285 
oaktrail_hdmi_destroy(struct drm_connector * connector)286 static void oaktrail_hdmi_destroy(struct drm_connector *connector)
287 {
288 	return;
289 }
290 
291 static const struct drm_encoder_helper_funcs oaktrail_hdmi_helper_funcs = {
292 	.dpms = oaktrail_hdmi_dpms,
293 	.mode_fixup = oaktrail_hdmi_mode_fixup,
294 	.prepare = psb_intel_encoder_prepare,
295 	.mode_set = oaktrail_hdmi_mode_set,
296 	.commit = psb_intel_encoder_commit,
297 };
298 
299 static const struct drm_connector_helper_funcs
300 					oaktrail_hdmi_connector_helper_funcs = {
301 	.get_modes = oaktrail_hdmi_get_modes,
302 	.mode_valid = oaktrail_hdmi_mode_valid,
303 	.best_encoder = psb_intel_best_encoder,
304 };
305 
306 static const struct drm_connector_funcs oaktrail_hdmi_connector_funcs = {
307 	.dpms = drm_helper_connector_dpms,
308 	.detect = oaktrail_hdmi_detect,
309 	.fill_modes = drm_helper_probe_single_connector_modes,
310 	.destroy = oaktrail_hdmi_destroy,
311 };
312 
oaktrail_hdmi_enc_destroy(struct drm_encoder * encoder)313 static void oaktrail_hdmi_enc_destroy(struct drm_encoder *encoder)
314 {
315 	drm_encoder_cleanup(encoder);
316 }
317 
318 static const struct drm_encoder_funcs oaktrail_hdmi_enc_funcs = {
319 	.destroy = oaktrail_hdmi_enc_destroy,
320 };
321 
oaktrail_hdmi_init(struct drm_device * dev,struct psb_intel_mode_device * mode_dev)322 void oaktrail_hdmi_init(struct drm_device *dev,
323 					struct psb_intel_mode_device *mode_dev)
324 {
325 	struct psb_intel_encoder *psb_intel_encoder;
326 	struct psb_intel_connector *psb_intel_connector;
327 	struct drm_connector *connector;
328 	struct drm_encoder *encoder;
329 
330 	psb_intel_encoder = kzalloc(sizeof(struct psb_intel_encoder), GFP_KERNEL);
331 	if (!psb_intel_encoder)
332 		return;
333 
334 	psb_intel_connector = kzalloc(sizeof(struct psb_intel_connector), GFP_KERNEL);
335 	if (!psb_intel_connector)
336 		goto failed_connector;
337 
338 	connector = &psb_intel_connector->base;
339 	encoder = &psb_intel_encoder->base;
340 	drm_connector_init(dev, connector,
341 			   &oaktrail_hdmi_connector_funcs,
342 			   DRM_MODE_CONNECTOR_DVID);
343 
344 	drm_encoder_init(dev, encoder,
345 			 &oaktrail_hdmi_enc_funcs,
346 			 DRM_MODE_ENCODER_TMDS);
347 
348 	psb_intel_connector_attach_encoder(psb_intel_connector,
349 					   psb_intel_encoder);
350 
351 	psb_intel_encoder->type = INTEL_OUTPUT_HDMI;
352 	drm_encoder_helper_add(encoder, &oaktrail_hdmi_helper_funcs);
353 	drm_connector_helper_add(connector, &oaktrail_hdmi_connector_helper_funcs);
354 
355 	connector->display_info.subpixel_order = SubPixelHorizontalRGB;
356 	connector->interlace_allowed = false;
357 	connector->doublescan_allowed = false;
358 	drm_sysfs_connector_add(connector);
359 
360 	return;
361 
362 failed_connector:
363 	kfree(psb_intel_encoder);
364 }
365 
366 static DEFINE_PCI_DEVICE_TABLE(hdmi_ids) = {
367 	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x080d) },
368 	{ 0 }
369 };
370 
oaktrail_hdmi_setup(struct drm_device * dev)371 void oaktrail_hdmi_setup(struct drm_device *dev)
372 {
373 	struct drm_psb_private *dev_priv = dev->dev_private;
374 	struct pci_dev *pdev;
375 	struct oaktrail_hdmi_dev *hdmi_dev;
376 	int ret;
377 
378 	pdev = pci_get_device(PCI_VENDOR_ID_INTEL, 0x080d, NULL);
379 	if (!pdev)
380 		return;
381 
382 	hdmi_dev = kzalloc(sizeof(struct oaktrail_hdmi_dev), GFP_KERNEL);
383 	if (!hdmi_dev) {
384 		dev_err(dev->dev, "failed to allocate memory\n");
385 		goto out;
386 	}
387 
388 
389 	ret = pci_enable_device(pdev);
390 	if (ret) {
391 		dev_err(dev->dev, "failed to enable hdmi controller\n");
392 		goto free;
393 	}
394 
395 	hdmi_dev->mmio = pci_resource_start(pdev, 0);
396 	hdmi_dev->mmio_len = pci_resource_len(pdev, 0);
397 	hdmi_dev->regs = ioremap(hdmi_dev->mmio, hdmi_dev->mmio_len);
398 	if (!hdmi_dev->regs) {
399 		dev_err(dev->dev, "failed to map hdmi mmio\n");
400 		goto free;
401 	}
402 
403 	hdmi_dev->dev = pdev;
404 	pci_set_drvdata(pdev, hdmi_dev);
405 
406 	/* Initialize i2c controller */
407 	ret = oaktrail_hdmi_i2c_init(hdmi_dev->dev);
408 	if (ret)
409 		dev_err(dev->dev, "HDMI I2C initialization failed\n");
410 
411 	dev_priv->hdmi_priv = hdmi_dev;
412 	oaktrail_hdmi_audio_disable(dev);
413 	return;
414 
415 free:
416 	kfree(hdmi_dev);
417 out:
418 	return;
419 }
420 
oaktrail_hdmi_teardown(struct drm_device * dev)421 void oaktrail_hdmi_teardown(struct drm_device *dev)
422 {
423 	struct drm_psb_private *dev_priv = dev->dev_private;
424 	struct oaktrail_hdmi_dev *hdmi_dev = dev_priv->hdmi_priv;
425 	struct pci_dev *pdev;
426 
427 	if (hdmi_dev) {
428 		pdev = hdmi_dev->dev;
429 		pci_set_drvdata(pdev, NULL);
430 		oaktrail_hdmi_i2c_exit(pdev);
431 		iounmap(hdmi_dev->regs);
432 		kfree(hdmi_dev);
433 		pci_dev_put(pdev);
434 	}
435 }
436 
437 /* save HDMI register state */
oaktrail_hdmi_save(struct drm_device * dev)438 void oaktrail_hdmi_save(struct drm_device *dev)
439 {
440 	struct drm_psb_private *dev_priv = dev->dev_private;
441 	struct oaktrail_hdmi_dev *hdmi_dev = dev_priv->hdmi_priv;
442 	struct psb_state *regs = &dev_priv->regs.psb;
443 	int i;
444 
445 	/* dpll */
446 	hdmi_dev->saveDPLL_CTRL = PSB_RVDC32(DPLL_CTRL);
447 	hdmi_dev->saveDPLL_DIV_CTRL = PSB_RVDC32(DPLL_DIV_CTRL);
448 	hdmi_dev->saveDPLL_ADJUST = PSB_RVDC32(DPLL_ADJUST);
449 	hdmi_dev->saveDPLL_UPDATE = PSB_RVDC32(DPLL_UPDATE);
450 	hdmi_dev->saveDPLL_CLK_ENABLE = PSB_RVDC32(DPLL_CLK_ENABLE);
451 
452 	/* pipe B */
453 	regs->savePIPEBCONF = PSB_RVDC32(PIPEBCONF);
454 	regs->savePIPEBSRC  = PSB_RVDC32(PIPEBSRC);
455 	regs->saveHTOTAL_B  = PSB_RVDC32(HTOTAL_B);
456 	regs->saveHBLANK_B  = PSB_RVDC32(HBLANK_B);
457 	regs->saveHSYNC_B   = PSB_RVDC32(HSYNC_B);
458 	regs->saveVTOTAL_B  = PSB_RVDC32(VTOTAL_B);
459 	regs->saveVBLANK_B  = PSB_RVDC32(VBLANK_B);
460 	regs->saveVSYNC_B   = PSB_RVDC32(VSYNC_B);
461 
462 	hdmi_dev->savePCH_PIPEBCONF = PSB_RVDC32(PCH_PIPEBCONF);
463 	hdmi_dev->savePCH_PIPEBSRC = PSB_RVDC32(PCH_PIPEBSRC);
464 	hdmi_dev->savePCH_HTOTAL_B = PSB_RVDC32(PCH_HTOTAL_B);
465 	hdmi_dev->savePCH_HBLANK_B = PSB_RVDC32(PCH_HBLANK_B);
466 	hdmi_dev->savePCH_HSYNC_B  = PSB_RVDC32(PCH_HSYNC_B);
467 	hdmi_dev->savePCH_VTOTAL_B = PSB_RVDC32(PCH_VTOTAL_B);
468 	hdmi_dev->savePCH_VBLANK_B = PSB_RVDC32(PCH_VBLANK_B);
469 	hdmi_dev->savePCH_VSYNC_B  = PSB_RVDC32(PCH_VSYNC_B);
470 
471 	/* plane */
472 	regs->saveDSPBCNTR = PSB_RVDC32(DSPBCNTR);
473 	regs->saveDSPBSTRIDE = PSB_RVDC32(DSPBSTRIDE);
474 	regs->saveDSPBADDR = PSB_RVDC32(DSPBBASE);
475 	regs->saveDSPBSURF = PSB_RVDC32(DSPBSURF);
476 	regs->saveDSPBLINOFF = PSB_RVDC32(DSPBLINOFF);
477 	regs->saveDSPBTILEOFF = PSB_RVDC32(DSPBTILEOFF);
478 
479 	/* cursor B */
480 	regs->saveDSPBCURSOR_CTRL = PSB_RVDC32(CURBCNTR);
481 	regs->saveDSPBCURSOR_BASE = PSB_RVDC32(CURBBASE);
482 	regs->saveDSPBCURSOR_POS = PSB_RVDC32(CURBPOS);
483 
484 	/* save palette */
485 	for (i = 0; i < 256; i++)
486 		regs->save_palette_b[i] = PSB_RVDC32(PALETTE_B + (i << 2));
487 }
488 
489 /* restore HDMI register state */
oaktrail_hdmi_restore(struct drm_device * dev)490 void oaktrail_hdmi_restore(struct drm_device *dev)
491 {
492 	struct drm_psb_private *dev_priv = dev->dev_private;
493 	struct oaktrail_hdmi_dev *hdmi_dev = dev_priv->hdmi_priv;
494 	struct psb_state *regs = &dev_priv->regs.psb;
495 	int i;
496 
497 	/* dpll */
498 	PSB_WVDC32(hdmi_dev->saveDPLL_CTRL, DPLL_CTRL);
499 	PSB_WVDC32(hdmi_dev->saveDPLL_DIV_CTRL, DPLL_DIV_CTRL);
500 	PSB_WVDC32(hdmi_dev->saveDPLL_ADJUST, DPLL_ADJUST);
501 	PSB_WVDC32(hdmi_dev->saveDPLL_UPDATE, DPLL_UPDATE);
502 	PSB_WVDC32(hdmi_dev->saveDPLL_CLK_ENABLE, DPLL_CLK_ENABLE);
503 	DRM_UDELAY(150);
504 
505 	/* pipe */
506 	PSB_WVDC32(regs->savePIPEBSRC, PIPEBSRC);
507 	PSB_WVDC32(regs->saveHTOTAL_B, HTOTAL_B);
508 	PSB_WVDC32(regs->saveHBLANK_B, HBLANK_B);
509 	PSB_WVDC32(regs->saveHSYNC_B,  HSYNC_B);
510 	PSB_WVDC32(regs->saveVTOTAL_B, VTOTAL_B);
511 	PSB_WVDC32(regs->saveVBLANK_B, VBLANK_B);
512 	PSB_WVDC32(regs->saveVSYNC_B,  VSYNC_B);
513 
514 	PSB_WVDC32(hdmi_dev->savePCH_PIPEBSRC, PCH_PIPEBSRC);
515 	PSB_WVDC32(hdmi_dev->savePCH_HTOTAL_B, PCH_HTOTAL_B);
516 	PSB_WVDC32(hdmi_dev->savePCH_HBLANK_B, PCH_HBLANK_B);
517 	PSB_WVDC32(hdmi_dev->savePCH_HSYNC_B,  PCH_HSYNC_B);
518 	PSB_WVDC32(hdmi_dev->savePCH_VTOTAL_B, PCH_VTOTAL_B);
519 	PSB_WVDC32(hdmi_dev->savePCH_VBLANK_B, PCH_VBLANK_B);
520 	PSB_WVDC32(hdmi_dev->savePCH_VSYNC_B,  PCH_VSYNC_B);
521 
522 	PSB_WVDC32(regs->savePIPEBCONF, PIPEBCONF);
523 	PSB_WVDC32(hdmi_dev->savePCH_PIPEBCONF, PCH_PIPEBCONF);
524 
525 	/* plane */
526 	PSB_WVDC32(regs->saveDSPBLINOFF, DSPBLINOFF);
527 	PSB_WVDC32(regs->saveDSPBSTRIDE, DSPBSTRIDE);
528 	PSB_WVDC32(regs->saveDSPBTILEOFF, DSPBTILEOFF);
529 	PSB_WVDC32(regs->saveDSPBCNTR, DSPBCNTR);
530 	PSB_WVDC32(regs->saveDSPBSURF, DSPBSURF);
531 
532 	/* cursor B */
533 	PSB_WVDC32(regs->saveDSPBCURSOR_CTRL, CURBCNTR);
534 	PSB_WVDC32(regs->saveDSPBCURSOR_POS, CURBPOS);
535 	PSB_WVDC32(regs->saveDSPBCURSOR_BASE, CURBBASE);
536 
537 	/* restore palette */
538 	for (i = 0; i < 256; i++)
539 		PSB_WVDC32(regs->save_palette_b[i], PALETTE_B + (i << 2));
540 }
541