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