1 /* 2 * Copyright 2006, Haiku, Inc. All Rights Reserved. 3 * Distributed under the terms of the MIT License. 4 * 5 * Authors: 6 * Axel Dörfler, axeld@pinc-software.de 7 */ 8 9 10 #include "accelerant_protos.h" 11 #include "accelerant.h" 12 #include "utility.h" 13 14 15 #define TRACE_MODE 16 #ifdef TRACE_MODE 17 extern "C" void _sPrintf(const char *format, ...); 18 # define TRACE(x) _sPrintf x 19 #else 20 # define TRACE(x) ; 21 #endif 22 23 24 #define POSITIVE_SYNC \ 25 (B_POSITIVE_HSYNC | B_POSITIVE_VSYNC) 26 #define MODE_FLAGS \ 27 (B_8_BIT_DAC | B_HARDWARE_CURSOR | B_PARALLEL_ACCESS | B_DPMS | B_SUPPORTS_OVERLAYS) 28 29 30 static const display_mode kBaseModeList[] = { 31 {{25175, 640, 656, 752, 800, 350, 387, 389, 449, B_POSITIVE_HSYNC}, B_CMAP8, 640, 350, 0, 0, MODE_FLAGS}, /* 640x350 - www.epanorama.net/documents/pc/vga_timing.html) */ 32 {{25175, 640, 656, 752, 800, 400, 412, 414, 449, B_POSITIVE_VSYNC}, B_CMAP8, 640, 400, 0, 0, MODE_FLAGS}, /* 640x400 - www.epanorama.net/documents/pc/vga_timing.html) */ 33 {{25175, 640, 656, 752, 800, 480, 490, 492, 525, 0}, B_CMAP8, 640, 480, 0, 0, MODE_FLAGS}, /* Vesa_Monitor_@60Hz_(640X480X8.Z1) */ 34 {{27500, 640, 672, 768, 864, 480, 488, 494, 530, 0}, B_CMAP8, 640, 480, 0, 0, MODE_FLAGS}, /* 640X480X60Hz */ 35 {{30500, 640, 672, 768, 864, 480, 517, 523, 588, 0}, B_CMAP8, 640, 480, 0, 0, MODE_FLAGS}, /* SVGA_640X480X60HzNI */ 36 {{31500, 640, 664, 704, 832, 480, 489, 492, 520, 0}, B_CMAP8, 640, 480, 0, 0, MODE_FLAGS}, /* Vesa_Monitor_@70-72Hz_(640X480X8.Z1) */ 37 {{31500, 640, 656, 720, 840, 480, 481, 484, 500, 0}, B_CMAP8, 640, 480, 0, 0, MODE_FLAGS}, /* Vesa_Monitor_@75Hz_(640X480X8.Z1) */ 38 {{36000, 640, 696, 752, 832, 480, 481, 484, 509, 0}, B_CMAP8, 640, 480, 0, 0, MODE_FLAGS}, /* Vesa_Monitor_@85Hz_(640X480X8.Z1) */ 39 {{38100, 800, 832, 960, 1088, 600, 602, 606, 620, 0}, B_CMAP8, 800, 600, 0, 0, MODE_FLAGS}, /* SVGA_800X600X56HzNI */ 40 {{40000, 800, 840, 968, 1056, 600, 601, 605, 628, POSITIVE_SYNC}, B_CMAP8, 800, 600, 0, 0, MODE_FLAGS}, /* Vesa_Monitor_@60Hz_(800X600X8.Z1) */ 41 {{49500, 800, 816, 896, 1056, 600, 601, 604, 625, POSITIVE_SYNC}, B_CMAP8, 800, 600, 0, 0, MODE_FLAGS}, /* Vesa_Monitor_@75Hz_(800X600X8.Z1) */ 42 {{50000, 800, 856, 976, 1040, 600, 637, 643, 666, POSITIVE_SYNC}, B_CMAP8, 800, 600, 0, 0, MODE_FLAGS}, /* Vesa_Monitor_@70-72Hz_(800X600X8.Z1) */ 43 {{56250, 800, 832, 896, 1048, 600, 601, 604, 631, POSITIVE_SYNC}, B_CMAP8, 800, 600, 0, 0, MODE_FLAGS}, /* Vesa_Monitor_@85Hz_(800X600X8.Z1) */ 44 {{65000, 1024, 1048, 1184, 1344, 768, 771, 777, 806, 0}, B_CMAP8, 1024, 768, 0, 0, MODE_FLAGS}, /* Vesa_Monitor_@60Hz_(1024X768X8.Z1) */ 45 {{75000, 1024, 1048, 1184, 1328, 768, 771, 777, 806, 0}, B_CMAP8, 1024, 768, 0, 0, MODE_FLAGS}, /* Vesa_Monitor_@70-72Hz_(1024X768X8.Z1) */ 46 {{78750, 1024, 1040, 1136, 1312, 768, 769, 772, 800, POSITIVE_SYNC}, B_CMAP8, 1024, 768, 0, 0, MODE_FLAGS}, /* Vesa_Monitor_@75Hz_(1024X768X8.Z1) */ 47 {{94500, 1024, 1072, 1168, 1376, 768, 769, 772, 808, POSITIVE_SYNC}, B_CMAP8, 1024, 768, 0, 0, MODE_FLAGS}, /* Vesa_Monitor_@85Hz_(1024X768X8.Z1) */ 48 {{94200, 1152, 1184, 1280, 1472, 864, 865, 868, 914, POSITIVE_SYNC}, B_CMAP8, 1152, 864, 0, 0, MODE_FLAGS}, /* Vesa_Monitor_@70Hz_(1152X864X8.Z1) */ 49 {{108000, 1152, 1216, 1344, 1600, 864, 865, 868, 900, POSITIVE_SYNC}, B_CMAP8, 1152, 864, 0, 0, MODE_FLAGS}, /* Vesa_Monitor_@75Hz_(1152X864X8.Z1) */ 50 {{121500, 1152, 1216, 1344, 1568, 864, 865, 868, 911, POSITIVE_SYNC}, B_CMAP8, 1152, 864, 0, 0, MODE_FLAGS}, /* Vesa_Monitor_@85Hz_(1152X864X8.Z1) */ 51 {{108000, 1280, 1328, 1440, 1688, 1024, 1025, 1028, 1066, POSITIVE_SYNC}, B_CMAP8, 1280, 1024, 0, 0, MODE_FLAGS}, /* Vesa_Monitor_@60Hz_(1280X1024X8.Z1) */ 52 {{135000, 1280, 1296, 1440, 1688, 1024, 1025, 1028, 1066, POSITIVE_SYNC}, B_CMAP8, 1280, 1024, 0, 0, MODE_FLAGS}, /* Vesa_Monitor_@75Hz_(1280X1024X8.Z1) */ 53 {{157500, 1280, 1344, 1504, 1728, 1024, 1025, 1028, 1072, POSITIVE_SYNC}, B_CMAP8, 1280, 1024, 0, 0, MODE_FLAGS}, /* Vesa_Monitor_@85Hz_(1280X1024X8.Z1) */ 54 {{162000, 1600, 1664, 1856, 2160, 1200, 1201, 1204, 1250, POSITIVE_SYNC}, B_CMAP8, 1600, 1200, 0, 0, MODE_FLAGS}, /* Vesa_Monitor_@60Hz_(1600X1200X8.Z1) */ 55 {{175500, 1600, 1664, 1856, 2160, 1200, 1201, 1204, 1250, POSITIVE_SYNC}, B_CMAP8, 1600, 1200, 0, 0, MODE_FLAGS}, /* Vesa_Monitor_@65Hz_(1600X1200X8.Z1) */ 56 {{189000, 1600, 1664, 1856, 2160, 1200, 1201, 1204, 1250, POSITIVE_SYNC}, B_CMAP8, 1600, 1200, 0, 0, MODE_FLAGS}, /* Vesa_Monitor_@70Hz_(1600X1200X8.Z1) */ 57 {{202500, 1600, 1664, 1856, 2160, 1200, 1201, 1204, 1250, POSITIVE_SYNC}, B_CMAP8, 1600, 1200, 0, 0, MODE_FLAGS}, /* Vesa_Monitor_@75Hz_(1600X1200X8.Z1) */ 58 {{216000, 1600, 1664, 1856, 2160, 1200, 1201, 1204, 1250, POSITIVE_SYNC}, B_CMAP8, 1600, 1200, 0, 0, MODE_FLAGS}, /* Vesa_Monitor_@80Hz_(1600X1200X8.Z1) */ 59 {{229500, 1600, 1664, 1856, 2160, 1200, 1201, 1204, 1250, POSITIVE_SYNC}, B_CMAP8, 1600, 1200, 0, 0, MODE_FLAGS} /* Vesa_Monitor_@85Hz_(1600X1200X8.Z1) */ 60 }; 61 static const uint32 kNumBaseModes = sizeof(kBaseModeList) / sizeof(display_mode); 62 static const uint32 kMaxNumModes = kNumBaseModes * 4; 63 64 65 /** Creates the initial mode list of the primary accelerant. 66 * It's called from intel_init_accelerant(). 67 */ 68 69 status_t 70 create_mode_list(void) 71 { 72 color_space spaces[4] = {B_RGB32_LITTLE, B_RGB16_LITTLE, B_RGB15_LITTLE, B_CMAP8}; 73 size_t size = ROUND_TO_PAGE_SIZE(kMaxNumModes * sizeof(display_mode)); 74 display_mode *list; 75 76 gInfo->mode_list_area = create_area("intel extreme modes", (void **)&list, B_ANY_ADDRESS, 77 size, B_NO_LOCK, B_READ_AREA | B_WRITE_AREA); 78 if (gInfo->mode_list_area < B_OK) 79 return gInfo->mode_list_area; 80 81 // for now, just copy all of the modes with different color spaces 82 83 const display_mode *source = kBaseModeList; 84 uint32 count = 0; 85 86 for (uint32 i = 0; i < kNumBaseModes; i++) { 87 for (uint32 j = 0; j < (sizeof(spaces) / sizeof(color_space)); j++) { 88 list[count] = *source; 89 list[count].space = spaces[j]; 90 91 count++; 92 } 93 94 source++; 95 } 96 97 gInfo->mode_list = list; 98 gInfo->shared_info->mode_list_area = gInfo->mode_list_area; 99 gInfo->shared_info->mode_count = count; 100 101 return B_OK; 102 } 103 104 105 void 106 wait_for_vblank(void) 107 { 108 acquire_sem_etc(gInfo->shared_info->vblank_sem, 1, B_RELATIVE_TIMEOUT, 25000); 109 // With the output turned off via DPMS, we might not get any interrupts anymore 110 // that's why we don't wait forever for it. 111 } 112 113 114 static void 115 compute_pll_divisors(const display_mode ¤t, uint32 &postDivisor, 116 uint32 &nDivisor, uint32 &m1Divisor, uint32 &m2Divisor) 117 { 118 float requestedPixelClock = current.timing.pixel_clock / 1000.0f; 119 float referenceClock = gInfo->shared_info->pll_info.reference_frequency / 1000.0f; 120 121 TRACE(("required MHz: %g\n", requestedPixelClock)); 122 123 float best = requestedPixelClock; 124 uint32 bestP = 0, bestN = 0, bestM = 0; 125 126 // Note, the limits are taken from the X driver; they have not yet been tested 127 128 for (uint32 p = 3; p < 31; p++) { 129 for (uint32 n = 3; n < 16; n++) { 130 for (uint32 m1 = 6; m1 < 26; m1++) { 131 for (uint32 m2 = 6; m2 < 16; m2++) { 132 uint32 m = m1 * 5 + m2; 133 float error = fabs(requestedPixelClock - ((referenceClock * m) / n) / (p*4)); 134 if (error < best) { 135 best = error; 136 bestP = p; 137 bestN = n; 138 bestM = m; 139 if (error == 0) 140 break; 141 } 142 } 143 } 144 } 145 } 146 147 postDivisor = bestP; 148 nDivisor = bestN; 149 150 TRACE(("found: %g MHz (p = %lu, n = %lu, m = %lu (m1 = %lu, m2 = %lu)\n", 151 ((referenceClock * bestM) / bestN) / (bestP*4), bestP, bestN, bestM, 152 m1Divisor, m2Divisor)); 153 154 m1Divisor = bestM / 5; 155 m2Divisor = bestM % 5; 156 while (m2Divisor < 6) { 157 m1Divisor--; 158 m2Divisor += 5; 159 } 160 } 161 162 163 static void 164 get_color_space_format(const display_mode &mode, uint32 &colorMode, 165 uint32 &bytesPerRow, uint32 &bitsPerPixel) 166 { 167 uint32 bytesPerPixel; 168 169 switch (mode.space) { 170 case B_RGB32_LITTLE: 171 colorMode = DISPLAY_CONTROL_RGB32; 172 bytesPerPixel = 4; 173 bitsPerPixel = 32; 174 break; 175 case B_RGB16_LITTLE: 176 colorMode = DISPLAY_CONTROL_RGB16; 177 bytesPerPixel = 2; 178 bitsPerPixel = 16; 179 break; 180 case B_RGB15_LITTLE: 181 colorMode = DISPLAY_CONTROL_RGB15; 182 bytesPerPixel = 2; 183 bitsPerPixel = 15; 184 break; 185 case B_CMAP8: 186 default: 187 colorMode = DISPLAY_CONTROL_CMAP8; 188 bytesPerPixel = 1; 189 bitsPerPixel = 8; 190 break; 191 } 192 193 bytesPerRow = mode.virtual_width * bytesPerPixel; 194 } 195 196 197 // #pragma mark - 198 199 200 uint32 201 intel_accelerant_mode_count(void) 202 { 203 TRACE(("intel_accelerant_mode_count()\n")); 204 return gInfo->shared_info->mode_count; 205 } 206 207 208 status_t 209 intel_get_mode_list(display_mode *modeList) 210 { 211 TRACE(("intel_get_mode_info()\n")); 212 memcpy(modeList, gInfo->mode_list, gInfo->shared_info->mode_count * sizeof(display_mode)); 213 return B_OK; 214 } 215 216 217 status_t 218 intel_propose_display_mode(display_mode *target, const display_mode *low, 219 const display_mode *high) 220 { 221 TRACE(("intel_propose_display_mode()\n")); 222 223 // just search for the specified mode in the list 224 225 for (uint32 i = 0; i < gInfo->shared_info->mode_count; i++) { 226 display_mode *mode = &gInfo->mode_list[i]; 227 228 // TODO: improve this, ie. adapt pixel clock to allowed values!!! 229 230 if (target->virtual_width != mode->virtual_width 231 || target->virtual_height != mode->virtual_height 232 || target->space != mode->space) 233 continue; 234 235 *target = *mode; 236 return B_OK; 237 } 238 return B_BAD_VALUE; 239 } 240 241 242 status_t 243 intel_set_display_mode(display_mode *mode) 244 { 245 TRACE(("intel_set_display_mode()\n")); 246 247 display_mode target = *mode; 248 249 if (mode == NULL || intel_propose_display_mode(&target, mode, mode)) 250 return B_BAD_VALUE; 251 252 intel_shared_info &sharedInfo = *gInfo->shared_info; 253 Autolock locker(sharedInfo.accelerant_lock); 254 255 set_display_power_mode(B_DPMS_OFF); 256 257 uint32 colorMode, bytesPerRow, bitsPerPixel; 258 get_color_space_format(target, colorMode, bytesPerRow, bitsPerPixel); 259 260 // free old and allocate new frame buffer in graphics memory 261 262 intel_free_memory(gInfo->frame_buffer_handle); 263 264 uint32 offset; 265 if (intel_allocate_memory(bytesPerRow * target.virtual_height, 266 gInfo->frame_buffer_handle, offset) < B_OK) { 267 // oh, how did that happen? Unfortunately, there is no really good way back 268 if (intel_allocate_memory(sharedInfo.current_mode.virtual_height 269 * sharedInfo.bytes_per_row, gInfo->frame_buffer_handle, 270 offset) == B_OK) { 271 sharedInfo.frame_buffer_offset = offset; 272 write32(INTEL_DISPLAY_A_BASE, offset); 273 } 274 275 return B_NO_MEMORY; 276 } 277 278 sharedInfo.frame_buffer_offset = offset; 279 280 // make sure VGA display is disabled 281 write32(INTEL_VGA_DISPLAY_CONTROL, read32(INTEL_VGA_DISPLAY_CONTROL) 282 | VGA_DISPLAY_DISABLED); 283 284 if (gInfo->head_mode & HEAD_MODE_A_ANALOG) { 285 // update timing parameters 286 write32(INTEL_DISPLAY_A_HTOTAL, ((uint32)(target.timing.h_total - 1) << 16) 287 | ((uint32)target.timing.h_display - 1)); 288 write32(INTEL_DISPLAY_A_HBLANK, ((uint32)(target.timing.h_total - 1) << 16) 289 | ((uint32)target.timing.h_display - 1)); 290 write32(INTEL_DISPLAY_A_HSYNC, ((uint32)(target.timing.h_sync_end - 1) << 16) 291 | ((uint32)target.timing.h_sync_start - 1)); 292 293 write32(INTEL_DISPLAY_A_VTOTAL, ((uint32)(target.timing.v_total - 1) << 16) 294 | ((uint32)target.timing.v_display - 1)); 295 write32(INTEL_DISPLAY_A_VBLANK, ((uint32)(target.timing.v_total - 1) << 16) 296 | ((uint32)target.timing.v_display - 1)); 297 write32(INTEL_DISPLAY_A_VSYNC, ((uint32)(target.timing.v_sync_end - 1) << 16) 298 | ((uint32)target.timing.v_sync_start - 1)); 299 300 write32(INTEL_DISPLAY_A_IMAGE_SIZE, ((uint32)(target.timing.h_display - 1) << 16) 301 | ((uint32)target.timing.v_display - 1)); 302 303 write32(INTEL_DISPLAY_A_ANALOG_PORT, (read32(INTEL_DISPLAY_A_ANALOG_PORT) 304 & ~(DISPLAY_MONITOR_POLARITY_MASK | DISPLAY_MONITOR_VGA_POLARITY)) 305 | ((target.timing.flags & B_POSITIVE_HSYNC) != 0 ? DISPLAY_MONITOR_POSITIVE_HSYNC : 0) 306 | ((target.timing.flags & B_POSITIVE_VSYNC) != 0 ? DISPLAY_MONITOR_POSITIVE_VSYNC : 0)); 307 308 uint32 postDivisor, nDivisor, m1Divisor, m2Divisor; 309 compute_pll_divisors(target, postDivisor, nDivisor, m1Divisor, m2Divisor); 310 311 // switch divisor register with every mode change (not required) 312 uint32 divisorRegister; 313 if (gInfo->shared_info->pll_info.divisor_register == INTEL_DISPLAY_A_PLL_DIVISOR_0) 314 divisorRegister = INTEL_DISPLAY_A_PLL_DIVISOR_1; 315 else 316 divisorRegister = INTEL_DISPLAY_A_PLL_DIVISOR_0; 317 318 write32(divisorRegister, 319 (((nDivisor - 2) << DISPLAY_PLL_N_DIVISOR_SHIFT) & DISPLAY_PLL_N_DIVISOR_MASK) 320 | (((m1Divisor - 2) << DISPLAY_PLL_M1_DIVISOR_SHIFT) & DISPLAY_PLL_M1_DIVISOR_MASK) 321 | (((m2Divisor - 2) << DISPLAY_PLL_M2_DIVISOR_SHIFT) & DISPLAY_PLL_M2_DIVISOR_MASK)); 322 write32(INTEL_DISPLAY_A_PLL, DISPLAY_PLL_ENABLED | DISPLAY_PLL_2X_CLOCK 323 | DISPLAY_PLL_NO_VGA_CONTROL | DISPLAY_PLL_DIVIDE_4X 324 | (((postDivisor - 2) << DISPLAY_PLL_POST_DIVISOR_SHIFT) & DISPLAY_PLL_POST_DIVISOR_MASK) 325 | (divisorRegister == INTEL_DISPLAY_A_PLL_DIVISOR_1 ? DISPLAY_PLL_DIVISOR_1 : 0)); 326 } 327 328 // These two have to be set for display B, too - this obviously means 329 // that the second head always must adopt the color space of the first 330 // head. 331 write32(INTEL_DISPLAY_A_CONTROL, (read32(INTEL_DISPLAY_A_CONTROL) 332 & ~(DISPLAY_CONTROL_COLOR_MASK | DISPLAY_CONTROL_GAMMA)) | colorMode); 333 334 if (gInfo->head_mode & HEAD_MODE_B_DIGITAL) { 335 write32(INTEL_DISPLAY_B_IMAGE_SIZE, ((uint32)(target.timing.h_display - 1) << 16) 336 | ((uint32)target.timing.v_display - 1)); 337 338 write32(INTEL_DISPLAY_B_CONTROL, (read32(INTEL_DISPLAY_B_CONTROL) 339 & ~(DISPLAY_CONTROL_COLOR_MASK | DISPLAY_CONTROL_GAMMA)) | colorMode); 340 } 341 342 set_display_power_mode(sharedInfo.dpms_mode); 343 344 // changing bytes per row seems to be ignored if the plane/pipe is turned off 345 346 if (gInfo->head_mode & HEAD_MODE_A_ANALOG) { 347 write32(INTEL_DISPLAY_A_BYTES_PER_ROW, bytesPerRow); 348 write32(INTEL_DISPLAY_A_BASE, sharedInfo.frame_buffer_offset); 349 // triggers writing back double-buffered registers 350 } 351 if (gInfo->head_mode & HEAD_MODE_B_DIGITAL) { 352 write32(INTEL_DISPLAY_B_BYTES_PER_ROW, bytesPerRow); 353 write32(INTEL_DISPLAY_B_BASE, sharedInfo.frame_buffer_offset); 354 // triggers writing back double-buffered registers 355 } 356 357 // update shared info 358 sharedInfo.bytes_per_row = bytesPerRow; 359 sharedInfo.current_mode = target; 360 sharedInfo.bits_per_pixel = bitsPerPixel; 361 362 #if 0 363 int fd = open("/boot/home/ie.regs", O_CREAT | O_WRONLY, 0644); 364 if (fd >= 0) { 365 for (int32 i = 0; i < 0x80000; i += 16) { 366 char line[512]; 367 int length = sprintf(line, "%05lx: %08lx %08lx %08lx %08lx\n", 368 i, read32(i), read32(i + 4), read32(i + 8), read32(i + 12)); 369 write(fd, line, length); 370 } 371 close(fd); 372 sync(); 373 } 374 #endif 375 376 return B_OK; 377 } 378 379 380 status_t 381 intel_get_display_mode(display_mode *_currentMode) 382 { 383 TRACE(("intel_get_display_mode()\n")); 384 *_currentMode = gInfo->shared_info->current_mode; 385 return B_OK; 386 } 387 388 389 status_t 390 intel_get_frame_buffer_config(frame_buffer_config *config) 391 { 392 TRACE(("intel_get_frame_buffer_config()\n")); 393 394 uint32 offset = gInfo->shared_info->frame_buffer_offset; 395 396 config->frame_buffer = gInfo->shared_info->graphics_memory + offset; 397 config->frame_buffer_dma = gInfo->shared_info->physical_graphics_memory + offset; 398 config->bytes_per_row = gInfo->shared_info->bytes_per_row; 399 400 return B_OK; 401 } 402 403 404 status_t 405 intel_get_pixel_clock_limits(display_mode *mode, uint32 *_low, uint32 *_high) 406 { 407 TRACE(("intel_get_pixel_clock_limits()\n")); 408 409 if (_low != NULL) { 410 // lower limit of about 48Hz vertical refresh 411 uint32 totalClocks = (uint32)mode->timing.h_total * (uint32)mode->timing.v_total; 412 uint32 low = (totalClocks * 48L) / 1000L; 413 if (low < gInfo->shared_info->pll_info.min_frequency) 414 low = gInfo->shared_info->pll_info.min_frequency; 415 else if (low > gInfo->shared_info->pll_info.max_frequency) 416 return B_ERROR; 417 418 *_low = low; 419 } 420 421 if (_high != NULL) 422 *_high = gInfo->shared_info->pll_info.max_frequency; 423 424 return B_OK; 425 } 426 427 428 status_t 429 intel_move_display(uint16 horizontalStart, uint16 verticalStart) 430 { 431 TRACE(("intel_move_display()\n")); 432 433 intel_shared_info &sharedInfo = *gInfo->shared_info; 434 Autolock locker(sharedInfo.accelerant_lock); 435 436 display_mode &mode = sharedInfo.current_mode; 437 438 if (horizontalStart + mode.timing.h_display > mode.virtual_width 439 || verticalStart + mode.timing.v_display > mode.virtual_height) 440 return B_BAD_VALUE; 441 442 mode.h_display_start = horizontalStart; 443 mode.v_display_start = verticalStart; 444 445 if (gInfo->head_mode & HEAD_MODE_A_ANALOG) { 446 write32(INTEL_DISPLAY_A_BASE, sharedInfo.frame_buffer_offset 447 + verticalStart * sharedInfo.bytes_per_row 448 + horizontalStart * (sharedInfo.bits_per_pixel + 7) / 8); 449 } 450 if (gInfo->head_mode & HEAD_MODE_B_DIGITAL) { 451 write32(INTEL_DISPLAY_B_BASE, sharedInfo.frame_buffer_offset 452 + verticalStart * sharedInfo.bytes_per_row 453 + horizontalStart * (sharedInfo.bits_per_pixel + 7) / 8); 454 } 455 456 return B_OK; 457 } 458 459 460 status_t 461 intel_get_timing_constraints(display_timing_constraints *constraints) 462 { 463 TRACE(("intel_get_timing_contraints()\n")); 464 return B_ERROR; 465 } 466 467 468 void 469 intel_set_indexed_colors(uint count, uint8 first, uint8 *colors, uint32 flags) 470 { 471 TRACE(("intel_set_indexed_colors(colors = %p, first = %u)\n", colors, first)); 472 473 if (colors == NULL) 474 return; 475 476 Autolock locker(gInfo->shared_info->accelerant_lock); 477 478 for (; count-- > 0; first++) { 479 uint32 color = colors[0] << 16 | colors[1] << 8 | colors[2]; 480 colors += 3; 481 482 if (gInfo->head_mode & HEAD_MODE_A_ANALOG) 483 write32(INTEL_DISPLAY_A_PALETTE + first * sizeof(uint32), color); 484 if (gInfo->head_mode & HEAD_MODE_B_DIGITAL) 485 write32(INTEL_DISPLAY_B_PALETTE + first * sizeof(uint32), color); 486 } 487 } 488 489