hrev43787 adds 3 changesets to branch 'master' old head: 69f78b22c4e6fc6dc7c13a9488e317cf7f6b71b9 new head: 59bfec576dcc58ab342be90facc3c512b9ed0d4a ---------------------------------------------------------------------------- a5e3ee7: radeon_hd: AtomBIOS, correct logic. No functional change 2399d17: radeon_hd: Begin improvement on crtc state control * Try to not blank the crtc when it is alreay disabled * Clean up wording, active now present on display info * Don't lock crtc when doing normal dpms calls, crtc should only be locked during mode set / change 59bfec5: radeon_hd: Better implement GPU idle function * Function only checked for idle and didn't wait for the gpu memory controler to idle. * May resolve mode setting issues on some newer hardware. [ Alexander von Gluck IV <kallisti5@xxxxxxxxxxx> ] ---------------------------------------------------------------------------- 8 files changed, 98 insertions(+), 103 deletions(-) src/add-ons/accelerants/radeon_hd/accelerant.h | 3 +- .../accelerants/radeon_hd/atombios/atom.cpp | 3 +- src/add-ons/accelerants/radeon_hd/display.cpp | 69 ++++++++++++--- src/add-ons/accelerants/radeon_hd/display.h | 1 + src/add-ons/accelerants/radeon_hd/encoder.cpp | 2 +- src/add-ons/accelerants/radeon_hd/gpu.cpp | 70 +++++++--------- src/add-ons/accelerants/radeon_hd/gpu.h | 2 +- src/add-ons/accelerants/radeon_hd/mode.cpp | 51 +---------- ############################################################################ Commit: a5e3ee78eeb19141af775feddfeb200a328d92df URL: http://cgit.haiku-os.org/haiku/commit/?id=a5e3ee7 Author: Alexander von Gluck IV <kallisti5@xxxxxxxxxxx> Date: Wed Feb 22 17:38:15 2012 UTC radeon_hd: AtomBIOS, correct logic. No functional change ---------------------------------------------------------------------------- diff --git a/src/add-ons/accelerants/radeon_hd/atombios/atom.cpp b/src/add-ons/accelerants/radeon_hd/atombios/atom.cpp index 3d71400..e10a2ce 100644 --- a/src/add-ons/accelerants/radeon_hd/atombios/atom.cpp +++ b/src/add-ons/accelerants/radeon_hd/atombios/atom.cpp @@ -969,9 +969,10 @@ atom_op_test(atom_exec_context *ctx, int *ptr, int arg) uint32 dst, src; dst = atom_get_dst(ctx, arg, attr, ptr, NULL, 1); src = atom_get_src(ctx, attr, ptr); + // logic is reversed ctx->ctx->cs_equal = ((dst & src) == 0); TRACE("%s: 0x%" B_PRIX32 " and 0x%" B_PRIX32 " are %s\n", __func__, - dst, src, ctx->ctx->cs_equal ? "EQ" : "NE"); + dst, src, ctx->ctx->cs_equal ? "NE" : "EQ"); } ############################################################################ Commit: 2399d174dc90c63e800c9a7218422a8533d85cae URL: http://cgit.haiku-os.org/haiku/commit/?id=2399d17 Author: Alexander von Gluck IV <kallisti5@xxxxxxxxxxx> Date: Sat Feb 25 15:35:13 2012 UTC radeon_hd: Begin improvement on crtc state control * Try to not blank the crtc when it is alreay disabled * Clean up wording, active now present on display info * Don't lock crtc when doing normal dpms calls, crtc should only be locked during mode set / change ---------------------------------------------------------------------------- diff --git a/src/add-ons/accelerants/radeon_hd/accelerant.h b/src/add-ons/accelerants/radeon_hd/accelerant.h index db8e5b0..ac71a18 100644 --- a/src/add-ons/accelerants/radeon_hd/accelerant.h +++ b/src/add-ons/accelerants/radeon_hd/accelerant.h @@ -161,7 +161,8 @@ typedef struct { typedef struct { - bool active; + bool attached; + bool powered; uint32 connectorIndex; // matches connector id in connector_info register_info* regs; bool found_ranges; diff --git a/src/add-ons/accelerants/radeon_hd/display.cpp b/src/add-ons/accelerants/radeon_hd/display.cpp index 0b79026..9a35988 100644 --- a/src/add-ons/accelerants/radeon_hd/display.cpp +++ b/src/add-ons/accelerants/radeon_hd/display.cpp @@ -245,7 +245,8 @@ detect_displays() { // reset known displays for (uint32 id = 0; id < MAX_DISPLAY; id++) { - gDisplay[id]->active = false; + gDisplay[id]->attached = false; + gDisplay[id]->powered = false; gDisplay[id]->found_ranges = false; } @@ -269,16 +270,16 @@ detect_displays() if (gConnector[id]->type == VIDEO_CONNECTOR_LVDS) { // If plain (non-DP) laptop LVDS, read mode info from AtomBIOS //TRACE("%s: non-DP laptop LVDS detected\n", __func__); - gDisplay[displayIndex]->active + gDisplay[displayIndex]->attached = connector_read_mode_lvds(id, &gDisplay[displayIndex]->preferredMode); } - if (gDisplay[displayIndex]->active == false) { + if (gDisplay[displayIndex]->attached == false) { TRACE("%s: bit-banging ddc for edid on connector %" B_PRIu32 "\n", __func__, id); // Lets try bit-banging edid from connector - gDisplay[displayIndex]->active = + gDisplay[displayIndex]->attached = connector_read_edid(id, &gDisplay[displayIndex]->edid_info); if (gConnector[id]->encoder.type == VIDEO_ENCODER_TVDAC @@ -288,17 +289,17 @@ detect_displays() if (encoder_analog_load_detect(id) != true) { TRACE("%s: no analog load on EDID valid connector " "#%" B_PRIu32 "\n", __func__, id); - gDisplay[displayIndex]->active = false; + gDisplay[displayIndex]->attached = false; } } } - if (gDisplay[displayIndex]->active != true) { + if (gDisplay[displayIndex]->attached != true) { // Nothing interesting here, move along continue; } - // We found a valid / active display + // We found a valid / attached display gDisplay[displayIndex]->connectorIndex = id; // Populate physical connector index from gConnector @@ -317,7 +318,7 @@ detect_displays() displayIndex++; } - // fallback if no active monitors were found + // fallback if no attached monitors were found if (displayIndex == 0) { ERROR("%s: ERROR: 0 attached monitors were found on display connectors." " Injecting first connector as a last resort.\n", __func__); @@ -325,7 +326,7 @@ detect_displays() // skip TV DAC connectors as likely fallback isn't for TV if (gConnector[id]->encoder.type == VIDEO_ENCODER_TVDAC) continue; - gDisplay[0]->active = true; + gDisplay[0]->attached = true; gDisplay[0]->connectorIndex = id; init_registers(gDisplay[0]->regs, 0); if (detect_crt_ranges(0) == B_OK) @@ -334,6 +335,12 @@ detect_displays() } } + // Initial boot state is the first two crtc's powered + if (gDisplay[0]->attached == true) + gDisplay[0]->powered = true; + if (gDisplay[1]->attached == true) + gDisplay[1]->powered = true; + return B_OK; } @@ -343,12 +350,12 @@ debug_displays() { TRACE("Currently detected monitors===============\n"); for (uint32 id = 0; id < MAX_DISPLAY; id++) { - ERROR("Display #%" B_PRIu32 " active = %s\n", - id, gDisplay[id]->active ? "true" : "false"); + ERROR("Display #%" B_PRIu32 " attached = %s\n", + id, gDisplay[id]->attached ? "true" : "false"); uint32 connectorIndex = gDisplay[id]->connectorIndex; - if (gDisplay[id]->active) { + if (gDisplay[id]->attached) { uint32 connectorType = gConnector[connectorIndex]->type; uint32 encoderType = gConnector[connectorIndex]->encoder.type; ERROR(" + connector ID: %" B_PRIu32 "\n", connectorIndex); @@ -412,6 +419,7 @@ void display_crtc_lock(uint8 crtcID, int command) { TRACE("%s\n", __func__); + ENABLE_CRTC_PS_ALLOCATION args; int index = GetIndexIntoMasterTable(COMMAND, UpdateCRTC_DoubleBufferRegisters); @@ -429,6 +437,7 @@ void display_crtc_blank(uint8 crtcID, int command) { TRACE("%s\n", __func__); + BLANK_CRTC_PS_ALLOCATION args; int index = GetIndexIntoMasterTable(COMMAND, BlankCRTC); @@ -437,8 +446,7 @@ display_crtc_blank(uint8 crtcID, int command) args.ucCRTC = crtcID; args.ucBlanking = command; - // DEBUG: Radeon red to know when we are blanked :) - args.usBlackColorRCr = 255; + args.usBlackColorRCr = 0; args.usBlackColorGY = 0; args.usBlackColorBCb = 0; @@ -463,6 +471,39 @@ display_crtc_scale(uint8 crtcID, display_mode* mode) void +display_crtc_dpms(uint8 crtcID, int mode) +{ + + radeon_shared_info &info = *gInfo->shared_info; + + switch (mode) { + case B_DPMS_ON: + TRACE("%s: crtc %" B_PRIu8 " dpms powerup\n", __func__, crtcID); + if (gDisplay[crtcID]->attached == false) + return; + gDisplay[crtcID]->powered = true; + display_crtc_power(crtcID, ATOM_ENABLE); + if (info.dceMajor >= 3) + display_crtc_memreq(crtcID, ATOM_ENABLE); + display_crtc_blank(crtcID, ATOM_BLANKING_OFF); + break; + case B_DPMS_STAND_BY: + case B_DPMS_SUSPEND: + case B_DPMS_OFF: + TRACE("%s: crtc %" B_PRIu8 " dpms powerdown\n", __func__, crtcID); + if (gDisplay[crtcID]->attached == false) + return; + if (gDisplay[crtcID]->powered == true) + display_crtc_blank(crtcID, ATOM_BLANKING); + if (info.dceMajor >= 3) + display_crtc_memreq(crtcID, ATOM_DISABLE); + display_crtc_power(crtcID, ATOM_DISABLE); + gDisplay[crtcID]->powered = false; + } +} + + +void display_crtc_fb_set(uint8 crtcID, display_mode* mode) { radeon_shared_info &info = *gInfo->shared_info; diff --git a/src/add-ons/accelerants/radeon_hd/display.h b/src/add-ons/accelerants/radeon_hd/display.h index b77ce8a..a132647 100644 --- a/src/add-ons/accelerants/radeon_hd/display.h +++ b/src/add-ons/accelerants/radeon_hd/display.h @@ -22,6 +22,7 @@ void debug_displays(); uint32 display_get_encoder_mode(uint32 connectorIndex); void display_crtc_lock(uint8 crtcID, int command); void display_crtc_blank(uint8 crtcID, int command); +void display_crtc_dpms(uint8 crtcID, int mode); void display_crtc_scale(uint8 crtcID, display_mode* mode); void display_crtc_fb_set(uint8 crtcID, display_mode* mode); void display_crtc_set(uint8 crtcID, display_mode* mode); diff --git a/src/add-ons/accelerants/radeon_hd/encoder.cpp b/src/add-ons/accelerants/radeon_hd/encoder.cpp index 0a88ca7..0618d27 100644 --- a/src/add-ons/accelerants/radeon_hd/encoder.cpp +++ b/src/add-ons/accelerants/radeon_hd/encoder.cpp @@ -190,7 +190,7 @@ encoder_pick_dig(uint32 connectorIndex) // obtain assigned CRT uint32 crtcID; for (crtcID = 0; crtcID < MAX_DISPLAY; crtcID++) { - if (gDisplay[crtcID]->active != true) + if (gDisplay[crtcID]->attached != true) continue; if (gDisplay[crtcID]->connectorIndex == connectorIndex) break; diff --git a/src/add-ons/accelerants/radeon_hd/mode.cpp b/src/add-ons/accelerants/radeon_hd/mode.cpp index beb2f88..8fd3a61 100644 --- a/src/add-ons/accelerants/radeon_hd/mode.cpp +++ b/src/add-ons/accelerants/radeon_hd/mode.cpp @@ -147,44 +147,9 @@ radeon_dpms_mode(void) void radeon_dpms_set(int mode) { - radeon_shared_info &info = *gInfo->shared_info; + for (uint8 id = 0; id < MAX_DISPLAY; id++) + display_crtc_dpms(id, mode); - switch (mode) { - case B_DPMS_ON: - TRACE("%s: ON\n", __func__); - for (uint8 id = 0; id < MAX_DISPLAY; id++) { - if (gDisplay[id]->active == false) - continue; - encoder_output_lock(true); - encoder_dpms_set(id, mode); - encoder_output_lock(false); - display_crtc_lock(id, ATOM_ENABLE); - display_crtc_power(id, ATOM_ENABLE); - if (info.dceMajor >= 3) - display_crtc_memreq(id, ATOM_ENABLE); - display_crtc_blank(id, ATOM_BLANKING_OFF); - display_crtc_lock(id, ATOM_DISABLE); - } - break; - case B_DPMS_STAND_BY: - case B_DPMS_SUSPEND: - case B_DPMS_OFF: - TRACE("%s: OFF\n", __func__); - for (uint8 id = 0; id < MAX_DISPLAY; id++) { - if (gDisplay[id]->active == false) - continue; - display_crtc_lock(id, ATOM_ENABLE); - display_crtc_blank(id, ATOM_BLANKING); - if (info.dceMajor >= 3) - display_crtc_memreq(id, ATOM_DISABLE); - display_crtc_power(id, ATOM_DISABLE); - display_crtc_lock(id, ATOM_DISABLE); - encoder_output_lock(true); - encoder_dpms_set(id, mode); - encoder_output_lock(false); - } - break; - } gInfo->dpms_mode = mode; } @@ -196,7 +161,7 @@ radeon_set_display_mode(display_mode* mode) // Set mode on each display for (uint8 id = 0; id < MAX_DISPLAY; id++) { - if (gDisplay[id]->active == false) + if (gDisplay[id]->attached == false) continue; uint16 connectorIndex = gDisplay[id]->connectorIndex; @@ -213,10 +178,7 @@ radeon_set_display_mode(display_mode* mode) // *** CRT controler prep display_crtc_lock(id, ATOM_ENABLE); - display_crtc_blank(id, ATOM_BLANKING); - if (info.dceMajor >= 3) - display_crtc_memreq(id, ATOM_DISABLE); - display_crtc_power(id, ATOM_DISABLE); + display_crtc_dpms(id, B_DPMS_OFF); // *** CRT controler mode set // TODO: program SS @@ -232,10 +194,7 @@ radeon_set_display_mode(display_mode* mode) encoder_mode_set(id, mode->timing.pixel_clock); // *** CRT controler commit - display_crtc_power(id, ATOM_ENABLE); - if (info.dceMajor >= 3) - display_crtc_memreq(id, ATOM_ENABLE); - display_crtc_blank(id, ATOM_BLANKING_OFF); + display_crtc_dpms(id, B_DPMS_ON); display_crtc_lock(id, ATOM_DISABLE); // *** encoder commit ############################################################################ Revision: hrev43787 Commit: 59bfec576dcc58ab342be90facc3c512b9ed0d4a URL: http://cgit.haiku-os.org/haiku/commit/?id=59bfec5 Author: Alexander von Gluck IV <kallisti5@xxxxxxxxxxx> Date: Sat Feb 25 17:02:40 2012 UTC radeon_hd: Better implement GPU idle function * Function only checked for idle and didn't wait for the gpu memory controler to idle. * May resolve mode setting issues on some newer hardware. ---------------------------------------------------------------------------- diff --git a/src/add-ons/accelerants/radeon_hd/gpu.cpp b/src/add-ons/accelerants/radeon_hd/gpu.cpp index 3d3829e..7d7a613 100644 --- a/src/add-ons/accelerants/radeon_hd/gpu.cpp +++ b/src/add-ons/accelerants/radeon_hd/gpu.cpp @@ -45,9 +45,8 @@ radeon_gpu_reset() struct gpu_state gpuState; radeon_gpu_mc_halt(&gpuState); - if (radeon_gpu_mc_idlecheck() > 0) { - ERROR("%s: Timeout waiting for MC to idle!\n", __func__); - } + if (radeon_gpu_mc_idlewait() != B_OK) + ERROR("%s: Couldn't idle memory controller!\n", __func__); if (info.chipsetID < RADEON_CEDAR) { Write32(OUT, CP_ME_CNTL, CP_ME_HALT); @@ -175,7 +174,6 @@ radeon_gpu_mc_halt(gpu_state* gpuState) gpuState->d2crtcControl = Read32(OUT, D2CRTC_CONTROL); // halt all memory controller actions - Write32(OUT, D2CRTC_UPDATE_LOCK, 0); Write32(OUT, VGA_RENDER_CONTROL, 0); Write32(OUT, D1CRTC_UPDATE_LOCK, 1); Write32(OUT, D2CRTC_UPDATE_LOCK, 1); @@ -195,6 +193,7 @@ radeon_gpu_mc_resume(gpu_state* gpuState) Write32(OUT, D1GRPH_SECONDARY_SURFACE_ADDRESS, gInfo->fb.vramStart); Write32(OUT, D2GRPH_PRIMARY_SURFACE_ADDRESS, gInfo->fb.vramStart); Write32(OUT, D2GRPH_SECONDARY_SURFACE_ADDRESS, gInfo->fb.vramStart); + // TODO: Evergreen high surface addresses? Write32(OUT, VGA_MEMORY_BASE_ADDRESS, gInfo->fb.vramStart); // Unlock host access @@ -214,15 +213,23 @@ radeon_gpu_mc_resume(gpu_state* gpuState) } -uint32 -radeon_gpu_mc_idlecheck() +status_t +radeon_gpu_mc_idlewait() { uint32 idleStatus; uint32 busyBits = (VMC_BUSY | MCB_BUSY | MCDZ_BUSY | MCDY_BUSY | MCDX_BUSY | MCDW_BUSY); - if (!((idleStatus = Read32(MC, SRBM_STATUS)) & busyBits)) - return 0; + + uint32 tryCount; + // We give the gpu 0.5 seconds to become idle checking once every 500usec + for (tryCount = 0; tryCount < 1000; tryCount++) { + if (((idleStatus = Read32(MC, SRBM_STATUS)) & busyBits) == 0) + return B_OK; + snooze(500); + } + + ERROR("%s: Couldn't idle SRBM!\n", __func__); bool state; state = (idleStatus & VMC_BUSY) != 0; @@ -238,7 +245,7 @@ radeon_gpu_mc_idlecheck() state = (idleStatus & MCDW_BUSY) != 0; TRACE("%s: MCDW is %s\n", __func__, state ? "busy" : "idle"); - return idleStatus; + return B_TIMED_OUT; } @@ -261,11 +268,8 @@ radeon_gpu_mc_setup_r600() struct gpu_state gpuState; radeon_gpu_mc_halt(&gpuState); - uint32 idleState = radeon_gpu_mc_idlecheck(); - if (idleState > 0) { - ERROR("%s: Modifying non-idle Memory Controller! " - " idlestate: 0x%" B_PRIX32 "\n", __func__, idleState); - } + if (radeon_gpu_mc_idlewait() != B_OK) + ERROR("%s: Modifying non-idle memory controller!\n", __func__); // TODO: Memory Controller AGP Write32(OUT, R600_MC_VM_SYSTEM_APERTURE_LOW_ADDR, @@ -291,11 +295,9 @@ radeon_gpu_mc_setup_r600() Write32(OUT, R600_MC_VM_AGP_TOP, 0x0FFFFFFF); Write32(OUT, R600_MC_VM_AGP_BOT, 0x0FFFFFFF); - idleState = radeon_gpu_mc_idlecheck(); - if (idleState > 0) { - ERROR("%s: Modifying non-idle Memory Controller! " - " idlestate: 0x%" B_PRIX32 "\n", __func__, idleState); - } + if (radeon_gpu_mc_idlewait() != B_OK) + ERROR("%s: Modifying non-idle memory controller!\n", __func__); + radeon_gpu_mc_resume(&gpuState); // disable render control @@ -326,11 +328,8 @@ radeon_gpu_mc_setup_r700() struct gpu_state gpuState; radeon_gpu_mc_halt(&gpuState); - uint32 idleState = radeon_gpu_mc_idlecheck(); - if (idleState > 0) { - ERROR("%s: Modifying non-idle Memory Controller! " - " idlestate: 0x%" B_PRIX32 "\n", __func__, idleState); - } + if (radeon_gpu_mc_idlewait() != B_OK) + ERROR("%s: Modifying non-idle memory controller!\n", __func__); Write32(OUT, VGA_HDP_CONTROL, VGA_MEMORY_DISABLE); @@ -358,11 +357,9 @@ radeon_gpu_mc_setup_r700() Write32(OUT, R700_MC_VM_AGP_TOP, 0x0FFFFFFF); Write32(OUT, R700_MC_VM_AGP_BOT, 0x0FFFFFFF); - idleState = radeon_gpu_mc_idlecheck(); - if (idleState > 0) { - ERROR("%s: Modifying non-idle Memory Controller! " - " idlestate: 0x%" B_PRIX32 "\n", __func__, idleState); - } + if (radeon_gpu_mc_idlewait() != B_OK) + ERROR("%s: Modifying non-idle memory controller!\n", __func__); + radeon_gpu_mc_resume(&gpuState); // disable render control @@ -391,11 +388,8 @@ radeon_gpu_mc_setup_evergreen() struct gpu_state gpuState; radeon_gpu_mc_halt(&gpuState); - uint32 idleState = radeon_gpu_mc_idlecheck(); - if (idleState > 0) { - ERROR("%s: Modifying non-idle Memory Controller! " - " idlestate: 0x%" B_PRIX32 "\n", __func__, idleState); - } + if (radeon_gpu_mc_idlewait() != B_OK) + ERROR("%s: Modifying non-idle memory controller!\n", __func__); Write32(OUT, VGA_HDP_CONTROL, VGA_MEMORY_DISABLE); @@ -434,11 +428,9 @@ radeon_gpu_mc_setup_evergreen() Write32(OUT, EVERGREEN_MC_VM_AGP_TOP, 0x0FFFFFFF); Write32(OUT, EVERGREEN_MC_VM_AGP_BOT, 0x0FFFFFFF); - idleState = radeon_gpu_mc_idlecheck(); - if (idleState > 0) { - ERROR("%s: Modifying non-idle Memory Controller! " - " idlestate: 0x%" B_PRIX32 "\n", __func__, idleState); - } + if (radeon_gpu_mc_idlewait() != B_OK) + ERROR("%s: Modifying non-idle memory controller!\n", __func__); + radeon_gpu_mc_resume(&gpuState); // disable render control diff --git a/src/add-ons/accelerants/radeon_hd/gpu.h b/src/add-ons/accelerants/radeon_hd/gpu.h index 324ba28..a9527d5 100644 --- a/src/add-ons/accelerants/radeon_hd/gpu.h +++ b/src/add-ons/accelerants/radeon_hd/gpu.h @@ -173,7 +173,7 @@ status_t radeon_gpu_reset(); void radeon_gpu_mc_halt(struct gpu_state *gpuState); void radeon_gpu_mc_resume(struct gpu_state *gpuState); -uint32 radeon_gpu_mc_idlecheck(); +status_t radeon_gpu_mc_idlewait(); status_t radeon_gpu_mc_setup(); status_t radeon_gpu_irq_setup(); status_t radeon_gpu_ss_disable();