Parts are re-used even on NVA3, others from GF100 on Signed-off-by: Roy Spliet <nouv...@spliet.org> --- drivers/gpu/drm/nouveau/nvkm/subdev/fb/ram.h | 17 +++ drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgf100.c | 92 +++++++++----- drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgk104.c | 140 +--------------------- drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgt215.c | 61 ++++++++++ 4 files changed, 140 insertions(+), 170 deletions(-)
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ram.h b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ram.h index b60068b..ce8a98e 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ram.h +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ram.h @@ -1,6 +1,7 @@ #ifndef __NVKM_FB_RAM_PRIV_H__ #define __NVKM_FB_RAM_PRIV_H__ #include "priv.h" +#include <subdev/bios/M0209.h> int nvkm_ram_ctor(const struct nvkm_ram_func *, struct nvkm_fb *, enum nvkm_ram_type, u64 size, u32 tags, @@ -24,6 +25,22 @@ int gf100_ram_ctor(const struct nvkm_ram_func *, struct nvkm_fb *, int gf100_ram_get(struct nvkm_ram *, u64, u32, u32, u32, struct nvkm_mem **); void gf100_ram_put(struct nvkm_ram *, struct nvkm_mem **); +/* Training */ +struct gt215_ram_train { + u16 mask; + struct nvbios_M0209S remap; + struct nvbios_M0209S type00; + struct nvbios_M0209S type01; + struct nvbios_M0209S type04; + struct nvbios_M0209S type06; + struct nvbios_M0209S type07; + struct nvbios_M0209S type08; + struct nvbios_M0209S type09; +}; +int gt215_ram_train_type(struct nvkm_ram *ram, int i, u8 ramcfg, + struct gt215_ram_train *train); +int gf100_ram_train_init(struct nvkm_ram *ram); + int gk104_ram_ctor(struct nvkm_fb *, struct nvkm_ram **, u32); int gk104_ram_init(struct nvkm_ram *ram); diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgf100.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgf100.c index b4fe3bb..38a7e2b 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgf100.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgf100.c @@ -28,6 +28,7 @@ #include <core/option.h> #include <subdev/bios.h> #include <subdev/bios/pll.h> +#include <subdev/bios/M0205.h> #include <subdev/bios/rammap.h> #include <subdev/bios/timing.h> #include <subdev/clk.h> @@ -549,45 +550,74 @@ gf100_ram_get(struct nvkm_ram *ram, u64 size, u32 align, u32 ncmin, } static int -gf100_ram_init(struct nvkm_ram *base) +gf100_ram_train_init_0(struct nvkm_ram *ram, struct gt215_ram_train *train) { - static const u8 train0[] = { - 0x00, 0xff, 0x55, 0xaa, 0x33, 0xcc, - 0x00, 0xff, 0xff, 0x00, 0xff, 0x00, - }; - static const u32 train1[] = { - 0x00000000, 0xffffffff, - 0x55555555, 0xaaaaaaaa, - 0x33333333, 0xcccccccc, - 0xf0f0f0f0, 0x0f0f0f0f, - 0x00ff00ff, 0xff00ff00, - 0x0000ffff, 0xffff0000, - }; - struct gf100_ram *ram = gf100_ram(base); - struct nvkm_device *device = ram->base.fb->subdev.device; - int i; + struct nvkm_subdev *subdev = &ram->fb->subdev; + struct nvkm_device *device = subdev->device; + int i, j; - switch (ram->base.type) { + if ((train->mask & 0x03d3) != 0x03d3) { + nvkm_warn(subdev, "missing link training data\n"); + return -EINVAL; + } + + for (i = 0; i < 0x30; i++) { + for (j = 0; j < 8; j += 4) { + nvkm_wr32(device, 0x10f968 + j, 0x00000000 | (i << 8)); + nvkm_wr32(device, 0x10f920 + j, 0x00000000 | + train->type08.data[i] << 4 | + train->type06.data[i]); + nvkm_wr32(device, 0x10f918 + j, train->type00.data[i]); + nvkm_wr32(device, 0x10f920 + j, 0x00000100 | + train->type09.data[i] << 4 | + train->type07.data[i]); + nvkm_wr32(device, 0x10f918 + j, train->type01.data[i]); + } + } + + for (j = 0; j < 8; j += 4) { + for (i = 0; i < 0x100; i++) { + nvkm_wr32(device, 0x10f968 + j, i); + nvkm_wr32(device, 0x10f900 + j, train->type04.data[i]); + } + } + + return 0; +} + +int +gf100_ram_train_init(struct nvkm_ram *ram) +{ + u8 ramcfg = nvbios_ramcfg_index(&ram->fb->subdev); + struct gt215_ram_train *train; + int ret, i; + + if (!(train = kzalloc(sizeof(*train), GFP_KERNEL))) + return -ENOMEM; + + for (i = 0; i < 0x100; i++) { + ret = gt215_ram_train_type(ram, i, ramcfg, train); + if (ret && ret != -ENOENT) + break; + } + + switch (ram->type) { case NVKM_RAM_TYPE_GDDR5: + ret = gf100_ram_train_init_0(ram, train); break; default: - return 0; + ret = 0; + break; } - /* prepare for ddr link training, and load training patterns */ - for (i = 0; i < 0x30; i++) { - nvkm_wr32(device, 0x10f968, 0x00000000 | (i << 8)); - nvkm_wr32(device, 0x10f96c, 0x00000000 | (i << 8)); - nvkm_wr32(device, 0x10f920, 0x00000100 | train0[i % 12]); - nvkm_wr32(device, 0x10f924, 0x00000100 | train0[i % 12]); - nvkm_wr32(device, 0x10f918, train1[i % 12]); - nvkm_wr32(device, 0x10f91c, train1[i % 12]); - nvkm_wr32(device, 0x10f920, 0x00000000 | train0[i % 12]); - nvkm_wr32(device, 0x10f924, 0x00000000 | train0[i % 12]); - nvkm_wr32(device, 0x10f918, train1[i % 12]); - nvkm_wr32(device, 0x10f91c, train1[i % 12]); - } + kfree(train); + return ret; +} +static int +gf100_ram_init(struct nvkm_ram *base) +{ + /* XXX: Don't hook up yet for bisectability */ return 0; } diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgk104.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgk104.c index 7904fa4..8bf4638 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgk104.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgk104.c @@ -1257,144 +1257,6 @@ gk104_ram_tidy(struct nvkm_ram *base) ram_exec(&ram->fuc, false); } -struct gk104_ram_train { - u16 mask; - struct nvbios_M0209S remap; - struct nvbios_M0209S type00; - struct nvbios_M0209S type01; - struct nvbios_M0209S type04; - struct nvbios_M0209S type06; - struct nvbios_M0209S type07; - struct nvbios_M0209S type08; - struct nvbios_M0209S type09; -}; - -static int -gk104_ram_train_type(struct nvkm_ram *ram, int i, u8 ramcfg, - struct gk104_ram_train *train) -{ - struct nvkm_bios *bios = ram->fb->subdev.device->bios; - struct nvbios_M0205E M0205E; - struct nvbios_M0205S M0205S; - struct nvbios_M0209E M0209E; - struct nvbios_M0209S *remap = &train->remap; - struct nvbios_M0209S *value; - u8 ver, hdr, cnt, len; - u32 data; - - /* determine type of data for this index */ - if (!(data = nvbios_M0205Ep(bios, i, &ver, &hdr, &cnt, &len, &M0205E))) - return -ENOENT; - - switch (M0205E.type) { - case 0x00: value = &train->type00; break; - case 0x01: value = &train->type01; break; - case 0x04: value = &train->type04; break; - case 0x06: value = &train->type06; break; - case 0x07: value = &train->type07; break; - case 0x08: value = &train->type08; break; - case 0x09: value = &train->type09; break; - default: - return 0; - } - - /* training data index determined by ramcfg strap */ - if (!(data = nvbios_M0205Sp(bios, i, ramcfg, &ver, &hdr, &M0205S))) - return -EINVAL; - i = M0205S.data; - - /* training data format information */ - if (!(data = nvbios_M0209Ep(bios, i, &ver, &hdr, &cnt, &len, &M0209E))) - return -EINVAL; - - /* ... and the raw data */ - if (!(data = nvbios_M0209Sp(bios, i, 0, &ver, &hdr, value))) - return -EINVAL; - - if (M0209E.v02_07 == 2) { - /* of course! why wouldn't we have a pointer to another entry - * in the same table, and use the first one as an array of - * remap indices... - */ - if (!(data = nvbios_M0209Sp(bios, M0209E.v03, 0, &ver, &hdr, - remap))) - return -EINVAL; - - for (i = 0; i < ARRAY_SIZE(value->data); i++) - value->data[i] = remap->data[value->data[i]]; - } else - if (M0209E.v02_07 != 1) - return -EINVAL; - - train->mask |= 1 << M0205E.type; - return 0; -} - -static int -gk104_ram_train_init_0(struct nvkm_ram *ram, struct gk104_ram_train *train) -{ - struct nvkm_subdev *subdev = &ram->fb->subdev; - struct nvkm_device *device = subdev->device; - int i, j; - - if ((train->mask & 0x03d3) != 0x03d3) { - nvkm_warn(subdev, "missing link training data\n"); - return -EINVAL; - } - - for (i = 0; i < 0x30; i++) { - for (j = 0; j < 8; j += 4) { - nvkm_wr32(device, 0x10f968 + j, 0x00000000 | (i << 8)); - nvkm_wr32(device, 0x10f920 + j, 0x00000000 | - train->type08.data[i] << 4 | - train->type06.data[i]); - nvkm_wr32(device, 0x10f918 + j, train->type00.data[i]); - nvkm_wr32(device, 0x10f920 + j, 0x00000100 | - train->type09.data[i] << 4 | - train->type07.data[i]); - nvkm_wr32(device, 0x10f918 + j, train->type01.data[i]); - } - } - - for (j = 0; j < 8; j += 4) { - for (i = 0; i < 0x100; i++) { - nvkm_wr32(device, 0x10f968 + j, i); - nvkm_wr32(device, 0x10f900 + j, train->type04.data[i]); - } - } - - return 0; -} - -static int -gk104_ram_train_init(struct nvkm_ram *ram) -{ - u8 ramcfg = nvbios_ramcfg_index(&ram->fb->subdev); - struct gk104_ram_train *train; - int ret, i; - - if (!(train = kzalloc(sizeof(*train), GFP_KERNEL))) - return -ENOMEM; - - for (i = 0; i < 0x100; i++) { - ret = gk104_ram_train_type(ram, i, ramcfg, train); - if (ret && ret != -ENOENT) - break; - } - - switch (ram->type) { - case NVKM_RAM_TYPE_GDDR5: - ret = gk104_ram_train_init_0(ram, train); - break; - default: - ret = 0; - break; - } - - kfree(train); - return ret; -} - int gk104_ram_init(struct nvkm_ram *ram) { @@ -1439,7 +1301,7 @@ gk104_ram_init(struct nvkm_ram *ram) nvkm_wr32(device, 0x10ecc0, 0xffffffff); nvkm_mask(device, 0x10f160, 0x00000010, 0x00000010); - return gk104_ram_train_init(ram); + return gf100_ram_train_init(ram); } static int diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgt215.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgt215.c index 8454899..6abd0e3 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgt215.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgt215.c @@ -267,6 +267,67 @@ gt215_link_train(struct gt215_ram *ram) return ret; } +int +gt215_ram_train_type(struct nvkm_ram *ram, int i, u8 ramcfg, + struct gt215_ram_train *train) +{ + struct nvkm_bios *bios = ram->fb->subdev.device->bios; + struct nvbios_M0205E M0205E; + struct nvbios_M0205S M0205S; + struct nvbios_M0209E M0209E; + struct nvbios_M0209S *remap = &train->remap; + struct nvbios_M0209S *value; + u8 ver, hdr, cnt, len; + u32 data; + + /* determine type of data for this index */ + if (!(data = nvbios_M0205Ep(bios, i, &ver, &hdr, &cnt, &len, &M0205E))) + return -ENOENT; + + switch (M0205E.type) { + case 0x00: value = &train->type00; break; + case 0x01: value = &train->type01; break; + case 0x04: value = &train->type04; break; + case 0x06: value = &train->type06; break; + case 0x07: value = &train->type07; break; + case 0x08: value = &train->type08; break; + case 0x09: value = &train->type09; break; + default: + return 0; + } + + /* training data index determined by ramcfg strap */ + if (!(data = nvbios_M0205Sp(bios, i, ramcfg, &ver, &hdr, &M0205S))) + return -EINVAL; + i = M0205S.data; + + /* training data format information */ + if (!(data = nvbios_M0209Ep(bios, i, &ver, &hdr, &cnt, &len, &M0209E))) + return -EINVAL; + + /* ... and the raw data */ + if (!(data = nvbios_M0209Sp(bios, i, 0, &ver, &hdr, value))) + return -EINVAL; + + if (M0209E.v02_07 == 2) { + /* of course! why wouldn't we have a pointer to another entry + * in the same table, and use the first one as an array of + * remap indices... + */ + if (!(data = nvbios_M0209Sp(bios, M0209E.v03, 0, &ver, &hdr, + remap))) + return -EINVAL; + + for (i = 0; i < ARRAY_SIZE(value->data); i++) + value->data[i] = remap->data[value->data[i]]; + } else + if (M0209E.v02_07 != 1) + return -EINVAL; + + train->mask |= 1 << M0205E.type; + return 0; +} + static int gt215_link_train_init(struct gt215_ram *ram) { -- 2.9.3 _______________________________________________ Nouveau mailing list Nouveau@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/nouveau