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" 18*6ab8261bSAlexander von Gluck IV #include "display.h" 19a90ebd77SClemens Zeidler 20a90ebd77SClemens Zeidler #include <stdio.h> 21a90ebd77SClemens Zeidler #include <string.h> 22a90ebd77SClemens Zeidler #include <math.h> 23a90ebd77SClemens Zeidler 24192781ddSAlexander von Gluck IV #include <create_display_modes.h> 25192781ddSAlexander von Gluck IV 26a90ebd77SClemens Zeidler 27a90ebd77SClemens Zeidler #define TRACE_MODE 28a90ebd77SClemens Zeidler #ifdef TRACE_MODE 29a90ebd77SClemens Zeidler extern "C" void _sPrintf(const char *format, ...); 30d5c3acacSAlexander von Gluck IV # define TRACE(x...) _sPrintf("radeon_hd: " x) 31a90ebd77SClemens Zeidler #else 32d5c3acacSAlexander von Gluck IV # define TRACE(x...) ; 33a90ebd77SClemens Zeidler #endif 34a90ebd77SClemens Zeidler 35a90ebd77SClemens Zeidler 36a90ebd77SClemens Zeidler status_t 37a90ebd77SClemens Zeidler create_mode_list(void) 38a90ebd77SClemens Zeidler { 39192781ddSAlexander von Gluck IV const color_space kRadeonHDSpaces[] = {B_RGB32_LITTLE, B_RGB24_LITTLE, 40192781ddSAlexander von Gluck IV B_RGB16_LITTLE, B_RGB15_LITTLE, B_CMAP8}; 41a90ebd77SClemens Zeidler 42192781ddSAlexander von Gluck IV gInfo->mode_list_area = create_display_modes("radeon HD modes", 432613175eSAlexander von Gluck IV gInfo->shared_info->has_edid ? &gInfo->shared_info->edid_info : NULL, 442613175eSAlexander von Gluck IV NULL, 0, kRadeonHDSpaces, 45192781ddSAlexander von Gluck IV sizeof(kRadeonHDSpaces) / sizeof(kRadeonHDSpaces[0]), 46192781ddSAlexander von Gluck IV is_mode_supported, &gInfo->mode_list, &gInfo->shared_info->mode_count); 47192781ddSAlexander von Gluck IV if (gInfo->mode_list_area < B_OK) 48192781ddSAlexander von Gluck IV return gInfo->mode_list_area; 49a90ebd77SClemens Zeidler 50192781ddSAlexander von Gluck IV gInfo->shared_info->mode_list_area = gInfo->mode_list_area; 51d5c3acacSAlexander von Gluck IV 52a90ebd77SClemens Zeidler return B_OK; 53a90ebd77SClemens Zeidler } 54a90ebd77SClemens Zeidler 55a90ebd77SClemens Zeidler 56a90ebd77SClemens Zeidler // #pragma mark - 57a90ebd77SClemens Zeidler 58a90ebd77SClemens Zeidler 59a90ebd77SClemens Zeidler uint32 60a90ebd77SClemens Zeidler radeon_accelerant_mode_count(void) 61a90ebd77SClemens Zeidler { 62333bd770SAlexander von Gluck IV TRACE("%s\n", __func__); 63a90ebd77SClemens Zeidler 64a90ebd77SClemens Zeidler return gInfo->shared_info->mode_count; 65a90ebd77SClemens Zeidler } 66a90ebd77SClemens Zeidler 67a90ebd77SClemens Zeidler 68a90ebd77SClemens Zeidler status_t 69a90ebd77SClemens Zeidler radeon_get_mode_list(display_mode *modeList) 70a90ebd77SClemens Zeidler { 71333bd770SAlexander von Gluck IV TRACE("%s\n", __func__); 72a90ebd77SClemens Zeidler memcpy(modeList, gInfo->mode_list, 73a90ebd77SClemens Zeidler gInfo->shared_info->mode_count * sizeof(display_mode)); 74a90ebd77SClemens Zeidler return B_OK; 75a90ebd77SClemens Zeidler } 76a90ebd77SClemens Zeidler 77a90ebd77SClemens Zeidler 7888bfef92SAlexander von Gluck IV status_t 7988bfef92SAlexander von Gluck IV radeon_get_edid_info(void* info, size_t size, uint32* edid_version) 8088bfef92SAlexander von Gluck IV { 8188bfef92SAlexander von Gluck IV TRACE("%s\n", __func__); 8288bfef92SAlexander von Gluck IV if (!gInfo->shared_info->has_edid) 8388bfef92SAlexander von Gluck IV return B_ERROR; 8488bfef92SAlexander von Gluck IV if (size < sizeof(struct edid1_info)) 8588bfef92SAlexander von Gluck IV return B_BUFFER_OVERFLOW; 8688bfef92SAlexander von Gluck IV 8788bfef92SAlexander von Gluck IV memcpy(info, &gInfo->shared_info->edid_info, sizeof(struct edid1_info)); 8888bfef92SAlexander von Gluck IV *edid_version = EDID_VERSION_1; 8988bfef92SAlexander von Gluck IV 9088bfef92SAlexander von Gluck IV return B_OK; 9188bfef92SAlexander von Gluck IV } 9288bfef92SAlexander von Gluck IV 9388bfef92SAlexander von Gluck IV 94a90ebd77SClemens Zeidler static void 95a90ebd77SClemens Zeidler get_color_space_format(const display_mode &mode, uint32 &colorMode, 96a90ebd77SClemens Zeidler uint32 &bytesPerRow, uint32 &bitsPerPixel) 97a90ebd77SClemens Zeidler { 98a90ebd77SClemens Zeidler uint32 bytesPerPixel; 99a90ebd77SClemens Zeidler 100a90ebd77SClemens Zeidler switch (mode.space) { 101a90ebd77SClemens Zeidler case B_RGB32_LITTLE: 102a90ebd77SClemens Zeidler colorMode = DISPLAY_CONTROL_RGB32; 103a90ebd77SClemens Zeidler bytesPerPixel = 4; 104a90ebd77SClemens Zeidler bitsPerPixel = 32; 105a90ebd77SClemens Zeidler break; 106a90ebd77SClemens Zeidler case B_RGB16_LITTLE: 107a90ebd77SClemens Zeidler colorMode = DISPLAY_CONTROL_RGB16; 108a90ebd77SClemens Zeidler bytesPerPixel = 2; 109a90ebd77SClemens Zeidler bitsPerPixel = 16; 110a90ebd77SClemens Zeidler break; 111a90ebd77SClemens Zeidler case B_RGB15_LITTLE: 112a90ebd77SClemens Zeidler colorMode = DISPLAY_CONTROL_RGB15; 113a90ebd77SClemens Zeidler bytesPerPixel = 2; 114a90ebd77SClemens Zeidler bitsPerPixel = 15; 115a90ebd77SClemens Zeidler break; 116a90ebd77SClemens Zeidler case B_CMAP8: 117a90ebd77SClemens Zeidler default: 118a90ebd77SClemens Zeidler colorMode = DISPLAY_CONTROL_CMAP8; 119a90ebd77SClemens Zeidler bytesPerPixel = 1; 120a90ebd77SClemens Zeidler bitsPerPixel = 8; 121a90ebd77SClemens Zeidler break; 122a90ebd77SClemens Zeidler } 123a90ebd77SClemens Zeidler 124a90ebd77SClemens Zeidler bytesPerRow = mode.virtual_width * bytesPerPixel; 125a90ebd77SClemens Zeidler } 126a90ebd77SClemens Zeidler 12747ad511fSAlexander von Gluck IV 128cf546fa0SAlexander von Gluck IV // Blacks the screen out, useful for mode setting 1295f6744a8SAlexander von Gluck IV static void 130f2fe29a0SAlexander von Gluck IV CardBlankSet(uint8 crtid, bool blank) 1315f6744a8SAlexander von Gluck IV { 132f2fe29a0SAlexander von Gluck IV int blackColorReg 1333fe78837SAlexander von Gluck IV = crtid == 1 ? D2CRTC_BLACK_COLOR : D1CRTC_BLACK_COLOR; 134f2fe29a0SAlexander von Gluck IV int blankControlReg 1353fe78837SAlexander von Gluck IV = crtid == 1 ? D2CRTC_BLANK_CONTROL : D1CRTC_BLANK_CONTROL; 1365f6744a8SAlexander von Gluck IV 137aa2a6e33SAlexander von Gluck IV Write32(CRT, blackColorReg, 0); 138aa2a6e33SAlexander von Gluck IV Write32Mask(CRT, blankControlReg, blank ? 1 << 8 : 0, 1 << 8); 1395f6744a8SAlexander von Gluck IV } 140cf546fa0SAlexander von Gluck IV 141cf546fa0SAlexander von Gluck IV 142cf546fa0SAlexander von Gluck IV static void 14395e1d7e8SAlexander von Gluck IV CardFBSet(uint8 crtid, display_mode *mode) 144cf546fa0SAlexander von Gluck IV { 14595e1d7e8SAlexander von Gluck IV register_info* regs = gDisplay[crtid]->regs; 14695e1d7e8SAlexander von Gluck IV 147cf546fa0SAlexander von Gluck IV uint32 colorMode; 148cf546fa0SAlexander von Gluck IV uint32 bytesPerRow; 149cf546fa0SAlexander von Gluck IV uint32 bitsPerPixel; 150cf546fa0SAlexander von Gluck IV 151cf546fa0SAlexander von Gluck IV get_color_space_format(*mode, colorMode, bytesPerRow, bitsPerPixel); 152cf546fa0SAlexander von Gluck IV 153eb027537SAlexander von Gluck IV LVDSAllIdle(); 154eb027537SAlexander von Gluck IV // DVI / HDMI / LCD 155eb027537SAlexander von Gluck IV TMDSAllIdle(); 156eb027537SAlexander von Gluck IV // DVI / HDMI 15784bcfa3dSAlexander von Gluck IV DACAllIdle(); 158eb027537SAlexander von Gluck IV // VGA 159eb027537SAlexander von Gluck IV 160eb027537SAlexander von Gluck IV // framebuffersize = w * h * bpp = fb bits / 8 = bytes needed 161eb027537SAlexander von Gluck IV uint64 fbAddressInt = gInfo->shared_info->frame_buffer_int; 16284bcfa3dSAlexander von Gluck IV 163*6ab8261bSAlexander von Gluck IV MCFBSetup(); 16484bcfa3dSAlexander von Gluck IV 16595e1d7e8SAlexander von Gluck IV Write32(CRT, regs->grphUpdate, (1<<16)); 166b6c5f468SAlexander von Gluck IV // Lock for update (isn't this normally the other way around on VGA? 167e7e76b29SAlexander von Gluck IV 168b6c5f468SAlexander von Gluck IV // Tell GPU which frame buffer address to draw from 169*6ab8261bSAlexander von Gluck IV Write32(CRT, regs->grphPrimarySurfaceAddr, fbAddressInt & 0xFFFFFFFF); 170*6ab8261bSAlexander von Gluck IV //Write32(CRT, regs->grphSecondarySurfaceAddr, fbAddressInt); 171b6c5f468SAlexander von Gluck IV 172b6c5f468SAlexander von Gluck IV if (gInfo->shared_info->device_chipset >= (RADEON_R700 | 0x70)) { 17395e1d7e8SAlexander von Gluck IV Write32(CRT, regs->grphPrimarySurfaceAddrHigh, 174eb027537SAlexander von Gluck IV (fbAddressInt >> 32) & 0xf); 17595e1d7e8SAlexander von Gluck IV Write32(CRT, regs->grphSecondarySurfaceAddrHigh, 176eb027537SAlexander von Gluck IV (fbAddressInt >> 32) & 0xf); 177b6c5f468SAlexander von Gluck IV } 178b6c5f468SAlexander von Gluck IV 17995e1d7e8SAlexander von Gluck IV Write32(CRT, regs->grphControl, 0); 180b6c5f468SAlexander von Gluck IV // Reset stored depth, format, etc 181cf546fa0SAlexander von Gluck IV 18251a43d0fSAlexander von Gluck IV // set color mode on video card 183cf546fa0SAlexander von Gluck IV switch (mode->space) { 184cf546fa0SAlexander von Gluck IV case B_CMAP8: 18595e1d7e8SAlexander von Gluck IV Write32Mask(CRT, regs->grphControl, 186bd34b2f7SAlexander von Gluck IV 0, 0x00000703); 187cf546fa0SAlexander von Gluck IV break; 188cf546fa0SAlexander von Gluck IV case B_RGB15_LITTLE: 18995e1d7e8SAlexander von Gluck IV Write32Mask(CRT, regs->grphControl, 190bd34b2f7SAlexander von Gluck IV 0x000001, 0x00000703); 191cf546fa0SAlexander von Gluck IV break; 192cf546fa0SAlexander von Gluck IV case B_RGB16_LITTLE: 19395e1d7e8SAlexander von Gluck IV Write32Mask(CRT, regs->grphControl, 194bd34b2f7SAlexander von Gluck IV 0x000101, 0x00000703); 195cf546fa0SAlexander von Gluck IV break; 196cf546fa0SAlexander von Gluck IV case B_RGB24_LITTLE: 197cf546fa0SAlexander von Gluck IV case B_RGB32_LITTLE: 198cf546fa0SAlexander von Gluck IV default: 19995e1d7e8SAlexander von Gluck IV Write32Mask(CRT, regs->grphControl, 200bd34b2f7SAlexander von Gluck IV 0x000002, 0x00000703); 201cf546fa0SAlexander von Gluck IV break; 202cf546fa0SAlexander von Gluck IV } 203cf546fa0SAlexander von Gluck IV 20495e1d7e8SAlexander von Gluck IV Write32(CRT, regs->grphSwapControl, 0); 205cf546fa0SAlexander von Gluck IV // only for chipsets > r600 206cf546fa0SAlexander von Gluck IV // R5xx - RS690 case is GRPH_CONTROL bit 16 207cf546fa0SAlexander von Gluck IV 20895e1d7e8SAlexander von Gluck IV Write32Mask(CRT, regs->grphEnable, 1, 0x00000001); 209b6c5f468SAlexander von Gluck IV // Enable graphics 2103be5e036SAlexander von Gluck IV 21195e1d7e8SAlexander von Gluck IV Write32(CRT, regs->grphSurfaceOffsetX, 0); 21295e1d7e8SAlexander von Gluck IV Write32(CRT, regs->grphSurfaceOffsetY, 0); 21395e1d7e8SAlexander von Gluck IV Write32(CRT, regs->grphXStart, 0); 21495e1d7e8SAlexander von Gluck IV Write32(CRT, regs->grphYStart, 0); 21595e1d7e8SAlexander von Gluck IV Write32(CRT, regs->grphXEnd, mode->virtual_width); 21695e1d7e8SAlexander von Gluck IV Write32(CRT, regs->grphYEnd, mode->virtual_height); 21795e1d7e8SAlexander von Gluck IV Write32(CRT, regs->grphPitch, bytesPerRow / 4); 218cf546fa0SAlexander von Gluck IV 21995e1d7e8SAlexander von Gluck IV Write32(CRT, regs->modeDesktopHeight, mode->virtual_height); 220eb5c4b07SAlexander von Gluck IV 22195e1d7e8SAlexander von Gluck IV Write32(CRT, regs->grphUpdate, 0); 222b6c5f468SAlexander von Gluck IV // Unlock changed registers 223cf546fa0SAlexander von Gluck IV 224cf546fa0SAlexander von Gluck IV // update shared info 225cf546fa0SAlexander von Gluck IV gInfo->shared_info->bytes_per_row = bytesPerRow; 226cf546fa0SAlexander von Gluck IV gInfo->shared_info->current_mode = *mode; 227cf546fa0SAlexander von Gluck IV gInfo->shared_info->bits_per_pixel = bitsPerPixel; 228cf546fa0SAlexander von Gluck IV } 229cf546fa0SAlexander von Gluck IV 230cf546fa0SAlexander von Gluck IV 231cf546fa0SAlexander von Gluck IV static void 23295e1d7e8SAlexander von Gluck IV CardModeSet(uint8 crtid, display_mode *mode) 233cf546fa0SAlexander von Gluck IV { 234a90ebd77SClemens Zeidler display_timing& displayTiming = mode->timing; 23595e1d7e8SAlexander von Gluck IV register_info* regs = gDisplay[crtid]->regs; 236a90ebd77SClemens Zeidler 237192781ddSAlexander von Gluck IV TRACE("%s called to do %dx%d\n", 238192781ddSAlexander von Gluck IV __func__, displayTiming.h_display, displayTiming.v_display); 239a90ebd77SClemens Zeidler 240192781ddSAlexander von Gluck IV // enable read requests 24195e1d7e8SAlexander von Gluck IV Write32Mask(CRT, regs->grphControl, 0, 0x01000000); 242a90ebd77SClemens Zeidler 243192781ddSAlexander von Gluck IV // *** Horizontal 24495e1d7e8SAlexander von Gluck IV Write32(CRT, regs->crtHTotal, 2455f6744a8SAlexander von Gluck IV displayTiming.h_total - 1); 246a90ebd77SClemens Zeidler 247*6ab8261bSAlexander von Gluck IV /* 248f2fe29a0SAlexander von Gluck IV // Blanking 249*6ab8261bSAlexander von Gluck IV uint16 blankStart = displayTiming.h_total 250eb027537SAlexander von Gluck IV + displayTiming.h_display - displayTiming.h_sync_start; 251*6ab8261bSAlexander von Gluck IV uint16 blankEnd = displayTiming.h_total - displayTiming.h_sync_start; 252192781ddSAlexander von Gluck IV 25395e1d7e8SAlexander von Gluck IV Write32(CRT, regs->crtHBlank, 254e7e76b29SAlexander von Gluck IV blankStart | (blankEnd << 16)); 255*6ab8261bSAlexander von Gluck IV */ 256a90ebd77SClemens Zeidler 25795e1d7e8SAlexander von Gluck IV Write32(CRT, regs->crtHSync, 258a90ebd77SClemens Zeidler (displayTiming.h_sync_end - displayTiming.h_sync_start) << 16); 259a90ebd77SClemens Zeidler 2603be5e036SAlexander von Gluck IV // set flag for neg. H sync. M76 Register Reference Guide 2-256 26195e1d7e8SAlexander von Gluck IV Write32Mask(CRT, regs->crtHPolarity, 2623be5e036SAlexander von Gluck IV displayTiming.flags & B_POSITIVE_HSYNC ? 0 : 1, 0x1); 263192781ddSAlexander von Gluck IV 264192781ddSAlexander von Gluck IV // *** Vertical 26595e1d7e8SAlexander von Gluck IV Write32(CRT, regs->crtVTotal, 2665f6744a8SAlexander von Gluck IV displayTiming.v_total - 1); 267a90ebd77SClemens Zeidler 268*6ab8261bSAlexander von Gluck IV /* 269eb027537SAlexander von Gluck IV // Blanking 270*6ab8261bSAlexander von Gluck IV blankStart = displayTiming.v_total 271eb027537SAlexander von Gluck IV + displayTiming.v_display - displayTiming.v_sync_start; 272*6ab8261bSAlexander von Gluck IV blankEnd = displayTiming.v_total - displayTiming.v_sync_start; 273a90ebd77SClemens Zeidler 27495e1d7e8SAlexander von Gluck IV Write32(CRT, regs->crtVBlank, 275e7e76b29SAlexander von Gluck IV blankStart | (blankEnd << 16)); 276*6ab8261bSAlexander von Gluck IV */ 277192781ddSAlexander von Gluck IV 278192781ddSAlexander von Gluck IV // Set Interlace if specified within mode line 279192781ddSAlexander von Gluck IV if (displayTiming.flags & B_TIMING_INTERLACED) { 28095e1d7e8SAlexander von Gluck IV Write32(CRT, regs->crtInterlace, 0x1); 28195e1d7e8SAlexander von Gluck IV Write32(CRT, regs->modeDataFormat, 0x1); 282a90ebd77SClemens Zeidler } else { 28395e1d7e8SAlexander von Gluck IV Write32(CRT, regs->crtInterlace, 0x0); 28495e1d7e8SAlexander von Gluck IV Write32(CRT, regs->modeDataFormat, 0x0); 285a90ebd77SClemens Zeidler } 286a90ebd77SClemens Zeidler 28795e1d7e8SAlexander von Gluck IV Write32(CRT, regs->crtVSync, 288a90ebd77SClemens Zeidler (displayTiming.v_sync_end - displayTiming.v_sync_start) << 16); 289192781ddSAlexander von Gluck IV 2903be5e036SAlexander von Gluck IV // set flag for neg. V sync. M76 Register Reference Guide 2-258 29195e1d7e8SAlexander von Gluck IV Write32Mask(CRT, regs->crtVPolarity, 292d1d65a79SAlexander von Gluck IV displayTiming.flags & B_POSITIVE_VSYNC ? 0 : 1, 0x1); 293a90ebd77SClemens Zeidler 29447ad511fSAlexander von Gluck IV /* set D1CRTC_HORZ_COUNT_BY2_EN to 0; 29547ad511fSAlexander von Gluck IV should only be set to 1 on 30bpp DVI modes 29647ad511fSAlexander von Gluck IV */ 29795e1d7e8SAlexander von Gluck IV Write32Mask(CRT, regs->crtCountControl, 0x0, 0x1); 298a90ebd77SClemens Zeidler } 299a90ebd77SClemens Zeidler 300a90ebd77SClemens Zeidler 301d5009951SClemens Zeidler static void 30295e1d7e8SAlexander von Gluck IV CardModeScale(uint8 crtid, display_mode *mode) 303d5009951SClemens Zeidler { 30495e1d7e8SAlexander von Gluck IV register_info* regs = gDisplay[crtid]->regs; 30595e1d7e8SAlexander von Gluck IV 306b6c5f468SAlexander von Gluck IV // No scaling 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 31595e1d7e8SAlexander von Gluck IV Write32(CRT, regs->viewportStart, 0); 31695e1d7e8SAlexander von Gluck IV Write32(CRT, regs->viewportSize, 317b6c5f468SAlexander von Gluck IV mode->timing.v_display | (mode->timing.h_display << 16)); 318*6ab8261bSAlexander von Gluck IV 31995e1d7e8SAlexander von Gluck IV Write32(CRT, regs->sclEnable, 0); 32095e1d7e8SAlexander von Gluck IV Write32(CRT, regs->sclTapControl, 0); 32195e1d7e8SAlexander von Gluck IV Write32(CRT, regs->modeCenter, 2); 322b6c5f468SAlexander von Gluck IV // D1MODE_DATA_FORMAT? 323d5009951SClemens Zeidler } 324d5009951SClemens Zeidler 325d5009951SClemens Zeidler 326a90ebd77SClemens Zeidler status_t 327a90ebd77SClemens Zeidler radeon_set_display_mode(display_mode *mode) 328a90ebd77SClemens Zeidler { 329*6ab8261bSAlexander von Gluck IV // Disable VGA (boo, hiss) 330*6ab8261bSAlexander von Gluck IV Write32Mask(OUT, VGA_RENDER_CONTROL, 0, 0x00030000); 331*6ab8261bSAlexander von Gluck IV Write32Mask(OUT, VGA_MODE_CONTROL, 0, 0x00000030); 332*6ab8261bSAlexander von Gluck IV Write32Mask(OUT, VGA_HDP_CONTROL, 0x00010010, 0x00010010); 333*6ab8261bSAlexander von Gluck IV Write32(OUT, D1VGA_CONTROL, 0); 334*6ab8261bSAlexander von Gluck IV Write32(OUT, D2VGA_CONTROL, 0); 335a90ebd77SClemens Zeidler 336*6ab8261bSAlexander von Gluck IV // TODO : We set the same VESA EDID mode on each display 337e7e76b29SAlexander von Gluck IV 338*6ab8261bSAlexander von Gluck IV // Set mode on each display 339*6ab8261bSAlexander von Gluck IV for (uint8 id = 0; id < MAX_DISPLAY; id++) { 340*6ab8261bSAlexander von Gluck IV // Skip if display is inactive 341*6ab8261bSAlexander von Gluck IV if (gDisplay[id]->active == false) { 342*6ab8261bSAlexander von Gluck IV CardBlankSet(id, true); 343*6ab8261bSAlexander von Gluck IV display_power(id, RHD_POWER_ON); 344*6ab8261bSAlexander von Gluck IV continue; 34595e1d7e8SAlexander von Gluck IV } 346f2fe29a0SAlexander von Gluck IV 347*6ab8261bSAlexander von Gluck IV // Program CRT Controller 348*6ab8261bSAlexander von Gluck IV CardFBSet(id, mode); 349*6ab8261bSAlexander von Gluck IV CardModeSet(id, mode); 350*6ab8261bSAlexander von Gluck IV CardModeScale(id, mode); 351*6ab8261bSAlexander von Gluck IV 352*6ab8261bSAlexander von Gluck IV display_power(id, RHD_POWER_RESET); 353*6ab8261bSAlexander von Gluck IV 354*6ab8261bSAlexander von Gluck IV // Program connector controllers 355*6ab8261bSAlexander von Gluck IV switch (gDisplay[id]->connection_type) { 356*6ab8261bSAlexander von Gluck IV case CONNECTION_DAC: 357*6ab8261bSAlexander von Gluck IV PLLSet(gDisplay[id]->connection_id, 358*6ab8261bSAlexander von Gluck IV mode->timing.pixel_clock); 359*6ab8261bSAlexander von Gluck IV DACSet(gDisplay[id]->connection_id, id); 360*6ab8261bSAlexander von Gluck IV break; 361*6ab8261bSAlexander von Gluck IV case CONNECTION_TMDS: 362*6ab8261bSAlexander von Gluck IV TMDSSet(gDisplay[id]->connection_id, mode); 363*6ab8261bSAlexander von Gluck IV break; 364*6ab8261bSAlexander von Gluck IV case CONNECTION_LVDS: 365*6ab8261bSAlexander von Gluck IV LVDSSet(gDisplay[id]->connection_id, mode); 366*6ab8261bSAlexander von Gluck IV break; 367*6ab8261bSAlexander von Gluck IV } 368*6ab8261bSAlexander von Gluck IV 369*6ab8261bSAlexander von Gluck IV // Power CRT Controller 370*6ab8261bSAlexander von Gluck IV display_power(id, RHD_POWER_ON); 371*6ab8261bSAlexander von Gluck IV CardBlankSet(id, false); 372*6ab8261bSAlexander von Gluck IV 373*6ab8261bSAlexander von Gluck IV // Power connector controllers 374*6ab8261bSAlexander von Gluck IV switch (gDisplay[id]->connection_type) { 375*6ab8261bSAlexander von Gluck IV case CONNECTION_DAC: 376*6ab8261bSAlexander von Gluck IV PLLPower(gDisplay[id]->connection_id, RHD_POWER_ON); 377*6ab8261bSAlexander von Gluck IV DACPower(gDisplay[id]->connection_id, RHD_POWER_ON); 378*6ab8261bSAlexander von Gluck IV break; 379*6ab8261bSAlexander von Gluck IV case CONNECTION_TMDS: 380*6ab8261bSAlexander von Gluck IV TMDSPower(gDisplay[id]->connection_id, RHD_POWER_ON); 381*6ab8261bSAlexander von Gluck IV break; 382*6ab8261bSAlexander von Gluck IV case CONNECTION_LVDS: 383*6ab8261bSAlexander von Gluck IV LVDSPower(gDisplay[id]->connection_id, RHD_POWER_ON); 384*6ab8261bSAlexander von Gluck IV break; 385*6ab8261bSAlexander von Gluck IV } 386*6ab8261bSAlexander von Gluck IV } 3876604b1b6SAlexander von Gluck IV 388aa2a6e33SAlexander von Gluck IV int32 crtstatus = Read32(CRT, D1CRTC_STATUS); 3895f6744a8SAlexander von Gluck IV TRACE("CRT0 Status: 0x%X\n", crtstatus); 390f2fe29a0SAlexander von Gluck IV crtstatus = Read32(CRT, D2CRTC_STATUS); 391f2fe29a0SAlexander von Gluck IV TRACE("CRT1 Status: 0x%X\n", crtstatus); 3923be5e036SAlexander von Gluck IV 393a90ebd77SClemens Zeidler return B_OK; 394a90ebd77SClemens Zeidler } 395a90ebd77SClemens Zeidler 396a90ebd77SClemens Zeidler 397a90ebd77SClemens Zeidler status_t 398a90ebd77SClemens Zeidler radeon_get_display_mode(display_mode *_currentMode) 399a90ebd77SClemens Zeidler { 400d5c3acacSAlexander von Gluck IV TRACE("%s\n", __func__); 401a90ebd77SClemens Zeidler 402192781ddSAlexander von Gluck IV *_currentMode = gInfo->shared_info->current_mode; 403a90ebd77SClemens Zeidler return B_OK; 404a90ebd77SClemens Zeidler } 405a90ebd77SClemens Zeidler 406a90ebd77SClemens Zeidler 407a90ebd77SClemens Zeidler status_t 408a90ebd77SClemens Zeidler radeon_get_frame_buffer_config(frame_buffer_config *config) 409a90ebd77SClemens Zeidler { 410d5c3acacSAlexander von Gluck IV TRACE("%s\n", __func__); 411a90ebd77SClemens Zeidler 4123be5e036SAlexander von Gluck IV config->frame_buffer = gInfo->shared_info->frame_buffer; 4133be5e036SAlexander von Gluck IV config->frame_buffer_dma = (uint8 *)gInfo->shared_info->frame_buffer_phys; 41451a43d0fSAlexander von Gluck IV 415a90ebd77SClemens Zeidler config->bytes_per_row = gInfo->shared_info->bytes_per_row; 416a90ebd77SClemens Zeidler 417a90ebd77SClemens Zeidler return B_OK; 418a90ebd77SClemens Zeidler } 419a90ebd77SClemens Zeidler 420a90ebd77SClemens Zeidler 421a90ebd77SClemens Zeidler status_t 422a90ebd77SClemens Zeidler radeon_get_pixel_clock_limits(display_mode *mode, uint32 *_low, uint32 *_high) 423a90ebd77SClemens Zeidler { 424d5c3acacSAlexander von Gluck IV TRACE("%s\n", __func__); 425e7e76b29SAlexander von Gluck IV 426a90ebd77SClemens Zeidler if (_low != NULL) { 427a90ebd77SClemens Zeidler // lower limit of about 48Hz vertical refresh 4285f6744a8SAlexander von Gluck IV uint32 totalClocks = (uint32)mode->timing.h_total 4295f6744a8SAlexander von Gluck IV *(uint32)mode->timing.v_total; 430a90ebd77SClemens Zeidler uint32 low = (totalClocks * 48L) / 1000L; 431e7e76b29SAlexander von Gluck IV 432a90ebd77SClemens Zeidler if (low < gInfo->shared_info->pll_info.min_frequency) 433a90ebd77SClemens Zeidler low = gInfo->shared_info->pll_info.min_frequency; 434a90ebd77SClemens Zeidler else if (low > gInfo->shared_info->pll_info.max_frequency) 435a90ebd77SClemens Zeidler return B_ERROR; 436a90ebd77SClemens Zeidler 437a90ebd77SClemens Zeidler *_low = low; 438a90ebd77SClemens Zeidler } 439a90ebd77SClemens Zeidler 440a90ebd77SClemens Zeidler if (_high != NULL) 441a90ebd77SClemens Zeidler *_high = gInfo->shared_info->pll_info.max_frequency; 442e7e76b29SAlexander von Gluck IV 443e7e76b29SAlexander von Gluck IV //*_low = 48L; 444e7e76b29SAlexander von Gluck IV //*_high = 100 * 1000000L; 445a90ebd77SClemens Zeidler return B_OK; 446a90ebd77SClemens Zeidler } 447a90ebd77SClemens Zeidler 448a90ebd77SClemens Zeidler 449192781ddSAlexander von Gluck IV bool 450192781ddSAlexander von Gluck IV is_mode_supported(display_mode *mode) 451192781ddSAlexander von Gluck IV { 452d1d65a79SAlexander von Gluck IV TRACE("MODE: %d ; %d %d %d %d ; %d %d %d %d\n", 453d1d65a79SAlexander von Gluck IV mode->timing.pixel_clock, mode->timing.h_display, 454d1d65a79SAlexander von Gluck IV mode->timing.h_sync_start, mode->timing.h_sync_end, 455d1d65a79SAlexander von Gluck IV mode->timing.h_total, mode->timing.v_display, 456d1d65a79SAlexander von Gluck IV mode->timing.v_sync_start, mode->timing.v_sync_end, 457d1d65a79SAlexander von Gluck IV mode->timing.v_total); 458d1d65a79SAlexander von Gluck IV 4591dac4469SAlexander von Gluck IV // Validate modeline is within a sane range 460192781ddSAlexander von Gluck IV if (is_mode_sane(mode) != B_OK) 461192781ddSAlexander von Gluck IV return false; 462192781ddSAlexander von Gluck IV 46395e1d7e8SAlexander von Gluck IV // TODO : is_mode_supported on *which* display? 464d1d65a79SAlexander von Gluck IV uint32 crtid = 0; 4651dac4469SAlexander von Gluck IV 466d1d65a79SAlexander von Gluck IV // if we have edid info, check frequency adginst crt reported valid ranges 467e1b9d6e6SAlexander von Gluck IV if (gInfo->shared_info->has_edid 468e1b9d6e6SAlexander von Gluck IV && gDisplay[crtid]->found_ranges) { 4691dac4469SAlexander von Gluck IV 470d1d65a79SAlexander von Gluck IV uint32 hfreq = mode->timing.pixel_clock / mode->timing.h_total; 47195e1d7e8SAlexander von Gluck IV if (hfreq > gDisplay[crtid]->hfreq_max + 1 47295e1d7e8SAlexander von Gluck IV || hfreq < gDisplay[crtid]->hfreq_min - 1) { 473d1d65a79SAlexander von Gluck IV TRACE("!!! hfreq : %d , hfreq_min : %d, hfreq_max : %d\n", 47495e1d7e8SAlexander von Gluck IV hfreq, gDisplay[crtid]->hfreq_min, gDisplay[crtid]->hfreq_max); 475d1d65a79SAlexander von Gluck IV TRACE("!!! %dx%d falls outside of CRT %d's valid " 476d1d65a79SAlexander von Gluck IV "horizontal range.\n", mode->timing.h_display, 477d1d65a79SAlexander von Gluck IV mode->timing.v_display, crtid); 478d1d65a79SAlexander von Gluck IV return false; 479d1d65a79SAlexander von Gluck IV } 480d1d65a79SAlexander von Gluck IV 481d1d65a79SAlexander von Gluck IV uint32 vfreq = mode->timing.pixel_clock / ((mode->timing.v_total 482d1d65a79SAlexander von Gluck IV * mode->timing.h_total) / 1000); 483d1d65a79SAlexander von Gluck IV 48495e1d7e8SAlexander von Gluck IV if (vfreq > gDisplay[crtid]->vfreq_max + 1 48595e1d7e8SAlexander von Gluck IV || vfreq < gDisplay[crtid]->vfreq_min - 1) { 486d1d65a79SAlexander von Gluck IV TRACE("!!! vfreq : %d , vfreq_min : %d, vfreq_max : %d\n", 48795e1d7e8SAlexander von Gluck IV vfreq, gDisplay[crtid]->vfreq_min, gDisplay[crtid]->vfreq_max); 488d1d65a79SAlexander von Gluck IV TRACE("!!! %dx%d falls outside of CRT %d's valid vertical range\n", 489d1d65a79SAlexander von Gluck IV mode->timing.h_display, mode->timing.v_display, crtid); 490d1d65a79SAlexander von Gluck IV return false; 491d1d65a79SAlexander von Gluck IV } 492e1b9d6e6SAlexander von Gluck IV } 493e1b9d6e6SAlexander von Gluck IV 494d1d65a79SAlexander von Gluck IV TRACE("%dx%d is within CRT %d's valid frequency range\n", 495d1d65a79SAlexander von Gluck IV mode->timing.h_display, mode->timing.v_display, crtid); 496192781ddSAlexander von Gluck IV 497192781ddSAlexander von Gluck IV return true; 498192781ddSAlexander von Gluck IV } 499192781ddSAlexander von Gluck IV 500192781ddSAlexander von Gluck IV 501d5c3acacSAlexander von Gluck IV /* 502d5c3acacSAlexander von Gluck IV * A quick sanity check of the provided display_mode 503d5c3acacSAlexander von Gluck IV */ 504d5c3acacSAlexander von Gluck IV status_t 505192781ddSAlexander von Gluck IV is_mode_sane(display_mode *mode) 506d5c3acacSAlexander von Gluck IV { 507333bd770SAlexander von Gluck IV // horizontal timing 508333bd770SAlexander von Gluck IV // validate h_sync_start is less then h_sync_end 509333bd770SAlexander von Gluck IV if (mode->timing.h_sync_start > mode->timing.h_sync_end) { 51091235829SAlexander von Gluck IV TRACE("%s: ERROR: (%dx%d) " 51191235829SAlexander von Gluck IV "received h_sync_start greater then h_sync_end!\n", 512333bd770SAlexander von Gluck IV __func__, mode->timing.h_display, mode->timing.v_display); 513333bd770SAlexander von Gluck IV return B_ERROR; 514333bd770SAlexander von Gluck IV } 515333bd770SAlexander von Gluck IV // validate h_total is greater then h_display 516333bd770SAlexander von Gluck IV if (mode->timing.h_total < mode->timing.h_display) { 51791235829SAlexander von Gluck IV TRACE("%s: ERROR: (%dx%d) " 51891235829SAlexander von Gluck IV "received h_total greater then h_display!\n", 519333bd770SAlexander von Gluck IV __func__, mode->timing.h_display, mode->timing.v_display); 520d5c3acacSAlexander von Gluck IV return B_ERROR; 521d5c3acacSAlexander von Gluck IV } 522d5c3acacSAlexander von Gluck IV 523333bd770SAlexander von Gluck IV // vertical timing 524333bd770SAlexander von Gluck IV // validate v_start is less then v_end 525333bd770SAlexander von Gluck IV if (mode->timing.v_sync_start > mode->timing.v_sync_end) { 52691235829SAlexander von Gluck IV TRACE("%s: ERROR: (%dx%d) " 52791235829SAlexander von Gluck IV "received v_sync_start greater then v_sync_end!\n", 528333bd770SAlexander von Gluck IV __func__, mode->timing.h_display, mode->timing.v_display); 529d5c3acacSAlexander von Gluck IV return B_ERROR; 530d5c3acacSAlexander von Gluck IV } 531333bd770SAlexander von Gluck IV // validate v_total is greater then v_display 532333bd770SAlexander von Gluck IV if (mode->timing.v_total < mode->timing.v_display) { 53391235829SAlexander von Gluck IV TRACE("%s: ERROR: (%dx%d) " 53491235829SAlexander von Gluck IV "received v_total greater then v_display!\n", 535333bd770SAlexander von Gluck IV __func__, mode->timing.h_display, mode->timing.v_display); 536d5c3acacSAlexander von Gluck IV return B_ERROR; 537d5c3acacSAlexander von Gluck IV } 538d5c3acacSAlexander von Gluck IV 53991235829SAlexander von Gluck IV // calculate refresh rate for given timings to whole int (in Hz) 54091235829SAlexander von Gluck IV int refresh = mode->timing.pixel_clock * 1000 54191235829SAlexander von Gluck IV / (mode->timing.h_total * mode->timing.v_total); 54291235829SAlexander von Gluck IV 54391235829SAlexander von Gluck IV if (refresh < 30 || refresh > 250) { 54491235829SAlexander von Gluck IV TRACE("%s: ERROR: (%dx%d) " 54591235829SAlexander von Gluck IV "refresh rate of %dHz is unlikely for any kind of monitor!\n", 54691235829SAlexander von Gluck IV __func__, mode->timing.h_display, mode->timing.v_display, refresh); 54791235829SAlexander von Gluck IV return B_ERROR; 54891235829SAlexander von Gluck IV } 54991235829SAlexander von Gluck IV 550d5c3acacSAlexander von Gluck IV return B_OK; 551d5c3acacSAlexander von Gluck IV } 552d5c3acacSAlexander von Gluck IV 553d1d65a79SAlexander von Gluck IV 554