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/nouveau_dp.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/gpu/drm/nouveau/nouveau_dp.c') diff --git a/drivers/gpu/drm/nouveau/nouveau_dp.c b/drivers/gpu/drm/nouveau/nouveau_dp.c index 7e289d2ad8e4..67b322554ac6 100644 --- a/drivers/gpu/drm/nouveau/nouveau_dp.c +++ b/drivers/gpu/drm/nouveau/nouveau_dp.c @@ -25,11 +25,11 @@ #include "drmP.h" #include "nouveau_drv.h" -#include "nouveau_i2c.h" +#include #include "nouveau_connector.h" #include "nouveau_encoder.h" #include "nouveau_crtc.h" -#include "nouveau_gpio.h" +#include /****************************************************************************** * aux channel util functions -- cgit v1.2.3 From e0996aea4c349ba302b63203b7d5cab6034dbdca Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Tue, 10 Jul 2012 12:20:17 +1000 Subject: drm/nouveau/gpio: port gpio to subdev interfaces v2: Ben Skeggs - rebase on top of v3.6-rc6 with gpio reset patch integrated already Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/Makefile | 3 + .../gpu/drm/nouveau/core/include/subdev/bios/dcb.h | 19 ++ .../drm/nouveau/core/include/subdev/bios/gpio.h | 26 ++ drivers/gpu/drm/nouveau/core/include/subdev/gpio.h | 113 ++++--- drivers/gpu/drm/nouveau/core/os.h | 1 + drivers/gpu/drm/nouveau/core/subdev/bios/dcb.c | 135 +++++++++ drivers/gpu/drm/nouveau/core/subdev/bios/gpio.c | 114 +++++++ 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 | 9 + drivers/gpu/drm/nouveau/core/subdev/device/nve0.c | 3 + drivers/gpu/drm/nouveau/core/subdev/gpio/base.c | 329 +++++++-------------- drivers/gpu/drm/nouveau/core/subdev/gpio/nv10.c | 116 +++++--- drivers/gpu/drm/nouveau/core/subdev/gpio/nv50.c | 179 ++++++----- drivers/gpu/drm/nouveau/core/subdev/gpio/nvd0.c | 104 +++++++ drivers/gpu/drm/nouveau/core/subdev/i2c/base.c | 2 +- drivers/gpu/drm/nouveau/nouveau_bios.c | 17 +- drivers/gpu/drm/nouveau/nouveau_bios.h | 15 +- drivers/gpu/drm/nouveau/nouveau_compat.c | 80 +++++ drivers/gpu/drm/nouveau/nouveau_compat.h | 11 + drivers/gpu/drm/nouveau/nouveau_connector.c | 3 +- drivers/gpu/drm/nouveau/nouveau_display.c | 3 +- drivers/gpu/drm/nouveau/nouveau_dp.c | 1 - drivers/gpu/drm/nouveau/nouveau_drv.h | 27 -- drivers/gpu/drm/nouveau/nouveau_mxm.c | 4 +- drivers/gpu/drm/nouveau/nouveau_pm.c | 17 +- drivers/gpu/drm/nouveau/nouveau_state.c | 42 +-- drivers/gpu/drm/nouveau/nouveau_volt.c | 5 +- drivers/gpu/drm/nouveau/nv04_dac.c | 3 +- drivers/gpu/drm/nouveau/nv17_tv.c | 3 +- 33 files changed, 933 insertions(+), 503 deletions(-) create mode 100644 drivers/gpu/drm/nouveau/core/include/subdev/bios/dcb.h create mode 100644 drivers/gpu/drm/nouveau/core/include/subdev/bios/gpio.h create mode 100644 drivers/gpu/drm/nouveau/core/subdev/bios/dcb.c create mode 100644 drivers/gpu/drm/nouveau/core/subdev/bios/gpio.c create mode 100644 drivers/gpu/drm/nouveau/core/subdev/gpio/nvd0.c (limited to 'drivers/gpu/drm/nouveau/nouveau_dp.c') diff --git a/drivers/gpu/drm/nouveau/Makefile b/drivers/gpu/drm/nouveau/Makefile index d10ec93c5ad8..414b2e8b8105 100644 --- a/drivers/gpu/drm/nouveau/Makefile +++ b/drivers/gpu/drm/nouveau/Makefile @@ -20,6 +20,8 @@ nouveau-y += core/core/subdev.o nouveau-y += core/subdev/bios/base.o 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/device/base.o nouveau-y += core/subdev/device/nv04.o nouveau-y += core/subdev/device/nv10.o @@ -41,6 +43,7 @@ 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 +nouveau-y += core/subdev/gpio/nvd0.o nouveau-y += core/subdev/i2c/base.o nouveau-y += core/subdev/instmem/nv04.o nouveau-y += core/subdev/instmem/nv50.o diff --git a/drivers/gpu/drm/nouveau/core/include/subdev/bios/dcb.h b/drivers/gpu/drm/nouveau/core/include/subdev/bios/dcb.h new file mode 100644 index 000000000000..7000dcf2ae95 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/include/subdev/bios/dcb.h @@ -0,0 +1,19 @@ +#ifndef __NVBIOS_DCB_H__ +#define __NVBIOS_DCB_H__ + +enum dcb_output_type { + DCB_OUTPUT_ANALOG = 0x0, + DCB_OUTPUT_TV = 0x1, + DCB_OUTPUT_TMDS = 0x2, + DCB_OUTPUT_LVDS = 0x3, + DCB_OUTPUT_DP = 0x4, + DCB_OUTPUT_EOL = 0xe, + DCB_OUTPUT_UNUSED = 0xf, +}; + +u16 dcb_table(struct nouveau_bios *, u8 *ver, u8 *hdr, u8 *ent, u8 *len); +u16 dcb_outp(struct nouveau_bios *, u8 idx, u8 *ver, u8 *len); +int dcb_outp_foreach(struct nouveau_bios *, void *data, int (*exec) + (struct nouveau_bios *, void *, int index, u16 entry)); + +#endif diff --git a/drivers/gpu/drm/nouveau/core/include/subdev/bios/gpio.h b/drivers/gpu/drm/nouveau/core/include/subdev/bios/gpio.h new file mode 100644 index 000000000000..e9789cf411c5 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/include/subdev/bios/gpio.h @@ -0,0 +1,26 @@ +#ifndef __NVBIOS_GPIO_H__ +#define __NVBIOS_GPIO_H__ + +struct nouveau_bios; + +enum dcb_gpio_func_name { + DCB_GPIO_PANEL_POWER = 0x01, + DCB_GPIO_TVDAC0 = 0x0c, + DCB_GPIO_TVDAC1 = 0x2d, + DCB_GPIO_PWM_FAN = 0x09, + DCB_GPIO_FAN_SENSE = 0x3d, + DCB_GPIO_UNUSED = 0xff +}; + +struct dcb_gpio_func { + u8 func; + u8 line; + u8 log[2]; +}; + +u16 dcb_gpio_table(struct nouveau_bios *); +u16 dcb_gpio_entry(struct nouveau_bios *, int idx, int ent, u8 *ver); +int dcb_gpio_parse(struct nouveau_bios *, int idx, u8 func, u8 line, + struct dcb_gpio_func *); + +#endif diff --git a/drivers/gpu/drm/nouveau/core/include/subdev/gpio.h b/drivers/gpu/drm/nouveau/core/include/subdev/gpio.h index 64c5cb077ace..9ea2b12cc15d 100644 --- a/drivers/gpu/drm/nouveau/core/include/subdev/gpio.h +++ b/drivers/gpu/drm/nouveau/core/include/subdev/gpio.h @@ -1,71 +1,64 @@ -/* - * Copyright 2011 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. - */ - #ifndef __NOUVEAU_GPIO_H__ #define __NOUVEAU_GPIO_H__ -struct gpio_func { - u8 func; - u8 line; - u8 log[2]; -}; +#include +#include -/* nouveau_gpio.c */ -int nouveau_gpio_create(struct drm_device *); -void nouveau_gpio_destroy(struct drm_device *); -int nouveau_gpio_init(struct drm_device *); -void nouveau_gpio_fini(struct drm_device *); -void nouveau_gpio_reset(struct drm_device *); -int nouveau_gpio_drive(struct drm_device *, int idx, int line, - int dir, int out); -int nouveau_gpio_sense(struct drm_device *, int idx, int line); -int nouveau_gpio_find(struct drm_device *, int idx, u8 tag, u8 line, - struct gpio_func *); -int nouveau_gpio_set(struct drm_device *, int idx, u8 tag, u8 line, int state); -int nouveau_gpio_get(struct drm_device *, int idx, u8 tag, u8 line); -int nouveau_gpio_irq(struct drm_device *, int idx, u8 tag, u8 line, bool on); -void nouveau_gpio_isr(struct drm_device *, int idx, u32 mask); -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); +#include +#include -static inline bool -nouveau_gpio_func_valid(struct drm_device *dev, u8 tag) -{ - struct gpio_func func; - return (nouveau_gpio_find(dev, 0, tag, 0xff, &func)) == 0; -} +struct nouveau_gpio { + struct nouveau_subdev base; -static inline int -nouveau_gpio_func_set(struct drm_device *dev, u8 tag, int state) -{ - return nouveau_gpio_set(dev, 0, tag, 0xff, state); -} + /* hardware interfaces */ + void (*reset)(struct nouveau_gpio *); + int (*drive)(struct nouveau_gpio *, int line, int dir, int out); + int (*sense)(struct nouveau_gpio *, int line); + void (*irq_enable)(struct nouveau_gpio *, int line, bool); + + /* software interfaces */ + int (*find)(struct nouveau_gpio *, int idx, u8 tag, u8 line, + struct dcb_gpio_func *); + int (*set)(struct nouveau_gpio *, int idx, u8 tag, u8 line, int state); + int (*get)(struct nouveau_gpio *, int idx, u8 tag, u8 line); + int (*irq)(struct nouveau_gpio *, int idx, u8 tag, u8 line, bool on); -static inline int -nouveau_gpio_func_get(struct drm_device *dev, u8 tag) + /* interrupt handling */ + struct list_head isr; + spinlock_t lock; + + void (*isr_run)(struct nouveau_gpio *, int idx, u32 mask); + int (*isr_add)(struct nouveau_gpio *, int idx, u8 tag, u8 line, + void (*)(void *, int state), void *data); + void (*isr_del)(struct nouveau_gpio *, int idx, u8 tag, u8 line, + void (*)(void *, int state), void *data); +}; + +static inline struct nouveau_gpio * +nouveau_gpio(void *obj) { - return nouveau_gpio_get(dev, 0, tag, 0xff); + return (void *)nv_device(obj)->subdev[NVDEV_SUBDEV_GPIO]; } +#define nouveau_gpio_create(p,e,o,d) \ + nouveau_gpio_create_((p), (e), (o), sizeof(**d), (void **)d) +#define nouveau_gpio_destroy(p) \ + nouveau_subdev_destroy(&(p)->base) +#define nouveau_gpio_fini(p,s) \ + nouveau_subdev_fini(&(p)->base, (s)) + +int nouveau_gpio_create_(struct nouveau_object *, struct nouveau_object *, + struct nouveau_oclass *, int, void **); +int nouveau_gpio_init(struct nouveau_gpio *); + +extern struct nouveau_oclass nv10_gpio_oclass; +extern struct nouveau_oclass nv50_gpio_oclass; +extern struct nouveau_oclass nvd0_gpio_oclass; + +void nv50_gpio_dtor(struct nouveau_object *); +int nv50_gpio_init(struct nouveau_object *); +int nv50_gpio_fini(struct nouveau_object *, bool); +void nv50_gpio_intr(struct nouveau_subdev *); +void nv50_gpio_irq_enable(struct nouveau_gpio *, int line, bool); + #endif diff --git a/drivers/gpu/drm/nouveau/core/os.h b/drivers/gpu/drm/nouveau/core/os.h index 76bdb0efc1e4..661b037729ea 100644 --- a/drivers/gpu/drm/nouveau/core/os.h +++ b/drivers/gpu/drm/nouveau/core/os.h @@ -15,6 +15,7 @@ #include #include #include +#include #include diff --git a/drivers/gpu/drm/nouveau/core/subdev/bios/dcb.c b/drivers/gpu/drm/nouveau/core/subdev/bios/dcb.c new file mode 100644 index 000000000000..9ed6e728a94c --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/subdev/bios/dcb.c @@ -0,0 +1,135 @@ +/* + * 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 "core/device.h" + +#include "subdev/bios.h" +#include "subdev/bios/dcb.h" + +u16 +dcb_table(struct nouveau_bios *bios, u8 *ver, u8 *hdr, u8 *cnt, u8 *len) +{ + struct nouveau_device *device = nv_device(bios); + u16 dcb = 0x0000; + + if (device->card_type > NV_04) + dcb = nv_ro16(bios, 0x36); + if (!dcb) { + nv_warn(bios, "DCB table not found\n"); + return dcb; + } + + *ver = nv_ro08(bios, dcb); + + if (*ver >= 0x41) { + nv_warn(bios, "DCB *ver 0x%02x unknown\n", *ver); + return 0x0000; + } else + if (*ver >= 0x30) { + if (nv_ro32(bios, dcb + 6) == 0x4edcbdcb) { + *hdr = nv_ro08(bios, dcb + 1); + *cnt = nv_ro08(bios, dcb + 2); + *len = nv_ro08(bios, dcb + 3); + return dcb; + } + } else + if (*ver >= 0x20) { + if (nv_ro32(bios, dcb + 4) == 0x4edcbdcb) { + u16 i2c = nv_ro16(bios, dcb + 2); + *hdr = 8; + *cnt = (i2c - dcb) / 8; + *len = 8; + return dcb; + } + } else + if (*ver >= 0x15) { + if (!nv_strncmp(bios, dcb - 7, 7, "DEV_REC")) { + u16 i2c = nv_ro16(bios, dcb + 2); + *hdr = 4; + *cnt = (i2c - dcb) / 10; + *len = 10; + return dcb; + } + } else { + /* + * v1.4 (some NV15/16, NV11+) seems the same as v1.5, but + * always has the same single (crt) entry, even when tv-out + * present, so the conclusion is this version cannot really + * be used. + * + * v1.2 tables (some NV6/10, and NV15+) normally have the + * same 5 entries, which are not specific to the card and so + * no use. + * + * v1.2 does have an I2C table that read_dcb_i2c_table can + * handle, but cards exist (nv11 in #14821) with a bad i2c + * table pointer, so use the indices parsed in + * parse_bmp_structure. + * + * v1.1 (NV5+, maybe some NV4) is entirely unhelpful + */ + nv_warn(bios, "DCB contains no useful data\n"); + return 0x0000; + } + + nv_warn(bios, "DCB header validation failed\n"); + return 0x0000; +} + +u16 +dcb_outp(struct nouveau_bios *bios, u8 idx, u8 *ver, u8 *len) +{ + u8 hdr, cnt; + u16 dcb = dcb_table(bios, ver, &hdr, &cnt, len); + if (dcb && idx < cnt) + return dcb + hdr + (idx * *len); + return 0x0000; +} + +int +dcb_outp_foreach(struct nouveau_bios *bios, void *data, + int (*exec)(struct nouveau_bios *, void *, int, u16)) +{ + int ret, idx = -1; + u8 ver, len; + u16 outp; + + while ((outp = dcb_outp(bios, ++idx, &ver, &len))) { + if (nv_ro32(bios, outp) == 0x00000000) + break; /* seen on an NV11 with DCB v1.5 */ + if (nv_ro32(bios, outp) == 0xffffffff) + break; /* seen on an NV17 with DCB v2.0 */ + + if (nv_ro08(bios, outp) == DCB_OUTPUT_UNUSED) + continue; + if (nv_ro08(bios, outp) == DCB_OUTPUT_EOL) + break; + + ret = exec(bios, data, idx, outp); + if (ret) + return ret; + } + + return 0; +} diff --git a/drivers/gpu/drm/nouveau/core/subdev/bios/gpio.c b/drivers/gpu/drm/nouveau/core/subdev/bios/gpio.c new file mode 100644 index 000000000000..718267d84c7b --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/subdev/bios/gpio.c @@ -0,0 +1,114 @@ +/* + * 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 + +u16 +dcb_gpio_table(struct nouveau_bios *bios) +{ + u8 ver, hdr, cnt, len; + u16 dcb = dcb_table(bios, &ver, &hdr, &cnt, &len); + if (dcb) { + if (ver >= 0x30 && hdr >= 0x0c) + return nv_ro16(bios, dcb + 0x0a); + if (ver >= 0x22 && nv_ro08(bios, dcb - 1) >= 0x13) + return nv_ro16(bios, dcb - 0x0f); + } + return 0x0000; +} + +u16 +dcb_gpio_entry(struct nouveau_bios *bios, int idx, int ent, u8 *ver) +{ + u16 gpio = dcb_gpio_table(bios); + if (gpio) { + *ver = nv_ro08(bios, gpio); + if (*ver < 0x30 && ent < nv_ro08(bios, gpio + 2)) + return gpio + 3 + (ent * nv_ro08(bios, gpio + 1)); + else if (ent < nv_ro08(bios, gpio + 2)) + return gpio + nv_ro08(bios, gpio + 1) + + (ent * nv_ro08(bios, gpio + 3)); + } + return 0x0000; +} + +int +dcb_gpio_parse(struct nouveau_bios *bios, int idx, u8 func, u8 line, + struct dcb_gpio_func *gpio) +{ + u8 ver, hdr, cnt, len; + u16 entry; + int i = -1; + + while ((entry = dcb_gpio_entry(bios, idx, ++i, &ver))) { + if (ver < 0x40) { + u16 data = nv_ro16(bios, entry); + *gpio = (struct dcb_gpio_func) { + .line = (data & 0x001f) >> 0, + .func = (data & 0x07e0) >> 5, + .log[0] = (data & 0x1800) >> 11, + .log[1] = (data & 0x6000) >> 13, + }; + } else + if (ver < 0x41) { + u32 data = nv_ro32(bios, entry); + *gpio = (struct dcb_gpio_func) { + .line = (data & 0x0000001f) >> 0, + .func = (data & 0x0000ff00) >> 8, + .log[0] = (data & 0x18000000) >> 27, + .log[1] = (data & 0x60000000) >> 29, + }; + } else { + u32 data = nv_ro32(bios, entry + 0); + u8 data1 = nv_ro32(bios, entry + 4); + *gpio = (struct dcb_gpio_func) { + .line = (data & 0x0000003f) >> 0, + .func = (data & 0x0000ff00) >> 8, + .log[0] = (data1 & 0x30) >> 4, + .log[1] = (data1 & 0xc0) >> 6, + }; + } + + if ((line == 0xff || line == gpio->line) && + (func == 0xff || func == gpio->func)) + return 0; + } + + /* DCB 2.2, fixed TVDAC GPIO data */ + if ((entry = dcb_table(bios, &ver, &hdr, &cnt, &len)) && ver >= 0x22) { + if (func == DCB_GPIO_TVDAC0) { + *gpio = (struct dcb_gpio_func) { + .func = DCB_GPIO_TVDAC0, + .line = nv_ro08(bios, entry - 4) >> 4, + .log[0] = !!(nv_ro08(bios, entry - 5) & 2), + .log[1] = !(nv_ro08(bios, entry - 5) & 2), + }; + return 0; + } + } + + return -EINVAL; +} diff --git a/drivers/gpu/drm/nouveau/core/subdev/device/nv10.c b/drivers/gpu/drm/nouveau/core/subdev/device/nv10.c index f9e428875187..c0c40cddaa2f 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/device/nv10.c +++ b/drivers/gpu/drm/nouveau/core/subdev/device/nv10.c @@ -24,6 +24,7 @@ #include #include +#include int nv10_identify(struct nouveau_device *device) @@ -31,27 +32,35 @@ nv10_identify(struct nouveau_device *device) switch (device->chipset) { case 0x10: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; + device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; break; case 0x15: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; + device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; break; case 0x16: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; + device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; break; case 0x1a: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; + device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; break; case 0x11: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; + device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; break; case 0x17: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; + device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; break; case 0x1f: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; + device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; break; case 0x18: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; + device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_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 b5dfb7e84836..1215e3ff47fa 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/device/nv20.c +++ b/drivers/gpu/drm/nouveau/core/subdev/device/nv20.c @@ -24,6 +24,7 @@ #include #include +#include int nv20_identify(struct nouveau_device *device) @@ -31,15 +32,19 @@ nv20_identify(struct nouveau_device *device) switch (device->chipset) { case 0x20: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; + device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; break; case 0x25: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; + device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; break; case 0x28: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; + device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; break; case 0x2a: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; + device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_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 b2e50e39dc8d..43eb94e7768a 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/device/nv30.c +++ b/drivers/gpu/drm/nouveau/core/subdev/device/nv30.c @@ -24,6 +24,7 @@ #include #include +#include int nv30_identify(struct nouveau_device *device) @@ -31,18 +32,23 @@ nv30_identify(struct nouveau_device *device) switch (device->chipset) { case 0x30: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; + device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; break; case 0x35: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; + device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; break; case 0x31: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; + device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; break; case 0x36: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; + device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; break; case 0x34: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; + device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_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 4a3e3a857a06..7c10a3c68d55 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/device/nv40.c +++ b/drivers/gpu/drm/nouveau/core/subdev/device/nv40.c @@ -24,6 +24,7 @@ #include #include +#include int nv40_identify(struct nouveau_device *device) @@ -31,51 +32,67 @@ nv40_identify(struct nouveau_device *device) switch (device->chipset) { case 0x40: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; + device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; break; case 0x41: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; + device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; break; case 0x42: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; + device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; break; case 0x43: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; + device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; break; case 0x45: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; + device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; break; case 0x47: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; + device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; break; case 0x49: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; + device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; break; case 0x4b: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; + device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; break; case 0x44: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; + device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; break; case 0x46: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; + device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; break; case 0x4a: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; + device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; break; case 0x4c: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; + device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; break; case 0x4e: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; + device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; break; case 0x63: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; + device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; break; case 0x67: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; + device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; break; case 0x68: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; + device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_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 018c71157675..581dcf199884 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/device/nv50.c +++ b/drivers/gpu/drm/nouveau/core/subdev/device/nv50.c @@ -24,6 +24,7 @@ #include #include +#include int nv50_identify(struct nouveau_device *device) @@ -31,45 +32,59 @@ nv50_identify(struct nouveau_device *device) switch (device->chipset) { case 0x50: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; + device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; break; case 0x84: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; + device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; break; case 0x86: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; + device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; break; case 0x92: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; + device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; break; case 0x94: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; + device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; break; case 0x96: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; + device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; break; case 0x98: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; + device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; break; case 0xa0: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; + device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; break; case 0xaa: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; + device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; break; case 0xac: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; + device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; break; case 0xa3: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; + device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; break; case 0xa5: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; + device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; break; case 0xa8: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; + device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; break; case 0xaf: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; + device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_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 0e8127793c50..df31111965c4 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/device/nvc0.c +++ b/drivers/gpu/drm/nouveau/core/subdev/device/nvc0.c @@ -24,6 +24,7 @@ #include #include +#include int nvc0_identify(struct nouveau_device *device) @@ -31,27 +32,35 @@ nvc0_identify(struct nouveau_device *device) switch (device->chipset) { case 0xc0: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; + device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; break; case 0xc4: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; + device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; break; case 0xc3: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; + device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; break; case 0xce: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; + device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; break; case 0xcf: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; + device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; break; case 0xc1: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; + device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; break; case 0xc8: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; + device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; break; case 0xd9: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; + device->oclass[NVDEV_SUBDEV_GPIO ] = &nvd0_gpio_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 15cae4364e9a..d321cb4ec138 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/device/nve0.c +++ b/drivers/gpu/drm/nouveau/core/subdev/device/nve0.c @@ -24,6 +24,7 @@ #include #include +#include int nve0_identify(struct nouveau_device *device) @@ -31,9 +32,11 @@ nve0_identify(struct nouveau_device *device) switch (device->chipset) { case 0xe4: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; + device->oclass[NVDEV_SUBDEV_GPIO ] = &nvd0_gpio_oclass; break; case 0xe7: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; + device->oclass[NVDEV_SUBDEV_GPIO ] = &nvd0_gpio_oclass; break; default: nv_fatal(device, "unknown Kepler chipset\n"); diff --git a/drivers/gpu/drm/nouveau/core/subdev/gpio/base.c b/drivers/gpu/drm/nouveau/core/subdev/gpio/base.c index 2c48309b0e19..abb135f74953 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/gpio/base.c +++ b/drivers/gpu/drm/nouveau/core/subdev/gpio/base.c @@ -22,114 +22,37 @@ * Authors: Ben Skeggs */ -#include "drmP.h" -#include "nouveau_drv.h" -#include #include +#include +#include -static u8 * -dcb_gpio_table(struct drm_device *dev) +static int +nouveau_gpio_drive(struct nouveau_gpio *gpio, + int idx, int line, int dir, int out) { - u8 *dcb = dcb_table(dev); - if (dcb) { - if (dcb[0] >= 0x30 && dcb[1] >= 0x0c) - return ROMPTR(dev, dcb[0x0a]); - if (dcb[0] >= 0x22 && dcb[-1] >= 0x13) - return ROMPTR(dev, dcb[-15]); - } - return NULL; -} - -static u8 * -dcb_gpio_entry(struct drm_device *dev, int idx, int ent, u8 *version) -{ - u8 *table = dcb_gpio_table(dev); - if (table) { - *version = table[0]; - if (*version < 0x30 && ent < table[2]) - return table + 3 + (ent * table[1]); - else if (ent < table[2]) - return table + table[1] + (ent * table[3]); - } - return NULL; + return gpio->drive ? gpio->drive(gpio, line, dir, out) : -ENODEV; } -int -nouveau_gpio_drive(struct drm_device *dev, int idx, int line, int dir, int out) +static int +nouveau_gpio_sense(struct nouveau_gpio *gpio, int idx, int line) { - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_gpio_engine *pgpio = &dev_priv->engine.gpio; - - return pgpio->drive ? pgpio->drive(dev, line, dir, out) : -ENODEV; + return gpio->sense ? gpio->sense(gpio, line) : -ENODEV; } -int -nouveau_gpio_sense(struct drm_device *dev, int idx, int line) +static int +nouveau_gpio_find(struct nouveau_gpio *gpio, int idx, u8 tag, u8 line, + struct dcb_gpio_func *func) { - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_gpio_engine *pgpio = &dev_priv->engine.gpio; - - return pgpio->sense ? pgpio->sense(dev, line) : -ENODEV; -} - -int -nouveau_gpio_find(struct drm_device *dev, int idx, u8 func, u8 line, - struct gpio_func *gpio) -{ - u8 *table, *entry, version; - int i = -1; - - if (line == 0xff && func == 0xff) + if (line == 0xff && tag == 0xff) return -EINVAL; - while ((entry = dcb_gpio_entry(dev, idx, ++i, &version))) { - if (version < 0x40) { - u16 data = ROM16(entry[0]); - *gpio = (struct gpio_func) { - .line = (data & 0x001f) >> 0, - .func = (data & 0x07e0) >> 5, - .log[0] = (data & 0x1800) >> 11, - .log[1] = (data & 0x6000) >> 13, - }; - } else - if (version < 0x41) { - *gpio = (struct gpio_func) { - .line = entry[0] & 0x1f, - .func = entry[1], - .log[0] = (entry[3] & 0x18) >> 3, - .log[1] = (entry[3] & 0x60) >> 5, - }; - } else { - *gpio = (struct gpio_func) { - .line = entry[0] & 0x3f, - .func = entry[1], - .log[0] = (entry[4] & 0x30) >> 4, - .log[1] = (entry[4] & 0xc0) >> 6, - }; - } - - if ((line == 0xff || line == gpio->line) && - (func == 0xff || func == gpio->func)) - return 0; - } - - /* DCB 2.2, fixed TVDAC GPIO data */ - if ((table = dcb_table(dev)) && table[0] >= 0x22) { - if (func == DCB_GPIO_TVDAC0) { - *gpio = (struct gpio_func) { - .func = DCB_GPIO_TVDAC0, - .line = table[-4] >> 4, - .log[0] = !!(table[-5] & 2), - .log[1] = !(table[-5] & 2), - }; - return 0; - } - } + if (!dcb_gpio_parse(nouveau_bios(gpio), idx, tag, line, func)) + return 0; /* Apple iMac G4 NV18 */ - if (nv_match_device(dev, 0x0189, 0x10de, 0x0010)) { - if (func == DCB_GPIO_TVDAC0) { - *gpio = (struct gpio_func) { + if (nv_device_match(nv_object(gpio), 0x0189, 0x10de, 0x0010)) { + if (tag == DCB_GPIO_TVDAC0) { + *func = (struct dcb_gpio_func) { .func = DCB_GPIO_TVDAC0, .line = 4, .log[0] = 0, @@ -142,50 +65,48 @@ nouveau_gpio_find(struct drm_device *dev, int idx, u8 func, u8 line, return -EINVAL; } -int -nouveau_gpio_set(struct drm_device *dev, int idx, u8 tag, u8 line, int state) +static int +nouveau_gpio_set(struct nouveau_gpio *gpio, int idx, u8 tag, u8 line, int state) { - struct gpio_func gpio; + struct dcb_gpio_func func; int ret; - ret = nouveau_gpio_find(dev, idx, tag, line, &gpio); + ret = nouveau_gpio_find(gpio, idx, tag, line, &func); if (ret == 0) { - int dir = !!(gpio.log[state] & 0x02); - int out = !!(gpio.log[state] & 0x01); - ret = nouveau_gpio_drive(dev, idx, gpio.line, dir, out); + int dir = !!(func.log[state] & 0x02); + int out = !!(func.log[state] & 0x01); + ret = nouveau_gpio_drive(gpio, idx, func.line, dir, out); } return ret; } -int -nouveau_gpio_get(struct drm_device *dev, int idx, u8 tag, u8 line) +static int +nouveau_gpio_get(struct nouveau_gpio *gpio, int idx, u8 tag, u8 line) { - struct gpio_func gpio; + struct dcb_gpio_func func; int ret; - ret = nouveau_gpio_find(dev, idx, tag, line, &gpio); + ret = nouveau_gpio_find(gpio, idx, tag, line, &func); if (ret == 0) { - ret = nouveau_gpio_sense(dev, idx, gpio.line); + ret = nouveau_gpio_sense(gpio, idx, func.line); if (ret >= 0) - ret = (ret == (gpio.log[1] & 1)); + ret = (ret == (func.log[1] & 1)); } return ret; } -int -nouveau_gpio_irq(struct drm_device *dev, int idx, u8 tag, u8 line, bool on) +static int +nouveau_gpio_irq(struct nouveau_gpio *gpio, int idx, u8 tag, u8 line, bool on) { - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_gpio_engine *pgpio = &dev_priv->engine.gpio; - struct gpio_func gpio; + struct dcb_gpio_func func; int ret; - ret = nouveau_gpio_find(dev, idx, tag, line, &gpio); + ret = nouveau_gpio_find(gpio, idx, tag, line, &func); if (ret == 0) { - if (idx == 0 && pgpio->irq_enable) - pgpio->irq_enable(dev, gpio.line, on); + if (idx == 0 && gpio->irq_enable) + gpio->irq_enable(gpio, func.line, on); else ret = -ENODEV; } @@ -194,11 +115,11 @@ nouveau_gpio_irq(struct drm_device *dev, int idx, u8 tag, u8 line, bool on) } struct gpio_isr { - struct drm_device *dev; + struct nouveau_gpio *gpio; struct list_head head; struct work_struct work; int idx; - struct gpio_func func; + struct dcb_gpio_func func; void (*handler)(void *, int); void *data; bool inhibit; @@ -208,33 +129,30 @@ static void nouveau_gpio_isr_bh(struct work_struct *work) { struct gpio_isr *isr = container_of(work, struct gpio_isr, work); - struct drm_device *dev = isr->dev; - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_gpio_engine *pgpio = &dev_priv->engine.gpio; + struct nouveau_gpio *gpio = isr->gpio; unsigned long flags; int state; - state = nouveau_gpio_get(dev, isr->idx, isr->func.func, isr->func.line); + state = nouveau_gpio_get(gpio, isr->idx, isr->func.func, + isr->func.line); if (state >= 0) isr->handler(isr->data, state); - spin_lock_irqsave(&pgpio->lock, flags); + spin_lock_irqsave(&gpio->lock, flags); isr->inhibit = false; - spin_unlock_irqrestore(&pgpio->lock, flags); + spin_unlock_irqrestore(&gpio->lock, flags); } -void -nouveau_gpio_isr(struct drm_device *dev, int idx, u32 line_mask) +static void +nouveau_gpio_isr_run(struct nouveau_gpio *gpio, int idx, u32 line_mask) { - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_gpio_engine *pgpio = &dev_priv->engine.gpio; struct gpio_isr *isr; if (idx != 0) return; - spin_lock(&pgpio->lock); - list_for_each_entry(isr, &pgpio->isr, head) { + spin_lock(&gpio->lock); + list_for_each_entry(isr, &gpio->isr, head) { if (line_mask & (1 << isr->func.line)) { if (isr->inhibit) continue; @@ -242,15 +160,13 @@ nouveau_gpio_isr(struct drm_device *dev, int idx, u32 line_mask) schedule_work(&isr->work); } } - spin_unlock(&pgpio->lock); + spin_unlock(&gpio->lock); } -int -nouveau_gpio_isr_add(struct drm_device *dev, int idx, u8 tag, u8 line, +static int +nouveau_gpio_isr_add(struct nouveau_gpio *gpio, int idx, u8 tag, u8 line, void (*handler)(void *, int), void *data) { - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_gpio_engine *pgpio = &dev_priv->engine.gpio; struct gpio_isr *isr; unsigned long flags; int ret; @@ -259,47 +175,45 @@ nouveau_gpio_isr_add(struct drm_device *dev, int idx, u8 tag, u8 line, if (!isr) return -ENOMEM; - ret = nouveau_gpio_find(dev, idx, tag, line, &isr->func); + ret = nouveau_gpio_find(gpio, idx, tag, line, &isr->func); if (ret) { kfree(isr); return ret; } INIT_WORK(&isr->work, nouveau_gpio_isr_bh); - isr->dev = dev; + isr->gpio = gpio; isr->handler = handler; isr->data = data; isr->idx = idx; - spin_lock_irqsave(&pgpio->lock, flags); - list_add(&isr->head, &pgpio->isr); - spin_unlock_irqrestore(&pgpio->lock, flags); + spin_lock_irqsave(&gpio->lock, flags); + list_add(&isr->head, &gpio->isr); + spin_unlock_irqrestore(&gpio->lock, flags); return 0; } -void -nouveau_gpio_isr_del(struct drm_device *dev, int idx, u8 tag, u8 line, +static void +nouveau_gpio_isr_del(struct nouveau_gpio *gpio, int idx, u8 tag, u8 line, void (*handler)(void *, int), void *data) { - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_gpio_engine *pgpio = &dev_priv->engine.gpio; struct gpio_isr *isr, *tmp; - struct gpio_func func; + struct dcb_gpio_func func; unsigned long flags; LIST_HEAD(tofree); int ret; - ret = nouveau_gpio_find(dev, idx, tag, line, &func); + ret = nouveau_gpio_find(gpio, idx, tag, line, &func); if (ret == 0) { - spin_lock_irqsave(&pgpio->lock, flags); - list_for_each_entry_safe(isr, tmp, &pgpio->isr, head) { + spin_lock_irqsave(&gpio->lock, flags); + list_for_each_entry_safe(isr, tmp, &gpio->isr, head) { if (memcmp(&isr->func, &func, sizeof(func)) || isr->idx != idx || isr->handler != handler || isr->data != data) continue; - list_move(&isr->head, &tofree); + list_move_tail(&isr->head, &tofree); } - spin_unlock_irqrestore(&pgpio->lock, flags); + spin_unlock_irqrestore(&gpio->lock, flags); list_for_each_entry_safe(isr, tmp, &tofree, head) { flush_work_sync(&isr->work); @@ -309,92 +223,49 @@ nouveau_gpio_isr_del(struct drm_device *dev, int idx, u8 tag, u8 line, } int -nouveau_gpio_create(struct drm_device *dev) +nouveau_gpio_create_(struct nouveau_object *parent, + struct nouveau_object *engine, + struct nouveau_oclass *oclass, int length, void **pobject) { - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_gpio_engine *pgpio = &dev_priv->engine.gpio; + struct nouveau_gpio *gpio; + int ret; - INIT_LIST_HEAD(&pgpio->isr); - spin_lock_init(&pgpio->lock); + ret = nouveau_subdev_create_(parent, engine, oclass, 0, "GPIO", "gpio", + length, pobject); + gpio = *pobject; + if (ret) + return ret; - return nouveau_gpio_init(dev); + gpio->find = nouveau_gpio_find; + gpio->set = nouveau_gpio_set; + gpio->get = nouveau_gpio_get; + gpio->irq = nouveau_gpio_irq; + gpio->isr_run = nouveau_gpio_isr_run; + gpio->isr_add = nouveau_gpio_isr_add; + gpio->isr_del = nouveau_gpio_isr_del; + INIT_LIST_HEAD(&gpio->isr); + spin_lock_init(&gpio->lock); + return 0; } -void -nouveau_gpio_destroy(struct drm_device *dev) -{ - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_gpio_engine *pgpio = &dev_priv->engine.gpio; - - nouveau_gpio_fini(dev); - BUG_ON(!list_empty(&pgpio->isr)); -} +static struct dmi_system_id gpio_reset_ids[] = { + { + .ident = "Apple Macbook 10,1", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."), + DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro10,1"), + } + }, + { } +}; int -nouveau_gpio_init(struct drm_device *dev) +nouveau_gpio_init(struct nouveau_gpio *gpio) { - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_gpio_engine *pgpio = &dev_priv->engine.gpio; - int ret = 0; - - if (pgpio->init) - ret = pgpio->init(dev); - - return ret; -} - -void -nouveau_gpio_fini(struct drm_device *dev) -{ - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_gpio_engine *pgpio = &dev_priv->engine.gpio; - - if (pgpio->fini) - pgpio->fini(dev); -} - -void -nouveau_gpio_reset(struct drm_device *dev) -{ - struct drm_nouveau_private *dev_priv = dev->dev_private; - u8 *entry, version; - int ent = -1; - - while ((entry = dcb_gpio_entry(dev, 0, ++ent, &version))) { - u8 func = 0xff, line, defs, unk0, unk1; - if (version >= 0x41) { - defs = !!(entry[0] & 0x80); - line = entry[0] & 0x3f; - func = entry[1]; - unk0 = entry[2]; - unk1 = entry[3] & 0x1f; - } else - if (version >= 0x40) { - line = entry[0] & 0x1f; - func = entry[1]; - defs = !!(entry[3] & 0x01); - unk0 = !!(entry[3] & 0x02); - unk1 = !!(entry[3] & 0x04); - } else { - break; - } - - if (func == 0xff) - continue; - - nouveau_gpio_func_set(dev, func, defs); - - if (dev_priv->card_type >= NV_D0) { - nv_mask(dev, 0x00d610 + (line * 4), 0xff, unk0); - if (unk1--) - nv_mask(dev, 0x00d740 + (unk1 * 4), 0xff, line); - } else - if (dev_priv->card_type >= NV_50) { - static const u32 regs[] = { 0xe100, 0xe28c }; - u32 val = (unk1 << 16) | unk0; - u32 reg = regs[line >> 4]; line &= 0x0f; - - nv_mask(dev, reg, 0x00010001 << line, val << line); - } + int ret = nouveau_subdev_init(&gpio->base); + if (ret == 0 && gpio->reset) { + if (dmi_check_system(gpio_reset_ids)) + gpio->reset(gpio); } + return ret; } diff --git a/drivers/gpu/drm/nouveau/core/subdev/gpio/nv10.c b/drivers/gpu/drm/nouveau/core/subdev/gpio/nv10.c index 42e600f68f2e..168d16a9a8e9 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/gpio/nv10.c +++ b/drivers/gpu/drm/nouveau/core/subdev/gpio/nv10.c @@ -24,100 +24,146 @@ * */ -#include "drmP.h" -#include "nouveau_drv.h" -#include "nouveau_hw.h" #include -int -nv10_gpio_sense(struct drm_device *dev, int line) +struct nv10_gpio_priv { + struct nouveau_gpio base; +}; + +static int +nv10_gpio_sense(struct nouveau_gpio *gpio, int line) { if (line < 2) { line = line * 16; - line = NVReadCRTC(dev, 0, NV_PCRTC_GPIO) >> line; + line = nv_rd32(gpio, 0x600818) >> line; return !!(line & 0x0100); } else if (line < 10) { line = (line - 2) * 4; - line = NVReadCRTC(dev, 0, NV_PCRTC_GPIO_EXT) >> line; + line = nv_rd32(gpio, 0x60081c) >> line; return !!(line & 0x04); } else if (line < 14) { line = (line - 10) * 4; - line = NVReadCRTC(dev, 0, NV_PCRTC_850) >> line; + line = nv_rd32(gpio, 0x600850) >> line; return !!(line & 0x04); } return -EINVAL; } -int -nv10_gpio_drive(struct drm_device *dev, int line, int dir, int out) +static int +nv10_gpio_drive(struct nouveau_gpio *gpio, int line, int dir, int out) { u32 reg, mask, data; if (line < 2) { line = line * 16; - reg = NV_PCRTC_GPIO; + reg = 0x600818; mask = 0x00000011; data = (dir << 4) | out; } else if (line < 10) { line = (line - 2) * 4; - reg = NV_PCRTC_GPIO_EXT; + reg = 0x60081c; mask = 0x00000003; data = (dir << 1) | out; } else if (line < 14) { line = (line - 10) * 4; - reg = NV_PCRTC_850; + reg = 0x600850; mask = 0x00000003; data = (dir << 1) | out; } else { return -EINVAL; } - mask = NVReadCRTC(dev, 0, reg) & ~(mask << line); - NVWriteCRTC(dev, 0, reg, mask | (data << line)); + nv_mask(gpio, reg, mask << line, data << line); return 0; } -void -nv10_gpio_irq_enable(struct drm_device *dev, int line, bool on) +static void +nv10_gpio_irq_enable(struct nouveau_gpio *gpio, int line, bool on) { u32 mask = 0x00010001 << line; - nv_wr32(dev, 0x001104, mask); - nv_mask(dev, 0x001144, mask, on ? mask : 0); + nv_wr32(gpio, 0x001104, mask); + nv_mask(gpio, 0x001144, mask, on ? mask : 0); } static void -nv10_gpio_isr(struct drm_device *dev) +nv10_gpio_intr(struct nouveau_subdev *subdev) { - u32 intr = nv_rd32(dev, 0x1104); + struct nv10_gpio_priv *priv = (void *)subdev; + u32 intr = nv_rd32(priv, 0x001104); u32 hi = (intr & 0x0000ffff) >> 0; u32 lo = (intr & 0xffff0000) >> 16; - nouveau_gpio_isr(dev, 0, hi | lo); + priv->base.isr_run(&priv->base, 0, hi | lo); - nv_wr32(dev, 0x001104, intr); + nv_wr32(priv, 0x001104, intr); } -int -nv10_gpio_init(struct drm_device *dev) +static int +nv10_gpio_ctor(struct nouveau_object *parent, struct nouveau_object *engine, + struct nouveau_oclass *oclass, void *data, u32 size, + struct nouveau_object **pobject) { - nv_wr32(dev, 0x001140, 0x00000000); - nv_wr32(dev, 0x001100, 0xffffffff); - nv_wr32(dev, 0x001144, 0x00000000); - nv_wr32(dev, 0x001104, 0xffffffff); - nouveau_irq_register(dev, 28, nv10_gpio_isr); /* PBUS */ + struct nv10_gpio_priv *priv; + int ret; + + ret = nouveau_gpio_create(parent, engine, oclass, &priv); + *pobject = nv_object(priv); + if (ret) + return ret; + + priv->base.drive = nv10_gpio_drive; + priv->base.sense = nv10_gpio_sense; + priv->base.irq_enable = nv10_gpio_irq_enable; + nv_subdev(priv)->intr = nv10_gpio_intr; return 0; } -void -nv10_gpio_fini(struct drm_device *dev) +static void +nv10_gpio_dtor(struct nouveau_object *object) { - nv_wr32(dev, 0x001140, 0x00000000); - nv_wr32(dev, 0x001144, 0x00000000); - nouveau_irq_unregister(dev, 28); + struct nv10_gpio_priv *priv = (void *)object; + nouveau_gpio_destroy(&priv->base); } + +static int +nv10_gpio_init(struct nouveau_object *object) +{ + struct nv10_gpio_priv *priv = (void *)object; + int ret; + + ret = nouveau_gpio_init(&priv->base); + if (ret) + return ret; + + nv_wr32(priv, 0x001140, 0x00000000); + nv_wr32(priv, 0x001100, 0xffffffff); + nv_wr32(priv, 0x001144, 0x00000000); + nv_wr32(priv, 0x001104, 0xffffffff); + return 0; +} + +static int +nv10_gpio_fini(struct nouveau_object *object, bool suspend) +{ + struct nv10_gpio_priv *priv = (void *)object; + nv_wr32(priv, 0x001140, 0x00000000); + nv_wr32(priv, 0x001144, 0x00000000); + return nouveau_gpio_fini(&priv->base, suspend); +} + +struct nouveau_oclass +nv10_gpio_oclass = { + .handle = NV_SUBDEV(GPIO, 0x10), + .ofuncs = &(struct nouveau_ofuncs) { + .ctor = nv10_gpio_ctor, + .dtor = nv10_gpio_dtor, + .init = nv10_gpio_init, + .fini = nv10_gpio_fini, + }, +}; diff --git a/drivers/gpu/drm/nouveau/core/subdev/gpio/nv50.c b/drivers/gpu/drm/nouveau/core/subdev/gpio/nv50.c index 48509b0a1c86..f3502c961cd9 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/gpio/nv50.c +++ b/drivers/gpu/drm/nouveau/core/subdev/gpio/nv50.c @@ -1,5 +1,5 @@ /* - * Copyright 2010 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,18 +22,45 @@ * Authors: Ben Skeggs */ -#include -#include "drmP.h" -#include "nouveau_drv.h" -#include "nouveau_hw.h" #include -#include "nv50_display.h" +struct nv50_gpio_priv { + struct nouveau_gpio base; +}; + +static void +nv50_gpio_reset(struct nouveau_gpio *gpio) +{ + struct nouveau_bios *bios = nouveau_bios(gpio); + struct nv50_gpio_priv *priv = (void *)gpio; + u16 entry; + u8 ver; + int ent = -1; + + while ((entry = dcb_gpio_entry(bios, 0, ++ent, &ver))) { + static const u32 regs[] = { 0xe100, 0xe28c }; + u32 data = nv_ro32(bios, entry); + u8 line = (data & 0x0000001f); + u8 func = (data & 0x0000ff00) >> 8; + u8 defs = !!(data & 0x01000000); + u8 unk0 = !!(data & 0x02000000); + u8 unk1 = !!(data & 0x04000000); + u32 val = (unk1 << 16) | unk0; + u32 reg = regs[line >> 4]; line &= 0x0f; + + if (func == 0xff) + continue; + + gpio->set(gpio, 0, func, line, defs); + + nv_mask(priv, reg, 0x00010001 << line, val << line); + } +} static int nv50_gpio_location(int line, u32 *reg, u32 *shift) { - const uint32_t nv50_gpio_reg[4] = { 0xe104, 0xe108, 0xe280, 0xe284 }; + const u32 nv50_gpio_reg[4] = { 0xe104, 0xe108, 0xe280, 0xe284 }; if (line >= 32) return -EINVAL; @@ -43,113 +70,125 @@ nv50_gpio_location(int line, u32 *reg, u32 *shift) return 0; } -int -nv50_gpio_drive(struct drm_device *dev, int line, int dir, int out) +static int +nv50_gpio_drive(struct nouveau_gpio *gpio, int line, int dir, int out) { u32 reg, shift; if (nv50_gpio_location(line, ®, &shift)) return -EINVAL; - nv_mask(dev, reg, 7 << shift, (((dir ^ 1) << 1) | out) << shift); + nv_mask(gpio, reg, 7 << shift, (((dir ^ 1) << 1) | out) << shift); return 0; } -int -nv50_gpio_sense(struct drm_device *dev, int line) +static int +nv50_gpio_sense(struct nouveau_gpio *gpio, int line) { u32 reg, shift; if (nv50_gpio_location(line, ®, &shift)) return -EINVAL; - return !!(nv_rd32(dev, reg) & (4 << shift)); + return !!(nv_rd32(gpio, reg) & (4 << shift)); } void -nv50_gpio_irq_enable(struct drm_device *dev, int line, bool on) +nv50_gpio_irq_enable(struct nouveau_gpio *gpio, int line, bool on) { u32 reg = line < 16 ? 0xe050 : 0xe070; u32 mask = 0x00010001 << (line & 0xf); - nv_wr32(dev, reg + 4, mask); - nv_mask(dev, reg + 0, mask, on ? mask : 0); -} - -int -nvd0_gpio_drive(struct drm_device *dev, int line, int dir, int out) -{ - u32 data = ((dir ^ 1) << 13) | (out << 12); - nv_mask(dev, 0x00d610 + (line * 4), 0x00003000, data); - nv_mask(dev, 0x00d604, 0x00000001, 0x00000001); /* update? */ - return 0; -} - -int -nvd0_gpio_sense(struct drm_device *dev, int line) -{ - return !!(nv_rd32(dev, 0x00d610 + (line * 4)) & 0x00004000); + nv_wr32(gpio, reg + 4, mask); + nv_mask(gpio, reg + 0, mask, on ? mask : 0); } -static void -nv50_gpio_isr(struct drm_device *dev) +void +nv50_gpio_intr(struct nouveau_subdev *subdev) { - struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nv50_gpio_priv *priv = (void *)subdev; u32 intr0, intr1 = 0; u32 hi, lo; - intr0 = nv_rd32(dev, 0xe054) & nv_rd32(dev, 0xe050); - if (dev_priv->chipset >= 0x90) - intr1 = nv_rd32(dev, 0xe074) & nv_rd32(dev, 0xe070); + intr0 = nv_rd32(priv, 0xe054) & nv_rd32(priv, 0xe050); + if (nv_device(priv)->chipset >= 0x90) + intr1 = nv_rd32(priv, 0xe074) & nv_rd32(priv, 0xe070); hi = (intr0 & 0x0000ffff) | (intr1 << 16); lo = (intr0 >> 16) | (intr1 & 0xffff0000); - nouveau_gpio_isr(dev, 0, hi | lo); + priv->base.isr_run(&priv->base, 0, hi | lo); - nv_wr32(dev, 0xe054, intr0); - if (dev_priv->chipset >= 0x90) - nv_wr32(dev, 0xe074, intr1); + nv_wr32(priv, 0xe054, intr0); + if (nv_device(priv)->chipset >= 0x90) + nv_wr32(priv, 0xe074, intr1); } -static struct dmi_system_id gpio_reset_ids[] = { - { - .ident = "Apple Macbook 10,1", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."), - DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro10,1"), - } - }, - { } -}; +static int +nv50_gpio_ctor(struct nouveau_object *parent, struct nouveau_object *engine, + struct nouveau_oclass *oclass, void *data, u32 size, + struct nouveau_object **pobject) +{ + struct nv50_gpio_priv *priv; + int ret; + + ret = nouveau_gpio_create(parent, engine, oclass, &priv); + *pobject = nv_object(priv); + if (ret) + return ret; + + priv->base.reset = nv50_gpio_reset; + priv->base.drive = nv50_gpio_drive; + priv->base.sense = nv50_gpio_sense; + priv->base.irq_enable = nv50_gpio_irq_enable; + nv_subdev(priv)->intr = nv50_gpio_intr; + return 0; +} + +void +nv50_gpio_dtor(struct nouveau_object *object) +{ + struct nv50_gpio_priv *priv = (void *)object; + nouveau_gpio_destroy(&priv->base); +} int -nv50_gpio_init(struct drm_device *dev) +nv50_gpio_init(struct nouveau_object *object) { - struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nv50_gpio_priv *priv = (void *)object; + int ret; - /* initialise gpios and routing to vbios defaults */ - if (dmi_check_system(gpio_reset_ids)) - nouveau_gpio_reset(dev); + ret = nouveau_gpio_init(&priv->base); + if (ret) + return ret; /* disable, and ack any pending gpio interrupts */ - nv_wr32(dev, 0xe050, 0x00000000); - nv_wr32(dev, 0xe054, 0xffffffff); - if (dev_priv->chipset >= 0x90) { - nv_wr32(dev, 0xe070, 0x00000000); - nv_wr32(dev, 0xe074, 0xffffffff); + nv_wr32(priv, 0xe050, 0x00000000); + nv_wr32(priv, 0xe054, 0xffffffff); + if (nv_device(priv)->chipset >= 0x90) { + nv_wr32(priv, 0xe070, 0x00000000); + nv_wr32(priv, 0xe074, 0xffffffff); } - nouveau_irq_register(dev, 21, nv50_gpio_isr); return 0; } -void -nv50_gpio_fini(struct drm_device *dev) +int +nv50_gpio_fini(struct nouveau_object *object, bool suspend) { - struct drm_nouveau_private *dev_priv = dev->dev_private; - - nv_wr32(dev, 0xe050, 0x00000000); - if (dev_priv->chipset >= 0x90) - nv_wr32(dev, 0xe070, 0x00000000); - nouveau_irq_unregister(dev, 21); + struct nv50_gpio_priv *priv = (void *)object; + nv_wr32(priv, 0xe050, 0x00000000); + if (nv_device(priv)->chipset >= 0x90) + nv_wr32(priv, 0xe070, 0x00000000); + return nouveau_gpio_fini(&priv->base, suspend); } + +struct nouveau_oclass +nv50_gpio_oclass = { + .handle = NV_SUBDEV(GPIO, 0x50), + .ofuncs = &(struct nouveau_ofuncs) { + .ctor = nv50_gpio_ctor, + .dtor = nv50_gpio_dtor, + .init = nv50_gpio_init, + .fini = nv50_gpio_fini, + }, +}; diff --git a/drivers/gpu/drm/nouveau/core/subdev/gpio/nvd0.c b/drivers/gpu/drm/nouveau/core/subdev/gpio/nvd0.c new file mode 100644 index 000000000000..8d18fcad26e0 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/subdev/gpio/nvd0.c @@ -0,0 +1,104 @@ +/* + * 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 nvd0_gpio_priv { + struct nouveau_gpio base; +}; + +static void +nvd0_gpio_reset(struct nouveau_gpio *gpio) +{ + struct nouveau_bios *bios = nouveau_bios(gpio); + struct nvd0_gpio_priv *priv = (void *)gpio; + u16 entry; + u8 ver; + int ent = -1; + + while ((entry = dcb_gpio_entry(bios, 0, ++ent, &ver))) { + u32 data = nv_ro32(bios, entry); + u8 line = (data & 0x0000003f); + u8 defs = !!(data & 0x00000080); + u8 func = (data & 0x0000ff00) >> 8; + u8 unk0 = (data & 0x00ff0000) >> 16; + u8 unk1 = (data & 0x1f000000) >> 24; + + if (func == 0xff) + continue; + + gpio->set(gpio, 0, func, line, defs); + + nv_mask(priv, 0x00d610 + (line * 4), 0xff, unk0); + if (unk1--) + nv_mask(priv, 0x00d740 + (unk1 * 4), 0xff, line); + } +} + +static int +nvd0_gpio_drive(struct nouveau_gpio *gpio, int line, int dir, int out) +{ + u32 data = ((dir ^ 1) << 13) | (out << 12); + nv_mask(gpio, 0x00d610 + (line * 4), 0x00003000, data); + nv_mask(gpio, 0x00d604, 0x00000001, 0x00000001); /* update? */ + return 0; +} + +static int +nvd0_gpio_sense(struct nouveau_gpio *gpio, int line) +{ + return !!(nv_rd32(gpio, 0x00d610 + (line * 4)) & 0x00004000); +} + +static int +nvd0_gpio_ctor(struct nouveau_object *parent, struct nouveau_object *engine, + struct nouveau_oclass *oclass, void *data, u32 size, + struct nouveau_object **pobject) +{ + struct nvd0_gpio_priv *priv; + int ret; + + ret = nouveau_gpio_create(parent, engine, oclass, &priv); + *pobject = nv_object(priv); + if (ret) + return ret; + + priv->base.reset = nvd0_gpio_reset; + priv->base.drive = nvd0_gpio_drive; + priv->base.sense = nvd0_gpio_sense; + priv->base.irq_enable = nv50_gpio_irq_enable; + nv_subdev(priv)->intr = nv50_gpio_intr; + return 0; +} + +struct nouveau_oclass +nvd0_gpio_oclass = { + .handle = NV_SUBDEV(GPIO, 0xd0), + .ofuncs = &(struct nouveau_ofuncs) { + .ctor = nvd0_gpio_ctor, + .dtor = nv50_gpio_dtor, + .init = nv50_gpio_init, + .fini = nv50_gpio_fini, + }, +}; diff --git a/drivers/gpu/drm/nouveau/core/subdev/i2c/base.c b/drivers/gpu/drm/nouveau/core/subdev/i2c/base.c index 71e936158347..740e399bc7ab 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/i2c/base.c +++ b/drivers/gpu/drm/nouveau/core/subdev/i2c/base.c @@ -118,7 +118,7 @@ static const uint32_t nv50_i2c_port[] = { static u8 * i2c_table(struct drm_device *dev, u8 *version) { - u8 *dcb = dcb_table(dev), *i2c = NULL; + u8 *dcb = olddcb_table(dev), *i2c = NULL; if (dcb) { if (dcb[0] >= 0x15) i2c = ROMPTR(dev, dcb[2]); diff --git a/drivers/gpu/drm/nouveau/nouveau_bios.c b/drivers/gpu/drm/nouveau/nouveau_bios.c index f86985363acf..4f0d9bd1914b 100644 --- a/drivers/gpu/drm/nouveau/nouveau_bios.c +++ b/drivers/gpu/drm/nouveau/nouveau_bios.c @@ -27,7 +27,6 @@ #include "nouveau_drv.h" #include "nouveau_hw.h" #include "nouveau_encoder.h" -#include #include #include @@ -5384,7 +5383,7 @@ static uint16_t findstr(uint8_t *data, int n, const uint8_t *str, int len) } void * -dcb_table(struct drm_device *dev) +olddcb_table(struct drm_device *dev) { struct drm_nouveau_private *dev_priv = dev->dev_private; u8 *dcb = NULL; @@ -5438,9 +5437,9 @@ dcb_table(struct drm_device *dev) } void * -dcb_outp(struct drm_device *dev, u8 idx) +olddcb_outp(struct drm_device *dev, u8 idx) { - u8 *dcb = dcb_table(dev); + u8 *dcb = olddcb_table(dev); if (dcb && dcb[0] >= 0x30) { if (idx < dcb[2]) return dcb + dcb[1] + (idx * dcb[3]); @@ -5462,12 +5461,12 @@ dcb_outp(struct drm_device *dev, u8 idx) } int -dcb_outp_foreach(struct drm_device *dev, void *data, +olddcb_outp_foreach(struct drm_device *dev, void *data, int (*exec)(struct drm_device *, void *, int idx, u8 *outp)) { int ret, idx = -1; u8 *outp = NULL; - while ((outp = dcb_outp(dev, ++idx))) { + while ((outp = olddcb_outp(dev, ++idx))) { if (ROM32(outp[0]) == 0x00000000) break; /* seen on an NV11 with DCB v1.5 */ if (ROM32(outp[0]) == 0xffffffff) @@ -5489,7 +5488,7 @@ dcb_outp_foreach(struct drm_device *dev, void *data, u8 * dcb_conntab(struct drm_device *dev) { - u8 *dcb = dcb_table(dev); + u8 *dcb = olddcb_table(dev); if (dcb && dcb[0] >= 0x30 && dcb[1] >= 0x16) { u8 *conntab = ROMPTR(dev, dcb[0x14]); if (conntab && conntab[0] >= 0x30 && conntab[0] <= 0x40) @@ -5982,7 +5981,7 @@ parse_dcb_table(struct drm_device *dev, struct nvbios *bios) u8 *dcbt, *conn; int idx; - dcbt = dcb_table(dev); + dcbt = olddcb_table(dev); if (!dcbt) { /* handle pre-DCB boards */ if (bios->type == NVBIOS_BMP) { @@ -5996,7 +5995,7 @@ parse_dcb_table(struct drm_device *dev, struct nvbios *bios) NV_TRACE(dev, "DCB version %d.%d\n", dcbt[0] >> 4, dcbt[0] & 0xf); dcb->version = dcbt[0]; - dcb_outp_foreach(dev, NULL, parse_dcb_entry); + olddcb_outp_foreach(dev, NULL, parse_dcb_entry); /* * apart for v2.1+ not being known for requiring merging, this diff --git a/drivers/gpu/drm/nouveau/nouveau_bios.h b/drivers/gpu/drm/nouveau/nouveau_bios.h index b42aa31144a1..b4529a0b35aa 100644 --- a/drivers/gpu/drm/nouveau/nouveau_bios.h +++ b/drivers/gpu/drm/nouveau/nouveau_bios.h @@ -53,15 +53,6 @@ struct bit_entry { int bit_table(struct drm_device *, u8 id, struct bit_entry *); -enum dcb_gpio_tag { - DCB_GPIO_PANEL_POWER = 0x01, - DCB_GPIO_TVDAC0 = 0x0c, - DCB_GPIO_TVDAC1 = 0x2d, - DCB_GPIO_PWM_FAN = 0x09, - DCB_GPIO_FAN_SENSE = 0x3d, - DCB_GPIO_UNUSED = 0xff -}; - enum dcb_connector_type { DCB_CONNECTOR_VGA = 0x00, DCB_CONNECTOR_TV_0 = 0x10, @@ -302,9 +293,9 @@ struct nvbios { } legacy; }; -void *dcb_table(struct drm_device *); -void *dcb_outp(struct drm_device *, u8 idx); -int dcb_outp_foreach(struct drm_device *, void *data, +void *olddcb_table(struct drm_device *); +void *olddcb_outp(struct drm_device *, u8 idx); +int olddcb_outp_foreach(struct drm_device *, void *data, int (*)(struct drm_device *, void *, int idx, u8 *outp)); u8 *dcb_conntab(struct drm_device *); u8 *dcb_conn(struct drm_device *, u8 idx); diff --git a/drivers/gpu/drm/nouveau/nouveau_compat.c b/drivers/gpu/drm/nouveau/nouveau_compat.c index ca871d66f280..81fc8494e767 100644 --- a/drivers/gpu/drm/nouveau/nouveau_compat.c +++ b/drivers/gpu/drm/nouveau/nouveau_compat.c @@ -2,6 +2,7 @@ #include "nouveau_compat.h" #include +#include void *nouveau_newpriv(struct drm_device *); @@ -50,3 +51,82 @@ _nv_bios(struct drm_device *dev, u8 **data, u32 *size) *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); +} diff --git a/drivers/gpu/drm/nouveau/nouveau_compat.h b/drivers/gpu/drm/nouveau/nouveau_compat.h index d1ce3bc77930..f1143c362db6 100644 --- a/drivers/gpu/drm/nouveau/nouveau_compat.h +++ b/drivers/gpu/drm/nouveau/nouveau_compat.h @@ -9,4 +9,15 @@ 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); #endif diff --git a/drivers/gpu/drm/nouveau/nouveau_connector.c b/drivers/gpu/drm/nouveau/nouveau_connector.c index d6eabd98506a..cbf8348ca224 100644 --- a/drivers/gpu/drm/nouveau/nouveau_connector.c +++ b/drivers/gpu/drm/nouveau/nouveau_connector.c @@ -35,9 +35,10 @@ #include "nouveau_encoder.h" #include "nouveau_crtc.h" #include "nouveau_connector.h" -#include #include "nouveau_hw.h" +#include + static void nouveau_connector_hotplug(void *, int); struct nouveau_encoder * diff --git a/drivers/gpu/drm/nouveau/nouveau_display.c b/drivers/gpu/drm/nouveau/nouveau_display.c index d6051e01967d..44835c464957 100644 --- a/drivers/gpu/drm/nouveau/nouveau_display.c +++ b/drivers/gpu/drm/nouveau/nouveau_display.c @@ -34,10 +34,11 @@ #include "nouveau_dma.h" #include "nouveau_connector.h" #include "nouveau_software.h" -#include #include "nouveau_fence.h" #include "nv50_display.h" +#include + static void nouveau_user_framebuffer_destroy(struct drm_framebuffer *drm_fb) { diff --git a/drivers/gpu/drm/nouveau/nouveau_dp.c b/drivers/gpu/drm/nouveau/nouveau_dp.c index 67b322554ac6..63c0e827c302 100644 --- a/drivers/gpu/drm/nouveau/nouveau_dp.c +++ b/drivers/gpu/drm/nouveau/nouveau_dp.c @@ -29,7 +29,6 @@ #include "nouveau_connector.h" #include "nouveau_encoder.h" #include "nouveau_crtc.h" -#include /****************************************************************************** * aux channel util functions diff --git a/drivers/gpu/drm/nouveau/nouveau_drv.h b/drivers/gpu/drm/nouveau/nouveau_drv.h index 581a95078a38..afe978702097 100644 --- a/drivers/gpu/drm/nouveau/nouveau_drv.h +++ b/drivers/gpu/drm/nouveau/nouveau_drv.h @@ -366,16 +366,6 @@ struct nouveau_display_engine { struct drm_property *color_vibrance_property; }; -struct nouveau_gpio_engine { - spinlock_t lock; - struct list_head isr; - int (*init)(struct drm_device *); - void (*fini)(struct drm_device *); - int (*drive)(struct drm_device *, int line, int dir, int out); - int (*sense)(struct drm_device *, int line); - void (*irq_enable)(struct drm_device *, int line, bool); -}; - struct nouveau_pm_voltage_level { u32 voltage; /* microvolts */ u8 vid; @@ -555,7 +545,6 @@ struct nouveau_engine { struct nouveau_timer_engine timer; struct nouveau_fb_engine fb; struct nouveau_display_engine display; - struct nouveau_gpio_engine gpio; struct nouveau_pm_engine pm; struct nouveau_vram_engine vram; }; @@ -1376,22 +1365,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); -/* nv10_gpio.c */ -int nv10_gpio_init(struct drm_device *dev); -void nv10_gpio_fini(struct drm_device *dev); -int nv10_gpio_drive(struct drm_device *dev, int line, int dir, int out); -int nv10_gpio_sense(struct drm_device *dev, int line); -void nv10_gpio_irq_enable(struct drm_device *, int line, bool on); - -/* nv50_gpio.c */ -int nv50_gpio_init(struct drm_device *dev); -void nv50_gpio_fini(struct drm_device *dev); -int nv50_gpio_drive(struct drm_device *dev, int line, int dir, int out); -int nv50_gpio_sense(struct drm_device *dev, int line); -void nv50_gpio_irq_enable(struct drm_device *, int line, bool on); -int nvd0_gpio_drive(struct drm_device *dev, int line, int dir, int out); -int nvd0_gpio_sense(struct drm_device *dev, int line); - /* 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); diff --git a/drivers/gpu/drm/nouveau/nouveau_mxm.c b/drivers/gpu/drm/nouveau/nouveau_mxm.c index 07d0d1e03690..b2b326b83edd 100644 --- a/drivers/gpu/drm/nouveau/nouveau_mxm.c +++ b/drivers/gpu/drm/nouveau/nouveau_mxm.c @@ -460,13 +460,13 @@ mxm_show_unmatched(struct drm_device *dev, u8 *data, void *info) static void mxm_dcb_sanitise(struct drm_device *dev) { - u8 *dcb = dcb_table(dev); + u8 *dcb = olddcb_table(dev); if (!dcb || dcb[0] != 0x40) { MXM_DBG(dev, "unsupported DCB version\n"); return; } - dcb_outp_foreach(dev, NULL, mxm_dcb_sanitise_entry); + olddcb_outp_foreach(dev, NULL, mxm_dcb_sanitise_entry); mxms_foreach(dev, 0x01, mxm_show_unmatched, NULL); } diff --git a/drivers/gpu/drm/nouveau/nouveau_pm.c b/drivers/gpu/drm/nouveau/nouveau_pm.c index dc34664572c1..fd74cbf7ef69 100644 --- a/drivers/gpu/drm/nouveau/nouveau_pm.c +++ b/drivers/gpu/drm/nouveau/nouveau_pm.c @@ -26,7 +26,7 @@ #include "nouveau_drv.h" #include "nouveau_pm.h" -#include +#include #ifdef CONFIG_ACPI #include @@ -40,7 +40,7 @@ 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 gpio_func gpio; + struct dcb_gpio_func gpio; u32 divs, duty; int ret; @@ -68,7 +68,7 @@ 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 gpio_func gpio; + struct dcb_gpio_func gpio; u32 divs, duty; int ret; @@ -555,24 +555,21 @@ nouveau_hwmon_show_fan0_input(struct device *d, struct device_attribute *attr, struct drm_device *dev = dev_get_drvdata(d); struct drm_nouveau_private *dev_priv = dev->dev_private; struct nouveau_timer_engine *ptimer = &dev_priv->engine.timer; - struct gpio_func gpio; u32 cycles, cur, prev; u64 start; - int ret; - ret = nouveau_gpio_find(dev, 0, DCB_GPIO_FAN_SENSE, 0xff, &gpio); - if (ret) - return ret; + if (!nouveau_gpio_func_valid(dev, DCB_GPIO_FAN_SENSE)) + 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 = ptimer->read(dev); - prev = nouveau_gpio_sense(dev, 0, gpio.line); + prev = nouveau_gpio_func_get(dev, DCB_GPIO_FAN_SENSE); cycles = 0; do { - cur = nouveau_gpio_sense(dev, 0, gpio.line); + cur = nouveau_gpio_func_get(dev, DCB_GPIO_FAN_SENSE); if (prev != cur) { cycles++; prev = cur; diff --git a/drivers/gpu/drm/nouveau/nouveau_state.c b/drivers/gpu/drm/nouveau/nouveau_state.c index 85cb5f974dfd..84e03797bec3 100644 --- a/drivers/gpu/drm/nouveau/nouveau_state.c +++ b/drivers/gpu/drm/nouveau/nouveau_state.c @@ -37,7 +37,6 @@ #include "nouveau_agp.h" #include "nouveau_fbcon.h" #include -#include #include "nouveau_pm.h" #include "nv50_display.h" #include @@ -109,8 +108,6 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev) engine->display.destroy = nv04_display_destroy; engine->display.init = nv04_display_init; engine->display.fini = nv04_display_fini; - engine->gpio.drive = nv10_gpio_drive; - engine->gpio.sense = nv10_gpio_sense; engine->pm.clocks_get = nv04_pm_clocks_get; engine->pm.clocks_pre = nv04_pm_clocks_pre; engine->pm.clocks_set = nv04_pm_clocks_set; @@ -148,8 +145,6 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev) engine->display.destroy = nv04_display_destroy; engine->display.init = nv04_display_init; engine->display.fini = nv04_display_fini; - engine->gpio.drive = nv10_gpio_drive; - engine->gpio.sense = nv10_gpio_sense; engine->pm.clocks_get = nv04_pm_clocks_get; engine->pm.clocks_pre = nv04_pm_clocks_pre; engine->pm.clocks_set = nv04_pm_clocks_set; @@ -183,8 +178,6 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev) engine->display.destroy = nv04_display_destroy; engine->display.init = nv04_display_init; engine->display.fini = nv04_display_fini; - engine->gpio.drive = nv10_gpio_drive; - engine->gpio.sense = nv10_gpio_sense; engine->pm.clocks_get = nv04_pm_clocks_get; engine->pm.clocks_pre = nv04_pm_clocks_pre; engine->pm.clocks_set = nv04_pm_clocks_set; @@ -221,11 +214,6 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev) engine->display.destroy = nv04_display_destroy; engine->display.init = nv04_display_init; engine->display.fini = nv04_display_fini; - engine->gpio.init = nv10_gpio_init; - engine->gpio.fini = nv10_gpio_fini; - engine->gpio.drive = nv10_gpio_drive; - engine->gpio.sense = nv10_gpio_sense; - engine->gpio.irq_enable = nv10_gpio_irq_enable; engine->pm.clocks_get = nv40_pm_clocks_get; engine->pm.clocks_pre = nv40_pm_clocks_pre; engine->pm.clocks_set = nv40_pm_clocks_set; @@ -267,11 +255,6 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev) engine->display.destroy = nv50_display_destroy; engine->display.init = nv50_display_init; engine->display.fini = nv50_display_fini; - engine->gpio.init = nv50_gpio_init; - engine->gpio.fini = nv50_gpio_fini; - engine->gpio.drive = nv50_gpio_drive; - engine->gpio.sense = nv50_gpio_sense; - engine->gpio.irq_enable = nv50_gpio_irq_enable; switch (dev_priv->chipset) { case 0x84: case 0x86: @@ -330,11 +313,6 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev) engine->display.destroy = nv50_display_destroy; engine->display.init = nv50_display_init; engine->display.fini = nv50_display_fini; - engine->gpio.init = nv50_gpio_init; - engine->gpio.fini = nv50_gpio_fini; - engine->gpio.drive = nv50_gpio_drive; - engine->gpio.sense = nv50_gpio_sense; - engine->gpio.irq_enable = nv50_gpio_irq_enable; engine->vram.init = nvc0_vram_init; engine->vram.takedown = nv50_vram_fini; engine->vram.get = nvc0_vram_new; @@ -372,11 +350,6 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev) engine->display.destroy = nvd0_display_destroy; engine->display.init = nvd0_display_init; engine->display.fini = nvd0_display_fini; - engine->gpio.init = nv50_gpio_init; - engine->gpio.fini = nv50_gpio_fini; - engine->gpio.drive = nvd0_gpio_drive; - engine->gpio.sense = nvd0_gpio_sense; - engine->gpio.irq_enable = nv50_gpio_irq_enable; engine->vram.init = nvc0_vram_init; engine->vram.takedown = nv50_vram_fini; engine->vram.get = nvc0_vram_new; @@ -412,11 +385,6 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev) engine->display.destroy = nvd0_display_destroy; engine->display.init = nvd0_display_init; engine->display.fini = nvd0_display_fini; - engine->gpio.init = nv50_gpio_init; - engine->gpio.fini = nv50_gpio_fini; - engine->gpio.drive = nvd0_gpio_drive; - engine->gpio.sense = nvd0_gpio_sense; - engine->gpio.irq_enable = nv50_gpio_irq_enable; engine->vram.init = nvc0_vram_init; engine->vram.takedown = nv50_vram_fini; engine->vram.get = nvc0_vram_new; @@ -588,14 +556,9 @@ nouveau_card_init(struct drm_device *dev) if (ret) goto out_fb; - /* PGPIO */ - ret = nouveau_gpio_create(dev); - if (ret) - goto out_vram; - ret = nouveau_gpuobj_init(dev); if (ret) - goto out_gpio; + goto out_vram; ret = engine->instmem.init(dev); if (ret) @@ -830,8 +793,6 @@ out_instmem: engine->instmem.takedown(dev); out_gpuobj: nouveau_gpuobj_takedown(dev); -out_gpio: - nouveau_gpio_destroy(dev); out_vram: engine->vram.takedown(dev); out_fb: @@ -890,7 +851,6 @@ static void nouveau_card_takedown(struct drm_device *dev) engine->instmem.takedown(dev); nouveau_gpuobj_takedown(dev); - nouveau_gpio_destroy(dev); engine->vram.takedown(dev); engine->fb.takedown(dev); engine->timer.takedown(dev); diff --git a/drivers/gpu/drm/nouveau/nouveau_volt.c b/drivers/gpu/drm/nouveau/nouveau_volt.c index 9e34b573b8de..da3222c5a30b 100644 --- a/drivers/gpu/drm/nouveau/nouveau_volt.c +++ b/drivers/gpu/drm/nouveau/nouveau_volt.c @@ -26,9 +26,10 @@ #include "nouveau_drv.h" #include "nouveau_pm.h" -#include -static const enum dcb_gpio_tag vidtag[] = { 0x04, 0x05, 0x06, 0x1a, 0x73 }; +#include + +static const enum dcb_gpio_func_name vidtag[] = { 0x04, 0x05, 0x06, 0x1a, 0x73 }; static int nr_vidtag = sizeof(vidtag) / sizeof(vidtag[0]); int diff --git a/drivers/gpu/drm/nouveau/nv04_dac.c b/drivers/gpu/drm/nouveau/nv04_dac.c index da091a1caed6..54deb2779f8c 100644 --- a/drivers/gpu/drm/nouveau/nv04_dac.c +++ b/drivers/gpu/drm/nouveau/nv04_dac.c @@ -32,9 +32,10 @@ #include "nouveau_connector.h" #include "nouveau_crtc.h" #include "nouveau_hw.h" -#include #include "nvreg.h" +#include + int nv04_dac_output_offset(struct drm_encoder *encoder) { struct dcb_entry *dcb = nouveau_encoder(encoder)->dcb; diff --git a/drivers/gpu/drm/nouveau/nv17_tv.c b/drivers/gpu/drm/nouveau/nv17_tv.c index 65f7c452e479..a66a348d7f23 100644 --- a/drivers/gpu/drm/nouveau/nv17_tv.c +++ b/drivers/gpu/drm/nouveau/nv17_tv.c @@ -30,10 +30,11 @@ #include "nouveau_encoder.h" #include "nouveau_connector.h" #include "nouveau_crtc.h" -#include #include "nouveau_hw.h" #include "nv17_tv.h" +#include + static uint32_t nv42_tv_sample_load(struct drm_encoder *encoder) { struct drm_device *dev = encoder->dev; -- cgit v1.2.3 From 4196faa8623264b79279a06fd186654c959f2767 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Tue, 10 Jul 2012 14:36:38 +1000 Subject: drm/nouveau/i2c: port to subdev interfaces v2/v3: Ben Skeggs - fix typo in default bus selection - fix accidental loss of destructor v4: Dmitry Eremin-Solenikov - fix typo causing incorrect default i2c port settings when no BMP data Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/Makefile | 4 + drivers/gpu/drm/nouveau/core/engine/disp/vga.c | 214 ++++++++ .../gpu/drm/nouveau/core/include/subdev/bios/i2c.h | 25 + drivers/gpu/drm/nouveau/core/include/subdev/i2c.h | 79 +-- drivers/gpu/drm/nouveau/core/include/subdev/vga.h | 28 ++ drivers/gpu/drm/nouveau/core/subdev/bios/i2c.c | 129 +++++ 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 | 9 + drivers/gpu/drm/nouveau/core/subdev/device/nve0.c | 3 + drivers/gpu/drm/nouveau/core/subdev/i2c/aux.c | 212 ++++++++ drivers/gpu/drm/nouveau/core/subdev/i2c/base.c | 547 +++++++++++---------- drivers/gpu/drm/nouveau/core/subdev/i2c/bit.c | 230 +++++++++ drivers/gpu/drm/nouveau/nouveau_bios.c | 49 +- drivers/gpu/drm/nouveau/nouveau_bios.h | 1 - drivers/gpu/drm/nouveau/nouveau_compat.c | 50 ++ drivers/gpu/drm/nouveau/nouveau_compat.h | 13 + drivers/gpu/drm/nouveau/nouveau_connector.c | 8 +- drivers/gpu/drm/nouveau/nouveau_connector.h | 3 +- drivers/gpu/drm/nouveau/nouveau_dp.c | 219 +-------- drivers/gpu/drm/nouveau/nouveau_encoder.h | 4 +- drivers/gpu/drm/nouveau/nouveau_mxm.c | 6 +- drivers/gpu/drm/nouveau/nouveau_temp.c | 6 +- drivers/gpu/drm/nouveau/nv04_dfp.c | 4 +- drivers/gpu/drm/nouveau/nv04_tv.c | 4 +- 29 files changed, 1347 insertions(+), 555 deletions(-) create mode 100644 drivers/gpu/drm/nouveau/core/engine/disp/vga.c create mode 100644 drivers/gpu/drm/nouveau/core/include/subdev/bios/i2c.h create mode 100644 drivers/gpu/drm/nouveau/core/include/subdev/vga.h create mode 100644 drivers/gpu/drm/nouveau/core/subdev/bios/i2c.c create mode 100644 drivers/gpu/drm/nouveau/core/subdev/i2c/aux.c create mode 100644 drivers/gpu/drm/nouveau/core/subdev/i2c/bit.c (limited to 'drivers/gpu/drm/nouveau/nouveau_dp.c') diff --git a/drivers/gpu/drm/nouveau/Makefile b/drivers/gpu/drm/nouveau/Makefile index 414b2e8b8105..40ce4e18e7eb 100644 --- a/drivers/gpu/drm/nouveau/Makefile +++ b/drivers/gpu/drm/nouveau/Makefile @@ -22,6 +22,7 @@ nouveau-y += core/subdev/bios/base.o 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/device/base.o nouveau-y += core/subdev/device/nv04.o nouveau-y += core/subdev/device/nv10.o @@ -45,6 +46,8 @@ nouveau-y += core/subdev/gpio/nv10.o nouveau-y += core/subdev/gpio/nv50.o nouveau-y += core/subdev/gpio/nvd0.o nouveau-y += core/subdev/i2c/base.o +nouveau-y += core/subdev/i2c/aux.o +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 @@ -61,6 +64,7 @@ nouveau-y += core/engine/copy/nva3.o nouveau-y += core/engine/copy/nvc0.o nouveau-y += core/engine/crypt/nv84.o nouveau-y += core/engine/crypt/nv98.o +nouveau-y += core/engine/disp/vga.o nouveau-y += core/engine/fifo/nv04.o nouveau-y += core/engine/fifo/nv10.o nouveau-y += core/engine/fifo/nv17.o diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/vga.c b/drivers/gpu/drm/nouveau/core/engine/disp/vga.c new file mode 100644 index 000000000000..cec2110cc53e --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/engine/disp/vga.c @@ -0,0 +1,214 @@ +/* + * 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 + +u8 +nv_rdport(void *obj, int head, u16 port) +{ + struct nouveau_device *device = nv_device(obj); + + if (device->card_type >= NV_50) + return nv_rd08(obj, 0x601000 + port); + + if (port == 0x03c0 || port == 0x03c1 || /* AR */ + port == 0x03c2 || port == 0x03da || /* INP0 */ + port == 0x03d4 || port == 0x03d5) /* CR */ + return nv_rd08(obj, 0x601000 + (head * 0x2000) + port); + + if (port == 0x03c2 || port == 0x03cc || /* MISC */ + port == 0x03c4 || port == 0x03c5 || /* SR */ + port == 0x03ce || port == 0x03cf) { /* GR */ + if (device->card_type < NV_40) + head = 0; /* CR44 selects head */ + return nv_rd08(obj, 0x0c0000 + (head * 0x2000) + port); + } + + nv_error(obj, "unknown vga port 0x%04x\n", port); + return 0x00; +} + +void +nv_wrport(void *obj, int head, u16 port, u8 data) +{ + struct nouveau_device *device = nv_device(obj); + + if (device->card_type >= NV_50) + nv_wr08(obj, 0x601000 + port, data); + else + if (port == 0x03c0 || port == 0x03c1 || /* AR */ + port == 0x03c2 || port == 0x03da || /* INP0 */ + port == 0x03d4 || port == 0x03d5) /* CR */ + nv_wr08(obj, 0x601000 + (head * 0x2000) + port, data); + else + if (port == 0x03c2 || port == 0x03cc || /* MISC */ + port == 0x03c4 || port == 0x03c5 || /* SR */ + port == 0x03ce || port == 0x03cf) { /* GR */ + if (device->card_type < NV_40) + head = 0; /* CR44 selects head */ + nv_wr08(obj, 0x0c0000 + (head * 0x2000) + port, data); + } else + nv_error(obj, "unknown vga port 0x%04x\n", port); +} + +u8 +nv_rdvgas(void *obj, int head, u8 index) +{ + nv_wrport(obj, head, 0x03c4, index); + return nv_rdport(obj, head, 0x03c5); +} + +void +nv_wrvgas(void *obj, int head, u8 index, u8 value) +{ + nv_wrport(obj, head, 0x03c4, index); + nv_wrport(obj, head, 0x03c5, value); +} + +u8 +nv_rdvgag(void *obj, int head, u8 index) +{ + nv_wrport(obj, head, 0x03ce, index); + return nv_rdport(obj, head, 0x03cf); +} + +void +nv_wrvgag(void *obj, int head, u8 index, u8 value) +{ + nv_wrport(obj, head, 0x03ce, index); + nv_wrport(obj, head, 0x03cf, value); +} + +u8 +nv_rdvgac(void *obj, int head, u8 index) +{ + nv_wrport(obj, head, 0x03d4, index); + return nv_rdport(obj, head, 0x03d5); +} + +void +nv_wrvgac(void *obj, int head, u8 index, u8 value) +{ + nv_wrport(obj, head, 0x03d4, index); + nv_wrport(obj, head, 0x03d5, value); +} + +u8 +nv_rdvgai(void *obj, int head, u16 port, u8 index) +{ + if (port == 0x03c4) return nv_rdvgas(obj, head, index); + if (port == 0x03ce) return nv_rdvgag(obj, head, index); + if (port == 0x03d4) return nv_rdvgac(obj, head, index); + nv_error(obj, "unknown indexed vga port 0x%04x\n", port); + return 0x00; +} + +void +nv_wrvgai(void *obj, int head, u16 port, u8 index, u8 value) +{ + if (port == 0x03c4) nv_wrvgas(obj, head, index, value); + else if (port == 0x03ce) nv_wrvgag(obj, head, index, value); + else if (port == 0x03d4) nv_wrvgac(obj, head, index, value); + else nv_error(obj, "unknown indexed vga port 0x%04x\n", port); +} + +bool +nv_lockvgac(void *obj, bool lock) +{ + bool locked = !nv_rdvgac(obj, 0, 0x1f); + u8 data = lock ? 0x99 : 0x57; + nv_wrvgac(obj, 0, 0x1f, data); + if (nv_device(obj)->chipset == 0x11) { + if (!(nv_rd32(obj, 0x001084) & 0x10000000)) + nv_wrvgac(obj, 1, 0x1f, data); + } + return locked; +} + +/* CR44 takes values 0 (head A), 3 (head B) and 4 (heads tied) + * it affects only the 8 bit vga io regs, which we access using mmio at + * 0xc{0,2}3c*, 0x60{1,3}3*, and 0x68{1,3}3d* + * in general, the set value of cr44 does not matter: reg access works as + * expected and values can be set for the appropriate head by using a 0x2000 + * offset as required + * however: + * a) pre nv40, the head B range of PRMVIO regs at 0xc23c* was not exposed and + * cr44 must be set to 0 or 3 for accessing values on the correct head + * through the common 0xc03c* addresses + * b) in tied mode (4) head B is programmed to the values set on head A, and + * access using the head B addresses can have strange results, ergo we leave + * tied mode in init once we know to what cr44 should be restored on exit + * + * the owner parameter is slightly abused: + * 0 and 1 are treated as head values and so the set value is (owner * 3) + * other values are treated as literal values to set + */ +u8 +nv_rdvgaowner(void *obj) +{ + if (nv_device(obj)->card_type < NV_50) { + if (nv_device(obj)->chipset == 0x11) { + u32 tied = nv_rd32(obj, 0x001084) & 0x10000000; + if (tied == 0) { + u8 slA = nv_rdvgac(obj, 0, 0x28) & 0x80; + u8 tvA = nv_rdvgac(obj, 0, 0x33) & 0x01; + u8 slB = nv_rdvgac(obj, 1, 0x28) & 0x80; + u8 tvB = nv_rdvgac(obj, 1, 0x33) & 0x01; + if (slA && !tvA) return 0x00; + if (slB && !tvB) return 0x03; + if (slA) return 0x00; + if (slB) return 0x03; + return 0x00; + } + return 0x04; + } + + return nv_rdvgac(obj, 0, 0x44); + } + + nv_error(obj, "rdvgaowner after nv4x\n"); + return 0x00; +} + +void +nv_wrvgaowner(void *obj, u8 select) +{ + if (nv_device(obj)->card_type < NV_50) { + u8 owner = (select == 1) ? 3 : select; + if (nv_device(obj)->chipset == 0x11) { + /* workaround hw lockup bug */ + nv_rdvgac(obj, 0, 0x1f); + nv_rdvgac(obj, 1, 0x1f); + } + + nv_wrvgac(obj, 0, 0x44, owner); + + if (nv_device(obj)->chipset == 0x11) { + nv_wrvgac(obj, 0, 0x2e, owner); + nv_wrvgac(obj, 0, 0x2e, owner); + } + } else + nv_error(obj, "wrvgaowner after nv4x\n"); +} diff --git a/drivers/gpu/drm/nouveau/core/include/subdev/bios/i2c.h b/drivers/gpu/drm/nouveau/core/include/subdev/bios/i2c.h new file mode 100644 index 000000000000..5079bedfd985 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/include/subdev/bios/i2c.h @@ -0,0 +1,25 @@ +#ifndef __NVBIOS_I2C_H__ +#define __NVBIOS_I2C_H__ + +struct nouveau_bios; + +enum dcb_i2c_type { + DCB_I2C_NV04_BIT = 0, + DCB_I2C_NV4E_BIT = 4, + DCB_I2C_NVIO_BIT = 5, + DCB_I2C_NVIO_AUX = 6, + DCB_I2C_UNUSED = 0xff +}; + +struct dcb_i2c_entry { + enum dcb_i2c_type type; + u8 drive; + u8 sense; + u32 data; +}; + +u16 dcb_i2c_table(struct nouveau_bios *, u8 *ver, u8 *hdr, u8 *cnt, u8 *len); +u16 dcb_i2c_entry(struct nouveau_bios *, u8 index, u8 *ver, u8 *len); +int dcb_i2c_parse(struct nouveau_bios *, u8 index, struct dcb_i2c_entry *); + +#endif diff --git a/drivers/gpu/drm/nouveau/core/include/subdev/i2c.h b/drivers/gpu/drm/nouveau/core/include/subdev/i2c.h index 1d083893a4d7..b93ab01e3785 100644 --- a/drivers/gpu/drm/nouveau/core/include/subdev/i2c.h +++ b/drivers/gpu/drm/nouveau/core/include/subdev/i2c.h @@ -1,39 +1,18 @@ -/* - * Copyright 2009 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. - */ - #ifndef __NOUVEAU_I2C_H__ #define __NOUVEAU_I2C_H__ -#include -#include -#include "drm_dp_helper.h" +#include +#include + +#include +#include #define NV_I2C_PORT(n) (0x00 + (n)) -#define NV_I2C_PORT_NUM 0x10 #define NV_I2C_DEFAULT(n) (0x80 + (n)) -struct nouveau_i2c_chan { +struct nouveau_i2c_port { struct i2c_adapter adapter; - struct drm_device *dev; + struct nouveau_i2c *i2c; struct i2c_algo_bit_data bit; struct list_head head; u8 index; @@ -44,16 +23,38 @@ struct nouveau_i2c_chan { u32 state; }; -int nouveau_i2c_init(struct drm_device *); -void nouveau_i2c_fini(struct drm_device *); -struct nouveau_i2c_chan *nouveau_i2c_find(struct drm_device *, u8 index); -bool nouveau_probe_i2c_addr(struct nouveau_i2c_chan *i2c, int addr); -int nouveau_i2c_identify(struct drm_device *dev, const char *what, - struct i2c_board_info *info, - bool (*match)(struct nouveau_i2c_chan *, - struct i2c_board_info *), - int index); +struct nouveau_i2c { + struct nouveau_subdev base; + + struct nouveau_i2c_port *(*find)(struct nouveau_i2c *, u8 index); + int (*identify)(struct nouveau_i2c *, int index, + const char *what, struct i2c_board_info *, + bool (*match)(struct nouveau_i2c_port *, + struct i2c_board_info *)); + struct list_head ports; +}; + +static inline struct nouveau_i2c * +nouveau_i2c(void *obj) +{ + return (void *)nv_device(obj)->subdev[NVDEV_SUBDEV_I2C]; +} + +extern struct nouveau_oclass nouveau_i2c_oclass; + +void nouveau_i2c_drive_scl(void *, int); +void nouveau_i2c_drive_sda(void *, int); +int nouveau_i2c_sense_scl(void *); +int nouveau_i2c_sense_sda(void *); + +int nv_rdi2cr(struct nouveau_i2c_port *, u8 addr, u8 reg); +int nv_wri2cr(struct nouveau_i2c_port *, u8 addr, u8 reg, u8 val); +bool nv_probe_i2c(struct nouveau_i2c_port *, u8 addr); + +int nv_rdaux(struct nouveau_i2c_port *, u32 addr, u8 *data, u8 size); +int nv_wraux(struct nouveau_i2c_port *, u32 addr, u8 *data, u8 size); -extern const struct i2c_algorithm nouveau_dp_i2c_algo; +extern const struct i2c_algorithm nouveau_i2c_bit_algo; +extern const struct i2c_algorithm nouveau_i2c_aux_algo; -#endif /* __NOUVEAU_I2C_H__ */ +#endif diff --git a/drivers/gpu/drm/nouveau/core/include/subdev/vga.h b/drivers/gpu/drm/nouveau/core/include/subdev/vga.h new file mode 100644 index 000000000000..d81df1ae442d --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/include/subdev/vga.h @@ -0,0 +1,28 @@ +#ifndef __NOUVEAU_VGA_H__ +#define __NOUVEAU_VGA_H__ + +/* 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); + +/* VGA Sequencer */ +u8 nv_rdvgas(void *obj, int head, u8 index); +void nv_wrvgas(void *obj, int head, u8 index, u8 value); + +/* VGA Graphics */ +u8 nv_rdvgag(void *obj, int head, u8 index); +void nv_wrvgag(void *obj, int head, u8 index, u8 value); + +/* VGA CRTC */ +u8 nv_rdvgac(void *obj, int head, u8 index); +void nv_wrvgac(void *obj, int head, u8 index, u8 value); + +/* VGA indexed port access dispatcher */ +u8 nv_rdvgai(void *obj, int head, u16 port, u8 index); +void nv_wrvgai(void *obj, int head, u16 port, u8 index, u8 value); + +bool nv_lockvgac(void *obj, bool lock); +u8 nv_rdvgaowner(void *obj); +void nv_wrvgaowner(void *obj, u8); + +#endif diff --git a/drivers/gpu/drm/nouveau/core/subdev/bios/i2c.c b/drivers/gpu/drm/nouveau/core/subdev/bios/i2c.c new file mode 100644 index 000000000000..ad577db83766 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/subdev/bios/i2c.c @@ -0,0 +1,129 @@ +/* + * 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/bios.h" +#include "subdev/bios/dcb.h" +#include "subdev/bios/i2c.h" + +u16 +dcb_i2c_table(struct nouveau_bios *bios, u8 *ver, u8 *hdr, u8 *cnt, u8 *len) +{ + u16 i2c = 0x0000; + u16 dcb = dcb_table(bios, ver, hdr, cnt, len); + if (dcb) { + if (*ver >= 0x15) + i2c = nv_ro16(bios, dcb + 2); + if (*ver >= 0x30) + i2c = nv_ro16(bios, dcb + 4); + } + + if (i2c && *ver >= 0x30) { + *ver = nv_ro08(bios, i2c + 0); + *hdr = nv_ro08(bios, i2c + 1); + *cnt = nv_ro08(bios, i2c + 2); + *len = nv_ro08(bios, i2c + 3); + } else { + *ver = *ver; /* use DCB version */ + *hdr = 0; + *cnt = 16; + *len = 4; + } + + return i2c; +} + +u16 +dcb_i2c_entry(struct nouveau_bios *bios, u8 idx, u8 *ver, u8 *len) +{ + u8 hdr, cnt; + u16 i2c = dcb_i2c_table(bios, ver, &hdr, &cnt, len); + if (i2c && idx < cnt) + return i2c + hdr + (idx * *len); + return 0x0000; +} + +int +dcb_i2c_parse(struct nouveau_bios *bios, u8 idx, struct dcb_i2c_entry *info) +{ + u8 ver, len; + u16 ent = dcb_i2c_entry(bios, idx, &ver, &len); + if (ent) { + info->data = nv_ro32(bios, ent + 0); + info->type = nv_ro08(bios, ent + 3); + if (ver < 0x30) { + info->type &= 0x07; + if (info->type == 0x07) + info->type = 0xff; + } + + switch (info->type) { + case DCB_I2C_NV04_BIT: + info->drive = nv_ro08(bios, ent + 0); + info->sense = nv_ro08(bios, ent + 1); + return 0; + case DCB_I2C_NV4E_BIT: + info->drive = nv_ro08(bios, ent + 1); + return 0; + case DCB_I2C_NVIO_BIT: + case DCB_I2C_NVIO_AUX: + info->drive = nv_ro08(bios, ent + 0); + return 0; + case DCB_I2C_UNUSED: + return 0; + default: + nv_warn(bios, "unknown i2c type %d\n", info->type); + info->type = DCB_I2C_UNUSED; + return 0; + } + } + + if (bios->bmp_offset && idx < 2) { + /* BMP (from v4.0 has i2c info in the structure, it's in a + * fixed location on earlier VBIOS + */ + if (nv_ro08(bios, bios->bmp_offset + 5) < 4) + ent = 0x0048; + else + ent = 0x0036 + bios->bmp_offset; + + if (idx == 0) { + info->drive = nv_ro08(bios, ent + 4); + if (!info->drive) info->drive = 0x3f; + info->sense = nv_ro08(bios, ent + 5); + if (!info->sense) info->sense = 0x3e; + } else + if (idx == 1) { + info->drive = nv_ro08(bios, ent + 6); + if (!info->drive) info->drive = 0x37; + info->sense = nv_ro08(bios, ent + 7); + if (!info->sense) info->sense = 0x36; + } + + info->type = DCB_I2C_NV04_BIT; + return 0; + } + + return -ENOENT; +} diff --git a/drivers/gpu/drm/nouveau/core/subdev/device/nv04.c b/drivers/gpu/drm/nouveau/core/subdev/device/nv04.c index d54daa3f0df3..e0ebbe184c9d 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/device/nv04.c +++ b/drivers/gpu/drm/nouveau/core/subdev/device/nv04.c @@ -24,6 +24,7 @@ #include #include +#include int nv04_identify(struct nouveau_device *device) @@ -31,9 +32,11 @@ nv04_identify(struct nouveau_device *device) switch (device->chipset) { case 0x04: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; + device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; break; case 0x05: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; + device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_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 c0c40cddaa2f..19b1de60db2a 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/device/nv10.c +++ b/drivers/gpu/drm/nouveau/core/subdev/device/nv10.c @@ -25,6 +25,7 @@ #include #include #include +#include int nv10_identify(struct nouveau_device *device) @@ -33,34 +34,42 @@ nv10_identify(struct nouveau_device *device) case 0x10: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; + device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; break; case 0x15: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; + device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; break; case 0x16: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; + device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; break; case 0x1a: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; + device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; break; case 0x11: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; + device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; break; case 0x17: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; + device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; break; case 0x1f: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; + device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; break; case 0x18: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; + device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_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 1215e3ff47fa..8f735275b88d 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/device/nv20.c +++ b/drivers/gpu/drm/nouveau/core/subdev/device/nv20.c @@ -25,6 +25,7 @@ #include #include #include +#include int nv20_identify(struct nouveau_device *device) @@ -33,18 +34,22 @@ nv20_identify(struct nouveau_device *device) case 0x20: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; + device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; break; case 0x25: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; + device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; break; case 0x28: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; + device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; break; case 0x2a: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; + device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_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 43eb94e7768a..eefc3455bd20 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/device/nv30.c +++ b/drivers/gpu/drm/nouveau/core/subdev/device/nv30.c @@ -25,6 +25,7 @@ #include #include #include +#include int nv30_identify(struct nouveau_device *device) @@ -33,22 +34,27 @@ nv30_identify(struct nouveau_device *device) case 0x30: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; + device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; break; case 0x35: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; + device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; break; case 0x31: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; + device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; break; case 0x36: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; + device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; break; case 0x34: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; + device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_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 7c10a3c68d55..63047c5bfdc4 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/device/nv40.c +++ b/drivers/gpu/drm/nouveau/core/subdev/device/nv40.c @@ -25,6 +25,7 @@ #include #include #include +#include int nv40_identify(struct nouveau_device *device) @@ -33,66 +34,82 @@ nv40_identify(struct nouveau_device *device) case 0x40: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; + device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; break; case 0x41: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; + device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; break; case 0x42: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; + device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; break; case 0x43: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; + device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; break; case 0x45: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; + device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; break; case 0x47: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; + device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; break; case 0x49: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; + device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; break; case 0x4b: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; + device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; break; case 0x44: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; + device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; break; case 0x46: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; + device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; break; case 0x4a: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; + device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; break; case 0x4c: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; + device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; break; case 0x4e: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; + device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; break; case 0x63: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; + device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; break; case 0x67: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; + device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; break; case 0x68: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; + device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_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 581dcf199884..9f4f6eff4431 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/device/nv50.c +++ b/drivers/gpu/drm/nouveau/core/subdev/device/nv50.c @@ -25,6 +25,7 @@ #include #include #include +#include int nv50_identify(struct nouveau_device *device) @@ -33,58 +34,72 @@ nv50_identify(struct nouveau_device *device) case 0x50: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; + device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; break; case 0x84: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; + device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; break; case 0x86: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; + device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; break; case 0x92: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; + device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; break; case 0x94: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; + device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; break; case 0x96: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; + device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; break; case 0x98: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; + device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; break; case 0xa0: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; + device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; break; case 0xaa: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; + device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; break; case 0xac: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; + device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; break; case 0xa3: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; + device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; break; case 0xa5: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; + device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; break; case 0xa8: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; + device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; break; case 0xaf: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; + device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_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 df31111965c4..f941024723c2 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/device/nvc0.c +++ b/drivers/gpu/drm/nouveau/core/subdev/device/nvc0.c @@ -25,6 +25,7 @@ #include #include #include +#include int nvc0_identify(struct nouveau_device *device) @@ -33,34 +34,42 @@ nvc0_identify(struct nouveau_device *device) case 0xc0: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; + device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; break; case 0xc4: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; + device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; break; case 0xc3: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; + device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; break; case 0xce: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; + device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; break; case 0xcf: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; + device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; break; case 0xc1: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; + device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; break; case 0xc8: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; + device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; break; case 0xd9: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nvd0_gpio_oclass; + device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_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 d321cb4ec138..21763cf39ec5 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/device/nve0.c +++ b/drivers/gpu/drm/nouveau/core/subdev/device/nve0.c @@ -25,6 +25,7 @@ #include #include #include +#include int nve0_identify(struct nouveau_device *device) @@ -33,10 +34,12 @@ nve0_identify(struct nouveau_device *device) case 0xe4: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nvd0_gpio_oclass; + device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; break; case 0xe7: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nvd0_gpio_oclass; + device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; break; default: nv_fatal(device, "unknown Kepler chipset\n"); diff --git a/drivers/gpu/drm/nouveau/core/subdev/i2c/aux.c b/drivers/gpu/drm/nouveau/core/subdev/i2c/aux.c new file mode 100644 index 000000000000..fe1ebf199ba9 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/subdev/i2c/aux.c @@ -0,0 +1,212 @@ +/* + * Copyright 2009 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 + +/****************************************************************************** + * aux channel util functions + *****************************************************************************/ +#define AUX_DBG(fmt, args...) nv_debug(aux, "AUXCH(%d): " fmt, ch, ##args) +#define AUX_ERR(fmt, args...) nv_error(aux, "AUXCH(%d): " fmt, ch, ##args) + +static void +auxch_fini(struct nouveau_i2c *aux, int ch) +{ + nv_mask(aux, 0x00e4e4 + (ch * 0x50), 0x00310000, 0x00000000); +} + +static int +auxch_init(struct nouveau_i2c *aux, int ch) +{ + const u32 unksel = 1; /* nfi which to use, or if it matters.. */ + const u32 ureq = unksel ? 0x00100000 : 0x00200000; + const u32 urep = unksel ? 0x01000000 : 0x02000000; + u32 ctrl, timeout; + + /* wait up to 1ms for any previous transaction to be done... */ + timeout = 1000; + do { + ctrl = nv_rd32(aux, 0x00e4e4 + (ch * 0x50)); + udelay(1); + if (!timeout--) { + AUX_ERR("begin idle timeout 0x%08x", ctrl); + return -EBUSY; + } + } while (ctrl & 0x03010000); + + /* set some magic, and wait up to 1ms for it to appear */ + nv_mask(aux, 0x00e4e4 + (ch * 0x50), 0x00300000, ureq); + timeout = 1000; + do { + ctrl = nv_rd32(aux, 0x00e4e4 + (ch * 0x50)); + udelay(1); + if (!timeout--) { + AUX_ERR("magic wait 0x%08x\n", ctrl); + auxch_fini(aux, ch); + return -EBUSY; + } + } while ((ctrl & 0x03000000) != urep); + + return 0; +} + +static int +auxch_tx(struct nouveau_i2c *aux, int ch, u8 type, u32 addr, u8 *data, u8 size) +{ + u32 ctrl, stat, timeout, retries; + u32 xbuf[4] = {}; + int ret, i; + + AUX_DBG("%d: 0x%08x %d\n", type, addr, size); + + ret = auxch_init(aux, ch); + if (ret) + goto out; + + stat = nv_rd32(aux, 0x00e4e8 + (ch * 0x50)); + if (!(stat & 0x10000000)) { + AUX_DBG("sink not detected\n"); + ret = -ENXIO; + goto out; + } + + if (!(type & 1)) { + memcpy(xbuf, data, size); + for (i = 0; i < 16; i += 4) { + AUX_DBG("wr 0x%08x\n", xbuf[i / 4]); + nv_wr32(aux, 0x00e4c0 + (ch * 0x50) + i, xbuf[i / 4]); + } + } + + ctrl = nv_rd32(aux, 0x00e4e4 + (ch * 0x50)); + ctrl &= ~0x0001f0ff; + ctrl |= type << 12; + ctrl |= size - 1; + nv_wr32(aux, 0x00e4e0 + (ch * 0x50), addr); + + /* retry transaction a number of times on failure... */ + ret = -EREMOTEIO; + for (retries = 0; retries < 32; retries++) { + /* reset, and delay a while if this is a retry */ + nv_wr32(aux, 0x00e4e4 + (ch * 0x50), 0x80000000 | ctrl); + nv_wr32(aux, 0x00e4e4 + (ch * 0x50), 0x00000000 | ctrl); + if (retries) + udelay(400); + + /* transaction request, wait up to 1ms for it to complete */ + nv_wr32(aux, 0x00e4e4 + (ch * 0x50), 0x00010000 | ctrl); + + timeout = 1000; + do { + ctrl = nv_rd32(aux, 0x00e4e4 + (ch * 0x50)); + udelay(1); + if (!timeout--) { + AUX_ERR("tx req timeout 0x%08x\n", ctrl); + goto out; + } + } while (ctrl & 0x00010000); + + /* read status, and check if transaction completed ok */ + stat = nv_mask(aux, 0x00e4e8 + (ch * 0x50), 0, 0); + if (!(stat & 0x000f0f00)) { + ret = 0; + break; + } + + AUX_DBG("%02d 0x%08x 0x%08x\n", retries, ctrl, stat); + } + + if (type & 1) { + for (i = 0; i < 16; i += 4) { + xbuf[i / 4] = nv_rd32(aux, 0x00e4d0 + (ch * 0x50) + i); + AUX_DBG("rd 0x%08x\n", xbuf[i / 4]); + } + memcpy(data, xbuf, size); + } + +out: + auxch_fini(aux, ch); + return ret; +} + +int +nv_rdaux(struct nouveau_i2c_port *auxch, u32 addr, u8 *data, u8 size) +{ + return auxch_tx(auxch->i2c, auxch->drive, 9, addr, data, size); +} + +int +nv_wraux(struct nouveau_i2c_port *auxch, u32 addr, u8 *data, u8 size) +{ + return auxch_tx(auxch->i2c, auxch->drive, 8, addr, data, size); +} + +static int +aux_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num) +{ + struct nouveau_i2c_port *auxch = (struct nouveau_i2c_port *)adap; + struct i2c_msg *msg = msgs; + int ret, mcnt = num; + + while (mcnt--) { + u8 remaining = msg->len; + u8 *ptr = msg->buf; + + while (remaining) { + u8 cnt = (remaining > 16) ? 16 : remaining; + u8 cmd; + + if (msg->flags & I2C_M_RD) + cmd = 1; + else + cmd = 0; + + if (mcnt || remaining > 16) + cmd |= 4; /* MOT */ + + ret = auxch_tx(auxch->i2c, auxch->drive, cmd, + msg->addr, ptr, cnt); + if (ret < 0) + return ret; + + ptr += cnt; + remaining -= cnt; + } + + msg++; + } + + return num; +} + +static u32 +aux_func(struct i2c_adapter *adap) +{ + return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL; +} + +const struct i2c_algorithm nouveau_i2c_aux_algo = { + .master_xfer = aux_xfer, + .functionality = aux_func +}; diff --git a/drivers/gpu/drm/nouveau/core/subdev/i2c/base.c b/drivers/gpu/drm/nouveau/core/subdev/i2c/base.c index 740e399bc7ab..3d2c88310f98 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/i2c/base.c +++ b/drivers/gpu/drm/nouveau/core/subdev/i2c/base.c @@ -1,5 +1,5 @@ /* - * Copyright 2009 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,204 +22,277 @@ * Authors: Ben Skeggs */ -#include +#include "core/option.h" -#include "drmP.h" -#include "nouveau_drv.h" -#include -#include "nouveau_hw.h" +#include "subdev/i2c.h" +#include "subdev/vga.h" -static void -i2c_drive_scl(void *data, int state) +int +nv_rdi2cr(struct nouveau_i2c_port *port, u8 addr, u8 reg) +{ + u8 val; + struct i2c_msg msgs[] = { + { .addr = addr, .flags = 0, .len = 1, .buf = ® }, + { .addr = addr, .flags = I2C_M_RD, .len = 1, .buf = &val }, + }; + + int ret = i2c_transfer(&port->adapter, msgs, 2); + if (ret != 2) + return -EIO; + + return val; +} + +int +nv_wri2cr(struct nouveau_i2c_port *port, u8 addr, u8 reg, u8 val) +{ + struct i2c_msg msgs[] = { + { .addr = addr, .flags = 0, .len = 1, .buf = ® }, + { .addr = addr, .flags = 0, .len = 1, .buf = &val }, + }; + + int ret = i2c_transfer(&port->adapter, msgs, 2); + if (ret != 2) + return -EIO; + + return 0; +} + +bool +nv_probe_i2c(struct nouveau_i2c_port *port, u8 addr) +{ + u8 buf[] = { 0 }; + struct i2c_msg msgs[] = { + { + .addr = addr, + .flags = 0, + .len = 1, + .buf = buf, + }, + { + .addr = addr, + .flags = I2C_M_RD, + .len = 1, + .buf = buf, + } + }; + + return i2c_transfer(&port->adapter, msgs, 2) == 2; +} + +static struct nouveau_i2c_port * +nouveau_i2c_find(struct nouveau_i2c *i2c, u8 index) +{ + struct nouveau_bios *bios = nouveau_bios(i2c); + struct nouveau_i2c_port *port; + + if (index == NV_I2C_DEFAULT(0) || + index == NV_I2C_DEFAULT(1)) { + u8 ver, hdr, cnt, len; + u16 i2c = dcb_i2c_table(bios, &ver, &hdr, &cnt, &len); + if (i2c && ver >= 0x30) { + u8 auxidx = nv_ro08(bios, i2c + 4); + if (index == NV_I2C_DEFAULT(0)) + index = (auxidx & 0x0f) >> 0; + else + index = (auxidx & 0xf0) >> 4; + } else { + index = 2; + } + } + + list_for_each_entry(port, &i2c->ports, head) { + if (port->index == index) + break; + } + + if (&port->head == &i2c->ports) + return NULL; + + if (nv_device(i2c)->card_type >= NV_50 && (port->dcb & 0x00000100)) { + u32 reg = 0x00e500, val; + if (port->type == 6) { + reg += port->drive * 0x50; + val = 0x2002; + } else { + reg += ((port->dcb & 0x1e00) >> 9) * 0x50; + val = 0xe001; + } + + /* nfi, but neither auxch or i2c work if it's 1 */ + nv_mask(i2c, reg + 0x0c, 0x00000001, 0x00000000); + /* nfi, but switches auxch vs normal i2c */ + nv_mask(i2c, reg + 0x00, 0x0000f003, val); + } + + return port; +} + +static int +nouveau_i2c_identify(struct nouveau_i2c *i2c, int index, const char *what, + struct i2c_board_info *info, + bool (*match)(struct nouveau_i2c_port *, + struct i2c_board_info *)) { - struct nouveau_i2c_chan *port = data; - if (port->type == 0) { - u8 val = NVReadVgaCrtc(port->dev, 0, port->drive); + struct nouveau_i2c_port *port = nouveau_i2c_find(i2c, index); + int i; + + if (!port) { + nv_debug(i2c, "no bus when probing %s on %d\n", what, index); + return -ENODEV; + } + + nv_debug(i2c, "probing %ss on bus: %d\n", what, port->index); + for (i = 0; info[i].addr; i++) { + if (nv_probe_i2c(port, info[i].addr) && + (!match || match(port, &info[i]))) { + nv_info(i2c, "detected %s: %s\n", what, info[i].type); + return i; + } + } + + nv_debug(i2c, "no devices found.\n"); + return -ENODEV; +} + +void +nouveau_i2c_drive_scl(void *data, int state) +{ + struct nouveau_i2c_port *port = data; + + if (port->type == DCB_I2C_NV04_BIT) { + u8 val = nv_rdvgac(port->i2c, 0, port->drive); if (state) val |= 0x20; else val &= 0xdf; - NVWriteVgaCrtc(port->dev, 0, port->drive, val | 0x01); + nv_wrvgac(port->i2c, 0, port->drive, val | 0x01); } else - if (port->type == 4) { - nv_mask(port->dev, port->drive, 0x2f, state ? 0x21 : 0x01); + if (port->type == DCB_I2C_NV4E_BIT) { + nv_mask(port->i2c, port->drive, 0x2f, state ? 0x21 : 0x01); } else - if (port->type == 5) { + if (port->type == DCB_I2C_NVIO_BIT) { if (state) port->state |= 0x01; else port->state &= 0xfe; - nv_wr32(port->dev, port->drive, 4 | port->state); + nv_wr32(port->i2c, port->drive, 4 | port->state); } } -static void -i2c_drive_sda(void *data, int state) +void +nouveau_i2c_drive_sda(void *data, int state) { - struct nouveau_i2c_chan *port = data; - if (port->type == 0) { - u8 val = NVReadVgaCrtc(port->dev, 0, port->drive); + struct nouveau_i2c_port *port = data; + + if (port->type == DCB_I2C_NV04_BIT) { + u8 val = nv_rdvgac(port->i2c, 0, port->drive); if (state) val |= 0x10; else val &= 0xef; - NVWriteVgaCrtc(port->dev, 0, port->drive, val | 0x01); + nv_wrvgac(port->i2c, 0, port->drive, val | 0x01); } else - if (port->type == 4) { - nv_mask(port->dev, port->drive, 0x1f, state ? 0x11 : 0x01); + if (port->type == DCB_I2C_NV4E_BIT) { + nv_mask(port->i2c, port->drive, 0x1f, state ? 0x11 : 0x01); } else - if (port->type == 5) { + if (port->type == DCB_I2C_NVIO_BIT) { if (state) port->state |= 0x02; else port->state &= 0xfd; - nv_wr32(port->dev, port->drive, 4 | port->state); + nv_wr32(port->i2c, port->drive, 4 | port->state); } } -static int -i2c_sense_scl(void *data) +int +nouveau_i2c_sense_scl(void *data) { - struct nouveau_i2c_chan *port = data; - struct drm_nouveau_private *dev_priv = port->dev->dev_private; - if (port->type == 0) { - return !!(NVReadVgaCrtc(port->dev, 0, port->sense) & 0x04); + struct nouveau_i2c_port *port = data; + struct nouveau_device *device = nv_device(port->i2c); + + if (port->type == DCB_I2C_NV04_BIT) { + return !!(nv_rdvgac(port->i2c, 0, port->sense) & 0x04); } else - if (port->type == 4) { - return !!(nv_rd32(port->dev, port->sense) & 0x00040000); + if (port->type == DCB_I2C_NV4E_BIT) { + return !!(nv_rd32(port->i2c, port->sense) & 0x00040000); } else - if (port->type == 5) { - if (dev_priv->card_type < NV_D0) - return !!(nv_rd32(port->dev, port->sense) & 0x01); + if (port->type == DCB_I2C_NVIO_BIT) { + if (device->card_type < NV_D0) + return !!(nv_rd32(port->i2c, port->sense) & 0x01); else - return !!(nv_rd32(port->dev, port->sense) & 0x10); + return !!(nv_rd32(port->i2c, port->sense) & 0x10); } + return 0; } -static int -i2c_sense_sda(void *data) +int +nouveau_i2c_sense_sda(void *data) { - struct nouveau_i2c_chan *port = data; - struct drm_nouveau_private *dev_priv = port->dev->dev_private; - if (port->type == 0) { - return !!(NVReadVgaCrtc(port->dev, 0, port->sense) & 0x08); + struct nouveau_i2c_port *port = data; + struct nouveau_device *device = nv_device(port->i2c); + + if (port->type == DCB_I2C_NV04_BIT) { + return !!(nv_rdvgac(port->i2c, 0, port->sense) & 0x08); } else - if (port->type == 4) { - return !!(nv_rd32(port->dev, port->sense) & 0x00080000); + if (port->type == DCB_I2C_NV4E_BIT) { + return !!(nv_rd32(port->i2c, port->sense) & 0x00080000); } else - if (port->type == 5) { - if (dev_priv->card_type < NV_D0) - return !!(nv_rd32(port->dev, port->sense) & 0x02); + if (port->type == DCB_I2C_NVIO_BIT) { + if (device->card_type < NV_D0) + return !!(nv_rd32(port->i2c, port->sense) & 0x02); else - return !!(nv_rd32(port->dev, port->sense) & 0x20); + return !!(nv_rd32(port->i2c, port->sense) & 0x20); } + return 0; } -static const uint32_t nv50_i2c_port[] = { +static const u32 nv50_i2c_port[] = { 0x00e138, 0x00e150, 0x00e168, 0x00e180, 0x00e254, 0x00e274, 0x00e764, 0x00e780, 0x00e79c, 0x00e7b8 }; -static u8 * -i2c_table(struct drm_device *dev, u8 *version) -{ - u8 *dcb = olddcb_table(dev), *i2c = NULL; - if (dcb) { - if (dcb[0] >= 0x15) - i2c = ROMPTR(dev, dcb[2]); - if (dcb[0] >= 0x30) - i2c = ROMPTR(dev, dcb[4]); - } - - /* early revisions had no version number, use dcb version */ - if (i2c) { - *version = dcb[0]; - if (*version >= 0x30) - *version = i2c[0]; - } - - return i2c; -} - -int -nouveau_i2c_init(struct drm_device *dev) +static int +nouveau_i2c_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 nvbios *bios = &dev_priv->vbios; - struct nouveau_i2c_chan *port; - u8 version = 0x00, entries, recordlen; - u8 *i2c, *entry, legacy[2][4] = {}; - int ret, i; - - INIT_LIST_HEAD(&dev_priv->i2c_ports); - - i2c = i2c_table(dev, &version); - if (!i2c) { - u8 *bmp = &bios->data[bios->offset]; - if (bios->type != NVBIOS_BMP) - return -ENODEV; - - legacy[0][0] = NV_CIO_CRE_DDC_WR__INDEX; - legacy[0][1] = NV_CIO_CRE_DDC_STATUS__INDEX; - legacy[1][0] = NV_CIO_CRE_DDC0_WR__INDEX; - legacy[1][1] = NV_CIO_CRE_DDC0_STATUS__INDEX; - - /* BMP (from v4.0) has i2c info in the structure, it's in a - * fixed location on earlier VBIOS - */ - if (bmp[5] < 4) - i2c = &bios->data[0x48]; - else - i2c = &bmp[0x36]; - - if (i2c[4]) legacy[0][0] = i2c[4]; - if (i2c[5]) legacy[0][1] = i2c[5]; - if (i2c[6]) legacy[1][0] = i2c[6]; - if (i2c[7]) legacy[1][1] = i2c[7]; - } - - if (version >= 0x30) { - entry = i2c[1] + i2c; - entries = i2c[2]; - recordlen = i2c[3]; - } else - if (version) { - entry = i2c; - entries = 16; - recordlen = 4; - } else { - entry = legacy[0]; - entries = 2; - recordlen = 4; - } + struct nouveau_device *device = nv_device(parent); + struct nouveau_bios *bios = nouveau_bios(parent); + struct nouveau_i2c_port *port; + struct nouveau_i2c *i2c; + struct dcb_i2c_entry info; + int ret, i = -1; + + ret = nouveau_subdev_create(parent, engine, oclass, 0, + "I2C", "i2c", &i2c); + *pobject = nv_object(i2c); + if (ret) + return ret; + + i2c->find = nouveau_i2c_find; + i2c->identify = nouveau_i2c_identify; + INIT_LIST_HEAD(&i2c->ports); + + while (!dcb_i2c_parse(bios, ++i, &info)) { + if (info.type == DCB_I2C_UNUSED) + continue; - for (i = 0; i < entries; i++, entry += recordlen) { port = kzalloc(sizeof(*port), GFP_KERNEL); - if (port == NULL) { - nouveau_i2c_fini(dev); - return -ENOMEM; - } - - port->type = entry[3]; - if (version < 0x30) { - port->type &= 0x07; - if (port->type == 0x07) - port->type = 0xff; - } - - if (port->type == 0xff) { - kfree(port); - continue; + if (!port) { + nv_error(i2c, "failed port memory alloc at %d\n", i); + break; } + port->type = info.type; switch (port->type) { - case 0: /* NV04:NV50 */ - port->drive = entry[0]; - port->sense = entry[1]; + case DCB_I2C_NV04_BIT: + port->drive = info.drive; + port->sense = info.sense; break; - case 4: /* NV4E */ - port->drive = 0x600800 + entry[1]; + case DCB_I2C_NV4E_BIT: + port->drive = 0x600800 + info.drive; port->sense = port->drive; break; - case 5: /* NV50- */ - port->drive = entry[0] & 0x0f; - if (dev_priv->card_type < NV_D0) { - if (port->drive >= ARRAY_SIZE(nv50_i2c_port)) + case DCB_I2C_NVIO_BIT: + port->drive = info.drive & 0x0f; + if (device->card_type < NV_D0) { + if (info.drive >= ARRAY_SIZE(nv50_i2c_port)) break; port->drive = nv50_i2c_port[port->drive]; port->sense = port->drive; @@ -228,167 +301,107 @@ nouveau_i2c_init(struct drm_device *dev) port->sense = port->drive; } break; - case 6: /* NV50- DP AUX */ - port->drive = entry[0] & 0x0f; + case DCB_I2C_NVIO_AUX: + port->drive = info.drive & 0x0f; port->sense = port->drive; - port->adapter.algo = &nouveau_dp_i2c_algo; + port->adapter.algo = &nouveau_i2c_aux_algo; break; default: break; } if (!port->adapter.algo && !port->drive) { - NV_ERROR(dev, "I2C%d: type %d index %x/%x unknown\n", + nv_error(i2c, "I2C%d: type %d index %x/%x unknown\n", i, port->type, port->drive, port->sense); kfree(port); continue; } snprintf(port->adapter.name, sizeof(port->adapter.name), - "nouveau-%s-%d", pci_name(dev->pdev), i); + "nouveau-%s-%d", device->name, i); port->adapter.owner = THIS_MODULE; - port->adapter.dev.parent = &dev->pdev->dev; - port->dev = dev; + port->adapter.dev.parent = &device->pdev->dev; + port->i2c = i2c; port->index = i; - port->dcb = ROM32(entry[0]); + port->dcb = info.data; i2c_set_adapdata(&port->adapter, i2c); - if (port->adapter.algo != &nouveau_dp_i2c_algo) { - port->adapter.algo_data = &port->bit; - port->bit.udelay = 10; - port->bit.timeout = usecs_to_jiffies(2200); - port->bit.data = port; - port->bit.setsda = i2c_drive_sda; - port->bit.setscl = i2c_drive_scl; - port->bit.getsda = i2c_sense_sda; - port->bit.getscl = i2c_sense_scl; - - i2c_drive_scl(port, 0); - i2c_drive_sda(port, 1); - i2c_drive_scl(port, 1); - - ret = i2c_bit_add_bus(&port->adapter); + if (port->adapter.algo != &nouveau_i2c_aux_algo) { + nouveau_i2c_drive_scl(port, 0); + nouveau_i2c_drive_sda(port, 1); + nouveau_i2c_drive_scl(port, 1); + +#ifdef CONFIG_NOUVEAU_I2C_INTERNAL_DEFAULT + if (nouveau_boolopt(device->cfgopt, "NvI2C", true)) { +#else + if (nouveau_boolopt(device->cfgopt, "NvI2C", false)) { +#endif + port->adapter.algo = &nouveau_i2c_bit_algo; + ret = i2c_add_adapter(&port->adapter); + } else { + port->adapter.algo_data = &port->bit; + port->bit.udelay = 10; + port->bit.timeout = usecs_to_jiffies(2200); + port->bit.data = port; + port->bit.setsda = nouveau_i2c_drive_sda; + port->bit.setscl = nouveau_i2c_drive_scl; + port->bit.getsda = nouveau_i2c_sense_sda; + port->bit.getscl = nouveau_i2c_sense_scl; + ret = i2c_bit_add_bus(&port->adapter); + } } else { - port->adapter.algo = &nouveau_dp_i2c_algo; + port->adapter.algo = &nouveau_i2c_aux_algo; ret = i2c_add_adapter(&port->adapter); } if (ret) { - NV_ERROR(dev, "I2C%d: failed register: %d\n", i, ret); + nv_error(i2c, "I2C%d: failed register: %d\n", i, ret); kfree(port); continue; } - list_add_tail(&port->head, &dev_priv->i2c_ports); + list_add_tail(&port->head, &i2c->ports); } return 0; } -void -nouveau_i2c_fini(struct drm_device *dev) +static void +nouveau_i2c_dtor(struct nouveau_object *object) { - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_i2c_chan *port, *tmp; + struct nouveau_i2c *i2c = (void *)object; + struct nouveau_i2c_port *port, *temp; - list_for_each_entry_safe(port, tmp, &dev_priv->i2c_ports, head) { + list_for_each_entry_safe(port, temp, &i2c->ports, head) { i2c_del_adapter(&port->adapter); + list_del(&port->head); kfree(port); } -} - -struct nouveau_i2c_chan * -nouveau_i2c_find(struct drm_device *dev, u8 index) -{ - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_i2c_chan *port; - - if (index == NV_I2C_DEFAULT(0) || - index == NV_I2C_DEFAULT(1)) { - u8 version, *i2c = i2c_table(dev, &version); - if (i2c && version >= 0x30) { - if (index == NV_I2C_DEFAULT(0)) - index = (i2c[4] & 0x0f); - else - index = (i2c[4] & 0xf0) >> 4; - } else { - index = 2; - } - } - - list_for_each_entry(port, &dev_priv->i2c_ports, head) { - if (port->index == index) - break; - } - - if (&port->head == &dev_priv->i2c_ports) - return NULL; - if (dev_priv->card_type >= NV_50 && (port->dcb & 0x00000100)) { - u32 reg = 0x00e500, val; - if (port->type == 6) { - reg += port->drive * 0x50; - val = 0x2002; - } else { - reg += ((port->dcb & 0x1e00) >> 9) * 0x50; - val = 0xe001; - } - - /* nfi, but neither auxch or i2c work if it's 1 */ - nv_mask(dev, reg + 0x0c, 0x00000001, 0x00000000); - /* nfi, but switches auxch vs normal i2c */ - nv_mask(dev, reg + 0x00, 0x0000f003, val); - } - - return port; + nouveau_subdev_destroy(&i2c->base); } -bool -nouveau_probe_i2c_addr(struct nouveau_i2c_chan *i2c, int addr) +static int +nouveau_i2c_init(struct nouveau_object *object) { - uint8_t buf[] = { 0 }; - struct i2c_msg msgs[] = { - { - .addr = addr, - .flags = 0, - .len = 1, - .buf = buf, - }, - { - .addr = addr, - .flags = I2C_M_RD, - .len = 1, - .buf = buf, - } - }; - - return i2c_transfer(&i2c->adapter, msgs, 2) == 2; + struct nouveau_i2c *i2c = (void *)object; + return nouveau_subdev_init(&i2c->base); } -int -nouveau_i2c_identify(struct drm_device *dev, const char *what, - struct i2c_board_info *info, - bool (*match)(struct nouveau_i2c_chan *, - struct i2c_board_info *), - int index) +static int +nouveau_i2c_fini(struct nouveau_object *object, bool suspend) { - struct nouveau_i2c_chan *i2c = nouveau_i2c_find(dev, index); - int i; - - if (!i2c) { - NV_DEBUG(dev, "No bus when probing %s on %d\n", what, index); - return -ENODEV; - } - - NV_DEBUG(dev, "Probing %ss on I2C bus: %d\n", what, i2c->index); - for (i = 0; info[i].addr; i++) { - if (nouveau_probe_i2c_addr(i2c, info[i].addr) && - (!match || match(i2c, &info[i]))) { - NV_INFO(dev, "Detected %s: %s\n", what, info[i].type); - return i; - } - } - - NV_DEBUG(dev, "No devices found.\n"); - return -ENODEV; + struct nouveau_i2c *i2c = (void *)object; + return nouveau_subdev_fini(&i2c->base, suspend); } + +struct nouveau_oclass +nouveau_i2c_oclass = { + .handle = NV_SUBDEV(I2C, 0x00), + .ofuncs = &(struct nouveau_ofuncs) { + .ctor = nouveau_i2c_ctor, + .dtor = nouveau_i2c_dtor, + .init = nouveau_i2c_init, + .fini = nouveau_i2c_fini, + }, +}; diff --git a/drivers/gpu/drm/nouveau/core/subdev/i2c/bit.c b/drivers/gpu/drm/nouveau/core/subdev/i2c/bit.c new file mode 100644 index 000000000000..1c4c9a5c8e2e --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/subdev/i2c/bit.c @@ -0,0 +1,230 @@ +/* + * 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/i2c.h" + +#ifdef CONFIG_NOUVEAU_I2C_INTERNAL +#define T_TIMEOUT 2200000 +#define T_RISEFALL 1000 +#define T_HOLD 5000 + +static inline void +i2c_drive_scl(struct nouveau_i2c_port *port, int state) +{ + nouveau_i2c_drive_scl(port, state); +} + +static inline void +i2c_drive_sda(struct nouveau_i2c_port *port, int state) +{ + nouveau_i2c_drive_sda(port, state); +} + +static inline int +i2c_sense_scl(struct nouveau_i2c_port *port) +{ + return nouveau_i2c_sense_scl(port); +} + +static inline int +i2c_sense_sda(struct nouveau_i2c_port *port) +{ + return nouveau_i2c_sense_sda(port); +} + +static void +i2c_delay(struct nouveau_i2c_port *port, u32 nsec) +{ + udelay((nsec + 500) / 1000); +} + +static bool +i2c_raise_scl(struct nouveau_i2c_port *port) +{ + u32 timeout = T_TIMEOUT / T_RISEFALL; + + i2c_drive_scl(port, 1); + do { + i2c_delay(port, T_RISEFALL); + } while (!i2c_sense_scl(port) && --timeout); + + return timeout != 0; +} + +static int +i2c_start(struct nouveau_i2c_port *port) +{ + int ret = 0; + + port->state = i2c_sense_scl(port); + port->state |= i2c_sense_sda(port) << 1; + if (port->state != 3) { + i2c_drive_scl(port, 0); + i2c_drive_sda(port, 1); + if (!i2c_raise_scl(port)) + ret = -EBUSY; + } + + i2c_drive_sda(port, 0); + i2c_delay(port, T_HOLD); + i2c_drive_scl(port, 0); + i2c_delay(port, T_HOLD); + return ret; +} + +static void +i2c_stop(struct nouveau_i2c_port *port) +{ + i2c_drive_scl(port, 0); + i2c_drive_sda(port, 0); + i2c_delay(port, T_RISEFALL); + + i2c_drive_scl(port, 1); + i2c_delay(port, T_HOLD); + i2c_drive_sda(port, 1); + i2c_delay(port, T_HOLD); +} + +static int +i2c_bitw(struct nouveau_i2c_port *port, int sda) +{ + i2c_drive_sda(port, sda); + i2c_delay(port, T_RISEFALL); + + if (!i2c_raise_scl(port)) + return -ETIMEDOUT; + i2c_delay(port, T_HOLD); + + i2c_drive_scl(port, 0); + i2c_delay(port, T_HOLD); + return 0; +} + +static int +i2c_bitr(struct nouveau_i2c_port *port) +{ + int sda; + + i2c_drive_sda(port, 1); + i2c_delay(port, T_RISEFALL); + + if (!i2c_raise_scl(port)) + return -ETIMEDOUT; + i2c_delay(port, T_HOLD); + + sda = i2c_sense_sda(port); + + i2c_drive_scl(port, 0); + i2c_delay(port, T_HOLD); + return sda; +} + +static int +i2c_get_byte(struct nouveau_i2c_port *port, u8 *byte, bool last) +{ + int i, bit; + + *byte = 0; + for (i = 7; i >= 0; i--) { + bit = i2c_bitr(port); + if (bit < 0) + return bit; + *byte |= bit << i; + } + + return i2c_bitw(port, last ? 1 : 0); +} + +static int +i2c_put_byte(struct nouveau_i2c_port *port, u8 byte) +{ + int i, ret; + for (i = 7; i >= 0; i--) { + ret = i2c_bitw(port, !!(byte & (1 << i))); + if (ret < 0) + return ret; + } + + ret = i2c_bitr(port); + if (ret == 1) /* nack */ + ret = -EIO; + return ret; +} + +static int +i2c_addr(struct nouveau_i2c_port *port, struct i2c_msg *msg) +{ + u32 addr = msg->addr << 1; + if (msg->flags & I2C_M_RD) + addr |= 1; + return i2c_put_byte(port, addr); +} + +static int +i2c_bit_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num) +{ + struct nouveau_i2c_port *port = (struct nouveau_i2c_port *)adap; + struct i2c_msg *msg = msgs; + int ret = 0, mcnt = num; + + while (!ret && mcnt--) { + u8 remaining = msg->len; + u8 *ptr = msg->buf; + + ret = i2c_start(port); + if (ret == 0) + ret = i2c_addr(port, msg); + + if (msg->flags & I2C_M_RD) { + while (!ret && remaining--) + ret = i2c_get_byte(port, ptr++, !remaining); + } else { + while (!ret && remaining--) + ret = i2c_put_byte(port, *ptr++); + } + + msg++; + } + + i2c_stop(port); + return (ret < 0) ? ret : num; +} +#else +static int +i2c_bit_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num) +{ + return -ENODEV; +} +#endif + +static u32 +i2c_bit_func(struct i2c_adapter *adap) +{ + return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL; +} + +const struct i2c_algorithm nouveau_i2c_bit_algo = { + .master_xfer = i2c_bit_xfer, + .functionality = i2c_bit_func +}; diff --git a/drivers/gpu/drm/nouveau/nouveau_bios.c b/drivers/gpu/drm/nouveau/nouveau_bios.c index 4f0d9bd1914b..35b0a8f9c008 100644 --- a/drivers/gpu/drm/nouveau/nouveau_bios.c +++ b/drivers/gpu/drm/nouveau/nouveau_bios.c @@ -528,7 +528,7 @@ static int dcb_entry_idx_from_crtchead(struct drm_device *dev) return dcb_entry; } -static struct nouveau_i2c_chan * +static struct nouveau_i2c_port * init_i2c_device_find(struct drm_device *dev, int i2c_index) { if (i2c_index == 0xff) { @@ -537,9 +537,9 @@ init_i2c_device_find(struct drm_device *dev, int i2c_index) /* note: dcb_entry_idx_from_crtchead needs pre-script set-up */ int idx = dcb_entry_idx_from_crtchead(dev); - i2c_index = NV_I2C_DEFAULT(0); + i2c_index = 0x80; //NV_I2C_DEFAULT(0); if (idx != 0x7f && dcb->entry[idx].i2c_upper_default) - i2c_index = NV_I2C_DEFAULT(1); + i2c_index = 0x81; //NV_I2C_DEFAULT(1); } return nouveau_i2c_find(dev, i2c_index); @@ -920,7 +920,7 @@ init_dp_condition(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) break; case 5: { - struct nouveau_i2c_chan *auxch; + struct nouveau_i2c_port *auxch; int ret; auxch = nouveau_i2c_find(dev, bios->display.output->i2c_index); @@ -929,7 +929,7 @@ init_dp_condition(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) return 3; } - ret = nouveau_dp_auxch(auxch, 9, 0xd, &cond, 1); + ret = auxch_rd(dev, auxch, 0xd, &cond, 1); if (ret) { NV_ERROR(dev, "0x%04X: auxch rd fail: %d\n", offset, ret); return 3; @@ -1166,7 +1166,7 @@ init_i2c_byte(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) uint8_t i2c_index = bios->data[offset + 1]; uint8_t i2c_address = bios->data[offset + 2] >> 1; uint8_t count = bios->data[offset + 3]; - struct nouveau_i2c_chan *chan; + struct nouveau_i2c_port *chan; int len = 4 + count * 3; int ret, i; @@ -1189,7 +1189,7 @@ init_i2c_byte(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) uint8_t data = bios->data[offset + 6 + i * 3]; union i2c_smbus_data val; - ret = i2c_smbus_xfer(&chan->adapter, i2c_address, 0, + ret = i2c_smbus_xfer(nouveau_i2c_adapter(chan), i2c_address, 0, I2C_SMBUS_READ, reg, I2C_SMBUS_BYTE_DATA, &val); if (ret < 0) { @@ -1206,7 +1206,7 @@ init_i2c_byte(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) val.byte &= mask; val.byte |= data; - ret = i2c_smbus_xfer(&chan->adapter, i2c_address, 0, + ret = i2c_smbus_xfer(nouveau_i2c_adapter(chan), i2c_address, 0, I2C_SMBUS_WRITE, reg, I2C_SMBUS_BYTE_DATA, &val); if (ret < 0) { @@ -1241,7 +1241,7 @@ init_zm_i2c_byte(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) uint8_t i2c_index = bios->data[offset + 1]; uint8_t i2c_address = bios->data[offset + 2] >> 1; uint8_t count = bios->data[offset + 3]; - struct nouveau_i2c_chan *chan; + struct nouveau_i2c_port *chan; int len = 4 + count * 2; int ret, i; @@ -1270,7 +1270,7 @@ init_zm_i2c_byte(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) if (!bios->execute) continue; - ret = i2c_smbus_xfer(&chan->adapter, i2c_address, 0, + ret = i2c_smbus_xfer(nouveau_i2c_adapter(chan), i2c_address, 0, I2C_SMBUS_WRITE, reg, I2C_SMBUS_BYTE_DATA, &val); if (ret < 0) { @@ -1304,7 +1304,7 @@ init_zm_i2c(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) uint8_t i2c_address = bios->data[offset + 2] >> 1; uint8_t count = bios->data[offset + 3]; int len = 4 + count; - struct nouveau_i2c_chan *chan; + struct nouveau_i2c_port *chan; struct i2c_msg msg; uint8_t data[256]; int ret, i; @@ -1333,7 +1333,7 @@ init_zm_i2c(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) msg.flags = 0; msg.len = count; msg.buf = data; - ret = i2c_transfer(&chan->adapter, &msg, 1); + ret = i2c_transfer(nouveau_i2c_adapter(chan), &msg, 1); if (ret != 1) { NV_ERROR(dev, "0x%04X: i2c wr fail: %d\n", offset, ret); return len; @@ -1769,7 +1769,7 @@ init_i2c_if(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) uint8_t reg = bios->data[offset + 3]; uint8_t mask = bios->data[offset + 4]; uint8_t data = bios->data[offset + 5]; - struct nouveau_i2c_chan *chan; + struct nouveau_i2c_port *chan; union i2c_smbus_data val; int ret; @@ -1782,7 +1782,7 @@ init_i2c_if(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) if (!chan) return -ENODEV; - ret = i2c_smbus_xfer(&chan->adapter, i2c_address, 0, + ret = i2c_smbus_xfer(nouveau_i2c_adapter(chan), i2c_address, 0, I2C_SMBUS_READ, reg, I2C_SMBUS_BYTE_DATA, &val); if (ret < 0) { @@ -3167,7 +3167,7 @@ init_auxch(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) */ struct drm_device *dev = bios->dev; - struct nouveau_i2c_chan *auxch; + struct nouveau_i2c_port *auxch; uint32_t addr = ROM32(bios->data[offset + 1]); uint8_t count = bios->data[offset + 5]; int len = 6 + count * 2; @@ -3192,7 +3192,7 @@ init_auxch(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) for (i = 0; i < count; i++, offset += 2) { uint8_t data; - ret = nouveau_dp_auxch(auxch, 9, addr, &data, 1); + ret = auxch_rd(dev, auxch, addr, &data, 1); if (ret) { NV_ERROR(dev, "INIT_AUXCH: rd auxch fail %d\n", ret); return len; @@ -3201,7 +3201,7 @@ init_auxch(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) data &= bios->data[offset + 0]; data |= bios->data[offset + 1]; - ret = nouveau_dp_auxch(auxch, 8, addr, &data, 1); + ret = auxch_wr(dev, auxch, addr, &data, 1); if (ret) { NV_ERROR(dev, "INIT_AUXCH: wr auxch fail %d\n", ret); return len; @@ -3226,7 +3226,7 @@ init_zm_auxch(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) */ struct drm_device *dev = bios->dev; - struct nouveau_i2c_chan *auxch; + struct nouveau_i2c_port *auxch; uint32_t addr = ROM32(bios->data[offset + 1]); uint8_t count = bios->data[offset + 5]; int len = 6 + count; @@ -3249,7 +3249,7 @@ init_zm_auxch(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) offset += 6; for (i = 0; i < count; i++, offset++) { - ret = nouveau_dp_auxch(auxch, 8, addr, &bios->data[offset], 1); + ret = auxch_wr(dev, auxch, addr, &bios->data[offset], 1); if (ret) { NV_ERROR(dev, "INIT_ZM_AUXCH: wr auxch fail %d\n", ret); return len; @@ -3285,7 +3285,7 @@ init_i2c_long_if(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) uint8_t reghi = bios->data[offset + 4]; uint8_t mask = bios->data[offset + 5]; uint8_t data = bios->data[offset + 6]; - struct nouveau_i2c_chan *chan; + struct nouveau_i2c_port *chan; uint8_t buf0[2] = { reghi, reglo }; uint8_t buf1[1]; struct i2c_msg msg[2] = { @@ -3304,7 +3304,7 @@ init_i2c_long_if(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) return -ENODEV; - ret = i2c_transfer(&chan->adapter, msg, 2); + ret = i2c_transfer(nouveau_i2c_adapter(chan), msg, 2); if (ret < 0) { BIOSLOG(bios, "0x%04X: I2CReg: 0x%02X:0x%02X, Value: [no device], " "Mask: 0x%02X, Data: 0x%02X\n", @@ -6270,10 +6270,6 @@ nouveau_bios_init(struct drm_device *dev) if (ret) return ret; - ret = nouveau_i2c_init(dev); - if (ret) - return ret; - ret = nouveau_mxm_init(dev); if (ret) return ret; @@ -6318,8 +6314,5 @@ nouveau_bios_init(struct drm_device *dev) void nouveau_bios_takedown(struct drm_device *dev) { - struct drm_nouveau_private *dev_priv = dev->dev_private; - nouveau_mxm_fini(dev); - nouveau_i2c_fini(dev); } diff --git a/drivers/gpu/drm/nouveau/nouveau_bios.h b/drivers/gpu/drm/nouveau/nouveau_bios.h index b4529a0b35aa..52fce11e9d26 100644 --- a/drivers/gpu/drm/nouveau/nouveau_bios.h +++ b/drivers/gpu/drm/nouveau/nouveau_bios.h @@ -25,7 +25,6 @@ #define __NOUVEAU_BIOS_H__ #include "nvreg.h" -#include #define DCB_MAX_NUM_ENTRIES 16 #define DCB_MAX_NUM_I2C_ENTRIES 16 diff --git a/drivers/gpu/drm/nouveau/nouveau_compat.c b/drivers/gpu/drm/nouveau/nouveau_compat.c index 81fc8494e767..76582b0a9df8 100644 --- a/drivers/gpu/drm/nouveau/nouveau_compat.c +++ b/drivers/gpu/drm/nouveau/nouveau_compat.c @@ -3,6 +3,7 @@ #include #include +#include void *nouveau_newpriv(struct drm_device *); @@ -130,3 +131,52 @@ nouveau_gpio_isr_del(struct drm_device *dev, int idx, u8 tag, u8 line, 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); +} diff --git a/drivers/gpu/drm/nouveau/nouveau_compat.h b/drivers/gpu/drm/nouveau/nouveau_compat.h index f1143c362db6..9b3298bfe4ed 100644 --- a/drivers/gpu/drm/nouveau/nouveau_compat.h +++ b/drivers/gpu/drm/nouveau/nouveau_compat.h @@ -20,4 +20,17 @@ 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); + + #endif diff --git a/drivers/gpu/drm/nouveau/nouveau_connector.c b/drivers/gpu/drm/nouveau/nouveau_connector.c index cbf8348ca224..f9cc3b386065 100644 --- a/drivers/gpu/drm/nouveau/nouveau_connector.c +++ b/drivers/gpu/drm/nouveau/nouveau_connector.c @@ -105,7 +105,7 @@ nouveau_connector_destroy(struct drm_connector *connector) kfree(connector); } -static struct nouveau_i2c_chan * +static struct nouveau_i2c_port * nouveau_connector_ddc_detect(struct drm_connector *connector, struct nouveau_encoder **pnv_encoder) { @@ -113,7 +113,7 @@ nouveau_connector_ddc_detect(struct drm_connector *connector, int i; for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++) { - struct nouveau_i2c_chan *i2c = NULL; + struct nouveau_i2c_port *i2c = NULL; struct nouveau_encoder *nv_encoder; struct drm_mode_object *obj; int id; @@ -217,7 +217,7 @@ nouveau_connector_detect(struct drm_connector *connector, bool force) struct nouveau_connector *nv_connector = nouveau_connector(connector); struct nouveau_encoder *nv_encoder = NULL; struct nouveau_encoder *nv_partner; - struct nouveau_i2c_chan *i2c; + struct nouveau_i2c_port *i2c; int type; /* Cleanup the previous EDID block. */ @@ -229,7 +229,7 @@ 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, &i2c->adapter); + nv_connector->edid = drm_get_edid(connector, nouveau_i2c_adapter(i2c)); drm_mode_connector_update_edid_property(connector, nv_connector->edid); if (!nv_connector->edid) { diff --git a/drivers/gpu/drm/nouveau/nouveau_connector.h b/drivers/gpu/drm/nouveau/nouveau_connector.h index bb0faf9f5d1e..9503cfa0492c 100644 --- a/drivers/gpu/drm/nouveau/nouveau_connector.h +++ b/drivers/gpu/drm/nouveau/nouveau_connector.h @@ -28,7 +28,8 @@ #define __NOUVEAU_CONNECTOR_H__ #include "drm_edid.h" -#include + +struct nouveau_i2c_port; enum nouveau_underscan_type { UNDERSCAN_OFF, diff --git a/drivers/gpu/drm/nouveau/nouveau_dp.c b/drivers/gpu/drm/nouveau/nouveau_dp.c index 63c0e827c302..9e18b35803a8 100644 --- a/drivers/gpu/drm/nouveau/nouveau_dp.c +++ b/drivers/gpu/drm/nouveau/nouveau_dp.c @@ -23,143 +23,13 @@ */ #include "drmP.h" +#include "drm_dp_helper.h" #include "nouveau_drv.h" -#include #include "nouveau_connector.h" #include "nouveau_encoder.h" #include "nouveau_crtc.h" -/****************************************************************************** - * aux channel util functions - *****************************************************************************/ -#define AUX_DBG(fmt, args...) do { \ - if (nouveau_reg_debug & NOUVEAU_REG_DEBUG_AUXCH) { \ - NV_PRINTK(KERN_DEBUG, dev, "AUXCH(%d): " fmt, ch, ##args); \ - } \ -} while (0) -#define AUX_ERR(fmt, args...) NV_ERROR(dev, "AUXCH(%d): " fmt, ch, ##args) - -static void -auxch_fini(struct drm_device *dev, int ch) -{ - nv_mask(dev, 0x00e4e4 + (ch * 0x50), 0x00310000, 0x00000000); -} - -static int -auxch_init(struct drm_device *dev, int ch) -{ - const u32 unksel = 1; /* nfi which to use, or if it matters.. */ - const u32 ureq = unksel ? 0x00100000 : 0x00200000; - const u32 urep = unksel ? 0x01000000 : 0x02000000; - u32 ctrl, timeout; - - /* wait up to 1ms for any previous transaction to be done... */ - timeout = 1000; - do { - ctrl = nv_rd32(dev, 0x00e4e4 + (ch * 0x50)); - udelay(1); - if (!timeout--) { - AUX_ERR("begin idle timeout 0x%08x", ctrl); - return -EBUSY; - } - } while (ctrl & 0x03010000); - - /* set some magic, and wait up to 1ms for it to appear */ - nv_mask(dev, 0x00e4e4 + (ch * 0x50), 0x00300000, ureq); - timeout = 1000; - do { - ctrl = nv_rd32(dev, 0x00e4e4 + (ch * 0x50)); - udelay(1); - if (!timeout--) { - AUX_ERR("magic wait 0x%08x\n", ctrl); - auxch_fini(dev, ch); - return -EBUSY; - } - } while ((ctrl & 0x03000000) != urep); - - return 0; -} - -static int -auxch_tx(struct drm_device *dev, int ch, u8 type, u32 addr, u8 *data, u8 size) -{ - u32 ctrl, stat, timeout, retries; - u32 xbuf[4] = {}; - int ret, i; - - AUX_DBG("%d: 0x%08x %d\n", type, addr, size); - - ret = auxch_init(dev, ch); - if (ret) - goto out; - - stat = nv_rd32(dev, 0x00e4e8 + (ch * 0x50)); - if (!(stat & 0x10000000)) { - AUX_DBG("sink not detected\n"); - ret = -ENXIO; - goto out; - } - - if (!(type & 1)) { - memcpy(xbuf, data, size); - for (i = 0; i < 16; i += 4) { - AUX_DBG("wr 0x%08x\n", xbuf[i / 4]); - nv_wr32(dev, 0x00e4c0 + (ch * 0x50) + i, xbuf[i / 4]); - } - } - - ctrl = nv_rd32(dev, 0x00e4e4 + (ch * 0x50)); - ctrl &= ~0x0001f0ff; - ctrl |= type << 12; - ctrl |= size - 1; - nv_wr32(dev, 0x00e4e0 + (ch * 0x50), addr); - - /* retry transaction a number of times on failure... */ - ret = -EREMOTEIO; - for (retries = 0; retries < 32; retries++) { - /* reset, and delay a while if this is a retry */ - nv_wr32(dev, 0x00e4e4 + (ch * 0x50), 0x80000000 | ctrl); - nv_wr32(dev, 0x00e4e4 + (ch * 0x50), 0x00000000 | ctrl); - if (retries) - udelay(400); - - /* transaction request, wait up to 1ms for it to complete */ - nv_wr32(dev, 0x00e4e4 + (ch * 0x50), 0x00010000 | ctrl); - - timeout = 1000; - do { - ctrl = nv_rd32(dev, 0x00e4e4 + (ch * 0x50)); - udelay(1); - if (!timeout--) { - AUX_ERR("tx req timeout 0x%08x\n", ctrl); - goto out; - } - } while (ctrl & 0x00010000); - - /* read status, and check if transaction completed ok */ - stat = nv_mask(dev, 0x00e4e8 + (ch * 0x50), 0, 0); - if (!(stat & 0x000f0f00)) { - ret = 0; - break; - } - - AUX_DBG("%02d 0x%08x 0x%08x\n", retries, ctrl, stat); - } - - if (type & 1) { - for (i = 0; i < 16; i += 4) { - xbuf[i / 4] = nv_rd32(dev, 0x00e4d0 + (ch * 0x50) + i); - AUX_DBG("rd 0x%08x\n", xbuf[i / 4]); - } - memcpy(data, xbuf, size); - } - -out: - auxch_fini(dev, ch); - return ret; -} - u8 * nouveau_dp_bios_data(struct drm_device *dev, struct dcb_entry *dcb, u8 **entry) { @@ -208,9 +78,9 @@ nouveau_dp_bios_data(struct drm_device *dev, struct dcb_entry *dcb, u8 **entry) * link training *****************************************************************************/ struct dp_state { + struct nouveau_i2c_port *auxch; struct dp_train_func *func; struct dcb_entry *dcb; - int auxch; int crtc; u8 *dpcd; int link_nr; @@ -236,7 +106,7 @@ 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_tx(dev, dp->auxch, 8, DP_LINK_BW_SET, sink, 2); + auxch_wr(dev, dp->auxch, DP_LINK_BW_SET, sink, 2); } static void @@ -248,10 +118,10 @@ dp_set_training_pattern(struct drm_device *dev, struct dp_state *dp, u8 pattern) dp->func->train_set(dev, dp->dcb, pattern); - auxch_tx(dev, dp->auxch, 9, DP_TRAINING_PATTERN_SET, &sink_tp, 1); + auxch_rd(dev, dp->auxch, DP_TRAINING_PATTERN_SET, &sink_tp, 1); sink_tp &= ~DP_TRAINING_PATTERN_MASK; sink_tp |= pattern; - auxch_tx(dev, dp->auxch, 8, DP_TRAINING_PATTERN_SET, &sink_tp, 1); + auxch_wr(dev, dp->auxch, DP_TRAINING_PATTERN_SET, &sink_tp, 1); } static int @@ -274,7 +144,7 @@ dp_link_train_commit(struct drm_device *dev, struct dp_state *dp) dp->func->train_adj(dev, dp->dcb, i, lvsw, lpre); } - return auxch_tx(dev, dp->auxch, 8, DP_TRAINING_LANE0_SET, dp->conf, 4); + return auxch_wr(dev, dp->auxch, DP_TRAINING_LANE0_SET, dp->conf, 4); } static int @@ -284,7 +154,7 @@ dp_link_train_update(struct drm_device *dev, struct dp_state *dp, u32 delay) udelay(delay); - ret = auxch_tx(dev, dp->auxch, 9, DP_LANE0_1_STATUS, dp->stat, 6); + ret = auxch_rd(dev, dp->auxch, DP_LANE0_1_STATUS, dp->stat, 6); if (ret) return ret; @@ -417,19 +287,17 @@ 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_i2c_chan *auxch; const u32 bw_list[] = { 270000, 162000, 0 }; const u32 *link_bw = bw_list; struct dp_state dp; - auxch = nouveau_i2c_find(dev, nv_encoder->dcb->i2c_index); - if (!auxch) + dp.auxch = nouveau_i2c_find(dev, nv_encoder->dcb->i2c_index); + if (!dp.auxch) return false; dp.func = func; dp.dcb = nv_encoder->dcb; dp.crtc = nv_crtc->index; - dp.auxch = auxch->drive; dp.dpcd = nv_encoder->dp.dpcd; /* adjust required bandwidth for 8B/10B coding overhead */ @@ -491,7 +359,7 @@ 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_i2c_chan *auxch; + struct nouveau_i2c_port *auxch; u8 status; auxch = nouveau_i2c_find(encoder->dev, nv_encoder->dcb->i2c_index); @@ -503,14 +371,14 @@ nouveau_dp_dpms(struct drm_encoder *encoder, int mode, u32 datarate, else status = DP_SET_POWER_D3; - nouveau_dp_auxch(auxch, 8, DP_SET_POWER, &status, 1); + auxch_wr(encoder->dev, auxch, DP_SET_POWER, &status, 1); if (mode == DRM_MODE_DPMS_ON) nouveau_dp_link_train(encoder, datarate, func); } static void -nouveau_dp_probe_oui(struct drm_device *dev, struct nouveau_i2c_chan *auxch, +nouveau_dp_probe_oui(struct drm_device *dev, struct nouveau_i2c_port *auxch, u8 *dpcd) { u8 buf[3]; @@ -518,11 +386,11 @@ nouveau_dp_probe_oui(struct drm_device *dev, struct nouveau_i2c_chan *auxch, if (!(dpcd[DP_DOWN_STREAM_PORT_COUNT] & DP_OUI_SUPPORT)) return; - if (!auxch_tx(dev, auxch->drive, 9, DP_SINK_OUI, buf, 3)) + if (!auxch_rd(dev, auxch, DP_SINK_OUI, buf, 3)) NV_DEBUG_KMS(dev, "Sink OUI: %02hx%02hx%02hx\n", buf[0], buf[1], buf[2]); - if (!auxch_tx(dev, auxch->drive, 9, DP_BRANCH_OUI, buf, 3)) + if (!auxch_rd(dev, auxch, DP_BRANCH_OUI, buf, 3)) NV_DEBUG_KMS(dev, "Branch OUI: %02hx%02hx%02hx\n", buf[0], buf[1], buf[2]); @@ -533,7 +401,7 @@ nouveau_dp_detect(struct drm_encoder *encoder) { struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); struct drm_device *dev = encoder->dev; - struct nouveau_i2c_chan *auxch; + struct nouveau_i2c_port *auxch; u8 *dpcd = nv_encoder->dp.dpcd; int ret; @@ -541,7 +409,7 @@ nouveau_dp_detect(struct drm_encoder *encoder) if (!auxch) return false; - ret = auxch_tx(dev, auxch->drive, 9, DP_DPCD_REV, dpcd, 8); + ret = auxch_rd(dev, auxch, DP_DPCD_REV, dpcd, 8); if (ret) return false; @@ -566,58 +434,3 @@ nouveau_dp_detect(struct drm_encoder *encoder) return true; } - -int -nouveau_dp_auxch(struct nouveau_i2c_chan *auxch, int cmd, int addr, - uint8_t *data, int data_nr) -{ - return auxch_tx(auxch->dev, auxch->drive, cmd, addr, data, data_nr); -} - -static int -nouveau_dp_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num) -{ - struct nouveau_i2c_chan *auxch = (struct nouveau_i2c_chan *)adap; - struct i2c_msg *msg = msgs; - int ret, mcnt = num; - - while (mcnt--) { - u8 remaining = msg->len; - u8 *ptr = msg->buf; - - while (remaining) { - u8 cnt = (remaining > 16) ? 16 : remaining; - u8 cmd; - - if (msg->flags & I2C_M_RD) - cmd = AUX_I2C_READ; - else - cmd = AUX_I2C_WRITE; - - if (mcnt || remaining > 16) - cmd |= AUX_I2C_MOT; - - ret = nouveau_dp_auxch(auxch, cmd, msg->addr, ptr, cnt); - if (ret < 0) - return ret; - - ptr += cnt; - remaining -= cnt; - } - - msg++; - } - - return num; -} - -static u32 -nouveau_dp_i2c_func(struct i2c_adapter *adap) -{ - return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL; -} - -const struct i2c_algorithm nouveau_dp_i2c_algo = { - .master_xfer = nouveau_dp_i2c_xfer, - .functionality = nouveau_dp_i2c_func -}; diff --git a/drivers/gpu/drm/nouveau/nouveau_encoder.h b/drivers/gpu/drm/nouveau/nouveau_encoder.h index 3dc14a3dcc4c..1e79ee5fb89e 100644 --- a/drivers/gpu/drm/nouveau/nouveau_encoder.h +++ b/drivers/gpu/drm/nouveau/nouveau_encoder.h @@ -32,6 +32,8 @@ #define NV_DPMS_CLEARED 0x80 +struct nouveau_i2c_port; + struct dp_train_func { void (*link_set)(struct drm_device *, struct dcb_entry *, int crtc, int nr, u32 bw, bool enhframe); @@ -87,8 +89,6 @@ get_slave_funcs(struct drm_encoder *enc) } /* nouveau_dp.c */ -int nouveau_dp_auxch(struct nouveau_i2c_chan *auxch, int cmd, int addr, - uint8_t *data, int data_nr); bool nouveau_dp_detect(struct drm_encoder *); void nouveau_dp_dpms(struct drm_encoder *, int mode, u32 datarate, struct dp_train_func *); diff --git a/drivers/gpu/drm/nouveau/nouveau_mxm.c b/drivers/gpu/drm/nouveau/nouveau_mxm.c index b2b326b83edd..7ca129d55839 100644 --- a/drivers/gpu/drm/nouveau/nouveau_mxm.c +++ b/drivers/gpu/drm/nouveau/nouveau_mxm.c @@ -471,7 +471,7 @@ mxm_dcb_sanitise(struct drm_device *dev) } static bool -mxm_shadow_rom_fetch(struct nouveau_i2c_chan *i2c, u8 addr, +mxm_shadow_rom_fetch(struct nouveau_i2c_port *i2c, u8 addr, u8 offset, u8 size, u8 *data) { struct i2c_msg msgs[] = { @@ -479,14 +479,14 @@ mxm_shadow_rom_fetch(struct nouveau_i2c_chan *i2c, u8 addr, { .addr = addr, .flags = I2C_M_RD, .len = size, .buf = data, }, }; - return i2c_transfer(&i2c->adapter, msgs, 2) == 2; + return i2c_transfer(nouveau_i2c_adapter(i2c), msgs, 2) == 2; } static bool mxm_shadow_rom(struct drm_device *dev, u8 version) { struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_i2c_chan *i2c = NULL; + struct nouveau_i2c_port *i2c = NULL; u8 i2cidx, mxms[6], addr, size; i2cidx = mxm_ddc_map(dev, 1 /* LVDS_DDC */) & 0x0f; diff --git a/drivers/gpu/drm/nouveau/nouveau_temp.c b/drivers/gpu/drm/nouveau/nouveau_temp.c index 0f5a30160556..d00b9012a8fd 100644 --- a/drivers/gpu/drm/nouveau/nouveau_temp.c +++ b/drivers/gpu/drm/nouveau/nouveau_temp.c @@ -264,14 +264,14 @@ nouveau_temp_safety_checks(struct drm_device *dev) } static bool -probe_monitoring_device(struct nouveau_i2c_chan *i2c, +probe_monitoring_device(struct nouveau_i2c_port *i2c, struct i2c_board_info *info) { struct i2c_client *client; request_module("%s%s", I2C_MODULE_PREFIX, info->type); - client = i2c_new_device(&i2c->adapter, info); + client = i2c_new_device(nouveau_i2c_adapter(i2c), info); if (!client) return false; @@ -296,7 +296,7 @@ nouveau_temp_probe_i2c(struct drm_device *dev) }; nouveau_i2c_identify(dev, "monitoring device", info, - probe_monitoring_device, NV_I2C_DEFAULT(0)); + probe_monitoring_device, 0x80); //NV_I2C_DEFAULT(0)); } void diff --git a/drivers/gpu/drm/nouveau/nv04_dfp.c b/drivers/gpu/drm/nouveau/nv04_dfp.c index c2675623b7cd..c9835b9bd63d 100644 --- a/drivers/gpu/drm/nouveau/nv04_dfp.c +++ b/drivers/gpu/drm/nouveau/nv04_dfp.c @@ -624,7 +624,7 @@ static void nv04_tmds_slave_init(struct drm_encoder *encoder) { struct drm_device *dev = encoder->dev; struct dcb_entry *dcb = nouveau_encoder(encoder)->dcb; - struct nouveau_i2c_chan *i2c = nouveau_i2c_find(dev, 2); + struct nouveau_i2c_port *i2c = nouveau_i2c_find(dev, 2); struct i2c_board_info info[] = { { .type = "sil164", @@ -646,7 +646,7 @@ static void nv04_tmds_slave_init(struct drm_encoder *encoder) return; drm_i2c_encoder_init(dev, to_encoder_slave(encoder), - &i2c->adapter, &info[type]); + nouveau_i2c_adapter(i2c), &info[type]); } static const struct drm_encoder_helper_funcs nv04_lvds_helper_funcs = { diff --git a/drivers/gpu/drm/nouveau/nv04_tv.c b/drivers/gpu/drm/nouveau/nv04_tv.c index 3eb605ddfd03..3d7dd22879be 100644 --- a/drivers/gpu/drm/nouveau/nv04_tv.c +++ b/drivers/gpu/drm/nouveau/nv04_tv.c @@ -188,7 +188,7 @@ nv04_tv_create(struct drm_connector *connector, struct dcb_entry *entry) struct drm_device *dev = connector->dev; struct drm_encoder_helper_funcs *hfuncs; struct drm_encoder_slave_funcs *sfuncs; - struct nouveau_i2c_chan *i2c = + struct nouveau_i2c_port *i2c = nouveau_i2c_find(dev, entry->i2c_index); int type, ret; @@ -221,7 +221,7 @@ nv04_tv_create(struct drm_connector *connector, struct dcb_entry *entry) /* Run the slave-specific initialization */ ret = drm_i2c_encoder_init(dev, to_encoder_slave(encoder), - &i2c->adapter, &nv04_tv_encoder_info[type]); + nouveau_i2c_adapter(i2c), &nv04_tv_encoder_info[type]); if (ret < 0) goto fail_cleanup; -- cgit v1.2.3 From cb75d97e9c77743ecfcc43375be135a55a4d9b25 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Wed, 11 Jul 2012 10:44:20 +1000 Subject: drm/nouveau: implement devinit subdev, and new init table parser v2: - make sure not to execute display scripts unless resuming Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/Makefile | 10 + .../drm/nouveau/core/include/subdev/bios/conn.h | 27 + .../gpu/drm/nouveau/core/include/subdev/bios/dcb.h | 73 +- .../gpu/drm/nouveau/core/include/subdev/bios/dp.h | 8 + .../drm/nouveau/core/include/subdev/bios/init.h | 21 + .../gpu/drm/nouveau/core/include/subdev/devinit.h | 40 + drivers/gpu/drm/nouveau/core/subdev/bios/conn.c | 55 + drivers/gpu/drm/nouveau/core/subdev/bios/dp.c | 76 + drivers/gpu/drm/nouveau/core/subdev/bios/init.c | 2120 ++++++++++++ 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 | 9 + drivers/gpu/drm/nouveau/core/subdev/device/nve0.c | 3 + drivers/gpu/drm/nouveau/core/subdev/devinit/base.c | 69 + .../gpu/drm/nouveau/core/subdev/devinit/fbmem.h | 98 + drivers/gpu/drm/nouveau/core/subdev/devinit/nv04.c | 189 ++ drivers/gpu/drm/nouveau/core/subdev/devinit/nv05.c | 159 + drivers/gpu/drm/nouveau/core/subdev/devinit/nv10.c | 124 + drivers/gpu/drm/nouveau/core/subdev/devinit/nv1a.c | 58 + drivers/gpu/drm/nouveau/core/subdev/devinit/nv20.c | 96 + drivers/gpu/drm/nouveau/core/subdev/devinit/nv50.c | 87 + drivers/gpu/drm/nouveau/nouveau_agp.c | 72 +- drivers/gpu/drm/nouveau/nouveau_agp.h | 8 +- drivers/gpu/drm/nouveau/nouveau_backlight.c | 4 +- drivers/gpu/drm/nouveau/nouveau_bios.c | 3535 +------------------- drivers/gpu/drm/nouveau/nouveau_bios.h | 64 +- drivers/gpu/drm/nouveau/nouveau_compat.c | 38 + drivers/gpu/drm/nouveau/nouveau_compat.h | 6 + drivers/gpu/drm/nouveau/nouveau_connector.c | 86 +- drivers/gpu/drm/nouveau/nouveau_dp.c | 4 +- drivers/gpu/drm/nouveau/nouveau_drm.c | 36 + drivers/gpu/drm/nouveau/nouveau_drm.h | 10 + drivers/gpu/drm/nouveau/nouveau_drv.c | 7 - drivers/gpu/drm/nouveau/nouveau_drv.h | 23 +- drivers/gpu/drm/nouveau/nouveau_encoder.h | 14 +- drivers/gpu/drm/nouveau/nouveau_hw.h | 4 +- drivers/gpu/drm/nouveau/nouveau_mem.c | 6 +- drivers/gpu/drm/nouveau/nouveau_mxm.c | 4 +- drivers/gpu/drm/nouveau/nouveau_state.c | 4 - drivers/gpu/drm/nouveau/nv04_crtc.c | 10 +- drivers/gpu/drm/nouveau/nv04_dac.c | 26 +- drivers/gpu/drm/nouveau/nv04_dfp.c | 46 +- drivers/gpu/drm/nouveau/nv04_display.c | 76 +- drivers/gpu/drm/nouveau/nv04_tv.c | 2 +- drivers/gpu/drm/nouveau/nv17_tv.c | 12 +- drivers/gpu/drm/nouveau/nv50_dac.c | 6 +- drivers/gpu/drm/nouveau/nv50_display.c | 128 +- drivers/gpu/drm/nouveau/nv50_display.h | 2 +- drivers/gpu/drm/nouveau/nv50_sor.c | 30 +- drivers/gpu/drm/nouveau/nvd0_display.c | 70 +- 54 files changed, 3796 insertions(+), 3914 deletions(-) create mode 100644 drivers/gpu/drm/nouveau/core/include/subdev/bios/conn.h create mode 100644 drivers/gpu/drm/nouveau/core/include/subdev/bios/dp.h create mode 100644 drivers/gpu/drm/nouveau/core/include/subdev/bios/init.h create mode 100644 drivers/gpu/drm/nouveau/core/include/subdev/devinit.h create mode 100644 drivers/gpu/drm/nouveau/core/subdev/bios/conn.c create mode 100644 drivers/gpu/drm/nouveau/core/subdev/bios/dp.c create mode 100644 drivers/gpu/drm/nouveau/core/subdev/bios/init.c create mode 100644 drivers/gpu/drm/nouveau/core/subdev/devinit/base.c create mode 100644 drivers/gpu/drm/nouveau/core/subdev/devinit/fbmem.h create mode 100644 drivers/gpu/drm/nouveau/core/subdev/devinit/nv04.c create mode 100644 drivers/gpu/drm/nouveau/core/subdev/devinit/nv05.c create mode 100644 drivers/gpu/drm/nouveau/core/subdev/devinit/nv10.c create mode 100644 drivers/gpu/drm/nouveau/core/subdev/devinit/nv1a.c create mode 100644 drivers/gpu/drm/nouveau/core/subdev/devinit/nv20.c create mode 100644 drivers/gpu/drm/nouveau/core/subdev/devinit/nv50.c (limited to 'drivers/gpu/drm/nouveau/nouveau_dp.c') diff --git a/drivers/gpu/drm/nouveau/Makefile b/drivers/gpu/drm/nouveau/Makefile index 2574fd35122a..522bc1c1e4d0 100644 --- a/drivers/gpu/drm/nouveau/Makefile +++ b/drivers/gpu/drm/nouveau/Makefile @@ -20,9 +20,12 @@ nouveau-y += core/core/subdev.o nouveau-y += core/subdev/bios/base.o nouveau-y += core/subdev/bios/bit.o +nouveau-y += core/subdev/bios/conn.o nouveau-y += core/subdev/bios/dcb.o +nouveau-y += core/subdev/bios/dp.o nouveau-y += core/subdev/bios/gpio.o nouveau-y += core/subdev/bios/i2c.o +nouveau-y += core/subdev/bios/init.o nouveau-y += core/subdev/bios/pll.o nouveau-y += core/subdev/clock/nv04.o nouveau-y += core/subdev/clock/nv40.o @@ -40,6 +43,13 @@ nouveau-y += core/subdev/device/nv40.o nouveau-y += core/subdev/device/nv50.o nouveau-y += core/subdev/device/nvc0.o nouveau-y += core/subdev/device/nve0.o +nouveau-y += core/subdev/devinit/base.o +nouveau-y += core/subdev/devinit/nv04.o +nouveau-y += core/subdev/devinit/nv05.o +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/nv04.o nouveau-y += core/subdev/fb/nv10.o nouveau-y += core/subdev/fb/nv20.o diff --git a/drivers/gpu/drm/nouveau/core/include/subdev/bios/conn.h b/drivers/gpu/drm/nouveau/core/include/subdev/bios/conn.h new file mode 100644 index 000000000000..c1270548fd0d --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/include/subdev/bios/conn.h @@ -0,0 +1,27 @@ +#ifndef __NVBIOS_CONN_H__ +#define __NVBIOS_CONN_H__ + +enum dcb_connector_type { + DCB_CONNECTOR_VGA = 0x00, + DCB_CONNECTOR_TV_0 = 0x10, + DCB_CONNECTOR_TV_1 = 0x11, + DCB_CONNECTOR_TV_3 = 0x13, + DCB_CONNECTOR_DVI_I = 0x30, + DCB_CONNECTOR_DVI_D = 0x31, + DCB_CONNECTOR_DMS59_0 = 0x38, + DCB_CONNECTOR_DMS59_1 = 0x39, + DCB_CONNECTOR_LVDS = 0x40, + DCB_CONNECTOR_LVDS_SPWG = 0x41, + DCB_CONNECTOR_DP = 0x46, + DCB_CONNECTOR_eDP = 0x47, + DCB_CONNECTOR_HDMI_0 = 0x60, + DCB_CONNECTOR_HDMI_1 = 0x61, + DCB_CONNECTOR_DMS59_DP0 = 0x64, + DCB_CONNECTOR_DMS59_DP1 = 0x65, + DCB_CONNECTOR_NONE = 0xff +}; + +u16 dcb_conntab(struct nouveau_bios *bios, u8 *ver, u8 *hdr, u8 *cnt, u8 *len); +u16 dcb_conn(struct nouveau_bios *bios, u8 idx, u8 *ver, u8 *len); + +#endif diff --git a/drivers/gpu/drm/nouveau/core/include/subdev/bios/dcb.h b/drivers/gpu/drm/nouveau/core/include/subdev/bios/dcb.h index 7000dcf2ae95..d682fb625833 100644 --- a/drivers/gpu/drm/nouveau/core/include/subdev/bios/dcb.h +++ b/drivers/gpu/drm/nouveau/core/include/subdev/bios/dcb.h @@ -1,14 +1,56 @@ #ifndef __NVBIOS_DCB_H__ #define __NVBIOS_DCB_H__ +struct nouveau_bios; + enum dcb_output_type { DCB_OUTPUT_ANALOG = 0x0, DCB_OUTPUT_TV = 0x1, DCB_OUTPUT_TMDS = 0x2, DCB_OUTPUT_LVDS = 0x3, - DCB_OUTPUT_DP = 0x4, + DCB_OUTPUT_DP = 0x6, DCB_OUTPUT_EOL = 0xe, DCB_OUTPUT_UNUSED = 0xf, + DCB_OUTPUT_ANY = -1, +}; + +struct dcb_output { + int index; /* may not be raw dcb index if merging has happened */ + enum dcb_output_type type; + uint8_t i2c_index; + uint8_t heads; + uint8_t connector; + uint8_t bus; + uint8_t location; + uint8_t or; + bool duallink_possible; + union { + struct sor_conf { + int link; + } sorconf; + struct { + int maxfreq; + } crtconf; + struct { + struct sor_conf sor; + bool use_straps_for_mode; + bool use_acpi_for_edid; + bool use_power_scripts; + } lvdsconf; + struct { + bool has_component_output; + } tvconf; + struct { + struct sor_conf sor; + int link_nr; + int link_bw; + } dpconf; + struct { + struct sor_conf sor; + int slave_addr; + } tmdsconf; + }; + bool i2c_upper_default; }; u16 dcb_table(struct nouveau_bios *, u8 *ver, u8 *hdr, u8 *ent, u8 *len); @@ -16,4 +58,33 @@ u16 dcb_outp(struct nouveau_bios *, u8 idx, u8 *ver, u8 *len); int dcb_outp_foreach(struct nouveau_bios *, void *data, int (*exec) (struct nouveau_bios *, void *, int index, u16 entry)); + +/* BIT 'U'/'d' table encoder subtables have hashes matching them to + * a particular set of encoders. + * + * This function returns true if a particular DCB entry matches. + */ +static inline bool +dcb_hash_match(struct dcb_output *dcb, u32 hash) +{ + if ((hash & 0x000000f0) != (dcb->location << 4)) + return false; + if ((hash & 0x0000000f) != dcb->type) + return false; + if (!(hash & (dcb->or << 16))) + return false; + + switch (dcb->type) { + case DCB_OUTPUT_TMDS: + case DCB_OUTPUT_LVDS: + case DCB_OUTPUT_DP: + if (hash & 0x00c00000) { + if (!(hash & (dcb->sorconf.link << 22))) + return false; + } + default: + return true; + } +} + #endif diff --git a/drivers/gpu/drm/nouveau/core/include/subdev/bios/dp.h b/drivers/gpu/drm/nouveau/core/include/subdev/bios/dp.h new file mode 100644 index 000000000000..73b5e5d3e75a --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/include/subdev/bios/dp.h @@ -0,0 +1,8 @@ +#ifndef __NVBIOS_DP_H__ +#define __NVBIOS_DP_H__ + +u16 dp_table(struct nouveau_bios *, u8 *ver, u8 *hdr, u8 *cnt, u8 *len); +u16 dp_outp(struct nouveau_bios *, u8 idx, u8 *ver, u8 *len); +u16 dp_outp_match(struct nouveau_bios *, struct dcb_output *, u8 *ver, u8 *len); + +#endif diff --git a/drivers/gpu/drm/nouveau/core/include/subdev/bios/init.h b/drivers/gpu/drm/nouveau/core/include/subdev/bios/init.h new file mode 100644 index 000000000000..e69a8bdc6e97 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/include/subdev/bios/init.h @@ -0,0 +1,21 @@ +#ifndef __NVBIOS_INIT_H__ +#define __NVBIOS_INIT_H__ + +struct nvbios_init { + struct nouveau_subdev *subdev; + struct nouveau_bios *bios; + u16 offset; + struct dcb_output *outp; + int crtc; + + /* internal state used during parsing */ + u8 execute; + u32 nested; + u16 repeat; + u16 repend; +}; + +int nvbios_exec(struct nvbios_init *); +int nvbios_init(struct nouveau_subdev *, bool execute); + +#endif diff --git a/drivers/gpu/drm/nouveau/core/include/subdev/devinit.h b/drivers/gpu/drm/nouveau/core/include/subdev/devinit.h new file mode 100644 index 000000000000..29e4cc1f6cc0 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/include/subdev/devinit.h @@ -0,0 +1,40 @@ +#ifndef __NOUVEAU_DEVINIT_H__ +#define __NOUVEAU_DEVINIT_H__ + +#include +#include + +struct nouveau_devinit { + struct nouveau_subdev base; + bool post; + void (*meminit)(struct nouveau_devinit *); +}; + +static inline struct nouveau_devinit * +nouveau_devinit(void *obj) +{ + return (void *)nv_device(obj)->subdev[NVDEV_SUBDEV_DEVINIT]; +} + +#define nouveau_devinit_create(p,e,o,d) \ + nouveau_devinit_create_((p), (e), (o), sizeof(**d), (void **)d) +#define nouveau_devinit_destroy(p) \ + nouveau_subdev_destroy(&(p)->base) + +int nouveau_devinit_create_(struct nouveau_object *, struct nouveau_object *, + struct nouveau_oclass *, int, void **); +int nouveau_devinit_init(struct nouveau_devinit *); +int nouveau_devinit_fini(struct nouveau_devinit *, bool suspend); + +extern struct nouveau_oclass nv04_devinit_oclass; +extern struct nouveau_oclass nv05_devinit_oclass; +extern struct nouveau_oclass nv10_devinit_oclass; +extern struct nouveau_oclass nv1a_devinit_oclass; +extern struct nouveau_oclass nv20_devinit_oclass; +extern struct nouveau_oclass nv50_devinit_oclass; + +void nv04_devinit_dtor(struct nouveau_object *); +int nv04_devinit_init(struct nouveau_object *); +int nv04_devinit_fini(struct nouveau_object *, bool); + +#endif diff --git a/drivers/gpu/drm/nouveau/core/subdev/bios/conn.c b/drivers/gpu/drm/nouveau/core/subdev/bios/conn.c new file mode 100644 index 000000000000..ac4026cd315f --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/subdev/bios/conn.c @@ -0,0 +1,55 @@ +/* + * 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 + +u16 +dcb_conntab(struct nouveau_bios *bios, u8 *ver, u8 *hdr, u8 *cnt, u8 *len) +{ + u16 dcb = dcb_table(bios, ver, hdr, cnt, len); + if (dcb && *ver >= 0x30 && *hdr >= 0x16) { + u16 data = nv_ro16(bios, dcb + 0x14); + if (data) { + *ver = nv_ro08(bios, data + 0); + *hdr = nv_ro08(bios, data + 1); + *cnt = nv_ro08(bios, data + 2); + *len = nv_ro08(bios, data + 3); + return data; + } + } + return 0x0000; +} + +u16 +dcb_conn(struct nouveau_bios *bios, u8 idx, u8 *ver, u8 *len) +{ + u8 hdr, cnt; + u16 data = dcb_conntab(bios, ver, &hdr, &cnt, len); + if (data && idx < cnt) + return data + hdr + (idx * *len); + return 0x0000; +} diff --git a/drivers/gpu/drm/nouveau/core/subdev/bios/dp.c b/drivers/gpu/drm/nouveau/core/subdev/bios/dp.c new file mode 100644 index 000000000000..3cbc0f3e8d5e --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/subdev/bios/dp.c @@ -0,0 +1,76 @@ +/* + * 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/bios.h" +#include "subdev/bios/bit.h" +#include "subdev/bios/dcb.h" +#include "subdev/bios/dp.h" + +u16 +dp_table(struct nouveau_bios *bios, u8 *ver, u8 *hdr, u8 *cnt, u8 *len) +{ + struct bit_entry bit_d; + + if (!bit_entry(bios, 'd', &bit_d)) { + if (bit_d.version == 1) { + u16 data = nv_ro16(bios, bit_d.offset); + 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; + } + } + } + + return 0x0000; +} + +u16 +dp_outp(struct nouveau_bios *bios, u8 idx, u8 *ver, u8 *len) +{ + u8 hdr, cnt; + u16 table = dp_table(bios, ver, &hdr, &cnt, len); + if (table && idx < cnt) + return nv_ro16(bios, table + hdr + (idx * *len)); + return 0xffff; +} + +u16 +dp_outp_match(struct nouveau_bios *bios, struct dcb_output *outp, + u8 *ver, u8 *len) +{ + u8 idx = 0; + u16 data; + while ((data = dp_outp(bios, idx++, ver, len)) != 0xffff) { + if (data) { + u32 hash = nv_ro32(bios, data); + if (dcb_hash_match(outp, hash)) + return data; + } + } + return 0x0000; +} diff --git a/drivers/gpu/drm/nouveau/core/subdev/bios/init.c b/drivers/gpu/drm/nouveau/core/subdev/bios/init.c new file mode 100644 index 000000000000..6be8c32f6e4c --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/subdev/bios/init.c @@ -0,0 +1,2120 @@ +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define bioslog(lvl, fmt, args...) do { \ + nv_printk(init->bios, lvl, "0x%04x[%c]: "fmt, init->offset, \ + init_exec(init) ? '0' + (init->nested - 1) : ' ', ##args); \ +} while(0) +#define cont(fmt, args...) do { \ + if (nv_subdev(init->bios)->debug >= NV_DBG_TRACE) \ + printk(fmt, ##args); \ +} while(0) +#define trace(fmt, args...) bioslog(TRACE, fmt, ##args) +#define warn(fmt, args...) bioslog(WARN, fmt, ##args) +#define error(fmt, args...) bioslog(ERROR, fmt, ##args) + +/****************************************************************************** + * init parser control flow helpers + *****************************************************************************/ + +static inline bool +init_exec(struct nvbios_init *init) +{ + return (init->execute == 1) || ((init->execute & 5) == 5); +} + +static inline void +init_exec_set(struct nvbios_init *init, bool exec) +{ + if (exec) init->execute &= 0xfd; + else init->execute |= 0x02; +} + +static inline void +init_exec_inv(struct nvbios_init *init) +{ + init->execute ^= 0x02; +} + +static inline void +init_exec_force(struct nvbios_init *init, bool exec) +{ + if (exec) init->execute |= 0x04; + else init->execute &= 0xfb; +} + +/****************************************************************************** + * init parser wrappers for normal register/i2c/whatever accessors + *****************************************************************************/ + +static inline int +init_or(struct nvbios_init *init) +{ + if (init->outp) + return ffs(init->outp->or) - 1; + error("script needs OR!!\n"); + return 0; +} + +static inline int +init_link(struct nvbios_init *init) +{ + if (init->outp) + return !(init->outp->sorconf.link & 1); + error("script needs OR link\n"); + return 0; +} + +static inline int +init_crtc(struct nvbios_init *init) +{ + if (init->crtc >= 0) + return init->crtc; + error("script needs crtc\n"); + return 0; +} + +static u8 +init_conn(struct nvbios_init *init) +{ + struct nouveau_bios *bios = init->bios; + + if (init->outp) { + u8 ver, len; + u16 conn = dcb_conn(bios, init->outp->connector, &ver, &len); + if (conn) + return nv_ro08(bios, conn); + } + + error("script needs connector type\n"); + return 0x00; +} + +static inline u32 +init_nvreg(struct nvbios_init *init, u32 reg) +{ + /* C51 (at least) sometimes has the lower bits set which the VBIOS + * interprets to mean that access needs to go through certain IO + * ports instead. The NVIDIA binary driver has been seen to access + * these through the NV register address, so lets assume we can + * do the same + */ + reg &= ~0x00000003; + + /* GF8+ display scripts need register addresses mangled a bit to + * select a specific CRTC/OR + */ + if (nv_device(init->bios)->card_type >= NV_50) { + if (reg & 0x80000000) { + reg += init_crtc(init) * 0x800; + reg &= ~0x80000000; + } + + if (reg & 0x40000000) { + reg += init_or(init) * 0x800; + reg &= ~0x40000000; + if (reg & 0x20000000) { + reg += init_link(init) * 0x80; + reg &= ~0x20000000; + } + } + } + + if (reg & ~0x00fffffc) + warn("unknown bits in register 0x%08x\n", reg); + return reg; +} + +static u32 +init_rd32(struct nvbios_init *init, u32 reg) +{ + reg = init_nvreg(init, reg); + if (init_exec(init)) + return nv_rd32(init->subdev, reg); + return 0x00000000; +} + +static void +init_wr32(struct nvbios_init *init, u32 reg, u32 val) +{ + reg = init_nvreg(init, reg); + if (init_exec(init)) + nv_wr32(init->subdev, reg, val); +} + +static u32 +init_mask(struct nvbios_init *init, u32 reg, u32 mask, u32 val) +{ + reg = init_nvreg(init, reg); + if (init_exec(init)) { + u32 tmp = nv_rd32(init->subdev, reg); + nv_wr32(init->subdev, reg, (tmp & ~mask) | val); + return tmp; + } + return 0x00000000; +} + +static u8 +init_rdport(struct nvbios_init *init, u16 port) +{ + if (init_exec(init)) + return nv_rdport(init->subdev, init->crtc, port); + return 0x00; +} + +static void +init_wrport(struct nvbios_init *init, u16 port, u8 value) +{ + if (init_exec(init)) + nv_wrport(init->subdev, init->crtc, port, value); +} + +static u8 +init_rdvgai(struct nvbios_init *init, u16 port, u8 index) +{ + struct nouveau_subdev *subdev = init->subdev; + if (init_exec(init)) { + int head = init->crtc < 0 ? 0 : init->crtc; + return nv_rdvgai(subdev, head, port, index); + } + return 0x00; +} + +static void +init_wrvgai(struct nvbios_init *init, u16 port, u8 index, u8 value) +{ + /* force head 0 for updates to cr44, it only exists on first head */ + if (nv_device(init->subdev)->card_type < NV_50) { + if (port == 0x03d4 && index == 0x44) + init->crtc = 0; + } + + if (init_exec(init)) { + int head = init->crtc < 0 ? 0 : init->crtc; + nv_wrvgai(init->subdev, head, port, index, value); + } + + /* select head 1 if cr44 write selected it */ + if (nv_device(init->subdev)->card_type < NV_50) { + if (port == 0x03d4 && index == 0x44 && value == 3) + init->crtc = 1; + } +} + +static struct nouveau_i2c_port * +init_i2c(struct nvbios_init *init, int index) +{ + struct nouveau_i2c *i2c = nouveau_i2c(init->bios); + + if (index == 0xff) { + index = NV_I2C_DEFAULT(0); + if (init->outp && init->outp->i2c_upper_default) + index = NV_I2C_DEFAULT(1); + } else + if (index < 0) { + if (!init->outp) { + error("script needs output for i2c\n"); + return NULL; + } + + index = init->outp->i2c_index; + } + + return i2c->find(i2c, index); +} + +static int +init_rdi2cr(struct nvbios_init *init, u8 index, u8 addr, u8 reg) +{ + struct nouveau_i2c_port *port = init_i2c(init, index); + if (port && init_exec(init)) + return nv_rdi2cr(port, addr, reg); + return -ENODEV; +} + +static int +init_wri2cr(struct nvbios_init *init, u8 index, u8 addr, u8 reg, u8 val) +{ + struct nouveau_i2c_port *port = init_i2c(init, index); + if (port && init_exec(init)) + return nv_wri2cr(port, addr, reg, val); + return -ENODEV; +} + +static int +init_rdauxr(struct nvbios_init *init, u32 addr) +{ + struct nouveau_i2c_port *port = init_i2c(init, -1); + u8 data; + + if (port && init_exec(init)) { + int ret = nv_rdaux(port, addr, &data, 1); + if (ret) + return ret; + return data; + } + + return -ENODEV; +} + +static int +init_wrauxr(struct nvbios_init *init, u32 addr, u8 data) +{ + struct nouveau_i2c_port *port = init_i2c(init, -1); + if (port && init_exec(init)) + return nv_wraux(port, addr, &data, 1); + return -ENODEV; +} + +static void +init_prog_pll(struct nvbios_init *init, u32 id, u32 freq) +{ + struct nouveau_clock *clk = nouveau_clock(init->bios); + if (clk && clk->pll_set && init_exec(init)) { + int ret = clk->pll_set(clk, id, freq); + if (ret) + warn("failed to prog pll 0x%08x to %dkHz\n", id, freq); + } +} + +/****************************************************************************** + * parsing of bios structures that are required to execute init tables + *****************************************************************************/ + +static u16 +init_table(struct nouveau_bios *bios, u16 *len) +{ + struct bit_entry bit_I; + + if (!bit_entry(bios, 'I', &bit_I)) { + *len = bit_I.length; + return bit_I.offset; + } + + if (bmp_version(bios) >= 0x0510) { + *len = 14; + return bios->bmp_offset + 75; + } + + return 0x0000; +} + +static u16 +init_table_(struct nvbios_init *init, u16 offset, const char *name) +{ + struct nouveau_bios *bios = init->bios; + u16 len, data = init_table(bios, &len); + if (data) { + if (len >= offset + 2) { + data = nv_ro16(bios, data + offset); + if (data) + return data; + + warn("%s pointer invalid\n", name); + return 0x0000; + } + + warn("init data too short for %s pointer", name); + return 0x0000; + } + + warn("init data not found\n"); + return 0x0000; +} + +#define init_script_table(b) init_table_((b), 0x00, "script table") +#define init_macro_index_table(b) init_table_((b), 0x02, "macro index table") +#define init_macro_table(b) init_table_((b), 0x04, "macro table") +#define init_condition_table(b) init_table_((b), 0x06, "condition table") +#define init_io_condition_table(b) init_table_((b), 0x08, "io condition table") +#define init_io_flag_condition_table(b) init_table_((b), 0x0a, "io flag conditon table") +#define init_function_table(b) init_table_((b), 0x0c, "function table") +#define init_xlat_table(b) init_table_((b), 0x10, "xlat table"); + +static u16 +init_script(struct nouveau_bios *bios, int index) +{ + struct nvbios_init init = { .bios = bios }; + u16 data; + + if (bmp_version(bios) && bmp_version(bios) < 0x0510) { + if (index > 1) + return 0x0000; + + data = bios->bmp_offset + (bios->version.major < 2 ? 14 : 18); + return nv_ro16(bios, data + (index * 2)); + } + + data = init_script_table(&init); + if (data) + return nv_ro16(bios, data + (index * 2)); + + return 0x0000; +} + +static u16 +init_unknown_script(struct nouveau_bios *bios) +{ + u16 len, data = init_table(bios, &len); + if (data && len >= 16) + return nv_ro16(bios, data + 14); + return 0x0000; +} + +static u16 +init_ram_restrict_table(struct nvbios_init *init) +{ + struct nouveau_bios *bios = init->bios; + struct bit_entry bit_M; + u16 data = 0x0000; + + if (!bit_entry(bios, 'M', &bit_M)) { + if (bit_M.version == 1 && bit_M.length >= 5) + data = nv_ro16(bios, bit_M.offset + 3); + if (bit_M.version == 2 && bit_M.length >= 3) + data = nv_ro16(bios, bit_M.offset + 1); + } + + if (data == 0x0000) + warn("ram restrict table not found\n"); + return data; +} + +static u8 +init_ram_restrict_group_count(struct nvbios_init *init) +{ + struct nouveau_bios *bios = init->bios; + struct bit_entry bit_M; + + if (!bit_entry(bios, 'M', &bit_M)) { + if (bit_M.version == 1 && bit_M.length >= 5) + return nv_ro08(bios, bit_M.offset + 2); + if (bit_M.version == 2 && bit_M.length >= 3) + return nv_ro08(bios, bit_M.offset + 0); + } + + return 0x00; +} + +static u8 +init_ram_restrict(struct nvbios_init *init) +{ + u32 strap = (init_rd32(init, 0x101000) & 0x0000003c) >> 2; + u16 table = init_ram_restrict_table(init); + if (table) + return nv_ro08(init->bios, table + strap); + return 0x00; +} + +static u8 +init_xlat_(struct nvbios_init *init, u8 index, u8 offset) +{ + struct nouveau_bios *bios = init->bios; + u16 table = init_xlat_table(init); + if (table) { + u16 data = nv_ro16(bios, table + (index * 2)); + if (data) + return nv_ro08(bios, data + offset); + warn("xlat table pointer %d invalid\n", index); + } + return 0x00; +} + +/****************************************************************************** + * utility functions used by various init opcode handlers + *****************************************************************************/ + +static bool +init_condition_met(struct nvbios_init *init, u8 cond) +{ + struct nouveau_bios *bios = init->bios; + u16 table = init_condition_table(init); + if (table) { + u32 reg = nv_ro32(bios, table + (cond * 12) + 0); + u32 msk = nv_ro32(bios, table + (cond * 12) + 4); + u32 val = nv_ro32(bios, table + (cond * 12) + 8); + trace("\t[0x%02x] (R[0x%06x] & 0x%08x) == 0x%08x\n", + cond, reg, msk, val); + return (init_rd32(init, reg) & msk) == val; + } + return false; +} + +static bool +init_io_condition_met(struct nvbios_init *init, u8 cond) +{ + struct nouveau_bios *bios = init->bios; + u16 table = init_io_condition_table(init); + if (table) { + u16 port = nv_ro16(bios, table + (cond * 5) + 0); + u8 index = nv_ro08(bios, table + (cond * 5) + 2); + u8 mask = nv_ro08(bios, table + (cond * 5) + 3); + u8 value = nv_ro08(bios, table + (cond * 5) + 4); + trace("\t[0x%02x] (0x%04x[0x%02x] & 0x%02x) == 0x%02x\n", + cond, port, index, mask, value); + return (init_rdvgai(init, port, index) & mask) == value; + } + return false; +} + +static bool +init_io_flag_condition_met(struct nvbios_init *init, u8 cond) +{ + struct nouveau_bios *bios = init->bios; + u16 table = init_io_flag_condition_table(init); + if (table) { + u16 port = nv_ro16(bios, table + (cond * 9) + 0); + u8 index = nv_ro08(bios, table + (cond * 9) + 2); + u8 mask = nv_ro08(bios, table + (cond * 9) + 3); + u8 shift = nv_ro08(bios, table + (cond * 9) + 4); + u16 data = nv_ro16(bios, table + (cond * 9) + 5); + u8 dmask = nv_ro08(bios, table + (cond * 9) + 7); + u8 value = nv_ro08(bios, table + (cond * 9) + 8); + u8 ioval = (init_rdvgai(init, port, index) & mask) >> shift; + return (nv_ro08(bios, data + ioval) & dmask) == value; + } + return false; +} + +static inline u32 +init_shift(u32 data, u8 shift) +{ + if (shift < 0x80) + return data >> shift; + return data << (0x100 - shift); +} + +static u32 +init_tmds_reg(struct nvbios_init *init, u8 tmds) +{ + /* For mlv < 0x80, it is an index into a table of TMDS base addresses. + * For mlv == 0x80 use the "or" value of the dcb_entry indexed by + * CR58 for CR57 = 0 to index a table of offsets to the basic + * 0x6808b0 address. + * For mlv == 0x81 use the "or" value of the dcb_entry indexed by + * CR58 for CR57 = 0 to index a table of offsets to the basic + * 0x6808b0 address, and then flip the offset by 8. + */ + + const int pramdac_offset[13] = { + 0, 0, 0x8, 0, 0x2000, 0, 0, 0, 0x2008, 0, 0, 0, 0x2000 }; + const u32 pramdac_table[4] = { + 0x6808b0, 0x6808b8, 0x6828b0, 0x6828b8 }; + + if (tmds >= 0x80) { + if (init->outp) { + u32 dacoffset = pramdac_offset[init->outp->or]; + if (tmds == 0x81) + dacoffset ^= 8; + return 0x6808b0 + dacoffset; + } + + error("tmds opcodes need dcb\n"); + } else { + if (tmds < ARRAY_SIZE(pramdac_table)) + return pramdac_table[tmds]; + + error("tmds selector 0x%02x unknown\n", tmds); + } + + return 0; +} + +/****************************************************************************** + * init opcode handlers + *****************************************************************************/ + +/** + * init_reserved - stub for various unknown/unused single-byte opcodes + * + */ +static void +init_reserved(struct nvbios_init *init) +{ + u8 opcode = nv_ro08(init->bios, init->offset); + trace("RESERVED\t0x%02x\n", opcode); + init->offset += 1; +} + +/** + * INIT_DONE - opcode 0x71 + * + */ +static void +init_done(struct nvbios_init *init) +{ + trace("DONE\n"); + init->offset = 0x0000; +} + +/** + * INIT_IO_RESTRICT_PROG - opcode 0x32 + * + */ +static void +init_io_restrict_prog(struct nvbios_init *init) +{ + struct nouveau_bios *bios = init->bios; + u16 port = nv_ro16(bios, init->offset + 1); + u8 index = nv_ro08(bios, init->offset + 3); + u8 mask = nv_ro08(bios, init->offset + 4); + u8 shift = nv_ro08(bios, init->offset + 5); + u8 count = nv_ro08(bios, init->offset + 6); + u32 reg = nv_ro32(bios, init->offset + 7); + u8 conf, i; + + trace("IO_RESTRICT_PROG\tR[0x%06x] = " + "((0x%04x[0x%02x] & 0x%02x) >> %d) [{\n", + reg, port, index, mask, shift); + init->offset += 11; + + conf = (init_rdvgai(init, port, index) & mask) >> shift; + for (i = 0; i < count; i++) { + u32 data = nv_ro32(bios, init->offset); + + if (i == conf) { + trace("\t0x%08x *\n", data); + init_wr32(init, reg, data); + } else { + trace("\t0x%08x\n", data); + } + + init->offset += 4; + } + trace("}]\n"); +} + +/** + * INIT_REPEAT - opcode 0x33 + * + */ +static void +init_repeat(struct nvbios_init *init) +{ + struct nouveau_bios *bios = init->bios; + u8 count = nv_ro08(bios, init->offset + 1); + u16 repeat = init->repeat; + + trace("REPEAT\t0x%02x\n", count); + init->offset += 2; + + init->repeat = init->offset; + init->repend = init->offset; + while (count--) { + init->offset = init->repeat; + nvbios_exec(init); + if (count) + trace("REPEAT\t0x%02x\n", count); + } + init->offset = init->repend; + init->repeat = repeat; +} + +/** + * INIT_IO_RESTRICT_PLL - opcode 0x34 + * + */ +static void +init_io_restrict_pll(struct nvbios_init *init) +{ + struct nouveau_bios *bios = init->bios; + u16 port = nv_ro16(bios, init->offset + 1); + u8 index = nv_ro08(bios, init->offset + 3); + u8 mask = nv_ro08(bios, init->offset + 4); + u8 shift = nv_ro08(bios, init->offset + 5); + s8 iofc = nv_ro08(bios, init->offset + 6); + u8 count = nv_ro08(bios, init->offset + 7); + u32 reg = nv_ro32(bios, init->offset + 8); + u8 conf, i; + + trace("IO_RESTRICT_PLL\tR[0x%06x] =PLL= " + "((0x%04x[0x%02x] & 0x%02x) >> 0x%02x) IOFCOND 0x%02x [{\n", + reg, port, index, mask, shift, iofc); + init->offset += 12; + + conf = (init_rdvgai(init, port, index) & mask) >> shift; + for (i = 0; i < count; i++) { + u32 freq = nv_ro16(bios, init->offset) * 10; + + if (i == conf) { + trace("\t%dkHz *\n", freq); + if (iofc > 0 && init_io_flag_condition_met(init, iofc)) + freq *= 2; + init_prog_pll(init, reg, freq); + } else { + trace("\t%dkHz\n", freq); + } + + init->offset += 2; + } + trace("}]\n"); +} + +/** + * INIT_END_REPEAT - opcode 0x36 + * + */ +static void +init_end_repeat(struct nvbios_init *init) +{ + trace("END_REPEAT\n"); + init->offset += 1; + + if (init->repeat) { + init->repend = init->offset; + init->offset = 0; + } +} + +/** + * INIT_COPY - opcode 0x37 + * + */ +static void +init_copy(struct nvbios_init *init) +{ + struct nouveau_bios *bios = init->bios; + u32 reg = nv_ro32(bios, init->offset + 1); + u8 shift = nv_ro08(bios, init->offset + 5); + u8 smask = nv_ro08(bios, init->offset + 6); + u16 port = nv_ro16(bios, init->offset + 7); + u8 index = nv_ro08(bios, init->offset + 9); + u8 mask = nv_ro08(bios, init->offset + 10); + u8 data; + + trace("COPY\t0x%04x[0x%02x] &= 0x%02x |= " + "((R[0x%06x] %s 0x%02x) & 0x%02x)\n", + port, index, mask, reg, (shift & 0x80) ? "<<" : ">>", + (shift & 0x80) ? (0x100 - shift) : shift, smask); + init->offset += 11; + + data = init_rdvgai(init, port, index) & mask; + data |= init_shift(init_rd32(init, reg), shift) & smask; + init_wrvgai(init, port, index, data); +} + +/** + * INIT_NOT - opcode 0x38 + * + */ +static void +init_not(struct nvbios_init *init) +{ + trace("NOT\n"); + init->offset += 1; + init_exec_inv(init); +} + +/** + * INIT_IO_FLAG_CONDITION - opcode 0x39 + * + */ +static void +init_io_flag_condition(struct nvbios_init *init) +{ + struct nouveau_bios *bios = init->bios; + u8 cond = nv_ro08(bios, init->offset + 1); + + trace("IO_FLAG_CONDITION\t0x%02x\n", cond); + init->offset += 2; + + if (!init_io_flag_condition_met(init, cond)) + init_exec_set(init, false); +} + +/** + * INIT_DP_CONDITION - opcode 0x3a + * + */ +static void +init_dp_condition(struct nvbios_init *init) +{ + struct nouveau_bios *bios = init->bios; + u8 cond = nv_ro08(bios, init->offset + 1); + u8 unkn = nv_ro08(bios, init->offset + 2); + u8 ver, len; + u16 data; + + trace("DP_CONDITION\t0x%02x 0x%02x\n", cond, unkn); + init->offset += 3; + + switch (cond) { + case 0: + if (init_conn(init) != DCB_CONNECTOR_eDP) + init_exec_set(init, false); + break; + case 1: + case 2: + if ( init->outp && + (data = dp_outp_match(bios, init->outp, &ver, &len))) { + if (ver <= 0x40 && !(nv_ro08(bios, data + 5) & cond)) + init_exec_set(init, false); + if (ver == 0x40 && !(nv_ro08(bios, data + 4) & cond)) + init_exec_set(init, false); + break; + } + + warn("script needs dp output table data\n"); + break; + case 5: + if (!(init_rdauxr(init, 0x0d) & 1)) + init_exec_set(init, false); + break; + default: + warn("unknown dp condition 0x%02x\n", cond); + break; + } +} + +/** + * INIT_IO_MASK_OR - opcode 0x3b + * + */ +static void +init_io_mask_or(struct nvbios_init *init) +{ + struct nouveau_bios *bios = init->bios; + u8 index = nv_ro08(bios, init->offset + 1); + u8 or = init_or(init); + u8 data; + + trace("IO_MASK_OR\t0x03d4[0x%02x] &= ~(1 << 0x%02x)", index, or); + init->offset += 2; + + data = init_rdvgai(init, 0x03d4, index); + init_wrvgai(init, 0x03d4, index, data &= ~(1 << or)); +} + +/** + * INIT_IO_OR - opcode 0x3c + * + */ +static void +init_io_or(struct nvbios_init *init) +{ + struct nouveau_bios *bios = init->bios; + u8 index = nv_ro08(bios, init->offset + 1); + u8 or = init_or(init); + u8 data; + + trace("IO_OR\t0x03d4[0x%02x] |= (1 << 0x%02x)", index, or); + init->offset += 2; + + data = init_rdvgai(init, 0x03d4, index); + init_wrvgai(init, 0x03d4, index, data | (1 << or)); +} + +/** + * INIT_INDEX_ADDRESS_LATCHED - opcode 0x49 + * + */ +static void +init_idx_addr_latched(struct nvbios_init *init) +{ + struct nouveau_bios *bios = init->bios; + u32 creg = nv_ro32(bios, init->offset + 1); + u32 dreg = nv_ro32(bios, init->offset + 5); + u32 mask = nv_ro32(bios, init->offset + 9); + u32 data = nv_ro32(bios, init->offset + 13); + u8 count = nv_ro08(bios, init->offset + 17); + + trace("INDEX_ADDRESS_LATCHED\t" + "R[0x%06x] : R[0x%06x]\n\tCTRL &= 0x%08x |= 0x%08x\n", + creg, dreg, mask, data); + init->offset += 18; + + while (count--) { + u8 iaddr = nv_ro08(bios, init->offset + 0); + u8 idata = nv_ro08(bios, init->offset + 1); + + trace("\t[0x%02x] = 0x%02x\n", iaddr, idata); + init->offset += 2; + + init_wr32(init, dreg, idata); + init_mask(init, creg, ~mask, data | idata); + } +} + +/** + * INIT_IO_RESTRICT_PLL2 - opcode 0x4a + * + */ +static void +init_io_restrict_pll2(struct nvbios_init *init) +{ + struct nouveau_bios *bios = init->bios; + u16 port = nv_ro16(bios, init->offset + 1); + u8 index = nv_ro08(bios, init->offset + 3); + u8 mask = nv_ro08(bios, init->offset + 4); + u8 shift = nv_ro08(bios, init->offset + 5); + u8 count = nv_ro08(bios, init->offset + 6); + u32 reg = nv_ro32(bios, init->offset + 7); + u8 conf, i; + + trace("IO_RESTRICT_PLL2\t" + "R[0x%06x] =PLL= ((0x%04x[0x%02x] & 0x%02x) >> 0x%02x) [{\n", + reg, port, index, mask, shift); + init->offset += 11; + + conf = (init_rdvgai(init, port, index) & mask) >> shift; + for (i = 0; i < count; i++) { + u32 freq = nv_ro32(bios, init->offset); + if (i == conf) { + trace("\t%dkHz *\n", freq); + init_prog_pll(init, reg, freq); + } else { + trace("\t%dkHz\n", freq); + } + init->offset += 4; + } + trace("}]\n"); +} + +/** + * INIT_PLL2 - opcode 0x4b + * + */ +static void +init_pll2(struct nvbios_init *init) +{ + struct nouveau_bios *bios = init->bios; + u32 reg = nv_ro32(bios, init->offset + 1); + u32 freq = nv_ro32(bios, init->offset + 5); + + trace("PLL2\tR[0x%06x] =PLL= %dkHz\n", reg, freq); + init->offset += 9; + + init_prog_pll(init, reg, freq); +} + +/** + * INIT_I2C_BYTE - opcode 0x4c + * + */ +static void +init_i2c_byte(struct nvbios_init *init) +{ + struct nouveau_bios *bios = init->bios; + u8 index = nv_ro08(bios, init->offset + 1); + u8 addr = nv_ro08(bios, init->offset + 2) >> 1; + u8 count = nv_ro08(bios, init->offset + 3); + + trace("I2C_BYTE\tI2C[0x%02x][0x%02x]\n", index, addr); + init->offset += 4; + + while (count--) { + u8 reg = nv_ro08(bios, init->offset + 0); + u8 mask = nv_ro08(bios, init->offset + 1); + u8 data = nv_ro08(bios, init->offset + 2); + int val; + + trace("\t[0x%02x] &= 0x%02x |= 0x%02x\n", reg, mask, data); + init->offset += 3; + + val = init_rdi2cr(init, index, addr, reg); + if (val < 0) + continue; + init_wri2cr(init, index, addr, reg, (val & mask) | data); + } +} + +/** + * INIT_ZM_I2C_BYTE - opcode 0x4d + * + */ +static void +init_zm_i2c_byte(struct nvbios_init *init) +{ + struct nouveau_bios *bios = init->bios; + u8 index = nv_ro08(bios, init->offset + 1); + u8 addr = nv_ro08(bios, init->offset + 2) >> 1; + u8 count = nv_ro08(bios, init->offset + 3); + + trace("ZM_I2C_BYTE\tI2C[0x%02x][0x%02x]\n", index, addr); + init->offset += 4; + + while (count--) { + u8 reg = nv_ro08(bios, init->offset + 0); + u8 data = nv_ro08(bios, init->offset + 1); + + trace("\t[0x%02x] = 0x%02x\n", reg, data); + init->offset += 2; + + init_wri2cr(init, index, addr, reg, data); + } + +} + +/** + * INIT_ZM_I2C - opcode 0x4e + * + */ +static void +init_zm_i2c(struct nvbios_init *init) +{ + struct nouveau_bios *bios = init->bios; + u8 index = nv_ro08(bios, init->offset + 1); + u8 addr = nv_ro08(bios, init->offset + 2) >> 1; + u8 count = nv_ro08(bios, init->offset + 3); + u8 data[256], i; + + trace("ZM_I2C\tI2C[0x%02x][0x%02x]\n", index, addr); + init->offset += 4; + + for (i = 0; i < count; i++) { + data[i] = nv_ro08(bios, init->offset); + trace("\t0x%02x\n", data[i]); + init->offset++; + } + + if (init_exec(init)) { + struct nouveau_i2c_port *port = init_i2c(init, index); + struct i2c_msg msg = { + .addr = addr, .flags = 0, .len = count, .buf = data, + }; + int ret; + + if (port && (ret = i2c_transfer(&port->adapter, &msg, 1)) != 1) + warn("i2c wr failed, %d\n", ret); + } +} + +/** + * INIT_TMDS - opcode 0x4f + * + */ +static void +init_tmds(struct nvbios_init *init) +{ + struct nouveau_bios *bios = init->bios; + u8 tmds = nv_ro08(bios, init->offset + 1); + u8 addr = nv_ro08(bios, init->offset + 2); + u8 mask = nv_ro08(bios, init->offset + 3); + u8 data = nv_ro08(bios, init->offset + 4); + u32 reg = init_tmds_reg(init, tmds); + + trace("TMDS\tT[0x%02x][0x%02x] &= 0x%02x |= 0x%02x\n", + tmds, addr, mask, data); + init->offset += 5; + + if (reg == 0) + return; + + init_wr32(init, reg + 0, addr | 0x00010000); + init_wr32(init, reg + 4, data | (init_rd32(init, reg + 4) & mask)); + init_wr32(init, reg + 0, addr); +} + +/** + * INIT_ZM_TMDS_GROUP - opcode 0x50 + * + */ +static void +init_zm_tmds_group(struct nvbios_init *init) +{ + struct nouveau_bios *bios = init->bios; + u8 tmds = nv_ro08(bios, init->offset + 1); + u8 count = nv_ro08(bios, init->offset + 2); + u32 reg = init_tmds_reg(init, tmds); + + trace("TMDS_ZM_GROUP\tT[0x%02x]\n", tmds); + init->offset += 3; + + while (count--) { + u8 addr = nv_ro08(bios, init->offset + 0); + u8 data = nv_ro08(bios, init->offset + 1); + + trace("\t[0x%02x] = 0x%02x\n", addr, data); + init->offset += 2; + + init_wr32(init, reg + 4, data); + init_wr32(init, reg + 0, addr); + } +} + +/** + * INIT_CR_INDEX_ADDRESS_LATCHED - opcode 0x51 + * + */ +static void +init_cr_idx_adr_latch(struct nvbios_init *init) +{ + struct nouveau_bios *bios = init->bios; + u8 addr0 = nv_ro08(bios, init->offset + 1); + u8 addr1 = nv_ro08(bios, init->offset + 2); + u8 base = nv_ro08(bios, init->offset + 3); + u8 count = nv_ro08(bios, init->offset + 4); + u8 save0; + + trace("CR_INDEX_ADDR C[%02x] C[%02x]\n", addr0, addr1); + init->offset += 5; + + save0 = init_rdvgai(init, 0x03d4, addr0); + while (count--) { + u8 data = nv_ro08(bios, init->offset); + + trace("\t\t[0x%02x] = 0x%02x\n", base, data); + init->offset += 1; + + init_wrvgai(init, 0x03d4, addr0, base++); + init_wrvgai(init, 0x03d4, addr1, data); + } + init_wrvgai(init, 0x03d4, addr0, save0); +} + +/** + * INIT_CR - opcode 0x52 + * + */ +static void +init_cr(struct nvbios_init *init) +{ + struct nouveau_bios *bios = init->bios; + u8 addr = nv_ro08(bios, init->offset + 1); + u8 mask = nv_ro08(bios, init->offset + 2); + u8 data = nv_ro08(bios, init->offset + 3); + u8 val; + + trace("CR\t\tC[0x%02x] &= 0x%02x |= 0x%02x\n", addr, mask, data); + init->offset += 4; + + val = init_rdvgai(init, 0x03d4, addr) & mask; + init_wrvgai(init, 0x03d4, addr, val | data); +} + +/** + * INIT_ZM_CR - opcode 0x53 + * + */ +static void +init_zm_cr(struct nvbios_init *init) +{ + struct nouveau_bios *bios = init->bios; + u8 addr = nv_ro08(bios, init->offset + 1); + u8 data = nv_ro08(bios, init->offset + 2); + + trace("ZM_CR\tC[0x%02x] = 0x%02x\n", addr, data); + init->offset += 3; + + init_wrvgai(init, 0x03d4, addr, data); +} + +/** + * INIT_ZM_CR_GROUP - opcode 0x54 + * + */ +static void +init_zm_cr_group(struct nvbios_init *init) +{ + struct nouveau_bios *bios = init->bios; + u8 count = nv_ro08(bios, init->offset + 1); + + trace("ZM_CR_GROUP\n"); + init->offset += 2; + + while (count--) { + u8 addr = nv_ro08(bios, init->offset + 0); + u8 data = nv_ro08(bios, init->offset + 1); + + trace("\t\tC[0x%02x] = 0x%02x\n", addr, data); + init->offset += 2; + + init_wrvgai(init, 0x03d4, addr, data); + } +} + +/** + * INIT_CONDITION_TIME - opcode 0x56 + * + */ +static void +init_condition_time(struct nvbios_init *init) +{ + struct nouveau_bios *bios = init->bios; + u8 cond = nv_ro08(bios, init->offset + 1); + u8 retry = nv_ro08(bios, init->offset + 2); + u8 wait = min((u16)retry * 50, 100); + + trace("CONDITION_TIME\t0x%02x 0x%02x\n", cond, retry); + init->offset += 3; + + if (!init_exec(init)) + return; + + while (wait--) { + if (init_condition_met(init, cond)) + return; + mdelay(20); + } + + init_exec_set(init, false); +} + +/** + * INIT_LTIME - opcode 0x57 + * + */ +static void +init_ltime(struct nvbios_init *init) +{ + struct nouveau_bios *bios = init->bios; + u16 msec = nv_ro16(bios, init->offset + 1); + + trace("LTIME\t0x%04x\n", msec); + init->offset += 3; + + if (init_exec(init)) + mdelay(msec); +} + +/** + * INIT_ZM_REG_SEQUENCE - opcode 0x58 + * + */ +static void +init_zm_reg_sequence(struct nvbios_init *init) +{ + struct nouveau_bios *bios = init->bios; + u32 base = nv_ro32(bios, init->offset + 1); + u8 count = nv_ro08(bios, init->offset + 5); + + trace("ZM_REG_SEQUENCE\t0x%02x\n", count); + init->offset += 6; + + while (count--) { + u32 data = nv_ro32(bios, init->offset); + + trace("\t\tR[0x%06x] = 0x%08x\n", base, data); + init->offset += 4; + + init_wr32(init, base, data); + base += 4; + } +} + +/** + * INIT_SUB_DIRECT - opcode 0x5b + * + */ +static void +init_sub_direct(struct nvbios_init *init) +{ + struct nouveau_bios *bios = init->bios; + u16 addr = nv_ro16(bios, init->offset + 1); + u16 save; + + trace("SUB_DIRECT\t0x%04x\n", addr); + + if (init_exec(init)) { + save = init->offset; + init->offset = addr; + if (nvbios_exec(init)) { + error("error parsing sub-table\n"); + return; + } + init->offset = save; + } + + init->offset += 3; +} + +/** + * INIT_JUMP - opcode 0x5c + * + */ +static void +init_jump(struct nvbios_init *init) +{ + struct nouveau_bios *bios = init->bios; + u16 offset = nv_ro16(bios, init->offset + 1); + + trace("JUMP\t0x%04x\n", offset); + init->offset = offset; +} + +/** + * INIT_I2C_IF - opcode 0x5e + * + */ +static void +init_i2c_if(struct nvbios_init *init) +{ + struct nouveau_bios *bios = init->bios; + u8 index = nv_ro08(bios, init->offset + 1); + u8 addr = nv_ro08(bios, init->offset + 2); + u8 reg = nv_ro08(bios, init->offset + 3); + u8 mask = nv_ro08(bios, init->offset + 4); + u8 data = nv_ro08(bios, init->offset + 5); + u8 value; + + trace("I2C_IF\tI2C[0x%02x][0x%02x][0x%02x] & 0x%02x == 0x%02x\n", + index, addr, reg, mask, data); + init->offset += 6; + init_exec_force(init, true); + + value = init_rdi2cr(init, index, addr, reg); + if ((value & mask) != data) + init_exec_set(init, false); + + init_exec_force(init, false); +} + +/** + * INIT_COPY_NV_REG - opcode 0x5f + * + */ +static void +init_copy_nv_reg(struct nvbios_init *init) +{ + struct nouveau_bios *bios = init->bios; + u32 sreg = nv_ro32(bios, init->offset + 1); + u8 shift = nv_ro08(bios, init->offset + 5); + u32 smask = nv_ro32(bios, init->offset + 6); + u32 sxor = nv_ro32(bios, init->offset + 10); + u32 dreg = nv_ro32(bios, init->offset + 14); + u32 dmask = nv_ro32(bios, init->offset + 18); + u32 data; + + trace("COPY_NV_REG\tR[0x%06x] &= 0x%08x |= " + "((R[0x%06x] %s 0x%02x) & 0x%08x ^ 0x%08x)\n", + dreg, dmask, sreg, (shift & 0x80) ? "<<" : ">>", + (shift & 0x80) ? (0x100 - shift) : shift, smask, sxor); + init->offset += 22; + + data = init_shift(init_rd32(init, sreg), shift); + init_mask(init, dreg, ~dmask, (data & smask) ^ sxor); +} + +/** + * INIT_ZM_INDEX_IO - opcode 0x62 + * + */ +static void +init_zm_index_io(struct nvbios_init *init) +{ + struct nouveau_bios *bios = init->bios; + u16 port = nv_ro16(bios, init->offset + 1); + u8 index = nv_ro08(bios, init->offset + 3); + u8 data = nv_ro08(bios, init->offset + 4); + + trace("ZM_INDEX_IO\tI[0x%04x][0x%02x] = 0x%02x\n", port, index, data); + init->offset += 5; + + init_wrvgai(init, port, index, data); +} + +/** + * INIT_COMPUTE_MEM - opcode 0x63 + * + */ +static void +init_compute_mem(struct nvbios_init *init) +{ + struct nouveau_devinit *devinit = nouveau_devinit(init->bios); + + trace("COMPUTE_MEM\n"); + init->offset += 1; + + init_exec_force(init, true); + if (init_exec(init) && devinit->meminit) + devinit->meminit(devinit); + init_exec_force(init, false); +} + +/** + * INIT_RESET - opcode 0x65 + * + */ +static void +init_reset(struct nvbios_init *init) +{ + struct nouveau_bios *bios = init->bios; + u32 reg = nv_ro32(bios, init->offset + 1); + u32 data1 = nv_ro32(bios, init->offset + 5); + u32 data2 = nv_ro32(bios, init->offset + 9); + u32 savepci19; + + trace("RESET\tR[0x%08x] = 0x%08x, 0x%08x", reg, data1, data2); + init->offset += 13; + init_exec_force(init, true); + + savepci19 = init_mask(init, 0x00184c, 0x00000f00, 0x00000000); + init_wr32(init, reg, data1); + udelay(10); + init_wr32(init, reg, data2); + init_wr32(init, 0x00184c, savepci19); + init_mask(init, 0x001850, 0x00000001, 0x00000000); + + init_exec_force(init, false); +} + +/** + * INIT_CONFIGURE_MEM - opcode 0x66 + * + */ +static u16 +init_configure_mem_clk(struct nvbios_init *init) +{ + u16 mdata = bmp_mem_init_table(init->bios); + if (mdata) + mdata += (init_rdvgai(init, 0x03d4, 0x3c) >> 4) * 66; + return mdata; +} + +static void +init_configure_mem(struct nvbios_init *init) +{ + struct nouveau_bios *bios = init->bios; + u16 mdata, sdata; + u32 addr, data; + + trace("CONFIGURE_MEM\n"); + init->offset += 1; + + if (bios->version.major > 2) { + init_done(init); + return; + } + init_exec_force(init, true); + + mdata = init_configure_mem_clk(init); + sdata = bmp_sdr_seq_table(bios); + if (nv_ro08(bios, mdata) & 0x01) + sdata = bmp_ddr_seq_table(bios); + mdata += 6; /* skip to data */ + + data = init_rdvgai(init, 0x03c4, 0x01); + init_wrvgai(init, 0x03c4, 0x01, data | 0x20); + + while ((addr = nv_ro32(bios, sdata)) != 0xffffffff) { + switch (addr) { + case 0x10021c: /* CKE_NORMAL */ + case 0x1002d0: /* CMD_REFRESH */ + case 0x1002d4: /* CMD_PRECHARGE */ + data = 0x00000001; + break; + default: + data = nv_ro32(bios, mdata); + mdata += 4; + if (data == 0xffffffff) + continue; + break; + } + + init_wr32(init, addr, data); + } + + init_exec_force(init, false); +} + +/** + * INIT_CONFIGURE_CLK - opcode 0x67 + * + */ +static void +init_configure_clk(struct nvbios_init *init) +{ + struct nouveau_bios *bios = init->bios; + u16 mdata, clock; + + trace("CONFIGURE_CLK\n"); + init->offset += 1; + + if (bios->version.major > 2) { + init_done(init); + return; + } + init_exec_force(init, true); + + mdata = init_configure_mem_clk(init); + + /* NVPLL */ + clock = nv_ro16(bios, mdata + 4) * 10; + init_prog_pll(init, 0x680500, clock); + + /* MPLL */ + clock = nv_ro16(bios, mdata + 2) * 10; + if (nv_ro08(bios, mdata) & 0x01) + clock *= 2; + init_prog_pll(init, 0x680504, clock); + + init_exec_force(init, false); +} + +/** + * INIT_CONFIGURE_PREINIT - opcode 0x68 + * + */ +static void +init_configure_preinit(struct nvbios_init *init) +{ + struct nouveau_bios *bios = init->bios; + u32 strap; + + trace("CONFIGURE_PREINIT\n"); + init->offset += 1; + + if (bios->version.major > 2) { + init_done(init); + return; + } + init_exec_force(init, true); + + strap = init_rd32(init, 0x101000); + strap = ((strap << 2) & 0xf0) | ((strap & 0x40) >> 6); + init_wrvgai(init, 0x03d4, 0x3c, strap); + + init_exec_force(init, false); +} + +/** + * INIT_IO - opcode 0x69 + * + */ +static void +init_io(struct nvbios_init *init) +{ + struct nouveau_bios *bios = init->bios; + u16 port = nv_ro16(bios, init->offset + 1); + u8 mask = nv_ro16(bios, init->offset + 3); + u8 data = nv_ro16(bios, init->offset + 4); + u8 value; + + trace("IO\t\tI[0x%04x] &= 0x%02x |= 0x%02x\n", port, mask, data); + init->offset += 5; + + /* ummm.. yes.. should really figure out wtf this is and why it's + * needed some day.. it's almost certainly wrong, but, it also + * somehow makes things work... + */ + if (nv_device(init->bios)->card_type >= NV_50 && + port == 0x03c3 && data == 0x01) { + init_mask(init, 0x614100, 0xf0800000, 0x00800000); + init_mask(init, 0x00e18c, 0x00020000, 0x00020000); + init_mask(init, 0x614900, 0xf0800000, 0x00800000); + init_mask(init, 0x000200, 0x40000000, 0x00000000); + mdelay(10); + init_mask(init, 0x00e18c, 0x00020000, 0x00000000); + init_mask(init, 0x000200, 0x40000000, 0x40000000); + init_wr32(init, 0x614100, 0x00800018); + init_wr32(init, 0x614900, 0x00800018); + mdelay(10); + init_wr32(init, 0x614100, 0x10000018); + init_wr32(init, 0x614900, 0x10000018); + return; + } + + value = init_rdport(init, port) & mask; + init_wrport(init, port, data | value); +} + +/** + * INIT_SUB - opcode 0x6b + * + */ +static void +init_sub(struct nvbios_init *init) +{ + struct nouveau_bios *bios = init->bios; + u8 index = nv_ro08(bios, init->offset + 1); + u16 addr, save; + + trace("SUB\t0x%02x\n", index); + + addr = init_script(bios, index); + if (addr && init_exec(init)) { + save = init->offset; + init->offset = addr; + if (nvbios_exec(init)) { + error("error parsing sub-table\n"); + return; + } + init->offset = save; + } + + init->offset += 2; +} + +/** + * INIT_RAM_CONDITION - opcode 0x6d + * + */ +static void +init_ram_condition(struct nvbios_init *init) +{ + struct nouveau_bios *bios = init->bios; + u8 mask = nv_ro08(bios, init->offset + 1); + u8 value = nv_ro08(bios, init->offset + 2); + + trace("RAM_CONDITION\t" + "(R[0x100000] & 0x%02x) == 0x%02x\n", mask, value); + init->offset += 3; + + if ((init_rd32(init, 0x100000) & mask) != value) + init_exec_set(init, false); +} + +/** + * INIT_NV_REG - opcode 0x6e + * + */ +static void +init_nv_reg(struct nvbios_init *init) +{ + struct nouveau_bios *bios = init->bios; + u32 reg = nv_ro32(bios, init->offset + 1); + u32 mask = nv_ro32(bios, init->offset + 5); + u32 data = nv_ro32(bios, init->offset + 9); + + trace("NV_REG\tR[0x%06x] &= 0x%08x |= 0x%08x\n", reg, mask, data); + init->offset += 13; + + init_mask(init, reg, ~mask, data); +} + +/** + * INIT_MACRO - opcode 0x6f + * + */ +static void +init_macro(struct nvbios_init *init) +{ + struct nouveau_bios *bios = init->bios; + u8 macro = nv_ro08(bios, init->offset + 1); + u16 table; + + trace("MACRO\t0x%02x\n", macro); + + table = init_macro_table(init); + if (table) { + u32 addr = nv_ro32(bios, table + (macro * 8) + 0); + u32 data = nv_ro32(bios, table + (macro * 8) + 4); + trace("\t\tR[0x%06x] = 0x%08x\n", addr, data); + init_wr32(init, addr, data); + } + + init->offset += 2; +} + +/** + * INIT_RESUME - opcode 0x72 + * + */ +static void +init_resume(struct nvbios_init *init) +{ + trace("RESUME\n"); + init->offset += 1; + init_exec_set(init, true); +} + +/** + * INIT_TIME - opcode 0x74 + * + */ +static void +init_time(struct nvbios_init *init) +{ + struct nouveau_bios *bios = init->bios; + u16 usec = nv_ro16(bios, init->offset + 1); + + trace("TIME\t0x%04x\n", usec); + init->offset += 3; + + if (init_exec(init)) { + if (usec < 1000) + udelay(usec); + else + mdelay((usec + 900) / 1000); + } +} + +/** + * INIT_CONDITION - opcode 0x75 + * + */ +static void +init_condition(struct nvbios_init *init) +{ + struct nouveau_bios *bios = init->bios; + u8 cond = nv_ro08(bios, init->offset + 1); + + trace("CONDITION\t0x%02x\n", cond); + init->offset += 2; + + if (!init_condition_met(init, cond)) + init_exec_set(init, false); +} + +/** + * INIT_IO_CONDITION - opcode 0x76 + * + */ +static void +init_io_condition(struct nvbios_init *init) +{ + struct nouveau_bios *bios = init->bios; + u8 cond = nv_ro08(bios, init->offset + 1); + + trace("IO_CONDITION\t0x%02x\n", cond); + init->offset += 2; + + if (!init_io_condition_met(init, cond)) + init_exec_set(init, false); +} + +/** + * INIT_INDEX_IO - opcode 0x78 + * + */ +static void +init_index_io(struct nvbios_init *init) +{ + struct nouveau_bios *bios = init->bios; + u16 port = nv_ro16(bios, init->offset + 1); + u8 index = nv_ro16(bios, init->offset + 3); + u8 mask = nv_ro08(bios, init->offset + 4); + u8 data = nv_ro08(bios, init->offset + 5); + u8 value; + + trace("INDEX_IO\tI[0x%04x][0x%02x] &= 0x%02x |= 0x%02x\n", + port, index, mask, data); + init->offset += 6; + + value = init_rdvgai(init, port, index) & mask; + init_wrvgai(init, port, index, data | value); +} + +/** + * INIT_PLL - opcode 0x79 + * + */ +static void +init_pll(struct nvbios_init *init) +{ + struct nouveau_bios *bios = init->bios; + u32 reg = nv_ro32(bios, init->offset + 1); + u32 freq = nv_ro16(bios, init->offset + 5) * 10; + + trace("PLL\tR[0x%06x] =PLL= %dkHz\n", reg, freq); + init->offset += 7; + + init_prog_pll(init, reg, freq); +} + +/** + * INIT_ZM_REG - opcode 0x7a + * + */ +static void +init_zm_reg(struct nvbios_init *init) +{ + struct nouveau_bios *bios = init->bios; + u32 addr = nv_ro32(bios, init->offset + 1); + u32 data = nv_ro32(bios, init->offset + 5); + + trace("ZM_REG\tR[0x%06x] = 0x%08x\n", addr, data); + init->offset += 9; + + if (addr == 0x000200) + data |= 0x00000001; + + init_wr32(init, addr, data); +} + +/** + * INIT_RAM_RESTRICT_PLL - opcde 0x87 + * + */ +static void +init_ram_restrict_pll(struct nvbios_init *init) +{ + struct nouveau_bios *bios = init->bios; + u8 type = nv_ro08(bios, init->offset + 1); + u8 count = init_ram_restrict_group_count(init); + u8 strap = init_ram_restrict(init); + u8 cconf; + + trace("RAM_RESTRICT_PLL\t0x%02x\n", type); + init->offset += 2; + + for (cconf = 0; cconf < count; cconf++) { + u32 freq = nv_ro32(bios, init->offset); + + if (cconf == strap) { + trace("%dkHz *\n", freq); + init_prog_pll(init, type, freq); + } else { + trace("%dkHz\n", freq); + } + + init->offset += 4; + } +} + +/** + * INIT_GPIO - opcode 0x8e + * + */ +static void +init_gpio(struct nvbios_init *init) +{ + struct nouveau_gpio *gpio = nouveau_gpio(init->bios); + + trace("GPIO\n"); + init->offset += 1; + + if (init_exec(init) && gpio && gpio->reset) + gpio->reset(gpio); +} + +/** + * INIT_RAM_RESTRICT_ZM_GROUP - opcode 0x8f + * + */ +static void +init_ram_restrict_zm_reg_group(struct nvbios_init *init) +{ + struct nouveau_bios *bios = init->bios; + u32 addr = nv_ro32(bios, init->offset + 1); + u8 incr = nv_ro08(bios, init->offset + 5); + u8 num = nv_ro08(bios, init->offset + 6); + u8 count = init_ram_restrict_group_count(init); + u8 index = init_ram_restrict(init); + u8 i, j; + + trace("RAM_RESTRICT_ZM_REG_GROUP\t" + "R[%08x] 0x%02x 0x%02x\n", addr, incr, num); + init->offset += 7; + + for (i = 0; i < num; i++) { + trace("\tR[0x%06x] = {\n", addr); + for (j = 0; j < count; j++) { + u32 data = nv_ro32(bios, init->offset); + + if (j == index) { + trace("\t\t0x%08x *\n", data); + init_wr32(init, addr, data); + } else { + trace("\t\t0x%08x\n", data); + } + + init->offset += 4; + } + trace("\t}\n"); + addr += incr; + } +} + +/** + * INIT_COPY_ZM_REG - opcode 0x90 + * + */ +static void +init_copy_zm_reg(struct nvbios_init *init) +{ + struct nouveau_bios *bios = init->bios; + u32 sreg = nv_ro32(bios, init->offset + 1); + u32 dreg = nv_ro32(bios, init->offset + 5); + + trace("COPY_ZM_REG\tR[0x%06x] = R[0x%06x]\n", sreg, dreg); + init->offset += 9; + + init_wr32(init, dreg, init_rd32(init, sreg)); +} + +/** + * INIT_ZM_REG_GROUP - opcode 0x91 + * + */ +static void +init_zm_reg_group(struct nvbios_init *init) +{ + struct nouveau_bios *bios = init->bios; + u32 addr = nv_ro32(bios, init->offset + 1); + u8 count = nv_ro08(bios, init->offset + 5); + + trace("ZM_REG_GROUP\tR[0x%06x] =\n"); + init->offset += 6; + + while (count--) { + u32 data = nv_ro32(bios, init->offset); + trace("\t0x%08x\n", data); + init_wr32(init, addr, data); + init->offset += 4; + } +} + +/** + * INIT_XLAT - opcode 0x96 + * + */ +static void +init_xlat(struct nvbios_init *init) +{ + struct nouveau_bios *bios = init->bios; + u32 saddr = nv_ro32(bios, init->offset + 1); + u8 sshift = nv_ro08(bios, init->offset + 5); + u8 smask = nv_ro08(bios, init->offset + 6); + u8 index = nv_ro08(bios, init->offset + 7); + u32 daddr = nv_ro32(bios, init->offset + 8); + u32 dmask = nv_ro32(bios, init->offset + 12); + u8 shift = nv_ro08(bios, init->offset + 16); + u32 data; + + trace("INIT_XLAT\tR[0x%06x] &= 0x%08x |= " + "(X%02x((R[0x%06x] %s 0x%02x) & 0x%02x) << 0x%02x)\n", + daddr, dmask, index, saddr, (sshift & 0x80) ? "<<" : ">>", + (sshift & 0x80) ? (0x100 - sshift) : sshift, smask, shift); + init->offset += 17; + + data = init_shift(init_rd32(init, saddr), sshift) & smask; + data = init_xlat_(init, index, data) << shift; + init_mask(init, daddr, ~dmask, data); +} + +/** + * INIT_ZM_MASK_ADD - opcode 0x97 + * + */ +static void +init_zm_mask_add(struct nvbios_init *init) +{ + struct nouveau_bios *bios = init->bios; + u32 addr = nv_ro32(bios, init->offset + 1); + u32 mask = nv_ro32(bios, init->offset + 5); + u32 add = nv_ro32(bios, init->offset + 9); + u32 data; + + trace("ZM_MASK_ADD\tR[0x%06x] &= 0x%08x += 0x%08x\n", addr, mask, add); + init->offset += 13; + + data = init_rd32(init, addr) & mask; + data |= ((data + add) & ~mask); + init_wr32(init, addr, data); +} + +/** + * INIT_AUXCH - opcode 0x98 + * + */ +static void +init_auxch(struct nvbios_init *init) +{ + struct nouveau_bios *bios = init->bios; + u32 addr = nv_ro32(bios, init->offset + 1); + u8 count = nv_ro08(bios, init->offset + 5); + + trace("AUXCH\tAUX[0x%08x] 0x%02x\n", addr, count); + init->offset += 6; + + while (count--) { + u8 mask = nv_ro08(bios, init->offset + 0); + u8 data = nv_ro08(bios, init->offset + 1); + trace("\tAUX[0x%08x] &= 0x%02x |= 0x%02x\n", addr, mask, data); + mask = init_rdauxr(init, addr) & mask; + init_wrauxr(init, addr, mask | data); + init->offset += 2; + } +} + +/** + * INIT_AUXCH - opcode 0x99 + * + */ +static void +init_zm_auxch(struct nvbios_init *init) +{ + struct nouveau_bios *bios = init->bios; + u32 addr = nv_ro32(bios, init->offset + 1); + u8 count = nv_ro08(bios, init->offset + 5); + + trace("ZM_AUXCH\tAUX[0x%08x] 0x%02x\n", addr, count); + init->offset += 6; + + while (count--) { + u8 data = nv_ro08(bios, init->offset + 0); + trace("\tAUX[0x%08x] = 0x%02x\n", addr, data); + init_wrauxr(init, addr, data); + init->offset += 1; + } +} + +/** + * INIT_I2C_LONG_IF - opcode 0x9a + * + */ +static void +init_i2c_long_if(struct nvbios_init *init) +{ + struct nouveau_bios *bios = init->bios; + u8 index = nv_ro08(bios, init->offset + 1); + u8 addr = nv_ro08(bios, init->offset + 2) >> 1; + u8 reglo = nv_ro08(bios, init->offset + 3); + u8 reghi = nv_ro08(bios, init->offset + 4); + u8 mask = nv_ro08(bios, init->offset + 5); + u8 data = nv_ro08(bios, init->offset + 6); + struct nouveau_i2c_port *port; + + trace("I2C_LONG_IF\t" + "I2C[0x%02x][0x%02x][0x%02x%02x] & 0x%02x == 0x%02x\n", + index, addr, reglo, reghi, mask, data); + init->offset += 7; + + port = init_i2c(init, index); + if (port) { + u8 i[2] = { reghi, reglo }; + u8 o[1] = {}; + struct i2c_msg msg[] = { + { .addr = addr, .flags = 0, .len = 2, .buf = i }, + { .addr = addr, .flags = I2C_M_RD, .len = 1, .buf = o } + }; + int ret; + + ret = i2c_transfer(&port->adapter, msg, 2); + if (ret == 2 && ((o[0] & mask) == data)) + return; + } + + init_exec_set(init, false); +} + +static struct nvbios_init_opcode { + void (*exec)(struct nvbios_init *); +} init_opcode[] = { + [0x32] = { init_io_restrict_prog }, + [0x33] = { init_repeat }, + [0x34] = { init_io_restrict_pll }, + [0x36] = { init_end_repeat }, + [0x37] = { init_copy }, + [0x38] = { init_not }, + [0x39] = { init_io_flag_condition }, + [0x3a] = { init_dp_condition }, + [0x3b] = { init_io_mask_or }, + [0x3c] = { init_io_or }, + [0x49] = { init_idx_addr_latched }, + [0x4a] = { init_io_restrict_pll2 }, + [0x4b] = { init_pll2 }, + [0x4c] = { init_i2c_byte }, + [0x4d] = { init_zm_i2c_byte }, + [0x4e] = { init_zm_i2c }, + [0x4f] = { init_tmds }, + [0x50] = { init_zm_tmds_group }, + [0x51] = { init_cr_idx_adr_latch }, + [0x52] = { init_cr }, + [0x53] = { init_zm_cr }, + [0x54] = { init_zm_cr_group }, + [0x56] = { init_condition_time }, + [0x57] = { init_ltime }, + [0x58] = { init_zm_reg_sequence }, + [0x5b] = { init_sub_direct }, + [0x5c] = { init_jump }, + [0x5e] = { init_i2c_if }, + [0x5f] = { init_copy_nv_reg }, + [0x62] = { init_zm_index_io }, + [0x63] = { init_compute_mem }, + [0x65] = { init_reset }, + [0x66] = { init_configure_mem }, + [0x67] = { init_configure_clk }, + [0x68] = { init_configure_preinit }, + [0x69] = { init_io }, + [0x6b] = { init_sub }, + [0x6d] = { init_ram_condition }, + [0x6e] = { init_nv_reg }, + [0x6f] = { init_macro }, + [0x71] = { init_done }, + [0x72] = { init_resume }, + [0x74] = { init_time }, + [0x75] = { init_condition }, + [0x76] = { init_io_condition }, + [0x78] = { init_index_io }, + [0x79] = { init_pll }, + [0x7a] = { init_zm_reg }, + [0x87] = { init_ram_restrict_pll }, + [0x8c] = { init_reserved }, + [0x8d] = { init_reserved }, + [0x8e] = { init_gpio }, + [0x8f] = { init_ram_restrict_zm_reg_group }, + [0x90] = { init_copy_zm_reg }, + [0x91] = { init_zm_reg_group }, + [0x92] = { init_reserved }, + [0x96] = { init_xlat }, + [0x97] = { init_zm_mask_add }, + [0x98] = { init_auxch }, + [0x99] = { init_zm_auxch }, + [0x9a] = { init_i2c_long_if }, +}; + +#define init_opcode_nr (sizeof(init_opcode) / sizeof(init_opcode[0])) + +int +nvbios_exec(struct nvbios_init *init) +{ + init->nested++; + while (init->offset) { + u8 opcode = nv_ro08(init->bios, init->offset); + if (opcode >= init_opcode_nr || !init_opcode[opcode].exec) { + error("unknown opcode 0x%02x\n", opcode); + return -EINVAL; + } + + init_opcode[opcode].exec(init); + } + init->nested--; + return 0; +} + +int +nvbios_init(struct nouveau_subdev *subdev, bool execute) +{ + struct nouveau_bios *bios = nouveau_bios(subdev); + int ret = 0; + int i = -1; + u16 data; + + if (execute) + nv_info(bios, "running init tables\n"); + while (!ret && (data = (init_script(bios, ++i)))) { + struct nvbios_init init = { + .subdev = subdev, + .bios = bios, + .offset = data, + .outp = NULL, + .crtc = -1, + .execute = execute ? 1 : 0, + }; + + ret = nvbios_exec(&init); + } + + /* the vbios parser will run this right after the normal init + * tables, whereas the binary driver appears to run it later. + */ + if (!ret && (data = init_unknown_script(bios))) { + struct nvbios_init init = { + .subdev = subdev, + .bios = bios, + .offset = data, + .outp = NULL, + .crtc = -1, + .execute = execute ? 1 : 0, + }; + + ret = nvbios_exec(&init); + } + + return 0; +} diff --git a/drivers/gpu/drm/nouveau/core/subdev/device/nv04.c b/drivers/gpu/drm/nouveau/core/subdev/device/nv04.c index e24e74b9c437..47f7841ecaab 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/device/nv04.c +++ b/drivers/gpu/drm/nouveau/core/subdev/device/nv04.c @@ -26,6 +26,7 @@ #include #include #include +#include int nv04_identify(struct nouveau_device *device) @@ -35,11 +36,13 @@ nv04_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv04_clock_oclass; + device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv04_devinit_oclass; break; case 0x05: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv04_clock_oclass; + device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv05_devinit_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 0b8eb741686e..ad481ebe7eae 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/device/nv10.c +++ b/drivers/gpu/drm/nouveau/core/subdev/device/nv10.c @@ -27,6 +27,7 @@ #include #include #include +#include int nv10_identify(struct nouveau_device *device) @@ -37,48 +38,56 @@ nv10_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv04_clock_oclass; + device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv10_devinit_oclass; break; case 0x15: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv04_clock_oclass; + device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv10_devinit_oclass; break; case 0x16: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv04_clock_oclass; + device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv10_devinit_oclass; break; case 0x1a: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv04_clock_oclass; + device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass; break; case 0x11: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv04_clock_oclass; + device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv10_devinit_oclass; break; case 0x17: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv04_clock_oclass; + device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv10_devinit_oclass; break; case 0x1f: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv04_clock_oclass; + device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass; break; case 0x18: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv04_clock_oclass; + device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv10_devinit_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 1432ef046b72..51ef1f4b9a5f 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/device/nv20.c +++ b/drivers/gpu/drm/nouveau/core/subdev/device/nv20.c @@ -27,6 +27,7 @@ #include #include #include +#include int nv20_identify(struct nouveau_device *device) @@ -37,24 +38,28 @@ nv20_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv04_clock_oclass; + device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv20_devinit_oclass; break; case 0x25: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv04_clock_oclass; + device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv20_devinit_oclass; break; case 0x28: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv04_clock_oclass; + device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv20_devinit_oclass; break; case 0x2a: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv04_clock_oclass; + device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv20_devinit_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 7eeab7841793..e812f71a931c 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/device/nv30.c +++ b/drivers/gpu/drm/nouveau/core/subdev/device/nv30.c @@ -27,6 +27,7 @@ #include #include #include +#include int nv30_identify(struct nouveau_device *device) @@ -37,30 +38,35 @@ nv30_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv04_clock_oclass; + device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv20_devinit_oclass; break; case 0x35: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv04_clock_oclass; + device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv20_devinit_oclass; break; case 0x31: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv04_clock_oclass; + device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv20_devinit_oclass; break; case 0x36: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv04_clock_oclass; + device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv20_devinit_oclass; break; case 0x34: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv04_clock_oclass; + device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv10_devinit_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 ec7c03f96d77..8d2b62cbdffd 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/device/nv40.c +++ b/drivers/gpu/drm/nouveau/core/subdev/device/nv40.c @@ -27,6 +27,7 @@ #include #include #include +#include int nv40_identify(struct nouveau_device *device) @@ -37,96 +38,112 @@ nv40_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv40_clock_oclass; + device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass; break; case 0x41: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv40_clock_oclass; + device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass; break; case 0x42: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv40_clock_oclass; + device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass; break; case 0x43: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv40_clock_oclass; + device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass; break; case 0x45: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv40_clock_oclass; + device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass; break; case 0x47: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv40_clock_oclass; + device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass; break; case 0x49: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv40_clock_oclass; + device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass; break; case 0x4b: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv40_clock_oclass; + device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass; break; case 0x44: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv40_clock_oclass; + device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass; break; case 0x46: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv40_clock_oclass; + device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass; break; case 0x4a: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv40_clock_oclass; + device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass; break; case 0x4c: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv40_clock_oclass; + device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass; break; case 0x4e: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv40_clock_oclass; + device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass; break; case 0x63: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv40_clock_oclass; + device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass; break; case 0x67: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv40_clock_oclass; + device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass; break; case 0x68: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv40_clock_oclass; + device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_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 0674163506c5..cb50d8629bbb 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/device/nv50.c +++ b/drivers/gpu/drm/nouveau/core/subdev/device/nv50.c @@ -27,6 +27,7 @@ #include #include #include +#include int nv50_identify(struct nouveau_device *device) @@ -37,84 +38,98 @@ nv50_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv50_clock_oclass; + device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; break; case 0x84: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv50_clock_oclass; + device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; break; case 0x86: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv50_clock_oclass; + device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; break; case 0x92: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv50_clock_oclass; + device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; break; case 0x94: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv50_clock_oclass; + device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; break; case 0x96: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv50_clock_oclass; + device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; break; case 0x98: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv50_clock_oclass; + device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; break; case 0xa0: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv50_clock_oclass; + device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; break; case 0xaa: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv50_clock_oclass; + device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; break; case 0xac: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv50_clock_oclass; + device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; break; case 0xa3: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nva3_clock_oclass; + device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; break; case 0xa5: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nva3_clock_oclass; + device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; break; case 0xa8: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nva3_clock_oclass; + device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; break; case 0xaf: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nva3_clock_oclass; + device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_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 56aae6bfbf23..67c46fc15b8f 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/device/nvc0.c +++ b/drivers/gpu/drm/nouveau/core/subdev/device/nvc0.c @@ -27,6 +27,7 @@ #include #include #include +#include int nvc0_identify(struct nouveau_device *device) @@ -37,48 +38,56 @@ nvc0_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nvc0_clock_oclass; + device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; break; case 0xc4: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nvc0_clock_oclass; + device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; break; case 0xc3: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nvc0_clock_oclass; + device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; break; case 0xce: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nvc0_clock_oclass; + device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; break; case 0xcf: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nvc0_clock_oclass; + device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; break; case 0xc1: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nvc0_clock_oclass; + device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; break; case 0xc8: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nvc0_clock_oclass; + device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; break; case 0xd9: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nvd0_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nvc0_clock_oclass; + device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_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 8ad51cc0543e..a1e87dfccf6c 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/device/nve0.c +++ b/drivers/gpu/drm/nouveau/core/subdev/device/nve0.c @@ -27,6 +27,7 @@ #include #include #include +#include int nve0_identify(struct nouveau_device *device) @@ -37,12 +38,14 @@ nve0_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_GPIO ] = &nvd0_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nvc0_clock_oclass; + device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; break; case 0xe7: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nvd0_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nvc0_clock_oclass; + device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; break; default: nv_fatal(device, "unknown Kepler chipset\n"); diff --git a/drivers/gpu/drm/nouveau/core/subdev/devinit/base.c b/drivers/gpu/drm/nouveau/core/subdev/devinit/base.c new file mode 100644 index 000000000000..5a07a39c1735 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/subdev/devinit/base.c @@ -0,0 +1,69 @@ +/* + * 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 + +int +nouveau_devinit_init(struct nouveau_devinit *devinit) +{ + int ret = nouveau_subdev_init(&devinit->base); + if (ret) + return ret; + + return nvbios_init(&devinit->base, devinit->post); +} + +int +nouveau_devinit_fini(struct nouveau_devinit *devinit, bool suspend) +{ + /* force full reinit on resume */ + if (suspend) + devinit->post = true; + + return nouveau_subdev_fini(&devinit->base, suspend); +} + +int +nouveau_devinit_create_(struct nouveau_object *parent, + struct nouveau_object *engine, + struct nouveau_oclass *oclass, + int size, void **pobject) +{ + struct nouveau_device *device = nv_device(parent); + struct nouveau_devinit *devinit; + int ret; + + ret = nouveau_subdev_create_(parent, engine, oclass, 0, "DEVINIT", + "init", size, pobject); + devinit = *pobject; + if (ret) + return ret; + + devinit->post = nouveau_boolopt(device->cfgopt, "NvForcePost", false); + return 0; +} diff --git a/drivers/gpu/drm/nouveau/core/subdev/devinit/fbmem.h b/drivers/gpu/drm/nouveau/core/subdev/devinit/fbmem.h new file mode 100644 index 000000000000..6b56a0f4cb40 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/subdev/devinit/fbmem.h @@ -0,0 +1,98 @@ +/* + * 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. + * + */ + +#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_DEBUG_0 0x00100080 +# define NV04_PFB_DEBUG_0_PAGE_MODE 0x00000001 +# define NV04_PFB_DEBUG_0_REFRESH_OFF 0x00000010 +# define NV04_PFB_DEBUG_0_REFRESH_COUNTX64 0x00003f00 +# define NV04_PFB_DEBUG_0_REFRESH_SLOW_CLK 0x00004000 +# define NV04_PFB_DEBUG_0_SAFE_MODE 0x00008000 +# define NV04_PFB_DEBUG_0_ALOM_ENABLE 0x00010000 +# define NV04_PFB_DEBUG_0_CASOE 0x00100000 +# define NV04_PFB_DEBUG_0_CKE_INVERT 0x10000000 +# define NV04_PFB_DEBUG_0_REFINC 0x20000000 +# define NV04_PFB_DEBUG_0_SAVE_POWER_OFF 0x40000000 +#define NV04_PFB_CFG0 0x00100200 +# define NV04_PFB_CFG0_SCRAMBLE 0x20000000 +#define NV04_PFB_CFG1 0x00100204 +#define NV04_PFB_SCRAMBLE(i) (0x00100400 + 4 * (i)) + +#define NV10_PFB_REFCTRL 0x00100210 +# define NV10_PFB_REFCTRL_VALID_1 (1 << 31) + +static inline struct io_mapping * +fbmem_init(struct pci_dev *pdev) +{ + return io_mapping_create_wc(pci_resource_start(pdev, 1), + pci_resource_len(pdev, 1)); +} + +static inline void +fbmem_fini(struct io_mapping *fb) +{ + io_mapping_free(fb); +} + +static inline u32 +fbmem_peek(struct io_mapping *fb, u32 off) +{ + u8 __iomem *p = io_mapping_map_atomic_wc(fb, off & PAGE_MASK); + u32 val = ioread32(p + (off & ~PAGE_MASK)); + io_mapping_unmap_atomic(p); + return val; +} + +static inline void +fbmem_poke(struct io_mapping *fb, u32 off, u32 val) +{ + u8 __iomem *p = io_mapping_map_atomic_wc(fb, off & PAGE_MASK); + iowrite32(val, p + (off & ~PAGE_MASK)); + wmb(); + io_mapping_unmap_atomic(p); +} + +static inline bool +fbmem_readback(struct io_mapping *fb, u32 off, u32 val) +{ + fbmem_poke(fb, off, val); + return val == fbmem_peek(fb, off); +} diff --git a/drivers/gpu/drm/nouveau/core/subdev/devinit/nv04.c b/drivers/gpu/drm/nouveau/core/subdev/devinit/nv04.c new file mode 100644 index 000000000000..7a72d9394340 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/subdev/devinit/nv04.c @@ -0,0 +1,189 @@ +/* + * 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 +#include + +#include "fbmem.h" + +struct nv04_devinit_priv { + struct nouveau_devinit base; + int owner; +}; + +static void +nv04_devinit_meminit(struct nouveau_devinit *devinit) +{ + struct nv04_devinit_priv *priv = (void *)devinit; + u32 patt = 0xdeadbeef; + struct io_mapping *fb; + int i; + + /* Map the framebuffer aperture */ + fb = fbmem_init(nv_device(priv)->pdev); + if (!fb) { + nv_error(priv, "failed to map fb\n"); + return; + } + + /* Sequencer and refresh off */ + nv_wrvgas(priv, 0, 1, nv_rdvgas(priv, 0, 1) | 0x20); + nv_mask(priv, NV04_PFB_DEBUG_0, 0, NV04_PFB_DEBUG_0_REFRESH_OFF); + + nv_mask(priv, NV04_PFB_BOOT_0, ~0, + NV04_PFB_BOOT_0_RAM_AMOUNT_16MB | + NV04_PFB_BOOT_0_RAM_WIDTH_128 | + NV04_PFB_BOOT_0_RAM_TYPE_SGRAM_16MBIT); + + for (i = 0; i < 4; i++) + fbmem_poke(fb, 4 * i, patt); + + fbmem_poke(fb, 0x400000, patt + 1); + + if (fbmem_peek(fb, 0) == patt + 1) { + nv_mask(priv, NV04_PFB_BOOT_0, + NV04_PFB_BOOT_0_RAM_TYPE, + NV04_PFB_BOOT_0_RAM_TYPE_SDRAM_16MBIT); + nv_mask(priv, NV04_PFB_DEBUG_0, + NV04_PFB_DEBUG_0_REFRESH_OFF, 0); + + for (i = 0; i < 4; i++) + fbmem_poke(fb, 4 * i, patt); + + if ((fbmem_peek(fb, 0xc) & 0xffff) != (patt & 0xffff)) + nv_mask(priv, NV04_PFB_BOOT_0, + NV04_PFB_BOOT_0_RAM_WIDTH_128 | + NV04_PFB_BOOT_0_RAM_AMOUNT, + NV04_PFB_BOOT_0_RAM_AMOUNT_8MB); + } else + if ((fbmem_peek(fb, 0xc) & 0xffff0000) != (patt & 0xffff0000)) { + nv_mask(priv, NV04_PFB_BOOT_0, + NV04_PFB_BOOT_0_RAM_WIDTH_128 | + NV04_PFB_BOOT_0_RAM_AMOUNT, + NV04_PFB_BOOT_0_RAM_AMOUNT_4MB); + } else + if (fbmem_peek(fb, 0) != patt) { + if (fbmem_readback(fb, 0x800000, patt)) + nv_mask(priv, NV04_PFB_BOOT_0, + NV04_PFB_BOOT_0_RAM_AMOUNT, + NV04_PFB_BOOT_0_RAM_AMOUNT_8MB); + else + nv_mask(priv, NV04_PFB_BOOT_0, + NV04_PFB_BOOT_0_RAM_AMOUNT, + NV04_PFB_BOOT_0_RAM_AMOUNT_4MB); + + nv_mask(priv, NV04_PFB_BOOT_0, NV04_PFB_BOOT_0_RAM_TYPE, + NV04_PFB_BOOT_0_RAM_TYPE_SGRAM_8MBIT); + } else + if (!fbmem_readback(fb, 0x800000, patt)) { + nv_mask(priv, NV04_PFB_BOOT_0, NV04_PFB_BOOT_0_RAM_AMOUNT, + NV04_PFB_BOOT_0_RAM_AMOUNT_8MB); + + } + + /* Refresh on, sequencer on */ + nv_mask(priv, NV04_PFB_DEBUG_0, NV04_PFB_DEBUG_0_REFRESH_OFF, 0); + nv_wrvgas(priv, 0, 1, nv_rdvgas(priv, 0, 1) & ~0x20); + fbmem_fini(fb); +} + +static int +nv04_devinit_ctor(struct nouveau_object *parent, struct nouveau_object *engine, + struct nouveau_oclass *oclass, void *data, u32 size, + struct nouveau_object **pobject) +{ + struct nv04_devinit_priv *priv; + int ret; + + ret = nouveau_devinit_create(parent, engine, oclass, &priv); + *pobject = nv_object(priv); + if (ret) + return ret; + + priv->base.meminit = nv04_devinit_meminit; + priv->owner = -1; + return 0; +} + +void +nv04_devinit_dtor(struct nouveau_object *object) +{ + struct nv04_devinit_priv *priv = (void *)object; + + /* restore vga owner saved at first init, and lock crtc regs */ + nv_wrvgaowner(priv, priv->owner); + nv_lockvgac(priv, true); + + nouveau_devinit_destroy(&priv->base); +} + +int +nv04_devinit_init(struct nouveau_object *object) +{ + struct nv04_devinit_priv *priv = (void *)object; + + if (!priv->base.post) { + u32 htotal = nv_rdvgac(priv, 0, 0x06); + htotal |= (nv_rdvgac(priv, 0, 0x07) & 0x01) << 8; + htotal |= (nv_rdvgac(priv, 0, 0x07) & 0x20) << 4; + htotal |= (nv_rdvgac(priv, 0, 0x25) & 0x01) << 10; + htotal |= (nv_rdvgac(priv, 0, 0x41) & 0x01) << 11; + if (!htotal) { + nv_info(priv, "adaptor not initialised\n"); + priv->base.post = true; + } + } + + return nouveau_devinit_init(&priv->base); +} + +int +nv04_devinit_fini(struct nouveau_object *object, bool suspend) +{ + struct nv04_devinit_priv *priv = (void *)object; + + /* make i2c busses accessible */ + nv_mask(priv, 0x000200, 0x00000001, 0x00000001); + + /* unlock extended vga crtc regs, and unslave crtcs */ + nv_lockvgac(priv, false); + if (priv->owner < 0) + priv->owner = nv_rdvgaowner(priv); + nv_wrvgaowner(priv, 0); + + return nouveau_devinit_fini(&priv->base, suspend); +} + +struct nouveau_oclass +nv04_devinit_oclass = { + .handle = NV_SUBDEV(DEVINIT, 0x04), + .ofuncs = &(struct nouveau_ofuncs) { + .ctor = nv04_devinit_ctor, + .dtor = nv04_devinit_dtor, + .init = nv04_devinit_init, + .fini = nv04_devinit_fini, + }, +}; diff --git a/drivers/gpu/drm/nouveau/core/subdev/devinit/nv05.c b/drivers/gpu/drm/nouveau/core/subdev/devinit/nv05.c new file mode 100644 index 000000000000..191447d0d252 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/subdev/devinit/nv05.c @@ -0,0 +1,159 @@ +/* + * 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 +#include +#include +#include + +#include "fbmem.h" + +struct nv05_devinit_priv { + struct nouveau_devinit base; + u8 owner; +}; + +static void +nv05_devinit_meminit(struct nouveau_devinit *devinit) +{ + static const u8 default_config_tab[][2] = { + { 0x24, 0x00 }, + { 0x28, 0x00 }, + { 0x24, 0x01 }, + { 0x1f, 0x00 }, + { 0x0f, 0x00 }, + { 0x17, 0x00 }, + { 0x06, 0x00 }, + { 0x00, 0x00 } + }; + struct nv05_devinit_priv *priv = (void *)devinit; + struct nouveau_bios *bios = nouveau_bios(priv); + struct io_mapping *fb; + u32 patt = 0xdeadbeef; + u16 data; + u8 strap, ramcfg[2]; + int i, v; + + /* Map the framebuffer aperture */ + fb = fbmem_init(nv_device(priv)->pdev); + if (!fb) { + nv_error(priv, "failed to map fb\n"); + return; + } + + strap = (nv_rd32(priv, 0x101000) & 0x0000003c) >> 2; + if ((data = bmp_mem_init_table(bios))) { + ramcfg[0] = nv_ro08(bios, data + 2 * strap + 0); + ramcfg[1] = nv_ro08(bios, data + 2 * strap + 1); + } else { + ramcfg[0] = default_config_tab[strap][0]; + ramcfg[1] = default_config_tab[strap][1]; + } + + /* Sequencer off */ + nv_wrvgas(priv, 0, 1, nv_rdvgas(priv, 0, 1) | 0x20); + + if (nv_rd32(priv, NV04_PFB_BOOT_0) & NV04_PFB_BOOT_0_UMA_ENABLE) + goto out; + + nv_mask(priv, NV04_PFB_DEBUG_0, NV04_PFB_DEBUG_0_REFRESH_OFF, 0); + + /* If present load the hardcoded scrambling table */ + if (data) { + for (i = 0, data += 0x10; i < 8; i++, data += 4) { + u32 scramble = nv_ro32(bios, data); + nv_wr32(priv, NV04_PFB_SCRAMBLE(i), scramble); + } + } + + /* Set memory type/width/length defaults depending on the straps */ + nv_mask(priv, NV04_PFB_BOOT_0, 0x3f, ramcfg[0]); + + if (ramcfg[1] & 0x80) + nv_mask(priv, NV04_PFB_CFG0, 0, NV04_PFB_CFG0_SCRAMBLE); + + nv_mask(priv, NV04_PFB_CFG1, 0x700001, (ramcfg[1] & 1) << 20); + nv_mask(priv, NV04_PFB_CFG1, 0, 1); + + /* Probe memory bus width */ + for (i = 0; i < 4; i++) + fbmem_poke(fb, 4 * i, patt); + + if (fbmem_peek(fb, 0xc) != patt) + nv_mask(priv, NV04_PFB_BOOT_0, + NV04_PFB_BOOT_0_RAM_WIDTH_128, 0); + + /* Probe memory length */ + v = nv_rd32(priv, NV04_PFB_BOOT_0) & NV04_PFB_BOOT_0_RAM_AMOUNT; + + if (v == NV04_PFB_BOOT_0_RAM_AMOUNT_32MB && + (!fbmem_readback(fb, 0x1000000, ++patt) || + !fbmem_readback(fb, 0, ++patt))) + nv_mask(priv, NV04_PFB_BOOT_0, NV04_PFB_BOOT_0_RAM_AMOUNT, + NV04_PFB_BOOT_0_RAM_AMOUNT_16MB); + + if (v == NV04_PFB_BOOT_0_RAM_AMOUNT_16MB && + !fbmem_readback(fb, 0x800000, ++patt)) + nv_mask(priv, NV04_PFB_BOOT_0, NV04_PFB_BOOT_0_RAM_AMOUNT, + NV04_PFB_BOOT_0_RAM_AMOUNT_8MB); + + if (!fbmem_readback(fb, 0x400000, ++patt)) + nv_mask(priv, NV04_PFB_BOOT_0, NV04_PFB_BOOT_0_RAM_AMOUNT, + NV04_PFB_BOOT_0_RAM_AMOUNT_4MB); + +out: + /* Sequencer on */ + nv_wrvgas(priv, 0, 1, nv_rdvgas(priv, 0, 1) & ~0x20); + fbmem_fini(fb); +} + +static int +nv05_devinit_ctor(struct nouveau_object *parent, struct nouveau_object *engine, + struct nouveau_oclass *oclass, void *data, u32 size, + struct nouveau_object **pobject) +{ + struct nv05_devinit_priv *priv; + int ret; + + ret = nouveau_devinit_create(parent, engine, oclass, &priv); + *pobject = nv_object(priv); + if (ret) + return ret; + + priv->base.meminit = nv05_devinit_meminit; + return 0; +} + +struct nouveau_oclass +nv05_devinit_oclass = { + .handle = NV_SUBDEV(DEVINIT, 0x05), + .ofuncs = &(struct nouveau_ofuncs) { + .ctor = nv05_devinit_ctor, + .dtor = nv04_devinit_dtor, + .init = nv04_devinit_init, + .fini = nv04_devinit_fini, + }, +}; diff --git a/drivers/gpu/drm/nouveau/core/subdev/devinit/nv10.c b/drivers/gpu/drm/nouveau/core/subdev/devinit/nv10.c new file mode 100644 index 000000000000..eb76ffab6b0c --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/subdev/devinit/nv10.c @@ -0,0 +1,124 @@ +/* + * 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 +#include + +#include "fbmem.h" + +struct nv10_devinit_priv { + struct nouveau_devinit base; + u8 owner; +}; + +static void +nv10_devinit_meminit(struct nouveau_devinit *devinit) +{ + struct nv10_devinit_priv *priv = (void *)devinit; + const int mem_width[] = { 0x10, 0x00, 0x20 }; + const int mem_width_count = nv_device(priv)->chipset >= 0x17 ? 3 : 2; + uint32_t patt = 0xdeadbeef; + struct io_mapping *fb; + int i, j, k; + + /* Map the framebuffer aperture */ + fb = fbmem_init(nv_device(priv)->pdev); + if (!fb) { + nv_error(priv, "failed to map fb\n"); + return; + } + + nv_wr32(priv, NV10_PFB_REFCTRL, NV10_PFB_REFCTRL_VALID_1); + + /* Probe memory bus width */ + for (i = 0; i < mem_width_count; i++) { + nv_mask(priv, NV04_PFB_CFG0, 0x30, mem_width[i]); + + for (j = 0; j < 4; j++) { + for (k = 0; k < 4; k++) + fbmem_poke(fb, 0x1c, 0); + + fbmem_poke(fb, 0x1c, patt); + fbmem_poke(fb, 0x3c, 0); + + if (fbmem_peek(fb, 0x1c) == patt) + goto mem_width_found; + } + } + +mem_width_found: + patt <<= 1; + + /* Probe amount of installed memory */ + for (i = 0; i < 4; i++) { + int off = nv_rd32(priv, 0x10020c) - 0x100000; + + fbmem_poke(fb, off, patt); + fbmem_poke(fb, 0, 0); + + fbmem_peek(fb, 0); + fbmem_peek(fb, 0); + fbmem_peek(fb, 0); + fbmem_peek(fb, 0); + + if (fbmem_peek(fb, off) == patt) + goto amount_found; + } + + /* IC missing - disable the upper half memory space. */ + nv_mask(priv, NV04_PFB_CFG0, 0x1000, 0); + +amount_found: + fbmem_fini(fb); +} + +static int +nv10_devinit_ctor(struct nouveau_object *parent, struct nouveau_object *engine, + struct nouveau_oclass *oclass, void *data, u32 size, + struct nouveau_object **pobject) +{ + struct nv10_devinit_priv *priv; + int ret; + + ret = nouveau_devinit_create(parent, engine, oclass, &priv); + *pobject = nv_object(priv); + if (ret) + return ret; + + priv->base.meminit = nv10_devinit_meminit; + return 0; +} + +struct nouveau_oclass +nv10_devinit_oclass = { + .handle = NV_SUBDEV(DEVINIT, 0x10), + .ofuncs = &(struct nouveau_ofuncs) { + .ctor = nv10_devinit_ctor, + .dtor = nv04_devinit_dtor, + .init = nv04_devinit_init, + .fini = nv04_devinit_fini, + }, +}; diff --git a/drivers/gpu/drm/nouveau/core/subdev/devinit/nv1a.c b/drivers/gpu/drm/nouveau/core/subdev/devinit/nv1a.c new file mode 100644 index 000000000000..5b2ba630d913 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/subdev/devinit/nv1a.c @@ -0,0 +1,58 @@ +/* + * 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 + +struct nv1a_devinit_priv { + struct nouveau_devinit base; + u8 owner; +}; + +static int +nv1a_devinit_ctor(struct nouveau_object *parent, struct nouveau_object *engine, + struct nouveau_oclass *oclass, void *data, u32 size, + struct nouveau_object **pobject) +{ + struct nv1a_devinit_priv *priv; + int ret; + + ret = nouveau_devinit_create(parent, engine, oclass, &priv); + *pobject = nv_object(priv); + if (ret) + return ret; + + return 0; +} + +struct nouveau_oclass +nv1a_devinit_oclass = { + .handle = NV_SUBDEV(DEVINIT, 0x1a), + .ofuncs = &(struct nouveau_ofuncs) { + .ctor = nv1a_devinit_ctor, + .dtor = nv04_devinit_dtor, + .init = nv04_devinit_init, + .fini = nv04_devinit_fini, + }, +}; diff --git a/drivers/gpu/drm/nouveau/core/subdev/devinit/nv20.c b/drivers/gpu/drm/nouveau/core/subdev/devinit/nv20.c new file mode 100644 index 000000000000..eb32e99005e4 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/subdev/devinit/nv20.c @@ -0,0 +1,96 @@ +/* + * 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 +#include + +#include "fbmem.h" + +struct nv20_devinit_priv { + struct nouveau_devinit base; + u8 owner; +}; + +static void +nv20_devinit_meminit(struct nouveau_devinit *devinit) +{ + struct nv20_devinit_priv *priv = (void *)devinit; + struct nouveau_device *device = nv_device(priv); + uint32_t mask = (device->chipset >= 0x25 ? 0x300 : 0x900); + uint32_t amount, off; + struct io_mapping *fb; + + /* Map the framebuffer aperture */ + fb = fbmem_init(nv_device(priv)->pdev); + if (!fb) { + nv_error(priv, "failed to map fb\n"); + return; + } + + nv_wr32(priv, NV10_PFB_REFCTRL, NV10_PFB_REFCTRL_VALID_1); + + /* Allow full addressing */ + nv_mask(priv, NV04_PFB_CFG0, 0, mask); + + amount = nv_rd32(priv, 0x10020c); + for (off = amount; off > 0x2000000; off -= 0x2000000) + fbmem_poke(fb, off - 4, off); + + amount = nv_rd32(priv, 0x10020c); + if (amount != fbmem_peek(fb, amount - 4)) + /* IC missing - disable the upper half memory space. */ + nv_mask(priv, NV04_PFB_CFG0, mask, 0); + + fbmem_fini(fb); +} + +static int +nv20_devinit_ctor(struct nouveau_object *parent, struct nouveau_object *engine, + struct nouveau_oclass *oclass, void *data, u32 size, + struct nouveau_object **pobject) +{ + struct nv20_devinit_priv *priv; + int ret; + + ret = nouveau_devinit_create(parent, engine, oclass, &priv); + *pobject = nv_object(priv); + if (ret) + return ret; + + priv->base.meminit = nv20_devinit_meminit; + return 0; +} + +struct nouveau_oclass +nv20_devinit_oclass = { + .handle = NV_SUBDEV(DEVINIT, 0x20), + .ofuncs = &(struct nouveau_ofuncs) { + .ctor = nv20_devinit_ctor, + .dtor = nv04_devinit_dtor, + .init = nv04_devinit_init, + .fini = nv04_devinit_fini, + }, +}; diff --git a/drivers/gpu/drm/nouveau/core/subdev/devinit/nv50.c b/drivers/gpu/drm/nouveau/core/subdev/devinit/nv50.c new file mode 100644 index 000000000000..61becfa732e9 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/subdev/devinit/nv50.c @@ -0,0 +1,87 @@ +/* + * 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 + +struct nv50_devinit_priv { + struct nouveau_devinit base; +}; + +static int +nv50_devinit_ctor(struct nouveau_object *parent, struct nouveau_object *engine, + struct nouveau_oclass *oclass, void *data, u32 size, + struct nouveau_object **pobject) +{ + struct nv50_devinit_priv *priv; + int ret; + + ret = nouveau_devinit_create(parent, engine, oclass, &priv); + *pobject = nv_object(priv); + if (ret) + return ret; + + return 0; +} + +static void +nv50_devinit_dtor(struct nouveau_object *object) +{ + struct nv50_devinit_priv *priv = (void *)object; + nouveau_devinit_destroy(&priv->base); +} + +static int +nv50_devinit_init(struct nouveau_object *object) +{ + struct nv50_devinit_priv *priv = (void *)object; + + if (!priv->base.post) { + if (!nv_rdvgac(priv, 0, 0x00) && + !nv_rdvgac(priv, 0, 0x1a)) { + nv_info(priv, "adaptor not initialised\n"); + priv->base.post = true; + } + } + + return nouveau_devinit_init(&priv->base); +} + +static int +nv50_devinit_fini(struct nouveau_object *object, bool suspend) +{ + struct nv50_devinit_priv *priv = (void *)object; + return nouveau_devinit_fini(&priv->base, suspend); +} + +struct nouveau_oclass +nv50_devinit_oclass = { + .handle = NV_SUBDEV(DEVINIT, 0x50), + .ofuncs = &(struct nouveau_ofuncs) { + .ctor = nv50_devinit_ctor, + .dtor = nv50_devinit_dtor, + .init = nv50_devinit_init, + .fini = nv50_devinit_fini, + }, +}; diff --git a/drivers/gpu/drm/nouveau/nouveau_agp.c b/drivers/gpu/drm/nouveau/nouveau_agp.c index d33201c56aa1..d28430cd2ba6 100644 --- a/drivers/gpu/drm/nouveau/nouveau_agp.c +++ b/drivers/gpu/drm/nouveau/nouveau_agp.c @@ -1,10 +1,10 @@ #include -#include "drmP.h" -#include "drm.h" +#include -#include "nouveau_drv.h" +#include "nouveau_drm.h" #include "nouveau_agp.h" +#include "nouveau_reg.h" #if __OS_HAS_AGP MODULE_PARM_DESC(agpmode, "AGP mode (0 to disable AGP)"); @@ -12,15 +12,15 @@ static int nouveau_agpmode = -1; module_param_named(agpmode, nouveau_agpmode, int, 0400); static unsigned long -get_agp_mode(struct drm_device *dev, unsigned long mode) +get_agp_mode(struct nouveau_drm *drm, unsigned long mode) { - struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_device *device = nv_device(drm->device); /* * FW seems to be broken on nv18, it makes the card lock up * randomly. */ - if (dev_priv->chipset == 0x18) + if (device->chipset == 0x18) mode &= ~PCI_AGP_COMMAND_FW; /* @@ -37,42 +37,39 @@ get_agp_mode(struct drm_device *dev, unsigned long mode) } static bool -nouveau_agp_enabled(struct drm_device *dev) +nouveau_agp_enabled(struct nouveau_drm *drm) { - struct drm_nouveau_private *dev_priv = dev->dev_private; + struct drm_device *dev = drm->dev; if (!drm_pci_device_is_agp(dev) || !dev->agp) return false; - switch (dev_priv->gart_info.type) { - case NOUVEAU_GART_NONE: + if (drm->agp.stat == UNKNOWN) { if (!nouveau_agpmode) return false; - break; - case NOUVEAU_GART_AGP: - break; - default: - return false; + return true; } - return true; + return (drm->agp.stat == ENABLED); } #endif void -nouveau_agp_reset(struct drm_device *dev) +nouveau_agp_reset(struct nouveau_drm *drm) { #if __OS_HAS_AGP + struct nouveau_device *device = nv_device(drm->device); + struct drm_device *dev = drm->dev; u32 save[2]; int ret; - if (!nouveau_agp_enabled(dev)) + if (!nouveau_agp_enabled(drm)) return; /* First of all, disable fast writes, otherwise if it's * already enabled in the AGP bridge and we disable the card's * AGP controller we might be locking ourselves out of it. */ - if ((nv_rd32(dev, NV04_PBUS_PCI_NV_19) | + if ((nv_rd32(device, NV04_PBUS_PCI_NV_19) | dev->agp->mode) & PCI_AGP_COMMAND_FW) { struct drm_agp_info info; struct drm_agp_mode mode; @@ -81,7 +78,7 @@ nouveau_agp_reset(struct drm_device *dev) if (ret) return; - mode.mode = get_agp_mode(dev, info.mode); + mode.mode = get_agp_mode(drm, info.mode); mode.mode &= ~PCI_AGP_COMMAND_FW; ret = drm_agp_enable(dev, mode); @@ -91,61 +88,64 @@ nouveau_agp_reset(struct drm_device *dev) /* clear busmaster bit, and disable AGP */ - save[0] = nv_mask(dev, NV04_PBUS_PCI_NV_1, 0x00000004, 0x00000000); - nv_wr32(dev, NV04_PBUS_PCI_NV_19, 0); + save[0] = nv_mask(device, NV04_PBUS_PCI_NV_1, 0x00000004, 0x00000000); + nv_wr32(device, NV04_PBUS_PCI_NV_19, 0); /* reset PGRAPH, PFIFO and PTIMER */ - save[1] = nv_mask(dev, 0x000200, 0x00011100, 0x00000000); - nv_mask(dev, 0x000200, 0x00011100, save[1]); + save[1] = nv_mask(device, 0x000200, 0x00011100, 0x00000000); + nv_mask(device, 0x000200, 0x00011100, save[1]); /* and restore bustmaster bit (gives effect of resetting AGP) */ - nv_wr32(dev, NV04_PBUS_PCI_NV_1, save[0]); + nv_wr32(device, NV04_PBUS_PCI_NV_1, save[0]); #endif } void -nouveau_agp_init(struct drm_device *dev) +nouveau_agp_init(struct nouveau_drm *drm) { #if __OS_HAS_AGP - struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_device *device = nv_device(drm->device); + struct drm_device *dev = drm->dev; struct drm_agp_info info; struct drm_agp_mode mode; int ret; - if (!nouveau_agp_enabled(dev)) + if (!nouveau_agp_enabled(drm)) return; + drm->agp.stat = DISABLE; ret = drm_agp_acquire(dev); if (ret) { - NV_ERROR(dev, "Unable to acquire AGP: %d\n", ret); + nv_error(device, "unable to acquire AGP: %d\n", ret); return; } ret = drm_agp_info(dev, &info); if (ret) { - NV_ERROR(dev, "Unable to get AGP info: %d\n", ret); + nv_error(device, "unable to get AGP info: %d\n", ret); return; } /* see agp.h for the AGPSTAT_* modes available */ - mode.mode = get_agp_mode(dev, info.mode); + mode.mode = get_agp_mode(drm, info.mode); ret = drm_agp_enable(dev, mode); if (ret) { - NV_ERROR(dev, "Unable to enable AGP: %d\n", ret); + nv_error(device, "unable to enable AGP: %d\n", ret); return; } - dev_priv->gart_info.type = NOUVEAU_GART_AGP; - dev_priv->gart_info.aper_base = info.aperture_base; - dev_priv->gart_info.aper_size = info.aperture_size; + drm->agp.stat = ENABLED; + drm->agp.base = info.aperture_base; + drm->agp.size = info.aperture_size; #endif } void -nouveau_agp_fini(struct drm_device *dev) +nouveau_agp_fini(struct nouveau_drm *drm) { #if __OS_HAS_AGP + struct drm_device *dev = drm->dev; if (dev->agp && dev->agp->acquired) drm_agp_release(dev); #endif diff --git a/drivers/gpu/drm/nouveau/nouveau_agp.h b/drivers/gpu/drm/nouveau/nouveau_agp.h index b23db55eb2ca..b55c08652963 100644 --- a/drivers/gpu/drm/nouveau/nouveau_agp.h +++ b/drivers/gpu/drm/nouveau/nouveau_agp.h @@ -1,8 +1,10 @@ #ifndef __NOUVEAU_AGP_H__ #define __NOUVEAU_AGP_H__ -void nouveau_agp_reset(struct drm_device *); -void nouveau_agp_init(struct drm_device *); -void nouveau_agp_fini(struct drm_device *); +struct nouveau_drm; + +void nouveau_agp_reset(struct nouveau_drm *); +void nouveau_agp_init(struct nouveau_drm *); +void nouveau_agp_fini(struct nouveau_drm *); #endif diff --git a/drivers/gpu/drm/nouveau/nouveau_backlight.c b/drivers/gpu/drm/nouveau/nouveau_backlight.c index 7266902a74ed..d33e94a34517 100644 --- a/drivers/gpu/drm/nouveau/nouveau_backlight.c +++ b/drivers/gpu/drm/nouveau/nouveau_backlight.c @@ -181,9 +181,9 @@ nv50_backlight_init(struct drm_connector *connector) struct backlight_device *bd; const struct backlight_ops *ops; - nv_encoder = find_encoder(connector, OUTPUT_LVDS); + nv_encoder = find_encoder(connector, DCB_OUTPUT_LVDS); if (!nv_encoder) { - nv_encoder = find_encoder(connector, OUTPUT_DP); + nv_encoder = find_encoder(connector, DCB_OUTPUT_DP); if (!nv_encoder) return -ENODEV; } diff --git a/drivers/gpu/drm/nouveau/nouveau_bios.c b/drivers/gpu/drm/nouveau/nouveau_bios.c index 98eaac9da30e..e7abde138e27 100644 --- a/drivers/gpu/drm/nouveau/nouveau_bios.c +++ b/drivers/gpu/drm/nouveau/nouveau_bios.c @@ -64,3372 +64,6 @@ static bool nv_cksum(const uint8_t *data, unsigned int length) return false; } -struct init_tbl_entry { - char *name; - uint8_t id; - /* Return: - * > 0: success, length of opcode - * 0: success, but abort further parsing of table (INIT_DONE etc) - * < 0: failure, table parsing will be aborted - */ - int (*handler)(struct nvbios *, uint16_t, struct init_exec *); -}; - -static int parse_init_table(struct nvbios *, uint16_t, struct init_exec *); - -#define MACRO_INDEX_SIZE 2 -#define MACRO_SIZE 8 -#define CONDITION_SIZE 12 -#define IO_FLAG_CONDITION_SIZE 9 -#define IO_CONDITION_SIZE 5 -#define MEM_INIT_SIZE 66 - -static void still_alive(void) -{ -#if 0 - sync(); - mdelay(2); -#endif -} - -static uint32_t -munge_reg(struct nvbios *bios, uint32_t reg) -{ - struct drm_nouveau_private *dev_priv = bios->dev->dev_private; - struct dcb_entry *dcbent = bios->display.output; - - if (dev_priv->card_type < NV_50) - return reg; - - if (reg & 0x80000000) { - BUG_ON(bios->display.crtc < 0); - reg += bios->display.crtc * 0x800; - } - - if (reg & 0x40000000) { - BUG_ON(!dcbent); - - reg += (ffs(dcbent->or) - 1) * 0x800; - if ((reg & 0x20000000) && !(dcbent->sorconf.link & 1)) - reg += 0x00000080; - } - - reg &= ~0xe0000000; - return reg; -} - -static int -valid_reg(struct nvbios *bios, uint32_t reg) -{ - struct drm_nouveau_private *dev_priv = bios->dev->dev_private; - struct drm_device *dev = bios->dev; - - /* C51 has misaligned regs on purpose. Marvellous */ - if (reg & 0x2 || - (reg & 0x1 && dev_priv->vbios.chip_version != 0x51)) - NV_ERROR(dev, "======= misaligned reg 0x%08X =======\n", reg); - - /* warn on C51 regs that haven't been verified accessible in tracing */ - if (reg & 0x1 && dev_priv->vbios.chip_version == 0x51 && - reg != 0x130d && reg != 0x1311 && reg != 0x60081d) - NV_WARN(dev, "=== C51 misaligned reg 0x%08X not verified ===\n", - reg); - - if (reg >= (8*1024*1024)) { - NV_ERROR(dev, "=== reg 0x%08x out of mapped bounds ===\n", reg); - return 0; - } - - return 1; -} - -static bool -valid_idx_port(struct nvbios *bios, uint16_t port) -{ - struct drm_nouveau_private *dev_priv = bios->dev->dev_private; - struct drm_device *dev = bios->dev; - - /* - * If adding more ports here, the read/write functions below will need - * updating so that the correct mmio range (PRMCIO, PRMDIO, PRMVIO) is - * used for the port in question - */ - if (dev_priv->card_type < NV_50) { - if (port == NV_CIO_CRX__COLOR) - return true; - if (port == NV_VIO_SRX) - return true; - } else { - if (port == NV_CIO_CRX__COLOR) - return true; - } - - NV_ERROR(dev, "========== unknown indexed io port 0x%04X ==========\n", - port); - - return false; -} - -static bool -valid_port(struct nvbios *bios, uint16_t port) -{ - struct drm_device *dev = bios->dev; - - /* - * If adding more ports here, the read/write functions below will need - * updating so that the correct mmio range (PRMCIO, PRMDIO, PRMVIO) is - * used for the port in question - */ - if (port == NV_VIO_VSE2) - return true; - - NV_ERROR(dev, "========== unknown io port 0x%04X ==========\n", port); - - return false; -} - -static uint32_t -bios_rd32(struct nvbios *bios, uint32_t reg) -{ - uint32_t data; - - reg = munge_reg(bios, reg); - if (!valid_reg(bios, reg)) - return 0; - - /* - * C51 sometimes uses regs with bit0 set in the address. For these - * cases there should exist a translation in a BIOS table to an IO - * port address which the BIOS uses for accessing the reg - * - * These only seem to appear for the power control regs to a flat panel, - * and the GPIO regs at 0x60081*. In C51 mmio traces the normal regs - * for 0x1308 and 0x1310 are used - hence the mask below. An S3 - * suspend-resume mmio trace from a C51 will be required to see if this - * is true for the power microcode in 0x14.., or whether the direct IO - * port access method is needed - */ - if (reg & 0x1) - reg &= ~0x1; - - data = nv_rd32(bios->dev, reg); - - BIOSLOG(bios, " Read: Reg: 0x%08X, Data: 0x%08X\n", reg, data); - - return data; -} - -static void -bios_wr32(struct nvbios *bios, uint32_t reg, uint32_t data) -{ - struct drm_nouveau_private *dev_priv = bios->dev->dev_private; - - reg = munge_reg(bios, reg); - if (!valid_reg(bios, reg)) - return; - - /* see note in bios_rd32 */ - if (reg & 0x1) - reg &= 0xfffffffe; - - LOG_OLD_VALUE(bios_rd32(bios, reg)); - BIOSLOG(bios, " Write: Reg: 0x%08X, Data: 0x%08X\n", reg, data); - - if (dev_priv->vbios.execute) { - still_alive(); - nv_wr32(bios->dev, reg, data); - } -} - -static uint8_t -bios_idxprt_rd(struct nvbios *bios, uint16_t port, uint8_t index) -{ - struct drm_nouveau_private *dev_priv = bios->dev->dev_private; - struct drm_device *dev = bios->dev; - uint8_t data; - - if (!valid_idx_port(bios, port)) - return 0; - - if (dev_priv->card_type < NV_50) { - if (port == NV_VIO_SRX) - data = NVReadVgaSeq(dev, bios->state.crtchead, index); - else /* assume NV_CIO_CRX__COLOR */ - data = NVReadVgaCrtc(dev, bios->state.crtchead, index); - } else { - uint32_t data32; - - data32 = bios_rd32(bios, NV50_PDISPLAY_VGACRTC(index & ~3)); - data = (data32 >> ((index & 3) << 3)) & 0xff; - } - - BIOSLOG(bios, " Indexed IO read: Port: 0x%04X, Index: 0x%02X, " - "Head: 0x%02X, Data: 0x%02X\n", - port, index, bios->state.crtchead, data); - return data; -} - -static void -bios_idxprt_wr(struct nvbios *bios, uint16_t port, uint8_t index, uint8_t data) -{ - struct drm_nouveau_private *dev_priv = bios->dev->dev_private; - struct drm_device *dev = bios->dev; - - if (!valid_idx_port(bios, port)) - return; - - /* - * The current head is maintained in the nvbios member state.crtchead. - * We trap changes to CR44 and update the head variable and hence the - * register set written. - * As CR44 only exists on CRTC0, we update crtchead to head0 in advance - * of the write, and to head1 after the write - */ - if (port == NV_CIO_CRX__COLOR && index == NV_CIO_CRE_44 && - data != NV_CIO_CRE_44_HEADB) - bios->state.crtchead = 0; - - LOG_OLD_VALUE(bios_idxprt_rd(bios, port, index)); - BIOSLOG(bios, " Indexed IO write: Port: 0x%04X, Index: 0x%02X, " - "Head: 0x%02X, Data: 0x%02X\n", - port, index, bios->state.crtchead, data); - - if (bios->execute && dev_priv->card_type < NV_50) { - still_alive(); - if (port == NV_VIO_SRX) - NVWriteVgaSeq(dev, bios->state.crtchead, index, data); - else /* assume NV_CIO_CRX__COLOR */ - NVWriteVgaCrtc(dev, bios->state.crtchead, index, data); - } else - if (bios->execute) { - uint32_t data32, shift = (index & 3) << 3; - - still_alive(); - - data32 = bios_rd32(bios, NV50_PDISPLAY_VGACRTC(index & ~3)); - data32 &= ~(0xff << shift); - data32 |= (data << shift); - bios_wr32(bios, NV50_PDISPLAY_VGACRTC(index & ~3), data32); - } - - if (port == NV_CIO_CRX__COLOR && - index == NV_CIO_CRE_44 && data == NV_CIO_CRE_44_HEADB) - bios->state.crtchead = 1; -} - -static uint8_t -bios_port_rd(struct nvbios *bios, uint16_t port) -{ - uint8_t data, head = bios->state.crtchead; - - if (!valid_port(bios, port)) - return 0; - - data = NVReadPRMVIO(bios->dev, head, NV_PRMVIO0_OFFSET + port); - - BIOSLOG(bios, " IO read: Port: 0x%04X, Head: 0x%02X, Data: 0x%02X\n", - port, head, data); - - return data; -} - -static void -bios_port_wr(struct nvbios *bios, uint16_t port, uint8_t data) -{ - int head = bios->state.crtchead; - - if (!valid_port(bios, port)) - return; - - LOG_OLD_VALUE(bios_port_rd(bios, port)); - BIOSLOG(bios, " IO write: Port: 0x%04X, Head: 0x%02X, Data: 0x%02X\n", - port, head, data); - - if (!bios->execute) - return; - - still_alive(); - NVWritePRMVIO(bios->dev, head, NV_PRMVIO0_OFFSET + port, data); -} - -static bool -io_flag_condition_met(struct nvbios *bios, uint16_t offset, uint8_t cond) -{ - /* - * The IO flag condition entry has 2 bytes for the CRTC port; 1 byte - * for the CRTC index; 1 byte for the mask to apply to the value - * retrieved from the CRTC; 1 byte for the shift right to apply to the - * masked CRTC value; 2 bytes for the offset to the flag array, to - * which the shifted value is added; 1 byte for the mask applied to the - * value read from the flag array; and 1 byte for the value to compare - * against the masked byte from the flag table. - */ - - uint16_t condptr = bios->io_flag_condition_tbl_ptr + cond * IO_FLAG_CONDITION_SIZE; - uint16_t crtcport = ROM16(bios->data[condptr]); - uint8_t crtcindex = bios->data[condptr + 2]; - uint8_t mask = bios->data[condptr + 3]; - uint8_t shift = bios->data[condptr + 4]; - uint16_t flagarray = ROM16(bios->data[condptr + 5]); - uint8_t flagarraymask = bios->data[condptr + 7]; - uint8_t cmpval = bios->data[condptr + 8]; - uint8_t data; - - BIOSLOG(bios, "0x%04X: Port: 0x%04X, Index: 0x%02X, Mask: 0x%02X, " - "Shift: 0x%02X, FlagArray: 0x%04X, FAMask: 0x%02X, " - "Cmpval: 0x%02X\n", - offset, crtcport, crtcindex, mask, shift, flagarray, flagarraymask, cmpval); - - data = bios_idxprt_rd(bios, crtcport, crtcindex); - - data = bios->data[flagarray + ((data & mask) >> shift)]; - data &= flagarraymask; - - BIOSLOG(bios, "0x%04X: Checking if 0x%02X equals 0x%02X\n", - offset, data, cmpval); - - return (data == cmpval); -} - -static bool -bios_condition_met(struct nvbios *bios, uint16_t offset, uint8_t cond) -{ - /* - * The condition table entry has 4 bytes for the address of the - * register to check, 4 bytes for a mask to apply to the register and - * 4 for a test comparison value - */ - - uint16_t condptr = bios->condition_tbl_ptr + cond * CONDITION_SIZE; - uint32_t reg = ROM32(bios->data[condptr]); - uint32_t mask = ROM32(bios->data[condptr + 4]); - uint32_t cmpval = ROM32(bios->data[condptr + 8]); - uint32_t data; - - BIOSLOG(bios, "0x%04X: Cond: 0x%02X, Reg: 0x%08X, Mask: 0x%08X\n", - offset, cond, reg, mask); - - data = bios_rd32(bios, reg) & mask; - - BIOSLOG(bios, "0x%04X: Checking if 0x%08X equals 0x%08X\n", - offset, data, cmpval); - - return (data == cmpval); -} - -static bool -io_condition_met(struct nvbios *bios, uint16_t offset, uint8_t cond) -{ - /* - * The IO condition entry has 2 bytes for the IO port address; 1 byte - * for the index to write to io_port; 1 byte for the mask to apply to - * the byte read from io_port+1; and 1 byte for the value to compare - * against the masked byte. - */ - - uint16_t condptr = bios->io_condition_tbl_ptr + cond * IO_CONDITION_SIZE; - uint16_t io_port = ROM16(bios->data[condptr]); - uint8_t port_index = bios->data[condptr + 2]; - uint8_t mask = bios->data[condptr + 3]; - uint8_t cmpval = bios->data[condptr + 4]; - - uint8_t data = bios_idxprt_rd(bios, io_port, port_index) & mask; - - BIOSLOG(bios, "0x%04X: Checking if 0x%02X equals 0x%02X\n", - offset, data, cmpval); - - return (data == cmpval); -} - -static int dcb_entry_idx_from_crtchead(struct drm_device *dev) -{ - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nvbios *bios = &dev_priv->vbios; - - /* - * For the results of this function to be correct, CR44 must have been - * set (using bios_idxprt_wr to set crtchead), CR58 set for CR57 = 0, - * and the DCB table parsed, before the script calling the function is - * run. run_digital_op_script is example of how to do such setup - */ - - uint8_t dcb_entry = NVReadVgaCrtc5758(dev, bios->state.crtchead, 0); - - if (dcb_entry > bios->dcb.entries) { - NV_ERROR(dev, "CR58 doesn't have a valid DCB entry currently " - "(%02X)\n", dcb_entry); - dcb_entry = 0x7f; /* unused / invalid marker */ - } - - return dcb_entry; -} - -static struct nouveau_i2c_port * -init_i2c_device_find(struct drm_device *dev, int i2c_index) -{ - if (i2c_index == 0xff) { - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct dcb_table *dcb = &dev_priv->vbios.dcb; - /* note: dcb_entry_idx_from_crtchead needs pre-script set-up */ - int idx = dcb_entry_idx_from_crtchead(dev); - - i2c_index = 0x80; //NV_I2C_DEFAULT(0); - if (idx != 0x7f && dcb->entry[idx].i2c_upper_default) - i2c_index = 0x81; //NV_I2C_DEFAULT(1); - } - - return nouveau_i2c_find(dev, i2c_index); -} - -static uint32_t -get_tmds_index_reg(struct drm_device *dev, uint8_t mlv) -{ - /* - * For mlv < 0x80, it is an index into a table of TMDS base addresses. - * For mlv == 0x80 use the "or" value of the dcb_entry indexed by - * CR58 for CR57 = 0 to index a table of offsets to the basic - * 0x6808b0 address. - * For mlv == 0x81 use the "or" value of the dcb_entry indexed by - * CR58 for CR57 = 0 to index a table of offsets to the basic - * 0x6808b0 address, and then flip the offset by 8. - */ - - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nvbios *bios = &dev_priv->vbios; - const int pramdac_offset[13] = { - 0, 0, 0x8, 0, 0x2000, 0, 0, 0, 0x2008, 0, 0, 0, 0x2000 }; - const uint32_t pramdac_table[4] = { - 0x6808b0, 0x6808b8, 0x6828b0, 0x6828b8 }; - - if (mlv >= 0x80) { - int dcb_entry, dacoffset; - - /* note: dcb_entry_idx_from_crtchead needs pre-script set-up */ - dcb_entry = dcb_entry_idx_from_crtchead(dev); - if (dcb_entry == 0x7f) - return 0; - dacoffset = pramdac_offset[bios->dcb.entry[dcb_entry].or]; - if (mlv == 0x81) - dacoffset ^= 8; - return 0x6808b0 + dacoffset; - } else { - if (mlv >= ARRAY_SIZE(pramdac_table)) { - NV_ERROR(dev, "Magic Lookup Value too big (%02X)\n", - mlv); - return 0; - } - return pramdac_table[mlv]; - } -} - -static int -init_io_restrict_prog(struct nvbios *bios, uint16_t offset, - struct init_exec *iexec) -{ - /* - * INIT_IO_RESTRICT_PROG opcode: 0x32 ('2') - * - * offset (8 bit): opcode - * offset + 1 (16 bit): CRTC port - * offset + 3 (8 bit): CRTC index - * offset + 4 (8 bit): mask - * offset + 5 (8 bit): shift - * offset + 6 (8 bit): count - * offset + 7 (32 bit): register - * offset + 11 (32 bit): configuration 1 - * ... - * - * Starting at offset + 11 there are "count" 32 bit values. - * To find out which value to use read index "CRTC index" on "CRTC - * port", AND this value with "mask" and then bit shift right "shift" - * bits. Read the appropriate value using this index and write to - * "register" - */ - - uint16_t crtcport = ROM16(bios->data[offset + 1]); - uint8_t crtcindex = bios->data[offset + 3]; - uint8_t mask = bios->data[offset + 4]; - uint8_t shift = bios->data[offset + 5]; - uint8_t count = bios->data[offset + 6]; - uint32_t reg = ROM32(bios->data[offset + 7]); - uint8_t config; - uint32_t configval; - int len = 11 + count * 4; - - if (!iexec->execute) - return len; - - BIOSLOG(bios, "0x%04X: Port: 0x%04X, Index: 0x%02X, Mask: 0x%02X, " - "Shift: 0x%02X, Count: 0x%02X, Reg: 0x%08X\n", - offset, crtcport, crtcindex, mask, shift, count, reg); - - config = (bios_idxprt_rd(bios, crtcport, crtcindex) & mask) >> shift; - if (config > count) { - NV_ERROR(bios->dev, - "0x%04X: Config 0x%02X exceeds maximal bound 0x%02X\n", - offset, config, count); - return len; - } - - configval = ROM32(bios->data[offset + 11 + config * 4]); - - BIOSLOG(bios, "0x%04X: Writing config %02X\n", offset, config); - - bios_wr32(bios, reg, configval); - - return len; -} - -static int -init_repeat(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) -{ - /* - * INIT_REPEAT opcode: 0x33 ('3') - * - * offset (8 bit): opcode - * offset + 1 (8 bit): count - * - * Execute script following this opcode up to INIT_REPEAT_END - * "count" times - */ - - uint8_t count = bios->data[offset + 1]; - uint8_t i; - - /* no iexec->execute check by design */ - - BIOSLOG(bios, "0x%04X: Repeating following segment %d times\n", - offset, count); - - iexec->repeat = true; - - /* - * count - 1, as the script block will execute once when we leave this - * opcode -- this is compatible with bios behaviour as: - * a) the block is always executed at least once, even if count == 0 - * b) the bios interpreter skips to the op following INIT_END_REPEAT, - * while we don't - */ - for (i = 0; i < count - 1; i++) - parse_init_table(bios, offset + 2, iexec); - - iexec->repeat = false; - - return 2; -} - -static int -init_io_restrict_pll(struct nvbios *bios, uint16_t offset, - struct init_exec *iexec) -{ - /* - * INIT_IO_RESTRICT_PLL opcode: 0x34 ('4') - * - * offset (8 bit): opcode - * offset + 1 (16 bit): CRTC port - * offset + 3 (8 bit): CRTC index - * offset + 4 (8 bit): mask - * offset + 5 (8 bit): shift - * offset + 6 (8 bit): IO flag condition index - * offset + 7 (8 bit): count - * offset + 8 (32 bit): register - * offset + 12 (16 bit): frequency 1 - * ... - * - * Starting at offset + 12 there are "count" 16 bit frequencies (10kHz). - * Set PLL register "register" to coefficients for frequency n, - * selected by reading index "CRTC index" of "CRTC port" ANDed with - * "mask" and shifted right by "shift". - * - * If "IO flag condition index" > 0, and condition met, double - * frequency before setting it. - */ - - uint16_t crtcport = ROM16(bios->data[offset + 1]); - uint8_t crtcindex = bios->data[offset + 3]; - uint8_t mask = bios->data[offset + 4]; - uint8_t shift = bios->data[offset + 5]; - int8_t io_flag_condition_idx = bios->data[offset + 6]; - uint8_t count = bios->data[offset + 7]; - uint32_t reg = ROM32(bios->data[offset + 8]); - uint8_t config; - uint16_t freq; - int len = 12 + count * 2; - - if (!iexec->execute) - return len; - - BIOSLOG(bios, "0x%04X: Port: 0x%04X, Index: 0x%02X, Mask: 0x%02X, " - "Shift: 0x%02X, IO Flag Condition: 0x%02X, " - "Count: 0x%02X, Reg: 0x%08X\n", - offset, crtcport, crtcindex, mask, shift, - io_flag_condition_idx, count, reg); - - config = (bios_idxprt_rd(bios, crtcport, crtcindex) & mask) >> shift; - if (config > count) { - NV_ERROR(bios->dev, - "0x%04X: Config 0x%02X exceeds maximal bound 0x%02X\n", - offset, config, count); - return len; - } - - freq = ROM16(bios->data[offset + 12 + config * 2]); - - if (io_flag_condition_idx > 0) { - if (io_flag_condition_met(bios, offset, io_flag_condition_idx)) { - BIOSLOG(bios, "0x%04X: Condition fulfilled -- " - "frequency doubled\n", offset); - freq *= 2; - } else - BIOSLOG(bios, "0x%04X: Condition not fulfilled -- " - "frequency unchanged\n", offset); - } - - BIOSLOG(bios, "0x%04X: Reg: 0x%08X, Config: 0x%02X, Freq: %d0kHz\n", - offset, reg, config, freq); - - setPLL(bios->dev, reg, freq * 10); - - return len; -} - -static int -init_end_repeat(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) -{ - /* - * INIT_END_REPEAT opcode: 0x36 ('6') - * - * offset (8 bit): opcode - * - * Marks the end of the block for INIT_REPEAT to repeat - */ - - /* no iexec->execute check by design */ - - /* - * iexec->repeat flag necessary to go past INIT_END_REPEAT opcode when - * we're not in repeat mode - */ - if (iexec->repeat) - return 0; - - return 1; -} - -static int -init_copy(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) -{ - /* - * INIT_COPY opcode: 0x37 ('7') - * - * offset (8 bit): opcode - * offset + 1 (32 bit): register - * offset + 5 (8 bit): shift - * offset + 6 (8 bit): srcmask - * offset + 7 (16 bit): CRTC port - * offset + 9 (8 bit): CRTC index - * offset + 10 (8 bit): mask - * - * Read index "CRTC index" on "CRTC port", AND with "mask", OR with - * (REGVAL("register") >> "shift" & "srcmask") and write-back to CRTC - * port - */ - - uint32_t reg = ROM32(bios->data[offset + 1]); - uint8_t shift = bios->data[offset + 5]; - uint8_t srcmask = bios->data[offset + 6]; - uint16_t crtcport = ROM16(bios->data[offset + 7]); - uint8_t crtcindex = bios->data[offset + 9]; - uint8_t mask = bios->data[offset + 10]; - uint32_t data; - uint8_t crtcdata; - - if (!iexec->execute) - return 11; - - BIOSLOG(bios, "0x%04X: Reg: 0x%08X, Shift: 0x%02X, SrcMask: 0x%02X, " - "Port: 0x%04X, Index: 0x%02X, Mask: 0x%02X\n", - offset, reg, shift, srcmask, crtcport, crtcindex, mask); - - data = bios_rd32(bios, reg); - - if (shift < 0x80) - data >>= shift; - else - data <<= (0x100 - shift); - - data &= srcmask; - - crtcdata = bios_idxprt_rd(bios, crtcport, crtcindex) & mask; - crtcdata |= (uint8_t)data; - bios_idxprt_wr(bios, crtcport, crtcindex, crtcdata); - - return 11; -} - -static int -init_not(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) -{ - /* - * INIT_NOT opcode: 0x38 ('8') - * - * offset (8 bit): opcode - * - * Invert the current execute / no-execute condition (i.e. "else") - */ - if (iexec->execute) - BIOSLOG(bios, "0x%04X: ------ Skipping following commands ------\n", offset); - else - BIOSLOG(bios, "0x%04X: ------ Executing following commands ------\n", offset); - - iexec->execute = !iexec->execute; - return 1; -} - -static int -init_io_flag_condition(struct nvbios *bios, uint16_t offset, - struct init_exec *iexec) -{ - /* - * INIT_IO_FLAG_CONDITION opcode: 0x39 ('9') - * - * offset (8 bit): opcode - * offset + 1 (8 bit): condition number - * - * Check condition "condition number" in the IO flag condition table. - * If condition not met skip subsequent opcodes until condition is - * inverted (INIT_NOT), or we hit INIT_RESUME - */ - - uint8_t cond = bios->data[offset + 1]; - - if (!iexec->execute) - return 2; - - if (io_flag_condition_met(bios, offset, cond)) - BIOSLOG(bios, "0x%04X: Condition fulfilled -- continuing to execute\n", offset); - else { - BIOSLOG(bios, "0x%04X: Condition not fulfilled -- skipping following commands\n", offset); - iexec->execute = false; - } - - return 2; -} - -static int -init_dp_condition(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) -{ - /* - * INIT_DP_CONDITION opcode: 0x3A ('') - * - * offset (8 bit): opcode - * offset + 1 (8 bit): "sub" opcode - * offset + 2 (8 bit): unknown - * - */ - - struct dcb_entry *dcb = bios->display.output; - struct drm_device *dev = bios->dev; - uint8_t cond = bios->data[offset + 1]; - uint8_t *table, *entry; - - BIOSLOG(bios, "0x%04X: subop 0x%02X\n", offset, cond); - - if (!iexec->execute) - return 3; - - table = nouveau_dp_bios_data(dev, dcb, &entry); - if (!table) - return 3; - - switch (cond) { - case 0: - entry = dcb_conn(dev, dcb->connector); - if (!entry || entry[0] != DCB_CONNECTOR_eDP) - iexec->execute = false; - break; - case 1: - case 2: - if ((table[0] < 0x40 && !(entry[5] & cond)) || - (table[0] == 0x40 && !(entry[4] & cond))) - iexec->execute = false; - break; - case 5: - { - struct nouveau_i2c_port *auxch; - int ret; - - auxch = nouveau_i2c_find(dev, bios->display.output->i2c_index); - if (!auxch) { - NV_ERROR(dev, "0x%04X: couldn't get auxch\n", offset); - return 3; - } - - ret = auxch_rd(dev, auxch, 0xd, &cond, 1); - if (ret) { - NV_ERROR(dev, "0x%04X: auxch rd fail: %d\n", offset, ret); - return 3; - } - - if (!(cond & 1)) - iexec->execute = false; - } - break; - default: - NV_WARN(dev, "0x%04X: unknown INIT_3A op: %d\n", offset, cond); - break; - } - - if (iexec->execute) - BIOSLOG(bios, "0x%04X: continuing to execute\n", offset); - else - BIOSLOG(bios, "0x%04X: skipping following commands\n", offset); - - return 3; -} - -static int -init_op_3b(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) -{ - /* - * INIT_3B opcode: 0x3B ('') - * - * offset (8 bit): opcode - * offset + 1 (8 bit): crtc index - * - */ - - uint8_t or = ffs(bios->display.output->or) - 1; - uint8_t index = bios->data[offset + 1]; - uint8_t data; - - if (!iexec->execute) - return 2; - - data = bios_idxprt_rd(bios, 0x3d4, index); - bios_idxprt_wr(bios, 0x3d4, index, data & ~(1 << or)); - return 2; -} - -static int -init_op_3c(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) -{ - /* - * INIT_3C opcode: 0x3C ('') - * - * offset (8 bit): opcode - * offset + 1 (8 bit): crtc index - * - */ - - uint8_t or = ffs(bios->display.output->or) - 1; - uint8_t index = bios->data[offset + 1]; - uint8_t data; - - if (!iexec->execute) - return 2; - - data = bios_idxprt_rd(bios, 0x3d4, index); - bios_idxprt_wr(bios, 0x3d4, index, data | (1 << or)); - return 2; -} - -static int -init_idx_addr_latched(struct nvbios *bios, uint16_t offset, - struct init_exec *iexec) -{ - /* - * INIT_INDEX_ADDRESS_LATCHED opcode: 0x49 ('I') - * - * offset (8 bit): opcode - * offset + 1 (32 bit): control register - * offset + 5 (32 bit): data register - * offset + 9 (32 bit): mask - * offset + 13 (32 bit): data - * offset + 17 (8 bit): count - * offset + 18 (8 bit): address 1 - * offset + 19 (8 bit): data 1 - * ... - * - * For each of "count" address and data pairs, write "data n" to - * "data register", read the current value of "control register", - * and write it back once ANDed with "mask", ORed with "data", - * and ORed with "address n" - */ - - uint32_t controlreg = ROM32(bios->data[offset + 1]); - uint32_t datareg = ROM32(bios->data[offset + 5]); - uint32_t mask = ROM32(bios->data[offset + 9]); - uint32_t data = ROM32(bios->data[offset + 13]); - uint8_t count = bios->data[offset + 17]; - int len = 18 + count * 2; - uint32_t value; - int i; - - if (!iexec->execute) - return len; - - BIOSLOG(bios, "0x%04X: ControlReg: 0x%08X, DataReg: 0x%08X, " - "Mask: 0x%08X, Data: 0x%08X, Count: 0x%02X\n", - offset, controlreg, datareg, mask, data, count); - - for (i = 0; i < count; i++) { - uint8_t instaddress = bios->data[offset + 18 + i * 2]; - uint8_t instdata = bios->data[offset + 19 + i * 2]; - - BIOSLOG(bios, "0x%04X: Address: 0x%02X, Data: 0x%02X\n", - offset, instaddress, instdata); - - bios_wr32(bios, datareg, instdata); - value = bios_rd32(bios, controlreg) & mask; - value |= data; - value |= instaddress; - bios_wr32(bios, controlreg, value); - } - - return len; -} - -static int -init_io_restrict_pll2(struct nvbios *bios, uint16_t offset, - struct init_exec *iexec) -{ - /* - * INIT_IO_RESTRICT_PLL2 opcode: 0x4A ('J') - * - * offset (8 bit): opcode - * offset + 1 (16 bit): CRTC port - * offset + 3 (8 bit): CRTC index - * offset + 4 (8 bit): mask - * offset + 5 (8 bit): shift - * offset + 6 (8 bit): count - * offset + 7 (32 bit): register - * offset + 11 (32 bit): frequency 1 - * ... - * - * Starting at offset + 11 there are "count" 32 bit frequencies (kHz). - * Set PLL register "register" to coefficients for frequency n, - * selected by reading index "CRTC index" of "CRTC port" ANDed with - * "mask" and shifted right by "shift". - */ - - uint16_t crtcport = ROM16(bios->data[offset + 1]); - uint8_t crtcindex = bios->data[offset + 3]; - uint8_t mask = bios->data[offset + 4]; - uint8_t shift = bios->data[offset + 5]; - uint8_t count = bios->data[offset + 6]; - uint32_t reg = ROM32(bios->data[offset + 7]); - int len = 11 + count * 4; - uint8_t config; - uint32_t freq; - - if (!iexec->execute) - return len; - - BIOSLOG(bios, "0x%04X: Port: 0x%04X, Index: 0x%02X, Mask: 0x%02X, " - "Shift: 0x%02X, Count: 0x%02X, Reg: 0x%08X\n", - offset, crtcport, crtcindex, mask, shift, count, reg); - - if (!reg) - return len; - - config = (bios_idxprt_rd(bios, crtcport, crtcindex) & mask) >> shift; - if (config > count) { - NV_ERROR(bios->dev, - "0x%04X: Config 0x%02X exceeds maximal bound 0x%02X\n", - offset, config, count); - return len; - } - - freq = ROM32(bios->data[offset + 11 + config * 4]); - - BIOSLOG(bios, "0x%04X: Reg: 0x%08X, Config: 0x%02X, Freq: %dkHz\n", - offset, reg, config, freq); - - setPLL(bios->dev, reg, freq); - - return len; -} - -static int -init_pll2(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) -{ - /* - * INIT_PLL2 opcode: 0x4B ('K') - * - * offset (8 bit): opcode - * offset + 1 (32 bit): register - * offset + 5 (32 bit): freq - * - * Set PLL register "register" to coefficients for frequency "freq" - */ - - uint32_t reg = ROM32(bios->data[offset + 1]); - uint32_t freq = ROM32(bios->data[offset + 5]); - - if (!iexec->execute) - return 9; - - BIOSLOG(bios, "0x%04X: Reg: 0x%04X, Freq: %dkHz\n", - offset, reg, freq); - - setPLL(bios->dev, reg, freq); - return 9; -} - -static int -init_i2c_byte(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) -{ - /* - * INIT_I2C_BYTE opcode: 0x4C ('L') - * - * offset (8 bit): opcode - * offset + 1 (8 bit): DCB I2C table entry index - * offset + 2 (8 bit): I2C slave address - * offset + 3 (8 bit): count - * offset + 4 (8 bit): I2C register 1 - * offset + 5 (8 bit): mask 1 - * offset + 6 (8 bit): data 1 - * ... - * - * For each of "count" registers given by "I2C register n" on the device - * addressed by "I2C slave address" on the I2C bus given by - * "DCB I2C table entry index", read the register, AND the result with - * "mask n" and OR it with "data n" before writing it back to the device - */ - - struct drm_device *dev = bios->dev; - uint8_t i2c_index = bios->data[offset + 1]; - uint8_t i2c_address = bios->data[offset + 2] >> 1; - uint8_t count = bios->data[offset + 3]; - struct nouveau_i2c_port *chan; - int len = 4 + count * 3; - int ret, i; - - if (!iexec->execute) - return len; - - BIOSLOG(bios, "0x%04X: DCBI2CIndex: 0x%02X, I2CAddress: 0x%02X, " - "Count: 0x%02X\n", - offset, i2c_index, i2c_address, count); - - chan = init_i2c_device_find(dev, i2c_index); - if (!chan) { - NV_ERROR(dev, "0x%04X: i2c bus not found\n", offset); - return len; - } - - for (i = 0; i < count; i++) { - uint8_t reg = bios->data[offset + 4 + i * 3]; - uint8_t mask = bios->data[offset + 5 + i * 3]; - uint8_t data = bios->data[offset + 6 + i * 3]; - union i2c_smbus_data val; - - ret = i2c_smbus_xfer(nouveau_i2c_adapter(chan), i2c_address, 0, - I2C_SMBUS_READ, reg, - I2C_SMBUS_BYTE_DATA, &val); - if (ret < 0) { - NV_ERROR(dev, "0x%04X: i2c rd fail: %d\n", offset, ret); - return len; - } - - BIOSLOG(bios, "0x%04X: I2CReg: 0x%02X, Value: 0x%02X, " - "Mask: 0x%02X, Data: 0x%02X\n", - offset, reg, val.byte, mask, data); - - if (!bios->execute) - continue; - - val.byte &= mask; - val.byte |= data; - ret = i2c_smbus_xfer(nouveau_i2c_adapter(chan), i2c_address, 0, - I2C_SMBUS_WRITE, reg, - I2C_SMBUS_BYTE_DATA, &val); - if (ret < 0) { - NV_ERROR(dev, "0x%04X: i2c wr fail: %d\n", offset, ret); - return len; - } - } - - return len; -} - -static int -init_zm_i2c_byte(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) -{ - /* - * INIT_ZM_I2C_BYTE opcode: 0x4D ('M') - * - * offset (8 bit): opcode - * offset + 1 (8 bit): DCB I2C table entry index - * offset + 2 (8 bit): I2C slave address - * offset + 3 (8 bit): count - * offset + 4 (8 bit): I2C register 1 - * offset + 5 (8 bit): data 1 - * ... - * - * For each of "count" registers given by "I2C register n" on the device - * addressed by "I2C slave address" on the I2C bus given by - * "DCB I2C table entry index", set the register to "data n" - */ - - struct drm_device *dev = bios->dev; - uint8_t i2c_index = bios->data[offset + 1]; - uint8_t i2c_address = bios->data[offset + 2] >> 1; - uint8_t count = bios->data[offset + 3]; - struct nouveau_i2c_port *chan; - int len = 4 + count * 2; - int ret, i; - - if (!iexec->execute) - return len; - - BIOSLOG(bios, "0x%04X: DCBI2CIndex: 0x%02X, I2CAddress: 0x%02X, " - "Count: 0x%02X\n", - offset, i2c_index, i2c_address, count); - - chan = init_i2c_device_find(dev, i2c_index); - if (!chan) { - NV_ERROR(dev, "0x%04X: i2c bus not found\n", offset); - return len; - } - - for (i = 0; i < count; i++) { - uint8_t reg = bios->data[offset + 4 + i * 2]; - union i2c_smbus_data val; - - val.byte = bios->data[offset + 5 + i * 2]; - - BIOSLOG(bios, "0x%04X: I2CReg: 0x%02X, Data: 0x%02X\n", - offset, reg, val.byte); - - if (!bios->execute) - continue; - - ret = i2c_smbus_xfer(nouveau_i2c_adapter(chan), i2c_address, 0, - I2C_SMBUS_WRITE, reg, - I2C_SMBUS_BYTE_DATA, &val); - if (ret < 0) { - NV_ERROR(dev, "0x%04X: i2c wr fail: %d\n", offset, ret); - return len; - } - } - - return len; -} - -static int -init_zm_i2c(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) -{ - /* - * INIT_ZM_I2C opcode: 0x4E ('N') - * - * offset (8 bit): opcode - * offset + 1 (8 bit): DCB I2C table entry index - * offset + 2 (8 bit): I2C slave address - * offset + 3 (8 bit): count - * offset + 4 (8 bit): data 1 - * ... - * - * Send "count" bytes ("data n") to the device addressed by "I2C slave - * address" on the I2C bus given by "DCB I2C table entry index" - */ - - struct drm_device *dev = bios->dev; - uint8_t i2c_index = bios->data[offset + 1]; - uint8_t i2c_address = bios->data[offset + 2] >> 1; - uint8_t count = bios->data[offset + 3]; - int len = 4 + count; - struct nouveau_i2c_port *chan; - struct i2c_msg msg; - uint8_t data[256]; - int ret, i; - - if (!iexec->execute) - return len; - - BIOSLOG(bios, "0x%04X: DCBI2CIndex: 0x%02X, I2CAddress: 0x%02X, " - "Count: 0x%02X\n", - offset, i2c_index, i2c_address, count); - - chan = init_i2c_device_find(dev, i2c_index); - if (!chan) { - NV_ERROR(dev, "0x%04X: i2c bus not found\n", offset); - return len; - } - - for (i = 0; i < count; i++) { - data[i] = bios->data[offset + 4 + i]; - - BIOSLOG(bios, "0x%04X: Data: 0x%02X\n", offset, data[i]); - } - - if (bios->execute) { - msg.addr = i2c_address; - msg.flags = 0; - msg.len = count; - msg.buf = data; - ret = i2c_transfer(nouveau_i2c_adapter(chan), &msg, 1); - if (ret != 1) { - NV_ERROR(dev, "0x%04X: i2c wr fail: %d\n", offset, ret); - return len; - } - } - - return len; -} - -static int -init_tmds(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) -{ - /* - * INIT_TMDS opcode: 0x4F ('O') (non-canon name) - * - * offset (8 bit): opcode - * offset + 1 (8 bit): magic lookup value - * offset + 2 (8 bit): TMDS address - * offset + 3 (8 bit): mask - * offset + 4 (8 bit): data - * - * Read the data reg for TMDS address "TMDS address", AND it with mask - * and OR it with data, then write it back - * "magic lookup value" determines which TMDS base address register is - * used -- see get_tmds_index_reg() - */ - - struct drm_device *dev = bios->dev; - uint8_t mlv = bios->data[offset + 1]; - uint32_t tmdsaddr = bios->data[offset + 2]; - uint8_t mask = bios->data[offset + 3]; - uint8_t data = bios->data[offset + 4]; - uint32_t reg, value; - - if (!iexec->execute) - return 5; - - BIOSLOG(bios, "0x%04X: MagicLookupValue: 0x%02X, TMDSAddr: 0x%02X, " - "Mask: 0x%02X, Data: 0x%02X\n", - offset, mlv, tmdsaddr, mask, data); - - reg = get_tmds_index_reg(bios->dev, mlv); - if (!reg) { - NV_ERROR(dev, "0x%04X: no tmds_index_reg\n", offset); - return 5; - } - - bios_wr32(bios, reg, - tmdsaddr | NV_PRAMDAC_FP_TMDS_CONTROL_WRITE_DISABLE); - value = (bios_rd32(bios, reg + 4) & mask) | data; - bios_wr32(bios, reg + 4, value); - bios_wr32(bios, reg, tmdsaddr); - - return 5; -} - -static int -init_zm_tmds_group(struct nvbios *bios, uint16_t offset, - struct init_exec *iexec) -{ - /* - * INIT_ZM_TMDS_GROUP opcode: 0x50 ('P') (non-canon name) - * - * offset (8 bit): opcode - * offset + 1 (8 bit): magic lookup value - * offset + 2 (8 bit): count - * offset + 3 (8 bit): addr 1 - * offset + 4 (8 bit): data 1 - * ... - * - * For each of "count" TMDS address and data pairs write "data n" to - * "addr n". "magic lookup value" determines which TMDS base address - * register is used -- see get_tmds_index_reg() - */ - - struct drm_device *dev = bios->dev; - uint8_t mlv = bios->data[offset + 1]; - uint8_t count = bios->data[offset + 2]; - int len = 3 + count * 2; - uint32_t reg; - int i; - - if (!iexec->execute) - return len; - - BIOSLOG(bios, "0x%04X: MagicLookupValue: 0x%02X, Count: 0x%02X\n", - offset, mlv, count); - - reg = get_tmds_index_reg(bios->dev, mlv); - if (!reg) { - NV_ERROR(dev, "0x%04X: no tmds_index_reg\n", offset); - return len; - } - - for (i = 0; i < count; i++) { - uint8_t tmdsaddr = bios->data[offset + 3 + i * 2]; - uint8_t tmdsdata = bios->data[offset + 4 + i * 2]; - - bios_wr32(bios, reg + 4, tmdsdata); - bios_wr32(bios, reg, tmdsaddr); - } - - return len; -} - -static int -init_cr_idx_adr_latch(struct nvbios *bios, uint16_t offset, - struct init_exec *iexec) -{ - /* - * INIT_CR_INDEX_ADDRESS_LATCHED opcode: 0x51 ('Q') - * - * offset (8 bit): opcode - * offset + 1 (8 bit): CRTC index1 - * offset + 2 (8 bit): CRTC index2 - * offset + 3 (8 bit): baseaddr - * offset + 4 (8 bit): count - * offset + 5 (8 bit): data 1 - * ... - * - * For each of "count" address and data pairs, write "baseaddr + n" to - * "CRTC index1" and "data n" to "CRTC index2" - * Once complete, restore initial value read from "CRTC index1" - */ - uint8_t crtcindex1 = bios->data[offset + 1]; - uint8_t crtcindex2 = bios->data[offset + 2]; - uint8_t baseaddr = bios->data[offset + 3]; - uint8_t count = bios->data[offset + 4]; - int len = 5 + count; - uint8_t oldaddr, data; - int i; - - if (!iexec->execute) - return len; - - BIOSLOG(bios, "0x%04X: Index1: 0x%02X, Index2: 0x%02X, " - "BaseAddr: 0x%02X, Count: 0x%02X\n", - offset, crtcindex1, crtcindex2, baseaddr, count); - - oldaddr = bios_idxprt_rd(bios, NV_CIO_CRX__COLOR, crtcindex1); - - for (i = 0; i < count; i++) { - bios_idxprt_wr(bios, NV_CIO_CRX__COLOR, crtcindex1, - baseaddr + i); - data = bios->data[offset + 5 + i]; - bios_idxprt_wr(bios, NV_CIO_CRX__COLOR, crtcindex2, data); - } - - bios_idxprt_wr(bios, NV_CIO_CRX__COLOR, crtcindex1, oldaddr); - - return len; -} - -static int -init_cr(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) -{ - /* - * INIT_CR opcode: 0x52 ('R') - * - * offset (8 bit): opcode - * offset + 1 (8 bit): CRTC index - * offset + 2 (8 bit): mask - * offset + 3 (8 bit): data - * - * Assign the value of at "CRTC index" ANDed with mask and ORed with - * data back to "CRTC index" - */ - - uint8_t crtcindex = bios->data[offset + 1]; - uint8_t mask = bios->data[offset + 2]; - uint8_t data = bios->data[offset + 3]; - uint8_t value; - - if (!iexec->execute) - return 4; - - BIOSLOG(bios, "0x%04X: Index: 0x%02X, Mask: 0x%02X, Data: 0x%02X\n", - offset, crtcindex, mask, data); - - value = bios_idxprt_rd(bios, NV_CIO_CRX__COLOR, crtcindex) & mask; - value |= data; - bios_idxprt_wr(bios, NV_CIO_CRX__COLOR, crtcindex, value); - - return 4; -} - -static int -init_zm_cr(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) -{ - /* - * INIT_ZM_CR opcode: 0x53 ('S') - * - * offset (8 bit): opcode - * offset + 1 (8 bit): CRTC index - * offset + 2 (8 bit): value - * - * Assign "value" to CRTC register with index "CRTC index". - */ - - uint8_t crtcindex = ROM32(bios->data[offset + 1]); - uint8_t data = bios->data[offset + 2]; - - if (!iexec->execute) - return 3; - - bios_idxprt_wr(bios, NV_CIO_CRX__COLOR, crtcindex, data); - - return 3; -} - -static int -init_zm_cr_group(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) -{ - /* - * INIT_ZM_CR_GROUP opcode: 0x54 ('T') - * - * offset (8 bit): opcode - * offset + 1 (8 bit): count - * offset + 2 (8 bit): CRTC index 1 - * offset + 3 (8 bit): value 1 - * ... - * - * For "count", assign "value n" to CRTC register with index - * "CRTC index n". - */ - - uint8_t count = bios->data[offset + 1]; - int len = 2 + count * 2; - int i; - - if (!iexec->execute) - return len; - - for (i = 0; i < count; i++) - init_zm_cr(bios, offset + 2 + 2 * i - 1, iexec); - - return len; -} - -static int -init_condition_time(struct nvbios *bios, uint16_t offset, - struct init_exec *iexec) -{ - /* - * INIT_CONDITION_TIME opcode: 0x56 ('V') - * - * offset (8 bit): opcode - * offset + 1 (8 bit): condition number - * offset + 2 (8 bit): retries / 50 - * - * Check condition "condition number" in the condition table. - * Bios code then sleeps for 2ms if the condition is not met, and - * repeats up to "retries" times, but on one C51 this has proved - * insufficient. In mmiotraces the driver sleeps for 20ms, so we do - * this, and bail after "retries" times, or 2s, whichever is less. - * If still not met after retries, clear execution flag for this table. - */ - - uint8_t cond = bios->data[offset + 1]; - uint16_t retries = bios->data[offset + 2] * 50; - unsigned cnt; - - if (!iexec->execute) - return 3; - - if (retries > 100) - retries = 100; - - BIOSLOG(bios, "0x%04X: Condition: 0x%02X, Retries: 0x%02X\n", - offset, cond, retries); - - if (!bios->execute) /* avoid 2s delays when "faking" execution */ - retries = 1; - - for (cnt = 0; cnt < retries; cnt++) { - if (bios_condition_met(bios, offset, cond)) { - BIOSLOG(bios, "0x%04X: Condition met, continuing\n", - offset); - break; - } else { - BIOSLOG(bios, "0x%04X: " - "Condition not met, sleeping for 20ms\n", - offset); - mdelay(20); - } - } - - if (!bios_condition_met(bios, offset, cond)) { - NV_WARN(bios->dev, - "0x%04X: Condition still not met after %dms, " - "skipping following opcodes\n", offset, 20 * retries); - iexec->execute = false; - } - - return 3; -} - -static int -init_ltime(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) -{ - /* - * INIT_LTIME opcode: 0x57 ('V') - * - * offset (8 bit): opcode - * offset + 1 (16 bit): time - * - * Sleep for "time" milliseconds. - */ - - unsigned time = ROM16(bios->data[offset + 1]); - - if (!iexec->execute) - return 3; - - BIOSLOG(bios, "0x%04X: Sleeping for 0x%04X milliseconds\n", - offset, time); - - mdelay(time); - - return 3; -} - -static int -init_zm_reg_sequence(struct nvbios *bios, uint16_t offset, - struct init_exec *iexec) -{ - /* - * INIT_ZM_REG_SEQUENCE opcode: 0x58 ('X') - * - * offset (8 bit): opcode - * offset + 1 (32 bit): base register - * offset + 5 (8 bit): count - * offset + 6 (32 bit): value 1 - * ... - * - * Starting at offset + 6 there are "count" 32 bit values. - * For "count" iterations set "base register" + 4 * current_iteration - * to "value current_iteration" - */ - - uint32_t basereg = ROM32(bios->data[offset + 1]); - uint32_t count = bios->data[offset + 5]; - int len = 6 + count * 4; - int i; - - if (!iexec->execute) - return len; - - BIOSLOG(bios, "0x%04X: BaseReg: 0x%08X, Count: 0x%02X\n", - offset, basereg, count); - - for (i = 0; i < count; i++) { - uint32_t reg = basereg + i * 4; - uint32_t data = ROM32(bios->data[offset + 6 + i * 4]); - - bios_wr32(bios, reg, data); - } - - return len; -} - -static int -init_sub_direct(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) -{ - /* - * INIT_SUB_DIRECT opcode: 0x5B ('[') - * - * offset (8 bit): opcode - * offset + 1 (16 bit): subroutine offset (in bios) - * - * Calls a subroutine that will execute commands until INIT_DONE - * is found. - */ - - uint16_t sub_offset = ROM16(bios->data[offset + 1]); - - if (!iexec->execute) - return 3; - - BIOSLOG(bios, "0x%04X: Executing subroutine at 0x%04X\n", - offset, sub_offset); - - parse_init_table(bios, sub_offset, iexec); - - BIOSLOG(bios, "0x%04X: End of 0x%04X subroutine\n", offset, sub_offset); - - return 3; -} - -static int -init_jump(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) -{ - /* - * INIT_JUMP opcode: 0x5C ('\') - * - * offset (8 bit): opcode - * offset + 1 (16 bit): offset (in bios) - * - * Continue execution of init table from 'offset' - */ - - uint16_t jmp_offset = ROM16(bios->data[offset + 1]); - - if (!iexec->execute) - return 3; - - BIOSLOG(bios, "0x%04X: Jump to 0x%04X\n", offset, jmp_offset); - return jmp_offset - offset; -} - -static int -init_i2c_if(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) -{ - /* - * INIT_I2C_IF opcode: 0x5E ('^') - * - * offset (8 bit): opcode - * offset + 1 (8 bit): DCB I2C table entry index - * offset + 2 (8 bit): I2C slave address - * offset + 3 (8 bit): I2C register - * offset + 4 (8 bit): mask - * offset + 5 (8 bit): data - * - * Read the register given by "I2C register" on the device addressed - * by "I2C slave address" on the I2C bus given by "DCB I2C table - * entry index". Compare the result AND "mask" to "data". - * If they're not equal, skip subsequent opcodes until condition is - * inverted (INIT_NOT), or we hit INIT_RESUME - */ - - uint8_t i2c_index = bios->data[offset + 1]; - uint8_t i2c_address = bios->data[offset + 2] >> 1; - uint8_t reg = bios->data[offset + 3]; - uint8_t mask = bios->data[offset + 4]; - uint8_t data = bios->data[offset + 5]; - struct nouveau_i2c_port *chan; - union i2c_smbus_data val; - int ret; - - /* no execute check by design */ - - BIOSLOG(bios, "0x%04X: DCBI2CIndex: 0x%02X, I2CAddress: 0x%02X\n", - offset, i2c_index, i2c_address); - - chan = init_i2c_device_find(bios->dev, i2c_index); - if (!chan) - return -ENODEV; - - ret = i2c_smbus_xfer(nouveau_i2c_adapter(chan), i2c_address, 0, - I2C_SMBUS_READ, reg, - I2C_SMBUS_BYTE_DATA, &val); - if (ret < 0) { - BIOSLOG(bios, "0x%04X: I2CReg: 0x%02X, Value: [no device], " - "Mask: 0x%02X, Data: 0x%02X\n", - offset, reg, mask, data); - iexec->execute = 0; - return 6; - } - - BIOSLOG(bios, "0x%04X: I2CReg: 0x%02X, Value: 0x%02X, " - "Mask: 0x%02X, Data: 0x%02X\n", - offset, reg, val.byte, mask, data); - - iexec->execute = ((val.byte & mask) == data); - - return 6; -} - -static int -init_copy_nv_reg(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) -{ - /* - * INIT_COPY_NV_REG opcode: 0x5F ('_') - * - * offset (8 bit): opcode - * offset + 1 (32 bit): src reg - * offset + 5 (8 bit): shift - * offset + 6 (32 bit): src mask - * offset + 10 (32 bit): xor - * offset + 14 (32 bit): dst reg - * offset + 18 (32 bit): dst mask - * - * Shift REGVAL("src reg") right by (signed) "shift", AND result with - * "src mask", then XOR with "xor". Write this OR'd with - * (REGVAL("dst reg") AND'd with "dst mask") to "dst reg" - */ - - uint32_t srcreg = *((uint32_t *)(&bios->data[offset + 1])); - uint8_t shift = bios->data[offset + 5]; - uint32_t srcmask = *((uint32_t *)(&bios->data[offset + 6])); - uint32_t xor = *((uint32_t *)(&bios->data[offset + 10])); - uint32_t dstreg = *((uint32_t *)(&bios->data[offset + 14])); - uint32_t dstmask = *((uint32_t *)(&bios->data[offset + 18])); - uint32_t srcvalue, dstvalue; - - if (!iexec->execute) - return 22; - - BIOSLOG(bios, "0x%04X: SrcReg: 0x%08X, Shift: 0x%02X, SrcMask: 0x%08X, " - "Xor: 0x%08X, DstReg: 0x%08X, DstMask: 0x%08X\n", - offset, srcreg, shift, srcmask, xor, dstreg, dstmask); - - srcvalue = bios_rd32(bios, srcreg); - - if (shift < 0x80) - srcvalue >>= shift; - else - srcvalue <<= (0x100 - shift); - - srcvalue = (srcvalue & srcmask) ^ xor; - - dstvalue = bios_rd32(bios, dstreg) & dstmask; - - bios_wr32(bios, dstreg, dstvalue | srcvalue); - - return 22; -} - -static int -init_zm_index_io(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) -{ - /* - * INIT_ZM_INDEX_IO opcode: 0x62 ('b') - * - * offset (8 bit): opcode - * offset + 1 (16 bit): CRTC port - * offset + 3 (8 bit): CRTC index - * offset + 4 (8 bit): data - * - * Write "data" to index "CRTC index" of "CRTC port" - */ - uint16_t crtcport = ROM16(bios->data[offset + 1]); - uint8_t crtcindex = bios->data[offset + 3]; - uint8_t data = bios->data[offset + 4]; - - if (!iexec->execute) - return 5; - - bios_idxprt_wr(bios, crtcport, crtcindex, data); - - return 5; -} - -static inline void -bios_md32(struct nvbios *bios, uint32_t reg, - uint32_t mask, uint32_t val) -{ - bios_wr32(bios, reg, (bios_rd32(bios, reg) & ~mask) | val); -} - -static uint32_t -peek_fb(struct drm_device *dev, struct io_mapping *fb, - uint32_t off) -{ - uint32_t val = 0; - - if (off < pci_resource_len(dev->pdev, 1)) { - uint8_t __iomem *p = - io_mapping_map_atomic_wc(fb, off & PAGE_MASK); - - val = ioread32(p + (off & ~PAGE_MASK)); - - io_mapping_unmap_atomic(p); - } - - return val; -} - -static void -poke_fb(struct drm_device *dev, struct io_mapping *fb, - uint32_t off, uint32_t val) -{ - if (off < pci_resource_len(dev->pdev, 1)) { - uint8_t __iomem *p = - io_mapping_map_atomic_wc(fb, off & PAGE_MASK); - - iowrite32(val, p + (off & ~PAGE_MASK)); - wmb(); - - io_mapping_unmap_atomic(p); - } -} - -static inline bool -read_back_fb(struct drm_device *dev, struct io_mapping *fb, - uint32_t off, uint32_t val) -{ - poke_fb(dev, fb, off, val); - return val == peek_fb(dev, fb, off); -} - -static int -nv04_init_compute_mem(struct nvbios *bios) -{ - struct drm_device *dev = bios->dev; - uint32_t patt = 0xdeadbeef; - struct io_mapping *fb; - int i; - - /* Map the framebuffer aperture */ - fb = io_mapping_create_wc(pci_resource_start(dev->pdev, 1), - pci_resource_len(dev->pdev, 1)); - if (!fb) - return -ENOMEM; - - /* Sequencer and refresh off */ - NVWriteVgaSeq(dev, 0, 1, NVReadVgaSeq(dev, 0, 1) | 0x20); - bios_md32(bios, NV04_PFB_DEBUG_0, 0, NV04_PFB_DEBUG_0_REFRESH_OFF); - - bios_md32(bios, NV04_PFB_BOOT_0, ~0, - NV04_PFB_BOOT_0_RAM_AMOUNT_16MB | - NV04_PFB_BOOT_0_RAM_WIDTH_128 | - NV04_PFB_BOOT_0_RAM_TYPE_SGRAM_16MBIT); - - for (i = 0; i < 4; i++) - poke_fb(dev, fb, 4 * i, patt); - - poke_fb(dev, fb, 0x400000, patt + 1); - - if (peek_fb(dev, fb, 0) == patt + 1) { - bios_md32(bios, NV04_PFB_BOOT_0, NV04_PFB_BOOT_0_RAM_TYPE, - NV04_PFB_BOOT_0_RAM_TYPE_SDRAM_16MBIT); - bios_md32(bios, NV04_PFB_DEBUG_0, - NV04_PFB_DEBUG_0_REFRESH_OFF, 0); - - for (i = 0; i < 4; i++) - poke_fb(dev, fb, 4 * i, patt); - - if ((peek_fb(dev, fb, 0xc) & 0xffff) != (patt & 0xffff)) - bios_md32(bios, NV04_PFB_BOOT_0, - NV04_PFB_BOOT_0_RAM_WIDTH_128 | - NV04_PFB_BOOT_0_RAM_AMOUNT, - NV04_PFB_BOOT_0_RAM_AMOUNT_8MB); - - } else if ((peek_fb(dev, fb, 0xc) & 0xffff0000) != - (patt & 0xffff0000)) { - bios_md32(bios, NV04_PFB_BOOT_0, - NV04_PFB_BOOT_0_RAM_WIDTH_128 | - NV04_PFB_BOOT_0_RAM_AMOUNT, - NV04_PFB_BOOT_0_RAM_AMOUNT_4MB); - - } else if (peek_fb(dev, fb, 0) != patt) { - if (read_back_fb(dev, fb, 0x800000, patt)) - bios_md32(bios, NV04_PFB_BOOT_0, - NV04_PFB_BOOT_0_RAM_AMOUNT, - NV04_PFB_BOOT_0_RAM_AMOUNT_8MB); - else - bios_md32(bios, NV04_PFB_BOOT_0, - NV04_PFB_BOOT_0_RAM_AMOUNT, - NV04_PFB_BOOT_0_RAM_AMOUNT_4MB); - - bios_md32(bios, NV04_PFB_BOOT_0, NV04_PFB_BOOT_0_RAM_TYPE, - NV04_PFB_BOOT_0_RAM_TYPE_SGRAM_8MBIT); - - } else if (!read_back_fb(dev, fb, 0x800000, patt)) { - bios_md32(bios, NV04_PFB_BOOT_0, NV04_PFB_BOOT_0_RAM_AMOUNT, - NV04_PFB_BOOT_0_RAM_AMOUNT_8MB); - - } - - /* Refresh on, sequencer on */ - bios_md32(bios, NV04_PFB_DEBUG_0, NV04_PFB_DEBUG_0_REFRESH_OFF, 0); - NVWriteVgaSeq(dev, 0, 1, NVReadVgaSeq(dev, 0, 1) & ~0x20); - - io_mapping_free(fb); - return 0; -} - -static const uint8_t * -nv05_memory_config(struct nvbios *bios) -{ - /* Defaults for BIOSes lacking a memory config table */ - static const uint8_t default_config_tab[][2] = { - { 0x24, 0x00 }, - { 0x28, 0x00 }, - { 0x24, 0x01 }, - { 0x1f, 0x00 }, - { 0x0f, 0x00 }, - { 0x17, 0x00 }, - { 0x06, 0x00 }, - { 0x00, 0x00 } - }; - int i = (bios_rd32(bios, NV_PEXTDEV_BOOT_0) & - NV_PEXTDEV_BOOT_0_RAMCFG) >> 2; - - if (bios->legacy.mem_init_tbl_ptr) - return &bios->data[bios->legacy.mem_init_tbl_ptr + 2 * i]; - else - return default_config_tab[i]; -} - -static int -nv05_init_compute_mem(struct nvbios *bios) -{ - struct drm_device *dev = bios->dev; - const uint8_t *ramcfg = nv05_memory_config(bios); - uint32_t patt = 0xdeadbeef; - struct io_mapping *fb; - int i, v; - - /* Map the framebuffer aperture */ - fb = io_mapping_create_wc(pci_resource_start(dev->pdev, 1), - pci_resource_len(dev->pdev, 1)); - if (!fb) - return -ENOMEM; - - /* Sequencer off */ - NVWriteVgaSeq(dev, 0, 1, NVReadVgaSeq(dev, 0, 1) | 0x20); - - if (bios_rd32(bios, NV04_PFB_BOOT_0) & NV04_PFB_BOOT_0_UMA_ENABLE) - goto out; - - bios_md32(bios, NV04_PFB_DEBUG_0, NV04_PFB_DEBUG_0_REFRESH_OFF, 0); - - /* If present load the hardcoded scrambling table */ - if (bios->legacy.mem_init_tbl_ptr) { - uint32_t *scramble_tab = (uint32_t *)&bios->data[ - bios->legacy.mem_init_tbl_ptr + 0x10]; - - for (i = 0; i < 8; i++) - bios_wr32(bios, NV04_PFB_SCRAMBLE(i), - ROM32(scramble_tab[i])); - } - - /* Set memory type/width/length defaults depending on the straps */ - bios_md32(bios, NV04_PFB_BOOT_0, 0x3f, ramcfg[0]); - - if (ramcfg[1] & 0x80) - bios_md32(bios, NV04_PFB_CFG0, 0, NV04_PFB_CFG0_SCRAMBLE); - - bios_md32(bios, NV04_PFB_CFG1, 0x700001, (ramcfg[1] & 1) << 20); - bios_md32(bios, NV04_PFB_CFG1, 0, 1); - - /* Probe memory bus width */ - for (i = 0; i < 4; i++) - poke_fb(dev, fb, 4 * i, patt); - - if (peek_fb(dev, fb, 0xc) != patt) - bios_md32(bios, NV04_PFB_BOOT_0, - NV04_PFB_BOOT_0_RAM_WIDTH_128, 0); - - /* Probe memory length */ - v = bios_rd32(bios, NV04_PFB_BOOT_0) & NV04_PFB_BOOT_0_RAM_AMOUNT; - - if (v == NV04_PFB_BOOT_0_RAM_AMOUNT_32MB && - (!read_back_fb(dev, fb, 0x1000000, ++patt) || - !read_back_fb(dev, fb, 0, ++patt))) - bios_md32(bios, NV04_PFB_BOOT_0, NV04_PFB_BOOT_0_RAM_AMOUNT, - NV04_PFB_BOOT_0_RAM_AMOUNT_16MB); - - if (v == NV04_PFB_BOOT_0_RAM_AMOUNT_16MB && - !read_back_fb(dev, fb, 0x800000, ++patt)) - bios_md32(bios, NV04_PFB_BOOT_0, NV04_PFB_BOOT_0_RAM_AMOUNT, - NV04_PFB_BOOT_0_RAM_AMOUNT_8MB); - - if (!read_back_fb(dev, fb, 0x400000, ++patt)) - bios_md32(bios, NV04_PFB_BOOT_0, NV04_PFB_BOOT_0_RAM_AMOUNT, - NV04_PFB_BOOT_0_RAM_AMOUNT_4MB); - -out: - /* Sequencer on */ - NVWriteVgaSeq(dev, 0, 1, NVReadVgaSeq(dev, 0, 1) & ~0x20); - - io_mapping_free(fb); - return 0; -} - -static int -nv10_init_compute_mem(struct nvbios *bios) -{ - struct drm_device *dev = bios->dev; - struct drm_nouveau_private *dev_priv = bios->dev->dev_private; - const int mem_width[] = { 0x10, 0x00, 0x20 }; - const int mem_width_count = (dev_priv->chipset >= 0x17 ? 3 : 2); - uint32_t patt = 0xdeadbeef; - struct io_mapping *fb; - int i, j, k; - - /* Map the framebuffer aperture */ - fb = io_mapping_create_wc(pci_resource_start(dev->pdev, 1), - pci_resource_len(dev->pdev, 1)); - if (!fb) - return -ENOMEM; - - bios_wr32(bios, NV10_PFB_REFCTRL, NV10_PFB_REFCTRL_VALID_1); - - /* Probe memory bus width */ - for (i = 0; i < mem_width_count; i++) { - bios_md32(bios, NV04_PFB_CFG0, 0x30, mem_width[i]); - - for (j = 0; j < 4; j++) { - for (k = 0; k < 4; k++) - poke_fb(dev, fb, 0x1c, 0); - - poke_fb(dev, fb, 0x1c, patt); - poke_fb(dev, fb, 0x3c, 0); - - if (peek_fb(dev, fb, 0x1c) == patt) - goto mem_width_found; - } - } - -mem_width_found: - patt <<= 1; - - /* Probe amount of installed memory */ - for (i = 0; i < 4; i++) { - int off = bios_rd32(bios, NV04_PFB_FIFO_DATA) - 0x100000; - - poke_fb(dev, fb, off, patt); - poke_fb(dev, fb, 0, 0); - - peek_fb(dev, fb, 0); - peek_fb(dev, fb, 0); - peek_fb(dev, fb, 0); - peek_fb(dev, fb, 0); - - if (peek_fb(dev, fb, off) == patt) - goto amount_found; - } - - /* IC missing - disable the upper half memory space. */ - bios_md32(bios, NV04_PFB_CFG0, 0x1000, 0); - -amount_found: - io_mapping_free(fb); - return 0; -} - -static int -nv20_init_compute_mem(struct nvbios *bios) -{ - struct drm_device *dev = bios->dev; - struct drm_nouveau_private *dev_priv = bios->dev->dev_private; - uint32_t mask = (dev_priv->chipset >= 0x25 ? 0x300 : 0x900); - uint32_t amount, off; - struct io_mapping *fb; - - /* Map the framebuffer aperture */ - fb = io_mapping_create_wc(pci_resource_start(dev->pdev, 1), - pci_resource_len(dev->pdev, 1)); - if (!fb) - return -ENOMEM; - - bios_wr32(bios, NV10_PFB_REFCTRL, NV10_PFB_REFCTRL_VALID_1); - - /* Allow full addressing */ - bios_md32(bios, NV04_PFB_CFG0, 0, mask); - - amount = bios_rd32(bios, NV04_PFB_FIFO_DATA); - for (off = amount; off > 0x2000000; off -= 0x2000000) - poke_fb(dev, fb, off - 4, off); - - amount = bios_rd32(bios, NV04_PFB_FIFO_DATA); - if (amount != peek_fb(dev, fb, amount - 4)) - /* IC missing - disable the upper half memory space. */ - bios_md32(bios, NV04_PFB_CFG0, mask, 0); - - io_mapping_free(fb); - return 0; -} - -static int -init_compute_mem(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) -{ - /* - * INIT_COMPUTE_MEM opcode: 0x63 ('c') - * - * offset (8 bit): opcode - * - * This opcode is meant to set the PFB memory config registers - * appropriately so that we can correctly calculate how much VRAM it - * has (on nv10 and better chipsets the amount of installed VRAM is - * subsequently reported in NV_PFB_CSTATUS (0x10020C)). - * - * The implementation of this opcode in general consists of several - * parts: - * - * 1) Determination of memory type and density. Only necessary for - * really old chipsets, the memory type reported by the strap bits - * (0x101000) is assumed to be accurate on nv05 and newer. - * - * 2) Determination of the memory bus width. Usually done by a cunning - * combination of writes to offsets 0x1c and 0x3c in the fb, and - * seeing whether the written values are read back correctly. - * - * Only necessary on nv0x-nv1x and nv34, on the other cards we can - * trust the straps. - * - * 3) Determination of how many of the card's RAM pads have ICs - * attached, usually done by a cunning combination of writes to an - * offset slightly less than the maximum memory reported by - * NV_PFB_CSTATUS, then seeing if the test pattern can be read back. - * - * This appears to be a NOP on IGPs and NV4x or newer chipsets, both io - * logs of the VBIOS and kmmio traces of the binary driver POSTing the - * card show nothing being done for this opcode. Why is it still listed - * in the table?! - */ - - /* no iexec->execute check by design */ - - struct drm_nouveau_private *dev_priv = bios->dev->dev_private; - int ret; - - if (dev_priv->chipset >= 0x40 || - dev_priv->chipset == 0x1a || - dev_priv->chipset == 0x1f) - ret = 0; - else if (dev_priv->chipset >= 0x20 && - dev_priv->chipset != 0x34) - ret = nv20_init_compute_mem(bios); - else if (dev_priv->chipset >= 0x10) - ret = nv10_init_compute_mem(bios); - else if (dev_priv->chipset >= 0x5) - ret = nv05_init_compute_mem(bios); - else - ret = nv04_init_compute_mem(bios); - - if (ret) - return ret; - - return 1; -} - -static int -init_reset(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) -{ - /* - * INIT_RESET opcode: 0x65 ('e') - * - * offset (8 bit): opcode - * offset + 1 (32 bit): register - * offset + 5 (32 bit): value1 - * offset + 9 (32 bit): value2 - * - * Assign "value1" to "register", then assign "value2" to "register" - */ - - uint32_t reg = ROM32(bios->data[offset + 1]); - uint32_t value1 = ROM32(bios->data[offset + 5]); - uint32_t value2 = ROM32(bios->data[offset + 9]); - uint32_t pci_nv_19, pci_nv_20; - - /* no iexec->execute check by design */ - - pci_nv_19 = bios_rd32(bios, NV_PBUS_PCI_NV_19); - bios_wr32(bios, NV_PBUS_PCI_NV_19, pci_nv_19 & ~0xf00); - - bios_wr32(bios, reg, value1); - - udelay(10); - - bios_wr32(bios, reg, value2); - bios_wr32(bios, NV_PBUS_PCI_NV_19, pci_nv_19); - - pci_nv_20 = bios_rd32(bios, NV_PBUS_PCI_NV_20); - pci_nv_20 &= ~NV_PBUS_PCI_NV_20_ROM_SHADOW_ENABLED; /* 0xfffffffe */ - bios_wr32(bios, NV_PBUS_PCI_NV_20, pci_nv_20); - - return 13; -} - -static int -init_configure_mem(struct nvbios *bios, uint16_t offset, - struct init_exec *iexec) -{ - /* - * INIT_CONFIGURE_MEM opcode: 0x66 ('f') - * - * offset (8 bit): opcode - * - * Equivalent to INIT_DONE on bios version 3 or greater. - * For early bios versions, sets up the memory registers, using values - * taken from the memory init table - */ - - /* no iexec->execute check by design */ - - uint16_t meminitoffs = bios->legacy.mem_init_tbl_ptr + MEM_INIT_SIZE * (bios_idxprt_rd(bios, NV_CIO_CRX__COLOR, NV_CIO_CRE_SCRATCH4__INDEX) >> 4); - uint16_t seqtbloffs = bios->legacy.sdr_seq_tbl_ptr, meminitdata = meminitoffs + 6; - uint32_t reg, data; - - if (bios->major_version > 2) - return 0; - - bios_idxprt_wr(bios, NV_VIO_SRX, NV_VIO_SR_CLOCK_INDEX, bios_idxprt_rd( - bios, NV_VIO_SRX, NV_VIO_SR_CLOCK_INDEX) | 0x20); - - if (bios->data[meminitoffs] & 1) - seqtbloffs = bios->legacy.ddr_seq_tbl_ptr; - - for (reg = ROM32(bios->data[seqtbloffs]); - reg != 0xffffffff; - reg = ROM32(bios->data[seqtbloffs += 4])) { - - switch (reg) { - case NV04_PFB_PRE: - data = NV04_PFB_PRE_CMD_PRECHARGE; - break; - case NV04_PFB_PAD: - data = NV04_PFB_PAD_CKE_NORMAL; - break; - case NV04_PFB_REF: - data = NV04_PFB_REF_CMD_REFRESH; - break; - default: - data = ROM32(bios->data[meminitdata]); - meminitdata += 4; - if (data == 0xffffffff) - continue; - } - - bios_wr32(bios, reg, data); - } - - return 1; -} - -static int -init_configure_clk(struct nvbios *bios, uint16_t offset, - struct init_exec *iexec) -{ - /* - * INIT_CONFIGURE_CLK opcode: 0x67 ('g') - * - * offset (8 bit): opcode - * - * Equivalent to INIT_DONE on bios version 3 or greater. - * For early bios versions, sets up the NVClk and MClk PLLs, using - * values taken from the memory init table - */ - - /* no iexec->execute check by design */ - - uint16_t meminitoffs = bios->legacy.mem_init_tbl_ptr + MEM_INIT_SIZE * (bios_idxprt_rd(bios, NV_CIO_CRX__COLOR, NV_CIO_CRE_SCRATCH4__INDEX) >> 4); - int clock; - - if (bios->major_version > 2) - return 0; - - clock = ROM16(bios->data[meminitoffs + 4]) * 10; - 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->dev, NV_PRAMDAC_MPLL_COEFF, clock); - - return 1; -} - -static int -init_configure_preinit(struct nvbios *bios, uint16_t offset, - struct init_exec *iexec) -{ - /* - * INIT_CONFIGURE_PREINIT opcode: 0x68 ('h') - * - * offset (8 bit): opcode - * - * Equivalent to INIT_DONE on bios version 3 or greater. - * For early bios versions, does early init, loading ram and crystal - * configuration from straps into CR3C - */ - - /* no iexec->execute check by design */ - - uint32_t straps = bios_rd32(bios, NV_PEXTDEV_BOOT_0); - uint8_t cr3c = ((straps << 2) & 0xf0) | (straps & 0x40) >> 6; - - if (bios->major_version > 2) - return 0; - - bios_idxprt_wr(bios, NV_CIO_CRX__COLOR, - NV_CIO_CRE_SCRATCH4__INDEX, cr3c); - - return 1; -} - -static int -init_io(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) -{ - /* - * INIT_IO opcode: 0x69 ('i') - * - * offset (8 bit): opcode - * offset + 1 (16 bit): CRTC port - * offset + 3 (8 bit): mask - * offset + 4 (8 bit): data - * - * Assign ((IOVAL("crtc port") & "mask") | "data") to "crtc port" - */ - - struct drm_nouveau_private *dev_priv = bios->dev->dev_private; - uint16_t crtcport = ROM16(bios->data[offset + 1]); - uint8_t mask = bios->data[offset + 3]; - uint8_t data = bios->data[offset + 4]; - - if (!iexec->execute) - return 5; - - BIOSLOG(bios, "0x%04X: Port: 0x%04X, Mask: 0x%02X, Data: 0x%02X\n", - offset, crtcport, mask, data); - - /* - * I have no idea what this does, but NVIDIA do this magic sequence - * in the places where this INIT_IO happens.. - */ - if (dev_priv->card_type >= NV_50 && crtcport == 0x3c3 && data == 1) { - int i; - - bios_wr32(bios, 0x614100, (bios_rd32( - bios, 0x614100) & 0x0fffffff) | 0x00800000); - - bios_wr32(bios, 0x00e18c, bios_rd32( - bios, 0x00e18c) | 0x00020000); - - bios_wr32(bios, 0x614900, (bios_rd32( - bios, 0x614900) & 0x0fffffff) | 0x00800000); - - bios_wr32(bios, 0x000200, bios_rd32( - bios, 0x000200) & ~0x40000000); - - mdelay(10); - - bios_wr32(bios, 0x00e18c, bios_rd32( - bios, 0x00e18c) & ~0x00020000); - - bios_wr32(bios, 0x000200, bios_rd32( - bios, 0x000200) | 0x40000000); - - bios_wr32(bios, 0x614100, 0x00800018); - bios_wr32(bios, 0x614900, 0x00800018); - - mdelay(10); - - bios_wr32(bios, 0x614100, 0x10000018); - bios_wr32(bios, 0x614900, 0x10000018); - - for (i = 0; i < 3; i++) - bios_wr32(bios, 0x614280 + (i*0x800), bios_rd32( - bios, 0x614280 + (i*0x800)) & 0xf0f0f0f0); - - for (i = 0; i < 2; i++) - bios_wr32(bios, 0x614300 + (i*0x800), bios_rd32( - bios, 0x614300 + (i*0x800)) & 0xfffff0f0); - - for (i = 0; i < 3; i++) - bios_wr32(bios, 0x614380 + (i*0x800), bios_rd32( - bios, 0x614380 + (i*0x800)) & 0xfffff0f0); - - for (i = 0; i < 2; i++) - bios_wr32(bios, 0x614200 + (i*0x800), bios_rd32( - bios, 0x614200 + (i*0x800)) & 0xfffffff0); - - for (i = 0; i < 2; i++) - bios_wr32(bios, 0x614108 + (i*0x800), bios_rd32( - bios, 0x614108 + (i*0x800)) & 0x0fffffff); - return 5; - } - - bios_port_wr(bios, crtcport, (bios_port_rd(bios, crtcport) & mask) | - data); - return 5; -} - -static int -init_sub(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) -{ - /* - * INIT_SUB opcode: 0x6B ('k') - * - * offset (8 bit): opcode - * offset + 1 (8 bit): script number - * - * Execute script number "script number", as a subroutine - */ - - uint8_t sub = bios->data[offset + 1]; - - if (!iexec->execute) - return 2; - - BIOSLOG(bios, "0x%04X: Calling script %d\n", offset, sub); - - parse_init_table(bios, - ROM16(bios->data[bios->init_script_tbls_ptr + sub * 2]), - iexec); - - BIOSLOG(bios, "0x%04X: End of script %d\n", offset, sub); - - return 2; -} - -static int -init_ram_condition(struct nvbios *bios, uint16_t offset, - struct init_exec *iexec) -{ - /* - * INIT_RAM_CONDITION opcode: 0x6D ('m') - * - * offset (8 bit): opcode - * offset + 1 (8 bit): mask - * offset + 2 (8 bit): cmpval - * - * Test if (NV04_PFB_BOOT_0 & "mask") equals "cmpval". - * If condition not met skip subsequent opcodes until condition is - * inverted (INIT_NOT), or we hit INIT_RESUME - */ - - uint8_t mask = bios->data[offset + 1]; - uint8_t cmpval = bios->data[offset + 2]; - uint8_t data; - - if (!iexec->execute) - return 3; - - data = bios_rd32(bios, NV04_PFB_BOOT_0) & mask; - - BIOSLOG(bios, "0x%04X: Checking if 0x%08X equals 0x%08X\n", - offset, data, cmpval); - - if (data == cmpval) - BIOSLOG(bios, "0x%04X: Condition fulfilled -- continuing to execute\n", offset); - else { - BIOSLOG(bios, "0x%04X: Condition not fulfilled -- skipping following commands\n", offset); - iexec->execute = false; - } - - return 3; -} - -static int -init_nv_reg(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) -{ - /* - * INIT_NV_REG opcode: 0x6E ('n') - * - * offset (8 bit): opcode - * offset + 1 (32 bit): register - * offset + 5 (32 bit): mask - * offset + 9 (32 bit): data - * - * Assign ((REGVAL("register") & "mask") | "data") to "register" - */ - - uint32_t reg = ROM32(bios->data[offset + 1]); - uint32_t mask = ROM32(bios->data[offset + 5]); - uint32_t data = ROM32(bios->data[offset + 9]); - - if (!iexec->execute) - return 13; - - BIOSLOG(bios, "0x%04X: Reg: 0x%08X, Mask: 0x%08X, Data: 0x%08X\n", - offset, reg, mask, data); - - bios_wr32(bios, reg, (bios_rd32(bios, reg) & mask) | data); - - return 13; -} - -static int -init_macro(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) -{ - /* - * INIT_MACRO opcode: 0x6F ('o') - * - * offset (8 bit): opcode - * offset + 1 (8 bit): macro number - * - * Look up macro index "macro number" in the macro index table. - * The macro index table entry has 1 byte for the index in the macro - * table, and 1 byte for the number of times to repeat the macro. - * The macro table entry has 4 bytes for the register address and - * 4 bytes for the value to write to that register - */ - - uint8_t macro_index_tbl_idx = bios->data[offset + 1]; - uint16_t tmp = bios->macro_index_tbl_ptr + (macro_index_tbl_idx * MACRO_INDEX_SIZE); - uint8_t macro_tbl_idx = bios->data[tmp]; - uint8_t count = bios->data[tmp + 1]; - uint32_t reg, data; - int i; - - if (!iexec->execute) - return 2; - - BIOSLOG(bios, "0x%04X: Macro: 0x%02X, MacroTableIndex: 0x%02X, " - "Count: 0x%02X\n", - offset, macro_index_tbl_idx, macro_tbl_idx, count); - - for (i = 0; i < count; i++) { - uint16_t macroentryptr = bios->macro_tbl_ptr + (macro_tbl_idx + i) * MACRO_SIZE; - - reg = ROM32(bios->data[macroentryptr]); - data = ROM32(bios->data[macroentryptr + 4]); - - bios_wr32(bios, reg, data); - } - - return 2; -} - -static int -init_done(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) -{ - /* - * INIT_DONE opcode: 0x71 ('q') - * - * offset (8 bit): opcode - * - * End the current script - */ - - /* mild retval abuse to stop parsing this table */ - return 0; -} - -static int -init_resume(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) -{ - /* - * INIT_RESUME opcode: 0x72 ('r') - * - * offset (8 bit): opcode - * - * End the current execute / no-execute condition - */ - - if (iexec->execute) - return 1; - - iexec->execute = true; - BIOSLOG(bios, "0x%04X: ---- Executing following commands ----\n", offset); - - return 1; -} - -static int -init_time(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) -{ - /* - * INIT_TIME opcode: 0x74 ('t') - * - * offset (8 bit): opcode - * offset + 1 (16 bit): time - * - * Sleep for "time" microseconds. - */ - - unsigned time = ROM16(bios->data[offset + 1]); - - if (!iexec->execute) - return 3; - - BIOSLOG(bios, "0x%04X: Sleeping for 0x%04X microseconds\n", - offset, time); - - if (time < 1000) - udelay(time); - else - mdelay((time + 900) / 1000); - - return 3; -} - -static int -init_condition(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) -{ - /* - * INIT_CONDITION opcode: 0x75 ('u') - * - * offset (8 bit): opcode - * offset + 1 (8 bit): condition number - * - * Check condition "condition number" in the condition table. - * If condition not met skip subsequent opcodes until condition is - * inverted (INIT_NOT), or we hit INIT_RESUME - */ - - uint8_t cond = bios->data[offset + 1]; - - if (!iexec->execute) - return 2; - - BIOSLOG(bios, "0x%04X: Condition: 0x%02X\n", offset, cond); - - if (bios_condition_met(bios, offset, cond)) - BIOSLOG(bios, "0x%04X: Condition fulfilled -- continuing to execute\n", offset); - else { - BIOSLOG(bios, "0x%04X: Condition not fulfilled -- skipping following commands\n", offset); - iexec->execute = false; - } - - return 2; -} - -static int -init_io_condition(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) -{ - /* - * INIT_IO_CONDITION opcode: 0x76 - * - * offset (8 bit): opcode - * offset + 1 (8 bit): condition number - * - * Check condition "condition number" in the io condition table. - * If condition not met skip subsequent opcodes until condition is - * inverted (INIT_NOT), or we hit INIT_RESUME - */ - - uint8_t cond = bios->data[offset + 1]; - - if (!iexec->execute) - return 2; - - BIOSLOG(bios, "0x%04X: IO condition: 0x%02X\n", offset, cond); - - if (io_condition_met(bios, offset, cond)) - BIOSLOG(bios, "0x%04X: Condition fulfilled -- continuing to execute\n", offset); - else { - BIOSLOG(bios, "0x%04X: Condition not fulfilled -- skipping following commands\n", offset); - iexec->execute = false; - } - - return 2; -} - -static int -init_index_io(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) -{ - /* - * INIT_INDEX_IO opcode: 0x78 ('x') - * - * offset (8 bit): opcode - * offset + 1 (16 bit): CRTC port - * offset + 3 (8 bit): CRTC index - * offset + 4 (8 bit): mask - * offset + 5 (8 bit): data - * - * Read value at index "CRTC index" on "CRTC port", AND with "mask", - * OR with "data", write-back - */ - - uint16_t crtcport = ROM16(bios->data[offset + 1]); - uint8_t crtcindex = bios->data[offset + 3]; - uint8_t mask = bios->data[offset + 4]; - uint8_t data = bios->data[offset + 5]; - uint8_t value; - - if (!iexec->execute) - return 6; - - BIOSLOG(bios, "0x%04X: Port: 0x%04X, Index: 0x%02X, Mask: 0x%02X, " - "Data: 0x%02X\n", - offset, crtcport, crtcindex, mask, data); - - value = (bios_idxprt_rd(bios, crtcport, crtcindex) & mask) | data; - bios_idxprt_wr(bios, crtcport, crtcindex, value); - - return 6; -} - -static int -init_pll(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) -{ - /* - * INIT_PLL opcode: 0x79 ('y') - * - * offset (8 bit): opcode - * offset + 1 (32 bit): register - * offset + 5 (16 bit): freq - * - * Set PLL register "register" to coefficients for frequency (10kHz) - * "freq" - */ - - uint32_t reg = ROM32(bios->data[offset + 1]); - uint16_t freq = ROM16(bios->data[offset + 5]); - - if (!iexec->execute) - return 7; - - BIOSLOG(bios, "0x%04X: Reg: 0x%08X, Freq: %d0kHz\n", offset, reg, freq); - - setPLL(bios->dev, reg, freq * 10); - - return 7; -} - -static int -init_zm_reg(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) -{ - /* - * INIT_ZM_REG opcode: 0x7A ('z') - * - * offset (8 bit): opcode - * offset + 1 (32 bit): register - * offset + 5 (32 bit): value - * - * Assign "value" to "register" - */ - - uint32_t reg = ROM32(bios->data[offset + 1]); - uint32_t value = ROM32(bios->data[offset + 5]); - - if (!iexec->execute) - return 9; - - if (reg == 0x000200) - value |= 1; - - bios_wr32(bios, reg, value); - - return 9; -} - -static int -init_ram_restrict_pll(struct nvbios *bios, uint16_t offset, - struct init_exec *iexec) -{ - /* - * INIT_RAM_RESTRICT_PLL opcode: 0x87 ('') - * - * offset (8 bit): opcode - * offset + 1 (8 bit): PLL type - * offset + 2 (32 bit): frequency 0 - * - * Uses the RAMCFG strap of PEXTDEV_BOOT as an index into the table at - * ram_restrict_table_ptr. The value read from there is used to select - * a frequency from the table starting at 'frequency 0' to be - * programmed into the PLL corresponding to 'type'. - * - * The PLL limits table on cards using this opcode has a mapping of - * 'type' to the relevant registers. - */ - - struct drm_device *dev = bios->dev; - uint32_t strap = (bios_rd32(bios, NV_PEXTDEV_BOOT_0) & 0x0000003c) >> 2; - uint8_t index = bios->data[bios->ram_restrict_tbl_ptr + strap]; - uint8_t type = bios->data[offset + 1]; - uint32_t freq = ROM32(bios->data[offset + 2 + (index * 4)]); - uint8_t *pll_limits = &bios->data[bios->pll_limit_tbl_ptr], *entry; - int len = 2 + bios->ram_restrict_group_count * 4; - int i; - - if (!iexec->execute) - return len; - - if (!bios->pll_limit_tbl_ptr || (pll_limits[0] & 0xf0) != 0x30) { - NV_ERROR(dev, "PLL limits table not version 3.x\n"); - return len; /* deliberate, allow default clocks to remain */ - } - - entry = pll_limits + pll_limits[1]; - for (i = 0; i < pll_limits[3]; i++, entry += pll_limits[2]) { - if (entry[0] == type) { - uint32_t reg = ROM32(entry[3]); - - BIOSLOG(bios, "0x%04X: " - "Type %02x Reg 0x%08x Freq %dKHz\n", - offset, type, reg, freq); - - setPLL(bios->dev, reg, freq); - return len; - } - } - - NV_ERROR(dev, "PLL type 0x%02x not found in PLL limits table", type); - return len; -} - -static int -init_8c(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) -{ - /* - * INIT_8C opcode: 0x8C ('') - * - * NOP so far.... - * - */ - - return 1; -} - -static int -init_8d(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) -{ - /* - * INIT_8D opcode: 0x8D ('') - * - * NOP so far.... - * - */ - - return 1; -} - -static int -init_gpio(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) -{ - /* - * INIT_GPIO opcode: 0x8E ('') - * - * offset (8 bit): opcode - * - * Loop over all entries in the DCB GPIO table, and initialise - * each GPIO according to various values listed in each entry - */ - - if (iexec->execute && bios->execute) - nouveau_gpio_reset(bios->dev); - - return 1; -} - -static int -init_ram_restrict_zm_reg_group(struct nvbios *bios, uint16_t offset, - struct init_exec *iexec) -{ - /* - * INIT_RAM_RESTRICT_ZM_REG_GROUP opcode: 0x8F ('') - * - * offset (8 bit): opcode - * offset + 1 (32 bit): reg - * offset + 5 (8 bit): regincrement - * offset + 6 (8 bit): count - * offset + 7 (32 bit): value 1,1 - * ... - * - * Use the RAMCFG strap of PEXTDEV_BOOT as an index into the table at - * ram_restrict_table_ptr. The value read from here is 'n', and - * "value 1,n" gets written to "reg". This repeats "count" times and on - * each iteration 'm', "reg" increases by "regincrement" and - * "value m,n" is used. The extent of n is limited by a number read - * from the 'M' BIT table, herein called "blocklen" - */ - - uint32_t reg = ROM32(bios->data[offset + 1]); - uint8_t regincrement = bios->data[offset + 5]; - uint8_t count = bios->data[offset + 6]; - uint32_t strap_ramcfg, data; - /* previously set by 'M' BIT table */ - uint16_t blocklen = bios->ram_restrict_group_count * 4; - int len = 7 + count * blocklen; - uint8_t index; - int i; - - /* critical! to know the length of the opcode */; - if (!blocklen) { - NV_ERROR(bios->dev, - "0x%04X: Zero block length - has the M table " - "been parsed?\n", offset); - return -EINVAL; - } - - if (!iexec->execute) - return len; - - strap_ramcfg = (bios_rd32(bios, NV_PEXTDEV_BOOT_0) >> 2) & 0xf; - index = bios->data[bios->ram_restrict_tbl_ptr + strap_ramcfg]; - - BIOSLOG(bios, "0x%04X: Reg: 0x%08X, RegIncrement: 0x%02X, " - "Count: 0x%02X, StrapRamCfg: 0x%02X, Index: 0x%02X\n", - offset, reg, regincrement, count, strap_ramcfg, index); - - for (i = 0; i < count; i++) { - data = ROM32(bios->data[offset + 7 + index * 4 + blocklen * i]); - - bios_wr32(bios, reg, data); - - reg += regincrement; - } - - return len; -} - -static int -init_copy_zm_reg(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) -{ - /* - * INIT_COPY_ZM_REG opcode: 0x90 ('') - * - * offset (8 bit): opcode - * offset + 1 (32 bit): src reg - * offset + 5 (32 bit): dst reg - * - * Put contents of "src reg" into "dst reg" - */ - - uint32_t srcreg = ROM32(bios->data[offset + 1]); - uint32_t dstreg = ROM32(bios->data[offset + 5]); - - if (!iexec->execute) - return 9; - - bios_wr32(bios, dstreg, bios_rd32(bios, srcreg)); - - return 9; -} - -static int -init_zm_reg_group_addr_latched(struct nvbios *bios, uint16_t offset, - struct init_exec *iexec) -{ - /* - * INIT_ZM_REG_GROUP_ADDRESS_LATCHED opcode: 0x91 ('') - * - * offset (8 bit): opcode - * offset + 1 (32 bit): dst reg - * offset + 5 (8 bit): count - * offset + 6 (32 bit): data 1 - * ... - * - * For each of "count" values write "data n" to "dst reg" - */ - - uint32_t reg = ROM32(bios->data[offset + 1]); - uint8_t count = bios->data[offset + 5]; - int len = 6 + count * 4; - int i; - - if (!iexec->execute) - return len; - - for (i = 0; i < count; i++) { - uint32_t data = ROM32(bios->data[offset + 6 + 4 * i]); - bios_wr32(bios, reg, data); - } - - return len; -} - -static int -init_reserved(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) -{ - /* - * INIT_RESERVED opcode: 0x92 ('') - * - * offset (8 bit): opcode - * - * Seemingly does nothing - */ - - return 1; -} - -static int -init_96(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) -{ - /* - * INIT_96 opcode: 0x96 ('') - * - * offset (8 bit): opcode - * offset + 1 (32 bit): sreg - * offset + 5 (8 bit): sshift - * offset + 6 (8 bit): smask - * offset + 7 (8 bit): index - * offset + 8 (32 bit): reg - * offset + 12 (32 bit): mask - * offset + 16 (8 bit): shift - * - */ - - uint16_t xlatptr = bios->init96_tbl_ptr + (bios->data[offset + 7] * 2); - uint32_t reg = ROM32(bios->data[offset + 8]); - uint32_t mask = ROM32(bios->data[offset + 12]); - uint32_t val; - - val = bios_rd32(bios, ROM32(bios->data[offset + 1])); - if (bios->data[offset + 5] < 0x80) - val >>= bios->data[offset + 5]; - else - val <<= (0x100 - bios->data[offset + 5]); - val &= bios->data[offset + 6]; - - val = bios->data[ROM16(bios->data[xlatptr]) + val]; - val <<= bios->data[offset + 16]; - - if (!iexec->execute) - return 17; - - bios_wr32(bios, reg, (bios_rd32(bios, reg) & mask) | val); - return 17; -} - -static int -init_97(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) -{ - /* - * INIT_97 opcode: 0x97 ('') - * - * offset (8 bit): opcode - * offset + 1 (32 bit): register - * offset + 5 (32 bit): mask - * offset + 9 (32 bit): value - * - * Adds "value" to "register" preserving the fields specified - * by "mask" - */ - - uint32_t reg = ROM32(bios->data[offset + 1]); - uint32_t mask = ROM32(bios->data[offset + 5]); - uint32_t add = ROM32(bios->data[offset + 9]); - uint32_t val; - - val = bios_rd32(bios, reg); - val = (val & mask) | ((val + add) & ~mask); - - if (!iexec->execute) - return 13; - - bios_wr32(bios, reg, val); - return 13; -} - -static int -init_auxch(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) -{ - /* - * INIT_AUXCH opcode: 0x98 ('') - * - * offset (8 bit): opcode - * offset + 1 (32 bit): address - * offset + 5 (8 bit): count - * offset + 6 (8 bit): mask 0 - * offset + 7 (8 bit): data 0 - * ... - * - */ - - struct drm_device *dev = bios->dev; - struct nouveau_i2c_port *auxch; - uint32_t addr = ROM32(bios->data[offset + 1]); - uint8_t count = bios->data[offset + 5]; - int len = 6 + count * 2; - int ret, i; - - if (!bios->display.output) { - NV_ERROR(dev, "INIT_AUXCH: no active output\n"); - return len; - } - - auxch = init_i2c_device_find(dev, bios->display.output->i2c_index); - if (!auxch) { - NV_ERROR(dev, "INIT_AUXCH: couldn't get auxch %d\n", - bios->display.output->i2c_index); - return len; - } - - if (!iexec->execute) - return len; - - offset += 6; - for (i = 0; i < count; i++, offset += 2) { - uint8_t data; - - ret = auxch_rd(dev, auxch, addr, &data, 1); - if (ret) { - NV_ERROR(dev, "INIT_AUXCH: rd auxch fail %d\n", ret); - return len; - } - - data &= bios->data[offset + 0]; - data |= bios->data[offset + 1]; - - ret = auxch_wr(dev, auxch, addr, &data, 1); - if (ret) { - NV_ERROR(dev, "INIT_AUXCH: wr auxch fail %d\n", ret); - return len; - } - } - - return len; -} - -static int -init_zm_auxch(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) -{ - /* - * INIT_ZM_AUXCH opcode: 0x99 ('') - * - * offset (8 bit): opcode - * offset + 1 (32 bit): address - * offset + 5 (8 bit): count - * offset + 6 (8 bit): data 0 - * ... - * - */ - - struct drm_device *dev = bios->dev; - struct nouveau_i2c_port *auxch; - uint32_t addr = ROM32(bios->data[offset + 1]); - uint8_t count = bios->data[offset + 5]; - int len = 6 + count; - int ret, i; - - if (!bios->display.output) { - NV_ERROR(dev, "INIT_ZM_AUXCH: no active output\n"); - return len; - } - - auxch = init_i2c_device_find(dev, bios->display.output->i2c_index); - if (!auxch) { - NV_ERROR(dev, "INIT_ZM_AUXCH: couldn't get auxch %d\n", - bios->display.output->i2c_index); - return len; - } - - if (!iexec->execute) - return len; - - offset += 6; - for (i = 0; i < count; i++, offset++) { - ret = auxch_wr(dev, auxch, addr, &bios->data[offset], 1); - if (ret) { - NV_ERROR(dev, "INIT_ZM_AUXCH: wr auxch fail %d\n", ret); - return len; - } - } - - return len; -} - -static int -init_i2c_long_if(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) -{ - /* - * INIT_I2C_LONG_IF opcode: 0x9A ('') - * - * offset (8 bit): opcode - * offset + 1 (8 bit): DCB I2C table entry index - * offset + 2 (8 bit): I2C slave address - * offset + 3 (16 bit): I2C register - * offset + 5 (8 bit): mask - * offset + 6 (8 bit): data - * - * Read the register given by "I2C register" on the device addressed - * by "I2C slave address" on the I2C bus given by "DCB I2C table - * entry index". Compare the result AND "mask" to "data". - * If they're not equal, skip subsequent opcodes until condition is - * inverted (INIT_NOT), or we hit INIT_RESUME - */ - - uint8_t i2c_index = bios->data[offset + 1]; - uint8_t i2c_address = bios->data[offset + 2] >> 1; - uint8_t reglo = bios->data[offset + 3]; - uint8_t reghi = bios->data[offset + 4]; - uint8_t mask = bios->data[offset + 5]; - uint8_t data = bios->data[offset + 6]; - struct nouveau_i2c_port *chan; - uint8_t buf0[2] = { reghi, reglo }; - uint8_t buf1[1]; - struct i2c_msg msg[2] = { - { i2c_address, 0, 1, buf0 }, - { i2c_address, I2C_M_RD, 1, buf1 }, - }; - int ret; - - /* no execute check by design */ - - BIOSLOG(bios, "0x%04X: DCBI2CIndex: 0x%02X, I2CAddress: 0x%02X\n", - offset, i2c_index, i2c_address); - - chan = init_i2c_device_find(bios->dev, i2c_index); - if (!chan) - return -ENODEV; - - - ret = i2c_transfer(nouveau_i2c_adapter(chan), msg, 2); - if (ret < 0) { - BIOSLOG(bios, "0x%04X: I2CReg: 0x%02X:0x%02X, Value: [no device], " - "Mask: 0x%02X, Data: 0x%02X\n", - offset, reghi, reglo, mask, data); - iexec->execute = 0; - return 7; - } - - BIOSLOG(bios, "0x%04X: I2CReg: 0x%02X:0x%02X, Value: 0x%02X, " - "Mask: 0x%02X, Data: 0x%02X\n", - offset, reghi, reglo, buf1[0], mask, data); - - iexec->execute = ((buf1[0] & mask) == data); - - return 7; -} - -static struct init_tbl_entry itbl_entry[] = { - /* command name , id , length , offset , mult , command handler */ - /* INIT_PROG (0x31, 15, 10, 4) removed due to no example of use */ - { "INIT_IO_RESTRICT_PROG" , 0x32, init_io_restrict_prog }, - { "INIT_REPEAT" , 0x33, init_repeat }, - { "INIT_IO_RESTRICT_PLL" , 0x34, init_io_restrict_pll }, - { "INIT_END_REPEAT" , 0x36, init_end_repeat }, - { "INIT_COPY" , 0x37, init_copy }, - { "INIT_NOT" , 0x38, init_not }, - { "INIT_IO_FLAG_CONDITION" , 0x39, init_io_flag_condition }, - { "INIT_DP_CONDITION" , 0x3A, init_dp_condition }, - { "INIT_OP_3B" , 0x3B, init_op_3b }, - { "INIT_OP_3C" , 0x3C, init_op_3c }, - { "INIT_INDEX_ADDRESS_LATCHED" , 0x49, init_idx_addr_latched }, - { "INIT_IO_RESTRICT_PLL2" , 0x4A, init_io_restrict_pll2 }, - { "INIT_PLL2" , 0x4B, init_pll2 }, - { "INIT_I2C_BYTE" , 0x4C, init_i2c_byte }, - { "INIT_ZM_I2C_BYTE" , 0x4D, init_zm_i2c_byte }, - { "INIT_ZM_I2C" , 0x4E, init_zm_i2c }, - { "INIT_TMDS" , 0x4F, init_tmds }, - { "INIT_ZM_TMDS_GROUP" , 0x50, init_zm_tmds_group }, - { "INIT_CR_INDEX_ADDRESS_LATCHED" , 0x51, init_cr_idx_adr_latch }, - { "INIT_CR" , 0x52, init_cr }, - { "INIT_ZM_CR" , 0x53, init_zm_cr }, - { "INIT_ZM_CR_GROUP" , 0x54, init_zm_cr_group }, - { "INIT_CONDITION_TIME" , 0x56, init_condition_time }, - { "INIT_LTIME" , 0x57, init_ltime }, - { "INIT_ZM_REG_SEQUENCE" , 0x58, init_zm_reg_sequence }, - /* INIT_INDIRECT_REG (0x5A, 7, 0, 0) removed due to no example of use */ - { "INIT_SUB_DIRECT" , 0x5B, init_sub_direct }, - { "INIT_JUMP" , 0x5C, init_jump }, - { "INIT_I2C_IF" , 0x5E, init_i2c_if }, - { "INIT_COPY_NV_REG" , 0x5F, init_copy_nv_reg }, - { "INIT_ZM_INDEX_IO" , 0x62, init_zm_index_io }, - { "INIT_COMPUTE_MEM" , 0x63, init_compute_mem }, - { "INIT_RESET" , 0x65, init_reset }, - { "INIT_CONFIGURE_MEM" , 0x66, init_configure_mem }, - { "INIT_CONFIGURE_CLK" , 0x67, init_configure_clk }, - { "INIT_CONFIGURE_PREINIT" , 0x68, init_configure_preinit }, - { "INIT_IO" , 0x69, init_io }, - { "INIT_SUB" , 0x6B, init_sub }, - { "INIT_RAM_CONDITION" , 0x6D, init_ram_condition }, - { "INIT_NV_REG" , 0x6E, init_nv_reg }, - { "INIT_MACRO" , 0x6F, init_macro }, - { "INIT_DONE" , 0x71, init_done }, - { "INIT_RESUME" , 0x72, init_resume }, - /* INIT_RAM_CONDITION2 (0x73, 9, 0, 0) removed due to no example of use */ - { "INIT_TIME" , 0x74, init_time }, - { "INIT_CONDITION" , 0x75, init_condition }, - { "INIT_IO_CONDITION" , 0x76, init_io_condition }, - { "INIT_INDEX_IO" , 0x78, init_index_io }, - { "INIT_PLL" , 0x79, init_pll }, - { "INIT_ZM_REG" , 0x7A, init_zm_reg }, - { "INIT_RAM_RESTRICT_PLL" , 0x87, init_ram_restrict_pll }, - { "INIT_8C" , 0x8C, init_8c }, - { "INIT_8D" , 0x8D, init_8d }, - { "INIT_GPIO" , 0x8E, init_gpio }, - { "INIT_RAM_RESTRICT_ZM_REG_GROUP" , 0x8F, init_ram_restrict_zm_reg_group }, - { "INIT_COPY_ZM_REG" , 0x90, init_copy_zm_reg }, - { "INIT_ZM_REG_GROUP_ADDRESS_LATCHED" , 0x91, init_zm_reg_group_addr_latched }, - { "INIT_RESERVED" , 0x92, init_reserved }, - { "INIT_96" , 0x96, init_96 }, - { "INIT_97" , 0x97, init_97 }, - { "INIT_AUXCH" , 0x98, init_auxch }, - { "INIT_ZM_AUXCH" , 0x99, init_zm_auxch }, - { "INIT_I2C_LONG_IF" , 0x9A, init_i2c_long_if }, - { NULL , 0 , NULL } -}; - -#define MAX_TABLE_OPS 1000 - -static int -parse_init_table(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) -{ - /* - * Parses all commands in an init table. - * - * We start out executing all commands found in the init table. Some - * opcodes may change the status of iexec->execute to SKIP, which will - * cause the following opcodes to perform no operation until the value - * is changed back to EXECUTE. - */ - - int count = 0, i, ret; - uint8_t id; - - /* catch NULL script pointers */ - if (offset == 0) - return 0; - - /* - * Loop until INIT_DONE causes us to break out of the loop - * (or until offset > bios length just in case... ) - * (and no more than MAX_TABLE_OPS iterations, just in case... ) - */ - while ((offset < bios->length) && (count++ < MAX_TABLE_OPS)) { - id = bios->data[offset]; - - /* Find matching id in itbl_entry */ - for (i = 0; itbl_entry[i].name && (itbl_entry[i].id != id); i++) - ; - - if (!itbl_entry[i].name) { - NV_ERROR(bios->dev, - "0x%04X: Init table command not found: " - "0x%02X\n", offset, id); - return -ENOENT; - } - - BIOSLOG(bios, "0x%04X: [ (0x%02X) - %s ]\n", offset, - itbl_entry[i].id, itbl_entry[i].name); - - /* execute eventual command handler */ - ret = (*itbl_entry[i].handler)(bios, offset, iexec); - if (ret < 0) { - NV_ERROR(bios->dev, "0x%04X: Failed parsing init " - "table opcode: %s %d\n", offset, - itbl_entry[i].name, ret); - } - - if (ret <= 0) - break; - - /* - * Add the offset of the current command including all data - * of that command. The offset will then be pointing on the - * next op code. - */ - offset += ret; - } - - if (offset >= bios->length) - NV_WARN(bios->dev, - "Offset 0x%04X greater than known bios image length. " - "Corrupt image?\n", offset); - if (count >= MAX_TABLE_OPS) - NV_WARN(bios->dev, - "More than %d opcodes to a table is unlikely, " - "is the bios image corrupt?\n", MAX_TABLE_OPS); - - return 0; -} - -static void -parse_init_tables(struct nvbios *bios) -{ - /* Loops and calls parse_init_table() for each present table. */ - - int i = 0; - uint16_t table; - struct init_exec iexec = {true, false}; - - if (bios->old_style_init) { - if (bios->init_script_tbls_ptr) - parse_init_table(bios, bios->init_script_tbls_ptr, &iexec); - if (bios->extra_init_script_tbl_ptr) - parse_init_table(bios, bios->extra_init_script_tbl_ptr, &iexec); - - return; - } - - while ((table = ROM16(bios->data[bios->init_script_tbls_ptr + i]))) { - NV_INFO(bios->dev, - "Parsing VBIOS init table %d at offset 0x%04X\n", - i / 2, table); - BIOSLOG(bios, "0x%04X: ------ Executing following commands ------\n", table); - - parse_init_table(bios, table, &iexec); - i += 2; - } -} - static uint16_t clkcmptable(struct nvbios *bios, uint16_t clktable, int pxclk) { int compare_record_len, i = 0; @@ -3458,28 +92,22 @@ static uint16_t clkcmptable(struct nvbios *bios, uint16_t clktable, int pxclk) static void run_digital_op_script(struct drm_device *dev, uint16_t scriptptr, - struct dcb_entry *dcbent, int head, bool dl) + struct dcb_output *dcbent, int head, bool dl) { - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nvbios *bios = &dev_priv->vbios; - struct init_exec iexec = {true, false}; - NV_TRACE(dev, "0x%04X: Parsing digital output script table\n", scriptptr); - bios_idxprt_wr(bios, NV_CIO_CRX__COLOR, NV_CIO_CRE_44, - head ? NV_CIO_CRE_44_HEADB : NV_CIO_CRE_44_HEADA); - /* note: if dcb entries have been merged, index may be misleading */ - NVWriteVgaCrtc5758(dev, head, 0, dcbent->index); - parse_init_table(bios, scriptptr, &iexec); + NVWriteVgaCrtc(dev, 0, NV_CIO_CRE_44, head ? NV_CIO_CRE_44_HEADB : + NV_CIO_CRE_44_HEADA); + nouveau_bios_run_init_table(dev, scriptptr, dcbent, head); nv04_dfp_bind_head(dev, dcbent, head, dl); } -static int call_lvds_manufacturer_script(struct drm_device *dev, struct dcb_entry *dcbent, int head, enum LVDS_script script) +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; - uint8_t sub = bios->data[bios->fp.xlated_entry + script] + (bios->fp.link_c_increment && dcbent->or & OUTPUT_C ? 1 : 0); + 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]); if (!bios->fp.xlated_entry || !sub || !scriptofs) @@ -3502,7 +130,7 @@ static int call_lvds_manufacturer_script(struct drm_device *dev, struct dcb_entr return 0; } -static int run_lvds_table(struct drm_device *dev, struct dcb_entry *dcbent, int head, enum LVDS_script script, int pxclk) +static int run_lvds_table(struct drm_device *dev, struct dcb_output *dcbent, int head, enum LVDS_script script, int pxclk) { /* * The BIT LVDS table's header has the information to setup the @@ -3575,7 +203,7 @@ static int run_lvds_table(struct drm_device *dev, struct dcb_entry *dcbent, int return 0; } -int call_lvds_script(struct drm_device *dev, struct dcb_entry *dcbent, int head, enum LVDS_script script, int pxclk) +int call_lvds_script(struct drm_device *dev, struct dcb_output *dcbent, int head, enum LVDS_script script, int pxclk) { /* * LVDS operations are multiplexed in an effort to present a single API @@ -3606,7 +234,7 @@ int call_lvds_script(struct drm_device *dev, struct dcb_entry *dcbent, int head, NV_TRACE(dev, "Calling LVDS script %d:\n", script); /* don't let script change pll->head binding */ - sel_clk_binding = bios_rd32(bios, NV_PRAMDAC_SEL_CLK) & 0x50000; + sel_clk_binding = nv_rd32(dev, NV_PRAMDAC_SEL_CLK) & 0x50000; if (lvds_ver < 0x30) ret = call_lvds_manufacturer_script(dev, dcbent, head, script); @@ -3700,9 +328,9 @@ get_fp_strap(struct drm_device *dev, struct nvbios *bios) return NVReadVgaCrtc5758(dev, 0, 0xf) & 0xf; if (dev_priv->card_type >= NV_50) - return (bios_rd32(bios, NV_PEXTDEV_BOOT_0) >> 24) & 0xf; + return (nv_rd32(dev, NV_PEXTDEV_BOOT_0) >> 24) & 0xf; else - return (bios_rd32(bios, NV_PEXTDEV_BOOT_0) >> 16) & 0xf; + return (nv_rd32(dev, NV_PEXTDEV_BOOT_0) >> 16) & 0xf; } static int parse_fp_mode_table(struct drm_device *dev, struct nvbios *bios) @@ -3994,7 +622,7 @@ int nouveau_bios_parse_lvds_table(struct drm_device *dev, int pxclk, bool *dl, b * This function returns true if a particular DCB entry matches. */ bool -bios_encoder_match(struct dcb_entry *dcb, u32 hash) +bios_encoder_match(struct dcb_output *dcb, u32 hash) { if ((hash & 0x000000f0) != (dcb->location << 4)) return false; @@ -4004,9 +632,9 @@ bios_encoder_match(struct dcb_entry *dcb, u32 hash) return false; switch (dcb->type) { - case OUTPUT_TMDS: - case OUTPUT_LVDS: - case OUTPUT_DP: + case DCB_OUTPUT_TMDS: + case DCB_OUTPUT_LVDS: + case DCB_OUTPUT_DP: if (hash & 0x00c00000) { if (!(hash & (dcb->sorconf.link << 22))) return false; @@ -4018,7 +646,7 @@ bios_encoder_match(struct dcb_entry *dcb, u32 hash) int nouveau_bios_run_display_table(struct drm_device *dev, u16 type, int pclk, - struct dcb_entry *dcbent, int crtc) + struct dcb_output *dcbent, int crtc) { /* * The display script table is located by the BIT 'U' table. @@ -4188,7 +816,7 @@ nouveau_bios_run_display_table(struct drm_device *dev, u16 type, int pclk, } -int run_tmds_table(struct drm_device *dev, struct dcb_entry *dcbent, int head, int pxclk) +int run_tmds_table(struct drm_device *dev, struct dcb_output *dcbent, int head, int pxclk) { /* * the pxclk parameter is in kHz @@ -4233,7 +861,7 @@ int run_tmds_table(struct drm_device *dev, struct dcb_entry *dcbent, int head, i } /* don't let script change pll->head binding */ - sel_clk_binding = bios_rd32(bios, NV_PRAMDAC_SEL_CLK) & 0x50000; + sel_clk_binding = nv_rd32(dev, 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); @@ -4967,9 +1595,9 @@ olddcb_outp_foreach(struct drm_device *dev, void *data, if (ROM32(outp[0]) == 0xffffffff) break; /* seen on an NV17 with DCB v2.0 */ - if ((outp[0] & 0x0f) == OUTPUT_UNUSED) + if ((outp[0] & 0x0f) == DCB_OUTPUT_UNUSED) continue; - if ((outp[0] & 0x0f) == OUTPUT_EOL) + if ((outp[0] & 0x0f) == DCB_OUTPUT_EOL) break; ret = exec(dev, data, idx, outp); @@ -4981,7 +1609,7 @@ olddcb_outp_foreach(struct drm_device *dev, void *data, } u8 * -dcb_conntab(struct drm_device *dev) +olddcb_conntab(struct drm_device *dev) { u8 *dcb = olddcb_table(dev); if (dcb && dcb[0] >= 0x30 && dcb[1] >= 0x16) { @@ -4993,19 +1621,19 @@ dcb_conntab(struct drm_device *dev) } u8 * -dcb_conn(struct drm_device *dev, u8 idx) +olddcb_conn(struct drm_device *dev, u8 idx) { - u8 *conntab = dcb_conntab(dev); + u8 *conntab = olddcb_conntab(dev); if (conntab && idx < conntab[2]) return conntab + conntab[1] + (idx * conntab[3]); return NULL; } -static struct dcb_entry *new_dcb_entry(struct dcb_table *dcb) +static struct dcb_output *new_dcb_entry(struct dcb_table *dcb) { - struct dcb_entry *entry = &dcb->entry[dcb->entries]; + struct dcb_output *entry = &dcb->entry[dcb->entries]; - memset(entry, 0, sizeof(struct dcb_entry)); + memset(entry, 0, sizeof(struct dcb_output)); entry->index = dcb->entries++; return entry; @@ -5014,19 +1642,19 @@ static struct dcb_entry *new_dcb_entry(struct dcb_table *dcb) static void fabricate_dcb_output(struct dcb_table *dcb, int type, int i2c, int heads, int or) { - struct dcb_entry *entry = new_dcb_entry(dcb); + struct dcb_output *entry = new_dcb_entry(dcb); entry->type = type; entry->i2c_index = i2c; entry->heads = heads; - if (type != OUTPUT_ANALOG) + if (type != DCB_OUTPUT_ANALOG) entry->location = !DCB_LOC_ON_CHIP; /* ie OFF CHIP */ entry->or = or; } static bool parse_dcb20_entry(struct drm_device *dev, struct dcb_table *dcb, - uint32_t conn, uint32_t conf, struct dcb_entry *entry) + uint32_t conn, uint32_t conf, struct dcb_output *entry) { entry->type = conn & 0xf; entry->i2c_index = (conn >> 4) & 0xf; @@ -5037,7 +1665,7 @@ parse_dcb20_entry(struct drm_device *dev, struct dcb_table *dcb, entry->or = (conn >> 24) & 0xf; switch (entry->type) { - case OUTPUT_ANALOG: + case DCB_OUTPUT_ANALOG: /* * Although the rest of a CRT conf dword is usually * zeros, mac biosen have stuff there so we must mask @@ -5046,7 +1674,7 @@ parse_dcb20_entry(struct drm_device *dev, struct dcb_table *dcb, (conf & 0xffff) * 10 : (conf & 0xff) * 10000; break; - case OUTPUT_LVDS: + case DCB_OUTPUT_LVDS: { uint32_t mask; if (conf & 0x1) @@ -5086,7 +1714,7 @@ parse_dcb20_entry(struct drm_device *dev, struct dcb_table *dcb, } break; } - case OUTPUT_TV: + case DCB_OUTPUT_TV: { if (dcb->version >= 0x30) entry->tvconf.has_component_output = conf & (0x8 << 4); @@ -5095,7 +1723,7 @@ parse_dcb20_entry(struct drm_device *dev, struct dcb_table *dcb, break; } - case OUTPUT_DP: + case DCB_OUTPUT_DP: entry->dpconf.sor.link = (conf & 0x00000030) >> 4; switch ((conf & 0x00e00000) >> 21) { case 0: @@ -5117,7 +1745,7 @@ parse_dcb20_entry(struct drm_device *dev, struct dcb_table *dcb, break; } break; - case OUTPUT_TMDS: + case DCB_OUTPUT_TMDS: if (dcb->version >= 0x40) entry->tmdsconf.sor.link = (conf & 0x00000030) >> 4; else if (dcb->version >= 0x30) @@ -5126,7 +1754,7 @@ parse_dcb20_entry(struct drm_device *dev, struct dcb_table *dcb, entry->tmdsconf.slave_addr = (conf & 0x00000070) >> 4; break; - case OUTPUT_EOL: + case DCB_OUTPUT_EOL: /* weird g80 mobile type that "nv" treats as a terminator */ dcb->entries--; return false; @@ -5153,24 +1781,24 @@ parse_dcb20_entry(struct drm_device *dev, struct dcb_table *dcb, static bool parse_dcb15_entry(struct drm_device *dev, struct dcb_table *dcb, - uint32_t conn, uint32_t conf, struct dcb_entry *entry) + uint32_t conn, uint32_t conf, struct dcb_output *entry) { switch (conn & 0x0000000f) { case 0: - entry->type = OUTPUT_ANALOG; + entry->type = DCB_OUTPUT_ANALOG; break; case 1: - entry->type = OUTPUT_TV; + entry->type = DCB_OUTPUT_TV; break; case 2: case 4: if (conn & 0x10) - entry->type = OUTPUT_LVDS; + entry->type = DCB_OUTPUT_LVDS; else - entry->type = OUTPUT_TMDS; + entry->type = DCB_OUTPUT_TMDS; break; case 3: - entry->type = OUTPUT_LVDS; + entry->type = DCB_OUTPUT_LVDS; break; default: NV_ERROR(dev, "Unknown DCB type %d\n", conn & 0x0000000f); @@ -5185,13 +1813,13 @@ parse_dcb15_entry(struct drm_device *dev, struct dcb_table *dcb, entry->duallink_possible = false; switch (entry->type) { - case OUTPUT_ANALOG: + case DCB_OUTPUT_ANALOG: entry->crtconf.maxfreq = (conf & 0xffff) * 10; break; - case OUTPUT_TV: + case DCB_OUTPUT_TV: entry->tvconf.has_component_output = false; break; - case OUTPUT_LVDS: + case DCB_OUTPUT_LVDS: if ((conn & 0x00003f00) >> 8 != 0x10) entry->lvdsconf.use_straps_for_mode = true; entry->lvdsconf.use_power_scripts = true; @@ -5215,11 +1843,11 @@ void merge_like_dcb_entries(struct drm_device *dev, struct dcb_table *dcb) int i, newentries = 0; for (i = 0; i < dcb->entries; i++) { - struct dcb_entry *ient = &dcb->entry[i]; + struct dcb_output *ient = &dcb->entry[i]; int j; for (j = i + 1; j < dcb->entries; j++) { - struct dcb_entry *jent = &dcb->entry[j]; + struct dcb_output *jent = &dcb->entry[j]; if (jent->type == 100) /* already merged entry */ continue; @@ -5282,7 +1910,7 @@ apply_dcb_encoder_quirks(struct drm_device *dev, int idx, u32 *conn, u32 *conf) */ if (nv_match_device(dev, 0x0201, 0x1462, 0x8851)) { if (*conn == 0xf2005014 && *conf == 0xffffffff) { - fabricate_dcb_output(dcb, OUTPUT_TMDS, 1, 1, 1); + fabricate_dcb_output(dcb, DCB_OUTPUT_TMDS, 1, 1, 1); return false; } } @@ -5368,24 +1996,24 @@ fabricate_dcb_encoder_table(struct drm_device *dev, struct nvbios *bios) #ifdef __powerpc__ /* Apple iMac G4 NV17 */ if (of_machine_is_compatible("PowerMac4,5")) { - fabricate_dcb_output(dcb, OUTPUT_TMDS, 0, all_heads, 1); - fabricate_dcb_output(dcb, OUTPUT_ANALOG, 1, all_heads, 2); + fabricate_dcb_output(dcb, DCB_OUTPUT_TMDS, 0, all_heads, 1); + fabricate_dcb_output(dcb, DCB_OUTPUT_ANALOG, 1, all_heads, 2); return; } #endif /* Make up some sane defaults */ - fabricate_dcb_output(dcb, OUTPUT_ANALOG, + fabricate_dcb_output(dcb, DCB_OUTPUT_ANALOG, bios->legacy.i2c_indices.crt, 1, 1); if (nv04_tv_identify(dev, bios->legacy.i2c_indices.tv) >= 0) - fabricate_dcb_output(dcb, OUTPUT_TV, + fabricate_dcb_output(dcb, DCB_OUTPUT_TV, bios->legacy.i2c_indices.tv, all_heads, 0); else if (bios->tmds.output0_script_ptr || bios->tmds.output1_script_ptr) - fabricate_dcb_output(dcb, OUTPUT_TMDS, + fabricate_dcb_output(dcb, DCB_OUTPUT_TMDS, bios->legacy.i2c_indices.panel, all_heads, 1); } @@ -5400,7 +2028,7 @@ parse_dcb_entry(struct drm_device *dev, void *data, int idx, u8 *outp) bool ret; if (apply_dcb_encoder_quirks(dev, idx, &conn, &conf)) { - struct dcb_entry *entry = new_dcb_entry(dcb); + struct dcb_output *entry = new_dcb_entry(dcb); NV_TRACEWARN(dev, "DCB outp %02d: %08x %08x\n", idx, conn, conf); @@ -5415,7 +2043,7 @@ parse_dcb_entry(struct drm_device *dev, void *data, int idx, u8 *outp) * are cards with bogus values (nv31m in bug 23212), * and it's otherwise useless. */ - if (entry->type == OUTPUT_TV && + if (entry->type == DCB_OUTPUT_TV && entry->location == DCB_LOC_ON_CHIP) entry->i2c_index = 0x0f; } @@ -5463,7 +2091,7 @@ dcb_fake_connectors(struct nvbios *bios) * table - just in case it has random, rather than stub, entries. */ if (i > 1) { - u8 *conntab = dcb_conntab(bios->dev); + u8 *conntab = olddcb_conntab(bios->dev); if (conntab) conntab[0] = 0x00; } @@ -5504,10 +2132,10 @@ parse_dcb_table(struct drm_device *dev, struct nvbios *bios) /* dump connector table entries to log, if any exist */ idx = -1; - while ((conn = dcb_conn(dev, ++idx))) { + while ((conn = olddcb_conn(dev, ++idx))) { if (conn[0] != 0xff) { NV_TRACE(dev, "DCB conn %02d: ", idx); - if (dcb_conntab(dev)[3] < 4) + if (olddcb_conntab(dev)[3] < 4) printk("%04x\n", ROM16(conn[0])); else printk("%08x\n", ROM32(conn[0])); @@ -5550,15 +2178,15 @@ static int load_nv17_hwsq_ucode_entry(struct drm_device *dev, struct nvbios *bio hwsq_entry_offset = hwsq_offset + 2 + entry * bytes_to_write; /* set sequencer control */ - bios_wr32(bios, 0x00001304, ROM32(bios->data[hwsq_entry_offset])); + nv_wr32(dev, 0x00001304, ROM32(bios->data[hwsq_entry_offset])); bytes_to_write -= 4; /* write ucode */ for (i = 0; i < bytes_to_write; i += 4) - bios_wr32(bios, 0x00001400 + i, ROM32(bios->data[hwsq_entry_offset + i + 4])); + nv_wr32(dev, 0x00001400 + i, ROM32(bios->data[hwsq_entry_offset + i + 4])); /* twiddle NV_PBUS_DEBUG_4 */ - bios_wr32(bios, NV_PBUS_DEBUG_4, bios_rd32(bios, NV_PBUS_DEBUG_4) | 0x18); + nv_wr32(dev, NV_PBUS_DEBUG_4, nv_rd32(dev, NV_PBUS_DEBUG_4) | 0x18); return 0; } @@ -5618,32 +2246,6 @@ uint8_t *nouveau_bios_embedded_edid(struct drm_device *dev) return bios->fp.edid = &bios->data[offset]; } -void -nouveau_bios_run_init_table(struct drm_device *dev, uint16_t table, - struct dcb_entry *dcbent, int crtc) -{ - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nvbios *bios = &dev_priv->vbios; - struct init_exec iexec = { true, false }; - - spin_lock_bh(&bios->lock); - bios->display.output = dcbent; - bios->display.crtc = crtc; - parse_init_table(bios, table, &iexec); - bios->display.output = NULL; - spin_unlock_bh(&bios->lock); -} - -void -nouveau_bios_init_exec(struct drm_device *dev, uint16_t table) -{ - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nvbios *bios = &dev_priv->vbios; - struct init_exec iexec = { true, false }; - - parse_init_table(bios, table, &iexec); -} - static bool NVInitVBIOS(struct drm_device *dev) { struct drm_nouveau_private *dev_priv = dev->dev_private; @@ -5704,23 +2306,8 @@ nouveau_run_vbios_init(struct drm_device *dev) bios->fp.lvds_init_run = false; } - parse_init_tables(bios); - - /* - * Runs some additional script seen on G8x VBIOSen. The VBIOS' - * parser will run this right after the init tables, the binary - * driver appears to run it at some point later. - */ - if (bios->some_script_ptr) { - struct init_exec iexec = {true, false}; - - NV_INFO(dev, "Parsing VBIOS init table at offset 0x%04X\n", - bios->some_script_ptr); - parse_init_table(bios, bios->some_script_ptr, &iexec); - } - if (dev_priv->card_type >= NV_50) { - for (i = 0; i < bios->dcb.entries; i++) { + for (i = 0; bios->execute && i < bios->dcb.entries; i++) { nouveau_bios_run_display_table(dev, 0, 0, &bios->dcb.entry[i], -1); } diff --git a/drivers/gpu/drm/nouveau/nouveau_bios.h b/drivers/gpu/drm/nouveau/nouveau_bios.h index e9bb14ec8c3b..13a7e1270801 100644 --- a/drivers/gpu/drm/nouveau/nouveau_bios.h +++ b/drivers/gpu/drm/nouveau/nouveau_bios.h @@ -72,66 +72,18 @@ enum dcb_connector_type { DCB_CONNECTOR_NONE = 0xff }; -enum dcb_type { - OUTPUT_ANALOG = 0, - OUTPUT_TV = 1, - OUTPUT_TMDS = 2, - OUTPUT_LVDS = 3, - OUTPUT_DP = 6, - OUTPUT_EOL = 14, /* DCB 4.0+, appears to be end-of-list */ - OUTPUT_UNUSED = 15, - OUTPUT_ANY = -1 -}; - -struct dcb_entry { - int index; /* may not be raw dcb index if merging has happened */ - enum dcb_type type; - uint8_t i2c_index; - uint8_t heads; - uint8_t connector; - uint8_t bus; - uint8_t location; - uint8_t or; - bool duallink_possible; - union { - struct sor_conf { - int link; - } sorconf; - struct { - int maxfreq; - } crtconf; - struct { - struct sor_conf sor; - bool use_straps_for_mode; - bool use_acpi_for_edid; - bool use_power_scripts; - } lvdsconf; - struct { - bool has_component_output; - } tvconf; - struct { - struct sor_conf sor; - int link_nr; - int link_bw; - } dpconf; - struct { - struct sor_conf sor; - int slave_addr; - } tmdsconf; - }; - bool i2c_upper_default; -}; +#include struct dcb_table { uint8_t version; int entries; - struct dcb_entry entry[DCB_MAX_NUM_ENTRIES]; + struct dcb_output entry[DCB_MAX_NUM_ENTRIES]; }; enum nouveau_or { - OUTPUT_A = (1 << 0), - OUTPUT_B = (1 << 1), - OUTPUT_C = (1 << 2) + DCB_OUTPUT_A = (1 << 0), + DCB_OUTPUT_B = (1 << 1), + DCB_OUTPUT_C = (1 << 2) }; enum LVDS_script { @@ -195,7 +147,7 @@ struct nvbios { } state; struct { - struct dcb_entry *output; + struct dcb_output *output; int crtc; uint16_t script_table_ptr; } display; @@ -244,7 +196,7 @@ void *olddcb_table(struct drm_device *); void *olddcb_outp(struct drm_device *, u8 idx); int olddcb_outp_foreach(struct drm_device *, void *data, int (*)(struct drm_device *, void *, int idx, u8 *outp)); -u8 *dcb_conntab(struct drm_device *); -u8 *dcb_conn(struct drm_device *, u8 idx); +u8 *olddcb_conntab(struct drm_device *); +u8 *olddcb_conn(struct drm_device *, u8 idx); #endif diff --git a/drivers/gpu/drm/nouveau/nouveau_compat.c b/drivers/gpu/drm/nouveau/nouveau_compat.c index 30431c820bb3..3fc7d5785c6f 100644 --- a/drivers/gpu/drm/nouveau/nouveau_compat.c +++ b/drivers/gpu/drm/nouveau/nouveau_compat.c @@ -2,6 +2,8 @@ #include "nouveau_compat.h" #include +#include +#include #include #include #include @@ -9,6 +11,18 @@ void *nouveau_newpriv(struct drm_device *); +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) { @@ -255,3 +269,27 @@ nva3_calc_pll(struct drm_device *dev, struct nvbios_pll *info, u32 freq, 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); +} diff --git a/drivers/gpu/drm/nouveau/nouveau_compat.h b/drivers/gpu/drm/nouveau/nouveau_compat.h index 8bf5bec81710..7ffad0a7a301 100644 --- a/drivers/gpu/drm/nouveau/nouveau_compat.h +++ b/drivers/gpu/drm/nouveau/nouveau_compat.h @@ -1,6 +1,8 @@ #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); @@ -45,4 +47,8 @@ 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); + #endif diff --git a/drivers/gpu/drm/nouveau/nouveau_connector.c b/drivers/gpu/drm/nouveau/nouveau_connector.c index f9cc3b386065..bd0985a4ff64 100644 --- a/drivers/gpu/drm/nouveau/nouveau_connector.c +++ b/drivers/gpu/drm/nouveau/nouveau_connector.c @@ -59,7 +59,7 @@ find_encoder(struct drm_connector *connector, int type) continue; nv_encoder = nouveau_encoder(obj_to_encoder(obj)); - if (type == OUTPUT_ANY || nv_encoder->dcb->type == type) + if (type == DCB_OUTPUT_ANY || nv_encoder->dcb->type == type) return nv_encoder; } @@ -149,8 +149,8 @@ nouveau_connector_of_detect(struct drm_connector *connector) struct device_node *cn, *dn = pci_device_to_OF_node(dev->pdev); if (!dn || - !((nv_encoder = find_encoder(connector, OUTPUT_TMDS)) || - (nv_encoder = find_encoder(connector, OUTPUT_ANALOG)))) + !((nv_encoder = find_encoder(connector, DCB_OUTPUT_TMDS)) || + (nv_encoder = find_encoder(connector, DCB_OUTPUT_ANALOG)))) return NULL; for_each_child_of_node(dn, cn) { @@ -185,8 +185,8 @@ nouveau_connector_set_encoder(struct drm_connector *connector, connector->interlace_allowed = true; connector->doublescan_allowed = true; } else - if (nv_encoder->dcb->type == OUTPUT_LVDS || - nv_encoder->dcb->type == OUTPUT_TMDS) { + if (nv_encoder->dcb->type == DCB_OUTPUT_LVDS || + nv_encoder->dcb->type == DCB_OUTPUT_TMDS) { connector->doublescan_allowed = false; connector->interlace_allowed = false; } else { @@ -204,7 +204,7 @@ nouveau_connector_set_encoder(struct drm_connector *connector, if (nv_connector->type == DCB_CONNECTOR_DVI_I) { drm_connector_property_set_value(connector, dev->mode_config.dvi_i_subconnector_property, - nv_encoder->dcb->type == OUTPUT_TMDS ? + nv_encoder->dcb->type == DCB_OUTPUT_TMDS ? DRM_MODE_SUBCONNECTOR_DVID : DRM_MODE_SUBCONNECTOR_DVIA); } @@ -238,7 +238,7 @@ nouveau_connector_detect(struct drm_connector *connector, bool force) goto detect_analog; } - if (nv_encoder->dcb->type == OUTPUT_DP && + 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", drm_get_connector_name(connector)); @@ -251,19 +251,19 @@ nouveau_connector_detect(struct drm_connector *connector, bool force) * isn't necessarily correct. */ nv_partner = NULL; - if (nv_encoder->dcb->type == OUTPUT_TMDS) - nv_partner = find_encoder(connector, OUTPUT_ANALOG); - if (nv_encoder->dcb->type == OUTPUT_ANALOG) - nv_partner = find_encoder(connector, OUTPUT_TMDS); - - if (nv_partner && ((nv_encoder->dcb->type == OUTPUT_ANALOG && - nv_partner->dcb->type == OUTPUT_TMDS) || - (nv_encoder->dcb->type == OUTPUT_TMDS && - nv_partner->dcb->type == OUTPUT_ANALOG))) { + if (nv_encoder->dcb->type == DCB_OUTPUT_TMDS) + nv_partner = find_encoder(connector, DCB_OUTPUT_ANALOG); + if (nv_encoder->dcb->type == DCB_OUTPUT_ANALOG) + nv_partner = find_encoder(connector, DCB_OUTPUT_TMDS); + + if (nv_partner && ((nv_encoder->dcb->type == DCB_OUTPUT_ANALOG && + nv_partner->dcb->type == DCB_OUTPUT_TMDS) || + (nv_encoder->dcb->type == DCB_OUTPUT_TMDS && + nv_partner->dcb->type == DCB_OUTPUT_ANALOG))) { if (nv_connector->edid->input & DRM_EDID_INPUT_DIGITAL) - type = OUTPUT_TMDS; + type = DCB_OUTPUT_TMDS; else - type = OUTPUT_ANALOG; + type = DCB_OUTPUT_ANALOG; nv_encoder = find_encoder(connector, type); } @@ -279,9 +279,9 @@ nouveau_connector_detect(struct drm_connector *connector, bool force) } detect_analog: - nv_encoder = find_encoder(connector, OUTPUT_ANALOG); + nv_encoder = find_encoder(connector, DCB_OUTPUT_ANALOG); if (!nv_encoder && !nouveau_tv_disable) - nv_encoder = find_encoder(connector, OUTPUT_TV); + nv_encoder = find_encoder(connector, DCB_OUTPUT_TV); if (nv_encoder && force) { struct drm_encoder *encoder = to_drm_encoder(nv_encoder); struct drm_encoder_helper_funcs *helper = @@ -314,7 +314,7 @@ nouveau_connector_detect_lvds(struct drm_connector *connector, bool force) nv_connector->edid = NULL; } - nv_encoder = find_encoder(connector, OUTPUT_LVDS); + nv_encoder = find_encoder(connector, DCB_OUTPUT_LVDS); if (!nv_encoder) return connector_status_disconnected; @@ -386,11 +386,11 @@ nouveau_connector_force(struct drm_connector *connector) if (nv_connector->type == DCB_CONNECTOR_DVI_I) { if (connector->force == DRM_FORCE_ON_DIGITAL) - type = OUTPUT_TMDS; + type = DCB_OUTPUT_TMDS; else - type = OUTPUT_ANALOG; + type = DCB_OUTPUT_ANALOG; } else - type = OUTPUT_ANY; + type = DCB_OUTPUT_ANY; nv_encoder = find_encoder(connector, type); if (!nv_encoder) { @@ -533,7 +533,7 @@ nouveau_connector_set_property(struct drm_connector *connector, } } - if (nv_encoder && nv_encoder->dcb->type == OUTPUT_TV) + if (nv_encoder && nv_encoder->dcb->type == DCB_OUTPUT_TV) return get_slave_funcs(encoder)->set_property( encoder, connector, property, value); @@ -662,7 +662,7 @@ nouveau_connector_detect_depth(struct drm_connector *connector) } /* we're out of options unless we're LVDS, default to 8bpc */ - if (nv_encoder->dcb->type != OUTPUT_LVDS) { + if (nv_encoder->dcb->type != DCB_OUTPUT_LVDS) { connector->display_info.bpc = 8; return; } @@ -710,7 +710,7 @@ nouveau_connector_get_modes(struct drm_connector *connector) if (nv_connector->edid) ret = drm_add_edid_modes(connector, nv_connector->edid); else - if (nv_encoder->dcb->type == OUTPUT_LVDS && + 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)) { struct drm_display_mode mode; @@ -747,7 +747,7 @@ nouveau_connector_get_modes(struct drm_connector *connector) if (connector->connector_type == DRM_MODE_CONNECTOR_LVDS) nouveau_connector_detect_depth(connector); - if (nv_encoder->dcb->type == OUTPUT_TV) + if (nv_encoder->dcb->type == DCB_OUTPUT_TV) ret = get_slave_funcs(encoder)->get_modes(encoder, connector); if (nv_connector->type == DCB_CONNECTOR_LVDS || @@ -763,7 +763,7 @@ 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 dcb_entry *dcb = nv_connector->detected_encoder->dcb; + struct dcb_output *dcb = nv_connector->detected_encoder->dcb; if (dcb->location != DCB_LOC_ON_CHIP || dev_priv->chipset >= 0x46) @@ -787,7 +787,7 @@ nouveau_connector_mode_valid(struct drm_connector *connector, unsigned clock = mode->clock; switch (nv_encoder->dcb->type) { - case OUTPUT_LVDS: + case DCB_OUTPUT_LVDS: if (nv_connector->native_mode && (mode->hdisplay > nv_connector->native_mode->hdisplay || mode->vdisplay > nv_connector->native_mode->vdisplay)) @@ -796,19 +796,19 @@ nouveau_connector_mode_valid(struct drm_connector *connector, min_clock = 0; max_clock = 400000; break; - case OUTPUT_TMDS: + case DCB_OUTPUT_TMDS: max_clock = get_tmds_link_bandwidth(connector); if (nouveau_duallink && nv_encoder->dcb->duallink_possible) max_clock *= 2; break; - case OUTPUT_ANALOG: + case DCB_OUTPUT_ANALOG: max_clock = nv_encoder->dcb->crtconf.maxfreq; if (!max_clock) max_clock = 350000; break; - case OUTPUT_TV: + case DCB_OUTPUT_TV: return get_slave_funcs(encoder)->mode_valid(encoder, mode); - case OUTPUT_DP: + case DCB_OUTPUT_DP: max_clock = nv_encoder->dp.link_nr; max_clock *= nv_encoder->dp.link_bw; clock = clock * (connector->display_info.bpc * 3) / 10; @@ -923,7 +923,7 @@ nouveau_connector_create(struct drm_device *dev, int index) nv_connector->index = index; /* attempt to parse vbios connector type and hotplug gpio */ - nv_connector->dcb = dcb_conn(dev, index); + nv_connector->dcb = olddcb_conn(dev, index); if (nv_connector->dcb) { static const u8 hpd[16] = { 0xff, 0x07, 0x08, 0xff, 0xff, 0x51, 0x52, 0xff, @@ -931,7 +931,7 @@ nouveau_connector_create(struct drm_device *dev, int index) }; u32 entry = ROM16(nv_connector->dcb[0]); - if (dcb_conntab(dev)[3] >= 4) + if (olddcb_conntab(dev)[3] >= 4) entry |= (u32)ROM16(nv_connector->dcb[2]) << 16; nv_connector->hpd = ffs((entry & 0x07033000) >> 12); @@ -975,25 +975,25 @@ nouveau_connector_create(struct drm_device *dev, int index) encoders |= (1 << dcbt->entry[i].type); } - if (encoders & (1 << OUTPUT_DP)) { - if (encoders & (1 << OUTPUT_TMDS)) + if (encoders & (1 << DCB_OUTPUT_DP)) { + if (encoders & (1 << DCB_OUTPUT_TMDS)) nv_connector->type = DCB_CONNECTOR_DP; else nv_connector->type = DCB_CONNECTOR_eDP; } else - if (encoders & (1 << OUTPUT_TMDS)) { - if (encoders & (1 << OUTPUT_ANALOG)) + if (encoders & (1 << DCB_OUTPUT_TMDS)) { + if (encoders & (1 << DCB_OUTPUT_ANALOG)) nv_connector->type = DCB_CONNECTOR_DVI_I; else nv_connector->type = DCB_CONNECTOR_DVI_D; } else - if (encoders & (1 << OUTPUT_ANALOG)) { + if (encoders & (1 << DCB_OUTPUT_ANALOG)) { nv_connector->type = DCB_CONNECTOR_VGA; } else - if (encoders & (1 << OUTPUT_LVDS)) { + if (encoders & (1 << DCB_OUTPUT_LVDS)) { nv_connector->type = DCB_CONNECTOR_LVDS; } else - if (encoders & (1 << OUTPUT_TV)) { + if (encoders & (1 << DCB_OUTPUT_TV)) { nv_connector->type = DCB_CONNECTOR_TV_0; } } diff --git a/drivers/gpu/drm/nouveau/nouveau_dp.c b/drivers/gpu/drm/nouveau/nouveau_dp.c index 9e18b35803a8..6fe11f8c5f6c 100644 --- a/drivers/gpu/drm/nouveau/nouveau_dp.c +++ b/drivers/gpu/drm/nouveau/nouveau_dp.c @@ -31,7 +31,7 @@ #include "nouveau_crtc.h" u8 * -nouveau_dp_bios_data(struct drm_device *dev, struct dcb_entry *dcb, u8 **entry) +nouveau_dp_bios_data(struct drm_device *dev, struct dcb_output *dcb, u8 **entry) { struct bit_entry d; u8 *table; @@ -80,7 +80,7 @@ nouveau_dp_bios_data(struct drm_device *dev, struct dcb_entry *dcb, u8 **entry) struct dp_state { struct nouveau_i2c_port *auxch; struct dp_train_func *func; - struct dcb_entry *dcb; + struct dcb_output *dcb; int crtc; u8 *dpcd; int link_nr; diff --git a/drivers/gpu/drm/nouveau/nouveau_drm.c b/drivers/gpu/drm/nouveau/nouveau_drm.c index c72d42636c89..3b4e65d5122b 100644 --- a/drivers/gpu/drm/nouveau/nouveau_drm.c +++ b/drivers/gpu/drm/nouveau/nouveau_drm.c @@ -32,6 +32,7 @@ #include #include "nouveau_drm.h" +#include "nouveau_agp.h" int __devinit nouveau_pci_probe(struct pci_dev *, const struct pci_device_id *); void nouveau_pci_remove(struct pci_dev *); @@ -123,6 +124,30 @@ nouveau_drm_load(struct drm_device *dev, unsigned long flags) INIT_LIST_HEAD(&drm->clients); drm->dev = dev; + /* make sure AGP controller is in a consistent state before we + * (possibly) execute vbios init tables (see nouveau_agp.h) + */ + if (drm_pci_device_is_agp(dev) && dev->agp) { + /* dummy device object, doesn't init anything, but allows + * agp code access to registers + */ + ret = nouveau_object_new(nv_object(drm), NVDRM_CLIENT, + NVDRM_DEVICE, 0x0080, + &(struct nv_device_class) { + .device = ~0, + .disable = + ~(NV_DEVICE_DISABLE_MMIO | + NV_DEVICE_DISABLE_IDENTIFY), + .debug0 = ~0, + }, sizeof(struct nv_device_class), + &drm->device); + if (ret) + return ret; + + nouveau_agp_reset(drm); + nouveau_object_del(nv_object(drm), NVDRM_CLIENT, NVDRM_DEVICE); + } + ret = nouveau_object_new(nv_object(drm), NVDRM_CLIENT, NVDRM_DEVICE, 0x0080, &(struct nv_device_class) { .device = ~0, @@ -133,6 +158,9 @@ nouveau_drm_load(struct drm_device *dev, unsigned long flags) if (ret) goto fail_device; + /* initialise AGP */ + nouveau_agp_init(drm); + ret = nouveau_load(dev, flags); if (ret) goto fail_device; @@ -155,6 +183,8 @@ nouveau_drm_unload(struct drm_device *dev) if (ret) return ret; + nouveau_agp_fini(drm); + pci_set_drvdata(pdev, drm->client.base.device); nouveau_cli_destroy(&drm->client); return 0; @@ -195,6 +225,8 @@ nouveau_drm_suspend(struct pci_dev *pdev, pm_message_t pm_state) if (ret) goto fail_client; + nouveau_agp_fini(drm); + pci_save_state(pdev); if (pm_state.event == PM_EVENT_SUSPEND) { pci_disable_device(pdev); @@ -230,12 +262,16 @@ nouveau_drm_resume(struct pci_dev *pdev) return ret; pci_set_master(pdev); + nouveau_agp_reset(drm); + nouveau_client_init(&drm->client.base); list_for_each_entry(cli, &drm->clients, head) { nouveau_client_init(&cli->base); } + nouveau_agp_init(drm); + return nouveau_pci_resume(pdev); } diff --git a/drivers/gpu/drm/nouveau/nouveau_drm.h b/drivers/gpu/drm/nouveau/nouveau_drm.h index ef5500f56864..87698067244b 100644 --- a/drivers/gpu/drm/nouveau/nouveau_drm.h +++ b/drivers/gpu/drm/nouveau/nouveau_drm.h @@ -23,6 +23,16 @@ struct nouveau_drm { struct nouveau_object *device; struct list_head clients; + + struct { + enum { + UNKNOWN = 0, + DISABLE = 1, + ENABLED = 2 + } stat; + u32 base; + u32 size; + } agp; }; 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 index cea947beb35b..25487c148e4a 100644 --- a/drivers/gpu/drm/nouveau/nouveau_drv.c +++ b/drivers/gpu/drm/nouveau/nouveau_drv.c @@ -29,7 +29,6 @@ #include "drm.h" #include "drm_crtc_helper.h" #include "nouveau_drv.h" -#include "nouveau_agp.h" #include "nouveau_abi16.h" #include "nouveau_hw.h" #include "nouveau_fb.h" @@ -219,7 +218,6 @@ nouveau_pci_suspend(struct pci_dev *pdev, pm_message_t pm_state) goto out_abort; } - nouveau_agp_fini(dev); return 0; out_abort: @@ -241,9 +239,6 @@ nouveau_pci_resume(struct pci_dev *pdev) struct drm_crtc *crtc; int ret, i; - /* Make sure the AGP controller is in a consistent state */ - nouveau_agp_reset(dev); - /* Make the CRTCs accessible */ engine->display.early_init(dev); @@ -252,8 +247,6 @@ nouveau_pci_resume(struct pci_dev *pdev) if (ret) return ret; - nouveau_agp_init(dev); - NV_INFO(dev, "Restoring GPU objects...\n"); nouveau_gpuobj_resume(dev); diff --git a/drivers/gpu/drm/nouveau/nouveau_drv.h b/drivers/gpu/drm/nouveau/nouveau_drv.h index 2b519b5cfac9..f6be94d323f0 100644 --- a/drivers/gpu/drm/nouveau/nouveau_drv.h +++ b/drivers/gpu/drm/nouveau/nouveau_drv.h @@ -1040,22 +1040,19 @@ static inline void nouveau_backlight_exit(struct drm_device *dev) { } 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 void nouveau_bios_run_init_table(struct drm_device *, uint16_t table, - struct dcb_entry *, int crtc); -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 int nouveau_bios_run_display_table(struct drm_device *, u16 id, int clk, - struct dcb_entry *, int crtc); + 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_entry *, +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_entry *, int head, +extern int call_lvds_script(struct drm_device *, struct dcb_output *, int head, enum LVDS_script, int pxclk); -bool bios_encoder_match(struct dcb_entry *, u32 hash); +bool bios_encoder_match(struct dcb_output *, u32 hash); /* nouveau_mxm.c */ int nouveau_mxm_init(struct drm_device *dev); @@ -1234,26 +1231,26 @@ extern long nouveau_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg); /* nv04_dac.c */ -extern int nv04_dac_create(struct drm_connector *, struct dcb_entry *); +extern int nv04_dac_create(struct drm_connector *, struct dcb_output *); extern uint32_t nv17_dac_sample_load(struct drm_encoder *encoder); extern int nv04_dac_output_offset(struct drm_encoder *encoder); extern void nv04_dac_update_dacclk(struct drm_encoder *encoder, bool enable); extern bool nv04_dac_in_use(struct drm_encoder *encoder); /* nv04_dfp.c */ -extern int nv04_dfp_create(struct drm_connector *, struct dcb_entry *); -extern int nv04_dfp_get_bound_head(struct drm_device *dev, struct dcb_entry *dcbent); -extern void nv04_dfp_bind_head(struct drm_device *dev, struct dcb_entry *dcbent, +extern int nv04_dfp_create(struct drm_connector *, struct dcb_output *); +extern int nv04_dfp_get_bound_head(struct drm_device *dev, struct dcb_output *dcbent); +extern void nv04_dfp_bind_head(struct drm_device *dev, struct dcb_output *dcbent, int head, bool dl); extern void nv04_dfp_disable(struct drm_device *dev, int head); extern void nv04_dfp_update_fp_control(struct drm_encoder *encoder, int mode); /* nv04_tv.c */ extern int nv04_tv_identify(struct drm_device *dev, int i2c_index); -extern int nv04_tv_create(struct drm_connector *, struct dcb_entry *); +extern int nv04_tv_create(struct drm_connector *, struct dcb_output *); /* nv17_tv.c */ -extern int nv17_tv_create(struct drm_connector *, struct dcb_entry *); +extern int nv17_tv_create(struct drm_connector *, struct dcb_output *); /* nv04_display.c */ extern int nv04_display_early_init(struct drm_device *); diff --git a/drivers/gpu/drm/nouveau/nouveau_encoder.h b/drivers/gpu/drm/nouveau/nouveau_encoder.h index 1e79ee5fb89e..789221d86c4a 100644 --- a/drivers/gpu/drm/nouveau/nouveau_encoder.h +++ b/drivers/gpu/drm/nouveau/nouveau_encoder.h @@ -35,17 +35,17 @@ struct nouveau_i2c_port; struct dp_train_func { - void (*link_set)(struct drm_device *, struct dcb_entry *, int crtc, + void (*link_set)(struct drm_device *, struct dcb_output *, int crtc, int nr, u32 bw, bool enhframe); - void (*train_set)(struct drm_device *, struct dcb_entry *, u8 pattern); - void (*train_adj)(struct drm_device *, struct dcb_entry *, + void (*train_set)(struct drm_device *, struct dcb_output *, u8 pattern); + void (*train_adj)(struct drm_device *, struct dcb_output *, u8 lane, u8 swing, u8 preem); }; struct nouveau_encoder { struct drm_encoder_slave base; - struct dcb_entry *dcb; + struct dcb_output *dcb; int or; /* different to drm_encoder.crtc, this reflects what's @@ -92,13 +92,13 @@ get_slave_funcs(struct drm_encoder *enc) bool nouveau_dp_detect(struct drm_encoder *); void nouveau_dp_dpms(struct drm_encoder *, int mode, u32 datarate, struct dp_train_func *); -u8 *nouveau_dp_bios_data(struct drm_device *, struct dcb_entry *, u8 **); +u8 *nouveau_dp_bios_data(struct drm_device *, struct dcb_output *, u8 **); struct nouveau_connector * nouveau_encoder_connector_get(struct nouveau_encoder *encoder); -int nv50_sor_create(struct drm_connector *, struct dcb_entry *); +int nv50_sor_create(struct drm_connector *, struct dcb_output *); void nv50_sor_dp_calc_tu(struct drm_device *, int, int, u32, u32); -int nv50_dac_create(struct drm_connector *, struct dcb_entry *); +int nv50_dac_create(struct drm_connector *, struct dcb_output *); #endif /* __NOUVEAU_ENCODER_H__ */ diff --git a/drivers/gpu/drm/nouveau/nouveau_hw.h b/drivers/gpu/drm/nouveau/nouveau_hw.h index ff7f31c279d8..24c459213613 100644 --- a/drivers/gpu/drm/nouveau/nouveau_hw.h +++ b/drivers/gpu/drm/nouveau/nouveau_hw.h @@ -161,7 +161,7 @@ static inline void NVWriteRAMDAC(struct drm_device *dev, static inline uint8_t nv_read_tmds(struct drm_device *dev, int or, int dl, uint8_t address) { - int ramdac = (or & OUTPUT_C) >> 2; + int ramdac = (or & DCB_OUTPUT_C) >> 2; NVWriteRAMDAC(dev, ramdac, NV_PRAMDAC_FP_TMDS_CONTROL + dl * 8, NV_PRAMDAC_FP_TMDS_CONTROL_WRITE_DISABLE | address); @@ -172,7 +172,7 @@ static inline void nv_write_tmds(struct drm_device *dev, int or, int dl, uint8_t address, uint8_t data) { - int ramdac = (or & OUTPUT_C) >> 2; + int ramdac = (or & DCB_OUTPUT_C) >> 2; NVWriteRAMDAC(dev, ramdac, NV_PRAMDAC_FP_TMDS_DATA + dl * 8, data); NVWriteRAMDAC(dev, ramdac, NV_PRAMDAC_FP_TMDS_CONTROL + dl * 8, address); diff --git a/drivers/gpu/drm/nouveau/nouveau_mem.c b/drivers/gpu/drm/nouveau/nouveau_mem.c index c816e03c15d4..689d3e708057 100644 --- a/drivers/gpu/drm/nouveau/nouveau_mem.c +++ b/drivers/gpu/drm/nouveau/nouveau_mem.c @@ -36,7 +36,6 @@ #include "drm_sarea.h" #include "nouveau_drv.h" -#include "nouveau_agp.h" #include "nouveau_pm.h" #include #include @@ -173,7 +172,6 @@ void nouveau_mem_gart_fini(struct drm_device *dev) { nouveau_sgdma_takedown(dev); - nouveau_agp_fini(dev); } bool @@ -308,7 +306,9 @@ nouveau_mem_gart_init(struct drm_device *dev) struct ttm_bo_device *bdev = &dev_priv->ttm.bdev; int ret; - nouveau_agp_init(dev); + if (!nvdrm_gart_init(dev, &dev_priv->gart_info.aper_base, + &dev_priv->gart_info.aper_size)) + dev_priv->gart_info.type = NOUVEAU_GART_AGP; if (dev_priv->gart_info.type == NOUVEAU_GART_NONE) { ret = nouveau_sgdma_init(dev); diff --git a/drivers/gpu/drm/nouveau/nouveau_mxm.c b/drivers/gpu/drm/nouveau/nouveau_mxm.c index 7ca129d55839..670ef087d3d3 100644 --- a/drivers/gpu/drm/nouveau/nouveau_mxm.c +++ b/drivers/gpu/drm/nouveau/nouveau_mxm.c @@ -390,7 +390,7 @@ mxm_dcb_sanitise_entry(struct drm_device *dev, void *data, int idx, u8 *dcbe) * vbios mxm table */ i2cidx = mxm_ddc_map(dev, ctx.desc.ddc_port); - if ((ctx.outp[0] & 0x0000000f) != OUTPUT_DP) + if ((ctx.outp[0] & 0x0000000f) != DCB_OUTPUT_DP) i2cidx = (i2cidx & 0x0f) << 4; else i2cidx = (i2cidx & 0xf0); @@ -419,7 +419,7 @@ mxm_dcb_sanitise_entry(struct drm_device *dev, void *data, int idx, u8 *dcbe) * and the mxm data says the connector is really HDMI. another * common example is DP->eDP. */ - conn = dcb_conn(dev, (ctx.outp[0] & 0x0000f000) >> 12); + conn = olddcb_conn(dev, (ctx.outp[0] & 0x0000f000) >> 12); type = conn[0]; switch (ctx.desc.conn_type) { case 0x01: /* LVDS */ diff --git a/drivers/gpu/drm/nouveau/nouveau_state.c b/drivers/gpu/drm/nouveau/nouveau_state.c index 84e03797bec3..1a07655d1e9c 100644 --- a/drivers/gpu/drm/nouveau/nouveau_state.c +++ b/drivers/gpu/drm/nouveau/nouveau_state.c @@ -34,7 +34,6 @@ #include "nouveau_drv.h" #include -#include "nouveau_agp.h" #include "nouveau_fbcon.h" #include #include "nouveau_pm.h" @@ -516,9 +515,6 @@ nouveau_card_init(struct drm_device *dev) spin_lock_init(&dev_priv->context_switch_lock); spin_lock_init(&dev_priv->vm_lock); - /* Make sure the AGP controller is in a consistent state */ - nouveau_agp_reset(dev); - /* Make the CRTCs and I2C buses accessible */ ret = engine->display.early_init(dev); if (ret) diff --git a/drivers/gpu/drm/nouveau/nv04_crtc.c b/drivers/gpu/drm/nouveau/nv04_crtc.c index 93ca09b90da5..1d38968abcf1 100644 --- a/drivers/gpu/drm/nouveau/nv04_crtc.c +++ b/drivers/gpu/drm/nouveau/nv04_crtc.c @@ -251,8 +251,8 @@ nv_crtc_mode_set_vga(struct drm_crtc *crtc, struct drm_display_mode *mode) struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); if (encoder->crtc == crtc && - (nv_encoder->dcb->type == OUTPUT_LVDS || - nv_encoder->dcb->type == OUTPUT_TMDS)) + (nv_encoder->dcb->type == DCB_OUTPUT_LVDS || + nv_encoder->dcb->type == DCB_OUTPUT_TMDS)) fp_output = true; } @@ -467,11 +467,11 @@ nv_crtc_mode_set_regs(struct drm_crtc *crtc, struct drm_display_mode * mode) if (encoder->crtc != crtc) continue; - if (nv_encoder->dcb->type == OUTPUT_LVDS) + if (nv_encoder->dcb->type == DCB_OUTPUT_LVDS) digital = lvds_output = true; - if (nv_encoder->dcb->type == OUTPUT_TV) + if (nv_encoder->dcb->type == DCB_OUTPUT_TV) tv_output = true; - if (nv_encoder->dcb->type == OUTPUT_TMDS) + if (nv_encoder->dcb->type == DCB_OUTPUT_TMDS) digital = tmds_output = true; if (nv_encoder->dcb->location != DCB_LOC_ON_CHIP && digital) off_chip_digital = true; diff --git a/drivers/gpu/drm/nouveau/nv04_dac.c b/drivers/gpu/drm/nouveau/nv04_dac.c index 54deb2779f8c..a1a2c2f33d53 100644 --- a/drivers/gpu/drm/nouveau/nv04_dac.c +++ b/drivers/gpu/drm/nouveau/nv04_dac.c @@ -38,12 +38,12 @@ int nv04_dac_output_offset(struct drm_encoder *encoder) { - struct dcb_entry *dcb = nouveau_encoder(encoder)->dcb; + struct dcb_output *dcb = nouveau_encoder(encoder)->dcb; int offset = 0; - if (dcb->or & (8 | OUTPUT_C)) + if (dcb->or & (8 | DCB_OUTPUT_C)) offset += 0x68; - if (dcb->or & (8 | OUTPUT_B)) + if (dcb->or & (8 | DCB_OUTPUT_B)) offset += 0x2000; return offset; @@ -222,14 +222,14 @@ 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 dcb_entry *dcb = nouveau_encoder(encoder)->dcb; + 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; int head; #define RGB_TEST_DATA(r, g, b) (r << 0 | g << 10 | b << 20) - if (dcb->type == OUTPUT_TV) { + if (dcb->type == DCB_OUTPUT_TV) { testval = RGB_TEST_DATA(0xa0, 0xa0, 0xa0); if (dev_priv->vbios.tvdactestval) @@ -256,8 +256,8 @@ uint32_t nv17_dac_sample_load(struct drm_encoder *encoder) 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 == OUTPUT_TV); - nouveau_gpio_func_set(dev, DCB_GPIO_TVDAC0, dcb->type == OUTPUT_TV); + 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); msleep(4); @@ -272,7 +272,7 @@ uint32_t nv17_dac_sample_load(struct drm_encoder *encoder) routput = (saved_routput & 0xfffffece) | head << 8; if (dev_priv->card_type >= NV_40) { - if (dcb->type == OUTPUT_TV) + if (dcb->type == DCB_OUTPUT_TV) routput |= 0x1a << 16; else routput &= ~(0x1a << 16); @@ -317,7 +317,7 @@ static enum drm_connector_status nv17_dac_detect(struct drm_encoder *encoder, struct drm_connector *connector) { struct drm_device *dev = encoder->dev; - struct dcb_entry *dcb = nouveau_encoder(encoder)->dcb; + struct dcb_output *dcb = nouveau_encoder(encoder)->dcb; if (nv04_dac_in_use(encoder)) return connector_status_disconnected; @@ -373,7 +373,7 @@ static void nv04_dac_mode_set(struct drm_encoder *encoder, /* force any other vga encoders to bind to the other crtc */ list_for_each_entry(rebind, &dev->mode_config.encoder_list, head) { if (rebind == encoder - || nouveau_encoder(rebind)->dcb->type != OUTPUT_ANALOG) + || nouveau_encoder(rebind)->dcb->type != DCB_OUTPUT_ANALOG) continue; dac_offset = nv04_dac_output_offset(rebind); @@ -408,7 +408,7 @@ void nv04_dac_update_dacclk(struct drm_encoder *encoder, bool enable) { struct drm_device *dev = encoder->dev; struct drm_nouveau_private *dev_priv = dev->dev_private; - struct dcb_entry *dcb = nouveau_encoder(encoder)->dcb; + struct dcb_output *dcb = nouveau_encoder(encoder)->dcb; if (nv_gf4_disp_arch(dev)) { uint32_t *dac_users = &dev_priv->dac_users[ffs(dcb->or) - 1]; @@ -433,7 +433,7 @@ void nv04_dac_update_dacclk(struct drm_encoder *encoder, bool enable) bool nv04_dac_in_use(struct drm_encoder *encoder) { struct drm_nouveau_private *dev_priv = encoder->dev->dev_private; - struct dcb_entry *dcb = nouveau_encoder(encoder)->dcb; + struct dcb_output *dcb = nouveau_encoder(encoder)->dcb; return nv_gf4_disp_arch(encoder->dev) && (dev_priv->dac_users[ffs(dcb->or) - 1] & ~(1 << dcb->index)); @@ -513,7 +513,7 @@ static const struct drm_encoder_funcs nv04_dac_funcs = { }; int -nv04_dac_create(struct drm_connector *connector, struct dcb_entry *entry) +nv04_dac_create(struct drm_connector *connector, struct dcb_output *entry) { const struct drm_encoder_helper_funcs *helper; struct nouveau_encoder *nv_encoder = NULL; diff --git a/drivers/gpu/drm/nouveau/nv04_dfp.c b/drivers/gpu/drm/nouveau/nv04_dfp.c index c9835b9bd63d..823a1c5c0755 100644 --- a/drivers/gpu/drm/nouveau/nv04_dfp.c +++ b/drivers/gpu/drm/nouveau/nv04_dfp.c @@ -49,20 +49,20 @@ static inline bool is_fpc_off(uint32_t fpc) FP_TG_CONTROL_OFF); } -int nv04_dfp_get_bound_head(struct drm_device *dev, struct dcb_entry *dcbent) +int nv04_dfp_get_bound_head(struct drm_device *dev, struct dcb_output *dcbent) { /* special case of nv_read_tmds to find crtc associated with an output. * this does not give a correct answer for off-chip dvi, but there's no * use for such an answer anyway */ - int ramdac = (dcbent->or & OUTPUT_C) >> 2; + int ramdac = (dcbent->or & DCB_OUTPUT_C) >> 2; NVWriteRAMDAC(dev, ramdac, NV_PRAMDAC_FP_TMDS_CONTROL, NV_PRAMDAC_FP_TMDS_CONTROL_WRITE_DISABLE | 0x4); return ((NVReadRAMDAC(dev, ramdac, NV_PRAMDAC_FP_TMDS_DATA) & 0x8) >> 3) ^ ramdac; } -void nv04_dfp_bind_head(struct drm_device *dev, struct dcb_entry *dcbent, +void nv04_dfp_bind_head(struct drm_device *dev, struct dcb_output *dcbent, int head, bool dl) { /* The BIOS scripts don't do this for us, sadly @@ -72,13 +72,13 @@ void nv04_dfp_bind_head(struct drm_device *dev, struct dcb_entry *dcbent, * (for VT restore etc.) */ - int ramdac = (dcbent->or & OUTPUT_C) >> 2; + int ramdac = (dcbent->or & DCB_OUTPUT_C) >> 2; uint8_t tmds04 = 0x80; if (head != ramdac) tmds04 = 0x88; - if (dcbent->type == OUTPUT_LVDS) + if (dcbent->type == DCB_OUTPUT_LVDS) tmds04 |= 0x01; nv_write_tmds(dev, dcbent->or, 0, 0x04, tmds04); @@ -151,10 +151,10 @@ void nv04_dfp_update_fp_control(struct drm_encoder *encoder, int mode) static struct drm_encoder *get_tmds_slave(struct drm_encoder *encoder) { struct drm_device *dev = encoder->dev; - struct dcb_entry *dcb = nouveau_encoder(encoder)->dcb; + struct dcb_output *dcb = nouveau_encoder(encoder)->dcb; struct drm_encoder *slave; - if (dcb->type != OUTPUT_TMDS || dcb->location == DCB_LOC_ON_CHIP) + if (dcb->type != DCB_OUTPUT_TMDS || dcb->location == DCB_LOC_ON_CHIP) return NULL; /* Some BIOSes (e.g. the one in a Quadro FX1000) report several @@ -168,9 +168,9 @@ static struct drm_encoder *get_tmds_slave(struct drm_encoder *encoder) * let's do the same. */ list_for_each_entry(slave, &dev->mode_config.encoder_list, head) { - struct dcb_entry *slave_dcb = nouveau_encoder(slave)->dcb; + struct dcb_output *slave_dcb = nouveau_encoder(slave)->dcb; - if (slave_dcb->type == OUTPUT_TMDS && get_slave_funcs(slave) && + if (slave_dcb->type == DCB_OUTPUT_TMDS && get_slave_funcs(slave) && slave_dcb->tmdsconf.slave_addr == dcb->tmdsconf.slave_addr) return slave; } @@ -204,7 +204,7 @@ static void nv04_dfp_prepare_sel_clk(struct drm_device *dev, { struct drm_nouveau_private *dev_priv = dev->dev_private; struct nv04_mode_state *state = &dev_priv->mode_reg; - uint32_t bits1618 = nv_encoder->dcb->or & OUTPUT_A ? 0x10000 : 0x40000; + uint32_t bits1618 = nv_encoder->dcb->or & DCB_OUTPUT_A ? 0x10000 : 0x40000; if (nv_encoder->dcb->location != DCB_LOC_ON_CHIP) return; @@ -233,7 +233,7 @@ static void nv04_dfp_prepare_sel_clk(struct drm_device *dev, * and which bit-pair to use, is unclear on nv40 (for earlier cards, the fp table * entry has the necessary info) */ - if (nv_encoder->dcb->type == OUTPUT_LVDS && dev_priv->saved_reg.sel_clk & 0xf0) { + if (nv_encoder->dcb->type == DCB_OUTPUT_LVDS && dev_priv->saved_reg.sel_clk & 0xf0) { int shift = (dev_priv->saved_reg.sel_clk & 0x50) ? 0 : 1; state->sel_clk &= ~0xf0; @@ -263,7 +263,7 @@ static void nv04_dfp_prepare(struct drm_encoder *encoder) *cr_lcd |= head ? 0x0 : 0x8; else { *cr_lcd |= (nv_encoder->dcb->or << 4) & 0x30; - if (nv_encoder->dcb->type == OUTPUT_LVDS) + if (nv_encoder->dcb->type == DCB_OUTPUT_LVDS) *cr_lcd |= 0x30; if ((*cr_lcd & 0x30) == (*cr_lcd_oth & 0x30)) { /* avoid being connected to both crtcs */ @@ -340,7 +340,7 @@ static void nv04_dfp_mode_set(struct drm_encoder *encoder, if (nv_encoder->dcb->location != DCB_LOC_ON_CHIP && output_mode->clock > 165000) regp->fp_control |= (2 << 24); - if (nv_encoder->dcb->type == OUTPUT_LVDS) { + if (nv_encoder->dcb->type == DCB_OUTPUT_LVDS) { bool duallink = false, dummy; if (nv_connector->edid && nv_connector->type == DCB_CONNECTOR_LVDS_SPWG) { @@ -448,13 +448,13 @@ static void nv04_dfp_commit(struct drm_encoder *encoder) 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); - struct dcb_entry *dcbe = nv_encoder->dcb; + struct dcb_output *dcbe = nv_encoder->dcb; int head = nouveau_crtc(encoder->crtc)->index; struct drm_encoder *slave_encoder; - if (dcbe->type == OUTPUT_TMDS) + if (dcbe->type == DCB_OUTPUT_TMDS) run_tmds_table(dev, dcbe, head, nv_encoder->mode.clock); - else if (dcbe->type == OUTPUT_LVDS) + else if (dcbe->type == DCB_OUTPUT_LVDS) call_lvds_script(dev, dcbe, head, LVDS_RESET, nv_encoder->mode.clock); /* update fp_control state for any changes made by scripts, @@ -588,7 +588,7 @@ static void nv04_dfp_restore(struct drm_encoder *encoder) struct drm_nouveau_private *dev_priv = dev->dev_private; int head = nv_encoder->restore.head; - if (nv_encoder->dcb->type == OUTPUT_LVDS) { + if (nv_encoder->dcb->type == DCB_OUTPUT_LVDS) { struct nouveau_connector *connector = nouveau_encoder_connector_get(nv_encoder); @@ -597,7 +597,7 @@ static void nv04_dfp_restore(struct drm_encoder *encoder) LVDS_PANEL_ON, connector->native_mode->clock); - } else if (nv_encoder->dcb->type == OUTPUT_TMDS) { + } else if (nv_encoder->dcb->type == DCB_OUTPUT_TMDS) { int clock = nouveau_hw_pllvals_to_clk (&dev_priv->saved_reg.crtc_reg[head].pllvals); @@ -623,7 +623,7 @@ static void nv04_dfp_destroy(struct drm_encoder *encoder) static void nv04_tmds_slave_init(struct drm_encoder *encoder) { struct drm_device *dev = encoder->dev; - struct dcb_entry *dcb = nouveau_encoder(encoder)->dcb; + struct dcb_output *dcb = nouveau_encoder(encoder)->dcb; struct nouveau_i2c_port *i2c = nouveau_i2c_find(dev, 2); struct i2c_board_info info[] = { { @@ -676,7 +676,7 @@ static const struct drm_encoder_funcs nv04_dfp_funcs = { }; int -nv04_dfp_create(struct drm_connector *connector, struct dcb_entry *entry) +nv04_dfp_create(struct drm_connector *connector, struct dcb_output *entry) { const struct drm_encoder_helper_funcs *helper; struct nouveau_encoder *nv_encoder = NULL; @@ -684,11 +684,11 @@ nv04_dfp_create(struct drm_connector *connector, struct dcb_entry *entry) int type; switch (entry->type) { - case OUTPUT_TMDS: + case DCB_OUTPUT_TMDS: type = DRM_MODE_ENCODER_TMDS; helper = &nv04_tmds_helper_funcs; break; - case OUTPUT_LVDS: + case DCB_OUTPUT_LVDS: type = DRM_MODE_ENCODER_LVDS; helper = &nv04_lvds_helper_funcs; break; @@ -711,7 +711,7 @@ nv04_dfp_create(struct drm_connector *connector, struct dcb_entry *entry) encoder->possible_crtcs = entry->heads; encoder->possible_clones = 0; - if (entry->type == OUTPUT_TMDS && + if (entry->type == DCB_OUTPUT_TMDS && entry->location != DCB_LOC_ON_CHIP) nv04_tmds_slave_init(encoder); diff --git a/drivers/gpu/drm/nouveau/nv04_display.c b/drivers/gpu/drm/nouveau/nv04_display.c index 44488e3a257d..2b7d23e8f27f 100644 --- a/drivers/gpu/drm/nouveau/nv04_display.c +++ b/drivers/gpu/drm/nouveau/nv04_display.c @@ -35,69 +35,9 @@ static void nv04_vblank_crtc0_isr(struct drm_device *); static void nv04_vblank_crtc1_isr(struct drm_device *); -static void -nv04_display_store_initial_head_owner(struct drm_device *dev) -{ - struct drm_nouveau_private *dev_priv = dev->dev_private; - - if (dev_priv->chipset != 0x11) { - dev_priv->crtc_owner = NVReadVgaCrtc(dev, 0, NV_CIO_CRE_44); - return; - } - - /* reading CR44 is broken on nv11, so we attempt to infer it */ - if (nvReadMC(dev, NV_PBUS_DEBUG_1) & (1 << 28)) /* heads tied, restore both */ - dev_priv->crtc_owner = 0x4; - else { - uint8_t slaved_on_A, slaved_on_B; - bool tvA = false; - bool tvB = false; - - slaved_on_B = NVReadVgaCrtc(dev, 1, NV_CIO_CRE_PIXEL_INDEX) & - 0x80; - if (slaved_on_B) - tvB = !(NVReadVgaCrtc(dev, 1, NV_CIO_CRE_LCD__INDEX) & - MASK(NV_CIO_CRE_LCD_LCD_SELECT)); - - slaved_on_A = NVReadVgaCrtc(dev, 0, NV_CIO_CRE_PIXEL_INDEX) & - 0x80; - if (slaved_on_A) - tvA = !(NVReadVgaCrtc(dev, 0, NV_CIO_CRE_LCD__INDEX) & - MASK(NV_CIO_CRE_LCD_LCD_SELECT)); - - if (slaved_on_A && !tvA) - dev_priv->crtc_owner = 0x0; - else if (slaved_on_B && !tvB) - dev_priv->crtc_owner = 0x3; - else if (slaved_on_A) - dev_priv->crtc_owner = 0x0; - else if (slaved_on_B) - dev_priv->crtc_owner = 0x3; - else - dev_priv->crtc_owner = 0x0; - } -} - int nv04_display_early_init(struct drm_device *dev) { - /* Make the I2C buses accessible. */ - if (!nv_gf4_disp_arch(dev)) { - uint32_t pmc_enable = nv_rd32(dev, NV03_PMC_ENABLE); - - if (!(pmc_enable & 1)) - nv_wr32(dev, NV03_PMC_ENABLE, pmc_enable | 1); - } - - /* Unlock the VGA CRTCs. */ - NVLockVgaCrtcs(dev, false); - - /* Make sure the CRTCs aren't in slaved mode. */ - if (nv_two_heads(dev)) { - nv04_display_store_initial_head_owner(dev); - NVSetOwner(dev, 0); - } - /* ensure vblank interrupts are off, they can't be enabled until * drm_vblank has been initialised */ @@ -111,12 +51,6 @@ nv04_display_early_init(struct drm_device *dev) void nv04_display_late_takedown(struct drm_device *dev) { - struct drm_nouveau_private *dev_priv = dev->dev_private; - - if (nv_two_heads(dev)) - NVSetOwner(dev, dev_priv->crtc_owner); - - NVLockVgaCrtcs(dev, true); } int @@ -138,21 +72,21 @@ nv04_display_create(struct drm_device *dev) nv04_crtc_create(dev, 1); for (i = 0; i < dcb->entries; i++) { - struct dcb_entry *dcbent = &dcb->entry[i]; + struct dcb_output *dcbent = &dcb->entry[i]; connector = nouveau_connector_create(dev, dcbent->connector); if (IS_ERR(connector)) continue; switch (dcbent->type) { - case OUTPUT_ANALOG: + case DCB_OUTPUT_ANALOG: ret = nv04_dac_create(connector, dcbent); break; - case OUTPUT_LVDS: - case OUTPUT_TMDS: + case DCB_OUTPUT_LVDS: + case DCB_OUTPUT_TMDS: ret = nv04_dfp_create(connector, dcbent); break; - case OUTPUT_TV: + case DCB_OUTPUT_TV: if (dcbent->location == DCB_LOC_ON_CHIP) ret = nv17_tv_create(connector, dcbent); else diff --git a/drivers/gpu/drm/nouveau/nv04_tv.c b/drivers/gpu/drm/nouveau/nv04_tv.c index 3d7dd22879be..5927391373e9 100644 --- a/drivers/gpu/drm/nouveau/nv04_tv.c +++ b/drivers/gpu/drm/nouveau/nv04_tv.c @@ -181,7 +181,7 @@ static const struct drm_encoder_funcs nv04_tv_funcs = { }; int -nv04_tv_create(struct drm_connector *connector, struct dcb_entry *entry) +nv04_tv_create(struct drm_connector *connector, struct dcb_output *entry) { struct nouveau_encoder *nv_encoder; struct drm_encoder *encoder; diff --git a/drivers/gpu/drm/nouveau/nv17_tv.c b/drivers/gpu/drm/nouveau/nv17_tv.c index a66a348d7f23..54ff394e005b 100644 --- a/drivers/gpu/drm/nouveau/nv17_tv.c +++ b/drivers/gpu/drm/nouveau/nv17_tv.c @@ -144,7 +144,7 @@ nv17_tv_detect(struct drm_encoder *encoder, struct drm_connector *connector) struct drm_nouveau_private *dev_priv = dev->dev_private; struct drm_mode_config *conf = &dev->mode_config; struct nv17_tv_encoder *tv_enc = to_tv_enc(encoder); - struct dcb_entry *dcb = tv_enc->base.dcb; + struct dcb_output *dcb = tv_enc->base.dcb; bool reliable = get_tv_detect_quirks(dev, &tv_enc->pin_mask); if (nv04_dac_in_use(encoder)) @@ -411,10 +411,10 @@ static void nv17_tv_prepare(struct drm_encoder *encoder) struct drm_encoder *enc; list_for_each_entry(enc, &dev->mode_config.encoder_list, head) { - struct dcb_entry *dcb = nouveau_encoder(enc)->dcb; + struct dcb_output *dcb = nouveau_encoder(enc)->dcb; - if ((dcb->type == OUTPUT_TMDS || - dcb->type == OUTPUT_LVDS) && + if ((dcb->type == DCB_OUTPUT_TMDS || + dcb->type == DCB_OUTPUT_LVDS) && !enc->crtc && nv04_dfp_get_bound_head(dev, dcb) == head) { nv04_dfp_bind_head(dev, dcb, head ^ 1, @@ -633,7 +633,7 @@ static int nv17_tv_create_resources(struct drm_encoder *encoder, struct drm_device *dev = encoder->dev; struct drm_mode_config *conf = &dev->mode_config; struct nv17_tv_encoder *tv_enc = to_tv_enc(encoder); - struct dcb_entry *dcb = nouveau_encoder(encoder)->dcb; + struct dcb_output *dcb = nouveau_encoder(encoder)->dcb; int num_tv_norms = dcb->tvconf.has_component_output ? NUM_TV_NORMS : NUM_LD_TV_NORMS; int i; @@ -789,7 +789,7 @@ static struct drm_encoder_funcs nv17_tv_funcs = { }; int -nv17_tv_create(struct drm_connector *connector, struct dcb_entry *entry) +nv17_tv_create(struct drm_connector *connector, struct dcb_output *entry) { struct drm_device *dev = connector->dev; struct drm_encoder *encoder; diff --git a/drivers/gpu/drm/nouveau/nv50_dac.c b/drivers/gpu/drm/nouveau/nv50_dac.c index 2c36a6b92c53..dd3b8f2a3960 100644 --- a/drivers/gpu/drm/nouveau/nv50_dac.c +++ b/drivers/gpu/drm/nouveau/nv50_dac.c @@ -224,10 +224,10 @@ nv50_dac_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode, mode_ctl |= NV50_EVO_DAC_MODE_CTRL_CRTC0; /* Lacking a working tv-out, this is not a 100% sure. */ - if (nv_encoder->dcb->type == OUTPUT_ANALOG) + if (nv_encoder->dcb->type == DCB_OUTPUT_ANALOG) mode_ctl |= 0x40; else - if (nv_encoder->dcb->type == OUTPUT_TV) + if (nv_encoder->dcb->type == DCB_OUTPUT_TV) mode_ctl |= 0x100; if (adjusted_mode->flags & DRM_MODE_FLAG_NHSYNC) @@ -286,7 +286,7 @@ static const struct drm_encoder_funcs nv50_dac_encoder_funcs = { }; int -nv50_dac_create(struct drm_connector *connector, struct dcb_entry *entry) +nv50_dac_create(struct drm_connector *connector, struct dcb_output *entry) { struct nouveau_encoder *nv_encoder; struct drm_encoder *encoder; diff --git a/drivers/gpu/drm/nouveau/nv50_display.c b/drivers/gpu/drm/nouveau/nv50_display.c index 66abff11d1bd..e7cd8216d114 100644 --- a/drivers/gpu/drm/nouveau/nv50_display.c +++ b/drivers/gpu/drm/nouveau/nv50_display.c @@ -74,53 +74,9 @@ nv50_display_active_crtcs(struct drm_device *dev) return mask & 3; } -static int -evo_icmd(struct drm_device *dev, int ch, u32 mthd, u32 data) -{ - int ret = 0; - nv_mask(dev, 0x610300 + (ch * 0x08), 0x00000001, 0x00000001); - nv_wr32(dev, 0x610304 + (ch * 0x08), data); - nv_wr32(dev, 0x610300 + (ch * 0x08), 0x80000001 | mthd); - if (!nv_wait(dev, 0x610300 + (ch * 0x08), 0x80000000, 0x00000000)) - ret = -EBUSY; - if (ret || (nouveau_reg_debug & NOUVEAU_REG_DEBUG_EVO)) - NV_INFO(dev, "EvoPIO: %d 0x%04x 0x%08x\n", ch, mthd, data); - nv_mask(dev, 0x610300 + (ch * 0x08), 0x00000001, 0x00000000); - return ret; -} - int nv50_display_early_init(struct drm_device *dev) { - u32 ctrl = nv_rd32(dev, 0x610200); - int i; - - /* check if master evo channel is already active, a good a sign as any - * that the display engine is in a weird state (hibernate/kexec), if - * it is, do our best to reset the display engine... - */ - if ((ctrl & 0x00000003) == 0x00000003) { - NV_INFO(dev, "PDISP: EVO(0) 0x%08x, resetting...\n", ctrl); - - /* deactivate both heads first, PDISP will disappear forever - * (well, until you power cycle) on some boards as soon as - * PMC_ENABLE is hit unless they are.. - */ - for (i = 0; i < 2; i++) { - evo_icmd(dev, 0, 0x0880 + (i * 0x400), 0x05000000); - evo_icmd(dev, 0, 0x089c + (i * 0x400), 0); - evo_icmd(dev, 0, 0x0840 + (i * 0x400), 0); - evo_icmd(dev, 0, 0x0844 + (i * 0x400), 0); - evo_icmd(dev, 0, 0x085c + (i * 0x400), 0); - evo_icmd(dev, 0, 0x0874 + (i * 0x400), 0); - } - evo_icmd(dev, 0, 0x0080, 0); - - /* reset PDISP */ - nv_mask(dev, 0x000200, 0x40000000, 0x00000000); - nv_mask(dev, 0x000200, 0x40000000, 0x40000000); - } - return 0; } @@ -367,7 +323,7 @@ nv50_display_create(struct drm_device *dev) /* We setup the encoders from the BIOS table */ for (i = 0 ; i < dcb->entries; i++) { - struct dcb_entry *entry = &dcb->entry[i]; + struct dcb_output *entry = &dcb->entry[i]; if (entry->location != DCB_LOC_ON_CHIP) { NV_WARN(dev, "Off-chip encoder %d/%d unsupported\n", @@ -380,12 +336,12 @@ nv50_display_create(struct drm_device *dev) continue; switch (entry->type) { - case OUTPUT_TMDS: - case OUTPUT_LVDS: - case OUTPUT_DP: + case DCB_OUTPUT_TMDS: + case DCB_OUTPUT_LVDS: + case DCB_OUTPUT_DP: nv50_sor_create(connector, entry); break; - case OUTPUT_ANALOG: + case DCB_OUTPUT_ANALOG: nv50_dac_create(connector, entry); break; default: @@ -555,7 +511,7 @@ nv50_display_flip_next(struct drm_crtc *crtc, struct drm_framebuffer *fb, } static u16 -nv50_display_script_select(struct drm_device *dev, struct dcb_entry *dcb, +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; @@ -576,7 +532,7 @@ nv50_display_script_select(struct drm_device *dev, struct dcb_entry *dcb, or = ffs(dcb->or) - 1; switch (dcb->type) { - case OUTPUT_LVDS: + case DCB_OUTPUT_LVDS: script = (mc >> 8) & 0xf; if (bios->fp_no_ddc) { if (bios->fp.dual_link) @@ -617,7 +573,7 @@ nv50_display_script_select(struct drm_device *dev, struct dcb_entry *dcb, script = nouveau_uscript_lvds; } break; - case OUTPUT_TMDS: + case DCB_OUTPUT_TMDS: script = (mc >> 8) & 0xf; if (pxclk >= 165000) script |= 0x0100; @@ -629,10 +585,10 @@ nv50_display_script_select(struct drm_device *dev, struct dcb_entry *dcb, script = nouveau_uscript_tmds; } break; - case OUTPUT_DP: + case DCB_OUTPUT_DP: script = (mc >> 8) & 0xf; break; - case OUTPUT_ANALOG: + case DCB_OUTPUT_ANALOG: script = 0xff; break; default: @@ -691,7 +647,7 @@ nv50_display_unk10_handler(struct drm_device *dev) struct drm_nouveau_private *dev_priv = dev->dev_private; struct nv50_display *disp = nv50_display(dev); u32 unk30 = nv_rd32(dev, 0x610030), mc; - int i, crtc, or = 0, type = OUTPUT_ANY; + int i, crtc, or = 0, type = DCB_OUTPUT_ANY; NV_DEBUG_KMS(dev, "0x610030: 0x%08x\n", unk30); disp->irq.dcb = NULL; @@ -711,15 +667,15 @@ nv50_display_unk10_handler(struct drm_device *dev) goto ack; /* Find which encoder was connected to the CRTC */ - for (i = 0; type == OUTPUT_ANY && i < 3; i++) { + 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); if (!(mc & (1 << crtc))) continue; switch ((mc & 0x00000f00) >> 8) { - case 0: type = OUTPUT_ANALOG; break; - case 1: type = OUTPUT_TV; break; + 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); goto ack; @@ -728,7 +684,7 @@ nv50_display_unk10_handler(struct drm_device *dev) or = i; } - for (i = 0; type == OUTPUT_ANY && i < nv50_sor_nr(dev); i++) { + 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) @@ -741,12 +697,12 @@ nv50_display_unk10_handler(struct drm_device *dev) continue; switch ((mc & 0x00000f00) >> 8) { - case 0: type = OUTPUT_LVDS; break; - case 1: type = OUTPUT_TMDS; break; - case 2: type = OUTPUT_TMDS; break; - case 5: type = OUTPUT_TMDS; break; - case 8: type = OUTPUT_DP; break; - case 9: type = OUTPUT_DP; break; + case 0: type = DCB_OUTPUT_LVDS; break; + case 1: type = DCB_OUTPUT_TMDS; break; + case 2: type = DCB_OUTPUT_TMDS; break; + case 5: type = DCB_OUTPUT_TMDS; break; + 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); goto ack; @@ -756,12 +712,12 @@ nv50_display_unk10_handler(struct drm_device *dev) } /* There was no encoder to disable */ - if (type == OUTPUT_ANY) + if (type == DCB_OUTPUT_ANY) goto ack; /* Disable the encoder */ for (i = 0; i < dev_priv->vbios.dcb.entries; i++) { - struct dcb_entry *dcb = &dev_priv->vbios.dcb.entry[i]; + struct dcb_output *dcb = &dev_priv->vbios.dcb.entry[i]; if (dcb->type == type && (dcb->or & (1 << or))) { nouveau_bios_run_display_table(dev, 0, -1, dcb, -1); @@ -782,8 +738,8 @@ nv50_display_unk20_handler(struct drm_device *dev) struct drm_nouveau_private *dev_priv = dev->dev_private; struct nv50_display *disp = nv50_display(dev); u32 unk30 = nv_rd32(dev, 0x610030), tmp, pclk, script, mc = 0; - struct dcb_entry *dcb; - int i, crtc, or = 0, type = OUTPUT_ANY; + struct dcb_output *dcb; + int i, crtc, or = 0, type = DCB_OUTPUT_ANY; NV_DEBUG_KMS(dev, "0x610030: 0x%08x\n", unk30); dcb = disp->irq.dcb; @@ -812,15 +768,15 @@ nv50_display_unk20_handler(struct drm_device *dev) pclk = nv_rd32(dev, NV50_PDISPLAY_CRTC_P(crtc, CLOCK)) & 0x003fffff; /* Find which encoder is connected to the CRTC */ - for (i = 0; type == OUTPUT_ANY && i < 3; i++) { + 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); if (!(mc & (1 << crtc))) continue; switch ((mc & 0x00000f00) >> 8) { - case 0: type = OUTPUT_ANALOG; break; - case 1: type = OUTPUT_TV; break; + 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); goto ack; @@ -829,7 +785,7 @@ nv50_display_unk20_handler(struct drm_device *dev) or = i; } - for (i = 0; type == OUTPUT_ANY && i < nv50_sor_nr(dev); i++) { + 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) @@ -842,12 +798,12 @@ nv50_display_unk20_handler(struct drm_device *dev) continue; switch ((mc & 0x00000f00) >> 8) { - case 0: type = OUTPUT_LVDS; break; - case 1: type = OUTPUT_TMDS; break; - case 2: type = OUTPUT_TMDS; break; - case 5: type = OUTPUT_TMDS; break; - case 8: type = OUTPUT_DP; break; - case 9: type = OUTPUT_DP; break; + case 0: type = DCB_OUTPUT_LVDS; break; + case 1: type = DCB_OUTPUT_TMDS; break; + case 2: type = DCB_OUTPUT_TMDS; break; + case 5: type = DCB_OUTPUT_TMDS; break; + 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); goto ack; @@ -856,7 +812,7 @@ nv50_display_unk20_handler(struct drm_device *dev) or = i; } - if (type == OUTPUT_ANY) + if (type == DCB_OUTPUT_ANY) goto ack; /* Enable the encoder */ @@ -874,7 +830,7 @@ nv50_display_unk20_handler(struct drm_device *dev) script = nv50_display_script_select(dev, dcb, mc, pclk); nouveau_bios_run_display_table(dev, script, pclk, dcb, -1); - if (type == OUTPUT_DP) { + if (type == DCB_OUTPUT_DP) { int link = !(dcb->dpconf.sor.link & 1); if ((mc & 0x000f0000) == 0x00020000) nv50_sor_dp_calc_tu(dev, or, link, pclk, 18); @@ -882,7 +838,7 @@ nv50_display_unk20_handler(struct drm_device *dev) nv50_sor_dp_calc_tu(dev, or, link, pclk, 24); } - if (dcb->type != OUTPUT_ANALOG) { + if (dcb->type != DCB_OUTPUT_ANALOG) { tmp = nv_rd32(dev, NV50_PDISPLAY_SOR_CLK_CTRL2(or)); tmp &= ~0x00000f0f; if (script & 0x0100) @@ -910,19 +866,19 @@ ack: * programmed for DisplayPort. */ static void -nv50_display_unk40_dp_set_tmds(struct drm_device *dev, struct dcb_entry *dcb) +nv50_display_unk40_dp_set_tmds(struct drm_device *dev, struct dcb_output *dcb) { int or = ffs(dcb->or) - 1, link = !(dcb->dpconf.sor.link & 1); struct drm_encoder *encoder; u32 tmp; - if (dcb->type != OUTPUT_TMDS) + if (dcb->type != DCB_OUTPUT_TMDS) return; list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); - if (nv_encoder->dcb->type == OUTPUT_DP && + 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 &= ~NV50_SOR_DP_CTRL_ENABLED; @@ -936,7 +892,7 @@ static void nv50_display_unk40_handler(struct drm_device *dev) { struct nv50_display *disp = nv50_display(dev); - struct dcb_entry *dcb = disp->irq.dcb; + struct dcb_output *dcb = disp->irq.dcb; u16 script = disp->irq.script; u32 unk30 = nv_rd32(dev, 0x610030), pclk = disp->irq.pclk; diff --git a/drivers/gpu/drm/nouveau/nv50_display.h b/drivers/gpu/drm/nouveau/nv50_display.h index e9db9b97f041..25c301391724 100644 --- a/drivers/gpu/drm/nouveau/nv50_display.h +++ b/drivers/gpu/drm/nouveau/nv50_display.h @@ -53,7 +53,7 @@ struct nv50_display { struct tasklet_struct tasklet; struct { - struct dcb_entry *dcb; + struct dcb_output *dcb; u16 script; u32 pclk; } irq; diff --git a/drivers/gpu/drm/nouveau/nv50_sor.c b/drivers/gpu/drm/nouveau/nv50_sor.c index 93240bde891b..2e6d83b37a0f 100644 --- a/drivers/gpu/drm/nouveau/nv50_sor.c +++ b/drivers/gpu/drm/nouveau/nv50_sor.c @@ -37,7 +37,7 @@ #include "nv50_display.h" static u32 -nv50_sor_dp_lane_map(struct drm_device *dev, struct dcb_entry *dcb, u8 lane) +nv50_sor_dp_lane_map(struct drm_device *dev, struct dcb_output *dcb, u8 lane) { struct drm_nouveau_private *dev_priv = dev->dev_private; static const u8 nvaf[] = { 24, 16, 8, 0 }; /* thanks, apple.. */ @@ -48,14 +48,14 @@ nv50_sor_dp_lane_map(struct drm_device *dev, struct dcb_entry *dcb, u8 lane) } static void -nv50_sor_dp_train_set(struct drm_device *dev, struct dcb_entry *dcb, u8 pattern) +nv50_sor_dp_train_set(struct drm_device *dev, struct dcb_output *dcb, u8 pattern) { u32 or = ffs(dcb->or) - 1, link = !(dcb->sorconf.link & 1); nv_mask(dev, NV50_SOR_DP_CTRL(or, link), 0x0f000000, pattern << 24); } static void -nv50_sor_dp_train_adj(struct drm_device *dev, struct dcb_entry *dcb, +nv50_sor_dp_train_adj(struct drm_device *dev, struct dcb_output *dcb, u8 lane, u8 swing, u8 preem) { u32 or = ffs(dcb->or) - 1, link = !(dcb->sorconf.link & 1); @@ -82,7 +82,7 @@ nv50_sor_dp_train_adj(struct drm_device *dev, struct dcb_entry *dcb, } static void -nv50_sor_dp_link_set(struct drm_device *dev, struct dcb_entry *dcb, int crtc, +nv50_sor_dp_link_set(struct drm_device *dev, struct dcb_output *dcb, int crtc, int link_nr, u32 link_bw, bool enhframe) { u32 or = ffs(dcb->or) - 1, link = !(dcb->sorconf.link & 1); @@ -269,9 +269,9 @@ nv50_sor_dpms(struct drm_encoder *encoder, int mode) struct nouveau_encoder *nvenc = nouveau_encoder(enc); if (nvenc == nv_encoder || - (nvenc->dcb->type != OUTPUT_TMDS && - nvenc->dcb->type != OUTPUT_LVDS && - nvenc->dcb->type != OUTPUT_DP) || + (nvenc->dcb->type != DCB_OUTPUT_TMDS && + nvenc->dcb->type != DCB_OUTPUT_LVDS && + nvenc->dcb->type != DCB_OUTPUT_DP) || nvenc->dcb->or != nv_encoder->dcb->or) continue; @@ -303,7 +303,7 @@ nv50_sor_dpms(struct drm_encoder *encoder, int mode) nv_rd32(dev, NV50_PDISPLAY_SOR_DPMS_STATE(or))); } - if (nv_encoder->dcb->type == OUTPUT_DP) { + if (nv_encoder->dcb->type == DCB_OUTPUT_DP) { struct dp_train_func func = { .link_set = nv50_sor_dp_link_set, .train_set = nv50_sor_dp_train_set, @@ -354,7 +354,7 @@ nv50_sor_prepare(struct drm_encoder *encoder) { struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); nv50_sor_disconnect(encoder); - if (nv_encoder->dcb->type == OUTPUT_DP) { + if (nv_encoder->dcb->type == DCB_OUTPUT_DP) { /* avoid race between link training and supervisor intr */ nv50_display_sync(encoder->dev); } @@ -382,7 +382,7 @@ nv50_sor_mode_set(struct drm_encoder *encoder, struct drm_display_mode *umode, nv_encoder->crtc = encoder->crtc; switch (nv_encoder->dcb->type) { - case OUTPUT_TMDS: + case DCB_OUTPUT_TMDS: if (nv_encoder->dcb->sorconf.link & 1) { if (mode->clock < 165000) mode_ctl = 0x0100; @@ -393,7 +393,7 @@ nv50_sor_mode_set(struct drm_encoder *encoder, struct drm_display_mode *umode, nouveau_hdmi_mode_set(encoder, mode); break; - case OUTPUT_DP: + case DCB_OUTPUT_DP: nv_connector = nouveau_encoder_connector_get(nv_encoder); if (nv_connector && nv_connector->base.display_info.bpc == 6) { nv_encoder->dp.datarate = mode->clock * 18 / 8; @@ -474,7 +474,7 @@ static const struct drm_encoder_funcs nv50_sor_encoder_funcs = { }; int -nv50_sor_create(struct drm_connector *connector, struct dcb_entry *entry) +nv50_sor_create(struct drm_connector *connector, struct dcb_output *entry) { struct nouveau_encoder *nv_encoder = NULL; struct drm_device *dev = connector->dev; @@ -484,11 +484,11 @@ nv50_sor_create(struct drm_connector *connector, struct dcb_entry *entry) NV_DEBUG_KMS(dev, "\n"); switch (entry->type) { - case OUTPUT_TMDS: - case OUTPUT_DP: + case DCB_OUTPUT_TMDS: + case DCB_OUTPUT_DP: type = DRM_MODE_ENCODER_TMDS; break; - case OUTPUT_LVDS: + case DCB_OUTPUT_LVDS: type = DRM_MODE_ENCODER_LVDS; break; default: diff --git a/drivers/gpu/drm/nouveau/nvd0_display.c b/drivers/gpu/drm/nouveau/nvd0_display.c index 8a2fc89b7763..d26dd02f3d13 100644 --- a/drivers/gpu/drm/nouveau/nvd0_display.c +++ b/drivers/gpu/drm/nouveau/nvd0_display.c @@ -1063,7 +1063,7 @@ static const struct drm_encoder_funcs nvd0_dac_func = { }; static int -nvd0_dac_create(struct drm_connector *connector, struct dcb_entry *dcbe) +nvd0_dac_create(struct drm_connector *connector, struct dcb_output *dcbe) { struct drm_device *dev = connector->dev; struct nouveau_encoder *nv_encoder; @@ -1191,14 +1191,14 @@ nvd0_hdmi_disconnect(struct drm_encoder *encoder) * SOR *****************************************************************************/ static inline u32 -nvd0_sor_dp_lane_map(struct drm_device *dev, struct dcb_entry *dcb, u8 lane) +nvd0_sor_dp_lane_map(struct drm_device *dev, struct dcb_output *dcb, u8 lane) { static const u8 nvd0[] = { 16, 8, 0, 24 }; return nvd0[lane]; } static void -nvd0_sor_dp_train_set(struct drm_device *dev, struct dcb_entry *dcb, u8 pattern) +nvd0_sor_dp_train_set(struct drm_device *dev, struct dcb_output *dcb, u8 pattern) { const u32 or = ffs(dcb->or) - 1, link = !(dcb->sorconf.link & 1); const u32 loff = (or * 0x800) + (link * 0x80); @@ -1206,7 +1206,7 @@ nvd0_sor_dp_train_set(struct drm_device *dev, struct dcb_entry *dcb, u8 pattern) } static void -nvd0_sor_dp_train_adj(struct drm_device *dev, struct dcb_entry *dcb, +nvd0_sor_dp_train_adj(struct drm_device *dev, struct dcb_output *dcb, u8 lane, u8 swing, u8 preem) { const u32 or = ffs(dcb->or) - 1, link = !(dcb->sorconf.link & 1); @@ -1247,7 +1247,7 @@ nvd0_sor_dp_train_adj(struct drm_device *dev, struct dcb_entry *dcb, } static void -nvd0_sor_dp_link_set(struct drm_device *dev, struct dcb_entry *dcb, int crtc, +nvd0_sor_dp_link_set(struct drm_device *dev, struct dcb_output *dcb, int crtc, int link_nr, u32 link_bw, bool enhframe) { const u32 or = ffs(dcb->or) - 1, link = !(dcb->sorconf.link & 1); @@ -1290,7 +1290,7 @@ nvd0_sor_dp_link_set(struct drm_device *dev, struct dcb_entry *dcb, int crtc, } static void -nvd0_sor_dp_link_get(struct drm_device *dev, struct dcb_entry *dcb, +nvd0_sor_dp_link_get(struct drm_device *dev, struct dcb_output *dcb, u32 *link_nr, u32 *link_bw) { const u32 or = ffs(dcb->or) - 1, link = !(dcb->sorconf.link & 1); @@ -1308,7 +1308,7 @@ nvd0_sor_dp_link_get(struct drm_device *dev, struct dcb_entry *dcb, } static void -nvd0_sor_dp_calc_tu(struct drm_device *dev, struct dcb_entry *dcb, +nvd0_sor_dp_calc_tu(struct drm_device *dev, struct dcb_output *dcb, u32 crtc, u32 datarate) { const u32 symbol = 100000; @@ -1366,7 +1366,7 @@ nvd0_sor_dpms(struct drm_encoder *encoder, int mode) nv_wait(dev, 0x61c004 + (or * 0x0800), 0x80000000, 0x00000000); nv_wait(dev, 0x61c030 + (or * 0x0800), 0x10000000, 0x00000000); - if (nv_encoder->dcb->type == OUTPUT_DP) { + if (nv_encoder->dcb->type == DCB_OUTPUT_DP) { struct dp_train_func func = { .link_set = nvd0_sor_dp_link_set, .train_set = nvd0_sor_dp_train_set, @@ -1427,7 +1427,7 @@ static void nvd0_sor_prepare(struct drm_encoder *encoder) { nvd0_sor_disconnect(encoder); - if (nouveau_encoder(encoder)->dcb->type == OUTPUT_DP) + if (nouveau_encoder(encoder)->dcb->type == DCB_OUTPUT_DP) evo_sync(encoder->dev, EVO_MASTER); } @@ -1462,7 +1462,7 @@ nvd0_sor_mode_set(struct drm_encoder *encoder, struct drm_display_mode *umode, nv_connector = nouveau_encoder_connector_get(nv_encoder); switch (nv_encoder->dcb->type) { - case OUTPUT_TMDS: + case DCB_OUTPUT_TMDS: if (nv_encoder->dcb->sorconf.link & 1) { if (mode->clock < 165000) mode_ctrl |= 0x00000100; @@ -1478,7 +1478,7 @@ nvd0_sor_mode_set(struct drm_encoder *encoder, struct drm_display_mode *umode, nvd0_hdmi_mode_set(encoder, mode); break; - case OUTPUT_LVDS: + case DCB_OUTPUT_LVDS: or_config = (mode_ctrl & 0x00000f00) >> 8; if (bios->fp_no_ddc) { if (bios->fp.dual_link) @@ -1507,7 +1507,7 @@ nvd0_sor_mode_set(struct drm_encoder *encoder, struct drm_display_mode *umode, } break; - case OUTPUT_DP: + case DCB_OUTPUT_DP: if (nv_connector->base.display_info.bpc == 6) { nv_encoder->dp.datarate = mode->clock * 18 / 8; syncs |= 0x00000002 << 6; @@ -1530,7 +1530,7 @@ nvd0_sor_mode_set(struct drm_encoder *encoder, struct drm_display_mode *umode, nvd0_sor_dpms(encoder, DRM_MODE_DPMS_ON); - if (nv_encoder->dcb->type == OUTPUT_DP) { + if (nv_encoder->dcb->type == DCB_OUTPUT_DP) { nvd0_sor_dp_calc_tu(dev, nv_encoder->dcb, nv_crtc->index, nv_encoder->dp.datarate); } @@ -1571,7 +1571,7 @@ static const struct drm_encoder_funcs nvd0_sor_func = { }; static int -nvd0_sor_create(struct drm_connector *connector, struct dcb_entry *dcbe) +nvd0_sor_create(struct drm_connector *connector, struct dcb_output *dcbe) { struct drm_device *dev = connector->dev; struct nouveau_encoder *nv_encoder; @@ -1597,23 +1597,23 @@ nvd0_sor_create(struct drm_connector *connector, struct dcb_entry *dcbe) /****************************************************************************** * IRQ *****************************************************************************/ -static struct dcb_entry * +static struct dcb_output * lookup_dcb(struct drm_device *dev, int id, u32 mc) { struct drm_nouveau_private *dev_priv = dev->dev_private; int type, or, i, link = -1; if (id < 4) { - type = OUTPUT_ANALOG; + type = DCB_OUTPUT_ANALOG; or = id; } else { switch (mc & 0x00000f00) { - case 0x00000000: link = 0; type = OUTPUT_LVDS; break; - case 0x00000100: link = 0; type = OUTPUT_TMDS; break; - case 0x00000200: link = 1; type = OUTPUT_TMDS; break; - case 0x00000500: link = 0; type = OUTPUT_TMDS; break; - case 0x00000800: link = 0; type = OUTPUT_DP; break; - case 0x00000900: link = 1; type = OUTPUT_DP; break; + case 0x00000000: link = 0; type = DCB_OUTPUT_LVDS; break; + case 0x00000100: link = 0; type = DCB_OUTPUT_TMDS; break; + case 0x00000200: link = 1; type = DCB_OUTPUT_TMDS; break; + case 0x00000500: link = 0; type = DCB_OUTPUT_TMDS; break; + 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); return NULL; @@ -1623,7 +1623,7 @@ lookup_dcb(struct drm_device *dev, int id, u32 mc) } for (i = 0; i < dev_priv->vbios.dcb.entries; i++) { - struct dcb_entry *dcb = &dev_priv->vbios.dcb.entry[i]; + struct dcb_output *dcb = &dev_priv->vbios.dcb.entry[i]; if (dcb->type == type && (dcb->or & (1 << or)) && (link < 0 || link == !(dcb->sorconf.link & 1))) return dcb; @@ -1636,7 +1636,7 @@ lookup_dcb(struct drm_device *dev, int id, u32 mc) static void nvd0_display_unk1_handler(struct drm_device *dev, u32 crtc, u32 mask) { - struct dcb_entry *dcb; + struct dcb_output *dcb; int i; for (i = 0; mask && i < 8; i++) { @@ -1659,7 +1659,7 @@ nvd0_display_unk1_handler(struct drm_device *dev, u32 crtc, u32 mask) static void nvd0_display_unk2_handler(struct drm_device *dev, u32 crtc, u32 mask) { - struct dcb_entry *dcb; + struct dcb_output *dcb; u32 or, tmp, pclk; int i; @@ -1697,12 +1697,12 @@ nvd0_display_unk2_handler(struct drm_device *dev, u32 crtc, u32 mask) nv_wr32(dev, 0x612200 + (crtc * 0x800), 0x00000000); switch (dcb->type) { - case OUTPUT_ANALOG: + case DCB_OUTPUT_ANALOG: nv_wr32(dev, 0x612280 + (or * 0x800), 0x00000000); break; - case OUTPUT_TMDS: - case OUTPUT_LVDS: - case OUTPUT_DP: + case DCB_OUTPUT_TMDS: + case DCB_OUTPUT_LVDS: + case DCB_OUTPUT_DP: if (cfg & 0x00000100) tmp = 0x00000101; else @@ -1725,7 +1725,7 @@ nvd0_display_unk2_handler(struct drm_device *dev, u32 crtc, u32 mask) static void nvd0_display_unk4_handler(struct drm_device *dev, u32 crtc, u32 mask) { - struct dcb_entry *dcb; + struct dcb_output *dcb; int pclk, i; pclk = nv_rd32(dev, 0x660450 + (crtc * 0x300)) / 1000; @@ -1972,7 +1972,7 @@ nvd0_display_create(struct drm_device *dev) struct drm_connector *connector, *tmp; struct pci_dev *pdev = dev->pdev; struct nvd0_display *disp; - struct dcb_entry *dcbe; + struct dcb_output *dcbe; int crtcs, ret, i; disp = kzalloc(sizeof(*disp), GFP_KERNEL); @@ -2001,12 +2001,12 @@ nvd0_display_create(struct drm_device *dev) } switch (dcbe->type) { - case OUTPUT_TMDS: - case OUTPUT_LVDS: - case OUTPUT_DP: + case DCB_OUTPUT_TMDS: + case DCB_OUTPUT_LVDS: + case DCB_OUTPUT_DP: nvd0_sor_create(connector, dcbe); break; - case OUTPUT_ANALOG: + case DCB_OUTPUT_ANALOG: nvd0_dac_create(connector, dcbe); break; default: -- 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/nouveau_dp.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 From 5b8a43aeb9cbf6b965f67f6c850382788076325a Mon Sep 17 00:00:00 2001 From: Marcin Slusarz Date: Sun, 19 Aug 2012 23:00:00 +0200 Subject: drm/nouveau: quiet some static-related sparse noise Signed-off-by: Marcin Slusarz Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/core/core/gpuobj.c | 2 +- drivers/gpu/drm/nouveau/core/core/object.c | 8 ++++---- drivers/gpu/drm/nouveau/core/core/option.c | 2 +- drivers/gpu/drm/nouveau/core/engine/copy/fuc/nva3.fuc.h | 4 ++-- drivers/gpu/drm/nouveau/core/engine/copy/fuc/nvc0.fuc.h | 4 ++-- drivers/gpu/drm/nouveau/core/engine/crypt/fuc/nv98.fuc.h | 4 ++-- drivers/gpu/drm/nouveau/core/engine/disp/vga.c | 1 + drivers/gpu/drm/nouveau/core/engine/fifo/base.c | 2 +- drivers/gpu/drm/nouveau/core/engine/fifo/nv84.c | 2 +- drivers/gpu/drm/nouveau/core/engine/graph/fuc/gpcnvc0.fuc.h | 4 ++-- drivers/gpu/drm/nouveau/core/engine/graph/fuc/hubnvc0.fuc.h | 4 ++-- drivers/gpu/drm/nouveau/core/engine/graph/nv40.c | 2 +- drivers/gpu/drm/nouveau/core/engine/graph/nv50.c | 2 +- drivers/gpu/drm/nouveau/core/engine/mpeg/nv31.c | 4 ++-- drivers/gpu/drm/nouveau/core/subdev/bios/conn.c | 1 + drivers/gpu/drm/nouveau/core/subdev/mxm/base.c | 2 +- drivers/gpu/drm/nouveau/core/subdev/vm/nv50.c | 10 +++++----- drivers/gpu/drm/nouveau/core/subdev/vm/nvc0.c | 10 +++++----- drivers/gpu/drm/nouveau/nouveau_chan.c | 2 +- drivers/gpu/drm/nouveau/nouveau_dp.c | 2 +- drivers/gpu/drm/nouveau/nouveau_drm.c | 12 ++++++------ drivers/gpu/drm/nouveau/nouveau_irq.c | 1 + drivers/gpu/drm/nouveau/nouveau_mem.c | 6 +++--- drivers/gpu/drm/nouveau/nouveau_ttm.c | 6 +++--- drivers/gpu/drm/nouveau/nouveau_vga.c | 1 + 25 files changed, 51 insertions(+), 47 deletions(-) (limited to 'drivers/gpu/drm/nouveau/nouveau_dp.c') diff --git a/drivers/gpu/drm/nouveau/core/core/gpuobj.c b/drivers/gpu/drm/nouveau/core/core/gpuobj.c index 715fd318f234..1f34549aff18 100644 --- a/drivers/gpu/drm/nouveau/core/core/gpuobj.c +++ b/drivers/gpu/drm/nouveau/core/core/gpuobj.c @@ -139,7 +139,7 @@ struct nouveau_gpuobj_class { u32 flags; }; -int +static int _nouveau_gpuobj_ctor(struct nouveau_object *parent, struct nouveau_object *engine, struct nouveau_oclass *oclass, void *data, u32 size, diff --git a/drivers/gpu/drm/nouveau/core/core/object.c b/drivers/gpu/drm/nouveau/core/core/object.c index f37598e3f5aa..0daab62ea14c 100644 --- a/drivers/gpu/drm/nouveau/core/core/object.c +++ b/drivers/gpu/drm/nouveau/core/core/object.c @@ -61,7 +61,7 @@ nouveau_object_create_(struct nouveau_object *parent, return 0; } -int +static int _nouveau_object_ctor(struct nouveau_object *parent, struct nouveau_object *engine, struct nouveau_oclass *oclass, void *data, u32 size, @@ -91,7 +91,7 @@ nouveau_object_destroy(struct nouveau_object *object) kfree(object); } -void +static void _nouveau_object_dtor(struct nouveau_object *object) { nouveau_object_destroy(object); @@ -103,7 +103,7 @@ nouveau_object_init(struct nouveau_object *object) return 0; } -int +static int _nouveau_object_init(struct nouveau_object *object) { return nouveau_object_init(object); @@ -115,7 +115,7 @@ nouveau_object_fini(struct nouveau_object *object, bool suspend) return 0; } -int +static int _nouveau_object_fini(struct nouveau_object *object, bool suspend) { return nouveau_object_fini(object, suspend); diff --git a/drivers/gpu/drm/nouveau/core/core/option.c b/drivers/gpu/drm/nouveau/core/core/option.c index 1b53ebb57af3..62a432ea39e5 100644 --- a/drivers/gpu/drm/nouveau/core/core/option.c +++ b/drivers/gpu/drm/nouveau/core/core/option.c @@ -22,7 +22,7 @@ * Authors: Ben Skeggs */ -#include +#include #include /* compares unterminated string 'str' with zero-terminated string 'cmp' */ diff --git a/drivers/gpu/drm/nouveau/core/engine/copy/fuc/nva3.fuc.h b/drivers/gpu/drm/nouveau/core/engine/copy/fuc/nva3.fuc.h index 37d6de3c9d61..c92520f3ed46 100644 --- a/drivers/gpu/drm/nouveau/core/engine/copy/fuc/nva3.fuc.h +++ b/drivers/gpu/drm/nouveau/core/engine/copy/fuc/nva3.fuc.h @@ -1,4 +1,4 @@ -u32 nva3_pcopy_data[] = { +static u32 nva3_pcopy_data[] = { /* 0x0000: ctx_object */ 0x00000000, /* 0x0004: ctx_dma */ @@ -183,7 +183,7 @@ u32 nva3_pcopy_data[] = { 0x00000800, }; -u32 nva3_pcopy_code[] = { +static u32 nva3_pcopy_code[] = { /* 0x0000: main */ 0x04fe04bd, 0x3517f000, diff --git a/drivers/gpu/drm/nouveau/core/engine/copy/fuc/nvc0.fuc.h b/drivers/gpu/drm/nouveau/core/engine/copy/fuc/nvc0.fuc.h index cd879f31bb38..0d98c6c0958d 100644 --- a/drivers/gpu/drm/nouveau/core/engine/copy/fuc/nvc0.fuc.h +++ b/drivers/gpu/drm/nouveau/core/engine/copy/fuc/nvc0.fuc.h @@ -1,4 +1,4 @@ -u32 nvc0_pcopy_data[] = { +static u32 nvc0_pcopy_data[] = { /* 0x0000: ctx_object */ 0x00000000, /* 0x0004: ctx_query_address_high */ @@ -171,7 +171,7 @@ u32 nvc0_pcopy_data[] = { 0x00000800, }; -u32 nvc0_pcopy_code[] = { +static u32 nvc0_pcopy_code[] = { /* 0x0000: main */ 0x04fe04bd, 0x3517f000, diff --git a/drivers/gpu/drm/nouveau/core/engine/crypt/fuc/nv98.fuc.h b/drivers/gpu/drm/nouveau/core/engine/crypt/fuc/nv98.fuc.h index 38676c74e6e0..09962e4210e9 100644 --- a/drivers/gpu/drm/nouveau/core/engine/crypt/fuc/nv98.fuc.h +++ b/drivers/gpu/drm/nouveau/core/engine/crypt/fuc/nv98.fuc.h @@ -1,4 +1,4 @@ -uint32_t nv98_pcrypt_data[] = { +static uint32_t nv98_pcrypt_data[] = { /* 0x0000: ctx_dma */ /* 0x0000: ctx_dma_query */ 0x00000000, @@ -150,7 +150,7 @@ uint32_t nv98_pcrypt_data[] = { 0x00000000, }; -uint32_t nv98_pcrypt_code[] = { +static uint32_t nv98_pcrypt_code[] = { 0x17f004bd, 0x0010fe35, 0xf10004fe, diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/vga.c b/drivers/gpu/drm/nouveau/core/engine/disp/vga.c index cec2110cc53e..5a1c68474597 100644 --- a/drivers/gpu/drm/nouveau/core/engine/disp/vga.c +++ b/drivers/gpu/drm/nouveau/core/engine/disp/vga.c @@ -24,6 +24,7 @@ #include #include +#include u8 nv_rdport(void *obj, int head, u16 port) diff --git a/drivers/gpu/drm/nouveau/core/engine/fifo/base.c b/drivers/gpu/drm/nouveau/core/engine/fifo/base.c index 2a7c13d55aca..bbb43c67c2ae 100644 --- a/drivers/gpu/drm/nouveau/core/engine/fifo/base.c +++ b/drivers/gpu/drm/nouveau/core/engine/fifo/base.c @@ -132,7 +132,7 @@ _nouveau_fifo_channel_wr32(struct nouveau_object *object, u32 addr, u32 data) iowrite32_native(data, chan->user + addr); } -int +static int nouveau_fifo_chid(struct nouveau_fifo *priv, struct nouveau_object *object) { int engidx = nv_hclass(priv) & 0xff; diff --git a/drivers/gpu/drm/nouveau/core/engine/fifo/nv84.c b/drivers/gpu/drm/nouveau/core/engine/fifo/nv84.c index 55620fbd5c21..b4fd26d8f166 100644 --- a/drivers/gpu/drm/nouveau/core/engine/fifo/nv84.c +++ b/drivers/gpu/drm/nouveau/core/engine/fifo/nv84.c @@ -319,7 +319,7 @@ nv84_fifo_sclass[] = { * FIFO context - basically just the instmem reserved for the channel ******************************************************************************/ -int +static int nv84_fifo_context_ctor(struct nouveau_object *parent, struct nouveau_object *engine, struct nouveau_oclass *oclass, void *data, u32 size, diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/fuc/gpcnvc0.fuc.h b/drivers/gpu/drm/nouveau/core/engine/graph/fuc/gpcnvc0.fuc.h index a988b8ad00ac..826a7b321937 100644 --- a/drivers/gpu/drm/nouveau/core/engine/graph/fuc/gpcnvc0.fuc.h +++ b/drivers/gpu/drm/nouveau/core/engine/graph/fuc/gpcnvc0.fuc.h @@ -1,4 +1,4 @@ -uint32_t nvc0_grgpc_data[] = { +static uint32_t nvc0_grgpc_data[] = { 0x00000000, 0x00000000, 0x00000000, @@ -150,7 +150,7 @@ uint32_t nvc0_grgpc_data[] = { 0x08000750, }; -uint32_t nvc0_grgpc_code[] = { +static uint32_t nvc0_grgpc_code[] = { 0x03060ef5, 0x9800d898, 0x86f001d9, diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/fuc/hubnvc0.fuc.h b/drivers/gpu/drm/nouveau/core/engine/graph/fuc/hubnvc0.fuc.h index c5ed307abeb9..db0c0ee5496d 100644 --- a/drivers/gpu/drm/nouveau/core/engine/graph/fuc/hubnvc0.fuc.h +++ b/drivers/gpu/drm/nouveau/core/engine/graph/fuc/hubnvc0.fuc.h @@ -1,4 +1,4 @@ -uint32_t nvc0_grhub_data[] = { +static uint32_t nvc0_grhub_data[] = { 0x00000000, 0x00000000, 0x00000000, @@ -194,7 +194,7 @@ uint32_t nvc0_grhub_data[] = { 0x00000000, }; -uint32_t nvc0_grhub_code[] = { +static uint32_t nvc0_grhub_code[] = { 0x03090ef5, 0x9800d898, 0x86f001d9, diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/nv40.c b/drivers/gpu/drm/nouveau/core/engine/graph/nv40.c index 5690fe37d660..8d0021049ec0 100644 --- a/drivers/gpu/drm/nouveau/core/engine/graph/nv40.c +++ b/drivers/gpu/drm/nouveau/core/engine/graph/nv40.c @@ -75,7 +75,7 @@ nv40_graph_object_ctor(struct nouveau_object *parent, return 0; } -struct nouveau_ofuncs +static struct nouveau_ofuncs nv40_graph_ofuncs = { .ctor = nv40_graph_object_ctor, .dtor = _nouveau_gpuobj_dtor, diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/nv50.c b/drivers/gpu/drm/nouveau/core/engine/graph/nv50.c index 7d30d0287ab2..ab3b9dcaf478 100644 --- a/drivers/gpu/drm/nouveau/core/engine/graph/nv50.c +++ b/drivers/gpu/drm/nouveau/core/engine/graph/nv50.c @@ -73,7 +73,7 @@ nv50_graph_object_ctor(struct nouveau_object *parent, return 0; } -struct nouveau_ofuncs +static struct nouveau_ofuncs nv50_graph_ofuncs = { .ctor = nv50_graph_object_ctor, .dtor = _nouveau_gpuobj_dtor, diff --git a/drivers/gpu/drm/nouveau/core/engine/mpeg/nv31.c b/drivers/gpu/drm/nouveau/core/engine/mpeg/nv31.c index 9adcefc275fb..1f394a2629e7 100644 --- a/drivers/gpu/drm/nouveau/core/engine/mpeg/nv31.c +++ b/drivers/gpu/drm/nouveau/core/engine/mpeg/nv31.c @@ -109,7 +109,7 @@ nv31_mpeg_mthd_dma(struct nouveau_object *object, u32 mthd, void *arg, u32 len) return 0; } -struct nouveau_ofuncs +static struct nouveau_ofuncs nv31_mpeg_ofuncs = { .ctor = nv31_mpeg_object_ctor, .dtor = _nouveau_gpuobj_dtor, @@ -119,7 +119,7 @@ nv31_mpeg_ofuncs = { .wr32 = _nouveau_gpuobj_wr32, }; -struct nouveau_omthds +static struct nouveau_omthds nv31_mpeg_omthds[] = { { 0x0190, nv31_mpeg_mthd_dma }, { 0x01a0, nv31_mpeg_mthd_dma }, diff --git a/drivers/gpu/drm/nouveau/core/subdev/bios/conn.c b/drivers/gpu/drm/nouveau/core/subdev/bios/conn.c index ac4026cd315f..5ac010efd959 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/bios/conn.c +++ b/drivers/gpu/drm/nouveau/core/subdev/bios/conn.c @@ -26,6 +26,7 @@ #include #include +#include u16 dcb_conntab(struct nouveau_bios *bios, u8 *ver, u8 *hdr, u8 *cnt, u8 *len) diff --git a/drivers/gpu/drm/nouveau/core/subdev/mxm/base.c b/drivers/gpu/drm/nouveau/core/subdev/mxm/base.c index 684f39678bf7..93e3ddf7303a 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/mxm/base.c +++ b/drivers/gpu/drm/nouveau/core/subdev/mxm/base.c @@ -210,7 +210,7 @@ mxm_shadow_wmi(struct nouveau_mxm *mxm, u8 version) } #endif -struct mxm_shadow_h { +static struct mxm_shadow_h { const char *name; bool (*exec)(struct nouveau_mxm *, u8 version); } _mxm_shadow[] = { diff --git a/drivers/gpu/drm/nouveau/core/subdev/vm/nv50.c b/drivers/gpu/drm/nouveau/core/subdev/vm/nv50.c index 0f0d3a5de5c2..d83489c44c3a 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/vm/nv50.c +++ b/drivers/gpu/drm/nouveau/core/subdev/vm/nv50.c @@ -34,7 +34,7 @@ struct nv50_vmmgr_priv { spinlock_t lock; }; -void +static void nv50_vm_map_pgt(struct nouveau_gpuobj *pgd, u32 pde, struct nouveau_gpuobj *pgt[2]) { @@ -76,7 +76,7 @@ vm_addr(struct nouveau_vma *vma, u64 phys, u32 memtype, u32 target) return phys; } -void +static void nv50_vm_map(struct nouveau_vma *vma, struct nouveau_gpuobj *pgt, struct nouveau_mem *mem, u32 pte, u32 cnt, u64 phys, u64 delta) { @@ -123,7 +123,7 @@ nv50_vm_map(struct nouveau_vma *vma, struct nouveau_gpuobj *pgt, } } -void +static void nv50_vm_map_sg(struct nouveau_vma *vma, struct nouveau_gpuobj *pgt, struct nouveau_mem *mem, u32 pte, u32 cnt, dma_addr_t *list) { @@ -137,7 +137,7 @@ nv50_vm_map_sg(struct nouveau_vma *vma, struct nouveau_gpuobj *pgt, } } -void +static void nv50_vm_unmap(struct nouveau_gpuobj *pgt, u32 pte, u32 cnt) { pte <<= 3; @@ -148,7 +148,7 @@ nv50_vm_unmap(struct nouveau_gpuobj *pgt, u32 pte, u32 cnt) } } -void +static void nv50_vm_flush(struct nouveau_vm *vm) { struct nouveau_engine *engine; diff --git a/drivers/gpu/drm/nouveau/core/subdev/vm/nvc0.c b/drivers/gpu/drm/nouveau/core/subdev/vm/nvc0.c index e48ece297511..44721a4714d1 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/vm/nvc0.c +++ b/drivers/gpu/drm/nouveau/core/subdev/vm/nvc0.c @@ -34,7 +34,7 @@ struct nvc0_vmmgr_priv { spinlock_t lock; }; -void +static void nvc0_vm_map_pgt(struct nouveau_gpuobj *pgd, u32 index, struct nouveau_gpuobj *pgt[2]) { @@ -64,7 +64,7 @@ nvc0_vm_addr(struct nouveau_vma *vma, u64 phys, u32 memtype, u32 target) return phys; } -void +static void nvc0_vm_map(struct nouveau_vma *vma, struct nouveau_gpuobj *pgt, struct nouveau_mem *mem, u32 pte, u32 cnt, u64 phys, u64 delta) { @@ -80,7 +80,7 @@ nvc0_vm_map(struct nouveau_vma *vma, struct nouveau_gpuobj *pgt, } } -void +static void nvc0_vm_map_sg(struct nouveau_vma *vma, struct nouveau_gpuobj *pgt, struct nouveau_mem *mem, u32 pte, u32 cnt, dma_addr_t *list) { @@ -95,7 +95,7 @@ nvc0_vm_map_sg(struct nouveau_vma *vma, struct nouveau_gpuobj *pgt, } } -void +static void nvc0_vm_unmap(struct nouveau_gpuobj *pgt, u32 pte, u32 cnt) { pte <<= 3; @@ -132,7 +132,7 @@ nvc0_vm_flush_engine(struct nouveau_subdev *subdev, u64 addr, int type) spin_unlock_irqrestore(&priv->lock, flags); } -void +static void nvc0_vm_flush(struct nouveau_vm *vm) { struct nouveau_vm_pgd *vpgd; diff --git a/drivers/gpu/drm/nouveau/nouveau_chan.c b/drivers/gpu/drm/nouveau/nouveau_chan.c index 55dc51c1b92e..3b3791453178 100644 --- a/drivers/gpu/drm/nouveau/nouveau_chan.c +++ b/drivers/gpu/drm/nouveau/nouveau_chan.c @@ -182,7 +182,7 @@ nouveau_channel_prep(struct nouveau_drm *drm, struct nouveau_cli *cli, return 0; } -int +static int nouveau_channel_ind(struct nouveau_drm *drm, struct nouveau_cli *cli, u32 parent, u32 handle, u32 engine, struct nouveau_channel **pchan) diff --git a/drivers/gpu/drm/nouveau/nouveau_dp.c b/drivers/gpu/drm/nouveau/nouveau_dp.c index 78e54cb8dfbe..e1387bd73d76 100644 --- a/drivers/gpu/drm/nouveau/nouveau_dp.c +++ b/drivers/gpu/drm/nouveau/nouveau_dp.c @@ -286,7 +286,7 @@ dp_link_train_fini(struct drm_device *dev, struct dp_state *dp) nouveau_bios_run_init_table(dev, script, dp->dcb, dp->crtc); } -bool +static bool nouveau_dp_link_train(struct drm_encoder *encoder, u32 datarate, struct dp_train_func *func) { diff --git a/drivers/gpu/drm/nouveau/nouveau_drm.c b/drivers/gpu/drm/nouveau/nouveau_drm.c index 4dfc40e3dabe..e26358c79151 100644 --- a/drivers/gpu/drm/nouveau/nouveau_drm.c +++ b/drivers/gpu/drm/nouveau/nouveau_drm.c @@ -64,7 +64,7 @@ static int nouveau_noaccel = 0; module_param_named(noaccel, nouveau_noaccel, int, 0400); MODULE_PARM_DESC(modeset, "enable driver"); -int nouveau_modeset = -1; +static int nouveau_modeset = -1; module_param_named(modeset, nouveau_modeset, int, 0400); static struct drm_driver driver; @@ -238,7 +238,7 @@ nouveau_drm_probe(struct pci_dev *pdev, const struct pci_device_id *pent) return 0; } -int +static int nouveau_drm_load(struct drm_device *dev, unsigned long flags) { struct pci_dev *pdev = dev->pdev; @@ -352,7 +352,7 @@ fail_device: return ret; } -int +static int nouveau_drm_unload(struct drm_device *dev) { struct nouveau_drm *drm = nouveau_drm(dev); @@ -490,7 +490,7 @@ nouveau_drm_resume(struct pci_dev *pdev) return 0; } -int +static int nouveau_drm_open(struct drm_device *dev, struct drm_file *fpriv) { struct pci_dev *pdev = dev->pdev; @@ -519,7 +519,7 @@ nouveau_drm_open(struct drm_device *dev, struct drm_file *fpriv) return 0; } -void +static void nouveau_drm_preclose(struct drm_device *dev, struct drm_file *fpriv) { struct nouveau_cli *cli = nouveau_cli(fpriv); @@ -533,7 +533,7 @@ nouveau_drm_preclose(struct drm_device *dev, struct drm_file *fpriv) mutex_unlock(&drm->client.mutex); } -void +static void nouveau_drm_postclose(struct drm_device *dev, struct drm_file *fpriv) { struct nouveau_cli *cli = nouveau_cli(fpriv); diff --git a/drivers/gpu/drm/nouveau/nouveau_irq.c b/drivers/gpu/drm/nouveau/nouveau_irq.c index af0cfe81da69..9ca8afdb5549 100644 --- a/drivers/gpu/drm/nouveau/nouveau_irq.c +++ b/drivers/gpu/drm/nouveau/nouveau_irq.c @@ -25,6 +25,7 @@ #include #include "nouveau_drm.h" +#include "nouveau_irq.h" #include "nv50_display.h" void diff --git a/drivers/gpu/drm/nouveau/nouveau_mem.c b/drivers/gpu/drm/nouveau/nouveau_mem.c index 8f8f421367bc..7e0ff10a2759 100644 --- a/drivers/gpu/drm/nouveau/nouveau_mem.c +++ b/drivers/gpu/drm/nouveau/nouveau_mem.c @@ -248,7 +248,7 @@ nouveau_mem_ddr2_mr(struct drm_device *dev, u32 freq, return 0; } -uint8_t nv_mem_wr_lut_ddr3[NV_MEM_WR_DDR3_MAX] = { +static const uint8_t nv_mem_wr_lut_ddr3[NV_MEM_WR_DDR3_MAX] = { 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 5, 6, 6, 7, 7, 0, 0}; static int @@ -297,9 +297,9 @@ nouveau_mem_ddr3_mr(struct drm_device *dev, u32 freq, return 0; } -uint8_t nv_mem_cl_lut_gddr3[NV_MEM_CL_GDDR3_MAX] = { +static const uint8_t nv_mem_cl_lut_gddr3[NV_MEM_CL_GDDR3_MAX] = { 0, 0, 0, 0, 4, 5, 6, 7, 0, 1, 2, 3, 8, 9, 10, 11}; -uint8_t nv_mem_wr_lut_gddr3[NV_MEM_WR_GDDR3_MAX] = { +static const uint8_t nv_mem_wr_lut_gddr3[NV_MEM_WR_GDDR3_MAX] = { 0, 0, 0, 0, 0, 2, 3, 8, 9, 10, 11, 0, 0, 1, 1, 0, 3}; static int diff --git a/drivers/gpu/drm/nouveau/nouveau_ttm.c b/drivers/gpu/drm/nouveau/nouveau_ttm.c index 030e4b84386c..d2fc121ff861 100644 --- a/drivers/gpu/drm/nouveau/nouveau_ttm.c +++ b/drivers/gpu/drm/nouveau/nouveau_ttm.c @@ -101,7 +101,7 @@ nouveau_vram_manager_new(struct ttm_mem_type_manager *man, return 0; } -void +static void nouveau_vram_manager_debug(struct ttm_mem_type_manager *man, const char *prefix) { struct nouveau_mm *mm = man->priv; @@ -176,7 +176,7 @@ nouveau_gart_manager_new(struct ttm_mem_type_manager *man, return 0; } -void +static void nouveau_gart_manager_debug(struct ttm_mem_type_manager *man, const char *prefix) { } @@ -248,7 +248,7 @@ nv04_gart_manager_new(struct ttm_mem_type_manager *man, return 0; } -void +static void nv04_gart_manager_debug(struct ttm_mem_type_manager *man, const char *prefix) { } diff --git a/drivers/gpu/drm/nouveau/nouveau_vga.c b/drivers/gpu/drm/nouveau/nouveau_vga.c index 9d455444f958..7bf7d131eee0 100644 --- a/drivers/gpu/drm/nouveau/nouveau_vga.c +++ b/drivers/gpu/drm/nouveau/nouveau_vga.c @@ -7,6 +7,7 @@ #include "nouveau_drm.h" #include "nouveau_acpi.h" #include "nouveau_fbcon.h" +#include "nouveau_vga.h" static unsigned int nouveau_vga_set_decode(void *priv, bool state) -- cgit v1.2.3