intel_extreme: Add pipe selection for ports

This commit is contained in:
Alexander von Gluck IV
2015-11-08 10:39:07 -06:00
parent b809fb52ed
commit 37b903fbc8
5 changed files with 88 additions and 17 deletions
@@ -424,7 +424,7 @@ struct intel_free_graphics_memory {
#define PCH_INTERRUPT_VBLANK_PIPEA_SNB (1 << 7)
#define PCH_INTERRUPT_VBLANK_PIPEB_SNB (1 << 15)
// display ports
// graphics port control
#define DISPLAY_MONITOR_PORT_ENABLED (1UL << 31)
#define DISPLAY_MONITOR_PIPE_B (1UL << 30)
#define DISPLAY_MONITOR_VGA_POLARITY (1UL << 15)
@@ -436,13 +436,14 @@ struct intel_free_graphics_memory {
#define DISPLAY_MONITOR_POLARITY_MASK (3UL << 3)
#define DISPLAY_MONITOR_POSITIVE_HSYNC (1UL << 3)
#define DISPLAY_MONITOR_POSITIVE_VSYNC (2UL << 3)
#define DISPLAY_MONITOR_PORT_DETECTED (1UL << 2) // TMDS/DisplayPort only
#define LVDS_POST2_RATE_SLOW 14 // PLL Divisors
#define LVDS_POST2_RATE_FAST 7
#define LVDS_CLKB_POWER_MASK (3 << 4)
#define LVDS_CLKB_POWER_UP (3 << 4)
#define LVDS_PORT_EN (1 << 31)
#define LVDS_A0A2_CLKA_POWER_UP (3 << 8)
#define LVDS_PIPEB_SELECT (1 << 30)
#define LVDS_B0B3PAIRS_POWER_UP (3 << 2)
#define LVDS_PLL_MODE_LVDS (2 << 26)
#define LVDS_18BIT_DITHER (1 << 25)
@@ -511,9 +512,6 @@ struct intel_free_graphics_memory {
#define INTEL_DISPLAY_PORT_C (0x4200 | REGS_NORTH_PIPE_AND_PORT)
#define INTEL_DISPLAY_PORT_D (0x4300 | REGS_NORTH_PIPE_AND_PORT)
// valid for both DVI/HDMI and DisplayPort
#define PORT_DETECTED (1 << 2)
// planes
#define INTEL_PIPE_BASE_REGISTER (0x0000 | REGS_NORTH_PLANE_CONTROL)
#define INTEL_PIPE_ENABLED (1UL << 31)
@@ -38,6 +38,7 @@ Port::Port(port_index index, const char* baseName)
:
fPortIndex(index),
fPortName(NULL),
fPipeIndex(INTEL_PIPE_ANY),
fEDIDState(B_NO_INIT)
{
char portID[2];
@@ -70,6 +71,33 @@ Port::HasEDID()
}
void
Port::PipeSelect(pipe_index pipeIndex)
{
CALLED();
uint32 portRegister = _PortRegister();
if (portRegister == 0) {
ERROR("%s: Invalid PortRegister ((0x%" B_PRIx32 ") for %s\n", __func__,
portRegister, PortName());
return;
}
TRACE("%s: Assigning %s (0x%" B_PRIx32 ") to pipe %s\n", __func__,
PortName(), portRegister, (pipeIndex == INTEL_PIPE_A) ? "A" : "B");
uint32 portState = read32(portRegister);
if (pipeIndex == INTEL_PIPE_A)
write32(portRegister, portState & ~DISPLAY_MONITOR_PIPE_B);
else
write32(portRegister, portState | DISPLAY_MONITOR_PIPE_B);
fPipeIndex = pipeIndex;
read32(portRegister);
}
status_t
Port::GetEDID(edid1_info* edid, bool forceRead)
{
@@ -194,6 +222,14 @@ AnalogPort::_DDCRegister()
}
addr_t
AnalogPort::_PortRegister()
{
// always fixed
return INTEL_ANALOG_PORT;
}
status_t
AnalogPort::SetDisplayMode(display_mode* target, uint32 colorMode)
{
@@ -373,6 +409,14 @@ LVDSPort::_DDCRegister()
}
addr_t
LVDSPort::_PortRegister()
{
// always fixed
return INTEL_DIGITAL_LVDS_PORT;
}
status_t
LVDSPort::SetDisplayMode(display_mode* target, uint32 colorMode)
{
@@ -465,7 +509,7 @@ LVDSPort::SetDisplayMode(display_mode* target, uint32 colorMode)
}
uint32 lvds = read32(INTEL_DIGITAL_LVDS_PORT) | LVDS_PORT_EN
| LVDS_A0A2_CLKA_POWER_UP | LVDS_PIPEB_SELECT;
| LVDS_A0A2_CLKA_POWER_UP;
lvds |= LVDS_18BIT_DITHER;
// TODO: do not do this if the connected panel is 24-bit
@@ -662,6 +706,13 @@ DigitalPort::_DDCRegister()
}
addr_t
DigitalPort::_PortRegister()
{
return 0;
}
// #pragma mark - HDMI
@@ -678,7 +729,7 @@ HDMIPort::IsConnected()
if (!gInfo->shared_info->device_type.SupportsHDMI())
return false;
uint32 portRegister = _PortRegister();
addr_t portRegister = _PortRegister();
TRACE("%s - %d: PortRegister: %" B_PRIx32 "\n", PortName(), PortIndex(),
portRegister);
@@ -688,14 +739,14 @@ HDMIPort::IsConnected()
if (!gInfo->shared_info->device_type.HasPlatformControlHub()
&& PortIndex() == INTEL_PORT_C) {
// there's no detection bit on this port
} else if ((read32(portRegister) & PORT_DETECTED) == 0)
} else if ((read32(portRegister) & DISPLAY_MONITOR_PORT_DETECTED) == 0)
return false;
return HasEDID();
}
uint32
addr_t
HDMIPort::_PortRegister()
{
// on PCH there's an additional port sandwiched in
@@ -736,18 +787,18 @@ DisplayPort::DisplayPort(port_index index, const char* baseName)
bool
DisplayPort::IsConnected()
{
uint32 portRegister = _PortRegister();
addr_t portRegister = _PortRegister();
if (portRegister == 0)
return false;
if ((read32(portRegister) & PORT_DETECTED) == 0)
if ((read32(portRegister) & DISPLAY_MONITOR_PORT_DETECTED) == 0)
return false;
return HasEDID();
}
uint32
addr_t
DisplayPort::_PortRegister()
{
switch (PortIndex()) {
+21 -2
View File
@@ -39,6 +39,14 @@ enum port_index {
};
// TODO: This likely should go in some pipe header
enum pipe_index {
INTEL_PIPE_ANY,
INTEL_PIPE_A,
INTEL_PIPE_B
};
class Port {
public:
Port(port_index index,
@@ -52,8 +60,13 @@ virtual uint32 Type() const = 0;
port_index PortIndex() const
{ return fPortIndex; }
pipe_index PipeIndex() const
{ return fPipeIndex; }
virtual bool IsConnected() = 0;
void PipeSelect(pipe_index pipeIndex);
bool HasEDID();
virtual status_t GetEDID(edid1_info* edid,
bool forceRead = false);
@@ -75,10 +88,13 @@ static status_t _SetI2CSignals(void* cookie, int clock,
private:
virtual addr_t _DDCRegister() = 0;
virtual addr_t _PortRegister() = 0;
port_index fPortIndex;
char* fPortName;
pipe_index fPipeIndex;
status_t fEDIDState;
edid1_info fEDIDInfo;
};
@@ -98,6 +114,7 @@ virtual status_t SetDisplayMode(display_mode* mode,
protected:
virtual addr_t _DDCRegister();
virtual addr_t _PortRegister();
};
@@ -115,6 +132,7 @@ virtual status_t SetDisplayMode(display_mode* mode,
protected:
virtual addr_t _DDCRegister();
virtual addr_t _PortRegister();
};
@@ -132,6 +150,7 @@ virtual bool IsConnected();
protected:
virtual addr_t _DDCRegister();
virtual addr_t _PortRegister();
};
@@ -145,7 +164,7 @@ virtual uint32 Type() const
virtual bool IsConnected();
protected:
uint32 _PortRegister();
virtual addr_t _PortRegister();
};
@@ -160,7 +179,7 @@ virtual uint32 Type() const
virtual bool IsConnected();
protected:
uint32 _PortRegister();
virtual uint32 _PortRegister();
};
@@ -189,16 +189,16 @@ dump_ports()
return;
}
TRACE("%s: Connected ports: (port_count: %d)\n", __func__,
TRACE("%s: Connected ports: (port_count: %" B_PRIu32 ")\n", __func__,
gInfo->port_count);
for (uint32 i = 0; i < gInfo->port_count; i++) {
Port* port = gInfo->ports[i];
if (!port) {
TRACE("port %d: INVALID ALLOC!\n", i);
TRACE("port %" B_PRIu32 ":: INVALID ALLOC!\n", i);
continue;
}
TRACE("port %d: %s %s\n", i, port->PortName(),
TRACE("port %" B_PRIu32 ": %s %s\n", i, port->PortName(),
port->IsConnected() ? "connected" : "disconnected");
}
}
@@ -615,6 +615,9 @@ if (first) {
if (!gInfo->ports[i]->IsConnected())
continue;
// XXX: For now we force everything on PIPE A
gInfo->ports[i]->PipeSelect(INTEL_PIPE_A);
status_t status = gInfo->ports[i]->SetDisplayMode(&target, colorMode);
if (status != B_OK)
ERROR("%s: Unable to set display mode!\n", __func__);