hrev45352 adds 2 changesets to branch 'master' old head: acd512e9c64483a56d4fbec4a46d60ac13910fe4 new head: e43a7e3db6c24b6f3fe649a51c5e88379dd2f567 overview: http://cgit.haiku-os.org/haiku/log/?qt=range&q=e43a7e3+%5Eacd512e ---------------------------------------------------------------------------- 087341f: intel_extreme: reordered functions. * retrieve_current_mode() was not static, but should have been. * static functions come now first, as usual. e43a7e3: intel_extreme: sanitize BIOS mode. * For LVDS output, the sync parameters aren't really used which is why the mode set from the BIOS might not be valid if the PLL hardware would actually be used. * Therefore, we sanitize this mode to make sure it's within allowed parameters so that intel_set_mode() will accept it. * This should fix at least #8132, and #8796. * Sorry for looking into this so late! I obviously messed up testing this before, as my EeePC 900 was actually affected by this, too. [ Axel Dörfler <axeld@xxxxxxxxxxxxxxxx> ] ---------------------------------------------------------------------------- 1 file changed, 141 insertions(+), 133 deletions(-) src/add-ons/accelerants/intel_extreme/mode.cpp | 274 +++++++++++---------- ############################################################################ Commit: 087341fcfb283fb115f296c83c9e5486c0381089 URL: http://cgit.haiku-os.org/haiku/commit/?id=087341f Author: Axel Dörfler <axeld@xxxxxxxxxxxxxxxx> Date: Sun Mar 10 15:50:34 2013 UTC intel_extreme: reordered functions. * retrieve_current_mode() was not static, but should have been. * static functions come now first, as usual. ---------------------------------------------------------------------------- diff --git a/src/add-ons/accelerants/intel_extreme/mode.cpp b/src/add-ons/accelerants/intel_extreme/mode.cpp index f9bf68f..1ddb343 100644 --- a/src/add-ons/accelerants/intel_extreme/mode.cpp +++ b/src/add-ons/accelerants/intel_extreme/mode.cpp @@ -123,122 +123,6 @@ set_i2c_signals(void* cookie, int clock, int data) } -void -set_frame_buffer_base() -{ - intel_shared_info &sharedInfo = *gInfo->shared_info; - display_mode &mode = sharedInfo.current_mode; - uint32 baseRegister; - uint32 surfaceRegister; - - if (gInfo->head_mode & HEAD_MODE_A_ANALOG) { - baseRegister = INTEL_DISPLAY_A_BASE; - surfaceRegister = INTEL_DISPLAY_A_SURFACE; - } else { - baseRegister = INTEL_DISPLAY_B_BASE; - surfaceRegister = INTEL_DISPLAY_B_SURFACE; - } - - if (sharedInfo.device_type.InGroup(INTEL_TYPE_96x) - || sharedInfo.device_type.InGroup(INTEL_TYPE_G4x) - || sharedInfo.device_type.InGroup(INTEL_TYPE_ILK) - || sharedInfo.device_type.InGroup(INTEL_TYPE_SNB) - || sharedInfo.device_type.InGroup(INTEL_TYPE_IVB)) { - write32(baseRegister, mode.v_display_start * sharedInfo.bytes_per_row - + mode.h_display_start * (sharedInfo.bits_per_pixel + 7) / 8); - read32(baseRegister); - write32(surfaceRegister, sharedInfo.frame_buffer_offset); - read32(surfaceRegister); - } else { - write32(baseRegister, sharedInfo.frame_buffer_offset - + mode.v_display_start * sharedInfo.bytes_per_row - + mode.h_display_start * (sharedInfo.bits_per_pixel + 7) / 8); - read32(baseRegister); - } -} - - -/*! Creates the initial mode list of the primary accelerant. - It's called from intel_init_accelerant(). -*/ -status_t -create_mode_list(void) -{ - i2c_bus bus; - bus.cookie = (void*)INTEL_I2C_IO_A; - bus.set_signals = &set_i2c_signals; - bus.get_signals = &get_i2c_signals; - ddc2_init_timing(&bus); - - status_t error = ddc2_read_edid1(&bus, &gInfo->edid_info, NULL, NULL); - if (error == B_OK) { - edid_dump(&gInfo->edid_info); - gInfo->has_edid = true; - } else { - TRACE("getting EDID on port A (analog) failed : %s. " - "Trying on port C (lvds)\n", strerror(error)); - bus.cookie = (void*)INTEL_I2C_IO_C; - error = ddc2_read_edid1(&bus, &gInfo->edid_info, NULL, NULL); - if (error == B_OK) { - edid_dump(&gInfo->edid_info); - gInfo->has_edid = true; - } else { - TRACE("getting EDID on port C failed : %s\n", - strerror(error)); - - // 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); - - 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 < B_OK) - return area; - - memcpy(list, &gInfo->lvds_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; - } - } - } - - // Otherwise return the 'real' list of modes - display_mode* list; - uint32 count = 0; - gInfo->mode_list_area = create_display_modes("intel extreme modes", - gInfo->has_edid ? &gInfo->edid_info : NULL, NULL, 0, NULL, 0, NULL, - &list, &count); - if (gInfo->mode_list_area < B_OK) - return gInfo->mode_list_area; - - gInfo->mode_list = list; - gInfo->shared_info->mode_list_area = gInfo->mode_list_area; - gInfo->shared_info->mode_count = count; - - return B_OK; -} - - -void -wait_for_vblank(void) -{ - acquire_sem_etc(gInfo->shared_info->vblank_sem, 1, B_RELATIVE_TIMEOUT, - 25000); - // With the output turned off via DPMS, we might not get any interrupts - // anymore that's why we don't wait forever for it. -} - - static void get_pll_limits(pll_limits &limits) { @@ -398,7 +282,7 @@ compute_pll_divisors(const display_mode ¤t, pll_divisors& divisors, } -void +static void retrieve_current_mode(display_mode& mode, uint32 pllRegister) { uint32 pll = read32(pllRegister); @@ -551,19 +435,6 @@ retrieve_current_mode(display_mode& mode, uint32 pllRegister) } -/*! 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); - gInfo->lvds_panel_mode = biosMode; -} - - static void get_color_space_format(const display_mode &mode, uint32 &colorMode, uint32 &bytesPerRow, uint32 &bitsPerPixel) @@ -633,6 +504,138 @@ sanitize_display_mode(display_mode& mode) } +// #pragma mark - + + +void +set_frame_buffer_base() +{ + intel_shared_info &sharedInfo = *gInfo->shared_info; + display_mode &mode = sharedInfo.current_mode; + uint32 baseRegister; + uint32 surfaceRegister; + + if (gInfo->head_mode & HEAD_MODE_A_ANALOG) { + baseRegister = INTEL_DISPLAY_A_BASE; + surfaceRegister = INTEL_DISPLAY_A_SURFACE; + } else { + baseRegister = INTEL_DISPLAY_B_BASE; + surfaceRegister = INTEL_DISPLAY_B_SURFACE; + } + + if (sharedInfo.device_type.InGroup(INTEL_TYPE_96x) + || sharedInfo.device_type.InGroup(INTEL_TYPE_G4x) + || sharedInfo.device_type.InGroup(INTEL_TYPE_ILK) + || sharedInfo.device_type.InGroup(INTEL_TYPE_SNB) + || sharedInfo.device_type.InGroup(INTEL_TYPE_IVB)) { + write32(baseRegister, mode.v_display_start * sharedInfo.bytes_per_row + + mode.h_display_start * (sharedInfo.bits_per_pixel + 7) / 8); + read32(baseRegister); + write32(surfaceRegister, sharedInfo.frame_buffer_offset); + read32(surfaceRegister); + } else { + write32(baseRegister, sharedInfo.frame_buffer_offset + + mode.v_display_start * sharedInfo.bytes_per_row + + mode.h_display_start * (sharedInfo.bits_per_pixel + 7) / 8); + read32(baseRegister); + } +} + + +/*! Creates the initial mode list of the primary accelerant. + It's called from intel_init_accelerant(). +*/ +status_t +create_mode_list(void) +{ + i2c_bus bus; + bus.cookie = (void*)INTEL_I2C_IO_A; + bus.set_signals = &set_i2c_signals; + bus.get_signals = &get_i2c_signals; + ddc2_init_timing(&bus); + + status_t error = ddc2_read_edid1(&bus, &gInfo->edid_info, NULL, NULL); + if (error == B_OK) { + edid_dump(&gInfo->edid_info); + gInfo->has_edid = true; + } else { + TRACE("getting EDID on port A (analog) failed : %s. " + "Trying on port C (lvds)\n", strerror(error)); + bus.cookie = (void*)INTEL_I2C_IO_C; + error = ddc2_read_edid1(&bus, &gInfo->edid_info, NULL, NULL); + if (error == B_OK) { + edid_dump(&gInfo->edid_info); + gInfo->has_edid = true; + } else { + TRACE("getting EDID on port C failed : %s\n", + strerror(error)); + + // 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); + + 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 < B_OK) + return area; + + memcpy(list, &gInfo->lvds_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; + } + } + } + + // Otherwise return the 'real' list of modes + display_mode* list; + uint32 count = 0; + gInfo->mode_list_area = create_display_modes("intel extreme modes", + gInfo->has_edid ? &gInfo->edid_info : NULL, NULL, 0, NULL, 0, NULL, + &list, &count); + if (gInfo->mode_list_area < B_OK) + return gInfo->mode_list_area; + + gInfo->mode_list = list; + gInfo->shared_info->mode_list_area = gInfo->mode_list_area; + gInfo->shared_info->mode_count = count; + + return B_OK; +} + + +void +wait_for_vblank(void) +{ + acquire_sem_etc(gInfo->shared_info->vblank_sem, 1, B_RELATIVE_TIMEOUT, + 25000); + // With the output turned off via DPMS, we might not get any interrupts + // anymore that's why we don't wait forever for it. +} + + +/*! 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); + gInfo->lvds_panel_mode = biosMode; +} + + // #pragma mark - @@ -667,14 +670,14 @@ intel_propose_display_mode(display_mode* target, const display_mode* low, // configurations. for (uint32 i = 0; i < gInfo->shared_info->mode_count; i++) { display_mode *mode = &gInfo->mode_list[i]; - + // TODO: improve this, ie. adapt pixel clock to allowed values!!! - + if (target->virtual_width != mode->virtual_width || target->virtual_height != mode->virtual_height || target->space != mode->space) continue; - + *target = *mode; return B_OK; } ############################################################################ Revision: hrev45352 Commit: e43a7e3db6c24b6f3fe649a51c5e88379dd2f567 URL: http://cgit.haiku-os.org/haiku/commit/?id=e43a7e3 Author: Axel Dörfler <axeld@xxxxxxxxxxxxxxxx> Date: Sun Mar 10 15:54:09 2013 UTC Ticket: https://dev.haiku-os.org/ticket/8132 Ticket: https://dev.haiku-os.org/ticket/8796 intel_extreme: sanitize BIOS mode. * For LVDS output, the sync parameters aren't really used which is why the mode set from the BIOS might not be valid if the PLL hardware would actually be used. * Therefore, we sanitize this mode to make sure it's within allowed parameters so that intel_set_mode() will accept it. * This should fix at least #8132, and #8796. * Sorry for looking into this so late! I obviously messed up testing this before, as my EeePC 900 was actually affected by this, too. ---------------------------------------------------------------------------- diff --git a/src/add-ons/accelerants/intel_extreme/mode.cpp b/src/add-ons/accelerants/intel_extreme/mode.cpp index 1ddb343..76742c1 100644 --- a/src/add-ons/accelerants/intel_extreme/mode.cpp +++ b/src/add-ons/accelerants/intel_extreme/mode.cpp @@ -632,6 +632,11 @@ 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; }