intel_extreme: leverage VBT device type for internal panel
* also handle dp aux on PCH. * tested on Gen7, should work from Gen6. Change-Id: I8d99bcdc10c817e66441a6a644df490dd988a74d Reviewed-on: https://review.haiku-os.org/c/haiku/+/5290 Tested-by: Commit checker robot <no-reply+buildbot@haiku-os.org> Reviewed-by: Jérôme Duval <jerome.duval@gmail.com>
This commit is contained in:
parent
d98fcb7db6
commit
1c23e6bcf1
@ -289,6 +289,22 @@ struct ring_buffer {
|
|||||||
struct child_device_config {
|
struct child_device_config {
|
||||||
uint16 handle;
|
uint16 handle;
|
||||||
uint16 device_type;
|
uint16 device_type;
|
||||||
|
#define DEVICE_TYPE_ANALOG_OUTPUT (1 << 0)
|
||||||
|
#define DEVICE_TYPE_DIGITAL_OUTPUT (1 << 1)
|
||||||
|
#define DEVICE_TYPE_DISPLAYPORT_OUTPUT (1 << 2)
|
||||||
|
#define DEVICE_TYPE_VIDEO_SIGNALING (1 << 3)
|
||||||
|
#define DEVICE_TYPE_TMDS_DVI_SIGNALING (1 << 4)
|
||||||
|
#define DEVICE_TYPE_LVDS_SIGNALING (1 << 5)
|
||||||
|
#define DEVICE_TYPE_HIGH_SPEED_LINK (1 << 6)
|
||||||
|
#define DEVICE_TYPE_DUAL_CHANNEL (1 << 8)
|
||||||
|
#define DEVICE_TYPE_COMPOSITE_OUTPUT (1 << 9)
|
||||||
|
#define DEVICE_TYPE_MIPI_OUTPUT (1 << 10)
|
||||||
|
#define DEVICE_TYPE_NOT_HDMI_OUTPUT (1 << 11)
|
||||||
|
#define DEVICE_TYPE_INTERNAL_CONNECTOR (1 << 12)
|
||||||
|
#define DEVICE_TYPE_HOTPLUG_SIGNALING (1 << 13)
|
||||||
|
#define DEVICE_TYPE_POWER_MANAGEMENT (1 << 14)
|
||||||
|
#define DEVICE_TYPE_CLASS_EXTENSION (1 << 15)
|
||||||
|
|
||||||
uint8 device_id[10];
|
uint8 device_id[10];
|
||||||
uint16 addin_offset;
|
uint16 addin_offset;
|
||||||
uint8 dvo_port;
|
uint8 dvo_port;
|
||||||
@ -1112,6 +1128,15 @@ struct intel_brightness_legacy {
|
|||||||
(_DPA_AUX_CH_CTL + (_DPB_AUX_CH_CTL - _DPA_AUX_CH_CTL) * aux)
|
(_DPA_AUX_CH_CTL + (_DPB_AUX_CH_CTL - _DPA_AUX_CH_CTL) * aux)
|
||||||
#define DP_AUX_CH_DATA(aux, i) \
|
#define DP_AUX_CH_DATA(aux, i) \
|
||||||
(_DPA_AUX_CH_DATA1 + (_DPB_AUX_CH_DATA1 - _DPA_AUX_CH_DATA1) * aux + i * 4)
|
(_DPA_AUX_CH_DATA1 + (_DPB_AUX_CH_DATA1 - _DPA_AUX_CH_DATA1) * aux + i * 4)
|
||||||
|
#define _PCH_DPB_AUX_CH_CTL (0x4110 | REGS_SOUTH_TRANSCODER_PORT)
|
||||||
|
#define _PCH_DPB_AUX_CH_DATA1 (0x4114 | REGS_SOUTH_TRANSCODER_PORT)
|
||||||
|
#define _PCH_DPC_AUX_CH_CTL (0x4210 | REGS_SOUTH_TRANSCODER_PORT)
|
||||||
|
#define _PCH_DPC_AUX_CH_DATA1 (0x4214 | REGS_SOUTH_TRANSCODER_PORT)
|
||||||
|
#define PCH_DP_AUX_CH_CTL(aux) \
|
||||||
|
(_PCH_DPB_AUX_CH_CTL + (_PCH_DPC_AUX_CH_CTL - _PCH_DPB_AUX_CH_CTL) * (aux - AUX_CH_B))
|
||||||
|
#define PCH_DP_AUX_CH_DATA(aux, i) \
|
||||||
|
(_PCH_DPB_AUX_CH_DATA1 + (_PCH_DPC_AUX_CH_DATA1 - _PCH_DPB_AUX_CH_DATA1) * (aux - AUX_CH_B) \
|
||||||
|
+ i * 4)
|
||||||
|
|
||||||
#define INTEL_DP_AUX_CTL_BUSY (1 << 31)
|
#define INTEL_DP_AUX_CTL_BUSY (1 << 31)
|
||||||
#define INTEL_DP_AUX_CTL_DONE (1 << 30)
|
#define INTEL_DP_AUX_CTL_DONE (1 << 30)
|
||||||
|
@ -457,6 +457,17 @@ Port::_IsDisplayPortInVBT()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool
|
||||||
|
Port::_IsInternalPanelPort()
|
||||||
|
{
|
||||||
|
uint32 foundIndex = 0;
|
||||||
|
if (!_IsPortInVBT(&foundIndex))
|
||||||
|
return false;
|
||||||
|
child_device_config& config = gInfo->shared_info->device_configs[foundIndex];
|
||||||
|
return (config.device_type & DEVICE_TYPE_INTERNAL_CONNECTOR) == DEVICE_TYPE_INTERNAL_CONNECTOR;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// #pragma mark - Analog Port
|
// #pragma mark - Analog Port
|
||||||
|
|
||||||
|
|
||||||
@ -1224,7 +1235,8 @@ DisplayPort::IsConnected()
|
|||||||
TRACE("%s: %s link detected\n", __func__, PortName());
|
TRACE("%s: %s link detected\n", __func__, PortName());
|
||||||
|
|
||||||
// On laptops we always have an internal panel.. (this is on the eDP port)
|
// On laptops we always have an internal panel.. (this is on the eDP port)
|
||||||
if (gInfo->shared_info->device_type.IsMobile() && (PortIndex() == INTEL_PORT_A)) {
|
if ((gInfo->shared_info->device_type.IsMobile() || _IsInternalPanelPort())
|
||||||
|
&& (PortIndex() == INTEL_PORT_A)) {
|
||||||
if (gInfo->shared_info->has_vesa_edid_info) {
|
if (gInfo->shared_info->has_vesa_edid_info) {
|
||||||
TRACE("%s: Laptop. Using VESA edid info\n", __func__);
|
TRACE("%s: Laptop. Using VESA edid info\n", __func__);
|
||||||
memcpy(&fEDIDInfo, &gInfo->shared_info->vesa_edid_info,
|
memcpy(&fEDIDInfo, &gInfo->shared_info->vesa_edid_info,
|
||||||
@ -1260,7 +1272,7 @@ DigitalDisplayInterface::SetupI2c(i2c_bus *bus)
|
|||||||
CALLED();
|
CALLED();
|
||||||
|
|
||||||
const uint32 deviceConfigCount = gInfo->shared_info->device_config_count;
|
const uint32 deviceConfigCount = gInfo->shared_info->device_config_count;
|
||||||
if (gInfo->shared_info->device_type.Generation() >= 9 && deviceConfigCount > 0) {
|
if (gInfo->shared_info->device_type.Generation() >= 6 && deviceConfigCount > 0) {
|
||||||
if (!_IsDisplayPortInVBT())
|
if (!_IsDisplayPortInVBT())
|
||||||
return Port::SetupI2c(bus);
|
return Port::SetupI2c(bus);
|
||||||
}
|
}
|
||||||
@ -1510,11 +1522,16 @@ DigitalDisplayInterface::_DpAuxTransfer(uint8* transmitBuffer, uint8 transmitSiz
|
|||||||
{
|
{
|
||||||
addr_t channelControl;
|
addr_t channelControl;
|
||||||
addr_t channelData[5];
|
addr_t channelData[5];
|
||||||
if (gInfo->shared_info->device_type.Generation() >= 9) {
|
aux_channel channel = _DpAuxChannel();
|
||||||
// assume AUX channel 0
|
if (gInfo->shared_info->device_type.Generation() >= 9
|
||||||
channelControl = DP_AUX_CH_CTL(_DpAuxChannel());
|
|| (gInfo->shared_info->pch_info != INTEL_PCH_NONE && channel == AUX_CH_A)) {
|
||||||
|
channelControl = DP_AUX_CH_CTL(channel);
|
||||||
for (int i = 0; i < 5; i++)
|
for (int i = 0; i < 5; i++)
|
||||||
channelData[i] = DP_AUX_CH_DATA(_DpAuxChannel(), i);
|
channelData[i] = DP_AUX_CH_DATA(channel, i);
|
||||||
|
} else if (gInfo->shared_info->pch_info != INTEL_PCH_NONE) {
|
||||||
|
channelControl = PCH_DP_AUX_CH_CTL(channel);
|
||||||
|
for (int i = 0; i < 5; i++)
|
||||||
|
channelData[i] = PCH_DP_AUX_CH_DATA(channel, i);
|
||||||
} else {
|
} else {
|
||||||
ERROR("DigitalDisplayInterface::_DpAuxTransfer() unknown register config\n");
|
ERROR("DigitalDisplayInterface::_DpAuxTransfer() unknown register config\n");
|
||||||
return B_BUSY;
|
return B_BUSY;
|
||||||
@ -1537,6 +1554,15 @@ DigitalDisplayInterface::_DpAuxTransfer(uint8* transmitBuffer, uint8 transmitSiz
|
|||||||
| INTEL_DP_AUX_CTL_TIMEOUT_ERROR | INTEL_DP_AUX_CTL_TIMEOUT_1600us | INTEL_DP_AUX_CTL_RECEIVE_ERROR
|
| INTEL_DP_AUX_CTL_TIMEOUT_ERROR | INTEL_DP_AUX_CTL_TIMEOUT_1600us | INTEL_DP_AUX_CTL_RECEIVE_ERROR
|
||||||
| (transmitSize << INTEL_DP_AUX_CTL_MSG_SIZE_SHIFT) | INTEL_DP_AUX_CTL_FW_SYNC_PULSE_SKL(32)
|
| (transmitSize << INTEL_DP_AUX_CTL_MSG_SIZE_SHIFT) | INTEL_DP_AUX_CTL_FW_SYNC_PULSE_SKL(32)
|
||||||
| INTEL_DP_AUX_CTL_SYNC_PULSE_SKL(32);
|
| INTEL_DP_AUX_CTL_SYNC_PULSE_SKL(32);
|
||||||
|
} else {
|
||||||
|
uint32 aux_clock_divider = 0xe1; // TODO: value for 450Mhz
|
||||||
|
uint32 timeout = INTEL_DP_AUX_CTL_TIMEOUT_400us;
|
||||||
|
if (gInfo->shared_info->device_type.InGroup(INTEL_GROUP_BDW))
|
||||||
|
timeout = INTEL_DP_AUX_CTL_TIMEOUT_600us;
|
||||||
|
sendControl = INTEL_DP_AUX_CTL_BUSY | INTEL_DP_AUX_CTL_DONE | INTEL_DP_AUX_CTL_INTERRUPT
|
||||||
|
| INTEL_DP_AUX_CTL_TIMEOUT_ERROR | timeout | INTEL_DP_AUX_CTL_RECEIVE_ERROR
|
||||||
|
| (transmitSize << INTEL_DP_AUX_CTL_MSG_SIZE_SHIFT) | (3 << INTEL_DP_AUX_CTL_PRECHARGE_2US_SHIFT)
|
||||||
|
| (aux_clock_divider << INTEL_DP_AUX_CTL_BIT_CLOCK_2X_SHIFT);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8 retry;
|
uint8 retry;
|
||||||
@ -1863,7 +1889,8 @@ DisplayPort::SetDisplayMode(display_mode* target, uint32 colorMode)
|
|||||||
} else {
|
} else {
|
||||||
display_timing hardwareTarget = target->timing;
|
display_timing hardwareTarget = target->timing;
|
||||||
bool needsScaling = false;
|
bool needsScaling = false;
|
||||||
if ((PortIndex() == INTEL_PORT_A) && gInfo->shared_info->device_type.IsMobile()) {
|
if ((PortIndex() == INTEL_PORT_A)
|
||||||
|
&& (gInfo->shared_info->device_type.IsMobile() || _IsInternalPanelPort())) {
|
||||||
// For internal panels, we may need to set the timings according to the panel
|
// For internal panels, we may need to set the timings according to the panel
|
||||||
// native video mode, and let the panel fitter do the scaling.
|
// native video mode, and let the panel fitter do the scaling.
|
||||||
// note: upto/including generation 5 laptop panels are still LVDS types, handled elsewhere.
|
// note: upto/including generation 5 laptop panels are still LVDS types, handled elsewhere.
|
||||||
@ -2175,7 +2202,7 @@ DigitalDisplayInterface::IsConnected()
|
|||||||
}
|
}
|
||||||
|
|
||||||
const uint32 deviceConfigCount = gInfo->shared_info->device_config_count;
|
const uint32 deviceConfigCount = gInfo->shared_info->device_config_count;
|
||||||
if (gInfo->shared_info->device_type.Generation() >= 9 && deviceConfigCount > 0) {
|
if (gInfo->shared_info->device_type.Generation() >= 6 && deviceConfigCount > 0) {
|
||||||
// check VBT mapping
|
// check VBT mapping
|
||||||
if (!_IsPortInVBT()) {
|
if (!_IsPortInVBT()) {
|
||||||
TRACE("%s: %s: port not found in VBT\n", __func__, PortName());
|
TRACE("%s: %s: port not found in VBT\n", __func__, PortName());
|
||||||
@ -2192,7 +2219,8 @@ DigitalDisplayInterface::IsConnected()
|
|||||||
|
|
||||||
// On laptops we always have an internal panel.. (on the eDP port on DDI systems, fixed on eDP pipe)
|
// On laptops we always have an internal panel.. (on the eDP port on DDI systems, fixed on eDP pipe)
|
||||||
uint32 pipeState = 0;
|
uint32 pipeState = 0;
|
||||||
if (gInfo->shared_info->device_type.IsMobile() && (PortIndex() == INTEL_PORT_E)) {
|
if ((gInfo->shared_info->device_type.IsMobile() || _IsInternalPanelPort())
|
||||||
|
&& (PortIndex() == INTEL_PORT_E)) {
|
||||||
pipeState = read32(PIPE_DDI_FUNC_CTL_EDP);
|
pipeState = read32(PIPE_DDI_FUNC_CTL_EDP);
|
||||||
TRACE("%s: PIPE_DDI_FUNC_CTL_EDP: 0x%" B_PRIx32 "\n", __func__, pipeState);
|
TRACE("%s: PIPE_DDI_FUNC_CTL_EDP: 0x%" B_PRIx32 "\n", __func__, pipeState);
|
||||||
if (!(pipeState & PIPE_DDI_FUNC_CTL_ENABLE)) {
|
if (!(pipeState & PIPE_DDI_FUNC_CTL_ENABLE)) {
|
||||||
@ -2426,7 +2454,8 @@ DigitalDisplayInterface::SetDisplayMode(display_mode* target, uint32 colorMode)
|
|||||||
|
|
||||||
display_timing hardwareTarget = target->timing;
|
display_timing hardwareTarget = target->timing;
|
||||||
bool needsScaling = false;
|
bool needsScaling = false;
|
||||||
if ((PortIndex() == INTEL_PORT_E) && gInfo->shared_info->device_type.IsMobile()) {
|
if ((PortIndex() == INTEL_PORT_E)
|
||||||
|
&& (gInfo->shared_info->device_type.IsMobile() || _IsInternalPanelPort())) {
|
||||||
// For internal panels, we may need to set the timings according to the panel
|
// For internal panels, we may need to set the timings according to the panel
|
||||||
// native video mode, and let the panel fitter do the scaling.
|
// native video mode, and let the panel fitter do the scaling.
|
||||||
|
|
||||||
|
@ -77,6 +77,7 @@ static status_t _SetI2CSignals(void* cookie, int clock,
|
|||||||
int data);
|
int data);
|
||||||
bool _IsPortInVBT(uint32* foundIndex = NULL);
|
bool _IsPortInVBT(uint32* foundIndex = NULL);
|
||||||
bool _IsDisplayPortInVBT();
|
bool _IsDisplayPortInVBT();
|
||||||
|
bool _IsInternalPanelPort();
|
||||||
|
|
||||||
display_mode fCurrentMode;
|
display_mode fCurrentMode;
|
||||||
Pipe* fPipe;
|
Pipe* fPipe;
|
||||||
|
Loading…
Reference in New Issue
Block a user