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

Commit c378eb74 authored by Ben Skeggs's avatar Ben Skeggs
Browse files

drm/nouveau/bios: parse older ramcfg/timing data like we do newer ones



Done after discussion with Roy.

Signed-off-by: default avatarBen Skeggs <bskeggs@redhat.com>
parent a4073189
Loading
Loading
Loading
Loading
+100 −62
Original line number Diff line number Diff line
@@ -8,6 +8,12 @@ struct nvbios_ramcfg {
	unsigned rammap_hdr;
	unsigned rammap_min;
	unsigned rammap_max;
	union {
		struct {
			unsigned rammap_10_04_02:1;
			unsigned rammap_10_04_08:1;
		};
		struct {
			unsigned rammap_11_08_01:1;
			unsigned rammap_11_08_0c:2;
			unsigned rammap_11_08_10:1;
@@ -23,10 +29,30 @@ struct nvbios_ramcfg {
			unsigned rammap_11_0e:8;
			unsigned rammap_11_0f:8;
			unsigned rammap_11_11_0c:2;
		};
	};

	unsigned ramcfg_ver;
	unsigned ramcfg_hdr;
	unsigned ramcfg_timing;
	union {
		struct {
			unsigned ramcfg_10_02_01:1;
			unsigned ramcfg_10_02_02:1;
			unsigned ramcfg_10_02_04:1;
			unsigned ramcfg_10_02_08:1;
			unsigned ramcfg_10_02_10:1;
			unsigned ramcfg_10_02_20:1;
			unsigned ramcfg_10_02_40:1;
			unsigned ramcfg_10_03_0f:4;
			unsigned ramcfg_10_05:8;
			unsigned ramcfg_10_06:8;
			unsigned ramcfg_10_07:8;
			unsigned ramcfg_10_08:8;
			unsigned ramcfg_10_09_0f:4;
			unsigned ramcfg_10_09_f0:4;
		};
		struct {
			unsigned ramcfg_11_01_01:1;
			unsigned ramcfg_11_01_02:1;
			unsigned ramcfg_11_01_04:1;
@@ -60,10 +86,20 @@ struct nvbios_ramcfg {
			unsigned ramcfg_11_08_10:1;
			unsigned ramcfg_11_08_20:1;
			unsigned ramcfg_11_09:8;
		};
	};

	unsigned timing_ver;
	unsigned timing_hdr;
	unsigned timing[11];
	union {
		struct {
			unsigned timing_10_WR:8;
			unsigned timing_10_CL:8;
			unsigned timing_10_ODT:3;
			unsigned timing_10_CWL:8;
		};
		struct {
			unsigned timing_20_2e_03:2;
			unsigned timing_20_2e_30:2;
			unsigned timing_20_2e_c0:2;
@@ -79,6 +115,8 @@ struct nvbios_ramcfg {
			unsigned timing_20_31_7000:3;
			unsigned timing_20_31_8000:1;
		};
	};
};

u8 nvbios_ramcfg_count(struct nouveau_bios *);
u8 nvbios_ramcfg_index(struct nouveau_subdev *);
+0 −5
Original line number Diff line number Diff line
@@ -146,11 +146,6 @@ struct nouveau_ram {
	int  (*calc)(struct nouveau_fb *, u32 freq);
	int  (*prog)(struct nouveau_fb *);
	void (*tidy)(struct nouveau_fb *);
	struct {
		u8  version;
		u32 data;
		u8  size;
	} rammap, ramcfg, timing;
	u32 freq;
	u32 mr[16];
	u32 mr1_nuts;
+19 −0
Original line number Diff line number Diff line
@@ -87,6 +87,8 @@ nvbios_rammapEp(struct nouveau_bios *bios, int idx,
	case 0x10:
		p->rammap_min      =  nv_ro16(bios, data + 0x00);
		p->rammap_max      =  nv_ro16(bios, data + 0x02);
		p->rammap_10_04_02 = (nv_ro08(bios, data + 0x04) & 0x02) >> 1;
		p->rammap_10_04_08 = (nv_ro08(bios, data + 0x04) & 0x08) >> 3;
		break;
	case 0x11:
		p->rammap_min      =  nv_ro16(bios, data + 0x00);
@@ -152,6 +154,23 @@ nvbios_rammapSp(struct nouveau_bios *bios, u32 data,
	p->ramcfg_ver = *ver;
	p->ramcfg_hdr = *hdr;
	switch (!!data * *ver) {
	case 0x10:
		p->ramcfg_timing   =  nv_ro08(bios, data + 0x01);
		p->ramcfg_10_02_01 = (nv_ro08(bios, data + 0x02) & 0x01) >> 0;
		p->ramcfg_10_02_02 = (nv_ro08(bios, data + 0x02) & 0x02) >> 1;
		p->ramcfg_10_02_04 = (nv_ro08(bios, data + 0x02) & 0x04) >> 2;
		p->ramcfg_10_02_08 = (nv_ro08(bios, data + 0x02) & 0x08) >> 3;
		p->ramcfg_10_02_10 = (nv_ro08(bios, data + 0x02) & 0x10) >> 4;
		p->ramcfg_10_02_20 = (nv_ro08(bios, data + 0x02) & 0x20) >> 5;
		p->ramcfg_10_02_40 = (nv_ro08(bios, data + 0x02) & 0x40) >> 6;
		p->ramcfg_10_03_0f = (nv_ro08(bios, data + 0x03) & 0x0f) >> 0;
		p->ramcfg_10_05    = (nv_ro08(bios, data + 0x05) & 0xff) >> 0;
		p->ramcfg_10_06    = (nv_ro08(bios, data + 0x06) & 0xff) >> 0;
		p->ramcfg_10_07    = (nv_ro08(bios, data + 0x07) & 0xff) >> 0;
		p->ramcfg_10_08    = (nv_ro08(bios, data + 0x08) & 0xff) >> 0;
		p->ramcfg_10_09_0f = (nv_ro08(bios, data + 0x09) & 0x0f) >> 0;
		p->ramcfg_10_09_f0 = (nv_ro08(bios, data + 0x09) & 0xf0) >> 4;
		break;
	case 0x11:
		p->ramcfg_timing   =  nv_ro08(bios, data + 0x00);
		p->ramcfg_11_01_01 = (nv_ro08(bios, data + 0x01) & 0x01) >> 0;
+6 −0
Original line number Diff line number Diff line
@@ -92,6 +92,12 @@ nvbios_timingEp(struct nouveau_bios *bios, int idx,
	p->timing_ver = *ver;
	p->timing_hdr = *hdr;
	switch (!!data * *ver) {
	case 0x10:
		p->timing_10_WR = nv_ro08(bios, data + 0x00);
		p->timing_10_CL = nv_ro08(bios, data + 0x02);
		p->timing_10_ODT = nv_ro08(bios, data + 0x0e) & 0x07;
		p->timing_10_CWL = nv_ro08(bios, data + 0x13);
		break;
	case 0x20:
		p->timing[0] = nv_ro32(bios, data + 0x00);
		p->timing[1] = nv_ro32(bios, data + 0x04);
+45 −42
Original line number Diff line number Diff line
@@ -79,21 +79,27 @@ nva3_ram_calc(struct nouveau_fb *pfb, u32 freq)
	struct nva3_ram *ram = (void *)pfb->ram;
	struct nva3_ramfuc *fuc = &ram->fuc;
	struct nva3_clock_info mclk;
	struct nvbios_ramcfg cfg;
	u8  ver, cnt, len, strap;
	struct nouveau_ram_data *next;
	u8  ver, hdr, cnt, len, strap;
	u32 data;
	struct {
		u32 data;
		u8  size;
	} rammap, ramcfg, timing;
	u32 r004018, r100760, ctrl;
	u32 unk714, unk718, unk71c;
	int ret;
	int ret, i;

	next = &ram->base.target;
	next->freq = freq;
	ram->base.next = next;

	/* lookup memory config data relevant to the target frequency */
	rammap.data = nvbios_rammapEm(bios, freq / 1000, &ver, &rammap.size,
				     &cnt, &ramcfg.size, &cfg);
	if (!rammap.data || ver != 0x10 || rammap.size < 0x0e) {
	i = 0;
	while ((data = nvbios_rammapEp(bios, i++, &ver, &hdr, &cnt, &len,
				      &next->bios))) {
		if (freq / 1000 >= next->bios.rammap_min &&
		    freq / 1000 <= next->bios.rammap_max)
			break;
	}

	if (!data || ver != 0x10 || hdr < 0x0e) {
		nv_error(pfb, "invalid/missing rammap entry\n");
		return -EINVAL;
	}
@@ -105,23 +111,22 @@ nva3_ram_calc(struct nouveau_fb *pfb, u32 freq)
		return -EINVAL;
	}

	ramcfg.data = rammap.data + rammap.size + (strap * ramcfg.size);
	if (!ramcfg.data || ver != 0x10 || ramcfg.size < 0x0e) {
	data = nvbios_rammapSp(bios, data, ver, hdr, cnt, len, strap,
			       &ver, &hdr, &next->bios);
	if (!data || ver != 0x10 || hdr < 0x0e) {
		nv_error(pfb, "invalid/missing ramcfg entry\n");
		return -EINVAL;
	}

	/* lookup memory timings, if bios says they're present */
	strap = nv_ro08(bios, ramcfg.data + 0x01);
	if (strap != 0xff) {
		timing.data = nvbios_timingEe(bios, strap, &ver, &timing.size,
					     &cnt, &len);
		if (!timing.data || ver != 0x10 || timing.size < 0x19) {
	if (next->bios.ramcfg_timing != 0xff) {
		data = nvbios_timingEp(bios, next->bios.ramcfg_timing,
				       &ver, &hdr, &cnt, &len,
				       &next->bios);
		if (!data || ver != 0x10 || hdr < 0x19) {
			nv_error(pfb, "invalid/missing timing entry\n");
			return -EINVAL;
		}
	} else {
		timing.data = 0;
	}

	ret = nva3_pll_info(nouveau_clock(pfb), 0x12, 0x4000, freq, &mclk);
@@ -164,17 +169,17 @@ nva3_ram_calc(struct nouveau_fb *pfb, u32 freq)
		ram_mask(fuc, 0x004168, 0x003f3141, ctrl);
	}

	if ( (nv_ro08(bios, ramcfg.data + 0x02) & 0x10)) {
	if (next->bios.ramcfg_10_02_10) {
		ram_mask(fuc, 0x111104, 0x00000600, 0x00000000);
	} else {
		ram_mask(fuc, 0x111100, 0x40000000, 0x40000000);
		ram_mask(fuc, 0x111104, 0x00000180, 0x00000000);
	}

	if (!(nv_ro08(bios, rammap.data + 0x04) & 0x02))
	if (!next->bios.rammap_10_04_02)
		ram_mask(fuc, 0x100200, 0x00000800, 0x00000000);
	ram_wr32(fuc, 0x611200, 0x00003300);
	if (!(nv_ro08(bios, ramcfg.data + 0x02) & 0x10))
	if (!next->bios.ramcfg_10_02_10)
		ram_wr32(fuc, 0x111100, 0x4c020000); /*XXX*/

	ram_wr32(fuc, 0x1002d4, 0x00000001);
@@ -203,17 +208,16 @@ nva3_ram_calc(struct nouveau_fb *pfb, u32 freq)
		ram_wr32(fuc, 0x004018, 0x0000d000 | r004018);
	}

	if ( (nv_ro08(bios, rammap.data + 0x04) & 0x08)) {
		u32 unk5a0 = (nv_ro16(bios, ramcfg.data + 0x05) << 8) |
			      nv_ro08(bios, ramcfg.data + 0x05);
		u32 unk5a4 = (nv_ro16(bios, ramcfg.data + 0x07));
		u32 unk804 = (nv_ro08(bios, ramcfg.data + 0x09) & 0xf0) << 16 |
			     (nv_ro08(bios, ramcfg.data + 0x03) & 0x0f) << 16 |
			     (nv_ro08(bios, ramcfg.data + 0x09) & 0x0f) |
			     0x80000000;
		ram_wr32(fuc, 0x1005a0, unk5a0);
		ram_wr32(fuc, 0x1005a4, unk5a4);
		ram_wr32(fuc, 0x10f804, unk804);
	if (next->bios.rammap_10_04_08) {
		ram_wr32(fuc, 0x1005a0, next->bios.ramcfg_10_06 << 16 |
					next->bios.ramcfg_10_05 << 8 |
					next->bios.ramcfg_10_05);
		ram_wr32(fuc, 0x1005a4, next->bios.ramcfg_10_08 << 8 |
					next->bios.ramcfg_10_07);
		ram_wr32(fuc, 0x10f804, next->bios.ramcfg_10_09_f0 << 20 |
					next->bios.ramcfg_10_03_0f << 16 |
					next->bios.ramcfg_10_09_0f |
					0x80000000);
		ram_mask(fuc, 0x10053c, 0x00001000, 0x00000000);
	} else {
		ram_mask(fuc, 0x10053c, 0x00001000, 0x00001000);
@@ -251,27 +255,26 @@ nva3_ram_calc(struct nouveau_fb *pfb, u32 freq)
	ram_mask(fuc, 0x100220[0], 0x00000000, 0x00000000);
	ram_mask(fuc, 0x100220[8], 0x00000000, 0x00000000);

	data = (nv_ro08(bios, ramcfg.data + 0x02) & 0x08) ? 0x00000000 : 0x00001000;
	ram_mask(fuc, 0x100200, 0x00001000, data);
	ram_mask(fuc, 0x100200, 0x00001000, !next->bios.ramcfg_10_02_08 << 12);

	unk714 = ram_rd32(fuc, 0x100714) & ~0xf0000010;
	unk718 = ram_rd32(fuc, 0x100718) & ~0x00000100;
	unk71c = ram_rd32(fuc, 0x10071c) & ~0x00000100;
	if ( (nv_ro08(bios, ramcfg.data + 0x02) & 0x20))
	if (next->bios.ramcfg_10_02_20)
		unk714 |= 0xf0000000;
	if (!(nv_ro08(bios, ramcfg.data + 0x02) & 0x04))
	if (!next->bios.ramcfg_10_02_04)
		unk714 |= 0x00000010;
	ram_wr32(fuc, 0x100714, unk714);

	if (nv_ro08(bios, ramcfg.data + 0x02) & 0x01)
	if (next->bios.ramcfg_10_02_01)
		unk71c |= 0x00000100;
	ram_wr32(fuc, 0x10071c, unk71c);

	if (nv_ro08(bios, ramcfg.data + 0x02) & 0x02)
	if (next->bios.ramcfg_10_02_02)
		unk718 |= 0x00000100;
	ram_wr32(fuc, 0x100718, unk718);

	if (nv_ro08(bios, ramcfg.data + 0x02) & 0x10)
	if (next->bios.ramcfg_10_02_10)
		ram_wr32(fuc, 0x111100, 0x48000000); /*XXX*/

	ram_mask(fuc, mr[0], 0x100, 0x100);
@@ -283,9 +286,9 @@ nva3_ram_calc(struct nouveau_fb *pfb, u32 freq)
	ram_nsec(fuc, 12000);

	ram_wr32(fuc, 0x611200, 0x00003330);
	if ( (nv_ro08(bios, rammap.data + 0x04) & 0x02))
	if (next->bios.rammap_10_04_02)
		ram_mask(fuc, 0x100200, 0x00000800, 0x00000800);
	if ( (nv_ro08(bios, ramcfg.data + 0x02) & 0x10)) {
	if (next->bios.ramcfg_10_02_10) {
		ram_mask(fuc, 0x111104, 0x00000180, 0x00000180);
		ram_mask(fuc, 0x111100, 0x40000000, 0x00000000);
	} else {
Loading