1 /* 2 * Copyright 2006-2007, Haiku, Inc. All Rights Reserved. 3 * Distributed under the terms of the MIT License. 4 * 5 * Support for i915 chipset and up based on the X driver, 6 * Copyright 2006-2007 Intel Corporation. 7 * 8 * Authors: 9 * Axel Dörfler, axeld@pinc-software.de 10 */ 11 12 13 #include "accelerant_protos.h" 14 #include "accelerant.h" 15 #include "utility.h" 16 17 #include <stdio.h> 18 #include <string.h> 19 #include <math.h> 20 21 #include <create_display_modes.h> 22 #include <ddc.h> 23 #include <edid.h> 24 25 26 #define TRACE_MODE 27 #ifdef TRACE_MODE 28 extern "C" void _sPrintf(const char *format, ...); 29 # define TRACE(x) _sPrintf x 30 #else 31 # define TRACE(x) ; 32 #endif 33 34 35 struct display_registers { 36 uint32 pll; 37 uint32 divisors; 38 uint32 control; 39 uint32 pipe_config; 40 uint32 horiz_total; 41 uint32 horiz_blank; 42 uint32 horiz_sync; 43 uint32 vert_total; 44 uint32 vert_blank; 45 uint32 vert_sync; 46 uint32 size; 47 uint32 stride; 48 uint32 position; 49 uint32 pipe_source; 50 }; 51 52 struct pll_divisors { 53 uint32 post; 54 uint32 post1; 55 uint32 post2; 56 bool post2_high; 57 uint32 n; 58 uint32 m; 59 uint32 m1; 60 uint32 m2; 61 }; 62 63 struct pll_limits { 64 pll_divisors min; 65 pll_divisors max; 66 uint32 min_post2_frequency; 67 uint32 min_vco; 68 uint32 max_vco; 69 }; 70 71 72 static status_t 73 get_i2c_signals(void* cookie, int* _clock, int* _data) 74 { 75 uint32 ioRegister = (uint32)cookie; 76 uint32 value = read32(ioRegister); 77 78 *_clock = (value & I2C_CLOCK_VALUE_IN) != 0; 79 *_data = (value & I2C_DATA_VALUE_IN) != 0; 80 81 return B_OK; 82 } 83 84 85 static status_t 86 set_i2c_signals(void* cookie, int clock, int data) 87 { 88 uint32 ioRegister = (uint32)cookie; 89 uint32 value; 90 91 if (gInfo->shared_info->device_type == (INTEL_TYPE_8xx | INTEL_TYPE_83x)) { 92 // on these chips, the reserved values are fixed 93 value = 0; 94 } else { 95 // on all others, we have to preserve them manually 96 value = read32(ioRegister) & I2C_RESERVED; 97 } 98 99 if (data != 0) 100 value |= I2C_DATA_DIRECTION_MASK; 101 else 102 value |= I2C_DATA_DIRECTION_MASK | I2C_DATA_DIRECTION_OUT | I2C_DATA_VALUE_MASK; 103 104 if (clock != 0) 105 value |= I2C_CLOCK_DIRECTION_MASK; 106 else 107 value |= I2C_CLOCK_DIRECTION_MASK | I2C_CLOCK_DIRECTION_OUT | I2C_CLOCK_VALUE_MASK; 108 109 write32(ioRegister, value); 110 read32(ioRegister); 111 // make sure the PCI bus has flushed the write 112 113 return B_OK; 114 } 115 116 117 void 118 set_frame_buffer_base() 119 { 120 intel_shared_info &sharedInfo = *gInfo->shared_info; 121 display_mode &mode = sharedInfo.current_mode; 122 uint32 baseRegister; 123 uint32 surfaceRegister; 124 125 if (gInfo->head_mode & HEAD_MODE_A_ANALOG) { 126 baseRegister = INTEL_DISPLAY_A_BASE; 127 surfaceRegister = INTEL_DISPLAY_A_SURFACE; 128 } else { 129 baseRegister = INTEL_DISPLAY_B_BASE; 130 surfaceRegister = INTEL_DISPLAY_B_SURFACE; 131 } 132 133 if (sharedInfo.device_type == (INTEL_TYPE_9xx | INTEL_TYPE_965)) { 134 write32(baseRegister, mode.v_display_start * sharedInfo.bytes_per_row 135 + mode.h_display_start * (sharedInfo.bits_per_pixel + 7) / 8); 136 read32(baseRegister); 137 write32(surfaceRegister, sharedInfo.frame_buffer_offset); 138 read32(surfaceRegister); 139 } else { 140 write32(baseRegister, sharedInfo.frame_buffer_offset 141 + mode.v_display_start * sharedInfo.bytes_per_row 142 + mode.h_display_start * (sharedInfo.bits_per_pixel + 7) / 8); 143 read32(baseRegister); 144 } 145 } 146 147 148 /*! Creates the initial mode list of the primary accelerant. 149 It's called from intel_init_accelerant(). 150 */ 151 status_t 152 create_mode_list(void) 153 { 154 i2c_bus bus; 155 bus.cookie = (void*)INTEL_I2C_IO_A; 156 bus.set_signals = &set_i2c_signals; 157 bus.get_signals = &get_i2c_signals; 158 ddc2_init_timing(&bus); 159 160 if (ddc2_read_edid1(&bus, &gInfo->edid_info, NULL, NULL) == B_OK) { 161 edid_dump(&gInfo->edid_info); 162 gInfo->has_edid = true; 163 } else { 164 TRACE(("intel_extreme: getting EDID failed!\n")); 165 } 166 167 display_mode *list; 168 uint32 count = 0; 169 gInfo->mode_list_area = create_display_modes("intel extreme modes", 170 gInfo->has_edid ? &gInfo->edid_info : NULL, NULL, 0, NULL, 0, NULL, 171 &list, &count); 172 if (gInfo->mode_list_area < B_OK) 173 return gInfo->mode_list_area; 174 175 gInfo->mode_list = list; 176 gInfo->shared_info->mode_list_area = gInfo->mode_list_area; 177 gInfo->shared_info->mode_count = count; 178 179 return B_OK; 180 } 181 182 183 void 184 wait_for_vblank(void) 185 { 186 acquire_sem_etc(gInfo->shared_info->vblank_sem, 1, B_RELATIVE_TIMEOUT, 25000); 187 // With the output turned off via DPMS, we might not get any interrupts anymore 188 // that's why we don't wait forever for it. 189 } 190 191 192 static void 193 get_pll_limits(pll_limits &limits) 194 { 195 // Note, the limits are taken from the X driver; they have not yet been tested 196 197 if ((gInfo->shared_info->device_type & INTEL_TYPE_9xx) != 0) { 198 // TODO: support LVDS output limits as well 199 static const pll_limits kLimits = { 200 // p, p1, p2, high, n, m, m1, m2 201 { 5, 1, 10, false, 5, 70, 12, 7}, // min 202 { 80, 8, 5, true, 10, 120, 22, 11}, // max 203 200000, 1400000, 2800000 204 }; 205 limits = kLimits; 206 } else { 207 // TODO: support LVDS output limits as well 208 static const pll_limits kLimits = { 209 // p, p1, p2, high, n, m, m1, m2 210 { 4, 2, 4, false, 5, 96, 20, 8}, 211 {128, 33, 2, true, 18, 140, 28, 18}, 212 165000, 930000, 1400000 213 }; 214 limits = kLimits; 215 } 216 217 TRACE(("PLL limits, min: p %lu (p1 %lu, p2 %lu), n %lu, m %lu (m1 %lu, m2 %lu)\n", 218 limits.min.post, limits.min.post1, limits.min.post2, limits.min.n, 219 limits.min.m, limits.min.m1, limits.min.m2)); 220 TRACE(("PLL limits, max: p %lu (p1 %lu, p2 %lu), n %lu, m %lu (m1 %lu, m2 %lu)\n", 221 limits.max.post, limits.max.post1, limits.max.post2, limits.max.n, 222 limits.max.m, limits.max.m1, limits.max.m2)); 223 } 224 225 226 static bool 227 valid_pll_divisors(const pll_divisors& divisors, const pll_limits& limits) 228 { 229 pll_info &info = gInfo->shared_info->pll_info; 230 uint32 vco = info.reference_frequency * divisors.m / divisors.n; 231 uint32 frequency = vco / divisors.post; 232 233 if (divisors.post < limits.min.post || divisors.post > limits.max.post 234 || divisors.m < limits.min.m || divisors.m > limits.max.m 235 || vco < limits.min_vco || vco > limits.max_vco 236 || frequency < info.min_frequency || frequency > info.max_frequency) 237 return false; 238 239 return true; 240 } 241 242 243 static void 244 compute_pll_divisors(const display_mode ¤t, pll_divisors& divisors) 245 { 246 float requestedPixelClock = current.timing.pixel_clock / 1000.0f; 247 float referenceClock = gInfo->shared_info->pll_info.reference_frequency / 1000.0f; 248 pll_limits limits; 249 get_pll_limits(limits); 250 251 TRACE(("required MHz: %g\n", requestedPixelClock)); 252 253 if (current.timing.pixel_clock < limits.min_post2_frequency) { 254 // slow DAC timing 255 divisors.post2 = limits.min.post2; 256 divisors.post2_high = limits.min.post2_high; 257 } else { 258 // fast DAC timing 259 divisors.post2 = limits.max.post2; 260 divisors.post2_high = limits.max.post2_high; 261 } 262 263 float best = requestedPixelClock; 264 pll_divisors bestDivisors; 265 266 for (divisors.m1 = limits.min.m1; divisors.m1 <= limits.max.m1; divisors.m1++) { 267 for (divisors.m2 = limits.min.m2; divisors.m2 < divisors.m1 268 && divisors.m2 <= limits.max.m2; divisors.m2++) { 269 for (divisors.n = limits.min.n; divisors.n <= limits.max.n; 270 divisors.n++) { 271 for (divisors.post1 = limits.min.post1; 272 divisors.post1 <= limits.max.post1; divisors.post1++) { 273 divisors.m = 5 * divisors.m1 + divisors.m2; 274 divisors.post = divisors.post1 * divisors.post2; 275 276 if (!valid_pll_divisors(divisors, limits)) 277 continue; 278 279 float error = fabs(requestedPixelClock 280 - ((referenceClock * divisors.m) / divisors.n) / divisors.post); 281 if (error < best) { 282 best = error; 283 bestDivisors = divisors; 284 285 if (error == 0) 286 break; 287 } 288 } 289 } 290 } 291 } 292 293 divisors = bestDivisors; 294 295 TRACE(("found: %g MHz, p = %lu (p1 = %lu, p2 = %lu), n = %lu, m = %lu (m1 = %lu, m2 = %lu)\n", 296 ((referenceClock * divisors.m) / divisors.n) / divisors.post, 297 divisors.post, divisors.post1, divisors.post2, divisors.n, 298 divisors.m, divisors.m1, divisors.m2)); 299 } 300 301 302 static void 303 get_color_space_format(const display_mode &mode, uint32 &colorMode, 304 uint32 &bytesPerRow, uint32 &bitsPerPixel) 305 { 306 uint32 bytesPerPixel; 307 308 switch (mode.space) { 309 case B_RGB32_LITTLE: 310 colorMode = DISPLAY_CONTROL_RGB32; 311 bytesPerPixel = 4; 312 bitsPerPixel = 32; 313 break; 314 case B_RGB16_LITTLE: 315 colorMode = DISPLAY_CONTROL_RGB16; 316 bytesPerPixel = 2; 317 bitsPerPixel = 16; 318 break; 319 case B_RGB15_LITTLE: 320 colorMode = DISPLAY_CONTROL_RGB15; 321 bytesPerPixel = 2; 322 bitsPerPixel = 15; 323 break; 324 case B_CMAP8: 325 default: 326 colorMode = DISPLAY_CONTROL_CMAP8; 327 bytesPerPixel = 1; 328 bitsPerPixel = 8; 329 break; 330 } 331 332 bytesPerRow = mode.virtual_width * bytesPerPixel; 333 } 334 335 336 // #pragma mark - 337 338 339 uint32 340 intel_accelerant_mode_count(void) 341 { 342 TRACE(("intel_accelerant_mode_count()\n")); 343 return gInfo->shared_info->mode_count; 344 } 345 346 347 status_t 348 intel_get_mode_list(display_mode *modeList) 349 { 350 TRACE(("intel_get_mode_info()\n")); 351 memcpy(modeList, gInfo->mode_list, 352 gInfo->shared_info->mode_count * sizeof(display_mode)); 353 return B_OK; 354 } 355 356 357 status_t 358 intel_propose_display_mode(display_mode *target, const display_mode *low, 359 const display_mode *high) 360 { 361 TRACE(("intel_propose_display_mode()\n")); 362 363 // just search for the specified mode in the list 364 365 for (uint32 i = 0; i < gInfo->shared_info->mode_count; i++) { 366 display_mode *mode = &gInfo->mode_list[i]; 367 368 // TODO: improve this, ie. adapt pixel clock to allowed values!!! 369 370 if (target->virtual_width != mode->virtual_width 371 || target->virtual_height != mode->virtual_height 372 || target->space != mode->space) 373 continue; 374 375 *target = *mode; 376 return B_OK; 377 } 378 return B_BAD_VALUE; 379 } 380 381 382 status_t 383 intel_set_display_mode(display_mode *mode) 384 { 385 TRACE(("intel_set_display_mode()\n")); 386 387 display_mode target = *mode; 388 389 if (mode == NULL || intel_propose_display_mode(&target, mode, mode)) 390 return B_BAD_VALUE; 391 392 uint32 colorMode, bytesPerRow, bitsPerPixel; 393 get_color_space_format(target, colorMode, bytesPerRow, bitsPerPixel); 394 395 #if 0 396 static bool first = true; 397 if (first) { 398 int fd = open("/boot/home/ie_.regs", O_CREAT | O_WRONLY, 0644); 399 if (fd >= 0) { 400 for (int32 i = 0; i < 0x80000; i += 16) { 401 char line[512]; 402 int length = sprintf(line, "%05lx: %08lx %08lx %08lx %08lx\n", 403 i, read32(i), read32(i + 4), read32(i + 8), read32(i + 12)); 404 write(fd, line, length); 405 } 406 close(fd); 407 sync(); 408 } 409 first = false; 410 } 411 #endif 412 413 intel_shared_info &sharedInfo = *gInfo->shared_info; 414 Autolock locker(sharedInfo.accelerant_lock); 415 416 set_display_power_mode(B_DPMS_OFF); 417 418 // free old and allocate new frame buffer in graphics memory 419 420 intel_free_memory(gInfo->frame_buffer_handle); 421 422 uint32 offset; 423 if (intel_allocate_memory(bytesPerRow * target.virtual_height, 424 gInfo->frame_buffer_handle, offset) < B_OK) { 425 // oh, how did that happen? Unfortunately, there is no really good way back 426 if (intel_allocate_memory(sharedInfo.current_mode.virtual_height 427 * sharedInfo.bytes_per_row, gInfo->frame_buffer_handle, 428 offset) == B_OK) { 429 sharedInfo.frame_buffer_offset = offset; 430 set_frame_buffer_base(); 431 } 432 433 return B_NO_MEMORY; 434 } 435 436 sharedInfo.frame_buffer_offset = offset; 437 438 // make sure VGA display is disabled 439 write32(INTEL_VGA_DISPLAY_CONTROL, VGA_DISPLAY_DISABLED); 440 read32(INTEL_VGA_DISPLAY_CONTROL); 441 442 if (gInfo->shared_info->device_type != (INTEL_TYPE_8xx | INTEL_TYPE_85x)) { 443 } 444 445 if (gInfo->head_mode & HEAD_MODE_A_ANALOG) { 446 pll_divisors divisors; 447 compute_pll_divisors(target, divisors); 448 449 write32(INTEL_DISPLAY_A_PLL_DIVISOR_0, 450 (((divisors.n - 2) << DISPLAY_PLL_N_DIVISOR_SHIFT) & DISPLAY_PLL_N_DIVISOR_MASK) 451 | (((divisors.m1 - 2) << DISPLAY_PLL_M1_DIVISOR_SHIFT) & DISPLAY_PLL_M1_DIVISOR_MASK) 452 | (((divisors.m2 - 2) << DISPLAY_PLL_M2_DIVISOR_SHIFT) & DISPLAY_PLL_M2_DIVISOR_MASK)); 453 454 uint32 pll = DISPLAY_PLL_ENABLED | DISPLAY_PLL_NO_VGA_CONTROL; 455 if ((gInfo->shared_info->device_type & INTEL_TYPE_9xx) != 0) { 456 pll |= ((1 << (divisors.post1 - 1)) << DISPLAY_PLL_POST1_DIVISOR_SHIFT) 457 & DISPLAY_PLL_9xx_POST1_DIVISOR_MASK; 458 // pll |= ((divisors.post1 - 1) << DISPLAY_PLL_POST1_DIVISOR_SHIFT) 459 // & DISPLAY_PLL_9xx_POST1_DIVISOR_MASK; 460 if (divisors.post2_high) 461 pll |= DISPLAY_PLL_DIVIDE_HIGH; 462 463 pll |= DISPLAY_PLL_MODE_ANALOG; 464 465 if ((gInfo->shared_info->device_type & INTEL_TYPE_GROUP_MASK) == INTEL_TYPE_965) 466 pll |= 6 << DISPLAY_PLL_PULSE_PHASE_SHIFT; 467 } else { 468 if (!divisors.post2_high) 469 pll |= DISPLAY_PLL_DIVIDE_4X; 470 471 pll |= DISPLAY_PLL_2X_CLOCK; 472 473 if (divisors.post1 > 2) { 474 pll |= (((divisors.post1 - 2) << DISPLAY_PLL_POST1_DIVISOR_SHIFT) 475 & DISPLAY_PLL_POST1_DIVISOR_MASK); 476 } else 477 pll |= DISPLAY_PLL_POST1_DIVIDE_2; 478 } 479 480 write32(INTEL_DISPLAY_A_PLL, pll); 481 read32(INTEL_DISPLAY_A_PLL); 482 spin(150); 483 write32(INTEL_DISPLAY_A_PLL, pll); 484 read32(INTEL_DISPLAY_A_PLL); 485 spin(150); 486 #if 0 487 write32(INTEL_DISPLAY_A_PLL, DISPLAY_PLL_ENABLED | DISPLAY_PLL_2X_CLOCK 488 | DISPLAY_PLL_NO_VGA_CONTROL | DISPLAY_PLL_DIVIDE_4X 489 | (((divisors.post1 - 2) << DISPLAY_PLL_POST1_DIVISOR_SHIFT) & DISPLAY_PLL_POST1_DIVISOR_MASK) 490 | (divisorRegister == INTEL_DISPLAY_A_PLL_DIVISOR_1 ? DISPLAY_PLL_DIVISOR_1 : 0)); 491 #endif 492 // update timing parameters 493 write32(INTEL_DISPLAY_A_HTOTAL, ((uint32)(target.timing.h_total - 1) << 16) 494 | ((uint32)target.timing.h_display - 1)); 495 write32(INTEL_DISPLAY_A_HBLANK, ((uint32)(target.timing.h_total - 1) << 16) 496 | ((uint32)target.timing.h_display - 1)); 497 write32(INTEL_DISPLAY_A_HSYNC, ((uint32)(target.timing.h_sync_end - 1) << 16) 498 | ((uint32)target.timing.h_sync_start - 1)); 499 500 write32(INTEL_DISPLAY_A_VTOTAL, ((uint32)(target.timing.v_total - 1) << 16) 501 | ((uint32)target.timing.v_display - 1)); 502 write32(INTEL_DISPLAY_A_VBLANK, ((uint32)(target.timing.v_total - 1) << 16) 503 | ((uint32)target.timing.v_display - 1)); 504 write32(INTEL_DISPLAY_A_VSYNC, ((uint32)(target.timing.v_sync_end - 1) << 16) 505 | ((uint32)target.timing.v_sync_start - 1)); 506 507 write32(INTEL_DISPLAY_A_IMAGE_SIZE, ((uint32)(target.timing.h_display - 1) << 16) 508 | ((uint32)target.timing.v_display - 1)); 509 510 write32(INTEL_DISPLAY_A_ANALOG_PORT, (read32(INTEL_DISPLAY_A_ANALOG_PORT) 511 & ~(DISPLAY_MONITOR_POLARITY_MASK | DISPLAY_MONITOR_VGA_POLARITY)) 512 | ((target.timing.flags & B_POSITIVE_HSYNC) != 0 ? DISPLAY_MONITOR_POSITIVE_HSYNC : 0) 513 | ((target.timing.flags & B_POSITIVE_VSYNC) != 0 ? DISPLAY_MONITOR_POSITIVE_VSYNC : 0)); 514 } 515 516 // These two have to be set for display B, too - this obviously means 517 // that the second head always must adopt the color space of the first 518 // head. 519 write32(INTEL_DISPLAY_A_CONTROL, (read32(INTEL_DISPLAY_A_CONTROL) 520 & ~(DISPLAY_CONTROL_COLOR_MASK | DISPLAY_CONTROL_GAMMA)) | colorMode); 521 522 if (gInfo->head_mode & HEAD_MODE_B_DIGITAL) { 523 write32(INTEL_DISPLAY_B_IMAGE_SIZE, ((uint32)(target.timing.h_display - 1) << 16) 524 | ((uint32)target.timing.v_display - 1)); 525 526 write32(INTEL_DISPLAY_B_CONTROL, (read32(INTEL_DISPLAY_B_CONTROL) 527 & ~(DISPLAY_CONTROL_COLOR_MASK | DISPLAY_CONTROL_GAMMA)) | colorMode); 528 } 529 530 set_display_power_mode(sharedInfo.dpms_mode); 531 532 // changing bytes per row seems to be ignored if the plane/pipe is turned off 533 534 if (gInfo->head_mode & HEAD_MODE_A_ANALOG) 535 write32(INTEL_DISPLAY_A_BYTES_PER_ROW, bytesPerRow); 536 if (gInfo->head_mode & HEAD_MODE_B_DIGITAL) 537 write32(INTEL_DISPLAY_B_BYTES_PER_ROW, bytesPerRow); 538 539 set_frame_buffer_base(); 540 // triggers writing back double-buffered registers 541 542 // update shared info 543 sharedInfo.bytes_per_row = bytesPerRow; 544 sharedInfo.current_mode = target; 545 sharedInfo.bits_per_pixel = bitsPerPixel; 546 547 return B_OK; 548 } 549 550 551 status_t 552 intel_get_display_mode(display_mode *_currentMode) 553 { 554 TRACE(("intel_get_display_mode()\n")); 555 556 display_mode &mode = *_currentMode; 557 558 uint32 pll = read32(INTEL_DISPLAY_A_PLL); 559 uint32 pllDivisor = read32((pll & DISPLAY_PLL_DIVISOR_1) != 0 560 ? INTEL_DISPLAY_A_PLL_DIVISOR_1 : INTEL_DISPLAY_A_PLL_DIVISOR_0); 561 562 pll_divisors divisors; 563 divisors.m1 = (pllDivisor & DISPLAY_PLL_M1_DIVISOR_MASK) 564 >> DISPLAY_PLL_M1_DIVISOR_SHIFT; 565 divisors.m2 = (pllDivisor & DISPLAY_PLL_M2_DIVISOR_MASK) 566 >> DISPLAY_PLL_M2_DIVISOR_SHIFT; 567 divisors.n = (pllDivisor & DISPLAY_PLL_N_DIVISOR_MASK) 568 >> DISPLAY_PLL_N_DIVISOR_SHIFT; 569 570 pll_limits limits; 571 get_pll_limits(limits); 572 573 if ((gInfo->shared_info->device_type & INTEL_TYPE_9xx) != 0) { 574 divisors.post1 = (pll & DISPLAY_PLL_9xx_POST1_DIVISOR_MASK) 575 >> DISPLAY_PLL_POST1_DIVISOR_SHIFT; 576 577 if ((pll & DISPLAY_PLL_DIVIDE_HIGH) != 0) 578 divisors.post2 = limits.max.post2; 579 else 580 divisors.post2 = limits.min.post2; 581 } else { 582 // 8xx 583 divisors.post1 = (pll & DISPLAY_PLL_POST1_DIVISOR_MASK) 584 >> DISPLAY_PLL_POST1_DIVISOR_SHIFT; 585 586 if ((pll & DISPLAY_PLL_DIVIDE_4X) != 0) 587 divisors.post2 = limits.max.post2; 588 else 589 divisors.post2 = limits.min.post2; 590 } 591 592 divisors.m = 5 * divisors.m1 + divisors.m2; 593 divisors.post = divisors.post1 * divisors.post2; 594 595 float referenceClock = gInfo->shared_info->pll_info.reference_frequency / 1000.0f; 596 float pixelClock = ((referenceClock * divisors.m) / divisors.n) / divisors.post; 597 598 // timing 599 600 mode.timing.pixel_clock = uint32(pixelClock * 1000); 601 mode.timing.flags = 0; 602 603 uint32 value = read32(INTEL_DISPLAY_A_HTOTAL); 604 mode.timing.h_total = (value >> 16) + 1; 605 mode.timing.h_display = (value & 0xffff) + 1; 606 607 value = read32(INTEL_DISPLAY_A_HSYNC); 608 mode.timing.h_sync_end = (value >> 16) + 1; 609 mode.timing.h_sync_start = (value & 0xffff) + 1; 610 611 value = read32(INTEL_DISPLAY_A_VTOTAL); 612 mode.timing.v_total = (value >> 16) + 1; 613 mode.timing.v_display = (value & 0xffff) + 1; 614 615 value = read32(INTEL_DISPLAY_A_VSYNC); 616 mode.timing.v_sync_end = (value >> 16) + 1; 617 mode.timing.v_sync_start = (value & 0xffff) + 1; 618 619 // image size and color space 620 621 value = read32(INTEL_DISPLAY_A_IMAGE_SIZE); 622 mode.virtual_width = (value >> 16) + 1; 623 mode.virtual_height = (value & 0xffff) + 1; 624 625 value = read32(INTEL_DISPLAY_A_CONTROL); 626 switch (value & DISPLAY_CONTROL_COLOR_MASK) { 627 case DISPLAY_CONTROL_RGB32: 628 default: 629 mode.space = B_RGB32; 630 break; 631 case DISPLAY_CONTROL_RGB16: 632 mode.space = B_RGB16; 633 break; 634 case DISPLAY_CONTROL_RGB15: 635 mode.space = B_RGB15; 636 break; 637 case DISPLAY_CONTROL_CMAP8: 638 mode.space = B_CMAP8; 639 break; 640 } 641 642 mode.h_display_start = 0; 643 mode.v_display_start = 0; 644 mode.flags = 0; 645 return B_OK; 646 } 647 648 #ifdef __HAIKU__ 649 650 status_t 651 intel_get_edid_info(void* info, size_t size, uint32* _version) 652 { 653 if (!gInfo->has_edid) 654 return B_ERROR; 655 if (size < sizeof(struct edid1_info)) 656 return B_BUFFER_OVERFLOW; 657 658 memcpy(info, &gInfo->edid_info, sizeof(struct edid1_info)); 659 *_version = EDID_VERSION_1; 660 return B_OK; 661 } 662 663 #endif // __HAIKU__ 664 665 status_t 666 intel_get_frame_buffer_config(frame_buffer_config *config) 667 { 668 TRACE(("intel_get_frame_buffer_config()\n")); 669 670 uint32 offset = gInfo->shared_info->frame_buffer_offset; 671 672 config->frame_buffer = gInfo->shared_info->graphics_memory + offset; 673 config->frame_buffer_dma = gInfo->shared_info->physical_graphics_memory + offset; 674 config->bytes_per_row = gInfo->shared_info->bytes_per_row; 675 676 return B_OK; 677 } 678 679 680 status_t 681 intel_get_pixel_clock_limits(display_mode *mode, uint32 *_low, uint32 *_high) 682 { 683 TRACE(("intel_get_pixel_clock_limits()\n")); 684 685 if (_low != NULL) { 686 // lower limit of about 48Hz vertical refresh 687 uint32 totalClocks = (uint32)mode->timing.h_total * (uint32)mode->timing.v_total; 688 uint32 low = (totalClocks * 48L) / 1000L; 689 if (low < gInfo->shared_info->pll_info.min_frequency) 690 low = gInfo->shared_info->pll_info.min_frequency; 691 else if (low > gInfo->shared_info->pll_info.max_frequency) 692 return B_ERROR; 693 694 *_low = low; 695 } 696 697 if (_high != NULL) 698 *_high = gInfo->shared_info->pll_info.max_frequency; 699 700 return B_OK; 701 } 702 703 704 status_t 705 intel_move_display(uint16 horizontalStart, uint16 verticalStart) 706 { 707 TRACE(("intel_move_display()\n")); 708 709 intel_shared_info &sharedInfo = *gInfo->shared_info; 710 Autolock locker(sharedInfo.accelerant_lock); 711 712 display_mode &mode = sharedInfo.current_mode; 713 714 if (horizontalStart + mode.timing.h_display > mode.virtual_width 715 || verticalStart + mode.timing.v_display > mode.virtual_height) 716 return B_BAD_VALUE; 717 718 mode.h_display_start = horizontalStart; 719 mode.v_display_start = verticalStart; 720 721 set_frame_buffer_base(); 722 723 return B_OK; 724 } 725 726 727 status_t 728 intel_get_timing_constraints(display_timing_constraints *constraints) 729 { 730 TRACE(("intel_get_timing_contraints()\n")); 731 return B_ERROR; 732 } 733 734 735 void 736 intel_set_indexed_colors(uint count, uint8 first, uint8 *colors, uint32 flags) 737 { 738 TRACE(("intel_set_indexed_colors(colors = %p, first = %u)\n", colors, first)); 739 740 if (colors == NULL) 741 return; 742 743 Autolock locker(gInfo->shared_info->accelerant_lock); 744 745 for (; count-- > 0; first++) { 746 uint32 color = colors[0] << 16 | colors[1] << 8 | colors[2]; 747 colors += 3; 748 749 if (gInfo->head_mode & HEAD_MODE_A_ANALOG) 750 write32(INTEL_DISPLAY_A_PALETTE + first * sizeof(uint32), color); 751 if (gInfo->head_mode & HEAD_MODE_B_DIGITAL) 752 write32(INTEL_DISPLAY_B_PALETTE + first * sizeof(uint32), color); 753 } 754 } 755 756