1 /* 2 * Copyright 2006-2009, 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 static display_mode gDisplayMode; 36 37 38 status_t 39 create_mode_list(void) 40 { 41 gDisplayMode.timing.pixel_clock = 71500; 42 gDisplayMode.timing.h_display = 1366; /* in pixels (not character clocks) */ 43 gDisplayMode.timing.h_sync_start = 1406; 44 gDisplayMode.timing.h_sync_end = 1438; 45 gDisplayMode.timing.h_total = 1510; 46 gDisplayMode.timing.v_display = 768; /* in lines */ 47 gDisplayMode.timing.v_sync_start = 771; 48 gDisplayMode.timing.v_sync_end = 777; 49 gDisplayMode.timing.v_total = 789; 50 gDisplayMode.timing.flags = 0; /* sync polarity, etc. */ 51 52 gDisplayMode.space = B_RGB32_LITTLE; /* pixel configuration */ 53 gDisplayMode.virtual_width = 1366; /* in pixels */ 54 gDisplayMode.virtual_height = 768; /* in lines */ 55 gDisplayMode.h_display_start = 0; /* first displayed pixel in line */ 56 gDisplayMode.v_display_start = 0; /* first displayed line */ 57 gDisplayMode.flags = 0; /* mode flags (Some drivers use this */ 58 59 gInfo->mode_list = &gDisplayMode; 60 gInfo->shared_info->mode_count = 1; 61 return B_OK; 62 } 63 64 65 // #pragma mark - 66 67 68 uint32 69 radeon_accelerant_mode_count(void) 70 { 71 TRACE(("radeon_accelerant_mode_count()\n")); 72 73 return gInfo->shared_info->mode_count; 74 } 75 76 77 status_t 78 radeon_get_mode_list(display_mode *modeList) 79 { 80 TRACE(("radeon_get_mode_info()\n")); 81 memcpy(modeList, gInfo->mode_list, 82 gInfo->shared_info->mode_count * sizeof(display_mode)); 83 return B_OK; 84 } 85 86 87 inline void 88 write32AtMask(uint32 adress, uint32 value, uint32 mask) 89 { 90 uint32 temp; 91 temp = read32(adress); 92 temp &= ~mask; 93 temp |= value & mask; 94 write32(adress, temp); 95 } 96 97 98 enum { 99 /* CRTC1 registers */ 100 D1CRTC_H_TOTAL = 0x6000, 101 D1CRTC_H_BLANK_START_END = 0x6004, 102 D1CRTC_H_SYNC_A = 0x6008, 103 D1CRTC_H_SYNC_A_CNTL = 0x600C, 104 D1CRTC_H_SYNC_B = 0x6010, 105 D1CRTC_H_SYNC_B_CNTL = 0x6014, 106 107 D1CRTC_V_TOTAL = 0x6020, 108 D1CRTC_V_BLANK_START_END = 0x6024, 109 D1CRTC_V_SYNC_A = 0x6028, 110 D1CRTC_V_SYNC_A_CNTL = 0x602C, 111 D1CRTC_V_SYNC_B = 0x6030, 112 D1CRTC_V_SYNC_B_CNTL = 0x6034, 113 114 D1CRTC_CONTROL = 0x6080, 115 D1CRTC_BLANK_CONTROL = 0x6084, 116 D1CRTC_INTERLACE_CONTROL = 0x6088, 117 D1CRTC_BLACK_COLOR = 0x6098, 118 D1CRTC_STATUS = 0x609C, 119 D1CRTC_COUNT_CONTROL = 0x60B4, 120 121 /* D1GRPH registers */ 122 D1GRPH_ENABLE = 0x6100, 123 D1GRPH_CONTROL = 0x6104, 124 D1GRPH_LUT_SEL = 0x6108, 125 D1GRPH_SWAP_CNTL = 0x610C, 126 D1GRPH_PRIMARY_SURFACE_ADDRESS = 0x6110, 127 D1GRPH_SECONDARY_SURFACE_ADDRESS = 0x6118, 128 D1GRPH_PITCH = 0x6120, 129 D1GRPH_SURFACE_OFFSET_X = 0x6124, 130 D1GRPH_SURFACE_OFFSET_Y = 0x6128, 131 D1GRPH_X_START = 0x612C, 132 D1GRPH_Y_START = 0x6130, 133 D1GRPH_X_END = 0x6134, 134 D1GRPH_Y_END = 0x6138, 135 D1GRPH_UPDATE = 0x6144, 136 137 /* D1MODE */ 138 D1MODE_DESKTOP_HEIGHT = 0x652C, 139 D1MODE_VLINE_START_END = 0x6538, 140 D1MODE_VLINE_STATUS = 0x653C, 141 D1MODE_VIEWPORT_START = 0x6580, 142 D1MODE_VIEWPORT_SIZE = 0x6584, 143 D1MODE_EXT_OVERSCAN_LEFT_RIGHT = 0x6588, 144 D1MODE_EXT_OVERSCAN_TOP_BOTTOM = 0x658C, 145 D1MODE_DATA_FORMAT = 0x6528, 146 147 /* D1SCL */ 148 D1SCL_ENABLE = 0x6590, 149 D1SCL_TAP_CONTROL = 0x6594, 150 D1MODE_CENTER = 0x659C, /* guess */ 151 D1SCL_HVSCALE = 0x65A4, /* guess */ 152 D1SCL_HFILTER = 0x65B0, /* guess */ 153 D1SCL_VFILTER = 0x65C0, /* guess */ 154 D1SCL_UPDATE = 0x65CC, 155 D1SCL_DITHER = 0x65D4, /* guess */ 156 D1SCL_FLIP_CONTROL = 0x65D8 /* guess */ 157 158 }; 159 160 161 static void 162 get_color_space_format(const display_mode &mode, uint32 &colorMode, 163 uint32 &bytesPerRow, uint32 &bitsPerPixel) 164 { 165 uint32 bytesPerPixel; 166 167 switch (mode.space) { 168 case B_RGB32_LITTLE: 169 colorMode = DISPLAY_CONTROL_RGB32; 170 bytesPerPixel = 4; 171 bitsPerPixel = 32; 172 break; 173 case B_RGB16_LITTLE: 174 colorMode = DISPLAY_CONTROL_RGB16; 175 bytesPerPixel = 2; 176 bitsPerPixel = 16; 177 break; 178 case B_RGB15_LITTLE: 179 colorMode = DISPLAY_CONTROL_RGB15; 180 bytesPerPixel = 2; 181 bitsPerPixel = 15; 182 break; 183 case B_CMAP8: 184 default: 185 colorMode = DISPLAY_CONTROL_CMAP8; 186 bytesPerPixel = 1; 187 bitsPerPixel = 8; 188 break; 189 } 190 191 bytesPerRow = mode.virtual_width * bytesPerPixel; 192 193 // Make sure bytesPerRow is a multiple of 64 194 // TODO: check if the older chips have the same restriction! 195 if ((bytesPerRow & 63) != 0) 196 bytesPerRow = (bytesPerRow + 63) & ~63; 197 } 198 199 #define D1_REG_OFFSET 0x0000 200 #define D2_REG_OFFSET 0x0800 201 202 203 static void 204 DxModeSet(display_mode *mode) 205 { 206 uint32 regOffset = D1_REG_OFFSET; 207 208 display_timing& displayTiming = mode->timing; 209 210 211 /* enable read requests */ 212 write32AtMask(regOffset + D1CRTC_CONTROL, 0, 0x01000000); 213 214 /* Horizontal */ 215 write32(regOffset + D1CRTC_H_TOTAL, displayTiming.h_total - 1); 216 217 uint16 blankStart = displayTiming.h_display; //displayTiming.h_sync_end; 218 uint16 blankEnd = displayTiming.h_sync_start;//displayTiming.h_total; 219 // write32(regOffset + D1CRTC_H_BLANK_START_END, 220 // blankStart | (blankEnd << 16)); 221 222 write32(regOffset + D1CRTC_H_SYNC_A, 223 (displayTiming.h_sync_end - displayTiming.h_sync_start) << 16); 224 //write32(regOffset + D1CRTC_H_SYNC_A_CNTL, Mode->Flags & V_NHSYNC); 225 //!!!write32(regOffset + D1CRTC_H_SYNC_A_CNTL, V_NHSYNC); 226 227 /* Vertical */ 228 write32(regOffset + D1CRTC_V_TOTAL, displayTiming.v_total - 1); 229 230 blankStart = displayTiming.v_display;//displayTiming.v_sync_end; 231 blankEnd = displayTiming.v_sync_start;//displayTiming.v_total; 232 // write32(regOffset + D1CRTC_V_BLANK_START_END, 233 // blankStart | (blankEnd << 16)); 234 235 /* set interlaced */ 236 //if (Mode->Flags & V_INTERLACE) { 237 if (0) { 238 write32(regOffset + D1CRTC_INTERLACE_CONTROL, 0x1); 239 write32(regOffset + D1MODE_DATA_FORMAT, 0x1); 240 } else { 241 write32(regOffset + D1CRTC_INTERLACE_CONTROL, 0x0); 242 write32(regOffset + D1MODE_DATA_FORMAT, 0x0); 243 } 244 245 write32(regOffset + D1CRTC_V_SYNC_A, 246 (displayTiming.v_sync_end - displayTiming.v_sync_start) << 16); 247 //write32(regOffset + D1CRTC_V_SYNC_A_CNTL, Mode->Flags & V_NVSYNC); 248 //!!!write32(regOffset + D1CRTC_V_SYNC_A_CNTL, V_NVSYNC); 249 250 /* set D1CRTC_HORZ_COUNT_BY2_EN to 0; should only be set to 1 on 30bpp DVI modes */ 251 write32AtMask(regOffset + D1CRTC_COUNT_CONTROL, 0x0, 0x1); 252 253 } 254 255 256 static void 257 DxModeScale(display_mode *mode) 258 { 259 uint32 regOffset = D1_REG_OFFSET; 260 261 /* D1Mode registers */ 262 write32(regOffset + D1MODE_VIEWPORT_SIZE, 263 mode->timing.v_display | (mode->timing.h_display << 16)); 264 write32(regOffset + D1MODE_VIEWPORT_START, 0); 265 266 /* write32(regOffset + D1MODE_EXT_OVERSCAN_LEFT_RIGHT, 267 (Overscan.OverscanLeft << 16) | Overscan.OverscanRight); 268 write32(regOffset + D1MODE_EXT_OVERSCAN_TOP_BOTTOM, 269 (Overscan.OverscanTop << 16) | Overscan.OverscanBottom); 270 */ 271 write32(regOffset + D1SCL_ENABLE, 0); 272 write32(regOffset + D1SCL_TAP_CONTROL, 0); 273 write32(regOffset + D1MODE_CENTER, 0); 274 } 275 276 277 status_t 278 radeon_set_display_mode(display_mode *mode) 279 { 280 DxModeSet(mode); 281 282 DxModeScale(mode); 283 284 uint32 colorMode, bytesPerRow, bitsPerPixel; 285 get_color_space_format(*mode, colorMode, bytesPerRow, bitsPerPixel); 286 287 uint32 regOffset = D1_REG_OFFSET; 288 289 write32AtMask(regOffset + D1GRPH_ENABLE, 1, 0x00000001); 290 291 /* disable R/B swap, disable tiling, disable 16bit alpha, etc. */ 292 write32(regOffset + D1GRPH_CONTROL, 0); 293 294 switch (mode->space) { 295 case B_CMAP8: 296 write32AtMask(regOffset + D1GRPH_CONTROL, 0, 0x00000703); 297 break; 298 case B_RGB15_LITTLE: 299 write32AtMask(regOffset + D1GRPH_CONTROL, 0x000001, 0x00000703); 300 break; 301 case B_RGB16_LITTLE: 302 write32AtMask(regOffset + D1GRPH_CONTROL, 0x000101, 0x00000703); 303 break; 304 case B_RGB24_LITTLE: 305 case B_RGB32_LITTLE: 306 default: 307 write32AtMask(regOffset + D1GRPH_CONTROL, 0x000002, 0x00000703); 308 break; 309 /* TODO: 64bpp ;p */ 310 } 311 312 /* Make sure that we are not swapping colours around */ 313 //if (rhdPtr->ChipSet > RHD_R600) 314 write32(regOffset + D1GRPH_SWAP_CNTL, 0); 315 /* R5xx - RS690 case is GRPH_CONTROL bit 16 */ 316 317 #define R6XX_CONFIG_FB_BASE 0x542C /* AKA CONFIG_F0_BASE */ 318 319 uint32 fbIntAddress = read32(R6XX_CONFIG_FB_BASE); 320 321 uint32 offset = gInfo->shared_info->frame_buffer_offset; 322 write32(regOffset + D1GRPH_PRIMARY_SURFACE_ADDRESS, 323 fbIntAddress + offset); 324 write32(regOffset + D1GRPH_PITCH, bytesPerRow / 4); 325 write32(regOffset + D1GRPH_SURFACE_OFFSET_X, 0); 326 write32(regOffset + D1GRPH_SURFACE_OFFSET_Y, 0); 327 write32(regOffset + D1GRPH_X_START, 0); 328 write32(regOffset + D1GRPH_Y_START, 0); 329 write32(regOffset + D1GRPH_X_END, mode->virtual_width); 330 write32(regOffset + D1GRPH_Y_END, mode->virtual_height); 331 332 /* D1Mode registers */ 333 write32(regOffset + D1MODE_DESKTOP_HEIGHT, mode->virtual_height); 334 335 // update shared info 336 gInfo->shared_info->bytes_per_row = bytesPerRow; 337 gInfo->shared_info->current_mode = *mode; 338 gInfo->shared_info->bits_per_pixel = bitsPerPixel; 339 340 return B_OK; 341 } 342 343 344 status_t 345 radeon_get_display_mode(display_mode *_currentMode) 346 { 347 TRACE(("radeon_get_display_mode()\n")); 348 349 *_currentMode = gDisplayMode; 350 return B_OK; 351 } 352 353 354 status_t 355 radeon_get_frame_buffer_config(frame_buffer_config *config) 356 { 357 TRACE(("radeon_get_frame_buffer_config()\n")); 358 359 uint32 offset = gInfo->shared_info->frame_buffer_offset; 360 361 config->frame_buffer = gInfo->shared_info->graphics_memory + offset; 362 config->frame_buffer_dma 363 = (uint8 *)gInfo->shared_info->physical_graphics_memory + offset; 364 config->bytes_per_row = gInfo->shared_info->bytes_per_row; 365 366 return B_OK; 367 } 368 369 370 status_t 371 radeon_get_pixel_clock_limits(display_mode *mode, uint32 *_low, uint32 *_high) 372 { 373 TRACE(("radeon_get_pixel_clock_limits()\n")); 374 /* 375 if (_low != NULL) { 376 // lower limit of about 48Hz vertical refresh 377 uint32 totalClocks = (uint32)mode->timing.h_total * (uint32)mode->timing.v_total; 378 uint32 low = (totalClocks * 48L) / 1000L; 379 if (low < gInfo->shared_info->pll_info.min_frequency) 380 low = gInfo->shared_info->pll_info.min_frequency; 381 else if (low > gInfo->shared_info->pll_info.max_frequency) 382 return B_ERROR; 383 384 *_low = low; 385 } 386 387 if (_high != NULL) 388 *_high = gInfo->shared_info->pll_info.max_frequency; 389 */ 390 *_low = 48L; 391 *_high = 100 * 1000000L; 392 return B_OK; 393 } 394 395 396