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