intel_extreme: Properly use VBIOS panel mode
* Move current_mode into the accelerant as the driver doesn't care. * Record panel_mode in driver and present to accelerant * eDP, if no EDID and mobile, leave edid incomplete. Mode set should notice that and fall back to panel_mode
This commit is contained in:
@@ -213,7 +213,7 @@ struct intel_shared_info {
|
|||||||
area_id mode_list_area; // area containing display mode list
|
area_id mode_list_area; // area containing display mode list
|
||||||
uint32 mode_count;
|
uint32 mode_count;
|
||||||
|
|
||||||
display_mode current_mode;
|
display_mode panel_mode; // VBIOS VBT panel mode
|
||||||
uint32 bytes_per_row;
|
uint32 bytes_per_row;
|
||||||
uint32 bits_per_pixel;
|
uint32 bits_per_pixel;
|
||||||
uint32 dpms_mode;
|
uint32 dpms_mode;
|
||||||
|
|||||||
@@ -963,8 +963,24 @@ EmbeddedDisplayPort::EmbeddedDisplayPort()
|
|||||||
bool
|
bool
|
||||||
EmbeddedDisplayPort::IsConnected()
|
EmbeddedDisplayPort::IsConnected()
|
||||||
{
|
{
|
||||||
if (!gInfo->shared_info->device_type.IsMobile())
|
addr_t portRegister = _PortRegister();
|
||||||
return false;
|
|
||||||
|
|
||||||
return DisplayPort::IsConnected();
|
TRACE("%s: %s PortRegister: 0x%" B_PRIxADDR "\n", __func__, PortName(),
|
||||||
|
portRegister);
|
||||||
|
|
||||||
|
if (!gInfo->shared_info->device_type.IsMobile()) {
|
||||||
|
TRACE("%s: skipping eDP on non-mobile GPU\n", __func__);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((read32(portRegister) & DISPLAY_MONITOR_PORT_DETECTED) == 0) {
|
||||||
|
TRACE("%s: %s link not detected\n", __func__, PortName());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
HasEDID();
|
||||||
|
|
||||||
|
// If eDP has EDID, awesome. We use it.
|
||||||
|
// No EDID? The modesetting code falls back to VBIOS panel_mode
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -40,6 +40,8 @@ struct accelerant_info {
|
|||||||
intel_shared_info* shared_info;
|
intel_shared_info* shared_info;
|
||||||
area_id shared_info_area;
|
area_id shared_info_area;
|
||||||
|
|
||||||
|
display_mode current_mode; // pretty much a hack until per-display modes
|
||||||
|
|
||||||
display_mode* mode_list; // cloned list of standard display modes
|
display_mode* mode_list; // cloned list of standard display modes
|
||||||
area_id mode_list_area;
|
area_id mode_list_area;
|
||||||
|
|
||||||
@@ -68,9 +70,6 @@ struct accelerant_info {
|
|||||||
int device;
|
int device;
|
||||||
uint8 head_mode;
|
uint8 head_mode;
|
||||||
bool is_clone;
|
bool is_clone;
|
||||||
|
|
||||||
// LVDS panel mode passed from the bios/startup.
|
|
||||||
display_mode lvds_panel_mode;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@@ -114,7 +113,6 @@ extern void setup_ring_buffer(ring_buffer &ringBuffer, const char* name);
|
|||||||
// modes.cpp
|
// modes.cpp
|
||||||
extern void wait_for_vblank(void);
|
extern void wait_for_vblank(void);
|
||||||
extern void set_frame_buffer_base(void);
|
extern void set_frame_buffer_base(void);
|
||||||
extern void save_lvds_mode(void);
|
|
||||||
extern status_t create_mode_list(void);
|
extern status_t create_mode_list(void);
|
||||||
|
|
||||||
// memory.cpp
|
// memory.cpp
|
||||||
|
|||||||
@@ -40,6 +40,9 @@
|
|||||||
#define CALLED(x...) TRACE("CALLED %s\n", __PRETTY_FUNCTION__)
|
#define CALLED(x...) TRACE("CALLED %s\n", __PRETTY_FUNCTION__)
|
||||||
|
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
// This hack needs to die. Leaving in for a little while
|
||||||
|
// incase we *really* need it.
|
||||||
static void
|
static void
|
||||||
retrieve_current_mode(display_mode& mode, uint32 pllRegister)
|
retrieve_current_mode(display_mode& mode, uint32 pllRegister)
|
||||||
{
|
{
|
||||||
@@ -193,6 +196,7 @@ retrieve_current_mode(display_mode& mode, uint32 pllRegister)
|
|||||||
mode.flags = B_8_BIT_DAC | B_HARDWARE_CURSOR | B_PARALLEL_ACCESS
|
mode.flags = B_8_BIT_DAC | B_HARDWARE_CURSOR | B_PARALLEL_ACCESS
|
||||||
| B_DPMS | B_SUPPORTS_OVERLAYS;
|
| B_DPMS | B_SUPPORTS_OVERLAYS;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@@ -274,7 +278,8 @@ void
|
|||||||
set_frame_buffer_base()
|
set_frame_buffer_base()
|
||||||
{
|
{
|
||||||
intel_shared_info &sharedInfo = *gInfo->shared_info;
|
intel_shared_info &sharedInfo = *gInfo->shared_info;
|
||||||
display_mode &mode = sharedInfo.current_mode;
|
display_mode &mode = gInfo->current_mode;
|
||||||
|
|
||||||
uint32 baseRegister;
|
uint32 baseRegister;
|
||||||
uint32 surfaceRegister;
|
uint32 surfaceRegister;
|
||||||
|
|
||||||
@@ -320,12 +325,12 @@ create_mode_list(void)
|
|||||||
gInfo->has_edid = true;
|
gInfo->has_edid = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!gInfo->has_edid) {
|
// If no EDID, but have vbt from driver, use that mode
|
||||||
|
if (!gInfo->has_edid && gInfo->shared_info->got_vbt) {
|
||||||
// We could not read any EDID info. Fallback to creating a list with
|
// We could not read any EDID info. Fallback to creating a list with
|
||||||
// only the mode set up by the BIOS.
|
// only the mode set up by the BIOS.
|
||||||
|
|
||||||
// TODO: support lower modes via scaling and windowing
|
// TODO: support lower modes via scaling and windowing
|
||||||
if ((gInfo->head_mode & HEAD_MODE_LVDS_PANEL) != 0
|
|
||||||
&& (gInfo->head_mode & HEAD_MODE_A_ANALOG) == 0) {
|
|
||||||
size_t size = (sizeof(display_mode) + B_PAGE_SIZE - 1)
|
size_t size = (sizeof(display_mode) + B_PAGE_SIZE - 1)
|
||||||
& ~(B_PAGE_SIZE - 1);
|
& ~(B_PAGE_SIZE - 1);
|
||||||
|
|
||||||
@@ -336,7 +341,7 @@ create_mode_list(void)
|
|||||||
if (area < 0)
|
if (area < 0)
|
||||||
return area;
|
return area;
|
||||||
|
|
||||||
memcpy(list, &gInfo->lvds_panel_mode, sizeof(display_mode));
|
memcpy(list, &gInfo->shared_info->panel_mode, sizeof(display_mode));
|
||||||
|
|
||||||
gInfo->mode_list_area = area;
|
gInfo->mode_list_area = area;
|
||||||
gInfo->mode_list = list;
|
gInfo->mode_list = list;
|
||||||
@@ -344,7 +349,6 @@ create_mode_list(void)
|
|||||||
gInfo->shared_info->mode_count = 1;
|
gInfo->shared_info->mode_count = 1;
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// Otherwise return the 'real' list of modes
|
// Otherwise return the 'real' list of modes
|
||||||
display_mode* list;
|
display_mode* list;
|
||||||
@@ -373,24 +377,6 @@ wait_for_vblank(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*! Store away panel information if identified on startup
|
|
||||||
(used for pipe B->lvds).
|
|
||||||
*/
|
|
||||||
void
|
|
||||||
save_lvds_mode(void)
|
|
||||||
{
|
|
||||||
// dump currently programmed mode.
|
|
||||||
display_mode biosMode;
|
|
||||||
retrieve_current_mode(biosMode, INTEL_DISPLAY_B_PLL);
|
|
||||||
|
|
||||||
sanitize_display_mode(biosMode);
|
|
||||||
// The BIOS mode may not be a valid mode, as LVDS output does not
|
|
||||||
// really care about the sync values
|
|
||||||
|
|
||||||
gInfo->lvds_panel_mode = biosMode;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// #pragma mark -
|
// #pragma mark -
|
||||||
|
|
||||||
|
|
||||||
@@ -488,7 +474,7 @@ intel_set_display_mode(display_mode* mode)
|
|||||||
base) < B_OK) {
|
base) < B_OK) {
|
||||||
// oh, how did that happen? Unfortunately, there is no really good way
|
// oh, how did that happen? Unfortunately, there is no really good way
|
||||||
// back
|
// back
|
||||||
if (intel_allocate_memory(sharedInfo.current_mode.virtual_height
|
if (intel_allocate_memory(gInfo->current_mode.virtual_height
|
||||||
* sharedInfo.bytes_per_row, 0, base) == B_OK) {
|
* sharedInfo.bytes_per_row, 0, base) == B_OK) {
|
||||||
sharedInfo.frame_buffer = base;
|
sharedInfo.frame_buffer = base;
|
||||||
sharedInfo.frame_buffer_offset = base
|
sharedInfo.frame_buffer_offset = base
|
||||||
@@ -618,8 +604,10 @@ intel_set_display_mode(display_mode* mode)
|
|||||||
write32(INTEL_DISPLAY_B_BYTES_PER_ROW, bytesPerRow);
|
write32(INTEL_DISPLAY_B_BYTES_PER_ROW, bytesPerRow);
|
||||||
|
|
||||||
// update shared info
|
// update shared info
|
||||||
|
gInfo->current_mode = target;
|
||||||
|
|
||||||
|
// TODO: move to gInfo
|
||||||
sharedInfo.bytes_per_row = bytesPerRow;
|
sharedInfo.bytes_per_row = bytesPerRow;
|
||||||
sharedInfo.current_mode = target;
|
|
||||||
sharedInfo.bits_per_pixel = bitsPerPixel;
|
sharedInfo.bits_per_pixel = bitsPerPixel;
|
||||||
|
|
||||||
set_frame_buffer_base();
|
set_frame_buffer_base();
|
||||||
@@ -637,7 +625,7 @@ intel_get_display_mode(display_mode* _currentMode)
|
|||||||
{
|
{
|
||||||
CALLED();
|
CALLED();
|
||||||
|
|
||||||
*_currentMode = gInfo->shared_info->current_mode;
|
*_currentMode = gInfo->current_mode;
|
||||||
|
|
||||||
// This seems unreliable. We should always know the current_mode
|
// This seems unreliable. We should always know the current_mode
|
||||||
//retrieve_current_mode(*_currentMode, INTEL_DISPLAY_A_PLL);
|
//retrieve_current_mode(*_currentMode, INTEL_DISPLAY_A_PLL);
|
||||||
@@ -710,7 +698,7 @@ intel_move_display(uint16 horizontalStart, uint16 verticalStart)
|
|||||||
intel_shared_info &sharedInfo = *gInfo->shared_info;
|
intel_shared_info &sharedInfo = *gInfo->shared_info;
|
||||||
Autolock locker(sharedInfo.accelerant_lock);
|
Autolock locker(sharedInfo.accelerant_lock);
|
||||||
|
|
||||||
display_mode &mode = sharedInfo.current_mode;
|
display_mode &mode = gInfo->current_mode;
|
||||||
|
|
||||||
if (horizontalStart + mode.timing.h_display > mode.virtual_width
|
if (horizontalStart + mode.timing.h_display > mode.virtual_width
|
||||||
|| verticalStart + mode.timing.v_display > mode.virtual_height)
|
|| verticalStart + mode.timing.v_display > mode.virtual_height)
|
||||||
|
|||||||
@@ -207,7 +207,7 @@ set_color_key(uint8 red, uint8 green, uint8 blue, uint8 redMask,
|
|||||||
static void
|
static void
|
||||||
set_color_key(const overlay_window* window)
|
set_color_key(const overlay_window* window)
|
||||||
{
|
{
|
||||||
switch (gInfo->shared_info->current_mode.space) {
|
switch (gInfo->current_mode.space) {
|
||||||
case B_CMAP8:
|
case B_CMAP8:
|
||||||
set_color_key(0, 0, window->blue.value, 0x0, 0x0, 0xff);
|
set_color_key(0, 0, window->blue.value, 0x0, 0x0, 0xff);
|
||||||
break;
|
break;
|
||||||
@@ -589,10 +589,10 @@ intel_configure_overlay(overlay_token overlayToken,
|
|||||||
left = 0;
|
left = 0;
|
||||||
if (top < 0)
|
if (top < 0)
|
||||||
top = 0;
|
top = 0;
|
||||||
if (right > gInfo->shared_info->current_mode.timing.h_display)
|
if (right > gInfo->current_mode.timing.h_display)
|
||||||
right = gInfo->shared_info->current_mode.timing.h_display;
|
right = gInfo->current_mode.timing.h_display;
|
||||||
if (bottom > gInfo->shared_info->current_mode.timing.v_display)
|
if (bottom > gInfo->current_mode.timing.v_display)
|
||||||
bottom = gInfo->shared_info->current_mode.timing.v_display;
|
bottom = gInfo->current_mode.timing.v_display;
|
||||||
if (left >= right || top >= bottom) {
|
if (left >= right || top >= bottom) {
|
||||||
// overlay is not within visible bounds
|
// overlay is not within visible bounds
|
||||||
hide_overlay();
|
hide_overlay();
|
||||||
|
|||||||
@@ -119,8 +119,6 @@ static struct vbios {
|
|||||||
} vbios;
|
} vbios;
|
||||||
|
|
||||||
|
|
||||||
/* TODO: move code to accelerant, if possible */
|
|
||||||
|
|
||||||
/*! This is reimplementation, Haiku uses BIOS call and gets most current panel
|
/*! This is reimplementation, Haiku uses BIOS call and gets most current panel
|
||||||
info, we're, otherwise, digging in VBIOS memory and parsing VBT tables to
|
info, we're, otherwise, digging in VBIOS memory and parsing VBT tables to
|
||||||
get native panel timings. This will allow to get non-updated,
|
get native panel timings. This will allow to get non-updated,
|
||||||
|
|||||||
@@ -405,8 +405,10 @@ intel_extreme_init(intel_info &info)
|
|||||||
info.shared_info->frame_buffer = 0;
|
info.shared_info->frame_buffer = 0;
|
||||||
info.shared_info->dpms_mode = B_DPMS_ON;
|
info.shared_info->dpms_mode = B_DPMS_ON;
|
||||||
|
|
||||||
|
// Pull VBIOS panel mode for later use
|
||||||
info.shared_info->got_vbt = get_lvds_mode_from_bios(
|
info.shared_info->got_vbt = get_lvds_mode_from_bios(
|
||||||
&info.shared_info->current_mode);
|
&info.shared_info->panel_mode);
|
||||||
|
|
||||||
/* at least 855gm can't drive more than one head at time */
|
/* at least 855gm can't drive more than one head at time */
|
||||||
if (info.device_type.InFamily(INTEL_FAMILY_8xx))
|
if (info.device_type.InFamily(INTEL_FAMILY_8xx))
|
||||||
info.shared_info->single_head_locked = 1;
|
info.shared_info->single_head_locked = 1;
|
||||||
|
|||||||
@@ -70,7 +70,7 @@ find_reg(const intel_info& info, uint32 target)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
extern bool get_lvds_mode_from_bios(display_mode *shared_info);
|
extern bool get_lvds_mode_from_bios(display_mode *mode);
|
||||||
extern status_t intel_free_memory(intel_info& info, addr_t offset);
|
extern status_t intel_free_memory(intel_info& info, addr_t offset);
|
||||||
extern status_t intel_allocate_memory(intel_info& info, size_t size,
|
extern status_t intel_allocate_memory(intel_info& info, size_t size,
|
||||||
size_t alignment, uint32 flags, addr_t* _offset,
|
size_t alignment, uint32 flags, addr_t* _offset,
|
||||||
|
|||||||
Reference in New Issue
Block a user