V2: - Slightly clarify the conditional timings in nv50_ram_timing_calc() - now rated U, approved for general audiences
Roy Spliet
2015-May-23 08:37 UTC
[Nouveau] [PATCH v2 01/10] clk/gt215: u32->s32 for difference in req. and set clock
This difference can of course be negative too...
Signed-off-by: Roy Spliet <rspliet at eclipso.eu>
---
drivers/gpu/drm/nouveau/nvkm/subdev/clk/gt215.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/clk/gt215.c
b/drivers/gpu/drm/nouveau/nvkm/subdev/clk/gt215.c
index 822d32a..065e9f5 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/clk/gt215.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/clk/gt215.c
@@ -180,7 +180,8 @@ gt215_clk_info(struct nvkm_clk *clock, int clk, u32 khz,
struct gt215_clk_info *info)
{
struct gt215_clk_priv *priv = (void *)clock;
- u32 oclk, sclk, sdiv, diff;
+ u32 oclk, sclk, sdiv;
+ s32 diff;
info->clk = 0;
--
2.1.0
Roy Spliet
2015-May-23 08:37 UTC
[Nouveau] [PATCH v2 02/10] bios/rammap: Pull DLLoff bit out of version 0x10 struct
In preparation of NV50 reclocking, where there is no version
Signed-off-by: Roy Spliet <rspliet at eclipso.eu>
---
drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/ramcfg.h | 2 +-
drivers/gpu/drm/nouveau/nvkm/subdev/bios/rammap.c | 2 +-
drivers/gpu/drm/nouveau/nvkm/subdev/fb/gddr3.c | 2 +-
drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgt215.c | 6 +++---
drivers/gpu/drm/nouveau/nvkm/subdev/fb/sddr2.c | 2 +-
drivers/gpu/drm/nouveau/nvkm/subdev/fb/sddr3.c | 2 +-
6 files changed, 8 insertions(+), 8 deletions(-)
diff --git a/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/ramcfg.h
b/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/ramcfg.h
index 4204267..c6fb6aa 100644
--- a/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/ramcfg.h
+++ b/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/ramcfg.h
@@ -32,6 +32,7 @@ struct nvbios_ramcfg {
unsigned ramcfg_ver;
unsigned ramcfg_hdr;
unsigned ramcfg_timing;
+ unsigned ramcfg_DLLoff;
union {
struct {
unsigned ramcfg_10_02_01:1;
@@ -40,7 +41,6 @@ struct nvbios_ramcfg {
unsigned ramcfg_10_02_08:1;
unsigned ramcfg_10_02_10:1;
unsigned ramcfg_10_02_20:1;
- unsigned ramcfg_10_DLLoff:1;
unsigned ramcfg_10_03_0f:4;
unsigned ramcfg_10_04_01:1;
unsigned ramcfg_10_05:8;
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/bios/rammap.c
b/drivers/gpu/drm/nouveau/nvkm/subdev/bios/rammap.c
index 8b17bb4..a688d3b 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/bios/rammap.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/bios/rammap.c
@@ -157,7 +157,7 @@ nvbios_rammapSp(struct nvkm_bios *bios, u32 data,
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_DLLoff = (nv_ro08(bios, data + 0x02) & 0x40) >> 6;
+ p->ramcfg_DLLoff = (nv_ro08(bios, data + 0x02) & 0x40) >> 6;
p->ramcfg_10_03_0f = (nv_ro08(bios, data + 0x03) & 0x0f) >> 0;
p->ramcfg_10_04_01 = (nv_ro08(bios, data + 0x04) & 0x01) >> 0;
p->ramcfg_10_05 = (nv_ro08(bios, data + 0x05) & 0xff) >> 0;
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gddr3.c
b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gddr3.c
index 15b462a..e1d11f7 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gddr3.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gddr3.c
@@ -77,7 +77,7 @@ nvkm_gddr3_calc(struct nvkm_ram *ram)
CWL = ram->next->bios.timing_10_CWL;
CL = ram->next->bios.timing_10_CL;
WR = ram->next->bios.timing_10_WR;
- DLL = !ram->next->bios.ramcfg_10_DLLoff;
+ DLL = !ram->next->bios.ramcfg_DLLoff;
ODT = ram->next->bios.timing_10_ODT;
break;
case 0x20:
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgt215.c
b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgt215.c
index 2417640..47d53ed 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgt215.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgt215.c
@@ -590,7 +590,7 @@ gt215_ram_calc(struct nvkm_fb *pfb, u32 freq)
r100da0 = 0x00000000;
}
- if (!next->bios.ramcfg_10_DLLoff)
+ if (!next->bios.ramcfg_DLLoff)
r004018 |= 0x00004000;
/* pll2pll requires to switch to a safe clock first */
@@ -630,7 +630,7 @@ gt215_ram_calc(struct nvkm_fb *pfb, u32 freq)
}
/* If we're disabling the DLL, do it now */
- switch (next->bios.ramcfg_10_DLLoff * ram->base.type) {
+ switch (next->bios.ramcfg_DLLoff * ram->base.type) {
case NV_MEM_TYPE_DDR3:
nvkm_sddr3_dll_disable(fuc, ram->base.mr);
break;
@@ -810,7 +810,7 @@ gt215_ram_calc(struct nvkm_fb *pfb, u32 freq)
gt215_ram_fbvref(fuc, 1);
/* Reset DLL */
- if (!next->bios.ramcfg_10_DLLoff)
+ if (!next->bios.ramcfg_DLLoff)
nvkm_sddr2_dll_reset(fuc);
if (ram->base.type == NV_MEM_TYPE_GDDR3) {
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/sddr2.c
b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/sddr2.c
index afab42d..86bf674 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/sddr2.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/sddr2.c
@@ -65,7 +65,7 @@ nvkm_sddr2_calc(struct nvkm_ram *ram)
case 0x10:
CL = ram->next->bios.timing_10_CL;
WR = ram->next->bios.timing_10_WR;
- DLL = !ram->next->bios.ramcfg_10_DLLoff;
+ DLL = !ram->next->bios.ramcfg_DLLoff;
ODT = ram->next->bios.timing_10_ODT & 3;
break;
case 0x20:
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/sddr3.c
b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/sddr3.c
index 1084435..77c53f9 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/sddr3.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/sddr3.c
@@ -79,7 +79,7 @@ nvkm_sddr3_calc(struct nvkm_ram *ram)
CWL = ram->next->bios.timing_10_CWL;
CL = ram->next->bios.timing_10_CL;
WR = ram->next->bios.timing_10_WR;
- DLL = !ram->next->bios.ramcfg_10_DLLoff;
+ DLL = !ram->next->bios.ramcfg_DLLoff;
ODT = ram->next->bios.timing_10_ODT;
break;
case 0x20:
--
2.1.0
Roy Spliet
2015-May-23 08:37 UTC
[Nouveau] [PATCH v2 03/10] fb/ramnv50: Make 0x100da0 per-partition
Like on GT215
Signed-off-by: Roy Spliet <rspliet at eclipso.eu>
---
drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramnv50.c | 20 +++++++++++++-------
1 file changed, 13 insertions(+), 7 deletions(-)
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramnv50.c
b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramnv50.c
index d2c81dd..67715c6 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramnv50.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramnv50.c
@@ -42,7 +42,7 @@ struct nv50_ramseq {
struct hwsq_reg r_0x1002d0;
struct hwsq_reg r_0x1002d4;
struct hwsq_reg r_0x1002dc;
- struct hwsq_reg r_0x100da0[8];
+ struct hwsq_reg r_0x100da0;
struct hwsq_reg r_0x100e20;
struct hwsq_reg r_0x100e24;
struct hwsq_reg r_0x611200;
@@ -70,6 +70,7 @@ nv50_ram_calc(struct nvkm_fb *pfb, u32 freq)
u8 size;
} ramcfg, timing;
u8 ver, hdr, cnt, len, strap;
+ u32 r100da0;
int N1, M1, N2, M2, P;
int ret, i;
@@ -109,6 +110,13 @@ nv50_ram_calc(struct nvkm_fb *pfb, u32 freq)
timing.data = 0;
}
+ /* XXX: 750MHz seems rather arbitrary */
+ if (freq <= 750000) {
+ r100da0 = 0x00000010;
+ } else {
+ r100da0 = 0x00000000;
+ }
+
ret = ram_init(hwsq, nv_subdev(pfb));
if (ret)
return ret;
@@ -144,10 +152,9 @@ nv50_ram_calc(struct nvkm_fb *pfb, u32 freq)
ram_mask(hwsq, 0x00400c, 0x0000ffff, (N1 << 8) | M1);
ram_mask(hwsq, 0x004008, 0x81ff0000, 0x80000000 | (mpll.bias_p << 19) |
(P << 22) | (P << 16));
-#if QFX5800NVA0
- for (i = 0; i < 8; i++)
- ram_mask(hwsq, 0x100da0[i], 0x00000000, 0x00000000); /*XXX*/
-#endif
+
+ if (nv_device(pfb)->chipset == 0xa0)
+ ram_wr32(hwsq, 0x100da0, r100da0); /*XXX: here?*/
ram_nsec(hwsq, 96000); /*XXX*/
ram_mask(hwsq, 0x004008, 0x00002200, 0x00002000);
@@ -430,8 +437,7 @@ nv50_ram_ctor(struct nvkm_object *parent, struct nvkm_object
*engine,
ram->hwsq.r_0x1002d0 = hwsq_reg(0x1002d0);
ram->hwsq.r_0x1002d4 = hwsq_reg(0x1002d4);
ram->hwsq.r_0x1002dc = hwsq_reg(0x1002dc);
- for (i = 0; i < 8; i++)
- ram->hwsq.r_0x100da0[i] = hwsq_reg(0x100da0 + (i * 0x04));
+ ram->hwsq.r_0x100da0 = hwsq_stride(0x100da0, 4, ram->base.part_mask);
ram->hwsq.r_0x100e20 = hwsq_reg(0x100e20);
ram->hwsq.r_0x100e24 = hwsq_reg(0x100e24);
ram->hwsq.r_0x611200 = hwsq_reg(0x611200);
--
2.1.0
Roy Spliet
2015-May-23 08:37 UTC
[Nouveau] [PATCH v2 04/10] fb/ramgt215: No need to cuss like that
Signed-off-by: Roy Spliet <rspliet at eclipso.eu>
---
drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgt215.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgt215.c
b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgt215.c
index 47d53ed..bc36a4f 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgt215.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgt215.c
@@ -579,7 +579,7 @@ gt215_ram_calc(struct nvkm_fb *pfb, u32 freq)
if (ret)
return ret;
- /* XXX: where the fuck does 750MHz come from? */
+ /* XXX: 750MHz seems rather arbitrary */
if (freq <= 750000) {
r004018 = 0x10000000;
r100760 = 0x22222222;
--
2.1.0
Roy Spliet
2015-May-23 08:37 UTC
[Nouveau] [PATCH v2 05/10] fb/ramnv50: Ressurect timing code, use proper timing/rammap handlers
Might need some generalisation to < GT200. For those: use at your own risk!
Signed-off-by: Roy Spliet <rspliet at eclipso.eu>
---
.../drm/nouveau/include/nvkm/subdev/bios/ramcfg.h | 16 ++
.../drm/nouveau/include/nvkm/subdev/bios/rammap.h | 2 +
drivers/gpu/drm/nouveau/nvkm/subdev/bios/rammap.c | 29 ++++
drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramnv50.c | 168 +++++++++++++++++----
4 files changed, 182 insertions(+), 33 deletions(-)
diff --git a/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/ramcfg.h
b/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/ramcfg.h
index c6fb6aa..f09b6bf 100644
--- a/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/ramcfg.h
+++ b/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/ramcfg.h
@@ -35,6 +35,22 @@ struct nvbios_ramcfg {
unsigned ramcfg_DLLoff;
union {
struct {
+ unsigned ramcfg_00_03_01:1;
+ unsigned ramcfg_00_03_02:1;
+ unsigned ramcfg_00_03_08:1;
+ unsigned ramcfg_00_03_10:1;
+ unsigned ramcfg_00_04_02:1;
+ unsigned ramcfg_00_04_04:1;
+ unsigned ramcfg_00_04_20:1;
+ unsigned ramcfg_00_05:8;
+ unsigned ramcfg_00_06:8;
+ unsigned ramcfg_00_07:8;
+ unsigned ramcfg_00_08:8;
+ unsigned ramcfg_00_09:8;
+ unsigned ramcfg_00_0a_0f:4;
+ unsigned ramcfg_00_0a_f0:4;
+ };
+ struct {
unsigned ramcfg_10_02_01:1;
unsigned ramcfg_10_02_02:1;
unsigned ramcfg_10_02_04:1;
diff --git a/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/rammap.h
b/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/rammap.h
index 609a905..2044fc9 100644
--- a/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/rammap.h
+++ b/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/rammap.h
@@ -15,6 +15,8 @@ u32 nvbios_rammapEm(struct nvkm_bios *, u16 mhz,
u32 nvbios_rammapSe(struct nvkm_bios *, u32 data,
u8 ever, u8 ehdr, u8 ecnt, u8 elen, int idx,
u8 *ver, u8 *hdr);
+u32 nvbios_rammapSp_from_perf(struct nvkm_bios *bios, u32 data, u8 size, int
idx,
+ struct nvbios_ramcfg *p);
u32 nvbios_rammapSp(struct nvkm_bios *, u32 data,
u8 ever, u8 ehdr, u8 ecnt, u8 elen, int idx,
u8 *ver, u8 *hdr, struct nvbios_ramcfg *);
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/bios/rammap.c
b/drivers/gpu/drm/nouveau/nvkm/subdev/bios/rammap.c
index a688d3b..4ec376a 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/bios/rammap.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/bios/rammap.c
@@ -141,6 +141,35 @@ nvbios_rammapSe(struct nvkm_bios *bios, u32 data,
}
u32
+nvbios_rammapSp_from_perf(struct nvkm_bios *bios, u32 data, u8 size, int idx,
+ struct nvbios_ramcfg *p)
+{
+ data += (idx * size);
+
+ if (size < 11)
+ return NULL;
+
+ p->ramcfg_timing = nv_ro08(bios, data + 0x01);
+ p->ramcfg_00_03_01 = (nv_ro08(bios, data + 0x03) & 0x01) >> 0;
+ p->ramcfg_00_03_02 = (nv_ro08(bios, data + 0x03) & 0x02) >> 1;
+ p->ramcfg_DLLoff = (nv_ro08(bios, data + 0x03) & 0x04) >> 2;
+ p->ramcfg_00_03_08 = (nv_ro08(bios, data + 0x03) & 0x08) >> 3;
+ p->ramcfg_00_03_10 = (nv_ro08(bios, data + 0x03) & 0x10) >> 4;
+ p->ramcfg_00_04_02 = (nv_ro08(bios, data + 0x04) & 0x02) >> 1;
+ p->ramcfg_00_04_04 = (nv_ro08(bios, data + 0x04) & 0x04) >> 2;
+ p->ramcfg_00_04_20 = (nv_ro08(bios, data + 0x04) & 0x20) >> 5;
+ p->ramcfg_00_05 = (nv_ro08(bios, data + 0x05) & 0xff) >> 0;
+ p->ramcfg_00_06 = (nv_ro08(bios, data + 0x06) & 0xff) >> 0;
+ p->ramcfg_00_07 = (nv_ro08(bios, data + 0x07) & 0xff) >> 0;
+ p->ramcfg_00_08 = (nv_ro08(bios, data + 0x08) & 0xff) >> 0;
+ p->ramcfg_00_09 = (nv_ro08(bios, data + 0x09) & 0xff) >> 0;
+ p->ramcfg_00_0a_0f = (nv_ro08(bios, data + 0x0a) & 0x0f) >> 0;
+ p->ramcfg_00_0a_f0 = (nv_ro08(bios, data + 0x0a) & 0xf0) >> 4;
+
+ return data;
+}
+
+u32
nvbios_rammapSp(struct nvkm_bios *bios, u32 data,
u8 ever, u8 ehdr, u8 ecnt, u8 elen, int idx,
u8 *ver, u8 *hdr, struct nvbios_ramcfg *p)
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramnv50.c
b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramnv50.c
index 67715c6..37ccc4d 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramnv50.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramnv50.c
@@ -29,6 +29,7 @@
#include <subdev/bios.h>
#include <subdev/bios/perf.h>
#include <subdev/bios/pll.h>
+#include <subdev/bios/rammap.h>
#include <subdev/bios/timing.h>
#include <subdev/clk/pll.h>
@@ -55,6 +56,85 @@ struct nv50_ram {
struct nv50_ramseq hwsq;
};
+#define T(t) cfg->timing_10_##t
+static int
+nv50_ram_timing_calc(struct nvkm_fb *pfb, u32 *timing)
+{
+ struct nv50_ram *ram = (void *)pfb->ram;
+ struct nvbios_ramcfg *cfg = &ram->base.target.bios;
+ u32 cur2, cur3, cur4, cur7, cur8;
+ u8 unkt3b;
+
+ cur2 = nv_rd32(pfb, 0x100228);
+ cur3 = nv_rd32(pfb, 0x10022c);
+ cur4 = nv_rd32(pfb, 0x100230);
+ cur7 = nv_rd32(pfb, 0x10023c);
+ cur8 = nv_rd32(pfb, 0x100240);
+
+ switch ((!T(CWL)) * ram->base.type) {
+ case NV_MEM_TYPE_DDR2:
+ T(CWL) = T(CL) - 1;
+ break;
+ case NV_MEM_TYPE_GDDR3:
+ T(CWL) = ((cur2 & 0xff000000) >> 24) + 1;
+ break;
+ }
+
+ /* XXX: N=1 is not proper statistics */
+ if (nv_device(pfb)->chipset == 0xa0) {
+ unkt3b = 0x19 + ram->base.next->bios.rammap_00_16_40;
+ timing[6] = (0x2d + T(CL) - T(CWL) +
+ ram->base.next->bios.rammap_00_16_40) << 16 |
+ T(CWL) << 8 |
+ (0x2f + T(CL) - T(CWL));
+ } else {
+ unkt3b = 0x16;
+ timing[6] = (0x2b + T(CL) - T(CWL)) << 16 |
+ max_t(s8, T(CWL) - 2, 1) << 8 |
+ (0x2e + T(CL) - T(CWL));
+ }
+
+ timing[0] = (T(RP) << 24 | T(RAS) << 16 | T(RFC) << 8 |
T(RC));
+ timing[1] = (T(WR) + 1 + T(CWL)) << 24 |
+ max_t(u8, T(18), 1) << 16 |
+ (T(WTR) + 1 + T(CWL)) << 8 |
+ (3 + T(CL) - T(CWL));
+ timing[2] = (T(CWL) - 1) << 24 |
+ (T(RRD) << 16) |
+ (T(RCDWR) << 8) |
+ T(RCDRD);
+ timing[3] = (unkt3b - 2 + T(CL)) << 24 |
+ unkt3b << 16 |
+ (T(CL) - 1) << 8 |
+ (T(CL) - 1);
+ timing[4] = (cur4 & 0xffff0000) |
+ T(13) << 8 |
+ T(13);
+ timing[5] = T(RFC) << 24 |
+ max_t(u8, T(RCDRD), T(RCDWR)) << 16 |
+ T(RP);
+ /* Timing 6 is already done above */
+ timing[7] = (cur7 & 0xff00ffff) | (T(CL) - 1) << 16;
+ timing[8] = (cur8 & 0xffffff00);
+
+ /* XXX: P.version == 1 only has DDR2 and GDDR3? */
+ if (pfb->ram->type == NV_MEM_TYPE_DDR2) {
+ timing[5] |= (T(CL) + 3) << 8;
+ timing[8] |= (T(CL) - 4);
+ } else if (pfb->ram->type == NV_MEM_TYPE_GDDR3) {
+ timing[5] |= (T(CL) + 2) << 8;
+ timing[8] |= (T(CL) - 2);
+ }
+
+ nv_debug(pfb, " 220: %08x %08x %08x %08x\n",
+ timing[0], timing[1], timing[2], timing[3]);
+ nv_debug(pfb, " 230: %08x %08x %08x %08x\n",
+ timing[4], timing[5], timing[6], timing[7]);
+ nv_debug(pfb, " 240: %08x\n", timing[8]);
+ return 0;
+}
+#undef T
+
#define QFX5800NVA0 1
static int
@@ -65,22 +145,25 @@ nv50_ram_calc(struct nvkm_fb *pfb, u32 freq)
struct nv50_ramseq *hwsq = &ram->hwsq;
struct nvbios_perfE perfE;
struct nvbios_pll mpll;
- struct {
- u32 data;
- u8 size;
- } ramcfg, timing;
- u8 ver, hdr, cnt, len, strap;
+ struct nvkm_ram_data *next;
+ u8 ver, hdr, cnt, len, strap, size;
+ u32 data;
u32 r100da0;
int N1, M1, N2, M2, P;
int ret, i;
+ u32 timing[9];
+
+ next = &ram->base.target;
+ next->freq = freq;
+ ram->base.next = next;
/* lookup closest matching performance table entry for frequency */
i = 0;
do {
- ramcfg.data = nvbios_perfEp(bios, i++, &ver, &hdr, &cnt,
- &ramcfg.size, &perfE);
- if (!ramcfg.data || (ver < 0x25 || ver >= 0x40) ||
- (ramcfg.size < 2)) {
+ data = nvbios_perfEp(bios, i++, &ver, &hdr, &cnt,
+ &size, &perfE);
+ if (!data || (ver < 0x25 || ver >= 0x40) ||
+ (size < 2)) {
nv_error(pfb, "invalid/missing perftab entry\n");
return -EINVAL;
}
@@ -93,23 +176,48 @@ nv50_ram_calc(struct nvkm_fb *pfb, u32 freq)
return -EINVAL;
}
- ramcfg.data += hdr + (strap * ramcfg.size);
+ data = nvbios_rammapSp_from_perf(bios, data + hdr, size, strap,
+ &next->bios);
+ if (!data) {
+ nv_error(pfb, "invalid/missing rammap entry ");
+ 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, &hdr,
- &cnt, &len);
- if (!timing.data || ver != 0x10 || hdr < 0x12) {
+ 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 < 0x12) {
nv_error(pfb, "invalid/missing timing entry "
"%02x %04x %02x %02x\n",
- strap, timing.data, ver, hdr);
+ strap, data, ver, hdr);
return -EINVAL;
}
- } else {
- timing.data = 0;
}
+ nv50_ram_timing_calc(pfb, timing);
+
+ ret = ram_init(hwsq, nv_subdev(pfb));
+ if (ret)
+ return ret;
+
+ /* Determine ram-specific MR values */
+ ram->base.mr[0] = ram_rd32(hwsq, mr[0]);
+ ram->base.mr[1] = ram_rd32(hwsq, mr[1]);
+ ram->base.mr[2] = ram_rd32(hwsq, mr[2]);
+
+ switch (ram->base.type) {
+ case NV_MEM_TYPE_GDDR3:
+ ret = nvkm_gddr3_calc(&ram->base);
+ break;
+ default:
+ ret = -ENOSYS;
+ break;
+ }
+
+ if (ret)
+ return ret;
+
/* XXX: 750MHz seems rather arbitrary */
if (freq <= 750000) {
r100da0 = 0x00000010;
@@ -117,10 +225,6 @@ nv50_ram_calc(struct nvkm_fb *pfb, u32 freq)
r100da0 = 0x00000000;
}
- ret = ram_init(hwsq, nv_subdev(pfb));
- if (ret)
- return ret;
-
ram_wait(hwsq, 0x01, 0x00); /* wait for !vblank */
ram_wait(hwsq, 0x01, 0x01); /* wait for vblank */
ram_wr32(hwsq, 0x611200, 0x00003300);
@@ -177,17 +281,15 @@ nv50_ram_calc(struct nvkm_fb *pfb, u32 freq)
break;
}
- ram_mask(hwsq, timing[3], 0x00000000, 0x00000000); /*XXX*/
- ram_mask(hwsq, timing[1], 0x00000000, 0x00000000); /*XXX*/
- ram_mask(hwsq, timing[6], 0x00000000, 0x00000000); /*XXX*/
- ram_mask(hwsq, timing[7], 0x00000000, 0x00000000); /*XXX*/
- ram_mask(hwsq, timing[8], 0x00000000, 0x00000000); /*XXX*/
- ram_mask(hwsq, timing[0], 0x00000000, 0x00000000); /*XXX*/
- ram_mask(hwsq, timing[2], 0x00000000, 0x00000000); /*XXX*/
- ram_mask(hwsq, timing[4], 0x00000000, 0x00000000); /*XXX*/
- ram_mask(hwsq, timing[5], 0x00000000, 0x00000000); /*XXX*/
-
- ram_mask(hwsq, timing[0], 0x00000000, 0x00000000); /*XXX*/
+ ram_mask(hwsq, timing[3], 0xffffffff, timing[3]);
+ ram_mask(hwsq, timing[1], 0xffffffff, timing[1]);
+ ram_mask(hwsq, timing[6], 0xffffffff, timing[6]);
+ ram_mask(hwsq, timing[7], 0xffffffff, timing[7]);
+ ram_mask(hwsq, timing[8], 0xffffffff, timing[8]);
+ ram_mask(hwsq, timing[0], 0xffffffff, timing[0]);
+ ram_mask(hwsq, timing[2], 0xffffffff, timing[2]);
+ ram_mask(hwsq, timing[4], 0xffffffff, timing[4]);
+ ram_mask(hwsq, timing[5], 0xffffffff, timing[5]);
#if QFX5800NVA0
ram_nuke(hwsq, 0x100e24);
--
2.1.0
Roy Spliet
2015-May-23 08:37 UTC
[Nouveau] [PATCH v2 06/10] bios/rammap: Parse perf mode as if it's a rammap entry
Some of the bits in there are similar to the bits in the gt215 rammap.
Signed-off-by: Roy Spliet <rspliet at eclipso.eu>
---
drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/ramcfg.h | 5 +++++
drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/rammap.h | 2 ++
drivers/gpu/drm/nouveau/nvkm/subdev/bios/rammap.c | 15 +++++++++++++++
drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramnv50.c | 2 ++
4 files changed, 24 insertions(+)
diff --git a/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/ramcfg.h
b/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/ramcfg.h
index f09b6bf..26e233a 100644
--- a/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/ramcfg.h
+++ b/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/ramcfg.h
@@ -7,6 +7,11 @@ struct nvbios_ramcfg {
unsigned rammap_max;
union {
struct {
+ unsigned rammap_00_16_20:1;
+ unsigned rammap_00_16_40:1;
+ unsigned rammap_00_17_02:1;
+ };
+ struct {
unsigned rammap_10_04_02:1;
unsigned rammap_10_04_08:1;
};
diff --git a/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/rammap.h
b/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/rammap.h
index 2044fc9..8d8ee13 100644
--- a/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/rammap.h
+++ b/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/rammap.h
@@ -7,6 +7,8 @@ u32 nvbios_rammapTe(struct nvkm_bios *, u8 *ver, u8 *hdr,
u32 nvbios_rammapEe(struct nvkm_bios *, int idx,
u8 *ver, u8 *hdr, u8 *cnt, u8 *len);
+u32 nvbios_rammapEp_from_perf(struct nvkm_bios *bios, u32 data, u8 size,
+ struct nvbios_ramcfg *p);
u32 nvbios_rammapEp(struct nvkm_bios *, int idx,
u8 *ver, u8 *hdr, u8 *cnt, u8 *len, struct nvbios_ramcfg *);
u32 nvbios_rammapEm(struct nvkm_bios *, u16 mhz,
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/bios/rammap.c
b/drivers/gpu/drm/nouveau/nvkm/subdev/bios/rammap.c
index 4ec376a..8da8b26 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/bios/rammap.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/bios/rammap.c
@@ -72,6 +72,21 @@ nvbios_rammapEe(struct nvkm_bios *bios, int idx,
return 0x0000;
}
+/* Pretend a performance mode is also a rammap entry, helps coalesce entries
+ * later on */
+u32
+nvbios_rammapEp_from_perf(struct nvkm_bios *bios, u32 data, u8 size,
+ struct nvbios_ramcfg *p)
+{
+ memset(p, 0x00, sizeof(*p));
+
+ p->rammap_00_16_20 = (nv_ro08(bios, data + 0x16) & 0x20) >> 5;
+ p->rammap_00_16_40 = (nv_ro08(bios, data + 0x16) & 0x40) >> 6;
+ p->rammap_00_17_02 = (nv_ro08(bios, data + 0x17) & 0x02) >> 1;
+
+ return data;
+}
+
u32
nvbios_rammapEp(struct nvkm_bios *bios, int idx,
u8 *ver, u8 *hdr, u8 *cnt, u8 *len, struct nvbios_ramcfg *p)
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramnv50.c
b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramnv50.c
index 37ccc4d..91e9cff 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramnv50.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramnv50.c
@@ -169,6 +169,8 @@ nv50_ram_calc(struct nvkm_fb *pfb, u32 freq)
}
} while (perfE.memory < freq);
+ nvbios_rammapEp_from_perf(bios, data, hdr, &next->bios);
+
/* locate specific data set for the attached memory */
strap = nvbios_ramcfg_index(nv_subdev(pfb));
if (strap >= cnt) {
--
2.1.0