intel_extreme: updated PLL restricts, updated set- and proposemode. Requested modes are now set more precise.
This commit is contained in:
@@ -273,42 +273,21 @@ intel_propose_display_mode(display_mode* target, const display_mode* low,
|
|||||||
{
|
{
|
||||||
CALLED();
|
CALLED();
|
||||||
|
|
||||||
// first search for the specified mode in the list, if no mode is found
|
display_mode mode = *target;
|
||||||
// try to fix the target mode in sanitize_display_mode
|
|
||||||
// TODO: Only sanitize_display_mode should be used. However, at the moment
|
|
||||||
// the mode constraints are not optimal and do not work for all
|
|
||||||
// configurations.
|
|
||||||
uint32 VirtualWidth = target->virtual_width;
|
|
||||||
uint32 VirtualHeight = target->virtual_height;
|
|
||||||
float RefreshRate = (float)target->timing.pixel_clock /
|
|
||||||
(target->timing.h_total * target->timing.v_total);
|
|
||||||
|
|
||||||
for (uint32 i = 0; i < gInfo->shared_info->mode_count; i++) {
|
if (sanitize_display_mode(*target)) {
|
||||||
display_mode *mode = &gInfo->mode_list[i];
|
TRACE("Video mode was adjusted by sanitize_display_mode\n");
|
||||||
|
TRACE("Initial mode: Hd %d Hs %d He %d Ht %d Vd %d Vs %d Ve %d Vt %d\n",
|
||||||
// TODO: improve this, ie. adapt pixel clock to allowed values!!!
|
mode.timing.h_display, mode.timing.h_sync_start,
|
||||||
|
mode.timing.h_sync_end, mode.timing.h_total,
|
||||||
if (target->timing.h_display != mode->timing.h_display
|
mode.timing.v_display, mode.timing.v_sync_start,
|
||||||
|| target->timing.v_display != mode->timing.v_display
|
mode.timing.v_sync_end, mode.timing.v_total);
|
||||||
|| target->space != mode->space) {
|
TRACE("Sanitized: Hd %d Hs %d He %d Ht %d Vd %d Vs %d Ve %d Vt %d\n",
|
||||||
continue;
|
target->timing.h_display, target->timing.h_sync_start,
|
||||||
|
target->timing.h_sync_end, target->timing.h_total,
|
||||||
|
target->timing.v_display, target->timing.v_sync_start,
|
||||||
|
target->timing.v_sync_end, target->timing.v_total);
|
||||||
}
|
}
|
||||||
|
|
||||||
*target = *mode;
|
|
||||||
// retain requested virtual size
|
|
||||||
target->virtual_width = VirtualWidth;
|
|
||||||
target->virtual_height = VirtualHeight;
|
|
||||||
// retain requested refreshrate
|
|
||||||
target->timing.pixel_clock =
|
|
||||||
target->timing.h_total * target->timing.v_total * RefreshRate;
|
|
||||||
|
|
||||||
// (most) modeflags are outputs from us (the driver). So we should
|
|
||||||
// set them depending on the mode and the current hardware config
|
|
||||||
target->flags |= B_SCROLL;
|
|
||||||
return B_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
sanitize_display_mode(*target);
|
|
||||||
// (most) modeflags are outputs from us (the driver). So we should
|
// (most) modeflags are outputs from us (the driver). So we should
|
||||||
// set them depending on the mode and the current hardware config
|
// set them depending on the mode and the current hardware config
|
||||||
target->flags |= B_SCROLL;
|
target->flags |= B_SCROLL;
|
||||||
@@ -329,19 +308,6 @@ intel_set_display_mode(display_mode* mode)
|
|||||||
|
|
||||||
display_mode target = *mode;
|
display_mode target = *mode;
|
||||||
|
|
||||||
if (sanitize_display_mode(target)) { //should be in proposemode..
|
|
||||||
TRACE("Video mode was adjusted by sanitize_display_mode\n");
|
|
||||||
TRACE("Initial mode: Hd %d Hs %d He %d Ht %d Vd %d Vs %d Ve %d Vt %d\n",
|
|
||||||
mode->timing.h_display, mode->timing.h_sync_start,
|
|
||||||
mode->timing.h_sync_end, mode->timing.h_total,
|
|
||||||
mode->timing.v_display, mode->timing.v_sync_start,
|
|
||||||
mode->timing.v_sync_end, mode->timing.v_total);
|
|
||||||
TRACE("Sanitized: Hd %d Hs %d He %d Ht %d Vd %d Vs %d Ve %d Vt %d\n",
|
|
||||||
target.timing.h_display, target.timing.h_sync_start,
|
|
||||||
target.timing.h_sync_end, target.timing.h_total,
|
|
||||||
target.timing.v_display, target.timing.v_sync_start,
|
|
||||||
target.timing.v_sync_end, target.timing.v_total);
|
|
||||||
}
|
|
||||||
if (intel_propose_display_mode(&target, &target, &target) != B_OK)
|
if (intel_propose_display_mode(&target, &target, &target) != B_OK)
|
||||||
return B_BAD_VALUE;
|
return B_BAD_VALUE;
|
||||||
|
|
||||||
|
|||||||
@@ -39,89 +39,86 @@
|
|||||||
#define CALLED(x...) TRACE("CALLED %s\n", __PRETTY_FUNCTION__)
|
#define CALLED(x...) TRACE("CALLED %s\n", __PRETTY_FUNCTION__)
|
||||||
|
|
||||||
|
|
||||||
// PLL limits, taken from programming manual when available, and from Linux KMS
|
// PLL limits, taken from i915 DRM driver. However, note that we use the values of
|
||||||
// drivers otherwise. However, note that we use the values of N+2, M1+2 and
|
// N+2, M1+2 and M2+2 here, the - 2 being applied when we write the values to the registers.
|
||||||
// M2+2 here, the - 2 being applied when we write the values to the registers.
|
|
||||||
|
|
||||||
static pll_limits kLimits85x = {
|
static pll_limits kLimits85x = {
|
||||||
// p, p1, p2, n, m, m1, m2
|
// p, p1, p2, n, m, m1, m2
|
||||||
{ 4, 2, 2, 5, 96, 20, 8},
|
{ 4, 2, 2, 4, 96, 20, 8},
|
||||||
{128, 33, 4, 18, 140, 28, 18},
|
{128, 33, 4, 18, 140, 28, 18},
|
||||||
165000, 930000, 1400000
|
165000, 908000, 1512000
|
||||||
};
|
};
|
||||||
|
|
||||||
// TODO according to the docs, the limits for 9xx anf G45 should be the same.
|
|
||||||
// For Iron Lake, a new set of timings is introduced along with the FDI system,
|
// For Iron Lake, a new set of timings is introduced along with the FDI system,
|
||||||
// and carried on to later cards with just one further change (to the P2 cutoff
|
// and carried on to later cards with just one further change (to the P2 cutoff
|
||||||
// frequency) in Sandy Bridge.
|
// frequency) in Sandy Bridge.
|
||||||
//
|
|
||||||
// So, it makes no sense to have separate limits and algorithm for 9xx and G45.
|
|
||||||
|
|
||||||
static pll_limits kLimits9xxSdvo = {
|
static pll_limits kLimits9xxSdvo = {
|
||||||
// p, p1, p2, n, m, m1, m2
|
// p, p1, p2, n, m, m1, m2
|
||||||
{ 5, 1, 5, 5, 70, 12, 7}, // min
|
{ 5, 1, 5, 3, 70, 10, 5}, // min
|
||||||
{ 80, 8, 10, 10, 120, 22, 11}, // max
|
{ 80, 8, 10, 8, 120, 20, 9}, // max
|
||||||
200000, 1400000, 2800000
|
200000, 1400000, 2800000
|
||||||
};
|
};
|
||||||
|
|
||||||
static pll_limits kLimits9xxLvds = {
|
static pll_limits kLimits9xxLvds = {
|
||||||
// p, p1, p2, n, m, m1, m2
|
// p, p1, p2, n, m, m1, m2
|
||||||
{ 7, 1, 7, 1, 70, 8, 3}, // min
|
{ 7, 1, 7, 3, 70, 10, 5}, // min
|
||||||
{ 98, 8, 14, 6, 120, 18, 7}, // max
|
{ 98, 8, 14, 8, 120, 20, 9}, // max
|
||||||
112000, 1400000, 2800000
|
112000, 1400000, 2800000
|
||||||
};
|
};
|
||||||
|
|
||||||
// Limits for G45 cards taken from g45_vlo3_register_0_0_0.pdf, page 46
|
// Limits for G45 cards taken from i915 DRM driver, mixed with old setup
|
||||||
// Note that n here is actually n+2, but m1 and m2 are as in the datasheet.
|
// plus tests to accomodate lower resolutions with still correct refresh.
|
||||||
|
// Note that n here is actually n+2, same applies to m1 and m2.
|
||||||
|
|
||||||
static pll_limits kLimitsG4xSdvo = {
|
static pll_limits kLimitsG4xSdvo = {
|
||||||
// p, p1, p2, n, m, m1, m2
|
// p, p1, p2, n, m, m1, m2
|
||||||
{ 5, 1, 5, 5, 70, 12, 7}, // min
|
{ 10, 1, 10, 3, 104, 19, 7}, // min
|
||||||
{ 80, 8, 10, 10, 120, 22, 11}, // max
|
{ 80, 8, 10, 8, 138, 25, 13}, // max
|
||||||
270000, 1400000, 2800000
|
270000, 1750000, 3500000
|
||||||
};
|
};
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
static pll_limits kLimitsG4xHdmi = {
|
static pll_limits kLimitsG4xHdmi = {
|
||||||
// p, p1, p2, n, m, m1, m2
|
// p, p1, p2, n, m, m1, m2
|
||||||
{ 5, 1, 5, 5, 70, 12, 7}, // min
|
{ 5, 1, 5, 3, 104, 18, 7}, // min
|
||||||
{ 80, 8, 10, 10, 120, 22, 11}, // max
|
{ 80, 8, 10, 8, 138, 25, 13}, // max
|
||||||
165000, 1400000, 2800000
|
165000, 1750000, 3500000
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static pll_limits kLimitsG4xLvdsSingle = {
|
static pll_limits kLimitsG4xLvdsSingle = {
|
||||||
// p, p1, p2, n, m, m1, m2
|
// p, p1, p2, n, m, m1, m2
|
||||||
{ 7, 1, 14, 5, 70, 12, 7}, // min
|
{ 28, 2, 14, 3, 104, 19, 7}, // min
|
||||||
{ 98, 8, 14, 10, 120, 22, 11}, // max
|
{112, 8, 14, 8, 138, 25, 13}, // max
|
||||||
0, 1400000, 2800000
|
0, 1750000, 3500000
|
||||||
};
|
};
|
||||||
|
|
||||||
static pll_limits kLimitsG4xLvdsDual = {
|
static pll_limits kLimitsG4xLvdsDual = {
|
||||||
// p, p1, p2, n, m, m1, m2
|
// p, p1, p2, n, m, m1, m2
|
||||||
{ 14, 2, 7, 5, 70, 12, 7}, // min
|
{ 14, 2, 7, 3, 104, 19, 7}, // min
|
||||||
{ 42, 6, 7, 10, 120, 22, 11}, // max
|
{ 42, 6, 7, 8, 138, 25, 13}, // max
|
||||||
0, 1400000, 2800000
|
0, 1750000, 3500000
|
||||||
};
|
};
|
||||||
|
|
||||||
static pll_limits kLimitsIlkDac = {
|
static pll_limits kLimitsIlkDac = {
|
||||||
// p, p1, p2, n, m, m1, m2
|
// p, p1, p2, n, m, m1, m2
|
||||||
{ 5, 1, 5, 3, 79, 14, 7}, // min
|
{ 5, 1, 5, 3, 79, 14, 7}, // min
|
||||||
{ 80, 8, 10, 8, 118, 24, 11}, // max
|
{ 80, 8, 10, 7, 127, 24, 11}, // max
|
||||||
225000, 1760000, 3510000
|
225000, 1760000, 3510000
|
||||||
};
|
};
|
||||||
|
|
||||||
static pll_limits kLimitsIlkLvdsSingle = {
|
static pll_limits kLimitsIlkLvdsSingle = {
|
||||||
// p, p1, p2, n, m, m1, m2
|
// p, p1, p2, n, m, m1, m2
|
||||||
{ 28, 2, 14, 3, 79, 14, 7}, // min
|
{ 28, 2, 14, 3, 79, 14, 7}, // min
|
||||||
{112, 8, 14, 8, 118, 24, 11}, // max
|
{112, 8, 14, 5, 118, 24, 11}, // max
|
||||||
225000, 1760000, 3510000
|
225000, 1760000, 3510000
|
||||||
};
|
};
|
||||||
|
|
||||||
static pll_limits kLimitsIlkLvdsDual = {
|
static pll_limits kLimitsIlkLvdsDual = {
|
||||||
// p, p1, p2, n, m, m1, m2
|
// p, p1, p2, n, m, m1, m2
|
||||||
{ 14, 2, 7, 3, 79, 14, 7}, // min
|
{ 14, 2, 7, 3, 79, 14, 7}, // min
|
||||||
{ 56, 8, 7, 8, 127, 24, 11}, // max
|
{ 56, 8, 7, 5, 127, 24, 11}, // max
|
||||||
225000, 1760000, 3510000
|
225000, 1760000, 3510000
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -129,14 +126,14 @@ static pll_limits kLimitsIlkLvdsDual = {
|
|||||||
static pll_limits kLimitsIlkLvdsSingle100 = {
|
static pll_limits kLimitsIlkLvdsSingle100 = {
|
||||||
// p, p1, p2, n, m, m1, m2
|
// p, p1, p2, n, m, m1, m2
|
||||||
{ 28, 2, 14, 3, 79, 14, 7}, // min
|
{ 28, 2, 14, 3, 79, 14, 7}, // min
|
||||||
{112, 8, 14, 8, 126, 24, 11}, // max
|
{112, 8, 14, 4, 126, 24, 11}, // max
|
||||||
225000, 1760000, 3510000
|
225000, 1760000, 3510000
|
||||||
};
|
};
|
||||||
|
|
||||||
static pll_limits kLimitsIlkLvdsDual100 = {
|
static pll_limits kLimitsIlkLvdsDual100 = {
|
||||||
// p, p1, p2, n, m, m1, m2
|
// p, p1, p2, n, m, m1, m2
|
||||||
{ 14, 2, 7, 3, 79, 14, 7}, // min
|
{ 14, 2, 7, 3, 79, 14, 7}, // min
|
||||||
{ 42, 6, 7, 8, 126, 24, 11}, // max
|
{ 42, 6, 7, 5, 126, 24, 11}, // max
|
||||||
225000, 1760000, 3510000
|
225000, 1760000, 3510000
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -345,8 +342,8 @@ compute_dpll_g4x(display_mode* current, pll_divisors* divisors, bool isLVDS)
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
float error = fabs(requestedPixelClock
|
float error = fabs(requestedPixelClock
|
||||||
- ((referenceClock * divisors->m) / divisors->n)
|
- (referenceClock * divisors->m)
|
||||||
/ divisors->p);
|
/ (divisors->n * divisors->p));
|
||||||
if (error < best) {
|
if (error < best) {
|
||||||
best = error;
|
best = error;
|
||||||
bestDivisors = *divisors;
|
bestDivisors = *divisors;
|
||||||
@@ -360,7 +357,7 @@ compute_dpll_g4x(display_mode* current, pll_divisors* divisors, bool isLVDS)
|
|||||||
}
|
}
|
||||||
*divisors = bestDivisors;
|
*divisors = bestDivisors;
|
||||||
TRACE("%s: best MHz: %g (error: %g)\n", __func__,
|
TRACE("%s: best MHz: %g (error: %g)\n", __func__,
|
||||||
((referenceClock * divisors->m) / divisors->n) / divisors->p,
|
(referenceClock * divisors->m) / (divisors->n * divisors->p),
|
||||||
best);
|
best);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -423,8 +420,8 @@ compute_dpll_9xx(display_mode* current, pll_divisors* divisors, bool isLVDS)
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
float error = fabs(requestedPixelClock
|
float error = fabs(requestedPixelClock
|
||||||
- ((referenceClock * divisors->m) / divisors->n)
|
- (referenceClock * divisors->m)
|
||||||
/ divisors->p);
|
/ (divisors->n * divisors->p));
|
||||||
if (error < best) {
|
if (error < best) {
|
||||||
best = error;
|
best = error;
|
||||||
bestDivisors = *divisors;
|
bestDivisors = *divisors;
|
||||||
@@ -443,7 +440,7 @@ compute_dpll_9xx(display_mode* current, pll_divisors* divisors, bool isLVDS)
|
|||||||
debugger("No valid PLL configuration found");
|
debugger("No valid PLL configuration found");
|
||||||
else {
|
else {
|
||||||
TRACE("%s: best MHz: %g (error: %g)\n", __func__,
|
TRACE("%s: best MHz: %g (error: %g)\n", __func__,
|
||||||
((referenceClock * divisors->m) / divisors->n) / divisors->p,
|
(referenceClock * divisors->m) / (divisors->n * divisors->p),
|
||||||
best);
|
best);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user