* added support for the Atom IGD, based on the X driver sources (fixes #6202)

* fixes G4x PLL limits


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@40319 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Brecht Machiels
2011-01-29 21:20:00 +00:00
parent 476bfd22cb
commit 2f4d9fdbab
4 changed files with 114 additions and 43 deletions
@@ -33,6 +33,7 @@
#define INTEL_TYPE_96x (INTEL_TYPE_9xx | 0x0100) #define INTEL_TYPE_96x (INTEL_TYPE_9xx | 0x0100)
#define INTEL_TYPE_Gxx (INTEL_TYPE_9xx | 0x0200) #define INTEL_TYPE_Gxx (INTEL_TYPE_9xx | 0x0200)
#define INTEL_TYPE_G4x (INTEL_TYPE_9xx | 0x0400) #define INTEL_TYPE_G4x (INTEL_TYPE_9xx | 0x0400)
#define INTEL_TYPE_IGD (INTEL_TYPE_9xx | 0x0800)
// models // models
#define INTEL_TYPE_MOBILE 0x0008 #define INTEL_TYPE_MOBILE 0x0008
#define INTEL_TYPE_915 (INTEL_TYPE_91x) #define INTEL_TYPE_915 (INTEL_TYPE_91x)
@@ -43,6 +44,8 @@
#define INTEL_TYPE_G33 (INTEL_TYPE_Gxx) #define INTEL_TYPE_G33 (INTEL_TYPE_Gxx)
#define INTEL_TYPE_G45 (INTEL_TYPE_G4x) #define INTEL_TYPE_G45 (INTEL_TYPE_G4x)
#define INTEL_TYPE_GM45 (INTEL_TYPE_G4x | INTEL_TYPE_MOBILE) #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 DEVICE_NAME "intel_extreme" #define DEVICE_NAME "intel_extreme"
#define INTEL_ACCELERANT_NAME "intel_extreme.accelerant" #define INTEL_ACCELERANT_NAME "intel_extreme.accelerant"
@@ -301,11 +304,15 @@ struct intel_free_graphics_memory {
#define DISPLAY_PLL_POST1_DIVIDE_2 (1UL << 21) #define DISPLAY_PLL_POST1_DIVIDE_2 (1UL << 21)
#define DISPLAY_PLL_POST1_DIVISOR_MASK 0x001f0000 #define DISPLAY_PLL_POST1_DIVISOR_MASK 0x001f0000
#define DISPLAY_PLL_9xx_POST1_DIVISOR_MASK 0x00ff0000 #define DISPLAY_PLL_9xx_POST1_DIVISOR_MASK 0x00ff0000
#define DISPLAY_PLL_IGD_POST1_DIVISOR_MASK 0x00ff8000
#define DISPLAY_PLL_POST1_DIVISOR_SHIFT 16 #define DISPLAY_PLL_POST1_DIVISOR_SHIFT 16
#define DISPLAY_PLL_IGD_POST1_DIVISOR_SHIFT 15
#define DISPLAY_PLL_DIVISOR_1 (1UL << 8) #define DISPLAY_PLL_DIVISOR_1 (1UL << 8)
#define DISPLAY_PLL_N_DIVISOR_MASK 0x001f0000 #define DISPLAY_PLL_N_DIVISOR_MASK 0x001f0000
#define DISPLAY_PLL_IGD_N_DIVISOR_MASK 0x00ff0000
#define DISPLAY_PLL_M1_DIVISOR_MASK 0x00001f00 #define DISPLAY_PLL_M1_DIVISOR_MASK 0x00001f00
#define DISPLAY_PLL_M2_DIVISOR_MASK 0x0000001f #define DISPLAY_PLL_M2_DIVISOR_MASK 0x0000001f
#define DISPLAY_PLL_IGD_M2_DIVISOR_MASK 0x000000ff
#define DISPLAY_PLL_N_DIVISOR_SHIFT 16 #define DISPLAY_PLL_N_DIVISOR_SHIFT 16
#define DISPLAY_PLL_M1_DIVISOR_SHIFT 8 #define DISPLAY_PLL_M1_DIVISOR_SHIFT 8
#define DISPLAY_PLL_M2_DIVISOR_SHIFT 0 #define DISPLAY_PLL_M2_DIVISOR_SHIFT 0
+99 -42
View File
@@ -234,13 +234,22 @@ get_pll_limits(pll_limits &limits)
// tested // tested
if (gInfo->shared_info->device_type.InGroup(INTEL_TYPE_G4x)) { if (gInfo->shared_info->device_type.InGroup(INTEL_TYPE_G4x)) {
// single LVDS output // TODO: support LVDS output limits as well
// NOTE: not sure these will work with CRT displays
static const pll_limits kLimits = { static const pll_limits kLimits = {
// p, p1, p2, high, n, m, m1, m2 // p, p1, p2, high, n, m, m1, m2
{ 28, 2, 14, false, 1, 104, 17, 5}, // min { 10, 1, 10, false, 1, 104, 17, 5}, // min
{112, 8, 0, true, 3, 138, 23, 11}, // max { 30, 3, 10, true, 4, 138, 23, 11}, // max
200000, 1750000, 3500000 270000, 1750000, 3500000
};
limits = kLimits;
} else if (gInfo->shared_info->device_type.InGroup(INTEL_TYPE_IGD)) {
// TODO: support LVDS output limits as well
// m1 is reserved and must be 0
static const 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, 256}, // max
200000, 1700000, 3500000
}; };
limits = kLimits; limits = kLimits;
} else if (gInfo->shared_info->device_type.InFamily(INTEL_TYPE_9xx)) { } else if (gInfo->shared_info->device_type.InFamily(INTEL_TYPE_9xx)) {
@@ -323,9 +332,10 @@ compute_pll_divisors(const display_mode &current, pll_divisors& divisors,
float best = requestedPixelClock; float best = requestedPixelClock;
pll_divisors bestDivisors; pll_divisors bestDivisors;
bool is_igd = gInfo->shared_info->device_type.InGroup(INTEL_TYPE_IGD);
for (divisors.m1 = limits.min.m1; divisors.m1 <= limits.max.m1; divisors.m1++) { for (divisors.m1 = limits.min.m1; divisors.m1 <= limits.max.m1; divisors.m1++) {
for (divisors.m2 = limits.min.m2; divisors.m2 < divisors.m1 for (divisors.m2 = limits.min.m2; divisors.m2 <= limits.max.m2
&& divisors.m2 <= limits.max.m2; divisors.m2++) { && ((divisors.m2 < divisors.m1) || is_igd); divisors.m2++) {
for (divisors.n = limits.min.n; divisors.n <= limits.max.n; for (divisors.n = limits.min.n; divisors.n <= limits.max.n;
divisors.n++) { divisors.n++) {
for (divisors.post1 = limits.min.post1; for (divisors.post1 = limits.min.post1;
@@ -397,19 +407,32 @@ retrieve_current_mode(display_mode& mode, uint32 pllRegister)
} }
pll_divisors divisors; pll_divisors divisors;
divisors.m1 = (pllDivisor & DISPLAY_PLL_M1_DIVISOR_MASK) if (gInfo->shared_info->device_type.InGroup(INTEL_TYPE_IGD)) {
>> DISPLAY_PLL_M1_DIVISOR_SHIFT; divisors.m1 = 0;
divisors.m2 = (pllDivisor & DISPLAY_PLL_M2_DIVISOR_MASK) divisors.m2 = (pllDivisor & DISPLAY_PLL_IGD_M2_DIVISOR_MASK)
>> DISPLAY_PLL_M2_DIVISOR_SHIFT; >> DISPLAY_PLL_M2_DIVISOR_SHIFT;
divisors.n = (pllDivisor & DISPLAY_PLL_N_DIVISOR_MASK) divisors.n = ((pllDivisor & DISPLAY_PLL_IGD_N_DIVISOR_MASK)
>> DISPLAY_PLL_N_DIVISOR_SHIFT; >> DISPLAY_PLL_N_DIVISOR_SHIFT) - 1;
} else {
divisors.m1 = (pllDivisor & DISPLAY_PLL_M1_DIVISOR_MASK)
>> DISPLAY_PLL_M1_DIVISOR_SHIFT;
divisors.m2 = (pllDivisor & DISPLAY_PLL_M2_DIVISOR_MASK)
>> DISPLAY_PLL_M2_DIVISOR_SHIFT;
divisors.n = (pllDivisor & DISPLAY_PLL_N_DIVISOR_MASK)
>> DISPLAY_PLL_N_DIVISOR_SHIFT;
}
pll_limits limits; pll_limits limits;
get_pll_limits(limits); get_pll_limits(limits);
if (gInfo->shared_info->device_type.InFamily(INTEL_TYPE_9xx)) { if (gInfo->shared_info->device_type.InFamily(INTEL_TYPE_9xx)) {
divisors.post1 = (pll & DISPLAY_PLL_9xx_POST1_DIVISOR_MASK) if (gInfo->shared_info->device_type.InGroup(INTEL_TYPE_IGD)) {
>> DISPLAY_PLL_POST1_DIVISOR_SHIFT; divisors.post1 = (pll & DISPLAY_PLL_IGD_POST1_DIVISOR_MASK)
>> DISPLAY_PLL_IGD_POST1_DIVISOR_SHIFT;
} else {
divisors.post1 = (pll & DISPLAY_PLL_9xx_POST1_DIVISOR_MASK)
>> DISPLAY_PLL_POST1_DIVISOR_SHIFT;
}
if (pllRegister == INTEL_DISPLAY_B_PLL if (pllRegister == INTEL_DISPLAY_B_PLL
&& !gInfo->shared_info->device_type.InGroup(INTEL_TYPE_96x)) { && !gInfo->shared_info->device_type.InGroup(INTEL_TYPE_96x)) {
@@ -725,7 +748,11 @@ if (first) {
} }
// Compute bitmask from p1 value // Compute bitmask from p1 value
dpll |= (1 << (divisors.post1 - 1)) << DISPLAY_PLL_POST1_DIVISOR_SHIFT; if (gInfo->shared_info->device_type.InGroup(INTEL_TYPE_IGD)) {
dpll |= (1 << (divisors.post1 - 1)) << DISPLAY_PLL_IGD_POST1_DIVISOR_SHIFT;
} else {
dpll |= (1 << (divisors.post1 - 1)) << DISPLAY_PLL_POST1_DIVISOR_SHIFT;
}
switch (divisors.post2) { switch (divisors.post2) {
case 5: case 5:
case 7: case 7:
@@ -739,13 +766,21 @@ if (first) {
// (I don't know how to detect that) // (I don't know how to detect that)
if ((dpll & DISPLAY_PLL_ENABLED) != 0) { if ((dpll & DISPLAY_PLL_ENABLED) != 0) {
write32(INTEL_DISPLAY_B_PLL_DIVISOR_0, if (gInfo->shared_info->device_type.InGroup(INTEL_TYPE_IGD)) {
(((divisors.n - 2) << DISPLAY_PLL_N_DIVISOR_SHIFT) write32(INTEL_DISPLAY_B_PLL_DIVISOR_0,
& DISPLAY_PLL_N_DIVISOR_MASK) (((1 << divisors.n) << DISPLAY_PLL_N_DIVISOR_SHIFT)
| (((divisors.m1 - 2) << DISPLAY_PLL_M1_DIVISOR_SHIFT) & DISPLAY_PLL_IGD_N_DIVISOR_MASK)
& DISPLAY_PLL_M1_DIVISOR_MASK) | (((divisors.m2 - 2) << DISPLAY_PLL_M2_DIVISOR_SHIFT)
| (((divisors.m2 - 2) << DISPLAY_PLL_M2_DIVISOR_SHIFT) & DISPLAY_PLL_IGD_M2_DIVISOR_MASK));
& DISPLAY_PLL_M2_DIVISOR_MASK)); } else {
write32(INTEL_DISPLAY_B_PLL_DIVISOR_0,
(((divisors.n - 2) << DISPLAY_PLL_N_DIVISOR_SHIFT)
& DISPLAY_PLL_N_DIVISOR_MASK)
| (((divisors.m1 - 2) << DISPLAY_PLL_M1_DIVISOR_SHIFT)
& DISPLAY_PLL_M1_DIVISOR_MASK)
| (((divisors.m2 - 2) << DISPLAY_PLL_M2_DIVISOR_SHIFT)
& DISPLAY_PLL_M2_DIVISOR_MASK));
}
write32(INTEL_DISPLAY_B_PLL, dpll & ~DISPLAY_PLL_ENABLED); write32(INTEL_DISPLAY_B_PLL, dpll & ~DISPLAY_PLL_ENABLED);
read32(INTEL_DISPLAY_B_PLL); read32(INTEL_DISPLAY_B_PLL);
spin(150); spin(150);
@@ -771,13 +806,21 @@ if (first) {
write32(INTEL_DISPLAY_LVDS_PORT, lvds); write32(INTEL_DISPLAY_LVDS_PORT, lvds);
read32(INTEL_DISPLAY_LVDS_PORT); read32(INTEL_DISPLAY_LVDS_PORT);
write32(INTEL_DISPLAY_B_PLL_DIVISOR_0, if (gInfo->shared_info->device_type.InGroup(INTEL_TYPE_IGD)) {
(((divisors.n - 2) << DISPLAY_PLL_N_DIVISOR_SHIFT) write32(INTEL_DISPLAY_B_PLL_DIVISOR_0,
& DISPLAY_PLL_N_DIVISOR_MASK) (((1 << divisors.n) << DISPLAY_PLL_N_DIVISOR_SHIFT)
| (((divisors.m1 - 2) << DISPLAY_PLL_M1_DIVISOR_SHIFT) & DISPLAY_PLL_IGD_N_DIVISOR_MASK)
& DISPLAY_PLL_M1_DIVISOR_MASK) | (((divisors.m2 - 2) << DISPLAY_PLL_M2_DIVISOR_SHIFT)
| (((divisors.m2 - 2) << DISPLAY_PLL_M2_DIVISOR_SHIFT) & DISPLAY_PLL_IGD_M2_DIVISOR_MASK));
& DISPLAY_PLL_M2_DIVISOR_MASK)); } else {
write32(INTEL_DISPLAY_B_PLL_DIVISOR_0,
(((divisors.n - 2) << DISPLAY_PLL_N_DIVISOR_SHIFT)
& DISPLAY_PLL_N_DIVISOR_MASK)
| (((divisors.m1 - 2) << DISPLAY_PLL_M1_DIVISOR_SHIFT)
& DISPLAY_PLL_M1_DIVISOR_MASK)
| (((divisors.m2 - 2) << DISPLAY_PLL_M2_DIVISOR_SHIFT)
& DISPLAY_PLL_M2_DIVISOR_MASK));
}
write32(INTEL_DISPLAY_B_PLL, dpll); write32(INTEL_DISPLAY_B_PLL, dpll);
read32(INTEL_DISPLAY_B_PLL); read32(INTEL_DISPLAY_B_PLL);
@@ -904,21 +947,35 @@ if (first) {
pll_divisors divisors; pll_divisors divisors;
compute_pll_divisors(target, divisors, false); compute_pll_divisors(target, divisors, false);
write32(INTEL_DISPLAY_A_PLL_DIVISOR_0, if (gInfo->shared_info->device_type.InGroup(INTEL_TYPE_IGD)) {
(((divisors.n - 2) << DISPLAY_PLL_N_DIVISOR_SHIFT) write32(INTEL_DISPLAY_A_PLL_DIVISOR_0,
& DISPLAY_PLL_N_DIVISOR_MASK) (((1 << divisors.n) << DISPLAY_PLL_N_DIVISOR_SHIFT)
| (((divisors.m1 - 2) << DISPLAY_PLL_M1_DIVISOR_SHIFT) & DISPLAY_PLL_IGD_N_DIVISOR_MASK)
& DISPLAY_PLL_M1_DIVISOR_MASK) | (((divisors.m2 - 2) << DISPLAY_PLL_M2_DIVISOR_SHIFT)
| (((divisors.m2 - 2) << DISPLAY_PLL_M2_DIVISOR_SHIFT) & DISPLAY_PLL_IGD_M2_DIVISOR_MASK));
& DISPLAY_PLL_M2_DIVISOR_MASK)); } else {
write32(INTEL_DISPLAY_A_PLL_DIVISOR_0,
(((divisors.n - 2) << DISPLAY_PLL_N_DIVISOR_SHIFT)
& DISPLAY_PLL_N_DIVISOR_MASK)
| (((divisors.m1 - 2) << DISPLAY_PLL_M1_DIVISOR_SHIFT)
& DISPLAY_PLL_M1_DIVISOR_MASK)
| (((divisors.m2 - 2) << DISPLAY_PLL_M2_DIVISOR_SHIFT)
& DISPLAY_PLL_M2_DIVISOR_MASK));
}
uint32 pll = DISPLAY_PLL_ENABLED | DISPLAY_PLL_NO_VGA_CONTROL; uint32 pll = DISPLAY_PLL_ENABLED | DISPLAY_PLL_NO_VGA_CONTROL;
if (gInfo->shared_info->device_type.InFamily(INTEL_TYPE_9xx)) { if (gInfo->shared_info->device_type.InFamily(INTEL_TYPE_9xx)) {
pll |= ((1 << (divisors.post1 - 1)) if (gInfo->shared_info->device_type.InGroup(INTEL_TYPE_IGD)) {
<< DISPLAY_PLL_POST1_DIVISOR_SHIFT) pll |= ((1 << (divisors.post1 - 1))
& DISPLAY_PLL_9xx_POST1_DIVISOR_MASK; << DISPLAY_PLL_IGD_POST1_DIVISOR_SHIFT)
// pll |= ((divisors.post1 - 1) << DISPLAY_PLL_POST1_DIVISOR_SHIFT) & DISPLAY_PLL_IGD_POST1_DIVISOR_MASK;
// & DISPLAY_PLL_9xx_POST1_DIVISOR_MASK; } else {
pll |= ((1 << (divisors.post1 - 1))
<< DISPLAY_PLL_POST1_DIVISOR_SHIFT)
& DISPLAY_PLL_9xx_POST1_DIVISOR_MASK;
// pll |= ((divisors.post1 - 1) << DISPLAY_PLL_POST1_DIVISOR_SHIFT)
// & DISPLAY_PLL_9xx_POST1_DIVISOR_MASK;
}
if (divisors.post2_high) if (divisors.post2_high)
pll |= DISPLAY_PLL_DIVIDE_HIGH; pll |= DISPLAY_PLL_DIVIDE_HIGH;
@@ -71,6 +71,9 @@ const struct supported_device {
{0x2e30, 0x2e32, INTEL_TYPE_GM45, "GMA_X4500_VGA"}, {0x2e30, 0x2e32, INTEL_TYPE_GM45, "GMA_X4500_VGA"},
{0x2a40, 0x2a42, INTEL_TYPE_GM45, "GM45"}, {0x2a40, 0x2a42, INTEL_TYPE_GM45, "GM45"},
{0xa000, 0xa001, INTEL_TYPE_IGDG, "Atom_Dx10"},
{0xa010, 0xa011, INTEL_TYPE_IGDGM, "Atom_N4x0"},
}; };
struct intel_info { struct intel_info {
@@ -140,7 +143,8 @@ determine_memory_sizes(intel_info &info, size_t &gttSize, size_t &stolenSize)
gttSize = 512 << 10; gttSize = 512 << 10;
break; break;
} }
} else if (info.type == INTEL_TYPE_G33) { } else if (info.type == INTEL_TYPE_G33
|| (info.type & INTEL_TYPE_GROUP_MASK) == INTEL_TYPE_IGD) {
switch (memoryConfig & G33_GTT_MASK) { switch (memoryConfig & G33_GTT_MASK) {
case G33_GTT_1M: case G33_GTT_1M:
gttSize = 1 << 20; gttSize = 1 << 20;
@@ -59,6 +59,9 @@ const struct supported_device {
{0x2e32, INTEL_TYPE_GM45, "GMA_X4500_VGA"}, {0x2e32, INTEL_TYPE_GM45, "GMA_X4500_VGA"},
{0x2a42, INTEL_TYPE_GM45, "GM45"}, {0x2a42, INTEL_TYPE_GM45, "GM45"},
{0xa001, INTEL_TYPE_IGDG, "Atom_Dx10"},
{0xa011, INTEL_TYPE_IGDGM, "Atom_N4x0"},
}; };
int32 api_version = B_CUR_DRIVER_API_VERSION; int32 api_version = B_CUR_DRIVER_API_VERSION;