1/*
2 * intelfb
3 *
4 * Linux framebuffer driver for Intel(R) 865G integrated graphics chips.
5 *
6 * Copyright � 2002, 2003 David Dawes <dawes@xfree86.org>
7 *                   2004 Sylvain Meyer
8 *
9 * This driver consists of two parts.  The first part (intelfbdrv.c) provides
10 * the basic fbdev interfaces, is derived in part from the radeonfb and
11 * vesafb drivers, and is covered by the GPL.  The second part (intelfbhw.c)
12 * provides the code to program the hardware.  Most of it is derived from
13 * the i810/i830 XFree86 driver.  The HW-specific code is covered here
14 * under a dual license (GPL and MIT/XFree86 license).
15 *
16 * Author: David Dawes
17 *
18 */
19
20/* $DHD: intelfb/intelfbhw.c,v 1.9 2003/06/27 15:06:25 dawes Exp $ */
21
22#include <linux/module.h>
23#include <linux/kernel.h>
24#include <linux/errno.h>
25#include <linux/string.h>
26#include <linux/mm.h>
27#include <linux/slab.h>
28#include <linux/delay.h>
29#include <linux/fb.h>
30#include <linux/ioport.h>
31#include <linux/init.h>
32#include <linux/pci.h>
33#include <linux/vmalloc.h>
34#include <linux/pagemap.h>
35#include <linux/interrupt.h>
36
37#include <asm/io.h>
38
39#include "intelfb.h"
40#include "intelfbhw.h"
41
42struct pll_min_max {
43	int min_m, max_m, min_m1, max_m1;
44	int min_m2, max_m2, min_n, max_n;
45	int min_p, max_p, min_p1, max_p1;
46	int min_vco, max_vco, p_transition_clk, ref_clk;
47	int p_inc_lo, p_inc_hi;
48};
49
50#define PLLS_I8xx 0
51#define PLLS_I9xx 1
52#define PLLS_MAX 2
53
54static struct pll_min_max plls[PLLS_MAX] = {
55	{ 108, 140, 18, 26,
56	  6, 16, 3, 16,
57	  4, 128, 0, 31,
58	  930000, 1400000, 165000, 48000,
59	  4, 2 }, //I8xx
60
61	{ 75, 120, 10, 20,
62	  5, 9, 4, 7,
63	  5, 80, 1, 8,
64	  1400000, 2800000, 200000, 96000,
65	  10, 5 }  //I9xx
66};
67
68int
69intelfbhw_get_chipset(struct pci_dev *pdev, struct intelfb_info *dinfo)
70{
71	u32 tmp;
72	if (!pdev || !dinfo)
73		return 1;
74
75	switch (pdev->device) {
76	case PCI_DEVICE_ID_INTEL_830M:
77		dinfo->name = "Intel(R) 830M";
78		dinfo->chipset = INTEL_830M;
79		dinfo->mobile = 1;
80		dinfo->pll_index = PLLS_I8xx;
81		return 0;
82	case PCI_DEVICE_ID_INTEL_845G:
83		dinfo->name = "Intel(R) 845G";
84		dinfo->chipset = INTEL_845G;
85		dinfo->mobile = 0;
86		dinfo->pll_index = PLLS_I8xx;
87		return 0;
88	case PCI_DEVICE_ID_INTEL_85XGM:
89		tmp = 0;
90		dinfo->mobile = 1;
91		dinfo->pll_index = PLLS_I8xx;
92		pci_read_config_dword(pdev, INTEL_85X_CAPID, &tmp);
93		switch ((tmp >> INTEL_85X_VARIANT_SHIFT) &
94			INTEL_85X_VARIANT_MASK) {
95		case INTEL_VAR_855GME:
96			dinfo->name = "Intel(R) 855GME";
97			dinfo->chipset = INTEL_855GME;
98			return 0;
99		case INTEL_VAR_855GM:
100			dinfo->name = "Intel(R) 855GM";
101			dinfo->chipset = INTEL_855GM;
102			return 0;
103		case INTEL_VAR_852GME:
104			dinfo->name = "Intel(R) 852GME";
105			dinfo->chipset = INTEL_852GME;
106			return 0;
107		case INTEL_VAR_852GM:
108			dinfo->name = "Intel(R) 852GM";
109			dinfo->chipset = INTEL_852GM;
110			return 0;
111		default:
112			dinfo->name = "Intel(R) 852GM/855GM";
113			dinfo->chipset = INTEL_85XGM;
114			return 0;
115		}
116		break;
117	case PCI_DEVICE_ID_INTEL_865G:
118		dinfo->name = "Intel(R) 865G";
119		dinfo->chipset = INTEL_865G;
120		dinfo->mobile = 0;
121		dinfo->pll_index = PLLS_I8xx;
122		return 0;
123	case PCI_DEVICE_ID_INTEL_915G:
124		dinfo->name = "Intel(R) 915G";
125		dinfo->chipset = INTEL_915G;
126		dinfo->mobile = 0;
127		dinfo->pll_index = PLLS_I9xx;
128		return 0;
129	case PCI_DEVICE_ID_INTEL_915GM:
130		dinfo->name = "Intel(R) 915GM";
131		dinfo->chipset = INTEL_915GM;
132		dinfo->mobile = 1;
133		dinfo->pll_index = PLLS_I9xx;
134		return 0;
135	case PCI_DEVICE_ID_INTEL_945G:
136		dinfo->name = "Intel(R) 945G";
137		dinfo->chipset = INTEL_945G;
138		dinfo->mobile = 0;
139		dinfo->pll_index = PLLS_I9xx;
140		return 0;
141	case PCI_DEVICE_ID_INTEL_945GM:
142		dinfo->name = "Intel(R) 945GM";
143		dinfo->chipset = INTEL_945GM;
144		dinfo->mobile = 1;
145		dinfo->pll_index = PLLS_I9xx;
146		return 0;
147	default:
148		return 1;
149	}
150}
151
152int
153intelfbhw_get_memory(struct pci_dev *pdev, int *aperture_size,
154		     int *stolen_size)
155{
156	struct pci_dev *bridge_dev;
157	u16 tmp;
158	int stolen_overhead;
159
160	if (!pdev || !aperture_size || !stolen_size)
161		return 1;
162
163	/* Find the bridge device.  It is always 0:0.0 */
164	if (!(bridge_dev = pci_get_bus_and_slot(0, PCI_DEVFN(0, 0)))) {
165		ERR_MSG("cannot find bridge device\n");
166		return 1;
167	}
168
169	/* Get the fb aperture size and "stolen" memory amount. */
170	tmp = 0;
171	pci_read_config_word(bridge_dev, INTEL_GMCH_CTRL, &tmp);
172	pci_dev_put(bridge_dev);
173
174	switch (pdev->device) {
175	case PCI_DEVICE_ID_INTEL_915G:
176	case PCI_DEVICE_ID_INTEL_915GM:
177	case PCI_DEVICE_ID_INTEL_945G:
178	case PCI_DEVICE_ID_INTEL_945GM:
179		/* 915 and 945 chipsets support a 256MB aperture.
180		   Aperture size is determined by inspected the
181		   base address of the aperture. */
182		if (pci_resource_start(pdev, 2) & 0x08000000)
183			*aperture_size = MB(128);
184		else
185			*aperture_size = MB(256);
186		break;
187	default:
188		if ((tmp & INTEL_GMCH_MEM_MASK) == INTEL_GMCH_MEM_64M)
189			*aperture_size = MB(64);
190		else
191			*aperture_size = MB(128);
192		break;
193	}
194
195	/* Stolen memory size is reduced by the GTT and the popup.
196	   GTT is 1K per MB of aperture size, and popup is 4K. */
197	stolen_overhead = (*aperture_size / MB(1)) + 4;
198	switch(pdev->device) {
199	case PCI_DEVICE_ID_INTEL_830M:
200	case PCI_DEVICE_ID_INTEL_845G:
201		switch (tmp & INTEL_830_GMCH_GMS_MASK) {
202		case INTEL_830_GMCH_GMS_STOLEN_512:
203			*stolen_size = KB(512) - KB(stolen_overhead);
204			return 0;
205		case INTEL_830_GMCH_GMS_STOLEN_1024:
206			*stolen_size = MB(1) - KB(stolen_overhead);
207			return 0;
208		case INTEL_830_GMCH_GMS_STOLEN_8192:
209			*stolen_size = MB(8) - KB(stolen_overhead);
210			return 0;
211		case INTEL_830_GMCH_GMS_LOCAL:
212			ERR_MSG("only local memory found\n");
213			return 1;
214		case INTEL_830_GMCH_GMS_DISABLED:
215			ERR_MSG("video memory is disabled\n");
216			return 1;
217		default:
218			ERR_MSG("unexpected GMCH_GMS value: 0x%02x\n",
219				tmp & INTEL_830_GMCH_GMS_MASK);
220			return 1;
221		}
222		break;
223	default:
224		switch (tmp & INTEL_855_GMCH_GMS_MASK) {
225		case INTEL_855_GMCH_GMS_STOLEN_1M:
226			*stolen_size = MB(1) - KB(stolen_overhead);
227			return 0;
228		case INTEL_855_GMCH_GMS_STOLEN_4M:
229			*stolen_size = MB(4) - KB(stolen_overhead);
230			return 0;
231		case INTEL_855_GMCH_GMS_STOLEN_8M:
232			*stolen_size = MB(8) - KB(stolen_overhead);
233			return 0;
234		case INTEL_855_GMCH_GMS_STOLEN_16M:
235			*stolen_size = MB(16) - KB(stolen_overhead);
236			return 0;
237		case INTEL_855_GMCH_GMS_STOLEN_32M:
238			*stolen_size = MB(32) - KB(stolen_overhead);
239			return 0;
240		case INTEL_915G_GMCH_GMS_STOLEN_48M:
241			*stolen_size = MB(48) - KB(stolen_overhead);
242			return 0;
243		case INTEL_915G_GMCH_GMS_STOLEN_64M:
244			*stolen_size = MB(64) - KB(stolen_overhead);
245			return 0;
246		case INTEL_855_GMCH_GMS_DISABLED:
247			ERR_MSG("video memory is disabled\n");
248			return 0;
249		default:
250			ERR_MSG("unexpected GMCH_GMS value: 0x%02x\n",
251				tmp & INTEL_855_GMCH_GMS_MASK);
252			return 1;
253		}
254	}
255}
256
257int
258intelfbhw_check_non_crt(struct intelfb_info *dinfo)
259{
260	int dvo = 0;
261
262	if (INREG(LVDS) & PORT_ENABLE)
263		dvo |= LVDS_PORT;
264	if (INREG(DVOA) & PORT_ENABLE)
265		dvo |= DVOA_PORT;
266	if (INREG(DVOB) & PORT_ENABLE)
267		dvo |= DVOB_PORT;
268	if (INREG(DVOC) & PORT_ENABLE)
269		dvo |= DVOC_PORT;
270
271	return dvo;
272}
273
274const char *
275intelfbhw_dvo_to_string(int dvo)
276{
277	if (dvo & DVOA_PORT)
278		return "DVO port A";
279	else if (dvo & DVOB_PORT)
280		return "DVO port B";
281	else if (dvo & DVOC_PORT)
282		return "DVO port C";
283	else if (dvo & LVDS_PORT)
284		return "LVDS port";
285	else
286		return NULL;
287}
288
289
290int
291intelfbhw_validate_mode(struct intelfb_info *dinfo,
292			struct fb_var_screeninfo *var)
293{
294	int bytes_per_pixel;
295	int tmp;
296
297#if VERBOSE > 0
298	DBG_MSG("intelfbhw_validate_mode\n");
299#endif
300
301	bytes_per_pixel = var->bits_per_pixel / 8;
302	if (bytes_per_pixel == 3)
303		bytes_per_pixel = 4;
304
305	/* Check if enough video memory. */
306	tmp = var->yres_virtual * var->xres_virtual * bytes_per_pixel;
307	if (tmp > dinfo->fb.size) {
308		WRN_MSG("Not enough video ram for mode "
309			"(%d KByte vs %d KByte).\n",
310			BtoKB(tmp), BtoKB(dinfo->fb.size));
311		return 1;
312	}
313
314	/* Check if x/y limits are OK. */
315	if (var->xres - 1 > HACTIVE_MASK) {
316		WRN_MSG("X resolution too large (%d vs %d).\n",
317			var->xres, HACTIVE_MASK + 1);
318		return 1;
319	}
320	if (var->yres - 1 > VACTIVE_MASK) {
321		WRN_MSG("Y resolution too large (%d vs %d).\n",
322			var->yres, VACTIVE_MASK + 1);
323		return 1;
324	}
325
326	/* Check for interlaced/doublescan modes. */
327	if (var->vmode & FB_VMODE_INTERLACED) {
328		WRN_MSG("Mode is interlaced.\n");
329		return 1;
330	}
331	if (var->vmode & FB_VMODE_DOUBLE) {
332		WRN_MSG("Mode is double-scan.\n");
333		return 1;
334	}
335
336	/* Check if clock is OK. */
337	tmp = 1000000000 / var->pixclock;
338	if (tmp < MIN_CLOCK) {
339		WRN_MSG("Pixel clock is too low (%d MHz vs %d MHz).\n",
340			(tmp + 500) / 1000, MIN_CLOCK / 1000);
341		return 1;
342	}
343	if (tmp > MAX_CLOCK) {
344		WRN_MSG("Pixel clock is too high (%d MHz vs %d MHz).\n",
345			(tmp + 500) / 1000, MAX_CLOCK / 1000);
346		return 1;
347	}
348
349	return 0;
350}
351
352int
353intelfbhw_pan_display(struct fb_var_screeninfo *var, struct fb_info *info)
354{
355	struct intelfb_info *dinfo = GET_DINFO(info);
356	u32 offset, xoffset, yoffset;
357
358#if VERBOSE > 0
359	DBG_MSG("intelfbhw_pan_display\n");
360#endif
361
362	xoffset = ROUND_DOWN_TO(var->xoffset, 8);
363	yoffset = var->yoffset;
364
365	if ((xoffset + var->xres > var->xres_virtual) ||
366	    (yoffset + var->yres > var->yres_virtual))
367		return -EINVAL;
368
369	offset = (yoffset * dinfo->pitch) +
370		 (xoffset * var->bits_per_pixel) / 8;
371
372	offset += dinfo->fb.offset << 12;
373
374	dinfo->vsync.pan_offset = offset;
375	if ((var->activate & FB_ACTIVATE_VBL) && !intelfbhw_enable_irq(dinfo, 0)) {
376		dinfo->vsync.pan_display = 1;
377	} else {
378		dinfo->vsync.pan_display = 0;
379		OUTREG(DSPABASE, offset);
380	}
381
382	return 0;
383}
384
385/* Blank the screen. */
386void
387intelfbhw_do_blank(int blank, struct fb_info *info)
388{
389	struct intelfb_info *dinfo = GET_DINFO(info);
390	u32 tmp;
391
392#if VERBOSE > 0
393	DBG_MSG("intelfbhw_do_blank: blank is %d\n", blank);
394#endif
395
396	/* Turn plane A on or off */
397	tmp = INREG(DSPACNTR);
398	if (blank)
399		tmp &= ~DISPPLANE_PLANE_ENABLE;
400	else
401		tmp |= DISPPLANE_PLANE_ENABLE;
402	OUTREG(DSPACNTR, tmp);
403	/* Flush */
404	tmp = INREG(DSPABASE);
405	OUTREG(DSPABASE, tmp);
406
407	/* Turn off/on the HW cursor */
408#if VERBOSE > 0
409	DBG_MSG("cursor_on is %d\n", dinfo->cursor_on);
410#endif
411	if (dinfo->cursor_on) {
412		if (blank) {
413			intelfbhw_cursor_hide(dinfo);
414		} else {
415			intelfbhw_cursor_show(dinfo);
416		}
417		dinfo->cursor_on = 1;
418	}
419	dinfo->cursor_blanked = blank;
420
421	/* Set DPMS level */
422	tmp = INREG(ADPA) & ~ADPA_DPMS_CONTROL_MASK;
423	switch (blank) {
424	case FB_BLANK_UNBLANK:
425	case FB_BLANK_NORMAL:
426		tmp |= ADPA_DPMS_D0;
427		break;
428	case FB_BLANK_VSYNC_SUSPEND:
429		tmp |= ADPA_DPMS_D1;
430		break;
431	case FB_BLANK_HSYNC_SUSPEND:
432		tmp |= ADPA_DPMS_D2;
433		break;
434	case FB_BLANK_POWERDOWN:
435		tmp |= ADPA_DPMS_D3;
436		break;
437	}
438	OUTREG(ADPA, tmp);
439
440	return;
441}
442
443
444void
445intelfbhw_setcolreg(struct intelfb_info *dinfo, unsigned regno,
446		    unsigned red, unsigned green, unsigned blue,
447		    unsigned transp)
448{
449#if VERBOSE > 0
450	DBG_MSG("intelfbhw_setcolreg: %d: (%d, %d, %d)\n",
451		regno, red, green, blue);
452#endif
453
454	u32 palette_reg = (dinfo->pipe == PIPE_A) ?
455			  PALETTE_A : PALETTE_B;
456
457	OUTREG(palette_reg + (regno << 2),
458	       (red << PALETTE_8_RED_SHIFT) |
459	       (green << PALETTE_8_GREEN_SHIFT) |
460	       (blue << PALETTE_8_BLUE_SHIFT));
461}
462
463
464int
465intelfbhw_read_hw_state(struct intelfb_info *dinfo, struct intelfb_hwstate *hw,
466			int flag)
467{
468	int i;
469
470#if VERBOSE > 0
471	DBG_MSG("intelfbhw_read_hw_state\n");
472#endif
473
474	if (!hw || !dinfo)
475		return -1;
476
477	/* Read in as much of the HW state as possible. */
478	hw->vga0_divisor = INREG(VGA0_DIVISOR);
479	hw->vga1_divisor = INREG(VGA1_DIVISOR);
480	hw->vga_pd = INREG(VGAPD);
481	hw->dpll_a = INREG(DPLL_A);
482	hw->dpll_b = INREG(DPLL_B);
483	hw->fpa0 = INREG(FPA0);
484	hw->fpa1 = INREG(FPA1);
485	hw->fpb0 = INREG(FPB0);
486	hw->fpb1 = INREG(FPB1);
487
488	if (flag == 1)
489		return flag;
490
491
492	if (flag == 2)
493		return flag;
494
495	hw->htotal_a = INREG(HTOTAL_A);
496	hw->hblank_a = INREG(HBLANK_A);
497	hw->hsync_a = INREG(HSYNC_A);
498	hw->vtotal_a = INREG(VTOTAL_A);
499	hw->vblank_a = INREG(VBLANK_A);
500	hw->vsync_a = INREG(VSYNC_A);
501	hw->src_size_a = INREG(SRC_SIZE_A);
502	hw->bclrpat_a = INREG(BCLRPAT_A);
503	hw->htotal_b = INREG(HTOTAL_B);
504	hw->hblank_b = INREG(HBLANK_B);
505	hw->hsync_b = INREG(HSYNC_B);
506	hw->vtotal_b = INREG(VTOTAL_B);
507	hw->vblank_b = INREG(VBLANK_B);
508	hw->vsync_b = INREG(VSYNC_B);
509	hw->src_size_b = INREG(SRC_SIZE_B);
510	hw->bclrpat_b = INREG(BCLRPAT_B);
511
512	if (flag == 3)
513		return flag;
514
515	hw->adpa = INREG(ADPA);
516	hw->dvoa = INREG(DVOA);
517	hw->dvob = INREG(DVOB);
518	hw->dvoc = INREG(DVOC);
519	hw->dvoa_srcdim = INREG(DVOA_SRCDIM);
520	hw->dvob_srcdim = INREG(DVOB_SRCDIM);
521	hw->dvoc_srcdim = INREG(DVOC_SRCDIM);
522	hw->lvds = INREG(LVDS);
523
524	if (flag == 4)
525		return flag;
526
527	hw->pipe_a_conf = INREG(PIPEACONF);
528	hw->pipe_b_conf = INREG(PIPEBCONF);
529	hw->disp_arb = INREG(DISPARB);
530
531	if (flag == 5)
532		return flag;
533
534	hw->cursor_a_control = INREG(CURSOR_A_CONTROL);
535	hw->cursor_b_control = INREG(CURSOR_B_CONTROL);
536	hw->cursor_a_base = INREG(CURSOR_A_BASEADDR);
537	hw->cursor_b_base = INREG(CURSOR_B_BASEADDR);
538
539	if (flag == 6)
540		return flag;
541
542	for (i = 0; i < 4; i++) {
543		hw->cursor_a_palette[i] = INREG(CURSOR_A_PALETTE0 + (i << 2));
544		hw->cursor_b_palette[i] = INREG(CURSOR_B_PALETTE0 + (i << 2));
545	}
546
547	if (flag == 7)
548		return flag;
549
550	hw->cursor_size = INREG(CURSOR_SIZE);
551
552	if (flag == 8)
553		return flag;
554
555	hw->disp_a_ctrl = INREG(DSPACNTR);
556	hw->disp_b_ctrl = INREG(DSPBCNTR);
557	hw->disp_a_base = INREG(DSPABASE);
558	hw->disp_b_base = INREG(DSPBBASE);
559	hw->disp_a_stride = INREG(DSPASTRIDE);
560	hw->disp_b_stride = INREG(DSPBSTRIDE);
561
562	if (flag == 9)
563		return flag;
564
565	hw->vgacntrl = INREG(VGACNTRL);
566
567	if (flag == 10)
568		return flag;
569
570	hw->add_id = INREG(ADD_ID);
571
572	if (flag == 11)
573		return flag;
574
575	for (i = 0; i < 7; i++) {
576		hw->swf0x[i] = INREG(SWF00 + (i << 2));
577		hw->swf1x[i] = INREG(SWF10 + (i << 2));
578		if (i < 3)
579			hw->swf3x[i] = INREG(SWF30 + (i << 2));
580	}
581
582	for (i = 0; i < 8; i++)
583		hw->fence[i] = INREG(FENCE + (i << 2));
584
585	hw->instpm = INREG(INSTPM);
586	hw->mem_mode = INREG(MEM_MODE);
587	hw->fw_blc_0 = INREG(FW_BLC_0);
588	hw->fw_blc_1 = INREG(FW_BLC_1);
589
590	hw->hwstam = INREG16(HWSTAM);
591	hw->ier = INREG16(IER);
592	hw->iir = INREG16(IIR);
593	hw->imr = INREG16(IMR);
594
595	return 0;
596}
597
598
599static int calc_vclock3(int index, int m, int n, int p)
600{
601	if (p == 0 || n == 0)
602		return 0;
603	return plls[index].ref_clk * m / n / p;
604}
605
606static int calc_vclock(int index, int m1, int m2, int n, int p1, int p2, int lvds)
607{
608	struct pll_min_max *pll = &plls[index];
609	u32 m, vco, p;
610
611	m = (5 * (m1 + 2)) + (m2 + 2);
612	n += 2;
613	vco = pll->ref_clk * m / n;
614
615	if (index == PLLS_I8xx) {
616		p = ((p1 + 2) * (1 << (p2 + 1)));
617	} else {
618		p = ((p1) * (p2 ? 5 : 10));
619	}
620	return vco / p;
621}
622
623#if REGDUMP
624static void
625intelfbhw_get_p1p2(struct intelfb_info *dinfo, int dpll, int *o_p1, int *o_p2)
626{
627	int p1, p2;
628
629	if (IS_I9XX(dinfo)) {
630		if (dpll & DPLL_P1_FORCE_DIV2)
631			p1 = 1;
632		else
633			p1 = (dpll >> DPLL_P1_SHIFT) & 0xff;
634
635		p1 = ffs(p1);
636
637		p2 = (dpll >> DPLL_I9XX_P2_SHIFT) & DPLL_P2_MASK;
638	} else {
639		if (dpll & DPLL_P1_FORCE_DIV2)
640			p1 = 0;
641		else
642			p1 = (dpll >> DPLL_P1_SHIFT) & DPLL_P1_MASK;
643		p2 = (dpll >> DPLL_P2_SHIFT) & DPLL_P2_MASK;
644	}
645
646	*o_p1 = p1;
647	*o_p2 = p2;
648}
649#endif
650
651
652void
653intelfbhw_print_hw_state(struct intelfb_info *dinfo, struct intelfb_hwstate *hw)
654{
655#if REGDUMP
656	int i, m1, m2, n, p1, p2;
657	int index = dinfo->pll_index;
658	DBG_MSG("intelfbhw_print_hw_state\n");
659
660	if (!hw)
661		return;
662	/* Read in as much of the HW state as possible. */
663	printk("hw state dump start\n");
664	printk("	VGA0_DIVISOR:		0x%08x\n", hw->vga0_divisor);
665	printk("	VGA1_DIVISOR:		0x%08x\n", hw->vga1_divisor);
666	printk("	VGAPD: 			0x%08x\n", hw->vga_pd);
667	n = (hw->vga0_divisor >> FP_N_DIVISOR_SHIFT) & FP_DIVISOR_MASK;
668	m1 = (hw->vga0_divisor >> FP_M1_DIVISOR_SHIFT) & FP_DIVISOR_MASK;
669	m2 = (hw->vga0_divisor >> FP_M2_DIVISOR_SHIFT) & FP_DIVISOR_MASK;
670
671	intelfbhw_get_p1p2(dinfo, hw->vga_pd, &p1, &p2);
672
673	printk("	VGA0: (m1, m2, n, p1, p2) = (%d, %d, %d, %d, %d)\n",
674	       m1, m2, n, p1, p2);
675	printk("	VGA0: clock is %d\n",
676	       calc_vclock(index, m1, m2, n, p1, p2, 0));
677
678	n = (hw->vga1_divisor >> FP_N_DIVISOR_SHIFT) & FP_DIVISOR_MASK;
679	m1 = (hw->vga1_divisor >> FP_M1_DIVISOR_SHIFT) & FP_DIVISOR_MASK;
680	m2 = (hw->vga1_divisor >> FP_M2_DIVISOR_SHIFT) & FP_DIVISOR_MASK;
681
682	intelfbhw_get_p1p2(dinfo, hw->vga_pd, &p1, &p2);
683	printk("	VGA1: (m1, m2, n, p1, p2) = (%d, %d, %d, %d, %d)\n",
684	       m1, m2, n, p1, p2);
685	printk("	VGA1: clock is %d\n", calc_vclock(index, m1, m2, n, p1, p2, 0));
686
687	printk("	DPLL_A:			0x%08x\n", hw->dpll_a);
688	printk("	DPLL_B:			0x%08x\n", hw->dpll_b);
689	printk("	FPA0:			0x%08x\n", hw->fpa0);
690	printk("	FPA1:			0x%08x\n", hw->fpa1);
691	printk("	FPB0:			0x%08x\n", hw->fpb0);
692	printk("	FPB1:			0x%08x\n", hw->fpb1);
693
694	n = (hw->fpa0 >> FP_N_DIVISOR_SHIFT) & FP_DIVISOR_MASK;
695	m1 = (hw->fpa0 >> FP_M1_DIVISOR_SHIFT) & FP_DIVISOR_MASK;
696	m2 = (hw->fpa0 >> FP_M2_DIVISOR_SHIFT) & FP_DIVISOR_MASK;
697
698	intelfbhw_get_p1p2(dinfo, hw->dpll_a, &p1, &p2);
699
700	printk("	PLLA0: (m1, m2, n, p1, p2) = (%d, %d, %d, %d, %d)\n",
701	       m1, m2, n, p1, p2);
702	printk("	PLLA0: clock is %d\n", calc_vclock(index, m1, m2, n, p1, p2, 0));
703
704	n = (hw->fpa1 >> FP_N_DIVISOR_SHIFT) & FP_DIVISOR_MASK;
705	m1 = (hw->fpa1 >> FP_M1_DIVISOR_SHIFT) & FP_DIVISOR_MASK;
706	m2 = (hw->fpa1 >> FP_M2_DIVISOR_SHIFT) & FP_DIVISOR_MASK;
707
708	intelfbhw_get_p1p2(dinfo, hw->dpll_a, &p1, &p2);
709
710	printk("	PLLA1: (m1, m2, n, p1, p2) = (%d, %d, %d, %d, %d)\n",
711	       m1, m2, n, p1, p2);
712	printk("	PLLA1: clock is %d\n", calc_vclock(index, m1, m2, n, p1, p2, 0));
713
714
715	printk("	HTOTAL_A:		0x%08x\n", hw->htotal_a);
716	printk("	HBLANK_A:		0x%08x\n", hw->hblank_a);
717	printk("	HSYNC_A:		0x%08x\n", hw->hsync_a);
718	printk("	VTOTAL_A:		0x%08x\n", hw->vtotal_a);
719	printk("	VBLANK_A:		0x%08x\n", hw->vblank_a);
720	printk("	VSYNC_A:		0x%08x\n", hw->vsync_a);
721	printk("	SRC_SIZE_A:		0x%08x\n", hw->src_size_a);
722	printk("	BCLRPAT_A:		0x%08x\n", hw->bclrpat_a);
723	printk("	HTOTAL_B:		0x%08x\n", hw->htotal_b);
724	printk("	HBLANK_B:		0x%08x\n", hw->hblank_b);
725	printk("	HSYNC_B:		0x%08x\n", hw->hsync_b);
726	printk("	VTOTAL_B:		0x%08x\n", hw->vtotal_b);
727	printk("	VBLANK_B:		0x%08x\n", hw->vblank_b);
728	printk("	VSYNC_B:		0x%08x\n", hw->vsync_b);
729	printk("	SRC_SIZE_B:		0x%08x\n", hw->src_size_b);
730	printk("	BCLRPAT_B:		0x%08x\n", hw->bclrpat_b);
731
732	printk("	ADPA:			0x%08x\n", hw->adpa);
733	printk("	DVOA:			0x%08x\n", hw->dvoa);
734	printk("	DVOB:			0x%08x\n", hw->dvob);
735	printk("	DVOC:			0x%08x\n", hw->dvoc);
736	printk("	DVOA_SRCDIM:		0x%08x\n", hw->dvoa_srcdim);
737	printk("	DVOB_SRCDIM:		0x%08x\n", hw->dvob_srcdim);
738	printk("	DVOC_SRCDIM:		0x%08x\n", hw->dvoc_srcdim);
739	printk("	LVDS:			0x%08x\n", hw->lvds);
740
741	printk("	PIPEACONF:		0x%08x\n", hw->pipe_a_conf);
742	printk("	PIPEBCONF:		0x%08x\n", hw->pipe_b_conf);
743	printk("	DISPARB:		0x%08x\n", hw->disp_arb);
744
745	printk("	CURSOR_A_CONTROL:	0x%08x\n", hw->cursor_a_control);
746	printk("	CURSOR_B_CONTROL:	0x%08x\n", hw->cursor_b_control);
747	printk("	CURSOR_A_BASEADDR:	0x%08x\n", hw->cursor_a_base);
748	printk("	CURSOR_B_BASEADDR:	0x%08x\n", hw->cursor_b_base);
749
750	printk("	CURSOR_A_PALETTE:	");
751	for (i = 0; i < 4; i++) {
752		printk("0x%08x", hw->cursor_a_palette[i]);
753		if (i < 3)
754			printk(", ");
755	}
756	printk("\n");
757	printk("	CURSOR_B_PALETTE:	");
758	for (i = 0; i < 4; i++) {
759		printk("0x%08x", hw->cursor_b_palette[i]);
760		if (i < 3)
761			printk(", ");
762	}
763	printk("\n");
764
765	printk("	CURSOR_SIZE:		0x%08x\n", hw->cursor_size);
766
767	printk("	DSPACNTR:		0x%08x\n", hw->disp_a_ctrl);
768	printk("	DSPBCNTR:		0x%08x\n", hw->disp_b_ctrl);
769	printk("	DSPABASE:		0x%08x\n", hw->disp_a_base);
770	printk("	DSPBBASE:		0x%08x\n", hw->disp_b_base);
771	printk("	DSPASTRIDE:		0x%08x\n", hw->disp_a_stride);
772	printk("	DSPBSTRIDE:		0x%08x\n", hw->disp_b_stride);
773
774	printk("	VGACNTRL:		0x%08x\n", hw->vgacntrl);
775	printk("	ADD_ID:			0x%08x\n", hw->add_id);
776
777	for (i = 0; i < 7; i++) {
778		printk("	SWF0%d			0x%08x\n", i,
779			hw->swf0x[i]);
780	}
781	for (i = 0; i < 7; i++) {
782		printk("	SWF1%d			0x%08x\n", i,
783			hw->swf1x[i]);
784	}
785	for (i = 0; i < 3; i++) {
786		printk("	SWF3%d			0x%08x\n", i,
787		       hw->swf3x[i]);
788	}
789	for (i = 0; i < 8; i++)
790		printk("	FENCE%d			0x%08x\n", i,
791		       hw->fence[i]);
792
793	printk("	INSTPM			0x%08x\n", hw->instpm);
794	printk("	MEM_MODE		0x%08x\n", hw->mem_mode);
795	printk("	FW_BLC_0		0x%08x\n", hw->fw_blc_0);
796	printk("	FW_BLC_1		0x%08x\n", hw->fw_blc_1);
797
798	printk("	HWSTAM			0x%04x\n", hw->hwstam);
799	printk("	IER			0x%04x\n", hw->ier);
800	printk("	IIR			0x%04x\n", hw->iir);
801	printk("	IMR			0x%04x\n", hw->imr);
802	printk("hw state dump end\n");
803#endif
804}
805
806
807
808/* Split the M parameter into M1 and M2. */
809static int
810splitm(int index, unsigned int m, unsigned int *retm1, unsigned int *retm2)
811{
812	int m1, m2;
813	int testm;
814	struct pll_min_max *pll = &plls[index];
815
816	/* no point optimising too much - brute force m */
817	for (m1 = pll->min_m1; m1 < pll->max_m1 + 1; m1++) {
818		for (m2 = pll->min_m2; m2 < pll->max_m2 + 1; m2++) {
819			testm = (5 * (m1 + 2)) + (m2 + 2);
820			if (testm == m) {
821				*retm1 = (unsigned int)m1;
822				*retm2 = (unsigned int)m2;
823				return 0;
824			}
825		}
826	}
827	return 1;
828}
829
830/* Split the P parameter into P1 and P2. */
831static int
832splitp(int index, unsigned int p, unsigned int *retp1, unsigned int *retp2)
833{
834	int p1, p2;
835	struct pll_min_max *pll = &plls[index];
836
837	if (index == PLLS_I9xx) {
838		p2 = (p % 10) ? 1 : 0;
839
840		p1 = p / (p2 ? 5 : 10);
841
842		*retp1 = (unsigned int)p1;
843		*retp2 = (unsigned int)p2;
844		return 0;
845	}
846
847	if (p % 4 == 0)
848		p2 = 1;
849	else
850		p2 = 0;
851	p1 = (p / (1 << (p2 + 1))) - 2;
852	if (p % 4 == 0 && p1 < pll->min_p1) {
853		p2 = 0;
854		p1 = (p / (1 << (p2 + 1))) - 2;
855	}
856	if (p1 < pll->min_p1 || p1 > pll->max_p1 ||
857	    (p1 + 2) * (1 << (p2 + 1)) != p) {
858		return 1;
859	} else {
860		*retp1 = (unsigned int)p1;
861		*retp2 = (unsigned int)p2;
862		return 0;
863	}
864}
865
866static int
867calc_pll_params(int index, int clock, u32 *retm1, u32 *retm2, u32 *retn, u32 *retp1,
868		u32 *retp2, u32 *retclock)
869{
870	u32 m1, m2, n, p1, p2, n1, testm;
871	u32 f_vco, p, p_best = 0, m, f_out = 0;
872	u32 err_max, err_target, err_best = 10000000;
873	u32 n_best = 0, m_best = 0, f_best, f_err;
874	u32 p_min, p_max, p_inc, div_max;
875	struct pll_min_max *pll = &plls[index];
876
877	/* Accept 0.5% difference, but aim for 0.1% */
878	err_max = 5 * clock / 1000;
879	err_target = clock / 1000;
880
881	DBG_MSG("Clock is %d\n", clock);
882
883	div_max = pll->max_vco / clock;
884
885	p_inc = (clock <= pll->p_transition_clk) ? pll->p_inc_lo : pll->p_inc_hi;
886	p_min = p_inc;
887	p_max = ROUND_DOWN_TO(div_max, p_inc);
888	if (p_min < pll->min_p)
889		p_min = pll->min_p;
890	if (p_max > pll->max_p)
891		p_max = pll->max_p;
892
893	DBG_MSG("p range is %d-%d (%d)\n", p_min, p_max, p_inc);
894
895	p = p_min;
896	do {
897		if (splitp(index, p, &p1, &p2)) {
898			WRN_MSG("cannot split p = %d\n", p);
899			p += p_inc;
900			continue;
901		}
902		n = pll->min_n;
903		f_vco = clock * p;
904
905		do {
906			m = ROUND_UP_TO(f_vco * n, pll->ref_clk) / pll->ref_clk;
907			if (m < pll->min_m)
908				m = pll->min_m + 1;
909			if (m > pll->max_m)
910				m = pll->max_m - 1;
911			for (testm = m - 1; testm <= m; testm++) {
912				f_out = calc_vclock3(index, m, n, p);
913				if (splitm(index, testm, &m1, &m2)) {
914					WRN_MSG("cannot split m = %d\n", m);
915					n++;
916					continue;
917				}
918				if (clock > f_out)
919					f_err = clock - f_out;
920				else/* slightly bias the error for bigger clocks */
921					f_err = f_out - clock + 1;
922
923				if (f_err < err_best) {
924					m_best = testm;
925					n_best = n;
926					p_best = p;
927					f_best = f_out;
928					err_best = f_err;
929				}
930			}
931			n++;
932		} while ((n <= pll->max_n) && (f_out >= clock));
933		p += p_inc;
934	} while ((p <= p_max));
935
936	if (!m_best) {
937		WRN_MSG("cannot find parameters for clock %d\n", clock);
938		return 1;
939	}
940	m = m_best;
941	n = n_best;
942	p = p_best;
943	splitm(index, m, &m1, &m2);
944	splitp(index, p, &p1, &p2);
945	n1 = n - 2;
946
947	DBG_MSG("m, n, p: %d (%d,%d), %d (%d), %d (%d,%d), "
948		"f: %d (%d), VCO: %d\n",
949		m, m1, m2, n, n1, p, p1, p2,
950		calc_vclock3(index, m, n, p),
951		calc_vclock(index, m1, m2, n1, p1, p2, 0),
952		calc_vclock3(index, m, n, p) * p);
953	*retm1 = m1;
954	*retm2 = m2;
955	*retn = n1;
956	*retp1 = p1;
957	*retp2 = p2;
958	*retclock = calc_vclock(index, m1, m2, n1, p1, p2, 0);
959
960	return 0;
961}
962
963static __inline__ int
964check_overflow(u32 value, u32 limit, const char *description)
965{
966	if (value > limit) {
967		WRN_MSG("%s value %d exceeds limit %d\n",
968			description, value, limit);
969		return 1;
970	}
971	return 0;
972}
973
974/* It is assumed that hw is filled in with the initial state information. */
975int
976intelfbhw_mode_to_hw(struct intelfb_info *dinfo, struct intelfb_hwstate *hw,
977		     struct fb_var_screeninfo *var)
978{
979	int pipe = PIPE_A;
980	u32 *dpll, *fp0, *fp1;
981	u32 m1, m2, n, p1, p2, clock_target, clock;
982	u32 hsync_start, hsync_end, hblank_start, hblank_end, htotal, hactive;
983	u32 vsync_start, vsync_end, vblank_start, vblank_end, vtotal, vactive;
984	u32 vsync_pol, hsync_pol;
985	u32 *vs, *vb, *vt, *hs, *hb, *ht, *ss, *pipe_conf;
986	u32 stride_alignment;
987
988	DBG_MSG("intelfbhw_mode_to_hw\n");
989
990	/* Disable VGA */
991	hw->vgacntrl |= VGA_DISABLE;
992
993	/* Check whether pipe A or pipe B is enabled. */
994	if (hw->pipe_a_conf & PIPECONF_ENABLE)
995		pipe = PIPE_A;
996	else if (hw->pipe_b_conf & PIPECONF_ENABLE)
997		pipe = PIPE_B;
998
999	/* Set which pipe's registers will be set. */
1000	if (pipe == PIPE_B) {
1001		dpll = &hw->dpll_b;
1002		fp0 = &hw->fpb0;
1003		fp1 = &hw->fpb1;
1004		hs = &hw->hsync_b;
1005		hb = &hw->hblank_b;
1006		ht = &hw->htotal_b;
1007		vs = &hw->vsync_b;
1008		vb = &hw->vblank_b;
1009		vt = &hw->vtotal_b;
1010		ss = &hw->src_size_b;
1011		pipe_conf = &hw->pipe_b_conf;
1012	} else {
1013		dpll = &hw->dpll_a;
1014		fp0 = &hw->fpa0;
1015		fp1 = &hw->fpa1;
1016		hs = &hw->hsync_a;
1017		hb = &hw->hblank_a;
1018		ht = &hw->htotal_a;
1019		vs = &hw->vsync_a;
1020		vb = &hw->vblank_a;
1021		vt = &hw->vtotal_a;
1022		ss = &hw->src_size_a;
1023		pipe_conf = &hw->pipe_a_conf;
1024	}
1025
1026	/* Use ADPA register for sync control. */
1027	hw->adpa &= ~ADPA_USE_VGA_HVPOLARITY;
1028
1029	/* sync polarity */
1030	hsync_pol = (var->sync & FB_SYNC_HOR_HIGH_ACT) ?
1031			ADPA_SYNC_ACTIVE_HIGH : ADPA_SYNC_ACTIVE_LOW;
1032	vsync_pol = (var->sync & FB_SYNC_VERT_HIGH_ACT) ?
1033			ADPA_SYNC_ACTIVE_HIGH : ADPA_SYNC_ACTIVE_LOW;
1034	hw->adpa &= ~((ADPA_SYNC_ACTIVE_MASK << ADPA_VSYNC_ACTIVE_SHIFT) |
1035		      (ADPA_SYNC_ACTIVE_MASK << ADPA_HSYNC_ACTIVE_SHIFT));
1036	hw->adpa |= (hsync_pol << ADPA_HSYNC_ACTIVE_SHIFT) |
1037		    (vsync_pol << ADPA_VSYNC_ACTIVE_SHIFT);
1038
1039	/* Connect correct pipe to the analog port DAC */
1040	hw->adpa &= ~(PIPE_MASK << ADPA_PIPE_SELECT_SHIFT);
1041	hw->adpa |= (pipe << ADPA_PIPE_SELECT_SHIFT);
1042
1043	/* Set DPMS state to D0 (on) */
1044	hw->adpa &= ~ADPA_DPMS_CONTROL_MASK;
1045	hw->adpa |= ADPA_DPMS_D0;
1046
1047	hw->adpa |= ADPA_DAC_ENABLE;
1048
1049	*dpll |= (DPLL_VCO_ENABLE | DPLL_VGA_MODE_DISABLE);
1050	*dpll &= ~(DPLL_RATE_SELECT_MASK | DPLL_REFERENCE_SELECT_MASK);
1051	*dpll |= (DPLL_REFERENCE_DEFAULT | DPLL_RATE_SELECT_FP0);
1052
1053	/* Desired clock in kHz */
1054	clock_target = 1000000000 / var->pixclock;
1055
1056	if (calc_pll_params(dinfo->pll_index, clock_target, &m1, &m2,
1057			    &n, &p1, &p2, &clock)) {
1058		WRN_MSG("calc_pll_params failed\n");
1059		return 1;
1060	}
1061
1062	/* Check for overflow. */
1063	if (check_overflow(p1, DPLL_P1_MASK, "PLL P1 parameter"))
1064		return 1;
1065	if (check_overflow(p2, DPLL_P2_MASK, "PLL P2 parameter"))
1066		return 1;
1067	if (check_overflow(m1, FP_DIVISOR_MASK, "PLL M1 parameter"))
1068		return 1;
1069	if (check_overflow(m2, FP_DIVISOR_MASK, "PLL M2 parameter"))
1070		return 1;
1071	if (check_overflow(n, FP_DIVISOR_MASK, "PLL N parameter"))
1072		return 1;
1073
1074	*dpll &= ~DPLL_P1_FORCE_DIV2;
1075	*dpll &= ~((DPLL_P2_MASK << DPLL_P2_SHIFT) |
1076		   (DPLL_P1_MASK << DPLL_P1_SHIFT));
1077
1078	if (IS_I9XX(dinfo)) {
1079		*dpll |= (p2 << DPLL_I9XX_P2_SHIFT);
1080		*dpll |= (1 << (p1 - 1)) << DPLL_P1_SHIFT;
1081	} else {
1082		*dpll |= (p2 << DPLL_P2_SHIFT) | (p1 << DPLL_P1_SHIFT);
1083	}
1084
1085	*fp0 = (n << FP_N_DIVISOR_SHIFT) |
1086	       (m1 << FP_M1_DIVISOR_SHIFT) |
1087	       (m2 << FP_M2_DIVISOR_SHIFT);
1088	*fp1 = *fp0;
1089
1090	hw->dvob &= ~PORT_ENABLE;
1091	hw->dvoc &= ~PORT_ENABLE;
1092
1093	/* Use display plane A. */
1094	hw->disp_a_ctrl |= DISPPLANE_PLANE_ENABLE;
1095	hw->disp_a_ctrl &= ~DISPPLANE_GAMMA_ENABLE;
1096	hw->disp_a_ctrl &= ~DISPPLANE_PIXFORMAT_MASK;
1097	switch (intelfb_var_to_depth(var)) {
1098	case 8:
1099		hw->disp_a_ctrl |= DISPPLANE_8BPP | DISPPLANE_GAMMA_ENABLE;
1100		break;
1101	case 15:
1102		hw->disp_a_ctrl |= DISPPLANE_15_16BPP;
1103		break;
1104	case 16:
1105		hw->disp_a_ctrl |= DISPPLANE_16BPP;
1106		break;
1107	case 24:
1108		hw->disp_a_ctrl |= DISPPLANE_32BPP_NO_ALPHA;
1109		break;
1110	}
1111	hw->disp_a_ctrl &= ~(PIPE_MASK << DISPPLANE_SEL_PIPE_SHIFT);
1112	hw->disp_a_ctrl |= (pipe << DISPPLANE_SEL_PIPE_SHIFT);
1113
1114	/* Set CRTC registers. */
1115	hactive = var->xres;
1116	hsync_start = hactive + var->right_margin;
1117	hsync_end = hsync_start + var->hsync_len;
1118	htotal = hsync_end + var->left_margin;
1119	hblank_start = hactive;
1120	hblank_end = htotal;
1121
1122	DBG_MSG("H: act %d, ss %d, se %d, tot %d bs %d, be %d\n",
1123		hactive, hsync_start, hsync_end, htotal, hblank_start,
1124		hblank_end);
1125
1126	vactive = var->yres;
1127	vsync_start = vactive + var->lower_margin;
1128	vsync_end = vsync_start + var->vsync_len;
1129	vtotal = vsync_end + var->upper_margin;
1130	vblank_start = vactive;
1131	vblank_end = vtotal;
1132	vblank_end = vsync_end + 1;
1133
1134	DBG_MSG("V: act %d, ss %d, se %d, tot %d bs %d, be %d\n",
1135		vactive, vsync_start, vsync_end, vtotal, vblank_start,
1136		vblank_end);
1137
1138	/* Adjust for register values, and check for overflow. */
1139	hactive--;
1140	if (check_overflow(hactive, HACTIVE_MASK, "CRTC hactive"))
1141		return 1;
1142	hsync_start--;
1143	if (check_overflow(hsync_start, HSYNCSTART_MASK, "CRTC hsync_start"))
1144		return 1;
1145	hsync_end--;
1146	if (check_overflow(hsync_end, HSYNCEND_MASK, "CRTC hsync_end"))
1147		return 1;
1148	htotal--;
1149	if (check_overflow(htotal, HTOTAL_MASK, "CRTC htotal"))
1150		return 1;
1151	hblank_start--;
1152	if (check_overflow(hblank_start, HBLANKSTART_MASK, "CRTC hblank_start"))
1153		return 1;
1154	hblank_end--;
1155	if (check_overflow(hblank_end, HBLANKEND_MASK, "CRTC hblank_end"))
1156		return 1;
1157
1158	vactive--;
1159	if (check_overflow(vactive, VACTIVE_MASK, "CRTC vactive"))
1160		return 1;
1161	vsync_start--;
1162	if (check_overflow(vsync_start, VSYNCSTART_MASK, "CRTC vsync_start"))
1163		return 1;
1164	vsync_end--;
1165	if (check_overflow(vsync_end, VSYNCEND_MASK, "CRTC vsync_end"))
1166		return 1;
1167	vtotal--;
1168	if (check_overflow(vtotal, VTOTAL_MASK, "CRTC vtotal"))
1169		return 1;
1170	vblank_start--;
1171	if (check_overflow(vblank_start, VBLANKSTART_MASK, "CRTC vblank_start"))
1172		return 1;
1173	vblank_end--;
1174	if (check_overflow(vblank_end, VBLANKEND_MASK, "CRTC vblank_end"))
1175		return 1;
1176
1177	*ht = (htotal << HTOTAL_SHIFT) | (hactive << HACTIVE_SHIFT);
1178	*hb = (hblank_start << HBLANKSTART_SHIFT) |
1179	      (hblank_end << HSYNCEND_SHIFT);
1180	*hs = (hsync_start << HSYNCSTART_SHIFT) | (hsync_end << HSYNCEND_SHIFT);
1181
1182	*vt = (vtotal << VTOTAL_SHIFT) | (vactive << VACTIVE_SHIFT);
1183	*vb = (vblank_start << VBLANKSTART_SHIFT) |
1184	      (vblank_end << VSYNCEND_SHIFT);
1185	*vs = (vsync_start << VSYNCSTART_SHIFT) | (vsync_end << VSYNCEND_SHIFT);
1186	*ss = (hactive << SRC_SIZE_HORIZ_SHIFT) |
1187	      (vactive << SRC_SIZE_VERT_SHIFT);
1188
1189	hw->disp_a_stride = dinfo->pitch;
1190	DBG_MSG("pitch is %d\n", hw->disp_a_stride);
1191
1192	hw->disp_a_base = hw->disp_a_stride * var->yoffset +
1193			  var->xoffset * var->bits_per_pixel / 8;
1194
1195	hw->disp_a_base += dinfo->fb.offset << 12;
1196
1197	/* Check stride alignment. */
1198	stride_alignment = IS_I9XX(dinfo) ? STRIDE_ALIGNMENT_I9XX :
1199					    STRIDE_ALIGNMENT;
1200	if (hw->disp_a_stride % stride_alignment != 0) {
1201		WRN_MSG("display stride %d has bad alignment %d\n",
1202			hw->disp_a_stride, stride_alignment);
1203		return 1;
1204	}
1205
1206	/* Set the palette to 8-bit mode. */
1207	*pipe_conf &= ~PIPECONF_GAMMA;
1208	return 0;
1209}
1210
1211/* Program a (non-VGA) video mode. */
1212int
1213intelfbhw_program_mode(struct intelfb_info *dinfo,
1214		     const struct intelfb_hwstate *hw, int blank)
1215{
1216	int pipe = PIPE_A;
1217	u32 tmp;
1218	const u32 *dpll, *fp0, *fp1, *pipe_conf;
1219	const u32 *hs, *ht, *hb, *vs, *vt, *vb, *ss;
1220	u32 dpll_reg, fp0_reg, fp1_reg, pipe_conf_reg;
1221	u32 hsync_reg, htotal_reg, hblank_reg;
1222	u32 vsync_reg, vtotal_reg, vblank_reg;
1223	u32 src_size_reg;
1224	u32 count, tmp_val[3];
1225
1226	/* Assume single pipe, display plane A, analog CRT. */
1227
1228#if VERBOSE > 0
1229	DBG_MSG("intelfbhw_program_mode\n");
1230#endif
1231
1232	/* Disable VGA */
1233	tmp = INREG(VGACNTRL);
1234	tmp |= VGA_DISABLE;
1235	OUTREG(VGACNTRL, tmp);
1236
1237	/* Check whether pipe A or pipe B is enabled. */
1238	if (hw->pipe_a_conf & PIPECONF_ENABLE)
1239		pipe = PIPE_A;
1240	else if (hw->pipe_b_conf & PIPECONF_ENABLE)
1241		pipe = PIPE_B;
1242
1243	dinfo->pipe = pipe;
1244
1245	if (pipe == PIPE_B) {
1246		dpll = &hw->dpll_b;
1247		fp0 = &hw->fpb0;
1248		fp1 = &hw->fpb1;
1249		pipe_conf = &hw->pipe_b_conf;
1250		hs = &hw->hsync_b;
1251		hb = &hw->hblank_b;
1252		ht = &hw->htotal_b;
1253		vs = &hw->vsync_b;
1254		vb = &hw->vblank_b;
1255		vt = &hw->vtotal_b;
1256		ss = &hw->src_size_b;
1257		dpll_reg = DPLL_B;
1258		fp0_reg = FPB0;
1259		fp1_reg = FPB1;
1260		pipe_conf_reg = PIPEBCONF;
1261		hsync_reg = HSYNC_B;
1262		htotal_reg = HTOTAL_B;
1263		hblank_reg = HBLANK_B;
1264		vsync_reg = VSYNC_B;
1265		vtotal_reg = VTOTAL_B;
1266		vblank_reg = VBLANK_B;
1267		src_size_reg = SRC_SIZE_B;
1268	} else {
1269		dpll = &hw->dpll_a;
1270		fp0 = &hw->fpa0;
1271		fp1 = &hw->fpa1;
1272		pipe_conf = &hw->pipe_a_conf;
1273		hs = &hw->hsync_a;
1274		hb = &hw->hblank_a;
1275		ht = &hw->htotal_a;
1276		vs = &hw->vsync_a;
1277		vb = &hw->vblank_a;
1278		vt = &hw->vtotal_a;
1279		ss = &hw->src_size_a;
1280		dpll_reg = DPLL_A;
1281		fp0_reg = FPA0;
1282		fp1_reg = FPA1;
1283		pipe_conf_reg = PIPEACONF;
1284		hsync_reg = HSYNC_A;
1285		htotal_reg = HTOTAL_A;
1286		hblank_reg = HBLANK_A;
1287		vsync_reg = VSYNC_A;
1288		vtotal_reg = VTOTAL_A;
1289		vblank_reg = VBLANK_A;
1290		src_size_reg = SRC_SIZE_A;
1291	}
1292
1293	/* turn off pipe */
1294	tmp = INREG(pipe_conf_reg);
1295	tmp &= ~PIPECONF_ENABLE;
1296	OUTREG(pipe_conf_reg, tmp);
1297
1298	count = 0;
1299	do {
1300		tmp_val[count%3] = INREG(0x70000);
1301		if ((tmp_val[0] == tmp_val[1]) && (tmp_val[1]==tmp_val[2]))
1302			break;
1303		count++;
1304		udelay(1);
1305		if (count % 200 == 0) {
1306			tmp = INREG(pipe_conf_reg);
1307			tmp &= ~PIPECONF_ENABLE;
1308			OUTREG(pipe_conf_reg, tmp);
1309		}
1310	} while(count < 2000);
1311
1312	OUTREG(ADPA, INREG(ADPA) & ~ADPA_DAC_ENABLE);
1313
1314	/* Disable planes A and B. */
1315	tmp = INREG(DSPACNTR);
1316	tmp &= ~DISPPLANE_PLANE_ENABLE;
1317	OUTREG(DSPACNTR, tmp);
1318	tmp = INREG(DSPBCNTR);
1319	tmp &= ~DISPPLANE_PLANE_ENABLE;
1320	OUTREG(DSPBCNTR, tmp);
1321
1322	/* Wait for vblank. For now, just wait for a 50Hz cycle (20ms)) */
1323	mdelay(20);
1324
1325	OUTREG(DVOB, INREG(DVOB) & ~PORT_ENABLE);
1326	OUTREG(DVOC, INREG(DVOC) & ~PORT_ENABLE);
1327	OUTREG(ADPA, INREG(ADPA) & ~ADPA_DAC_ENABLE);
1328
1329	/* Disable Sync */
1330	tmp = INREG(ADPA);
1331	tmp &= ~ADPA_DPMS_CONTROL_MASK;
1332	tmp |= ADPA_DPMS_D3;
1333	OUTREG(ADPA, tmp);
1334
1335	/* do some funky magic - xyzzy */
1336	OUTREG(0x61204, 0xabcd0000);
1337
1338	/* turn off PLL */
1339	tmp = INREG(dpll_reg);
1340	dpll_reg &= ~DPLL_VCO_ENABLE;
1341	OUTREG(dpll_reg, tmp);
1342
1343	/* Set PLL parameters */
1344	OUTREG(fp0_reg, *fp0);
1345	OUTREG(fp1_reg, *fp1);
1346
1347	/* Enable PLL */
1348	OUTREG(dpll_reg, *dpll);
1349
1350	/* Set DVOs B/C */
1351	OUTREG(DVOB, hw->dvob);
1352	OUTREG(DVOC, hw->dvoc);
1353
1354	/* undo funky magic */
1355	OUTREG(0x61204, 0x00000000);
1356
1357	/* Set ADPA */
1358	OUTREG(ADPA, INREG(ADPA) | ADPA_DAC_ENABLE);
1359	OUTREG(ADPA, (hw->adpa & ~(ADPA_DPMS_CONTROL_MASK)) | ADPA_DPMS_D3);
1360
1361	/* Set pipe parameters */
1362	OUTREG(hsync_reg, *hs);
1363	OUTREG(hblank_reg, *hb);
1364	OUTREG(htotal_reg, *ht);
1365	OUTREG(vsync_reg, *vs);
1366	OUTREG(vblank_reg, *vb);
1367	OUTREG(vtotal_reg, *vt);
1368	OUTREG(src_size_reg, *ss);
1369
1370	/* Enable pipe */
1371	OUTREG(pipe_conf_reg, *pipe_conf | PIPECONF_ENABLE);
1372
1373	/* Enable sync */
1374	tmp = INREG(ADPA);
1375	tmp &= ~ADPA_DPMS_CONTROL_MASK;
1376	tmp |= ADPA_DPMS_D0;
1377	OUTREG(ADPA, tmp);
1378
1379	/* setup display plane */
1380	if (dinfo->pdev->device == PCI_DEVICE_ID_INTEL_830M) {
1381		/*
1382		 *      i830M errata: the display plane must be enabled
1383		 *      to allow writes to the other bits in the plane
1384		 *      control register.
1385		 */
1386		tmp = INREG(DSPACNTR);
1387		if ((tmp & DISPPLANE_PLANE_ENABLE) != DISPPLANE_PLANE_ENABLE) {
1388			tmp |= DISPPLANE_PLANE_ENABLE;
1389			OUTREG(DSPACNTR, tmp);
1390			OUTREG(DSPACNTR,
1391			       hw->disp_a_ctrl|DISPPLANE_PLANE_ENABLE);
1392			mdelay(1);
1393		}
1394	}
1395
1396	OUTREG(DSPACNTR, hw->disp_a_ctrl & ~DISPPLANE_PLANE_ENABLE);
1397	OUTREG(DSPASTRIDE, hw->disp_a_stride);
1398	OUTREG(DSPABASE, hw->disp_a_base);
1399
1400	/* Enable plane */
1401	if (!blank) {
1402		tmp = INREG(DSPACNTR);
1403		tmp |= DISPPLANE_PLANE_ENABLE;
1404		OUTREG(DSPACNTR, tmp);
1405		OUTREG(DSPABASE, hw->disp_a_base);
1406	}
1407
1408	return 0;
1409}
1410
1411/* forward declarations */
1412static void refresh_ring(struct intelfb_info *dinfo);
1413static void reset_state(struct intelfb_info *dinfo);
1414static void do_flush(struct intelfb_info *dinfo);
1415
1416static  u32 get_ring_space(struct intelfb_info *dinfo)
1417{
1418	u32 ring_space;
1419
1420	if (dinfo->ring_tail >= dinfo->ring_head)
1421		ring_space = dinfo->ring.size -
1422			(dinfo->ring_tail - dinfo->ring_head);
1423	else
1424		ring_space = dinfo->ring_head - dinfo->ring_tail;
1425
1426	if (ring_space > RING_MIN_FREE)
1427		ring_space -= RING_MIN_FREE;
1428	else
1429		ring_space = 0;
1430
1431	return ring_space;
1432}
1433
1434static int
1435wait_ring(struct intelfb_info *dinfo, int n)
1436{
1437	int i = 0;
1438	unsigned long end;
1439	u32 last_head = INREG(PRI_RING_HEAD) & RING_HEAD_MASK;
1440
1441#if VERBOSE > 0
1442	DBG_MSG("wait_ring: %d\n", n);
1443#endif
1444
1445	end = jiffies + (HZ * 3);
1446	while (dinfo->ring_space < n) {
1447		dinfo->ring_head = INREG(PRI_RING_HEAD) & RING_HEAD_MASK;
1448		dinfo->ring_space = get_ring_space(dinfo);
1449
1450		if (dinfo->ring_head != last_head) {
1451			end = jiffies + (HZ * 3);
1452			last_head = dinfo->ring_head;
1453		}
1454		i++;
1455		if (time_before(end, jiffies)) {
1456			if (!i) {
1457				/* Try again */
1458				reset_state(dinfo);
1459				refresh_ring(dinfo);
1460				do_flush(dinfo);
1461				end = jiffies + (HZ * 3);
1462				i = 1;
1463			} else {
1464				WRN_MSG("ring buffer : space: %d wanted %d\n",
1465					dinfo->ring_space, n);
1466				WRN_MSG("lockup - turning off hardware "
1467					"acceleration\n");
1468				dinfo->ring_lockup = 1;
1469				break;
1470			}
1471		}
1472		udelay(1);
1473	}
1474	return i;
1475}
1476
1477static void
1478do_flush(struct intelfb_info *dinfo) {
1479	START_RING(2);
1480	OUT_RING(MI_FLUSH | MI_WRITE_DIRTY_STATE | MI_INVALIDATE_MAP_CACHE);
1481	OUT_RING(MI_NOOP);
1482	ADVANCE_RING();
1483}
1484
1485void
1486intelfbhw_do_sync(struct intelfb_info *dinfo)
1487{
1488#if VERBOSE > 0
1489	DBG_MSG("intelfbhw_do_sync\n");
1490#endif
1491
1492	if (!dinfo->accel)
1493		return;
1494
1495	/*
1496	 * Send a flush, then wait until the ring is empty.  This is what
1497	 * the XFree86 driver does, and actually it doesn't seem a lot worse
1498	 * than the recommended method (both have problems).
1499	 */
1500	do_flush(dinfo);
1501	wait_ring(dinfo, dinfo->ring.size - RING_MIN_FREE);
1502	dinfo->ring_space = dinfo->ring.size - RING_MIN_FREE;
1503}
1504
1505static void
1506refresh_ring(struct intelfb_info *dinfo)
1507{
1508#if VERBOSE > 0
1509	DBG_MSG("refresh_ring\n");
1510#endif
1511
1512	dinfo->ring_head = INREG(PRI_RING_HEAD) & RING_HEAD_MASK;
1513	dinfo->ring_tail = INREG(PRI_RING_TAIL) & RING_TAIL_MASK;
1514	dinfo->ring_space = get_ring_space(dinfo);
1515}
1516
1517static void
1518reset_state(struct intelfb_info *dinfo)
1519{
1520	int i;
1521	u32 tmp;
1522
1523#if VERBOSE > 0
1524	DBG_MSG("reset_state\n");
1525#endif
1526
1527	for (i = 0; i < FENCE_NUM; i++)
1528		OUTREG(FENCE + (i << 2), 0);
1529
1530	/* Flush the ring buffer if it's enabled. */
1531	tmp = INREG(PRI_RING_LENGTH);
1532	if (tmp & RING_ENABLE) {
1533#if VERBOSE > 0
1534		DBG_MSG("reset_state: ring was enabled\n");
1535#endif
1536		refresh_ring(dinfo);
1537		intelfbhw_do_sync(dinfo);
1538		DO_RING_IDLE();
1539	}
1540
1541	OUTREG(PRI_RING_LENGTH, 0);
1542	OUTREG(PRI_RING_HEAD, 0);
1543	OUTREG(PRI_RING_TAIL, 0);
1544	OUTREG(PRI_RING_START, 0);
1545}
1546
1547/* Stop the 2D engine, and turn off the ring buffer. */
1548void
1549intelfbhw_2d_stop(struct intelfb_info *dinfo)
1550{
1551#if VERBOSE > 0
1552	DBG_MSG("intelfbhw_2d_stop: accel: %d, ring_active: %d\n", dinfo->accel,
1553		dinfo->ring_active);
1554#endif
1555
1556	if (!dinfo->accel)
1557		return;
1558
1559	dinfo->ring_active = 0;
1560	reset_state(dinfo);
1561}
1562
1563/*
1564 * Enable the ring buffer, and initialise the 2D engine.
1565 * It is assumed that the graphics engine has been stopped by previously
1566 * calling intelfb_2d_stop().
1567 */
1568void
1569intelfbhw_2d_start(struct intelfb_info *dinfo)
1570{
1571#if VERBOSE > 0
1572	DBG_MSG("intelfbhw_2d_start: accel: %d, ring_active: %d\n",
1573		dinfo->accel, dinfo->ring_active);
1574#endif
1575
1576	if (!dinfo->accel)
1577		return;
1578
1579	/* Initialise the primary ring buffer. */
1580	OUTREG(PRI_RING_LENGTH, 0);
1581	OUTREG(PRI_RING_TAIL, 0);
1582	OUTREG(PRI_RING_HEAD, 0);
1583
1584	OUTREG(PRI_RING_START, dinfo->ring.physical & RING_START_MASK);
1585	OUTREG(PRI_RING_LENGTH,
1586		((dinfo->ring.size - GTT_PAGE_SIZE) & RING_LENGTH_MASK) |
1587		RING_NO_REPORT | RING_ENABLE);
1588	refresh_ring(dinfo);
1589	dinfo->ring_active = 1;
1590}
1591
1592/* 2D fillrect (solid fill or invert) */
1593void
1594intelfbhw_do_fillrect(struct intelfb_info *dinfo, u32 x, u32 y, u32 w, u32 h,
1595		      u32 color, u32 pitch, u32 bpp, u32 rop)
1596{
1597	u32 br00, br09, br13, br14, br16;
1598
1599#if VERBOSE > 0
1600	DBG_MSG("intelfbhw_do_fillrect: (%d,%d) %dx%d, c 0x%06x, p %d bpp %d, "
1601		"rop 0x%02x\n", x, y, w, h, color, pitch, bpp, rop);
1602#endif
1603
1604	br00 = COLOR_BLT_CMD;
1605	br09 = dinfo->fb_start + (y * pitch + x * (bpp / 8));
1606	br13 = (rop << ROP_SHIFT) | pitch;
1607	br14 = (h << HEIGHT_SHIFT) | ((w * (bpp / 8)) << WIDTH_SHIFT);
1608	br16 = color;
1609
1610	switch (bpp) {
1611	case 8:
1612		br13 |= COLOR_DEPTH_8;
1613		break;
1614	case 16:
1615		br13 |= COLOR_DEPTH_16;
1616		break;
1617	case 32:
1618		br13 |= COLOR_DEPTH_32;
1619		br00 |= WRITE_ALPHA | WRITE_RGB;
1620		break;
1621	}
1622
1623	START_RING(6);
1624	OUT_RING(br00);
1625	OUT_RING(br13);
1626	OUT_RING(br14);
1627	OUT_RING(br09);
1628	OUT_RING(br16);
1629	OUT_RING(MI_NOOP);
1630	ADVANCE_RING();
1631
1632#if VERBOSE > 0
1633	DBG_MSG("ring = 0x%08x, 0x%08x (%d)\n", dinfo->ring_head,
1634		dinfo->ring_tail, dinfo->ring_space);
1635#endif
1636}
1637
1638void
1639intelfbhw_do_bitblt(struct intelfb_info *dinfo, u32 curx, u32 cury,
1640		    u32 dstx, u32 dsty, u32 w, u32 h, u32 pitch, u32 bpp)
1641{
1642	u32 br00, br09, br11, br12, br13, br22, br23, br26;
1643
1644#if VERBOSE > 0
1645	DBG_MSG("intelfbhw_do_bitblt: (%d,%d)->(%d,%d) %dx%d, p %d bpp %d\n",
1646		curx, cury, dstx, dsty, w, h, pitch, bpp);
1647#endif
1648
1649	br00 = XY_SRC_COPY_BLT_CMD;
1650	br09 = dinfo->fb_start;
1651	br11 = (pitch << PITCH_SHIFT);
1652	br12 = dinfo->fb_start;
1653	br13 = (SRC_ROP_GXCOPY << ROP_SHIFT) | (pitch << PITCH_SHIFT);
1654	br22 = (dstx << WIDTH_SHIFT) | (dsty << HEIGHT_SHIFT);
1655	br23 = ((dstx + w) << WIDTH_SHIFT) |
1656	       ((dsty + h) << HEIGHT_SHIFT);
1657	br26 = (curx << WIDTH_SHIFT) | (cury << HEIGHT_SHIFT);
1658
1659	switch (bpp) {
1660	case 8:
1661		br13 |= COLOR_DEPTH_8;
1662		break;
1663	case 16:
1664		br13 |= COLOR_DEPTH_16;
1665		break;
1666	case 32:
1667		br13 |= COLOR_DEPTH_32;
1668		br00 |= WRITE_ALPHA | WRITE_RGB;
1669		break;
1670	}
1671
1672	START_RING(8);
1673	OUT_RING(br00);
1674	OUT_RING(br13);
1675	OUT_RING(br22);
1676	OUT_RING(br23);
1677	OUT_RING(br09);
1678	OUT_RING(br26);
1679	OUT_RING(br11);
1680	OUT_RING(br12);
1681	ADVANCE_RING();
1682}
1683
1684int
1685intelfbhw_do_drawglyph(struct intelfb_info *dinfo, u32 fg, u32 bg, u32 w,
1686		       u32 h, const u8* cdat, u32 x, u32 y, u32 pitch, u32 bpp)
1687{
1688	int nbytes, ndwords, pad, tmp;
1689	u32 br00, br09, br13, br18, br19, br22, br23;
1690	int dat, ix, iy, iw;
1691	int i, j;
1692
1693#if VERBOSE > 0
1694	DBG_MSG("intelfbhw_do_drawglyph: (%d,%d) %dx%d\n", x, y, w, h);
1695#endif
1696
1697	/* size in bytes of a padded scanline */
1698	nbytes = ROUND_UP_TO(w, 16) / 8;
1699
1700	/* Total bytes of padded scanline data to write out. */
1701	nbytes = nbytes * h;
1702
1703	/*
1704	 * Check if the glyph data exceeds the immediate mode limit.
1705	 * It would take a large font (1K pixels) to hit this limit.
1706	 */
1707	if (nbytes > MAX_MONO_IMM_SIZE)
1708		return 0;
1709
1710	/* Src data is packaged a dword (32-bit) at a time. */
1711	ndwords = ROUND_UP_TO(nbytes, 4) / 4;
1712
1713	/*
1714	 * Ring has to be padded to a quad word. But because the command starts
1715	   with 7 bytes, pad only if there is an even number of ndwords
1716	 */
1717	pad = !(ndwords % 2);
1718
1719	tmp = (XY_MONO_SRC_IMM_BLT_CMD & DW_LENGTH_MASK) + ndwords;
1720	br00 = (XY_MONO_SRC_IMM_BLT_CMD & ~DW_LENGTH_MASK) | tmp;
1721	br09 = dinfo->fb_start;
1722	br13 = (SRC_ROP_GXCOPY << ROP_SHIFT) | (pitch << PITCH_SHIFT);
1723	br18 = bg;
1724	br19 = fg;
1725	br22 = (x << WIDTH_SHIFT) | (y << HEIGHT_SHIFT);
1726	br23 = ((x + w) << WIDTH_SHIFT) | ((y + h) << HEIGHT_SHIFT);
1727
1728	switch (bpp) {
1729	case 8:
1730		br13 |= COLOR_DEPTH_8;
1731		break;
1732	case 16:
1733		br13 |= COLOR_DEPTH_16;
1734		break;
1735	case 32:
1736		br13 |= COLOR_DEPTH_32;
1737		br00 |= WRITE_ALPHA | WRITE_RGB;
1738		break;
1739	}
1740
1741	START_RING(8 + ndwords);
1742	OUT_RING(br00);
1743	OUT_RING(br13);
1744	OUT_RING(br22);
1745	OUT_RING(br23);
1746	OUT_RING(br09);
1747	OUT_RING(br18);
1748	OUT_RING(br19);
1749	ix = iy = 0;
1750	iw = ROUND_UP_TO(w, 8) / 8;
1751	while (ndwords--) {
1752		dat = 0;
1753		for (j = 0; j < 2; ++j) {
1754			for (i = 0; i < 2; ++i) {
1755				if (ix != iw || i == 0)
1756					dat |= cdat[iy*iw + ix++] << (i+j*2)*8;
1757			}
1758			if (ix == iw && iy != (h-1)) {
1759				ix = 0;
1760				++iy;
1761			}
1762		}
1763		OUT_RING(dat);
1764	}
1765	if (pad)
1766		OUT_RING(MI_NOOP);
1767	ADVANCE_RING();
1768
1769	return 1;
1770}
1771
1772/* HW cursor functions. */
1773void
1774intelfbhw_cursor_init(struct intelfb_info *dinfo)
1775{
1776	u32 tmp;
1777
1778#if VERBOSE > 0
1779	DBG_MSG("intelfbhw_cursor_init\n");
1780#endif
1781
1782	if (dinfo->mobile || IS_I9XX(dinfo)) {
1783		if (!dinfo->cursor.physical)
1784			return;
1785		tmp = INREG(CURSOR_A_CONTROL);
1786		tmp &= ~(CURSOR_MODE_MASK | CURSOR_MOBILE_GAMMA_ENABLE |
1787			 CURSOR_MEM_TYPE_LOCAL |
1788			 (1 << CURSOR_PIPE_SELECT_SHIFT));
1789		tmp |= CURSOR_MODE_DISABLE;
1790		OUTREG(CURSOR_A_CONTROL, tmp);
1791		OUTREG(CURSOR_A_BASEADDR, dinfo->cursor.physical);
1792	} else {
1793		tmp = INREG(CURSOR_CONTROL);
1794		tmp &= ~(CURSOR_FORMAT_MASK | CURSOR_GAMMA_ENABLE |
1795			 CURSOR_ENABLE | CURSOR_STRIDE_MASK);
1796		tmp = CURSOR_FORMAT_3C;
1797		OUTREG(CURSOR_CONTROL, tmp);
1798		OUTREG(CURSOR_A_BASEADDR, dinfo->cursor.offset << 12);
1799		tmp = (64 << CURSOR_SIZE_H_SHIFT) |
1800		      (64 << CURSOR_SIZE_V_SHIFT);
1801		OUTREG(CURSOR_SIZE, tmp);
1802	}
1803}
1804
1805void
1806intelfbhw_cursor_hide(struct intelfb_info *dinfo)
1807{
1808	u32 tmp;
1809
1810#if VERBOSE > 0
1811	DBG_MSG("intelfbhw_cursor_hide\n");
1812#endif
1813
1814	dinfo->cursor_on = 0;
1815	if (dinfo->mobile || IS_I9XX(dinfo)) {
1816		if (!dinfo->cursor.physical)
1817			return;
1818		tmp = INREG(CURSOR_A_CONTROL);
1819		tmp &= ~CURSOR_MODE_MASK;
1820		tmp |= CURSOR_MODE_DISABLE;
1821		OUTREG(CURSOR_A_CONTROL, tmp);
1822		/* Flush changes */
1823		OUTREG(CURSOR_A_BASEADDR, dinfo->cursor.physical);
1824	} else {
1825		tmp = INREG(CURSOR_CONTROL);
1826		tmp &= ~CURSOR_ENABLE;
1827		OUTREG(CURSOR_CONTROL, tmp);
1828	}
1829}
1830
1831void
1832intelfbhw_cursor_show(struct intelfb_info *dinfo)
1833{
1834	u32 tmp;
1835
1836#if VERBOSE > 0
1837	DBG_MSG("intelfbhw_cursor_show\n");
1838#endif
1839
1840	dinfo->cursor_on = 1;
1841
1842	if (dinfo->cursor_blanked)
1843		return;
1844
1845	if (dinfo->mobile || IS_I9XX(dinfo)) {
1846		if (!dinfo->cursor.physical)
1847			return;
1848		tmp = INREG(CURSOR_A_CONTROL);
1849		tmp &= ~CURSOR_MODE_MASK;
1850		tmp |= CURSOR_MODE_64_4C_AX;
1851		OUTREG(CURSOR_A_CONTROL, tmp);
1852		/* Flush changes */
1853		OUTREG(CURSOR_A_BASEADDR, dinfo->cursor.physical);
1854	} else {
1855		tmp = INREG(CURSOR_CONTROL);
1856		tmp |= CURSOR_ENABLE;
1857		OUTREG(CURSOR_CONTROL, tmp);
1858	}
1859}
1860
1861void
1862intelfbhw_cursor_setpos(struct intelfb_info *dinfo, int x, int y)
1863{
1864	u32 tmp;
1865
1866#if VERBOSE > 0
1867	DBG_MSG("intelfbhw_cursor_setpos: (%d, %d)\n", x, y);
1868#endif
1869
1870	/*
1871	 * Sets the position. The coordinates are assumed to already
1872	 * have any offset adjusted. Assume that the cursor is never
1873	 * completely off-screen, and that x, y are always >= 0.
1874	 */
1875
1876	tmp = ((x & CURSOR_POS_MASK) << CURSOR_X_SHIFT) |
1877	      ((y & CURSOR_POS_MASK) << CURSOR_Y_SHIFT);
1878	OUTREG(CURSOR_A_POSITION, tmp);
1879
1880	if (IS_I9XX(dinfo)) {
1881		OUTREG(CURSOR_A_BASEADDR, dinfo->cursor.physical);
1882	}
1883}
1884
1885void
1886intelfbhw_cursor_setcolor(struct intelfb_info *dinfo, u32 bg, u32 fg)
1887{
1888#if VERBOSE > 0
1889	DBG_MSG("intelfbhw_cursor_setcolor\n");
1890#endif
1891
1892	OUTREG(CURSOR_A_PALETTE0, bg & CURSOR_PALETTE_MASK);
1893	OUTREG(CURSOR_A_PALETTE1, fg & CURSOR_PALETTE_MASK);
1894	OUTREG(CURSOR_A_PALETTE2, fg & CURSOR_PALETTE_MASK);
1895	OUTREG(CURSOR_A_PALETTE3, bg & CURSOR_PALETTE_MASK);
1896}
1897
1898void
1899intelfbhw_cursor_load(struct intelfb_info *dinfo, int width, int height,
1900		      u8 *data)
1901{
1902	u8 __iomem *addr = (u8 __iomem *)dinfo->cursor.virtual;
1903	int i, j, w = width / 8;
1904	int mod = width % 8, t_mask, d_mask;
1905
1906#if VERBOSE > 0
1907	DBG_MSG("intelfbhw_cursor_load\n");
1908#endif
1909
1910	if (!dinfo->cursor.virtual)
1911		return;
1912
1913	t_mask = 0xff >> mod;
1914	d_mask = ~(0xff >> mod);
1915	for (i = height; i--; ) {
1916		for (j = 0; j < w; j++) {
1917			writeb(0x00, addr + j);
1918			writeb(*(data++), addr + j+8);
1919		}
1920		if (mod) {
1921			writeb(t_mask, addr + j);
1922			writeb(*(data++) & d_mask, addr + j+8);
1923		}
1924		addr += 16;
1925	}
1926}
1927
1928void
1929intelfbhw_cursor_reset(struct intelfb_info *dinfo) {
1930	u8 __iomem *addr = (u8 __iomem *)dinfo->cursor.virtual;
1931	int i, j;
1932
1933#if VERBOSE > 0
1934	DBG_MSG("intelfbhw_cursor_reset\n");
1935#endif
1936
1937	if (!dinfo->cursor.virtual)
1938		return;
1939
1940	for (i = 64; i--; ) {
1941		for (j = 0; j < 8; j++) {
1942			writeb(0xff, addr + j+0);
1943			writeb(0x00, addr + j+8);
1944		}
1945		addr += 16;
1946	}
1947}
1948
1949static irqreturn_t
1950intelfbhw_irq(int irq, void *dev_id) {
1951	int handled = 0;
1952	u16 tmp;
1953	struct intelfb_info *dinfo = (struct intelfb_info *)dev_id;
1954
1955	spin_lock(&dinfo->int_lock);
1956
1957	tmp = INREG16(IIR);
1958	tmp &= VSYNC_PIPE_A_INTERRUPT;
1959
1960	if (tmp == 0) {
1961		spin_unlock(&dinfo->int_lock);
1962		return IRQ_RETVAL(handled);
1963	}
1964
1965	OUTREG16(IIR, tmp);
1966
1967	if (tmp & VSYNC_PIPE_A_INTERRUPT) {
1968		dinfo->vsync.count++;
1969		if (dinfo->vsync.pan_display) {
1970			dinfo->vsync.pan_display = 0;
1971			OUTREG(DSPABASE, dinfo->vsync.pan_offset);
1972		}
1973		wake_up_interruptible(&dinfo->vsync.wait);
1974		handled = 1;
1975	}
1976
1977	spin_unlock(&dinfo->int_lock);
1978
1979	return IRQ_RETVAL(handled);
1980}
1981
1982int
1983intelfbhw_enable_irq(struct intelfb_info *dinfo, int reenable) {
1984
1985	if (!test_and_set_bit(0, &dinfo->irq_flags)) {
1986		if (request_irq(dinfo->pdev->irq, intelfbhw_irq, IRQF_SHARED,
1987		     "intelfb", dinfo)) {
1988			clear_bit(0, &dinfo->irq_flags);
1989			return -EINVAL;
1990		}
1991
1992		spin_lock_irq(&dinfo->int_lock);
1993		OUTREG16(HWSTAM, 0xfffe);
1994		OUTREG16(IMR, 0x0);
1995		OUTREG16(IER, VSYNC_PIPE_A_INTERRUPT);
1996		spin_unlock_irq(&dinfo->int_lock);
1997	} else if (reenable) {
1998		u16 ier;
1999
2000		spin_lock_irq(&dinfo->int_lock);
2001		ier = INREG16(IER);
2002		if ((ier & VSYNC_PIPE_A_INTERRUPT)) {
2003			DBG_MSG("someone disabled the IRQ [%08X]\n", ier);
2004			OUTREG(IER, VSYNC_PIPE_A_INTERRUPT);
2005		}
2006		spin_unlock_irq(&dinfo->int_lock);
2007	}
2008	return 0;
2009}
2010
2011void
2012intelfbhw_disable_irq(struct intelfb_info *dinfo) {
2013	u16 tmp;
2014
2015	if (test_and_clear_bit(0, &dinfo->irq_flags)) {
2016		if (dinfo->vsync.pan_display) {
2017			dinfo->vsync.pan_display = 0;
2018			OUTREG(DSPABASE, dinfo->vsync.pan_offset);
2019		}
2020		spin_lock_irq(&dinfo->int_lock);
2021		OUTREG16(HWSTAM, 0xffff);
2022		OUTREG16(IMR, 0xffff);
2023		OUTREG16(IER, 0x0);
2024
2025		tmp = INREG16(IIR);
2026		OUTREG16(IIR, tmp);
2027		spin_unlock_irq(&dinfo->int_lock);
2028
2029		free_irq(dinfo->pdev->irq, dinfo);
2030	}
2031}
2032
2033int
2034intelfbhw_wait_for_vsync(struct intelfb_info *dinfo, u32 pipe) {
2035	struct intelfb_vsync *vsync;
2036	unsigned int count;
2037	int ret;
2038
2039	switch (pipe) {
2040		case 0:
2041			vsync = &dinfo->vsync;
2042			break;
2043		default:
2044			return -ENODEV;
2045	}
2046
2047	ret = intelfbhw_enable_irq(dinfo, 0);
2048	if (ret) {
2049		return ret;
2050	}
2051
2052	count = vsync->count;
2053	ret = wait_event_interruptible_timeout(vsync->wait, count != vsync->count, HZ/10);
2054	if (ret < 0) {
2055		return ret;
2056	}
2057	if (ret == 0) {
2058		intelfbhw_enable_irq(dinfo, 1);
2059		DBG_MSG("wait_for_vsync timed out!\n");
2060		return -ETIMEDOUT;
2061	}
2062
2063	return 0;
2064}
2065