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