intel_extreme: Rebase and refactor mmlr's work from 2013
* New port storage classes and cleaner logic
This commit is contained in:
parent
c06aefa0ee
commit
50f0b3fe76
|
@ -134,6 +134,24 @@ struct DeviceType {
|
|||
return (type & INTEL_TYPE_MODEL_MASK) == model;
|
||||
}
|
||||
|
||||
bool IsMobile() const
|
||||
{
|
||||
return (type & INTEL_TYPE_MODEL_MASK) == INTEL_TYPE_MOBILE;
|
||||
}
|
||||
|
||||
bool SupportsHDMI() const
|
||||
{
|
||||
switch (type & INTEL_TYPE_GROUP_MASK) {
|
||||
case INTEL_TYPE_G4x:
|
||||
case INTEL_TYPE_ILK:
|
||||
case INTEL_TYPE_SNB:
|
||||
case INTEL_TYPE_IVBG:
|
||||
case INTEL_TYPE_VLV:
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool HasPlatformControlHub() const
|
||||
{
|
||||
return InGroup(INTEL_TYPE_ILK) || InGroup(INTEL_TYPE_SNB)
|
||||
|
@ -439,19 +457,37 @@ struct intel_free_graphics_memory {
|
|||
#define INTEL_DISPLAY_A_IMAGE_SIZE (0x001c | REGS_NORTH_PIPE_AND_PORT)
|
||||
#define INTEL_DISPLAY_B_IMAGE_SIZE (0x101c | REGS_NORTH_PIPE_AND_PORT)
|
||||
|
||||
#define INTEL_DISPLAY_A_ANALOG_PORT (0x1100 | REGS_SOUTH_TRANSCODER_PORT)
|
||||
#define INTEL_DISPLAY_A_DIGITAL_PORT (0x1120 | REGS_SOUTH_TRANSCODER_PORT)
|
||||
#define INTEL_DISPLAY_B_DIGITAL_PORT (0x1140 | REGS_SOUTH_TRANSCODER_PORT)
|
||||
#define INTEL_DISPLAY_C_DIGITAL (0x1160 | REGS_SOUTH_TRANSCODER_PORT)
|
||||
#define INTEL_DISPLAY_LVDS_PORT (0x1180 | REGS_SOUTH_TRANSCODER_PORT)
|
||||
#define INTEL_ANALOG_PORT (0x1100 | REGS_SOUTH_TRANSCODER_PORT)
|
||||
#define INTEL_DIGITAL_PORT_A (0x1120 | REGS_SOUTH_TRANSCODER_PORT)
|
||||
#define INTEL_DIGITAL_PORT_B (0x1140 | REGS_SOUTH_TRANSCODER_PORT)
|
||||
#define INTEL_DIGITAL_PORT_C (0x1160 | REGS_SOUTH_TRANSCODER_PORT)
|
||||
#define INTEL_DIGITAL_LVDS_PORT (0x1180 | REGS_SOUTH_TRANSCODER_PORT)
|
||||
|
||||
#define INTEL_HDMI_PORT_B (0x1140 | REGS_NORTH_PIPE_AND_PORT)
|
||||
#define INTEL_HDMI_PORT_C (0x1160 | REGS_NORTH_PIPE_AND_PORT)
|
||||
|
||||
#define PCH_HDMI_PORT_B (0x1140 | REGS_SOUTH_TRANSCODER_PORT)
|
||||
#define PCH_HDMI_PORT_C (0x1150 | REGS_SOUTH_TRANSCODER_PORT)
|
||||
#define PCH_HDMI_PORT_D (0x1160 | REGS_SOUTH_TRANSCODER_PORT)
|
||||
|
||||
#define INTEL_DISPLAY_PORT_A (0x4000 | REGS_NORTH_PIPE_AND_PORT)
|
||||
#define INTEL_DISPLAY_PORT_B (0x4100 | 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)
|
||||
|
||||
// valid for both DVI/HDMI and DisplayPort
|
||||
#define PORT_DETECTED (1 << 2)
|
||||
|
||||
// planes
|
||||
#define INTEL_DISPLAY_A_PIPE_CONTROL (0x0008 | REGS_NORTH_PLANE_CONTROL)
|
||||
#define INTEL_PIPE_ENABLED (1UL << 31)
|
||||
#define INTEL_PIPE_CONTROL 0x08
|
||||
#define INTEL_PIPE_STATUS 0x24
|
||||
#define INTEL_PIPE_OFFSET 0x1000
|
||||
#define INTEL_DISPLAY_A_PIPE_CONTROL (0x0008 | REGS_NORTH_PLANE_CONTROL)
|
||||
#define INTEL_DISPLAY_B_PIPE_CONTROL (0x1008 | REGS_NORTH_PLANE_CONTROL)
|
||||
#define DISPLAY_PIPE_ENABLED (1UL << 31)
|
||||
|
||||
#define INTEL_DISPLAY_A_PIPE_STATUS (0x0024 | REGS_NORTH_PLANE_CONTROL)
|
||||
#define INTEL_DISPLAY_B_PIPE_STATUS (0x1024 | REGS_NORTH_PLANE_CONTROL)
|
||||
|
||||
#define DISPLAY_PIPE_VBLANK_ENABLED (1UL << 17)
|
||||
#define DISPLAY_PIPE_VBLANK_STATUS (1UL << 1)
|
||||
|
||||
|
@ -594,6 +630,43 @@ struct intel_free_graphics_memory {
|
|||
#define INTEL_OVERLAY_GAMMA_1 0x30020
|
||||
#define INTEL_OVERLAY_GAMMA_0 0x30024
|
||||
|
||||
// FDI - Flexible Display Interface, the interface between the (CPU-internal)
|
||||
// GPU and the PCH display outputs. Proprietary interface, based on DisplayPort
|
||||
// though, so similar link training and all...
|
||||
// There's an FDI transmitter (TX) on the CPU and an FDI receiver (RX) on the
|
||||
// PCH for each display pipe.
|
||||
// FDI receiver A is hooked up to transcoder A, FDI receiver B is hooked up to
|
||||
// transcoder B, so we have the same mapping as with the display pipes.
|
||||
#define PCH_FDI_RX_BASE_REGISTER 0xf0000
|
||||
#define PCH_FDI_RX_PIPE_OFFSET 0x01000
|
||||
|
||||
#define PCH_FDI_RX_CONTROL 0x0c
|
||||
#define FDI_RX_CLOCK_MASK (1 << 4)
|
||||
#define FDI_RX_CLOCK_RAW (0 << 4)
|
||||
#define FDI_RX_CLOCK_PCD (1 << 4)
|
||||
|
||||
#define PCH_FDI_RX_TRANS_UNIT_SIZE_1 0x30
|
||||
#define PCH_FDI_RX_TRANS_UNIT_SIZE_2 0x38
|
||||
#define FDI_RX_TRANS_UNIT_SIZE(x) ((x - 1) << 25)
|
||||
#define FDI_RX_TRANS_UNIT_MASK 0x7e000000
|
||||
// Transfer unit size 1 is the primary and fixed transfer unit size,
|
||||
// TU size 2 is the lower power state transfer unit size when using dynamic
|
||||
// refresh rates (we don't do that though).
|
||||
|
||||
// CPU Panel Fitters - These are for IronLake and up and are the CPU internal
|
||||
// panel fitters.
|
||||
#define PCH_PANEL_FITTER_BASE_REGISTER 0x68000
|
||||
#define PCH_PANEL_FITTER_PIPE_OFFSET 0x00800
|
||||
|
||||
#define PCH_PANEL_FITTER_WINDOW_POS 0x70
|
||||
#define PCH_PANEL_FITTER_WINDOW_SIZE 0x74
|
||||
#define PCH_PANEL_FITTER_CONTROL 0x80
|
||||
#define PCH_PANEL_FITTER_V_SCALE 0x84
|
||||
#define PCH_PANEL_FITTER_H_SCALE 0x90
|
||||
|
||||
#define PANEL_FITTER_ENABLED (1 << 31)
|
||||
#define PANEL_FITTER_FILTER_MASK (3 << 23)
|
||||
|
||||
struct overlay_scale {
|
||||
uint32 _reserved0 : 3;
|
||||
uint32 horizontal_scale_fraction : 12;
|
||||
|
|
|
@ -0,0 +1,183 @@
|
|||
/*
|
||||
* Copyright 2011, Haiku, Inc. All Rights Reserved.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*
|
||||
* Authors:
|
||||
* Michael Lotz, mmlr@mlotz.ch
|
||||
*/
|
||||
|
||||
|
||||
#include "DisplayPipe.h"
|
||||
|
||||
#include "accelerant.h"
|
||||
#include "intel_extreme.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
|
||||
#define TRACE_PIPE
|
||||
#ifdef TRACE_PIPE
|
||||
extern "C" void _sPrintf(const char* format, ...);
|
||||
# define TRACE(x) _sPrintf x
|
||||
#else
|
||||
# define TRACE(x) ;
|
||||
#endif
|
||||
|
||||
|
||||
// #pragma mark - DisplayPipe
|
||||
|
||||
|
||||
DisplayPipe::DisplayPipe(int32 pipeIndex)
|
||||
:
|
||||
fFDILink(NULL),
|
||||
fPanelFitter(NULL),
|
||||
fBaseRegister(INTEL_PIPE_BASE_REGISTER + pipeIndex * INTEL_PIPE_PIPE_OFFSET)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
DisplayPipe::IsEnabled()
|
||||
{
|
||||
return (read32(fBaseRegister + INTEL_PIPE_CONTROL) & PIPE_ENABLED) != 0;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
DisplayPipe::Enable(const display_mode& mode)
|
||||
{
|
||||
_Enable(true);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
DisplayPipe::Disable()
|
||||
{
|
||||
_Enable(false);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
DisplayPipe::ConfigureTimings(const pll_divisors& divisors)
|
||||
{
|
||||
if (gInfo->shared_info->device_type.InGroup(INTEL_TYPE_IGD)) {
|
||||
write32(INTEL_DISPLAY_A_PLL_DIVISOR_0,
|
||||
(((1 << divisors.n) << DISPLAY_PLL_N_DIVISOR_SHIFT)
|
||||
& DISPLAY_PLL_IGD_N_DIVISOR_MASK)
|
||||
| (((divisors.m2 - 2) << DISPLAY_PLL_M2_DIVISOR_SHIFT)
|
||||
& DISPLAY_PLL_IGD_M2_DIVISOR_MASK));
|
||||
} else {
|
||||
write32(INTEL_DISPLAY_A_PLL_DIVISOR_0,
|
||||
(((divisors.n - 2) << DISPLAY_PLL_N_DIVISOR_SHIFT)
|
||||
& DISPLAY_PLL_N_DIVISOR_MASK)
|
||||
| (((divisors.m1 - 2) << DISPLAY_PLL_M1_DIVISOR_SHIFT)
|
||||
& DISPLAY_PLL_M1_DIVISOR_MASK)
|
||||
| (((divisors.m2 - 2) << DISPLAY_PLL_M2_DIVISOR_SHIFT)
|
||||
& DISPLAY_PLL_M2_DIVISOR_MASK));
|
||||
}
|
||||
|
||||
uint32 pll = DISPLAY_PLL_ENABLED | DISPLAY_PLL_NO_VGA_CONTROL;
|
||||
if (gInfo->shared_info->device_type.InFamily(INTEL_TYPE_9xx)) {
|
||||
if (gInfo->shared_info->device_type.InGroup(INTEL_TYPE_IGD)) {
|
||||
pll |= ((1 << (divisors.post1 - 1))
|
||||
<< DISPLAY_PLL_IGD_POST1_DIVISOR_SHIFT)
|
||||
& DISPLAY_PLL_IGD_POST1_DIVISOR_MASK;
|
||||
} else {
|
||||
pll |= ((1 << (divisors.post1 - 1))
|
||||
<< DISPLAY_PLL_POST1_DIVISOR_SHIFT)
|
||||
& DISPLAY_PLL_9xx_POST1_DIVISOR_MASK;
|
||||
// pll |= ((divisors.post1 - 1) << DISPLAY_PLL_POST1_DIVISOR_SHIFT)
|
||||
// & DISPLAY_PLL_9xx_POST1_DIVISOR_MASK;
|
||||
}
|
||||
if (divisors.post2_high)
|
||||
pll |= DISPLAY_PLL_DIVIDE_HIGH;
|
||||
|
||||
pll |= DISPLAY_PLL_MODE_ANALOG;
|
||||
|
||||
if (gInfo->shared_info->device_type.InGroup(INTEL_TYPE_96x))
|
||||
pll |= 6 << DISPLAY_PLL_PULSE_PHASE_SHIFT;
|
||||
} else {
|
||||
if (!divisors.post2_high)
|
||||
pll |= DISPLAY_PLL_DIVIDE_4X;
|
||||
|
||||
pll |= DISPLAY_PLL_2X_CLOCK;
|
||||
|
||||
if (divisors.post1 > 2) {
|
||||
pll |= ((divisors.post1 - 2) << DISPLAY_PLL_POST1_DIVISOR_SHIFT)
|
||||
& DISPLAY_PLL_POST1_DIVISOR_MASK;
|
||||
} else
|
||||
pll |= DISPLAY_PLL_POST1_DIVIDE_2;
|
||||
}
|
||||
|
||||
write32(INTEL_DISPLAY_A_PLL, pll);
|
||||
read32(INTEL_DISPLAY_A_PLL);
|
||||
spin(150);
|
||||
write32(INTEL_DISPLAY_A_PLL, pll);
|
||||
read32(INTEL_DISPLAY_A_PLL);
|
||||
spin(150);
|
||||
|
||||
// update timing parameters
|
||||
write32(INTEL_DISPLAY_A_HTOTAL,
|
||||
((uint32)(target.timing.h_total - 1) << 16)
|
||||
| ((uint32)target.timing.h_display - 1));
|
||||
write32(INTEL_DISPLAY_A_HBLANK,
|
||||
((uint32)(target.timing.h_total - 1) << 16)
|
||||
| ((uint32)target.timing.h_display - 1));
|
||||
write32(INTEL_DISPLAY_A_HSYNC,
|
||||
((uint32)(target.timing.h_sync_end - 1) << 16)
|
||||
| ((uint32)target.timing.h_sync_start - 1));
|
||||
|
||||
write32(INTEL_DISPLAY_A_VTOTAL,
|
||||
((uint32)(target.timing.v_total - 1) << 16)
|
||||
| ((uint32)target.timing.v_display - 1));
|
||||
write32(INTEL_DISPLAY_A_VBLANK,
|
||||
((uint32)(target.timing.v_total - 1) << 16)
|
||||
| ((uint32)target.timing.v_display - 1));
|
||||
write32(INTEL_DISPLAY_A_VSYNC,
|
||||
((uint32)(target.timing.v_sync_end - 1) << 16)
|
||||
| ((uint32)target.timing.v_sync_start - 1));
|
||||
|
||||
write32(INTEL_DISPLAY_A_IMAGE_SIZE,
|
||||
((uint32)(target.virtual_width - 1) << 16)
|
||||
| ((uint32)target.virtual_height - 1));
|
||||
|
||||
write32(INTEL_ANALOG_PORT, (read32(INTEL_ANALOG_PORT)
|
||||
& ~(DISPLAY_MONITOR_POLARITY_MASK
|
||||
| DISPLAY_MONITOR_VGA_POLARITY))
|
||||
| ((target.timing.flags & B_POSITIVE_HSYNC) != 0
|
||||
? DISPLAY_MONITOR_POSITIVE_HSYNC : 0)
|
||||
| ((target.timing.flags & B_POSITIVE_VSYNC) != 0
|
||||
? DISPLAY_MONITOR_POSITIVE_VSYNC : 0));
|
||||
|
||||
// TODO: verify the two comments below: the X driver doesn't seem to
|
||||
// care about both of them!
|
||||
|
||||
// These two have to be set for display B, too - this obviously means
|
||||
// that the second head always must adopt the color space of the first
|
||||
// head.
|
||||
write32(INTEL_DISPLAY_A_CONTROL, (read32(INTEL_DISPLAY_A_CONTROL)
|
||||
& ~(DISPLAY_CONTROL_COLOR_MASK | DISPLAY_CONTROL_GAMMA))
|
||||
| colorMode);
|
||||
|
||||
if ((gInfo->head_mode & HEAD_MODE_B_DIGITAL) != 0) {
|
||||
write32(INTEL_DISPLAY_B_IMAGE_SIZE,
|
||||
((uint32)(target.virtual_width - 1) << 16)
|
||||
| ((uint32)target.virtual_height - 1));
|
||||
|
||||
write32(INTEL_DISPLAY_B_CONTROL, (read32(INTEL_DISPLAY_B_CONTROL)
|
||||
& ~(DISPLAY_CONTROL_COLOR_MASK | DISPLAY_CONTROL_GAMMA))
|
||||
| colorMode);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
DisplayPipe::_Enable(bool enable)
|
||||
{
|
||||
uint32 targetRegister = fBaseRegister + INTEL_PIPE_CONTROL;
|
||||
write32(targetRegister, read32(targetRegister) & ~PIPE_ENABLED
|
||||
| (enable ? PIPE_ENABLED | 0));
|
||||
read32(targetRegister);
|
||||
}
|
|
@ -0,0 +1,44 @@
|
|||
/*
|
||||
* Copyright 2011, Haiku, Inc. All Rights Reserved.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*
|
||||
* Authors:
|
||||
* Michael Lotz, mmlr@mlotz.ch
|
||||
*/
|
||||
#ifndef INTEL_PIPE_H
|
||||
#define INTEL_PIPE_H
|
||||
|
||||
|
||||
class FDILink;
|
||||
class PanelFitter;
|
||||
|
||||
struct pll_divisors;
|
||||
|
||||
class DisplayPipe {
|
||||
public:
|
||||
DisplayPipe(int32 pipeIndex);
|
||||
virtual ~DisplayPipe();
|
||||
|
||||
bool IsEnabled();
|
||||
void Enable(const display_mode& mode);
|
||||
void Disable();
|
||||
|
||||
void ConfigureTimings(
|
||||
const pll_divisors& divisors);
|
||||
|
||||
// access to the various parts of the pipe
|
||||
::FDILink* FDILink()
|
||||
{ return fFDILink; }
|
||||
::PanelFitter* PanelFitter()
|
||||
{ return fPanelFitter; }
|
||||
|
||||
private:
|
||||
void _Enable(bool enable);
|
||||
|
||||
FDILink* fFDILink;
|
||||
PanelFitter* fPanelFitter;
|
||||
|
||||
uint32 fRegisterBase;
|
||||
};
|
||||
|
||||
#endif // INTEL_PIPE_H
|
|
@ -0,0 +1,138 @@
|
|||
/*
|
||||
* Copyright 2011, Haiku, Inc. All Rights Reserved.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*
|
||||
* Authors:
|
||||
* Michael Lotz, mmlr@mlotz.ch
|
||||
*/
|
||||
|
||||
|
||||
#include "FlexibleDisplayInterface.h"
|
||||
|
||||
#include "accelerant.h"
|
||||
#include "intel_extreme.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
|
||||
#define TRACE_FDI
|
||||
#ifdef TRACE_FDI
|
||||
extern "C" void _sPrintf(const char* format, ...);
|
||||
# define TRACE(x) _sPrintf x
|
||||
#else
|
||||
# define TRACE(x) ;
|
||||
#endif
|
||||
|
||||
|
||||
// #pragma mark - FDITransmitter
|
||||
|
||||
|
||||
FDITransmitter::FDITransmitter(int32 pipeIndex)
|
||||
:
|
||||
fBaseRegister(PCH_FDI_TX_BASE_REGISTER + pipeIndex * PCH_FDI_TX_PIPE_OFFSET)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
FDITransmitter::IsPLLEnabled()
|
||||
{
|
||||
return (read32(fBaseRegister + PCH_FDI_TX_CONTROL) & PCH_FDI_TX_PLL_ENABLED)
|
||||
!= 0;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
FDITransmitter::EnablePLL()
|
||||
{
|
||||
uint32 targetRegister = fBaseRegister + PCH_FDI_TX_CONTROL;
|
||||
uint32 value = read32(targetRegister);
|
||||
if ((value & PCH_FDI_TX_PLL_ENABLED) != 0) {
|
||||
// already enabled, possibly IronLake where it always is
|
||||
return;
|
||||
}
|
||||
|
||||
write32(targetRegister, value | PCH_FDI_TX_PLL_ENABLED);
|
||||
read32(targetRegister);
|
||||
spin(100); // warmup 10us + dmi delay 20us, be generous
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
FDITransmitter::DisablePLL()
|
||||
{
|
||||
if (gInfo->shared_info->device_type.IsGroup(INTEL_TYPE_ILK)) {
|
||||
// on IronLake the FDI PLL is alaways enabled, so no point in trying...
|
||||
return;
|
||||
}
|
||||
|
||||
uint32 targetRegister = fBaseRegister + PCH_FDI_TX_CONTROL;
|
||||
write32(targetRegister, read32(targetRegister) & ~PCH_FDI_TX_PLL_ENABLED);
|
||||
read32(targetRegister);
|
||||
spin(100);
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark - FDIReceiver
|
||||
|
||||
|
||||
FDIReceiver::FDIReceiver(int32 pipeIndex)
|
||||
:
|
||||
fBaseRegister(PCH_FDI_RX_BASE_REGISTER + pipeIndex * PCH_FDI_RX_PIPE_OFFSET)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
FDIReceiver::IsPLLEnabled()
|
||||
{
|
||||
return (read32(fBaseRegister + PCH_FDI_RX_CONTROL) & PCH_FDI_RX_PLL_ENABLED)
|
||||
!= 0;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
FDIReceiver::EnablePLL()
|
||||
{
|
||||
uint32 targetRegister = fBaseRegister + PCH_FDI_RX_CONTROL;
|
||||
uint32 value = read32(targetRegister);
|
||||
if ((value & PCH_FDI_RX_PLL_ENABLED) != 0)
|
||||
return;
|
||||
|
||||
write32(targetRegister, value | PCH_FDI_RX_PLL_ENABLED);
|
||||
read32(targetRegister);
|
||||
spin(200); // warmup 10us + dmi delay 20us, be generous
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
FDIReceiver::DisablePLL()
|
||||
{
|
||||
uint32 targetRegister = fBaseRegister + PCH_FDI_RX_CONTROL;
|
||||
write32(targetRegister, read32(targetRegister) & ~PCH_FDI_RX_PLL_ENABLED);
|
||||
read32(targetRegister);
|
||||
spin(100);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
FDIReceiver::SwtichClock(bool toPCDClock)
|
||||
{
|
||||
uint32 targetRegister = fBaseRegister + PCH_FDI_RX_CONTROL;
|
||||
write32(targetRegister, (read32(targetRegister) & ~PCH_FDI_RX_CLOCK_MASK)
|
||||
| (toPCDClock ? PCH_FDI_RX_CLOCK_PCD : PCH_FDI_RX_CLOCK_RAW));
|
||||
read32(targetRegister);
|
||||
spin(200);
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark - FDILink
|
||||
|
||||
|
||||
FDILink::FDILink(int32 pipeIndex)
|
||||
:
|
||||
fTransmitter(pipeIndex),
|
||||
fReceiver(pipeIndex)
|
||||
{
|
||||
}
|
|
@ -0,0 +1,53 @@
|
|||
/*
|
||||
* Copyright 2011, Haiku, Inc. All Rights Reserved.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*
|
||||
* Authors:
|
||||
* Michael Lotz, mmlr@mlotz.ch
|
||||
*/
|
||||
#ifndef INTEL_FDI_H
|
||||
#define INTEL_FDI_H
|
||||
|
||||
|
||||
class FDITransmitter {
|
||||
public:
|
||||
FDITransmitter(int32 pipeIndex);
|
||||
virtual ~FDITransmitter();
|
||||
|
||||
bool IsPLLEnabled();
|
||||
void EnablePLL();
|
||||
void DisablePLL();
|
||||
|
||||
private:
|
||||
uint32 fRegisterBase;
|
||||
};
|
||||
|
||||
|
||||
class FDIReceiver {
|
||||
public:
|
||||
FDIReceiver(int32 pipeIndex);
|
||||
|
||||
bool IsPLLEnabled();
|
||||
void EnablePLL();
|
||||
void DisablePLL();
|
||||
|
||||
void SwitchClock(bool toPCDClock);
|
||||
|
||||
protected:
|
||||
uint32 fRegisterBase;
|
||||
};
|
||||
|
||||
|
||||
class FDILink {
|
||||
public:
|
||||
FDILink(int32 pipeIndex);
|
||||
|
||||
FDITransmitter& Transmitter();
|
||||
FDIReceiver& Receiver();
|
||||
|
||||
private:
|
||||
FDITransmitter fTransmitter;
|
||||
FDIReceiver fReceiver;
|
||||
};
|
||||
|
||||
#endif // INTEL_FDI_H
|
|
@ -16,5 +16,10 @@ Addon intel_extreme.accelerant :
|
|||
mode.cpp
|
||||
overlay.cpp
|
||||
# overlay_3d_i965.cpp
|
||||
: be libaccelerantscommon.a
|
||||
# classes
|
||||
# DisplayPipe.cpp
|
||||
# FlexibleDisplayInterface.cpp
|
||||
# PanelFitter.cpp
|
||||
Ports.cpp
|
||||
: be $(TARGET_LIBSTDC++) libaccelerantscommon.a
|
||||
;
|
||||
|
|
|
@ -0,0 +1,69 @@
|
|||
/*
|
||||
* Copyright 2011, Haiku, Inc. All Rights Reserved.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*
|
||||
* Authors:
|
||||
* Michael Lotz, mmlr@mlotz.ch
|
||||
*/
|
||||
|
||||
|
||||
#include "PanelFitter.h"
|
||||
|
||||
#include "accelerant.h"
|
||||
#include "intel_extreme.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
|
||||
#define TRACE_FITTER
|
||||
#ifdef TRACE_FITTER
|
||||
extern "C" void _sPrintf(const char* format, ...);
|
||||
# define TRACE(x) _sPrintf x
|
||||
#else
|
||||
# define TRACE(x) ;
|
||||
#endif
|
||||
|
||||
|
||||
// #pragma mark - PanelFitter
|
||||
|
||||
|
||||
PanelFitter::PanelFitter(int32 pipeIndex)
|
||||
:
|
||||
fBaseRegister(PCH_PANEL_FITTER_BASE_REGISTER
|
||||
+ pipeIndex * PCH_PANEL_FITTER_PIPE_OFFSET)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
PanelFitter::IsEnabled()
|
||||
{
|
||||
return (read32(fBaseRegister + PCH_PANEL_FITTER_CONTROL)
|
||||
& PANEL_FITTER_ENABLED) != 0;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
PanelFitter::Enable(const display_mode& mode)
|
||||
{
|
||||
// TODO: program the right window size and position based on the mode
|
||||
_Enable(true);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
PanelFitter::Disable()
|
||||
{
|
||||
_Enable(false);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
PanelFitter::_Enable(bool enable)
|
||||
{
|
||||
uint32 targetRegister = fBaseRegister + PCH_PANEL_FITTER_CONTROL;
|
||||
write32(targetRegister, read32(targetRegister) & ~PANEL_FITTER_ENABLED
|
||||
| (enable ? PANEL_FITTER_ENABLED | 0));
|
||||
read32(targetRegister);
|
||||
}
|
|
@ -0,0 +1,27 @@
|
|||
/*
|
||||
* Copyright 2011, Haiku, Inc. All Rights Reserved.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*
|
||||
* Authors:
|
||||
* Michael Lotz, mmlr@mlotz.ch
|
||||
*/
|
||||
#ifndef INTEL_FITTER_H
|
||||
#define INTEL_FITTER_H
|
||||
|
||||
|
||||
class PanelFitter {
|
||||
public:
|
||||
PanelFitter(int32 pipeIndex);
|
||||
virtual ~PanelFitter();
|
||||
|
||||
bool IsEnabled();
|
||||
void Enable(const display_mode& mode);
|
||||
void Disable();
|
||||
|
||||
private:
|
||||
void _Enable(bool enable);
|
||||
|
||||
uint32 fRegisterBase;
|
||||
};
|
||||
|
||||
#endif // INTEL_FITTER_H
|
|
@ -0,0 +1,378 @@
|
|||
/*
|
||||
* Copyright 2006-2015, Haiku, Inc. All Rights Reserved.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*
|
||||
* Authors:
|
||||
* Axel Dörfler, axeld@pinc-software.de
|
||||
* Michael Lotz, mmlr@mlotz.ch
|
||||
* Alexander von Gluck IV, kallisti5@unixzen.com
|
||||
*/
|
||||
|
||||
|
||||
#include "Ports.h"
|
||||
|
||||
#include <Debug.h>
|
||||
#include <ddc.h>
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "accelerant.h"
|
||||
#include "intel_extreme.h"
|
||||
|
||||
|
||||
#undef TRACE
|
||||
#define TRACE_PORTS
|
||||
#ifdef TRACE_PORTS
|
||||
# define TRACE(x...) _sPrintf("intel_extreme:" x)
|
||||
#else
|
||||
# define TRACE(x...)
|
||||
#endif
|
||||
|
||||
#define ERROR(x...) _sPrintf("intel_extreme: " x)
|
||||
#define CALLED(x...) TRACE("CALLED %s\n", __PRETTY_FUNCTION__)
|
||||
|
||||
|
||||
Port::Port(port_index index, const char* baseName)
|
||||
:
|
||||
fPortIndex(index),
|
||||
fPortName(NULL),
|
||||
fEDIDState(B_NO_INIT)
|
||||
{
|
||||
char portID[2];
|
||||
portID[0] = 'A' + index - INTEL_PORT_A;
|
||||
portID[1] = 0;
|
||||
|
||||
char buffer[32];
|
||||
buffer[0] = 0;
|
||||
|
||||
strlcat(buffer, baseName, sizeof(buffer));
|
||||
strlcat(buffer, " ", sizeof(buffer));
|
||||
strlcat(buffer, portID, sizeof(buffer));
|
||||
fPortName = strdup(buffer);
|
||||
}
|
||||
|
||||
|
||||
Port::~Port()
|
||||
{
|
||||
free(fPortName);
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
Port::HasEDID()
|
||||
{
|
||||
if (fEDIDState == B_NO_INIT)
|
||||
GetEDID(NULL);
|
||||
|
||||
return fEDIDState == B_OK;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
Port::GetEDID(edid1_info* edid, bool forceRead)
|
||||
{
|
||||
CALLED();
|
||||
|
||||
if (fEDIDState == B_NO_INIT || forceRead) {
|
||||
TRACE("%s: trying to read EDID\n", PortName());
|
||||
|
||||
addr_t ddcRegister = _DDCRegister();
|
||||
if (ddcRegister == 0) {
|
||||
fEDIDState = B_ERROR;
|
||||
return fEDIDState;
|
||||
}
|
||||
|
||||
TRACE("%s: using register %" B_PRIx32 "\n", PortName(), ddcRegister);
|
||||
|
||||
i2c_bus bus;
|
||||
bus.cookie = (void*)ddcRegister;
|
||||
bus.set_signals = &_SetI2CSignals;
|
||||
bus.get_signals = &_GetI2CSignals;
|
||||
ddc2_init_timing(&bus);
|
||||
|
||||
fEDIDState = ddc2_read_edid1(&bus, &fEDIDInfo, NULL, NULL);
|
||||
|
||||
if (fEDIDState == B_OK) {
|
||||
TRACE("%s: found EDID information!\n", PortName());
|
||||
edid_dump(&fEDIDInfo);
|
||||
}
|
||||
}
|
||||
|
||||
if (fEDIDState != B_OK) {
|
||||
TRACE("%s: no EDID information found.\n", PortName());
|
||||
return fEDIDState;
|
||||
}
|
||||
|
||||
if (edid != NULL)
|
||||
memcpy(edid, &fEDIDInfo, sizeof(edid1_info));
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
Port::GetPLLLimits(pll_limits& limits)
|
||||
{
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
Port::_GetI2CSignals(void* cookie, int* _clock, int* _data)
|
||||
{
|
||||
addr_t ioRegister = (addr_t)cookie;
|
||||
uint32 value = read32(ioRegister);
|
||||
|
||||
*_clock = (value & I2C_CLOCK_VALUE_IN) != 0;
|
||||
*_data = (value & I2C_DATA_VALUE_IN) != 0;
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
Port::_SetI2CSignals(void* cookie, int clock, int data)
|
||||
{
|
||||
addr_t ioRegister = (addr_t)cookie;
|
||||
uint32 value;
|
||||
|
||||
if (gInfo->shared_info->device_type.InGroup(INTEL_TYPE_83x)) {
|
||||
// on these chips, the reserved values are fixed
|
||||
value = 0;
|
||||
} else {
|
||||
// on all others, we have to preserve them manually
|
||||
value = read32(ioRegister) & I2C_RESERVED;
|
||||
}
|
||||
|
||||
if (data != 0)
|
||||
value |= I2C_DATA_DIRECTION_MASK;
|
||||
else {
|
||||
value |= I2C_DATA_DIRECTION_MASK | I2C_DATA_DIRECTION_OUT
|
||||
| I2C_DATA_VALUE_MASK;
|
||||
}
|
||||
|
||||
if (clock != 0)
|
||||
value |= I2C_CLOCK_DIRECTION_MASK;
|
||||
else {
|
||||
value |= I2C_CLOCK_DIRECTION_MASK | I2C_CLOCK_DIRECTION_OUT
|
||||
| I2C_CLOCK_VALUE_MASK;
|
||||
}
|
||||
|
||||
write32(ioRegister, value);
|
||||
read32(ioRegister);
|
||||
// make sure the PCI bus has flushed the write
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark - Analog Port
|
||||
|
||||
|
||||
AnalogPort::AnalogPort()
|
||||
:
|
||||
Port(INTEL_PORT_A, "Analog")
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
AnalogPort::IsConnected()
|
||||
{
|
||||
return HasEDID();
|
||||
}
|
||||
|
||||
|
||||
uint32
|
||||
AnalogPort::_DDCRegister()
|
||||
{
|
||||
// always fixed
|
||||
return INTEL_I2C_IO_A;
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark - LVDS Panel
|
||||
|
||||
|
||||
LVDSPort::LVDSPort()
|
||||
:
|
||||
Port(INTEL_PORT_C, "LVDS")
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
LVDSPort::IsConnected()
|
||||
{
|
||||
uint32 registerValue = read32(INTEL_DIGITAL_LVDS_PORT);
|
||||
if (gInfo->shared_info->device_type.HasPlatformControlHub()) {
|
||||
// there's a detection bit we can use
|
||||
if ((registerValue & PCH_LVDS_DETECTED) == 0)
|
||||
return false;
|
||||
}
|
||||
|
||||
// Try getting EDID, as the LVDS port doesn't overlap with anything else,
|
||||
// we don't run the risk of getting someone else's data.
|
||||
return HasEDID();
|
||||
}
|
||||
|
||||
|
||||
uint32
|
||||
LVDSPort::_DDCRegister()
|
||||
{
|
||||
// always fixed
|
||||
return INTEL_I2C_IO_C;
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark - DVI/SDVO/generic
|
||||
|
||||
|
||||
DigitalPort::DigitalPort(port_index index, const char* baseName)
|
||||
:
|
||||
Port(index, baseName)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
DigitalPort::IsConnected()
|
||||
{
|
||||
// As this port overlaps with pretty much everything, this must be called
|
||||
// after having ruled out all other port types.
|
||||
return HasEDID();
|
||||
}
|
||||
|
||||
|
||||
uint32
|
||||
DigitalPort::_DDCRegister()
|
||||
{
|
||||
switch (PortIndex()) {
|
||||
case INTEL_PORT_B:
|
||||
return INTEL_I2C_IO_E;
|
||||
case INTEL_PORT_C:
|
||||
return INTEL_I2C_IO_D;
|
||||
case INTEL_PORT_D:
|
||||
return INTEL_I2C_IO_F;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark - HDMI
|
||||
|
||||
|
||||
HDMIPort::HDMIPort(port_index index)
|
||||
:
|
||||
DigitalPort(index, "HDMI")
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
HDMIPort::IsConnected()
|
||||
{
|
||||
if (!gInfo->shared_info->device_type.SupportsHDMI())
|
||||
return false;
|
||||
|
||||
uint32 portRegister = _PortRegister();
|
||||
if (portRegister == 0)
|
||||
return false;
|
||||
|
||||
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)
|
||||
return false;
|
||||
|
||||
return HasEDID();
|
||||
}
|
||||
|
||||
|
||||
uint32
|
||||
HDMIPort::_PortRegister()
|
||||
{
|
||||
// on PCH there's an additional port sandwiched in
|
||||
bool hasPCH = gInfo->shared_info->device_type.HasPlatformControlHub();
|
||||
|
||||
switch (PortIndex()) {
|
||||
case INTEL_PORT_B:
|
||||
return hasPCH ? PCH_HDMI_PORT_B : INTEL_HDMI_PORT_B;
|
||||
case INTEL_PORT_C:
|
||||
return hasPCH ? PCH_HDMI_PORT_C : INTEL_HDMI_PORT_C;
|
||||
case INTEL_PORT_D:
|
||||
return hasPCH ? PCH_HDMI_PORT_D : 0;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark - DisplayPort
|
||||
|
||||
|
||||
DisplayPort::DisplayPort(port_index index, const char* baseName)
|
||||
:
|
||||
DigitalPort(index, baseName)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
DisplayPort::IsConnected()
|
||||
{
|
||||
uint32 portRegister = _PortRegister();
|
||||
if (portRegister == 0)
|
||||
return false;
|
||||
|
||||
if ((read32(portRegister) & PORT_DETECTED) == 0)
|
||||
return false;
|
||||
|
||||
return HasEDID();
|
||||
}
|
||||
|
||||
|
||||
uint32
|
||||
DisplayPort::_PortRegister()
|
||||
{
|
||||
switch (PortIndex()) {
|
||||
case INTEL_PORT_A:
|
||||
return INTEL_DISPLAY_PORT_A;
|
||||
case INTEL_PORT_B:
|
||||
return INTEL_DISPLAY_PORT_B;
|
||||
case INTEL_PORT_C:
|
||||
return INTEL_DISPLAY_PORT_C;
|
||||
case INTEL_PORT_D:
|
||||
return INTEL_DISPLAY_PORT_D;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark - Embedded DisplayPort
|
||||
|
||||
|
||||
EmbeddedDisplayPort::EmbeddedDisplayPort()
|
||||
:
|
||||
DisplayPort(INTEL_PORT_A, "Embedded DisplayPort")
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
EmbeddedDisplayPort::IsConnected()
|
||||
{
|
||||
if (!gInfo->shared_info->device_type.IsMobile())
|
||||
return false;
|
||||
|
||||
return DisplayPort::IsConnected();
|
||||
}
|
|
@ -0,0 +1,160 @@
|
|||
/*
|
||||
* Copyright 2011, Haiku, Inc. All Rights Reserved.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*
|
||||
* Authors:
|
||||
* Michael Lotz, mmlr@mlotz.ch
|
||||
*/
|
||||
#ifndef INTEL_PORTS_H
|
||||
#define INTEL_PORTS_H
|
||||
|
||||
#include <edid.h>
|
||||
|
||||
|
||||
#define MAX_PORTS 20 // a generous upper bound
|
||||
|
||||
struct pll_limits;
|
||||
|
||||
enum port_type {
|
||||
INTEL_PORT_TYPE_ANY, // wildcard for lookup functions
|
||||
INTEL_PORT_TYPE_ANALOG,
|
||||
INTEL_PORT_TYPE_DVI,
|
||||
INTEL_PORT_TYPE_LVDS,
|
||||
INTEL_PORT_TYPE_DP,
|
||||
INTEL_PORT_TYPE_eDP,
|
||||
INTEL_PORT_TYPE_HDMI
|
||||
};
|
||||
|
||||
enum port_index {
|
||||
INTEL_PORT_ANY, // wildcard for lookup functions
|
||||
INTEL_PORT_A,
|
||||
INTEL_PORT_B,
|
||||
INTEL_PORT_C,
|
||||
INTEL_PORT_D
|
||||
};
|
||||
|
||||
|
||||
class Port {
|
||||
public:
|
||||
Port(port_index index,
|
||||
const char* baseName);
|
||||
virtual ~Port();
|
||||
|
||||
virtual uint32 Type() const = 0;
|
||||
const char* PortName() const
|
||||
{ return fPortName; }
|
||||
|
||||
port_index PortIndex() const
|
||||
{ return fPortIndex; }
|
||||
|
||||
virtual bool IsConnected() = 0;
|
||||
|
||||
bool HasEDID();
|
||||
virtual status_t GetEDID(edid1_info* edid,
|
||||
bool forceRead = false);
|
||||
|
||||
virtual status_t GetPLLLimits(pll_limits& limits);
|
||||
|
||||
protected:
|
||||
void _SetName(const char* name);
|
||||
|
||||
static status_t _GetI2CSignals(void* cookie, int* _clock,
|
||||
int* _data);
|
||||
static status_t _SetI2CSignals(void* cookie, int clock,
|
||||
int data);
|
||||
|
||||
private:
|
||||
virtual uint32 _DDCRegister() = 0;
|
||||
|
||||
port_index fPortIndex;
|
||||
char* fPortName;
|
||||
|
||||
status_t fEDIDState;
|
||||
edid1_info fEDIDInfo;
|
||||
};
|
||||
|
||||
|
||||
class AnalogPort : public Port {
|
||||
public:
|
||||
AnalogPort();
|
||||
|
||||
virtual uint32 Type() const
|
||||
{ return INTEL_PORT_TYPE_ANALOG; }
|
||||
|
||||
virtual bool IsConnected();
|
||||
|
||||
protected:
|
||||
virtual uint32 _DDCRegister();
|
||||
};
|
||||
|
||||
|
||||
class LVDSPort : public Port {
|
||||
public:
|
||||
LVDSPort();
|
||||
|
||||
virtual uint32 Type() const
|
||||
{ return INTEL_PORT_TYPE_LVDS; }
|
||||
|
||||
virtual bool IsConnected();
|
||||
|
||||
protected:
|
||||
virtual uint32 _DDCRegister();
|
||||
};
|
||||
|
||||
|
||||
class DigitalPort : public Port {
|
||||
public:
|
||||
DigitalPort(
|
||||
port_index index = INTEL_PORT_B,
|
||||
const char* baseName = "DVI");
|
||||
|
||||
virtual uint32 Type() const
|
||||
{ return INTEL_PORT_TYPE_DVI; }
|
||||
|
||||
virtual bool IsConnected();
|
||||
|
||||
protected:
|
||||
virtual uint32 _DDCRegister();
|
||||
};
|
||||
|
||||
|
||||
class HDMIPort : public DigitalPort {
|
||||
public:
|
||||
HDMIPort(port_index index);
|
||||
|
||||
virtual uint32 Type() const
|
||||
{ return INTEL_PORT_TYPE_HDMI; }
|
||||
|
||||
virtual bool IsConnected();
|
||||
|
||||
protected:
|
||||
uint32 _PortRegister();
|
||||
};
|
||||
|
||||
|
||||
class DisplayPort : public DigitalPort {
|
||||
public:
|
||||
DisplayPort(port_index index,
|
||||
const char* baseName = "DisplayPort");
|
||||
|
||||
virtual uint32 Type() const
|
||||
{ return INTEL_PORT_TYPE_DP; }
|
||||
|
||||
virtual bool IsConnected();
|
||||
|
||||
protected:
|
||||
uint32 _PortRegister();
|
||||
};
|
||||
|
||||
|
||||
class EmbeddedDisplayPort : public DisplayPort {
|
||||
public:
|
||||
EmbeddedDisplayPort();
|
||||
|
||||
virtual uint32 Type() const
|
||||
{ return INTEL_PORT_TYPE_eDP; }
|
||||
|
||||
virtual bool IsConnected();
|
||||
};
|
||||
|
||||
#endif // INTEL_PORTS_H
|
|
@ -19,18 +19,20 @@
|
|||
#include <unistd.h>
|
||||
#include <syslog.h>
|
||||
|
||||
#include <new>
|
||||
|
||||
#include <AGP.h>
|
||||
|
||||
|
||||
#undef TRACE
|
||||
#define TRACE_ACCELERANT
|
||||
#ifdef TRACE_ACCELERANT
|
||||
# define TRACE(x...) _sPrintf("intel_extreme accelerant:" x)
|
||||
# define TRACE(x...) _sPrintf("intel_extreme:" x)
|
||||
#else
|
||||
# define TRACE(x...)
|
||||
#endif
|
||||
|
||||
#define ERROR(x...) _sPrintf("intel_extreme accelerant: " x)
|
||||
#define ERROR(x...) _sPrintf("intel_extreme: " x)
|
||||
#define CALLED(x...) TRACE("CALLED %s\n", __PRETTY_FUNCTION__)
|
||||
|
||||
|
||||
|
@ -179,6 +181,23 @@ uninit_common(void)
|
|||
}
|
||||
|
||||
|
||||
static bool
|
||||
has_connected_port(port_index portIndex, uint32 type)
|
||||
{
|
||||
for (uint32 i = 0; i < gInfo->port_count; i++) {
|
||||
Port* port = gInfo->ports[i];
|
||||
if (type != INTEL_PORT_TYPE_ANY && port->Type() != type)
|
||||
continue;
|
||||
if (portIndex != INTEL_PORT_ANY && port->PortIndex() != portIndex)
|
||||
continue;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark - public accelerant functions
|
||||
|
||||
|
||||
|
@ -199,36 +218,91 @@ intel_init_accelerant(int device)
|
|||
|
||||
setup_ring_buffer(info.primary_ring_buffer, "intel primary ring buffer");
|
||||
|
||||
// determine head depending on what's already enabled from the BIOS
|
||||
// TODO: it would be nicer to retrieve this data via DDC - else the
|
||||
// display is gone for good if the BIOS decides to only show the
|
||||
// picture on the connected analog monitor!
|
||||
gInfo->head_mode = 0;
|
||||
if (read32(INTEL_DISPLAY_B_PIPE_CONTROL) & DISPLAY_PIPE_ENABLED)
|
||||
gInfo->head_mode |= HEAD_MODE_B_DIGITAL;
|
||||
if (read32(INTEL_DISPLAY_A_PIPE_CONTROL) & DISPLAY_PIPE_ENABLED)
|
||||
gInfo->head_mode |= HEAD_MODE_A_ANALOG;
|
||||
TRACE("pipe control for: 0x%" B_PRIx32 " 0x%" B_PRIx32 "\n",
|
||||
read32(INTEL_PIPE_CONTROL), read32(INTEL_PIPE_CONTROL));
|
||||
|
||||
uint32 lvds = read32(INTEL_DISPLAY_LVDS_PORT);
|
||||
// Try to determine what ports to use. We use the following heuristic:
|
||||
// * Check for DisplayPort, these can be more or less detected reliably.
|
||||
// * Check for HDMI, it'll fail on devices not having HDMI for us to fall
|
||||
// back to DVI.
|
||||
// * Assume DVI B if no HDMI and no DisplayPort is present, confirmed by
|
||||
// reading EDID in the IsConnected() call.
|
||||
// * Check for analog if possible (there's a detection bit on PCH),
|
||||
// otherwise the assumed presence is confirmed by reading EDID in
|
||||
// IsConnected().
|
||||
|
||||
// If we have an enabled display pipe we save the passed information and
|
||||
// assume it is the valid panel size..
|
||||
// Later we query for proper EDID info if it exists, or figure something
|
||||
// else out. (Default modes, etc.)
|
||||
bool hasPCH = gInfo->shared_info->device_type.HasPlatformControlHub();
|
||||
if ((hasPCH && (lvds & PCH_LVDS_DETECTED) != 0)
|
||||
|| (!hasPCH && (lvds & DISPLAY_PIPE_ENABLED) != 0)) {
|
||||
save_lvds_mode();
|
||||
gInfo->head_mode |= HEAD_MODE_LVDS_PANEL;
|
||||
gInfo->port_count = 0;
|
||||
for (int i = INTEL_PORT_B; i <= INTEL_PORT_D; i++) {
|
||||
Port* displayPort = new(std::nothrow) DisplayPort((port_index)i);
|
||||
if (displayPort == NULL)
|
||||
return B_NO_MEMORY;
|
||||
|
||||
if (displayPort->IsConnected())
|
||||
gInfo->ports[gInfo->port_count++] = displayPort;
|
||||
else
|
||||
delete displayPort;
|
||||
}
|
||||
|
||||
TRACE("head detected: %#x\n", gInfo->head_mode);
|
||||
TRACE("adpa: %08" B_PRIx32 ", dova: %08" B_PRIx32 ", dovb: %08" B_PRIx32
|
||||
", lvds: %08" B_PRIx32 "\n",
|
||||
read32(INTEL_DISPLAY_A_ANALOG_PORT),
|
||||
read32(INTEL_DISPLAY_A_DIGITAL_PORT),
|
||||
read32(INTEL_DISPLAY_B_DIGITAL_PORT),
|
||||
read32(INTEL_DISPLAY_LVDS_PORT));
|
||||
for (int i = INTEL_PORT_B; i <= INTEL_PORT_D; i++) {
|
||||
if (has_connected_port((port_index)i, INTEL_PORT_TYPE_ANY)) {
|
||||
// we overlap with a DisplayPort, this is not HDMI
|
||||
continue;
|
||||
}
|
||||
|
||||
Port* hdmiPort = new(std::nothrow) HDMIPort((port_index)i);
|
||||
if (hdmiPort == NULL)
|
||||
return B_NO_MEMORY;
|
||||
|
||||
if (hdmiPort->IsConnected())
|
||||
gInfo->ports[gInfo->port_count++] = hdmiPort;
|
||||
else
|
||||
delete hdmiPort;
|
||||
}
|
||||
|
||||
if (!has_connected_port(INTEL_PORT_ANY, INTEL_PORT_TYPE_ANY)) {
|
||||
// there's neither DisplayPort nor HDMI so far, assume DVI B
|
||||
Port* dviPort = new(std::nothrow) DigitalPort(INTEL_PORT_B);
|
||||
if (dviPort == NULL)
|
||||
return B_NO_MEMORY;
|
||||
|
||||
if (dviPort->IsConnected()) {
|
||||
gInfo->ports[gInfo->port_count++] = dviPort;
|
||||
gInfo->head_mode |= HEAD_MODE_B_DIGITAL;
|
||||
} else
|
||||
delete dviPort;
|
||||
}
|
||||
|
||||
// always try the LVDS port, it'll simply fail if not applicable
|
||||
Port* lvdsPort = new(std::nothrow) LVDSPort();
|
||||
if (lvdsPort == NULL)
|
||||
return B_NO_MEMORY;
|
||||
if (lvdsPort->IsConnected()) {
|
||||
gInfo->ports[gInfo->port_count++] = lvdsPort;
|
||||
gInfo->head_mode |= HEAD_MODE_LVDS_PANEL;
|
||||
gInfo->head_mode |= HEAD_MODE_A_ANALOG;
|
||||
} else
|
||||
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
|
||||
Port* analogPort = new(std::nothrow) AnalogPort();
|
||||
if (analogPort == NULL)
|
||||
return B_NO_MEMORY;
|
||||
if (analogPort->IsConnected()) {
|
||||
gInfo->ports[gInfo->port_count++] = analogPort;
|
||||
gInfo->head_mode |= HEAD_MODE_A_ANALOG;
|
||||
} else
|
||||
delete analogPort;
|
||||
|
||||
TRACE("connected ports detected: %" B_PRIu32 "\n", gInfo->port_count);
|
||||
|
||||
status = create_mode_list();
|
||||
if (status != B_OK) {
|
||||
|
|
|
@ -14,6 +14,8 @@
|
|||
#include <edid.h>
|
||||
#include <video_overlay.h>
|
||||
|
||||
#include "Ports.h"
|
||||
|
||||
|
||||
struct overlay {
|
||||
overlay_buffer buffer;
|
||||
|
@ -48,6 +50,9 @@ struct accelerant_info {
|
|||
uint32 last_vertical_overlay_scale;
|
||||
uint32 overlay_position_buffer_offset;
|
||||
|
||||
uint32 port_count;
|
||||
Port* ports[MAX_PORTS];
|
||||
|
||||
edid1_info edid_info;
|
||||
bool has_edid;
|
||||
|
||||
|
@ -64,10 +69,12 @@ struct accelerant_info {
|
|||
display_mode lvds_panel_mode;
|
||||
};
|
||||
|
||||
#define HEAD_MODE_A_ANALOG 0x01
|
||||
#define HEAD_MODE_B_DIGITAL 0x02
|
||||
#define HEAD_MODE_CLONE 0x03
|
||||
#define HEAD_MODE_LVDS_PANEL 0x08
|
||||
#define HEAD_MODE_A_ANALOG 0x0001
|
||||
#define HEAD_MODE_B_DIGITAL 0x0002
|
||||
#define HEAD_MODE_CLONE 0x0003
|
||||
#define HEAD_MODE_LVDS_PANEL 0x0008
|
||||
#define HEAD_MODE_TESTING 0x1000
|
||||
#define HEAD_MODE_STIPPI 0x2000
|
||||
|
||||
extern accelerant_info* gInfo;
|
||||
|
||||
|
|
|
@ -71,22 +71,22 @@ enable_display_pipe(bool enable)
|
|||
if (enable) {
|
||||
if (gInfo->head_mode & HEAD_MODE_A_ANALOG) {
|
||||
write32(INTEL_DISPLAY_A_PIPE_CONTROL,
|
||||
pipeAControl | DISPLAY_PIPE_ENABLED);
|
||||
pipeAControl | INTEL_PIPE_ENABLED);
|
||||
}
|
||||
|
||||
if (gInfo->head_mode & HEAD_MODE_B_DIGITAL) {
|
||||
write32(INTEL_DISPLAY_B_PIPE_CONTROL,
|
||||
pipeBControl | DISPLAY_PIPE_ENABLED);
|
||||
pipeBControl | INTEL_PIPE_ENABLED);
|
||||
}
|
||||
} else {
|
||||
if (gInfo->head_mode & HEAD_MODE_A_ANALOG) {
|
||||
write32(INTEL_DISPLAY_A_PIPE_CONTROL,
|
||||
pipeAControl & ~DISPLAY_PIPE_ENABLED);
|
||||
pipeAControl & ~INTEL_PIPE_ENABLED);
|
||||
}
|
||||
|
||||
if (gInfo->head_mode & HEAD_MODE_B_DIGITAL) {
|
||||
write32(INTEL_DISPLAY_B_PIPE_CONTROL,
|
||||
pipeBControl & ~DISPLAY_PIPE_ENABLED);
|
||||
pipeBControl & ~INTEL_PIPE_ENABLED);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -188,16 +188,15 @@ set_display_power_mode(uint32 mode)
|
|||
}
|
||||
|
||||
if (gInfo->head_mode & HEAD_MODE_A_ANALOG) {
|
||||
write32(INTEL_DISPLAY_A_ANALOG_PORT,
|
||||
(read32(INTEL_DISPLAY_A_ANALOG_PORT)
|
||||
write32(INTEL_ANALOG_PORT, (read32(INTEL_ANALOG_PORT)
|
||||
& ~(DISPLAY_MONITOR_MODE_MASK | DISPLAY_MONITOR_PORT_ENABLED))
|
||||
| monitorMode
|
||||
| (mode != B_DPMS_OFF ? DISPLAY_MONITOR_PORT_ENABLED : 0));
|
||||
}
|
||||
|
||||
if (gInfo->head_mode & HEAD_MODE_B_DIGITAL) {
|
||||
write32(INTEL_DISPLAY_B_DIGITAL_PORT,
|
||||
(read32(INTEL_DISPLAY_B_DIGITAL_PORT)
|
||||
& ~(DISPLAY_MONITOR_MODE_MASK | DISPLAY_MONITOR_PORT_ENABLED))
|
||||
write32(INTEL_DIGITAL_PORT_B, (read32(INTEL_DIGITAL_PORT_B)
|
||||
& ~(/*DISPLAY_MONITOR_MODE_MASK |*/ DISPLAY_MONITOR_PORT_ENABLED))
|
||||
| (mode != B_DPMS_OFF ? DISPLAY_MONITOR_PORT_ENABLED : 0));
|
||||
// TODO: monitorMode?
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2006-2014, Haiku, Inc. All Rights Reserved.
|
||||
* Copyright 2006-2010, Haiku, Inc. All Rights Reserved.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*
|
||||
* Support for i915 chipset and up based on the X driver,
|
||||
|
@ -10,20 +10,26 @@
|
|||
*/
|
||||
|
||||
|
||||
#include "accelerant_protos.h"
|
||||
#include "accelerant.h"
|
||||
#include "utility.h"
|
||||
|
||||
#include <Debug.h>
|
||||
#include <math.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
|
||||
#include <Debug.h>
|
||||
|
||||
#include <create_display_modes.h>
|
||||
#include <ddc.h>
|
||||
#include <edid.h>
|
||||
#include <validate_display_mode.h>
|
||||
|
||||
#include "accelerant_protos.h"
|
||||
#include "accelerant.h"
|
||||
#if 0
|
||||
#include "DisplayPipe.h"
|
||||
#include "FlexibleDisplayInterface.h"
|
||||
#endif
|
||||
#include "Ports.h"
|
||||
#include "utility.h"
|
||||
|
||||
|
||||
#undef TRACE
|
||||
#define TRACE_MODE
|
||||
|
@ -37,23 +43,6 @@
|
|||
#define CALLED(x...) TRACE("CALLED %s\n", __PRETTY_FUNCTION__)
|
||||
|
||||
|
||||
struct display_registers {
|
||||
uint32 pll;
|
||||
uint32 divisors;
|
||||
uint32 control;
|
||||
uint32 pipe_config;
|
||||
uint32 horiz_total;
|
||||
uint32 horiz_blank;
|
||||
uint32 horiz_sync;
|
||||
uint32 vert_total;
|
||||
uint32 vert_blank;
|
||||
uint32 vert_sync;
|
||||
uint32 size;
|
||||
uint32 stride;
|
||||
uint32 position;
|
||||
uint32 pipe_source;
|
||||
};
|
||||
|
||||
struct pll_divisors {
|
||||
uint32 post;
|
||||
uint32 post1;
|
||||
|
@ -73,64 +62,6 @@ 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);
|
||||
|
||||
|
||||
static status_t
|
||||
get_i2c_signals(void* cookie, int* _clock, int* _data)
|
||||
{
|
||||
uint32 ioRegister = (uint32)(addr_t)cookie;
|
||||
uint32 value = read32(ioRegister);
|
||||
|
||||
*_clock = (value & I2C_CLOCK_VALUE_IN) != 0;
|
||||
*_data = (value & I2C_DATA_VALUE_IN) != 0;
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
static status_t
|
||||
set_i2c_signals(void* cookie, int clock, int data)
|
||||
{
|
||||
uint32 ioRegister = (uint32)(addr_t)cookie;
|
||||
uint32 value;
|
||||
|
||||
if (gInfo->shared_info->device_type.InGroup(INTEL_TYPE_83x)) {
|
||||
// on these chips, the reserved values are fixed
|
||||
value = 0;
|
||||
} else {
|
||||
// on all others, we have to preserve them manually
|
||||
value = read32(ioRegister) & I2C_RESERVED;
|
||||
}
|
||||
|
||||
if (data != 0)
|
||||
value |= I2C_DATA_DIRECTION_MASK;
|
||||
else {
|
||||
value |= I2C_DATA_DIRECTION_MASK | I2C_DATA_DIRECTION_OUT
|
||||
| I2C_DATA_VALUE_MASK;
|
||||
}
|
||||
|
||||
if (clock != 0)
|
||||
value |= I2C_CLOCK_DIRECTION_MASK;
|
||||
else {
|
||||
value |= I2C_CLOCK_DIRECTION_MASK | I2C_CLOCK_DIRECTION_OUT
|
||||
| I2C_CLOCK_VALUE_MASK;
|
||||
}
|
||||
|
||||
write32(ioRegister, value);
|
||||
read32(ioRegister);
|
||||
// make sure the PCI bus has flushed the write
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
get_pll_limits(pll_limits &limits)
|
||||
|
@ -191,14 +122,16 @@ get_pll_limits(pll_limits &limits)
|
|||
limits = kLimits;
|
||||
}
|
||||
|
||||
TRACE("PLL limits, min: p %" B_PRIu32 " (p1 %" B_PRIu32 ", p2 %" B_PRIu32
|
||||
"), n %" B_PRIu32 ", m %" B_PRIu32 " (m1 %" B_PRIu32 ", m2 %" B_PRIu32
|
||||
")\n", limits.min.post, limits.min.post1, limits.min.post2,
|
||||
limits.min.n, limits.min.m, limits.min.m1, limits.min.m2);
|
||||
TRACE("PLL limits, max: p %" B_PRIu32 " (p1 %" B_PRIu32 ", p2 %" B_PRIu32
|
||||
"), n %" B_PRIu32 ", m %" B_PRIu32 " (m1 %" B_PRIu32 ", m2 %" B_PRIu32
|
||||
")\n", limits.max.post, limits.max.post1, limits.max.post2,
|
||||
limits.max.n, limits.max.m, limits.max.m1, limits.max.m2);
|
||||
TRACE("PLL limits, min: p %" B_PRId32 " (p1 %" B_PRId32 ", "
|
||||
"p2 %" B_PRId32 "), n %" B_PRId32 ", m %" B_PRId32 " "
|
||||
"(m1 %" B_PRId32 ", m2 %" B_PRId32 ")\n", limits.min.post,
|
||||
limits.min.post1, limits.min.post2, limits.min.n, limits.min.m,
|
||||
limits.min.m1, limits.min.m2);
|
||||
TRACE("PLL limits, max: p %" B_PRId32 " (p1 %" B_PRId32 ", "
|
||||
"p2 %" B_PRId32 "), n %" B_PRId32 ", m %" B_PRId32 " "
|
||||
"(m1 %" B_PRId32 ", m2 %" B_PRId32 ")\n", limits.max.post,
|
||||
limits.max.post1, limits.max.post2, limits.max.n, limits.max.m,
|
||||
limits.max.m1, limits.max.m2);
|
||||
}
|
||||
|
||||
|
||||
|
@ -232,7 +165,7 @@ compute_pll_divisors(const display_mode ¤t, pll_divisors& divisors,
|
|||
TRACE("%s: required MHz: %g\n", __func__, requestedPixelClock);
|
||||
|
||||
if (isLVDS) {
|
||||
if ((read32(INTEL_DISPLAY_LVDS_PORT) & LVDS_CLKB_POWER_MASK)
|
||||
if ((read32(INTEL_DIGITAL_LVDS_PORT) & LVDS_CLKB_POWER_MASK)
|
||||
== LVDS_CLKB_POWER_UP)
|
||||
divisors.post2 = LVDS_POST2_RATE_FAST;
|
||||
else
|
||||
|
@ -284,40 +217,15 @@ compute_pll_divisors(const display_mode ¤t, pll_divisors& divisors,
|
|||
|
||||
divisors = bestDivisors;
|
||||
|
||||
TRACE("%s: found: %g MHz, p = %" B_PRIu32 " (p1 = %" B_PRIu32 ", p2 = %"
|
||||
B_PRIu32 "), n = %" B_PRIu32 ", m = %" B_PRIu32 " (m1 = %" B_PRIu32
|
||||
", m2 = %" B_PRIu32 ")\n", __func__,
|
||||
TRACE("%s: found: %g MHz, p = %" B_PRId32 " (p1 = %" B_PRId32 ", "
|
||||
"p2 = %" B_PRId32 "), n = %" B_PRId32 ", m = %" B_PRId32 " "
|
||||
"(m1 = %" B_PRId32 ", m2 = %" B_PRId32 ")\n", __func__,
|
||||
((referenceClock * divisors.m) / divisors.n) / divisors.post,
|
||||
divisors.post, divisors.post1, divisors.post2, divisors.n,
|
||||
divisors.m, divisors.m1, divisors.m2);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
mode_fill_missing_bits(display_mode *mode, uint32 cntrl)
|
||||
{
|
||||
uint32 value = read32(cntrl);
|
||||
|
||||
switch (value & DISPLAY_CONTROL_COLOR_MASK) {
|
||||
case DISPLAY_CONTROL_RGB32:
|
||||
default:
|
||||
mode->space = B_RGB32;
|
||||
break;
|
||||
case DISPLAY_CONTROL_RGB16:
|
||||
mode->space = B_RGB16;
|
||||
break;
|
||||
case DISPLAY_CONTROL_RGB15:
|
||||
mode->space = B_RGB15;
|
||||
break;
|
||||
case DISPLAY_CONTROL_CMAP8:
|
||||
mode->space = B_CMAP8;
|
||||
break;
|
||||
}
|
||||
|
||||
mode->flags = B_8_BIT_DAC | B_HARDWARE_CURSOR | B_PARALLEL_ACCESS | B_DPMS;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
retrieve_current_mode(display_mode& mode, uint32 pllRegister)
|
||||
{
|
||||
|
@ -352,7 +260,6 @@ retrieve_current_mode(display_mode& mode, uint32 pllRegister)
|
|||
controlRegister = INTEL_DISPLAY_B_CONTROL;
|
||||
} else {
|
||||
// TODO: not supported
|
||||
TRACE("%s: pllRegister not yet supported\n", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -448,13 +355,27 @@ retrieve_current_mode(display_mode& mode, uint32 pllRegister)
|
|||
if (mode.virtual_height < mode.timing.v_display)
|
||||
mode.virtual_height = mode.timing.v_display;
|
||||
|
||||
mode_fill_missing_bits(&mode, controlRegister);
|
||||
value = read32(controlRegister);
|
||||
switch (value & DISPLAY_CONTROL_COLOR_MASK) {
|
||||
case DISPLAY_CONTROL_RGB32:
|
||||
default:
|
||||
mode.space = B_RGB32;
|
||||
break;
|
||||
case DISPLAY_CONTROL_RGB16:
|
||||
mode.space = B_RGB16;
|
||||
break;
|
||||
case DISPLAY_CONTROL_RGB15:
|
||||
mode.space = B_RGB15;
|
||||
break;
|
||||
case DISPLAY_CONTROL_CMAP8:
|
||||
mode.space = B_CMAP8;
|
||||
break;
|
||||
}
|
||||
|
||||
mode.h_display_start = 0;
|
||||
mode.v_display_start = 0;
|
||||
if (gInfo->overlay_registers != NULL) {
|
||||
mode.flags |= B_SUPPORTS_OVERLAYS;
|
||||
}
|
||||
mode.flags = B_8_BIT_DAC | B_HARDWARE_CURSOR | B_PARALLEL_ACCESS
|
||||
| B_DPMS | B_SUPPORTS_OVERLAYS;
|
||||
}
|
||||
|
||||
|
||||
|
@ -502,12 +423,15 @@ sanitize_display_mode(display_mode& mode)
|
|||
{
|
||||
// Some cards only support even pixel counts, while others require an odd
|
||||
// one.
|
||||
bool olderCard = gInfo->shared_info->device_type.InGroup(INTEL_TYPE_Gxx);
|
||||
olderCard |= gInfo->shared_info->device_type.InGroup(INTEL_TYPE_96x);
|
||||
olderCard |= gInfo->shared_info->device_type.InGroup(INTEL_TYPE_94x);
|
||||
olderCard |= gInfo->shared_info->device_type.InGroup(INTEL_TYPE_91x);
|
||||
olderCard |= gInfo->shared_info->device_type.InFamily(INTEL_TYPE_8xx);
|
||||
olderCard |= gInfo->shared_info->device_type.InFamily(INTEL_TYPE_7xx);
|
||||
uint16 pixelCount = 1;
|
||||
if (gInfo->shared_info->device_type.InGroup(INTEL_TYPE_Gxx)
|
||||
|| gInfo->shared_info->device_type.InGroup(INTEL_TYPE_96x)
|
||||
|| gInfo->shared_info->device_type.InGroup(INTEL_TYPE_94x)
|
||||
|| gInfo->shared_info->device_type.InGroup(INTEL_TYPE_91x)
|
||||
|| gInfo->shared_info->device_type.InFamily(INTEL_TYPE_8xx)
|
||||
|| gInfo->shared_info->device_type.InFamily(INTEL_TYPE_7xx)) {
|
||||
pixelCount = 2;
|
||||
}
|
||||
|
||||
// TODO: verify constraints - these are more or less taken from the
|
||||
// radeon driver!
|
||||
|
@ -518,32 +442,15 @@ sanitize_display_mode(display_mode& mode)
|
|||
gInfo->shared_info->pll_info.min_frequency,
|
||||
gInfo->shared_info->pll_info.max_frequency,
|
||||
// horizontal
|
||||
{1, 0, 8160, 32, 8192, 0, 8192},
|
||||
{pixelCount, 0, 8160, 32, 8192, 0, 8192},
|
||||
{1, 1, 4092, 2, 63, 1, 4096}
|
||||
};
|
||||
|
||||
if (olderCard)
|
||||
constraints.horizontal_timing.resolution = 2;
|
||||
|
||||
return sanitize_display_mode(mode, constraints,
|
||||
gInfo->has_edid ? &gInfo->edid_info : NULL);
|
||||
}
|
||||
|
||||
|
||||
static bool
|
||||
check_and_sanitize_display_mode(display_mode* mode)
|
||||
{
|
||||
uint16 width = mode->timing.h_display;
|
||||
uint16 height = mode->timing.v_display;
|
||||
|
||||
// Only accept the mode if it is within the supported resolution
|
||||
// TODO: sanitize_display_mode() should report resolution changes
|
||||
// differently!
|
||||
return !sanitize_display_mode(*mode) || (width == mode->timing.h_display
|
||||
&& height == mode->timing.v_display);
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark -
|
||||
|
||||
|
||||
|
@ -555,12 +462,12 @@ set_frame_buffer_base()
|
|||
uint32 baseRegister;
|
||||
uint32 surfaceRegister;
|
||||
|
||||
if (gInfo->head_mode & HEAD_MODE_B_DIGITAL) {
|
||||
baseRegister = INTEL_DISPLAY_B_BASE;
|
||||
surfaceRegister = INTEL_DISPLAY_B_SURFACE;
|
||||
} else {
|
||||
if (gInfo->head_mode & HEAD_MODE_A_ANALOG) {
|
||||
baseRegister = INTEL_DISPLAY_A_BASE;
|
||||
surfaceRegister = INTEL_DISPLAY_A_SURFACE;
|
||||
} else {
|
||||
baseRegister = INTEL_DISPLAY_B_BASE;
|
||||
surfaceRegister = INTEL_DISPLAY_B_SURFACE;
|
||||
}
|
||||
|
||||
if (sharedInfo.device_type.InGroup(INTEL_TYPE_96x)
|
||||
|
@ -568,7 +475,7 @@ set_frame_buffer_base()
|
|||
|| sharedInfo.device_type.InGroup(INTEL_TYPE_ILK)
|
||||
|| sharedInfo.device_type.InGroup(INTEL_TYPE_SNB)
|
||||
|| sharedInfo.device_type.InGroup(INTEL_TYPE_IVB)
|
||||
|| sharedInfo.device_type.InGroup(INTEL_TYPE_VLV)) {
|
||||
|| gInfo->shared_info->device_type.InGroup(INTEL_TYPE_VLV)) {
|
||||
write32(baseRegister, mode.v_display_start * sharedInfo.bytes_per_row
|
||||
+ mode.h_display_start * (sharedInfo.bits_per_pixel + 7) / 8);
|
||||
read32(baseRegister);
|
||||
|
@ -589,53 +496,21 @@ set_frame_buffer_base()
|
|||
status_t
|
||||
create_mode_list(void)
|
||||
{
|
||||
// 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*)(uintptr_t)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)
|
||||
for (uint32 i = 0; i < gInfo->port_count; i++) {
|
||||
if (gInfo->ports[i] == NULL)
|
||||
continue;
|
||||
|
||||
TRACE("found edid data on gpio '%s'\n", gpioPinMap[i].name);
|
||||
|
||||
edid_dump(&gInfo->edid_info);
|
||||
gInfo->has_edid = true;
|
||||
if (gInfo->shared_info->single_head_locked)
|
||||
gInfo->head_mode = HEAD_MODE_A_ANALOG;
|
||||
|
||||
// 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;
|
||||
status_t status = gInfo->ports[i]->GetEDID(&gInfo->edid_info);
|
||||
if (status == B_OK)
|
||||
gInfo->has_edid = true;
|
||||
}
|
||||
|
||||
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)) {
|
||||
if ((gInfo->head_mode & HEAD_MODE_LVDS_PANEL) != 0
|
||||
&& (gInfo->head_mode & HEAD_MODE_A_ANALOG) == 0) {
|
||||
size_t size = (sizeof(display_mode) + B_PAGE_SIZE - 1)
|
||||
& ~(B_PAGE_SIZE - 1);
|
||||
|
||||
|
@ -643,27 +518,10 @@ create_mode_list(void)
|
|||
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)
|
||||
if (area < 0)
|
||||
return area;
|
||||
|
||||
// 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));
|
||||
|
||||
if (gInfo->shared_info->got_vbt)
|
||||
TRACE("intel_extreme: ignoring VBT mode.");
|
||||
}
|
||||
memcpy(list, &gInfo->lvds_panel_mode, sizeof(display_mode));
|
||||
|
||||
gInfo->mode_list_area = area;
|
||||
gInfo->mode_list = list;
|
||||
|
@ -677,8 +535,8 @@ create_mode_list(void)
|
|||
display_mode* list;
|
||||
uint32 count = 0;
|
||||
gInfo->mode_list_area = create_display_modes("intel extreme modes",
|
||||
gInfo->has_edid ? &gInfo->edid_info : NULL, NULL, 0, NULL, 0,
|
||||
&check_and_sanitize_display_mode, &list, &count);
|
||||
gInfo->has_edid ? &gInfo->edid_info : NULL, NULL, 0, NULL, 0, NULL,
|
||||
&list, &count);
|
||||
if (gInfo->mode_list_area < B_OK)
|
||||
return gInfo->mode_list_area;
|
||||
|
||||
|
@ -747,7 +605,7 @@ intel_propose_display_mode(display_mode* target, const display_mode* low,
|
|||
|
||||
// first search for the specified mode in the list, if no mode is found
|
||||
// try to fix the target mode in sanitize_display_mode
|
||||
// TODO: Only sanitize_display_mode should be used. However, at the moment
|
||||
// TODO: Only sanitize_display_mode should be used. However, at the moments
|
||||
// the mode constraints are not optimal and do not work for all
|
||||
// configurations.
|
||||
for (uint32 i = 0; i < gInfo->shared_info->mode_count; i++) {
|
||||
|
@ -774,12 +632,12 @@ intel_propose_display_mode(display_mode* target, const display_mode* low,
|
|||
status_t
|
||||
intel_set_display_mode(display_mode* mode)
|
||||
{
|
||||
if (mode == NULL)
|
||||
return B_BAD_VALUE;
|
||||
|
||||
TRACE("%s(%" B_PRIu16 "x%" B_PRIu16 ")\n", __func__,
|
||||
mode->virtual_width, mode->virtual_height);
|
||||
|
||||
if (mode == NULL)
|
||||
return B_BAD_VALUE;
|
||||
|
||||
display_mode target = *mode;
|
||||
|
||||
// TODO: it may be acceptable to continue when using panel fitting or
|
||||
|
@ -793,9 +651,9 @@ intel_set_display_mode(display_mode* mode)
|
|||
uint32 colorMode, bytesPerRow, bitsPerPixel;
|
||||
get_color_space_format(target, colorMode, bytesPerRow, bitsPerPixel);
|
||||
|
||||
// TODO stop here, when the requested mode is the same as the current one.
|
||||
// This would avoid screen flickering when setting a mode that's already in
|
||||
// place.
|
||||
// TODO: do not go further if the mode is identical to the current one.
|
||||
// This would avoid the screen being off when switching workspaces when they
|
||||
// have the same resolution.
|
||||
|
||||
#if 0
|
||||
static bool first = true;
|
||||
|
@ -847,6 +705,86 @@ if (first) {
|
|||
sharedInfo.frame_buffer = base;
|
||||
sharedInfo.frame_buffer_offset = base - (addr_t)sharedInfo.graphics_memory;
|
||||
|
||||
#if 0
|
||||
if ((gInfo->head_mode & HEAD_MODE_TESTING) != 0) {
|
||||
// 1. Enable panel power as needed to retrieve panel configuration
|
||||
// (use AUX VDD enable bit)
|
||||
// skip, did detection already, might need that before that though
|
||||
|
||||
// 2. Enable PCH clock reference source and PCH SSC modulator,
|
||||
// wait for warmup (Can be done anytime before enabling port)
|
||||
// skip, most certainly already set up by bios to use other ports,
|
||||
// will need for coldstart though
|
||||
|
||||
// 3. If enabling CPU embedded DisplayPort A: (Can be done anytime
|
||||
// before enabling CPU pipe or port)
|
||||
// a. Enable PCH 120MHz clock source output to CPU, wait for DMI
|
||||
// latency
|
||||
// b. Configure and enable CPU DisplayPort PLL in the DisplayPort A
|
||||
// register, wait for warmup
|
||||
// skip, not doing eDP right now, should go into
|
||||
// EmbeddedDisplayPort class though
|
||||
|
||||
// 4. If enabling port on PCH: (Must be done before enabling CPU pipe
|
||||
// or FDI)
|
||||
// a. Enable PCH FDI Receiver PLL, wait for warmup plus DMI latency
|
||||
// b. Switch from Rawclk to PCDclk in FDI Receiver (FDI A OR FDI B)
|
||||
// c. [DevSNB] Enable CPU FDI Transmitter PLL, wait for warmup
|
||||
// d. [DevILK] CPU FDI PLL is always on and does not need to be
|
||||
// enabled
|
||||
FDILink* link = pipe->FDILink();
|
||||
if (link != NULL) {
|
||||
link->Receiver().EnablePLL();
|
||||
link->Receiver().SwitchClock(true);
|
||||
link->Transmitter().EnablePLL();
|
||||
}
|
||||
|
||||
// 5. Enable CPU panel fitter if needed for hires, required for VGA
|
||||
// (Can be done anytime before enabling CPU pipe)
|
||||
PanelFitter* fitter = pipe->PanelFitter();
|
||||
if (fitter != NULL)
|
||||
fitter->Enable(mode);
|
||||
|
||||
// 6. Configure CPU pipe timings, M/N/TU, and other pipe settings
|
||||
// (Can be done anytime before enabling CPU pipe)
|
||||
pll_divisors divisors;
|
||||
compute_pll_divisors(target, divisors, false);
|
||||
pipe->ConfigureTimings(divisors);
|
||||
|
||||
// 7. Enable CPU pipe
|
||||
pipe->Enable();
|
||||
|
||||
8. Configure and enable CPU planes (VGA or hires)
|
||||
9. If enabling port on PCH:
|
||||
// a. Program PCH FDI Receiver TU size same as Transmitter TU size for TU error checking
|
||||
// b. Train FDI
|
||||
// i. Set pre-emphasis and voltage (iterate if training steps fail)
|
||||
ii. Enable CPU FDI Transmitter and PCH FDI Receiver with Training Pattern 1 enabled.
|
||||
iii. Wait for FDI training pattern 1 time
|
||||
iv. Read PCH FDI Receiver ISR ([DevIBX-B+] IIR) for bit lock in bit 8 (retry at least once if no lock)
|
||||
v. Enable training pattern 2 on CPU FDI Transmitter and PCH FDI Receiver
|
||||
vi. Wait for FDI training pattern 2 time
|
||||
vii. Read PCH FDI Receiver ISR ([DevIBX-B+] IIR) for symbol lock in bit 9 (retry at least once if no
|
||||
lock)
|
||||
viii. Enable normal pixel output on CPU FDI Transmitter and PCH FDI Receiver
|
||||
ix. Wait for FDI idle pattern time for link to become active
|
||||
c. Configure and enable PCH DPLL, wait for PCH DPLL warmup (Can be done anytime before enabling
|
||||
PCH transcoder)
|
||||
d. [DevCPT] Configure DPLL SEL to set the DPLL to transcoder mapping and enable DPLL to the
|
||||
transcoder.
|
||||
e. [DevCPT] Configure DPLL_CTL DPLL_HDMI_multipler.
|
||||
f. Configure PCH transcoder timings, M/N/TU, and other transcoder settings (should match CPU settings).
|
||||
g. [DevCPT] Configure and enable Transcoder DisplayPort Control if DisplayPort will be used
|
||||
h. Enable PCH transcoder
|
||||
10. Enable ports (DisplayPort must enable in training pattern 1)
|
||||
11. Enable panel power through panel power sequencing
|
||||
12. Wait for panel power sequencing to reach enabled steady state
|
||||
13. Disable panel power override
|
||||
14. If DisplayPort, complete link training
|
||||
15. Enable panel backlight
|
||||
}
|
||||
#endif
|
||||
|
||||
// make sure VGA display is disabled
|
||||
write32(INTEL_VGA_DISPLAY_CONTROL, VGA_DISPLAY_DISABLED);
|
||||
read32(INTEL_VGA_DISPLAY_CONTROL);
|
||||
|
@ -941,7 +879,7 @@ if (first) {
|
|||
spin(150);
|
||||
}
|
||||
|
||||
uint32 lvds = read32(INTEL_DISPLAY_LVDS_PORT) | LVDS_PORT_EN
|
||||
uint32 lvds = read32(INTEL_DIGITAL_LVDS_PORT) | LVDS_PORT_EN
|
||||
| LVDS_A0A2_CLKA_POWER_UP | LVDS_PIPEB_SELECT;
|
||||
|
||||
lvds |= LVDS_18BIT_DITHER;
|
||||
|
@ -958,8 +896,8 @@ if (first) {
|
|||
else
|
||||
lvds &= ~(LVDS_B0B3PAIRS_POWER_UP | LVDS_CLKB_POWER_UP);
|
||||
|
||||
write32(INTEL_DISPLAY_LVDS_PORT, lvds);
|
||||
read32(INTEL_DISPLAY_LVDS_PORT);
|
||||
write32(INTEL_DIGITAL_LVDS_PORT, lvds);
|
||||
read32(INTEL_DIGITAL_LVDS_PORT);
|
||||
|
||||
if (gInfo->shared_info->device_type.InGroup(INTEL_TYPE_IGD)) {
|
||||
write32(INTEL_DISPLAY_B_PLL_DIVISOR_0,
|
||||
|
@ -1094,10 +1032,98 @@ if (first) {
|
|||
| colorMode);
|
||||
|
||||
write32(INTEL_DISPLAY_B_PIPE_CONTROL,
|
||||
read32(INTEL_DISPLAY_B_PIPE_CONTROL) | DISPLAY_PIPE_ENABLED);
|
||||
read32(INTEL_DISPLAY_B_PIPE_CONTROL) | INTEL_PIPE_ENABLED);
|
||||
read32(INTEL_DISPLAY_B_PIPE_CONTROL);
|
||||
}
|
||||
|
||||
if ((gInfo->head_mode & HEAD_MODE_STIPPI) != 0) {
|
||||
pll_divisors divisors;
|
||||
compute_pll_divisors(target, divisors, false);
|
||||
|
||||
if (gInfo->shared_info->device_type.InGroup(INTEL_TYPE_IGD)) {
|
||||
write32(INTEL_DISPLAY_B_PLL_DIVISOR_0,
|
||||
(((1 << divisors.n) << DISPLAY_PLL_N_DIVISOR_SHIFT)
|
||||
& DISPLAY_PLL_IGD_N_DIVISOR_MASK)
|
||||
| (((divisors.m2 - 2) << DISPLAY_PLL_M2_DIVISOR_SHIFT)
|
||||
& DISPLAY_PLL_IGD_M2_DIVISOR_MASK));
|
||||
} else {
|
||||
write32(INTEL_DISPLAY_B_PLL_DIVISOR_0,
|
||||
(((divisors.n - 2) << DISPLAY_PLL_N_DIVISOR_SHIFT)
|
||||
& DISPLAY_PLL_N_DIVISOR_MASK)
|
||||
| (((divisors.m1 - 2) << DISPLAY_PLL_M1_DIVISOR_SHIFT)
|
||||
& DISPLAY_PLL_M1_DIVISOR_MASK)
|
||||
| (((divisors.m2 - 2) << DISPLAY_PLL_M2_DIVISOR_SHIFT)
|
||||
& DISPLAY_PLL_M2_DIVISOR_MASK));
|
||||
}
|
||||
|
||||
uint32 pll = DISPLAY_PLL_ENABLED | DISPLAY_PLL_NO_VGA_CONTROL;
|
||||
if (gInfo->shared_info->device_type.InFamily(INTEL_TYPE_9xx)) {
|
||||
if (gInfo->shared_info->device_type.InGroup(INTEL_TYPE_IGD)) {
|
||||
pll |= ((1 << (divisors.post1 - 1))
|
||||
<< DISPLAY_PLL_IGD_POST1_DIVISOR_SHIFT)
|
||||
& DISPLAY_PLL_IGD_POST1_DIVISOR_MASK;
|
||||
} else {
|
||||
pll |= ((1 << (divisors.post1 - 1))
|
||||
<< DISPLAY_PLL_POST1_DIVISOR_SHIFT)
|
||||
& DISPLAY_PLL_9xx_POST1_DIVISOR_MASK;
|
||||
// pll |= ((divisors.post1 - 1) << DISPLAY_PLL_POST1_DIVISOR_SHIFT)
|
||||
// & DISPLAY_PLL_9xx_POST1_DIVISOR_MASK;
|
||||
}
|
||||
if (divisors.post2_high)
|
||||
pll |= DISPLAY_PLL_DIVIDE_HIGH;
|
||||
|
||||
if (gInfo->shared_info->device_type.InGroup(INTEL_TYPE_96x))
|
||||
pll |= 6 << DISPLAY_PLL_PULSE_PHASE_SHIFT;
|
||||
} else {
|
||||
if (!divisors.post2_high)
|
||||
pll |= DISPLAY_PLL_DIVIDE_4X;
|
||||
|
||||
pll |= DISPLAY_PLL_2X_CLOCK;
|
||||
|
||||
if (divisors.post1 > 2) {
|
||||
pll |= ((divisors.post1 - 2) << DISPLAY_PLL_POST1_DIVISOR_SHIFT)
|
||||
& DISPLAY_PLL_POST1_DIVISOR_MASK;
|
||||
} else
|
||||
pll |= DISPLAY_PLL_POST1_DIVIDE_2;
|
||||
}
|
||||
|
||||
write32(INTEL_DISPLAY_B_PLL, pll);
|
||||
read32(INTEL_DISPLAY_B_PLL);
|
||||
spin(150);
|
||||
write32(INTEL_DISPLAY_B_PLL, pll);
|
||||
read32(INTEL_DISPLAY_B_PLL);
|
||||
spin(150);
|
||||
|
||||
// update timing parameters
|
||||
write32(INTEL_DISPLAY_B_HTOTAL,
|
||||
((uint32)(target.timing.h_total - 1) << 16)
|
||||
| ((uint32)target.timing.h_display - 1));
|
||||
write32(INTEL_DISPLAY_B_HBLANK,
|
||||
((uint32)(target.timing.h_total - 1) << 16)
|
||||
| ((uint32)target.timing.h_display - 1));
|
||||
write32(INTEL_DISPLAY_B_HSYNC,
|
||||
((uint32)(target.timing.h_sync_end - 1) << 16)
|
||||
| ((uint32)target.timing.h_sync_start - 1));
|
||||
|
||||
write32(INTEL_DISPLAY_B_VTOTAL,
|
||||
((uint32)(target.timing.v_total - 1) << 16)
|
||||
| ((uint32)target.timing.v_display - 1));
|
||||
write32(INTEL_DISPLAY_B_VBLANK,
|
||||
((uint32)(target.timing.v_total - 1) << 16)
|
||||
| ((uint32)target.timing.v_display - 1));
|
||||
write32(INTEL_DISPLAY_B_VSYNC,
|
||||
((uint32)(target.timing.v_sync_end - 1) << 16)
|
||||
| ((uint32)target.timing.v_sync_start - 1));
|
||||
|
||||
write32(INTEL_DISPLAY_B_IMAGE_SIZE,
|
||||
((uint32)(target.virtual_width - 1) << 16)
|
||||
| ((uint32)target.virtual_height - 1));
|
||||
|
||||
write32(INTEL_DISPLAY_B_CONTROL, (read32(INTEL_DISPLAY_B_CONTROL)
|
||||
& ~(DISPLAY_CONTROL_COLOR_MASK | DISPLAY_CONTROL_GAMMA))
|
||||
| colorMode);
|
||||
}
|
||||
|
||||
if ((gInfo->head_mode & HEAD_MODE_A_ANALOG) != 0) {
|
||||
pll_divisors divisors;
|
||||
compute_pll_divisors(target, divisors, false);
|
||||
|
@ -1151,9 +1177,7 @@ if (first) {
|
|||
pll |= DISPLAY_PLL_POST1_DIVIDE_2;
|
||||
}
|
||||
|
||||
// Programmer's Ref says we must allow the DPLL to "warm up" before starting the plane
|
||||
// so mask its bit, wait, enable its bit
|
||||
write32(INTEL_DISPLAY_A_PLL, pll & ~DISPLAY_PLL_NO_VGA_CONTROL);
|
||||
write32(INTEL_DISPLAY_A_PLL, pll);
|
||||
read32(INTEL_DISPLAY_A_PLL);
|
||||
spin(150);
|
||||
write32(INTEL_DISPLAY_A_PLL, pll);
|
||||
|
@ -1185,8 +1209,7 @@ if (first) {
|
|||
((uint32)(target.virtual_width - 1) << 16)
|
||||
| ((uint32)target.virtual_height - 1));
|
||||
|
||||
write32(INTEL_DISPLAY_A_ANALOG_PORT,
|
||||
(read32(INTEL_DISPLAY_A_ANALOG_PORT)
|
||||
write32(INTEL_ANALOG_PORT, (read32(INTEL_ANALOG_PORT)
|
||||
& ~(DISPLAY_MONITOR_POLARITY_MASK
|
||||
| DISPLAY_MONITOR_VGA_POLARITY))
|
||||
| ((target.timing.flags & B_POSITIVE_HSYNC) != 0
|
||||
|
@ -1215,18 +1238,20 @@ if (first) {
|
|||
}
|
||||
}
|
||||
|
||||
set_display_power_mode(sharedInfo.dpms_mode);
|
||||
if ((gInfo->head_mode & HEAD_MODE_TESTING) == 0) {
|
||||
set_display_power_mode(sharedInfo.dpms_mode);
|
||||
|
||||
// Changing bytes per row seems to be ignored if the plane/pipe is turned
|
||||
// off
|
||||
// Changing bytes per row seems to be ignored if the plane/pipe is turned
|
||||
// off
|
||||
|
||||
if (gInfo->head_mode & HEAD_MODE_A_ANALOG)
|
||||
write32(INTEL_DISPLAY_A_BYTES_PER_ROW, bytesPerRow);
|
||||
if (gInfo->head_mode & HEAD_MODE_B_DIGITAL)
|
||||
write32(INTEL_DISPLAY_B_BYTES_PER_ROW, bytesPerRow);
|
||||
if (gInfo->head_mode & HEAD_MODE_A_ANALOG)
|
||||
write32(INTEL_DISPLAY_A_BYTES_PER_ROW, bytesPerRow);
|
||||
if (gInfo->head_mode & HEAD_MODE_B_DIGITAL)
|
||||
write32(INTEL_DISPLAY_B_BYTES_PER_ROW, bytesPerRow);
|
||||
|
||||
set_frame_buffer_base();
|
||||
// triggers writing back double-buffered registers
|
||||
set_frame_buffer_base();
|
||||
// triggers writing back double-buffered registers
|
||||
}
|
||||
|
||||
// update shared info
|
||||
sharedInfo.bytes_per_row = bytesPerRow;
|
||||
|
|
|
@ -47,6 +47,7 @@
|
|||
(*((volatile uint32*)(address)))
|
||||
|
||||
|
||||
// PCI "Host bridge" is most cases :-)
|
||||
const struct supported_device {
|
||||
uint32 bridge_id;
|
||||
uint32 display_id;
|
||||
|
@ -112,6 +113,7 @@ const struct supported_device {
|
|||
{0x0c00, 0x0412, INTEL_TYPE_IVBG, "Haswell Desktop"},
|
||||
{0x0c04, 0x0416, INTEL_TYPE_IVBGM, "Haswell Mobile"},
|
||||
{0x0d04, 0x0d26, INTEL_TYPE_IVBGM, "Haswell Mobile"},
|
||||
{0x0a04, 0x0a16, INTEL_TYPE_IVBGM, "Haswell Mobile"},
|
||||
|
||||
// XXX: 0x0f00 only confirmed on 0x0f30, 0x0f31
|
||||
{0x0f00, 0x0155, INTEL_TYPE_VLVG, "ValleyView Desktop"},
|
||||
|
@ -374,6 +376,19 @@ determine_memory_sizes(intel_info &info, size_t >tSize, size_t &stolenSize)
|
|||
static void
|
||||
set_gtt_entry(intel_info &info, uint32 offset, phys_addr_t physicalAddress)
|
||||
{
|
||||
if ((info.type & INTEL_TYPE_GROUP_MASK) == INTEL_TYPE_96x
|
||||
|| (info.type & INTEL_TYPE_GROUP_MASK) == INTEL_TYPE_Gxx
|
||||
|| (info.type & INTEL_TYPE_GROUP_MASK) == INTEL_TYPE_G4x
|
||||
|| (info.type & INTEL_TYPE_GROUP_MASK) == INTEL_TYPE_IGD
|
||||
|| (info.type & INTEL_TYPE_GROUP_MASK) == INTEL_TYPE_ILK
|
||||
|| (info.type & INTEL_TYPE_GROUP_MASK) == INTEL_TYPE_VLV) {
|
||||
// possible high bits are stored in the lower end
|
||||
physicalAddress |= (physicalAddress >> 28) & 0x00f0;
|
||||
} else if ((info.type & INTEL_TYPE_GROUP_MASK) == INTEL_TYPE_SNB) {
|
||||
physicalAddress |= (physicalAddress >> 28) & 0x0ff0;
|
||||
physicalAddress |= 0x02; // cache control, l3 cacheable
|
||||
}
|
||||
|
||||
// TODO: this is not 64-bit safe!
|
||||
write32(info.gtt_base + (offset >> GTT_PAGE_SHIFT),
|
||||
(uint32)physicalAddress | GTT_ENTRY_VALID);
|
||||
|
|
|
@ -100,6 +100,7 @@ const struct supported_device {
|
|||
{0x0412, INTEL_TYPE_IVBG, "Haswell Desktop"},
|
||||
{0x0416, INTEL_TYPE_IVBGM, "Haswell Mobile"},
|
||||
{0x0d26, INTEL_TYPE_IVBGM, "Haswell Mobile"},
|
||||
{0x0a16, INTEL_TYPE_IVBGM, "Haswell Mobile"},
|
||||
|
||||
{0x0155, INTEL_TYPE_VLVG, "ValleyView Desktop"},
|
||||
{0x0f30, INTEL_TYPE_VLVGM, "ValleyView Mobile"},
|
||||
|
|
Loading…
Reference in New Issue