xref: /linux/drivers/gpu/drm/gma500/oaktrail_hdmi.c (revision 08ec212c0f92cbf30e3ecc7349f18151714041d6)
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 
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 
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 
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 
179 static int oaktrail_hdmi_mode_valid(struct drm_connector *connector,
180 				struct drm_display_mode *mode)
181 {
182 	if (mode->clock > 165000)
183 		return MODE_CLOCK_HIGH;
184 	if (mode->clock < 20000)
185 		return MODE_CLOCK_LOW;
186 
187 	if (mode->flags & DRM_MODE_FLAG_DBLSCAN)
188 		return MODE_NO_DBLESCAN;
189 
190 	return MODE_OK;
191 }
192 
193 static bool oaktrail_hdmi_mode_fixup(struct drm_encoder *encoder,
194 				 const struct drm_display_mode *mode,
195 				 struct drm_display_mode *adjusted_mode)
196 {
197 	return true;
198 }
199 
200 static enum drm_connector_status
201 oaktrail_hdmi_detect(struct drm_connector *connector, bool force)
202 {
203 	enum drm_connector_status status;
204 	struct drm_device *dev = connector->dev;
205 	struct drm_psb_private *dev_priv = dev->dev_private;
206 	struct oaktrail_hdmi_dev *hdmi_dev = dev_priv->hdmi_priv;
207 	u32 temp;
208 
209 	temp = HDMI_READ(HDMI_HSR);
210 	DRM_DEBUG_KMS("HDMI_HSR %x\n", temp);
211 
212 	if ((temp & HDMI_DETECT_HDP) != 0)
213 		status = connector_status_connected;
214 	else
215 		status = connector_status_disconnected;
216 
217 	return status;
218 }
219 
220 static const unsigned char raw_edid[] = {
221 	0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x10, 0xac, 0x2f, 0xa0,
222 	0x53, 0x55, 0x33, 0x30, 0x16, 0x13, 0x01, 0x03, 0x0e, 0x3a, 0x24, 0x78,
223 	0xea, 0xe9, 0xf5, 0xac, 0x51, 0x30, 0xb4, 0x25, 0x11, 0x50, 0x54, 0xa5,
224 	0x4b, 0x00, 0x81, 0x80, 0xa9, 0x40, 0x71, 0x4f, 0xb3, 0x00, 0x01, 0x01,
225 	0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x28, 0x3c, 0x80, 0xa0, 0x70, 0xb0,
226 	0x23, 0x40, 0x30, 0x20, 0x36, 0x00, 0x46, 0x6c, 0x21, 0x00, 0x00, 0x1a,
227 	0x00, 0x00, 0x00, 0xff, 0x00, 0x47, 0x4e, 0x37, 0x32, 0x31, 0x39, 0x35,
228 	0x52, 0x30, 0x33, 0x55, 0x53, 0x0a, 0x00, 0x00, 0x00, 0xfc, 0x00, 0x44,
229 	0x45, 0x4c, 0x4c, 0x20, 0x32, 0x37, 0x30, 0x39, 0x57, 0x0a, 0x20, 0x20,
230 	0x00, 0x00, 0x00, 0xfd, 0x00, 0x38, 0x4c, 0x1e, 0x53, 0x11, 0x00, 0x0a,
231 	0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x00, 0x8d
232 };
233 
234 static int oaktrail_hdmi_get_modes(struct drm_connector *connector)
235 {
236 	struct drm_device *dev = connector->dev;
237 	struct drm_psb_private *dev_priv = dev->dev_private;
238 	struct i2c_adapter *i2c_adap;
239 	struct edid *edid;
240 	struct drm_display_mode *mode, *t;
241 	int i = 0, ret = 0;
242 
243 	i2c_adap = i2c_get_adapter(3);
244 	if (i2c_adap == NULL) {
245 		DRM_ERROR("No ddc adapter available!\n");
246 		edid = (struct edid *)raw_edid;
247 	} else {
248 		edid = (struct edid *)raw_edid;
249 		/* FIXME ? edid = drm_get_edid(connector, i2c_adap); */
250 	}
251 
252 	if (edid) {
253 		drm_mode_connector_update_edid_property(connector, edid);
254 		ret = drm_add_edid_modes(connector, edid);
255 	}
256 
257 	/*
258 	 * prune modes that require frame buffer bigger than stolen mem
259 	 */
260 	list_for_each_entry_safe(mode, t, &connector->probed_modes, head) {
261 		if ((mode->hdisplay * mode->vdisplay * 4) >= dev_priv->vram_stolen_size) {
262 			i++;
263 			drm_mode_remove(connector, mode);
264 		}
265 	}
266 	return ret - i;
267 }
268 
269 static void oaktrail_hdmi_mode_set(struct drm_encoder *encoder,
270 			       struct drm_display_mode *mode,
271 			       struct drm_display_mode *adjusted_mode)
272 {
273 	struct drm_device *dev = encoder->dev;
274 
275 	oaktrail_hdmi_audio_enable(dev);
276 	return;
277 }
278 
279 static void oaktrail_hdmi_destroy(struct drm_connector *connector)
280 {
281 	return;
282 }
283 
284 static const struct drm_encoder_helper_funcs oaktrail_hdmi_helper_funcs = {
285 	.dpms = oaktrail_hdmi_dpms,
286 	.mode_fixup = oaktrail_hdmi_mode_fixup,
287 	.prepare = psb_intel_encoder_prepare,
288 	.mode_set = oaktrail_hdmi_mode_set,
289 	.commit = psb_intel_encoder_commit,
290 };
291 
292 static const struct drm_connector_helper_funcs
293 					oaktrail_hdmi_connector_helper_funcs = {
294 	.get_modes = oaktrail_hdmi_get_modes,
295 	.mode_valid = oaktrail_hdmi_mode_valid,
296 	.best_encoder = psb_intel_best_encoder,
297 };
298 
299 static const struct drm_connector_funcs oaktrail_hdmi_connector_funcs = {
300 	.dpms = drm_helper_connector_dpms,
301 	.detect = oaktrail_hdmi_detect,
302 	.fill_modes = drm_helper_probe_single_connector_modes,
303 	.destroy = oaktrail_hdmi_destroy,
304 };
305 
306 static void oaktrail_hdmi_enc_destroy(struct drm_encoder *encoder)
307 {
308 	drm_encoder_cleanup(encoder);
309 }
310 
311 static const struct drm_encoder_funcs oaktrail_hdmi_enc_funcs = {
312 	.destroy = oaktrail_hdmi_enc_destroy,
313 };
314 
315 void oaktrail_hdmi_init(struct drm_device *dev,
316 					struct psb_intel_mode_device *mode_dev)
317 {
318 	struct psb_intel_encoder *psb_intel_encoder;
319 	struct psb_intel_connector *psb_intel_connector;
320 	struct drm_connector *connector;
321 	struct drm_encoder *encoder;
322 
323 	psb_intel_encoder = kzalloc(sizeof(struct psb_intel_encoder), GFP_KERNEL);
324 	if (!psb_intel_encoder)
325 		return;
326 
327 	psb_intel_connector = kzalloc(sizeof(struct psb_intel_connector), GFP_KERNEL);
328 	if (!psb_intel_connector)
329 		goto failed_connector;
330 
331 	connector = &psb_intel_connector->base;
332 	encoder = &psb_intel_encoder->base;
333 	drm_connector_init(dev, connector,
334 			   &oaktrail_hdmi_connector_funcs,
335 			   DRM_MODE_CONNECTOR_DVID);
336 
337 	drm_encoder_init(dev, encoder,
338 			 &oaktrail_hdmi_enc_funcs,
339 			 DRM_MODE_ENCODER_TMDS);
340 
341 	psb_intel_connector_attach_encoder(psb_intel_connector,
342 					   psb_intel_encoder);
343 
344 	psb_intel_encoder->type = INTEL_OUTPUT_HDMI;
345 	drm_encoder_helper_add(encoder, &oaktrail_hdmi_helper_funcs);
346 	drm_connector_helper_add(connector, &oaktrail_hdmi_connector_helper_funcs);
347 
348 	connector->display_info.subpixel_order = SubPixelHorizontalRGB;
349 	connector->interlace_allowed = false;
350 	connector->doublescan_allowed = false;
351 	drm_sysfs_connector_add(connector);
352 
353 	return;
354 
355 failed_connector:
356 	kfree(psb_intel_encoder);
357 }
358 
359 static DEFINE_PCI_DEVICE_TABLE(hdmi_ids) = {
360 	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x080d) },
361 	{ 0 }
362 };
363 
364 void oaktrail_hdmi_setup(struct drm_device *dev)
365 {
366 	struct drm_psb_private *dev_priv = dev->dev_private;
367 	struct pci_dev *pdev;
368 	struct oaktrail_hdmi_dev *hdmi_dev;
369 	int ret;
370 
371 	pdev = pci_get_device(PCI_VENDOR_ID_INTEL, 0x080d, NULL);
372 	if (!pdev)
373 		return;
374 
375 	hdmi_dev = kzalloc(sizeof(struct oaktrail_hdmi_dev), GFP_KERNEL);
376 	if (!hdmi_dev) {
377 		dev_err(dev->dev, "failed to allocate memory\n");
378 		goto out;
379 	}
380 
381 
382 	ret = pci_enable_device(pdev);
383 	if (ret) {
384 		dev_err(dev->dev, "failed to enable hdmi controller\n");
385 		goto free;
386 	}
387 
388 	hdmi_dev->mmio = pci_resource_start(pdev, 0);
389 	hdmi_dev->mmio_len = pci_resource_len(pdev, 0);
390 	hdmi_dev->regs = ioremap(hdmi_dev->mmio, hdmi_dev->mmio_len);
391 	if (!hdmi_dev->regs) {
392 		dev_err(dev->dev, "failed to map hdmi mmio\n");
393 		goto free;
394 	}
395 
396 	hdmi_dev->dev = pdev;
397 	pci_set_drvdata(pdev, hdmi_dev);
398 
399 	/* Initialize i2c controller */
400 	ret = oaktrail_hdmi_i2c_init(hdmi_dev->dev);
401 	if (ret)
402 		dev_err(dev->dev, "HDMI I2C initialization failed\n");
403 
404 	dev_priv->hdmi_priv = hdmi_dev;
405 	oaktrail_hdmi_audio_disable(dev);
406 	return;
407 
408 free:
409 	kfree(hdmi_dev);
410 out:
411 	return;
412 }
413 
414 void oaktrail_hdmi_teardown(struct drm_device *dev)
415 {
416 	struct drm_psb_private *dev_priv = dev->dev_private;
417 	struct oaktrail_hdmi_dev *hdmi_dev = dev_priv->hdmi_priv;
418 	struct pci_dev *pdev;
419 
420 	if (hdmi_dev) {
421 		pdev = hdmi_dev->dev;
422 		pci_set_drvdata(pdev, NULL);
423 		oaktrail_hdmi_i2c_exit(pdev);
424 		iounmap(hdmi_dev->regs);
425 		kfree(hdmi_dev);
426 		pci_dev_put(pdev);
427 	}
428 }
429 
430 /* save HDMI register state */
431 void oaktrail_hdmi_save(struct drm_device *dev)
432 {
433 	struct drm_psb_private *dev_priv = dev->dev_private;
434 	struct oaktrail_hdmi_dev *hdmi_dev = dev_priv->hdmi_priv;
435 	struct psb_state *regs = &dev_priv->regs.psb;
436 	struct psb_pipe *pipeb = &dev_priv->regs.pipe[1];
437 	int i;
438 
439 	/* dpll */
440 	hdmi_dev->saveDPLL_CTRL = PSB_RVDC32(DPLL_CTRL);
441 	hdmi_dev->saveDPLL_DIV_CTRL = PSB_RVDC32(DPLL_DIV_CTRL);
442 	hdmi_dev->saveDPLL_ADJUST = PSB_RVDC32(DPLL_ADJUST);
443 	hdmi_dev->saveDPLL_UPDATE = PSB_RVDC32(DPLL_UPDATE);
444 	hdmi_dev->saveDPLL_CLK_ENABLE = PSB_RVDC32(DPLL_CLK_ENABLE);
445 
446 	/* pipe B */
447 	pipeb->conf = PSB_RVDC32(PIPEBCONF);
448 	pipeb->src = PSB_RVDC32(PIPEBSRC);
449 	pipeb->htotal = PSB_RVDC32(HTOTAL_B);
450 	pipeb->hblank = PSB_RVDC32(HBLANK_B);
451 	pipeb->hsync = PSB_RVDC32(HSYNC_B);
452 	pipeb->vtotal = PSB_RVDC32(VTOTAL_B);
453 	pipeb->vblank = PSB_RVDC32(VBLANK_B);
454 	pipeb->vsync = PSB_RVDC32(VSYNC_B);
455 
456 	hdmi_dev->savePCH_PIPEBCONF = PSB_RVDC32(PCH_PIPEBCONF);
457 	hdmi_dev->savePCH_PIPEBSRC = PSB_RVDC32(PCH_PIPEBSRC);
458 	hdmi_dev->savePCH_HTOTAL_B = PSB_RVDC32(PCH_HTOTAL_B);
459 	hdmi_dev->savePCH_HBLANK_B = PSB_RVDC32(PCH_HBLANK_B);
460 	hdmi_dev->savePCH_HSYNC_B  = PSB_RVDC32(PCH_HSYNC_B);
461 	hdmi_dev->savePCH_VTOTAL_B = PSB_RVDC32(PCH_VTOTAL_B);
462 	hdmi_dev->savePCH_VBLANK_B = PSB_RVDC32(PCH_VBLANK_B);
463 	hdmi_dev->savePCH_VSYNC_B  = PSB_RVDC32(PCH_VSYNC_B);
464 
465 	/* plane */
466 	pipeb->cntr = PSB_RVDC32(DSPBCNTR);
467 	pipeb->stride = PSB_RVDC32(DSPBSTRIDE);
468 	pipeb->addr = PSB_RVDC32(DSPBBASE);
469 	pipeb->surf = PSB_RVDC32(DSPBSURF);
470 	pipeb->linoff = PSB_RVDC32(DSPBLINOFF);
471 	pipeb->tileoff = PSB_RVDC32(DSPBTILEOFF);
472 
473 	/* cursor B */
474 	regs->saveDSPBCURSOR_CTRL = PSB_RVDC32(CURBCNTR);
475 	regs->saveDSPBCURSOR_BASE = PSB_RVDC32(CURBBASE);
476 	regs->saveDSPBCURSOR_POS = PSB_RVDC32(CURBPOS);
477 
478 	/* save palette */
479 	for (i = 0; i < 256; i++)
480 		pipeb->palette[i] = PSB_RVDC32(PALETTE_B + (i << 2));
481 }
482 
483 /* restore HDMI register state */
484 void oaktrail_hdmi_restore(struct drm_device *dev)
485 {
486 	struct drm_psb_private *dev_priv = dev->dev_private;
487 	struct oaktrail_hdmi_dev *hdmi_dev = dev_priv->hdmi_priv;
488 	struct psb_state *regs = &dev_priv->regs.psb;
489 	struct psb_pipe *pipeb = &dev_priv->regs.pipe[1];
490 	int i;
491 
492 	/* dpll */
493 	PSB_WVDC32(hdmi_dev->saveDPLL_CTRL, DPLL_CTRL);
494 	PSB_WVDC32(hdmi_dev->saveDPLL_DIV_CTRL, DPLL_DIV_CTRL);
495 	PSB_WVDC32(hdmi_dev->saveDPLL_ADJUST, DPLL_ADJUST);
496 	PSB_WVDC32(hdmi_dev->saveDPLL_UPDATE, DPLL_UPDATE);
497 	PSB_WVDC32(hdmi_dev->saveDPLL_CLK_ENABLE, DPLL_CLK_ENABLE);
498 	DRM_UDELAY(150);
499 
500 	/* pipe */
501 	PSB_WVDC32(pipeb->src, PIPEBSRC);
502 	PSB_WVDC32(pipeb->htotal, HTOTAL_B);
503 	PSB_WVDC32(pipeb->hblank, HBLANK_B);
504 	PSB_WVDC32(pipeb->hsync,  HSYNC_B);
505 	PSB_WVDC32(pipeb->vtotal, VTOTAL_B);
506 	PSB_WVDC32(pipeb->vblank, VBLANK_B);
507 	PSB_WVDC32(pipeb->vsync,  VSYNC_B);
508 
509 	PSB_WVDC32(hdmi_dev->savePCH_PIPEBSRC, PCH_PIPEBSRC);
510 	PSB_WVDC32(hdmi_dev->savePCH_HTOTAL_B, PCH_HTOTAL_B);
511 	PSB_WVDC32(hdmi_dev->savePCH_HBLANK_B, PCH_HBLANK_B);
512 	PSB_WVDC32(hdmi_dev->savePCH_HSYNC_B,  PCH_HSYNC_B);
513 	PSB_WVDC32(hdmi_dev->savePCH_VTOTAL_B, PCH_VTOTAL_B);
514 	PSB_WVDC32(hdmi_dev->savePCH_VBLANK_B, PCH_VBLANK_B);
515 	PSB_WVDC32(hdmi_dev->savePCH_VSYNC_B,  PCH_VSYNC_B);
516 
517 	PSB_WVDC32(pipeb->conf, PIPEBCONF);
518 	PSB_WVDC32(hdmi_dev->savePCH_PIPEBCONF, PCH_PIPEBCONF);
519 
520 	/* plane */
521 	PSB_WVDC32(pipeb->linoff, DSPBLINOFF);
522 	PSB_WVDC32(pipeb->stride, DSPBSTRIDE);
523 	PSB_WVDC32(pipeb->tileoff, DSPBTILEOFF);
524 	PSB_WVDC32(pipeb->cntr, DSPBCNTR);
525 	PSB_WVDC32(pipeb->surf, DSPBSURF);
526 
527 	/* cursor B */
528 	PSB_WVDC32(regs->saveDSPBCURSOR_CTRL, CURBCNTR);
529 	PSB_WVDC32(regs->saveDSPBCURSOR_POS, CURBPOS);
530 	PSB_WVDC32(regs->saveDSPBCURSOR_BASE, CURBBASE);
531 
532 	/* restore palette */
533 	for (i = 0; i < 256; i++)
534 		PSB_WVDC32(pipeb->palette[i], PALETTE_B + (i << 2));
535 }
536