Commit 6d857c18 authored by Mathieu Larouche's avatar Mathieu Larouche Committed by Dave Airlie

drm/mgag200: Add support for a new G200eW3 chipset

- Added support for the new deviceID for G200eW3
- Added PLL algorithm for the G200eW3
- Added some initialization code for G200eW3
Signed-off-by: default avatarMathieu Larouche <mathieu.larouche@matrox.com>
Signed-off-by: default avatarDave Airlie <airlied@redhat.com>
parent 44790462
...@@ -35,6 +35,7 @@ static const struct pci_device_id pciidlist[] = { ...@@ -35,6 +35,7 @@ static const struct pci_device_id pciidlist[] = {
{ PCI_VENDOR_ID_MATROX, 0x532, PCI_ANY_ID, PCI_ANY_ID, 0, 0, G200_WB }, { PCI_VENDOR_ID_MATROX, 0x532, PCI_ANY_ID, PCI_ANY_ID, 0, 0, G200_WB },
{ PCI_VENDOR_ID_MATROX, 0x533, PCI_ANY_ID, PCI_ANY_ID, 0, 0, G200_EH }, { PCI_VENDOR_ID_MATROX, 0x533, PCI_ANY_ID, PCI_ANY_ID, 0, 0, G200_EH },
{ PCI_VENDOR_ID_MATROX, 0x534, PCI_ANY_ID, PCI_ANY_ID, 0, 0, G200_ER }, { PCI_VENDOR_ID_MATROX, 0x534, PCI_ANY_ID, PCI_ANY_ID, 0, 0, G200_ER },
{ PCI_VENDOR_ID_MATROX, 0x536, PCI_ANY_ID, PCI_ANY_ID, 0, 0, G200_EW3 },
{0,} {0,}
}; };
......
...@@ -180,6 +180,7 @@ enum mga_type { ...@@ -180,6 +180,7 @@ enum mga_type {
G200_EV, G200_EV,
G200_EH, G200_EH,
G200_ER, G200_ER,
G200_EW3,
}; };
#define IS_G200_SE(mdev) (mdev->type == G200_SE_A || mdev->type == G200_SE_B) #define IS_G200_SE(mdev) (mdev->type == G200_SE_A || mdev->type == G200_SE_B)
......
...@@ -101,6 +101,7 @@ struct mga_i2c_chan *mgag200_i2c_create(struct drm_device *dev) ...@@ -101,6 +101,7 @@ struct mga_i2c_chan *mgag200_i2c_create(struct drm_device *dev)
case G200_SE_B: case G200_SE_B:
case G200_EV: case G200_EV:
case G200_WB: case G200_WB:
case G200_EW3:
data = 1; data = 1;
clock = 2; clock = 2;
break; break;
......
...@@ -82,12 +82,19 @@ static int mga_probe_vram(struct mga_device *mdev, void __iomem *mem) ...@@ -82,12 +82,19 @@ static int mga_probe_vram(struct mga_device *mdev, void __iomem *mem)
int orig; int orig;
int test1, test2; int test1, test2;
int orig1, orig2; int orig1, orig2;
unsigned int vram_size;
/* Probe */ /* Probe */
orig = ioread16(mem); orig = ioread16(mem);
iowrite16(0, mem); iowrite16(0, mem);
for (offset = 0x100000; offset < mdev->mc.vram_window; offset += 0x4000) { vram_size = mdev->mc.vram_window;
if ((mdev->type == G200_EW3) && (vram_size >= 0x1000000)) {
vram_size = vram_size - 0x400000;
}
for (offset = 0x100000; offset < vram_size; offset += 0x4000) {
orig1 = ioread8(mem + offset); orig1 = ioread8(mem + offset);
orig2 = ioread8(mem + offset + 0x100); orig2 = ioread8(mem + offset + 0x100);
......
...@@ -159,7 +159,7 @@ static int mga_g200wb_set_plls(struct mga_device *mdev, long clock) ...@@ -159,7 +159,7 @@ static int mga_g200wb_set_plls(struct mga_device *mdev, long clock)
{ {
unsigned int vcomax, vcomin, pllreffreq; unsigned int vcomax, vcomin, pllreffreq;
unsigned int delta, tmpdelta; unsigned int delta, tmpdelta;
unsigned int testp, testm, testn; unsigned int testp, testm, testn, testp2;
unsigned int p, m, n; unsigned int p, m, n;
unsigned int computed; unsigned int computed;
int i, j, tmpcount, vcount; int i, j, tmpcount, vcount;
...@@ -167,31 +167,71 @@ static int mga_g200wb_set_plls(struct mga_device *mdev, long clock) ...@@ -167,31 +167,71 @@ static int mga_g200wb_set_plls(struct mga_device *mdev, long clock)
u8 tmp; u8 tmp;
m = n = p = 0; m = n = p = 0;
vcomax = 550000;
vcomin = 150000;
pllreffreq = 48000;
delta = 0xffffffff; delta = 0xffffffff;
for (testp = 1; testp < 9; testp++) { if (mdev->type == G200_EW3) {
if (clock * testp > vcomax)
continue; vcomax = 800000;
if (clock * testp < vcomin) vcomin = 400000;
continue; pllreffreq = 25000;
for (testp = 1; testp < 8; testp++) {
for (testp2 = 1; testp2 < 8; testp2++) {
if (testp < testp2)
continue;
if ((clock * testp * testp2) > vcomax)
continue;
if ((clock * testp * testp2) < vcomin)
continue;
for (testm = 1; testm < 26; testm++) {
for (testn = 32; testn < 2048 ; testn++) {
computed = (pllreffreq * testn) /
(testm * testp * testp2);
if (computed > clock)
tmpdelta = computed - clock;
else
tmpdelta = clock - computed;
if (tmpdelta < delta) {
delta = tmpdelta;
m = ((testn & 0x100) >> 1) |
(testm);
n = (testn & 0xFF);
p = ((testn & 0x600) >> 3) |
(testp2 << 3) |
(testp);
}
}
}
}
}
} else {
for (testm = 1; testm < 17; testm++) { vcomax = 550000;
for (testn = 1; testn < 151; testn++) { vcomin = 150000;
computed = (pllreffreq * testn) / pllreffreq = 48000;
(testm * testp);
if (computed > clock) for (testp = 1; testp < 9; testp++) {
tmpdelta = computed - clock; if (clock * testp > vcomax)
else continue;
tmpdelta = clock - computed; if (clock * testp < vcomin)
if (tmpdelta < delta) { continue;
delta = tmpdelta;
n = testn - 1; for (testm = 1; testm < 17; testm++) {
m = (testm - 1) | ((n >> 1) & 0x80); for (testn = 1; testn < 151; testn++) {
p = testp - 1; computed = (pllreffreq * testn) /
(testm * testp);
if (computed > clock)
tmpdelta = computed - clock;
else
tmpdelta = clock - computed;
if (tmpdelta < delta) {
delta = tmpdelta;
n = testn - 1;
m = (testm - 1) |
((n >> 1) & 0x80);
p = testp - 1;
}
} }
} }
} }
...@@ -569,6 +609,7 @@ static int mga_crtc_set_plls(struct mga_device *mdev, long clock) ...@@ -569,6 +609,7 @@ static int mga_crtc_set_plls(struct mga_device *mdev, long clock)
return mga_g200se_set_plls(mdev, clock); return mga_g200se_set_plls(mdev, clock);
break; break;
case G200_WB: case G200_WB:
case G200_EW3:
return mga_g200wb_set_plls(mdev, clock); return mga_g200wb_set_plls(mdev, clock);
break; break;
case G200_EV: case G200_EV:
...@@ -820,6 +861,7 @@ static int mga_crtc_mode_set(struct drm_crtc *crtc, ...@@ -820,6 +861,7 @@ static int mga_crtc_mode_set(struct drm_crtc *crtc,
option2 = 0x00008000; option2 = 0x00008000;
break; break;
case G200_WB: case G200_WB:
case G200_EW3:
dacvalue[MGA1064_VREF_CTL] = 0x07; dacvalue[MGA1064_VREF_CTL] = 0x07;
option = 0x41049120; option = 0x41049120;
option2 = 0x0000b000; option2 = 0x0000b000;
...@@ -875,7 +917,10 @@ static int mga_crtc_mode_set(struct drm_crtc *crtc, ...@@ -875,7 +917,10 @@ static int mga_crtc_mode_set(struct drm_crtc *crtc,
if (IS_G200_SE(mdev) && if (IS_G200_SE(mdev) &&
((i == 0x2c) || (i == 0x2d) || (i == 0x2e))) ((i == 0x2c) || (i == 0x2d) || (i == 0x2e)))
continue; continue;
if ((mdev->type == G200_EV || mdev->type == G200_WB || mdev->type == G200_EH) && if ((mdev->type == G200_EV ||
mdev->type == G200_WB ||
mdev->type == G200_EH ||
mdev->type == G200_EW3) &&
(i >= 0x44) && (i <= 0x4e)) (i >= 0x44) && (i <= 0x4e))
continue; continue;
...@@ -977,7 +1022,7 @@ static int mga_crtc_mode_set(struct drm_crtc *crtc, ...@@ -977,7 +1022,7 @@ static int mga_crtc_mode_set(struct drm_crtc *crtc,
else else
ext_vga[3] = ((1 << bppshift) - 1) | 0x80; ext_vga[3] = ((1 << bppshift) - 1) | 0x80;
ext_vga[4] = 0; ext_vga[4] = 0;
if (mdev->type == G200_WB) if (mdev->type == G200_WB || mdev->type == G200_EW3)
ext_vga[1] |= 0x88; ext_vga[1] |= 0x88;
/* Set pixel clocks */ /* Set pixel clocks */
...@@ -993,6 +1038,9 @@ static int mga_crtc_mode_set(struct drm_crtc *crtc, ...@@ -993,6 +1038,9 @@ static int mga_crtc_mode_set(struct drm_crtc *crtc,
if (mdev->type == G200_ER) if (mdev->type == G200_ER)
WREG_ECRT(0x24, 0x5); WREG_ECRT(0x24, 0x5);
if (mdev->type == G200_EW3)
WREG_ECRT(0x34, 0x5);
if (mdev->type == G200_EV) { if (mdev->type == G200_EV) {
WREG_ECRT(6, 0); WREG_ECRT(6, 0);
} }
...@@ -1205,7 +1253,7 @@ static void mga_crtc_prepare(struct drm_crtc *crtc) ...@@ -1205,7 +1253,7 @@ static void mga_crtc_prepare(struct drm_crtc *crtc)
WREG_SEQ(1, tmp | 0x20); WREG_SEQ(1, tmp | 0x20);
} }
if (mdev->type == G200_WB) if (mdev->type == G200_WB || mdev->type == G200_EW3)
mga_g200wb_prepare(crtc); mga_g200wb_prepare(crtc);
WREG_CRT(17, 0); WREG_CRT(17, 0);
...@@ -1222,7 +1270,7 @@ static void mga_crtc_commit(struct drm_crtc *crtc) ...@@ -1222,7 +1270,7 @@ static void mga_crtc_commit(struct drm_crtc *crtc)
const struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private; const struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private;
u8 tmp; u8 tmp;
if (mdev->type == G200_WB) if (mdev->type == G200_WB || mdev->type == G200_EW3)
mga_g200wb_commit(crtc); mga_g200wb_commit(crtc);
if (mdev->type == G200_SE_A || mdev->type == G200_SE_B) { if (mdev->type == G200_SE_A || mdev->type == G200_SE_B) {
......
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