hrev43767 adds 1 changeset to branch 'master' old head: 9498da9c141e258af52351fe72d1b9068a2b0416 new head: 4bd6c200c1a30b78827a0f2852b8ab0995027d1a ---------------------------------------------------------------------------- 4bd6c20: radeon_hd: Implement preferred mode * Add preferredMode display mode to each display. * If LVDS is detected, set preferredMode based on AtomBIOS * Fixes blocker #8329 ? [ Alexander von Gluck IV <kallisti5@xxxxxxxxxxx> ] ---------------------------------------------------------------------------- Revision: hrev43767 Commit: 4bd6c200c1a30b78827a0f2852b8ab0995027d1a URL: http://cgit.haiku-os.org/haiku/commit/?id=4bd6c20 Author: Alexander von Gluck IV <kallisti5@xxxxxxxxxxx> Date: Tue Feb 21 15:47:14 2012 UTC Ticket: https://dev.haiku-os.org/ticket/8329 ---------------------------------------------------------------------------- 7 files changed, 79 insertions(+), 25 deletions(-) src/add-ons/accelerants/radeon_hd/accelerant.h | 4 +- .../accelerants/radeon_hd/accelerant_protos.h | 1 + src/add-ons/accelerants/radeon_hd/connector.cpp | 23 ++++---- src/add-ons/accelerants/radeon_hd/connector.h | 3 +- src/add-ons/accelerants/radeon_hd/display.cpp | 50 ++++++++++++--- src/add-ons/accelerants/radeon_hd/hooks.cpp | 2 + src/add-ons/accelerants/radeon_hd/mode.cpp | 21 +++++++ ---------------------------------------------------------------------------- diff --git a/src/add-ons/accelerants/radeon_hd/accelerant.h b/src/add-ons/accelerants/radeon_hd/accelerant.h index 9e3dd51..db8e5b0 100644 --- a/src/add-ons/accelerants/radeon_hd/accelerant.h +++ b/src/add-ons/accelerants/radeon_hd/accelerant.h @@ -69,9 +69,6 @@ struct accelerant_info { struct fb_info fb; // used for frame buffer info within MC volatile uint32 dpms_mode; // current driver dpms mode - - // LVDS panel mode passed from the bios/startup. - display_mode lvds_panel_mode; }; @@ -173,6 +170,7 @@ typedef struct { uint32 hfreq_max; uint32 hfreq_min; edid1_info edid_info; + display_mode preferredMode; } display_info; diff --git a/src/add-ons/accelerants/radeon_hd/accelerant_protos.h b/src/add-ons/accelerants/radeon_hd/accelerant_protos.h index 8731165..1f75ee3 100644 --- a/src/add-ons/accelerants/radeon_hd/accelerant_protos.h +++ b/src/add-ons/accelerants/radeon_hd/accelerant_protos.h @@ -32,6 +32,7 @@ uint32 radeon_accelerant_mode_count(void); status_t radeon_get_mode_list(display_mode* dm); status_t radeon_set_display_mode(display_mode* mode); status_t radeon_get_display_mode(display_mode* currentMode); +status_t radeon_get_preferred_mode(display_mode* preferredMode); status_t radeon_get_frame_buffer_config(frame_buffer_config* config); status_t radeon_get_pixel_clock_limits(display_mode* mode, uint32* low, uint32* high); diff --git a/src/add-ons/accelerants/radeon_hd/connector.cpp b/src/add-ons/accelerants/radeon_hd/connector.cpp index 1a96239..9134526 100644 --- a/src/add-ons/accelerants/radeon_hd/connector.cpp +++ b/src/add-ons/accelerants/radeon_hd/connector.cpp @@ -121,16 +121,10 @@ connector_read_edid(uint32 connectorIndex, edid1_info* edid) { // ensure things are sane uint32 gpioID = gConnector[connectorIndex]->gpioID; - if (gGPIOInfo[gpioID]->valid == false) + if (gGPIOInfo[gpioID]->valid == false) { + ERROR("%s: invalid gpio %" B_PRIu32 " for connector %" B_PRIu32 "\n", + __func__, gpioID, connectorIndex); return false; - - if (gConnector[connectorIndex]->type == VIDEO_CONNECTOR_LVDS) { - ERROR("%s: LCD panel detected (LVDS), sending VESA EDID!\n", - __func__); - // TODO: connector_read_edid_lvds doesn't do anything yet - connector_read_edid_lvds(connectorIndex, edid); - memcpy(edid, &gInfo->shared_info->edid_info, sizeof(struct edid1_info)); - return true; } i2c_bus bus; @@ -155,7 +149,7 @@ connector_read_edid(uint32 connectorIndex, edid1_info* edid) bool -connector_read_edid_lvds(uint32 connectorIndex, edid1_info* edid) +connector_read_mode_lvds(uint32 connectorIndex, display_mode* mode) { uint8 dceMajor; uint8 dceMinor; @@ -224,8 +218,15 @@ connector_read_edid_lvds(uint32 connectorIndex, edid1_info* edid) timing.flags |= MODE_FLAG_DBLSCAN; #endif - // TODO: generate a fake EDID with information above. For now just dump + mode->timing = timing; + mode->h_display_start = 0; + mode->v_display_start = 0; + mode->virtual_width = timing.h_display; + mode->virtual_height = timing.v_display; + // Assume 32-bit color + mode->space = B_RGB32_LITTLE; + TRACE("%s: %" B_PRIu32 " %" B_PRIu16 " %" B_PRIu16 " %" B_PRIu16 " %" B_PRIu16 " %" B_PRIu16 " %" B_PRIu16 " %" B_PRIu16 " %" B_PRIu16 "\n", __func__, timing.pixel_clock, timing.h_display, timing.h_sync_start, diff --git a/src/add-ons/accelerants/radeon_hd/connector.h b/src/add-ons/accelerants/radeon_hd/connector.h index f2c7611..302cc00 100644 --- a/src/add-ons/accelerants/radeon_hd/connector.h +++ b/src/add-ons/accelerants/radeon_hd/connector.h @@ -63,7 +63,8 @@ const int kConnectorConvert[] = { status_t gpio_probe(); status_t connector_attach_gpio(uint32 id, uint8 hwPin); bool connector_read_edid(uint32 connector, edid1_info* edid); -bool connector_read_edid_lvds(uint32 connectorIndex, edid1_info* edid); +bool connector_read_mode_lvds(uint32 connectorIndex, display_mode* mode); + status_t connector_probe(); status_t connector_probe_legacy(); bool connector_is_dp(uint32 connectorIndex); diff --git a/src/add-ons/accelerants/radeon_hd/display.cpp b/src/add-ons/accelerants/radeon_hd/display.cpp index 48697da..0b79026 100644 --- a/src/add-ons/accelerants/radeon_hd/display.cpp +++ b/src/add-ons/accelerants/radeon_hd/display.cpp @@ -256,13 +256,30 @@ detect_displays() if (displayIndex >= MAX_DISPLAY) continue; + // TODO: As DP aux transactions don't work yet, just use LVDS as a hack + #if 0 if (gConnector[id]->encoder.isDPBridge == true) { - // if this is a DisplayPort Bridge, setup ddc on bus + // If this is a DisplayPort Bridge, setup ddc on bus + // TRAVIS (LVDS) or NUTMEG (VGA) TRACE("%s: is bridge, performing bridge DDC setup\n", __func__); - encoder_external_setup(id, 0, EXTERNAL_ENCODER_ACTION_V3_DDC_SETUP); + encoder_external_setup(id, 23860, + EXTERNAL_ENCODER_ACTION_V3_DDC_SETUP); + } else if (gConnector[id]->type == VIDEO_CONNECTOR_LVDS) { + #endif + 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 + = connector_read_mode_lvds(id, + &gDisplay[displayIndex]->preferredMode); } - if (connector_read_edid(id, &gDisplay[displayIndex]->edid_info)) { + if (gDisplay[displayIndex]->active == 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 = + connector_read_edid(id, &gDisplay[displayIndex]->edid_info); if (gConnector[id]->encoder.type == VIDEO_ENCODER_TVDAC || gConnector[id]->encoder.type == VIDEO_ENCODER_DAC) { @@ -271,23 +288,36 @@ detect_displays() if (encoder_analog_load_detect(id) != true) { TRACE("%s: no analog load on EDID valid connector " "#%" B_PRIu32 "\n", __func__, id); - continue; + gDisplay[displayIndex]->active = false; } } + } + + if (gDisplay[displayIndex]->active != true) { + // Nothing interesting here, move along + continue; + } + + // We found a valid / active display - gDisplay[displayIndex]->active = true; - gDisplay[displayIndex]->connectorIndex = id; - // set physical connector index from gConnector + gDisplay[displayIndex]->connectorIndex = id; + // Populate physical connector index from gConnector - init_registers(gDisplay[displayIndex]->regs, displayIndex); + init_registers(gDisplay[displayIndex]->regs, displayIndex); + if (gDisplay[displayIndex]->preferredMode.virtual_width > 0) { + // Found a single preferred mode + gDisplay[displayIndex]->found_ranges = false; + } else { + // Use edid data and pull ranges if (detect_crt_ranges(displayIndex) == B_OK) gDisplay[displayIndex]->found_ranges = true; - displayIndex++; } + + displayIndex++; } - // fallback if no edid monitors were found + // fallback if no active 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__); diff --git a/src/add-ons/accelerants/radeon_hd/hooks.cpp b/src/add-ons/accelerants/radeon_hd/hooks.cpp index 645544b..d57bb73 100644 --- a/src/add-ons/accelerants/radeon_hd/hooks.cpp +++ b/src/add-ons/accelerants/radeon_hd/hooks.cpp @@ -48,6 +48,8 @@ get_accelerant_hook(uint32 feature, void* data) return (void*)radeon_get_edid_info; case B_GET_MODE_LIST: return (void*)radeon_get_mode_list; + case B_GET_PREFERRED_DISPLAY_MODE: + return (void*)radeon_get_preferred_mode; case B_SET_DISPLAY_MODE: return (void*)radeon_set_display_mode; case B_GET_DISPLAY_MODE: diff --git a/src/add-ons/accelerants/radeon_hd/mode.cpp b/src/add-ons/accelerants/radeon_hd/mode.cpp index 394cd28..beb2f88 100644 --- a/src/add-ons/accelerants/radeon_hd/mode.cpp +++ b/src/add-ons/accelerants/radeon_hd/mode.cpp @@ -85,6 +85,27 @@ radeon_get_mode_list(display_mode* modeList) status_t +radeon_get_preferred_mode(display_mode* preferredMode) +{ + TRACE("%s\n", __func__); + + // TODO: Argh! Which display? :) + uint8_t crtc = 0; + + if (gDisplay[crtc]->preferredMode.virtual_width > 0 + && gDisplay[crtc]->preferredMode.virtual_height > 0) { + TRACE("%s: preferred mode was found for display %" B_PRIu8 "\n", + __func__, crtc); + memcpy(preferredMode, &gDisplay[crtc]->preferredMode, + sizeof(gDisplay[crtc]->preferredMode)); + return B_OK; + } + + return B_ERROR; +} + + +status_t radeon_get_edid_info(void* info, size_t size, uint32* edid_version) { // TODO: multi-monitor? for now we use VESA edid