intel_extreme: Add initial work for DDI ports
This commit is contained in:
parent
3d1bd895ad
commit
ca95e9dad9
@ -162,6 +162,12 @@ struct DeviceType {
|
|||||||
return InFamily(INTEL_FAMILY_SER5);
|
return InFamily(INTEL_FAMILY_SER5);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool HasDDI() const
|
||||||
|
{
|
||||||
|
// Intel Digital Display Interface
|
||||||
|
return InGroup(INTEL_GROUP_HAS) || (Generation() >= 8);
|
||||||
|
}
|
||||||
|
|
||||||
int Generation() const
|
int Generation() const
|
||||||
{
|
{
|
||||||
if (InFamily(INTEL_FAMILY_7xx))
|
if (InFamily(INTEL_FAMILY_7xx))
|
||||||
@ -542,6 +548,18 @@ struct intel_free_graphics_memory {
|
|||||||
#define GEN4_HDMI_PORT_C (0x1160 | REGS_SOUTH_TRANSCODER_PORT)
|
#define GEN4_HDMI_PORT_C (0x1160 | REGS_SOUTH_TRANSCODER_PORT)
|
||||||
#define CHV_HDMI_PORT_D (0x116C | REGS_SOUTH_TRANSCODER_PORT)
|
#define CHV_HDMI_PORT_D (0x116C | REGS_SOUTH_TRANSCODER_PORT)
|
||||||
|
|
||||||
|
// DDI Buffer Control (This replaces DP on Haswell+)
|
||||||
|
#define DDI_BUF_CTL_A (0x4000 | REGS_NORTH_PIPE_AND_PORT)
|
||||||
|
#define DDI_BUF_CTL_B (0x4100 | REGS_NORTH_PIPE_AND_PORT)
|
||||||
|
#define DDI_BUF_CTL_ENABLE (1 << 31)
|
||||||
|
#define DDI_BUF_TRANS_SELECT(n) ((n) << 24)
|
||||||
|
#define DDI_BUF_EMP_MASK (0xf << 24)
|
||||||
|
#define DDI_BUF_PORT_REVERSAL (1 << 16)
|
||||||
|
#define DDI_BUF_IS_IDLE (1 << 7)
|
||||||
|
#define DDI_A_4_LANES (1 << 4)
|
||||||
|
#define DDI_PORT_WIDTH(width) (((width) - 1) << 1)
|
||||||
|
#define DDI_INIT_DISPLAY_DETECTED (1 << 0)
|
||||||
|
|
||||||
// DP_A always @ 6xxxx, DP_B-DP_D move with PCH
|
// DP_A always @ 6xxxx, DP_B-DP_D move with PCH
|
||||||
#define INTEL_DISPLAY_PORT_A (0x4000 | REGS_NORTH_PIPE_AND_PORT)
|
#define INTEL_DISPLAY_PORT_A (0x4000 | REGS_NORTH_PIPE_AND_PORT)
|
||||||
#define INTEL_DISPLAY_PORT_B (0x4100 | REGS_SOUTH_TRANSCODER_PORT)
|
#define INTEL_DISPLAY_PORT_B (0x4100 | REGS_SOUTH_TRANSCODER_PORT)
|
||||||
|
@ -984,3 +984,100 @@ EmbeddedDisplayPort::IsConnected()
|
|||||||
// No EDID? The modesetting code falls back to VBIOS panel_mode
|
// No EDID? The modesetting code falls back to VBIOS panel_mode
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// #pragma mark - Digital Display Port
|
||||||
|
|
||||||
|
|
||||||
|
DigitalDisplayInterface::DigitalDisplayInterface(port_index index,
|
||||||
|
const char* baseName)
|
||||||
|
:
|
||||||
|
Port(index, baseName)
|
||||||
|
{
|
||||||
|
// As of Haswell, Intel decided to change eDP ports to a "DDI" bus...
|
||||||
|
// on a dare because the hardware engineers were drunk one night.
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
addr_t
|
||||||
|
DigitalDisplayInterface::_PortRegister()
|
||||||
|
{
|
||||||
|
switch (PortIndex()) {
|
||||||
|
case INTEL_PORT_A:
|
||||||
|
return DDI_BUF_CTL_A;
|
||||||
|
case INTEL_PORT_B:
|
||||||
|
return DDI_BUF_CTL_B;
|
||||||
|
default:
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
addr_t
|
||||||
|
DigitalDisplayInterface::_DDCRegister()
|
||||||
|
{
|
||||||
|
// TODO: No idea, does DDI have DDC?
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool
|
||||||
|
DigitalDisplayInterface::IsConnected()
|
||||||
|
{
|
||||||
|
addr_t portRegister = _PortRegister();
|
||||||
|
|
||||||
|
TRACE("%s: %s PortRegister: 0x%" B_PRIxADDR "\n", __func__, PortName(),
|
||||||
|
portRegister);
|
||||||
|
|
||||||
|
if (portRegister == 0)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if ((read32(portRegister) & DDI_INIT_DISPLAY_DETECTED) == 0) {
|
||||||
|
TRACE("%s: %s link not detected\n", __func__, PortName());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
HasEDID();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
DigitalDisplayInterface::SetDisplayMode(display_mode* target, uint32 colorMode)
|
||||||
|
{
|
||||||
|
TRACE("%s: %s %dx%d\n", __func__, PortName(), target->virtual_width,
|
||||||
|
target->virtual_height);
|
||||||
|
|
||||||
|
if (fPipe == NULL) {
|
||||||
|
ERROR("%s: Setting display mode without assigned pipe!\n", __func__);
|
||||||
|
return B_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Train FDI if it exists
|
||||||
|
FDILink* link = fPipe->FDI();
|
||||||
|
if (link != NULL)
|
||||||
|
link->Train(target);
|
||||||
|
|
||||||
|
pll_divisors divisors;
|
||||||
|
compute_pll_divisors(target, &divisors, false);
|
||||||
|
|
||||||
|
uint32 extraPLLFlags = 0;
|
||||||
|
if (gInfo->shared_info->device_type.Generation() >= 3)
|
||||||
|
extraPLLFlags |= DISPLAY_PLL_MODE_NORMAL;
|
||||||
|
|
||||||
|
// Program general pipe config
|
||||||
|
fPipe->Configure(target);
|
||||||
|
|
||||||
|
// Program pipe PLL's
|
||||||
|
fPipe->ConfigureClocks(divisors, target->timing.pixel_clock, extraPLLFlags);
|
||||||
|
|
||||||
|
// Program target display mode
|
||||||
|
fPipe->ConfigureTimings(target);
|
||||||
|
|
||||||
|
// Set fCurrentMode to our set display mode
|
||||||
|
memcpy(&fCurrentMode, target, sizeof(display_mode));
|
||||||
|
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
@ -199,4 +199,25 @@ virtual uint32 Type() const
|
|||||||
virtual bool IsConnected();
|
virtual bool IsConnected();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class DigitalDisplayInterface : public Port {
|
||||||
|
public:
|
||||||
|
DigitalDisplayInterface(
|
||||||
|
port_index index = INTEL_PORT_A,
|
||||||
|
const char* baseName = "Digital Display Interface");
|
||||||
|
|
||||||
|
virtual uint32 Type() const
|
||||||
|
{ return INTEL_PORT_TYPE_DVI; }
|
||||||
|
|
||||||
|
virtual bool IsConnected();
|
||||||
|
|
||||||
|
virtual status_t SetDisplayMode(display_mode* mode,
|
||||||
|
uint32 colorMode);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
virtual addr_t _DDCRegister();
|
||||||
|
virtual addr_t _PortRegister();
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
#endif // INTEL_PORTS_H
|
#endif // INTEL_PORTS_H
|
||||||
|
@ -306,9 +306,37 @@ probe_ports()
|
|||||||
delete displayPort;
|
delete displayPort;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Digital Display Interface
|
||||||
|
if (gInfo->shared_info->device_type.HasDDI()) {
|
||||||
|
for (int i = INTEL_PORT_A; i <= INTEL_PORT_B; i++) {
|
||||||
|
Port* ddiPort
|
||||||
|
= new(std::nothrow) DigitalDisplayInterface((port_index)i);
|
||||||
|
|
||||||
|
if (ddiPort == NULL)
|
||||||
|
return B_NO_MEMORY;
|
||||||
|
|
||||||
|
if (ddiPort->IsConnected())
|
||||||
|
gInfo->ports[gInfo->port_count++] = ddiPort;
|
||||||
|
else
|
||||||
|
delete ddiPort;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ensure DP_A isn't already taken (or DDI)
|
||||||
|
if (!has_connected_port((port_index)INTEL_PORT_A, INTEL_PORT_TYPE_ANY)) {
|
||||||
|
// also always try eDP, it'll also just fail if not applicable
|
||||||
|
Port* eDPPort = new(std::nothrow) EmbeddedDisplayPort();
|
||||||
|
if (eDPPort == NULL)
|
||||||
|
return B_NO_MEMORY;
|
||||||
|
if (eDPPort->IsConnected())
|
||||||
|
gInfo->ports[gInfo->port_count++] = eDPPort;
|
||||||
|
else
|
||||||
|
delete eDPPort;
|
||||||
|
}
|
||||||
|
|
||||||
for (int i = INTEL_PORT_B; i <= INTEL_PORT_D; i++) {
|
for (int i = INTEL_PORT_B; i <= INTEL_PORT_D; i++) {
|
||||||
if (has_connected_port((port_index)i, INTEL_PORT_TYPE_ANY)) {
|
if (has_connected_port((port_index)i, INTEL_PORT_TYPE_ANY)) {
|
||||||
// we overlap with a DisplayPort, this is not HDMI
|
// Ensure port not already claimed by something like DDI
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -346,15 +374,6 @@ probe_ports()
|
|||||||
} else
|
} else
|
||||||
delete lvdsPort;
|
delete lvdsPort;
|
||||||
|
|
||||||
// also always try eDP, it'll also just fail if not applicable
|
|
||||||
Port* eDPPort = new(std::nothrow) EmbeddedDisplayPort();
|
|
||||||
if (eDPPort == NULL)
|
|
||||||
return B_NO_MEMORY;
|
|
||||||
if (eDPPort->IsConnected())
|
|
||||||
gInfo->ports[gInfo->port_count++] = eDPPort;
|
|
||||||
else
|
|
||||||
delete eDPPort;
|
|
||||||
|
|
||||||
// then finally always try the analog port
|
// then finally always try the analog port
|
||||||
Port* analogPort = new(std::nothrow) AnalogPort();
|
Port* analogPort = new(std::nothrow) AnalogPort();
|
||||||
if (analogPort == NULL)
|
if (analogPort == NULL)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user