Commit ac5c15fa authored by Roy Spliet's avatar Roy Spliet Committed by Ben Skeggs
Browse files

drm/nouveau: correct memtiming table parsing for nv4x



In line with envytools, verified on 4 or 5 BIOS'es.

Signed-off-by: default avatarBen Skeggs <bskeggs@redhat.com>
Signed-off-by: default avatarRoy Spliet <r.spliet@student.tudelft.nl>
parent 758f231e
Loading
Loading
Loading
Loading
+49 −27
Original line number Diff line number Diff line
@@ -552,6 +552,7 @@ nouveau_mem_timing_init(struct drm_device *dev)
	u8 tRC;		/* Byte 9 */
	u8 tUNK_10, tUNK_11, tUNK_12, tUNK_13, tUNK_14;
	u8 tUNK_18, tUNK_19, tUNK_20, tUNK_21;
	u8 magic_number = 0; /* Yeah... sorry*/
	u8 *mem = NULL, *entry;
	int i, recordlen, entries;

@@ -596,6 +597,12 @@ nouveau_mem_timing_init(struct drm_device *dev)
	if (!memtimings->timing)
		return;

	/* Get "some number" from the timing reg for NV_40
	 * Used in calculations later */
	if(dev_priv->card_type == NV_40) {
		magic_number = (nv_rd32(dev,0x100228) & 0x0f000000) >> 24;
	}

	entry = mem + mem[1];
	for (i = 0; i < entries; i++, entry += recordlen) {
		struct nouveau_pm_memtiming *timing = &pm->memtimings.timing[i];
@@ -635,36 +642,51 @@ nouveau_mem_timing_init(struct drm_device *dev)

		/* XXX: I don't trust the -1's and +1's... they must come
		 *      from somewhere! */
		timing->reg_100224 = ((tUNK_0 + tUNK_19 + 1) << 24 |
		timing->reg_100224 = (tUNK_0 + tUNK_19 + 1 + magic_number) << 24 |
				      tUNK_18 << 16 |
				      (tUNK_1 + tUNK_19 + 1) << 8 |
				      (tUNK_2 - 1));
				      (tUNK_1 + tUNK_19 + 1 + magic_number) << 8;
		if(dev_priv->chipset == 0xa8) {
			timing->reg_100224 |= (tUNK_2 - 1);
		} else {
			timing->reg_100224 |= (tUNK_2 + 2 - magic_number);
		}

		timing->reg_100228 = (tUNK_12 << 16 | tUNK_11 << 8 | tUNK_10);
		if(recordlen > 19) {
			timing->reg_100228 += (tUNK_19 - 1) << 24;
		}/* I cannot back-up this else-statement right now
			 else {
			timing->reg_100228 += tUNK_12 << 24;
		}*/
		if(dev_priv->chipset >= 0xa3 && dev_priv->chipset < 0xaa) {
			timing->reg_100228 |= (tUNK_19 - 1) << 24;
		}

		if(dev_priv->card_type == NV_40) {
			/* NV40: don't know what the rest of the regs are..
			 * And don't need to know either */
			timing->reg_100228 |= 0x20200000 | magic_number << 24;
		} else if(dev_priv->card_type >= NV_50) {
			/* XXX: reg_10022c */
			timing->reg_10022c = tUNK_2 - 1;

			timing->reg_100230 = (tUNK_20 << 24 | tUNK_21 << 16 |
						  tUNK_13 << 8  | tUNK_13);

		/* XXX: +6? */
		timing->reg_100234 = (tRAS << 24 | (tUNK_19 + 6) << 8 | tRC);
			timing->reg_100234 = (tRAS << 24 | tRC);
			timing->reg_100234 += max(tUNK_10,tUNK_11) << 16;

			if(dev_priv->chipset < 0xa3) {
				timing->reg_100234 |= (tUNK_2 + 2) << 8;
			} else {
				/* XXX: +6? */
				timing->reg_100234 |= (tUNK_19 + 6) << 8;
			}

			/* XXX; reg_100238, reg_10023c
		 * reg: 0x00??????
		 * reg_10023c:
		 *      0 for pre-NV50 cards
		 *      0x????0202 for NV50+ cards (empirical evidence) */
		if(dev_priv->card_type >= NV_50) {
			 * reg_100238: 0x00??????
			 * reg_10023c: 0x!!??0202 for NV50+ cards (empirical evidence) */
			timing->reg_10023c = 0x202;
			if(dev_priv->chipset < 0xa3) {
				timing->reg_10023c |= 0x4000000 | (tUNK_2 - 1) << 16;
			} else {
				/* currently unknown
				 * 10023c seen as 06xxxxxx, 0bxxxxxx or 0fxxxxxx */
			}
		}

		NV_DEBUG(dev, "Entry %d: 220: %08x %08x %08x %08x\n", i,