radeon_hd: Implement preferred mode

* Add preferredMode display mode to each display.
* If LVDS is detected, set preferredMode based on AtomBIOS
* Fixes blocker #8329 ?
This commit is contained in:
Alexander von Gluck IV
2012-02-21 09:48:11 -06:00
parent 9498da9c14
commit 4bd6c200c1
7 changed files with 79 additions and 25 deletions
@@ -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;
@@ -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);
+12 -11
View File
@@ -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,
@@ -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);
+40 -10
View File
@@ -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;
}
}
}
gDisplay[displayIndex]->active = true;
gDisplay[displayIndex]->connectorIndex = id;
// set physical connector index from gConnector
if (gDisplay[displayIndex]->active != true) {
// Nothing interesting here, move along
continue;
}
init_registers(gDisplay[displayIndex]->regs, displayIndex);
// We found a valid / active display
gDisplay[displayIndex]->connectorIndex = id;
// Populate physical connector index from gConnector
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__);
@@ -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:
@@ -84,6 +84,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)
{