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