* 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

View File

@ -54,6 +54,43 @@
#define DEVICE_NAME "intel_extreme"
#define INTEL_ACCELERANT_NAME "intel_extreme.accelerant"
// We encode the register block into the value and extract/translate it when
// actually accessing.
#define REGISTER_BLOCK_COUNT 7
#define REGISTER_BLOCK_SHIFT 24
#define REGISTER_BLOCK_MASK 0xff000000
#define REGISTER_REGISTER_MASK 0x00ffffff
#define REGISTER_BLOCK(x) ((x & REGISTER_BLOCK_MASK) >> REGISTER_BLOCK_SHIFT)
#define REGISTER_REGISTER(x) (x & REGISTER_REGISTER_MASK)
#define REGS_FLAT (0 << REGISTER_BLOCK_SHIFT)
#define REGS_INTERRUPT (1 << REGISTER_BLOCK_SHIFT)
#define REGS_NORTH_SHARED (2 << REGISTER_BLOCK_SHIFT)
#define REGS_NORTH_PIPE_AND_PORT (3 << REGISTER_BLOCK_SHIFT)
#define REGS_NORTH_PLANE_CONTROL (4 << REGISTER_BLOCK_SHIFT)
#define REGS_SOUTH_SHARED (5 << REGISTER_BLOCK_SHIFT)
#define REGS_SOUTH_TRANSCODER_PORT (6 << REGISTER_BLOCK_SHIFT)
// register blocks for (G)MCH/ICH based platforms
#define MCH_INTERRUPT_REGISTER_BASE 0x020a0
#define MCH_SHARED_REGISTER_BASE 0x00000
#define MCH_PIPE_AND_PORT_REGISTER_BASE 0x60000
#define MCH_PLANE_CONTROL_REGISTER_BASE 0x70000
#define ICH_SHARED_REGISTER_BASE 0x00000
#define ICH_PORT_REGISTER_BASE 0x60000
// PCH - Platform Control Hub - Newer hardware moves from a MCH/ICH based setup
// to a PCH based one, that means anything that used to communicate via (G)MCH
// registers needs to use different ones on PCH based platforms (Ironlake and
// up, SandyBridge, etc.).
#define PCH_DE_INTERRUPT_REGISTER_BASE 0x44000
#define PCH_NORTH_SHARED_REGISTER_BASE 0x40000
#define PCH_NORTH_PIPE_AND_PORT_REGISTER_BASE 0x60000
#define PCH_NORTH_PLANE_CONTROL_REGISTER_BASE 0x70000
#define PCH_SOUTH_SHARED_REGISTER_BASE 0xc0000
#define PCH_SOUTH_TRANSCODER_AND_PORT_REGISTER_BASE 0xe0000
struct DeviceType {
uint32 type;
@ -114,6 +151,7 @@ struct intel_shared_info {
uint32 dpms_mode;
area_id registers_area; // area of memory mapped registers
uint32 register_blocks[REGISTER_BLOCK_COUNT];
uint8* status_page;
phys_addr_t physical_status_page;
uint8* graphics_memory;
@ -221,58 +259,6 @@ struct intel_free_graphics_memory {
#define G4X_STOLEN_MEMORY_224MB 0xc0
#define G4X_STOLEN_MEMORY_352MB 0xd0
// PCH - Platform Control Hub - Newer hardware moves from a MCH/ICH based setup
// to a PCH based one, that means anything that used to communicate via (G)MCH
// registers needs to use different ones on PCH based platforms (Ironlake and
// up, SandyBridge, etc.).
// North Shared Functions
#define PCH_DE_POWER_MEASUREMENT 0x42400
#define PCH_DE_INTERRUPT_STATUS 0x44000 // INTEL_INTERRUPT_STATUS
#define PCH_DE_INTERRUPT_MASK 0x44004 // INTEL_INTERRUPT_MASK
#define PCH_DE_INTERRUPT_IDENTITY 0x44008 // INTEL_INTERRUPT_IDENTITY
#define PCH_DE_INTERRUPT_ENABLED 0x4400c // INTEL_INTERRUPT_ENABLED
#define PCH_DISPLAY_A_PALETTE 0x4a000 // INTEL_DISPLAY_A_PALETTE
#define PCH_DISPLAY_B_PALETTE 0x4a800 // INTEL_DISPLAY_B_PALETTE
#define PCH_INTERRUPT_VBLANK_PIPEA (1 << 7)
#define PCH_INTERRUPT_VBLANK_PIPEB (1 << 15)
// South Shared Functions
#define PCH_I2C_IO_A 0xc5010 // INTEL_I2C_IO_A
#define PCH_I2C_IO_C 0xc5018 // INTEL_I2C_IO_C
#define PCH_DISPLAY_A_PLL 0xc6014 // INTEL_DISPLAY_A_PLL
#define PCH_DISPLAY_B_PLL 0xc6018 // INTEL_DISPLAY_B_PLL
#define PCH_DISPLAY_A_PLL_DIVISOR_0 0xc6040 // INTEL_DISPLAY_A_PLL_DIVISOR_0
#define PCH_DISPLAY_A_PLL_DIVISOR_1 0xc6044 // INTEL_DISPLAY_A_PLL_DIVISOR_1
#define PCH_DISPLAY_B_PLL_DIVISOR_0 0xc6048 // INTEL_DISPLAY_B_PLL_DIVISOR_0
#define PCH_DISPLAY_B_PLL_DIVISOR_1 0xc604c // INTEL_DISPLAY_B_PLL_DIVISOR_1
#define PCH_PANEL_CONTROL 0xc7200 // INTEL_PANEL_CONTROL
#define PCH_PANEL_STATUS 0xc7204 // INTEL_PANEL_STATUS
#define PANEL_REGISTER_UNLOCK (0xabcd << 16)
// South Display Engine (SDE) Transcoder and Port Controls
#define PCH_DISPLAY_A_ANALOG_PORT 0xe1100 // INTEL_DISPLAY_A_ANALOG_PORT
#define PCH_DISPLAY_A_DIGITAL_PORT 0xe1120 // INTEL_DISPLAY_A_DIGITAL_PORT
#define PCH_DISPLAY_B_DIGITAL_PORT 0xe1140 // INTEL_DISPLAY_B_DIGITAL_PORT
#define PCH_DISPLAY_LVDS_PORT 0xe1180 // INTEL_DISPLAY_LVDS_PORT
#define PCH_TRANSCODER_A_HTOTAL 0xe0000 // INTEL_DISPLAY_A_HTOTAL
#define PCH_TRANSCODER_A_HBLANK 0xe0004 // INTEL_DISPLAY_A_HBLANK
#define PCH_TRANSCODER_A_HSYNC 0xe0008 // INTEL_DISPLAY_A_HSYNC
#define PCH_TRANSCODER_A_VTOTAL 0xe000c // INTEL_DISPLAY_A_VTOTAL
#define PCH_TRANSCODER_A_VBLANK 0xe0010 // INTEL_DISPLAY_A_VBLANK
#define PCH_TRANSCODER_A_VSYNC 0xe0014 // INTEL_DISPLAY_A_VSYNC
#define PCH_TRANSCODER_B_HTOTAL 0xe1000 // INTEL_DISPLAY_B_HTOTAL
#define PCH_TRANSCODER_B_HBLANK 0xe1004 // INTEL_DISPLAY_B_HBLANK
#define PCH_TRANSCODER_B_HSYNC 0xe1008 // INTEL_DISPLAY_B_HSYNC
#define PCH_TRANSCODER_B_VTOTAL 0xe100c // INTEL_DISPLAY_B_VTOTAL
#define PCH_TRANSCODER_B_VBLANK 0xe1010 // INTEL_DISPLAY_B_VBLANK
#define PCH_TRANSCODER_B_VSYNC 0xe1014 // INTEL_DISPLAY_B_VSYNC
#define PCH_LVDS_DETECTED (1 << 1)
// SandyBridge (SNB)
#define SNB_GRAPHICS_MEMORY_CONTROL 0x50
@ -326,13 +312,6 @@ struct intel_free_graphics_memory {
#define GTT_ENTRY_LOCAL_MEMORY 0x02
#define GTT_PAGE_SHIFT 12
// interrupts
#define INTEL_INTERRUPT_ENABLED 0x020a0
#define INTEL_INTERRUPT_IDENTITY 0x020a4
#define INTEL_INTERRUPT_MASK 0x020a8
#define INTEL_INTERRUPT_STATUS 0x020ac
#define INTERRUPT_VBLANK_PIPEA (1 << 7)
#define INTERRUPT_VBLANK_PIPEB (1 << 5)
// ring buffer
#define INTEL_PRIMARY_RING_BUFFER 0x02030
@ -347,8 +326,19 @@ struct intel_free_graphics_memory {
#define INTEL_RING_BUFFER_HEAD_MASK 0x001ffffc
#define INTEL_RING_BUFFER_ENABLED 1
// interrupts
#define INTEL_INTERRUPT_ENABLED (0x0000 | REGS_INTERRUPT)
#define INTEL_INTERRUPT_IDENTITY (0x0004 | REGS_INTERRUPT)
#define INTEL_INTERRUPT_MASK (0x0008 | REGS_INTERRUPT)
#define INTEL_INTERRUPT_STATUS (0x000c | REGS_INTERRUPT)
#define INTERRUPT_VBLANK_PIPEA (1 << 7)
#define INTERRUPT_VBLANK_PIPEB (1 << 5)
// TODO: verify that these are actually different on older versions
#define PCH_INTERRUPT_VBLANK_PIPEA (1 << 7)
#define PCH_INTERRUPT_VBLANK_PIPEB (1 << 15)
// display ports
#define INTEL_DISPLAY_A_ANALOG_PORT 0x61100
#define INTEL_DISPLAY_A_ANALOG_PORT (0x1100 | REGS_SOUTH_TRANSCODER_PORT)
#define DISPLAY_MONITOR_PORT_ENABLED (1UL << 31)
#define DISPLAY_MONITOR_PIPE_B (1UL << 30)
#define DISPLAY_MONITOR_VGA_POLARITY (1UL << 15)
@ -360,9 +350,9 @@ struct intel_free_graphics_memory {
#define DISPLAY_MONITOR_POLARITY_MASK (3UL << 3)
#define DISPLAY_MONITOR_POSITIVE_HSYNC (1UL << 3)
#define DISPLAY_MONITOR_POSITIVE_VSYNC (2UL << 3)
#define INTEL_DISPLAY_A_DIGITAL_PORT 0x61120
#define INTEL_DISPLAY_C_DIGITAL 0x61160
#define INTEL_DISPLAY_LVDS_PORT 0x61180
#define INTEL_DISPLAY_A_DIGITAL_PORT (0x1120 | 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 LVDS_POST2_RATE_SLOW 14 // PLL Divisors
#define LVDS_POST2_RATE_FAST 7
#define LVDS_CLKB_POWER_MASK (3 << 4)
@ -399,21 +389,51 @@ struct intel_free_graphics_memory {
#define DISPLAY_PLL_M2_DIVISOR_SHIFT 0
#define DISPLAY_PLL_PULSE_PHASE_SHIFT 9
// display A
#define INTEL_DISPLAY_A_HTOTAL 0x60000
#define INTEL_DISPLAY_A_HBLANK 0x60004
#define INTEL_DISPLAY_A_HSYNC 0x60008
#define INTEL_DISPLAY_A_VTOTAL 0x6000c
#define INTEL_DISPLAY_A_VBLANK 0x60010
#define INTEL_DISPLAY_A_VSYNC 0x60014
#define INTEL_DISPLAY_A_IMAGE_SIZE 0x6001c
// display
#define INTEL_DISPLAY_A_HTOTAL (0x0000 | REGS_SOUTH_TRANSCODER_PORT)
#define INTEL_DISPLAY_A_HBLANK (0x0004 | REGS_SOUTH_TRANSCODER_PORT)
#define INTEL_DISPLAY_A_HSYNC (0x0008 | REGS_SOUTH_TRANSCODER_PORT)
#define INTEL_DISPLAY_A_VTOTAL (0x000c | REGS_SOUTH_TRANSCODER_PORT)
#define INTEL_DISPLAY_A_VBLANK (0x0010 | REGS_SOUTH_TRANSCODER_PORT)
#define INTEL_DISPLAY_A_VSYNC (0x0014 | REGS_SOUTH_TRANSCODER_PORT)
#define INTEL_DISPLAY_A_IMAGE_SIZE (0x001c | REGS_SOUTH_TRANSCODER_PORT)
#define INTEL_DISPLAY_B_HTOTAL (0x1000 | REGS_SOUTH_TRANSCODER_PORT)
#define INTEL_DISPLAY_B_HBLANK (0x1004 | REGS_SOUTH_TRANSCODER_PORT)
#define INTEL_DISPLAY_B_HSYNC (0x1008 | REGS_SOUTH_TRANSCODER_PORT)
#define INTEL_DISPLAY_B_VTOTAL (0x100c | REGS_SOUTH_TRANSCODER_PORT)
#define INTEL_DISPLAY_B_VBLANK (0x1010 | REGS_SOUTH_TRANSCODER_PORT)
#define INTEL_DISPLAY_B_VSYNC (0x1014 | REGS_SOUTH_TRANSCODER_PORT)
#define INTEL_DISPLAY_B_IMAGE_SIZE (0x101c | REGS_SOUTH_TRANSCODER_PORT)
#define INTEL_DISPLAY_B_DIGITAL_PORT (0x1140 | REGS_SOUTH_TRANSCODER_PORT)
// planes
#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)
#define INTEL_DISPLAY_A_CONTROL (0x0180 | REGS_NORTH_PLANE_CONTROL)
#define INTEL_DISPLAY_A_BASE (0x0184 | REGS_NORTH_PLANE_CONTROL)
#define INTEL_DISPLAY_A_BYTES_PER_ROW (0x0188 | REGS_NORTH_PLANE_CONTROL)
#define INTEL_DISPLAY_A_POS (0x018c | REGS_NORTH_PLANE_CONTROL)
// reserved on A
#define INTEL_DISPLAY_A_PIPE_SIZE (0x0190 | REGS_NORTH_PLANE_CONTROL)
#define INTEL_DISPLAY_A_SURFACE (0x019c | REGS_NORTH_PLANE_CONTROL)
// i965 and up only
#define INTEL_DISPLAY_B_CONTROL (0x1180 | REGS_NORTH_PLANE_CONTROL)
#define INTEL_DISPLAY_B_BASE (0x1184 | REGS_NORTH_PLANE_CONTROL)
#define INTEL_DISPLAY_B_BYTES_PER_ROW (0x1188 | REGS_NORTH_PLANE_CONTROL)
#define INTEL_DISPLAY_B_POS (0x118c | REGS_NORTH_PLANE_CONTROL)
#define INTEL_DISPLAY_B_PIPE_SIZE (0x1190 | REGS_NORTH_PLANE_CONTROL)
#define INTEL_DISPLAY_B_SURFACE (0x119c | REGS_NORTH_PLANE_CONTROL)
// i965 and up only
#define INTEL_DISPLAY_A_CONTROL 0x70180
#define INTEL_DISPLAY_A_BASE 0x70184
#define INTEL_DISPLAY_A_BYTES_PER_ROW 0x70188
#define INTEL_DISPLAY_A_POS 0x7018c // reserved
#define INTEL_DISPLAY_A_PIPE_SIZE 0x70190
#define INTEL_DISPLAY_A_SURFACE 0x7019c // i965 and up only
#define DISPLAY_CONTROL_ENABLED (1UL << 31)
#define DISPLAY_CONTROL_GAMMA (1UL << 30)
#define DISPLAY_CONTROL_COLOR_MASK (0x0fUL << 26)
@ -422,51 +442,64 @@ struct intel_free_graphics_memory {
#define DISPLAY_CONTROL_RGB16 (5UL << 26)
#define DISPLAY_CONTROL_RGB32 (6UL << 26)
// cursors
#define INTEL_CURSOR_CONTROL (0x0080 | REGS_NORTH_PLANE_CONTROL)
#define INTEL_CURSOR_BASE (0x0084 | REGS_NORTH_PLANE_CONTROL)
#define INTEL_CURSOR_POSITION (0x0088 | REGS_NORTH_PLANE_CONTROL)
#define INTEL_CURSOR_PALETTE (0x0090 | REGS_NORTH_PLANE_CONTROL)
// (- 0x009f)
#define INTEL_CURSOR_SIZE (0x00a0 | REGS_NORTH_PLANE_CONTROL)
#define CURSOR_ENABLED (1UL << 31)
#define CURSOR_FORMAT_2_COLORS (0UL << 24)
#define CURSOR_FORMAT_3_COLORS (1UL << 24)
#define CURSOR_FORMAT_4_COLORS (2UL << 24)
#define CURSOR_FORMAT_ARGB (4UL << 24)
#define CURSOR_FORMAT_XRGB (5UL << 24)
#define CURSOR_POSITION_NEGATIVE 0x8000
#define CURSOR_POSITION_MASK 0x3fff
// palette registers
#define INTEL_DISPLAY_A_PALETTE (0xa000 | REGS_NORTH_SHARED)
#define INTEL_DISPLAY_B_PALETTE (0xa800 | REGS_NORTH_SHARED)
// PLL registers
#define INTEL_DISPLAY_A_PLL (0x6014 | REGS_SOUTH_SHARED)
#define INTEL_DISPLAY_B_PLL (0x6018 | REGS_SOUTH_SHARED)
#define INTEL_DISPLAY_A_PLL_MULTIPLIER_DIVISOR \
(0x601c | REGS_SOUTH_SHARED)
#define INTEL_DISPLAY_B_PLL_MULTIPLIER_DIVISOR \
(0x6020 | REGS_SOUTH_SHARED)
#define INTEL_DISPLAY_A_PLL_DIVISOR_0 (0x6040 | REGS_SOUTH_SHARED)
#define INTEL_DISPLAY_A_PLL_DIVISOR_1 (0x6044 | REGS_SOUTH_SHARED)
#define INTEL_DISPLAY_B_PLL_DIVISOR_0 (0x6048 | REGS_SOUTH_SHARED)
#define INTEL_DISPLAY_B_PLL_DIVISOR_1 (0x604c | REGS_SOUTH_SHARED)
// i2c
#define INTEL_I2C_IO_A (0x5010 | REGS_SOUTH_SHARED)
#define INTEL_I2C_IO_B (0x5014 | REGS_SOUTH_SHARED)
#define INTEL_I2C_IO_C (0x5018 | REGS_SOUTH_SHARED)
#define INTEL_I2C_IO_D (0x501c | REGS_SOUTH_SHARED)
#define INTEL_I2C_IO_E (0x5020 | REGS_SOUTH_SHARED)
#define INTEL_I2C_IO_F (0x5024 | REGS_SOUTH_SHARED)
#define INTEL_I2C_IO_G (0x5028 | REGS_SOUTH_SHARED)
#define INTEL_I2C_IO_H (0x502c | REGS_SOUTH_SHARED)
#define I2C_CLOCK_DIRECTION_MASK (1 << 0)
#define I2C_CLOCK_DIRECTION_OUT (1 << 1)
#define I2C_CLOCK_VALUE_MASK (1 << 2)
#define I2C_CLOCK_VALUE_OUT (1 << 3)
#define I2C_CLOCK_VALUE_IN (1 << 4)
#define I2C_DATA_DIRECTION_MASK (1 << 8)
#define I2C_DATA_DIRECTION_OUT (1 << 9)
#define I2C_DATA_VALUE_MASK (1 << 10)
#define I2C_DATA_VALUE_OUT (1 << 11)
#define I2C_DATA_VALUE_IN (1 << 12)
#define I2C_RESERVED ((1 << 13) | (1 << 5))
// TODO: on IronLake this is in the north shared block at 0x41000
#define INTEL_VGA_DISPLAY_CONTROL 0x71400
#define VGA_DISPLAY_DISABLED (1UL << 31)
#define INTEL_DISPLAY_A_PALETTE 0x0a000
#define INTEL_DISPLAY_A_PIPE_CONTROL 0x70008
#define DISPLAY_PIPE_ENABLED (1UL << 31)
#define INTEL_DISPLAY_A_PIPE_STATUS 0x70024
#define DISPLAY_PIPE_VBLANK_ENABLED (1UL << 17)
#define DISPLAY_PIPE_VBLANK_STATUS (1UL << 1)
#define INTEL_DISPLAY_A_PLL 0x06014
#define INTEL_DISPLAY_A_PLL_MULTIPLIER_DIVISOR 0x0601c
#define INTEL_DISPLAY_A_PLL_DIVISOR_0 0x06040
#define INTEL_DISPLAY_A_PLL_DIVISOR_1 0x06044
// display B
#define INTEL_DISPLAY_B_HTOTAL 0x61000
#define INTEL_DISPLAY_B_HBLANK 0x61004
#define INTEL_DISPLAY_B_HSYNC 0x61008
#define INTEL_DISPLAY_B_VTOTAL 0x6100c
#define INTEL_DISPLAY_B_VBLANK 0x61010
#define INTEL_DISPLAY_B_VSYNC 0x61014
#define INTEL_DISPLAY_B_DIGITAL_PORT 0x61140
#define INTEL_DISPLAY_B_PIPE_SIZE 0x71190
#define INTEL_DISPLAY_B_PIPE_CONTROL 0x71008
#define INTEL_DISPLAY_B_PIPE_STATUS 0x71024
#define INTEL_DISPLAY_B_CONTROL 0x71180
#define INTEL_DISPLAY_B_BASE 0x71184
#define INTEL_DISPLAY_B_BYTES_PER_ROW 0x71188
#define INTEL_DISPLAY_B_POS 0x7118c
#define INTEL_DISPLAY_B_IMAGE_SIZE 0x6101c
#define INTEL_DISPLAY_B_SURFACE 0x7119c // i965 and up only
#define INTEL_DISPLAY_B_PALETTE 0x0a800
#define INTEL_DISPLAY_B_PLL 0x06018
#define INTEL_DISPLAY_B_PLL_MULTIPLIER_DIVISOR 0x06020
#define INTEL_DISPLAY_B_PLL_DIVISOR_0 0x06048
#define INTEL_DISPLAY_B_PLL_DIVISOR_1 0x0604c
// LVDS panel
#define INTEL_PANEL_STATUS 0x61200
#define PANEL_STATUS_POWER_ON (1UL << 31)
@ -475,20 +508,12 @@ struct intel_free_graphics_memory {
#define INTEL_PANEL_FIT_CONTROL 0x61230
#define INTEL_PANEL_FIT_RATIOS 0x61234
// cursor
#define INTEL_CURSOR_CONTROL 0x70080
#define INTEL_CURSOR_BASE 0x70084
#define INTEL_CURSOR_POSITION 0x70088
#define INTEL_CURSOR_PALETTE 0x70090 // (- 0x7009f)
#define INTEL_CURSOR_SIZE 0x700a0
#define CURSOR_ENABLED (1UL << 31)
#define CURSOR_FORMAT_2_COLORS (0UL << 24)
#define CURSOR_FORMAT_3_COLORS (1UL << 24)
#define CURSOR_FORMAT_4_COLORS (2UL << 24)
#define CURSOR_FORMAT_ARGB (4UL << 24)
#define CURSOR_FORMAT_XRGB (5UL << 24)
#define CURSOR_POSITION_NEGATIVE 0x8000
#define CURSOR_POSITION_MASK 0x3fff
// LVDS on IronLake and up
#define PCH_PANEL_CONTROL 0xc7200
#define PCH_PANEL_STATUS 0xc7204
#define PANEL_REGISTER_UNLOCK (0xabcd << 16)
#define PCH_LVDS_DETECTED (1 << 1)
// ring buffer commands
@ -519,31 +544,7 @@ struct intel_free_graphics_memory {
#define COMMAND_MODE_RGB16 0x01
#define COMMAND_MODE_RGB32 0x03
// i2c
#define INTEL_I2C_IO_A 0x5010
#define INTEL_I2C_IO_B 0x5014
#define INTEL_I2C_IO_C 0x5018
#define INTEL_I2C_IO_D 0x501c
#define INTEL_I2C_IO_E 0x5020
#define INTEL_I2C_IO_F 0x5024
#define INTEL_I2C_IO_G 0x5028
#define INTEL_I2C_IO_H 0x502c
#define I2C_CLOCK_DIRECTION_MASK (1 << 0)
#define I2C_CLOCK_DIRECTION_OUT (1 << 1)
#define I2C_CLOCK_VALUE_MASK (1 << 2)
#define I2C_CLOCK_VALUE_OUT (1 << 3)
#define I2C_CLOCK_VALUE_IN (1 << 4)
#define I2C_DATA_DIRECTION_MASK (1 << 8)
#define I2C_DATA_DIRECTION_OUT (1 << 9)
#define I2C_DATA_VALUE_MASK (1 << 10)
#define I2C_DATA_VALUE_OUT (1 << 11)
#define I2C_DATA_VALUE_IN (1 << 12)
#define I2C_RESERVED ((1 << 13) | (1 << 5))
// overlay
#define INTEL_OVERLAY_UPDATE 0x30000
#define INTEL_OVERLAY_TEST 0x30004
#define INTEL_OVERLAY_STATUS 0x30008

View File

@ -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) {

View File

@ -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;
}

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
}

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);
}
}

View File

@ -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);
}

View File

@ -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 */

View File

@ -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);

View File

@ -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;