diff options
Diffstat (limited to 'drivers/gpu/drm/nouveau/core/subdev')
62 files changed, 3664 insertions, 1201 deletions
diff --git a/drivers/gpu/drm/nouveau/core/subdev/bar/base.c b/drivers/gpu/drm/nouveau/core/subdev/bar/base.c index d70ba342aa2e..7098ddd54678 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/bar/base.c +++ b/drivers/gpu/drm/nouveau/core/subdev/bar/base.c @@ -23,7 +23,11 @@ */ #include <core/object.h> -#include <subdev/bar.h> + +#include <subdev/fb.h> +#include <subdev/vm.h> + +#include "priv.h" struct nouveau_barobj { struct nouveau_object base; diff --git a/drivers/gpu/drm/nouveau/core/subdev/bar/nv50.c b/drivers/gpu/drm/nouveau/core/subdev/bar/nv50.c index 160d27f3c7b4..090d594a21b3 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/bar/nv50.c +++ b/drivers/gpu/drm/nouveau/core/subdev/bar/nv50.c @@ -25,10 +25,11 @@ #include <core/gpuobj.h> #include <subdev/timer.h> -#include <subdev/bar.h> #include <subdev/fb.h> #include <subdev/vm.h> +#include "priv.h" + struct nv50_bar_priv { struct nouveau_bar base; spinlock_t lock; diff --git a/drivers/gpu/drm/nouveau/core/subdev/bar/nvc0.c b/drivers/gpu/drm/nouveau/core/subdev/bar/nvc0.c index b2ec7411eb2e..bac5e754de35 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/bar/nvc0.c +++ b/drivers/gpu/drm/nouveau/core/subdev/bar/nvc0.c @@ -25,10 +25,11 @@ #include <core/gpuobj.h> #include <subdev/timer.h> -#include <subdev/bar.h> #include <subdev/fb.h> #include <subdev/vm.h> +#include "priv.h" + struct nvc0_bar_priv { struct nouveau_bar base; spinlock_t lock; diff --git a/drivers/gpu/drm/nouveau/core/subdev/bar/priv.h b/drivers/gpu/drm/nouveau/core/subdev/bar/priv.h new file mode 100644 index 000000000000..ffad8f337ead --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/subdev/bar/priv.h @@ -0,0 +1,26 @@ +#ifndef __NVKM_BAR_PRIV_H__ +#define __NVKM_BAR_PRIV_H__ + +#include <subdev/bar.h> + +#define nouveau_bar_create(p,e,o,d) \ + nouveau_bar_create_((p), (e), (o), sizeof(**d), (void **)d) +#define nouveau_bar_init(p) \ + nouveau_subdev_init(&(p)->base) +#define nouveau_bar_fini(p,s) \ + nouveau_subdev_fini(&(p)->base, (s)) + +int nouveau_bar_create_(struct nouveau_object *, struct nouveau_object *, + struct nouveau_oclass *, int, void **); +void nouveau_bar_destroy(struct nouveau_bar *); + +void _nouveau_bar_dtor(struct nouveau_object *); +#define _nouveau_bar_init _nouveau_subdev_init +#define _nouveau_bar_fini _nouveau_subdev_fini + +int nouveau_bar_alloc(struct nouveau_bar *, struct nouveau_object *, + struct nouveau_mem *, struct nouveau_object **); + +void nv84_bar_flush(struct nouveau_bar *); + +#endif diff --git a/drivers/gpu/drm/nouveau/core/subdev/bios/base.c b/drivers/gpu/drm/nouveau/core/subdev/bios/base.c index aa0fbbec7f08..ef0c9c4a8cc3 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/bios/base.c +++ b/drivers/gpu/drm/nouveau/core/subdev/bios/base.c @@ -130,6 +130,10 @@ nouveau_bios_shadow_prom(struct nouveau_bios *bios) u16 pcir; int i; + /* there is no prom on nv4x IGP's */ + if (device->card_type == NV_40 && device->chipset >= 0x4c) + return; + /* enable access to rom */ if (device->card_type >= NV_50) pcireg = 0x088050; diff --git a/drivers/gpu/drm/nouveau/core/subdev/bios/init.c b/drivers/gpu/drm/nouveau/core/subdev/bios/init.c index 420908cb82b6..de201baeb053 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/bios/init.c +++ b/drivers/gpu/drm/nouveau/core/subdev/bios/init.c @@ -9,6 +9,7 @@ #include <subdev/bios/dp.h> #include <subdev/bios/gpio.h> #include <subdev/bios/init.h> +#include <subdev/bios/ramcfg.h> #include <subdev/devinit.h> #include <subdev/i2c.h> #include <subdev/vga.h> @@ -365,13 +366,13 @@ static u16 init_script(struct nouveau_bios *bios, int index) { struct nvbios_init init = { .bios = bios }; - u16 data; + u16 bmp_ver = bmp_version(bios), data; - if (bmp_version(bios) && bmp_version(bios) < 0x0510) { - if (index > 1) + if (bmp_ver && bmp_ver < 0x0510) { + if (index > 1 || bmp_ver < 0x0100) return 0x0000; - data = bios->bmp_offset + (bios->version.major < 2 ? 14 : 18); + data = bios->bmp_offset + (bmp_ver < 0x0200 ? 14 : 18); return nv_ro16(bios, data + (index * 2)); } @@ -391,43 +392,14 @@ init_unknown_script(struct nouveau_bios *bios) return 0x0000; } -static u16 -init_ram_restrict_table(struct nvbios_init *init) -{ - struct nouveau_bios *bios = init->bios; - struct bit_entry bit_M; - u16 data = 0x0000; - - if (!bit_entry(bios, 'M', &bit_M)) { - if (bit_M.version == 1 && bit_M.length >= 5) - data = nv_ro16(bios, bit_M.offset + 3); - if (bit_M.version == 2 && bit_M.length >= 3) - data = nv_ro16(bios, bit_M.offset + 1); - } - - if (data == 0x0000) - warn("ram restrict table not found\n"); - return data; -} - static u8 init_ram_restrict_group_count(struct nvbios_init *init) { - struct nouveau_bios *bios = init->bios; - struct bit_entry bit_M; - - if (!bit_entry(bios, 'M', &bit_M)) { - if (bit_M.version == 1 && bit_M.length >= 5) - return nv_ro08(bios, bit_M.offset + 2); - if (bit_M.version == 2 && bit_M.length >= 3) - return nv_ro08(bios, bit_M.offset + 0); - } - - return 0x00; + return nvbios_ramcfg_count(init->bios); } static u8 -init_ram_restrict_strap(struct nvbios_init *init) +init_ram_restrict(struct nvbios_init *init) { /* This appears to be the behaviour of the VBIOS parser, and *is* * important to cache the NV_PEXTDEV_BOOT0 on later chipsets to @@ -438,18 +410,8 @@ init_ram_restrict_strap(struct nvbios_init *init) * in case *not* re-reading the strap causes similar breakage. */ if (!init->ramcfg || init->bios->version.major < 0x70) - init->ramcfg = init_rd32(init, 0x101000); - return (init->ramcfg & 0x00000003c) >> 2; -} - -static u8 -init_ram_restrict(struct nvbios_init *init) -{ - u8 strap = init_ram_restrict_strap(init); - u16 table = init_ram_restrict_table(init); - if (table) - return nv_ro08(init->bios, table + strap); - return 0x00; + init->ramcfg = 0x80000000 | nvbios_ramcfg_index(init->bios); + return (init->ramcfg & 0x7fffffff); } static u8 @@ -1294,7 +1256,11 @@ init_jump(struct nvbios_init *init) u16 offset = nv_ro16(bios, init->offset + 1); trace("JUMP\t0x%04x\n", offset); - init->offset = offset; + + if (init_exec(init)) + init->offset = offset; + else + init->offset += 3; } /** diff --git a/drivers/gpu/drm/nouveau/core/subdev/bios/ramcfg.c b/drivers/gpu/drm/nouveau/core/subdev/bios/ramcfg.c new file mode 100644 index 000000000000..991aedda999b --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/subdev/bios/ramcfg.c @@ -0,0 +1,67 @@ +/* + * Copyright 2013 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 <subdev/bios.h> +#include <subdev/bios/bit.h> +#include <subdev/bios/ramcfg.h> + +static u8 +nvbios_ramcfg_strap(struct nouveau_bios *bios) +{ + return (nv_rd32(bios, 0x101000) & 0x0000003c) >> 2; +} + +u8 +nvbios_ramcfg_count(struct nouveau_bios *bios) +{ + struct bit_entry bit_M; + + if (!bit_entry(bios, 'M', &bit_M)) { + if (bit_M.version == 1 && bit_M.length >= 5) + return nv_ro08(bios, bit_M.offset + 2); + if (bit_M.version == 2 && bit_M.length >= 3) + return nv_ro08(bios, bit_M.offset + 0); + } + + return 0x00; +} + +u8 +nvbios_ramcfg_index(struct nouveau_bios *bios) +{ + u8 strap = nvbios_ramcfg_strap(bios); + u32 xlat = 0x00000000; + struct bit_entry bit_M; + + if (!bit_entry(bios, 'M', &bit_M)) { + if (bit_M.version == 1 && bit_M.length >= 5) + xlat = nv_ro16(bios, bit_M.offset + 3); + if (bit_M.version == 2 && bit_M.length >= 3) + xlat = nv_ro16(bios, bit_M.offset + 1); + } + + if (xlat) + strap = nv_ro08(bios, xlat + strap); + return strap; +} diff --git a/drivers/gpu/drm/nouveau/core/subdev/bios/rammap.c b/drivers/gpu/drm/nouveau/core/subdev/bios/rammap.c index 916fa9d302b7..1811b2cb0472 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/bios/rammap.c +++ b/drivers/gpu/drm/nouveau/core/subdev/bios/rammap.c @@ -24,11 +24,12 @@ #include <subdev/bios.h> #include <subdev/bios/bit.h> +#include <subdev/bios/ramcfg.h> #include <subdev/bios/rammap.h> -u16 -nvbios_rammap_table(struct nouveau_bios *bios, u8 *ver, u8 *hdr, - u8 *cnt, u8 *len, u8 *snr, u8 *ssz) +u32 +nvbios_rammapTe(struct nouveau_bios *bios, u8 *ver, u8 *hdr, + u8 *cnt, u8 *len, u8 *snr, u8 *ssz) { struct bit_entry bit_P; u16 rammap = 0x0000; @@ -57,12 +58,12 @@ nvbios_rammap_table(struct nouveau_bios *bios, u8 *ver, u8 *hdr, return 0x0000; } -u16 -nvbios_rammap_entry(struct nouveau_bios *bios, int idx, - u8 *ver, u8 *hdr, u8 *cnt, u8 *len) +u32 +nvbios_rammapEe(struct nouveau_bios *bios, int idx, + u8 *ver, u8 *hdr, u8 *cnt, u8 *len) { 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) { rammap = rammap + *hdr + (idx * (*len + (snr * ssz))); *hdr = *len; @@ -73,16 +74,100 @@ nvbios_rammap_entry(struct nouveau_bios *bios, int idx, return 0x0000; } -u16 -nvbios_rammap_match(struct nouveau_bios *bios, u16 khz, - u8 *ver, u8 *hdr, u8 *cnt, u8 *len) +u32 +nvbios_rammapEm(struct nouveau_bios *bios, u16 khz, + u8 *ver, u8 *hdr, u8 *cnt, u8 *len) { int idx = 0; 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) && khz <= nv_ro16(bios, data + 0x02)) break; } 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_08_20 = (nv_ro08(bios, data + 0x08) & 0x20) >> 5; + p->ramcfg_11_09 = (nv_ro08(bios, data + 0x09) & 0xff) >> 0; + break; + default: + data = 0; + break; + } + return data; +} diff --git a/drivers/gpu/drm/nouveau/core/subdev/bios/timing.c b/drivers/gpu/drm/nouveau/core/subdev/bios/timing.c index 151c2d6aaee8..350d44ab2ba2 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/bios/timing.c +++ b/drivers/gpu/drm/nouveau/core/subdev/bios/timing.c @@ -24,11 +24,12 @@ #include <subdev/bios.h> #include <subdev/bios/bit.h> +#include <subdev/bios/ramcfg.h> #include <subdev/bios/timing.h> u16 -nvbios_timing_table(struct nouveau_bios *bios, - u8 *ver, u8 *hdr, u8 *cnt, u8 *len) +nvbios_timingTe(struct nouveau_bios *bios, + u8 *ver, u8 *hdr, u8 *cnt, u8 *len, u8 *snr, u8 *ssz) { struct bit_entry bit_P; u16 timing = 0x0000; @@ -47,11 +48,15 @@ nvbios_timing_table(struct nouveau_bios *bios, *hdr = nv_ro08(bios, timing + 1); *cnt = nv_ro08(bios, timing + 2); *len = nv_ro08(bios, timing + 3); + *snr = 0; + *ssz = 0; return timing; case 0x20: *hdr = nv_ro08(bios, timing + 1); - *cnt = nv_ro08(bios, timing + 3); + *cnt = nv_ro08(bios, timing + 5); *len = nv_ro08(bios, timing + 2); + *snr = nv_ro08(bios, timing + 4); + *ssz = nv_ro08(bios, timing + 3); return timing; default: break; @@ -63,11 +68,60 @@ nvbios_timing_table(struct nouveau_bios *bios, } u16 -nvbios_timing_entry(struct nouveau_bios *bios, int idx, u8 *ver, u8 *len) +nvbios_timingEe(struct nouveau_bios *bios, int idx, + u8 *ver, u8 *hdr, u8 *cnt, u8 *len) { - u8 hdr, cnt; - u16 timing = nvbios_timing_table(bios, ver, &hdr, &cnt, len); - if (timing && idx < cnt) - return timing + hdr + (idx * *len); + u8 snr, ssz; + u16 timing = nvbios_timingTe(bios, ver, hdr, cnt, len, &snr, &ssz); + if (timing && idx < *cnt) { + timing += *hdr + idx * (*len + (snr * ssz)); + *hdr = *len; + *cnt = snr; + *len = ssz; + return timing; + } 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; +} diff --git a/drivers/gpu/drm/nouveau/core/subdev/clock/base.c b/drivers/gpu/drm/nouveau/core/subdev/clock/base.c index e2938a21b06f..dd62baead39c 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/clock/base.c +++ b/drivers/gpu/drm/nouveau/core/subdev/clock/base.c @@ -182,9 +182,12 @@ nouveau_pstate_prog(struct nouveau_clock *clk, int pstatei) clk->pstate = pstatei; if (pfb->ram->calc) { - ret = pfb->ram->calc(pfb, pstate->base.domain[nv_clk_src_mem]); - if (ret == 0) - ret = pfb->ram->prog(pfb); + int khz = pstate->base.domain[nv_clk_src_mem]; + do { + ret = pfb->ram->calc(pfb, khz); + if (ret == 0) + ret = pfb->ram->prog(pfb); + } while (ret > 0); pfb->ram->tidy(pfb); } diff --git a/drivers/gpu/drm/nouveau/core/subdev/clock/nv04.c b/drivers/gpu/drm/nouveau/core/subdev/clock/nv04.c index 30c1f3a4158e..b74db6cfc4e2 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/clock/nv04.c +++ b/drivers/gpu/drm/nouveau/core/subdev/clock/nv04.c @@ -25,7 +25,7 @@ #include <subdev/bios.h> #include <subdev/bios/pll.h> #include <subdev/clock.h> -#include <subdev/devinit/priv.h> +#include <subdev/devinit/nv04.h> #include "pll.h" diff --git a/drivers/gpu/drm/nouveau/core/subdev/clock/nve0.c b/drivers/gpu/drm/nouveau/core/subdev/clock/nve0.c index 4c62e84b96f5..d3c37c96f0e7 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/clock/nve0.c +++ b/drivers/gpu/drm/nouveau/core/subdev/clock/nve0.c @@ -457,7 +457,7 @@ nve0_domain[] = { { nv_clk_src_gpc , 0x00, NVKM_CLK_DOM_FLAG_CORE, "core", 2000 }, { nv_clk_src_hubk07 , 0x01, NVKM_CLK_DOM_FLAG_CORE }, { nv_clk_src_rop , 0x02, NVKM_CLK_DOM_FLAG_CORE }, - { nv_clk_src_mem , 0x03, 0, "memory", 1000 }, + { nv_clk_src_mem , 0x03, 0, "memory", 500 }, { nv_clk_src_hubk06 , 0x04, NVKM_CLK_DOM_FLAG_CORE }, { nv_clk_src_hubk01 , 0x05 }, { nv_clk_src_vdec , 0x06 }, diff --git a/drivers/gpu/drm/nouveau/core/subdev/devinit/base.c b/drivers/gpu/drm/nouveau/core/subdev/devinit/base.c index 79c81d3d9bac..8fa34e8152c2 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/devinit/base.c +++ b/drivers/gpu/drm/nouveau/core/subdev/devinit/base.c @@ -24,9 +24,11 @@ #include <core/option.h> -#include <subdev/devinit.h> #include <subdev/bios.h> #include <subdev/bios/init.h> +#include <subdev/vga.h> + +#include "priv.h" int _nouveau_devinit_fini(struct nouveau_object *object, bool suspend) @@ -37,18 +39,41 @@ _nouveau_devinit_fini(struct nouveau_object *object, bool suspend) if (suspend) devinit->post = true; + /* unlock the extended vga crtc regs */ + nv_lockvgac(devinit, false); + return nouveau_subdev_fini(&devinit->base, suspend); } int _nouveau_devinit_init(struct nouveau_object *object) { + struct nouveau_devinit_impl *impl = (void *)object->oclass; struct nouveau_devinit *devinit = (void *)object; - int ret = nouveau_subdev_init(&devinit->base); + int ret; + + ret = nouveau_subdev_init(&devinit->base); + if (ret) + return ret; + + ret = nvbios_init(&devinit->base, devinit->post); if (ret) return ret; - return nvbios_init(&devinit->base, devinit->post); + if (impl->disable) + nv_device(devinit)->disable_mask |= impl->disable(devinit); + return 0; +} + +void +_nouveau_devinit_dtor(struct nouveau_object *object) +{ + struct nouveau_devinit *devinit = (void *)object; + + /* lock crtc regs */ + nv_lockvgac(devinit, true); + + nouveau_subdev_destroy(&devinit->base); } int @@ -57,6 +82,7 @@ nouveau_devinit_create_(struct nouveau_object *parent, struct nouveau_oclass *oclass, int size, void **pobject) { + struct nouveau_devinit_impl *impl = (void *)oclass; struct nouveau_device *device = nv_device(parent); struct nouveau_devinit *devinit; int ret; @@ -68,5 +94,7 @@ nouveau_devinit_create_(struct nouveau_object *parent, return ret; devinit->post = nouveau_boolopt(device->cfgopt, "NvForcePost", false); + devinit->meminit = impl->meminit; + devinit->pll_set = impl->pll_set; return 0; } diff --git a/drivers/gpu/drm/nouveau/core/subdev/devinit/nv04.c b/drivers/gpu/drm/nouveau/core/subdev/devinit/nv04.c index 27c8235f1a85..7037eae46e44 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/devinit/nv04.c +++ b/drivers/gpu/drm/nouveau/core/subdev/devinit/nv04.c @@ -27,12 +27,7 @@ #include <subdev/vga.h> #include "fbmem.h" -#include "priv.h" - -struct nv04_devinit_priv { - struct nouveau_devinit base; - int owner; -}; +#include "nv04.h" static void nv04_devinit_meminit(struct nouveau_devinit *devinit) @@ -393,17 +388,21 @@ int nv04_devinit_fini(struct nouveau_object *object, bool suspend) { struct nv04_devinit_priv *priv = (void *)object; + int ret; /* make i2c busses accessible */ nv_mask(priv, 0x000200, 0x00000001, 0x00000001); - /* unlock extended vga crtc regs, and unslave crtcs */ - nv_lockvgac(priv, false); + ret = nouveau_devinit_fini(&priv->base, suspend); + if (ret) + return ret; + + /* unslave crtcs */ if (priv->owner < 0) priv->owner = nv_rdvgaowner(priv); nv_wrvgaowner(priv, 0); - return nouveau_devinit_fini(&priv->base, suspend); + return 0; } int @@ -431,14 +430,13 @@ nv04_devinit_dtor(struct nouveau_object *object) { struct nv04_devinit_priv *priv = (void *)object; - /* restore vga owner saved at first init, and lock crtc regs */ + /* restore vga owner saved at first init */ nv_wrvgaowner(priv, priv->owner); - nv_lockvgac(priv, true); nouveau_devinit_destroy(&priv->base); } -static int +int nv04_devinit_ctor(struct nouveau_object *parent, struct nouveau_object *engine, struct nouveau_oclass *oclass, void *data, u32 size, struct nouveau_object **pobject) @@ -451,19 +449,19 @@ nv04_devinit_ctor(struct nouveau_object *parent, struct nouveau_object *engine, if (ret) return ret; - priv->base.meminit = nv04_devinit_meminit; - priv->base.pll_set = nv04_devinit_pll_set; priv->owner = -1; return 0; } -struct nouveau_oclass -nv04_devinit_oclass = { - .handle = NV_SUBDEV(DEVINIT, 0x04), - .ofuncs = &(struct nouveau_ofuncs) { +struct nouveau_oclass * +nv04_devinit_oclass = &(struct nouveau_devinit_impl) { + .base.handle = NV_SUBDEV(DEVINIT, 0x04), + .base.ofuncs = &(struct nouveau_ofuncs) { .ctor = nv04_devinit_ctor, .dtor = nv04_devinit_dtor, .init = nv04_devinit_init, .fini = nv04_devinit_fini, }, -}; + .meminit = nv04_devinit_meminit, + .pll_set = nv04_devinit_pll_set, +}.base; diff --git a/drivers/gpu/drm/nouveau/core/subdev/devinit/nv04.h b/drivers/gpu/drm/nouveau/core/subdev/devinit/nv04.h new file mode 100644 index 000000000000..23470a57510c --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/subdev/devinit/nv04.h @@ -0,0 +1,23 @@ +#ifndef __NVKM_DEVINIT_NV04_H__ +#define __NVKM_DEVINIT_NV04_H__ + +#include "priv.h" + +struct nv04_devinit_priv { + struct nouveau_devinit base; + u8 owner; +}; + +int nv04_devinit_ctor(struct nouveau_object *, struct nouveau_object *, + struct nouveau_oclass *, void *, u32, + struct nouveau_object **); +void nv04_devinit_dtor(struct nouveau_object *); +int nv04_devinit_init(struct nouveau_object *); +int nv04_devinit_fini(struct nouveau_object *, bool); +int nv04_devinit_pll_set(struct nouveau_devinit *, u32, u32); + +void setPLL_single(struct nouveau_devinit *, u32, struct nouveau_pll_vals *); +void setPLL_double_highregs(struct nouveau_devinit *, u32, struct nouveau_pll_vals *); +void setPLL_double_lowregs(struct nouveau_devinit *, u32, struct nouveau_pll_vals *); + +#endif diff --git a/drivers/gpu/drm/nouveau/core/subdev/devinit/nv05.c b/drivers/gpu/drm/nouveau/core/subdev/devinit/nv05.c index b1912a8a8942..98b7e6780dc7 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/devinit/nv05.c +++ b/drivers/gpu/drm/nouveau/core/subdev/devinit/nv05.c @@ -29,12 +29,7 @@ #include <subdev/vga.h> #include "fbmem.h" -#include "priv.h" - -struct nv05_devinit_priv { - struct nouveau_devinit base; - u8 owner; -}; +#include "nv04.h" static void nv05_devinit_meminit(struct nouveau_devinit *devinit) @@ -49,7 +44,7 @@ nv05_devinit_meminit(struct nouveau_devinit *devinit) { 0x06, 0x00 }, { 0x00, 0x00 } }; - struct nv05_devinit_priv *priv = (void *)devinit; + struct nv04_devinit_priv *priv = (void *)devinit; struct nouveau_bios *bios = nouveau_bios(priv); struct io_mapping *fb; u32 patt = 0xdeadbeef; @@ -130,31 +125,15 @@ out: fbmem_fini(fb); } -static int -nv05_devinit_ctor(struct nouveau_object *parent, struct nouveau_object *engine, - struct nouveau_oclass *oclass, void *data, u32 size, - struct nouveau_object **pobject) -{ - struct nv05_devinit_priv *priv; - int ret; - - ret = nouveau_devinit_create(parent, engine, oclass, &priv); - *pobject = nv_object(priv); - if (ret) - return ret; - - priv->base.meminit = nv05_devinit_meminit; - priv->base.pll_set = nv04_devinit_pll_set; - return 0; -} - -struct nouveau_oclass -nv05_devinit_oclass = { - .handle = NV_SUBDEV(DEVINIT, 0x05), - .ofuncs = &(struct nouveau_ofuncs) { - .ctor = nv05_devinit_ctor, +struct nouveau_oclass * +nv05_devinit_oclass = &(struct nouveau_devinit_impl) { + .base.handle = NV_SUBDEV(DEVINIT, 0x05), + .base.ofuncs = &(struct nouveau_ofuncs) { + .ctor = nv04_devinit_ctor, .dtor = nv04_devinit_dtor, .init = nv04_devinit_init, .fini = nv04_devinit_fini, }, -}; + .meminit = nv05_devinit_meminit, + .pll_set = nv04_devinit_pll_set, +}.base; diff --git a/drivers/gpu/drm/nouveau/core/subdev/devinit/nv10.c b/drivers/gpu/drm/nouveau/core/subdev/devinit/nv10.c index 8d274dba1ef1..32b3d2131a7f 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/devinit/nv10.c +++ b/drivers/gpu/drm/nouveau/core/subdev/devinit/nv10.c @@ -27,17 +27,12 @@ #include <subdev/vga.h> #include "fbmem.h" -#include "priv.h" - -struct nv10_devinit_priv { - struct nouveau_devinit base; - u8 owner; -}; +#include "nv04.h" static void nv10_devinit_meminit(struct nouveau_devinit *devinit) { - struct nv10_devinit_priv *priv = (void *)devinit; + struct nv04_devinit_priv *priv = (void *)devinit; static const int mem_width[] = { 0x10, 0x00, 0x20 }; int mem_width_count; uint32_t patt = 0xdeadbeef; @@ -101,31 +96,15 @@ amount_found: fbmem_fini(fb); } -static int -nv10_devinit_ctor(struct nouveau_object *parent, struct nouveau_object *engine, - struct nouveau_oclass *oclass, void *data, u32 size, - struct nouveau_object **pobject) -{ - struct nv10_devinit_priv *priv; - int ret; - - ret = nouveau_devinit_create(parent, engine, oclass, &priv); - *pobject = nv_object(priv); - if (ret) - return ret; - - priv->base.meminit = nv10_devinit_meminit; - priv->base.pll_set = nv04_devinit_pll_set; - return 0; -} - -struct nouveau_oclass -nv10_devinit_oclass = { - .handle = NV_SUBDEV(DEVINIT, 0x10), - .ofuncs = &(struct nouveau_ofuncs) { - .ctor = nv10_devinit_ctor, +struct nouveau_oclass * +nv10_devinit_oclass = &(struct nouveau_devinit_impl) { + .base.handle = NV_SUBDEV(DEVINIT, 0x10), + .base.ofuncs = &(struct nouveau_ofuncs) { + .ctor = nv04_devinit_ctor, .dtor = nv04_devinit_dtor, .init = nv04_devinit_init, .fini = nv04_devinit_fini, }, -}; + .meminit = nv10_devinit_meminit, + .pll_set = nv04_devinit_pll_set, +}.base; diff --git a/drivers/gpu/drm/nouveau/core/subdev/devinit/nv1a.c b/drivers/gpu/drm/nouveau/core/subdev/devinit/nv1a.c index e9743cdabe75..526d0c6faacd 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/devinit/nv1a.c +++ b/drivers/gpu/drm/nouveau/core/subdev/devinit/nv1a.c @@ -22,37 +22,16 @@ * Authors: Ben Skeggs */ -#include "priv.h" +#include "nv04.h" -struct nv1a_devinit_priv { - struct nouveau_devinit base; - u8 owner; -}; - -static int -nv1a_devinit_ctor(struct nouveau_object *parent, struct nouveau_object *engine, - struct nouveau_oclass *oclass, void *data, u32 size, - struct nouveau_object **pobject) -{ - struct nv1a_devinit_priv *priv; - int ret; - - ret = nouveau_devinit_create(parent, engine, oclass, &priv); - *pobject = nv_object(priv); - if (ret) - return ret; - - priv->base.pll_set = nv04_devinit_pll_set; - return 0; -} - -struct nouveau_oclass -nv1a_devinit_oclass = { - .handle = NV_SUBDEV(DEVINIT, 0x1a), - .ofuncs = &(struct nouveau_ofuncs) { - .ctor = nv1a_devinit_ctor, +struct nouveau_oclass * +nv1a_devinit_oclass = &(struct nouveau_devinit_impl) { + .base.handle = NV_SUBDEV(DEVINIT, 0x1a), + .base.ofuncs = &(struct nouveau_ofuncs) { + .ctor = nv04_devinit_ctor, .dtor = nv04_devinit_dtor, .init = nv04_devinit_init, .fini = nv04_devinit_fini, }, -}; + .pll_set = nv04_devinit_pll_set, +}.base; diff --git a/drivers/gpu/drm/nouveau/core/subdev/devinit/nv20.c b/drivers/gpu/drm/nouveau/core/subdev/devinit/nv20.c index 6cc6080d3bc0..4689ba303b0b 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/devinit/nv20.c +++ b/drivers/gpu/drm/nouveau/core/subdev/devinit/nv20.c @@ -24,18 +24,13 @@ * */ -#include "priv.h" +#include "nv04.h" #include "fbmem.h" -struct nv20_devinit_priv { - struct nouveau_devinit base; - u8 owner; -}; - static void nv20_devinit_meminit(struct nouveau_devinit *devinit) { - struct nv20_devinit_priv *priv = (void *)devinit; + struct nv04_devinit_priv *priv = (void *)devinit; struct nouveau_device *device = nv_device(priv); uint32_t mask = (device->chipset >= 0x25 ? 0x300 : 0x900); uint32_t amount, off; @@ -65,31 +60,15 @@ nv20_devinit_meminit(struct nouveau_devinit *devinit) fbmem_fini(fb); } -static int -nv20_devinit_ctor(struct nouveau_object *parent, struct nouveau_object *engine, - struct nouveau_oclass *oclass, void *data, u32 size, - struct nouveau_object **pobject) -{ - struct nv20_devinit_priv *priv; - int ret; - - ret = nouveau_devinit_create(parent, engine, oclass, &priv); - *pobject = nv_object(priv); - if (ret) - return ret; - - priv->base.meminit = nv20_devinit_meminit; - priv->base.pll_set = nv04_devinit_pll_set; - return 0; -} - -struct nouveau_oclass -nv20_devinit_oclass = { - .handle = NV_SUBDEV(DEVINIT, 0x20), - .ofuncs = &(struct nouveau_ofuncs) { - .ctor = nv20_devinit_ctor, +struct nouveau_oclass * +nv20_devinit_oclass = &(struct nouveau_devinit_impl) { + .base.handle = NV_SUBDEV(DEVINIT, 0x20), + .base.ofuncs = &(struct nouveau_ofuncs) { + .ctor = nv04_devinit_ctor, .dtor = nv04_devinit_dtor, .init = nv04_devinit_init, .fini = nv04_devinit_fini, }, -}; + .meminit = nv20_devinit_meminit, + .pll_set = nv04_devinit_pll_set, +}.base; diff --git a/drivers/gpu/drm/nouveau/core/subdev/devinit/nv50.c b/drivers/gpu/drm/nouveau/core/subdev/devinit/nv50.c index 6df72247c477..b46c62a1d5d8 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/devinit/nv50.c +++ b/drivers/gpu/drm/nouveau/core/subdev/devinit/nv50.c @@ -28,9 +28,9 @@ #include <subdev/bios/init.h> #include <subdev/vga.h> -#include "priv.h" +#include "nv50.h" -static int +int nv50_devinit_pll_set(struct nouveau_devinit *devinit, u32 type, u32 freq) { struct nv50_devinit_priv *priv = (void *)devinit; @@ -74,6 +74,19 @@ nv50_devinit_pll_set(struct nouveau_devinit *devinit, u32 type, u32 freq) return 0; } +static u64 +nv50_devinit_disable(struct nouveau_devinit *devinit) +{ + struct nv50_devinit_priv *priv = (void *)devinit; + u32 r001540 = nv_rd32(priv, 0x001540); + u64 disable = 0ULL; + + if (!(r001540 & 0x40000000)) + disable |= (1ULL << NVDEV_ENGINE_MPEG); + + return disable; +} + int nv50_devinit_init(struct nouveau_object *object) { @@ -120,7 +133,7 @@ nv50_devinit_init(struct nouveau_object *object) return 0; } -static int +int nv50_devinit_ctor(struct nouveau_object *parent, struct nouveau_object *engine, struct nouveau_oclass *oclass, void *data, u32 size, struct nouveau_object **pobject) @@ -133,17 +146,18 @@ nv50_devinit_ctor(struct nouveau_object *parent, struct nouveau_object *engine, if (ret) return ret; - priv->base.pll_set = nv50_devinit_pll_set; return 0; } -struct nouveau_oclass -nv50_devinit_oclass = { - .handle = NV_SUBDEV(DEVINIT, 0x50), - .ofuncs = &(struct nouveau_ofuncs) { +struct nouveau_oclass * +nv50_devinit_oclass = &(struct nouveau_devinit_impl) { + .base.handle = NV_SUBDEV(DEVINIT, 0x50), + .base.ofuncs = &(struct nouveau_ofuncs) { .ctor = nv50_devinit_ctor, .dtor = _nouveau_devinit_dtor, .init = nv50_devinit_init, .fini = _nouveau_devinit_fini, }, -}; + .pll_set = nv50_devinit_pll_set, + .disable = nv50_devinit_disable, +}.base; diff --git a/drivers/gpu/drm/nouveau/core/subdev/devinit/nv50.h b/drivers/gpu/drm/nouveau/core/subdev/devinit/nv50.h new file mode 100644 index 000000000000..141c27e9f182 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/subdev/devinit/nv50.h @@ -0,0 +1,18 @@ +#ifndef __NVKM_DEVINIT_NV50_H__ +#define __NVKM_DEVINIT_NV50_H__ + +#include "priv.h" + +struct nv50_devinit_priv { + struct nouveau_devinit base; +}; + +int nv50_devinit_ctor(struct nouveau_object *, struct nouveau_object *, + struct nouveau_oclass *, void *, u32, + struct nouveau_object **); +int nv50_devinit_init(struct nouveau_object *); +int nv50_devinit_pll_set(struct nouveau_devinit *, u32, u32); + +int nva3_devinit_pll_set(struct nouveau_devinit *, u32, u32); + +#endif diff --git a/drivers/gpu/drm/nouveau/core/subdev/devinit/nv84.c b/drivers/gpu/drm/nouveau/core/subdev/devinit/nv84.c new file mode 100644 index 000000000000..787422505d87 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/subdev/devinit/nv84.c @@ -0,0 +1,63 @@ +/* + * Copyright 2013 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 + */ + +#include "nv50.h" + +static u64 +nv84_devinit_disable(struct nouveau_devinit *devinit) +{ + struct nv50_devinit_priv *priv = (void *)devinit; + u32 r001540 = nv_rd32(priv, 0x001540); + u32 r00154c = nv_rd32(priv, 0x00154c); + u64 disable = 0ULL; + + if (!(r001540 & 0x40000000)) { + disable |= (1ULL << NVDEV_ENGINE_MPEG); + disable |= (1ULL << NVDEV_ENGINE_VP); + disable |= (1ULL << NVDEV_ENGINE_BSP); + disable |= (1ULL << NVDEV_ENGINE_CRYPT); + } + + if (!(r00154c & 0x00000004)) + disable |= (1ULL << NVDEV_ENGINE_DISP); + if (!(r00154c & 0x00000020)) + disable |= (1ULL << NVDEV_ENGINE_BSP); + if (!(r00154c & 0x00000040)) + disable |= (1ULL << NVDEV_ENGINE_CRYPT); + + return disable; +} + +struct nouveau_oclass * +nv84_devinit_oclass = &(struct nouveau_devinit_impl) { + .base.handle = NV_SUBDEV(DEVINIT, 0x84), + .base.ofuncs = &(struct nouveau_ofuncs) { + .ctor = nv50_devinit_ctor, + .dtor = _nouveau_devinit_dtor, + .init = nv50_devinit_init, + .fini = _nouveau_devinit_fini, + }, + .pll_set = nv50_devinit_pll_set, + .disable = nv84_devinit_disable, +}.base; diff --git a/drivers/gpu/drm/nouveau/core/subdev/devinit/nv98.c b/drivers/gpu/drm/nouveau/core/subdev/devinit/nv98.c new file mode 100644 index 000000000000..2b0e963fc6f0 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/subdev/devinit/nv98.c @@ -0,0 +1,62 @@ +/* + * Copyright 2013 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 + */ + +#include "nv50.h" + +static u64 +nv98_devinit_disable(struct nouveau_devinit *devinit) +{ + struct nv50_devinit_priv *priv = (void *)devinit; + u32 r001540 = nv_rd32(priv, 0x001540); + u32 r00154c = nv_rd32(priv, 0x00154c); + u64 disable = 0ULL; + + if (!(r001540 & 0x40000000)) { + disable |= (1ULL << NVDEV_ENGINE_VP); + disable |= (1ULL << NVDEV_ENGINE_BSP); + disable |= (1ULL << NVDEV_ENGINE_PPP); + } + + if (!(r00154c & 0x00000004)) + disable |= (1ULL << NVDEV_ENGINE_DISP); + if (!(r00154c & 0x00000020)) + disable |= (1ULL << NVDEV_ENGINE_BSP); + if (!(r00154c & 0x00000040)) + disable |= (1ULL << NVDEV_ENGINE_CRYPT); + + return disable; +} + +struct nouveau_oclass * +nv98_devinit_oclass = &(struct nouveau_devinit_impl) { + .base.handle = NV_SUBDEV(DEVINIT, 0x98), + .base.ofuncs = &(struct nouveau_ofuncs) { + .ctor = nv50_devinit_ctor, + .dtor = _nouveau_devinit_dtor, + .init = nv50_devinit_init, + .fini = _nouveau_devinit_fini, + }, + .pll_set = nv50_devinit_pll_set, + .disable = nv98_devinit_disable, +}.base; diff --git a/drivers/gpu/drm/nouveau/core/subdev/devinit/nva3.c b/drivers/gpu/drm/nouveau/core/subdev/devinit/nva3.c index 76a68b290141..6dedf1dad7f7 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/devinit/nva3.c +++ b/drivers/gpu/drm/nouveau/core/subdev/devinit/nva3.c @@ -22,12 +22,12 @@ * Authors: Ben Skeggs */ -#include "priv.h" +#include "nv50.h" -static int +int nva3_devinit_pll_set(struct nouveau_devinit *devinit, u32 type, u32 freq) { - struct nva3_devinit_priv *priv = (void *)devinit; + struct nv50_devinit_priv *priv = (void *)devinit; struct nouveau_bios *bios = nouveau_bios(priv); struct nvbios_pll info; int N, fN, M, P; @@ -58,30 +58,38 @@ nva3_devinit_pll_set(struct nouveau_devinit *devinit, u32 type, u32 freq) return ret; } -static int -nva3_devinit_ctor(struct nouveau_object *parent, struct nouveau_object *engine, - struct nouveau_oclass *oclass, void *data, u32 size, - struct nouveau_object **pobject) +static u64 +nva3_devinit_disable(struct nouveau_devinit *devinit) { - struct nv50_devinit_priv *priv; - int ret; + struct nv50_devinit_priv *priv = (void *)devinit; + u32 r001540 = nv_rd32(priv, 0x001540); + u32 r00154c = nv_rd32(priv, 0x00154c); + u64 disable = 0ULL; - ret = nouveau_devinit_create(parent, engine, oclass, &priv); - *pobject = nv_object(priv); - if (ret) - return ret; + if (!(r001540 & 0x40000000)) { + disable |= (1ULL << NVDEV_ENGINE_VP); + disable |= (1ULL << NVDEV_ENGINE_PPP); + } + + if (!(r00154c & 0x00000004)) + disable |= (1ULL << NVDEV_ENGINE_DISP); + if (!(r00154c & 0x00000020)) + disable |= (1ULL << NVDEV_ENGINE_BSP); + if (!(r00154c & 0x00000200)) + disable |= (1ULL << NVDEV_ENGINE_COPY0); - priv->base.pll_set = nva3_devinit_pll_set; - return 0; + return disable; } -struct nouveau_oclass -nva3_devinit_oclass = { - .handle = NV_SUBDEV(DEVINIT, 0xa3), - .ofuncs = &(struct nouveau_ofuncs) { - .ctor = nva3_devinit_ctor, +struct nouveau_oclass * +nva3_devinit_oclass = &(struct nouveau_devinit_impl) { + .base.handle = NV_SUBDEV(DEVINIT, 0xa3), + .base.ofuncs = &(struct nouveau_ofuncs) { + .ctor = nv50_devinit_ctor, .dtor = _nouveau_devinit_dtor, .init = nv50_devinit_init, .fini = _nouveau_devinit_fini, }, -}; + .pll_set = nva3_devinit_pll_set, + .disable = nva3_devinit_disable, +}.base; diff --git a/drivers/gpu/drm/nouveau/core/subdev/devinit/nvaf.c b/drivers/gpu/drm/nouveau/core/subdev/devinit/nvaf.c new file mode 100644 index 000000000000..4fc68d27eff3 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/subdev/devinit/nvaf.c @@ -0,0 +1,63 @@ +/* + * Copyright 2013 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 + */ + +#include "nv50.h" + +static u64 +nvaf_devinit_disable(struct nouveau_devinit *devinit) +{ + struct nv50_devinit_priv *priv = (void *)devinit; + u32 r001540 = nv_rd32(priv, 0x001540); + u32 r00154c = nv_rd32(priv, 0x00154c); + u64 disable = 0; + + if (!(r001540 & 0x40000000)) { + disable |= (1ULL << NVDEV_ENGINE_VP); + disable |= (1ULL << NVDEV_ENGINE_PPP); + } + + if (!(r00154c & 0x00000004)) + disable |= (1ULL << NVDEV_ENGINE_DISP); + if (!(r00154c & 0x00000020)) + disable |= (1ULL << NVDEV_ENGINE_BSP); + if (!(r00154c & 0x00000040)) + disable |= (1ULL << NVDEV_ENGINE_VIC); + if (!(r00154c & 0x00000200)) + disable |= (1ULL << NVDEV_ENGINE_COPY0); + + return disable; +} + +struct nouveau_oclass * +nvaf_devinit_oclass = &(struct nouveau_devinit_impl) { + .base.handle = NV_SUBDEV(DEVINIT, 0xaf), + .base.ofuncs = &(struct nouveau_ofuncs) { + .ctor = nv50_devinit_ctor, + .dtor = _nouveau_devinit_dtor, + .init = nv50_devinit_init, + .fini = _nouveau_devinit_fini, + }, + .pll_set = nva3_devinit_pll_set, + .disable = nvaf_devinit_disable, +}.base; diff --git a/drivers/gpu/drm/nouveau/core/subdev/devinit/nvc0.c b/drivers/gpu/drm/nouveau/core/subdev/devinit/nvc0.c index 19e265bf4574..fa7e63766b1b 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/devinit/nvc0.c +++ b/drivers/gpu/drm/nouveau/core/subdev/devinit/nvc0.c @@ -22,12 +22,12 @@ * Authors: Ben Skeggs */ -#include "priv.h" +#include "nv50.h" static int nvc0_devinit_pll_set(struct nouveau_devinit *devinit, u32 type, u32 freq) { - struct nvc0_devinit_priv *priv = (void *)devinit; + struct nv50_devinit_priv *priv = (void *)devinit; struct nouveau_bios *bios = nouveau_bios(priv); struct nvbios_pll info; int N, fN, M, P; @@ -59,6 +59,33 @@ nvc0_devinit_pll_set(struct nouveau_devinit *devinit, u32 type, u32 freq) return ret; } +static u64 +nvc0_devinit_disable(struct nouveau_devinit *devinit) +{ + struct nv50_devinit_priv *priv = (void *)devinit; + u32 r022500 = nv_rd32(priv, 0x022500); + u64 disable = 0ULL; + + if (r022500 & 0x00000001) + disable |= (1ULL << NVDEV_ENGINE_DISP); + + if (r022500 & 0x00000002) { + disable |= (1ULL << NVDEV_ENGINE_VP); + disable |= (1ULL << NVDEV_ENGINE_PPP); + } + + if (r022500 & 0x00000004) + disable |= (1ULL << NVDEV_ENGINE_BSP); + if (r022500 & 0x00000008) + disable |= (1ULL << NVDEV_ENGINE_VENC); + if (r022500 & 0x00000100) + disable |= (1ULL << NVDEV_ENGINE_COPY0); + if (r022500 & 0x00000200) + disable |= (1ULL << NVDEV_ENGINE_COPY1); + + return disable; +} + static int nvc0_devinit_ctor(struct nouveau_object *parent, struct nouveau_object *engine, struct nouveau_oclass *oclass, void *data, u32 size, @@ -72,19 +99,20 @@ nvc0_devinit_ctor(struct nouveau_object *parent, struct nouveau_object *engine, if (ret) return ret; - priv->base.pll_set = nvc0_devinit_pll_set; if (nv_rd32(priv, 0x022500) & 0x00000001) priv->base.post = true; return 0; } -struct nouveau_oclass -nvc0_devinit_oclass = { - .handle = NV_SUBDEV(DEVINIT, 0xc0), - .ofuncs = &(struct nouveau_ofuncs) { +struct nouveau_oclass * +nvc0_devinit_oclass = &(struct nouveau_devinit_impl) { + .base.handle = NV_SUBDEV(DEVINIT, 0xc0), + .base.ofuncs = &(struct nouveau_ofuncs) { .ctor = nvc0_devinit_ctor, .dtor = _nouveau_devinit_dtor, .init = nv50_devinit_init, .fini = _nouveau_devinit_fini, }, -}; + .pll_set = nvc0_devinit_pll_set, + .disable = nvc0_devinit_disable, +}.base; diff --git a/drivers/gpu/drm/nouveau/core/subdev/devinit/priv.h b/drivers/gpu/drm/nouveau/core/subdev/devinit/priv.h index 7d622e2b0171..822a2fbf44a5 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/devinit/priv.h +++ b/drivers/gpu/drm/nouveau/core/subdev/devinit/priv.h @@ -6,20 +6,32 @@ #include <subdev/clock/pll.h> #include <subdev/devinit.h> -void nv04_devinit_dtor(struct nouveau_object *); -int nv04_devinit_init(struct nouveau_object *); -int nv04_devinit_fini(struct nouveau_object *, bool); -int nv04_devinit_pll_set(struct nouveau_devinit *, u32, u32); - -void setPLL_single(struct nouveau_devinit *, u32, struct nouveau_pll_vals *); -void setPLL_double_highregs(struct nouveau_devinit *, u32, struct nouveau_pll_vals *); -void setPLL_double_lowregs(struct nouveau_devinit *, u32, struct nouveau_pll_vals *); - - -struct nv50_devinit_priv { - struct nouveau_devinit base; +struct nouveau_devinit_impl { + struct nouveau_oclass base; + void (*meminit)(struct nouveau_devinit *); + int (*pll_set)(struct nouveau_devinit *, u32 type, u32 freq); + u64 (*disable)(struct nouveau_devinit *); }; -int nv50_devinit_init(struct nouveau_object *); +#define nouveau_devinit_create(p,e,o,d) \ + nouveau_devinit_create_((p), (e), (o), sizeof(**d), (void **)d) +#define nouveau_devinit_destroy(p) ({ \ + struct nouveau_devinit *d = (p); \ + _nouveau_devinit_dtor(nv_object(d)); \ +}) +#define nouveau_devinit_init(p) ({ \ + struct nouveau_devinit *d = (p); \ + _nouveau_devinit_init(nv_object(d)); \ +}) +#define nouveau_devinit_fini(p,s) ({ \ + struct nouveau_devinit *d = (p); \ + _nouveau_devinit_fini(nv_object(d), (s)); \ +}) + +int nouveau_devinit_create_(struct nouveau_object *, struct nouveau_object *, + struct nouveau_oclass *, int, void **); +void _nouveau_devinit_dtor(struct nouveau_object *); +int _nouveau_devinit_init(struct nouveau_object *); +int _nouveau_devinit_fini(struct nouveau_object *, bool suspend); #endif diff --git a/drivers/gpu/drm/nouveau/core/subdev/fb/gddr5.c b/drivers/gpu/drm/nouveau/core/subdev/fb/gddr5.c index 34f9605ffee6..66fe959b4f74 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/fb/gddr5.c +++ b/drivers/gpu/drm/nouveau/core/subdev/fb/gddr5.c @@ -25,35 +25,44 @@ #include <subdev/bios.h> #include "priv.h" +/* binary driver only executes this path if the condition (a) is true + * for any configuration (combination of rammap+ramcfg+timing) that + * can be reached on a given card. for now, we will execute the branch + * unconditionally in the hope that a "false everywhere" in the bios + * tables doesn't actually mean "don't touch this". + */ +#define NOTE00(a) 1 + int -nouveau_gddr5_calc(struct nouveau_ram *ram) +nouveau_gddr5_calc(struct nouveau_ram *ram, bool nuts) { - struct nouveau_bios *bios = nouveau_bios(ram); - int pd, lf, xd, vh, vr, vo; - int WL, CL, WR, at, dt, ds; + int pd, lf, xd, vh, vr, vo, l3; + int WL, CL, WR, at[2], dt, ds; int rq = ram->freq < 1000000; /* XXX */ - switch (!!ram->ramcfg.data * ram->ramcfg.version) { + switch (ram->ramcfg.version) { case 0x11: - pd = (nv_ro08(bios, ram->ramcfg.data + 0x01) & 0x80) >> 7; - lf = (nv_ro08(bios, ram->ramcfg.data + 0x01) & 0x40) >> 6; - xd = !(nv_ro08(bios, ram->ramcfg.data + 0x01) & 0x20); - vh = (nv_ro08(bios, ram->ramcfg.data + 0x02) & 0x10) >> 4; - vr = (nv_ro08(bios, ram->ramcfg.data + 0x02) & 0x04) >> 2; - vo = nv_ro08(bios, ram->ramcfg.data + 0x06) & 0xff; + pd = ram->next->bios.ramcfg_11_01_80; + lf = ram->next->bios.ramcfg_11_01_40; + xd = !ram->next->bios.ramcfg_11_01_20; + vh = ram->next->bios.ramcfg_11_02_10; + vr = ram->next->bios.ramcfg_11_02_04; + vo = ram->next->bios.ramcfg_11_06; + l3 = !ram->next->bios.ramcfg_11_07_02; break; default: return -ENOSYS; } - switch (!!ram->timing.data * ram->timing.version) { + switch (ram->timing.version) { case 0x20: - WL = (nv_ro16(bios, ram->timing.data + 0x04) & 0x0f80) >> 7; - CL = nv_ro08(bios, ram->timing.data + 0x04) & 0x1f; - WR = nv_ro08(bios, ram->timing.data + 0x0a) & 0x7f; - at = (nv_ro08(bios, ram->timing.data + 0x2e) & 0xc0) >> 6; - dt = nv_ro08(bios, ram->timing.data + 0x2e) & 0x03; - ds = nv_ro08(bios, ram->timing.data + 0x2f) & 0x03; + WL = (ram->next->bios.timing[1] & 0x00000f80) >> 7; + CL = (ram->next->bios.timing[1] & 0x0000001f); + WR = (ram->next->bios.timing[2] & 0x007f0000) >> 16; + at[0] = ram->next->bios.timing_20_2e_c0; + at[1] = ram->next->bios.timing_20_2e_30; + dt = ram->next->bios.timing_20_2e_03; + ds = ram->next->bios.timing_20_2f_03; break; default: return -ENOSYS; @@ -71,13 +80,25 @@ nouveau_gddr5_calc(struct nouveau_ram *ram) ram->mr[1] &= ~0x0bf; ram->mr[1] |= (xd & 0x01) << 7; - ram->mr[1] |= (at & 0x03) << 4; + ram->mr[1] |= (at[0] & 0x03) << 4; ram->mr[1] |= (dt & 0x03) << 2; ram->mr[1] |= (ds & 0x03) << 0; + /* this seems wrong, alternate field used for the broadcast + * on nuts vs non-nuts configs.. meh, it matches for now. + */ + ram->mr1_nuts = ram->mr[1]; + if (nuts) { + ram->mr[1] &= ~0x030; + ram->mr[1] |= (at[1] & 0x03) << 4; + } + ram->mr[3] &= ~0x020; ram->mr[3] |= (rq & 0x01) << 5; + ram->mr[5] &= ~0x004; + ram->mr[5] |= (l3 << 2); + if (!vo) vo = (ram->mr[6] & 0xff0) >> 4; if (ram->mr[6] & 0x001) @@ -86,11 +107,16 @@ nouveau_gddr5_calc(struct nouveau_ram *ram) ram->mr[6] |= (vo & 0xff) << 4; ram->mr[6] |= (pd & 0x01) << 0; - if (!(ram->mr[7] & 0x100)) - vr = 0; /* binary driver does this.. bug? */ - ram->mr[7] &= ~0x188; - ram->mr[7] |= (vr & 0x01) << 8; + if (NOTE00(vr)) { + ram->mr[7] &= ~0x300; + ram->mr[7] |= (vr & 0x03) << 8; + } + ram->mr[7] &= ~0x088; ram->mr[7] |= (vh & 0x01) << 7; ram->mr[7] |= (lf & 0x01) << 3; + + ram->mr[8] &= ~0x003; + ram->mr[8] |= (WR & 0x10) >> 3; + ram->mr[8] |= (CL & 0x10) >> 4; return 0; } diff --git a/drivers/gpu/drm/nouveau/core/subdev/fb/nv1a.c b/drivers/gpu/drm/nouveau/core/subdev/fb/nv1a.c index 9159a5ccee93..265d1253624a 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/fb/nv1a.c +++ b/drivers/gpu/drm/nouveau/core/subdev/fb/nv1a.c @@ -36,7 +36,7 @@ nv1a_fb_oclass = &(struct nv04_fb_impl) { .fini = _nouveau_fb_fini, }, .base.memtype = nv04_fb_memtype_valid, - .base.ram = &nv10_ram_oclass, + .base.ram = &nv1a_ram_oclass, .tile.regions = 8, .tile.init = nv10_fb_tile_init, .tile.fini = nv10_fb_tile_fini, diff --git a/drivers/gpu/drm/nouveau/core/subdev/fb/nvc0.c b/drivers/gpu/drm/nouveau/core/subdev/fb/nvc0.c index e5fc37c4caac..45470e1f0385 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/fb/nvc0.c +++ b/drivers/gpu/drm/nouveau/core/subdev/fb/nvc0.c @@ -33,6 +33,21 @@ nvc0_fb_memtype_valid(struct nouveau_fb *pfb, u32 tile_flags) return likely((nvc0_pte_storage_type_map[memtype] != 0xff)); } +static void +nvc0_fb_intr(struct nouveau_subdev *subdev) +{ + struct nvc0_fb_priv *priv = (void *)subdev; + u32 intr = nv_rd32(priv, 0x000100); + if (intr & 0x08000000) { + nv_debug(priv, "PFFB intr\n"); + intr &= ~0x08000000; + } + if (intr & 0x00002000) { + nv_debug(priv, "PBFB intr\n"); + intr &= ~0x00002000; + } +} + int nvc0_fb_init(struct nouveau_object *object) { @@ -86,6 +101,7 @@ nvc0_fb_ctor(struct nouveau_object *parent, struct nouveau_object *engine, return -EFAULT; } + nv_subdev(priv)->intr = nvc0_fb_intr; return 0; } diff --git a/drivers/gpu/drm/nouveau/core/subdev/fb/priv.h b/drivers/gpu/drm/nouveau/core/subdev/fb/priv.h index 493125214e88..edaf95dee612 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/fb/priv.h +++ b/drivers/gpu/drm/nouveau/core/subdev/fb/priv.h @@ -34,7 +34,7 @@ extern struct nouveau_oclass nvc0_ram_oclass; extern struct nouveau_oclass nve0_ram_oclass; int nouveau_sddr3_calc(struct nouveau_ram *ram); -int nouveau_gddr5_calc(struct nouveau_ram *ram); +int nouveau_gddr5_calc(struct nouveau_ram *ram, bool nuts); #define nouveau_fb_create(p,e,c,d) \ nouveau_fb_create_((p), (e), (c), sizeof(**d), (void **)d) diff --git a/drivers/gpu/drm/nouveau/core/subdev/fb/ramnv50.c b/drivers/gpu/drm/nouveau/core/subdev/fb/ramnv50.c index 76762a17d89c..c7fdb3a9e88b 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/fb/ramnv50.c +++ b/drivers/gpu/drm/nouveau/core/subdev/fb/ramnv50.c @@ -70,13 +70,11 @@ nv50_ram_calc(struct nouveau_fb *pfb, u32 freq) struct nv50_ramseq *hwsq = &ram->hwsq; struct nvbios_perfE perfE; struct nvbios_pll mpll; - struct bit_entry M; struct { u32 data; u8 size; } ramcfg, timing; - u8 ver, hdr, cnt, strap; - u32 data; + u8 ver, hdr, cnt, len, strap; int N1, M1, N2, M2, P; int ret, i; @@ -93,16 +91,7 @@ nv50_ram_calc(struct nouveau_fb *pfb, u32 freq) } while (perfE.memory < freq); /* locate specific data set for the attached memory */ - if (bit_entry(bios, 'M', &M) || M.version != 1 || M.length < 5) { - nv_error(pfb, "invalid/missing memory table\n"); - return -EINVAL; - } - - strap = (nv_rd32(pfb, 0x101000) & 0x0000003c) >> 2; - data = nv_ro16(bios, M.offset + 3); - if (data) - strap = nv_ro08(bios, data + strap); - + strap = nvbios_ramcfg_index(bios); if (strap >= cnt) { nv_error(pfb, "invalid ramcfg strap\n"); return -EINVAL; @@ -113,7 +102,8 @@ nv50_ram_calc(struct nouveau_fb *pfb, u32 freq) /* lookup memory timings, if bios says they're present */ strap = nv_ro08(bios, ramcfg.data + 0x01); if (strap != 0xff) { - timing.data = nvbios_timing_entry(bios, strap, &ver, &hdr); + timing.data = nvbios_timingEe(bios, strap, &ver, &hdr, + &cnt, &len); if (!timing.data || ver != 0x10 || hdr < 0x12) { nv_error(pfb, "invalid/missing timing entry " "%02x %04x %02x %02x\n", diff --git a/drivers/gpu/drm/nouveau/core/subdev/fb/ramnva3.c b/drivers/gpu/drm/nouveau/core/subdev/fb/ramnva3.c index f6292cd9207c..f4ae8aa46a25 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/fb/ramnva3.c +++ b/drivers/gpu/drm/nouveau/core/subdev/fb/ramnva3.c @@ -79,8 +79,7 @@ nva3_ram_calc(struct nouveau_fb *pfb, u32 freq) struct nva3_ram *ram = (void *)pfb->ram; struct nva3_ramfuc *fuc = &ram->fuc; struct nva3_clock_info mclk; - struct bit_entry M; - u8 ver, cnt, strap; + u8 ver, cnt, len, strap; u32 data; struct { u32 data; @@ -91,24 +90,15 @@ nva3_ram_calc(struct nouveau_fb *pfb, u32 freq) int ret; /* lookup memory config data relevant to the target frequency */ - rammap.data = nvbios_rammap_match(bios, freq / 1000, &ver, &rammap.size, - &cnt, &ramcfg.size); + rammap.data = nvbios_rammapEm(bios, freq / 1000, &ver, &rammap.size, + &cnt, &ramcfg.size); if (!rammap.data || ver != 0x10 || rammap.size < 0x0e) { nv_error(pfb, "invalid/missing rammap entry\n"); return -EINVAL; } /* locate specific data set for the attached memory */ - if (bit_entry(bios, 'M', &M) || M.version != 2 || M.length < 3) { - nv_error(pfb, "invalid/missing memory table\n"); - return -EINVAL; - } - - strap = (nv_rd32(pfb, 0x101000) & 0x0000003c) >> 2; - data = nv_ro16(bios, M.offset + 1); - if (data) - strap = nv_ro08(bios, data + strap); - + strap = nvbios_ramcfg_index(bios); if (strap >= cnt) { nv_error(pfb, "invalid ramcfg strap\n"); return -EINVAL; @@ -123,8 +113,8 @@ nva3_ram_calc(struct nouveau_fb *pfb, u32 freq) /* lookup memory timings, if bios says they're present */ strap = nv_ro08(bios, ramcfg.data + 0x01); if (strap != 0xff) { - timing.data = nvbios_timing_entry(bios, strap, &ver, - &timing.size); + timing.data = nvbios_timingEe(bios, strap, &ver, &timing.size, + &cnt, &len); if (!timing.data || ver != 0x10 || timing.size < 0x19) { nv_error(pfb, "invalid/missing timing entry\n"); return -EINVAL; diff --git a/drivers/gpu/drm/nouveau/core/subdev/fb/ramnvc0.c b/drivers/gpu/drm/nouveau/core/subdev/fb/ramnvc0.c index f464547c6bab..0391b824ee76 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/fb/ramnvc0.c +++ b/drivers/gpu/drm/nouveau/core/subdev/fb/ramnvc0.c @@ -23,7 +23,6 @@ */ #include <subdev/bios.h> -#include <subdev/bios/bit.h> #include <subdev/bios/pll.h> #include <subdev/bios/rammap.h> #include <subdev/bios/timing.h> @@ -134,9 +133,7 @@ nvc0_ram_calc(struct nouveau_fb *pfb, u32 freq) struct nouveau_bios *bios = nouveau_bios(pfb); struct nvc0_ram *ram = (void *)pfb->ram; struct nvc0_ramfuc *fuc = &ram->fuc; - struct bit_entry M; - u8 ver, cnt, strap; - u32 data; + u8 ver, cnt, len, strap; struct { u32 data; u8 size; @@ -147,24 +144,15 @@ nvc0_ram_calc(struct nouveau_fb *pfb, u32 freq) int ret; /* lookup memory config data relevant to the target frequency */ - rammap.data = nvbios_rammap_match(bios, freq / 1000, &ver, &rammap.size, - &cnt, &ramcfg.size); + rammap.data = nvbios_rammapEm(bios, freq / 1000, &ver, &rammap.size, + &cnt, &ramcfg.size); if (!rammap.data || ver != 0x10 || rammap.size < 0x0e) { nv_error(pfb, "invalid/missing rammap entry\n"); return -EINVAL; } /* locate specific data set for the attached memory */ - if (bit_entry(bios, 'M', &M) || M.version != 2 || M.length < 3) { - nv_error(pfb, "invalid/missing memory table\n"); - return -EINVAL; - } - - strap = (nv_rd32(pfb, 0x101000) & 0x0000003c) >> 2; - data = nv_ro16(bios, M.offset + 1); - if (data) - strap = nv_ro08(bios, data + strap); - + strap = nvbios_ramcfg_index(bios); if (strap >= cnt) { nv_error(pfb, "invalid ramcfg strap\n"); return -EINVAL; @@ -179,8 +167,8 @@ nvc0_ram_calc(struct nouveau_fb *pfb, u32 freq) /* lookup memory timings, if bios says they're present */ strap = nv_ro08(bios, ramcfg.data + 0x01); if (strap != 0xff) { - timing.data = nvbios_timing_entry(bios, strap, &ver, - &timing.size); + timing.data = nvbios_timingEe(bios, strap, &ver, &timing.size, + &cnt, &len); if (!timing.data || ver != 0x10 || timing.size < 0x19) { nv_error(pfb, "invalid/missing timing entry\n"); return -EINVAL; diff --git a/drivers/gpu/drm/nouveau/core/subdev/fb/ramnve0.c b/drivers/gpu/drm/nouveau/core/subdev/fb/ramnve0.c index bc86cfd084f6..3257c522a021 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/fb/ramnve0.c +++ b/drivers/gpu/drm/nouveau/core/subdev/fb/ramnve0.c @@ -25,7 +25,6 @@ #include <subdev/gpio.h> #include <subdev/bios.h> -#include <subdev/bios/bit.h> #include <subdev/bios/pll.h> #include <subdev/bios/init.h> #include <subdev/bios/rammap.h> @@ -42,6 +41,14 @@ #include "ramfuc.h" +/* binary driver only executes this path if the condition (a) is true + * for any configuration (combination of rammap+ramcfg+timing) that + * can be reached on a given card. for now, we will execute the branch + * unconditionally in the hope that a "false everywhere" in the bios + * tables doesn't actually mean "don't touch this". + */ +#define NOTE00(a) 1 + struct nve0_ramfuc { struct ramfuc base; @@ -104,7 +111,9 @@ struct nve0_ramfuc { struct ramfuc_reg r_mr[16]; /* MR0 - MR8, MR15 */ struct ramfuc_reg r_0x62c000; + struct ramfuc_reg r_0x10f200; + struct ramfuc_reg r_0x10f210; struct ramfuc_reg r_0x10f310; struct ramfuc_reg r_0x10f314; @@ -118,12 +127,17 @@ struct nve0_ramfuc { struct ramfuc_reg r_0x10f65c; struct ramfuc_reg r_0x10f6bc; struct ramfuc_reg r_0x100710; - struct ramfuc_reg r_0x10f750; + struct ramfuc_reg r_0x100750; }; struct nve0_ram { struct nouveau_ram base; struct nve0_ramfuc fuc; + + u32 parts; + u32 pmask; + u32 pnuts; + int from; int mode; int N1, fN1, M1, P1; @@ -134,17 +148,17 @@ struct nve0_ram { * GDDR5 ******************************************************************************/ static void -train(struct nve0_ramfuc *fuc, u32 magic) +nve0_ram_train(struct nve0_ramfuc *fuc, u32 mask, u32 data) { struct nve0_ram *ram = container_of(fuc, typeof(*ram), fuc); - struct nouveau_fb *pfb = nouveau_fb(ram); - const int mc = nv_rd32(pfb, 0x02243c); - int i; - - ram_mask(fuc, 0x10f910, 0xbc0e0000, magic); - ram_mask(fuc, 0x10f914, 0xbc0e0000, magic); - for (i = 0; i < mc; i++) { - const u32 addr = 0x110974 + (i * 0x1000); + u32 addr = 0x110974, i; + + ram_mask(fuc, 0x10f910, mask, data); + ram_mask(fuc, 0x10f914, mask, data); + + for (i = 0; (data & 0x80000000) && i < ram->parts; addr += 0x1000, i++) { + if (ram->pmask & (1 << i)) + continue; ram_wait(fuc, addr, 0x0000000f, 0x00000000, 500000); } } @@ -199,12 +213,12 @@ r1373f4_init(struct nve0_ramfuc *fuc) } static void -r1373f4_fini(struct nve0_ramfuc *fuc, u32 ramcfg) +r1373f4_fini(struct nve0_ramfuc *fuc) { struct nve0_ram *ram = container_of(fuc, typeof(*ram), fuc); - struct nouveau_bios *bios = nouveau_bios(ram); - u8 v0 = (nv_ro08(bios, ramcfg + 0x03) & 0xc0) >> 6; - u8 v1 = (nv_ro08(bios, ramcfg + 0x03) & 0x30) >> 4; + struct nouveau_ram_data *next = ram->base.next; + u8 v0 = next->bios.ramcfg_11_03_c0; + u8 v1 = next->bios.ramcfg_11_03_30; u32 tmp; tmp = ram_rd32(fuc, 0x1373ec) & ~0x00030000; @@ -220,25 +234,46 @@ r1373f4_fini(struct nve0_ramfuc *fuc, u32 ramcfg) ram_mask(fuc, 0x10f800, 0x00000030, (v0 ^ v1) << 4); } +static void +nve0_ram_nuts(struct nve0_ram *ram, struct ramfuc_reg *reg, + u32 _mask, u32 _data, u32 _copy) +{ + struct nve0_fb_priv *priv = (void *)nouveau_fb(ram); + struct ramfuc *fuc = &ram->fuc.base; + u32 addr = 0x110000 + (reg->addr[0] & 0xfff); + u32 mask = _mask | _copy; + u32 data = (_data & _mask) | (reg->data & _copy); + u32 i; + + for (i = 0; i < 16; i++, addr += 0x1000) { + if (ram->pnuts & (1 << i)) { + u32 prev = nv_rd32(priv, addr); + u32 next = (prev & ~mask) | data; + nouveau_memx_wr32(fuc->memx, addr, next); + } + } +} +#define ram_nuts(s,r,m,d,c) \ + nve0_ram_nuts((s), &(s)->fuc.r_##r, (m), (d), (c)) + static int nve0_ram_calc_gddr5(struct nouveau_fb *pfb, u32 freq) { - struct nouveau_bios *bios = nouveau_bios(pfb); struct nve0_ram *ram = (void *)pfb->ram; struct nve0_ramfuc *fuc = &ram->fuc; - const u32 rammap = ram->base.rammap.data; - const u32 ramcfg = ram->base.ramcfg.data; - const u32 timing = ram->base.timing.data; - int vc = !(nv_ro08(bios, ramcfg + 0x02) & 0x08); - int mv = 1; /*XXX*/ + struct nouveau_ram_data *next = ram->base.next; + int vc = !(next->bios.ramcfg_11_02_08); + int mv = !(next->bios.ramcfg_11_02_04); u32 mask, data; ram_mask(fuc, 0x10f808, 0x40000000, 0x40000000); ram_wr32(fuc, 0x62c000, 0x0f0f0000); /* MR1: turn termination on early, for some reason.. */ - if ((ram->base.mr[1] & 0x03c) != 0x030) + if ((ram->base.mr[1] & 0x03c) != 0x030) { ram_mask(fuc, mr[1], 0x03c, ram->base.mr[1] & 0x03c); + ram_nuts(ram, mr[1], 0x03c, ram->base.mr1_nuts & 0x03c, 0x000); + } if (vc == 1 && ram_have(fuc, gpio2E)) { u32 temp = ram_mask(fuc, gpio2E, 0x3000, fuc->r_func2E[1]); @@ -250,8 +285,7 @@ nve0_ram_calc_gddr5(struct nouveau_fb *pfb, u32 freq) ram_mask(fuc, 0x10f200, 0x00000800, 0x00000000); - ram_mask(fuc, 0x10f914, 0x01020000, 0x000c0000); - ram_mask(fuc, 0x10f910, 0x01020000, 0x000c0000); + nve0_ram_train(fuc, 0x01020000, 0x000c0000); ram_wr32(fuc, 0x10f210, 0x00000000); /* REFRESH_AUTO = 0 */ ram_nsec(fuc, 1000); @@ -280,28 +314,28 @@ nve0_ram_calc_gddr5(struct nouveau_fb *pfb, u32 freq) if (1) { data |= 0x800807e0; - switch (nv_ro08(bios, ramcfg + 0x03) & 0xc0) { - case 0xc0: data &= ~0x00000040; break; - case 0x80: data &= ~0x00000100; break; - case 0x40: data &= ~0x80000000; break; - case 0x00: data &= ~0x00000400; break; + switch (next->bios.ramcfg_11_03_c0) { + case 3: data &= ~0x00000040; break; + case 2: data &= ~0x00000100; break; + case 1: data &= ~0x80000000; break; + case 0: data &= ~0x00000400; break; } - switch (nv_ro08(bios, ramcfg + 0x03) & 0x30) { - case 0x30: data &= ~0x00000020; break; - case 0x20: data &= ~0x00000080; break; - case 0x10: data &= ~0x00080000; break; - case 0x00: data &= ~0x00000200; break; + switch (next->bios.ramcfg_11_03_30) { + case 3: data &= ~0x00000020; break; + case 2: data &= ~0x00000080; break; + case 1: data &= ~0x00080000; break; + case 0: data &= ~0x00000200; break; } } - if (nv_ro08(bios, ramcfg + 0x02) & 0x80) + if (next->bios.ramcfg_11_02_80) mask |= 0x03000000; - if (nv_ro08(bios, ramcfg + 0x02) & 0x40) + if (next->bios.ramcfg_11_02_40) mask |= 0x00002000; - if (nv_ro08(bios, ramcfg + 0x07) & 0x10) + if (next->bios.ramcfg_11_07_10) mask |= 0x00004000; - if (nv_ro08(bios, ramcfg + 0x07) & 0x08) + if (next->bios.ramcfg_11_07_08) mask |= 0x00000003; else { mask |= 0x34000000; @@ -314,18 +348,18 @@ nve0_ram_calc_gddr5(struct nouveau_fb *pfb, u32 freq) if (ram->from == 2 && ram->mode != 2) { ram_mask(fuc, 0x10f808, 0x00080000, 0x00000000); - ram_mask(fuc, 0x10f200, 0x00008000, 0x00008000); + ram_mask(fuc, 0x10f200, 0x18008000, 0x00008000); ram_mask(fuc, 0x10f800, 0x00000000, 0x00000004); ram_mask(fuc, 0x10f830, 0x00008000, 0x01040010); ram_mask(fuc, 0x10f830, 0x01000000, 0x00000000); r1373f4_init(fuc); ram_mask(fuc, 0x1373f0, 0x00000002, 0x00000001); - r1373f4_fini(fuc, ramcfg); + r1373f4_fini(fuc); ram_mask(fuc, 0x10f830, 0x00c00000, 0x00240001); } else if (ram->from != 2 && ram->mode != 2) { r1373f4_init(fuc); - r1373f4_fini(fuc, ramcfg); + r1373f4_fini(fuc); } if (ram_have(fuc, gpioMV)) { @@ -336,49 +370,54 @@ nve0_ram_calc_gddr5(struct nouveau_fb *pfb, u32 freq) } } - if ( (nv_ro08(bios, ramcfg + 0x02) & 0x40) || - (nv_ro08(bios, ramcfg + 0x07) & 0x10)) { + if ( (next->bios.ramcfg_11_02_40) || + (next->bios.ramcfg_11_07_10)) { ram_mask(fuc, 0x132040, 0x00010000, 0x00010000); ram_nsec(fuc, 20000); } if (ram->from != 2 && ram->mode == 2) { + if (0 /*XXX: Titan */) + ram_mask(fuc, 0x10f200, 0x18000000, 0x18000000); ram_mask(fuc, 0x10f800, 0x00000004, 0x00000000); ram_mask(fuc, 0x1373f0, 0x00000000, 0x00000002); ram_mask(fuc, 0x10f830, 0x00800001, 0x00408010); r1373f4_init(fuc); - r1373f4_fini(fuc, ramcfg); + r1373f4_fini(fuc); ram_mask(fuc, 0x10f808, 0x00000000, 0x00080000); ram_mask(fuc, 0x10f200, 0x00808000, 0x00800000); } else if (ram->from == 2 && ram->mode == 2) { ram_mask(fuc, 0x10f800, 0x00000004, 0x00000000); r1373f4_init(fuc); - r1373f4_fini(fuc, ramcfg); + r1373f4_fini(fuc); } if (ram->mode != 2) /*XXX*/ { - if (nv_ro08(bios, ramcfg + 0x07) & 0x40) + if (next->bios.ramcfg_11_07_40) ram_mask(fuc, 0x10f670, 0x80000000, 0x80000000); } - data = (nv_ro08(bios, rammap + 0x11) & 0x0c) >> 2; - ram_wr32(fuc, 0x10f65c, 0x00000011 * data); - ram_wr32(fuc, 0x10f6b8, 0x01010101 * nv_ro08(bios, ramcfg + 0x09)); - ram_wr32(fuc, 0x10f6bc, 0x01010101 * nv_ro08(bios, ramcfg + 0x09)); + ram_wr32(fuc, 0x10f65c, 0x00000011 * next->bios.rammap_11_11_0c); + ram_wr32(fuc, 0x10f6b8, 0x01010101 * next->bios.ramcfg_11_09); + ram_wr32(fuc, 0x10f6bc, 0x01010101 * next->bios.ramcfg_11_09); - data = nv_ro08(bios, ramcfg + 0x04); - if (!(nv_ro08(bios, ramcfg + 0x07) & 0x08)) { - ram_wr32(fuc, 0x10f698, 0x01010101 * data); - ram_wr32(fuc, 0x10f69c, 0x01010101 * data); + if (!next->bios.ramcfg_11_07_08 && !next->bios.ramcfg_11_07_04) { + ram_wr32(fuc, 0x10f698, 0x01010101 * next->bios.ramcfg_11_04); + ram_wr32(fuc, 0x10f69c, 0x01010101 * next->bios.ramcfg_11_04); + } else + if (!next->bios.ramcfg_11_07_08) { + ram_wr32(fuc, 0x10f698, 0x00000000); + ram_wr32(fuc, 0x10f69c, 0x00000000); } if (ram->mode != 2) { - u32 temp = ram_rd32(fuc, 0x10f694) & ~0xff00ff00; - ram_wr32(fuc, 0x10f694, temp | (0x01000100 * data)); + u32 data = 0x01000100 * next->bios.ramcfg_11_04; + ram_nuke(fuc, 0x10f694); + ram_mask(fuc, 0x10f694, 0xff00ff00, data); } - if (ram->mode == 2 && (nv_ro08(bios, ramcfg + 0x08) & 0x10)) + if (ram->mode == 2 && (next->bios.ramcfg_11_08_10)) data = 0x00000080; else data = 0x00000000; @@ -386,19 +425,19 @@ nve0_ram_calc_gddr5(struct nouveau_fb *pfb, u32 freq) mask = 0x00070000; data = 0x00000000; - if (!(nv_ro08(bios, ramcfg + 0x02) & 0x80)) + if (!(next->bios.ramcfg_11_02_80)) data |= 0x03000000; - if (!(nv_ro08(bios, ramcfg + 0x02) & 0x40)) + if (!(next->bios.ramcfg_11_02_40)) data |= 0x00002000; - if (!(nv_ro08(bios, ramcfg + 0x07) & 0x10)) + if (!(next->bios.ramcfg_11_07_10)) data |= 0x00004000; - if (!(nv_ro08(bios, ramcfg + 0x07) & 0x08)) + if (!(next->bios.ramcfg_11_07_08)) data |= 0x00000003; else data |= 0x74000000; ram_mask(fuc, 0x10f824, mask, data); - if (nv_ro08(bios, ramcfg + 0x01) & 0x08) + if (next->bios.ramcfg_11_01_08) data = 0x00000000; else data = 0x00001000; @@ -409,61 +448,90 @@ nve0_ram_calc_gddr5(struct nouveau_fb *pfb, u32 freq) ram_mask(fuc, 0x10f670, 0x80000000, 0x00000000); } - if (nv_ro08(bios, ramcfg + 0x08) & 0x01) + if (next->bios.ramcfg_11_08_01) data = 0x00100000; else data = 0x00000000; ram_mask(fuc, 0x10f82c, 0x00100000, data); data = 0x00000000; - if (nv_ro08(bios, ramcfg + 0x08) & 0x08) + if (next->bios.ramcfg_11_08_08) data |= 0x00002000; - if (nv_ro08(bios, ramcfg + 0x08) & 0x04) + if (next->bios.ramcfg_11_08_04) data |= 0x00001000; - if (nv_ro08(bios, ramcfg + 0x08) & 0x02) + if (next->bios.ramcfg_11_08_02) data |= 0x00004000; ram_mask(fuc, 0x10f830, 0x00007000, data); /* PFB timing */ - ram_mask(fuc, 0x10f248, 0xffffffff, nv_ro32(bios, timing + 0x28)); - ram_mask(fuc, 0x10f290, 0xffffffff, nv_ro32(bios, timing + 0x00)); - ram_mask(fuc, 0x10f294, 0xffffffff, nv_ro32(bios, timing + 0x04)); - ram_mask(fuc, 0x10f298, 0xffffffff, nv_ro32(bios, timing + 0x08)); - ram_mask(fuc, 0x10f29c, 0xffffffff, nv_ro32(bios, timing + 0x0c)); - ram_mask(fuc, 0x10f2a0, 0xffffffff, nv_ro32(bios, timing + 0x10)); - ram_mask(fuc, 0x10f2a4, 0xffffffff, nv_ro32(bios, timing + 0x14)); - ram_mask(fuc, 0x10f2a8, 0xffffffff, nv_ro32(bios, timing + 0x18)); - ram_mask(fuc, 0x10f2ac, 0xffffffff, nv_ro32(bios, timing + 0x1c)); - ram_mask(fuc, 0x10f2cc, 0xffffffff, nv_ro32(bios, timing + 0x20)); - ram_mask(fuc, 0x10f2e8, 0xffffffff, nv_ro32(bios, timing + 0x24)); - - data = (nv_ro08(bios, ramcfg + 0x02) & 0x03) << 8; - if (nv_ro08(bios, ramcfg + 0x01) & 0x10) - data |= 0x70000000; - ram_mask(fuc, 0x10f604, 0x70000300, data); - - data = (nv_ro08(bios, timing + 0x30) & 0x07) << 28; - if (nv_ro08(bios, ramcfg + 0x01) & 0x01) - data |= 0x00000100; - ram_mask(fuc, 0x10f614, 0x70000000, data); - - data = (nv_ro08(bios, timing + 0x30) & 0x07) << 28; - if (nv_ro08(bios, ramcfg + 0x01) & 0x02) - data |= 0x00000100; - ram_mask(fuc, 0x10f610, 0x70000000, data); + ram_mask(fuc, 0x10f248, 0xffffffff, next->bios.timing[10]); + ram_mask(fuc, 0x10f290, 0xffffffff, next->bios.timing[0]); + ram_mask(fuc, 0x10f294, 0xffffffff, next->bios.timing[1]); + ram_mask(fuc, 0x10f298, 0xffffffff, next->bios.timing[2]); + ram_mask(fuc, 0x10f29c, 0xffffffff, next->bios.timing[3]); + ram_mask(fuc, 0x10f2a0, 0xffffffff, next->bios.timing[4]); + ram_mask(fuc, 0x10f2a4, 0xffffffff, next->bios.timing[5]); + ram_mask(fuc, 0x10f2a8, 0xffffffff, next->bios.timing[6]); + ram_mask(fuc, 0x10f2ac, 0xffffffff, next->bios.timing[7]); + ram_mask(fuc, 0x10f2cc, 0xffffffff, next->bios.timing[8]); + ram_mask(fuc, 0x10f2e8, 0xffffffff, next->bios.timing[9]); + + data = mask = 0x00000000; + if (NOTE00(ramcfg_08_20)) { + if (next->bios.ramcfg_11_08_20) + data |= 0x01000000; + mask |= 0x01000000; + } + ram_mask(fuc, 0x10f200, mask, data); + + data = mask = 0x00000000; + if (NOTE00(ramcfg_02_03 != 0)) { + data |= (next->bios.ramcfg_11_02_03) << 8; + mask |= 0x00000300; + } + if (NOTE00(ramcfg_01_10)) { + if (next->bios.ramcfg_11_01_10) + data |= 0x70000000; + mask |= 0x70000000; + } + ram_mask(fuc, 0x10f604, mask, data); + + data = mask = 0x00000000; + if (NOTE00(timing_30_07 != 0)) { + data |= (next->bios.timing_20_30_07) << 28; + mask |= 0x70000000; + } + if (NOTE00(ramcfg_01_01)) { + if (next->bios.ramcfg_11_01_01) + data |= 0x00000100; + mask |= 0x00000100; + } + ram_mask(fuc, 0x10f614, mask, data); + + data = mask = 0x00000000; + if (NOTE00(timing_30_07 != 0)) { + data |= (next->bios.timing_20_30_07) << 28; + mask |= 0x70000000; + } + if (NOTE00(ramcfg_01_02)) { + if (next->bios.ramcfg_11_01_02) + data |= 0x00000100; + mask |= 0x00000100; + } + ram_mask(fuc, 0x10f610, mask, data); mask = 0x33f00000; data = 0x00000000; - if (!(nv_ro08(bios, ramcfg + 0x01) & 0x04)) + if (!(next->bios.ramcfg_11_01_04)) data |= 0x20200000; - if (!(nv_ro08(bios, ramcfg + 0x07) & 0x80)) + if (!(next->bios.ramcfg_11_07_80)) data |= 0x12800000; /*XXX: see note above about there probably being some condition * for the 10f824 stuff that uses ramcfg 3... */ - if ( (nv_ro08(bios, ramcfg + 0x03) & 0xf0)) { - if (nv_ro08(bios, rammap + 0x08) & 0x0c) { - if (!(nv_ro08(bios, ramcfg + 0x07) & 0x80)) + if ( (next->bios.ramcfg_11_03_f0)) { + if (next->bios.rammap_11_08_0c) { + if (!(next->bios.ramcfg_11_07_80)) mask |= 0x00000020; else data |= 0x00000020; @@ -476,49 +544,53 @@ nve0_ram_calc_gddr5(struct nouveau_fb *pfb, u32 freq) ram_mask(fuc, 0x10f808, mask, data); - data = nv_ro08(bios, ramcfg + 0x03) & 0x0f; - ram_wr32(fuc, 0x10f870, 0x11111111 * data); + ram_wr32(fuc, 0x10f870, 0x11111111 * next->bios.ramcfg_11_03_0f); - data = nv_ro08(bios, ramcfg + 0x02) & 0x03; - if (nv_ro08(bios, ramcfg + 0x01) & 0x10) - data |= 0x00000004; - if ((nv_rd32(bios, 0x100770) & 0x00000004) != (data & 0x00000004)) { - ram_wr32(fuc, 0x10f750, 0x04000009); + data = mask = 0x00000000; + if (NOTE00(ramcfg_02_03 != 0)) { + data |= next->bios.ramcfg_11_02_03; + mask |= 0x00000003; + } + if (NOTE00(ramcfg_01_10)) { + if (next->bios.ramcfg_11_01_10) + data |= 0x00000004; + mask |= 0x00000004; + } + + if ((ram_mask(fuc, 0x100770, mask, data) & mask & 4) != (data & 4)) { + ram_mask(fuc, 0x100750, 0x00000008, 0x00000008); ram_wr32(fuc, 0x100710, 0x00000000); ram_wait(fuc, 0x100710, 0x80000000, 0x80000000, 200000); } - ram_mask(fuc, 0x100770, 0x00000007, data); - data = (nv_ro08(bios, timing + 0x30) & 0x07) << 8; - if (nv_ro08(bios, ramcfg + 0x01) & 0x01) + data = (next->bios.timing_20_30_07) << 8; + if (next->bios.ramcfg_11_01_01) data |= 0x80000000; ram_mask(fuc, 0x100778, 0x00000700, data); - data = nv_ro16(bios, timing + 0x2c); - ram_mask(fuc, 0x10f250, 0x000003f0, (data & 0x003f) << 4); - ram_mask(fuc, 0x10f24c, 0x7f000000, (data & 0x1fc0) << 18); - - data = nv_ro08(bios, timing + 0x30); - ram_mask(fuc, 0x10f224, 0x001f0000, (data & 0xf8) << 13); + ram_mask(fuc, 0x10f250, 0x000003f0, next->bios.timing_20_2c_003f << 4); + data = (next->bios.timing[10] & 0x7f000000) >> 24; + if (data < next->bios.timing_20_2c_1fc0) + data = next->bios.timing_20_2c_1fc0; + ram_mask(fuc, 0x10f24c, 0x7f000000, data << 24); + ram_mask(fuc, 0x10f224, 0x001f0000, next->bios.timing_20_30_f8 << 16); - data = nv_ro16(bios, timing + 0x31); - ram_mask(fuc, 0x10fec4, 0x041e0f07, (data & 0x0800) << 15 | - (data & 0x0780) << 10 | - (data & 0x0078) << 5 | - (data & 0x0007)); - ram_mask(fuc, 0x10fec8, 0x00000027, (data & 0x8000) >> 10 | - (data & 0x7000) >> 12); + ram_mask(fuc, 0x10fec4, 0x041e0f07, next->bios.timing_20_31_0800 << 26 | + next->bios.timing_20_31_0780 << 17 | + next->bios.timing_20_31_0078 << 8 | + next->bios.timing_20_31_0007); + ram_mask(fuc, 0x10fec8, 0x00000027, next->bios.timing_20_31_8000 << 5 | + next->bios.timing_20_31_7000); ram_wr32(fuc, 0x10f090, 0x4000007e); - ram_nsec(fuc, 1000); + ram_nsec(fuc, 2000); ram_wr32(fuc, 0x10f314, 0x00000001); /* PRECHARGE */ ram_wr32(fuc, 0x10f310, 0x00000001); /* REFRESH */ - ram_nsec(fuc, 2000); ram_wr32(fuc, 0x10f210, 0x80000000); /* REFRESH_AUTO = 1 */ - if ((nv_ro08(bios, ramcfg + 0x08) & 0x10) && (ram->mode == 2) /*XXX*/) { + if ((next->bios.ramcfg_11_08_10) && (ram->mode == 2) /*XXX*/) { u32 temp = ram_mask(fuc, 0x10f294, 0xff000000, 0x24000000); - train(fuc, 0xa4010000); /*XXX*/ + nve0_ram_train(fuc, 0xbc0e0000, 0xa4010000); /*XXX*/ ram_nsec(fuc, 1000); ram_wr32(fuc, 0x10f294, temp); } @@ -528,7 +600,7 @@ nve0_ram_calc_gddr5(struct nouveau_fb *pfb, u32 freq) ram_mask(fuc, mr[8], 0xfff, ram->base.mr[8]); ram_nsec(fuc, 1000); ram_mask(fuc, mr[1], 0xfff, ram->base.mr[1]); - ram_mask(fuc, mr[5], 0xfff, ram->base.mr[5]); + ram_mask(fuc, mr[5], 0xfff, ram->base.mr[5] & ~0x004); /* LP3 later */ ram_mask(fuc, mr[6], 0xfff, ram->base.mr[6]); ram_mask(fuc, mr[7], 0xfff, ram->base.mr[7]); @@ -544,12 +616,13 @@ nve0_ram_calc_gddr5(struct nouveau_fb *pfb, u32 freq) ram_wr32(fuc, 0x10f318, 0x00000001); /* NOP? */ ram_mask(fuc, 0x10f200, 0x80000000, 0x00000000); ram_nsec(fuc, 1000); + ram_nuts(ram, 0x10f200, 0x18808800, 0x00000000, 0x18808800); data = ram_rd32(fuc, 0x10f978); data &= ~0x00046144; data |= 0x0000000b; - if (!(nv_ro08(bios, ramcfg + 0x07) & 0x08)) { - if (!(nv_ro08(bios, ramcfg + 0x07) & 0x04)) + if (!(next->bios.ramcfg_11_07_08)) { + if (!(next->bios.ramcfg_11_07_04)) data |= 0x0000200c; else data |= 0x00000000; @@ -563,44 +636,43 @@ nve0_ram_calc_gddr5(struct nouveau_fb *pfb, u32 freq) ram_wr32(fuc, 0x10f830, data); } - if (!(nv_ro08(bios, ramcfg + 0x07) & 0x08)) { + if (!(next->bios.ramcfg_11_07_08)) { data = 0x88020000; - if ( (nv_ro08(bios, ramcfg + 0x07) & 0x04)) + if ( (next->bios.ramcfg_11_07_04)) data |= 0x10000000; - if (!(nv_ro08(bios, rammap + 0x08) & 0x10)) + if (!(next->bios.rammap_11_08_10)) data |= 0x00080000; } else { data = 0xa40e0000; } - train(fuc, data); - ram_nsec(fuc, 1000); + nve0_ram_train(fuc, 0xbc0f0000, data); + if (1) /* XXX: not always? */ + ram_nsec(fuc, 1000); if (ram->mode == 2) { /*XXX*/ ram_mask(fuc, 0x10f800, 0x00000004, 0x00000004); } - /* MR5: (re)enable LP3 if necessary - * XXX: need to find the switch, keeping off for now - */ - ram_mask(fuc, mr[5], 0x00000004, 0x00000000); + /* LP3 */ + if (ram_mask(fuc, mr[5], 0x004, ram->base.mr[5]) != ram->base.mr[5]) + ram_nsec(fuc, 1000); if (ram->mode != 2) { ram_mask(fuc, 0x10f830, 0x01000000, 0x01000000); ram_mask(fuc, 0x10f830, 0x01000000, 0x00000000); } - if (nv_ro08(bios, ramcfg + 0x07) & 0x02) { - ram_mask(fuc, 0x10f910, 0x80020000, 0x01000000); - ram_mask(fuc, 0x10f914, 0x80020000, 0x01000000); - } + if (next->bios.ramcfg_11_07_02) + nve0_ram_train(fuc, 0x80020000, 0x01000000); ram_wr32(fuc, 0x62c000, 0x0f0f0f00); - if (nv_ro08(bios, rammap + 0x08) & 0x01) + if (next->bios.rammap_11_08_01) data = 0x00000800; else data = 0x00000000; ram_mask(fuc, 0x10f200, 0x00000800, data); + ram_nuts(ram, 0x10f200, 0x18808800, data, 0x18808800); return 0; } @@ -611,17 +683,14 @@ nve0_ram_calc_gddr5(struct nouveau_fb *pfb, u32 freq) static int nve0_ram_calc_sddr3(struct nouveau_fb *pfb, u32 freq) { - struct nouveau_bios *bios = nouveau_bios(pfb); struct nve0_ram *ram = (void *)pfb->ram; struct nve0_ramfuc *fuc = &ram->fuc; const u32 rcoef = (( ram->P1 << 16) | (ram->N1 << 8) | ram->M1); const u32 runk0 = ram->fN1 << 16; const u32 runk1 = ram->fN1; - const u32 rammap = ram->base.rammap.data; - const u32 ramcfg = ram->base.ramcfg.data; - const u32 timing = ram->base.timing.data; - int vc = !(nv_ro08(bios, ramcfg + 0x02) & 0x08); - int mv = 1; /*XXX*/ + struct nouveau_ram_data *next = ram->base.next; + int vc = !(next->bios.ramcfg_11_02_08); + int mv = !(next->bios.ramcfg_11_02_04); u32 mask, data; ram_mask(fuc, 0x10f808, 0x40000000, 0x40000000); @@ -636,7 +705,7 @@ nve0_ram_calc_sddr3(struct nouveau_fb *pfb, u32 freq) } ram_mask(fuc, 0x10f200, 0x00000800, 0x00000000); - if ((nv_ro08(bios, ramcfg + 0x03) & 0xf0)) + if ((next->bios.ramcfg_11_03_f0)) ram_mask(fuc, 0x10f808, 0x04000000, 0x04000000); ram_wr32(fuc, 0x10f314, 0x00000001); /* PRECHARGE */ @@ -661,28 +730,28 @@ nve0_ram_calc_sddr3(struct nouveau_fb *pfb, u32 freq) if (1) { mask |= 0x800807e0; data |= 0x800807e0; - switch (nv_ro08(bios, ramcfg + 0x03) & 0xc0) { - case 0xc0: data &= ~0x00000040; break; - case 0x80: data &= ~0x00000100; break; - case 0x40: data &= ~0x80000000; break; - case 0x00: data &= ~0x00000400; break; + switch (next->bios.ramcfg_11_03_c0) { + case 3: data &= ~0x00000040; break; + case 2: data &= ~0x00000100; break; + case 1: data &= ~0x80000000; break; + case 0: data &= ~0x00000400; break; } - switch (nv_ro08(bios, ramcfg + 0x03) & 0x30) { - case 0x30: data &= ~0x00000020; break; - case 0x20: data &= ~0x00000080; break; - case 0x10: data &= ~0x00080000; break; - case 0x00: data &= ~0x00000200; break; + switch (next->bios.ramcfg_11_03_30) { + case 3: data &= ~0x00000020; break; + case 2: data &= ~0x00000080; break; + case 1: data &= ~0x00080000; break; + case 0: data &= ~0x00000200; break; } } - if (nv_ro08(bios, ramcfg + 0x02) & 0x80) + if (next->bios.ramcfg_11_02_80) mask |= 0x03000000; - if (nv_ro08(bios, ramcfg + 0x02) & 0x40) + if (next->bios.ramcfg_11_02_40) mask |= 0x00002000; - if (nv_ro08(bios, ramcfg + 0x07) & 0x10) + if (next->bios.ramcfg_11_07_10) mask |= 0x00004000; - if (nv_ro08(bios, ramcfg + 0x07) & 0x08) + if (next->bios.ramcfg_11_07_08) mask |= 0x00000003; else mask |= 0x14000000; @@ -692,7 +761,7 @@ nve0_ram_calc_sddr3(struct nouveau_fb *pfb, u32 freq) ram_mask(fuc, 0x1373f4, 0x00000000, 0x00010010); data = ram_rd32(fuc, 0x1373ec) & ~0x00030000; - data |= (nv_ro08(bios, ramcfg + 0x03) & 0x30) << 12; + data |= (next->bios.ramcfg_11_03_30) << 12; ram_wr32(fuc, 0x1373ec, data); ram_mask(fuc, 0x1373f4, 0x00000003, 0x00000000); ram_mask(fuc, 0x1373f4, 0x00000010, 0x00000000); @@ -724,68 +793,67 @@ nve0_ram_calc_sddr3(struct nouveau_fb *pfb, u32 freq) } } - if ( (nv_ro08(bios, ramcfg + 0x02) & 0x40) || - (nv_ro08(bios, ramcfg + 0x07) & 0x10)) { + if ( (next->bios.ramcfg_11_02_40) || + (next->bios.ramcfg_11_07_10)) { ram_mask(fuc, 0x132040, 0x00010000, 0x00010000); ram_nsec(fuc, 20000); } if (ram->mode != 2) /*XXX*/ { - if (nv_ro08(bios, ramcfg + 0x07) & 0x40) + if (next->bios.ramcfg_11_07_40) ram_mask(fuc, 0x10f670, 0x80000000, 0x80000000); } - data = (nv_ro08(bios, rammap + 0x11) & 0x0c) >> 2; - ram_wr32(fuc, 0x10f65c, 0x00000011 * data); - ram_wr32(fuc, 0x10f6b8, 0x01010101 * nv_ro08(bios, ramcfg + 0x09)); - ram_wr32(fuc, 0x10f6bc, 0x01010101 * nv_ro08(bios, ramcfg + 0x09)); + ram_wr32(fuc, 0x10f65c, 0x00000011 * next->bios.rammap_11_11_0c); + ram_wr32(fuc, 0x10f6b8, 0x01010101 * next->bios.ramcfg_11_09); + ram_wr32(fuc, 0x10f6bc, 0x01010101 * next->bios.ramcfg_11_09); mask = 0x00010000; data = 0x00000000; - if (!(nv_ro08(bios, ramcfg + 0x02) & 0x80)) + if (!(next->bios.ramcfg_11_02_80)) data |= 0x03000000; - if (!(nv_ro08(bios, ramcfg + 0x02) & 0x40)) + if (!(next->bios.ramcfg_11_02_40)) data |= 0x00002000; - if (!(nv_ro08(bios, ramcfg + 0x07) & 0x10)) + if (!(next->bios.ramcfg_11_07_10)) data |= 0x00004000; - if (!(nv_ro08(bios, ramcfg + 0x07) & 0x08)) + if (!(next->bios.ramcfg_11_07_08)) data |= 0x00000003; else data |= 0x14000000; ram_mask(fuc, 0x10f824, mask, data); ram_nsec(fuc, 1000); - if (nv_ro08(bios, ramcfg + 0x08) & 0x01) + if (next->bios.ramcfg_11_08_01) data = 0x00100000; else data = 0x00000000; ram_mask(fuc, 0x10f82c, 0x00100000, data); /* PFB timing */ - ram_mask(fuc, 0x10f248, 0xffffffff, nv_ro32(bios, timing + 0x28)); - ram_mask(fuc, 0x10f290, 0xffffffff, nv_ro32(bios, timing + 0x00)); - ram_mask(fuc, 0x10f294, 0xffffffff, nv_ro32(bios, timing + 0x04)); - ram_mask(fuc, 0x10f298, 0xffffffff, nv_ro32(bios, timing + 0x08)); - ram_mask(fuc, 0x10f29c, 0xffffffff, nv_ro32(bios, timing + 0x0c)); - ram_mask(fuc, 0x10f2a0, 0xffffffff, nv_ro32(bios, timing + 0x10)); - ram_mask(fuc, 0x10f2a4, 0xffffffff, nv_ro32(bios, timing + 0x14)); - ram_mask(fuc, 0x10f2a8, 0xffffffff, nv_ro32(bios, timing + 0x18)); - ram_mask(fuc, 0x10f2ac, 0xffffffff, nv_ro32(bios, timing + 0x1c)); - ram_mask(fuc, 0x10f2cc, 0xffffffff, nv_ro32(bios, timing + 0x20)); - ram_mask(fuc, 0x10f2e8, 0xffffffff, nv_ro32(bios, timing + 0x24)); + ram_mask(fuc, 0x10f248, 0xffffffff, next->bios.timing[10]); + ram_mask(fuc, 0x10f290, 0xffffffff, next->bios.timing[0]); + ram_mask(fuc, 0x10f294, 0xffffffff, next->bios.timing[1]); + ram_mask(fuc, 0x10f298, 0xffffffff, next->bios.timing[2]); + ram_mask(fuc, 0x10f29c, 0xffffffff, next->bios.timing[3]); + ram_mask(fuc, 0x10f2a0, 0xffffffff, next->bios.timing[4]); + ram_mask(fuc, 0x10f2a4, 0xffffffff, next->bios.timing[5]); + ram_mask(fuc, 0x10f2a8, 0xffffffff, next->bios.timing[6]); + ram_mask(fuc, 0x10f2ac, 0xffffffff, next->bios.timing[7]); + ram_mask(fuc, 0x10f2cc, 0xffffffff, next->bios.timing[8]); + ram_mask(fuc, 0x10f2e8, 0xffffffff, next->bios.timing[9]); mask = 0x33f00000; data = 0x00000000; - if (!(nv_ro08(bios, ramcfg + 0x01) & 0x04)) + if (!(next->bios.ramcfg_11_01_04)) data |= 0x20200000; - if (!(nv_ro08(bios, ramcfg + 0x07) & 0x80)) + if (!(next->bios.ramcfg_11_07_80)) data |= 0x12800000; /*XXX: see note above about there probably being some condition * for the 10f824 stuff that uses ramcfg 3... */ - if ( (nv_ro08(bios, ramcfg + 0x03) & 0xf0)) { - if (nv_ro08(bios, rammap + 0x08) & 0x0c) { - if (!(nv_ro08(bios, ramcfg + 0x07) & 0x80)) + if ( (next->bios.ramcfg_11_03_f0)) { + if (next->bios.rammap_11_08_0c) { + if (!(next->bios.ramcfg_11_07_80)) mask |= 0x00000020; else data |= 0x00000020; @@ -799,21 +867,16 @@ nve0_ram_calc_sddr3(struct nouveau_fb *pfb, u32 freq) ram_mask(fuc, 0x10f808, mask, data); - data = nv_ro08(bios, ramcfg + 0x03) & 0x0f; - ram_wr32(fuc, 0x10f870, 0x11111111 * data); + ram_wr32(fuc, 0x10f870, 0x11111111 * next->bios.ramcfg_11_03_0f); - data = nv_ro16(bios, timing + 0x2c); - ram_mask(fuc, 0x10f250, 0x000003f0, (data & 0x003f) << 4); + ram_mask(fuc, 0x10f250, 0x000003f0, next->bios.timing_20_2c_003f << 4); - if (((nv_ro32(bios, timing + 0x2c) & 0x00001fc0) >> 6) > - ((nv_ro32(bios, timing + 0x28) & 0x7f000000) >> 24)) - data = (nv_ro32(bios, timing + 0x2c) & 0x00001fc0) >> 6; - else - data = (nv_ro32(bios, timing + 0x28) & 0x1f000000) >> 24; + data = (next->bios.timing[10] & 0x7f000000) >> 24; + if (data < next->bios.timing_20_2c_1fc0) + data = next->bios.timing_20_2c_1fc0; ram_mask(fuc, 0x10f24c, 0x7f000000, data << 24); - data = nv_ro08(bios, timing + 0x30); - ram_mask(fuc, 0x10f224, 0x001f0000, (data & 0xf8) << 13); + ram_mask(fuc, 0x10f224, 0x001f0000, next->bios.timing_20_30_f8); ram_wr32(fuc, 0x10f090, 0x4000007f); ram_nsec(fuc, 1000); @@ -855,7 +918,7 @@ nve0_ram_calc_sddr3(struct nouveau_fb *pfb, u32 freq) ram_wr32(fuc, 0x62c000, 0x0f0f0f00); - if (nv_ro08(bios, rammap + 0x08) & 0x01) + if (next->bios.rammap_11_08_01) data = 0x00000800; else data = 0x00000000; @@ -868,21 +931,18 @@ nve0_ram_calc_sddr3(struct nouveau_fb *pfb, u32 freq) ******************************************************************************/ static int -nve0_ram_calc(struct nouveau_fb *pfb, u32 freq) +nve0_ram_calc_data(struct nouveau_fb *pfb, u32 freq, + struct nouveau_ram_data *data) { struct nouveau_bios *bios = nouveau_bios(pfb); struct nve0_ram *ram = (void *)pfb->ram; - struct nve0_ramfuc *fuc = &ram->fuc; - struct bit_entry M; - int ret, refclk, strap, i; - u32 data; - u8 cnt; + u8 strap, cnt, len; /* lookup memory config data relevant to the target frequency */ - ram->base.rammap.data = nvbios_rammap_match(bios, freq / 1000, - &ram->base.rammap.version, - &ram->base.rammap.size, &cnt, - &ram->base.ramcfg.size); + ram->base.rammap.data = nvbios_rammapEp(bios, freq / 1000, + &ram->base.rammap.version, + &ram->base.rammap.size, + &cnt, &len, &data->bios); if (!ram->base.rammap.data || ram->base.rammap.version != 0x11 || ram->base.rammap.size < 0x09) { nv_error(pfb, "invalid/missing rammap entry\n"); @@ -890,24 +950,13 @@ nve0_ram_calc(struct nouveau_fb *pfb, u32 freq) } /* locate specific data set for the attached memory */ - if (bit_entry(bios, 'M', &M) || M.version != 2 || M.length < 3) { - nv_error(pfb, "invalid/missing memory table\n"); - return -EINVAL; - } - - strap = (nv_rd32(pfb, 0x101000) & 0x0000003c) >> 2; - data = nv_ro16(bios, M.offset + 1); - if (data) - strap = nv_ro08(bios, data + strap); - - if (strap >= cnt) { - nv_error(pfb, "invalid ramcfg strap\n"); - return -EINVAL; - } - - ram->base.ramcfg.version = ram->base.rammap.version; - ram->base.ramcfg.data = ram->base.rammap.data + ram->base.rammap.size + - (ram->base.ramcfg.size * strap); + ram->base.ramcfg.data = nvbios_rammapSp(bios, ram->base.rammap.data, + ram->base.rammap.version, + ram->base.rammap.size, cnt, len, + nvbios_ramcfg_index(bios), + &ram->base.ramcfg.version, + &ram->base.ramcfg.size, + &data->bios); if (!ram->base.ramcfg.data || ram->base.ramcfg.version != 0x11 || ram->base.ramcfg.size < 0x08) { nv_error(pfb, "invalid/missing ramcfg entry\n"); @@ -918,9 +967,9 @@ nve0_ram_calc(struct nouveau_fb *pfb, u32 freq) strap = nv_ro08(bios, ram->base.ramcfg.data + 0x00); if (strap != 0xff) { ram->base.timing.data = - nvbios_timing_entry(bios, strap, - &ram->base.timing.version, - &ram->base.timing.size); + nvbios_timingEp(bios, strap, &ram->base.timing.version, + &ram->base.timing.size, &cnt, &len, + &data->bios); if (!ram->base.timing.data || ram->base.timing.version != 0x20 || ram->base.timing.size < 0x33) { @@ -931,11 +980,23 @@ nve0_ram_calc(struct nouveau_fb *pfb, u32 freq) ram->base.timing.data = 0; } + data->freq = freq; + return 0; +} + +static int +nve0_ram_calc_xits(struct nouveau_fb *pfb, struct nouveau_ram_data *next) +{ + struct nve0_ram *ram = (void *)pfb->ram; + struct nve0_ramfuc *fuc = &ram->fuc; + int refclk, i; + int ret; + ret = ram_init(fuc, pfb); if (ret) return ret; - ram->mode = (freq > fuc->refpll.vco1.max_freq) ? 2 : 1; + ram->mode = (next->freq > fuc->refpll.vco1.max_freq) ? 2 : 1; ram->from = ram_rd32(fuc, 0x1373f4) & 0x0000000f; /* XXX: this is *not* what nvidia do. on fermi nvidia generally @@ -946,7 +1007,7 @@ nve0_ram_calc(struct nouveau_fb *pfb, u32 freq) * so far, i've seen very weird values being chosen by nvidia on * kepler boards, no idea how/why they're chosen. */ - refclk = freq; + refclk = next->freq; if (ram->mode == 2) refclk = fuc->mempll.refclk; @@ -968,7 +1029,7 @@ nve0_ram_calc(struct nouveau_fb *pfb, u32 freq) fuc->mempll.min_p = 1; fuc->mempll.max_p = 2; - ret = nva3_pll_calc(nv_subdev(pfb), &fuc->mempll, freq, + ret = nva3_pll_calc(nv_subdev(pfb), &fuc->mempll, next->freq, &ram->N2, NULL, &ram->M2, &ram->P2); if (ret <= 0) { nv_error(pfb, "unable to calc mempll\n"); @@ -980,17 +1041,18 @@ nve0_ram_calc(struct nouveau_fb *pfb, u32 freq) if (ram_have(fuc, mr[i])) ram->base.mr[i] = ram_rd32(fuc, mr[i]); } + ram->base.freq = next->freq; switch (ram->base.type) { case NV_MEM_TYPE_DDR3: ret = nouveau_sddr3_calc(&ram->base); if (ret == 0) - ret = nve0_ram_calc_sddr3(pfb, freq); + ret = nve0_ram_calc_sddr3(pfb, next->freq); break; case NV_MEM_TYPE_GDDR5: - ret = nouveau_gddr5_calc(&ram->base); + ret = nouveau_gddr5_calc(&ram->base, ram->pnuts != 0); if (ret == 0) - ret = nve0_ram_calc_gddr5(pfb, freq); + ret = nve0_ram_calc_gddr5(pfb, next->freq); break; default: ret = -ENOSYS; @@ -1001,13 +1063,55 @@ nve0_ram_calc(struct nouveau_fb *pfb, u32 freq) } static int +nve0_ram_calc(struct nouveau_fb *pfb, u32 freq) +{ + struct nouveau_clock *clk = nouveau_clock(pfb); + struct nve0_ram *ram = (void *)pfb->ram; + struct nouveau_ram_data *xits = &ram->base.xition; + struct nouveau_ram_data *copy; + int ret; + + if (ram->base.next == NULL) { + ret = nve0_ram_calc_data(pfb, clk->read(clk, nv_clk_src_mem), + &ram->base.former); + if (ret) + return ret; + + ret = nve0_ram_calc_data(pfb, freq, &ram->base.target); + if (ret) + return ret; + + if (ram->base.target.freq < ram->base.former.freq) { + *xits = ram->base.target; + copy = &ram->base.former; + } else { + *xits = ram->base.former; + copy = &ram->base.target; + } + + xits->bios.ramcfg_11_02_04 = copy->bios.ramcfg_11_02_04; + xits->bios.ramcfg_11_02_03 = copy->bios.ramcfg_11_02_03; + xits->bios.timing_20_30_07 = copy->bios.timing_20_30_07; + + ram->base.next = &ram->base.target; + if (memcmp(xits, &ram->base.former, sizeof(xits->bios))) + ram->base.next = &ram->base.xition; + } else { + BUG_ON(ram->base.next != &ram->base.xition); + ram->base.next = &ram->base.target; + } + + return nve0_ram_calc_xits(pfb, ram->base.next); +} + +static int nve0_ram_prog(struct nouveau_fb *pfb) { struct nouveau_device *device = nv_device(pfb); struct nve0_ram *ram = (void *)pfb->ram; struct nve0_ramfuc *fuc = &ram->fuc; ram_exec(fuc, nouveau_boolopt(device->cfgopt, "NvMemExec", false)); - return 0; + return (ram->base.next == &ram->base.xition); } static void @@ -1015,6 +1119,7 @@ nve0_ram_tidy(struct nouveau_fb *pfb) { struct nve0_ram *ram = (void *)pfb->ram; struct nve0_ramfuc *fuc = &ram->fuc; + ram->base.next = NULL; ram_exec(fuc, false); } @@ -1055,7 +1160,7 @@ nve0_ram_init(struct nouveau_object *object) * binary driver skips the one that's already been setup by * the init tables. */ - data = nvbios_rammap_table(bios, &ver, &hdr, &cnt, &len, &snr, &ssz); + data = nvbios_rammapTe(bios, &ver, &hdr, &cnt, &len, &snr, &ssz); if (!data || hdr < 0x15) return -EINVAL; @@ -1073,6 +1178,7 @@ nve0_ram_init(struct nouveau_object *object) data += 4; } nv_wr32(pfb, 0x10f65c, save); + nv_mask(pfb, 0x10f584, 0x11000000, 0x00000000); switch (ram->base.type) { case NV_MEM_TYPE_GDDR5: @@ -1117,7 +1223,8 @@ nve0_ram_ctor(struct nouveau_object *parent, struct nouveau_object *engine, struct nouveau_gpio *gpio = nouveau_gpio(pfb); struct dcb_gpio_func func; struct nve0_ram *ram; - int ret; + int ret, i; + u32 tmp; ret = nvc0_ram_create(parent, engine, oclass, &ram); *pobject = nv_object(ram); @@ -1136,6 +1243,25 @@ nve0_ram_ctor(struct nouveau_object *parent, struct nouveau_object *engine, break; } + /* calculate a mask of differently configured memory partitions, + * because, of course reclocking wasn't complicated enough + * already without having to treat some of them differently to + * the others.... + */ + ram->parts = nv_rd32(pfb, 0x022438); + ram->pmask = nv_rd32(pfb, 0x022554); + ram->pnuts = 0; + for (i = 0, tmp = 0; i < ram->parts; i++) { + if (!(ram->pmask & (1 << i))) { + u32 cfg1 = nv_rd32(pfb, 0x110204 + (i * 0x1000)); + if (tmp && tmp != cfg1) { + ram->pnuts |= (1 << i); + continue; + } + tmp = cfg1; + } + } + // parse bios data for both pll's ret = nvbios_pll_parse(bios, 0x0c, &ram->fuc.refpll); if (ret) { @@ -1248,7 +1374,7 @@ nve0_ram_ctor(struct nouveau_object *parent, struct nouveau_object *engine, ram->fuc.r_0x10f65c = ramfuc_reg(0x10f65c); ram->fuc.r_0x10f6bc = ramfuc_reg(0x10f6bc); ram->fuc.r_0x100710 = ramfuc_reg(0x100710); - ram->fuc.r_0x10f750 = ramfuc_reg(0x10f750); + ram->fuc.r_0x100750 = ramfuc_reg(0x100750); return 0; } diff --git a/drivers/gpu/drm/nouveau/core/subdev/i2c/base.c b/drivers/gpu/drm/nouveau/core/subdev/i2c/base.c index 041fd5edaebf..c33c03d2f4af 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/i2c/base.c +++ b/drivers/gpu/drm/nouveau/core/subdev/i2c/base.c @@ -197,7 +197,7 @@ static int nouveau_i2c_identify(struct nouveau_i2c *i2c, int index, const char *what, struct nouveau_i2c_board_info *info, bool (*match)(struct nouveau_i2c_port *, - struct i2c_board_info *)) + struct i2c_board_info *, void *), void *data) { struct nouveau_i2c_port *port = nouveau_i2c_find(i2c, index); int i; @@ -221,7 +221,7 @@ nouveau_i2c_identify(struct nouveau_i2c *i2c, int index, const char *what, } if (nv_probe_i2c(port, info[i].dev.addr) && - (!match || match(port, &info[i].dev))) { + (!match || match(port, &info[i].dev, data))) { nv_info(i2c, "detected %s: %s\n", what, info[i].dev.type); return i; diff --git a/drivers/gpu/drm/nouveau/core/subdev/instmem/base.c b/drivers/gpu/drm/nouveau/core/subdev/instmem/base.c index 6565f3dbbe04..14706d9842ca 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/instmem/base.c +++ b/drivers/gpu/drm/nouveau/core/subdev/instmem/base.c @@ -22,7 +22,24 @@ * Authors: Ben Skeggs */ -#include <subdev/instmem.h> +#include "priv.h" + +/****************************************************************************** + * instmem object base implementation + *****************************************************************************/ + +void +_nouveau_instobj_dtor(struct nouveau_object *object) +{ + struct nouveau_instmem *imem = (void *)object->engine; + struct nouveau_instobj *iobj = (void *)object; + + mutex_lock(&nv_subdev(imem)->mutex); + list_del(&iobj->head); + mutex_unlock(&nv_subdev(imem)->mutex); + + return nouveau_object_destroy(&iobj->base); +} int nouveau_instobj_create_(struct nouveau_object *parent, @@ -46,73 +63,26 @@ nouveau_instobj_create_(struct nouveau_object *parent, return 0; } -void -nouveau_instobj_destroy(struct nouveau_instobj *iobj) -{ - struct nouveau_subdev *subdev = nv_subdev(iobj->base.engine); +/****************************************************************************** + * instmem subdev base implementation + *****************************************************************************/ - mutex_lock(&subdev->mutex); - list_del(&iobj->head); - mutex_unlock(&subdev->mutex); - - return nouveau_object_destroy(&iobj->base); -} - -void -_nouveau_instobj_dtor(struct nouveau_object *object) +static int +nouveau_instmem_alloc(struct nouveau_instmem *imem, + struct nouveau_object *parent, u32 size, u32 align, + struct nouveau_object **pobject) { - struct nouveau_instobj *iobj = (void *)object; - return nouveau_instobj_destroy(iobj); + struct nouveau_object *engine = nv_object(imem); + struct nouveau_instmem_impl *impl = (void *)engine->oclass; + struct nouveau_instobj_args args = { .size = size, .align = align }; + return nouveau_object_ctor(parent, engine, impl->instobj, &args, + sizeof(args), pobject); } int -nouveau_instmem_create_(struct nouveau_object *parent, - struct nouveau_object *engine, - struct nouveau_oclass *oclass, - int length, void **pobject) -{ - struct nouveau_instmem *imem; - int ret; - - ret = nouveau_subdev_create_(parent, engine, oclass, 0, - "INSTMEM", "instmem", length, pobject); - imem = *pobject; - if (ret) - return ret; - - INIT_LIST_HEAD(&imem->list); - return 0; -} - -int -nouveau_instmem_init(struct nouveau_instmem *imem) -{ - struct nouveau_instobj *iobj; - int ret, i; - - ret = nouveau_subdev_init(&imem->base); - if (ret) - return ret; - - mutex_lock(&imem->base.mutex); - - list_for_each_entry(iobj, &imem->list, head) { - if (iobj->suspend) { - for (i = 0; i < iobj->size; i += 4) - nv_wo32(iobj, i, iobj->suspend[i / 4]); - vfree(iobj->suspend); - iobj->suspend = NULL; - } - } - - mutex_unlock(&imem->base.mutex); - - return 0; -} - -int -nouveau_instmem_fini(struct nouveau_instmem *imem, bool suspend) +_nouveau_instmem_fini(struct nouveau_object *object, bool suspend) { + struct nouveau_instmem *imem = (void *)object; struct nouveau_instobj *iobj; int i, ret = 0; @@ -143,12 +113,45 @@ int _nouveau_instmem_init(struct nouveau_object *object) { struct nouveau_instmem *imem = (void *)object; - return nouveau_instmem_init(imem); + struct nouveau_instobj *iobj; + int ret, i; + + ret = nouveau_subdev_init(&imem->base); + if (ret) + return ret; + + mutex_lock(&imem->base.mutex); + + list_for_each_entry(iobj, &imem->list, head) { + if (iobj->suspend) { + for (i = 0; i < iobj->size; i += 4) + nv_wo32(iobj, i, iobj->suspend[i / 4]); + vfree(iobj->suspend); + iobj->suspend = NULL; + } + } + + mutex_unlock(&imem->base.mutex); + + return 0; } int -_nouveau_instmem_fini(struct nouveau_object *object, bool suspend) +nouveau_instmem_create_(struct nouveau_object *parent, + struct nouveau_object *engine, + struct nouveau_oclass *oclass, + int length, void **pobject) { - struct nouveau_instmem *imem = (void *)object; - return nouveau_instmem_fini(imem, suspend); + struct nouveau_instmem *imem; + int ret; + + ret = nouveau_subdev_create_(parent, engine, oclass, 0, + "INSTMEM", "instmem", length, pobject); + imem = *pobject; + if (ret) + return ret; + + INIT_LIST_HEAD(&imem->list); + imem->alloc = nouveau_instmem_alloc; + return 0; } diff --git a/drivers/gpu/drm/nouveau/core/subdev/instmem/nv04.c b/drivers/gpu/drm/nouveau/core/subdev/instmem/nv04.c index 795393d7b2f5..7b64befee48f 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/instmem/nv04.c +++ b/drivers/gpu/drm/nouveau/core/subdev/instmem/nv04.c @@ -22,10 +22,35 @@ * Authors: Ben Skeggs */ -#include <subdev/fb.h> - #include "nv04.h" +/****************************************************************************** + * instmem object implementation + *****************************************************************************/ + +static u32 +nv04_instobj_rd32(struct nouveau_object *object, u64 addr) +{ + struct nv04_instobj_priv *node = (void *)object; + return nv_ro32(object->engine, node->mem->offset + addr); +} + +static void +nv04_instobj_wr32(struct nouveau_object *object, u64 addr, u32 data) +{ + struct nv04_instobj_priv *node = (void *)object; + nv_wo32(object->engine, node->mem->offset + addr, data); +} + +static void +nv04_instobj_dtor(struct nouveau_object *object) +{ + struct nv04_instmem_priv *priv = (void *)object->engine; + struct nv04_instobj_priv *node = (void *)object; + nouveau_mm_free(&priv->heap, &node->mem); + nouveau_instobj_destroy(&node->base); +} + static int nv04_instobj_ctor(struct nouveau_object *parent, struct nouveau_object *engine, struct nouveau_oclass *oclass, void *data, u32 size, @@ -33,18 +58,19 @@ nv04_instobj_ctor(struct nouveau_object *parent, struct nouveau_object *engine, { struct nv04_instmem_priv *priv = (void *)engine; struct nv04_instobj_priv *node; - int ret, align; + struct nouveau_instobj_args *args = data; + int ret; - align = (unsigned long)data; - if (!align) - align = 1; + if (!args->align) + args->align = 1; ret = nouveau_instobj_create(parent, engine, oclass, &node); *pobject = nv_object(node); if (ret) return ret; - ret = nouveau_mm_head(&priv->heap, 1, size, size, align, &node->mem); + ret = nouveau_mm_head(&priv->heap, 1, args->size, args->size, + args->align, &node->mem); if (ret) return ret; @@ -53,32 +79,9 @@ nv04_instobj_ctor(struct nouveau_object *parent, struct nouveau_object *engine, return 0; } -static void -nv04_instobj_dtor(struct nouveau_object *object) -{ - struct nv04_instmem_priv *priv = (void *)object->engine; - struct nv04_instobj_priv *node = (void *)object; - nouveau_mm_free(&priv->heap, &node->mem); - nouveau_instobj_destroy(&node->base); -} - -static u32 -nv04_instobj_rd32(struct nouveau_object *object, u64 addr) -{ - struct nv04_instobj_priv *node = (void *)object; - return nv_ro32(object->engine, node->mem->offset + addr); -} - -static void -nv04_instobj_wr32(struct nouveau_object *object, u64 addr, u32 data) -{ - struct nv04_instobj_priv *node = (void *)object; - nv_wo32(object->engine, node->mem->offset + addr, data); -} - -static struct nouveau_oclass +struct nouveau_instobj_impl nv04_instobj_oclass = { - .ofuncs = &(struct nouveau_ofuncs) { + .base.ofuncs = &(struct nouveau_ofuncs) { .ctor = nv04_instobj_ctor, .dtor = nv04_instobj_dtor, .init = _nouveau_instobj_init, @@ -88,19 +91,34 @@ nv04_instobj_oclass = { }, }; -int -nv04_instmem_alloc(struct nouveau_instmem *imem, struct nouveau_object *parent, - u32 size, u32 align, struct nouveau_object **pobject) +/****************************************************************************** + * instmem subdev implementation + *****************************************************************************/ + +static u32 +nv04_instmem_rd32(struct nouveau_object *object, u64 addr) { - struct nouveau_object *engine = nv_object(imem); - int ret; + return nv_rd32(object, 0x700000 + addr); +} - ret = nouveau_object_ctor(parent, engine, &nv04_instobj_oclass, - (void *)(unsigned long)align, size, pobject); - if (ret) - return ret; +static void +nv04_instmem_wr32(struct nouveau_object *object, u64 addr, u32 data) +{ + return nv_wr32(object, 0x700000 + addr, data); +} - return 0; +void +nv04_instmem_dtor(struct nouveau_object *object) +{ + struct nv04_instmem_priv *priv = (void *)object; + nouveau_gpuobj_ref(NULL, &priv->ramfc); + nouveau_gpuobj_ref(NULL, &priv->ramro); + nouveau_ramht_ref(NULL, &priv->ramht); + nouveau_gpuobj_ref(NULL, &priv->vbios); + nouveau_mm_fini(&priv->heap); + if (priv->iomem) + iounmap(priv->iomem); + nouveau_instmem_destroy(&priv->base); } static int @@ -118,7 +136,6 @@ nv04_instmem_ctor(struct nouveau_object *parent, struct nouveau_object *engine, /* PRAMIN aperture maps over the end of VRAM, reserve it */ priv->base.reserved = 512 * 1024; - priv->base.alloc = nv04_instmem_alloc; ret = nouveau_mm_init(&priv->heap, 0, priv->base.reserved, 1); if (ret) @@ -150,36 +167,10 @@ nv04_instmem_ctor(struct nouveau_object *parent, struct nouveau_object *engine, return 0; } -void -nv04_instmem_dtor(struct nouveau_object *object) -{ - struct nv04_instmem_priv *priv = (void *)object; - nouveau_gpuobj_ref(NULL, &priv->ramfc); - nouveau_gpuobj_ref(NULL, &priv->ramro); - nouveau_ramht_ref(NULL, &priv->ramht); - nouveau_gpuobj_ref(NULL, &priv->vbios); - nouveau_mm_fini(&priv->heap); - if (priv->iomem) - iounmap(priv->iomem); - nouveau_instmem_destroy(&priv->base); -} - -static u32 -nv04_instmem_rd32(struct nouveau_object *object, u64 addr) -{ - return nv_rd32(object, 0x700000 + addr); -} - -static void -nv04_instmem_wr32(struct nouveau_object *object, u64 addr, u32 data) -{ - return nv_wr32(object, 0x700000 + addr, data); -} - -struct nouveau_oclass -nv04_instmem_oclass = { - .handle = NV_SUBDEV(INSTMEM, 0x04), - .ofuncs = &(struct nouveau_ofuncs) { +struct nouveau_oclass * +nv04_instmem_oclass = &(struct nouveau_instmem_impl) { + .base.handle = NV_SUBDEV(INSTMEM, 0x04), + .base.ofuncs = &(struct nouveau_ofuncs) { .ctor = nv04_instmem_ctor, .dtor = nv04_instmem_dtor, .init = _nouveau_instmem_init, @@ -187,4 +178,5 @@ nv04_instmem_oclass = { .rd32 = nv04_instmem_rd32, .wr32 = nv04_instmem_wr32, }, -}; + .instobj = &nv04_instobj_oclass.base, +}.base; diff --git a/drivers/gpu/drm/nouveau/core/subdev/instmem/nv04.h b/drivers/gpu/drm/nouveau/core/subdev/instmem/nv04.h index b15b61310236..095fbc6fc099 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/instmem/nv04.h +++ b/drivers/gpu/drm/nouveau/core/subdev/instmem/nv04.h @@ -5,7 +5,9 @@ #include <core/ramht.h> #include <core/mm.h> -#include <subdev/instmem.h> +#include "priv.h" + +extern struct nouveau_instobj_impl nv04_instobj_oclass; struct nv04_instmem_priv { struct nouveau_instmem base; diff --git a/drivers/gpu/drm/nouveau/core/subdev/instmem/nv40.c b/drivers/gpu/drm/nouveau/core/subdev/instmem/nv40.c index b10a143787a7..ec0b9661d614 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/instmem/nv40.c +++ b/drivers/gpu/drm/nouveau/core/subdev/instmem/nv40.c @@ -26,6 +26,24 @@ #include "nv04.h" +/****************************************************************************** + * instmem subdev implementation + *****************************************************************************/ + +static u32 +nv40_instmem_rd32(struct nouveau_object *object, u64 addr) +{ + struct nv04_instmem_priv *priv = (void *)object; + return ioread32_native(priv->iomem + addr); +} + +static void +nv40_instmem_wr32(struct nouveau_object *object, u64 addr, u32 data) +{ + struct nv04_instmem_priv *priv = (void *)object; + iowrite32_native(data, priv->iomem + addr); +} + static int nv40_instmem_ctor(struct nouveau_object *parent, struct nouveau_object *engine, struct nouveau_oclass *oclass, void *data, u32 size, @@ -69,7 +87,6 @@ nv40_instmem_ctor(struct nouveau_object *parent, struct nouveau_object *engine, priv->base.reserved += 512 * 1024; /* object storage */ priv->base.reserved = round_up(priv->base.reserved, 4096); - priv->base.alloc = nv04_instmem_alloc; ret = nouveau_mm_init(&priv->heap, 0, priv->base.reserved, 1); if (ret) @@ -106,24 +123,10 @@ nv40_instmem_ctor(struct nouveau_object *parent, struct nouveau_object *engine, return 0; } -static u32 -nv40_instmem_rd32(struct nouveau_object *object, u64 addr) -{ - struct nv04_instmem_priv *priv = (void *)object; - return ioread32_native(priv->iomem + addr); -} - -static void -nv40_instmem_wr32(struct nouveau_object *object, u64 addr, u32 data) -{ - struct nv04_instmem_priv *priv = (void *)object; - iowrite32_native(data, priv->iomem + addr); -} - -struct nouveau_oclass -nv40_instmem_oclass = { - .handle = NV_SUBDEV(INSTMEM, 0x40), - .ofuncs = &(struct nouveau_ofuncs) { +struct nouveau_oclass * +nv40_instmem_oclass = &(struct nouveau_instmem_impl) { + .base.handle = NV_SUBDEV(INSTMEM, 0x40), + .base.ofuncs = &(struct nouveau_ofuncs) { .ctor = nv40_instmem_ctor, .dtor = nv04_instmem_dtor, .init = _nouveau_instmem_init, @@ -131,4 +134,5 @@ nv40_instmem_oclass = { .rd32 = nv40_instmem_rd32, .wr32 = nv40_instmem_wr32, }, -}; + .instobj = &nv04_instobj_oclass.base, +}.base; diff --git a/drivers/gpu/drm/nouveau/core/subdev/instmem/nv50.c b/drivers/gpu/drm/nouveau/core/subdev/instmem/nv50.c index 97bc5dff93e7..7cb3b098a08d 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/instmem/nv50.c +++ b/drivers/gpu/drm/nouveau/core/subdev/instmem/nv50.c @@ -22,11 +22,11 @@ * Authors: Ben Skeggs */ -#include <subdev/instmem.h> #include <subdev/fb.h> - #include <core/mm.h> +#include "priv.h" + struct nv50_instmem_priv { struct nouveau_instmem base; spinlock_t lock; @@ -38,42 +38,9 @@ struct nv50_instobj_priv { struct nouveau_mem *mem; }; -static int -nv50_instobj_ctor(struct nouveau_object *parent, struct nouveau_object *engine, - struct nouveau_oclass *oclass, void *data, u32 size, - struct nouveau_object **pobject) -{ - struct nouveau_fb *pfb = nouveau_fb(parent); - struct nv50_instobj_priv *node; - u32 align = (unsigned long)data; - int ret; - - size = max((size + 4095) & ~4095, (u32)4096); - align = max((align + 4095) & ~4095, (u32)4096); - - ret = nouveau_instobj_create(parent, engine, oclass, &node); - *pobject = nv_object(node); - if (ret) - return ret; - - ret = pfb->ram->get(pfb, size, align, 0, 0x800, &node->mem); - if (ret) - return ret; - - node->base.addr = node->mem->offset; - node->base.size = node->mem->size << 12; - node->mem->page_shift = 12; - return 0; -} - -static void -nv50_instobj_dtor(struct nouveau_object *object) -{ - struct nv50_instobj_priv *node = (void *)object; - struct nouveau_fb *pfb = nouveau_fb(object); - pfb->ram->put(pfb, &node->mem); - nouveau_instobj_destroy(&node->base); -} +/****************************************************************************** + * instmem object implementation + *****************************************************************************/ static u32 nv50_instobj_rd32(struct nouveau_object *object, u64 offset) @@ -113,9 +80,46 @@ nv50_instobj_wr32(struct nouveau_object *object, u64 offset, u32 data) spin_unlock_irqrestore(&priv->lock, flags); } -static struct nouveau_oclass +static void +nv50_instobj_dtor(struct nouveau_object *object) +{ + struct nv50_instobj_priv *node = (void *)object; + struct nouveau_fb *pfb = nouveau_fb(object); + pfb->ram->put(pfb, &node->mem); + nouveau_instobj_destroy(&node->base); +} + +static int +nv50_instobj_ctor(struct nouveau_object *parent, struct nouveau_object *engine, + struct nouveau_oclass *oclass, void *data, u32 size, + struct nouveau_object **pobject) +{ + struct nouveau_fb *pfb = nouveau_fb(parent); + struct nouveau_instobj_args *args = data; + struct nv50_instobj_priv *node; + int ret; + + args->size = max((args->size + 4095) & ~4095, (u32)4096); + args->align = max((args->align + 4095) & ~4095, (u32)4096); + + ret = nouveau_instobj_create(parent, engine, oclass, &node); + *pobject = nv_object(node); + if (ret) + return ret; + + ret = pfb->ram->get(pfb, args->size, args->align, 0, 0x800, &node->mem); + if (ret) + return ret; + + node->base.addr = node->mem->offset; + node->base.size = node->mem->size << 12; + node->mem->page_shift = 12; + return 0; +} + +static struct nouveau_instobj_impl nv50_instobj_oclass = { - .ofuncs = &(struct nouveau_ofuncs) { + .base.ofuncs = &(struct nouveau_ofuncs) { .ctor = nv50_instobj_ctor, .dtor = nv50_instobj_dtor, .init = _nouveau_instobj_init, @@ -125,13 +129,16 @@ nv50_instobj_oclass = { }, }; +/****************************************************************************** + * instmem subdev implementation + *****************************************************************************/ + static int -nv50_instmem_alloc(struct nouveau_instmem *imem, struct nouveau_object *parent, - u32 size, u32 align, struct nouveau_object **pobject) +nv50_instmem_fini(struct nouveau_object *object, bool suspend) { - struct nouveau_object *engine = nv_object(imem); - return nouveau_object_ctor(parent, engine, &nv50_instobj_oclass, - (void *)(unsigned long)align, size, pobject); + struct nv50_instmem_priv *priv = (void *)object; + priv->addr = ~0ULL; + return nouveau_instmem_fini(&priv->base, suspend); } static int @@ -148,25 +155,17 @@ nv50_instmem_ctor(struct nouveau_object *parent, struct nouveau_object *engine, return ret; spin_lock_init(&priv->lock); - priv->base.alloc = nv50_instmem_alloc; return 0; } -static int -nv50_instmem_fini(struct nouveau_object *object, bool suspend) -{ - struct nv50_instmem_priv *priv = (void *)object; - priv->addr = ~0ULL; - return nouveau_instmem_fini(&priv->base, suspend); -} - -struct nouveau_oclass -nv50_instmem_oclass = { - .handle = NV_SUBDEV(INSTMEM, 0x50), - .ofuncs = &(struct nouveau_ofuncs) { +struct nouveau_oclass * +nv50_instmem_oclass = &(struct nouveau_instmem_impl) { + .base.handle = NV_SUBDEV(INSTMEM, 0x50), + .base.ofuncs = &(struct nouveau_ofuncs) { .ctor = nv50_instmem_ctor, .dtor = _nouveau_instmem_dtor, .init = _nouveau_instmem_init, .fini = nv50_instmem_fini, }, -}; + .instobj = &nv50_instobj_oclass.base, +}.base; diff --git a/drivers/gpu/drm/nouveau/core/subdev/instmem/priv.h b/drivers/gpu/drm/nouveau/core/subdev/instmem/priv.h new file mode 100644 index 000000000000..8d67dedc5bb2 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/subdev/instmem/priv.h @@ -0,0 +1,56 @@ +#ifndef __NVKM_INSTMEM_PRIV_H__ +#define __NVKM_INSTMEM_PRIV_H__ + +#include <subdev/instmem.h> + +struct nouveau_instobj_impl { + struct nouveau_oclass base; +}; + +struct nouveau_instobj_args { + u32 size; + u32 align; +}; + +#define nouveau_instobj_create(p,e,o,d) \ + nouveau_instobj_create_((p), (e), (o), sizeof(**d), (void **)d) +#define nouveau_instobj_destroy(p) ({ \ + struct nouveau_instobj *iobj = (p); \ + _nouveau_instobj_dtor(nv_object(iobj)); \ +}) +#define nouveau_instobj_init(p) \ + nouveau_object_init(&(p)->base) +#define nouveau_instobj_fini(p,s) \ + nouveau_object_fini(&(p)->base, (s)) + +int nouveau_instobj_create_(struct nouveau_object *, struct nouveau_object *, + struct nouveau_oclass *, int, void **); +void _nouveau_instobj_dtor(struct nouveau_object *); +#define _nouveau_instobj_init nouveau_object_init +#define _nouveau_instobj_fini nouveau_object_fini + +struct nouveau_instmem_impl { + struct nouveau_oclass base; + struct nouveau_oclass *instobj; +}; + +#define nouveau_instmem_create(p,e,o,d) \ + nouveau_instmem_create_((p), (e), (o), sizeof(**d), (void **)d) +#define nouveau_instmem_destroy(p) \ + nouveau_subdev_destroy(&(p)->base) +#define nouveau_instmem_init(p) ({ \ + struct nouveau_instmem *imem = (p); \ + _nouveau_instmem_init(nv_object(imem)); \ +}) +#define nouveau_instmem_fini(p,s) ({ \ + struct nouveau_instmem *imem = (p); \ + _nouveau_instmem_fini(nv_object(imem), (s)); \ +}) + +int nouveau_instmem_create_(struct nouveau_object *, struct nouveau_object *, + struct nouveau_oclass *, int, void **); +#define _nouveau_instmem_dtor _nouveau_subdev_dtor +int _nouveau_instmem_init(struct nouveau_object *); +int _nouveau_instmem_fini(struct nouveau_object *, bool); + +#endif diff --git a/drivers/gpu/drm/nouveau/core/subdev/mc/nv04.h b/drivers/gpu/drm/nouveau/core/subdev/mc/nv04.h index b0d5c31606c1..81a408e7d034 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/mc/nv04.h +++ b/drivers/gpu/drm/nouveau/core/subdev/mc/nv04.h @@ -14,6 +14,7 @@ int nv04_mc_ctor(struct nouveau_object *, struct nouveau_object *, extern const struct nouveau_mc_intr nv04_mc_intr[]; int nv04_mc_init(struct nouveau_object *); void nv40_mc_msi_rearm(struct nouveau_mc *); +int nv44_mc_init(struct nouveau_object *object); int nv50_mc_init(struct nouveau_object *); extern const struct nouveau_mc_intr nv50_mc_intr[]; extern const struct nouveau_mc_intr nvc0_mc_intr[]; diff --git a/drivers/gpu/drm/nouveau/core/subdev/mc/nv44.c b/drivers/gpu/drm/nouveau/core/subdev/mc/nv44.c index 3bfee5c6c4f2..cc4d0d2d886e 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/mc/nv44.c +++ b/drivers/gpu/drm/nouveau/core/subdev/mc/nv44.c @@ -24,7 +24,7 @@ #include "nv04.h" -static int +int nv44_mc_init(struct nouveau_object *object) { struct nv04_mc_priv *priv = (void *)object; diff --git a/drivers/gpu/drm/nouveau/core/subdev/mc/nv4c.c b/drivers/gpu/drm/nouveau/core/subdev/mc/nv4c.c new file mode 100644 index 000000000000..a75c35ccf25c --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/subdev/mc/nv4c.c @@ -0,0 +1,45 @@ +/* + * Copyright 2014 Ilia Mirkin + * + * 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: Ilia Mirkin + */ + +#include "nv04.h" + +static void +nv4c_mc_msi_rearm(struct nouveau_mc *pmc) +{ + struct nv04_mc_priv *priv = (void *)pmc; + nv_wr08(priv, 0x088050, 0xff); +} + +struct nouveau_oclass * +nv4c_mc_oclass = &(struct nouveau_mc_oclass) { + .base.handle = NV_SUBDEV(MC, 0x4c), + .base.ofuncs = &(struct nouveau_ofuncs) { + .ctor = nv04_mc_ctor, + .dtor = _nouveau_mc_dtor, + .init = nv44_mc_init, + .fini = _nouveau_mc_fini, + }, + .intr = nv04_mc_intr, + .msi_rearm = nv4c_mc_msi_rearm, +}.base; diff --git a/drivers/gpu/drm/nouveau/core/subdev/mc/nvc0.c b/drivers/gpu/drm/nouveau/core/subdev/mc/nvc0.c index c02b4763a2d5..34472d317097 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/mc/nvc0.c +++ b/drivers/gpu/drm/nouveau/core/subdev/mc/nvc0.c @@ -32,6 +32,7 @@ nvc0_mc_intr[] = { { 0x00000080, NVDEV_ENGINE_COPY2 }, { 0x00000100, NVDEV_ENGINE_FIFO }, { 0x00001000, NVDEV_ENGINE_GR }, + { 0x00002000, NVDEV_SUBDEV_FB }, { 0x00008000, NVDEV_ENGINE_BSP }, { 0x00040000, NVDEV_SUBDEV_THERM }, { 0x00020000, NVDEV_ENGINE_VP }, @@ -40,6 +41,7 @@ nvc0_mc_intr[] = { { 0x01000000, NVDEV_SUBDEV_PWR }, { 0x02000000, NVDEV_SUBDEV_LTCG }, { 0x04000000, NVDEV_ENGINE_DISP }, + { 0x08000000, NVDEV_SUBDEV_FB }, { 0x10000000, NVDEV_SUBDEV_BUS }, { 0x40000000, NVDEV_SUBDEV_IBUS }, { 0x80000000, NVDEV_ENGINE_SW }, diff --git a/drivers/gpu/drm/nouveau/core/subdev/mxm/base.c b/drivers/gpu/drm/nouveau/core/subdev/mxm/base.c index 129120473f6c..13c5af88a601 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/mxm/base.c +++ b/drivers/gpu/drm/nouveau/core/subdev/mxm/base.c @@ -87,55 +87,39 @@ mxm_shadow_dsm(struct nouveau_mxm *mxm, u8 version) 0xB8, 0x9C, 0x79, 0xB6, 0x2F, 0xD5, 0x56, 0x65 }; u32 mxms_args[] = { 0x00000000 }; - union acpi_object args[4] = { - /* _DSM MUID */ - { .buffer.type = 3, - .buffer.length = sizeof(muid), - .buffer.pointer = muid, - }, - /* spec says this can be zero to mean "highest revision", but - * of course there's at least one bios out there which fails - * unless you pass in exactly the version it supports.. - */ - { .integer.type = ACPI_TYPE_INTEGER, - .integer.value = (version & 0xf0) << 4 | (version & 0x0f), - }, - /* MXMS function */ - { .integer.type = ACPI_TYPE_INTEGER, - .integer.value = 0x00000010, - }, - /* Pointer to MXMS arguments */ - { .buffer.type = ACPI_TYPE_BUFFER, - .buffer.length = sizeof(mxms_args), - .buffer.pointer = (char *)mxms_args, - }, + union acpi_object argv4 = { + .buffer.type = ACPI_TYPE_BUFFER, + .buffer.length = sizeof(mxms_args), + .buffer.pointer = (char *)mxms_args, }; - struct acpi_object_list list = { ARRAY_SIZE(args), args }; - struct acpi_buffer retn = { ACPI_ALLOCATE_BUFFER, NULL }; union acpi_object *obj; acpi_handle handle; - int ret; + int rev; handle = ACPI_HANDLE(&device->pdev->dev); if (!handle) return false; - ret = acpi_evaluate_object(handle, "_DSM", &list, &retn); - if (ret) { - nv_debug(mxm, "DSM MXMS failed: %d\n", ret); + /* + * spec says this can be zero to mean "highest revision", but + * of course there's at least one bios out there which fails + * unless you pass in exactly the version it supports.. + */ + rev = (version & 0xf0) << 4 | (version & 0x0f); + obj = acpi_evaluate_dsm(handle, muid, rev, 0x00000010, &argv4); + if (!obj) { + nv_debug(mxm, "DSM MXMS failed\n"); return false; } - obj = retn.pointer; if (obj->type == ACPI_TYPE_BUFFER) { mxm->mxms = kmemdup(obj->buffer.pointer, obj->buffer.length, GFP_KERNEL); - } else - if (obj->type == ACPI_TYPE_INTEGER) { + } else if (obj->type == ACPI_TYPE_INTEGER) { nv_debug(mxm, "DSM MXMS returned 0x%llx\n", obj->integer.value); } - kfree(obj); + ACPI_FREE(obj); return mxm->mxms != NULL; } #endif diff --git a/drivers/gpu/drm/nouveau/core/subdev/mxm/nv50.c b/drivers/gpu/drm/nouveau/core/subdev/mxm/nv50.c index af129c2e8113..64f8b4702bf7 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/mxm/nv50.c +++ b/drivers/gpu/drm/nouveau/core/subdev/mxm/nv50.c @@ -100,7 +100,7 @@ mxm_match_dcb(struct nouveau_mxm *mxm, u8 *data, void *info) static int mxm_dcb_sanitise_entry(struct nouveau_bios *bios, void *data, int idx, u16 pdcb) { - struct nouveau_mxm *mxm = nouveau_mxm(bios); + struct nouveau_mxm *mxm = data; struct context ctx = { .outp = (u32 *)(bios->data + pdcb) }; u8 type, i2cidx, link, ver, len; u8 *conn; @@ -199,7 +199,7 @@ mxm_dcb_sanitise(struct nouveau_mxm *mxm) return; } - dcb_outp_foreach(bios, NULL, mxm_dcb_sanitise_entry); + dcb_outp_foreach(bios, mxm, mxm_dcb_sanitise_entry); mxms_foreach(mxm, 0x01, mxm_show_unmatched, NULL); } diff --git a/drivers/gpu/drm/nouveau/core/subdev/pwr/fuc/i2c_.fuc b/drivers/gpu/drm/nouveau/core/subdev/pwr/fuc/i2c_.fuc new file mode 100644 index 000000000000..757dda700024 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/subdev/pwr/fuc/i2c_.fuc @@ -0,0 +1,393 @@ +/* + * Copyright 2013 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 + */ + +#define T_TIMEOUT 2200000 +#define T_RISEFALL 1000 +#define T_HOLD 5000 + +#ifdef INCLUDE_PROC +process(PROC_I2C_, #i2c_init, #i2c_recv) +#endif + +/****************************************************************************** + * I2C_ data segment + *****************************************************************************/ +#ifdef INCLUDE_DATA +i2c_scl_map: +.b32 NV_PPWR_OUTPUT_I2C_0_SCL +.b32 NV_PPWR_OUTPUT_I2C_1_SCL +.b32 NV_PPWR_OUTPUT_I2C_2_SCL +.b32 NV_PPWR_OUTPUT_I2C_3_SCL +.b32 NV_PPWR_OUTPUT_I2C_4_SCL +.b32 NV_PPWR_OUTPUT_I2C_5_SCL +.b32 NV_PPWR_OUTPUT_I2C_6_SCL +.b32 NV_PPWR_OUTPUT_I2C_7_SCL +.b32 NV_PPWR_OUTPUT_I2C_8_SCL +.b32 NV_PPWR_OUTPUT_I2C_9_SCL +i2c_sda_map: +.b32 NV_PPWR_OUTPUT_I2C_0_SDA +.b32 NV_PPWR_OUTPUT_I2C_1_SDA +.b32 NV_PPWR_OUTPUT_I2C_2_SDA +.b32 NV_PPWR_OUTPUT_I2C_3_SDA +.b32 NV_PPWR_OUTPUT_I2C_4_SDA +.b32 NV_PPWR_OUTPUT_I2C_5_SDA +.b32 NV_PPWR_OUTPUT_I2C_6_SDA +.b32 NV_PPWR_OUTPUT_I2C_7_SDA +.b32 NV_PPWR_OUTPUT_I2C_8_SDA +.b32 NV_PPWR_OUTPUT_I2C_9_SDA +#if NVKM_PPWR_CHIPSET < GF119 +i2c_ctrl: +.b32 0x00e138 +.b32 0x00e150 +.b32 0x00e168 +.b32 0x00e180 +.b32 0x00e254 +.b32 0x00e274 +.b32 0x00e764 +.b32 0x00e780 +.b32 0x00e79c +.b32 0x00e7b8 +#endif +#endif + +/****************************************************************************** + * I2C_ code segment + *****************************************************************************/ +#ifdef INCLUDE_CODE + +// $r3 - value +// $r2 - sda line +// $r1 - scl line +// $r0 - zero +i2c_drive_scl: + cmp b32 $r3 0 + bra e #i2c_drive_scl_lo + nv_iowr(NV_PPWR_OUTPUT_SET, $r1) + ret + i2c_drive_scl_lo: + nv_iowr(NV_PPWR_OUTPUT_CLR, $r1) + ret + +i2c_drive_sda: + cmp b32 $r3 0 + bra e #i2c_drive_sda_lo + nv_iowr(NV_PPWR_OUTPUT_SET, $r2) + ret + i2c_drive_sda_lo: + nv_iowr(NV_PPWR_OUTPUT_CLR, $r2) + ret + +i2c_sense_scl: + bclr $flags $p1 + nv_iord($r3, NV_PPWR_INPUT) + and $r3 $r1 + bra z #i2c_sense_scl_done + bset $flags $p1 + i2c_sense_scl_done: + ret + +i2c_sense_sda: + bclr $flags $p1 + nv_iord($r3, NV_PPWR_INPUT) + and $r3 $r2 + bra z #i2c_sense_sda_done + bset $flags $p1 + i2c_sense_sda_done: + ret + +#define i2c_drive_scl(v) /* +*/ mov $r3 (v) /* +*/ call(i2c_drive_scl) +#define i2c_drive_sda(v) /* +*/ mov $r3 (v) /* +*/ call(i2c_drive_sda) +#define i2c_sense_scl() /* +*/ call(i2c_sense_scl) +#define i2c_sense_sda() /* +*/ call(i2c_sense_sda) +#define i2c_delay(v) /* +*/ mov $r14 (v) /* +*/ call(nsec) + +#define i2c_trace_init() /* +*/ imm32($r6, 0x10000000) /* +*/ sub b32 $r7 $r6 1 /* +*/ +#define i2c_trace_down() /* +*/ shr b32 $r6 4 /* +*/ push $r5 /* +*/ shl b32 $r5 $r6 4 /* +*/ sub b32 $r5 $r6 /* +*/ not b32 $r5 /* +*/ and $r7 $r5 /* +*/ pop $r5 /* +*/ +#define i2c_trace_exit() /* +*/ shl b32 $r6 4 /* +*/ +#define i2c_trace_next() /* +*/ add b32 $r7 $r6 /* +*/ +#define i2c_trace_call(func) /* +*/ i2c_trace_next() /* +*/ i2c_trace_down() /* +*/ call(func) /* +*/ i2c_trace_exit() /* +*/ + +i2c_raise_scl: + push $r4 + mov $r4 (T_TIMEOUT / T_RISEFALL) + i2c_drive_scl(1) + i2c_raise_scl_wait: + i2c_delay(T_RISEFALL) + i2c_sense_scl() + bra $p1 #i2c_raise_scl_done + sub b32 $r4 1 + bra nz #i2c_raise_scl_wait + i2c_raise_scl_done: + pop $r4 + ret + +i2c_start: + i2c_sense_scl() + bra not $p1 #i2c_start_rep + i2c_sense_sda() + bra not $p1 #i2c_start_rep + bra #i2c_start_send + i2c_start_rep: + i2c_drive_scl(0) + i2c_drive_sda(1) + i2c_trace_call(i2c_raise_scl) + bra not $p1 #i2c_start_out + i2c_start_send: + i2c_drive_sda(0) + i2c_delay(T_HOLD) + i2c_drive_scl(0) + i2c_delay(T_HOLD) + i2c_start_out: + ret + +i2c_stop: + i2c_drive_scl(0) + i2c_drive_sda(0) + i2c_delay(T_RISEFALL) + i2c_drive_scl(1) + i2c_delay(T_HOLD) + i2c_drive_sda(1) + i2c_delay(T_HOLD) + ret + +// $r3 - value +// $r2 - sda line +// $r1 - scl line +// $r0 - zero +i2c_bitw: + call(i2c_drive_sda) + i2c_delay(T_RISEFALL) + i2c_trace_call(i2c_raise_scl) + bra not $p1 #i2c_bitw_out + i2c_delay(T_HOLD) + i2c_drive_scl(0) + i2c_delay(T_HOLD) + i2c_bitw_out: + ret + +// $r3 - value (out) +// $r2 - sda line +// $r1 - scl line +// $r0 - zero +i2c_bitr: + i2c_drive_sda(1) + i2c_delay(T_RISEFALL) + i2c_trace_call(i2c_raise_scl) + bra not $p1 #i2c_bitr_done + i2c_sense_sda() + i2c_drive_scl(0) + i2c_delay(T_HOLD) + xbit $r3 $flags $p1 + bset $flags $p1 + i2c_bitr_done: + ret + +i2c_get_byte: + mov $r5 0 + mov $r4 8 + i2c_get_byte_next: + shl b32 $r5 1 + i2c_trace_call(i2c_bitr) + bra not $p1 #i2c_get_byte_done + or $r5 $r3 + sub b32 $r4 1 + bra nz #i2c_get_byte_next + mov $r3 1 + i2c_trace_call(i2c_bitw) + i2c_get_byte_done: + ret + +i2c_put_byte: + mov $r4 8 + i2c_put_byte_next: + sub b32 $r4 1 + xbit $r3 $r5 $r4 + i2c_trace_call(i2c_bitw) + bra not $p1 #i2c_put_byte_done + cmp b32 $r4 0 + bra ne #i2c_put_byte_next + i2c_trace_call(i2c_bitr) + bra not $p1 #i2c_put_byte_done + i2c_trace_next() + cmp b32 $r3 1 + bra ne #i2c_put_byte_done + bclr $flags $p1 // nack + i2c_put_byte_done: + ret + +i2c_addr: + i2c_trace_call(i2c_start) + bra not $p1 #i2c_addr_done + extr $r3 $r12 I2C__MSG_DATA0_ADDR + shl b32 $r3 1 + or $r5 $r3 + i2c_trace_call(i2c_put_byte) + i2c_addr_done: + ret + +i2c_acquire_addr: + extr $r14 $r12 I2C__MSG_DATA0_PORT +#if NVKM_PPWR_CHIPSET < GF119 + shl b32 $r14 2 + add b32 $r14 #i2c_ctrl + ld b32 $r14 D[$r14] +#else + shl b32 $r14 5 + add b32 $r14 0x00d014 +#endif + ret + +i2c_acquire: + call(i2c_acquire_addr) + call(rd32) + bset $r13 3 + call(wr32) + ret + +i2c_release: + call(i2c_acquire_addr) + call(rd32) + bclr $r13 3 + call(wr32) + ret + +// description +// +// $r15 - current (i2c) +// $r14 - sender process name +// $r13 - message +// $r12 - data0 +// $r11 - data1 +// $r0 - zero +i2c_recv: + bclr $flags $p1 + extr $r1 $r12 I2C__MSG_DATA0_PORT + shl b32 $r1 2 + cmp b32 $r1 (#i2c_sda_map - #i2c_scl_map) + bra ge #i2c_recv_done + add b32 $r3 $r1 #i2c_sda_map + ld b32 $r2 D[$r3] + add b32 $r3 $r1 #i2c_scl_map + ld b32 $r1 D[$r3] + + bset $flags $p2 + push $r13 + push $r14 + + push $r13 + i2c_trace_init() + i2c_trace_call(i2c_acquire) + pop $r13 + + cmp b32 $r13 I2C__MSG_RD08 + bra ne #i2c_recv_not_rd08 + mov $r5 0 + i2c_trace_call(i2c_addr) + bra not $p1 #i2c_recv_done + extr $r5 $r12 I2C__MSG_DATA0_RD08_REG + i2c_trace_call(i2c_put_byte) + bra not $p1 #i2c_recv_done + mov $r5 1 + i2c_trace_call(i2c_addr) + bra not $p1 #i2c_recv_done + i2c_trace_call(i2c_get_byte) + bra not $p1 #i2c_recv_done + ins $r11 $r5 I2C__MSG_DATA1_RD08_VAL + i2c_trace_call(i2c_stop) + mov b32 $r11 $r5 + clear b32 $r7 + bra #i2c_recv_done + + i2c_recv_not_rd08: + cmp b32 $r13 I2C__MSG_WR08 + bra ne #i2c_recv_not_wr08 + mov $r5 0 + call(i2c_addr) + bra not $p1 #i2c_recv_done + extr $r5 $r12 I2C__MSG_DATA0_WR08_REG + call(i2c_put_byte) + bra not $p1 #i2c_recv_done + mov $r5 0 + call(i2c_addr) + bra not $p1 #i2c_recv_done + extr $r5 $r11 I2C__MSG_DATA1_WR08_VAL + call(i2c_put_byte) + bra not $p1 #i2c_recv_done + call(i2c_stop) + clear b32 $r7 + extr $r5 $r12 I2C__MSG_DATA0_WR08_SYNC + bra nz #i2c_recv_done + bclr $flags $p2 + bra #i2c_recv_done + + i2c_recv_not_wr08: + + i2c_recv_done: + extr $r14 $r12 I2C__MSG_DATA0_PORT + call(i2c_release) + + pop $r14 + pop $r13 + bra not $p2 #i2c_recv_exit + mov b32 $r12 $r7 + call(send) + + i2c_recv_exit: + ret + +// description +// +// $r15 - current (i2c) +// $r0 - zero +i2c_init: + ret +#endif diff --git a/drivers/gpu/drm/nouveau/core/subdev/pwr/fuc/kernel.fuc b/drivers/gpu/drm/nouveau/core/subdev/pwr/fuc/kernel.fuc index 0a7b05fa5c11..8f29badd785f 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/pwr/fuc/kernel.fuc +++ b/drivers/gpu/drm/nouveau/core/subdev/pwr/fuc/kernel.fuc @@ -51,12 +51,12 @@ time_next: .b32 0 // $r0 - zero rd32: nv_iowr(NV_PPWR_MMIO_ADDR, $r14) - mov $r14 NV_PPWR_MMIO_CTRL_OP_RD - sethi $r14 NV_PPWR_MMIO_CTRL_TRIGGER - nv_iowr(NV_PPWR_MMIO_CTRL, $r14) + mov $r13 NV_PPWR_MMIO_CTRL_OP_RD + sethi $r13 NV_PPWR_MMIO_CTRL_TRIGGER + nv_iowr(NV_PPWR_MMIO_CTRL, $r13) rd32_wait: - nv_iord($r14, NV_PPWR_MMIO_CTRL) - and $r14 NV_PPWR_MMIO_CTRL_STATUS + nv_iord($r13, NV_PPWR_MMIO_CTRL) + and $r13 NV_PPWR_MMIO_CTRL_STATUS bra nz #rd32_wait nv_iord($r13, NV_PPWR_MMIO_DATA) ret @@ -70,23 +70,25 @@ rd32: wr32: nv_iowr(NV_PPWR_MMIO_ADDR, $r14) nv_iowr(NV_PPWR_MMIO_DATA, $r13) - mov $r14 NV_PPWR_MMIO_CTRL_OP_WR - or $r14 NV_PPWR_MMIO_CTRL_MASK_B32_0 - sethi $r14 NV_PPWR_MMIO_CTRL_TRIGGER + mov $r13 NV_PPWR_MMIO_CTRL_OP_WR + or $r13 NV_PPWR_MMIO_CTRL_MASK_B32_0 + sethi $r13 NV_PPWR_MMIO_CTRL_TRIGGER #ifdef NVKM_FALCON_MMIO_TRAP - mov $r8 NV_PPWR_INTR_TRIGGER_USER1 - nv_iowr(NV_PPWR_INTR_TRIGGER, $r8) + push $r13 + mov $r13 NV_PPWR_INTR_TRIGGER_USER1 + nv_iowr(NV_PPWR_INTR_TRIGGER, $r13) wr32_host: - nv_iord($r8, NV_PPWR_INTR) - and $r8 NV_PPWR_INTR_USER1 + nv_iord($r13, NV_PPWR_INTR) + and $r13 NV_PPWR_INTR_USER1 bra nz #wr32_host + pop $r13 #endif - nv_iowr(NV_PPWR_MMIO_CTRL, $r14) + nv_iowr(NV_PPWR_MMIO_CTRL, $r13) wr32_wait: - nv_iord($r14, NV_PPWR_MMIO_CTRL) - and $r14 NV_PPWR_MMIO_CTRL_STATUS + nv_iord($r13, NV_PPWR_MMIO_CTRL) + and $r13 NV_PPWR_MMIO_CTRL_STATUS bra nz #wr32_wait ret diff --git a/drivers/gpu/drm/nouveau/core/subdev/pwr/fuc/macros.fuc b/drivers/gpu/drm/nouveau/core/subdev/pwr/fuc/macros.fuc index 2a74ea907604..e2a63ac5422b 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/pwr/fuc/macros.fuc +++ b/drivers/gpu/drm/nouveau/core/subdev/pwr/fuc/macros.fuc @@ -83,6 +83,50 @@ #define NV_PPWR_MMIO_CTRL_OP_WR 0x00000002 #define NV_PPWR_OUTPUT 0x07c0 #define NV_PPWR_OUTPUT_FB_PAUSE 0x00000004 +#if NVKM_PPWR_CHIPSET < GF119 +#define NV_PPWR_OUTPUT_I2C_3_SCL 0x00000100 +#define NV_PPWR_OUTPUT_I2C_3_SDA 0x00000200 +#define NV_PPWR_OUTPUT_I2C_0_SCL 0x00001000 +#define NV_PPWR_OUTPUT_I2C_0_SDA 0x00002000 +#define NV_PPWR_OUTPUT_I2C_1_SCL 0x00004000 +#define NV_PPWR_OUTPUT_I2C_1_SDA 0x00008000 +#define NV_PPWR_OUTPUT_I2C_2_SCL 0x00010000 +#define NV_PPWR_OUTPUT_I2C_2_SDA 0x00020000 +#define NV_PPWR_OUTPUT_I2C_4_SCL 0x00040000 +#define NV_PPWR_OUTPUT_I2C_4_SDA 0x00080000 +#define NV_PPWR_OUTPUT_I2C_5_SCL 0x00100000 +#define NV_PPWR_OUTPUT_I2C_5_SDA 0x00200000 +#define NV_PPWR_OUTPUT_I2C_6_SCL 0x00400000 +#define NV_PPWR_OUTPUT_I2C_6_SDA 0x00800000 +#define NV_PPWR_OUTPUT_I2C_7_SCL 0x01000000 +#define NV_PPWR_OUTPUT_I2C_7_SDA 0x02000000 +#define NV_PPWR_OUTPUT_I2C_8_SCL 0x04000000 +#define NV_PPWR_OUTPUT_I2C_8_SDA 0x08000000 +#define NV_PPWR_OUTPUT_I2C_9_SCL 0x10000000 +#define NV_PPWR_OUTPUT_I2C_9_SDA 0x20000000 +#else +#define NV_PPWR_OUTPUT_I2C_0_SCL 0x00000400 +#define NV_PPWR_OUTPUT_I2C_1_SCL 0x00000800 +#define NV_PPWR_OUTPUT_I2C_2_SCL 0x00001000 +#define NV_PPWR_OUTPUT_I2C_3_SCL 0x00002000 +#define NV_PPWR_OUTPUT_I2C_4_SCL 0x00004000 +#define NV_PPWR_OUTPUT_I2C_5_SCL 0x00008000 +#define NV_PPWR_OUTPUT_I2C_6_SCL 0x00010000 +#define NV_PPWR_OUTPUT_I2C_7_SCL 0x00020000 +#define NV_PPWR_OUTPUT_I2C_8_SCL 0x00040000 +#define NV_PPWR_OUTPUT_I2C_9_SCL 0x00080000 +#define NV_PPWR_OUTPUT_I2C_0_SDA 0x00100000 +#define NV_PPWR_OUTPUT_I2C_1_SDA 0x00200000 +#define NV_PPWR_OUTPUT_I2C_2_SDA 0x00400000 +#define NV_PPWR_OUTPUT_I2C_3_SDA 0x00800000 +#define NV_PPWR_OUTPUT_I2C_4_SDA 0x01000000 +#define NV_PPWR_OUTPUT_I2C_5_SDA 0x02000000 +#define NV_PPWR_OUTPUT_I2C_6_SDA 0x04000000 +#define NV_PPWR_OUTPUT_I2C_7_SDA 0x08000000 +#define NV_PPWR_OUTPUT_I2C_8_SDA 0x10000000 +#define NV_PPWR_OUTPUT_I2C_9_SDA 0x20000000 +#endif +#define NV_PPWR_INPUT 0x07c4 #define NV_PPWR_OUTPUT_SET 0x07e0 #define NV_PPWR_OUTPUT_SET_FB_PAUSE 0x00000004 #define NV_PPWR_OUTPUT_CLR 0x07e4 @@ -125,6 +169,15 @@ */ .b32 0 /* */ .skip 64 +#if NV_PPWR_CHIPSET < GK208 +#define imm32(reg,val) /* +*/ movw reg ((val) & 0x0000ffff) /* +*/ sethi reg ((val) & 0xffff0000) +#else +#define imm32(reg,val) /* +*/ mov reg (val) +#endif + #ifndef NVKM_FALCON_UNSHIFTED_IO #define nv_iord(reg,ior) /* */ mov reg ior /* diff --git a/drivers/gpu/drm/nouveau/core/subdev/pwr/fuc/nv108.fuc b/drivers/gpu/drm/nouveau/core/subdev/pwr/fuc/nv108.fuc index 947be536daef..17a8a383d91a 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/pwr/fuc/nv108.fuc +++ b/drivers/gpu/drm/nouveau/core/subdev/pwr/fuc/nv108.fuc @@ -37,6 +37,7 @@ #include "host.fuc" #include "memx.fuc" #include "perf.fuc" +#include "i2c_.fuc" #include "test.fuc" #include "idle.fuc" #undef INCLUDE_PROC @@ -46,6 +47,7 @@ #include "host.fuc" #include "memx.fuc" #include "perf.fuc" +#include "i2c_.fuc" #include "test.fuc" #include "idle.fuc" #undef INCLUDE_DATA @@ -57,6 +59,7 @@ #include "host.fuc" #include "memx.fuc" #include "perf.fuc" +#include "i2c_.fuc" #include "test.fuc" #include "idle.fuc" #undef INCLUDE_CODE diff --git a/drivers/gpu/drm/nouveau/core/subdev/pwr/fuc/nv108.fuc.h b/drivers/gpu/drm/nouveau/core/subdev/pwr/fuc/nv108.fuc.h index 9342e2d7d3b7..4bd43a99fdcc 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/pwr/fuc/nv108.fuc.h +++ b/drivers/gpu/drm/nouveau/core/subdev/pwr/fuc/nv108.fuc.h @@ -89,16 +89,9 @@ uint32_t nv108_pwr_data[] = { 0x00000000, 0x00000000, 0x00000000, - 0x54534554, - 0x00000494, - 0x00000475, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, + 0x5f433249, + 0x00000877, + 0x0000071e, 0x00000000, 0x00000000, 0x00000000, @@ -111,16 +104,6 @@ uint32_t nv108_pwr_data[] = { 0x00000000, 0x00000000, 0x00000000, - 0x454c4449, - 0x0000049f, - 0x0000049d, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, @@ -128,17 +111,16 @@ uint32_t nv108_pwr_data[] = { 0x00000000, 0x00000000, 0x00000000, + 0x54534554, + 0x00000898, + 0x00000879, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, -/* 0x0210: proc_list_tail */ -/* 0x0210: time_prev */ 0x00000000, -/* 0x0214: time_next */ 0x00000000, -/* 0x0218: fifo_queue */ 0x00000000, 0x00000000, 0x00000000, @@ -151,6 +133,9 @@ uint32_t nv108_pwr_data[] = { 0x00000000, 0x00000000, 0x00000000, + 0x454c4449, + 0x000008a3, + 0x000008a1, 0x00000000, 0x00000000, 0x00000000, @@ -170,9 +155,12 @@ uint32_t nv108_pwr_data[] = { 0x00000000, 0x00000000, 0x00000000, +/* 0x0268: proc_list_tail */ +/* 0x0268: time_prev */ 0x00000000, -/* 0x0298: rfifo_queue */ +/* 0x026c: time_next */ 0x00000000, +/* 0x0270: fifo_queue */ 0x00000000, 0x00000000, 0x00000000, @@ -204,31 +192,8 @@ uint32_t nv108_pwr_data[] = { 0x00000000, 0x00000000, 0x00000000, -/* 0x0318: memx_func_head */ - 0x00010000, - 0x00000000, - 0x000003a9, -/* 0x0324: memx_func_next */ - 0x00000001, - 0x00000000, - 0x000003c7, - 0x00000002, - 0x00000002, - 0x000003df, - 0x00040003, - 0x00000000, - 0x00000407, - 0x00010004, - 0x00000000, - 0x00000421, -/* 0x0354: memx_func_tail */ -/* 0x0354: memx_data_head */ - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, 0x00000000, +/* 0x02f0: rfifo_queue */ 0x00000000, 0x00000000, 0x00000000, @@ -261,10 +226,25 @@ uint32_t nv108_pwr_data[] = { 0x00000000, 0x00000000, 0x00000000, +/* 0x0370: memx_func_head */ + 0x00010000, 0x00000000, + 0x000003a9, +/* 0x037c: memx_func_next */ + 0x00000001, 0x00000000, + 0x000003c7, + 0x00000002, + 0x00000002, + 0x000003df, + 0x00040003, 0x00000000, + 0x00000407, + 0x00010004, 0x00000000, + 0x00000421, +/* 0x03ac: memx_func_tail */ +/* 0x03ac: memx_data_head */ 0x00000000, 0x00000000, 0x00000000, @@ -735,7 +715,6 @@ uint32_t nv108_pwr_data[] = { 0x00000000, 0x00000000, 0x00000000, -/* 0x0b54: memx_data_tail */ 0x00000000, 0x00000000, 0x00000000, @@ -778,6 +757,29 @@ uint32_t nv108_pwr_data[] = { 0x00000000, 0x00000000, 0x00000000, +/* 0x0bac: memx_data_tail */ +/* 0x0bac: i2c_scl_map */ + 0x00000400, + 0x00000800, + 0x00001000, + 0x00002000, + 0x00004000, + 0x00008000, + 0x00010000, + 0x00020000, + 0x00040000, + 0x00080000, +/* 0x0bd4: i2c_sda_map */ + 0x00100000, + 0x00200000, + 0x00400000, + 0x00800000, + 0x01000000, + 0x02000000, + 0x04000000, + 0x08000000, + 0x10000000, + 0x20000000, 0x00000000, }; @@ -786,13 +788,13 @@ uint32_t nv108_pwr_code[] = { /* 0x0004: rd32 */ 0xf607a040, 0x04bd000e, - 0xe3f0010e, + 0xd3f0010d, 0x07ac4001, - 0xbd000ef6, + 0xbd000df6, /* 0x0019: rd32_wait */ - 0x07ac4e04, - 0xf100eecf, - 0xf47000e4, + 0x07ac4d04, + 0xf100ddcf, + 0xf47000d4, 0xa44df61b, 0x00ddcf07, /* 0x002e: wr32 */ @@ -800,14 +802,14 @@ uint32_t nv108_pwr_code[] = { 0x000ef607, 0xa44004bd, 0x000df607, - 0x020e04bd, - 0xf0f0e5f0, - 0xac4001e3, - 0x000ef607, + 0x020d04bd, + 0xf0f0d5f0, + 0xac4001d3, + 0x000df607, /* 0x004e: wr32_wait */ - 0xac4e04bd, - 0x00eecf07, - 0x7000e4f1, + 0xac4d04bd, + 0x00ddcf07, + 0x7000d4f1, 0xf8f61bf4, /* 0x005d: nsec */ 0xcf2c0800, @@ -832,20 +834,20 @@ uint32_t nv108_pwr_code[] = { 0x03e99800, 0xf40096b0, 0x0a98280b, - 0x029abb84, + 0x029abb9a, 0x0d0e1cf4, 0x01de7e01, 0xf494bd00, /* 0x00b2: intr_watchdog_next_time */ 0x0a98140e, - 0x00a6b085, + 0x00a6b09b, 0xa6080bf4, 0x061cf49a, /* 0x00c0: intr_watchdog_next_time_set */ /* 0x00c3: intr_watchdog_next_proc */ - 0xb58509b5, + 0xb59b09b5, 0xe0b603e9, - 0x10e6b158, + 0x68e6b158, 0xc81bf402, /* 0x00d2: intr */ 0x00f900f8, @@ -862,15 +864,15 @@ uint32_t nv108_pwr_code[] = { 0x080804bd, 0xc40088cf, 0x0bf40289, - 0x8500b51f, + 0x9b00b51f, 0x957e580e, 0x09980000, - 0x0096b085, + 0x0096b09b, 0x000d0bf4, 0x0009f634, 0x09b504bd, /* 0x0125: intr_skip_watchdog */ - 0x0089e484, + 0x0089e49a, 0x360bf408, 0xcf068849, 0x9ac40099, @@ -918,7 +920,7 @@ uint32_t nv108_pwr_code[] = { /* 0x01c6: timer_reset */ 0x3400161e, 0xbd000ef6, - 0x840eb504, + 0x9a0eb504, /* 0x01d0: timer_enable */ 0x38000108, 0xbd0008f6, @@ -949,7 +951,7 @@ uint32_t nv108_pwr_code[] = { 0xa6008a98, 0x100bf4ae, 0xb15880b6, - 0xf4021086, + 0xf4026886, 0x32f4f11b, /* 0x0239: find_done */ 0xfc8eb201, @@ -1009,7 +1011,7 @@ uint32_t nv108_pwr_code[] = { 0x0bf412a6, 0x071ec42e, 0xb704ee94, - 0x980218e0, + 0x980270e0, 0xec9803eb, 0x01ed9802, 0x7e00ee98, @@ -1031,7 +1033,7 @@ uint32_t nv108_pwr_code[] = { 0xf412a608, 0x23c4ef0b, 0x0434b607, - 0x029830b7, + 0x02f030b7, 0xb5033bb5, 0x3db5023c, 0x003eb501, @@ -1044,11 +1046,11 @@ uint32_t nv108_pwr_code[] = { /* 0x0379: host_init */ 0x00804100, 0xf11014b6, - 0x40021815, + 0x40027015, 0x01f604d0, 0x4104bd00, 0x14b60080, - 0x9815f110, + 0xf015f110, 0x04dc4002, 0xbd0001f6, 0x40010104, @@ -1101,13 +1103,13 @@ uint32_t nv108_pwr_code[] = { 0x001398b2, 0x950410b6, 0x30f01034, - 0xc835980c, + 0xde35980c, 0x12a655f9, 0xfced1ef4, 0x7ee0fcd0, 0xf800023f, /* 0x0455: memx_info */ - 0x03544c00, + 0x03ac4c00, 0x7e08004b, 0xf800023f, /* 0x0461: memx_recv */ @@ -1119,7 +1121,301 @@ uint32_t nv108_pwr_code[] = { /* 0x0471: perf_recv */ /* 0x0473: perf_init */ 0xf800f800, -/* 0x0475: test_recv */ +/* 0x0475: i2c_drive_scl */ + 0x0036b000, + 0x400d0bf4, + 0x01f607e0, + 0xf804bd00, +/* 0x0485: i2c_drive_scl_lo */ + 0x07e44000, + 0xbd0001f6, +/* 0x048f: i2c_drive_sda */ + 0xb000f804, + 0x0bf40036, + 0x07e0400d, + 0xbd0002f6, +/* 0x049f: i2c_drive_sda_lo */ + 0x4000f804, + 0x02f607e4, + 0xf804bd00, +/* 0x04a9: i2c_sense_scl */ + 0x0132f400, + 0xcf07c443, + 0x31fd0033, + 0x060bf404, +/* 0x04bb: i2c_sense_scl_done */ + 0xf80131f4, +/* 0x04bd: i2c_sense_sda */ + 0x0132f400, + 0xcf07c443, + 0x32fd0033, + 0x060bf404, +/* 0x04cf: i2c_sense_sda_done */ + 0xf80131f4, +/* 0x04d1: i2c_raise_scl */ + 0x4440f900, + 0x01030898, + 0x0004757e, +/* 0x04dc: i2c_raise_scl_wait */ + 0x7e03e84e, + 0x7e00005d, + 0xf40004a9, + 0x42b60901, + 0xef1bf401, +/* 0x04f0: i2c_raise_scl_done */ + 0x00f840fc, +/* 0x04f4: i2c_start */ + 0x0004a97e, + 0x7e0d11f4, + 0xf40004bd, + 0x0ef40611, +/* 0x0505: i2c_start_rep */ + 0x7e00032e, + 0x03000475, + 0x048f7e01, + 0x0076bb00, + 0xf90465b6, + 0x04659450, + 0xbd0256bb, + 0x0475fd50, + 0xd17e50fc, + 0x64b60004, + 0x1d11f404, +/* 0x0530: i2c_start_send */ + 0x8f7e0003, + 0x884e0004, + 0x005d7e13, + 0x7e000300, + 0x4e000475, + 0x5d7e1388, +/* 0x054a: i2c_start_out */ + 0x00f80000, +/* 0x054c: i2c_stop */ + 0x757e0003, + 0x00030004, + 0x00048f7e, + 0x7e03e84e, + 0x0300005d, + 0x04757e01, + 0x13884e00, + 0x00005d7e, + 0x8f7e0103, + 0x884e0004, + 0x005d7e13, +/* 0x057b: i2c_bitw */ + 0x7e00f800, + 0x4e00048f, + 0x5d7e03e8, + 0x76bb0000, + 0x0465b600, + 0x659450f9, + 0x0256bb04, + 0x75fd50bd, + 0x7e50fc04, + 0xb60004d1, + 0x11f40464, + 0x13884e17, + 0x00005d7e, + 0x757e0003, + 0x884e0004, + 0x005d7e13, +/* 0x05b9: i2c_bitw_out */ +/* 0x05bb: i2c_bitr */ + 0x0300f800, + 0x048f7e01, + 0x03e84e00, + 0x00005d7e, + 0xb60076bb, + 0x50f90465, + 0xbb046594, + 0x50bd0256, + 0xfc0475fd, + 0x04d17e50, + 0x0464b600, + 0x7e1a11f4, + 0x030004bd, + 0x04757e00, + 0x13884e00, + 0x00005d7e, + 0xf4013cf0, +/* 0x05fe: i2c_bitr_done */ + 0x00f80131, +/* 0x0600: i2c_get_byte */ + 0x08040005, +/* 0x0604: i2c_get_byte_next */ + 0xbb0154b6, + 0x65b60076, + 0x9450f904, + 0x56bb0465, + 0xfd50bd02, + 0x50fc0475, + 0x0005bb7e, + 0xf40464b6, + 0x53fd2a11, + 0x0142b605, + 0x03d81bf4, + 0x0076bb01, + 0xf90465b6, + 0x04659450, + 0xbd0256bb, + 0x0475fd50, + 0x7b7e50fc, + 0x64b60005, +/* 0x064d: i2c_get_byte_done */ +/* 0x064f: i2c_put_byte */ + 0x0400f804, +/* 0x0651: i2c_put_byte_next */ + 0x0142b608, + 0xbb3854ff, + 0x65b60076, + 0x9450f904, + 0x56bb0465, + 0xfd50bd02, + 0x50fc0475, + 0x00057b7e, + 0xf40464b6, + 0x46b03411, + 0xd81bf400, + 0xb60076bb, + 0x50f90465, + 0xbb046594, + 0x50bd0256, + 0xfc0475fd, + 0x05bb7e50, + 0x0464b600, + 0xbb0f11f4, + 0x36b00076, + 0x061bf401, +/* 0x06a7: i2c_put_byte_done */ + 0xf80132f4, +/* 0x06a9: i2c_addr */ + 0x0076bb00, + 0xf90465b6, + 0x04659450, + 0xbd0256bb, + 0x0475fd50, + 0xf47e50fc, + 0x64b60004, + 0x2911f404, + 0x012ec3e7, + 0xfd0134b6, + 0x76bb0553, + 0x0465b600, + 0x659450f9, + 0x0256bb04, + 0x75fd50bd, + 0x7e50fc04, + 0xb600064f, +/* 0x06ee: i2c_addr_done */ + 0x00f80464, +/* 0x06f0: i2c_acquire_addr */ + 0xb6f8cec7, + 0xe0b705e4, + 0x00f8d014, +/* 0x06fc: i2c_acquire */ + 0x0006f07e, + 0x0000047e, + 0x7e03d9f0, + 0xf800002e, +/* 0x070d: i2c_release */ + 0x06f07e00, + 0x00047e00, + 0x03daf000, + 0x00002e7e, +/* 0x071e: i2c_recv */ + 0x32f400f8, + 0xf8c1c701, + 0xb00214b6, + 0x1ff52816, + 0x13b80137, + 0x98000bd4, + 0x13b80032, + 0x98000bac, + 0x31f40031, + 0xf9d0f902, + 0xf1d0f9e0, + 0xf1000067, + 0x92100063, + 0x76bb0167, + 0x0465b600, + 0x659450f9, + 0x0256bb04, + 0x75fd50bd, + 0x7e50fc04, + 0xb60006fc, + 0xd0fc0464, + 0xf500d6b0, + 0x0500b01b, + 0x0076bb00, + 0xf90465b6, + 0x04659450, + 0xbd0256bb, + 0x0475fd50, + 0xa97e50fc, + 0x64b60006, + 0xcc11f504, + 0xe0c5c700, + 0xb60076bb, + 0x50f90465, + 0xbb046594, + 0x50bd0256, + 0xfc0475fd, + 0x064f7e50, + 0x0464b600, + 0x00a911f5, + 0x76bb0105, + 0x0465b600, + 0x659450f9, + 0x0256bb04, + 0x75fd50bd, + 0x7e50fc04, + 0xb60006a9, + 0x11f50464, + 0x76bb0087, + 0x0465b600, + 0x659450f9, + 0x0256bb04, + 0x75fd50bd, + 0x7e50fc04, + 0xb6000600, + 0x11f40464, + 0xe05bcb67, + 0xb60076bb, + 0x50f90465, + 0xbb046594, + 0x50bd0256, + 0xfc0475fd, + 0x054c7e50, + 0x0464b600, + 0x74bd5bb2, +/* 0x0823: i2c_recv_not_rd08 */ + 0xb0410ef4, + 0x1bf401d6, + 0x7e00053b, + 0xf40006a9, + 0xc5c73211, + 0x064f7ee0, + 0x2811f400, + 0xa97e0005, + 0x11f40006, + 0xe0b5c71f, + 0x00064f7e, + 0x7e1511f4, + 0xbd00054c, + 0x08c5c774, + 0xf4091bf4, + 0x0ef40232, +/* 0x0861: i2c_recv_not_wr08 */ +/* 0x0861: i2c_recv_done */ + 0xf8cec703, + 0x00070d7e, + 0xd0fce0fc, + 0xb20912f4, + 0x023f7e7c, +/* 0x0875: i2c_recv_exit */ +/* 0x0877: i2c_init */ + 0xf800f800, +/* 0x0879: test_recv */ 0x04584100, 0xb60011cf, 0x58400110, @@ -1128,26 +1424,26 @@ uint32_t nv108_pwr_code[] = { 0xe3f1d900, 0x967e134f, 0x00f80001, -/* 0x0494: test_init */ +/* 0x0898: test_init */ 0x7e08004e, 0xf8000196, -/* 0x049d: idle_recv */ -/* 0x049f: idle */ +/* 0x08a1: idle_recv */ +/* 0x08a3: idle */ 0xf400f800, 0x54410031, 0x0011cf04, 0x400110b6, 0x01f60454, -/* 0x04b3: idle_loop */ +/* 0x08b7: idle_loop */ 0x0104bd00, 0x0232f458, -/* 0x04b8: idle_proc */ -/* 0x04b8: idle_proc_exec */ +/* 0x08bc: idle_proc */ +/* 0x08bc: idle_proc_exec */ 0x1eb210f9, 0x0002487e, 0x11f410fc, 0x0231f409, -/* 0x04cb: idle_proc_next */ +/* 0x08cf: idle_proc_next */ 0xb6f00ef4, 0x1fa65810, 0xf4e81bf4, @@ -1161,5 +1457,4 @@ uint32_t nv108_pwr_code[] = { 0x00000000, 0x00000000, 0x00000000, - 0x00000000, }; diff --git a/drivers/gpu/drm/nouveau/core/subdev/pwr/fuc/nva3.fuc b/drivers/gpu/drm/nouveau/core/subdev/pwr/fuc/nva3.fuc index 6fde0b89e5aa..6744fcc06151 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/pwr/fuc/nva3.fuc +++ b/drivers/gpu/drm/nouveau/core/subdev/pwr/fuc/nva3.fuc @@ -37,6 +37,7 @@ #include "host.fuc" #include "memx.fuc" #include "perf.fuc" +#include "i2c_.fuc" #include "test.fuc" #include "idle.fuc" #undef INCLUDE_PROC @@ -46,6 +47,7 @@ #include "host.fuc" #include "memx.fuc" #include "perf.fuc" +#include "i2c_.fuc" #include "test.fuc" #include "idle.fuc" #undef INCLUDE_DATA @@ -57,6 +59,7 @@ #include "host.fuc" #include "memx.fuc" #include "perf.fuc" +#include "i2c_.fuc" #include "test.fuc" #include "idle.fuc" #undef INCLUDE_CODE diff --git a/drivers/gpu/drm/nouveau/core/subdev/pwr/fuc/nva3.fuc.h b/drivers/gpu/drm/nouveau/core/subdev/pwr/fuc/nva3.fuc.h index 0fa4d7dcd407..5a73fa620978 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/pwr/fuc/nva3.fuc.h +++ b/drivers/gpu/drm/nouveau/core/subdev/pwr/fuc/nva3.fuc.h @@ -89,9 +89,31 @@ uint32_t nva3_pwr_data[] = { 0x00000000, 0x00000000, 0x00000000, + 0x5f433249, + 0x00000982, + 0x00000825, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, 0x54534554, - 0x0000057b, - 0x00000554, + 0x000009ab, + 0x00000984, 0x00000000, 0x00000000, 0x00000000, @@ -112,8 +134,8 @@ uint32_t nva3_pwr_data[] = { 0x00000000, 0x00000000, 0x454c4449, - 0x00000587, - 0x00000585, + 0x000009b7, + 0x000009b5, 0x00000000, 0x00000000, 0x00000000, @@ -133,12 +155,12 @@ uint32_t nva3_pwr_data[] = { 0x00000000, 0x00000000, 0x00000000, -/* 0x0210: proc_list_tail */ -/* 0x0210: time_prev */ +/* 0x0268: proc_list_tail */ +/* 0x0268: time_prev */ 0x00000000, -/* 0x0214: time_next */ +/* 0x026c: time_next */ 0x00000000, -/* 0x0218: fifo_queue */ +/* 0x0270: fifo_queue */ 0x00000000, 0x00000000, 0x00000000, @@ -171,7 +193,7 @@ uint32_t nva3_pwr_data[] = { 0x00000000, 0x00000000, 0x00000000, -/* 0x0298: rfifo_queue */ +/* 0x02f0: rfifo_queue */ 0x00000000, 0x00000000, 0x00000000, @@ -204,11 +226,11 @@ uint32_t nva3_pwr_data[] = { 0x00000000, 0x00000000, 0x00000000, -/* 0x0318: memx_func_head */ +/* 0x0370: memx_func_head */ 0x00010000, 0x00000000, 0x0000046f, -/* 0x0324: memx_func_next */ +/* 0x037c: memx_func_next */ 0x00000001, 0x00000000, 0x00000496, @@ -221,8 +243,18 @@ uint32_t nva3_pwr_data[] = { 0x00010004, 0x00000000, 0x000004fc, -/* 0x0354: memx_func_tail */ -/* 0x0354: memx_data_head */ +/* 0x03ac: memx_func_tail */ +/* 0x03ac: memx_data_head */ + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, @@ -725,6 +757,42 @@ uint32_t nva3_pwr_data[] = { 0x00000000, 0x00000000, 0x00000000, +/* 0x0bac: memx_data_tail */ +/* 0x0bac: i2c_scl_map */ + 0x00001000, + 0x00004000, + 0x00010000, + 0x00000100, + 0x00040000, + 0x00100000, + 0x00400000, + 0x01000000, + 0x04000000, + 0x10000000, +/* 0x0bd4: i2c_sda_map */ + 0x00002000, + 0x00008000, + 0x00020000, + 0x00000200, + 0x00080000, + 0x00200000, + 0x00800000, + 0x02000000, + 0x08000000, + 0x20000000, +/* 0x0bfc: i2c_ctrl */ + 0x0000e138, + 0x0000e150, + 0x0000e168, + 0x0000e180, + 0x0000e254, + 0x0000e274, + 0x0000e764, + 0x0000e780, + 0x0000e79c, + 0x0000e7b8, + 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, @@ -735,7 +803,6 @@ uint32_t nva3_pwr_data[] = { 0x00000000, 0x00000000, 0x00000000, -/* 0x0b54: memx_data_tail */ 0x00000000, 0x00000000, 0x00000000, @@ -787,15 +854,15 @@ uint32_t nva3_pwr_code[] = { 0x07a007f1, 0xd00604b6, 0x04bd000e, - 0xf001e7f0, - 0x07f101e3, + 0xf001d7f0, + 0x07f101d3, 0x04b607ac, - 0x000ed006, + 0x000dd006, /* 0x0022: rd32_wait */ - 0xe7f104bd, - 0xe4b607ac, - 0x00eecf06, - 0x7000e4f1, + 0xd7f104bd, + 0xd4b607ac, + 0x00ddcf06, + 0x7000d4f1, 0xf1f21bf4, 0xb607a4d7, 0xddcf06d4, @@ -807,15 +874,15 @@ uint32_t nva3_pwr_code[] = { 0xb607a407, 0x0dd00604, 0xf004bd00, - 0xe5f002e7, - 0x01e3f0f0, + 0xd5f002d7, + 0x01d3f0f0, 0x07ac07f1, 0xd00604b6, - 0x04bd000e, + 0x04bd000d, /* 0x006c: wr32_wait */ - 0x07ace7f1, - 0xcf06e4b6, - 0xe4f100ee, + 0x07acd7f1, + 0xcf06d4b6, + 0xd4f100dd, 0x1bf47000, /* 0x007f: nsec */ 0xf000f8f2, @@ -845,21 +912,21 @@ uint32_t nva3_pwr_code[] = { 0x9800f8df, 0x96b003e9, 0x2a0bf400, - 0xbb840a98, + 0xbb9a0a98, 0x1cf4029a, 0x01d7f00f, 0x025421f5, 0x0ef494bd, /* 0x00e9: intr_watchdog_next_time */ - 0x850a9815, + 0x9b0a9815, 0xf400a6b0, 0x9ab8090b, 0x061cf406, /* 0x00f8: intr_watchdog_next_time_set */ /* 0x00fb: intr_watchdog_next_proc */ - 0x80850980, + 0x809b0980, 0xe0b603e9, - 0x10e6b158, + 0x68e6b158, 0xc61bf402, /* 0x010a: intr */ 0x00f900f8, @@ -880,15 +947,15 @@ uint32_t nva3_pwr_code[] = { 0x0088cf06, 0xf40289c4, 0x0080230b, - 0x58e7f085, + 0x58e7f09b, 0x98cb21f4, - 0x96b08509, + 0x96b09b09, 0x110bf400, 0xb63407f0, 0x09d00604, 0x8004bd00, /* 0x016e: intr_skip_watchdog */ - 0x89e48409, + 0x89e49a09, 0x0bf40800, 0x8897f148, 0x0694b606, @@ -948,7 +1015,7 @@ uint32_t nva3_pwr_code[] = { 0x000ed006, 0x0e8004bd, /* 0x0241: timer_enable */ - 0x0187f084, + 0x0187f09a, 0xb63807f0, 0x08d00604, /* 0x024f: timer_done */ @@ -979,7 +1046,7 @@ uint32_t nva3_pwr_code[] = { 0xb8008a98, 0x0bf406ae, 0x5880b610, - 0x021086b1, + 0x026886b1, 0xf4f01bf4, /* 0x02b2: find_done */ 0x8eb90132, @@ -1049,7 +1116,7 @@ uint32_t nva3_pwr_code[] = { 0x320bf406, 0x94071ec4, 0xe0b704ee, - 0xeb980218, + 0xeb980270, 0x02ec9803, 0x9801ed98, 0x21f500ee, @@ -1075,7 +1142,7 @@ uint32_t nva3_pwr_code[] = { 0xe60bf406, 0xb60723c4, 0x30b70434, - 0x3b800298, + 0x3b8002f0, 0x023c8003, 0x80013d80, 0x20b6003e, @@ -1090,13 +1157,13 @@ uint32_t nva3_pwr_code[] = { /* 0x0430: host_init */ 0x008017f1, 0xf11014b6, - 0xf1021815, + 0xf1027015, 0xb604d007, 0x01d00604, 0xf104bd00, 0xb6008017, 0x15f11014, - 0x07f10298, + 0x07f102f0, 0x04b604dc, 0x0001d006, 0x17f004bd, @@ -1156,14 +1223,14 @@ uint32_t nva3_pwr_code[] = { 0x00139802, 0x950410b6, 0x30f01034, - 0xc835980c, + 0xde35980c, 0x12b855f9, 0xec1ef406, 0xe0fcd0fc, 0x02b921f5, /* 0x0532: memx_info */ 0xc7f100f8, - 0xb7f10354, + 0xb7f103ac, 0x21f50800, 0x00f802b9, /* 0x0540: memx_recv */ @@ -1175,7 +1242,312 @@ uint32_t nva3_pwr_code[] = { /* 0x0550: perf_recv */ /* 0x0552: perf_init */ 0x00f800f8, -/* 0x0554: test_recv */ +/* 0x0554: i2c_drive_scl */ + 0xf40036b0, + 0x07f1110b, + 0x04b607e0, + 0x0001d006, + 0x00f804bd, +/* 0x0568: i2c_drive_scl_lo */ + 0x07e407f1, + 0xd00604b6, + 0x04bd0001, +/* 0x0576: i2c_drive_sda */ + 0x36b000f8, + 0x110bf400, + 0x07e007f1, + 0xd00604b6, + 0x04bd0002, +/* 0x058a: i2c_drive_sda_lo */ + 0x07f100f8, + 0x04b607e4, + 0x0002d006, + 0x00f804bd, +/* 0x0598: i2c_sense_scl */ + 0xf10132f4, + 0xb607c437, + 0x33cf0634, + 0x0431fd00, + 0xf4060bf4, +/* 0x05ae: i2c_sense_scl_done */ + 0x00f80131, +/* 0x05b0: i2c_sense_sda */ + 0xf10132f4, + 0xb607c437, + 0x33cf0634, + 0x0432fd00, + 0xf4060bf4, +/* 0x05c6: i2c_sense_sda_done */ + 0x00f80131, +/* 0x05c8: i2c_raise_scl */ + 0x47f140f9, + 0x37f00898, + 0x5421f501, +/* 0x05d5: i2c_raise_scl_wait */ + 0xe8e7f105, + 0x7f21f403, + 0x059821f5, + 0xb60901f4, + 0x1bf40142, +/* 0x05e9: i2c_raise_scl_done */ + 0xf840fcef, +/* 0x05ed: i2c_start */ + 0x9821f500, + 0x0d11f405, + 0x05b021f5, + 0xf40611f4, +/* 0x05fe: i2c_start_rep */ + 0x37f0300e, + 0x5421f500, + 0x0137f005, + 0x057621f5, + 0xb60076bb, + 0x50f90465, + 0xbb046594, + 0x50bd0256, + 0xfc0475fd, + 0xc821f550, + 0x0464b605, +/* 0x062b: i2c_start_send */ + 0xf01f11f4, + 0x21f50037, + 0xe7f10576, + 0x21f41388, + 0x0037f07f, + 0x055421f5, + 0x1388e7f1, +/* 0x0647: i2c_start_out */ + 0xf87f21f4, +/* 0x0649: i2c_stop */ + 0x0037f000, + 0x055421f5, + 0xf50037f0, + 0xf1057621, + 0xf403e8e7, + 0x37f07f21, + 0x5421f501, + 0x88e7f105, + 0x7f21f413, + 0xf50137f0, + 0xf1057621, + 0xf41388e7, + 0x00f87f21, +/* 0x067c: i2c_bitw */ + 0x057621f5, + 0x03e8e7f1, + 0xbb7f21f4, + 0x65b60076, + 0x9450f904, + 0x56bb0465, + 0xfd50bd02, + 0x50fc0475, + 0x05c821f5, + 0xf40464b6, + 0xe7f11811, + 0x21f41388, + 0x0037f07f, + 0x055421f5, + 0x1388e7f1, +/* 0x06bb: i2c_bitw_out */ + 0xf87f21f4, +/* 0x06bd: i2c_bitr */ + 0x0137f000, + 0x057621f5, + 0x03e8e7f1, + 0xbb7f21f4, + 0x65b60076, + 0x9450f904, + 0x56bb0465, + 0xfd50bd02, + 0x50fc0475, + 0x05c821f5, + 0xf40464b6, + 0x21f51b11, + 0x37f005b0, + 0x5421f500, + 0x88e7f105, + 0x7f21f413, + 0xf4013cf0, +/* 0x0702: i2c_bitr_done */ + 0x00f80131, +/* 0x0704: i2c_get_byte */ + 0xf00057f0, +/* 0x070a: i2c_get_byte_next */ + 0x54b60847, + 0x0076bb01, + 0xf90465b6, + 0x04659450, + 0xbd0256bb, + 0x0475fd50, + 0x21f550fc, + 0x64b606bd, + 0x2b11f404, + 0xb60553fd, + 0x1bf40142, + 0x0137f0d8, + 0xb60076bb, + 0x50f90465, + 0xbb046594, + 0x50bd0256, + 0xfc0475fd, + 0x7c21f550, + 0x0464b606, +/* 0x0754: i2c_get_byte_done */ +/* 0x0756: i2c_put_byte */ + 0x47f000f8, +/* 0x0759: i2c_put_byte_next */ + 0x0142b608, + 0xbb3854ff, + 0x65b60076, + 0x9450f904, + 0x56bb0465, + 0xfd50bd02, + 0x50fc0475, + 0x067c21f5, + 0xf40464b6, + 0x46b03411, + 0xd81bf400, + 0xb60076bb, + 0x50f90465, + 0xbb046594, + 0x50bd0256, + 0xfc0475fd, + 0xbd21f550, + 0x0464b606, + 0xbb0f11f4, + 0x36b00076, + 0x061bf401, +/* 0x07af: i2c_put_byte_done */ + 0xf80132f4, +/* 0x07b1: i2c_addr */ + 0x0076bb00, + 0xf90465b6, + 0x04659450, + 0xbd0256bb, + 0x0475fd50, + 0x21f550fc, + 0x64b605ed, + 0x2911f404, + 0x012ec3e7, + 0xfd0134b6, + 0x76bb0553, + 0x0465b600, + 0x659450f9, + 0x0256bb04, + 0x75fd50bd, + 0xf550fc04, + 0xb6075621, +/* 0x07f6: i2c_addr_done */ + 0x00f80464, +/* 0x07f8: i2c_acquire_addr */ + 0xb6f8cec7, + 0xe0b702e4, + 0xee980bfc, +/* 0x0807: i2c_acquire */ + 0xf500f800, + 0xf407f821, + 0xd9f00421, + 0x3f21f403, +/* 0x0816: i2c_release */ + 0x21f500f8, + 0x21f407f8, + 0x03daf004, + 0xf83f21f4, +/* 0x0825: i2c_recv */ + 0x0132f400, + 0xb6f8c1c7, + 0x16b00214, + 0x3a1ff528, + 0xd413a001, + 0x0032980b, + 0x0bac13a0, + 0xf4003198, + 0xd0f90231, + 0xd0f9e0f9, + 0x000067f1, + 0x100063f1, + 0xbb016792, + 0x65b60076, + 0x9450f904, + 0x56bb0465, + 0xfd50bd02, + 0x50fc0475, + 0x080721f5, + 0xfc0464b6, + 0x00d6b0d0, + 0x00b31bf5, + 0xbb0057f0, + 0x65b60076, + 0x9450f904, + 0x56bb0465, + 0xfd50bd02, + 0x50fc0475, + 0x07b121f5, + 0xf50464b6, + 0xc700d011, + 0x76bbe0c5, + 0x0465b600, + 0x659450f9, + 0x0256bb04, + 0x75fd50bd, + 0xf550fc04, + 0xb6075621, + 0x11f50464, + 0x57f000ad, + 0x0076bb01, + 0xf90465b6, + 0x04659450, + 0xbd0256bb, + 0x0475fd50, + 0x21f550fc, + 0x64b607b1, + 0x8a11f504, + 0x0076bb00, + 0xf90465b6, + 0x04659450, + 0xbd0256bb, + 0x0475fd50, + 0x21f550fc, + 0x64b60704, + 0x6a11f404, + 0xbbe05bcb, + 0x65b60076, + 0x9450f904, + 0x56bb0465, + 0xfd50bd02, + 0x50fc0475, + 0x064921f5, + 0xb90464b6, + 0x74bd025b, +/* 0x092b: i2c_recv_not_rd08 */ + 0xb0430ef4, + 0x1bf401d6, + 0x0057f03d, + 0x07b121f5, + 0xc73311f4, + 0x21f5e0c5, + 0x11f40756, + 0x0057f029, + 0x07b121f5, + 0xc71f11f4, + 0x21f5e0b5, + 0x11f40756, + 0x4921f515, + 0xc774bd06, + 0x1bf408c5, + 0x0232f409, +/* 0x096b: i2c_recv_not_wr08 */ +/* 0x096b: i2c_recv_done */ + 0xc7030ef4, + 0x21f5f8ce, + 0xe0fc0816, + 0x12f4d0fc, + 0x027cb90a, + 0x02b921f5, +/* 0x0980: i2c_recv_exit */ +/* 0x0982: i2c_init */ + 0x00f800f8, +/* 0x0984: test_recv */ 0x05d817f1, 0xcf0614b6, 0x10b60011, @@ -1185,12 +1557,12 @@ uint32_t nva3_pwr_code[] = { 0x00e7f104, 0x4fe3f1d9, 0xf521f513, -/* 0x057b: test_init */ +/* 0x09ab: test_init */ 0xf100f801, 0xf50800e7, 0xf801f521, -/* 0x0585: idle_recv */ -/* 0x0587: idle */ +/* 0x09b5: idle_recv */ +/* 0x09b7: idle */ 0xf400f800, 0x17f10031, 0x14b605d4, @@ -1198,32 +1570,20 @@ uint32_t nva3_pwr_code[] = { 0xf10110b6, 0xb605d407, 0x01d00604, -/* 0x05a3: idle_loop */ +/* 0x09d3: idle_loop */ 0xf004bd00, 0x32f45817, -/* 0x05a9: idle_proc */ -/* 0x05a9: idle_proc_exec */ +/* 0x09d9: idle_proc */ +/* 0x09d9: idle_proc_exec */ 0xb910f902, 0x21f5021e, 0x10fc02c2, 0xf40911f4, 0x0ef40231, -/* 0x05bd: idle_proc_next */ +/* 0x09ed: idle_proc_next */ 0x5810b6ef, 0xf4061fb8, 0x02f4e61b, 0x0028f4dd, 0x00bb0ef4, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, }; diff --git a/drivers/gpu/drm/nouveau/core/subdev/pwr/fuc/nvc0.fuc b/drivers/gpu/drm/nouveau/core/subdev/pwr/fuc/nvc0.fuc index eaa64da68e36..48f79434a449 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/pwr/fuc/nvc0.fuc +++ b/drivers/gpu/drm/nouveau/core/subdev/pwr/fuc/nvc0.fuc @@ -37,6 +37,7 @@ #include "host.fuc" #include "memx.fuc" #include "perf.fuc" +#include "i2c_.fuc" #include "test.fuc" #include "idle.fuc" #undef INCLUDE_PROC @@ -46,6 +47,7 @@ #include "host.fuc" #include "memx.fuc" #include "perf.fuc" +#include "i2c_.fuc" #include "test.fuc" #include "idle.fuc" #undef INCLUDE_DATA @@ -57,6 +59,7 @@ #include "host.fuc" #include "memx.fuc" #include "perf.fuc" +#include "i2c_.fuc" #include "test.fuc" #include "idle.fuc" #undef INCLUDE_CODE diff --git a/drivers/gpu/drm/nouveau/core/subdev/pwr/fuc/nvc0.fuc.h b/drivers/gpu/drm/nouveau/core/subdev/pwr/fuc/nvc0.fuc.h index 82c8e8b88917..4dba00d2dd1a 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/pwr/fuc/nvc0.fuc.h +++ b/drivers/gpu/drm/nouveau/core/subdev/pwr/fuc/nvc0.fuc.h @@ -89,9 +89,31 @@ uint32_t nvc0_pwr_data[] = { 0x00000000, 0x00000000, 0x00000000, + 0x5f433249, + 0x00000982, + 0x00000825, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, 0x54534554, - 0x0000057b, - 0x00000554, + 0x000009ab, + 0x00000984, 0x00000000, 0x00000000, 0x00000000, @@ -112,8 +134,8 @@ uint32_t nvc0_pwr_data[] = { 0x00000000, 0x00000000, 0x454c4449, - 0x00000587, - 0x00000585, + 0x000009b7, + 0x000009b5, 0x00000000, 0x00000000, 0x00000000, @@ -133,12 +155,12 @@ uint32_t nvc0_pwr_data[] = { 0x00000000, 0x00000000, 0x00000000, -/* 0x0210: proc_list_tail */ -/* 0x0210: time_prev */ +/* 0x0268: proc_list_tail */ +/* 0x0268: time_prev */ 0x00000000, -/* 0x0214: time_next */ +/* 0x026c: time_next */ 0x00000000, -/* 0x0218: fifo_queue */ +/* 0x0270: fifo_queue */ 0x00000000, 0x00000000, 0x00000000, @@ -171,7 +193,7 @@ uint32_t nvc0_pwr_data[] = { 0x00000000, 0x00000000, 0x00000000, -/* 0x0298: rfifo_queue */ +/* 0x02f0: rfifo_queue */ 0x00000000, 0x00000000, 0x00000000, @@ -204,11 +226,11 @@ uint32_t nvc0_pwr_data[] = { 0x00000000, 0x00000000, 0x00000000, -/* 0x0318: memx_func_head */ +/* 0x0370: memx_func_head */ 0x00010000, 0x00000000, 0x0000046f, -/* 0x0324: memx_func_next */ +/* 0x037c: memx_func_next */ 0x00000001, 0x00000000, 0x00000496, @@ -221,8 +243,18 @@ uint32_t nvc0_pwr_data[] = { 0x00010004, 0x00000000, 0x000004fc, -/* 0x0354: memx_func_tail */ -/* 0x0354: memx_data_head */ +/* 0x03ac: memx_func_tail */ +/* 0x03ac: memx_data_head */ + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, @@ -725,6 +757,42 @@ uint32_t nvc0_pwr_data[] = { 0x00000000, 0x00000000, 0x00000000, +/* 0x0bac: memx_data_tail */ +/* 0x0bac: i2c_scl_map */ + 0x00001000, + 0x00004000, + 0x00010000, + 0x00000100, + 0x00040000, + 0x00100000, + 0x00400000, + 0x01000000, + 0x04000000, + 0x10000000, +/* 0x0bd4: i2c_sda_map */ + 0x00002000, + 0x00008000, + 0x00020000, + 0x00000200, + 0x00080000, + 0x00200000, + 0x00800000, + 0x02000000, + 0x08000000, + 0x20000000, +/* 0x0bfc: i2c_ctrl */ + 0x0000e138, + 0x0000e150, + 0x0000e168, + 0x0000e180, + 0x0000e254, + 0x0000e274, + 0x0000e764, + 0x0000e780, + 0x0000e79c, + 0x0000e7b8, + 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, @@ -735,7 +803,6 @@ uint32_t nvc0_pwr_data[] = { 0x00000000, 0x00000000, 0x00000000, -/* 0x0b54: memx_data_tail */ 0x00000000, 0x00000000, 0x00000000, @@ -787,15 +854,15 @@ uint32_t nvc0_pwr_code[] = { 0x07a007f1, 0xd00604b6, 0x04bd000e, - 0xf001e7f0, - 0x07f101e3, + 0xf001d7f0, + 0x07f101d3, 0x04b607ac, - 0x000ed006, + 0x000dd006, /* 0x0022: rd32_wait */ - 0xe7f104bd, - 0xe4b607ac, - 0x00eecf06, - 0x7000e4f1, + 0xd7f104bd, + 0xd4b607ac, + 0x00ddcf06, + 0x7000d4f1, 0xf1f21bf4, 0xb607a4d7, 0xddcf06d4, @@ -807,15 +874,15 @@ uint32_t nvc0_pwr_code[] = { 0xb607a407, 0x0dd00604, 0xf004bd00, - 0xe5f002e7, - 0x01e3f0f0, + 0xd5f002d7, + 0x01d3f0f0, 0x07ac07f1, 0xd00604b6, - 0x04bd000e, + 0x04bd000d, /* 0x006c: wr32_wait */ - 0x07ace7f1, - 0xcf06e4b6, - 0xe4f100ee, + 0x07acd7f1, + 0xcf06d4b6, + 0xd4f100dd, 0x1bf47000, /* 0x007f: nsec */ 0xf000f8f2, @@ -845,21 +912,21 @@ uint32_t nvc0_pwr_code[] = { 0x9800f8df, 0x96b003e9, 0x2a0bf400, - 0xbb840a98, + 0xbb9a0a98, 0x1cf4029a, 0x01d7f00f, 0x025421f5, 0x0ef494bd, /* 0x00e9: intr_watchdog_next_time */ - 0x850a9815, + 0x9b0a9815, 0xf400a6b0, 0x9ab8090b, 0x061cf406, /* 0x00f8: intr_watchdog_next_time_set */ /* 0x00fb: intr_watchdog_next_proc */ - 0x80850980, + 0x809b0980, 0xe0b603e9, - 0x10e6b158, + 0x68e6b158, 0xc61bf402, /* 0x010a: intr */ 0x00f900f8, @@ -880,15 +947,15 @@ uint32_t nvc0_pwr_code[] = { 0x0088cf06, 0xf40289c4, 0x0080230b, - 0x58e7f085, + 0x58e7f09b, 0x98cb21f4, - 0x96b08509, + 0x96b09b09, 0x110bf400, 0xb63407f0, 0x09d00604, 0x8004bd00, /* 0x016e: intr_skip_watchdog */ - 0x89e48409, + 0x89e49a09, 0x0bf40800, 0x8897f148, 0x0694b606, @@ -948,7 +1015,7 @@ uint32_t nvc0_pwr_code[] = { 0x000ed006, 0x0e8004bd, /* 0x0241: timer_enable */ - 0x0187f084, + 0x0187f09a, 0xb63807f0, 0x08d00604, /* 0x024f: timer_done */ @@ -979,7 +1046,7 @@ uint32_t nvc0_pwr_code[] = { 0xb8008a98, 0x0bf406ae, 0x5880b610, - 0x021086b1, + 0x026886b1, 0xf4f01bf4, /* 0x02b2: find_done */ 0x8eb90132, @@ -1049,7 +1116,7 @@ uint32_t nvc0_pwr_code[] = { 0x320bf406, 0x94071ec4, 0xe0b704ee, - 0xeb980218, + 0xeb980270, 0x02ec9803, 0x9801ed98, 0x21f500ee, @@ -1075,7 +1142,7 @@ uint32_t nvc0_pwr_code[] = { 0xe60bf406, 0xb60723c4, 0x30b70434, - 0x3b800298, + 0x3b8002f0, 0x023c8003, 0x80013d80, 0x20b6003e, @@ -1090,13 +1157,13 @@ uint32_t nvc0_pwr_code[] = { /* 0x0430: host_init */ 0x008017f1, 0xf11014b6, - 0xf1021815, + 0xf1027015, 0xb604d007, 0x01d00604, 0xf104bd00, 0xb6008017, 0x15f11014, - 0x07f10298, + 0x07f102f0, 0x04b604dc, 0x0001d006, 0x17f004bd, @@ -1156,14 +1223,14 @@ uint32_t nvc0_pwr_code[] = { 0x00139802, 0x950410b6, 0x30f01034, - 0xc835980c, + 0xde35980c, 0x12b855f9, 0xec1ef406, 0xe0fcd0fc, 0x02b921f5, /* 0x0532: memx_info */ 0xc7f100f8, - 0xb7f10354, + 0xb7f103ac, 0x21f50800, 0x00f802b9, /* 0x0540: memx_recv */ @@ -1175,7 +1242,312 @@ uint32_t nvc0_pwr_code[] = { /* 0x0550: perf_recv */ /* 0x0552: perf_init */ 0x00f800f8, -/* 0x0554: test_recv */ +/* 0x0554: i2c_drive_scl */ + 0xf40036b0, + 0x07f1110b, + 0x04b607e0, + 0x0001d006, + 0x00f804bd, +/* 0x0568: i2c_drive_scl_lo */ + 0x07e407f1, + 0xd00604b6, + 0x04bd0001, +/* 0x0576: i2c_drive_sda */ + 0x36b000f8, + 0x110bf400, + 0x07e007f1, + 0xd00604b6, + 0x04bd0002, +/* 0x058a: i2c_drive_sda_lo */ + 0x07f100f8, + 0x04b607e4, + 0x0002d006, + 0x00f804bd, +/* 0x0598: i2c_sense_scl */ + 0xf10132f4, + 0xb607c437, + 0x33cf0634, + 0x0431fd00, + 0xf4060bf4, +/* 0x05ae: i2c_sense_scl_done */ + 0x00f80131, +/* 0x05b0: i2c_sense_sda */ + 0xf10132f4, + 0xb607c437, + 0x33cf0634, + 0x0432fd00, + 0xf4060bf4, +/* 0x05c6: i2c_sense_sda_done */ + 0x00f80131, +/* 0x05c8: i2c_raise_scl */ + 0x47f140f9, + 0x37f00898, + 0x5421f501, +/* 0x05d5: i2c_raise_scl_wait */ + 0xe8e7f105, + 0x7f21f403, + 0x059821f5, + 0xb60901f4, + 0x1bf40142, +/* 0x05e9: i2c_raise_scl_done */ + 0xf840fcef, +/* 0x05ed: i2c_start */ + 0x9821f500, + 0x0d11f405, + 0x05b021f5, + 0xf40611f4, +/* 0x05fe: i2c_start_rep */ + 0x37f0300e, + 0x5421f500, + 0x0137f005, + 0x057621f5, + 0xb60076bb, + 0x50f90465, + 0xbb046594, + 0x50bd0256, + 0xfc0475fd, + 0xc821f550, + 0x0464b605, +/* 0x062b: i2c_start_send */ + 0xf01f11f4, + 0x21f50037, + 0xe7f10576, + 0x21f41388, + 0x0037f07f, + 0x055421f5, + 0x1388e7f1, +/* 0x0647: i2c_start_out */ + 0xf87f21f4, +/* 0x0649: i2c_stop */ + 0x0037f000, + 0x055421f5, + 0xf50037f0, + 0xf1057621, + 0xf403e8e7, + 0x37f07f21, + 0x5421f501, + 0x88e7f105, + 0x7f21f413, + 0xf50137f0, + 0xf1057621, + 0xf41388e7, + 0x00f87f21, +/* 0x067c: i2c_bitw */ + 0x057621f5, + 0x03e8e7f1, + 0xbb7f21f4, + 0x65b60076, + 0x9450f904, + 0x56bb0465, + 0xfd50bd02, + 0x50fc0475, + 0x05c821f5, + 0xf40464b6, + 0xe7f11811, + 0x21f41388, + 0x0037f07f, + 0x055421f5, + 0x1388e7f1, +/* 0x06bb: i2c_bitw_out */ + 0xf87f21f4, +/* 0x06bd: i2c_bitr */ + 0x0137f000, + 0x057621f5, + 0x03e8e7f1, + 0xbb7f21f4, + 0x65b60076, + 0x9450f904, + 0x56bb0465, + 0xfd50bd02, + 0x50fc0475, + 0x05c821f5, + 0xf40464b6, + 0x21f51b11, + 0x37f005b0, + 0x5421f500, + 0x88e7f105, + 0x7f21f413, + 0xf4013cf0, +/* 0x0702: i2c_bitr_done */ + 0x00f80131, +/* 0x0704: i2c_get_byte */ + 0xf00057f0, +/* 0x070a: i2c_get_byte_next */ + 0x54b60847, + 0x0076bb01, + 0xf90465b6, + 0x04659450, + 0xbd0256bb, + 0x0475fd50, + 0x21f550fc, + 0x64b606bd, + 0x2b11f404, + 0xb60553fd, + 0x1bf40142, + 0x0137f0d8, + 0xb60076bb, + 0x50f90465, + 0xbb046594, + 0x50bd0256, + 0xfc0475fd, + 0x7c21f550, + 0x0464b606, +/* 0x0754: i2c_get_byte_done */ +/* 0x0756: i2c_put_byte */ + 0x47f000f8, +/* 0x0759: i2c_put_byte_next */ + 0x0142b608, + 0xbb3854ff, + 0x65b60076, + 0x9450f904, + 0x56bb0465, + 0xfd50bd02, + 0x50fc0475, + 0x067c21f5, + 0xf40464b6, + 0x46b03411, + 0xd81bf400, + 0xb60076bb, + 0x50f90465, + 0xbb046594, + 0x50bd0256, + 0xfc0475fd, + 0xbd21f550, + 0x0464b606, + 0xbb0f11f4, + 0x36b00076, + 0x061bf401, +/* 0x07af: i2c_put_byte_done */ + 0xf80132f4, +/* 0x07b1: i2c_addr */ + 0x0076bb00, + 0xf90465b6, + 0x04659450, + 0xbd0256bb, + 0x0475fd50, + 0x21f550fc, + 0x64b605ed, + 0x2911f404, + 0x012ec3e7, + 0xfd0134b6, + 0x76bb0553, + 0x0465b600, + 0x659450f9, + 0x0256bb04, + 0x75fd50bd, + 0xf550fc04, + 0xb6075621, +/* 0x07f6: i2c_addr_done */ + 0x00f80464, +/* 0x07f8: i2c_acquire_addr */ + 0xb6f8cec7, + 0xe0b702e4, + 0xee980bfc, +/* 0x0807: i2c_acquire */ + 0xf500f800, + 0xf407f821, + 0xd9f00421, + 0x3f21f403, +/* 0x0816: i2c_release */ + 0x21f500f8, + 0x21f407f8, + 0x03daf004, + 0xf83f21f4, +/* 0x0825: i2c_recv */ + 0x0132f400, + 0xb6f8c1c7, + 0x16b00214, + 0x3a1ff528, + 0xd413a001, + 0x0032980b, + 0x0bac13a0, + 0xf4003198, + 0xd0f90231, + 0xd0f9e0f9, + 0x000067f1, + 0x100063f1, + 0xbb016792, + 0x65b60076, + 0x9450f904, + 0x56bb0465, + 0xfd50bd02, + 0x50fc0475, + 0x080721f5, + 0xfc0464b6, + 0x00d6b0d0, + 0x00b31bf5, + 0xbb0057f0, + 0x65b60076, + 0x9450f904, + 0x56bb0465, + 0xfd50bd02, + 0x50fc0475, + 0x07b121f5, + 0xf50464b6, + 0xc700d011, + 0x76bbe0c5, + 0x0465b600, + 0x659450f9, + 0x0256bb04, + 0x75fd50bd, + 0xf550fc04, + 0xb6075621, + 0x11f50464, + 0x57f000ad, + 0x0076bb01, + 0xf90465b6, + 0x04659450, + 0xbd0256bb, + 0x0475fd50, + 0x21f550fc, + 0x64b607b1, + 0x8a11f504, + 0x0076bb00, + 0xf90465b6, + 0x04659450, + 0xbd0256bb, + 0x0475fd50, + 0x21f550fc, + 0x64b60704, + 0x6a11f404, + 0xbbe05bcb, + 0x65b60076, + 0x9450f904, + 0x56bb0465, + 0xfd50bd02, + 0x50fc0475, + 0x064921f5, + 0xb90464b6, + 0x74bd025b, +/* 0x092b: i2c_recv_not_rd08 */ + 0xb0430ef4, + 0x1bf401d6, + 0x0057f03d, + 0x07b121f5, + 0xc73311f4, + 0x21f5e0c5, + 0x11f40756, + 0x0057f029, + 0x07b121f5, + 0xc71f11f4, + 0x21f5e0b5, + 0x11f40756, + 0x4921f515, + 0xc774bd06, + 0x1bf408c5, + 0x0232f409, +/* 0x096b: i2c_recv_not_wr08 */ +/* 0x096b: i2c_recv_done */ + 0xc7030ef4, + 0x21f5f8ce, + 0xe0fc0816, + 0x12f4d0fc, + 0x027cb90a, + 0x02b921f5, +/* 0x0980: i2c_recv_exit */ +/* 0x0982: i2c_init */ + 0x00f800f8, +/* 0x0984: test_recv */ 0x05d817f1, 0xcf0614b6, 0x10b60011, @@ -1185,12 +1557,12 @@ uint32_t nvc0_pwr_code[] = { 0x00e7f104, 0x4fe3f1d9, 0xf521f513, -/* 0x057b: test_init */ +/* 0x09ab: test_init */ 0xf100f801, 0xf50800e7, 0xf801f521, -/* 0x0585: idle_recv */ -/* 0x0587: idle */ +/* 0x09b5: idle_recv */ +/* 0x09b7: idle */ 0xf400f800, 0x17f10031, 0x14b605d4, @@ -1198,32 +1570,20 @@ uint32_t nvc0_pwr_code[] = { 0xf10110b6, 0xb605d407, 0x01d00604, -/* 0x05a3: idle_loop */ +/* 0x09d3: idle_loop */ 0xf004bd00, 0x32f45817, -/* 0x05a9: idle_proc */ -/* 0x05a9: idle_proc_exec */ +/* 0x09d9: idle_proc */ +/* 0x09d9: idle_proc_exec */ 0xb910f902, 0x21f5021e, 0x10fc02c2, 0xf40911f4, 0x0ef40231, -/* 0x05bd: idle_proc_next */ +/* 0x09ed: idle_proc_next */ 0x5810b6ef, 0xf4061fb8, 0x02f4e61b, 0x0028f4dd, 0x00bb0ef4, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, }; diff --git a/drivers/gpu/drm/nouveau/core/subdev/pwr/fuc/nvd0.fuc b/drivers/gpu/drm/nouveau/core/subdev/pwr/fuc/nvd0.fuc index 32d65ea254dd..8a89dfe41ce1 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/pwr/fuc/nvd0.fuc +++ b/drivers/gpu/drm/nouveau/core/subdev/pwr/fuc/nvd0.fuc @@ -37,6 +37,7 @@ #include "host.fuc" #include "memx.fuc" #include "perf.fuc" +#include "i2c_.fuc" #include "test.fuc" #include "idle.fuc" #undef INCLUDE_PROC @@ -46,6 +47,7 @@ #include "host.fuc" #include "memx.fuc" #include "perf.fuc" +#include "i2c_.fuc" #include "test.fuc" #include "idle.fuc" #undef INCLUDE_DATA @@ -57,6 +59,7 @@ #include "host.fuc" #include "memx.fuc" #include "perf.fuc" +#include "i2c_.fuc" #include "test.fuc" #include "idle.fuc" #undef INCLUDE_CODE diff --git a/drivers/gpu/drm/nouveau/core/subdev/pwr/fuc/nvd0.fuc.h b/drivers/gpu/drm/nouveau/core/subdev/pwr/fuc/nvd0.fuc.h index ce65e2a4b789..5e24c6bc041d 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/pwr/fuc/nvd0.fuc.h +++ b/drivers/gpu/drm/nouveau/core/subdev/pwr/fuc/nvd0.fuc.h @@ -89,33 +89,13 @@ uint32_t nvd0_pwr_data[] = { 0x00000000, 0x00000000, 0x00000000, - 0x54534554, - 0x000004eb, - 0x000004ca, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, + 0x5f433249, + 0x000008e3, + 0x00000786, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x454c4449, - 0x000004f7, - 0x000004f5, - 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, @@ -131,14 +111,13 @@ uint32_t nvd0_pwr_data[] = { 0x00000000, 0x00000000, 0x00000000, + 0x54534554, + 0x00000906, + 0x000008e5, 0x00000000, 0x00000000, -/* 0x0210: proc_list_tail */ -/* 0x0210: time_prev */ 0x00000000, -/* 0x0214: time_next */ 0x00000000, -/* 0x0218: fifo_queue */ 0x00000000, 0x00000000, 0x00000000, @@ -154,6 +133,9 @@ uint32_t nvd0_pwr_data[] = { 0x00000000, 0x00000000, 0x00000000, + 0x454c4449, + 0x00000912, + 0x00000910, 0x00000000, 0x00000000, 0x00000000, @@ -171,11 +153,14 @@ uint32_t nvd0_pwr_data[] = { 0x00000000, 0x00000000, 0x00000000, -/* 0x0298: rfifo_queue */ 0x00000000, 0x00000000, +/* 0x0268: proc_list_tail */ +/* 0x0268: time_prev */ 0x00000000, +/* 0x026c: time_next */ 0x00000000, +/* 0x0270: fifo_queue */ 0x00000000, 0x00000000, 0x00000000, @@ -204,31 +189,11 @@ uint32_t nvd0_pwr_data[] = { 0x00000000, 0x00000000, 0x00000000, -/* 0x0318: memx_func_head */ - 0x00010000, - 0x00000000, - 0x000003f4, -/* 0x0324: memx_func_next */ - 0x00000001, - 0x00000000, - 0x00000415, - 0x00000002, - 0x00000002, - 0x00000430, - 0x00040003, - 0x00000000, - 0x00000458, - 0x00010004, - 0x00000000, - 0x00000472, -/* 0x0354: memx_func_tail */ -/* 0x0354: memx_data_head */ - 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, +/* 0x02f0: rfifo_queue */ 0x00000000, 0x00000000, 0x00000000, @@ -261,10 +226,25 @@ uint32_t nvd0_pwr_data[] = { 0x00000000, 0x00000000, 0x00000000, +/* 0x0370: memx_func_head */ + 0x00010000, 0x00000000, + 0x000003f4, +/* 0x037c: memx_func_next */ + 0x00000001, 0x00000000, + 0x00000415, + 0x00000002, + 0x00000002, + 0x00000430, + 0x00040003, 0x00000000, + 0x00000458, + 0x00010004, 0x00000000, + 0x00000472, +/* 0x03ac: memx_func_tail */ +/* 0x03ac: memx_data_head */ 0x00000000, 0x00000000, 0x00000000, @@ -735,7 +715,6 @@ uint32_t nvd0_pwr_data[] = { 0x00000000, 0x00000000, 0x00000000, -/* 0x0b54: memx_data_tail */ 0x00000000, 0x00000000, 0x00000000, @@ -778,6 +757,29 @@ uint32_t nvd0_pwr_data[] = { 0x00000000, 0x00000000, 0x00000000, +/* 0x0bac: memx_data_tail */ +/* 0x0bac: i2c_scl_map */ + 0x00000400, + 0x00000800, + 0x00001000, + 0x00002000, + 0x00004000, + 0x00008000, + 0x00010000, + 0x00020000, + 0x00040000, + 0x00080000, +/* 0x0bd4: i2c_sda_map */ + 0x00100000, + 0x00200000, + 0x00400000, + 0x00800000, + 0x01000000, + 0x02000000, + 0x04000000, + 0x08000000, + 0x10000000, + 0x20000000, 0x00000000, }; @@ -786,14 +788,14 @@ uint32_t nvd0_pwr_code[] = { /* 0x0004: rd32 */ 0x07a007f1, 0xbd000ed0, - 0x01e7f004, - 0xf101e3f0, + 0x01d7f004, + 0xf101d3f0, 0xd007ac07, - 0x04bd000e, + 0x04bd000d, /* 0x001c: rd32_wait */ - 0x07ace7f1, - 0xf100eecf, - 0xf47000e4, + 0x07acd7f1, + 0xf100ddcf, + 0xf47000d4, 0xd7f1f51b, 0xddcf07a4, /* 0x0033: wr32 */ @@ -802,14 +804,14 @@ uint32_t nvd0_pwr_code[] = { 0x04bd000e, 0x07a407f1, 0xbd000dd0, - 0x02e7f004, - 0xf0f0e5f0, - 0x07f101e3, - 0x0ed007ac, + 0x02d7f004, + 0xf0f0d5f0, + 0x07f101d3, + 0x0dd007ac, /* 0x0057: wr32_wait */ 0xf104bd00, - 0xcf07ace7, - 0xe4f100ee, + 0xcf07acd7, + 0xd4f100dd, 0x1bf47000, /* 0x0067: nsec */ 0xf000f8f5, @@ -836,21 +838,21 @@ uint32_t nvd0_pwr_code[] = { 0x9800f8e2, 0x96b003e9, 0x2a0bf400, - 0xbb840a98, + 0xbb9a0a98, 0x1cf4029a, 0x01d7f00f, 0x020621f5, 0x0ef494bd, /* 0x00c5: intr_watchdog_next_time */ - 0x850a9815, + 0x9b0a9815, 0xf400a6b0, 0x9ab8090b, 0x061cf406, /* 0x00d4: intr_watchdog_next_time_set */ /* 0x00d7: intr_watchdog_next_proc */ - 0x80850980, + 0x809b0980, 0xe0b603e9, - 0x10e6b158, + 0x68e6b158, 0xc61bf402, /* 0x00e6: intr */ 0x00f900f8, @@ -868,15 +870,15 @@ uint32_t nvd0_pwr_code[] = { 0x0887f004, 0xc40088cf, 0x0bf40289, - 0x85008020, + 0x9b008020, 0xf458e7f0, 0x0998a721, - 0x0096b085, + 0x0096b09b, 0xf00e0bf4, 0x09d03407, 0x8004bd00, /* 0x013e: intr_skip_watchdog */ - 0x89e48409, + 0x89e49a09, 0x0bf40800, 0x8897f13c, 0x0099cf06, @@ -929,7 +931,7 @@ uint32_t nvd0_pwr_code[] = { 0x0ed03407, 0x8004bd00, /* 0x01f6: timer_enable */ - 0x87f0840e, + 0x87f09a0e, 0x3807f001, 0xbd0008d0, /* 0x0201: timer_done */ @@ -960,7 +962,7 @@ uint32_t nvd0_pwr_code[] = { 0x06aeb800, 0xb6100bf4, 0x86b15880, - 0x1bf40210, + 0x1bf40268, 0x0132f4f0, /* 0x0264: find_done */ 0xfc028eb9, @@ -1024,7 +1026,7 @@ uint32_t nvd0_pwr_code[] = { 0x0bf40612, 0x071ec42f, 0xb704ee94, - 0x980218e0, + 0x980270e0, 0xec9803eb, 0x01ed9802, 0xf500ee98, @@ -1048,7 +1050,7 @@ uint32_t nvd0_pwr_code[] = { 0xec0bf406, 0xb60723c4, 0x30b70434, - 0x3b800298, + 0x3b8002f0, 0x023c8003, 0x80013d80, 0x20b6003e, @@ -1061,12 +1063,12 @@ uint32_t nvd0_pwr_code[] = { /* 0x03be: host_init */ 0x17f100f8, 0x14b60080, - 0x1815f110, + 0x7015f110, 0xd007f102, 0x0001d004, 0x17f104bd, 0x14b60080, - 0x9815f110, + 0xf015f110, 0xdc07f102, 0x0001d004, 0x17f004bd, @@ -1122,13 +1124,13 @@ uint32_t nvd0_pwr_code[] = { 0x10b60013, 0x10349504, 0x980c30f0, - 0x55f9c835, + 0x55f9de35, 0xf40612b8, 0xd0fcec1e, 0x21f5e0fc, 0x00f8026b, /* 0x04a8: memx_info */ - 0x0354c7f1, + 0x03acc7f1, 0x0800b7f1, 0x026b21f5, /* 0x04b6: memx_recv */ @@ -1140,49 +1142,342 @@ uint32_t nvd0_pwr_code[] = { /* 0x04c6: perf_recv */ 0x00f800f8, /* 0x04c8: perf_init */ -/* 0x04ca: test_recv */ - 0x17f100f8, - 0x11cf05d8, - 0x0110b600, - 0x05d807f1, +/* 0x04ca: i2c_drive_scl */ + 0x36b000f8, + 0x0e0bf400, + 0x07e007f1, 0xbd0001d0, - 0x00e7f104, - 0x4fe3f1d9, - 0xb621f513, -/* 0x04eb: test_init */ - 0xf100f801, - 0xf50800e7, - 0xf801b621, -/* 0x04f5: idle_recv */ -/* 0x04f7: idle */ - 0xf400f800, - 0x17f10031, - 0x11cf05d4, - 0x0110b600, - 0x05d407f1, - 0xbd0001d0, -/* 0x050d: idle_loop */ - 0x5817f004, -/* 0x0513: idle_proc */ -/* 0x0513: idle_proc_exec */ - 0xf90232f4, - 0x021eb910, - 0x027421f5, - 0x11f410fc, - 0x0231f409, -/* 0x0527: idle_proc_next */ - 0xb6ef0ef4, - 0x1fb85810, - 0xe61bf406, - 0xf4dd02f4, - 0x0ef40028, - 0x000000c1, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, +/* 0x04db: i2c_drive_scl_lo */ + 0xf100f804, + 0xd007e407, + 0x04bd0001, +/* 0x04e6: i2c_drive_sda */ + 0x36b000f8, + 0x0e0bf400, + 0x07e007f1, + 0xbd0002d0, +/* 0x04f7: i2c_drive_sda_lo */ + 0xf100f804, + 0xd007e407, + 0x04bd0002, +/* 0x0502: i2c_sense_scl */ + 0x32f400f8, + 0xc437f101, + 0x0033cf07, + 0xf40431fd, + 0x31f4060b, +/* 0x0515: i2c_sense_scl_done */ +/* 0x0517: i2c_sense_sda */ + 0xf400f801, + 0x37f10132, + 0x33cf07c4, + 0x0432fd00, + 0xf4060bf4, +/* 0x052a: i2c_sense_sda_done */ + 0x00f80131, +/* 0x052c: i2c_raise_scl */ + 0x47f140f9, + 0x37f00898, + 0xca21f501, +/* 0x0539: i2c_raise_scl_wait */ + 0xe8e7f104, + 0x6721f403, + 0x050221f5, + 0xb60901f4, + 0x1bf40142, +/* 0x054d: i2c_raise_scl_done */ + 0xf840fcef, +/* 0x0551: i2c_start */ + 0x0221f500, + 0x0d11f405, + 0x051721f5, + 0xf40611f4, +/* 0x0562: i2c_start_rep */ + 0x37f0300e, + 0xca21f500, + 0x0137f004, + 0x04e621f5, + 0xb60076bb, + 0x50f90465, + 0xbb046594, + 0x50bd0256, + 0xfc0475fd, + 0x2c21f550, + 0x0464b605, +/* 0x058f: i2c_start_send */ + 0xf01f11f4, + 0x21f50037, + 0xe7f104e6, + 0x21f41388, + 0x0037f067, + 0x04ca21f5, + 0x1388e7f1, +/* 0x05ab: i2c_start_out */ + 0xf86721f4, +/* 0x05ad: i2c_stop */ + 0x0037f000, + 0x04ca21f5, + 0xf50037f0, + 0xf104e621, + 0xf403e8e7, + 0x37f06721, + 0xca21f501, + 0x88e7f104, + 0x6721f413, + 0xf50137f0, + 0xf104e621, + 0xf41388e7, + 0x00f86721, +/* 0x05e0: i2c_bitw */ + 0x04e621f5, + 0x03e8e7f1, + 0xbb6721f4, + 0x65b60076, + 0x9450f904, + 0x56bb0465, + 0xfd50bd02, + 0x50fc0475, + 0x052c21f5, + 0xf40464b6, + 0xe7f11811, + 0x21f41388, + 0x0037f067, + 0x04ca21f5, + 0x1388e7f1, +/* 0x061f: i2c_bitw_out */ + 0xf86721f4, +/* 0x0621: i2c_bitr */ + 0x0137f000, + 0x04e621f5, + 0x03e8e7f1, + 0xbb6721f4, + 0x65b60076, + 0x9450f904, + 0x56bb0465, + 0xfd50bd02, + 0x50fc0475, + 0x052c21f5, + 0xf40464b6, + 0x21f51b11, + 0x37f00517, + 0xca21f500, + 0x88e7f104, + 0x6721f413, + 0xf4013cf0, +/* 0x0666: i2c_bitr_done */ + 0x00f80131, +/* 0x0668: i2c_get_byte */ + 0xf00057f0, +/* 0x066e: i2c_get_byte_next */ + 0x54b60847, + 0x0076bb01, + 0xf90465b6, + 0x04659450, + 0xbd0256bb, + 0x0475fd50, + 0x21f550fc, + 0x64b60621, + 0x2b11f404, + 0xb60553fd, + 0x1bf40142, + 0x0137f0d8, + 0xb60076bb, + 0x50f90465, + 0xbb046594, + 0x50bd0256, + 0xfc0475fd, + 0xe021f550, + 0x0464b605, +/* 0x06b8: i2c_get_byte_done */ +/* 0x06ba: i2c_put_byte */ + 0x47f000f8, +/* 0x06bd: i2c_put_byte_next */ + 0x0142b608, + 0xbb3854ff, + 0x65b60076, + 0x9450f904, + 0x56bb0465, + 0xfd50bd02, + 0x50fc0475, + 0x05e021f5, + 0xf40464b6, + 0x46b03411, + 0xd81bf400, + 0xb60076bb, + 0x50f90465, + 0xbb046594, + 0x50bd0256, + 0xfc0475fd, + 0x2121f550, + 0x0464b606, + 0xbb0f11f4, + 0x36b00076, + 0x061bf401, +/* 0x0713: i2c_put_byte_done */ + 0xf80132f4, +/* 0x0715: i2c_addr */ + 0x0076bb00, + 0xf90465b6, + 0x04659450, + 0xbd0256bb, + 0x0475fd50, + 0x21f550fc, + 0x64b60551, + 0x2911f404, + 0x012ec3e7, + 0xfd0134b6, + 0x76bb0553, + 0x0465b600, + 0x659450f9, + 0x0256bb04, + 0x75fd50bd, + 0xf550fc04, + 0xb606ba21, +/* 0x075a: i2c_addr_done */ + 0x00f80464, +/* 0x075c: i2c_acquire_addr */ + 0xb6f8cec7, + 0xe0b705e4, + 0x00f8d014, +/* 0x0768: i2c_acquire */ + 0x075c21f5, + 0xf00421f4, + 0x21f403d9, +/* 0x0777: i2c_release */ + 0xf500f833, + 0xf4075c21, + 0xdaf00421, + 0x3321f403, +/* 0x0786: i2c_recv */ + 0x32f400f8, + 0xf8c1c701, + 0xb00214b6, + 0x1ff52816, + 0x13a0013a, + 0x32980bd4, + 0xac13a000, + 0x0031980b, + 0xf90231f4, + 0xf9e0f9d0, + 0x0067f1d0, + 0x0063f100, + 0x01679210, + 0xb60076bb, + 0x50f90465, + 0xbb046594, + 0x50bd0256, + 0xfc0475fd, + 0x6821f550, + 0x0464b607, + 0xd6b0d0fc, + 0xb31bf500, + 0x0057f000, + 0xb60076bb, + 0x50f90465, + 0xbb046594, + 0x50bd0256, + 0xfc0475fd, + 0x1521f550, + 0x0464b607, + 0x00d011f5, + 0xbbe0c5c7, + 0x65b60076, + 0x9450f904, + 0x56bb0465, + 0xfd50bd02, + 0x50fc0475, + 0x06ba21f5, + 0xf50464b6, + 0xf000ad11, + 0x76bb0157, + 0x0465b600, + 0x659450f9, + 0x0256bb04, + 0x75fd50bd, + 0xf550fc04, + 0xb6071521, + 0x11f50464, + 0x76bb008a, + 0x0465b600, + 0x659450f9, + 0x0256bb04, + 0x75fd50bd, + 0xf550fc04, + 0xb6066821, + 0x11f40464, + 0xe05bcb6a, + 0xb60076bb, + 0x50f90465, + 0xbb046594, + 0x50bd0256, + 0xfc0475fd, + 0xad21f550, + 0x0464b605, + 0xbd025bb9, + 0x430ef474, +/* 0x088c: i2c_recv_not_rd08 */ + 0xf401d6b0, + 0x57f03d1b, + 0x1521f500, + 0x3311f407, + 0xf5e0c5c7, + 0xf406ba21, + 0x57f02911, + 0x1521f500, + 0x1f11f407, + 0xf5e0b5c7, + 0xf406ba21, + 0x21f51511, + 0x74bd05ad, + 0xf408c5c7, + 0x32f4091b, + 0x030ef402, +/* 0x08cc: i2c_recv_not_wr08 */ +/* 0x08cc: i2c_recv_done */ + 0xf5f8cec7, + 0xfc077721, + 0xf4d0fce0, + 0x7cb90a12, + 0x6b21f502, +/* 0x08e1: i2c_recv_exit */ +/* 0x08e3: i2c_init */ + 0xf800f802, +/* 0x08e5: test_recv */ + 0xd817f100, + 0x0011cf05, + 0xf10110b6, + 0xd005d807, + 0x04bd0001, + 0xd900e7f1, + 0x134fe3f1, + 0x01b621f5, +/* 0x0906: test_init */ + 0xe7f100f8, + 0x21f50800, + 0x00f801b6, +/* 0x0910: idle_recv */ +/* 0x0912: idle */ + 0x31f400f8, + 0xd417f100, + 0x0011cf05, + 0xf10110b6, + 0xd005d407, + 0x04bd0001, +/* 0x0928: idle_loop */ + 0xf45817f0, +/* 0x092e: idle_proc */ +/* 0x092e: idle_proc_exec */ + 0x10f90232, + 0xf5021eb9, + 0xfc027421, + 0x0911f410, + 0xf40231f4, +/* 0x0942: idle_proc_next */ + 0x10b6ef0e, + 0x061fb858, + 0xf4e61bf4, + 0x28f4dd02, + 0xc10ef400, 0x00000000, 0x00000000, 0x00000000, diff --git a/drivers/gpu/drm/nouveau/core/subdev/pwr/fuc/os.h b/drivers/gpu/drm/nouveau/core/subdev/pwr/fuc/os.h index 5fb0cccc6c64..574acfa44c8c 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/pwr/fuc/os.h +++ b/drivers/gpu/drm/nouveau/core/subdev/pwr/fuc/os.h @@ -7,6 +7,7 @@ #define PROC_HOST 0x54534f48 #define PROC_MEMX 0x584d454d #define PROC_PERF 0x46524550 +#define PROC_I2C_ 0x5f433249 #define PROC_TEST 0x54534554 /* KERN: message identifiers */ @@ -24,4 +25,22 @@ #define MEMX_WAIT 3 #define MEMX_DELAY 4 +/* I2C_: message identifiers */ +#define I2C__MSG_RD08 0 +#define I2C__MSG_WR08 1 + +#define I2C__MSG_DATA0_PORT 24:31 +#define I2C__MSG_DATA0_ADDR 14:23 + +#define I2C__MSG_DATA0_RD08_PORT I2C__MSG_DATA0_PORT +#define I2C__MSG_DATA0_RD08_ADDR I2C__MSG_DATA0_ADDR +#define I2C__MSG_DATA0_RD08_REG 0:7 +#define I2C__MSG_DATA1_RD08_VAL 0:7 + +#define I2C__MSG_DATA0_WR08_PORT I2C__MSG_DATA0_PORT +#define I2C__MSG_DATA0_WR08_ADDR I2C__MSG_DATA0_ADDR +#define I2C__MSG_DATA0_WR08_SYNC 8:8 +#define I2C__MSG_DATA0_WR08_REG 0:7 +#define I2C__MSG_DATA1_WR08_VAL 0:7 + #endif diff --git a/drivers/gpu/drm/nouveau/core/subdev/therm/ic.c b/drivers/gpu/drm/nouveau/core/subdev/therm/ic.c index e44ed7b93c6d..7610fc5f8fa2 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/therm/ic.c +++ b/drivers/gpu/drm/nouveau/core/subdev/therm/ic.c @@ -29,9 +29,9 @@ static bool probe_monitoring_device(struct nouveau_i2c_port *i2c, - struct i2c_board_info *info) + struct i2c_board_info *info, void *data) { - struct nouveau_therm_priv *priv = (void *)nouveau_therm(i2c); + struct nouveau_therm_priv *priv = data; struct nvbios_therm_sensor *sensor = &priv->bios_sensor; struct i2c_client *client; @@ -96,7 +96,7 @@ nouveau_therm_ic_ctor(struct nouveau_therm *therm) }; i2c->identify(i2c, NV_I2C_DEFAULT(0), "monitoring device", - board, probe_monitoring_device); + board, probe_monitoring_device, therm); if (priv->ic) return; } @@ -108,7 +108,7 @@ nouveau_therm_ic_ctor(struct nouveau_therm *therm) }; i2c->identify(i2c, NV_I2C_DEFAULT(0), "monitoring device", - board, probe_monitoring_device); + board, probe_monitoring_device, therm); if (priv->ic) return; } @@ -117,5 +117,5 @@ nouveau_therm_ic_ctor(struct nouveau_therm *therm) device. Let's try our static list. */ i2c->identify(i2c, NV_I2C_DEFAULT(0), "monitoring device", - nv_board_infos, probe_monitoring_device); + nv_board_infos, probe_monitoring_device, therm); } diff --git a/drivers/gpu/drm/nouveau/core/subdev/vm/base.c b/drivers/gpu/drm/nouveau/core/subdev/vm/base.c index ef3133e7575c..7dd680ff2f6f 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/vm/base.c +++ b/drivers/gpu/drm/nouveau/core/subdev/vm/base.c @@ -72,13 +72,7 @@ nouveau_vm_map_at(struct nouveau_vma *vma, u64 delta, struct nouveau_mem *node) vmm->flush(vm); } -void -nouveau_vm_map(struct nouveau_vma *vma, struct nouveau_mem *node) -{ - nouveau_vm_map_at(vma, 0, node); -} - -void +static void nouveau_vm_map_sg_table(struct nouveau_vma *vma, u64 delta, u64 length, struct nouveau_mem *mem) { @@ -136,7 +130,7 @@ finish: vmm->flush(vm); } -void +static void nouveau_vm_map_sg(struct nouveau_vma *vma, u64 delta, u64 length, struct nouveau_mem *mem) { @@ -175,6 +169,18 @@ nouveau_vm_map_sg(struct nouveau_vma *vma, u64 delta, u64 length, } void +nouveau_vm_map(struct nouveau_vma *vma, struct nouveau_mem *node) +{ + if (node->sg) + nouveau_vm_map_sg_table(vma, 0, node->size << 12, node); + else + if (node->pages) + nouveau_vm_map_sg(vma, 0, node->size << 12, node); + else + nouveau_vm_map_at(vma, 0, node); +} + +void nouveau_vm_unmap_at(struct nouveau_vma *vma, u64 delta, u64 length) { struct nouveau_vm *vm = vma->vm; |