Commit b655f2bb authored by Ben Skeggs's avatar Ben Skeggs

drm/nve0/fb/gddr5: parse bios data into struct rather than using directly

Still essentially a struct of magic values with magic names and unknown
purposes.  But, we will shortly need to be able to mix and match bits of
the previous and next configurations to do a transition reclock, as such,
we can no longer directly use the vbios data with any ease.

This is probably nicer anyway in the long run, for a few reasons.
Signed-off-by: default avatarBen Skeggs <bskeggs@redhat.com>
parent ea8b4a38
...@@ -3,6 +3,62 @@ ...@@ -3,6 +3,62 @@
struct nouveau_bios; struct nouveau_bios;
struct nvbios_ramcfg {
unsigned rammap_11_08_01:1;
unsigned rammap_11_08_0c:2;
unsigned rammap_11_08_10:1;
unsigned rammap_11_11_0c:2;
unsigned ramcfg_11_01_01:1;
unsigned ramcfg_11_01_02:1;
unsigned ramcfg_11_01_04:1;
unsigned ramcfg_11_01_08:1;
unsigned ramcfg_11_01_10:1;
unsigned ramcfg_11_01_20:1;
unsigned ramcfg_11_01_40:1;
unsigned ramcfg_11_01_80:1;
unsigned ramcfg_11_02_03:2;
unsigned ramcfg_11_02_04:1;
unsigned ramcfg_11_02_08:1;
unsigned ramcfg_11_02_10:1;
unsigned ramcfg_11_02_40:1;
unsigned ramcfg_11_02_80:1;
unsigned ramcfg_11_03_0f:4;
unsigned ramcfg_11_03_30:2;
unsigned ramcfg_11_03_c0:2;
unsigned ramcfg_11_03_f0:4;
unsigned ramcfg_11_04:8;
unsigned ramcfg_11_06:8;
unsigned ramcfg_11_07_02:1;
unsigned ramcfg_11_07_04:1;
unsigned ramcfg_11_07_08:1;
unsigned ramcfg_11_07_10:1;
unsigned ramcfg_11_07_40:1;
unsigned ramcfg_11_07_80:1;
unsigned ramcfg_11_08_01:1;
unsigned ramcfg_11_08_02:1;
unsigned ramcfg_11_08_04:1;
unsigned ramcfg_11_08_08:1;
unsigned ramcfg_11_08_10:1;
unsigned ramcfg_11_09:8;
unsigned timing[11];
unsigned timing_20_2e_03:2;
unsigned timing_20_2e_30:2;
unsigned timing_20_2e_c0:2;
unsigned timing_20_2f_03:2;
unsigned timing_20_2c_003f:6;
unsigned timing_20_2c_1fc0:7;
unsigned timing_20_30_f8:5;
unsigned timing_20_30_07:3;
unsigned timing_20_31_0007:3;
unsigned timing_20_31_0078:4;
unsigned timing_20_31_0780:4;
unsigned timing_20_31_0800:1;
unsigned timing_20_31_7000:3;
unsigned timing_20_31_8000:1;
};
u8 nvbios_ramcfg_count(struct nouveau_bios *); u8 nvbios_ramcfg_count(struct nouveau_bios *);
u8 nvbios_ramcfg_index(struct nouveau_bios *); u8 nvbios_ramcfg_index(struct nouveau_bios *);
......
#ifndef __NVBIOS_RAMMAP_H__ #ifndef __NVBIOS_RAMMAP_H__
#define __NVBIOS_RAMMAP_H__ #define __NVBIOS_RAMMAP_H__
u16 nvbios_rammap_table(struct nouveau_bios *, u8 *ver, u8 *hdr, struct nvbios_ramcfg;
u8 *cnt, u8 *len, u8 *snr, u8 *ssz);
u16 nvbios_rammap_entry(struct nouveau_bios *, int idx, u32 nvbios_rammapTe(struct nouveau_bios *, u8 *ver, u8 *hdr,
u8 *ver, u8 *hdr, u8 *cnt, u8 *len); u8 *cnt, u8 *len, u8 *snr, u8 *ssz);
u16 nvbios_rammap_match(struct nouveau_bios *, u16 khz,
u8 *ver, u8 *hdr, u8 *cnt, u8 *len); u32 nvbios_rammapEe(struct nouveau_bios *, int idx,
u8 *ver, u8 *hdr, u8 *cnt, u8 *len);
u32 nvbios_rammapEm(struct nouveau_bios *, u16 mhz,
u8 *ver, u8 *hdr, u8 *cnt, u8 *len);
u32 nvbios_rammapEp(struct nouveau_bios *, u16 mhz,
u8 *ver, u8 *hdr, u8 *cnt, u8 *len,
struct nvbios_ramcfg *);
u32 nvbios_rammapSe(struct nouveau_bios *, u32 data,
u8 ever, u8 ehdr, u8 ecnt, u8 elen, int idx,
u8 *ver, u8 *hdr);
u32 nvbios_rammapSp(struct nouveau_bios *, u32 data,
u8 ever, u8 ehdr, u8 ecnt, u8 elen, int idx,
u8 *ver, u8 *hdr,
struct nvbios_ramcfg *);
#endif #endif
#ifndef __NVBIOS_TIMING_H__ #ifndef __NVBIOS_TIMING_H__
#define __NVBIOS_TIMING_H__ #define __NVBIOS_TIMING_H__
struct nvbios_ramcfg;
u16 nvbios_timingTe(struct nouveau_bios *, u16 nvbios_timingTe(struct nouveau_bios *,
u8 *ver, u8 *hdr, u8 *cnt, u8 *len, u8 *snr, u8 *ssz); u8 *ver, u8 *hdr, u8 *cnt, u8 *len, u8 *snr, u8 *ssz);
u16 nvbios_timingEe(struct nouveau_bios *, int idx, u16 nvbios_timingEe(struct nouveau_bios *, int idx,
u8 *ver, u8 *hdr, u8 *cnt, u8 *len); u8 *ver, u8 *hdr, u8 *cnt, u8 *len);
u16 nvbios_timingEp(struct nouveau_bios *, int idx,
u8 *ver, u8 *hdr, u8 *cnt, u8 *len,
struct nvbios_ramcfg *);
#endif #endif
...@@ -106,6 +106,12 @@ extern struct nouveau_oclass *nvaf_fb_oclass; ...@@ -106,6 +106,12 @@ extern struct nouveau_oclass *nvaf_fb_oclass;
extern struct nouveau_oclass *nvc0_fb_oclass; extern struct nouveau_oclass *nvc0_fb_oclass;
extern struct nouveau_oclass *nve0_fb_oclass; extern struct nouveau_oclass *nve0_fb_oclass;
#include <subdev/bios/ramcfg.h>
struct nouveau_ram_data {
struct nvbios_ramcfg bios;
};
struct nouveau_ram { struct nouveau_ram {
struct nouveau_object base; struct nouveau_object base;
enum { enum {
...@@ -143,6 +149,9 @@ struct nouveau_ram { ...@@ -143,6 +149,9 @@ struct nouveau_ram {
u32 freq; u32 freq;
u32 mr[16]; u32 mr[16];
u32 mr1_nuts; u32 mr1_nuts;
struct nouveau_ram_data *next;
struct nouveau_ram_data target;
}; };
#endif #endif
...@@ -24,11 +24,12 @@ ...@@ -24,11 +24,12 @@
#include <subdev/bios.h> #include <subdev/bios.h>
#include <subdev/bios/bit.h> #include <subdev/bios/bit.h>
#include <subdev/bios/ramcfg.h>
#include <subdev/bios/rammap.h> #include <subdev/bios/rammap.h>
u16 u32
nvbios_rammap_table(struct nouveau_bios *bios, u8 *ver, u8 *hdr, nvbios_rammapTe(struct nouveau_bios *bios, u8 *ver, u8 *hdr,
u8 *cnt, u8 *len, u8 *snr, u8 *ssz) u8 *cnt, u8 *len, u8 *snr, u8 *ssz)
{ {
struct bit_entry bit_P; struct bit_entry bit_P;
u16 rammap = 0x0000; u16 rammap = 0x0000;
...@@ -57,12 +58,12 @@ nvbios_rammap_table(struct nouveau_bios *bios, u8 *ver, u8 *hdr, ...@@ -57,12 +58,12 @@ nvbios_rammap_table(struct nouveau_bios *bios, u8 *ver, u8 *hdr,
return 0x0000; return 0x0000;
} }
u16 u32
nvbios_rammap_entry(struct nouveau_bios *bios, int idx, nvbios_rammapEe(struct nouveau_bios *bios, int idx,
u8 *ver, u8 *hdr, u8 *cnt, u8 *len) u8 *ver, u8 *hdr, u8 *cnt, u8 *len)
{ {
u8 snr, ssz; u8 snr, ssz;
u16 rammap = nvbios_rammap_table(bios, ver, hdr, cnt, len, &snr, &ssz); u16 rammap = nvbios_rammapTe(bios, ver, hdr, cnt, len, &snr, &ssz);
if (rammap && idx < *cnt) { if (rammap && idx < *cnt) {
rammap = rammap + *hdr + (idx * (*len + (snr * ssz))); rammap = rammap + *hdr + (idx * (*len + (snr * ssz)));
*hdr = *len; *hdr = *len;
...@@ -73,16 +74,99 @@ nvbios_rammap_entry(struct nouveau_bios *bios, int idx, ...@@ -73,16 +74,99 @@ nvbios_rammap_entry(struct nouveau_bios *bios, int idx,
return 0x0000; return 0x0000;
} }
u16 u32
nvbios_rammap_match(struct nouveau_bios *bios, u16 khz, nvbios_rammapEm(struct nouveau_bios *bios, u16 khz,
u8 *ver, u8 *hdr, u8 *cnt, u8 *len) u8 *ver, u8 *hdr, u8 *cnt, u8 *len)
{ {
int idx = 0; int idx = 0;
u32 data; u32 data;
while ((data = nvbios_rammap_entry(bios, idx++, ver, hdr, cnt, len))) { while ((data = nvbios_rammapEe(bios, idx++, ver, hdr, cnt, len))) {
if (khz >= nv_ro16(bios, data + 0x00) && if (khz >= nv_ro16(bios, data + 0x00) &&
khz <= nv_ro16(bios, data + 0x02)) khz <= nv_ro16(bios, data + 0x02))
break; break;
} }
return data; return data;
} }
u32
nvbios_rammapEp(struct nouveau_bios *bios, u16 khz,
u8 *ver, u8 *hdr, u8 *cnt, u8 *len,
struct nvbios_ramcfg *p)
{
u32 data = nvbios_rammapEm(bios, khz, ver, hdr, cnt, len);
memset(p, 0x00, sizeof(*p));
switch (!!data * *ver) {
case 0x11:
p->rammap_11_08_01 = (nv_ro08(bios, data + 0x08) & 0x01) >> 0;
p->rammap_11_08_0c = (nv_ro08(bios, data + 0x08) & 0x0c) >> 2;
p->rammap_11_08_10 = (nv_ro08(bios, data + 0x08) & 0x10) >> 4;
p->rammap_11_11_0c = (nv_ro08(bios, data + 0x11) & 0x0c) >> 2;
break;
default:
data = 0;
break;
}
return data;
}
u32
nvbios_rammapSe(struct nouveau_bios *bios, u32 data,
u8 ever, u8 ehdr, u8 ecnt, u8 elen, int idx,
u8 *ver, u8 *hdr)
{
if (idx < ecnt) {
data = data + ehdr + (idx * elen);
*ver = ever;
*hdr = elen;
return data;
}
return 0;
}
u32
nvbios_rammapSp(struct nouveau_bios *bios, u32 data,
u8 ever, u8 ehdr, u8 ecnt, u8 elen, int idx,
u8 *ver, u8 *hdr, struct nvbios_ramcfg *p)
{
data = nvbios_rammapSe(bios, data, ever, ehdr, ecnt, elen, idx, ver, hdr);
switch (!!data * *ver) {
case 0x11:
p->ramcfg_11_01_01 = (nv_ro08(bios, data + 0x01) & 0x01) >> 0;
p->ramcfg_11_01_02 = (nv_ro08(bios, data + 0x01) & 0x02) >> 1;
p->ramcfg_11_01_04 = (nv_ro08(bios, data + 0x01) & 0x04) >> 2;
p->ramcfg_11_01_08 = (nv_ro08(bios, data + 0x01) & 0x08) >> 3;
p->ramcfg_11_01_10 = (nv_ro08(bios, data + 0x01) & 0x10) >> 4;
p->ramcfg_11_01_20 = (nv_ro08(bios, data + 0x01) & 0x20) >> 5;
p->ramcfg_11_01_40 = (nv_ro08(bios, data + 0x01) & 0x40) >> 6;
p->ramcfg_11_01_80 = (nv_ro08(bios, data + 0x01) & 0x80) >> 7;
p->ramcfg_11_02_03 = (nv_ro08(bios, data + 0x02) & 0x03) >> 0;
p->ramcfg_11_02_04 = (nv_ro08(bios, data + 0x02) & 0x04) >> 2;
p->ramcfg_11_02_08 = (nv_ro08(bios, data + 0x02) & 0x08) >> 3;
p->ramcfg_11_02_10 = (nv_ro08(bios, data + 0x02) & 0x10) >> 4;
p->ramcfg_11_02_40 = (nv_ro08(bios, data + 0x02) & 0x40) >> 6;
p->ramcfg_11_02_80 = (nv_ro08(bios, data + 0x02) & 0x80) >> 7;
p->ramcfg_11_03_0f = (nv_ro08(bios, data + 0x03) & 0x0f) >> 0;
p->ramcfg_11_03_30 = (nv_ro08(bios, data + 0x03) & 0x30) >> 4;
p->ramcfg_11_03_c0 = (nv_ro08(bios, data + 0x03) & 0xc0) >> 6;
p->ramcfg_11_03_f0 = (nv_ro08(bios, data + 0x03) & 0xf0) >> 4;
p->ramcfg_11_04 = (nv_ro08(bios, data + 0x04) & 0xff) >> 0;
p->ramcfg_11_06 = (nv_ro08(bios, data + 0x06) & 0xff) >> 0;
p->ramcfg_11_07_02 = (nv_ro08(bios, data + 0x07) & 0x02) >> 1;
p->ramcfg_11_07_04 = (nv_ro08(bios, data + 0x07) & 0x04) >> 2;
p->ramcfg_11_07_08 = (nv_ro08(bios, data + 0x07) & 0x08) >> 3;
p->ramcfg_11_07_10 = (nv_ro08(bios, data + 0x07) & 0x10) >> 4;
p->ramcfg_11_07_40 = (nv_ro08(bios, data + 0x07) & 0x40) >> 6;
p->ramcfg_11_07_80 = (nv_ro08(bios, data + 0x07) & 0x80) >> 7;
p->ramcfg_11_08_01 = (nv_ro08(bios, data + 0x08) & 0x01) >> 0;
p->ramcfg_11_08_02 = (nv_ro08(bios, data + 0x08) & 0x02) >> 1;
p->ramcfg_11_08_04 = (nv_ro08(bios, data + 0x08) & 0x04) >> 2;
p->ramcfg_11_08_08 = (nv_ro08(bios, data + 0x08) & 0x08) >> 3;
p->ramcfg_11_08_10 = (nv_ro08(bios, data + 0x08) & 0x10) >> 4;
p->ramcfg_11_09 = (nv_ro08(bios, data + 0x09) & 0xff) >> 0;
break;
default:
data = 0;
break;
}
return data;
}
...@@ -24,6 +24,7 @@ ...@@ -24,6 +24,7 @@
#include <subdev/bios.h> #include <subdev/bios.h>
#include <subdev/bios/bit.h> #include <subdev/bios/bit.h>
#include <subdev/bios/ramcfg.h>
#include <subdev/bios/timing.h> #include <subdev/bios/timing.h>
u16 u16
...@@ -81,3 +82,46 @@ nvbios_timingEe(struct nouveau_bios *bios, int idx, ...@@ -81,3 +82,46 @@ nvbios_timingEe(struct nouveau_bios *bios, int idx,
} }
return 0x0000; return 0x0000;
} }
u16
nvbios_timingEp(struct nouveau_bios *bios, int idx,
u8 *ver, u8 *hdr, u8 *cnt, u8 *len,
struct nvbios_ramcfg *p)
{
u16 data = nvbios_timingEe(bios, idx, ver, hdr, cnt, len), temp;
switch (!!data * *ver) {
case 0x20:
p->timing[0] = nv_ro32(bios, data + 0x00);
p->timing[1] = nv_ro32(bios, data + 0x04);
p->timing[2] = nv_ro32(bios, data + 0x08);
p->timing[3] = nv_ro32(bios, data + 0x0c);
p->timing[4] = nv_ro32(bios, data + 0x10);
p->timing[5] = nv_ro32(bios, data + 0x14);
p->timing[6] = nv_ro32(bios, data + 0x18);
p->timing[7] = nv_ro32(bios, data + 0x1c);
p->timing[8] = nv_ro32(bios, data + 0x20);
p->timing[9] = nv_ro32(bios, data + 0x24);
p->timing[10] = nv_ro32(bios, data + 0x28);
p->timing_20_2e_03 = (nv_ro08(bios, data + 0x2e) & 0x03) >> 0;
p->timing_20_2e_30 = (nv_ro08(bios, data + 0x2e) & 0x30) >> 4;
p->timing_20_2e_c0 = (nv_ro08(bios, data + 0x2e) & 0xc0) >> 6;
p->timing_20_2f_03 = (nv_ro08(bios, data + 0x2f) & 0x03) >> 0;
temp = nv_ro16(bios, data + 0x2c);
p->timing_20_2c_003f = (temp & 0x003f) >> 0;
p->timing_20_2c_1fc0 = (temp & 0x1fc0) >> 6;
p->timing_20_30_07 = (nv_ro08(bios, data + 0x30) & 0x07) >> 0;
p->timing_20_30_f8 = (nv_ro08(bios, data + 0x30) & 0xf8) >> 3;
temp = nv_ro16(bios, data + 0x31);
p->timing_20_31_0007 = (temp & 0x0007) >> 0;
p->timing_20_31_0078 = (temp & 0x0078) >> 3;
p->timing_20_31_0780 = (temp & 0x0780) >> 7;
p->timing_20_31_0800 = (temp & 0x0800) >> 11;
p->timing_20_31_7000 = (temp & 0x7000) >> 12;
p->timing_20_31_8000 = (temp & 0x8000) >> 15;
break;
default:
data = 0;
break;
}
return data;
}
...@@ -28,34 +28,33 @@ ...@@ -28,34 +28,33 @@
int int
nouveau_gddr5_calc(struct nouveau_ram *ram, bool nuts) nouveau_gddr5_calc(struct nouveau_ram *ram, bool nuts)
{ {
struct nouveau_bios *bios = nouveau_bios(ram);
int pd, lf, xd, vh, vr, vo, l3; int pd, lf, xd, vh, vr, vo, l3;
int WL, CL, WR, at[2], dt, ds; int WL, CL, WR, at[2], dt, ds;
int rq = ram->freq < 1000000; /* XXX */ int rq = ram->freq < 1000000; /* XXX */
switch (!!ram->ramcfg.data * ram->ramcfg.version) { switch (ram->ramcfg.version) {
case 0x11: case 0x11:
pd = (nv_ro08(bios, ram->ramcfg.data + 0x01) & 0x80) >> 7; pd = ram->next->bios.ramcfg_11_01_80;
lf = (nv_ro08(bios, ram->ramcfg.data + 0x01) & 0x40) >> 6; lf = ram->next->bios.ramcfg_11_01_40;
xd = !(nv_ro08(bios, ram->ramcfg.data + 0x01) & 0x20); xd = !ram->next->bios.ramcfg_11_01_20;
vh = (nv_ro08(bios, ram->ramcfg.data + 0x02) & 0x10) >> 4; vh = ram->next->bios.ramcfg_11_02_10;
vr = (nv_ro08(bios, ram->ramcfg.data + 0x02) & 0x04) >> 2; vr = ram->next->bios.ramcfg_11_02_04;
vo = nv_ro08(bios, ram->ramcfg.data + 0x06) & 0xff; vo = ram->next->bios.ramcfg_11_06;
l3 = !(nv_ro08(bios, ram->ramcfg.data + 0x07) & 0x02); l3 = !ram->next->bios.ramcfg_11_07_02;
break; break;
default: default:
return -ENOSYS; return -ENOSYS;
} }
switch (!!ram->timing.data * ram->timing.version) { switch (ram->timing.version) {
case 0x20: case 0x20:
WL = (nv_ro16(bios, ram->timing.data + 0x04) & 0x0f80) >> 7; WL = (ram->next->bios.timing[1] & 0x00000f80) >> 7;
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;
at[0] = (nv_ro08(bios, ram->timing.data + 0x2e) & 0xc0) >> 6; at[0] = ram->next->bios.timing_20_2e_c0;
at[1] = (nv_ro08(bios, ram->timing.data + 0x2e) & 0x30) >> 4; at[1] = ram->next->bios.timing_20_2e_30;
dt = nv_ro08(bios, ram->timing.data + 0x2e) & 0x03; dt = ram->next->bios.timing_20_2e_03;
ds = nv_ro08(bios, ram->timing.data + 0x2f) & 0x03; ds = ram->next->bios.timing_20_2f_03;
break; break;
default: default:
return -ENOSYS; return -ENOSYS;
......
...@@ -90,8 +90,8 @@ nva3_ram_calc(struct nouveau_fb *pfb, u32 freq) ...@@ -90,8 +90,8 @@ nva3_ram_calc(struct nouveau_fb *pfb, u32 freq)
int ret; int ret;
/* lookup memory config data relevant to the target frequency */ /* lookup memory config data relevant to the target frequency */
rammap.data = nvbios_rammap_match(bios, freq / 1000, &ver, &rammap.size, rammap.data = nvbios_rammapEm(bios, freq / 1000, &ver, &rammap.size,
&cnt, &ramcfg.size); &cnt, &ramcfg.size);
if (!rammap.data || ver != 0x10 || rammap.size < 0x0e) { if (!rammap.data || ver != 0x10 || rammap.size < 0x0e) {
nv_error(pfb, "invalid/missing rammap entry\n"); nv_error(pfb, "invalid/missing rammap entry\n");
return -EINVAL; return -EINVAL;
......
...@@ -144,8 +144,8 @@ nvc0_ram_calc(struct nouveau_fb *pfb, u32 freq) ...@@ -144,8 +144,8 @@ nvc0_ram_calc(struct nouveau_fb *pfb, u32 freq)
int ret; int ret;
/* lookup memory config data relevant to the target frequency */ /* lookup memory config data relevant to the target frequency */
rammap.data = nvbios_rammap_match(bios, freq / 1000, &ver, &rammap.size, rammap.data = nvbios_rammapEm(bios, freq / 1000, &ver, &rammap.size,
&cnt, &ramcfg.size); &cnt, &ramcfg.size);
if (!rammap.data || ver != 0x10 || rammap.size < 0x0e) { if (!rammap.data || ver != 0x10 || rammap.size < 0x0e) {
nv_error(pfb, "invalid/missing rammap entry\n"); nv_error(pfb, "invalid/missing rammap entry\n");
return -EINVAL; return -EINVAL;
......
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