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:
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user