From 02a841d434513c7b3620250271c372fabce56de5 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Wed, 4 Jul 2012 23:44:54 +1000 Subject: drm/nouveau: restructure source tree, split core from drm implementation Future work will be headed in the way of separating the policy supplied by the nouveau drm module from the mechanisms provided by the driver core. There will be a couple of major classes (subdev, engine) of driver modules that have clearly defined tasks, and the further directory structure change is to reflect this. No code changes here whatsoever, aside from fixing up a couple of include file pathnames. Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/nva3_pm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpu/drm/nouveau/nva3_pm.c') diff --git a/drivers/gpu/drm/nouveau/nva3_pm.c b/drivers/gpu/drm/nouveau/nva3_pm.c index 798829353fb6..ff0fafbfe621 100644 --- a/drivers/gpu/drm/nouveau/nva3_pm.c +++ b/drivers/gpu/drm/nouveau/nva3_pm.c @@ -24,7 +24,7 @@ #include "drmP.h" #include "nouveau_drv.h" -#include "nouveau_bios.h" +#include #include "nouveau_pm.h" static u32 read_clk(struct drm_device *, int, bool); -- cgit v1.2.3 From 70790f4f819875e8f390871fd15bbbf823f28e1b Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Tue, 10 Jul 2012 17:26:46 +1000 Subject: drm/nouveau/clock: pull in the implementation from all over the place Still missing the main bits we use to change performance levels, I'll get to it after all the hard yakka has been finished. Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/Makefile | 4 +- .../gpu/drm/nouveau/core/include/subdev/bios/pll.h | 77 +++ .../gpu/drm/nouveau/core/include/subdev/clock.h | 21 +- drivers/gpu/drm/nouveau/core/include/subdev/vga.h | 2 + drivers/gpu/drm/nouveau/core/subdev/bios/pll.c | 417 +++++++++++++++++ drivers/gpu/drm/nouveau/core/subdev/clock/nv04.c | 296 +++++++++++- drivers/gpu/drm/nouveau/core/subdev/clock/nv40.c | 12 +- drivers/gpu/drm/nouveau/core/subdev/clock/nv50.c | 44 +- drivers/gpu/drm/nouveau/core/subdev/clock/nva3.c | 34 +- drivers/gpu/drm/nouveau/core/subdev/clock/nvc0.c | 33 +- drivers/gpu/drm/nouveau/core/subdev/clock/pll.h | 9 + .../gpu/drm/nouveau/core/subdev/clock/pllnv04.c | 242 ++++++++++ .../gpu/drm/nouveau/core/subdev/clock/pllnva3.c | 80 ++++ drivers/gpu/drm/nouveau/nouveau_bios.c | 519 +-------------------- drivers/gpu/drm/nouveau/nouveau_bios.h | 52 --- drivers/gpu/drm/nouveau/nouveau_calc.c | 216 --------- drivers/gpu/drm/nouveau/nouveau_compat.c | 75 +++ drivers/gpu/drm/nouveau/nouveau_compat.h | 12 + drivers/gpu/drm/nouveau/nouveau_drv.h | 31 +- drivers/gpu/drm/nouveau/nouveau_hw.c | 280 +---------- drivers/gpu/drm/nouveau/nouveau_hw.h | 10 +- drivers/gpu/drm/nouveau/nv04_crtc.c | 4 +- drivers/gpu/drm/nouveau/nv04_pm.c | 2 +- drivers/gpu/drm/nouveau/nv40_pm.c | 12 +- drivers/gpu/drm/nouveau/nv50_calc.c | 97 ---- drivers/gpu/drm/nouveau/nv50_crtc.c | 50 +- drivers/gpu/drm/nouveau/nv50_pm.c | 12 +- drivers/gpu/drm/nouveau/nva3_pm.c | 2 +- drivers/gpu/drm/nouveau/nvc0_pm.c | 4 +- 29 files changed, 1382 insertions(+), 1267 deletions(-) create mode 100644 drivers/gpu/drm/nouveau/core/include/subdev/bios/pll.h create mode 100644 drivers/gpu/drm/nouveau/core/subdev/bios/pll.c create mode 100644 drivers/gpu/drm/nouveau/core/subdev/clock/pll.h create mode 100644 drivers/gpu/drm/nouveau/core/subdev/clock/pllnv04.c create mode 100644 drivers/gpu/drm/nouveau/core/subdev/clock/pllnva3.c delete mode 100644 drivers/gpu/drm/nouveau/nv50_calc.c (limited to 'drivers/gpu/drm/nouveau/nva3_pm.c') diff --git a/drivers/gpu/drm/nouveau/Makefile b/drivers/gpu/drm/nouveau/Makefile index 2964d71d3996..2574fd35122a 100644 --- a/drivers/gpu/drm/nouveau/Makefile +++ b/drivers/gpu/drm/nouveau/Makefile @@ -23,11 +23,14 @@ nouveau-y += core/subdev/bios/bit.o nouveau-y += core/subdev/bios/dcb.o nouveau-y += core/subdev/bios/gpio.o nouveau-y += core/subdev/bios/i2c.o +nouveau-y += core/subdev/bios/pll.o nouveau-y += core/subdev/clock/nv04.o nouveau-y += core/subdev/clock/nv40.o nouveau-y += core/subdev/clock/nv50.o nouveau-y += core/subdev/clock/nva3.o nouveau-y += core/subdev/clock/nvc0.o +nouveau-y += core/subdev/clock/pllnv04.o +nouveau-y += core/subdev/clock/pllnva3.o nouveau-y += core/subdev/device/base.o nouveau-y += core/subdev/device/nv04.o nouveau-y += core/subdev/device/nv10.o @@ -114,7 +117,6 @@ nouveau-y += nouveau_drm.o nouveau_compat.o \ nv50_cursor.o nv50_display.o \ nvd0_display.o \ nv04_fbcon.o nv50_fbcon.o nvc0_fbcon.o \ - nv50_calc.o \ nv04_pm.o nv40_pm.o nv50_pm.o nva3_pm.o nvc0_pm.o \ nouveau_prime.o diff --git a/drivers/gpu/drm/nouveau/core/include/subdev/bios/pll.h b/drivers/gpu/drm/nouveau/core/include/subdev/bios/pll.h new file mode 100644 index 000000000000..c345097592f2 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/include/subdev/bios/pll.h @@ -0,0 +1,77 @@ +#ifndef __NVBIOS_PLL_H__ +#define __NVBIOS_PLL_H__ + +/*XXX: kill me */ +struct nouveau_pll_vals { + union { + struct { +#ifdef __BIG_ENDIAN + uint8_t N1, M1, N2, M2; +#else + uint8_t M1, N1, M2, N2; +#endif + }; + struct { + uint16_t NM1, NM2; + } __attribute__((packed)); + }; + int log2P; + + int refclk; +}; + +struct nouveau_bios; + +/* these match types in pll limits table version 0x40, + * nouveau uses them on all chipsets internally where a + * specific pll needs to be referenced, but the exact + * register isn't known. + */ +enum nvbios_pll_type { + PLL_CORE = 0x01, + PLL_SHADER = 0x02, + PLL_UNK03 = 0x03, + PLL_MEMORY = 0x04, + PLL_VDEC = 0x05, + PLL_UNK40 = 0x40, + PLL_UNK41 = 0x41, + PLL_UNK42 = 0x42, + PLL_VPLL0 = 0x80, + PLL_VPLL1 = 0x81, + PLL_MAX = 0xff +}; + +struct nvbios_pll { + enum nvbios_pll_type type; + u32 reg; + u32 refclk; + + u8 min_p; + u8 max_p; + u8 bias_p; + + /* + * for most pre nv50 cards setting a log2P of 7 (the common max_log2p + * value) is no different to 6 (at least for vplls) so allowing the MNP + * calc to use 7 causes the generated clock to be out by a factor of 2. + * however, max_log2p cannot be fixed-up during parsing as the + * unmodified max_log2p value is still needed for setting mplls, hence + * an additional max_usable_log2p member + */ + u8 max_p_usable; + + struct { + u32 min_freq; + u32 max_freq; + u32 min_inputfreq; + u32 max_inputfreq; + u8 min_m; + u8 max_m; + u8 min_n; + u8 max_n; + } vco1, vco2; +}; + +int nvbios_pll_parse(struct nouveau_bios *, u32 type, struct nvbios_pll *); + +#endif diff --git a/drivers/gpu/drm/nouveau/core/include/subdev/clock.h b/drivers/gpu/drm/nouveau/core/include/subdev/clock.h index 137c4598a1b6..39e73b91d360 100644 --- a/drivers/gpu/drm/nouveau/core/include/subdev/clock.h +++ b/drivers/gpu/drm/nouveau/core/include/subdev/clock.h @@ -4,9 +4,21 @@ #include #include +struct nouveau_pll_vals; +struct nvbios_pll; + struct nouveau_clock { struct nouveau_subdev base; - void (*pll_set)(struct nouveau_clock *, u32 type, u32 freq); + + int (*pll_set)(struct nouveau_clock *, u32 type, u32 freq); + + /*XXX: die, these are here *only* to support the completely + * bat-shit insane what-was-nouveau_hw.c code + */ + int (*pll_calc)(struct nouveau_clock *, struct nvbios_pll *, + int clk, struct nouveau_pll_vals *pv); + int (*pll_prog)(struct nouveau_clock *, u32 reg1, + struct nouveau_pll_vals *pv); }; static inline struct nouveau_clock * @@ -37,4 +49,11 @@ extern struct nouveau_oclass nv50_clock_oclass; extern struct nouveau_oclass nva3_clock_oclass; extern struct nouveau_oclass nvc0_clock_oclass; +int nv04_clock_pll_set(struct nouveau_clock *, u32 type, u32 freq); +int nv04_clock_pll_calc(struct nouveau_clock *, struct nvbios_pll *, + int clk, struct nouveau_pll_vals *); +int nv04_clock_pll_prog(struct nouveau_clock *, u32 reg1, + struct nouveau_pll_vals *); + + #endif diff --git a/drivers/gpu/drm/nouveau/core/include/subdev/vga.h b/drivers/gpu/drm/nouveau/core/include/subdev/vga.h index d81df1ae442d..fee09ad818e4 100644 --- a/drivers/gpu/drm/nouveau/core/include/subdev/vga.h +++ b/drivers/gpu/drm/nouveau/core/include/subdev/vga.h @@ -1,6 +1,8 @@ #ifndef __NOUVEAU_VGA_H__ #define __NOUVEAU_VGA_H__ +#include + /* access to various legacy io ports */ u8 nv_rdport(void *obj, int head, u16 port); void nv_wrport(void *obj, int head, u16 port, u8 value); diff --git a/drivers/gpu/drm/nouveau/core/subdev/bios/pll.c b/drivers/gpu/drm/nouveau/core/subdev/bios/pll.c new file mode 100644 index 000000000000..5e5f4cddae3c --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/subdev/bios/pll.c @@ -0,0 +1,417 @@ +/* + * Copyright 2005-2006 Erik Waling + * Copyright 2006 Stephane Marchesin + * Copyright 2007-2009 Stuart Bennett + * + * 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 AUTHORS 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. + */ + +#include +#include +#include +#include +#include + +struct pll_mapping { + u8 type; + u32 reg; +}; + +static struct pll_mapping +nv04_pll_mapping[] = { + { PLL_CORE , 0x680500 }, + { PLL_MEMORY, 0x680504 }, + { PLL_VPLL0 , 0x680508 }, + { PLL_VPLL1 , 0x680520 }, + {} +}; + +static struct pll_mapping +nv40_pll_mapping[] = { + { PLL_CORE , 0x004000 }, + { PLL_MEMORY, 0x004020 }, + { PLL_VPLL0 , 0x680508 }, + { PLL_VPLL1 , 0x680520 }, + {} +}; + +static struct pll_mapping +nv50_pll_mapping[] = { + { PLL_CORE , 0x004028 }, + { PLL_SHADER, 0x004020 }, + { PLL_UNK03 , 0x004000 }, + { PLL_MEMORY, 0x004008 }, + { PLL_UNK40 , 0x00e810 }, + { PLL_UNK41 , 0x00e818 }, + { PLL_UNK42 , 0x00e824 }, + { PLL_VPLL0 , 0x614100 }, + { PLL_VPLL1 , 0x614900 }, + {} +}; + +static struct pll_mapping +nv84_pll_mapping[] = { + { PLL_CORE , 0x004028 }, + { PLL_SHADER, 0x004020 }, + { PLL_MEMORY, 0x004008 }, + { PLL_VDEC , 0x004030 }, + { PLL_UNK41 , 0x00e818 }, + { PLL_VPLL0 , 0x614100 }, + { PLL_VPLL1 , 0x614900 }, + {} +}; + +static u16 +pll_limits_table(struct nouveau_bios *bios, u8 *ver, u8 *hdr, u8 *cnt, u8 *len) +{ + struct bit_entry bit_C; + + if (!bit_entry(bios, 'C', &bit_C) && bit_C.length >= 10) { + u16 data = nv_ro16(bios, bit_C.offset + 8); + if (data) { + *ver = nv_ro08(bios, data + 0); + *hdr = nv_ro08(bios, data + 1); + *len = nv_ro08(bios, data + 2); + *cnt = nv_ro08(bios, data + 3); + return data; + } + } + + if (bmp_version(bios) >= 0x0524) { + u16 data = nv_ro16(bios, bios->bmp_offset + 142); + if (data) { + *ver = nv_ro08(bios, data + 0); + *hdr = 1; + *cnt = 1; + *len = 0x18; + return data; + } + } + + *ver = 0x00; + return 0x0000; +} + +static struct pll_mapping * +pll_map(struct nouveau_bios *bios) +{ + switch (nv_device(bios)->card_type) { + case NV_04: + case NV_10: + case NV_20: + case NV_30: + return nv04_pll_mapping; + break; + case NV_40: + return nv40_pll_mapping; + case NV_50: + if (nv_device(bios)->chipset == 0x50) + return nv50_pll_mapping; + else + if (nv_device(bios)->chipset < 0xa3 || + nv_device(bios)->chipset == 0xaa || + nv_device(bios)->chipset == 0xac) + return nv84_pll_mapping; + default: + return NULL; + } +} + +static u16 +pll_map_reg(struct nouveau_bios *bios, u32 reg, u32 *type, u8 *ver, u8 *len) +{ + struct pll_mapping *map; + u8 hdr, cnt; + u16 data; + + data = pll_limits_table(bios, ver, &hdr, &cnt, len); + if (data && *ver >= 0x30) { + data += hdr; + while (cnt--) { + if (nv_ro32(bios, data + 3) == reg) { + *type = nv_ro08(bios, data + 0); + return data; + } + data += *len; + } + return 0x0000; + } + + map = pll_map(bios); + while (map->reg) { + if (map->reg == reg && *ver >= 0x20) { + u16 addr = (data += hdr); + while (cnt--) { + if (nv_ro32(bios, data) == map->reg) { + *type = map->type; + return data; + } + data += *len; + } + return addr; + } else + if (map->reg == reg) { + *type = map->type; + return data + 1; + } + map++; + } + + return 0x0000; +} + +static u16 +pll_map_type(struct nouveau_bios *bios, u8 type, u32 *reg, u8 *ver, u8 *len) +{ + struct pll_mapping *map; + u8 hdr, cnt; + u16 data; + + data = pll_limits_table(bios, ver, &hdr, &cnt, len); + if (data && *ver >= 0x30) { + data += hdr; + while (cnt--) { + if (nv_ro08(bios, data + 0) == type) { + *reg = nv_ro32(bios, data + 3); + return data; + } + data += *len; + } + return 0x0000; + } + + map = pll_map(bios); + while (map->reg) { + if (map->type == type && *ver >= 0x20) { + u16 addr = (data += hdr); + while (cnt--) { + if (nv_ro32(bios, data) == map->reg) { + *reg = map->reg; + return data; + } + data += *len; + } + return addr; + } else + if (map->type == type) { + *reg = map->reg; + return data + 1; + } + map++; + } + + return 0x0000; +} + +int +nvbios_pll_parse(struct nouveau_bios *bios, u32 type, struct nvbios_pll *info) +{ + u8 ver, len; + u32 reg = type; + u16 data; + + if (type > PLL_MAX) { + reg = type; + data = pll_map_reg(bios, reg, &type, &ver, &len); + } else { + data = pll_map_type(bios, type, ®, &ver, &len); + } + + if (ver && !data) + return -ENOENT; + + memset(info, 0, sizeof(*info)); + info->type = type; + info->reg = reg; + + switch (ver) { + case 0x00: + break; + case 0x10: + case 0x11: + info->vco1.min_freq = nv_ro32(bios, data + 0); + info->vco1.max_freq = nv_ro32(bios, data + 4); + info->vco2.min_freq = nv_ro32(bios, data + 8); + info->vco2.max_freq = nv_ro32(bios, data + 12); + info->vco1.min_inputfreq = nv_ro32(bios, data + 16); + info->vco2.min_inputfreq = nv_ro32(bios, data + 20); + info->vco1.max_inputfreq = INT_MAX; + info->vco2.max_inputfreq = INT_MAX; + + info->max_p = 0x7; + info->max_p_usable = 0x6; + + /* these values taken from nv30/31/36 */ + switch (bios->version.chip) { + case 0x36: + info->vco1.min_n = 0x5; + break; + default: + info->vco1.min_n = 0x1; + break; + } + info->vco1.max_n = 0xff; + info->vco1.min_m = 0x1; + info->vco1.max_m = 0xd; + + /* + * On nv30, 31, 36 (i.e. all cards with two stage PLLs with this + * table version (apart from nv35)), N2 is compared to + * maxN2 (0x46) and 10 * maxM2 (0x4), so set maxN2 to 0x28 and + * save a comparison + */ + info->vco2.min_n = 0x4; + switch (bios->version.chip) { + case 0x30: + case 0x35: + info->vco2.max_n = 0x1f; + break; + default: + info->vco2.max_n = 0x28; + break; + } + info->vco2.min_m = 0x1; + info->vco2.max_m = 0x4; + break; + case 0x20: + case 0x21: + info->vco1.min_freq = nv_ro16(bios, data + 4) * 1000; + info->vco1.max_freq = nv_ro16(bios, data + 6) * 1000; + info->vco2.min_freq = nv_ro16(bios, data + 8) * 1000; + info->vco2.max_freq = nv_ro16(bios, data + 10) * 1000; + info->vco1.min_inputfreq = nv_ro16(bios, data + 12) * 1000; + info->vco2.min_inputfreq = nv_ro16(bios, data + 14) * 1000; + info->vco1.max_inputfreq = nv_ro16(bios, data + 16) * 1000; + info->vco2.max_inputfreq = nv_ro16(bios, data + 18) * 1000; + info->vco1.min_n = nv_ro08(bios, data + 20); + info->vco1.max_n = nv_ro08(bios, data + 21); + info->vco1.min_m = nv_ro08(bios, data + 22); + info->vco1.max_m = nv_ro08(bios, data + 23); + info->vco2.min_n = nv_ro08(bios, data + 24); + info->vco2.max_n = nv_ro08(bios, data + 25); + info->vco2.min_m = nv_ro08(bios, data + 26); + info->vco2.max_m = nv_ro08(bios, data + 27); + + info->max_p = nv_ro08(bios, data + 29); + info->max_p_usable = info->max_p; + if (bios->version.chip < 0x60) + info->max_p_usable = 0x6; + info->bias_p = nv_ro08(bios, data + 30); + + if (len > 0x22) + info->refclk = nv_ro32(bios, data + 31); + break; + case 0x30: + data = nv_ro16(bios, data + 1); + + info->vco1.min_freq = nv_ro16(bios, data + 0) * 1000; + info->vco1.max_freq = nv_ro16(bios, data + 2) * 1000; + info->vco2.min_freq = nv_ro16(bios, data + 4) * 1000; + info->vco2.max_freq = nv_ro16(bios, data + 6) * 1000; + info->vco1.min_inputfreq = nv_ro16(bios, data + 8) * 1000; + info->vco2.min_inputfreq = nv_ro16(bios, data + 10) * 1000; + info->vco1.max_inputfreq = nv_ro16(bios, data + 12) * 1000; + info->vco2.max_inputfreq = nv_ro16(bios, data + 14) * 1000; + info->vco1.min_n = nv_ro08(bios, data + 16); + info->vco1.max_n = nv_ro08(bios, data + 17); + info->vco1.min_m = nv_ro08(bios, data + 18); + info->vco1.max_m = nv_ro08(bios, data + 19); + info->vco2.min_n = nv_ro08(bios, data + 20); + info->vco2.max_n = nv_ro08(bios, data + 21); + info->vco2.min_m = nv_ro08(bios, data + 22); + info->vco2.max_m = nv_ro08(bios, data + 23); + info->max_p_usable = info->max_p = nv_ro08(bios, data + 25); + info->bias_p = nv_ro08(bios, data + 27); + info->refclk = nv_ro32(bios, data + 28); + break; + case 0x40: + info->refclk = nv_ro16(bios, data + 9) * 1000; + data = nv_ro16(bios, data + 1); + + info->vco1.min_freq = nv_ro16(bios, data + 0) * 1000; + info->vco1.max_freq = nv_ro16(bios, data + 2) * 1000; + info->vco1.min_inputfreq = nv_ro16(bios, data + 4) * 1000; + info->vco1.max_inputfreq = nv_ro16(bios, data + 6) * 1000; + info->vco1.min_m = nv_ro08(bios, data + 8); + info->vco1.max_m = nv_ro08(bios, data + 9); + info->vco1.min_n = nv_ro08(bios, data + 10); + info->vco1.max_n = nv_ro08(bios, data + 11); + info->min_p = nv_ro08(bios, data + 12); + info->max_p = nv_ro08(bios, data + 13); + break; + default: + nv_error(bios, "unknown pll limits version 0x%02x\n", ver); + return -EINVAL; + } + + if (!info->refclk) { + info->refclk = nv_device(bios)->crystal; + if (bios->version.chip == 0x51) { + u32 sel_clk = nv_rd32(bios, 0x680524); + if ((info->reg == 0x680508 && sel_clk & 0x20) || + (info->reg == 0x680520 && sel_clk & 0x80)) { + if (nv_rdvgac(bios, 0, 0x27) < 0xa3) + info->refclk = 200000; + else + info->refclk = 25000; + } + } + } + + /* + * By now any valid limit table ought to have set a max frequency for + * vco1, so if it's zero it's either a pre limit table bios, or one + * with an empty limit table (seen on nv18) + */ + if (!info->vco1.max_freq) { + info->vco1.max_freq = nv_ro32(bios, bios->bmp_offset + 67); + info->vco1.min_freq = nv_ro32(bios, bios->bmp_offset + 71); + if (bmp_version(bios) < 0x0506) { + info->vco1.max_freq = 256000; + info->vco1.min_freq = 128000; + } + + info->vco1.min_inputfreq = 0; + info->vco1.max_inputfreq = INT_MAX; + info->vco1.min_n = 0x1; + info->vco1.max_n = 0xff; + info->vco1.min_m = 0x1; + + if (nv_device(bios)->crystal == 13500) { + /* nv05 does this, nv11 doesn't, nv10 unknown */ + if (bios->version.chip < 0x11) + info->vco1.min_m = 0x7; + info->vco1.max_m = 0xd; + } else { + if (bios->version.chip < 0x11) + info->vco1.min_m = 0x8; + info->vco1.max_m = 0xe; + } + + if (bios->version.chip < 0x17 || + bios->version.chip == 0x1a || + bios->version.chip == 0x20) + info->max_p = 4; + else + info->max_p = 5; + info->max_p_usable = info->max_p; + } + + return 0; +} diff --git a/drivers/gpu/drm/nouveau/core/subdev/clock/nv04.c b/drivers/gpu/drm/nouveau/core/subdev/clock/nv04.c index 3a3b3b149690..b7fd1151166e 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/clock/nv04.c +++ b/drivers/gpu/drm/nouveau/core/subdev/clock/nv04.c @@ -23,17 +23,309 @@ */ #include +#include +#include + +#include "pll.h" struct nv04_clock_priv { struct nouveau_clock base; }; +static int +powerctrl_1_shift(int chip_version, int reg) +{ + int shift = -4; + + if (chip_version < 0x17 || chip_version == 0x1a || chip_version == 0x20) + return shift; + + switch (reg) { + case 0x680520: + shift += 4; + case 0x680508: + shift += 4; + case 0x680504: + shift += 4; + case 0x680500: + shift += 4; + } + + /* + * the shift for vpll regs is only used for nv3x chips with a single + * stage pll + */ + if (shift > 4 && (chip_version < 0x32 || chip_version == 0x35 || + chip_version == 0x36 || chip_version >= 0x40)) + shift = -4; + + return shift; +} + static void +setPLL_single(struct nv04_clock_priv *priv, u32 reg, + struct nouveau_pll_vals *pv) +{ + int chip_version = nouveau_bios(priv)->version.chip; + uint32_t oldpll = nv_rd32(priv, reg); + int oldN = (oldpll >> 8) & 0xff, oldM = oldpll & 0xff; + uint32_t pll = (oldpll & 0xfff80000) | pv->log2P << 16 | pv->NM1; + uint32_t saved_powerctrl_1 = 0; + int shift_powerctrl_1 = powerctrl_1_shift(chip_version, reg); + + if (oldpll == pll) + return; /* already set */ + + if (shift_powerctrl_1 >= 0) { + saved_powerctrl_1 = nv_rd32(priv, 0x001584); + nv_wr32(priv, 0x001584, + (saved_powerctrl_1 & ~(0xf << shift_powerctrl_1)) | + 1 << shift_powerctrl_1); + } + + if (oldM && pv->M1 && (oldN / oldM < pv->N1 / pv->M1)) + /* upclock -- write new post divider first */ + nv_wr32(priv, reg, pv->log2P << 16 | (oldpll & 0xffff)); + else + /* downclock -- write new NM first */ + nv_wr32(priv, reg, (oldpll & 0xffff0000) | pv->NM1); + + if (chip_version < 0x17 && chip_version != 0x11) + /* wait a bit on older chips */ + msleep(64); + nv_rd32(priv, reg); + + /* then write the other half as well */ + nv_wr32(priv, reg, pll); + + if (shift_powerctrl_1 >= 0) + nv_wr32(priv, 0x001584, saved_powerctrl_1); +} + +static uint32_t +new_ramdac580(uint32_t reg1, bool ss, uint32_t ramdac580) +{ + bool head_a = (reg1 == 0x680508); + + if (ss) /* single stage pll mode */ + ramdac580 |= head_a ? 0x00000100 : 0x10000000; + else + ramdac580 &= head_a ? 0xfffffeff : 0xefffffff; + + return ramdac580; +} + +static void +setPLL_double_highregs(struct nv04_clock_priv *priv, u32 reg1, + struct nouveau_pll_vals *pv) +{ + int chip_version = nouveau_bios(priv)->version.chip; + bool nv3035 = chip_version == 0x30 || chip_version == 0x35; + uint32_t reg2 = reg1 + ((reg1 == 0x680520) ? 0x5c : 0x70); + uint32_t oldpll1 = nv_rd32(priv, reg1); + uint32_t oldpll2 = !nv3035 ? nv_rd32(priv, reg2) : 0; + uint32_t pll1 = (oldpll1 & 0xfff80000) | pv->log2P << 16 | pv->NM1; + uint32_t pll2 = (oldpll2 & 0x7fff0000) | 1 << 31 | pv->NM2; + uint32_t oldramdac580 = 0, ramdac580 = 0; + bool single_stage = !pv->NM2 || pv->N2 == pv->M2; /* nv41+ only */ + uint32_t saved_powerctrl_1 = 0, savedc040 = 0; + int shift_powerctrl_1 = powerctrl_1_shift(chip_version, reg1); + + /* model specific additions to generic pll1 and pll2 set up above */ + if (nv3035) { + pll1 = (pll1 & 0xfcc7ffff) | (pv->N2 & 0x18) << 21 | + (pv->N2 & 0x7) << 19 | 8 << 4 | (pv->M2 & 7) << 4; + pll2 = 0; + } + if (chip_version > 0x40 && reg1 >= 0x680508) { /* !nv40 */ + oldramdac580 = nv_rd32(priv, 0x680580); + ramdac580 = new_ramdac580(reg1, single_stage, oldramdac580); + if (oldramdac580 != ramdac580) + oldpll1 = ~0; /* force mismatch */ + if (single_stage) + /* magic value used by nvidia in single stage mode */ + pll2 |= 0x011f; + } + if (chip_version > 0x70) + /* magic bits set by the blob (but not the bios) on g71-73 */ + pll1 = (pll1 & 0x7fffffff) | (single_stage ? 0x4 : 0xc) << 28; + + if (oldpll1 == pll1 && oldpll2 == pll2) + return; /* already set */ + + if (shift_powerctrl_1 >= 0) { + saved_powerctrl_1 = nv_rd32(priv, 0x001584); + nv_wr32(priv, 0x001584, + (saved_powerctrl_1 & ~(0xf << shift_powerctrl_1)) | + 1 << shift_powerctrl_1); + } + + if (chip_version >= 0x40) { + int shift_c040 = 14; + + switch (reg1) { + case 0x680504: + shift_c040 += 2; + case 0x680500: + shift_c040 += 2; + case 0x680520: + shift_c040 += 2; + case 0x680508: + shift_c040 += 2; + } + + savedc040 = nv_rd32(priv, 0xc040); + if (shift_c040 != 14) + nv_wr32(priv, 0xc040, savedc040 & ~(3 << shift_c040)); + } + + if (oldramdac580 != ramdac580) + nv_wr32(priv, 0x680580, ramdac580); + + if (!nv3035) + nv_wr32(priv, reg2, pll2); + nv_wr32(priv, reg1, pll1); + + if (shift_powerctrl_1 >= 0) + nv_wr32(priv, 0x001584, saved_powerctrl_1); + if (chip_version >= 0x40) + nv_wr32(priv, 0xc040, savedc040); +} + +static void +setPLL_double_lowregs(struct nv04_clock_priv *priv, u32 NMNMreg, + struct nouveau_pll_vals *pv) +{ + /* When setting PLLs, there is a merry game of disabling and enabling + * various bits of hardware during the process. This function is a + * synthesis of six nv4x traces, nearly each card doing a subtly + * different thing. With luck all the necessary bits for each card are + * combined herein. Without luck it deviates from each card's formula + * so as to not work on any :) + */ + + uint32_t Preg = NMNMreg - 4; + bool mpll = Preg == 0x4020; + uint32_t oldPval = nv_rd32(priv, Preg); + uint32_t NMNM = pv->NM2 << 16 | pv->NM1; + uint32_t Pval = (oldPval & (mpll ? ~(0x77 << 16) : ~(7 << 16))) | + 0xc << 28 | pv->log2P << 16; + uint32_t saved4600 = 0; + /* some cards have different maskc040s */ + uint32_t maskc040 = ~(3 << 14), savedc040; + bool single_stage = !pv->NM2 || pv->N2 == pv->M2; + + if (nv_rd32(priv, NMNMreg) == NMNM && (oldPval & 0xc0070000) == Pval) + return; + + if (Preg == 0x4000) + maskc040 = ~0x333; + if (Preg == 0x4058) + maskc040 = ~(0xc << 24); + + if (mpll) { + struct nvbios_pll info; + uint8_t Pval2; + + if (nvbios_pll_parse(nouveau_bios(priv), Preg, &info)) + return; + + Pval2 = pv->log2P + info.bias_p; + if (Pval2 > info.max_p) + Pval2 = info.max_p; + Pval |= 1 << 28 | Pval2 << 20; + + saved4600 = nv_rd32(priv, 0x4600); + nv_wr32(priv, 0x4600, saved4600 | 8 << 28); + } + if (single_stage) + Pval |= mpll ? 1 << 12 : 1 << 8; + + nv_wr32(priv, Preg, oldPval | 1 << 28); + nv_wr32(priv, Preg, Pval & ~(4 << 28)); + if (mpll) { + Pval |= 8 << 20; + nv_wr32(priv, 0x4020, Pval & ~(0xc << 28)); + nv_wr32(priv, 0x4038, Pval & ~(0xc << 28)); + } + + savedc040 = nv_rd32(priv, 0xc040); + nv_wr32(priv, 0xc040, savedc040 & maskc040); + + nv_wr32(priv, NMNMreg, NMNM); + if (NMNMreg == 0x4024) + nv_wr32(priv, 0x403c, NMNM); + + nv_wr32(priv, Preg, Pval); + if (mpll) { + Pval &= ~(8 << 20); + nv_wr32(priv, 0x4020, Pval); + nv_wr32(priv, 0x4038, Pval); + nv_wr32(priv, 0x4600, saved4600); + } + + nv_wr32(priv, 0xc040, savedc040); + + if (mpll) { + nv_wr32(priv, 0x4020, Pval & ~(1 << 28)); + nv_wr32(priv, 0x4038, Pval & ~(1 << 28)); + } +} + +int nv04_clock_pll_set(struct nouveau_clock *clk, u32 type, u32 freq) { struct nv04_clock_priv *priv = (void *)clk; + struct nouveau_pll_vals pv; + struct nvbios_pll info; + int ret; + + ret = nvbios_pll_parse(nouveau_bios(priv), type > 0x405c ? + type : type - 4, &info); + if (ret) + return ret; + + ret = clk->pll_calc(clk, &info, freq, &pv); + if (!ret) + return ret; + + return clk->pll_prog(clk, type, &pv); +} - nv_warn(priv, "0x%08x/%dKhz unimplemented\n", type, freq); +int +nv04_clock_pll_calc(struct nouveau_clock *clock, struct nvbios_pll *info, + int clk, struct nouveau_pll_vals *pv) +{ + int N1, M1, N2, M2, P; + int ret = nv04_pll_calc(clock, info, clk, &N1, &M1, &N2, &M2, &P); + if (ret) { + pv->refclk = info->refclk; + pv->N1 = N1; + pv->M1 = M1; + pv->N2 = N2; + pv->M2 = M2; + pv->log2P = P; + } + return ret; +} + +int +nv04_clock_pll_prog(struct nouveau_clock *clk, u32 reg1, + struct nouveau_pll_vals *pv) +{ + struct nv04_clock_priv *priv = (void *)clk; + int cv = nouveau_bios(clk)->version.chip; + + if (cv == 0x30 || cv == 0x31 || cv == 0x35 || cv == 0x36 || + cv >= 0x40) { + if (reg1 > 0x405c) + setPLL_double_highregs(priv, reg1, pv); + else + setPLL_double_lowregs(priv, reg1, pv); + } else + setPLL_single(priv, reg1, pv); + + return 0; } static int @@ -50,6 +342,8 @@ nv04_clock_ctor(struct nouveau_object *parent, struct nouveau_object *engine, return ret; priv->base.pll_set = nv04_clock_pll_set; + priv->base.pll_calc = nv04_clock_pll_calc; + priv->base.pll_prog = nv04_clock_pll_prog; return 0; } diff --git a/drivers/gpu/drm/nouveau/core/subdev/clock/nv40.c b/drivers/gpu/drm/nouveau/core/subdev/clock/nv40.c index 60d1ca44e39c..a4b2b7ebf9af 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/clock/nv40.c +++ b/drivers/gpu/drm/nouveau/core/subdev/clock/nv40.c @@ -28,14 +28,6 @@ struct nv40_clock_priv { struct nouveau_clock base; }; -static void -nv40_clock_pll_set(struct nouveau_clock *clk, u32 type, u32 freq) -{ - struct nv40_clock_priv *priv = (void *)clk; - - nv_warn(priv, "0x%08x/%dKhz unimplemented\n", type, freq); -} - static int nv40_clock_ctor(struct nouveau_object *parent, struct nouveau_object *engine, struct nouveau_oclass *oclass, void *data, u32 size, @@ -49,7 +41,9 @@ nv40_clock_ctor(struct nouveau_object *parent, struct nouveau_object *engine, if (ret) return ret; - priv->base.pll_set = nv40_clock_pll_set; + priv->base.pll_set = nv04_clock_pll_set; + priv->base.pll_calc = nv04_clock_pll_calc; + priv->base.pll_prog = nv04_clock_pll_prog; return 0; } diff --git a/drivers/gpu/drm/nouveau/core/subdev/clock/nv50.c b/drivers/gpu/drm/nouveau/core/subdev/clock/nv50.c index 82804bdcec31..fd181fbceddb 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/clock/nv50.c +++ b/drivers/gpu/drm/nouveau/core/subdev/clock/nv50.c @@ -23,17 +23,57 @@ */ #include +#include +#include + +#include "pll.h" struct nv50_clock_priv { struct nouveau_clock base; }; -static void +static int nv50_clock_pll_set(struct nouveau_clock *clk, u32 type, u32 freq) { struct nv50_clock_priv *priv = (void *)clk; + struct nouveau_bios *bios = nouveau_bios(priv); + struct nvbios_pll info; + int N1, M1, N2, M2, P; + int ret; + + ret = nvbios_pll_parse(bios, type, &info); + if (ret) { + nv_error(clk, "failed to retrieve pll data, %d\n", ret); + return ret; + } - nv_warn(priv, "0x%08x/%dKhz unimplemented\n", type, freq); + ret = nv04_pll_calc(clk, &info, freq, &N1, &M1, &N2, &M2, &P); + if (!ret) { + nv_error(clk, "failed pll calculation\n"); + return ret; + } + + switch (info.type) { + case PLL_VPLL0: + case PLL_VPLL1: + nv_wr32(priv, info.reg + 0, 0x10000611); + nv_mask(priv, info.reg + 4, 0x00ff00ff, (M1 << 16) | N1); + nv_mask(priv, info.reg + 8, 0x7fff00ff, (P << 28) | + (M2 << 16) | N2); + break; + case PLL_MEMORY: + nv_mask(priv, info.reg + 0, 0x01ff0000, (P << 22) | + (info.bias_p << 19) | + (P << 16)); + nv_wr32(priv, info.reg + 4, (N1 << 8) | M1); + break; + default: + nv_mask(priv, info.reg + 0, 0x00070000, (P << 16)); + nv_wr32(priv, info.reg + 4, (N1 << 8) | M1); + break; + } + + return 0; } static int diff --git a/drivers/gpu/drm/nouveau/core/subdev/clock/nva3.c b/drivers/gpu/drm/nouveau/core/subdev/clock/nva3.c index 876ec46e2b41..cc8d7d162d7c 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/clock/nva3.c +++ b/drivers/gpu/drm/nouveau/core/subdev/clock/nva3.c @@ -23,17 +23,47 @@ */ #include +#include +#include + +#include "pll.h" struct nva3_clock_priv { struct nouveau_clock base; }; -static void +static int nva3_clock_pll_set(struct nouveau_clock *clk, u32 type, u32 freq) { struct nva3_clock_priv *priv = (void *)clk; + struct nouveau_bios *bios = nouveau_bios(priv); + struct nvbios_pll info; + int N, fN, M, P; + int ret; + + ret = nvbios_pll_parse(bios, type, &info); + if (ret) + return ret; + + ret = nva3_pll_calc(clk, &info, freq, &N, &fN, &M, &P); + if (ret < 0) + return ret; + + switch (info.type) { + case PLL_VPLL0: + case PLL_VPLL1: + nv_wr32(priv, info.reg + 0, 0x50000610); + nv_mask(priv, info.reg + 4, 0x003fffff, + (P << 16) | (M << 8) | N); + nv_wr32(priv, info.reg + 8, fN); + break; + default: + nv_warn(priv, "0x%08x/%dKhz unimplemented\n", type, freq); + ret = -EINVAL; + break; + } - nv_warn(priv, "0x%08x/%dKhz unimplemented\n", type, freq); + return ret; } static int diff --git a/drivers/gpu/drm/nouveau/core/subdev/clock/nvc0.c b/drivers/gpu/drm/nouveau/core/subdev/clock/nvc0.c index 00641566f2e7..5ccce0b17bf3 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/clock/nvc0.c +++ b/drivers/gpu/drm/nouveau/core/subdev/clock/nvc0.c @@ -23,17 +23,46 @@ */ #include +#include +#include + +#include "pll.h" struct nvc0_clock_priv { struct nouveau_clock base; }; -static void +static int nvc0_clock_pll_set(struct nouveau_clock *clk, u32 type, u32 freq) { struct nvc0_clock_priv *priv = (void *)clk; + struct nouveau_bios *bios = nouveau_bios(priv); + struct nvbios_pll info; + int N, fN, M, P; + int ret; + + ret = nvbios_pll_parse(bios, type, &info); + if (ret) + return ret; + + ret = nva3_pll_calc(clk, &info, freq, &N, &fN, &M, &P); + if (ret < 0) + return ret; + + switch (info.type) { + case PLL_VPLL0: + case PLL_VPLL1: + nv_mask(priv, info.reg + 0x0c, 0x00000000, 0x00000100); + nv_wr32(priv, info.reg + 0x04, (P << 16) | (N << 8) | M); + nv_wr32(priv, info.reg + 0x10, fN << 16); + break; + default: + nv_warn(priv, "0x%08x/%dKhz unimplemented\n", type, freq); + ret = -EINVAL; + break; + } - nv_warn(priv, "0x%08x/%dKhz unimplemented\n", type, freq); + return ret; } static int diff --git a/drivers/gpu/drm/nouveau/core/subdev/clock/pll.h b/drivers/gpu/drm/nouveau/core/subdev/clock/pll.h new file mode 100644 index 000000000000..ef2c0078f337 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/subdev/clock/pll.h @@ -0,0 +1,9 @@ +#ifndef __NOUVEAU_PLL_H__ +#define __NOUVEAU_PLL_H__ + +int nv04_pll_calc(struct nouveau_clock *, struct nvbios_pll *, u32 freq, + int *N1, int *M1, int *N2, int *M2, int *P); +int nva3_pll_calc(struct nouveau_clock *, struct nvbios_pll *, u32 freq, + int *N, int *fN, int *M, int *P); + +#endif diff --git a/drivers/gpu/drm/nouveau/core/subdev/clock/pllnv04.c b/drivers/gpu/drm/nouveau/core/subdev/clock/pllnv04.c new file mode 100644 index 000000000000..a2ab6d051ba8 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/subdev/clock/pllnv04.c @@ -0,0 +1,242 @@ +/* + * Copyright 1993-2003 NVIDIA, Corporation + * Copyright 2007-2009 Stuart Bennett + * + * 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 AUTHORS 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. + */ + +#include +#include +#include + +#include "pll.h" + +static int +getMNP_single(struct nouveau_clock *clock, struct nvbios_pll *info, int clk, + int *pN, int *pM, int *pP) +{ + /* Find M, N and P for a single stage PLL + * + * Note that some bioses (NV3x) have lookup tables of precomputed MNP + * values, but we're too lazy to use those atm + * + * "clk" parameter in kHz + * returns calculated clock + */ + int cv = nouveau_bios(clock)->version.chip; + int minvco = info->vco1.min_freq, maxvco = info->vco1.max_freq; + int minM = info->vco1.min_m, maxM = info->vco1.max_m; + int minN = info->vco1.min_n, maxN = info->vco1.max_n; + int minU = info->vco1.min_inputfreq; + int maxU = info->vco1.max_inputfreq; + int minP = info->min_p; + int maxP = info->max_p_usable; + int crystal = info->refclk; + int M, N, thisP, P; + int clkP, calcclk; + int delta, bestdelta = INT_MAX; + int bestclk = 0; + + /* this division verified for nv20, nv18, nv28 (Haiku), and nv34 */ + /* possibly correlated with introduction of 27MHz crystal */ + if (cv < 0x17 || cv == 0x1a || cv == 0x20) { + if (clk > 250000) + maxM = 6; + if (clk > 340000) + maxM = 2; + } else if (cv < 0x40) { + if (clk > 150000) + maxM = 6; + if (clk > 200000) + maxM = 4; + if (clk > 340000) + maxM = 2; + } + + P = 1 << maxP; + if ((clk * P) < minvco) { + minvco = clk * maxP; + maxvco = minvco * 2; + } + + if (clk + clk/200 > maxvco) /* +0.5% */ + maxvco = clk + clk/200; + + /* NV34 goes maxlog2P->0, NV20 goes 0->maxlog2P */ + for (thisP = minP; thisP <= maxP; thisP++) { + P = 1 << thisP; + clkP = clk * P; + + if (clkP < minvco) + continue; + if (clkP > maxvco) + return bestclk; + + for (M = minM; M <= maxM; M++) { + if (crystal/M < minU) + return bestclk; + if (crystal/M > maxU) + continue; + + /* add crystal/2 to round better */ + N = (clkP * M + crystal/2) / crystal; + + if (N < minN) + continue; + if (N > maxN) + break; + + /* more rounding additions */ + calcclk = ((N * crystal + P/2) / P + M/2) / M; + delta = abs(calcclk - clk); + /* we do an exhaustive search rather than terminating + * on an optimality condition... + */ + if (delta < bestdelta) { + bestdelta = delta; + bestclk = calcclk; + *pN = N; + *pM = M; + *pP = thisP; + if (delta == 0) /* except this one */ + return bestclk; + } + } + } + + return bestclk; +} + +static int +getMNP_double(struct nouveau_clock *clock, struct nvbios_pll *info, int clk, + int *pN1, int *pM1, int *pN2, int *pM2, int *pP) +{ + /* Find M, N and P for a two stage PLL + * + * Note that some bioses (NV30+) have lookup tables of precomputed MNP + * values, but we're too lazy to use those atm + * + * "clk" parameter in kHz + * returns calculated clock + */ + int chip_version = nouveau_bios(clock)->version.chip; + int minvco1 = info->vco1.min_freq, maxvco1 = info->vco1.max_freq; + int minvco2 = info->vco2.min_freq, maxvco2 = info->vco2.max_freq; + int minU1 = info->vco1.min_inputfreq, minU2 = info->vco2.min_inputfreq; + int maxU1 = info->vco1.max_inputfreq, maxU2 = info->vco2.max_inputfreq; + int minM1 = info->vco1.min_m, maxM1 = info->vco1.max_m; + int minN1 = info->vco1.min_n, maxN1 = info->vco1.max_n; + int minM2 = info->vco2.min_m, maxM2 = info->vco2.max_m; + int minN2 = info->vco2.min_n, maxN2 = info->vco2.max_n; + int maxlog2P = info->max_p_usable; + int crystal = info->refclk; + bool fixedgain2 = (minM2 == maxM2 && minN2 == maxN2); + int M1, N1, M2, N2, log2P; + int clkP, calcclk1, calcclk2, calcclkout; + int delta, bestdelta = INT_MAX; + int bestclk = 0; + + int vco2 = (maxvco2 - maxvco2/200) / 2; + for (log2P = 0; clk && log2P < maxlog2P && clk <= (vco2 >> log2P); log2P++) + ; + clkP = clk << log2P; + + if (maxvco2 < clk + clk/200) /* +0.5% */ + maxvco2 = clk + clk/200; + + for (M1 = minM1; M1 <= maxM1; M1++) { + if (crystal/M1 < minU1) + return bestclk; + if (crystal/M1 > maxU1) + continue; + + for (N1 = minN1; N1 <= maxN1; N1++) { + calcclk1 = crystal * N1 / M1; + if (calcclk1 < minvco1) + continue; + if (calcclk1 > maxvco1) + break; + + for (M2 = minM2; M2 <= maxM2; M2++) { + if (calcclk1/M2 < minU2) + break; + if (calcclk1/M2 > maxU2) + continue; + + /* add calcclk1/2 to round better */ + N2 = (clkP * M2 + calcclk1/2) / calcclk1; + if (N2 < minN2) + continue; + if (N2 > maxN2) + break; + + if (!fixedgain2) { + if (chip_version < 0x60) + if (N2/M2 < 4 || N2/M2 > 10) + continue; + + calcclk2 = calcclk1 * N2 / M2; + if (calcclk2 < minvco2) + break; + if (calcclk2 > maxvco2) + continue; + } else + calcclk2 = calcclk1; + + calcclkout = calcclk2 >> log2P; + delta = abs(calcclkout - clk); + /* we do an exhaustive search rather than terminating + * on an optimality condition... + */ + if (delta < bestdelta) { + bestdelta = delta; + bestclk = calcclkout; + *pN1 = N1; + *pM1 = M1; + *pN2 = N2; + *pM2 = M2; + *pP = log2P; + if (delta == 0) /* except this one */ + return bestclk; + } + } + } + } + + return bestclk; +} + +int +nv04_pll_calc(struct nouveau_clock *clk, struct nvbios_pll *info, u32 freq, + int *N1, int *M1, int *N2, int *M2, int *P) +{ + int ret; + + if (!info->vco2.max_freq) { + ret = getMNP_single(clk, info, freq, N1, M1, P); + *N2 = 1; + *M2 = 1; + } else { + ret = getMNP_double(clk, info, freq, N1, M1, N2, M2, P); + } + + if (!ret) + nv_error(clk, "unable to compute acceptable pll values\n"); + return ret; +} diff --git a/drivers/gpu/drm/nouveau/core/subdev/clock/pllnva3.c b/drivers/gpu/drm/nouveau/core/subdev/clock/pllnva3.c new file mode 100644 index 000000000000..eed5c16cf610 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/subdev/clock/pllnva3.c @@ -0,0 +1,80 @@ +/* + * Copyright 2010 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 +#include +#include + +#include "pll.h" + +int +nva3_pll_calc(struct nouveau_clock *clock, struct nvbios_pll *info, + u32 freq, int *pN, int *pfN, int *pM, int *P) +{ + u32 best_err = ~0, err; + int M, lM, hM, N, fN; + + *P = info->vco1.max_freq / freq; + if (*P > info->max_p) + *P = info->max_p; + if (*P < info->min_p) + *P = info->min_p; + + lM = (info->refclk + info->vco1.max_inputfreq) / info->vco1.max_inputfreq; + lM = max(lM, (int)info->vco1.min_m); + hM = (info->refclk + info->vco1.min_inputfreq) / info->vco1.min_inputfreq; + hM = min(hM, (int)info->vco1.max_m); + + for (M = lM; M <= hM; M++) { + u32 tmp = freq * *P * M; + N = tmp / info->refclk; + fN = tmp % info->refclk; + if (!pfN && fN >= info->refclk / 2) + N++; + + if (N < info->vco1.min_n) + continue; + if (N > info->vco1.max_n) + break; + + err = abs(freq - (info->refclk * N / M / *P)); + if (err < best_err) { + best_err = err; + *pN = N; + *pM = M; + } + + if (pfN) { + *pfN = (((fN << 13) / info->refclk) - 4096) & 0xffff; + return freq; + } + } + + if (unlikely(best_err == ~0)) { + nv_error(clock, "unable to find matching pll values\n"); + return -EINVAL; + } + + return info->refclk * *pN / *pM / *P; +} diff --git a/drivers/gpu/drm/nouveau/nouveau_bios.c b/drivers/gpu/drm/nouveau/nouveau_bios.c index 35b0a8f9c008..98eaac9da30e 100644 --- a/drivers/gpu/drm/nouveau/nouveau_bios.c +++ b/drivers/gpu/drm/nouveau/nouveau_bios.c @@ -441,70 +441,6 @@ io_condition_met(struct nvbios *bios, uint16_t offset, uint8_t cond) return (data == cmpval); } -static int -nv50_pll_set(struct drm_device *dev, uint32_t reg, uint32_t clk) -{ - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_pll_vals pll; - struct pll_lims pll_limits; - u32 ctrl, mask, coef; - int ret; - - ret = get_pll_limits(dev, reg, &pll_limits); - if (ret) - return ret; - - clk = nouveau_calc_pll_mnp(dev, &pll_limits, clk, &pll); - if (!clk) - return -ERANGE; - - coef = pll.N1 << 8 | pll.M1; - ctrl = pll.log2P << 16; - mask = 0x00070000; - if (reg == 0x004008) { - mask |= 0x01f80000; - ctrl |= (pll_limits.log2p_bias << 19); - ctrl |= (pll.log2P << 22); - } - - if (!dev_priv->vbios.execute) - return 0; - - nv_mask(dev, reg + 0, mask, ctrl); - nv_wr32(dev, reg + 4, coef); - return 0; -} - -static int -setPLL(struct nvbios *bios, uint32_t reg, uint32_t clk) -{ - struct drm_device *dev = bios->dev; - struct drm_nouveau_private *dev_priv = dev->dev_private; - /* clk in kHz */ - struct pll_lims pll_lim; - struct nouveau_pll_vals pllvals; - int ret; - - if (dev_priv->card_type >= NV_50) - return nv50_pll_set(dev, reg, clk); - - /* high regs (such as in the mac g5 table) are not -= 4 */ - ret = get_pll_limits(dev, reg > 0x405c ? reg : reg - 4, &pll_lim); - if (ret) - return ret; - - clk = nouveau_calc_pll_mnp(dev, &pll_lim, clk, &pllvals); - if (!clk) - return -ERANGE; - - if (bios->execute) { - still_alive(); - nouveau_hw_setpll(dev, reg, &pllvals); - } - - return 0; -} - static int dcb_entry_idx_from_crtchead(struct drm_device *dev) { struct drm_nouveau_private *dev_priv = dev->dev_private; @@ -752,7 +688,7 @@ init_io_restrict_pll(struct nvbios *bios, uint16_t offset, BIOSLOG(bios, "0x%04X: Reg: 0x%08X, Config: 0x%02X, Freq: %d0kHz\n", offset, reg, config, freq); - setPLL(bios, reg, freq * 10); + setPLL(bios->dev, reg, freq * 10); return len; } @@ -1110,7 +1046,7 @@ init_io_restrict_pll2(struct nvbios *bios, uint16_t offset, BIOSLOG(bios, "0x%04X: Reg: 0x%08X, Config: 0x%02X, Freq: %dkHz\n", offset, reg, config, freq); - setPLL(bios, reg, freq); + setPLL(bios->dev, reg, freq); return len; } @@ -1137,7 +1073,7 @@ init_pll2(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) BIOSLOG(bios, "0x%04X: Reg: 0x%04X, Freq: %dkHz\n", offset, reg, freq); - setPLL(bios, reg, freq); + setPLL(bios->dev, reg, freq); return 9; } @@ -2376,12 +2312,12 @@ init_configure_clk(struct nvbios *bios, uint16_t offset, return 0; clock = ROM16(bios->data[meminitoffs + 4]) * 10; - setPLL(bios, NV_PRAMDAC_NVPLL_COEFF, clock); + setPLL(bios->dev, NV_PRAMDAC_NVPLL_COEFF, clock); clock = ROM16(bios->data[meminitoffs + 2]) * 10; if (bios->data[meminitoffs] & 1) /* DDR */ clock *= 2; - setPLL(bios, NV_PRAMDAC_MPLL_COEFF, clock); + setPLL(bios->dev, NV_PRAMDAC_MPLL_COEFF, clock); return 1; } @@ -2820,7 +2756,7 @@ init_pll(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) BIOSLOG(bios, "0x%04X: Reg: 0x%08X, Freq: %d0kHz\n", offset, reg, freq); - setPLL(bios, reg, freq * 10); + setPLL(bios->dev, reg, freq * 10); return 7; } @@ -2898,7 +2834,7 @@ init_ram_restrict_pll(struct nvbios *bios, uint16_t offset, "Type %02x Reg 0x%08x Freq %dKHz\n", offset, type, reg, freq); - setPLL(bios, reg, freq); + setPLL(bios->dev, reg, freq); return len; } } @@ -4305,447 +4241,6 @@ int run_tmds_table(struct drm_device *dev, struct dcb_entry *dcbent, int head, i return 0; } -struct pll_mapping { - u8 type; - u32 reg; -}; - -static struct pll_mapping nv04_pll_mapping[] = { - { PLL_CORE , NV_PRAMDAC_NVPLL_COEFF }, - { PLL_MEMORY, NV_PRAMDAC_MPLL_COEFF }, - { PLL_VPLL0 , NV_PRAMDAC_VPLL_COEFF }, - { PLL_VPLL1 , NV_RAMDAC_VPLL2 }, - {} -}; - -static struct pll_mapping nv40_pll_mapping[] = { - { PLL_CORE , 0x004000 }, - { PLL_MEMORY, 0x004020 }, - { PLL_VPLL0 , NV_PRAMDAC_VPLL_COEFF }, - { PLL_VPLL1 , NV_RAMDAC_VPLL2 }, - {} -}; - -static struct pll_mapping nv50_pll_mapping[] = { - { PLL_CORE , 0x004028 }, - { PLL_SHADER, 0x004020 }, - { PLL_UNK03 , 0x004000 }, - { PLL_MEMORY, 0x004008 }, - { PLL_UNK40 , 0x00e810 }, - { PLL_UNK41 , 0x00e818 }, - { PLL_UNK42 , 0x00e824 }, - { PLL_VPLL0 , 0x614100 }, - { PLL_VPLL1 , 0x614900 }, - {} -}; - -static struct pll_mapping nv84_pll_mapping[] = { - { PLL_CORE , 0x004028 }, - { PLL_SHADER, 0x004020 }, - { PLL_MEMORY, 0x004008 }, - { PLL_VDEC , 0x004030 }, - { PLL_UNK41 , 0x00e818 }, - { PLL_VPLL0 , 0x614100 }, - { PLL_VPLL1 , 0x614900 }, - {} -}; - -u32 -get_pll_register(struct drm_device *dev, enum pll_types type) -{ - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nvbios *bios = &dev_priv->vbios; - struct pll_mapping *map; - int i; - - if (dev_priv->card_type < NV_40) - map = nv04_pll_mapping; - else - if (dev_priv->card_type < NV_50) - map = nv40_pll_mapping; - else { - u8 *plim = &bios->data[bios->pll_limit_tbl_ptr]; - - if (plim[0] >= 0x30) { - u8 *entry = plim + plim[1]; - for (i = 0; i < plim[3]; i++, entry += plim[2]) { - if (entry[0] == type) - return ROM32(entry[3]); - } - - return 0; - } - - if (dev_priv->chipset == 0x50) - map = nv50_pll_mapping; - else - map = nv84_pll_mapping; - } - - while (map->reg) { - if (map->type == type) - return map->reg; - map++; - } - - return 0; -} - -int get_pll_limits(struct drm_device *dev, uint32_t limit_match, struct pll_lims *pll_lim) -{ - /* - * PLL limits table - * - * Version 0x10: NV30, NV31 - * One byte header (version), one record of 24 bytes - * Version 0x11: NV36 - Not implemented - * Seems to have same record style as 0x10, but 3 records rather than 1 - * Version 0x20: Found on Geforce 6 cards - * Trivial 4 byte BIT header. 31 (0x1f) byte record length - * Version 0x21: Found on Geforce 7, 8 and some Geforce 6 cards - * 5 byte header, fifth byte of unknown purpose. 35 (0x23) byte record - * length in general, some (integrated) have an extra configuration byte - * Version 0x30: Found on Geforce 8, separates the register mapping - * from the limits tables. - */ - - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nvbios *bios = &dev_priv->vbios; - int cv = bios->chip_version, pllindex = 0; - uint8_t pll_lim_ver = 0, headerlen = 0, recordlen = 0, entries = 0; - uint32_t crystal_strap_mask, crystal_straps; - - if (!bios->pll_limit_tbl_ptr) { - if (cv == 0x30 || cv == 0x31 || cv == 0x35 || cv == 0x36 || - cv >= 0x40) { - NV_ERROR(dev, "Pointer to PLL limits table invalid\n"); - return -EINVAL; - } - } else - pll_lim_ver = bios->data[bios->pll_limit_tbl_ptr]; - - crystal_strap_mask = 1 << 6; - /* open coded dev->twoHeads test */ - if (cv > 0x10 && cv != 0x15 && cv != 0x1a && cv != 0x20) - crystal_strap_mask |= 1 << 22; - crystal_straps = nvReadEXTDEV(dev, NV_PEXTDEV_BOOT_0) & - crystal_strap_mask; - - switch (pll_lim_ver) { - /* - * We use version 0 to indicate a pre limit table bios (single stage - * pll) and load the hard coded limits instead. - */ - case 0: - break; - case 0x10: - case 0x11: - /* - * Strictly v0x11 has 3 entries, but the last two don't seem - * to get used. - */ - headerlen = 1; - recordlen = 0x18; - entries = 1; - pllindex = 0; - break; - case 0x20: - case 0x21: - case 0x30: - case 0x40: - headerlen = bios->data[bios->pll_limit_tbl_ptr + 1]; - recordlen = bios->data[bios->pll_limit_tbl_ptr + 2]; - entries = bios->data[bios->pll_limit_tbl_ptr + 3]; - break; - default: - NV_ERROR(dev, "PLL limits table revision 0x%X not currently " - "supported\n", pll_lim_ver); - return -ENOSYS; - } - - /* initialize all members to zero */ - memset(pll_lim, 0, sizeof(struct pll_lims)); - - /* if we were passed a type rather than a register, figure - * out the register and store it - */ - if (limit_match > PLL_MAX) - pll_lim->reg = limit_match; - else { - pll_lim->reg = get_pll_register(dev, limit_match); - if (!pll_lim->reg) - return -ENOENT; - } - - if (pll_lim_ver == 0x10 || pll_lim_ver == 0x11) { - uint8_t *pll_rec = &bios->data[bios->pll_limit_tbl_ptr + headerlen + recordlen * pllindex]; - - pll_lim->vco1.minfreq = ROM32(pll_rec[0]); - pll_lim->vco1.maxfreq = ROM32(pll_rec[4]); - pll_lim->vco2.minfreq = ROM32(pll_rec[8]); - pll_lim->vco2.maxfreq = ROM32(pll_rec[12]); - pll_lim->vco1.min_inputfreq = ROM32(pll_rec[16]); - pll_lim->vco2.min_inputfreq = ROM32(pll_rec[20]); - pll_lim->vco1.max_inputfreq = pll_lim->vco2.max_inputfreq = INT_MAX; - - /* these values taken from nv30/31/36 */ - pll_lim->vco1.min_n = 0x1; - if (cv == 0x36) - pll_lim->vco1.min_n = 0x5; - pll_lim->vco1.max_n = 0xff; - pll_lim->vco1.min_m = 0x1; - pll_lim->vco1.max_m = 0xd; - pll_lim->vco2.min_n = 0x4; - /* - * On nv30, 31, 36 (i.e. all cards with two stage PLLs with this - * table version (apart from nv35)), N2 is compared to - * maxN2 (0x46) and 10 * maxM2 (0x4), so set maxN2 to 0x28 and - * save a comparison - */ - pll_lim->vco2.max_n = 0x28; - if (cv == 0x30 || cv == 0x35) - /* only 5 bits available for N2 on nv30/35 */ - pll_lim->vco2.max_n = 0x1f; - pll_lim->vco2.min_m = 0x1; - pll_lim->vco2.max_m = 0x4; - pll_lim->max_log2p = 0x7; - pll_lim->max_usable_log2p = 0x6; - } else if (pll_lim_ver == 0x20 || pll_lim_ver == 0x21) { - uint16_t plloffs = bios->pll_limit_tbl_ptr + headerlen; - uint8_t *pll_rec; - int i; - - /* - * First entry is default match, if nothing better. warn if - * reg field nonzero - */ - if (ROM32(bios->data[plloffs])) - NV_WARN(dev, "Default PLL limit entry has non-zero " - "register field\n"); - - for (i = 1; i < entries; i++) - if (ROM32(bios->data[plloffs + recordlen * i]) == pll_lim->reg) { - pllindex = i; - break; - } - - if ((dev_priv->card_type >= NV_50) && (pllindex == 0)) { - NV_ERROR(dev, "Register 0x%08x not found in PLL " - "limits table", pll_lim->reg); - return -ENOENT; - } - - pll_rec = &bios->data[plloffs + recordlen * pllindex]; - - BIOSLOG(bios, "Loading PLL limits for reg 0x%08x\n", - pllindex ? pll_lim->reg : 0); - - /* - * Frequencies are stored in tables in MHz, kHz are more - * useful, so we convert. - */ - - /* What output frequencies can each VCO generate? */ - pll_lim->vco1.minfreq = ROM16(pll_rec[4]) * 1000; - pll_lim->vco1.maxfreq = ROM16(pll_rec[6]) * 1000; - pll_lim->vco2.minfreq = ROM16(pll_rec[8]) * 1000; - pll_lim->vco2.maxfreq = ROM16(pll_rec[10]) * 1000; - - /* What input frequencies they accept (past the m-divider)? */ - pll_lim->vco1.min_inputfreq = ROM16(pll_rec[12]) * 1000; - pll_lim->vco2.min_inputfreq = ROM16(pll_rec[14]) * 1000; - pll_lim->vco1.max_inputfreq = ROM16(pll_rec[16]) * 1000; - pll_lim->vco2.max_inputfreq = ROM16(pll_rec[18]) * 1000; - - /* What values are accepted as multiplier and divider? */ - pll_lim->vco1.min_n = pll_rec[20]; - pll_lim->vco1.max_n = pll_rec[21]; - pll_lim->vco1.min_m = pll_rec[22]; - pll_lim->vco1.max_m = pll_rec[23]; - pll_lim->vco2.min_n = pll_rec[24]; - pll_lim->vco2.max_n = pll_rec[25]; - pll_lim->vco2.min_m = pll_rec[26]; - pll_lim->vco2.max_m = pll_rec[27]; - - pll_lim->max_usable_log2p = pll_lim->max_log2p = pll_rec[29]; - if (pll_lim->max_log2p > 0x7) - /* pll decoding in nv_hw.c assumes never > 7 */ - NV_WARN(dev, "Max log2 P value greater than 7 (%d)\n", - pll_lim->max_log2p); - if (cv < 0x60) - pll_lim->max_usable_log2p = 0x6; - pll_lim->log2p_bias = pll_rec[30]; - - if (recordlen > 0x22) - pll_lim->refclk = ROM32(pll_rec[31]); - - if (recordlen > 0x23 && pll_rec[35]) - NV_WARN(dev, - "Bits set in PLL configuration byte (%x)\n", - pll_rec[35]); - - /* C51 special not seen elsewhere */ - if (cv == 0x51 && !pll_lim->refclk) { - uint32_t sel_clk = bios_rd32(bios, NV_PRAMDAC_SEL_CLK); - - if ((pll_lim->reg == NV_PRAMDAC_VPLL_COEFF && sel_clk & 0x20) || - (pll_lim->reg == NV_RAMDAC_VPLL2 && sel_clk & 0x80)) { - if (bios_idxprt_rd(bios, NV_CIO_CRX__COLOR, NV_CIO_CRE_CHIP_ID_INDEX) < 0xa3) - pll_lim->refclk = 200000; - else - pll_lim->refclk = 25000; - } - } - } else if (pll_lim_ver == 0x30) { /* ver 0x30 */ - uint8_t *entry = &bios->data[bios->pll_limit_tbl_ptr + headerlen]; - uint8_t *record = NULL; - int i; - - BIOSLOG(bios, "Loading PLL limits for register 0x%08x\n", - pll_lim->reg); - - for (i = 0; i < entries; i++, entry += recordlen) { - if (ROM32(entry[3]) == pll_lim->reg) { - record = &bios->data[ROM16(entry[1])]; - break; - } - } - - if (!record) { - NV_ERROR(dev, "Register 0x%08x not found in PLL " - "limits table", pll_lim->reg); - return -ENOENT; - } - - pll_lim->vco1.minfreq = ROM16(record[0]) * 1000; - pll_lim->vco1.maxfreq = ROM16(record[2]) * 1000; - pll_lim->vco2.minfreq = ROM16(record[4]) * 1000; - pll_lim->vco2.maxfreq = ROM16(record[6]) * 1000; - pll_lim->vco1.min_inputfreq = ROM16(record[8]) * 1000; - pll_lim->vco2.min_inputfreq = ROM16(record[10]) * 1000; - pll_lim->vco1.max_inputfreq = ROM16(record[12]) * 1000; - pll_lim->vco2.max_inputfreq = ROM16(record[14]) * 1000; - pll_lim->vco1.min_n = record[16]; - pll_lim->vco1.max_n = record[17]; - pll_lim->vco1.min_m = record[18]; - pll_lim->vco1.max_m = record[19]; - pll_lim->vco2.min_n = record[20]; - pll_lim->vco2.max_n = record[21]; - pll_lim->vco2.min_m = record[22]; - pll_lim->vco2.max_m = record[23]; - pll_lim->max_usable_log2p = pll_lim->max_log2p = record[25]; - pll_lim->log2p_bias = record[27]; - pll_lim->refclk = ROM32(record[28]); - } else if (pll_lim_ver) { /* ver 0x40 */ - uint8_t *entry = &bios->data[bios->pll_limit_tbl_ptr + headerlen]; - uint8_t *record = NULL; - int i; - - BIOSLOG(bios, "Loading PLL limits for register 0x%08x\n", - pll_lim->reg); - - for (i = 0; i < entries; i++, entry += recordlen) { - if (ROM32(entry[3]) == pll_lim->reg) { - record = &bios->data[ROM16(entry[1])]; - break; - } - } - - if (!record) { - NV_ERROR(dev, "Register 0x%08x not found in PLL " - "limits table", pll_lim->reg); - return -ENOENT; - } - - pll_lim->vco1.minfreq = ROM16(record[0]) * 1000; - pll_lim->vco1.maxfreq = ROM16(record[2]) * 1000; - pll_lim->vco1.min_inputfreq = ROM16(record[4]) * 1000; - pll_lim->vco1.max_inputfreq = ROM16(record[6]) * 1000; - pll_lim->vco1.min_m = record[8]; - pll_lim->vco1.max_m = record[9]; - pll_lim->vco1.min_n = record[10]; - pll_lim->vco1.max_n = record[11]; - pll_lim->min_p = record[12]; - pll_lim->max_p = record[13]; - pll_lim->refclk = ROM16(entry[9]) * 1000; - } - - /* - * By now any valid limit table ought to have set a max frequency for - * vco1, so if it's zero it's either a pre limit table bios, or one - * with an empty limit table (seen on nv18) - */ - if (!pll_lim->vco1.maxfreq) { - pll_lim->vco1.minfreq = bios->fminvco; - pll_lim->vco1.maxfreq = bios->fmaxvco; - pll_lim->vco1.min_inputfreq = 0; - pll_lim->vco1.max_inputfreq = INT_MAX; - pll_lim->vco1.min_n = 0x1; - pll_lim->vco1.max_n = 0xff; - pll_lim->vco1.min_m = 0x1; - if (crystal_straps == 0) { - /* nv05 does this, nv11 doesn't, nv10 unknown */ - if (cv < 0x11) - pll_lim->vco1.min_m = 0x7; - pll_lim->vco1.max_m = 0xd; - } else { - if (cv < 0x11) - pll_lim->vco1.min_m = 0x8; - pll_lim->vco1.max_m = 0xe; - } - if (cv < 0x17 || cv == 0x1a || cv == 0x20) - pll_lim->max_log2p = 4; - else - pll_lim->max_log2p = 5; - pll_lim->max_usable_log2p = pll_lim->max_log2p; - } - - if (!pll_lim->refclk) - switch (crystal_straps) { - case 0: - pll_lim->refclk = 13500; - break; - case (1 << 6): - pll_lim->refclk = 14318; - break; - case (1 << 22): - pll_lim->refclk = 27000; - break; - case (1 << 22 | 1 << 6): - pll_lim->refclk = 25000; - break; - } - - NV_DEBUG(dev, "pll.vco1.minfreq: %d\n", pll_lim->vco1.minfreq); - NV_DEBUG(dev, "pll.vco1.maxfreq: %d\n", pll_lim->vco1.maxfreq); - NV_DEBUG(dev, "pll.vco1.min_inputfreq: %d\n", pll_lim->vco1.min_inputfreq); - NV_DEBUG(dev, "pll.vco1.max_inputfreq: %d\n", pll_lim->vco1.max_inputfreq); - NV_DEBUG(dev, "pll.vco1.min_n: %d\n", pll_lim->vco1.min_n); - NV_DEBUG(dev, "pll.vco1.max_n: %d\n", pll_lim->vco1.max_n); - NV_DEBUG(dev, "pll.vco1.min_m: %d\n", pll_lim->vco1.min_m); - NV_DEBUG(dev, "pll.vco1.max_m: %d\n", pll_lim->vco1.max_m); - if (pll_lim->vco2.maxfreq) { - NV_DEBUG(dev, "pll.vco2.minfreq: %d\n", pll_lim->vco2.minfreq); - NV_DEBUG(dev, "pll.vco2.maxfreq: %d\n", pll_lim->vco2.maxfreq); - NV_DEBUG(dev, "pll.vco2.min_inputfreq: %d\n", pll_lim->vco2.min_inputfreq); - NV_DEBUG(dev, "pll.vco2.max_inputfreq: %d\n", pll_lim->vco2.max_inputfreq); - NV_DEBUG(dev, "pll.vco2.min_n: %d\n", pll_lim->vco2.min_n); - NV_DEBUG(dev, "pll.vco2.max_n: %d\n", pll_lim->vco2.max_n); - NV_DEBUG(dev, "pll.vco2.min_m: %d\n", pll_lim->vco2.min_m); - NV_DEBUG(dev, "pll.vco2.max_m: %d\n", pll_lim->vco2.max_m); - } - if (!pll_lim->max_p) { - NV_DEBUG(dev, "pll.max_log2p: %d\n", pll_lim->max_log2p); - NV_DEBUG(dev, "pll.log2p_bias: %d\n", pll_lim->log2p_bias); - } else { - NV_DEBUG(dev, "pll.min_p: %d\n", pll_lim->min_p); - NV_DEBUG(dev, "pll.max_p: %d\n", pll_lim->max_p); - } - NV_DEBUG(dev, "pll.refclk: %d\n", pll_lim->refclk); - - return 0; -} - static void parse_bios_version(struct drm_device *dev, struct nvbios *bios, uint16_t offset) { /* diff --git a/drivers/gpu/drm/nouveau/nouveau_bios.h b/drivers/gpu/drm/nouveau/nouveau_bios.h index 52fce11e9d26..e9bb14ec8c3b 100644 --- a/drivers/gpu/drm/nouveau/nouveau_bios.h +++ b/drivers/gpu/drm/nouveau/nouveau_bios.h @@ -144,58 +144,6 @@ enum LVDS_script { LVDS_PANEL_OFF }; -/* these match types in pll limits table version 0x40, - * nouveau uses them on all chipsets internally where a - * specific pll needs to be referenced, but the exact - * register isn't known. - */ -enum pll_types { - PLL_CORE = 0x01, - PLL_SHADER = 0x02, - PLL_UNK03 = 0x03, - PLL_MEMORY = 0x04, - PLL_VDEC = 0x05, - PLL_UNK40 = 0x40, - PLL_UNK41 = 0x41, - PLL_UNK42 = 0x42, - PLL_VPLL0 = 0x80, - PLL_VPLL1 = 0x81, - PLL_MAX = 0xff -}; - -struct pll_lims { - u32 reg; - - struct { - int minfreq; - int maxfreq; - int min_inputfreq; - int max_inputfreq; - - uint8_t min_m; - uint8_t max_m; - uint8_t min_n; - uint8_t max_n; - } vco1, vco2; - - uint8_t max_log2p; - /* - * for most pre nv50 cards setting a log2P of 7 (the common max_log2p - * value) is no different to 6 (at least for vplls) so allowing the MNP - * calc to use 7 causes the generated clock to be out by a factor of 2. - * however, max_log2p cannot be fixed-up during parsing as the - * unmodified max_log2p value is still needed for setting mplls, hence - * an additional max_usable_log2p member - */ - uint8_t max_usable_log2p; - uint8_t log2p_bias; - - uint8_t min_p; - uint8_t max_p; - - int refclk; -}; - struct nvbios { struct drm_device *dev; enum { diff --git a/drivers/gpu/drm/nouveau/nouveau_calc.c b/drivers/gpu/drm/nouveau/nouveau_calc.c index dad96cce5e39..5b487655d6b8 100644 --- a/drivers/gpu/drm/nouveau/nouveau_calc.c +++ b/drivers/gpu/drm/nouveau/nouveau_calc.c @@ -260,219 +260,3 @@ nouveau_calc_arb(struct drm_device *dev, int vclk, int bpp, int *burst, int *lwm } else nv20_update_arb(burst, lwm); } - -static int -getMNP_single(struct drm_device *dev, struct pll_lims *pll_lim, int clk, - struct nouveau_pll_vals *bestpv) -{ - /* Find M, N and P for a single stage PLL - * - * Note that some bioses (NV3x) have lookup tables of precomputed MNP - * values, but we're too lazy to use those atm - * - * "clk" parameter in kHz - * returns calculated clock - */ - struct drm_nouveau_private *dev_priv = dev->dev_private; - int cv = dev_priv->vbios.chip_version; - int minvco = pll_lim->vco1.minfreq, maxvco = pll_lim->vco1.maxfreq; - int minM = pll_lim->vco1.min_m, maxM = pll_lim->vco1.max_m; - int minN = pll_lim->vco1.min_n, maxN = pll_lim->vco1.max_n; - int minU = pll_lim->vco1.min_inputfreq; - int maxU = pll_lim->vco1.max_inputfreq; - int minP = pll_lim->max_p ? pll_lim->min_p : 0; - int maxP = pll_lim->max_p ? pll_lim->max_p : pll_lim->max_usable_log2p; - int crystal = pll_lim->refclk; - int M, N, thisP, P; - int clkP, calcclk; - int delta, bestdelta = INT_MAX; - int bestclk = 0; - - /* this division verified for nv20, nv18, nv28 (Haiku), and nv34 */ - /* possibly correlated with introduction of 27MHz crystal */ - if (dev_priv->card_type < NV_50) { - if (cv < 0x17 || cv == 0x1a || cv == 0x20) { - if (clk > 250000) - maxM = 6; - if (clk > 340000) - maxM = 2; - } else if (cv < 0x40) { - if (clk > 150000) - maxM = 6; - if (clk > 200000) - maxM = 4; - if (clk > 340000) - maxM = 2; - } - } - - P = pll_lim->max_p ? maxP : (1 << maxP); - if ((clk * P) < minvco) { - minvco = clk * maxP; - maxvco = minvco * 2; - } - - if (clk + clk/200 > maxvco) /* +0.5% */ - maxvco = clk + clk/200; - - /* NV34 goes maxlog2P->0, NV20 goes 0->maxlog2P */ - for (thisP = minP; thisP <= maxP; thisP++) { - P = pll_lim->max_p ? thisP : (1 << thisP); - clkP = clk * P; - - if (clkP < minvco) - continue; - if (clkP > maxvco) - return bestclk; - - for (M = minM; M <= maxM; M++) { - if (crystal/M < minU) - return bestclk; - if (crystal/M > maxU) - continue; - - /* add crystal/2 to round better */ - N = (clkP * M + crystal/2) / crystal; - - if (N < minN) - continue; - if (N > maxN) - break; - - /* more rounding additions */ - calcclk = ((N * crystal + P/2) / P + M/2) / M; - delta = abs(calcclk - clk); - /* we do an exhaustive search rather than terminating - * on an optimality condition... - */ - if (delta < bestdelta) { - bestdelta = delta; - bestclk = calcclk; - bestpv->N1 = N; - bestpv->M1 = M; - bestpv->log2P = thisP; - if (delta == 0) /* except this one */ - return bestclk; - } - } - } - - return bestclk; -} - -static int -getMNP_double(struct drm_device *dev, struct pll_lims *pll_lim, int clk, - struct nouveau_pll_vals *bestpv) -{ - /* Find M, N and P for a two stage PLL - * - * Note that some bioses (NV30+) have lookup tables of precomputed MNP - * values, but we're too lazy to use those atm - * - * "clk" parameter in kHz - * returns calculated clock - */ - struct drm_nouveau_private *dev_priv = dev->dev_private; - int chip_version = dev_priv->vbios.chip_version; - int minvco1 = pll_lim->vco1.minfreq, maxvco1 = pll_lim->vco1.maxfreq; - int minvco2 = pll_lim->vco2.minfreq, maxvco2 = pll_lim->vco2.maxfreq; - int minU1 = pll_lim->vco1.min_inputfreq, minU2 = pll_lim->vco2.min_inputfreq; - int maxU1 = pll_lim->vco1.max_inputfreq, maxU2 = pll_lim->vco2.max_inputfreq; - int minM1 = pll_lim->vco1.min_m, maxM1 = pll_lim->vco1.max_m; - int minN1 = pll_lim->vco1.min_n, maxN1 = pll_lim->vco1.max_n; - int minM2 = pll_lim->vco2.min_m, maxM2 = pll_lim->vco2.max_m; - int minN2 = pll_lim->vco2.min_n, maxN2 = pll_lim->vco2.max_n; - int maxlog2P = pll_lim->max_usable_log2p; - int crystal = pll_lim->refclk; - bool fixedgain2 = (minM2 == maxM2 && minN2 == maxN2); - int M1, N1, M2, N2, log2P; - int clkP, calcclk1, calcclk2, calcclkout; - int delta, bestdelta = INT_MAX; - int bestclk = 0; - - int vco2 = (maxvco2 - maxvco2/200) / 2; - for (log2P = 0; clk && log2P < maxlog2P && clk <= (vco2 >> log2P); log2P++) - ; - clkP = clk << log2P; - - if (maxvco2 < clk + clk/200) /* +0.5% */ - maxvco2 = clk + clk/200; - - for (M1 = minM1; M1 <= maxM1; M1++) { - if (crystal/M1 < minU1) - return bestclk; - if (crystal/M1 > maxU1) - continue; - - for (N1 = minN1; N1 <= maxN1; N1++) { - calcclk1 = crystal * N1 / M1; - if (calcclk1 < minvco1) - continue; - if (calcclk1 > maxvco1) - break; - - for (M2 = minM2; M2 <= maxM2; M2++) { - if (calcclk1/M2 < minU2) - break; - if (calcclk1/M2 > maxU2) - continue; - - /* add calcclk1/2 to round better */ - N2 = (clkP * M2 + calcclk1/2) / calcclk1; - if (N2 < minN2) - continue; - if (N2 > maxN2) - break; - - if (!fixedgain2) { - if (chip_version < 0x60) - if (N2/M2 < 4 || N2/M2 > 10) - continue; - - calcclk2 = calcclk1 * N2 / M2; - if (calcclk2 < minvco2) - break; - if (calcclk2 > maxvco2) - continue; - } else - calcclk2 = calcclk1; - - calcclkout = calcclk2 >> log2P; - delta = abs(calcclkout - clk); - /* we do an exhaustive search rather than terminating - * on an optimality condition... - */ - if (delta < bestdelta) { - bestdelta = delta; - bestclk = calcclkout; - bestpv->N1 = N1; - bestpv->M1 = M1; - bestpv->N2 = N2; - bestpv->M2 = M2; - bestpv->log2P = log2P; - if (delta == 0) /* except this one */ - return bestclk; - } - } - } - } - - return bestclk; -} - -int -nouveau_calc_pll_mnp(struct drm_device *dev, struct pll_lims *pll_lim, int clk, - struct nouveau_pll_vals *pv) -{ - int outclk; - - if (!pll_lim->vco2.maxfreq) - outclk = getMNP_single(dev, pll_lim, clk, pv); - else - outclk = getMNP_double(dev, pll_lim, clk, pv); - - if (!outclk) - NV_ERROR(dev, "Could not find a compatible set of PLL values\n"); - - return outclk; -} diff --git a/drivers/gpu/drm/nouveau/nouveau_compat.c b/drivers/gpu/drm/nouveau/nouveau_compat.c index 76582b0a9df8..30431c820bb3 100644 --- a/drivers/gpu/drm/nouveau/nouveau_compat.c +++ b/drivers/gpu/drm/nouveau/nouveau_compat.c @@ -2,8 +2,10 @@ #include "nouveau_compat.h" #include +#include #include #include +#include void *nouveau_newpriv(struct drm_device *); @@ -180,3 +182,76 @@ auxch_wr(struct drm_device *dev, struct nouveau_i2c_port *port, { return nv_wraux(port, addr, data, size); } + +u32 +get_pll_register(struct drm_device *dev, u32 type) +{ + struct nouveau_drm *drm = nouveau_newpriv(dev); + struct nouveau_bios *bios = nouveau_bios(drm->device); + struct nvbios_pll info; + + if (nvbios_pll_parse(bios, type, &info)) + return 0; + return info.reg; +} + +int +get_pll_limits(struct drm_device *dev, u32 type, struct nvbios_pll *info) +{ + struct nouveau_drm *drm = nouveau_newpriv(dev); + struct nouveau_bios *bios = nouveau_bios(drm->device); + + return nvbios_pll_parse(bios, type, info); +} + +int +setPLL(struct drm_device *dev, u32 reg, u32 freq) +{ + struct nouveau_drm *drm = nouveau_newpriv(dev); + struct nouveau_clock *clk = nouveau_clock(drm->device); + int ret = -ENODEV; + + if (clk->pll_set) + ret = clk->pll_set(clk, reg, freq); + return ret; +} + + +int +nouveau_calc_pll_mnp(struct drm_device *dev, struct nvbios_pll *info, + int freq, struct nouveau_pll_vals *pv) +{ + struct nouveau_drm *drm = nouveau_newpriv(dev); + struct nouveau_clock *clk = nouveau_clock(drm->device); + int ret = 0; + + if (clk->pll_calc) + ret = clk->pll_calc(clk, info, freq, pv); + return ret; +} + +int +nouveau_hw_setpll(struct drm_device *dev, u32 reg1, + struct nouveau_pll_vals *pv) +{ + struct nouveau_drm *drm = nouveau_newpriv(dev); + struct nouveau_clock *clk = nouveau_clock(drm->device); + int ret = -ENODEV; + + if (clk->pll_prog) + ret = clk->pll_prog(clk, reg1, pv); + return ret; +} + +int nva3_pll_calc(struct nouveau_clock *, struct nvbios_pll *, u32 freq, + int *N, int *fN, int *M, int *P); + +int +nva3_calc_pll(struct drm_device *dev, struct nvbios_pll *info, u32 freq, + int *N, int *fN, int *M, int *P) +{ + struct nouveau_drm *drm = nouveau_newpriv(dev); + struct nouveau_clock *clk = nouveau_clock(drm->device); + + return nva3_pll_calc(clk, info, freq, N, fN, M, P); +} diff --git a/drivers/gpu/drm/nouveau/nouveau_compat.h b/drivers/gpu/drm/nouveau/nouveau_compat.h index 9b3298bfe4ed..8bf5bec81710 100644 --- a/drivers/gpu/drm/nouveau/nouveau_compat.h +++ b/drivers/gpu/drm/nouveau/nouveau_compat.h @@ -32,5 +32,17 @@ int nouveau_i2c_identify(struct drm_device *dev, const char *what, int auxch_rd(struct drm_device *, struct nouveau_i2c_port *, u32, u8 *, u8); int auxch_wr(struct drm_device *, struct nouveau_i2c_port *, u32, u8 *, u8); +struct nvbios_pll; +struct nouveau_pll_vals; + +u32 get_pll_register(struct drm_device *dev, u32 type); +int get_pll_limits(struct drm_device *, u32, struct nvbios_pll *); +int setPLL(struct drm_device *, u32 reg, u32 clk); + +int nouveau_calc_pll_mnp(struct drm_device *, struct nvbios_pll *, + int, struct nouveau_pll_vals *); +int nva3_calc_pll(struct drm_device *dev, struct nvbios_pll *info, u32 freq, + int *N, int *fN, int *M, int *P); +int nouveau_hw_setpll(struct drm_device *, u32, struct nouveau_pll_vals *); #endif diff --git a/drivers/gpu/drm/nouveau/nouveau_drv.h b/drivers/gpu/drm/nouveau/nouveau_drv.h index afe978702097..2b519b5cfac9 100644 --- a/drivers/gpu/drm/nouveau/nouveau_drv.h +++ b/drivers/gpu/drm/nouveau/nouveau_drv.h @@ -68,6 +68,9 @@ struct nouveau_grctx; struct nouveau_mem; #include +#include +#include "nouveau_compat.h" + #define MAX_NUM_DCB_ENTRIES 16 #define NOUVEAU_MAX_CHANNEL_NR 4096 @@ -549,24 +552,6 @@ struct nouveau_engine { struct nouveau_vram_engine vram; }; -struct nouveau_pll_vals { - union { - struct { -#ifdef __BIG_ENDIAN - uint8_t N1, M1, N2, M2; -#else - uint8_t M1, N1, M2, N2; -#endif - }; - struct { - uint16_t NM1, NM2; - } __attribute__((packed)); - }; - int log2P; - - int refclk; -}; - enum nv04_fp_display_regs { FP_DISPLAY_END, FP_TOTAL, @@ -1060,9 +1045,6 @@ extern void nouveau_bios_run_init_table(struct drm_device *, uint16_t table, extern void nouveau_bios_init_exec(struct drm_device *, uint16_t table); extern struct dcb_connector_table_entry * nouveau_bios_connector_entry(struct drm_device *, int index); -extern u32 get_pll_register(struct drm_device *, enum pll_types); -extern int get_pll_limits(struct drm_device *, uint32_t limit_match, - struct pll_lims *); extern int nouveau_bios_run_display_table(struct drm_device *, u16 id, int clk, struct dcb_entry *, int crtc); extern bool nouveau_bios_fp_mode(struct drm_device *, struct drm_display_mode *); @@ -1365,12 +1347,6 @@ int nouveau_display_dumb_map_offset(struct drm_file *, struct drm_device *, int nouveau_display_dumb_destroy(struct drm_file *, struct drm_device *, uint32_t handle); -/* nv50_calc.c */ -int nv50_calc_pll(struct drm_device *, struct pll_lims *, int clk, - int *N1, int *M1, int *N2, int *M2, int *P); -int nva3_calc_pll(struct drm_device *, struct pll_lims *, - int clk, int *N, int *fN, int *M, int *P); - #ifndef ioread32_native #ifdef __BIG_ENDIAN #define ioread16_native ioread16be @@ -1398,7 +1374,6 @@ static inline void nvchan_wr32(struct nouveau_channel *chan, } /* register access */ -#include "nouveau_compat.h" #define nv_rd08 _nv_rd08 #define nv_wr08 _nv_wr08 #define nv_rd32 _nv_rd32 diff --git a/drivers/gpu/drm/nouveau/nouveau_hw.c b/drivers/gpu/drm/nouveau/nouveau_hw.c index b87ad3bd7739..fdd667b70528 100644 --- a/drivers/gpu/drm/nouveau/nouveau_hw.c +++ b/drivers/gpu/drm/nouveau/nouveau_hw.c @@ -26,6 +26,8 @@ #include "nouveau_drv.h" #include "nouveau_hw.h" +#include + #define CHIPSET_NFORCE 0x01a0 #define CHIPSET_NFORCE2 0x01f0 @@ -122,270 +124,6 @@ NVBlankScreen(struct drm_device *dev, int head, bool blank) NVVgaSeqReset(dev, head, false); } -/* - * PLL setting - */ - -static int -powerctrl_1_shift(int chip_version, int reg) -{ - int shift = -4; - - if (chip_version < 0x17 || chip_version == 0x1a || chip_version == 0x20) - return shift; - - switch (reg) { - case NV_RAMDAC_VPLL2: - shift += 4; - case NV_PRAMDAC_VPLL_COEFF: - shift += 4; - case NV_PRAMDAC_MPLL_COEFF: - shift += 4; - case NV_PRAMDAC_NVPLL_COEFF: - shift += 4; - } - - /* - * the shift for vpll regs is only used for nv3x chips with a single - * stage pll - */ - if (shift > 4 && (chip_version < 0x32 || chip_version == 0x35 || - chip_version == 0x36 || chip_version >= 0x40)) - shift = -4; - - return shift; -} - -static void -setPLL_single(struct drm_device *dev, uint32_t reg, struct nouveau_pll_vals *pv) -{ - struct drm_nouveau_private *dev_priv = dev->dev_private; - int chip_version = dev_priv->vbios.chip_version; - uint32_t oldpll = NVReadRAMDAC(dev, 0, reg); - int oldN = (oldpll >> 8) & 0xff, oldM = oldpll & 0xff; - uint32_t pll = (oldpll & 0xfff80000) | pv->log2P << 16 | pv->NM1; - uint32_t saved_powerctrl_1 = 0; - int shift_powerctrl_1 = powerctrl_1_shift(chip_version, reg); - - if (oldpll == pll) - return; /* already set */ - - if (shift_powerctrl_1 >= 0) { - saved_powerctrl_1 = nvReadMC(dev, NV_PBUS_POWERCTRL_1); - nvWriteMC(dev, NV_PBUS_POWERCTRL_1, - (saved_powerctrl_1 & ~(0xf << shift_powerctrl_1)) | - 1 << shift_powerctrl_1); - } - - if (oldM && pv->M1 && (oldN / oldM < pv->N1 / pv->M1)) - /* upclock -- write new post divider first */ - NVWriteRAMDAC(dev, 0, reg, pv->log2P << 16 | (oldpll & 0xffff)); - else - /* downclock -- write new NM first */ - NVWriteRAMDAC(dev, 0, reg, (oldpll & 0xffff0000) | pv->NM1); - - if (chip_version < 0x17 && chip_version != 0x11) - /* wait a bit on older chips */ - msleep(64); - NVReadRAMDAC(dev, 0, reg); - - /* then write the other half as well */ - NVWriteRAMDAC(dev, 0, reg, pll); - - if (shift_powerctrl_1 >= 0) - nvWriteMC(dev, NV_PBUS_POWERCTRL_1, saved_powerctrl_1); -} - -static uint32_t -new_ramdac580(uint32_t reg1, bool ss, uint32_t ramdac580) -{ - bool head_a = (reg1 == NV_PRAMDAC_VPLL_COEFF); - - if (ss) /* single stage pll mode */ - ramdac580 |= head_a ? NV_RAMDAC_580_VPLL1_ACTIVE : - NV_RAMDAC_580_VPLL2_ACTIVE; - else - ramdac580 &= head_a ? ~NV_RAMDAC_580_VPLL1_ACTIVE : - ~NV_RAMDAC_580_VPLL2_ACTIVE; - - return ramdac580; -} - -static void -setPLL_double_highregs(struct drm_device *dev, uint32_t reg1, - struct nouveau_pll_vals *pv) -{ - struct drm_nouveau_private *dev_priv = dev->dev_private; - int chip_version = dev_priv->vbios.chip_version; - bool nv3035 = chip_version == 0x30 || chip_version == 0x35; - uint32_t reg2 = reg1 + ((reg1 == NV_RAMDAC_VPLL2) ? 0x5c : 0x70); - uint32_t oldpll1 = NVReadRAMDAC(dev, 0, reg1); - uint32_t oldpll2 = !nv3035 ? NVReadRAMDAC(dev, 0, reg2) : 0; - uint32_t pll1 = (oldpll1 & 0xfff80000) | pv->log2P << 16 | pv->NM1; - uint32_t pll2 = (oldpll2 & 0x7fff0000) | 1 << 31 | pv->NM2; - uint32_t oldramdac580 = 0, ramdac580 = 0; - bool single_stage = !pv->NM2 || pv->N2 == pv->M2; /* nv41+ only */ - uint32_t saved_powerctrl_1 = 0, savedc040 = 0; - int shift_powerctrl_1 = powerctrl_1_shift(chip_version, reg1); - - /* model specific additions to generic pll1 and pll2 set up above */ - if (nv3035) { - pll1 = (pll1 & 0xfcc7ffff) | (pv->N2 & 0x18) << 21 | - (pv->N2 & 0x7) << 19 | 8 << 4 | (pv->M2 & 7) << 4; - pll2 = 0; - } - if (chip_version > 0x40 && reg1 >= NV_PRAMDAC_VPLL_COEFF) { /* !nv40 */ - oldramdac580 = NVReadRAMDAC(dev, 0, NV_PRAMDAC_580); - ramdac580 = new_ramdac580(reg1, single_stage, oldramdac580); - if (oldramdac580 != ramdac580) - oldpll1 = ~0; /* force mismatch */ - if (single_stage) - /* magic value used by nvidia in single stage mode */ - pll2 |= 0x011f; - } - if (chip_version > 0x70) - /* magic bits set by the blob (but not the bios) on g71-73 */ - pll1 = (pll1 & 0x7fffffff) | (single_stage ? 0x4 : 0xc) << 28; - - if (oldpll1 == pll1 && oldpll2 == pll2) - return; /* already set */ - - if (shift_powerctrl_1 >= 0) { - saved_powerctrl_1 = nvReadMC(dev, NV_PBUS_POWERCTRL_1); - nvWriteMC(dev, NV_PBUS_POWERCTRL_1, - (saved_powerctrl_1 & ~(0xf << shift_powerctrl_1)) | - 1 << shift_powerctrl_1); - } - - if (chip_version >= 0x40) { - int shift_c040 = 14; - - switch (reg1) { - case NV_PRAMDAC_MPLL_COEFF: - shift_c040 += 2; - case NV_PRAMDAC_NVPLL_COEFF: - shift_c040 += 2; - case NV_RAMDAC_VPLL2: - shift_c040 += 2; - case NV_PRAMDAC_VPLL_COEFF: - shift_c040 += 2; - } - - savedc040 = nvReadMC(dev, 0xc040); - if (shift_c040 != 14) - nvWriteMC(dev, 0xc040, savedc040 & ~(3 << shift_c040)); - } - - if (oldramdac580 != ramdac580) - NVWriteRAMDAC(dev, 0, NV_PRAMDAC_580, ramdac580); - - if (!nv3035) - NVWriteRAMDAC(dev, 0, reg2, pll2); - NVWriteRAMDAC(dev, 0, reg1, pll1); - - if (shift_powerctrl_1 >= 0) - nvWriteMC(dev, NV_PBUS_POWERCTRL_1, saved_powerctrl_1); - if (chip_version >= 0x40) - nvWriteMC(dev, 0xc040, savedc040); -} - -static void -setPLL_double_lowregs(struct drm_device *dev, uint32_t NMNMreg, - struct nouveau_pll_vals *pv) -{ - /* When setting PLLs, there is a merry game of disabling and enabling - * various bits of hardware during the process. This function is a - * synthesis of six nv4x traces, nearly each card doing a subtly - * different thing. With luck all the necessary bits for each card are - * combined herein. Without luck it deviates from each card's formula - * so as to not work on any :) - */ - - uint32_t Preg = NMNMreg - 4; - bool mpll = Preg == 0x4020; - uint32_t oldPval = nvReadMC(dev, Preg); - uint32_t NMNM = pv->NM2 << 16 | pv->NM1; - uint32_t Pval = (oldPval & (mpll ? ~(0x77 << 16) : ~(7 << 16))) | - 0xc << 28 | pv->log2P << 16; - uint32_t saved4600 = 0; - /* some cards have different maskc040s */ - uint32_t maskc040 = ~(3 << 14), savedc040; - bool single_stage = !pv->NM2 || pv->N2 == pv->M2; - - if (nvReadMC(dev, NMNMreg) == NMNM && (oldPval & 0xc0070000) == Pval) - return; - - if (Preg == 0x4000) - maskc040 = ~0x333; - if (Preg == 0x4058) - maskc040 = ~(0xc << 24); - - if (mpll) { - struct pll_lims pll_lim; - uint8_t Pval2; - - if (get_pll_limits(dev, Preg, &pll_lim)) - return; - - Pval2 = pv->log2P + pll_lim.log2p_bias; - if (Pval2 > pll_lim.max_log2p) - Pval2 = pll_lim.max_log2p; - Pval |= 1 << 28 | Pval2 << 20; - - saved4600 = nvReadMC(dev, 0x4600); - nvWriteMC(dev, 0x4600, saved4600 | 8 << 28); - } - if (single_stage) - Pval |= mpll ? 1 << 12 : 1 << 8; - - nvWriteMC(dev, Preg, oldPval | 1 << 28); - nvWriteMC(dev, Preg, Pval & ~(4 << 28)); - if (mpll) { - Pval |= 8 << 20; - nvWriteMC(dev, 0x4020, Pval & ~(0xc << 28)); - nvWriteMC(dev, 0x4038, Pval & ~(0xc << 28)); - } - - savedc040 = nvReadMC(dev, 0xc040); - nvWriteMC(dev, 0xc040, savedc040 & maskc040); - - nvWriteMC(dev, NMNMreg, NMNM); - if (NMNMreg == 0x4024) - nvWriteMC(dev, 0x403c, NMNM); - - nvWriteMC(dev, Preg, Pval); - if (mpll) { - Pval &= ~(8 << 20); - nvWriteMC(dev, 0x4020, Pval); - nvWriteMC(dev, 0x4038, Pval); - nvWriteMC(dev, 0x4600, saved4600); - } - - nvWriteMC(dev, 0xc040, savedc040); - - if (mpll) { - nvWriteMC(dev, 0x4020, Pval & ~(1 << 28)); - nvWriteMC(dev, 0x4038, Pval & ~(1 << 28)); - } -} - -void -nouveau_hw_setpll(struct drm_device *dev, uint32_t reg1, - struct nouveau_pll_vals *pv) -{ - struct drm_nouveau_private *dev_priv = dev->dev_private; - int cv = dev_priv->vbios.chip_version; - - if (cv == 0x30 || cv == 0x31 || cv == 0x35 || cv == 0x36 || - cv >= 0x40) { - if (reg1 > 0x405c) - setPLL_double_highregs(dev, reg1, pv); - else - setPLL_double_lowregs(dev, reg1, pv); - } else - setPLL_single(dev, reg1, pv); -} - /* * PLL getting */ @@ -423,12 +161,12 @@ nouveau_hw_decode_pll(struct drm_device *dev, uint32_t reg1, uint32_t pll1, } int -nouveau_hw_get_pllvals(struct drm_device *dev, enum pll_types plltype, +nouveau_hw_get_pllvals(struct drm_device *dev, enum nvbios_pll_type plltype, struct nouveau_pll_vals *pllvals) { struct drm_nouveau_private *dev_priv = dev->dev_private; uint32_t reg1 = get_pll_register(dev, plltype), pll1, pll2 = 0; - struct pll_lims pll_lim; + struct nvbios_pll pll_lim; int ret; if (reg1 == 0) @@ -478,7 +216,7 @@ nouveau_hw_pllvals_to_clk(struct nouveau_pll_vals *pv) } int -nouveau_hw_get_clock(struct drm_device *dev, enum pll_types plltype) +nouveau_hw_get_clock(struct drm_device *dev, enum nvbios_pll_type plltype) { struct nouveau_pll_vals pllvals; int ret; @@ -517,9 +255,9 @@ nouveau_hw_fix_bad_vpll(struct drm_device *dev, int head) * when such a condition detected. only seen on nv11 to date */ - struct pll_lims pll_lim; + struct nvbios_pll pll_lim; struct nouveau_pll_vals pv; - enum pll_types pll = head ? PLL_VPLL1 : PLL_VPLL0; + enum nvbios_pll_type pll = head ? PLL_VPLL1 : PLL_VPLL0; if (get_pll_limits(dev, pll, &pll_lim)) return; @@ -527,7 +265,7 @@ nouveau_hw_fix_bad_vpll(struct drm_device *dev, int head) if (pv.M1 >= pll_lim.vco1.min_m && pv.M1 <= pll_lim.vco1.max_m && pv.N1 >= pll_lim.vco1.min_n && pv.N1 <= pll_lim.vco1.max_n && - pv.log2P <= pll_lim.max_log2p) + pv.log2P <= pll_lim.max_p) return; NV_WARN(dev, "VPLL %d outwith limits, attempting to fix\n", head + 1); @@ -535,7 +273,7 @@ nouveau_hw_fix_bad_vpll(struct drm_device *dev, int head) /* set lowest clock within static limits */ pv.M1 = pll_lim.vco1.max_m; pv.N1 = pll_lim.vco1.min_n; - pv.log2P = pll_lim.max_usable_log2p; + pv.log2P = pll_lim.max_p_usable; nouveau_hw_setpll(dev, pll_lim.reg, &pv); } diff --git a/drivers/gpu/drm/nouveau/nouveau_hw.h b/drivers/gpu/drm/nouveau/nouveau_hw.h index 2989090b9434..ff7f31c279d8 100644 --- a/drivers/gpu/drm/nouveau/nouveau_hw.h +++ b/drivers/gpu/drm/nouveau/nouveau_hw.h @@ -26,6 +26,8 @@ #include "drmP.h" #include "nouveau_drv.h" +#include + #define MASK(field) ( \ (0xffffffff >> (31 - ((1 ? field) - (0 ? field)))) << (0 ? field)) @@ -38,12 +40,10 @@ void NVWriteVgaGr(struct drm_device *, int head, uint8_t index, uint8_t value); uint8_t NVReadVgaGr(struct drm_device *, int head, uint8_t index); void NVSetOwner(struct drm_device *, int owner); void NVBlankScreen(struct drm_device *, int head, bool blank); -void nouveau_hw_setpll(struct drm_device *, uint32_t reg1, - struct nouveau_pll_vals *pv); -int nouveau_hw_get_pllvals(struct drm_device *, enum pll_types plltype, +int nouveau_hw_get_pllvals(struct drm_device *, enum nvbios_pll_type plltype, struct nouveau_pll_vals *pllvals); int nouveau_hw_pllvals_to_clk(struct nouveau_pll_vals *pllvals); -int nouveau_hw_get_clock(struct drm_device *, enum pll_types plltype); +int nouveau_hw_get_clock(struct drm_device *, enum nvbios_pll_type plltype); void nouveau_hw_save_vga_fonts(struct drm_device *, bool save); void nouveau_hw_save_state(struct drm_device *, int head, struct nv04_mode_state *state); @@ -55,8 +55,6 @@ void nouveau_hw_load_state_palette(struct drm_device *, int head, /* nouveau_calc.c */ extern void nouveau_calc_arb(struct drm_device *, int vclk, int bpp, int *burst, int *lwm); -extern int nouveau_calc_pll_mnp(struct drm_device *, struct pll_lims *pll_lim, - int clk, struct nouveau_pll_vals *pv); static inline uint32_t nvReadMC(struct drm_device *dev, uint32_t reg) diff --git a/drivers/gpu/drm/nouveau/nv04_crtc.c b/drivers/gpu/drm/nouveau/nv04_crtc.c index 43accc11102f..93ca09b90da5 100644 --- a/drivers/gpu/drm/nouveau/nv04_crtc.c +++ b/drivers/gpu/drm/nouveau/nv04_crtc.c @@ -108,7 +108,7 @@ static void nv_crtc_calc_state_ext(struct drm_crtc *crtc, struct drm_display_mod struct nv04_mode_state *state = &dev_priv->mode_reg; struct nv04_crtc_reg *regp = &state->crtc_reg[nv_crtc->index]; struct nouveau_pll_vals *pv = ®p->pllvals; - struct pll_lims pll_lim; + struct nvbios_pll pll_lim; if (get_pll_limits(dev, nv_crtc->index ? PLL_VPLL1 : PLL_VPLL0, &pll_lim)) return; @@ -126,7 +126,7 @@ static void nv_crtc_calc_state_ext(struct drm_crtc *crtc, struct drm_display_mod * has yet been observed in allowing the use a single stage pll on all * nv43 however. the behaviour of single stage use is untested on nv40 */ - if (dev_priv->chipset > 0x40 && dot_clock <= (pll_lim.vco1.maxfreq / 2)) + if (dev_priv->chipset > 0x40 && dot_clock <= (pll_lim.vco1.max_freq / 2)) memset(&pll_lim.vco2, 0, sizeof(pll_lim.vco2)); if (!nouveau_calc_pll_mnp(dev, &pll_lim, dot_clock, pv)) diff --git a/drivers/gpu/drm/nouveau/nv04_pm.c b/drivers/gpu/drm/nouveau/nv04_pm.c index 6e7589918fa9..4528d48dc52b 100644 --- a/drivers/gpu/drm/nouveau/nv04_pm.c +++ b/drivers/gpu/drm/nouveau/nv04_pm.c @@ -46,7 +46,7 @@ nv04_pm_clocks_get(struct drm_device *dev, struct nouveau_pm_level *perflvl) } struct nv04_pm_clock { - struct pll_lims pll; + struct nvbios_pll pll; struct nouveau_pll_vals calc; }; diff --git a/drivers/gpu/drm/nouveau/nv40_pm.c b/drivers/gpu/drm/nouveau/nv40_pm.c index 661d9cfd980d..d857525666ee 100644 --- a/drivers/gpu/drm/nouveau/nv40_pm.c +++ b/drivers/gpu/drm/nouveau/nv40_pm.c @@ -107,7 +107,7 @@ struct nv40_pm_state { }; static int -nv40_calc_pll(struct drm_device *dev, u32 reg, struct pll_lims *pll, +nv40_calc_pll(struct drm_device *dev, u32 reg, struct nvbios_pll *pll, u32 clk, int *N1, int *M1, int *N2, int *M2, int *log2P) { struct nouveau_pll_vals coef; @@ -117,8 +117,8 @@ nv40_calc_pll(struct drm_device *dev, u32 reg, struct pll_lims *pll, if (ret) return ret; - if (clk < pll->vco1.maxfreq) - pll->vco2.maxfreq = 0; + if (clk < pll->vco1.max_freq) + pll->vco2.max_freq = 0; ret = nouveau_calc_pll_mnp(dev, pll, clk, &coef); if (ret == 0) @@ -127,7 +127,7 @@ nv40_calc_pll(struct drm_device *dev, u32 reg, struct pll_lims *pll, *N1 = coef.N1; *M1 = coef.M1; if (N2 && M2) { - if (pll->vco2.maxfreq) { + if (pll->vco2.max_freq) { *N2 = coef.N2; *M2 = coef.M2; } else { @@ -143,7 +143,7 @@ void * nv40_pm_clocks_pre(struct drm_device *dev, struct nouveau_pm_level *perflvl) { struct nv40_pm_state *info; - struct pll_lims pll; + struct nvbios_pll pll; int N1, N2, M1, M2, log2P; int ret; @@ -191,7 +191,7 @@ nv40_pm_clocks_pre(struct drm_device *dev, struct nouveau_pm_level *perflvl) goto out; info->mpll_ctrl = 0x80000000 | (log2P << 16); - info->mpll_ctrl |= min2(pll.log2p_bias + log2P, pll.max_log2p) << 20; + info->mpll_ctrl |= min2(pll.bias_p + log2P, pll.max_p) << 20; if (N2 == M2) { info->mpll_ctrl |= 0x00000100; info->mpll_coef = (N1 << 8) | M1; diff --git a/drivers/gpu/drm/nouveau/nv50_calc.c b/drivers/gpu/drm/nouveau/nv50_calc.c deleted file mode 100644 index 8cf63a8b30cd..000000000000 --- a/drivers/gpu/drm/nouveau/nv50_calc.c +++ /dev/null @@ -1,97 +0,0 @@ -/* - * Copyright 2010 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 "drmP.h" -#include "nouveau_drv.h" -#include "nouveau_hw.h" - -int -nv50_calc_pll(struct drm_device *dev, struct pll_lims *pll, int clk, - int *N1, int *M1, int *N2, int *M2, int *P) -{ - struct nouveau_pll_vals pll_vals; - int ret; - - ret = nouveau_calc_pll_mnp(dev, pll, clk, &pll_vals); - if (ret <= 0) - return ret; - - *N1 = pll_vals.N1; - *M1 = pll_vals.M1; - *N2 = pll_vals.N2; - *M2 = pll_vals.M2; - *P = pll_vals.log2P; - return ret; -} - -int -nva3_calc_pll(struct drm_device *dev, struct pll_lims *pll, int clk, - int *pN, int *pfN, int *pM, int *P) -{ - u32 best_err = ~0, err; - int M, lM, hM, N, fN; - - *P = pll->vco1.maxfreq / clk; - if (*P > pll->max_p) - *P = pll->max_p; - if (*P < pll->min_p) - *P = pll->min_p; - - lM = (pll->refclk + pll->vco1.max_inputfreq) / pll->vco1.max_inputfreq; - lM = max(lM, (int)pll->vco1.min_m); - hM = (pll->refclk + pll->vco1.min_inputfreq) / pll->vco1.min_inputfreq; - hM = min(hM, (int)pll->vco1.max_m); - - for (M = lM; M <= hM; M++) { - u32 tmp = clk * *P * M; - N = tmp / pll->refclk; - fN = tmp % pll->refclk; - if (!pfN && fN >= pll->refclk / 2) - N++; - - if (N < pll->vco1.min_n) - continue; - if (N > pll->vco1.max_n) - break; - - err = abs(clk - (pll->refclk * N / M / *P)); - if (err < best_err) { - best_err = err; - *pN = N; - *pM = M; - } - - if (pfN) { - *pfN = (((fN << 13) / pll->refclk) - 4096) & 0xffff; - return clk; - } - } - - if (unlikely(best_err == ~0)) { - NV_ERROR(dev, "unable to find matching pll values\n"); - return -EINVAL; - } - - return pll->refclk * *pN / *pM / *P; -} diff --git a/drivers/gpu/drm/nouveau/nv50_crtc.c b/drivers/gpu/drm/nouveau/nv50_crtc.c index 22cebd5dd694..40042c1bbc6e 100644 --- a/drivers/gpu/drm/nouveau/nv50_crtc.c +++ b/drivers/gpu/drm/nouveau/nv50_crtc.c @@ -329,55 +329,7 @@ nv50_crtc_set_scale(struct nouveau_crtc *nv_crtc, bool update) int nv50_crtc_set_clock(struct drm_device *dev, int head, int pclk) { - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct pll_lims pll; - uint32_t reg1, reg2; - int ret, N1, M1, N2, M2, P; - - ret = get_pll_limits(dev, PLL_VPLL0 + head, &pll); - if (ret) - return ret; - - if (pll.vco2.maxfreq) { - ret = nv50_calc_pll(dev, &pll, pclk, &N1, &M1, &N2, &M2, &P); - if (ret <= 0) - return 0; - - NV_DEBUG(dev, "pclk %d out %d NM1 %d %d NM2 %d %d P %d\n", - pclk, ret, N1, M1, N2, M2, P); - - reg1 = nv_rd32(dev, pll.reg + 4) & 0xff00ff00; - reg2 = nv_rd32(dev, pll.reg + 8) & 0x8000ff00; - nv_wr32(dev, pll.reg + 0, 0x10000611); - nv_wr32(dev, pll.reg + 4, reg1 | (M1 << 16) | N1); - nv_wr32(dev, pll.reg + 8, reg2 | (P << 28) | (M2 << 16) | N2); - } else - if (dev_priv->chipset < NV_C0) { - ret = nva3_calc_pll(dev, &pll, pclk, &N1, &N2, &M1, &P); - if (ret <= 0) - return 0; - - NV_DEBUG(dev, "pclk %d out %d N %d fN 0x%04x M %d P %d\n", - pclk, ret, N1, N2, M1, P); - - reg1 = nv_rd32(dev, pll.reg + 4) & 0xffc00000; - nv_wr32(dev, pll.reg + 0, 0x50000610); - nv_wr32(dev, pll.reg + 4, reg1 | (P << 16) | (M1 << 8) | N1); - nv_wr32(dev, pll.reg + 8, N2); - } else { - ret = nva3_calc_pll(dev, &pll, pclk, &N1, &N2, &M1, &P); - if (ret <= 0) - return 0; - - NV_DEBUG(dev, "pclk %d out %d N %d fN 0x%04x M %d P %d\n", - pclk, ret, N1, N2, M1, P); - - nv_mask(dev, pll.reg + 0x0c, 0x00000000, 0x00000100); - nv_wr32(dev, pll.reg + 0x04, (P << 16) | (N1 << 8) | M1); - nv_wr32(dev, pll.reg + 0x10, N2 << 16); - } - - return 0; + return setPLL(dev, PLL_VPLL0 + head, pclk); } static void diff --git a/drivers/gpu/drm/nouveau/nv50_pm.c b/drivers/gpu/drm/nouveau/nv50_pm.c index be5704fd4a86..378ca8ca9d6a 100644 --- a/drivers/gpu/drm/nouveau/nv50_pm.c +++ b/drivers/gpu/drm/nouveau/nv50_pm.c @@ -363,7 +363,7 @@ struct nv50_pm_state { }; static u32 -calc_pll(struct drm_device *dev, u32 reg, struct pll_lims *pll, +calc_pll(struct drm_device *dev, u32 reg, struct nvbios_pll *pll, u32 clk, int *N1, int *M1, int *log2P) { struct nouveau_pll_vals coef; @@ -373,7 +373,7 @@ calc_pll(struct drm_device *dev, u32 reg, struct pll_lims *pll, if (ret) return 0; - pll->vco2.maxfreq = 0; + pll->vco2.max_freq = 0; pll->refclk = read_pll_ref(dev, reg); if (!pll->refclk) return 0; @@ -542,7 +542,7 @@ calc_mclk(struct drm_device *dev, struct nouveau_pm_level *perflvl, .priv = info }; struct hwsq_ucode *hwsq = &info->mclk_hwsq; - struct pll_lims pll; + struct nvbios_pll pll; int N, M, P; int ret; @@ -550,14 +550,14 @@ calc_mclk(struct drm_device *dev, struct nouveau_pm_level *perflvl, info->mctrl = nv_rd32(dev, 0x004008); info->mctrl &= ~0x81ff0200; if (clk_same(perflvl->memory, read_clk(dev, clk_src_href))) { - info->mctrl |= 0x00000200 | (pll.log2p_bias << 19); + info->mctrl |= 0x00000200 | (pll.bias_p << 19); } else { ret = calc_pll(dev, 0x4008, &pll, perflvl->memory, &N, &M, &P); if (ret == 0) return -EINVAL; info->mctrl |= 0x80000000 | (P << 22) | (P << 16); - info->mctrl |= pll.log2p_bias << 19; + info->mctrl |= pll.bias_p << 19; info->mcoef = (N << 8) | M; } @@ -590,7 +590,7 @@ nv50_pm_clocks_pre(struct drm_device *dev, struct nouveau_pm_level *perflvl) struct drm_nouveau_private *dev_priv = dev->dev_private; struct nv50_pm_state *info; struct hwsq_ucode *hwsq; - struct pll_lims pll; + struct nvbios_pll pll; u32 out, mast, divs, ctrl; int clk, ret = -EINVAL; int N, M, P1, P2; diff --git a/drivers/gpu/drm/nouveau/nva3_pm.c b/drivers/gpu/drm/nouveau/nva3_pm.c index ff0fafbfe621..847c616de12f 100644 --- a/drivers/gpu/drm/nouveau/nva3_pm.c +++ b/drivers/gpu/drm/nouveau/nva3_pm.c @@ -111,7 +111,7 @@ struct creg { static int calc_clk(struct drm_device *dev, int clk, u32 pll, u32 khz, struct creg *reg) { - struct pll_lims limits; + struct nvbios_pll limits; u32 oclk, sclk, sdiv; int P, N, M, diff; int ret; diff --git a/drivers/gpu/drm/nouveau/nvc0_pm.c b/drivers/gpu/drm/nouveau/nvc0_pm.c index 81b649864fa1..4a21a7264c3c 100644 --- a/drivers/gpu/drm/nouveau/nvc0_pm.c +++ b/drivers/gpu/drm/nouveau/nvc0_pm.c @@ -212,7 +212,7 @@ calc_src(struct drm_device *dev, int clk, u32 freq, u32 *dsrc, u32 *ddiv) static u32 calc_pll(struct drm_device *dev, int clk, u32 freq, u32 *coef) { - struct pll_lims limits; + struct nvbios_pll limits; int N, M, P, ret; ret = get_pll_limits(dev, 0x137000 + (clk * 0x20), &limits); @@ -308,7 +308,7 @@ calc_clk(struct drm_device *dev, int clk, struct nvc0_pm_clock *info, u32 freq) static int calc_mem(struct drm_device *dev, struct nvc0_pm_clock *info, u32 freq) { - struct pll_lims pll; + struct nvbios_pll pll; int N, M, P, ret; u32 ctrl; -- cgit v1.2.3 From 861d21074bbb141b0cc165a61c11f571571cda12 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Wed, 11 Jul 2012 19:05:01 +1000 Subject: drm/nouveau/fb: merge fb/vram and port to subdev interfaces Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/Makefile | 5 +- drivers/gpu/drm/nouveau/core/engine/fifo/nv40.c | 2 +- drivers/gpu/drm/nouveau/core/engine/graph/nv10.c | 4 +- drivers/gpu/drm/nouveau/core/engine/graph/nv20.c | 2 +- drivers/gpu/drm/nouveau/core/engine/graph/nv40.c | 5 +- drivers/gpu/drm/nouveau/core/engine/mpeg/nv31.c | 7 +- drivers/gpu/drm/nouveau/core/include/subdev/fb.h | 137 ++++++++ drivers/gpu/drm/nouveau/core/include/subdev/ltcg.h | 33 ++ drivers/gpu/drm/nouveau/core/include/subdev/vm.h | 5 +- drivers/gpu/drm/nouveau/core/subdev/device/nv04.c | 3 + drivers/gpu/drm/nouveau/core/subdev/device/nv10.c | 9 + drivers/gpu/drm/nouveau/core/subdev/device/nv20.c | 5 + drivers/gpu/drm/nouveau/core/subdev/device/nv30.c | 6 + drivers/gpu/drm/nouveau/core/subdev/device/nv40.c | 17 + drivers/gpu/drm/nouveau/core/subdev/device/nv50.c | 15 + drivers/gpu/drm/nouveau/core/subdev/device/nvc0.c | 18 + drivers/gpu/drm/nouveau/core/subdev/device/nve0.c | 6 + drivers/gpu/drm/nouveau/core/subdev/fb/base.c | 130 +++++++ drivers/gpu/drm/nouveau/core/subdev/fb/nv04.c | 139 ++++++-- drivers/gpu/drm/nouveau/core/subdev/fb/nv10.c | 186 +++++----- drivers/gpu/drm/nouveau/core/subdev/fb/nv20.c | 208 ++++++----- drivers/gpu/drm/nouveau/core/subdev/fb/nv30.c | 114 +++--- drivers/gpu/drm/nouveau/core/subdev/fb/nv40.c | 261 ++++++++------ drivers/gpu/drm/nouveau/core/subdev/fb/nv50.c | 384 ++++++++++++++++----- drivers/gpu/drm/nouveau/core/subdev/fb/nv50_vram.c | 243 ------------- drivers/gpu/drm/nouveau/core/subdev/fb/nvc0.c | 252 ++++++++++---- drivers/gpu/drm/nouveau/core/subdev/fb/nvc0_vram.c | 167 --------- drivers/gpu/drm/nouveau/core/subdev/instmem/nv50.c | 10 +- drivers/gpu/drm/nouveau/core/subdev/ltcg/nvc0.c | 91 +++++ drivers/gpu/drm/nouveau/core/subdev/mc/nvc0.c | 1 + drivers/gpu/drm/nouveau/core/subdev/vm/nv50.c | 6 +- drivers/gpu/drm/nouveau/nouveau_bo.c | 2 +- drivers/gpu/drm/nouveau/nouveau_compat.c | 106 ++++++ drivers/gpu/drm/nouveau/nouveau_compat.h | 20 ++ drivers/gpu/drm/nouveau/nouveau_debugfs.c | 3 +- drivers/gpu/drm/nouveau/nouveau_drv.c | 1 - drivers/gpu/drm/nouveau/nouveau_drv.h | 146 +------- drivers/gpu/drm/nouveau/nouveau_fb.h | 4 +- drivers/gpu/drm/nouveau/nouveau_fbcon.c | 4 +- drivers/gpu/drm/nouveau/nouveau_gem.c | 2 +- drivers/gpu/drm/nouveau/nouveau_mem.c | 90 +---- drivers/gpu/drm/nouveau/nouveau_state.c | 87 +---- drivers/gpu/drm/nouveau/nouveau_util.c | 43 +-- drivers/gpu/drm/nouveau/nouveau_util.h | 16 +- drivers/gpu/drm/nouveau/nv50_evo.c | 14 +- drivers/gpu/drm/nouveau/nv50_pm.c | 5 +- drivers/gpu/drm/nouveau/nva3_pm.c | 6 +- drivers/gpu/drm/nouveau/nvc0_pm.c | 10 +- drivers/gpu/drm/nouveau/nvd0_display.c | 6 +- 49 files changed, 1691 insertions(+), 1345 deletions(-) create mode 100644 drivers/gpu/drm/nouveau/core/include/subdev/fb.h create mode 100644 drivers/gpu/drm/nouveau/core/include/subdev/ltcg.h create mode 100644 drivers/gpu/drm/nouveau/core/subdev/fb/base.c delete mode 100644 drivers/gpu/drm/nouveau/core/subdev/fb/nv50_vram.c delete mode 100644 drivers/gpu/drm/nouveau/core/subdev/fb/nvc0_vram.c create mode 100644 drivers/gpu/drm/nouveau/core/subdev/ltcg/nvc0.c (limited to 'drivers/gpu/drm/nouveau/nva3_pm.c') diff --git a/drivers/gpu/drm/nouveau/Makefile b/drivers/gpu/drm/nouveau/Makefile index 0615e954d238..5e18a53e2c0c 100644 --- a/drivers/gpu/drm/nouveau/Makefile +++ b/drivers/gpu/drm/nouveau/Makefile @@ -8,6 +8,7 @@ ccflags-y += -I$(src) nouveau-y := core/core/client.o nouveau-y += core/core/engine.o +nouveau-y += core/core/enum.o nouveau-y += core/core/handle.o nouveau-y += core/core/mm.o nouveau-y += core/core/namedb.o @@ -50,6 +51,7 @@ nouveau-y += core/subdev/devinit/nv10.o nouveau-y += core/subdev/devinit/nv1a.o nouveau-y += core/subdev/devinit/nv20.o nouveau-y += core/subdev/devinit/nv50.o +nouveau-y += core/subdev/fb/base.o nouveau-y += core/subdev/fb/nv04.o nouveau-y += core/subdev/fb/nv10.o nouveau-y += core/subdev/fb/nv20.o @@ -57,8 +59,6 @@ nouveau-y += core/subdev/fb/nv30.o nouveau-y += core/subdev/fb/nv40.o nouveau-y += core/subdev/fb/nv50.o nouveau-y += core/subdev/fb/nvc0.o -nouveau-y += core/subdev/fb/nv50_vram.o -nouveau-y += core/subdev/fb/nvc0_vram.o nouveau-y += core/subdev/gpio/base.o nouveau-y += core/subdev/gpio/nv10.o nouveau-y += core/subdev/gpio/nv50.o @@ -69,6 +69,7 @@ nouveau-y += core/subdev/i2c/bit.o nouveau-y += core/subdev/instmem/nv04.o nouveau-y += core/subdev/instmem/nv50.o nouveau-y += core/subdev/instmem/nvc0.o +nouveau-y += core/subdev/ltcg/nvc0.o nouveau-y += core/subdev/mc/base.o nouveau-y += core/subdev/mc/nv04.o nouveau-y += core/subdev/mc/nv44.o diff --git a/drivers/gpu/drm/nouveau/core/engine/fifo/nv40.c b/drivers/gpu/drm/nouveau/core/engine/fifo/nv40.c index 3079f080d40e..23ae4591b7bd 100644 --- a/drivers/gpu/drm/nouveau/core/engine/fifo/nv40.c +++ b/drivers/gpu/drm/nouveau/core/engine/fifo/nv40.c @@ -163,7 +163,7 @@ nv40_fifo_init(struct drm_device *dev, int engine) break; default: nv_wr32(dev, 0x002230, 0x00000000); - nv_wr32(dev, 0x002220, ((dev_priv->vram_size - 512 * 1024 + + nv_wr32(dev, 0x002220, ((nvfb_vram_size(dev) - 512 * 1024 + dev_priv->ramfc->pinst) >> 16) | 0x00030000); break; diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/nv10.c b/drivers/gpu/drm/nouveau/core/engine/graph/nv10.c index 19e303b423af..d006658e6468 100644 --- a/drivers/gpu/drm/nouveau/core/engine/graph/nv10.c +++ b/drivers/gpu/drm/nouveau/core/engine/graph/nv10.c @@ -895,9 +895,7 @@ nv10_graph_context_del(struct nouveau_channel *chan, int engine) static void nv10_graph_set_tile_region(struct drm_device *dev, int i) { - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_tile_reg *tile = &dev_priv->tile.reg[i]; - + struct nouveau_fb_tile *tile = nvfb_tile(dev, i); nv_wr32(dev, NV10_PGRAPH_TLIMIT(i), tile->limit); nv_wr32(dev, NV10_PGRAPH_TSIZE(i), tile->pitch); nv_wr32(dev, NV10_PGRAPH_TILE(i), tile->addr); diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/nv20.c b/drivers/gpu/drm/nouveau/core/engine/graph/nv20.c index 718ecf761823..dd31156e3029 100644 --- a/drivers/gpu/drm/nouveau/core/engine/graph/nv20.c +++ b/drivers/gpu/drm/nouveau/core/engine/graph/nv20.c @@ -472,7 +472,7 @@ static void nv20_graph_set_tile_region(struct drm_device *dev, int i) { struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_tile_reg *tile = &dev_priv->tile.reg[i]; + struct nouveau_fb_tile *tile = nvfb_tile(dev, i); nv_wr32(dev, NV20_PGRAPH_TLIMIT(i), tile->limit); nv_wr32(dev, NV20_PGRAPH_TSIZE(i), tile->pitch); diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/nv40.c b/drivers/gpu/drm/nouveau/core/engine/graph/nv40.c index 4ad9759f821e..ab3af6d15381 100644 --- a/drivers/gpu/drm/nouveau/core/engine/graph/nv40.c +++ b/drivers/gpu/drm/nouveau/core/engine/graph/nv40.c @@ -125,7 +125,7 @@ static void nv40_graph_set_tile_region(struct drm_device *dev, int i) { struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_tile_reg *tile = &dev_priv->tile.reg[i]; + struct nouveau_fb_tile *tile = nvfb_tile(dev, i); switch (dev_priv->chipset) { case 0x40: @@ -178,7 +178,6 @@ nv40_graph_init(struct drm_device *dev, int engine) { struct nv40_graph_engine *pgraph = nv_engine(dev, engine); struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_fb_engine *pfb = &dev_priv->engine.fb; uint32_t vramsz; int i, j; @@ -280,7 +279,7 @@ nv40_graph_init(struct drm_device *dev, int engine) } /* Turn all the tiling regions off. */ - for (i = 0; i < pfb->num_tiles; i++) + for (i = 0; i < nvfb_tile_nr(dev); i++) nv40_graph_set_tile_region(dev, i); /* begin RAM config */ diff --git a/drivers/gpu/drm/nouveau/core/engine/mpeg/nv31.c b/drivers/gpu/drm/nouveau/core/engine/mpeg/nv31.c index 4a14a6763dac..eb5455fed1bf 100644 --- a/drivers/gpu/drm/nouveau/core/engine/mpeg/nv31.c +++ b/drivers/gpu/drm/nouveau/core/engine/mpeg/nv31.c @@ -128,7 +128,6 @@ nv31_mpeg_object_new(struct nouveau_channel *chan, int engine, static int nv31_mpeg_init(struct drm_device *dev, int engine) { - struct drm_nouveau_private *dev_priv = dev->dev_private; struct nv31_mpeg_engine *pmpeg = nv_engine(dev, engine); int i; @@ -138,7 +137,7 @@ nv31_mpeg_init(struct drm_device *dev, int engine) nv_wr32(dev, 0x00b0e0, 0x00000020); /* nvidia: rd 0x01, wr 0x20 */ nv_wr32(dev, 0x00b0e8, 0x00000020); /* nvidia: rd 0x01, wr 0x20 */ - for (i = 0; i < dev_priv->engine.fb.num_tiles; i++) + for (i = 0; i < nvfb_tile_nr(dev); i++) pmpeg->base.set_tile_region(dev, i); /* PMPEG init */ @@ -235,9 +234,7 @@ nv31_mpeg_isr_chid(struct drm_device *dev, u32 inst) static void nv31_vpe_set_tile_region(struct drm_device *dev, int i) { - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_tile_reg *tile = &dev_priv->tile.reg[i]; - + struct nouveau_fb_tile *tile = nvfb_tile(dev, i); nv_wr32(dev, 0x00b008 + (i * 0x10), tile->pitch); nv_wr32(dev, 0x00b004 + (i * 0x10), tile->limit); nv_wr32(dev, 0x00b000 + (i * 0x10), tile->addr); diff --git a/drivers/gpu/drm/nouveau/core/include/subdev/fb.h b/drivers/gpu/drm/nouveau/core/include/subdev/fb.h new file mode 100644 index 000000000000..91dbdc16ac94 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/include/subdev/fb.h @@ -0,0 +1,137 @@ +#ifndef __NOUVEAU_FB_H__ +#define __NOUVEAU_FB_H__ + +#ifndef XXX_THIS_IS_A_HACK +#include +#include +#endif +#include +#include + +/* memory type/access flags, do not match hardware values */ +#define NV_MEM_ACCESS_RO 1 +#define NV_MEM_ACCESS_WO 2 +#define NV_MEM_ACCESS_RW (NV_MEM_ACCESS_RO | NV_MEM_ACCESS_WO) +#define NV_MEM_ACCESS_SYS 4 +#define NV_MEM_ACCESS_VM 8 +#define NV_MEM_ACCESS_NOSNOOP 16 + +#define NV_MEM_TARGET_VRAM 0 +#define NV_MEM_TARGET_PCI 1 +#define NV_MEM_TARGET_PCI_NOSNOOP 2 +#define NV_MEM_TARGET_VM 3 +#define NV_MEM_TARGET_GART 4 + +#define NV_MEM_TYPE_VM 0x7f +#define NV_MEM_COMP_VM 0x03 + +struct nouveau_mem { + struct drm_device *dev; + + struct nouveau_vma bar_vma; + struct nouveau_vma vma[2]; + u8 page_shift; + + struct nouveau_mm_node *tag; + struct list_head regions; + dma_addr_t *pages; + u32 memtype; + u64 offset; + u64 size; + struct sg_table *sg; +}; + +struct nouveau_fb_tile { + struct nouveau_mm_node *tag; + u32 addr; + u32 limit; + u32 pitch; + u32 zcomp; +}; + +#ifndef XXX_THIS_IS_A_HACK +struct nouveau_fb { + struct nouveau_subdev base; + + bool (*memtype_valid)(struct nouveau_fb *, u32 memtype); + + struct { + enum { + NV_MEM_TYPE_UNKNOWN = 0, + NV_MEM_TYPE_STOLEN, + NV_MEM_TYPE_SGRAM, + NV_MEM_TYPE_SDRAM, + NV_MEM_TYPE_DDR1, + NV_MEM_TYPE_DDR2, + NV_MEM_TYPE_DDR3, + NV_MEM_TYPE_GDDR2, + NV_MEM_TYPE_GDDR3, + NV_MEM_TYPE_GDDR4, + NV_MEM_TYPE_GDDR5 + } type; + u64 stolen; + u64 size; + int ranks; + + int (*get)(struct nouveau_fb *, u64 size, u32 align, + u32 size_nc, u32 type, struct nouveau_mem **); + void (*put)(struct nouveau_fb *, struct nouveau_mem **); + } ram; + + struct nouveau_mm vram; + struct nouveau_mm tags; + + struct { + struct nouveau_fb_tile region[16]; + int regions; + void (*init)(struct nouveau_fb *, int i, u32 addr, u32 size, + u32 pitch, u32 flags, struct nouveau_fb_tile *); + void (*fini)(struct nouveau_fb *, int i, + struct nouveau_fb_tile *); + void (*prog)(struct nouveau_fb *, int i, + struct nouveau_fb_tile *); + } tile; +}; + +static inline struct nouveau_fb * +nouveau_fb(void *obj) +{ + return (void *)nv_device(obj)->subdev[NVDEV_SUBDEV_FB]; +} + +#define nouveau_fb_create(p,e,c,d) \ + nouveau_subdev_create((p), (e), (c), 0, "PFB", "fb", (d)) +int nouveau_fb_created(struct nouveau_fb *); +void nouveau_fb_destroy(struct nouveau_fb *); +int nouveau_fb_init(struct nouveau_fb *); +#define nouveau_fb_fini(p,s) \ + nouveau_subdev_fini(&(p)->base, (s)) + +void _nouveau_fb_dtor(struct nouveau_object *); +int _nouveau_fb_init(struct nouveau_object *); +#define _nouveau_fb_fini _nouveau_subdev_fini + +extern struct nouveau_oclass nv04_fb_oclass; +extern struct nouveau_oclass nv10_fb_oclass; +extern struct nouveau_oclass nv20_fb_oclass; +extern struct nouveau_oclass nv30_fb_oclass; +extern struct nouveau_oclass nv40_fb_oclass; +extern struct nouveau_oclass nv50_fb_oclass; +extern struct nouveau_oclass nvc0_fb_oclass; + +struct nouveau_bios; +int nouveau_fb_bios_memtype(struct nouveau_bios *); + +bool nv04_fb_memtype_valid(struct nouveau_fb *, u32 memtype); + +void nv10_fb_tile_prog(struct nouveau_fb *, int, struct nouveau_fb_tile *); + +void nv30_fb_tile_init(struct nouveau_fb *, int i, u32 addr, u32 size, + u32 pitch, u32 flags, struct nouveau_fb_tile *); +void nv30_fb_tile_fini(struct nouveau_fb *, int i, struct nouveau_fb_tile *); + +void nv50_fb_vram_del(struct nouveau_fb *, struct nouveau_mem **); +void nv50_fb_trap(struct nouveau_fb *, int display); +#endif + +#endif diff --git a/drivers/gpu/drm/nouveau/core/include/subdev/ltcg.h b/drivers/gpu/drm/nouveau/core/include/subdev/ltcg.h new file mode 100644 index 000000000000..f351f63bc654 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/include/subdev/ltcg.h @@ -0,0 +1,33 @@ +#ifndef __NOUVEAU_LTCG_H__ +#define __NOUVEAU_LTCG_H__ + +#include +#include + +struct nouveau_ltcg { + struct nouveau_subdev base; +}; + +static inline struct nouveau_ltcg * +nouveau_ltcg(void *obj) +{ + return (void *)nv_device(obj)->subdev[NVDEV_SUBDEV_LTCG]; +} + +#define nouveau_ltcg_create(p,e,o,d) \ + nouveau_subdev_create_((p), (e), (o), 0, "PLTCG", "level2", \ + sizeof(**d), (void **)d) +#define nouveau_ltcg_destroy(p) \ + nouveau_subdev_destroy(&(p)->base) +#define nouveau_ltcg_init(p) \ + nouveau_subdev_init(&(p)->base) +#define nouveau_ltcg_fini(p,s) \ + nouveau_subdev_fini(&(p)->base, (s)) + +#define _nouveau_ltcg_dtor _nouveau_subdev_dtor +#define _nouveau_ltcg_init _nouveau_subdev_init +#define _nouveau_ltcg_fini _nouveau_subdev_fini + +extern struct nouveau_oclass nvc0_ltcg_oclass; + +#endif diff --git a/drivers/gpu/drm/nouveau/core/include/subdev/vm.h b/drivers/gpu/drm/nouveau/core/include/subdev/vm.h index 7c1fc2114fec..6d3764b416f4 100644 --- a/drivers/gpu/drm/nouveau/core/include/subdev/vm.h +++ b/drivers/gpu/drm/nouveau/core/include/subdev/vm.h @@ -25,11 +25,10 @@ #ifndef __NOUVEAU_VM_H__ #define __NOUVEAU_VM_H__ -#include "drmP.h" - -#include "nouveau_drv.h" #include +struct nouveau_mem; + struct nouveau_vm_pgt { struct nouveau_gpuobj *obj[2]; u32 refcount[2]; diff --git a/drivers/gpu/drm/nouveau/core/subdev/device/nv04.c b/drivers/gpu/drm/nouveau/core/subdev/device/nv04.c index aa43bd5c2374..66b7156281c9 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/device/nv04.c +++ b/drivers/gpu/drm/nouveau/core/subdev/device/nv04.c @@ -29,6 +29,7 @@ #include #include #include +#include int nv04_identify(struct nouveau_device *device) @@ -41,6 +42,7 @@ nv04_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv04_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; + device->oclass[NVDEV_SUBDEV_FB ] = &nv04_fb_oclass; break; case 0x05: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -49,6 +51,7 @@ nv04_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv05_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; + device->oclass[NVDEV_SUBDEV_FB ] = &nv04_fb_oclass; break; default: nv_fatal(device, "unknown RIVA chipset\n"); diff --git a/drivers/gpu/drm/nouveau/core/subdev/device/nv10.c b/drivers/gpu/drm/nouveau/core/subdev/device/nv10.c index 1926c33fb6f8..cf81479725ad 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/device/nv10.c +++ b/drivers/gpu/drm/nouveau/core/subdev/device/nv10.c @@ -30,6 +30,7 @@ #include #include #include +#include int nv10_identify(struct nouveau_device *device) @@ -43,6 +44,7 @@ nv10_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv10_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; + device->oclass[NVDEV_SUBDEV_FB ] = &nv10_fb_oclass; break; case 0x15: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -52,6 +54,7 @@ nv10_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv10_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; + device->oclass[NVDEV_SUBDEV_FB ] = &nv10_fb_oclass; break; case 0x16: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -61,6 +64,7 @@ nv10_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv10_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; + device->oclass[NVDEV_SUBDEV_FB ] = &nv10_fb_oclass; break; case 0x1a: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -70,6 +74,7 @@ nv10_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; + device->oclass[NVDEV_SUBDEV_FB ] = &nv10_fb_oclass; break; case 0x11: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -79,6 +84,7 @@ nv10_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv10_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; + device->oclass[NVDEV_SUBDEV_FB ] = &nv10_fb_oclass; break; case 0x17: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -88,6 +94,7 @@ nv10_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv10_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; + device->oclass[NVDEV_SUBDEV_FB ] = &nv10_fb_oclass; break; case 0x1f: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -97,6 +104,7 @@ nv10_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; + device->oclass[NVDEV_SUBDEV_FB ] = &nv10_fb_oclass; break; case 0x18: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -106,6 +114,7 @@ nv10_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv10_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; + device->oclass[NVDEV_SUBDEV_FB ] = &nv10_fb_oclass; break; default: nv_fatal(device, "unknown Celsius chipset\n"); diff --git a/drivers/gpu/drm/nouveau/core/subdev/device/nv20.c b/drivers/gpu/drm/nouveau/core/subdev/device/nv20.c index 88729c308565..e97280cd43b0 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/device/nv20.c +++ b/drivers/gpu/drm/nouveau/core/subdev/device/nv20.c @@ -30,6 +30,7 @@ #include #include #include +#include int nv20_identify(struct nouveau_device *device) @@ -43,6 +44,7 @@ nv20_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv20_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; + device->oclass[NVDEV_SUBDEV_FB ] = &nv20_fb_oclass; break; case 0x25: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -52,6 +54,7 @@ nv20_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv20_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; + device->oclass[NVDEV_SUBDEV_FB ] = &nv20_fb_oclass; break; case 0x28: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -61,6 +64,7 @@ nv20_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv20_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; + device->oclass[NVDEV_SUBDEV_FB ] = &nv20_fb_oclass; break; case 0x2a: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -70,6 +74,7 @@ nv20_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv20_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; + device->oclass[NVDEV_SUBDEV_FB ] = &nv20_fb_oclass; break; default: nv_fatal(device, "unknown Kelvin chipset\n"); diff --git a/drivers/gpu/drm/nouveau/core/subdev/device/nv30.c b/drivers/gpu/drm/nouveau/core/subdev/device/nv30.c index 4feea8804a78..ddd3ab6cb733 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/device/nv30.c +++ b/drivers/gpu/drm/nouveau/core/subdev/device/nv30.c @@ -30,6 +30,7 @@ #include #include #include +#include int nv30_identify(struct nouveau_device *device) @@ -43,6 +44,7 @@ nv30_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv20_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; + device->oclass[NVDEV_SUBDEV_FB ] = &nv30_fb_oclass; break; case 0x35: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -52,6 +54,7 @@ nv30_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv20_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; + device->oclass[NVDEV_SUBDEV_FB ] = &nv30_fb_oclass; break; case 0x31: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -61,6 +64,7 @@ nv30_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv20_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; + device->oclass[NVDEV_SUBDEV_FB ] = &nv30_fb_oclass; break; case 0x36: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -70,6 +74,7 @@ nv30_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv20_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; + device->oclass[NVDEV_SUBDEV_FB ] = &nv30_fb_oclass; break; case 0x34: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -79,6 +84,7 @@ nv30_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv10_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; + device->oclass[NVDEV_SUBDEV_FB ] = &nv30_fb_oclass; break; default: nv_fatal(device, "unknown Rankine chipset\n"); diff --git a/drivers/gpu/drm/nouveau/core/subdev/device/nv40.c b/drivers/gpu/drm/nouveau/core/subdev/device/nv40.c index 8f683613788d..c7ea921e0309 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/device/nv40.c +++ b/drivers/gpu/drm/nouveau/core/subdev/device/nv40.c @@ -30,6 +30,7 @@ #include #include #include +#include int nv40_identify(struct nouveau_device *device) @@ -43,6 +44,7 @@ nv40_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; + device->oclass[NVDEV_SUBDEV_FB ] = &nv40_fb_oclass; break; case 0x41: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -52,6 +54,7 @@ nv40_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; + device->oclass[NVDEV_SUBDEV_FB ] = &nv40_fb_oclass; break; case 0x42: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -61,6 +64,7 @@ nv40_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; + device->oclass[NVDEV_SUBDEV_FB ] = &nv40_fb_oclass; break; case 0x43: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -70,6 +74,7 @@ nv40_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; + device->oclass[NVDEV_SUBDEV_FB ] = &nv40_fb_oclass; break; case 0x45: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -79,6 +84,7 @@ nv40_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; + device->oclass[NVDEV_SUBDEV_FB ] = &nv40_fb_oclass; break; case 0x47: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -88,6 +94,7 @@ nv40_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; + device->oclass[NVDEV_SUBDEV_FB ] = &nv40_fb_oclass; break; case 0x49: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -97,6 +104,7 @@ nv40_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; + device->oclass[NVDEV_SUBDEV_FB ] = &nv40_fb_oclass; break; case 0x4b: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -106,6 +114,7 @@ nv40_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; + device->oclass[NVDEV_SUBDEV_FB ] = &nv40_fb_oclass; break; case 0x44: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -115,6 +124,7 @@ nv40_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv44_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; + device->oclass[NVDEV_SUBDEV_FB ] = &nv40_fb_oclass; break; case 0x46: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -124,6 +134,7 @@ nv40_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv44_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; + device->oclass[NVDEV_SUBDEV_FB ] = &nv40_fb_oclass; break; case 0x4a: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -133,6 +144,7 @@ nv40_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv44_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; + device->oclass[NVDEV_SUBDEV_FB ] = &nv40_fb_oclass; break; case 0x4c: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -142,6 +154,7 @@ nv40_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv44_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; + device->oclass[NVDEV_SUBDEV_FB ] = &nv40_fb_oclass; break; case 0x4e: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -151,6 +164,7 @@ nv40_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv44_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; + device->oclass[NVDEV_SUBDEV_FB ] = &nv40_fb_oclass; break; case 0x63: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -160,6 +174,7 @@ nv40_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv44_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; + device->oclass[NVDEV_SUBDEV_FB ] = &nv40_fb_oclass; break; case 0x67: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -169,6 +184,7 @@ nv40_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv44_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; + device->oclass[NVDEV_SUBDEV_FB ] = &nv40_fb_oclass; break; case 0x68: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -178,6 +194,7 @@ nv40_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv44_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; + device->oclass[NVDEV_SUBDEV_FB ] = &nv40_fb_oclass; break; default: nv_fatal(device, "unknown Curie chipset\n"); diff --git a/drivers/gpu/drm/nouveau/core/subdev/device/nv50.c b/drivers/gpu/drm/nouveau/core/subdev/device/nv50.c index e844525d5694..e60cdf26ebf9 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/device/nv50.c +++ b/drivers/gpu/drm/nouveau/core/subdev/device/nv50.c @@ -30,6 +30,7 @@ #include #include #include +#include int nv50_identify(struct nouveau_device *device) @@ -43,6 +44,7 @@ nv50_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv50_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; + device->oclass[NVDEV_SUBDEV_FB ] = &nv50_fb_oclass; break; case 0x84: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -52,6 +54,7 @@ nv50_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv50_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; + device->oclass[NVDEV_SUBDEV_FB ] = &nv50_fb_oclass; break; case 0x86: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -61,6 +64,7 @@ nv50_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv50_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; + device->oclass[NVDEV_SUBDEV_FB ] = &nv50_fb_oclass; break; case 0x92: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -70,6 +74,7 @@ nv50_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv50_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; + device->oclass[NVDEV_SUBDEV_FB ] = &nv50_fb_oclass; break; case 0x94: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -79,6 +84,7 @@ nv50_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv50_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; + device->oclass[NVDEV_SUBDEV_FB ] = &nv50_fb_oclass; break; case 0x96: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -88,6 +94,7 @@ nv50_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv50_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; + device->oclass[NVDEV_SUBDEV_FB ] = &nv50_fb_oclass; break; case 0x98: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -97,6 +104,7 @@ nv50_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv98_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; + device->oclass[NVDEV_SUBDEV_FB ] = &nv50_fb_oclass; break; case 0xa0: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -106,6 +114,7 @@ nv50_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv98_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; + device->oclass[NVDEV_SUBDEV_FB ] = &nv50_fb_oclass; break; case 0xaa: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -115,6 +124,7 @@ nv50_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv98_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; + device->oclass[NVDEV_SUBDEV_FB ] = &nv50_fb_oclass; break; case 0xac: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -124,6 +134,7 @@ nv50_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv98_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; + device->oclass[NVDEV_SUBDEV_FB ] = &nv50_fb_oclass; break; case 0xa3: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -133,6 +144,7 @@ nv50_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv98_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; + device->oclass[NVDEV_SUBDEV_FB ] = &nv50_fb_oclass; break; case 0xa5: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -142,6 +154,7 @@ nv50_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv98_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; + device->oclass[NVDEV_SUBDEV_FB ] = &nv50_fb_oclass; break; case 0xa8: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -151,6 +164,7 @@ nv50_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv98_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; + device->oclass[NVDEV_SUBDEV_FB ] = &nv50_fb_oclass; break; case 0xaf: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -160,6 +174,7 @@ nv50_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv98_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; + device->oclass[NVDEV_SUBDEV_FB ] = &nv50_fb_oclass; break; default: nv_fatal(device, "unknown Tesla chipset\n"); diff --git a/drivers/gpu/drm/nouveau/core/subdev/device/nvc0.c b/drivers/gpu/drm/nouveau/core/subdev/device/nvc0.c index 56d1950c9b77..8de67307eea7 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/device/nvc0.c +++ b/drivers/gpu/drm/nouveau/core/subdev/device/nvc0.c @@ -30,6 +30,8 @@ #include #include #include +#include +#include int nvc0_identify(struct nouveau_device *device) @@ -43,6 +45,8 @@ nvc0_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nvc0_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; + device->oclass[NVDEV_SUBDEV_FB ] = &nvc0_fb_oclass; + device->oclass[NVDEV_SUBDEV_LTCG ] = &nvc0_ltcg_oclass; break; case 0xc4: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -52,6 +56,8 @@ nvc0_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nvc0_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; + device->oclass[NVDEV_SUBDEV_FB ] = &nvc0_fb_oclass; + device->oclass[NVDEV_SUBDEV_LTCG ] = &nvc0_ltcg_oclass; break; case 0xc3: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -61,6 +67,8 @@ nvc0_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nvc0_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; + device->oclass[NVDEV_SUBDEV_FB ] = &nvc0_fb_oclass; + device->oclass[NVDEV_SUBDEV_LTCG ] = &nvc0_ltcg_oclass; break; case 0xce: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -70,6 +78,8 @@ nvc0_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nvc0_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; + device->oclass[NVDEV_SUBDEV_FB ] = &nvc0_fb_oclass; + device->oclass[NVDEV_SUBDEV_LTCG ] = &nvc0_ltcg_oclass; break; case 0xcf: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -79,6 +89,8 @@ nvc0_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nvc0_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; + device->oclass[NVDEV_SUBDEV_FB ] = &nvc0_fb_oclass; + device->oclass[NVDEV_SUBDEV_LTCG ] = &nvc0_ltcg_oclass; break; case 0xc1: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -88,6 +100,8 @@ nvc0_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nvc0_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; + device->oclass[NVDEV_SUBDEV_FB ] = &nvc0_fb_oclass; + device->oclass[NVDEV_SUBDEV_LTCG ] = &nvc0_ltcg_oclass; break; case 0xc8: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -97,6 +111,8 @@ nvc0_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nvc0_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; + device->oclass[NVDEV_SUBDEV_FB ] = &nvc0_fb_oclass; + device->oclass[NVDEV_SUBDEV_LTCG ] = &nvc0_ltcg_oclass; break; case 0xd9: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -106,6 +122,8 @@ nvc0_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nvc0_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; + device->oclass[NVDEV_SUBDEV_FB ] = &nvc0_fb_oclass; + device->oclass[NVDEV_SUBDEV_LTCG ] = &nvc0_ltcg_oclass; break; default: nv_fatal(device, "unknown Fermi chipset\n"); diff --git a/drivers/gpu/drm/nouveau/core/subdev/device/nve0.c b/drivers/gpu/drm/nouveau/core/subdev/device/nve0.c index ab5e05291465..919a10280d7e 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/device/nve0.c +++ b/drivers/gpu/drm/nouveau/core/subdev/device/nve0.c @@ -30,6 +30,8 @@ #include #include #include +#include +#include int nve0_identify(struct nouveau_device *device) @@ -43,6 +45,8 @@ nve0_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nvc0_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; + device->oclass[NVDEV_SUBDEV_FB ] = &nvc0_fb_oclass; + device->oclass[NVDEV_SUBDEV_LTCG ] = &nvc0_ltcg_oclass; break; case 0xe7: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -52,6 +56,8 @@ nve0_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nvc0_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; + device->oclass[NVDEV_SUBDEV_FB ] = &nvc0_fb_oclass; + device->oclass[NVDEV_SUBDEV_LTCG ] = &nvc0_ltcg_oclass; break; default: nv_fatal(device, "unknown Kepler chipset\n"); diff --git a/drivers/gpu/drm/nouveau/core/subdev/fb/base.c b/drivers/gpu/drm/nouveau/core/subdev/fb/base.c new file mode 100644 index 000000000000..f0086de8af31 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/subdev/fb/base.c @@ -0,0 +1,130 @@ +/* + * Copyright 2012 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 "subdev/fb.h" +#include "subdev/bios.h" +#include "subdev/bios/bit.h" + +int +nouveau_fb_bios_memtype(struct nouveau_bios *bios) +{ + struct bit_entry M; + u8 ramcfg; + + ramcfg = (nv_rd32(bios, 0x101000) & 0x0000003c) >> 2; + if (!bit_entry(bios, 'M', &M) && M.version == 2 && M.length >= 5) { + u16 table = nv_ro16(bios, M.offset + 3); + u8 version = nv_ro08(bios, table + 0); + u8 header = nv_ro08(bios, table + 1); + u8 record = nv_ro08(bios, table + 2); + u8 entries = nv_ro08(bios, table + 3); + if (table && version == 0x10 && ramcfg < entries) { + u16 entry = table + header + (ramcfg * record); + switch (nv_ro08(bios, entry) & 0x0f) { + case 0: return NV_MEM_TYPE_DDR2; + case 1: return NV_MEM_TYPE_DDR3; + case 2: return NV_MEM_TYPE_GDDR3; + case 3: return NV_MEM_TYPE_GDDR5; + default: + break; + } + + } + } + + return NV_MEM_TYPE_UNKNOWN; +} + +int +nouveau_fb_init(struct nouveau_fb *pfb) +{ + int ret, i; + + ret = nouveau_subdev_init(&pfb->base); + if (ret) + return ret; + + for (i = 0; i < pfb->tile.regions; i++) + pfb->tile.prog(pfb, i, &pfb->tile.region[i]); + + return 0; +} + +int +_nouveau_fb_init(struct nouveau_object *object) +{ + struct nouveau_fb *pfb = (void *)object; + return nouveau_fb_init(pfb); +} + +void +nouveau_fb_destroy(struct nouveau_fb *pfb) +{ + int i; + + for (i = 0; i < pfb->tile.regions; i++) + pfb->tile.fini(pfb, i, &pfb->tile.region[i]); + + if (pfb->tags.block_size) + nouveau_mm_fini(&pfb->tags); + + if (pfb->vram.block_size) + nouveau_mm_fini(&pfb->vram); + + nouveau_subdev_destroy(&pfb->base); +} + +void +_nouveau_fb_dtor(struct nouveau_object *object) +{ + struct nouveau_fb *pfb = (void *)object; + nouveau_fb_destroy(pfb); +} + +int +nouveau_fb_created(struct nouveau_fb *pfb) +{ + static const char *name[] = { + [NV_MEM_TYPE_UNKNOWN] = "unknown", + [NV_MEM_TYPE_STOLEN ] = "stolen system memory", + [NV_MEM_TYPE_SGRAM ] = "SGRAM", + [NV_MEM_TYPE_SDRAM ] = "SDRAM", + [NV_MEM_TYPE_DDR1 ] = "DDR1", + [NV_MEM_TYPE_DDR2 ] = "DDR2", + [NV_MEM_TYPE_DDR3 ] = "DDR3", + [NV_MEM_TYPE_GDDR2 ] = "GDDR2", + [NV_MEM_TYPE_GDDR3 ] = "GDDR3", + [NV_MEM_TYPE_GDDR4 ] = "GDDR4", + [NV_MEM_TYPE_GDDR5 ] = "GDDR5", + }; + + if (pfb->ram.size == 0) { + nv_fatal(pfb, "no vram detected!!\n"); + return -ERANGE; + } + + nv_info(pfb, "RAM type: %s\n", name[pfb->ram.type]); + nv_info(pfb, "RAM size: %d MiB\n", (int)(pfb->ram.size >> 20)); + return 0; +} diff --git a/drivers/gpu/drm/nouveau/core/subdev/fb/nv04.c b/drivers/gpu/drm/nouveau/core/subdev/fb/nv04.c index eef48440fbec..eb06836b69f7 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/fb/nv04.c +++ b/drivers/gpu/drm/nouveau/core/subdev/fb/nv04.c @@ -1,55 +1,130 @@ -#include "drmP.h" -#include "drm.h" -#include "nouveau_drv.h" -#include +/* + * Copyright 2012 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 + */ -int -nv04_fb_vram_init(struct drm_device *dev) +#include + +#define NV04_PFB_BOOT_0 0x00100000 +# define NV04_PFB_BOOT_0_RAM_AMOUNT 0x00000003 +# define NV04_PFB_BOOT_0_RAM_AMOUNT_32MB 0x00000000 +# define NV04_PFB_BOOT_0_RAM_AMOUNT_4MB 0x00000001 +# define NV04_PFB_BOOT_0_RAM_AMOUNT_8MB 0x00000002 +# define NV04_PFB_BOOT_0_RAM_AMOUNT_16MB 0x00000003 +# define NV04_PFB_BOOT_0_RAM_WIDTH_128 0x00000004 +# define NV04_PFB_BOOT_0_RAM_TYPE 0x00000028 +# define NV04_PFB_BOOT_0_RAM_TYPE_SGRAM_8MBIT 0x00000000 +# define NV04_PFB_BOOT_0_RAM_TYPE_SGRAM_16MBIT 0x00000008 +# define NV04_PFB_BOOT_0_RAM_TYPE_SGRAM_16MBIT_4BANK 0x00000010 +# define NV04_PFB_BOOT_0_RAM_TYPE_SDRAM_16MBIT 0x00000018 +# define NV04_PFB_BOOT_0_RAM_TYPE_SDRAM_64MBIT 0x00000020 +# define NV04_PFB_BOOT_0_RAM_TYPE_SDRAM_64MBITX16 0x00000028 +# define NV04_PFB_BOOT_0_UMA_ENABLE 0x00000100 +# define NV04_PFB_BOOT_0_UMA_SIZE 0x0000f000 +#define NV04_PFB_CFG0 0x00100200 + +struct nv04_fb_priv { + struct nouveau_fb base; +}; + +bool +nv04_fb_memtype_valid(struct nouveau_fb *pfb, u32 tile_flags) +{ + if (!(tile_flags & 0xff00)) + return true; + + return false; +} + +static int +nv04_fb_init(struct nouveau_object *object) { - struct drm_nouveau_private *dev_priv = dev->dev_private; - u32 boot0 = nv_rd32(dev, NV04_PFB_BOOT_0); + struct nv04_fb_priv *priv = (void *)object; + int ret; + + ret = nouveau_fb_init(&priv->base); + if (ret) + return ret; + + /* This is what the DDX did for NV_ARCH_04, but a mmio-trace shows + * nvidia reading PFB_CFG_0, then writing back its original value. + * (which was 0x701114 in this case) + */ + nv_wr32(priv, NV04_PFB_CFG0, 0x1114); + return 0; +} +static int +nv04_fb_ctor(struct nouveau_object *parent, struct nouveau_object *engine, + struct nouveau_oclass *oclass, void *data, u32 size, + struct nouveau_object **pobject) +{ + struct nv04_fb_priv *priv; + u32 boot0; + int ret; + + ret = nouveau_fb_create(parent, engine, oclass, &priv); + *pobject = nv_object(priv); + if (ret) + return ret; + + boot0 = nv_rd32(priv, NV04_PFB_BOOT_0); if (boot0 & 0x00000100) { - dev_priv->vram_size = ((boot0 >> 12) & 0xf) * 2 + 2; - dev_priv->vram_size *= 1024 * 1024; + priv->base.ram.size = ((boot0 >> 12) & 0xf) * 2 + 2; + priv->base.ram.size *= 1024 * 1024; } else { switch (boot0 & NV04_PFB_BOOT_0_RAM_AMOUNT) { case NV04_PFB_BOOT_0_RAM_AMOUNT_32MB: - dev_priv->vram_size = 32 * 1024 * 1024; + priv->base.ram.size = 32 * 1024 * 1024; break; case NV04_PFB_BOOT_0_RAM_AMOUNT_16MB: - dev_priv->vram_size = 16 * 1024 * 1024; + priv->base.ram.size = 16 * 1024 * 1024; break; case NV04_PFB_BOOT_0_RAM_AMOUNT_8MB: - dev_priv->vram_size = 8 * 1024 * 1024; + priv->base.ram.size = 8 * 1024 * 1024; break; case NV04_PFB_BOOT_0_RAM_AMOUNT_4MB: - dev_priv->vram_size = 4 * 1024 * 1024; + priv->base.ram.size = 4 * 1024 * 1024; break; } } if ((boot0 & 0x00000038) <= 0x10) - dev_priv->vram_type = NV_MEM_TYPE_SGRAM; + priv->base.ram.type = NV_MEM_TYPE_SGRAM; else - dev_priv->vram_type = NV_MEM_TYPE_SDRAM; + priv->base.ram.type = NV_MEM_TYPE_SDRAM; - return 0; -} - -int -nv04_fb_init(struct drm_device *dev) -{ - /* This is what the DDX did for NV_ARCH_04, but a mmio-trace shows - * nvidia reading PFB_CFG_0, then writing back its original value. - * (which was 0x701114 in this case) - */ - nv_wr32(dev, NV04_PFB_CFG0, 0x1114); - return 0; + priv->base.memtype_valid = nv04_fb_memtype_valid; + return nouveau_fb_created(&priv->base); } -void -nv04_fb_takedown(struct drm_device *dev) -{ -} +struct nouveau_oclass +nv04_fb_oclass = { + .handle = NV_SUBDEV(FB, 0x04), + .ofuncs = &(struct nouveau_ofuncs) { + .ctor = nv04_fb_ctor, + .dtor = _nouveau_fb_dtor, + .init = nv04_fb_init, + .fini = _nouveau_fb_fini, + }, +}; diff --git a/drivers/gpu/drm/nouveau/core/subdev/fb/nv10.c b/drivers/gpu/drm/nouveau/core/subdev/fb/nv10.c index 09af63b55f59..f037a422d2f4 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/fb/nv10.c +++ b/drivers/gpu/drm/nouveau/core/subdev/fb/nv10.c @@ -1,104 +1,120 @@ -#include "drmP.h" -#include "drm.h" -#include "nouveau_drv.h" -#include - -void -nv10_fb_init_tile_region(struct drm_device *dev, int i, uint32_t addr, - uint32_t size, uint32_t pitch, uint32_t flags) +/* + * Copyright (C) 2010 Francisco Jerez. + * All Rights Reserved. + * + * 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 (including the + * next paragraph) 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 OWNER(S) AND/OR ITS SUPPLIERS 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. + * + */ + +#include + +struct nv10_fb_priv { + struct nouveau_fb base; +}; + +static void +nv10_fb_tile_init(struct nouveau_fb *pfb, int i, u32 addr, u32 size, u32 pitch, + u32 flags, struct nouveau_fb_tile *tile) { - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_tile_reg *tile = &dev_priv->tile.reg[i]; - tile->addr = 0x80000000 | addr; tile->limit = max(1u, addr + size) - 1; tile->pitch = pitch; } -void -nv10_fb_free_tile_region(struct drm_device *dev, int i) +static void +nv10_fb_tile_fini(struct nouveau_fb *pfb, int i, struct nouveau_fb_tile *tile) { - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_tile_reg *tile = &dev_priv->tile.reg[i]; - - tile->addr = tile->limit = tile->pitch = tile->zcomp = 0; + tile->addr = 0; + tile->limit = 0; + tile->pitch = 0; + tile->zcomp = 0; } void -nv10_fb_set_tile_region(struct drm_device *dev, int i) +nv10_fb_tile_prog(struct nouveau_fb *pfb, int i, struct nouveau_fb_tile *tile) { - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_tile_reg *tile = &dev_priv->tile.reg[i]; - - nv_wr32(dev, NV10_PFB_TLIMIT(i), tile->limit); - nv_wr32(dev, NV10_PFB_TSIZE(i), tile->pitch); - nv_wr32(dev, NV10_PFB_TILE(i), tile->addr); + nv_wr32(pfb, 0x100244 + (i * 0x10), tile->limit); + nv_wr32(pfb, 0x100248 + (i * 0x10), tile->pitch); + nv_wr32(pfb, 0x100240 + (i * 0x10), tile->addr); } -int -nv1a_fb_vram_init(struct drm_device *dev) +static int +nv10_fb_ctor(struct nouveau_object *parent, struct nouveau_object *engine, + struct nouveau_oclass *oclass, void *data, u32 size, + struct nouveau_object **pobject) { - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct pci_dev *bridge; - uint32_t mem, mib; - - bridge = pci_get_bus_and_slot(0, PCI_DEVFN(0, 1)); - if (!bridge) { - NV_ERROR(dev, "no bridge device\n"); - return 0; - } - - if (dev_priv->chipset == 0x1a) { - pci_read_config_dword(bridge, 0x7c, &mem); - mib = ((mem >> 6) & 31) + 1; + struct nouveau_device *device = nv_device(parent); + struct nv10_fb_priv *priv; + int ret; + + ret = nouveau_fb_create(parent, engine, oclass, &priv); + *pobject = nv_object(priv); + if (ret) + return ret; + + if (device->chipset == 0x1a || device->chipset == 0x1f) { + struct pci_dev *bridge; + u32 mem, mib; + + bridge = pci_get_bus_and_slot(0, PCI_DEVFN(0, 1)); + if (!bridge) { + nv_fatal(device, "no bridge device\n"); + return 0; + } + + if (device->chipset == 0x1a) { + pci_read_config_dword(bridge, 0x7c, &mem); + mib = ((mem >> 6) & 31) + 1; + } else { + pci_read_config_dword(bridge, 0x84, &mem); + mib = ((mem >> 4) & 127) + 1; + } + + priv->base.ram.type = NV_MEM_TYPE_STOLEN; + priv->base.ram.size = mib * 1024 * 1024; } else { - pci_read_config_dword(bridge, 0x84, &mem); - mib = ((mem >> 4) & 127) + 1; - } + u32 cfg0 = nv_rd32(priv, 0x100200); + if (cfg0 & 0x00000001) + priv->base.ram.type = NV_MEM_TYPE_DDR1; + else + priv->base.ram.type = NV_MEM_TYPE_SDRAM; - dev_priv->vram_size = mib * 1024 * 1024; - return 0; -} - -int -nv10_fb_vram_init(struct drm_device *dev) -{ - struct drm_nouveau_private *dev_priv = dev->dev_private; - u32 fifo_data = nv_rd32(dev, NV04_PFB_FIFO_DATA); - u32 cfg0 = nv_rd32(dev, 0x100200); - - dev_priv->vram_size = fifo_data & NV10_PFB_FIFO_DATA_RAM_AMOUNT_MB_MASK; - - if (cfg0 & 0x00000001) - dev_priv->vram_type = NV_MEM_TYPE_DDR1; - else - dev_priv->vram_type = NV_MEM_TYPE_SDRAM; - - return 0; -} - -int -nv10_fb_init(struct drm_device *dev) -{ - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_fb_engine *pfb = &dev_priv->engine.fb; - int i; - - /* Turn all the tiling regions off. */ - pfb->num_tiles = NV10_PFB_TILE__SIZE; - for (i = 0; i < pfb->num_tiles; i++) - pfb->set_tile_region(dev, i); + priv->base.ram.size = nv_rd32(priv, 0x10020c) & 0xff000000; + } - return 0; + priv->base.memtype_valid = nv04_fb_memtype_valid; + priv->base.tile.regions = 8; + priv->base.tile.init = nv10_fb_tile_init; + priv->base.tile.fini = nv10_fb_tile_fini; + priv->base.tile.prog = nv10_fb_tile_prog; + return nouveau_fb_created(&priv->base); } -void -nv10_fb_takedown(struct drm_device *dev) -{ - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_fb_engine *pfb = &dev_priv->engine.fb; - int i; - - for (i = 0; i < pfb->num_tiles; i++) - pfb->free_tile_region(dev, i); -} +struct nouveau_oclass +nv10_fb_oclass = { + .handle = NV_SUBDEV(FB, 0x10), + .ofuncs = &(struct nouveau_ofuncs) { + .ctor = nv10_fb_ctor, + .dtor = _nouveau_fb_dtor, + .init = _nouveau_fb_init, + .fini = _nouveau_fb_fini, + }, +}; diff --git a/drivers/gpu/drm/nouveau/core/subdev/fb/nv20.c b/drivers/gpu/drm/nouveau/core/subdev/fb/nv20.c index a7f056c367e4..4b3578fcb7fb 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/fb/nv20.c +++ b/drivers/gpu/drm/nouveau/core/subdev/fb/nv20.c @@ -1,49 +1,41 @@ -#include "drmP.h" -#include "drm.h" -#include "nouveau_drv.h" -#include - -static struct drm_mm_node * -nv20_fb_alloc_tag(struct drm_device *dev, uint32_t size) -{ - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_fb_engine *pfb = &dev_priv->engine.fb; - struct drm_mm_node *mem; - int ret; - - ret = drm_mm_pre_get(&pfb->tag_heap); - if (ret) - return NULL; - - spin_lock(&dev_priv->tile.lock); - mem = drm_mm_search_free(&pfb->tag_heap, size, 0, 0); - if (mem) - mem = drm_mm_get_block_atomic(mem, size, 0); - spin_unlock(&dev_priv->tile.lock); - - return mem; -} +/* + * Copyright (C) 2010 Francisco Jerez. + * All Rights Reserved. + * + * 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 (including the + * next paragraph) 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 OWNER(S) AND/OR ITS SUPPLIERS 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. + * + */ + +#include + +struct nv20_fb_priv { + struct nouveau_fb base; +}; static void -nv20_fb_free_tag(struct drm_device *dev, struct drm_mm_node **pmem) +nv20_fb_tile_init(struct nouveau_fb *pfb, int i, u32 addr, u32 size, u32 pitch, + u32 flags, struct nouveau_fb_tile *tile) { - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct drm_mm_node *mem = *pmem; - if (mem) { - spin_lock(&dev_priv->tile.lock); - drm_mm_put_block(mem); - spin_unlock(&dev_priv->tile.lock); - *pmem = NULL; - } -} - -void -nv20_fb_init_tile_region(struct drm_device *dev, int i, uint32_t addr, - uint32_t size, uint32_t pitch, uint32_t flags) -{ - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_tile_reg *tile = &dev_priv->tile.reg[i]; - int bpp = (flags & NOUVEAU_GEM_TILE_32BPP ? 32 : 16); + struct nouveau_device *device = nv_device(pfb); + int bpp = (flags & 2) ? 32 : 16; tile->addr = 0x00000001 | addr; tile->limit = max(1u, addr + size) - 1; @@ -53,20 +45,20 @@ nv20_fb_init_tile_region(struct drm_device *dev, int i, uint32_t addr, * compression meta-data (most likely just a bitmap determining * if a given tile is compressed or not). */ - if (flags & NOUVEAU_GEM_TILE_ZETA) { - tile->tag_mem = nv20_fb_alloc_tag(dev, size / 256); - if (tile->tag_mem) { + size /= 256; + if (flags & 4) { + if (!nouveau_mm_head(&pfb->tags, 1, size, size, 1, &tile->tag)) { /* Enable Z compression */ - tile->zcomp = tile->tag_mem->start; - if (dev_priv->chipset >= 0x25) { + tile->zcomp = tile->tag->offset; + if (device->chipset >= 0x25) { if (bpp == 16) - tile->zcomp |= NV25_PFB_ZCOMP_MODE_16; + tile->zcomp |= 0x00100000; else - tile->zcomp |= NV25_PFB_ZCOMP_MODE_32; + tile->zcomp |= 0x00200000; } else { - tile->zcomp |= NV20_PFB_ZCOMP_EN; + tile->zcomp |= 0x80000000; if (bpp != 16) - tile->zcomp |= NV20_PFB_ZCOMP_MODE_32; + tile->zcomp |= 0x04000000; } } @@ -74,75 +66,71 @@ nv20_fb_init_tile_region(struct drm_device *dev, int i, uint32_t addr, } } -void -nv20_fb_free_tile_region(struct drm_device *dev, int i) +static void +nv20_fb_tile_fini(struct nouveau_fb *pfb, int i, struct nouveau_fb_tile *tile) { - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_tile_reg *tile = &dev_priv->tile.reg[i]; - - tile->addr = tile->limit = tile->pitch = tile->zcomp = 0; - nv20_fb_free_tag(dev, &tile->tag_mem); + tile->addr = 0; + tile->limit = 0; + tile->pitch = 0; + tile->zcomp = 0; + nouveau_mm_free(&pfb->tags, &tile->tag); } -void -nv20_fb_set_tile_region(struct drm_device *dev, int i) +static void +nv20_fb_tile_prog(struct nouveau_fb *pfb, int i, struct nouveau_fb_tile *tile) { - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_tile_reg *tile = &dev_priv->tile.reg[i]; - - nv_wr32(dev, NV10_PFB_TLIMIT(i), tile->limit); - nv_wr32(dev, NV10_PFB_TSIZE(i), tile->pitch); - nv_wr32(dev, NV10_PFB_TILE(i), tile->addr); - nv_wr32(dev, NV20_PFB_ZCOMP(i), tile->zcomp); + nv_wr32(pfb, 0x100244 + (i * 0x10), tile->limit); + nv_wr32(pfb, 0x100248 + (i * 0x10), tile->pitch); + nv_wr32(pfb, 0x100240 + (i * 0x10), tile->addr); + nv_wr32(pfb, 0x100300 + (i * 0x04), tile->zcomp); } -int -nv20_fb_vram_init(struct drm_device *dev) +static int +nv20_fb_ctor(struct nouveau_object *parent, struct nouveau_object *engine, + struct nouveau_oclass *oclass, void *data, u32 size, + struct nouveau_object **pobject) { - struct drm_nouveau_private *dev_priv = dev->dev_private; - u32 mem_size = nv_rd32(dev, 0x10020c); - u32 pbus1218 = nv_rd32(dev, 0x001218); + struct nouveau_device *device = nv_device(parent); + struct nv20_fb_priv *priv; + u32 pbus1218; + int ret; + + ret = nouveau_fb_create(parent, engine, oclass, &priv); + *pobject = nv_object(priv); + if (ret) + return ret; - dev_priv->vram_size = mem_size & 0xff000000; + pbus1218 = nv_rd32(priv, 0x001218); switch (pbus1218 & 0x00000300) { - case 0x00000000: dev_priv->vram_type = NV_MEM_TYPE_SDRAM; break; - case 0x00000100: dev_priv->vram_type = NV_MEM_TYPE_DDR1; break; - case 0x00000200: dev_priv->vram_type = NV_MEM_TYPE_GDDR3; break; - case 0x00000300: dev_priv->vram_type = NV_MEM_TYPE_GDDR2; break; + case 0x00000000: priv->base.ram.type = NV_MEM_TYPE_SDRAM; break; + case 0x00000100: priv->base.ram.type = NV_MEM_TYPE_DDR1; break; + case 0x00000200: priv->base.ram.type = NV_MEM_TYPE_GDDR3; break; + case 0x00000300: priv->base.ram.type = NV_MEM_TYPE_GDDR2; break; } + priv->base.ram.size = nv_rd32(priv, 0x10020c) & 0xff000000; - return 0; -} - -int -nv20_fb_init(struct drm_device *dev) -{ - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_fb_engine *pfb = &dev_priv->engine.fb; - int i; - - if (dev_priv->chipset >= 0x25) - drm_mm_init(&pfb->tag_heap, 0, 64 * 1024); + if (device->chipset >= 0x25) + ret = nouveau_mm_init(&priv->base.tags, 0, 64 * 1024, 1); else - drm_mm_init(&pfb->tag_heap, 0, 32 * 1024); - - /* Turn all the tiling regions off. */ - pfb->num_tiles = NV10_PFB_TILE__SIZE; - for (i = 0; i < pfb->num_tiles; i++) - pfb->set_tile_region(dev, i); - - return 0; + ret = nouveau_mm_init(&priv->base.tags, 0, 32 * 1024, 1); + if (ret) + return ret; + + priv->base.memtype_valid = nv04_fb_memtype_valid; + priv->base.tile.regions = 8; + priv->base.tile.init = nv20_fb_tile_init; + priv->base.tile.fini = nv20_fb_tile_fini; + priv->base.tile.prog = nv20_fb_tile_prog; + return nouveau_fb_created(&priv->base); } -void -nv20_fb_takedown(struct drm_device *dev) -{ - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_fb_engine *pfb = &dev_priv->engine.fb; - int i; - - for (i = 0; i < pfb->num_tiles; i++) - pfb->free_tile_region(dev, i); - - drm_mm_takedown(&pfb->tag_heap); -} +struct nouveau_oclass +nv20_fb_oclass = { + .handle = NV_SUBDEV(FB, 0x20), + .ofuncs = &(struct nouveau_ofuncs) { + .ctor = nv20_fb_ctor, + .dtor = _nouveau_fb_dtor, + .init = _nouveau_fb_init, + .fini = _nouveau_fb_fini, + }, +}; diff --git a/drivers/gpu/drm/nouveau/core/subdev/fb/nv30.c b/drivers/gpu/drm/nouveau/core/subdev/fb/nv30.c index 30639a065273..cba67bc91390 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/fb/nv30.c +++ b/drivers/gpu/drm/nouveau/core/subdev/fb/nv30.c @@ -24,50 +24,47 @@ * */ -#include "drmP.h" -#include "drm.h" -#include "nouveau_drv.h" -#include +#include + +struct nv30_fb_priv { + struct nouveau_fb base; +}; void -nv30_fb_init_tile_region(struct drm_device *dev, int i, uint32_t addr, - uint32_t size, uint32_t pitch, uint32_t flags) +nv30_fb_tile_init(struct nouveau_fb *pfb, int i, u32 addr, u32 size, u32 pitch, + u32 flags, struct nouveau_fb_tile *tile) { - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_tile_reg *tile = &dev_priv->tile.reg[i]; - tile->addr = addr | 1; tile->limit = max(1u, addr + size) - 1; tile->pitch = pitch; } void -nv30_fb_free_tile_region(struct drm_device *dev, int i) +nv30_fb_tile_fini(struct nouveau_fb *pfb, int i, struct nouveau_fb_tile *tile) { - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_tile_reg *tile = &dev_priv->tile.reg[i]; - - tile->addr = tile->limit = tile->pitch = 0; + tile->addr = 0; + tile->limit = 0; + tile->pitch = 0; } static int -calc_bias(struct drm_device *dev, int k, int i, int j) +calc_bias(struct nv30_fb_priv *priv, int k, int i, int j) { - struct drm_nouveau_private *dev_priv = dev->dev_private; - int b = (dev_priv->chipset > 0x30 ? - nv_rd32(dev, 0x122c + 0x10 * k + 0x4 * j) >> (4 * (i ^ 1)) : + struct nouveau_device *device = nv_device(priv); + int b = (device->chipset > 0x30 ? + nv_rd32(priv, 0x122c + 0x10 * k + 0x4 * j) >> (4 * (i ^ 1)) : 0) & 0xf; return 2 * (b & 0x8 ? b - 0x10 : b); } static int -calc_ref(struct drm_device *dev, int l, int k, int i) +calc_ref(struct nv30_fb_priv *priv, int l, int k, int i) { int j, x = 0; for (j = 0; j < 4; j++) { - int m = (l >> (8 * i) & 0xff) + calc_bias(dev, k, i, j); + int m = (l >> (8 * i) & 0xff) + calc_bias(priv, k, i, j); x |= (0x80 | clamp(m, 0, 0x1f)) << (8 * j); } @@ -75,42 +72,77 @@ calc_ref(struct drm_device *dev, int l, int k, int i) return x; } -int -nv30_fb_init(struct drm_device *dev) +static int +nv30_fb_init(struct nouveau_object *object) { - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_fb_engine *pfb = &dev_priv->engine.fb; - int i, j; - - pfb->num_tiles = NV10_PFB_TILE__SIZE; + struct nouveau_device *device = nv_device(object); + struct nv30_fb_priv *priv = (void *)object; + int ret, i, j; - /* Turn all the tiling regions off. */ - for (i = 0; i < pfb->num_tiles; i++) - pfb->set_tile_region(dev, i); + ret = nouveau_fb_init(&priv->base); + if (ret) + return ret; /* Init the memory timing regs at 0x10037c/0x1003ac */ - if (dev_priv->chipset == 0x30 || - dev_priv->chipset == 0x31 || - dev_priv->chipset == 0x35) { + if (device->chipset == 0x30 || + device->chipset == 0x31 || + device->chipset == 0x35) { /* Related to ROP count */ - int n = (dev_priv->chipset == 0x31 ? 2 : 4); - int l = nv_rd32(dev, 0x1003d0); + int n = (device->chipset == 0x31 ? 2 : 4); + int l = nv_rd32(priv, 0x1003d0); for (i = 0; i < n; i++) { for (j = 0; j < 3; j++) - nv_wr32(dev, 0x10037c + 0xc * i + 0x4 * j, - calc_ref(dev, l, 0, j)); + nv_wr32(priv, 0x10037c + 0xc * i + 0x4 * j, + calc_ref(priv, l, 0, j)); for (j = 0; j < 2; j++) - nv_wr32(dev, 0x1003ac + 0x8 * i + 0x4 * j, - calc_ref(dev, l, 1, j)); + nv_wr32(priv, 0x1003ac + 0x8 * i + 0x4 * j, + calc_ref(priv, l, 1, j)); } } return 0; } -void -nv30_fb_takedown(struct drm_device *dev) +static int +nv30_fb_ctor(struct nouveau_object *parent, struct nouveau_object *engine, + struct nouveau_oclass *oclass, void *data, u32 size, + struct nouveau_object **pobject) { + struct nv30_fb_priv *priv; + u32 pbus1218; + int ret; + + ret = nouveau_fb_create(parent, engine, oclass, &priv); + *pobject = nv_object(priv); + if (ret) + return ret; + + pbus1218 = nv_rd32(priv, 0x001218); + switch (pbus1218 & 0x00000300) { + case 0x00000000: priv->base.ram.type = NV_MEM_TYPE_SDRAM; break; + case 0x00000100: priv->base.ram.type = NV_MEM_TYPE_DDR1; break; + case 0x00000200: priv->base.ram.type = NV_MEM_TYPE_GDDR3; break; + case 0x00000300: priv->base.ram.type = NV_MEM_TYPE_GDDR2; break; + } + priv->base.ram.size = nv_rd32(priv, 0x10020c) & 0xff000000; + + priv->base.memtype_valid = nv04_fb_memtype_valid; + priv->base.tile.regions = 8; + priv->base.tile.init = nv30_fb_tile_init; + priv->base.tile.fini = nv30_fb_tile_fini; + priv->base.tile.prog = nv10_fb_tile_prog; + return nouveau_fb_created(&priv->base); } + +struct nouveau_oclass +nv30_fb_oclass = { + .handle = NV_SUBDEV(FB, 0x30), + .ofuncs = &(struct nouveau_ofuncs) { + .ctor = nv30_fb_ctor, + .dtor = _nouveau_fb_dtor, + .init = nv30_fb_init, + .fini = _nouveau_fb_fini, + }, +}; diff --git a/drivers/gpu/drm/nouveau/core/subdev/fb/nv40.c b/drivers/gpu/drm/nouveau/core/subdev/fb/nv40.c index e08c2e1c8f1f..84aa71c47128 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/fb/nv40.c +++ b/drivers/gpu/drm/nouveau/core/subdev/fb/nv40.c @@ -1,55 +1,83 @@ -#include "drmP.h" -#include "drm.h" -#include "nouveau_drv.h" -#include - -void -nv40_fb_set_tile_region(struct drm_device *dev, int i) +/* + * Copyright (C) 2010 Francisco Jerez. + * All Rights Reserved. + * + * 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 (including the + * next paragraph) 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 OWNER(S) AND/OR ITS SUPPLIERS 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. + * + */ + +#include + +struct nv40_fb_priv { + struct nouveau_fb base; +}; + +static inline int +nv44_graph_class(struct nouveau_device *device) { - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_tile_reg *tile = &dev_priv->tile.reg[i]; + if ((device->chipset & 0xf0) == 0x60) + return 1; - switch (dev_priv->chipset) { - case 0x40: - nv_wr32(dev, NV10_PFB_TLIMIT(i), tile->limit); - nv_wr32(dev, NV10_PFB_TSIZE(i), tile->pitch); - nv_wr32(dev, NV10_PFB_TILE(i), tile->addr); - break; + return !(0x0baf & (1 << (device->chipset & 0x0f))); +} - default: - nv_wr32(dev, NV40_PFB_TLIMIT(i), tile->limit); - nv_wr32(dev, NV40_PFB_TSIZE(i), tile->pitch); - nv_wr32(dev, NV40_PFB_TILE(i), tile->addr); - break; - } +static void +nv40_fb_tile_prog(struct nouveau_fb *pfb, int i, struct nouveau_fb_tile *tile) +{ + nv_wr32(pfb, 0x100604 + (i * 0x10), tile->limit); + nv_wr32(pfb, 0x100608 + (i * 0x10), tile->pitch); + nv_wr32(pfb, 0x100600 + (i * 0x10), tile->addr); } static void -nv40_fb_init_gart(struct drm_device *dev) +nv40_fb_init_gart(struct nv40_fb_priv *priv) { - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_gpuobj *gart = dev_priv->gart_info.sg_ctxdma; +#if 0 + struct nouveau_gpuobj *gart = ndev->gart_info.sg_ctxdma; - if (dev_priv->gart_info.type != NOUVEAU_GART_HW) { - nv_wr32(dev, 0x100800, 0x00000001); + if (ndev->gart_info.type != NOUVEAU_GART_HW) { +#endif + nv_wr32(priv, 0x100800, 0x00000001); +#if 0 return; } - nv_wr32(dev, 0x100800, gart->pinst | 0x00000002); - nv_mask(dev, 0x10008c, 0x00000100, 0x00000100); - nv_wr32(dev, 0x100820, 0x00000000); + nv_wr32(ndev, 0x100800, gart->pinst | 0x00000002); + nv_mask(ndev, 0x10008c, 0x00000100, 0x00000100); + nv_wr32(ndev, 0x100820, 0x00000000); +#endif } static void -nv44_fb_init_gart(struct drm_device *dev) +nv44_fb_init_gart(struct nv40_fb_priv *priv) { - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_gpuobj *gart = dev_priv->gart_info.sg_ctxdma; +#if 0 + struct nouveau_gpuobj *gart = ndev->gart_info.sg_ctxdma; u32 vinst; - if (dev_priv->gart_info.type != NOUVEAU_GART_HW) { - nv_wr32(dev, 0x100850, 0x80000000); - nv_wr32(dev, 0x100800, 0x00000001); + if (ndev->gart_info.type != NOUVEAU_GART_HW) { +#endif + nv_wr32(priv, 0x100850, 0x80000000); + nv_wr32(priv, 0x100800, 0x00000001); +#if 0 return; } @@ -57,24 +85,60 @@ nv44_fb_init_gart(struct drm_device *dev) * must be allocated on 512KiB alignment, and not exceed * a total size of 512KiB for this to work correctly */ - vinst = nv_rd32(dev, 0x10020c); + vinst = nv_rd32(ndev, 0x10020c); vinst -= ((gart->pinst >> 19) + 1) << 19; - nv_wr32(dev, 0x100850, 0x80000000); - nv_wr32(dev, 0x100818, dev_priv->gart_info.dummy.addr); + nv_wr32(ndev, 0x100850, 0x80000000); + nv_wr32(ndev, 0x100818, ndev->gart_info.dummy.addr); + + nv_wr32(ndev, 0x100804, ndev->gart_info.aper_size); + nv_wr32(ndev, 0x100850, 0x00008000); + nv_mask(ndev, 0x10008c, 0x00000200, 0x00000200); + nv_wr32(ndev, 0x100820, 0x00000000); + nv_wr32(ndev, 0x10082c, 0x00000001); + nv_wr32(ndev, 0x100800, vinst | 0x00000010); +#endif +} + +static int +nv40_fb_init(struct nouveau_object *object) +{ + struct nv40_fb_priv *priv = (void *)object; + int ret; + + ret = nouveau_fb_init(&priv->base); + if (ret) + return ret; + + switch (nv_device(priv)->chipset) { + case 0x40: + case 0x45: + nv_mask(priv, 0x10033c, 0x00008000, 0x00000000); + break; + default: + if (nv44_graph_class(nv_device(priv))) + nv44_fb_init_gart(priv); + else + nv40_fb_init_gart(priv); + break; + } - nv_wr32(dev, 0x100804, dev_priv->gart_info.aper_size); - nv_wr32(dev, 0x100850, 0x00008000); - nv_mask(dev, 0x10008c, 0x00000200, 0x00000200); - nv_wr32(dev, 0x100820, 0x00000000); - nv_wr32(dev, 0x10082c, 0x00000001); - nv_wr32(dev, 0x100800, vinst | 0x00000010); + return 0; } -int -nv40_fb_vram_init(struct drm_device *dev) +static int +nv40_fb_ctor(struct nouveau_object *parent, struct nouveau_object *engine, + struct nouveau_oclass *oclass, void *data, u32 size, + struct nouveau_object **pobject) { - struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_device *device = nv_device(parent); + struct nv40_fb_priv *priv; + int ret; + + ret = nouveau_fb_create(parent, engine, oclass, &priv); + *pobject = nv_object(priv); + if (ret) + return ret; /* 0x001218 is actually present on a few other NV4X I looked at, * and even contains sane values matching 0x100474. From looking @@ -82,82 +146,73 @@ nv40_fb_vram_init(struct drm_device *dev) * So, I chose to use the same regs I've seen NVIDIA reading around * the memory detection, hopefully that'll get us the right numbers */ - if (dev_priv->chipset == 0x40) { - u32 pbus1218 = nv_rd32(dev, 0x001218); + if (device->chipset == 0x40) { + u32 pbus1218 = nv_rd32(priv, 0x001218); switch (pbus1218 & 0x00000300) { - case 0x00000000: dev_priv->vram_type = NV_MEM_TYPE_SDRAM; break; - case 0x00000100: dev_priv->vram_type = NV_MEM_TYPE_DDR1; break; - case 0x00000200: dev_priv->vram_type = NV_MEM_TYPE_GDDR3; break; - case 0x00000300: dev_priv->vram_type = NV_MEM_TYPE_DDR2; break; + case 0x00000000: priv->base.ram.type = NV_MEM_TYPE_SDRAM; break; + case 0x00000100: priv->base.ram.type = NV_MEM_TYPE_DDR1; break; + case 0x00000200: priv->base.ram.type = NV_MEM_TYPE_GDDR3; break; + case 0x00000300: priv->base.ram.type = NV_MEM_TYPE_DDR2; break; } } else - if (dev_priv->chipset == 0x49 || dev_priv->chipset == 0x4b) { - u32 pfb914 = nv_rd32(dev, 0x100914); + if (device->chipset == 0x49 || device->chipset == 0x4b) { + u32 pfb914 = nv_rd32(priv, 0x100914); switch (pfb914 & 0x00000003) { - case 0x00000000: dev_priv->vram_type = NV_MEM_TYPE_DDR1; break; - case 0x00000001: dev_priv->vram_type = NV_MEM_TYPE_DDR2; break; - case 0x00000002: dev_priv->vram_type = NV_MEM_TYPE_GDDR3; break; + case 0x00000000: priv->base.ram.type = NV_MEM_TYPE_DDR1; break; + case 0x00000001: priv->base.ram.type = NV_MEM_TYPE_DDR2; break; + case 0x00000002: priv->base.ram.type = NV_MEM_TYPE_GDDR3; break; case 0x00000003: break; } } else - if (dev_priv->chipset != 0x4e) { - u32 pfb474 = nv_rd32(dev, 0x100474); + if (device->chipset != 0x4e) { + u32 pfb474 = nv_rd32(priv, 0x100474); if (pfb474 & 0x00000004) - dev_priv->vram_type = NV_MEM_TYPE_GDDR3; + priv->base.ram.type = NV_MEM_TYPE_GDDR3; if (pfb474 & 0x00000002) - dev_priv->vram_type = NV_MEM_TYPE_DDR2; + priv->base.ram.type = NV_MEM_TYPE_DDR2; if (pfb474 & 0x00000001) - dev_priv->vram_type = NV_MEM_TYPE_DDR1; + priv->base.ram.type = NV_MEM_TYPE_DDR1; } else { - dev_priv->vram_type = NV_MEM_TYPE_STOLEN; + priv->base.ram.type = NV_MEM_TYPE_STOLEN; } - dev_priv->vram_size = nv_rd32(dev, 0x10020c) & 0xff000000; - return 0; -} - -int -nv40_fb_init(struct drm_device *dev) -{ - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_fb_engine *pfb = &dev_priv->engine.fb; - uint32_t tmp; - int i; - - if (dev_priv->chipset != 0x40 && dev_priv->chipset != 0x45) { - if (nv44_graph_class(dev)) - nv44_fb_init_gart(dev); - else - nv40_fb_init_gart(dev); - } + priv->base.ram.size = nv_rd32(priv, 0x10020c) & 0xff000000; - switch (dev_priv->chipset) { + priv->base.memtype_valid = nv04_fb_memtype_valid; + switch (device->chipset) { case 0x40: case 0x45: - tmp = nv_rd32(dev, NV10_PFB_CLOSE_PAGE2); - nv_wr32(dev, NV10_PFB_CLOSE_PAGE2, tmp & ~(1 << 15)); - pfb->num_tiles = NV10_PFB_TILE__SIZE; + priv->base.tile.regions = 8; break; - case 0x46: /* G72 */ - case 0x47: /* G70 */ - case 0x49: /* G71 */ - case 0x4b: /* G73 */ - case 0x4c: /* C51 (G7X version) */ - pfb->num_tiles = NV40_PFB_TILE__SIZE_1; + case 0x46: + case 0x47: + case 0x49: + case 0x4b: + case 0x4c: + priv->base.tile.regions = 15; break; default: - pfb->num_tiles = NV40_PFB_TILE__SIZE_0; + priv->base.tile.regions = 12; break; } - - /* Turn all the tiling regions off. */ - for (i = 0; i < pfb->num_tiles; i++) - pfb->set_tile_region(dev, i); - - return 0; + priv->base.tile.init = nv30_fb_tile_init; + priv->base.tile.fini = nv30_fb_tile_fini; + if (device->chipset == 0x40) + priv->base.tile.prog = nv10_fb_tile_prog; + else + priv->base.tile.prog = nv40_fb_tile_prog; + + return nouveau_fb_created(&priv->base); } -void -nv40_fb_takedown(struct drm_device *dev) -{ -} + +struct nouveau_oclass +nv40_fb_oclass = { + .handle = NV_SUBDEV(FB, 0x40), + .ofuncs = &(struct nouveau_ofuncs) { + .ctor = nv40_fb_ctor, + .dtor = _nouveau_fb_dtor, + .init = nv40_fb_init, + .fini = _nouveau_fb_fini, + }, +}; diff --git a/drivers/gpu/drm/nouveau/core/subdev/fb/nv50.c b/drivers/gpu/drm/nouveau/core/subdev/fb/nv50.c index a145b1c81ecb..eaf18fb2c306 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/fb/nv50.c +++ b/drivers/gpu/drm/nouveau/core/subdev/fb/nv50.c @@ -1,119 +1,335 @@ -#include "drmP.h" -#include "drm.h" -#include "nouveau_drv.h" -#include -#include +/* + * Copyright 2012 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 +#include + +#include +#include struct nv50_fb_priv { + struct nouveau_fb base; struct page *r100c08_page; dma_addr_t r100c08; }; -static void -nv50_fb_destroy(struct drm_device *dev) +static int types[0x80] = { + 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 0, 0, 0, 0, 2, 2, 2, 2, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 0, 2, 2, 2, 2, 2, 2, 2, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 0, 0, + 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 2, 2, 2, 2, + 1, 0, 2, 0, 1, 0, 2, 0, 1, 1, 2, 2, 1, 1, 0, 0 +}; + +static bool +nv50_fb_memtype_valid(struct nouveau_fb *pfb, u32 memtype) { - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_fb_engine *pfb = &dev_priv->engine.fb; - struct nv50_fb_priv *priv = pfb->priv; + return types[(memtype & 0xff00) >> 8] != 0; +} - if (drm_mm_initialized(&pfb->tag_heap)) - drm_mm_takedown(&pfb->tag_heap); +static int +nv50_fb_vram_new(struct nouveau_fb *pfb, u64 size, u32 align, u32 ncmin, + u32 memtype, struct nouveau_mem **pmem) +{ + struct nv50_fb_priv *priv = (void *)pfb; + struct nouveau_mm *heap = &priv->base.vram; + struct nouveau_mm *tags = &priv->base.tags; + struct nouveau_mm_node *r; + struct nouveau_mem *mem; + int comp = (memtype & 0x300) >> 8; + int type = (memtype & 0x07f); + int back = (memtype & 0x800); + int min, max, ret; + + max = (size >> 12); + min = ncmin ? (ncmin >> 12) : max; + align >>= 12; + + mem = kzalloc(sizeof(*mem), GFP_KERNEL); + if (!mem) + return -ENOMEM; - if (priv->r100c08_page) { - pci_unmap_page(dev->pdev, priv->r100c08, PAGE_SIZE, - PCI_DMA_BIDIRECTIONAL); - __free_page(priv->r100c08_page); + mutex_lock(&pfb->base.mutex); + if (comp) { + if (align == 16) { + int n = (max >> 4) * comp; + + ret = nouveau_mm_head(tags, 1, n, n, 1, &mem->tag); + if (ret) + mem->tag = NULL; + } + + if (unlikely(!mem->tag)) + comp = 0; } - kfree(priv); - pfb->priv = NULL; + INIT_LIST_HEAD(&mem->regions); + mem->memtype = (comp << 7) | type; + mem->size = max; + + type = types[type]; + do { + if (back) + ret = nouveau_mm_tail(heap, type, max, min, align, &r); + else + ret = nouveau_mm_head(heap, type, max, min, align, &r); + if (ret) { + mutex_unlock(&pfb->base.mutex); + pfb->ram.put(pfb, &mem); + return ret; + } + + list_add_tail(&r->rl_entry, &mem->regions); + max -= r->length; + } while (max); + mutex_unlock(&pfb->base.mutex); + + r = list_first_entry(&mem->regions, struct nouveau_mm_node, rl_entry); + mem->offset = (u64)r->offset << 12; + *pmem = mem; + return 0; } -static int -nv50_fb_create(struct drm_device *dev) +void +nv50_fb_vram_del(struct nouveau_fb *pfb, struct nouveau_mem **pmem) { - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_fb_engine *pfb = &dev_priv->engine.fb; - struct nv50_fb_priv *priv; - u32 tagmem; - int ret; + struct nv50_fb_priv *priv = (void *)pfb; + struct nouveau_mm_node *this; + struct nouveau_mem *mem; - priv = kzalloc(sizeof(*priv), GFP_KERNEL); - if (!priv) - return -ENOMEM; - pfb->priv = priv; + mem = *pmem; + *pmem = NULL; + if (unlikely(mem == NULL)) + return; - priv->r100c08_page = alloc_page(GFP_KERNEL | __GFP_ZERO); - if (!priv->r100c08_page) { - nv50_fb_destroy(dev); - return -ENOMEM; + mutex_lock(&pfb->base.mutex); + while (!list_empty(&mem->regions)) { + this = list_first_entry(&mem->regions, typeof(*this), rl_entry); + + list_del(&this->rl_entry); + nouveau_mm_free(&priv->base.vram, &this); } - priv->r100c08 = pci_map_page(dev->pdev, priv->r100c08_page, 0, - PAGE_SIZE, PCI_DMA_BIDIRECTIONAL); - if (pci_dma_mapping_error(dev->pdev, priv->r100c08)) { - nv50_fb_destroy(dev); - return -EFAULT; + nouveau_mm_free(&priv->base.tags, &mem->tag); + mutex_unlock(&pfb->base.mutex); + + kfree(mem); +} + +static u32 +nv50_vram_rblock(struct nv50_fb_priv *priv) +{ + int i, parts, colbits, rowbitsa, rowbitsb, banks; + u64 rowsize, predicted; + u32 r0, r4, rt, ru, rblock_size; + + r0 = nv_rd32(priv, 0x100200); + r4 = nv_rd32(priv, 0x100204); + rt = nv_rd32(priv, 0x100250); + ru = nv_rd32(priv, 0x001540); + nv_debug(priv, "memcfg 0x%08x 0x%08x 0x%08x 0x%08x\n", r0, r4, rt, ru); + + for (i = 0, parts = 0; i < 8; i++) { + if (ru & (0x00010000 << i)) + parts++; } - tagmem = nv_rd32(dev, 0x100320); - NV_DEBUG(dev, "%d tags available\n", tagmem); - ret = drm_mm_init(&pfb->tag_heap, 0, tagmem); - if (ret) { - nv50_fb_destroy(dev); - return ret; + colbits = (r4 & 0x0000f000) >> 12; + rowbitsa = ((r4 & 0x000f0000) >> 16) + 8; + rowbitsb = ((r4 & 0x00f00000) >> 20) + 8; + banks = 1 << (((r4 & 0x03000000) >> 24) + 2); + + rowsize = parts * banks * (1 << colbits) * 8; + predicted = rowsize << rowbitsa; + if (r0 & 0x00000004) + predicted += rowsize << rowbitsb; + + if (predicted != priv->base.ram.size) { + nv_warn(priv, "memory controller reports %d MiB VRAM\n", + (u32)(priv->base.ram.size >> 20)); } - return 0; + rblock_size = rowsize; + if (rt & 1) + rblock_size *= 3; + + nv_debug(priv, "rblock %d bytes\n", rblock_size); + return rblock_size; } -int -nv50_fb_init(struct drm_device *dev) +static int +nv50_fb_ctor(struct nouveau_object *parent, struct nouveau_object *engine, + struct nouveau_oclass *oclass, void *data, u32 size, + struct nouveau_object **pobject) { - struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_device *device = nv_device(parent); + struct nouveau_bios *bios = nouveau_bios(device); + const u32 rsvd_head = ( 256 * 1024) >> 12; /* vga memory */ + const u32 rsvd_tail = (1024 * 1024) >> 12; /* vbios etc */ struct nv50_fb_priv *priv; + u32 tags; int ret; - if (!dev_priv->engine.fb.priv) { - ret = nv50_fb_create(dev); + ret = nouveau_fb_create(parent, engine, oclass, &priv); + *pobject = nv_object(priv); + if (ret) + return ret; + + switch (nv_rd32(priv, 0x100714) & 0x00000007) { + case 0: priv->base.ram.type = NV_MEM_TYPE_DDR1; break; + case 1: + if (nouveau_fb_bios_memtype(bios) == NV_MEM_TYPE_DDR3) + priv->base.ram.type = NV_MEM_TYPE_DDR3; + else + priv->base.ram.type = NV_MEM_TYPE_DDR2; + break; + case 2: priv->base.ram.type = NV_MEM_TYPE_GDDR3; break; + case 3: priv->base.ram.type = NV_MEM_TYPE_GDDR4; break; + case 4: priv->base.ram.type = NV_MEM_TYPE_GDDR5; break; + default: + break; + } + + priv->base.ram.size = nv_rd32(priv, 0x10020c); + priv->base.ram.size = (priv->base.ram.size & 0xffffff00) | + ((priv->base.ram.size & 0x000000ff) << 32); + + tags = nv_rd32(priv, 0x100320); + if (tags) { + ret = nouveau_mm_init(&priv->base.tags, 0, tags, 1); if (ret) return ret; + + nv_debug(priv, "%d compression tags\n", tags); + } + + size = (priv->base.ram.size >> 12) - rsvd_head - rsvd_tail; + switch (device->chipset) { + case 0xaa: + case 0xac: + case 0xaf: /* IGPs, no reordering, no real VRAM */ + ret = nouveau_mm_init(&priv->base.vram, rsvd_head, size, 1); + if (ret) + return ret; + + priv->base.ram.stolen = (u64)nv_rd32(priv, 0x100e10) << 12; + break; + default: + ret = nouveau_mm_init(&priv->base.vram, rsvd_head, size, + nv50_vram_rblock(priv) >> 12); + if (ret) + return ret; + + priv->base.ram.ranks = (nv_rd32(priv, 0x100200) & 0x4) ? 2 : 1; + break; + } + + priv->r100c08_page = alloc_page(GFP_KERNEL | __GFP_ZERO); + if (priv->r100c08_page) { + priv->r100c08 = pci_map_page(device->pdev, priv->r100c08_page, + 0, PAGE_SIZE, + PCI_DMA_BIDIRECTIONAL); + if (pci_dma_mapping_error(device->pdev, priv->r100c08)) + nv_warn(priv, "failed 0x100c08 page map\n"); + } else { + nv_warn(priv, "failed 0x100c08 page alloc\n"); } - priv = dev_priv->engine.fb.priv; + + priv->base.memtype_valid = nv50_fb_memtype_valid; + priv->base.ram.get = nv50_fb_vram_new; + priv->base.ram.put = nv50_fb_vram_del; + return nouveau_fb_created(&priv->base); +} + +static void +nv50_fb_dtor(struct nouveau_object *object) +{ + struct nouveau_device *device = nv_device(object); + struct nv50_fb_priv *priv = (void *)object; + + if (priv->r100c08_page) { + pci_unmap_page(device->pdev, priv->r100c08, PAGE_SIZE, + PCI_DMA_BIDIRECTIONAL); + __free_page(priv->r100c08_page); + } + + nouveau_mm_fini(&priv->base.vram); + nouveau_fb_destroy(&priv->base); +} + +static int +nv50_fb_init(struct nouveau_object *object) +{ + struct nouveau_device *device = nv_device(object); + struct nv50_fb_priv *priv = (void *)object; + int ret; + + ret = nouveau_fb_init(&priv->base); + if (ret) + return ret; /* Not a clue what this is exactly. Without pointing it at a * scratch page, VRAM->GART blits with M2MF (as in DDX DFS) * cause IOMMU "read from address 0" errors (rh#561267) */ - nv_wr32(dev, 0x100c08, priv->r100c08 >> 8); + nv_wr32(priv, 0x100c08, priv->r100c08 >> 8); /* This is needed to get meaningful information from 100c90 * on traps. No idea what these values mean exactly. */ - switch (dev_priv->chipset) { + switch (device->chipset) { case 0x50: - nv_wr32(dev, 0x100c90, 0x000707ff); + nv_wr32(priv, 0x100c90, 0x000707ff); break; case 0xa3: case 0xa5: case 0xa8: - nv_wr32(dev, 0x100c90, 0x000d0fff); + nv_wr32(priv, 0x100c90, 0x000d0fff); break; case 0xaf: - nv_wr32(dev, 0x100c90, 0x089d1fff); + nv_wr32(priv, 0x100c90, 0x089d1fff); break; default: - nv_wr32(dev, 0x100c90, 0x001d07ff); + nv_wr32(priv, 0x100c90, 0x001d07ff); break; } return 0; } -void -nv50_fb_takedown(struct drm_device *dev) -{ - nv50_fb_destroy(dev); -} +struct nouveau_oclass +nv50_fb_oclass = { + .handle = NV_SUBDEV(FB, 0x50), + .ofuncs = &(struct nouveau_ofuncs) { + .ctor = nv50_fb_ctor, + .dtor = nv50_fb_dtor, + .init = nv50_fb_init, + .fini = _nouveau_fb_fini, + }, +}; static struct nouveau_enum vm_dispatch_subclients[] = { { 0x00000000, "GRCTX", NULL }, @@ -211,47 +427,32 @@ static struct nouveau_enum vm_fault[] = { }; void -nv50_fb_vm_trap(struct drm_device *dev, int display) +nv50_fb_trap(struct nouveau_fb *pfb, int display) { - struct nouveau_fifo_priv *pfifo = nv_engine(dev, NVOBJ_ENGINE_FIFO); - struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_device *device = nv_device(pfb); + struct nv50_fb_priv *priv = (void *)pfb; const struct nouveau_enum *en, *cl; - unsigned long flags; - u32 trap[6], idx, chinst; + u32 trap[6], idx, chan; u8 st0, st1, st2, st3; - int i, ch; + int i; - idx = nv_rd32(dev, 0x100c90); + idx = nv_rd32(priv, 0x100c90); if (!(idx & 0x80000000)) return; idx &= 0x00ffffff; for (i = 0; i < 6; i++) { - nv_wr32(dev, 0x100c90, idx | i << 24); - trap[i] = nv_rd32(dev, 0x100c94); + nv_wr32(priv, 0x100c90, idx | i << 24); + trap[i] = nv_rd32(priv, 0x100c94); } - nv_wr32(dev, 0x100c90, idx | 0x80000000); + nv_wr32(priv, 0x100c90, idx | 0x80000000); if (!display) return; - /* lookup channel id */ - chinst = (trap[2] << 16) | trap[1]; - spin_lock_irqsave(&dev_priv->channels.lock, flags); - for (ch = 0; ch < pfifo->channels; ch++) { - struct nouveau_channel *chan = dev_priv->channels.ptr[ch]; - - if (!chan || !chan->ramin) - continue; - - if (chinst == chan->ramin->vinst >> 12) - break; - } - spin_unlock_irqrestore(&dev_priv->channels.lock, flags); - /* decode status bits into something more useful */ - if (dev_priv->chipset < 0xa3 || - dev_priv->chipset == 0xaa || dev_priv->chipset == 0xac) { + if (device->chipset < 0xa3 || + device->chipset == 0xaa || device->chipset == 0xac) { st0 = (trap[0] & 0x0000000f) >> 0; st1 = (trap[0] & 0x000000f0) >> 4; st2 = (trap[0] & 0x00000f00) >> 8; @@ -262,10 +463,11 @@ nv50_fb_vm_trap(struct drm_device *dev, int display) st2 = (trap[0] & 0x00ff0000) >> 16; st3 = (trap[0] & 0xff000000) >> 24; } + chan = (trap[2] << 16) | trap[1]; - NV_INFO(dev, "VM: trapped %s at 0x%02x%04x%04x on ch %d [0x%08x] ", - (trap[5] & 0x00000100) ? "read" : "write", - trap[5] & 0xff, trap[4] & 0xffff, trap[3] & 0xffff, ch, chinst); + nv_error(priv, "trapped %s at 0x%02x%04x%04x on channel 0x%08x ", + (trap[5] & 0x00000100) ? "read" : "write", + trap[5] & 0xff, trap[4] & 0xffff, trap[3] & 0xffff, chan); en = nouveau_enum_find(vm_engine, st0); if (en) diff --git a/drivers/gpu/drm/nouveau/core/subdev/fb/nv50_vram.c b/drivers/gpu/drm/nouveau/core/subdev/fb/nv50_vram.c deleted file mode 100644 index 84b99b608b2b..000000000000 --- a/drivers/gpu/drm/nouveau/core/subdev/fb/nv50_vram.c +++ /dev/null @@ -1,243 +0,0 @@ -/* - * Copyright 2010 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 "drmP.h" -#include "nouveau_drv.h" -#include - -static int types[0x80] = { - 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 1, 1, 1, 1, 0, 0, 0, 0, 2, 2, 2, 2, 0, 0, 0, 0, - 1, 1, 1, 1, 1, 1, 1, 0, 2, 2, 2, 2, 2, 2, 2, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 0, 0, - 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 2, 2, 2, 2, - 1, 0, 2, 0, 1, 0, 2, 0, 1, 1, 2, 2, 1, 1, 0, 0 -}; - -bool -nv50_vram_flags_valid(struct drm_device *dev, u32 tile_flags) -{ - int type = (tile_flags & NOUVEAU_GEM_TILE_LAYOUT_MASK) >> 8; - - if (likely(type < ARRAY_SIZE(types) && types[type])) - return true; - return false; -} - -void -nv50_vram_del(struct drm_device *dev, struct nouveau_mem **pmem) -{ - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_mm *mm = &dev_priv->engine.vram.mm; - struct nouveau_mm_node *this; - struct nouveau_mem *mem; - - mem = *pmem; - *pmem = NULL; - if (unlikely(mem == NULL)) - return; - - mutex_lock(&mm->mutex); - while (!list_empty(&mem->regions)) { - this = list_first_entry(&mem->regions, struct nouveau_mm_node, rl_entry); - - list_del(&this->rl_entry); - nouveau_mm_free(mm, &this); - } - - if (mem->tag) { - drm_mm_put_block(mem->tag); - mem->tag = NULL; - } - mutex_unlock(&mm->mutex); - - kfree(mem); -} - -int -nv50_vram_new(struct drm_device *dev, u64 size, u32 align, u32 ncmin, - u32 memtype, struct nouveau_mem **pmem) -{ - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_mm *mm = &dev_priv->engine.vram.mm; - struct nouveau_mm_node *r; - struct nouveau_mem *mem; - int comp = (memtype & 0x300) >> 8; - int type = (memtype & 0x07f); - int back = (memtype & 0x800); - int ret; - - size >>= 12; - align >>= 12; - ncmin >>= 12; - if (!ncmin) - ncmin = size; - - mem = kzalloc(sizeof(*mem), GFP_KERNEL); - if (!mem) - return -ENOMEM; - - mutex_lock(&mm->mutex); - if (comp) { - if (align == 16) { - struct nouveau_fb_engine *pfb = &dev_priv->engine.fb; - int n = (size >> 4) * comp; - - mem->tag = drm_mm_search_free(&pfb->tag_heap, n, 0, 0); - if (mem->tag) - mem->tag = drm_mm_get_block(mem->tag, n, 0); - } - - if (unlikely(!mem->tag)) - comp = 0; - } - - INIT_LIST_HEAD(&mem->regions); - mem->dev = dev_priv->dev; - mem->memtype = (comp << 7) | type; - mem->size = size; - - type = types[type]; - do { - if (back) - ret = nouveau_mm_tail(mm, type, size, ncmin, align, &r); - else - ret = nouveau_mm_head(mm, type, size, ncmin, align, &r); - - if (ret) { - mutex_unlock(&mm->mutex); - nv50_vram_del(dev, &mem); - return ret; - } - - list_add_tail(&r->rl_entry, &mem->regions); - size -= r->length; - } while (size); - mutex_unlock(&mm->mutex); - - r = list_first_entry(&mem->regions, struct nouveau_mm_node, rl_entry); - mem->offset = (u64)r->offset << 12; - *pmem = mem; - return 0; -} - -static u32 -nv50_vram_rblock(struct drm_device *dev) -{ - struct drm_nouveau_private *dev_priv = dev->dev_private; - int i, parts, colbits, rowbitsa, rowbitsb, banks; - u64 rowsize, predicted; - u32 r0, r4, rt, ru, rblock_size; - - r0 = nv_rd32(dev, 0x100200); - r4 = nv_rd32(dev, 0x100204); - rt = nv_rd32(dev, 0x100250); - ru = nv_rd32(dev, 0x001540); - NV_DEBUG(dev, "memcfg 0x%08x 0x%08x 0x%08x 0x%08x\n", r0, r4, rt, ru); - - for (i = 0, parts = 0; i < 8; i++) { - if (ru & (0x00010000 << i)) - parts++; - } - - colbits = (r4 & 0x0000f000) >> 12; - rowbitsa = ((r4 & 0x000f0000) >> 16) + 8; - rowbitsb = ((r4 & 0x00f00000) >> 20) + 8; - banks = 1 << (((r4 & 0x03000000) >> 24) + 2); - - rowsize = parts * banks * (1 << colbits) * 8; - predicted = rowsize << rowbitsa; - if (r0 & 0x00000004) - predicted += rowsize << rowbitsb; - - if (predicted != dev_priv->vram_size) { - NV_WARN(dev, "memory controller reports %dMiB VRAM\n", - (u32)(dev_priv->vram_size >> 20)); - NV_WARN(dev, "we calculated %dMiB VRAM\n", - (u32)(predicted >> 20)); - } - - rblock_size = rowsize; - if (rt & 1) - rblock_size *= 3; - - NV_DEBUG(dev, "rblock %d bytes\n", rblock_size); - return rblock_size; -} - -int -nv50_vram_init(struct drm_device *dev) -{ - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_vram_engine *vram = &dev_priv->engine.vram; - const u32 rsvd_head = ( 256 * 1024) >> 12; /* vga memory */ - const u32 rsvd_tail = (1024 * 1024) >> 12; /* vbios etc */ - u32 pfb714 = nv_rd32(dev, 0x100714); - u32 rblock, length; - - switch (pfb714 & 0x00000007) { - case 0: dev_priv->vram_type = NV_MEM_TYPE_DDR1; break; - case 1: - if (nouveau_mem_vbios_type(dev) == NV_MEM_TYPE_DDR3) - dev_priv->vram_type = NV_MEM_TYPE_DDR3; - else - dev_priv->vram_type = NV_MEM_TYPE_DDR2; - break; - case 2: dev_priv->vram_type = NV_MEM_TYPE_GDDR3; break; - case 3: dev_priv->vram_type = NV_MEM_TYPE_GDDR4; break; - case 4: dev_priv->vram_type = NV_MEM_TYPE_GDDR5; break; - default: - break; - } - - dev_priv->vram_rank_B = !!(nv_rd32(dev, 0x100200) & 0x4); - dev_priv->vram_size = nv_rd32(dev, 0x10020c); - dev_priv->vram_size |= (dev_priv->vram_size & 0xff) << 32; - dev_priv->vram_size &= 0xffffffff00ULL; - - /* IGPs, no funky reordering happens here, they don't have VRAM */ - if (dev_priv->chipset == 0xaa || - dev_priv->chipset == 0xac || - dev_priv->chipset == 0xaf) { - dev_priv->vram_sys_base = (u64)nv_rd32(dev, 0x100e10) << 12; - rblock = 4096 >> 12; - } else { - rblock = nv50_vram_rblock(dev) >> 12; - } - - length = (dev_priv->vram_size >> 12) - rsvd_head - rsvd_tail; - - return nouveau_mm_init(&vram->mm, rsvd_head, length, rblock); -} - -void -nv50_vram_fini(struct drm_device *dev) -{ - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_vram_engine *vram = &dev_priv->engine.vram; - - nouveau_mm_fini(&vram->mm); -} diff --git a/drivers/gpu/drm/nouveau/core/subdev/fb/nvc0.c b/drivers/gpu/drm/nouveau/core/subdev/fb/nvc0.c index f054331e37d8..9f59f2bf0079 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/fb/nvc0.c +++ b/drivers/gpu/drm/nouveau/core/subdev/fb/nvc0.c @@ -1,5 +1,5 @@ /* - * Copyright 2011 Red Hat Inc. + * Copyright 2012 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"), @@ -22,114 +22,224 @@ * Authors: Ben Skeggs */ -#include "drmP.h" -#include "drm.h" -#include "nouveau_drv.h" -#include +#include +#include struct nvc0_fb_priv { + struct nouveau_fb base; struct page *r100c10_page; dma_addr_t r100c10; }; -static inline void -nvc0_mfb_subp_isr(struct drm_device *dev, int unit, int subp) +/* 0 = unsupported + * 1 = non-compressed + * 3 = compressed + */ +static const u8 types[256] = { + 1, 1, 3, 3, 3, 3, 0, 3, 3, 3, 3, 0, 0, 0, 0, 0, + 0, 1, 0, 0, 0, 0, 0, 3, 3, 3, 3, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 3, 3, 3, 3, 3, + 3, 3, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 3, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 3, 3, 3, 3, 0, 1, 1, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 3, 3, 3, 3, 1, 1, 1, 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, + 3, 3, 3, 1, 0, 0, 0, 0, 0, 0, 0, 0, 3, 3, 3, 3, + 3, 3, 0, 0, 0, 0, 0, 0, 3, 0, 0, 3, 0, 3, 0, 3, + 3, 0, 3, 3, 3, 3, 3, 0, 0, 3, 0, 3, 0, 3, 3, 0, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 1, 1, 0 +}; + +static bool +nvc0_fb_memtype_valid(struct nouveau_fb *pfb, u32 tile_flags) { - u32 subp_base = 0x141000 + (unit * 0x2000) + (subp * 0x400); - u32 stat = nv_rd32(dev, subp_base + 0x020); + u8 memtype = (tile_flags & 0x0000ff00) >> 8; + return likely((types[memtype] == 1)); +} - if (stat) { - NV_INFO(dev, "PMFB%d_SUBP%d: 0x%08x\n", unit, subp, stat); - nv_wr32(dev, subp_base + 0x020, stat); - } +static int +nvc0_fb_vram_new(struct nouveau_fb *pfb, u64 size, u32 align, u32 ncmin, + u32 memtype, struct nouveau_mem **pmem) +{ + struct nouveau_mm *mm = &pfb->vram; + struct nouveau_mm_node *r; + struct nouveau_mem *mem; + int type = (memtype & 0x0ff); + int back = (memtype & 0x800); + int ret; + + size >>= 12; + align >>= 12; + ncmin >>= 12; + if (!ncmin) + ncmin = size; + + mem = kzalloc(sizeof(*mem), GFP_KERNEL); + if (!mem) + return -ENOMEM; + + INIT_LIST_HEAD(&mem->regions); + mem->memtype = type; + mem->size = size; + + mutex_lock(&mm->mutex); + do { + if (back) + ret = nouveau_mm_tail(mm, 1, size, ncmin, align, &r); + else + ret = nouveau_mm_head(mm, 1, size, ncmin, align, &r); + if (ret) { + mutex_unlock(&mm->mutex); + pfb->ram.put(pfb, &mem); + return ret; + } + + list_add_tail(&r->rl_entry, &mem->regions); + size -= r->length; + } while (size); + mutex_unlock(&mm->mutex); + + r = list_first_entry(&mem->regions, struct nouveau_mm_node, rl_entry); + mem->offset = (u64)r->offset << 12; + *pmem = mem; + return 0; } -static void -nvc0_mfb_isr(struct drm_device *dev) +static int +nvc0_fb_init(struct nouveau_object *object) { - u32 units = nv_rd32(dev, 0x00017c); - while (units) { - u32 subp, unit = ffs(units) - 1; - for (subp = 0; subp < 2; subp++) - nvc0_mfb_subp_isr(dev, unit, subp); - units &= ~(1 << unit); - } + struct nvc0_fb_priv *priv = (void *)object; + int ret; + + ret = nouveau_fb_init(&priv->base); + if (ret) + return ret; - /* we do something horribly wrong and upset PMFB a lot, so mask off - * interrupts from it after the first one until it's fixed - */ - nv_mask(dev, 0x000640, 0x02000000, 0x00000000); + nv_wr32(priv, 0x100c10, priv->r100c10 >> 8); + return 0; } static void -nvc0_fb_destroy(struct drm_device *dev) +nvc0_fb_dtor(struct nouveau_object *object) { - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_fb_engine *pfb = &dev_priv->engine.fb; - struct nvc0_fb_priv *priv = pfb->priv; - - nouveau_irq_unregister(dev, 25); + struct nouveau_device *device = nv_device(object); + struct nvc0_fb_priv *priv = (void *)object; if (priv->r100c10_page) { - pci_unmap_page(dev->pdev, priv->r100c10, PAGE_SIZE, + pci_unmap_page(device->pdev, priv->r100c10, PAGE_SIZE, PCI_DMA_BIDIRECTIONAL); __free_page(priv->r100c10_page); } - kfree(priv); - pfb->priv = NULL; + nouveau_fb_destroy(&priv->base); } static int -nvc0_fb_create(struct drm_device *dev) +nvc0_vram_detect(struct nvc0_fb_priv *priv) { - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_fb_engine *pfb = &dev_priv->engine.fb; - struct nvc0_fb_priv *priv; - - priv = kzalloc(sizeof(*priv), GFP_KERNEL); - if (!priv) - return -ENOMEM; - pfb->priv = priv; + struct nouveau_bios *bios = nouveau_bios(priv); + struct nouveau_fb *pfb = &priv->base; + const u32 rsvd_head = ( 256 * 1024) >> 12; /* vga memory */ + const u32 rsvd_tail = (1024 * 1024) >> 12; /* vbios etc */ + u32 parts = nv_rd32(priv, 0x022438); + u32 pmask = nv_rd32(priv, 0x022554); + u32 bsize = nv_rd32(priv, 0x10f20c); + u32 offset, length; + bool uniform = true; + int ret, part; + + nv_debug(priv, "0x100800: 0x%08x\n", nv_rd32(priv, 0x100800)); + nv_debug(priv, "parts 0x%08x mask 0x%08x\n", parts, pmask); + + priv->base.ram.type = nouveau_fb_bios_memtype(bios); + priv->base.ram.ranks = (nv_rd32(priv, 0x10f200) & 0x00000004) ? 2 : 1; + + /* read amount of vram attached to each memory controller */ + for (part = 0; part < parts; part++) { + if (!(pmask & (1 << part))) { + u32 psize = nv_rd32(priv, 0x11020c + (part * 0x1000)); + if (psize != bsize) { + if (psize < bsize) + bsize = psize; + uniform = false; + } + + nv_debug(priv, "%d: mem_amount 0x%08x\n", part, psize); + priv->base.ram.size += (u64)psize << 20; + } + } - priv->r100c10_page = alloc_page(GFP_KERNEL | __GFP_ZERO); - if (!priv->r100c10_page) { - nvc0_fb_destroy(dev); - return -ENOMEM; + /* if all controllers have the same amount attached, there's no holes */ + if (uniform) { + offset = rsvd_head; + length = (priv->base.ram.size >> 12) - rsvd_head - rsvd_tail; + return nouveau_mm_init(&pfb->vram, offset, length, 1); } - priv->r100c10 = pci_map_page(dev->pdev, priv->r100c10_page, 0, - PAGE_SIZE, PCI_DMA_BIDIRECTIONAL); - if (pci_dma_mapping_error(dev->pdev, priv->r100c10)) { - nvc0_fb_destroy(dev); - return -EFAULT; + /* otherwise, address lowest common amount from 0GiB */ + ret = nouveau_mm_init(&pfb->vram, rsvd_head, (bsize << 8) * parts, 1); + if (ret) + return ret; + + /* and the rest starting from (8GiB + common_size) */ + offset = (0x0200000000ULL >> 12) + (bsize << 8); + length = (priv->base.ram.size >> 12) - (bsize << 8) - rsvd_tail; + + ret = nouveau_mm_init(&pfb->vram, offset, length, 0); + if (ret) { + nouveau_mm_fini(&pfb->vram); + return ret; } - nouveau_irq_register(dev, 25, nvc0_mfb_isr); return 0; } -int -nvc0_fb_init(struct drm_device *dev) +static int +nvc0_fb_ctor(struct nouveau_object *parent, struct nouveau_object *engine, + struct nouveau_oclass *oclass, void *data, u32 size, + struct nouveau_object **pobject) { - struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_device *device = nv_device(parent); struct nvc0_fb_priv *priv; int ret; - if (!dev_priv->engine.fb.priv) { - ret = nvc0_fb_create(dev); - if (ret) - return ret; - } - priv = dev_priv->engine.fb.priv; + ret = nouveau_fb_create(parent, engine, oclass, &priv); + *pobject = nv_object(priv); + if (ret) + return ret; - nv_wr32(dev, 0x100c10, priv->r100c10 >> 8); - nv_mask(dev, 0x17e820, 0x00100000, 0x00000000); /* NV_PLTCG_INTR_EN */ - return 0; -} + priv->base.memtype_valid = nvc0_fb_memtype_valid; + priv->base.ram.get = nvc0_fb_vram_new; + priv->base.ram.put = nv50_fb_vram_del; -void -nvc0_fb_takedown(struct drm_device *dev) -{ - nvc0_fb_destroy(dev); + ret = nvc0_vram_detect(priv); + if (ret) + return ret; + + priv->r100c10_page = alloc_page(GFP_KERNEL | __GFP_ZERO); + if (!priv->r100c10_page) + return -ENOMEM; + + priv->r100c10 = pci_map_page(device->pdev, priv->r100c10_page, 0, + PAGE_SIZE, PCI_DMA_BIDIRECTIONAL); + if (pci_dma_mapping_error(device->pdev, priv->r100c10)) + return -EFAULT; + + return nouveau_fb_created(&priv->base); } + + +struct nouveau_oclass +nvc0_fb_oclass = { + .handle = NV_SUBDEV(FB, 0xc0), + .ofuncs = &(struct nouveau_ofuncs) { + .ctor = nvc0_fb_ctor, + .dtor = nvc0_fb_dtor, + .init = nvc0_fb_init, + .fini = _nouveau_fb_fini, + }, +}; diff --git a/drivers/gpu/drm/nouveau/core/subdev/fb/nvc0_vram.c b/drivers/gpu/drm/nouveau/core/subdev/fb/nvc0_vram.c deleted file mode 100644 index f363234a3f44..000000000000 --- a/drivers/gpu/drm/nouveau/core/subdev/fb/nvc0_vram.c +++ /dev/null @@ -1,167 +0,0 @@ -/* - * Copyright 2010 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 "drmP.h" -#include "nouveau_drv.h" -#include - -/* 0 = unsupported - * 1 = non-compressed - * 3 = compressed - */ -static const u8 types[256] = { - 1, 1, 3, 3, 3, 3, 0, 3, 3, 3, 3, 0, 0, 0, 0, 0, - 0, 1, 0, 0, 0, 0, 0, 3, 3, 3, 3, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 3, 3, 3, 3, 3, - 3, 3, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 3, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 3, 3, 3, 3, 0, 1, 1, 1, 1, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 3, 3, 3, 3, 1, 1, 1, 1, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, - 3, 3, 3, 1, 0, 0, 0, 0, 0, 0, 0, 0, 3, 3, 3, 3, - 3, 3, 0, 0, 0, 0, 0, 0, 3, 0, 0, 3, 0, 3, 0, 3, - 3, 0, 3, 3, 3, 3, 3, 0, 0, 3, 0, 3, 0, 3, 3, 0, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 1, 1, 0 -}; - -bool -nvc0_vram_flags_valid(struct drm_device *dev, u32 tile_flags) -{ - u8 memtype = (tile_flags & NOUVEAU_GEM_TILE_LAYOUT_MASK) >> 8; - return likely((types[memtype] == 1)); -} - -int -nvc0_vram_new(struct drm_device *dev, u64 size, u32 align, u32 ncmin, - u32 memtype, struct nouveau_mem **pmem) -{ - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_mm *mm = &dev_priv->engine.vram.mm; - struct nouveau_mm_node *r; - struct nouveau_mem *mem; - int type = (memtype & 0x0ff); - int back = (memtype & 0x800); - int ret; - - size >>= 12; - align >>= 12; - ncmin >>= 12; - if (!ncmin) - ncmin = size; - - mem = kzalloc(sizeof(*mem), GFP_KERNEL); - if (!mem) - return -ENOMEM; - - INIT_LIST_HEAD(&mem->regions); - mem->dev = dev_priv->dev; - mem->memtype = type; - mem->size = size; - - mutex_lock(&mm->mutex); - do { - if (back) - ret = nouveau_mm_tail(mm, 1, size, ncmin, align, &r); - else - ret = nouveau_mm_head(mm, 1, size, ncmin, align, &r); - if (ret) { - mutex_unlock(&mm->mutex); - nv50_vram_del(dev, &mem); - return ret; - } - - list_add_tail(&r->rl_entry, &mem->regions); - size -= r->length; - } while (size); - mutex_unlock(&mm->mutex); - - r = list_first_entry(&mem->regions, struct nouveau_mm_node, rl_entry); - mem->offset = (u64)r->offset << 12; - *pmem = mem; - return 0; -} - -int -nvc0_vram_init(struct drm_device *dev) -{ - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_vram_engine *vram = &dev_priv->engine.vram; - const u32 rsvd_head = ( 256 * 1024) >> 12; /* vga memory */ - const u32 rsvd_tail = (1024 * 1024) >> 12; /* vbios etc */ - u32 parts = nv_rd32(dev, 0x022438); - u32 pmask = nv_rd32(dev, 0x022554); - u32 bsize = nv_rd32(dev, 0x10f20c); - u32 offset, length; - bool uniform = true; - int ret, part; - - NV_DEBUG(dev, "0x100800: 0x%08x\n", nv_rd32(dev, 0x100800)); - NV_DEBUG(dev, "parts 0x%08x mask 0x%08x\n", parts, pmask); - - dev_priv->vram_type = nouveau_mem_vbios_type(dev); - dev_priv->vram_rank_B = !!(nv_rd32(dev, 0x10f200) & 0x00000004); - - /* read amount of vram attached to each memory controller */ - for (part = 0; part < parts; part++) { - if (!(pmask & (1 << part))) { - u32 psize = nv_rd32(dev, 0x11020c + (part * 0x1000)); - if (psize != bsize) { - if (psize < bsize) - bsize = psize; - uniform = false; - } - - NV_DEBUG(dev, "%d: mem_amount 0x%08x\n", part, psize); - dev_priv->vram_size += (u64)psize << 20; - } - } - - /* if all controllers have the same amount attached, there's no holes */ - if (uniform) { - offset = rsvd_head; - length = (dev_priv->vram_size >> 12) - rsvd_head - rsvd_tail; - return nouveau_mm_init(&vram->mm, offset, length, 1); - } - - /* otherwise, address lowest common amount from 0GiB */ - ret = nouveau_mm_init(&vram->mm, rsvd_head, (bsize << 8) * parts, 1); - if (ret) - return ret; - - /* and the rest starting from (8GiB + common_size) */ - offset = (0x0200000000ULL >> 12) + (bsize << 8); - length = (dev_priv->vram_size >> 12) - (bsize << 8) - rsvd_tail; - - ret = nouveau_mm_init(&vram->mm, offset, length, 0); - if (ret) { - nouveau_mm_fini(&vram->mm); - return ret; - } - - return 0; -} diff --git a/drivers/gpu/drm/nouveau/core/subdev/instmem/nv50.c b/drivers/gpu/drm/nouveau/core/subdev/instmem/nv50.c index 5965eb7cf390..24d077a1d842 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/instmem/nv50.c +++ b/drivers/gpu/drm/nouveau/core/subdev/instmem/nv50.c @@ -310,8 +310,6 @@ nv50_instmem_get(struct nouveau_gpuobj *gpuobj, struct nouveau_channel *chan, u32 size, u32 align) { struct drm_device *dev = gpuobj->dev; - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_vram_engine *vram = &dev_priv->engine.vram; struct nv50_gpuobj_node *node = NULL; int ret; @@ -323,7 +321,7 @@ nv50_instmem_get(struct nouveau_gpuobj *gpuobj, struct nouveau_channel *chan, size = (size + 4095) & ~4095; align = max(align, (u32)4096); - ret = vram->get(dev, size, align, 0, 0x800, &node->vram); + ret = nvfb_vram_get(dev, size, align, 0, 0x800, &node->vram); if (ret) { kfree(node); return ret; @@ -339,7 +337,7 @@ nv50_instmem_get(struct nouveau_gpuobj *gpuobj, struct nouveau_channel *chan, ret = nouveau_vm_get(chan->vm, size, 12, flags, &node->chan_vma); if (ret) { - vram->put(dev, &node->vram); + nvfb_vram_put(dev, &node->vram); kfree(node); return ret; } @@ -357,8 +355,6 @@ void nv50_instmem_put(struct nouveau_gpuobj *gpuobj) { struct drm_device *dev = gpuobj->dev; - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_vram_engine *vram = &dev_priv->engine.vram; struct nv50_gpuobj_node *node; node = gpuobj->node; @@ -368,7 +364,7 @@ nv50_instmem_put(struct nouveau_gpuobj *gpuobj) nouveau_vm_unmap(&node->chan_vma); nouveau_vm_put(&node->chan_vma); } - vram->put(dev, &node->vram); + nvfb_vram_put(dev, &node->vram); kfree(node); } diff --git a/drivers/gpu/drm/nouveau/core/subdev/ltcg/nvc0.c b/drivers/gpu/drm/nouveau/core/subdev/ltcg/nvc0.c new file mode 100644 index 000000000000..7c2840cc2bbf --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/subdev/ltcg/nvc0.c @@ -0,0 +1,91 @@ +/* + * Copyright 2012 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 + +struct nvc0_ltcg_priv { + struct nouveau_ltcg base; +}; + +static void +nvc0_ltcg_subp_isr(struct nvc0_ltcg_priv *priv, int unit, int subp) +{ + u32 subp_base = 0x141000 + (unit * 0x2000) + (subp * 0x400); + u32 stat = nv_rd32(priv, subp_base + 0x020); + + if (stat) { + nv_info(priv, "LTC%d_LTS%d: 0x%08x\n", unit, subp, stat); + nv_wr32(priv, subp_base + 0x020, stat); + } +} + +static void +nvc0_ltcg_intr(struct nouveau_subdev *subdev) +{ + struct nvc0_ltcg_priv *priv = (void *)subdev; + u32 units; + + units = nv_rd32(priv, 0x00017c); + while (units) { + u32 subp, unit = ffs(units) - 1; + for (subp = 0; subp < 2; subp++) + nvc0_ltcg_subp_isr(priv, unit, subp); + units &= ~(1 << unit); + } + + /* we do something horribly wrong and upset PMFB a lot, so mask off + * interrupts from it after the first one until it's fixed + */ + nv_mask(priv, 0x000640, 0x02000000, 0x00000000); +} + +static int +nvc0_ltcg_ctor(struct nouveau_object *parent, struct nouveau_object *engine, + struct nouveau_oclass *oclass, void *data, u32 size, + struct nouveau_object **pobject) +{ + struct nvc0_ltcg_priv *priv; + int ret; + + ret = nouveau_ltcg_create(parent, engine, oclass, &priv); + *pobject = nv_object(priv); + if (ret) + return ret; + + nv_mask(priv, 0x17e820, 0x00100000, 0x00000000); /* INTR_EN &= ~0x10 */ + + nv_subdev(priv)->intr = nvc0_ltcg_intr; + return 0; +} + +struct nouveau_oclass +nvc0_ltcg_oclass = { + .handle = NV_SUBDEV(LTCG, 0xc0), + .ofuncs = &(struct nouveau_ofuncs) { + .ctor = nvc0_ltcg_ctor, + .dtor = _nouveau_ltcg_dtor, + .init = _nouveau_ltcg_init, + .fini = _nouveau_ltcg_fini, + }, +}; diff --git a/drivers/gpu/drm/nouveau/core/subdev/mc/nvc0.c b/drivers/gpu/drm/nouveau/core/subdev/mc/nvc0.c index 3fa39bb9a724..bd9e99463ff7 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/mc/nvc0.c +++ b/drivers/gpu/drm/nouveau/core/subdev/mc/nvc0.c @@ -38,6 +38,7 @@ nvc0_mc_intr[] = { { 0x00008000, NVDEV_ENGINE_BSP }, { 0x00100000, NVDEV_SUBDEV_TIMER }, { 0x00200000, NVDEV_SUBDEV_GPIO }, + { 0x02000000, NVDEV_SUBDEV_LTCG }, { 0x04000000, NVDEV_ENGINE_DISP }, { 0x80000000, NVDEV_ENGINE_SW }, {}, diff --git a/drivers/gpu/drm/nouveau/core/subdev/vm/nv50.c b/drivers/gpu/drm/nouveau/core/subdev/vm/nv50.c index eeac72f40201..7e46826de0e9 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/vm/nv50.c +++ b/drivers/gpu/drm/nouveau/core/subdev/vm/nv50.c @@ -80,8 +80,8 @@ nv50_vm_map(struct nouveau_vma *vma, struct nouveau_gpuobj *pgt, /* IGPs don't have real VRAM, re-target to stolen system memory */ target = 0; - if (dev_priv->vram_sys_base) { - phys += dev_priv->vram_sys_base; + if (nvfb_vram_sys_base(dev_priv->dev)) { + phys += nvfb_vram_sys_base(dev_priv->dev); target = 3; } @@ -103,7 +103,7 @@ nv50_vm_map(struct nouveau_vma *vma, struct nouveau_gpuobj *pgt, phys += block << (vma->node->type - 3); cnt -= block; if (comp) { - u32 tag = mem->tag->start + ((delta >> 16) * comp); + u32 tag = mem->tag->offset + ((delta >> 16) * comp); offset_h |= (tag << 17); delta += block << (vma->node->type - 3); } diff --git a/drivers/gpu/drm/nouveau/nouveau_bo.c b/drivers/gpu/drm/nouveau/nouveau_bo.c index d95275437a4b..f63785c2aae0 100644 --- a/drivers/gpu/drm/nouveau/nouveau_bo.c +++ b/drivers/gpu/drm/nouveau/nouveau_bo.c @@ -156,7 +156,7 @@ static void set_placement_range(struct nouveau_bo *nvbo, uint32_t type) { struct drm_nouveau_private *dev_priv = nouveau_bdev(nvbo->bo.bdev); - int vram_pages = dev_priv->vram_size >> PAGE_SHIFT; + int vram_pages = nvfb_vram_size(dev_priv->dev) >> PAGE_SHIFT; if (dev_priv->card_type == NV_10 && nvbo->tile_mode && (type & TTM_PL_FLAG_VRAM) && diff --git a/drivers/gpu/drm/nouveau/nouveau_compat.c b/drivers/gpu/drm/nouveau/nouveau_compat.c index 7880ebb9a7d9..3d65c1763311 100644 --- a/drivers/gpu/drm/nouveau/nouveau_compat.c +++ b/drivers/gpu/drm/nouveau/nouveau_compat.c @@ -10,6 +10,7 @@ #include #include #include +#include void *nouveau_newpriv(struct drm_device *); @@ -332,3 +333,108 @@ nv_timer_read(struct drm_device *dev) struct nouveau_timer *ptimer = nouveau_timer(drm->device); return ptimer->read(ptimer); } + +int +nvfb_tile_nr(struct drm_device *dev) +{ + struct nouveau_drm *drm = nouveau_newpriv(dev); + struct nouveau_fb *pfb = nouveau_fb(drm->device); + return pfb->tile.regions; +} + +struct nouveau_fb_tile * +nvfb_tile(struct drm_device *dev, int i) +{ + struct nouveau_drm *drm = nouveau_newpriv(dev); + struct nouveau_fb *pfb = nouveau_fb(drm->device); + return &pfb->tile.region[i]; +} + +void +nvfb_tile_init(struct drm_device *dev, int i, u32 a, u32 b, u32 c, u32 d) +{ + struct nouveau_drm *drm = nouveau_newpriv(dev); + struct nouveau_fb *pfb = nouveau_fb(drm->device); + pfb->tile.init(pfb, i, a, b, c, d, &pfb->tile.region[i]); +} + +void +nvfb_tile_fini(struct drm_device *dev, int i) +{ + struct nouveau_drm *drm = nouveau_newpriv(dev); + struct nouveau_fb *pfb = nouveau_fb(drm->device); + pfb->tile.fini(pfb, i, &pfb->tile.region[i]); +} + +void +nvfb_tile_prog(struct drm_device *dev, int i) +{ + struct nouveau_drm *drm = nouveau_newpriv(dev); + struct nouveau_fb *pfb = nouveau_fb(drm->device); + pfb->tile.prog(pfb, i, &pfb->tile.region[i]); +} + +bool +nvfb_flags_valid(struct drm_device *dev, u32 flags) +{ + struct nouveau_drm *drm = nouveau_newpriv(dev); + struct nouveau_fb *pfb = nouveau_fb(drm->device); + return pfb->memtype_valid(pfb, flags); +} + +int +nvfb_vram_get(struct drm_device *dev, u64 size, u32 align, u32 ncmin, + u32 memtype, struct nouveau_mem **pmem) +{ + struct nouveau_drm *drm = nouveau_newpriv(dev); + struct nouveau_fb *pfb = nouveau_fb(drm->device); + int ret = pfb->ram.get(pfb, size, align, ncmin, memtype, pmem); + if (ret) + return ret; + (*pmem)->dev = dev; + return 0; +} + +void +nvfb_vram_put(struct drm_device *dev, struct nouveau_mem **pmem) +{ + struct nouveau_drm *drm = nouveau_newpriv(dev); + struct nouveau_fb *pfb = nouveau_fb(drm->device); + pfb->ram.put(pfb, pmem); +} + + +u64 nvfb_vram_sys_base(struct drm_device *dev) +{ + struct nouveau_drm *drm = nouveau_newpriv(dev); + struct nouveau_fb *pfb = nouveau_fb(drm->device); + return pfb->ram.stolen; +} + +u64 nvfb_vram_size(struct drm_device *dev) +{ + struct nouveau_drm *drm = nouveau_newpriv(dev); + struct nouveau_fb *pfb = nouveau_fb(drm->device); + return pfb->ram.size; +} + +int nvfb_vram_type(struct drm_device *dev) +{ + struct nouveau_drm *drm = nouveau_newpriv(dev); + struct nouveau_fb *pfb = nouveau_fb(drm->device); + return pfb->ram.type; +} + +int nvfb_vram_rank_B(struct drm_device *dev) +{ + struct nouveau_drm *drm = nouveau_newpriv(dev); + struct nouveau_fb *pfb = nouveau_fb(drm->device); + return pfb->ram.ranks > 1; +} + +void +nv50_fb_vm_trap(struct drm_device *dev, int disp) +{ + struct nouveau_drm *drm = nouveau_newpriv(dev); + nv50_fb_trap(nouveau_fb(drm->device), disp); +} diff --git a/drivers/gpu/drm/nouveau/nouveau_compat.h b/drivers/gpu/drm/nouveau/nouveau_compat.h index c9622ebf5cbe..d047a2046959 100644 --- a/drivers/gpu/drm/nouveau/nouveau_compat.h +++ b/drivers/gpu/drm/nouveau/nouveau_compat.h @@ -62,4 +62,24 @@ bool nouveau_wait_cb(struct drm_device *, u64 timeout, u64 nv_timer_read(struct drm_device *); +int nvfb_tile_nr(struct drm_device *); +void nvfb_tile_init(struct drm_device *, int, u32, u32, u32, u32); +void nvfb_tile_fini(struct drm_device *, int); +void nvfb_tile_prog(struct drm_device *, int); + +struct nouveau_fb_tile *nvfb_tile(struct drm_device *, int); + +struct nouveau_mem; +int nvfb_vram_get(struct drm_device *dev, u64 size, u32 align, u32 ncmin, + u32 memtype, struct nouveau_mem **pmem); +void nvfb_vram_put(struct drm_device *dev, struct nouveau_mem **pmem); +bool nvfb_flags_valid(struct drm_device *dev, u32); + +u64 nvfb_vram_sys_base(struct drm_device *); +u64 nvfb_vram_size(struct drm_device *); +int nvfb_vram_type(struct drm_device *); +int nvfb_vram_rank_B(struct drm_device *); + +void nv50_fb_vm_trap(struct drm_device *, int); + #endif diff --git a/drivers/gpu/drm/nouveau/nouveau_debugfs.c b/drivers/gpu/drm/nouveau/nouveau_debugfs.c index 188c92b327e2..6564b547973e 100644 --- a/drivers/gpu/drm/nouveau/nouveau_debugfs.c +++ b/drivers/gpu/drm/nouveau/nouveau_debugfs.c @@ -137,9 +137,8 @@ nouveau_debugfs_memory_info(struct seq_file *m, void *data) { struct drm_info_node *node = (struct drm_info_node *) m->private; struct drm_minor *minor = node->minor; - struct drm_nouveau_private *dev_priv = minor->dev->dev_private; - seq_printf(m, "VRAM total: %dKiB\n", (int)(dev_priv->vram_size >> 10)); + seq_printf(m, "VRAM total: %dKiB\n", (int)(nvfb_vram_size(minor->dev) >> 10)); return 0; } diff --git a/drivers/gpu/drm/nouveau/nouveau_drv.c b/drivers/gpu/drm/nouveau/nouveau_drv.c index 7223a4f69231..3f660a94dd18 100644 --- a/drivers/gpu/drm/nouveau/nouveau_drv.c +++ b/drivers/gpu/drm/nouveau/nouveau_drv.c @@ -252,7 +252,6 @@ nouveau_pci_resume(struct pci_dev *pdev) NV_INFO(dev, "Reinitialising engines...\n"); engine->instmem.resume(dev); - engine->fb.init(dev); for (i = 0; i < NVOBJ_ENGINE_NR; i++) { if (dev_priv->eng[i]) dev_priv->eng[i]->init(dev, i); diff --git a/drivers/gpu/drm/nouveau/nouveau_drv.h b/drivers/gpu/drm/nouveau/nouveau_drv.h index b4595990f5e8..c7bc6ecad601 100644 --- a/drivers/gpu/drm/nouveau/nouveau_drv.h +++ b/drivers/gpu/drm/nouveau/nouveau_drv.h @@ -45,6 +45,23 @@ #include "ttm/ttm_memory.h" #include "ttm/ttm_module.h" +#define XXX_THIS_IS_A_HACK +#include + +enum blah { + NV_MEM_TYPE_UNKNOWN = 0, + NV_MEM_TYPE_STOLEN, + NV_MEM_TYPE_SGRAM, + NV_MEM_TYPE_SDRAM, + NV_MEM_TYPE_DDR1, + NV_MEM_TYPE_DDR2, + NV_MEM_TYPE_DDR3, + NV_MEM_TYPE_GDDR2, + NV_MEM_TYPE_GDDR3, + NV_MEM_TYPE_GDDR4, + NV_MEM_TYPE_GDDR5 +}; + struct nouveau_fpriv { spinlock_t lock; struct list_head channels; @@ -76,29 +93,8 @@ struct nouveau_mem; #define NOUVEAU_MAX_CHANNEL_NR 4096 #define NOUVEAU_MAX_TILE_NR 15 -struct nouveau_mem { - struct drm_device *dev; - - struct nouveau_vma bar_vma; - struct nouveau_vma vma[2]; - u8 page_shift; - - struct drm_mm_node *tag; - struct list_head regions; - dma_addr_t *pages; - u32 memtype; - u64 offset; - u64 size; - struct sg_table *sg; -}; - struct nouveau_tile_reg { bool used; - uint32_t addr; - uint32_t limit; - uint32_t pitch; - uint32_t zcomp; - struct drm_mm_node *tag_mem; struct nouveau_fence *fence; }; @@ -324,21 +320,6 @@ struct nouveau_instmem_engine { void (*flush)(struct drm_device *); }; -struct nouveau_fb_engine { - int num_tiles; - struct drm_mm tag_heap; - void *priv; - - int (*init)(struct drm_device *dev); - void (*takedown)(struct drm_device *dev); - - void (*init_tile_region)(struct drm_device *dev, int i, - uint32_t addr, uint32_t size, - uint32_t pitch, uint32_t flags); - void (*set_tile_region)(struct drm_device *dev, int i); - void (*free_tile_region)(struct drm_device *dev, int i); -}; - struct nouveau_display_engine { void *priv; int (*early_init)(struct drm_device *); @@ -519,24 +500,10 @@ struct nouveau_pm_engine { int (*temp_get)(struct drm_device *); }; -struct nouveau_vram_engine { - struct nouveau_mm mm; - - int (*init)(struct drm_device *); - void (*takedown)(struct drm_device *dev); - int (*get)(struct drm_device *, u64, u32 align, u32 size_nc, - u32 type, struct nouveau_mem **); - void (*put)(struct drm_device *, struct nouveau_mem **); - - bool (*flags_valid)(struct drm_device *, u32 tile_flags); -}; - struct nouveau_engine { struct nouveau_instmem_engine instmem; - struct nouveau_fb_engine fb; struct nouveau_display_engine display; struct nouveau_pm_engine pm; - struct nouveau_vram_engine vram; }; enum nv04_fp_display_regs { @@ -714,24 +681,6 @@ struct drm_nouveau_private { spinlock_t lock; } tile; - /* VRAM/fb configuration */ - enum { - NV_MEM_TYPE_UNKNOWN = 0, - NV_MEM_TYPE_STOLEN, - NV_MEM_TYPE_SGRAM, - NV_MEM_TYPE_SDRAM, - NV_MEM_TYPE_DDR1, - NV_MEM_TYPE_DDR2, - NV_MEM_TYPE_DDR3, - NV_MEM_TYPE_GDDR2, - NV_MEM_TYPE_GDDR3, - NV_MEM_TYPE_GDDR4, - NV_MEM_TYPE_GDDR5 - } vram_type; - uint64_t vram_size; - uint64_t vram_sys_base; - bool vram_rank_B; - uint64_t fb_available_size; uint64_t fb_mappable_pages; uint64_t fb_aper_free; @@ -1047,55 +996,6 @@ int nouveau_ttm_mmap(struct file *, struct vm_area_struct *); /* nouveau_hdmi.c */ void nouveau_hdmi_mode_set(struct drm_encoder *, struct drm_display_mode *); -/* nv04_fb.c */ -extern int nv04_fb_vram_init(struct drm_device *); -extern int nv04_fb_init(struct drm_device *); -extern void nv04_fb_takedown(struct drm_device *); - -/* nv10_fb.c */ -extern int nv10_fb_vram_init(struct drm_device *dev); -extern int nv1a_fb_vram_init(struct drm_device *dev); -extern int nv10_fb_init(struct drm_device *); -extern void nv10_fb_takedown(struct drm_device *); -extern void nv10_fb_init_tile_region(struct drm_device *dev, int i, - uint32_t addr, uint32_t size, - uint32_t pitch, uint32_t flags); -extern void nv10_fb_set_tile_region(struct drm_device *dev, int i); -extern void nv10_fb_free_tile_region(struct drm_device *dev, int i); - -/* nv20_fb.c */ -extern int nv20_fb_vram_init(struct drm_device *dev); -extern int nv20_fb_init(struct drm_device *); -extern void nv20_fb_takedown(struct drm_device *); -extern void nv20_fb_init_tile_region(struct drm_device *dev, int i, - uint32_t addr, uint32_t size, - uint32_t pitch, uint32_t flags); -extern void nv20_fb_set_tile_region(struct drm_device *dev, int i); -extern void nv20_fb_free_tile_region(struct drm_device *dev, int i); - -/* nv30_fb.c */ -extern int nv30_fb_init(struct drm_device *); -extern void nv30_fb_takedown(struct drm_device *); -extern void nv30_fb_init_tile_region(struct drm_device *dev, int i, - uint32_t addr, uint32_t size, - uint32_t pitch, uint32_t flags); -extern void nv30_fb_free_tile_region(struct drm_device *dev, int i); - -/* nv40_fb.c */ -extern int nv40_fb_vram_init(struct drm_device *dev); -extern int nv40_fb_init(struct drm_device *); -extern void nv40_fb_takedown(struct drm_device *); -extern void nv40_fb_set_tile_region(struct drm_device *dev, int i); - -/* nv50_fb.c */ -extern int nv50_fb_init(struct drm_device *); -extern void nv50_fb_takedown(struct drm_device *); -extern void nv50_fb_vm_trap(struct drm_device *, int display); - -/* nvc0_fb.c */ -extern int nvc0_fb_init(struct drm_device *); -extern void nvc0_fb_takedown(struct drm_device *); - /* nv04_graph.c */ extern int nv04_graph_create(struct drm_device *); extern int nv04_graph_object_new(struct nouveau_channel *, int, u32, u16); @@ -1488,18 +1388,6 @@ nv44_graph_class(struct drm_device *dev) return !(0x0baf & (1 << (dev_priv->chipset & 0x0f))); } -int nv50_vram_init(struct drm_device *); -void nv50_vram_fini(struct drm_device *); -int nv50_vram_new(struct drm_device *, u64 size, u32 align, u32 size_nc, - u32 memtype, struct nouveau_mem **); -void nv50_vram_del(struct drm_device *, struct nouveau_mem **); -bool nv50_vram_flags_valid(struct drm_device *, u32 tile_flags); - -int nvc0_vram_init(struct drm_device *); -int nvc0_vram_new(struct drm_device *, u64 size, u32 align, u32 ncmin, - u32 memtype, struct nouveau_mem **); -bool nvc0_vram_flags_valid(struct drm_device *, u32 tile_flags); - /* memory type/access flags, do not match hardware values */ #define NV_MEM_ACCESS_RO 1 #define NV_MEM_ACCESS_WO 2 diff --git a/drivers/gpu/drm/nouveau/nouveau_fb.h b/drivers/gpu/drm/nouveau/nouveau_fb.h index f3fb649fe454..d767567977ee 100644 --- a/drivers/gpu/drm/nouveau/nouveau_fb.h +++ b/drivers/gpu/drm/nouveau/nouveau_fb.h @@ -24,8 +24,8 @@ * */ -#ifndef __NOUVEAU_FB_H__ -#define __NOUVEAU_FB_H__ +#ifndef __NOUVEAU_FRB_H__ +#define __NOUVEAU_FRB_H__ struct nouveau_framebuffer { struct drm_framebuffer base; diff --git a/drivers/gpu/drm/nouveau/nouveau_fbcon.c b/drivers/gpu/drm/nouveau/nouveau_fbcon.c index 9b078033ec19..f3f0b4c362cb 100644 --- a/drivers/gpu/drm/nouveau/nouveau_fbcon.c +++ b/drivers/gpu/drm/nouveau/nouveau_fbcon.c @@ -475,9 +475,9 @@ int nouveau_fbcon_init(struct drm_device *dev) drm_fb_helper_single_add_all_connectors(&nfbdev->helper); - if (dev_priv->vram_size <= 32 * 1024 * 1024) + if (nvfb_vram_size(dev) <= 32 * 1024 * 1024) preferred_bpp = 8; - else if (dev_priv->vram_size <= 64 * 1024 * 1024) + else if (nvfb_vram_size(dev) <= 64 * 1024 * 1024) preferred_bpp = 16; else preferred_bpp = 32; diff --git a/drivers/gpu/drm/nouveau/nouveau_gem.c b/drivers/gpu/drm/nouveau/nouveau_gem.c index c8bb9f230222..96a34bce54ce 100644 --- a/drivers/gpu/drm/nouveau/nouveau_gem.c +++ b/drivers/gpu/drm/nouveau/nouveau_gem.c @@ -209,7 +209,7 @@ nouveau_gem_ioctl_new(struct drm_device *dev, void *data, dev_priv->ttm.bdev.dev_mapping = dev->dev_mapping; - if (!dev_priv->engine.vram.flags_valid(dev, req->info.tile_flags)) { + if (!nvfb_flags_valid(dev, req->info.tile_flags)) { NV_ERROR(dev, "bad page flags: 0x%08x\n", req->info.tile_flags); return -EINVAL; } diff --git a/drivers/gpu/drm/nouveau/nouveau_mem.c b/drivers/gpu/drm/nouveau/nouveau_mem.c index 689d3e708057..4aea1c4c46ef 100644 --- a/drivers/gpu/drm/nouveau/nouveau_mem.c +++ b/drivers/gpu/drm/nouveau/nouveau_mem.c @@ -48,21 +48,21 @@ static void nv10_mem_update_tile_region(struct drm_device *dev, - struct nouveau_tile_reg *tile, uint32_t addr, + struct nouveau_tile_reg *tilereg, uint32_t addr, uint32_t size, uint32_t pitch, uint32_t flags) { struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_fb_engine *pfb = &dev_priv->engine.fb; - int i = tile - dev_priv->tile.reg, j; + int i = tilereg - dev_priv->tile.reg, j; + struct nouveau_fb_tile *tile = nvfb_tile(dev, i); unsigned long save; - nouveau_fence_unref(&tile->fence); + nouveau_fence_unref(&tilereg->fence); if (tile->pitch) - pfb->free_tile_region(dev, i); + nvfb_tile_fini(dev, i); if (pitch) - pfb->init_tile_region(dev, i, addr, size, pitch, flags); + nvfb_tile_init(dev, i, addr, size, pitch, flags); spin_lock_irqsave(&dev_priv->context_switch_lock, save); nv_wr32(dev, NV03_PFIFO_CACHES, 0); @@ -70,7 +70,7 @@ nv10_mem_update_tile_region(struct drm_device *dev, nouveau_wait_for_idle(dev); - pfb->set_tile_region(dev, i); + nvfb_tile_prog(dev, i); for (j = 0; j < NVOBJ_ENGINE_NR; j++) { if (dev_priv->eng[j] && dev_priv->eng[j]->set_tile_region) dev_priv->eng[j]->set_tile_region(dev, i); @@ -122,19 +122,17 @@ struct nouveau_tile_reg * nv10_mem_set_tiling(struct drm_device *dev, uint32_t addr, uint32_t size, uint32_t pitch, uint32_t flags) { - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_fb_engine *pfb = &dev_priv->engine.fb; struct nouveau_tile_reg *tile, *found = NULL; int i; - for (i = 0; i < pfb->num_tiles; i++) { + for (i = 0; i < nvfb_tile_nr(dev); i++) { tile = nv10_mem_get_tile_region(dev, i); if (pitch && !found) { found = tile; continue; - } else if (tile && tile->pitch) { + } else if (tile && nvfb_tile(dev, i)->pitch) { /* Kill an unused tile region. */ nv10_mem_update_tile_region(dev, tile, 0, 0, 0, 0); } @@ -174,38 +172,11 @@ nouveau_mem_gart_fini(struct drm_device *dev) nouveau_sgdma_takedown(dev); } -bool -nouveau_mem_flags_valid(struct drm_device *dev, u32 tile_flags) -{ - if (!(tile_flags & NOUVEAU_GEM_TILE_LAYOUT_MASK)) - return true; - - return false; -} - -static const struct vram_types { - int value; - const char *name; -} vram_type_map[] = { - { NV_MEM_TYPE_STOLEN , "stolen system memory" }, - { NV_MEM_TYPE_SGRAM , "SGRAM" }, - { NV_MEM_TYPE_SDRAM , "SDRAM" }, - { NV_MEM_TYPE_DDR1 , "DDR1" }, - { NV_MEM_TYPE_DDR2 , "DDR2" }, - { NV_MEM_TYPE_DDR3 , "DDR3" }, - { NV_MEM_TYPE_GDDR2 , "GDDR2" }, - { NV_MEM_TYPE_GDDR3 , "GDDR3" }, - { NV_MEM_TYPE_GDDR4 , "GDDR4" }, - { NV_MEM_TYPE_GDDR5 , "GDDR5" }, - { NV_MEM_TYPE_UNKNOWN, "unknown type" } -}; - int nouveau_mem_vram_init(struct drm_device *dev) { struct drm_nouveau_private *dev_priv = dev->dev_private; struct ttm_bo_device *bdev = &dev_priv->ttm.bdev; - const struct vram_types *vram_type; int ret, dma_bits; dma_bits = 32; @@ -243,27 +214,7 @@ nouveau_mem_vram_init(struct drm_device *dev) return ret; } - vram_type = vram_type_map; - while (vram_type->value != NV_MEM_TYPE_UNKNOWN) { - if (nouveau_vram_type) { - if (!strcasecmp(nouveau_vram_type, vram_type->name)) - break; - dev_priv->vram_type = vram_type->value; - } else { - if (vram_type->value == dev_priv->vram_type) - break; - } - vram_type++; - } - - NV_INFO(dev, "Detected %dMiB VRAM (%s)\n", - (int)(dev_priv->vram_size >> 20), vram_type->name); - if (dev_priv->vram_sys_base) { - NV_INFO(dev, "Stolen system memory at: 0x%010llx\n", - dev_priv->vram_sys_base); - } - - dev_priv->fb_available_size = dev_priv->vram_size; + dev_priv->fb_available_size = nvfb_vram_size(dev); dev_priv->fb_mappable_pages = dev_priv->fb_available_size; if (dev_priv->fb_mappable_pages > pci_resource_len(dev->pdev, 1)) dev_priv->fb_mappable_pages = pci_resource_len(dev->pdev, 1); @@ -364,7 +315,6 @@ nv50_mem_timing_calc(struct drm_device *dev, u32 freq, struct nouveau_pm_memtiming *boot, struct nouveau_pm_memtiming *t) { - struct drm_nouveau_private *dev_priv = dev->dev_private; struct bit_entry P; uint8_t unk18 = 1, unk20 = 0, unk21 = 0, tmp7_3; @@ -418,7 +368,7 @@ nv50_mem_timing_calc(struct drm_device *dev, u32 freq, t->reg[7] = 0x4000202 | (e->tCL - 1) << 16; /* XXX: P.version == 1 only has DDR2 and GDDR3? */ - if (dev_priv->vram_type == NV_MEM_TYPE_DDR2) { + if (nvfb_vram_type(dev) == NV_MEM_TYPE_DDR2) { t->reg[5] |= (e->tCL + 3) << 8; t->reg[6] |= (t->tCWL - 2) << 8; t->reg[8] |= (e->tCL - 4); @@ -711,7 +661,7 @@ nouveau_mem_timing_calc(struct drm_device *dev, u32 freq, break; } - switch (dev_priv->vram_type * !ret) { + switch (nvfb_vram_type(dev) * !ret) { case NV_MEM_TYPE_GDDR3: ret = nouveau_mem_gddr3_mr(dev, freq, e, len, boot, t); break; @@ -738,7 +688,7 @@ nouveau_mem_timing_calc(struct drm_device *dev, u32 freq, else dll_off = !!(ramcfg[2] & 0x40); - switch (dev_priv->vram_type) { + switch (nvfb_vram_type(dev)) { case NV_MEM_TYPE_GDDR3: t->mr[1] &= ~0x00000040; t->mr[1] |= 0x00000040 * dll_off; @@ -804,7 +754,7 @@ nouveau_mem_timing_read(struct drm_device *dev, struct nouveau_pm_memtiming *t) t->odt = 0; t->drive_strength = 0; - switch (dev_priv->vram_type) { + switch (nvfb_vram_type(dev)) { case NV_MEM_TYPE_DDR3: t->odt |= (t->mr[1] & 0x200) >> 7; case NV_MEM_TYPE_DDR2: @@ -831,7 +781,7 @@ nouveau_mem_exec(struct nouveau_mem_exec_func *exec, u32 mr[3] = { info->mr[0], info->mr[1], info->mr[2] }; u32 mr1_dlloff; - switch (dev_priv->vram_type) { + switch (nvfb_vram_type(dev_priv->dev)) { case NV_MEM_TYPE_DDR2: tDLLK = 2000; mr1_dlloff = 0x00000001; @@ -852,7 +802,7 @@ nouveau_mem_exec(struct nouveau_mem_exec_func *exec, } /* fetch current MRs */ - switch (dev_priv->vram_type) { + switch (nvfb_vram_type(dev_priv->dev)) { case NV_MEM_TYPE_GDDR3: case NV_MEM_TYPE_DDR3: mr[2] = exec->mrg(exec, 2); @@ -919,7 +869,7 @@ nouveau_mem_exec(struct nouveau_mem_exec_func *exec, exec->mrs (exec, 0, info->mr[0] | 0x00000000); exec->wait(exec, tMRD); exec->wait(exec, tDLLK); - if (dev_priv->vram_type == NV_MEM_TYPE_GDDR3) + if (nvfb_vram_type(dev_priv->dev) == NV_MEM_TYPE_GDDR3) exec->precharge(exec); } @@ -982,11 +932,10 @@ nouveau_vram_manager_del(struct ttm_mem_type_manager *man, struct ttm_mem_reg *mem) { struct drm_nouveau_private *dev_priv = nouveau_bdev(man->bdev); - struct nouveau_vram_engine *vram = &dev_priv->engine.vram; struct drm_device *dev = dev_priv->dev; nouveau_mem_node_cleanup(mem->mm_node); - vram->put(dev, (struct nouveau_mem **)&mem->mm_node); + nvfb_vram_put(dev, (struct nouveau_mem **)&mem->mm_node); } static int @@ -996,7 +945,6 @@ nouveau_vram_manager_new(struct ttm_mem_type_manager *man, struct ttm_mem_reg *mem) { struct drm_nouveau_private *dev_priv = nouveau_bdev(man->bdev); - struct nouveau_vram_engine *vram = &dev_priv->engine.vram; struct drm_device *dev = dev_priv->dev; struct nouveau_bo *nvbo = nouveau_bo(bo); struct nouveau_mem *node; @@ -1006,7 +954,7 @@ nouveau_vram_manager_new(struct ttm_mem_type_manager *man, if (nvbo->tile_flags & NOUVEAU_GEM_TILE_NONCONTIG) size_nc = 1 << nvbo->page_shift; - ret = vram->get(dev, mem->num_pages << PAGE_SHIFT, + ret = nvfb_vram_get(dev, mem->num_pages << PAGE_SHIFT, mem->page_alignment << PAGE_SHIFT, size_nc, (nvbo->tile_flags >> 8) & 0x3ff, &node); if (ret) { diff --git a/drivers/gpu/drm/nouveau/nouveau_state.c b/drivers/gpu/drm/nouveau/nouveau_state.c index 3b11962d7d6d..d8d9e5c527a4 100644 --- a/drivers/gpu/drm/nouveau/nouveau_state.c +++ b/drivers/gpu/drm/nouveau/nouveau_state.c @@ -61,8 +61,6 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev) engine->instmem.map = nv04_instmem_map; engine->instmem.unmap = nv04_instmem_unmap; engine->instmem.flush = nv04_instmem_flush; - engine->fb.init = nv04_fb_init; - engine->fb.takedown = nv04_fb_takedown; engine->display.early_init = nv04_display_early_init; engine->display.late_takedown = nv04_display_late_takedown; engine->display.create = nv04_display_create; @@ -72,9 +70,6 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev) engine->pm.clocks_get = nv04_pm_clocks_get; engine->pm.clocks_pre = nv04_pm_clocks_pre; engine->pm.clocks_set = nv04_pm_clocks_set; - engine->vram.init = nv04_fb_vram_init; - engine->vram.takedown = nouveau_stub_takedown; - engine->vram.flags_valid = nouveau_mem_flags_valid; break; case 0x10: engine->instmem.init = nv04_instmem_init; @@ -86,11 +81,6 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev) engine->instmem.map = nv04_instmem_map; engine->instmem.unmap = nv04_instmem_unmap; engine->instmem.flush = nv04_instmem_flush; - engine->fb.init = nv10_fb_init; - engine->fb.takedown = nv10_fb_takedown; - engine->fb.init_tile_region = nv10_fb_init_tile_region; - engine->fb.set_tile_region = nv10_fb_set_tile_region; - engine->fb.free_tile_region = nv10_fb_free_tile_region; engine->display.early_init = nv04_display_early_init; engine->display.late_takedown = nv04_display_late_takedown; engine->display.create = nv04_display_create; @@ -100,13 +90,6 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev) engine->pm.clocks_get = nv04_pm_clocks_get; engine->pm.clocks_pre = nv04_pm_clocks_pre; engine->pm.clocks_set = nv04_pm_clocks_set; - if (dev_priv->chipset == 0x1a || - dev_priv->chipset == 0x1f) - engine->vram.init = nv1a_fb_vram_init; - else - engine->vram.init = nv10_fb_vram_init; - engine->vram.takedown = nouveau_stub_takedown; - engine->vram.flags_valid = nouveau_mem_flags_valid; break; case 0x20: engine->instmem.init = nv04_instmem_init; @@ -118,11 +101,6 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev) engine->instmem.map = nv04_instmem_map; engine->instmem.unmap = nv04_instmem_unmap; engine->instmem.flush = nv04_instmem_flush; - engine->fb.init = nv20_fb_init; - engine->fb.takedown = nv20_fb_takedown; - engine->fb.init_tile_region = nv20_fb_init_tile_region; - engine->fb.set_tile_region = nv20_fb_set_tile_region; - engine->fb.free_tile_region = nv20_fb_free_tile_region; engine->display.early_init = nv04_display_early_init; engine->display.late_takedown = nv04_display_late_takedown; engine->display.create = nv04_display_create; @@ -132,9 +110,6 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev) engine->pm.clocks_get = nv04_pm_clocks_get; engine->pm.clocks_pre = nv04_pm_clocks_pre; engine->pm.clocks_set = nv04_pm_clocks_set; - engine->vram.init = nv20_fb_vram_init; - engine->vram.takedown = nouveau_stub_takedown; - engine->vram.flags_valid = nouveau_mem_flags_valid; break; case 0x30: engine->instmem.init = nv04_instmem_init; @@ -146,11 +121,6 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev) engine->instmem.map = nv04_instmem_map; engine->instmem.unmap = nv04_instmem_unmap; engine->instmem.flush = nv04_instmem_flush; - engine->fb.init = nv30_fb_init; - engine->fb.takedown = nv30_fb_takedown; - engine->fb.init_tile_region = nv30_fb_init_tile_region; - engine->fb.set_tile_region = nv10_fb_set_tile_region; - engine->fb.free_tile_region = nv30_fb_free_tile_region; engine->display.early_init = nv04_display_early_init; engine->display.late_takedown = nv04_display_late_takedown; engine->display.create = nv04_display_create; @@ -162,9 +132,6 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev) engine->pm.clocks_set = nv04_pm_clocks_set; engine->pm.voltage_get = nouveau_voltage_gpio_get; engine->pm.voltage_set = nouveau_voltage_gpio_set; - engine->vram.init = nv20_fb_vram_init; - engine->vram.takedown = nouveau_stub_takedown; - engine->vram.flags_valid = nouveau_mem_flags_valid; break; case 0x40: case 0x60: @@ -177,11 +144,6 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev) engine->instmem.map = nv04_instmem_map; engine->instmem.unmap = nv04_instmem_unmap; engine->instmem.flush = nv04_instmem_flush; - engine->fb.init = nv40_fb_init; - engine->fb.takedown = nv40_fb_takedown; - engine->fb.init_tile_region = nv30_fb_init_tile_region; - engine->fb.set_tile_region = nv40_fb_set_tile_region; - engine->fb.free_tile_region = nv30_fb_free_tile_region; engine->display.early_init = nv04_display_early_init; engine->display.late_takedown = nv04_display_late_takedown; engine->display.create = nv04_display_create; @@ -196,9 +158,6 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev) engine->pm.temp_get = nv40_temp_get; engine->pm.pwm_get = nv40_pm_pwm_get; engine->pm.pwm_set = nv40_pm_pwm_set; - engine->vram.init = nv40_fb_vram_init; - engine->vram.takedown = nouveau_stub_takedown; - engine->vram.flags_valid = nouveau_mem_flags_valid; break; case 0x50: case 0x80: /* gotta love NVIDIA's consistency.. */ @@ -216,8 +175,6 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev) engine->instmem.flush = nv50_instmem_flush; else engine->instmem.flush = nv84_instmem_flush; - engine->fb.init = nv50_fb_init; - engine->fb.takedown = nv50_fb_takedown; engine->display.early_init = nv50_display_early_init; engine->display.late_takedown = nv50_display_late_takedown; engine->display.create = nv50_display_create; @@ -253,11 +210,6 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev) engine->pm.temp_get = nv40_temp_get; engine->pm.pwm_get = nv50_pm_pwm_get; engine->pm.pwm_set = nv50_pm_pwm_set; - engine->vram.init = nv50_vram_init; - engine->vram.takedown = nv50_vram_fini; - engine->vram.get = nv50_vram_new; - engine->vram.put = nv50_vram_del; - engine->vram.flags_valid = nv50_vram_flags_valid; break; case 0xc0: engine->instmem.init = nvc0_instmem_init; @@ -269,19 +221,12 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev) engine->instmem.map = nv50_instmem_map; engine->instmem.unmap = nv50_instmem_unmap; engine->instmem.flush = nv84_instmem_flush; - engine->fb.init = nvc0_fb_init; - engine->fb.takedown = nvc0_fb_takedown; engine->display.early_init = nv50_display_early_init; engine->display.late_takedown = nv50_display_late_takedown; engine->display.create = nv50_display_create; engine->display.destroy = nv50_display_destroy; engine->display.init = nv50_display_init; engine->display.fini = nv50_display_fini; - engine->vram.init = nvc0_vram_init; - engine->vram.takedown = nv50_vram_fini; - engine->vram.get = nvc0_vram_new; - engine->vram.put = nv50_vram_del; - engine->vram.flags_valid = nvc0_vram_flags_valid; engine->pm.temp_get = nv84_temp_get; engine->pm.clocks_get = nvc0_pm_clocks_get; engine->pm.clocks_pre = nvc0_pm_clocks_pre; @@ -301,19 +246,12 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev) engine->instmem.map = nv50_instmem_map; engine->instmem.unmap = nv50_instmem_unmap; engine->instmem.flush = nv84_instmem_flush; - engine->fb.init = nvc0_fb_init; - engine->fb.takedown = nvc0_fb_takedown; engine->display.early_init = nouveau_stub_init; engine->display.late_takedown = nouveau_stub_takedown; engine->display.create = nvd0_display_create; engine->display.destroy = nvd0_display_destroy; engine->display.init = nvd0_display_init; engine->display.fini = nvd0_display_fini; - engine->vram.init = nvc0_vram_init; - engine->vram.takedown = nv50_vram_fini; - engine->vram.get = nvc0_vram_new; - engine->vram.put = nv50_vram_del; - engine->vram.flags_valid = nvc0_vram_flags_valid; engine->pm.temp_get = nv84_temp_get; engine->pm.clocks_get = nvc0_pm_clocks_get; engine->pm.clocks_pre = nvc0_pm_clocks_pre; @@ -331,19 +269,12 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev) engine->instmem.map = nv50_instmem_map; engine->instmem.unmap = nv50_instmem_unmap; engine->instmem.flush = nv84_instmem_flush; - engine->fb.init = nvc0_fb_init; - engine->fb.takedown = nvc0_fb_takedown; engine->display.early_init = nouveau_stub_init; engine->display.late_takedown = nouveau_stub_takedown; engine->display.create = nvd0_display_create; engine->display.destroy = nvd0_display_destroy; engine->display.init = nvd0_display_init; engine->display.fini = nvd0_display_fini; - engine->vram.init = nvc0_vram_init; - engine->vram.takedown = nv50_vram_fini; - engine->vram.get = nvc0_vram_new; - engine->vram.put = nv50_vram_del; - engine->vram.flags_valid = nvc0_vram_flags_valid; break; default: NV_ERROR(dev, "NV%02x unsupported\n", dev_priv->chipset); @@ -488,18 +419,9 @@ nouveau_card_init(struct drm_device *dev) nv_mask(dev, 0x00088080, 0x00000800, 0x00000000); } - /* PFB */ - ret = engine->fb.init(dev); - if (ret) - goto out_bios; - - ret = engine->vram.init(dev); - if (ret) - goto out_fb; - ret = nouveau_gpuobj_init(dev); if (ret) - goto out_vram; + goto out_bios; ret = engine->instmem.init(dev); if (ret) @@ -734,10 +656,6 @@ out_instmem: engine->instmem.takedown(dev); out_gpuobj: nouveau_gpuobj_takedown(dev); -out_vram: - engine->vram.takedown(dev); -out_fb: - engine->fb.takedown(dev); out_bios: nouveau_bios_takedown(dev); out_display_early: @@ -788,9 +706,6 @@ static void nouveau_card_takedown(struct drm_device *dev) engine->instmem.takedown(dev); nouveau_gpuobj_takedown(dev); - engine->vram.takedown(dev); - engine->fb.takedown(dev); - nouveau_bios_takedown(dev); engine->display.late_takedown(dev); diff --git a/drivers/gpu/drm/nouveau/nouveau_util.c b/drivers/gpu/drm/nouveau/nouveau_util.c index e51b51503baa..6bff634c95fe 100644 --- a/drivers/gpu/drm/nouveau/nouveau_util.c +++ b/drivers/gpu/drm/nouveau/nouveau_util.c @@ -26,50 +26,11 @@ */ #include - #include "nouveau_util.h" -static DEFINE_RATELIMIT_STATE(nouveau_ratelimit_state, 3 * HZ, 20); - -void -nouveau_bitfield_print(const struct nouveau_bitfield *bf, u32 value) -{ - while (bf->name) { - if (value & bf->mask) { - printk(" %s", bf->name); - value &= ~bf->mask; - } - - bf++; - } - - if (value) - printk(" (unknown bits 0x%08x)", value); -} +#include -const struct nouveau_enum * -nouveau_enum_find(const struct nouveau_enum *en, u32 value) -{ - while (en->name) { - if (en->value == value) - return en; - en++; - } - - return NULL; -} - -void -nouveau_enum_print(const struct nouveau_enum *en, u32 value) -{ - en = nouveau_enum_find(en, value); - if (en) { - printk("%s", en->name); - return; - } - - printk("(unknown enum 0x%08x)", value); -} +static DEFINE_RATELIMIT_STATE(nouveau_ratelimit_state, 3 * HZ, 20); int nouveau_ratelimit(void) diff --git a/drivers/gpu/drm/nouveau/nouveau_util.h b/drivers/gpu/drm/nouveau/nouveau_util.h index b97719fbb739..114293758f8c 100644 --- a/drivers/gpu/drm/nouveau/nouveau_util.h +++ b/drivers/gpu/drm/nouveau/nouveau_util.h @@ -28,21 +28,7 @@ #ifndef __NOUVEAU_UTIL_H__ #define __NOUVEAU_UTIL_H__ -struct nouveau_bitfield { - u32 mask; - const char *name; -}; - -struct nouveau_enum { - u32 value; - const char *name; - void *data; -}; - -void nouveau_bitfield_print(const struct nouveau_bitfield *, u32 value); -void nouveau_enum_print(const struct nouveau_enum *, u32 value); -const struct nouveau_enum * -nouveau_enum_find(const struct nouveau_enum *, u32 value); +#include int nouveau_ratelimit(void); diff --git a/drivers/gpu/drm/nouveau/nv50_evo.c b/drivers/gpu/drm/nouveau/nv50_evo.c index 5731cb3df67f..7a1424243665 100644 --- a/drivers/gpu/drm/nouveau/nv50_evo.c +++ b/drivers/gpu/drm/nouveau/nv50_evo.c @@ -300,24 +300,24 @@ nv50_evo_create(struct drm_device *dev) /* create some default objects for the scanout memtypes we support */ ret = nv50_evo_dmaobj_new(disp->master, NvEvoVRAM, 0x0000, - 0, dev_priv->vram_size, NULL); + 0, nvfb_vram_size(dev), NULL); if (ret) goto err; ret = nv50_evo_dmaobj_new(disp->master, NvEvoVRAM_LP, 0x80000000, - 0, dev_priv->vram_size, NULL); + 0, nvfb_vram_size(dev), NULL); if (ret) goto err; ret = nv50_evo_dmaobj_new(disp->master, NvEvoFB32, 0x80000000 | (dev_priv->chipset < 0xc0 ? 0x7a00 : 0xfe00), - 0, dev_priv->vram_size, NULL); + 0, nvfb_vram_size(dev), NULL); if (ret) goto err; ret = nv50_evo_dmaobj_new(disp->master, NvEvoFB16, 0x80000000 | (dev_priv->chipset < 0xc0 ? 0x7000 : 0xfe00), - 0, dev_priv->vram_size, NULL); + 0, nvfb_vram_size(dev), NULL); if (ret) goto err; @@ -352,21 +352,21 @@ nv50_evo_create(struct drm_device *dev) goto err; ret = nv50_evo_dmaobj_new(dispc->sync, NvEvoVRAM_LP, 0x80000000, - 0, dev_priv->vram_size, NULL); + 0, nvfb_vram_size(dev), NULL); if (ret) goto err; ret = nv50_evo_dmaobj_new(dispc->sync, NvEvoFB32, 0x80000000 | (dev_priv->chipset < 0xc0 ? 0x7a00 : 0xfe00), - 0, dev_priv->vram_size, NULL); + 0, nvfb_vram_size(dev), NULL); if (ret) goto err; ret = nv50_evo_dmaobj_new(dispc->sync, NvEvoFB16, 0x80000000 | (dev_priv->chipset < 0xc0 ? 0x7000 : 0xfe00), - 0, dev_priv->vram_size, NULL); + 0, nvfb_vram_size(dev), NULL); if (ret) goto err; diff --git a/drivers/gpu/drm/nouveau/nv50_pm.c b/drivers/gpu/drm/nouveau/nv50_pm.c index 378ca8ca9d6a..142cd4e83767 100644 --- a/drivers/gpu/drm/nouveau/nv50_pm.c +++ b/drivers/gpu/drm/nouveau/nv50_pm.c @@ -471,17 +471,16 @@ mclk_mrg(struct nouveau_mem_exec_func *exec, int mr) static void mclk_mrs(struct nouveau_mem_exec_func *exec, int mr, u32 data) { - struct drm_nouveau_private *dev_priv = exec->dev->dev_private; struct nv50_pm_state *info = exec->priv; struct hwsq_ucode *hwsq = &info->mclk_hwsq; if (mr <= 1) { - if (dev_priv->vram_rank_B) + if (nvfb_vram_rank_B(exec->dev)) hwsq_wr32(hwsq, 0x1002c8 + ((mr - 0) * 4), data); hwsq_wr32(hwsq, 0x1002c0 + ((mr - 0) * 4), data); } else if (mr <= 3) { - if (dev_priv->vram_rank_B) + if (nvfb_vram_rank_B(exec->dev)) hwsq_wr32(hwsq, 0x1002e8 + ((mr - 2) * 4), data); hwsq_wr32(hwsq, 0x1002e0 + ((mr - 2) * 4), data); } diff --git a/drivers/gpu/drm/nouveau/nva3_pm.c b/drivers/gpu/drm/nouveau/nva3_pm.c index 847c616de12f..2f7ee50440ae 100644 --- a/drivers/gpu/drm/nouveau/nva3_pm.c +++ b/drivers/gpu/drm/nouveau/nva3_pm.c @@ -361,15 +361,13 @@ mclk_mrg(struct nouveau_mem_exec_func *exec, int mr) static void mclk_mrs(struct nouveau_mem_exec_func *exec, int mr, u32 data) { - struct drm_nouveau_private *dev_priv = exec->dev->dev_private; - if (mr <= 1) { - if (dev_priv->vram_rank_B) + if (nvfb_vram_rank_B(exec->dev)) nv_wr32(exec->dev, 0x1002c8 + ((mr - 0) * 4), data); nv_wr32(exec->dev, 0x1002c0 + ((mr - 0) * 4), data); } else if (mr <= 3) { - if (dev_priv->vram_rank_B) + if (nvfb_vram_rank_B(exec->dev)) nv_wr32(exec->dev, 0x1002e8 + ((mr - 2) * 4), data); nv_wr32(exec->dev, 0x1002e0 + ((mr - 2) * 4), data); } diff --git a/drivers/gpu/drm/nouveau/nvc0_pm.c b/drivers/gpu/drm/nouveau/nvc0_pm.c index 4a21a7264c3c..a14711c25176 100644 --- a/drivers/gpu/drm/nouveau/nvc0_pm.c +++ b/drivers/gpu/drm/nouveau/nvc0_pm.c @@ -459,8 +459,7 @@ static u32 mclk_mrg(struct nouveau_mem_exec_func *exec, int mr) { struct drm_device *dev = exec->dev; - struct drm_nouveau_private *dev_priv = dev->dev_private; - if (dev_priv->vram_type != NV_MEM_TYPE_GDDR5) { + if (nvfb_vram_type(dev) != NV_MEM_TYPE_GDDR5) { if (mr <= 1) return nv_rd32(dev, 0x10f300 + ((mr - 0) * 4)); return nv_rd32(dev, 0x10f320 + ((mr - 2) * 4)); @@ -478,16 +477,15 @@ static void mclk_mrs(struct nouveau_mem_exec_func *exec, int mr, u32 data) { struct drm_device *dev = exec->dev; - struct drm_nouveau_private *dev_priv = dev->dev_private; - if (dev_priv->vram_type != NV_MEM_TYPE_GDDR5) { + if (nvfb_vram_type(dev) != NV_MEM_TYPE_GDDR5) { if (mr <= 1) { nv_wr32(dev, 0x10f300 + ((mr - 0) * 4), data); - if (dev_priv->vram_rank_B) + if (nvfb_vram_rank_B(dev)) nv_wr32(dev, 0x10f308 + ((mr - 0) * 4), data); } else if (mr <= 3) { nv_wr32(dev, 0x10f320 + ((mr - 2) * 4), data); - if (dev_priv->vram_rank_B) + if (nvfb_vram_rank_B(dev)) nv_wr32(dev, 0x10f328 + ((mr - 2) * 4), data); } } else { diff --git a/drivers/gpu/drm/nouveau/nvd0_display.c b/drivers/gpu/drm/nouveau/nvd0_display.c index d26dd02f3d13..8d9fc00718f0 100644 --- a/drivers/gpu/drm/nouveau/nvd0_display.c +++ b/drivers/gpu/drm/nouveau/nvd0_display.c @@ -2077,7 +2077,7 @@ nvd0_display_create(struct drm_device *dev) nv_wo32(disp->mem, dmao + 0x20, 0x00000049); nv_wo32(disp->mem, dmao + 0x24, 0x00000000); - nv_wo32(disp->mem, dmao + 0x28, (dev_priv->vram_size - 1) >> 8); + nv_wo32(disp->mem, dmao + 0x28, (nvfb_vram_size(dev) - 1) >> 8); nv_wo32(disp->mem, dmao + 0x2c, 0x00000000); nv_wo32(disp->mem, dmao + 0x30, 0x00000000); nv_wo32(disp->mem, dmao + 0x34, 0x00000000); @@ -2087,7 +2087,7 @@ nvd0_display_create(struct drm_device *dev) nv_wo32(disp->mem, dmao + 0x40, 0x00000009); nv_wo32(disp->mem, dmao + 0x44, 0x00000000); - nv_wo32(disp->mem, dmao + 0x48, (dev_priv->vram_size - 1) >> 8); + nv_wo32(disp->mem, dmao + 0x48, (nvfb_vram_size(dev) - 1) >> 8); nv_wo32(disp->mem, dmao + 0x4c, 0x00000000); nv_wo32(disp->mem, dmao + 0x50, 0x00000000); nv_wo32(disp->mem, dmao + 0x54, 0x00000000); @@ -2097,7 +2097,7 @@ nvd0_display_create(struct drm_device *dev) nv_wo32(disp->mem, dmao + 0x60, 0x0fe00009); nv_wo32(disp->mem, dmao + 0x64, 0x00000000); - nv_wo32(disp->mem, dmao + 0x68, (dev_priv->vram_size - 1) >> 8); + nv_wo32(disp->mem, dmao + 0x68, (nvfb_vram_size(dev) - 1) >> 8); nv_wo32(disp->mem, dmao + 0x6c, 0x00000000); nv_wo32(disp->mem, dmao + 0x70, 0x00000000); nv_wo32(disp->mem, dmao + 0x74, 0x00000000); -- cgit v1.2.3 From 77145f1cbdf8d28b46ff8070ca749bad821e0774 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Tue, 31 Jul 2012 16:16:21 +1000 Subject: drm/nouveau: port remainder of drm code, and rip out compat layer v2: Ben Skeggs - fill in nouveau_pm.dev to prevent oops - fix ppc issues (build + OF shadow) Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/Makefile | 47 +- .../gpu/drm/nouveau/core/include/subdev/timer.h | 4 +- drivers/gpu/drm/nouveau/core/subdev/bios/base.c | 30 +- drivers/gpu/drm/nouveau/nouveau_backlight.c | 16 +- drivers/gpu/drm/nouveau/nouveau_bios.c | 270 +++++---- drivers/gpu/drm/nouveau/nouveau_bios.h | 25 +- drivers/gpu/drm/nouveau/nouveau_bo.c | 10 +- drivers/gpu/drm/nouveau/nouveau_calc.c | 18 +- drivers/gpu/drm/nouveau/nouveau_compat.c | 609 --------------------- drivers/gpu/drm/nouveau/nouveau_compat.h | 141 ----- drivers/gpu/drm/nouveau/nouveau_connector.c | 129 +++-- drivers/gpu/drm/nouveau/nouveau_display.c | 214 ++++++-- drivers/gpu/drm/nouveau/nouveau_display.h | 94 ++++ drivers/gpu/drm/nouveau/nouveau_dp.c | 74 ++- drivers/gpu/drm/nouveau/nouveau_drm.c | 227 ++++++-- drivers/gpu/drm/nouveau/nouveau_drm.h | 27 +- drivers/gpu/drm/nouveau/nouveau_drv.c | 353 ------------ drivers/gpu/drm/nouveau/nouveau_drv.h | 551 ------------------- drivers/gpu/drm/nouveau/nouveau_fb.h | 47 -- drivers/gpu/drm/nouveau/nouveau_fbcon.c | 27 +- drivers/gpu/drm/nouveau/nouveau_fbcon.h | 2 +- drivers/gpu/drm/nouveau/nouveau_gem.c | 2 +- drivers/gpu/drm/nouveau/nouveau_hdmi.c | 41 +- drivers/gpu/drm/nouveau/nouveau_hw.c | 150 ++--- drivers/gpu/drm/nouveau/nouveau_hw.h | 88 +-- drivers/gpu/drm/nouveau/nouveau_irq.c | 130 ++--- drivers/gpu/drm/nouveau/nouveau_irq.h | 11 + drivers/gpu/drm/nouveau/nouveau_mem.c | 119 ++-- drivers/gpu/drm/nouveau/nouveau_perf.c | 63 ++- drivers/gpu/drm/nouveau/nouveau_pm.c | 254 +++++---- drivers/gpu/drm/nouveau/nouveau_pm.h | 194 +++++++ drivers/gpu/drm/nouveau/nouveau_prime.c | 8 +- drivers/gpu/drm/nouveau/nouveau_revcompat.c | 22 - drivers/gpu/drm/nouveau/nouveau_revcompat.h | 12 - drivers/gpu/drm/nouveau/nouveau_state.c | 508 ----------------- drivers/gpu/drm/nouveau/nouveau_temp.c | 56 +- drivers/gpu/drm/nouveau/nouveau_ttm.c | 2 +- drivers/gpu/drm/nouveau/nouveau_ttm.h | 4 + drivers/gpu/drm/nouveau/nouveau_vga.c | 98 ++++ drivers/gpu/drm/nouveau/nouveau_vga.h | 8 + drivers/gpu/drm/nouveau/nouveau_volt.c | 48 +- drivers/gpu/drm/nouveau/nv04_crtc.c | 87 +-- drivers/gpu/drm/nouveau/nv04_cursor.c | 6 +- drivers/gpu/drm/nouveau/nv04_dac.c | 116 ++-- drivers/gpu/drm/nouveau/nv04_dfp.c | 54 +- drivers/gpu/drm/nouveau/nv04_display.c | 26 +- drivers/gpu/drm/nouveau/nv04_display.h | 68 +++ drivers/gpu/drm/nouveau/nv04_fbcon.c | 8 +- drivers/gpu/drm/nouveau/nv04_pm.c | 36 +- drivers/gpu/drm/nouveau/nv04_tv.c | 25 +- drivers/gpu/drm/nouveau/nv17_tv.c | 79 +-- drivers/gpu/drm/nouveau/nv17_tv.h | 6 +- drivers/gpu/drm/nouveau/nv17_tv_modes.c | 2 +- drivers/gpu/drm/nouveau/nv40_pm.c | 150 ++--- drivers/gpu/drm/nouveau/nv50_crtc.c | 72 ++- drivers/gpu/drm/nouveau/nv50_cursor.c | 32 +- drivers/gpu/drm/nouveau/nv50_dac.c | 83 +-- drivers/gpu/drm/nouveau/nv50_display.c | 368 +++++++------ drivers/gpu/drm/nouveau/nv50_display.h | 24 +- drivers/gpu/drm/nouveau/nv50_evo.c | 96 ++-- drivers/gpu/drm/nouveau/nv50_fbcon.c | 8 +- drivers/gpu/drm/nouveau/nv50_fence.c | 7 +- drivers/gpu/drm/nouveau/nv50_pm.c | 201 ++++--- drivers/gpu/drm/nouveau/nv50_sor.c | 103 ++-- drivers/gpu/drm/nouveau/nv84_fence.c | 7 +- drivers/gpu/drm/nouveau/nva3_pm.c | 272 ++++----- drivers/gpu/drm/nouveau/nvc0_fbcon.c | 8 +- drivers/gpu/drm/nouveau/nvc0_fence.c | 10 +- drivers/gpu/drm/nouveau/nvc0_pm.c | 174 +++--- drivers/gpu/drm/nouveau/nvd0_display.c | 408 ++++++++------ 70 files changed, 3095 insertions(+), 4174 deletions(-) delete mode 100644 drivers/gpu/drm/nouveau/nouveau_compat.c delete mode 100644 drivers/gpu/drm/nouveau/nouveau_compat.h create mode 100644 drivers/gpu/drm/nouveau/nouveau_display.h delete mode 100644 drivers/gpu/drm/nouveau/nouveau_drv.c delete mode 100644 drivers/gpu/drm/nouveau/nouveau_drv.h delete mode 100644 drivers/gpu/drm/nouveau/nouveau_fb.h create mode 100644 drivers/gpu/drm/nouveau/nouveau_irq.h delete mode 100644 drivers/gpu/drm/nouveau/nouveau_revcompat.c delete mode 100644 drivers/gpu/drm/nouveau/nouveau_revcompat.h delete mode 100644 drivers/gpu/drm/nouveau/nouveau_state.c create mode 100644 drivers/gpu/drm/nouveau/nouveau_vga.c create mode 100644 drivers/gpu/drm/nouveau/nouveau_vga.h (limited to 'drivers/gpu/drm/nouveau/nva3_pm.c') diff --git a/drivers/gpu/drm/nouveau/Makefile b/drivers/gpu/drm/nouveau/Makefile index 72f1a1c2e56f..fe14f4bffde1 100644 --- a/drivers/gpu/drm/nouveau/Makefile +++ b/drivers/gpu/drm/nouveau/Makefile @@ -145,47 +145,17 @@ nouveau-y += core/engine/software/nv50.o nouveau-y += core/engine/software/nvc0.o nouveau-y += core/engine/vp/nv84.o -# drm/compat - will go away -nouveau-y += nouveau_compat.o nouveau_revcompat.o - # drm/core nouveau-y += nouveau_drm.o nouveau_chan.o nouveau_dma.o nouveau_fence.o -nouveau-y += nouveau_agp.o +nouveau-y += nouveau_irq.o nouveau_vga.o nouveau_agp.o nouveau-y += nouveau_ttm.o nouveau_sgdma.o nouveau_bo.o nouveau_gem.o - -nouveau-y += nouveau_abi16.o +nouveau-y += nouveau_prime.o nouveau_abi16.o nouveau-y += nv04_fence.o nv10_fence.o nv50_fence.o nv84_fence.o nvc0_fence.o -# drm/kms/common -nouveau-y += nouveau_fbcon.o - -# drm/kms/nv04:nv50 -nouveau-y += nv04_fbcon.o - -# drm/kms/nv50:nvd9 -nouveau-y += nv50_fbcon.o nvc0_fbcon.o - -# drm/kms/nvd9- - -# other random bits -nouveau-$(CONFIG_COMPAT) += nouveau_ioc32.o -nouveau-$(CONFIG_ACPI) += nouveau_acpi.o -nouveau-$(CONFIG_DRM_NOUVEAU_BACKLIGHT) += nouveau_backlight.o - -## -## unported bits below -## - -# drm/core -nouveau-y += nouveau_drv.o nouveau_state.o nouveau_irq.o -nouveau-y += nouveau_prime.o - -# drm/kms/bios -nouveau-y += nouveau_bios.o - -# drm/kms/common -nouveau-y += nouveau_display.o nouveau_connector.o -nouveau-y += nouveau_hdmi.o nouveau_dp.o +# drm/kms +nouveau-y += nouveau_bios.o nouveau_fbcon.o nouveau_display.o +nouveau-y += nouveau_connector.o nouveau_hdmi.o nouveau_dp.o +nouveau-y += nv04_fbcon.o nv50_fbcon.o nvc0_fbcon.o # drm/kms/nv04:nv50 nouveau-y += nouveau_hw.o nouveau_calc.o @@ -202,4 +172,9 @@ nouveau-y += nouveau_pm.o nouveau_volt.o nouveau_perf.o nouveau_temp.o nouveau-y += nv04_pm.o nv40_pm.o nv50_pm.o nva3_pm.o nvc0_pm.o nouveau-y += nouveau_mem.o +# other random bits +nouveau-$(CONFIG_COMPAT) += nouveau_ioc32.o +nouveau-$(CONFIG_ACPI) += nouveau_acpi.o +nouveau-$(CONFIG_DRM_NOUVEAU_BACKLIGHT) += nouveau_backlight.o + obj-$(CONFIG_DRM_NOUVEAU)+= nouveau.o diff --git a/drivers/gpu/drm/nouveau/core/include/subdev/timer.h b/drivers/gpu/drm/nouveau/core/include/subdev/timer.h index d971b83caebe..49bff901544c 100644 --- a/drivers/gpu/drm/nouveau/core/include/subdev/timer.h +++ b/drivers/gpu/drm/nouveau/core/include/subdev/timer.h @@ -20,8 +20,8 @@ void nouveau_timer_alarm(void *, u32 nsec, struct nouveau_alarm *); nouveau_timer_wait_eq((o), NV_WAIT_DEFAULT, (a), (m), (v)) #define nv_wait_ne(o,a,m,v) \ nouveau_timer_wait_ne((o), NV_WAIT_DEFAULT, (a), (m), (v)) -#define nv_wait_cb(o,a,m,v) \ - nouveau_timer_wait_cb((o), NV_WAIT_DEFAULT, (a), (m), (v)) +#define nv_wait_cb(o,c,d) \ + nouveau_timer_wait_cb((o), NV_WAIT_DEFAULT, (c), (d)) struct nouveau_timer { struct nouveau_subdev base; diff --git a/drivers/gpu/drm/nouveau/core/subdev/bios/base.c b/drivers/gpu/drm/nouveau/core/subdev/bios/base.c index e8e46eca947b..2fbb6df697cd 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/bios/base.c +++ b/drivers/gpu/drm/nouveau/core/subdev/bios/base.c @@ -56,6 +56,31 @@ nvbios_findstr(const u8 *data, int size, const char *str, int len) return 0; } +#if defined(__powerpc__) +static void +nouveau_bios_shadow_of(struct nouveau_bios *bios) +{ + struct pci_dev *pdev = nv_device(bios)->pdev; + struct device_node *dn; + const u32 *data; + int size, i; + + dn = pci_device_to_OF_node(pdev); + if (!dn) { + nv_info(bios, "Unable to get the OF node\n"); + return; + } + + data = of_get_property(dn, "NVDA,BMP", &size); + if (data) { + bios->size = size; + bios->data = kmalloc(bios->size, GFP_KERNEL); + if (bios->data) + memcpy(bios->data, data, size); + } +} +#endif + static void nouveau_bios_shadow_pramin(struct nouveau_bios *bios) { @@ -221,7 +246,7 @@ nouveau_bios_score(struct nouveau_bios *bios, const bool writeable) } struct methods { - const char desc[8]; + const char desc[16]; void (*shadow)(struct nouveau_bios *); const bool rw; int score; @@ -233,6 +258,9 @@ static int nouveau_bios_shadow(struct nouveau_bios *bios) { struct methods shadow_methods[] = { +#if defined(__powerpc__) + { "OpenFirmware", nouveau_bios_shadow_of, true, 0, 0, NULL }, +#endif { "PRAMIN", nouveau_bios_shadow_pramin, true, 0, 0, NULL }, { "PROM", nouveau_bios_shadow_prom, false, 0, 0, NULL }, { "ACPI", nouveau_bios_shadow_acpi, true, 0, 0, NULL }, diff --git a/drivers/gpu/drm/nouveau/nouveau_backlight.c b/drivers/gpu/drm/nouveau/nouveau_backlight.c index 5c4cc7a2117a..f65b20a375f6 100644 --- a/drivers/gpu/drm/nouveau/nouveau_backlight.c +++ b/drivers/gpu/drm/nouveau/nouveau_backlight.c @@ -71,7 +71,7 @@ static const struct backlight_ops nv40_bl_ops = { static int nv40_backlight_init(struct drm_connector *connector) { - struct nouveau_drm *drm = nouveau_newpriv(connector->dev); + struct nouveau_drm *drm = nouveau_drm(connector->dev); struct nouveau_device *device = nv_device(drm->device); struct backlight_properties props; struct backlight_device *bd; @@ -95,7 +95,7 @@ static int nv50_get_intensity(struct backlight_device *bd) { struct nouveau_encoder *nv_encoder = bl_get_data(bd); - struct nouveau_drm *drm = nouveau_newpriv(nv_encoder->base.base.dev); + struct nouveau_drm *drm = nouveau_drm(nv_encoder->base.base.dev); struct nouveau_device *device = nv_device(drm->device); int or = nv_encoder->or; u32 div = 1025; @@ -110,7 +110,7 @@ static int nv50_set_intensity(struct backlight_device *bd) { struct nouveau_encoder *nv_encoder = bl_get_data(bd); - struct nouveau_drm *drm = nouveau_newpriv(nv_encoder->base.base.dev); + struct nouveau_drm *drm = nouveau_drm(nv_encoder->base.base.dev); struct nouveau_device *device = nv_device(drm->device); int or = nv_encoder->or; u32 div = 1025; @@ -131,7 +131,7 @@ static int nva3_get_intensity(struct backlight_device *bd) { struct nouveau_encoder *nv_encoder = bl_get_data(bd); - struct nouveau_drm *drm = nouveau_newpriv(nv_encoder->base.base.dev); + struct nouveau_drm *drm = nouveau_drm(nv_encoder->base.base.dev); struct nouveau_device *device = nv_device(drm->device); int or = nv_encoder->or; u32 div, val; @@ -149,7 +149,7 @@ static int nva3_set_intensity(struct backlight_device *bd) { struct nouveau_encoder *nv_encoder = bl_get_data(bd); - struct nouveau_drm *drm = nouveau_newpriv(nv_encoder->base.base.dev); + struct nouveau_drm *drm = nouveau_drm(nv_encoder->base.base.dev); struct nouveau_device *device = nv_device(drm->device); int or = nv_encoder->or; u32 div, val; @@ -175,7 +175,7 @@ static const struct backlight_ops nva3_bl_ops = { static int nv50_backlight_init(struct drm_connector *connector) { - struct nouveau_drm *drm = nouveau_newpriv(connector->dev); + struct nouveau_drm *drm = nouveau_drm(connector->dev); struct nouveau_device *device = nv_device(drm->device); struct nouveau_encoder *nv_encoder; struct backlight_properties props; @@ -216,7 +216,7 @@ nv50_backlight_init(struct drm_connector *connector) int nouveau_backlight_init(struct drm_device *dev) { - struct nouveau_drm *drm = nouveau_newpriv(dev); + struct nouveau_drm *drm = nouveau_drm(dev); struct nouveau_device *device = nv_device(drm->device); struct drm_connector *connector; @@ -250,7 +250,7 @@ nouveau_backlight_init(struct drm_device *dev) void nouveau_backlight_exit(struct drm_device *dev) { - struct nouveau_drm *drm = nouveau_newpriv(dev); + struct nouveau_drm *drm = nouveau_drm(dev); if (drm->backlight) { backlight_device_unregister(drm->backlight); diff --git a/drivers/gpu/drm/nouveau/nouveau_bios.c b/drivers/gpu/drm/nouveau/nouveau_bios.c index b83c672a945a..f6b7fa39d312 100644 --- a/drivers/gpu/drm/nouveau/nouveau_bios.c +++ b/drivers/gpu/drm/nouveau/nouveau_bios.c @@ -22,9 +22,11 @@ * SOFTWARE. */ +#include + #include "drmP.h" -#define NV_DEBUG_NOTRACE -#include "nouveau_drv.h" +#include "nouveau_drm.h" +#include "nouveau_reg.h" #include "nouveau_hw.h" #include "nouveau_encoder.h" @@ -94,7 +96,9 @@ static void run_digital_op_script(struct drm_device *dev, uint16_t scriptptr, struct dcb_output *dcbent, int head, bool dl) { - NV_TRACE(dev, "0x%04X: Parsing digital output script table\n", + struct nouveau_drm *drm = nouveau_drm(dev); + + NV_INFO(drm, "0x%04X: Parsing digital output script table\n", scriptptr); NVWriteVgaCrtc(dev, 0, NV_CIO_CRE_44, head ? NV_CIO_CRE_44_HEADB : NV_CIO_CRE_44_HEADA); @@ -105,8 +109,8 @@ run_digital_op_script(struct drm_device *dev, uint16_t scriptptr, static int call_lvds_manufacturer_script(struct drm_device *dev, struct dcb_output *dcbent, int head, enum LVDS_script script) { - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nvbios *bios = &dev_priv->vbios; + struct nouveau_drm *drm = nouveau_drm(dev); + struct nvbios *bios = &drm->vbios; uint8_t sub = bios->data[bios->fp.xlated_entry + script] + (bios->fp.link_c_increment && dcbent->or & DCB_OUTPUT_C ? 1 : 0); uint16_t scriptofs = ROM16(bios->data[bios->init_script_tbls_ptr + sub * 2]); @@ -142,8 +146,8 @@ static int run_lvds_table(struct drm_device *dev, struct dcb_output *dcbent, int * conf byte. These tables are similar to the TMDS tables, consisting * of a list of pxclks and script pointers. */ - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nvbios *bios = &dev_priv->vbios; + struct nouveau_drm *drm = nouveau_drm(dev); + struct nvbios *bios = &drm->vbios; unsigned int outputset = (dcbent->or == 4) ? 1 : 0; uint16_t scriptptr = 0, clktable; @@ -188,14 +192,14 @@ static int run_lvds_table(struct drm_device *dev, struct dcb_output *dcbent, int clktable = ROM16(bios->data[clktable]); if (!clktable) { - NV_ERROR(dev, "Pixel clock comparison table not found\n"); + NV_ERROR(drm, "Pixel clock comparison table not found\n"); return -ENOENT; } scriptptr = clkcmptable(bios, clktable, pxclk); } if (!scriptptr) { - NV_ERROR(dev, "LVDS output init script not found\n"); + NV_ERROR(drm, "LVDS output init script not found\n"); return -ENOENT; } run_digital_op_script(dev, scriptptr, dcbent, head, bios->fp.dual_link); @@ -211,8 +215,9 @@ int call_lvds_script(struct drm_device *dev, struct dcb_output *dcbent, int head * This acts as the demux */ - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nvbios *bios = &dev_priv->vbios; + struct nouveau_drm *drm = nouveau_drm(dev); + struct nouveau_device *device = nv_device(drm->device); + struct nvbios *bios = &drm->vbios; uint8_t lvds_ver = bios->data[bios->fp.lvdsmanufacturerpointer]; uint32_t sel_clk_binding, sel_clk; int ret; @@ -231,10 +236,10 @@ int call_lvds_script(struct drm_device *dev, struct dcb_output *dcbent, int head if (script == LVDS_RESET && bios->fp.power_off_for_reset) call_lvds_script(dev, dcbent, head, LVDS_PANEL_OFF, pxclk); - NV_TRACE(dev, "Calling LVDS script %d:\n", script); + NV_INFO(drm, "Calling LVDS script %d:\n", script); /* don't let script change pll->head binding */ - sel_clk_binding = nv_rd32(dev, NV_PRAMDAC_SEL_CLK) & 0x50000; + sel_clk_binding = nv_rd32(device, NV_PRAMDAC_SEL_CLK) & 0x50000; if (lvds_ver < 0x30) ret = call_lvds_manufacturer_script(dev, dcbent, head, script); @@ -246,7 +251,7 @@ int call_lvds_script(struct drm_device *dev, struct dcb_output *dcbent, int head sel_clk = NVReadRAMDAC(dev, 0, NV_PRAMDAC_SEL_CLK) & ~0x50000; NVWriteRAMDAC(dev, 0, NV_PRAMDAC_SEL_CLK, sel_clk | sel_clk_binding); /* some scripts set a value in NV_PBUS_POWERCTRL_2 and break video overlay */ - nv_wr32(dev, NV_PBUS_POWERCTRL_2, 0); + nv_wr32(device, NV_PBUS_POWERCTRL_2, 0); return ret; } @@ -264,12 +269,13 @@ static int parse_lvds_manufacturer_table_header(struct drm_device *dev, struct n * the maximum number of records that can be held in the table. */ + struct nouveau_drm *drm = nouveau_drm(dev); uint8_t lvds_ver, headerlen, recordlen; memset(lth, 0, sizeof(struct lvdstableheader)); if (bios->fp.lvdsmanufacturerpointer == 0x0) { - NV_ERROR(dev, "Pointer to LVDS manufacturer table invalid\n"); + NV_ERROR(drm, "Pointer to LVDS manufacturer table invalid\n"); return -EINVAL; } @@ -283,7 +289,7 @@ static int parse_lvds_manufacturer_table_header(struct drm_device *dev, struct n case 0x30: /* NV4x */ headerlen = bios->data[bios->fp.lvdsmanufacturerpointer + 1]; if (headerlen < 0x1f) { - NV_ERROR(dev, "LVDS table header not understood\n"); + NV_ERROR(drm, "LVDS table header not understood\n"); return -EINVAL; } recordlen = bios->data[bios->fp.lvdsmanufacturerpointer + 2]; @@ -291,13 +297,13 @@ static int parse_lvds_manufacturer_table_header(struct drm_device *dev, struct n case 0x40: /* G80/G90 */ headerlen = bios->data[bios->fp.lvdsmanufacturerpointer + 1]; if (headerlen < 0x7) { - NV_ERROR(dev, "LVDS table header not understood\n"); + NV_ERROR(drm, "LVDS table header not understood\n"); return -EINVAL; } recordlen = bios->data[bios->fp.lvdsmanufacturerpointer + 2]; break; default: - NV_ERROR(dev, + NV_ERROR(drm, "LVDS table revision %d.%d not currently supported\n", lvds_ver >> 4, lvds_ver & 0xf); return -ENOSYS; @@ -313,7 +319,7 @@ static int parse_lvds_manufacturer_table_header(struct drm_device *dev, struct n static int get_fp_strap(struct drm_device *dev, struct nvbios *bios) { - struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_device *device = nouveau_dev(dev); /* * The fp strap is normally dictated by the "User Strap" in @@ -327,14 +333,15 @@ get_fp_strap(struct drm_device *dev, struct nvbios *bios) if (bios->major_version < 5 && bios->data[0x48] & 0x4) return NVReadVgaCrtc5758(dev, 0, 0xf) & 0xf; - if (dev_priv->card_type >= NV_50) - return (nv_rd32(dev, NV_PEXTDEV_BOOT_0) >> 24) & 0xf; + if (device->card_type >= NV_50) + return (nv_rd32(device, NV_PEXTDEV_BOOT_0) >> 24) & 0xf; else - return (nv_rd32(dev, NV_PEXTDEV_BOOT_0) >> 16) & 0xf; + return (nv_rd32(device, NV_PEXTDEV_BOOT_0) >> 16) & 0xf; } static int parse_fp_mode_table(struct drm_device *dev, struct nvbios *bios) { + struct nouveau_drm *drm = nouveau_drm(dev); uint8_t *fptable; uint8_t fptable_ver, headerlen = 0, recordlen, fpentries = 0xf, fpindex; int ret, ofs, fpstrapping; @@ -344,7 +351,7 @@ static int parse_fp_mode_table(struct drm_device *dev, struct nvbios *bios) /* Apple cards don't have the fp table; the laptops use DDC */ /* The table is also missing on some x86 IGPs */ #ifndef __powerpc__ - NV_ERROR(dev, "Pointer to flat panel table invalid\n"); + NV_ERROR(drm, "Pointer to flat panel table invalid\n"); #endif bios->digital_min_front_porch = 0x4b; return 0; @@ -383,7 +390,7 @@ static int parse_fp_mode_table(struct drm_device *dev, struct nvbios *bios) ofs = -7; break; default: - NV_ERROR(dev, + NV_ERROR(drm, "FP table revision %d.%d not currently supported\n", fptable_ver >> 4, fptable_ver & 0xf); return -ENOSYS; @@ -402,7 +409,7 @@ static int parse_fp_mode_table(struct drm_device *dev, struct nvbios *bios) bios->fp.xlatwidth = lth.recordlen; } if (bios->fp.fpxlatetableptr == 0x0) { - NV_ERROR(dev, "Pointer to flat panel xlat table invalid\n"); + NV_ERROR(drm, "Pointer to flat panel xlat table invalid\n"); return -EINVAL; } @@ -412,7 +419,7 @@ static int parse_fp_mode_table(struct drm_device *dev, struct nvbios *bios) fpstrapping * bios->fp.xlatwidth]; if (fpindex > fpentries) { - NV_ERROR(dev, "Bad flat panel table index\n"); + NV_ERROR(drm, "Bad flat panel table index\n"); return -ENOENT; } @@ -431,7 +438,7 @@ static int parse_fp_mode_table(struct drm_device *dev, struct nvbios *bios) bios->fp.mode_ptr = bios->fp.fptablepointer + headerlen + recordlen * fpindex + ofs; - NV_TRACE(dev, "BIOS FP mode: %dx%d (%dkHz pixel clock)\n", + NV_INFO(drm, "BIOS FP mode: %dx%d (%dkHz pixel clock)\n", ROM16(bios->data[bios->fp.mode_ptr + 11]) + 1, ROM16(bios->data[bios->fp.mode_ptr + 25]) + 1, ROM16(bios->data[bios->fp.mode_ptr + 7]) * 10); @@ -441,8 +448,8 @@ static int parse_fp_mode_table(struct drm_device *dev, struct nvbios *bios) bool nouveau_bios_fp_mode(struct drm_device *dev, struct drm_display_mode *mode) { - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nvbios *bios = &dev_priv->vbios; + struct nouveau_drm *drm = nouveau_drm(dev); + struct nvbios *bios = &drm->vbios; uint8_t *mode_entry = &bios->data[bios->fp.mode_ptr]; if (!mode) /* just checking whether we can produce a mode */ @@ -512,8 +519,8 @@ int nouveau_bios_parse_lvds_table(struct drm_device *dev, int pxclk, bool *dl, b * requiring tests against the native-mode pixel clock, cannot be done * until later, when this function should be called with non-zero pxclk */ - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nvbios *bios = &dev_priv->vbios; + struct nouveau_drm *drm = nouveau_drm(dev); + struct nvbios *bios = &drm->vbios; int fpstrapping = get_fp_strap(dev, bios), lvdsmanufacturerindex = 0; struct lvdstableheader lth; uint16_t lvdsofs; @@ -574,7 +581,7 @@ int nouveau_bios_parse_lvds_table(struct drm_device *dev, int pxclk, bool *dl, b lvdsmanufacturerindex = fpstrapping; break; default: - NV_ERROR(dev, "LVDS table revision not currently supported\n"); + NV_ERROR(drm, "LVDS table revision not currently supported\n"); return -ENOSYS; } @@ -671,15 +678,15 @@ nouveau_bios_run_display_table(struct drm_device *dev, u16 type, int pclk, * offset + 5 (16 bits): pointer to first output script table */ - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nvbios *bios = &dev_priv->vbios; + struct nouveau_drm *drm = nouveau_drm(dev); + struct nvbios *bios = &drm->vbios; uint8_t *table = &bios->data[bios->display.script_table_ptr]; uint8_t *otable = NULL; uint16_t script; int i; if (!bios->display.script_table_ptr) { - NV_ERROR(dev, "No pointer to output script table\n"); + NV_ERROR(drm, "No pointer to output script table\n"); return 1; } @@ -691,7 +698,7 @@ nouveau_bios_run_display_table(struct drm_device *dev, u16 type, int pclk, return 1; if (table[0] != 0x20 && table[0] != 0x21) { - NV_ERROR(dev, "Output script table version 0x%02x unknown\n", + NV_ERROR(drm, "Output script table version 0x%02x unknown\n", table[0]); return 1; } @@ -726,7 +733,7 @@ nouveau_bios_run_display_table(struct drm_device *dev, u16 type, int pclk, * script tables is a pointer to the script to execute. */ - NV_DEBUG_KMS(dev, "Searching for output entry for %d %d %d\n", + NV_DEBUG(drm, "Searching for output entry for %d %d %d\n", dcbent->type, dcbent->location, dcbent->or); for (i = 0; i < table[3]; i++) { otable = ROMPTR(dev, table[table[1] + (i * table[2])]); @@ -735,7 +742,7 @@ nouveau_bios_run_display_table(struct drm_device *dev, u16 type, int pclk, } if (!otable) { - NV_DEBUG_KMS(dev, "failed to match any output table\n"); + NV_DEBUG(drm, "failed to match any output table\n"); return 1; } @@ -747,7 +754,7 @@ nouveau_bios_run_display_table(struct drm_device *dev, u16 type, int pclk, } if (i == otable[5]) { - NV_ERROR(dev, "Table 0x%04x not found for %d/%d, " + NV_ERROR(drm, "Table 0x%04x not found for %d/%d, " "using first\n", type, dcbent->type, dcbent->or); i = 0; @@ -757,21 +764,21 @@ nouveau_bios_run_display_table(struct drm_device *dev, u16 type, int pclk, if (pclk == 0) { script = ROM16(otable[6]); if (!script) { - NV_DEBUG_KMS(dev, "output script 0 not found\n"); + NV_DEBUG(drm, "output script 0 not found\n"); return 1; } - NV_DEBUG_KMS(dev, "0x%04X: parsing output script 0\n", script); + NV_DEBUG(drm, "0x%04X: parsing output script 0\n", script); nouveau_bios_run_init_table(dev, script, dcbent, crtc); } else if (pclk == -1) { script = ROM16(otable[8]); if (!script) { - NV_DEBUG_KMS(dev, "output script 1 not found\n"); + NV_DEBUG(drm, "output script 1 not found\n"); return 1; } - NV_DEBUG_KMS(dev, "0x%04X: parsing output script 1\n", script); + NV_DEBUG(drm, "0x%04X: parsing output script 1\n", script); nouveau_bios_run_init_table(dev, script, dcbent, crtc); } else if (pclk == -2) { @@ -780,11 +787,11 @@ nouveau_bios_run_display_table(struct drm_device *dev, u16 type, int pclk, else script = 0; if (!script) { - NV_DEBUG_KMS(dev, "output script 2 not found\n"); + NV_DEBUG(drm, "output script 2 not found\n"); return 1; } - NV_DEBUG_KMS(dev, "0x%04X: parsing output script 2\n", script); + NV_DEBUG(drm, "0x%04X: parsing output script 2\n", script); nouveau_bios_run_init_table(dev, script, dcbent, crtc); } else if (pclk > 0) { @@ -792,11 +799,11 @@ nouveau_bios_run_display_table(struct drm_device *dev, u16 type, int pclk, if (script) script = clkcmptable(bios, script, pclk); if (!script) { - NV_DEBUG_KMS(dev, "clock script 0 not found\n"); + NV_DEBUG(drm, "clock script 0 not found\n"); return 1; } - NV_DEBUG_KMS(dev, "0x%04X: parsing clock script 0\n", script); + NV_DEBUG(drm, "0x%04X: parsing clock script 0\n", script); nouveau_bios_run_init_table(dev, script, dcbent, crtc); } else if (pclk < 0) { @@ -804,11 +811,11 @@ nouveau_bios_run_display_table(struct drm_device *dev, u16 type, int pclk, if (script) script = clkcmptable(bios, script, -pclk); if (!script) { - NV_DEBUG_KMS(dev, "clock script 1 not found\n"); + NV_DEBUG(drm, "clock script 1 not found\n"); return 1; } - NV_DEBUG_KMS(dev, "0x%04X: parsing clock script 1\n", script); + NV_DEBUG(drm, "0x%04X: parsing clock script 1\n", script); nouveau_bios_run_init_table(dev, script, dcbent, crtc); } @@ -827,8 +834,9 @@ int run_tmds_table(struct drm_device *dev, struct dcb_output *dcbent, int head, * ffs(or) == 3, use the second. */ - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nvbios *bios = &dev_priv->vbios; + struct nouveau_drm *drm = nouveau_drm(dev); + struct nouveau_device *device = nv_device(drm->device); + struct nvbios *bios = &drm->vbios; int cv = bios->chip_version; uint16_t clktable = 0, scriptptr; uint32_t sel_clk_binding, sel_clk; @@ -849,19 +857,19 @@ int run_tmds_table(struct drm_device *dev, struct dcb_output *dcbent, int head, } if (!clktable) { - NV_ERROR(dev, "Pixel clock comparison table not found\n"); + NV_ERROR(drm, "Pixel clock comparison table not found\n"); return -EINVAL; } scriptptr = clkcmptable(bios, clktable, pxclk); if (!scriptptr) { - NV_ERROR(dev, "TMDS output init script not found\n"); + NV_ERROR(drm, "TMDS output init script not found\n"); return -ENOENT; } /* don't let script change pll->head binding */ - sel_clk_binding = nv_rd32(dev, NV_PRAMDAC_SEL_CLK) & 0x50000; + sel_clk_binding = nv_rd32(device, NV_PRAMDAC_SEL_CLK) & 0x50000; run_digital_op_script(dev, scriptptr, dcbent, head, pxclk >= 165000); sel_clk = NVReadRAMDAC(dev, 0, NV_PRAMDAC_SEL_CLK) & ~0x50000; NVWriteRAMDAC(dev, 0, NV_PRAMDAC_SEL_CLK, sel_clk | sel_clk_binding); @@ -877,10 +885,11 @@ static void parse_bios_version(struct drm_device *dev, struct nvbios *bios, uint * offset + 2 (8 bits): Chip version * offset + 3 (8 bits): Major version */ + struct nouveau_drm *drm = nouveau_drm(dev); bios->major_version = bios->data[offset + 3]; bios->chip_version = bios->data[offset + 2]; - NV_TRACE(dev, "Bios version %02x.%02x.%02x.%02x\n", + NV_INFO(drm, "Bios version %02x.%02x.%02x.%02x\n", bios->data[offset + 3], bios->data[offset + 2], bios->data[offset + 1], bios->data[offset]); } @@ -916,25 +925,26 @@ static int parse_bit_A_tbl_entry(struct drm_device *dev, struct nvbios *bios, st * offset + 0 (16 bits): loadval table pointer */ + struct nouveau_drm *drm = nouveau_drm(dev); uint16_t load_table_ptr; uint8_t version, headerlen, entrylen, num_entries; if (bitentry->length != 3) { - NV_ERROR(dev, "Do not understand BIT A table\n"); + NV_ERROR(drm, "Do not understand BIT A table\n"); return -EINVAL; } load_table_ptr = ROM16(bios->data[bitentry->offset]); if (load_table_ptr == 0x0) { - NV_DEBUG(dev, "Pointer to BIT loadval table invalid\n"); + NV_DEBUG(drm, "Pointer to BIT loadval table invalid\n"); return -EINVAL; } version = bios->data[load_table_ptr]; if (version != 0x10) { - NV_ERROR(dev, "BIT loadval table version %d.%d not supported\n", + NV_ERROR(drm, "BIT loadval table version %d.%d not supported\n", version >> 4, version & 0xF); return -ENOSYS; } @@ -944,7 +954,7 @@ static int parse_bit_A_tbl_entry(struct drm_device *dev, struct nvbios *bios, st num_entries = bios->data[load_table_ptr + 3]; if (headerlen != 4 || entrylen != 4 || num_entries != 2) { - NV_ERROR(dev, "Do not understand BIT loadval table\n"); + NV_ERROR(drm, "Do not understand BIT loadval table\n"); return -EINVAL; } @@ -961,9 +971,10 @@ static int parse_bit_C_tbl_entry(struct drm_device *dev, struct nvbios *bios, st * * There's more in here, but that's unknown. */ + struct nouveau_drm *drm = nouveau_drm(dev); if (bitentry->length < 10) { - NV_ERROR(dev, "Do not understand BIT C table\n"); + NV_ERROR(drm, "Do not understand BIT C table\n"); return -EINVAL; } @@ -982,9 +993,10 @@ static int parse_bit_display_tbl_entry(struct drm_device *dev, struct nvbios *bi * records beginning with a freq. * offset + 2 (16 bits): mode table pointer */ + struct nouveau_drm *drm = nouveau_drm(dev); if (bitentry->length != 4) { - NV_ERROR(dev, "Do not understand BIT display table\n"); + NV_ERROR(drm, "Do not understand BIT display table\n"); return -EINVAL; } @@ -1000,9 +1012,10 @@ static int parse_bit_init_tbl_entry(struct drm_device *dev, struct nvbios *bios, * * See parse_script_table_pointers for layout */ + struct nouveau_drm *drm = nouveau_drm(dev); if (bitentry->length < 14) { - NV_ERROR(dev, "Do not understand init table\n"); + NV_ERROR(drm, "Do not understand init table\n"); return -EINVAL; } @@ -1029,11 +1042,12 @@ static int parse_bit_i_tbl_entry(struct drm_device *dev, struct nvbios *bios, st * There's other things in the table, purpose unknown */ + struct nouveau_drm *drm = nouveau_drm(dev); uint16_t daccmpoffset; uint8_t dacver, dacheaderlen; if (bitentry->length < 6) { - NV_ERROR(dev, "BIT i table too short for needed information\n"); + NV_ERROR(drm, "BIT i table too short for needed information\n"); return -EINVAL; } @@ -1047,7 +1061,7 @@ static int parse_bit_i_tbl_entry(struct drm_device *dev, struct nvbios *bios, st bios->is_mobile = bios->feature_byte & FEATURE_MOBILE; if (bitentry->length < 15) { - NV_WARN(dev, "BIT i table not long enough for DAC load " + NV_WARN(drm, "BIT i table not long enough for DAC load " "detection comparison table\n"); return -EINVAL; } @@ -1068,7 +1082,7 @@ static int parse_bit_i_tbl_entry(struct drm_device *dev, struct nvbios *bios, st dacheaderlen = bios->data[daccmpoffset + 1]; if (dacver != 0x00 && dacver != 0x10) { - NV_WARN(dev, "DAC load detection comparison table version " + NV_WARN(drm, "DAC load detection comparison table version " "%d.%d not known\n", dacver >> 4, dacver & 0xf); return -ENOSYS; } @@ -1088,8 +1102,10 @@ static int parse_bit_lvds_tbl_entry(struct drm_device *dev, struct nvbios *bios, * offset + 0 (16 bits): LVDS strap xlate table pointer */ + struct nouveau_drm *drm = nouveau_drm(dev); + if (bitentry->length != 2) { - NV_ERROR(dev, "Do not understand BIT LVDS table\n"); + NV_ERROR(drm, "Do not understand BIT LVDS table\n"); return -EINVAL; } @@ -1159,20 +1175,21 @@ static int parse_bit_tmds_tbl_entry(struct drm_device *dev, struct nvbios *bios, * "or" from the DCB. */ + struct nouveau_drm *drm = nouveau_drm(dev); uint16_t tmdstableptr, script1, script2; if (bitentry->length != 2) { - NV_ERROR(dev, "Do not understand BIT TMDS table\n"); + NV_ERROR(drm, "Do not understand BIT TMDS table\n"); return -EINVAL; } tmdstableptr = ROM16(bios->data[bitentry->offset]); if (!tmdstableptr) { - NV_ERROR(dev, "Pointer to TMDS table invalid\n"); + NV_ERROR(drm, "Pointer to TMDS table invalid\n"); return -EINVAL; } - NV_INFO(dev, "TMDS table version %d.%d\n", + NV_INFO(drm, "TMDS table version %d.%d\n", bios->data[tmdstableptr] >> 4, bios->data[tmdstableptr] & 0xf); /* nv50+ has v2.0, but we don't parse it atm */ @@ -1186,7 +1203,7 @@ static int parse_bit_tmds_tbl_entry(struct drm_device *dev, struct nvbios *bios, script1 = ROM16(bios->data[tmdstableptr + 7]); script2 = ROM16(bios->data[tmdstableptr + 9]); if (bios->data[script1] != 'q' || bios->data[script2] != 'q') - NV_WARN(dev, "TMDS table script pointers not stubbed\n"); + NV_WARN(drm, "TMDS table script pointers not stubbed\n"); bios->tmds.output0_script_ptr = ROM16(bios->data[tmdstableptr + 11]); bios->tmds.output1_script_ptr = ROM16(bios->data[tmdstableptr + 13]); @@ -1206,10 +1223,11 @@ parse_bit_U_tbl_entry(struct drm_device *dev, struct nvbios *bios, * offset + 0 (16 bits): output script table pointer */ + struct nouveau_drm *drm = nouveau_drm(dev); uint16_t outputscripttableptr; if (bitentry->length != 3) { - NV_ERROR(dev, "Do not understand BIT U table\n"); + NV_ERROR(drm, "Do not understand BIT U table\n"); return -EINVAL; } @@ -1228,8 +1246,8 @@ struct bit_table { int bit_table(struct drm_device *dev, u8 id, struct bit_entry *bit) { - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nvbios *bios = &dev_priv->vbios; + struct nouveau_drm *drm = nouveau_drm(dev); + struct nvbios *bios = &drm->vbios; u8 entries, *entry; if (bios->type != NVBIOS_BIT) @@ -1258,12 +1276,13 @@ parse_bit_table(struct nvbios *bios, const uint16_t bitoffset, struct bit_table *table) { struct drm_device *dev = bios->dev; + struct nouveau_drm *drm = nouveau_drm(dev); struct bit_entry bitentry; if (bit_table(dev, table->id, &bitentry) == 0) return table->parse_fn(dev, bios, &bitentry); - NV_INFO(dev, "BIT table '%c' not found\n", table->id); + NV_INFO(drm, "BIT table '%c' not found\n", table->id); return -ENOSYS; } @@ -1343,6 +1362,7 @@ static int parse_bmp_structure(struct drm_device *dev, struct nvbios *bios, unsi * offset + 156: minimum pixel clock for LVDS dual link */ + struct nouveau_drm *drm = nouveau_drm(dev); uint8_t *bmp = &bios->data[offset], bmp_version_major, bmp_version_minor; uint16_t bmplength; uint16_t legacy_scripts_offset, legacy_i2c_offset; @@ -1356,7 +1376,7 @@ static int parse_bmp_structure(struct drm_device *dev, struct nvbios *bios, unsi bmp_version_major = bmp[5]; bmp_version_minor = bmp[6]; - NV_TRACE(dev, "BMP version %d.%d\n", + NV_INFO(drm, "BMP version %d.%d\n", bmp_version_major, bmp_version_minor); /* @@ -1372,7 +1392,7 @@ static int parse_bmp_structure(struct drm_device *dev, struct nvbios *bios, unsi * happened instead. */ if ((bmp_version_major < 5 && bmp_version_minor != 1) || bmp_version_major > 5) { - NV_ERROR(dev, "You have an unsupported BMP version. " + NV_ERROR(drm, "You have an unsupported BMP version. " "Please send in your bios\n"); return -ENOSYS; } @@ -1421,7 +1441,7 @@ static int parse_bmp_structure(struct drm_device *dev, struct nvbios *bios, unsi /* checksum */ if (nv_cksum(bmp, 8)) { - NV_ERROR(dev, "Bad BMP checksum\n"); + NV_ERROR(drm, "Bad BMP checksum\n"); return -EINVAL; } @@ -1508,18 +1528,18 @@ static uint16_t findstr(uint8_t *data, int n, const uint8_t *str, int len) void * olddcb_table(struct drm_device *dev) { - struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_drm *drm = nouveau_drm(dev); u8 *dcb = NULL; - if (dev_priv->card_type > NV_04) - dcb = ROMPTR(dev, dev_priv->vbios.data[0x36]); + if (nv_device(drm->device)->card_type > NV_04) + dcb = ROMPTR(dev, drm->vbios.data[0x36]); if (!dcb) { - NV_WARNONCE(dev, "No DCB data found in VBIOS\n"); + NV_WARN(drm, "No DCB data found in VBIOS\n"); return NULL; } if (dcb[0] >= 0x41) { - NV_WARNONCE(dev, "DCB version 0x%02x unknown\n", dcb[0]); + NV_WARN(drm, "DCB version 0x%02x unknown\n", dcb[0]); return NULL; } else if (dcb[0] >= 0x30) { @@ -1551,11 +1571,11 @@ olddcb_table(struct drm_device *dev) * * v1.1 (NV5+, maybe some NV4) is entirely unhelpful */ - NV_WARNONCE(dev, "No useful DCB data in VBIOS\n"); + NV_WARN(drm, "No useful DCB data in VBIOS\n"); return NULL; } - NV_WARNONCE(dev, "DCB header validation failed\n"); + NV_WARN(drm, "DCB header validation failed\n"); return NULL; } @@ -1656,6 +1676,8 @@ static bool parse_dcb20_entry(struct drm_device *dev, struct dcb_table *dcb, uint32_t conn, uint32_t conf, struct dcb_output *entry) { + struct nouveau_drm *drm = nouveau_drm(dev); + entry->type = conn & 0xf; entry->i2c_index = (conn >> 4) & 0xf; entry->heads = (conn >> 8) & 0xf; @@ -1709,7 +1731,7 @@ parse_dcb20_entry(struct drm_device *dev, struct dcb_table *dcb, if (dcb->version >= 0x40) break; - NV_ERROR(dev, "Unknown LVDS configuration bits, " + NV_ERROR(drm, "Unknown LVDS configuration bits, " "please report\n"); } break; @@ -1783,6 +1805,8 @@ static bool parse_dcb15_entry(struct drm_device *dev, struct dcb_table *dcb, uint32_t conn, uint32_t conf, struct dcb_output *entry) { + struct nouveau_drm *drm = nouveau_drm(dev); + switch (conn & 0x0000000f) { case 0: entry->type = DCB_OUTPUT_ANALOG; @@ -1801,7 +1825,7 @@ parse_dcb15_entry(struct drm_device *dev, struct dcb_table *dcb, entry->type = DCB_OUTPUT_LVDS; break; default: - NV_ERROR(dev, "Unknown DCB type %d\n", conn & 0x0000000f); + NV_ERROR(drm, "Unknown DCB type %d\n", conn & 0x0000000f); return false; } @@ -1840,6 +1864,7 @@ void merge_like_dcb_entries(struct drm_device *dev, struct dcb_table *dcb) * more options */ + struct nouveau_drm *drm = nouveau_drm(dev); int i, newentries = 0; for (i = 0; i < dcb->entries; i++) { @@ -1857,7 +1882,7 @@ void merge_like_dcb_entries(struct drm_device *dev, struct dcb_table *dcb) jent->type == ient->type && jent->location == ient->location && jent->or == ient->or) { - NV_TRACE(dev, "Merging DCB entries %d and %d\n", + NV_INFO(drm, "Merging DCB entries %d and %d\n", i, j); ient->heads |= jent->heads; jent->type = 100; /* dummy value */ @@ -1883,8 +1908,8 @@ void merge_like_dcb_entries(struct drm_device *dev, struct dcb_table *dcb) static bool apply_dcb_encoder_quirks(struct drm_device *dev, int idx, u32 *conn, u32 *conf) { - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct dcb_table *dcb = &dev_priv->vbios.dcb; + struct nouveau_drm *drm = nouveau_drm(dev); + struct dcb_table *dcb = &drm->vbios.dcb; /* Dell Precision M6300 * DCB entry 2: 02025312 00000010 @@ -2021,8 +2046,8 @@ fabricate_dcb_encoder_table(struct drm_device *dev, struct nvbios *bios) static int parse_dcb_entry(struct drm_device *dev, void *data, int idx, u8 *outp) { - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct dcb_table *dcb = &dev_priv->vbios.dcb; + struct nouveau_drm *drm = nouveau_drm(dev); + struct dcb_table *dcb = &drm->vbios.dcb; u32 conf = (dcb->version >= 0x20) ? ROM32(outp[4]) : ROM32(outp[6]); u32 conn = ROM32(outp[0]); bool ret; @@ -2030,7 +2055,7 @@ parse_dcb_entry(struct drm_device *dev, void *data, int idx, u8 *outp) if (apply_dcb_encoder_quirks(dev, idx, &conn, &conf)) { struct dcb_output *entry = new_dcb_entry(dcb); - NV_TRACEWARN(dev, "DCB outp %02d: %08x %08x\n", idx, conn, conf); + NV_INFO(drm, "DCB outp %02d: %08x %08x\n", idx, conn, conf); if (dcb->version >= 0x20) ret = parse_dcb20_entry(dev, dcb, conn, conf, entry); @@ -2100,6 +2125,7 @@ dcb_fake_connectors(struct nvbios *bios) static int parse_dcb_table(struct drm_device *dev, struct nvbios *bios) { + struct nouveau_drm *drm = nouveau_drm(dev); struct dcb_table *dcb = &bios->dcb; u8 *dcbt, *conn; int idx; @@ -2115,7 +2141,7 @@ parse_dcb_table(struct drm_device *dev, struct nvbios *bios) return -EINVAL; } - NV_TRACE(dev, "DCB version %d.%d\n", dcbt[0] >> 4, dcbt[0] & 0xf); + NV_INFO(drm, "DCB version %d.%d\n", dcbt[0] >> 4, dcbt[0] & 0xf); dcb->version = dcbt[0]; olddcb_outp_foreach(dev, NULL, parse_dcb_entry); @@ -2134,7 +2160,7 @@ parse_dcb_table(struct drm_device *dev, struct nvbios *bios) idx = -1; while ((conn = olddcb_conn(dev, ++idx))) { if (conn[0] != 0xff) { - NV_TRACE(dev, "DCB conn %02d: ", idx); + NV_INFO(drm, "DCB conn %02d: ", idx); if (olddcb_conntab(dev)[3] < 4) printk("%04x\n", ROM16(conn[0])); else @@ -2156,12 +2182,14 @@ static int load_nv17_hwsq_ucode_entry(struct drm_device *dev, struct nvbios *bio * starting at reg 0x00001400 */ + struct nouveau_drm *drm = nouveau_drm(dev); + struct nouveau_device *device = nv_device(drm->device); uint8_t bytes_to_write; uint16_t hwsq_entry_offset; int i; if (bios->data[hwsq_offset] <= entry) { - NV_ERROR(dev, "Too few entries in HW sequencer table for " + NV_ERROR(drm, "Too few entries in HW sequencer table for " "requested entry\n"); return -ENOENT; } @@ -2169,24 +2197,24 @@ static int load_nv17_hwsq_ucode_entry(struct drm_device *dev, struct nvbios *bio bytes_to_write = bios->data[hwsq_offset + 1]; if (bytes_to_write != 36) { - NV_ERROR(dev, "Unknown HW sequencer entry size\n"); + NV_ERROR(drm, "Unknown HW sequencer entry size\n"); return -EINVAL; } - NV_TRACE(dev, "Loading NV17 power sequencing microcode\n"); + NV_INFO(drm, "Loading NV17 power sequencing microcode\n"); hwsq_entry_offset = hwsq_offset + 2 + entry * bytes_to_write; /* set sequencer control */ - nv_wr32(dev, 0x00001304, ROM32(bios->data[hwsq_entry_offset])); + nv_wr32(device, 0x00001304, ROM32(bios->data[hwsq_entry_offset])); bytes_to_write -= 4; /* write ucode */ for (i = 0; i < bytes_to_write; i += 4) - nv_wr32(dev, 0x00001400 + i, ROM32(bios->data[hwsq_entry_offset + i + 4])); + nv_wr32(device, 0x00001400 + i, ROM32(bios->data[hwsq_entry_offset + i + 4])); /* twiddle NV_PBUS_DEBUG_4 */ - nv_wr32(dev, NV_PBUS_DEBUG_4, nv_rd32(dev, NV_PBUS_DEBUG_4) | 0x18); + nv_wr32(device, NV_PBUS_DEBUG_4, nv_rd32(device, NV_PBUS_DEBUG_4) | 0x18); return 0; } @@ -2217,8 +2245,8 @@ static int load_nv17_hw_sequencer_ucode(struct drm_device *dev, uint8_t *nouveau_bios_embedded_edid(struct drm_device *dev) { - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nvbios *bios = &dev_priv->vbios; + struct nouveau_drm *drm = nouveau_drm(dev); + struct nvbios *bios = &drm->vbios; const uint8_t edid_sig[] = { 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00 }; uint16_t offset = 0; @@ -2241,27 +2269,29 @@ uint8_t *nouveau_bios_embedded_edid(struct drm_device *dev) offset++; } - NV_TRACE(dev, "Found EDID in BIOS\n"); + NV_INFO(drm, "Found EDID in BIOS\n"); return bios->fp.edid = &bios->data[offset]; } static bool NVInitVBIOS(struct drm_device *dev) { - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nvbios *bios = &dev_priv->vbios; + struct nouveau_drm *drm = nouveau_drm(dev); + struct nvbios *bios = &drm->vbios; memset(bios, 0, sizeof(struct nvbios)); spin_lock_init(&bios->lock); bios->dev = dev; - return _nv_bios(dev, &bios->data, &bios->length); + bios->data = nouveau_bios(drm->device)->data; + bios->length = nouveau_bios(drm->device)->size; + return true; } static int nouveau_parse_vbios_struct(struct drm_device *dev) { - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nvbios *bios = &dev_priv->vbios; + struct nouveau_drm *drm = nouveau_drm(dev); + struct nvbios *bios = &drm->vbios; const uint8_t bit_signature[] = { 0xff, 0xb8, 'B', 'I', 'T' }; const uint8_t bmp_signature[] = { 0xff, 0x7f, 'N', 'V', 0x0 }; int offset; @@ -2269,7 +2299,7 @@ static int nouveau_parse_vbios_struct(struct drm_device *dev) offset = findstr(bios->data, bios->length, bit_signature, sizeof(bit_signature)); if (offset) { - NV_TRACE(dev, "BIT BIOS found\n"); + NV_INFO(drm, "BIT BIOS found\n"); bios->type = NVBIOS_BIT; bios->offset = offset; return parse_bit_structure(bios, offset + 6); @@ -2278,21 +2308,21 @@ static int nouveau_parse_vbios_struct(struct drm_device *dev) offset = findstr(bios->data, bios->length, bmp_signature, sizeof(bmp_signature)); if (offset) { - NV_TRACE(dev, "BMP BIOS found\n"); + NV_INFO(drm, "BMP BIOS found\n"); bios->type = NVBIOS_BMP; bios->offset = offset; return parse_bmp_structure(dev, bios, offset); } - NV_ERROR(dev, "No known BIOS signature found\n"); + NV_ERROR(drm, "No known BIOS signature found\n"); return -ENODEV; } int nouveau_run_vbios_init(struct drm_device *dev) { - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nvbios *bios = &dev_priv->vbios; + struct nouveau_drm *drm = nouveau_drm(dev); + struct nvbios *bios = &drm->vbios; int i, ret = 0; /* Reset the BIOS head to 0. */ @@ -2306,7 +2336,7 @@ nouveau_run_vbios_init(struct drm_device *dev) bios->fp.lvds_init_run = false; } - if (dev_priv->card_type >= NV_50) { + if (nv_device(drm->device)->card_type >= NV_50) { for (i = 0; bios->execute && i < bios->dcb.entries; i++) { nouveau_bios_run_display_table(dev, 0, 0, &bios->dcb.entry[i], -1); @@ -2319,10 +2349,10 @@ nouveau_run_vbios_init(struct drm_device *dev) static bool nouveau_bios_posted(struct drm_device *dev) { - struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_drm *drm = nouveau_drm(dev); unsigned htotal; - if (dev_priv->card_type >= NV_50) { + if (nv_device(drm->device)->card_type >= NV_50) { if (NVReadVgaCrtc(dev, 0, 0x00) == 0 && NVReadVgaCrtc(dev, 0, 0x1a) == 0) return false; @@ -2341,8 +2371,8 @@ nouveau_bios_posted(struct drm_device *dev) int nouveau_bios_init(struct drm_device *dev) { - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nvbios *bios = &dev_priv->vbios; + struct nouveau_drm *drm = nouveau_drm(dev); + struct nvbios *bios = &drm->vbios; int ret; if (!NVInitVBIOS(dev)) @@ -2364,12 +2394,10 @@ nouveau_bios_init(struct drm_device *dev) /* ... unless card isn't POSTed already */ if (!nouveau_bios_posted(dev)) { - NV_INFO(dev, "Adaptor not initialised, " + NV_INFO(drm, "Adaptor not initialised, " "running VBIOS init tables.\n"); bios->execute = true; } - if (nouveau_force_post) - bios->execute = true; ret = nouveau_run_vbios_init(dev); if (ret) diff --git a/drivers/gpu/drm/nouveau/nouveau_bios.h b/drivers/gpu/drm/nouveau/nouveau_bios.h index 27a64db634d4..3befbb821a56 100644 --- a/drivers/gpu/drm/nouveau/nouveau_bios.h +++ b/drivers/gpu/drm/nouveau/nouveau_bios.h @@ -21,8 +21,8 @@ * DEALINGS IN THE SOFTWARE. */ -#ifndef __NOUVEAU_BIOS_H__ -#define __NOUVEAU_BIOS_H__ +#ifndef __NOUVEAU_DISPBIOS_H__ +#define __NOUVEAU_DISPBIOS_H__ #include "nvreg.h" @@ -38,8 +38,8 @@ #define ROM48(x) ({ u8 *p = &(x); (u64)ROM16(p[4]) << 32 | ROM32(p[0]); }) #define ROM64(x) le64_to_cpu(*(u64 *)&(x)) #define ROMPTR(d,x) ({ \ - struct drm_nouveau_private *dev_priv = (d)->dev_private; \ - ROM16(x) ? &dev_priv->vbios.data[ROM16(x)] : NULL; \ + struct nouveau_drm *drm = nouveau_drm((d)); \ + ROM16(x) ? &drm->vbios.data[ROM16(x)] : NULL; \ }) struct bit_entry { @@ -180,4 +180,21 @@ int olddcb_outp_foreach(struct drm_device *, void *data, u8 *olddcb_conntab(struct drm_device *); u8 *olddcb_conn(struct drm_device *, u8 idx); +int nouveau_bios_init(struct drm_device *); +void nouveau_bios_takedown(struct drm_device *dev); +int nouveau_run_vbios_init(struct drm_device *); +struct dcb_connector_table_entry * +nouveau_bios_connector_entry(struct drm_device *, int index); +int nouveau_bios_run_display_table(struct drm_device *, u16 id, int clk, + struct dcb_output *, int crtc); +bool nouveau_bios_fp_mode(struct drm_device *, struct drm_display_mode *); +uint8_t *nouveau_bios_embedded_edid(struct drm_device *); +int nouveau_bios_parse_lvds_table(struct drm_device *, int pxclk, + bool *dl, bool *if_is_24bit); +int run_tmds_table(struct drm_device *, struct dcb_output *, + int head, int pxclk); +int call_lvds_script(struct drm_device *, struct dcb_output *, int head, + enum LVDS_script, int pxclk); +bool bios_encoder_match(struct dcb_output *, u32 hash); + #endif diff --git a/drivers/gpu/drm/nouveau/nouveau_bo.c b/drivers/gpu/drm/nouveau/nouveau_bo.c index 3465df327227..ef96bdbb5255 100644 --- a/drivers/gpu/drm/nouveau/nouveau_bo.c +++ b/drivers/gpu/drm/nouveau/nouveau_bo.c @@ -49,7 +49,7 @@ static void nv10_bo_update_tile_region(struct drm_device *dev, struct nouveau_drm_tile *reg, u32 addr, u32 size, u32 pitch, u32 flags) { - struct nouveau_drm *drm = nouveau_newpriv(dev); + struct nouveau_drm *drm = nouveau_drm(dev); int i = reg - drm->tile.reg; struct nouveau_fb *pfb = nouveau_fb(drm->device); struct nouveau_fb_tile *tile = &pfb->tile.region[i]; @@ -74,7 +74,7 @@ nv10_bo_update_tile_region(struct drm_device *dev, struct nouveau_drm_tile *reg, static struct nouveau_drm_tile * nv10_bo_get_tile_region(struct drm_device *dev, int i) { - struct nouveau_drm *drm = nouveau_newpriv(dev); + struct nouveau_drm *drm = nouveau_drm(dev); struct nouveau_drm_tile *tile = &drm->tile.reg[i]; spin_lock(&drm->tile.lock); @@ -93,7 +93,7 @@ static void nv10_bo_put_tile_region(struct drm_device *dev, struct nouveau_drm_tile *tile, struct nouveau_fence *fence) { - struct nouveau_drm *drm = nouveau_newpriv(dev); + struct nouveau_drm *drm = nouveau_drm(dev); if (tile) { spin_lock(&drm->tile.lock); @@ -112,7 +112,7 @@ static struct nouveau_drm_tile * nv10_bo_set_tiling(struct drm_device *dev, u32 addr, u32 size, u32 pitch, u32 flags) { - struct nouveau_drm *drm = nouveau_newpriv(dev); + struct nouveau_drm *drm = nouveau_drm(dev); struct nouveau_fb *pfb = nouveau_fb(drm->device); struct nouveau_drm_tile *tile, *found = NULL; int i; @@ -191,7 +191,7 @@ nouveau_bo_new(struct drm_device *dev, int size, int align, struct sg_table *sg, struct nouveau_bo **pnvbo) { - struct nouveau_drm *drm = nouveau_newpriv(dev); + struct nouveau_drm *drm = nouveau_drm(dev); struct nouveau_bo *nvbo; size_t acc_size; int ret; diff --git a/drivers/gpu/drm/nouveau/nouveau_calc.c b/drivers/gpu/drm/nouveau/nouveau_calc.c index 5ec677ea1c78..77959526b5f3 100644 --- a/drivers/gpu/drm/nouveau/nouveau_calc.c +++ b/drivers/gpu/drm/nouveau/nouveau_calc.c @@ -22,7 +22,8 @@ */ #include "drmP.h" -#include "nouveau_drv.h" +#include "nouveau_drm.h" +#include "nouveau_reg.h" #include "nouveau_hw.h" /****************************************************************************\ @@ -195,12 +196,13 @@ static void nv04_update_arb(struct drm_device *dev, int VClk, int bpp, int *burst, int *lwm) { - struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_drm *drm = nouveau_drm(dev); + struct nouveau_device *device = nouveau_dev(dev); struct nv_fifo_info fifo_data; struct nv_sim_state sim_data; int MClk = nouveau_hw_get_clock(dev, PLL_MEMORY); int NVClk = nouveau_hw_get_clock(dev, PLL_CORE); - uint32_t cfg1 = nv_rd32(dev, NV04_PFB_CFG1); + uint32_t cfg1 = nv_rd32(device, NV04_PFB_CFG1); sim_data.pclk_khz = VClk; sim_data.mclk_khz = MClk; @@ -218,13 +220,13 @@ nv04_update_arb(struct drm_device *dev, int VClk, int bpp, sim_data.mem_latency = 3; sim_data.mem_page_miss = 10; } else { - sim_data.memory_type = nv_rd32(dev, NV04_PFB_CFG0) & 0x1; - sim_data.memory_width = (nv_rd32(dev, NV_PEXTDEV_BOOT_0) & 0x10) ? 128 : 64; + sim_data.memory_type = nv_rd32(device, NV04_PFB_CFG0) & 0x1; + sim_data.memory_width = (nv_rd32(device, NV_PEXTDEV_BOOT_0) & 0x10) ? 128 : 64; sim_data.mem_latency = cfg1 & 0xf; sim_data.mem_page_miss = ((cfg1 >> 4) & 0xf) + ((cfg1 >> 31) & 0x1); } - if (dev_priv->card_type == NV_04) + if (nv_device(drm->device)->card_type == NV_04) nv04_calc_arb(&fifo_data, &sim_data); else nv10_calc_arb(&fifo_data, &sim_data); @@ -249,9 +251,9 @@ nv20_update_arb(int *burst, int *lwm) void nouveau_calc_arb(struct drm_device *dev, int vclk, int bpp, int *burst, int *lwm) { - struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_drm *drm = nouveau_drm(dev); - if (dev_priv->card_type < NV_20) + if (nv_device(drm->device)->card_type < NV_20) nv04_update_arb(dev, vclk, bpp, burst, lwm); else if ((dev->pci_device & 0xfff0) == 0x0240 /*CHIPSET_C51*/ || (dev->pci_device & 0xfff0) == 0x03d0 /*CHIPSET_C512*/) { diff --git a/drivers/gpu/drm/nouveau/nouveau_compat.c b/drivers/gpu/drm/nouveau/nouveau_compat.c deleted file mode 100644 index 3db23496dff6..000000000000 --- a/drivers/gpu/drm/nouveau/nouveau_compat.c +++ /dev/null @@ -1,609 +0,0 @@ -#include "nouveau_drm.h" -#include "nouveau_chan.h" -#include "nouveau_compat.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -int -nvdrm_gart_init(struct drm_device *dev, u64 *base, u64 *size) -{ - struct nouveau_drm *drm = nouveau_newpriv(dev); - if (drm->agp.stat == ENABLED) { - *base = drm->agp.base; - *size = drm->agp.base; - return 0; - } - return -ENODEV; -} - -u8 -_nv_rd08(struct drm_device *dev, u32 reg) -{ - struct nouveau_drm *drm = nouveau_newpriv(dev); - return nv_ro08(drm->device, reg); -} - -void -_nv_wr08(struct drm_device *dev, u32 reg, u8 val) -{ - struct nouveau_drm *drm = nouveau_newpriv(dev); - nv_wo08(drm->device, reg, val); -} - -u32 -_nv_rd32(struct drm_device *dev, u32 reg) -{ - struct nouveau_drm *drm = nouveau_newpriv(dev); - return nv_ro32(drm->device, reg); -} - -void -_nv_wr32(struct drm_device *dev, u32 reg, u32 val) -{ - struct nouveau_drm *drm = nouveau_newpriv(dev); - nv_wo32(drm->device, reg, val); -} - -u32 -_nv_mask(struct drm_device *dev, u32 reg, u32 mask, u32 val) -{ - u32 tmp = _nv_rd32(dev, reg); - _nv_wr32(dev, reg, (tmp & ~mask) | val); - return tmp; -} - -bool -_nv_bios(struct drm_device *dev, u8 **data, u32 *size) -{ - struct nouveau_drm *drm = nouveau_newpriv(dev); - struct nouveau_bios *bios = nouveau_bios(drm->device); - *data = bios->data; - *size = bios->size; - return true; -} - -void -nouveau_gpio_reset(struct drm_device *dev) -{ - struct nouveau_drm *drm = nouveau_newpriv(dev); - struct nouveau_gpio *gpio = nouveau_gpio(drm->device); - gpio->reset(gpio); -} - -int -nouveau_gpio_find(struct drm_device *dev, int idx, u8 tag, u8 line, - struct dcb_gpio_func *func) -{ - struct nouveau_drm *drm = nouveau_newpriv(dev); - struct nouveau_gpio *gpio = nouveau_gpio(drm->device); - - return gpio->find(gpio, idx, tag, line, func); -} - -bool -nouveau_gpio_func_valid(struct drm_device *dev, u8 tag) -{ - struct nouveau_drm *drm = nouveau_newpriv(dev); - struct nouveau_gpio *gpio = nouveau_gpio(drm->device); - struct dcb_gpio_func func; - - return gpio->find(gpio, 0, tag, 0xff, &func) == 0; -} - -int -nouveau_gpio_func_set(struct drm_device *dev, u8 tag, int state) -{ - struct nouveau_drm *drm = nouveau_newpriv(dev); - struct nouveau_gpio *gpio = nouveau_gpio(drm->device); - if (gpio && gpio->get) - return gpio->set(gpio, 0, tag, 0xff, state); - return -ENODEV; -} - -int -nouveau_gpio_func_get(struct drm_device *dev, u8 tag) -{ - struct nouveau_drm *drm = nouveau_newpriv(dev); - struct nouveau_gpio *gpio = nouveau_gpio(drm->device); - if (gpio && gpio->get) - return gpio->get(gpio, 0, tag, 0xff); - return -ENODEV; -} - -int -nouveau_gpio_irq(struct drm_device *dev, int idx, u8 tag, u8 line, bool on) -{ - struct nouveau_drm *drm = nouveau_newpriv(dev); - struct nouveau_gpio *gpio = nouveau_gpio(drm->device); - if (gpio && gpio->irq) - return gpio->irq(gpio, idx, tag, line, on); - return -ENODEV; -} - -int -nouveau_gpio_isr_add(struct drm_device *dev, int idx, u8 tag, u8 line, - void (*exec)(void *, int state), void *data) -{ - struct nouveau_drm *drm = nouveau_newpriv(dev); - struct nouveau_gpio *gpio = nouveau_gpio(drm->device); - if (gpio && gpio->isr_add) - return gpio->isr_add(gpio, idx, tag, line, exec, data); - return -ENODEV; -} - -void -nouveau_gpio_isr_del(struct drm_device *dev, int idx, u8 tag, u8 line, - void (*exec)(void *, int state), void *data) -{ - struct nouveau_drm *drm = nouveau_newpriv(dev); - struct nouveau_gpio *gpio = nouveau_gpio(drm->device); - if (gpio && gpio->isr_del) - gpio->isr_del(gpio, idx, tag, line, exec, data); -} - -struct nouveau_i2c_port * -nouveau_i2c_find(struct drm_device *dev, u8 index) -{ - struct nouveau_drm *drm = nouveau_newpriv(dev); - struct nouveau_i2c *i2c = nouveau_i2c(drm->device); - - return i2c->find(i2c, index); -} - -bool -nouveau_probe_i2c_addr(struct nouveau_i2c_port *port, int addr) -{ - return nv_probe_i2c(port, addr); -} - -struct i2c_adapter * -nouveau_i2c_adapter(struct nouveau_i2c_port *port) -{ - return &port->adapter; -} - - -int -nouveau_i2c_identify(struct drm_device *dev, const char *what, - struct i2c_board_info *info, - bool (*match)(struct nouveau_i2c_port *, - struct i2c_board_info *), - int index) -{ - struct nouveau_drm *drm = nouveau_newpriv(dev); - struct nouveau_i2c *i2c = nouveau_i2c(drm->device); - - return i2c->identify(i2c, index, what, info, match); -} - -int -auxch_rd(struct drm_device *dev, struct nouveau_i2c_port *port, - u32 addr, u8 *data, u8 size) -{ - return nv_rdaux(port, addr, data, size); -} - -int -auxch_wr(struct drm_device *dev, struct nouveau_i2c_port *port, - u32 addr, u8 *data, u8 size) -{ - return nv_wraux(port, addr, data, size); -} - -u32 -get_pll_register(struct drm_device *dev, u32 type) -{ - struct nouveau_drm *drm = nouveau_newpriv(dev); - struct nouveau_bios *bios = nouveau_bios(drm->device); - struct nvbios_pll info; - - if (nvbios_pll_parse(bios, type, &info)) - return 0; - return info.reg; -} - -int -get_pll_limits(struct drm_device *dev, u32 type, struct nvbios_pll *info) -{ - struct nouveau_drm *drm = nouveau_newpriv(dev); - struct nouveau_bios *bios = nouveau_bios(drm->device); - - return nvbios_pll_parse(bios, type, info); -} - -int -setPLL(struct drm_device *dev, u32 reg, u32 freq) -{ - struct nouveau_drm *drm = nouveau_newpriv(dev); - struct nouveau_clock *clk = nouveau_clock(drm->device); - int ret = -ENODEV; - - if (clk->pll_set) - ret = clk->pll_set(clk, reg, freq); - return ret; -} - - -int -nouveau_calc_pll_mnp(struct drm_device *dev, struct nvbios_pll *info, - int freq, struct nouveau_pll_vals *pv) -{ - struct nouveau_drm *drm = nouveau_newpriv(dev); - struct nouveau_clock *clk = nouveau_clock(drm->device); - int ret = 0; - - if (clk->pll_calc) - ret = clk->pll_calc(clk, info, freq, pv); - return ret; -} - -int -nouveau_hw_setpll(struct drm_device *dev, u32 reg1, - struct nouveau_pll_vals *pv) -{ - struct nouveau_drm *drm = nouveau_newpriv(dev); - struct nouveau_clock *clk = nouveau_clock(drm->device); - int ret = -ENODEV; - - if (clk->pll_prog) - ret = clk->pll_prog(clk, reg1, pv); - return ret; -} - -int nva3_pll_calc(struct nouveau_clock *, struct nvbios_pll *, u32 freq, - int *N, int *fN, int *M, int *P); - -int -nva3_calc_pll(struct drm_device *dev, struct nvbios_pll *info, u32 freq, - int *N, int *fN, int *M, int *P) -{ - struct nouveau_drm *drm = nouveau_newpriv(dev); - struct nouveau_clock *clk = nouveau_clock(drm->device); - - return nva3_pll_calc(clk, info, freq, N, fN, M, P); -} - -void -nouveau_bios_run_init_table(struct drm_device *dev, uint16_t table, - struct dcb_output *dcbent, int crtc) -{ - struct nouveau_drm *drm = nouveau_newpriv(dev); - struct nouveau_bios *bios = nouveau_bios(drm->device); - struct nvbios_init init = { - .subdev = nv_subdev(bios), - .bios = bios, - .offset = table, - .outp = dcbent, - .crtc = crtc, - .execute = 1 - }; - - nvbios_exec(&init); -} - -void -nouveau_bios_init_exec(struct drm_device *dev, uint16_t table) -{ - nouveau_bios_run_init_table(dev, table, NULL, 0); -} - -void -nv_intr(struct drm_device *dev) -{ - struct nouveau_drm *drm = nouveau_newpriv(dev); - struct nouveau_mc *pmc = nouveau_mc(drm->device); - nv_subdev(pmc)->intr(&pmc->base); -} - -bool nouveau_wait_eq(struct drm_device *dev, uint64_t timeout, - uint32_t reg, uint32_t mask, uint32_t val) -{ - struct nouveau_drm *drm = nouveau_newpriv(dev); - return nouveau_timer_wait_eq(drm->device, timeout, reg, mask, val); -} - -bool nouveau_wait_ne(struct drm_device *dev, uint64_t timeout, - uint32_t reg, uint32_t mask, uint32_t val) -{ - struct nouveau_drm *drm = nouveau_newpriv(dev); - return nouveau_timer_wait_ne(drm->device, timeout, reg, mask, val); -} - -bool nouveau_wait_cb(struct drm_device *dev, u64 timeout, - bool (*cond)(void *), void *data) -{ - struct nouveau_drm *drm = nouveau_newpriv(dev); - return nouveau_timer_wait_cb(drm->device, timeout, cond, data); -} - -u64 -nv_timer_read(struct drm_device *dev) -{ - struct nouveau_drm *drm = nouveau_newpriv(dev); - struct nouveau_timer *ptimer = nouveau_timer(drm->device); - return ptimer->read(ptimer); -} - -int -nvfb_tile_nr(struct drm_device *dev) -{ - struct nouveau_drm *drm = nouveau_newpriv(dev); - struct nouveau_fb *pfb = nouveau_fb(drm->device); - return pfb->tile.regions; -} - -struct nouveau_fb_tile * -nvfb_tile(struct drm_device *dev, int i) -{ - struct nouveau_drm *drm = nouveau_newpriv(dev); - struct nouveau_fb *pfb = nouveau_fb(drm->device); - return &pfb->tile.region[i]; -} - -void -nvfb_tile_init(struct drm_device *dev, int i, u32 a, u32 b, u32 c, u32 d) -{ - struct nouveau_drm *drm = nouveau_newpriv(dev); - struct nouveau_fb *pfb = nouveau_fb(drm->device); - pfb->tile.init(pfb, i, a, b, c, d, &pfb->tile.region[i]); -} - -void -nvfb_tile_fini(struct drm_device *dev, int i) -{ - struct nouveau_drm *drm = nouveau_newpriv(dev); - struct nouveau_fb *pfb = nouveau_fb(drm->device); - pfb->tile.fini(pfb, i, &pfb->tile.region[i]); -} - -void -nvfb_tile_prog(struct drm_device *dev, int i) -{ - struct nouveau_drm *drm = nouveau_newpriv(dev); - struct nouveau_fb *pfb = nouveau_fb(drm->device); - pfb->tile.prog(pfb, i, &pfb->tile.region[i]); -} - -bool -nvfb_flags_valid(struct drm_device *dev, u32 flags) -{ - struct nouveau_drm *drm = nouveau_newpriv(dev); - struct nouveau_fb *pfb = nouveau_fb(drm->device); - return pfb->memtype_valid(pfb, flags); -} - -int -nvfb_vram_get(struct drm_device *dev, u64 size, u32 align, u32 ncmin, - u32 memtype, struct nouveau_mem **pmem) -{ - struct nouveau_drm *drm = nouveau_newpriv(dev); - struct nouveau_fb *pfb = nouveau_fb(drm->device); - int ret = pfb->ram.get(pfb, size, align, ncmin, memtype, pmem); - if (ret) - return ret; - (*pmem)->dev = dev; - return 0; -} - -void -nvfb_vram_put(struct drm_device *dev, struct nouveau_mem **pmem) -{ - struct nouveau_drm *drm = nouveau_newpriv(dev); - struct nouveau_fb *pfb = nouveau_fb(drm->device); - pfb->ram.put(pfb, pmem); -} - - -u64 nvfb_vram_sys_base(struct drm_device *dev) -{ - struct nouveau_drm *drm = nouveau_newpriv(dev); - struct nouveau_fb *pfb = nouveau_fb(drm->device); - return pfb->ram.stolen; -} - -u64 nvfb_vram_size(struct drm_device *dev) -{ - struct nouveau_drm *drm = nouveau_newpriv(dev); - struct nouveau_fb *pfb = nouveau_fb(drm->device); - return pfb->ram.size; -} - -int nvfb_vram_type(struct drm_device *dev) -{ - struct nouveau_drm *drm = nouveau_newpriv(dev); - struct nouveau_fb *pfb = nouveau_fb(drm->device); - return pfb->ram.type; -} - -int nvfb_vram_rank_B(struct drm_device *dev) -{ - struct nouveau_drm *drm = nouveau_newpriv(dev); - struct nouveau_fb *pfb = nouveau_fb(drm->device); - return pfb->ram.ranks > 1; -} - -void -nv50_fb_vm_trap(struct drm_device *dev, int disp) -{ - struct nouveau_drm *drm = nouveau_newpriv(dev); - nv50_fb_trap(nouveau_fb(drm->device), disp); -} - -#include - -struct nouveau_gpuobj * -nvimem_ramro(struct drm_device *dev) -{ - struct nouveau_drm *drm = nouveau_newpriv(dev); - struct nv04_instmem_priv *imem = (void *)nouveau_instmem(drm->device); - return imem->ramro; -} - -struct nouveau_gpuobj * -nvimem_ramfc(struct drm_device *dev) -{ - struct nouveau_drm *drm = nouveau_newpriv(dev); - struct nv04_instmem_priv *imem = (void *)nouveau_instmem(drm->device); - return imem->ramfc; -} - -int _nouveau_gpuobj_new(struct drm_device *dev, struct nouveau_gpuobj *par, - int size, int align, u32 flags, - struct nouveau_gpuobj **pobj) -{ - struct nouveau_drm *drm = nouveau_newpriv(dev); - int ret; - - if (!par) - flags |= NVOBJ_FLAG_HEAP; - - ret = nouveau_gpuobj_new(drm->device, nv_object(par), size, align, - flags, pobj); - if (ret) - return ret; - - (*pobj)->dev = dev; - return 0; -} - -u32 nv_ri32(struct drm_device *dev , u32 addr) -{ - struct nouveau_drm *drm = nouveau_newpriv(dev); - struct nouveau_instmem *imem = nouveau_instmem(drm->device); - return nv_ro32(imem, addr); -} - -void nv_wi32(struct drm_device *dev, u32 addr, u32 data) -{ - struct nouveau_drm *drm = nouveau_newpriv(dev); - struct nouveau_instmem *imem = nouveau_instmem(drm->device); - nv_wo32(imem, addr, data); -} - -u32 nvimem_reserved(struct drm_device *dev) -{ - struct nouveau_drm *drm = nouveau_newpriv(dev); - struct nouveau_instmem *imem = nouveau_instmem(drm->device); - return imem->reserved; -} - -int -nvbar_map(struct drm_device *dev, struct nouveau_mem *mem, u32 flags, - struct nouveau_vma *vma) -{ - struct nouveau_drm *drm = nouveau_newpriv(dev); - struct nouveau_bar *bar = nouveau_bar(drm->device); - return bar->umap(bar, mem, flags, vma); -} - -void -nvbar_unmap(struct drm_device *dev, struct nouveau_vma *vma) -{ - struct nouveau_drm *drm = nouveau_newpriv(dev); - struct nouveau_bar *bar = nouveau_bar(drm->device); - bar->unmap(bar, vma); -} - -int -nouveau_gpuobj_map_bar(struct nouveau_gpuobj *gpuobj, u32 flags, - struct nouveau_vma *vma) -{ - struct nouveau_drm *drm = nouveau_newpriv(gpuobj->dev); - struct nouveau_bar *bar = nouveau_bar(drm->device); - struct nouveau_instobj *iobj = (void *) - nv_pclass(nv_object(gpuobj), NV_MEMOBJ_CLASS); - struct nouveau_mem **mem = (void *)(iobj + 1); - struct nouveau_mem *node = *mem; - - return bar->umap(bar, node, flags, vma); -} - -void -nvimem_flush(struct drm_device *dev) -{ -} - -void _nv50_vm_flush_engine(struct drm_device *dev, int engine) -{ - struct nouveau_drm *drm = nouveau_newpriv(dev); - nv50_vm_flush_engine(nv_subdev(drm->device), engine); -} - -int _nouveau_vm_new(struct drm_device *dev, u64 offset, u64 length, - u64 mm_offset, struct nouveau_vm **pvm) -{ - struct nouveau_drm *drm = nouveau_newpriv(dev); - return nouveau_vm_new(nv_device(drm->device), offset, length, mm_offset, pvm); -} - -#include -struct nouveau_vm * -nv04vm_ref(struct drm_device *dev) -{ - struct nouveau_drm *drm = nouveau_newpriv(dev); - struct nouveau_vmmgr *vmm = nouveau_vmmgr(drm->device); - struct nv04_vmmgr_priv *priv = (void *)vmm; - return priv->vm; -} - -struct nouveau_gpuobj * -nv04vm_refdma(struct drm_device *dev) -{ - struct nouveau_gpuobj *gpuobj = NULL; - nouveau_gpuobj_ref(nv04vm_ref(dev)->pgt[0].obj[0], &gpuobj); - return gpuobj; -} - -void -nvvm_engref(struct nouveau_vm *vm, int eng, int ref) -{ - atomic_add(ref, &vm->engref[eng]); -} - -int -nvvm_spg_shift(struct nouveau_vm *vm) -{ - return vm->vmm->spg_shift; -} - -int -nvvm_lpg_shift(struct nouveau_vm *vm) -{ - return vm->vmm->lpg_shift; -} - -u64 nvgpuobj_addr(struct nouveau_object *object) -{ - return nv_gpuobj(object)->addr; -} - -struct drm_device * -nouveau_drv(void *ptr) -{ - struct nouveau_drm *drm = ptr; - return drm->dev; -} - -struct nouveau_channel * -nvdrm_channel(struct drm_device *dev) -{ - struct nouveau_drm *drm = nouveau_newpriv(dev); - return drm->channel; -} - -struct mutex * -nvchan_mutex(struct nouveau_channel *chan) -{ - return &chan->cli->mutex; -} diff --git a/drivers/gpu/drm/nouveau/nouveau_compat.h b/drivers/gpu/drm/nouveau/nouveau_compat.h deleted file mode 100644 index 9f42d1d0f868..000000000000 --- a/drivers/gpu/drm/nouveau/nouveau_compat.h +++ /dev/null @@ -1,141 +0,0 @@ -#ifndef __NOUVEAU_COMPAT_H__ -#define __NOUVEAU_COMPAT_H__ - -int nvdrm_gart_init(struct drm_device *, u64 *, u64 *); - -u8 _nv_rd08(struct drm_device *, u32); -void _nv_wr08(struct drm_device *, u32, u8); -u32 _nv_rd32(struct drm_device *, u32); -void _nv_wr32(struct drm_device *, u32, u32); -u32 _nv_mask(struct drm_device *, u32, u32, u32); - -bool _nv_bios(struct drm_device *, u8 **, u32 *); - -struct dcb_gpio_func; -void nouveau_gpio_reset(struct drm_device *); -int nouveau_gpio_find(struct drm_device *, int, u8, u8, struct dcb_gpio_func *); -bool nouveau_gpio_func_valid(struct drm_device *, u8 tag); -int nouveau_gpio_func_set(struct drm_device *, u8 tag, int state); -int nouveau_gpio_func_get(struct drm_device *, u8 tag); -int nouveau_gpio_irq(struct drm_device *, int idx, u8 tag, u8 line, bool on); -int nouveau_gpio_isr_add(struct drm_device *, int idx, u8 tag, u8 line, - void (*)(void *, int state), void *data); -void nouveau_gpio_isr_del(struct drm_device *, int idx, u8 tag, u8 line, - void (*)(void *, int state), void *data); - -struct nouveau_i2c_port *nouveau_i2c_find(struct drm_device *, u8); -bool nouveau_probe_i2c_addr(struct nouveau_i2c_port *, int addr); -struct i2c_adapter *nouveau_i2c_adapter(struct nouveau_i2c_port *); -int nouveau_i2c_identify(struct drm_device *dev, const char *what, - struct i2c_board_info *info, - bool (*match)(struct nouveau_i2c_port *, - struct i2c_board_info *), int index); - -int auxch_rd(struct drm_device *, struct nouveau_i2c_port *, u32, u8 *, u8); -int auxch_wr(struct drm_device *, struct nouveau_i2c_port *, u32, u8 *, u8); - -struct nvbios_pll; -struct nouveau_pll_vals; - -u32 get_pll_register(struct drm_device *dev, u32 type); -int get_pll_limits(struct drm_device *, u32, struct nvbios_pll *); -int setPLL(struct drm_device *, u32 reg, u32 clk); - -int nouveau_calc_pll_mnp(struct drm_device *, struct nvbios_pll *, - int, struct nouveau_pll_vals *); -int nva3_calc_pll(struct drm_device *dev, struct nvbios_pll *info, u32 freq, - int *N, int *fN, int *M, int *P); -int nouveau_hw_setpll(struct drm_device *, u32, struct nouveau_pll_vals *); - -struct dcb_output; -void nouveau_bios_run_init_table(struct drm_device *, u16, struct dcb_output *, int); -void nouveau_bios_init_exec(struct drm_device *, u16); - -void nv_intr(struct drm_device *); - -bool nouveau_wait_eq(struct drm_device *, uint64_t timeout, - uint32_t reg, uint32_t mask, uint32_t val); -bool nouveau_wait_ne(struct drm_device *, uint64_t timeout, - uint32_t reg, uint32_t mask, uint32_t val); -bool nouveau_wait_cb(struct drm_device *, u64 timeout, - bool (*cond)(void *), void *); - -u64 nv_timer_read(struct drm_device *); - -int nvfb_tile_nr(struct drm_device *); -void nvfb_tile_init(struct drm_device *, int, u32, u32, u32, u32); -void nvfb_tile_fini(struct drm_device *, int); -void nvfb_tile_prog(struct drm_device *, int); - -struct nouveau_fb_tile *nvfb_tile(struct drm_device *, int); - -struct nouveau_mem; -int nvfb_vram_get(struct drm_device *dev, u64 size, u32 align, u32 ncmin, - u32 memtype, struct nouveau_mem **pmem); -void nvfb_vram_put(struct drm_device *dev, struct nouveau_mem **pmem); -bool nvfb_flags_valid(struct drm_device *dev, u32); - -u64 nvfb_vram_sys_base(struct drm_device *); -u64 nvfb_vram_size(struct drm_device *); -int nvfb_vram_type(struct drm_device *); -int nvfb_vram_rank_B(struct drm_device *); - -void nv50_fb_vm_trap(struct drm_device *, int); - -struct nouveau_gpuobj *nvimem_ramro(struct drm_device *); -struct nouveau_gpuobj *nvimem_ramfc(struct drm_device *); - -int _nouveau_gpuobj_new(struct drm_device *dev, struct nouveau_gpuobj *par, - int size, int align, u32 flags, - struct nouveau_gpuobj **pboj); - -u32 nv_ri32(struct drm_device *, u32); -void nv_wi32(struct drm_device *, u32, u32); -u32 nvimem_reserved(struct drm_device *); - -void nvimem_flush(struct drm_device *); - -void _nv50_vm_flush_engine(struct drm_device *dev, int engine); - -int _nouveau_vm_new(struct drm_device *, u64 offset, u64 length, - u64 mm_offset, struct nouveau_vm **); - -struct nouveau_vma; -int nouveau_gpuobj_map_bar(struct nouveau_gpuobj *, u32, struct nouveau_vma *); - -int -nvbar_map(struct drm_device *dev, struct nouveau_mem *mem, u32 flags, - struct nouveau_vma *vma); -void -nvbar_unmap(struct drm_device *dev, struct nouveau_vma *vma); - -struct nouveau_vm * -nv04vm_ref(struct drm_device *dev); - -struct nouveau_gpuobj * -nv04vm_refdma(struct drm_device *dev); - -void -nvvm_engref(struct nouveau_vm *, int, int); - -int -nvvm_spg_shift(struct nouveau_vm *); - -int -nvvm_lpg_shift(struct nouveau_vm *); - -u32 -nv50_display_active_crtcs(struct drm_device *dev); - -u64 nvgpuobj_addr(struct nouveau_object *object); - -struct drm_device * -nouveau_drv(void *drm); - -struct nouveau_channel * -nvdrm_channel(struct drm_device *dev); - -struct mutex * -nvchan_mutex(struct nouveau_channel *chan); - -#endif diff --git a/drivers/gpu/drm/nouveau/nouveau_connector.c b/drivers/gpu/drm/nouveau/nouveau_connector.c index 5dbf2e45993d..702e2a74d2d1 100644 --- a/drivers/gpu/drm/nouveau/nouveau_connector.c +++ b/drivers/gpu/drm/nouveau/nouveau_connector.c @@ -31,14 +31,29 @@ #include "drm_crtc_helper.h" #include "nouveau_reg.h" -#include "nouveau_drv.h" -#include "nouveau_encoder.h" -#include "nouveau_crtc.h" -#include "nouveau_connector.h" +#include "nouveau_drm.h" #include "nouveau_hw.h" #include "nouveau_acpi.h" -#include +#include "nouveau_display.h" +#include "nouveau_connector.h" +#include "nouveau_encoder.h" +#include "nouveau_crtc.h" + +#include +#include + +MODULE_PARM_DESC(tv_disable, "Disable TV-out detection"); +static int nouveau_tv_disable = 0; +module_param_named(tv_disable, nouveau_tv_disable, int, 0400); + +MODULE_PARM_DESC(ignorelid, "Ignore ACPI lid status"); +static int nouveau_ignorelid = 0; +module_param_named(ignorelid, nouveau_ignorelid, int, 0400); + +MODULE_PARM_DESC(duallink, "Allow dual-link TMDS (default: enabled)"); +static int nouveau_duallink = 1; +module_param_named(duallink, nouveau_duallink, int, 0400); static void nouveau_connector_hotplug(void *, int); @@ -85,19 +100,21 @@ static void nouveau_connector_destroy(struct drm_connector *connector) { struct nouveau_connector *nv_connector = nouveau_connector(connector); - struct drm_nouveau_private *dev_priv; + struct nouveau_gpio *gpio; + struct nouveau_drm *drm; struct drm_device *dev; if (!nv_connector) return; - dev = nv_connector->base.dev; - dev_priv = dev->dev_private; - NV_DEBUG_KMS(dev, "\n"); + dev = nv_connector->base.dev; + drm = nouveau_drm(dev); + gpio = nouveau_gpio(drm->device); + NV_DEBUG(drm, "\n"); - if (nv_connector->hpd != DCB_GPIO_UNUSED) { - nouveau_gpio_isr_del(dev, 0, nv_connector->hpd, 0xff, - nouveau_connector_hotplug, connector); + if (gpio && nv_connector->hpd != DCB_GPIO_UNUSED) { + gpio->isr_del(gpio, 0, nv_connector->hpd, 0xff, + nouveau_connector_hotplug, connector); } kfree(nv_connector->edid); @@ -111,10 +128,12 @@ nouveau_connector_ddc_detect(struct drm_connector *connector, struct nouveau_encoder **pnv_encoder) { struct drm_device *dev = connector->dev; + struct nouveau_drm *drm = nouveau_drm(dev); + struct nouveau_i2c *i2c = nouveau_i2c(drm->device); int i; for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++) { - struct nouveau_i2c_port *i2c = NULL; + struct nouveau_i2c_port *port = NULL; struct nouveau_encoder *nv_encoder; struct drm_mode_object *obj; int id; @@ -129,11 +148,10 @@ nouveau_connector_ddc_detect(struct drm_connector *connector, nv_encoder = nouveau_encoder(obj_to_encoder(obj)); if (nv_encoder->dcb->i2c_index < 0xf) - i2c = nouveau_i2c_find(dev, nv_encoder->dcb->i2c_index); - - if (i2c && nouveau_probe_i2c_addr(i2c, 0x50)) { + port = i2c->find(i2c, nv_encoder->dcb->i2c_index); + if (port && nv_probe_i2c(port, 0x50)) { *pnv_encoder = nv_encoder; - return i2c; + return port; } } @@ -175,14 +193,14 @@ nouveau_connector_set_encoder(struct drm_connector *connector, struct nouveau_encoder *nv_encoder) { struct nouveau_connector *nv_connector = nouveau_connector(connector); - struct drm_nouveau_private *dev_priv = connector->dev->dev_private; + struct nouveau_drm *drm = nouveau_drm(connector->dev); struct drm_device *dev = connector->dev; if (nv_connector->detected_encoder == nv_encoder) return; nv_connector->detected_encoder = nv_encoder; - if (dev_priv->card_type >= NV_50) { + if (nv_device(drm->device)->card_type >= NV_50) { connector->interlace_allowed = true; connector->doublescan_allowed = true; } else @@ -192,8 +210,8 @@ nouveau_connector_set_encoder(struct drm_connector *connector, connector->interlace_allowed = false; } else { connector->doublescan_allowed = true; - if (dev_priv->card_type == NV_20 || - (dev_priv->card_type == NV_10 && + if (nv_device(drm->device)->card_type == NV_20 || + (nv_device(drm->device)->card_type == NV_10 && (dev->pci_device & 0x0ff0) != 0x0100 && (dev->pci_device & 0x0ff0) != 0x0150)) /* HW is broken */ @@ -215,6 +233,7 @@ static enum drm_connector_status nouveau_connector_detect(struct drm_connector *connector, bool force) { struct drm_device *dev = connector->dev; + struct nouveau_drm *drm = nouveau_drm(dev); struct nouveau_connector *nv_connector = nouveau_connector(connector); struct nouveau_encoder *nv_encoder = NULL; struct nouveau_encoder *nv_partner; @@ -230,18 +249,18 @@ nouveau_connector_detect(struct drm_connector *connector, bool force) i2c = nouveau_connector_ddc_detect(connector, &nv_encoder); if (i2c) { - nv_connector->edid = drm_get_edid(connector, nouveau_i2c_adapter(i2c)); + nv_connector->edid = drm_get_edid(connector, &i2c->adapter); drm_mode_connector_update_edid_property(connector, nv_connector->edid); if (!nv_connector->edid) { - NV_ERROR(dev, "DDC responded, but no EDID for %s\n", + NV_ERROR(drm, "DDC responded, but no EDID for %s\n", drm_get_connector_name(connector)); goto detect_analog; } if (nv_encoder->dcb->type == DCB_OUTPUT_DP && !nouveau_dp_detect(to_drm_encoder(nv_encoder))) { - NV_ERROR(dev, "Detected %s, but failed init\n", + NV_ERROR(drm, "Detected %s, but failed init\n", drm_get_connector_name(connector)); return connector_status_disconnected; } @@ -303,7 +322,7 @@ static enum drm_connector_status nouveau_connector_detect_lvds(struct drm_connector *connector, bool force) { struct drm_device *dev = connector->dev; - struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_drm *drm = nouveau_drm(dev); struct nouveau_connector *nv_connector = nouveau_connector(connector); struct nouveau_encoder *nv_encoder = NULL; enum drm_connector_status status = connector_status_disconnected; @@ -320,7 +339,7 @@ nouveau_connector_detect_lvds(struct drm_connector *connector, bool force) return connector_status_disconnected; /* Try retrieving EDID via DDC */ - if (!dev_priv->vbios.fp_no_ddc) { + if (!drm->vbios.fp_no_ddc) { status = nouveau_connector_detect(connector, force); if (status == connector_status_connected) goto out; @@ -346,7 +365,7 @@ nouveau_connector_detect_lvds(struct drm_connector *connector, bool force) * modeline is avalilable for the panel, set it as the panel's * native mode and exit. */ - if (nouveau_bios_fp_mode(dev, NULL) && (dev_priv->vbios.fp_no_ddc || + if (nouveau_bios_fp_mode(dev, NULL) && (drm->vbios.fp_no_ddc || nv_encoder->dcb->lvdsconf.use_straps_for_mode)) { status = connector_status_connected; goto out; @@ -355,7 +374,7 @@ nouveau_connector_detect_lvds(struct drm_connector *connector, bool force) /* Still nothing, some VBIOS images have a hardcoded EDID block * stored for the panel stored in them. */ - if (!dev_priv->vbios.fp_no_ddc) { + if (!drm->vbios.fp_no_ddc) { struct edid *edid = (struct edid *)nouveau_bios_embedded_edid(dev); if (edid) { @@ -381,6 +400,7 @@ out: static void nouveau_connector_force(struct drm_connector *connector) { + struct nouveau_drm *drm = nouveau_drm(connector->dev); struct nouveau_connector *nv_connector = nouveau_connector(connector); struct nouveau_encoder *nv_encoder; int type; @@ -395,7 +415,7 @@ nouveau_connector_force(struct drm_connector *connector) nv_encoder = find_encoder(connector, type); if (!nv_encoder) { - NV_ERROR(connector->dev, "can't find encoder to force %s on!\n", + NV_ERROR(drm, "can't find encoder to force %s on!\n", drm_get_connector_name(connector)); connector->status = connector_status_disconnected; return; @@ -408,8 +428,7 @@ static int nouveau_connector_set_property(struct drm_connector *connector, struct drm_property *property, uint64_t value) { - struct drm_nouveau_private *dev_priv = connector->dev->dev_private; - struct nouveau_display_engine *disp = &dev_priv->engine.display; + struct nouveau_display *disp = nouveau_display(connector->dev); struct nouveau_connector *nv_connector = nouveau_connector(connector); struct nouveau_encoder *nv_encoder = nv_connector->detected_encoder; struct drm_encoder *encoder = to_drm_encoder(nv_encoder); @@ -545,6 +564,7 @@ static struct drm_display_mode * nouveau_connector_native_mode(struct drm_connector *connector) { struct drm_connector_helper_funcs *helper = connector->helper_private; + struct nouveau_drm *drm = nouveau_drm(connector->dev); struct nouveau_connector *nv_connector = nouveau_connector(connector); struct drm_device *dev = connector->dev; struct drm_display_mode *mode, *largest = NULL; @@ -558,7 +578,7 @@ nouveau_connector_native_mode(struct drm_connector *connector) /* Use preferred mode if there is one.. */ if (mode->type & DRM_MODE_TYPE_PREFERRED) { - NV_DEBUG_KMS(dev, "native mode from preferred\n"); + NV_DEBUG(drm, "native mode from preferred\n"); return drm_mode_duplicate(dev, mode); } @@ -581,7 +601,7 @@ nouveau_connector_native_mode(struct drm_connector *connector) largest = mode; } - NV_DEBUG_KMS(dev, "native mode from largest: %dx%d@%d\n", + NV_DEBUG(drm, "native mode from largest: %dx%d@%d\n", high_w, high_h, high_v); return largest ? drm_mode_duplicate(dev, largest) : NULL; } @@ -645,10 +665,10 @@ nouveau_connector_scaler_modes_add(struct drm_connector *connector) static void nouveau_connector_detect_depth(struct drm_connector *connector) { - struct drm_nouveau_private *dev_priv = connector->dev->dev_private; + struct nouveau_drm *drm = nouveau_drm(connector->dev); struct nouveau_connector *nv_connector = nouveau_connector(connector); struct nouveau_encoder *nv_encoder = nv_connector->detected_encoder; - struct nvbios *bios = &dev_priv->vbios; + struct nvbios *bios = &drm->vbios; struct drm_display_mode *mode = nv_connector->native_mode; bool duallink; @@ -695,7 +715,7 @@ static int nouveau_connector_get_modes(struct drm_connector *connector) { struct drm_device *dev = connector->dev; - struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_drm *drm = nouveau_drm(dev); struct nouveau_connector *nv_connector = nouveau_connector(connector); struct nouveau_encoder *nv_encoder = nv_connector->detected_encoder; struct drm_encoder *encoder = to_drm_encoder(nv_encoder); @@ -713,7 +733,7 @@ nouveau_connector_get_modes(struct drm_connector *connector) else if (nv_encoder->dcb->type == DCB_OUTPUT_LVDS && (nv_encoder->dcb->lvdsconf.use_straps_for_mode || - dev_priv->vbios.fp_no_ddc) && nouveau_bios_fp_mode(dev, NULL)) { + drm->vbios.fp_no_ddc) && nouveau_bios_fp_mode(dev, NULL)) { struct drm_display_mode mode; nouveau_bios_fp_mode(dev, &mode); @@ -763,15 +783,15 @@ static unsigned get_tmds_link_bandwidth(struct drm_connector *connector) { struct nouveau_connector *nv_connector = nouveau_connector(connector); - struct drm_nouveau_private *dev_priv = connector->dev->dev_private; + struct nouveau_drm *drm = nouveau_drm(connector->dev); struct dcb_output *dcb = nv_connector->detected_encoder->dcb; if (dcb->location != DCB_LOC_ON_CHIP || - dev_priv->chipset >= 0x46) + nv_device(drm->device)->chipset >= 0x46) return 165000; - else if (dev_priv->chipset >= 0x40) + else if (nv_device(drm->device)->chipset >= 0x40) return 155000; - else if (dev_priv->chipset >= 0x18) + else if (nv_device(drm->device)->chipset >= 0x18) return 135000; else return 112000; @@ -901,14 +921,15 @@ struct drm_connector * nouveau_connector_create(struct drm_device *dev, int index) { const struct drm_connector_funcs *funcs = &nouveau_connector_funcs; - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_display_engine *disp = &dev_priv->engine.display; + struct nouveau_drm *drm = nouveau_drm(dev); + struct nouveau_gpio *gpio = nouveau_gpio(drm->device); + struct nouveau_display *disp = nouveau_display(dev); struct nouveau_connector *nv_connector = NULL; struct drm_connector *connector; int type, ret = 0; bool dummy; - NV_DEBUG_KMS(dev, "\n"); + NV_DEBUG(drm, "\n"); list_for_each_entry(connector, &dev->mode_config.connector_list, head) { nv_connector = nouveau_connector(connector); @@ -941,7 +962,7 @@ nouveau_connector_create(struct drm_device *dev, int index) nv_connector->type = nv_connector->dcb[0]; if (drm_conntype_from_dcb(nv_connector->type) == DRM_MODE_CONNECTOR_Unknown) { - NV_WARN(dev, "unknown connector type %02x\n", + NV_WARN(drm, "unknown connector type %02x\n", nv_connector->type); nv_connector->type = DCB_CONNECTOR_NONE; } @@ -966,8 +987,8 @@ nouveau_connector_create(struct drm_device *dev, int index) * figure out something suitable ourselves */ if (nv_connector->type == DCB_CONNECTOR_NONE) { - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct dcb_table *dcbt = &dev_priv->vbios.dcb; + struct nouveau_drm *drm = nouveau_drm(dev); + struct dcb_table *dcbt = &drm->vbios.dcb; u32 encoders = 0; int i; @@ -1003,7 +1024,7 @@ nouveau_connector_create(struct drm_device *dev, int index) if (type == DRM_MODE_CONNECTOR_LVDS) { ret = nouveau_bios_parse_lvds_table(dev, 0, &dummy, &dummy); if (ret) { - NV_ERROR(dev, "Error parsing LVDS table, disabling\n"); + NV_ERROR(drm, "Error parsing LVDS table, disabling\n"); kfree(nv_connector); return ERR_PTR(ret); } @@ -1053,7 +1074,7 @@ nouveau_connector_create(struct drm_device *dev, int index) switch (nv_connector->type) { case DCB_CONNECTOR_VGA: - if (dev_priv->card_type >= NV_50) { + if (nv_device(drm->device)->card_type >= NV_50) { drm_connector_attach_property(connector, dev->mode_config.scaling_mode_property, nv_connector->scaling_mode); @@ -1086,10 +1107,9 @@ nouveau_connector_create(struct drm_device *dev, int index) } connector->polled = DRM_CONNECTOR_POLL_CONNECT; - if (nv_connector->hpd != DCB_GPIO_UNUSED) { - ret = nouveau_gpio_isr_add(dev, 0, nv_connector->hpd, 0xff, - nouveau_connector_hotplug, - connector); + if (gpio && nv_connector->hpd != DCB_GPIO_UNUSED) { + ret = gpio->isr_add(gpio, 0, nv_connector->hpd, 0xff, + nouveau_connector_hotplug, connector); if (ret == 0) connector->polled = DRM_CONNECTOR_POLL_HPD; } @@ -1103,8 +1123,9 @@ nouveau_connector_hotplug(void *data, int plugged) { struct drm_connector *connector = data; struct drm_device *dev = connector->dev; + struct nouveau_drm *drm = nouveau_drm(dev); - NV_DEBUG(dev, "%splugged %s\n", plugged ? "" : "un", + NV_DEBUG(drm, "%splugged %s\n", plugged ? "" : "un", drm_get_connector_name(connector)); if (plugged) diff --git a/drivers/gpu/drm/nouveau/nouveau_display.c b/drivers/gpu/drm/nouveau/nouveau_display.c index a60a9f51e890..61f370d000e9 100644 --- a/drivers/gpu/drm/nouveau/nouveau_display.c +++ b/drivers/gpu/drm/nouveau/nouveau_display.c @@ -26,18 +26,20 @@ #include "drmP.h" #include "drm_crtc_helper.h" -#include "nouveau_drv.h" -#include "nouveau_fb.h" + #include "nouveau_fbcon.h" #include "nouveau_hw.h" #include "nouveau_crtc.h" #include "nouveau_dma.h" +#include "nouveau_gem.h" #include "nouveau_connector.h" #include "nv50_display.h" #include "nouveau_fence.h" #include +#include +#include static void nouveau_user_framebuffer_destroy(struct drm_framebuffer *drm_fb) @@ -72,7 +74,7 @@ nouveau_framebuffer_init(struct drm_device *dev, struct drm_mode_fb_cmd2 *mode_cmd, struct nouveau_bo *nvbo) { - struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_drm *drm = nouveau_drm(dev); struct drm_framebuffer *fb = &nv_fb->base; int ret; @@ -84,7 +86,7 @@ nouveau_framebuffer_init(struct drm_device *dev, drm_helper_mode_fill_fb_struct(fb, mode_cmd); nv_fb->nvbo = nvbo; - if (dev_priv->card_type >= NV_50) { + if (nv_device(drm->device)->card_type >= NV_50) { u32 tile_flags = nouveau_bo_tile_layout(nvbo); if (tile_flags == 0x7a00 || tile_flags == 0xfe00) @@ -103,21 +105,21 @@ nouveau_framebuffer_init(struct drm_device *dev, case 32: nv_fb->r_format = NV50_EVO_CRTC_FB_DEPTH_24; break; case 30: nv_fb->r_format = NV50_EVO_CRTC_FB_DEPTH_30; break; default: - NV_ERROR(dev, "unknown depth %d\n", fb->depth); + NV_ERROR(drm, "unknown depth %d\n", fb->depth); return -EINVAL; } - if (dev_priv->chipset == 0x50) + if (nv_device(drm->device)->chipset == 0x50) nv_fb->r_format |= (tile_flags << 8); if (!tile_flags) { - if (dev_priv->card_type < NV_D0) + if (nv_device(drm->device)->card_type < NV_D0) nv_fb->r_pitch = 0x00100000 | fb->pitches[0]; else nv_fb->r_pitch = 0x01000000 | fb->pitches[0]; } else { u32 mode = nvbo->tile_mode; - if (dev_priv->card_type >= NV_C0) + if (nv_device(drm->device)->card_type >= NV_C0) mode >>= 4; nv_fb->r_pitch = ((fb->pitches[0] / 4) << 4) | mode; } @@ -213,8 +215,9 @@ static struct nouveau_drm_prop_enum_list dither_depth[] = { int nouveau_display_init(struct drm_device *dev) { - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_display_engine *disp = &dev_priv->engine.display; + struct nouveau_drm *drm = nouveau_drm(dev); + struct nouveau_display *disp = nouveau_display(dev); + struct nouveau_gpio *gpio = nouveau_gpio(drm->device); struct drm_connector *connector; int ret; @@ -226,8 +229,8 @@ nouveau_display_init(struct drm_device *dev) * some vbios default this to off for some reason, causing the * panel to not work after resume */ - if (nouveau_gpio_func_get(dev, DCB_GPIO_PANEL_POWER) == 0) { - nouveau_gpio_func_set(dev, DCB_GPIO_PANEL_POWER, true); + if (gpio && gpio->get(gpio, 0, DCB_GPIO_PANEL_POWER, 0xff) == 0) { + gpio->set(gpio, 0, DCB_GPIO_PANEL_POWER, 0xff, 1); msleep(300); } @@ -237,7 +240,8 @@ nouveau_display_init(struct drm_device *dev) /* enable hotplug interrupts */ list_for_each_entry(connector, &dev->mode_config.connector_list, head) { struct nouveau_connector *conn = nouveau_connector(connector); - nouveau_gpio_irq(dev, 0, conn->hpd, 0xff, true); + if (gpio) + gpio->irq(gpio, 0, conn->hpd, 0xff, true); } return ret; @@ -246,14 +250,16 @@ nouveau_display_init(struct drm_device *dev) void nouveau_display_fini(struct drm_device *dev) { - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_display_engine *disp = &dev_priv->engine.display; + struct nouveau_drm *drm = nouveau_drm(dev); + struct nouveau_display *disp = nouveau_display(dev); + struct nouveau_gpio *gpio = nouveau_gpio(drm->device); struct drm_connector *connector; /* disable hotplug interrupts */ list_for_each_entry(connector, &dev->mode_config.connector_list, head) { struct nouveau_connector *conn = nouveau_connector(connector); - nouveau_gpio_irq(dev, 0, conn->hpd, 0xff, false); + if (gpio) + gpio->irq(gpio, 0, conn->hpd, 0xff, false); } drm_kms_helper_poll_disable(dev); @@ -281,18 +287,28 @@ nouveau_display_vblank_put(void *data, int crtc) int nouveau_display_create(struct drm_device *dev) { - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_display_engine *disp = &dev_priv->engine.display; + struct nouveau_drm *drm = nouveau_drm(dev); + struct nouveau_disp *pdisp = nouveau_disp(drm->device); + struct nouveau_display *disp; int ret, gen; + disp = drm->display = kzalloc(sizeof(*disp), GFP_KERNEL); + if (!disp) + return -ENOMEM; + + pdisp->vblank.data = dev; + pdisp->vblank.notify = nouveau_display_vblank_notify; + pdisp->vblank.get = nouveau_display_vblank_get; + pdisp->vblank.put = nouveau_display_vblank_put; + drm_mode_config_init(dev); drm_mode_create_scaling_mode_property(dev); drm_mode_create_dvi_i_properties(dev); - if (dev_priv->card_type < NV_50) + if (nv_device(drm->device)->card_type < NV_50) gen = 0; else - if (dev_priv->card_type < NV_D0) + if (nv_device(drm->device)->card_type < NV_D0) gen = 1; else gen = 2; @@ -326,11 +342,11 @@ nouveau_display_create(struct drm_device *dev) dev->mode_config.min_width = 0; dev->mode_config.min_height = 0; - if (dev_priv->card_type < NV_10) { + if (nv_device(drm->device)->card_type < NV_10) { dev->mode_config.max_width = 2048; dev->mode_config.max_height = 2048; } else - if (dev_priv->card_type < NV_50) { + if (nv_device(drm->device)->card_type < NV_50) { dev->mode_config.max_width = 4096; dev->mode_config.max_height = 4096; } else { @@ -344,7 +360,13 @@ nouveau_display_create(struct drm_device *dev) drm_kms_helper_poll_init(dev); drm_kms_helper_poll_disable(dev); - ret = disp->create(dev); + if (nv_device(drm->device)->card_type < NV_50) + ret = nv04_display_create(dev); + else + if (nv_device(drm->device)->card_type < NV_D0) + ret = nv50_display_create(dev); + else + ret = nvd0_display_create(dev); if (ret) goto disp_create_err; @@ -354,10 +376,11 @@ nouveau_display_create(struct drm_device *dev) goto vblank_err; } + nouveau_backlight_init(dev); return 0; vblank_err: - disp->destroy(dev); + disp->dtor(dev); disp_create_err: drm_kms_helper_poll_fini(dev); drm_mode_config_cleanup(dev); @@ -367,28 +390,109 @@ disp_create_err: void nouveau_display_destroy(struct drm_device *dev) { - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_display_engine *disp = &dev_priv->engine.display; + struct nouveau_display *disp = nouveau_display(dev); + nouveau_backlight_exit(dev); drm_vblank_cleanup(dev); - disp->destroy(dev); + disp->dtor(dev); drm_kms_helper_poll_fini(dev); drm_mode_config_cleanup(dev); + nouveau_drm(dev)->display = NULL; + kfree(disp); +} + +int +nouveau_display_suspend(struct drm_device *dev) +{ + struct nouveau_drm *drm = nouveau_drm(dev); + struct drm_crtc *crtc; + + nouveau_display_fini(dev); + + NV_INFO(drm, "unpinning framebuffer(s)...\n"); + list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { + struct nouveau_framebuffer *nouveau_fb; + + nouveau_fb = nouveau_framebuffer(crtc->fb); + if (!nouveau_fb || !nouveau_fb->nvbo) + continue; + + nouveau_bo_unpin(nouveau_fb->nvbo); + } + + list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { + struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); + + nouveau_bo_unmap(nv_crtc->cursor.nvbo); + nouveau_bo_unpin(nv_crtc->cursor.nvbo); + } + + return 0; +} + +void +nouveau_display_resume(struct drm_device *dev) +{ + struct nouveau_drm *drm = nouveau_drm(dev); + struct drm_crtc *crtc; + int ret; + + list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { + struct nouveau_framebuffer *nouveau_fb; + + nouveau_fb = nouveau_framebuffer(crtc->fb); + if (!nouveau_fb || !nouveau_fb->nvbo) + continue; + + nouveau_bo_pin(nouveau_fb->nvbo, TTM_PL_FLAG_VRAM); + } + + list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { + struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); + + ret = nouveau_bo_pin(nv_crtc->cursor.nvbo, TTM_PL_FLAG_VRAM); + if (!ret) + ret = nouveau_bo_map(nv_crtc->cursor.nvbo); + if (ret) + NV_ERROR(drm, "Could not pin/map cursor.\n"); + } + + nouveau_fbcon_set_suspend(dev, 0); + nouveau_fbcon_zfill_all(dev); + + nouveau_display_init(dev); + + /* Force CLUT to get re-loaded during modeset */ + list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { + struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); + + nv_crtc->lut.depth = 0; + } + + drm_helper_resume_force_mode(dev); + + list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { + struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); + u32 offset = nv_crtc->cursor.nvbo->bo.offset; + + nv_crtc->cursor.set_offset(nv_crtc, offset); + nv_crtc->cursor.set_pos(nv_crtc, nv_crtc->cursor_saved_x, + nv_crtc->cursor_saved_y); + } } int nouveau_vblank_enable(struct drm_device *dev, int crtc) { - struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_device *device = nouveau_dev(dev); - if (dev_priv->card_type >= NV_D0) - nv_mask(dev, 0x6100c0 + (crtc * 0x800), 1, 1); + if (device->card_type >= NV_D0) + nv_mask(device, 0x6100c0 + (crtc * 0x800), 1, 1); else - - if (dev_priv->card_type >= NV_50) - nv_mask(dev, NV50_PDISPLAY_INTR_EN_1, 0, + if (device->card_type >= NV_50) + nv_mask(device, NV50_PDISPLAY_INTR_EN_1, 0, NV50_PDISPLAY_INTR_EN_1_VBLANK_CRTC_(crtc)); else NVWriteCRTC(dev, crtc, NV_PCRTC_INTR_EN_0, @@ -400,13 +504,13 @@ nouveau_vblank_enable(struct drm_device *dev, int crtc) void nouveau_vblank_disable(struct drm_device *dev, int crtc) { - struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_device *device = nouveau_dev(dev); - if (dev_priv->card_type >= NV_D0) - nv_mask(dev, 0x6100c0 + (crtc * 0x800), 1, 0); + if (device->card_type >= NV_D0) + nv_mask(device, 0x6100c0 + (crtc * 0x800), 1, 0); else - if (dev_priv->card_type >= NV_50) - nv_mask(dev, NV50_PDISPLAY_INTR_EN_1, + if (device->card_type >= NV_50) + nv_mask(device, NV50_PDISPLAY_INTR_EN_1, NV50_PDISPLAY_INTR_EN_1_VBLANK_CRTC_(crtc), 0); else NVWriteCRTC(dev, crtc, NV_PCRTC_INTR_EN_0, 0); @@ -461,8 +565,8 @@ nouveau_page_flip_emit(struct nouveau_channel *chan, struct nouveau_fence **pfence) { struct nouveau_fence_chan *fctx = chan->fence; - struct drm_device *dev = nouveau_drv(chan->drm); - struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_drm *drm = chan->drm; + struct drm_device *dev = drm->dev; unsigned long flags; int ret; @@ -481,7 +585,7 @@ nouveau_page_flip_emit(struct nouveau_channel *chan, if (ret) goto fail; - if (dev_priv->card_type < NV_C0) { + if (nv_device(drm->device)->card_type < NV_C0) { BEGIN_NV04(chan, NvSubSw, NV_SW_PAGE_FLIP, 1); OUT_RING (chan, 0x00000000); OUT_RING (chan, 0x00000000); @@ -509,7 +613,7 @@ nouveau_crtc_page_flip(struct drm_crtc *crtc, struct drm_framebuffer *fb, struct drm_pending_vblank_event *event) { struct drm_device *dev = crtc->dev; - struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_drm *drm = nouveau_drm(dev); struct nouveau_bo *old_bo = nouveau_framebuffer(crtc->fb)->nvbo; struct nouveau_bo *new_bo = nouveau_framebuffer(fb)->nvbo; struct nouveau_page_flip_state *s; @@ -517,7 +621,7 @@ nouveau_crtc_page_flip(struct drm_crtc *crtc, struct drm_framebuffer *fb, struct nouveau_fence *fence; int ret; - if (!nvdrm_channel(dev)) + if (!drm->channel) return -ENODEV; s = kzalloc(sizeof(*s), GFP_KERNEL); @@ -540,23 +644,23 @@ nouveau_crtc_page_flip(struct drm_crtc *crtc, struct drm_framebuffer *fb, if (fence) chan = fence->channel; if (!chan) - chan = nvdrm_channel(dev); - mutex_lock(nvchan_mutex(chan)); + chan = drm->channel; + mutex_lock(&chan->cli->mutex); /* Emit a page flip */ - if (dev_priv->card_type >= NV_50) { - if (dev_priv->card_type >= NV_D0) + if (nv_device(drm->device)->card_type >= NV_50) { + if (nv_device(drm->device)->card_type >= NV_D0) ret = nvd0_display_flip_next(crtc, fb, chan, 0); else ret = nv50_display_flip_next(crtc, fb, chan); if (ret) { - mutex_unlock(nvchan_mutex(chan)); + mutex_unlock(&chan->cli->mutex); goto fail_unreserve; } } ret = nouveau_page_flip_emit(chan, old_bo, new_bo, s, &fence); - mutex_unlock(nvchan_mutex(chan)); + mutex_unlock(&chan->cli->mutex); if (ret) goto fail_unreserve; @@ -579,14 +683,15 @@ nouveau_finish_page_flip(struct nouveau_channel *chan, struct nouveau_page_flip_state *ps) { struct nouveau_fence_chan *fctx = chan->fence; - struct drm_device *dev = nouveau_drv(chan->drm); + struct nouveau_drm *drm = chan->drm; + struct drm_device *dev = drm->dev; struct nouveau_page_flip_state *s; unsigned long flags; spin_lock_irqsave(&dev->event_lock, flags); if (list_empty(&fctx->flip)) { - NV_ERROR(dev, "unexpected pageflip\n"); + NV_ERROR(drm, "unexpected pageflip\n"); spin_unlock_irqrestore(&dev->event_lock, flags); return -EINVAL; } @@ -617,13 +722,12 @@ int nouveau_flip_complete(void *data) { struct nouveau_channel *chan = data; - struct drm_device *dev = nouveau_drv(chan->drm); - struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_drm *drm = chan->drm; struct nouveau_page_flip_state state; if (!nouveau_finish_page_flip(chan, &state)) { - if (dev_priv->card_type < NV_50) { - nv_set_crtc_base(dev, state.crtc, state.offset + + if (nv_device(drm->device)->card_type < NV_50) { + nv_set_crtc_base(drm->dev, state.crtc, state.offset + state.y * state.pitch + state.x * state.bpp / 8); } diff --git a/drivers/gpu/drm/nouveau/nouveau_display.h b/drivers/gpu/drm/nouveau/nouveau_display.h new file mode 100644 index 000000000000..722548bb3bd3 --- /dev/null +++ b/drivers/gpu/drm/nouveau/nouveau_display.h @@ -0,0 +1,94 @@ +#ifndef __NOUVEAU_DISPLAY_H__ +#define __NOUVEAU_DISPLAY_H__ + +#include + +#include "nouveau_drm.h" + +struct nouveau_framebuffer { + struct drm_framebuffer base; + struct nouveau_bo *nvbo; + struct nouveau_vma vma; + u32 r_dma; + u32 r_format; + u32 r_pitch; +}; + +static inline struct nouveau_framebuffer * +nouveau_framebuffer(struct drm_framebuffer *fb) +{ + return container_of(fb, struct nouveau_framebuffer, base); +} + +int nouveau_framebuffer_init(struct drm_device *, struct nouveau_framebuffer *, + struct drm_mode_fb_cmd2 *, struct nouveau_bo *); + +struct nouveau_page_flip_state { + struct list_head head; + struct drm_pending_vblank_event *event; + int crtc, bpp, pitch, x, y; + u64 offset; +}; + +struct nouveau_display { + void *priv; + void (*dtor)(struct drm_device *); + int (*init)(struct drm_device *); + void (*fini)(struct drm_device *); + + struct drm_property *dithering_mode; + struct drm_property *dithering_depth; + struct drm_property *underscan_property; + struct drm_property *underscan_hborder_property; + struct drm_property *underscan_vborder_property; + /* not really hue and saturation: */ + struct drm_property *vibrant_hue_property; + struct drm_property *color_vibrance_property; +}; + +static inline struct nouveau_display * +nouveau_display(struct drm_device *dev) +{ + return nouveau_drm(dev)->display; +} + +int nouveau_display_create(struct drm_device *dev); +void nouveau_display_destroy(struct drm_device *dev); +int nouveau_display_init(struct drm_device *dev); +void nouveau_display_fini(struct drm_device *dev); +int nouveau_display_suspend(struct drm_device *dev); +void nouveau_display_resume(struct drm_device *dev); + +int nouveau_vblank_enable(struct drm_device *dev, int crtc); +void nouveau_vblank_disable(struct drm_device *dev, int crtc); + +int nouveau_crtc_page_flip(struct drm_crtc *crtc, struct drm_framebuffer *fb, + struct drm_pending_vblank_event *event); +int nouveau_finish_page_flip(struct nouveau_channel *, + struct nouveau_page_flip_state *); + +int nouveau_display_dumb_create(struct drm_file *, struct drm_device *, + struct drm_mode_create_dumb *args); +int nouveau_display_dumb_map_offset(struct drm_file *, struct drm_device *, + u32 handle, u64 *offset); +int nouveau_display_dumb_destroy(struct drm_file *, struct drm_device *, + u32 handle); + +void nouveau_hdmi_mode_set(struct drm_encoder *, struct drm_display_mode *); + +#ifdef CONFIG_DRM_NOUVEAU_BACKLIGHT +extern int nouveau_backlight_init(struct drm_device *); +extern void nouveau_backlight_exit(struct drm_device *); +#else +static inline int +nouveau_backlight_init(struct drm_device *dev) +{ + return 0; +} + +static inline void +nouveau_backlight_exit(struct drm_device *dev) { +} +#endif + +#endif diff --git a/drivers/gpu/drm/nouveau/nouveau_dp.c b/drivers/gpu/drm/nouveau/nouveau_dp.c index 6fe11f8c5f6c..78e54cb8dfbe 100644 --- a/drivers/gpu/drm/nouveau/nouveau_dp.c +++ b/drivers/gpu/drm/nouveau/nouveau_dp.c @@ -25,31 +25,35 @@ #include "drmP.h" #include "drm_dp_helper.h" -#include "nouveau_drv.h" +#include "nouveau_drm.h" #include "nouveau_connector.h" #include "nouveau_encoder.h" #include "nouveau_crtc.h" +#include +#include + u8 * nouveau_dp_bios_data(struct drm_device *dev, struct dcb_output *dcb, u8 **entry) { + struct nouveau_drm *drm = nouveau_drm(dev); struct bit_entry d; u8 *table; int i; if (bit_table(dev, 'd', &d)) { - NV_ERROR(dev, "BIT 'd' table not found\n"); + NV_ERROR(drm, "BIT 'd' table not found\n"); return NULL; } if (d.version != 1) { - NV_ERROR(dev, "BIT 'd' table version %d unknown\n", d.version); + NV_ERROR(drm, "BIT 'd' table version %d unknown\n", d.version); return NULL; } table = ROMPTR(dev, d.data[0]); if (!table) { - NV_ERROR(dev, "displayport table pointer invalid\n"); + NV_ERROR(drm, "displayport table pointer invalid\n"); return NULL; } @@ -60,7 +64,7 @@ nouveau_dp_bios_data(struct drm_device *dev, struct dcb_output *dcb, u8 **entry) case 0x40: break; default: - NV_ERROR(dev, "displayport table 0x%02x unknown\n", table[0]); + NV_ERROR(drm, "displayport table 0x%02x unknown\n", table[0]); return NULL; } @@ -70,7 +74,7 @@ nouveau_dp_bios_data(struct drm_device *dev, struct dcb_output *dcb, u8 **entry) return table; } - NV_ERROR(dev, "displayport encoder table not found\n"); + NV_ERROR(drm, "displayport encoder table not found\n"); return NULL; } @@ -92,9 +96,10 @@ struct dp_state { static void dp_set_link_config(struct drm_device *dev, struct dp_state *dp) { + struct nouveau_drm *drm = nouveau_drm(dev); u8 sink[2]; - NV_DEBUG_KMS(dev, "%d lanes at %d KB/s\n", dp->link_nr, dp->link_bw); + NV_DEBUG(drm, "%d lanes at %d KB/s\n", dp->link_nr, dp->link_bw); /* set desired link configuration on the source */ dp->func->link_set(dev, dp->dcb, dp->crtc, dp->link_nr, dp->link_bw, @@ -106,27 +111,29 @@ dp_set_link_config(struct drm_device *dev, struct dp_state *dp) if (dp->dpcd[2] & DP_ENHANCED_FRAME_CAP) sink[1] |= DP_LANE_COUNT_ENHANCED_FRAME_EN; - auxch_wr(dev, dp->auxch, DP_LINK_BW_SET, sink, 2); + nv_wraux(dp->auxch, DP_LINK_BW_SET, sink, 2); } static void dp_set_training_pattern(struct drm_device *dev, struct dp_state *dp, u8 pattern) { + struct nouveau_drm *drm = nouveau_drm(dev); u8 sink_tp; - NV_DEBUG_KMS(dev, "training pattern %d\n", pattern); + NV_DEBUG(drm, "training pattern %d\n", pattern); dp->func->train_set(dev, dp->dcb, pattern); - auxch_rd(dev, dp->auxch, DP_TRAINING_PATTERN_SET, &sink_tp, 1); + nv_rdaux(dp->auxch, DP_TRAINING_PATTERN_SET, &sink_tp, 1); sink_tp &= ~DP_TRAINING_PATTERN_MASK; sink_tp |= pattern; - auxch_wr(dev, dp->auxch, DP_TRAINING_PATTERN_SET, &sink_tp, 1); + nv_wraux(dp->auxch, DP_TRAINING_PATTERN_SET, &sink_tp, 1); } static int dp_link_train_commit(struct drm_device *dev, struct dp_state *dp) { + struct nouveau_drm *drm = nouveau_drm(dev); int i; for (i = 0; i < dp->link_nr; i++) { @@ -140,25 +147,26 @@ dp_link_train_commit(struct drm_device *dev, struct dp_state *dp) if ((lpre << 3) == DP_TRAIN_PRE_EMPHASIS_9_5) dp->conf[i] |= DP_TRAIN_MAX_PRE_EMPHASIS_REACHED; - NV_DEBUG_KMS(dev, "config lane %d %02x\n", i, dp->conf[i]); + NV_DEBUG(drm, "config lane %d %02x\n", i, dp->conf[i]); dp->func->train_adj(dev, dp->dcb, i, lvsw, lpre); } - return auxch_wr(dev, dp->auxch, DP_TRAINING_LANE0_SET, dp->conf, 4); + return nv_wraux(dp->auxch, DP_TRAINING_LANE0_SET, dp->conf, 4); } static int dp_link_train_update(struct drm_device *dev, struct dp_state *dp, u32 delay) { + struct nouveau_drm *drm = nouveau_drm(dev); int ret; udelay(delay); - ret = auxch_rd(dev, dp->auxch, DP_LANE0_1_STATUS, dp->stat, 6); + ret = nv_rdaux(dp->auxch, DP_LANE0_1_STATUS, dp->stat, 6); if (ret) return ret; - NV_DEBUG_KMS(dev, "status %02x %02x %02x %02x %02x %02x\n", + NV_DEBUG(drm, "status %02x %02x %02x %02x %02x %02x\n", dp->stat[0], dp->stat[1], dp->stat[2], dp->stat[3], dp->stat[4], dp->stat[5]); return 0; @@ -287,11 +295,14 @@ nouveau_dp_link_train(struct drm_encoder *encoder, u32 datarate, struct nouveau_connector *nv_connector = nouveau_encoder_connector_get(nv_encoder); struct drm_device *dev = encoder->dev; + struct nouveau_drm *drm = nouveau_drm(dev); + struct nouveau_i2c *i2c = nouveau_i2c(drm->device); + struct nouveau_gpio *gpio = nouveau_gpio(drm->device); const u32 bw_list[] = { 270000, 162000, 0 }; const u32 *link_bw = bw_list; struct dp_state dp; - dp.auxch = nouveau_i2c_find(dev, nv_encoder->dcb->i2c_index); + dp.auxch = i2c->find(i2c, nv_encoder->dcb->i2c_index); if (!dp.auxch) return false; @@ -307,7 +318,7 @@ nouveau_dp_link_train(struct drm_encoder *encoder, u32 datarate, * we take during link training (DP_SET_POWER is one), we need * to ignore them for the moment to avoid races. */ - nouveau_gpio_irq(dev, 0, nv_connector->hpd, 0xff, false); + gpio->irq(gpio, 0, nv_connector->hpd, 0xff, false); /* enable down-spreading, if possible */ dp_set_downspread(dev, &dp, nv_encoder->dp.dpcd[3] & 1); @@ -350,7 +361,7 @@ nouveau_dp_link_train(struct drm_encoder *encoder, u32 datarate, dp_link_train_fini(dev, &dp); /* re-enable hotplug detect */ - nouveau_gpio_irq(dev, 0, nv_connector->hpd, 0xff, true); + gpio->irq(gpio, 0, nv_connector->hpd, 0xff, true); return true; } @@ -359,10 +370,12 @@ nouveau_dp_dpms(struct drm_encoder *encoder, int mode, u32 datarate, struct dp_train_func *func) { struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); + struct nouveau_drm *drm = nouveau_drm(encoder->dev); + struct nouveau_i2c *i2c = nouveau_i2c(drm->device); struct nouveau_i2c_port *auxch; u8 status; - auxch = nouveau_i2c_find(encoder->dev, nv_encoder->dcb->i2c_index); + auxch = i2c->find(i2c, nv_encoder->dcb->i2c_index); if (!auxch) return; @@ -371,7 +384,7 @@ nouveau_dp_dpms(struct drm_encoder *encoder, int mode, u32 datarate, else status = DP_SET_POWER_D3; - auxch_wr(encoder->dev, auxch, DP_SET_POWER, &status, 1); + nv_wraux(auxch, DP_SET_POWER, &status, 1); if (mode == DRM_MODE_DPMS_ON) nouveau_dp_link_train(encoder, datarate, func); @@ -381,17 +394,18 @@ static void nouveau_dp_probe_oui(struct drm_device *dev, struct nouveau_i2c_port *auxch, u8 *dpcd) { + struct nouveau_drm *drm = nouveau_drm(dev); u8 buf[3]; if (!(dpcd[DP_DOWN_STREAM_PORT_COUNT] & DP_OUI_SUPPORT)) return; - if (!auxch_rd(dev, auxch, DP_SINK_OUI, buf, 3)) - NV_DEBUG_KMS(dev, "Sink OUI: %02hx%02hx%02hx\n", + if (!nv_rdaux(auxch, DP_SINK_OUI, buf, 3)) + NV_DEBUG(drm, "Sink OUI: %02hx%02hx%02hx\n", buf[0], buf[1], buf[2]); - if (!auxch_rd(dev, auxch, DP_BRANCH_OUI, buf, 3)) - NV_DEBUG_KMS(dev, "Branch OUI: %02hx%02hx%02hx\n", + if (!nv_rdaux(auxch, DP_BRANCH_OUI, buf, 3)) + NV_DEBUG(drm, "Branch OUI: %02hx%02hx%02hx\n", buf[0], buf[1], buf[2]); } @@ -401,24 +415,26 @@ nouveau_dp_detect(struct drm_encoder *encoder) { struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); struct drm_device *dev = encoder->dev; + struct nouveau_drm *drm = nouveau_drm(dev); + struct nouveau_i2c *i2c = nouveau_i2c(drm->device); struct nouveau_i2c_port *auxch; u8 *dpcd = nv_encoder->dp.dpcd; int ret; - auxch = nouveau_i2c_find(dev, nv_encoder->dcb->i2c_index); + auxch = i2c->find(i2c, nv_encoder->dcb->i2c_index); if (!auxch) return false; - ret = auxch_rd(dev, auxch, DP_DPCD_REV, dpcd, 8); + ret = nv_rdaux(auxch, DP_DPCD_REV, dpcd, 8); if (ret) return false; nv_encoder->dp.link_bw = 27000 * dpcd[1]; nv_encoder->dp.link_nr = dpcd[2] & DP_MAX_LANE_COUNT_MASK; - NV_DEBUG_KMS(dev, "display: %dx%d dpcd 0x%02x\n", + NV_DEBUG(drm, "display: %dx%d dpcd 0x%02x\n", nv_encoder->dp.link_nr, nv_encoder->dp.link_bw, dpcd[0]); - NV_DEBUG_KMS(dev, "encoder: %dx%d\n", + NV_DEBUG(drm, "encoder: %dx%d\n", nv_encoder->dcb->dpconf.link_nr, nv_encoder->dcb->dpconf.link_bw); @@ -427,7 +443,7 @@ nouveau_dp_detect(struct drm_encoder *encoder) if (nv_encoder->dcb->dpconf.link_bw < nv_encoder->dp.link_bw) nv_encoder->dp.link_bw = nv_encoder->dcb->dpconf.link_bw; - NV_DEBUG_KMS(dev, "maximum: %dx%d\n", + NV_DEBUG(drm, "maximum: %dx%d\n", nv_encoder->dp.link_nr, nv_encoder->dp.link_bw); nouveau_dp_probe_oui(dev, auxch, dpcd); diff --git a/drivers/gpu/drm/nouveau/nouveau_drm.c b/drivers/gpu/drm/nouveau/nouveau_drm.c index 92ecf50a39d3..8b508cec65a2 100644 --- a/drivers/gpu/drm/nouveau/nouveau_drm.c +++ b/drivers/gpu/drm/nouveau/nouveau_drm.c @@ -22,6 +22,7 @@ * Authors: Ben Skeggs */ +#include #include #include @@ -34,24 +35,22 @@ #include #include "nouveau_drm.h" +#include "nouveau_irq.h" #include "nouveau_dma.h" +#include "nouveau_ttm.h" +#include "nouveau_gem.h" #include "nouveau_agp.h" +#include "nouveau_vga.h" +#include "nouveau_pm.h" +#include "nouveau_acpi.h" +#include "nouveau_bios.h" +#include "nouveau_ioctl.h" #include "nouveau_abi16.h" #include "nouveau_fbcon.h" #include "nouveau_fence.h" #include "nouveau_ttm.h" -int __devinit nouveau_pci_probe(struct pci_dev *, const struct pci_device_id *); -void nouveau_pci_remove(struct pci_dev *); -int nouveau_pci_suspend(struct pci_dev *, pm_message_t); -int nouveau_pci_resume(struct pci_dev *); -int __init nouveau_init(struct pci_driver *); -void __exit nouveau_exit(struct pci_driver *); - -int nouveau_load(struct drm_device *, unsigned long); -int nouveau_unload(struct drm_device *); - MODULE_PARM_DESC(config, "option string to pass to driver core"); static char *nouveau_config; module_param_named(config, nouveau_config, charp, 0400); @@ -64,6 +63,12 @@ MODULE_PARM_DESC(noaccel, "disable kernel/abi16 acceleration"); static int nouveau_noaccel = 0; module_param_named(noaccel, nouveau_noaccel, int, 0400); +MODULE_PARM_DESC(modeset, "enable driver"); +int nouveau_modeset = -1; +module_param_named(modeset, nouveau_modeset, int, 0400); + +static struct drm_driver driver; + static u64 nouveau_name(struct pci_dev *pdev) { @@ -206,7 +211,7 @@ nouveau_drm_probe(struct pci_dev *pdev, const struct pci_device_id *pent) pci_set_master(pdev); - ret = nouveau_pci_probe(pdev, pent); + ret = drm_get_pci_dev(pdev, pent, &driver); if (ret) { nouveau_object_ref(NULL, (struct nouveau_object **)&device); return ret; @@ -224,13 +229,14 @@ nouveau_drm_load(struct drm_device *dev, unsigned long flags) int ret; ret = nouveau_cli_create(pdev, 0, sizeof(*drm), (void**)&drm); - dev->dev_private = drm; if (ret) return ret; + dev->dev_private = drm; + drm->dev = dev; + INIT_LIST_HEAD(&drm->clients); spin_lock_init(&drm->tile.lock); - drm->dev = dev; /* make sure AGP controller is in a consistent state before we * (possibly) execute vbios init tables (see nouveau_agp.h) @@ -266,9 +272,15 @@ nouveau_drm_load(struct drm_device *dev, unsigned long flags) if (ret) goto fail_device; + /* workaround an odd issue on nvc1 by disabling the device's + * nosnoop capability. hopefully won't cause issues until a + * better fix is found - assuming there is one... + */ device = nv_device(drm->device); + if (nv_device(drm->device)->chipset == 0xc1) + nv_mask(device, 0x00088080, 0x00000800, 0x00000000); - /* initialise AGP */ + nouveau_vga_init(drm); nouveau_agp_init(drm); if (device->card_type >= NV_50) { @@ -280,18 +292,43 @@ nouveau_drm_load(struct drm_device *dev, unsigned long flags) ret = nouveau_ttm_init(drm); if (ret) - goto fail_device; + goto fail_ttm; + + ret = nouveau_bios_init(dev); + if (ret) + goto fail_bios; + + ret = nouveau_irq_init(dev); + if (ret) + goto fail_irq; - ret = nouveau_load(dev, flags); + ret = nouveau_display_create(dev); if (ret) - goto fail_load; + goto fail_dispctor; + + if (dev->mode_config.num_crtc) { + ret = nouveau_display_init(dev); + if (ret) + goto fail_dispinit; + } + + nouveau_pm_init(dev); nouveau_accel_init(drm); nouveau_fbcon_init(dev); return 0; -fail_load: +fail_dispinit: + nouveau_display_destroy(dev); +fail_dispctor: + nouveau_irq_fini(dev); +fail_irq: + nouveau_bios_takedown(dev); +fail_bios: nouveau_ttm_fini(drm); +fail_ttm: + nouveau_agp_fini(drm); + nouveau_vga_fini(drm); fail_device: nouveau_cli_destroy(&drm->client); return ret; @@ -300,21 +337,23 @@ fail_device: int nouveau_drm_unload(struct drm_device *dev) { - struct nouveau_drm *drm = nouveau_newpriv(dev); - struct pci_dev *pdev = dev->pdev; - int ret; + struct nouveau_drm *drm = nouveau_drm(dev); nouveau_fbcon_fini(dev); nouveau_accel_fini(drm); - ret = nouveau_unload(dev); - if (ret) - return ret; + nouveau_pm_fini(dev); + + nouveau_display_fini(dev); + nouveau_display_destroy(dev); + + nouveau_irq_fini(dev); + nouveau_bios_takedown(dev); nouveau_ttm_fini(drm); nouveau_agp_fini(drm); + nouveau_vga_fini(drm); - pci_set_drvdata(pdev, drm->client.base.device); nouveau_cli_destroy(&drm->client); return 0; } @@ -322,9 +361,13 @@ nouveau_drm_unload(struct drm_device *dev) static void nouveau_drm_remove(struct pci_dev *pdev) { + struct drm_device *dev = pci_get_drvdata(pdev); + struct nouveau_drm *drm = nouveau_drm(dev); struct nouveau_object *device; - nouveau_pci_remove(pdev); - device = pci_get_drvdata(pdev); + + device = drm->client.base.device; + drm_put_dev(dev); + nouveau_object_ref(NULL, &device); nouveau_object_debug(); } @@ -333,7 +376,7 @@ int nouveau_drm_suspend(struct pci_dev *pdev, pm_message_t pm_state) { struct drm_device *dev = pci_get_drvdata(pdev); - struct nouveau_drm *drm = nouveau_newpriv(dev); + struct nouveau_drm *drm = nouveau_drm(dev); struct nouveau_cli *cli; int ret; @@ -344,8 +387,8 @@ nouveau_drm_suspend(struct pci_dev *pdev, pm_message_t pm_state) NV_INFO(drm, "suspending fbcon...\n"); nouveau_fbcon_set_suspend(dev, 1); - NV_INFO(drm, "suspending drm...\n"); - ret = nouveau_pci_suspend(pdev, pm_state); + NV_INFO(drm, "suspending display...\n"); + ret = nouveau_display_suspend(dev); if (ret) return ret; @@ -383,7 +426,8 @@ fail_client: nouveau_client_init(&cli->base); } - nouveau_pci_resume(pdev); + NV_INFO(drm, "resuming display...\n"); + nouveau_display_resume(dev); return ret; } @@ -391,7 +435,7 @@ int nouveau_drm_resume(struct pci_dev *pdev) { struct drm_device *dev = pci_get_drvdata(pdev); - struct nouveau_drm *drm = nouveau_newpriv(dev); + struct nouveau_drm *drm = nouveau_drm(dev); struct nouveau_cli *cli; int ret; @@ -419,7 +463,13 @@ nouveau_drm_resume(struct pci_dev *pdev) if (drm->fence && nouveau_fence(drm)->resume) nouveau_fence(drm)->resume(drm); - return nouveau_pci_resume(pdev); + nouveau_run_vbios_init(dev); + nouveau_irq_postinstall(dev); + nouveau_pm_resume(dev); + + NV_INFO(drm, "resuming display...\n"); + nouveau_display_resume(dev); + return 0; } int @@ -472,6 +522,90 @@ nouveau_drm_postclose(struct drm_device *dev, struct drm_file *fpriv) nouveau_cli_destroy(cli); } +static struct drm_ioctl_desc +nouveau_ioctls[] = { + DRM_IOCTL_DEF_DRV(NOUVEAU_GETPARAM, nouveau_abi16_ioctl_getparam, DRM_UNLOCKED|DRM_AUTH), + DRM_IOCTL_DEF_DRV(NOUVEAU_SETPARAM, nouveau_abi16_ioctl_setparam, DRM_UNLOCKED|DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), + DRM_IOCTL_DEF_DRV(NOUVEAU_CHANNEL_ALLOC, nouveau_abi16_ioctl_channel_alloc, DRM_UNLOCKED|DRM_AUTH), + DRM_IOCTL_DEF_DRV(NOUVEAU_CHANNEL_FREE, nouveau_abi16_ioctl_channel_free, DRM_UNLOCKED|DRM_AUTH), + DRM_IOCTL_DEF_DRV(NOUVEAU_GROBJ_ALLOC, nouveau_abi16_ioctl_grobj_alloc, DRM_UNLOCKED|DRM_AUTH), + DRM_IOCTL_DEF_DRV(NOUVEAU_NOTIFIEROBJ_ALLOC, nouveau_abi16_ioctl_notifierobj_alloc, DRM_UNLOCKED|DRM_AUTH), + DRM_IOCTL_DEF_DRV(NOUVEAU_GPUOBJ_FREE, nouveau_abi16_ioctl_gpuobj_free, DRM_UNLOCKED|DRM_AUTH), + DRM_IOCTL_DEF_DRV(NOUVEAU_GEM_NEW, nouveau_gem_ioctl_new, DRM_UNLOCKED|DRM_AUTH), + DRM_IOCTL_DEF_DRV(NOUVEAU_GEM_PUSHBUF, nouveau_gem_ioctl_pushbuf, DRM_UNLOCKED|DRM_AUTH), + DRM_IOCTL_DEF_DRV(NOUVEAU_GEM_CPU_PREP, nouveau_gem_ioctl_cpu_prep, DRM_UNLOCKED|DRM_AUTH), + DRM_IOCTL_DEF_DRV(NOUVEAU_GEM_CPU_FINI, nouveau_gem_ioctl_cpu_fini, DRM_UNLOCKED|DRM_AUTH), + DRM_IOCTL_DEF_DRV(NOUVEAU_GEM_INFO, nouveau_gem_ioctl_info, DRM_UNLOCKED|DRM_AUTH), +}; + +static const struct file_operations +nouveau_driver_fops = { + .owner = THIS_MODULE, + .open = drm_open, + .release = drm_release, + .unlocked_ioctl = drm_ioctl, + .mmap = nouveau_ttm_mmap, + .poll = drm_poll, + .fasync = drm_fasync, + .read = drm_read, +#if defined(CONFIG_COMPAT) + .compat_ioctl = nouveau_compat_ioctl, +#endif + .llseek = noop_llseek, +}; + +static struct drm_driver +driver = { + .driver_features = + DRIVER_USE_AGP | DRIVER_PCI_DMA | DRIVER_SG | + DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED | DRIVER_GEM | + DRIVER_MODESET | DRIVER_PRIME, + + .load = nouveau_drm_load, + .unload = nouveau_drm_unload, + .open = nouveau_drm_open, + .preclose = nouveau_drm_preclose, + .postclose = nouveau_drm_postclose, + .lastclose = nouveau_vga_lastclose, + + .irq_preinstall = nouveau_irq_preinstall, + .irq_postinstall = nouveau_irq_postinstall, + .irq_uninstall = nouveau_irq_uninstall, + .irq_handler = nouveau_irq_handler, + + .get_vblank_counter = drm_vblank_count, + .enable_vblank = nouveau_vblank_enable, + .disable_vblank = nouveau_vblank_disable, + + .ioctls = nouveau_ioctls, + .fops = &nouveau_driver_fops, + + .prime_handle_to_fd = drm_gem_prime_handle_to_fd, + .prime_fd_to_handle = drm_gem_prime_fd_to_handle, + .gem_prime_export = nouveau_gem_prime_export, + .gem_prime_import = nouveau_gem_prime_import, + + .gem_init_object = nouveau_gem_object_new, + .gem_free_object = nouveau_gem_object_del, + .gem_open_object = nouveau_gem_object_open, + .gem_close_object = nouveau_gem_object_close, + + .dumb_create = nouveau_display_dumb_create, + .dumb_map_offset = nouveau_display_dumb_map_offset, + .dumb_destroy = nouveau_display_dumb_destroy, + + .name = DRIVER_NAME, + .desc = DRIVER_DESC, +#ifdef GIT_REVISION + .date = GIT_REVISION, +#else + .date = DRIVER_DATE, +#endif + .major = DRIVER_MAJOR, + .minor = DRIVER_MINOR, + .patchlevel = DRIVER_PATCHLEVEL, +}; + static struct pci_device_id nouveau_drm_pci_table[] = { { @@ -500,19 +634,38 @@ nouveau_drm_pci_driver = { static int __init nouveau_drm_init(void) { - return nouveau_init(&nouveau_drm_pci_driver); + driver.num_ioctls = ARRAY_SIZE(nouveau_ioctls); + + if (nouveau_modeset == -1) { +#ifdef CONFIG_VGA_CONSOLE + if (vgacon_text_force()) + nouveau_modeset = 0; + else +#endif + nouveau_modeset = 1; + } + + if (!nouveau_modeset) + return 0; + + nouveau_register_dsm_handler(); + return drm_pci_init(&driver, &nouveau_drm_pci_driver); } static void __exit nouveau_drm_exit(void) { - nouveau_exit(&nouveau_drm_pci_driver); + if (!nouveau_modeset) + return; + + drm_pci_exit(&driver, &nouveau_drm_pci_driver); + nouveau_unregister_dsm_handler(); } module_init(nouveau_drm_init); module_exit(nouveau_drm_exit); MODULE_DEVICE_TABLE(pci, nouveau_drm_pci_table); -MODULE_AUTHOR("Nouveau Project"); -MODULE_DESCRIPTION("nVidia Riva/TNT/GeForce/Quadro/Tesla"); +MODULE_AUTHOR(DRIVER_AUTHOR); +MODULE_DESCRIPTION(DRIVER_DESC); MODULE_LICENSE("GPL and additional rights"); diff --git a/drivers/gpu/drm/nouveau/nouveau_drm.h b/drivers/gpu/drm/nouveau/nouveau_drm.h index d50352aa1a16..6abd1a15e742 100644 --- a/drivers/gpu/drm/nouveau/nouveau_drm.h +++ b/drivers/gpu/drm/nouveau/nouveau_drm.h @@ -1,6 +1,17 @@ #ifndef __NOUVEAU_DRMCLI_H__ #define __NOUVEAU_DRMCLI_H__ +#define DRIVER_AUTHOR "Nouveau Project" +#define DRIVER_EMAIL "nouveau@lists.freedesktop.org" + +#define DRIVER_NAME "nouveau" +#define DRIVER_DESC "nVidia Riva/TNT/GeForce/Quadro/Tesla" +#define DRIVER_DATE "20120801" + +#define DRIVER_MAJOR 1 +#define DRIVER_MINOR 1 +#define DRIVER_PATCHLEVEL 0 + #include #include @@ -19,8 +30,8 @@ struct nouveau_channel; #define DRM_FILE_PAGE_OFFSET (0x100000000ULL >> PAGE_SHIFT) -#include "nouveau_revcompat.h" #include "nouveau_fence.h" +#include "nouveau_bios.h" struct nouveau_drm_tile { struct nouveau_fence *fence; @@ -96,13 +107,25 @@ struct nouveau_drm { spinlock_t lock; } tile; + /* modesetting */ + struct nvbios vbios; + struct nouveau_display *display; struct backlight_device *backlight; + + /* power management */ + struct nouveau_pm *pm; }; static inline struct nouveau_drm * nouveau_drm(struct drm_device *dev) { - return nouveau_newpriv(dev); + return dev->dev_private; +} + +static inline struct nouveau_device * +nouveau_dev(struct drm_device *dev) +{ + return nv_device(nouveau_drm(dev)->device); } int nouveau_drm_suspend(struct pci_dev *, pm_message_t); diff --git a/drivers/gpu/drm/nouveau/nouveau_drv.c b/drivers/gpu/drm/nouveau/nouveau_drv.c deleted file mode 100644 index 204772160a4e..000000000000 --- a/drivers/gpu/drm/nouveau/nouveau_drv.c +++ /dev/null @@ -1,353 +0,0 @@ -/* - * Copyright 2005 Stephane Marchesin. - * All Rights Reserved. - * - * 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 (including the next - * paragraph) 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 - * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS 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. - */ - -#include -#include - -#include "drmP.h" -#include "drm.h" -#include "drm_crtc_helper.h" -#include "nouveau_drv.h" -#include "nouveau_abi16.h" -#include "nouveau_hw.h" -#include "nouveau_fb.h" -#include "nouveau_fbcon.h" -#include "nouveau_fence.h" -#include "nouveau_pm.h" -#include "nv50_display.h" -#include "nouveau_acpi.h" -#include "nouveau_ioctl.h" - -#include "drm_pciids.h" - -MODULE_PARM_DESC(modeset, "Enable kernel modesetting"); -int nouveau_modeset = -1; -module_param_named(modeset, nouveau_modeset, int, 0400); - -MODULE_PARM_DESC(vram_notify, "Force DMA notifiers to be in VRAM"); -int nouveau_vram_notify = 0; -module_param_named(vram_notify, nouveau_vram_notify, int, 0400); - -MODULE_PARM_DESC(vram_type, "Override detected VRAM type"); -char *nouveau_vram_type; -module_param_named(vram_type, nouveau_vram_type, charp, 0400); - -MODULE_PARM_DESC(duallink, "Allow dual-link TMDS (>=GeForce 8)"); -int nouveau_duallink = 1; -module_param_named(duallink, nouveau_duallink, int, 0400); - -MODULE_PARM_DESC(uscript_lvds, "LVDS output script table ID (>=GeForce 8)"); -int nouveau_uscript_lvds = -1; -module_param_named(uscript_lvds, nouveau_uscript_lvds, int, 0400); - -MODULE_PARM_DESC(uscript_tmds, "TMDS output script table ID (>=GeForce 8)"); -int nouveau_uscript_tmds = -1; -module_param_named(uscript_tmds, nouveau_uscript_tmds, int, 0400); - -MODULE_PARM_DESC(ignorelid, "Ignore ACPI lid status"); -int nouveau_ignorelid = 0; -module_param_named(ignorelid, nouveau_ignorelid, int, 0400); - -MODULE_PARM_DESC(force_post, "Force POST"); -int nouveau_force_post = 0; -module_param_named(force_post, nouveau_force_post, int, 0400); - -MODULE_PARM_DESC(override_conntype, "Ignore DCB connector type"); -int nouveau_override_conntype = 0; -module_param_named(override_conntype, nouveau_override_conntype, int, 0400); - -MODULE_PARM_DESC(tv_disable, "Disable TV-out detection"); -int nouveau_tv_disable = 0; -module_param_named(tv_disable, nouveau_tv_disable, int, 0400); - -MODULE_PARM_DESC(tv_norm, "Default TV norm.\n" - "\t\tSupported: PAL, PAL-M, PAL-N, PAL-Nc, NTSC-M, NTSC-J,\n" - "\t\t\thd480i, hd480p, hd576i, hd576p, hd720p, hd1080i.\n" - "\t\tDefault: PAL\n" - "\t\t*NOTE* Ignored for cards with external TV encoders."); -char *nouveau_tv_norm; -module_param_named(tv_norm, nouveau_tv_norm, charp, 0400); - -MODULE_PARM_DESC(perflvl, "Performance level (default: boot)"); -char *nouveau_perflvl; -module_param_named(perflvl, nouveau_perflvl, charp, 0400); - -MODULE_PARM_DESC(perflvl_wr, "Allow perflvl changes (warning: dangerous!)"); -int nouveau_perflvl_wr; -module_param_named(perflvl_wr, nouveau_perflvl_wr, int, 0400); - -MODULE_PARM_DESC(msi, "Enable MSI (default: off)"); -int nouveau_msi; -module_param_named(msi, nouveau_msi, int, 0400); - -MODULE_PARM_DESC(ctxfw, "Use external HUB/GPC ucode (fermi)"); -int nouveau_ctxfw; -module_param_named(ctxfw, nouveau_ctxfw, int, 0400); - -MODULE_PARM_DESC(mxmdcb, "Santise DCB table according to MXM-SIS"); -int nouveau_mxmdcb = 1; -module_param_named(mxmdcb, nouveau_mxmdcb, int, 0400); - -int nouveau_fbpercrtc; -#if 0 -module_param_named(fbpercrtc, nouveau_fbpercrtc, int, 0400); -#endif - -static struct drm_driver driver; - -int __devinit -nouveau_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) -{ - return drm_get_pci_dev(pdev, ent, &driver); -} - -void -nouveau_pci_remove(struct pci_dev *pdev) -{ - struct drm_device *dev = pci_get_drvdata(pdev); - - drm_put_dev(dev); -} - -int -nouveau_pci_suspend(struct pci_dev *pdev, pm_message_t pm_state) -{ - struct drm_device *dev = pci_get_drvdata(pdev); - struct drm_crtc *crtc; - - NV_INFO(dev, "Disabling display...\n"); - nouveau_display_fini(dev); - - NV_INFO(dev, "Unpinning framebuffer(s)...\n"); - list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { - struct nouveau_framebuffer *nouveau_fb; - - nouveau_fb = nouveau_framebuffer(crtc->fb); - if (!nouveau_fb || !nouveau_fb->nvbo) - continue; - - nouveau_bo_unpin(nouveau_fb->nvbo); - } - - list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { - struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); - - nouveau_bo_unmap(nv_crtc->cursor.nvbo); - nouveau_bo_unpin(nv_crtc->cursor.nvbo); - } - - return 0; -} - -int -nouveau_pci_resume(struct pci_dev *pdev) -{ - struct drm_device *dev = pci_get_drvdata(pdev); - struct drm_crtc *crtc; - int ret; - - ret = nouveau_run_vbios_init(dev); - if (ret) - return ret; - - nouveau_irq_postinstall(dev); - -#if 0 - /* Re-write SKIPS, they'll have been lost over the suspend */ - if (nouveau_vram_pushbuf) { - struct nouveau_channel *chan; - int j; - - for (i = 0; i < (pfifo ? pfifo->channels : 0); i++) { - chan = dev_priv->channels.ptr[i]; - if (!chan || !chan->pushbuf_bo) - continue; - - for (j = 0; j < NOUVEAU_DMA_SKIPS; j++) - nouveau_bo_wr32(chan->pushbuf_bo, i, 0); - } - } -#endif - - nouveau_pm_resume(dev); - - NV_INFO(dev, "Restoring mode...\n"); - list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { - struct nouveau_framebuffer *nouveau_fb; - - nouveau_fb = nouveau_framebuffer(crtc->fb); - if (!nouveau_fb || !nouveau_fb->nvbo) - continue; - - nouveau_bo_pin(nouveau_fb->nvbo, TTM_PL_FLAG_VRAM); - } - - list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { - struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); - - ret = nouveau_bo_pin(nv_crtc->cursor.nvbo, TTM_PL_FLAG_VRAM); - if (!ret) - ret = nouveau_bo_map(nv_crtc->cursor.nvbo); - if (ret) - NV_ERROR(dev, "Could not pin/map cursor.\n"); - } - - nouveau_fbcon_set_suspend(dev, 0); - nouveau_fbcon_zfill_all(dev); - - nouveau_display_init(dev); - - /* Force CLUT to get re-loaded during modeset */ - list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { - struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); - - nv_crtc->lut.depth = 0; - } - - drm_helper_resume_force_mode(dev); - - list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { - struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); - u32 offset = nv_crtc->cursor.nvbo->bo.offset; - - nv_crtc->cursor.set_offset(nv_crtc, offset); - nv_crtc->cursor.set_pos(nv_crtc, nv_crtc->cursor_saved_x, - nv_crtc->cursor_saved_y); - } - - return 0; -} - -static struct drm_ioctl_desc nouveau_ioctls[] = { - DRM_IOCTL_DEF_DRV(NOUVEAU_GETPARAM, nouveau_abi16_ioctl_getparam, DRM_UNLOCKED|DRM_AUTH), - DRM_IOCTL_DEF_DRV(NOUVEAU_SETPARAM, nouveau_abi16_ioctl_setparam, DRM_UNLOCKED|DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), - DRM_IOCTL_DEF_DRV(NOUVEAU_CHANNEL_ALLOC, nouveau_abi16_ioctl_channel_alloc, DRM_UNLOCKED|DRM_AUTH), - DRM_IOCTL_DEF_DRV(NOUVEAU_CHANNEL_FREE, nouveau_abi16_ioctl_channel_free, DRM_UNLOCKED|DRM_AUTH), - DRM_IOCTL_DEF_DRV(NOUVEAU_GROBJ_ALLOC, nouveau_abi16_ioctl_grobj_alloc, DRM_UNLOCKED|DRM_AUTH), - DRM_IOCTL_DEF_DRV(NOUVEAU_NOTIFIEROBJ_ALLOC, nouveau_abi16_ioctl_notifierobj_alloc, DRM_UNLOCKED|DRM_AUTH), - DRM_IOCTL_DEF_DRV(NOUVEAU_GPUOBJ_FREE, nouveau_abi16_ioctl_gpuobj_free, DRM_UNLOCKED|DRM_AUTH), - DRM_IOCTL_DEF_DRV(NOUVEAU_GEM_NEW, nouveau_gem_ioctl_new, DRM_UNLOCKED|DRM_AUTH), - DRM_IOCTL_DEF_DRV(NOUVEAU_GEM_PUSHBUF, nouveau_gem_ioctl_pushbuf, DRM_UNLOCKED|DRM_AUTH), - DRM_IOCTL_DEF_DRV(NOUVEAU_GEM_CPU_PREP, nouveau_gem_ioctl_cpu_prep, DRM_UNLOCKED|DRM_AUTH), - DRM_IOCTL_DEF_DRV(NOUVEAU_GEM_CPU_FINI, nouveau_gem_ioctl_cpu_fini, DRM_UNLOCKED|DRM_AUTH), - DRM_IOCTL_DEF_DRV(NOUVEAU_GEM_INFO, nouveau_gem_ioctl_info, DRM_UNLOCKED|DRM_AUTH), -}; - -static const struct file_operations nouveau_driver_fops = { - .owner = THIS_MODULE, - .open = drm_open, - .release = drm_release, - .unlocked_ioctl = drm_ioctl, - .mmap = nouveau_ttm_mmap, - .poll = drm_poll, - .fasync = drm_fasync, - .read = drm_read, -#if defined(CONFIG_COMPAT) - .compat_ioctl = nouveau_compat_ioctl, -#endif - .llseek = noop_llseek, -}; - -int nouveau_drm_load(struct drm_device *, unsigned long); -int nouveau_drm_unload(struct drm_device *); -int nouveau_drm_open(struct drm_device *, struct drm_file *); -void nouveau_drm_preclose(struct drm_device *dev, struct drm_file *); -void nouveau_drm_postclose(struct drm_device *, struct drm_file *); - -static struct drm_driver driver = { - .driver_features = - DRIVER_USE_AGP | DRIVER_PCI_DMA | DRIVER_SG | - DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED | DRIVER_GEM | - DRIVER_MODESET | DRIVER_PRIME, - .load = nouveau_drm_load, - .firstopen = nouveau_firstopen, - .lastclose = nouveau_lastclose, - .unload = nouveau_drm_unload, - .open = nouveau_drm_open, - .preclose = nouveau_drm_preclose, - .postclose = nouveau_drm_postclose, - .irq_preinstall = nouveau_irq_preinstall, - .irq_postinstall = nouveau_irq_postinstall, - .irq_uninstall = nouveau_irq_uninstall, - .irq_handler = nouveau_irq_handler, - .get_vblank_counter = drm_vblank_count, - .enable_vblank = nouveau_vblank_enable, - .disable_vblank = nouveau_vblank_disable, - .ioctls = nouveau_ioctls, - .fops = &nouveau_driver_fops, - - .prime_handle_to_fd = drm_gem_prime_handle_to_fd, - .prime_fd_to_handle = drm_gem_prime_fd_to_handle, - .gem_prime_export = nouveau_gem_prime_export, - .gem_prime_import = nouveau_gem_prime_import, - - .gem_init_object = nouveau_gem_object_new, - .gem_free_object = nouveau_gem_object_del, - .gem_open_object = nouveau_gem_object_open, - .gem_close_object = nouveau_gem_object_close, - - .dumb_create = nouveau_display_dumb_create, - .dumb_map_offset = nouveau_display_dumb_map_offset, - .dumb_destroy = nouveau_display_dumb_destroy, - - .name = DRIVER_NAME, - .desc = DRIVER_DESC, -#ifdef GIT_REVISION - .date = GIT_REVISION, -#else - .date = DRIVER_DATE, -#endif - .major = DRIVER_MAJOR, - .minor = DRIVER_MINOR, - .patchlevel = DRIVER_PATCHLEVEL, -}; - -int __init nouveau_init(struct pci_driver *pdrv) -{ - driver.num_ioctls = ARRAY_SIZE(nouveau_ioctls); - - if (nouveau_modeset == -1) { -#ifdef CONFIG_VGA_CONSOLE - if (vgacon_text_force()) - nouveau_modeset = 0; - else -#endif - nouveau_modeset = 1; - } - - if (!nouveau_modeset) - return 0; - - nouveau_register_dsm_handler(); - return drm_pci_init(&driver, pdrv); -} - -void __exit nouveau_exit(struct pci_driver *pdrv) -{ - if (!nouveau_modeset) - return; - - drm_pci_exit(&driver, pdrv); - nouveau_unregister_dsm_handler(); -} diff --git a/drivers/gpu/drm/nouveau/nouveau_drv.h b/drivers/gpu/drm/nouveau/nouveau_drv.h deleted file mode 100644 index 1228ac45e24c..000000000000 --- a/drivers/gpu/drm/nouveau/nouveau_drv.h +++ /dev/null @@ -1,551 +0,0 @@ -/* - * Copyright 2005 Stephane Marchesin. - * All Rights Reserved. - * - * 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 (including the next - * paragraph) 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 - * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS 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. - */ - -#ifndef __NOUVEAU_DRV_H__ -#define __NOUVEAU_DRV_H__ - -#define DRIVER_AUTHOR "Stephane Marchesin" -#define DRIVER_EMAIL "nouveau@lists.freedesktop.org" - -#define DRIVER_NAME "nouveau" -#define DRIVER_DESC "nVidia Riva/TNT/GeForce" -#define DRIVER_DATE "20120316" - -#define DRIVER_MAJOR 1 -#define DRIVER_MINOR 0 -#define DRIVER_PATCHLEVEL 0 - -#define NOUVEAU_FAMILY 0x0000FFFF -#define NOUVEAU_FLAGS 0xFFFF0000 - -#include "ttm/ttm_bo_api.h" -#include "ttm/ttm_bo_driver.h" -#include "ttm/ttm_placement.h" -#include "ttm/ttm_memory.h" -#include "ttm/ttm_module.h" - -#define XXX_THIS_IS_A_HACK -#include -#include -#include - -enum blah { - NV_MEM_TYPE_UNKNOWN = 0, - NV_MEM_TYPE_STOLEN, - NV_MEM_TYPE_SGRAM, - NV_MEM_TYPE_SDRAM, - NV_MEM_TYPE_DDR1, - NV_MEM_TYPE_DDR2, - NV_MEM_TYPE_DDR3, - NV_MEM_TYPE_GDDR2, - NV_MEM_TYPE_GDDR3, - NV_MEM_TYPE_GDDR4, - NV_MEM_TYPE_GDDR5 -}; - -#include -#include "nouveau_reg.h" -#include - -#include -#include "nouveau_compat.h" - -#define nouveau_gpuobj_new(d,c,s,a,f,o) \ - _nouveau_gpuobj_new((d), NULL, (s), (a), (f), (o)) - -#define nouveau_vm_new(d,o,l,m,v) \ - _nouveau_vm_new((d), (o), (l), (m), (v)) - -#define nv50_vm_flush_engine(d,e) \ - _nv50_vm_flush_engine((d), (e)) - -#include "nouveau_bo.h" -#include "nouveau_gem.h" - -struct nouveau_page_flip_state { - struct list_head head; - struct drm_pending_vblank_event *event; - int crtc, bpp, pitch, x, y; - uint64_t offset; -}; - -struct nouveau_display_engine { - void *priv; - int (*early_init)(struct drm_device *); - void (*late_takedown)(struct drm_device *); - int (*create)(struct drm_device *); - void (*destroy)(struct drm_device *); - int (*init)(struct drm_device *); - void (*fini)(struct drm_device *); - - struct drm_property *dithering_mode; - struct drm_property *dithering_depth; - struct drm_property *underscan_property; - struct drm_property *underscan_hborder_property; - struct drm_property *underscan_vborder_property; - /* not really hue and saturation: */ - struct drm_property *vibrant_hue_property; - struct drm_property *color_vibrance_property; -}; - -struct nouveau_pm_voltage_level { - u32 voltage; /* microvolts */ - u8 vid; -}; - -struct nouveau_pm_voltage { - bool supported; - u8 version; - u8 vid_mask; - - struct nouveau_pm_voltage_level *level; - int nr_level; -}; - -/* Exclusive upper limits */ -#define NV_MEM_CL_DDR2_MAX 8 -#define NV_MEM_WR_DDR2_MAX 9 -#define NV_MEM_CL_DDR3_MAX 17 -#define NV_MEM_WR_DDR3_MAX 17 -#define NV_MEM_CL_GDDR3_MAX 16 -#define NV_MEM_WR_GDDR3_MAX 18 -#define NV_MEM_CL_GDDR5_MAX 21 -#define NV_MEM_WR_GDDR5_MAX 20 - -struct nouveau_pm_memtiming { - int id; - - u32 reg[9]; - u32 mr[4]; - - u8 tCWL; - - u8 odt; - u8 drive_strength; -}; - -struct nouveau_pm_tbl_header { - u8 version; - u8 header_len; - u8 entry_cnt; - u8 entry_len; -}; - -struct nouveau_pm_tbl_entry { - u8 tWR; - u8 tWTR; - u8 tCL; - u8 tRC; - u8 empty_4; - u8 tRFC; /* Byte 5 */ - u8 empty_6; - u8 tRAS; /* Byte 7 */ - u8 empty_8; - u8 tRP; /* Byte 9 */ - u8 tRCDRD; - u8 tRCDWR; - u8 tRRD; - u8 tUNK_13; - u8 RAM_FT1; /* 14, a bitmask of random RAM features */ - u8 empty_15; - u8 tUNK_16; - u8 empty_17; - u8 tUNK_18; - u8 tCWL; - u8 tUNK_20, tUNK_21; -}; - -struct nouveau_pm_profile; -struct nouveau_pm_profile_func { - void (*destroy)(struct nouveau_pm_profile *); - void (*init)(struct nouveau_pm_profile *); - void (*fini)(struct nouveau_pm_profile *); - struct nouveau_pm_level *(*select)(struct nouveau_pm_profile *); -}; - -struct nouveau_pm_profile { - const struct nouveau_pm_profile_func *func; - struct list_head head; - char name[8]; -}; - -#define NOUVEAU_PM_MAX_LEVEL 8 -struct nouveau_pm_level { - struct nouveau_pm_profile profile; - struct device_attribute dev_attr; - char name[32]; - int id; - - struct nouveau_pm_memtiming timing; - u32 memory; - u16 memscript; - - u32 core; - u32 shader; - u32 rop; - u32 copy; - u32 daemon; - u32 vdec; - u32 dom6; - u32 unka0; /* nva3:nvc0 */ - u32 hub01; /* nvc0- */ - u32 hub06; /* nvc0- */ - u32 hub07; /* nvc0- */ - - u32 volt_min; /* microvolts */ - u32 volt_max; - u8 fanspeed; -}; - -struct nouveau_pm_temp_sensor_constants { - u16 offset_constant; - s16 offset_mult; - s16 offset_div; - s16 slope_mult; - s16 slope_div; -}; - -struct nouveau_pm_threshold_temp { - s16 critical; - s16 down_clock; - s16 fan_boost; -}; - -struct nouveau_pm_fan { - u32 percent; - u32 min_duty; - u32 max_duty; - u32 pwm_freq; - u32 pwm_divisor; -}; - -struct nouveau_pm_engine { - struct nouveau_pm_voltage voltage; - struct nouveau_pm_level perflvl[NOUVEAU_PM_MAX_LEVEL]; - int nr_perflvl; - struct nouveau_pm_temp_sensor_constants sensor_constants; - struct nouveau_pm_threshold_temp threshold_temp; - struct nouveau_pm_fan fan; - - struct nouveau_pm_profile *profile_ac; - struct nouveau_pm_profile *profile_dc; - struct nouveau_pm_profile *profile; - struct list_head profiles; - - struct nouveau_pm_level boot; - struct nouveau_pm_level *cur; - - struct device *hwmon; - struct notifier_block acpi_nb; - - int (*clocks_get)(struct drm_device *, struct nouveau_pm_level *); - void *(*clocks_pre)(struct drm_device *, struct nouveau_pm_level *); - int (*clocks_set)(struct drm_device *, void *); - - int (*voltage_get)(struct drm_device *); - int (*voltage_set)(struct drm_device *, int voltage); - int (*pwm_get)(struct drm_device *, int line, u32*, u32*); - int (*pwm_set)(struct drm_device *, int line, u32, u32); - int (*temp_get)(struct drm_device *); -}; - -struct nouveau_engine { - struct nouveau_display_engine display; - struct nouveau_pm_engine pm; -}; - -enum nouveau_card_type { - NV_04 = 0x04, - NV_10 = 0x10, - NV_20 = 0x20, - NV_30 = 0x30, - NV_40 = 0x40, - NV_50 = 0x50, - NV_C0 = 0xc0, - NV_D0 = 0xd0, - NV_E0 = 0xe0, -}; - -struct drm_nouveau_private { - struct drm_device *dev; - - void *newpriv; - - /* the card type, takes NV_* as values */ - enum nouveau_card_type card_type; - /* exact chipset, derived from NV_PMC_BOOT_0 */ - int chipset; - u32 crystal; - - /* interrupt handling */ - void (*irq_handler[32])(struct drm_device *); - bool msi_enabled; - - struct nouveau_engine engine; - - /* For PFIFO and PGRAPH. */ - spinlock_t context_switch_lock; - - struct nvbios vbios; -}; - -static inline struct drm_nouveau_private * -nouveau_private(struct drm_device *dev) -{ - return dev->dev_private; -} - -/* nouveau_drv.c */ -extern int nouveau_modeset; -extern int nouveau_duallink; -extern int nouveau_uscript_lvds; -extern int nouveau_uscript_tmds; -extern int nouveau_vram_pushbuf; -extern int nouveau_vram_notify; -extern char *nouveau_vram_type; -extern int nouveau_fbpercrtc; -extern int nouveau_tv_disable; -extern char *nouveau_tv_norm; -extern int nouveau_ignorelid; -extern int nouveau_force_post; -extern int nouveau_override_conntype; -extern char *nouveau_perflvl; -extern int nouveau_perflvl_wr; -extern int nouveau_msi; -extern int nouveau_ctxfw; -extern int nouveau_mxmdcb; - -extern int nouveau_pci_suspend(struct pci_dev *pdev, pm_message_t pm_state); -extern int nouveau_pci_resume(struct pci_dev *pdev); - -/* nouveau_state.c */ -extern int nouveau_load(struct drm_device *, unsigned long flags); -extern int nouveau_firstopen(struct drm_device *); -extern void nouveau_lastclose(struct drm_device *); -extern int nouveau_unload(struct drm_device *); -extern int nouveau_card_init(struct drm_device *); - -/* nouveau_mem.c */ -extern int nouveau_mem_timing_calc(struct drm_device *, u32 freq, - struct nouveau_pm_memtiming *); -extern void nouveau_mem_timing_read(struct drm_device *, - struct nouveau_pm_memtiming *); - -/* nouveau_irq.c */ -extern int nouveau_irq_init(struct drm_device *); -extern void nouveau_irq_fini(struct drm_device *); -extern irqreturn_t nouveau_irq_handler(DRM_IRQ_ARGS); -extern void nouveau_irq_register(struct drm_device *, int status_bit, - void (*)(struct drm_device *)); -extern void nouveau_irq_unregister(struct drm_device *, int status_bit); -extern void nouveau_irq_preinstall(struct drm_device *); -extern int nouveau_irq_postinstall(struct drm_device *); -extern void nouveau_irq_uninstall(struct drm_device *); - -/* nouveau_backlight.c */ -#ifdef CONFIG_DRM_NOUVEAU_BACKLIGHT -extern int nouveau_backlight_init(struct drm_device *); -extern void nouveau_backlight_exit(struct drm_device *); -#else -static inline int nouveau_backlight_init(struct drm_device *dev) -{ - return 0; -} - -static inline void nouveau_backlight_exit(struct drm_device *dev) { } -#endif - -/* nouveau_bios.c */ -extern int nouveau_bios_init(struct drm_device *); -extern void nouveau_bios_takedown(struct drm_device *dev); -extern int nouveau_run_vbios_init(struct drm_device *); -extern struct dcb_connector_table_entry * -nouveau_bios_connector_entry(struct drm_device *, int index); -extern int nouveau_bios_run_display_table(struct drm_device *, u16 id, int clk, - struct dcb_output *, int crtc); -extern bool nouveau_bios_fp_mode(struct drm_device *, struct drm_display_mode *); -extern uint8_t *nouveau_bios_embedded_edid(struct drm_device *); -extern int nouveau_bios_parse_lvds_table(struct drm_device *, int pxclk, - bool *dl, bool *if_is_24bit); -extern int run_tmds_table(struct drm_device *, struct dcb_output *, - int head, int pxclk); -extern int call_lvds_script(struct drm_device *, struct dcb_output *, int head, - enum LVDS_script, int pxclk); -bool bios_encoder_match(struct dcb_output *, u32 hash); - -/* nouveau_ttm.c */ -int nouveau_ttm_global_init(struct drm_nouveau_private *); -void nouveau_ttm_global_release(struct drm_nouveau_private *); -int nouveau_ttm_mmap(struct file *, struct vm_area_struct *); - -/* nouveau_hdmi.c */ -void nouveau_hdmi_mode_set(struct drm_encoder *, struct drm_display_mode *); - -/* nvd0_display.c */ -extern int nvd0_display_create(struct drm_device *); -extern void nvd0_display_destroy(struct drm_device *); -extern int nvd0_display_init(struct drm_device *); -extern void nvd0_display_fini(struct drm_device *); -struct nouveau_bo *nvd0_display_crtc_sema(struct drm_device *, int crtc); -void nvd0_display_flip_stop(struct drm_crtc *); -int nvd0_display_flip_next(struct drm_crtc *, struct drm_framebuffer *, - struct nouveau_channel *, u32 swap_interval); - - -/* nouveau_display.c */ -int nouveau_display_create(struct drm_device *dev); -void nouveau_display_destroy(struct drm_device *dev); -int nouveau_display_init(struct drm_device *dev); -void nouveau_display_fini(struct drm_device *dev); -int nouveau_vblank_enable(struct drm_device *dev, int crtc); -void nouveau_vblank_disable(struct drm_device *dev, int crtc); -int nouveau_crtc_page_flip(struct drm_crtc *crtc, struct drm_framebuffer *fb, - struct drm_pending_vblank_event *event); -int nouveau_finish_page_flip(struct nouveau_channel *, - struct nouveau_page_flip_state *); -int nouveau_display_dumb_create(struct drm_file *, struct drm_device *, - struct drm_mode_create_dumb *args); -int nouveau_display_dumb_map_offset(struct drm_file *, struct drm_device *, - uint32_t handle, uint64_t *offset); -int nouveau_display_dumb_destroy(struct drm_file *, struct drm_device *, - uint32_t handle); - -#ifndef ioread32_native -#ifdef __BIG_ENDIAN -#define ioread16_native ioread16be -#define iowrite16_native iowrite16be -#define ioread32_native ioread32be -#define iowrite32_native iowrite32be -#else /* def __BIG_ENDIAN */ -#define ioread16_native ioread16 -#define iowrite16_native iowrite16 -#define ioread32_native ioread32 -#define iowrite32_native iowrite32 -#endif /* def __BIG_ENDIAN else */ -#endif /* !ioread32_native */ - -/* register access */ -#define nv_rd08 _nv_rd08 -#define nv_wr08 _nv_wr08 -#define nv_rd32 _nv_rd32 -#define nv_wr32 _nv_wr32 -#define nv_mask _nv_mask - -#define nv_wait(dev, reg, mask, val) \ - nouveau_wait_eq(dev, 2000000000ULL, (reg), (mask), (val)) -#define nv_wait_ne(dev, reg, mask, val) \ - nouveau_wait_ne(dev, 2000000000ULL, (reg), (mask), (val)) -#define nv_wait_cb(dev, func, data) \ - nouveau_wait_cb(dev, 2000000000ULL, (func), (data)) - -/* - * Logging - * Argument d is (struct drm_device *). - */ -#define NV_PRINTK(level, d, fmt, arg...) \ - printk(level "[" DRM_NAME "] " DRIVER_NAME " %s: " fmt, \ - pci_name(d->pdev), ##arg) -#ifndef NV_DEBUG_NOTRACE -#define NV_DEBUG(d, fmt, arg...) do { \ - if (drm_debug & DRM_UT_DRIVER) { \ - NV_PRINTK(KERN_DEBUG, d, "%s:%d - " fmt, __func__, \ - __LINE__, ##arg); \ - } \ -} while (0) -#define NV_DEBUG_KMS(d, fmt, arg...) do { \ - if (drm_debug & DRM_UT_KMS) { \ - NV_PRINTK(KERN_DEBUG, d, "%s:%d - " fmt, __func__, \ - __LINE__, ##arg); \ - } \ -} while (0) -#else -#define NV_DEBUG(d, fmt, arg...) do { \ - if (drm_debug & DRM_UT_DRIVER) \ - NV_PRINTK(KERN_DEBUG, d, fmt, ##arg); \ -} while (0) -#define NV_DEBUG_KMS(d, fmt, arg...) do { \ - if (drm_debug & DRM_UT_KMS) \ - NV_PRINTK(KERN_DEBUG, d, fmt, ##arg); \ -} while (0) -#endif -#define NV_ERROR(d, fmt, arg...) NV_PRINTK(KERN_ERR, d, fmt, ##arg) -#define NV_INFO(d, fmt, arg...) NV_PRINTK(KERN_INFO, d, fmt, ##arg) -#define NV_TRACEWARN(d, fmt, arg...) NV_PRINTK(KERN_NOTICE, d, fmt, ##arg) -#define NV_TRACE(d, fmt, arg...) NV_PRINTK(KERN_INFO, d, fmt, ##arg) -#define NV_WARN(d, fmt, arg...) NV_PRINTK(KERN_WARNING, d, fmt, ##arg) -#define NV_WARNONCE(d, fmt, arg...) do { \ - static int _warned = 0; \ - if (!_warned) { \ - NV_WARN(d, fmt, ##arg); \ - _warned = 1; \ - } \ -} while(0) - -static inline bool -nv_two_heads(struct drm_device *dev) -{ - struct drm_nouveau_private *dev_priv = dev->dev_private; - const int impl = dev->pci_device & 0x0ff0; - - if (dev_priv->card_type >= NV_10 && impl != 0x0100 && - impl != 0x0150 && impl != 0x01a0 && impl != 0x0200) - return true; - - return false; -} - -static inline bool -nv_gf4_disp_arch(struct drm_device *dev) -{ - return nv_two_heads(dev) && (dev->pci_device & 0x0ff0) != 0x0110; -} - -static inline bool -nv_two_reg_pll(struct drm_device *dev) -{ - struct drm_nouveau_private *dev_priv = dev->dev_private; - const int impl = dev->pci_device & 0x0ff0; - - if (impl == 0x0310 || impl == 0x0340 || dev_priv->card_type >= NV_40) - return true; - return false; -} - -static inline bool -nv_match_device(struct drm_device *dev, unsigned device, - unsigned sub_vendor, unsigned sub_device) -{ - return dev->pdev->device == device && - dev->pdev->subsystem_vendor == sub_vendor && - dev->pdev->subsystem_device == sub_device; -} - -static inline struct nv04_display * -nv04_display(struct drm_device *dev) -{ - struct drm_nouveau_private *dev_priv = dev->dev_private; - return dev_priv->engine.display.priv; -} - -#endif /* __NOUVEAU_DRV_H__ */ diff --git a/drivers/gpu/drm/nouveau/nouveau_fb.h b/drivers/gpu/drm/nouveau/nouveau_fb.h deleted file mode 100644 index d767567977ee..000000000000 --- a/drivers/gpu/drm/nouveau/nouveau_fb.h +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright (C) 2008 Maarten Maathuis. - * All Rights Reserved. - * - * 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 (including the - * next paragraph) 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 OWNER(S) AND/OR ITS SUPPLIERS 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. - * - */ - -#ifndef __NOUVEAU_FRB_H__ -#define __NOUVEAU_FRB_H__ - -struct nouveau_framebuffer { - struct drm_framebuffer base; - struct nouveau_bo *nvbo; - struct nouveau_vma vma; - u32 r_dma; - u32 r_format; - u32 r_pitch; -}; - -static inline struct nouveau_framebuffer * -nouveau_framebuffer(struct drm_framebuffer *fb) -{ - return container_of(fb, struct nouveau_framebuffer, base); -} - -int nouveau_framebuffer_init(struct drm_device *dev, struct nouveau_framebuffer *nouveau_fb, - struct drm_mode_fb_cmd2 *mode_cmd, struct nouveau_bo *nvbo); -#endif /* __NOUVEAU_FB_H__ */ diff --git a/drivers/gpu/drm/nouveau/nouveau_fbcon.c b/drivers/gpu/drm/nouveau/nouveau_fbcon.c index 8b8bc8314d92..e75e071845b7 100644 --- a/drivers/gpu/drm/nouveau/nouveau_fbcon.c +++ b/drivers/gpu/drm/nouveau/nouveau_fbcon.c @@ -47,7 +47,6 @@ #include "nouveau_drm.h" #include "nouveau_gem.h" #include "nouveau_bo.h" -#include "nouveau_fb.h" #include "nouveau_fbcon.h" #include "nouveau_chan.h" @@ -66,7 +65,7 @@ static void nouveau_fbcon_fillrect(struct fb_info *info, const struct fb_fillrect *rect) { struct nouveau_fbdev *fbcon = info->par; - struct nouveau_drm *drm = nouveau_newpriv(fbcon->dev); + struct nouveau_drm *drm = nouveau_drm(fbcon->dev); struct nouveau_device *device = nv_device(drm->device); int ret; @@ -98,7 +97,7 @@ static void nouveau_fbcon_copyarea(struct fb_info *info, const struct fb_copyarea *image) { struct nouveau_fbdev *fbcon = info->par; - struct nouveau_drm *drm = nouveau_newpriv(fbcon->dev); + struct nouveau_drm *drm = nouveau_drm(fbcon->dev); struct nouveau_device *device = nv_device(drm->device); int ret; @@ -130,7 +129,7 @@ static void nouveau_fbcon_imageblit(struct fb_info *info, const struct fb_image *image) { struct nouveau_fbdev *fbcon = info->par; - struct nouveau_drm *drm = nouveau_newpriv(fbcon->dev); + struct nouveau_drm *drm = nouveau_drm(fbcon->dev); struct nouveau_device *device = nv_device(drm->device); int ret; @@ -162,7 +161,7 @@ static int nouveau_fbcon_sync(struct fb_info *info) { struct nouveau_fbdev *fbcon = info->par; - struct nouveau_drm *drm = nouveau_newpriv(fbcon->dev); + struct nouveau_drm *drm = nouveau_drm(fbcon->dev); struct nouveau_channel *chan = drm->channel; int ret; @@ -257,7 +256,7 @@ nouveau_fbcon_create(struct nouveau_fbdev *fbcon, struct drm_fb_helper_surface_size *sizes) { struct drm_device *dev = fbcon->dev; - struct nouveau_drm *drm = nouveau_newpriv(dev); + struct nouveau_drm *drm = nouveau_drm(dev); struct nouveau_device *device = nv_device(drm->device); struct fb_info *info; struct drm_framebuffer *fb; @@ -410,7 +409,7 @@ nouveau_fbcon_find_or_create_single(struct drm_fb_helper *helper, void nouveau_fbcon_output_poll_changed(struct drm_device *dev) { - struct nouveau_drm *drm = nouveau_newpriv(dev); + struct nouveau_drm *drm = nouveau_drm(dev); drm_fb_helper_hotplug_event(&drm->fbcon->helper); } @@ -442,7 +441,7 @@ nouveau_fbcon_destroy(struct drm_device *dev, struct nouveau_fbdev *fbcon) void nouveau_fbcon_gpu_lockup(struct fb_info *info) { struct nouveau_fbdev *fbcon = info->par; - struct nouveau_drm *drm = nouveau_newpriv(fbcon->dev); + struct nouveau_drm *drm = nouveau_drm(fbcon->dev); NV_ERROR(drm, "GPU lockup - switching to software fbcon\n"); info->flags |= FBINFO_HWACCEL_DISABLED; @@ -458,7 +457,7 @@ static struct drm_fb_helper_funcs nouveau_fbcon_helper_funcs = { int nouveau_fbcon_init(struct drm_device *dev) { - struct nouveau_drm *drm = nouveau_newpriv(dev); + struct nouveau_drm *drm = nouveau_drm(dev); struct nouveau_fb *pfb = nouveau_fb(drm->device); struct nouveau_fbdev *fbcon; int preferred_bpp; @@ -499,7 +498,7 @@ nouveau_fbcon_init(struct drm_device *dev) void nouveau_fbcon_fini(struct drm_device *dev) { - struct nouveau_drm *drm = nouveau_newpriv(dev); + struct nouveau_drm *drm = nouveau_drm(dev); if (!drm->fbcon) return; @@ -511,7 +510,7 @@ nouveau_fbcon_fini(struct drm_device *dev) void nouveau_fbcon_save_disable_accel(struct drm_device *dev) { - struct nouveau_drm *drm = nouveau_newpriv(dev); + struct nouveau_drm *drm = nouveau_drm(dev); drm->fbcon->saved_flags = drm->fbcon->helper.fbdev->flags; drm->fbcon->helper.fbdev->flags |= FBINFO_HWACCEL_DISABLED; @@ -519,13 +518,13 @@ void nouveau_fbcon_save_disable_accel(struct drm_device *dev) void nouveau_fbcon_restore_accel(struct drm_device *dev) { - struct nouveau_drm *drm = nouveau_newpriv(dev); + struct nouveau_drm *drm = nouveau_drm(dev); drm->fbcon->helper.fbdev->flags = drm->fbcon->saved_flags; } void nouveau_fbcon_set_suspend(struct drm_device *dev, int state) { - struct nouveau_drm *drm = nouveau_newpriv(dev); + struct nouveau_drm *drm = nouveau_drm(dev); console_lock(); if (state == 0) nouveau_fbcon_save_disable_accel(dev); @@ -537,6 +536,6 @@ void nouveau_fbcon_set_suspend(struct drm_device *dev, int state) void nouveau_fbcon_zfill_all(struct drm_device *dev) { - struct nouveau_drm *drm = nouveau_newpriv(dev); + struct nouveau_drm *drm = nouveau_drm(dev); nouveau_fbcon_zfill(dev, drm->fbcon); } diff --git a/drivers/gpu/drm/nouveau/nouveau_fbcon.h b/drivers/gpu/drm/nouveau/nouveau_fbcon.h index e6404e39eaf1..18e028008225 100644 --- a/drivers/gpu/drm/nouveau/nouveau_fbcon.h +++ b/drivers/gpu/drm/nouveau/nouveau_fbcon.h @@ -29,7 +29,7 @@ #include "drm_fb_helper.h" -#include "nouveau_fb.h" +#include "nouveau_display.h" struct nouveau_fbdev { struct drm_fb_helper helper; diff --git a/drivers/gpu/drm/nouveau/nouveau_gem.c b/drivers/gpu/drm/nouveau/nouveau_gem.c index ba744daeb50e..6454370e78cf 100644 --- a/drivers/gpu/drm/nouveau/nouveau_gem.c +++ b/drivers/gpu/drm/nouveau/nouveau_gem.c @@ -550,7 +550,7 @@ nouveau_gem_pushbuf_reloc_apply(struct drm_device *dev, struct drm_nouveau_gem_pushbuf *req, struct drm_nouveau_gem_pushbuf_bo *bo) { - struct nouveau_drm *drm = nouveau_newpriv(dev); + struct nouveau_drm *drm = nouveau_drm(dev); struct drm_nouveau_gem_pushbuf_reloc *reloc = NULL; int ret = 0; unsigned i; diff --git a/drivers/gpu/drm/nouveau/nouveau_hdmi.c b/drivers/gpu/drm/nouveau/nouveau_hdmi.c index c3de36384522..ea712b5762e7 100644 --- a/drivers/gpu/drm/nouveau/nouveau_hdmi.c +++ b/drivers/gpu/drm/nouveau/nouveau_hdmi.c @@ -23,7 +23,7 @@ */ #include "drmP.h" -#include "nouveau_drv.h" +#include "nouveau_drm.h" #include "nouveau_connector.h" #include "nouveau_encoder.h" #include "nouveau_crtc.h" @@ -31,10 +31,10 @@ static bool hdmi_sor(struct drm_encoder *encoder) { - struct drm_nouveau_private *dev_priv = encoder->dev->dev_private; - if (dev_priv->chipset < 0xa3 || - dev_priv->chipset == 0xaa || - dev_priv->chipset == 0xac) + struct nouveau_drm *drm = nouveau_drm(encoder->dev); + if (nv_device(drm->device)->chipset < 0xa3 || + nv_device(drm->device)->chipset == 0xaa || + nv_device(drm->device)->chipset == 0xac) return false; return true; } @@ -52,13 +52,15 @@ hdmi_base(struct drm_encoder *encoder) static void hdmi_wr32(struct drm_encoder *encoder, u32 reg, u32 val) { - nv_wr32(encoder->dev, hdmi_base(encoder) + reg, val); + struct nouveau_device *device = nouveau_dev(encoder->dev); + nv_wr32(device, hdmi_base(encoder) + reg, val); } static u32 hdmi_rd32(struct drm_encoder *encoder, u32 reg) { - return nv_rd32(encoder->dev, hdmi_base(encoder) + reg); + struct nouveau_device *device = nouveau_dev(encoder->dev); + return nv_rd32(device, hdmi_base(encoder) + reg); } static u32 @@ -73,12 +75,11 @@ static void nouveau_audio_disconnect(struct drm_encoder *encoder) { struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); - struct drm_device *dev = encoder->dev; + struct nouveau_device *device = nouveau_dev(encoder->dev); u32 or = nv_encoder->or * 0x800; - if (hdmi_sor(encoder)) { - nv_mask(dev, 0x61c448 + or, 0x00000003, 0x00000000); - } + if (hdmi_sor(encoder)) + nv_mask(device, 0x61c448 + or, 0x00000003, 0x00000000); } static void @@ -86,8 +87,8 @@ nouveau_audio_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode) { struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); + struct nouveau_device *device = nouveau_dev(encoder->dev); struct nouveau_connector *nv_connector; - struct drm_device *dev = encoder->dev; u32 or = nv_encoder->or * 0x800; int i; @@ -98,16 +99,16 @@ nouveau_audio_mode_set(struct drm_encoder *encoder, } if (hdmi_sor(encoder)) { - nv_mask(dev, 0x61c448 + or, 0x00000001, 0x00000001); + nv_mask(device, 0x61c448 + or, 0x00000001, 0x00000001); drm_edid_to_eld(&nv_connector->base, nv_connector->edid); if (nv_connector->base.eld[0]) { u8 *eld = nv_connector->base.eld; for (i = 0; i < eld[2] * 4; i++) - nv_wr32(dev, 0x61c440 + or, (i << 8) | eld[i]); + nv_wr32(device, 0x61c440 + or, (i << 8) | eld[i]); for (i = eld[2] * 4; i < 0x60; i++) - nv_wr32(dev, 0x61c440 + or, (i << 8) | 0x00); - nv_mask(dev, 0x61c448 + or, 0x00000002, 0x00000002); + nv_wr32(device, 0x61c440 + or, (i << 8) | 0x00); + nv_mask(device, 0x61c448 + or, 0x00000002, 0x00000002); } } } @@ -219,9 +220,9 @@ void nouveau_hdmi_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode) { + struct nouveau_device *device = nouveau_dev(encoder->dev); struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); struct nouveau_connector *nv_connector; - struct drm_device *dev = encoder->dev; u32 max_ac_packet, rekey; nv_connector = nouveau_encoder_connector_get(nv_encoder); @@ -238,9 +239,9 @@ nouveau_hdmi_mode_set(struct drm_encoder *encoder, hdmi_mask(encoder, 0x068, 0x00010101, 0x00000000); /* ACR_CTRL, ?? */ hdmi_mask(encoder, 0x078, 0x80000000, 0x80000000); /* ACR_0441_ENABLE */ - nv_mask(dev, 0x61733c, 0x00100000, 0x00100000); /* RESETF */ - nv_mask(dev, 0x61733c, 0x10000000, 0x10000000); /* LOOKUP_EN */ - nv_mask(dev, 0x61733c, 0x00100000, 0x00000000); /* !RESETF */ + nv_mask(device, 0x61733c, 0x00100000, 0x00100000); /* RESETF */ + nv_mask(device, 0x61733c, 0x10000000, 0x10000000); /* LOOKUP_EN */ + nv_mask(device, 0x61733c, 0x00100000, 0x00000000); /* !RESETF */ /* value matches nvidia binary driver, and tegra constant */ rekey = 56; diff --git a/drivers/gpu/drm/nouveau/nouveau_hw.c b/drivers/gpu/drm/nouveau/nouveau_hw.c index dcb65797acbc..a78b24704794 100644 --- a/drivers/gpu/drm/nouveau/nouveau_hw.c +++ b/drivers/gpu/drm/nouveau/nouveau_hw.c @@ -23,10 +23,12 @@ */ #include "drmP.h" -#include "nouveau_drv.h" +#include "nouveau_drm.h" #include "nouveau_hw.h" #include +#include +#include #define CHIPSET_NFORCE 0x01a0 #define CHIPSET_NFORCE2 0x01f0 @@ -84,12 +86,12 @@ NVReadVgaGr(struct drm_device *dev, int head, uint8_t index) void NVSetOwner(struct drm_device *dev, int owner) { - struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_drm *drm = nouveau_drm(dev); if (owner == 1) owner *= 3; - if (dev_priv->chipset == 0x11) { + if (nv_device(drm->device)->chipset == 0x11) { /* This might seem stupid, but the blob does it and * omitting it often locks the system up. */ @@ -100,7 +102,7 @@ NVSetOwner(struct drm_device *dev, int owner) /* CR44 is always changed on CRTC0 */ NVWriteVgaCrtc(dev, 0, NV_CIO_CRE_44, owner); - if (dev_priv->chipset == 0x11) { /* set me harder */ + if (nv_device(drm->device)->chipset == 0x11) { /* set me harder */ NVWriteVgaCrtc(dev, 0, NV_CIO_CRE_2E, owner); NVWriteVgaCrtc(dev, 0, NV_CIO_CRE_2E, owner); } @@ -132,7 +134,7 @@ static void nouveau_hw_decode_pll(struct drm_device *dev, uint32_t reg1, uint32_t pll1, uint32_t pll2, struct nouveau_pll_vals *pllvals) { - struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_drm *drm = nouveau_drm(dev); /* to force parsing as single stage (i.e. nv40 vplls) pass pll2 as 0 */ @@ -149,7 +151,7 @@ nouveau_hw_decode_pll(struct drm_device *dev, uint32_t reg1, uint32_t pll1, pllvals->NM1 = pll1 & 0xffff; if (nv_two_reg_pll(dev) && pll2 & NV31_RAMDAC_ENABLE_VCO2) pllvals->NM2 = pll2 & 0xffff; - else if (dev_priv->chipset == 0x30 || dev_priv->chipset == 0x35) { + else if (nv_device(drm->device)->chipset == 0x30 || nv_device(drm->device)->chipset == 0x35) { pllvals->M1 &= 0xf; /* only 4 bits */ if (pll1 & NV30_RAMDAC_ENABLE_VCO2) { pllvals->M2 = (pll1 >> 4) & 0x7; @@ -164,25 +166,27 @@ int nouveau_hw_get_pllvals(struct drm_device *dev, enum nvbios_pll_type plltype, struct nouveau_pll_vals *pllvals) { - struct drm_nouveau_private *dev_priv = dev->dev_private; - uint32_t reg1 = get_pll_register(dev, plltype), pll1, pll2 = 0; + struct nouveau_drm *drm = nouveau_drm(dev); + struct nouveau_device *device = nv_device(drm->device); + struct nouveau_bios *bios = nouveau_bios(device); + uint32_t reg1, pll1, pll2 = 0; struct nvbios_pll pll_lim; int ret; - if (reg1 == 0) + ret = nvbios_pll_parse(bios, plltype, &pll_lim); + if (ret || !(reg1 = pll_lim.reg)) return -ENOENT; - pll1 = nv_rd32(dev, reg1); - + pll1 = nv_rd32(device, reg1); if (reg1 <= 0x405c) - pll2 = nv_rd32(dev, reg1 + 4); + pll2 = nv_rd32(device, reg1 + 4); else if (nv_two_reg_pll(dev)) { uint32_t reg2 = reg1 + (reg1 == NV_RAMDAC_VPLL2 ? 0x5c : 0x70); - pll2 = nv_rd32(dev, reg2); + pll2 = nv_rd32(device, reg2); } - if (dev_priv->card_type == 0x40 && reg1 >= NV_PRAMDAC_VPLL_COEFF) { + if (nv_device(drm->device)->card_type == 0x40 && reg1 >= NV_PRAMDAC_VPLL_COEFF) { uint32_t ramdac580 = NVReadRAMDAC(dev, 0, NV_PRAMDAC_580); /* check whether vpll has been forced into single stage mode */ @@ -195,13 +199,7 @@ nouveau_hw_get_pllvals(struct drm_device *dev, enum nvbios_pll_type plltype, } nouveau_hw_decode_pll(dev, reg1, pll1, pll2, pllvals); - - ret = get_pll_limits(dev, plltype, &pll_lim); - if (ret) - return ret; - pllvals->refclk = pll_lim.refclk; - return 0; } @@ -255,11 +253,15 @@ nouveau_hw_fix_bad_vpll(struct drm_device *dev, int head) * when such a condition detected. only seen on nv11 to date */ + struct nouveau_drm *drm = nouveau_drm(dev); + struct nouveau_device *device = nv_device(drm->device); + struct nouveau_clock *clk = nouveau_clock(device); + struct nouveau_bios *bios = nouveau_bios(device); struct nvbios_pll pll_lim; struct nouveau_pll_vals pv; enum nvbios_pll_type pll = head ? PLL_VPLL1 : PLL_VPLL0; - if (get_pll_limits(dev, pll, &pll_lim)) + if (nvbios_pll_parse(bios, pll, &pll_lim)) return; nouveau_hw_get_pllvals(dev, pll, &pv); @@ -268,13 +270,13 @@ nouveau_hw_fix_bad_vpll(struct drm_device *dev, int head) pv.log2P <= pll_lim.max_p) return; - NV_WARN(dev, "VPLL %d outwith limits, attempting to fix\n", head + 1); + NV_WARN(drm, "VPLL %d outwith limits, attempting to fix\n", head + 1); /* set lowest clock within static limits */ pv.M1 = pll_lim.vco1.max_m; pv.N1 = pll_lim.vco1.min_n; pv.log2P = pll_lim.max_p_usable; - nouveau_hw_setpll(dev, pll_lim.reg, &pv); + clk->pll_prog(clk, pll_lim.reg, &pv); } /* @@ -303,6 +305,7 @@ static void nouveau_vga_font_io(struct drm_device *dev, void nouveau_hw_save_vga_fonts(struct drm_device *dev, bool save) { + struct nouveau_drm *drm = nouveau_drm(dev); uint8_t misc, gr4, gr5, gr6, seq2, seq4; bool graphicsmode; unsigned plane; @@ -318,12 +321,12 @@ nouveau_hw_save_vga_fonts(struct drm_device *dev, bool save) if (graphicsmode) /* graphics mode => framebuffer => no need to save */ return; - NV_INFO(dev, "%sing VGA fonts\n", save ? "Sav" : "Restor"); + NV_INFO(drm, "%sing VGA fonts\n", save ? "Sav" : "Restor"); /* map first 64KiB of VRAM, holds VGA fonts etc */ iovram = ioremap(pci_resource_start(dev->pdev, 1), 65536); if (!iovram) { - NV_ERROR(dev, "Failed to map VRAM, " + NV_ERROR(drm, "Failed to map VRAM, " "cannot save/restore VGA fonts.\n"); return; } @@ -386,25 +389,25 @@ static void nv_save_state_ramdac(struct drm_device *dev, int head, struct nv04_mode_state *state) { - struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_drm *drm = nouveau_drm(dev); struct nv04_crtc_reg *regp = &state->crtc_reg[head]; int i; - if (dev_priv->card_type >= NV_10) + if (nv_device(drm->device)->card_type >= NV_10) regp->nv10_cursync = NVReadRAMDAC(dev, head, NV_RAMDAC_NV10_CURSYNC); nouveau_hw_get_pllvals(dev, head ? PLL_VPLL1 : PLL_VPLL0, ®p->pllvals); state->pllsel = NVReadRAMDAC(dev, 0, NV_PRAMDAC_PLL_COEFF_SELECT); if (nv_two_heads(dev)) state->sel_clk = NVReadRAMDAC(dev, 0, NV_PRAMDAC_SEL_CLK); - if (dev_priv->chipset == 0x11) + if (nv_device(drm->device)->chipset == 0x11) regp->dither = NVReadRAMDAC(dev, head, NV_RAMDAC_DITHER_NV11); regp->ramdac_gen_ctrl = NVReadRAMDAC(dev, head, NV_PRAMDAC_GENERAL_CONTROL); if (nv_gf4_disp_arch(dev)) regp->ramdac_630 = NVReadRAMDAC(dev, head, NV_PRAMDAC_630); - if (dev_priv->chipset >= 0x30) + if (nv_device(drm->device)->chipset >= 0x30) regp->ramdac_634 = NVReadRAMDAC(dev, head, NV_PRAMDAC_634); regp->tv_setup = NVReadRAMDAC(dev, head, NV_PRAMDAC_TV_SETUP); @@ -446,7 +449,7 @@ nv_save_state_ramdac(struct drm_device *dev, int head, if (nv_gf4_disp_arch(dev)) regp->ramdac_8c0 = NVReadRAMDAC(dev, head, NV_PRAMDAC_8C0); - if (dev_priv->card_type == NV_40) { + if (nv_device(drm->device)->card_type == NV_40) { regp->ramdac_a20 = NVReadRAMDAC(dev, head, NV_PRAMDAC_A20); regp->ramdac_a24 = NVReadRAMDAC(dev, head, NV_PRAMDAC_A24); regp->ramdac_a34 = NVReadRAMDAC(dev, head, NV_PRAMDAC_A34); @@ -461,26 +464,27 @@ static void nv_load_state_ramdac(struct drm_device *dev, int head, struct nv04_mode_state *state) { - struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_drm *drm = nouveau_drm(dev); + struct nouveau_clock *clk = nouveau_clock(drm->device); struct nv04_crtc_reg *regp = &state->crtc_reg[head]; uint32_t pllreg = head ? NV_RAMDAC_VPLL2 : NV_PRAMDAC_VPLL_COEFF; int i; - if (dev_priv->card_type >= NV_10) + if (nv_device(drm->device)->card_type >= NV_10) NVWriteRAMDAC(dev, head, NV_RAMDAC_NV10_CURSYNC, regp->nv10_cursync); - nouveau_hw_setpll(dev, pllreg, ®p->pllvals); + clk->pll_prog(clk, pllreg, ®p->pllvals); NVWriteRAMDAC(dev, 0, NV_PRAMDAC_PLL_COEFF_SELECT, state->pllsel); if (nv_two_heads(dev)) NVWriteRAMDAC(dev, 0, NV_PRAMDAC_SEL_CLK, state->sel_clk); - if (dev_priv->chipset == 0x11) + if (nv_device(drm->device)->chipset == 0x11) NVWriteRAMDAC(dev, head, NV_RAMDAC_DITHER_NV11, regp->dither); NVWriteRAMDAC(dev, head, NV_PRAMDAC_GENERAL_CONTROL, regp->ramdac_gen_ctrl); if (nv_gf4_disp_arch(dev)) NVWriteRAMDAC(dev, head, NV_PRAMDAC_630, regp->ramdac_630); - if (dev_priv->chipset >= 0x30) + if (nv_device(drm->device)->chipset >= 0x30) NVWriteRAMDAC(dev, head, NV_PRAMDAC_634, regp->ramdac_634); NVWriteRAMDAC(dev, head, NV_PRAMDAC_TV_SETUP, regp->tv_setup); @@ -517,7 +521,7 @@ nv_load_state_ramdac(struct drm_device *dev, int head, if (nv_gf4_disp_arch(dev)) NVWriteRAMDAC(dev, head, NV_PRAMDAC_8C0, regp->ramdac_8c0); - if (dev_priv->card_type == NV_40) { + if (nv_device(drm->device)->card_type == NV_40) { NVWriteRAMDAC(dev, head, NV_PRAMDAC_A20, regp->ramdac_a20); NVWriteRAMDAC(dev, head, NV_PRAMDAC_A24, regp->ramdac_a24); NVWriteRAMDAC(dev, head, NV_PRAMDAC_A34, regp->ramdac_a34); @@ -582,7 +586,7 @@ static void nv_save_state_ext(struct drm_device *dev, int head, struct nv04_mode_state *state) { - struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_drm *drm = nouveau_drm(dev); struct nv04_crtc_reg *regp = &state->crtc_reg[head]; int i; @@ -598,10 +602,10 @@ nv_save_state_ext(struct drm_device *dev, int head, rd_cio_state(dev, head, regp, NV_CIO_CRE_FFLWM__INDEX); rd_cio_state(dev, head, regp, NV_CIO_CRE_21); - if (dev_priv->card_type >= NV_20) + if (nv_device(drm->device)->card_type >= NV_20) rd_cio_state(dev, head, regp, NV_CIO_CRE_47); - if (dev_priv->card_type >= NV_30) + if (nv_device(drm->device)->card_type >= NV_30) rd_cio_state(dev, head, regp, 0x9f); rd_cio_state(dev, head, regp, NV_CIO_CRE_49); @@ -610,14 +614,14 @@ nv_save_state_ext(struct drm_device *dev, int head, rd_cio_state(dev, head, regp, NV_CIO_CRE_HCUR_ADDR2_INDEX); rd_cio_state(dev, head, regp, NV_CIO_CRE_ILACE__INDEX); - if (dev_priv->card_type >= NV_10) { + if (nv_device(drm->device)->card_type >= NV_10) { regp->crtc_830 = NVReadCRTC(dev, head, NV_PCRTC_830); regp->crtc_834 = NVReadCRTC(dev, head, NV_PCRTC_834); - if (dev_priv->card_type >= NV_30) + if (nv_device(drm->device)->card_type >= NV_30) regp->gpio_ext = NVReadCRTC(dev, head, NV_PCRTC_GPIO_EXT); - if (dev_priv->card_type == NV_40) + if (nv_device(drm->device)->card_type == NV_40) regp->crtc_850 = NVReadCRTC(dev, head, NV_PCRTC_850); if (nv_two_heads(dev)) @@ -629,7 +633,7 @@ nv_save_state_ext(struct drm_device *dev, int head, rd_cio_state(dev, head, regp, NV_CIO_CRE_SCRATCH3__INDEX); rd_cio_state(dev, head, regp, NV_CIO_CRE_SCRATCH4__INDEX); - if (dev_priv->card_type >= NV_10) { + if (nv_device(drm->device)->card_type >= NV_10) { rd_cio_state(dev, head, regp, NV_CIO_CRE_EBR_INDEX); rd_cio_state(dev, head, regp, NV_CIO_CRE_CSB); rd_cio_state(dev, head, regp, NV_CIO_CRE_4B); @@ -657,12 +661,14 @@ static void nv_load_state_ext(struct drm_device *dev, int head, struct nv04_mode_state *state) { - struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_drm *drm = nouveau_drm(dev); + struct nouveau_device *device = nv_device(drm->device); + struct nouveau_timer *ptimer = nouveau_timer(device); struct nv04_crtc_reg *regp = &state->crtc_reg[head]; uint32_t reg900; int i; - if (dev_priv->card_type >= NV_10) { + if (nv_device(drm->device)->card_type >= NV_10) { if (nv_two_heads(dev)) /* setting ENGINE_CTRL (EC) *must* come before * CIO_CRE_LCD, as writing CRE_LCD sets bits 16 & 17 in @@ -670,24 +676,24 @@ nv_load_state_ext(struct drm_device *dev, int head, */ NVWriteCRTC(dev, head, NV_PCRTC_ENGINE_CTRL, regp->crtc_eng_ctrl); - nv_wr32(dev, NV_PVIDEO_STOP, 1); - nv_wr32(dev, NV_PVIDEO_INTR_EN, 0); - nv_wr32(dev, NV_PVIDEO_OFFSET_BUFF(0), 0); - nv_wr32(dev, NV_PVIDEO_OFFSET_BUFF(1), 0); - nv_wr32(dev, NV_PVIDEO_LIMIT(0), 0); //dev_priv->fb_available_size - 1); - nv_wr32(dev, NV_PVIDEO_LIMIT(1), 0); //dev_priv->fb_available_size - 1); - nv_wr32(dev, NV_PVIDEO_UVPLANE_LIMIT(0), 0); //dev_priv->fb_available_size - 1); - nv_wr32(dev, NV_PVIDEO_UVPLANE_LIMIT(1), 0); //dev_priv->fb_available_size - 1); - nv_wr32(dev, NV_PBUS_POWERCTRL_2, 0); + nv_wr32(device, NV_PVIDEO_STOP, 1); + nv_wr32(device, NV_PVIDEO_INTR_EN, 0); + nv_wr32(device, NV_PVIDEO_OFFSET_BUFF(0), 0); + nv_wr32(device, NV_PVIDEO_OFFSET_BUFF(1), 0); + nv_wr32(device, NV_PVIDEO_LIMIT(0), 0); //drm->fb_available_size - 1); + nv_wr32(device, NV_PVIDEO_LIMIT(1), 0); //drm->fb_available_size - 1); + nv_wr32(device, NV_PVIDEO_UVPLANE_LIMIT(0), 0); //drm->fb_available_size - 1); + nv_wr32(device, NV_PVIDEO_UVPLANE_LIMIT(1), 0); //drm->fb_available_size - 1); + nv_wr32(device, NV_PBUS_POWERCTRL_2, 0); NVWriteCRTC(dev, head, NV_PCRTC_CURSOR_CONFIG, regp->cursor_cfg); NVWriteCRTC(dev, head, NV_PCRTC_830, regp->crtc_830); NVWriteCRTC(dev, head, NV_PCRTC_834, regp->crtc_834); - if (dev_priv->card_type >= NV_30) + if (nv_device(drm->device)->card_type >= NV_30) NVWriteCRTC(dev, head, NV_PCRTC_GPIO_EXT, regp->gpio_ext); - if (dev_priv->card_type == NV_40) { + if (nv_device(drm->device)->card_type == NV_40) { NVWriteCRTC(dev, head, NV_PCRTC_850, regp->crtc_850); reg900 = NVReadRAMDAC(dev, head, NV_PRAMDAC_900); @@ -710,23 +716,23 @@ nv_load_state_ext(struct drm_device *dev, int head, wr_cio_state(dev, head, regp, NV_CIO_CRE_FF_INDEX); wr_cio_state(dev, head, regp, NV_CIO_CRE_FFLWM__INDEX); - if (dev_priv->card_type >= NV_20) + if (nv_device(drm->device)->card_type >= NV_20) wr_cio_state(dev, head, regp, NV_CIO_CRE_47); - if (dev_priv->card_type >= NV_30) + if (nv_device(drm->device)->card_type >= NV_30) wr_cio_state(dev, head, regp, 0x9f); wr_cio_state(dev, head, regp, NV_CIO_CRE_49); wr_cio_state(dev, head, regp, NV_CIO_CRE_HCUR_ADDR0_INDEX); wr_cio_state(dev, head, regp, NV_CIO_CRE_HCUR_ADDR1_INDEX); wr_cio_state(dev, head, regp, NV_CIO_CRE_HCUR_ADDR2_INDEX); - if (dev_priv->card_type == NV_40) + if (nv_device(drm->device)->card_type == NV_40) nv_fix_nv40_hw_cursor(dev, head); wr_cio_state(dev, head, regp, NV_CIO_CRE_ILACE__INDEX); wr_cio_state(dev, head, regp, NV_CIO_CRE_SCRATCH3__INDEX); wr_cio_state(dev, head, regp, NV_CIO_CRE_SCRATCH4__INDEX); - if (dev_priv->card_type >= NV_10) { + if (nv_device(drm->device)->card_type >= NV_10) { wr_cio_state(dev, head, regp, NV_CIO_CRE_EBR_INDEX); wr_cio_state(dev, head, regp, NV_CIO_CRE_CSB); wr_cio_state(dev, head, regp, NV_CIO_CRE_4B); @@ -734,11 +740,11 @@ nv_load_state_ext(struct drm_device *dev, int head, } /* NV11 and NV20 stop at 0x52. */ if (nv_gf4_disp_arch(dev)) { - if (dev_priv->card_type == NV_10) { + if (nv_device(drm->device)->card_type == NV_10) { /* Not waiting for vertical retrace before modifying CRE_53/CRE_54 causes lockups. */ - nouveau_wait_eq(dev, 650000000, NV_PRMCIO_INP0__COLOR, 0x8, 0x8); - nouveau_wait_eq(dev, 650000000, NV_PRMCIO_INP0__COLOR, 0x8, 0x0); + nouveau_timer_wait_eq(ptimer, 650000000, NV_PRMCIO_INP0__COLOR, 0x8, 0x8); + nouveau_timer_wait_eq(ptimer, 650000000, NV_PRMCIO_INP0__COLOR, 0x8, 0x0); } wr_cio_state(dev, head, regp, NV_CIO_CRE_42); @@ -761,14 +767,15 @@ static void nv_save_state_palette(struct drm_device *dev, int head, struct nv04_mode_state *state) { + struct nouveau_device *device = nouveau_dev(dev); int head_offset = head * NV_PRMDIO_SIZE, i; - nv_wr08(dev, NV_PRMDIO_PIXEL_MASK + head_offset, + nv_wr08(device, NV_PRMDIO_PIXEL_MASK + head_offset, NV_PRMDIO_PIXEL_MASK_MASK); - nv_wr08(dev, NV_PRMDIO_READ_MODE_ADDRESS + head_offset, 0x0); + nv_wr08(device, NV_PRMDIO_READ_MODE_ADDRESS + head_offset, 0x0); for (i = 0; i < 768; i++) { - state->crtc_reg[head].DAC[i] = nv_rd08(dev, + state->crtc_reg[head].DAC[i] = nv_rd08(device, NV_PRMDIO_PALETTE_DATA + head_offset); } @@ -779,14 +786,15 @@ void nouveau_hw_load_state_palette(struct drm_device *dev, int head, struct nv04_mode_state *state) { + struct nouveau_device *device = nouveau_dev(dev); int head_offset = head * NV_PRMDIO_SIZE, i; - nv_wr08(dev, NV_PRMDIO_PIXEL_MASK + head_offset, + nv_wr08(device, NV_PRMDIO_PIXEL_MASK + head_offset, NV_PRMDIO_PIXEL_MASK_MASK); - nv_wr08(dev, NV_PRMDIO_WRITE_MODE_ADDRESS + head_offset, 0x0); + nv_wr08(device, NV_PRMDIO_WRITE_MODE_ADDRESS + head_offset, 0x0); for (i = 0; i < 768; i++) { - nv_wr08(dev, NV_PRMDIO_PALETTE_DATA + head_offset, + nv_wr08(device, NV_PRMDIO_PALETTE_DATA + head_offset, state->crtc_reg[head].DAC[i]); } @@ -796,9 +804,9 @@ nouveau_hw_load_state_palette(struct drm_device *dev, int head, void nouveau_hw_save_state(struct drm_device *dev, int head, struct nv04_mode_state *state) { - struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_drm *drm = nouveau_drm(dev); - if (dev_priv->chipset == 0x11) + if (nv_device(drm->device)->chipset == 0x11) /* NB: no attempt is made to restore the bad pll later on */ nouveau_hw_fix_bad_vpll(dev, head); nv_save_state_ramdac(dev, head, state); diff --git a/drivers/gpu/drm/nouveau/nouveau_hw.h b/drivers/gpu/drm/nouveau/nouveau_hw.h index b1c22b788be8..ba8fc0f9e0db 100644 --- a/drivers/gpu/drm/nouveau/nouveau_hw.h +++ b/drivers/gpu/drm/nouveau/nouveau_hw.h @@ -24,7 +24,6 @@ #define __NOUVEAU_HW_H__ #include "drmP.h" -#include "nouveau_drv.h" #include "nv04_display.h" #include @@ -60,37 +59,41 @@ extern void nouveau_calc_arb(struct drm_device *, int vclk, int bpp, static inline uint32_t NVReadCRTC(struct drm_device *dev, int head, uint32_t reg) { + struct nouveau_device *device = nouveau_dev(dev); uint32_t val; if (head) reg += NV_PCRTC0_SIZE; - val = nv_rd32(dev, reg); + val = nv_rd32(device, reg); return val; } static inline void NVWriteCRTC(struct drm_device *dev, int head, uint32_t reg, uint32_t val) { + struct nouveau_device *device = nouveau_dev(dev); if (head) reg += NV_PCRTC0_SIZE; - nv_wr32(dev, reg, val); + nv_wr32(device, reg, val); } static inline uint32_t NVReadRAMDAC(struct drm_device *dev, int head, uint32_t reg) { + struct nouveau_device *device = nouveau_dev(dev); uint32_t val; if (head) reg += NV_PRAMDAC0_SIZE; - val = nv_rd32(dev, reg); + val = nv_rd32(device, reg); return val; } static inline void NVWriteRAMDAC(struct drm_device *dev, int head, uint32_t reg, uint32_t val) { + struct nouveau_device *device = nouveau_dev(dev); if (head) reg += NV_PRAMDAC0_SIZE; - nv_wr32(dev, reg, val); + nv_wr32(device, reg, val); } static inline uint8_t nv_read_tmds(struct drm_device *dev, @@ -116,16 +119,18 @@ static inline void nv_write_tmds(struct drm_device *dev, static inline void NVWriteVgaCrtc(struct drm_device *dev, int head, uint8_t index, uint8_t value) { - nv_wr08(dev, NV_PRMCIO_CRX__COLOR + head * NV_PRMCIO_SIZE, index); - nv_wr08(dev, NV_PRMCIO_CR__COLOR + head * NV_PRMCIO_SIZE, value); + struct nouveau_device *device = nouveau_dev(dev); + nv_wr08(device, NV_PRMCIO_CRX__COLOR + head * NV_PRMCIO_SIZE, index); + nv_wr08(device, NV_PRMCIO_CR__COLOR + head * NV_PRMCIO_SIZE, value); } static inline uint8_t NVReadVgaCrtc(struct drm_device *dev, int head, uint8_t index) { + struct nouveau_device *device = nouveau_dev(dev); uint8_t val; - nv_wr08(dev, NV_PRMCIO_CRX__COLOR + head * NV_PRMCIO_SIZE, index); - val = nv_rd08(dev, NV_PRMCIO_CR__COLOR + head * NV_PRMCIO_SIZE); + nv_wr08(device, NV_PRMCIO_CRX__COLOR + head * NV_PRMCIO_SIZE, index); + val = nv_rd08(device, NV_PRMCIO_CR__COLOR + head * NV_PRMCIO_SIZE); return val; } @@ -159,68 +164,74 @@ static inline uint8_t NVReadVgaCrtc5758(struct drm_device *dev, int head, uint8_ static inline uint8_t NVReadPRMVIO(struct drm_device *dev, int head, uint32_t reg) { - struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_device *device = nouveau_dev(dev); + struct nouveau_drm *drm = nouveau_drm(dev); uint8_t val; /* Only NV4x have two pvio ranges; other twoHeads cards MUST call * NVSetOwner for the relevant head to be programmed */ - if (head && dev_priv->card_type == NV_40) + if (head && nv_device(drm->device)->card_type == NV_40) reg += NV_PRMVIO_SIZE; - val = nv_rd08(dev, reg); + val = nv_rd08(device, reg); return val; } static inline void NVWritePRMVIO(struct drm_device *dev, int head, uint32_t reg, uint8_t value) { - struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_device *device = nouveau_dev(dev); + struct nouveau_drm *drm = nouveau_drm(dev); /* Only NV4x have two pvio ranges; other twoHeads cards MUST call * NVSetOwner for the relevant head to be programmed */ - if (head && dev_priv->card_type == NV_40) + if (head && nv_device(drm->device)->card_type == NV_40) reg += NV_PRMVIO_SIZE; - nv_wr08(dev, reg, value); + nv_wr08(device, reg, value); } static inline void NVSetEnablePalette(struct drm_device *dev, int head, bool enable) { - nv_rd08(dev, NV_PRMCIO_INP0__COLOR + head * NV_PRMCIO_SIZE); - nv_wr08(dev, NV_PRMCIO_ARX + head * NV_PRMCIO_SIZE, enable ? 0 : 0x20); + struct nouveau_device *device = nouveau_dev(dev); + nv_rd08(device, NV_PRMCIO_INP0__COLOR + head * NV_PRMCIO_SIZE); + nv_wr08(device, NV_PRMCIO_ARX + head * NV_PRMCIO_SIZE, enable ? 0 : 0x20); } static inline bool NVGetEnablePalette(struct drm_device *dev, int head) { - nv_rd08(dev, NV_PRMCIO_INP0__COLOR + head * NV_PRMCIO_SIZE); - return !(nv_rd08(dev, NV_PRMCIO_ARX + head * NV_PRMCIO_SIZE) & 0x20); + struct nouveau_device *device = nouveau_dev(dev); + nv_rd08(device, NV_PRMCIO_INP0__COLOR + head * NV_PRMCIO_SIZE); + return !(nv_rd08(device, NV_PRMCIO_ARX + head * NV_PRMCIO_SIZE) & 0x20); } static inline void NVWriteVgaAttr(struct drm_device *dev, int head, uint8_t index, uint8_t value) { + struct nouveau_device *device = nouveau_dev(dev); if (NVGetEnablePalette(dev, head)) index &= ~0x20; else index |= 0x20; - nv_rd08(dev, NV_PRMCIO_INP0__COLOR + head * NV_PRMCIO_SIZE); - nv_wr08(dev, NV_PRMCIO_ARX + head * NV_PRMCIO_SIZE, index); - nv_wr08(dev, NV_PRMCIO_AR__WRITE + head * NV_PRMCIO_SIZE, value); + nv_rd08(device, NV_PRMCIO_INP0__COLOR + head * NV_PRMCIO_SIZE); + nv_wr08(device, NV_PRMCIO_ARX + head * NV_PRMCIO_SIZE, index); + nv_wr08(device, NV_PRMCIO_AR__WRITE + head * NV_PRMCIO_SIZE, value); } static inline uint8_t NVReadVgaAttr(struct drm_device *dev, int head, uint8_t index) { + struct nouveau_device *device = nouveau_dev(dev); uint8_t val; if (NVGetEnablePalette(dev, head)) index &= ~0x20; else index |= 0x20; - nv_rd08(dev, NV_PRMCIO_INP0__COLOR + head * NV_PRMCIO_SIZE); - nv_wr08(dev, NV_PRMCIO_ARX + head * NV_PRMCIO_SIZE, index); - val = nv_rd08(dev, NV_PRMCIO_AR__READ + head * NV_PRMCIO_SIZE); + nv_rd08(device, NV_PRMCIO_INP0__COLOR + head * NV_PRMCIO_SIZE); + nv_wr08(device, NV_PRMCIO_ARX + head * NV_PRMCIO_SIZE, index); + val = nv_rd08(device, NV_PRMCIO_AR__READ + head * NV_PRMCIO_SIZE); return val; } @@ -247,10 +258,11 @@ static inline void NVVgaProtect(struct drm_device *dev, int head, bool protect) static inline bool nv_heads_tied(struct drm_device *dev) { - struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_device *device = nouveau_dev(dev); + struct nouveau_drm *drm = nouveau_drm(dev); - if (dev_priv->chipset == 0x11) - return !!(nv_rd32(dev, NV_PBUS_DEBUG_1) & (1 << 28)); + if (nv_device(drm->device)->chipset == 0x11) + return !!(nv_rd32(device, NV_PBUS_DEBUG_1) & (1 << 28)); return NVReadVgaCrtc(dev, 0, NV_CIO_CRE_44) & 0x4; } @@ -299,13 +311,13 @@ nv_lock_vga_crtc_shadow(struct drm_device *dev, int head, int lock) static inline bool NVLockVgaCrtcs(struct drm_device *dev, bool lock) { - struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_drm *drm = nouveau_drm(dev); bool waslocked = !NVReadVgaCrtc(dev, 0, NV_CIO_SR_LOCK_INDEX); NVWriteVgaCrtc(dev, 0, NV_CIO_SR_LOCK_INDEX, lock ? NV_CIO_SR_LOCK_VALUE : NV_CIO_SR_UNLOCK_RW_VALUE); /* NV11 has independently lockable extended crtcs, except when tied */ - if (dev_priv->chipset == 0x11 && !nv_heads_tied(dev)) + if (nv_device(drm->device)->chipset == 0x11 && !nv_heads_tied(dev)) NVWriteVgaCrtc(dev, 1, NV_CIO_SR_LOCK_INDEX, lock ? NV_CIO_SR_LOCK_VALUE : NV_CIO_SR_UNLOCK_RW_VALUE); @@ -320,9 +332,9 @@ NVLockVgaCrtcs(struct drm_device *dev, bool lock) static inline int nv_cursor_width(struct drm_device *dev) { - struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_drm *drm = nouveau_drm(dev); - return dev_priv->card_type >= NV_10 ? NV10_CURSOR_SIZE : NV04_CURSOR_SIZE; + return nv_device(drm->device)->card_type >= NV_10 ? NV10_CURSOR_SIZE : NV04_CURSOR_SIZE; } static inline void @@ -340,11 +352,11 @@ nv_fix_nv40_hw_cursor(struct drm_device *dev, int head) static inline void nv_set_crtc_base(struct drm_device *dev, int head, uint32_t offset) { - struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_drm *drm = nouveau_drm(dev); NVWriteCRTC(dev, head, NV_PCRTC_START, offset); - if (dev_priv->card_type == NV_04) { + if (nv_device(drm->device)->card_type == NV_04) { /* * Hilarious, the 24th bit doesn't want to stick to * PCRTC_START... @@ -359,7 +371,7 @@ nv_set_crtc_base(struct drm_device *dev, int head, uint32_t offset) static inline void nv_show_cursor(struct drm_device *dev, int head, bool show) { - struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_drm *drm = nouveau_drm(dev); uint8_t *curctl1 = &nv04_display(dev)->mode_reg.crtc_reg[head].CRTC[NV_CIO_CRE_HCUR_ADDR1_INDEX]; @@ -369,14 +381,14 @@ nv_show_cursor(struct drm_device *dev, int head, bool show) *curctl1 &= ~MASK(NV_CIO_CRE_HCUR_ADDR1_ENABLE); NVWriteVgaCrtc(dev, head, NV_CIO_CRE_HCUR_ADDR1_INDEX, *curctl1); - if (dev_priv->card_type == NV_40) + if (nv_device(drm->device)->card_type == NV_40) nv_fix_nv40_hw_cursor(dev, head); } static inline uint32_t nv_pitch_align(struct drm_device *dev, uint32_t width, int bpp) { - struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_drm *drm = nouveau_drm(dev); int mask; if (bpp == 15) @@ -385,7 +397,7 @@ nv_pitch_align(struct drm_device *dev, uint32_t width, int bpp) bpp = 8; /* Alignment requirements taken from the Haiku driver */ - if (dev_priv->card_type == NV_04) + if (nv_device(drm->device)->card_type == NV_04) mask = 128 / bpp - 1; else mask = 512 / bpp - 1; diff --git a/drivers/gpu/drm/nouveau/nouveau_irq.c b/drivers/gpu/drm/nouveau/nouveau_irq.c index d5281499744b..af0cfe81da69 100644 --- a/drivers/gpu/drm/nouveau/nouveau_irq.c +++ b/drivers/gpu/drm/nouveau/nouveau_irq.c @@ -1,145 +1,85 @@ /* - * Copyright (C) 2006 Ben Skeggs. + * Copyright 2012 Red Hat Inc. * - * All Rights Reserved. + * 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: * - * 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 above copyright notice and this permission notice (including the - * next paragraph) 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 OWNER(S) AND/OR ITS SUPPLIERS 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. + * 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 */ -/* - * Authors: - * Ben Skeggs - */ +#include -#include "drmP.h" -#include "drm.h" -#include -#include "nouveau_drv.h" -#include "nouveau_reg.h" +#include "nouveau_drm.h" +#include "nv50_display.h" void nouveau_irq_preinstall(struct drm_device *dev) { - /* Master disable */ - nv_wr32(dev, NV03_PMC_INTR_EN_0, 0); + nv_wr32(nouveau_dev(dev), 0x000140, 0x00000000); } int nouveau_irq_postinstall(struct drm_device *dev) { - struct drm_nouveau_private *dev_priv = dev->dev_private; - - /* Master enable */ - nv_wr32(dev, NV03_PMC_INTR_EN_0, NV_PMC_INTR_EN_0_MASTER_ENABLE); - if (dev_priv->msi_enabled) - nv_wr08(dev, 0x00088068, 0xff); - + nv_wr32(nouveau_dev(dev), 0x000140, 0x00000001); return 0; } void nouveau_irq_uninstall(struct drm_device *dev) { - /* Master disable */ - nv_wr32(dev, NV03_PMC_INTR_EN_0, 0); + nv_wr32(nouveau_dev(dev), 0x000140, 0x00000000); } irqreturn_t nouveau_irq_handler(DRM_IRQ_ARGS) { - struct drm_device *dev = (struct drm_device *)arg; - struct drm_nouveau_private *dev_priv = dev->dev_private; - unsigned long flags; + struct drm_device *dev = arg; + struct nouveau_device *device = nouveau_dev(dev); + struct nouveau_mc *pmc = nouveau_mc(device); u32 stat; - int i; - stat = nv_rd32(dev, NV03_PMC_INTR_0); + stat = nv_rd32(device, 0x000100); if (stat == 0 || stat == ~0) return IRQ_NONE; - spin_lock_irqsave(&dev_priv->context_switch_lock, flags); - for (i = 0; i < 32 && stat; i++) { - if (!(stat & (1 << i)) || !dev_priv->irq_handler[i]) - continue; + nv_subdev(pmc)->intr(nv_subdev(pmc)); - dev_priv->irq_handler[i](dev); - stat &= ~(1 << i); + if (device->card_type >= NV_D0) { + if (nv_rd32(device, 0x000100) & 0x04000000) + nvd0_display_intr(dev); + } else + if (device->card_type >= NV_50) { + if (nv_rd32(device, 0x000100) & 0x04000000) + nv50_display_intr(dev); } - nv_intr(dev); - - if (dev_priv->msi_enabled) - nv_wr08(dev, 0x00088068, 0xff); - spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags); - return IRQ_HANDLED; } int nouveau_irq_init(struct drm_device *dev) { - struct drm_nouveau_private *dev_priv = dev->dev_private; - int ret; - - if (nouveau_msi != 0 && dev_priv->card_type >= NV_50) { - ret = pci_enable_msi(dev->pdev); - if (ret == 0) { - NV_INFO(dev, "enabled MSI\n"); - dev_priv->msi_enabled = true; - } - } - return drm_irq_install(dev); } void nouveau_irq_fini(struct drm_device *dev) { - struct drm_nouveau_private *dev_priv = dev->dev_private; - drm_irq_uninstall(dev); - if (dev_priv->msi_enabled) - pci_disable_msi(dev->pdev); -} - -void -nouveau_irq_register(struct drm_device *dev, int status_bit, - void (*handler)(struct drm_device *)) -{ - struct drm_nouveau_private *dev_priv = dev->dev_private; - unsigned long flags; - - spin_lock_irqsave(&dev_priv->context_switch_lock, flags); - dev_priv->irq_handler[status_bit] = handler; - spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags); -} - -void -nouveau_irq_unregister(struct drm_device *dev, int status_bit) -{ - struct drm_nouveau_private *dev_priv = dev->dev_private; - unsigned long flags; - - spin_lock_irqsave(&dev_priv->context_switch_lock, flags); - dev_priv->irq_handler[status_bit] = NULL; - spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags); } diff --git a/drivers/gpu/drm/nouveau/nouveau_irq.h b/drivers/gpu/drm/nouveau/nouveau_irq.h new file mode 100644 index 000000000000..06714ad857bb --- /dev/null +++ b/drivers/gpu/drm/nouveau/nouveau_irq.h @@ -0,0 +1,11 @@ +#ifndef __NOUVEAU_IRQ_H__ +#define __NOUVEAU_IRQ_H__ + +extern int nouveau_irq_init(struct drm_device *); +extern void nouveau_irq_fini(struct drm_device *); +extern irqreturn_t nouveau_irq_handler(DRM_IRQ_ARGS); +extern void nouveau_irq_preinstall(struct drm_device *); +extern int nouveau_irq_postinstall(struct drm_device *); +extern void nouveau_irq_uninstall(struct drm_device *); + +#endif diff --git a/drivers/gpu/drm/nouveau/nouveau_mem.c b/drivers/gpu/drm/nouveau/nouveau_mem.c index 220c1a877ff5..8f8f421367bc 100644 --- a/drivers/gpu/drm/nouveau/nouveau_mem.c +++ b/drivers/gpu/drm/nouveau/nouveau_mem.c @@ -30,20 +30,19 @@ * Roy Spliet */ - -#include "drmP.h" -#include "drm.h" -#include "drm_sarea.h" - -#include "nouveau_drv.h" +#include "nouveau_drm.h" #include "nouveau_pm.h" +#include + static int nv40_mem_timing_calc(struct drm_device *dev, u32 freq, struct nouveau_pm_tbl_entry *e, u8 len, struct nouveau_pm_memtiming *boot, struct nouveau_pm_memtiming *t) { + struct nouveau_drm *drm = nouveau_drm(dev); + t->reg[0] = (e->tRP << 24 | e->tRAS << 16 | e->tRFC << 8 | e->tRC); /* XXX: I don't trust the -1's and +1's... they must come @@ -59,7 +58,7 @@ nv40_mem_timing_calc(struct drm_device *dev, u32 freq, e->tRCDWR << 8 | e->tRCDRD); - NV_DEBUG(dev, "Entry %d: 220: %08x %08x %08x\n", t->id, + NV_DEBUG(drm, "Entry %d: 220: %08x %08x %08x\n", t->id, t->reg[0], t->reg[1], t->reg[2]); return 0; } @@ -70,6 +69,9 @@ nv50_mem_timing_calc(struct drm_device *dev, u32 freq, struct nouveau_pm_memtiming *boot, struct nouveau_pm_memtiming *t) { + struct nouveau_device *device = nouveau_dev(dev); + struct nouveau_fb *pfb = nouveau_fb(device); + struct nouveau_drm *drm = nouveau_drm(dev); struct bit_entry P; uint8_t unk18 = 1, unk20 = 0, unk21 = 0, tmp7_3; @@ -123,7 +125,7 @@ nv50_mem_timing_calc(struct drm_device *dev, u32 freq, t->reg[7] = 0x4000202 | (e->tCL - 1) << 16; /* XXX: P.version == 1 only has DDR2 and GDDR3? */ - if (nvfb_vram_type(dev) == NV_MEM_TYPE_DDR2) { + if (pfb->ram.type == NV_MEM_TYPE_DDR2) { t->reg[5] |= (e->tCL + 3) << 8; t->reg[6] |= (t->tCWL - 2) << 8; t->reg[8] |= (e->tCL - 4); @@ -156,11 +158,11 @@ nv50_mem_timing_calc(struct drm_device *dev, u32 freq, 0x202; } - NV_DEBUG(dev, "Entry %d: 220: %08x %08x %08x %08x\n", t->id, + NV_DEBUG(drm, "Entry %d: 220: %08x %08x %08x %08x\n", t->id, t->reg[0], t->reg[1], t->reg[2], t->reg[3]); - NV_DEBUG(dev, " 230: %08x %08x %08x %08x\n", + NV_DEBUG(drm, " 230: %08x %08x %08x %08x\n", t->reg[4], t->reg[5], t->reg[6], t->reg[7]); - NV_DEBUG(dev, " 240: %08x\n", t->reg[8]); + NV_DEBUG(drm, " 240: %08x\n", t->reg[8]); return 0; } @@ -170,6 +172,8 @@ nvc0_mem_timing_calc(struct drm_device *dev, u32 freq, struct nouveau_pm_memtiming *boot, struct nouveau_pm_memtiming *t) { + struct nouveau_drm *drm = nouveau_drm(dev); + if (e->tCWL > 0) t->tCWL = e->tCWL; @@ -192,9 +196,9 @@ nvc0_mem_timing_calc(struct drm_device *dev, u32 freq, t->reg[4] = (boot->reg[4] & 0xfff00fff) | (e->tRRD&0x1f) << 15; - NV_DEBUG(dev, "Entry %d: 290: %08x %08x %08x %08x\n", t->id, + NV_DEBUG(drm, "Entry %d: 290: %08x %08x %08x %08x\n", t->id, t->reg[0], t->reg[1], t->reg[2], t->reg[3]); - NV_DEBUG(dev, " 2a0: %08x\n", t->reg[4]); + NV_DEBUG(drm, " 2a0: %08x\n", t->reg[4]); return 0; } @@ -208,6 +212,8 @@ nouveau_mem_ddr2_mr(struct drm_device *dev, u32 freq, struct nouveau_pm_memtiming *boot, struct nouveau_pm_memtiming *t) { + struct nouveau_drm *drm = nouveau_drm(dev); + t->drive_strength = 0; if (len < 15) { t->odt = boot->odt; @@ -216,17 +222,17 @@ nouveau_mem_ddr2_mr(struct drm_device *dev, u32 freq, } if (e->tCL >= NV_MEM_CL_DDR2_MAX) { - NV_WARN(dev, "(%u) Invalid tCL: %u", t->id, e->tCL); + NV_WARN(drm, "(%u) Invalid tCL: %u", t->id, e->tCL); return -ERANGE; } if (e->tWR >= NV_MEM_WR_DDR2_MAX) { - NV_WARN(dev, "(%u) Invalid tWR: %u", t->id, e->tWR); + NV_WARN(drm, "(%u) Invalid tWR: %u", t->id, e->tWR); return -ERANGE; } if (t->odt > 3) { - NV_WARN(dev, "(%u) Invalid odt value, assuming disabled: %x", + NV_WARN(drm, "(%u) Invalid odt value, assuming disabled: %x", t->id, t->odt); t->odt = 0; } @@ -238,7 +244,7 @@ nouveau_mem_ddr2_mr(struct drm_device *dev, u32 freq, (t->odt & 0x1) << 2 | (t->odt & 0x2) << 5; - NV_DEBUG(dev, "(%u) MR: %08x", t->id, t->mr[0]); + NV_DEBUG(drm, "(%u) MR: %08x", t->id, t->mr[0]); return 0; } @@ -251,6 +257,7 @@ nouveau_mem_ddr3_mr(struct drm_device *dev, u32 freq, struct nouveau_pm_memtiming *boot, struct nouveau_pm_memtiming *t) { + struct nouveau_drm *drm = nouveau_drm(dev); u8 cl = e->tCL - 4; t->drive_strength = 0; @@ -261,17 +268,17 @@ nouveau_mem_ddr3_mr(struct drm_device *dev, u32 freq, } if (e->tCL >= NV_MEM_CL_DDR3_MAX || e->tCL < 4) { - NV_WARN(dev, "(%u) Invalid tCL: %u", t->id, e->tCL); + NV_WARN(drm, "(%u) Invalid tCL: %u", t->id, e->tCL); return -ERANGE; } if (e->tWR >= NV_MEM_WR_DDR3_MAX || e->tWR < 4) { - NV_WARN(dev, "(%u) Invalid tWR: %u", t->id, e->tWR); + NV_WARN(drm, "(%u) Invalid tWR: %u", t->id, e->tWR); return -ERANGE; } if (e->tCWL < 5) { - NV_WARN(dev, "(%u) Invalid tCWL: %u", t->id, e->tCWL); + NV_WARN(drm, "(%u) Invalid tCWL: %u", t->id, e->tCWL); return -ERANGE; } @@ -286,7 +293,7 @@ nouveau_mem_ddr3_mr(struct drm_device *dev, u32 freq, (t->odt & 0x4) << 7; t->mr[2] = (boot->mr[2] & 0x20ffb7) | (e->tCWL - 5) << 3; - NV_DEBUG(dev, "(%u) MR: %08x %08x", t->id, t->mr[0], t->mr[2]); + NV_DEBUG(drm, "(%u) MR: %08x %08x", t->id, t->mr[0], t->mr[2]); return 0; } @@ -301,6 +308,8 @@ nouveau_mem_gddr3_mr(struct drm_device *dev, u32 freq, struct nouveau_pm_memtiming *boot, struct nouveau_pm_memtiming *t) { + struct nouveau_drm *drm = nouveau_drm(dev); + if (len < 15) { t->drive_strength = boot->drive_strength; t->odt = boot->odt; @@ -310,17 +319,17 @@ nouveau_mem_gddr3_mr(struct drm_device *dev, u32 freq, } if (e->tCL >= NV_MEM_CL_GDDR3_MAX) { - NV_WARN(dev, "(%u) Invalid tCL: %u", t->id, e->tCL); + NV_WARN(drm, "(%u) Invalid tCL: %u", t->id, e->tCL); return -ERANGE; } if (e->tWR >= NV_MEM_WR_GDDR3_MAX) { - NV_WARN(dev, "(%u) Invalid tWR: %u", t->id, e->tWR); + NV_WARN(drm, "(%u) Invalid tWR: %u", t->id, e->tWR); return -ERANGE; } if (t->odt > 3) { - NV_WARN(dev, "(%u) Invalid odt value, assuming autocal: %x", + NV_WARN(drm, "(%u) Invalid odt value, assuming autocal: %x", t->id, t->odt); t->odt = 0; } @@ -334,7 +343,7 @@ nouveau_mem_gddr3_mr(struct drm_device *dev, u32 freq, (nv_mem_wr_lut_gddr3[e->tWR] & 0xf) << 4; t->mr[2] = boot->mr[2]; - NV_DEBUG(dev, "(%u) MR: %08x %08x %08x", t->id, + NV_DEBUG(drm, "(%u) MR: %08x %08x %08x", t->id, t->mr[0], t->mr[1], t->mr[2]); return 0; } @@ -345,6 +354,8 @@ nouveau_mem_gddr5_mr(struct drm_device *dev, u32 freq, struct nouveau_pm_memtiming *boot, struct nouveau_pm_memtiming *t) { + struct nouveau_drm *drm = nouveau_drm(dev); + if (len < 15) { t->drive_strength = boot->drive_strength; t->odt = boot->odt; @@ -354,17 +365,17 @@ nouveau_mem_gddr5_mr(struct drm_device *dev, u32 freq, } if (e->tCL >= NV_MEM_CL_GDDR5_MAX) { - NV_WARN(dev, "(%u) Invalid tCL: %u", t->id, e->tCL); + NV_WARN(drm, "(%u) Invalid tCL: %u", t->id, e->tCL); return -ERANGE; } if (e->tWR >= NV_MEM_WR_GDDR5_MAX) { - NV_WARN(dev, "(%u) Invalid tWR: %u", t->id, e->tWR); + NV_WARN(drm, "(%u) Invalid tWR: %u", t->id, e->tWR); return -ERANGE; } if (t->odt > 3) { - NV_WARN(dev, "(%u) Invalid odt value, assuming autocal: %x", + NV_WARN(drm, "(%u) Invalid odt value, assuming autocal: %x", t->id, t->odt); t->odt = 0; } @@ -376,7 +387,7 @@ nouveau_mem_gddr5_mr(struct drm_device *dev, u32 freq, t->drive_strength | (t->odt << 2); - NV_DEBUG(dev, "(%u) MR: %08x %08x", t->id, t->mr[0], t->mr[1]); + NV_DEBUG(drm, "(%u) MR: %08x %08x", t->id, t->mr[0], t->mr[1]); return 0; } @@ -384,8 +395,9 @@ int nouveau_mem_timing_calc(struct drm_device *dev, u32 freq, struct nouveau_pm_memtiming *t) { - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_pm_engine *pm = &dev_priv->engine.pm; + struct nouveau_device *device = nouveau_dev(dev); + struct nouveau_fb *pfb = nouveau_fb(device); + struct nouveau_pm *pm = nouveau_pm(dev); struct nouveau_pm_memtiming *boot = &pm->boot.timing; struct nouveau_pm_tbl_entry *e; u8 ver, len, *ptr, *ramcfg; @@ -400,7 +412,7 @@ nouveau_mem_timing_calc(struct drm_device *dev, u32 freq, t->tCWL = boot->tCWL; - switch (dev_priv->card_type) { + switch (device->card_type) { case NV_40: ret = nv40_mem_timing_calc(dev, freq, e, len, boot, t); break; @@ -416,7 +428,7 @@ nouveau_mem_timing_calc(struct drm_device *dev, u32 freq, break; } - switch (nvfb_vram_type(dev) * !ret) { + switch (pfb->ram.type * !ret) { case NV_MEM_TYPE_GDDR3: ret = nouveau_mem_gddr3_mr(dev, freq, e, len, boot, t); break; @@ -443,7 +455,7 @@ nouveau_mem_timing_calc(struct drm_device *dev, u32 freq, else dll_off = !!(ramcfg[2] & 0x40); - switch (nvfb_vram_type(dev)) { + switch (pfb->ram.type) { case NV_MEM_TYPE_GDDR3: t->mr[1] &= ~0x00000040; t->mr[1] |= 0x00000040 * dll_off; @@ -461,11 +473,12 @@ nouveau_mem_timing_calc(struct drm_device *dev, u32 freq, void nouveau_mem_timing_read(struct drm_device *dev, struct nouveau_pm_memtiming *t) { - struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_device *device = nouveau_dev(dev); + struct nouveau_fb *pfb = nouveau_fb(device); u32 timing_base, timing_regs, mr_base; int i; - if (dev_priv->card_type >= 0xC0) { + if (device->card_type >= 0xC0) { timing_base = 0x10f290; mr_base = 0x10f300; } else { @@ -475,7 +488,7 @@ nouveau_mem_timing_read(struct drm_device *dev, struct nouveau_pm_memtiming *t) t->id = -1; - switch (dev_priv->card_type) { + switch (device->card_type) { case NV_50: timing_regs = 9; break; @@ -492,24 +505,24 @@ nouveau_mem_timing_read(struct drm_device *dev, struct nouveau_pm_memtiming *t) return; } for(i = 0; i < timing_regs; i++) - t->reg[i] = nv_rd32(dev, timing_base + (0x04 * i)); + t->reg[i] = nv_rd32(device, timing_base + (0x04 * i)); t->tCWL = 0; - if (dev_priv->card_type < NV_C0) { - t->tCWL = ((nv_rd32(dev, 0x100228) & 0x0f000000) >> 24) + 1; - } else if (dev_priv->card_type <= NV_D0) { - t->tCWL = ((nv_rd32(dev, 0x10f294) & 0x00000f80) >> 7); + if (device->card_type < NV_C0) { + t->tCWL = ((nv_rd32(device, 0x100228) & 0x0f000000) >> 24) + 1; + } else if (device->card_type <= NV_D0) { + t->tCWL = ((nv_rd32(device, 0x10f294) & 0x00000f80) >> 7); } - t->mr[0] = nv_rd32(dev, mr_base); - t->mr[1] = nv_rd32(dev, mr_base + 0x04); - t->mr[2] = nv_rd32(dev, mr_base + 0x20); - t->mr[3] = nv_rd32(dev, mr_base + 0x24); + t->mr[0] = nv_rd32(device, mr_base); + t->mr[1] = nv_rd32(device, mr_base + 0x04); + t->mr[2] = nv_rd32(device, mr_base + 0x20); + t->mr[3] = nv_rd32(device, mr_base + 0x24); t->odt = 0; t->drive_strength = 0; - switch (nvfb_vram_type(dev)) { + switch (pfb->ram.type) { case NV_MEM_TYPE_DDR3: t->odt |= (t->mr[1] & 0x200) >> 7; case NV_MEM_TYPE_DDR2: @@ -530,13 +543,15 @@ int nouveau_mem_exec(struct nouveau_mem_exec_func *exec, struct nouveau_pm_level *perflvl) { - struct drm_nouveau_private *dev_priv = exec->dev->dev_private; + struct nouveau_drm *drm = nouveau_drm(exec->dev); + struct nouveau_device *device = nouveau_dev(exec->dev); + struct nouveau_fb *pfb = nouveau_fb(device); struct nouveau_pm_memtiming *info = &perflvl->timing; u32 tMRD = 1000, tCKSRE = 0, tCKSRX = 0, tXS = 0, tDLLK = 0; u32 mr[3] = { info->mr[0], info->mr[1], info->mr[2] }; u32 mr1_dlloff; - switch (nvfb_vram_type(dev_priv->dev)) { + switch (pfb->ram.type) { case NV_MEM_TYPE_DDR2: tDLLK = 2000; mr1_dlloff = 0x00000001; @@ -552,12 +567,12 @@ nouveau_mem_exec(struct nouveau_mem_exec_func *exec, mr1_dlloff = 0x00000040; break; default: - NV_ERROR(exec->dev, "cannot reclock unsupported memtype\n"); + NV_ERROR(drm, "cannot reclock unsupported memtype\n"); return -ENODEV; } /* fetch current MRs */ - switch (nvfb_vram_type(dev_priv->dev)) { + switch (pfb->ram.type) { case NV_MEM_TYPE_GDDR3: case NV_MEM_TYPE_DDR3: mr[2] = exec->mrg(exec, 2); @@ -624,7 +639,7 @@ nouveau_mem_exec(struct nouveau_mem_exec_func *exec, exec->mrs (exec, 0, info->mr[0] | 0x00000000); exec->wait(exec, tMRD); exec->wait(exec, tDLLK); - if (nvfb_vram_type(dev_priv->dev) == NV_MEM_TYPE_GDDR3) + if (pfb->ram.type == NV_MEM_TYPE_GDDR3) exec->precharge(exec); } diff --git a/drivers/gpu/drm/nouveau/nouveau_perf.c b/drivers/gpu/drm/nouveau/nouveau_perf.c index ea6acf1c4a78..b5c6a43511d9 100644 --- a/drivers/gpu/drm/nouveau/nouveau_perf.c +++ b/drivers/gpu/drm/nouveau/nouveau_perf.c @@ -24,14 +24,15 @@ #include "drmP.h" -#include "nouveau_drv.h" +#include "nouveau_drm.h" +#include "nouveau_reg.h" #include "nouveau_pm.h" static u8 * nouveau_perf_table(struct drm_device *dev, u8 *ver) { - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nvbios *bios = &dev_priv->vbios; + struct nouveau_drm *drm = nouveau_drm(dev); + struct nvbios *bios = &drm->vbios; struct bit_entry P; if (!bit_table(dev, 'P', &P) && P.version && P.version <= 2) { @@ -87,7 +88,7 @@ u8 * nouveau_perf_rammap(struct drm_device *dev, u32 freq, u8 *ver, u8 *hdr, u8 *cnt, u8 *len) { - struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_drm *drm = nouveau_drm(dev); struct bit_entry P; u8 *perf, i = 0; @@ -114,8 +115,8 @@ nouveau_perf_rammap(struct drm_device *dev, u32 freq, return NULL; } - if (dev_priv->chipset == 0x49 || - dev_priv->chipset == 0x4b) + if (nv_device(drm->device)->chipset == 0x49 || + nv_device(drm->device)->chipset == 0x4b) freq /= 2; while ((perf = nouveau_perf_entry(dev, i++, ver, hdr, cnt, len))) { @@ -142,12 +143,13 @@ nouveau_perf_rammap(struct drm_device *dev, u32 freq, u8 * nouveau_perf_ramcfg(struct drm_device *dev, u32 freq, u8 *ver, u8 *len) { - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nvbios *bios = &dev_priv->vbios; + struct nouveau_device *device = nouveau_dev(dev); + struct nouveau_drm *drm = nouveau_drm(dev); + struct nvbios *bios = &drm->vbios; u8 strap, hdr, cnt; u8 *rammap; - strap = (nv_rd32(dev, 0x101000) & 0x0000003c) >> 2; + strap = (nv_rd32(device, 0x101000) & 0x0000003c) >> 2; if (bios->ram_restrict_tbl_ptr) strap = bios->data[bios->ram_restrict_tbl_ptr + strap]; @@ -161,8 +163,8 @@ nouveau_perf_ramcfg(struct drm_device *dev, u32 freq, u8 *ver, u8 *len) u8 * nouveau_perf_timing(struct drm_device *dev, u32 freq, u8 *ver, u8 *len) { - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nvbios *bios = &dev_priv->vbios; + struct nouveau_drm *drm = nouveau_drm(dev); + struct nvbios *bios = &drm->vbios; struct bit_entry P; u8 *perf, *timing = NULL; u8 i = 0, hdr, cnt; @@ -202,20 +204,21 @@ nouveau_perf_timing(struct drm_device *dev, u32 freq, u8 *ver, u8 *len) static void legacy_perf_init(struct drm_device *dev) { - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nvbios *bios = &dev_priv->vbios; - struct nouveau_pm_engine *pm = &dev_priv->engine.pm; + struct nouveau_device *device = nouveau_dev(dev); + struct nouveau_drm *drm = nouveau_drm(dev); + struct nvbios *bios = &drm->vbios; + struct nouveau_pm *pm = nouveau_pm(dev); char *perf, *entry, *bmp = &bios->data[bios->offset]; int headerlen, use_straps; if (bmp[5] < 0x5 || bmp[6] < 0x14) { - NV_DEBUG(dev, "BMP version too old for perf\n"); + NV_DEBUG(drm, "BMP version too old for perf\n"); return; } perf = ROMPTR(dev, bmp[0x73]); if (!perf) { - NV_DEBUG(dev, "No memclock table pointer found.\n"); + NV_DEBUG(drm, "No memclock table pointer found.\n"); return; } @@ -231,13 +234,13 @@ legacy_perf_init(struct drm_device *dev) headerlen = (use_straps ? 8 : 2); break; default: - NV_WARN(dev, "Unknown memclock table version %x.\n", perf[0]); + NV_WARN(drm, "Unknown memclock table version %x.\n", perf[0]); return; } entry = perf + headerlen; if (use_straps) - entry += (nv_rd32(dev, NV_PEXTDEV_BOOT_0) & 0x3c) >> 1; + entry += (nv_rd32(device, NV_PEXTDEV_BOOT_0) & 0x3c) >> 1; sprintf(pm->perflvl[0].name, "performance_level_0"); pm->perflvl[0].memory = ROM16(entry[0]) * 20; @@ -247,7 +250,7 @@ legacy_perf_init(struct drm_device *dev) static void nouveau_perf_voltage(struct drm_device *dev, struct nouveau_pm_level *perflvl) { - struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_drm *drm = nouveau_drm(dev); struct bit_entry P; u8 *vmap; int id; @@ -258,7 +261,7 @@ nouveau_perf_voltage(struct drm_device *dev, struct nouveau_pm_level *perflvl) /* boards using voltage table version <0x40 store the voltage * level directly in the perflvl entry as a multiple of 10mV */ - if (dev_priv->engine.pm.voltage.version < 0x40) { + if (drm->pm->voltage.version < 0x40) { perflvl->volt_min = id * 10000; perflvl->volt_max = perflvl->volt_min; return; @@ -268,14 +271,14 @@ nouveau_perf_voltage(struct drm_device *dev, struct nouveau_pm_level *perflvl) * vbios table containing a min/max voltage value for the perflvl */ if (bit_table(dev, 'P', &P) || P.version != 2 || P.length < 34) { - NV_DEBUG(dev, "where's our volt map table ptr? %d %d\n", + NV_DEBUG(drm, "where's our volt map table ptr? %d %d\n", P.version, P.length); return; } vmap = ROMPTR(dev, P.data[32]); if (!vmap) { - NV_DEBUG(dev, "volt map table pointer invalid\n"); + NV_DEBUG(drm, "volt map table pointer invalid\n"); return; } @@ -289,9 +292,9 @@ nouveau_perf_voltage(struct drm_device *dev, struct nouveau_pm_level *perflvl) void nouveau_perf_init(struct drm_device *dev) { - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_pm_engine *pm = &dev_priv->engine.pm; - struct nvbios *bios = &dev_priv->vbios; + struct nouveau_drm *drm = nouveau_drm(dev); + struct nouveau_pm *pm = nouveau_pm(dev); + struct nvbios *bios = &drm->vbios; u8 *perf, ver, hdr, cnt, len; int ret, vid, i = -1; @@ -328,8 +331,8 @@ nouveau_perf_init(struct drm_device *dev) perflvl->shader = ROM16(perf[6]) * 1000; perflvl->core = perflvl->shader; perflvl->core += (signed char)perf[8] * 1000; - if (dev_priv->chipset == 0x49 || - dev_priv->chipset == 0x4b) + if (nv_device(drm->device)->chipset == 0x49 || + nv_device(drm->device)->chipset == 0x4b) perflvl->memory = ROM16(perf[11]) * 1000; else perflvl->memory = ROM16(perf[11]) * 2000; @@ -356,7 +359,7 @@ nouveau_perf_init(struct drm_device *dev) #define subent(n) ((ROM16(perf[hdr + (n) * len]) & 0xfff) * 1000) perflvl->fanspeed = 0; /*XXX*/ perflvl->volt_min = perf[2]; - if (dev_priv->card_type == NV_50) { + if (nv_device(drm->device)->card_type == NV_50) { perflvl->core = subent(0); perflvl->shader = subent(1); perflvl->memory = subent(2); @@ -382,7 +385,7 @@ nouveau_perf_init(struct drm_device *dev) if (pm->voltage.supported && perflvl->volt_min) { vid = nouveau_volt_vid_lookup(dev, perflvl->volt_min); if (vid < 0) { - NV_DEBUG(dev, "perflvl %d, bad vid\n", i); + NV_DEBUG(drm, "perflvl %d, bad vid\n", i); continue; } } @@ -391,7 +394,7 @@ nouveau_perf_init(struct drm_device *dev) ret = nouveau_mem_timing_calc(dev, perflvl->memory, &perflvl->timing); if (ret) { - NV_DEBUG(dev, "perflvl %d, bad timing: %d\n", i, ret); + NV_DEBUG(drm, "perflvl %d, bad timing: %d\n", i, ret); continue; } diff --git a/drivers/gpu/drm/nouveau/nouveau_pm.c b/drivers/gpu/drm/nouveau/nouveau_pm.c index 539e81c416cd..3c55ec2366d3 100644 --- a/drivers/gpu/drm/nouveau/nouveau_pm.c +++ b/drivers/gpu/drm/nouveau/nouveau_pm.c @@ -22,12 +22,6 @@ * Authors: Ben Skeggs */ -#include "drmP.h" - -#include "nouveau_drv.h" -#include "nouveau_pm.h" -#include - #ifdef CONFIG_ACPI #include #endif @@ -35,29 +29,48 @@ #include #include +#include "drmP.h" + +#include "nouveau_drm.h" +#include "nouveau_pm.h" + +#include +#include +#include + +MODULE_PARM_DESC(perflvl, "Performance level (default: boot)"); +static char *nouveau_perflvl; +module_param_named(perflvl, nouveau_perflvl, charp, 0400); + +MODULE_PARM_DESC(perflvl_wr, "Allow perflvl changes (warning: dangerous!)"); +static int nouveau_perflvl_wr; +module_param_named(perflvl_wr, nouveau_perflvl_wr, int, 0400); + static int nouveau_pwmfan_get(struct drm_device *dev) { - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_pm_engine *pm = &dev_priv->engine.pm; - struct dcb_gpio_func gpio; + struct nouveau_pm *pm = nouveau_pm(dev); + struct nouveau_drm *drm = nouveau_drm(dev); + struct nouveau_device *device = nv_device(drm->device); + struct nouveau_gpio *gpio = nouveau_gpio(device); + struct dcb_gpio_func func; u32 divs, duty; int ret; if (!pm->pwm_get) return -ENODEV; - ret = nouveau_gpio_find(dev, 0, DCB_GPIO_PWM_FAN, 0xff, &gpio); + ret = gpio->find(gpio, 0, DCB_GPIO_PWM_FAN, 0xff, &func); if (ret == 0) { - ret = pm->pwm_get(dev, gpio.line, &divs, &duty); + ret = pm->pwm_get(dev, func.line, &divs, &duty); if (ret == 0 && divs) { divs = max(divs, duty); - if (dev_priv->card_type <= NV_40 || (gpio.log[0] & 1)) + if (device->card_type <= NV_40 || (func.log[0] & 1)) duty = divs - duty; return (duty * 100) / divs; } - return nouveau_gpio_func_get(dev, gpio.func) * 100; + return gpio->get(gpio, 0, func.func, func.line) * 100; } return -ENODEV; @@ -66,30 +79,32 @@ nouveau_pwmfan_get(struct drm_device *dev) static int nouveau_pwmfan_set(struct drm_device *dev, int percent) { - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_pm_engine *pm = &dev_priv->engine.pm; - struct dcb_gpio_func gpio; + struct nouveau_pm *pm = nouveau_pm(dev); + struct nouveau_drm *drm = nouveau_drm(dev); + struct nouveau_device *device = nv_device(drm->device); + struct nouveau_gpio *gpio = nouveau_gpio(device); + struct dcb_gpio_func func; u32 divs, duty; int ret; if (!pm->pwm_set) return -ENODEV; - ret = nouveau_gpio_find(dev, 0, DCB_GPIO_PWM_FAN, 0xff, &gpio); + ret = gpio->find(gpio, 0, DCB_GPIO_PWM_FAN, 0xff, &func); if (ret == 0) { divs = pm->fan.pwm_divisor; if (pm->fan.pwm_freq) { /*XXX: PNVIO clock more than likely... */ divs = 135000 / pm->fan.pwm_freq; - if (dev_priv->chipset < 0xa3) + if (nv_device(drm->device)->chipset < 0xa3) divs /= 4; } duty = ((divs * percent) + 99) / 100; - if (dev_priv->card_type <= NV_40 || (gpio.log[0] & 1)) + if (device->card_type <= NV_40 || (func.log[0] & 1)) duty = divs - duty; - ret = pm->pwm_set(dev, gpio.line, divs, duty); + ret = pm->pwm_set(dev, func.line, divs, duty); if (!ret) pm->fan.percent = percent; return ret; @@ -102,8 +117,8 @@ static int nouveau_pm_perflvl_aux(struct drm_device *dev, struct nouveau_pm_level *perflvl, struct nouveau_pm_level *a, struct nouveau_pm_level *b) { - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_pm_engine *pm = &dev_priv->engine.pm; + struct nouveau_drm *drm = nouveau_drm(dev); + struct nouveau_pm *pm = nouveau_pm(dev); int ret; /*XXX: not on all boards, we should control based on temperature @@ -113,7 +128,7 @@ nouveau_pm_perflvl_aux(struct drm_device *dev, struct nouveau_pm_level *perflvl, if (a->fanspeed && b->fanspeed && b->fanspeed > a->fanspeed) { ret = nouveau_pwmfan_set(dev, perflvl->fanspeed); if (ret && ret != -ENODEV) { - NV_ERROR(dev, "fanspeed set failed: %d\n", ret); + NV_ERROR(drm, "fanspeed set failed: %d\n", ret); return ret; } } @@ -122,7 +137,7 @@ nouveau_pm_perflvl_aux(struct drm_device *dev, struct nouveau_pm_level *perflvl, if (perflvl->volt_min && b->volt_min > a->volt_min) { ret = pm->voltage_set(dev, perflvl->volt_min); if (ret) { - NV_ERROR(dev, "voltage set failed: %d\n", ret); + NV_ERROR(drm, "voltage set failed: %d\n", ret); return ret; } } @@ -134,8 +149,7 @@ nouveau_pm_perflvl_aux(struct drm_device *dev, struct nouveau_pm_level *perflvl, static int nouveau_pm_perflvl_set(struct drm_device *dev, struct nouveau_pm_level *perflvl) { - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_pm_engine *pm = &dev_priv->engine.pm; + struct nouveau_pm *pm = nouveau_pm(dev); void *state; int ret; @@ -171,8 +185,9 @@ error: void nouveau_pm_trigger(struct drm_device *dev) { - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_pm_engine *pm = &dev_priv->engine.pm; + struct nouveau_drm *drm = nouveau_drm(dev); + struct nouveau_timer *ptimer = nouveau_timer(drm->device); + struct nouveau_pm *pm = nouveau_pm(dev); struct nouveau_pm_profile *profile = NULL; struct nouveau_pm_level *perflvl = NULL; int ret; @@ -194,23 +209,22 @@ nouveau_pm_trigger(struct drm_device *dev) /* change perflvl, if necessary */ if (perflvl != pm->cur) { - u64 time0 = nv_timer_read(dev); + u64 time0 = ptimer->read(ptimer); - NV_INFO(dev, "setting performance level: %d", perflvl->id); + NV_INFO(drm, "setting performance level: %d", perflvl->id); ret = nouveau_pm_perflvl_set(dev, perflvl); if (ret) - NV_INFO(dev, "> reclocking failed: %d\n\n", ret); + NV_INFO(drm, "> reclocking failed: %d\n\n", ret); - NV_INFO(dev, "> reclocking took %lluns\n\n", - nv_timer_read(dev) - time0); + NV_INFO(drm, "> reclocking took %lluns\n\n", + ptimer->read(ptimer) - time0); } } static struct nouveau_pm_profile * profile_find(struct drm_device *dev, const char *string) { - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_pm_engine *pm = &dev_priv->engine.pm; + struct nouveau_pm *pm = nouveau_pm(dev); struct nouveau_pm_profile *profile; list_for_each_entry(profile, &pm->profiles, head) { @@ -224,8 +238,7 @@ profile_find(struct drm_device *dev, const char *string) static int nouveau_pm_profile_set(struct drm_device *dev, const char *profile) { - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_pm_engine *pm = &dev_priv->engine.pm; + struct nouveau_pm *pm = nouveau_pm(dev); struct nouveau_pm_profile *ac = NULL, *dc = NULL; char string[16], *cur = string, *ptr; @@ -278,8 +291,7 @@ const struct nouveau_pm_profile_func nouveau_pm_static_profile_func = { static int nouveau_pm_perflvl_get(struct drm_device *dev, struct nouveau_pm_level *perflvl) { - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_pm_engine *pm = &dev_priv->engine.pm; + struct nouveau_pm *pm = nouveau_pm(dev); int ret; memset(perflvl, 0, sizeof(*perflvl)); @@ -361,8 +373,7 @@ static ssize_t nouveau_pm_get_perflvl(struct device *d, struct device_attribute *a, char *buf) { struct drm_device *dev = pci_get_drvdata(to_pci_dev(d)); - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_pm_engine *pm = &dev_priv->engine.pm; + struct nouveau_pm *pm = nouveau_pm(dev); struct nouveau_pm_level cur; int len = PAGE_SIZE, ret; char *ptr = buf; @@ -397,8 +408,8 @@ static DEVICE_ATTR(performance_level, S_IRUGO | S_IWUSR, static int nouveau_sysfs_init(struct drm_device *dev) { - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_pm_engine *pm = &dev_priv->engine.pm; + struct nouveau_drm *drm = nouveau_drm(dev); + struct nouveau_pm *pm = nouveau_pm(dev); struct device *d = &dev->pdev->dev; int ret, i; @@ -417,7 +428,7 @@ nouveau_sysfs_init(struct drm_device *dev) ret = device_create_file(d, &perflvl->dev_attr); if (ret) { - NV_ERROR(dev, "failed pervlvl %d sysfs: %d\n", + NV_ERROR(drm, "failed pervlvl %d sysfs: %d\n", perflvl->id, i); perflvl->dev_attr.attr.name = NULL; nouveau_pm_fini(dev); @@ -431,8 +442,7 @@ nouveau_sysfs_init(struct drm_device *dev) static void nouveau_sysfs_fini(struct drm_device *dev) { - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_pm_engine *pm = &dev_priv->engine.pm; + struct nouveau_pm *pm = nouveau_pm(dev); struct device *d = &dev->pdev->dev; int i; @@ -452,8 +462,7 @@ static ssize_t nouveau_hwmon_show_temp(struct device *d, struct device_attribute *a, char *buf) { struct drm_device *dev = dev_get_drvdata(d); - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_pm_engine *pm = &dev_priv->engine.pm; + struct nouveau_pm *pm = nouveau_pm(dev); return snprintf(buf, PAGE_SIZE, "%d\n", pm->temp_get(dev)*1000); } @@ -464,8 +473,7 @@ static ssize_t nouveau_hwmon_max_temp(struct device *d, struct device_attribute *a, char *buf) { struct drm_device *dev = dev_get_drvdata(d); - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_pm_engine *pm = &dev_priv->engine.pm; + struct nouveau_pm *pm = nouveau_pm(dev); struct nouveau_pm_threshold_temp *temp = &pm->threshold_temp; return snprintf(buf, PAGE_SIZE, "%d\n", temp->down_clock*1000); @@ -475,8 +483,7 @@ nouveau_hwmon_set_max_temp(struct device *d, struct device_attribute *a, const char *buf, size_t count) { struct drm_device *dev = dev_get_drvdata(d); - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_pm_engine *pm = &dev_priv->engine.pm; + struct nouveau_pm *pm = nouveau_pm(dev); struct nouveau_pm_threshold_temp *temp = &pm->threshold_temp; long value; @@ -498,8 +505,7 @@ nouveau_hwmon_critical_temp(struct device *d, struct device_attribute *a, char *buf) { struct drm_device *dev = dev_get_drvdata(d); - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_pm_engine *pm = &dev_priv->engine.pm; + struct nouveau_pm *pm = nouveau_pm(dev); struct nouveau_pm_threshold_temp *temp = &pm->threshold_temp; return snprintf(buf, PAGE_SIZE, "%d\n", temp->critical*1000); @@ -510,8 +516,7 @@ nouveau_hwmon_set_critical_temp(struct device *d, struct device_attribute *a, size_t count) { struct drm_device *dev = dev_get_drvdata(d); - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_pm_engine *pm = &dev_priv->engine.pm; + struct nouveau_pm *pm = nouveau_pm(dev); struct nouveau_pm_threshold_temp *temp = &pm->threshold_temp; long value; @@ -552,28 +557,32 @@ nouveau_hwmon_show_fan0_input(struct device *d, struct device_attribute *attr, char *buf) { struct drm_device *dev = dev_get_drvdata(d); + struct nouveau_drm *drm = nouveau_drm(dev); + struct nouveau_timer *ptimer = nouveau_timer(drm->device); + struct nouveau_gpio *gpio = nouveau_gpio(drm->device); + struct dcb_gpio_func func; u32 cycles, cur, prev; u64 start; - if (!nouveau_gpio_func_valid(dev, DCB_GPIO_FAN_SENSE)) + if (gpio->find(gpio, 0, DCB_GPIO_FAN_SENSE, 0xff, &func)) return -ENODEV; /* Monitor the GPIO input 0x3b for 250ms. * When the fan spins, it changes the value of GPIO FAN_SENSE. * We get 4 changes (0 -> 1 -> 0 -> 1 -> [...]) per complete rotation. */ - start = nv_timer_read(dev); - prev = nouveau_gpio_func_get(dev, DCB_GPIO_FAN_SENSE); + start = ptimer->read(ptimer); + prev = gpio->get(gpio, 0, func.func, func.line); cycles = 0; do { - cur = nouveau_gpio_func_get(dev, DCB_GPIO_FAN_SENSE); + cur = gpio->get(gpio, 0, func.func, func.line); if (prev != cur) { cycles++; prev = cur; } usleep_range(500, 1000); /* supports 0 < rpm < 7500 */ - } while (nv_timer_read(dev) - start < 250000000); + } while (ptimer->read(ptimer) - start < 250000000); /* interpolate to get rpm */ return sprintf(buf, "%i\n", cycles / 4 * 4 * 60); @@ -599,8 +608,7 @@ nouveau_hwmon_set_pwm0(struct device *d, struct device_attribute *a, const char *buf, size_t count) { struct drm_device *dev = dev_get_drvdata(d); - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_pm_engine *pm = &dev_priv->engine.pm; + struct nouveau_pm *pm = nouveau_pm(dev); int ret = -ENODEV; long value; @@ -631,8 +639,7 @@ nouveau_hwmon_get_pwm0_min(struct device *d, struct device_attribute *a, char *buf) { struct drm_device *dev = dev_get_drvdata(d); - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_pm_engine *pm = &dev_priv->engine.pm; + struct nouveau_pm *pm = nouveau_pm(dev); return sprintf(buf, "%i\n", pm->fan.min_duty); } @@ -642,8 +649,7 @@ nouveau_hwmon_set_pwm0_min(struct device *d, struct device_attribute *a, const char *buf, size_t count) { struct drm_device *dev = dev_get_drvdata(d); - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_pm_engine *pm = &dev_priv->engine.pm; + struct nouveau_pm *pm = nouveau_pm(dev); long value; if (kstrtol(buf, 10, &value) == -EINVAL) @@ -672,8 +678,7 @@ nouveau_hwmon_get_pwm0_max(struct device *d, struct device_attribute *a, char *buf) { struct drm_device *dev = dev_get_drvdata(d); - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_pm_engine *pm = &dev_priv->engine.pm; + struct nouveau_pm *pm = nouveau_pm(dev); return sprintf(buf, "%i\n", pm->fan.max_duty); } @@ -683,8 +688,7 @@ nouveau_hwmon_set_pwm0_max(struct device *d, struct device_attribute *a, const char *buf, size_t count) { struct drm_device *dev = dev_get_drvdata(d); - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_pm_engine *pm = &dev_priv->engine.pm; + struct nouveau_pm *pm = nouveau_pm(dev); long value; if (kstrtol(buf, 10, &value) == -EINVAL) @@ -741,8 +745,11 @@ static const struct attribute_group hwmon_pwm_fan_attrgroup = { static int nouveau_hwmon_init(struct drm_device *dev) { - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_pm_engine *pm = &dev_priv->engine.pm; + struct nouveau_pm *pm = nouveau_pm(dev); + struct nouveau_drm *drm = nouveau_drm(dev); + struct nouveau_gpio *gpio = nouveau_gpio(drm->device); + struct dcb_gpio_func func; + #if defined(CONFIG_HWMON) || (defined(MODULE) && defined(CONFIG_HWMON_MODULE)) struct device *hwmon_dev; int ret = 0; @@ -753,8 +760,7 @@ nouveau_hwmon_init(struct drm_device *dev) hwmon_dev = hwmon_device_register(&dev->pdev->dev); if (IS_ERR(hwmon_dev)) { ret = PTR_ERR(hwmon_dev); - NV_ERROR(dev, - "Unable to register hwmon device: %d\n", ret); + NV_ERROR(drm, "Unable to register hwmon device: %d\n", ret); return ret; } dev_set_drvdata(hwmon_dev, dev); @@ -778,7 +784,7 @@ nouveau_hwmon_init(struct drm_device *dev) } /* if the card can read the fan rpm */ - if (nouveau_gpio_func_valid(dev, DCB_GPIO_FAN_SENSE)) { + if (!gpio->find(gpio, 0, DCB_GPIO_FAN_SENSE, 0xff, &func)) { ret = sysfs_create_group(&dev->pdev->dev.kobj, &hwmon_fan_rpm_attrgroup); if (ret) @@ -790,7 +796,7 @@ nouveau_hwmon_init(struct drm_device *dev) return 0; error: - NV_ERROR(dev, "Unable to create some hwmon sysfs files: %d\n", ret); + NV_ERROR(drm, "Unable to create some hwmon sysfs files: %d\n", ret); hwmon_device_unregister(hwmon_dev); pm->hwmon = NULL; return ret; @@ -804,8 +810,7 @@ static void nouveau_hwmon_fini(struct drm_device *dev) { #if defined(CONFIG_HWMON) || (defined(MODULE) && defined(CONFIG_HWMON_MODULE)) - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_pm_engine *pm = &dev_priv->engine.pm; + struct nouveau_pm *pm = nouveau_pm(dev); if (pm->hwmon) { sysfs_remove_group(&dev->pdev->dev.kobj, &hwmon_attrgroup); @@ -823,16 +828,15 @@ nouveau_hwmon_fini(struct drm_device *dev) static int nouveau_pm_acpi_event(struct notifier_block *nb, unsigned long val, void *data) { - struct drm_nouveau_private *dev_priv = - container_of(nb, struct drm_nouveau_private, engine.pm.acpi_nb); - struct drm_device *dev = dev_priv->dev; + struct nouveau_pm *pm = container_of(nb, struct nouveau_pm, acpi_nb); + struct nouveau_drm *drm = nouveau_drm(pm->dev); struct acpi_bus_event *entry = (struct acpi_bus_event *)data; if (strcmp(entry->device_class, "ac_adapter") == 0) { bool ac = power_supply_is_system_supplied(); - NV_DEBUG(dev, "power supply changed: %s\n", ac ? "AC" : "DC"); - nouveau_pm_trigger(dev); + NV_DEBUG(drm, "power supply changed: %s\n", ac ? "AC" : "DC"); + nouveau_pm_trigger(pm->dev); } return NOTIFY_OK; @@ -842,11 +846,72 @@ nouveau_pm_acpi_event(struct notifier_block *nb, unsigned long val, void *data) int nouveau_pm_init(struct drm_device *dev) { - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_pm_engine *pm = &dev_priv->engine.pm; + struct nouveau_device *device = nouveau_dev(dev); + struct nouveau_drm *drm = nouveau_drm(dev); + struct nouveau_pm *pm; char info[256]; int ret, i; + pm = drm->pm = kzalloc(sizeof(*pm), GFP_KERNEL); + if (!pm) + return -ENOMEM; + + pm->dev = dev; + + if (device->card_type < NV_40) { + pm->clocks_get = nv04_pm_clocks_get; + pm->clocks_pre = nv04_pm_clocks_pre; + pm->clocks_set = nv04_pm_clocks_set; + if (nouveau_gpio(drm->device)) { + pm->voltage_get = nouveau_voltage_gpio_get; + pm->voltage_set = nouveau_voltage_gpio_set; + } + } else + if (device->card_type < NV_50) { + pm->clocks_get = nv40_pm_clocks_get; + pm->clocks_pre = nv40_pm_clocks_pre; + pm->clocks_set = nv40_pm_clocks_set; + pm->voltage_get = nouveau_voltage_gpio_get; + pm->voltage_set = nouveau_voltage_gpio_set; + pm->temp_get = nv40_temp_get; + pm->pwm_get = nv40_pm_pwm_get; + pm->pwm_set = nv40_pm_pwm_set; + } else + if (device->card_type < NV_C0) { + if (device->chipset < 0xa3 || + device->chipset == 0xaa || + device->chipset == 0xac) { + pm->clocks_get = nv50_pm_clocks_get; + pm->clocks_pre = nv50_pm_clocks_pre; + pm->clocks_set = nv50_pm_clocks_set; + } else { + pm->clocks_get = nva3_pm_clocks_get; + pm->clocks_pre = nva3_pm_clocks_pre; + pm->clocks_set = nva3_pm_clocks_set; + } + pm->voltage_get = nouveau_voltage_gpio_get; + pm->voltage_set = nouveau_voltage_gpio_set; + if (device->chipset == 0x50) + pm->temp_get = nv40_temp_get; + else + pm->temp_get = nv84_temp_get; + pm->pwm_get = nv50_pm_pwm_get; + pm->pwm_set = nv50_pm_pwm_set; + } else + if (device->card_type < NV_E0) { + pm->clocks_get = nvc0_pm_clocks_get; + pm->clocks_pre = nvc0_pm_clocks_pre; + pm->clocks_set = nvc0_pm_clocks_set; + pm->voltage_get = nouveau_voltage_gpio_get; + pm->voltage_set = nouveau_voltage_gpio_set; + pm->temp_get = nv84_temp_get; + if (device->card_type < NV_D0) { + pm->pwm_get = nv50_pm_pwm_get; + pm->pwm_set = nv50_pm_pwm_set; + } + } + + /* parse aux tables from vbios */ nouveau_volt_init(dev); nouveau_temp_init(dev); @@ -854,7 +919,7 @@ nouveau_pm_init(struct drm_device *dev) /* determine current ("boot") performance level */ ret = nouveau_pm_perflvl_get(dev, &pm->boot); if (ret) { - NV_ERROR(dev, "failed to determine boot perflvl\n"); + NV_ERROR(drm, "failed to determine boot perflvl\n"); return ret; } @@ -874,14 +939,14 @@ nouveau_pm_init(struct drm_device *dev) nouveau_perf_init(dev); /* display available performance levels */ - NV_INFO(dev, "%d available performance level(s)\n", pm->nr_perflvl); + NV_INFO(drm, "%d available performance level(s)\n", pm->nr_perflvl); for (i = 0; i < pm->nr_perflvl; i++) { nouveau_pm_perflvl_info(&pm->perflvl[i], info, sizeof(info)); - NV_INFO(dev, "%d:%s", pm->perflvl[i].id, info); + NV_INFO(drm, "%d:%s", pm->perflvl[i].id, info); } nouveau_pm_perflvl_info(&pm->boot, info, sizeof(info)); - NV_INFO(dev, "c:%s", info); + NV_INFO(drm, "c:%s", info); /* switch performance levels now if requested */ if (nouveau_perflvl != NULL) @@ -903,8 +968,7 @@ nouveau_pm_init(struct drm_device *dev) void nouveau_pm_fini(struct drm_device *dev) { - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_pm_engine *pm = &dev_priv->engine.pm; + struct nouveau_pm *pm = nouveau_pm(dev); struct nouveau_pm_profile *profile, *tmp; list_for_each_entry_safe(profile, tmp, &pm->profiles, head) { @@ -924,13 +988,15 @@ nouveau_pm_fini(struct drm_device *dev) #endif nouveau_hwmon_fini(dev); nouveau_sysfs_fini(dev); + + nouveau_drm(dev)->pm = NULL; + kfree(pm); } void nouveau_pm_resume(struct drm_device *dev) { - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_pm_engine *pm = &dev_priv->engine.pm; + struct nouveau_pm *pm = nouveau_pm(dev); struct nouveau_pm_level *perflvl; if (!pm->cur || pm->cur == &pm->boot) diff --git a/drivers/gpu/drm/nouveau/nouveau_pm.h b/drivers/gpu/drm/nouveau/nouveau_pm.h index 07cac72c72b4..e2ec9c0ed567 100644 --- a/drivers/gpu/drm/nouveau/nouveau_pm.h +++ b/drivers/gpu/drm/nouveau/nouveau_pm.h @@ -25,6 +25,178 @@ #ifndef __NOUVEAU_PM_H__ #define __NOUVEAU_PM_H__ +#include +#include + +struct nouveau_pm_voltage_level { + u32 voltage; /* microvolts */ + u8 vid; +}; + +struct nouveau_pm_voltage { + bool supported; + u8 version; + u8 vid_mask; + + struct nouveau_pm_voltage_level *level; + int nr_level; +}; + +/* Exclusive upper limits */ +#define NV_MEM_CL_DDR2_MAX 8 +#define NV_MEM_WR_DDR2_MAX 9 +#define NV_MEM_CL_DDR3_MAX 17 +#define NV_MEM_WR_DDR3_MAX 17 +#define NV_MEM_CL_GDDR3_MAX 16 +#define NV_MEM_WR_GDDR3_MAX 18 +#define NV_MEM_CL_GDDR5_MAX 21 +#define NV_MEM_WR_GDDR5_MAX 20 + +struct nouveau_pm_memtiming { + int id; + + u32 reg[9]; + u32 mr[4]; + + u8 tCWL; + + u8 odt; + u8 drive_strength; +}; + +struct nouveau_pm_tbl_header { + u8 version; + u8 header_len; + u8 entry_cnt; + u8 entry_len; +}; + +struct nouveau_pm_tbl_entry { + u8 tWR; + u8 tWTR; + u8 tCL; + u8 tRC; + u8 empty_4; + u8 tRFC; /* Byte 5 */ + u8 empty_6; + u8 tRAS; /* Byte 7 */ + u8 empty_8; + u8 tRP; /* Byte 9 */ + u8 tRCDRD; + u8 tRCDWR; + u8 tRRD; + u8 tUNK_13; + u8 RAM_FT1; /* 14, a bitmask of random RAM features */ + u8 empty_15; + u8 tUNK_16; + u8 empty_17; + u8 tUNK_18; + u8 tCWL; + u8 tUNK_20, tUNK_21; +}; + +struct nouveau_pm_profile; +struct nouveau_pm_profile_func { + void (*destroy)(struct nouveau_pm_profile *); + void (*init)(struct nouveau_pm_profile *); + void (*fini)(struct nouveau_pm_profile *); + struct nouveau_pm_level *(*select)(struct nouveau_pm_profile *); +}; + +struct nouveau_pm_profile { + const struct nouveau_pm_profile_func *func; + struct list_head head; + char name[8]; +}; + +#define NOUVEAU_PM_MAX_LEVEL 8 +struct nouveau_pm_level { + struct nouveau_pm_profile profile; + struct device_attribute dev_attr; + char name[32]; + int id; + + struct nouveau_pm_memtiming timing; + u32 memory; + u16 memscript; + + u32 core; + u32 shader; + u32 rop; + u32 copy; + u32 daemon; + u32 vdec; + u32 dom6; + u32 unka0; /* nva3:nvc0 */ + u32 hub01; /* nvc0- */ + u32 hub06; /* nvc0- */ + u32 hub07; /* nvc0- */ + + u32 volt_min; /* microvolts */ + u32 volt_max; + u8 fanspeed; +}; + +struct nouveau_pm_temp_sensor_constants { + u16 offset_constant; + s16 offset_mult; + s16 offset_div; + s16 slope_mult; + s16 slope_div; +}; + +struct nouveau_pm_threshold_temp { + s16 critical; + s16 down_clock; + s16 fan_boost; +}; + +struct nouveau_pm_fan { + u32 percent; + u32 min_duty; + u32 max_duty; + u32 pwm_freq; + u32 pwm_divisor; +}; + +struct nouveau_pm { + struct drm_device *dev; + + struct nouveau_pm_voltage voltage; + struct nouveau_pm_level perflvl[NOUVEAU_PM_MAX_LEVEL]; + int nr_perflvl; + struct nouveau_pm_temp_sensor_constants sensor_constants; + struct nouveau_pm_threshold_temp threshold_temp; + struct nouveau_pm_fan fan; + + struct nouveau_pm_profile *profile_ac; + struct nouveau_pm_profile *profile_dc; + struct nouveau_pm_profile *profile; + struct list_head profiles; + + struct nouveau_pm_level boot; + struct nouveau_pm_level *cur; + + struct device *hwmon; + struct notifier_block acpi_nb; + + int (*clocks_get)(struct drm_device *, struct nouveau_pm_level *); + void *(*clocks_pre)(struct drm_device *, struct nouveau_pm_level *); + int (*clocks_set)(struct drm_device *, void *); + + int (*voltage_get)(struct drm_device *); + int (*voltage_set)(struct drm_device *, int voltage); + int (*pwm_get)(struct drm_device *, int line, u32*, u32*); + int (*pwm_set)(struct drm_device *, int line, u32, u32); + int (*temp_get)(struct drm_device *); +}; + +static inline struct nouveau_pm * +nouveau_pm(struct drm_device *dev) +{ + return nouveau_drm(dev)->pm; +} + struct nouveau_mem_exec_func { struct drm_device *dev; void (*precharge)(struct nouveau_mem_exec_func *); @@ -106,4 +278,26 @@ void nouveau_temp_safety_checks(struct drm_device *dev); int nv40_temp_get(struct drm_device *dev); int nv84_temp_get(struct drm_device *dev); +/* nouveau_mem.c */ +int nouveau_mem_timing_calc(struct drm_device *, u32 freq, + struct nouveau_pm_memtiming *); +void nouveau_mem_timing_read(struct drm_device *, + struct nouveau_pm_memtiming *); + +static inline int +nva3_calc_pll(struct drm_device *dev, struct nvbios_pll *pll, u32 freq, + int *N, int *fN, int *M, int *P) +{ + struct nouveau_device *device = nouveau_dev(dev); + struct nouveau_clock *clk = nouveau_clock(device); + struct nouveau_pll_vals pv; + int ret; + + ret = clk->pll_calc(clk, pll, freq, &pv); + *N = pv.N1; + *M = pv.M1; + *P = pv.log2P; + return ret; +} + #endif diff --git a/drivers/gpu/drm/nouveau/nouveau_prime.c b/drivers/gpu/drm/nouveau/nouveau_prime.c index de0b81fbdcc1..4ffa655545e5 100644 --- a/drivers/gpu/drm/nouveau/nouveau_prime.c +++ b/drivers/gpu/drm/nouveau/nouveau_prime.c @@ -22,13 +22,13 @@ * Authors: Dave Airlie */ +#include + #include "drmP.h" #include "drm.h" -#include "nouveau_drv.h" -#include - -#include +#include "nouveau_drm.h" +#include "nouveau_gem.h" static struct sg_table *nouveau_gem_map_dma_buf(struct dma_buf_attachment *attachment, enum dma_data_direction dir) diff --git a/drivers/gpu/drm/nouveau/nouveau_revcompat.c b/drivers/gpu/drm/nouveau/nouveau_revcompat.c deleted file mode 100644 index d5c3390503db..000000000000 --- a/drivers/gpu/drm/nouveau/nouveau_revcompat.c +++ /dev/null @@ -1,22 +0,0 @@ -#include "nouveau_revcompat.h" -#include "nouveau_drv.h" -#include "nv50_display.h" - -struct nouveau_drm * -nouveau_newpriv(struct drm_device *dev) -{ - struct drm_nouveau_private *dev_priv = dev->dev_private; - return dev_priv->newpriv; -} - -struct nouveau_bo * -nv50sema(struct drm_device *dev, int crtc) -{ - return nv50_display(dev)->crtc[crtc].sem.bo; -} - -struct nouveau_bo * -nvd0sema(struct drm_device *dev, int crtc) -{ - return nvd0_display_crtc_sema(dev, crtc); -} diff --git a/drivers/gpu/drm/nouveau/nouveau_revcompat.h b/drivers/gpu/drm/nouveau/nouveau_revcompat.h deleted file mode 100644 index 41cf61f1415f..000000000000 --- a/drivers/gpu/drm/nouveau/nouveau_revcompat.h +++ /dev/null @@ -1,12 +0,0 @@ -#ifndef __NOUVEAU_REVCOMPAT_H__ -#define __NOUVEAU_REVCOMPAT_H__ - -#include "drmP.h" - -struct nouveau_drm * -nouveau_newpriv(struct drm_device *); - -struct nouveau_bo *nv50sema(struct drm_device *dev, int crtc); -struct nouveau_bo *nvd0sema(struct drm_device *dev, int crtc); - -#endif diff --git a/drivers/gpu/drm/nouveau/nouveau_state.c b/drivers/gpu/drm/nouveau/nouveau_state.c deleted file mode 100644 index d4daba331bb8..000000000000 --- a/drivers/gpu/drm/nouveau/nouveau_state.c +++ /dev/null @@ -1,508 +0,0 @@ -/* - * Copyright 2005 Stephane Marchesin - * Copyright 2008 Stuart Bennett - * All Rights Reserved. - * - * 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 (including the next - * paragraph) 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 - * PRECISION INSIGHT AND/OR ITS SUPPLIERS 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. - */ - -#include -#include -#include "drmP.h" -#include "drm.h" -#include "drm_sarea.h" -#include "drm_crtc_helper.h" -#include -#include - -#include "nouveau_drv.h" -#include -#include "nouveau_fbcon.h" -#include "nouveau_pm.h" -#include "nv04_display.h" -#include "nv50_display.h" -#include "nouveau_acpi.h" - -static void nouveau_stub_takedown(struct drm_device *dev) {} -static int nouveau_stub_init(struct drm_device *dev) { return 0; } - -static int nouveau_init_engine_ptrs(struct drm_device *dev) -{ - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_engine *engine = &dev_priv->engine; - - switch (dev_priv->chipset & 0xf0) { - case 0x00: - engine->display.early_init = nv04_display_early_init; - engine->display.late_takedown = nv04_display_late_takedown; - engine->display.create = nv04_display_create; - engine->display.destroy = nv04_display_destroy; - engine->display.init = nv04_display_init; - engine->display.fini = nv04_display_fini; - engine->pm.clocks_get = nv04_pm_clocks_get; - engine->pm.clocks_pre = nv04_pm_clocks_pre; - engine->pm.clocks_set = nv04_pm_clocks_set; - break; - case 0x10: - engine->display.early_init = nv04_display_early_init; - engine->display.late_takedown = nv04_display_late_takedown; - engine->display.create = nv04_display_create; - engine->display.destroy = nv04_display_destroy; - engine->display.init = nv04_display_init; - engine->display.fini = nv04_display_fini; - engine->pm.clocks_get = nv04_pm_clocks_get; - engine->pm.clocks_pre = nv04_pm_clocks_pre; - engine->pm.clocks_set = nv04_pm_clocks_set; - break; - case 0x20: - engine->display.early_init = nv04_display_early_init; - engine->display.late_takedown = nv04_display_late_takedown; - engine->display.create = nv04_display_create; - engine->display.destroy = nv04_display_destroy; - engine->display.init = nv04_display_init; - engine->display.fini = nv04_display_fini; - engine->pm.clocks_get = nv04_pm_clocks_get; - engine->pm.clocks_pre = nv04_pm_clocks_pre; - engine->pm.clocks_set = nv04_pm_clocks_set; - break; - case 0x30: - engine->display.early_init = nv04_display_early_init; - engine->display.late_takedown = nv04_display_late_takedown; - engine->display.create = nv04_display_create; - engine->display.destroy = nv04_display_destroy; - engine->display.init = nv04_display_init; - engine->display.fini = nv04_display_fini; - engine->pm.clocks_get = nv04_pm_clocks_get; - engine->pm.clocks_pre = nv04_pm_clocks_pre; - engine->pm.clocks_set = nv04_pm_clocks_set; - engine->pm.voltage_get = nouveau_voltage_gpio_get; - engine->pm.voltage_set = nouveau_voltage_gpio_set; - break; - case 0x40: - case 0x60: - engine->display.early_init = nv04_display_early_init; - engine->display.late_takedown = nv04_display_late_takedown; - engine->display.create = nv04_display_create; - engine->display.destroy = nv04_display_destroy; - engine->display.init = nv04_display_init; - engine->display.fini = nv04_display_fini; - engine->pm.clocks_get = nv40_pm_clocks_get; - engine->pm.clocks_pre = nv40_pm_clocks_pre; - engine->pm.clocks_set = nv40_pm_clocks_set; - engine->pm.voltage_get = nouveau_voltage_gpio_get; - engine->pm.voltage_set = nouveau_voltage_gpio_set; - engine->pm.temp_get = nv40_temp_get; - engine->pm.pwm_get = nv40_pm_pwm_get; - engine->pm.pwm_set = nv40_pm_pwm_set; - break; - case 0x50: - case 0x80: /* gotta love NVIDIA's consistency.. */ - case 0x90: - case 0xa0: - engine->display.early_init = nv50_display_early_init; - engine->display.late_takedown = nv50_display_late_takedown; - engine->display.create = nv50_display_create; - engine->display.destroy = nv50_display_destroy; - engine->display.init = nv50_display_init; - engine->display.fini = nv50_display_fini; - switch (dev_priv->chipset) { - case 0x84: - case 0x86: - case 0x92: - case 0x94: - case 0x96: - case 0x98: - case 0xa0: - case 0xaa: - case 0xac: - case 0x50: - engine->pm.clocks_get = nv50_pm_clocks_get; - engine->pm.clocks_pre = nv50_pm_clocks_pre; - engine->pm.clocks_set = nv50_pm_clocks_set; - break; - default: - engine->pm.clocks_get = nva3_pm_clocks_get; - engine->pm.clocks_pre = nva3_pm_clocks_pre; - engine->pm.clocks_set = nva3_pm_clocks_set; - break; - } - engine->pm.voltage_get = nouveau_voltage_gpio_get; - engine->pm.voltage_set = nouveau_voltage_gpio_set; - if (dev_priv->chipset >= 0x84) - engine->pm.temp_get = nv84_temp_get; - else - engine->pm.temp_get = nv40_temp_get; - engine->pm.pwm_get = nv50_pm_pwm_get; - engine->pm.pwm_set = nv50_pm_pwm_set; - break; - case 0xc0: - engine->display.early_init = nv50_display_early_init; - engine->display.late_takedown = nv50_display_late_takedown; - engine->display.create = nv50_display_create; - engine->display.destroy = nv50_display_destroy; - engine->display.init = nv50_display_init; - engine->display.fini = nv50_display_fini; - engine->pm.temp_get = nv84_temp_get; - engine->pm.clocks_get = nvc0_pm_clocks_get; - engine->pm.clocks_pre = nvc0_pm_clocks_pre; - engine->pm.clocks_set = nvc0_pm_clocks_set; - engine->pm.voltage_get = nouveau_voltage_gpio_get; - engine->pm.voltage_set = nouveau_voltage_gpio_set; - engine->pm.pwm_get = nv50_pm_pwm_get; - engine->pm.pwm_set = nv50_pm_pwm_set; - break; - case 0xd0: - engine->display.early_init = nouveau_stub_init; - engine->display.late_takedown = nouveau_stub_takedown; - engine->display.create = nvd0_display_create; - engine->display.destroy = nvd0_display_destroy; - engine->display.init = nvd0_display_init; - engine->display.fini = nvd0_display_fini; - engine->pm.temp_get = nv84_temp_get; - engine->pm.clocks_get = nvc0_pm_clocks_get; - engine->pm.clocks_pre = nvc0_pm_clocks_pre; - engine->pm.clocks_set = nvc0_pm_clocks_set; - engine->pm.voltage_get = nouveau_voltage_gpio_get; - engine->pm.voltage_set = nouveau_voltage_gpio_set; - break; - case 0xe0: - engine->display.early_init = nouveau_stub_init; - engine->display.late_takedown = nouveau_stub_takedown; - engine->display.create = nvd0_display_create; - engine->display.destroy = nvd0_display_destroy; - engine->display.init = nvd0_display_init; - engine->display.fini = nvd0_display_fini; - break; - default: - NV_ERROR(dev, "NV%02x unsupported\n", dev_priv->chipset); - return 1; - } - - /* headless mode */ - if (nouveau_modeset == 2) { - engine->display.early_init = nouveau_stub_init; - engine->display.late_takedown = nouveau_stub_takedown; - engine->display.create = nouveau_stub_init; - engine->display.init = nouveau_stub_init; - engine->display.destroy = nouveau_stub_takedown; - } - - return 0; -} - -static unsigned int -nouveau_vga_set_decode(void *priv, bool state) -{ - struct drm_device *dev = priv; - struct drm_nouveau_private *dev_priv = dev->dev_private; - - if (dev_priv->chipset >= 0x40) - nv_wr32(dev, 0x88054, state); - else - nv_wr32(dev, 0x1854, state); - - if (state) - return VGA_RSRC_LEGACY_IO | VGA_RSRC_LEGACY_MEM | - VGA_RSRC_NORMAL_IO | VGA_RSRC_NORMAL_MEM; - else - return VGA_RSRC_NORMAL_IO | VGA_RSRC_NORMAL_MEM; -} - -static void nouveau_switcheroo_set_state(struct pci_dev *pdev, - enum vga_switcheroo_state state) -{ - struct drm_device *dev = pci_get_drvdata(pdev); - pm_message_t pmm = { .event = PM_EVENT_SUSPEND }; - if (state == VGA_SWITCHEROO_ON) { - printk(KERN_ERR "VGA switcheroo: switched nouveau on\n"); - dev->switch_power_state = DRM_SWITCH_POWER_CHANGING; - nouveau_pci_resume(pdev); - drm_kms_helper_poll_enable(dev); - dev->switch_power_state = DRM_SWITCH_POWER_ON; - } else { - printk(KERN_ERR "VGA switcheroo: switched nouveau off\n"); - dev->switch_power_state = DRM_SWITCH_POWER_CHANGING; - drm_kms_helper_poll_disable(dev); - nouveau_switcheroo_optimus_dsm(); - nouveau_pci_suspend(pdev, pmm); - dev->switch_power_state = DRM_SWITCH_POWER_OFF; - } -} - -static void nouveau_switcheroo_reprobe(struct pci_dev *pdev) -{ - struct drm_device *dev = pci_get_drvdata(pdev); - nouveau_fbcon_output_poll_changed(dev); -} - -static bool nouveau_switcheroo_can_switch(struct pci_dev *pdev) -{ - struct drm_device *dev = pci_get_drvdata(pdev); - bool can_switch; - - spin_lock(&dev->count_lock); - can_switch = (dev->open_count == 0); - spin_unlock(&dev->count_lock); - return can_switch; -} - -static const struct vga_switcheroo_client_ops nouveau_switcheroo_ops = { - .set_gpu_state = nouveau_switcheroo_set_state, - .reprobe = nouveau_switcheroo_reprobe, - .can_switch = nouveau_switcheroo_can_switch, -}; - -int -nouveau_card_init(struct drm_device *dev) -{ - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_engine *engine; - int ret; - - vga_client_register(dev->pdev, dev, NULL, nouveau_vga_set_decode); - vga_switcheroo_register_client(dev->pdev, &nouveau_switcheroo_ops); - - /* Initialise internal driver API hooks */ - ret = nouveau_init_engine_ptrs(dev); - if (ret) - goto out; - engine = &dev_priv->engine; - spin_lock_init(&dev_priv->context_switch_lock); - - /* Make the CRTCs and I2C buses accessible */ - ret = engine->display.early_init(dev); - if (ret) - goto out; - - /* Parse BIOS tables / Run init tables if card not POSTed */ - ret = nouveau_bios_init(dev); - if (ret) - goto out_display_early; - - /* workaround an odd issue on nvc1 by disabling the device's - * nosnoop capability. hopefully won't cause issues until a - * better fix is found - assuming there is one... - */ - if (dev_priv->chipset == 0xc1) { - nv_mask(dev, 0x00088080, 0x00000800, 0x00000000); - } - - ret = nouveau_irq_init(dev); - if (ret) - goto out_bios; - - ret = nouveau_display_create(dev); - if (ret) - goto out_irq; - - nouveau_backlight_init(dev); - nouveau_pm_init(dev); - - if (dev->mode_config.num_crtc) { - ret = nouveau_display_init(dev); - if (ret) - goto out_pm; - } - - return 0; - -out_pm: - nouveau_pm_fini(dev); - nouveau_backlight_exit(dev); - nouveau_display_destroy(dev); -out_irq: - nouveau_irq_fini(dev); -out_bios: - nouveau_bios_takedown(dev); -out_display_early: - engine->display.late_takedown(dev); -out: - vga_switcheroo_unregister_client(dev->pdev); - vga_client_register(dev->pdev, NULL, NULL, NULL); - return ret; -} - -static void nouveau_card_takedown(struct drm_device *dev) -{ - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_engine *engine = &dev_priv->engine; - - if (dev->mode_config.num_crtc) - nouveau_display_fini(dev); - - nouveau_pm_fini(dev); - nouveau_backlight_exit(dev); - nouveau_display_destroy(dev); - - nouveau_bios_takedown(dev); - engine->display.late_takedown(dev); - - nouveau_irq_fini(dev); - - vga_switcheroo_unregister_client(dev->pdev); - vga_client_register(dev->pdev, NULL, NULL, NULL); -} - -/* first module load, setup the mmio/fb mapping */ -/* KMS: we need mmio at load time, not when the first drm client opens. */ -int nouveau_firstopen(struct drm_device *dev) -{ - return 0; -} - -/* if we have an OF card, copy vbios to RAMIN */ -static void nouveau_OF_copy_vbios_to_ramin(struct drm_device *dev) -{ -#if defined(__powerpc__) - int size, i; - const uint32_t *bios; - struct device_node *dn = pci_device_to_OF_node(dev->pdev); - if (!dn) { - NV_INFO(dev, "Unable to get the OF node\n"); - return; - } - - bios = of_get_property(dn, "NVDA,BMP", &size); - if (bios) { - for (i = 0; i < size; i += 4) - nv_wi32(dev, i, bios[i/4]); - NV_INFO(dev, "OF bios successfully copied (%d bytes)\n", size); - } else { - NV_INFO(dev, "Unable to get the OF bios\n"); - } -#endif -} - -int nouveau_load(struct drm_device *dev, unsigned long flags) -{ - struct drm_nouveau_private *dev_priv; - uint32_t reg0 = ~0, strap; - int ret; - - dev_priv = kzalloc(sizeof(*dev_priv), GFP_KERNEL); - if (!dev_priv) { - ret = -ENOMEM; - goto err_out; - } - dev_priv->newpriv = dev->dev_private; - dev->dev_private = dev_priv; - dev_priv->dev = dev; - - NV_DEBUG(dev, "vendor: 0x%X device: 0x%X class: 0x%X\n", - dev->pci_vendor, dev->pci_device, dev->pdev->class); - - /* determine chipset and derive architecture from it */ - reg0 = nv_rd32(dev, NV03_PMC_BOOT_0); - if ((reg0 & 0x0f000000) > 0) { - dev_priv->chipset = (reg0 & 0xff00000) >> 20; - switch (dev_priv->chipset & 0xf0) { - case 0x10: - case 0x20: - case 0x30: - dev_priv->card_type = dev_priv->chipset & 0xf0; - break; - case 0x40: - case 0x60: - dev_priv->card_type = NV_40; - break; - case 0x50: - case 0x80: - case 0x90: - case 0xa0: - dev_priv->card_type = NV_50; - break; - case 0xc0: - dev_priv->card_type = NV_C0; - break; - case 0xd0: - dev_priv->card_type = NV_D0; - break; - case 0xe0: - dev_priv->card_type = NV_E0; - break; - default: - break; - } - } else - if ((reg0 & 0xff00fff0) == 0x20004000) { - if (reg0 & 0x00f00000) - dev_priv->chipset = 0x05; - else - dev_priv->chipset = 0x04; - dev_priv->card_type = NV_04; - } - - if (!dev_priv->card_type) { - NV_ERROR(dev, "unsupported chipset 0x%08x\n", reg0); - ret = -EINVAL; - goto err_priv; - } - - NV_INFO(dev, "Detected an NV%02x generation card (0x%08x)\n", - dev_priv->card_type, reg0); - - /* determine frequency of timing crystal */ - strap = nv_rd32(dev, 0x101000); - if ( dev_priv->chipset < 0x17 || - (dev_priv->chipset >= 0x20 && dev_priv->chipset <= 0x25)) - strap &= 0x00000040; - else - strap &= 0x00400040; - - switch (strap) { - case 0x00000000: dev_priv->crystal = 13500; break; - case 0x00000040: dev_priv->crystal = 14318; break; - case 0x00400000: dev_priv->crystal = 27000; break; - case 0x00400040: dev_priv->crystal = 25000; break; - } - - NV_DEBUG(dev, "crystal freq: %dKHz\n", dev_priv->crystal); - - nouveau_OF_copy_vbios_to_ramin(dev); - - /* For kernel modesetting, init card now and bring up fbcon */ - ret = nouveau_card_init(dev); - if (ret) - goto err_priv; - - return 0; - -err_priv: - dev->dev_private = dev_priv->newpriv; - kfree(dev_priv); -err_out: - return ret; -} - -void nouveau_lastclose(struct drm_device *dev) -{ - vga_switcheroo_process_delayed_switch(); -} - -int nouveau_unload(struct drm_device *dev) -{ - struct drm_nouveau_private *dev_priv = dev->dev_private; - - nouveau_card_takedown(dev); - - dev->dev_private = dev_priv->newpriv; - kfree(dev_priv); - return 0; -} diff --git a/drivers/gpu/drm/nouveau/nouveau_temp.c b/drivers/gpu/drm/nouveau/nouveau_temp.c index d00b9012a8fd..7ae25e47be9f 100644 --- a/drivers/gpu/drm/nouveau/nouveau_temp.c +++ b/drivers/gpu/drm/nouveau/nouveau_temp.c @@ -26,20 +26,22 @@ #include "drmP.h" -#include "nouveau_drv.h" +#include "nouveau_drm.h" #include "nouveau_pm.h" +#include + static void nouveau_temp_vbios_parse(struct drm_device *dev, u8 *temp) { - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_pm_engine *pm = &dev_priv->engine.pm; + struct nouveau_drm *drm = nouveau_drm(dev); + struct nouveau_pm *pm = nouveau_pm(dev); struct nouveau_pm_temp_sensor_constants *sensor = &pm->sensor_constants; struct nouveau_pm_threshold_temp *temps = &pm->threshold_temp; int i, headerlen, recordlen, entries; if (!temp) { - NV_DEBUG(dev, "temperature table pointer invalid\n"); + NV_DEBUG(drm, "temperature table pointer invalid\n"); return; } @@ -60,8 +62,8 @@ nouveau_temp_vbios_parse(struct drm_device *dev, u8 *temp) pm->fan.max_duty = 100; /* Set the known default values to setup the temperature sensor */ - if (dev_priv->card_type >= NV_40) { - switch (dev_priv->chipset) { + if (nv_device(drm->device)->card_type >= NV_40) { + switch (nv_device(drm->device)->chipset) { case 0x43: sensor->offset_mult = 32060; sensor->offset_div = 1000; @@ -185,8 +187,9 @@ nouveau_temp_vbios_parse(struct drm_device *dev, u8 *temp) static int nv40_sensor_setup(struct drm_device *dev) { - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_pm_engine *pm = &dev_priv->engine.pm; + struct nouveau_device *device = nouveau_dev(dev); + struct nouveau_drm *drm = nouveau_drm(dev); + struct nouveau_pm *pm = nouveau_pm(dev); struct nouveau_pm_temp_sensor_constants *sensor = &pm->sensor_constants; s32 offset = sensor->offset_mult / sensor->offset_div; s32 sensor_calibration; @@ -196,33 +199,34 @@ nv40_sensor_setup(struct drm_device *dev) sensor_calibration = sensor_calibration * sensor->slope_div / sensor->slope_mult; - if (dev_priv->chipset >= 0x46) + if (nv_device(drm->device)->chipset >= 0x46) sensor_calibration |= 0x80000000; else sensor_calibration |= 0x10000000; - nv_wr32(dev, 0x0015b0, sensor_calibration); + nv_wr32(device, 0x0015b0, sensor_calibration); /* Wait for the sensor to update */ msleep(5); /* read */ - return nv_rd32(dev, 0x0015b4) & 0x1fff; + return nv_rd32(device, 0x0015b4) & 0x1fff; } int nv40_temp_get(struct drm_device *dev) { - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_pm_engine *pm = &dev_priv->engine.pm; + struct nouveau_device *device = nouveau_dev(dev); + struct nouveau_drm *drm = nouveau_drm(dev); + struct nouveau_pm *pm = nouveau_pm(dev); struct nouveau_pm_temp_sensor_constants *sensor = &pm->sensor_constants; int offset = sensor->offset_mult / sensor->offset_div; int core_temp; - if (dev_priv->card_type >= NV_50) { - core_temp = nv_rd32(dev, 0x20008); + if (nv_device(drm->device)->card_type >= NV_50) { + core_temp = nv_rd32(device, 0x20008); } else { - core_temp = nv_rd32(dev, 0x0015b4) & 0x1fff; + core_temp = nv_rd32(device, 0x0015b4) & 0x1fff; /* Setup the sensor if the temperature is 0 */ if (core_temp == 0) core_temp = nv40_sensor_setup(dev); @@ -237,14 +241,14 @@ nv40_temp_get(struct drm_device *dev) int nv84_temp_get(struct drm_device *dev) { - return nv_rd32(dev, 0x20400); + struct nouveau_device *device = nouveau_dev(dev); + return nv_rd32(device, 0x20400); } void nouveau_temp_safety_checks(struct drm_device *dev) { - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_pm_engine *pm = &dev_priv->engine.pm; + struct nouveau_pm *pm = nouveau_pm(dev); struct nouveau_pm_threshold_temp *temps = &pm->threshold_temp; if (temps->critical > 120) @@ -271,7 +275,7 @@ probe_monitoring_device(struct nouveau_i2c_port *i2c, request_module("%s%s", I2C_MODULE_PREFIX, info->type); - client = i2c_new_device(nouveau_i2c_adapter(i2c), info); + client = i2c_new_device(&i2c->adapter, info); if (!client) return false; @@ -286,6 +290,8 @@ probe_monitoring_device(struct nouveau_i2c_port *i2c, static void nouveau_temp_probe_i2c(struct drm_device *dev) { + struct nouveau_device *device = nouveau_dev(dev); + struct nouveau_i2c *i2c = nouveau_i2c(device); struct i2c_board_info info[] = { { I2C_BOARD_INFO("w83l785ts", 0x2d) }, { I2C_BOARD_INFO("w83781d", 0x2d) }, @@ -295,15 +301,15 @@ nouveau_temp_probe_i2c(struct drm_device *dev) { } }; - nouveau_i2c_identify(dev, "monitoring device", info, - probe_monitoring_device, 0x80); //NV_I2C_DEFAULT(0)); + i2c->identify(i2c, NV_I2C_DEFAULT(0), "monitoring device", info, + probe_monitoring_device); } void nouveau_temp_init(struct drm_device *dev) { - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nvbios *bios = &dev_priv->vbios; + struct nouveau_drm *drm = nouveau_drm(dev); + struct nvbios *bios = &drm->vbios; struct bit_entry P; u8 *temp = NULL; @@ -316,7 +322,7 @@ nouveau_temp_init(struct drm_device *dev) else if (P.version == 2) temp = ROMPTR(dev, P.data[16]); else - NV_WARN(dev, "unknown temp for BIT P %d\n", P.version); + NV_WARN(drm, "unknown temp for BIT P %d\n", P.version); nouveau_temp_vbios_parse(dev, temp); } diff --git a/drivers/gpu/drm/nouveau/nouveau_ttm.c b/drivers/gpu/drm/nouveau/nouveau_ttm.c index 560e816138eb..030e4b84386c 100644 --- a/drivers/gpu/drm/nouveau/nouveau_ttm.c +++ b/drivers/gpu/drm/nouveau/nouveau_ttm.c @@ -265,7 +265,7 @@ int nouveau_ttm_mmap(struct file *filp, struct vm_area_struct *vma) { struct drm_file *file_priv = filp->private_data; - struct nouveau_drm *drm = nouveau_newpriv(file_priv->minor->dev); + struct nouveau_drm *drm = nouveau_drm(file_priv->minor->dev); if (unlikely(vma->vm_pgoff < DRM_FILE_PAGE_OFFSET)) return drm_mmap(filp, vma); diff --git a/drivers/gpu/drm/nouveau/nouveau_ttm.h b/drivers/gpu/drm/nouveau/nouveau_ttm.h index 9f4d2715584b..25b0de413352 100644 --- a/drivers/gpu/drm/nouveau/nouveau_ttm.h +++ b/drivers/gpu/drm/nouveau/nouveau_ttm.h @@ -17,5 +17,9 @@ struct ttm_tt *nouveau_sgdma_create_ttm(struct ttm_bo_device *, int nouveau_ttm_init(struct nouveau_drm *drm); void nouveau_ttm_fini(struct nouveau_drm *drm); +int nouveau_ttm_mmap(struct file *, struct vm_area_struct *); + +int nouveau_ttm_global_init(struct nouveau_drm *); +void nouveau_ttm_global_release(struct nouveau_drm *); #endif diff --git a/drivers/gpu/drm/nouveau/nouveau_vga.c b/drivers/gpu/drm/nouveau/nouveau_vga.c new file mode 100644 index 000000000000..9d455444f958 --- /dev/null +++ b/drivers/gpu/drm/nouveau/nouveau_vga.c @@ -0,0 +1,98 @@ +#include +#include + +#include "drmP.h" +#include "drm_crtc_helper.h" + +#include "nouveau_drm.h" +#include "nouveau_acpi.h" +#include "nouveau_fbcon.h" + +static unsigned int +nouveau_vga_set_decode(void *priv, bool state) +{ + struct nouveau_device *device = nouveau_dev(priv); + + if (device->chipset >= 0x40) + nv_wr32(device, 0x088054, state); + else + nv_wr32(device, 0x001854, state); + + if (state) + return VGA_RSRC_LEGACY_IO | VGA_RSRC_LEGACY_MEM | + VGA_RSRC_NORMAL_IO | VGA_RSRC_NORMAL_MEM; + else + return VGA_RSRC_NORMAL_IO | VGA_RSRC_NORMAL_MEM; +} + +static void +nouveau_switcheroo_set_state(struct pci_dev *pdev, + enum vga_switcheroo_state state) +{ + struct drm_device *dev = pci_get_drvdata(pdev); + pm_message_t pmm = { .event = PM_EVENT_SUSPEND }; + + if (state == VGA_SWITCHEROO_ON) { + printk(KERN_ERR "VGA switcheroo: switched nouveau on\n"); + dev->switch_power_state = DRM_SWITCH_POWER_CHANGING; + nouveau_drm_resume(pdev); + drm_kms_helper_poll_enable(dev); + dev->switch_power_state = DRM_SWITCH_POWER_ON; + } else { + printk(KERN_ERR "VGA switcheroo: switched nouveau off\n"); + dev->switch_power_state = DRM_SWITCH_POWER_CHANGING; + drm_kms_helper_poll_disable(dev); + nouveau_switcheroo_optimus_dsm(); + nouveau_drm_suspend(pdev, pmm); + dev->switch_power_state = DRM_SWITCH_POWER_OFF; + } +} + +static void +nouveau_switcheroo_reprobe(struct pci_dev *pdev) +{ + struct drm_device *dev = pci_get_drvdata(pdev); + nouveau_fbcon_output_poll_changed(dev); +} + +static bool +nouveau_switcheroo_can_switch(struct pci_dev *pdev) +{ + struct drm_device *dev = pci_get_drvdata(pdev); + bool can_switch; + + spin_lock(&dev->count_lock); + can_switch = (dev->open_count == 0); + spin_unlock(&dev->count_lock); + return can_switch; +} + +static const struct vga_switcheroo_client_ops +nouveau_switcheroo_ops = { + .set_gpu_state = nouveau_switcheroo_set_state, + .reprobe = nouveau_switcheroo_reprobe, + .can_switch = nouveau_switcheroo_can_switch, +}; + +void +nouveau_vga_init(struct nouveau_drm *drm) +{ + struct drm_device *dev = drm->dev; + vga_client_register(dev->pdev, dev, NULL, nouveau_vga_set_decode); + vga_switcheroo_register_client(dev->pdev, &nouveau_switcheroo_ops); +} + +void +nouveau_vga_fini(struct nouveau_drm *drm) +{ + struct drm_device *dev = drm->dev; + vga_switcheroo_unregister_client(dev->pdev); + vga_client_register(dev->pdev, NULL, NULL, NULL); +} + + +void +nouveau_vga_lastclose(struct drm_device *dev) +{ + vga_switcheroo_process_delayed_switch(); +} diff --git a/drivers/gpu/drm/nouveau/nouveau_vga.h b/drivers/gpu/drm/nouveau/nouveau_vga.h new file mode 100644 index 000000000000..ea3ad6974c65 --- /dev/null +++ b/drivers/gpu/drm/nouveau/nouveau_vga.h @@ -0,0 +1,8 @@ +#ifndef __NOUVEAU_VGA_H__ +#define __NOUVEAU_VGA_H__ + +void nouveau_vga_init(struct nouveau_drm *); +void nouveau_vga_fini(struct nouveau_drm *); +void nouveau_vga_lastclose(struct drm_device *dev); + +#endif diff --git a/drivers/gpu/drm/nouveau/nouveau_volt.c b/drivers/gpu/drm/nouveau/nouveau_volt.c index da3222c5a30b..c2cc8e2d6539 100644 --- a/drivers/gpu/drm/nouveau/nouveau_volt.c +++ b/drivers/gpu/drm/nouveau/nouveau_volt.c @@ -24,10 +24,11 @@ #include "drmP.h" -#include "nouveau_drv.h" +#include "nouveau_drm.h" #include "nouveau_pm.h" #include +#include static const enum dcb_gpio_func_name vidtag[] = { 0x04, 0x05, 0x06, 0x1a, 0x73 }; static int nr_vidtag = sizeof(vidtag) / sizeof(vidtag[0]); @@ -35,8 +36,9 @@ static int nr_vidtag = sizeof(vidtag) / sizeof(vidtag[0]); int nouveau_voltage_gpio_get(struct drm_device *dev) { - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_pm_voltage *volt = &dev_priv->engine.pm.voltage; + struct nouveau_pm_voltage *volt = &nouveau_pm(dev)->voltage; + struct nouveau_device *device = nouveau_dev(dev); + struct nouveau_gpio *gpio = nouveau_gpio(device); u8 vid = 0; int i; @@ -44,7 +46,7 @@ nouveau_voltage_gpio_get(struct drm_device *dev) if (!(volt->vid_mask & (1 << i))) continue; - vid |= nouveau_gpio_func_get(dev, vidtag[i]) << i; + vid |= gpio->get(gpio, 0, vidtag[i], 0xff) << i; } return nouveau_volt_lvl_lookup(dev, vid); @@ -53,8 +55,9 @@ nouveau_voltage_gpio_get(struct drm_device *dev) int nouveau_voltage_gpio_set(struct drm_device *dev, int voltage) { - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_pm_voltage *volt = &dev_priv->engine.pm.voltage; + struct nouveau_device *device = nouveau_dev(dev); + struct nouveau_gpio *gpio = nouveau_gpio(device); + struct nouveau_pm_voltage *volt = &nouveau_pm(dev)->voltage; int vid, i; vid = nouveau_volt_vid_lookup(dev, voltage); @@ -65,7 +68,7 @@ nouveau_voltage_gpio_set(struct drm_device *dev, int voltage) if (!(volt->vid_mask & (1 << i))) continue; - nouveau_gpio_func_set(dev, vidtag[i], !!(vid & (1 << i))); + gpio->set(gpio, 0, vidtag[i], 0xff, !!(vid & (1 << i))); } return 0; @@ -74,8 +77,7 @@ nouveau_voltage_gpio_set(struct drm_device *dev, int voltage) int nouveau_volt_vid_lookup(struct drm_device *dev, int voltage) { - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_pm_voltage *volt = &dev_priv->engine.pm.voltage; + struct nouveau_pm_voltage *volt = &nouveau_pm(dev)->voltage; int i; for (i = 0; i < volt->nr_level; i++) { @@ -89,8 +91,7 @@ nouveau_volt_vid_lookup(struct drm_device *dev, int voltage) int nouveau_volt_lvl_lookup(struct drm_device *dev, int vid) { - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_pm_voltage *volt = &dev_priv->engine.pm.voltage; + struct nouveau_pm_voltage *volt = &nouveau_pm(dev)->voltage; int i; for (i = 0; i < volt->nr_level; i++) { @@ -104,10 +105,12 @@ nouveau_volt_lvl_lookup(struct drm_device *dev, int vid) void nouveau_volt_init(struct drm_device *dev) { - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_pm_engine *pm = &dev_priv->engine.pm; + struct nouveau_drm *drm = nouveau_drm(dev); + struct nouveau_gpio *gpio = nouveau_gpio(drm->device); + struct nouveau_pm *pm = nouveau_pm(dev); struct nouveau_pm_voltage *voltage = &pm->voltage; - struct nvbios *bios = &dev_priv->vbios; + struct nvbios *bios = &drm->vbios; + struct dcb_gpio_func func; struct bit_entry P; u8 *volt = NULL, *entry; int i, headerlen, recordlen, entries, vidmask, vidshift; @@ -122,11 +125,11 @@ nouveau_volt_init(struct drm_device *dev) if (P.version == 2) volt = ROMPTR(dev, P.data[12]); else { - NV_WARN(dev, "unknown volt for BIT P %d\n", P.version); + NV_WARN(drm, "unknown volt for BIT P %d\n", P.version); } } else { if (bios->data[bios->offset + 6] < 0x27) { - NV_DEBUG(dev, "BMP version too old for voltage\n"); + NV_DEBUG(drm, "BMP version too old for voltage\n"); return; } @@ -134,7 +137,7 @@ nouveau_volt_init(struct drm_device *dev) } if (!volt) { - NV_DEBUG(dev, "voltage table pointer invalid\n"); + NV_DEBUG(drm, "voltage table pointer invalid\n"); return; } @@ -178,7 +181,7 @@ nouveau_volt_init(struct drm_device *dev) vidshift = 0; break; default: - NV_WARN(dev, "voltage table 0x%02x unknown\n", volt[0]); + NV_WARN(drm, "voltage table 0x%02x unknown\n", volt[0]); return; } @@ -190,12 +193,12 @@ nouveau_volt_init(struct drm_device *dev) i = 0; while (vidmask) { if (i > nr_vidtag) { - NV_DEBUG(dev, "vid bit %d unknown\n", i); + NV_DEBUG(drm, "vid bit %d unknown\n", i); return; } - if (!nouveau_gpio_func_valid(dev, vidtag[i])) { - NV_DEBUG(dev, "vid bit %d has no gpio tag\n", i); + if (gpio && gpio->find(gpio, 0, vidtag[i], 0xff, &func)) { + NV_DEBUG(drm, "vid bit %d has no gpio tag\n", i); return; } @@ -241,8 +244,7 @@ nouveau_volt_init(struct drm_device *dev) void nouveau_volt_fini(struct drm_device *dev) { - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_pm_voltage *volt = &dev_priv->engine.pm.voltage; + struct nouveau_pm_voltage *volt = &nouveau_pm(dev)->voltage; kfree(volt->level); } diff --git a/drivers/gpu/drm/nouveau/nv04_crtc.c b/drivers/gpu/drm/nouveau/nv04_crtc.c index f5d17bf954ff..8b8a9d3d9e8b 100644 --- a/drivers/gpu/drm/nouveau/nv04_crtc.c +++ b/drivers/gpu/drm/nouveau/nv04_crtc.c @@ -26,14 +26,20 @@ #include "drmP.h" #include "drm_crtc_helper.h" -#include "nouveau_drv.h" +#include "nouveau_drm.h" +#include "nouveau_reg.h" +#include "nouveau_bo.h" +#include "nouveau_gem.h" #include "nouveau_encoder.h" #include "nouveau_connector.h" #include "nouveau_crtc.h" -#include "nouveau_fb.h" #include "nouveau_hw.h" #include "nvreg.h" #include "nouveau_fbcon.h" +#include "nv04_display.h" + +#include +#include static int nv04_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y, @@ -103,14 +109,17 @@ static void nv_crtc_set_image_sharpening(struct drm_crtc *crtc, int level) static void nv_crtc_calc_state_ext(struct drm_crtc *crtc, struct drm_display_mode * mode, int dot_clock) { struct drm_device *dev = crtc->dev; - struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_drm *drm = nouveau_drm(dev); + struct nouveau_bios *bios = nouveau_bios(drm->device); + struct nouveau_clock *clk = nouveau_clock(drm->device); struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); struct nv04_mode_state *state = &nv04_display(dev)->mode_reg; struct nv04_crtc_reg *regp = &state->crtc_reg[nv_crtc->index]; struct nouveau_pll_vals *pv = ®p->pllvals; struct nvbios_pll pll_lim; - if (get_pll_limits(dev, nv_crtc->index ? PLL_VPLL1 : PLL_VPLL0, &pll_lim)) + if (nvbios_pll_parse(bios, nv_crtc->index ? PLL_VPLL1 : PLL_VPLL0, + &pll_lim)) return; /* NM2 == 0 is used to determine single stage mode on two stage plls */ @@ -126,28 +135,29 @@ static void nv_crtc_calc_state_ext(struct drm_crtc *crtc, struct drm_display_mod * has yet been observed in allowing the use a single stage pll on all * nv43 however. the behaviour of single stage use is untested on nv40 */ - if (dev_priv->chipset > 0x40 && dot_clock <= (pll_lim.vco1.max_freq / 2)) + if (nv_device(drm->device)->chipset > 0x40 && dot_clock <= (pll_lim.vco1.max_freq / 2)) memset(&pll_lim.vco2, 0, sizeof(pll_lim.vco2)); - if (!nouveau_calc_pll_mnp(dev, &pll_lim, dot_clock, pv)) + + if (!clk->pll_calc(clk, &pll_lim, dot_clock, pv)) return; state->pllsel &= PLLSEL_VPLL1_MASK | PLLSEL_VPLL2_MASK | PLLSEL_TV_MASK; /* The blob uses this always, so let's do the same */ - if (dev_priv->card_type == NV_40) + if (nv_device(drm->device)->card_type == NV_40) state->pllsel |= NV_PRAMDAC_PLL_COEFF_SELECT_USE_VPLL2_TRUE; /* again nv40 and some nv43 act more like nv3x as described above */ - if (dev_priv->chipset < 0x41) + if (nv_device(drm->device)->chipset < 0x41) state->pllsel |= NV_PRAMDAC_PLL_COEFF_SELECT_SOURCE_PROG_MPLL | NV_PRAMDAC_PLL_COEFF_SELECT_SOURCE_PROG_NVPLL; state->pllsel |= nv_crtc->index ? PLLSEL_VPLL2_MASK : PLLSEL_VPLL1_MASK; if (pv->NM2) - NV_DEBUG_KMS(dev, "vpll: n1 %d n2 %d m1 %d m2 %d log2p %d\n", + NV_DEBUG(drm, "vpll: n1 %d n2 %d m1 %d m2 %d log2p %d\n", pv->N1, pv->N2, pv->M1, pv->M2, pv->log2P); else - NV_DEBUG_KMS(dev, "vpll: n %d m %d log2p %d\n", + NV_DEBUG(drm, "vpll: n %d m %d log2p %d\n", pv->N1, pv->M1, pv->log2P); nv_crtc->cursor.set_offset(nv_crtc, nv_crtc->cursor.offset); @@ -158,10 +168,11 @@ nv_crtc_dpms(struct drm_crtc *crtc, int mode) { struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); struct drm_device *dev = crtc->dev; + struct nouveau_drm *drm = nouveau_drm(dev); unsigned char seq1 = 0, crtc17 = 0; unsigned char crtc1A; - NV_DEBUG_KMS(dev, "Setting dpms mode %d on CRTC %d\n", mode, + NV_DEBUG(drm, "Setting dpms mode %d on CRTC %d\n", mode, nv_crtc->index); if (nv_crtc->last_dpms == mode) /* Don't do unnecessary mode changes. */ @@ -263,7 +274,7 @@ nv_crtc_mode_set_vga(struct drm_crtc *crtc, struct drm_display_mode *mode) horizEnd = horizTotal - 2; horizBlankEnd = horizTotal + 4; #if 0 - if (dev->overlayAdaptor && dev_priv->card_type >= NV_10) + if (dev->overlayAdaptor && nv_device(drm->device)->card_type >= NV_10) /* This reportedly works around some video overlay bandwidth problems */ horizTotal += 2; #endif @@ -451,7 +462,7 @@ static void nv_crtc_mode_set_regs(struct drm_crtc *crtc, struct drm_display_mode * mode) { struct drm_device *dev = crtc->dev; - struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_drm *drm = nouveau_drm(dev); struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); struct nv04_crtc_reg *regp = &nv04_display(dev)->mode_reg.crtc_reg[nv_crtc->index]; struct nv04_crtc_reg *savep = &nv04_display(dev)->saved_reg.crtc_reg[nv_crtc->index]; @@ -499,7 +510,7 @@ nv_crtc_mode_set_regs(struct drm_crtc *crtc, struct drm_display_mode * mode) regp->cursor_cfg = NV_PCRTC_CURSOR_CONFIG_CUR_LINES_64 | NV_PCRTC_CURSOR_CONFIG_CUR_PIXELS_64 | NV_PCRTC_CURSOR_CONFIG_ADDRESS_SPACE_PNVM; - if (dev_priv->chipset >= 0x11) + if (nv_device(drm->device)->chipset >= 0x11) regp->cursor_cfg |= NV_PCRTC_CURSOR_CONFIG_CUR_BPP_32; if (mode->flags & DRM_MODE_FLAG_DBLSCAN) regp->cursor_cfg |= NV_PCRTC_CURSOR_CONFIG_DOUBLE_SCAN_ENABLE; @@ -540,26 +551,26 @@ nv_crtc_mode_set_regs(struct drm_crtc *crtc, struct drm_display_mode * mode) * 1 << 30 on 0x60.830), for no apparent reason */ regp->CRTC[NV_CIO_CRE_59] = off_chip_digital; - if (dev_priv->card_type >= NV_30) + if (nv_device(drm->device)->card_type >= NV_30) regp->CRTC[0x9f] = off_chip_digital ? 0x11 : 0x1; regp->crtc_830 = mode->crtc_vdisplay - 3; regp->crtc_834 = mode->crtc_vdisplay - 1; - if (dev_priv->card_type == NV_40) + if (nv_device(drm->device)->card_type == NV_40) /* This is what the blob does */ regp->crtc_850 = NVReadCRTC(dev, 0, NV_PCRTC_850); - if (dev_priv->card_type >= NV_30) + if (nv_device(drm->device)->card_type >= NV_30) regp->gpio_ext = NVReadCRTC(dev, 0, NV_PCRTC_GPIO_EXT); - if (dev_priv->card_type >= NV_10) + if (nv_device(drm->device)->card_type >= NV_10) regp->crtc_cfg = NV10_PCRTC_CONFIG_START_ADDRESS_HSYNC; else regp->crtc_cfg = NV04_PCRTC_CONFIG_START_ADDRESS_HSYNC; /* Some misc regs */ - if (dev_priv->card_type == NV_40) { + if (nv_device(drm->device)->card_type == NV_40) { regp->CRTC[NV_CIO_CRE_85] = 0xFF; regp->CRTC[NV_CIO_CRE_86] = 0x1; } @@ -571,7 +582,7 @@ nv_crtc_mode_set_regs(struct drm_crtc *crtc, struct drm_display_mode * mode) /* Generic PRAMDAC regs */ - if (dev_priv->card_type >= NV_10) + if (nv_device(drm->device)->card_type >= NV_10) /* Only bit that bios and blob set. */ regp->nv10_cursync = (1 << 25); @@ -580,7 +591,7 @@ nv_crtc_mode_set_regs(struct drm_crtc *crtc, struct drm_display_mode * mode) NV_PRAMDAC_GENERAL_CONTROL_PIXMIX_ON; if (crtc->fb->depth == 16) regp->ramdac_gen_ctrl |= NV_PRAMDAC_GENERAL_CONTROL_ALT_MODE_SEL; - if (dev_priv->chipset >= 0x11) + if (nv_device(drm->device)->chipset >= 0x11) regp->ramdac_gen_ctrl |= NV_PRAMDAC_GENERAL_CONTROL_PIPE_LONG; regp->ramdac_630 = 0; /* turn off green mode (tv test pattern?) */ @@ -610,9 +621,9 @@ nv_crtc_mode_set(struct drm_crtc *crtc, struct drm_display_mode *mode, { struct drm_device *dev = crtc->dev; struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); - struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_drm *drm = nouveau_drm(dev); - NV_DEBUG_KMS(dev, "CTRC mode on CRTC %d:\n", nv_crtc->index); + NV_DEBUG(drm, "CTRC mode on CRTC %d:\n", nv_crtc->index); drm_mode_debug_printmodeline(adjusted_mode); /* unlock must come after turning off FP_TG_CONTROL in output_prepare */ @@ -620,7 +631,7 @@ nv_crtc_mode_set(struct drm_crtc *crtc, struct drm_display_mode *mode, nv_crtc_mode_set_vga(crtc, adjusted_mode); /* calculated in nv04_dfp_prepare, nv40 needs it written before calculating PLLs */ - if (dev_priv->card_type == NV_40) + if (nv_device(drm->device)->card_type == NV_40) NVWriteRAMDAC(dev, 0, NV_PRAMDAC_SEL_CLK, nv04_display(dev)->mode_reg.sel_clk); nv_crtc_mode_set_regs(crtc, adjusted_mode); nv_crtc_calc_state_ext(crtc, mode, adjusted_mode->clock); @@ -667,7 +678,7 @@ static void nv_crtc_restore(struct drm_crtc *crtc) static void nv_crtc_prepare(struct drm_crtc *crtc) { struct drm_device *dev = crtc->dev; - struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_drm *drm = nouveau_drm(dev); struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); struct drm_crtc_helper_funcs *funcs = crtc->helper_private; @@ -681,7 +692,7 @@ static void nv_crtc_prepare(struct drm_crtc *crtc) /* Some more preparation. */ NVWriteCRTC(dev, nv_crtc->index, NV_PCRTC_CONFIG, NV_PCRTC_CONFIG_START_ADDRESS_NON_VGA); - if (dev_priv->card_type == NV_40) { + if (nv_device(drm->device)->card_type == NV_40) { uint32_t reg900 = NVReadRAMDAC(dev, nv_crtc->index, NV_PRAMDAC_900); NVWriteRAMDAC(dev, nv_crtc->index, NV_PRAMDAC_900, reg900 & ~0x10000); } @@ -713,8 +724,6 @@ static void nv_crtc_destroy(struct drm_crtc *crtc) { struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); - NV_DEBUG_KMS(crtc->dev, "\n"); - if (!nv_crtc) return; @@ -776,18 +785,18 @@ nv04_crtc_do_mode_set_base(struct drm_crtc *crtc, { struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); struct drm_device *dev = crtc->dev; - struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_drm *drm = nouveau_drm(dev); struct nv04_crtc_reg *regp = &nv04_display(dev)->mode_reg.crtc_reg[nv_crtc->index]; struct drm_framebuffer *drm_fb; struct nouveau_framebuffer *fb; int arb_burst, arb_lwm; int ret; - NV_DEBUG_KMS(dev, "index %d\n", nv_crtc->index); + NV_DEBUG(drm, "index %d\n", nv_crtc->index); /* no fb bound */ if (!atomic && !crtc->fb) { - NV_DEBUG_KMS(dev, "No FB bound\n"); + NV_DEBUG(drm, "No FB bound\n"); return 0; } @@ -855,7 +864,7 @@ nv04_crtc_do_mode_set_base(struct drm_crtc *crtc, crtc_wr_cio_state(crtc, regp, NV_CIO_CRE_FF_INDEX); crtc_wr_cio_state(crtc, regp, NV_CIO_CRE_FFLWM__INDEX); - if (dev_priv->card_type >= NV_20) { + if (nv_device(drm->device)->card_type >= NV_20) { regp->CRTC[NV_CIO_CRE_47] = arb_lwm >> 8; crtc_wr_cio_state(crtc, regp, NV_CIO_CRE_47); } @@ -875,8 +884,8 @@ nv04_crtc_mode_set_base_atomic(struct drm_crtc *crtc, struct drm_framebuffer *fb, int x, int y, enum mode_set_atomic state) { - struct drm_nouveau_private *dev_priv = crtc->dev->dev_private; - struct drm_device *dev = dev_priv->dev; + struct nouveau_drm *drm = nouveau_drm(crtc->dev); + struct drm_device *dev = drm->dev; if (state == ENTER_ATOMIC_MODE_SET) nouveau_fbcon_save_disable_accel(dev); @@ -931,9 +940,9 @@ static void nv11_cursor_upload(struct drm_device *dev, struct nouveau_bo *src, #ifdef __BIG_ENDIAN { - struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_drm *drm = nouveau_drm(dev); - if (dev_priv->chipset == 0x11) { + if (nv_device(drm->device)->chipset == 0x11) { pixel = ((pixel & 0x000000ff) << 24) | ((pixel & 0x0000ff00) << 8) | ((pixel & 0x00ff0000) >> 8) | @@ -950,8 +959,8 @@ static int nv04_crtc_cursor_set(struct drm_crtc *crtc, struct drm_file *file_priv, uint32_t buffer_handle, uint32_t width, uint32_t height) { - struct drm_nouveau_private *dev_priv = crtc->dev->dev_private; - struct drm_device *dev = dev_priv->dev; + struct nouveau_drm *drm = nouveau_drm(crtc->dev); + struct drm_device *dev = drm->dev; struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); struct nouveau_bo *cursor = NULL; struct drm_gem_object *gem; @@ -974,7 +983,7 @@ nv04_crtc_cursor_set(struct drm_crtc *crtc, struct drm_file *file_priv, if (ret) goto out; - if (dev_priv->chipset >= 0x11) + if (nv_device(drm->device)->chipset >= 0x11) nv11_cursor_upload(dev, cursor, nv_crtc->cursor.nvbo); else nv04_cursor_upload(dev, cursor, nv_crtc->cursor.nvbo); diff --git a/drivers/gpu/drm/nouveau/nv04_cursor.c b/drivers/gpu/drm/nouveau/nv04_cursor.c index 62294b8712db..d2ea8b460364 100644 --- a/drivers/gpu/drm/nouveau/nv04_cursor.c +++ b/drivers/gpu/drm/nouveau/nv04_cursor.c @@ -1,7 +1,7 @@ #include "drmP.h" #include "drm_mode.h" +#include "nouveau_drm.h" #include "nouveau_reg.h" -#include "nouveau_drv.h" #include "nouveau_crtc.h" #include "nouveau_hw.h" @@ -38,7 +38,7 @@ static void nv04_cursor_set_offset(struct nouveau_crtc *nv_crtc, uint32_t offset) { struct drm_device *dev = nv_crtc->base.dev; - struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_drm *drm = nouveau_drm(dev); struct nv04_crtc_reg *regp = &nv04_display(dev)->mode_reg.crtc_reg[nv_crtc->index]; struct drm_crtc *crtc = &nv_crtc->base; @@ -55,7 +55,7 @@ nv04_cursor_set_offset(struct nouveau_crtc *nv_crtc, uint32_t offset) crtc_wr_cio_state(crtc, regp, NV_CIO_CRE_HCUR_ADDR0_INDEX); crtc_wr_cio_state(crtc, regp, NV_CIO_CRE_HCUR_ADDR1_INDEX); crtc_wr_cio_state(crtc, regp, NV_CIO_CRE_HCUR_ADDR2_INDEX); - if (dev_priv->card_type == NV_40) + if (nv_device(drm->device)->card_type == NV_40) nv_fix_nv40_hw_cursor(dev, nv_crtc->index); } diff --git a/drivers/gpu/drm/nouveau/nv04_dac.c b/drivers/gpu/drm/nouveau/nv04_dac.c index 7ff2eb3bd340..336f953084f9 100644 --- a/drivers/gpu/drm/nouveau/nv04_dac.c +++ b/drivers/gpu/drm/nouveau/nv04_dac.c @@ -27,7 +27,7 @@ #include "drmP.h" #include "drm_crtc_helper.h" -#include "nouveau_drv.h" +#include "nouveau_drm.h" #include "nouveau_encoder.h" #include "nouveau_connector.h" #include "nouveau_crtc.h" @@ -35,6 +35,8 @@ #include "nvreg.h" #include +#include +#include int nv04_dac_output_offset(struct drm_encoder *encoder) { @@ -63,6 +65,8 @@ int nv04_dac_output_offset(struct drm_encoder *encoder) static int sample_load_twice(struct drm_device *dev, bool sense[2]) { + struct nouveau_device *device = nouveau_dev(dev); + struct nouveau_timer *ptimer = nouveau_timer(device); int i; for (i = 0; i < 2; i++) { @@ -76,27 +80,30 @@ static int sample_load_twice(struct drm_device *dev, bool sense[2]) * use a 10ms timeout (guards against crtc being inactive, in * which case blank state would never change) */ - if (!nouveau_wait_eq(dev, 10000000, NV_PRMCIO_INP0__COLOR, - 0x00000001, 0x00000000)) + if (!nouveau_timer_wait_eq(ptimer, 10000000, + NV_PRMCIO_INP0__COLOR, + 0x00000001, 0x00000000)) return -EBUSY; - if (!nouveau_wait_eq(dev, 10000000, NV_PRMCIO_INP0__COLOR, - 0x00000001, 0x00000001)) + if (!nouveau_timer_wait_eq(ptimer, 10000000, + NV_PRMCIO_INP0__COLOR, + 0x00000001, 0x00000001)) return -EBUSY; - if (!nouveau_wait_eq(dev, 10000000, NV_PRMCIO_INP0__COLOR, - 0x00000001, 0x00000000)) + if (!nouveau_timer_wait_eq(ptimer, 10000000, + NV_PRMCIO_INP0__COLOR, + 0x00000001, 0x00000000)) return -EBUSY; udelay(100); /* when level triggers, sense is _LO_ */ - sense_a = nv_rd08(dev, NV_PRMCIO_INP0) & 0x10; + sense_a = nv_rd08(device, NV_PRMCIO_INP0) & 0x10; /* take another reading until it agrees with sense_a... */ do { udelay(100); - sense_b = nv_rd08(dev, NV_PRMCIO_INP0) & 0x10; + sense_b = nv_rd08(device, NV_PRMCIO_INP0) & 0x10; if (sense_a != sense_b) { sense_b_prime = - nv_rd08(dev, NV_PRMCIO_INP0) & 0x10; + nv_rd08(device, NV_PRMCIO_INP0) & 0x10; if (sense_b == sense_b_prime) { /* ... unless two consecutive subsequent * samples agree; sense_a is replaced */ @@ -121,6 +128,8 @@ static enum drm_connector_status nv04_dac_detect(struct drm_encoder *encoder, struct drm_connector *connector) { struct drm_device *dev = encoder->dev; + struct nouveau_device *device = nouveau_dev(dev); + struct nouveau_drm *drm = nouveau_drm(dev); uint8_t saved_seq1, saved_pi, saved_rpc1, saved_cr_mode; uint8_t saved_palette0[3], saved_palette_mask; uint32_t saved_rtest_ctrl, saved_rgen_ctrl; @@ -155,11 +164,11 @@ static enum drm_connector_status nv04_dac_detect(struct drm_encoder *encoder, saved_rpc1 = NVReadVgaCrtc(dev, 0, NV_CIO_CRE_RPC1_INDEX); NVWriteVgaCrtc(dev, 0, NV_CIO_CRE_RPC1_INDEX, saved_rpc1 & ~0xc0); - nv_wr08(dev, NV_PRMDIO_READ_MODE_ADDRESS, 0x0); + nv_wr08(device, NV_PRMDIO_READ_MODE_ADDRESS, 0x0); for (i = 0; i < 3; i++) - saved_palette0[i] = nv_rd08(dev, NV_PRMDIO_PALETTE_DATA); - saved_palette_mask = nv_rd08(dev, NV_PRMDIO_PIXEL_MASK); - nv_wr08(dev, NV_PRMDIO_PIXEL_MASK, 0); + saved_palette0[i] = nv_rd08(device, NV_PRMDIO_PALETTE_DATA); + saved_palette_mask = nv_rd08(device, NV_PRMDIO_PIXEL_MASK); + nv_wr08(device, NV_PRMDIO_PIXEL_MASK, 0); saved_rgen_ctrl = NVReadRAMDAC(dev, 0, NV_PRAMDAC_GENERAL_CONTROL); NVWriteRAMDAC(dev, 0, NV_PRAMDAC_GENERAL_CONTROL, @@ -172,11 +181,11 @@ static enum drm_connector_status nv04_dac_detect(struct drm_encoder *encoder, do { bool sense_pair[2]; - nv_wr08(dev, NV_PRMDIO_WRITE_MODE_ADDRESS, 0); - nv_wr08(dev, NV_PRMDIO_PALETTE_DATA, 0); - nv_wr08(dev, NV_PRMDIO_PALETTE_DATA, 0); + nv_wr08(device, NV_PRMDIO_WRITE_MODE_ADDRESS, 0); + nv_wr08(device, NV_PRMDIO_PALETTE_DATA, 0); + nv_wr08(device, NV_PRMDIO_PALETTE_DATA, 0); /* testing blue won't find monochrome monitors. I don't care */ - nv_wr08(dev, NV_PRMDIO_PALETTE_DATA, blue); + nv_wr08(device, NV_PRMDIO_PALETTE_DATA, blue); i = 0; /* take sample pairs until both samples in the pair agree */ @@ -199,11 +208,11 @@ static enum drm_connector_status nv04_dac_detect(struct drm_encoder *encoder, } while (++blue < 0x18 && sense); out: - nv_wr08(dev, NV_PRMDIO_PIXEL_MASK, saved_palette_mask); + nv_wr08(device, NV_PRMDIO_PIXEL_MASK, saved_palette_mask); NVWriteRAMDAC(dev, 0, NV_PRAMDAC_GENERAL_CONTROL, saved_rgen_ctrl); - nv_wr08(dev, NV_PRMDIO_WRITE_MODE_ADDRESS, 0); + nv_wr08(device, NV_PRMDIO_WRITE_MODE_ADDRESS, 0); for (i = 0; i < 3; i++) - nv_wr08(dev, NV_PRMDIO_PALETTE_DATA, saved_palette0[i]); + nv_wr08(device, NV_PRMDIO_PALETTE_DATA, saved_palette0[i]); NVWriteRAMDAC(dev, 0, NV_PRAMDAC_TEST_CONTROL, saved_rtest_ctrl); NVWriteVgaCrtc(dev, 0, NV_CIO_CRE_PIXEL_INDEX, saved_pi); NVWriteVgaCrtc(dev, 0, NV_CIO_CRE_RPC1_INDEX, saved_rpc1); @@ -211,7 +220,7 @@ out: NVWriteVgaCrtc(dev, 0, NV_CIO_CR_MODE_INDEX, saved_cr_mode); if (blue == 0x18) { - NV_INFO(dev, "Load detected on head A\n"); + NV_INFO(drm, "Load detected on head A\n"); return connector_status_connected; } @@ -221,43 +230,46 @@ out: uint32_t nv17_dac_sample_load(struct drm_encoder *encoder) { struct drm_device *dev = encoder->dev; - struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_drm *drm = nouveau_drm(dev); + struct nouveau_device *device = nouveau_dev(dev); + struct nouveau_gpio *gpio = nouveau_gpio(device); struct dcb_output *dcb = nouveau_encoder(encoder)->dcb; uint32_t sample, testval, regoffset = nv04_dac_output_offset(encoder); uint32_t saved_powerctrl_2 = 0, saved_powerctrl_4 = 0, saved_routput, - saved_rtest_ctrl, saved_gpio0, saved_gpio1, temp, routput; + saved_rtest_ctrl, saved_gpio0 = 0, saved_gpio1 = 0, temp, routput; int head; #define RGB_TEST_DATA(r, g, b) (r << 0 | g << 10 | b << 20) if (dcb->type == DCB_OUTPUT_TV) { testval = RGB_TEST_DATA(0xa0, 0xa0, 0xa0); - if (dev_priv->vbios.tvdactestval) - testval = dev_priv->vbios.tvdactestval; + if (drm->vbios.tvdactestval) + testval = drm->vbios.tvdactestval; } else { testval = RGB_TEST_DATA(0x140, 0x140, 0x140); /* 0x94050140 */ - if (dev_priv->vbios.dactestval) - testval = dev_priv->vbios.dactestval; + if (drm->vbios.dactestval) + testval = drm->vbios.dactestval; } saved_rtest_ctrl = NVReadRAMDAC(dev, 0, NV_PRAMDAC_TEST_CONTROL + regoffset); NVWriteRAMDAC(dev, 0, NV_PRAMDAC_TEST_CONTROL + regoffset, saved_rtest_ctrl & ~NV_PRAMDAC_TEST_CONTROL_PWRDWN_DAC_OFF); - saved_powerctrl_2 = nv_rd32(dev, NV_PBUS_POWERCTRL_2); + saved_powerctrl_2 = nv_rd32(device, NV_PBUS_POWERCTRL_2); - nv_wr32(dev, NV_PBUS_POWERCTRL_2, saved_powerctrl_2 & 0xd7ffffff); + nv_wr32(device, NV_PBUS_POWERCTRL_2, saved_powerctrl_2 & 0xd7ffffff); if (regoffset == 0x68) { - saved_powerctrl_4 = nv_rd32(dev, NV_PBUS_POWERCTRL_4); - nv_wr32(dev, NV_PBUS_POWERCTRL_4, saved_powerctrl_4 & 0xffffffcf); + saved_powerctrl_4 = nv_rd32(device, NV_PBUS_POWERCTRL_4); + nv_wr32(device, NV_PBUS_POWERCTRL_4, saved_powerctrl_4 & 0xffffffcf); } - saved_gpio1 = nouveau_gpio_func_get(dev, DCB_GPIO_TVDAC1); - saved_gpio0 = nouveau_gpio_func_get(dev, DCB_GPIO_TVDAC0); - - nouveau_gpio_func_set(dev, DCB_GPIO_TVDAC1, dcb->type == DCB_OUTPUT_TV); - nouveau_gpio_func_set(dev, DCB_GPIO_TVDAC0, dcb->type == DCB_OUTPUT_TV); + if (gpio) { + saved_gpio1 = gpio->get(gpio, 0, DCB_GPIO_TVDAC1, 0xff); + saved_gpio0 = gpio->get(gpio, 0, DCB_GPIO_TVDAC0, 0xff); + gpio->set(gpio, 0, DCB_GPIO_TVDAC1, 0xff, dcb->type == DCB_OUTPUT_TV); + gpio->set(gpio, 0, DCB_GPIO_TVDAC0, 0xff, dcb->type == DCB_OUTPUT_TV); + } msleep(4); @@ -271,7 +283,7 @@ uint32_t nv17_dac_sample_load(struct drm_encoder *encoder) /* nv driver and nv31 use 0xfffffeee, nv34 and 6600 use 0xfffffece */ routput = (saved_routput & 0xfffffece) | head << 8; - if (dev_priv->card_type >= NV_40) { + if (nv_device(drm->device)->card_type >= NV_40) { if (dcb->type == DCB_OUTPUT_TV) routput |= 0x1a << 16; else @@ -304,11 +316,13 @@ uint32_t nv17_dac_sample_load(struct drm_encoder *encoder) NVWriteRAMDAC(dev, 0, NV_PRAMDAC_DACCLK + regoffset, saved_routput); NVWriteRAMDAC(dev, 0, NV_PRAMDAC_TEST_CONTROL + regoffset, saved_rtest_ctrl); if (regoffset == 0x68) - nv_wr32(dev, NV_PBUS_POWERCTRL_4, saved_powerctrl_4); - nv_wr32(dev, NV_PBUS_POWERCTRL_2, saved_powerctrl_2); + nv_wr32(device, NV_PBUS_POWERCTRL_4, saved_powerctrl_4); + nv_wr32(device, NV_PBUS_POWERCTRL_2, saved_powerctrl_2); - nouveau_gpio_func_set(dev, DCB_GPIO_TVDAC1, saved_gpio1); - nouveau_gpio_func_set(dev, DCB_GPIO_TVDAC0, saved_gpio0); + if (gpio) { + gpio->set(gpio, 0, DCB_GPIO_TVDAC1, 0xff, saved_gpio1); + gpio->set(gpio, 0, DCB_GPIO_TVDAC0, 0xff, saved_gpio0); + } return sample; } @@ -316,7 +330,7 @@ uint32_t nv17_dac_sample_load(struct drm_encoder *encoder) static enum drm_connector_status nv17_dac_detect(struct drm_encoder *encoder, struct drm_connector *connector) { - struct drm_device *dev = encoder->dev; + struct nouveau_drm *drm = nouveau_drm(encoder->dev); struct dcb_output *dcb = nouveau_encoder(encoder)->dcb; if (nv04_dac_in_use(encoder)) @@ -324,7 +338,7 @@ nv17_dac_detect(struct drm_encoder *encoder, struct drm_connector *connector) if (nv17_dac_sample_load(encoder) & NV_PRAMDAC_TEST_CONTROL_SENSEB_ALLHI) { - NV_INFO(dev, "Load detected on output %c\n", + NV_INFO(drm, "Load detected on output %c\n", '@' + ffs(dcb->or)); return connector_status_connected; } else { @@ -358,7 +372,7 @@ static void nv04_dac_mode_set(struct drm_encoder *encoder, struct drm_display_mode *adjusted_mode) { struct drm_device *dev = encoder->dev; - struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_drm *drm = nouveau_drm(dev); int head = nouveau_crtc(encoder->crtc)->index; if (nv_gf4_disp_arch(dev)) { @@ -384,7 +398,7 @@ static void nv04_dac_mode_set(struct drm_encoder *encoder, } /* This could use refinement for flatpanels, but it should work this way */ - if (dev_priv->chipset < 0x44) + if (nv_device(drm->device)->chipset < 0x44) NVWriteRAMDAC(dev, 0, NV_PRAMDAC_TEST_CONTROL + nv04_dac_output_offset(encoder), 0xf0000000); else NVWriteRAMDAC(dev, 0, NV_PRAMDAC_TEST_CONTROL + nv04_dac_output_offset(encoder), 0x00100000); @@ -393,13 +407,13 @@ static void nv04_dac_mode_set(struct drm_encoder *encoder, static void nv04_dac_commit(struct drm_encoder *encoder) { struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); - struct drm_device *dev = encoder->dev; + struct nouveau_drm *drm = nouveau_drm(encoder->dev); struct nouveau_crtc *nv_crtc = nouveau_crtc(encoder->crtc); struct drm_encoder_helper_funcs *helper = encoder->helper_private; helper->dpms(encoder, DRM_MODE_DPMS_ON); - NV_INFO(dev, "Output %s is running on CRTC %d using output %c\n", + NV_INFO(drm, "Output %s is running on CRTC %d using output %c\n", drm_get_connector_name(&nouveau_encoder_connector_get(nv_encoder)->base), nv_crtc->index, '@' + ffs(nv_encoder->dcb->or)); } @@ -440,14 +454,14 @@ bool nv04_dac_in_use(struct drm_encoder *encoder) static void nv04_dac_dpms(struct drm_encoder *encoder, int mode) { - struct drm_device *dev = encoder->dev; struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); + struct nouveau_drm *drm = nouveau_drm(encoder->dev); if (nv_encoder->last_dpms == mode) return; nv_encoder->last_dpms = mode; - NV_INFO(dev, "Setting dpms mode %d on vga encoder (output %d)\n", + NV_INFO(drm, "Setting dpms mode %d on vga encoder (output %d)\n", mode, nv_encoder->dcb->index); nv04_dac_update_dacclk(encoder, mode == DRM_MODE_DPMS_ON); @@ -479,8 +493,6 @@ static void nv04_dac_destroy(struct drm_encoder *encoder) { struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); - NV_DEBUG_KMS(encoder->dev, "\n"); - drm_encoder_cleanup(encoder); kfree(nv_encoder); } diff --git a/drivers/gpu/drm/nouveau/nv04_dfp.c b/drivers/gpu/drm/nouveau/nv04_dfp.c index b53de928dcaf..e53df742cc01 100644 --- a/drivers/gpu/drm/nouveau/nv04_dfp.c +++ b/drivers/gpu/drm/nouveau/nv04_dfp.c @@ -27,7 +27,8 @@ #include "drmP.h" #include "drm_crtc_helper.h" -#include "nouveau_drv.h" +#include "nouveau_drm.h" +#include "nouveau_reg.h" #include "nouveau_encoder.h" #include "nouveau_connector.h" #include "nouveau_crtc.h" @@ -36,6 +37,8 @@ #include "i2c/sil164.h" +#include + #define FP_TG_CONTROL_ON (NV_PRAMDAC_FP_TG_CONTROL_DISPEN_POS | \ NV_PRAMDAC_FP_TG_CONTROL_HSYNC_POS | \ NV_PRAMDAC_FP_TG_CONTROL_VSYNC_POS) @@ -278,7 +281,8 @@ static void nv04_dfp_mode_set(struct drm_encoder *encoder, struct drm_display_mode *adjusted_mode) { struct drm_device *dev = encoder->dev; - struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_device *device = nouveau_dev(dev); + struct nouveau_drm *drm = nouveau_drm(dev); struct nouveau_crtc *nv_crtc = nouveau_crtc(encoder->crtc); struct nv04_crtc_reg *regp = &nv04_display(dev)->mode_reg.crtc_reg[nv_crtc->index]; struct nv04_crtc_reg *savep = &nv04_display(dev)->saved_reg.crtc_reg[nv_crtc->index]; @@ -288,7 +292,7 @@ static void nv04_dfp_mode_set(struct drm_encoder *encoder, struct drm_connector *connector = &nv_connector->base; uint32_t mode_ratio, panel_ratio; - NV_DEBUG_KMS(dev, "Output mode on CRTC %d:\n", nv_crtc->index); + NV_DEBUG(drm, "Output mode on CRTC %d:\n", nv_crtc->index); drm_mode_debug_printmodeline(output_mode); /* Initialize the FP registers in this CRTC. */ @@ -296,10 +300,10 @@ static void nv04_dfp_mode_set(struct drm_encoder *encoder, regp->fp_horiz_regs[FP_TOTAL] = output_mode->htotal - 1; if (!nv_gf4_disp_arch(dev) || (output_mode->hsync_start - output_mode->hdisplay) >= - dev_priv->vbios.digital_min_front_porch) + drm->vbios.digital_min_front_porch) regp->fp_horiz_regs[FP_CRTC] = output_mode->hdisplay; else - regp->fp_horiz_regs[FP_CRTC] = output_mode->hsync_start - dev_priv->vbios.digital_min_front_porch - 1; + regp->fp_horiz_regs[FP_CRTC] = output_mode->hsync_start - drm->vbios.digital_min_front_porch - 1; regp->fp_horiz_regs[FP_SYNC_START] = output_mode->hsync_start - 1; regp->fp_horiz_regs[FP_SYNC_END] = output_mode->hsync_end - 1; regp->fp_horiz_regs[FP_VALID_START] = output_mode->hskew; @@ -331,7 +335,7 @@ static void nv04_dfp_mode_set(struct drm_encoder *encoder, regp->fp_control |= NV_PRAMDAC_FP_TG_CONTROL_MODE_NATIVE; else /* gpu needs to scale */ regp->fp_control |= NV_PRAMDAC_FP_TG_CONTROL_MODE_SCALE; - if (nv_rd32(dev, NV_PEXTDEV_BOOT_0) & NV_PEXTDEV_BOOT_0_STRAP_FP_IFACE_12BIT) + if (nv_rd32(device, NV_PEXTDEV_BOOT_0) & NV_PEXTDEV_BOOT_0_STRAP_FP_IFACE_12BIT) regp->fp_control |= NV_PRAMDAC_FP_TG_CONTROL_WIDTH_12; if (nv_encoder->dcb->location != DCB_LOC_ON_CHIP && output_mode->clock > 165000) @@ -412,7 +416,7 @@ static void nv04_dfp_mode_set(struct drm_encoder *encoder, if ((nv_connector->dithering_mode == DITHERING_MODE_ON) || (nv_connector->dithering_mode == DITHERING_MODE_AUTO && encoder->crtc->fb->depth > connector->display_info.bpc * 3)) { - if (dev_priv->chipset == 0x11) + if (nv_device(drm->device)->chipset == 0x11) regp->dither = savep->dither | 0x00010000; else { int i; @@ -423,7 +427,7 @@ static void nv04_dfp_mode_set(struct drm_encoder *encoder, } } } else { - if (dev_priv->chipset != 0x11) { + if (nv_device(drm->device)->chipset != 0x11) { /* reset them */ int i; for (i = 0; i < 3; i++) { @@ -440,7 +444,7 @@ static void nv04_dfp_mode_set(struct drm_encoder *encoder, static void nv04_dfp_commit(struct drm_encoder *encoder) { struct drm_device *dev = encoder->dev; - struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_drm *drm = nouveau_drm(dev); struct drm_encoder_helper_funcs *helper = encoder->helper_private; struct nouveau_crtc *nv_crtc = nouveau_crtc(encoder->crtc); struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); @@ -459,7 +463,7 @@ static void nv04_dfp_commit(struct drm_encoder *encoder) NVReadRAMDAC(dev, head, NV_PRAMDAC_FP_TG_CONTROL); /* This could use refinement for flatpanels, but it should work this way */ - if (dev_priv->chipset < 0x44) + if (nv_device(drm->device)->chipset < 0x44) NVWriteRAMDAC(dev, 0, NV_PRAMDAC_TEST_CONTROL + nv04_dac_output_offset(encoder), 0xf0000000); else NVWriteRAMDAC(dev, 0, NV_PRAMDAC_TEST_CONTROL + nv04_dac_output_offset(encoder), 0x00100000); @@ -472,7 +476,7 @@ static void nv04_dfp_commit(struct drm_encoder *encoder) helper->dpms(encoder, DRM_MODE_DPMS_ON); - NV_INFO(dev, "Output %s is running on CRTC %d using output %c\n", + NV_INFO(drm, "Output %s is running on CRTC %d using output %c\n", drm_get_connector_name(&nouveau_encoder_connector_get(nv_encoder)->base), nv_crtc->index, '@' + ffs(nv_encoder->dcb->or)); } @@ -481,6 +485,7 @@ static void nv04_dfp_update_backlight(struct drm_encoder *encoder, int mode) { #ifdef __powerpc__ struct drm_device *dev = encoder->dev; + struct nouveau_device *device = nouveau_dev(dev); /* BIOS scripts usually take care of the backlight, thanks * Apple for your consistency. @@ -488,11 +493,11 @@ static void nv04_dfp_update_backlight(struct drm_encoder *encoder, int mode) if (dev->pci_device == 0x0179 || dev->pci_device == 0x0189 || dev->pci_device == 0x0329) { if (mode == DRM_MODE_DPMS_ON) { - nv_mask(dev, NV_PBUS_DEBUG_DUALHEAD_CTL, 0, 1 << 31); - nv_mask(dev, NV_PCRTC_GPIO_EXT, 3, 1); + nv_mask(device, NV_PBUS_DEBUG_DUALHEAD_CTL, 0, 1 << 31); + nv_mask(device, NV_PCRTC_GPIO_EXT, 3, 1); } else { - nv_mask(dev, NV_PBUS_DEBUG_DUALHEAD_CTL, 1 << 31, 0); - nv_mask(dev, NV_PCRTC_GPIO_EXT, 3, 0); + nv_mask(device, NV_PBUS_DEBUG_DUALHEAD_CTL, 1 << 31, 0); + nv_mask(device, NV_PCRTC_GPIO_EXT, 3, 0); } } #endif @@ -507,6 +512,7 @@ static void nv04_lvds_dpms(struct drm_encoder *encoder, int mode) { struct drm_device *dev = encoder->dev; struct drm_crtc *crtc = encoder->crtc; + struct nouveau_drm *drm = nouveau_drm(dev); struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); bool was_powersaving = is_powersaving_dpms(nv_encoder->last_dpms); @@ -514,7 +520,7 @@ static void nv04_lvds_dpms(struct drm_encoder *encoder, int mode) return; nv_encoder->last_dpms = mode; - NV_INFO(dev, "Setting dpms mode %d on lvds encoder (output %d)\n", + NV_INFO(drm, "Setting dpms mode %d on lvds encoder (output %d)\n", mode, nv_encoder->dcb->index); if (was_powersaving && is_powersaving_dpms(mode)) @@ -552,14 +558,14 @@ static void nv04_lvds_dpms(struct drm_encoder *encoder, int mode) static void nv04_tmds_dpms(struct drm_encoder *encoder, int mode) { - struct drm_device *dev = encoder->dev; + struct nouveau_drm *drm = nouveau_drm(encoder->dev); struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); if (nv_encoder->last_dpms == mode) return; nv_encoder->last_dpms = mode; - NV_INFO(dev, "Setting dpms mode %d on tmds encoder (output %d)\n", + NV_INFO(drm, "Setting dpms mode %d on tmds encoder (output %d)\n", mode, nv_encoder->dcb->index); nv04_dfp_update_backlight(encoder, mode); @@ -605,8 +611,6 @@ static void nv04_dfp_destroy(struct drm_encoder *encoder) { struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); - NV_DEBUG_KMS(encoder->dev, "\n"); - if (get_slave_funcs(encoder)) get_slave_funcs(encoder)->destroy(encoder); @@ -618,7 +622,9 @@ static void nv04_tmds_slave_init(struct drm_encoder *encoder) { struct drm_device *dev = encoder->dev; struct dcb_output *dcb = nouveau_encoder(encoder)->dcb; - struct nouveau_i2c_port *i2c = nouveau_i2c_find(dev, 2); + struct nouveau_drm *drm = nouveau_drm(dev); + struct nouveau_i2c *i2c = nouveau_i2c(drm->device); + struct nouveau_i2c_port *port = i2c->find(i2c, 2); struct i2c_board_info info[] = { { .type = "sil164", @@ -631,16 +637,16 @@ static void nv04_tmds_slave_init(struct drm_encoder *encoder) }; int type; - if (!nv_gf4_disp_arch(dev) || !i2c || + if (!nv_gf4_disp_arch(dev) || !port || get_tmds_slave(encoder)) return; - type = nouveau_i2c_identify(dev, "TMDS transmitter", info, NULL, 2); + type = i2c->identify(i2c, 2, "TMDS transmitter", info, NULL); if (type < 0) return; drm_i2c_encoder_init(dev, to_encoder_slave(encoder), - nouveau_i2c_adapter(i2c), &info[type]); + &port->adapter, &info[type]); } static const struct drm_encoder_helper_funcs nv04_lvds_helper_funcs = { diff --git a/drivers/gpu/drm/nouveau/nv04_display.c b/drivers/gpu/drm/nouveau/nv04_display.c index 6ab936376c40..b25b8d9c2fcc 100644 --- a/drivers/gpu/drm/nouveau/nv04_display.c +++ b/drivers/gpu/drm/nouveau/nv04_display.c @@ -26,8 +26,8 @@ #include "drm.h" #include "drm_crtc_helper.h" -#include "nouveau_drv.h" -#include "nouveau_fb.h" +#include "nouveau_drm.h" +#include "nouveau_reg.h" #include "nouveau_hw.h" #include "nouveau_encoder.h" #include "nouveau_connector.h" @@ -53,21 +53,25 @@ nv04_display_late_takedown(struct drm_device *dev) int nv04_display_create(struct drm_device *dev) { - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct dcb_table *dcb = &dev_priv->vbios.dcb; + struct nouveau_drm *drm = nouveau_drm(dev); + struct dcb_table *dcb = &drm->vbios.dcb; struct drm_connector *connector, *ct; struct drm_encoder *encoder; struct drm_crtc *crtc; struct nv04_display *disp; int i, ret; - NV_DEBUG_KMS(dev, "\n"); + NV_DEBUG(drm, "\n"); disp = kzalloc(sizeof(*disp), GFP_KERNEL); - dev_priv->engine.display.priv = disp; if (!disp) return -ENOMEM; + nouveau_display(dev)->priv = disp; + nouveau_display(dev)->dtor = nv04_display_destroy; + nouveau_display(dev)->init = nv04_display_init; + nouveau_display(dev)->fini = nv04_display_fini; + nouveau_hw_save_vga_fonts(dev, 1); nv04_crtc_create(dev, 0); @@ -96,7 +100,7 @@ nv04_display_create(struct drm_device *dev) ret = nv04_tv_create(connector, dcbent); break; default: - NV_WARN(dev, "DCB type %d not known\n", dcbent->type); + NV_WARN(drm, "DCB type %d not known\n", dcbent->type); continue; } @@ -107,7 +111,7 @@ nv04_display_create(struct drm_device *dev) list_for_each_entry_safe(connector, ct, &dev->mode_config.connector_list, head) { if (!connector->encoder_ids[0]) { - NV_WARN(dev, "%s has no encoders, removing\n", + NV_WARN(drm, "%s has no encoders, removing\n", drm_get_connector_name(connector)); connector->funcs->destroy(connector); } @@ -129,12 +133,12 @@ nv04_display_create(struct drm_device *dev) void nv04_display_destroy(struct drm_device *dev) { - struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_drm *drm = nouveau_drm(dev); struct nv04_display *disp = nv04_display(dev); struct drm_encoder *encoder; struct drm_crtc *crtc; - NV_DEBUG_KMS(dev, "\n"); + NV_DEBUG(drm, "\n"); /* Turn every CRTC off. */ list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { @@ -157,7 +161,7 @@ nv04_display_destroy(struct drm_device *dev) nouveau_hw_save_vga_fonts(dev, 0); - dev_priv->engine.display.priv = NULL; + nouveau_display(dev)->priv = NULL; kfree(disp); } diff --git a/drivers/gpu/drm/nouveau/nv04_display.h b/drivers/gpu/drm/nouveau/nv04_display.h index 139b8b057534..45322802e37d 100644 --- a/drivers/gpu/drm/nouveau/nv04_display.h +++ b/drivers/gpu/drm/nouveau/nv04_display.h @@ -3,6 +3,8 @@ #include +#include "nouveau_display.h" + enum nv04_fp_display_regs { FP_DISPLAY_END, FP_TOTAL, @@ -80,6 +82,12 @@ struct nv04_display { uint32_t dac_users[4]; }; +static inline struct nv04_display * +nv04_display(struct drm_device *dev) +{ + return nouveau_display(dev)->priv; +} + /* nv04_display.c */ int nv04_display_early_init(struct drm_device *); void nv04_display_late_takedown(struct drm_device *); @@ -113,4 +121,64 @@ int nv04_tv_create(struct drm_connector *, struct dcb_output *); /* nv17_tv.c */ int nv17_tv_create(struct drm_connector *, struct dcb_output *); +static inline bool +nv_two_heads(struct drm_device *dev) +{ + struct nouveau_drm *drm = nouveau_drm(dev); + const int impl = dev->pci_device & 0x0ff0; + + if (nv_device(drm->device)->card_type >= NV_10 && impl != 0x0100 && + impl != 0x0150 && impl != 0x01a0 && impl != 0x0200) + return true; + + return false; +} + +static inline bool +nv_gf4_disp_arch(struct drm_device *dev) +{ + return nv_two_heads(dev) && (dev->pci_device & 0x0ff0) != 0x0110; +} + +static inline bool +nv_two_reg_pll(struct drm_device *dev) +{ + struct nouveau_drm *drm = nouveau_drm(dev); + const int impl = dev->pci_device & 0x0ff0; + + if (impl == 0x0310 || impl == 0x0340 || nv_device(drm->device)->card_type >= NV_40) + return true; + return false; +} + +static inline bool +nv_match_device(struct drm_device *dev, unsigned device, + unsigned sub_vendor, unsigned sub_device) +{ + return dev->pdev->device == device && + dev->pdev->subsystem_vendor == sub_vendor && + dev->pdev->subsystem_device == sub_device; +} + +#include +#include + +static inline void +nouveau_bios_run_init_table(struct drm_device *dev, u16 table, + struct dcb_output *outp, int crtc) +{ + struct nouveau_device *device = nouveau_dev(dev); + struct nouveau_bios *bios = nouveau_bios(device); + struct nvbios_init init = { + .subdev = nv_subdev(bios), + .bios = bios, + .offset = table, + .outp = outp, + .crtc = crtc, + .execute = 1, + }; + + nvbios_exec(&init); +} + #endif diff --git a/drivers/gpu/drm/nouveau/nv04_fbcon.c b/drivers/gpu/drm/nouveau/nv04_fbcon.c index 35480b6776f8..77dcc9c50777 100644 --- a/drivers/gpu/drm/nouveau/nv04_fbcon.c +++ b/drivers/gpu/drm/nouveau/nv04_fbcon.c @@ -32,7 +32,7 @@ int nv04_fbcon_copyarea(struct fb_info *info, const struct fb_copyarea *region) { struct nouveau_fbdev *nfbdev = info->par; - struct nouveau_drm *drm = nouveau_newpriv(nfbdev->dev); + struct nouveau_drm *drm = nouveau_drm(nfbdev->dev); struct nouveau_channel *chan = drm->channel; int ret; @@ -52,7 +52,7 @@ int nv04_fbcon_fillrect(struct fb_info *info, const struct fb_fillrect *rect) { struct nouveau_fbdev *nfbdev = info->par; - struct nouveau_drm *drm = nouveau_newpriv(nfbdev->dev); + struct nouveau_drm *drm = nouveau_drm(nfbdev->dev); struct nouveau_channel *chan = drm->channel; int ret; @@ -79,7 +79,7 @@ int nv04_fbcon_imageblit(struct fb_info *info, const struct fb_image *image) { struct nouveau_fbdev *nfbdev = info->par; - struct nouveau_drm *drm = nouveau_newpriv(nfbdev->dev); + struct nouveau_drm *drm = nouveau_drm(nfbdev->dev); struct nouveau_channel *chan = drm->channel; uint32_t fg; uint32_t bg; @@ -139,7 +139,7 @@ nv04_fbcon_accel_init(struct fb_info *info) { struct nouveau_fbdev *nfbdev = info->par; struct drm_device *dev = nfbdev->dev; - struct nouveau_drm *drm = nouveau_newpriv(dev); + struct nouveau_drm *drm = nouveau_drm(dev); struct nouveau_channel *chan = drm->channel; struct nouveau_device *device = nv_device(drm->device); struct nouveau_object *object; diff --git a/drivers/gpu/drm/nouveau/nv04_pm.c b/drivers/gpu/drm/nouveau/nv04_pm.c index 76b5340603a9..410be011c2f0 100644 --- a/drivers/gpu/drm/nouveau/nv04_pm.c +++ b/drivers/gpu/drm/nouveau/nv04_pm.c @@ -23,10 +23,15 @@ */ #include "drmP.h" -#include "nouveau_drv.h" +#include "nouveau_drm.h" +#include "nouveau_reg.h" #include "nouveau_hw.h" #include "nouveau_pm.h" +#include +#include +#include + int nv04_pm_clocks_get(struct drm_device *dev, struct nouveau_pm_level *perflvl) { @@ -58,13 +63,16 @@ struct nv04_pm_state { static int calc_pll(struct drm_device *dev, u32 id, int khz, struct nv04_pm_clock *clk) { + struct nouveau_device *device = nouveau_dev(dev); + struct nouveau_bios *bios = nouveau_bios(device); + struct nouveau_clock *pclk = nouveau_clock(device); int ret; - ret = get_pll_limits(dev, id, &clk->pll); + ret = nvbios_pll_parse(bios, id, &clk->pll); if (ret) return ret; - ret = nouveau_calc_pll_mnp(dev, &clk->pll, khz, &clk->calc); + ret = pclk->pll_calc(pclk, &clk->pll, khz, &clk->calc); if (!ret) return -EINVAL; @@ -100,38 +108,38 @@ error: static void prog_pll(struct drm_device *dev, struct nv04_pm_clock *clk) { - struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_device *device = nouveau_dev(dev); + struct nouveau_clock *pclk = nouveau_clock(device); u32 reg = clk->pll.reg; /* thank the insane nouveau_hw_setpll() interface for this */ - if (dev_priv->card_type >= NV_40) + if (device->card_type >= NV_40) reg += 4; - nouveau_hw_setpll(dev, reg, &clk->calc); + pclk->pll_prog(pclk, reg, &clk->calc); } int nv04_pm_clocks_set(struct drm_device *dev, void *pre_state) { - struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_device *device = nouveau_dev(dev); + struct nouveau_timer *ptimer = nouveau_timer(device); struct nv04_pm_state *state = pre_state; prog_pll(dev, &state->core); if (state->memory.pll.reg) { prog_pll(dev, &state->memory); - if (dev_priv->card_type < NV_30) { - if (dev_priv->card_type == NV_20) - nv_mask(dev, 0x1002c4, 0, 1 << 20); + if (device->card_type < NV_30) { + if (device->card_type == NV_20) + nv_mask(device, 0x1002c4, 0, 1 << 20); /* Reset the DLLs */ - nv_mask(dev, 0x1002c0, 0, 1 << 8); + nv_mask(device, 0x1002c0, 0, 1 << 8); } } -#if 0 /*XXX*/ - ptimer->init(dev); -#endif + nv_ofuncs(ptimer)->init(nv_object(ptimer)); kfree(state); return 0; diff --git a/drivers/gpu/drm/nouveau/nv04_tv.c b/drivers/gpu/drm/nouveau/nv04_tv.c index 5f5c25d77343..45c5c039e7e4 100644 --- a/drivers/gpu/drm/nouveau/nv04_tv.c +++ b/drivers/gpu/drm/nouveau/nv04_tv.c @@ -25,7 +25,8 @@ */ #include "drmP.h" -#include "nouveau_drv.h" +#include "nouveau_drm.h" +#include "nouveau_reg.h" #include "nouveau_encoder.h" #include "nouveau_connector.h" #include "nouveau_crtc.h" @@ -34,6 +35,8 @@ #include "i2c/ch7006.h" +#include + static struct i2c_board_info nv04_tv_encoder_info[] = { { I2C_BOARD_INFO("ch7006", 0x75), @@ -49,8 +52,11 @@ static struct i2c_board_info nv04_tv_encoder_info[] = { int nv04_tv_identify(struct drm_device *dev, int i2c_index) { - return nouveau_i2c_identify(dev, "TV encoder", nv04_tv_encoder_info, - NULL, i2c_index); + struct nouveau_drm *drm = nouveau_drm(dev); + struct nouveau_i2c *i2c = nouveau_i2c(drm->device); + + return i2c->identify(i2c, i2c_index, "TV encoder", + nv04_tv_encoder_info, NULL); } @@ -64,11 +70,12 @@ int nv04_tv_identify(struct drm_device *dev, int i2c_index) static void nv04_tv_dpms(struct drm_encoder *encoder, int mode) { struct drm_device *dev = encoder->dev; + struct nouveau_drm *drm = nouveau_drm(dev); struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); struct nv04_mode_state *state = &nv04_display(dev)->mode_reg; uint8_t crtc1A; - NV_INFO(dev, "Setting dpms mode %d on TV encoder (output %d)\n", + NV_INFO(drm, "Setting dpms mode %d on TV encoder (output %d)\n", mode, nv_encoder->dcb->index); state->pllsel &= ~(PLLSEL_TV_CRTC1_MASK | PLLSEL_TV_CRTC2_MASK); @@ -154,12 +161,13 @@ static void nv04_tv_commit(struct drm_encoder *encoder) { struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); struct drm_device *dev = encoder->dev; + struct nouveau_drm *drm = nouveau_drm(dev); struct nouveau_crtc *nv_crtc = nouveau_crtc(encoder->crtc); struct drm_encoder_helper_funcs *helper = encoder->helper_private; helper->dpms(encoder, DRM_MODE_DPMS_ON); - NV_INFO(dev, "Output %s is running on CRTC %d using output %c\n", + NV_INFO(drm, "Output %s is running on CRTC %d using output %c\n", drm_get_connector_name(&nouveau_encoder_connector_get(nv_encoder)->base), nv_crtc->index, '@' + ffs(nv_encoder->dcb->or)); } @@ -185,8 +193,9 @@ nv04_tv_create(struct drm_connector *connector, struct dcb_output *entry) struct drm_device *dev = connector->dev; struct drm_encoder_helper_funcs *hfuncs; struct drm_encoder_slave_funcs *sfuncs; - struct nouveau_i2c_port *i2c = - nouveau_i2c_find(dev, entry->i2c_index); + struct nouveau_drm *drm = nouveau_drm(dev); + struct nouveau_i2c *i2c = nouveau_i2c(drm->device); + struct nouveau_i2c_port *port = i2c->find(i2c, entry->i2c_index); int type, ret; /* Ensure that we can talk to this encoder */ @@ -218,7 +227,7 @@ nv04_tv_create(struct drm_connector *connector, struct dcb_output *entry) /* Run the slave-specific initialization */ ret = drm_i2c_encoder_init(dev, to_encoder_slave(encoder), - nouveau_i2c_adapter(i2c), &nv04_tv_encoder_info[type]); + &port->adapter, &nv04_tv_encoder_info[type]); if (ret < 0) goto fail_cleanup; diff --git a/drivers/gpu/drm/nouveau/nv17_tv.c b/drivers/gpu/drm/nouveau/nv17_tv.c index 5d1f6f6de257..dd85f0f79acf 100644 --- a/drivers/gpu/drm/nouveau/nv17_tv.c +++ b/drivers/gpu/drm/nouveau/nv17_tv.c @@ -26,19 +26,32 @@ #include "drmP.h" #include "drm_crtc_helper.h" -#include "nouveau_drv.h" +#include "nouveau_drm.h" +#include "nouveau_reg.h" #include "nouveau_encoder.h" #include "nouveau_connector.h" #include "nouveau_crtc.h" #include "nouveau_hw.h" #include "nv17_tv.h" +#include + #include +#include + +MODULE_PARM_DESC(tv_norm, "Default TV norm.\n" + "\t\tSupported: PAL, PAL-M, PAL-N, PAL-Nc, NTSC-M, NTSC-J,\n" + "\t\t\thd480i, hd480p, hd576i, hd576p, hd720p, hd1080i.\n" + "\t\tDefault: PAL\n" + "\t\t*NOTE* Ignored for cards with external TV encoders."); +static char *nouveau_tv_norm; +module_param_named(tv_norm, nouveau_tv_norm, charp, 0400); static uint32_t nv42_tv_sample_load(struct drm_encoder *encoder) { struct drm_device *dev = encoder->dev; - struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_drm *drm = nouveau_drm(dev); + struct nouveau_gpio *gpio = nouveau_gpio(drm->device); uint32_t testval, regoffset = nv04_dac_output_offset(encoder); uint32_t gpio0, gpio1, fp_htotal, fp_hsync_start, fp_hsync_end, fp_control, test_ctrl, dacclk, ctv_14, ctv_1c, ctv_6c; @@ -47,15 +60,15 @@ static uint32_t nv42_tv_sample_load(struct drm_encoder *encoder) #define RGB_TEST_DATA(r, g, b) (r << 0 | g << 10 | b << 20) testval = RGB_TEST_DATA(0x82, 0xeb, 0x82); - if (dev_priv->vbios.tvdactestval) - testval = dev_priv->vbios.tvdactestval; + if (drm->vbios.tvdactestval) + testval = drm->vbios.tvdactestval; dacclk = NVReadRAMDAC(dev, 0, NV_PRAMDAC_DACCLK + regoffset); head = (dacclk & 0x100) >> 8; /* Save the previous state. */ - gpio1 = nouveau_gpio_func_get(dev, DCB_GPIO_TVDAC1); - gpio0 = nouveau_gpio_func_get(dev, DCB_GPIO_TVDAC0); + gpio1 = gpio->get(gpio, 0, DCB_GPIO_TVDAC1, 0xff); + gpio0 = gpio->get(gpio, 0, DCB_GPIO_TVDAC0, 0xff); fp_htotal = NVReadRAMDAC(dev, head, NV_PRAMDAC_FP_HTOTAL); fp_hsync_start = NVReadRAMDAC(dev, head, NV_PRAMDAC_FP_HSYNC_START); fp_hsync_end = NVReadRAMDAC(dev, head, NV_PRAMDAC_FP_HSYNC_END); @@ -66,8 +79,8 @@ static uint32_t nv42_tv_sample_load(struct drm_encoder *encoder) ctv_6c = NVReadRAMDAC(dev, head, 0x680c6c); /* Prepare the DAC for load detection. */ - nouveau_gpio_func_set(dev, DCB_GPIO_TVDAC1, true); - nouveau_gpio_func_set(dev, DCB_GPIO_TVDAC0, true); + gpio->set(gpio, 0, DCB_GPIO_TVDAC1, 0xff, true); + gpio->set(gpio, 0, DCB_GPIO_TVDAC0, 0xff, true); NVWriteRAMDAC(dev, head, NV_PRAMDAC_FP_HTOTAL, 1343); NVWriteRAMDAC(dev, head, NV_PRAMDAC_FP_HSYNC_START, 1047); @@ -112,8 +125,8 @@ static uint32_t nv42_tv_sample_load(struct drm_encoder *encoder) NVWriteRAMDAC(dev, head, NV_PRAMDAC_FP_HSYNC_END, fp_hsync_end); NVWriteRAMDAC(dev, head, NV_PRAMDAC_FP_HSYNC_START, fp_hsync_start); NVWriteRAMDAC(dev, head, NV_PRAMDAC_FP_HTOTAL, fp_htotal); - nouveau_gpio_func_set(dev, DCB_GPIO_TVDAC1, gpio1); - nouveau_gpio_func_set(dev, DCB_GPIO_TVDAC0, gpio0); + gpio->set(gpio, 0, DCB_GPIO_TVDAC1, 0xff, gpio1); + gpio->set(gpio, 0, DCB_GPIO_TVDAC0, 0xff, gpio0); return sample; } @@ -121,15 +134,18 @@ static uint32_t nv42_tv_sample_load(struct drm_encoder *encoder) static bool get_tv_detect_quirks(struct drm_device *dev, uint32_t *pin_mask) { + struct nouveau_drm *drm = nouveau_drm(dev); + struct nouveau_object *device = drm->device; + /* Zotac FX5200 */ - if (nv_match_device(dev, 0x0322, 0x19da, 0x1035) || - nv_match_device(dev, 0x0322, 0x19da, 0x2035)) { + if (nv_device_match(device, 0x0322, 0x19da, 0x1035) || + nv_device_match(device, 0x0322, 0x19da, 0x2035)) { *pin_mask = 0xc; return false; } /* MSI nForce2 IGP */ - if (nv_match_device(dev, 0x01f0, 0x1462, 0x5710)) { + if (nv_device_match(device, 0x01f0, 0x1462, 0x5710)) { *pin_mask = 0xc; return false; } @@ -141,7 +157,7 @@ static enum drm_connector_status nv17_tv_detect(struct drm_encoder *encoder, struct drm_connector *connector) { struct drm_device *dev = encoder->dev; - struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_drm *drm = nouveau_drm(dev); struct drm_mode_config *conf = &dev->mode_config; struct nv17_tv_encoder *tv_enc = to_tv_enc(encoder); struct dcb_output *dcb = tv_enc->base.dcb; @@ -151,8 +167,8 @@ nv17_tv_detect(struct drm_encoder *encoder, struct drm_connector *connector) return connector_status_disconnected; if (reliable) { - if (dev_priv->chipset == 0x42 || - dev_priv->chipset == 0x43) + if (nv_device(drm->device)->chipset == 0x42 || + nv_device(drm->device)->chipset == 0x43) tv_enc->pin_mask = nv42_tv_sample_load(encoder) >> 28 & 0xe; else @@ -186,7 +202,7 @@ nv17_tv_detect(struct drm_encoder *encoder, struct drm_connector *connector) if (!reliable) { return connector_status_unknown; } else if (tv_enc->subconnector) { - NV_INFO(dev, "Load detected on output %c\n", + NV_INFO(drm, "Load detected on output %c\n", '@' + ffs(dcb->or)); return connector_status_connected; } else { @@ -358,6 +374,8 @@ static bool nv17_tv_mode_fixup(struct drm_encoder *encoder, static void nv17_tv_dpms(struct drm_encoder *encoder, int mode) { struct drm_device *dev = encoder->dev; + struct nouveau_drm *drm = nouveau_drm(dev); + struct nouveau_gpio *gpio = nouveau_gpio(drm->device); struct nv17_tv_state *regs = &to_tv_enc(encoder)->state; struct nv17_tv_norm_params *tv_norm = get_tv_norm(encoder); @@ -365,7 +383,7 @@ static void nv17_tv_dpms(struct drm_encoder *encoder, int mode) return; nouveau_encoder(encoder)->last_dpms = mode; - NV_INFO(dev, "Setting dpms mode %d on TV encoder (output %d)\n", + NV_INFO(drm, "Setting dpms mode %d on TV encoder (output %d)\n", mode, nouveau_encoder(encoder)->dcb->index); regs->ptv_200 &= ~1; @@ -382,8 +400,8 @@ static void nv17_tv_dpms(struct drm_encoder *encoder, int mode) nv_load_ptv(dev, regs, 200); - nouveau_gpio_func_set(dev, DCB_GPIO_TVDAC1, mode == DRM_MODE_DPMS_ON); - nouveau_gpio_func_set(dev, DCB_GPIO_TVDAC0, mode == DRM_MODE_DPMS_ON); + gpio->set(gpio, 0, DCB_GPIO_TVDAC1, 0xff, mode == DRM_MODE_DPMS_ON); + gpio->set(gpio, 0, DCB_GPIO_TVDAC0, 0xff, mode == DRM_MODE_DPMS_ON); nv04_dac_update_dacclk(encoder, mode == DRM_MODE_DPMS_ON); } @@ -391,7 +409,7 @@ static void nv17_tv_dpms(struct drm_encoder *encoder, int mode) static void nv17_tv_prepare(struct drm_encoder *encoder) { struct drm_device *dev = encoder->dev; - struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_drm *drm = nouveau_drm(dev); struct drm_encoder_helper_funcs *helper = encoder->helper_private; struct nv17_tv_norm_params *tv_norm = get_tv_norm(encoder); int head = nouveau_crtc(encoder->crtc)->index; @@ -418,7 +436,7 @@ static void nv17_tv_prepare(struct drm_encoder *encoder) !enc->crtc && nv04_dfp_get_bound_head(dev, dcb) == head) { nv04_dfp_bind_head(dev, dcb, head ^ 1, - dev_priv->vbios.fp.dual_link); + drm->vbios.fp.dual_link); } } @@ -430,7 +448,7 @@ static void nv17_tv_prepare(struct drm_encoder *encoder) /* Set the DACCLK register */ dacclk = (NVReadRAMDAC(dev, 0, dacclk_off) & ~0x30) | 0x1; - if (dev_priv->card_type == NV_40) + if (nv_device(drm->device)->card_type == NV_40) dacclk |= 0x1a << 16; if (tv_norm->kind == CTV_ENC_MODE) { @@ -454,7 +472,7 @@ static void nv17_tv_mode_set(struct drm_encoder *encoder, struct drm_display_mode *adjusted_mode) { struct drm_device *dev = encoder->dev; - struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_drm *drm = nouveau_drm(dev); int head = nouveau_crtc(encoder->crtc)->index; struct nv04_crtc_reg *regs = &nv04_display(dev)->mode_reg.crtc_reg[head]; struct nv17_tv_state *tv_regs = &to_tv_enc(encoder)->state; @@ -487,7 +505,7 @@ static void nv17_tv_mode_set(struct drm_encoder *encoder, tv_regs->ptv_614 = 0x13; } - if (dev_priv->card_type >= NV_30) { + if (nv_device(drm->device)->card_type >= NV_30) { tv_regs->ptv_500 = 0xe8e0; tv_regs->ptv_504 = 0x1710; tv_regs->ptv_604 = 0x0; @@ -567,7 +585,7 @@ static void nv17_tv_mode_set(struct drm_encoder *encoder, static void nv17_tv_commit(struct drm_encoder *encoder) { struct drm_device *dev = encoder->dev; - struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_drm *drm = nouveau_drm(dev); struct nouveau_crtc *nv_crtc = nouveau_crtc(encoder->crtc); struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); struct drm_encoder_helper_funcs *helper = encoder->helper_private; @@ -582,7 +600,7 @@ static void nv17_tv_commit(struct drm_encoder *encoder) nv17_tv_state_load(dev, &to_tv_enc(encoder)->state); /* This could use refinement for flatpanels, but it should work */ - if (dev_priv->chipset < 0x44) + if (nv_device(drm->device)->chipset < 0x44) NVWriteRAMDAC(dev, 0, NV_PRAMDAC_TEST_CONTROL + nv04_dac_output_offset(encoder), 0xf0000000); @@ -593,7 +611,7 @@ static void nv17_tv_commit(struct drm_encoder *encoder) helper->dpms(encoder, DRM_MODE_DPMS_ON); - NV_INFO(dev, "Output %s is running on CRTC %d using output %c\n", + NV_INFO(drm, "Output %s is running on CRTC %d using output %c\n", drm_get_connector_name( &nouveau_encoder_connector_get(nv_encoder)->base), nv_crtc->index, '@' + ffs(nv_encoder->dcb->or)); @@ -631,6 +649,7 @@ static int nv17_tv_create_resources(struct drm_encoder *encoder, struct drm_connector *connector) { struct drm_device *dev = encoder->dev; + struct nouveau_drm *drm = nouveau_drm(dev); struct drm_mode_config *conf = &dev->mode_config; struct nv17_tv_encoder *tv_enc = to_tv_enc(encoder); struct dcb_output *dcb = nouveau_encoder(encoder)->dcb; @@ -647,7 +666,7 @@ static int nv17_tv_create_resources(struct drm_encoder *encoder, } if (i == num_tv_norms) - NV_WARN(dev, "Invalid TV norm setting \"%s\"\n", + NV_WARN(drm, "Invalid TV norm setting \"%s\"\n", nouveau_tv_norm); } @@ -760,8 +779,6 @@ static void nv17_tv_destroy(struct drm_encoder *encoder) { struct nv17_tv_encoder *tv_enc = to_tv_enc(encoder); - NV_DEBUG_KMS(encoder->dev, "\n"); - drm_encoder_cleanup(encoder); kfree(tv_enc); } diff --git a/drivers/gpu/drm/nouveau/nv17_tv.h b/drivers/gpu/drm/nouveau/nv17_tv.h index 622e72221682..7b331543a41b 100644 --- a/drivers/gpu/drm/nouveau/nv17_tv.h +++ b/drivers/gpu/drm/nouveau/nv17_tv.h @@ -130,12 +130,14 @@ void nv17_ctv_update_rescaler(struct drm_encoder *encoder); static inline void nv_write_ptv(struct drm_device *dev, uint32_t reg, uint32_t val) { - nv_wr32(dev, reg, val); + struct nouveau_device *device = nouveau_dev(dev); + nv_wr32(device, reg, val); } static inline uint32_t nv_read_ptv(struct drm_device *dev, uint32_t reg) { - return nv_rd32(dev, reg); + struct nouveau_device *device = nouveau_dev(dev); + return nv_rd32(device, reg); } static inline void nv_write_tv_enc(struct drm_device *dev, uint8_t reg, diff --git a/drivers/gpu/drm/nouveau/nv17_tv_modes.c b/drivers/gpu/drm/nouveau/nv17_tv_modes.c index 381d388def3a..a4c4b0c2c7ce 100644 --- a/drivers/gpu/drm/nouveau/nv17_tv_modes.c +++ b/drivers/gpu/drm/nouveau/nv17_tv_modes.c @@ -26,7 +26,7 @@ #include "drmP.h" #include "drm_crtc_helper.h" -#include "nouveau_drv.h" +#include "nouveau_drm.h" #include "nouveau_encoder.h" #include "nouveau_crtc.h" #include "nouveau_hw.h" diff --git a/drivers/gpu/drm/nouveau/nv40_pm.c b/drivers/gpu/drm/nouveau/nv40_pm.c index 93f536de3779..23f200630d8b 100644 --- a/drivers/gpu/drm/nouveau/nv40_pm.c +++ b/drivers/gpu/drm/nouveau/nv40_pm.c @@ -23,17 +23,24 @@ */ #include "drmP.h" -#include "nouveau_drv.h" -#include +#include "nouveau_drm.h" +#include "nouveau_bios.h" #include "nouveau_pm.h" #include "nouveau_hw.h" +#include +#include +#include + +#include + #define min2(a,b) ((a) < (b) ? (a) : (b)) static u32 read_pll_1(struct drm_device *dev, u32 reg) { - u32 ctrl = nv_rd32(dev, reg + 0x00); + struct nouveau_device *device = nouveau_dev(dev); + u32 ctrl = nv_rd32(device, reg + 0x00); int P = (ctrl & 0x00070000) >> 16; int N = (ctrl & 0x0000ff00) >> 8; int M = (ctrl & 0x000000ff) >> 0; @@ -48,8 +55,9 @@ read_pll_1(struct drm_device *dev, u32 reg) static u32 read_pll_2(struct drm_device *dev, u32 reg) { - u32 ctrl = nv_rd32(dev, reg + 0x00); - u32 coef = nv_rd32(dev, reg + 0x04); + struct nouveau_device *device = nouveau_dev(dev); + u32 ctrl = nv_rd32(device, reg + 0x00); + u32 coef = nv_rd32(device, reg + 0x04); int N2 = (coef & 0xff000000) >> 24; int M2 = (coef & 0x00ff0000) >> 16; int N1 = (coef & 0x0000ff00) >> 8; @@ -88,7 +96,8 @@ read_clk(struct drm_device *dev, u32 src) int nv40_pm_clocks_get(struct drm_device *dev, struct nouveau_pm_level *perflvl) { - u32 ctrl = nv_rd32(dev, 0x00c040); + struct nouveau_device *device = nouveau_dev(dev); + u32 ctrl = nv_rd32(device, 0x00c040); perflvl->core = read_clk(dev, (ctrl & 0x00000003) >> 0); perflvl->shader = read_clk(dev, (ctrl & 0x00000030) >> 4); @@ -109,17 +118,20 @@ static int nv40_calc_pll(struct drm_device *dev, u32 reg, struct nvbios_pll *pll, u32 clk, int *N1, int *M1, int *N2, int *M2, int *log2P) { + struct nouveau_device *device = nouveau_dev(dev); + struct nouveau_bios *bios = nouveau_bios(device); + struct nouveau_clock *pclk = nouveau_clock(device); struct nouveau_pll_vals coef; int ret; - ret = get_pll_limits(dev, reg, pll); + ret = nvbios_pll_parse(bios, reg, pll); if (ret) return ret; if (clk < pll->vco1.max_freq) pll->vco2.max_freq = 0; - ret = nouveau_calc_pll_mnp(dev, pll, clk, &coef); + pclk->pll_calc(pclk, pll, clk, &coef); if (ret == 0) return -ERANGE; @@ -211,12 +223,13 @@ static bool nv40_pm_gr_idle(void *data) { struct drm_device *dev = data; + struct nouveau_device *device = nouveau_dev(dev); - if ((nv_rd32(dev, 0x400760) & 0x000000f0) >> 4 != - (nv_rd32(dev, 0x400760) & 0x0000000f)) + if ((nv_rd32(device, 0x400760) & 0x000000f0) >> 4 != + (nv_rd32(device, 0x400760) & 0x0000000f)) return false; - if (nv_rd32(dev, 0x400700)) + if (nv_rd32(device, 0x400700)) return false; return true; @@ -225,7 +238,9 @@ nv40_pm_gr_idle(void *data) int nv40_pm_clocks_set(struct drm_device *dev, void *pre_state) { - struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_device *device = nouveau_dev(dev); + struct nouveau_fifo *pfifo = nouveau_fifo(device); + struct nouveau_drm *drm = nouveau_drm(dev); struct nv40_pm_state *info = pre_state; unsigned long flags; struct bit_entry M; @@ -235,12 +250,12 @@ nv40_pm_clocks_set(struct drm_device *dev, void *pre_state) /* determine which CRTCs are active, fetch VGA_SR1 for each */ for (i = 0; i < 2; i++) { - u32 vbl = nv_rd32(dev, 0x600808 + (i * 0x2000)); + u32 vbl = nv_rd32(device, 0x600808 + (i * 0x2000)); u32 cnt = 0; do { - if (vbl != nv_rd32(dev, 0x600808 + (i * 0x2000))) { - nv_wr08(dev, 0x0c03c4 + (i * 0x2000), 0x01); - sr1[i] = nv_rd08(dev, 0x0c03c5 + (i * 0x2000)); + if (vbl != nv_rd32(device, 0x600808 + (i * 0x2000))) { + nv_wr08(device, 0x0c03c4 + (i * 0x2000), 0x01); + sr1[i] = nv_rd08(device, 0x0c03c5 + (i * 0x2000)); if (!(sr1[i] & 0x20)) crtc_mask |= (1 << i); break; @@ -250,28 +265,20 @@ nv40_pm_clocks_set(struct drm_device *dev, void *pre_state) } /* halt and idle engines */ - spin_lock_irqsave(&dev_priv->context_switch_lock, flags); - nv_mask(dev, 0x002500, 0x00000001, 0x00000000); - if (!nv_wait(dev, 0x002500, 0x00000010, 0x00000000)) - goto resume; - nv_mask(dev, 0x003220, 0x00000001, 0x00000000); - if (!nv_wait(dev, 0x003220, 0x00000010, 0x00000000)) - goto resume; - nv_mask(dev, 0x003200, 0x00000001, 0x00000000); - //XXX: nv04_fifo_cache_pull(dev, false); + pfifo->pause(pfifo, &flags); - if (!nv_wait_cb(dev, nv40_pm_gr_idle, dev)) + if (!nv_wait_cb(device, nv40_pm_gr_idle, dev)) goto resume; ret = 0; /* set engine clocks */ - nv_mask(dev, 0x00c040, 0x00000333, 0x00000000); - nv_wr32(dev, 0x004004, info->npll_coef); - nv_mask(dev, 0x004000, 0xc0070100, info->npll_ctrl); - nv_mask(dev, 0x004008, 0xc007ffff, info->spll); + nv_mask(device, 0x00c040, 0x00000333, 0x00000000); + nv_wr32(device, 0x004004, info->npll_coef); + nv_mask(device, 0x004000, 0xc0070100, info->npll_ctrl); + nv_mask(device, 0x004008, 0xc007ffff, info->spll); mdelay(5); - nv_mask(dev, 0x00c040, 0x00000333, info->ctrl); + nv_mask(device, 0x00c040, 0x00000333, info->ctrl); if (!info->mpll_ctrl) goto resume; @@ -280,52 +287,52 @@ nv40_pm_clocks_set(struct drm_device *dev, void *pre_state) for (i = 0; i < 2; i++) { if (!(crtc_mask & (1 << i))) continue; - nv_wait(dev, 0x600808 + (i * 0x2000), 0x00010000, 0x00000000); - nv_wait(dev, 0x600808 + (i * 0x2000), 0x00010000, 0x00010000); - nv_wr08(dev, 0x0c03c4 + (i * 0x2000), 0x01); - nv_wr08(dev, 0x0c03c5 + (i * 0x2000), sr1[i] | 0x20); + nv_wait(device, 0x600808 + (i * 0x2000), 0x00010000, 0x00000000); + nv_wait(device, 0x600808 + (i * 0x2000), 0x00010000, 0x00010000); + nv_wr08(device, 0x0c03c4 + (i * 0x2000), 0x01); + nv_wr08(device, 0x0c03c5 + (i * 0x2000), sr1[i] | 0x20); } /* prepare ram for reclocking */ - nv_wr32(dev, 0x1002d4, 0x00000001); /* precharge */ - nv_wr32(dev, 0x1002d0, 0x00000001); /* refresh */ - nv_wr32(dev, 0x1002d0, 0x00000001); /* refresh */ - nv_mask(dev, 0x100210, 0x80000000, 0x00000000); /* no auto refresh */ - nv_wr32(dev, 0x1002dc, 0x00000001); /* enable self-refresh */ + nv_wr32(device, 0x1002d4, 0x00000001); /* precharge */ + nv_wr32(device, 0x1002d0, 0x00000001); /* refresh */ + nv_wr32(device, 0x1002d0, 0x00000001); /* refresh */ + nv_mask(device, 0x100210, 0x80000000, 0x00000000); /* no auto refresh */ + nv_wr32(device, 0x1002dc, 0x00000001); /* enable self-refresh */ /* change the PLL of each memory partition */ - nv_mask(dev, 0x00c040, 0x0000c000, 0x00000000); - switch (dev_priv->chipset) { + nv_mask(device, 0x00c040, 0x0000c000, 0x00000000); + switch (nv_device(drm->device)->chipset) { case 0x40: case 0x45: case 0x41: case 0x42: case 0x47: - nv_mask(dev, 0x004044, 0xc0771100, info->mpll_ctrl); - nv_mask(dev, 0x00402c, 0xc0771100, info->mpll_ctrl); - nv_wr32(dev, 0x004048, info->mpll_coef); - nv_wr32(dev, 0x004030, info->mpll_coef); + nv_mask(device, 0x004044, 0xc0771100, info->mpll_ctrl); + nv_mask(device, 0x00402c, 0xc0771100, info->mpll_ctrl); + nv_wr32(device, 0x004048, info->mpll_coef); + nv_wr32(device, 0x004030, info->mpll_coef); case 0x43: case 0x49: case 0x4b: - nv_mask(dev, 0x004038, 0xc0771100, info->mpll_ctrl); - nv_wr32(dev, 0x00403c, info->mpll_coef); + nv_mask(device, 0x004038, 0xc0771100, info->mpll_ctrl); + nv_wr32(device, 0x00403c, info->mpll_coef); default: - nv_mask(dev, 0x004020, 0xc0771100, info->mpll_ctrl); - nv_wr32(dev, 0x004024, info->mpll_coef); + nv_mask(device, 0x004020, 0xc0771100, info->mpll_ctrl); + nv_wr32(device, 0x004024, info->mpll_coef); break; } udelay(100); - nv_mask(dev, 0x00c040, 0x0000c000, 0x0000c000); + nv_mask(device, 0x00c040, 0x0000c000, 0x0000c000); /* re-enable normal operation of memory controller */ - nv_wr32(dev, 0x1002dc, 0x00000000); - nv_mask(dev, 0x100210, 0x80000000, 0x80000000); + nv_wr32(device, 0x1002dc, 0x00000000); + nv_mask(device, 0x100210, 0x80000000, 0x80000000); udelay(100); /* execute memory reset script from vbios */ if (!bit_table(dev, 'M', &M)) - nouveau_bios_init_exec(dev, ROM16(M.data[0])); + nouveau_bios_run_init_table(dev, ROM16(M.data[0]), NULL, 0); /* make sure we're in vblank (hopefully the same one as before), and * then re-enable crtc memory access @@ -333,19 +340,14 @@ nv40_pm_clocks_set(struct drm_device *dev, void *pre_state) for (i = 0; i < 2; i++) { if (!(crtc_mask & (1 << i))) continue; - nv_wait(dev, 0x600808 + (i * 0x2000), 0x00010000, 0x00010000); - nv_wr08(dev, 0x0c03c4 + (i * 0x2000), 0x01); - nv_wr08(dev, 0x0c03c5 + (i * 0x2000), sr1[i]); + nv_wait(device, 0x600808 + (i * 0x2000), 0x00010000, 0x00010000); + nv_wr08(device, 0x0c03c4 + (i * 0x2000), 0x01); + nv_wr08(device, 0x0c03c5 + (i * 0x2000), sr1[i]); } /* resume engines */ resume: - nv_wr32(dev, 0x003250, 0x00000001); - nv_mask(dev, 0x003220, 0x00000001, 0x00000001); - nv_wr32(dev, 0x003200, 0x00000001); - nv_wr32(dev, 0x002500, 0x00000001); - spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags); - + pfifo->start(pfifo, &flags); kfree(info); return ret; } @@ -353,8 +355,11 @@ resume: int nv40_pm_pwm_get(struct drm_device *dev, int line, u32 *divs, u32 *duty) { + struct nouveau_drm *drm = nouveau_drm(dev); + struct nouveau_device *device = nouveau_dev(dev); + if (line == 2) { - u32 reg = nv_rd32(dev, 0x0010f0); + u32 reg = nv_rd32(device, 0x0010f0); if (reg & 0x80000000) { *duty = (reg & 0x7fff0000) >> 16; *divs = (reg & 0x00007fff); @@ -362,14 +367,14 @@ nv40_pm_pwm_get(struct drm_device *dev, int line, u32 *divs, u32 *duty) } } else if (line == 9) { - u32 reg = nv_rd32(dev, 0x0015f4); + u32 reg = nv_rd32(device, 0x0015f4); if (reg & 0x80000000) { - *divs = nv_rd32(dev, 0x0015f8); + *divs = nv_rd32(device, 0x0015f8); *duty = (reg & 0x7fffffff); return 0; } } else { - NV_ERROR(dev, "unknown pwm ctrl for gpio %d\n", line); + NV_ERROR(drm, "unknown pwm ctrl for gpio %d\n", line); return -ENODEV; } @@ -379,14 +384,17 @@ nv40_pm_pwm_get(struct drm_device *dev, int line, u32 *divs, u32 *duty) int nv40_pm_pwm_set(struct drm_device *dev, int line, u32 divs, u32 duty) { + struct nouveau_device *device = nouveau_dev(dev); + struct nouveau_drm *drm = nouveau_drm(dev); + if (line == 2) { - nv_wr32(dev, 0x0010f0, 0x80000000 | (duty << 16) | divs); + nv_wr32(device, 0x0010f0, 0x80000000 | (duty << 16) | divs); } else if (line == 9) { - nv_wr32(dev, 0x0015f8, divs); - nv_wr32(dev, 0x0015f4, duty | 0x80000000); + nv_wr32(device, 0x0015f8, divs); + nv_wr32(device, 0x0015f4, duty | 0x80000000); } else { - NV_ERROR(dev, "unknown pwm ctrl for gpio %d\n", line); + NV_ERROR(drm, "unknown pwm ctrl for gpio %d\n", line); return -ENODEV; } diff --git a/drivers/gpu/drm/nouveau/nv50_crtc.c b/drivers/gpu/drm/nouveau/nv50_crtc.c index 40042c1bbc6e..a771e9067ebf 100644 --- a/drivers/gpu/drm/nouveau/nv50_crtc.c +++ b/drivers/gpu/drm/nouveau/nv50_crtc.c @@ -28,24 +28,27 @@ #include "drm_mode.h" #include "drm_crtc_helper.h" -#define NOUVEAU_DMA_DEBUG (nouveau_reg_debug & NOUVEAU_REG_DEBUG_EVO) #include "nouveau_reg.h" -#include "nouveau_drv.h" +#include "nouveau_drm.h" +#include "nouveau_dma.h" +#include "nouveau_gem.h" #include "nouveau_hw.h" #include "nouveau_encoder.h" #include "nouveau_crtc.h" -#include "nouveau_fb.h" #include "nouveau_connector.h" #include "nv50_display.h" +#include + static void nv50_crtc_lut_load(struct drm_crtc *crtc) { + struct nouveau_drm *drm = nouveau_drm(crtc->dev); struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); void __iomem *lut = nvbo_kmap_obj_iovirtual(nv_crtc->lut.nvbo); int i; - NV_DEBUG_KMS(crtc->dev, "\n"); + NV_DEBUG(drm, "\n"); for (i = 0; i < 256; i++) { writew(nv_crtc->lut.r[i] >> 2, lut + 8*i + 0); @@ -64,25 +67,25 @@ int nv50_crtc_blank(struct nouveau_crtc *nv_crtc, bool blanked) { struct drm_device *dev = nv_crtc->base.dev; - struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_drm *drm = nouveau_drm(dev); struct nouveau_channel *evo = nv50_display(dev)->master; int index = nv_crtc->index, ret; - NV_DEBUG_KMS(dev, "index %d\n", nv_crtc->index); - NV_DEBUG_KMS(dev, "%s\n", blanked ? "blanked" : "unblanked"); + NV_DEBUG(drm, "index %d\n", nv_crtc->index); + NV_DEBUG(drm, "%s\n", blanked ? "blanked" : "unblanked"); if (blanked) { nv_crtc->cursor.hide(nv_crtc, false); - ret = RING_SPACE(evo, dev_priv->chipset != 0x50 ? 7 : 5); + ret = RING_SPACE(evo, nv_device(drm->device)->chipset != 0x50 ? 7 : 5); if (ret) { - NV_ERROR(dev, "no space while blanking crtc\n"); + NV_ERROR(drm, "no space while blanking crtc\n"); return ret; } BEGIN_NV04(evo, 0, NV50_EVO_CRTC(index, CLUT_MODE), 2); OUT_RING(evo, NV50_EVO_CRTC_CLUT_MODE_BLANK); OUT_RING(evo, 0); - if (dev_priv->chipset != 0x50) { + if (nv_device(drm->device)->chipset != 0x50) { BEGIN_NV04(evo, 0, NV84_EVO_CRTC(index, CLUT_DMA), 1); OUT_RING(evo, NV84_EVO_CRTC_CLUT_DMA_HANDLE_NONE); } @@ -95,9 +98,9 @@ nv50_crtc_blank(struct nouveau_crtc *nv_crtc, bool blanked) else nv_crtc->cursor.hide(nv_crtc, false); - ret = RING_SPACE(evo, dev_priv->chipset != 0x50 ? 10 : 8); + ret = RING_SPACE(evo, nv_device(drm->device)->chipset != 0x50 ? 10 : 8); if (ret) { - NV_ERROR(dev, "no space while unblanking crtc\n"); + NV_ERROR(drm, "no space while unblanking crtc\n"); return ret; } BEGIN_NV04(evo, 0, NV50_EVO_CRTC(index, CLUT_MODE), 2); @@ -105,7 +108,7 @@ nv50_crtc_blank(struct nouveau_crtc *nv_crtc, bool blanked) NV50_EVO_CRTC_CLUT_MODE_OFF : NV50_EVO_CRTC_CLUT_MODE_ON); OUT_RING(evo, nv_crtc->lut.nvbo->bo.offset >> 8); - if (dev_priv->chipset != 0x50) { + if (nv_device(drm->device)->chipset != 0x50) { BEGIN_NV04(evo, 0, NV84_EVO_CRTC(index, CLUT_DMA), 1); OUT_RING(evo, NvEvoVRAM); } @@ -114,7 +117,7 @@ nv50_crtc_blank(struct nouveau_crtc *nv_crtc, bool blanked) OUT_RING(evo, nv_crtc->fb.offset >> 8); OUT_RING(evo, 0); BEGIN_NV04(evo, 0, NV50_EVO_CRTC(index, FB_DMA), 1); - if (dev_priv->chipset != 0x50) + if (nv_device(drm->device)->chipset != 0x50) if (nv_crtc->fb.tile_flags == 0x7a00 || nv_crtc->fb.tile_flags == 0xfe00) OUT_RING(evo, NvEvoFB32); @@ -174,17 +177,18 @@ static int nv50_crtc_set_color_vibrance(struct nouveau_crtc *nv_crtc, bool update) { struct drm_device *dev = nv_crtc->base.dev; + struct nouveau_drm *drm = nouveau_drm(dev); struct nouveau_channel *evo = nv50_display(dev)->master; int ret; int adj; u32 hue, vib; - NV_DEBUG_KMS(dev, "vibrance = %i, hue = %i\n", + NV_DEBUG(drm, "vibrance = %i, hue = %i\n", nv_crtc->color_vibrance, nv_crtc->vibrant_hue); ret = RING_SPACE(evo, 2 + (update ? 2 : 0)); if (ret) { - NV_ERROR(dev, "no space while setting color vibrance\n"); + NV_ERROR(drm, "no space while setting color vibrance\n"); return ret; } @@ -229,17 +233,18 @@ nv50_crtc_set_scale(struct nouveau_crtc *nv_crtc, bool update) struct nouveau_connector *nv_connector; struct drm_crtc *crtc = &nv_crtc->base; struct drm_device *dev = crtc->dev; + struct nouveau_drm *drm = nouveau_drm(dev); struct nouveau_channel *evo = nv50_display(dev)->master; struct drm_display_mode *umode = &crtc->mode; struct drm_display_mode *omode; int scaling_mode, ret; u32 ctrl = 0, oX, oY; - NV_DEBUG_KMS(dev, "\n"); + NV_DEBUG(drm, "\n"); nv_connector = nouveau_crtc_connector_get(nv_crtc); if (!nv_connector || !nv_connector->native_mode) { - NV_ERROR(dev, "no native mode, forcing panel scaling\n"); + NV_ERROR(drm, "no native mode, forcing panel scaling\n"); scaling_mode = DRM_MODE_SCALE_NONE; } else { scaling_mode = nv_connector->scaling_mode; @@ -329,15 +334,19 @@ nv50_crtc_set_scale(struct nouveau_crtc *nv_crtc, bool update) int nv50_crtc_set_clock(struct drm_device *dev, int head, int pclk) { - return setPLL(dev, PLL_VPLL0 + head, pclk); + struct nouveau_device *device = nouveau_dev(dev); + struct nouveau_clock *clk = nouveau_clock(device); + + return clk->pll_set(clk, PLL_VPLL0 + head, pclk); } static void nv50_crtc_destroy(struct drm_crtc *crtc) { struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); + struct nouveau_drm *drm = nouveau_drm(crtc->dev); - NV_DEBUG_KMS(crtc->dev, "\n"); + NV_DEBUG(drm, "\n"); nouveau_bo_unmap(nv_crtc->lut.nvbo); nouveau_bo_ref(NULL, &nv_crtc->lut.nvbo); @@ -426,13 +435,15 @@ nv50_crtc_gamma_set(struct drm_crtc *crtc, u16 *r, u16 *g, u16 *b, static void nv50_crtc_save(struct drm_crtc *crtc) { - NV_ERROR(crtc->dev, "!!\n"); + struct nouveau_drm *drm = nouveau_drm(crtc->dev); + NV_ERROR(drm, "!!\n"); } static void nv50_crtc_restore(struct drm_crtc *crtc) { - NV_ERROR(crtc->dev, "!!\n"); + struct nouveau_drm *drm = nouveau_drm(crtc->dev); + NV_ERROR(drm, "!!\n"); } static const struct drm_crtc_funcs nv50_crtc_funcs = { @@ -456,8 +467,9 @@ nv50_crtc_prepare(struct drm_crtc *crtc) { struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); struct drm_device *dev = crtc->dev; + struct nouveau_drm *drm = nouveau_drm(dev); - NV_DEBUG_KMS(dev, "index %d\n", nv_crtc->index); + NV_DEBUG(drm, "index %d\n", nv_crtc->index); nv50_display_flip_stop(crtc); drm_vblank_pre_modeset(dev, nv_crtc->index); @@ -468,9 +480,10 @@ static void nv50_crtc_commit(struct drm_crtc *crtc) { struct drm_device *dev = crtc->dev; + struct nouveau_drm *drm = nouveau_drm(dev); struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); - NV_DEBUG_KMS(dev, "index %d\n", nv_crtc->index); + NV_DEBUG(drm, "index %d\n", nv_crtc->index); nv50_crtc_blank(nv_crtc, false); drm_vblank_post_modeset(dev, nv_crtc->index); @@ -492,17 +505,17 @@ nv50_crtc_do_mode_set_base(struct drm_crtc *crtc, { struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); struct drm_device *dev = nv_crtc->base.dev; - struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_drm *drm = nouveau_drm(dev); struct nouveau_channel *evo = nv50_display(dev)->master; struct drm_framebuffer *drm_fb; struct nouveau_framebuffer *fb; int ret; - NV_DEBUG_KMS(dev, "index %d\n", nv_crtc->index); + NV_DEBUG(drm, "index %d\n", nv_crtc->index); /* no fb bound */ if (!atomic && !crtc->fb) { - NV_DEBUG_KMS(dev, "No FB bound\n"); + NV_DEBUG(drm, "No FB bound\n"); return 0; } @@ -532,7 +545,7 @@ nv50_crtc_do_mode_set_base(struct drm_crtc *crtc, nv_crtc->fb.offset = fb->nvbo->bo.offset; nv_crtc->fb.tile_flags = nouveau_bo_tile_layout(fb->nvbo); nv_crtc->fb.cpp = drm_fb->bits_per_pixel / 8; - if (!nv_crtc->fb.blanked && dev_priv->chipset != 0x50) { + if (!nv_crtc->fb.blanked && nv_device(drm->device)->chipset != 0x50) { ret = RING_SPACE(evo, 2); if (ret) return ret; @@ -690,10 +703,11 @@ static const struct drm_crtc_helper_funcs nv50_crtc_helper_funcs = { int nv50_crtc_create(struct drm_device *dev, int index) { + struct nouveau_drm *drm = nouveau_drm(dev); struct nouveau_crtc *nv_crtc = NULL; int ret, i; - NV_DEBUG_KMS(dev, "\n"); + NV_DEBUG(drm, "\n"); nv_crtc = kzalloc(sizeof(*nv_crtc), GFP_KERNEL); if (!nv_crtc) diff --git a/drivers/gpu/drm/nouveau/nv50_cursor.c b/drivers/gpu/drm/nouveau/nv50_cursor.c index af4ec7bf3670..ba047e9251b3 100644 --- a/drivers/gpu/drm/nouveau/nv50_cursor.c +++ b/drivers/gpu/drm/nouveau/nv50_cursor.c @@ -27,9 +27,8 @@ #include "drmP.h" #include "drm_mode.h" -#define NOUVEAU_DMA_DEBUG (nouveau_reg_debug & NOUVEAU_REG_DEBUG_EVO) -#include "nouveau_reg.h" -#include "nouveau_drv.h" +#include "nouveau_drm.h" +#include "nouveau_dma.h" #include "nouveau_crtc.h" #include "nv50_display.h" @@ -37,22 +36,22 @@ static void nv50_cursor_show(struct nouveau_crtc *nv_crtc, bool update) { struct drm_device *dev = nv_crtc->base.dev; - struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_drm *drm = nouveau_drm(dev); struct nouveau_channel *evo = nv50_display(dev)->master; int ret; - NV_DEBUG_KMS(dev, "\n"); + NV_DEBUG(drm, "\n"); if (update && nv_crtc->cursor.visible) return; - ret = RING_SPACE(evo, (dev_priv->chipset != 0x50 ? 5 : 3) + update * 2); + ret = RING_SPACE(evo, (nv_device(drm->device)->chipset != 0x50 ? 5 : 3) + update * 2); if (ret) { - NV_ERROR(dev, "no space while unhiding cursor\n"); + NV_ERROR(drm, "no space while unhiding cursor\n"); return; } - if (dev_priv->chipset != 0x50) { + if (nv_device(drm->device)->chipset != 0x50) { BEGIN_NV04(evo, 0, NV84_EVO_CRTC(nv_crtc->index, CURSOR_DMA), 1); OUT_RING(evo, NvEvoVRAM); } @@ -72,24 +71,24 @@ static void nv50_cursor_hide(struct nouveau_crtc *nv_crtc, bool update) { struct drm_device *dev = nv_crtc->base.dev; - struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_drm *drm = nouveau_drm(dev); struct nouveau_channel *evo = nv50_display(dev)->master; int ret; - NV_DEBUG_KMS(dev, "\n"); + NV_DEBUG(drm, "\n"); if (update && !nv_crtc->cursor.visible) return; - ret = RING_SPACE(evo, (dev_priv->chipset != 0x50 ? 5 : 3) + update * 2); + ret = RING_SPACE(evo, (nv_device(drm->device)->chipset != 0x50 ? 5 : 3) + update * 2); if (ret) { - NV_ERROR(dev, "no space while hiding cursor\n"); + NV_ERROR(drm, "no space while hiding cursor\n"); return; } BEGIN_NV04(evo, 0, NV50_EVO_CRTC(nv_crtc->index, CURSOR_CTRL), 2); OUT_RING(evo, NV50_EVO_CRTC_CURSOR_CTRL_HIDE); OUT_RING(evo, 0); - if (dev_priv->chipset != 0x50) { + if (nv_device(drm->device)->chipset != 0x50) { BEGIN_NV04(evo, 0, NV84_EVO_CRTC(nv_crtc->index, CURSOR_DMA), 1); OUT_RING(evo, NV84_EVO_CRTC_CURSOR_DMA_HANDLE_NONE); } @@ -105,19 +104,18 @@ nv50_cursor_hide(struct nouveau_crtc *nv_crtc, bool update) static void nv50_cursor_set_pos(struct nouveau_crtc *nv_crtc, int x, int y) { - struct drm_device *dev = nv_crtc->base.dev; + struct nouveau_device *device = nouveau_dev(nv_crtc->base.dev); nv_crtc->cursor_saved_x = x; nv_crtc->cursor_saved_y = y; - nv_wr32(dev, NV50_PDISPLAY_CURSOR_USER_POS(nv_crtc->index), + nv_wr32(device, NV50_PDISPLAY_CURSOR_USER_POS(nv_crtc->index), ((y & 0xFFFF) << 16) | (x & 0xFFFF)); /* Needed to make the cursor move. */ - nv_wr32(dev, NV50_PDISPLAY_CURSOR_USER_POS_CTRL(nv_crtc->index), 0); + nv_wr32(device, NV50_PDISPLAY_CURSOR_USER_POS_CTRL(nv_crtc->index), 0); } static void nv50_cursor_set_offset(struct nouveau_crtc *nv_crtc, uint32_t offset) { - NV_DEBUG_KMS(nv_crtc->base.dev, "\n"); if (offset == nv_crtc->cursor.offset) return; diff --git a/drivers/gpu/drm/nouveau/nv50_dac.c b/drivers/gpu/drm/nouveau/nv50_dac.c index dd3b8f2a3960..4a01b49d5ece 100644 --- a/drivers/gpu/drm/nouveau/nv50_dac.c +++ b/drivers/gpu/drm/nouveau/nv50_dac.c @@ -29,18 +29,21 @@ #define NOUVEAU_DMA_DEBUG (nouveau_reg_debug & NOUVEAU_REG_DEBUG_EVO) #include "nouveau_reg.h" -#include "nouveau_drv.h" +#include "nouveau_drm.h" #include "nouveau_dma.h" #include "nouveau_encoder.h" #include "nouveau_connector.h" #include "nouveau_crtc.h" #include "nv50_display.h" +#include + static void nv50_dac_disconnect(struct drm_encoder *encoder) { struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); struct drm_device *dev = encoder->dev; + struct nouveau_drm *drm = nouveau_drm(dev); struct nouveau_channel *evo = nv50_display(dev)->master; int ret; @@ -48,11 +51,11 @@ nv50_dac_disconnect(struct drm_encoder *encoder) return; nv50_crtc_blank(nouveau_crtc(nv_encoder->crtc), true); - NV_DEBUG_KMS(dev, "Disconnecting DAC %d\n", nv_encoder->or); + NV_DEBUG(drm, "Disconnecting DAC %d\n", nv_encoder->or); ret = RING_SPACE(evo, 4); if (ret) { - NV_ERROR(dev, "no space while disconnecting DAC\n"); + NV_ERROR(drm, "no space while disconnecting DAC\n"); return; } BEGIN_NV04(evo, 0, NV50_EVO_DAC(nv_encoder->or, MODE_CTRL), 1); @@ -67,43 +70,43 @@ static enum drm_connector_status nv50_dac_detect(struct drm_encoder *encoder, struct drm_connector *connector) { struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); - struct drm_device *dev = encoder->dev; - struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_device *device = nouveau_dev(encoder->dev); + struct nouveau_drm *drm = nouveau_drm(encoder->dev); enum drm_connector_status status = connector_status_disconnected; uint32_t dpms_state, load_pattern, load_state; int or = nv_encoder->or; - nv_wr32(dev, NV50_PDISPLAY_DAC_CLK_CTRL1(or), 0x00000001); - dpms_state = nv_rd32(dev, NV50_PDISPLAY_DAC_DPMS_CTRL(or)); + nv_wr32(device, NV50_PDISPLAY_DAC_CLK_CTRL1(or), 0x00000001); + dpms_state = nv_rd32(device, NV50_PDISPLAY_DAC_DPMS_CTRL(or)); - nv_wr32(dev, NV50_PDISPLAY_DAC_DPMS_CTRL(or), + nv_wr32(device, NV50_PDISPLAY_DAC_DPMS_CTRL(or), 0x00150000 | NV50_PDISPLAY_DAC_DPMS_CTRL_PENDING); - if (!nv_wait(dev, NV50_PDISPLAY_DAC_DPMS_CTRL(or), + if (!nv_wait(device, NV50_PDISPLAY_DAC_DPMS_CTRL(or), NV50_PDISPLAY_DAC_DPMS_CTRL_PENDING, 0)) { - NV_ERROR(dev, "timeout: DAC_DPMS_CTRL_PENDING(%d) == 0\n", or); - NV_ERROR(dev, "DAC_DPMS_CTRL(%d) = 0x%08x\n", or, - nv_rd32(dev, NV50_PDISPLAY_DAC_DPMS_CTRL(or))); + NV_ERROR(drm, "timeout: DAC_DPMS_CTRL_PENDING(%d) == 0\n", or); + NV_ERROR(drm, "DAC_DPMS_CTRL(%d) = 0x%08x\n", or, + nv_rd32(device, NV50_PDISPLAY_DAC_DPMS_CTRL(or))); return status; } /* Use bios provided value if possible. */ - if (dev_priv->vbios.dactestval) { - load_pattern = dev_priv->vbios.dactestval; - NV_DEBUG_KMS(dev, "Using bios provided load_pattern of %d\n", + if (drm->vbios.dactestval) { + load_pattern = drm->vbios.dactestval; + NV_DEBUG(drm, "Using bios provided load_pattern of %d\n", load_pattern); } else { load_pattern = 340; - NV_DEBUG_KMS(dev, "Using default load_pattern of %d\n", + NV_DEBUG(drm, "Using default load_pattern of %d\n", load_pattern); } - nv_wr32(dev, NV50_PDISPLAY_DAC_LOAD_CTRL(or), + nv_wr32(device, NV50_PDISPLAY_DAC_LOAD_CTRL(or), NV50_PDISPLAY_DAC_LOAD_CTRL_ACTIVE | load_pattern); mdelay(45); /* give it some time to process */ - load_state = nv_rd32(dev, NV50_PDISPLAY_DAC_LOAD_CTRL(or)); + load_state = nv_rd32(device, NV50_PDISPLAY_DAC_LOAD_CTRL(or)); - nv_wr32(dev, NV50_PDISPLAY_DAC_LOAD_CTRL(or), 0); - nv_wr32(dev, NV50_PDISPLAY_DAC_DPMS_CTRL(or), dpms_state | + nv_wr32(device, NV50_PDISPLAY_DAC_LOAD_CTRL(or), 0); + nv_wr32(device, NV50_PDISPLAY_DAC_DPMS_CTRL(or), dpms_state | NV50_PDISPLAY_DAC_DPMS_CTRL_PENDING); if ((load_state & NV50_PDISPLAY_DAC_LOAD_CTRL_PRESENT) == @@ -111,9 +114,9 @@ nv50_dac_detect(struct drm_encoder *encoder, struct drm_connector *connector) status = connector_status_connected; if (status == connector_status_connected) - NV_DEBUG_KMS(dev, "Load was detected on output with or %d\n", or); + NV_DEBUG(drm, "Load was detected on output with or %d\n", or); else - NV_DEBUG_KMS(dev, "Load was not detected on output with or %d\n", or); + NV_DEBUG(drm, "Load was not detected on output with or %d\n", or); return status; } @@ -121,23 +124,24 @@ nv50_dac_detect(struct drm_encoder *encoder, struct drm_connector *connector) static void nv50_dac_dpms(struct drm_encoder *encoder, int mode) { - struct drm_device *dev = encoder->dev; + struct nouveau_device *device = nouveau_dev(encoder->dev); + struct nouveau_drm *drm = nouveau_drm(encoder->dev); struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); uint32_t val; int or = nv_encoder->or; - NV_DEBUG_KMS(dev, "or %d mode %d\n", or, mode); + NV_DEBUG(drm, "or %d mode %d\n", or, mode); /* wait for it to be done */ - if (!nv_wait(dev, NV50_PDISPLAY_DAC_DPMS_CTRL(or), + if (!nv_wait(device, NV50_PDISPLAY_DAC_DPMS_CTRL(or), NV50_PDISPLAY_DAC_DPMS_CTRL_PENDING, 0)) { - NV_ERROR(dev, "timeout: DAC_DPMS_CTRL_PENDING(%d) == 0\n", or); - NV_ERROR(dev, "DAC_DPMS_CTRL(%d) = 0x%08x\n", or, - nv_rd32(dev, NV50_PDISPLAY_DAC_DPMS_CTRL(or))); + NV_ERROR(drm, "timeout: DAC_DPMS_CTRL_PENDING(%d) == 0\n", or); + NV_ERROR(drm, "DAC_DPMS_CTRL(%d) = 0x%08x\n", or, + nv_rd32(device, NV50_PDISPLAY_DAC_DPMS_CTRL(or))); return; } - val = nv_rd32(dev, NV50_PDISPLAY_DAC_DPMS_CTRL(or)) & ~0x7F; + val = nv_rd32(device, NV50_PDISPLAY_DAC_DPMS_CTRL(or)) & ~0x7F; if (mode != DRM_MODE_DPMS_ON) val |= NV50_PDISPLAY_DAC_DPMS_CTRL_BLANKED; @@ -158,20 +162,22 @@ nv50_dac_dpms(struct drm_encoder *encoder, int mode) break; } - nv_wr32(dev, NV50_PDISPLAY_DAC_DPMS_CTRL(or), val | + nv_wr32(device, NV50_PDISPLAY_DAC_DPMS_CTRL(or), val | NV50_PDISPLAY_DAC_DPMS_CTRL_PENDING); } static void nv50_dac_save(struct drm_encoder *encoder) { - NV_ERROR(encoder->dev, "!!\n"); + struct nouveau_drm *drm = nouveau_drm(encoder->dev); + NV_ERROR(drm, "!!\n"); } static void nv50_dac_restore(struct drm_encoder *encoder) { - NV_ERROR(encoder->dev, "!!\n"); + struct nouveau_drm *drm = nouveau_drm(encoder->dev); + NV_ERROR(drm, "!!\n"); } static bool @@ -179,14 +185,15 @@ nv50_dac_mode_fixup(struct drm_encoder *encoder, const struct drm_display_mode *mode, struct drm_display_mode *adjusted_mode) { + struct nouveau_drm *drm = nouveau_drm(encoder->dev); struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); struct nouveau_connector *connector; - NV_DEBUG_KMS(encoder->dev, "or %d\n", nv_encoder->or); + NV_DEBUG(drm, "or %d\n", nv_encoder->or); connector = nouveau_encoder_connector_get(nv_encoder); if (!connector) { - NV_ERROR(encoder->dev, "Encoder has no connector\n"); + NV_ERROR(drm, "Encoder has no connector\n"); return false; } @@ -207,13 +214,14 @@ nv50_dac_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode, struct drm_display_mode *adjusted_mode) { struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); + struct nouveau_drm *drm = nouveau_drm(encoder->dev); struct drm_device *dev = encoder->dev; struct nouveau_channel *evo = nv50_display(dev)->master; struct nouveau_crtc *crtc = nouveau_crtc(encoder->crtc); uint32_t mode_ctl = 0, mode_ctl2 = 0; int ret; - NV_DEBUG_KMS(dev, "or %d type %d crtc %d\n", + NV_DEBUG(drm, "or %d type %d crtc %d\n", nv_encoder->or, nv_encoder->dcb->type, crtc->index); nv50_dac_dpms(encoder, DRM_MODE_DPMS_ON); @@ -238,7 +246,7 @@ nv50_dac_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode, ret = RING_SPACE(evo, 3); if (ret) { - NV_ERROR(dev, "no space while connecting DAC\n"); + NV_ERROR(drm, "no space while connecting DAC\n"); return; } BEGIN_NV04(evo, 0, NV50_EVO_DAC(nv_encoder->or, MODE_CTRL), 2); @@ -271,11 +279,12 @@ static void nv50_dac_destroy(struct drm_encoder *encoder) { struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); + struct nouveau_drm *drm = nouveau_drm(encoder->dev); if (!encoder) return; - NV_DEBUG_KMS(encoder->dev, "\n"); + NV_DEBUG(drm, "\n"); drm_encoder_cleanup(encoder); kfree(nv_encoder); diff --git a/drivers/gpu/drm/nouveau/nv50_display.c b/drivers/gpu/drm/nouveau/nv50_display.c index ae72f7656106..787ddc9f314c 100644 --- a/drivers/gpu/drm/nouveau/nv50_display.c +++ b/drivers/gpu/drm/nouveau/nv50_display.c @@ -24,27 +24,30 @@ * */ -#define NOUVEAU_DMA_DEBUG (nouveau_reg_debug & NOUVEAU_REG_DEBUG_EVO) +#include "nouveau_drm.h" +#include "nouveau_dma.h" + #include "nv50_display.h" #include "nouveau_crtc.h" #include "nouveau_encoder.h" #include "nouveau_connector.h" -#include "nouveau_fb.h" #include "nouveau_fbcon.h" #include "drm_crtc_helper.h" #include "nouveau_fence.h" -static void nv50_display_isr(struct drm_device *); +#include +#include + static void nv50_display_bh(unsigned long); static inline int nv50_sor_nr(struct drm_device *dev) { - struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_device *device = nouveau_dev(dev); - if (dev_priv->chipset < 0x90 || - dev_priv->chipset == 0x92 || - dev_priv->chipset == 0xa0) + if (device->chipset < 0x90 || + device->chipset == 0x92 || + device->chipset == 0xa0) return 2; return 4; @@ -53,22 +56,22 @@ nv50_sor_nr(struct drm_device *dev) u32 nv50_display_active_crtcs(struct drm_device *dev) { - struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_device *device = nouveau_dev(dev); u32 mask = 0; int i; - if (dev_priv->chipset < 0x90 || - dev_priv->chipset == 0x92 || - dev_priv->chipset == 0xa0) { + if (device->chipset < 0x90 || + device->chipset == 0x92 || + device->chipset == 0xa0) { for (i = 0; i < 2; i++) - mask |= nv_rd32(dev, NV50_PDISPLAY_SOR_MODE_CTRL_C(i)); + mask |= nv_rd32(device, NV50_PDISPLAY_SOR_MODE_CTRL_C(i)); } else { for (i = 0; i < 4; i++) - mask |= nv_rd32(dev, NV90_PDISPLAY_SOR_MODE_CTRL_C(i)); + mask |= nv_rd32(device, NV90_PDISPLAY_SOR_MODE_CTRL_C(i)); } for (i = 0; i < 3; i++) - mask |= nv_rd32(dev, NV50_PDISPLAY_DAC_MODE_CTRL_C(i)); + mask |= nv_rd32(device, NV50_PDISPLAY_DAC_MODE_CTRL_C(i)); return mask & 3; } @@ -89,7 +92,6 @@ nv50_display_sync(struct drm_device *dev) { struct nv50_display *disp = nv50_display(dev); struct nouveau_channel *evo = disp->master; - u64 start; int ret; ret = RING_SPACE(evo, 6); @@ -104,11 +106,8 @@ nv50_display_sync(struct drm_device *dev) nv_wo32(disp->ramin, 0x2000, 0x00000000); FIRE_RING (evo); - start = nv_timer_read(dev); - do { - if (nv_ro32(disp->ramin, 0x2000)) - return 0; - } while (nv_timer_read(dev) - start < 2000000000ULL); + if (nv_wait_ne(disp->ramin, 0x2000, 0xffffffff, 0x00000000)) + return 0; } return 0; @@ -117,13 +116,15 @@ nv50_display_sync(struct drm_device *dev) int nv50_display_init(struct drm_device *dev) { + struct nouveau_drm *drm = nouveau_drm(dev); + struct nouveau_device *device = nouveau_dev(dev); struct nouveau_channel *evo; int ret, i; u32 val; - NV_DEBUG_KMS(dev, "\n"); + NV_DEBUG(drm, "\n"); - nv_wr32(dev, 0x00610184, nv_rd32(dev, 0x00614004)); + nv_wr32(device, 0x00610184, nv_rd32(device, 0x00614004)); /* * I think the 0x006101XX range is some kind of main control area @@ -131,82 +132,82 @@ nv50_display_init(struct drm_device *dev) */ /* CRTC? */ for (i = 0; i < 2; i++) { - val = nv_rd32(dev, 0x00616100 + (i * 0x800)); - nv_wr32(dev, 0x00610190 + (i * 0x10), val); - val = nv_rd32(dev, 0x00616104 + (i * 0x800)); - nv_wr32(dev, 0x00610194 + (i * 0x10), val); - val = nv_rd32(dev, 0x00616108 + (i * 0x800)); - nv_wr32(dev, 0x00610198 + (i * 0x10), val); - val = nv_rd32(dev, 0x0061610c + (i * 0x800)); - nv_wr32(dev, 0x0061019c + (i * 0x10), val); + val = nv_rd32(device, 0x00616100 + (i * 0x800)); + nv_wr32(device, 0x00610190 + (i * 0x10), val); + val = nv_rd32(device, 0x00616104 + (i * 0x800)); + nv_wr32(device, 0x00610194 + (i * 0x10), val); + val = nv_rd32(device, 0x00616108 + (i * 0x800)); + nv_wr32(device, 0x00610198 + (i * 0x10), val); + val = nv_rd32(device, 0x0061610c + (i * 0x800)); + nv_wr32(device, 0x0061019c + (i * 0x10), val); } /* DAC */ for (i = 0; i < 3; i++) { - val = nv_rd32(dev, 0x0061a000 + (i * 0x800)); - nv_wr32(dev, 0x006101d0 + (i * 0x04), val); + val = nv_rd32(device, 0x0061a000 + (i * 0x800)); + nv_wr32(device, 0x006101d0 + (i * 0x04), val); } /* SOR */ for (i = 0; i < nv50_sor_nr(dev); i++) { - val = nv_rd32(dev, 0x0061c000 + (i * 0x800)); - nv_wr32(dev, 0x006101e0 + (i * 0x04), val); + val = nv_rd32(device, 0x0061c000 + (i * 0x800)); + nv_wr32(device, 0x006101e0 + (i * 0x04), val); } /* EXT */ for (i = 0; i < 3; i++) { - val = nv_rd32(dev, 0x0061e000 + (i * 0x800)); - nv_wr32(dev, 0x006101f0 + (i * 0x04), val); + val = nv_rd32(device, 0x0061e000 + (i * 0x800)); + nv_wr32(device, 0x006101f0 + (i * 0x04), val); } for (i = 0; i < 3; i++) { - nv_wr32(dev, NV50_PDISPLAY_DAC_DPMS_CTRL(i), 0x00550000 | + nv_wr32(device, NV50_PDISPLAY_DAC_DPMS_CTRL(i), 0x00550000 | NV50_PDISPLAY_DAC_DPMS_CTRL_PENDING); - nv_wr32(dev, NV50_PDISPLAY_DAC_CLK_CTRL1(i), 0x00000001); + nv_wr32(device, NV50_PDISPLAY_DAC_CLK_CTRL1(i), 0x00000001); } /* The precise purpose is unknown, i suspect it has something to do * with text mode. */ - if (nv_rd32(dev, NV50_PDISPLAY_INTR_1) & 0x100) { - nv_wr32(dev, NV50_PDISPLAY_INTR_1, 0x100); - nv_wr32(dev, 0x006194e8, nv_rd32(dev, 0x006194e8) & ~1); - if (!nv_wait(dev, 0x006194e8, 2, 0)) { - NV_ERROR(dev, "timeout: (0x6194e8 & 2) != 0\n"); - NV_ERROR(dev, "0x6194e8 = 0x%08x\n", - nv_rd32(dev, 0x6194e8)); + if (nv_rd32(device, NV50_PDISPLAY_INTR_1) & 0x100) { + nv_wr32(device, NV50_PDISPLAY_INTR_1, 0x100); + nv_wr32(device, 0x006194e8, nv_rd32(device, 0x006194e8) & ~1); + if (!nv_wait(device, 0x006194e8, 2, 0)) { + NV_ERROR(drm, "timeout: (0x6194e8 & 2) != 0\n"); + NV_ERROR(drm, "0x6194e8 = 0x%08x\n", + nv_rd32(device, 0x6194e8)); return -EBUSY; } } for (i = 0; i < 2; i++) { - nv_wr32(dev, NV50_PDISPLAY_CURSOR_CURSOR_CTRL2(i), 0x2000); - if (!nv_wait(dev, NV50_PDISPLAY_CURSOR_CURSOR_CTRL2(i), + nv_wr32(device, NV50_PDISPLAY_CURSOR_CURSOR_CTRL2(i), 0x2000); + if (!nv_wait(device, NV50_PDISPLAY_CURSOR_CURSOR_CTRL2(i), NV50_PDISPLAY_CURSOR_CURSOR_CTRL2_STATUS, 0)) { - NV_ERROR(dev, "timeout: CURSOR_CTRL2_STATUS == 0\n"); - NV_ERROR(dev, "CURSOR_CTRL2 = 0x%08x\n", - nv_rd32(dev, NV50_PDISPLAY_CURSOR_CURSOR_CTRL2(i))); + NV_ERROR(drm, "timeout: CURSOR_CTRL2_STATUS == 0\n"); + NV_ERROR(drm, "CURSOR_CTRL2 = 0x%08x\n", + nv_rd32(device, NV50_PDISPLAY_CURSOR_CURSOR_CTRL2(i))); return -EBUSY; } - nv_wr32(dev, NV50_PDISPLAY_CURSOR_CURSOR_CTRL2(i), + nv_wr32(device, NV50_PDISPLAY_CURSOR_CURSOR_CTRL2(i), NV50_PDISPLAY_CURSOR_CURSOR_CTRL2_ON); - if (!nv_wait(dev, NV50_PDISPLAY_CURSOR_CURSOR_CTRL2(i), + if (!nv_wait(device, NV50_PDISPLAY_CURSOR_CURSOR_CTRL2(i), NV50_PDISPLAY_CURSOR_CURSOR_CTRL2_STATUS, NV50_PDISPLAY_CURSOR_CURSOR_CTRL2_STATUS_ACTIVE)) { - NV_ERROR(dev, "timeout: " + NV_ERROR(drm, "timeout: " "CURSOR_CTRL2_STATUS_ACTIVE(%d)\n", i); - NV_ERROR(dev, "CURSOR_CTRL2(%d) = 0x%08x\n", i, - nv_rd32(dev, NV50_PDISPLAY_CURSOR_CURSOR_CTRL2(i))); + NV_ERROR(drm, "CURSOR_CTRL2(%d) = 0x%08x\n", i, + nv_rd32(device, NV50_PDISPLAY_CURSOR_CURSOR_CTRL2(i))); return -EBUSY; } } - nv_wr32(dev, NV50_PDISPLAY_PIO_CTRL, 0x00000000); - nv_mask(dev, NV50_PDISPLAY_INTR_0, 0x00000000, 0x00000000); - nv_wr32(dev, NV50_PDISPLAY_INTR_EN_0, 0x00000000); - nv_mask(dev, NV50_PDISPLAY_INTR_1, 0x00000000, 0x00000000); - nv_wr32(dev, NV50_PDISPLAY_INTR_EN_1, + nv_wr32(device, NV50_PDISPLAY_PIO_CTRL, 0x00000000); + nv_mask(device, NV50_PDISPLAY_INTR_0, 0x00000000, 0x00000000); + nv_wr32(device, NV50_PDISPLAY_INTR_EN_0, 0x00000000); + nv_mask(device, NV50_PDISPLAY_INTR_1, 0x00000000, 0x00000000); + nv_wr32(device, NV50_PDISPLAY_INTR_EN_1, NV50_PDISPLAY_INTR_EN_1_CLK_UNK10 | NV50_PDISPLAY_INTR_EN_1_CLK_UNK20 | NV50_PDISPLAY_INTR_EN_1_CLK_UNK40); @@ -216,7 +217,7 @@ nv50_display_init(struct drm_device *dev) return ret; evo = nv50_display(dev)->master; - nv_wr32(dev, NV50_PDISPLAY_OBJECTS, (nv50_display(dev)->ramin->addr >> 8) | 9); + nv_wr32(device, NV50_PDISPLAY_OBJECTS, (nv50_display(dev)->ramin->addr >> 8) | 9); ret = RING_SPACE(evo, 3); if (ret) @@ -231,12 +232,14 @@ nv50_display_init(struct drm_device *dev) void nv50_display_fini(struct drm_device *dev) { + struct nouveau_drm *drm = nouveau_drm(dev); + struct nouveau_device *device = nouveau_dev(dev); struct nv50_display *disp = nv50_display(dev); struct nouveau_channel *evo = disp->master; struct drm_crtc *drm_crtc; int ret, i; - NV_DEBUG_KMS(dev, "\n"); + NV_DEBUG(drm, "\n"); list_for_each_entry(drm_crtc, &dev->mode_config.crtc_list, head) { struct nouveau_crtc *crtc = nouveau_crtc(drm_crtc); @@ -261,55 +264,59 @@ nv50_display_fini(struct drm_device *dev) if (!crtc->base.enabled) continue; - nv_wr32(dev, NV50_PDISPLAY_INTR_1, mask); - if (!nv_wait(dev, NV50_PDISPLAY_INTR_1, mask, mask)) { - NV_ERROR(dev, "timeout: (0x610024 & 0x%08x) == " + nv_wr32(device, NV50_PDISPLAY_INTR_1, mask); + if (!nv_wait(device, NV50_PDISPLAY_INTR_1, mask, mask)) { + NV_ERROR(drm, "timeout: (0x610024 & 0x%08x) == " "0x%08x\n", mask, mask); - NV_ERROR(dev, "0x610024 = 0x%08x\n", - nv_rd32(dev, NV50_PDISPLAY_INTR_1)); + NV_ERROR(drm, "0x610024 = 0x%08x\n", + nv_rd32(device, NV50_PDISPLAY_INTR_1)); } } for (i = 0; i < 2; i++) { - nv_wr32(dev, NV50_PDISPLAY_CURSOR_CURSOR_CTRL2(i), 0); - if (!nv_wait(dev, NV50_PDISPLAY_CURSOR_CURSOR_CTRL2(i), + nv_wr32(device, NV50_PDISPLAY_CURSOR_CURSOR_CTRL2(i), 0); + if (!nv_wait(device, NV50_PDISPLAY_CURSOR_CURSOR_CTRL2(i), NV50_PDISPLAY_CURSOR_CURSOR_CTRL2_STATUS, 0)) { - NV_ERROR(dev, "timeout: CURSOR_CTRL2_STATUS == 0\n"); - NV_ERROR(dev, "CURSOR_CTRL2 = 0x%08x\n", - nv_rd32(dev, NV50_PDISPLAY_CURSOR_CURSOR_CTRL2(i))); + NV_ERROR(drm, "timeout: CURSOR_CTRL2_STATUS == 0\n"); + NV_ERROR(drm, "CURSOR_CTRL2 = 0x%08x\n", + nv_rd32(device, NV50_PDISPLAY_CURSOR_CURSOR_CTRL2(i))); } } nv50_evo_fini(dev); for (i = 0; i < 3; i++) { - if (!nv_wait(dev, NV50_PDISPLAY_SOR_DPMS_STATE(i), + if (!nv_wait(device, NV50_PDISPLAY_SOR_DPMS_STATE(i), NV50_PDISPLAY_SOR_DPMS_STATE_WAIT, 0)) { - NV_ERROR(dev, "timeout: SOR_DPMS_STATE_WAIT(%d) == 0\n", i); - NV_ERROR(dev, "SOR_DPMS_STATE(%d) = 0x%08x\n", i, - nv_rd32(dev, NV50_PDISPLAY_SOR_DPMS_STATE(i))); + NV_ERROR(drm, "timeout: SOR_DPMS_STATE_WAIT(%d) == 0\n", i); + NV_ERROR(drm, "SOR_DPMS_STATE(%d) = 0x%08x\n", i, + nv_rd32(device, NV50_PDISPLAY_SOR_DPMS_STATE(i))); } } /* disable interrupts. */ - nv_wr32(dev, NV50_PDISPLAY_INTR_EN_1, 0x00000000); + nv_wr32(device, NV50_PDISPLAY_INTR_EN_1, 0x00000000); } int nv50_display_create(struct drm_device *dev) { - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct dcb_table *dcb = &dev_priv->vbios.dcb; + struct nouveau_drm *drm = nouveau_drm(dev); + struct dcb_table *dcb = &drm->vbios.dcb; struct drm_connector *connector, *ct; struct nv50_display *priv; int ret, i; - NV_DEBUG_KMS(dev, "\n"); + NV_DEBUG(drm, "\n"); priv = kzalloc(sizeof(*priv), GFP_KERNEL); if (!priv) return -ENOMEM; - dev_priv->engine.display.priv = priv; + + nouveau_display(dev)->priv = priv; + nouveau_display(dev)->dtor = nv50_display_destroy; + nouveau_display(dev)->init = nv50_display_init; + nouveau_display(dev)->fini = nv50_display_fini; /* Create CRTC objects */ for (i = 0; i < 2; i++) { @@ -323,7 +330,7 @@ nv50_display_create(struct drm_device *dev) struct dcb_output *entry = &dcb->entry[i]; if (entry->location != DCB_LOC_ON_CHIP) { - NV_WARN(dev, "Off-chip encoder %d/%d unsupported\n", + NV_WARN(drm, "Off-chip encoder %d/%d unsupported\n", entry->type, ffs(entry->or) - 1); continue; } @@ -342,7 +349,7 @@ nv50_display_create(struct drm_device *dev) nv50_dac_create(connector, entry); break; default: - NV_WARN(dev, "DCB encoder %d unknown\n", entry->type); + NV_WARN(drm, "DCB encoder %d unknown\n", entry->type); continue; } } @@ -350,14 +357,13 @@ nv50_display_create(struct drm_device *dev) list_for_each_entry_safe(connector, ct, &dev->mode_config.connector_list, head) { if (!connector->encoder_ids[0]) { - NV_WARN(dev, "%s has no encoders, removing\n", + NV_WARN(drm, "%s has no encoders, removing\n", drm_get_connector_name(connector)); connector->funcs->destroy(connector); } } tasklet_init(&priv->tasklet, nv50_display_bh, (unsigned long)dev); - nouveau_irq_register(dev, 26, nv50_display_isr); ret = nv50_evo_create(dev); if (ret) { @@ -373,13 +379,16 @@ nv50_display_destroy(struct drm_device *dev) { struct nv50_display *disp = nv50_display(dev); - NV_DEBUG_KMS(dev, "\n"); - nv50_evo_destroy(dev); - nouveau_irq_unregister(dev, 26); kfree(disp); } +struct nouveau_bo * +nv50_display_crtc_sema(struct drm_device *dev, int crtc) +{ + return nv50_display(dev)->crtc[crtc].sem.bo; +} + void nv50_display_flip_stop(struct drm_crtc *crtc) { @@ -410,7 +419,7 @@ int nv50_display_flip_next(struct drm_crtc *crtc, struct drm_framebuffer *fb, struct nouveau_channel *chan) { - struct drm_nouveau_private *dev_priv = crtc->dev->dev_private; + struct nouveau_drm *drm = nouveau_drm(crtc->dev); struct nouveau_framebuffer *nv_fb = nouveau_framebuffer(fb); struct nv50_display *disp = nv50_display(crtc->dev); struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); @@ -430,7 +439,7 @@ nv50_display_flip_next(struct drm_crtc *crtc, struct drm_framebuffer *fb, return ret; } - if (dev_priv->chipset < 0xc0) { + if (nv_device(drm->device)->chipset < 0xc0) { BEGIN_NV04(chan, 0, 0x0060, 2); OUT_RING (chan, NvEvoSema0 + nv_crtc->index); OUT_RING (chan, dispc->sem.offset); @@ -440,7 +449,7 @@ nv50_display_flip_next(struct drm_crtc *crtc, struct drm_framebuffer *fb, OUT_RING (chan, dispc->sem.offset ^ 0x10); OUT_RING (chan, 0x74b1e000); BEGIN_NV04(chan, 0, 0x0060, 1); - if (dev_priv->chipset < 0x84) + if (nv_device(drm->device)->chipset < 0x84) OUT_RING (chan, NvSema); else OUT_RING (chan, chan->vram); @@ -511,10 +520,10 @@ static u16 nv50_display_script_select(struct drm_device *dev, struct dcb_output *dcb, u32 mc, int pxclk) { - struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_drm *drm = nouveau_drm(dev); struct nouveau_connector *nv_connector = NULL; struct drm_encoder *encoder; - struct nvbios *bios = &dev_priv->vbios; + struct nvbios *bios = &drm->vbios; u32 script = 0, or; list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { @@ -562,25 +571,11 @@ nv50_display_script_select(struct drm_device *dev, struct dcb_output *dcb, (nv_connector->edid->input & 0x70) >= 0x20) script |= 0x0200; } - - if (nouveau_uscript_lvds >= 0) { - NV_INFO(dev, "override script 0x%04x with 0x%04x " - "for output LVDS-%d\n", script, - nouveau_uscript_lvds, or); - script = nouveau_uscript_lvds; - } break; case DCB_OUTPUT_TMDS: script = (mc >> 8) & 0xf; if (pxclk >= 165000) script |= 0x0100; - - if (nouveau_uscript_tmds >= 0) { - NV_INFO(dev, "override script 0x%04x with 0x%04x " - "for output TMDS-%d\n", script, - nouveau_uscript_tmds, or); - script = nouveau_uscript_tmds; - } break; case DCB_OUTPUT_DP: script = (mc >> 8) & 0xf; @@ -589,7 +584,7 @@ nv50_display_script_select(struct drm_device *dev, struct dcb_output *dcb, script = 0xff; break; default: - NV_ERROR(dev, "modeset on unsupported output type!\n"); + NV_ERROR(drm, "modeset on unsupported output type!\n"); break; } @@ -599,15 +594,16 @@ nv50_display_script_select(struct drm_device *dev, struct dcb_output *dcb, static void nv50_display_unk10_handler(struct drm_device *dev) { - struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_device *device = nouveau_dev(dev); + struct nouveau_drm *drm = nouveau_drm(dev); struct nv50_display *disp = nv50_display(dev); - u32 unk30 = nv_rd32(dev, 0x610030), mc; + u32 unk30 = nv_rd32(device, 0x610030), mc; int i, crtc, or = 0, type = DCB_OUTPUT_ANY; - NV_DEBUG_KMS(dev, "0x610030: 0x%08x\n", unk30); + NV_DEBUG(drm, "0x610030: 0x%08x\n", unk30); disp->irq.dcb = NULL; - nv_wr32(dev, 0x619494, nv_rd32(dev, 0x619494) & ~8); + nv_wr32(device, 0x619494, nv_rd32(device, 0x619494) & ~8); /* Determine which CRTC we're dealing with, only 1 ever will be * signalled at the same time with the current nouveau code. @@ -623,8 +619,8 @@ nv50_display_unk10_handler(struct drm_device *dev) /* Find which encoder was connected to the CRTC */ for (i = 0; type == DCB_OUTPUT_ANY && i < 3; i++) { - mc = nv_rd32(dev, NV50_PDISPLAY_DAC_MODE_CTRL_C(i)); - NV_DEBUG_KMS(dev, "DAC-%d mc: 0x%08x\n", i, mc); + mc = nv_rd32(device, NV50_PDISPLAY_DAC_MODE_CTRL_C(i)); + NV_DEBUG(drm, "DAC-%d mc: 0x%08x\n", i, mc); if (!(mc & (1 << crtc))) continue; @@ -632,7 +628,7 @@ nv50_display_unk10_handler(struct drm_device *dev) case 0: type = DCB_OUTPUT_ANALOG; break; case 1: type = DCB_OUTPUT_TV; break; default: - NV_ERROR(dev, "invalid mc, DAC-%d: 0x%08x\n", i, mc); + NV_ERROR(drm, "invalid mc, DAC-%d: 0x%08x\n", i, mc); goto ack; } @@ -640,14 +636,14 @@ nv50_display_unk10_handler(struct drm_device *dev) } for (i = 0; type == DCB_OUTPUT_ANY && i < nv50_sor_nr(dev); i++) { - if (dev_priv->chipset < 0x90 || - dev_priv->chipset == 0x92 || - dev_priv->chipset == 0xa0) - mc = nv_rd32(dev, NV50_PDISPLAY_SOR_MODE_CTRL_C(i)); + if (nv_device(drm->device)->chipset < 0x90 || + nv_device(drm->device)->chipset == 0x92 || + nv_device(drm->device)->chipset == 0xa0) + mc = nv_rd32(device, NV50_PDISPLAY_SOR_MODE_CTRL_C(i)); else - mc = nv_rd32(dev, NV90_PDISPLAY_SOR_MODE_CTRL_C(i)); + mc = nv_rd32(device, NV90_PDISPLAY_SOR_MODE_CTRL_C(i)); - NV_DEBUG_KMS(dev, "SOR-%d mc: 0x%08x\n", i, mc); + NV_DEBUG(drm, "SOR-%d mc: 0x%08x\n", i, mc); if (!(mc & (1 << crtc))) continue; @@ -659,7 +655,7 @@ nv50_display_unk10_handler(struct drm_device *dev) case 8: type = DCB_OUTPUT_DP; break; case 9: type = DCB_OUTPUT_DP; break; default: - NV_ERROR(dev, "invalid mc, SOR-%d: 0x%08x\n", i, mc); + NV_ERROR(drm, "invalid mc, SOR-%d: 0x%08x\n", i, mc); goto ack; } @@ -671,8 +667,8 @@ nv50_display_unk10_handler(struct drm_device *dev) goto ack; /* Disable the encoder */ - for (i = 0; i < dev_priv->vbios.dcb.entries; i++) { - struct dcb_output *dcb = &dev_priv->vbios.dcb.entry[i]; + for (i = 0; i < drm->vbios.dcb.entries; i++) { + struct dcb_output *dcb = &drm->vbios.dcb.entry[i]; if (dcb->type == type && (dcb->or & (1 << or))) { nouveau_bios_run_display_table(dev, 0, -1, dcb, -1); @@ -681,22 +677,23 @@ nv50_display_unk10_handler(struct drm_device *dev) } } - NV_ERROR(dev, "no dcb for %d %d 0x%08x\n", or, type, mc); + NV_ERROR(drm, "no dcb for %d %d 0x%08x\n", or, type, mc); ack: - nv_wr32(dev, NV50_PDISPLAY_INTR_1, NV50_PDISPLAY_INTR_1_CLK_UNK10); - nv_wr32(dev, 0x610030, 0x80000000); + nv_wr32(device, NV50_PDISPLAY_INTR_1, NV50_PDISPLAY_INTR_1_CLK_UNK10); + nv_wr32(device, 0x610030, 0x80000000); } static void nv50_display_unk20_handler(struct drm_device *dev) { - struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_device *device = nouveau_dev(dev); + struct nouveau_drm *drm = nouveau_drm(dev); struct nv50_display *disp = nv50_display(dev); - u32 unk30 = nv_rd32(dev, 0x610030), tmp, pclk, script, mc = 0; + u32 unk30 = nv_rd32(device, 0x610030), tmp, pclk, script, mc = 0; struct dcb_output *dcb; int i, crtc, or = 0, type = DCB_OUTPUT_ANY; - NV_DEBUG_KMS(dev, "0x610030: 0x%08x\n", unk30); + NV_DEBUG(drm, "0x610030: 0x%08x\n", unk30); dcb = disp->irq.dcb; if (dcb) { nouveau_bios_run_display_table(dev, 0, -2, dcb, -1); @@ -706,26 +703,26 @@ nv50_display_unk20_handler(struct drm_device *dev) /* CRTC clock change requested? */ crtc = ffs((unk30 & 0x00000600) >> 9) - 1; if (crtc >= 0) { - pclk = nv_rd32(dev, NV50_PDISPLAY_CRTC_P(crtc, CLOCK)); + pclk = nv_rd32(device, NV50_PDISPLAY_CRTC_P(crtc, CLOCK)); pclk &= 0x003fffff; if (pclk) nv50_crtc_set_clock(dev, crtc, pclk); - tmp = nv_rd32(dev, NV50_PDISPLAY_CRTC_CLK_CTRL2(crtc)); + tmp = nv_rd32(device, NV50_PDISPLAY_CRTC_CLK_CTRL2(crtc)); tmp &= ~0x000000f; - nv_wr32(dev, NV50_PDISPLAY_CRTC_CLK_CTRL2(crtc), tmp); + nv_wr32(device, NV50_PDISPLAY_CRTC_CLK_CTRL2(crtc), tmp); } /* Nothing needs to be done for the encoder */ crtc = ffs((unk30 & 0x00000180) >> 7) - 1; if (crtc < 0) goto ack; - pclk = nv_rd32(dev, NV50_PDISPLAY_CRTC_P(crtc, CLOCK)) & 0x003fffff; + pclk = nv_rd32(device, NV50_PDISPLAY_CRTC_P(crtc, CLOCK)) & 0x003fffff; /* Find which encoder is connected to the CRTC */ for (i = 0; type == DCB_OUTPUT_ANY && i < 3; i++) { - mc = nv_rd32(dev, NV50_PDISPLAY_DAC_MODE_CTRL_P(i)); - NV_DEBUG_KMS(dev, "DAC-%d mc: 0x%08x\n", i, mc); + mc = nv_rd32(device, NV50_PDISPLAY_DAC_MODE_CTRL_P(i)); + NV_DEBUG(drm, "DAC-%d mc: 0x%08x\n", i, mc); if (!(mc & (1 << crtc))) continue; @@ -733,7 +730,7 @@ nv50_display_unk20_handler(struct drm_device *dev) case 0: type = DCB_OUTPUT_ANALOG; break; case 1: type = DCB_OUTPUT_TV; break; default: - NV_ERROR(dev, "invalid mc, DAC-%d: 0x%08x\n", i, mc); + NV_ERROR(drm, "invalid mc, DAC-%d: 0x%08x\n", i, mc); goto ack; } @@ -741,14 +738,14 @@ nv50_display_unk20_handler(struct drm_device *dev) } for (i = 0; type == DCB_OUTPUT_ANY && i < nv50_sor_nr(dev); i++) { - if (dev_priv->chipset < 0x90 || - dev_priv->chipset == 0x92 || - dev_priv->chipset == 0xa0) - mc = nv_rd32(dev, NV50_PDISPLAY_SOR_MODE_CTRL_P(i)); + if (nv_device(drm->device)->chipset < 0x90 || + nv_device(drm->device)->chipset == 0x92 || + nv_device(drm->device)->chipset == 0xa0) + mc = nv_rd32(device, NV50_PDISPLAY_SOR_MODE_CTRL_P(i)); else - mc = nv_rd32(dev, NV90_PDISPLAY_SOR_MODE_CTRL_P(i)); + mc = nv_rd32(device, NV90_PDISPLAY_SOR_MODE_CTRL_P(i)); - NV_DEBUG_KMS(dev, "SOR-%d mc: 0x%08x\n", i, mc); + NV_DEBUG(drm, "SOR-%d mc: 0x%08x\n", i, mc); if (!(mc & (1 << crtc))) continue; @@ -760,7 +757,7 @@ nv50_display_unk20_handler(struct drm_device *dev) case 8: type = DCB_OUTPUT_DP; break; case 9: type = DCB_OUTPUT_DP; break; default: - NV_ERROR(dev, "invalid mc, SOR-%d: 0x%08x\n", i, mc); + NV_ERROR(drm, "invalid mc, SOR-%d: 0x%08x\n", i, mc); goto ack; } @@ -771,14 +768,14 @@ nv50_display_unk20_handler(struct drm_device *dev) goto ack; /* Enable the encoder */ - for (i = 0; i < dev_priv->vbios.dcb.entries; i++) { - dcb = &dev_priv->vbios.dcb.entry[i]; + for (i = 0; i < drm->vbios.dcb.entries; i++) { + dcb = &drm->vbios.dcb.entry[i]; if (dcb->type == type && (dcb->or & (1 << or))) break; } - if (i == dev_priv->vbios.dcb.entries) { - NV_ERROR(dev, "no dcb for %d %d 0x%08x\n", or, type, mc); + if (i == drm->vbios.dcb.entries) { + NV_ERROR(drm, "no dcb for %d %d 0x%08x\n", or, type, mc); goto ack; } @@ -794,13 +791,13 @@ nv50_display_unk20_handler(struct drm_device *dev) } if (dcb->type != DCB_OUTPUT_ANALOG) { - tmp = nv_rd32(dev, NV50_PDISPLAY_SOR_CLK_CTRL2(or)); + tmp = nv_rd32(device, NV50_PDISPLAY_SOR_CLK_CTRL2(or)); tmp &= ~0x00000f0f; if (script & 0x0100) tmp |= 0x00000101; - nv_wr32(dev, NV50_PDISPLAY_SOR_CLK_CTRL2(or), tmp); + nv_wr32(device, NV50_PDISPLAY_SOR_CLK_CTRL2(or), tmp); } else { - nv_wr32(dev, NV50_PDISPLAY_DAC_CLK_CTRL2(or), 0); + nv_wr32(device, NV50_PDISPLAY_DAC_CLK_CTRL2(or), 0); } disp->irq.dcb = dcb; @@ -808,8 +805,8 @@ nv50_display_unk20_handler(struct drm_device *dev) disp->irq.script = script; ack: - nv_wr32(dev, NV50_PDISPLAY_INTR_1, NV50_PDISPLAY_INTR_1_CLK_UNK20); - nv_wr32(dev, 0x610030, 0x80000000); + nv_wr32(device, NV50_PDISPLAY_INTR_1, NV50_PDISPLAY_INTR_1_CLK_UNK20); + nv_wr32(device, 0x610030, 0x80000000); } /* If programming a TMDS output on a SOR that can also be configured for @@ -823,6 +820,7 @@ ack: static void nv50_display_unk40_dp_set_tmds(struct drm_device *dev, struct dcb_output *dcb) { + struct nouveau_device *device = nouveau_dev(dev); int or = ffs(dcb->or) - 1, link = !(dcb->dpconf.sor.link & 1); struct drm_encoder *encoder; u32 tmp; @@ -835,9 +833,9 @@ nv50_display_unk40_dp_set_tmds(struct drm_device *dev, struct dcb_output *dcb) if (nv_encoder->dcb->type == DCB_OUTPUT_DP && nv_encoder->dcb->or & (1 << or)) { - tmp = nv_rd32(dev, NV50_SOR_DP_CTRL(or, link)); + tmp = nv_rd32(device, NV50_SOR_DP_CTRL(or, link)); tmp &= ~NV50_SOR_DP_CTRL_ENABLED; - nv_wr32(dev, NV50_SOR_DP_CTRL(or, link), tmp); + nv_wr32(device, NV50_SOR_DP_CTRL(or, link), tmp); break; } } @@ -846,12 +844,14 @@ nv50_display_unk40_dp_set_tmds(struct drm_device *dev, struct dcb_output *dcb) static void nv50_display_unk40_handler(struct drm_device *dev) { + struct nouveau_device *device = nouveau_dev(dev); + struct nouveau_drm *drm = nouveau_drm(dev); struct nv50_display *disp = nv50_display(dev); struct dcb_output *dcb = disp->irq.dcb; u16 script = disp->irq.script; - u32 unk30 = nv_rd32(dev, 0x610030), pclk = disp->irq.pclk; + u32 unk30 = nv_rd32(device, 0x610030), pclk = disp->irq.pclk; - NV_DEBUG_KMS(dev, "0x610030: 0x%08x\n", unk30); + NV_DEBUG(drm, "0x610030: 0x%08x\n", unk30); disp->irq.dcb = NULL; if (!dcb) goto ack; @@ -860,21 +860,23 @@ nv50_display_unk40_handler(struct drm_device *dev) nv50_display_unk40_dp_set_tmds(dev, dcb); ack: - nv_wr32(dev, NV50_PDISPLAY_INTR_1, NV50_PDISPLAY_INTR_1_CLK_UNK40); - nv_wr32(dev, 0x610030, 0x80000000); - nv_wr32(dev, 0x619494, nv_rd32(dev, 0x619494) | 8); + nv_wr32(device, NV50_PDISPLAY_INTR_1, NV50_PDISPLAY_INTR_1_CLK_UNK40); + nv_wr32(device, 0x610030, 0x80000000); + nv_wr32(device, 0x619494, nv_rd32(device, 0x619494) | 8); } static void nv50_display_bh(unsigned long data) { struct drm_device *dev = (struct drm_device *)data; + struct nouveau_device *device = nouveau_dev(dev); + struct nouveau_drm *drm = nouveau_drm(dev); for (;;) { - uint32_t intr0 = nv_rd32(dev, NV50_PDISPLAY_INTR_0); - uint32_t intr1 = nv_rd32(dev, NV50_PDISPLAY_INTR_1); + uint32_t intr0 = nv_rd32(device, NV50_PDISPLAY_INTR_0); + uint32_t intr1 = nv_rd32(device, NV50_PDISPLAY_INTR_1); - NV_DEBUG_KMS(dev, "PDISPLAY_INTR_BH 0x%08x 0x%08x\n", intr0, intr1); + NV_DEBUG(drm, "PDISPLAY_INTR_BH 0x%08x 0x%08x\n", intr0, intr1); if (intr1 & NV50_PDISPLAY_INTR_1_CLK_UNK10) nv50_display_unk10_handler(dev); @@ -888,13 +890,15 @@ nv50_display_bh(unsigned long data) break; } - nv_wr32(dev, NV03_PMC_INTR_EN_0, 1); + nv_wr32(device, NV03_PMC_INTR_EN_0, 1); } static void nv50_display_error_handler(struct drm_device *dev) { - u32 channels = (nv_rd32(dev, NV50_PDISPLAY_INTR_0) & 0x001f0000) >> 16; + struct nouveau_device *device = nouveau_dev(dev); + struct nouveau_drm *drm = nouveau_drm(dev); + u32 channels = (nv_rd32(device, NV50_PDISPLAY_INTR_0) & 0x001f0000) >> 16; u32 addr, data; int chid; @@ -902,29 +906,31 @@ nv50_display_error_handler(struct drm_device *dev) if (!(channels & (1 << chid))) continue; - nv_wr32(dev, NV50_PDISPLAY_INTR_0, 0x00010000 << chid); - addr = nv_rd32(dev, NV50_PDISPLAY_TRAPPED_ADDR(chid)); - data = nv_rd32(dev, NV50_PDISPLAY_TRAPPED_DATA(chid)); - NV_ERROR(dev, "EvoCh %d Mthd 0x%04x Data 0x%08x " + nv_wr32(device, NV50_PDISPLAY_INTR_0, 0x00010000 << chid); + addr = nv_rd32(device, NV50_PDISPLAY_TRAPPED_ADDR(chid)); + data = nv_rd32(device, NV50_PDISPLAY_TRAPPED_DATA(chid)); + NV_ERROR(drm, "EvoCh %d Mthd 0x%04x Data 0x%08x " "(0x%04x 0x%02x)\n", chid, addr & 0xffc, data, addr >> 16, (addr >> 12) & 0xf); - nv_wr32(dev, NV50_PDISPLAY_TRAPPED_ADDR(chid), 0x90000000); + nv_wr32(device, NV50_PDISPLAY_TRAPPED_ADDR(chid), 0x90000000); } } -static void -nv50_display_isr(struct drm_device *dev) +void +nv50_display_intr(struct drm_device *dev) { + struct nouveau_device *device = nouveau_dev(dev); + struct nouveau_drm *drm = nouveau_drm(dev); struct nv50_display *disp = nv50_display(dev); uint32_t delayed = 0; - while (nv_rd32(dev, NV50_PMC_INTR_0) & NV50_PMC_INTR_0_DISPLAY) { - uint32_t intr0 = nv_rd32(dev, NV50_PDISPLAY_INTR_0); - uint32_t intr1 = nv_rd32(dev, NV50_PDISPLAY_INTR_1); + while (nv_rd32(device, NV50_PMC_INTR_0) & NV50_PMC_INTR_0_DISPLAY) { + uint32_t intr0 = nv_rd32(device, NV50_PDISPLAY_INTR_0); + uint32_t intr1 = nv_rd32(device, NV50_PDISPLAY_INTR_1); uint32_t clock; - NV_DEBUG_KMS(dev, "PDISPLAY_INTR 0x%08x 0x%08x\n", intr0, intr1); + NV_DEBUG(drm, "PDISPLAY_INTR 0x%08x 0x%08x\n", intr0, intr1); if (!intr0 && !(intr1 & ~delayed)) break; @@ -943,21 +949,21 @@ nv50_display_isr(struct drm_device *dev) NV50_PDISPLAY_INTR_1_CLK_UNK20 | NV50_PDISPLAY_INTR_1_CLK_UNK40)); if (clock) { - nv_wr32(dev, NV03_PMC_INTR_EN_0, 0); + nv_wr32(device, NV03_PMC_INTR_EN_0, 0); tasklet_schedule(&disp->tasklet); delayed |= clock; intr1 &= ~clock; } if (intr0) { - NV_ERROR(dev, "unknown PDISPLAY_INTR_0: 0x%08x\n", intr0); - nv_wr32(dev, NV50_PDISPLAY_INTR_0, intr0); + NV_ERROR(drm, "unknown PDISPLAY_INTR_0: 0x%08x\n", intr0); + nv_wr32(device, NV50_PDISPLAY_INTR_0, intr0); } if (intr1) { - NV_ERROR(dev, + NV_ERROR(drm, "unknown PDISPLAY_INTR_1: 0x%08x\n", intr1); - nv_wr32(dev, NV50_PDISPLAY_INTR_1, intr1); + nv_wr32(device, NV50_PDISPLAY_INTR_1, intr1); } } } diff --git a/drivers/gpu/drm/nouveau/nv50_display.h b/drivers/gpu/drm/nouveau/nv50_display.h index ef12a7afac9c..973554d8a7a6 100644 --- a/drivers/gpu/drm/nouveau/nv50_display.h +++ b/drivers/gpu/drm/nouveau/nv50_display.h @@ -27,12 +27,9 @@ #ifndef __NV50_DISPLAY_H__ #define __NV50_DISPLAY_H__ -#include "drmP.h" -#include "drm.h" -#include "nouveau_drv.h" -#include "nouveau_dma.h" -#include "nouveau_reg.h" +#include "nouveau_display.h" #include "nouveau_crtc.h" +#include "nouveau_reg.h" #include "nv50_evo.h" struct nv50_display_crtc { @@ -64,8 +61,7 @@ struct nv50_display { static inline struct nv50_display * nv50_display(struct drm_device *dev) { - struct drm_nouveau_private *dev_priv = dev->dev_private; - return dev_priv->engine.display.priv; + return nouveau_display(dev)->priv; } int nv50_display_early_init(struct drm_device *dev); @@ -74,6 +70,7 @@ int nv50_display_create(struct drm_device *dev); int nv50_display_init(struct drm_device *dev); void nv50_display_fini(struct drm_device *dev); void nv50_display_destroy(struct drm_device *dev); +void nv50_display_intr(struct drm_device *); int nv50_crtc_blank(struct nouveau_crtc *, bool blank); int nv50_crtc_set_clock(struct drm_device *, int head, int pclk); @@ -93,4 +90,17 @@ void nv50_evo_dmaobj_init(struct nouveau_gpuobj *, u32 memtype, u64 base, int nv50_evo_dmaobj_new(struct nouveau_channel *, u32 handle, u32 memtype, u64 base, u64 size, struct nouveau_gpuobj **); +int nvd0_display_create(struct drm_device *); +void nvd0_display_destroy(struct drm_device *); +int nvd0_display_init(struct drm_device *); +void nvd0_display_fini(struct drm_device *); +void nvd0_display_intr(struct drm_device *); + +void nvd0_display_flip_stop(struct drm_crtc *); +int nvd0_display_flip_next(struct drm_crtc *, struct drm_framebuffer *, + struct nouveau_channel *, u32 swap_interval); + +struct nouveau_bo *nv50_display_crtc_sema(struct drm_device *, int head); +struct nouveau_bo *nvd0_display_crtc_sema(struct drm_device *, int head); + #endif /* __NV50_DISPLAY_H__ */ diff --git a/drivers/gpu/drm/nouveau/nv50_evo.c b/drivers/gpu/drm/nouveau/nv50_evo.c index d7d8080c6a14..0f534160c021 100644 --- a/drivers/gpu/drm/nouveau/nv50_evo.c +++ b/drivers/gpu/drm/nouveau/nv50_evo.c @@ -24,10 +24,15 @@ #include "drmP.h" -#include "nouveau_drv.h" +#include "nouveau_drm.h" #include "nouveau_dma.h" #include "nv50_display.h" +#include + +#include +#include + static u32 nv50_evo_rd32(struct nouveau_object *object, u32 addr) { @@ -65,15 +70,15 @@ nv50_evo_dmaobj_new(struct nouveau_channel *evo, u32 handle, u32 memtype, u64 base, u64 size, struct nouveau_gpuobj **pobj) { struct drm_device *dev = evo->fence; - struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_drm *drm = nouveau_drm(dev); struct nv50_display *disp = nv50_display(dev); u32 dmao = disp->dmao; u32 hash = disp->hash; u32 flags5; - if (dev_priv->chipset < 0xc0) { + if (nv_device(drm->device)->chipset < 0xc0) { /* not supported on 0x50, specified in format mthd */ - if (dev_priv->chipset == 0x50) + if (nv_device(drm->device)->chipset == 0x50) memtype = 0; flags5 = 0x00010000; } else { @@ -104,6 +109,7 @@ static int nv50_evo_channel_new(struct drm_device *dev, int chid, struct nouveau_channel **pevo) { + struct nouveau_drm *drm = nouveau_drm(dev); struct nv50_display *disp = nv50_display(dev); struct nouveau_channel *evo; int ret; @@ -113,6 +119,7 @@ nv50_evo_channel_new(struct drm_device *dev, int chid, return -ENOMEM; *pevo = evo; + evo->drm = drm; evo->handle = chid; evo->fence = dev; evo->user_get = 4; @@ -123,14 +130,14 @@ nv50_evo_channel_new(struct drm_device *dev, int chid, if (ret == 0) ret = nouveau_bo_pin(evo->push.buffer, TTM_PL_FLAG_VRAM); if (ret) { - NV_ERROR(dev, "Error creating EVO DMA push buffer: %d\n", ret); + NV_ERROR(drm, "Error creating EVO DMA push buffer: %d\n", ret); nv50_evo_channel_del(pevo); return ret; } ret = nouveau_bo_map(evo->push.buffer); if (ret) { - NV_ERROR(dev, "Error mapping EVO DMA push buffer: %d\n", ret); + NV_ERROR(drm, "Error mapping EVO DMA push buffer: %d\n", ret); nv50_evo_channel_del(pevo); return ret; } @@ -156,39 +163,40 @@ nv50_evo_channel_new(struct drm_device *dev, int chid, static int nv50_evo_channel_init(struct nouveau_channel *evo) { - struct drm_device *dev = evo->fence; + struct nouveau_drm *drm = evo->drm; + struct nouveau_device *device = nv_device(drm->device); int id = evo->handle, ret, i; u64 pushbuf = evo->push.buffer->bo.offset; u32 tmp; - tmp = nv_rd32(dev, NV50_PDISPLAY_EVO_CTRL(id)); + tmp = nv_rd32(device, NV50_PDISPLAY_EVO_CTRL(id)); if ((tmp & 0x009f0000) == 0x00020000) - nv_wr32(dev, NV50_PDISPLAY_EVO_CTRL(id), tmp | 0x00800000); + nv_wr32(device, NV50_PDISPLAY_EVO_CTRL(id), tmp | 0x00800000); - tmp = nv_rd32(dev, NV50_PDISPLAY_EVO_CTRL(id)); + tmp = nv_rd32(device, NV50_PDISPLAY_EVO_CTRL(id)); if ((tmp & 0x003f0000) == 0x00030000) - nv_wr32(dev, NV50_PDISPLAY_EVO_CTRL(id), tmp | 0x00600000); + nv_wr32(device, NV50_PDISPLAY_EVO_CTRL(id), tmp | 0x00600000); /* initialise fifo */ - nv_wr32(dev, NV50_PDISPLAY_EVO_DMA_CB(id), pushbuf >> 8 | + nv_wr32(device, NV50_PDISPLAY_EVO_DMA_CB(id), pushbuf >> 8 | NV50_PDISPLAY_EVO_DMA_CB_LOCATION_VRAM | NV50_PDISPLAY_EVO_DMA_CB_VALID); - nv_wr32(dev, NV50_PDISPLAY_EVO_UNK2(id), 0x00010000); - nv_wr32(dev, NV50_PDISPLAY_EVO_HASH_TAG(id), id); - nv_mask(dev, NV50_PDISPLAY_EVO_CTRL(id), NV50_PDISPLAY_EVO_CTRL_DMA, + nv_wr32(device, NV50_PDISPLAY_EVO_UNK2(id), 0x00010000); + nv_wr32(device, NV50_PDISPLAY_EVO_HASH_TAG(id), id); + nv_mask(device, NV50_PDISPLAY_EVO_CTRL(id), NV50_PDISPLAY_EVO_CTRL_DMA, NV50_PDISPLAY_EVO_CTRL_DMA_ENABLED); - nv_wr32(dev, NV50_PDISPLAY_USER_PUT(id), 0x00000000); - nv_wr32(dev, NV50_PDISPLAY_EVO_CTRL(id), 0x01000003 | + nv_wr32(device, NV50_PDISPLAY_USER_PUT(id), 0x00000000); + nv_wr32(device, NV50_PDISPLAY_EVO_CTRL(id), 0x01000003 | NV50_PDISPLAY_EVO_CTRL_DMA_ENABLED); - if (!nv_wait(dev, NV50_PDISPLAY_EVO_CTRL(id), 0x80000000, 0x00000000)) { - NV_ERROR(dev, "EvoCh %d init timeout: 0x%08x\n", id, - nv_rd32(dev, NV50_PDISPLAY_EVO_CTRL(id))); + if (!nv_wait(device, NV50_PDISPLAY_EVO_CTRL(id), 0x80000000, 0x00000000)) { + NV_ERROR(drm, "EvoCh %d init timeout: 0x%08x\n", id, + nv_rd32(device, NV50_PDISPLAY_EVO_CTRL(id))); return -EBUSY; } /* enable error reporting on the channel */ - nv_mask(dev, 0x610028, 0x00000000, 0x00010001 << id); + nv_mask(device, 0x610028, 0x00000000, 0x00010001 << id); evo->dma.max = (4096/4) - 2; evo->dma.max &= ~7; @@ -209,16 +217,17 @@ nv50_evo_channel_init(struct nouveau_channel *evo) static void nv50_evo_channel_fini(struct nouveau_channel *evo) { - struct drm_device *dev = evo->fence; + struct nouveau_drm *drm = evo->drm; + struct nouveau_device *device = nv_device(drm->device); int id = evo->handle; - nv_mask(dev, 0x610028, 0x00010001 << id, 0x00000000); - nv_mask(dev, NV50_PDISPLAY_EVO_CTRL(id), 0x00001010, 0x00001000); - nv_wr32(dev, NV50_PDISPLAY_INTR_0, (1 << id)); - nv_mask(dev, NV50_PDISPLAY_EVO_CTRL(id), 0x00000003, 0x00000000); - if (!nv_wait(dev, NV50_PDISPLAY_EVO_CTRL(id), 0x001e0000, 0x00000000)) { - NV_ERROR(dev, "EvoCh %d takedown timeout: 0x%08x\n", id, - nv_rd32(dev, NV50_PDISPLAY_EVO_CTRL(id))); + nv_mask(device, 0x610028, 0x00010001 << id, 0x00000000); + nv_mask(device, NV50_PDISPLAY_EVO_CTRL(id), 0x00001010, 0x00001000); + nv_wr32(device, NV50_PDISPLAY_INTR_0, (1 << id)); + nv_mask(device, NV50_PDISPLAY_EVO_CTRL(id), 0x00000003, 0x00000000); + if (!nv_wait(device, NV50_PDISPLAY_EVO_CTRL(id), 0x001e0000, 0x00000000)) { + NV_ERROR(drm, "EvoCh %d takedown timeout: 0x%08x\n", id, + nv_rd32(device, NV50_PDISPLAY_EVO_CTRL(id))); } } @@ -242,7 +251,8 @@ nv50_evo_destroy(struct drm_device *dev) int nv50_evo_create(struct drm_device *dev) { - struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_drm *drm = nouveau_drm(dev); + struct nouveau_fb *pfb = nouveau_fb(drm->device); struct nv50_display *disp = nv50_display(dev); struct nouveau_channel *evo; int ret, i, j; @@ -251,10 +261,10 @@ nv50_evo_create(struct drm_device *dev) * use this also as there's no per-channel support on the * hardware */ - ret = nouveau_gpuobj_new(dev, NULL, 32768, 65536, + ret = nouveau_gpuobj_new(drm->device, NULL, 32768, 65536, NVOBJ_FLAG_ZERO_ALLOC, &disp->ramin); if (ret) { - NV_ERROR(dev, "Error allocating EVO channel memory: %d\n", ret); + NV_ERROR(drm, "Error allocating EVO channel memory: %d\n", ret); goto err; } @@ -276,24 +286,24 @@ nv50_evo_create(struct drm_device *dev) /* create some default objects for the scanout memtypes we support */ ret = nv50_evo_dmaobj_new(disp->master, NvEvoVRAM, 0x0000, - 0, nvfb_vram_size(dev), NULL); + 0, pfb->ram.size, NULL); if (ret) goto err; ret = nv50_evo_dmaobj_new(disp->master, NvEvoVRAM_LP, 0x80000000, - 0, nvfb_vram_size(dev), NULL); + 0, pfb->ram.size, NULL); if (ret) goto err; ret = nv50_evo_dmaobj_new(disp->master, NvEvoFB32, 0x80000000 | - (dev_priv->chipset < 0xc0 ? 0x7a : 0xfe), - 0, nvfb_vram_size(dev), NULL); + (nv_device(drm->device)->chipset < 0xc0 ? 0x7a : 0xfe), + 0, pfb->ram.size, NULL); if (ret) goto err; ret = nv50_evo_dmaobj_new(disp->master, NvEvoFB16, 0x80000000 | - (dev_priv->chipset < 0xc0 ? 0x70 : 0xfe), - 0, nvfb_vram_size(dev), NULL); + (nv_device(drm->device)->chipset < 0xc0 ? 0x70 : 0xfe), + 0, pfb->ram.size, NULL); if (ret) goto err; @@ -328,21 +338,21 @@ nv50_evo_create(struct drm_device *dev) goto err; ret = nv50_evo_dmaobj_new(dispc->sync, NvEvoVRAM_LP, 0x80000000, - 0, nvfb_vram_size(dev), NULL); + 0, pfb->ram.size, NULL); if (ret) goto err; ret = nv50_evo_dmaobj_new(dispc->sync, NvEvoFB32, 0x80000000 | - (dev_priv->chipset < 0xc0 ? + (nv_device(drm->device)->chipset < 0xc0 ? 0x7a : 0xfe), - 0, nvfb_vram_size(dev), NULL); + 0, pfb->ram.size, NULL); if (ret) goto err; ret = nv50_evo_dmaobj_new(dispc->sync, NvEvoFB16, 0x80000000 | - (dev_priv->chipset < 0xc0 ? + (nv_device(drm->device)->chipset < 0xc0 ? 0x70 : 0xfe), - 0, nvfb_vram_size(dev), NULL); + 0, pfb->ram.size, NULL); if (ret) goto err; diff --git a/drivers/gpu/drm/nouveau/nv50_fbcon.c b/drivers/gpu/drm/nouveau/nv50_fbcon.c index 2028a4447124..52068a0910dc 100644 --- a/drivers/gpu/drm/nouveau/nv50_fbcon.c +++ b/drivers/gpu/drm/nouveau/nv50_fbcon.c @@ -30,7 +30,7 @@ int nv50_fbcon_fillrect(struct fb_info *info, const struct fb_fillrect *rect) { struct nouveau_fbdev *nfbdev = info->par; - struct nouveau_drm *drm = nouveau_newpriv(nfbdev->dev); + struct nouveau_drm *drm = nouveau_drm(nfbdev->dev); struct nouveau_channel *chan = drm->channel; int ret; @@ -65,7 +65,7 @@ int nv50_fbcon_copyarea(struct fb_info *info, const struct fb_copyarea *region) { struct nouveau_fbdev *nfbdev = info->par; - struct nouveau_drm *drm = nouveau_newpriv(nfbdev->dev); + struct nouveau_drm *drm = nouveau_drm(nfbdev->dev); struct nouveau_channel *chan = drm->channel; int ret; @@ -93,7 +93,7 @@ int nv50_fbcon_imageblit(struct fb_info *info, const struct fb_image *image) { struct nouveau_fbdev *nfbdev = info->par; - struct nouveau_drm *drm = nouveau_newpriv(nfbdev->dev); + struct nouveau_drm *drm = nouveau_drm(nfbdev->dev); struct nouveau_channel *chan = drm->channel; uint32_t width, dwords, *data = (uint32_t *)image->data; uint32_t mask = ~(~0 >> (32 - info->var.bits_per_pixel)); @@ -152,7 +152,7 @@ nv50_fbcon_accel_init(struct fb_info *info) struct nouveau_fbdev *nfbdev = info->par; struct nouveau_framebuffer *fb = &nfbdev->nouveau_fb; struct drm_device *dev = nfbdev->dev; - struct nouveau_drm *drm = nouveau_newpriv(dev); + struct nouveau_drm *drm = nouveau_drm(dev); struct nouveau_channel *chan = drm->channel; struct nouveau_object *object; int ret, format; diff --git a/drivers/gpu/drm/nouveau/nv50_fence.c b/drivers/gpu/drm/nouveau/nv50_fence.c index e717aaaf62c6..e0763ea88ee2 100644 --- a/drivers/gpu/drm/nouveau/nv50_fence.c +++ b/drivers/gpu/drm/nouveau/nv50_fence.c @@ -29,6 +29,8 @@ #include "nouveau_dma.h" #include "nouveau_fence.h" +#include "nv50_display.h" + struct nv50_fence_chan { struct nouveau_fence_chan base; }; @@ -43,6 +45,7 @@ struct nv50_fence_priv { static int nv50_fence_context_new(struct nouveau_channel *chan) { + struct drm_device *dev = chan->drm->dev; struct nv50_fence_priv *priv = chan->drm->fence; struct nv50_fence_chan *fctx; struct ttm_mem_reg *mem = &priv->bo->bo.mem; @@ -66,8 +69,8 @@ nv50_fence_context_new(struct nouveau_channel *chan) &object); /* dma objects for display sync channel semaphore blocks */ - for (i = 0; !ret && i < chan->drm->dev->mode_config.num_crtc; i++) { - struct nouveau_bo *bo = nv50sema(chan->drm->dev, i); + for (i = 0; !ret && i < dev->mode_config.num_crtc; i++) { + struct nouveau_bo *bo = nv50_display_crtc_sema(dev, i); ret = nouveau_object_new(nv_object(chan->cli), chan->handle, NvEvoSema0 + i, 0x003d, diff --git a/drivers/gpu/drm/nouveau/nv50_pm.c b/drivers/gpu/drm/nouveau/nv50_pm.c index ac0208438ace..0036c8c966de 100644 --- a/drivers/gpu/drm/nouveau/nv50_pm.c +++ b/drivers/gpu/drm/nouveau/nv50_pm.c @@ -23,12 +23,19 @@ */ #include "drmP.h" -#include "nouveau_drv.h" -#include +#include "nouveau_drm.h" +#include "nouveau_bios.h" #include "nouveau_hw.h" #include "nouveau_pm.h" #include "nouveau_hwsq.h" +#include "nv50_display.h" + +#include +#include +#include +#include + enum clk_src { clk_src_crystal, clk_src_href, @@ -48,19 +55,20 @@ static u32 read_clk(struct drm_device *, enum clk_src); static u32 read_div(struct drm_device *dev) { - struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_device *device = nouveau_dev(dev); + struct nouveau_drm *drm = nouveau_drm(dev); - switch (dev_priv->chipset) { + switch (nv_device(drm->device)->chipset) { case 0x50: /* it exists, but only has bit 31, not the dividers.. */ case 0x84: case 0x86: case 0x98: case 0xa0: - return nv_rd32(dev, 0x004700); + return nv_rd32(device, 0x004700); case 0x92: case 0x94: case 0x96: - return nv_rd32(dev, 0x004800); + return nv_rd32(device, 0x004800); default: return 0x00000000; } @@ -69,12 +77,13 @@ read_div(struct drm_device *dev) static u32 read_pll_src(struct drm_device *dev, u32 base) { - struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_device *device = nouveau_dev(dev); + struct nouveau_drm *drm = nouveau_drm(dev); u32 coef, ref = read_clk(dev, clk_src_crystal); - u32 rsel = nv_rd32(dev, 0x00e18c); + u32 rsel = nv_rd32(device, 0x00e18c); int P, N, M, id; - switch (dev_priv->chipset) { + switch (nv_device(drm->device)->chipset) { case 0x50: case 0xa0: switch (base) { @@ -83,11 +92,11 @@ read_pll_src(struct drm_device *dev, u32 base) case 0x4008: id = !!(rsel & 0x00000008); break; case 0x4030: id = 0; break; default: - NV_ERROR(dev, "ref: bad pll 0x%06x\n", base); + NV_ERROR(drm, "ref: bad pll 0x%06x\n", base); return 0; } - coef = nv_rd32(dev, 0x00e81c + (id * 0x0c)); + coef = nv_rd32(device, 0x00e81c + (id * 0x0c)); ref *= (coef & 0x01000000) ? 2 : 4; P = (coef & 0x00070000) >> 16; N = ((coef & 0x0000ff00) >> 8) + 1; @@ -96,7 +105,7 @@ read_pll_src(struct drm_device *dev, u32 base) case 0x84: case 0x86: case 0x92: - coef = nv_rd32(dev, 0x00e81c); + coef = nv_rd32(device, 0x00e81c); P = (coef & 0x00070000) >> 16; N = (coef & 0x0000ff00) >> 8; M = (coef & 0x000000ff) >> 0; @@ -104,14 +113,14 @@ read_pll_src(struct drm_device *dev, u32 base) case 0x94: case 0x96: case 0x98: - rsel = nv_rd32(dev, 0x00c050); + rsel = nv_rd32(device, 0x00c050); switch (base) { case 0x4020: rsel = (rsel & 0x00000003) >> 0; break; case 0x4008: rsel = (rsel & 0x0000000c) >> 2; break; case 0x4028: rsel = (rsel & 0x00001800) >> 11; break; case 0x4030: rsel = 3; break; default: - NV_ERROR(dev, "ref: bad pll 0x%06x\n", base); + NV_ERROR(drm, "ref: bad pll 0x%06x\n", base); return 0; } @@ -122,8 +131,8 @@ read_pll_src(struct drm_device *dev, u32 base) case 3: id = 0; break; } - coef = nv_rd32(dev, 0x00e81c + (id * 0x28)); - P = (nv_rd32(dev, 0x00e824 + (id * 0x28)) >> 16) & 7; + coef = nv_rd32(device, 0x00e81c + (id * 0x28)); + P = (nv_rd32(device, 0x00e824 + (id * 0x28)) >> 16) & 7; P += (coef & 0x00070000) >> 16; N = (coef & 0x0000ff00) >> 8; M = (coef & 0x000000ff) >> 0; @@ -140,7 +149,9 @@ read_pll_src(struct drm_device *dev, u32 base) static u32 read_pll_ref(struct drm_device *dev, u32 base) { - u32 src, mast = nv_rd32(dev, 0x00c040); + struct nouveau_device *device = nouveau_dev(dev); + struct nouveau_drm *drm = nouveau_drm(dev); + u32 src, mast = nv_rd32(device, 0x00c040); switch (base) { case 0x004028: @@ -158,7 +169,7 @@ read_pll_ref(struct drm_device *dev, u32 base) case 0x00e810: return read_clk(dev, clk_src_crystal); default: - NV_ERROR(dev, "bad pll 0x%06x\n", base); + NV_ERROR(drm, "bad pll 0x%06x\n", base); return 0; } @@ -170,17 +181,18 @@ read_pll_ref(struct drm_device *dev, u32 base) static u32 read_pll(struct drm_device *dev, u32 base) { - struct drm_nouveau_private *dev_priv = dev->dev_private; - u32 mast = nv_rd32(dev, 0x00c040); - u32 ctrl = nv_rd32(dev, base + 0); - u32 coef = nv_rd32(dev, base + 4); + struct nouveau_device *device = nouveau_dev(dev); + struct nouveau_drm *drm = nouveau_drm(dev); + u32 mast = nv_rd32(device, 0x00c040); + u32 ctrl = nv_rd32(device, base + 0); + u32 coef = nv_rd32(device, base + 4); u32 ref = read_pll_ref(dev, base); u32 clk = 0; int N1, N2, M1, M2; if (base == 0x004028 && (mast & 0x00100000)) { /* wtf, appears to only disable post-divider on nva0 */ - if (dev_priv->chipset != 0xa0) + if (nv_device(drm->device)->chipset != 0xa0) return read_clk(dev, clk_src_dom6); } @@ -204,13 +216,14 @@ read_pll(struct drm_device *dev, u32 base) static u32 read_clk(struct drm_device *dev, enum clk_src src) { - struct drm_nouveau_private *dev_priv = dev->dev_private; - u32 mast = nv_rd32(dev, 0x00c040); + struct nouveau_device *device = nouveau_dev(dev); + struct nouveau_drm *drm = nouveau_drm(dev); + u32 mast = nv_rd32(device, 0x00c040); u32 P = 0; switch (src) { case clk_src_crystal: - return dev_priv->crystal; + return device->crystal; case clk_src_href: return 100000; /* PCIE reference clock */ case clk_src_hclk: @@ -229,7 +242,7 @@ read_clk(struct drm_device *dev, enum clk_src src) break; case clk_src_nvclk: if (!(mast & 0x00100000)) - P = (nv_rd32(dev, 0x004028) & 0x00070000) >> 16; + P = (nv_rd32(device, 0x004028) & 0x00070000) >> 16; switch (mast & 0x00000003) { case 0x00000000: return read_clk(dev, clk_src_crystal) >> P; case 0x00000001: return read_clk(dev, clk_src_dom6); @@ -238,7 +251,7 @@ read_clk(struct drm_device *dev, enum clk_src src) } break; case clk_src_sclk: - P = (nv_rd32(dev, 0x004020) & 0x00070000) >> 16; + P = (nv_rd32(device, 0x004020) & 0x00070000) >> 16; switch (mast & 0x00000030) { case 0x00000000: if (mast & 0x00000080) @@ -250,8 +263,8 @@ read_clk(struct drm_device *dev, enum clk_src src) } break; case clk_src_mclk: - P = (nv_rd32(dev, 0x004008) & 0x00070000) >> 16; - if (nv_rd32(dev, 0x004008) & 0x00000200) { + P = (nv_rd32(device, 0x004008) & 0x00070000) >> 16; + if (nv_rd32(device, 0x004008) & 0x00000200) { switch (mast & 0x0000c000) { case 0x00000000: return read_clk(dev, clk_src_crystal) >> P; @@ -265,7 +278,7 @@ read_clk(struct drm_device *dev, enum clk_src src) break; case clk_src_vdec: P = (read_div(dev) & 0x00000700) >> 8; - switch (dev_priv->chipset) { + switch (nv_device(drm->device)->chipset) { case 0x84: case 0x86: case 0x92: @@ -274,7 +287,7 @@ read_clk(struct drm_device *dev, enum clk_src src) case 0xa0: switch (mast & 0x00000c00) { case 0x00000000: - if (dev_priv->chipset == 0xa0) /* wtf?? */ + if (nv_device(drm->device)->chipset == 0xa0) /* wtf?? */ return read_clk(dev, clk_src_nvclk) >> P; return read_clk(dev, clk_src_crystal) >> P; case 0x00000400: @@ -302,7 +315,7 @@ read_clk(struct drm_device *dev, enum clk_src src) } break; case clk_src_dom6: - switch (dev_priv->chipset) { + switch (nv_device(drm->device)->chipset) { case 0x50: case 0xa0: return read_pll(dev, 0x00e810) >> 2; @@ -328,22 +341,22 @@ read_clk(struct drm_device *dev, enum clk_src src) break; } - NV_DEBUG(dev, "unknown clock source %d 0x%08x\n", src, mast); + NV_DEBUG(drm, "unknown clock source %d 0x%08x\n", src, mast); return 0; } int nv50_pm_clocks_get(struct drm_device *dev, struct nouveau_pm_level *perflvl) { - struct drm_nouveau_private *dev_priv = dev->dev_private; - if (dev_priv->chipset == 0xaa || - dev_priv->chipset == 0xac) + struct nouveau_drm *drm = nouveau_drm(dev); + if (nv_device(drm->device)->chipset == 0xaa || + nv_device(drm->device)->chipset == 0xac) return 0; perflvl->core = read_clk(dev, clk_src_nvclk); perflvl->shader = read_clk(dev, clk_src_sclk); perflvl->memory = read_clk(dev, clk_src_mclk); - if (dev_priv->chipset != 0x50) { + if (nv_device(drm->device)->chipset != 0x50) { perflvl->vdec = read_clk(dev, clk_src_vdec); perflvl->dom6 = read_clk(dev, clk_src_dom6); } @@ -365,10 +378,13 @@ static u32 calc_pll(struct drm_device *dev, u32 reg, struct nvbios_pll *pll, u32 clk, int *N1, int *M1, int *log2P) { + struct nouveau_device *device = nouveau_dev(dev); + struct nouveau_bios *bios = nouveau_bios(device); + struct nouveau_clock *pclk = nouveau_clock(device); struct nouveau_pll_vals coef; int ret; - ret = get_pll_limits(dev, reg, pll); + ret = nvbios_pll_parse(bios, reg, pll); if (ret) return 0; @@ -377,7 +393,7 @@ calc_pll(struct drm_device *dev, u32 reg, struct nvbios_pll *pll, if (!pll->refclk) return 0; - ret = nouveau_calc_pll_mnp(dev, pll, clk, &coef); + ret = pclk->pll_calc(pclk, pll, clk, &coef); if (ret == 0) return 0; @@ -460,26 +476,29 @@ mclk_wait(struct nouveau_mem_exec_func *exec, u32 nsec) static u32 mclk_mrg(struct nouveau_mem_exec_func *exec, int mr) { + struct nouveau_device *device = nouveau_dev(exec->dev); if (mr <= 1) - return nv_rd32(exec->dev, 0x1002c0 + ((mr - 0) * 4)); + return nv_rd32(device, 0x1002c0 + ((mr - 0) * 4)); if (mr <= 3) - return nv_rd32(exec->dev, 0x1002e0 + ((mr - 2) * 4)); + return nv_rd32(device, 0x1002e0 + ((mr - 2) * 4)); return 0; } static void mclk_mrs(struct nouveau_mem_exec_func *exec, int mr, u32 data) { + struct nouveau_device *device = nouveau_dev(exec->dev); + struct nouveau_fb *pfb = nouveau_fb(device); struct nv50_pm_state *info = exec->priv; struct hwsq_ucode *hwsq = &info->mclk_hwsq; if (mr <= 1) { - if (nvfb_vram_rank_B(exec->dev)) + if (pfb->ram.ranks > 1) hwsq_wr32(hwsq, 0x1002c8 + ((mr - 0) * 4), data); hwsq_wr32(hwsq, 0x1002c0 + ((mr - 0) * 4), data); } else if (mr <= 3) { - if (nvfb_vram_rank_B(exec->dev)) + if (pfb->ram.ranks > 1) hwsq_wr32(hwsq, 0x1002e8 + ((mr - 2) * 4), data); hwsq_wr32(hwsq, 0x1002e0 + ((mr - 2) * 4), data); } @@ -488,11 +507,12 @@ mclk_mrs(struct nouveau_mem_exec_func *exec, int mr, u32 data) static void mclk_clock_set(struct nouveau_mem_exec_func *exec) { + struct nouveau_device *device = nouveau_dev(exec->dev); struct nv50_pm_state *info = exec->priv; struct hwsq_ucode *hwsq = &info->mclk_hwsq; - u32 ctrl = nv_rd32(exec->dev, 0x004008); + u32 ctrl = nv_rd32(device, 0x004008); - info->mmast = nv_rd32(exec->dev, 0x00c040); + info->mmast = nv_rd32(device, 0x00c040); info->mmast &= ~0xc0000000; /* get MCLK_2 from HREF */ info->mmast |= 0x0000c000; /* use MCLK_2 as MPLL_BYPASS clock */ @@ -506,7 +526,7 @@ mclk_clock_set(struct nouveau_mem_exec_func *exec) static void mclk_timing_set(struct nouveau_mem_exec_func *exec) { - struct drm_device *dev = exec->dev; + struct nouveau_device *device = nouveau_dev(exec->dev); struct nv50_pm_state *info = exec->priv; struct nouveau_pm_level *perflvl = info->perflvl; struct hwsq_ucode *hwsq = &info->mclk_hwsq; @@ -514,7 +534,7 @@ mclk_timing_set(struct nouveau_mem_exec_func *exec) for (i = 0; i < 9; i++) { u32 reg = 0x100220 + (i * 4); - u32 val = nv_rd32(dev, reg); + u32 val = nv_rd32(device, reg); if (val != perflvl->timing.reg[i]) hwsq_wr32(hwsq, reg, perflvl->timing.reg[i]); } @@ -524,7 +544,8 @@ static int calc_mclk(struct drm_device *dev, struct nouveau_pm_level *perflvl, struct nv50_pm_state *info) { - struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_drm *drm = nouveau_drm(dev); + struct nouveau_device *device = nouveau_dev(dev); u32 crtc_mask = nv50_display_active_crtcs(dev); struct nouveau_mem_exec_func exec = { .dev = dev, @@ -545,7 +566,7 @@ calc_mclk(struct drm_device *dev, struct nouveau_pm_level *perflvl, int ret; /* use pcie refclock if possible, otherwise use mpll */ - info->mctrl = nv_rd32(dev, 0x004008); + info->mctrl = nv_rd32(device, 0x004008); info->mctrl &= ~0x81ff0200; if (clk_same(perflvl->memory, read_clk(dev, clk_src_href))) { info->mctrl |= 0x00000200 | (pll.bias_p << 19); @@ -565,7 +586,7 @@ calc_mclk(struct drm_device *dev, struct nouveau_pm_level *perflvl, hwsq_op5f(hwsq, crtc_mask, 0x00); /* wait for scanout */ hwsq_op5f(hwsq, crtc_mask, 0x01); /* wait for vblank */ } - if (dev_priv->chipset >= 0x92) + if (nv_device(drm->device)->chipset >= 0x92) hwsq_wr32(hwsq, 0x611200, 0x00003300); /* disable scanout */ hwsq_setf(hwsq, 0x10, 0); /* disable bus access */ hwsq_op5f(hwsq, 0x00, 0x01); /* no idea :s */ @@ -576,7 +597,7 @@ calc_mclk(struct drm_device *dev, struct nouveau_pm_level *perflvl, hwsq_setf(hwsq, 0x10, 1); /* enable bus access */ hwsq_op5f(hwsq, 0x00, 0x00); /* no idea, reverse of 0x00, 0x01? */ - if (dev_priv->chipset >= 0x92) + if (nv_device(drm->device)->chipset >= 0x92) hwsq_wr32(hwsq, 0x611200, 0x00003330); /* enable scanout */ hwsq_fini(hwsq); return 0; @@ -585,7 +606,8 @@ calc_mclk(struct drm_device *dev, struct nouveau_pm_level *perflvl, void * nv50_pm_clocks_pre(struct drm_device *dev, struct nouveau_pm_level *perflvl) { - struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_device *device = nouveau_dev(dev); + struct nouveau_drm *drm = nouveau_drm(dev); struct nv50_pm_state *info; struct hwsq_ucode *hwsq; struct nvbios_pll pll; @@ -593,8 +615,8 @@ nv50_pm_clocks_pre(struct drm_device *dev, struct nouveau_pm_level *perflvl) int clk, ret = -EINVAL; int N, M, P1, P2; - if (dev_priv->chipset == 0xaa || - dev_priv->chipset == 0xac) + if (nv_device(drm->device)->chipset == 0xaa || + nv_device(drm->device)->chipset == 0xac) return ERR_PTR(-ENODEV); info = kmalloc(sizeof(*info), GFP_KERNEL); @@ -643,7 +665,7 @@ nv50_pm_clocks_pre(struct drm_device *dev, struct nouveau_pm_level *perflvl) clk = calc_div(perflvl->core, perflvl->vdec, &P1); /* see how close we can get using xpll/hclk as a source */ - if (dev_priv->chipset != 0x98) + if (nv_device(drm->device)->chipset != 0x98) out = read_pll(dev, 0x004030); else out = read_clk(dev, clk_src_hclkm3d2); @@ -652,7 +674,7 @@ nv50_pm_clocks_pre(struct drm_device *dev, struct nouveau_pm_level *perflvl) /* select whichever gets us closest */ if (abs((int)perflvl->vdec - clk) <= abs((int)perflvl->vdec - out)) { - if (dev_priv->chipset != 0x98) + if (nv_device(drm->device)->chipset != 0x98) mast |= 0x00000c00; divs |= P1 << 8; } else { @@ -680,7 +702,7 @@ nv50_pm_clocks_pre(struct drm_device *dev, struct nouveau_pm_level *perflvl) } /* vdec/dom6: complete switch to new clocks */ - switch (dev_priv->chipset) { + switch (nv_device(drm->device)->chipset) { case 0x92: case 0x94: case 0x96: @@ -696,7 +718,7 @@ nv50_pm_clocks_pre(struct drm_device *dev, struct nouveau_pm_level *perflvl) /* core/shader: make sure sclk/nvclk are disconnected from their * PLLs (nvclk to dom6, sclk to hclk) */ - if (dev_priv->chipset < 0x92) + if (nv_device(drm->device)->chipset < 0x92) mast = (mast & ~0x001000b0) | 0x00100080; else mast = (mast & ~0x000000b3) | 0x00000081; @@ -708,7 +730,7 @@ nv50_pm_clocks_pre(struct drm_device *dev, struct nouveau_pm_level *perflvl) if (clk == 0) goto error; - ctrl = nv_rd32(dev, 0x004028) & ~0xc03f0100; + ctrl = nv_rd32(device, 0x004028) & ~0xc03f0100; mast &= ~0x00100000; mast |= 3; @@ -721,7 +743,7 @@ nv50_pm_clocks_pre(struct drm_device *dev, struct nouveau_pm_level *perflvl) * cases will be handled by tying to nvclk, but it's possible there's * corners */ - ctrl = nv_rd32(dev, 0x004020) & ~0xc03f0100; + ctrl = nv_rd32(device, 0x004020) & ~0xc03f0100; if (P1-- && perflvl->shader == (perflvl->core << 1)) { hwsq_wr32(hwsq, 0x004020, (P1 << 19) | (P1 << 16) | ctrl); @@ -750,11 +772,12 @@ error: static int prog_hwsq(struct drm_device *dev, struct hwsq_ucode *hwsq) { - struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_device *device = nouveau_dev(dev); + struct nouveau_drm *drm = nouveau_drm(dev); u32 hwsq_data, hwsq_kick; int i; - if (dev_priv->chipset < 0x94) { + if (nv_device(drm->device)->chipset < 0x94) { hwsq_data = 0x001400; hwsq_kick = 0x00000003; } else { @@ -762,22 +785,22 @@ prog_hwsq(struct drm_device *dev, struct hwsq_ucode *hwsq) hwsq_kick = 0x00000001; } /* upload hwsq ucode */ - nv_mask(dev, 0x001098, 0x00000008, 0x00000000); - nv_wr32(dev, 0x001304, 0x00000000); - if (dev_priv->chipset >= 0x92) - nv_wr32(dev, 0x001318, 0x00000000); + nv_mask(device, 0x001098, 0x00000008, 0x00000000); + nv_wr32(device, 0x001304, 0x00000000); + if (nv_device(drm->device)->chipset >= 0x92) + nv_wr32(device, 0x001318, 0x00000000); for (i = 0; i < hwsq->len / 4; i++) - nv_wr32(dev, hwsq_data + (i * 4), hwsq->ptr.u32[i]); - nv_mask(dev, 0x001098, 0x00000018, 0x00000018); + nv_wr32(device, hwsq_data + (i * 4), hwsq->ptr.u32[i]); + nv_mask(device, 0x001098, 0x00000018, 0x00000018); /* launch, and wait for completion */ - nv_wr32(dev, 0x00130c, hwsq_kick); - if (!nv_wait(dev, 0x001308, 0x00000100, 0x00000000)) { - NV_ERROR(dev, "hwsq ucode exec timed out\n"); - NV_ERROR(dev, "0x001308: 0x%08x\n", nv_rd32(dev, 0x001308)); + nv_wr32(device, 0x00130c, hwsq_kick); + if (!nv_wait(device, 0x001308, 0x00000100, 0x00000000)) { + NV_ERROR(drm, "hwsq ucode exec timed out\n"); + NV_ERROR(drm, "0x001308: 0x%08x\n", nv_rd32(device, 0x001308)); for (i = 0; i < hwsq->len / 4; i++) { - NV_ERROR(dev, "0x%06x: 0x%08x\n", 0x1400 + (i * 4), - nv_rd32(dev, 0x001400 + (i * 4))); + NV_ERROR(drm, "0x%06x: 0x%08x\n", 0x1400 + (i * 4), + nv_rd32(device, 0x001400 + (i * 4))); } return -EIO; @@ -789,20 +812,22 @@ prog_hwsq(struct drm_device *dev, struct hwsq_ucode *hwsq) int nv50_pm_clocks_set(struct drm_device *dev, void *data) { + struct nouveau_device *device = nouveau_dev(dev); struct nv50_pm_state *info = data; struct bit_entry M; int ret = -EBUSY; /* halt and idle execution engines */ - nv_mask(dev, 0x002504, 0x00000001, 0x00000001); - if (!nv_wait(dev, 0x002504, 0x00000010, 0x00000010)) + nv_mask(device, 0x002504, 0x00000001, 0x00000001); + if (!nv_wait(device, 0x002504, 0x00000010, 0x00000010)) goto resume; - if (!nv_wait(dev, 0x00251c, 0x0000003f, 0x0000003f)) + if (!nv_wait(device, 0x00251c, 0x0000003f, 0x0000003f)) goto resume; /* program memory clock, if necessary - must come before engine clock * reprogramming due to how we construct the hwsq scripts in pre() */ +#define nouveau_bios_init_exec(a,b) nouveau_bios_run_init_table((a), (b), NULL, 0) if (info->mclk_hwsq.len) { /* execute some scripts that do ??? from the vbios.. */ if (!bit_table(dev, 'M', &M) && M.version == 1) { @@ -824,7 +849,7 @@ nv50_pm_clocks_set(struct drm_device *dev, void *data) ret = prog_hwsq(dev, &info->eclk_hwsq); resume: - nv_mask(dev, 0x002504, 0x00000001, 0x00000000); + nv_mask(device, 0x002504, 0x00000001, 0x00000000); kfree(info); return ret; } @@ -832,6 +857,8 @@ resume: static int pwm_info(struct drm_device *dev, int *line, int *ctrl, int *indx) { + struct nouveau_drm *drm = nouveau_drm(dev); + if (*line == 0x04) { *ctrl = 0x00e100; *line = 4; @@ -847,7 +874,7 @@ pwm_info(struct drm_device *dev, int *line, int *ctrl, int *indx) *line = 0; *indx = 0; } else { - NV_ERROR(dev, "unknown pwm ctrl for gpio %d\n", *line); + NV_ERROR(drm, "unknown pwm ctrl for gpio %d\n", *line); return -ENODEV; } @@ -857,13 +884,14 @@ pwm_info(struct drm_device *dev, int *line, int *ctrl, int *indx) int nv50_pm_pwm_get(struct drm_device *dev, int line, u32 *divs, u32 *duty) { + struct nouveau_device *device = nouveau_dev(dev); int ctrl, id, ret = pwm_info(dev, &line, &ctrl, &id); if (ret) return ret; - if (nv_rd32(dev, ctrl) & (1 << line)) { - *divs = nv_rd32(dev, 0x00e114 + (id * 8)); - *duty = nv_rd32(dev, 0x00e118 + (id * 8)); + if (nv_rd32(device, ctrl) & (1 << line)) { + *divs = nv_rd32(device, 0x00e114 + (id * 8)); + *duty = nv_rd32(device, 0x00e118 + (id * 8)); return 0; } @@ -873,12 +901,13 @@ nv50_pm_pwm_get(struct drm_device *dev, int line, u32 *divs, u32 *duty) int nv50_pm_pwm_set(struct drm_device *dev, int line, u32 divs, u32 duty) { + struct nouveau_device *device = nouveau_dev(dev); int ctrl, id, ret = pwm_info(dev, &line, &ctrl, &id); if (ret) return ret; - nv_mask(dev, ctrl, 0x00010001 << line, 0x00000001 << line); - nv_wr32(dev, 0x00e114 + (id * 8), divs); - nv_wr32(dev, 0x00e118 + (id * 8), duty | 0x80000000); + nv_mask(device, ctrl, 0x00010001 << line, 0x00000001 << line); + nv_wr32(device, 0x00e114 + (id * 8), divs); + nv_wr32(device, 0x00e118 + (id * 8), duty | 0x80000000); return 0; } diff --git a/drivers/gpu/drm/nouveau/nv50_sor.c b/drivers/gpu/drm/nouveau/nv50_sor.c index 2e6d83b37a0f..48644e379e86 100644 --- a/drivers/gpu/drm/nouveau/nv50_sor.c +++ b/drivers/gpu/drm/nouveau/nv50_sor.c @@ -29,20 +29,22 @@ #define NOUVEAU_DMA_DEBUG (nouveau_reg_debug & NOUVEAU_REG_DEBUG_EVO) #include "nouveau_reg.h" -#include "nouveau_drv.h" +#include "nouveau_drm.h" #include "nouveau_dma.h" #include "nouveau_encoder.h" #include "nouveau_connector.h" #include "nouveau_crtc.h" #include "nv50_display.h" +#include + static u32 nv50_sor_dp_lane_map(struct drm_device *dev, struct dcb_output *dcb, u8 lane) { - struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_drm *drm = nouveau_drm(dev); static const u8 nvaf[] = { 24, 16, 8, 0 }; /* thanks, apple.. */ static const u8 nv50[] = { 16, 8, 0, 24 }; - if (dev_priv->chipset == 0xaf) + if (nv_device(drm->device)->chipset == 0xaf) return nvaf[lane]; return nv50[lane]; } @@ -50,14 +52,17 @@ nv50_sor_dp_lane_map(struct drm_device *dev, struct dcb_output *dcb, u8 lane) static void nv50_sor_dp_train_set(struct drm_device *dev, struct dcb_output *dcb, u8 pattern) { + struct nouveau_device *device = nouveau_dev(dev); u32 or = ffs(dcb->or) - 1, link = !(dcb->sorconf.link & 1); - nv_mask(dev, NV50_SOR_DP_CTRL(or, link), 0x0f000000, pattern << 24); + nv_mask(device, NV50_SOR_DP_CTRL(or, link), 0x0f000000, pattern << 24); } static void nv50_sor_dp_train_adj(struct drm_device *dev, struct dcb_output *dcb, u8 lane, u8 swing, u8 preem) { + struct nouveau_device *device = nouveau_dev(dev); + struct nouveau_drm *drm = nouveau_drm(dev); u32 or = ffs(dcb->or) - 1, link = !(dcb->sorconf.link & 1); u32 shift = nv50_sor_dp_lane_map(dev, dcb, lane); u32 mask = 0x000000ff << shift; @@ -65,7 +70,7 @@ nv50_sor_dp_train_adj(struct drm_device *dev, struct dcb_output *dcb, table = nouveau_dp_bios_data(dev, dcb, &entry); if (!table || (table[0] != 0x20 && table[0] != 0x21)) { - NV_ERROR(dev, "PDISP: unsupported DP table for chipset\n"); + NV_ERROR(drm, "PDISP: unsupported DP table for chipset\n"); return; } @@ -76,24 +81,26 @@ nv50_sor_dp_train_adj(struct drm_device *dev, struct dcb_output *dcb, return; } - nv_mask(dev, NV50_SOR_DP_UNK118(or, link), mask, config[2] << shift); - nv_mask(dev, NV50_SOR_DP_UNK120(or, link), mask, config[3] << shift); - nv_mask(dev, NV50_SOR_DP_UNK130(or, link), 0x0000ff00, config[4] << 8); + nv_mask(device, NV50_SOR_DP_UNK118(or, link), mask, config[2] << shift); + nv_mask(device, NV50_SOR_DP_UNK120(or, link), mask, config[3] << shift); + nv_mask(device, NV50_SOR_DP_UNK130(or, link), 0x0000ff00, config[4] << 8); } static void nv50_sor_dp_link_set(struct drm_device *dev, struct dcb_output *dcb, int crtc, int link_nr, u32 link_bw, bool enhframe) { + struct nouveau_device *device = nouveau_dev(dev); + struct nouveau_drm *drm = nouveau_drm(dev); u32 or = ffs(dcb->or) - 1, link = !(dcb->sorconf.link & 1); - u32 dpctrl = nv_rd32(dev, NV50_SOR_DP_CTRL(or, link)) & ~0x001f4000; - u32 clksor = nv_rd32(dev, 0x614300 + (or * 0x800)) & ~0x000c0000; + u32 dpctrl = nv_rd32(device, NV50_SOR_DP_CTRL(or, link)) & ~0x001f4000; + u32 clksor = nv_rd32(device, 0x614300 + (or * 0x800)) & ~0x000c0000; u8 *table, *entry, mask; int i; table = nouveau_dp_bios_data(dev, dcb, &entry); if (!table || (table[0] != 0x20 && table[0] != 0x21)) { - NV_ERROR(dev, "PDISP: unsupported DP table for chipset\n"); + NV_ERROR(drm, "PDISP: unsupported DP table for chipset\n"); return; } @@ -112,20 +119,21 @@ nv50_sor_dp_link_set(struct drm_device *dev, struct dcb_output *dcb, int crtc, if (link_bw > 162000) clksor |= 0x00040000; - nv_wr32(dev, 0x614300 + (or * 0x800), clksor); - nv_wr32(dev, NV50_SOR_DP_CTRL(or, link), dpctrl); + nv_wr32(device, 0x614300 + (or * 0x800), clksor); + nv_wr32(device, NV50_SOR_DP_CTRL(or, link), dpctrl); mask = 0; for (i = 0; i < link_nr; i++) mask |= 1 << (nv50_sor_dp_lane_map(dev, dcb, i) >> 3); - nv_mask(dev, NV50_SOR_DP_UNK130(or, link), 0x0000000f, mask); + nv_mask(device, NV50_SOR_DP_UNK130(or, link), 0x0000000f, mask); } static void nv50_sor_dp_link_get(struct drm_device *dev, u32 or, u32 link, u32 *nr, u32 *bw) { - u32 dpctrl = nv_rd32(dev, NV50_SOR_DP_CTRL(or, link)) & 0x000f0000; - u32 clksor = nv_rd32(dev, 0x614300 + (or * 0x800)); + struct nouveau_device *device = nouveau_dev(dev); + u32 dpctrl = nv_rd32(device, NV50_SOR_DP_CTRL(or, link)) & 0x000f0000; + u32 clksor = nv_rd32(device, 0x614300 + (or * 0x800)); if (clksor & 0x000c0000) *bw = 270000; else @@ -139,6 +147,8 @@ nv50_sor_dp_link_get(struct drm_device *dev, u32 or, u32 link, u32 *nr, u32 *bw) void nv50_sor_dp_calc_tu(struct drm_device *dev, int or, int link, u32 clk, u32 bpp) { + struct nouveau_device *device = nouveau_dev(dev); + struct nouveau_drm *drm = nouveau_drm(dev); const u32 symbol = 100000; int bestTU = 0, bestVTUi = 0, bestVTUf = 0, bestVTUa = 0; int TU, VTUi, VTUf, VTUa; @@ -206,7 +216,7 @@ nv50_sor_dp_calc_tu(struct drm_device *dev, int or, int link, u32 clk, u32 bpp) } if (!bestTU) { - NV_ERROR(dev, "DP: unable to find suitable config\n"); + NV_ERROR(drm, "DP: unable to find suitable config\n"); return; } @@ -217,8 +227,8 @@ nv50_sor_dp_calc_tu(struct drm_device *dev, int or, int link, u32 clk, u32 bpp) r = do_div(unk, symbol); unk += 6; - nv_mask(dev, NV50_SOR_DP_CTRL(or, link), 0x000001fc, bestTU << 2); - nv_mask(dev, NV50_SOR_DP_SCFG(or, link), 0x010f7f3f, bestVTUa << 24 | + nv_mask(device, NV50_SOR_DP_CTRL(or, link), 0x000001fc, bestTU << 2); + nv_mask(device, NV50_SOR_DP_SCFG(or, link), 0x010f7f3f, bestVTUa << 24 | bestVTUf << 16 | bestVTUi << 8 | unk); @@ -227,6 +237,7 @@ static void nv50_sor_disconnect(struct drm_encoder *encoder) { struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); + struct nouveau_drm *drm = nouveau_drm(encoder->dev); struct drm_device *dev = encoder->dev; struct nouveau_channel *evo = nv50_display(dev)->master; int ret; @@ -235,11 +246,11 @@ nv50_sor_disconnect(struct drm_encoder *encoder) return; nv50_crtc_blank(nouveau_crtc(nv_encoder->crtc), true); - NV_DEBUG_KMS(dev, "Disconnecting SOR %d\n", nv_encoder->or); + NV_DEBUG(drm, "Disconnecting SOR %d\n", nv_encoder->or); ret = RING_SPACE(evo, 4); if (ret) { - NV_ERROR(dev, "no space while disconnecting SOR\n"); + NV_ERROR(drm, "no space while disconnecting SOR\n"); return; } BEGIN_NV04(evo, 0, NV50_EVO_SOR(nv_encoder->or, MODE_CTRL), 1); @@ -256,13 +267,15 @@ nv50_sor_disconnect(struct drm_encoder *encoder) static void nv50_sor_dpms(struct drm_encoder *encoder, int mode) { + struct nouveau_device *device = nouveau_dev(encoder->dev); + struct nouveau_drm *drm = nouveau_drm(encoder->dev); struct drm_device *dev = encoder->dev; struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); struct drm_encoder *enc; uint32_t val; int or = nv_encoder->or; - NV_DEBUG_KMS(dev, "or %d type %d mode %d\n", or, nv_encoder->dcb->type, mode); + NV_DEBUG(drm, "or %d type %d mode %d\n", or, nv_encoder->dcb->type, mode); nv_encoder->last_dpms = mode; list_for_each_entry(enc, &dev->mode_config.encoder_list, head) { @@ -280,27 +293,27 @@ nv50_sor_dpms(struct drm_encoder *encoder, int mode) } /* wait for it to be done */ - if (!nv_wait(dev, NV50_PDISPLAY_SOR_DPMS_CTRL(or), + if (!nv_wait(device, NV50_PDISPLAY_SOR_DPMS_CTRL(or), NV50_PDISPLAY_SOR_DPMS_CTRL_PENDING, 0)) { - NV_ERROR(dev, "timeout: SOR_DPMS_CTRL_PENDING(%d) == 0\n", or); - NV_ERROR(dev, "SOR_DPMS_CTRL(%d) = 0x%08x\n", or, - nv_rd32(dev, NV50_PDISPLAY_SOR_DPMS_CTRL(or))); + NV_ERROR(drm, "timeout: SOR_DPMS_CTRL_PENDING(%d) == 0\n", or); + NV_ERROR(drm, "SOR_DPMS_CTRL(%d) = 0x%08x\n", or, + nv_rd32(device, NV50_PDISPLAY_SOR_DPMS_CTRL(or))); } - val = nv_rd32(dev, NV50_PDISPLAY_SOR_DPMS_CTRL(or)); + val = nv_rd32(device, NV50_PDISPLAY_SOR_DPMS_CTRL(or)); if (mode == DRM_MODE_DPMS_ON) val |= NV50_PDISPLAY_SOR_DPMS_CTRL_ON; else val &= ~NV50_PDISPLAY_SOR_DPMS_CTRL_ON; - nv_wr32(dev, NV50_PDISPLAY_SOR_DPMS_CTRL(or), val | + nv_wr32(device, NV50_PDISPLAY_SOR_DPMS_CTRL(or), val | NV50_PDISPLAY_SOR_DPMS_CTRL_PENDING); - if (!nv_wait(dev, NV50_PDISPLAY_SOR_DPMS_STATE(or), + if (!nv_wait(device, NV50_PDISPLAY_SOR_DPMS_STATE(or), NV50_PDISPLAY_SOR_DPMS_STATE_WAIT, 0)) { - NV_ERROR(dev, "timeout: SOR_DPMS_STATE_WAIT(%d) == 0\n", or); - NV_ERROR(dev, "SOR_DPMS_STATE(%d) = 0x%08x\n", or, - nv_rd32(dev, NV50_PDISPLAY_SOR_DPMS_STATE(or))); + NV_ERROR(drm, "timeout: SOR_DPMS_STATE_WAIT(%d) == 0\n", or); + NV_ERROR(drm, "SOR_DPMS_STATE(%d) = 0x%08x\n", or, + nv_rd32(device, NV50_PDISPLAY_SOR_DPMS_STATE(or))); } if (nv_encoder->dcb->type == DCB_OUTPUT_DP) { @@ -317,13 +330,15 @@ nv50_sor_dpms(struct drm_encoder *encoder, int mode) static void nv50_sor_save(struct drm_encoder *encoder) { - NV_ERROR(encoder->dev, "!!\n"); + struct nouveau_drm *drm = nouveau_drm(encoder->dev); + NV_ERROR(drm, "!!\n"); } static void nv50_sor_restore(struct drm_encoder *encoder) { - NV_ERROR(encoder->dev, "!!\n"); + struct nouveau_drm *drm = nouveau_drm(encoder->dev); + NV_ERROR(drm, "!!\n"); } static bool @@ -331,14 +346,15 @@ nv50_sor_mode_fixup(struct drm_encoder *encoder, const struct drm_display_mode *mode, struct drm_display_mode *adjusted_mode) { + struct nouveau_drm *drm = nouveau_drm(encoder->dev); struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); struct nouveau_connector *connector; - NV_DEBUG_KMS(encoder->dev, "or %d\n", nv_encoder->or); + NV_DEBUG(drm, "or %d\n", nv_encoder->or); connector = nouveau_encoder_connector_get(nv_encoder); if (!connector) { - NV_ERROR(encoder->dev, "Encoder has no connector\n"); + NV_ERROR(drm, "Encoder has no connector\n"); return false; } @@ -371,13 +387,13 @@ nv50_sor_mode_set(struct drm_encoder *encoder, struct drm_display_mode *umode, { struct nouveau_channel *evo = nv50_display(encoder->dev)->master; struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); - struct drm_device *dev = encoder->dev; + struct nouveau_drm *drm = nouveau_drm(encoder->dev); struct nouveau_crtc *crtc = nouveau_crtc(encoder->crtc); struct nouveau_connector *nv_connector; uint32_t mode_ctl = 0; int ret; - NV_DEBUG_KMS(dev, "or %d type %d -> crtc %d\n", + NV_DEBUG(drm, "or %d type %d -> crtc %d\n", nv_encoder->or, nv_encoder->dcb->type, crtc->index); nv_encoder->crtc = encoder->crtc; @@ -427,7 +443,7 @@ nv50_sor_mode_set(struct drm_encoder *encoder, struct drm_display_mode *umode, ret = RING_SPACE(evo, 2); if (ret) { - NV_ERROR(dev, "no space while connecting SOR\n"); + NV_ERROR(drm, "no space while connecting SOR\n"); nv_encoder->crtc = NULL; return; } @@ -458,11 +474,9 @@ static void nv50_sor_destroy(struct drm_encoder *encoder) { struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); + struct nouveau_drm *drm = nouveau_drm(encoder->dev); - if (!encoder) - return; - - NV_DEBUG_KMS(encoder->dev, "\n"); + NV_DEBUG(drm, "\n"); drm_encoder_cleanup(encoder); @@ -478,10 +492,11 @@ nv50_sor_create(struct drm_connector *connector, struct dcb_output *entry) { struct nouveau_encoder *nv_encoder = NULL; struct drm_device *dev = connector->dev; + struct nouveau_drm *drm = nouveau_drm(dev); struct drm_encoder *encoder; int type; - NV_DEBUG_KMS(dev, "\n"); + NV_DEBUG(drm, "\n"); switch (entry->type) { case DCB_OUTPUT_TMDS: diff --git a/drivers/gpu/drm/nouveau/nv84_fence.c b/drivers/gpu/drm/nouveau/nv84_fence.c index b0d147a675c4..c686650584b6 100644 --- a/drivers/gpu/drm/nouveau/nv84_fence.c +++ b/drivers/gpu/drm/nouveau/nv84_fence.c @@ -31,6 +31,8 @@ #include "nouveau_dma.h" #include "nouveau_fence.h" +#include "nv50_display.h" + struct nv84_fence_chan { struct nouveau_fence_chan base; }; @@ -99,6 +101,7 @@ nv84_fence_context_del(struct nouveau_channel *chan) static int nv84_fence_context_new(struct nouveau_channel *chan) { + struct drm_device *dev = chan->drm->dev; struct nouveau_fifo_chan *fifo = (void *)chan->object; struct nv84_fence_priv *priv = chan->drm->fence; struct nv84_fence_chan *fctx; @@ -123,8 +126,8 @@ nv84_fence_context_new(struct nouveau_channel *chan) &object); /* dma objects for display sync channel semaphore blocks */ - for (i = 0; !ret && i < chan->drm->dev->mode_config.num_crtc; i++) { - struct nouveau_bo *bo = nv50sema(chan->drm->dev, i); + for (i = 0; !ret && i < dev->mode_config.num_crtc; i++) { + struct nouveau_bo *bo = nv50_display_crtc_sema(dev, i); ret = nouveau_object_new(nv_object(chan->cli), chan->handle, NvEvoSema0 + i, 0x003d, diff --git a/drivers/gpu/drm/nouveau/nva3_pm.c b/drivers/gpu/drm/nouveau/nva3_pm.c index 2f7ee50440ae..3f69e46436cf 100644 --- a/drivers/gpu/drm/nouveau/nva3_pm.c +++ b/drivers/gpu/drm/nouveau/nva3_pm.c @@ -23,17 +23,24 @@ */ #include "drmP.h" -#include "nouveau_drv.h" -#include +#include "nouveau_drm.h" +#include "nouveau_bios.h" #include "nouveau_pm.h" +#include +#include +#include +#include +#include + static u32 read_clk(struct drm_device *, int, bool); static u32 read_pll(struct drm_device *, int, u32); static u32 read_vco(struct drm_device *dev, int clk) { - u32 sctl = nv_rd32(dev, 0x4120 + (clk * 4)); + struct nouveau_device *device = nouveau_dev(dev); + u32 sctl = nv_rd32(device, 0x4120 + (clk * 4)); if ((sctl & 0x00000030) != 0x00000030) return read_pll(dev, 0x41, 0x00e820); return read_pll(dev, 0x42, 0x00e8a0); @@ -42,26 +49,27 @@ read_vco(struct drm_device *dev, int clk) static u32 read_clk(struct drm_device *dev, int clk, bool ignore_en) { - struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_device *device = nouveau_dev(dev); + struct nouveau_drm *drm = nouveau_drm(dev); u32 sctl, sdiv, sclk; /* refclk for the 0xe8xx plls is a fixed frequency */ if (clk >= 0x40) { - if (dev_priv->chipset == 0xaf) { + if (nv_device(drm->device)->chipset == 0xaf) { /* no joke.. seriously.. sigh.. */ - return nv_rd32(dev, 0x00471c) * 1000; + return nv_rd32(device, 0x00471c) * 1000; } - return dev_priv->crystal; + return device->crystal; } - sctl = nv_rd32(dev, 0x4120 + (clk * 4)); + sctl = nv_rd32(device, 0x4120 + (clk * 4)); if (!ignore_en && !(sctl & 0x00000100)) return 0; switch (sctl & 0x00003000) { case 0x00000000: - return dev_priv->crystal; + return device->crystal; case 0x00002000: if (sctl & 0x00000040) return 108000; @@ -78,12 +86,13 @@ read_clk(struct drm_device *dev, int clk, bool ignore_en) static u32 read_pll(struct drm_device *dev, int clk, u32 pll) { - u32 ctrl = nv_rd32(dev, pll + 0); + struct nouveau_device *device = nouveau_dev(dev); + u32 ctrl = nv_rd32(device, pll + 0); u32 sclk = 0, P = 1, N = 1, M = 1; if (!(ctrl & 0x00000008)) { if (ctrl & 0x00000001) { - u32 coef = nv_rd32(dev, pll + 4); + u32 coef = nv_rd32(device, pll + 4); M = (coef & 0x000000ff) >> 0; N = (coef & 0x0000ff00) >> 8; P = (coef & 0x003f0000) >> 16; @@ -111,6 +120,9 @@ struct creg { static int calc_clk(struct drm_device *dev, int clk, u32 pll, u32 khz, struct creg *reg) { + struct nouveau_drm *drm = nouveau_drm(dev); + struct nouveau_device *device = nouveau_dev(dev); + struct nouveau_bios *bios = nouveau_bios(device); struct nvbios_pll limits; u32 oclk, sclk, sdiv; int P, N, M, diff; @@ -119,7 +131,7 @@ calc_clk(struct drm_device *dev, int clk, u32 pll, u32 khz, struct creg *reg) reg->pll = 0; reg->clk = 0; if (!khz) { - NV_DEBUG(dev, "no clock for 0x%04x/0x%02x\n", pll, clk); + NV_DEBUG(drm, "no clock for 0x%04x/0x%02x\n", pll, clk); return 0; } @@ -154,14 +166,14 @@ calc_clk(struct drm_device *dev, int clk, u32 pll, u32 khz, struct creg *reg) } if (!pll) { - NV_ERROR(dev, "bad freq %02x: %d %d\n", clk, khz, sclk); + NV_ERROR(drm, "bad freq %02x: %d %d\n", clk, khz, sclk); return -ERANGE; } break; } - ret = get_pll_limits(dev, pll, &limits); + ret = nvbios_pll_parse(bios, pll, &limits); if (ret) return ret; @@ -171,54 +183,60 @@ calc_clk(struct drm_device *dev, int clk, u32 pll, u32 khz, struct creg *reg) ret = nva3_calc_pll(dev, &limits, khz, &N, NULL, &M, &P); if (ret >= 0) { - reg->clk = nv_rd32(dev, 0x4120 + (clk * 4)); + reg->clk = nv_rd32(device, 0x4120 + (clk * 4)); reg->pll = (P << 16) | (N << 8) | M; } + return ret; } static void prog_pll(struct drm_device *dev, int clk, u32 pll, struct creg *reg) { + struct nouveau_device *device = nouveau_dev(dev); + struct nouveau_drm *drm = nouveau_drm(dev); const u32 src0 = 0x004120 + (clk * 4); const u32 src1 = 0x004160 + (clk * 4); const u32 ctrl = pll + 0; const u32 coef = pll + 4; if (!reg->clk && !reg->pll) { - NV_DEBUG(dev, "no clock for %02x\n", clk); + NV_DEBUG(drm, "no clock for %02x\n", clk); return; } if (reg->pll) { - nv_mask(dev, src0, 0x00000101, 0x00000101); - nv_wr32(dev, coef, reg->pll); - nv_mask(dev, ctrl, 0x00000015, 0x00000015); - nv_mask(dev, ctrl, 0x00000010, 0x00000000); - nv_wait(dev, ctrl, 0x00020000, 0x00020000); - nv_mask(dev, ctrl, 0x00000010, 0x00000010); - nv_mask(dev, ctrl, 0x00000008, 0x00000000); - nv_mask(dev, src1, 0x00000100, 0x00000000); - nv_mask(dev, src1, 0x00000001, 0x00000000); + nv_mask(device, src0, 0x00000101, 0x00000101); + nv_wr32(device, coef, reg->pll); + nv_mask(device, ctrl, 0x00000015, 0x00000015); + nv_mask(device, ctrl, 0x00000010, 0x00000000); + nv_wait(device, ctrl, 0x00020000, 0x00020000); + nv_mask(device, ctrl, 0x00000010, 0x00000010); + nv_mask(device, ctrl, 0x00000008, 0x00000000); + nv_mask(device, src1, 0x00000100, 0x00000000); + nv_mask(device, src1, 0x00000001, 0x00000000); } else { - nv_mask(dev, src1, 0x003f3141, 0x00000101 | reg->clk); - nv_mask(dev, ctrl, 0x00000018, 0x00000018); + nv_mask(device, src1, 0x003f3141, 0x00000101 | reg->clk); + nv_mask(device, ctrl, 0x00000018, 0x00000018); udelay(20); - nv_mask(dev, ctrl, 0x00000001, 0x00000000); - nv_mask(dev, src0, 0x00000100, 0x00000000); - nv_mask(dev, src0, 0x00000001, 0x00000000); + nv_mask(device, ctrl, 0x00000001, 0x00000000); + nv_mask(device, src0, 0x00000100, 0x00000000); + nv_mask(device, src0, 0x00000001, 0x00000000); } } static void prog_clk(struct drm_device *dev, int clk, struct creg *reg) { + struct nouveau_device *device = nouveau_dev(dev); + struct nouveau_drm *drm = nouveau_drm(dev); + if (!reg->clk) { - NV_DEBUG(dev, "no clock for %02x\n", clk); + NV_DEBUG(drm, "no clock for %02x\n", clk); return; } - nv_mask(dev, 0x004120 + (clk * 4), 0x003f3141, 0x00000101 | reg->clk); + nv_mask(device, 0x004120 + (clk * 4), 0x003f3141, 0x00000101 | reg->clk); } int @@ -309,10 +327,11 @@ static bool nva3_pm_grcp_idle(void *data) { struct drm_device *dev = data; + struct nouveau_device *device = nouveau_dev(dev); - if (!(nv_rd32(dev, 0x400304) & 0x00000001)) + if (!(nv_rd32(device, 0x400304) & 0x00000001)) return true; - if (nv_rd32(dev, 0x400308) == 0x0050001c) + if (nv_rd32(device, 0x400308) == 0x0050001c) return true; return false; } @@ -320,83 +339,91 @@ nva3_pm_grcp_idle(void *data) static void mclk_precharge(struct nouveau_mem_exec_func *exec) { - nv_wr32(exec->dev, 0x1002d4, 0x00000001); + struct nouveau_device *device = nouveau_dev(exec->dev); + nv_wr32(device, 0x1002d4, 0x00000001); } static void mclk_refresh(struct nouveau_mem_exec_func *exec) { - nv_wr32(exec->dev, 0x1002d0, 0x00000001); + struct nouveau_device *device = nouveau_dev(exec->dev); + nv_wr32(device, 0x1002d0, 0x00000001); } static void mclk_refresh_auto(struct nouveau_mem_exec_func *exec, bool enable) { - nv_wr32(exec->dev, 0x100210, enable ? 0x80000000 : 0x00000000); + struct nouveau_device *device = nouveau_dev(exec->dev); + nv_wr32(device, 0x100210, enable ? 0x80000000 : 0x00000000); } static void mclk_refresh_self(struct nouveau_mem_exec_func *exec, bool enable) { - nv_wr32(exec->dev, 0x1002dc, enable ? 0x00000001 : 0x00000000); + struct nouveau_device *device = nouveau_dev(exec->dev); + nv_wr32(device, 0x1002dc, enable ? 0x00000001 : 0x00000000); } static void mclk_wait(struct nouveau_mem_exec_func *exec, u32 nsec) { - volatile u32 post = nv_rd32(exec->dev, 0); (void)post; + struct nouveau_device *device = nouveau_dev(exec->dev); + volatile u32 post = nv_rd32(device, 0); (void)post; udelay((nsec + 500) / 1000); } static u32 mclk_mrg(struct nouveau_mem_exec_func *exec, int mr) { + struct nouveau_device *device = nouveau_dev(exec->dev); if (mr <= 1) - return nv_rd32(exec->dev, 0x1002c0 + ((mr - 0) * 4)); + return nv_rd32(device, 0x1002c0 + ((mr - 0) * 4)); if (mr <= 3) - return nv_rd32(exec->dev, 0x1002e0 + ((mr - 2) * 4)); + return nv_rd32(device, 0x1002e0 + ((mr - 2) * 4)); return 0; } static void mclk_mrs(struct nouveau_mem_exec_func *exec, int mr, u32 data) { + struct nouveau_device *device = nouveau_dev(exec->dev); + struct nouveau_fb *pfb = nouveau_fb(device); if (mr <= 1) { - if (nvfb_vram_rank_B(exec->dev)) - nv_wr32(exec->dev, 0x1002c8 + ((mr - 0) * 4), data); - nv_wr32(exec->dev, 0x1002c0 + ((mr - 0) * 4), data); + if (pfb->ram.ranks > 1) + nv_wr32(device, 0x1002c8 + ((mr - 0) * 4), data); + nv_wr32(device, 0x1002c0 + ((mr - 0) * 4), data); } else if (mr <= 3) { - if (nvfb_vram_rank_B(exec->dev)) - nv_wr32(exec->dev, 0x1002e8 + ((mr - 2) * 4), data); - nv_wr32(exec->dev, 0x1002e0 + ((mr - 2) * 4), data); + if (pfb->ram.ranks > 1) + nv_wr32(device, 0x1002e8 + ((mr - 2) * 4), data); + nv_wr32(device, 0x1002e0 + ((mr - 2) * 4), data); } } static void mclk_clock_set(struct nouveau_mem_exec_func *exec) { - struct drm_device *dev = exec->dev; + struct nouveau_device *device = nouveau_dev(exec->dev); struct nva3_pm_state *info = exec->priv; u32 ctrl; - ctrl = nv_rd32(dev, 0x004000); + ctrl = nv_rd32(device, 0x004000); if (!(ctrl & 0x00000008) && info->mclk.pll) { - nv_wr32(dev, 0x004000, (ctrl |= 0x00000008)); - nv_mask(dev, 0x1110e0, 0x00088000, 0x00088000); - nv_wr32(dev, 0x004018, 0x00001000); - nv_wr32(dev, 0x004000, (ctrl &= ~0x00000001)); - nv_wr32(dev, 0x004004, info->mclk.pll); - nv_wr32(dev, 0x004000, (ctrl |= 0x00000001)); + nv_wr32(device, 0x004000, (ctrl |= 0x00000008)); + nv_mask(device, 0x1110e0, 0x00088000, 0x00088000); + nv_wr32(device, 0x004018, 0x00001000); + nv_wr32(device, 0x004000, (ctrl &= ~0x00000001)); + nv_wr32(device, 0x004004, info->mclk.pll); + nv_wr32(device, 0x004000, (ctrl |= 0x00000001)); udelay(64); - nv_wr32(dev, 0x004018, 0x00005000 | info->r004018); + nv_wr32(device, 0x004018, 0x00005000 | info->r004018); udelay(20); } else if (!info->mclk.pll) { - nv_mask(dev, 0x004168, 0x003f3040, info->mclk.clk); - nv_wr32(dev, 0x004000, (ctrl |= 0x00000008)); - nv_mask(dev, 0x1110e0, 0x00088000, 0x00088000); - nv_wr32(dev, 0x004018, 0x0000d000 | info->r004018); + nv_mask(device, 0x004168, 0x003f3040, info->mclk.clk); + nv_wr32(device, 0x004000, (ctrl |= 0x00000008)); + nv_mask(device, 0x1110e0, 0x00088000, 0x00088000); + nv_wr32(device, 0x004018, 0x0000d000 | info->r004018); } if (info->rammap) { @@ -408,67 +435,68 @@ mclk_clock_set(struct nouveau_mem_exec_func *exec) (info->ramcfg[3] & 0x0f) << 16 | (info->ramcfg[9] & 0x0f) | 0x80000000; - nv_wr32(dev, 0x1005a0, unk5a0); - nv_wr32(dev, 0x1005a4, unk5a4); - nv_wr32(dev, 0x10f804, unk804); - nv_mask(dev, 0x10053c, 0x00001000, 0x00000000); + nv_wr32(device, 0x1005a0, unk5a0); + nv_wr32(device, 0x1005a4, unk5a4); + nv_wr32(device, 0x10f804, unk804); + nv_mask(device, 0x10053c, 0x00001000, 0x00000000); } else { - nv_mask(dev, 0x10053c, 0x00001000, 0x00001000); - nv_mask(dev, 0x10f804, 0x80000000, 0x00000000); - nv_mask(dev, 0x100760, 0x22222222, info->r100760); - nv_mask(dev, 0x1007a0, 0x22222222, info->r100760); - nv_mask(dev, 0x1007e0, 0x22222222, info->r100760); + nv_mask(device, 0x10053c, 0x00001000, 0x00001000); + nv_mask(device, 0x10f804, 0x80000000, 0x00000000); + nv_mask(device, 0x100760, 0x22222222, info->r100760); + nv_mask(device, 0x1007a0, 0x22222222, info->r100760); + nv_mask(device, 0x1007e0, 0x22222222, info->r100760); } } if (info->mclk.pll) { - nv_mask(dev, 0x1110e0, 0x00088000, 0x00011000); - nv_wr32(dev, 0x004000, (ctrl &= ~0x00000008)); + nv_mask(device, 0x1110e0, 0x00088000, 0x00011000); + nv_wr32(device, 0x004000, (ctrl &= ~0x00000008)); } } static void mclk_timing_set(struct nouveau_mem_exec_func *exec) { - struct drm_device *dev = exec->dev; + struct nouveau_device *device = nouveau_dev(exec->dev); struct nva3_pm_state *info = exec->priv; struct nouveau_pm_level *perflvl = info->perflvl; int i; for (i = 0; i < 9; i++) - nv_wr32(dev, 0x100220 + (i * 4), perflvl->timing.reg[i]); + nv_wr32(device, 0x100220 + (i * 4), perflvl->timing.reg[i]); if (info->ramcfg) { u32 data = (info->ramcfg[2] & 0x08) ? 0x00000000 : 0x00001000; - nv_mask(dev, 0x100200, 0x00001000, data); + nv_mask(device, 0x100200, 0x00001000, data); } if (info->ramcfg) { - u32 unk714 = nv_rd32(dev, 0x100714) & ~0xf0000010; - u32 unk718 = nv_rd32(dev, 0x100718) & ~0x00000100; - u32 unk71c = nv_rd32(dev, 0x10071c) & ~0x00000100; + u32 unk714 = nv_rd32(device, 0x100714) & ~0xf0000010; + u32 unk718 = nv_rd32(device, 0x100718) & ~0x00000100; + u32 unk71c = nv_rd32(device, 0x10071c) & ~0x00000100; if ( (info->ramcfg[2] & 0x20)) unk714 |= 0xf0000000; if (!(info->ramcfg[2] & 0x04)) unk714 |= 0x00000010; - nv_wr32(dev, 0x100714, unk714); + nv_wr32(device, 0x100714, unk714); if (info->ramcfg[2] & 0x01) unk71c |= 0x00000100; - nv_wr32(dev, 0x10071c, unk71c); + nv_wr32(device, 0x10071c, unk71c); if (info->ramcfg[2] & 0x02) unk718 |= 0x00000100; - nv_wr32(dev, 0x100718, unk718); + nv_wr32(device, 0x100718, unk718); if (info->ramcfg[2] & 0x10) - nv_wr32(dev, 0x111100, 0x48000000); /*XXX*/ + nv_wr32(device, 0x111100, 0x48000000); /*XXX*/ } } static void prog_mem(struct drm_device *dev, struct nva3_pm_state *info) { + struct nouveau_device *device = nouveau_dev(dev); struct nouveau_mem_exec_func exec = { .dev = dev, .precharge = mclk_precharge, @@ -490,17 +518,17 @@ prog_mem(struct drm_device *dev, struct nva3_pm_state *info) info->r100760 = 0x22222222; } - ctrl = nv_rd32(dev, 0x004000); + ctrl = nv_rd32(device, 0x004000); if (ctrl & 0x00000008) { if (info->mclk.pll) { - nv_mask(dev, 0x004128, 0x00000101, 0x00000101); - nv_wr32(dev, 0x004004, info->mclk.pll); - nv_wr32(dev, 0x004000, (ctrl |= 0x00000001)); - nv_wr32(dev, 0x004000, (ctrl &= 0xffffffef)); - nv_wait(dev, 0x004000, 0x00020000, 0x00020000); - nv_wr32(dev, 0x004000, (ctrl |= 0x00000010)); - nv_wr32(dev, 0x004018, 0x00005000 | info->r004018); - nv_wr32(dev, 0x004000, (ctrl |= 0x00000004)); + nv_mask(device, 0x004128, 0x00000101, 0x00000101); + nv_wr32(device, 0x004004, info->mclk.pll); + nv_wr32(device, 0x004000, (ctrl |= 0x00000001)); + nv_wr32(device, 0x004000, (ctrl &= 0xffffffef)); + nv_wait(device, 0x004000, 0x00020000, 0x00020000); + nv_wr32(device, 0x004000, (ctrl |= 0x00000010)); + nv_wr32(device, 0x004018, 0x00005000 | info->r004018); + nv_wr32(device, 0x004000, (ctrl |= 0x00000004)); } } else { u32 ssel = 0x00000101; @@ -508,68 +536,67 @@ prog_mem(struct drm_device *dev, struct nva3_pm_state *info) ssel |= info->mclk.clk; else ssel |= 0x00080000; /* 324MHz, shouldn't matter... */ - nv_mask(dev, 0x004168, 0x003f3141, ctrl); + nv_mask(device, 0x004168, 0x003f3141, ctrl); } if (info->ramcfg) { if (info->ramcfg[2] & 0x10) { - nv_mask(dev, 0x111104, 0x00000600, 0x00000000); + nv_mask(device, 0x111104, 0x00000600, 0x00000000); } else { - nv_mask(dev, 0x111100, 0x40000000, 0x40000000); - nv_mask(dev, 0x111104, 0x00000180, 0x00000000); + nv_mask(device, 0x111100, 0x40000000, 0x40000000); + nv_mask(device, 0x111104, 0x00000180, 0x00000000); } } if (info->rammap && !(info->rammap[4] & 0x02)) - nv_mask(dev, 0x100200, 0x00000800, 0x00000000); - nv_wr32(dev, 0x611200, 0x00003300); + nv_mask(device, 0x100200, 0x00000800, 0x00000000); + nv_wr32(device, 0x611200, 0x00003300); if (!(info->ramcfg[2] & 0x10)) - nv_wr32(dev, 0x111100, 0x4c020000); /*XXX*/ + nv_wr32(device, 0x111100, 0x4c020000); /*XXX*/ nouveau_mem_exec(&exec, info->perflvl); - nv_wr32(dev, 0x611200, 0x00003330); + nv_wr32(device, 0x611200, 0x00003330); if (info->rammap && (info->rammap[4] & 0x02)) - nv_mask(dev, 0x100200, 0x00000800, 0x00000800); + nv_mask(device, 0x100200, 0x00000800, 0x00000800); if (info->ramcfg) { if (info->ramcfg[2] & 0x10) { - nv_mask(dev, 0x111104, 0x00000180, 0x00000180); - nv_mask(dev, 0x111100, 0x40000000, 0x00000000); + nv_mask(device, 0x111104, 0x00000180, 0x00000180); + nv_mask(device, 0x111100, 0x40000000, 0x00000000); } else { - nv_mask(dev, 0x111104, 0x00000600, 0x00000600); + nv_mask(device, 0x111104, 0x00000600, 0x00000600); } } if (info->mclk.pll) { - nv_mask(dev, 0x004168, 0x00000001, 0x00000000); - nv_mask(dev, 0x004168, 0x00000100, 0x00000000); + nv_mask(device, 0x004168, 0x00000001, 0x00000000); + nv_mask(device, 0x004168, 0x00000100, 0x00000000); } else { - nv_mask(dev, 0x004000, 0x00000001, 0x00000000); - nv_mask(dev, 0x004128, 0x00000001, 0x00000000); - nv_mask(dev, 0x004128, 0x00000100, 0x00000000); + nv_mask(device, 0x004000, 0x00000001, 0x00000000); + nv_mask(device, 0x004128, 0x00000001, 0x00000000); + nv_mask(device, 0x004128, 0x00000100, 0x00000000); } } int nva3_pm_clocks_set(struct drm_device *dev, void *pre_state) { - struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_device *device = nouveau_dev(dev); + struct nouveau_drm *drm = nouveau_drm(dev); struct nva3_pm_state *info = pre_state; - unsigned long flags; int ret = -EAGAIN; /* prevent any new grctx switches from starting */ - spin_lock_irqsave(&dev_priv->context_switch_lock, flags); - nv_wr32(dev, 0x400324, 0x00000000); - nv_wr32(dev, 0x400328, 0x0050001c); /* wait flag 0x1c */ + nv_wr32(device, 0x400324, 0x00000000); + nv_wr32(device, 0x400328, 0x0050001c); /* wait flag 0x1c */ /* wait for any pending grctx switches to complete */ - if (!nv_wait_cb(dev, nva3_pm_grcp_idle, dev)) { - NV_ERROR(dev, "pm: ctxprog didn't go idle\n"); + if (!nv_wait_cb(device, nva3_pm_grcp_idle, dev)) { + NV_ERROR(drm, "pm: ctxprog didn't go idle\n"); goto cleanup; } /* freeze PFIFO */ - nv_mask(dev, 0x002504, 0x00000001, 0x00000001); - if (!nv_wait(dev, 0x002504, 0x00000010, 0x00000010)) { - NV_ERROR(dev, "pm: fifo didn't go idle\n"); + nv_mask(device, 0x002504, 0x00000001, 0x00000001); + if (!nv_wait(device, 0x002504, 0x00000010, 0x00000010)) { + NV_ERROR(drm, "pm: fifo didn't go idle\n"); goto cleanup; } @@ -585,14 +612,13 @@ nva3_pm_clocks_set(struct drm_device *dev, void *pre_state) cleanup: /* unfreeze PFIFO */ - nv_mask(dev, 0x002504, 0x00000001, 0x00000000); + nv_mask(device, 0x002504, 0x00000001, 0x00000000); /* restore ctxprog to normal */ - nv_wr32(dev, 0x400324, 0x00000000); - nv_wr32(dev, 0x400328, 0x0070009c); /* set flag 0x1c */ + nv_wr32(device, 0x400324, 0x00000000); + nv_wr32(device, 0x400328, 0x0070009c); /* set flag 0x1c */ /* unblock it if necessary */ - if (nv_rd32(dev, 0x400308) == 0x0050001c) - nv_mask(dev, 0x400824, 0x10000000, 0x10000000); - spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags); + if (nv_rd32(device, 0x400308) == 0x0050001c) + nv_mask(device, 0x400824, 0x10000000, 0x10000000); kfree(info); return ret; } diff --git a/drivers/gpu/drm/nouveau/nvc0_fbcon.c b/drivers/gpu/drm/nouveau/nvc0_fbcon.c index cc88f3649909..9dcd30f3e1e0 100644 --- a/drivers/gpu/drm/nouveau/nvc0_fbcon.c +++ b/drivers/gpu/drm/nouveau/nvc0_fbcon.c @@ -30,7 +30,7 @@ int nvc0_fbcon_fillrect(struct fb_info *info, const struct fb_fillrect *rect) { struct nouveau_fbdev *nfbdev = info->par; - struct nouveau_drm *drm = nouveau_newpriv(nfbdev->dev); + struct nouveau_drm *drm = nouveau_drm(nfbdev->dev); struct nouveau_channel *chan = drm->channel; int ret; @@ -65,7 +65,7 @@ int nvc0_fbcon_copyarea(struct fb_info *info, const struct fb_copyarea *region) { struct nouveau_fbdev *nfbdev = info->par; - struct nouveau_drm *drm = nouveau_newpriv(nfbdev->dev); + struct nouveau_drm *drm = nouveau_drm(nfbdev->dev); struct nouveau_channel *chan = drm->channel; int ret; @@ -93,7 +93,7 @@ int nvc0_fbcon_imageblit(struct fb_info *info, const struct fb_image *image) { struct nouveau_fbdev *nfbdev = info->par; - struct nouveau_drm *drm = nouveau_newpriv(nfbdev->dev); + struct nouveau_drm *drm = nouveau_drm(nfbdev->dev); struct nouveau_channel *chan = drm->channel; uint32_t width, dwords, *data = (uint32_t *)image->data; uint32_t mask = ~(~0 >> (32 - info->var.bits_per_pixel)); @@ -152,7 +152,7 @@ nvc0_fbcon_accel_init(struct fb_info *info) struct nouveau_fbdev *nfbdev = info->par; struct drm_device *dev = nfbdev->dev; struct nouveau_framebuffer *fb = &nfbdev->nouveau_fb; - struct nouveau_drm *drm = nouveau_newpriv(dev); + struct nouveau_drm *drm = nouveau_drm(dev); struct nouveau_channel *chan = drm->channel; struct nouveau_object *object; int ret, format; diff --git a/drivers/gpu/drm/nouveau/nvc0_fence.c b/drivers/gpu/drm/nouveau/nvc0_fence.c index ce612ad398ad..53299eac9676 100644 --- a/drivers/gpu/drm/nouveau/nvc0_fence.c +++ b/drivers/gpu/drm/nouveau/nvc0_fence.c @@ -32,6 +32,8 @@ #include "nouveau_dma.h" #include "nouveau_fence.h" +#include "nv50_display.h" + struct nvc0_fence_priv { struct nouveau_fence_priv base; struct nouveau_bo *bo; @@ -114,13 +116,13 @@ nvc0_fence_context_del(struct nouveau_channel *chan) if (nv_device(chan->drm->device)->card_type >= NV_D0) { for (i = 0; i < dev->mode_config.num_crtc; i++) { - struct nouveau_bo *bo = nvd0sema(dev, i); + struct nouveau_bo *bo = nvd0_display_crtc_sema(dev, i); nouveau_bo_vma_del(bo, &fctx->dispc_vma[i]); } } else if (nv_device(chan->drm->device)->card_type >= NV_50) { for (i = 0; i < dev->mode_config.num_crtc; i++) { - struct nouveau_bo *bo = nv50sema(dev, i); + struct nouveau_bo *bo = nv50_display_crtc_sema(dev, i); nouveau_bo_vma_del(bo, &fctx->dispc_vma[i]); } } @@ -154,9 +156,9 @@ nvc0_fence_context_new(struct nouveau_channel *chan) for (i = 0; !ret && i < chan->drm->dev->mode_config.num_crtc; i++) { struct nouveau_bo *bo; if (nv_device(chan->drm->device)->card_type >= NV_D0) - bo = nvd0sema(chan->drm->dev, i); + bo = nvd0_display_crtc_sema(chan->drm->dev, i); else - bo = nv50sema(chan->drm->dev, i); + bo = nv50_display_crtc_sema(chan->drm->dev, i); ret = nouveau_bo_vma_add(bo, client->vm, &fctx->dispc_vma[i]); } diff --git a/drivers/gpu/drm/nouveau/nvc0_pm.c b/drivers/gpu/drm/nouveau/nvc0_pm.c index a14711c25176..0d34eb581179 100644 --- a/drivers/gpu/drm/nouveau/nvc0_pm.c +++ b/drivers/gpu/drm/nouveau/nvc0_pm.c @@ -22,18 +22,24 @@ * Authors: Ben Skeggs */ -#include "drmP.h" -#include "nouveau_drv.h" -#include +#include "nouveau_drm.h" +#include "nouveau_bios.h" #include "nouveau_pm.h" +#include +#include +#include +#include +#include + static u32 read_div(struct drm_device *, int, u32, u32); static u32 read_pll(struct drm_device *, u32); static u32 read_vco(struct drm_device *dev, u32 dsrc) { - u32 ssrc = nv_rd32(dev, dsrc); + struct nouveau_device *device = nouveau_dev(dev); + u32 ssrc = nv_rd32(device, dsrc); if (!(ssrc & 0x00000100)) return read_pll(dev, 0x00e800); return read_pll(dev, 0x00e820); @@ -42,8 +48,9 @@ read_vco(struct drm_device *dev, u32 dsrc) static u32 read_pll(struct drm_device *dev, u32 pll) { - u32 ctrl = nv_rd32(dev, pll + 0); - u32 coef = nv_rd32(dev, pll + 4); + struct nouveau_device *device = nouveau_dev(dev); + u32 ctrl = nv_rd32(device, pll + 0); + u32 coef = nv_rd32(device, pll + 4); u32 P = (coef & 0x003f0000) >> 16; u32 N = (coef & 0x0000ff00) >> 8; u32 M = (coef & 0x000000ff) >> 0; @@ -83,8 +90,9 @@ read_pll(struct drm_device *dev, u32 pll) static u32 read_div(struct drm_device *dev, int doff, u32 dsrc, u32 dctl) { - u32 ssrc = nv_rd32(dev, dsrc + (doff * 4)); - u32 sctl = nv_rd32(dev, dctl + (doff * 4)); + struct nouveau_device *device = nouveau_dev(dev); + u32 ssrc = nv_rd32(device, dsrc + (doff * 4)); + u32 sctl = nv_rd32(device, dctl + (doff * 4)); switch (ssrc & 0x00000003) { case 0: @@ -109,7 +117,8 @@ read_div(struct drm_device *dev, int doff, u32 dsrc, u32 dctl) static u32 read_mem(struct drm_device *dev) { - u32 ssel = nv_rd32(dev, 0x1373f0); + struct nouveau_device *device = nouveau_dev(dev); + u32 ssel = nv_rd32(device, 0x1373f0); if (ssel & 0x00000001) return read_div(dev, 0, 0x137300, 0x137310); return read_pll(dev, 0x132000); @@ -118,8 +127,9 @@ read_mem(struct drm_device *dev) static u32 read_clk(struct drm_device *dev, int clk) { - u32 sctl = nv_rd32(dev, 0x137250 + (clk * 4)); - u32 ssel = nv_rd32(dev, 0x137100); + struct nouveau_device *device = nouveau_dev(dev); + u32 sctl = nv_rd32(device, 0x137250 + (clk * 4)); + u32 ssel = nv_rd32(device, 0x137100); u32 sclk, sdiv; if (ssel & (1 << clk)) { @@ -212,10 +222,12 @@ calc_src(struct drm_device *dev, int clk, u32 freq, u32 *dsrc, u32 *ddiv) static u32 calc_pll(struct drm_device *dev, int clk, u32 freq, u32 *coef) { + struct nouveau_device *device = nouveau_dev(dev); + struct nouveau_bios *bios = nouveau_bios(device); struct nvbios_pll limits; int N, M, P, ret; - ret = get_pll_limits(dev, 0x137000 + (clk * 0x20), &limits); + ret = nvbios_pll_parse(bios, 0x137000 + (clk * 0x20), &limits); if (ret) return 0; @@ -308,31 +320,33 @@ calc_clk(struct drm_device *dev, int clk, struct nvc0_pm_clock *info, u32 freq) static int calc_mem(struct drm_device *dev, struct nvc0_pm_clock *info, u32 freq) { + struct nouveau_device *device = nouveau_dev(dev); + struct nouveau_bios *bios = nouveau_bios(device); struct nvbios_pll pll; int N, M, P, ret; u32 ctrl; /* mclk pll input freq comes from another pll, make sure it's on */ - ctrl = nv_rd32(dev, 0x132020); + ctrl = nv_rd32(device, 0x132020); if (!(ctrl & 0x00000001)) { /* if not, program it to 567MHz. nfi where this value comes * from - it looks like it's in the pll limits table for * 132000 but the binary driver ignores all my attempts to * change this value. */ - nv_wr32(dev, 0x137320, 0x00000103); - nv_wr32(dev, 0x137330, 0x81200606); - nv_wait(dev, 0x132020, 0x00010000, 0x00010000); - nv_wr32(dev, 0x132024, 0x0001150f); - nv_mask(dev, 0x132020, 0x00000001, 0x00000001); - nv_wait(dev, 0x137390, 0x00020000, 0x00020000); - nv_mask(dev, 0x132020, 0x00000004, 0x00000004); + nv_wr32(device, 0x137320, 0x00000103); + nv_wr32(device, 0x137330, 0x81200606); + nv_wait(device, 0x132020, 0x00010000, 0x00010000); + nv_wr32(device, 0x132024, 0x0001150f); + nv_mask(device, 0x132020, 0x00000001, 0x00000001); + nv_wait(device, 0x137390, 0x00020000, 0x00020000); + nv_mask(device, 0x132020, 0x00000004, 0x00000004); } /* for the moment, until the clock tree is better understood, use * pll mode for all clock frequencies */ - ret = get_pll_limits(dev, 0x132000, &pll); + ret = nvbios_pll_parse(bios, 0x132000, &pll); if (ret == 0) { pll.refclk = read_pll(dev, 0x132020); if (pll.refclk) { @@ -350,7 +364,7 @@ calc_mem(struct drm_device *dev, struct nvc0_pm_clock *info, u32 freq) void * nvc0_pm_clocks_pre(struct drm_device *dev, struct nouveau_pm_level *perflvl) { - struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_device *device = nouveau_dev(dev); struct nvc0_pm_state *info; int ret; @@ -364,7 +378,7 @@ nvc0_pm_clocks_pre(struct drm_device *dev, struct nouveau_pm_level *perflvl) * are always the same freq with the binary driver even when the * performance table says they should differ. */ - if (dev_priv->chipset == 0xd9) + if (device->chipset == 0xd9) perflvl->rop = 0; if ((ret = calc_clk(dev, 0x00, &info->eng[0x00], perflvl->shader)) || @@ -394,38 +408,40 @@ nvc0_pm_clocks_pre(struct drm_device *dev, struct nouveau_pm_level *perflvl) static void prog_clk(struct drm_device *dev, int clk, struct nvc0_pm_clock *info) { + struct nouveau_device *device = nouveau_dev(dev); + /* program dividers at 137160/1371d0 first */ if (clk < 7 && !info->ssel) { - nv_mask(dev, 0x1371d0 + (clk * 0x04), 0x80003f3f, info->ddiv); - nv_wr32(dev, 0x137160 + (clk * 0x04), info->dsrc); + nv_mask(device, 0x1371d0 + (clk * 0x04), 0x80003f3f, info->ddiv); + nv_wr32(device, 0x137160 + (clk * 0x04), info->dsrc); } /* switch clock to non-pll mode */ - nv_mask(dev, 0x137100, (1 << clk), 0x00000000); - nv_wait(dev, 0x137100, (1 << clk), 0x00000000); + nv_mask(device, 0x137100, (1 << clk), 0x00000000); + nv_wait(device, 0x137100, (1 << clk), 0x00000000); /* reprogram pll */ if (clk < 7) { /* make sure it's disabled first... */ u32 base = 0x137000 + (clk * 0x20); - u32 ctrl = nv_rd32(dev, base + 0x00); + u32 ctrl = nv_rd32(device, base + 0x00); if (ctrl & 0x00000001) { - nv_mask(dev, base + 0x00, 0x00000004, 0x00000000); - nv_mask(dev, base + 0x00, 0x00000001, 0x00000000); + nv_mask(device, base + 0x00, 0x00000004, 0x00000000); + nv_mask(device, base + 0x00, 0x00000001, 0x00000000); } /* program it to new values, if necessary */ if (info->ssel) { - nv_wr32(dev, base + 0x04, info->coef); - nv_mask(dev, base + 0x00, 0x00000001, 0x00000001); - nv_wait(dev, base + 0x00, 0x00020000, 0x00020000); - nv_mask(dev, base + 0x00, 0x00020004, 0x00000004); + nv_wr32(device, base + 0x04, info->coef); + nv_mask(device, base + 0x00, 0x00000001, 0x00000001); + nv_wait(device, base + 0x00, 0x00020000, 0x00020000); + nv_mask(device, base + 0x00, 0x00020004, 0x00000004); } } /* select pll/non-pll mode, and program final clock divider */ - nv_mask(dev, 0x137100, (1 << clk), info->ssel); - nv_wait(dev, 0x137100, (1 << clk), info->ssel); - nv_mask(dev, 0x137250 + (clk * 0x04), 0x00003f3f, info->mdiv); + nv_mask(device, 0x137100, (1 << clk), info->ssel); + nv_wait(device, 0x137100, (1 << clk), info->ssel); + nv_mask(device, 0x137250 + (clk * 0x04), 0x00003f3f, info->mdiv); } static void @@ -441,7 +457,8 @@ mclk_refresh(struct nouveau_mem_exec_func *exec) static void mclk_refresh_auto(struct nouveau_mem_exec_func *exec, bool enable) { - nv_wr32(exec->dev, 0x10f210, enable ? 0x80000000 : 0x00000000); + struct nouveau_device *device = nouveau_dev(exec->dev); + nv_wr32(device, 0x10f210, enable ? 0x80000000 : 0x00000000); } static void @@ -458,81 +475,84 @@ mclk_wait(struct nouveau_mem_exec_func *exec, u32 nsec) static u32 mclk_mrg(struct nouveau_mem_exec_func *exec, int mr) { - struct drm_device *dev = exec->dev; - if (nvfb_vram_type(dev) != NV_MEM_TYPE_GDDR5) { + struct nouveau_device *device = nouveau_dev(exec->dev); + struct nouveau_fb *pfb = nouveau_fb(device); + if (pfb->ram.type != NV_MEM_TYPE_GDDR5) { if (mr <= 1) - return nv_rd32(dev, 0x10f300 + ((mr - 0) * 4)); - return nv_rd32(dev, 0x10f320 + ((mr - 2) * 4)); + return nv_rd32(device, 0x10f300 + ((mr - 0) * 4)); + return nv_rd32(device, 0x10f320 + ((mr - 2) * 4)); } else { if (mr == 0) - return nv_rd32(dev, 0x10f300 + (mr * 4)); + return nv_rd32(device, 0x10f300 + (mr * 4)); else if (mr <= 7) - return nv_rd32(dev, 0x10f32c + (mr * 4)); - return nv_rd32(dev, 0x10f34c); + return nv_rd32(device, 0x10f32c + (mr * 4)); + return nv_rd32(device, 0x10f34c); } } static void mclk_mrs(struct nouveau_mem_exec_func *exec, int mr, u32 data) { - struct drm_device *dev = exec->dev; - if (nvfb_vram_type(dev) != NV_MEM_TYPE_GDDR5) { + struct nouveau_device *device = nouveau_dev(exec->dev); + struct nouveau_fb *pfb = nouveau_fb(device); + if (pfb->ram.type != NV_MEM_TYPE_GDDR5) { if (mr <= 1) { - nv_wr32(dev, 0x10f300 + ((mr - 0) * 4), data); - if (nvfb_vram_rank_B(dev)) - nv_wr32(dev, 0x10f308 + ((mr - 0) * 4), data); + nv_wr32(device, 0x10f300 + ((mr - 0) * 4), data); + if (pfb->ram.ranks > 1) + nv_wr32(device, 0x10f308 + ((mr - 0) * 4), data); } else if (mr <= 3) { - nv_wr32(dev, 0x10f320 + ((mr - 2) * 4), data); - if (nvfb_vram_rank_B(dev)) - nv_wr32(dev, 0x10f328 + ((mr - 2) * 4), data); + nv_wr32(device, 0x10f320 + ((mr - 2) * 4), data); + if (pfb->ram.ranks > 1) + nv_wr32(device, 0x10f328 + ((mr - 2) * 4), data); } } else { - if (mr == 0) nv_wr32(dev, 0x10f300 + (mr * 4), data); - else if (mr <= 7) nv_wr32(dev, 0x10f32c + (mr * 4), data); - else if (mr == 15) nv_wr32(dev, 0x10f34c, data); + if (mr == 0) nv_wr32(device, 0x10f300 + (mr * 4), data); + else if (mr <= 7) nv_wr32(device, 0x10f32c + (mr * 4), data); + else if (mr == 15) nv_wr32(device, 0x10f34c, data); } } static void mclk_clock_set(struct nouveau_mem_exec_func *exec) { + struct nouveau_device *device = nouveau_dev(exec->dev); struct nvc0_pm_state *info = exec->priv; - struct drm_device *dev = exec->dev; - u32 ctrl = nv_rd32(dev, 0x132000); + u32 ctrl = nv_rd32(device, 0x132000); - nv_wr32(dev, 0x137360, 0x00000001); - nv_wr32(dev, 0x137370, 0x00000000); - nv_wr32(dev, 0x137380, 0x00000000); + nv_wr32(device, 0x137360, 0x00000001); + nv_wr32(device, 0x137370, 0x00000000); + nv_wr32(device, 0x137380, 0x00000000); if (ctrl & 0x00000001) - nv_wr32(dev, 0x132000, (ctrl &= ~0x00000001)); + nv_wr32(device, 0x132000, (ctrl &= ~0x00000001)); - nv_wr32(dev, 0x132004, info->mem.coef); - nv_wr32(dev, 0x132000, (ctrl |= 0x00000001)); - nv_wait(dev, 0x137390, 0x00000002, 0x00000002); - nv_wr32(dev, 0x132018, 0x00005000); + nv_wr32(device, 0x132004, info->mem.coef); + nv_wr32(device, 0x132000, (ctrl |= 0x00000001)); + nv_wait(device, 0x137390, 0x00000002, 0x00000002); + nv_wr32(device, 0x132018, 0x00005000); - nv_wr32(dev, 0x137370, 0x00000001); - nv_wr32(dev, 0x137380, 0x00000001); - nv_wr32(dev, 0x137360, 0x00000000); + nv_wr32(device, 0x137370, 0x00000001); + nv_wr32(device, 0x137380, 0x00000001); + nv_wr32(device, 0x137360, 0x00000000); } static void mclk_timing_set(struct nouveau_mem_exec_func *exec) { + struct nouveau_device *device = nouveau_dev(exec->dev); struct nvc0_pm_state *info = exec->priv; struct nouveau_pm_level *perflvl = info->perflvl; int i; for (i = 0; i < 5; i++) - nv_wr32(exec->dev, 0x10f290 + (i * 4), perflvl->timing.reg[i]); + nv_wr32(device, 0x10f290 + (i * 4), perflvl->timing.reg[i]); } static void prog_mem(struct drm_device *dev, struct nvc0_pm_state *info) { - struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_device *device = nouveau_dev(dev); struct nouveau_mem_exec_func exec = { .dev = dev, .precharge = mclk_precharge, @@ -547,17 +567,17 @@ prog_mem(struct drm_device *dev, struct nvc0_pm_state *info) .priv = info }; - if (dev_priv->chipset < 0xd0) - nv_wr32(dev, 0x611200, 0x00003300); + if (device->chipset < 0xd0) + nv_wr32(device, 0x611200, 0x00003300); else - nv_wr32(dev, 0x62c000, 0x03030000); + nv_wr32(device, 0x62c000, 0x03030000); nouveau_mem_exec(&exec, info->perflvl); - if (dev_priv->chipset < 0xd0) - nv_wr32(dev, 0x611200, 0x00003330); + if (device->chipset < 0xd0) + nv_wr32(device, 0x611200, 0x00003330); else - nv_wr32(dev, 0x62c000, 0x03030300); + nv_wr32(device, 0x62c000, 0x03030300); } int nvc0_pm_clocks_set(struct drm_device *dev, void *data) diff --git a/drivers/gpu/drm/nouveau/nvd0_display.c b/drivers/gpu/drm/nouveau/nvd0_display.c index 77d5ce365bb2..37037bc33266 100644 --- a/drivers/gpu/drm/nouveau/nvd0_display.c +++ b/drivers/gpu/drm/nouveau/nvd0_display.c @@ -27,14 +27,21 @@ #include "drmP.h" #include "drm_crtc_helper.h" -#include "nouveau_drv.h" +#include "nouveau_drm.h" +#include "nouveau_dma.h" +#include "nouveau_gem.h" #include "nouveau_connector.h" #include "nouveau_encoder.h" #include "nouveau_crtc.h" -#include "nouveau_fb.h" #include "nouveau_fence.h" #include "nv50_display.h" +#include + +#include +#include +#include + #define EVO_DMA_NR 9 #define EVO_MASTER (0x00) @@ -71,8 +78,7 @@ struct nvd0_display { static struct nvd0_display * nvd0_display(struct drm_device *dev) { - struct drm_nouveau_private *dev_priv = dev->dev_private; - return dev_priv->engine.display.priv; + return nouveau_display(dev)->priv; } static struct drm_crtc * @@ -87,28 +93,31 @@ nvd0_display_crtc_get(struct drm_encoder *encoder) static inline int evo_icmd(struct drm_device *dev, int id, u32 mthd, u32 data) { + struct nouveau_device *device = nouveau_dev(dev); int ret = 0; - nv_mask(dev, 0x610700 + (id * 0x10), 0x00000001, 0x00000001); - nv_wr32(dev, 0x610704 + (id * 0x10), data); - nv_mask(dev, 0x610704 + (id * 0x10), 0x80000ffc, 0x80000000 | mthd); - if (!nv_wait(dev, 0x610704 + (id * 0x10), 0x80000000, 0x00000000)) + nv_mask(device, 0x610700 + (id * 0x10), 0x00000001, 0x00000001); + nv_wr32(device, 0x610704 + (id * 0x10), data); + nv_mask(device, 0x610704 + (id * 0x10), 0x80000ffc, 0x80000000 | mthd); + if (!nv_wait(device, 0x610704 + (id * 0x10), 0x80000000, 0x00000000)) ret = -EBUSY; - nv_mask(dev, 0x610700 + (id * 0x10), 0x00000001, 0x00000000); + nv_mask(device, 0x610700 + (id * 0x10), 0x00000001, 0x00000000); return ret; } static u32 * evo_wait(struct drm_device *dev, int id, int nr) { + struct nouveau_device *device = nouveau_dev(dev); + struct nouveau_drm *drm = nouveau_drm(dev); struct nvd0_display *disp = nvd0_display(dev); - u32 put = nv_rd32(dev, 0x640000 + (id * 0x1000)) / 4; + u32 put = nv_rd32(device, 0x640000 + (id * 0x1000)) / 4; if (put + nr >= (PAGE_SIZE / 4)) { disp->evo[id].ptr[put] = 0x20000000; - nv_wr32(dev, 0x640000 + (id * 0x1000), 0x00000000); - if (!nv_wait(dev, 0x640004 + (id * 0x1000), ~0, 0x00000000)) { - NV_ERROR(dev, "evo %d dma stalled\n", id); + nv_wr32(device, 0x640000 + (id * 0x1000), 0x00000000); + if (!nv_wait(device, 0x640004 + (id * 0x1000), ~0, 0x00000000)) { + NV_ERROR(drm, "evo %d dma stalled\n", id); return NULL; } @@ -121,9 +130,10 @@ evo_wait(struct drm_device *dev, int id, int nr) static void evo_kick(u32 *push, struct drm_device *dev, int id) { + struct nouveau_device *device = nouveau_dev(dev); struct nvd0_display *disp = nvd0_display(dev); - nv_wr32(dev, 0x640000 + (id * 0x1000), (push - disp->evo[id].ptr) << 2); + nv_wr32(device, 0x640000 + (id * 0x1000), (push - disp->evo[id].ptr) << 2); } #define evo_mthd(p,m,s) *((p)++) = (((s) << 18) | (m)) @@ -132,6 +142,8 @@ evo_kick(u32 *push, struct drm_device *dev, int id) static int evo_init_dma(struct drm_device *dev, int ch) { + struct nouveau_device *device = nouveau_dev(dev); + struct nouveau_drm *drm = nouveau_drm(dev); struct nvd0_display *disp = nvd0_display(dev); u32 flags; @@ -139,68 +151,76 @@ evo_init_dma(struct drm_device *dev, int ch) if (ch == EVO_MASTER) flags |= 0x01000000; - nv_wr32(dev, 0x610494 + (ch * 0x0010), (disp->evo[ch].handle >> 8) | 3); - nv_wr32(dev, 0x610498 + (ch * 0x0010), 0x00010000); - nv_wr32(dev, 0x61049c + (ch * 0x0010), 0x00000001); - nv_mask(dev, 0x610490 + (ch * 0x0010), 0x00000010, 0x00000010); - nv_wr32(dev, 0x640000 + (ch * 0x1000), 0x00000000); - nv_wr32(dev, 0x610490 + (ch * 0x0010), 0x00000013 | flags); - if (!nv_wait(dev, 0x610490 + (ch * 0x0010), 0x80000000, 0x00000000)) { - NV_ERROR(dev, "PDISP: ch%d 0x%08x\n", ch, - nv_rd32(dev, 0x610490 + (ch * 0x0010))); + nv_wr32(device, 0x610494 + (ch * 0x0010), (disp->evo[ch].handle >> 8) | 3); + nv_wr32(device, 0x610498 + (ch * 0x0010), 0x00010000); + nv_wr32(device, 0x61049c + (ch * 0x0010), 0x00000001); + nv_mask(device, 0x610490 + (ch * 0x0010), 0x00000010, 0x00000010); + nv_wr32(device, 0x640000 + (ch * 0x1000), 0x00000000); + nv_wr32(device, 0x610490 + (ch * 0x0010), 0x00000013 | flags); + if (!nv_wait(device, 0x610490 + (ch * 0x0010), 0x80000000, 0x00000000)) { + NV_ERROR(drm, "PDISP: ch%d 0x%08x\n", ch, + nv_rd32(device, 0x610490 + (ch * 0x0010))); return -EBUSY; } - nv_mask(dev, 0x610090, (1 << ch), (1 << ch)); - nv_mask(dev, 0x6100a0, (1 << ch), (1 << ch)); + nv_mask(device, 0x610090, (1 << ch), (1 << ch)); + nv_mask(device, 0x6100a0, (1 << ch), (1 << ch)); return 0; } static void evo_fini_dma(struct drm_device *dev, int ch) { - if (!(nv_rd32(dev, 0x610490 + (ch * 0x0010)) & 0x00000010)) + struct nouveau_device *device = nouveau_dev(dev); + + if (!(nv_rd32(device, 0x610490 + (ch * 0x0010)) & 0x00000010)) return; - nv_mask(dev, 0x610490 + (ch * 0x0010), 0x00000010, 0x00000000); - nv_mask(dev, 0x610490 + (ch * 0x0010), 0x00000003, 0x00000000); - nv_wait(dev, 0x610490 + (ch * 0x0010), 0x80000000, 0x00000000); - nv_mask(dev, 0x610090, (1 << ch), 0x00000000); - nv_mask(dev, 0x6100a0, (1 << ch), 0x00000000); + nv_mask(device, 0x610490 + (ch * 0x0010), 0x00000010, 0x00000000); + nv_mask(device, 0x610490 + (ch * 0x0010), 0x00000003, 0x00000000); + nv_wait(device, 0x610490 + (ch * 0x0010), 0x80000000, 0x00000000); + nv_mask(device, 0x610090, (1 << ch), 0x00000000); + nv_mask(device, 0x6100a0, (1 << ch), 0x00000000); } static inline void evo_piow(struct drm_device *dev, int ch, u16 mthd, u32 data) { - nv_wr32(dev, 0x640000 + (ch * 0x1000) + mthd, data); + struct nouveau_device *device = nouveau_dev(dev); + nv_wr32(device, 0x640000 + (ch * 0x1000) + mthd, data); } static int evo_init_pio(struct drm_device *dev, int ch) { - nv_wr32(dev, 0x610490 + (ch * 0x0010), 0x00000001); - if (!nv_wait(dev, 0x610490 + (ch * 0x0010), 0x00010000, 0x00010000)) { - NV_ERROR(dev, "PDISP: ch%d 0x%08x\n", ch, - nv_rd32(dev, 0x610490 + (ch * 0x0010))); + struct nouveau_device *device = nouveau_dev(dev); + struct nouveau_drm *drm = nouveau_drm(dev); + + nv_wr32(device, 0x610490 + (ch * 0x0010), 0x00000001); + if (!nv_wait(device, 0x610490 + (ch * 0x0010), 0x00010000, 0x00010000)) { + NV_ERROR(drm, "PDISP: ch%d 0x%08x\n", ch, + nv_rd32(device, 0x610490 + (ch * 0x0010))); return -EBUSY; } - nv_mask(dev, 0x610090, (1 << ch), (1 << ch)); - nv_mask(dev, 0x6100a0, (1 << ch), (1 << ch)); + nv_mask(device, 0x610090, (1 << ch), (1 << ch)); + nv_mask(device, 0x6100a0, (1 << ch), (1 << ch)); return 0; } static void evo_fini_pio(struct drm_device *dev, int ch) { - if (!(nv_rd32(dev, 0x610490 + (ch * 0x0010)) & 0x00000001)) + struct nouveau_device *device = nouveau_dev(dev); + + if (!(nv_rd32(device, 0x610490 + (ch * 0x0010)) & 0x00000001)) return; - nv_mask(dev, 0x610490 + (ch * 0x0010), 0x00000010, 0x00000010); - nv_mask(dev, 0x610490 + (ch * 0x0010), 0x00000001, 0x00000000); - nv_wait(dev, 0x610490 + (ch * 0x0010), 0x00010000, 0x00000000); - nv_mask(dev, 0x610090, (1 << ch), 0x00000000); - nv_mask(dev, 0x6100a0, (1 << ch), 0x00000000); + nv_mask(device, 0x610490 + (ch * 0x0010), 0x00000010, 0x00000010); + nv_mask(device, 0x610490 + (ch * 0x0010), 0x00000001, 0x00000000); + nv_wait(device, 0x610490 + (ch * 0x0010), 0x00010000, 0x00000000); + nv_mask(device, 0x610090, (1 << ch), 0x00000000); + nv_mask(device, 0x6100a0, (1 << ch), 0x00000000); } static bool @@ -212,6 +232,7 @@ evo_sync_wait(void *data) static int evo_sync(struct drm_device *dev, int ch) { + struct nouveau_device *device = nouveau_dev(dev); struct nvd0_display *disp = nvd0_display(dev); u32 *push = evo_wait(dev, ch, 8); if (push) { @@ -222,7 +243,7 @@ evo_sync(struct drm_device *dev, int ch) evo_data(push, 0x00000000); evo_data(push, 0x00000000); evo_kick(push, dev, ch); - if (nv_wait_cb(dev, evo_sync_wait, disp->sync)) + if (nv_wait_cb(device, evo_sync_wait, disp->sync)) return 0; } @@ -350,7 +371,7 @@ nvd0_display_flip_next(struct drm_crtc *crtc, struct drm_framebuffer *fb, static int nvd0_crtc_set_dither(struct nouveau_crtc *nv_crtc, bool update) { - struct drm_nouveau_private *dev_priv = nv_crtc->base.dev->dev_private; + struct nouveau_drm *drm = nouveau_drm(nv_crtc->base.dev); struct drm_device *dev = nv_crtc->base.dev; struct nouveau_connector *nv_connector; struct drm_connector *connector; @@ -373,7 +394,7 @@ nvd0_crtc_set_dither(struct nouveau_crtc *nv_crtc, bool update) mode |= nv_connector->dithering_depth; } - if (dev_priv->card_type < NV_E0) + if (nv_device(drm->device)->card_type < NV_E0) mthd = 0x0490 + (nv_crtc->index * 0x0300); else mthd = 0x04a0 + (nv_crtc->index * 0x0300); @@ -688,11 +709,12 @@ static int nvd0_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y, struct drm_framebuffer *old_fb) { + struct nouveau_drm *drm = nouveau_drm(crtc->dev); struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); int ret; if (!crtc->fb) { - NV_DEBUG_KMS(crtc->dev, "No FB bound\n"); + NV_DEBUG(drm, "No FB bound\n"); return 0; } @@ -910,6 +932,7 @@ nvd0_dac_dpms(struct drm_encoder *encoder, int mode) { struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); struct drm_device *dev = encoder->dev; + struct nouveau_device *device = nouveau_dev(dev); int or = nv_encoder->or; u32 dpms_ctrl; @@ -919,9 +942,9 @@ nvd0_dac_dpms(struct drm_encoder *encoder, int mode) if (mode == DRM_MODE_DPMS_SUSPEND || mode == DRM_MODE_DPMS_OFF) dpms_ctrl |= 0x00000004; - nv_wait(dev, 0x61a004 + (or * 0x0800), 0x80000000, 0x00000000); - nv_mask(dev, 0x61a004 + (or * 0x0800), 0xc000007f, dpms_ctrl); - nv_wait(dev, 0x61a004 + (or * 0x0800), 0x80000000, 0x00000000); + nv_wait(device, 0x61a004 + (or * 0x0800), 0x80000000, 0x00000000); + nv_mask(device, 0x61a004 + (or * 0x0800), 0xc000007f, dpms_ctrl); + nv_wait(device, 0x61a004 + (or * 0x0800), 0x80000000, 0x00000000); } static bool @@ -1012,18 +1035,19 @@ nvd0_dac_detect(struct drm_encoder *encoder, struct drm_connector *connector) enum drm_connector_status status = connector_status_disconnected; struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); struct drm_device *dev = encoder->dev; + struct nouveau_device *device = nouveau_dev(dev); int or = nv_encoder->or; u32 load; - nv_wr32(dev, 0x61a00c + (or * 0x800), 0x00100000); + nv_wr32(device, 0x61a00c + (or * 0x800), 0x00100000); udelay(9500); - nv_wr32(dev, 0x61a00c + (or * 0x800), 0x80000000); + nv_wr32(device, 0x61a00c + (or * 0x800), 0x80000000); - load = nv_rd32(dev, 0x61a00c + (or * 0x800)); + load = nv_rd32(device, 0x61a00c + (or * 0x800)); if ((load & 0x38000000) == 0x38000000) status = connector_status_connected; - nv_wr32(dev, 0x61a00c + (or * 0x800), 0x00000000); + nv_wr32(device, 0x61a00c + (or * 0x800), 0x00000000); return status; } @@ -1081,24 +1105,25 @@ nvd0_audio_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode) struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); struct nouveau_connector *nv_connector; struct drm_device *dev = encoder->dev; + struct nouveau_device *device = nouveau_dev(dev); int i, or = nv_encoder->or * 0x30; nv_connector = nouveau_encoder_connector_get(nv_encoder); if (!drm_detect_monitor_audio(nv_connector->edid)) return; - nv_mask(dev, 0x10ec10 + or, 0x80000003, 0x80000001); + nv_mask(device, 0x10ec10 + or, 0x80000003, 0x80000001); drm_edid_to_eld(&nv_connector->base, nv_connector->edid); if (nv_connector->base.eld[0]) { u8 *eld = nv_connector->base.eld; for (i = 0; i < eld[2] * 4; i++) - nv_wr32(dev, 0x10ec00 + or, (i << 8) | eld[i]); + nv_wr32(device, 0x10ec00 + or, (i << 8) | eld[i]); for (i = eld[2] * 4; i < 0x60; i++) - nv_wr32(dev, 0x10ec00 + or, (i << 8) | 0x00); + nv_wr32(device, 0x10ec00 + or, (i << 8) | 0x00); - nv_mask(dev, 0x10ec10 + or, 0x80000002, 0x80000002); + nv_mask(device, 0x10ec10 + or, 0x80000002, 0x80000002); } } @@ -1107,9 +1132,10 @@ nvd0_audio_disconnect(struct drm_encoder *encoder) { struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); struct drm_device *dev = encoder->dev; + struct nouveau_device *device = nouveau_dev(dev); int or = nv_encoder->or * 0x30; - nv_mask(dev, 0x10ec10 + or, 0x80000003, 0x80000000); + nv_mask(device, 0x10ec10 + or, 0x80000003, 0x80000000); } /****************************************************************************** @@ -1122,6 +1148,7 @@ nvd0_hdmi_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode) struct nouveau_crtc *nv_crtc = nouveau_crtc(encoder->crtc); struct nouveau_connector *nv_connector; struct drm_device *dev = encoder->dev; + struct nouveau_device *device = nouveau_dev(dev); int head = nv_crtc->index * 0x800; u32 rekey = 56; /* binary driver, and tegra constant */ u32 max_ac_packet; @@ -1136,25 +1163,25 @@ nvd0_hdmi_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode) max_ac_packet /= 32; /* AVI InfoFrame */ - nv_mask(dev, 0x616714 + head, 0x00000001, 0x00000000); - nv_wr32(dev, 0x61671c + head, 0x000d0282); - nv_wr32(dev, 0x616720 + head, 0x0000006f); - nv_wr32(dev, 0x616724 + head, 0x00000000); - nv_wr32(dev, 0x616728 + head, 0x00000000); - nv_wr32(dev, 0x61672c + head, 0x00000000); - nv_mask(dev, 0x616714 + head, 0x00000001, 0x00000001); + nv_mask(device, 0x616714 + head, 0x00000001, 0x00000000); + nv_wr32(device, 0x61671c + head, 0x000d0282); + nv_wr32(device, 0x616720 + head, 0x0000006f); + nv_wr32(device, 0x616724 + head, 0x00000000); + nv_wr32(device, 0x616728 + head, 0x00000000); + nv_wr32(device, 0x61672c + head, 0x00000000); + nv_mask(device, 0x616714 + head, 0x00000001, 0x00000001); /* ??? InfoFrame? */ - nv_mask(dev, 0x6167a4 + head, 0x00000001, 0x00000000); - nv_wr32(dev, 0x6167ac + head, 0x00000010); - nv_mask(dev, 0x6167a4 + head, 0x00000001, 0x00000001); + nv_mask(device, 0x6167a4 + head, 0x00000001, 0x00000000); + nv_wr32(device, 0x6167ac + head, 0x00000010); + nv_mask(device, 0x6167a4 + head, 0x00000001, 0x00000001); /* HDMI_CTRL */ - nv_mask(dev, 0x616798 + head, 0x401f007f, 0x40000000 | rekey | + nv_mask(device, 0x616798 + head, 0x401f007f, 0x40000000 | rekey | max_ac_packet << 16); /* NFI, audio doesn't work without it though.. */ - nv_mask(dev, 0x616548 + head, 0x00000070, 0x00000000); + nv_mask(device, 0x616548 + head, 0x00000070, 0x00000000); nvd0_audio_mode_set(encoder, mode); } @@ -1165,13 +1192,14 @@ nvd0_hdmi_disconnect(struct drm_encoder *encoder) struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); struct nouveau_crtc *nv_crtc = nouveau_crtc(nv_encoder->crtc); struct drm_device *dev = encoder->dev; + struct nouveau_device *device = nouveau_dev(dev); int head = nv_crtc->index * 0x800; nvd0_audio_disconnect(encoder); - nv_mask(dev, 0x616798 + head, 0x40000000, 0x00000000); - nv_mask(dev, 0x6167a4 + head, 0x00000001, 0x00000000); - nv_mask(dev, 0x616714 + head, 0x00000001, 0x00000000); + nv_mask(device, 0x616798 + head, 0x40000000, 0x00000000); + nv_mask(device, 0x6167a4 + head, 0x00000001, 0x00000000); + nv_mask(device, 0x616714 + head, 0x00000001, 0x00000000); } /****************************************************************************** @@ -1187,15 +1215,18 @@ nvd0_sor_dp_lane_map(struct drm_device *dev, struct dcb_output *dcb, u8 lane) static void nvd0_sor_dp_train_set(struct drm_device *dev, struct dcb_output *dcb, u8 pattern) { + struct nouveau_device *device = nouveau_dev(dev); const u32 or = ffs(dcb->or) - 1, link = !(dcb->sorconf.link & 1); const u32 loff = (or * 0x800) + (link * 0x80); - nv_mask(dev, 0x61c110 + loff, 0x0f0f0f0f, 0x01010101 * pattern); + nv_mask(device, 0x61c110 + loff, 0x0f0f0f0f, 0x01010101 * pattern); } static void nvd0_sor_dp_train_adj(struct drm_device *dev, struct dcb_output *dcb, u8 lane, u8 swing, u8 preem) { + struct nouveau_device *device = nouveau_dev(dev); + struct nouveau_drm *drm = nouveau_drm(dev); const u32 or = ffs(dcb->or) - 1, link = !(dcb->sorconf.link & 1); const u32 loff = (or * 0x800) + (link * 0x80); u32 shift = nvd0_sor_dp_lane_map(dev, dcb, lane); @@ -1223,25 +1254,26 @@ nvd0_sor_dp_train_adj(struct drm_device *dev, struct dcb_output *dcb, } if (!config) { - NV_ERROR(dev, "PDISP: unsupported DP table for chipset\n"); + NV_ERROR(drm, "PDISP: unsupported DP table for chipset\n"); return; } - nv_mask(dev, 0x61c118 + loff, mask, config[1] << shift); - nv_mask(dev, 0x61c120 + loff, mask, config[2] << shift); - nv_mask(dev, 0x61c130 + loff, 0x0000ff00, config[3] << 8); - nv_mask(dev, 0x61c13c + loff, 0x00000000, 0x00000000); + nv_mask(device, 0x61c118 + loff, mask, config[1] << shift); + nv_mask(device, 0x61c120 + loff, mask, config[2] << shift); + nv_mask(device, 0x61c130 + loff, 0x0000ff00, config[3] << 8); + nv_mask(device, 0x61c13c + loff, 0x00000000, 0x00000000); } static void nvd0_sor_dp_link_set(struct drm_device *dev, struct dcb_output *dcb, int crtc, int link_nr, u32 link_bw, bool enhframe) { + struct nouveau_device *device = nouveau_dev(dev); const u32 or = ffs(dcb->or) - 1, link = !(dcb->sorconf.link & 1); const u32 loff = (or * 0x800) + (link * 0x80); const u32 soff = (or * 0x800); - u32 dpctrl = nv_rd32(dev, 0x61c10c + loff) & ~0x001f4000; - u32 clksor = nv_rd32(dev, 0x612300 + soff) & ~0x007c0000; + u32 dpctrl = nv_rd32(device, 0x61c10c + loff) & ~0x001f4000; + u32 clksor = nv_rd32(device, 0x612300 + soff) & ~0x007c0000; u32 script = 0x0000, lane_mask = 0; u8 *table, *entry; int i; @@ -1271,20 +1303,21 @@ nvd0_sor_dp_link_set(struct drm_device *dev, struct dcb_output *dcb, int crtc, for (i = 0; i < link_nr; i++) lane_mask |= 1 << (nvd0_sor_dp_lane_map(dev, dcb, i) >> 3); - nv_wr32(dev, 0x612300 + soff, clksor); - nv_wr32(dev, 0x61c10c + loff, dpctrl); - nv_mask(dev, 0x61c130 + loff, 0x0000000f, lane_mask); + nv_wr32(device, 0x612300 + soff, clksor); + nv_wr32(device, 0x61c10c + loff, dpctrl); + nv_mask(device, 0x61c130 + loff, 0x0000000f, lane_mask); } static void nvd0_sor_dp_link_get(struct drm_device *dev, struct dcb_output *dcb, u32 *link_nr, u32 *link_bw) { + struct nouveau_device *device = nouveau_dev(dev); const u32 or = ffs(dcb->or) - 1, link = !(dcb->sorconf.link & 1); const u32 loff = (or * 0x800) + (link * 0x80); const u32 soff = (or * 0x800); - u32 dpctrl = nv_rd32(dev, 0x61c10c + loff) & 0x000f0000; - u32 clksor = nv_rd32(dev, 0x612300 + soff); + u32 dpctrl = nv_rd32(device, 0x61c10c + loff) & 0x000f0000; + u32 clksor = nv_rd32(device, 0x612300 + soff); if (dpctrl > 0x00030000) *link_nr = 4; else if (dpctrl > 0x00010000) *link_nr = 2; @@ -1298,6 +1331,7 @@ static void nvd0_sor_dp_calc_tu(struct drm_device *dev, struct dcb_output *dcb, u32 crtc, u32 datarate) { + struct nouveau_device *device = nouveau_dev(dev); const u32 symbol = 100000; const u32 TU = 64; u32 link_nr, link_bw; @@ -1317,7 +1351,7 @@ nvd0_sor_dp_calc_tu(struct drm_device *dev, struct dcb_output *dcb, value += 5; value |= 0x08000000; - nv_wr32(dev, 0x616610 + (crtc * 0x800), value); + nv_wr32(device, 0x616610 + (crtc * 0x800), value); } static void @@ -1325,6 +1359,7 @@ nvd0_sor_dpms(struct drm_encoder *encoder, int mode) { struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); struct drm_device *dev = encoder->dev; + struct nouveau_device *device = nouveau_dev(dev); struct drm_encoder *partner; int or = nv_encoder->or; u32 dpms_ctrl; @@ -1348,10 +1383,10 @@ nvd0_sor_dpms(struct drm_encoder *encoder, int mode) dpms_ctrl = (mode == DRM_MODE_DPMS_ON); dpms_ctrl |= 0x80000000; - nv_wait(dev, 0x61c004 + (or * 0x0800), 0x80000000, 0x00000000); - nv_mask(dev, 0x61c004 + (or * 0x0800), 0x80000001, dpms_ctrl); - nv_wait(dev, 0x61c004 + (or * 0x0800), 0x80000000, 0x00000000); - nv_wait(dev, 0x61c030 + (or * 0x0800), 0x10000000, 0x00000000); + nv_wait(device, 0x61c004 + (or * 0x0800), 0x80000000, 0x00000000); + nv_mask(device, 0x61c004 + (or * 0x0800), 0x80000001, dpms_ctrl); + nv_wait(device, 0x61c004 + (or * 0x0800), 0x80000000, 0x00000000); + nv_wait(device, 0x61c030 + (or * 0x0800), 0x10000000, 0x00000000); if (nv_encoder->dcb->type == DCB_OUTPUT_DP) { struct dp_train_func func = { @@ -1428,11 +1463,11 @@ nvd0_sor_mode_set(struct drm_encoder *encoder, struct drm_display_mode *umode, struct drm_display_mode *mode) { struct drm_device *dev = encoder->dev; - struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_drm *drm = nouveau_drm(dev); struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); struct nouveau_crtc *nv_crtc = nouveau_crtc(encoder->crtc); struct nouveau_connector *nv_connector; - struct nvbios *bios = &dev_priv->vbios; + struct nvbios *bios = &drm->vbios; u32 mode_ctrl = (1 << nv_crtc->index); u32 syncs, magic, *push; u32 or_config; @@ -1587,7 +1622,7 @@ nvd0_sor_create(struct drm_connector *connector, struct dcb_output *dcbe) static struct dcb_output * lookup_dcb(struct drm_device *dev, int id, u32 mc) { - struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_drm *drm = nouveau_drm(dev); int type, or, i, link = -1; if (id < 4) { @@ -1602,32 +1637,33 @@ lookup_dcb(struct drm_device *dev, int id, u32 mc) case 0x00000800: link = 0; type = DCB_OUTPUT_DP; break; case 0x00000900: link = 1; type = DCB_OUTPUT_DP; break; default: - NV_ERROR(dev, "PDISP: unknown SOR mc 0x%08x\n", mc); + NV_ERROR(drm, "PDISP: unknown SOR mc 0x%08x\n", mc); return NULL; } or = id - 4; } - for (i = 0; i < dev_priv->vbios.dcb.entries; i++) { - struct dcb_output *dcb = &dev_priv->vbios.dcb.entry[i]; + for (i = 0; i < drm->vbios.dcb.entries; i++) { + struct dcb_output *dcb = &drm->vbios.dcb.entry[i]; if (dcb->type == type && (dcb->or & (1 << or)) && (link < 0 || link == !(dcb->sorconf.link & 1))) return dcb; } - NV_ERROR(dev, "PDISP: DCB for %d/0x%08x not found\n", id, mc); + NV_ERROR(drm, "PDISP: DCB for %d/0x%08x not found\n", id, mc); return NULL; } static void nvd0_display_unk1_handler(struct drm_device *dev, u32 crtc, u32 mask) { + struct nouveau_device *device = nouveau_dev(dev); struct dcb_output *dcb; int i; for (i = 0; mask && i < 8; i++) { - u32 mcc = nv_rd32(dev, 0x640180 + (i * 0x20)); + u32 mcc = nv_rd32(device, 0x640180 + (i * 0x20)); if (!(mcc & (1 << crtc))) continue; @@ -1638,20 +1674,22 @@ nvd0_display_unk1_handler(struct drm_device *dev, u32 crtc, u32 mask) nouveau_bios_run_display_table(dev, 0x0000, -1, dcb, crtc); } - nv_wr32(dev, 0x6101d4, 0x00000000); - nv_wr32(dev, 0x6109d4, 0x00000000); - nv_wr32(dev, 0x6101d0, 0x80000000); + nv_wr32(device, 0x6101d4, 0x00000000); + nv_wr32(device, 0x6109d4, 0x00000000); + nv_wr32(device, 0x6101d0, 0x80000000); } static void nvd0_display_unk2_handler(struct drm_device *dev, u32 crtc, u32 mask) { + struct nouveau_device *device = nouveau_dev(dev); + struct nouveau_drm *drm = nouveau_drm(dev); struct dcb_output *dcb; u32 or, tmp, pclk; int i; for (i = 0; mask && i < 8; i++) { - u32 mcc = nv_rd32(dev, 0x640180 + (i * 0x20)); + u32 mcc = nv_rd32(device, 0x640180 + (i * 0x20)); if (!(mcc & (1 << crtc))) continue; @@ -1662,16 +1700,16 @@ nvd0_display_unk2_handler(struct drm_device *dev, u32 crtc, u32 mask) nouveau_bios_run_display_table(dev, 0x0000, -2, dcb, crtc); } - pclk = nv_rd32(dev, 0x660450 + (crtc * 0x300)) / 1000; - NV_DEBUG_KMS(dev, "PDISP: crtc %d pclk %d mask 0x%08x\n", + pclk = nv_rd32(device, 0x660450 + (crtc * 0x300)) / 1000; + NV_DEBUG(drm, "PDISP: crtc %d pclk %d mask 0x%08x\n", crtc, pclk, mask); if (pclk && (mask & 0x00010000)) { nv50_crtc_set_clock(dev, crtc, pclk); } for (i = 0; mask && i < 8; i++) { - u32 mcp = nv_rd32(dev, 0x660180 + (i * 0x20)); - u32 cfg = nv_rd32(dev, 0x660184 + (i * 0x20)); + u32 mcp = nv_rd32(device, 0x660180 + (i * 0x20)); + u32 cfg = nv_rd32(device, 0x660184 + (i * 0x20)); if (!(mcp & (1 << crtc))) continue; @@ -1682,10 +1720,10 @@ nvd0_display_unk2_handler(struct drm_device *dev, u32 crtc, u32 mask) nouveau_bios_run_display_table(dev, cfg, pclk, dcb, crtc); - nv_wr32(dev, 0x612200 + (crtc * 0x800), 0x00000000); + nv_wr32(device, 0x612200 + (crtc * 0x800), 0x00000000); switch (dcb->type) { case DCB_OUTPUT_ANALOG: - nv_wr32(dev, 0x612280 + (or * 0x800), 0x00000000); + nv_wr32(device, 0x612280 + (or * 0x800), 0x00000000); break; case DCB_OUTPUT_TMDS: case DCB_OUTPUT_LVDS: @@ -1695,7 +1733,7 @@ nvd0_display_unk2_handler(struct drm_device *dev, u32 crtc, u32 mask) else tmp = 0x00000000; - nv_mask(dev, 0x612300 + (or * 0x800), 0x00000707, tmp); + nv_mask(device, 0x612300 + (or * 0x800), 0x00000707, tmp); break; default: break; @@ -1704,22 +1742,23 @@ nvd0_display_unk2_handler(struct drm_device *dev, u32 crtc, u32 mask) break; } - nv_wr32(dev, 0x6101d4, 0x00000000); - nv_wr32(dev, 0x6109d4, 0x00000000); - nv_wr32(dev, 0x6101d0, 0x80000000); + nv_wr32(device, 0x6101d4, 0x00000000); + nv_wr32(device, 0x6109d4, 0x00000000); + nv_wr32(device, 0x6101d0, 0x80000000); } static void nvd0_display_unk4_handler(struct drm_device *dev, u32 crtc, u32 mask) { + struct nouveau_device *device = nouveau_dev(dev); struct dcb_output *dcb; int pclk, i; - pclk = nv_rd32(dev, 0x660450 + (crtc * 0x300)) / 1000; + pclk = nv_rd32(device, 0x660450 + (crtc * 0x300)) / 1000; for (i = 0; mask && i < 8; i++) { - u32 mcp = nv_rd32(dev, 0x660180 + (i * 0x20)); - u32 cfg = nv_rd32(dev, 0x660184 + (i * 0x20)); + u32 mcp = nv_rd32(device, 0x660180 + (i * 0x20)); + u32 cfg = nv_rd32(device, 0x660184 + (i * 0x20)); if (!(mcp & (1 << crtc))) continue; @@ -1730,34 +1769,36 @@ nvd0_display_unk4_handler(struct drm_device *dev, u32 crtc, u32 mask) nouveau_bios_run_display_table(dev, cfg, -pclk, dcb, crtc); } - nv_wr32(dev, 0x6101d4, 0x00000000); - nv_wr32(dev, 0x6109d4, 0x00000000); - nv_wr32(dev, 0x6101d0, 0x80000000); + nv_wr32(device, 0x6101d4, 0x00000000); + nv_wr32(device, 0x6109d4, 0x00000000); + nv_wr32(device, 0x6101d0, 0x80000000); } static void nvd0_display_bh(unsigned long data) { struct drm_device *dev = (struct drm_device *)data; + struct nouveau_device *device = nouveau_dev(dev); + struct nouveau_drm *drm = nouveau_drm(dev); struct nvd0_display *disp = nvd0_display(dev); u32 mask = 0, crtc = ~0; int i; if (drm_debug & (DRM_UT_DRIVER | DRM_UT_KMS)) { - NV_INFO(dev, "PDISP: modeset req %d\n", disp->modeset); - NV_INFO(dev, " STAT: 0x%08x 0x%08x 0x%08x\n", - nv_rd32(dev, 0x6101d0), - nv_rd32(dev, 0x6101d4), nv_rd32(dev, 0x6109d4)); + NV_INFO(drm, "PDISP: modeset req %d\n", disp->modeset); + NV_INFO(drm, " STAT: 0x%08x 0x%08x 0x%08x\n", + nv_rd32(device, 0x6101d0), + nv_rd32(device, 0x6101d4), nv_rd32(device, 0x6109d4)); for (i = 0; i < 8; i++) { - NV_INFO(dev, " %s%d: 0x%08x 0x%08x\n", + NV_INFO(drm, " %s%d: 0x%08x 0x%08x\n", i < 4 ? "DAC" : "SOR", i, - nv_rd32(dev, 0x640180 + (i * 0x20)), - nv_rd32(dev, 0x660180 + (i * 0x20))); + nv_rd32(device, 0x640180 + (i * 0x20)), + nv_rd32(device, 0x660180 + (i * 0x20))); } } while (!mask && ++crtc < dev->mode_config.num_crtc) - mask = nv_rd32(dev, 0x6101d4 + (crtc * 0x800)); + mask = nv_rd32(device, 0x6101d4 + (crtc * 0x800)); if (disp->modeset & 0x00000001) nvd0_display_unk1_handler(dev, crtc, mask); @@ -1767,51 +1808,52 @@ nvd0_display_bh(unsigned long data) nvd0_display_unk4_handler(dev, crtc, mask); } -static void +void nvd0_display_intr(struct drm_device *dev) { struct nvd0_display *disp = nvd0_display(dev); - u32 intr = nv_rd32(dev, 0x610088); - int i; + struct nouveau_device *device = nouveau_dev(dev); + struct nouveau_drm *drm = nouveau_drm(dev); + u32 intr = nv_rd32(device, 0x610088); if (intr & 0x00000001) { - u32 stat = nv_rd32(dev, 0x61008c); - nv_wr32(dev, 0x61008c, stat); + u32 stat = nv_rd32(device, 0x61008c); + nv_wr32(device, 0x61008c, stat); intr &= ~0x00000001; } if (intr & 0x00000002) { - u32 stat = nv_rd32(dev, 0x61009c); + u32 stat = nv_rd32(device, 0x61009c); int chid = ffs(stat) - 1; if (chid >= 0) { - u32 mthd = nv_rd32(dev, 0x6101f0 + (chid * 12)); - u32 data = nv_rd32(dev, 0x6101f4 + (chid * 12)); - u32 unkn = nv_rd32(dev, 0x6101f8 + (chid * 12)); + u32 mthd = nv_rd32(device, 0x6101f0 + (chid * 12)); + u32 data = nv_rd32(device, 0x6101f4 + (chid * 12)); + u32 unkn = nv_rd32(device, 0x6101f8 + (chid * 12)); - NV_INFO(dev, "EvoCh: chid %d mthd 0x%04x data 0x%08x " + NV_INFO(drm, "EvoCh: chid %d mthd 0x%04x data 0x%08x " "0x%08x 0x%08x\n", chid, (mthd & 0x0000ffc), data, mthd, unkn); - nv_wr32(dev, 0x61009c, (1 << chid)); - nv_wr32(dev, 0x6101f0 + (chid * 12), 0x90000000); + nv_wr32(device, 0x61009c, (1 << chid)); + nv_wr32(device, 0x6101f0 + (chid * 12), 0x90000000); } intr &= ~0x00000002; } if (intr & 0x00100000) { - u32 stat = nv_rd32(dev, 0x6100ac); + u32 stat = nv_rd32(device, 0x6100ac); if (stat & 0x00000007) { disp->modeset = stat; tasklet_schedule(&disp->tasklet); - nv_wr32(dev, 0x6100ac, (stat & 0x00000007)); + nv_wr32(device, 0x6100ac, (stat & 0x00000007)); stat &= ~0x00000007; } if (stat) { - NV_INFO(dev, "PDISP: unknown intr24 0x%08x\n", stat); - nv_wr32(dev, 0x6100ac, stat); + NV_INFO(drm, "PDISP: unknown intr24 0x%08x\n", stat); + nv_wr32(device, 0x6100ac, stat); } intr &= ~0x00100000; @@ -1819,7 +1861,7 @@ nvd0_display_intr(struct drm_device *dev) intr &= ~0x0f000000; /* vblank, handled in core */ if (intr) - NV_INFO(dev, "PDISP: unknown intr 0x%08x\n", intr); + NV_INFO(drm, "PDISP: unknown intr 0x%08x\n", intr); } /****************************************************************************** @@ -1846,15 +1888,17 @@ int nvd0_display_init(struct drm_device *dev) { struct nvd0_display *disp = nvd0_display(dev); + struct nouveau_device *device = nouveau_dev(dev); + struct nouveau_drm *drm = nouveau_drm(dev); int ret, i; u32 *push; - if (nv_rd32(dev, 0x6100ac) & 0x00000100) { - nv_wr32(dev, 0x6100ac, 0x00000100); - nv_mask(dev, 0x6194e8, 0x00000001, 0x00000000); - if (!nv_wait(dev, 0x6194e8, 0x00000002, 0x00000000)) { - NV_ERROR(dev, "PDISP: 0x6194e8 0x%08x\n", - nv_rd32(dev, 0x6194e8)); + if (nv_rd32(device, 0x6100ac) & 0x00000100) { + nv_wr32(device, 0x6100ac, 0x00000100); + nv_mask(device, 0x6194e8, 0x00000001, 0x00000000); + if (!nv_wait(device, 0x6194e8, 0x00000002, 0x00000000)) { + NV_ERROR(drm, "PDISP: 0x6194e8 0x%08x\n", + nv_rd32(device, 0x6194e8)); return -EBUSY; } } @@ -1863,27 +1907,27 @@ nvd0_display_init(struct drm_device *dev) * work at all unless you do the SOR part below. */ for (i = 0; i < 3; i++) { - u32 dac = nv_rd32(dev, 0x61a000 + (i * 0x800)); - nv_wr32(dev, 0x6101c0 + (i * 0x800), dac); + u32 dac = nv_rd32(device, 0x61a000 + (i * 0x800)); + nv_wr32(device, 0x6101c0 + (i * 0x800), dac); } for (i = 0; i < 4; i++) { - u32 sor = nv_rd32(dev, 0x61c000 + (i * 0x800)); - nv_wr32(dev, 0x6301c4 + (i * 0x800), sor); + u32 sor = nv_rd32(device, 0x61c000 + (i * 0x800)); + nv_wr32(device, 0x6301c4 + (i * 0x800), sor); } for (i = 0; i < dev->mode_config.num_crtc; i++) { - u32 crtc0 = nv_rd32(dev, 0x616104 + (i * 0x800)); - u32 crtc1 = nv_rd32(dev, 0x616108 + (i * 0x800)); - u32 crtc2 = nv_rd32(dev, 0x61610c + (i * 0x800)); - nv_wr32(dev, 0x6101b4 + (i * 0x800), crtc0); - nv_wr32(dev, 0x6101b8 + (i * 0x800), crtc1); - nv_wr32(dev, 0x6101bc + (i * 0x800), crtc2); + u32 crtc0 = nv_rd32(device, 0x616104 + (i * 0x800)); + u32 crtc1 = nv_rd32(device, 0x616108 + (i * 0x800)); + u32 crtc2 = nv_rd32(device, 0x61610c + (i * 0x800)); + nv_wr32(device, 0x6101b4 + (i * 0x800), crtc0); + nv_wr32(device, 0x6101b8 + (i * 0x800), crtc1); + nv_wr32(device, 0x6101bc + (i * 0x800), crtc2); } /* point at our hash table / objects, enable interrupts */ - nv_wr32(dev, 0x610010, (disp->mem->addr >> 8) | 9); - nv_mask(dev, 0x6100b0, 0x00000307, 0x00000307); + nv_wr32(device, 0x610010, (disp->mem->addr >> 8) | 9); + nv_mask(device, 0x6100b0, 0x00000307, 0x00000307); /* init master */ ret = evo_init_dma(dev, EVO_MASTER); @@ -1923,7 +1967,6 @@ error: void nvd0_display_destroy(struct drm_device *dev) { - struct drm_nouveau_private *dev_priv = dev->dev_private; struct nvd0_display *disp = nvd0_display(dev); struct pci_dev *pdev = dev->pdev; int i; @@ -1936,17 +1979,19 @@ nvd0_display_destroy(struct drm_device *dev) nouveau_gpuobj_ref(NULL, &disp->mem); nouveau_bo_unmap(disp->sync); nouveau_bo_ref(NULL, &disp->sync); - nouveau_irq_unregister(dev, 26); - dev_priv->engine.display.priv = NULL; + nouveau_display(dev)->priv = NULL; kfree(disp); } int nvd0_display_create(struct drm_device *dev) { - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct dcb_table *dcb = &dev_priv->vbios.dcb; + struct nouveau_device *device = nouveau_dev(dev); + struct nouveau_drm *drm = nouveau_drm(dev); + struct nouveau_bar *bar = nouveau_bar(device); + struct nouveau_fb *pfb = nouveau_fb(device); + struct dcb_table *dcb = &drm->vbios.dcb; struct drm_connector *connector, *tmp; struct pci_dev *pdev = dev->pdev; struct nvd0_display *disp; @@ -1956,10 +2001,14 @@ nvd0_display_create(struct drm_device *dev) disp = kzalloc(sizeof(*disp), GFP_KERNEL); if (!disp) return -ENOMEM; - dev_priv->engine.display.priv = disp; + + nouveau_display(dev)->priv = disp; + nouveau_display(dev)->dtor = nvd0_display_destroy; + nouveau_display(dev)->init = nvd0_display_init; + nouveau_display(dev)->fini = nvd0_display_fini; /* create crtc objects to represent the hw heads */ - crtcs = nv_rd32(dev, 0x022448); + crtcs = nv_rd32(device, 0x022448); for (i = 0; i < crtcs; i++) { ret = nvd0_crtc_create(dev, i); if (ret) @@ -1973,7 +2022,7 @@ nvd0_display_create(struct drm_device *dev) continue; if (dcbe->location != DCB_LOC_ON_CHIP) { - NV_WARN(dev, "skipping off-chip encoder %d/%d\n", + NV_WARN(drm, "skipping off-chip encoder %d/%d\n", dcbe->type, ffs(dcbe->or) - 1); continue; } @@ -1988,7 +2037,7 @@ nvd0_display_create(struct drm_device *dev) nvd0_dac_create(connector, dcbe); break; default: - NV_WARN(dev, "skipping unsupported encoder %d/%d\n", + NV_WARN(drm, "skipping unsupported encoder %d/%d\n", dcbe->type, ffs(dcbe->or) - 1); continue; } @@ -1999,14 +2048,13 @@ nvd0_display_create(struct drm_device *dev) if (connector->encoder_ids[0]) continue; - NV_WARN(dev, "%s has no encoders, removing\n", + NV_WARN(drm, "%s has no encoders, removing\n", drm_get_connector_name(connector)); connector->funcs->destroy(connector); } /* setup interrupt handling */ tasklet_init(&disp->tasklet, nvd0_display_bh, (unsigned long)dev); - nouveau_irq_register(dev, 26, nvd0_display_intr); /* small shared memory area we use for notifiers and semaphores */ ret = nouveau_bo_new(dev, 4096, 0x1000, TTM_PL_FLAG_VRAM, @@ -2023,7 +2071,7 @@ nvd0_display_create(struct drm_device *dev) goto out; /* hash table and dma objects for the memory areas we care about */ - ret = nouveau_gpuobj_new(dev, NULL, 0x4000, 0x10000, + ret = nouveau_gpuobj_new(nv_object(device), NULL, 0x4000, 0x10000, NVOBJ_FLAG_ZERO_ALLOC, &disp->mem); if (ret) goto out; @@ -2055,7 +2103,7 @@ nvd0_display_create(struct drm_device *dev) nv_wo32(disp->mem, dmao + 0x20, 0x00000049); nv_wo32(disp->mem, dmao + 0x24, 0x00000000); - nv_wo32(disp->mem, dmao + 0x28, (nvfb_vram_size(dev) - 1) >> 8); + nv_wo32(disp->mem, dmao + 0x28, (pfb->ram.size - 1) >> 8); nv_wo32(disp->mem, dmao + 0x2c, 0x00000000); nv_wo32(disp->mem, dmao + 0x30, 0x00000000); nv_wo32(disp->mem, dmao + 0x34, 0x00000000); @@ -2065,7 +2113,7 @@ nvd0_display_create(struct drm_device *dev) nv_wo32(disp->mem, dmao + 0x40, 0x00000009); nv_wo32(disp->mem, dmao + 0x44, 0x00000000); - nv_wo32(disp->mem, dmao + 0x48, (nvfb_vram_size(dev) - 1) >> 8); + nv_wo32(disp->mem, dmao + 0x48, (pfb->ram.size - 1) >> 8); nv_wo32(disp->mem, dmao + 0x4c, 0x00000000); nv_wo32(disp->mem, dmao + 0x50, 0x00000000); nv_wo32(disp->mem, dmao + 0x54, 0x00000000); @@ -2075,7 +2123,7 @@ nvd0_display_create(struct drm_device *dev) nv_wo32(disp->mem, dmao + 0x60, 0x0fe00009); nv_wo32(disp->mem, dmao + 0x64, 0x00000000); - nv_wo32(disp->mem, dmao + 0x68, (nvfb_vram_size(dev) - 1) >> 8); + nv_wo32(disp->mem, dmao + 0x68, (pfb->ram.size - 1) >> 8); nv_wo32(disp->mem, dmao + 0x6c, 0x00000000); nv_wo32(disp->mem, dmao + 0x70, 0x00000000); nv_wo32(disp->mem, dmao + 0x74, 0x00000000); @@ -2084,7 +2132,7 @@ nvd0_display_create(struct drm_device *dev) ((dmao + 0x60) << 9)); } - nvimem_flush(dev); + bar->flush(bar); out: if (ret) -- cgit v1.2.3