* Rework how registers are accessed. Most registers are now grouped into

register blocks and we encode their block into the register definition. On
  register access these blocks are then translated into the final address.
* Set up the register blocks for (G)MCH and PCH variants.
* Remove most SandyBridge code that was actually PCH specific and is now taken
  care of automatically.
* This will temporarily break SandyBridge support again until the right
  transcoders are actually programmed.


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@42857 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Michael Lotz
2011-10-15 15:35:35 +00:00
parent 16cc59778b
commit f0468be384
9 changed files with 345 additions and 339 deletions
@@ -123,7 +123,7 @@ init_common(int device, bool isClone)
AreaCloner regsCloner;
gInfo->regs_area = regsCloner.Clone("intel extreme regs",
(void **)&gInfo->regs, B_ANY_ADDRESS, B_READ_AREA | B_WRITE_AREA,
(void **)&gInfo->registers, B_ANY_ADDRESS, B_READ_AREA | B_WRITE_AREA,
gInfo->shared_info->registers_area);
status = regsCloner.InitCheck();
if (status < B_OK) {
@@ -203,14 +203,13 @@ intel_init_accelerant(int device)
if (read32(INTEL_DISPLAY_A_PIPE_CONTROL) & DISPLAY_PIPE_ENABLED)
gInfo->head_mode |= HEAD_MODE_A_ANALOG;
bool isSNB = gInfo->shared_info->device_type.InGroup(INTEL_TYPE_SNB);
int lvdsRegister = isSNB ? PCH_DISPLAY_LVDS_PORT : INTEL_DISPLAY_LVDS_PORT;
uint32 lvds = read32(lvdsRegister);
uint32 lvds = read32(INTEL_DISPLAY_LVDS_PORT);
// 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 isSNB = gInfo->shared_info->device_type.InGroup(INTEL_TYPE_SNB);
if ((isSNB && (lvds & PCH_LVDS_DETECTED) != 0)
|| (!isSNB && (lvds & DISPLAY_PIPE_ENABLED) != 0)) {
save_lvds_mode();
@@ -219,11 +218,9 @@ intel_init_accelerant(int device)
TRACE(("head detected: %#x\n", gInfo->head_mode));
TRACE(("adpa: %08lx, dova: %08lx, dovb: %08lx, lvds: %08lx\n",
read32(isSNB ? PCH_DISPLAY_A_ANALOG_PORT : INTEL_DISPLAY_A_ANALOG_PORT),
read32(isSNB ? PCH_DISPLAY_A_DIGITAL_PORT
: INTEL_DISPLAY_A_DIGITAL_PORT),
read32(isSNB ? PCH_DISPLAY_B_DIGITAL_PORT
: INTEL_DISPLAY_B_DIGITAL_PORT), read32(lvdsRegister)));
read32(INTEL_DISPLAY_A_ANALOG_PORT),
read32(INTEL_DISPLAY_A_DIGITAL_PORT),
read32(INTEL_DISPLAY_B_DIGITAL_PORT), read32(INTEL_DISPLAY_LVDS_PORT)));
status = create_mode_list();
if (status != B_OK) {
@@ -31,7 +31,7 @@ struct overlay_frame {
};
struct accelerant_info {
vuint8 *regs;
uint8 *registers;
area_id regs_area;
intel_shared_info *shared_info;
@@ -74,15 +74,19 @@ extern accelerant_info *gInfo;
// register access
inline uint32
read32(uint32 offset)
read32(uint32 encodedRegister)
{
return *(volatile uint32 *)(gInfo->regs + offset);
return *(volatile uint32 *)(gInfo->registers
+ gInfo->shared_info->register_blocks[REGISTER_BLOCK(encodedRegister)]
+ REGISTER_REGISTER(encodedRegister));
}
inline void
write32(uint32 offset, uint32 value)
write32(uint32 encodedRegister, uint32 value)
{
*(volatile uint32 *)(gInfo->regs + offset) = value;
*(volatile uint32 *)(gInfo->registers
+ gInfo->shared_info->register_blocks[REGISTER_BLOCK(encodedRegister)]
+ REGISTER_REGISTER(encodedRegister)) = value;
}
+30 -33
View File
@@ -75,6 +75,11 @@ static void
enable_lvds_panel(bool enable)
{
bool isSNB = gInfo->shared_info->device_type.InGroup(INTEL_TYPE_SNB);
if (isSNB) {
// TODO: fix for SNB
return;
}
int controlRegister = isSNB ? PCH_PANEL_CONTROL : INTEL_PANEL_CONTROL;
int statusRegister = isSNB ? PCH_PANEL_STATUS : INTEL_PANEL_STATUS;
@@ -108,35 +113,32 @@ set_display_power_mode(uint32 mode)
{
uint32 monitorMode = 0;
bool isSNB = gInfo->shared_info->device_type.InGroup(INTEL_TYPE_SNB);
if (mode == B_DPMS_ON) {
int targetRegister = isSNB ? PCH_DISPLAY_A_PLL : INTEL_DISPLAY_A_PLL;
uint32 pll = read32(targetRegister);
uint32 pll = read32(INTEL_DISPLAY_A_PLL);
if ((pll & DISPLAY_PLL_ENABLED) == 0) {
// reactivate PLL
write32(targetRegister, pll);
read32(targetRegister);
write32(INTEL_DISPLAY_A_PLL, pll);
read32(INTEL_DISPLAY_A_PLL);
spin(150);
write32(targetRegister, pll | DISPLAY_PLL_ENABLED);
read32(targetRegister);
write32(INTEL_DISPLAY_A_PLL, pll | DISPLAY_PLL_ENABLED);
read32(INTEL_DISPLAY_A_PLL);
spin(150);
write32(targetRegister, pll | DISPLAY_PLL_ENABLED);
read32(targetRegister);
write32(INTEL_DISPLAY_A_PLL, pll | DISPLAY_PLL_ENABLED);
read32(INTEL_DISPLAY_A_PLL);
spin(150);
}
targetRegister = isSNB ? PCH_DISPLAY_B_PLL : INTEL_DISPLAY_B_PLL;
pll = read32(targetRegister);
pll = read32(INTEL_DISPLAY_B_PLL);
if ((pll & DISPLAY_PLL_ENABLED) == 0) {
// reactivate PLL
write32(targetRegister, pll);
read32(targetRegister);
write32(INTEL_DISPLAY_B_PLL, pll);
read32(INTEL_DISPLAY_B_PLL);
spin(150);
write32(targetRegister, pll | DISPLAY_PLL_ENABLED);
read32(targetRegister);
write32(INTEL_DISPLAY_B_PLL, pll | DISPLAY_PLL_ENABLED);
read32(INTEL_DISPLAY_B_PLL);
spin(150);
write32(targetRegister, pll | DISPLAY_PLL_ENABLED);
read32(targetRegister);
write32(INTEL_DISPLAY_B_PLL, pll | DISPLAY_PLL_ENABLED);
read32(INTEL_DISPLAY_B_PLL);
spin(150);
}
@@ -162,17 +164,15 @@ set_display_power_mode(uint32 mode)
}
if (gInfo->head_mode & HEAD_MODE_A_ANALOG) {
int targetRegister
= isSNB ? PCH_DISPLAY_A_ANALOG_PORT : INTEL_DISPLAY_A_ANALOG_PORT;
write32(targetRegister, (read32(targetRegister)
& ~(DISPLAY_MONITOR_MODE_MASK | DISPLAY_MONITOR_PORT_ENABLED))
write32(INTEL_DISPLAY_A_ANALOG_PORT,
(read32(INTEL_DISPLAY_A_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) {
int targetRegister
= isSNB ? PCH_DISPLAY_B_DIGITAL_PORT : INTEL_DISPLAY_B_DIGITAL_PORT;
write32(targetRegister, (read32(targetRegister)
& ~(DISPLAY_MONITOR_MODE_MASK | DISPLAY_MONITOR_PORT_ENABLED))
write32(INTEL_DISPLAY_B_DIGITAL_PORT,
(read32(INTEL_DISPLAY_B_DIGITAL_PORT)
& ~(DISPLAY_MONITOR_MODE_MASK | DISPLAY_MONITOR_PORT_ENABLED))
| (mode != B_DPMS_OFF ? DISPLAY_MONITOR_PORT_ENABLED : 0));
// TODO: monitorMode?
}
@@ -184,25 +184,22 @@ set_display_power_mode(uint32 mode)
}
if (mode == B_DPMS_OFF) {
int targetRegister = isSNB ? PCH_DISPLAY_A_PLL : INTEL_DISPLAY_A_PLL;
write32(targetRegister, read32(targetRegister)
write32(INTEL_DISPLAY_A_PLL, read32(INTEL_DISPLAY_A_PLL)
| DISPLAY_PLL_ENABLED);
targetRegister = isSNB ? PCH_DISPLAY_B_PLL : INTEL_DISPLAY_B_PLL;
write32(targetRegister, read32(targetRegister)
write32(INTEL_DISPLAY_B_PLL, read32(INTEL_DISPLAY_B_PLL)
| DISPLAY_PLL_ENABLED);
read32(targetRegister);
read32(INTEL_DISPLAY_B_PLL);
// flush the possibly cached PCI bus writes
spin(150);
}
// TODO: fix for SNB
if (!isSNB && (gInfo->head_mode & HEAD_MODE_LVDS_PANEL) != 0)
if ((gInfo->head_mode & HEAD_MODE_LVDS_PANEL) != 0)
enable_lvds_panel(mode == B_DPMS_ON);
read32(INTEL_DISPLAY_A_BASE);
// flush the eventually cached PCI bus writes
// flush the possibly cached PCI bus writes
}
+43 -90
View File
@@ -154,10 +154,8 @@ set_frame_buffer_base()
status_t
create_mode_list(void)
{
bool isSNB = gInfo->shared_info->device_type.InGroup(INTEL_TYPE_SNB);
i2c_bus bus;
bus.cookie = (void*)(isSNB ? PCH_I2C_IO_A : INTEL_I2C_IO_A);
bus.cookie = (void*)INTEL_I2C_IO_A;
bus.set_signals = &set_i2c_signals;
bus.get_signals = &get_i2c_signals;
ddc2_init_timing(&bus);
@@ -169,7 +167,7 @@ create_mode_list(void)
} else {
TRACE(("intel_extreme: getting EDID on port A (analog) failed : %s. "
"Trying on port C (lvds)\n", strerror(error)));
bus.cookie = (void*)(isSNB ? PCH_I2C_IO_C : INTEL_I2C_IO_C);
bus.cookie = (void*)INTEL_I2C_IO_C;
error = ddc2_read_edid1(&bus, &gInfo->edid_info, NULL, NULL);
if (error == B_OK) {
edid_dump(&gInfo->edid_info);
@@ -324,12 +322,8 @@ compute_pll_divisors(const display_mode &current, pll_divisors& divisors,
TRACE(("required MHz: %g\n", requestedPixelClock));
bool isSNB = gInfo->shared_info->device_type.InGroup(INTEL_TYPE_SNB);
if (isLVDS) {
int targetRegister
= isSNB ? PCH_DISPLAY_LVDS_PORT : INTEL_DISPLAY_LVDS_PORT;
if ((read32(targetRegister) & LVDS_CLKB_POWER_MASK)
if ((read32(INTEL_DISPLAY_LVDS_PORT) & LVDS_CLKB_POWER_MASK)
== LVDS_CLKB_POWER_UP)
divisors.post2 = LVDS_POST2_RATE_FAST;
else
@@ -418,26 +412,6 @@ retrieve_current_mode(display_mode& mode, uint32 pllRegister)
vSyncRegister = INTEL_DISPLAY_B_VSYNC;
imageSizeRegister = INTEL_DISPLAY_B_IMAGE_SIZE;
controlRegister = INTEL_DISPLAY_B_CONTROL;
} else if (pllRegister == PCH_DISPLAY_A_PLL) {
pllDivisor = read32((pll & DISPLAY_PLL_DIVISOR_1) != 0
? PCH_DISPLAY_A_PLL_DIVISOR_1 : PCH_DISPLAY_A_PLL_DIVISOR_0);
hTotalRegister = PCH_TRANSCODER_A_HTOTAL;
vTotalRegister = PCH_TRANSCODER_A_VTOTAL;
hSyncRegister = PCH_TRANSCODER_A_HSYNC;
vSyncRegister = PCH_TRANSCODER_A_VSYNC;
imageSizeRegister = INTEL_DISPLAY_A_IMAGE_SIZE;
controlRegister = INTEL_DISPLAY_A_CONTROL;
} else if (pllRegister == PCH_DISPLAY_B_PLL) {
pllDivisor = read32((pll & DISPLAY_PLL_DIVISOR_1) != 0
? PCH_DISPLAY_B_PLL_DIVISOR_1 : PCH_DISPLAY_B_PLL_DIVISOR_0);
hTotalRegister = PCH_TRANSCODER_B_HTOTAL;
vTotalRegister = PCH_TRANSCODER_B_VTOTAL;
hSyncRegister = PCH_TRANSCODER_B_HSYNC;
vSyncRegister = PCH_TRANSCODER_B_VSYNC;
imageSizeRegister = INTEL_DISPLAY_B_IMAGE_SIZE;
controlRegister = INTEL_DISPLAY_B_CONTROL;
} else {
// TODO: not supported
return;
@@ -565,12 +539,9 @@ retrieve_current_mode(display_mode& mode, uint32 pllRegister)
void
save_lvds_mode(void)
{
bool isSNB = gInfo->shared_info->device_type.InGroup(INTEL_TYPE_SNB);
// dump currently programmed mode.
display_mode biosMode;
retrieve_current_mode(biosMode,
isSNB ? PCH_DISPLAY_B_PLL : INTEL_DISPLAY_B_PLL);
retrieve_current_mode(biosMode, INTEL_DISPLAY_B_PLL);
gInfo->lvds_panel_mode = biosMode;
}
@@ -749,9 +720,6 @@ if (first) {
write32(INTEL_VGA_DISPLAY_CONTROL, VGA_DISPLAY_DISABLED);
read32(INTEL_VGA_DISPLAY_CONTROL);
bool isSNB = gInfo->shared_info->device_type.InGroup(INTEL_TYPE_SNB);
int targetRegister;
if ((gInfo->head_mode & HEAD_MODE_B_DIGITAL) != 0) {
// For LVDS panels, we actually always set the native mode in hardware
// Then we use the panel fitter to scale the picture to that.
@@ -829,8 +797,7 @@ if (first) {
| (((divisors.m2 - 2) << DISPLAY_PLL_M2_DIVISOR_SHIFT)
& DISPLAY_PLL_IGD_M2_DIVISOR_MASK));
} else {
write32(isSNB ? PCH_DISPLAY_B_PLL_DIVISOR_0
: INTEL_DISPLAY_B_PLL_DIVISOR_0,
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)
@@ -838,15 +805,12 @@ if (first) {
| (((divisors.m2 - 2) << DISPLAY_PLL_M2_DIVISOR_SHIFT)
& DISPLAY_PLL_M2_DIVISOR_MASK));
}
targetRegister = isSNB ? PCH_DISPLAY_B_PLL : INTEL_DISPLAY_B_PLL;
write32(targetRegister, dpll & ~DISPLAY_PLL_ENABLED);
read32(targetRegister);
write32(INTEL_DISPLAY_B_PLL, dpll & ~DISPLAY_PLL_ENABLED);
read32(INTEL_DISPLAY_B_PLL);
spin(150);
}
targetRegister
= isSNB ? PCH_DISPLAY_LVDS_PORT : INTEL_DISPLAY_LVDS_PORT;
uint32 lvds = read32(targetRegister) | LVDS_PORT_EN
uint32 lvds = read32(INTEL_DISPLAY_LVDS_PORT) | LVDS_PORT_EN
| LVDS_A0A2_CLKA_POWER_UP | LVDS_PIPEB_SELECT;
lvds |= LVDS_18BIT_DITHER;
@@ -863,8 +827,8 @@ if (first) {
else
lvds &= ~(LVDS_B0B3PAIRS_POWER_UP | LVDS_CLKB_POWER_UP);
write32(targetRegister, lvds);
read32(targetRegister);
write32(INTEL_DISPLAY_LVDS_PORT, lvds);
read32(INTEL_DISPLAY_LVDS_PORT);
if (gInfo->shared_info->device_type.InGroup(INTEL_TYPE_IGD)) {
write32(INTEL_DISPLAY_B_PLL_DIVISOR_0,
@@ -873,8 +837,7 @@ if (first) {
| (((divisors.m2 - 2) << DISPLAY_PLL_M2_DIVISOR_SHIFT)
& DISPLAY_PLL_IGD_M2_DIVISOR_MASK));
} else {
write32(isSNB ? PCH_DISPLAY_B_PLL_DIVISOR_0
: INTEL_DISPLAY_B_PLL_DIVISOR_0,
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)
@@ -883,9 +846,8 @@ if (first) {
& DISPLAY_PLL_M2_DIVISOR_MASK));
}
targetRegister = isSNB ? PCH_DISPLAY_B_PLL : INTEL_DISPLAY_B_PLL;
write32(targetRegister, dpll);
read32(targetRegister);
write32(INTEL_DISPLAY_B_PLL, dpll);
read32(INTEL_DISPLAY_B_PLL);
// Wait for the clocks to stabilize
spin(150);
@@ -905,9 +867,9 @@ if (first) {
write32(INTEL_DISPLAY_B_PLL_MULTIPLIER_DIVISOR, (0 << 24)
| ((pixelMultiply - 1) << 8));
} else
write32(targetRegister, dpll);
write32(INTEL_DISPLAY_B_PLL, dpll);
read32(targetRegister);
read32(INTEL_DISPLAY_B_PLL);
spin(150);
// update timing parameters
@@ -928,14 +890,14 @@ if (first) {
+ (hardwareTarget.timing.h_total
- target.timing.h_display) / 2;
write32(isSNB ? PCH_TRANSCODER_B_HTOTAL : INTEL_DISPLAY_B_HTOTAL,
write32(INTEL_DISPLAY_B_HTOTAL,
((uint32)(hardwareTarget.timing.h_total - 1) << 16)
| ((uint32)target.timing.h_display - 1));
write32(isSNB ? PCH_TRANSCODER_B_HBLANK : INTEL_DISPLAY_B_HBLANK,
write32(INTEL_DISPLAY_B_HBLANK,
((uint32)(hardwareTarget.timing.h_total - borderWidth / 2 - 1)
<< 16)
| ((uint32)target.timing.h_display + borderWidth / 2 - 1));
write32(isSNB ? PCH_TRANSCODER_B_HSYNC : INTEL_DISPLAY_B_HSYNC,
write32(INTEL_DISPLAY_B_HSYNC,
((uint32)(syncCenter + syncWidth / 2 - 1) << 16)
| ((uint32)syncCenter - syncWidth / 2 - 1));
@@ -949,15 +911,15 @@ if (first) {
+ (hardwareTarget.timing.v_total
- target.timing.v_display) / 2;
write32(isSNB ? PCH_TRANSCODER_B_VTOTAL : INTEL_DISPLAY_B_VTOTAL,
write32(INTEL_DISPLAY_B_VTOTAL,
((uint32)(hardwareTarget.timing.v_total - 1) << 16)
| ((uint32)target.timing.v_display - 1));
write32(isSNB ? PCH_TRANSCODER_B_VBLANK : INTEL_DISPLAY_B_VBLANK,
write32(INTEL_DISPLAY_B_VBLANK,
((uint32)(hardwareTarget.timing.v_total - borderHeight / 2 - 1)
<< 16)
| ((uint32)target.timing.v_display
+ borderHeight / 2 - 1));
write32(isSNB ? PCH_TRANSCODER_B_VSYNC : INTEL_DISPLAY_B_VSYNC,
write32(INTEL_DISPLAY_B_VSYNC,
((uint32)(syncCenter + syncHeight / 2 - 1) << 16)
| ((uint32)syncCenter - syncHeight / 2 - 1));
@@ -966,23 +928,23 @@ if (first) {
// sync)
// write32(0x61020, 0x00FF0000);
} else {
write32(isSNB ? PCH_TRANSCODER_B_HTOTAL : INTEL_DISPLAY_B_HTOTAL,
write32(INTEL_DISPLAY_B_HTOTAL,
((uint32)(target.timing.h_total - 1) << 16)
| ((uint32)target.timing.h_display - 1));
write32(isSNB ? PCH_TRANSCODER_B_HBLANK : INTEL_DISPLAY_B_HBLANK,
write32(INTEL_DISPLAY_B_HBLANK,
((uint32)(target.timing.h_total - 1) << 16)
| ((uint32)target.timing.h_display - 1));
write32(isSNB ? PCH_TRANSCODER_B_HSYNC : INTEL_DISPLAY_B_HSYNC,
write32(INTEL_DISPLAY_B_HSYNC,
((uint32)(target.timing.h_sync_end - 1) << 16)
| ((uint32)target.timing.h_sync_start - 1));
write32(isSNB ? PCH_TRANSCODER_B_VTOTAL : INTEL_DISPLAY_B_VTOTAL,
write32(INTEL_DISPLAY_B_VTOTAL,
((uint32)(target.timing.v_total - 1) << 16)
| ((uint32)target.timing.v_display - 1));
write32(isSNB ? PCH_TRANSCODER_B_VBLANK : INTEL_DISPLAY_B_VBLANK,
write32(INTEL_DISPLAY_B_VBLANK,
((uint32)(target.timing.v_total - 1) << 16)
| ((uint32)target.timing.v_display - 1));
write32(isSNB ? PCH_TRANSCODER_B_VSYNC : INTEL_DISPLAY_B_VSYNC, (
write32(INTEL_DISPLAY_B_VSYNC, (
(uint32)(target.timing.v_sync_end - 1) << 16)
| ((uint32)target.timing.v_sync_start - 1));
}
@@ -1016,8 +978,7 @@ if (first) {
| (((divisors.m2 - 2) << DISPLAY_PLL_M2_DIVISOR_SHIFT)
& DISPLAY_PLL_IGD_M2_DIVISOR_MASK));
} else {
write32(isSNB ? PCH_DISPLAY_A_PLL_DIVISOR_0
: INTEL_DISPLAY_A_PLL_DIVISOR_0,
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)
@@ -1059,32 +1020,31 @@ if (first) {
pll |= DISPLAY_PLL_POST1_DIVIDE_2;
}
targetRegister = isSNB ? PCH_DISPLAY_A_PLL : INTEL_DISPLAY_A_PLL;
write32(targetRegister, pll);
read32(targetRegister);
write32(INTEL_DISPLAY_A_PLL, pll);
read32(INTEL_DISPLAY_A_PLL);
spin(150);
write32(targetRegister, pll);
read32(targetRegister);
write32(INTEL_DISPLAY_A_PLL, pll);
read32(INTEL_DISPLAY_A_PLL);
spin(150);
// update timing parameters
write32(isSNB ? PCH_TRANSCODER_A_HTOTAL : INTEL_DISPLAY_A_HTOTAL,
write32(INTEL_DISPLAY_A_HTOTAL,
((uint32)(target.timing.h_total - 1) << 16)
| ((uint32)target.timing.h_display - 1));
write32(isSNB ? PCH_TRANSCODER_A_HBLANK : INTEL_DISPLAY_A_HBLANK,
write32(INTEL_DISPLAY_A_HBLANK,
((uint32)(target.timing.h_total - 1) << 16)
| ((uint32)target.timing.h_display - 1));
write32(isSNB ? PCH_TRANSCODER_A_HSYNC : INTEL_DISPLAY_A_HSYNC,
write32(INTEL_DISPLAY_A_HSYNC,
((uint32)(target.timing.h_sync_end - 1) << 16)
| ((uint32)target.timing.h_sync_start - 1));
write32(isSNB ? PCH_TRANSCODER_A_VTOTAL : INTEL_DISPLAY_A_VTOTAL,
write32(INTEL_DISPLAY_A_VTOTAL,
((uint32)(target.timing.v_total - 1) << 16)
| ((uint32)target.timing.v_display - 1));
write32(isSNB ? PCH_TRANSCODER_A_VBLANK : INTEL_DISPLAY_A_VBLANK,
write32(INTEL_DISPLAY_A_VBLANK,
((uint32)(target.timing.v_total - 1) << 16)
| ((uint32)target.timing.v_display - 1));
write32(isSNB ? PCH_TRANSCODER_A_VSYNC : INTEL_DISPLAY_A_VSYNC,
write32(INTEL_DISPLAY_A_VSYNC,
((uint32)(target.timing.v_sync_end - 1) << 16)
| ((uint32)target.timing.v_sync_start - 1));
@@ -1092,10 +1052,8 @@ if (first) {
((uint32)(target.virtual_width - 1) << 16)
| ((uint32)target.virtual_height - 1));
targetRegister
= isSNB ? PCH_DISPLAY_A_ANALOG_PORT : INTEL_DISPLAY_A_ANALOG_PORT;
write32(targetRegister,
(read32(targetRegister)
write32(INTEL_DISPLAY_A_ANALOG_PORT,
(read32(INTEL_DISPLAY_A_ANALOG_PORT)
& ~(DISPLAY_MONITOR_POLARITY_MASK
| DISPLAY_MONITOR_VGA_POLARITY))
| ((target.timing.flags & B_POSITIVE_HSYNC) != 0
@@ -1151,9 +1109,7 @@ intel_get_display_mode(display_mode *_currentMode)
{
TRACE(("intel_get_display_mode()\n"));
bool isSNB = gInfo->shared_info->device_type.InGroup(INTEL_TYPE_SNB);
retrieve_current_mode(*_currentMode,
isSNB ? PCH_DISPLAY_A_PLL : INTEL_DISPLAY_A_PLL);
retrieve_current_mode(*_currentMode, INTEL_DISPLAY_A_PLL);
return B_OK;
}
@@ -1259,11 +1215,8 @@ intel_set_indexed_colors(uint count, uint8 first, uint8 *colors, uint32 flags)
uint32 color = colors[0] << 16 | colors[1] << 8 | colors[2];
colors += 3;
bool isSNB = gInfo->shared_info->device_type.InGroup(INTEL_TYPE_SNB);
write32((isSNB ? PCH_DISPLAY_A_PALETTE : INTEL_DISPLAY_A_PALETTE)
+ first * sizeof(uint32), color);
write32((isSNB ? PCH_DISPLAY_B_PALETTE : INTEL_DISPLAY_B_PALETTE)
+ first * sizeof(uint32), color);
write32(INTEL_DISPLAY_A_PALETTE + first * sizeof(uint32), color);
write32(INTEL_DISPLAY_B_PALETTE + first * sizeof(uint32), color);
}
}
@@ -76,14 +76,14 @@ getset_register(int argc, char **argv)
kprintf("intel_extreme register %#lx\n", reg);
intel_info &info = *gDeviceInfo[0];
uint32 oldValue = read32(info.registers + reg);
uint32 oldValue = read32(info, reg);
kprintf(" %svalue: %#lx (%lu)\n", set ? "old " : "", oldValue, oldValue);
if (set) {
write32(info.registers + reg, value);
write32(info, reg, value);
value = read32(info.registers + reg);
value = read32(info, reg);
kprintf(" new value: %#lx (%lu)\n", value, value);
}
@@ -17,16 +17,6 @@
#include "intel_extreme_private.h"
// PCI Communications
#define read8(address) (*((volatile uint8*)(address)))
#define read16(address) (*((volatile uint16*)(address)))
#define read32(address) (*((volatile uint32*)(address)))
#define write8(address, data) (*((volatile uint8*)(address)) = (data))
#define write16(address, data) (*((volatile uint16*)(address)) = (data))
#define write32(address, data) (*((volatile uint32*)(address)) = (data))
extern char* gDeviceNames[];
extern intel_info* gDeviceInfo[];
extern pci_module_info* gPCI;
@@ -49,4 +39,40 @@ set_pci_config(pci_info* info, uint8 offset, uint8 size, uint32 value)
size, value);
}
static inline uint16
read16(intel_info &info, uint32 encodedRegister)
{
return *(volatile uint16 *)(info.registers
+ info.shared_info->register_blocks[REGISTER_BLOCK(encodedRegister)]
+ REGISTER_REGISTER(encodedRegister));
}
static inline uint32
read32(intel_info &info, uint32 encodedRegister)
{
return *(volatile uint32 *)(info.registers
+ info.shared_info->register_blocks[REGISTER_BLOCK(encodedRegister)]
+ REGISTER_REGISTER(encodedRegister));
}
static inline void
write16(intel_info &info, uint32 encodedRegister, uint16 value)
{
*(volatile uint16 *)(info.registers
+ info.shared_info->register_blocks[REGISTER_BLOCK(encodedRegister)]
+ REGISTER_REGISTER(encodedRegister)) = value;
}
static inline void
write32(intel_info &info, uint32 encodedRegister, uint32 value)
{
*(volatile uint32 *)(info.registers
+ info.shared_info->register_blocks[REGISTER_BLOCK(encodedRegister)]
+ REGISTER_REGISTER(encodedRegister)) = value;
}
#endif /* DRIVER_H */
@@ -76,20 +76,20 @@ intel_interrupt_handler(void *data)
{
intel_info &info = *(intel_info *)data;
bool isSNB = info.device_type.InGroup(INTEL_TYPE_SNB);
uint32 identity = read16(info.registers
+ (isSNB ? PCH_DE_INTERRUPT_IDENTITY : INTEL_INTERRUPT_IDENTITY));
uint16 identity = read16(info, INTEL_INTERRUPT_IDENTITY);
if (identity == 0)
return B_UNHANDLED_INTERRUPT;
int32 handled = B_HANDLED_INTERRUPT;
uint32 mask = isSNB ? PCH_INTERRUPT_VBLANK_PIPEA : INTERRUPT_VBLANK_PIPEA;
// TODO: verify that these aren't actually the same
bool isSNB = info.device_type.InGroup(INTEL_TYPE_SNB);
uint16 mask = isSNB ? PCH_INTERRUPT_VBLANK_PIPEA : INTERRUPT_VBLANK_PIPEA;
if ((identity & mask) != 0) {
handled = release_vblank_sem(info);
// make sure we'll get another one of those
write32(info.registers + INTEL_DISPLAY_A_PIPE_STATUS,
write32(info, INTEL_DISPLAY_A_PIPE_STATUS,
DISPLAY_PIPE_VBLANK_STATUS | DISPLAY_PIPE_VBLANK_ENABLED);
}
@@ -98,13 +98,12 @@ intel_interrupt_handler(void *data)
handled = release_vblank_sem(info);
// make sure we'll get another one of those
write32(info.registers + INTEL_DISPLAY_B_PIPE_STATUS,
write32(info, INTEL_DISPLAY_B_PIPE_STATUS,
DISPLAY_PIPE_VBLANK_STATUS | DISPLAY_PIPE_VBLANK_ENABLED);
}
// setting the bit clears it!
write16(info.registers + (isSNB ? PCH_DE_INTERRUPT_IDENTITY
: INTEL_INTERRUPT_IDENTITY), identity);
write16(info, INTEL_INTERRUPT_IDENTITY, identity);
return handled;
}
@@ -138,26 +137,22 @@ init_interrupt_handler(intel_info &info)
status = install_io_interrupt_handler(info.pci->u.h0.interrupt_line,
&intel_interrupt_handler, (void *)&info, 0);
if (status == B_OK) {
write32(info.registers + INTEL_DISPLAY_A_PIPE_STATUS,
write32(info, INTEL_DISPLAY_A_PIPE_STATUS,
DISPLAY_PIPE_VBLANK_STATUS | DISPLAY_PIPE_VBLANK_ENABLED);
write32(info.registers + INTEL_DISPLAY_B_PIPE_STATUS,
write32(info, INTEL_DISPLAY_B_PIPE_STATUS,
DISPLAY_PIPE_VBLANK_STATUS | DISPLAY_PIPE_VBLANK_ENABLED);
bool isSNB = info.device_type.InGroup(INTEL_TYPE_SNB);
write16(info.registers + (isSNB ? PCH_DE_INTERRUPT_IDENTITY
: INTEL_INTERRUPT_IDENTITY), ~0);
write16(info, INTEL_INTERRUPT_IDENTITY, ~0);
// enable interrupts - we only want VBLANK interrupts
bool isSNB = info.device_type.InGroup(INTEL_TYPE_SNB);
uint16 enable = isSNB
? (PCH_INTERRUPT_VBLANK_PIPEA | PCH_INTERRUPT_VBLANK_PIPEB)
: (INTERRUPT_VBLANK_PIPEA | INTERRUPT_VBLANK_PIPEB);
write16(info.registers + (isSNB ? PCH_DE_INTERRUPT_ENABLED
: INTEL_INTERRUPT_ENABLED),
read16(info.registers + (isSNB ? PCH_DE_INTERRUPT_ENABLED
: INTEL_INTERRUPT_ENABLED)) | enable);
write16(info.registers + (isSNB ? PCH_DE_INTERRUPT_MASK
: INTEL_INTERRUPT_MASK), ~enable);
write16(info, INTEL_INTERRUPT_ENABLED,
read16(info, INTEL_INTERRUPT_ENABLED) | enable);
write16(info, INTEL_INTERRUPT_MASK, ~enable);
}
}
if (status < B_OK) {
@@ -248,6 +243,40 @@ intel_extreme_init(intel_info &info)
return info.registers_area;
}
uint32 *blocks = info.shared_info->register_blocks;
blocks[REGISTER_BLOCK(REGS_FLAT)] = 0;
// setup the register blocks for the different architectures
if (info.device_type.InGroup(INTEL_TYPE_SNB)) {
// PCH based platforms (IronLake and up)
blocks[REGISTER_BLOCK(REGS_INTERRUPT)]
= PCH_DE_INTERRUPT_REGISTER_BASE;
blocks[REGISTER_BLOCK(REGS_NORTH_SHARED)]
= PCH_NORTH_SHARED_REGISTER_BASE;
blocks[REGISTER_BLOCK(REGS_NORTH_PIPE_AND_PORT)]
= PCH_NORTH_PIPE_AND_PORT_REGISTER_BASE;
blocks[REGISTER_BLOCK(REGS_NORTH_PLANE_CONTROL)]
= PCH_NORTH_PLANE_CONTROL_REGISTER_BASE;
blocks[REGISTER_BLOCK(REGS_SOUTH_SHARED)]
= PCH_SOUTH_SHARED_REGISTER_BASE;
blocks[REGISTER_BLOCK(REGS_SOUTH_TRANSCODER_PORT)]
= PCH_SOUTH_TRANSCODER_AND_PORT_REGISTER_BASE;
} else {
// (G)MCH/ICH based platforms
blocks[REGISTER_BLOCK(REGS_INTERRUPT)]
= MCH_INTERRUPT_REGISTER_BASE;
blocks[REGISTER_BLOCK(REGS_NORTH_SHARED)]
= MCH_SHARED_REGISTER_BASE;
blocks[REGISTER_BLOCK(REGS_NORTH_PIPE_AND_PORT)]
= MCH_PIPE_AND_PORT_REGISTER_BASE;
blocks[REGISTER_BLOCK(REGS_NORTH_PLANE_CONTROL)]
= MCH_PLANE_CONTROL_REGISTER_BASE;
blocks[REGISTER_BLOCK(REGS_SOUTH_SHARED)]
= ICH_SHARED_REGISTER_BASE;
blocks[REGISTER_BLOCK(REGS_SOUTH_TRANSCODER_PORT)]
= ICH_PORT_REGISTER_BASE;
}
// make sure bus master, memory-mapped I/O, and frame buffer is enabled
set_pci_config(info.pci, PCI_command, 2, get_pci_config(info.pci, PCI_command, 2)
| PCI_command_io | PCI_command_memory | PCI_command_master);
@@ -269,27 +298,27 @@ intel_extreme_init(intel_info &info)
// TODO: clean this up
if (info.pci->device_id == 0x2a02 || info.pci->device_id == 0x2a12) {
dprintf("i965GM/i965GME quirk\n");
write32(info.registers + 0x6204, (1L << 29));
write32(info, 0x6204, (1L << 29));
} else if (info.device_type.InGroup(INTEL_TYPE_SNB)) {
dprintf("SNB clock gating\n");
write32(info.registers + 0x42020, (1L << 28) | (1L << 7) | (1L << 5));
write32(info, 0x42020, (1L << 28) | (1L << 7) | (1L << 5));
} else if (info.device_type.InGroup(INTEL_TYPE_G4x)) {
dprintf("G4x clock gating\n");
write32(info.registers + 0x6204, 0);
write32(info.registers + 0x6208, (1L << 9) | (1L << 7) | (1L << 6));
write32(info.registers + 0x6210, 0);
write32(info, 0x6204, 0);
write32(info, 0x6208, (1L << 9) | (1L << 7) | (1L << 6));
write32(info, 0x6210, 0);
uint32 gateValue = (1L << 28) | (1L << 3) | (1L << 2);
if ((info.device_type.type & INTEL_TYPE_MOBILE) == INTEL_TYPE_MOBILE) {
dprintf("G4x mobile clock gating\n");
gateValue |= 1L << 18;
}
write32(info.registers + 0x6200, gateValue);
write32(info, 0x6200, gateValue);
} else {
dprintf("i965 quirk\n");
write32(info.registers + 0x6204, (1L << 29) | (1L << 23));
write32(info, 0x6204, (1L << 29) | (1L << 23));
}
write32(info.registers + 0x7408, 0x10);
write32(info, 0x7408, 0x10);
// no errors, so keep areas and mappings
sharedCreator.Detach();
@@ -367,11 +396,8 @@ intel_extreme_uninit(intel_info &info)
if (!info.fake_interrupts && info.shared_info->vblank_sem > 0) {
// disable interrupt generation
bool isSNB = info.device_type.InGroup(INTEL_TYPE_SNB);
write16(info.registers + (isSNB ? PCH_DE_INTERRUPT_ENABLED
: INTEL_INTERRUPT_ENABLED), 0);
write16(info.registers + (isSNB ? PCH_DE_INTERRUPT_MASK
: INTEL_INTERRUPT_MASK), ~0);
write16(info, INTEL_INTERRUPT_ENABLED, 0);
write16(info, INTEL_INTERRUPT_MASK, ~0);
remove_io_interrupt_handler(info.pci->u.h0.interrupt_line,
intel_interrupt_handler, &info);
@@ -24,7 +24,9 @@ struct intel_info {
pci_info* pci;
addr_t aperture_base;
aperture_id aperture;
uint8* registers;
area_id registers_area;
struct intel_shared_info* shared_info;
area_id shared_area;