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_PIPEA_SNB (1 << 7)
#define PCH_INTERRUPT_VBLANK_PIPEB_SNB (1 << 15) #define PCH_INTERRUPT_VBLANK_PIPEB_SNB (1 << 15)
// display ports // graphics port control
#define DISPLAY_MONITOR_PORT_ENABLED (1UL << 31) #define DISPLAY_MONITOR_PORT_ENABLED (1UL << 31)
#define DISPLAY_MONITOR_PIPE_B (1UL << 30) #define DISPLAY_MONITOR_PIPE_B (1UL << 30)
#define DISPLAY_MONITOR_VGA_POLARITY (1UL << 15) #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_POLARITY_MASK (3UL << 3)
#define DISPLAY_MONITOR_POSITIVE_HSYNC (1UL << 3) #define DISPLAY_MONITOR_POSITIVE_HSYNC (1UL << 3)
#define DISPLAY_MONITOR_POSITIVE_VSYNC (2UL << 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_SLOW 14 // PLL Divisors
#define LVDS_POST2_RATE_FAST 7 #define LVDS_POST2_RATE_FAST 7
#define LVDS_CLKB_POWER_MASK (3 << 4) #define LVDS_CLKB_POWER_MASK (3 << 4)
#define LVDS_CLKB_POWER_UP (3 << 4) #define LVDS_CLKB_POWER_UP (3 << 4)
#define LVDS_PORT_EN (1 << 31) #define LVDS_PORT_EN (1 << 31)
#define LVDS_A0A2_CLKA_POWER_UP (3 << 8) #define LVDS_A0A2_CLKA_POWER_UP (3 << 8)
#define LVDS_PIPEB_SELECT (1 << 30)
#define LVDS_B0B3PAIRS_POWER_UP (3 << 2) #define LVDS_B0B3PAIRS_POWER_UP (3 << 2)
#define LVDS_PLL_MODE_LVDS (2 << 26) #define LVDS_PLL_MODE_LVDS (2 << 26)
#define LVDS_18BIT_DITHER (1 << 25) #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_C (0x4200 | REGS_NORTH_PIPE_AND_PORT)
#define INTEL_DISPLAY_PORT_D (0x4300 | 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 // planes
#define INTEL_PIPE_BASE_REGISTER (0x0000 | REGS_NORTH_PLANE_CONTROL) #define INTEL_PIPE_BASE_REGISTER (0x0000 | REGS_NORTH_PLANE_CONTROL)
#define INTEL_PIPE_ENABLED (1UL << 31) #define INTEL_PIPE_ENABLED (1UL << 31)
@@ -38,6 +38,7 @@ Port::Port(port_index index, const char* baseName)
: :
fPortIndex(index), fPortIndex(index),
fPortName(NULL), fPortName(NULL),
fPipeIndex(INTEL_PIPE_ANY),
fEDIDState(B_NO_INIT) fEDIDState(B_NO_INIT)
{ {
char portID[2]; 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 status_t
Port::GetEDID(edid1_info* edid, bool forceRead) 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 status_t
AnalogPort::SetDisplayMode(display_mode* target, uint32 colorMode) 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 status_t
LVDSPort::SetDisplayMode(display_mode* target, uint32 colorMode) 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 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; lvds |= LVDS_18BIT_DITHER;
// TODO: do not do this if the connected panel is 24-bit // 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 // #pragma mark - HDMI
@@ -678,7 +729,7 @@ HDMIPort::IsConnected()
if (!gInfo->shared_info->device_type.SupportsHDMI()) if (!gInfo->shared_info->device_type.SupportsHDMI())
return false; return false;
uint32 portRegister = _PortRegister(); addr_t portRegister = _PortRegister();
TRACE("%s - %d: PortRegister: %" B_PRIx32 "\n", PortName(), PortIndex(), TRACE("%s - %d: PortRegister: %" B_PRIx32 "\n", PortName(), PortIndex(),
portRegister); portRegister);
@@ -688,14 +739,14 @@ HDMIPort::IsConnected()
if (!gInfo->shared_info->device_type.HasPlatformControlHub() if (!gInfo->shared_info->device_type.HasPlatformControlHub()
&& PortIndex() == INTEL_PORT_C) { && PortIndex() == INTEL_PORT_C) {
// there's no detection bit on this port // 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 false;
return HasEDID(); return HasEDID();
} }
uint32 addr_t
HDMIPort::_PortRegister() HDMIPort::_PortRegister()
{ {
// on PCH there's an additional port sandwiched in // on PCH there's an additional port sandwiched in
@@ -736,18 +787,18 @@ DisplayPort::DisplayPort(port_index index, const char* baseName)
bool bool
DisplayPort::IsConnected() DisplayPort::IsConnected()
{ {
uint32 portRegister = _PortRegister(); addr_t portRegister = _PortRegister();
if (portRegister == 0) if (portRegister == 0)
return false; return false;
if ((read32(portRegister) & PORT_DETECTED) == 0) if ((read32(portRegister) & DISPLAY_MONITOR_PORT_DETECTED) == 0)
return false; return false;
return HasEDID(); return HasEDID();
} }
uint32 addr_t
DisplayPort::_PortRegister() DisplayPort::_PortRegister()
{ {
switch (PortIndex()) { 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 { class Port {
public: public:
Port(port_index index, Port(port_index index,
@@ -52,8 +60,13 @@ virtual uint32 Type() const = 0;
port_index PortIndex() const port_index PortIndex() const
{ return fPortIndex; } { return fPortIndex; }
pipe_index PipeIndex() const
{ return fPipeIndex; }
virtual bool IsConnected() = 0; virtual bool IsConnected() = 0;
void PipeSelect(pipe_index pipeIndex);
bool HasEDID(); bool HasEDID();
virtual status_t GetEDID(edid1_info* edid, virtual status_t GetEDID(edid1_info* edid,
bool forceRead = false); bool forceRead = false);
@@ -75,10 +88,13 @@ static status_t _SetI2CSignals(void* cookie, int clock,
private: private:
virtual addr_t _DDCRegister() = 0; virtual addr_t _DDCRegister() = 0;
virtual addr_t _PortRegister() = 0;
port_index fPortIndex; port_index fPortIndex;
char* fPortName; char* fPortName;
pipe_index fPipeIndex;
status_t fEDIDState; status_t fEDIDState;
edid1_info fEDIDInfo; edid1_info fEDIDInfo;
}; };
@@ -98,6 +114,7 @@ virtual status_t SetDisplayMode(display_mode* mode,
protected: protected:
virtual addr_t _DDCRegister(); virtual addr_t _DDCRegister();
virtual addr_t _PortRegister();
}; };
@@ -115,6 +132,7 @@ virtual status_t SetDisplayMode(display_mode* mode,
protected: protected:
virtual addr_t _DDCRegister(); virtual addr_t _DDCRegister();
virtual addr_t _PortRegister();
}; };
@@ -132,6 +150,7 @@ virtual bool IsConnected();
protected: protected:
virtual addr_t _DDCRegister(); virtual addr_t _DDCRegister();
virtual addr_t _PortRegister();
}; };
@@ -145,7 +164,7 @@ virtual uint32 Type() const
virtual bool IsConnected(); virtual bool IsConnected();
protected: protected:
uint32 _PortRegister(); virtual addr_t _PortRegister();
}; };
@@ -160,7 +179,7 @@ virtual uint32 Type() const
virtual bool IsConnected(); virtual bool IsConnected();
protected: protected:
uint32 _PortRegister(); virtual uint32 _PortRegister();
}; };
@@ -189,16 +189,16 @@ dump_ports()
return; return;
} }
TRACE("%s: Connected ports: (port_count: %d)\n", __func__, TRACE("%s: Connected ports: (port_count: %" B_PRIu32 ")\n", __func__,
gInfo->port_count); gInfo->port_count);
for (uint32 i = 0; i < gInfo->port_count; i++) { for (uint32 i = 0; i < gInfo->port_count; i++) {
Port* port = gInfo->ports[i]; Port* port = gInfo->ports[i];
if (!port) { if (!port) {
TRACE("port %d: INVALID ALLOC!\n", i); TRACE("port %" B_PRIu32 ":: INVALID ALLOC!\n", i);
continue; continue;
} }
TRACE("port %d: %s %s\n", i, port->PortName(), TRACE("port %" B_PRIu32 ": %s %s\n", i, port->PortName(),
port->IsConnected() ? "connected" : "disconnected"); port->IsConnected() ? "connected" : "disconnected");
} }
} }
@@ -615,6 +615,9 @@ if (first) {
if (!gInfo->ports[i]->IsConnected()) if (!gInfo->ports[i]->IsConnected())
continue; 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); status_t status = gInfo->ports[i]->SetDisplayMode(&target, colorMode);
if (status != B_OK) if (status != B_OK)
ERROR("%s: Unable to set display mode!\n", __func__); ERROR("%s: Unable to set display mode!\n", __func__);