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