Roy Spliet
2015-May-24 08:43 UTC
[Nouveau] [PATCH v2 07/10] bios/ramcfg: Separate out RON pull value
Signed-off-by: Roy Spliet <rspliet at eclipso.eu>
---
drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/ramcfg.h | 1 +
drivers/gpu/drm/nouveau/nvkm/subdev/bios/rammap.c | 3 ++-
drivers/gpu/drm/nouveau/nvkm/subdev/bios/timing.c | 2 ++
drivers/gpu/drm/nouveau/nvkm/subdev/fb/gddr3.c | 6 ++++--
4 files changed, 9 insertions(+), 3 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 26e233a..3a9abd3 100644
--- a/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/ramcfg.h
+++ b/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/ramcfg.h
@@ -38,6 +38,7 @@ struct nvbios_ramcfg {
unsigned ramcfg_hdr;
unsigned ramcfg_timing;
unsigned ramcfg_DLLoff;
+ unsigned ramcfg_RON;
union {
struct {
unsigned ramcfg_00_03_01:1;
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/bios/rammap.c
b/drivers/gpu/drm/nouveau/nvkm/subdev/bios/rammap.c
index 8da8b26..5815f42 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/bios/rammap.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/bios/rammap.c
@@ -164,12 +164,13 @@ nvbios_rammapSp_from_perf(struct nvkm_bios *bios, u32
data, u8 size, int idx,
if (size < 11)
return NULL;
+ p->ramcfg_ver = 0;
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_RON = (nv_ro08(bios, data + 0x03) & 0x10) >> 3;
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;
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/bios/timing.c
b/drivers/gpu/drm/nouveau/nvkm/subdev/bios/timing.c
index 763fd29..bacd433 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/bios/timing.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/bios/timing.c
@@ -102,6 +102,8 @@ nvbios_timingEp(struct nvkm_bios *bios, int idx,
p->timing_10_RRD = nv_ro08(bios, data + 0x0c);
p->timing_10_13 = nv_ro08(bios, data + 0x0d);
p->timing_10_ODT = nv_ro08(bios, data + 0x0e) & 0x07;
+ if (p->ramcfg_ver >= 0x10)
+ p->ramcfg_RON = nv_ro08(bios, data + 0x0e) & 0x07;
p->timing_10_24 = 0xff;
p->timing_10_21 = 0;
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gddr3.c
b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gddr3.c
index e1d11f7..8d759f8a 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gddr3.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gddr3.c
@@ -70,7 +70,7 @@ ramgddr3_wr_lo[] = {
int
nvkm_gddr3_calc(struct nvkm_ram *ram)
{
- int CL, WR, CWL, DLL = 0, ODT = 0, hi;
+ int CL, WR, CWL, DLL = 0, ODT = 0, RON, hi;
switch (ram->next->bios.timing_ver) {
case 0x10:
@@ -79,6 +79,7 @@ nvkm_gddr3_calc(struct nvkm_ram *ram)
WR = ram->next->bios.timing_10_WR;
DLL = !ram->next->bios.ramcfg_DLLoff;
ODT = ram->next->bios.timing_10_ODT;
+ RON = ram->next->bios.ramcfg_RON;
break;
case 0x20:
CWL = (ram->next->bios.timing[1] & 0x00000f80) >> 7;
@@ -89,6 +90,7 @@ nvkm_gddr3_calc(struct nvkm_ram *ram)
ODT = (ram->mr[1] & 0x004) >> 2 |
(ram->mr[1] & 0x040) >> 5 |
(ram->mr[1] & 0x200) >> 7;
+ RON = !(ram->mr[1] & 0x300) >> 8;
break;
default:
return -ENOSYS;
@@ -107,7 +109,7 @@ nvkm_gddr3_calc(struct nvkm_ram *ram)
ram->mr[1] &= ~0x3fc;
ram->mr[1] |= (ODT & 0x03) << 2;
- ram->mr[1] |= (ODT & 0x03) << 8;
+ ram->mr[1] |= (RON & 0x03) << 8;
ram->mr[1] |= (WR & 0x03) << 4;
ram->mr[1] |= (WR & 0x04) << 5;
ram->mr[1] |= !DLL << 6;
--
2.1.0
Roy Spliet
2015-May-24 08:44 UTC
[Nouveau] [PATCH v2 08/10] fb/ramnv50: GDDR3 script for NVA0
This looks surprisingly similar to scripts on earlier cards as well
but they don't seem to work just yet. That... and I don't have any,
which
makes it a tough job to reverse engineer.
Signed-off-by: Roy Spliet <rspliet at eclipso.eu>
---
drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramnv50.c | 129 ++++++++++++++++++-----
1 file changed, 104 insertions(+), 25 deletions(-)
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramnv50.c
b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramnv50.c
index 91e9cff..66db0a4 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramnv50.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramnv50.c
@@ -39,10 +39,19 @@ struct nv50_ramseq {
struct hwsq_reg r_0x004008;
struct hwsq_reg r_0x00400c;
struct hwsq_reg r_0x00c040;
+ struct hwsq_reg r_0x100200;
struct hwsq_reg r_0x100210;
+ struct hwsq_reg r_0x10021c;
struct hwsq_reg r_0x1002d0;
struct hwsq_reg r_0x1002d4;
struct hwsq_reg r_0x1002dc;
+ struct hwsq_reg r_0x10053c;
+ struct hwsq_reg r_0x1005a0;
+ struct hwsq_reg r_0x1005a4;
+ struct hwsq_reg r_0x100710;
+ struct hwsq_reg r_0x100714;
+ struct hwsq_reg r_0x100718;
+ struct hwsq_reg r_0x10071c;
struct hwsq_reg r_0x100da0;
struct hwsq_reg r_0x100e20;
struct hwsq_reg r_0x100e24;
@@ -135,7 +144,13 @@ nv50_ram_timing_calc(struct nvkm_fb *pfb, u32 *timing)
}
#undef T
-#define QFX5800NVA0 1
+static void
+nvkm_sddr2_dll_reset(struct nv50_ramseq *hwsq)
+{
+ ram_mask(hwsq, mr[0], 0x100, 0x100);
+ ram_mask(hwsq, mr[0], 0x100, 0x000);
+ ram_nsec(hwsq, 24000);
+}
static int
nv50_ram_calc(struct nvkm_fb *pfb, u32 freq)
@@ -148,7 +163,7 @@ nv50_ram_calc(struct nvkm_fb *pfb, u32 freq)
struct nvkm_ram_data *next;
u8 ver, hdr, cnt, len, strap, size;
u32 data;
- u32 r100da0;
+ u32 r100da0, r004008, unk710, unk714, unk718, unk71c;
int N1, M1, N2, M2, P;
int ret, i;
u32 timing[9];
@@ -220,12 +235,8 @@ nv50_ram_calc(struct nvkm_fb *pfb, u32 freq)
if (ret)
return ret;
- /* XXX: 750MHz seems rather arbitrary */
- if (freq <= 750000) {
- r100da0 = 0x00000010;
- } else {
- r100da0 = 0x00000000;
- }
+ /* Always disable this bit during reclock */
+ ram_mask(hwsq, 0x100200, 0x00000800, 0x00000000);
ram_wait(hwsq, 0x01, 0x00); /* wait for !vblank */
ram_wait(hwsq, 0x01, 0x01); /* wait for vblank */
@@ -234,6 +245,7 @@ nv50_ram_calc(struct nvkm_fb *pfb, u32 freq)
ram_nsec(hwsq, 8000);
ram_setf(hwsq, 0x10, 0x00); /* disable fb */
ram_wait(hwsq, 0x00, 0x01); /* wait for fb disabled */
+ ram_nsec(hwsq, 2000);
ram_wr32(hwsq, 0x1002d4, 0x00000001); /* precharge */
ram_wr32(hwsq, 0x1002d0, 0x00000001); /* refresh */
@@ -253,18 +265,33 @@ nv50_ram_calc(struct nvkm_fb *pfb, u32 freq)
if (ret < 0)
return ret;
+ /* XXX: 750MHz seems rather arbitrary */
+ if (freq <= 750000) {
+ r100da0 = 0x00000010;
+ r004008 = 0x90000000;
+ } else {
+ r100da0 = 0x00000000;
+ r004008 = 0x80000000;
+ }
+
+ r004008 |= (mpll.bias_p << 19) | (P << 22) | (P << 16);
+
ram_mask(hwsq, 0x00c040, 0xc000c000, 0x0000c000);
- ram_mask(hwsq, 0x004008, 0x00000200, 0x00000200);
+ /* XXX: Is rammap_00_16_40 the DLL bit we've seen in GT215? Why does
+ * it have a different rammap bit from DLLoff? */
+ ram_mask(hwsq, 0x004008, 0x00004200, 0x00000200 |
+ next->bios.rammap_00_16_40 << 14);
ram_mask(hwsq, 0x00400c, 0x0000ffff, (N1 << 8) | M1);
- ram_mask(hwsq, 0x004008, 0x81ff0000, 0x80000000 | (mpll.bias_p << 19) |
- (P << 22) | (P << 16));
+ ram_mask(hwsq, 0x004008, 0x91ff0000, r004008);
+ if (nv_device(pfb)->chipset >= 0x96)
+ ram_wr32(hwsq, 0x100da0, r100da0);
+ ram_nsec(hwsq, 64000); /*XXX*/
+ ram_nsec(hwsq, 32000); /*XXX*/
- if (nv_device(pfb)->chipset == 0xa0)
- ram_wr32(hwsq, 0x100da0, r100da0); /*XXX: here?*/
- ram_nsec(hwsq, 96000); /*XXX*/
ram_mask(hwsq, 0x004008, 0x00002200, 0x00002000);
ram_wr32(hwsq, 0x1002dc, 0x00000000); /* disable self-refresh */
+ ram_wr32(hwsq, 0x1002d4, 0x00000001); /* disable self-refresh */
ram_wr32(hwsq, 0x100210, 0x80000000); /* enable auto-refresh */
ram_nsec(hwsq, 12000);
@@ -275,9 +302,10 @@ nv50_ram_calc(struct nvkm_fb *pfb, u32 freq)
ram_mask(hwsq, mr[0], 0x000, 0x000);
break;
case NV_MEM_TYPE_GDDR3:
- ram_mask(hwsq, mr[2], 0x000, 0x000);
+ ram_nuke(hwsq, mr[1]); /* force update */
+ ram_wr32(hwsq, mr[1], ram->base.mr[1]);
ram_nuke(hwsq, mr[0]); /* force update */
- ram_mask(hwsq, mr[0], 0x000, 0x000);
+ ram_wr32(hwsq, mr[0], ram->base.mr[0]);
break;
default:
break;
@@ -293,20 +321,62 @@ nv50_ram_calc(struct nvkm_fb *pfb, u32 freq)
ram_mask(hwsq, timing[4], 0xffffffff, timing[4]);
ram_mask(hwsq, timing[5], 0xffffffff, timing[5]);
-#if QFX5800NVA0
- ram_nuke(hwsq, 0x100e24);
- ram_mask(hwsq, 0x100e24, 0x00000000, 0x00000000);
- ram_nuke(hwsq, 0x100e20);
- ram_mask(hwsq, 0x100e20, 0x00000000, 0x00000000);
-#endif
+ if (!next->bios.ramcfg_00_03_02)
+ ram_mask(hwsq, 0x10021c, 0x00010000, 0x00000000);
+ ram_mask(hwsq, 0x100200, 0x00001000, !next->bios.ramcfg_00_04_02 <<
12);
+
+ /* XXX: A lot of this could be "chipset"/"ram type"
specific stuff */
+ unk710 = ram_rd32(hwsq, 0x100710) & ~0x00000101;
+ unk714 = ram_rd32(hwsq, 0x100714) & ~0xf0000020;
+ unk718 = ram_rd32(hwsq, 0x100718) & ~0x00000100;
+ unk71c = ram_rd32(hwsq, 0x10071c) & ~0x00000100;
+
+ if ( next->bios.ramcfg_00_03_01)
+ unk71c |= 0x00000100;
+ if ( next->bios.ramcfg_00_03_02)
+ unk710 |= 0x00000100;
+ if (!next->bios.ramcfg_00_03_08) {
+ unk710 |= 0x1;
+ unk714 |= 0x20;
+ }
+ if ( next->bios.ramcfg_00_04_04)
+ unk714 |= 0x70000000;
+ if ( next->bios.ramcfg_00_04_20)
+ unk718 |= 0x00000100;
+
+ ram_mask(hwsq, 0x100714, 0xffffffff, unk714);
+ ram_mask(hwsq, 0x10071c, 0xffffffff, unk71c);
+ ram_mask(hwsq, 0x100718, 0xffffffff, unk718);
+ ram_mask(hwsq, 0x100710, 0xffffffff, unk710);
+
+ if (next->bios.rammap_00_16_20) {
+ ram_wr32(hwsq, 0x1005a0, next->bios.ramcfg_00_07 << 16 |
+ next->bios.ramcfg_00_06 << 8 |
+ next->bios.ramcfg_00_05);
+ ram_wr32(hwsq, 0x1005a4, next->bios.ramcfg_00_09 << 8 |
+ next->bios.ramcfg_00_08);
+ ram_mask(hwsq, 0x10053c, 0x00001000, 0x00000000);
+ } else {
+ ram_mask(hwsq, 0x10053c, 0x00001000, 0x00001000);
+ }
+ ram_mask(hwsq, mr[1], 0xffffffff, ram->base.mr[1]);
- ram_mask(hwsq, mr[0], 0x100, 0x100);
- ram_mask(hwsq, mr[0], 0x100, 0x000);
+ /* Reset DLL */
+ if (!next->bios.ramcfg_DLLoff)
+ nvkm_sddr2_dll_reset(hwsq);
ram_setf(hwsq, 0x10, 0x01); /* enable fb */
ram_wait(hwsq, 0x00, 0x00); /* wait for fb enabled */
ram_wr32(hwsq, 0x611200, 0x00003330);
ram_wr32(hwsq, 0x002504, 0x00000000); /* un-block fifo */
+
+ if (next->bios.rammap_00_17_02)
+ ram_mask(hwsq, 0x100200, 0x00000800, 0x00000800);
+ if (!next->bios.rammap_00_16_40)
+ ram_mask(hwsq, 0x004008, 0x00004000, 0x00000000);
+ if (next->bios.ramcfg_00_03_02)
+ ram_mask(hwsq, 0x10021c, 0x00010000, 0x00010000);
+
return 0;
}
@@ -522,12 +592,12 @@ nv50_ram_ctor(struct nvkm_object *parent, struct
nvkm_object *engine,
return ret;
switch (ram->base.type) {
- case NV_MEM_TYPE_DDR2:
case NV_MEM_TYPE_GDDR3:
ram->base.calc = nv50_ram_calc;
ram->base.prog = nv50_ram_prog;
ram->base.tidy = nv50_ram_tidy;
break;
+ case NV_MEM_TYPE_DDR2:
default:
nv_warn(ram, "reclocking of this ram type unsupported\n");
return 0;
@@ -537,10 +607,19 @@ nv50_ram_ctor(struct nvkm_object *parent, struct
nvkm_object *engine,
ram->hwsq.r_0x00c040 = hwsq_reg(0x00c040);
ram->hwsq.r_0x004008 = hwsq_reg(0x004008);
ram->hwsq.r_0x00400c = hwsq_reg(0x00400c);
+ ram->hwsq.r_0x100200 = hwsq_reg(0x100200);
ram->hwsq.r_0x100210 = hwsq_reg(0x100210);
+ ram->hwsq.r_0x10021c = hwsq_reg(0x10021c);
ram->hwsq.r_0x1002d0 = hwsq_reg(0x1002d0);
ram->hwsq.r_0x1002d4 = hwsq_reg(0x1002d4);
ram->hwsq.r_0x1002dc = hwsq_reg(0x1002dc);
+ ram->hwsq.r_0x10053c = hwsq_reg(0x10053c);
+ ram->hwsq.r_0x1005a0 = hwsq_reg(0x1005a0);
+ ram->hwsq.r_0x1005a4 = hwsq_reg(0x1005a4);
+ ram->hwsq.r_0x100710 = hwsq_reg(0x100710);
+ ram->hwsq.r_0x100714 = hwsq_reg(0x100714);
+ ram->hwsq.r_0x100718 = hwsq_reg(0x100718);
+ ram->hwsq.r_0x10071c = hwsq_reg(0x10071c);
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);
--
2.1.0
Roy Spliet
2015-May-24 08:44 UTC
[Nouveau] [PATCH v2 09/10] fb/gddr3: Add a few CL and WR entries observed on GTX260
Signed-off-by: Roy Spliet <rspliet at eclipso.eu>
---
drivers/gpu/drm/nouveau/nvkm/subdev/fb/gddr3.c | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gddr3.c
b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gddr3.c
index 8d759f8a..4465446 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gddr3.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gddr3.c
@@ -42,9 +42,9 @@ ramxlat(const struct ramxlat *xlat, int id)
static const struct ramxlat
ramgddr3_cl_lo[] = {
- { 7, 7 }, { 8, 0 }, { 9, 1 }, { 10, 2 }, { 11, 3 },
+ { 5, 5 }, { 7, 7 }, { 8, 0 }, { 9, 1 }, { 10, 2 }, { 11, 3 }, { 12, 8 },
/* the below are mentioned in some, but not all, gddr3 docs */
- { 12, 4 }, { 13, 5 }, { 14, 6 },
+ { 13, 9 }, { 14, 6 },
/* XXX: Per Samsung docs, are these used? They overlap with Qimonda */
/* { 4, 4 }, { 5, 5 }, { 6, 6 }, { 12, 8 }, { 13, 9 }, { 14, 10 },
* { 15, 11 }, */
@@ -61,9 +61,9 @@ ramgddr3_cl_hi[] = {
static const struct ramxlat
ramgddr3_wr_lo[] = {
{ 5, 2 }, { 7, 4 }, { 8, 5 }, { 9, 6 }, { 10, 7 },
- { 11, 0 },
+ { 11, 0 }, { 13 , 1 },
/* the below are mentioned in some, but not all, gddr3 docs */
- { 4, 1 }, { 6, 3 }, { 12, 1 }, { 13 , 2 },
+ { 4, 1 }, { 6, 3 }, { 12, 1 },
{ -1 }
};
--
2.1.0
Roy Spliet
2015-May-24 08:44 UTC
[Nouveau] [PATCH v2 10/10] clk/nv50: Enable user reclocking for NVA0
Tested on a few cards. Probably works quite well for most, given they should all be GDDR3. Signed-off-by: Roy Spliet <rspliet at eclipso.eu> --- drivers/gpu/drm/nouveau/nvkm/subdev/clk/nv50.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/clk/nv50.c b/drivers/gpu/drm/nouveau/nvkm/subdev/clk/nv50.c index 9b4ffd6..89c5d88 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/clk/nv50.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/clk/nv50.c @@ -509,7 +509,8 @@ nv50_clk_ctor(struct nvkm_object *parent, struct nvkm_object *engine, int ret; ret = nvkm_clk_create(parent, engine, oclass, pclass->domains, - NULL, 0, false, &priv); + NULL, 0, nv_device(parent)->chipset == 0xa0, + &priv); *pobject = nv_object(priv); if (ret) return ret; -- 2.1.0