1a90ebd77SClemens Zeidler /* 2d5c3acacSAlexander von Gluck IV * Copyright 2006-2011, Haiku, Inc. All Rights Reserved. 3a90ebd77SClemens Zeidler * Distributed under the terms of the MIT License. 4a90ebd77SClemens Zeidler * 5a90ebd77SClemens Zeidler * Support for i915 chipset and up based on the X driver, 6a90ebd77SClemens Zeidler * Copyright 2006-2007 Intel Corporation. 7a90ebd77SClemens Zeidler * 8a90ebd77SClemens Zeidler * Authors: 9a90ebd77SClemens Zeidler * Axel Dörfler, axeld@pinc-software.de 10d5c3acacSAlexander von Gluck IV * Alexander von Gluck, kallisti5@unixzen.com 11a90ebd77SClemens Zeidler */ 12a90ebd77SClemens Zeidler 13a90ebd77SClemens Zeidler 14a90ebd77SClemens Zeidler #include "accelerant_protos.h" 15a90ebd77SClemens Zeidler #include "accelerant.h" 16a90ebd77SClemens Zeidler #include "utility.h" 17d5c3acacSAlexander von Gluck IV #include "mode.h" 18a90ebd77SClemens Zeidler 19a90ebd77SClemens Zeidler #include <stdio.h> 20a90ebd77SClemens Zeidler #include <string.h> 21a90ebd77SClemens Zeidler #include <math.h> 22a90ebd77SClemens Zeidler 23192781ddSAlexander von Gluck IV #include <create_display_modes.h> 24192781ddSAlexander von Gluck IV 25a90ebd77SClemens Zeidler 26a90ebd77SClemens Zeidler #define TRACE_MODE 27a90ebd77SClemens Zeidler #ifdef TRACE_MODE 28a90ebd77SClemens Zeidler extern "C" void _sPrintf(const char *format, ...); 29d5c3acacSAlexander von Gluck IV # define TRACE(x...) _sPrintf("radeon_hd: " x) 30a90ebd77SClemens Zeidler #else 31d5c3acacSAlexander von Gluck IV # define TRACE(x...) ; 32a90ebd77SClemens Zeidler #endif 33a90ebd77SClemens Zeidler 34a90ebd77SClemens Zeidler 35a90ebd77SClemens Zeidler status_t 36a90ebd77SClemens Zeidler create_mode_list(void) 37a90ebd77SClemens Zeidler { 38192781ddSAlexander von Gluck IV const color_space kRadeonHDSpaces[] = {B_RGB32_LITTLE, B_RGB24_LITTLE, 39192781ddSAlexander von Gluck IV B_RGB16_LITTLE, B_RGB15_LITTLE, B_CMAP8}; 40a90ebd77SClemens Zeidler 41192781ddSAlexander von Gluck IV gInfo->mode_list_area = create_display_modes("radeon HD modes", 422613175eSAlexander von Gluck IV gInfo->shared_info->has_edid ? &gInfo->shared_info->edid_info : NULL, 432613175eSAlexander von Gluck IV NULL, 0, kRadeonHDSpaces, 44192781ddSAlexander von Gluck IV sizeof(kRadeonHDSpaces) / sizeof(kRadeonHDSpaces[0]), 45192781ddSAlexander von Gluck IV is_mode_supported, &gInfo->mode_list, &gInfo->shared_info->mode_count); 46192781ddSAlexander von Gluck IV if (gInfo->mode_list_area < B_OK) 47192781ddSAlexander von Gluck IV return gInfo->mode_list_area; 48a90ebd77SClemens Zeidler 49192781ddSAlexander von Gluck IV gInfo->shared_info->mode_list_area = gInfo->mode_list_area; 50d5c3acacSAlexander von Gluck IV 51a90ebd77SClemens Zeidler return B_OK; 52a90ebd77SClemens Zeidler } 53a90ebd77SClemens Zeidler 54a90ebd77SClemens Zeidler 55a90ebd77SClemens Zeidler // #pragma mark - 56a90ebd77SClemens Zeidler 57a90ebd77SClemens Zeidler 58a90ebd77SClemens Zeidler uint32 59a90ebd77SClemens Zeidler radeon_accelerant_mode_count(void) 60a90ebd77SClemens Zeidler { 61333bd770SAlexander von Gluck IV TRACE("%s\n", __func__); 62a90ebd77SClemens Zeidler 63a90ebd77SClemens Zeidler return gInfo->shared_info->mode_count; 64a90ebd77SClemens Zeidler } 65a90ebd77SClemens Zeidler 66a90ebd77SClemens Zeidler 67a90ebd77SClemens Zeidler status_t 68a90ebd77SClemens Zeidler radeon_get_mode_list(display_mode *modeList) 69a90ebd77SClemens Zeidler { 70333bd770SAlexander von Gluck IV TRACE("%s\n", __func__); 71a90ebd77SClemens Zeidler memcpy(modeList, gInfo->mode_list, 72a90ebd77SClemens Zeidler gInfo->shared_info->mode_count * sizeof(display_mode)); 73a90ebd77SClemens Zeidler return B_OK; 74a90ebd77SClemens Zeidler } 75a90ebd77SClemens Zeidler 76a90ebd77SClemens Zeidler 7788bfef92SAlexander von Gluck IV status_t 7888bfef92SAlexander von Gluck IV radeon_get_edid_info(void* info, size_t size, uint32* edid_version) 7988bfef92SAlexander von Gluck IV { 8088bfef92SAlexander von Gluck IV TRACE("%s\n", __func__); 8188bfef92SAlexander von Gluck IV if (!gInfo->shared_info->has_edid) 8288bfef92SAlexander von Gluck IV return B_ERROR; 8388bfef92SAlexander von Gluck IV if (size < sizeof(struct edid1_info)) 8488bfef92SAlexander von Gluck IV return B_BUFFER_OVERFLOW; 8588bfef92SAlexander von Gluck IV 8688bfef92SAlexander von Gluck IV memcpy(info, &gInfo->shared_info->edid_info, sizeof(struct edid1_info)); 8788bfef92SAlexander von Gluck IV *edid_version = EDID_VERSION_1; 8888bfef92SAlexander von Gluck IV 8988bfef92SAlexander von Gluck IV return B_OK; 9088bfef92SAlexander von Gluck IV } 9188bfef92SAlexander von Gluck IV 9288bfef92SAlexander von Gluck IV 93a90ebd77SClemens Zeidler static void 94a90ebd77SClemens Zeidler get_color_space_format(const display_mode &mode, uint32 &colorMode, 95a90ebd77SClemens Zeidler uint32 &bytesPerRow, uint32 &bitsPerPixel) 96a90ebd77SClemens Zeidler { 97a90ebd77SClemens Zeidler uint32 bytesPerPixel; 98a90ebd77SClemens Zeidler 99a90ebd77SClemens Zeidler switch (mode.space) { 100a90ebd77SClemens Zeidler case B_RGB32_LITTLE: 101a90ebd77SClemens Zeidler colorMode = DISPLAY_CONTROL_RGB32; 102a90ebd77SClemens Zeidler bytesPerPixel = 4; 103a90ebd77SClemens Zeidler bitsPerPixel = 32; 104a90ebd77SClemens Zeidler break; 105a90ebd77SClemens Zeidler case B_RGB16_LITTLE: 106a90ebd77SClemens Zeidler colorMode = DISPLAY_CONTROL_RGB16; 107a90ebd77SClemens Zeidler bytesPerPixel = 2; 108a90ebd77SClemens Zeidler bitsPerPixel = 16; 109a90ebd77SClemens Zeidler break; 110a90ebd77SClemens Zeidler case B_RGB15_LITTLE: 111a90ebd77SClemens Zeidler colorMode = DISPLAY_CONTROL_RGB15; 112a90ebd77SClemens Zeidler bytesPerPixel = 2; 113a90ebd77SClemens Zeidler bitsPerPixel = 15; 114a90ebd77SClemens Zeidler break; 115a90ebd77SClemens Zeidler case B_CMAP8: 116a90ebd77SClemens Zeidler default: 117a90ebd77SClemens Zeidler colorMode = DISPLAY_CONTROL_CMAP8; 118a90ebd77SClemens Zeidler bytesPerPixel = 1; 119a90ebd77SClemens Zeidler bitsPerPixel = 8; 120a90ebd77SClemens Zeidler break; 121a90ebd77SClemens Zeidler } 122a90ebd77SClemens Zeidler 123a90ebd77SClemens Zeidler bytesPerRow = mode.virtual_width * bytesPerPixel; 124a90ebd77SClemens Zeidler } 125a90ebd77SClemens Zeidler 12647ad511fSAlexander von Gluck IV 127cf546fa0SAlexander von Gluck IV // Blacks the screen out, useful for mode setting 1285f6744a8SAlexander von Gluck IV static void 129f2fe29a0SAlexander von Gluck IV CardBlankSet(uint8 crtid, bool blank) 1305f6744a8SAlexander von Gluck IV { 131f2fe29a0SAlexander von Gluck IV int blackColorReg 1323fe78837SAlexander von Gluck IV = crtid == 1 ? D2CRTC_BLACK_COLOR : D1CRTC_BLACK_COLOR; 133f2fe29a0SAlexander von Gluck IV int blankControlReg 1343fe78837SAlexander von Gluck IV = crtid == 1 ? D2CRTC_BLANK_CONTROL : D1CRTC_BLANK_CONTROL; 1355f6744a8SAlexander von Gluck IV 136aa2a6e33SAlexander von Gluck IV Write32(CRT, blackColorReg, 0); 137aa2a6e33SAlexander von Gluck IV Write32Mask(CRT, blankControlReg, blank ? 1 << 8 : 0, 1 << 8); 1385f6744a8SAlexander von Gluck IV } 139cf546fa0SAlexander von Gluck IV 140cf546fa0SAlexander von Gluck IV 141cf546fa0SAlexander von Gluck IV static void 142*95e1d7e8SAlexander von Gluck IV CardFBSet(uint8 crtid, display_mode *mode) 143cf546fa0SAlexander von Gluck IV { 144*95e1d7e8SAlexander von Gluck IV register_info* regs = gDisplay[crtid]->regs; 145*95e1d7e8SAlexander von Gluck IV 146cf546fa0SAlexander von Gluck IV uint32 colorMode; 147cf546fa0SAlexander von Gluck IV uint32 bytesPerRow; 148cf546fa0SAlexander von Gluck IV uint32 bitsPerPixel; 149cf546fa0SAlexander von Gluck IV 150cf546fa0SAlexander von Gluck IV get_color_space_format(*mode, colorMode, bytesPerRow, bitsPerPixel); 151cf546fa0SAlexander von Gluck IV 152*95e1d7e8SAlexander von Gluck IV 15384bcfa3dSAlexander von Gluck IV #if 0 15484bcfa3dSAlexander von Gluck IV // TMDSAllIdle // DVI / HDMI 15584bcfa3dSAlexander von Gluck IV // LVTMAAllIdle // DVI 15684bcfa3dSAlexander von Gluck IV DACAllIdle(); 15784bcfa3dSAlexander von Gluck IV 15884bcfa3dSAlexander von Gluck IV // Set the inital frame buffer location in the memory controler 15984bcfa3dSAlexander von Gluck IV uint32 mcFbSize; 16084bcfa3dSAlexander von Gluck IV MCFBLocation(0, &mcFbSize); 16184bcfa3dSAlexander von Gluck IV MCFBSetup(Read32(OUT, R6XX_CONFIG_FB_BASE), mcFbSize); 16284bcfa3dSAlexander von Gluck IV #endif 16384bcfa3dSAlexander von Gluck IV 164*95e1d7e8SAlexander von Gluck IV Write32(CRT, regs->grphUpdate, (1<<16)); 165b6c5f468SAlexander von Gluck IV // Lock for update (isn't this normally the other way around on VGA? 166e7e76b29SAlexander von Gluck IV 167b6c5f468SAlexander von Gluck IV // framebuffersize = w * h * bpp = fb bits / 8 = bytes needed 168b6c5f468SAlexander von Gluck IV uint64_t fbAddress = gInfo->shared_info->frame_buffer_phys; 169b6c5f468SAlexander von Gluck IV 170b6c5f468SAlexander von Gluck IV // Tell GPU which frame buffer address to draw from 171*95e1d7e8SAlexander von Gluck IV Write32(CRT, regs->grphPrimarySurfaceAddr, 172b6c5f468SAlexander von Gluck IV fbAddress & 0xffffffff); 173*95e1d7e8SAlexander von Gluck IV Write32(CRT, regs->grphSecondarySurfaceAddr, 174b6c5f468SAlexander von Gluck IV fbAddress & 0xffffffff); 175b6c5f468SAlexander von Gluck IV 176b6c5f468SAlexander von Gluck IV if (gInfo->shared_info->device_chipset >= (RADEON_R700 | 0x70)) { 177*95e1d7e8SAlexander von Gluck IV Write32(CRT, regs->grphPrimarySurfaceAddrHigh, 178b6c5f468SAlexander von Gluck IV (fbAddress >> 32) & 0xf); 179*95e1d7e8SAlexander von Gluck IV Write32(CRT, regs->grphSecondarySurfaceAddrHigh, 180b6c5f468SAlexander von Gluck IV (fbAddress >> 32) & 0xf); 181b6c5f468SAlexander von Gluck IV } 182b6c5f468SAlexander von Gluck IV 183*95e1d7e8SAlexander von Gluck IV Write32(CRT, regs->grphControl, 0); 184b6c5f468SAlexander von Gluck IV // Reset stored depth, format, etc 185cf546fa0SAlexander von Gluck IV 18651a43d0fSAlexander von Gluck IV // set color mode on video card 187cf546fa0SAlexander von Gluck IV switch (mode->space) { 188cf546fa0SAlexander von Gluck IV case B_CMAP8: 189*95e1d7e8SAlexander von Gluck IV Write32Mask(CRT, regs->grphControl, 190bd34b2f7SAlexander von Gluck IV 0, 0x00000703); 191cf546fa0SAlexander von Gluck IV break; 192cf546fa0SAlexander von Gluck IV case B_RGB15_LITTLE: 193*95e1d7e8SAlexander von Gluck IV Write32Mask(CRT, regs->grphControl, 194bd34b2f7SAlexander von Gluck IV 0x000001, 0x00000703); 195cf546fa0SAlexander von Gluck IV break; 196cf546fa0SAlexander von Gluck IV case B_RGB16_LITTLE: 197*95e1d7e8SAlexander von Gluck IV Write32Mask(CRT, regs->grphControl, 198bd34b2f7SAlexander von Gluck IV 0x000101, 0x00000703); 199cf546fa0SAlexander von Gluck IV break; 200cf546fa0SAlexander von Gluck IV case B_RGB24_LITTLE: 201cf546fa0SAlexander von Gluck IV case B_RGB32_LITTLE: 202cf546fa0SAlexander von Gluck IV default: 203*95e1d7e8SAlexander von Gluck IV Write32Mask(CRT, regs->grphControl, 204bd34b2f7SAlexander von Gluck IV 0x000002, 0x00000703); 205cf546fa0SAlexander von Gluck IV break; 206cf546fa0SAlexander von Gluck IV } 207cf546fa0SAlexander von Gluck IV 208*95e1d7e8SAlexander von Gluck IV Write32(CRT, regs->grphSwapControl, 0); 209cf546fa0SAlexander von Gluck IV // only for chipsets > r600 210cf546fa0SAlexander von Gluck IV // R5xx - RS690 case is GRPH_CONTROL bit 16 211cf546fa0SAlexander von Gluck IV 212*95e1d7e8SAlexander von Gluck IV Write32Mask(CRT, regs->grphEnable, 1, 0x00000001); 213b6c5f468SAlexander von Gluck IV // Enable graphics 2143be5e036SAlexander von Gluck IV 215*95e1d7e8SAlexander von Gluck IV Write32(CRT, regs->grphSurfaceOffsetX, 0); 216*95e1d7e8SAlexander von Gluck IV Write32(CRT, regs->grphSurfaceOffsetY, 0); 217*95e1d7e8SAlexander von Gluck IV Write32(CRT, regs->grphXStart, 0); 218*95e1d7e8SAlexander von Gluck IV Write32(CRT, regs->grphYStart, 0); 219*95e1d7e8SAlexander von Gluck IV Write32(CRT, regs->grphXEnd, mode->virtual_width); 220*95e1d7e8SAlexander von Gluck IV Write32(CRT, regs->grphYEnd, mode->virtual_height); 221*95e1d7e8SAlexander von Gluck IV Write32(CRT, regs->grphPitch, bytesPerRow / 4); 222cf546fa0SAlexander von Gluck IV 223*95e1d7e8SAlexander von Gluck IV Write32(CRT, regs->modeDesktopHeight, mode->virtual_height); 224eb5c4b07SAlexander von Gluck IV 225*95e1d7e8SAlexander von Gluck IV Write32(CRT, regs->grphUpdate, 0); 226b6c5f468SAlexander von Gluck IV // Unlock changed registers 227cf546fa0SAlexander von Gluck IV 228cf546fa0SAlexander von Gluck IV // update shared info 229cf546fa0SAlexander von Gluck IV gInfo->shared_info->bytes_per_row = bytesPerRow; 230cf546fa0SAlexander von Gluck IV gInfo->shared_info->current_mode = *mode; 231cf546fa0SAlexander von Gluck IV gInfo->shared_info->bits_per_pixel = bitsPerPixel; 232cf546fa0SAlexander von Gluck IV } 233cf546fa0SAlexander von Gluck IV 234cf546fa0SAlexander von Gluck IV 235cf546fa0SAlexander von Gluck IV static void 236*95e1d7e8SAlexander von Gluck IV CardModeSet(uint8 crtid, display_mode *mode) 237cf546fa0SAlexander von Gluck IV { 238a90ebd77SClemens Zeidler display_timing& displayTiming = mode->timing; 239*95e1d7e8SAlexander von Gluck IV register_info* regs = gDisplay[crtid]->regs; 240a90ebd77SClemens Zeidler 241192781ddSAlexander von Gluck IV TRACE("%s called to do %dx%d\n", 242192781ddSAlexander von Gluck IV __func__, displayTiming.h_display, displayTiming.v_display); 243a90ebd77SClemens Zeidler 244192781ddSAlexander von Gluck IV // enable read requests 245*95e1d7e8SAlexander von Gluck IV Write32Mask(CRT, regs->grphControl, 0, 0x01000000); 246a90ebd77SClemens Zeidler 247192781ddSAlexander von Gluck IV // *** Horizontal 248*95e1d7e8SAlexander von Gluck IV Write32(CRT, regs->crtHTotal, 2495f6744a8SAlexander von Gluck IV displayTiming.h_total - 1); 250a90ebd77SClemens Zeidler 251f2fe29a0SAlexander von Gluck IV // Blanking 252f2fe29a0SAlexander von Gluck IV uint16 blankStart = displayTiming.h_total 253f2fe29a0SAlexander von Gluck IV + displayTiming.h_display - displayTiming.h_sync_start; 254f2fe29a0SAlexander von Gluck IV uint16 blankEnd = displayTiming.h_total - displayTiming.h_sync_start; 255192781ddSAlexander von Gluck IV 256*95e1d7e8SAlexander von Gluck IV Write32(CRT, regs->crtHBlank, 257e7e76b29SAlexander von Gluck IV blankStart | (blankEnd << 16)); 258a90ebd77SClemens Zeidler 259*95e1d7e8SAlexander von Gluck IV Write32(CRT, regs->crtHSync, 260a90ebd77SClemens Zeidler (displayTiming.h_sync_end - displayTiming.h_sync_start) << 16); 261a90ebd77SClemens Zeidler 2623be5e036SAlexander von Gluck IV // set flag for neg. H sync. M76 Register Reference Guide 2-256 263*95e1d7e8SAlexander von Gluck IV Write32Mask(CRT, regs->crtHPolarity, 2643be5e036SAlexander von Gluck IV displayTiming.flags & B_POSITIVE_HSYNC ? 0 : 1, 0x1); 265192781ddSAlexander von Gluck IV 266192781ddSAlexander von Gluck IV // *** Vertical 267*95e1d7e8SAlexander von Gluck IV Write32(CRT, regs->crtVTotal, 2685f6744a8SAlexander von Gluck IV displayTiming.v_total - 1); 269a90ebd77SClemens Zeidler 270f2fe29a0SAlexander von Gluck IV blankStart = displayTiming.v_total 271f2fe29a0SAlexander von Gluck IV + displayTiming.v_display - displayTiming.v_sync_start; 272f2fe29a0SAlexander von Gluck IV blankEnd = displayTiming.v_total - displayTiming.v_sync_start; 273a90ebd77SClemens Zeidler 274*95e1d7e8SAlexander von Gluck IV Write32(CRT, regs->crtVBlank, 275e7e76b29SAlexander von Gluck IV blankStart | (blankEnd << 16)); 276192781ddSAlexander von Gluck IV 277192781ddSAlexander von Gluck IV // Set Interlace if specified within mode line 278192781ddSAlexander von Gluck IV if (displayTiming.flags & B_TIMING_INTERLACED) { 279*95e1d7e8SAlexander von Gluck IV Write32(CRT, regs->crtInterlace, 0x1); 280*95e1d7e8SAlexander von Gluck IV Write32(CRT, regs->modeDataFormat, 0x1); 281a90ebd77SClemens Zeidler } else { 282*95e1d7e8SAlexander von Gluck IV Write32(CRT, regs->crtInterlace, 0x0); 283*95e1d7e8SAlexander von Gluck IV Write32(CRT, regs->modeDataFormat, 0x0); 284a90ebd77SClemens Zeidler } 285a90ebd77SClemens Zeidler 286*95e1d7e8SAlexander von Gluck IV Write32(CRT, regs->crtVSync, 287a90ebd77SClemens Zeidler (displayTiming.v_sync_end - displayTiming.v_sync_start) << 16); 288192781ddSAlexander von Gluck IV 2893be5e036SAlexander von Gluck IV // set flag for neg. V sync. M76 Register Reference Guide 2-258 290*95e1d7e8SAlexander von Gluck IV Write32Mask(CRT, regs->crtVPolarity, 291d1d65a79SAlexander von Gluck IV displayTiming.flags & B_POSITIVE_VSYNC ? 0 : 1, 0x1); 292a90ebd77SClemens Zeidler 29347ad511fSAlexander von Gluck IV /* set D1CRTC_HORZ_COUNT_BY2_EN to 0; 29447ad511fSAlexander von Gluck IV should only be set to 1 on 30bpp DVI modes 29547ad511fSAlexander von Gluck IV */ 296*95e1d7e8SAlexander von Gluck IV Write32Mask(CRT, regs->crtCountControl, 0x0, 0x1); 297a90ebd77SClemens Zeidler } 298a90ebd77SClemens Zeidler 299a90ebd77SClemens Zeidler 300d5009951SClemens Zeidler static void 301*95e1d7e8SAlexander von Gluck IV CardModeScale(uint8 crtid, display_mode *mode) 302d5009951SClemens Zeidler { 303*95e1d7e8SAlexander von Gluck IV register_info* regs = gDisplay[crtid]->regs; 304*95e1d7e8SAlexander von Gluck IV 305b6c5f468SAlexander von Gluck IV // No scaling 306*95e1d7e8SAlexander von Gluck IV Write32(CRT, regs->sclUpdate, (1<<16));// Lock 307d5009951SClemens Zeidler 308f2fe29a0SAlexander von Gluck IV #if 0 309aa2a6e33SAlexander von Gluck IV Write32(CRT, D1MODE_EXT_OVERSCAN_LEFT_RIGHT, 310d1d65a79SAlexander von Gluck IV (OVERSCAN << 16) | OVERSCAN); // LEFT | RIGHT 311aa2a6e33SAlexander von Gluck IV Write32(CRT, D1MODE_EXT_OVERSCAN_TOP_BOTTOM, 312d1d65a79SAlexander von Gluck IV (OVERSCAN << 16) | OVERSCAN); // TOP | BOTTOM 313f2fe29a0SAlexander von Gluck IV #endif 3142cc7e38cSAlexander von Gluck IV 315*95e1d7e8SAlexander von Gluck IV Write32(CRT, regs->viewportStart, 0); 316*95e1d7e8SAlexander von Gluck IV Write32(CRT, regs->viewportSize, 317b6c5f468SAlexander von Gluck IV mode->timing.v_display | (mode->timing.h_display << 16)); 318*95e1d7e8SAlexander von Gluck IV Write32(CRT, regs->sclEnable, 0); 319*95e1d7e8SAlexander von Gluck IV Write32(CRT, regs->sclTapControl, 0); 320*95e1d7e8SAlexander von Gluck IV Write32(CRT, regs->modeCenter, 2); 321b6c5f468SAlexander von Gluck IV // D1MODE_DATA_FORMAT? 322*95e1d7e8SAlexander von Gluck IV Write32(CRT, regs->sclUpdate, 0); // Unlock 323d5009951SClemens Zeidler } 324d5009951SClemens Zeidler 325d5009951SClemens Zeidler 326a90ebd77SClemens Zeidler status_t 327a90ebd77SClemens Zeidler radeon_set_display_mode(display_mode *mode) 328a90ebd77SClemens Zeidler { 329*95e1d7e8SAlexander von Gluck IV uint8 display_id = 0; 330a90ebd77SClemens Zeidler 331*95e1d7e8SAlexander von Gluck IV CardFBSet(display_id, mode); 332*95e1d7e8SAlexander von Gluck IV CardModeSet(display_id, mode); 333*95e1d7e8SAlexander von Gluck IV CardModeScale(display_id, mode); 334e7e76b29SAlexander von Gluck IV 335*95e1d7e8SAlexander von Gluck IV // If this is DAC, set our PLL 336*95e1d7e8SAlexander von Gluck IV if ((gDisplay[display_id]->connection_type & CONNECTION_DAC) != 0) { 337*95e1d7e8SAlexander von Gluck IV PLLSet(gDisplay[display_id]->connection_id, mode->timing.pixel_clock); 338*95e1d7e8SAlexander von Gluck IV DACSet(gDisplay[display_id]->connection_id, display_id); 339f2fe29a0SAlexander von Gluck IV 340f2fe29a0SAlexander von Gluck IV // TODO : Shutdown unused PLL/DAC 341f2fe29a0SAlexander von Gluck IV 342f2fe29a0SAlexander von Gluck IV // Power up the output 343*95e1d7e8SAlexander von Gluck IV PLLPower(gDisplay[display_id]->connection_id, RHD_POWER_ON); 344*95e1d7e8SAlexander von Gluck IV DACPower(gDisplay[display_id]->connection_id, RHD_POWER_ON); 345*95e1d7e8SAlexander von Gluck IV } 346f2fe29a0SAlexander von Gluck IV 347f2fe29a0SAlexander von Gluck IV // Ensure screen isn't blanked 348*95e1d7e8SAlexander von Gluck IV CardBlankSet(display_id, false); 3496604b1b6SAlexander von Gluck IV 350aa2a6e33SAlexander von Gluck IV int32 crtstatus = Read32(CRT, D1CRTC_STATUS); 3515f6744a8SAlexander von Gluck IV TRACE("CRT0 Status: 0x%X\n", crtstatus); 352f2fe29a0SAlexander von Gluck IV crtstatus = Read32(CRT, D2CRTC_STATUS); 353f2fe29a0SAlexander von Gluck IV TRACE("CRT1 Status: 0x%X\n", crtstatus); 3543be5e036SAlexander von Gluck IV 355a90ebd77SClemens Zeidler return B_OK; 356a90ebd77SClemens Zeidler } 357a90ebd77SClemens Zeidler 358a90ebd77SClemens Zeidler 359a90ebd77SClemens Zeidler status_t 360a90ebd77SClemens Zeidler radeon_get_display_mode(display_mode *_currentMode) 361a90ebd77SClemens Zeidler { 362d5c3acacSAlexander von Gluck IV TRACE("%s\n", __func__); 363a90ebd77SClemens Zeidler 364192781ddSAlexander von Gluck IV *_currentMode = gInfo->shared_info->current_mode; 365a90ebd77SClemens Zeidler return B_OK; 366a90ebd77SClemens Zeidler } 367a90ebd77SClemens Zeidler 368a90ebd77SClemens Zeidler 369a90ebd77SClemens Zeidler status_t 370a90ebd77SClemens Zeidler radeon_get_frame_buffer_config(frame_buffer_config *config) 371a90ebd77SClemens Zeidler { 372d5c3acacSAlexander von Gluck IV TRACE("%s\n", __func__); 373a90ebd77SClemens Zeidler 3743be5e036SAlexander von Gluck IV config->frame_buffer = gInfo->shared_info->frame_buffer; 3753be5e036SAlexander von Gluck IV config->frame_buffer_dma = (uint8 *)gInfo->shared_info->frame_buffer_phys; 37651a43d0fSAlexander von Gluck IV 377a90ebd77SClemens Zeidler config->bytes_per_row = gInfo->shared_info->bytes_per_row; 378a90ebd77SClemens Zeidler 379a90ebd77SClemens Zeidler return B_OK; 380a90ebd77SClemens Zeidler } 381a90ebd77SClemens Zeidler 382a90ebd77SClemens Zeidler 383a90ebd77SClemens Zeidler status_t 384a90ebd77SClemens Zeidler radeon_get_pixel_clock_limits(display_mode *mode, uint32 *_low, uint32 *_high) 385a90ebd77SClemens Zeidler { 386d5c3acacSAlexander von Gluck IV TRACE("%s\n", __func__); 387e7e76b29SAlexander von Gluck IV 388a90ebd77SClemens Zeidler if (_low != NULL) { 389a90ebd77SClemens Zeidler // lower limit of about 48Hz vertical refresh 3905f6744a8SAlexander von Gluck IV uint32 totalClocks = (uint32)mode->timing.h_total 3915f6744a8SAlexander von Gluck IV *(uint32)mode->timing.v_total; 392a90ebd77SClemens Zeidler uint32 low = (totalClocks * 48L) / 1000L; 393e7e76b29SAlexander von Gluck IV 394a90ebd77SClemens Zeidler if (low < gInfo->shared_info->pll_info.min_frequency) 395a90ebd77SClemens Zeidler low = gInfo->shared_info->pll_info.min_frequency; 396a90ebd77SClemens Zeidler else if (low > gInfo->shared_info->pll_info.max_frequency) 397a90ebd77SClemens Zeidler return B_ERROR; 398a90ebd77SClemens Zeidler 399a90ebd77SClemens Zeidler *_low = low; 400a90ebd77SClemens Zeidler } 401a90ebd77SClemens Zeidler 402a90ebd77SClemens Zeidler if (_high != NULL) 403a90ebd77SClemens Zeidler *_high = gInfo->shared_info->pll_info.max_frequency; 404e7e76b29SAlexander von Gluck IV 405e7e76b29SAlexander von Gluck IV //*_low = 48L; 406e7e76b29SAlexander von Gluck IV //*_high = 100 * 1000000L; 407a90ebd77SClemens Zeidler return B_OK; 408a90ebd77SClemens Zeidler } 409a90ebd77SClemens Zeidler 410a90ebd77SClemens Zeidler 411192781ddSAlexander von Gluck IV bool 412192781ddSAlexander von Gluck IV is_mode_supported(display_mode *mode) 413192781ddSAlexander von Gluck IV { 414d1d65a79SAlexander von Gluck IV TRACE("MODE: %d ; %d %d %d %d ; %d %d %d %d\n", 415d1d65a79SAlexander von Gluck IV mode->timing.pixel_clock, mode->timing.h_display, 416d1d65a79SAlexander von Gluck IV mode->timing.h_sync_start, mode->timing.h_sync_end, 417d1d65a79SAlexander von Gluck IV mode->timing.h_total, mode->timing.v_display, 418d1d65a79SAlexander von Gluck IV mode->timing.v_sync_start, mode->timing.v_sync_end, 419d1d65a79SAlexander von Gluck IV mode->timing.v_total); 420d1d65a79SAlexander von Gluck IV 4211dac4469SAlexander von Gluck IV // Validate modeline is within a sane range 422192781ddSAlexander von Gluck IV if (is_mode_sane(mode) != B_OK) 423192781ddSAlexander von Gluck IV return false; 424192781ddSAlexander von Gluck IV 425*95e1d7e8SAlexander von Gluck IV // TODO : is_mode_supported on *which* display? 426d1d65a79SAlexander von Gluck IV uint32 crtid = 0; 4271dac4469SAlexander von Gluck IV 428d1d65a79SAlexander von Gluck IV // if we have edid info, check frequency adginst crt reported valid ranges 429d1d65a79SAlexander von Gluck IV if (gInfo->shared_info->has_edid) { 4301dac4469SAlexander von Gluck IV 431d1d65a79SAlexander von Gluck IV uint32 hfreq = mode->timing.pixel_clock / mode->timing.h_total; 432*95e1d7e8SAlexander von Gluck IV if (hfreq > gDisplay[crtid]->hfreq_max + 1 433*95e1d7e8SAlexander von Gluck IV || hfreq < gDisplay[crtid]->hfreq_min - 1) { 434d1d65a79SAlexander von Gluck IV TRACE("!!! hfreq : %d , hfreq_min : %d, hfreq_max : %d\n", 435*95e1d7e8SAlexander von Gluck IV hfreq, gDisplay[crtid]->hfreq_min, gDisplay[crtid]->hfreq_max); 436d1d65a79SAlexander von Gluck IV TRACE("!!! %dx%d falls outside of CRT %d's valid " 437d1d65a79SAlexander von Gluck IV "horizontal range.\n", mode->timing.h_display, 438d1d65a79SAlexander von Gluck IV mode->timing.v_display, crtid); 439d1d65a79SAlexander von Gluck IV return false; 440d1d65a79SAlexander von Gluck IV } 441d1d65a79SAlexander von Gluck IV 442d1d65a79SAlexander von Gluck IV uint32 vfreq = mode->timing.pixel_clock / ((mode->timing.v_total 443d1d65a79SAlexander von Gluck IV * mode->timing.h_total) / 1000); 444d1d65a79SAlexander von Gluck IV 445*95e1d7e8SAlexander von Gluck IV if (vfreq > gDisplay[crtid]->vfreq_max + 1 446*95e1d7e8SAlexander von Gluck IV || vfreq < gDisplay[crtid]->vfreq_min - 1) { 447d1d65a79SAlexander von Gluck IV TRACE("!!! vfreq : %d , vfreq_min : %d, vfreq_max : %d\n", 448*95e1d7e8SAlexander von Gluck IV vfreq, gDisplay[crtid]->vfreq_min, gDisplay[crtid]->vfreq_max); 449d1d65a79SAlexander von Gluck IV TRACE("!!! %dx%d falls outside of CRT %d's valid vertical range\n", 450d1d65a79SAlexander von Gluck IV mode->timing.h_display, mode->timing.v_display, crtid); 451d1d65a79SAlexander von Gluck IV return false; 452d1d65a79SAlexander von Gluck IV } 453d1d65a79SAlexander von Gluck IV TRACE("%dx%d is within CRT %d's valid frequency range\n", 454d1d65a79SAlexander von Gluck IV mode->timing.h_display, mode->timing.v_display, crtid); 455d1d65a79SAlexander von Gluck IV } 456192781ddSAlexander von Gluck IV 457192781ddSAlexander von Gluck IV return true; 458192781ddSAlexander von Gluck IV } 459192781ddSAlexander von Gluck IV 460192781ddSAlexander von Gluck IV 461d5c3acacSAlexander von Gluck IV /* 462d5c3acacSAlexander von Gluck IV * A quick sanity check of the provided display_mode 463d5c3acacSAlexander von Gluck IV */ 464d5c3acacSAlexander von Gluck IV status_t 465192781ddSAlexander von Gluck IV is_mode_sane(display_mode *mode) 466d5c3acacSAlexander von Gluck IV { 467333bd770SAlexander von Gluck IV // horizontal timing 468333bd770SAlexander von Gluck IV // validate h_sync_start is less then h_sync_end 469333bd770SAlexander von Gluck IV if (mode->timing.h_sync_start > mode->timing.h_sync_end) { 47091235829SAlexander von Gluck IV TRACE("%s: ERROR: (%dx%d) " 47191235829SAlexander von Gluck IV "received h_sync_start greater then h_sync_end!\n", 472333bd770SAlexander von Gluck IV __func__, mode->timing.h_display, mode->timing.v_display); 473333bd770SAlexander von Gluck IV return B_ERROR; 474333bd770SAlexander von Gluck IV } 475333bd770SAlexander von Gluck IV // validate h_total is greater then h_display 476333bd770SAlexander von Gluck IV if (mode->timing.h_total < mode->timing.h_display) { 47791235829SAlexander von Gluck IV TRACE("%s: ERROR: (%dx%d) " 47891235829SAlexander von Gluck IV "received h_total greater then h_display!\n", 479333bd770SAlexander von Gluck IV __func__, mode->timing.h_display, mode->timing.v_display); 480d5c3acacSAlexander von Gluck IV return B_ERROR; 481d5c3acacSAlexander von Gluck IV } 482d5c3acacSAlexander von Gluck IV 483333bd770SAlexander von Gluck IV // vertical timing 484333bd770SAlexander von Gluck IV // validate v_start is less then v_end 485333bd770SAlexander von Gluck IV if (mode->timing.v_sync_start > mode->timing.v_sync_end) { 48691235829SAlexander von Gluck IV TRACE("%s: ERROR: (%dx%d) " 48791235829SAlexander von Gluck IV "received v_sync_start greater then v_sync_end!\n", 488333bd770SAlexander von Gluck IV __func__, mode->timing.h_display, mode->timing.v_display); 489d5c3acacSAlexander von Gluck IV return B_ERROR; 490d5c3acacSAlexander von Gluck IV } 491333bd770SAlexander von Gluck IV // validate v_total is greater then v_display 492333bd770SAlexander von Gluck IV if (mode->timing.v_total < mode->timing.v_display) { 49391235829SAlexander von Gluck IV TRACE("%s: ERROR: (%dx%d) " 49491235829SAlexander von Gluck IV "received v_total greater then v_display!\n", 495333bd770SAlexander von Gluck IV __func__, mode->timing.h_display, mode->timing.v_display); 496d5c3acacSAlexander von Gluck IV return B_ERROR; 497d5c3acacSAlexander von Gluck IV } 498d5c3acacSAlexander von Gluck IV 49991235829SAlexander von Gluck IV // calculate refresh rate for given timings to whole int (in Hz) 50091235829SAlexander von Gluck IV int refresh = mode->timing.pixel_clock * 1000 50191235829SAlexander von Gluck IV / (mode->timing.h_total * mode->timing.v_total); 50291235829SAlexander von Gluck IV 50391235829SAlexander von Gluck IV if (refresh < 30 || refresh > 250) { 50491235829SAlexander von Gluck IV TRACE("%s: ERROR: (%dx%d) " 50591235829SAlexander von Gluck IV "refresh rate of %dHz is unlikely for any kind of monitor!\n", 50691235829SAlexander von Gluck IV __func__, mode->timing.h_display, mode->timing.v_display, refresh); 50791235829SAlexander von Gluck IV return B_ERROR; 50891235829SAlexander von Gluck IV } 50991235829SAlexander von Gluck IV 510d5c3acacSAlexander von Gluck IV return B_OK; 511d5c3acacSAlexander von Gluck IV } 512d5c3acacSAlexander von Gluck IV 513d1d65a79SAlexander von Gluck IV 514