Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

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
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -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, 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, 0x536, PCI_ANY_ID, PCI_ANY_ID, 0, 0, G200_EW3 },
	{0,}
};

+1 −0
Original line number Diff line number Diff line
@@ -180,6 +180,7 @@ enum mga_type {
	G200_EV,
	G200_EH,
	G200_ER,
	G200_EW3,
};

#define IS_G200_SE(mdev) (mdev->type == G200_SE_A || mdev->type == G200_SE_B)
+1 −0
Original line number Diff line number Diff line
@@ -101,6 +101,7 @@ struct mga_i2c_chan *mgag200_i2c_create(struct drm_device *dev)
	case G200_SE_B:
	case G200_EV:
	case G200_WB:
	case G200_EW3:
		data = 1;
		clock = 2;
		break;
+8 −1
Original line number Diff line number Diff line
@@ -82,12 +82,19 @@ static int mga_probe_vram(struct mga_device *mdev, void __iomem *mem)
	int orig;
	int test1, test2;
	int orig1, orig2;
	unsigned int vram_size;

	/* Probe */
	orig = ioread16(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);
		orig2 = ioread8(mem + offset + 0x100);

+74 −26
Original line number Diff line number Diff line
@@ -159,7 +159,7 @@ static int mga_g200wb_set_plls(struct mga_device *mdev, long clock)
{
	unsigned int vcomax, vcomin, pllreffreq;
	unsigned int delta, tmpdelta;
	unsigned int testp, testm, testn;
	unsigned int testp, testm, testn, testp2;
	unsigned int p, m, n;
	unsigned int computed;
	int i, j, tmpcount, vcount;
@@ -167,12 +167,50 @@ static int mga_g200wb_set_plls(struct mga_device *mdev, long clock)
	u8 tmp;

	m = n = p = 0;

	delta = 0xffffffff;

	if (mdev->type == G200_EW3) {

		vcomax = 800000;
		vcomin = 400000;
		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 {

		vcomax = 550000;
		vcomin = 150000;
		pllreffreq = 48000;

	delta = 0xffffffff;

		for (testp = 1; testp < 9; testp++) {
			if (clock * testp > vcomax)
				continue;
@@ -190,12 +228,14 @@ static int mga_g200wb_set_plls(struct mga_device *mdev, long clock)
					if (tmpdelta < delta) {
						delta = tmpdelta;
						n = testn - 1;
					m = (testm - 1) | ((n >> 1) & 0x80);
						m = (testm - 1) |
							((n >> 1) & 0x80);
						p = testp - 1;
					}
				}
			}
		}
	}

	for (i = 0; i <= 32 && pll_locked == false; i++) {
		if (i > 0) {
@@ -569,6 +609,7 @@ static int mga_crtc_set_plls(struct mga_device *mdev, long clock)
		return mga_g200se_set_plls(mdev, clock);
		break;
	case G200_WB:
	case G200_EW3:
		return mga_g200wb_set_plls(mdev, clock);
		break;
	case G200_EV:
@@ -820,6 +861,7 @@ static int mga_crtc_mode_set(struct drm_crtc *crtc,
		option2 = 0x00008000;
		break;
	case G200_WB:
	case G200_EW3:
		dacvalue[MGA1064_VREF_CTL] = 0x07;
		option = 0x41049120;
		option2 = 0x0000b000;
@@ -875,7 +917,10 @@ static int mga_crtc_mode_set(struct drm_crtc *crtc,
		if (IS_G200_SE(mdev) &&
		    ((i == 0x2c) || (i == 0x2d) || (i == 0x2e)))
			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))
			continue;

@@ -977,7 +1022,7 @@ static int mga_crtc_mode_set(struct drm_crtc *crtc,
	else
		ext_vga[3] = ((1 << bppshift) - 1) | 0x80;
	ext_vga[4] = 0;
	if (mdev->type == G200_WB)
	if (mdev->type == G200_WB || mdev->type == G200_EW3)
		ext_vga[1] |= 0x88;

	/* Set pixel clocks */
@@ -993,6 +1038,9 @@ static int mga_crtc_mode_set(struct drm_crtc *crtc,
	if (mdev->type == G200_ER)
		WREG_ECRT(0x24, 0x5);

	if (mdev->type == G200_EW3)
		WREG_ECRT(0x34, 0x5);

	if (mdev->type == G200_EV) {
		WREG_ECRT(6, 0);
	}
@@ -1205,7 +1253,7 @@ static void mga_crtc_prepare(struct drm_crtc *crtc)
		WREG_SEQ(1, tmp | 0x20);
	}

	if (mdev->type == G200_WB)
	if (mdev->type == G200_WB || mdev->type == G200_EW3)
		mga_g200wb_prepare(crtc);

	WREG_CRT(17, 0);
@@ -1222,7 +1270,7 @@ static void mga_crtc_commit(struct drm_crtc *crtc)
	const struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private;
	u8 tmp;

	if (mdev->type == G200_WB)
	if (mdev->type == G200_WB || mdev->type == G200_EW3)
		mga_g200wb_commit(crtc);

	if (mdev->type == G200_SE_A || mdev->type == G200_SE_B) {