Commit c378eb74 authored by Ben Skeggs's avatar Ben Skeggs

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
...@@ -8,6 +8,12 @@ struct nvbios_ramcfg { ...@@ -8,6 +8,12 @@ struct nvbios_ramcfg {
unsigned rammap_hdr; unsigned rammap_hdr;
unsigned rammap_min; unsigned rammap_min;
unsigned rammap_max; 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_01:1;
unsigned rammap_11_08_0c:2; unsigned rammap_11_08_0c:2;
unsigned rammap_11_08_10:1; unsigned rammap_11_08_10:1;
...@@ -23,10 +29,30 @@ struct nvbios_ramcfg { ...@@ -23,10 +29,30 @@ struct nvbios_ramcfg {
unsigned rammap_11_0e:8; unsigned rammap_11_0e:8;
unsigned rammap_11_0f:8; unsigned rammap_11_0f:8;
unsigned rammap_11_11_0c:2; unsigned rammap_11_11_0c:2;
};
};
unsigned ramcfg_ver; unsigned ramcfg_ver;
unsigned ramcfg_hdr; unsigned ramcfg_hdr;
unsigned ramcfg_timing; 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_01:1;
unsigned ramcfg_11_01_02:1; unsigned ramcfg_11_01_02:1;
unsigned ramcfg_11_01_04:1; unsigned ramcfg_11_01_04:1;
...@@ -60,10 +86,20 @@ struct nvbios_ramcfg { ...@@ -60,10 +86,20 @@ struct nvbios_ramcfg {
unsigned ramcfg_11_08_10:1; unsigned ramcfg_11_08_10:1;
unsigned ramcfg_11_08_20:1; unsigned ramcfg_11_08_20:1;
unsigned ramcfg_11_09:8; unsigned ramcfg_11_09:8;
};
};
unsigned timing_ver; unsigned timing_ver;
unsigned timing_hdr; unsigned timing_hdr;
unsigned timing[11]; 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_03:2;
unsigned timing_20_2e_30:2; unsigned timing_20_2e_30:2;
unsigned timing_20_2e_c0:2; unsigned timing_20_2e_c0:2;
...@@ -78,6 +114,8 @@ struct nvbios_ramcfg { ...@@ -78,6 +114,8 @@ struct nvbios_ramcfg {
unsigned timing_20_31_0800:1; unsigned timing_20_31_0800:1;
unsigned timing_20_31_7000:3; unsigned timing_20_31_7000:3;
unsigned timing_20_31_8000:1; unsigned timing_20_31_8000:1;
};
};
}; };
u8 nvbios_ramcfg_count(struct nouveau_bios *); u8 nvbios_ramcfg_count(struct nouveau_bios *);
......
...@@ -146,11 +146,6 @@ struct nouveau_ram { ...@@ -146,11 +146,6 @@ struct nouveau_ram {
int (*calc)(struct nouveau_fb *, u32 freq); int (*calc)(struct nouveau_fb *, u32 freq);
int (*prog)(struct nouveau_fb *); int (*prog)(struct nouveau_fb *);
void (*tidy)(struct nouveau_fb *); void (*tidy)(struct nouveau_fb *);
struct {
u8 version;
u32 data;
u8 size;
} rammap, ramcfg, timing;
u32 freq; u32 freq;
u32 mr[16]; u32 mr[16];
u32 mr1_nuts; u32 mr1_nuts;
......
...@@ -87,6 +87,8 @@ nvbios_rammapEp(struct nouveau_bios *bios, int idx, ...@@ -87,6 +87,8 @@ nvbios_rammapEp(struct nouveau_bios *bios, int idx,
case 0x10: case 0x10:
p->rammap_min = nv_ro16(bios, data + 0x00); p->rammap_min = nv_ro16(bios, data + 0x00);
p->rammap_max = nv_ro16(bios, data + 0x02); 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; break;
case 0x11: case 0x11:
p->rammap_min = nv_ro16(bios, data + 0x00); p->rammap_min = nv_ro16(bios, data + 0x00);
...@@ -152,6 +154,23 @@ nvbios_rammapSp(struct nouveau_bios *bios, u32 data, ...@@ -152,6 +154,23 @@ nvbios_rammapSp(struct nouveau_bios *bios, u32 data,
p->ramcfg_ver = *ver; p->ramcfg_ver = *ver;
p->ramcfg_hdr = *hdr; p->ramcfg_hdr = *hdr;
switch (!!data * *ver) { 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: case 0x11:
p->ramcfg_timing = nv_ro08(bios, data + 0x00); p->ramcfg_timing = nv_ro08(bios, data + 0x00);
p->ramcfg_11_01_01 = (nv_ro08(bios, data + 0x01) & 0x01) >> 0; p->ramcfg_11_01_01 = (nv_ro08(bios, data + 0x01) & 0x01) >> 0;
......
...@@ -92,6 +92,12 @@ nvbios_timingEp(struct nouveau_bios *bios, int idx, ...@@ -92,6 +92,12 @@ nvbios_timingEp(struct nouveau_bios *bios, int idx,
p->timing_ver = *ver; p->timing_ver = *ver;
p->timing_hdr = *hdr; p->timing_hdr = *hdr;
switch (!!data * *ver) { 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: case 0x20:
p->timing[0] = nv_ro32(bios, data + 0x00); p->timing[0] = nv_ro32(bios, data + 0x00);
p->timing[1] = nv_ro32(bios, data + 0x04); p->timing[1] = nv_ro32(bios, data + 0x04);
......
...@@ -79,21 +79,27 @@ nva3_ram_calc(struct nouveau_fb *pfb, u32 freq) ...@@ -79,21 +79,27 @@ nva3_ram_calc(struct nouveau_fb *pfb, u32 freq)
struct nva3_ram *ram = (void *)pfb->ram; struct nva3_ram *ram = (void *)pfb->ram;
struct nva3_ramfuc *fuc = &ram->fuc; struct nva3_ramfuc *fuc = &ram->fuc;
struct nva3_clock_info mclk; struct nva3_clock_info mclk;
struct nvbios_ramcfg cfg; struct nouveau_ram_data *next;
u8 ver, cnt, len, strap; u8 ver, hdr, cnt, len, strap;
u32 data; u32 data;
struct {
u32 data;
u8 size;
} rammap, ramcfg, timing;
u32 r004018, r100760, ctrl; u32 r004018, r100760, ctrl;
u32 unk714, unk718, unk71c; 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 */ /* lookup memory config data relevant to the target frequency */
rammap.data = nvbios_rammapEm(bios, freq / 1000, &ver, &rammap.size, i = 0;
&cnt, &ramcfg.size, &cfg); while ((data = nvbios_rammapEp(bios, i++, &ver, &hdr, &cnt, &len,
if (!rammap.data || ver != 0x10 || rammap.size < 0x0e) { &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"); nv_error(pfb, "invalid/missing rammap entry\n");
return -EINVAL; return -EINVAL;
} }
...@@ -105,23 +111,22 @@ nva3_ram_calc(struct nouveau_fb *pfb, u32 freq) ...@@ -105,23 +111,22 @@ nva3_ram_calc(struct nouveau_fb *pfb, u32 freq)
return -EINVAL; return -EINVAL;
} }
ramcfg.data = rammap.data + rammap.size + (strap * ramcfg.size); data = nvbios_rammapSp(bios, data, ver, hdr, cnt, len, strap,
if (!ramcfg.data || ver != 0x10 || ramcfg.size < 0x0e) { &ver, &hdr, &next->bios);
if (!data || ver != 0x10 || hdr < 0x0e) {
nv_error(pfb, "invalid/missing ramcfg entry\n"); nv_error(pfb, "invalid/missing ramcfg entry\n");
return -EINVAL; return -EINVAL;
} }
/* lookup memory timings, if bios says they're present */ /* lookup memory timings, if bios says they're present */
strap = nv_ro08(bios, ramcfg.data + 0x01); if (next->bios.ramcfg_timing != 0xff) {
if (strap != 0xff) { data = nvbios_timingEp(bios, next->bios.ramcfg_timing,
timing.data = nvbios_timingEe(bios, strap, &ver, &timing.size, &ver, &hdr, &cnt, &len,
&cnt, &len); &next->bios);
if (!timing.data || ver != 0x10 || timing.size < 0x19) { if (!data || ver != 0x10 || hdr < 0x19) {
nv_error(pfb, "invalid/missing timing entry\n"); nv_error(pfb, "invalid/missing timing entry\n");
return -EINVAL; return -EINVAL;
} }
} else {
timing.data = 0;
} }
ret = nva3_pll_info(nouveau_clock(pfb), 0x12, 0x4000, freq, &mclk); ret = nva3_pll_info(nouveau_clock(pfb), 0x12, 0x4000, freq, &mclk);
...@@ -164,17 +169,17 @@ nva3_ram_calc(struct nouveau_fb *pfb, u32 freq) ...@@ -164,17 +169,17 @@ nva3_ram_calc(struct nouveau_fb *pfb, u32 freq)
ram_mask(fuc, 0x004168, 0x003f3141, ctrl); 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); ram_mask(fuc, 0x111104, 0x00000600, 0x00000000);
} else { } else {
ram_mask(fuc, 0x111100, 0x40000000, 0x40000000); ram_mask(fuc, 0x111100, 0x40000000, 0x40000000);
ram_mask(fuc, 0x111104, 0x00000180, 0x00000000); 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_mask(fuc, 0x100200, 0x00000800, 0x00000000);
ram_wr32(fuc, 0x611200, 0x00003300); 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, 0x111100, 0x4c020000); /*XXX*/
ram_wr32(fuc, 0x1002d4, 0x00000001); ram_wr32(fuc, 0x1002d4, 0x00000001);
...@@ -203,17 +208,16 @@ nva3_ram_calc(struct nouveau_fb *pfb, u32 freq) ...@@ -203,17 +208,16 @@ nva3_ram_calc(struct nouveau_fb *pfb, u32 freq)
ram_wr32(fuc, 0x004018, 0x0000d000 | r004018); ram_wr32(fuc, 0x004018, 0x0000d000 | r004018);
} }
if ( (nv_ro08(bios, rammap.data + 0x04) & 0x08)) { if (next->bios.rammap_10_04_08) {
u32 unk5a0 = (nv_ro16(bios, ramcfg.data + 0x05) << 8) | ram_wr32(fuc, 0x1005a0, next->bios.ramcfg_10_06 << 16 |
nv_ro08(bios, ramcfg.data + 0x05); next->bios.ramcfg_10_05 << 8 |
u32 unk5a4 = (nv_ro16(bios, ramcfg.data + 0x07)); next->bios.ramcfg_10_05);
u32 unk804 = (nv_ro08(bios, ramcfg.data + 0x09) & 0xf0) << 16 | ram_wr32(fuc, 0x1005a4, next->bios.ramcfg_10_08 << 8 |
(nv_ro08(bios, ramcfg.data + 0x03) & 0x0f) << 16 | next->bios.ramcfg_10_07);
(nv_ro08(bios, ramcfg.data + 0x09) & 0x0f) | ram_wr32(fuc, 0x10f804, next->bios.ramcfg_10_09_f0 << 20 |
0x80000000; next->bios.ramcfg_10_03_0f << 16 |
ram_wr32(fuc, 0x1005a0, unk5a0); next->bios.ramcfg_10_09_0f |
ram_wr32(fuc, 0x1005a4, unk5a4); 0x80000000);
ram_wr32(fuc, 0x10f804, unk804);
ram_mask(fuc, 0x10053c, 0x00001000, 0x00000000); ram_mask(fuc, 0x10053c, 0x00001000, 0x00000000);
} else { } else {
ram_mask(fuc, 0x10053c, 0x00001000, 0x00001000); ram_mask(fuc, 0x10053c, 0x00001000, 0x00001000);
...@@ -251,27 +255,26 @@ nva3_ram_calc(struct nouveau_fb *pfb, u32 freq) ...@@ -251,27 +255,26 @@ nva3_ram_calc(struct nouveau_fb *pfb, u32 freq)
ram_mask(fuc, 0x100220[0], 0x00000000, 0x00000000); ram_mask(fuc, 0x100220[0], 0x00000000, 0x00000000);
ram_mask(fuc, 0x100220[8], 0x00000000, 0x00000000); ram_mask(fuc, 0x100220[8], 0x00000000, 0x00000000);
data = (nv_ro08(bios, ramcfg.data + 0x02) & 0x08) ? 0x00000000 : 0x00001000; ram_mask(fuc, 0x100200, 0x00001000, !next->bios.ramcfg_10_02_08 << 12);
ram_mask(fuc, 0x100200, 0x00001000, data);
unk714 = ram_rd32(fuc, 0x100714) & ~0xf0000010; unk714 = ram_rd32(fuc, 0x100714) & ~0xf0000010;
unk718 = ram_rd32(fuc, 0x100718) & ~0x00000100; unk718 = ram_rd32(fuc, 0x100718) & ~0x00000100;
unk71c = ram_rd32(fuc, 0x10071c) & ~0x00000100; unk71c = ram_rd32(fuc, 0x10071c) & ~0x00000100;
if ( (nv_ro08(bios, ramcfg.data + 0x02) & 0x20)) if (next->bios.ramcfg_10_02_20)
unk714 |= 0xf0000000; unk714 |= 0xf0000000;
if (!(nv_ro08(bios, ramcfg.data + 0x02) & 0x04)) if (!next->bios.ramcfg_10_02_04)
unk714 |= 0x00000010; unk714 |= 0x00000010;
ram_wr32(fuc, 0x100714, unk714); ram_wr32(fuc, 0x100714, unk714);
if (nv_ro08(bios, ramcfg.data + 0x02) & 0x01) if (next->bios.ramcfg_10_02_01)
unk71c |= 0x00000100; unk71c |= 0x00000100;
ram_wr32(fuc, 0x10071c, unk71c); ram_wr32(fuc, 0x10071c, unk71c);
if (nv_ro08(bios, ramcfg.data + 0x02) & 0x02) if (next->bios.ramcfg_10_02_02)
unk718 |= 0x00000100; unk718 |= 0x00000100;
ram_wr32(fuc, 0x100718, unk718); 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_wr32(fuc, 0x111100, 0x48000000); /*XXX*/
ram_mask(fuc, mr[0], 0x100, 0x100); ram_mask(fuc, mr[0], 0x100, 0x100);
...@@ -283,9 +286,9 @@ nva3_ram_calc(struct nouveau_fb *pfb, u32 freq) ...@@ -283,9 +286,9 @@ nva3_ram_calc(struct nouveau_fb *pfb, u32 freq)
ram_nsec(fuc, 12000); ram_nsec(fuc, 12000);
ram_wr32(fuc, 0x611200, 0x00003330); 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); 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, 0x111104, 0x00000180, 0x00000180);
ram_mask(fuc, 0x111100, 0x40000000, 0x00000000); ram_mask(fuc, 0x111100, 0x40000000, 0x00000000);
} else { } else {
......
...@@ -23,7 +23,6 @@ ...@@ -23,7 +23,6 @@
* Ben Skeggs * Ben Skeggs
*/ */
#include <subdev/bios.h>
#include "priv.h" #include "priv.h"
struct ramxlat { struct ramxlat {
...@@ -61,19 +60,18 @@ ramddr2_wr[] = { ...@@ -61,19 +60,18 @@ ramddr2_wr[] = {
int int
nouveau_sddr2_calc(struct nouveau_ram *ram) nouveau_sddr2_calc(struct nouveau_ram *ram)
{ {
struct nouveau_bios *bios = nouveau_bios(ram);
int CL, WR, DLL = 0, ODT = 0; int CL, WR, DLL = 0, ODT = 0;
switch (!!ram->timing.data * ram->timing.version) { switch (ram->next->bios.timing_ver) {
case 0x10: case 0x10:
CL = nv_ro08(bios, ram->timing.data + 0x02); CL = ram->next->bios.timing_10_CL;
WR = nv_ro08(bios, ram->timing.data + 0x00); WR = ram->next->bios.timing_10_WR;
DLL = !(nv_ro08(bios, ram->ramcfg.data + 0x02) & 0x40); DLL = !ram->next->bios.ramcfg_10_02_40;
ODT = nv_ro08(bios, ram->timing.data + 0x0e) & 0x03; ODT = ram->next->bios.timing_10_ODT & 3;
break; break;
case 0x20: case 0x20:
CL = nv_ro08(bios, ram->timing.data + 0x04) & 0x1f; CL = (ram->next->bios.timing[1] & 0x0000001f);
WR = nv_ro08(bios, ram->timing.data + 0x0a) & 0x7f; WR = (ram->next->bios.timing[2] & 0x007f0000) >> 16;
break; break;
default: default:
return -ENOSYS; return -ENOSYS;
......
...@@ -23,7 +23,6 @@ ...@@ -23,7 +23,6 @@
* Roy Spliet <rspliet@eclipso.eu> * Roy Spliet <rspliet@eclipso.eu>
*/ */
#include <subdev/bios.h>
#include "priv.h" #include "priv.h"
struct ramxlat { struct ramxlat {
...@@ -70,25 +69,19 @@ ramddr3_cwl[] = { ...@@ -70,25 +69,19 @@ ramddr3_cwl[] = {
int int
nouveau_sddr3_calc(struct nouveau_ram *ram) nouveau_sddr3_calc(struct nouveau_ram *ram)
{ {
struct nouveau_bios *bios = nouveau_bios(ram);
int CWL, CL, WR, DLL = 0, ODT = 0; int CWL, CL, WR, DLL = 0, ODT = 0;
u8 ver;
ver = !!ram->timing.data * ram->timing.version; switch (ram->next->bios.timing_ver) {
if (ram->next)
ver = ram->next->bios.timing_ver;
switch (ver) {
case 0x10: case 0x10:
if (ram->timing.size < 0x17) { if (ram->next->bios.timing_hdr < 0x17) {
/* XXX: NV50: Get CWL from the timing register */ /* XXX: NV50: Get CWL from the timing register */
return -ENOSYS; return -ENOSYS;
} }
CWL = nv_ro08(bios, ram->timing.data + 0x13); CWL = ram->next->bios.timing_10_CWL;
CL = nv_ro08(bios, ram->timing.data + 0x02); CL = ram->next->bios.timing_10_CL;
WR = nv_ro08(bios, ram->timing.data + 0x00); WR = ram->next->bios.timing_10_WR;
DLL = !(nv_ro08(bios, ram->ramcfg.data + 0x02) & 0x40); DLL = !ram->next->bios.ramcfg_10_02_40;
ODT = nv_ro08(bios, ram->timing.data + 0x0e) & 0x07; ODT = ram->next->bios.timing_10_ODT;
break; break;
case 0x20: case 0x20:
CWL = (ram->next->bios.timing[1] & 0x00000f80) >> 7; CWL = (ram->next->bios.timing[1] & 0x00000f80) >> 7;
......
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