intel_extreme: probe all GPIO pins
This commit is contained in:
parent
9965ac0677
commit
cee64ce507
137
src/add-ons/accelerants/intel_extreme/mode.cpp
Normal file → Executable file
137
src/add-ons/accelerants/intel_extreme/mode.cpp
Normal file → Executable file
@ -73,6 +73,12 @@ struct pll_limits {
|
||||
uint32 max_vco;
|
||||
};
|
||||
|
||||
struct gpio_map {
|
||||
const char* name;
|
||||
uint32 pin;
|
||||
uint32 validOn;
|
||||
};
|
||||
|
||||
|
||||
static void mode_fill_missing_bits(display_mode *, uint32);
|
||||
|
||||
@ -579,78 +585,87 @@ set_frame_buffer_base()
|
||||
status_t
|
||||
create_mode_list(void)
|
||||
{
|
||||
i2c_bus bus;
|
||||
bus.cookie = (void*)(addr_t)INTEL_I2C_IO_A;
|
||||
bus.set_signals = &set_i2c_signals;
|
||||
bus.get_signals = &get_i2c_signals;
|
||||
ddc2_init_timing(&bus);
|
||||
// TODO: We may want to choose different GPIO pin maps
|
||||
// for different generations of cards... not sure
|
||||
const gpio_map gpioPinMap[] = {
|
||||
{"ssc", INTEL_I2C_IO_B, 0},
|
||||
{"vga", INTEL_I2C_IO_A, HEAD_MODE_A_ANALOG},
|
||||
{"lvds", INTEL_I2C_IO_C, HEAD_MODE_LVDS_PANEL},
|
||||
{"dpc", INTEL_I2C_IO_D, 0},
|
||||
{"dpb", INTEL_I2C_IO_E, 0},
|
||||
{"dpd", INTEL_I2C_IO_F, 0},
|
||||
};
|
||||
|
||||
// TODO: We may want to do extra validation on gpio validOn
|
||||
// vs the HEAD_MODE_ in head_mode
|
||||
for (uint32 i = 0; i < sizeof(gpioPinMap) / sizeof(gpioPinMap[0]); i++) {
|
||||
i2c_bus bus;
|
||||
bus.cookie = (void*)gpioPinMap[i].pin;
|
||||
bus.set_signals = &set_i2c_signals;
|
||||
bus.get_signals = &get_i2c_signals;
|
||||
ddc2_init_timing(&bus);
|
||||
|
||||
status_t result = ddc2_read_edid1(&bus, &gInfo->edid_info,
|
||||
NULL, NULL);
|
||||
|
||||
if (result != B_OK)
|
||||
continue;
|
||||
|
||||
TRACE("found edid data on gpio '%s'\n", gpioPinMap[i].name);
|
||||
|
||||
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;
|
||||
if (gInfo->shared_info->single_head_locked)
|
||||
gInfo->head_mode = HEAD_MODE_A_ANALOG;
|
||||
} 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 if (gInfo->shared_info->has_vesa_edid_info) {
|
||||
TRACE("getting EDID on port C failed: %s. Use VESA EDID info\n",
|
||||
strerror(error));
|
||||
memcpy(&gInfo->edid_info, &gInfo->shared_info->vesa_edid_info,
|
||||
sizeof(edid1_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)
|
||||
|| ((gInfo->head_mode & HEAD_MODE_LVDS_PANEL) != 0
|
||||
&& gInfo->shared_info->got_vbt)) {
|
||||
size_t size = (sizeof(display_mode) + B_PAGE_SIZE - 1)
|
||||
& ~(B_PAGE_SIZE - 1);
|
||||
// TODO: We may want to probe multiple GPIO pins here
|
||||
// someday and store valid ones for multi-head support.
|
||||
// For now, we break on the first valid one.
|
||||
break;
|
||||
}
|
||||
|
||||
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;
|
||||
if (!gInfo->has_edid) {
|
||||
// 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)
|
||||
|| ((gInfo->head_mode & HEAD_MODE_LVDS_PANEL) != 0
|
||||
&& gInfo->shared_info->got_vbt)) {
|
||||
size_t size = (sizeof(display_mode) + B_PAGE_SIZE - 1)
|
||||
& ~(B_PAGE_SIZE - 1);
|
||||
|
||||
// Prefer information dumped directly from VBT, as the BIOS
|
||||
// one may have display scaling, but only do this if the VBT
|
||||
// resolution is higher than the BIOS one.
|
||||
if (gInfo->shared_info->got_vbt
|
||||
&& gInfo->shared_info->current_mode.virtual_width
|
||||
>= gInfo->lvds_panel_mode.virtual_width
|
||||
&& gInfo->shared_info->current_mode.virtual_height
|
||||
>= gInfo->lvds_panel_mode.virtual_height) {
|
||||
memcpy(list, &gInfo->shared_info->current_mode,
|
||||
sizeof(display_mode));
|
||||
mode_fill_missing_bits(list, INTEL_DISPLAY_B_CONTROL);
|
||||
} else {
|
||||
memcpy(list, &gInfo->lvds_panel_mode,
|
||||
sizeof(display_mode));
|
||||
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;
|
||||
|
||||
if (gInfo->shared_info->got_vbt)
|
||||
TRACE("intel_extreme: ignoring VBT mode.");
|
||||
}
|
||||
// Prefer information dumped directly from VBT, as the BIOS
|
||||
// one may have display scaling, but only do this if the VBT
|
||||
// resolution is higher than the BIOS one.
|
||||
if (gInfo->shared_info->got_vbt
|
||||
&& gInfo->shared_info->current_mode.virtual_width
|
||||
>= gInfo->lvds_panel_mode.virtual_width
|
||||
&& gInfo->shared_info->current_mode.virtual_height
|
||||
>= gInfo->lvds_panel_mode.virtual_height) {
|
||||
memcpy(list, &gInfo->shared_info->current_mode,
|
||||
sizeof(display_mode));
|
||||
mode_fill_missing_bits(list, INTEL_DISPLAY_B_CONTROL);
|
||||
} else {
|
||||
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;
|
||||
if (gInfo->shared_info->got_vbt)
|
||||
TRACE("intel_extreme: ignoring VBT 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;
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user