Merge branch 'intel-extreme'
Rework of the intel-extreme driver. Don't expect anything special yet.
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012 Haiku, Inc. All rights reserved.
|
||||
* Copyright 2012-2016 Haiku, Inc. All rights reserved.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*
|
||||
* Authors:
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
/*
|
||||
* Copyright 2006-2014, Haiku, Inc. All Rights Reserved.
|
||||
* Copyright 2006-2016, Haiku, Inc. All Rights Reserved.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*
|
||||
* Authors:
|
||||
* Axel Dörfler, [email protected]
|
||||
* Alexander von Gluck, [email protected]
|
||||
*/
|
||||
#ifndef INTEL_EXTREME_H
|
||||
#define INTEL_EXTREME_H
|
||||
@@ -20,50 +21,61 @@
|
||||
|
||||
#define VENDOR_ID_INTEL 0x8086
|
||||
|
||||
#define INTEL_TYPE_FAMILY_MASK 0x000f0000
|
||||
#define INTEL_TYPE_GROUP_MASK 0x000ffff0
|
||||
#define INTEL_TYPE_MODEL_MASK 0x000fffff
|
||||
#define INTEL_FAMILY_MASK 0x00ff0000
|
||||
#define INTEL_GROUP_MASK 0x00fffff0
|
||||
#define INTEL_MODEL_MASK 0x00ffffff
|
||||
#define INTEL_TYPE_MASK 0x0000000f
|
||||
// families
|
||||
#define INTEL_TYPE_7xx 0x00010000
|
||||
#define INTEL_TYPE_8xx 0x00020000
|
||||
#define INTEL_TYPE_9xx 0x00040000
|
||||
#define INTEL_FAMILY_7xx 0x00010000 // First Gen
|
||||
#define INTEL_FAMILY_8xx 0x00020000 // Second Gen
|
||||
#define INTEL_FAMILY_9xx 0x00040000 // Third Gen +
|
||||
#define INTEL_FAMILY_SER5 0x00080000 // Intel5 Series
|
||||
#define INTEL_FAMILY_POVR 0x00100000 // PowerVR (uugh)
|
||||
#define INTEL_FAMILY_SOC0 0x00200000 // Atom SOC
|
||||
// groups
|
||||
#define INTEL_TYPE_83x (INTEL_TYPE_8xx | 0x0010)
|
||||
#define INTEL_TYPE_85x (INTEL_TYPE_8xx | 0x0020)
|
||||
#define INTEL_TYPE_91x (INTEL_TYPE_9xx | 0x0040)
|
||||
#define INTEL_TYPE_94x (INTEL_TYPE_9xx | 0x0080)
|
||||
#define INTEL_TYPE_96x (INTEL_TYPE_9xx | 0x0100)
|
||||
#define INTEL_TYPE_Gxx (INTEL_TYPE_9xx | 0x0200)
|
||||
#define INTEL_TYPE_G4x (INTEL_TYPE_9xx | 0x0400)
|
||||
#define INTEL_TYPE_IGD (INTEL_TYPE_9xx | 0x0800)
|
||||
#define INTEL_TYPE_ILK (INTEL_TYPE_9xx | 0x1000)
|
||||
#define INTEL_TYPE_SNB (INTEL_TYPE_9xx | 0x2000)
|
||||
#define INTEL_TYPE_IVB (INTEL_TYPE_9xx | 0x4000)
|
||||
#define INTEL_TYPE_VLV (INTEL_TYPE_9xx | 0x8000)
|
||||
#define INTEL_GROUP_83x (INTEL_FAMILY_8xx | 0x0010)
|
||||
#define INTEL_GROUP_85x (INTEL_FAMILY_8xx | 0x0020)
|
||||
#define INTEL_GROUP_91x (INTEL_FAMILY_9xx | 0x0010)
|
||||
#define INTEL_GROUP_94x (INTEL_FAMILY_9xx | 0x0020)
|
||||
#define INTEL_GROUP_96x (INTEL_FAMILY_9xx | 0x0040)
|
||||
#define INTEL_GROUP_Gxx (INTEL_FAMILY_9xx | 0x0080)
|
||||
#define INTEL_GROUP_G4x (INTEL_FAMILY_9xx | 0x0100)
|
||||
#define INTEL_GROUP_PIN (INTEL_FAMILY_9xx | 0x0200) // PineView
|
||||
#define INTEL_GROUP_ILK (INTEL_FAMILY_SER5 | 0x0010) // IronLake
|
||||
#define INTEL_GROUP_SNB (INTEL_FAMILY_SER5 | 0x0020) // SandyBridge
|
||||
#define INTEL_GROUP_IVB (INTEL_FAMILY_SER5 | 0x0040) // IvyBridge
|
||||
#define INTEL_GROUP_HAS (INTEL_FAMILY_SER5 | 0x0080) // Haswell
|
||||
#define INTEL_GROUP_SLT (INTEL_FAMILY_POVR | 0x0010) // Saltwell
|
||||
#define INTEL_GROUP_FSM (INTEL_FAMILY_POVR | 0x0020) // Fu.Silvermont
|
||||
#define INTEL_GROUP_VLV (INTEL_FAMILY_SOC0 | 0x0010) // ValleyView
|
||||
#define INTEL_GROUP_CHV (INTEL_FAMILY_SOC0 | 0x0020) // CherryView
|
||||
#define INTEL_GROUP_BXT (INTEL_FAMILY_SOC0 | 0x0040) // Broxton
|
||||
// models
|
||||
#define INTEL_TYPE_SERVER 0x0004
|
||||
#define INTEL_TYPE_MOBILE 0x0008
|
||||
#define INTEL_TYPE_915 (INTEL_TYPE_91x)
|
||||
#define INTEL_TYPE_915M (INTEL_TYPE_91x | INTEL_TYPE_MOBILE)
|
||||
#define INTEL_TYPE_945 (INTEL_TYPE_94x)
|
||||
#define INTEL_TYPE_945M (INTEL_TYPE_94x | INTEL_TYPE_MOBILE)
|
||||
#define INTEL_TYPE_965 (INTEL_TYPE_96x)
|
||||
#define INTEL_TYPE_965M (INTEL_TYPE_96x | INTEL_TYPE_MOBILE)
|
||||
#define INTEL_TYPE_G33 (INTEL_TYPE_Gxx)
|
||||
#define INTEL_TYPE_G45 (INTEL_TYPE_G4x)
|
||||
#define INTEL_TYPE_GM45 (INTEL_TYPE_G4x | INTEL_TYPE_MOBILE)
|
||||
#define INTEL_TYPE_IGDG (INTEL_TYPE_IGD)
|
||||
#define INTEL_TYPE_IGDGM (INTEL_TYPE_IGD | INTEL_TYPE_MOBILE)
|
||||
#define INTEL_TYPE_ILKG (INTEL_TYPE_ILK)
|
||||
#define INTEL_TYPE_ILKGM (INTEL_TYPE_ILK | INTEL_TYPE_MOBILE)
|
||||
#define INTEL_TYPE_SNBG (INTEL_TYPE_SNB)
|
||||
#define INTEL_TYPE_SNBGM (INTEL_TYPE_SNB | INTEL_TYPE_MOBILE)
|
||||
#define INTEL_TYPE_SNBGS (INTEL_TYPE_SNB | INTEL_TYPE_SERVER)
|
||||
#define INTEL_TYPE_IVBG (INTEL_TYPE_IVB)
|
||||
#define INTEL_TYPE_IVBGM (INTEL_TYPE_IVB | INTEL_TYPE_MOBILE)
|
||||
#define INTEL_TYPE_IVBGS (INTEL_TYPE_IVB | INTEL_TYPE_SERVER)
|
||||
#define INTEL_TYPE_VLVG (INTEL_TYPE_VLV)
|
||||
#define INTEL_TYPE_VLVGM (INTEL_TYPE_VLV | INTEL_TYPE_MOBILE)
|
||||
#define INTEL_TYPE_SERVER 0x0004
|
||||
#define INTEL_TYPE_MOBILE 0x0008
|
||||
#define INTEL_MODEL_915 (INTEL_GROUP_91x)
|
||||
#define INTEL_MODEL_915M (INTEL_GROUP_91x | INTEL_TYPE_MOBILE)
|
||||
#define INTEL_MODEL_945 (INTEL_GROUP_94x)
|
||||
#define INTEL_MODEL_945M (INTEL_GROUP_94x | INTEL_TYPE_MOBILE)
|
||||
#define INTEL_MODEL_965 (INTEL_GROUP_96x)
|
||||
#define INTEL_MODEL_965M (INTEL_GROUP_96x | INTEL_TYPE_MOBILE)
|
||||
#define INTEL_MODEL_G33 (INTEL_GROUP_Gxx)
|
||||
#define INTEL_MODEL_G45 (INTEL_GROUP_G4x)
|
||||
#define INTEL_MODEL_GM45 (INTEL_GROUP_G4x | INTEL_TYPE_MOBILE)
|
||||
#define INTEL_MODEL_PINE (INTEL_GROUP_PIN)
|
||||
#define INTEL_MODEL_PINEM (INTEL_GROUP_PIN | INTEL_TYPE_MOBILE)
|
||||
#define INTEL_MODEL_ILKG (INTEL_GROUP_ILK)
|
||||
#define INTEL_MODEL_ILKGM (INTEL_GROUP_ILK | INTEL_TYPE_MOBILE)
|
||||
#define INTEL_MODEL_SNBG (INTEL_GROUP_SNB)
|
||||
#define INTEL_MODEL_SNBGM (INTEL_GROUP_SNB | INTEL_TYPE_MOBILE)
|
||||
#define INTEL_MODEL_SNBGS (INTEL_GROUP_SNB | INTEL_TYPE_SERVER)
|
||||
#define INTEL_MODEL_IVBG (INTEL_GROUP_IVB)
|
||||
#define INTEL_MODEL_IVBGM (INTEL_GROUP_IVB | INTEL_TYPE_MOBILE)
|
||||
#define INTEL_MODEL_IVBGS (INTEL_GROUP_IVB | INTEL_TYPE_SERVER)
|
||||
#define INTEL_MODEL_HAS (INTEL_GROUP_HAS)
|
||||
#define INTEL_MODEL_HASM (INTEL_GROUP_HAS | INTEL_TYPE_MOBILE)
|
||||
#define INTEL_MODEL_VLV (INTEL_GROUP_VLV)
|
||||
#define INTEL_MODEL_VLVM (INTEL_GROUP_VLV | INTEL_TYPE_MOBILE)
|
||||
|
||||
// ValleyView MMIO offset
|
||||
#define VLV_DISPLAY_BASE 0x180000
|
||||
@@ -94,10 +106,10 @@
|
||||
#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.).
|
||||
// PCH - Platform Control Hub - Some 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, SandyBridge, IvyBridge, Some Haswell).
|
||||
#define PCH_NORTH_SHARED_REGISTER_BASE 0x40000
|
||||
#define PCH_NORTH_PIPE_AND_PORT_REGISTER_BASE 0x60000
|
||||
#define PCH_NORTH_PLANE_CONTROL_REGISTER_BASE 0x70000
|
||||
@@ -121,23 +133,65 @@ struct DeviceType {
|
||||
|
||||
bool InFamily(uint32 family) const
|
||||
{
|
||||
return (type & INTEL_TYPE_FAMILY_MASK) == family;
|
||||
return (type & INTEL_FAMILY_MASK) == family;
|
||||
}
|
||||
|
||||
bool InGroup(uint32 group) const
|
||||
{
|
||||
return (type & INTEL_TYPE_GROUP_MASK) == group;
|
||||
return (type & INTEL_GROUP_MASK) == group;
|
||||
}
|
||||
|
||||
bool IsModel(uint32 model) const
|
||||
{
|
||||
return (type & INTEL_TYPE_MODEL_MASK) == model;
|
||||
return (type & INTEL_MODEL_MASK) == model;
|
||||
}
|
||||
|
||||
bool IsMobile() const
|
||||
{
|
||||
return (type & INTEL_TYPE_MASK) == INTEL_TYPE_MOBILE;
|
||||
}
|
||||
|
||||
bool SupportsHDMI() const
|
||||
{
|
||||
return InGroup(INTEL_GROUP_G4x) || InFamily(INTEL_FAMILY_SER5)
|
||||
|| InFamily(INTEL_FAMILY_SOC0);
|
||||
}
|
||||
|
||||
bool HasPlatformControlHub() const
|
||||
{
|
||||
return InGroup(INTEL_TYPE_ILK) || InGroup(INTEL_TYPE_SNB)
|
||||
|| InGroup(INTEL_TYPE_IVB) || InGroup(INTEL_TYPE_VLV);
|
||||
return InFamily(INTEL_FAMILY_SER5);
|
||||
}
|
||||
|
||||
bool HasDDI() const
|
||||
{
|
||||
// Intel Digital Display Interface
|
||||
return InGroup(INTEL_GROUP_HAS) || (Generation() >= 8);
|
||||
}
|
||||
|
||||
int Generation() const
|
||||
{
|
||||
if (InFamily(INTEL_FAMILY_7xx))
|
||||
return 1;
|
||||
if (InFamily(INTEL_FAMILY_8xx))
|
||||
return 2;
|
||||
if (InGroup(INTEL_GROUP_91x) || InGroup(INTEL_GROUP_94x)
|
||||
|| IsModel(INTEL_MODEL_G33) || InGroup(INTEL_GROUP_PIN))
|
||||
return 3;
|
||||
if (InFamily(INTEL_FAMILY_9xx))
|
||||
return 4;
|
||||
if (InGroup(INTEL_GROUP_ILK))
|
||||
return 5;
|
||||
if (InGroup(INTEL_GROUP_SNB))
|
||||
return 6;
|
||||
if (InFamily(INTEL_FAMILY_SER5) || InGroup(INTEL_GROUP_VLV))
|
||||
return 7;
|
||||
if (InGroup(INTEL_GROUP_CHV))
|
||||
return 8;
|
||||
if (InGroup(INTEL_GROUP_BXT))
|
||||
return 9;
|
||||
|
||||
// Generation 0 means somethins is wrong :-)
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -165,12 +219,12 @@ struct intel_shared_info {
|
||||
area_id mode_list_area; // area containing display mode list
|
||||
uint32 mode_count;
|
||||
|
||||
display_mode current_mode;
|
||||
display_mode panel_mode; // VBIOS VBT panel mode
|
||||
uint32 bytes_per_row;
|
||||
uint32 bits_per_pixel;
|
||||
uint32 dpms_mode;
|
||||
|
||||
area_id registers_area; // area of memory mapped registers
|
||||
area_id registers_area; // area of memory mapped registers
|
||||
uint32 register_blocks[REGISTER_BLOCK_COUNT];
|
||||
|
||||
uint8* status_page;
|
||||
@@ -182,6 +236,8 @@ struct intel_shared_info {
|
||||
addr_t frame_buffer;
|
||||
uint32 frame_buffer_offset;
|
||||
|
||||
uint32 fdi_link_frequency; // In Mhz
|
||||
|
||||
bool got_vbt;
|
||||
bool single_head_locked;
|
||||
|
||||
@@ -215,6 +271,12 @@ struct intel_shared_info {
|
||||
bool has_vesa_edid_info;
|
||||
};
|
||||
|
||||
enum pipe_index {
|
||||
INTEL_PIPE_ANY,
|
||||
INTEL_PIPE_A,
|
||||
INTEL_PIPE_B
|
||||
};
|
||||
|
||||
//----------------- ioctl() interface ----------------
|
||||
|
||||
// magic code for ioctls
|
||||
@@ -254,7 +316,8 @@ struct intel_free_graphics_memory {
|
||||
// Register definitions, taken from X driver
|
||||
|
||||
// PCI bridge memory management
|
||||
#define INTEL_GRAPHICS_MEMORY_CONTROL 0x52
|
||||
#define INTEL_GRAPHICS_MEMORY_CONTROL 0x52 // i830+
|
||||
|
||||
// GGC - (G)MCH Graphics Control Register
|
||||
#define MEMORY_CONTROL_ENABLED 0x0004
|
||||
#define MEMORY_MASK 0x0001
|
||||
@@ -288,6 +351,7 @@ struct intel_free_graphics_memory {
|
||||
#define G4X_STOLEN_MEMORY_352MB 0xd0
|
||||
|
||||
// SandyBridge (SNB)
|
||||
|
||||
#define SNB_GRAPHICS_MEMORY_CONTROL 0x50
|
||||
|
||||
#define SNB_STOLEN_MEMORY_MASK 0xf8
|
||||
@@ -374,7 +438,7 @@ struct intel_free_graphics_memory {
|
||||
#define PCH_INTERRUPT_VBLANK_PIPEA_SNB (1 << 7)
|
||||
#define PCH_INTERRUPT_VBLANK_PIPEB_SNB (1 << 15)
|
||||
|
||||
// display ports
|
||||
// graphics port control
|
||||
#define DISPLAY_MONITOR_PORT_ENABLED (1UL << 31)
|
||||
#define DISPLAY_MONITOR_PIPE_B (1UL << 30)
|
||||
#define DISPLAY_MONITOR_VGA_POLARITY (1UL << 15)
|
||||
@@ -386,23 +450,31 @@ 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 DISPLAY_MONITOR_PORT_DETECTED (1UL << 2) // TMDS/DisplayPort only
|
||||
|
||||
#define LVDS_POST2_RATE_SLOW 14 // PLL Divisors
|
||||
#define LVDS_POST2_RATE_FAST 7
|
||||
#define LVDS_CLKB_POWER_MASK (3 << 4)
|
||||
#define LVDS_CLKB_POWER_UP (3 << 4)
|
||||
#define LVDS_PORT_EN (1 << 31)
|
||||
#define LVDS_A0A2_CLKA_POWER_UP (3 << 8)
|
||||
#define LVDS_PIPEB_SELECT (1 << 30)
|
||||
#define LVDS_B0B3PAIRS_POWER_UP (3 << 2)
|
||||
#define LVDS_PLL_MODE_LVDS (2 << 26)
|
||||
#define LVDS_18BIT_DITHER (1 << 25)
|
||||
#define LVDS_B0B3_POWER_MASK (3UL << 2)
|
||||
#define LVDS_B0B3_POWER_UP (3UL << 2)
|
||||
#define LVDS_CLKB_POWER_MASK (3UL << 4)
|
||||
#define LVDS_CLKB_POWER_UP (3UL << 4)
|
||||
#define LVDS_A3_POWER_MASK (3UL << 6)
|
||||
#define LVDS_A3_POWER_UP (3UL << 6)
|
||||
#define LVDS_A0A2_CLKA_POWER_UP (3UL << 8)
|
||||
#define LVDS_BORDER_ENABLE (1UL << 15)
|
||||
#define LVDS_HSYNC_POLARITY (1UL << 20)
|
||||
#define LVDS_VSYNC_POLARITY (1UL << 21)
|
||||
#define LVDS_18BIT_DITHER (1UL << 25)
|
||||
#define LVDS_PORT_EN (1UL << 31)
|
||||
|
||||
|
||||
// PLL flags
|
||||
#define DISPLAY_PLL_ENABLED (1UL << 31)
|
||||
#define DISPLAY_PLL_2X_CLOCK (1UL << 30)
|
||||
#define DISPLAY_PLL_SYNC_LOCK_ENABLED (1UL << 29)
|
||||
#define DISPLAY_PLL_NO_VGA_CONTROL (1UL << 28)
|
||||
#define DISPLAY_PLL_MODE_ANALOG (1UL << 26)
|
||||
#define DISPLAY_PLL_MODE_NORMAL (1UL << 26)
|
||||
#define DISPLAY_PLL_MODE_LVDS (2UL << 26)
|
||||
#define DISPLAY_PLL_DIVIDE_HIGH (1UL << 24)
|
||||
#define DISPLAY_PLL_DIVIDE_4X (1UL << 23)
|
||||
#define DISPLAY_PLL_POST1_DIVIDE_2 (1UL << 21)
|
||||
@@ -423,35 +495,122 @@ struct intel_free_graphics_memory {
|
||||
#define DISPLAY_PLL_PULSE_PHASE_SHIFT 9
|
||||
|
||||
// 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_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_OFFSET 0x1000
|
||||
|
||||
#define INTEL_DISPLAY_A_HTOTAL (0x0000 | REGS_NORTH_PIPE_AND_PORT)
|
||||
#define INTEL_DISPLAY_A_HBLANK (0x0004 | REGS_NORTH_PIPE_AND_PORT)
|
||||
#define INTEL_DISPLAY_A_HSYNC (0x0008 | REGS_NORTH_PIPE_AND_PORT)
|
||||
#define INTEL_DISPLAY_A_VTOTAL (0x000c | REGS_NORTH_PIPE_AND_PORT)
|
||||
#define INTEL_DISPLAY_A_VBLANK (0x0010 | REGS_NORTH_PIPE_AND_PORT)
|
||||
#define INTEL_DISPLAY_A_VSYNC (0x0014 | REGS_NORTH_PIPE_AND_PORT)
|
||||
#define INTEL_DISPLAY_B_HTOTAL (0x1000 | REGS_NORTH_PIPE_AND_PORT)
|
||||
#define INTEL_DISPLAY_B_HBLANK (0x1004 | REGS_NORTH_PIPE_AND_PORT)
|
||||
#define INTEL_DISPLAY_B_HSYNC (0x1008 | REGS_NORTH_PIPE_AND_PORT)
|
||||
#define INTEL_DISPLAY_B_VTOTAL (0x100c | REGS_NORTH_PIPE_AND_PORT)
|
||||
#define INTEL_DISPLAY_B_VBLANK (0x1010 | REGS_NORTH_PIPE_AND_PORT)
|
||||
#define INTEL_DISPLAY_B_VSYNC (0x1014 | REGS_NORTH_PIPE_AND_PORT)
|
||||
|
||||
#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)
|
||||
// on PCH we also have to set the transcoder
|
||||
#define INTEL_TRANSCODER_A_HTOTAL (0x0000 | REGS_SOUTH_TRANSCODER_PORT)
|
||||
#define INTEL_TRANSCODER_A_HBLANK (0x0004 | REGS_SOUTH_TRANSCODER_PORT)
|
||||
#define INTEL_TRANSCODER_A_HSYNC (0x0008 | REGS_SOUTH_TRANSCODER_PORT)
|
||||
#define INTEL_TRANSCODER_A_VTOTAL (0x000c | REGS_SOUTH_TRANSCODER_PORT)
|
||||
#define INTEL_TRANSCODER_A_VBLANK (0x0010 | REGS_SOUTH_TRANSCODER_PORT)
|
||||
#define INTEL_TRANSCODER_A_VSYNC (0x0014 | REGS_SOUTH_TRANSCODER_PORT)
|
||||
#define INTEL_TRANSCODER_B_HTOTAL (0x1000 | REGS_SOUTH_TRANSCODER_PORT)
|
||||
#define INTEL_TRANSCODER_B_HBLANK (0x1004 | REGS_SOUTH_TRANSCODER_PORT)
|
||||
#define INTEL_TRANSCODER_B_HSYNC (0x1008 | REGS_SOUTH_TRANSCODER_PORT)
|
||||
#define INTEL_TRANSCODER_B_VTOTAL (0x100c | REGS_SOUTH_TRANSCODER_PORT)
|
||||
#define INTEL_TRANSCODER_B_VBLANK (0x1010 | REGS_SOUTH_TRANSCODER_PORT)
|
||||
#define INTEL_TRANSCODER_B_VSYNC (0x1014 | REGS_SOUTH_TRANSCODER_PORT)
|
||||
|
||||
#define INTEL_TRANSCODER_A_IMAGE_SIZE (0x001c | REGS_SOUTH_TRANSCODER_PORT)
|
||||
#define INTEL_TRANSCODER_B_IMAGE_SIZE (0x101c | 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_SOUTH_TRANSCODER_PORT)
|
||||
#define INTEL_HDMI_PORT_C (0x1160 | REGS_SOUTH_TRANSCODER_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 GEN4_HDMI_PORT_B (0x1140 | REGS_SOUTH_TRANSCODER_PORT)
|
||||
#define GEN4_HDMI_PORT_C (0x1160 | REGS_SOUTH_TRANSCODER_PORT)
|
||||
#define CHV_HDMI_PORT_D (0x116C | REGS_SOUTH_TRANSCODER_PORT)
|
||||
|
||||
// DDI Buffer Control (This replaces DP on Haswell+)
|
||||
#define DDI_BUF_CTL_A (0x4000 | REGS_NORTH_PIPE_AND_PORT)
|
||||
#define DDI_BUF_CTL_B (0x4100 | REGS_NORTH_PIPE_AND_PORT)
|
||||
#define DDI_BUF_CTL_ENABLE (1 << 31)
|
||||
#define DDI_BUF_TRANS_SELECT(n) ((n) << 24)
|
||||
#define DDI_BUF_EMP_MASK (0xf << 24)
|
||||
#define DDI_BUF_PORT_REVERSAL (1 << 16)
|
||||
#define DDI_BUF_IS_IDLE (1 << 7)
|
||||
#define DDI_A_4_LANES (1 << 4)
|
||||
#define DDI_PORT_WIDTH(width) (((width) - 1) << 1)
|
||||
#define DDI_INIT_DISPLAY_DETECTED (1 << 0)
|
||||
|
||||
// DP_A always @ 6xxxx, DP_B-DP_D move with PCH
|
||||
#define INTEL_DISPLAY_PORT_A (0x4000 | REGS_NORTH_PIPE_AND_PORT)
|
||||
#define INTEL_DISPLAY_PORT_B (0x4100 | REGS_SOUTH_TRANSCODER_PORT)
|
||||
#define INTEL_DISPLAY_PORT_C (0x4200 | REGS_SOUTH_TRANSCODER_PORT)
|
||||
#define INTEL_DISPLAY_PORT_D (0x4300 | REGS_SOUTH_TRANSCODER_PORT)
|
||||
|
||||
// Unless you're a damn Valley/CherryView unicorn :-(
|
||||
#define VLV_DISPLAY_PORT_B (VLV_DISPLAY_BASE + 0x64100)
|
||||
#define VLV_DISPLAY_PORT_C (VLV_DISPLAY_BASE + 0x64200)
|
||||
#define CHV_DISPLAY_PORT_D (VLV_DISPLAY_BASE + 0x64300)
|
||||
|
||||
// DP AUX channels
|
||||
#define INTEL_DP_AUX_CTL_A (0x4010 | REGS_NORTH_PIPE_AND_PORT)
|
||||
#define INTEL_DP_AUX_CTL_B (0x4110 | REGS_SOUTH_TRANSCODER_PORT)
|
||||
#define INTEL_DP_AUX_CTL_C (0x4210 | REGS_SOUTH_TRANSCODER_PORT)
|
||||
#define INTEL_DP_AUX_CTL_D (0x4310 | REGS_SOUTH_TRANSCODER_PORT)
|
||||
|
||||
#define VLV_DP_AUX_CTL_B (VLV_DISPLAY_BASE + 0x64110)
|
||||
#define VLV_DP_AUX_CTL_C (VLV_DISPLAY_BASE + 0x64210)
|
||||
#define CHV_DP_AUX_CTL_D (VLV_DISPLAY_BASE + 0x64310)
|
||||
|
||||
#define INTEL_DP_AUX_CTL_BUSY (1 << 31)
|
||||
#define INTEL_DP_AUX_CTL_DONE (1 << 30)
|
||||
#define INTEL_DP_AUX_CTL_INTERRUPT (1 << 29)
|
||||
#define INTEL_DP_AUX_CTL_TIMEOUT_ERROR (1 << 28)
|
||||
#define INTEL_DP_AUX_CTL_TIMEOUT_400us (0 << 26)
|
||||
#define INTEL_DP_AUX_CTL_TIMEOUT_600us (1 << 26)
|
||||
#define INTEL_DP_AUX_CTL_TIMEOUT_800us (2 << 26)
|
||||
#define INTEL_DP_AUX_CTL_TIMEOUT_1600us (3 << 26)
|
||||
#define INTEL_DP_AUX_CTL_TIMEOUT_MASK (3 << 26)
|
||||
#define INTEL_DP_AUX_CTL_RECEIVE_ERROR (1 << 25)
|
||||
#define INTEL_DP_AUX_CTL_MSG_SIZE_MASK (0x1f << 20)
|
||||
#define INTEL_DP_AUX_CTL_MSG_SIZE_SHIFT 20
|
||||
#define INTEL_DP_AUX_CTL_PRECHARGE_2US_MASK (0xf << 16)
|
||||
#define INTEL_DP_AUX_CTL_PRECHARGE_2US_SHIFT 16
|
||||
#define INTEL_DP_AUX_CTL_BIT_CLOCK_2X_MASK (0x7ff)
|
||||
#define INTEL_DP_AUX_CTL_BIT_CLOCK_2X_SHIFT 0
|
||||
#define INTEL_DP_AUX_CTL_SYNC_PULSE_SKL(c) ((c) - 1)
|
||||
|
||||
// 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_PIPE_ENABLED (1UL << 31)
|
||||
#define INTEL_PIPE_CONTROL 0x0008
|
||||
#define INTEL_PIPE_STATUS 0x0024
|
||||
|
||||
#define INTEL_PLANE_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 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)
|
||||
|
||||
@@ -472,6 +631,7 @@ struct intel_free_graphics_memory {
|
||||
#define INTEL_DISPLAY_B_SURFACE (0x119c | REGS_NORTH_PLANE_CONTROL)
|
||||
// i965 and up only
|
||||
|
||||
// INTEL_DISPLAY_A_CONTROL source pixel format
|
||||
#define DISPLAY_CONTROL_ENABLED (1UL << 31)
|
||||
#define DISPLAY_CONTROL_GAMMA (1UL << 30)
|
||||
#define DISPLAY_CONTROL_COLOR_MASK (0x0fUL << 26)
|
||||
@@ -480,6 +640,19 @@ struct intel_free_graphics_memory {
|
||||
#define DISPLAY_CONTROL_RGB16 (5UL << 26)
|
||||
#define DISPLAY_CONTROL_RGB32 (6UL << 26)
|
||||
|
||||
// INTEL_DISPLAY_A_PIPE_CONTROL ILK+
|
||||
#define INTEL_PIPE_DITHER_TYPE_MASK (0x0000000c)
|
||||
#define INTEL_PIPE_DITHER_TYPE_SP (0 << 2)
|
||||
#define INTEL_PIPE_DITHER_TYPE_ST1 (1 << 2)
|
||||
#define INTEL_PIPE_DITHER_TYPE_ST2 (2 << 2)
|
||||
#define INTEL_PIPE_DITHER_TYPE_TEMP (3 << 2)
|
||||
#define INTEL_PIPE_DITHER_EN (1 << 4)
|
||||
#define INTEL_PIPE_8BPC (0 << 5)
|
||||
#define INTEL_PIPE_10BPC (1 << 5)
|
||||
#define INTEL_PIPE_6BPC (2 << 5)
|
||||
#define INTEL_PIPE_12BPC (3 << 5)
|
||||
#define INTEL_PIPE_PROGRESSIVE (0 << 21)
|
||||
|
||||
// cursors
|
||||
#define INTEL_CURSOR_CONTROL (0x0080 | REGS_NORTH_PLANE_CONTROL)
|
||||
#define INTEL_CURSOR_BASE (0x0084 | REGS_NORTH_PLANE_CONTROL)
|
||||
@@ -503,10 +676,13 @@ struct intel_free_graphics_memory {
|
||||
// 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 CHV_DISPLAY_C_PLL (0x6030 | REGS_SOUTH_SHARED)
|
||||
|
||||
// Multiplier Divisor
|
||||
#define INTEL_DISPLAY_A_PLL_MD (0x601C | REGS_SOUTH_SHARED)
|
||||
#define INTEL_DISPLAY_B_PLL_MD (0x6020 | REGS_SOUTH_SHARED)
|
||||
#define CHV_DISPLAY_B_PLL_MD (0x603C | 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)
|
||||
@@ -535,23 +711,41 @@ struct intel_free_graphics_memory {
|
||||
#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 INTEL_VGA_DISPLAY_CONTROL (0x1400 | REGS_NORTH_PLANE_CONTROL)
|
||||
#define VGA_DISPLAY_DISABLED (1UL << 31)
|
||||
|
||||
// LVDS panel
|
||||
#define INTEL_PANEL_STATUS 0x61200
|
||||
#define PANEL_STATUS_POWER_ON (1UL << 31)
|
||||
#define INTEL_PANEL_CONTROL 0x61204
|
||||
#define PANEL_CONTROL_POWER_TARGET_ON (1UL << 0)
|
||||
#define INTEL_PANEL_FIT_CONTROL 0x61230
|
||||
#define INTEL_PANEL_FIT_RATIOS 0x61234
|
||||
#define INTEL_PANEL_STATUS (0x1200 | REGS_NORTH_PIPE_AND_PORT)
|
||||
#define INTEL_PANEL_CONTROL (0x1204 | REGS_NORTH_PIPE_AND_PORT)
|
||||
#define INTEL_PANEL_FIT_CONTROL (0x1230 | REGS_NORTH_PIPE_AND_PORT)
|
||||
#define INTEL_PANEL_FIT_RATIOS (0x1234 | REGS_NORTH_PIPE_AND_PORT)
|
||||
|
||||
// LVDS on IronLake and up
|
||||
#define PCH_PANEL_CONTROL 0xc7200
|
||||
#define PCH_PANEL_STATUS 0xc7204
|
||||
#define PANEL_REGISTER_UNLOCK (0xabcd << 16)
|
||||
#define PCH_PANEL_STATUS (0x7200 | REGS_SOUTH_SHARED)
|
||||
#define PCH_PANEL_CONTROL (0x7204 | REGS_SOUTH_SHARED)
|
||||
#define PCH_PANEL_ON_DELAYS (0x7208 | REGS_SOUTH_SHARED)
|
||||
#define PCH_PANEL_OFF_DELAYS (0x720c | REGS_SOUTH_SHARED)
|
||||
#define PCH_PANEL_DIVISOR (0x7210 | REGS_SOUTH_SHARED)
|
||||
#define PCH_LVDS_DETECTED (1 << 1)
|
||||
|
||||
#define PANEL_STATUS_POWER_ON (1UL << 31)
|
||||
#define PANEL_CONTROL_POWER_TARGET_OFF (0UL << 0)
|
||||
#define PANEL_CONTROL_POWER_TARGET_ON (1UL << 0)
|
||||
#define PANEL_CONTROL_POWER_TARGET_RST (1UL << 1)
|
||||
#define PANEL_REGISTER_UNLOCK (0xabcd << 16)
|
||||
|
||||
// PCH_PANEL_ON_DELAYS
|
||||
#define PANEL_DELAY_PORT_SELECT_MASK (3 << 30)
|
||||
#define PANEL_DELAY_PORT_SELECT_LVDS (0 << 30)
|
||||
#define PANEL_DELAY_PORT_SELECT_DPA (1 << 30)
|
||||
#define PANEL_DELAY_PORT_SELECT_DPC (2 << 30)
|
||||
#define PANEL_DELAY_PORT_SELECT_DPD (3 << 30)
|
||||
|
||||
// PCH_PANEL_DIVISOR
|
||||
#define PANEL_DIVISOR_REFERENCE_DIV_MASK 0xffffff00
|
||||
#define PANEL_DIVISOR_REFERENCE_DIV_SHIFT 8
|
||||
#define PANEL_DIVISOR_POW_CYCLE_DLY_MASK 0x1f
|
||||
#define PANEL_DIVISOR_POW_CYCLE_DLY_SHIFT 0x1f
|
||||
|
||||
// ring buffer commands
|
||||
|
||||
@@ -594,6 +788,99 @@ 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 0x00c
|
||||
#define FDI_RX_ENABLE (1 << 31)
|
||||
#define FDI_RX_PLL_ENABLED (1 << 13)
|
||||
|
||||
#define FDI_FS_ERRC_ENABLE (1 << 27)
|
||||
#define FDI_FE_ERRC_ENABLE (1 << 26)
|
||||
|
||||
#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
|
||||
|
||||
#define FDI_RX_ENHANCE_FRAME_ENABLE (1 << 6)
|
||||
#define FDI_RX_CLOCK_MASK (1 << 4)
|
||||
#define FDI_RX_CLOCK_RAW (0 << 4)
|
||||
#define FDI_RX_CLOCK_PCD (1 << 4)
|
||||
|
||||
#define PCH_FDI_TX_BASE_REGISTER 0x60000
|
||||
#define PCH_FDI_TX_PIPE_OFFSET 0x01000
|
||||
#define PCH_FDI_TX_CONTROL 0x100
|
||||
#define FDI_TX_ENABLE (1 << 31)
|
||||
#define FDI_TX_ENHANCE_FRAME_ENABLE (1 << 18)
|
||||
#define FDI_TX_PLL_ENABLED (1 << 14)
|
||||
|
||||
#define FDI_PLL_BIOS_0 0x46000
|
||||
#define FDI_PLL_FB_CLOCK_MASK 0xff
|
||||
#define FDI_PLL_BIOS_1 0x46004
|
||||
#define FDI_PLL_BIOS_2 0x46008
|
||||
|
||||
#define FDI_LINK_TRAIN_PATTERN_1 (0 << 28)
|
||||
#define FDI_LINK_TRAIN_PATTERN_2 (1 << 28)
|
||||
#define FDI_LINK_TRAIN_PATTERN_IDLE (2 << 28)
|
||||
#define FDI_LINK_TRAIN_NONE (3 << 28)
|
||||
#define FDI_LINK_TRAIN_VOLTAGE_0_4V (0 << 25)
|
||||
#define FDI_LINK_TRAIN_VOLTAGE_0_6V (1 << 25)
|
||||
#define FDI_LINK_TRAIN_VOLTAGE_0_8V (2 << 25)
|
||||
#define FDI_LINK_TRAIN_VOLTAGE_1_2V (3 << 25)
|
||||
#define FDI_LINK_TRAIN_PRE_EMPHASIS_NONE (0 << 22)
|
||||
#define FDI_LINK_TRAIN_PRE_EMPHASIS_1_5X (1 << 22)
|
||||
#define FDI_LINK_TRAIN_PRE_EMPHASIS_2X (2 << 22)
|
||||
#define FDI_LINK_TRAIN_PRE_EMPHASIS_3X (3 << 22)
|
||||
|
||||
#define FDI_AUTO_TRAINING (1 << 10)
|
||||
#define FDI_AUTO_TRAIN_DONE (1 << 1)
|
||||
|
||||
// SNB A-stepping
|
||||
#define FDI_LINK_TRAIN_400MV_0DB_SNB_A (0x38 << 22)
|
||||
#define FDI_LINK_TRAIN_400MV_6DB_SNB_A (0x02 << 22)
|
||||
#define FDI_LINK_TRAIN_600MV_3_5DB_SNB_A (0x01 << 22)
|
||||
#define FDI_LINK_TRAIN_800MV_0DB_SNB_A (0x00 << 22)
|
||||
|
||||
// SNB B-stepping
|
||||
#define FDI_LINK_TRAIN_400MV_0DB_SNB_B (0x00 << 22)
|
||||
#define FDI_LINK_TRAIN_400MV_6DB_SNB_B (0x3a << 22)
|
||||
#define FDI_LINK_TRAIN_600MV_3_5DB_SNB_B (0x39 << 22)
|
||||
#define FDI_LINK_TRAIN_800MV_0DB_SNB_B (0x38 << 22)
|
||||
#define FDI_LINK_TRAIN_VOL_EMP_MASK (0x3f << 22)
|
||||
|
||||
#define FDI_LINK_TRAIN_PATTERN_1_CPT (0 << 8)
|
||||
#define FDI_LINK_TRAIN_PATTERN_2_CPT (1 << 8)
|
||||
#define FDI_LINK_TRAIN_PATTERN_IDLE_CPT (2 << 8)
|
||||
#define FDI_LINK_TRAIN_NORMAL_CPT (3 << 8)
|
||||
#define FDI_LINK_TRAIN_PATTERN_MASK_CPT (3 << 8)
|
||||
|
||||
// IvyBridge changes it up because... they hate developers?
|
||||
#define FDI_LINK_TRAIN_PATTERN_1_IVB (0 << 8)
|
||||
#define FDI_LINK_TRAIN_PATTERN_2_IVB (1 << 8)
|
||||
#define FDI_LINK_TRAIN_PATTERN_IDLE_IVB (2 << 8)
|
||||
#define FDI_LINK_TRAIN_NONE_IVB (3 << 8)
|
||||
|
||||
// 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;
|
||||
@@ -768,7 +1055,7 @@ struct overlay_registers {
|
||||
inline bool
|
||||
intel_uses_physical_overlay(intel_shared_info &info)
|
||||
{
|
||||
return !info.device_type.InGroup(INTEL_TYPE_Gxx);
|
||||
return !info.device_type.InGroup(INTEL_GROUP_Gxx);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012, Haiku, Inc. All Rights Reserved.
|
||||
* Copyright 2012-2016, Haiku, Inc. All Rights Reserved.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*
|
||||
* Authors:
|
||||
@@ -13,12 +13,12 @@
|
||||
#define TRACE_DISPLAY
|
||||
#ifdef TRACE_DISPLAY
|
||||
extern "C" void _sPrintf(const char* format, ...);
|
||||
# define TRACE(x...) _sPrintf("radeon_hd: " x)
|
||||
# define TRACE(x...) _sPrintf("dp_common: " x)
|
||||
#else
|
||||
# define TRACE(x...) ;
|
||||
#endif
|
||||
|
||||
#define ERROR(x...) _sPrintf("radeon_hd: " x)
|
||||
#define ERROR(x...) _sPrintf("dp_common: " x)
|
||||
|
||||
|
||||
uint32
|
||||
|
||||
@@ -0,0 +1,364 @@
|
||||
/*
|
||||
* Copyright 2011-2015, Haiku, Inc. All Rights Reserved.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*
|
||||
* Authors:
|
||||
* Michael Lotz, [email protected]
|
||||
* Alexander von Gluck IV, [email protected]
|
||||
*/
|
||||
|
||||
|
||||
#include "FlexibleDisplayInterface.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <Debug.h>
|
||||
#include <KernelExport.h>
|
||||
|
||||
#include "accelerant.h"
|
||||
#include "intel_extreme.h"
|
||||
|
||||
|
||||
#undef TRACE
|
||||
#define TRACE_FDI
|
||||
#ifdef TRACE_FDI
|
||||
# define TRACE(x...) _sPrintf("intel_extreme: " x)
|
||||
#else
|
||||
# define TRACE(x...)
|
||||
#endif
|
||||
|
||||
#define ERROR(x...) _sPrintf("intel_extreme: " x)
|
||||
#define CALLED() TRACE("CALLED %s\n", __PRETTY_FUNCTION__)
|
||||
|
||||
|
||||
// #pragma mark - FDITransmitter
|
||||
|
||||
|
||||
FDITransmitter::FDITransmitter(pipe_index pipeIndex)
|
||||
:
|
||||
fRegisterBase(PCH_FDI_TX_BASE_REGISTER)
|
||||
{
|
||||
if (pipeIndex == INTEL_PIPE_B)
|
||||
fRegisterBase += PCH_FDI_TX_PIPE_OFFSET * 1;
|
||||
}
|
||||
|
||||
|
||||
FDITransmitter::~FDITransmitter()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
FDITransmitter::Enable()
|
||||
{
|
||||
CALLED();
|
||||
uint32 targetRegister = fRegisterBase + PCH_FDI_TX_CONTROL;
|
||||
uint32 value = read32(targetRegister);
|
||||
|
||||
write32(targetRegister, value | FDI_TX_ENABLE);
|
||||
read32(targetRegister);
|
||||
spin(150);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
FDITransmitter::Disable()
|
||||
{
|
||||
CALLED();
|
||||
uint32 targetRegister = fRegisterBase + PCH_FDI_TX_CONTROL;
|
||||
uint32 value = read32(targetRegister);
|
||||
|
||||
write32(targetRegister, value & ~FDI_TX_ENABLE);
|
||||
read32(targetRegister);
|
||||
spin(150);
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
FDITransmitter::IsPLLEnabled()
|
||||
{
|
||||
CALLED();
|
||||
return (read32(fRegisterBase + PCH_FDI_TX_CONTROL) & FDI_TX_PLL_ENABLED)
|
||||
!= 0;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
FDITransmitter::EnablePLL()
|
||||
{
|
||||
CALLED();
|
||||
uint32 targetRegister = fRegisterBase + PCH_FDI_TX_CONTROL;
|
||||
uint32 value = read32(targetRegister);
|
||||
if ((value & FDI_TX_PLL_ENABLED) != 0) {
|
||||
// already enabled, possibly IronLake where it always is
|
||||
return;
|
||||
}
|
||||
|
||||
write32(targetRegister, value | FDI_TX_PLL_ENABLED);
|
||||
read32(targetRegister);
|
||||
spin(100); // warmup 10us + dmi delay 20us, be generous
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
FDITransmitter::DisablePLL()
|
||||
{
|
||||
CALLED();
|
||||
if (gInfo->shared_info->device_type.InGroup(INTEL_GROUP_ILK)) {
|
||||
// on IronLake the FDI PLL is alaways enabled, so no point in trying...
|
||||
return;
|
||||
}
|
||||
|
||||
uint32 targetRegister = fRegisterBase + PCH_FDI_TX_CONTROL;
|
||||
write32(targetRegister, read32(targetRegister) & ~FDI_TX_PLL_ENABLED);
|
||||
read32(targetRegister);
|
||||
spin(100);
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark - FDIReceiver
|
||||
|
||||
|
||||
FDIReceiver::FDIReceiver(pipe_index pipeIndex)
|
||||
:
|
||||
fRegisterBase(PCH_FDI_RX_BASE_REGISTER)
|
||||
{
|
||||
if (pipeIndex == INTEL_PIPE_B)
|
||||
fRegisterBase += PCH_FDI_RX_PIPE_OFFSET * 1;
|
||||
}
|
||||
|
||||
|
||||
FDIReceiver::~FDIReceiver()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
FDIReceiver::Enable()
|
||||
{
|
||||
CALLED();
|
||||
uint32 targetRegister = fRegisterBase + PCH_FDI_RX_CONTROL;
|
||||
uint32 value = read32(targetRegister);
|
||||
|
||||
write32(targetRegister, value | FDI_RX_ENABLE);
|
||||
read32(targetRegister);
|
||||
spin(150);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
FDIReceiver::Disable()
|
||||
{
|
||||
CALLED();
|
||||
uint32 targetRegister = fRegisterBase + PCH_FDI_RX_CONTROL;
|
||||
uint32 value = read32(targetRegister);
|
||||
|
||||
write32(targetRegister, value & ~FDI_RX_ENABLE);
|
||||
read32(targetRegister);
|
||||
spin(150);
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
FDIReceiver::IsPLLEnabled()
|
||||
{
|
||||
CALLED();
|
||||
return (read32(fRegisterBase + PCH_FDI_RX_CONTROL) & FDI_RX_PLL_ENABLED)
|
||||
!= 0;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
FDIReceiver::EnablePLL()
|
||||
{
|
||||
CALLED();
|
||||
uint32 targetRegister = fRegisterBase + PCH_FDI_RX_CONTROL;
|
||||
uint32 value = read32(targetRegister);
|
||||
if ((value & FDI_RX_PLL_ENABLED) != 0)
|
||||
return;
|
||||
|
||||
write32(targetRegister, value | FDI_RX_PLL_ENABLED);
|
||||
read32(targetRegister);
|
||||
spin(200); // warmup 10us + dmi delay 20us, be generous
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
FDIReceiver::DisablePLL()
|
||||
{
|
||||
CALLED();
|
||||
uint32 targetRegister = fRegisterBase + PCH_FDI_RX_CONTROL;
|
||||
write32(targetRegister, read32(targetRegister) & ~FDI_RX_PLL_ENABLED);
|
||||
read32(targetRegister);
|
||||
spin(100);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
FDIReceiver::SwitchClock(bool toPCDClock)
|
||||
{
|
||||
CALLED();
|
||||
uint32 targetRegister = fRegisterBase + PCH_FDI_RX_CONTROL;
|
||||
write32(targetRegister, (read32(targetRegister) & ~FDI_RX_CLOCK_MASK)
|
||||
| (toPCDClock ? FDI_RX_CLOCK_PCD : FDI_RX_CLOCK_RAW));
|
||||
read32(targetRegister);
|
||||
spin(200);
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark - FDILink
|
||||
|
||||
|
||||
FDILink::FDILink(pipe_index pipeIndex)
|
||||
:
|
||||
fTransmitter(pipeIndex),
|
||||
fReceiver(pipeIndex)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
FDILink::Train(display_mode* target)
|
||||
{
|
||||
CALLED();
|
||||
|
||||
uint32 bitsPerPixel;
|
||||
switch (target->space) {
|
||||
case B_RGB32_LITTLE:
|
||||
bitsPerPixel = 32;
|
||||
break;
|
||||
case B_RGB16_LITTLE:
|
||||
bitsPerPixel = 16;
|
||||
break;
|
||||
case B_RGB15_LITTLE:
|
||||
bitsPerPixel = 15;
|
||||
break;
|
||||
case B_CMAP8:
|
||||
default:
|
||||
bitsPerPixel = 8;
|
||||
break;
|
||||
}
|
||||
|
||||
// Khz / 10. ( each output octet encoded as 10 bits.
|
||||
uint32 linkBandwidth = gInfo->shared_info->fdi_link_frequency * 1000 / 10;
|
||||
uint32 bps = target->timing.pixel_clock * bitsPerPixel * 21 / 20;
|
||||
|
||||
uint32 lanes = bps / (linkBandwidth * 8);
|
||||
|
||||
TRACE("%s: FDI Link Lanes: %" B_PRIu32 "\n", __func__, lanes);
|
||||
|
||||
// Enable FDI clocks
|
||||
Receiver().EnablePLL();
|
||||
Receiver().SwitchClock(true);
|
||||
Transmitter().EnablePLL();
|
||||
|
||||
status_t result = B_ERROR;
|
||||
|
||||
// Over IVB supports AutoTraining of FDI
|
||||
if (gInfo->shared_info->device_type.Generation() >= 7) {
|
||||
result = _AutoTrain(lanes);
|
||||
if (result != B_OK) {
|
||||
ERROR("%s: FDI auto-training fault. Attempting manual train.\n",
|
||||
__func__);
|
||||
return _ManualTrain(lanes);
|
||||
}
|
||||
return B_OK;
|
||||
}
|
||||
return _ManualTrain(lanes);
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
FDILink::_ManualTrain(uint32 lanes)
|
||||
{
|
||||
CALLED();
|
||||
|
||||
// This needs completed
|
||||
ERROR("TODO: Manual FDI Link Training\n");
|
||||
|
||||
// Enable pipes
|
||||
Transmitter().Enable();
|
||||
Receiver().Enable();
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
FDILink::_AutoTrain(uint32 lanes)
|
||||
{
|
||||
CALLED();
|
||||
uint32 txControl = Transmitter().Base() + PCH_FDI_TX_CONTROL;
|
||||
uint32 rxControl = Receiver().Base() + PCH_FDI_RX_CONTROL;
|
||||
|
||||
uint32 buffer = read32(txControl);
|
||||
|
||||
// Clear port width selection and set number of lanes
|
||||
buffer &= ~(7 << 19);
|
||||
buffer |= (lanes - 1) << 19;
|
||||
|
||||
if (gInfo->shared_info->device_type.InGroup(INTEL_GROUP_IVB))
|
||||
buffer &= ~FDI_LINK_TRAIN_NONE_IVB;
|
||||
else
|
||||
buffer &= ~FDI_LINK_TRAIN_NONE;
|
||||
write32(txControl, buffer);
|
||||
|
||||
static const int snb_b_fdi_train_param[] = {
|
||||
FDI_LINK_TRAIN_400MV_0DB_SNB_B,
|
||||
FDI_LINK_TRAIN_400MV_6DB_SNB_B,
|
||||
FDI_LINK_TRAIN_600MV_3_5DB_SNB_B,
|
||||
FDI_LINK_TRAIN_800MV_0DB_SNB_B,
|
||||
};
|
||||
|
||||
bool trained = false;
|
||||
|
||||
for (uint32 i = 0; i < (sizeof(snb_b_fdi_train_param)
|
||||
/ sizeof(snb_b_fdi_train_param[0])); i++) {
|
||||
for (int j = 0; j < 2; j++) {
|
||||
buffer = read32(txControl);
|
||||
buffer |= FDI_AUTO_TRAINING;
|
||||
buffer &= ~FDI_LINK_TRAIN_VOL_EMP_MASK;
|
||||
buffer |= snb_b_fdi_train_param[i];
|
||||
write32(txControl, buffer | FDI_TX_ENABLE);
|
||||
|
||||
write32(rxControl, read32(rxControl) | FDI_RX_ENABLE);
|
||||
|
||||
spin(5);
|
||||
|
||||
buffer = read32(txControl);
|
||||
if ((buffer & FDI_AUTO_TRAIN_DONE) != 0) {
|
||||
TRACE("%s: FDI auto train complete!\n", __func__);
|
||||
trained = true;
|
||||
break;
|
||||
}
|
||||
|
||||
write32(txControl, read32(txControl) & ~FDI_TX_ENABLE);
|
||||
write32(rxControl, read32(rxControl) & ~FDI_RX_ENABLE);
|
||||
read32(rxControl);
|
||||
|
||||
spin(31);
|
||||
}
|
||||
|
||||
// If Trained, we fall out of autotraining
|
||||
if (trained)
|
||||
break;
|
||||
}
|
||||
|
||||
if (!trained) {
|
||||
ERROR("%s: FDI auto train failed!\n", __func__);
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
// Enable ecc on IVB
|
||||
if (gInfo->shared_info->device_type.InGroup(INTEL_GROUP_IVB)) {
|
||||
write32(rxControl, read32(rxControl)
|
||||
| FDI_FS_ERRC_ENABLE | FDI_FE_ERRC_ENABLE);
|
||||
read32(rxControl);
|
||||
}
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
FDILink::~FDILink()
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
/*
|
||||
* Copyright 2011-2015, Haiku, Inc. All Rights Reserved.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*
|
||||
* Authors:
|
||||
* Michael Lotz, [email protected]
|
||||
* Alexander von Gluck IV, [email protected]
|
||||
*/
|
||||
#ifndef INTEL_FDI_H
|
||||
#define INTEL_FDI_H
|
||||
|
||||
|
||||
#include "intel_extreme.h"
|
||||
|
||||
|
||||
class FDITransmitter {
|
||||
public:
|
||||
FDITransmitter(pipe_index pipeIndex);
|
||||
~FDITransmitter();
|
||||
|
||||
void Enable();
|
||||
void Disable();
|
||||
|
||||
bool IsPLLEnabled();
|
||||
void EnablePLL();
|
||||
void DisablePLL();
|
||||
|
||||
uint32 Base()
|
||||
{ return fRegisterBase; };
|
||||
|
||||
private:
|
||||
uint32 fRegisterBase;
|
||||
};
|
||||
|
||||
|
||||
class FDIReceiver {
|
||||
public:
|
||||
FDIReceiver(pipe_index pipeIndex);
|
||||
~FDIReceiver();
|
||||
|
||||
void Enable();
|
||||
void Disable();
|
||||
|
||||
bool IsPLLEnabled();
|
||||
void EnablePLL();
|
||||
void DisablePLL();
|
||||
|
||||
void SwitchClock(bool toPCDClock);
|
||||
|
||||
uint32 Base()
|
||||
{ return fRegisterBase; };
|
||||
|
||||
protected:
|
||||
uint32 fRegisterBase;
|
||||
};
|
||||
|
||||
|
||||
class FDILink {
|
||||
public:
|
||||
FDILink(pipe_index pipeIndex);
|
||||
~FDILink();
|
||||
|
||||
FDITransmitter& Transmitter()
|
||||
{ return fTransmitter; };
|
||||
FDIReceiver& Receiver()
|
||||
{ return fReceiver; };
|
||||
|
||||
status_t Train(display_mode* target);
|
||||
|
||||
private:
|
||||
status_t _ManualTrain(uint32 lanes);
|
||||
status_t _AutoTrain(uint32 lanes);
|
||||
|
||||
FDITransmitter fTransmitter;
|
||||
FDIReceiver fReceiver;
|
||||
};
|
||||
|
||||
|
||||
#endif // INTEL_FDI_H
|
||||
@@ -16,5 +16,11 @@ Addon intel_extreme.accelerant :
|
||||
mode.cpp
|
||||
overlay.cpp
|
||||
# overlay_3d_i965.cpp
|
||||
: be libaccelerantscommon.a
|
||||
pll.cpp
|
||||
# classes
|
||||
FlexibleDisplayInterface.cpp
|
||||
# PanelFitter.cpp
|
||||
Ports.cpp
|
||||
Pipes.cpp
|
||||
: be $(TARGET_LIBSTDC++) libaccelerantscommon.a
|
||||
;
|
||||
|
||||
@@ -0,0 +1,72 @@
|
||||
/*
|
||||
* Copyright 2011, Haiku, Inc. All Rights Reserved.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*
|
||||
* Authors:
|
||||
* Michael Lotz, [email protected]
|
||||
*/
|
||||
|
||||
|
||||
#include "PanelFitter.h"
|
||||
|
||||
#include "accelerant.h"
|
||||
#include "intel_extreme.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
|
||||
#undef TRACE
|
||||
#define TRACE_FITTER
|
||||
#ifdef TRACE_FITTER
|
||||
# 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__)
|
||||
|
||||
|
||||
// #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,335 @@
|
||||
/*
|
||||
* Copyright 2011-2015, Haiku, Inc. All Rights Reserved.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*
|
||||
* Authors:
|
||||
* Michael Lotz, mmlr@mlotz.ch
|
||||
* Alexander von Gluck IV, kallisti5@unixzen.com
|
||||
*/
|
||||
#include "Pipes.h"
|
||||
|
||||
#include "accelerant.h"
|
||||
#include "intel_extreme.h"
|
||||
#include <KernelExport.h>
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <new>
|
||||
|
||||
|
||||
#define TRACE_PIPE
|
||||
#ifdef TRACE_PIPE
|
||||
extern "C" void _sPrintf(const char* format, ...);
|
||||
# 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__)
|
||||
|
||||
|
||||
// PIPE: 6
|
||||
// PLANE: 7
|
||||
|
||||
|
||||
void
|
||||
program_pipe_color_modes(uint32 colorMode)
|
||||
{
|
||||
// All pipes get the same color mode
|
||||
write32(INTEL_DISPLAY_A_CONTROL, (read32(INTEL_DISPLAY_A_CONTROL)
|
||||
& ~(DISPLAY_CONTROL_COLOR_MASK | DISPLAY_CONTROL_GAMMA))
|
||||
| colorMode);
|
||||
write32(INTEL_DISPLAY_B_CONTROL, (read32(INTEL_DISPLAY_B_CONTROL)
|
||||
& ~(DISPLAY_CONTROL_COLOR_MASK | DISPLAY_CONTROL_GAMMA))
|
||||
| colorMode);
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark - Pipe
|
||||
|
||||
|
||||
Pipe::Pipe(pipe_index pipeIndex)
|
||||
:
|
||||
fHasTranscoder(false),
|
||||
fFDILink(NULL),
|
||||
// fPanelFitter(NULL),
|
||||
fPipeIndex(pipeIndex),
|
||||
fPipeOffset(0),
|
||||
fPlaneOffset(0)
|
||||
{
|
||||
if (pipeIndex == INTEL_PIPE_B) {
|
||||
fPipeOffset = INTEL_DISPLAY_OFFSET;
|
||||
fPlaneOffset = INTEL_PLANE_OFFSET;
|
||||
}
|
||||
|
||||
if (gInfo->shared_info->device_type.HasPlatformControlHub()) {
|
||||
fHasTranscoder = true;
|
||||
|
||||
// Program FDILink if PCH
|
||||
if (fFDILink == NULL)
|
||||
fFDILink = new(std::nothrow) FDILink(pipeIndex);
|
||||
}
|
||||
|
||||
TRACE("Pipe %s. Pipe Base: 0x%" B_PRIxADDR
|
||||
" Plane Base: 0x% " B_PRIxADDR "\n", (pipeIndex == INTEL_PIPE_A)
|
||||
? "A" : "B", fPipeOffset, fPlaneOffset);
|
||||
}
|
||||
|
||||
|
||||
Pipe::~Pipe()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
Pipe::IsEnabled()
|
||||
{
|
||||
CALLED();
|
||||
|
||||
return (read32(INTEL_DISPLAY_A_PIPE_CONTROL + fPipeOffset)
|
||||
& INTEL_PIPE_ENABLED) != 0;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
Pipe::Configure(display_mode* mode)
|
||||
{
|
||||
uint32 pipeControl = read32(INTEL_DISPLAY_A_PIPE_CONTROL + fPipeOffset);
|
||||
|
||||
// TODO: Haswell+ dithering changes.
|
||||
if (gInfo->shared_info->device_type.Generation() >= 4) {
|
||||
pipeControl |= (INTEL_PIPE_DITHER_EN | INTEL_PIPE_DITHER_TYPE_SP);
|
||||
switch (mode->space) {
|
||||
case B_CMAP8:
|
||||
case B_RGB15_LITTLE:
|
||||
case B_RGB16_LITTLE:
|
||||
pipeControl |= INTEL_PIPE_6BPC;
|
||||
break;
|
||||
case B_RGB24_LITTLE:
|
||||
pipeControl |= INTEL_PIPE_8BPC;
|
||||
break;
|
||||
case B_RGB32_LITTLE:
|
||||
default:
|
||||
pipeControl |= INTEL_PIPE_10BPC;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: CxSR downclocking?
|
||||
|
||||
// TODO: Interlaced modes
|
||||
pipeControl |= INTEL_PIPE_PROGRESSIVE;
|
||||
|
||||
write32(INTEL_DISPLAY_A_PIPE_CONTROL + fPipeOffset, pipeControl);
|
||||
read32(INTEL_DISPLAY_A_PIPE_CONTROL + fPipeOffset);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
Pipe::_ConfigureTranscoder(display_mode* target)
|
||||
{
|
||||
// update timing (fPipeOffset bumps the DISPLAY_A to B when needed)
|
||||
write32(INTEL_TRANSCODER_A_HTOTAL + fPipeOffset,
|
||||
((uint32)(target->timing.h_total - 1) << 16)
|
||||
| ((uint32)target->timing.h_display - 1));
|
||||
write32(INTEL_TRANSCODER_A_HBLANK + fPipeOffset,
|
||||
((uint32)(target->timing.h_total - 1) << 16)
|
||||
| ((uint32)target->timing.h_display - 1));
|
||||
write32(INTEL_TRANSCODER_A_HSYNC + fPipeOffset,
|
||||
((uint32)(target->timing.h_sync_end - 1) << 16)
|
||||
| ((uint32)target->timing.h_sync_start - 1));
|
||||
|
||||
write32(INTEL_TRANSCODER_A_VTOTAL + fPipeOffset,
|
||||
((uint32)(target->timing.v_total - 1) << 16)
|
||||
| ((uint32)target->timing.v_display - 1));
|
||||
write32(INTEL_TRANSCODER_A_VBLANK + fPipeOffset,
|
||||
((uint32)(target->timing.v_total - 1) << 16)
|
||||
| ((uint32)target->timing.v_display - 1));
|
||||
write32(INTEL_TRANSCODER_A_VSYNC + fPipeOffset,
|
||||
((uint32)(target->timing.v_sync_end - 1) << 16)
|
||||
| ((uint32)target->timing.v_sync_start - 1));
|
||||
|
||||
#if 0
|
||||
// XXX: Is it ok to do these on non-digital?
|
||||
write32(INTEL_TRANSCODER_A_POS + fPipeOffset, 0);
|
||||
write32(INTEL_TRANSCODER_A_IMAGE_SIZE + fPipeOffset,
|
||||
((uint32)(target->virtual_width - 1) << 16)
|
||||
| ((uint32)target->virtual_height - 1));
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
Pipe::ConfigureTimings(display_mode* target)
|
||||
{
|
||||
CALLED();
|
||||
|
||||
if (target == NULL) {
|
||||
ERROR("%s: Invalid display mode!\n", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
// update timing (fPipeOffset bumps the DISPLAY_A to B when needed)
|
||||
write32(INTEL_DISPLAY_A_HTOTAL + fPipeOffset,
|
||||
((uint32)(target->timing.h_total - 1) << 16)
|
||||
| ((uint32)target->timing.h_display - 1));
|
||||
write32(INTEL_DISPLAY_A_HBLANK + fPipeOffset,
|
||||
((uint32)(target->timing.h_total - 1) << 16)
|
||||
| ((uint32)target->timing.h_display - 1));
|
||||
write32(INTEL_DISPLAY_A_HSYNC + fPipeOffset,
|
||||
((uint32)(target->timing.h_sync_end - 1) << 16)
|
||||
| ((uint32)target->timing.h_sync_start - 1));
|
||||
|
||||
write32(INTEL_DISPLAY_A_VTOTAL + fPipeOffset,
|
||||
((uint32)(target->timing.v_total - 1) << 16)
|
||||
| ((uint32)target->timing.v_display - 1));
|
||||
write32(INTEL_DISPLAY_A_VBLANK + fPipeOffset,
|
||||
((uint32)(target->timing.v_total - 1) << 16)
|
||||
| ((uint32)target->timing.v_display - 1));
|
||||
write32(INTEL_DISPLAY_A_VSYNC + fPipeOffset,
|
||||
((uint32)(target->timing.v_sync_end - 1) << 16)
|
||||
| ((uint32)target->timing.v_sync_start - 1));
|
||||
|
||||
// XXX: Is it ok to do these on non-digital?
|
||||
write32(INTEL_DISPLAY_A_POS + fPipeOffset, 0);
|
||||
write32(INTEL_DISPLAY_A_IMAGE_SIZE + fPipeOffset,
|
||||
((uint32)(target->virtual_width - 1) << 16)
|
||||
| ((uint32)target->virtual_height - 1));
|
||||
|
||||
write32(INTEL_DISPLAY_A_PIPE_SIZE + fPipeOffset,
|
||||
((uint32)(target->timing.v_display - 1) << 16)
|
||||
| ((uint32)target->timing.h_display - 1));
|
||||
|
||||
// This is useful for debugging: it sets the border to red, so you
|
||||
// can see what is border and what is porch (black area around the
|
||||
// sync)
|
||||
//write32(INTEL_DISPLAY_A_RED + fPipeOffset, 0x00FF0000);
|
||||
|
||||
if (fHasTranscoder)
|
||||
_ConfigureTranscoder(target);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
Pipe::ConfigureClocks(const pll_divisors& divisors, uint32 pixelClock,
|
||||
uint32 extraFlags)
|
||||
{
|
||||
CALLED();
|
||||
|
||||
addr_t pllDivisorA = INTEL_DISPLAY_A_PLL_DIVISOR_0;
|
||||
addr_t pllDivisorB = INTEL_DISPLAY_A_PLL_DIVISOR_1;
|
||||
addr_t pllControl = INTEL_DISPLAY_A_PLL;
|
||||
addr_t pllMD = INTEL_DISPLAY_A_PLL_MD;
|
||||
|
||||
if (fPipeIndex == INTEL_PIPE_B) {
|
||||
pllDivisorA = INTEL_DISPLAY_B_PLL_DIVISOR_0;
|
||||
pllDivisorB = INTEL_DISPLAY_B_PLL_DIVISOR_1;
|
||||
pllControl = INTEL_DISPLAY_B_PLL;
|
||||
pllMD = INTEL_DISPLAY_B_PLL_MD;
|
||||
}
|
||||
|
||||
float refFreq = gInfo->shared_info->pll_info.reference_frequency / 1000.0f;
|
||||
|
||||
if (gInfo->shared_info->device_type.InGroup(INTEL_GROUP_96x)) {
|
||||
float adjusted = ((refFreq * divisors.m) / divisors.n) / divisors.post;
|
||||
uint32 pixelMultiply = uint32(adjusted / (pixelClock / 1000.0f));
|
||||
write32(pllMD, (0 << 24) | ((pixelMultiply - 1) << 8));
|
||||
}
|
||||
|
||||
// XXX: For now we assume no LVDS downclocking and program the same divisor
|
||||
// value to both divisor 0 (standard) and 1 (reduced divisor)
|
||||
if (gInfo->shared_info->device_type.InGroup(INTEL_GROUP_PIN)) {
|
||||
write32(pllDivisorA, (((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));
|
||||
write32(pllDivisorB, (((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(pllDivisorA, (((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));
|
||||
write32(pllDivisorB, (((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 | extraFlags;
|
||||
|
||||
if (gInfo->shared_info->device_type.Generation() >= 3) {
|
||||
// post1 divisor << 1 , 1-8
|
||||
if (gInfo->shared_info->device_type.InGroup(INTEL_GROUP_PIN)) {
|
||||
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;
|
||||
}
|
||||
|
||||
// p2 clock divider. 5 or 7 high
|
||||
if (divisors.post2_high)
|
||||
pll |= DISPLAY_PLL_DIVIDE_HIGH;
|
||||
|
||||
if (gInfo->shared_info->device_type.InGroup(INTEL_GROUP_96x))
|
||||
pll |= 6 << DISPLAY_PLL_PULSE_PHASE_SHIFT;
|
||||
} else {
|
||||
if (!divisors.post2_high)
|
||||
pll |= DISPLAY_PLL_DIVIDE_4X;
|
||||
|
||||
pll |= DISPLAY_PLL_2X_CLOCK;
|
||||
|
||||
// TODO: Is this supposed to be DISPLAY_PLL_IGD_POST1_DIVISOR_MASK??
|
||||
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;
|
||||
}
|
||||
|
||||
// Allow the PLL to warm up by masking its bit.
|
||||
write32(pllControl, pll & ~DISPLAY_PLL_NO_VGA_CONTROL);
|
||||
read32(pllControl);
|
||||
spin(150);
|
||||
write32(pllControl, pll);
|
||||
read32(pllControl);
|
||||
spin(150);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
Pipe::Enable(bool enable)
|
||||
{
|
||||
CALLED();
|
||||
|
||||
addr_t pipeReg = INTEL_DISPLAY_A_PIPE_CONTROL + fPipeOffset;
|
||||
addr_t planeReg = INTEL_DISPLAY_A_CONTROL + fPlaneOffset;
|
||||
|
||||
// Planes always have to operate on an enabled pipe
|
||||
|
||||
if (enable) {
|
||||
write32(pipeReg, read32(pipeReg) | INTEL_PIPE_ENABLED);
|
||||
wait_for_vblank();
|
||||
write32(planeReg, read32(planeReg) | DISPLAY_CONTROL_ENABLED);
|
||||
} else {
|
||||
write32(planeReg, read32(planeReg) & ~DISPLAY_CONTROL_ENABLED);
|
||||
wait_for_vblank();
|
||||
write32(pipeReg, read32(pipeReg) & ~INTEL_PIPE_ENABLED);
|
||||
}
|
||||
|
||||
read32(INTEL_DISPLAY_A_BASE);
|
||||
// flush the eventually cached PCI bus writes
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
/*
|
||||
* Copyright 2011-2015, Haiku, Inc. All Rights Reserved.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*
|
||||
* Authors:
|
||||
* Michael Lotz, mmlr@mlotz.ch
|
||||
* Alexander von Gluck IV, kallisti5@unixzen.com
|
||||
*/
|
||||
#ifndef INTEL_PIPE_H
|
||||
#define INTEL_PIPE_H
|
||||
|
||||
|
||||
#include <edid.h>
|
||||
|
||||
#include "intel_extreme.h"
|
||||
|
||||
#include "pll.h"
|
||||
#include "FlexibleDisplayInterface.h"
|
||||
|
||||
|
||||
#define MAX_PIPES 2
|
||||
|
||||
|
||||
void program_pipe_color_modes(uint32 colorMode);
|
||||
|
||||
//class FDILink;
|
||||
//class PanelFitter;
|
||||
|
||||
class Pipe {
|
||||
public:
|
||||
Pipe(pipe_index pipeIndex);
|
||||
~Pipe();
|
||||
|
||||
pipe_index Index()
|
||||
{ return fPipeIndex; }
|
||||
|
||||
bool IsEnabled();
|
||||
void Enable(bool enable);
|
||||
void Disable();
|
||||
|
||||
void Configure(display_mode* mode);
|
||||
void ConfigureTimings(display_mode* mode);
|
||||
void ConfigureClocks(
|
||||
const pll_divisors& divisors,
|
||||
uint32 pixelClock,
|
||||
uint32 extraFlags);
|
||||
|
||||
// access to the various parts of the pipe
|
||||
::FDILink* FDI()
|
||||
{ return fFDILink; }
|
||||
// ::PanelFitter* PanelFitter()
|
||||
// { return fPanelFitter; }
|
||||
|
||||
private:
|
||||
void _ConfigureTranscoder(display_mode* mode);
|
||||
|
||||
bool fHasTranscoder;
|
||||
|
||||
FDILink* fFDILink;
|
||||
// PanelFitter* fPanelFitter;
|
||||
|
||||
pipe_index fPipeIndex;
|
||||
|
||||
addr_t fPipeOffset;
|
||||
addr_t fPlaneOffset;
|
||||
};
|
||||
|
||||
|
||||
#endif // INTEL_PIPE_H
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,225 @@
|
||||
/*
|
||||
* Copyright 2011-2015, Haiku, Inc. All Rights Reserved.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*
|
||||
* Authors:
|
||||
* Michael Lotz, mmlr@mlotz.ch
|
||||
* Alexander von Gluck IV, kallisti5@unixzen.com
|
||||
*/
|
||||
#ifndef INTEL_PORTS_H
|
||||
#define INTEL_PORTS_H
|
||||
|
||||
|
||||
#include <edid.h>
|
||||
|
||||
#include "intel_extreme.h"
|
||||
|
||||
#include "Pipes.h"
|
||||
#include "pll.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;
|
||||
|
||||
status_t SetPipe(Pipe* pipe);
|
||||
::Pipe* GetPipe()
|
||||
{ return fPipe; };
|
||||
|
||||
virtual status_t Power(bool enabled);
|
||||
|
||||
bool HasEDID();
|
||||
virtual status_t GetEDID(edid1_info* edid,
|
||||
bool forceRead = false);
|
||||
|
||||
virtual status_t GetPLLLimits(pll_limits& limits);
|
||||
|
||||
virtual status_t SetDisplayMode(display_mode* mode,
|
||||
uint32 colorMode) { return B_ERROR; };
|
||||
|
||||
virtual pipe_index PipePreference()
|
||||
{ return INTEL_PIPE_ANY; };
|
||||
|
||||
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);
|
||||
|
||||
display_mode fCurrentMode;
|
||||
Pipe* fPipe;
|
||||
|
||||
private:
|
||||
virtual addr_t _DDCRegister() = 0;
|
||||
virtual addr_t _PortRegister() = 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();
|
||||
|
||||
virtual status_t SetDisplayMode(display_mode* mode,
|
||||
uint32 colorMode);
|
||||
|
||||
protected:
|
||||
virtual addr_t _DDCRegister();
|
||||
virtual addr_t _PortRegister();
|
||||
};
|
||||
|
||||
|
||||
class LVDSPort : public Port {
|
||||
public:
|
||||
LVDSPort();
|
||||
|
||||
virtual uint32 Type() const
|
||||
{ return INTEL_PORT_TYPE_LVDS; }
|
||||
|
||||
virtual bool IsConnected();
|
||||
|
||||
virtual status_t SetDisplayMode(display_mode* mode,
|
||||
uint32 colorMode);
|
||||
|
||||
virtual pipe_index PipePreference()
|
||||
{ return INTEL_PIPE_B; };
|
||||
|
||||
protected:
|
||||
virtual addr_t _DDCRegister();
|
||||
virtual addr_t _PortRegister();
|
||||
};
|
||||
|
||||
|
||||
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();
|
||||
|
||||
virtual status_t SetDisplayMode(display_mode* mode,
|
||||
uint32 colorMode);
|
||||
|
||||
protected:
|
||||
virtual addr_t _DDCRegister();
|
||||
virtual addr_t _PortRegister();
|
||||
};
|
||||
|
||||
|
||||
class HDMIPort : public DigitalPort {
|
||||
public:
|
||||
HDMIPort(port_index index);
|
||||
|
||||
virtual uint32 Type() const
|
||||
{ return INTEL_PORT_TYPE_HDMI; }
|
||||
|
||||
virtual bool IsConnected();
|
||||
|
||||
protected:
|
||||
virtual addr_t _PortRegister();
|
||||
};
|
||||
|
||||
|
||||
class DisplayPort : public Port {
|
||||
public:
|
||||
DisplayPort(port_index index,
|
||||
const char* baseName = "DisplayPort");
|
||||
|
||||
virtual uint32 Type() const
|
||||
{ return INTEL_PORT_TYPE_DP; }
|
||||
|
||||
virtual bool IsConnected();
|
||||
|
||||
virtual status_t SetDisplayMode(display_mode* mode,
|
||||
uint32 colorMode);
|
||||
|
||||
protected:
|
||||
virtual addr_t _DDCRegister();
|
||||
virtual addr_t _PortRegister();
|
||||
};
|
||||
|
||||
|
||||
class EmbeddedDisplayPort : public DisplayPort {
|
||||
public:
|
||||
EmbeddedDisplayPort();
|
||||
|
||||
virtual uint32 Type() const
|
||||
{ return INTEL_PORT_TYPE_eDP; }
|
||||
|
||||
virtual bool IsConnected();
|
||||
};
|
||||
|
||||
|
||||
class DigitalDisplayInterface : public Port {
|
||||
public:
|
||||
DigitalDisplayInterface(
|
||||
port_index index = INTEL_PORT_A,
|
||||
const char* baseName = "Digital Display Interface");
|
||||
|
||||
virtual uint32 Type() const
|
||||
{ return INTEL_PORT_TYPE_DVI; }
|
||||
|
||||
virtual status_t Power(bool enabled);
|
||||
|
||||
virtual bool IsConnected();
|
||||
|
||||
virtual status_t SetDisplayMode(display_mode* mode,
|
||||
uint32 colorMode);
|
||||
|
||||
protected:
|
||||
virtual addr_t _DDCRegister();
|
||||
virtual addr_t _PortRegister();
|
||||
};
|
||||
|
||||
|
||||
#endif // INTEL_PORTS_H
|
||||
@@ -19,22 +19,25 @@
|
||||
#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__)
|
||||
|
||||
|
||||
struct accelerant_info* gInfo;
|
||||
uint32 gDumpCount;
|
||||
|
||||
|
||||
class AreaCloner {
|
||||
@@ -87,6 +90,36 @@ AreaCloner::Keep()
|
||||
// #pragma mark -
|
||||
|
||||
|
||||
// intel_reg --mmio=ie-0001.bin --devid=27a2 dump
|
||||
void
|
||||
dump_registers()
|
||||
{
|
||||
char filename[255];
|
||||
|
||||
sprintf(filename, "/boot/system/cache/tmp/ie-%04" B_PRId32 ".bin",
|
||||
gDumpCount);
|
||||
|
||||
ERROR("%s: Taking register dump #%" B_PRId32 "\n", __func__, gDumpCount);
|
||||
|
||||
int fd = open(filename, O_CREAT | O_WRONLY, 0644);
|
||||
uint32 data = 0;
|
||||
if (fd >= 0) {
|
||||
for (int32 i = 0; i < 0x80000; i += sizeof(data)) {
|
||||
//char line[512];
|
||||
//int length = sprintf(line, "%05" B_PRIx32 ": "
|
||||
// "%08" B_PRIx32 " %08" B_PRIx32 " %08" B_PRIx32 " %08" B_PRIx32 "\n",
|
||||
// i, read32(i), read32(i + 4), read32(i + 8), read32(i + 12));
|
||||
data = read32(i);
|
||||
write(fd, &data, sizeof(data));
|
||||
}
|
||||
close(fd);
|
||||
sync();
|
||||
}
|
||||
|
||||
gDumpCount++;
|
||||
}
|
||||
|
||||
|
||||
/*! This is the common accelerant_info initializer. It is called by
|
||||
both, the first accelerant and all clones.
|
||||
*/
|
||||
@@ -95,6 +128,9 @@ init_common(int device, bool isClone)
|
||||
{
|
||||
// initialize global accelerant info structure
|
||||
|
||||
// Number of register dumps we have... taken.
|
||||
gDumpCount = 0;
|
||||
|
||||
gInfo = (accelerant_info*)malloc(sizeof(accelerant_info));
|
||||
if (gInfo == NULL)
|
||||
return B_NO_MEMORY;
|
||||
@@ -147,7 +183,7 @@ init_common(int device, bool isClone)
|
||||
+ gInfo->shared_info->overlay_offset);
|
||||
}
|
||||
|
||||
if (gInfo->shared_info->device_type.InGroup(INTEL_TYPE_96x)) {
|
||||
if (gInfo->shared_info->device_type.InGroup(INTEL_GROUP_96x)) {
|
||||
// allocate some extra memory for the 3D context
|
||||
if (intel_allocate_memory(INTEL_i965_3D_CONTEXT_SIZE,
|
||||
B_APERTURE_NON_RESERVED, gInfo->context_base) == B_OK) {
|
||||
@@ -156,6 +192,26 @@ init_common(int device, bool isClone)
|
||||
}
|
||||
}
|
||||
|
||||
gInfo->pipe_count = 0;
|
||||
|
||||
// Allocate all of our pipes
|
||||
for (int i = 0; i < MAX_PIPES; i++) {
|
||||
switch (i) {
|
||||
case 0:
|
||||
gInfo->pipes[i] = new(std::nothrow) Pipe(INTEL_PIPE_A);
|
||||
break;
|
||||
case 1:
|
||||
gInfo->pipes[i] = new(std::nothrow) Pipe(INTEL_PIPE_B);
|
||||
break;
|
||||
default:
|
||||
ERROR("%s: Unknown pipe %d\n", __func__, i);
|
||||
}
|
||||
if (gInfo->pipes[i] == NULL)
|
||||
ERROR("%s: Error allocating pipe %d\n", __func__, i);
|
||||
else
|
||||
gInfo->pipe_count++;
|
||||
}
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
@@ -179,6 +235,200 @@ uninit_common(void)
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
dump_ports()
|
||||
{
|
||||
if (gInfo->port_count == 0) {
|
||||
TRACE("%s: No ports connected\n", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
TRACE("%s: Connected ports: (port_count: %" B_PRIu32 ")\n", __func__,
|
||||
gInfo->port_count);
|
||||
|
||||
for (uint32 i = 0; i < gInfo->port_count; i++) {
|
||||
Port* port = gInfo->ports[i];
|
||||
if (!port) {
|
||||
TRACE("port %" B_PRIu32 ":: INVALID ALLOC!\n", i);
|
||||
continue;
|
||||
}
|
||||
TRACE("port %" B_PRIu32 ": %s %s\n", i, port->PortName(),
|
||||
port->IsConnected() ? "connected" : "disconnected");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
static status_t
|
||||
probe_ports()
|
||||
{
|
||||
// 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().
|
||||
|
||||
TRACE("adpa: %08" B_PRIx32 "\n", read32(INTEL_ANALOG_PORT));
|
||||
TRACE("dova: %08" B_PRIx32 ", dovb: %08" B_PRIx32
|
||||
", dovc: %08" B_PRIx32 "\n", read32(INTEL_DIGITAL_PORT_A),
|
||||
read32(INTEL_DIGITAL_PORT_B), read32(INTEL_DIGITAL_PORT_C));
|
||||
TRACE("lvds: %08" B_PRIx32 "\n", read32(INTEL_DIGITAL_LVDS_PORT));
|
||||
|
||||
gInfo->port_count = 0;
|
||||
for (int i = INTEL_PORT_A; 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;
|
||||
}
|
||||
|
||||
// Digital Display Interface
|
||||
if (gInfo->shared_info->device_type.HasDDI()) {
|
||||
for (int i = INTEL_PORT_A; i <= INTEL_PORT_B; i++) {
|
||||
Port* ddiPort
|
||||
= new(std::nothrow) DigitalDisplayInterface((port_index)i);
|
||||
|
||||
if (ddiPort == NULL)
|
||||
return B_NO_MEMORY;
|
||||
|
||||
if (ddiPort->IsConnected())
|
||||
gInfo->ports[gInfo->port_count++] = ddiPort;
|
||||
else
|
||||
delete ddiPort;
|
||||
}
|
||||
}
|
||||
|
||||
// Ensure DP_A isn't already taken (or DDI)
|
||||
if (!has_connected_port((port_index)INTEL_PORT_A, INTEL_PORT_TYPE_ANY)) {
|
||||
// also always try eDP, it'll also just fail if not applicable
|
||||
Port* eDPPort = new(std::nothrow) EmbeddedDisplayPort();
|
||||
if (eDPPort == NULL)
|
||||
return B_NO_MEMORY;
|
||||
if (eDPPort->IsConnected())
|
||||
gInfo->ports[gInfo->port_count++] = eDPPort;
|
||||
else
|
||||
delete eDPPort;
|
||||
}
|
||||
|
||||
for (int i = INTEL_PORT_B; i <= INTEL_PORT_D; i++) {
|
||||
if (has_connected_port((port_index)i, INTEL_PORT_TYPE_ANY)) {
|
||||
// Ensure port not already claimed by something like DDI
|
||||
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_B_DIGITAL;
|
||||
} else
|
||||
delete lvdsPort;
|
||||
|
||||
// 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;
|
||||
|
||||
if (gInfo->port_count == 0)
|
||||
return B_ERROR;
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
static status_t
|
||||
assign_pipes()
|
||||
{
|
||||
// TODO: At some point we should "group" ports to pipes with the same mode.
|
||||
// You can drive multiple ports from a single pipe as long as the mode is
|
||||
// the same. For the moment we could get displays with the wrong pipes
|
||||
// assigned when the count is > 1;
|
||||
|
||||
uint32 current = 0;
|
||||
for (uint32 i = 0; i < gInfo->port_count; i++) {
|
||||
if (gInfo->ports[i] == NULL)
|
||||
continue;
|
||||
|
||||
pipe_index preference = gInfo->ports[i]->PipePreference();
|
||||
if (preference != INTEL_PIPE_ANY) {
|
||||
// Some ports *really* need to be assigned a pipe due to
|
||||
// implementation bugs.
|
||||
int index = (preference == INTEL_PIPE_B) ? 1 : 0;
|
||||
gInfo->ports[i]->SetPipe(gInfo->pipes[index]);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (gInfo->ports[i]->IsConnected()) {
|
||||
if (current >= gInfo->pipe_count) {
|
||||
ERROR("%s: No pipes left to assign to port %s!\n", __func__,
|
||||
gInfo->ports[i]->PortName());
|
||||
continue;
|
||||
}
|
||||
|
||||
gInfo->ports[i]->SetPipe(gInfo->pipes[current]);
|
||||
current++;
|
||||
}
|
||||
}
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark - public accelerant functions
|
||||
|
||||
|
||||
@@ -199,36 +449,22 @@ 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);
|
||||
// Probe all ports
|
||||
status = probe_ports();
|
||||
|
||||
// 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;
|
||||
}
|
||||
// On TRACE, dump ports and states
|
||||
dump_ports();
|
||||
|
||||
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));
|
||||
if (status != B_OK)
|
||||
ERROR("Warning: zero active displays were found!\n");
|
||||
|
||||
status = assign_pipes();
|
||||
|
||||
if (status != B_OK)
|
||||
ERROR("Warning: error while assigning pipes!\n");
|
||||
|
||||
status = create_mode_list();
|
||||
if (status != B_OK) {
|
||||
@@ -325,8 +561,22 @@ intel_get_accelerant_device_info(accelerant_device_info* info)
|
||||
CALLED();
|
||||
|
||||
info->version = B_ACCELERANT_VERSION;
|
||||
strcpy(info->name, gInfo->shared_info->device_type.InFamily(INTEL_TYPE_7xx)
|
||||
? "Intel Extreme Graphics 1" : "Intel Extreme Graphics 2");
|
||||
|
||||
DeviceType* type = &gInfo->shared_info->device_type;
|
||||
|
||||
if (type->InFamily(INTEL_FAMILY_7xx))
|
||||
strcpy(info->name, "Intel Extreme Graphics");
|
||||
else if (type->InFamily(INTEL_FAMILY_8xx))
|
||||
strcpy(info->name, "Intel Extreme Graphics 2");
|
||||
else if (type->InFamily(INTEL_FAMILY_9xx))
|
||||
strcpy(info->name, "Intel Graphics Media Accelerator");
|
||||
else if (type->InFamily(INTEL_FAMILY_SER5))
|
||||
strcpy(info->name, "Intel HD/Iris Graphics");
|
||||
else if (type->InFamily(INTEL_FAMILY_POVR))
|
||||
strcpy(info->name, "Intel PowerVR Graphics");
|
||||
else if (type->InFamily(INTEL_FAMILY_SOC0))
|
||||
strcpy(info->name, "Intel Atom Graphics");
|
||||
|
||||
strcpy(info->chipset, gInfo->shared_info->device_identifier);
|
||||
strcpy(info->serial_no, "None");
|
||||
|
||||
|
||||
@@ -14,6 +14,9 @@
|
||||
#include <edid.h>
|
||||
#include <video_overlay.h>
|
||||
|
||||
#include "Ports.h"
|
||||
#include "Pipes.h"
|
||||
|
||||
|
||||
struct overlay {
|
||||
overlay_buffer buffer;
|
||||
@@ -37,6 +40,8 @@ struct accelerant_info {
|
||||
intel_shared_info* shared_info;
|
||||
area_id shared_info_area;
|
||||
|
||||
display_mode current_mode; // pretty much a hack until per-display modes
|
||||
|
||||
display_mode* mode_list; // cloned list of standard display modes
|
||||
area_id mode_list_area;
|
||||
|
||||
@@ -48,6 +53,12 @@ struct accelerant_info {
|
||||
uint32 last_vertical_overlay_scale;
|
||||
uint32 overlay_position_buffer_offset;
|
||||
|
||||
uint32 port_count;
|
||||
Port* ports[MAX_PORTS];
|
||||
|
||||
uint32 pipe_count;
|
||||
Pipe* pipes[MAX_PIPES];
|
||||
|
||||
edid1_info edid_info;
|
||||
bool has_edid;
|
||||
|
||||
@@ -59,15 +70,15 @@ struct accelerant_info {
|
||||
int device;
|
||||
uint8 head_mode;
|
||||
bool is_clone;
|
||||
|
||||
// LVDS panel mode passed from the bios/startup.
|
||||
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;
|
||||
|
||||
@@ -89,6 +100,7 @@ write32(uint32 encodedRegister, uint32 value)
|
||||
+ REGISTER_REGISTER(encodedRegister)) = value;
|
||||
}
|
||||
|
||||
void dump_registers(void);
|
||||
|
||||
// dpms.cpp
|
||||
extern void enable_display_plane(bool enable);
|
||||
@@ -101,7 +113,6 @@ extern void setup_ring_buffer(ring_buffer &ringBuffer, const char* name);
|
||||
// modes.cpp
|
||||
extern void wait_for_vblank(void);
|
||||
extern void set_frame_buffer_base(void);
|
||||
extern void save_lvds_mode(void);
|
||||
extern status_t create_mode_list(void);
|
||||
|
||||
// memory.cpp
|
||||
|
||||
@@ -14,84 +14,32 @@
|
||||
#undef TRACE
|
||||
//#define TRACE_DPMS
|
||||
#ifdef TRACE_DPMS
|
||||
# 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__)
|
||||
|
||||
|
||||
void
|
||||
enable_display_plane(bool enable)
|
||||
{
|
||||
uint32 planeAControl = read32(INTEL_DISPLAY_A_CONTROL);
|
||||
uint32 planeBControl = read32(INTEL_DISPLAY_B_CONTROL);
|
||||
|
||||
if (enable) {
|
||||
// when enabling the display, the register values are updated
|
||||
// automatically
|
||||
if (gInfo->head_mode & HEAD_MODE_A_ANALOG) {
|
||||
write32(INTEL_DISPLAY_A_CONTROL,
|
||||
planeAControl | DISPLAY_CONTROL_ENABLED);
|
||||
}
|
||||
|
||||
if (gInfo->head_mode & HEAD_MODE_B_DIGITAL) {
|
||||
write32(INTEL_DISPLAY_B_CONTROL,
|
||||
planeBControl | DISPLAY_CONTROL_ENABLED);
|
||||
}
|
||||
|
||||
read32(INTEL_DISPLAY_A_BASE);
|
||||
// flush the eventually cached PCI bus writes
|
||||
} else {
|
||||
// when disabling it, we have to trigger the update using a write to
|
||||
// the display base address
|
||||
if (gInfo->head_mode & HEAD_MODE_A_ANALOG) {
|
||||
write32(INTEL_DISPLAY_A_CONTROL,
|
||||
planeAControl & ~DISPLAY_CONTROL_ENABLED);
|
||||
}
|
||||
|
||||
if (gInfo->head_mode & HEAD_MODE_B_DIGITAL) {
|
||||
write32(INTEL_DISPLAY_B_CONTROL,
|
||||
planeBControl & ~DISPLAY_CONTROL_ENABLED);
|
||||
}
|
||||
|
||||
set_frame_buffer_base();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
enable_display_pipe(bool enable)
|
||||
enable_all_pipes(bool enable)
|
||||
{
|
||||
uint32 pipeAControl = read32(INTEL_DISPLAY_A_PIPE_CONTROL);
|
||||
uint32 pipeBControl = read32(INTEL_DISPLAY_B_PIPE_CONTROL);
|
||||
// Go over each port and enable pipe/plane
|
||||
for (uint32 i = 0; i < gInfo->port_count; i++) {
|
||||
if (gInfo->ports[i] == NULL)
|
||||
continue;
|
||||
if (!gInfo->ports[i]->IsConnected())
|
||||
continue;
|
||||
|
||||
if (enable) {
|
||||
if (gInfo->head_mode & HEAD_MODE_A_ANALOG) {
|
||||
write32(INTEL_DISPLAY_A_PIPE_CONTROL,
|
||||
pipeAControl | DISPLAY_PIPE_ENABLED);
|
||||
}
|
||||
|
||||
if (gInfo->head_mode & HEAD_MODE_B_DIGITAL) {
|
||||
write32(INTEL_DISPLAY_B_PIPE_CONTROL,
|
||||
pipeBControl | DISPLAY_PIPE_ENABLED);
|
||||
}
|
||||
} else {
|
||||
if (gInfo->head_mode & HEAD_MODE_A_ANALOG) {
|
||||
write32(INTEL_DISPLAY_A_PIPE_CONTROL,
|
||||
pipeAControl & ~DISPLAY_PIPE_ENABLED);
|
||||
}
|
||||
|
||||
if (gInfo->head_mode & HEAD_MODE_B_DIGITAL) {
|
||||
write32(INTEL_DISPLAY_B_PIPE_CONTROL,
|
||||
pipeBControl & ~DISPLAY_PIPE_ENABLED);
|
||||
}
|
||||
gInfo->ports[i]->Power(enable);
|
||||
}
|
||||
|
||||
read32(INTEL_DISPLAY_A_BASE);
|
||||
// flush the eventually cached PCI bus writes
|
||||
// flush the possibly cached PCI bus writes
|
||||
|
||||
set_frame_buffer_base();
|
||||
}
|
||||
|
||||
|
||||
@@ -99,10 +47,6 @@ static void
|
||||
enable_lvds_panel(bool enable)
|
||||
{
|
||||
bool hasPCH = gInfo->shared_info->device_type.HasPlatformControlHub();
|
||||
if (hasPCH) {
|
||||
// TODO: fix for PCH
|
||||
return;
|
||||
}
|
||||
|
||||
int controlRegister = hasPCH ? PCH_PANEL_CONTROL : INTEL_PANEL_CONTROL;
|
||||
int statusRegister = hasPCH ? PCH_PANEL_STATUS : INTEL_PANEL_STATUS;
|
||||
@@ -166,8 +110,7 @@ set_display_power_mode(uint32 mode)
|
||||
spin(150);
|
||||
}
|
||||
|
||||
enable_display_pipe(true);
|
||||
enable_display_plane(true);
|
||||
enable_all_pipes(true);
|
||||
}
|
||||
|
||||
wait_for_vblank();
|
||||
@@ -188,25 +131,21 @@ 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?
|
||||
}
|
||||
|
||||
if (mode != B_DPMS_ON) {
|
||||
enable_display_plane(false);
|
||||
wait_for_vblank();
|
||||
enable_display_pipe(false);
|
||||
}
|
||||
if (mode != B_DPMS_ON)
|
||||
enable_all_pipes(false);
|
||||
|
||||
if (mode == B_DPMS_OFF) {
|
||||
write32(INTEL_DISPLAY_A_PLL, read32(INTEL_DISPLAY_A_PLL)
|
||||
|
||||
@@ -17,12 +17,12 @@
|
||||
#undef TRACE
|
||||
//#define TRACE_ENGINE
|
||||
#ifdef TRACE_ENGINE
|
||||
# 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__)
|
||||
|
||||
|
||||
|
||||
@@ -111,15 +111,15 @@ get_accelerant_hook(uint32 feature, void* data)
|
||||
return (void*)intel_overlay_supported_features;
|
||||
case B_ALLOCATE_OVERLAY_BUFFER:
|
||||
// TODO: overlay doesn't seem to work on these chips
|
||||
if (gInfo->shared_info->device_type.InGroup(INTEL_TYPE_91x)
|
||||
|| gInfo->shared_info->device_type.InGroup(INTEL_TYPE_94x)
|
||||
|| gInfo->shared_info->device_type.IsModel(INTEL_TYPE_965M)
|
||||
|| gInfo->shared_info->device_type.InGroup(INTEL_TYPE_G4x)
|
||||
|| gInfo->shared_info->device_type.InGroup(INTEL_TYPE_IGD)
|
||||
|| gInfo->shared_info->device_type.InGroup(INTEL_TYPE_ILK)
|
||||
|| gInfo->shared_info->device_type.InGroup(INTEL_TYPE_SNB)
|
||||
|| gInfo->shared_info->device_type.InGroup(INTEL_TYPE_IVB)
|
||||
|| gInfo->shared_info->device_type.InGroup(INTEL_TYPE_VLV))
|
||||
if (gInfo->shared_info->device_type.InGroup(INTEL_GROUP_91x)
|
||||
|| gInfo->shared_info->device_type.InGroup(INTEL_GROUP_94x)
|
||||
|| gInfo->shared_info->device_type.IsModel(INTEL_MODEL_965M)
|
||||
|| gInfo->shared_info->device_type.InGroup(INTEL_GROUP_G4x)
|
||||
|| gInfo->shared_info->device_type.InGroup(INTEL_GROUP_PIN)
|
||||
|| gInfo->shared_info->device_type.InGroup(INTEL_GROUP_ILK)
|
||||
|| gInfo->shared_info->device_type.InFamily(INTEL_FAMILY_SER5)
|
||||
|| gInfo->shared_info->device_type.InFamily(INTEL_FAMILY_POVR)
|
||||
|| gInfo->shared_info->device_type.InFamily(INTEL_FAMILY_SOC0))
|
||||
return NULL;
|
||||
|
||||
return (void*)intel_allocate_overlay_buffer;
|
||||
|
||||
Executable → Regular
+205
-820
File diff suppressed because it is too large
Load Diff
@@ -25,12 +25,12 @@
|
||||
#undef TRACE
|
||||
//#define TRACE_OVERLAY
|
||||
#ifdef TRACE_OVERLAY
|
||||
# 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__)
|
||||
|
||||
|
||||
@@ -207,7 +207,7 @@ set_color_key(uint8 red, uint8 green, uint8 blue, uint8 redMask,
|
||||
static void
|
||||
set_color_key(const overlay_window* window)
|
||||
{
|
||||
switch (gInfo->shared_info->current_mode.space) {
|
||||
switch (gInfo->current_mode.space) {
|
||||
case B_CMAP8:
|
||||
set_color_key(0, 0, window->blue.value, 0x0, 0x0, 0xff);
|
||||
break;
|
||||
@@ -235,7 +235,7 @@ static void
|
||||
update_overlay(bool updateCoefficients)
|
||||
{
|
||||
if (!gInfo->shared_info->overlay_active
|
||||
|| gInfo->shared_info->device_type.InGroup(INTEL_TYPE_965))
|
||||
|| gInfo->shared_info->device_type.IsModel(INTEL_MODEL_965))
|
||||
return;
|
||||
|
||||
QueueCommands queue(gInfo->shared_info->primary_ring_buffer);
|
||||
@@ -259,7 +259,7 @@ static void
|
||||
show_overlay(void)
|
||||
{
|
||||
if (gInfo->shared_info->overlay_active
|
||||
|| gInfo->shared_info->device_type.InGroup(INTEL_TYPE_965))
|
||||
|| gInfo->shared_info->device_type.IsModel(INTEL_MODEL_965))
|
||||
return;
|
||||
|
||||
gInfo->shared_info->overlay_active = true;
|
||||
@@ -281,7 +281,7 @@ static void
|
||||
hide_overlay(void)
|
||||
{
|
||||
if (!gInfo->shared_info->overlay_active
|
||||
|| gInfo->shared_info->device_type.InGroup(INTEL_TYPE_965))
|
||||
|| gInfo->shared_info->device_type.IsModel(INTEL_MODEL_965))
|
||||
return;
|
||||
|
||||
overlay_registers* registers = gInfo->overlay_registers;
|
||||
@@ -327,7 +327,7 @@ intel_overlay_supported_spaces(const display_mode* mode)
|
||||
static const uint32 kSupportedi965Spaces[] = {B_YCbCr422, 0};
|
||||
intel_shared_info &sharedInfo = *gInfo->shared_info;
|
||||
|
||||
if (sharedInfo.device_type.InGroup(INTEL_TYPE_96x))
|
||||
if (sharedInfo.device_type.InGroup(INTEL_GROUP_96x))
|
||||
return kSupportedi965Spaces;
|
||||
|
||||
return kSupportedSpaces;
|
||||
@@ -380,7 +380,7 @@ intel_allocate_overlay_buffer(color_space colorSpace, uint16 width,
|
||||
// alloc graphics mem
|
||||
|
||||
int32 alignment = 0x3f;
|
||||
if (sharedInfo.device_type.InGroup(INTEL_TYPE_965))
|
||||
if (sharedInfo.device_type.IsModel(INTEL_MODEL_965))
|
||||
alignment = 0xff;
|
||||
|
||||
overlay_buffer* buffer = &overlay->buffer;
|
||||
@@ -396,7 +396,7 @@ intel_allocate_overlay_buffer(color_space colorSpace, uint16 width,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (sharedInfo.device_type.InGroup(INTEL_TYPE_965)) {
|
||||
if (sharedInfo.device_type.IsModel(INTEL_MODEL_965)) {
|
||||
status = intel_allocate_memory(INTEL_i965_OVERLAY_STATE_SIZE,
|
||||
B_APERTURE_NON_RESERVED, overlay->state_base);
|
||||
if (status < B_OK) {
|
||||
@@ -437,7 +437,7 @@ intel_release_overlay_buffer(const overlay_buffer* buffer)
|
||||
hide_overlay();
|
||||
|
||||
intel_free_memory(overlay->buffer_base);
|
||||
if (gInfo->shared_info->device_type.InGroup(INTEL_TYPE_965))
|
||||
if (gInfo->shared_info->device_type.IsModel(INTEL_MODEL_965))
|
||||
intel_free_memory(overlay->state_base);
|
||||
free(overlay);
|
||||
|
||||
@@ -589,10 +589,10 @@ intel_configure_overlay(overlay_token overlayToken,
|
||||
left = 0;
|
||||
if (top < 0)
|
||||
top = 0;
|
||||
if (right > gInfo->shared_info->current_mode.timing.h_display)
|
||||
right = gInfo->shared_info->current_mode.timing.h_display;
|
||||
if (bottom > gInfo->shared_info->current_mode.timing.v_display)
|
||||
bottom = gInfo->shared_info->current_mode.timing.v_display;
|
||||
if (right > gInfo->current_mode.timing.h_display)
|
||||
right = gInfo->current_mode.timing.h_display;
|
||||
if (bottom > gInfo->current_mode.timing.v_display)
|
||||
bottom = gInfo->current_mode.timing.v_display;
|
||||
if (left >= right || top >= bottom) {
|
||||
// overlay is not within visible bounds
|
||||
hide_overlay();
|
||||
@@ -630,7 +630,7 @@ intel_configure_overlay(overlay_token overlayToken,
|
||||
// the result will be wrong, too.
|
||||
registers->source_width_rgb = right - left;
|
||||
registers->source_height_rgb = bottom - top;
|
||||
if (gInfo->shared_info->device_type.InFamily(INTEL_TYPE_8xx)) {
|
||||
if (gInfo->shared_info->device_type.InFamily(INTEL_FAMILY_8xx)) {
|
||||
registers->source_bytes_per_row_rgb = (((overlay->buffer_offset
|
||||
+ (view->width << 1) + 0x1f) >> 5)
|
||||
- (overlay->buffer_offset >> 5) - 1) << 2;
|
||||
|
||||
@@ -0,0 +1,279 @@
|
||||
/*
|
||||
* Copyright 2006-2015, Haiku, Inc. All Rights Reserved.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*
|
||||
* Authors:
|
||||
* Axel Dörfler, axeld@pinc-software.de
|
||||
* Alexander von Gluck IV, kallisti5@unixzen.com
|
||||
*/
|
||||
|
||||
|
||||
#include "pll.h"
|
||||
|
||||
#include <math.h>
|
||||
#include <stdio.h>
|
||||
#include <string.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"
|
||||
#include "utility.h"
|
||||
|
||||
|
||||
#undef TRACE
|
||||
#define TRACE_MODE
|
||||
#ifdef TRACE_MODE
|
||||
# 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__)
|
||||
|
||||
|
||||
void
|
||||
get_pll_limits(pll_limits* limits, bool isLVDS)
|
||||
{
|
||||
// Note, the limits are taken from the X driver; they have not yet been
|
||||
// tested
|
||||
|
||||
// TODO: Breakout BXT
|
||||
|
||||
if (gInfo->shared_info->device_type.InGroup(INTEL_GROUP_CHV)) {
|
||||
pll_limits kLimits = {
|
||||
// p, p1, p2, high, n, m, m1, m2
|
||||
{ 5, 2, 14, false, 1, 79, 2, 24 << 22}, // min
|
||||
{ 80, 4, 1, true, 1, 127, 2, 175 << 22}, // max
|
||||
225000, 4800000, 6480000
|
||||
};
|
||||
memcpy(limits, &kLimits, sizeof(pll_limits));
|
||||
} else if (gInfo->shared_info->device_type.InGroup(INTEL_GROUP_VLV)) {
|
||||
pll_limits kLimits = {
|
||||
// p, p1, p2, high, n, m, m1, m2
|
||||
{ 5, 2, 20, false, 1, 79, 2, 11}, // min
|
||||
{ 80, 3, 2, true, 7, 127, 3, 156}, // max
|
||||
225000, 4000000, 6000000
|
||||
};
|
||||
memcpy(limits, &kLimits, sizeof(pll_limits));
|
||||
} else if (gInfo->shared_info->device_type.InFamily(INTEL_FAMILY_SER5)
|
||||
|| gInfo->shared_info->device_type.InGroup(INTEL_GROUP_BXT)) {
|
||||
pll_limits kLimits = {
|
||||
// p, p1, p2, high, n, m, m1, m2
|
||||
{ 5, 1, 10, false, 1, 79, 12, 5}, // min
|
||||
{ 80, 8, 5, true, 5, 127, 22, 9}, // max
|
||||
225000, 1760000, 3510000
|
||||
};
|
||||
// TODO: validate these LVDS dividers!
|
||||
if (isLVDS) {
|
||||
kLimits.min.post = 7;
|
||||
kLimits.max.post = 98;
|
||||
kLimits.min.post2 = 14;
|
||||
kLimits.max.post2 = 7;
|
||||
}
|
||||
memcpy(limits, &kLimits, sizeof(pll_limits));
|
||||
} else if (gInfo->shared_info->device_type.InFamily(INTEL_FAMILY_9xx)) {
|
||||
pll_limits kLimits = {
|
||||
// p, p1, p2, high, n, m, m1, m2
|
||||
{ 5, 1, 10, false, 1, 70, 8, 3}, // min
|
||||
{ 80, 8, 5, true, 6, 120, 18, 7}, // max
|
||||
200000, 1400000, 2800000
|
||||
};
|
||||
if (isLVDS) {
|
||||
kLimits.min.post = 7;
|
||||
kLimits.max.post = 98;
|
||||
kLimits.min.post2 = 14;
|
||||
kLimits.max.post2 = 7;
|
||||
}
|
||||
memcpy(limits, &kLimits, sizeof(pll_limits));
|
||||
} else if (gInfo->shared_info->device_type.InGroup(INTEL_GROUP_G4x)) {
|
||||
pll_limits kLimits = {
|
||||
// p, p1, p2, high, n, m, m1, m2
|
||||
{ 10, 1, 10, false, 1, 104, 17, 5}, // min
|
||||
{ 30, 3, 10, true, 4, 138, 23, 11}, // max
|
||||
270000, 1750000, 3500000
|
||||
};
|
||||
// TODO: validate these LVDS dividers!
|
||||
if (isLVDS) {
|
||||
kLimits.min.post = 7;
|
||||
kLimits.max.post = 98;
|
||||
kLimits.min.post2 = 14;
|
||||
kLimits.max.post2 = 7;
|
||||
}
|
||||
memcpy(limits, &kLimits, sizeof(pll_limits));
|
||||
} else if (gInfo->shared_info->device_type.InGroup(INTEL_GROUP_PIN)) {
|
||||
// m1 is reserved and must be 0
|
||||
pll_limits kLimits = {
|
||||
// p, p1, p2, high, n, m, m1, m2
|
||||
{ 5, 1, 10, false, 3, 2, 0, 2}, // min
|
||||
{ 80, 8, 5, true, 6, 256, 0, 254}, // max
|
||||
200000, 1700000, 3500000
|
||||
};
|
||||
if (isLVDS) {
|
||||
kLimits.min.post = 7;
|
||||
kLimits.max.post = 112;
|
||||
kLimits.min.post2 = 14;
|
||||
kLimits.max.post2 = 14;
|
||||
}
|
||||
memcpy(limits, &kLimits, sizeof(pll_limits));
|
||||
} else {
|
||||
static pll_limits kLimits = {
|
||||
// p, p1, p2, high, n, m, m1, m2
|
||||
{ 4, 2, 4, false, 5, 96, 20, 8},
|
||||
{128, 33, 2, true, 18, 140, 28, 18},
|
||||
165000, 930000, 1400000
|
||||
};
|
||||
// TODO: Validate these LVDS dividers!
|
||||
if (isLVDS) {
|
||||
kLimits.min.post = 7;
|
||||
kLimits.max.post = 98;
|
||||
kLimits.min.post2 = 14;
|
||||
kLimits.max.post2 = 7;
|
||||
}
|
||||
memcpy(limits, &kLimits, sizeof(pll_limits));
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
valid_pll_divisors(pll_divisors* divisors, pll_limits* limits)
|
||||
{
|
||||
pll_info &info = gInfo->shared_info->pll_info;
|
||||
uint32 vco = info.reference_frequency * divisors->m / divisors->n;
|
||||
uint32 frequency = vco / divisors->post;
|
||||
|
||||
if (divisors->post < limits->min.post || divisors->post > limits->max.post
|
||||
|| divisors->m < limits->min.m || divisors->m > limits->max.m
|
||||
|| vco < limits->min_vco || vco > limits->max_vco
|
||||
|| frequency < info.min_frequency || frequency > info.max_frequency)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
static uint32
|
||||
compute_pll_m(pll_divisors* divisors)
|
||||
{
|
||||
if (gInfo->shared_info->device_type.InGroup(INTEL_GROUP_CHV)
|
||||
|| gInfo->shared_info->device_type.InGroup(INTEL_GROUP_VLV)) {
|
||||
return divisors->m1 * divisors->m2;
|
||||
}
|
||||
|
||||
// Pineview, m1 is reserved
|
||||
if (gInfo->shared_info->device_type.InGroup(INTEL_GROUP_PIN))
|
||||
return divisors->m2 + 2;
|
||||
|
||||
if (gInfo->shared_info->device_type.Generation() >= 3)
|
||||
return 5 * (divisors->m1 + 2) + (divisors->m2 + 2);
|
||||
|
||||
// TODO: This logic needs validated... PLL's were calculated differently
|
||||
// on 8xx chipsets
|
||||
|
||||
return 5 * divisors->m1 + divisors->m2;
|
||||
}
|
||||
|
||||
|
||||
static uint32
|
||||
compute_pll_p(pll_divisors* divisors)
|
||||
{
|
||||
return divisors->post1 * divisors->post2;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
compute_pll_divisors(display_mode* current, pll_divisors* divisors,
|
||||
bool isLVDS)
|
||||
{
|
||||
float requestedPixelClock = current->timing.pixel_clock / 1000.0f;
|
||||
float referenceClock
|
||||
= gInfo->shared_info->pll_info.reference_frequency / 1000.0f;
|
||||
pll_limits limits;
|
||||
get_pll_limits(&limits, isLVDS);
|
||||
|
||||
TRACE("%s: required MHz: %g\n", __func__, requestedPixelClock);
|
||||
|
||||
// Calculate p2
|
||||
if (isLVDS) {
|
||||
if (requestedPixelClock > 112.999
|
||||
|| (read32(INTEL_DIGITAL_LVDS_PORT) & LVDS_CLKB_POWER_MASK)
|
||||
== LVDS_CLKB_POWER_UP) {
|
||||
// fast DAC timing via 2 channels
|
||||
divisors->post2 = limits.max.post2;
|
||||
divisors->post2_high = limits.max.post2_high;
|
||||
} else {
|
||||
// slow DAC timing
|
||||
divisors->post2 = limits.min.post2;
|
||||
divisors->post2_high = limits.min.post2_high;
|
||||
}
|
||||
} else {
|
||||
if (current->timing.pixel_clock < limits.min_post2_frequency) {
|
||||
// slow DAC timing
|
||||
divisors->post2 = limits.min.post2;
|
||||
divisors->post2_high = limits.min.post2_high;
|
||||
} else {
|
||||
// fast DAC timing
|
||||
divisors->post2 = limits.max.post2;
|
||||
divisors->post2_high = limits.max.post2_high;
|
||||
}
|
||||
}
|
||||
|
||||
float best = requestedPixelClock;
|
||||
pll_divisors bestDivisors;
|
||||
|
||||
bool is_pine = gInfo->shared_info->device_type.InGroup(INTEL_GROUP_PIN);
|
||||
for (divisors->m1 = limits.min.m1; divisors->m1 <= limits.max.m1;
|
||||
divisors->m1++) {
|
||||
for (divisors->m2 = limits.min.m2; divisors->m2 <= limits.max.m2
|
||||
&& ((divisors->m2 < divisors->m1) || is_pine); divisors->m2++) {
|
||||
for (divisors->n = limits.min.n; divisors->n <= limits.max.n;
|
||||
divisors->n++) {
|
||||
for (divisors->post1 = limits.min.post1;
|
||||
divisors->post1 <= limits.max.post1; divisors->post1++) {
|
||||
divisors->m = compute_pll_m(divisors);
|
||||
divisors->post = compute_pll_p(divisors);
|
||||
|
||||
if (!valid_pll_divisors(divisors, &limits))
|
||||
continue;
|
||||
|
||||
float error = fabs(requestedPixelClock
|
||||
- ((referenceClock * divisors->m) / divisors->n)
|
||||
/ divisors->post);
|
||||
if (error < best) {
|
||||
best = error;
|
||||
bestDivisors = *divisors;
|
||||
|
||||
if (error == 0)
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
*divisors = bestDivisors;
|
||||
|
||||
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);
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* Copyright 2006-2015, Haiku, Inc. All Rights Reserved.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*
|
||||
* Authors:
|
||||
* Axel Dörfler, axeld@pinc-software.de
|
||||
* Alexander von Gluck IV, kallisti5@unixzen.com
|
||||
*/
|
||||
#ifndef INTEL_EXTREME_PLL_H
|
||||
#define INTEL_EXTREME_PLL_H
|
||||
|
||||
|
||||
#include "intel_extreme.h"
|
||||
|
||||
|
||||
struct pll_divisors {
|
||||
uint32 post;
|
||||
uint32 post1;
|
||||
uint32 post2;
|
||||
bool post2_high;
|
||||
uint32 n;
|
||||
uint32 m;
|
||||
uint32 m1;
|
||||
uint32 m2;
|
||||
};
|
||||
|
||||
struct pll_limits {
|
||||
pll_divisors min;
|
||||
pll_divisors max;
|
||||
uint32 min_post2_frequency;
|
||||
uint32 min_vco;
|
||||
uint32 max_vco;
|
||||
};
|
||||
|
||||
|
||||
void get_pll_limits(pll_limits* limits, bool isLVDS);
|
||||
bool valid_pll_divisors(pll_divisors* divisors, pll_limits* limits);
|
||||
void compute_pll_divisors(display_mode* current, pll_divisors* divisors,
|
||||
bool isLVDS);
|
||||
|
||||
|
||||
#endif /* INTEL_EXTREME_PLL_H */
|
||||
@@ -21,13 +21,16 @@
|
||||
#include <KernelExport.h>
|
||||
#include <PCI.h>
|
||||
|
||||
#include <new>
|
||||
|
||||
//#define TRACE_INTEL
|
||||
|
||||
#define TRACE_INTEL
|
||||
#ifdef TRACE_INTEL
|
||||
# define TRACE(x...) dprintf("\33[33magp-intel:\33[0m " x)
|
||||
# define TRACE(x...) dprintf("intel_gart: " x)
|
||||
#else
|
||||
# define TRACE(x...) ;
|
||||
#endif
|
||||
#define ERROR(x...) dprintf("intel_gart: " x)
|
||||
|
||||
#ifndef __HAIKU__
|
||||
# define B_KERNEL_READ_AREA 0
|
||||
@@ -47,93 +50,95 @@
|
||||
(*((volatile uint32*)(address)))
|
||||
|
||||
|
||||
// PCI "Host bridge" is most cases :-)
|
||||
const struct supported_device {
|
||||
uint32 bridge_id;
|
||||
uint32 display_id;
|
||||
uint32 type;
|
||||
int32 type;
|
||||
const char *name;
|
||||
} kSupportedDevices[] = {
|
||||
{0x3575, 0x3577, INTEL_TYPE_83x, "i830GM"},
|
||||
{0x2560, 0x2562, INTEL_TYPE_83x, "i845G"},
|
||||
{0x3580, 0x3582, INTEL_TYPE_85x, "i855G"},
|
||||
{0x358c, 0x358e, INTEL_TYPE_85x, "i855G"},
|
||||
{0x2570, 0x2572, INTEL_TYPE_85x, "i865G"},
|
||||
{0x3575, 0x3577, INTEL_GROUP_83x, "i830GM"},
|
||||
{0x2560, 0x2562, INTEL_GROUP_83x, "i845G"},
|
||||
{0x3580, 0x3582, INTEL_GROUP_85x, "i855G"},
|
||||
{0x358c, 0x358e, INTEL_GROUP_85x, "i855G"},
|
||||
{0x2570, 0x2572, INTEL_GROUP_85x, "i865G"},
|
||||
|
||||
// {0x2792, INTEL_TYPE_91x, "i910"},
|
||||
// {0x258a, INTEL_TYPE_91x, "i915"},
|
||||
{0x2580, 0x2582, INTEL_TYPE_915, "i915G"},
|
||||
{0x2590, 0x2592, INTEL_TYPE_915M, "i915GM"},
|
||||
{0x2770, 0x2772, INTEL_TYPE_945, "i945G"},
|
||||
{0x27a0, 0x27a2, INTEL_TYPE_945M, "i945GM"},
|
||||
{0x27ac, 0x27ae, INTEL_TYPE_945M, "i945GME"},
|
||||
// {0x2792, INTEL_GROUP_91x, "i910"},
|
||||
// {0x258a, INTEL_GROUP_91x, "i915"},
|
||||
{0x2580, 0x2582, INTEL_MODEL_915, "i915G"},
|
||||
{0x2590, 0x2592, INTEL_MODEL_915M, "i915GM"},
|
||||
{0x2770, 0x2772, INTEL_MODEL_945, "i945G"},
|
||||
{0x27a0, 0x27a2, INTEL_MODEL_945M, "i945GM"},
|
||||
{0x27ac, 0x27ae, INTEL_MODEL_945M, "i945GME"},
|
||||
|
||||
{0x2970, 0x2972, INTEL_TYPE_965, "i946GZ"},
|
||||
{0x2980, 0x2982, INTEL_TYPE_965, "G35"},
|
||||
{0x2990, 0x2992, INTEL_TYPE_965, "i965Q"},
|
||||
{0x29a0, 0x29a2, INTEL_TYPE_965, "i965G"},
|
||||
{0x2a00, 0x2a02, INTEL_TYPE_965, "i965GM"},
|
||||
{0x2a10, 0x2a12, INTEL_TYPE_965, "i965GME"},
|
||||
{0x2970, 0x2972, INTEL_MODEL_965, "i946GZ"},
|
||||
{0x2980, 0x2982, INTEL_MODEL_965, "G35"},
|
||||
{0x2990, 0x2992, INTEL_MODEL_965, "i965Q"},
|
||||
{0x29a0, 0x29a2, INTEL_MODEL_965, "i965G"},
|
||||
{0x2a00, 0x2a02, INTEL_MODEL_965, "i965GM"},
|
||||
{0x2a10, 0x2a12, INTEL_MODEL_965, "i965GME"},
|
||||
|
||||
{0x29b0, 0x29b2, INTEL_TYPE_G33, "G33"},
|
||||
{0x29c0, 0x29c2, INTEL_TYPE_G33, "Q35"},
|
||||
{0x29d0, 0x29d2, INTEL_TYPE_G33, "Q33"},
|
||||
{0x29b0, 0x29b2, INTEL_MODEL_G33, "G33"},
|
||||
{0x29c0, 0x29c2, INTEL_MODEL_G33, "Q35"},
|
||||
{0x29d0, 0x29d2, INTEL_MODEL_G33, "Q33"},
|
||||
|
||||
{0x2a40, 0x2a42, INTEL_TYPE_GM45, "GM45"},
|
||||
{0x2e00, 0x2e02, INTEL_TYPE_G45, "IGD"},
|
||||
{0x2e10, 0x2e12, INTEL_TYPE_G45, "Q45"},
|
||||
{0x2e20, 0x2e22, INTEL_TYPE_G45, "G45"},
|
||||
{0x2e30, 0x2e32, INTEL_TYPE_G45, "G41"},
|
||||
{0x2e40, 0x2e42, INTEL_TYPE_G45, "B43"},
|
||||
{0x2e90, 0x2e92, INTEL_TYPE_G45, "B43"},
|
||||
{0x2a40, 0x2a42, INTEL_MODEL_GM45, "GM45"},
|
||||
{0x2e00, 0x2e02, INTEL_MODEL_G45, "IGD"},
|
||||
{0x2e10, 0x2e12, INTEL_MODEL_G45, "Q45"},
|
||||
{0x2e20, 0x2e22, INTEL_MODEL_G45, "G45"},
|
||||
{0x2e30, 0x2e32, INTEL_MODEL_G45, "G41"},
|
||||
{0x2e40, 0x2e42, INTEL_MODEL_G45, "B43"},
|
||||
{0x2e90, 0x2e92, INTEL_MODEL_G45, "B43"},
|
||||
|
||||
{0xa000, 0xa001, INTEL_TYPE_IGDG, "Atom_Dx10"},
|
||||
{0xa010, 0xa011, INTEL_TYPE_IGDGM, "Atom_N4x0"},
|
||||
{0xa000, 0xa001, INTEL_MODEL_PINE, "Atom_Dx10"},
|
||||
{0xa010, 0xa011, INTEL_MODEL_PINEM, "Atom_N4x0"},
|
||||
|
||||
{0x0040, 0x0042, INTEL_TYPE_ILKG, "IronLake Desktop"},
|
||||
{0x0044, 0x0046, INTEL_TYPE_ILKGM, "IronLake Mobile"},
|
||||
{0x0062, 0x0046, INTEL_TYPE_ILKGM, "IronLake Mobile"},
|
||||
{0x006a, 0x0046, INTEL_TYPE_ILKGM, "IronLake Mobile"},
|
||||
{0x0040, 0x0042, INTEL_MODEL_ILKG, "IronLake Desktop"},
|
||||
{0x0044, 0x0046, INTEL_MODEL_ILKGM, "IronLake Mobile"},
|
||||
{0x0062, 0x0046, INTEL_MODEL_ILKGM, "IronLake Mobile"},
|
||||
{0x006a, 0x0046, INTEL_MODEL_ILKGM, "IronLake Mobile"},
|
||||
|
||||
{0x0100, 0x0102, INTEL_TYPE_SNBG, "SandyBridge Desktop GT1"},
|
||||
{0x0100, 0x0112, INTEL_TYPE_SNBG, "SandyBridge Desktop GT2"},
|
||||
{0x0100, 0x0122, INTEL_TYPE_SNBG, "SandyBridge Desktop GT2+"},
|
||||
{0x0104, 0x0106, INTEL_TYPE_SNBGM, "SandyBridge Mobile GT1"},
|
||||
{0x0104, 0x0116, INTEL_TYPE_SNBGM, "SandyBridge Mobile GT2"},
|
||||
{0x0104, 0x0126, INTEL_TYPE_SNBGM, "SandyBridge Mobile GT2+"},
|
||||
{0x0108, 0x010a, INTEL_TYPE_SNBGS, "SandyBridge Server"},
|
||||
{0x0100, 0x0102, INTEL_MODEL_SNBG, "SandyBridge Desktop GT1"},
|
||||
{0x0100, 0x0112, INTEL_MODEL_SNBG, "SandyBridge Desktop GT2"},
|
||||
{0x0100, 0x0122, INTEL_MODEL_SNBG, "SandyBridge Desktop GT2+"},
|
||||
{0x0104, 0x0106, INTEL_MODEL_SNBGM, "SandyBridge Mobile GT1"},
|
||||
{0x0104, 0x0116, INTEL_MODEL_SNBGM, "SandyBridge Mobile GT2"},
|
||||
{0x0104, 0x0126, INTEL_MODEL_SNBGM, "SandyBridge Mobile GT2+"},
|
||||
{0x0108, 0x010a, INTEL_MODEL_SNBGS, "SandyBridge Server"},
|
||||
|
||||
{0x0150, 0x0152, INTEL_TYPE_IVBG, "IvyBridge Desktop GT1"},
|
||||
{0x0150, 0x0162, INTEL_TYPE_IVBG, "IvyBridge Desktop GT2"},
|
||||
{0x0154, 0x0156, INTEL_TYPE_IVBGM, "IvyBridge Mobile GT1"},
|
||||
{0x0154, 0x0166, INTEL_TYPE_IVBGM, "IvyBridge Mobile GT2"},
|
||||
{0x0158, 0x015a, INTEL_TYPE_IVBGS, "IvyBridge Server GT1"},
|
||||
{0x0158, 0x016a, INTEL_TYPE_IVBGS, "IvyBridge Server GT2"},
|
||||
{0x0150, 0x0152, INTEL_MODEL_IVBG, "IvyBridge Desktop GT1"},
|
||||
{0x0150, 0x0162, INTEL_MODEL_IVBG, "IvyBridge Desktop GT2"},
|
||||
{0x0154, 0x0156, INTEL_MODEL_IVBGM, "IvyBridge Mobile GT1"},
|
||||
{0x0154, 0x0166, INTEL_MODEL_IVBGM, "IvyBridge Mobile GT2"},
|
||||
{0x0158, 0x015a, INTEL_MODEL_IVBGS, "IvyBridge Server GT1"},
|
||||
{0x0158, 0x016a, INTEL_MODEL_IVBGS, "IvyBridge Server GT2"},
|
||||
|
||||
{0x0c00, 0x0412, INTEL_TYPE_IVBG, "Haswell Desktop"},
|
||||
{0x0c04, 0x0416, INTEL_TYPE_IVBGM, "Haswell Mobile"},
|
||||
{0x0d04, 0x0d26, INTEL_TYPE_IVBGM, "Haswell Mobile"},
|
||||
{0x0c00, 0x0412, INTEL_MODEL_HAS, "Haswell Desktop"},
|
||||
{0x0c04, 0x0416, INTEL_MODEL_HASM, "Haswell Mobile"},
|
||||
{0x0d04, 0x0d26, INTEL_MODEL_HASM, "Haswell Mobile"},
|
||||
{0x0a04, 0x0a16, INTEL_MODEL_HASM, "Haswell Mobile"},
|
||||
|
||||
// XXX: 0x0f00 only confirmed on 0x0f30, 0x0f31
|
||||
{0x0f00, 0x0155, INTEL_TYPE_VLVG, "ValleyView Desktop"},
|
||||
{0x0f00, 0x0f30, INTEL_TYPE_VLVGM, "ValleyView Mobile"},
|
||||
{0x0f00, 0x0f31, INTEL_TYPE_VLVGM, "ValleyView Mobile"},
|
||||
{0x0f00, 0x0f32, INTEL_TYPE_VLVGM, "ValleyView Mobile"},
|
||||
{0x0f00, 0x0f33, INTEL_TYPE_VLVGM, "ValleyView Mobile"},
|
||||
{0x0f00, 0x0157, INTEL_TYPE_VLVGM, "ValleyView Mobile"},
|
||||
{0x0f00, 0x0155, INTEL_MODEL_VLV, "ValleyView Desktop"},
|
||||
{0x0f00, 0x0f30, INTEL_MODEL_VLVM, "ValleyView Mobile"},
|
||||
{0x0f00, 0x0f31, INTEL_MODEL_VLVM, "ValleyView Mobile"},
|
||||
{0x0f00, 0x0f32, INTEL_MODEL_VLVM, "ValleyView Mobile"},
|
||||
{0x0f00, 0x0f33, INTEL_MODEL_VLVM, "ValleyView Mobile"},
|
||||
{0x0f00, 0x0157, INTEL_MODEL_VLVM, "ValleyView Mobile"},
|
||||
};
|
||||
|
||||
struct intel_info {
|
||||
pci_info bridge;
|
||||
pci_info display;
|
||||
uint32 type;
|
||||
DeviceType* type;
|
||||
|
||||
uint32 *gtt_base;
|
||||
uint32* gtt_base;
|
||||
phys_addr_t gtt_physical_base;
|
||||
area_id gtt_area;
|
||||
size_t gtt_entries;
|
||||
size_t gtt_stolen_entries;
|
||||
|
||||
vuint32 *registers;
|
||||
vuint32* registers;
|
||||
area_id registers_area;
|
||||
|
||||
addr_t aperture_base;
|
||||
@@ -167,99 +172,29 @@ has_display_device(pci_info &info, uint32 deviceID)
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
determine_memory_sizes(intel_info &info, size_t >tSize, size_t &stolenSize)
|
||||
static uint16
|
||||
gtt_memory_config(intel_info &info)
|
||||
{
|
||||
// read stolen memory from the PCI configuration of the PCI bridge
|
||||
uint8 controlRegister = INTEL_GRAPHICS_MEMORY_CONTROL;
|
||||
if ((info.type & INTEL_TYPE_GROUP_MASK) == INTEL_TYPE_SNB)
|
||||
if (info.type->InGroup(INTEL_GROUP_SNB))
|
||||
controlRegister = SNB_GRAPHICS_MEMORY_CONTROL;
|
||||
|
||||
uint16 memoryConfig = get_pci_config(info.bridge, controlRegister, 2);
|
||||
return get_pci_config(info.bridge, controlRegister, 2);
|
||||
}
|
||||
|
||||
|
||||
static size_t
|
||||
determine_gtt_stolen(intel_info &info)
|
||||
{
|
||||
uint16 memoryConfig = gtt_memory_config(info);
|
||||
size_t memorySize = 1 << 20; // 1 MB
|
||||
gttSize = 0;
|
||||
stolenSize = 0;
|
||||
|
||||
if (info.type == INTEL_TYPE_965) {
|
||||
switch (memoryConfig & i965_GTT_MASK) {
|
||||
case i965_GTT_128K:
|
||||
gttSize = 128 << 10;
|
||||
break;
|
||||
case i965_GTT_256K:
|
||||
gttSize = 256 << 10;
|
||||
break;
|
||||
case i965_GTT_512K:
|
||||
gttSize = 512 << 10;
|
||||
break;
|
||||
}
|
||||
} else if (info.type == INTEL_TYPE_G33
|
||||
|| (info.type & INTEL_TYPE_GROUP_MASK) == INTEL_TYPE_IGD) {
|
||||
switch (memoryConfig & G33_GTT_MASK) {
|
||||
case G33_GTT_1M:
|
||||
gttSize = 1 << 20;
|
||||
break;
|
||||
case G33_GTT_2M:
|
||||
gttSize = 2 << 20;
|
||||
break;
|
||||
}
|
||||
} else if ((info.type & INTEL_TYPE_GROUP_MASK) == INTEL_TYPE_G4x
|
||||
|| (info.type & INTEL_TYPE_GROUP_MASK) == INTEL_TYPE_ILK) {
|
||||
switch (memoryConfig & G4X_GTT_MASK) {
|
||||
case G4X_GTT_NONE:
|
||||
gttSize = 0;
|
||||
break;
|
||||
case G4X_GTT_1M_NO_IVT:
|
||||
gttSize = 1 << 20;
|
||||
break;
|
||||
case G4X_GTT_2M_NO_IVT:
|
||||
case G4X_GTT_2M_IVT:
|
||||
gttSize = 2 << 20;
|
||||
break;
|
||||
case G4X_GTT_3M_IVT:
|
||||
gttSize = 3 << 20;
|
||||
break;
|
||||
case G4X_GTT_4M_IVT:
|
||||
gttSize = 4 << 20;
|
||||
break;
|
||||
}
|
||||
} else if ((info.type & INTEL_TYPE_GROUP_MASK) == INTEL_TYPE_SNB) {
|
||||
switch (memoryConfig & SNB_GTT_SIZE_MASK) {
|
||||
case SNB_GTT_SIZE_NONE:
|
||||
gttSize = 0;
|
||||
break;
|
||||
case SNB_GTT_SIZE_1MB:
|
||||
gttSize = 1 << 20;
|
||||
break;
|
||||
case SNB_GTT_SIZE_2MB:
|
||||
gttSize = 2 << 20;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
// older models have the GTT as large as their frame buffer mapping
|
||||
// TODO: check if the i9xx version works with the i8xx chips as well
|
||||
size_t frameBufferSize = 0;
|
||||
if ((info.type & INTEL_TYPE_8xx) != 0) {
|
||||
if (info.type == INTEL_TYPE_83x
|
||||
&& (memoryConfig & MEMORY_MASK) == i830_FRAME_BUFFER_64M)
|
||||
frameBufferSize = 64 << 20;
|
||||
else
|
||||
frameBufferSize = 128 << 20;
|
||||
} else if ((info.type & INTEL_TYPE_9xx) != 0)
|
||||
frameBufferSize = info.display.u.h0.base_register_sizes[2];
|
||||
|
||||
TRACE("frame buffer size %lu MB\n", frameBufferSize >> 20);
|
||||
gttSize = frameBufferSize / 1024;
|
||||
}
|
||||
|
||||
// TODO: test with different models!
|
||||
|
||||
if (info.type == INTEL_TYPE_83x) {
|
||||
if (info.type->InGroup(INTEL_GROUP_83x)) {
|
||||
// Older chips
|
||||
switch (memoryConfig & STOLEN_MEMORY_MASK) {
|
||||
case i830_LOCAL_MEMORY_ONLY:
|
||||
// TODO: determine its size!
|
||||
dprintf("intel_gart: getting local memory size not "
|
||||
"implemented.\n");
|
||||
ERROR("getting local memory size not implemented.\n");
|
||||
break;
|
||||
case i830_STOLEN_512K:
|
||||
memorySize >>= 1;
|
||||
@@ -271,7 +206,7 @@ determine_memory_sizes(intel_info &info, size_t >tSize, size_t &stolenSize)
|
||||
memorySize *= 8;
|
||||
break;
|
||||
}
|
||||
} else if ((info.type & INTEL_TYPE_GROUP_MASK) == INTEL_TYPE_SNB) {
|
||||
} else if (info.type->InGroup(INTEL_GROUP_SNB)) {
|
||||
switch (memoryConfig & SNB_STOLEN_MEMORY_MASK) {
|
||||
case SNB_STOLEN_MEMORY_32MB:
|
||||
memorySize *= 32;
|
||||
@@ -322,8 +257,11 @@ determine_memory_sizes(intel_info &info, size_t >tSize, size_t &stolenSize)
|
||||
memorySize *= 512;
|
||||
break;
|
||||
}
|
||||
} else if (info.type == INTEL_TYPE_85x
|
||||
|| (info.type & INTEL_TYPE_9xx) == INTEL_TYPE_9xx) {
|
||||
} else if (info.type->InGroup(INTEL_GROUP_85x)
|
||||
|| info.type->InFamily(INTEL_FAMILY_9xx)
|
||||
|| info.type->InFamily(INTEL_FAMILY_SER5)
|
||||
|| info.type->InFamily(INTEL_FAMILY_SOC0)
|
||||
|| info.type->InFamily(INTEL_FAMILY_POVR)) {
|
||||
switch (memoryConfig & STOLEN_MEMORY_MASK) {
|
||||
case i855_STOLEN_MEMORY_4M:
|
||||
memorySize *= 4;
|
||||
@@ -366,14 +304,109 @@ determine_memory_sizes(intel_info &info, size_t >tSize, size_t &stolenSize)
|
||||
// TODO: error out!
|
||||
memorySize = 4096;
|
||||
}
|
||||
return memorySize - 4096;
|
||||
}
|
||||
|
||||
stolenSize = memorySize - 4096;
|
||||
|
||||
static size_t
|
||||
determine_gtt_size(intel_info &info)
|
||||
{
|
||||
uint16 memoryConfig = gtt_memory_config(info);
|
||||
size_t gttSize = 0;
|
||||
|
||||
if (info.type->IsModel(INTEL_MODEL_965)) {
|
||||
switch (memoryConfig & i965_GTT_MASK) {
|
||||
case i965_GTT_128K:
|
||||
gttSize = 128 << 10;
|
||||
break;
|
||||
case i965_GTT_256K:
|
||||
gttSize = 256 << 10;
|
||||
break;
|
||||
case i965_GTT_512K:
|
||||
gttSize = 512 << 10;
|
||||
break;
|
||||
}
|
||||
} else if (info.type->IsModel(INTEL_MODEL_G33)
|
||||
|| info.type->InGroup(INTEL_GROUP_PIN)) {
|
||||
switch (memoryConfig & G33_GTT_MASK) {
|
||||
case G33_GTT_1M:
|
||||
gttSize = 1 << 20;
|
||||
break;
|
||||
case G33_GTT_2M:
|
||||
gttSize = 2 << 20;
|
||||
break;
|
||||
}
|
||||
} else if (info.type->InGroup(INTEL_GROUP_G4x)
|
||||
|| info.type->InGroup(INTEL_GROUP_ILK)) {
|
||||
switch (memoryConfig & G4X_GTT_MASK) {
|
||||
case G4X_GTT_NONE:
|
||||
gttSize = 0;
|
||||
break;
|
||||
case G4X_GTT_1M_NO_IVT:
|
||||
gttSize = 1 << 20;
|
||||
break;
|
||||
case G4X_GTT_2M_NO_IVT:
|
||||
case G4X_GTT_2M_IVT:
|
||||
gttSize = 2 << 20;
|
||||
break;
|
||||
case G4X_GTT_3M_IVT:
|
||||
gttSize = 3 << 20;
|
||||
break;
|
||||
case G4X_GTT_4M_IVT:
|
||||
gttSize = 4 << 20;
|
||||
break;
|
||||
}
|
||||
} else if (info.type->InGroup(INTEL_GROUP_SNB)) {
|
||||
switch (memoryConfig & SNB_GTT_SIZE_MASK) {
|
||||
case SNB_GTT_SIZE_NONE:
|
||||
gttSize = 0;
|
||||
break;
|
||||
case SNB_GTT_SIZE_1MB:
|
||||
gttSize = 1 << 20;
|
||||
break;
|
||||
case SNB_GTT_SIZE_2MB:
|
||||
gttSize = 2 << 20;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
// older models have the GTT as large as their frame buffer mapping
|
||||
// TODO: check if the i9xx version works with the i8xx chips as well
|
||||
size_t frameBufferSize = 0;
|
||||
if (info.type->InFamily(INTEL_FAMILY_8xx)) {
|
||||
if (info.type->InGroup(INTEL_GROUP_83x)
|
||||
&& (memoryConfig & MEMORY_MASK) == i830_FRAME_BUFFER_64M)
|
||||
frameBufferSize = 64 << 20;
|
||||
else
|
||||
frameBufferSize = 128 << 20;
|
||||
} else if (info.type->Generation() >= 3) {
|
||||
frameBufferSize = info.display.u.h0.base_register_sizes[2];
|
||||
}
|
||||
|
||||
TRACE("frame buffer size %lu MB\n", frameBufferSize >> 20);
|
||||
gttSize = frameBufferSize / 1024;
|
||||
}
|
||||
return gttSize;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
set_gtt_entry(intel_info &info, uint32 offset, phys_addr_t physicalAddress)
|
||||
{
|
||||
if (info.type->Generation() >= 8) {
|
||||
// CHV + BXT
|
||||
physicalAddress |= (physicalAddress >> 28) & 0x07f0;
|
||||
// TODO: cache control?
|
||||
} else if (info.type->Generation() >= 6) {
|
||||
// SandyBridge, IronLake, IvyBridge, Haswell
|
||||
physicalAddress |= (physicalAddress >> 28) & 0x0ff0;
|
||||
physicalAddress |= 0x02; // cache control, l3 cacheable
|
||||
} else if (info.type->Generation() >= 4) {
|
||||
// Intel 9xx minus 91x, 94x, G33
|
||||
// possible high bits are stored in the lower end
|
||||
physicalAddress |= (physicalAddress >> 28) & 0x00f0;
|
||||
// TODO: cache control?
|
||||
}
|
||||
|
||||
// TODO: this is not 64-bit safe!
|
||||
write32(info.gtt_base + (offset >> GTT_PAGE_SHIFT),
|
||||
(uint32)physicalAddress | GTT_ENTRY_VALID);
|
||||
@@ -396,7 +429,7 @@ intel_map(intel_info &info)
|
||||
{
|
||||
int fbIndex = 0;
|
||||
int mmioIndex = 1;
|
||||
if ((info.type & INTEL_TYPE_FAMILY_MASK) == INTEL_TYPE_9xx) {
|
||||
if (info.type->Generation() >= 3) {
|
||||
// for some reason Intel saw the need to change the order of the
|
||||
// mappings with the introduction of the i9xx family
|
||||
mmioIndex = 0;
|
||||
@@ -410,7 +443,7 @@ intel_map(intel_info &info)
|
||||
B_KERNEL_READ_AREA | B_KERNEL_WRITE_AREA, (void**)&info.registers);
|
||||
|
||||
if (mmioMapper.InitCheck() < B_OK) {
|
||||
dprintf("agp_intel: could not map memory I/O!\n");
|
||||
ERROR("could not map memory I/O!\n");
|
||||
return info.registers_area;
|
||||
}
|
||||
|
||||
@@ -425,7 +458,7 @@ intel_map(intel_info &info)
|
||||
&scratchAddress, B_ANY_KERNEL_ADDRESS, B_PAGE_SIZE, B_FULL_LOCK,
|
||||
B_KERNEL_READ_AREA | B_KERNEL_WRITE_AREA);
|
||||
if (scratchCreator.InitCheck() < B_OK) {
|
||||
dprintf("agp_intel: could not create scratch page!\n");
|
||||
ERROR("could not create scratch page!\n");
|
||||
return info.scratch_area;
|
||||
}
|
||||
|
||||
@@ -433,29 +466,27 @@ intel_map(intel_info &info)
|
||||
if (get_memory_map(scratchAddress, B_PAGE_SIZE, &entry, 1) != B_OK)
|
||||
return B_ERROR;
|
||||
|
||||
if ((info.type & INTEL_TYPE_FAMILY_MASK) == INTEL_TYPE_9xx) {
|
||||
if ((info.type & INTEL_TYPE_GROUP_MASK) == INTEL_TYPE_G4x
|
||||
|| (info.type & INTEL_TYPE_GROUP_MASK) == INTEL_TYPE_ILK
|
||||
|| (info.type & INTEL_TYPE_GROUP_MASK) == INTEL_TYPE_SNB) {
|
||||
info.gtt_physical_base = info.display.u.h0.base_registers[mmioIndex]
|
||||
+ (2UL << 20);
|
||||
} else
|
||||
info.gtt_physical_base
|
||||
= get_pci_config(info.display, i915_GTT_BASE, 4);
|
||||
} else {
|
||||
// TODO: Review these
|
||||
if (info.type->InFamily(INTEL_FAMILY_8xx)) {
|
||||
info.gtt_physical_base = read32(info.registers
|
||||
+ INTEL_PAGE_TABLE_CONTROL) & ~PAGE_TABLE_ENABLED;
|
||||
if (info.gtt_physical_base == 0) {
|
||||
// TODO: not sure how this is supposed to work under Linux/FreeBSD,
|
||||
// but on my i865, this code is needed for Haiku.
|
||||
dprintf("intel_gart: Use GTT address fallback.\n");
|
||||
ERROR("Use GTT address fallback.\n");
|
||||
info.gtt_physical_base = info.display.u.h0.base_registers[mmioIndex]
|
||||
+ i830_GTT_BASE;
|
||||
}
|
||||
} else if (info.type->InGroup(INTEL_GROUP_91x)) {
|
||||
info.gtt_physical_base = get_pci_config(info.display, i915_GTT_BASE, 4);
|
||||
} else {
|
||||
// 945+?
|
||||
info.gtt_physical_base = info.display.u.h0.base_registers[mmioIndex]
|
||||
+ (2UL << 20);
|
||||
}
|
||||
|
||||
size_t gttSize, stolenSize;
|
||||
determine_memory_sizes(info, gttSize, stolenSize);
|
||||
size_t gttSize = determine_gtt_size(info);
|
||||
size_t stolenSize = determine_gtt_stolen(info);
|
||||
|
||||
info.gtt_entries = gttSize / 4096;
|
||||
info.gtt_stolen_entries = stolenSize / 4096;
|
||||
@@ -468,7 +499,7 @@ intel_map(intel_info &info)
|
||||
info.gtt_physical_base, gttSize, B_ANY_KERNEL_ADDRESS,
|
||||
B_KERNEL_READ_AREA | B_KERNEL_WRITE_AREA, (void**)&info.gtt_base);
|
||||
if (gttMapper.InitCheck() < B_OK) {
|
||||
dprintf("intel_gart: could not map GTT!\n");
|
||||
ERROR("could not map GTT!\n");
|
||||
return info.gtt_area;
|
||||
}
|
||||
|
||||
@@ -477,16 +508,14 @@ intel_map(intel_info &info)
|
||||
if (info.aperture_size == 0)
|
||||
info.aperture_size = info.display.u.h0.base_register_sizes[fbIndex];
|
||||
|
||||
dprintf("intel_gart: detected %ld MB of stolen memory, aperture "
|
||||
"size %ld MB, GTT size %ld KB\n", (stolenSize + (1023 << 10)) >> 20,
|
||||
ERROR("detected %ld MB of stolen memory, aperture size %ld MB, "
|
||||
"GTT size %ld KB\n", (stolenSize + (1023 << 10)) >> 20,
|
||||
info.aperture_size >> 20, gttSize >> 10);
|
||||
|
||||
dprintf("intel_gart: GTT base = 0x%" B_PRIxPHYSADDR "\n",
|
||||
info.gtt_physical_base);
|
||||
dprintf("intel_gart: MMIO base = 0x%" B_PRIx32 "\n",
|
||||
ERROR("GTT base = 0x%" B_PRIxPHYSADDR "\n", info.gtt_physical_base);
|
||||
ERROR("MMIO base = 0x%" B_PRIx32 "\n",
|
||||
info.display.u.h0.base_registers[mmioIndex]);
|
||||
dprintf("intel_gart: GMR base = 0x%" B_PRIxPHYSADDR "\n",
|
||||
info.aperture_physical_base);
|
||||
ERROR("GMR base = 0x%" B_PRIxPHYSADDR "\n", info.aperture_physical_base);
|
||||
|
||||
AreaKeeper apertureMapper;
|
||||
info.aperture_area = apertureMapper.Map("intel graphics aperture",
|
||||
@@ -495,7 +524,7 @@ intel_map(intel_info &info)
|
||||
B_READ_AREA | B_WRITE_AREA, (void**)&info.aperture_base);
|
||||
if (apertureMapper.InitCheck() < B_OK) {
|
||||
// try again without write combining
|
||||
dprintf(DEVICE_NAME ": enabling write combined mode failed.\n");
|
||||
ERROR("enabling write combined mode failed.\n");
|
||||
|
||||
info.aperture_area = apertureMapper.Map("intel graphics aperture",
|
||||
info.aperture_physical_base, info.aperture_size,
|
||||
@@ -503,7 +532,7 @@ intel_map(intel_info &info)
|
||||
(void**)&info.aperture_base);
|
||||
}
|
||||
if (apertureMapper.InitCheck() < B_OK) {
|
||||
dprintf(DEVICE_NAME ": could not map graphics aperture!\n");
|
||||
ERROR("could not map graphics aperture!\n");
|
||||
return info.aperture_area;
|
||||
}
|
||||
|
||||
@@ -639,7 +668,7 @@ intel_init()
|
||||
for (uint32 i = 0; i < sizeof(kSupportedDevices)
|
||||
/ sizeof(kSupportedDevices[0]); i++) {
|
||||
if (sInfo.bridge.device_id == kSupportedDevices[i].bridge_id) {
|
||||
sInfo.type = kSupportedDevices[i].type;
|
||||
sInfo.type = new DeviceType(kSupportedDevices[i].type);
|
||||
if (has_display_device(sInfo.display,
|
||||
kSupportedDevices[i].display_id)) {
|
||||
TRACE("found intel bridge\n");
|
||||
@@ -656,6 +685,8 @@ intel_init()
|
||||
static void
|
||||
intel_uninit()
|
||||
{
|
||||
if (sInfo.type)
|
||||
delete sInfo.type;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -119,8 +119,6 @@ static struct vbios {
|
||||
} vbios;
|
||||
|
||||
|
||||
/* TODO: move code to accelerant, if possible */
|
||||
|
||||
/*! This is reimplementation, Haiku uses BIOS call and gets most current panel
|
||||
info, we're, otherwise, digging in VBIOS memory and parsing VBT tables to
|
||||
get native panel timings. This will allow to get non-updated,
|
||||
|
||||
@@ -42,71 +42,75 @@ const struct supported_device {
|
||||
int32 type;
|
||||
const char* name;
|
||||
} kSupportedDevices[] = {
|
||||
{0x3577, INTEL_TYPE_83x, "i830GM"},
|
||||
{0x2562, INTEL_TYPE_83x, "i845G"},
|
||||
{0x3577, INTEL_GROUP_83x, "i830GM"},
|
||||
{0x2562, INTEL_GROUP_83x, "i845G"},
|
||||
|
||||
{0x2572, INTEL_TYPE_85x, "i865G"},
|
||||
{0x3582, INTEL_TYPE_85x, "i855G"},
|
||||
{0x358e, INTEL_TYPE_85x, "i855G"},
|
||||
{0x2572, INTEL_GROUP_85x, "i865G"},
|
||||
{0x3582, INTEL_GROUP_85x, "i855G"},
|
||||
{0x358e, INTEL_GROUP_85x, "i855G"},
|
||||
|
||||
{0x2582, INTEL_TYPE_915, "i915G"},
|
||||
{0x258a, INTEL_TYPE_915, "i915"},
|
||||
{0x2592, INTEL_TYPE_915M, "i915GM"},
|
||||
{0x2792, INTEL_TYPE_915, "i910"},
|
||||
{0x2772, INTEL_TYPE_945, "i945G"},
|
||||
{0x27a2, INTEL_TYPE_945M, "i945GM"},
|
||||
{0x27ae, INTEL_TYPE_945M, "i945GME"},
|
||||
{0x2972, INTEL_TYPE_965, "i946G"},
|
||||
{0x2982, INTEL_TYPE_965, "G35"},
|
||||
{0x2992, INTEL_TYPE_965, "i965Q"},
|
||||
{0x29a2, INTEL_TYPE_965, "i965G"},
|
||||
{0x2a02, INTEL_TYPE_965M, "i965GM"},
|
||||
{0x2a12, INTEL_TYPE_965M, "i965GME"},
|
||||
{0x29b2, INTEL_TYPE_G33, "G33G"},
|
||||
{0x29c2, INTEL_TYPE_G33, "Q35G"},
|
||||
{0x29d2, INTEL_TYPE_G33, "Q33G"},
|
||||
{0x2582, INTEL_MODEL_915, "i915G"},
|
||||
{0x258a, INTEL_MODEL_915, "i915"},
|
||||
{0x2592, INTEL_MODEL_915M, "i915GM"},
|
||||
{0x2792, INTEL_MODEL_915, "i910"},
|
||||
{0x2772, INTEL_MODEL_945, "i945G"},
|
||||
{0x27a2, INTEL_MODEL_945M, "i945GM"},
|
||||
{0x27ae, INTEL_MODEL_945M, "i945GME"},
|
||||
{0x2972, INTEL_MODEL_965, "i946G"},
|
||||
{0x2982, INTEL_MODEL_965, "G35"},
|
||||
{0x2992, INTEL_MODEL_965, "i965Q"},
|
||||
{0x29a2, INTEL_MODEL_965, "i965G"},
|
||||
{0x2a02, INTEL_MODEL_965M, "i965GM"},
|
||||
{0x2a12, INTEL_MODEL_965M, "i965GME"},
|
||||
{0x29b2, INTEL_MODEL_G33, "G33G"},
|
||||
{0x29c2, INTEL_MODEL_G33, "Q35G"},
|
||||
{0x29d2, INTEL_MODEL_G33, "Q33G"},
|
||||
|
||||
{0x2a42, INTEL_TYPE_GM45, "GM45"},
|
||||
{0x2e02, INTEL_TYPE_G45, "IGD"},
|
||||
{0x2e12, INTEL_TYPE_G45, "Q45"},
|
||||
{0x2e22, INTEL_TYPE_G45, "G45"},
|
||||
{0x2e32, INTEL_TYPE_G45, "G41"},
|
||||
{0x2e42, INTEL_TYPE_G45, "B43"},
|
||||
{0x2e92, INTEL_TYPE_G45, "B43"},
|
||||
{0x2a42, INTEL_MODEL_GM45, "GM45"},
|
||||
{0x2e02, INTEL_MODEL_G45, "IGD"},
|
||||
{0x2e12, INTEL_MODEL_G45, "Q45"},
|
||||
{0x2e22, INTEL_MODEL_G45, "G45"},
|
||||
{0x2e32, INTEL_MODEL_G45, "G41"},
|
||||
{0x2e42, INTEL_MODEL_G45, "B43"},
|
||||
{0x2e92, INTEL_MODEL_G45, "B43"},
|
||||
|
||||
{0xa001, INTEL_TYPE_IGDG, "Atom_Dx10"},
|
||||
{0xa011, INTEL_TYPE_IGDGM, "Atom_N4x0"},
|
||||
{0xa001, INTEL_MODEL_PINE, "Atom_Dx10"},
|
||||
{0xa011, INTEL_MODEL_PINEM, "Atom_N4x0"},
|
||||
|
||||
{0x0042, INTEL_TYPE_ILKG, "IronLake Desktop"},
|
||||
{0x0046, INTEL_TYPE_ILKGM, "IronLake Mobile"},
|
||||
{0x0046, INTEL_TYPE_ILKGM, "IronLake Mobile"},
|
||||
{0x0046, INTEL_TYPE_ILKGM, "IronLake Mobile"},
|
||||
{0x0042, INTEL_MODEL_ILKG, "IronLake Desktop"},
|
||||
{0x0046, INTEL_MODEL_ILKGM, "IronLake Mobile"},
|
||||
{0x0046, INTEL_MODEL_ILKGM, "IronLake Mobile"},
|
||||
{0x0046, INTEL_MODEL_ILKGM, "IronLake Mobile"},
|
||||
|
||||
{0x0102, INTEL_TYPE_SNBG, "SandyBridge Desktop GT1"},
|
||||
{0x0112, INTEL_TYPE_SNBG, "SandyBridge Desktop GT2"},
|
||||
{0x0122, INTEL_TYPE_SNBG, "SandyBridge Desktop GT2+"},
|
||||
{0x0106, INTEL_TYPE_SNBGM, "SandyBridge Mobile GT1"},
|
||||
{0x0116, INTEL_TYPE_SNBGM, "SandyBridge Mobile GT2"},
|
||||
{0x0126, INTEL_TYPE_SNBGM, "SandyBridge Mobile GT2+"},
|
||||
{0x010a, INTEL_TYPE_SNBGS, "SandyBridge Server"},
|
||||
// Experimental
|
||||
#if 0
|
||||
{0x0102, INTEL_MODEL_SNBG, "SandyBridge Desktop GT1"},
|
||||
{0x0112, INTEL_MODEL_SNBG, "SandyBridge Desktop GT2"},
|
||||
{0x0122, INTEL_MODEL_SNBG, "SandyBridge Desktop GT2+"},
|
||||
{0x0106, INTEL_MODEL_SNBGM, "SandyBridge Mobile GT1"},
|
||||
{0x0116, INTEL_MODEL_SNBGM, "SandyBridge Mobile GT2"},
|
||||
{0x0126, INTEL_MODEL_SNBGM, "SandyBridge Mobile GT2+"},
|
||||
{0x010a, INTEL_MODEL_SNBGS, "SandyBridge Server"},
|
||||
|
||||
{0x0152, INTEL_TYPE_IVBG, "IvyBridge Desktop GT1"},
|
||||
{0x0162, INTEL_TYPE_IVBG, "IvyBridge Desktop GT2"},
|
||||
{0x0156, INTEL_TYPE_IVBGM, "IvyBridge Mobile GT1"},
|
||||
{0x0166, INTEL_TYPE_IVBGM, "IvyBridge Mobile GT2"},
|
||||
{0x015a, INTEL_TYPE_IVBGS, "IvyBridge Server GT1"},
|
||||
{0x016a, INTEL_TYPE_IVBGS, "IvyBridge Server GT2"},
|
||||
{0x0152, INTEL_MODEL_IVBG, "IvyBridge Desktop GT1"},
|
||||
{0x0162, INTEL_MODEL_IVBG, "IvyBridge Desktop GT2"},
|
||||
{0x0156, INTEL_MODEL_IVBGM, "IvyBridge Mobile GT1"},
|
||||
{0x0166, INTEL_MODEL_IVBGM, "IvyBridge Mobile GT2"},
|
||||
{0x015a, INTEL_MODEL_IVBGS, "IvyBridge Server GT1"},
|
||||
{0x016a, INTEL_MODEL_IVBGS, "IvyBridge Server GT2"},
|
||||
|
||||
{0x0412, INTEL_TYPE_IVBG, "Haswell Desktop"},
|
||||
{0x0416, INTEL_TYPE_IVBGM, "Haswell Mobile"},
|
||||
{0x0d26, INTEL_TYPE_IVBGM, "Haswell Mobile"},
|
||||
{0x0412, INTEL_MODEL_HAS, "Haswell Desktop"},
|
||||
{0x0416, INTEL_MODEL_HASM, "Haswell Mobile"},
|
||||
{0x0d26, INTEL_MODEL_HASM, "Haswell Mobile"},
|
||||
{0x0a16, INTEL_MODEL_HASM, "Haswell Mobile"},
|
||||
|
||||
{0x0155, INTEL_TYPE_VLVG, "ValleyView Desktop"},
|
||||
{0x0f30, INTEL_TYPE_VLVGM, "ValleyView Mobile"},
|
||||
{0x0f31, INTEL_TYPE_VLVGM, "ValleyView Mobile"},
|
||||
{0x0f32, INTEL_TYPE_VLVGM, "ValleyView Mobile"},
|
||||
{0x0f33, INTEL_TYPE_VLVGM, "ValleyView Mobile"},
|
||||
{0x0157, INTEL_TYPE_VLVGM, "ValleyView Mobile"},
|
||||
{0x0155, INTEL_MODEL_VLV, "ValleyView Desktop"},
|
||||
{0x0f30, INTEL_MODEL_VLVM, "ValleyView Mobile"},
|
||||
{0x0f31, INTEL_MODEL_VLVM, "ValleyView Mobile"},
|
||||
{0x0f32, INTEL_MODEL_VLVM, "ValleyView Mobile"},
|
||||
{0x0f33, INTEL_MODEL_VLVM, "ValleyView Mobile"},
|
||||
{0x0157, INTEL_MODEL_VLVM, "ValleyView Mobile"},
|
||||
#endif
|
||||
};
|
||||
|
||||
int32 api_version = B_CUR_DRIVER_API_VERSION;
|
||||
|
||||
@@ -98,7 +98,7 @@ intel_interrupt_handler(void* data)
|
||||
|
||||
// Intel changed the PCH register mapping between Sandy Bridge and the
|
||||
// later generations (Ivy Bridge and up).
|
||||
if (info.device_type.InFamily(INTEL_TYPE_SNB)) {
|
||||
if (info.device_type.InGroup(INTEL_GROUP_SNB)) {
|
||||
mask = hasPCH ? PCH_INTERRUPT_VBLANK_PIPEA_SNB
|
||||
: INTERRUPT_VBLANK_PIPEA;
|
||||
if ((identity & mask) != 0) {
|
||||
@@ -287,7 +287,7 @@ intel_extreme_init(intel_info &info)
|
||||
|
||||
int fbIndex = 0;
|
||||
int mmioIndex = 1;
|
||||
if (info.device_type.InFamily(INTEL_TYPE_9xx)) {
|
||||
if (info.device_type.Generation() >= 3) {
|
||||
// For some reason Intel saw the need to change the order of the
|
||||
// mappings with the introduction of the i9xx family
|
||||
mmioIndex = 0;
|
||||
@@ -316,12 +316,16 @@ intel_extreme_init(intel_info &info)
|
||||
return info.registers_area;
|
||||
}
|
||||
|
||||
ERROR("Init Intel generation %" B_PRId32 " GPU %s PCH split.\n",
|
||||
info.device_type.Generation(),
|
||||
info.device_type.HasPlatformControlHub() ? "with" : "without");
|
||||
|
||||
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.HasPlatformControlHub()) {
|
||||
// PCH based platforms (IronLake and up)
|
||||
// PCH based platforms (IronLake through ultra-low-power Broadwells)
|
||||
blocks[REGISTER_BLOCK(REGS_NORTH_SHARED)]
|
||||
= PCH_NORTH_SHARED_REGISTER_BASE;
|
||||
blocks[REGISTER_BLOCK(REGS_NORTH_PIPE_AND_PORT)]
|
||||
@@ -346,14 +350,24 @@ intel_extreme_init(intel_info &info)
|
||||
= ICH_PORT_REGISTER_BASE;
|
||||
}
|
||||
|
||||
// "I nearly got violent with the hw guys when they told me..."
|
||||
if (info.device_type.InFamily(INTEL_TYPE_VLV)) {
|
||||
TRACE("%s: ValleyView MMIO offset engaged\n", __func__);
|
||||
blocks[REGISTER_BLOCK(REGS_NORTH_PLANE_CONTROL)] += VLV_DISPLAY_BASE;
|
||||
blocks[REGISTER_BLOCK(REGS_NORTH_SHARED)] += VLV_DISPLAY_BASE;
|
||||
// Everything in the display PRM gets +0x180000
|
||||
if (info.device_type.InGroup(INTEL_GROUP_VLV)) {
|
||||
// "I nearly got violent with the hw guys when they told me..."
|
||||
blocks[REGISTER_BLOCK(REGS_SOUTH_SHARED)] += VLV_DISPLAY_BASE;
|
||||
blocks[REGISTER_BLOCK(REGS_SOUTH_TRANSCODER_PORT)] += VLV_DISPLAY_BASE;
|
||||
}
|
||||
|
||||
TRACE("REGS_NORTH_SHARED: 0x%X\n",
|
||||
blocks[REGISTER_BLOCK(REGS_NORTH_SHARED)]);
|
||||
TRACE("REGS_NORTH_PIPE_AND_PORT: 0x%X\n",
|
||||
blocks[REGISTER_BLOCK(REGS_NORTH_PIPE_AND_PORT)]);
|
||||
TRACE("REGS_NORTH_PLANE_CONTROL: 0x%X\n",
|
||||
blocks[REGISTER_BLOCK(REGS_NORTH_PLANE_CONTROL)]);
|
||||
TRACE("REGS_SOUTH_SHARED: 0x%X\n",
|
||||
blocks[REGISTER_BLOCK(REGS_SOUTH_SHARED)]);
|
||||
TRACE("REGS_SOUTH_TRANSCODER_PORT: 0x%X\n",
|
||||
blocks[REGISTER_BLOCK(REGS_SOUTH_TRANSCODER_PORT)]);
|
||||
|
||||
// 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
|
||||
@@ -391,13 +405,16 @@ intel_extreme_init(intel_info &info)
|
||||
info.shared_info->frame_buffer = 0;
|
||||
info.shared_info->dpms_mode = B_DPMS_ON;
|
||||
|
||||
// Pull VBIOS panel mode for later use
|
||||
info.shared_info->got_vbt = get_lvds_mode_from_bios(
|
||||
&info.shared_info->current_mode);
|
||||
&info.shared_info->panel_mode);
|
||||
|
||||
/* at least 855gm can't drive more than one head at time */
|
||||
if (info.device_type.InFamily(INTEL_TYPE_8xx))
|
||||
if (info.device_type.InFamily(INTEL_FAMILY_8xx))
|
||||
info.shared_info->single_head_locked = 1;
|
||||
|
||||
if (info.device_type.InFamily(INTEL_TYPE_9xx)) {
|
||||
if (info.device_type.InFamily(INTEL_FAMILY_9xx)
|
||||
| info.device_type.InFamily(INTEL_FAMILY_SER5)) {
|
||||
info.shared_info->pll_info.reference_frequency = 96000; // 96 kHz
|
||||
info.shared_info->pll_info.max_frequency = 400000;
|
||||
// 400 MHz RAM DAC speed
|
||||
@@ -457,6 +474,18 @@ intel_extreme_init(intel_info &info)
|
||||
|
||||
init_interrupt_handler(info);
|
||||
|
||||
if (info.device_type.HasPlatformControlHub()) {
|
||||
if (info.device_type.Generation() == 5) {
|
||||
info.shared_info->fdi_link_frequency = (read32(info, FDI_PLL_BIOS_0)
|
||||
& FDI_PLL_FB_CLOCK_MASK) + 2;
|
||||
info.shared_info->fdi_link_frequency *= 100;
|
||||
} else {
|
||||
info.shared_info->fdi_link_frequency = 2700;
|
||||
}
|
||||
} else {
|
||||
info.shared_info->fdi_link_frequency = 0;
|
||||
}
|
||||
|
||||
TRACE("%s: completed successfully!\n", __func__);
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
@@ -70,7 +70,7 @@ find_reg(const intel_info& info, uint32 target)
|
||||
}
|
||||
|
||||
|
||||
extern bool get_lvds_mode_from_bios(display_mode *shared_info);
|
||||
extern bool get_lvds_mode_from_bios(display_mode *mode);
|
||||
extern status_t intel_free_memory(intel_info& info, addr_t offset);
|
||||
extern status_t intel_allocate_memory(intel_info& info, size_t size,
|
||||
size_t alignment, uint32 flags, addr_t* _offset,
|
||||
|
||||
@@ -31,19 +31,19 @@ intel_en_gating(intel_info &info)
|
||||
if (info.pci->device_id == 0x2a02 || info.pci->device_id == 0x2a12) {
|
||||
TRACE("i965GM/i965GME quirk\n");
|
||||
write32(info, 0x6204, (1L << 29));
|
||||
} else if (info.device_type.InGroup(INTEL_TYPE_SNB)) {
|
||||
} else if (info.device_type.InGroup(INTEL_GROUP_SNB)) {
|
||||
TRACE("SandyBridge clock gating\n");
|
||||
write32(info, 0x42020, (1L << 28) | (1L << 7) | (1L << 5));
|
||||
} else if (info.device_type.InGroup(INTEL_TYPE_IVB)) {
|
||||
} else if (info.device_type.InGroup(INTEL_GROUP_IVB)) {
|
||||
TRACE("IvyBridge clock gating\n");
|
||||
write32(info, 0x42020, (1L << 28));
|
||||
} else if (info.device_type.InGroup(INTEL_TYPE_VLV)) {
|
||||
} else if (info.device_type.InGroup(INTEL_GROUP_VLV)) {
|
||||
TRACE("ValleyView clock gating\n");
|
||||
write32(info, VLV_DISPLAY_BASE + 0x6200, (1L << 28));
|
||||
} else if (info.device_type.InGroup(INTEL_TYPE_ILK)) {
|
||||
} else if (info.device_type.InGroup(INTEL_GROUP_ILK)) {
|
||||
TRACE("IronLake clock gating\n");
|
||||
write32(info, 0x42020, (1L << 7) | (1L << 5));
|
||||
} else if (info.device_type.InGroup(INTEL_TYPE_G4x)) {
|
||||
} else if (info.device_type.InGroup(INTEL_GROUP_G4x)) {
|
||||
TRACE("G4x clock gating\n");
|
||||
write32(info, 0x6204, 0);
|
||||
write32(info, 0x6208, (1L << 9) | (1L << 7) | (1L << 6));
|
||||
@@ -70,8 +70,8 @@ intel_en_downclock(intel_info &info)
|
||||
{
|
||||
CALLED();
|
||||
|
||||
if (!info.device_type.InGroup(INTEL_TYPE_SNB)
|
||||
&& !info.device_type.InGroup(INTEL_TYPE_IVB)) {
|
||||
if (!info.device_type.InGroup(INTEL_GROUP_SNB)
|
||||
&& !info.device_type.InGroup(INTEL_GROUP_IVB)) {
|
||||
TRACE("%s: Downclocking not supported on this chipset.\n", __func__);
|
||||
return B_NOT_ALLOWED;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user