Commit e829d7ef authored by Mathieu Larouche's avatar Mathieu Larouche Committed by Dave Airlie

drm/mgag200: Add support for a new rev of G200e

- Added PLL algorithm for a new rev of G200e
- Removed the bandwidth limitation for the new G200e
Signed-off-by: default avatarMathieu Larouche <mathieu.larouche@matrox.com>
Signed-off-by: default avatarDave Airlie <airlied@redhat.com>
parent 6d857c18
...@@ -104,6 +104,8 @@ static bool mga_crtc_mode_fixup(struct drm_crtc *crtc, ...@@ -104,6 +104,8 @@ static bool mga_crtc_mode_fixup(struct drm_crtc *crtc,
return true; return true;
} }
#define P_ARRAY_SIZE 9
static int mga_g200se_set_plls(struct mga_device *mdev, long clock) static int mga_g200se_set_plls(struct mga_device *mdev, long clock)
{ {
unsigned int vcomax, vcomin, pllreffreq; unsigned int vcomax, vcomin, pllreffreq;
...@@ -111,37 +113,97 @@ static int mga_g200se_set_plls(struct mga_device *mdev, long clock) ...@@ -111,37 +113,97 @@ static int mga_g200se_set_plls(struct mga_device *mdev, long clock)
unsigned int testp, testm, testn; unsigned int testp, testm, testn;
unsigned int p, m, n; unsigned int p, m, n;
unsigned int computed; unsigned int computed;
unsigned int pvalues_e4[P_ARRAY_SIZE] = {16, 14, 12, 10, 8, 6, 4, 2, 1};
unsigned int fvv;
unsigned int i;
m = n = p = 0; if (mdev->unique_rev_id <= 0x03) {
vcomax = 320000;
vcomin = 160000;
pllreffreq = 25000;
delta = 0xffffffff; m = n = p = 0;
permitteddelta = clock * 5 / 1000; vcomax = 320000;
vcomin = 160000;
pllreffreq = 25000;
for (testp = 8; testp > 0; testp /= 2) { delta = 0xffffffff;
if (clock * testp > vcomax) permitteddelta = clock * 5 / 1000;
continue;
if (clock * testp < vcomin)
continue;
for (testn = 17; testn < 256; testn++) { for (testp = 8; testp > 0; testp /= 2) {
for (testm = 1; testm < 32; testm++) { if (clock * testp > vcomax)
computed = (pllreffreq * testn) / continue;
(testm * testp); if (clock * testp < vcomin)
if (computed > clock) continue;
tmpdelta = computed - clock;
else for (testn = 17; testn < 256; testn++) {
tmpdelta = clock - computed; for (testm = 1; testm < 32; testm++) {
if (tmpdelta < delta) { computed = (pllreffreq * testn) /
delta = tmpdelta; (testm * testp);
m = testm - 1; if (computed > clock)
n = testn - 1; tmpdelta = computed - clock;
p = testp - 1; else
tmpdelta = clock - computed;
if (tmpdelta < delta) {
delta = tmpdelta;
m = testm - 1;
n = testn - 1;
p = testp - 1;
}
}
}
}
} else {
m = n = p = 0;
vcomax = 1600000;
vcomin = 800000;
pllreffreq = 25000;
if (clock < 25000)
clock = 25000;
clock = clock * 2;
delta = 0xFFFFFFFF;
/* Permited delta is 0.5% as VESA Specification */
permitteddelta = clock * 5 / 1000;
for (i = 0 ; i < P_ARRAY_SIZE ; i++) {
testp = pvalues_e4[i];
if ((clock * testp) > vcomax)
continue;
if ((clock * testp) < vcomin)
continue;
for (testn = 50; testn <= 256; testn++) {
for (testm = 1; testm <= 32; testm++) {
computed = (pllreffreq * testn) /
(testm * testp);
if (computed > clock)
tmpdelta = computed - clock;
else
tmpdelta = clock - computed;
if (tmpdelta < delta) {
delta = tmpdelta;
m = testm - 1;
n = testn - 1;
p = testp - 1;
}
} }
} }
} }
fvv = pllreffreq * testn / testm;
fvv = (fvv - 800000) / 50000;
if (fvv > 15)
fvv = 15;
p |= (fvv << 4);
m |= 0x80;
clock = clock / 2;
} }
if (delta > permitteddelta) { if (delta > permitteddelta) {
...@@ -1540,7 +1602,7 @@ static int mga_vga_mode_valid(struct drm_connector *connector, ...@@ -1540,7 +1602,7 @@ static int mga_vga_mode_valid(struct drm_connector *connector,
if (mga_vga_calculate_mode_bandwidth(mode, bpp) if (mga_vga_calculate_mode_bandwidth(mode, bpp)
> (24400 * 1024)) > (24400 * 1024))
return MODE_BANDWIDTH; return MODE_BANDWIDTH;
} else if (mdev->unique_rev_id >= 0x02) { } else if (mdev->unique_rev_id == 0x02) {
if (mode->hdisplay > 1920) if (mode->hdisplay > 1920)
return MODE_VIRTUAL_X; return MODE_VIRTUAL_X;
if (mode->vdisplay > 1200) if (mode->vdisplay > 1200)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment