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,12 +213,12 @@ struct intel_shared_info {
|
||||
area_id mode_list_area; // area containing display mode list
|
||||
uint32 mode_count;
|
||||
|
||||
display_mode current_mode;
|
||||
display_mode panel_mode; // VBIOS VBT panel mode
|
||||
uint32 bytes_per_row;
|
||||
uint32 bits_per_pixel;
|
||||
uint32 dpms_mode;
|
||||
|
||||
area_id registers_area; // area of memory mapped registers
|
||||
area_id registers_area; // area of memory mapped registers
|
||||
uint32 register_blocks[REGISTER_BLOCK_COUNT];
|
||||
|
||||
uint8* status_page;
|
||||
|
||||
@@ -963,8 +963,24 @@ EmbeddedDisplayPort::EmbeddedDisplayPort()
|
||||
bool
|
||||
EmbeddedDisplayPort::IsConnected()
|
||||
{
|
||||
if (!gInfo->shared_info->device_type.IsMobile())
|
||||
return false;
|
||||
addr_t portRegister = _PortRegister();
|
||||
|
||||
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;
|
||||
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
|
||||
area_id mode_list_area;
|
||||
|
||||
@@ -68,9 +70,6 @@ struct accelerant_info {
|
||||
int device;
|
||||
uint8 head_mode;
|
||||
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
|
||||
extern void wait_for_vblank(void);
|
||||
extern void set_frame_buffer_base(void);
|
||||
extern void save_lvds_mode(void);
|
||||
extern status_t create_mode_list(void);
|
||||
|
||||
// memory.cpp
|
||||
|
||||
@@ -40,6 +40,9 @@
|
||||
#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
|
||||
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
|
||||
| B_DPMS | B_SUPPORTS_OVERLAYS;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
static void
|
||||
@@ -274,7 +278,8 @@ void
|
||||
set_frame_buffer_base()
|
||||
{
|
||||
intel_shared_info &sharedInfo = *gInfo->shared_info;
|
||||
display_mode &mode = sharedInfo.current_mode;
|
||||
display_mode &mode = gInfo->current_mode;
|
||||
|
||||
uint32 baseRegister;
|
||||
uint32 surfaceRegister;
|
||||
|
||||
@@ -320,30 +325,29 @@ create_mode_list(void)
|
||||
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
|
||||
// only the mode set up by the BIOS.
|
||||
|
||||
// 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)
|
||||
& ~(B_PAGE_SIZE - 1);
|
||||
size_t size = (sizeof(display_mode) + B_PAGE_SIZE - 1)
|
||||
& ~(B_PAGE_SIZE - 1);
|
||||
|
||||
display_mode* list;
|
||||
area_id area = create_area("intel extreme modes",
|
||||
(void**)&list, B_ANY_ADDRESS, size, B_NO_LOCK,
|
||||
B_READ_AREA | B_WRITE_AREA);
|
||||
if (area < 0)
|
||||
return area;
|
||||
display_mode* list;
|
||||
area_id area = create_area("intel extreme modes",
|
||||
(void**)&list, B_ANY_ADDRESS, size, B_NO_LOCK,
|
||||
B_READ_AREA | B_WRITE_AREA);
|
||||
if (area < 0)
|
||||
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 = list;
|
||||
gInfo->shared_info->mode_list_area = gInfo->mode_list_area;
|
||||
gInfo->shared_info->mode_count = 1;
|
||||
return B_OK;
|
||||
}
|
||||
gInfo->mode_list_area = area;
|
||||
gInfo->mode_list = list;
|
||||
gInfo->shared_info->mode_list_area = gInfo->mode_list_area;
|
||||
gInfo->shared_info->mode_count = 1;
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
// Otherwise return the 'real' list of modes
|
||||
@@ -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 -
|
||||
|
||||
|
||||
@@ -488,7 +474,7 @@ intel_set_display_mode(display_mode* mode)
|
||||
base) < B_OK) {
|
||||
// oh, how did that happen? Unfortunately, there is no really good way
|
||||
// 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.frame_buffer = 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);
|
||||
|
||||
// update shared info
|
||||
gInfo->current_mode = target;
|
||||
|
||||
// TODO: move to gInfo
|
||||
sharedInfo.bytes_per_row = bytesPerRow;
|
||||
sharedInfo.current_mode = target;
|
||||
sharedInfo.bits_per_pixel = bitsPerPixel;
|
||||
|
||||
set_frame_buffer_base();
|
||||
@@ -637,7 +625,7 @@ intel_get_display_mode(display_mode* _currentMode)
|
||||
{
|
||||
CALLED();
|
||||
|
||||
*_currentMode = gInfo->shared_info->current_mode;
|
||||
*_currentMode = gInfo->current_mode;
|
||||
|
||||
// This seems unreliable. We should always know the current_mode
|
||||
//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;
|
||||
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
|
||||
|| 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
|
||||
set_color_key(const overlay_window* window)
|
||||
{
|
||||
switch (gInfo->shared_info->current_mode.space) {
|
||||
switch (gInfo->current_mode.space) {
|
||||
case B_CMAP8:
|
||||
set_color_key(0, 0, window->blue.value, 0x0, 0x0, 0xff);
|
||||
break;
|
||||
@@ -589,10 +589,10 @@ intel_configure_overlay(overlay_token overlayToken,
|
||||
left = 0;
|
||||
if (top < 0)
|
||||
top = 0;
|
||||
if (right > gInfo->shared_info->current_mode.timing.h_display)
|
||||
right = gInfo->shared_info->current_mode.timing.h_display;
|
||||
if (bottom > gInfo->shared_info->current_mode.timing.v_display)
|
||||
bottom = gInfo->shared_info->current_mode.timing.v_display;
|
||||
if (right > gInfo->current_mode.timing.h_display)
|
||||
right = gInfo->current_mode.timing.h_display;
|
||||
if (bottom > gInfo->current_mode.timing.v_display)
|
||||
bottom = gInfo->current_mode.timing.v_display;
|
||||
if (left >= right || top >= bottom) {
|
||||
// overlay is not within visible bounds
|
||||
hide_overlay();
|
||||
|
||||
@@ -119,8 +119,6 @@ static struct vbios {
|
||||
} vbios;
|
||||
|
||||
|
||||
/* TODO: move code to accelerant, if possible */
|
||||
|
||||
/*! 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
|
||||
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->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->current_mode);
|
||||
&info.shared_info->panel_mode);
|
||||
|
||||
/* at least 855gm can't drive more than one head at time */
|
||||
if (info.device_type.InFamily(INTEL_FAMILY_8xx))
|
||||
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_allocate_memory(intel_info& info, size_t size,
|
||||
size_t alignment, uint32 flags, addr_t* _offset,
|
||||
|
||||
Reference in New Issue
Block a user