diff options
Diffstat (limited to 'drivers/gpu/drm/nouveau/nvkm/subdev/fb')
-rw-r--r-- | drivers/gpu/drm/nouveau/nvkm/subdev/fb/Kbuild | 3 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nvkm/subdev/fb/gf108.c | 42 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nvkm/subdev/fb/gm200.c | 2 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nvkm/subdev/fb/ram.h | 33 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgf100.c | 148 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgf108.c | 62 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgk104.c | 70 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgm107.c | 25 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgm200.c | 68 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgp100.c | 68 |
10 files changed, 375 insertions, 146 deletions
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/Kbuild b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/Kbuild index 63566ba12fbb..1c5e5ba487a8 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/Kbuild +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/Kbuild @@ -20,6 +20,7 @@ nvkm-y += nvkm/subdev/fb/gt215.o nvkm-y += nvkm/subdev/fb/mcp77.o nvkm-y += nvkm/subdev/fb/mcp89.o nvkm-y += nvkm/subdev/fb/gf100.o +nvkm-y += nvkm/subdev/fb/gf108.o nvkm-y += nvkm/subdev/fb/gk104.o nvkm-y += nvkm/subdev/fb/gk20a.o nvkm-y += nvkm/subdev/fb/gm107.o @@ -42,8 +43,10 @@ nvkm-y += nvkm/subdev/fb/ramnv50.o nvkm-y += nvkm/subdev/fb/ramgt215.o nvkm-y += nvkm/subdev/fb/rammcp77.o nvkm-y += nvkm/subdev/fb/ramgf100.o +nvkm-y += nvkm/subdev/fb/ramgf108.o nvkm-y += nvkm/subdev/fb/ramgk104.o nvkm-y += nvkm/subdev/fb/ramgm107.o +nvkm-y += nvkm/subdev/fb/ramgm200.o nvkm-y += nvkm/subdev/fb/ramgp100.o nvkm-y += nvkm/subdev/fb/sddr2.o nvkm-y += nvkm/subdev/fb/sddr3.o diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gf108.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gf108.c new file mode 100644 index 000000000000..56af84aa333b --- /dev/null +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gf108.c @@ -0,0 +1,42 @@ +/* + * Copyright 2017 Red Hat Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: Ben Skeggs <bskeggs@redhat.com> + */ +#include "gf100.h" +#include "ram.h" + +static const struct nvkm_fb_func +gf108_fb = { + .dtor = gf100_fb_dtor, + .oneinit = gf100_fb_oneinit, + .init = gf100_fb_init, + .init_page = gf100_fb_init_page, + .intr = gf100_fb_intr, + .ram_new = gf108_ram_new, + .memtype_valid = gf100_fb_memtype_valid, +}; + +int +gf108_fb_new(struct nvkm_device *device, int index, struct nvkm_fb **pfb) +{ + return gf100_fb_new_(&gf108_fb, device, index, pfb); +} diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gm200.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gm200.c index fe5886013ac0..d83da5ddbc1e 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gm200.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gm200.c @@ -68,7 +68,7 @@ gm200_fb = { .init = gm200_fb_init, .init_page = gm200_fb_init_page, .intr = gf100_fb_intr, - .ram_new = gm107_ram_new, + .ram_new = gm200_ram_new, .memtype_valid = gf100_fb_memtype_valid, }; diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ram.h b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ram.h index b60068b7d8f9..fac7e73c3ddf 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ram.h +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ram.h @@ -19,13 +19,38 @@ int nv50_ram_get(struct nvkm_ram *, u64, u32, u32, u32, struct nvkm_mem **); void nv50_ram_put(struct nvkm_ram *, struct nvkm_mem **); void __nv50_ram_put(struct nvkm_ram *, struct nvkm_mem *); +int gf100_ram_new_(const struct nvkm_ram_func *, struct nvkm_fb *, + struct nvkm_ram **); int gf100_ram_ctor(const struct nvkm_ram_func *, struct nvkm_fb *, - u32, struct nvkm_ram *); + struct nvkm_ram *); +u32 gf100_ram_probe_fbp(const struct nvkm_ram_func *, + struct nvkm_device *, int, int *); +u32 gf100_ram_probe_fbp_amount(const struct nvkm_ram_func *, u32, + struct nvkm_device *, int, int *); +u32 gf100_ram_probe_fbpa_amount(struct nvkm_device *, int); int gf100_ram_get(struct nvkm_ram *, u64, u32, u32, u32, struct nvkm_mem **); void gf100_ram_put(struct nvkm_ram *, struct nvkm_mem **); +int gf100_ram_init(struct nvkm_ram *); +int gf100_ram_calc(struct nvkm_ram *, u32); +int gf100_ram_prog(struct nvkm_ram *); +void gf100_ram_tidy(struct nvkm_ram *); + +u32 gf108_ram_probe_fbp_amount(const struct nvkm_ram_func *, u32, + struct nvkm_device *, int, int *); + +int gk104_ram_new_(const struct nvkm_ram_func *, struct nvkm_fb *, + struct nvkm_ram **); +void *gk104_ram_dtor(struct nvkm_ram *); +int gk104_ram_init(struct nvkm_ram *); +int gk104_ram_calc(struct nvkm_ram *, u32); +int gk104_ram_prog(struct nvkm_ram *); +void gk104_ram_tidy(struct nvkm_ram *); + +u32 gm107_ram_probe_fbp(const struct nvkm_ram_func *, + struct nvkm_device *, int, int *); -int gk104_ram_ctor(struct nvkm_fb *, struct nvkm_ram **, u32); -int gk104_ram_init(struct nvkm_ram *ram); +u32 gm200_ram_probe_fbp_amount(const struct nvkm_ram_func *, u32, + struct nvkm_device *, int, int *); /* RAM type-specific MR calculation routines */ int nvkm_sddr2_calc(struct nvkm_ram *); @@ -46,7 +71,9 @@ int nv50_ram_new(struct nvkm_fb *, struct nvkm_ram **); int gt215_ram_new(struct nvkm_fb *, struct nvkm_ram **); int mcp77_ram_new(struct nvkm_fb *, struct nvkm_ram **); int gf100_ram_new(struct nvkm_fb *, struct nvkm_ram **); +int gf108_ram_new(struct nvkm_fb *, struct nvkm_ram **); int gk104_ram_new(struct nvkm_fb *, struct nvkm_ram **); int gm107_ram_new(struct nvkm_fb *, struct nvkm_ram **); +int gm200_ram_new(struct nvkm_fb *, struct nvkm_ram **); int gp100_ram_new(struct nvkm_fb *, struct nvkm_ram **); #endif diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgf100.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgf100.c index 6758da93a3a1..53c32fc694e9 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgf100.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgf100.c @@ -124,7 +124,7 @@ gf100_ram_train(struct gf100_ramfuc *fuc, u32 magic) } } -static int +int gf100_ram_calc(struct nvkm_ram *base, u32 freq) { struct gf100_ram *ram = gf100_ram(base); @@ -404,7 +404,7 @@ gf100_ram_calc(struct nvkm_ram *base, u32 freq) return 0; } -static int +int gf100_ram_prog(struct nvkm_ram *base) { struct gf100_ram *ram = gf100_ram(base); @@ -413,7 +413,7 @@ gf100_ram_prog(struct nvkm_ram *base) return 0; } -static void +void gf100_ram_tidy(struct nvkm_ram *base) { struct gf100_ram *ram = gf100_ram(base); @@ -500,7 +500,7 @@ gf100_ram_get(struct nvkm_ram *ram, u64 size, u32 align, u32 ncmin, return 0; } -static int +int gf100_ram_init(struct nvkm_ram *base) { static const u8 train0[] = { @@ -543,77 +543,96 @@ gf100_ram_init(struct nvkm_ram *base) return 0; } -static const struct nvkm_ram_func -gf100_ram_func = { - .init = gf100_ram_init, - .get = gf100_ram_get, - .put = gf100_ram_put, - .calc = gf100_ram_calc, - .prog = gf100_ram_prog, - .tidy = gf100_ram_tidy, -}; +u32 +gf100_ram_probe_fbpa_amount(struct nvkm_device *device, int fbpa) +{ + return nvkm_rd32(device, 0x11020c + (fbpa * 0x1000)); +} + +u32 +gf100_ram_probe_fbp_amount(const struct nvkm_ram_func *func, u32 fbpao, + struct nvkm_device *device, int fbp, int *pltcs) +{ + if (!(fbpao & BIT(fbp))) { + *pltcs = 1; + return func->probe_fbpa_amount(device, fbp); + } + return 0; +} + +u32 +gf100_ram_probe_fbp(const struct nvkm_ram_func *func, + struct nvkm_device *device, int fbp, int *pltcs) +{ + u32 fbpao = nvkm_rd32(device, 0x022554); + return func->probe_fbp_amount(func, fbpao, device, fbp, pltcs); +} int gf100_ram_ctor(const struct nvkm_ram_func *func, struct nvkm_fb *fb, - u32 maskaddr, struct nvkm_ram *ram) + struct nvkm_ram *ram) { struct nvkm_subdev *subdev = &fb->subdev; struct nvkm_device *device = subdev->device; struct nvkm_bios *bios = device->bios; const u32 rsvd_head = ( 256 * 1024); /* vga memory */ const u32 rsvd_tail = (1024 * 1024); /* vbios etc */ - u32 parts = nvkm_rd32(device, 0x022438); - u32 pmask = nvkm_rd32(device, maskaddr); - u64 bsize = (u64)nvkm_rd32(device, 0x10f20c) << 20; - u64 psize, size = 0; enum nvkm_ram_type type = nvkm_fb_bios_memtype(bios); - bool uniform = true; - int ret, i; - - nvkm_debug(subdev, "100800: %08x\n", nvkm_rd32(device, 0x100800)); - nvkm_debug(subdev, "parts %08x mask %08x\n", parts, pmask); - - /* read amount of vram attached to each memory controller */ - for (i = 0; i < parts; i++) { - if (pmask & (1 << i)) - continue; - - psize = (u64)nvkm_rd32(device, 0x11020c + (i * 0x1000)) << 20; - if (psize != bsize) { - if (psize < bsize) - bsize = psize; - uniform = false; + u32 fbps = nvkm_rd32(device, 0x022438); + u64 total = 0, lcomm = ~0, lower, ubase, usize; + int ret, fbp, ltcs, ltcn = 0; + + nvkm_debug(subdev, "%d FBP(s)\n", fbps); + for (fbp = 0; fbp < fbps; fbp++) { + u32 size = func->probe_fbp(func, device, fbp, <cs); + if (size) { + nvkm_debug(subdev, "FBP %d: %4d MiB, %d LTC(s)\n", + fbp, size, ltcs); + lcomm = min(lcomm, (u64)(size / ltcs) << 20); + total += size << 20; + ltcn += ltcs; + } else { + nvkm_debug(subdev, "FBP %d: disabled\n", fbp); } - - nvkm_debug(subdev, "%d: %d MiB\n", i, (u32)(psize >> 20)); - size += psize; } - ret = nvkm_ram_ctor(func, fb, type, size, 0, ram); + lower = lcomm * ltcn; + ubase = lcomm + func->upper; + usize = total - lower; + + nvkm_debug(subdev, "Lower: %4lld MiB @ %010llx\n", lower >> 20, 0ULL); + nvkm_debug(subdev, "Upper: %4lld MiB @ %010llx\n", usize >> 20, ubase); + nvkm_debug(subdev, "Total: %4lld MiB\n", total >> 20); + + ret = nvkm_ram_ctor(func, fb, type, total, 0, ram); if (ret) return ret; nvkm_mm_fini(&ram->vram); - /* if all controllers have the same amount attached, there's no holes */ - if (uniform) { + /* Some GPUs are in what's known as a "mixed memory" configuration. + * + * This is either where some FBPs have more memory than the others, + * or where LTCs have been disabled on a FBP. + */ + if (lower != total) { + /* The common memory amount is addressed normally. */ ret = nvkm_mm_init(&ram->vram, rsvd_head >> NVKM_RAM_MM_SHIFT, - (size - rsvd_head - rsvd_tail) >> - NVKM_RAM_MM_SHIFT, 1); + (lower - rsvd_head) >> NVKM_RAM_MM_SHIFT, 1); if (ret) return ret; - } else { - /* otherwise, address lowest common amount from 0GiB */ - ret = nvkm_mm_init(&ram->vram, rsvd_head >> NVKM_RAM_MM_SHIFT, - ((bsize * parts) - rsvd_head) >> - NVKM_RAM_MM_SHIFT, 1); + + /* And the rest is much higher in the physical address + * space, and may not be usable for certain operations. + */ + ret = nvkm_mm_init(&ram->vram, ubase >> NVKM_RAM_MM_SHIFT, + (usize - rsvd_tail) >> NVKM_RAM_MM_SHIFT, 1); if (ret) return ret; - - /* and the rest starting from (8GiB + common_size) */ - ret = nvkm_mm_init(&ram->vram, (0x0200000000ULL + bsize) >> - NVKM_RAM_MM_SHIFT, - (size - (bsize * parts) - rsvd_tail) >> + } else { + /* GPUs without mixed-memory are a lot nicer... */ + ret = nvkm_mm_init(&ram->vram, rsvd_head >> NVKM_RAM_MM_SHIFT, + (total - rsvd_head - rsvd_tail) >> NVKM_RAM_MM_SHIFT, 1); if (ret) return ret; @@ -624,7 +643,8 @@ gf100_ram_ctor(const struct nvkm_ram_func *func, struct nvkm_fb *fb, } int -gf100_ram_new(struct nvkm_fb *fb, struct nvkm_ram **pram) +gf100_ram_new_(const struct nvkm_ram_func *func, + struct nvkm_fb *fb, struct nvkm_ram **pram) { struct nvkm_subdev *subdev = &fb->subdev; struct nvkm_bios *bios = subdev->device->bios; @@ -635,7 +655,7 @@ gf100_ram_new(struct nvkm_fb *fb, struct nvkm_ram **pram) return -ENOMEM; *pram = &ram->base; - ret = gf100_ram_ctor(&gf100_ram_func, fb, 0x022554, &ram->base); + ret = gf100_ram_ctor(func, fb, &ram->base); if (ret) return ret; @@ -711,3 +731,23 @@ gf100_ram_new(struct nvkm_fb *fb, struct nvkm_ram **pram) ram->fuc.r_0x13d8f4 = ramfuc_reg(0x13d8f4); return 0; } + +static const struct nvkm_ram_func +gf100_ram = { + .upper = 0x0200000000, + .probe_fbp = gf100_ram_probe_fbp, + .probe_fbp_amount = gf100_ram_probe_fbp_amount, + .probe_fbpa_amount = gf100_ram_probe_fbpa_amount, + .init = gf100_ram_init, + .get = gf100_ram_get, + .put = gf100_ram_put, + .calc = gf100_ram_calc, + .prog = gf100_ram_prog, + .tidy = gf100_ram_tidy, +}; + +int +gf100_ram_new(struct nvkm_fb *fb, struct nvkm_ram **pram) +{ + return gf100_ram_new_(&gf100_ram, fb, pram); +} diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgf108.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgf108.c new file mode 100644 index 000000000000..985ec64cf369 --- /dev/null +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgf108.c @@ -0,0 +1,62 @@ +/* + * Copyright 2017 Red Hat Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: Ben Skeggs <bskeggs@redhat.com> + */ +#include "ram.h" + +u32 +gf108_ram_probe_fbp_amount(const struct nvkm_ram_func *func, u32 fbpao, + struct nvkm_device *device, int fbp, int *pltcs) +{ + u32 fbpt = nvkm_rd32(device, 0x022438); + u32 fbpat = nvkm_rd32(device, 0x02243c); + u32 fbpas = fbpat / fbpt; + u32 fbpa = fbp * fbpas; + u32 size = 0; + while (fbpas--) { + if (!(fbpao & BIT(fbpa))) + size += func->probe_fbpa_amount(device, fbpa); + fbpa++; + } + *pltcs = 1; + return size; +} + +static const struct nvkm_ram_func +gf108_ram = { + .upper = 0x0200000000, + .probe_fbp = gf100_ram_probe_fbp, + .probe_fbp_amount = gf108_ram_probe_fbp_amount, + .probe_fbpa_amount = gf100_ram_probe_fbpa_amount, + .init = gf100_ram_init, + .get = gf100_ram_get, + .put = gf100_ram_put, + .calc = gf100_ram_calc, + .prog = gf100_ram_prog, + .tidy = gf100_ram_tidy, +}; + +int +gf108_ram_new(struct nvkm_fb *fb, struct nvkm_ram **pram) +{ + return gf100_ram_new_(&gf108_ram, fb, pram); +} diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgk104.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgk104.c index fb8a1239743d..f6c00791722c 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgk104.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgk104.c @@ -1108,7 +1108,7 @@ gk104_ram_calc_xits(struct gk104_ram *ram, struct nvkm_ram_data *next) return ret; } -static int +int gk104_ram_calc(struct nvkm_ram *base, u32 freq) { struct gk104_ram *ram = gk104_ram(base); @@ -1227,7 +1227,7 @@ gk104_ram_prog_0(struct gk104_ram *ram, u32 freq) nvkm_mask(device, 0x10f444, mask, data); } -static int +int gk104_ram_prog(struct nvkm_ram *base) { struct gk104_ram *ram = gk104_ram(base); @@ -1247,7 +1247,7 @@ gk104_ram_prog(struct nvkm_ram *base) return (ram->base.next == &ram->base.xition); } -static void +void gk104_ram_tidy(struct nvkm_ram *base) { struct gk104_ram *ram = gk104_ram(base); @@ -1509,7 +1509,7 @@ done: return ret; } -static void * +void * gk104_ram_dtor(struct nvkm_ram *base) { struct gk104_ram *ram = gk104_ram(base); @@ -1522,31 +1522,14 @@ gk104_ram_dtor(struct nvkm_ram *base) return ram; } -static const struct nvkm_ram_func -gk104_ram_func = { - .dtor = gk104_ram_dtor, - .init = gk104_ram_init, - .get = gf100_ram_get, - .put = gf100_ram_put, - .calc = gk104_ram_calc, - .prog = gk104_ram_prog, - .tidy = gk104_ram_tidy, -}; - int -gk104_ram_new(struct nvkm_fb *fb, struct nvkm_ram **pram) -{ - return gk104_ram_ctor(fb, pram, 0x022554); -} - -int -gk104_ram_ctor(struct nvkm_fb *fb, struct nvkm_ram **pram, u32 maskaddr) +gk104_ram_new_(const struct nvkm_ram_func *func, struct nvkm_fb *fb, + struct nvkm_ram **pram) { struct nvkm_subdev *subdev = &fb->subdev; struct nvkm_device *device = subdev->device; struct nvkm_bios *bios = device->bios; - struct nvkm_gpio *gpio = device->gpio; - struct dcb_gpio_func func; + struct dcb_gpio_func gpio; struct gk104_ram *ram; int ret, i; u8 ramcfg = nvbios_ramcfg_index(subdev); @@ -1556,7 +1539,7 @@ gk104_ram_ctor(struct nvkm_fb *fb, struct nvkm_ram **pram, u32 maskaddr) return -ENOMEM; *pram = &ram->base; - ret = gf100_ram_ctor(&gk104_ram_func, fb, maskaddr, &ram->base); + ret = gf100_ram_ctor(func, fb, &ram->base); if (ret) return ret; @@ -1614,18 +1597,18 @@ gk104_ram_ctor(struct nvkm_fb *fb, struct nvkm_ram **pram, u32 maskaddr) } /* lookup memory voltage gpios */ - ret = nvkm_gpio_find(gpio, 0, 0x18, DCB_GPIO_UNUSED, &func); + ret = nvkm_gpio_find(device->gpio, 0, 0x18, DCB_GPIO_UNUSED, &gpio); if (ret == 0) { - ram->fuc.r_gpioMV = ramfuc_reg(0x00d610 + (func.line * 0x04)); - ram->fuc.r_funcMV[0] = (func.log[0] ^ 2) << 12; - ram->fuc.r_funcMV[1] = (func.log[1] ^ 2) << 12; + ram->fuc.r_gpioMV = ramfuc_reg(0x00d610 + (gpio.line * 0x04)); + ram->fuc.r_funcMV[0] = (gpio.log[0] ^ 2) << 12; + ram->fuc.r_funcMV[1] = (gpio.log[1] ^ 2) << 12; } - ret = nvkm_gpio_find(gpio, 0, 0x2e, DCB_GPIO_UNUSED, &func); + ret = nvkm_gpio_find(device->gpio, 0, 0x2e, DCB_GPIO_UNUSED, &gpio); if (ret == 0) { - ram->fuc.r_gpio2E = ramfuc_reg(0x00d610 + (func.line * 0x04)); - ram->fuc.r_func2E[0] = (func.log[0] ^ 2) << 12; - ram->fuc.r_func2E[1] = (func.log[1] ^ 2) << 12; + ram->fuc.r_gpio2E = ramfuc_reg(0x00d610 + (gpio.line * 0x04)); + ram->fuc.r_func2E[0] = (gpio.log[0] ^ 2) << 12; + ram->fuc.r_func2E[1] = (gpio.log[1] ^ 2) << 12; } ram->fuc.r_gpiotrig = ramfuc_reg(0x00d604); @@ -1717,3 +1700,24 @@ gk104_ram_ctor(struct nvkm_fb *fb, struct nvkm_ram **pram, u32 maskaddr) ram->fuc.r_0x100750 = ramfuc_reg(0x100750); return 0; } + +static const struct nvkm_ram_func +gk104_ram = { + .upper = 0x0200000000, + .probe_fbp = gf100_ram_probe_fbp, + .probe_fbp_amount = gf108_ram_probe_fbp_amount, + .probe_fbpa_amount = gf100_ram_probe_fbpa_amount, + .dtor = gk104_ram_dtor, + .init = gk104_ram_init, + .get = gf100_ram_get, + .put = gf100_ram_put, + .calc = gk104_ram_calc, + .prog = gk104_ram_prog, + .tidy = gk104_ram_tidy, +}; + +int +gk104_ram_new(struct nvkm_fb *fb, struct nvkm_ram **pram) +{ + return gk104_ram_new_(&gk104_ram, fb, pram); +} diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgm107.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgm107.c index ac862d1d77bd..3f0b56347291 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgm107.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgm107.c @@ -23,8 +23,31 @@ */ #include "ram.h" +u32 +gm107_ram_probe_fbp(const struct nvkm_ram_func *func, + struct nvkm_device *device, int fbp, int *pltcs) +{ + u32 fbpao = nvkm_rd32(device, 0x021c14); + return func->probe_fbp_amount(func, fbpao, device, fbp, pltcs); +} + +static const struct nvkm_ram_func +gm107_ram = { + .upper = 0x1000000000, + .probe_fbp = gm107_ram_probe_fbp, + .probe_fbp_amount = gf108_ram_probe_fbp_amount, + .probe_fbpa_amount = gf100_ram_probe_fbpa_amount, + .dtor = gk104_ram_dtor, + .init = gk104_ram_init, + .get = gf100_ram_get, + .put = gf100_ram_put, + .calc = gk104_ram_calc, + .prog = gk104_ram_prog, + .tidy = gk104_ram_tidy, +}; + int gm107_ram_new(struct nvkm_fb *fb, struct nvkm_ram **pram) { - return gk104_ram_ctor(fb, pram, 0x021c14); + return gk104_ram_new_(&gm107_ram, fb, pram); } diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgm200.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgm200.c new file mode 100644 index 000000000000..fd8facf90476 --- /dev/null +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgm200.c @@ -0,0 +1,68 @@ +/* + * Copyright 2017 Red Hat Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: Ben Skeggs <bskeggs@redhat.com> + */ +#include "ram.h" + +u32 +gm200_ram_probe_fbp_amount(const struct nvkm_ram_func *func, u32 fbpao, + struct nvkm_device *device, int fbp, int *pltcs) +{ + u32 ltcs = nvkm_rd32(device, 0x022450); + u32 fbpas = nvkm_rd32(device, 0x022458); + u32 fbpa = fbp * fbpas; + u32 size = 0; + if (!(nvkm_rd32(device, 0x021d38) & BIT(fbp))) { + u32 ltco = nvkm_rd32(device, 0x021d70 + (fbp * 4)); + u32 ltcm = ~ltco & ((1 << ltcs) - 1); + + while (fbpas--) { + if (!(fbpao & (1 << fbpa))) + size += func->probe_fbpa_amount(device, fbpa); + fbpa++; + } + + *pltcs = hweight32(ltcm); + } + return size; +} + +static const struct nvkm_ram_func +gm200_ram = { + .upper = 0x1000000000, + .probe_fbp = gm107_ram_probe_fbp, + .probe_fbp_amount = gm200_ram_probe_fbp_amount, + .probe_fbpa_amount = gf100_ram_probe_fbpa_amount, + .dtor = gk104_ram_dtor, + .init = gk104_ram_init, + .get = gf100_ram_get, + .put = gf100_ram_put, + .calc = gk104_ram_calc, + .prog = gk104_ram_prog, + .tidy = gk104_ram_tidy, +}; + +int +gm200_ram_new(struct nvkm_fb *fb, struct nvkm_ram **pram) +{ + return gk104_ram_new_(&gm200_ram, fb, pram); +} diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgp100.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgp100.c index 405faabe8dcd..cac70047ad5a 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgp100.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgp100.c @@ -76,8 +76,18 @@ gp100_ram_init(struct nvkm_ram *ram) return 0; } +static u32 +gp100_ram_probe_fbpa(struct nvkm_device *device, int fbpa) +{ + return nvkm_rd32(device, 0x90020c + (fbpa * 0x4000)); +} + static const struct nvkm_ram_func -gp100_ram_func = { +gp100_ram = { + .upper = 0x1000000000, + .probe_fbp = gm107_ram_probe_fbp, + .probe_fbp_amount = gm200_ram_probe_fbp_amount, + .probe_fbpa_amount = gp100_ram_probe_fbpa, .init = gp100_ram_init, .get = gf100_ram_get, .put = gf100_ram_put, @@ -87,60 +97,10 @@ int gp100_ram_new(struct nvkm_fb *fb, struct nvkm_ram **pram) { struct nvkm_ram *ram; - struct nvkm_subdev *subdev = &fb->subdev; - struct nvkm_device *device = subdev->device; - enum nvkm_ram_type type = nvkm_fb_bios_memtype(device->bios); - const u32 rsvd_head = ( 256 * 1024); /* vga memory */ - const u32 rsvd_tail = (1024 * 1024); /* vbios etc */ - u32 fbpa_num = nvkm_rd32(device, 0x02243c), fbpa; - u32 fbio_opt = nvkm_rd32(device, 0x021c14); - u64 part, size = 0, comm = ~0ULL; - bool mixed = false; - int ret; - - nvkm_debug(subdev, "02243c: %08x\n", fbpa_num); - nvkm_debug(subdev, "021c14: %08x\n", fbio_opt); - for (fbpa = 0; fbpa < fbpa_num; fbpa++) { - if (!(fbio_opt & (1 << fbpa))) { - part = nvkm_rd32(device, 0x90020c + (fbpa * 0x4000)); - nvkm_debug(subdev, "fbpa %02x: %lld MiB\n", fbpa, part); - part = part << 20; - if (part != comm) { - if (comm != ~0ULL) - mixed = true; - comm = min(comm, part); - } - size = size + part; - } - } - - ret = nvkm_ram_new_(&gp100_ram_func, fb, type, size, 0, &ram); - *pram = ram; - if (ret) - return ret; - nvkm_mm_fini(&ram->vram); + if (!(ram = *pram = kzalloc(sizeof(*ram), GFP_KERNEL))) + return -ENOMEM; - if (mixed) { - ret = nvkm_mm_init(&ram->vram, rsvd_head >> NVKM_RAM_MM_SHIFT, - ((comm * fbpa_num) - rsvd_head) >> - NVKM_RAM_MM_SHIFT, 1); - if (ret) - return ret; + return gf100_ram_ctor(&gp100_ram, fb, ram); - ret = nvkm_mm_init(&ram->vram, (0x1000000000ULL + comm) >> - NVKM_RAM_MM_SHIFT, - (size - (comm * fbpa_num) - rsvd_tail) >> - NVKM_RAM_MM_SHIFT, 1); - if (ret) - return ret; - } else { - ret = nvkm_mm_init(&ram->vram, rsvd_head >> NVKM_RAM_MM_SHIFT, - (size - rsvd_head - rsvd_tail) >> - NVKM_RAM_MM_SHIFT, 1); - if (ret) - return ret; - } - - return 0; } |