Author: kallisti5 Date: 2011-07-30 19:45:14 +0200 (Sat, 30 Jul 2011) New Revision: 42515 Changeset: https://dev.haiku-os.org/changeset/42515 Modified: haiku/trunk/src/add-ons/accelerants/radeon_hd/accelerant.cpp haiku/trunk/src/add-ons/accelerants/radeon_hd/accelerant_protos.h haiku/trunk/src/add-ons/accelerants/radeon_hd/display.cpp haiku/trunk/src/add-ons/accelerants/radeon_hd/display.h haiku/trunk/src/add-ons/accelerants/radeon_hd/hooks.cpp haiku/trunk/src/add-ons/accelerants/radeon_hd/mc.cpp haiku/trunk/src/add-ons/accelerants/radeon_hd/mc.h haiku/trunk/src/add-ons/accelerants/radeon_hd/mode.cpp haiku/trunk/src/add-ons/kernel/drivers/graphics/radeon_hd/radeon_hd.cpp Log: * Pass device name into shared info * Refactor MCFBsetup to be a little simpler for now * Implement radeon accelerant_device_info for screen preflet * Re-add CRT Power calls to display code. * Disable blanking setting for now... just can't figure out what AMD wants for this. * Remove some un-needed locking in the scaling code * Be sure to disable VGA when set_display_mode is called * Refactor mode setting code to loop over all possible displays and set the provided mode on the attached ones. Modified: haiku/trunk/src/add-ons/accelerants/radeon_hd/accelerant.cpp =================================================================== --- haiku/trunk/src/add-ons/accelerants/radeon_hd/accelerant.cpp 2011-07-30 16:05:28 UTC (rev 42514) +++ haiku/trunk/src/add-ons/accelerants/radeon_hd/accelerant.cpp 2011-07-30 17:45:14 UTC (rev 42515) @@ -244,3 +244,16 @@ TRACE("%s done\n", __func__); } + +status_t +radeon_get_accelerant_device_info(accelerant_device_info *di) +{ + di->version = B_ACCELERANT_VERSION; + strcpy(di->name, gInfo->shared_info->device_identifier); + strcpy(di->chipset, "radeon_hd"); + // TODO : Give chipset, ex: r600 + strcpy(di->serial_no, "None" ); + + di->memory = gInfo->shared_info->graphics_memory_size; + return B_OK; +} Modified: haiku/trunk/src/add-ons/accelerants/radeon_hd/accelerant_protos.h =================================================================== --- haiku/trunk/src/add-ons/accelerants/radeon_hd/accelerant_protos.h 2011-07-30 16:05:28 UTC (rev 42514) +++ haiku/trunk/src/add-ons/accelerants/radeon_hd/accelerant_protos.h 2011-07-30 17:45:14 UTC (rev 42515) @@ -18,11 +18,13 @@ extern "C" { #endif + void spin(bigtime_t delay); // general status_t radeon_init_accelerant(int fd); void radeon_uninit_accelerant(void); +status_t radeon_get_accelerant_device_info(accelerant_device_info *di); // modes & constraints uint32 radeon_accelerant_mode_count(void); Modified: haiku/trunk/src/add-ons/accelerants/radeon_hd/display.cpp =================================================================== --- haiku/trunk/src/add-ons/accelerants/radeon_hd/display.cpp 2011-07-30 16:05:28 UTC (rev 42514) +++ haiku/trunk/src/add-ons/accelerants/radeon_hd/display.cpp 2011-07-30 17:45:14 UTC (rev 42515) @@ -301,3 +301,30 @@ } + +void +display_power(uint8 crtid, int command) +{ + register_info* regs = gDisplay[crtid]->regs; + + switch (command) { + case RHD_POWER_ON: + Write32Mask(OUT, regs->grphEnable, 0x00000001, 0x00000001); + snooze(2); + Write32Mask(OUT, regs->crtControl, 0, 0x01000000); + // Enable read requests + Write32Mask(OUT, regs->crtControl, 1, 1); + return; + case RHD_POWER_RESET: + Write32Mask(OUT, regs->crtControl, 0x01000000, 0x01000000); + // Disable read requestes + //D1CRTCDisable? + return; + case RHD_POWER_SHUTDOWN: + Write32Mask(OUT, regs->crtControl, 0x01000000, 0x01000000); + // Disable read requests + //D1CRTCDisable? + Write32Mask(OUT, regs->grphEnable, 0x00000001, 0x00000001); + return; + } +} Modified: haiku/trunk/src/add-ons/accelerants/radeon_hd/display.h =================================================================== --- haiku/trunk/src/add-ons/accelerants/radeon_hd/display.h 2011-07-30 16:05:28 UTC (rev 42514) +++ haiku/trunk/src/add-ons/accelerants/radeon_hd/display.h 2011-07-30 17:45:14 UTC (rev 42515) @@ -13,6 +13,7 @@ status_t detect_crt_ranges(uint32 crtid); status_t detect_displays(); void debug_displays(); +void display_power(uint8 crtid, int command); #endif /* RADEON_HD_DISPLAY_H */ Modified: haiku/trunk/src/add-ons/accelerants/radeon_hd/hooks.cpp =================================================================== --- haiku/trunk/src/add-ons/accelerants/radeon_hd/hooks.cpp 2011-07-30 16:05:28 UTC (rev 42514) +++ haiku/trunk/src/add-ons/accelerants/radeon_hd/hooks.cpp 2011-07-30 17:45:14 UTC (rev 42515) @@ -26,11 +26,14 @@ return (void*)radeon_accelerant_clone_info_size; case B_GET_ACCELERANT_CLONE_INFO: return (void*)radeon_get_accelerant_clone_info; + */ case B_GET_ACCELERANT_DEVICE_INFO: return (void*)radeon_get_accelerant_device_info; + /* case B_ACCELERANT_RETRACE_SEMAPHORE: return (void*)radeon_accelerant_retrace_semaphore; -*/ + */ + /* mode configuration */ case B_ACCELERANT_MODE_COUNT: return (void*)radeon_accelerant_mode_count; Modified: haiku/trunk/src/add-ons/accelerants/radeon_hd/mc.cpp =================================================================== --- haiku/trunk/src/add-ons/accelerants/radeon_hd/mc.cpp 2011-07-30 16:05:28 UTC (rev 42514) +++ haiku/trunk/src/add-ons/accelerants/radeon_hd/mc.cpp 2011-07-30 17:45:14 UTC (rev 42515) @@ -28,17 +28,6 @@ #endif -uint64 -MCFBLocation(uint16 chipset, uint32* size) -{ - // TODO : R800 : This is only valid for all R6xx and R7xx? - uint32 fbLocationReg = Read32(MC, R7XX_MC_VM_FB_LOCATION); - *size = (((fbLocationReg & 0xFFFF0000) - - ((fbLocationReg & 0xFFFF) << 16))) << 8; - return (fbLocationReg & 0xFFFF) << 24; -} - - uint32 MCIdle() { @@ -53,23 +42,16 @@ status_t -MCFBSetup(uint32 newFbLocation, uint32 newFbSize) +MCFBSetup() { - uint32 oldFbSize; - uint64 oldFbLocation = MCFBLocation(0, &oldFbSize); + uint32 fb_location_int = gInfo->shared_info->frame_buffer_int; - if (oldFbLocation == newFbLocation - && oldFbSize == newFbSize) { - TRACE("%s: not adjusting frame buffer as it is already correct\n", - __func__); - return B_OK; - } + uint32 fb_location = Read32(OUT, R6XX_MC_VM_FB_LOCATION); + uint16 fb_size = (fb_location >> 16) - (fb_location & 0xFFFF); + uint32 fb_location_tmp = fb_location_int >> 24; + fb_location_tmp |= (fb_location_tmp + fb_size) << 16; + uint32 fb_offset_tmp = (fb_location_int >> 8) & 0xff0000; - if (oldFbLocation >> 32) { - TRACE("%s: board claims to use a frame buffer address > 32-bits\n", - __func__); - } - uint32 idleState = MCIdle(); if (idleState > 0) { TRACE("%s: Cannot modify non-idle MC! idleState: %X\n", @@ -77,13 +59,12 @@ return B_ERROR; } - TRACE("%s: Setting MC/FB from 0x%08X to 0x%08X [size 0x%08X]\n", - __func__, oldFbLocation, newFbLocation, newFbSize); + TRACE("%s: Setting frame buffer from 0x%08X to 0x%08X [size 0x%08X]\n", + __func__, fb_location, fb_location_tmp, fb_size); // The MC Write32 will handle cards needing a special MC read/write register - Write32(MC, R6XX_MC_VM_FB_LOCATION, - R6XX_FB_LOCATION(newFbLocation, newFbSize)); - Write32(MC, R6XX_HDP_NONSURFACE_BASE, R6XX_HDP_LOCATION(newFbLocation)); + Write32(MC, R6XX_MC_VM_FB_LOCATION, fb_location_tmp); + Write32(MC, R6XX_HDP_NONSURFACE_BASE, fb_offset_tmp); return B_OK; } Modified: haiku/trunk/src/add-ons/accelerants/radeon_hd/mc.h =================================================================== --- haiku/trunk/src/add-ons/accelerants/radeon_hd/mc.h 2011-07-30 16:05:28 UTC (rev 42514) +++ haiku/trunk/src/add-ons/accelerants/radeon_hd/mc.h 2011-07-30 17:45:14 UTC (rev 42515) @@ -9,14 +9,8 @@ #define RADEON_HD_MC_H -#define R6XX_FB_LOCATION(address, size) \ - (((((address) + (size)) >> 8) & 0xFFFF0000) | (((address) >> 24) & 0xFFFF)) -#define R6XX_HDP_LOCATION(address) \ - ((((address) >> 8) & 0x00FF0000)) +uint32 MCIdle(); +status_t MCFBSetup(); -uint64 MCFBLocation(uint16 chipset, uint32* size); -status_t MCFBSetup(uint32 newFbLocation, uint32 newFbSize); - - #endif Modified: haiku/trunk/src/add-ons/accelerants/radeon_hd/mode.cpp =================================================================== --- haiku/trunk/src/add-ons/accelerants/radeon_hd/mode.cpp 2011-07-30 16:05:28 UTC (rev 42514) +++ haiku/trunk/src/add-ons/accelerants/radeon_hd/mode.cpp 2011-07-30 17:45:14 UTC (rev 42515) @@ -15,6 +15,7 @@ #include "accelerant.h" #include "utility.h" #include "mode.h" +#include "display.h" #include <stdio.h> #include <string.h> @@ -157,20 +158,16 @@ // VGA // framebuffersize = w * h * bpp = fb bits / 8 = bytes needed - //uint64 fbAddress = gInfo->shared_info->frame_buffer_phys; uint64 fbAddressInt = gInfo->shared_info->frame_buffer_int; - // Set the inital frame buffer location in the memory controler - uint32 mcFbSize; - MCFBLocation(fbAddressInt, &mcFbSize); - //MCFBSetup(gInfo->shared_info->frame_buffer_int, mcFbSize); + MCFBSetup(); Write32(CRT, regs->grphUpdate, (1<<16)); // Lock for update (isn't this normally the other way around on VGA? // Tell GPU which frame buffer address to draw from - Write32(CRT, regs->grphPrimarySurfaceAddr, fbAddressInt & 0xffffffff); - Write32(CRT, regs->grphSecondarySurfaceAddr, fbAddressInt & 0xffffffff); + Write32(CRT, regs->grphPrimarySurfaceAddr, fbAddressInt & 0xFFFFFFFF); + //Write32(CRT, regs->grphSecondarySurfaceAddr, fbAddressInt); if (gInfo->shared_info->device_chipset >= (RADEON_R700 | 0x70)) { Write32(CRT, regs->grphPrimarySurfaceAddrHigh, @@ -247,13 +244,15 @@ Write32(CRT, regs->crtHTotal, displayTiming.h_total - 1); + /* // Blanking - uint16 blankStart = displayTiming.h_total - displayTiming.h_sync_start; - uint16 blankEnd = displayTiming.h_total + uint16 blankStart = displayTiming.h_total + displayTiming.h_display - displayTiming.h_sync_start; + uint16 blankEnd = displayTiming.h_total - displayTiming.h_sync_start; Write32(CRT, regs->crtHBlank, blankStart | (blankEnd << 16)); + */ Write32(CRT, regs->crtHSync, (displayTiming.h_sync_end - displayTiming.h_sync_start) << 16); @@ -266,13 +265,15 @@ Write32(CRT, regs->crtVTotal, displayTiming.v_total - 1); + /* // Blanking - blankStart = displayTiming.v_total - displayTiming.v_sync_start; - blankEnd = displayTiming.v_total + blankStart = displayTiming.v_total + displayTiming.v_display - displayTiming.v_sync_start; + blankEnd = displayTiming.v_total - displayTiming.v_sync_start; Write32(CRT, regs->crtVBlank, blankStart | (blankEnd << 16)); + */ // Set Interlace if specified within mode line if (displayTiming.flags & B_TIMING_INTERLACED) { @@ -303,7 +304,6 @@ register_info* regs = gDisplay[crtid]->regs; // No scaling - Write32(CRT, regs->sclUpdate, (1<<16));// Lock #if 0 Write32(CRT, D1MODE_EXT_OVERSCAN_LEFT_RIGHT, @@ -315,44 +315,76 @@ Write32(CRT, regs->viewportStart, 0); Write32(CRT, regs->viewportSize, mode->timing.v_display | (mode->timing.h_display << 16)); + Write32(CRT, regs->sclEnable, 0); Write32(CRT, regs->sclTapControl, 0); Write32(CRT, regs->modeCenter, 2); // D1MODE_DATA_FORMAT? - Write32(CRT, regs->sclUpdate, 0); // Unlock } status_t radeon_set_display_mode(display_mode *mode) { - uint8 display_id = 0; + // Disable VGA (boo, hiss) + Write32Mask(OUT, VGA_RENDER_CONTROL, 0, 0x00030000); + Write32Mask(OUT, VGA_MODE_CONTROL, 0, 0x00000030); + Write32Mask(OUT, VGA_HDP_CONTROL, 0x00010010, 0x00010010); + Write32(OUT, D1VGA_CONTROL, 0); + Write32(OUT, D2VGA_CONTROL, 0); - CardFBSet(display_id, mode); - CardModeSet(display_id, mode); - CardModeScale(display_id, mode); + // TODO : We set the same VESA EDID mode on each display - // If this is DAC, set our PLL - if ((gDisplay[display_id]->connection_type & CONNECTION_DAC) != 0) { - PLLSet(gDisplay[display_id]->connection_id, mode->timing.pixel_clock); - DACSet(gDisplay[display_id]->connection_id, display_id); + // Set mode on each display + for (uint8 id = 0; id < MAX_DISPLAY; id++) { + // Skip if display is inactive + if (gDisplay[id]->active == false) { + CardBlankSet(id, true); + display_power(id, RHD_POWER_ON); + continue; + } - // TODO : Shutdown unused PLL/DAC + // Program CRT Controller + CardFBSet(id, mode); + CardModeSet(id, mode); + CardModeScale(id, mode); - // Power up the output - PLLPower(gDisplay[display_id]->connection_id, RHD_POWER_ON); - DACPower(gDisplay[display_id]->connection_id, RHD_POWER_ON); - } else if ((gDisplay[display_id]->connection_type & CONNECTION_TMDS) != 0) { - TMDSSet(gDisplay[display_id]->connection_id, mode); - TMDSPower(gDisplay[display_id]->connection_id, RHD_POWER_ON); - } else if ((gDisplay[display_id]->connection_type & CONNECTION_LVDS) != 0) { - LVDSSet(gDisplay[display_id]->connection_id, mode); - LVDSPower(gDisplay[display_id]->connection_id, RHD_POWER_ON); + display_power(id, RHD_POWER_RESET); + + // Program connector controllers + switch (gDisplay[id]->connection_type) { + case CONNECTION_DAC: + PLLSet(gDisplay[id]->connection_id, + mode->timing.pixel_clock); + DACSet(gDisplay[id]->connection_id, id); + break; + case CONNECTION_TMDS: + TMDSSet(gDisplay[id]->connection_id, mode); + break; + case CONNECTION_LVDS: + LVDSSet(gDisplay[id]->connection_id, mode); + break; + } + + // Power CRT Controller + display_power(id, RHD_POWER_ON); + CardBlankSet(id, false); + + // Power connector controllers + switch (gDisplay[id]->connection_type) { + case CONNECTION_DAC: + PLLPower(gDisplay[id]->connection_id, RHD_POWER_ON); + DACPower(gDisplay[id]->connection_id, RHD_POWER_ON); + break; + case CONNECTION_TMDS: + TMDSPower(gDisplay[id]->connection_id, RHD_POWER_ON); + break; + case CONNECTION_LVDS: + LVDSPower(gDisplay[id]->connection_id, RHD_POWER_ON); + break; + } } - // Ensure screen isn't blanked - CardBlankSet(display_id, false); - int32 crtstatus = Read32(CRT, D1CRTC_STATUS); TRACE("CRT0 Status: 0x%X\n", crtstatus); crtstatus = Read32(CRT, D2CRTC_STATUS); Modified: haiku/trunk/src/add-ons/kernel/drivers/graphics/radeon_hd/radeon_hd.cpp =================================================================== --- haiku/trunk/src/add-ons/kernel/drivers/graphics/radeon_hd/radeon_hd.cpp 2011-07-30 16:05:28 UTC (rev 42514) +++ haiku/trunk/src/add-ons/kernel/drivers/graphics/radeon_hd/radeon_hd.cpp 2011-07-30 17:45:14 UTC (rev 42515) @@ -102,6 +102,8 @@ info.shared_info->frame_buffer_int = read32(info.registers + R6XX_CONFIG_FB_BASE); + strcpy(info.shared_info->device_identifier, info.device_identifier); + // Pull active monitor VESA EDID from boot loader edid1_info* edidInfo = (edid1_info*)get_boot_item(EDID_BOOT_INFO, NULL);