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_mem.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers/gpu/drm/nouveau/nouveau_mem.c') diff --git a/drivers/gpu/drm/nouveau/nouveau_mem.c b/drivers/gpu/drm/nouveau/nouveau_mem.c index 5b498ea32e14..0887236a3645 100644 --- a/drivers/gpu/drm/nouveau/nouveau_mem.c +++ b/drivers/gpu/drm/nouveau/nouveau_mem.c @@ -37,9 +37,9 @@ #include "nouveau_drv.h" #include "nouveau_pm.h" -#include "nouveau_mm.h" -#include "nouveau_vm.h" -#include "nouveau_fifo.h" +#include +#include +#include #include "nouveau_fence.h" /* -- cgit v1.2.3 From aa4cc5d274c09909fe32861825c2377d0ccb3bfd Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Thu, 5 Jul 2012 21:36:32 +1000 Subject: drm/nouveau/agp: move all agp stuff into its own source file Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/Makefile | 2 +- drivers/gpu/drm/nouveau/nouveau_agp.c | 152 ++++++++++++++++++++++++++++++++ drivers/gpu/drm/nouveau/nouveau_agp.h | 8 ++ drivers/gpu/drm/nouveau/nouveau_drv.c | 18 ++-- drivers/gpu/drm/nouveau/nouveau_drv.h | 3 - drivers/gpu/drm/nouveau/nouveau_mem.c | 147 +----------------------------- drivers/gpu/drm/nouveau/nouveau_state.c | 4 + 7 files changed, 173 insertions(+), 161 deletions(-) create mode 100644 drivers/gpu/drm/nouveau/nouveau_agp.c create mode 100644 drivers/gpu/drm/nouveau/nouveau_agp.h (limited to 'drivers/gpu/drm/nouveau/nouveau_mem.c') diff --git a/drivers/gpu/drm/nouveau/Makefile b/drivers/gpu/drm/nouveau/Makefile index 40c311e24bcd..8b632934f01d 100644 --- a/drivers/gpu/drm/nouveau/Makefile +++ b/drivers/gpu/drm/nouveau/Makefile @@ -70,7 +70,7 @@ nouveau-y += nouveau_drv.o nouveau_state.o nouveau_channel.o nouveau_mem.o \ nouveau_display.o nouveau_connector.o nouveau_fbcon.o \ nouveau_hdmi.o nouveau_dp.o \ nouveau_pm.o nouveau_volt.o nouveau_perf.o nouveau_temp.o \ - nouveau_mxm.o \ + nouveau_mxm.o nouveau_agp.o \ nouveau_abi16.o \ nouveau_bios.o \ nv04_fence.o nv10_fence.o nv84_fence.o nvc0_fence.o \ diff --git a/drivers/gpu/drm/nouveau/nouveau_agp.c b/drivers/gpu/drm/nouveau/nouveau_agp.c new file mode 100644 index 000000000000..d33201c56aa1 --- /dev/null +++ b/drivers/gpu/drm/nouveau/nouveau_agp.c @@ -0,0 +1,152 @@ +#include + +#include "drmP.h" +#include "drm.h" + +#include "nouveau_drv.h" +#include "nouveau_agp.h" + +#if __OS_HAS_AGP +MODULE_PARM_DESC(agpmode, "AGP mode (0 to disable AGP)"); +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) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + + /* + * FW seems to be broken on nv18, it makes the card lock up + * randomly. + */ + if (dev_priv->chipset == 0x18) + mode &= ~PCI_AGP_COMMAND_FW; + + /* + * AGP mode set in the command line. + */ + if (nouveau_agpmode > 0) { + bool agpv3 = mode & 0x8; + int rate = agpv3 ? nouveau_agpmode / 4 : nouveau_agpmode; + + mode = (mode & ~0x7) | (rate & 0x7); + } + + return mode; +} + +static bool +nouveau_agp_enabled(struct drm_device *dev) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + + if (!drm_pci_device_is_agp(dev) || !dev->agp) + return false; + + switch (dev_priv->gart_info.type) { + case NOUVEAU_GART_NONE: + if (!nouveau_agpmode) + return false; + break; + case NOUVEAU_GART_AGP: + break; + default: + return false; + } + + return true; +} +#endif + +void +nouveau_agp_reset(struct drm_device *dev) +{ +#if __OS_HAS_AGP + u32 save[2]; + int ret; + + if (!nouveau_agp_enabled(dev)) + 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) | + dev->agp->mode) & PCI_AGP_COMMAND_FW) { + struct drm_agp_info info; + struct drm_agp_mode mode; + + ret = drm_agp_info(dev, &info); + if (ret) + return; + + mode.mode = get_agp_mode(dev, info.mode); + mode.mode &= ~PCI_AGP_COMMAND_FW; + + ret = drm_agp_enable(dev, mode); + if (ret) + return; + } + + + /* 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); + + /* reset PGRAPH, PFIFO and PTIMER */ + save[1] = nv_mask(dev, 0x000200, 0x00011100, 0x00000000); + nv_mask(dev, 0x000200, 0x00011100, save[1]); + + /* and restore bustmaster bit (gives effect of resetting AGP) */ + nv_wr32(dev, NV04_PBUS_PCI_NV_1, save[0]); +#endif +} + +void +nouveau_agp_init(struct drm_device *dev) +{ +#if __OS_HAS_AGP + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct drm_agp_info info; + struct drm_agp_mode mode; + int ret; + + if (!nouveau_agp_enabled(dev)) + return; + + ret = drm_agp_acquire(dev); + if (ret) { + NV_ERROR(dev, "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); + return; + } + + /* see agp.h for the AGPSTAT_* modes available */ + mode.mode = get_agp_mode(dev, info.mode); + + ret = drm_agp_enable(dev, mode); + if (ret) { + NV_ERROR(dev, "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; +#endif +} + +void +nouveau_agp_fini(struct drm_device *dev) +{ +#if __OS_HAS_AGP + 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 new file mode 100644 index 000000000000..b23db55eb2ca --- /dev/null +++ b/drivers/gpu/drm/nouveau/nouveau_agp.h @@ -0,0 +1,8 @@ +#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 *); + +#endif diff --git a/drivers/gpu/drm/nouveau/nouveau_drv.c b/drivers/gpu/drm/nouveau/nouveau_drv.c index 74c226587d52..33dd955e26d3 100644 --- a/drivers/gpu/drm/nouveau/nouveau_drv.c +++ b/drivers/gpu/drm/nouveau/nouveau_drv.c @@ -29,6 +29,7 @@ #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" @@ -39,10 +40,6 @@ #include "drm_pciids.h" -MODULE_PARM_DESC(agpmode, "AGP mode (0 to disable AGP)"); -int nouveau_agpmode = -1; -module_param_named(agpmode, nouveau_agpmode, int, 0400); - MODULE_PARM_DESC(modeset, "Enable kernel modesetting"); int nouveau_modeset = -1; module_param_named(modeset, nouveau_modeset, int, 0400); @@ -248,6 +245,8 @@ nouveau_pci_suspend(struct pci_dev *pdev, pm_message_t pm_state) goto out_abort; } + nouveau_agp_fini(dev); + NV_INFO(dev, "And we're gone!\n"); pci_save_state(pdev); if (pm_state.event == PM_EVENT_SUSPEND) { @@ -287,8 +286,7 @@ nouveau_pci_resume(struct pci_dev *pdev) pci_set_master(dev->pdev); /* Make sure the AGP controller is in a consistent state */ - if (dev_priv->gart_info.type == NOUVEAU_GART_AGP) - nouveau_mem_reset_agp(dev); + nouveau_agp_reset(dev); /* Make the CRTCs accessible */ engine->display.early_init(dev); @@ -298,13 +296,7 @@ nouveau_pci_resume(struct pci_dev *pdev) if (ret) return ret; - if (dev_priv->gart_info.type == NOUVEAU_GART_AGP) { - ret = nouveau_mem_init_agp(dev); - if (ret) { - NV_ERROR(dev, "error reinitialising AGP: %d\n", 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 a781d4400105..2158710cd6ad 100644 --- a/drivers/gpu/drm/nouveau/nouveau_drv.h +++ b/drivers/gpu/drm/nouveau/nouveau_drv.h @@ -836,7 +836,6 @@ nouveau_bo_ref(struct nouveau_bo *ref, struct nouveau_bo **pnvbo) /* nouveau_drv.c */ extern int nouveau_modeset; -extern int nouveau_agpmode; extern int nouveau_duallink; extern int nouveau_uscript_lvds; extern int nouveau_uscript_tmds; @@ -884,8 +883,6 @@ extern int nouveau_mem_vram_init(struct drm_device *); extern void nouveau_mem_vram_fini(struct drm_device *); extern int nouveau_mem_gart_init(struct drm_device *); extern void nouveau_mem_gart_fini(struct drm_device *); -extern int nouveau_mem_init_agp(struct drm_device *); -extern int nouveau_mem_reset_agp(struct drm_device *); extern void nouveau_mem_close(struct drm_device *); extern bool nouveau_mem_flags_valid(struct drm_device *, u32 tile_flags); extern int nouveau_mem_timing_calc(struct drm_device *, u32 freq, diff --git a/drivers/gpu/drm/nouveau/nouveau_mem.c b/drivers/gpu/drm/nouveau/nouveau_mem.c index 0887236a3645..c816e03c15d4 100644 --- a/drivers/gpu/drm/nouveau/nouveau_mem.c +++ b/drivers/gpu/drm/nouveau/nouveau_mem.c @@ -36,6 +36,7 @@ #include "drm_sarea.h" #include "nouveau_drv.h" +#include "nouveau_agp.h" #include "nouveau_pm.h" #include #include @@ -172,26 +173,7 @@ void nouveau_mem_gart_fini(struct drm_device *dev) { nouveau_sgdma_takedown(dev); - - if (drm_core_has_AGP(dev) && dev->agp) { - struct drm_agp_mem *entry, *tempe; - - /* Remove AGP resources, but leave dev->agp - intact until drv_cleanup is called. */ - list_for_each_entry_safe(entry, tempe, &dev->agp->memory, head) { - if (entry->bound) - drm_unbind_agp(entry->memory); - drm_free_agp(entry->memory, entry->pages); - kfree(entry); - } - INIT_LIST_HEAD(&dev->agp->memory); - - if (dev->agp->acquired) - drm_agp_release(dev); - - dev->agp->acquired = 0; - dev->agp->enabled = 0; - } + nouveau_agp_fini(dev); } bool @@ -203,121 +185,6 @@ nouveau_mem_flags_valid(struct drm_device *dev, u32 tile_flags) return false; } -#if __OS_HAS_AGP -static unsigned long -get_agp_mode(struct drm_device *dev, unsigned long mode) -{ - struct drm_nouveau_private *dev_priv = dev->dev_private; - - /* - * FW seems to be broken on nv18, it makes the card lock up - * randomly. - */ - if (dev_priv->chipset == 0x18) - mode &= ~PCI_AGP_COMMAND_FW; - - /* - * AGP mode set in the command line. - */ - if (nouveau_agpmode > 0) { - bool agpv3 = mode & 0x8; - int rate = agpv3 ? nouveau_agpmode / 4 : nouveau_agpmode; - - mode = (mode & ~0x7) | (rate & 0x7); - } - - return mode; -} -#endif - -int -nouveau_mem_reset_agp(struct drm_device *dev) -{ -#if __OS_HAS_AGP - uint32_t saved_pci_nv_1, pmc_enable; - int ret; - - /* 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) | - dev->agp->mode) & PCI_AGP_COMMAND_FW) { - struct drm_agp_info info; - struct drm_agp_mode mode; - - ret = drm_agp_info(dev, &info); - if (ret) - return ret; - - mode.mode = get_agp_mode(dev, info.mode) & ~PCI_AGP_COMMAND_FW; - ret = drm_agp_enable(dev, mode); - if (ret) - return ret; - } - - saved_pci_nv_1 = nv_rd32(dev, NV04_PBUS_PCI_NV_1); - - /* clear busmaster bit */ - nv_wr32(dev, NV04_PBUS_PCI_NV_1, saved_pci_nv_1 & ~0x4); - /* disable AGP */ - nv_wr32(dev, NV04_PBUS_PCI_NV_19, 0); - - /* power cycle pgraph, if enabled */ - pmc_enable = nv_rd32(dev, NV03_PMC_ENABLE); - if (pmc_enable & NV_PMC_ENABLE_PGRAPH) { - nv_wr32(dev, NV03_PMC_ENABLE, - pmc_enable & ~NV_PMC_ENABLE_PGRAPH); - nv_wr32(dev, NV03_PMC_ENABLE, nv_rd32(dev, NV03_PMC_ENABLE) | - NV_PMC_ENABLE_PGRAPH); - } - - /* and restore (gives effect of resetting AGP) */ - nv_wr32(dev, NV04_PBUS_PCI_NV_1, saved_pci_nv_1); -#endif - - return 0; -} - -int -nouveau_mem_init_agp(struct drm_device *dev) -{ -#if __OS_HAS_AGP - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct drm_agp_info info; - struct drm_agp_mode mode; - int ret; - - if (!dev->agp->acquired) { - ret = drm_agp_acquire(dev); - if (ret) { - NV_ERROR(dev, "Unable to acquire AGP: %d\n", ret); - return ret; - } - } - - nouveau_mem_reset_agp(dev); - - ret = drm_agp_info(dev, &info); - if (ret) { - NV_ERROR(dev, "Unable to get AGP info: %d\n", ret); - return ret; - } - - /* see agp.h for the AGPSTAT_* modes available */ - mode.mode = get_agp_mode(dev, info.mode); - ret = drm_agp_enable(dev, mode); - if (ret) { - NV_ERROR(dev, "Unable to enable AGP: %d\n", ret); - return ret; - } - - 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; -#endif - return 0; -} - static const struct vram_types { int value; const char *name; @@ -441,15 +308,7 @@ nouveau_mem_gart_init(struct drm_device *dev) struct ttm_bo_device *bdev = &dev_priv->ttm.bdev; int ret; - dev_priv->gart_info.type = NOUVEAU_GART_NONE; - -#if !defined(__powerpc__) && !defined(__ia64__) - if (drm_pci_device_is_agp(dev) && dev->agp && nouveau_agpmode) { - ret = nouveau_mem_init_agp(dev); - if (ret) - NV_ERROR(dev, "Error initialising AGP: %d\n", ret); - } -#endif + nouveau_agp_init(dev); if (dev_priv->gart_info.type == NOUVEAU_GART_NONE) { ret = nouveau_sgdma_init(dev); diff --git a/drivers/gpu/drm/nouveau/nouveau_state.c b/drivers/gpu/drm/nouveau/nouveau_state.c index 0e8f325c709c..31c570c2bc36 100644 --- a/drivers/gpu/drm/nouveau/nouveau_state.c +++ b/drivers/gpu/drm/nouveau/nouveau_state.c @@ -34,6 +34,7 @@ #include "nouveau_drv.h" #include "nouveau_drm.h" +#include "nouveau_agp.h" #include "nouveau_fbcon.h" #include #include @@ -547,6 +548,9 @@ 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) -- 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_mem.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 861d21074bbb141b0cc165a61c11f571571cda12 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Wed, 11 Jul 2012 19:05:01 +1000 Subject: drm/nouveau/fb: merge fb/vram and port to subdev interfaces Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/Makefile | 5 +- drivers/gpu/drm/nouveau/core/engine/fifo/nv40.c | 2 +- drivers/gpu/drm/nouveau/core/engine/graph/nv10.c | 4 +- drivers/gpu/drm/nouveau/core/engine/graph/nv20.c | 2 +- drivers/gpu/drm/nouveau/core/engine/graph/nv40.c | 5 +- drivers/gpu/drm/nouveau/core/engine/mpeg/nv31.c | 7 +- drivers/gpu/drm/nouveau/core/include/subdev/fb.h | 137 ++++++++ drivers/gpu/drm/nouveau/core/include/subdev/ltcg.h | 33 ++ drivers/gpu/drm/nouveau/core/include/subdev/vm.h | 5 +- drivers/gpu/drm/nouveau/core/subdev/device/nv04.c | 3 + drivers/gpu/drm/nouveau/core/subdev/device/nv10.c | 9 + drivers/gpu/drm/nouveau/core/subdev/device/nv20.c | 5 + drivers/gpu/drm/nouveau/core/subdev/device/nv30.c | 6 + drivers/gpu/drm/nouveau/core/subdev/device/nv40.c | 17 + drivers/gpu/drm/nouveau/core/subdev/device/nv50.c | 15 + drivers/gpu/drm/nouveau/core/subdev/device/nvc0.c | 18 + drivers/gpu/drm/nouveau/core/subdev/device/nve0.c | 6 + drivers/gpu/drm/nouveau/core/subdev/fb/base.c | 130 +++++++ drivers/gpu/drm/nouveau/core/subdev/fb/nv04.c | 139 ++++++-- drivers/gpu/drm/nouveau/core/subdev/fb/nv10.c | 186 +++++----- drivers/gpu/drm/nouveau/core/subdev/fb/nv20.c | 208 ++++++----- drivers/gpu/drm/nouveau/core/subdev/fb/nv30.c | 114 +++--- drivers/gpu/drm/nouveau/core/subdev/fb/nv40.c | 261 ++++++++------ drivers/gpu/drm/nouveau/core/subdev/fb/nv50.c | 384 ++++++++++++++++----- drivers/gpu/drm/nouveau/core/subdev/fb/nv50_vram.c | 243 ------------- drivers/gpu/drm/nouveau/core/subdev/fb/nvc0.c | 252 ++++++++++---- drivers/gpu/drm/nouveau/core/subdev/fb/nvc0_vram.c | 167 --------- drivers/gpu/drm/nouveau/core/subdev/instmem/nv50.c | 10 +- drivers/gpu/drm/nouveau/core/subdev/ltcg/nvc0.c | 91 +++++ drivers/gpu/drm/nouveau/core/subdev/mc/nvc0.c | 1 + drivers/gpu/drm/nouveau/core/subdev/vm/nv50.c | 6 +- drivers/gpu/drm/nouveau/nouveau_bo.c | 2 +- drivers/gpu/drm/nouveau/nouveau_compat.c | 106 ++++++ drivers/gpu/drm/nouveau/nouveau_compat.h | 20 ++ drivers/gpu/drm/nouveau/nouveau_debugfs.c | 3 +- drivers/gpu/drm/nouveau/nouveau_drv.c | 1 - drivers/gpu/drm/nouveau/nouveau_drv.h | 146 +------- drivers/gpu/drm/nouveau/nouveau_fb.h | 4 +- drivers/gpu/drm/nouveau/nouveau_fbcon.c | 4 +- drivers/gpu/drm/nouveau/nouveau_gem.c | 2 +- drivers/gpu/drm/nouveau/nouveau_mem.c | 90 +---- drivers/gpu/drm/nouveau/nouveau_state.c | 87 +---- drivers/gpu/drm/nouveau/nouveau_util.c | 43 +-- drivers/gpu/drm/nouveau/nouveau_util.h | 16 +- drivers/gpu/drm/nouveau/nv50_evo.c | 14 +- drivers/gpu/drm/nouveau/nv50_pm.c | 5 +- drivers/gpu/drm/nouveau/nva3_pm.c | 6 +- drivers/gpu/drm/nouveau/nvc0_pm.c | 10 +- drivers/gpu/drm/nouveau/nvd0_display.c | 6 +- 49 files changed, 1691 insertions(+), 1345 deletions(-) create mode 100644 drivers/gpu/drm/nouveau/core/include/subdev/fb.h create mode 100644 drivers/gpu/drm/nouveau/core/include/subdev/ltcg.h create mode 100644 drivers/gpu/drm/nouveau/core/subdev/fb/base.c delete mode 100644 drivers/gpu/drm/nouveau/core/subdev/fb/nv50_vram.c delete mode 100644 drivers/gpu/drm/nouveau/core/subdev/fb/nvc0_vram.c create mode 100644 drivers/gpu/drm/nouveau/core/subdev/ltcg/nvc0.c (limited to 'drivers/gpu/drm/nouveau/nouveau_mem.c') diff --git a/drivers/gpu/drm/nouveau/Makefile b/drivers/gpu/drm/nouveau/Makefile index 0615e954d238..5e18a53e2c0c 100644 --- a/drivers/gpu/drm/nouveau/Makefile +++ b/drivers/gpu/drm/nouveau/Makefile @@ -8,6 +8,7 @@ ccflags-y += -I$(src) nouveau-y := core/core/client.o nouveau-y += core/core/engine.o +nouveau-y += core/core/enum.o nouveau-y += core/core/handle.o nouveau-y += core/core/mm.o nouveau-y += core/core/namedb.o @@ -50,6 +51,7 @@ nouveau-y += core/subdev/devinit/nv10.o nouveau-y += core/subdev/devinit/nv1a.o nouveau-y += core/subdev/devinit/nv20.o nouveau-y += core/subdev/devinit/nv50.o +nouveau-y += core/subdev/fb/base.o nouveau-y += core/subdev/fb/nv04.o nouveau-y += core/subdev/fb/nv10.o nouveau-y += core/subdev/fb/nv20.o @@ -57,8 +59,6 @@ nouveau-y += core/subdev/fb/nv30.o nouveau-y += core/subdev/fb/nv40.o nouveau-y += core/subdev/fb/nv50.o nouveau-y += core/subdev/fb/nvc0.o -nouveau-y += core/subdev/fb/nv50_vram.o -nouveau-y += core/subdev/fb/nvc0_vram.o nouveau-y += core/subdev/gpio/base.o nouveau-y += core/subdev/gpio/nv10.o nouveau-y += core/subdev/gpio/nv50.o @@ -69,6 +69,7 @@ nouveau-y += core/subdev/i2c/bit.o nouveau-y += core/subdev/instmem/nv04.o nouveau-y += core/subdev/instmem/nv50.o nouveau-y += core/subdev/instmem/nvc0.o +nouveau-y += core/subdev/ltcg/nvc0.o nouveau-y += core/subdev/mc/base.o nouveau-y += core/subdev/mc/nv04.o nouveau-y += core/subdev/mc/nv44.o diff --git a/drivers/gpu/drm/nouveau/core/engine/fifo/nv40.c b/drivers/gpu/drm/nouveau/core/engine/fifo/nv40.c index 3079f080d40e..23ae4591b7bd 100644 --- a/drivers/gpu/drm/nouveau/core/engine/fifo/nv40.c +++ b/drivers/gpu/drm/nouveau/core/engine/fifo/nv40.c @@ -163,7 +163,7 @@ nv40_fifo_init(struct drm_device *dev, int engine) break; default: nv_wr32(dev, 0x002230, 0x00000000); - nv_wr32(dev, 0x002220, ((dev_priv->vram_size - 512 * 1024 + + nv_wr32(dev, 0x002220, ((nvfb_vram_size(dev) - 512 * 1024 + dev_priv->ramfc->pinst) >> 16) | 0x00030000); break; diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/nv10.c b/drivers/gpu/drm/nouveau/core/engine/graph/nv10.c index 19e303b423af..d006658e6468 100644 --- a/drivers/gpu/drm/nouveau/core/engine/graph/nv10.c +++ b/drivers/gpu/drm/nouveau/core/engine/graph/nv10.c @@ -895,9 +895,7 @@ nv10_graph_context_del(struct nouveau_channel *chan, int engine) static void nv10_graph_set_tile_region(struct drm_device *dev, int i) { - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_tile_reg *tile = &dev_priv->tile.reg[i]; - + struct nouveau_fb_tile *tile = nvfb_tile(dev, i); nv_wr32(dev, NV10_PGRAPH_TLIMIT(i), tile->limit); nv_wr32(dev, NV10_PGRAPH_TSIZE(i), tile->pitch); nv_wr32(dev, NV10_PGRAPH_TILE(i), tile->addr); diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/nv20.c b/drivers/gpu/drm/nouveau/core/engine/graph/nv20.c index 718ecf761823..dd31156e3029 100644 --- a/drivers/gpu/drm/nouveau/core/engine/graph/nv20.c +++ b/drivers/gpu/drm/nouveau/core/engine/graph/nv20.c @@ -472,7 +472,7 @@ static void nv20_graph_set_tile_region(struct drm_device *dev, int i) { struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_tile_reg *tile = &dev_priv->tile.reg[i]; + struct nouveau_fb_tile *tile = nvfb_tile(dev, i); nv_wr32(dev, NV20_PGRAPH_TLIMIT(i), tile->limit); nv_wr32(dev, NV20_PGRAPH_TSIZE(i), tile->pitch); diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/nv40.c b/drivers/gpu/drm/nouveau/core/engine/graph/nv40.c index 4ad9759f821e..ab3af6d15381 100644 --- a/drivers/gpu/drm/nouveau/core/engine/graph/nv40.c +++ b/drivers/gpu/drm/nouveau/core/engine/graph/nv40.c @@ -125,7 +125,7 @@ static void nv40_graph_set_tile_region(struct drm_device *dev, int i) { struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_tile_reg *tile = &dev_priv->tile.reg[i]; + struct nouveau_fb_tile *tile = nvfb_tile(dev, i); switch (dev_priv->chipset) { case 0x40: @@ -178,7 +178,6 @@ nv40_graph_init(struct drm_device *dev, int engine) { struct nv40_graph_engine *pgraph = nv_engine(dev, engine); struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_fb_engine *pfb = &dev_priv->engine.fb; uint32_t vramsz; int i, j; @@ -280,7 +279,7 @@ nv40_graph_init(struct drm_device *dev, int engine) } /* Turn all the tiling regions off. */ - for (i = 0; i < pfb->num_tiles; i++) + for (i = 0; i < nvfb_tile_nr(dev); i++) nv40_graph_set_tile_region(dev, i); /* begin RAM config */ diff --git a/drivers/gpu/drm/nouveau/core/engine/mpeg/nv31.c b/drivers/gpu/drm/nouveau/core/engine/mpeg/nv31.c index 4a14a6763dac..eb5455fed1bf 100644 --- a/drivers/gpu/drm/nouveau/core/engine/mpeg/nv31.c +++ b/drivers/gpu/drm/nouveau/core/engine/mpeg/nv31.c @@ -128,7 +128,6 @@ nv31_mpeg_object_new(struct nouveau_channel *chan, int engine, static int nv31_mpeg_init(struct drm_device *dev, int engine) { - struct drm_nouveau_private *dev_priv = dev->dev_private; struct nv31_mpeg_engine *pmpeg = nv_engine(dev, engine); int i; @@ -138,7 +137,7 @@ nv31_mpeg_init(struct drm_device *dev, int engine) nv_wr32(dev, 0x00b0e0, 0x00000020); /* nvidia: rd 0x01, wr 0x20 */ nv_wr32(dev, 0x00b0e8, 0x00000020); /* nvidia: rd 0x01, wr 0x20 */ - for (i = 0; i < dev_priv->engine.fb.num_tiles; i++) + for (i = 0; i < nvfb_tile_nr(dev); i++) pmpeg->base.set_tile_region(dev, i); /* PMPEG init */ @@ -235,9 +234,7 @@ nv31_mpeg_isr_chid(struct drm_device *dev, u32 inst) static void nv31_vpe_set_tile_region(struct drm_device *dev, int i) { - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_tile_reg *tile = &dev_priv->tile.reg[i]; - + struct nouveau_fb_tile *tile = nvfb_tile(dev, i); nv_wr32(dev, 0x00b008 + (i * 0x10), tile->pitch); nv_wr32(dev, 0x00b004 + (i * 0x10), tile->limit); nv_wr32(dev, 0x00b000 + (i * 0x10), tile->addr); diff --git a/drivers/gpu/drm/nouveau/core/include/subdev/fb.h b/drivers/gpu/drm/nouveau/core/include/subdev/fb.h new file mode 100644 index 000000000000..91dbdc16ac94 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/include/subdev/fb.h @@ -0,0 +1,137 @@ +#ifndef __NOUVEAU_FB_H__ +#define __NOUVEAU_FB_H__ + +#ifndef XXX_THIS_IS_A_HACK +#include +#include +#endif +#include +#include + +/* memory type/access flags, do not match hardware values */ +#define NV_MEM_ACCESS_RO 1 +#define NV_MEM_ACCESS_WO 2 +#define NV_MEM_ACCESS_RW (NV_MEM_ACCESS_RO | NV_MEM_ACCESS_WO) +#define NV_MEM_ACCESS_SYS 4 +#define NV_MEM_ACCESS_VM 8 +#define NV_MEM_ACCESS_NOSNOOP 16 + +#define NV_MEM_TARGET_VRAM 0 +#define NV_MEM_TARGET_PCI 1 +#define NV_MEM_TARGET_PCI_NOSNOOP 2 +#define NV_MEM_TARGET_VM 3 +#define NV_MEM_TARGET_GART 4 + +#define NV_MEM_TYPE_VM 0x7f +#define NV_MEM_COMP_VM 0x03 + +struct nouveau_mem { + struct drm_device *dev; + + struct nouveau_vma bar_vma; + struct nouveau_vma vma[2]; + u8 page_shift; + + struct nouveau_mm_node *tag; + struct list_head regions; + dma_addr_t *pages; + u32 memtype; + u64 offset; + u64 size; + struct sg_table *sg; +}; + +struct nouveau_fb_tile { + struct nouveau_mm_node *tag; + u32 addr; + u32 limit; + u32 pitch; + u32 zcomp; +}; + +#ifndef XXX_THIS_IS_A_HACK +struct nouveau_fb { + struct nouveau_subdev base; + + bool (*memtype_valid)(struct nouveau_fb *, u32 memtype); + + struct { + enum { + NV_MEM_TYPE_UNKNOWN = 0, + NV_MEM_TYPE_STOLEN, + NV_MEM_TYPE_SGRAM, + NV_MEM_TYPE_SDRAM, + NV_MEM_TYPE_DDR1, + NV_MEM_TYPE_DDR2, + NV_MEM_TYPE_DDR3, + NV_MEM_TYPE_GDDR2, + NV_MEM_TYPE_GDDR3, + NV_MEM_TYPE_GDDR4, + NV_MEM_TYPE_GDDR5 + } type; + u64 stolen; + u64 size; + int ranks; + + int (*get)(struct nouveau_fb *, u64 size, u32 align, + u32 size_nc, u32 type, struct nouveau_mem **); + void (*put)(struct nouveau_fb *, struct nouveau_mem **); + } ram; + + struct nouveau_mm vram; + struct nouveau_mm tags; + + struct { + struct nouveau_fb_tile region[16]; + int regions; + void (*init)(struct nouveau_fb *, int i, u32 addr, u32 size, + u32 pitch, u32 flags, struct nouveau_fb_tile *); + void (*fini)(struct nouveau_fb *, int i, + struct nouveau_fb_tile *); + void (*prog)(struct nouveau_fb *, int i, + struct nouveau_fb_tile *); + } tile; +}; + +static inline struct nouveau_fb * +nouveau_fb(void *obj) +{ + return (void *)nv_device(obj)->subdev[NVDEV_SUBDEV_FB]; +} + +#define nouveau_fb_create(p,e,c,d) \ + nouveau_subdev_create((p), (e), (c), 0, "PFB", "fb", (d)) +int nouveau_fb_created(struct nouveau_fb *); +void nouveau_fb_destroy(struct nouveau_fb *); +int nouveau_fb_init(struct nouveau_fb *); +#define nouveau_fb_fini(p,s) \ + nouveau_subdev_fini(&(p)->base, (s)) + +void _nouveau_fb_dtor(struct nouveau_object *); +int _nouveau_fb_init(struct nouveau_object *); +#define _nouveau_fb_fini _nouveau_subdev_fini + +extern struct nouveau_oclass nv04_fb_oclass; +extern struct nouveau_oclass nv10_fb_oclass; +extern struct nouveau_oclass nv20_fb_oclass; +extern struct nouveau_oclass nv30_fb_oclass; +extern struct nouveau_oclass nv40_fb_oclass; +extern struct nouveau_oclass nv50_fb_oclass; +extern struct nouveau_oclass nvc0_fb_oclass; + +struct nouveau_bios; +int nouveau_fb_bios_memtype(struct nouveau_bios *); + +bool nv04_fb_memtype_valid(struct nouveau_fb *, u32 memtype); + +void nv10_fb_tile_prog(struct nouveau_fb *, int, struct nouveau_fb_tile *); + +void nv30_fb_tile_init(struct nouveau_fb *, int i, u32 addr, u32 size, + u32 pitch, u32 flags, struct nouveau_fb_tile *); +void nv30_fb_tile_fini(struct nouveau_fb *, int i, struct nouveau_fb_tile *); + +void nv50_fb_vram_del(struct nouveau_fb *, struct nouveau_mem **); +void nv50_fb_trap(struct nouveau_fb *, int display); +#endif + +#endif diff --git a/drivers/gpu/drm/nouveau/core/include/subdev/ltcg.h b/drivers/gpu/drm/nouveau/core/include/subdev/ltcg.h new file mode 100644 index 000000000000..f351f63bc654 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/include/subdev/ltcg.h @@ -0,0 +1,33 @@ +#ifndef __NOUVEAU_LTCG_H__ +#define __NOUVEAU_LTCG_H__ + +#include +#include + +struct nouveau_ltcg { + struct nouveau_subdev base; +}; + +static inline struct nouveau_ltcg * +nouveau_ltcg(void *obj) +{ + return (void *)nv_device(obj)->subdev[NVDEV_SUBDEV_LTCG]; +} + +#define nouveau_ltcg_create(p,e,o,d) \ + nouveau_subdev_create_((p), (e), (o), 0, "PLTCG", "level2", \ + sizeof(**d), (void **)d) +#define nouveau_ltcg_destroy(p) \ + nouveau_subdev_destroy(&(p)->base) +#define nouveau_ltcg_init(p) \ + nouveau_subdev_init(&(p)->base) +#define nouveau_ltcg_fini(p,s) \ + nouveau_subdev_fini(&(p)->base, (s)) + +#define _nouveau_ltcg_dtor _nouveau_subdev_dtor +#define _nouveau_ltcg_init _nouveau_subdev_init +#define _nouveau_ltcg_fini _nouveau_subdev_fini + +extern struct nouveau_oclass nvc0_ltcg_oclass; + +#endif diff --git a/drivers/gpu/drm/nouveau/core/include/subdev/vm.h b/drivers/gpu/drm/nouveau/core/include/subdev/vm.h index 7c1fc2114fec..6d3764b416f4 100644 --- a/drivers/gpu/drm/nouveau/core/include/subdev/vm.h +++ b/drivers/gpu/drm/nouveau/core/include/subdev/vm.h @@ -25,11 +25,10 @@ #ifndef __NOUVEAU_VM_H__ #define __NOUVEAU_VM_H__ -#include "drmP.h" - -#include "nouveau_drv.h" #include +struct nouveau_mem; + struct nouveau_vm_pgt { struct nouveau_gpuobj *obj[2]; u32 refcount[2]; diff --git a/drivers/gpu/drm/nouveau/core/subdev/device/nv04.c b/drivers/gpu/drm/nouveau/core/subdev/device/nv04.c index aa43bd5c2374..66b7156281c9 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/device/nv04.c +++ b/drivers/gpu/drm/nouveau/core/subdev/device/nv04.c @@ -29,6 +29,7 @@ #include #include #include +#include int nv04_identify(struct nouveau_device *device) @@ -41,6 +42,7 @@ nv04_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv04_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; + device->oclass[NVDEV_SUBDEV_FB ] = &nv04_fb_oclass; break; case 0x05: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -49,6 +51,7 @@ nv04_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv05_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; + device->oclass[NVDEV_SUBDEV_FB ] = &nv04_fb_oclass; break; default: nv_fatal(device, "unknown RIVA chipset\n"); diff --git a/drivers/gpu/drm/nouveau/core/subdev/device/nv10.c b/drivers/gpu/drm/nouveau/core/subdev/device/nv10.c index 1926c33fb6f8..cf81479725ad 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/device/nv10.c +++ b/drivers/gpu/drm/nouveau/core/subdev/device/nv10.c @@ -30,6 +30,7 @@ #include #include #include +#include int nv10_identify(struct nouveau_device *device) @@ -43,6 +44,7 @@ nv10_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv10_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; + device->oclass[NVDEV_SUBDEV_FB ] = &nv10_fb_oclass; break; case 0x15: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -52,6 +54,7 @@ nv10_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv10_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; + device->oclass[NVDEV_SUBDEV_FB ] = &nv10_fb_oclass; break; case 0x16: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -61,6 +64,7 @@ nv10_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv10_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; + device->oclass[NVDEV_SUBDEV_FB ] = &nv10_fb_oclass; break; case 0x1a: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -70,6 +74,7 @@ nv10_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; + device->oclass[NVDEV_SUBDEV_FB ] = &nv10_fb_oclass; break; case 0x11: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -79,6 +84,7 @@ nv10_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv10_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; + device->oclass[NVDEV_SUBDEV_FB ] = &nv10_fb_oclass; break; case 0x17: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -88,6 +94,7 @@ nv10_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv10_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; + device->oclass[NVDEV_SUBDEV_FB ] = &nv10_fb_oclass; break; case 0x1f: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -97,6 +104,7 @@ nv10_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; + device->oclass[NVDEV_SUBDEV_FB ] = &nv10_fb_oclass; break; case 0x18: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -106,6 +114,7 @@ nv10_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv10_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; + device->oclass[NVDEV_SUBDEV_FB ] = &nv10_fb_oclass; break; default: nv_fatal(device, "unknown Celsius chipset\n"); diff --git a/drivers/gpu/drm/nouveau/core/subdev/device/nv20.c b/drivers/gpu/drm/nouveau/core/subdev/device/nv20.c index 88729c308565..e97280cd43b0 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/device/nv20.c +++ b/drivers/gpu/drm/nouveau/core/subdev/device/nv20.c @@ -30,6 +30,7 @@ #include #include #include +#include int nv20_identify(struct nouveau_device *device) @@ -43,6 +44,7 @@ nv20_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv20_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; + device->oclass[NVDEV_SUBDEV_FB ] = &nv20_fb_oclass; break; case 0x25: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -52,6 +54,7 @@ nv20_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv20_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; + device->oclass[NVDEV_SUBDEV_FB ] = &nv20_fb_oclass; break; case 0x28: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -61,6 +64,7 @@ nv20_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv20_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; + device->oclass[NVDEV_SUBDEV_FB ] = &nv20_fb_oclass; break; case 0x2a: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -70,6 +74,7 @@ nv20_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv20_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; + device->oclass[NVDEV_SUBDEV_FB ] = &nv20_fb_oclass; break; default: nv_fatal(device, "unknown Kelvin chipset\n"); diff --git a/drivers/gpu/drm/nouveau/core/subdev/device/nv30.c b/drivers/gpu/drm/nouveau/core/subdev/device/nv30.c index 4feea8804a78..ddd3ab6cb733 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/device/nv30.c +++ b/drivers/gpu/drm/nouveau/core/subdev/device/nv30.c @@ -30,6 +30,7 @@ #include #include #include +#include int nv30_identify(struct nouveau_device *device) @@ -43,6 +44,7 @@ nv30_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv20_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; + device->oclass[NVDEV_SUBDEV_FB ] = &nv30_fb_oclass; break; case 0x35: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -52,6 +54,7 @@ nv30_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv20_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; + device->oclass[NVDEV_SUBDEV_FB ] = &nv30_fb_oclass; break; case 0x31: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -61,6 +64,7 @@ nv30_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv20_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; + device->oclass[NVDEV_SUBDEV_FB ] = &nv30_fb_oclass; break; case 0x36: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -70,6 +74,7 @@ nv30_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv20_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; + device->oclass[NVDEV_SUBDEV_FB ] = &nv30_fb_oclass; break; case 0x34: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -79,6 +84,7 @@ nv30_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv10_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; + device->oclass[NVDEV_SUBDEV_FB ] = &nv30_fb_oclass; break; default: nv_fatal(device, "unknown Rankine chipset\n"); diff --git a/drivers/gpu/drm/nouveau/core/subdev/device/nv40.c b/drivers/gpu/drm/nouveau/core/subdev/device/nv40.c index 8f683613788d..c7ea921e0309 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/device/nv40.c +++ b/drivers/gpu/drm/nouveau/core/subdev/device/nv40.c @@ -30,6 +30,7 @@ #include #include #include +#include int nv40_identify(struct nouveau_device *device) @@ -43,6 +44,7 @@ nv40_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; + device->oclass[NVDEV_SUBDEV_FB ] = &nv40_fb_oclass; break; case 0x41: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -52,6 +54,7 @@ nv40_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; + device->oclass[NVDEV_SUBDEV_FB ] = &nv40_fb_oclass; break; case 0x42: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -61,6 +64,7 @@ nv40_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; + device->oclass[NVDEV_SUBDEV_FB ] = &nv40_fb_oclass; break; case 0x43: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -70,6 +74,7 @@ nv40_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; + device->oclass[NVDEV_SUBDEV_FB ] = &nv40_fb_oclass; break; case 0x45: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -79,6 +84,7 @@ nv40_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; + device->oclass[NVDEV_SUBDEV_FB ] = &nv40_fb_oclass; break; case 0x47: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -88,6 +94,7 @@ nv40_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; + device->oclass[NVDEV_SUBDEV_FB ] = &nv40_fb_oclass; break; case 0x49: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -97,6 +104,7 @@ nv40_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; + device->oclass[NVDEV_SUBDEV_FB ] = &nv40_fb_oclass; break; case 0x4b: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -106,6 +114,7 @@ nv40_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; + device->oclass[NVDEV_SUBDEV_FB ] = &nv40_fb_oclass; break; case 0x44: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -115,6 +124,7 @@ nv40_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv44_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; + device->oclass[NVDEV_SUBDEV_FB ] = &nv40_fb_oclass; break; case 0x46: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -124,6 +134,7 @@ nv40_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv44_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; + device->oclass[NVDEV_SUBDEV_FB ] = &nv40_fb_oclass; break; case 0x4a: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -133,6 +144,7 @@ nv40_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv44_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; + device->oclass[NVDEV_SUBDEV_FB ] = &nv40_fb_oclass; break; case 0x4c: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -142,6 +154,7 @@ nv40_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv44_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; + device->oclass[NVDEV_SUBDEV_FB ] = &nv40_fb_oclass; break; case 0x4e: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -151,6 +164,7 @@ nv40_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv44_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; + device->oclass[NVDEV_SUBDEV_FB ] = &nv40_fb_oclass; break; case 0x63: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -160,6 +174,7 @@ nv40_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv44_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; + device->oclass[NVDEV_SUBDEV_FB ] = &nv40_fb_oclass; break; case 0x67: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -169,6 +184,7 @@ nv40_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv44_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; + device->oclass[NVDEV_SUBDEV_FB ] = &nv40_fb_oclass; break; case 0x68: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -178,6 +194,7 @@ nv40_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv44_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; + device->oclass[NVDEV_SUBDEV_FB ] = &nv40_fb_oclass; break; default: nv_fatal(device, "unknown Curie chipset\n"); diff --git a/drivers/gpu/drm/nouveau/core/subdev/device/nv50.c b/drivers/gpu/drm/nouveau/core/subdev/device/nv50.c index e844525d5694..e60cdf26ebf9 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/device/nv50.c +++ b/drivers/gpu/drm/nouveau/core/subdev/device/nv50.c @@ -30,6 +30,7 @@ #include #include #include +#include int nv50_identify(struct nouveau_device *device) @@ -43,6 +44,7 @@ nv50_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv50_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; + device->oclass[NVDEV_SUBDEV_FB ] = &nv50_fb_oclass; break; case 0x84: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -52,6 +54,7 @@ nv50_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv50_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; + device->oclass[NVDEV_SUBDEV_FB ] = &nv50_fb_oclass; break; case 0x86: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -61,6 +64,7 @@ nv50_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv50_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; + device->oclass[NVDEV_SUBDEV_FB ] = &nv50_fb_oclass; break; case 0x92: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -70,6 +74,7 @@ nv50_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv50_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; + device->oclass[NVDEV_SUBDEV_FB ] = &nv50_fb_oclass; break; case 0x94: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -79,6 +84,7 @@ nv50_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv50_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; + device->oclass[NVDEV_SUBDEV_FB ] = &nv50_fb_oclass; break; case 0x96: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -88,6 +94,7 @@ nv50_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv50_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; + device->oclass[NVDEV_SUBDEV_FB ] = &nv50_fb_oclass; break; case 0x98: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -97,6 +104,7 @@ nv50_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv98_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; + device->oclass[NVDEV_SUBDEV_FB ] = &nv50_fb_oclass; break; case 0xa0: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -106,6 +114,7 @@ nv50_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv98_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; + device->oclass[NVDEV_SUBDEV_FB ] = &nv50_fb_oclass; break; case 0xaa: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -115,6 +124,7 @@ nv50_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv98_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; + device->oclass[NVDEV_SUBDEV_FB ] = &nv50_fb_oclass; break; case 0xac: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -124,6 +134,7 @@ nv50_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv98_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; + device->oclass[NVDEV_SUBDEV_FB ] = &nv50_fb_oclass; break; case 0xa3: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -133,6 +144,7 @@ nv50_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv98_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; + device->oclass[NVDEV_SUBDEV_FB ] = &nv50_fb_oclass; break; case 0xa5: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -142,6 +154,7 @@ nv50_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv98_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; + device->oclass[NVDEV_SUBDEV_FB ] = &nv50_fb_oclass; break; case 0xa8: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -151,6 +164,7 @@ nv50_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv98_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; + device->oclass[NVDEV_SUBDEV_FB ] = &nv50_fb_oclass; break; case 0xaf: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -160,6 +174,7 @@ nv50_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv98_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; + device->oclass[NVDEV_SUBDEV_FB ] = &nv50_fb_oclass; break; default: nv_fatal(device, "unknown Tesla chipset\n"); diff --git a/drivers/gpu/drm/nouveau/core/subdev/device/nvc0.c b/drivers/gpu/drm/nouveau/core/subdev/device/nvc0.c index 56d1950c9b77..8de67307eea7 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/device/nvc0.c +++ b/drivers/gpu/drm/nouveau/core/subdev/device/nvc0.c @@ -30,6 +30,8 @@ #include #include #include +#include +#include int nvc0_identify(struct nouveau_device *device) @@ -43,6 +45,8 @@ nvc0_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nvc0_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; + device->oclass[NVDEV_SUBDEV_FB ] = &nvc0_fb_oclass; + device->oclass[NVDEV_SUBDEV_LTCG ] = &nvc0_ltcg_oclass; break; case 0xc4: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -52,6 +56,8 @@ nvc0_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nvc0_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; + device->oclass[NVDEV_SUBDEV_FB ] = &nvc0_fb_oclass; + device->oclass[NVDEV_SUBDEV_LTCG ] = &nvc0_ltcg_oclass; break; case 0xc3: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -61,6 +67,8 @@ nvc0_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nvc0_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; + device->oclass[NVDEV_SUBDEV_FB ] = &nvc0_fb_oclass; + device->oclass[NVDEV_SUBDEV_LTCG ] = &nvc0_ltcg_oclass; break; case 0xce: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -70,6 +78,8 @@ nvc0_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nvc0_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; + device->oclass[NVDEV_SUBDEV_FB ] = &nvc0_fb_oclass; + device->oclass[NVDEV_SUBDEV_LTCG ] = &nvc0_ltcg_oclass; break; case 0xcf: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -79,6 +89,8 @@ nvc0_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nvc0_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; + device->oclass[NVDEV_SUBDEV_FB ] = &nvc0_fb_oclass; + device->oclass[NVDEV_SUBDEV_LTCG ] = &nvc0_ltcg_oclass; break; case 0xc1: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -88,6 +100,8 @@ nvc0_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nvc0_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; + device->oclass[NVDEV_SUBDEV_FB ] = &nvc0_fb_oclass; + device->oclass[NVDEV_SUBDEV_LTCG ] = &nvc0_ltcg_oclass; break; case 0xc8: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -97,6 +111,8 @@ nvc0_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nvc0_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; + device->oclass[NVDEV_SUBDEV_FB ] = &nvc0_fb_oclass; + device->oclass[NVDEV_SUBDEV_LTCG ] = &nvc0_ltcg_oclass; break; case 0xd9: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -106,6 +122,8 @@ nvc0_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nvc0_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; + device->oclass[NVDEV_SUBDEV_FB ] = &nvc0_fb_oclass; + device->oclass[NVDEV_SUBDEV_LTCG ] = &nvc0_ltcg_oclass; break; default: nv_fatal(device, "unknown Fermi chipset\n"); diff --git a/drivers/gpu/drm/nouveau/core/subdev/device/nve0.c b/drivers/gpu/drm/nouveau/core/subdev/device/nve0.c index ab5e05291465..919a10280d7e 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/device/nve0.c +++ b/drivers/gpu/drm/nouveau/core/subdev/device/nve0.c @@ -30,6 +30,8 @@ #include #include #include +#include +#include int nve0_identify(struct nouveau_device *device) @@ -43,6 +45,8 @@ nve0_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nvc0_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; + device->oclass[NVDEV_SUBDEV_FB ] = &nvc0_fb_oclass; + device->oclass[NVDEV_SUBDEV_LTCG ] = &nvc0_ltcg_oclass; break; case 0xe7: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -52,6 +56,8 @@ nve0_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nvc0_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; + device->oclass[NVDEV_SUBDEV_FB ] = &nvc0_fb_oclass; + device->oclass[NVDEV_SUBDEV_LTCG ] = &nvc0_ltcg_oclass; break; default: nv_fatal(device, "unknown Kepler chipset\n"); diff --git a/drivers/gpu/drm/nouveau/core/subdev/fb/base.c b/drivers/gpu/drm/nouveau/core/subdev/fb/base.c new file mode 100644 index 000000000000..f0086de8af31 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/subdev/fb/base.c @@ -0,0 +1,130 @@ +/* + * Copyright 2012 Red Hat Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: Ben Skeggs + */ + +#include "subdev/fb.h" +#include "subdev/bios.h" +#include "subdev/bios/bit.h" + +int +nouveau_fb_bios_memtype(struct nouveau_bios *bios) +{ + struct bit_entry M; + u8 ramcfg; + + ramcfg = (nv_rd32(bios, 0x101000) & 0x0000003c) >> 2; + if (!bit_entry(bios, 'M', &M) && M.version == 2 && M.length >= 5) { + u16 table = nv_ro16(bios, M.offset + 3); + u8 version = nv_ro08(bios, table + 0); + u8 header = nv_ro08(bios, table + 1); + u8 record = nv_ro08(bios, table + 2); + u8 entries = nv_ro08(bios, table + 3); + if (table && version == 0x10 && ramcfg < entries) { + u16 entry = table + header + (ramcfg * record); + switch (nv_ro08(bios, entry) & 0x0f) { + case 0: return NV_MEM_TYPE_DDR2; + case 1: return NV_MEM_TYPE_DDR3; + case 2: return NV_MEM_TYPE_GDDR3; + case 3: return NV_MEM_TYPE_GDDR5; + default: + break; + } + + } + } + + return NV_MEM_TYPE_UNKNOWN; +} + +int +nouveau_fb_init(struct nouveau_fb *pfb) +{ + int ret, i; + + ret = nouveau_subdev_init(&pfb->base); + if (ret) + return ret; + + for (i = 0; i < pfb->tile.regions; i++) + pfb->tile.prog(pfb, i, &pfb->tile.region[i]); + + return 0; +} + +int +_nouveau_fb_init(struct nouveau_object *object) +{ + struct nouveau_fb *pfb = (void *)object; + return nouveau_fb_init(pfb); +} + +void +nouveau_fb_destroy(struct nouveau_fb *pfb) +{ + int i; + + for (i = 0; i < pfb->tile.regions; i++) + pfb->tile.fini(pfb, i, &pfb->tile.region[i]); + + if (pfb->tags.block_size) + nouveau_mm_fini(&pfb->tags); + + if (pfb->vram.block_size) + nouveau_mm_fini(&pfb->vram); + + nouveau_subdev_destroy(&pfb->base); +} + +void +_nouveau_fb_dtor(struct nouveau_object *object) +{ + struct nouveau_fb *pfb = (void *)object; + nouveau_fb_destroy(pfb); +} + +int +nouveau_fb_created(struct nouveau_fb *pfb) +{ + static const char *name[] = { + [NV_MEM_TYPE_UNKNOWN] = "unknown", + [NV_MEM_TYPE_STOLEN ] = "stolen system memory", + [NV_MEM_TYPE_SGRAM ] = "SGRAM", + [NV_MEM_TYPE_SDRAM ] = "SDRAM", + [NV_MEM_TYPE_DDR1 ] = "DDR1", + [NV_MEM_TYPE_DDR2 ] = "DDR2", + [NV_MEM_TYPE_DDR3 ] = "DDR3", + [NV_MEM_TYPE_GDDR2 ] = "GDDR2", + [NV_MEM_TYPE_GDDR3 ] = "GDDR3", + [NV_MEM_TYPE_GDDR4 ] = "GDDR4", + [NV_MEM_TYPE_GDDR5 ] = "GDDR5", + }; + + if (pfb->ram.size == 0) { + nv_fatal(pfb, "no vram detected!!\n"); + return -ERANGE; + } + + nv_info(pfb, "RAM type: %s\n", name[pfb->ram.type]); + nv_info(pfb, "RAM size: %d MiB\n", (int)(pfb->ram.size >> 20)); + return 0; +} diff --git a/drivers/gpu/drm/nouveau/core/subdev/fb/nv04.c b/drivers/gpu/drm/nouveau/core/subdev/fb/nv04.c index eef48440fbec..eb06836b69f7 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/fb/nv04.c +++ b/drivers/gpu/drm/nouveau/core/subdev/fb/nv04.c @@ -1,55 +1,130 @@ -#include "drmP.h" -#include "drm.h" -#include "nouveau_drv.h" -#include +/* + * Copyright 2012 Red Hat Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: Ben Skeggs + */ -int -nv04_fb_vram_init(struct drm_device *dev) +#include + +#define NV04_PFB_BOOT_0 0x00100000 +# define NV04_PFB_BOOT_0_RAM_AMOUNT 0x00000003 +# define NV04_PFB_BOOT_0_RAM_AMOUNT_32MB 0x00000000 +# define NV04_PFB_BOOT_0_RAM_AMOUNT_4MB 0x00000001 +# define NV04_PFB_BOOT_0_RAM_AMOUNT_8MB 0x00000002 +# define NV04_PFB_BOOT_0_RAM_AMOUNT_16MB 0x00000003 +# define NV04_PFB_BOOT_0_RAM_WIDTH_128 0x00000004 +# define NV04_PFB_BOOT_0_RAM_TYPE 0x00000028 +# define NV04_PFB_BOOT_0_RAM_TYPE_SGRAM_8MBIT 0x00000000 +# define NV04_PFB_BOOT_0_RAM_TYPE_SGRAM_16MBIT 0x00000008 +# define NV04_PFB_BOOT_0_RAM_TYPE_SGRAM_16MBIT_4BANK 0x00000010 +# define NV04_PFB_BOOT_0_RAM_TYPE_SDRAM_16MBIT 0x00000018 +# define NV04_PFB_BOOT_0_RAM_TYPE_SDRAM_64MBIT 0x00000020 +# define NV04_PFB_BOOT_0_RAM_TYPE_SDRAM_64MBITX16 0x00000028 +# define NV04_PFB_BOOT_0_UMA_ENABLE 0x00000100 +# define NV04_PFB_BOOT_0_UMA_SIZE 0x0000f000 +#define NV04_PFB_CFG0 0x00100200 + +struct nv04_fb_priv { + struct nouveau_fb base; +}; + +bool +nv04_fb_memtype_valid(struct nouveau_fb *pfb, u32 tile_flags) +{ + if (!(tile_flags & 0xff00)) + return true; + + return false; +} + +static int +nv04_fb_init(struct nouveau_object *object) { - struct drm_nouveau_private *dev_priv = dev->dev_private; - u32 boot0 = nv_rd32(dev, NV04_PFB_BOOT_0); + struct nv04_fb_priv *priv = (void *)object; + int ret; + + ret = nouveau_fb_init(&priv->base); + if (ret) + return ret; + + /* This is what the DDX did for NV_ARCH_04, but a mmio-trace shows + * nvidia reading PFB_CFG_0, then writing back its original value. + * (which was 0x701114 in this case) + */ + nv_wr32(priv, NV04_PFB_CFG0, 0x1114); + return 0; +} +static int +nv04_fb_ctor(struct nouveau_object *parent, struct nouveau_object *engine, + struct nouveau_oclass *oclass, void *data, u32 size, + struct nouveau_object **pobject) +{ + struct nv04_fb_priv *priv; + u32 boot0; + int ret; + + ret = nouveau_fb_create(parent, engine, oclass, &priv); + *pobject = nv_object(priv); + if (ret) + return ret; + + boot0 = nv_rd32(priv, NV04_PFB_BOOT_0); if (boot0 & 0x00000100) { - dev_priv->vram_size = ((boot0 >> 12) & 0xf) * 2 + 2; - dev_priv->vram_size *= 1024 * 1024; + priv->base.ram.size = ((boot0 >> 12) & 0xf) * 2 + 2; + priv->base.ram.size *= 1024 * 1024; } else { switch (boot0 & NV04_PFB_BOOT_0_RAM_AMOUNT) { case NV04_PFB_BOOT_0_RAM_AMOUNT_32MB: - dev_priv->vram_size = 32 * 1024 * 1024; + priv->base.ram.size = 32 * 1024 * 1024; break; case NV04_PFB_BOOT_0_RAM_AMOUNT_16MB: - dev_priv->vram_size = 16 * 1024 * 1024; + priv->base.ram.size = 16 * 1024 * 1024; break; case NV04_PFB_BOOT_0_RAM_AMOUNT_8MB: - dev_priv->vram_size = 8 * 1024 * 1024; + priv->base.ram.size = 8 * 1024 * 1024; break; case NV04_PFB_BOOT_0_RAM_AMOUNT_4MB: - dev_priv->vram_size = 4 * 1024 * 1024; + priv->base.ram.size = 4 * 1024 * 1024; break; } } if ((boot0 & 0x00000038) <= 0x10) - dev_priv->vram_type = NV_MEM_TYPE_SGRAM; + priv->base.ram.type = NV_MEM_TYPE_SGRAM; else - dev_priv->vram_type = NV_MEM_TYPE_SDRAM; + priv->base.ram.type = NV_MEM_TYPE_SDRAM; - return 0; -} - -int -nv04_fb_init(struct drm_device *dev) -{ - /* This is what the DDX did for NV_ARCH_04, but a mmio-trace shows - * nvidia reading PFB_CFG_0, then writing back its original value. - * (which was 0x701114 in this case) - */ - nv_wr32(dev, NV04_PFB_CFG0, 0x1114); - return 0; + priv->base.memtype_valid = nv04_fb_memtype_valid; + return nouveau_fb_created(&priv->base); } -void -nv04_fb_takedown(struct drm_device *dev) -{ -} +struct nouveau_oclass +nv04_fb_oclass = { + .handle = NV_SUBDEV(FB, 0x04), + .ofuncs = &(struct nouveau_ofuncs) { + .ctor = nv04_fb_ctor, + .dtor = _nouveau_fb_dtor, + .init = nv04_fb_init, + .fini = _nouveau_fb_fini, + }, +}; diff --git a/drivers/gpu/drm/nouveau/core/subdev/fb/nv10.c b/drivers/gpu/drm/nouveau/core/subdev/fb/nv10.c index 09af63b55f59..f037a422d2f4 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/fb/nv10.c +++ b/drivers/gpu/drm/nouveau/core/subdev/fb/nv10.c @@ -1,104 +1,120 @@ -#include "drmP.h" -#include "drm.h" -#include "nouveau_drv.h" -#include - -void -nv10_fb_init_tile_region(struct drm_device *dev, int i, uint32_t addr, - uint32_t size, uint32_t pitch, uint32_t flags) +/* + * Copyright (C) 2010 Francisco Jerez. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial + * portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ + +#include + +struct nv10_fb_priv { + struct nouveau_fb base; +}; + +static void +nv10_fb_tile_init(struct nouveau_fb *pfb, int i, u32 addr, u32 size, u32 pitch, + u32 flags, struct nouveau_fb_tile *tile) { - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_tile_reg *tile = &dev_priv->tile.reg[i]; - tile->addr = 0x80000000 | addr; tile->limit = max(1u, addr + size) - 1; tile->pitch = pitch; } -void -nv10_fb_free_tile_region(struct drm_device *dev, int i) +static void +nv10_fb_tile_fini(struct nouveau_fb *pfb, int i, struct nouveau_fb_tile *tile) { - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_tile_reg *tile = &dev_priv->tile.reg[i]; - - tile->addr = tile->limit = tile->pitch = tile->zcomp = 0; + tile->addr = 0; + tile->limit = 0; + tile->pitch = 0; + tile->zcomp = 0; } void -nv10_fb_set_tile_region(struct drm_device *dev, int i) +nv10_fb_tile_prog(struct nouveau_fb *pfb, int i, struct nouveau_fb_tile *tile) { - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_tile_reg *tile = &dev_priv->tile.reg[i]; - - nv_wr32(dev, NV10_PFB_TLIMIT(i), tile->limit); - nv_wr32(dev, NV10_PFB_TSIZE(i), tile->pitch); - nv_wr32(dev, NV10_PFB_TILE(i), tile->addr); + nv_wr32(pfb, 0x100244 + (i * 0x10), tile->limit); + nv_wr32(pfb, 0x100248 + (i * 0x10), tile->pitch); + nv_wr32(pfb, 0x100240 + (i * 0x10), tile->addr); } -int -nv1a_fb_vram_init(struct drm_device *dev) +static int +nv10_fb_ctor(struct nouveau_object *parent, struct nouveau_object *engine, + struct nouveau_oclass *oclass, void *data, u32 size, + struct nouveau_object **pobject) { - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct pci_dev *bridge; - uint32_t mem, mib; - - bridge = pci_get_bus_and_slot(0, PCI_DEVFN(0, 1)); - if (!bridge) { - NV_ERROR(dev, "no bridge device\n"); - return 0; - } - - if (dev_priv->chipset == 0x1a) { - pci_read_config_dword(bridge, 0x7c, &mem); - mib = ((mem >> 6) & 31) + 1; + struct nouveau_device *device = nv_device(parent); + struct nv10_fb_priv *priv; + int ret; + + ret = nouveau_fb_create(parent, engine, oclass, &priv); + *pobject = nv_object(priv); + if (ret) + return ret; + + if (device->chipset == 0x1a || device->chipset == 0x1f) { + struct pci_dev *bridge; + u32 mem, mib; + + bridge = pci_get_bus_and_slot(0, PCI_DEVFN(0, 1)); + if (!bridge) { + nv_fatal(device, "no bridge device\n"); + return 0; + } + + if (device->chipset == 0x1a) { + pci_read_config_dword(bridge, 0x7c, &mem); + mib = ((mem >> 6) & 31) + 1; + } else { + pci_read_config_dword(bridge, 0x84, &mem); + mib = ((mem >> 4) & 127) + 1; + } + + priv->base.ram.type = NV_MEM_TYPE_STOLEN; + priv->base.ram.size = mib * 1024 * 1024; } else { - pci_read_config_dword(bridge, 0x84, &mem); - mib = ((mem >> 4) & 127) + 1; - } + u32 cfg0 = nv_rd32(priv, 0x100200); + if (cfg0 & 0x00000001) + priv->base.ram.type = NV_MEM_TYPE_DDR1; + else + priv->base.ram.type = NV_MEM_TYPE_SDRAM; - dev_priv->vram_size = mib * 1024 * 1024; - return 0; -} - -int -nv10_fb_vram_init(struct drm_device *dev) -{ - struct drm_nouveau_private *dev_priv = dev->dev_private; - u32 fifo_data = nv_rd32(dev, NV04_PFB_FIFO_DATA); - u32 cfg0 = nv_rd32(dev, 0x100200); - - dev_priv->vram_size = fifo_data & NV10_PFB_FIFO_DATA_RAM_AMOUNT_MB_MASK; - - if (cfg0 & 0x00000001) - dev_priv->vram_type = NV_MEM_TYPE_DDR1; - else - dev_priv->vram_type = NV_MEM_TYPE_SDRAM; - - return 0; -} - -int -nv10_fb_init(struct drm_device *dev) -{ - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_fb_engine *pfb = &dev_priv->engine.fb; - int i; - - /* Turn all the tiling regions off. */ - pfb->num_tiles = NV10_PFB_TILE__SIZE; - for (i = 0; i < pfb->num_tiles; i++) - pfb->set_tile_region(dev, i); + priv->base.ram.size = nv_rd32(priv, 0x10020c) & 0xff000000; + } - return 0; + priv->base.memtype_valid = nv04_fb_memtype_valid; + priv->base.tile.regions = 8; + priv->base.tile.init = nv10_fb_tile_init; + priv->base.tile.fini = nv10_fb_tile_fini; + priv->base.tile.prog = nv10_fb_tile_prog; + return nouveau_fb_created(&priv->base); } -void -nv10_fb_takedown(struct drm_device *dev) -{ - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_fb_engine *pfb = &dev_priv->engine.fb; - int i; - - for (i = 0; i < pfb->num_tiles; i++) - pfb->free_tile_region(dev, i); -} +struct nouveau_oclass +nv10_fb_oclass = { + .handle = NV_SUBDEV(FB, 0x10), + .ofuncs = &(struct nouveau_ofuncs) { + .ctor = nv10_fb_ctor, + .dtor = _nouveau_fb_dtor, + .init = _nouveau_fb_init, + .fini = _nouveau_fb_fini, + }, +}; diff --git a/drivers/gpu/drm/nouveau/core/subdev/fb/nv20.c b/drivers/gpu/drm/nouveau/core/subdev/fb/nv20.c index a7f056c367e4..4b3578fcb7fb 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/fb/nv20.c +++ b/drivers/gpu/drm/nouveau/core/subdev/fb/nv20.c @@ -1,49 +1,41 @@ -#include "drmP.h" -#include "drm.h" -#include "nouveau_drv.h" -#include - -static struct drm_mm_node * -nv20_fb_alloc_tag(struct drm_device *dev, uint32_t size) -{ - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_fb_engine *pfb = &dev_priv->engine.fb; - struct drm_mm_node *mem; - int ret; - - ret = drm_mm_pre_get(&pfb->tag_heap); - if (ret) - return NULL; - - spin_lock(&dev_priv->tile.lock); - mem = drm_mm_search_free(&pfb->tag_heap, size, 0, 0); - if (mem) - mem = drm_mm_get_block_atomic(mem, size, 0); - spin_unlock(&dev_priv->tile.lock); - - return mem; -} +/* + * Copyright (C) 2010 Francisco Jerez. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial + * portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ + +#include + +struct nv20_fb_priv { + struct nouveau_fb base; +}; static void -nv20_fb_free_tag(struct drm_device *dev, struct drm_mm_node **pmem) +nv20_fb_tile_init(struct nouveau_fb *pfb, int i, u32 addr, u32 size, u32 pitch, + u32 flags, struct nouveau_fb_tile *tile) { - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct drm_mm_node *mem = *pmem; - if (mem) { - spin_lock(&dev_priv->tile.lock); - drm_mm_put_block(mem); - spin_unlock(&dev_priv->tile.lock); - *pmem = NULL; - } -} - -void -nv20_fb_init_tile_region(struct drm_device *dev, int i, uint32_t addr, - uint32_t size, uint32_t pitch, uint32_t flags) -{ - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_tile_reg *tile = &dev_priv->tile.reg[i]; - int bpp = (flags & NOUVEAU_GEM_TILE_32BPP ? 32 : 16); + struct nouveau_device *device = nv_device(pfb); + int bpp = (flags & 2) ? 32 : 16; tile->addr = 0x00000001 | addr; tile->limit = max(1u, addr + size) - 1; @@ -53,20 +45,20 @@ nv20_fb_init_tile_region(struct drm_device *dev, int i, uint32_t addr, * compression meta-data (most likely just a bitmap determining * if a given tile is compressed or not). */ - if (flags & NOUVEAU_GEM_TILE_ZETA) { - tile->tag_mem = nv20_fb_alloc_tag(dev, size / 256); - if (tile->tag_mem) { + size /= 256; + if (flags & 4) { + if (!nouveau_mm_head(&pfb->tags, 1, size, size, 1, &tile->tag)) { /* Enable Z compression */ - tile->zcomp = tile->tag_mem->start; - if (dev_priv->chipset >= 0x25) { + tile->zcomp = tile->tag->offset; + if (device->chipset >= 0x25) { if (bpp == 16) - tile->zcomp |= NV25_PFB_ZCOMP_MODE_16; + tile->zcomp |= 0x00100000; else - tile->zcomp |= NV25_PFB_ZCOMP_MODE_32; + tile->zcomp |= 0x00200000; } else { - tile->zcomp |= NV20_PFB_ZCOMP_EN; + tile->zcomp |= 0x80000000; if (bpp != 16) - tile->zcomp |= NV20_PFB_ZCOMP_MODE_32; + tile->zcomp |= 0x04000000; } } @@ -74,75 +66,71 @@ nv20_fb_init_tile_region(struct drm_device *dev, int i, uint32_t addr, } } -void -nv20_fb_free_tile_region(struct drm_device *dev, int i) +static void +nv20_fb_tile_fini(struct nouveau_fb *pfb, int i, struct nouveau_fb_tile *tile) { - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_tile_reg *tile = &dev_priv->tile.reg[i]; - - tile->addr = tile->limit = tile->pitch = tile->zcomp = 0; - nv20_fb_free_tag(dev, &tile->tag_mem); + tile->addr = 0; + tile->limit = 0; + tile->pitch = 0; + tile->zcomp = 0; + nouveau_mm_free(&pfb->tags, &tile->tag); } -void -nv20_fb_set_tile_region(struct drm_device *dev, int i) +static void +nv20_fb_tile_prog(struct nouveau_fb *pfb, int i, struct nouveau_fb_tile *tile) { - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_tile_reg *tile = &dev_priv->tile.reg[i]; - - nv_wr32(dev, NV10_PFB_TLIMIT(i), tile->limit); - nv_wr32(dev, NV10_PFB_TSIZE(i), tile->pitch); - nv_wr32(dev, NV10_PFB_TILE(i), tile->addr); - nv_wr32(dev, NV20_PFB_ZCOMP(i), tile->zcomp); + nv_wr32(pfb, 0x100244 + (i * 0x10), tile->limit); + nv_wr32(pfb, 0x100248 + (i * 0x10), tile->pitch); + nv_wr32(pfb, 0x100240 + (i * 0x10), tile->addr); + nv_wr32(pfb, 0x100300 + (i * 0x04), tile->zcomp); } -int -nv20_fb_vram_init(struct drm_device *dev) +static int +nv20_fb_ctor(struct nouveau_object *parent, struct nouveau_object *engine, + struct nouveau_oclass *oclass, void *data, u32 size, + struct nouveau_object **pobject) { - struct drm_nouveau_private *dev_priv = dev->dev_private; - u32 mem_size = nv_rd32(dev, 0x10020c); - u32 pbus1218 = nv_rd32(dev, 0x001218); + struct nouveau_device *device = nv_device(parent); + struct nv20_fb_priv *priv; + u32 pbus1218; + int ret; + + ret = nouveau_fb_create(parent, engine, oclass, &priv); + *pobject = nv_object(priv); + if (ret) + return ret; - dev_priv->vram_size = mem_size & 0xff000000; + pbus1218 = nv_rd32(priv, 0x001218); switch (pbus1218 & 0x00000300) { - case 0x00000000: dev_priv->vram_type = NV_MEM_TYPE_SDRAM; break; - case 0x00000100: dev_priv->vram_type = NV_MEM_TYPE_DDR1; break; - case 0x00000200: dev_priv->vram_type = NV_MEM_TYPE_GDDR3; break; - case 0x00000300: dev_priv->vram_type = NV_MEM_TYPE_GDDR2; break; + case 0x00000000: priv->base.ram.type = NV_MEM_TYPE_SDRAM; break; + case 0x00000100: priv->base.ram.type = NV_MEM_TYPE_DDR1; break; + case 0x00000200: priv->base.ram.type = NV_MEM_TYPE_GDDR3; break; + case 0x00000300: priv->base.ram.type = NV_MEM_TYPE_GDDR2; break; } + priv->base.ram.size = nv_rd32(priv, 0x10020c) & 0xff000000; - return 0; -} - -int -nv20_fb_init(struct drm_device *dev) -{ - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_fb_engine *pfb = &dev_priv->engine.fb; - int i; - - if (dev_priv->chipset >= 0x25) - drm_mm_init(&pfb->tag_heap, 0, 64 * 1024); + if (device->chipset >= 0x25) + ret = nouveau_mm_init(&priv->base.tags, 0, 64 * 1024, 1); else - drm_mm_init(&pfb->tag_heap, 0, 32 * 1024); - - /* Turn all the tiling regions off. */ - pfb->num_tiles = NV10_PFB_TILE__SIZE; - for (i = 0; i < pfb->num_tiles; i++) - pfb->set_tile_region(dev, i); - - return 0; + ret = nouveau_mm_init(&priv->base.tags, 0, 32 * 1024, 1); + if (ret) + return ret; + + priv->base.memtype_valid = nv04_fb_memtype_valid; + priv->base.tile.regions = 8; + priv->base.tile.init = nv20_fb_tile_init; + priv->base.tile.fini = nv20_fb_tile_fini; + priv->base.tile.prog = nv20_fb_tile_prog; + return nouveau_fb_created(&priv->base); } -void -nv20_fb_takedown(struct drm_device *dev) -{ - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_fb_engine *pfb = &dev_priv->engine.fb; - int i; - - for (i = 0; i < pfb->num_tiles; i++) - pfb->free_tile_region(dev, i); - - drm_mm_takedown(&pfb->tag_heap); -} +struct nouveau_oclass +nv20_fb_oclass = { + .handle = NV_SUBDEV(FB, 0x20), + .ofuncs = &(struct nouveau_ofuncs) { + .ctor = nv20_fb_ctor, + .dtor = _nouveau_fb_dtor, + .init = _nouveau_fb_init, + .fini = _nouveau_fb_fini, + }, +}; diff --git a/drivers/gpu/drm/nouveau/core/subdev/fb/nv30.c b/drivers/gpu/drm/nouveau/core/subdev/fb/nv30.c index 30639a065273..cba67bc91390 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/fb/nv30.c +++ b/drivers/gpu/drm/nouveau/core/subdev/fb/nv30.c @@ -24,50 +24,47 @@ * */ -#include "drmP.h" -#include "drm.h" -#include "nouveau_drv.h" -#include +#include + +struct nv30_fb_priv { + struct nouveau_fb base; +}; void -nv30_fb_init_tile_region(struct drm_device *dev, int i, uint32_t addr, - uint32_t size, uint32_t pitch, uint32_t flags) +nv30_fb_tile_init(struct nouveau_fb *pfb, int i, u32 addr, u32 size, u32 pitch, + u32 flags, struct nouveau_fb_tile *tile) { - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_tile_reg *tile = &dev_priv->tile.reg[i]; - tile->addr = addr | 1; tile->limit = max(1u, addr + size) - 1; tile->pitch = pitch; } void -nv30_fb_free_tile_region(struct drm_device *dev, int i) +nv30_fb_tile_fini(struct nouveau_fb *pfb, int i, struct nouveau_fb_tile *tile) { - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_tile_reg *tile = &dev_priv->tile.reg[i]; - - tile->addr = tile->limit = tile->pitch = 0; + tile->addr = 0; + tile->limit = 0; + tile->pitch = 0; } static int -calc_bias(struct drm_device *dev, int k, int i, int j) +calc_bias(struct nv30_fb_priv *priv, int k, int i, int j) { - struct drm_nouveau_private *dev_priv = dev->dev_private; - int b = (dev_priv->chipset > 0x30 ? - nv_rd32(dev, 0x122c + 0x10 * k + 0x4 * j) >> (4 * (i ^ 1)) : + struct nouveau_device *device = nv_device(priv); + int b = (device->chipset > 0x30 ? + nv_rd32(priv, 0x122c + 0x10 * k + 0x4 * j) >> (4 * (i ^ 1)) : 0) & 0xf; return 2 * (b & 0x8 ? b - 0x10 : b); } static int -calc_ref(struct drm_device *dev, int l, int k, int i) +calc_ref(struct nv30_fb_priv *priv, int l, int k, int i) { int j, x = 0; for (j = 0; j < 4; j++) { - int m = (l >> (8 * i) & 0xff) + calc_bias(dev, k, i, j); + int m = (l >> (8 * i) & 0xff) + calc_bias(priv, k, i, j); x |= (0x80 | clamp(m, 0, 0x1f)) << (8 * j); } @@ -75,42 +72,77 @@ calc_ref(struct drm_device *dev, int l, int k, int i) return x; } -int -nv30_fb_init(struct drm_device *dev) +static int +nv30_fb_init(struct nouveau_object *object) { - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_fb_engine *pfb = &dev_priv->engine.fb; - int i, j; - - pfb->num_tiles = NV10_PFB_TILE__SIZE; + struct nouveau_device *device = nv_device(object); + struct nv30_fb_priv *priv = (void *)object; + int ret, i, j; - /* Turn all the tiling regions off. */ - for (i = 0; i < pfb->num_tiles; i++) - pfb->set_tile_region(dev, i); + ret = nouveau_fb_init(&priv->base); + if (ret) + return ret; /* Init the memory timing regs at 0x10037c/0x1003ac */ - if (dev_priv->chipset == 0x30 || - dev_priv->chipset == 0x31 || - dev_priv->chipset == 0x35) { + if (device->chipset == 0x30 || + device->chipset == 0x31 || + device->chipset == 0x35) { /* Related to ROP count */ - int n = (dev_priv->chipset == 0x31 ? 2 : 4); - int l = nv_rd32(dev, 0x1003d0); + int n = (device->chipset == 0x31 ? 2 : 4); + int l = nv_rd32(priv, 0x1003d0); for (i = 0; i < n; i++) { for (j = 0; j < 3; j++) - nv_wr32(dev, 0x10037c + 0xc * i + 0x4 * j, - calc_ref(dev, l, 0, j)); + nv_wr32(priv, 0x10037c + 0xc * i + 0x4 * j, + calc_ref(priv, l, 0, j)); for (j = 0; j < 2; j++) - nv_wr32(dev, 0x1003ac + 0x8 * i + 0x4 * j, - calc_ref(dev, l, 1, j)); + nv_wr32(priv, 0x1003ac + 0x8 * i + 0x4 * j, + calc_ref(priv, l, 1, j)); } } return 0; } -void -nv30_fb_takedown(struct drm_device *dev) +static int +nv30_fb_ctor(struct nouveau_object *parent, struct nouveau_object *engine, + struct nouveau_oclass *oclass, void *data, u32 size, + struct nouveau_object **pobject) { + struct nv30_fb_priv *priv; + u32 pbus1218; + int ret; + + ret = nouveau_fb_create(parent, engine, oclass, &priv); + *pobject = nv_object(priv); + if (ret) + return ret; + + pbus1218 = nv_rd32(priv, 0x001218); + switch (pbus1218 & 0x00000300) { + case 0x00000000: priv->base.ram.type = NV_MEM_TYPE_SDRAM; break; + case 0x00000100: priv->base.ram.type = NV_MEM_TYPE_DDR1; break; + case 0x00000200: priv->base.ram.type = NV_MEM_TYPE_GDDR3; break; + case 0x00000300: priv->base.ram.type = NV_MEM_TYPE_GDDR2; break; + } + priv->base.ram.size = nv_rd32(priv, 0x10020c) & 0xff000000; + + priv->base.memtype_valid = nv04_fb_memtype_valid; + priv->base.tile.regions = 8; + priv->base.tile.init = nv30_fb_tile_init; + priv->base.tile.fini = nv30_fb_tile_fini; + priv->base.tile.prog = nv10_fb_tile_prog; + return nouveau_fb_created(&priv->base); } + +struct nouveau_oclass +nv30_fb_oclass = { + .handle = NV_SUBDEV(FB, 0x30), + .ofuncs = &(struct nouveau_ofuncs) { + .ctor = nv30_fb_ctor, + .dtor = _nouveau_fb_dtor, + .init = nv30_fb_init, + .fini = _nouveau_fb_fini, + }, +}; diff --git a/drivers/gpu/drm/nouveau/core/subdev/fb/nv40.c b/drivers/gpu/drm/nouveau/core/subdev/fb/nv40.c index e08c2e1c8f1f..84aa71c47128 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/fb/nv40.c +++ b/drivers/gpu/drm/nouveau/core/subdev/fb/nv40.c @@ -1,55 +1,83 @@ -#include "drmP.h" -#include "drm.h" -#include "nouveau_drv.h" -#include - -void -nv40_fb_set_tile_region(struct drm_device *dev, int i) +/* + * Copyright (C) 2010 Francisco Jerez. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial + * portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ + +#include + +struct nv40_fb_priv { + struct nouveau_fb base; +}; + +static inline int +nv44_graph_class(struct nouveau_device *device) { - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_tile_reg *tile = &dev_priv->tile.reg[i]; + if ((device->chipset & 0xf0) == 0x60) + return 1; - switch (dev_priv->chipset) { - case 0x40: - nv_wr32(dev, NV10_PFB_TLIMIT(i), tile->limit); - nv_wr32(dev, NV10_PFB_TSIZE(i), tile->pitch); - nv_wr32(dev, NV10_PFB_TILE(i), tile->addr); - break; + return !(0x0baf & (1 << (device->chipset & 0x0f))); +} - default: - nv_wr32(dev, NV40_PFB_TLIMIT(i), tile->limit); - nv_wr32(dev, NV40_PFB_TSIZE(i), tile->pitch); - nv_wr32(dev, NV40_PFB_TILE(i), tile->addr); - break; - } +static void +nv40_fb_tile_prog(struct nouveau_fb *pfb, int i, struct nouveau_fb_tile *tile) +{ + nv_wr32(pfb, 0x100604 + (i * 0x10), tile->limit); + nv_wr32(pfb, 0x100608 + (i * 0x10), tile->pitch); + nv_wr32(pfb, 0x100600 + (i * 0x10), tile->addr); } static void -nv40_fb_init_gart(struct drm_device *dev) +nv40_fb_init_gart(struct nv40_fb_priv *priv) { - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_gpuobj *gart = dev_priv->gart_info.sg_ctxdma; +#if 0 + struct nouveau_gpuobj *gart = ndev->gart_info.sg_ctxdma; - if (dev_priv->gart_info.type != NOUVEAU_GART_HW) { - nv_wr32(dev, 0x100800, 0x00000001); + if (ndev->gart_info.type != NOUVEAU_GART_HW) { +#endif + nv_wr32(priv, 0x100800, 0x00000001); +#if 0 return; } - nv_wr32(dev, 0x100800, gart->pinst | 0x00000002); - nv_mask(dev, 0x10008c, 0x00000100, 0x00000100); - nv_wr32(dev, 0x100820, 0x00000000); + nv_wr32(ndev, 0x100800, gart->pinst | 0x00000002); + nv_mask(ndev, 0x10008c, 0x00000100, 0x00000100); + nv_wr32(ndev, 0x100820, 0x00000000); +#endif } static void -nv44_fb_init_gart(struct drm_device *dev) +nv44_fb_init_gart(struct nv40_fb_priv *priv) { - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_gpuobj *gart = dev_priv->gart_info.sg_ctxdma; +#if 0 + struct nouveau_gpuobj *gart = ndev->gart_info.sg_ctxdma; u32 vinst; - if (dev_priv->gart_info.type != NOUVEAU_GART_HW) { - nv_wr32(dev, 0x100850, 0x80000000); - nv_wr32(dev, 0x100800, 0x00000001); + if (ndev->gart_info.type != NOUVEAU_GART_HW) { +#endif + nv_wr32(priv, 0x100850, 0x80000000); + nv_wr32(priv, 0x100800, 0x00000001); +#if 0 return; } @@ -57,24 +85,60 @@ nv44_fb_init_gart(struct drm_device *dev) * must be allocated on 512KiB alignment, and not exceed * a total size of 512KiB for this to work correctly */ - vinst = nv_rd32(dev, 0x10020c); + vinst = nv_rd32(ndev, 0x10020c); vinst -= ((gart->pinst >> 19) + 1) << 19; - nv_wr32(dev, 0x100850, 0x80000000); - nv_wr32(dev, 0x100818, dev_priv->gart_info.dummy.addr); + nv_wr32(ndev, 0x100850, 0x80000000); + nv_wr32(ndev, 0x100818, ndev->gart_info.dummy.addr); + + nv_wr32(ndev, 0x100804, ndev->gart_info.aper_size); + nv_wr32(ndev, 0x100850, 0x00008000); + nv_mask(ndev, 0x10008c, 0x00000200, 0x00000200); + nv_wr32(ndev, 0x100820, 0x00000000); + nv_wr32(ndev, 0x10082c, 0x00000001); + nv_wr32(ndev, 0x100800, vinst | 0x00000010); +#endif +} + +static int +nv40_fb_init(struct nouveau_object *object) +{ + struct nv40_fb_priv *priv = (void *)object; + int ret; + + ret = nouveau_fb_init(&priv->base); + if (ret) + return ret; + + switch (nv_device(priv)->chipset) { + case 0x40: + case 0x45: + nv_mask(priv, 0x10033c, 0x00008000, 0x00000000); + break; + default: + if (nv44_graph_class(nv_device(priv))) + nv44_fb_init_gart(priv); + else + nv40_fb_init_gart(priv); + break; + } - nv_wr32(dev, 0x100804, dev_priv->gart_info.aper_size); - nv_wr32(dev, 0x100850, 0x00008000); - nv_mask(dev, 0x10008c, 0x00000200, 0x00000200); - nv_wr32(dev, 0x100820, 0x00000000); - nv_wr32(dev, 0x10082c, 0x00000001); - nv_wr32(dev, 0x100800, vinst | 0x00000010); + return 0; } -int -nv40_fb_vram_init(struct drm_device *dev) +static int +nv40_fb_ctor(struct nouveau_object *parent, struct nouveau_object *engine, + struct nouveau_oclass *oclass, void *data, u32 size, + struct nouveau_object **pobject) { - struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_device *device = nv_device(parent); + struct nv40_fb_priv *priv; + int ret; + + ret = nouveau_fb_create(parent, engine, oclass, &priv); + *pobject = nv_object(priv); + if (ret) + return ret; /* 0x001218 is actually present on a few other NV4X I looked at, * and even contains sane values matching 0x100474. From looking @@ -82,82 +146,73 @@ nv40_fb_vram_init(struct drm_device *dev) * So, I chose to use the same regs I've seen NVIDIA reading around * the memory detection, hopefully that'll get us the right numbers */ - if (dev_priv->chipset == 0x40) { - u32 pbus1218 = nv_rd32(dev, 0x001218); + if (device->chipset == 0x40) { + u32 pbus1218 = nv_rd32(priv, 0x001218); switch (pbus1218 & 0x00000300) { - case 0x00000000: dev_priv->vram_type = NV_MEM_TYPE_SDRAM; break; - case 0x00000100: dev_priv->vram_type = NV_MEM_TYPE_DDR1; break; - case 0x00000200: dev_priv->vram_type = NV_MEM_TYPE_GDDR3; break; - case 0x00000300: dev_priv->vram_type = NV_MEM_TYPE_DDR2; break; + case 0x00000000: priv->base.ram.type = NV_MEM_TYPE_SDRAM; break; + case 0x00000100: priv->base.ram.type = NV_MEM_TYPE_DDR1; break; + case 0x00000200: priv->base.ram.type = NV_MEM_TYPE_GDDR3; break; + case 0x00000300: priv->base.ram.type = NV_MEM_TYPE_DDR2; break; } } else - if (dev_priv->chipset == 0x49 || dev_priv->chipset == 0x4b) { - u32 pfb914 = nv_rd32(dev, 0x100914); + if (device->chipset == 0x49 || device->chipset == 0x4b) { + u32 pfb914 = nv_rd32(priv, 0x100914); switch (pfb914 & 0x00000003) { - case 0x00000000: dev_priv->vram_type = NV_MEM_TYPE_DDR1; break; - case 0x00000001: dev_priv->vram_type = NV_MEM_TYPE_DDR2; break; - case 0x00000002: dev_priv->vram_type = NV_MEM_TYPE_GDDR3; break; + case 0x00000000: priv->base.ram.type = NV_MEM_TYPE_DDR1; break; + case 0x00000001: priv->base.ram.type = NV_MEM_TYPE_DDR2; break; + case 0x00000002: priv->base.ram.type = NV_MEM_TYPE_GDDR3; break; case 0x00000003: break; } } else - if (dev_priv->chipset != 0x4e) { - u32 pfb474 = nv_rd32(dev, 0x100474); + if (device->chipset != 0x4e) { + u32 pfb474 = nv_rd32(priv, 0x100474); if (pfb474 & 0x00000004) - dev_priv->vram_type = NV_MEM_TYPE_GDDR3; + priv->base.ram.type = NV_MEM_TYPE_GDDR3; if (pfb474 & 0x00000002) - dev_priv->vram_type = NV_MEM_TYPE_DDR2; + priv->base.ram.type = NV_MEM_TYPE_DDR2; if (pfb474 & 0x00000001) - dev_priv->vram_type = NV_MEM_TYPE_DDR1; + priv->base.ram.type = NV_MEM_TYPE_DDR1; } else { - dev_priv->vram_type = NV_MEM_TYPE_STOLEN; + priv->base.ram.type = NV_MEM_TYPE_STOLEN; } - dev_priv->vram_size = nv_rd32(dev, 0x10020c) & 0xff000000; - return 0; -} - -int -nv40_fb_init(struct drm_device *dev) -{ - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_fb_engine *pfb = &dev_priv->engine.fb; - uint32_t tmp; - int i; - - if (dev_priv->chipset != 0x40 && dev_priv->chipset != 0x45) { - if (nv44_graph_class(dev)) - nv44_fb_init_gart(dev); - else - nv40_fb_init_gart(dev); - } + priv->base.ram.size = nv_rd32(priv, 0x10020c) & 0xff000000; - switch (dev_priv->chipset) { + priv->base.memtype_valid = nv04_fb_memtype_valid; + switch (device->chipset) { case 0x40: case 0x45: - tmp = nv_rd32(dev, NV10_PFB_CLOSE_PAGE2); - nv_wr32(dev, NV10_PFB_CLOSE_PAGE2, tmp & ~(1 << 15)); - pfb->num_tiles = NV10_PFB_TILE__SIZE; + priv->base.tile.regions = 8; break; - case 0x46: /* G72 */ - case 0x47: /* G70 */ - case 0x49: /* G71 */ - case 0x4b: /* G73 */ - case 0x4c: /* C51 (G7X version) */ - pfb->num_tiles = NV40_PFB_TILE__SIZE_1; + case 0x46: + case 0x47: + case 0x49: + case 0x4b: + case 0x4c: + priv->base.tile.regions = 15; break; default: - pfb->num_tiles = NV40_PFB_TILE__SIZE_0; + priv->base.tile.regions = 12; break; } - - /* Turn all the tiling regions off. */ - for (i = 0; i < pfb->num_tiles; i++) - pfb->set_tile_region(dev, i); - - return 0; + priv->base.tile.init = nv30_fb_tile_init; + priv->base.tile.fini = nv30_fb_tile_fini; + if (device->chipset == 0x40) + priv->base.tile.prog = nv10_fb_tile_prog; + else + priv->base.tile.prog = nv40_fb_tile_prog; + + return nouveau_fb_created(&priv->base); } -void -nv40_fb_takedown(struct drm_device *dev) -{ -} + +struct nouveau_oclass +nv40_fb_oclass = { + .handle = NV_SUBDEV(FB, 0x40), + .ofuncs = &(struct nouveau_ofuncs) { + .ctor = nv40_fb_ctor, + .dtor = _nouveau_fb_dtor, + .init = nv40_fb_init, + .fini = _nouveau_fb_fini, + }, +}; diff --git a/drivers/gpu/drm/nouveau/core/subdev/fb/nv50.c b/drivers/gpu/drm/nouveau/core/subdev/fb/nv50.c index a145b1c81ecb..eaf18fb2c306 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/fb/nv50.c +++ b/drivers/gpu/drm/nouveau/core/subdev/fb/nv50.c @@ -1,119 +1,335 @@ -#include "drmP.h" -#include "drm.h" -#include "nouveau_drv.h" -#include -#include +/* + * Copyright 2012 Red Hat Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: Ben Skeggs + */ + +#include +#include + +#include +#include struct nv50_fb_priv { + struct nouveau_fb base; struct page *r100c08_page; dma_addr_t r100c08; }; -static void -nv50_fb_destroy(struct drm_device *dev) +static int types[0x80] = { + 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 0, 0, 0, 0, 2, 2, 2, 2, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 0, 2, 2, 2, 2, 2, 2, 2, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 0, 0, + 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 2, 2, 2, 2, + 1, 0, 2, 0, 1, 0, 2, 0, 1, 1, 2, 2, 1, 1, 0, 0 +}; + +static bool +nv50_fb_memtype_valid(struct nouveau_fb *pfb, u32 memtype) { - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_fb_engine *pfb = &dev_priv->engine.fb; - struct nv50_fb_priv *priv = pfb->priv; + return types[(memtype & 0xff00) >> 8] != 0; +} - if (drm_mm_initialized(&pfb->tag_heap)) - drm_mm_takedown(&pfb->tag_heap); +static int +nv50_fb_vram_new(struct nouveau_fb *pfb, u64 size, u32 align, u32 ncmin, + u32 memtype, struct nouveau_mem **pmem) +{ + struct nv50_fb_priv *priv = (void *)pfb; + struct nouveau_mm *heap = &priv->base.vram; + struct nouveau_mm *tags = &priv->base.tags; + struct nouveau_mm_node *r; + struct nouveau_mem *mem; + int comp = (memtype & 0x300) >> 8; + int type = (memtype & 0x07f); + int back = (memtype & 0x800); + int min, max, ret; + + max = (size >> 12); + min = ncmin ? (ncmin >> 12) : max; + align >>= 12; + + mem = kzalloc(sizeof(*mem), GFP_KERNEL); + if (!mem) + return -ENOMEM; - if (priv->r100c08_page) { - pci_unmap_page(dev->pdev, priv->r100c08, PAGE_SIZE, - PCI_DMA_BIDIRECTIONAL); - __free_page(priv->r100c08_page); + mutex_lock(&pfb->base.mutex); + if (comp) { + if (align == 16) { + int n = (max >> 4) * comp; + + ret = nouveau_mm_head(tags, 1, n, n, 1, &mem->tag); + if (ret) + mem->tag = NULL; + } + + if (unlikely(!mem->tag)) + comp = 0; } - kfree(priv); - pfb->priv = NULL; + INIT_LIST_HEAD(&mem->regions); + mem->memtype = (comp << 7) | type; + mem->size = max; + + type = types[type]; + do { + if (back) + ret = nouveau_mm_tail(heap, type, max, min, align, &r); + else + ret = nouveau_mm_head(heap, type, max, min, align, &r); + if (ret) { + mutex_unlock(&pfb->base.mutex); + pfb->ram.put(pfb, &mem); + return ret; + } + + list_add_tail(&r->rl_entry, &mem->regions); + max -= r->length; + } while (max); + mutex_unlock(&pfb->base.mutex); + + r = list_first_entry(&mem->regions, struct nouveau_mm_node, rl_entry); + mem->offset = (u64)r->offset << 12; + *pmem = mem; + return 0; } -static int -nv50_fb_create(struct drm_device *dev) +void +nv50_fb_vram_del(struct nouveau_fb *pfb, struct nouveau_mem **pmem) { - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_fb_engine *pfb = &dev_priv->engine.fb; - struct nv50_fb_priv *priv; - u32 tagmem; - int ret; + struct nv50_fb_priv *priv = (void *)pfb; + struct nouveau_mm_node *this; + struct nouveau_mem *mem; - priv = kzalloc(sizeof(*priv), GFP_KERNEL); - if (!priv) - return -ENOMEM; - pfb->priv = priv; + mem = *pmem; + *pmem = NULL; + if (unlikely(mem == NULL)) + return; - priv->r100c08_page = alloc_page(GFP_KERNEL | __GFP_ZERO); - if (!priv->r100c08_page) { - nv50_fb_destroy(dev); - return -ENOMEM; + mutex_lock(&pfb->base.mutex); + while (!list_empty(&mem->regions)) { + this = list_first_entry(&mem->regions, typeof(*this), rl_entry); + + list_del(&this->rl_entry); + nouveau_mm_free(&priv->base.vram, &this); } - priv->r100c08 = pci_map_page(dev->pdev, priv->r100c08_page, 0, - PAGE_SIZE, PCI_DMA_BIDIRECTIONAL); - if (pci_dma_mapping_error(dev->pdev, priv->r100c08)) { - nv50_fb_destroy(dev); - return -EFAULT; + nouveau_mm_free(&priv->base.tags, &mem->tag); + mutex_unlock(&pfb->base.mutex); + + kfree(mem); +} + +static u32 +nv50_vram_rblock(struct nv50_fb_priv *priv) +{ + int i, parts, colbits, rowbitsa, rowbitsb, banks; + u64 rowsize, predicted; + u32 r0, r4, rt, ru, rblock_size; + + r0 = nv_rd32(priv, 0x100200); + r4 = nv_rd32(priv, 0x100204); + rt = nv_rd32(priv, 0x100250); + ru = nv_rd32(priv, 0x001540); + nv_debug(priv, "memcfg 0x%08x 0x%08x 0x%08x 0x%08x\n", r0, r4, rt, ru); + + for (i = 0, parts = 0; i < 8; i++) { + if (ru & (0x00010000 << i)) + parts++; } - tagmem = nv_rd32(dev, 0x100320); - NV_DEBUG(dev, "%d tags available\n", tagmem); - ret = drm_mm_init(&pfb->tag_heap, 0, tagmem); - if (ret) { - nv50_fb_destroy(dev); - return ret; + colbits = (r4 & 0x0000f000) >> 12; + rowbitsa = ((r4 & 0x000f0000) >> 16) + 8; + rowbitsb = ((r4 & 0x00f00000) >> 20) + 8; + banks = 1 << (((r4 & 0x03000000) >> 24) + 2); + + rowsize = parts * banks * (1 << colbits) * 8; + predicted = rowsize << rowbitsa; + if (r0 & 0x00000004) + predicted += rowsize << rowbitsb; + + if (predicted != priv->base.ram.size) { + nv_warn(priv, "memory controller reports %d MiB VRAM\n", + (u32)(priv->base.ram.size >> 20)); } - return 0; + rblock_size = rowsize; + if (rt & 1) + rblock_size *= 3; + + nv_debug(priv, "rblock %d bytes\n", rblock_size); + return rblock_size; } -int -nv50_fb_init(struct drm_device *dev) +static int +nv50_fb_ctor(struct nouveau_object *parent, struct nouveau_object *engine, + struct nouveau_oclass *oclass, void *data, u32 size, + struct nouveau_object **pobject) { - struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_device *device = nv_device(parent); + struct nouveau_bios *bios = nouveau_bios(device); + const u32 rsvd_head = ( 256 * 1024) >> 12; /* vga memory */ + const u32 rsvd_tail = (1024 * 1024) >> 12; /* vbios etc */ struct nv50_fb_priv *priv; + u32 tags; int ret; - if (!dev_priv->engine.fb.priv) { - ret = nv50_fb_create(dev); + ret = nouveau_fb_create(parent, engine, oclass, &priv); + *pobject = nv_object(priv); + if (ret) + return ret; + + switch (nv_rd32(priv, 0x100714) & 0x00000007) { + case 0: priv->base.ram.type = NV_MEM_TYPE_DDR1; break; + case 1: + if (nouveau_fb_bios_memtype(bios) == NV_MEM_TYPE_DDR3) + priv->base.ram.type = NV_MEM_TYPE_DDR3; + else + priv->base.ram.type = NV_MEM_TYPE_DDR2; + break; + case 2: priv->base.ram.type = NV_MEM_TYPE_GDDR3; break; + case 3: priv->base.ram.type = NV_MEM_TYPE_GDDR4; break; + case 4: priv->base.ram.type = NV_MEM_TYPE_GDDR5; break; + default: + break; + } + + priv->base.ram.size = nv_rd32(priv, 0x10020c); + priv->base.ram.size = (priv->base.ram.size & 0xffffff00) | + ((priv->base.ram.size & 0x000000ff) << 32); + + tags = nv_rd32(priv, 0x100320); + if (tags) { + ret = nouveau_mm_init(&priv->base.tags, 0, tags, 1); if (ret) return ret; + + nv_debug(priv, "%d compression tags\n", tags); + } + + size = (priv->base.ram.size >> 12) - rsvd_head - rsvd_tail; + switch (device->chipset) { + case 0xaa: + case 0xac: + case 0xaf: /* IGPs, no reordering, no real VRAM */ + ret = nouveau_mm_init(&priv->base.vram, rsvd_head, size, 1); + if (ret) + return ret; + + priv->base.ram.stolen = (u64)nv_rd32(priv, 0x100e10) << 12; + break; + default: + ret = nouveau_mm_init(&priv->base.vram, rsvd_head, size, + nv50_vram_rblock(priv) >> 12); + if (ret) + return ret; + + priv->base.ram.ranks = (nv_rd32(priv, 0x100200) & 0x4) ? 2 : 1; + break; + } + + priv->r100c08_page = alloc_page(GFP_KERNEL | __GFP_ZERO); + if (priv->r100c08_page) { + priv->r100c08 = pci_map_page(device->pdev, priv->r100c08_page, + 0, PAGE_SIZE, + PCI_DMA_BIDIRECTIONAL); + if (pci_dma_mapping_error(device->pdev, priv->r100c08)) + nv_warn(priv, "failed 0x100c08 page map\n"); + } else { + nv_warn(priv, "failed 0x100c08 page alloc\n"); } - priv = dev_priv->engine.fb.priv; + + priv->base.memtype_valid = nv50_fb_memtype_valid; + priv->base.ram.get = nv50_fb_vram_new; + priv->base.ram.put = nv50_fb_vram_del; + return nouveau_fb_created(&priv->base); +} + +static void +nv50_fb_dtor(struct nouveau_object *object) +{ + struct nouveau_device *device = nv_device(object); + struct nv50_fb_priv *priv = (void *)object; + + if (priv->r100c08_page) { + pci_unmap_page(device->pdev, priv->r100c08, PAGE_SIZE, + PCI_DMA_BIDIRECTIONAL); + __free_page(priv->r100c08_page); + } + + nouveau_mm_fini(&priv->base.vram); + nouveau_fb_destroy(&priv->base); +} + +static int +nv50_fb_init(struct nouveau_object *object) +{ + struct nouveau_device *device = nv_device(object); + struct nv50_fb_priv *priv = (void *)object; + int ret; + + ret = nouveau_fb_init(&priv->base); + if (ret) + return ret; /* Not a clue what this is exactly. Without pointing it at a * scratch page, VRAM->GART blits with M2MF (as in DDX DFS) * cause IOMMU "read from address 0" errors (rh#561267) */ - nv_wr32(dev, 0x100c08, priv->r100c08 >> 8); + nv_wr32(priv, 0x100c08, priv->r100c08 >> 8); /* This is needed to get meaningful information from 100c90 * on traps. No idea what these values mean exactly. */ - switch (dev_priv->chipset) { + switch (device->chipset) { case 0x50: - nv_wr32(dev, 0x100c90, 0x000707ff); + nv_wr32(priv, 0x100c90, 0x000707ff); break; case 0xa3: case 0xa5: case 0xa8: - nv_wr32(dev, 0x100c90, 0x000d0fff); + nv_wr32(priv, 0x100c90, 0x000d0fff); break; case 0xaf: - nv_wr32(dev, 0x100c90, 0x089d1fff); + nv_wr32(priv, 0x100c90, 0x089d1fff); break; default: - nv_wr32(dev, 0x100c90, 0x001d07ff); + nv_wr32(priv, 0x100c90, 0x001d07ff); break; } return 0; } -void -nv50_fb_takedown(struct drm_device *dev) -{ - nv50_fb_destroy(dev); -} +struct nouveau_oclass +nv50_fb_oclass = { + .handle = NV_SUBDEV(FB, 0x50), + .ofuncs = &(struct nouveau_ofuncs) { + .ctor = nv50_fb_ctor, + .dtor = nv50_fb_dtor, + .init = nv50_fb_init, + .fini = _nouveau_fb_fini, + }, +}; static struct nouveau_enum vm_dispatch_subclients[] = { { 0x00000000, "GRCTX", NULL }, @@ -211,47 +427,32 @@ static struct nouveau_enum vm_fault[] = { }; void -nv50_fb_vm_trap(struct drm_device *dev, int display) +nv50_fb_trap(struct nouveau_fb *pfb, int display) { - struct nouveau_fifo_priv *pfifo = nv_engine(dev, NVOBJ_ENGINE_FIFO); - struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_device *device = nv_device(pfb); + struct nv50_fb_priv *priv = (void *)pfb; const struct nouveau_enum *en, *cl; - unsigned long flags; - u32 trap[6], idx, chinst; + u32 trap[6], idx, chan; u8 st0, st1, st2, st3; - int i, ch; + int i; - idx = nv_rd32(dev, 0x100c90); + idx = nv_rd32(priv, 0x100c90); if (!(idx & 0x80000000)) return; idx &= 0x00ffffff; for (i = 0; i < 6; i++) { - nv_wr32(dev, 0x100c90, idx | i << 24); - trap[i] = nv_rd32(dev, 0x100c94); + nv_wr32(priv, 0x100c90, idx | i << 24); + trap[i] = nv_rd32(priv, 0x100c94); } - nv_wr32(dev, 0x100c90, idx | 0x80000000); + nv_wr32(priv, 0x100c90, idx | 0x80000000); if (!display) return; - /* lookup channel id */ - chinst = (trap[2] << 16) | trap[1]; - spin_lock_irqsave(&dev_priv->channels.lock, flags); - for (ch = 0; ch < pfifo->channels; ch++) { - struct nouveau_channel *chan = dev_priv->channels.ptr[ch]; - - if (!chan || !chan->ramin) - continue; - - if (chinst == chan->ramin->vinst >> 12) - break; - } - spin_unlock_irqrestore(&dev_priv->channels.lock, flags); - /* decode status bits into something more useful */ - if (dev_priv->chipset < 0xa3 || - dev_priv->chipset == 0xaa || dev_priv->chipset == 0xac) { + if (device->chipset < 0xa3 || + device->chipset == 0xaa || device->chipset == 0xac) { st0 = (trap[0] & 0x0000000f) >> 0; st1 = (trap[0] & 0x000000f0) >> 4; st2 = (trap[0] & 0x00000f00) >> 8; @@ -262,10 +463,11 @@ nv50_fb_vm_trap(struct drm_device *dev, int display) st2 = (trap[0] & 0x00ff0000) >> 16; st3 = (trap[0] & 0xff000000) >> 24; } + chan = (trap[2] << 16) | trap[1]; - NV_INFO(dev, "VM: trapped %s at 0x%02x%04x%04x on ch %d [0x%08x] ", - (trap[5] & 0x00000100) ? "read" : "write", - trap[5] & 0xff, trap[4] & 0xffff, trap[3] & 0xffff, ch, chinst); + nv_error(priv, "trapped %s at 0x%02x%04x%04x on channel 0x%08x ", + (trap[5] & 0x00000100) ? "read" : "write", + trap[5] & 0xff, trap[4] & 0xffff, trap[3] & 0xffff, chan); en = nouveau_enum_find(vm_engine, st0); if (en) diff --git a/drivers/gpu/drm/nouveau/core/subdev/fb/nv50_vram.c b/drivers/gpu/drm/nouveau/core/subdev/fb/nv50_vram.c deleted file mode 100644 index 84b99b608b2b..000000000000 --- a/drivers/gpu/drm/nouveau/core/subdev/fb/nv50_vram.c +++ /dev/null @@ -1,243 +0,0 @@ -/* - * Copyright 2010 Red Hat Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: Ben Skeggs - */ - -#include "drmP.h" -#include "nouveau_drv.h" -#include - -static int types[0x80] = { - 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 1, 1, 1, 1, 0, 0, 0, 0, 2, 2, 2, 2, 0, 0, 0, 0, - 1, 1, 1, 1, 1, 1, 1, 0, 2, 2, 2, 2, 2, 2, 2, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 0, 0, - 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 2, 2, 2, 2, - 1, 0, 2, 0, 1, 0, 2, 0, 1, 1, 2, 2, 1, 1, 0, 0 -}; - -bool -nv50_vram_flags_valid(struct drm_device *dev, u32 tile_flags) -{ - int type = (tile_flags & NOUVEAU_GEM_TILE_LAYOUT_MASK) >> 8; - - if (likely(type < ARRAY_SIZE(types) && types[type])) - return true; - return false; -} - -void -nv50_vram_del(struct drm_device *dev, struct nouveau_mem **pmem) -{ - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_mm *mm = &dev_priv->engine.vram.mm; - struct nouveau_mm_node *this; - struct nouveau_mem *mem; - - mem = *pmem; - *pmem = NULL; - if (unlikely(mem == NULL)) - return; - - mutex_lock(&mm->mutex); - while (!list_empty(&mem->regions)) { - this = list_first_entry(&mem->regions, struct nouveau_mm_node, rl_entry); - - list_del(&this->rl_entry); - nouveau_mm_free(mm, &this); - } - - if (mem->tag) { - drm_mm_put_block(mem->tag); - mem->tag = NULL; - } - mutex_unlock(&mm->mutex); - - kfree(mem); -} - -int -nv50_vram_new(struct drm_device *dev, u64 size, u32 align, u32 ncmin, - u32 memtype, struct nouveau_mem **pmem) -{ - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_mm *mm = &dev_priv->engine.vram.mm; - struct nouveau_mm_node *r; - struct nouveau_mem *mem; - int comp = (memtype & 0x300) >> 8; - int type = (memtype & 0x07f); - int back = (memtype & 0x800); - int ret; - - size >>= 12; - align >>= 12; - ncmin >>= 12; - if (!ncmin) - ncmin = size; - - mem = kzalloc(sizeof(*mem), GFP_KERNEL); - if (!mem) - return -ENOMEM; - - mutex_lock(&mm->mutex); - if (comp) { - if (align == 16) { - struct nouveau_fb_engine *pfb = &dev_priv->engine.fb; - int n = (size >> 4) * comp; - - mem->tag = drm_mm_search_free(&pfb->tag_heap, n, 0, 0); - if (mem->tag) - mem->tag = drm_mm_get_block(mem->tag, n, 0); - } - - if (unlikely(!mem->tag)) - comp = 0; - } - - INIT_LIST_HEAD(&mem->regions); - mem->dev = dev_priv->dev; - mem->memtype = (comp << 7) | type; - mem->size = size; - - type = types[type]; - do { - if (back) - ret = nouveau_mm_tail(mm, type, size, ncmin, align, &r); - else - ret = nouveau_mm_head(mm, type, size, ncmin, align, &r); - - if (ret) { - mutex_unlock(&mm->mutex); - nv50_vram_del(dev, &mem); - return ret; - } - - list_add_tail(&r->rl_entry, &mem->regions); - size -= r->length; - } while (size); - mutex_unlock(&mm->mutex); - - r = list_first_entry(&mem->regions, struct nouveau_mm_node, rl_entry); - mem->offset = (u64)r->offset << 12; - *pmem = mem; - return 0; -} - -static u32 -nv50_vram_rblock(struct drm_device *dev) -{ - struct drm_nouveau_private *dev_priv = dev->dev_private; - int i, parts, colbits, rowbitsa, rowbitsb, banks; - u64 rowsize, predicted; - u32 r0, r4, rt, ru, rblock_size; - - r0 = nv_rd32(dev, 0x100200); - r4 = nv_rd32(dev, 0x100204); - rt = nv_rd32(dev, 0x100250); - ru = nv_rd32(dev, 0x001540); - NV_DEBUG(dev, "memcfg 0x%08x 0x%08x 0x%08x 0x%08x\n", r0, r4, rt, ru); - - for (i = 0, parts = 0; i < 8; i++) { - if (ru & (0x00010000 << i)) - parts++; - } - - colbits = (r4 & 0x0000f000) >> 12; - rowbitsa = ((r4 & 0x000f0000) >> 16) + 8; - rowbitsb = ((r4 & 0x00f00000) >> 20) + 8; - banks = 1 << (((r4 & 0x03000000) >> 24) + 2); - - rowsize = parts * banks * (1 << colbits) * 8; - predicted = rowsize << rowbitsa; - if (r0 & 0x00000004) - predicted += rowsize << rowbitsb; - - if (predicted != dev_priv->vram_size) { - NV_WARN(dev, "memory controller reports %dMiB VRAM\n", - (u32)(dev_priv->vram_size >> 20)); - NV_WARN(dev, "we calculated %dMiB VRAM\n", - (u32)(predicted >> 20)); - } - - rblock_size = rowsize; - if (rt & 1) - rblock_size *= 3; - - NV_DEBUG(dev, "rblock %d bytes\n", rblock_size); - return rblock_size; -} - -int -nv50_vram_init(struct drm_device *dev) -{ - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_vram_engine *vram = &dev_priv->engine.vram; - const u32 rsvd_head = ( 256 * 1024) >> 12; /* vga memory */ - const u32 rsvd_tail = (1024 * 1024) >> 12; /* vbios etc */ - u32 pfb714 = nv_rd32(dev, 0x100714); - u32 rblock, length; - - switch (pfb714 & 0x00000007) { - case 0: dev_priv->vram_type = NV_MEM_TYPE_DDR1; break; - case 1: - if (nouveau_mem_vbios_type(dev) == NV_MEM_TYPE_DDR3) - dev_priv->vram_type = NV_MEM_TYPE_DDR3; - else - dev_priv->vram_type = NV_MEM_TYPE_DDR2; - break; - case 2: dev_priv->vram_type = NV_MEM_TYPE_GDDR3; break; - case 3: dev_priv->vram_type = NV_MEM_TYPE_GDDR4; break; - case 4: dev_priv->vram_type = NV_MEM_TYPE_GDDR5; break; - default: - break; - } - - dev_priv->vram_rank_B = !!(nv_rd32(dev, 0x100200) & 0x4); - dev_priv->vram_size = nv_rd32(dev, 0x10020c); - dev_priv->vram_size |= (dev_priv->vram_size & 0xff) << 32; - dev_priv->vram_size &= 0xffffffff00ULL; - - /* IGPs, no funky reordering happens here, they don't have VRAM */ - if (dev_priv->chipset == 0xaa || - dev_priv->chipset == 0xac || - dev_priv->chipset == 0xaf) { - dev_priv->vram_sys_base = (u64)nv_rd32(dev, 0x100e10) << 12; - rblock = 4096 >> 12; - } else { - rblock = nv50_vram_rblock(dev) >> 12; - } - - length = (dev_priv->vram_size >> 12) - rsvd_head - rsvd_tail; - - return nouveau_mm_init(&vram->mm, rsvd_head, length, rblock); -} - -void -nv50_vram_fini(struct drm_device *dev) -{ - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_vram_engine *vram = &dev_priv->engine.vram; - - nouveau_mm_fini(&vram->mm); -} diff --git a/drivers/gpu/drm/nouveau/core/subdev/fb/nvc0.c b/drivers/gpu/drm/nouveau/core/subdev/fb/nvc0.c index f054331e37d8..9f59f2bf0079 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/fb/nvc0.c +++ b/drivers/gpu/drm/nouveau/core/subdev/fb/nvc0.c @@ -1,5 +1,5 @@ /* - * Copyright 2011 Red Hat Inc. + * Copyright 2012 Red Hat Inc. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -22,114 +22,224 @@ * Authors: Ben Skeggs */ -#include "drmP.h" -#include "drm.h" -#include "nouveau_drv.h" -#include +#include +#include struct nvc0_fb_priv { + struct nouveau_fb base; struct page *r100c10_page; dma_addr_t r100c10; }; -static inline void -nvc0_mfb_subp_isr(struct drm_device *dev, int unit, int subp) +/* 0 = unsupported + * 1 = non-compressed + * 3 = compressed + */ +static const u8 types[256] = { + 1, 1, 3, 3, 3, 3, 0, 3, 3, 3, 3, 0, 0, 0, 0, 0, + 0, 1, 0, 0, 0, 0, 0, 3, 3, 3, 3, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 3, 3, 3, 3, 3, + 3, 3, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 3, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 3, 3, 3, 3, 0, 1, 1, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 3, 3, 3, 3, 1, 1, 1, 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, + 3, 3, 3, 1, 0, 0, 0, 0, 0, 0, 0, 0, 3, 3, 3, 3, + 3, 3, 0, 0, 0, 0, 0, 0, 3, 0, 0, 3, 0, 3, 0, 3, + 3, 0, 3, 3, 3, 3, 3, 0, 0, 3, 0, 3, 0, 3, 3, 0, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 1, 1, 0 +}; + +static bool +nvc0_fb_memtype_valid(struct nouveau_fb *pfb, u32 tile_flags) { - u32 subp_base = 0x141000 + (unit * 0x2000) + (subp * 0x400); - u32 stat = nv_rd32(dev, subp_base + 0x020); + u8 memtype = (tile_flags & 0x0000ff00) >> 8; + return likely((types[memtype] == 1)); +} - if (stat) { - NV_INFO(dev, "PMFB%d_SUBP%d: 0x%08x\n", unit, subp, stat); - nv_wr32(dev, subp_base + 0x020, stat); - } +static int +nvc0_fb_vram_new(struct nouveau_fb *pfb, u64 size, u32 align, u32 ncmin, + u32 memtype, struct nouveau_mem **pmem) +{ + struct nouveau_mm *mm = &pfb->vram; + struct nouveau_mm_node *r; + struct nouveau_mem *mem; + int type = (memtype & 0x0ff); + int back = (memtype & 0x800); + int ret; + + size >>= 12; + align >>= 12; + ncmin >>= 12; + if (!ncmin) + ncmin = size; + + mem = kzalloc(sizeof(*mem), GFP_KERNEL); + if (!mem) + return -ENOMEM; + + INIT_LIST_HEAD(&mem->regions); + mem->memtype = type; + mem->size = size; + + mutex_lock(&mm->mutex); + do { + if (back) + ret = nouveau_mm_tail(mm, 1, size, ncmin, align, &r); + else + ret = nouveau_mm_head(mm, 1, size, ncmin, align, &r); + if (ret) { + mutex_unlock(&mm->mutex); + pfb->ram.put(pfb, &mem); + return ret; + } + + list_add_tail(&r->rl_entry, &mem->regions); + size -= r->length; + } while (size); + mutex_unlock(&mm->mutex); + + r = list_first_entry(&mem->regions, struct nouveau_mm_node, rl_entry); + mem->offset = (u64)r->offset << 12; + *pmem = mem; + return 0; } -static void -nvc0_mfb_isr(struct drm_device *dev) +static int +nvc0_fb_init(struct nouveau_object *object) { - u32 units = nv_rd32(dev, 0x00017c); - while (units) { - u32 subp, unit = ffs(units) - 1; - for (subp = 0; subp < 2; subp++) - nvc0_mfb_subp_isr(dev, unit, subp); - units &= ~(1 << unit); - } + struct nvc0_fb_priv *priv = (void *)object; + int ret; + + ret = nouveau_fb_init(&priv->base); + if (ret) + return ret; - /* we do something horribly wrong and upset PMFB a lot, so mask off - * interrupts from it after the first one until it's fixed - */ - nv_mask(dev, 0x000640, 0x02000000, 0x00000000); + nv_wr32(priv, 0x100c10, priv->r100c10 >> 8); + return 0; } static void -nvc0_fb_destroy(struct drm_device *dev) +nvc0_fb_dtor(struct nouveau_object *object) { - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_fb_engine *pfb = &dev_priv->engine.fb; - struct nvc0_fb_priv *priv = pfb->priv; - - nouveau_irq_unregister(dev, 25); + struct nouveau_device *device = nv_device(object); + struct nvc0_fb_priv *priv = (void *)object; if (priv->r100c10_page) { - pci_unmap_page(dev->pdev, priv->r100c10, PAGE_SIZE, + pci_unmap_page(device->pdev, priv->r100c10, PAGE_SIZE, PCI_DMA_BIDIRECTIONAL); __free_page(priv->r100c10_page); } - kfree(priv); - pfb->priv = NULL; + nouveau_fb_destroy(&priv->base); } static int -nvc0_fb_create(struct drm_device *dev) +nvc0_vram_detect(struct nvc0_fb_priv *priv) { - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_fb_engine *pfb = &dev_priv->engine.fb; - struct nvc0_fb_priv *priv; - - priv = kzalloc(sizeof(*priv), GFP_KERNEL); - if (!priv) - return -ENOMEM; - pfb->priv = priv; + struct nouveau_bios *bios = nouveau_bios(priv); + struct nouveau_fb *pfb = &priv->base; + const u32 rsvd_head = ( 256 * 1024) >> 12; /* vga memory */ + const u32 rsvd_tail = (1024 * 1024) >> 12; /* vbios etc */ + u32 parts = nv_rd32(priv, 0x022438); + u32 pmask = nv_rd32(priv, 0x022554); + u32 bsize = nv_rd32(priv, 0x10f20c); + u32 offset, length; + bool uniform = true; + int ret, part; + + nv_debug(priv, "0x100800: 0x%08x\n", nv_rd32(priv, 0x100800)); + nv_debug(priv, "parts 0x%08x mask 0x%08x\n", parts, pmask); + + priv->base.ram.type = nouveau_fb_bios_memtype(bios); + priv->base.ram.ranks = (nv_rd32(priv, 0x10f200) & 0x00000004) ? 2 : 1; + + /* read amount of vram attached to each memory controller */ + for (part = 0; part < parts; part++) { + if (!(pmask & (1 << part))) { + u32 psize = nv_rd32(priv, 0x11020c + (part * 0x1000)); + if (psize != bsize) { + if (psize < bsize) + bsize = psize; + uniform = false; + } + + nv_debug(priv, "%d: mem_amount 0x%08x\n", part, psize); + priv->base.ram.size += (u64)psize << 20; + } + } - priv->r100c10_page = alloc_page(GFP_KERNEL | __GFP_ZERO); - if (!priv->r100c10_page) { - nvc0_fb_destroy(dev); - return -ENOMEM; + /* if all controllers have the same amount attached, there's no holes */ + if (uniform) { + offset = rsvd_head; + length = (priv->base.ram.size >> 12) - rsvd_head - rsvd_tail; + return nouveau_mm_init(&pfb->vram, offset, length, 1); } - priv->r100c10 = pci_map_page(dev->pdev, priv->r100c10_page, 0, - PAGE_SIZE, PCI_DMA_BIDIRECTIONAL); - if (pci_dma_mapping_error(dev->pdev, priv->r100c10)) { - nvc0_fb_destroy(dev); - return -EFAULT; + /* otherwise, address lowest common amount from 0GiB */ + ret = nouveau_mm_init(&pfb->vram, rsvd_head, (bsize << 8) * parts, 1); + if (ret) + return ret; + + /* and the rest starting from (8GiB + common_size) */ + offset = (0x0200000000ULL >> 12) + (bsize << 8); + length = (priv->base.ram.size >> 12) - (bsize << 8) - rsvd_tail; + + ret = nouveau_mm_init(&pfb->vram, offset, length, 0); + if (ret) { + nouveau_mm_fini(&pfb->vram); + return ret; } - nouveau_irq_register(dev, 25, nvc0_mfb_isr); return 0; } -int -nvc0_fb_init(struct drm_device *dev) +static int +nvc0_fb_ctor(struct nouveau_object *parent, struct nouveau_object *engine, + struct nouveau_oclass *oclass, void *data, u32 size, + struct nouveau_object **pobject) { - struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_device *device = nv_device(parent); struct nvc0_fb_priv *priv; int ret; - if (!dev_priv->engine.fb.priv) { - ret = nvc0_fb_create(dev); - if (ret) - return ret; - } - priv = dev_priv->engine.fb.priv; + ret = nouveau_fb_create(parent, engine, oclass, &priv); + *pobject = nv_object(priv); + if (ret) + return ret; - nv_wr32(dev, 0x100c10, priv->r100c10 >> 8); - nv_mask(dev, 0x17e820, 0x00100000, 0x00000000); /* NV_PLTCG_INTR_EN */ - return 0; -} + priv->base.memtype_valid = nvc0_fb_memtype_valid; + priv->base.ram.get = nvc0_fb_vram_new; + priv->base.ram.put = nv50_fb_vram_del; -void -nvc0_fb_takedown(struct drm_device *dev) -{ - nvc0_fb_destroy(dev); + ret = nvc0_vram_detect(priv); + if (ret) + return ret; + + priv->r100c10_page = alloc_page(GFP_KERNEL | __GFP_ZERO); + if (!priv->r100c10_page) + return -ENOMEM; + + priv->r100c10 = pci_map_page(device->pdev, priv->r100c10_page, 0, + PAGE_SIZE, PCI_DMA_BIDIRECTIONAL); + if (pci_dma_mapping_error(device->pdev, priv->r100c10)) + return -EFAULT; + + return nouveau_fb_created(&priv->base); } + + +struct nouveau_oclass +nvc0_fb_oclass = { + .handle = NV_SUBDEV(FB, 0xc0), + .ofuncs = &(struct nouveau_ofuncs) { + .ctor = nvc0_fb_ctor, + .dtor = nvc0_fb_dtor, + .init = nvc0_fb_init, + .fini = _nouveau_fb_fini, + }, +}; diff --git a/drivers/gpu/drm/nouveau/core/subdev/fb/nvc0_vram.c b/drivers/gpu/drm/nouveau/core/subdev/fb/nvc0_vram.c deleted file mode 100644 index f363234a3f44..000000000000 --- a/drivers/gpu/drm/nouveau/core/subdev/fb/nvc0_vram.c +++ /dev/null @@ -1,167 +0,0 @@ -/* - * Copyright 2010 Red Hat Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: Ben Skeggs - */ - -#include "drmP.h" -#include "nouveau_drv.h" -#include - -/* 0 = unsupported - * 1 = non-compressed - * 3 = compressed - */ -static const u8 types[256] = { - 1, 1, 3, 3, 3, 3, 0, 3, 3, 3, 3, 0, 0, 0, 0, 0, - 0, 1, 0, 0, 0, 0, 0, 3, 3, 3, 3, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 3, 3, 3, 3, 3, - 3, 3, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 3, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 3, 3, 3, 3, 0, 1, 1, 1, 1, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 3, 3, 3, 3, 1, 1, 1, 1, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, - 3, 3, 3, 1, 0, 0, 0, 0, 0, 0, 0, 0, 3, 3, 3, 3, - 3, 3, 0, 0, 0, 0, 0, 0, 3, 0, 0, 3, 0, 3, 0, 3, - 3, 0, 3, 3, 3, 3, 3, 0, 0, 3, 0, 3, 0, 3, 3, 0, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 1, 1, 0 -}; - -bool -nvc0_vram_flags_valid(struct drm_device *dev, u32 tile_flags) -{ - u8 memtype = (tile_flags & NOUVEAU_GEM_TILE_LAYOUT_MASK) >> 8; - return likely((types[memtype] == 1)); -} - -int -nvc0_vram_new(struct drm_device *dev, u64 size, u32 align, u32 ncmin, - u32 memtype, struct nouveau_mem **pmem) -{ - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_mm *mm = &dev_priv->engine.vram.mm; - struct nouveau_mm_node *r; - struct nouveau_mem *mem; - int type = (memtype & 0x0ff); - int back = (memtype & 0x800); - int ret; - - size >>= 12; - align >>= 12; - ncmin >>= 12; - if (!ncmin) - ncmin = size; - - mem = kzalloc(sizeof(*mem), GFP_KERNEL); - if (!mem) - return -ENOMEM; - - INIT_LIST_HEAD(&mem->regions); - mem->dev = dev_priv->dev; - mem->memtype = type; - mem->size = size; - - mutex_lock(&mm->mutex); - do { - if (back) - ret = nouveau_mm_tail(mm, 1, size, ncmin, align, &r); - else - ret = nouveau_mm_head(mm, 1, size, ncmin, align, &r); - if (ret) { - mutex_unlock(&mm->mutex); - nv50_vram_del(dev, &mem); - return ret; - } - - list_add_tail(&r->rl_entry, &mem->regions); - size -= r->length; - } while (size); - mutex_unlock(&mm->mutex); - - r = list_first_entry(&mem->regions, struct nouveau_mm_node, rl_entry); - mem->offset = (u64)r->offset << 12; - *pmem = mem; - return 0; -} - -int -nvc0_vram_init(struct drm_device *dev) -{ - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_vram_engine *vram = &dev_priv->engine.vram; - const u32 rsvd_head = ( 256 * 1024) >> 12; /* vga memory */ - const u32 rsvd_tail = (1024 * 1024) >> 12; /* vbios etc */ - u32 parts = nv_rd32(dev, 0x022438); - u32 pmask = nv_rd32(dev, 0x022554); - u32 bsize = nv_rd32(dev, 0x10f20c); - u32 offset, length; - bool uniform = true; - int ret, part; - - NV_DEBUG(dev, "0x100800: 0x%08x\n", nv_rd32(dev, 0x100800)); - NV_DEBUG(dev, "parts 0x%08x mask 0x%08x\n", parts, pmask); - - dev_priv->vram_type = nouveau_mem_vbios_type(dev); - dev_priv->vram_rank_B = !!(nv_rd32(dev, 0x10f200) & 0x00000004); - - /* read amount of vram attached to each memory controller */ - for (part = 0; part < parts; part++) { - if (!(pmask & (1 << part))) { - u32 psize = nv_rd32(dev, 0x11020c + (part * 0x1000)); - if (psize != bsize) { - if (psize < bsize) - bsize = psize; - uniform = false; - } - - NV_DEBUG(dev, "%d: mem_amount 0x%08x\n", part, psize); - dev_priv->vram_size += (u64)psize << 20; - } - } - - /* if all controllers have the same amount attached, there's no holes */ - if (uniform) { - offset = rsvd_head; - length = (dev_priv->vram_size >> 12) - rsvd_head - rsvd_tail; - return nouveau_mm_init(&vram->mm, offset, length, 1); - } - - /* otherwise, address lowest common amount from 0GiB */ - ret = nouveau_mm_init(&vram->mm, rsvd_head, (bsize << 8) * parts, 1); - if (ret) - return ret; - - /* and the rest starting from (8GiB + common_size) */ - offset = (0x0200000000ULL >> 12) + (bsize << 8); - length = (dev_priv->vram_size >> 12) - (bsize << 8) - rsvd_tail; - - ret = nouveau_mm_init(&vram->mm, offset, length, 0); - if (ret) { - nouveau_mm_fini(&vram->mm); - return ret; - } - - return 0; -} diff --git a/drivers/gpu/drm/nouveau/core/subdev/instmem/nv50.c b/drivers/gpu/drm/nouveau/core/subdev/instmem/nv50.c index 5965eb7cf390..24d077a1d842 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/instmem/nv50.c +++ b/drivers/gpu/drm/nouveau/core/subdev/instmem/nv50.c @@ -310,8 +310,6 @@ nv50_instmem_get(struct nouveau_gpuobj *gpuobj, struct nouveau_channel *chan, u32 size, u32 align) { struct drm_device *dev = gpuobj->dev; - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_vram_engine *vram = &dev_priv->engine.vram; struct nv50_gpuobj_node *node = NULL; int ret; @@ -323,7 +321,7 @@ nv50_instmem_get(struct nouveau_gpuobj *gpuobj, struct nouveau_channel *chan, size = (size + 4095) & ~4095; align = max(align, (u32)4096); - ret = vram->get(dev, size, align, 0, 0x800, &node->vram); + ret = nvfb_vram_get(dev, size, align, 0, 0x800, &node->vram); if (ret) { kfree(node); return ret; @@ -339,7 +337,7 @@ nv50_instmem_get(struct nouveau_gpuobj *gpuobj, struct nouveau_channel *chan, ret = nouveau_vm_get(chan->vm, size, 12, flags, &node->chan_vma); if (ret) { - vram->put(dev, &node->vram); + nvfb_vram_put(dev, &node->vram); kfree(node); return ret; } @@ -357,8 +355,6 @@ void nv50_instmem_put(struct nouveau_gpuobj *gpuobj) { struct drm_device *dev = gpuobj->dev; - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_vram_engine *vram = &dev_priv->engine.vram; struct nv50_gpuobj_node *node; node = gpuobj->node; @@ -368,7 +364,7 @@ nv50_instmem_put(struct nouveau_gpuobj *gpuobj) nouveau_vm_unmap(&node->chan_vma); nouveau_vm_put(&node->chan_vma); } - vram->put(dev, &node->vram); + nvfb_vram_put(dev, &node->vram); kfree(node); } diff --git a/drivers/gpu/drm/nouveau/core/subdev/ltcg/nvc0.c b/drivers/gpu/drm/nouveau/core/subdev/ltcg/nvc0.c new file mode 100644 index 000000000000..7c2840cc2bbf --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/subdev/ltcg/nvc0.c @@ -0,0 +1,91 @@ +/* + * Copyright 2012 Red Hat Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: Ben Skeggs + */ + +#include + +struct nvc0_ltcg_priv { + struct nouveau_ltcg base; +}; + +static void +nvc0_ltcg_subp_isr(struct nvc0_ltcg_priv *priv, int unit, int subp) +{ + u32 subp_base = 0x141000 + (unit * 0x2000) + (subp * 0x400); + u32 stat = nv_rd32(priv, subp_base + 0x020); + + if (stat) { + nv_info(priv, "LTC%d_LTS%d: 0x%08x\n", unit, subp, stat); + nv_wr32(priv, subp_base + 0x020, stat); + } +} + +static void +nvc0_ltcg_intr(struct nouveau_subdev *subdev) +{ + struct nvc0_ltcg_priv *priv = (void *)subdev; + u32 units; + + units = nv_rd32(priv, 0x00017c); + while (units) { + u32 subp, unit = ffs(units) - 1; + for (subp = 0; subp < 2; subp++) + nvc0_ltcg_subp_isr(priv, unit, subp); + units &= ~(1 << unit); + } + + /* we do something horribly wrong and upset PMFB a lot, so mask off + * interrupts from it after the first one until it's fixed + */ + nv_mask(priv, 0x000640, 0x02000000, 0x00000000); +} + +static int +nvc0_ltcg_ctor(struct nouveau_object *parent, struct nouveau_object *engine, + struct nouveau_oclass *oclass, void *data, u32 size, + struct nouveau_object **pobject) +{ + struct nvc0_ltcg_priv *priv; + int ret; + + ret = nouveau_ltcg_create(parent, engine, oclass, &priv); + *pobject = nv_object(priv); + if (ret) + return ret; + + nv_mask(priv, 0x17e820, 0x00100000, 0x00000000); /* INTR_EN &= ~0x10 */ + + nv_subdev(priv)->intr = nvc0_ltcg_intr; + return 0; +} + +struct nouveau_oclass +nvc0_ltcg_oclass = { + .handle = NV_SUBDEV(LTCG, 0xc0), + .ofuncs = &(struct nouveau_ofuncs) { + .ctor = nvc0_ltcg_ctor, + .dtor = _nouveau_ltcg_dtor, + .init = _nouveau_ltcg_init, + .fini = _nouveau_ltcg_fini, + }, +}; diff --git a/drivers/gpu/drm/nouveau/core/subdev/mc/nvc0.c b/drivers/gpu/drm/nouveau/core/subdev/mc/nvc0.c index 3fa39bb9a724..bd9e99463ff7 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/mc/nvc0.c +++ b/drivers/gpu/drm/nouveau/core/subdev/mc/nvc0.c @@ -38,6 +38,7 @@ nvc0_mc_intr[] = { { 0x00008000, NVDEV_ENGINE_BSP }, { 0x00100000, NVDEV_SUBDEV_TIMER }, { 0x00200000, NVDEV_SUBDEV_GPIO }, + { 0x02000000, NVDEV_SUBDEV_LTCG }, { 0x04000000, NVDEV_ENGINE_DISP }, { 0x80000000, NVDEV_ENGINE_SW }, {}, diff --git a/drivers/gpu/drm/nouveau/core/subdev/vm/nv50.c b/drivers/gpu/drm/nouveau/core/subdev/vm/nv50.c index eeac72f40201..7e46826de0e9 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/vm/nv50.c +++ b/drivers/gpu/drm/nouveau/core/subdev/vm/nv50.c @@ -80,8 +80,8 @@ nv50_vm_map(struct nouveau_vma *vma, struct nouveau_gpuobj *pgt, /* IGPs don't have real VRAM, re-target to stolen system memory */ target = 0; - if (dev_priv->vram_sys_base) { - phys += dev_priv->vram_sys_base; + if (nvfb_vram_sys_base(dev_priv->dev)) { + phys += nvfb_vram_sys_base(dev_priv->dev); target = 3; } @@ -103,7 +103,7 @@ nv50_vm_map(struct nouveau_vma *vma, struct nouveau_gpuobj *pgt, phys += block << (vma->node->type - 3); cnt -= block; if (comp) { - u32 tag = mem->tag->start + ((delta >> 16) * comp); + u32 tag = mem->tag->offset + ((delta >> 16) * comp); offset_h |= (tag << 17); delta += block << (vma->node->type - 3); } diff --git a/drivers/gpu/drm/nouveau/nouveau_bo.c b/drivers/gpu/drm/nouveau/nouveau_bo.c index d95275437a4b..f63785c2aae0 100644 --- a/drivers/gpu/drm/nouveau/nouveau_bo.c +++ b/drivers/gpu/drm/nouveau/nouveau_bo.c @@ -156,7 +156,7 @@ static void set_placement_range(struct nouveau_bo *nvbo, uint32_t type) { struct drm_nouveau_private *dev_priv = nouveau_bdev(nvbo->bo.bdev); - int vram_pages = dev_priv->vram_size >> PAGE_SHIFT; + int vram_pages = nvfb_vram_size(dev_priv->dev) >> PAGE_SHIFT; if (dev_priv->card_type == NV_10 && nvbo->tile_mode && (type & TTM_PL_FLAG_VRAM) && diff --git a/drivers/gpu/drm/nouveau/nouveau_compat.c b/drivers/gpu/drm/nouveau/nouveau_compat.c index 7880ebb9a7d9..3d65c1763311 100644 --- a/drivers/gpu/drm/nouveau/nouveau_compat.c +++ b/drivers/gpu/drm/nouveau/nouveau_compat.c @@ -10,6 +10,7 @@ #include #include #include +#include void *nouveau_newpriv(struct drm_device *); @@ -332,3 +333,108 @@ nv_timer_read(struct drm_device *dev) struct nouveau_timer *ptimer = nouveau_timer(drm->device); return ptimer->read(ptimer); } + +int +nvfb_tile_nr(struct drm_device *dev) +{ + struct nouveau_drm *drm = nouveau_newpriv(dev); + struct nouveau_fb *pfb = nouveau_fb(drm->device); + return pfb->tile.regions; +} + +struct nouveau_fb_tile * +nvfb_tile(struct drm_device *dev, int i) +{ + struct nouveau_drm *drm = nouveau_newpriv(dev); + struct nouveau_fb *pfb = nouveau_fb(drm->device); + return &pfb->tile.region[i]; +} + +void +nvfb_tile_init(struct drm_device *dev, int i, u32 a, u32 b, u32 c, u32 d) +{ + struct nouveau_drm *drm = nouveau_newpriv(dev); + struct nouveau_fb *pfb = nouveau_fb(drm->device); + pfb->tile.init(pfb, i, a, b, c, d, &pfb->tile.region[i]); +} + +void +nvfb_tile_fini(struct drm_device *dev, int i) +{ + struct nouveau_drm *drm = nouveau_newpriv(dev); + struct nouveau_fb *pfb = nouveau_fb(drm->device); + pfb->tile.fini(pfb, i, &pfb->tile.region[i]); +} + +void +nvfb_tile_prog(struct drm_device *dev, int i) +{ + struct nouveau_drm *drm = nouveau_newpriv(dev); + struct nouveau_fb *pfb = nouveau_fb(drm->device); + pfb->tile.prog(pfb, i, &pfb->tile.region[i]); +} + +bool +nvfb_flags_valid(struct drm_device *dev, u32 flags) +{ + struct nouveau_drm *drm = nouveau_newpriv(dev); + struct nouveau_fb *pfb = nouveau_fb(drm->device); + return pfb->memtype_valid(pfb, flags); +} + +int +nvfb_vram_get(struct drm_device *dev, u64 size, u32 align, u32 ncmin, + u32 memtype, struct nouveau_mem **pmem) +{ + struct nouveau_drm *drm = nouveau_newpriv(dev); + struct nouveau_fb *pfb = nouveau_fb(drm->device); + int ret = pfb->ram.get(pfb, size, align, ncmin, memtype, pmem); + if (ret) + return ret; + (*pmem)->dev = dev; + return 0; +} + +void +nvfb_vram_put(struct drm_device *dev, struct nouveau_mem **pmem) +{ + struct nouveau_drm *drm = nouveau_newpriv(dev); + struct nouveau_fb *pfb = nouveau_fb(drm->device); + pfb->ram.put(pfb, pmem); +} + + +u64 nvfb_vram_sys_base(struct drm_device *dev) +{ + struct nouveau_drm *drm = nouveau_newpriv(dev); + struct nouveau_fb *pfb = nouveau_fb(drm->device); + return pfb->ram.stolen; +} + +u64 nvfb_vram_size(struct drm_device *dev) +{ + struct nouveau_drm *drm = nouveau_newpriv(dev); + struct nouveau_fb *pfb = nouveau_fb(drm->device); + return pfb->ram.size; +} + +int nvfb_vram_type(struct drm_device *dev) +{ + struct nouveau_drm *drm = nouveau_newpriv(dev); + struct nouveau_fb *pfb = nouveau_fb(drm->device); + return pfb->ram.type; +} + +int nvfb_vram_rank_B(struct drm_device *dev) +{ + struct nouveau_drm *drm = nouveau_newpriv(dev); + struct nouveau_fb *pfb = nouveau_fb(drm->device); + return pfb->ram.ranks > 1; +} + +void +nv50_fb_vm_trap(struct drm_device *dev, int disp) +{ + struct nouveau_drm *drm = nouveau_newpriv(dev); + nv50_fb_trap(nouveau_fb(drm->device), disp); +} diff --git a/drivers/gpu/drm/nouveau/nouveau_compat.h b/drivers/gpu/drm/nouveau/nouveau_compat.h index c9622ebf5cbe..d047a2046959 100644 --- a/drivers/gpu/drm/nouveau/nouveau_compat.h +++ b/drivers/gpu/drm/nouveau/nouveau_compat.h @@ -62,4 +62,24 @@ bool nouveau_wait_cb(struct drm_device *, u64 timeout, u64 nv_timer_read(struct drm_device *); +int nvfb_tile_nr(struct drm_device *); +void nvfb_tile_init(struct drm_device *, int, u32, u32, u32, u32); +void nvfb_tile_fini(struct drm_device *, int); +void nvfb_tile_prog(struct drm_device *, int); + +struct nouveau_fb_tile *nvfb_tile(struct drm_device *, int); + +struct nouveau_mem; +int nvfb_vram_get(struct drm_device *dev, u64 size, u32 align, u32 ncmin, + u32 memtype, struct nouveau_mem **pmem); +void nvfb_vram_put(struct drm_device *dev, struct nouveau_mem **pmem); +bool nvfb_flags_valid(struct drm_device *dev, u32); + +u64 nvfb_vram_sys_base(struct drm_device *); +u64 nvfb_vram_size(struct drm_device *); +int nvfb_vram_type(struct drm_device *); +int nvfb_vram_rank_B(struct drm_device *); + +void nv50_fb_vm_trap(struct drm_device *, int); + #endif diff --git a/drivers/gpu/drm/nouveau/nouveau_debugfs.c b/drivers/gpu/drm/nouveau/nouveau_debugfs.c index 188c92b327e2..6564b547973e 100644 --- a/drivers/gpu/drm/nouveau/nouveau_debugfs.c +++ b/drivers/gpu/drm/nouveau/nouveau_debugfs.c @@ -137,9 +137,8 @@ nouveau_debugfs_memory_info(struct seq_file *m, void *data) { struct drm_info_node *node = (struct drm_info_node *) m->private; struct drm_minor *minor = node->minor; - struct drm_nouveau_private *dev_priv = minor->dev->dev_private; - seq_printf(m, "VRAM total: %dKiB\n", (int)(dev_priv->vram_size >> 10)); + seq_printf(m, "VRAM total: %dKiB\n", (int)(nvfb_vram_size(minor->dev) >> 10)); return 0; } diff --git a/drivers/gpu/drm/nouveau/nouveau_drv.c b/drivers/gpu/drm/nouveau/nouveau_drv.c index 7223a4f69231..3f660a94dd18 100644 --- a/drivers/gpu/drm/nouveau/nouveau_drv.c +++ b/drivers/gpu/drm/nouveau/nouveau_drv.c @@ -252,7 +252,6 @@ nouveau_pci_resume(struct pci_dev *pdev) NV_INFO(dev, "Reinitialising engines...\n"); engine->instmem.resume(dev); - engine->fb.init(dev); for (i = 0; i < NVOBJ_ENGINE_NR; i++) { if (dev_priv->eng[i]) dev_priv->eng[i]->init(dev, i); diff --git a/drivers/gpu/drm/nouveau/nouveau_drv.h b/drivers/gpu/drm/nouveau/nouveau_drv.h index b4595990f5e8..c7bc6ecad601 100644 --- a/drivers/gpu/drm/nouveau/nouveau_drv.h +++ b/drivers/gpu/drm/nouveau/nouveau_drv.h @@ -45,6 +45,23 @@ #include "ttm/ttm_memory.h" #include "ttm/ttm_module.h" +#define XXX_THIS_IS_A_HACK +#include + +enum blah { + NV_MEM_TYPE_UNKNOWN = 0, + NV_MEM_TYPE_STOLEN, + NV_MEM_TYPE_SGRAM, + NV_MEM_TYPE_SDRAM, + NV_MEM_TYPE_DDR1, + NV_MEM_TYPE_DDR2, + NV_MEM_TYPE_DDR3, + NV_MEM_TYPE_GDDR2, + NV_MEM_TYPE_GDDR3, + NV_MEM_TYPE_GDDR4, + NV_MEM_TYPE_GDDR5 +}; + struct nouveau_fpriv { spinlock_t lock; struct list_head channels; @@ -76,29 +93,8 @@ struct nouveau_mem; #define NOUVEAU_MAX_CHANNEL_NR 4096 #define NOUVEAU_MAX_TILE_NR 15 -struct nouveau_mem { - struct drm_device *dev; - - struct nouveau_vma bar_vma; - struct nouveau_vma vma[2]; - u8 page_shift; - - struct drm_mm_node *tag; - struct list_head regions; - dma_addr_t *pages; - u32 memtype; - u64 offset; - u64 size; - struct sg_table *sg; -}; - struct nouveau_tile_reg { bool used; - uint32_t addr; - uint32_t limit; - uint32_t pitch; - uint32_t zcomp; - struct drm_mm_node *tag_mem; struct nouveau_fence *fence; }; @@ -324,21 +320,6 @@ struct nouveau_instmem_engine { void (*flush)(struct drm_device *); }; -struct nouveau_fb_engine { - int num_tiles; - struct drm_mm tag_heap; - void *priv; - - int (*init)(struct drm_device *dev); - void (*takedown)(struct drm_device *dev); - - void (*init_tile_region)(struct drm_device *dev, int i, - uint32_t addr, uint32_t size, - uint32_t pitch, uint32_t flags); - void (*set_tile_region)(struct drm_device *dev, int i); - void (*free_tile_region)(struct drm_device *dev, int i); -}; - struct nouveau_display_engine { void *priv; int (*early_init)(struct drm_device *); @@ -519,24 +500,10 @@ struct nouveau_pm_engine { int (*temp_get)(struct drm_device *); }; -struct nouveau_vram_engine { - struct nouveau_mm mm; - - int (*init)(struct drm_device *); - void (*takedown)(struct drm_device *dev); - int (*get)(struct drm_device *, u64, u32 align, u32 size_nc, - u32 type, struct nouveau_mem **); - void (*put)(struct drm_device *, struct nouveau_mem **); - - bool (*flags_valid)(struct drm_device *, u32 tile_flags); -}; - struct nouveau_engine { struct nouveau_instmem_engine instmem; - struct nouveau_fb_engine fb; struct nouveau_display_engine display; struct nouveau_pm_engine pm; - struct nouveau_vram_engine vram; }; enum nv04_fp_display_regs { @@ -714,24 +681,6 @@ struct drm_nouveau_private { spinlock_t lock; } tile; - /* VRAM/fb configuration */ - enum { - NV_MEM_TYPE_UNKNOWN = 0, - NV_MEM_TYPE_STOLEN, - NV_MEM_TYPE_SGRAM, - NV_MEM_TYPE_SDRAM, - NV_MEM_TYPE_DDR1, - NV_MEM_TYPE_DDR2, - NV_MEM_TYPE_DDR3, - NV_MEM_TYPE_GDDR2, - NV_MEM_TYPE_GDDR3, - NV_MEM_TYPE_GDDR4, - NV_MEM_TYPE_GDDR5 - } vram_type; - uint64_t vram_size; - uint64_t vram_sys_base; - bool vram_rank_B; - uint64_t fb_available_size; uint64_t fb_mappable_pages; uint64_t fb_aper_free; @@ -1047,55 +996,6 @@ int nouveau_ttm_mmap(struct file *, struct vm_area_struct *); /* nouveau_hdmi.c */ void nouveau_hdmi_mode_set(struct drm_encoder *, struct drm_display_mode *); -/* nv04_fb.c */ -extern int nv04_fb_vram_init(struct drm_device *); -extern int nv04_fb_init(struct drm_device *); -extern void nv04_fb_takedown(struct drm_device *); - -/* nv10_fb.c */ -extern int nv10_fb_vram_init(struct drm_device *dev); -extern int nv1a_fb_vram_init(struct drm_device *dev); -extern int nv10_fb_init(struct drm_device *); -extern void nv10_fb_takedown(struct drm_device *); -extern void nv10_fb_init_tile_region(struct drm_device *dev, int i, - uint32_t addr, uint32_t size, - uint32_t pitch, uint32_t flags); -extern void nv10_fb_set_tile_region(struct drm_device *dev, int i); -extern void nv10_fb_free_tile_region(struct drm_device *dev, int i); - -/* nv20_fb.c */ -extern int nv20_fb_vram_init(struct drm_device *dev); -extern int nv20_fb_init(struct drm_device *); -extern void nv20_fb_takedown(struct drm_device *); -extern void nv20_fb_init_tile_region(struct drm_device *dev, int i, - uint32_t addr, uint32_t size, - uint32_t pitch, uint32_t flags); -extern void nv20_fb_set_tile_region(struct drm_device *dev, int i); -extern void nv20_fb_free_tile_region(struct drm_device *dev, int i); - -/* nv30_fb.c */ -extern int nv30_fb_init(struct drm_device *); -extern void nv30_fb_takedown(struct drm_device *); -extern void nv30_fb_init_tile_region(struct drm_device *dev, int i, - uint32_t addr, uint32_t size, - uint32_t pitch, uint32_t flags); -extern void nv30_fb_free_tile_region(struct drm_device *dev, int i); - -/* nv40_fb.c */ -extern int nv40_fb_vram_init(struct drm_device *dev); -extern int nv40_fb_init(struct drm_device *); -extern void nv40_fb_takedown(struct drm_device *); -extern void nv40_fb_set_tile_region(struct drm_device *dev, int i); - -/* nv50_fb.c */ -extern int nv50_fb_init(struct drm_device *); -extern void nv50_fb_takedown(struct drm_device *); -extern void nv50_fb_vm_trap(struct drm_device *, int display); - -/* nvc0_fb.c */ -extern int nvc0_fb_init(struct drm_device *); -extern void nvc0_fb_takedown(struct drm_device *); - /* nv04_graph.c */ extern int nv04_graph_create(struct drm_device *); extern int nv04_graph_object_new(struct nouveau_channel *, int, u32, u16); @@ -1488,18 +1388,6 @@ nv44_graph_class(struct drm_device *dev) return !(0x0baf & (1 << (dev_priv->chipset & 0x0f))); } -int nv50_vram_init(struct drm_device *); -void nv50_vram_fini(struct drm_device *); -int nv50_vram_new(struct drm_device *, u64 size, u32 align, u32 size_nc, - u32 memtype, struct nouveau_mem **); -void nv50_vram_del(struct drm_device *, struct nouveau_mem **); -bool nv50_vram_flags_valid(struct drm_device *, u32 tile_flags); - -int nvc0_vram_init(struct drm_device *); -int nvc0_vram_new(struct drm_device *, u64 size, u32 align, u32 ncmin, - u32 memtype, struct nouveau_mem **); -bool nvc0_vram_flags_valid(struct drm_device *, u32 tile_flags); - /* memory type/access flags, do not match hardware values */ #define NV_MEM_ACCESS_RO 1 #define NV_MEM_ACCESS_WO 2 diff --git a/drivers/gpu/drm/nouveau/nouveau_fb.h b/drivers/gpu/drm/nouveau/nouveau_fb.h index f3fb649fe454..d767567977ee 100644 --- a/drivers/gpu/drm/nouveau/nouveau_fb.h +++ b/drivers/gpu/drm/nouveau/nouveau_fb.h @@ -24,8 +24,8 @@ * */ -#ifndef __NOUVEAU_FB_H__ -#define __NOUVEAU_FB_H__ +#ifndef __NOUVEAU_FRB_H__ +#define __NOUVEAU_FRB_H__ struct nouveau_framebuffer { struct drm_framebuffer base; diff --git a/drivers/gpu/drm/nouveau/nouveau_fbcon.c b/drivers/gpu/drm/nouveau/nouveau_fbcon.c index 9b078033ec19..f3f0b4c362cb 100644 --- a/drivers/gpu/drm/nouveau/nouveau_fbcon.c +++ b/drivers/gpu/drm/nouveau/nouveau_fbcon.c @@ -475,9 +475,9 @@ int nouveau_fbcon_init(struct drm_device *dev) drm_fb_helper_single_add_all_connectors(&nfbdev->helper); - if (dev_priv->vram_size <= 32 * 1024 * 1024) + if (nvfb_vram_size(dev) <= 32 * 1024 * 1024) preferred_bpp = 8; - else if (dev_priv->vram_size <= 64 * 1024 * 1024) + else if (nvfb_vram_size(dev) <= 64 * 1024 * 1024) preferred_bpp = 16; else preferred_bpp = 32; diff --git a/drivers/gpu/drm/nouveau/nouveau_gem.c b/drivers/gpu/drm/nouveau/nouveau_gem.c index c8bb9f230222..96a34bce54ce 100644 --- a/drivers/gpu/drm/nouveau/nouveau_gem.c +++ b/drivers/gpu/drm/nouveau/nouveau_gem.c @@ -209,7 +209,7 @@ nouveau_gem_ioctl_new(struct drm_device *dev, void *data, dev_priv->ttm.bdev.dev_mapping = dev->dev_mapping; - if (!dev_priv->engine.vram.flags_valid(dev, req->info.tile_flags)) { + if (!nvfb_flags_valid(dev, req->info.tile_flags)) { NV_ERROR(dev, "bad page flags: 0x%08x\n", req->info.tile_flags); return -EINVAL; } diff --git a/drivers/gpu/drm/nouveau/nouveau_mem.c b/drivers/gpu/drm/nouveau/nouveau_mem.c index 689d3e708057..4aea1c4c46ef 100644 --- a/drivers/gpu/drm/nouveau/nouveau_mem.c +++ b/drivers/gpu/drm/nouveau/nouveau_mem.c @@ -48,21 +48,21 @@ static void nv10_mem_update_tile_region(struct drm_device *dev, - struct nouveau_tile_reg *tile, uint32_t addr, + struct nouveau_tile_reg *tilereg, uint32_t addr, uint32_t size, uint32_t pitch, uint32_t flags) { struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_fb_engine *pfb = &dev_priv->engine.fb; - int i = tile - dev_priv->tile.reg, j; + int i = tilereg - dev_priv->tile.reg, j; + struct nouveau_fb_tile *tile = nvfb_tile(dev, i); unsigned long save; - nouveau_fence_unref(&tile->fence); + nouveau_fence_unref(&tilereg->fence); if (tile->pitch) - pfb->free_tile_region(dev, i); + nvfb_tile_fini(dev, i); if (pitch) - pfb->init_tile_region(dev, i, addr, size, pitch, flags); + nvfb_tile_init(dev, i, addr, size, pitch, flags); spin_lock_irqsave(&dev_priv->context_switch_lock, save); nv_wr32(dev, NV03_PFIFO_CACHES, 0); @@ -70,7 +70,7 @@ nv10_mem_update_tile_region(struct drm_device *dev, nouveau_wait_for_idle(dev); - pfb->set_tile_region(dev, i); + nvfb_tile_prog(dev, i); for (j = 0; j < NVOBJ_ENGINE_NR; j++) { if (dev_priv->eng[j] && dev_priv->eng[j]->set_tile_region) dev_priv->eng[j]->set_tile_region(dev, i); @@ -122,19 +122,17 @@ struct nouveau_tile_reg * nv10_mem_set_tiling(struct drm_device *dev, uint32_t addr, uint32_t size, uint32_t pitch, uint32_t flags) { - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_fb_engine *pfb = &dev_priv->engine.fb; struct nouveau_tile_reg *tile, *found = NULL; int i; - for (i = 0; i < pfb->num_tiles; i++) { + for (i = 0; i < nvfb_tile_nr(dev); i++) { tile = nv10_mem_get_tile_region(dev, i); if (pitch && !found) { found = tile; continue; - } else if (tile && tile->pitch) { + } else if (tile && nvfb_tile(dev, i)->pitch) { /* Kill an unused tile region. */ nv10_mem_update_tile_region(dev, tile, 0, 0, 0, 0); } @@ -174,38 +172,11 @@ nouveau_mem_gart_fini(struct drm_device *dev) nouveau_sgdma_takedown(dev); } -bool -nouveau_mem_flags_valid(struct drm_device *dev, u32 tile_flags) -{ - if (!(tile_flags & NOUVEAU_GEM_TILE_LAYOUT_MASK)) - return true; - - return false; -} - -static const struct vram_types { - int value; - const char *name; -} vram_type_map[] = { - { NV_MEM_TYPE_STOLEN , "stolen system memory" }, - { NV_MEM_TYPE_SGRAM , "SGRAM" }, - { NV_MEM_TYPE_SDRAM , "SDRAM" }, - { NV_MEM_TYPE_DDR1 , "DDR1" }, - { NV_MEM_TYPE_DDR2 , "DDR2" }, - { NV_MEM_TYPE_DDR3 , "DDR3" }, - { NV_MEM_TYPE_GDDR2 , "GDDR2" }, - { NV_MEM_TYPE_GDDR3 , "GDDR3" }, - { NV_MEM_TYPE_GDDR4 , "GDDR4" }, - { NV_MEM_TYPE_GDDR5 , "GDDR5" }, - { NV_MEM_TYPE_UNKNOWN, "unknown type" } -}; - int nouveau_mem_vram_init(struct drm_device *dev) { struct drm_nouveau_private *dev_priv = dev->dev_private; struct ttm_bo_device *bdev = &dev_priv->ttm.bdev; - const struct vram_types *vram_type; int ret, dma_bits; dma_bits = 32; @@ -243,27 +214,7 @@ nouveau_mem_vram_init(struct drm_device *dev) return ret; } - vram_type = vram_type_map; - while (vram_type->value != NV_MEM_TYPE_UNKNOWN) { - if (nouveau_vram_type) { - if (!strcasecmp(nouveau_vram_type, vram_type->name)) - break; - dev_priv->vram_type = vram_type->value; - } else { - if (vram_type->value == dev_priv->vram_type) - break; - } - vram_type++; - } - - NV_INFO(dev, "Detected %dMiB VRAM (%s)\n", - (int)(dev_priv->vram_size >> 20), vram_type->name); - if (dev_priv->vram_sys_base) { - NV_INFO(dev, "Stolen system memory at: 0x%010llx\n", - dev_priv->vram_sys_base); - } - - dev_priv->fb_available_size = dev_priv->vram_size; + dev_priv->fb_available_size = nvfb_vram_size(dev); dev_priv->fb_mappable_pages = dev_priv->fb_available_size; if (dev_priv->fb_mappable_pages > pci_resource_len(dev->pdev, 1)) dev_priv->fb_mappable_pages = pci_resource_len(dev->pdev, 1); @@ -364,7 +315,6 @@ nv50_mem_timing_calc(struct drm_device *dev, u32 freq, struct nouveau_pm_memtiming *boot, struct nouveau_pm_memtiming *t) { - struct drm_nouveau_private *dev_priv = dev->dev_private; struct bit_entry P; uint8_t unk18 = 1, unk20 = 0, unk21 = 0, tmp7_3; @@ -418,7 +368,7 @@ nv50_mem_timing_calc(struct drm_device *dev, u32 freq, t->reg[7] = 0x4000202 | (e->tCL - 1) << 16; /* XXX: P.version == 1 only has DDR2 and GDDR3? */ - if (dev_priv->vram_type == NV_MEM_TYPE_DDR2) { + if (nvfb_vram_type(dev) == NV_MEM_TYPE_DDR2) { t->reg[5] |= (e->tCL + 3) << 8; t->reg[6] |= (t->tCWL - 2) << 8; t->reg[8] |= (e->tCL - 4); @@ -711,7 +661,7 @@ nouveau_mem_timing_calc(struct drm_device *dev, u32 freq, break; } - switch (dev_priv->vram_type * !ret) { + switch (nvfb_vram_type(dev) * !ret) { case NV_MEM_TYPE_GDDR3: ret = nouveau_mem_gddr3_mr(dev, freq, e, len, boot, t); break; @@ -738,7 +688,7 @@ nouveau_mem_timing_calc(struct drm_device *dev, u32 freq, else dll_off = !!(ramcfg[2] & 0x40); - switch (dev_priv->vram_type) { + switch (nvfb_vram_type(dev)) { case NV_MEM_TYPE_GDDR3: t->mr[1] &= ~0x00000040; t->mr[1] |= 0x00000040 * dll_off; @@ -804,7 +754,7 @@ nouveau_mem_timing_read(struct drm_device *dev, struct nouveau_pm_memtiming *t) t->odt = 0; t->drive_strength = 0; - switch (dev_priv->vram_type) { + switch (nvfb_vram_type(dev)) { case NV_MEM_TYPE_DDR3: t->odt |= (t->mr[1] & 0x200) >> 7; case NV_MEM_TYPE_DDR2: @@ -831,7 +781,7 @@ nouveau_mem_exec(struct nouveau_mem_exec_func *exec, u32 mr[3] = { info->mr[0], info->mr[1], info->mr[2] }; u32 mr1_dlloff; - switch (dev_priv->vram_type) { + switch (nvfb_vram_type(dev_priv->dev)) { case NV_MEM_TYPE_DDR2: tDLLK = 2000; mr1_dlloff = 0x00000001; @@ -852,7 +802,7 @@ nouveau_mem_exec(struct nouveau_mem_exec_func *exec, } /* fetch current MRs */ - switch (dev_priv->vram_type) { + switch (nvfb_vram_type(dev_priv->dev)) { case NV_MEM_TYPE_GDDR3: case NV_MEM_TYPE_DDR3: mr[2] = exec->mrg(exec, 2); @@ -919,7 +869,7 @@ nouveau_mem_exec(struct nouveau_mem_exec_func *exec, exec->mrs (exec, 0, info->mr[0] | 0x00000000); exec->wait(exec, tMRD); exec->wait(exec, tDLLK); - if (dev_priv->vram_type == NV_MEM_TYPE_GDDR3) + if (nvfb_vram_type(dev_priv->dev) == NV_MEM_TYPE_GDDR3) exec->precharge(exec); } @@ -982,11 +932,10 @@ nouveau_vram_manager_del(struct ttm_mem_type_manager *man, struct ttm_mem_reg *mem) { struct drm_nouveau_private *dev_priv = nouveau_bdev(man->bdev); - struct nouveau_vram_engine *vram = &dev_priv->engine.vram; struct drm_device *dev = dev_priv->dev; nouveau_mem_node_cleanup(mem->mm_node); - vram->put(dev, (struct nouveau_mem **)&mem->mm_node); + nvfb_vram_put(dev, (struct nouveau_mem **)&mem->mm_node); } static int @@ -996,7 +945,6 @@ nouveau_vram_manager_new(struct ttm_mem_type_manager *man, struct ttm_mem_reg *mem) { struct drm_nouveau_private *dev_priv = nouveau_bdev(man->bdev); - struct nouveau_vram_engine *vram = &dev_priv->engine.vram; struct drm_device *dev = dev_priv->dev; struct nouveau_bo *nvbo = nouveau_bo(bo); struct nouveau_mem *node; @@ -1006,7 +954,7 @@ nouveau_vram_manager_new(struct ttm_mem_type_manager *man, if (nvbo->tile_flags & NOUVEAU_GEM_TILE_NONCONTIG) size_nc = 1 << nvbo->page_shift; - ret = vram->get(dev, mem->num_pages << PAGE_SHIFT, + ret = nvfb_vram_get(dev, mem->num_pages << PAGE_SHIFT, mem->page_alignment << PAGE_SHIFT, size_nc, (nvbo->tile_flags >> 8) & 0x3ff, &node); if (ret) { diff --git a/drivers/gpu/drm/nouveau/nouveau_state.c b/drivers/gpu/drm/nouveau/nouveau_state.c index 3b11962d7d6d..d8d9e5c527a4 100644 --- a/drivers/gpu/drm/nouveau/nouveau_state.c +++ b/drivers/gpu/drm/nouveau/nouveau_state.c @@ -61,8 +61,6 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev) engine->instmem.map = nv04_instmem_map; engine->instmem.unmap = nv04_instmem_unmap; engine->instmem.flush = nv04_instmem_flush; - engine->fb.init = nv04_fb_init; - engine->fb.takedown = nv04_fb_takedown; engine->display.early_init = nv04_display_early_init; engine->display.late_takedown = nv04_display_late_takedown; engine->display.create = nv04_display_create; @@ -72,9 +70,6 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev) engine->pm.clocks_get = nv04_pm_clocks_get; engine->pm.clocks_pre = nv04_pm_clocks_pre; engine->pm.clocks_set = nv04_pm_clocks_set; - engine->vram.init = nv04_fb_vram_init; - engine->vram.takedown = nouveau_stub_takedown; - engine->vram.flags_valid = nouveau_mem_flags_valid; break; case 0x10: engine->instmem.init = nv04_instmem_init; @@ -86,11 +81,6 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev) engine->instmem.map = nv04_instmem_map; engine->instmem.unmap = nv04_instmem_unmap; engine->instmem.flush = nv04_instmem_flush; - engine->fb.init = nv10_fb_init; - engine->fb.takedown = nv10_fb_takedown; - engine->fb.init_tile_region = nv10_fb_init_tile_region; - engine->fb.set_tile_region = nv10_fb_set_tile_region; - engine->fb.free_tile_region = nv10_fb_free_tile_region; engine->display.early_init = nv04_display_early_init; engine->display.late_takedown = nv04_display_late_takedown; engine->display.create = nv04_display_create; @@ -100,13 +90,6 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev) engine->pm.clocks_get = nv04_pm_clocks_get; engine->pm.clocks_pre = nv04_pm_clocks_pre; engine->pm.clocks_set = nv04_pm_clocks_set; - if (dev_priv->chipset == 0x1a || - dev_priv->chipset == 0x1f) - engine->vram.init = nv1a_fb_vram_init; - else - engine->vram.init = nv10_fb_vram_init; - engine->vram.takedown = nouveau_stub_takedown; - engine->vram.flags_valid = nouveau_mem_flags_valid; break; case 0x20: engine->instmem.init = nv04_instmem_init; @@ -118,11 +101,6 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev) engine->instmem.map = nv04_instmem_map; engine->instmem.unmap = nv04_instmem_unmap; engine->instmem.flush = nv04_instmem_flush; - engine->fb.init = nv20_fb_init; - engine->fb.takedown = nv20_fb_takedown; - engine->fb.init_tile_region = nv20_fb_init_tile_region; - engine->fb.set_tile_region = nv20_fb_set_tile_region; - engine->fb.free_tile_region = nv20_fb_free_tile_region; engine->display.early_init = nv04_display_early_init; engine->display.late_takedown = nv04_display_late_takedown; engine->display.create = nv04_display_create; @@ -132,9 +110,6 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev) engine->pm.clocks_get = nv04_pm_clocks_get; engine->pm.clocks_pre = nv04_pm_clocks_pre; engine->pm.clocks_set = nv04_pm_clocks_set; - engine->vram.init = nv20_fb_vram_init; - engine->vram.takedown = nouveau_stub_takedown; - engine->vram.flags_valid = nouveau_mem_flags_valid; break; case 0x30: engine->instmem.init = nv04_instmem_init; @@ -146,11 +121,6 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev) engine->instmem.map = nv04_instmem_map; engine->instmem.unmap = nv04_instmem_unmap; engine->instmem.flush = nv04_instmem_flush; - engine->fb.init = nv30_fb_init; - engine->fb.takedown = nv30_fb_takedown; - engine->fb.init_tile_region = nv30_fb_init_tile_region; - engine->fb.set_tile_region = nv10_fb_set_tile_region; - engine->fb.free_tile_region = nv30_fb_free_tile_region; engine->display.early_init = nv04_display_early_init; engine->display.late_takedown = nv04_display_late_takedown; engine->display.create = nv04_display_create; @@ -162,9 +132,6 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev) engine->pm.clocks_set = nv04_pm_clocks_set; engine->pm.voltage_get = nouveau_voltage_gpio_get; engine->pm.voltage_set = nouveau_voltage_gpio_set; - engine->vram.init = nv20_fb_vram_init; - engine->vram.takedown = nouveau_stub_takedown; - engine->vram.flags_valid = nouveau_mem_flags_valid; break; case 0x40: case 0x60: @@ -177,11 +144,6 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev) engine->instmem.map = nv04_instmem_map; engine->instmem.unmap = nv04_instmem_unmap; engine->instmem.flush = nv04_instmem_flush; - engine->fb.init = nv40_fb_init; - engine->fb.takedown = nv40_fb_takedown; - engine->fb.init_tile_region = nv30_fb_init_tile_region; - engine->fb.set_tile_region = nv40_fb_set_tile_region; - engine->fb.free_tile_region = nv30_fb_free_tile_region; engine->display.early_init = nv04_display_early_init; engine->display.late_takedown = nv04_display_late_takedown; engine->display.create = nv04_display_create; @@ -196,9 +158,6 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev) engine->pm.temp_get = nv40_temp_get; engine->pm.pwm_get = nv40_pm_pwm_get; engine->pm.pwm_set = nv40_pm_pwm_set; - engine->vram.init = nv40_fb_vram_init; - engine->vram.takedown = nouveau_stub_takedown; - engine->vram.flags_valid = nouveau_mem_flags_valid; break; case 0x50: case 0x80: /* gotta love NVIDIA's consistency.. */ @@ -216,8 +175,6 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev) engine->instmem.flush = nv50_instmem_flush; else engine->instmem.flush = nv84_instmem_flush; - engine->fb.init = nv50_fb_init; - engine->fb.takedown = nv50_fb_takedown; engine->display.early_init = nv50_display_early_init; engine->display.late_takedown = nv50_display_late_takedown; engine->display.create = nv50_display_create; @@ -253,11 +210,6 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev) engine->pm.temp_get = nv40_temp_get; engine->pm.pwm_get = nv50_pm_pwm_get; engine->pm.pwm_set = nv50_pm_pwm_set; - engine->vram.init = nv50_vram_init; - engine->vram.takedown = nv50_vram_fini; - engine->vram.get = nv50_vram_new; - engine->vram.put = nv50_vram_del; - engine->vram.flags_valid = nv50_vram_flags_valid; break; case 0xc0: engine->instmem.init = nvc0_instmem_init; @@ -269,19 +221,12 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev) engine->instmem.map = nv50_instmem_map; engine->instmem.unmap = nv50_instmem_unmap; engine->instmem.flush = nv84_instmem_flush; - engine->fb.init = nvc0_fb_init; - engine->fb.takedown = nvc0_fb_takedown; engine->display.early_init = nv50_display_early_init; engine->display.late_takedown = nv50_display_late_takedown; engine->display.create = nv50_display_create; engine->display.destroy = nv50_display_destroy; engine->display.init = nv50_display_init; engine->display.fini = nv50_display_fini; - engine->vram.init = nvc0_vram_init; - engine->vram.takedown = nv50_vram_fini; - engine->vram.get = nvc0_vram_new; - engine->vram.put = nv50_vram_del; - engine->vram.flags_valid = nvc0_vram_flags_valid; engine->pm.temp_get = nv84_temp_get; engine->pm.clocks_get = nvc0_pm_clocks_get; engine->pm.clocks_pre = nvc0_pm_clocks_pre; @@ -301,19 +246,12 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev) engine->instmem.map = nv50_instmem_map; engine->instmem.unmap = nv50_instmem_unmap; engine->instmem.flush = nv84_instmem_flush; - engine->fb.init = nvc0_fb_init; - engine->fb.takedown = nvc0_fb_takedown; engine->display.early_init = nouveau_stub_init; engine->display.late_takedown = nouveau_stub_takedown; engine->display.create = nvd0_display_create; engine->display.destroy = nvd0_display_destroy; engine->display.init = nvd0_display_init; engine->display.fini = nvd0_display_fini; - engine->vram.init = nvc0_vram_init; - engine->vram.takedown = nv50_vram_fini; - engine->vram.get = nvc0_vram_new; - engine->vram.put = nv50_vram_del; - engine->vram.flags_valid = nvc0_vram_flags_valid; engine->pm.temp_get = nv84_temp_get; engine->pm.clocks_get = nvc0_pm_clocks_get; engine->pm.clocks_pre = nvc0_pm_clocks_pre; @@ -331,19 +269,12 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev) engine->instmem.map = nv50_instmem_map; engine->instmem.unmap = nv50_instmem_unmap; engine->instmem.flush = nv84_instmem_flush; - engine->fb.init = nvc0_fb_init; - engine->fb.takedown = nvc0_fb_takedown; engine->display.early_init = nouveau_stub_init; engine->display.late_takedown = nouveau_stub_takedown; engine->display.create = nvd0_display_create; engine->display.destroy = nvd0_display_destroy; engine->display.init = nvd0_display_init; engine->display.fini = nvd0_display_fini; - engine->vram.init = nvc0_vram_init; - engine->vram.takedown = nv50_vram_fini; - engine->vram.get = nvc0_vram_new; - engine->vram.put = nv50_vram_del; - engine->vram.flags_valid = nvc0_vram_flags_valid; break; default: NV_ERROR(dev, "NV%02x unsupported\n", dev_priv->chipset); @@ -488,18 +419,9 @@ nouveau_card_init(struct drm_device *dev) nv_mask(dev, 0x00088080, 0x00000800, 0x00000000); } - /* PFB */ - ret = engine->fb.init(dev); - if (ret) - goto out_bios; - - ret = engine->vram.init(dev); - if (ret) - goto out_fb; - ret = nouveau_gpuobj_init(dev); if (ret) - goto out_vram; + goto out_bios; ret = engine->instmem.init(dev); if (ret) @@ -734,10 +656,6 @@ out_instmem: engine->instmem.takedown(dev); out_gpuobj: nouveau_gpuobj_takedown(dev); -out_vram: - engine->vram.takedown(dev); -out_fb: - engine->fb.takedown(dev); out_bios: nouveau_bios_takedown(dev); out_display_early: @@ -788,9 +706,6 @@ static void nouveau_card_takedown(struct drm_device *dev) engine->instmem.takedown(dev); nouveau_gpuobj_takedown(dev); - engine->vram.takedown(dev); - engine->fb.takedown(dev); - nouveau_bios_takedown(dev); engine->display.late_takedown(dev); diff --git a/drivers/gpu/drm/nouveau/nouveau_util.c b/drivers/gpu/drm/nouveau/nouveau_util.c index e51b51503baa..6bff634c95fe 100644 --- a/drivers/gpu/drm/nouveau/nouveau_util.c +++ b/drivers/gpu/drm/nouveau/nouveau_util.c @@ -26,50 +26,11 @@ */ #include - #include "nouveau_util.h" -static DEFINE_RATELIMIT_STATE(nouveau_ratelimit_state, 3 * HZ, 20); - -void -nouveau_bitfield_print(const struct nouveau_bitfield *bf, u32 value) -{ - while (bf->name) { - if (value & bf->mask) { - printk(" %s", bf->name); - value &= ~bf->mask; - } - - bf++; - } - - if (value) - printk(" (unknown bits 0x%08x)", value); -} +#include -const struct nouveau_enum * -nouveau_enum_find(const struct nouveau_enum *en, u32 value) -{ - while (en->name) { - if (en->value == value) - return en; - en++; - } - - return NULL; -} - -void -nouveau_enum_print(const struct nouveau_enum *en, u32 value) -{ - en = nouveau_enum_find(en, value); - if (en) { - printk("%s", en->name); - return; - } - - printk("(unknown enum 0x%08x)", value); -} +static DEFINE_RATELIMIT_STATE(nouveau_ratelimit_state, 3 * HZ, 20); int nouveau_ratelimit(void) diff --git a/drivers/gpu/drm/nouveau/nouveau_util.h b/drivers/gpu/drm/nouveau/nouveau_util.h index b97719fbb739..114293758f8c 100644 --- a/drivers/gpu/drm/nouveau/nouveau_util.h +++ b/drivers/gpu/drm/nouveau/nouveau_util.h @@ -28,21 +28,7 @@ #ifndef __NOUVEAU_UTIL_H__ #define __NOUVEAU_UTIL_H__ -struct nouveau_bitfield { - u32 mask; - const char *name; -}; - -struct nouveau_enum { - u32 value; - const char *name; - void *data; -}; - -void nouveau_bitfield_print(const struct nouveau_bitfield *, u32 value); -void nouveau_enum_print(const struct nouveau_enum *, u32 value); -const struct nouveau_enum * -nouveau_enum_find(const struct nouveau_enum *, u32 value); +#include int nouveau_ratelimit(void); diff --git a/drivers/gpu/drm/nouveau/nv50_evo.c b/drivers/gpu/drm/nouveau/nv50_evo.c index 5731cb3df67f..7a1424243665 100644 --- a/drivers/gpu/drm/nouveau/nv50_evo.c +++ b/drivers/gpu/drm/nouveau/nv50_evo.c @@ -300,24 +300,24 @@ nv50_evo_create(struct drm_device *dev) /* create some default objects for the scanout memtypes we support */ ret = nv50_evo_dmaobj_new(disp->master, NvEvoVRAM, 0x0000, - 0, dev_priv->vram_size, NULL); + 0, nvfb_vram_size(dev), NULL); if (ret) goto err; ret = nv50_evo_dmaobj_new(disp->master, NvEvoVRAM_LP, 0x80000000, - 0, dev_priv->vram_size, NULL); + 0, nvfb_vram_size(dev), NULL); if (ret) goto err; ret = nv50_evo_dmaobj_new(disp->master, NvEvoFB32, 0x80000000 | (dev_priv->chipset < 0xc0 ? 0x7a00 : 0xfe00), - 0, dev_priv->vram_size, NULL); + 0, nvfb_vram_size(dev), NULL); if (ret) goto err; ret = nv50_evo_dmaobj_new(disp->master, NvEvoFB16, 0x80000000 | (dev_priv->chipset < 0xc0 ? 0x7000 : 0xfe00), - 0, dev_priv->vram_size, NULL); + 0, nvfb_vram_size(dev), NULL); if (ret) goto err; @@ -352,21 +352,21 @@ nv50_evo_create(struct drm_device *dev) goto err; ret = nv50_evo_dmaobj_new(dispc->sync, NvEvoVRAM_LP, 0x80000000, - 0, dev_priv->vram_size, NULL); + 0, nvfb_vram_size(dev), NULL); if (ret) goto err; ret = nv50_evo_dmaobj_new(dispc->sync, NvEvoFB32, 0x80000000 | (dev_priv->chipset < 0xc0 ? 0x7a00 : 0xfe00), - 0, dev_priv->vram_size, NULL); + 0, nvfb_vram_size(dev), NULL); if (ret) goto err; ret = nv50_evo_dmaobj_new(dispc->sync, NvEvoFB16, 0x80000000 | (dev_priv->chipset < 0xc0 ? 0x7000 : 0xfe00), - 0, dev_priv->vram_size, NULL); + 0, nvfb_vram_size(dev), NULL); if (ret) goto err; diff --git a/drivers/gpu/drm/nouveau/nv50_pm.c b/drivers/gpu/drm/nouveau/nv50_pm.c index 378ca8ca9d6a..142cd4e83767 100644 --- a/drivers/gpu/drm/nouveau/nv50_pm.c +++ b/drivers/gpu/drm/nouveau/nv50_pm.c @@ -471,17 +471,16 @@ mclk_mrg(struct nouveau_mem_exec_func *exec, int mr) static void mclk_mrs(struct nouveau_mem_exec_func *exec, int mr, u32 data) { - struct drm_nouveau_private *dev_priv = exec->dev->dev_private; struct nv50_pm_state *info = exec->priv; struct hwsq_ucode *hwsq = &info->mclk_hwsq; if (mr <= 1) { - if (dev_priv->vram_rank_B) + if (nvfb_vram_rank_B(exec->dev)) hwsq_wr32(hwsq, 0x1002c8 + ((mr - 0) * 4), data); hwsq_wr32(hwsq, 0x1002c0 + ((mr - 0) * 4), data); } else if (mr <= 3) { - if (dev_priv->vram_rank_B) + if (nvfb_vram_rank_B(exec->dev)) hwsq_wr32(hwsq, 0x1002e8 + ((mr - 2) * 4), data); hwsq_wr32(hwsq, 0x1002e0 + ((mr - 2) * 4), data); } diff --git a/drivers/gpu/drm/nouveau/nva3_pm.c b/drivers/gpu/drm/nouveau/nva3_pm.c index 847c616de12f..2f7ee50440ae 100644 --- a/drivers/gpu/drm/nouveau/nva3_pm.c +++ b/drivers/gpu/drm/nouveau/nva3_pm.c @@ -361,15 +361,13 @@ mclk_mrg(struct nouveau_mem_exec_func *exec, int mr) static void mclk_mrs(struct nouveau_mem_exec_func *exec, int mr, u32 data) { - struct drm_nouveau_private *dev_priv = exec->dev->dev_private; - if (mr <= 1) { - if (dev_priv->vram_rank_B) + if (nvfb_vram_rank_B(exec->dev)) nv_wr32(exec->dev, 0x1002c8 + ((mr - 0) * 4), data); nv_wr32(exec->dev, 0x1002c0 + ((mr - 0) * 4), data); } else if (mr <= 3) { - if (dev_priv->vram_rank_B) + if (nvfb_vram_rank_B(exec->dev)) nv_wr32(exec->dev, 0x1002e8 + ((mr - 2) * 4), data); nv_wr32(exec->dev, 0x1002e0 + ((mr - 2) * 4), data); } diff --git a/drivers/gpu/drm/nouveau/nvc0_pm.c b/drivers/gpu/drm/nouveau/nvc0_pm.c index 4a21a7264c3c..a14711c25176 100644 --- a/drivers/gpu/drm/nouveau/nvc0_pm.c +++ b/drivers/gpu/drm/nouveau/nvc0_pm.c @@ -459,8 +459,7 @@ static u32 mclk_mrg(struct nouveau_mem_exec_func *exec, int mr) { struct drm_device *dev = exec->dev; - struct drm_nouveau_private *dev_priv = dev->dev_private; - if (dev_priv->vram_type != NV_MEM_TYPE_GDDR5) { + if (nvfb_vram_type(dev) != NV_MEM_TYPE_GDDR5) { if (mr <= 1) return nv_rd32(dev, 0x10f300 + ((mr - 0) * 4)); return nv_rd32(dev, 0x10f320 + ((mr - 2) * 4)); @@ -478,16 +477,15 @@ static void mclk_mrs(struct nouveau_mem_exec_func *exec, int mr, u32 data) { struct drm_device *dev = exec->dev; - struct drm_nouveau_private *dev_priv = dev->dev_private; - if (dev_priv->vram_type != NV_MEM_TYPE_GDDR5) { + if (nvfb_vram_type(dev) != NV_MEM_TYPE_GDDR5) { if (mr <= 1) { nv_wr32(dev, 0x10f300 + ((mr - 0) * 4), data); - if (dev_priv->vram_rank_B) + if (nvfb_vram_rank_B(dev)) nv_wr32(dev, 0x10f308 + ((mr - 0) * 4), data); } else if (mr <= 3) { nv_wr32(dev, 0x10f320 + ((mr - 2) * 4), data); - if (dev_priv->vram_rank_B) + if (nvfb_vram_rank_B(dev)) nv_wr32(dev, 0x10f328 + ((mr - 2) * 4), data); } } else { diff --git a/drivers/gpu/drm/nouveau/nvd0_display.c b/drivers/gpu/drm/nouveau/nvd0_display.c index d26dd02f3d13..8d9fc00718f0 100644 --- a/drivers/gpu/drm/nouveau/nvd0_display.c +++ b/drivers/gpu/drm/nouveau/nvd0_display.c @@ -2077,7 +2077,7 @@ nvd0_display_create(struct drm_device *dev) nv_wo32(disp->mem, dmao + 0x20, 0x00000049); nv_wo32(disp->mem, dmao + 0x24, 0x00000000); - nv_wo32(disp->mem, dmao + 0x28, (dev_priv->vram_size - 1) >> 8); + nv_wo32(disp->mem, dmao + 0x28, (nvfb_vram_size(dev) - 1) >> 8); nv_wo32(disp->mem, dmao + 0x2c, 0x00000000); nv_wo32(disp->mem, dmao + 0x30, 0x00000000); nv_wo32(disp->mem, dmao + 0x34, 0x00000000); @@ -2087,7 +2087,7 @@ nvd0_display_create(struct drm_device *dev) nv_wo32(disp->mem, dmao + 0x40, 0x00000009); nv_wo32(disp->mem, dmao + 0x44, 0x00000000); - nv_wo32(disp->mem, dmao + 0x48, (dev_priv->vram_size - 1) >> 8); + nv_wo32(disp->mem, dmao + 0x48, (nvfb_vram_size(dev) - 1) >> 8); nv_wo32(disp->mem, dmao + 0x4c, 0x00000000); nv_wo32(disp->mem, dmao + 0x50, 0x00000000); nv_wo32(disp->mem, dmao + 0x54, 0x00000000); @@ -2097,7 +2097,7 @@ nvd0_display_create(struct drm_device *dev) nv_wo32(disp->mem, dmao + 0x60, 0x0fe00009); nv_wo32(disp->mem, dmao + 0x64, 0x00000000); - nv_wo32(disp->mem, dmao + 0x68, (dev_priv->vram_size - 1) >> 8); + nv_wo32(disp->mem, dmao + 0x68, (nvfb_vram_size(dev) - 1) >> 8); nv_wo32(disp->mem, dmao + 0x6c, 0x00000000); nv_wo32(disp->mem, dmao + 0x70, 0x00000000); nv_wo32(disp->mem, dmao + 0x74, 0x00000000); -- cgit v1.2.3 From 3863c9bc887e9638a9d905d55f6038641ece78d6 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Sat, 14 Jul 2012 19:09:17 +1000 Subject: drm/nouveau/instmem: completely new implementation, as a subdev module v2 (Ben Skeggs): - some fixes for 64KiB PAGE_SIZE - fix porting issues in (currently unused) nv41/nv44 pciegart code Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/Makefile | 9 +- drivers/gpu/drm/nouveau/core/core/ramht.c | 15 +- drivers/gpu/drm/nouveau/core/engine/bsp/nv84.c | 1 - drivers/gpu/drm/nouveau/core/engine/copy/nva3.c | 12 +- drivers/gpu/drm/nouveau/core/engine/copy/nvc0.c | 8 +- drivers/gpu/drm/nouveau/core/engine/crypt/nv84.c | 17 +- drivers/gpu/drm/nouveau/core/engine/crypt/nv98.c | 12 +- drivers/gpu/drm/nouveau/core/engine/fifo/nv04.c | 15 +- drivers/gpu/drm/nouveau/core/engine/fifo/nv10.c | 9 +- drivers/gpu/drm/nouveau/core/engine/fifo/nv17.c | 15 +- drivers/gpu/drm/nouveau/core/engine/fifo/nv40.c | 15 +- drivers/gpu/drm/nouveau/core/engine/fifo/nv50.c | 22 +- drivers/gpu/drm/nouveau/core/engine/fifo/nv84.c | 25 +- drivers/gpu/drm/nouveau/core/engine/fifo/nvc0.c | 16 +- drivers/gpu/drm/nouveau/core/engine/fifo/nve0.c | 16 +- drivers/gpu/drm/nouveau/core/engine/graph/nv20.c | 8 +- drivers/gpu/drm/nouveau/core/engine/graph/nv40.c | 10 +- drivers/gpu/drm/nouveau/core/engine/graph/nv50.c | 20 +- drivers/gpu/drm/nouveau/core/engine/graph/nvc0.c | 45 +- drivers/gpu/drm/nouveau/core/engine/graph/nve0.c | 40 +- drivers/gpu/drm/nouveau/core/engine/mpeg/nv31.c | 8 +- drivers/gpu/drm/nouveau/core/engine/mpeg/nv50.c | 10 +- drivers/gpu/drm/nouveau/core/engine/ppp/nv98.c | 1 - drivers/gpu/drm/nouveau/core/engine/vp/nv84.c | 1 - drivers/gpu/drm/nouveau/core/include/subdev/bar.h | 55 +++ drivers/gpu/drm/nouveau/core/include/subdev/fb.h | 1 + .../gpu/drm/nouveau/core/include/subdev/instmem.h | 74 ++++ drivers/gpu/drm/nouveau/core/include/subdev/vm.h | 88 ++-- drivers/gpu/drm/nouveau/core/subdev/bar/base.c | 135 ++++++ drivers/gpu/drm/nouveau/core/subdev/bar/nv50.c | 263 ++++++++++++ drivers/gpu/drm/nouveau/core/subdev/bar/nvc0.c | 215 ++++++++++ drivers/gpu/drm/nouveau/core/subdev/device/nv04.c | 6 + drivers/gpu/drm/nouveau/core/subdev/device/nv10.c | 18 + drivers/gpu/drm/nouveau/core/subdev/device/nv20.c | 10 + drivers/gpu/drm/nouveau/core/subdev/device/nv30.c | 12 + drivers/gpu/drm/nouveau/core/subdev/device/nv40.c | 34 ++ drivers/gpu/drm/nouveau/core/subdev/device/nv50.c | 45 ++ drivers/gpu/drm/nouveau/core/subdev/device/nvc0.c | 27 ++ drivers/gpu/drm/nouveau/core/subdev/device/nve0.c | 9 + drivers/gpu/drm/nouveau/core/subdev/fb/nv40.c | 46 +-- drivers/gpu/drm/nouveau/core/subdev/instmem/base.c | 135 ++++++ drivers/gpu/drm/nouveau/core/subdev/instmem/nv04.c | 254 +++++++----- drivers/gpu/drm/nouveau/core/subdev/instmem/nv04.h | 21 + drivers/gpu/drm/nouveau/core/subdev/instmem/nv40.c | 220 +++++----- drivers/gpu/drm/nouveau/core/subdev/instmem/nv50.c | 458 ++++++--------------- drivers/gpu/drm/nouveau/core/subdev/instmem/nvc0.c | 222 ---------- drivers/gpu/drm/nouveau/core/subdev/vm/base.c | 149 +++---- drivers/gpu/drm/nouveau/core/subdev/vm/nv04.c | 150 +++++++ drivers/gpu/drm/nouveau/core/subdev/vm/nv04.h | 13 + drivers/gpu/drm/nouveau/core/subdev/vm/nv41.c | 149 +++++++ drivers/gpu/drm/nouveau/core/subdev/vm/nv44.c | 257 ++++++++++++ drivers/gpu/drm/nouveau/core/subdev/vm/nv50.c | 108 +++-- drivers/gpu/drm/nouveau/core/subdev/vm/nvc0.c | 111 +++-- drivers/gpu/drm/nouveau/nouveau_bo.c | 56 +-- drivers/gpu/drm/nouveau/nouveau_channel.c | 3 + drivers/gpu/drm/nouveau/nouveau_compat.c | 145 +++++++ drivers/gpu/drm/nouveau/nouveau_compat.h | 42 ++ drivers/gpu/drm/nouveau/nouveau_drv.c | 19 - drivers/gpu/drm/nouveau/nouveau_drv.h | 156 +------ drivers/gpu/drm/nouveau/nouveau_gpuobj.c | 327 +-------------- drivers/gpu/drm/nouveau/nouveau_mem.c | 71 +++- drivers/gpu/drm/nouveau/nouveau_notifier.c | 12 - drivers/gpu/drm/nouveau/nouveau_sgdma.c | 315 +------------- drivers/gpu/drm/nouveau/nouveau_state.c | 142 +------ drivers/gpu/drm/nouveau/nv50_display.c | 2 +- drivers/gpu/drm/nouveau/nv50_evo.c | 10 +- drivers/gpu/drm/nouveau/nv50_software.c | 4 +- drivers/gpu/drm/nouveau/nv84_fence.c | 2 +- drivers/gpu/drm/nouveau/nvd0_display.c | 5 +- 69 files changed, 2777 insertions(+), 2169 deletions(-) create mode 100644 drivers/gpu/drm/nouveau/core/include/subdev/bar.h create mode 100644 drivers/gpu/drm/nouveau/core/include/subdev/instmem.h create mode 100644 drivers/gpu/drm/nouveau/core/subdev/bar/base.c create mode 100644 drivers/gpu/drm/nouveau/core/subdev/bar/nv50.c create mode 100644 drivers/gpu/drm/nouveau/core/subdev/bar/nvc0.c create mode 100644 drivers/gpu/drm/nouveau/core/subdev/instmem/base.c delete mode 100644 drivers/gpu/drm/nouveau/core/subdev/instmem/nvc0.c create mode 100644 drivers/gpu/drm/nouveau/core/subdev/vm/nv04.c create mode 100644 drivers/gpu/drm/nouveau/core/subdev/vm/nv04.h create mode 100644 drivers/gpu/drm/nouveau/core/subdev/vm/nv41.c create mode 100644 drivers/gpu/drm/nouveau/core/subdev/vm/nv44.c (limited to 'drivers/gpu/drm/nouveau/nouveau_mem.c') diff --git a/drivers/gpu/drm/nouveau/Makefile b/drivers/gpu/drm/nouveau/Makefile index 68043a40d9ea..9a86ae3e6807 100644 --- a/drivers/gpu/drm/nouveau/Makefile +++ b/drivers/gpu/drm/nouveau/Makefile @@ -9,6 +9,7 @@ ccflags-y += -I$(src) nouveau-y := core/core/client.o nouveau-y += core/core/engine.o nouveau-y += core/core/enum.o +nouveau-y += core/core/gpuobj.o nouveau-y += core/core/handle.o nouveau-y += core/core/mm.o nouveau-y += core/core/namedb.o @@ -19,6 +20,9 @@ nouveau-y += core/core/printk.o nouveau-y += core/core/ramht.o nouveau-y += core/core/subdev.o +nouveau-y += core/subdev/bar/base.o +nouveau-y += core/subdev/bar/nv50.o +nouveau-y += core/subdev/bar/nvc0.o nouveau-y += core/subdev/bios/base.o nouveau-y += core/subdev/bios/bit.o nouveau-y += core/subdev/bios/conn.o @@ -66,10 +70,10 @@ 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/base.o nouveau-y += core/subdev/instmem/nv04.o nouveau-y += core/subdev/instmem/nv40.o nouveau-y += core/subdev/instmem/nv50.o -nouveau-y += core/subdev/instmem/nvc0.o nouveau-y += core/subdev/ltcg/nvc0.o nouveau-y += core/subdev/mc/base.o nouveau-y += core/subdev/mc/nv04.o @@ -80,6 +84,9 @@ nouveau-y += core/subdev/mc/nvc0.o nouveau-y += core/subdev/timer/base.o nouveau-y += core/subdev/timer/nv04.o nouveau-y += core/subdev/vm/base.o +nouveau-y += core/subdev/vm/nv04.o +nouveau-y += core/subdev/vm/nv41.o +nouveau-y += core/subdev/vm/nv44.o nouveau-y += core/subdev/vm/nv50.o nouveau-y += core/subdev/vm/nvc0.o diff --git a/drivers/gpu/drm/nouveau/core/core/ramht.c b/drivers/gpu/drm/nouveau/core/core/ramht.c index 59c16192f0e4..5c22864fbd2c 100644 --- a/drivers/gpu/drm/nouveau/core/core/ramht.c +++ b/drivers/gpu/drm/nouveau/core/core/ramht.c @@ -86,7 +86,6 @@ nouveau_ramht_insert(struct nouveau_channel *chan, u32 handle, { struct drm_device *dev = chan->dev; struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_instmem_engine *instmem = &dev_priv->engine.instmem; struct nouveau_ramht_entry *entry; struct nouveau_gpuobj *ramht = chan->ramht->gpuobj; unsigned long flags; @@ -104,21 +103,21 @@ nouveau_ramht_insert(struct nouveau_channel *chan, u32 handle, nouveau_gpuobj_ref(gpuobj, &entry->gpuobj); if (dev_priv->card_type < NV_40) { - ctx = NV_RAMHT_CONTEXT_VALID | (gpuobj->pinst >> 4) | + ctx = NV_RAMHT_CONTEXT_VALID | (gpuobj->addr >> 4) | (chan->id << NV_RAMHT_CONTEXT_CHANNEL_SHIFT) | (gpuobj->engine << NV_RAMHT_CONTEXT_ENGINE_SHIFT); } else if (dev_priv->card_type < NV_50) { - ctx = (gpuobj->pinst >> 4) | + ctx = (gpuobj->addr >> 4) | (chan->id << NV40_RAMHT_CONTEXT_CHANNEL_SHIFT) | (gpuobj->engine << NV40_RAMHT_CONTEXT_ENGINE_SHIFT); } else { if (gpuobj->engine == NVOBJ_ENGINE_DISPLAY) { - ctx = (gpuobj->cinst << 10) | + ctx = (gpuobj->node->offset << 10) | (chan->id << 28) | chan->id; /* HASH_TAG */ } else { - ctx = (gpuobj->cinst >> 4) | + ctx = (gpuobj->node->offset >> 4) | ((gpuobj->engine << NV40_RAMHT_CONTEXT_ENGINE_SHIFT)); } @@ -137,7 +136,7 @@ nouveau_ramht_insert(struct nouveau_channel *chan, u32 handle, nv_wo32(ramht, co + 4, ctx); spin_unlock_irqrestore(&chan->ramht->lock, flags); - instmem->flush(dev); + nvimem_flush(dev); return 0; } NV_DEBUG(dev, "collision ch%d 0x%08x: h=0x%08x\n", @@ -184,8 +183,6 @@ static void nouveau_ramht_remove_hash(struct nouveau_channel *chan, u32 handle) { struct drm_device *dev = chan->dev; - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_instmem_engine *instmem = &dev_priv->engine.instmem; struct nouveau_gpuobj *ramht = chan->ramht->gpuobj; unsigned long flags; u32 co, ho; @@ -201,7 +198,7 @@ nouveau_ramht_remove_hash(struct nouveau_channel *chan, u32 handle) chan->id, co, handle, nv_ro32(ramht, co + 4)); nv_wo32(ramht, co + 0, 0x00000000); nv_wo32(ramht, co + 4, 0x00000000); - instmem->flush(dev); + nvimem_flush(dev); goto out; } diff --git a/drivers/gpu/drm/nouveau/core/engine/bsp/nv84.c b/drivers/gpu/drm/nouveau/core/engine/bsp/nv84.c index db3b57369830..4b809319e831 100644 --- a/drivers/gpu/drm/nouveau/core/engine/bsp/nv84.c +++ b/drivers/gpu/drm/nouveau/core/engine/bsp/nv84.c @@ -25,7 +25,6 @@ #include "drmP.h" #include "nouveau_drv.h" #include "nouveau_util.h" -#include #include /*XXX: This stub is currently used on NV98+ also, as soon as this becomes diff --git a/drivers/gpu/drm/nouveau/core/engine/copy/nva3.c b/drivers/gpu/drm/nouveau/core/engine/copy/nva3.c index fec52463456a..9150c5ed16c3 100644 --- a/drivers/gpu/drm/nouveau/core/engine/copy/nva3.c +++ b/drivers/gpu/drm/nouveau/core/engine/copy/nva3.c @@ -26,7 +26,6 @@ #include "drmP.h" #include "nouveau_drv.h" #include "nouveau_util.h" -#include #include #include "fuc/nva3.fuc.h" @@ -38,7 +37,6 @@ static int nva3_copy_context_new(struct nouveau_channel *chan, int engine) { struct drm_device *dev = chan->dev; - struct drm_nouveau_private *dev_priv = dev->dev_private; struct nouveau_gpuobj *ramin = chan->ramin; struct nouveau_gpuobj *ctx = NULL; int ret; @@ -51,14 +49,14 @@ nva3_copy_context_new(struct nouveau_channel *chan, int engine) return ret; nv_wo32(ramin, 0xc0, 0x00190000); - nv_wo32(ramin, 0xc4, ctx->vinst + ctx->size - 1); - nv_wo32(ramin, 0xc8, ctx->vinst); + nv_wo32(ramin, 0xc4, ctx->addr + ctx->size - 1); + nv_wo32(ramin, 0xc8, ctx->addr); nv_wo32(ramin, 0xcc, 0x00000000); nv_wo32(ramin, 0xd0, 0x00000000); nv_wo32(ramin, 0xd4, 0x00000000); - dev_priv->engine.instmem.flush(dev); + nvimem_flush(dev); - atomic_inc(&chan->vm->engref[engine]); + nvvm_engref(chan->vm, engine, 1); chan->engctx[engine] = ctx; return 0; } @@ -84,7 +82,7 @@ nva3_copy_context_del(struct nouveau_channel *chan, int engine) for (i = 0xc0; i <= 0xd4; i += 4) nv_wo32(chan->ramin, i, 0x00000000); - atomic_dec(&chan->vm->engref[engine]); + nvvm_engref(chan->vm, engine, -1); nouveau_gpuobj_ref(NULL, &ctx); chan->engctx[engine] = ctx; } diff --git a/drivers/gpu/drm/nouveau/core/engine/copy/nvc0.c b/drivers/gpu/drm/nouveau/core/engine/copy/nvc0.c index 926f21c0ebce..f39de5a593d6 100644 --- a/drivers/gpu/drm/nouveau/core/engine/copy/nvc0.c +++ b/drivers/gpu/drm/nouveau/core/engine/copy/nvc0.c @@ -26,7 +26,6 @@ #include "drmP.h" #include "nouveau_drv.h" #include "nouveau_util.h" -#include #include #include "fuc/nvc0.fuc.h" @@ -49,7 +48,6 @@ nvc0_copy_context_new(struct nouveau_channel *chan, int engine) struct nvc0_copy_engine *pcopy = nv_engine(chan->dev, engine); struct nvc0_copy_chan *cctx; struct drm_device *dev = chan->dev; - struct drm_nouveau_private *dev_priv = dev->dev_private; struct nouveau_gpuobj *ramin = chan->ramin; int ret; @@ -62,14 +60,14 @@ nvc0_copy_context_new(struct nouveau_channel *chan, int engine) if (ret) return ret; - ret = nouveau_gpuobj_map_vm(cctx->mem, NV_MEM_ACCESS_RW, chan->vm, + ret = nouveau_gpuobj_map_vm(cctx->mem, chan->vm, NV_MEM_ACCESS_RW, &cctx->vma); if (ret) return ret; nv_wo32(ramin, pcopy->ctx + 0, lower_32_bits(cctx->vma.offset)); nv_wo32(ramin, pcopy->ctx + 4, upper_32_bits(cctx->vma.offset)); - dev_priv->engine.instmem.flush(dev); + nvimem_flush(dev); return 0; } @@ -88,7 +86,7 @@ nvc0_copy_context_del(struct nouveau_channel *chan, int engine) struct drm_device *dev = chan->dev; u32 inst; - inst = (chan->ramin->vinst >> 12); + inst = (chan->ramin->addr >> 12); inst |= 0x40000000; /* disable fifo access */ diff --git a/drivers/gpu/drm/nouveau/core/engine/crypt/nv84.c b/drivers/gpu/drm/nouveau/core/engine/crypt/nv84.c index 388138946ad9..63051ab0ecca 100644 --- a/drivers/gpu/drm/nouveau/core/engine/crypt/nv84.c +++ b/drivers/gpu/drm/nouveau/core/engine/crypt/nv84.c @@ -25,7 +25,6 @@ #include "drmP.h" #include "nouveau_drv.h" #include "nouveau_util.h" -#include #include struct nv84_crypt_engine { @@ -36,7 +35,6 @@ static int nv84_crypt_context_new(struct nouveau_channel *chan, int engine) { struct drm_device *dev = chan->dev; - struct drm_nouveau_private *dev_priv = dev->dev_private; struct nouveau_gpuobj *ramin = chan->ramin; struct nouveau_gpuobj *ctx; int ret; @@ -49,14 +47,14 @@ nv84_crypt_context_new(struct nouveau_channel *chan, int engine) return ret; nv_wo32(ramin, 0xa0, 0x00190000); - nv_wo32(ramin, 0xa4, ctx->vinst + ctx->size - 1); - nv_wo32(ramin, 0xa8, ctx->vinst); + nv_wo32(ramin, 0xa4, ctx->addr + ctx->size - 1); + nv_wo32(ramin, 0xa8, ctx->addr); nv_wo32(ramin, 0xac, 0); nv_wo32(ramin, 0xb0, 0); nv_wo32(ramin, 0xb4, 0); - dev_priv->engine.instmem.flush(dev); + nvimem_flush(dev); - atomic_inc(&chan->vm->engref[engine]); + nvvm_engref(chan->vm, engine, 1); chan->engctx[engine] = ctx; return 0; } @@ -68,7 +66,7 @@ nv84_crypt_context_del(struct nouveau_channel *chan, int engine) struct drm_device *dev = chan->dev; u32 inst; - inst = (chan->ramin->vinst >> 12); + inst = (chan->ramin->addr >> 12); inst |= 0x80000000; /* mark context as invalid if still on the hardware, not @@ -84,7 +82,7 @@ nv84_crypt_context_del(struct nouveau_channel *chan, int engine) nouveau_gpuobj_ref(NULL, &ctx); - atomic_dec(&chan->vm->engref[engine]); + nvvm_engref(chan->vm, engine, -1); chan->engctx[engine] = NULL; } @@ -93,7 +91,6 @@ nv84_crypt_object_new(struct nouveau_channel *chan, int engine, u32 handle, u16 class) { struct drm_device *dev = chan->dev; - struct drm_nouveau_private *dev_priv = dev->dev_private; struct nouveau_gpuobj *obj = NULL; int ret; @@ -104,7 +101,7 @@ nv84_crypt_object_new(struct nouveau_channel *chan, int engine, obj->class = class; nv_wo32(obj, 0x00, class); - dev_priv->engine.instmem.flush(dev); + nvimem_flush(dev); ret = nouveau_ramht_insert(chan, handle, obj); nouveau_gpuobj_ref(NULL, &obj); diff --git a/drivers/gpu/drm/nouveau/core/engine/crypt/nv98.c b/drivers/gpu/drm/nouveau/core/engine/crypt/nv98.c index 563f60d1ce6e..c9adc1b8a7db 100644 --- a/drivers/gpu/drm/nouveau/core/engine/crypt/nv98.c +++ b/drivers/gpu/drm/nouveau/core/engine/crypt/nv98.c @@ -26,7 +26,6 @@ #include "nouveau_drv.h" #include "nouveau_util.h" -#include #include #include "fuc/nv98.fuc.h" @@ -43,7 +42,6 @@ static int nv98_crypt_context_new(struct nouveau_channel *chan, int engine) { struct drm_device *dev = chan->dev; - struct drm_nouveau_private *dev_priv = dev->dev_private; struct nv98_crypt_priv *priv = nv_engine(dev, engine); struct nv98_crypt_chan *cctx; int ret; @@ -52,7 +50,7 @@ nv98_crypt_context_new(struct nouveau_channel *chan, int engine) if (!cctx) return -ENOMEM; - atomic_inc(&chan->vm->engref[engine]); + nvvm_engref(chan->vm, engine, 1); ret = nouveau_gpuobj_new(dev, chan, 256, 0, NVOBJ_FLAG_ZERO_ALLOC | NVOBJ_FLAG_ZERO_FREE, &cctx->mem); @@ -60,12 +58,12 @@ nv98_crypt_context_new(struct nouveau_channel *chan, int engine) goto error; nv_wo32(chan->ramin, 0xa0, 0x00190000); - nv_wo32(chan->ramin, 0xa4, cctx->mem->vinst + cctx->mem->size - 1); - nv_wo32(chan->ramin, 0xa8, cctx->mem->vinst); + nv_wo32(chan->ramin, 0xa4, cctx->mem->addr + cctx->mem->size - 1); + nv_wo32(chan->ramin, 0xa8, cctx->mem->addr); nv_wo32(chan->ramin, 0xac, 0x00000000); nv_wo32(chan->ramin, 0xb0, 0x00000000); nv_wo32(chan->ramin, 0xb4, 0x00000000); - dev_priv->engine.instmem.flush(dev); + nvimem_flush(dev); error: if (ret) @@ -84,7 +82,7 @@ nv98_crypt_context_del(struct nouveau_channel *chan, int engine) nouveau_gpuobj_ref(NULL, &cctx->mem); - atomic_dec(&chan->vm->engref[engine]); + nvvm_engref(chan->vm, engine, -1); chan->engctx[engine] = NULL; kfree(cctx); } diff --git a/drivers/gpu/drm/nouveau/core/engine/fifo/nv04.c b/drivers/gpu/drm/nouveau/core/engine/fifo/nv04.c index ba76cf094a6b..6ab7eb0dd9bb 100644 --- a/drivers/gpu/drm/nouveau/core/engine/fifo/nv04.c +++ b/drivers/gpu/drm/nouveau/core/engine/fifo/nv04.c @@ -32,8 +32,6 @@ #include #include "nouveau_software.h" -#include - static struct ramfc_desc { unsigned bits:6; unsigned ctxs:5; @@ -120,7 +118,7 @@ nv04_fifo_context_new(struct nouveau_channel *chan, int engine) /* initialise default fifo context */ nv_wo32(priv->ramfc, fctx->ramfc + 0x00, chan->pushbuf_base); nv_wo32(priv->ramfc, fctx->ramfc + 0x04, chan->pushbuf_base); - nv_wo32(priv->ramfc, fctx->ramfc + 0x08, chan->pushbuf->pinst >> 4); + nv_wo32(priv->ramfc, fctx->ramfc + 0x08, chan->pushbuf->addr >> 4); nv_wo32(priv->ramfc, fctx->ramfc + 0x10, NV_PFIFO_CACHE1_DMA_FETCH_TRIG_128_BYTES | NV_PFIFO_CACHE1_DMA_FETCH_SIZE_128_BYTES | @@ -203,9 +201,9 @@ nv04_fifo_init(struct drm_device *dev, int engine) nv_wr32(dev, NV03_PFIFO_RAMHT, (0x03 << 24) /* search 128 */ | ((dev_priv->ramht->bits - 9) << 16) | - (dev_priv->ramht->gpuobj->pinst >> 8)); - nv_wr32(dev, NV03_PFIFO_RAMRO, priv->ramro->pinst >> 8); - nv_wr32(dev, NV03_PFIFO_RAMFC, priv->ramfc->pinst >> 8); + (dev_priv->ramht->gpuobj->addr >> 8)); + nv_wr32(dev, NV03_PFIFO_RAMRO, priv->ramro->addr >> 8); + nv_wr32(dev, NV03_PFIFO_RAMFC, priv->ramfc->addr >> 8); nv_wr32(dev, NV03_PFIFO_CACHE1_PUSH1, priv->base.channels); @@ -486,15 +484,14 @@ int nv04_fifo_create(struct drm_device *dev) { struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nv04_instmem_priv *imem = dev_priv->engine.instmem.priv; struct nv04_fifo_priv *priv; priv = kzalloc(sizeof(*priv), GFP_KERNEL); if (!priv) return -ENOMEM; - nouveau_gpuobj_ref(imem->ramro, &priv->ramro); - nouveau_gpuobj_ref(imem->ramfc, &priv->ramfc); + nouveau_gpuobj_ref(nvimem_ramro(dev), &priv->ramro); + nouveau_gpuobj_ref(nvimem_ramfc(dev), &priv->ramfc); priv->base.base.destroy = nv04_fifo_destroy; priv->base.base.init = nv04_fifo_init; diff --git a/drivers/gpu/drm/nouveau/core/engine/fifo/nv10.c b/drivers/gpu/drm/nouveau/core/engine/fifo/nv10.c index 0da287caf43f..2d38fa88f9c7 100644 --- a/drivers/gpu/drm/nouveau/core/engine/fifo/nv10.c +++ b/drivers/gpu/drm/nouveau/core/engine/fifo/nv10.c @@ -31,8 +31,6 @@ #include "nouveau_util.h" #include -#include - static struct ramfc_desc { unsigned bits:6; unsigned ctxs:5; @@ -91,7 +89,7 @@ nv10_fifo_context_new(struct nouveau_channel *chan, int engine) /* initialise default fifo context */ nv_wo32(priv->ramfc, fctx->ramfc + 0x00, chan->pushbuf_base); nv_wo32(priv->ramfc, fctx->ramfc + 0x04, chan->pushbuf_base); - nv_wo32(priv->ramfc, fctx->ramfc + 0x0c, chan->pushbuf->pinst >> 4); + nv_wo32(priv->ramfc, fctx->ramfc + 0x0c, chan->pushbuf->addr >> 4); nv_wo32(priv->ramfc, fctx->ramfc + 0x14, NV_PFIFO_CACHE1_DMA_FETCH_TRIG_128_BYTES | NV_PFIFO_CACHE1_DMA_FETCH_SIZE_128_BYTES | @@ -115,15 +113,14 @@ int nv10_fifo_create(struct drm_device *dev) { struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nv04_instmem_priv *imem = dev_priv->engine.instmem.priv; struct nv10_fifo_priv *priv; priv = kzalloc(sizeof(*priv), GFP_KERNEL); if (!priv) return -ENOMEM; - nouveau_gpuobj_ref(imem->ramro, &priv->ramro); - nouveau_gpuobj_ref(imem->ramfc, &priv->ramfc); + nouveau_gpuobj_ref(nvimem_ramro(dev), &priv->ramro); + nouveau_gpuobj_ref(nvimem_ramfc(dev), &priv->ramfc); priv->base.base.destroy = nv04_fifo_destroy; priv->base.base.init = nv04_fifo_init; diff --git a/drivers/gpu/drm/nouveau/core/engine/fifo/nv17.c b/drivers/gpu/drm/nouveau/core/engine/fifo/nv17.c index 99b88e0ef452..2f700a15e286 100644 --- a/drivers/gpu/drm/nouveau/core/engine/fifo/nv17.c +++ b/drivers/gpu/drm/nouveau/core/engine/fifo/nv17.c @@ -31,8 +31,6 @@ #include "nouveau_util.h" #include -#include - static struct ramfc_desc { unsigned bits:6; unsigned ctxs:5; @@ -96,7 +94,7 @@ nv17_fifo_context_new(struct nouveau_channel *chan, int engine) /* initialise default fifo context */ nv_wo32(priv->ramfc, fctx->ramfc + 0x00, chan->pushbuf_base); nv_wo32(priv->ramfc, fctx->ramfc + 0x04, chan->pushbuf_base); - nv_wo32(priv->ramfc, fctx->ramfc + 0x0c, chan->pushbuf->pinst >> 4); + nv_wo32(priv->ramfc, fctx->ramfc + 0x0c, chan->pushbuf->addr >> 4); nv_wo32(priv->ramfc, fctx->ramfc + 0x14, NV_PFIFO_CACHE1_DMA_FETCH_TRIG_128_BYTES | NV_PFIFO_CACHE1_DMA_FETCH_SIZE_128_BYTES | @@ -131,10 +129,10 @@ nv17_fifo_init(struct drm_device *dev, int engine) nv_wr32(dev, NV03_PFIFO_RAMHT, (0x03 << 24) /* search 128 */ | ((dev_priv->ramht->bits - 9) << 16) | - (dev_priv->ramht->gpuobj->pinst >> 8)); - nv_wr32(dev, NV03_PFIFO_RAMRO, priv->ramro->pinst >> 8); + (dev_priv->ramht->gpuobj->addr >> 8)); + nv_wr32(dev, NV03_PFIFO_RAMRO, priv->ramro->addr >> 8); nv_wr32(dev, NV03_PFIFO_RAMFC, 0x00010000 | - priv->ramfc->pinst >> 8); + priv->ramfc->addr >> 8); nv_wr32(dev, NV03_PFIFO_CACHE1_PUSH1, priv->base.channels); @@ -157,15 +155,14 @@ int nv17_fifo_create(struct drm_device *dev) { struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nv04_instmem_priv *imem = dev_priv->engine.instmem.priv; struct nv17_fifo_priv *priv; priv = kzalloc(sizeof(*priv), GFP_KERNEL); if (!priv) return -ENOMEM; - nouveau_gpuobj_ref(imem->ramro, &priv->ramro); - nouveau_gpuobj_ref(imem->ramfc, &priv->ramfc); + nouveau_gpuobj_ref(nvimem_ramro(dev), &priv->ramro); + nouveau_gpuobj_ref(nvimem_ramfc(dev), &priv->ramfc); priv->base.base.destroy = nv04_fifo_destroy; priv->base.base.init = nv17_fifo_init; diff --git a/drivers/gpu/drm/nouveau/core/engine/fifo/nv40.c b/drivers/gpu/drm/nouveau/core/engine/fifo/nv40.c index df53b9f27208..65a670f92a07 100644 --- a/drivers/gpu/drm/nouveau/core/engine/fifo/nv40.c +++ b/drivers/gpu/drm/nouveau/core/engine/fifo/nv40.c @@ -31,8 +31,6 @@ #include "nouveau_util.h" #include -#include - static struct ramfc_desc { unsigned bits:6; unsigned ctxs:5; @@ -104,7 +102,7 @@ nv40_fifo_context_new(struct nouveau_channel *chan, int engine) /* initialise default fifo context */ nv_wo32(priv->ramfc, fctx->ramfc + 0x00, chan->pushbuf_base); nv_wo32(priv->ramfc, fctx->ramfc + 0x04, chan->pushbuf_base); - nv_wo32(priv->ramfc, fctx->ramfc + 0x0c, chan->pushbuf->pinst >> 4); + nv_wo32(priv->ramfc, fctx->ramfc + 0x0c, chan->pushbuf->addr >> 4); nv_wo32(priv->ramfc, fctx->ramfc + 0x18, 0x30000000 | NV_PFIFO_CACHE1_DMA_FETCH_TRIG_128_BYTES | NV_PFIFO_CACHE1_DMA_FETCH_SIZE_128_BYTES | @@ -144,8 +142,8 @@ nv40_fifo_init(struct drm_device *dev, int engine) nv_wr32(dev, NV03_PFIFO_RAMHT, (0x03 << 24) /* search 128 */ | ((dev_priv->ramht->bits - 9) << 16) | - (dev_priv->ramht->gpuobj->pinst >> 8)); - nv_wr32(dev, NV03_PFIFO_RAMRO, priv->ramro->pinst >> 8); + (dev_priv->ramht->gpuobj->addr >> 8)); + nv_wr32(dev, NV03_PFIFO_RAMRO, priv->ramro->addr >> 8); switch (dev_priv->chipset) { case 0x47: @@ -163,7 +161,7 @@ nv40_fifo_init(struct drm_device *dev, int engine) default: nv_wr32(dev, 0x002230, 0x00000000); nv_wr32(dev, 0x002220, ((nvfb_vram_size(dev) - 512 * 1024 + - priv->ramfc->pinst) >> 16) | + priv->ramfc->addr) >> 16) | 0x00030000); break; } @@ -189,15 +187,14 @@ int nv40_fifo_create(struct drm_device *dev) { struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nv04_instmem_priv *imem = dev_priv->engine.instmem.priv; struct nv40_fifo_priv *priv; priv = kzalloc(sizeof(*priv), GFP_KERNEL); if (!priv) return -ENOMEM; - nouveau_gpuobj_ref(imem->ramro, &priv->ramro); - nouveau_gpuobj_ref(imem->ramfc, &priv->ramfc); + nouveau_gpuobj_ref(nvimem_ramro(dev), &priv->ramro); + nouveau_gpuobj_ref(nvimem_ramfc(dev), &priv->ramfc); priv->base.base.destroy = nv04_fifo_destroy; priv->base.base.init = nv40_fifo_init; diff --git a/drivers/gpu/drm/nouveau/core/engine/fifo/nv50.c b/drivers/gpu/drm/nouveau/core/engine/fifo/nv50.c index 2309871704e7..7b5b1592bf61 100644 --- a/drivers/gpu/drm/nouveau/core/engine/fifo/nv50.c +++ b/drivers/gpu/drm/nouveau/core/engine/fifo/nv50.c @@ -29,7 +29,6 @@ #include "nouveau_drv.h" #include #include -#include struct nv50_fifo_priv { struct nouveau_fifo_priv base; @@ -45,7 +44,6 @@ void nv50_fifo_playlist_update(struct drm_device *dev) { struct nv50_fifo_priv *priv = nv_engine(dev, NVOBJ_ENGINE_FIFO); - struct drm_nouveau_private *dev_priv = dev->dev_private; struct nouveau_gpuobj *cur; int i, p; @@ -57,9 +55,9 @@ nv50_fifo_playlist_update(struct drm_device *dev) nv_wo32(cur, p++ * 4, i); } - dev_priv->engine.instmem.flush(dev); + nvimem_flush(dev); - nv_wr32(dev, 0x0032f4, cur->vinst >> 12); + nv_wr32(dev, 0x0032f4, cur->addr >> 12); nv_wr32(dev, 0x0032ec, p); nv_wr32(dev, 0x002500, 0x00000101); } @@ -72,14 +70,14 @@ nv50_fifo_context_new(struct nouveau_channel *chan, int engine) struct drm_device *dev = chan->dev; struct drm_nouveau_private *dev_priv = dev->dev_private; u64 ib_offset = chan->pushbuf_base + chan->dma.ib_base * 4; - u64 instance = chan->ramin->vinst >> 12; + u64 instance = chan->ramin->addr >> 12; unsigned long flags; int ret = 0, i; fctx = chan->engctx[engine] = kzalloc(sizeof(*fctx), GFP_KERNEL); if (!fctx) return -ENOMEM; - atomic_inc(&chan->vm->engref[engine]); + nvvm_engref(chan->vm, engine, 1); chan->user = ioremap(pci_resource_start(dev->pdev, 0) + NV50_USER(chan->id), PAGE_SIZE); @@ -93,7 +91,7 @@ nv50_fifo_context_new(struct nouveau_channel *chan, int engine) nv_wo32(chan->ramin, 0x3c, 0x403f6078); nv_wo32(chan->ramin, 0x40, 0x00000000); nv_wo32(chan->ramin, 0x44, 0x01003fff); - nv_wo32(chan->ramin, 0x48, chan->pushbuf->cinst >> 4); + nv_wo32(chan->ramin, 0x48, chan->pushbuf->node->offset >> 4); nv_wo32(chan->ramin, 0x50, lower_32_bits(ib_offset)); nv_wo32(chan->ramin, 0x54, upper_32_bits(ib_offset) | drm_order(chan->dma.ib_max + 1) << 16); @@ -102,9 +100,9 @@ nv50_fifo_context_new(struct nouveau_channel *chan, int engine) nv_wo32(chan->ramin, 0x7c, 0x30000001); nv_wo32(chan->ramin, 0x80, ((chan->ramht->bits - 9) << 27) | (4 << 24) /* SEARCH_FULL */ | - (chan->ramht->gpuobj->cinst >> 4)); + (chan->ramht->gpuobj->node->offset >> 4)); - dev_priv->engine.instmem.flush(dev); + nvimem_flush(dev); spin_lock_irqsave(&dev_priv->context_switch_lock, flags); nv_wr32(dev, 0x002600 + (chan->id * 4), 0x80000000 | instance); @@ -141,7 +139,7 @@ nv50_fifo_kickoff(struct nouveau_channel *chan) me = nv_mask(dev, 0x00b860, 0x00000001, 0x00000001); /* do the kickoff... */ - nv_wr32(dev, 0x0032fc, chan->ramin->vinst >> 12); + nv_wr32(dev, 0x0032fc, chan->ramin->addr >> 12); if (!nv_wait_ne(dev, 0x0032fc, 0xffffffff, 0xffffffff)) { NV_INFO(dev, "PFIFO: channel %d unload timeout\n", chan->id); done = false; @@ -177,7 +175,7 @@ nv50_fifo_context_del(struct nouveau_channel *chan, int engine) chan->user = NULL; } - atomic_dec(&chan->vm->engref[engine]); + nvvm_engref(chan->vm, engine, -1); chan->engctx[engine] = NULL; kfree(fctx); } @@ -200,7 +198,7 @@ nv50_fifo_init(struct drm_device *dev, int engine) for (i = 0; i < 128; i++) { struct nouveau_channel *chan = dev_priv->channels.ptr[i]; if (chan && chan->engctx[engine]) - instance = 0x80000000 | chan->ramin->vinst >> 12; + instance = 0x80000000 | chan->ramin->addr >> 12; else instance = 0x00000000; nv_wr32(dev, 0x002600 + (i * 4), instance); diff --git a/drivers/gpu/drm/nouveau/core/engine/fifo/nv84.c b/drivers/gpu/drm/nouveau/core/engine/fifo/nv84.c index f505d1ed8866..63a4941e285c 100644 --- a/drivers/gpu/drm/nouveau/core/engine/fifo/nv84.c +++ b/drivers/gpu/drm/nouveau/core/engine/fifo/nv84.c @@ -29,7 +29,6 @@ #include "nouveau_drv.h" #include #include -#include struct nv84_fifo_priv { struct nouveau_fifo_priv base; @@ -58,7 +57,7 @@ nv84_fifo_context_new(struct nouveau_channel *chan, int engine) fctx = chan->engctx[engine] = kzalloc(sizeof(*fctx), GFP_KERNEL); if (!fctx) return -ENOMEM; - atomic_inc(&chan->vm->engref[engine]); + nvvm_engref(chan->vm, engine, 1); chan->user = ioremap(pci_resource_start(dev->pdev, 0) + NV50_USER(chan->id), PAGE_SIZE); @@ -72,7 +71,7 @@ nv84_fifo_context_new(struct nouveau_channel *chan, int engine) if (ret) goto error; - instance = fctx->ramfc->vinst >> 8; + instance = fctx->ramfc->addr >> 8; ret = nouveau_gpuobj_new(dev, chan, 4096, 1024, 0, &fctx->cache); if (ret) @@ -81,7 +80,7 @@ nv84_fifo_context_new(struct nouveau_channel *chan, int engine) nv_wo32(fctx->ramfc, 0x3c, 0x403f6078); nv_wo32(fctx->ramfc, 0x40, 0x00000000); nv_wo32(fctx->ramfc, 0x44, 0x01003fff); - nv_wo32(fctx->ramfc, 0x48, chan->pushbuf->cinst >> 4); + nv_wo32(fctx->ramfc, 0x48, chan->pushbuf->node->offset >> 4); nv_wo32(fctx->ramfc, 0x50, lower_32_bits(ib_offset)); nv_wo32(fctx->ramfc, 0x54, upper_32_bits(ib_offset) | drm_order(chan->dma.ib_max + 1) << 16); @@ -90,14 +89,14 @@ nv84_fifo_context_new(struct nouveau_channel *chan, int engine) nv_wo32(fctx->ramfc, 0x7c, 0x30000001); nv_wo32(fctx->ramfc, 0x80, ((chan->ramht->bits - 9) << 27) | (4 << 24) /* SEARCH_FULL */ | - (chan->ramht->gpuobj->cinst >> 4)); - nv_wo32(fctx->ramfc, 0x88, fctx->cache->vinst >> 10); - nv_wo32(fctx->ramfc, 0x98, chan->ramin->vinst >> 12); + (chan->ramht->gpuobj->node->offset >> 4)); + nv_wo32(fctx->ramfc, 0x88, fctx->cache->addr >> 10); + nv_wo32(fctx->ramfc, 0x98, chan->ramin->addr >> 12); nv_wo32(chan->ramin, 0x00, chan->id); - nv_wo32(chan->ramin, 0x04, fctx->ramfc->vinst >> 8); + nv_wo32(chan->ramin, 0x04, fctx->ramfc->addr >> 8); - dev_priv->engine.instmem.flush(dev); + nvimem_flush(dev); spin_lock_irqsave(&dev_priv->context_switch_lock, flags); nv_wr32(dev, 0x002600 + (chan->id * 4), 0x80000000 | instance); @@ -127,7 +126,7 @@ nv84_fifo_context_del(struct nouveau_channel *chan, int engine) save = nv_mask(dev, 0x002520, 0x0000003f, 0x15); /* tell any engines on this channel to unload their contexts */ - nv_wr32(dev, 0x0032fc, chan->ramin->vinst >> 12); + nv_wr32(dev, 0x0032fc, chan->ramin->addr >> 12); if (!nv_wait_ne(dev, 0x0032fc, 0xffffffff, 0xffffffff)) NV_INFO(dev, "PFIFO: channel %d unload timeout\n", chan->id); @@ -145,7 +144,7 @@ nv84_fifo_context_del(struct nouveau_channel *chan, int engine) nouveau_gpuobj_ref(NULL, &fctx->ramfc); nouveau_gpuobj_ref(NULL, &fctx->cache); - atomic_dec(&chan->vm->engref[engine]); + nvvm_engref(chan->vm, engine, -1); chan->engctx[engine] = NULL; kfree(fctx); } @@ -169,7 +168,7 @@ nv84_fifo_init(struct drm_device *dev, int engine) for (i = 0; i < 128; i++) { struct nouveau_channel *chan = dev_priv->channels.ptr[i]; if (chan && (fctx = chan->engctx[engine])) - instance = 0x80000000 | fctx->ramfc->vinst >> 8; + instance = 0x80000000 | fctx->ramfc->addr >> 8; else instance = 0x00000000; nv_wr32(dev, 0x002600 + (i * 4), instance); @@ -200,7 +199,7 @@ nv84_fifo_fini(struct drm_device *dev, int engine, bool suspend) for (i = 0; i < priv->base.channels; i++) { struct nouveau_channel *chan = dev_priv->channels.ptr[i]; if (chan) - nv_wr32(dev, 0x0032fc, chan->ramin->vinst >> 12); + nv_wr32(dev, 0x0032fc, chan->ramin->addr >> 12); if (!nv_wait_ne(dev, 0x0032fc, 0xffffffff, 0xffffffff)) { NV_INFO(dev, "PFIFO: channel %d unload timeout\n", i); return -EBUSY; diff --git a/drivers/gpu/drm/nouveau/core/engine/fifo/nvc0.c b/drivers/gpu/drm/nouveau/core/engine/fifo/nvc0.c index f60221d9235d..6535a999015d 100644 --- a/drivers/gpu/drm/nouveau/core/engine/fifo/nvc0.c +++ b/drivers/gpu/drm/nouveau/core/engine/fifo/nvc0.c @@ -48,8 +48,6 @@ struct nvc0_fifo_chan { static void nvc0_fifo_playlist_update(struct drm_device *dev) { - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_instmem_engine *pinstmem = &dev_priv->engine.instmem; struct nvc0_fifo_priv *priv = nv_engine(dev, NVOBJ_ENGINE_FIFO); struct nouveau_gpuobj *cur; int i, p; @@ -64,9 +62,9 @@ nvc0_fifo_playlist_update(struct drm_device *dev) nv_wo32(cur, p + 4, 0x00000004); p += 8; } - pinstmem->flush(dev); + nvimem_flush(dev); - nv_wr32(dev, 0x002270, cur->vinst >> 12); + nv_wr32(dev, 0x002270, cur->addr >> 12); nv_wr32(dev, 0x002274, 0x01f00000 | (p >> 3)); if (!nv_wait(dev, 0x00227c, 0x00100000, 0x00000000)) NV_ERROR(dev, "PFIFO - playlist update failed\n"); @@ -76,11 +74,9 @@ static int nvc0_fifo_context_new(struct nouveau_channel *chan, int engine) { struct drm_device *dev = chan->dev; - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_instmem_engine *pinstmem = &dev_priv->engine.instmem; struct nvc0_fifo_priv *priv = nv_engine(dev, engine); struct nvc0_fifo_chan *fctx; - u64 usermem = priv->user.mem->vinst + chan->id * 0x1000; + u64 usermem = priv->user.mem->addr + chan->id * 0x1000; u64 ib_virt = chan->pushbuf_base + chan->dma.ib_base * 4; int ret, i; @@ -115,10 +111,10 @@ nvc0_fifo_context_new(struct nouveau_channel *chan, int engine) nv_wo32(chan->ramin, 0xb8, 0xf8000000); nv_wo32(chan->ramin, 0xf8, 0x10003080); /* 0x002310 */ nv_wo32(chan->ramin, 0xfc, 0x10000010); /* 0x002350 */ - pinstmem->flush(dev); + nvimem_flush(dev); nv_wr32(dev, 0x003000 + (chan->id * 8), 0xc0000000 | - (chan->ramin->vinst >> 12)); + (chan->ramin->addr >> 12)); nv_wr32(dev, 0x003004 + (chan->id * 8), 0x001f0001); nvc0_fifo_playlist_update(dev); @@ -198,7 +194,7 @@ nvc0_fifo_init(struct drm_device *dev, int engine) continue; nv_wr32(dev, 0x003000 + (i * 8), 0xc0000000 | - (chan->ramin->vinst >> 12)); + (chan->ramin->addr >> 12)); nv_wr32(dev, 0x003004 + (i * 8), 0x001f0001); } nvc0_fifo_playlist_update(dev); diff --git a/drivers/gpu/drm/nouveau/core/engine/fifo/nve0.c b/drivers/gpu/drm/nouveau/core/engine/fifo/nve0.c index 1c06bde1bccf..461fbf62492d 100644 --- a/drivers/gpu/drm/nouveau/core/engine/fifo/nve0.c +++ b/drivers/gpu/drm/nouveau/core/engine/fifo/nve0.c @@ -55,8 +55,6 @@ struct nve0_fifo_chan { static void nve0_fifo_playlist_update(struct drm_device *dev, u32 engine) { - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_instmem_engine *pinstmem = &dev_priv->engine.instmem; struct nve0_fifo_priv *priv = nv_engine(dev, NVOBJ_ENGINE_FIFO); struct nve0_fifo_engine *peng = &priv->engine[engine]; struct nouveau_gpuobj *cur; @@ -84,9 +82,9 @@ nve0_fifo_playlist_update(struct drm_device *dev, u32 engine) nv_wo32(cur, p + 4, 0x00000000); p += 8; } - pinstmem->flush(dev); + nvimem_flush(dev); - nv_wr32(dev, 0x002270, cur->vinst >> 12); + nv_wr32(dev, 0x002270, cur->addr >> 12); nv_wr32(dev, 0x002274, (engine << 20) | (p >> 3)); if (!nv_wait(dev, 0x002284 + (engine * 4), 0x00100000, 0x00000000)) NV_ERROR(dev, "PFIFO: playlist %d update timeout\n", engine); @@ -96,11 +94,9 @@ static int nve0_fifo_context_new(struct nouveau_channel *chan, int engine) { struct drm_device *dev = chan->dev; - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_instmem_engine *pinstmem = &dev_priv->engine.instmem; struct nve0_fifo_priv *priv = nv_engine(dev, engine); struct nve0_fifo_chan *fctx; - u64 usermem = priv->user.mem->vinst + chan->id * 512; + u64 usermem = priv->user.mem->addr + chan->id * 512; u64 ib_virt = chan->pushbuf_base + chan->dma.ib_base * 4; int ret = 0, i; @@ -135,10 +131,10 @@ nve0_fifo_context_new(struct nouveau_channel *chan, int engine) nv_wo32(chan->ramin, 0xe8, chan->id); nv_wo32(chan->ramin, 0xf8, 0x10003080); /* 0x002310 */ nv_wo32(chan->ramin, 0xfc, 0x10000010); /* 0x002350 */ - pinstmem->flush(dev); + nvimem_flush(dev); nv_wr32(dev, 0x800000 + (chan->id * 8), 0x80000000 | - (chan->ramin->vinst >> 12)); + (chan->ramin->addr >> 12)); nv_mask(dev, 0x800004 + (chan->id * 8), 0x00000400, 0x00000400); nve0_fifo_playlist_update(dev, fctx->engine); nv_mask(dev, 0x800004 + (chan->id * 8), 0x00000400, 0x00000400); @@ -207,7 +203,7 @@ nve0_fifo_init(struct drm_device *dev, int engine) continue; nv_wr32(dev, 0x800000 + (i * 8), 0x80000000 | - (chan->ramin->vinst >> 12)); + (chan->ramin->addr >> 12)); nv_mask(dev, 0x800004 + (i * 8), 0x00000400, 0x00000400); nve0_fifo_playlist_update(dev, fctx->engine); nv_mask(dev, 0x800004 + (i * 8), 0x00000400, 0x00000400); diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/nv20.c b/drivers/gpu/drm/nouveau/core/engine/graph/nv20.c index dd31156e3029..0d874b8b18e5 100644 --- a/drivers/gpu/drm/nouveau/core/engine/graph/nv20.c +++ b/drivers/gpu/drm/nouveau/core/engine/graph/nv20.c @@ -52,7 +52,7 @@ nv20_graph_unload_context(struct drm_device *dev) return 0; grctx = chan->engctx[NVOBJ_ENGINE_GR]; - nv_wr32(dev, NV20_PGRAPH_CHANNEL_CTX_POINTER, grctx->pinst >> 4); + nv_wr32(dev, NV20_PGRAPH_CHANNEL_CTX_POINTER, grctx->addr >> 4); nv_wr32(dev, NV20_PGRAPH_CHANNEL_CTX_XFER, NV20_PGRAPH_CHANNEL_CTX_XFER_SAVE); @@ -437,7 +437,7 @@ nv20_graph_context_new(struct nouveau_channel *chan, int engine) /* CTX_USER */ nv_wo32(grctx, pgraph->grctx_user, (chan->id << 24) | 0x1); - nv_wo32(pgraph->ctxtab, chan->id * 4, grctx->pinst >> 4); + nv_wo32(pgraph->ctxtab, chan->id * 4, grctx->addr >> 4); chan->engctx[engine] = grctx; return 0; } @@ -505,7 +505,7 @@ nv20_graph_init(struct drm_device *dev, int engine) nv_wr32(dev, NV03_PMC_ENABLE, nv_rd32(dev, NV03_PMC_ENABLE) | NV_PMC_ENABLE_PGRAPH); - nv_wr32(dev, NV20_PGRAPH_CHANNEL_CTX_TABLE, pgraph->ctxtab->pinst >> 4); + nv_wr32(dev, NV20_PGRAPH_CHANNEL_CTX_TABLE, pgraph->ctxtab->addr >> 4); nv20_graph_rdi(dev); @@ -592,7 +592,7 @@ nv30_graph_init(struct drm_device *dev, int engine) nv_wr32(dev, NV03_PMC_ENABLE, nv_rd32(dev, NV03_PMC_ENABLE) | NV_PMC_ENABLE_PGRAPH); - nv_wr32(dev, NV20_PGRAPH_CHANNEL_CTX_TABLE, pgraph->ctxtab->pinst >> 4); + nv_wr32(dev, NV20_PGRAPH_CHANNEL_CTX_TABLE, pgraph->ctxtab->addr >> 4); nv_wr32(dev, NV03_PGRAPH_INTR , 0xFFFFFFFF); nv_wr32(dev, NV03_PGRAPH_INTR_EN, 0xFFFFFFFF); diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/nv40.c b/drivers/gpu/drm/nouveau/core/engine/graph/nv40.c index ab3af6d15381..466d21514b2c 100644 --- a/drivers/gpu/drm/nouveau/core/engine/graph/nv40.c +++ b/drivers/gpu/drm/nouveau/core/engine/graph/nv40.c @@ -52,16 +52,16 @@ nv40_graph_context_new(struct nouveau_channel *chan, int engine) /* Initialise default context values */ nv40_grctx_fill(dev, grctx); - nv_wo32(grctx, 0, grctx->vinst); + nv_wo32(grctx, 0, grctx->addr); /* init grctx pointer in ramfc, and on PFIFO if channel is * already active there */ spin_lock_irqsave(&dev_priv->context_switch_lock, flags); - nv_wo32(chan->ramfc, 0x38, grctx->vinst >> 4); + nv_wo32(chan->ramfc, 0x38, grctx->addr >> 4); nv_mask(dev, 0x002500, 0x00000001, 0x00000000); if ((nv_rd32(dev, 0x003204) & 0x0000001f) == chan->id) - nv_wr32(dev, 0x0032e0, grctx->vinst >> 4); + nv_wr32(dev, 0x0032e0, grctx->addr >> 4); nv_mask(dev, 0x002500, 0x00000001, 0x00000001); spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags); @@ -75,7 +75,7 @@ nv40_graph_context_del(struct nouveau_channel *chan, int engine) struct nouveau_gpuobj *grctx = chan->engctx[engine]; struct drm_device *dev = chan->dev; struct drm_nouveau_private *dev_priv = dev->dev_private; - u32 inst = 0x01000000 | (grctx->pinst >> 4); + u32 inst = 0x01000000 | (grctx->addr >> 4); unsigned long flags; spin_lock_irqsave(&dev_priv->context_switch_lock, flags); @@ -357,7 +357,7 @@ nv40_graph_isr_chid(struct drm_device *dev, u32 inst) continue; grctx = dev_priv->channels.ptr[i]->engctx[NVOBJ_ENGINE_GR]; - if (grctx && grctx->pinst == inst) + if (grctx && grctx->addr == inst) break; } spin_unlock_irqrestore(&dev_priv->channels.lock, flags); diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/nv50.c b/drivers/gpu/drm/nouveau/core/engine/graph/nv50.c index b2e9ad4dda06..28932c4662e9 100644 --- a/drivers/gpu/drm/nouveau/core/engine/graph/nv50.c +++ b/drivers/gpu/drm/nouveau/core/engine/graph/nv50.c @@ -30,7 +30,6 @@ #include #include #include "nouveau_dma.h" -#include #include "nv50_evo.h" struct nv50_graph_engine { @@ -155,18 +154,18 @@ nv50_graph_context_new(struct nouveau_channel *chan, int engine) hdr = (dev_priv->chipset == 0x50) ? 0x200 : 0x20; nv_wo32(ramin, hdr + 0x00, 0x00190002); - nv_wo32(ramin, hdr + 0x04, grctx->vinst + grctx->size - 1); - nv_wo32(ramin, hdr + 0x08, grctx->vinst); + nv_wo32(ramin, hdr + 0x04, grctx->addr + grctx->size - 1); + nv_wo32(ramin, hdr + 0x08, grctx->addr); nv_wo32(ramin, hdr + 0x0c, 0); nv_wo32(ramin, hdr + 0x10, 0); nv_wo32(ramin, hdr + 0x14, 0x00010000); nv50_grctx_fill(dev, grctx); - nv_wo32(grctx, 0x00000, chan->ramin->vinst >> 12); + nv_wo32(grctx, 0x00000, chan->ramin->addr >> 12); - dev_priv->engine.instmem.flush(dev); + nvimem_flush(dev); - atomic_inc(&chan->vm->engref[NVOBJ_ENGINE_GR]); + nvvm_engref(chan->vm, engine, 1); chan->engctx[NVOBJ_ENGINE_GR] = grctx; return 0; } @@ -181,9 +180,9 @@ nv50_graph_context_del(struct nouveau_channel *chan, int engine) for (i = hdr; i < hdr + 24; i += 4) nv_wo32(chan->ramin, i, 0); - dev_priv->engine.instmem.flush(dev); + nvimem_flush(dev); - atomic_dec(&chan->vm->engref[engine]); + nvvm_engref(chan->vm, engine, -1); nouveau_gpuobj_ref(NULL, &grctx); chan->engctx[engine] = NULL; } @@ -193,7 +192,6 @@ nv50_graph_object_new(struct nouveau_channel *chan, int engine, u32 handle, u16 class) { struct drm_device *dev = chan->dev; - struct drm_nouveau_private *dev_priv = dev->dev_private; struct nouveau_gpuobj *obj = NULL; int ret; @@ -207,7 +205,7 @@ nv50_graph_object_new(struct nouveau_channel *chan, int engine, nv_wo32(obj, 0x04, 0x00000000); nv_wo32(obj, 0x08, 0x00000000); nv_wo32(obj, 0x0c, 0x00000000); - dev_priv->engine.instmem.flush(dev); + nvimem_flush(dev); ret = nouveau_ramht_insert(chan, handle, obj); nouveau_gpuobj_ref(NULL, &obj); @@ -723,7 +721,7 @@ nv50_graph_isr_chid(struct drm_device *dev, u64 inst) if (!chan || !chan->ramin) continue; - if (inst == chan->ramin->vinst) + if (inst == chan->ramin->addr) break; } spin_unlock_irqrestore(&dev_priv->channels.lock, flags); diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/nvc0.c b/drivers/gpu/drm/nouveau/core/engine/graph/nvc0.c index 8d6eb89b8117..b741b038f0fd 100644 --- a/drivers/gpu/drm/nouveau/core/engine/graph/nvc0.c +++ b/drivers/gpu/drm/nouveau/core/engine/graph/nvc0.c @@ -65,7 +65,7 @@ nvc0_graph_load_context(struct nouveau_channel *chan) struct drm_device *dev = chan->dev; nv_wr32(dev, 0x409840, 0x00000030); - nv_wr32(dev, 0x409500, 0x80000000 | chan->ramin->vinst >> 12); + nv_wr32(dev, 0x409500, 0x80000000 | chan->ramin->addr >> 12); nv_wr32(dev, 0x409504, 0x00000003); if (!nv_wait(dev, 0x409800, 0x00000010, 0x00000010)) NV_ERROR(dev, "PGRAPH: load_ctx timeout\n"); @@ -90,7 +90,6 @@ nvc0_graph_unload_context_to(struct drm_device *dev, u64 chan) static int nvc0_graph_construct_context(struct nouveau_channel *chan) { - struct drm_nouveau_private *dev_priv = chan->dev->dev_private; struct nvc0_graph_priv *priv = nv_engine(chan->dev, NVOBJ_ENGINE_GR); struct nvc0_graph_chan *grch = chan->engctx[NVOBJ_ENGINE_GR]; struct drm_device *dev = chan->dev; @@ -103,7 +102,7 @@ nvc0_graph_construct_context(struct nouveau_channel *chan) if (!nouveau_ctxfw) { nv_wr32(dev, 0x409840, 0x80000000); - nv_wr32(dev, 0x409500, 0x80000000 | chan->ramin->vinst >> 12); + nv_wr32(dev, 0x409500, 0x80000000 | chan->ramin->addr >> 12); nv_wr32(dev, 0x409504, 0x00000001); if (!nv_wait(dev, 0x409800, 0x80000000, 0x80000000)) { NV_ERROR(dev, "PGRAPH: HUB_SET_CHAN timeout\n"); @@ -118,7 +117,7 @@ nvc0_graph_construct_context(struct nouveau_channel *chan) nv_wo32(grch->grctx, 0x20, 0); nv_wo32(grch->grctx, 0x28, 0); nv_wo32(grch->grctx, 0x2c, 0); - dev_priv->engine.instmem.flush(dev); + nvimem_flush(dev); } ret = nvc0_grctx_generate(chan); @@ -127,7 +126,7 @@ nvc0_graph_construct_context(struct nouveau_channel *chan) if (!nouveau_ctxfw) { nv_wr32(dev, 0x409840, 0x80000000); - nv_wr32(dev, 0x409500, 0x80000000 | chan->ramin->vinst >> 12); + nv_wr32(dev, 0x409500, 0x80000000 | chan->ramin->addr >> 12); nv_wr32(dev, 0x409504, 0x00000002); if (!nv_wait(dev, 0x409800, 0x80000000, 0x80000000)) { NV_ERROR(dev, "PGRAPH: HUB_CTX_SAVE timeout\n"); @@ -136,7 +135,7 @@ nvc0_graph_construct_context(struct nouveau_channel *chan) goto err; } } else { - ret = nvc0_graph_unload_context_to(dev, chan->ramin->vinst); + ret = nvc0_graph_unload_context_to(dev, chan->ramin->addr); if (ret) goto err; } @@ -165,8 +164,8 @@ nvc0_graph_create_context_mmio_list(struct nouveau_channel *chan) if (ret) return ret; - ret = nouveau_gpuobj_map_vm(grch->unk408004, NV_MEM_ACCESS_RW | - NV_MEM_ACCESS_SYS, chan->vm, + ret = nouveau_gpuobj_map_vm(grch->unk408004, chan->vm, + NV_MEM_ACCESS_RW | NV_MEM_ACCESS_SYS, &grch->unk408004_vma); if (ret) return ret; @@ -175,8 +174,8 @@ nvc0_graph_create_context_mmio_list(struct nouveau_channel *chan) if (ret) return ret; - ret = nouveau_gpuobj_map_vm(grch->unk40800c, NV_MEM_ACCESS_RW | - NV_MEM_ACCESS_SYS, chan->vm, + ret = nouveau_gpuobj_map_vm(grch->unk40800c, chan->vm, + NV_MEM_ACCESS_RW | NV_MEM_ACCESS_SYS, &grch->unk40800c_vma); if (ret) return ret; @@ -186,8 +185,8 @@ nvc0_graph_create_context_mmio_list(struct nouveau_channel *chan) if (ret) return ret; - ret = nouveau_gpuobj_map_vm(grch->unk418810, NV_MEM_ACCESS_RW, - chan->vm, &grch->unk418810_vma); + ret = nouveau_gpuobj_map_vm(grch->unk418810, chan->vm, + NV_MEM_ACCESS_RW, &grch->unk418810_vma); if (ret) return ret; @@ -195,9 +194,8 @@ nvc0_graph_create_context_mmio_list(struct nouveau_channel *chan) if (ret) return ret; - ret = nouveau_gpuobj_map_vm(grch->mmio, NV_MEM_ACCESS_RW | - NV_MEM_ACCESS_SYS, chan->vm, - &grch->mmio_vma); + ret = nouveau_gpuobj_map_vm(grch->mmio, chan->vm, NV_MEM_ACCESS_RW | + NV_MEM_ACCESS_SYS, &grch->mmio_vma); if (ret) return ret; @@ -268,8 +266,6 @@ static int nvc0_graph_context_new(struct nouveau_channel *chan, int engine) { struct drm_device *dev = chan->dev; - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_instmem_engine *pinstmem = &dev_priv->engine.instmem; struct nvc0_graph_priv *priv = nv_engine(dev, engine); struct nvc0_graph_chan *grch; struct nouveau_gpuobj *grctx; @@ -285,9 +281,8 @@ nvc0_graph_context_new(struct nouveau_channel *chan, int engine) if (ret) goto error; - ret = nouveau_gpuobj_map_vm(grch->grctx, NV_MEM_ACCESS_RW | - NV_MEM_ACCESS_SYS, chan->vm, - &grch->grctx_vma); + ret = nouveau_gpuobj_map_vm(grch->grctx, chan->vm, NV_MEM_ACCESS_RW | + NV_MEM_ACCESS_SYS, &grch->grctx_vma); if (ret) return ret; @@ -299,7 +294,7 @@ nvc0_graph_context_new(struct nouveau_channel *chan, int engine) nv_wo32(chan->ramin, 0x0210, lower_32_bits(grch->grctx_vma.offset) | 4); nv_wo32(chan->ramin, 0x0214, upper_32_bits(grch->grctx_vma.offset)); - pinstmem->flush(dev); + nvimem_flush(dev); if (!priv->grctx_vals) { ret = nvc0_graph_construct_context(chan); @@ -324,7 +319,7 @@ nvc0_graph_context_new(struct nouveau_channel *chan, int engine) nv_wo32(grctx, 0x28, 0); nv_wo32(grctx, 0x2c, 0); } - pinstmem->flush(dev); + nvimem_flush(dev); return 0; error: @@ -373,8 +368,8 @@ nvc0_graph_init_obj418880(struct drm_device *dev) nv_wr32(dev, GPC_BCAST(0x08a4), 0x00000000); for (i = 0; i < 4; i++) nv_wr32(dev, GPC_BCAST(0x0888) + (i * 4), 0x00000000); - nv_wr32(dev, GPC_BCAST(0x08b4), priv->unk4188b4->vinst >> 8); - nv_wr32(dev, GPC_BCAST(0x08b8), priv->unk4188b8->vinst >> 8); + nv_wr32(dev, GPC_BCAST(0x08b4), priv->unk4188b4->addr >> 8); + nv_wr32(dev, GPC_BCAST(0x08b8), priv->unk4188b8->addr >> 8); } static void @@ -662,7 +657,7 @@ nvc0_graph_isr_chid(struct drm_device *dev, u64 inst) if (!chan || !chan->ramin) continue; - if (inst == chan->ramin->vinst) + if (inst == chan->ramin->addr) break; } spin_unlock_irqrestore(&dev_priv->channels.lock, flags); diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/nve0.c b/drivers/gpu/drm/nouveau/core/engine/graph/nve0.c index 5f671a21b8bb..47bda63ddbcd 100644 --- a/drivers/gpu/drm/nouveau/core/engine/graph/nve0.c +++ b/drivers/gpu/drm/nouveau/core/engine/graph/nve0.c @@ -63,7 +63,7 @@ nve0_graph_load_context(struct nouveau_channel *chan) struct drm_device *dev = chan->dev; nv_wr32(dev, 0x409840, 0x00000030); - nv_wr32(dev, 0x409500, 0x80000000 | chan->ramin->vinst >> 12); + nv_wr32(dev, 0x409500, 0x80000000 | chan->ramin->addr >> 12); nv_wr32(dev, 0x409504, 0x00000003); if (!nv_wait(dev, 0x409800, 0x00000010, 0x00000010)) NV_ERROR(dev, "PGRAPH: load_ctx timeout\n"); @@ -88,7 +88,6 @@ nve0_graph_unload_context_to(struct drm_device *dev, u64 chan) static int nve0_graph_construct_context(struct nouveau_channel *chan) { - struct drm_nouveau_private *dev_priv = chan->dev->dev_private; struct nve0_graph_priv *priv = nv_engine(chan->dev, NVOBJ_ENGINE_GR); struct nve0_graph_chan *grch = chan->engctx[NVOBJ_ENGINE_GR]; struct drm_device *dev = chan->dev; @@ -105,13 +104,13 @@ nve0_graph_construct_context(struct nouveau_channel *chan) nv_wo32(grch->grctx, 0x20, 0); nv_wo32(grch->grctx, 0x28, 0); nv_wo32(grch->grctx, 0x2c, 0); - dev_priv->engine.instmem.flush(dev); + nvimem_flush(dev); ret = nve0_grctx_generate(chan); if (ret) goto err; - ret = nve0_graph_unload_context_to(dev, chan->ramin->vinst); + ret = nve0_graph_unload_context_to(dev, chan->ramin->addr); if (ret) goto err; @@ -141,8 +140,8 @@ nve0_graph_create_context_mmio_list(struct nouveau_channel *chan) if (ret) return ret; - ret = nouveau_gpuobj_map_vm(grch->unk408004, NV_MEM_ACCESS_RW | - NV_MEM_ACCESS_SYS, chan->vm, + ret = nouveau_gpuobj_map_vm(grch->unk408004, chan->vm, + NV_MEM_ACCESS_RW | NV_MEM_ACCESS_SYS, &grch->unk408004_vma); if (ret) return ret; @@ -151,8 +150,8 @@ nve0_graph_create_context_mmio_list(struct nouveau_channel *chan) if (ret) return ret; - ret = nouveau_gpuobj_map_vm(grch->unk40800c, NV_MEM_ACCESS_RW | - NV_MEM_ACCESS_SYS, chan->vm, + ret = nouveau_gpuobj_map_vm(grch->unk40800c, chan->vm, + NV_MEM_ACCESS_RW | NV_MEM_ACCESS_SYS, &grch->unk40800c_vma); if (ret) return ret; @@ -162,8 +161,8 @@ nve0_graph_create_context_mmio_list(struct nouveau_channel *chan) if (ret) return ret; - ret = nouveau_gpuobj_map_vm(grch->unk418810, NV_MEM_ACCESS_RW, - chan->vm, &grch->unk418810_vma); + ret = nouveau_gpuobj_map_vm(grch->unk418810, chan->vm, + NV_MEM_ACCESS_RW, &grch->unk418810_vma); if (ret) return ret; @@ -171,8 +170,8 @@ nve0_graph_create_context_mmio_list(struct nouveau_channel *chan) if (ret) return ret; - ret = nouveau_gpuobj_map_vm(grch->mmio, NV_MEM_ACCESS_RW | - NV_MEM_ACCESS_SYS, chan->vm, + ret = nouveau_gpuobj_map_vm(grch->mmio, chan->vm, + NV_MEM_ACCESS_RW | NV_MEM_ACCESS_SYS, &grch->mmio_vma); if (ret) return ret; @@ -221,8 +220,6 @@ static int nve0_graph_context_new(struct nouveau_channel *chan, int engine) { struct drm_device *dev = chan->dev; - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_instmem_engine *pinstmem = &dev_priv->engine.instmem; struct nve0_graph_priv *priv = nv_engine(dev, engine); struct nve0_graph_chan *grch; struct nouveau_gpuobj *grctx; @@ -238,9 +235,8 @@ nve0_graph_context_new(struct nouveau_channel *chan, int engine) if (ret) goto error; - ret = nouveau_gpuobj_map_vm(grch->grctx, NV_MEM_ACCESS_RW | - NV_MEM_ACCESS_SYS, chan->vm, - &grch->grctx_vma); + ret = nouveau_gpuobj_map_vm(grch->grctx, chan->vm, NV_MEM_ACCESS_RW | + NV_MEM_ACCESS_SYS, &grch->grctx_vma); if (ret) return ret; @@ -252,7 +248,7 @@ nve0_graph_context_new(struct nouveau_channel *chan, int engine) nv_wo32(chan->ramin, 0x0210, lower_32_bits(grch->grctx_vma.offset) | 4); nv_wo32(chan->ramin, 0x0214, upper_32_bits(grch->grctx_vma.offset)); - pinstmem->flush(dev); + nvimem_flush(dev); if (!priv->grctx_vals) { ret = nve0_graph_construct_context(chan); @@ -272,7 +268,7 @@ nve0_graph_context_new(struct nouveau_channel *chan, int engine) nv_wo32(grctx, 0x28, 0); nv_wo32(grctx, 0x2c, 0); - pinstmem->flush(dev); + nvimem_flush(dev); return 0; error: @@ -321,8 +317,8 @@ nve0_graph_init_obj418880(struct drm_device *dev) nv_wr32(dev, GPC_BCAST(0x08a4), 0x00000000); for (i = 0; i < 4; i++) nv_wr32(dev, GPC_BCAST(0x0888) + (i * 4), 0x00000000); - nv_wr32(dev, GPC_BCAST(0x08b4), priv->unk4188b4->vinst >> 8); - nv_wr32(dev, GPC_BCAST(0x08b8), priv->unk4188b8->vinst >> 8); + nv_wr32(dev, GPC_BCAST(0x08b4), priv->unk4188b4->addr >> 8); + nv_wr32(dev, GPC_BCAST(0x08b8), priv->unk4188b8->addr >> 8); } static void @@ -591,7 +587,7 @@ nve0_graph_isr_chid(struct drm_device *dev, u64 inst) if (!chan || !chan->ramin) continue; - if (inst == chan->ramin->vinst) + if (inst == chan->ramin->addr) break; } spin_unlock_irqrestore(&dev_priv->channels.lock, flags); diff --git a/drivers/gpu/drm/nouveau/core/engine/mpeg/nv31.c b/drivers/gpu/drm/nouveau/core/engine/mpeg/nv31.c index eb5455fed1bf..a0258c766850 100644 --- a/drivers/gpu/drm/nouveau/core/engine/mpeg/nv31.c +++ b/drivers/gpu/drm/nouveau/core/engine/mpeg/nv31.c @@ -74,8 +74,8 @@ nv40_mpeg_context_new(struct nouveau_channel *chan, int engine) spin_lock_irqsave(&dev_priv->context_switch_lock, flags); nv_mask(dev, 0x002500, 0x00000001, 0x00000000); if ((nv_rd32(dev, 0x003204) & 0x1f) == chan->id) - nv_wr32(dev, 0x00330c, ctx->pinst >> 4); - nv_wo32(chan->ramfc, 0x54, ctx->pinst >> 4); + nv_wr32(dev, 0x00330c, ctx->addr >> 4); + nv_wo32(chan->ramfc, 0x54, ctx->addr >> 4); nv_mask(dev, 0x002500, 0x00000001, 0x00000001); spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags); @@ -90,7 +90,7 @@ nv40_mpeg_context_del(struct nouveau_channel *chan, int engine) struct nouveau_gpuobj *ctx = chan->engctx[engine]; struct drm_device *dev = chan->dev; unsigned long flags; - u32 inst = 0x80000000 | (ctx->pinst >> 4); + u32 inst = 0x80000000 | (ctx->addr >> 4); spin_lock_irqsave(&dev_priv->context_switch_lock, flags); nv_mask(dev, 0x00b32c, 0x00000001, 0x00000000); @@ -224,7 +224,7 @@ nv31_mpeg_isr_chid(struct drm_device *dev, u32 inst) continue; ctx = dev_priv->channels.ptr[i]->engctx[NVOBJ_ENGINE_MPEG]; - if (ctx && ctx->pinst == inst) + if (ctx && ctx->addr == inst) break; } spin_unlock_irqrestore(&dev_priv->channels.lock, flags); diff --git a/drivers/gpu/drm/nouveau/core/engine/mpeg/nv50.c b/drivers/gpu/drm/nouveau/core/engine/mpeg/nv50.c index 47d37a2f478f..4e3292ed80c1 100644 --- a/drivers/gpu/drm/nouveau/core/engine/mpeg/nv50.c +++ b/drivers/gpu/drm/nouveau/core/engine/mpeg/nv50.c @@ -47,7 +47,6 @@ static int nv50_mpeg_context_new(struct nouveau_channel *chan, int engine) { struct drm_device *dev = chan->dev; - struct drm_nouveau_private *dev_priv = dev->dev_private; struct nouveau_gpuobj *ramin = chan->ramin; struct nouveau_gpuobj *ctx = NULL; int ret; @@ -60,15 +59,15 @@ nv50_mpeg_context_new(struct nouveau_channel *chan, int engine) return ret; nv_wo32(ramin, CTX_PTR(dev, 0x00), 0x80190002); - nv_wo32(ramin, CTX_PTR(dev, 0x04), ctx->vinst + ctx->size - 1); - nv_wo32(ramin, CTX_PTR(dev, 0x08), ctx->vinst); + nv_wo32(ramin, CTX_PTR(dev, 0x04), ctx->addr + ctx->size - 1); + nv_wo32(ramin, CTX_PTR(dev, 0x08), ctx->addr); nv_wo32(ramin, CTX_PTR(dev, 0x0c), 0); nv_wo32(ramin, CTX_PTR(dev, 0x10), 0); nv_wo32(ramin, CTX_PTR(dev, 0x14), 0x00010000); nv_wo32(ctx, 0x70, 0x00801ec1); nv_wo32(ctx, 0x7c, 0x0000037c); - dev_priv->engine.instmem.flush(dev); + nvimem_flush(dev); chan->engctx[engine] = ctx; return 0; @@ -93,7 +92,6 @@ nv50_mpeg_object_new(struct nouveau_channel *chan, int engine, u32 handle, u16 class) { struct drm_device *dev = chan->dev; - struct drm_nouveau_private *dev_priv = dev->dev_private; struct nouveau_gpuobj *obj = NULL; int ret; @@ -107,7 +105,7 @@ nv50_mpeg_object_new(struct nouveau_channel *chan, int engine, nv_wo32(obj, 0x04, 0x00000000); nv_wo32(obj, 0x08, 0x00000000); nv_wo32(obj, 0x0c, 0x00000000); - dev_priv->engine.instmem.flush(dev); + nvimem_flush(dev); ret = nouveau_ramht_insert(chan, handle, obj); nouveau_gpuobj_ref(NULL, &obj); diff --git a/drivers/gpu/drm/nouveau/core/engine/ppp/nv98.c b/drivers/gpu/drm/nouveau/core/engine/ppp/nv98.c index 20d33dcd7f40..384de6deeeea 100644 --- a/drivers/gpu/drm/nouveau/core/engine/ppp/nv98.c +++ b/drivers/gpu/drm/nouveau/core/engine/ppp/nv98.c @@ -25,7 +25,6 @@ #include "drmP.h" #include "nouveau_drv.h" #include "nouveau_util.h" -#include #include struct nv98_ppp_engine { diff --git a/drivers/gpu/drm/nouveau/core/engine/vp/nv84.c b/drivers/gpu/drm/nouveau/core/engine/vp/nv84.c index eb7e1960dd81..5e164a684aec 100644 --- a/drivers/gpu/drm/nouveau/core/engine/vp/nv84.c +++ b/drivers/gpu/drm/nouveau/core/engine/vp/nv84.c @@ -25,7 +25,6 @@ #include "drmP.h" #include "nouveau_drv.h" #include "nouveau_util.h" -#include #include /*XXX: This stub is currently used on NV98+ also, as soon as this becomes diff --git a/drivers/gpu/drm/nouveau/core/include/subdev/bar.h b/drivers/gpu/drm/nouveau/core/include/subdev/bar.h new file mode 100644 index 000000000000..4f4ff4502c3d --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/include/subdev/bar.h @@ -0,0 +1,55 @@ +#ifndef __NOUVEAU_BAR_H__ +#define __NOUVEAU_BAR_H__ + +#include +#include + +#include + +struct nouveau_vma; + +struct nouveau_bar { + struct nouveau_subdev base; + + int (*alloc)(struct nouveau_bar *, struct nouveau_object *, + struct nouveau_mem *, struct nouveau_object **); + void __iomem *iomem; + + int (*kmap)(struct nouveau_bar *, struct nouveau_mem *, + u32 flags, struct nouveau_vma *); + int (*umap)(struct nouveau_bar *, struct nouveau_mem *, + u32 flags, struct nouveau_vma *); + void (*unmap)(struct nouveau_bar *, struct nouveau_vma *); + void (*flush)(struct nouveau_bar *); +}; + +static inline struct nouveau_bar * +nouveau_bar(void *obj) +{ + return (void *)nv_device(obj)->subdev[NVDEV_SUBDEV_BAR]; +} + +#define nouveau_bar_create(p,e,o,d) \ + nouveau_bar_create_((p), (e), (o), sizeof(**d), (void **)d) +#define nouveau_bar_init(p) \ + nouveau_subdev_init(&(p)->base) +#define nouveau_bar_fini(p,s) \ + nouveau_subdev_fini(&(p)->base, (s)) + +int nouveau_bar_create_(struct nouveau_object *, struct nouveau_object *, + struct nouveau_oclass *, int, void **); +void nouveau_bar_destroy(struct nouveau_bar *); + +void _nouveau_bar_dtor(struct nouveau_object *); +#define _nouveau_bar_init _nouveau_subdev_init +#define _nouveau_bar_fini _nouveau_subdev_fini + +extern struct nouveau_oclass nv50_bar_oclass; +extern struct nouveau_oclass nvc0_bar_oclass; + +int nouveau_bar_alloc(struct nouveau_bar *, struct nouveau_object *, + struct nouveau_mem *, struct nouveau_object **); + +void nv84_bar_flush(struct nouveau_bar *); + +#endif diff --git a/drivers/gpu/drm/nouveau/core/include/subdev/fb.h b/drivers/gpu/drm/nouveau/core/include/subdev/fb.h index 91dbdc16ac94..f18c1a1e121c 100644 --- a/drivers/gpu/drm/nouveau/core/include/subdev/fb.h +++ b/drivers/gpu/drm/nouveau/core/include/subdev/fb.h @@ -6,6 +6,7 @@ #include #endif #include + #include /* memory type/access flags, do not match hardware values */ diff --git a/drivers/gpu/drm/nouveau/core/include/subdev/instmem.h b/drivers/gpu/drm/nouveau/core/include/subdev/instmem.h new file mode 100644 index 000000000000..2adfcafa4478 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/include/subdev/instmem.h @@ -0,0 +1,74 @@ +#ifndef __NOUVEAU_INSTMEM_H__ +#define __NOUVEAU_INSTMEM_H__ + +#include +#include +#include + +struct nouveau_instobj { + struct nouveau_object base; + struct list_head head; + struct nouveau_mm heap; + u32 *suspend; + u64 addr; + u32 size; +}; + +static inline struct nouveau_instobj * +nv_memobj(void *obj) +{ +#if CONFIG_NOUVEAU_DEBUG >= NV_DBG_PARANOIA + if (unlikely(!nv_iclass(obj, NV_MEMOBJ_CLASS))) + nv_assert("BAD CAST -> NvMemObj, %08x", nv_hclass(obj)); +#endif + return obj; +} + +#define nouveau_instobj_create(p,e,o,d) \ + nouveau_instobj_create_((p), (e), (o), sizeof(**d), (void **)d) +#define nouveau_instobj_init(p) \ + nouveau_object_init(&(p)->base) +#define nouveau_instobj_fini(p,s) \ + nouveau_object_fini(&(p)->base, (s)) + +int nouveau_instobj_create_(struct nouveau_object *, struct nouveau_object *, + struct nouveau_oclass *, int, void **); +void nouveau_instobj_destroy(struct nouveau_instobj *); + +void _nouveau_instobj_dtor(struct nouveau_object *); +#define _nouveau_instobj_init nouveau_object_init +#define _nouveau_instobj_fini nouveau_object_fini + +struct nouveau_instmem { + struct nouveau_subdev base; + struct list_head list; + + u32 reserved; + int (*alloc)(struct nouveau_instmem *, struct nouveau_object *, + u32 size, u32 align, struct nouveau_object **); +}; + +static inline struct nouveau_instmem * +nouveau_instmem(void *obj) +{ + return (void *)nv_device(obj)->subdev[NVDEV_SUBDEV_INSTMEM]; +} + +#define nouveau_instmem_create(p,e,o,d) \ + nouveau_instmem_create_((p), (e), (o), sizeof(**d), (void **)d) +#define nouveau_instmem_destroy(p) \ + nouveau_subdev_destroy(&(p)->base) +int nouveau_instmem_create_(struct nouveau_object *, struct nouveau_object *, + struct nouveau_oclass *, int, void **); +int nouveau_instmem_init(struct nouveau_instmem *); +int nouveau_instmem_fini(struct nouveau_instmem *, bool); + +#define _nouveau_instmem_dtor _nouveau_subdev_dtor +int _nouveau_instmem_init(struct nouveau_object *); +int _nouveau_instmem_fini(struct nouveau_object *, bool); + +extern struct nouveau_oclass nv04_instmem_oclass; +extern struct nouveau_oclass nv40_instmem_oclass; +extern struct nouveau_oclass nv50_instmem_oclass; + +#endif diff --git a/drivers/gpu/drm/nouveau/core/include/subdev/vm.h b/drivers/gpu/drm/nouveau/core/include/subdev/vm.h index 6d3764b416f4..81577bb783e8 100644 --- a/drivers/gpu/drm/nouveau/core/include/subdev/vm.h +++ b/drivers/gpu/drm/nouveau/core/include/subdev/vm.h @@ -25,10 +25,14 @@ #ifndef __NOUVEAU_VM_H__ #define __NOUVEAU_VM_H__ +#ifndef XXX_THIS_IS_A_HACK +#include +#include +#include +#endif #include -struct nouveau_mem; - +#ifndef XXX_THIS_IS_A_HACK struct nouveau_vm_pgt { struct nouveau_gpuobj *obj[2]; u32 refcount[2]; @@ -38,6 +42,10 @@ struct nouveau_vm_pgd { struct list_head head; struct nouveau_gpuobj *obj; }; +#endif + +struct nouveau_gpuobj; +struct nouveau_mem; struct nouveau_vma { struct list_head head; @@ -49,21 +57,29 @@ struct nouveau_vma { }; struct nouveau_vm { - struct drm_device *dev; + struct nouveau_vmmgr *vmm; struct nouveau_mm mm; int refcount; struct list_head pgd_list; - atomic_t engref[16]; + atomic_t engref[64]; //NVDEV_SUBDEV_NR]; struct nouveau_vm_pgt *pgt; u32 fpde; u32 lpde; +}; + +#ifndef XXX_THIS_IS_A_HACK +struct nouveau_vmmgr { + struct nouveau_subdev base; u32 pgt_bits; u8 spg_shift; u8 lpg_shift; + int (*create)(struct nouveau_vmmgr *, u64 offset, u64 length, + u64 mm_offset, struct nouveau_vm **); + void (*map_pgt)(struct nouveau_gpuobj *pgd, u32 pde, struct nouveau_gpuobj *pgt[2]); void (*map)(struct nouveau_vma *, struct nouveau_gpuobj *, @@ -71,16 +87,48 @@ struct nouveau_vm { u64 phys, u64 delta); void (*map_sg)(struct nouveau_vma *, struct nouveau_gpuobj *, struct nouveau_mem *, u32 pte, u32 cnt, dma_addr_t *); - - void (*map_sg_table)(struct nouveau_vma *, struct nouveau_gpuobj *, - struct nouveau_mem *, u32 pte, u32 cnt, dma_addr_t *); void (*unmap)(struct nouveau_gpuobj *pgt, u32 pte, u32 cnt); void (*flush)(struct nouveau_vm *); }; -/* nouveau_vm.c */ -int nouveau_vm_new(struct drm_device *, u64 offset, u64 length, u64 mm_offset, +static inline struct nouveau_vmmgr * +nouveau_vmmgr(void *obj) +{ + return (void *)nv_device(obj)->subdev[NVDEV_SUBDEV_VM]; +} + +#define nouveau_vmmgr_create(p,e,o,i,f,d) \ + nouveau_subdev_create((p), (e), (o), 0, (i), (f), (d)) +#define nouveau_vmmgr_destroy(p) \ + nouveau_subdev_destroy(&(p)->base) +#define nouveau_vmmgr_init(p) \ + nouveau_subdev_init(&(p)->base) +#define nouveau_vmmgr_fini(p,s) \ + nouveau_subdev_fini(&(p)->base, (s)) + +#define _nouveau_vmmgr_dtor _nouveau_subdev_dtor +#define _nouveau_vmmgr_init _nouveau_subdev_init +#define _nouveau_vmmgr_fini _nouveau_subdev_fini + +extern struct nouveau_oclass nv04_vmmgr_oclass; +extern struct nouveau_oclass nv41_vmmgr_oclass; +extern struct nouveau_oclass nv44_vmmgr_oclass; +extern struct nouveau_oclass nv50_vmmgr_oclass; +extern struct nouveau_oclass nvc0_vmmgr_oclass; + +int nv04_vm_create(struct nouveau_vmmgr *, u64, u64, u64, struct nouveau_vm **); +void nv04_vmmgr_dtor(struct nouveau_object *); + +void nv50_vm_flush_engine(struct nouveau_subdev *, int engine); +void nvc0_vm_flush_engine(struct nouveau_subdev *, u64 addr, int type); + +/* nouveau_vm.c */ +int nouveau_vm_create(struct nouveau_vmmgr *, u64 offset, u64 length, + u64 mm_offset, u32 block, struct nouveau_vm **); +int nouveau_vm_new(struct nouveau_device *, u64 offset, u64 length, + u64 mm_offset, struct nouveau_vm **); +#endif int nouveau_vm_ref(struct nouveau_vm *, struct nouveau_vm **, struct nouveau_gpuobj *pgd); int nouveau_vm_get(struct nouveau_vm *, u64 size, u32 page_shift, @@ -93,26 +141,6 @@ void nouveau_vm_unmap_at(struct nouveau_vma *, u64 offset, u64 length); void nouveau_vm_map_sg(struct nouveau_vma *, u64 offset, u64 length, struct nouveau_mem *); void nouveau_vm_map_sg_table(struct nouveau_vma *vma, u64 delta, u64 length, - struct nouveau_mem *mem); -/* nv50_vm.c */ -void nv50_vm_map_pgt(struct nouveau_gpuobj *pgd, u32 pde, - struct nouveau_gpuobj *pgt[2]); -void nv50_vm_map(struct nouveau_vma *, struct nouveau_gpuobj *, - struct nouveau_mem *, u32 pte, u32 cnt, u64 phys, u64 delta); -void nv50_vm_map_sg(struct nouveau_vma *, struct nouveau_gpuobj *, - struct nouveau_mem *, u32 pte, u32 cnt, dma_addr_t *); -void nv50_vm_unmap(struct nouveau_gpuobj *, u32 pte, u32 cnt); -void nv50_vm_flush(struct nouveau_vm *); -void nv50_vm_flush_engine(struct drm_device *, int engine); - -/* nvc0_vm.c */ -void nvc0_vm_map_pgt(struct nouveau_gpuobj *pgd, u32 pde, - struct nouveau_gpuobj *pgt[2]); -void nvc0_vm_map(struct nouveau_vma *, struct nouveau_gpuobj *, - struct nouveau_mem *, u32 pte, u32 cnt, u64 phys, u64 delta); -void nvc0_vm_map_sg(struct nouveau_vma *, struct nouveau_gpuobj *, - struct nouveau_mem *, u32 pte, u32 cnt, dma_addr_t *); -void nvc0_vm_unmap(struct nouveau_gpuobj *, u32 pte, u32 cnt); -void nvc0_vm_flush(struct nouveau_vm *); + struct nouveau_mem *mem); #endif diff --git a/drivers/gpu/drm/nouveau/core/subdev/bar/base.c b/drivers/gpu/drm/nouveau/core/subdev/bar/base.c new file mode 100644 index 000000000000..cd01c533007a --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/subdev/bar/base.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 +#include + +struct nouveau_barobj { + struct nouveau_object base; + struct nouveau_vma vma; + void __iomem *iomem; +}; + +static int +nouveau_barobj_ctor(struct nouveau_object *parent, + struct nouveau_object *engine, + struct nouveau_oclass *oclass, void *mem, u32 size, + struct nouveau_object **pobject) +{ + struct nouveau_bar *bar = (void *)engine; + struct nouveau_barobj *barobj; + int ret; + + ret = nouveau_object_create(parent, engine, oclass, 0, &barobj); + *pobject = nv_object(barobj); + if (ret) + return ret; + + ret = bar->kmap(bar, mem, NV_MEM_ACCESS_RW, &barobj->vma); + if (ret) + return ret; + + barobj->iomem = bar->iomem + (u32)barobj->vma.offset; + return 0; +} + +static void +nouveau_barobj_dtor(struct nouveau_object *object) +{ + struct nouveau_bar *bar = (void *)object->engine; + struct nouveau_barobj *barobj = (void *)object; + if (barobj->vma.node) + bar->unmap(bar, &barobj->vma); + nouveau_object_destroy(&barobj->base); +} + +static u32 +nouveau_barobj_rd32(struct nouveau_object *object, u32 addr) +{ + struct nouveau_barobj *barobj = (void *)object; + return ioread32_native(barobj->iomem + addr); +} + +static void +nouveau_barobj_wr32(struct nouveau_object *object, u32 addr, u32 data) +{ + struct nouveau_barobj *barobj = (void *)object; + iowrite32_native(data, barobj->iomem + addr); +} + +static struct nouveau_oclass +nouveau_barobj_oclass = { + .ofuncs = &(struct nouveau_ofuncs) { + .ctor = nouveau_barobj_ctor, + .dtor = nouveau_barobj_dtor, + .init = nouveau_object_init, + .fini = nouveau_object_fini, + .rd32 = nouveau_barobj_rd32, + .wr32 = nouveau_barobj_wr32, + }, +}; + +int +nouveau_bar_alloc(struct nouveau_bar *bar, struct nouveau_object *parent, + struct nouveau_mem *mem, struct nouveau_object **pobject) +{ + struct nouveau_object *engine = nv_object(bar); + return nouveau_object_ctor(parent, engine, &nouveau_barobj_oclass, + mem, 0, pobject); +} + +int +nouveau_bar_create_(struct nouveau_object *parent, + struct nouveau_object *engine, + struct nouveau_oclass *oclass, int length, void **pobject) +{ + struct nouveau_device *device = nv_device(parent); + struct nouveau_bar *bar; + int ret; + + ret = nouveau_subdev_create_(parent, engine, oclass, 0, "BARCTL", + "bar", length, pobject); + bar = *pobject; + if (ret) + return ret; + + bar->iomem = ioremap(pci_resource_start(device->pdev, 3), + pci_resource_len(device->pdev, 3)); + return 0; +} + +void +nouveau_bar_destroy(struct nouveau_bar *bar) +{ + if (bar->iomem) + iounmap(bar->iomem); + nouveau_subdev_destroy(&bar->base); +} + +void +_nouveau_bar_dtor(struct nouveau_object *object) +{ + struct nouveau_bar *bar = (void *)object; + nouveau_bar_destroy(bar); +} diff --git a/drivers/gpu/drm/nouveau/core/subdev/bar/nv50.c b/drivers/gpu/drm/nouveau/core/subdev/bar/nv50.c new file mode 100644 index 000000000000..c3acf5b70d9e --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/subdev/bar/nv50.c @@ -0,0 +1,263 @@ +/* + * 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 +#include + +struct nv50_bar_priv { + struct nouveau_bar base; + spinlock_t lock; + struct nouveau_gpuobj *mem; + struct nouveau_gpuobj *pad; + struct nouveau_gpuobj *pgd; + struct nouveau_vm *bar1_vm; + struct nouveau_gpuobj *bar1; + struct nouveau_vm *bar3_vm; + struct nouveau_gpuobj *bar3; +}; + +static int +nv50_bar_kmap(struct nouveau_bar *bar, struct nouveau_mem *mem, + u32 flags, struct nouveau_vma *vma) +{ + struct nv50_bar_priv *priv = (void *)bar; + int ret; + + ret = nouveau_vm_get(priv->bar3_vm, mem->size << 12, 12, flags, vma); + if (ret) + return ret; + + nouveau_vm_map(vma, mem); + nv50_vm_flush_engine(nv_subdev(bar), 6); + return 0; +} + +static int +nv50_bar_umap(struct nouveau_bar *bar, struct nouveau_mem *mem, + u32 flags, struct nouveau_vma *vma) +{ + struct nv50_bar_priv *priv = (void *)bar; + int ret; + + ret = nouveau_vm_get(priv->bar1_vm, mem->size << 12, 12, flags, vma); + if (ret) + return ret; + + nouveau_vm_map(vma, mem); + nv50_vm_flush_engine(nv_subdev(bar), 6); + return 0; +} + +static void +nv50_bar_unmap(struct nouveau_bar *bar, struct nouveau_vma *vma) +{ + nouveau_vm_unmap(vma); + nv50_vm_flush_engine(nv_subdev(bar), 6); + nouveau_vm_put(vma); +} + +static void +nv50_bar_flush(struct nouveau_bar *bar) +{ + struct nv50_bar_priv *priv = (void *)bar; + unsigned long flags; + spin_lock_irqsave(&priv->lock, flags); + nv_wr32(priv, 0x00330c, 0x00000001); + if (!nv_wait(priv, 0x00330c, 0x00000002, 0x00000000)) + nv_warn(priv, "flush timeout\n"); + spin_unlock_irqrestore(&priv->lock, flags); +} + +void +nv84_bar_flush(struct nouveau_bar *bar) +{ + struct nv50_bar_priv *priv = (void *)bar; + unsigned long flags; + spin_lock_irqsave(&priv->lock, flags); + nv_wr32(bar, 0x070000, 0x00000001); + if (!nv_wait(priv, 0x070000, 0x00000002, 0x00000000)) + nv_warn(priv, "flush timeout\n"); + spin_unlock_irqrestore(&priv->lock, flags); +} + +static int +nv50_bar_ctor(struct nouveau_object *parent, struct nouveau_object *engine, + struct nouveau_oclass *oclass, void *data, u32 size, + struct nouveau_object **pobject) +{ + struct nouveau_device *device = nv_device(parent); + struct nouveau_object *heap; + struct nouveau_vm *vm; + struct nv50_bar_priv *priv; + u64 start, limit; + int ret; + + ret = nouveau_bar_create(parent, engine, oclass, &priv); + *pobject = nv_object(priv); + if (ret) + return ret; + + ret = nouveau_gpuobj_new(parent, NULL, 0x20000, 0, NVOBJ_FLAG_HEAP, + &priv->mem); + heap = nv_object(priv->mem); + if (ret) + return ret; + + ret = nouveau_gpuobj_new(parent, heap, (device->chipset == 0x50) ? + 0x1400 : 0x0200, 0, 0, &priv->pad); + if (ret) + return ret; + + ret = nouveau_gpuobj_new(parent, heap, 0x4000, 0, 0, &priv->pgd); + if (ret) + return ret; + + /* BAR3 */ + start = 0x0100000000ULL; + limit = start + pci_resource_len(device->pdev, 3); + + ret = nouveau_vm_new(device, start, limit, start, &vm); + if (ret) + return ret; + + ret = nouveau_gpuobj_new(parent, heap, ((limit-- - start) >> 12) * 8, + 0x1000, NVOBJ_FLAG_ZERO_ALLOC, + &vm->pgt[0].obj[0]); + vm->pgt[0].refcount[0] = 1; + if (ret) + return ret; + + ret = nouveau_vm_ref(vm, &priv->bar3_vm, priv->pgd); + nouveau_vm_ref(NULL, &vm, NULL); + if (ret) + return ret; + + ret = nouveau_gpuobj_new(parent, heap, 24, 16, 0, &priv->bar3); + if (ret) + return ret; + + nv_wo32(priv->bar3, 0x00, 0x7fc00000); + nv_wo32(priv->bar3, 0x04, lower_32_bits(limit)); + nv_wo32(priv->bar3, 0x08, lower_32_bits(start)); + nv_wo32(priv->bar3, 0x0c, upper_32_bits(limit) << 24 | + upper_32_bits(start)); + nv_wo32(priv->bar3, 0x10, 0x00000000); + nv_wo32(priv->bar3, 0x14, 0x00000000); + + /* BAR1 */ + start = 0x0000000000ULL; + limit = start + pci_resource_len(device->pdev, 1); + + ret = nouveau_vm_new(device, start, limit--, start, &vm); + if (ret) + return ret; + + ret = nouveau_vm_ref(vm, &priv->bar1_vm, priv->pgd); + nouveau_vm_ref(NULL, &vm, NULL); + if (ret) + return ret; + + ret = nouveau_gpuobj_new(parent, heap, 24, 16, 0, &priv->bar1); + if (ret) + return ret; + + nv_wo32(priv->bar1, 0x00, 0x7fc00000); + nv_wo32(priv->bar1, 0x04, lower_32_bits(limit)); + nv_wo32(priv->bar1, 0x08, lower_32_bits(start)); + nv_wo32(priv->bar1, 0x0c, upper_32_bits(limit) << 24 | + upper_32_bits(start)); + nv_wo32(priv->bar1, 0x10, 0x00000000); + nv_wo32(priv->bar1, 0x14, 0x00000000); + + priv->base.alloc = nouveau_bar_alloc; + priv->base.kmap = nv50_bar_kmap; + priv->base.umap = nv50_bar_umap; + priv->base.unmap = nv50_bar_unmap; + if (device->chipset == 0x50) + priv->base.flush = nv50_bar_flush; + else + priv->base.flush = nv84_bar_flush; + spin_lock_init(&priv->lock); + return 0; +} + +static void +nv50_bar_dtor(struct nouveau_object *object) +{ + struct nv50_bar_priv *priv = (void *)object; + nouveau_gpuobj_ref(NULL, &priv->bar1); + nouveau_vm_ref(NULL, &priv->bar1_vm, priv->pgd); + nouveau_gpuobj_ref(NULL, &priv->bar3); + if (priv->bar3_vm) { + nouveau_gpuobj_ref(NULL, &priv->bar3_vm->pgt[0].obj[0]); + nouveau_vm_ref(NULL, &priv->bar3_vm, priv->pgd); + } + nouveau_gpuobj_ref(NULL, &priv->pgd); + nouveau_gpuobj_ref(NULL, &priv->pad); + nouveau_gpuobj_ref(NULL, &priv->mem); + nouveau_bar_destroy(&priv->base); +} + +static int +nv50_bar_init(struct nouveau_object *object) +{ + struct nv50_bar_priv *priv = (void *)object; + int ret; + + ret = nouveau_bar_init(&priv->base); + if (ret) + return ret; + + nv_mask(priv, 0x000200, 0x00000100, 0x00000000); + nv_mask(priv, 0x000200, 0x00000100, 0x00000100); + nv50_vm_flush_engine(nv_subdev(priv), 6); + + nv_wr32(priv, 0x001704, 0x00000000 | priv->mem->addr >> 12); + nv_wr32(priv, 0x001704, 0x40000000 | priv->mem->addr >> 12); + nv_wr32(priv, 0x001708, 0x80000000 | priv->bar1->node->offset >> 4); + nv_wr32(priv, 0x00170c, 0x80000000 | priv->bar3->node->offset >> 4); + return 0; +} + +static int +nv50_bar_fini(struct nouveau_object *object, bool suspend) +{ + struct nv50_bar_priv *priv = (void *)object; + return nouveau_bar_fini(&priv->base, suspend); +} + +struct nouveau_oclass +nv50_bar_oclass = { + .handle = NV_SUBDEV(BAR, 0x50), + .ofuncs = &(struct nouveau_ofuncs) { + .ctor = nv50_bar_ctor, + .dtor = nv50_bar_dtor, + .init = nv50_bar_init, + .fini = nv50_bar_fini, + }, +}; diff --git a/drivers/gpu/drm/nouveau/core/subdev/bar/nvc0.c b/drivers/gpu/drm/nouveau/core/subdev/bar/nvc0.c new file mode 100644 index 000000000000..77a6fb725d3f --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/subdev/bar/nvc0.c @@ -0,0 +1,215 @@ +/* + * 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 +#include + +struct nvc0_bar_priv { + struct nouveau_bar base; + spinlock_t lock; + struct { + struct nouveau_gpuobj *mem; + struct nouveau_gpuobj *pgd; + struct nouveau_vm *vm; + } bar[2]; +}; + +static int +nvc0_bar_kmap(struct nouveau_bar *bar, struct nouveau_mem *mem, + u32 flags, struct nouveau_vma *vma) +{ + struct nvc0_bar_priv *priv = (void *)bar; + int ret; + + ret = nouveau_vm_get(priv->bar[0].vm, mem->size << 12, 12, flags, vma); + if (ret) + return ret; + + nouveau_vm_map(vma, mem); + nvc0_vm_flush_engine(nv_subdev(bar), priv->bar[0].pgd->addr, 5); + return 0; +} + +static int +nvc0_bar_umap(struct nouveau_bar *bar, struct nouveau_mem *mem, + u32 flags, struct nouveau_vma *vma) +{ + struct nvc0_bar_priv *priv = (void *)bar; + int ret; + + ret = nouveau_vm_get(priv->bar[1].vm, mem->size << 12, + mem->page_shift, flags, vma); + if (ret) + return ret; + + nouveau_vm_map(vma, mem); + nvc0_vm_flush_engine(nv_subdev(bar), priv->bar[1].pgd->addr, 5); + return 0; +} + +static void +nvc0_bar_unmap(struct nouveau_bar *bar, struct nouveau_vma *vma) +{ + struct nvc0_bar_priv *priv = (void *)bar; + int i = !(vma->vm == priv->bar[0].vm); + + nouveau_vm_unmap(vma); + nvc0_vm_flush_engine(nv_subdev(bar), priv->bar[i].pgd->addr, 5); + nouveau_vm_put(vma); +} + +static int +nvc0_bar_ctor(struct nouveau_object *parent, struct nouveau_object *engine, + struct nouveau_oclass *oclass, void *data, u32 size, + struct nouveau_object **pobject) +{ + struct nouveau_device *device = nv_device(parent); + struct pci_dev *pdev = device->pdev; + struct nvc0_bar_priv *priv; + struct nouveau_gpuobj *mem; + struct nouveau_vm *vm; + int ret; + + ret = nouveau_bar_create(parent, engine, oclass, &priv); + *pobject = nv_object(priv); + if (ret) + return ret; + + /* BAR3 */ + ret = nouveau_gpuobj_new(parent, NULL, 0x1000, 0, 0, &priv->bar[0].mem); + mem = priv->bar[0].mem; + if (ret) + return ret; + + ret = nouveau_gpuobj_new(parent, NULL, 0x8000, 0, 0, &priv->bar[0].pgd); + if (ret) + return ret; + + ret = nouveau_vm_new(device, 0, pci_resource_len(pdev, 3), 0, &vm); + if (ret) + return ret; + + ret = nouveau_gpuobj_new(parent, NULL, + (pci_resource_len(pdev, 3) >> 12) * 8, + 0x1000, NVOBJ_FLAG_ZERO_ALLOC, + &vm->pgt[0].obj[0]); + vm->pgt[0].refcount[0] = 1; + if (ret) + return ret; + + ret = nouveau_vm_ref(vm, &priv->bar[0].vm, priv->bar[0].pgd); + nouveau_vm_ref(NULL, &vm, NULL); + if (ret) + return ret; + + nv_wo32(mem, 0x0200, lower_32_bits(priv->bar[0].pgd->addr)); + nv_wo32(mem, 0x0204, upper_32_bits(priv->bar[0].pgd->addr)); + nv_wo32(mem, 0x0208, lower_32_bits(pci_resource_len(pdev, 3) - 1)); + nv_wo32(mem, 0x020c, upper_32_bits(pci_resource_len(pdev, 3) - 1)); + + /* BAR1 */ + ret = nouveau_gpuobj_new(parent, NULL, 0x1000, 0, 0, &priv->bar[1].mem); + mem = priv->bar[1].mem; + if (ret) + return ret; + + ret = nouveau_gpuobj_new(parent, NULL, 0x8000, 0, 0, &priv->bar[1].pgd); + if (ret) + return ret; + + ret = nouveau_vm_new(device, 0, pci_resource_len(pdev, 1), 0, &vm); + if (ret) + return ret; + + ret = nouveau_vm_ref(vm, &priv->bar[1].vm, priv->bar[1].pgd); + nouveau_vm_ref(NULL, &vm, NULL); + if (ret) + return ret; + + nv_wo32(mem, 0x0200, lower_32_bits(priv->bar[1].pgd->addr)); + nv_wo32(mem, 0x0204, upper_32_bits(priv->bar[1].pgd->addr)); + nv_wo32(mem, 0x0208, lower_32_bits(pci_resource_len(pdev, 1) - 1)); + nv_wo32(mem, 0x020c, upper_32_bits(pci_resource_len(pdev, 1) - 1)); + + priv->base.alloc = nouveau_bar_alloc; + priv->base.kmap = nvc0_bar_kmap; + priv->base.umap = nvc0_bar_umap; + priv->base.unmap = nvc0_bar_unmap; + priv->base.flush = nv84_bar_flush; + spin_lock_init(&priv->lock); + return 0; +} + +static void +nvc0_bar_dtor(struct nouveau_object *object) +{ + struct nvc0_bar_priv *priv = (void *)object; + + nouveau_vm_ref(NULL, &priv->bar[1].vm, priv->bar[1].pgd); + nouveau_gpuobj_ref(NULL, &priv->bar[1].pgd); + nouveau_gpuobj_ref(NULL, &priv->bar[1].mem); + + if (priv->bar[0].vm) { + nouveau_gpuobj_ref(NULL, &priv->bar[0].vm->pgt[0].obj[0]); + nouveau_vm_ref(NULL, &priv->bar[0].vm, priv->bar[0].pgd); + } + nouveau_gpuobj_ref(NULL, &priv->bar[0].pgd); + nouveau_gpuobj_ref(NULL, &priv->bar[0].mem); + + nouveau_bar_destroy(&priv->base); +} + +static int +nvc0_bar_init(struct nouveau_object *object) +{ + struct nvc0_bar_priv *priv = (void *)object; + int ret; + + ret = nouveau_bar_init(&priv->base); + if (ret) + return ret; + + nv_mask(priv, 0x000200, 0x00000100, 0x00000000); + nv_mask(priv, 0x000200, 0x00000100, 0x00000100); + nv_mask(priv, 0x100c80, 0x00000001, 0x00000000); + + nv_wr32(priv, 0x001704, 0x80000000 | priv->bar[1].mem->addr >> 12); + nv_wr32(priv, 0x001714, 0xc0000000 | priv->bar[0].mem->addr >> 12); + return 0; +} + +struct nouveau_oclass +nvc0_bar_oclass = { + .handle = NV_SUBDEV(BAR, 0xc0), + .ofuncs = &(struct nouveau_ofuncs) { + .ctor = nvc0_bar_ctor, + .dtor = nvc0_bar_dtor, + .init = nvc0_bar_init, + .fini = _nouveau_bar_fini, + }, +}; diff --git a/drivers/gpu/drm/nouveau/core/subdev/device/nv04.c b/drivers/gpu/drm/nouveau/core/subdev/device/nv04.c index 66b7156281c9..5173c785b061 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/device/nv04.c +++ b/drivers/gpu/drm/nouveau/core/subdev/device/nv04.c @@ -30,6 +30,8 @@ #include #include #include +#include +#include int nv04_identify(struct nouveau_device *device) @@ -43,6 +45,8 @@ nv04_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; device->oclass[NVDEV_SUBDEV_FB ] = &nv04_fb_oclass; + device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv04_instmem_oclass; + device->oclass[NVDEV_SUBDEV_VM ] = &nv04_vmmgr_oclass; break; case 0x05: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -52,6 +56,8 @@ nv04_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; device->oclass[NVDEV_SUBDEV_FB ] = &nv04_fb_oclass; + device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv04_instmem_oclass; + device->oclass[NVDEV_SUBDEV_VM ] = &nv04_vmmgr_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 cf81479725ad..c4f2c2d3eaec 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/device/nv10.c +++ b/drivers/gpu/drm/nouveau/core/subdev/device/nv10.c @@ -31,6 +31,8 @@ #include #include #include +#include +#include int nv10_identify(struct nouveau_device *device) @@ -45,6 +47,8 @@ nv10_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; device->oclass[NVDEV_SUBDEV_FB ] = &nv10_fb_oclass; + device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv04_instmem_oclass; + device->oclass[NVDEV_SUBDEV_VM ] = &nv04_vmmgr_oclass; break; case 0x15: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -55,6 +59,8 @@ nv10_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; device->oclass[NVDEV_SUBDEV_FB ] = &nv10_fb_oclass; + device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv04_instmem_oclass; + device->oclass[NVDEV_SUBDEV_VM ] = &nv04_vmmgr_oclass; break; case 0x16: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -65,6 +71,8 @@ nv10_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; device->oclass[NVDEV_SUBDEV_FB ] = &nv10_fb_oclass; + device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv04_instmem_oclass; + device->oclass[NVDEV_SUBDEV_VM ] = &nv04_vmmgr_oclass; break; case 0x1a: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -75,6 +83,8 @@ nv10_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; device->oclass[NVDEV_SUBDEV_FB ] = &nv10_fb_oclass; + device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv04_instmem_oclass; + device->oclass[NVDEV_SUBDEV_VM ] = &nv04_vmmgr_oclass; break; case 0x11: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -85,6 +95,8 @@ nv10_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; device->oclass[NVDEV_SUBDEV_FB ] = &nv10_fb_oclass; + device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv04_instmem_oclass; + device->oclass[NVDEV_SUBDEV_VM ] = &nv04_vmmgr_oclass; break; case 0x17: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -95,6 +107,8 @@ nv10_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; device->oclass[NVDEV_SUBDEV_FB ] = &nv10_fb_oclass; + device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv04_instmem_oclass; + device->oclass[NVDEV_SUBDEV_VM ] = &nv04_vmmgr_oclass; break; case 0x1f: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -105,6 +119,8 @@ nv10_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; device->oclass[NVDEV_SUBDEV_FB ] = &nv10_fb_oclass; + device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv04_instmem_oclass; + device->oclass[NVDEV_SUBDEV_VM ] = &nv04_vmmgr_oclass; break; case 0x18: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -115,6 +131,8 @@ nv10_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; device->oclass[NVDEV_SUBDEV_FB ] = &nv10_fb_oclass; + device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv04_instmem_oclass; + device->oclass[NVDEV_SUBDEV_VM ] = &nv04_vmmgr_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 e97280cd43b0..719b72a43e47 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/device/nv20.c +++ b/drivers/gpu/drm/nouveau/core/subdev/device/nv20.c @@ -31,6 +31,8 @@ #include #include #include +#include +#include int nv20_identify(struct nouveau_device *device) @@ -45,6 +47,8 @@ nv20_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; device->oclass[NVDEV_SUBDEV_FB ] = &nv20_fb_oclass; + device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv04_instmem_oclass; + device->oclass[NVDEV_SUBDEV_VM ] = &nv04_vmmgr_oclass; break; case 0x25: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -55,6 +59,8 @@ nv20_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; device->oclass[NVDEV_SUBDEV_FB ] = &nv20_fb_oclass; + device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv04_instmem_oclass; + device->oclass[NVDEV_SUBDEV_VM ] = &nv04_vmmgr_oclass; break; case 0x28: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -65,6 +71,8 @@ nv20_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; device->oclass[NVDEV_SUBDEV_FB ] = &nv20_fb_oclass; + device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv04_instmem_oclass; + device->oclass[NVDEV_SUBDEV_VM ] = &nv04_vmmgr_oclass; break; case 0x2a: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -75,6 +83,8 @@ nv20_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; device->oclass[NVDEV_SUBDEV_FB ] = &nv20_fb_oclass; + device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv04_instmem_oclass; + device->oclass[NVDEV_SUBDEV_VM ] = &nv04_vmmgr_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 ddd3ab6cb733..0a1a72809d82 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/device/nv30.c +++ b/drivers/gpu/drm/nouveau/core/subdev/device/nv30.c @@ -31,6 +31,8 @@ #include #include #include +#include +#include int nv30_identify(struct nouveau_device *device) @@ -45,6 +47,8 @@ nv30_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; device->oclass[NVDEV_SUBDEV_FB ] = &nv30_fb_oclass; + device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv04_instmem_oclass; + device->oclass[NVDEV_SUBDEV_VM ] = &nv04_vmmgr_oclass; break; case 0x35: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -55,6 +59,8 @@ nv30_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; device->oclass[NVDEV_SUBDEV_FB ] = &nv30_fb_oclass; + device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv04_instmem_oclass; + device->oclass[NVDEV_SUBDEV_VM ] = &nv04_vmmgr_oclass; break; case 0x31: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -65,6 +71,8 @@ nv30_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; device->oclass[NVDEV_SUBDEV_FB ] = &nv30_fb_oclass; + device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv04_instmem_oclass; + device->oclass[NVDEV_SUBDEV_VM ] = &nv04_vmmgr_oclass; break; case 0x36: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -75,6 +83,8 @@ nv30_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; device->oclass[NVDEV_SUBDEV_FB ] = &nv30_fb_oclass; + device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv04_instmem_oclass; + device->oclass[NVDEV_SUBDEV_VM ] = &nv04_vmmgr_oclass; break; case 0x34: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -85,6 +95,8 @@ nv30_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; device->oclass[NVDEV_SUBDEV_FB ] = &nv30_fb_oclass; + device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv04_instmem_oclass; + device->oclass[NVDEV_SUBDEV_VM ] = &nv04_vmmgr_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 c7ea921e0309..5e1ef5e4cf7f 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/device/nv40.c +++ b/drivers/gpu/drm/nouveau/core/subdev/device/nv40.c @@ -31,6 +31,8 @@ #include #include #include +#include +#include int nv40_identify(struct nouveau_device *device) @@ -45,6 +47,8 @@ nv40_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; device->oclass[NVDEV_SUBDEV_FB ] = &nv40_fb_oclass; + device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv40_instmem_oclass; + device->oclass[NVDEV_SUBDEV_VM ] = &nv04_vmmgr_oclass; break; case 0x41: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -55,6 +59,8 @@ nv40_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; device->oclass[NVDEV_SUBDEV_FB ] = &nv40_fb_oclass; + device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv40_instmem_oclass; + device->oclass[NVDEV_SUBDEV_VM ] = &nv04_vmmgr_oclass; break; case 0x42: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -65,6 +71,8 @@ nv40_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; device->oclass[NVDEV_SUBDEV_FB ] = &nv40_fb_oclass; + device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv40_instmem_oclass; + device->oclass[NVDEV_SUBDEV_VM ] = &nv04_vmmgr_oclass; break; case 0x43: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -75,6 +83,8 @@ nv40_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; device->oclass[NVDEV_SUBDEV_FB ] = &nv40_fb_oclass; + device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv40_instmem_oclass; + device->oclass[NVDEV_SUBDEV_VM ] = &nv04_vmmgr_oclass; break; case 0x45: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -85,6 +95,8 @@ nv40_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; device->oclass[NVDEV_SUBDEV_FB ] = &nv40_fb_oclass; + device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv40_instmem_oclass; + device->oclass[NVDEV_SUBDEV_VM ] = &nv04_vmmgr_oclass; break; case 0x47: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -95,6 +107,8 @@ nv40_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; device->oclass[NVDEV_SUBDEV_FB ] = &nv40_fb_oclass; + device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv40_instmem_oclass; + device->oclass[NVDEV_SUBDEV_VM ] = &nv04_vmmgr_oclass; break; case 0x49: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -105,6 +119,8 @@ nv40_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; device->oclass[NVDEV_SUBDEV_FB ] = &nv40_fb_oclass; + device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv40_instmem_oclass; + device->oclass[NVDEV_SUBDEV_VM ] = &nv04_vmmgr_oclass; break; case 0x4b: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -115,6 +131,8 @@ nv40_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; device->oclass[NVDEV_SUBDEV_FB ] = &nv40_fb_oclass; + device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv40_instmem_oclass; + device->oclass[NVDEV_SUBDEV_VM ] = &nv04_vmmgr_oclass; break; case 0x44: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -125,6 +143,8 @@ nv40_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_MC ] = &nv44_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; device->oclass[NVDEV_SUBDEV_FB ] = &nv40_fb_oclass; + device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv40_instmem_oclass; + device->oclass[NVDEV_SUBDEV_VM ] = &nv04_vmmgr_oclass; break; case 0x46: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -135,6 +155,8 @@ nv40_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_MC ] = &nv44_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; device->oclass[NVDEV_SUBDEV_FB ] = &nv40_fb_oclass; + device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv40_instmem_oclass; + device->oclass[NVDEV_SUBDEV_VM ] = &nv04_vmmgr_oclass; break; case 0x4a: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -145,6 +167,8 @@ nv40_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_MC ] = &nv44_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; device->oclass[NVDEV_SUBDEV_FB ] = &nv40_fb_oclass; + device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv40_instmem_oclass; + device->oclass[NVDEV_SUBDEV_VM ] = &nv04_vmmgr_oclass; break; case 0x4c: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -155,6 +179,8 @@ nv40_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_MC ] = &nv44_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; device->oclass[NVDEV_SUBDEV_FB ] = &nv40_fb_oclass; + device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv40_instmem_oclass; + device->oclass[NVDEV_SUBDEV_VM ] = &nv04_vmmgr_oclass; break; case 0x4e: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -165,6 +191,8 @@ nv40_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_MC ] = &nv44_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; device->oclass[NVDEV_SUBDEV_FB ] = &nv40_fb_oclass; + device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv40_instmem_oclass; + device->oclass[NVDEV_SUBDEV_VM ] = &nv04_vmmgr_oclass; break; case 0x63: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -175,6 +203,8 @@ nv40_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_MC ] = &nv44_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; device->oclass[NVDEV_SUBDEV_FB ] = &nv40_fb_oclass; + device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv40_instmem_oclass; + device->oclass[NVDEV_SUBDEV_VM ] = &nv04_vmmgr_oclass; break; case 0x67: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -185,6 +215,8 @@ nv40_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_MC ] = &nv44_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; device->oclass[NVDEV_SUBDEV_FB ] = &nv40_fb_oclass; + device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv40_instmem_oclass; + device->oclass[NVDEV_SUBDEV_VM ] = &nv04_vmmgr_oclass; break; case 0x68: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -195,6 +227,8 @@ nv40_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_MC ] = &nv44_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; device->oclass[NVDEV_SUBDEV_FB ] = &nv40_fb_oclass; + device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv40_instmem_oclass; + device->oclass[NVDEV_SUBDEV_VM ] = &nv04_vmmgr_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 e60cdf26ebf9..5e86a2f6ad8a 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/device/nv50.c +++ b/drivers/gpu/drm/nouveau/core/subdev/device/nv50.c @@ -31,6 +31,9 @@ #include #include #include +#include +#include +#include int nv50_identify(struct nouveau_device *device) @@ -45,6 +48,9 @@ nv50_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_MC ] = &nv50_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; device->oclass[NVDEV_SUBDEV_FB ] = &nv50_fb_oclass; + device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass; + device->oclass[NVDEV_SUBDEV_VM ] = &nv50_vmmgr_oclass; + device->oclass[NVDEV_SUBDEV_BAR ] = &nv50_bar_oclass; break; case 0x84: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -55,6 +61,9 @@ nv50_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_MC ] = &nv50_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; device->oclass[NVDEV_SUBDEV_FB ] = &nv50_fb_oclass; + device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass; + device->oclass[NVDEV_SUBDEV_VM ] = &nv50_vmmgr_oclass; + device->oclass[NVDEV_SUBDEV_BAR ] = &nv50_bar_oclass; break; case 0x86: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -65,6 +74,9 @@ nv50_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_MC ] = &nv50_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; device->oclass[NVDEV_SUBDEV_FB ] = &nv50_fb_oclass; + device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass; + device->oclass[NVDEV_SUBDEV_VM ] = &nv50_vmmgr_oclass; + device->oclass[NVDEV_SUBDEV_BAR ] = &nv50_bar_oclass; break; case 0x92: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -75,6 +87,9 @@ nv50_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_MC ] = &nv50_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; device->oclass[NVDEV_SUBDEV_FB ] = &nv50_fb_oclass; + device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass; + device->oclass[NVDEV_SUBDEV_VM ] = &nv50_vmmgr_oclass; + device->oclass[NVDEV_SUBDEV_BAR ] = &nv50_bar_oclass; break; case 0x94: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -85,6 +100,9 @@ nv50_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_MC ] = &nv50_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; device->oclass[NVDEV_SUBDEV_FB ] = &nv50_fb_oclass; + device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass; + device->oclass[NVDEV_SUBDEV_VM ] = &nv50_vmmgr_oclass; + device->oclass[NVDEV_SUBDEV_BAR ] = &nv50_bar_oclass; break; case 0x96: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -95,6 +113,9 @@ nv50_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_MC ] = &nv50_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; device->oclass[NVDEV_SUBDEV_FB ] = &nv50_fb_oclass; + device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass; + device->oclass[NVDEV_SUBDEV_VM ] = &nv50_vmmgr_oclass; + device->oclass[NVDEV_SUBDEV_BAR ] = &nv50_bar_oclass; break; case 0x98: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -105,6 +126,9 @@ nv50_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_MC ] = &nv98_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; device->oclass[NVDEV_SUBDEV_FB ] = &nv50_fb_oclass; + device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass; + device->oclass[NVDEV_SUBDEV_VM ] = &nv50_vmmgr_oclass; + device->oclass[NVDEV_SUBDEV_BAR ] = &nv50_bar_oclass; break; case 0xa0: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -115,6 +139,9 @@ nv50_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_MC ] = &nv98_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; device->oclass[NVDEV_SUBDEV_FB ] = &nv50_fb_oclass; + device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass; + device->oclass[NVDEV_SUBDEV_VM ] = &nv50_vmmgr_oclass; + device->oclass[NVDEV_SUBDEV_BAR ] = &nv50_bar_oclass; break; case 0xaa: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -125,6 +152,9 @@ nv50_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_MC ] = &nv98_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; device->oclass[NVDEV_SUBDEV_FB ] = &nv50_fb_oclass; + device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass; + device->oclass[NVDEV_SUBDEV_VM ] = &nv50_vmmgr_oclass; + device->oclass[NVDEV_SUBDEV_BAR ] = &nv50_bar_oclass; break; case 0xac: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -135,6 +165,9 @@ nv50_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_MC ] = &nv98_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; device->oclass[NVDEV_SUBDEV_FB ] = &nv50_fb_oclass; + device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass; + device->oclass[NVDEV_SUBDEV_VM ] = &nv50_vmmgr_oclass; + device->oclass[NVDEV_SUBDEV_BAR ] = &nv50_bar_oclass; break; case 0xa3: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -145,6 +178,9 @@ nv50_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_MC ] = &nv98_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; device->oclass[NVDEV_SUBDEV_FB ] = &nv50_fb_oclass; + device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass; + device->oclass[NVDEV_SUBDEV_VM ] = &nv50_vmmgr_oclass; + device->oclass[NVDEV_SUBDEV_BAR ] = &nv50_bar_oclass; break; case 0xa5: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -155,6 +191,9 @@ nv50_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_MC ] = &nv98_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; device->oclass[NVDEV_SUBDEV_FB ] = &nv50_fb_oclass; + device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass; + device->oclass[NVDEV_SUBDEV_VM ] = &nv50_vmmgr_oclass; + device->oclass[NVDEV_SUBDEV_BAR ] = &nv50_bar_oclass; break; case 0xa8: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -165,6 +204,9 @@ nv50_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_MC ] = &nv98_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; device->oclass[NVDEV_SUBDEV_FB ] = &nv50_fb_oclass; + device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass; + device->oclass[NVDEV_SUBDEV_VM ] = &nv50_vmmgr_oclass; + device->oclass[NVDEV_SUBDEV_BAR ] = &nv50_bar_oclass; break; case 0xaf: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -175,6 +217,9 @@ nv50_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_MC ] = &nv98_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; device->oclass[NVDEV_SUBDEV_FB ] = &nv50_fb_oclass; + device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass; + device->oclass[NVDEV_SUBDEV_VM ] = &nv50_vmmgr_oclass; + device->oclass[NVDEV_SUBDEV_BAR ] = &nv50_bar_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 8de67307eea7..87f4e16379c6 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/device/nvc0.c +++ b/drivers/gpu/drm/nouveau/core/subdev/device/nvc0.c @@ -32,6 +32,9 @@ #include #include #include +#include +#include +#include int nvc0_identify(struct nouveau_device *device) @@ -47,6 +50,9 @@ nvc0_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; device->oclass[NVDEV_SUBDEV_FB ] = &nvc0_fb_oclass; device->oclass[NVDEV_SUBDEV_LTCG ] = &nvc0_ltcg_oclass; + device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass; + device->oclass[NVDEV_SUBDEV_VM ] = &nvc0_vmmgr_oclass; + device->oclass[NVDEV_SUBDEV_BAR ] = &nvc0_bar_oclass; break; case 0xc4: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -58,6 +64,9 @@ nvc0_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; device->oclass[NVDEV_SUBDEV_FB ] = &nvc0_fb_oclass; device->oclass[NVDEV_SUBDEV_LTCG ] = &nvc0_ltcg_oclass; + device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass; + device->oclass[NVDEV_SUBDEV_VM ] = &nvc0_vmmgr_oclass; + device->oclass[NVDEV_SUBDEV_BAR ] = &nvc0_bar_oclass; break; case 0xc3: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -69,6 +78,9 @@ nvc0_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; device->oclass[NVDEV_SUBDEV_FB ] = &nvc0_fb_oclass; device->oclass[NVDEV_SUBDEV_LTCG ] = &nvc0_ltcg_oclass; + device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass; + device->oclass[NVDEV_SUBDEV_VM ] = &nvc0_vmmgr_oclass; + device->oclass[NVDEV_SUBDEV_BAR ] = &nvc0_bar_oclass; break; case 0xce: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -80,6 +92,9 @@ nvc0_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; device->oclass[NVDEV_SUBDEV_FB ] = &nvc0_fb_oclass; device->oclass[NVDEV_SUBDEV_LTCG ] = &nvc0_ltcg_oclass; + device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass; + device->oclass[NVDEV_SUBDEV_VM ] = &nvc0_vmmgr_oclass; + device->oclass[NVDEV_SUBDEV_BAR ] = &nvc0_bar_oclass; break; case 0xcf: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -91,6 +106,9 @@ nvc0_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; device->oclass[NVDEV_SUBDEV_FB ] = &nvc0_fb_oclass; device->oclass[NVDEV_SUBDEV_LTCG ] = &nvc0_ltcg_oclass; + device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass; + device->oclass[NVDEV_SUBDEV_VM ] = &nvc0_vmmgr_oclass; + device->oclass[NVDEV_SUBDEV_BAR ] = &nvc0_bar_oclass; break; case 0xc1: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -102,6 +120,9 @@ nvc0_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; device->oclass[NVDEV_SUBDEV_FB ] = &nvc0_fb_oclass; device->oclass[NVDEV_SUBDEV_LTCG ] = &nvc0_ltcg_oclass; + device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass; + device->oclass[NVDEV_SUBDEV_VM ] = &nvc0_vmmgr_oclass; + device->oclass[NVDEV_SUBDEV_BAR ] = &nvc0_bar_oclass; break; case 0xc8: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -113,6 +134,9 @@ nvc0_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; device->oclass[NVDEV_SUBDEV_FB ] = &nvc0_fb_oclass; device->oclass[NVDEV_SUBDEV_LTCG ] = &nvc0_ltcg_oclass; + device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass; + device->oclass[NVDEV_SUBDEV_VM ] = &nvc0_vmmgr_oclass; + device->oclass[NVDEV_SUBDEV_BAR ] = &nvc0_bar_oclass; break; case 0xd9: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -124,6 +148,9 @@ nvc0_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; device->oclass[NVDEV_SUBDEV_FB ] = &nvc0_fb_oclass; device->oclass[NVDEV_SUBDEV_LTCG ] = &nvc0_ltcg_oclass; + device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass; + device->oclass[NVDEV_SUBDEV_VM ] = &nvc0_vmmgr_oclass; + device->oclass[NVDEV_SUBDEV_BAR ] = &nvc0_bar_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 919a10280d7e..ab8346b8bde0 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/device/nve0.c +++ b/drivers/gpu/drm/nouveau/core/subdev/device/nve0.c @@ -32,6 +32,9 @@ #include #include #include +#include +#include +#include int nve0_identify(struct nouveau_device *device) @@ -47,6 +50,9 @@ nve0_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; device->oclass[NVDEV_SUBDEV_FB ] = &nvc0_fb_oclass; device->oclass[NVDEV_SUBDEV_LTCG ] = &nvc0_ltcg_oclass; + device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass; + device->oclass[NVDEV_SUBDEV_VM ] = &nvc0_vmmgr_oclass; + device->oclass[NVDEV_SUBDEV_BAR ] = &nvc0_bar_oclass; break; case 0xe7: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -58,6 +64,9 @@ nve0_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; device->oclass[NVDEV_SUBDEV_FB ] = &nvc0_fb_oclass; device->oclass[NVDEV_SUBDEV_LTCG ] = &nvc0_ltcg_oclass; + device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass; + device->oclass[NVDEV_SUBDEV_VM ] = &nvc0_vmmgr_oclass; + device->oclass[NVDEV_SUBDEV_BAR ] = &nvc0_bar_oclass; break; default: nv_fatal(device, "unknown Kepler chipset\n"); diff --git a/drivers/gpu/drm/nouveau/core/subdev/fb/nv40.c b/drivers/gpu/drm/nouveau/core/subdev/fb/nv40.c index 84aa71c47128..347a496fcad8 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/fb/nv40.c +++ b/drivers/gpu/drm/nouveau/core/subdev/fb/nv40.c @@ -50,54 +50,14 @@ nv40_fb_tile_prog(struct nouveau_fb *pfb, int i, struct nouveau_fb_tile *tile) static void nv40_fb_init_gart(struct nv40_fb_priv *priv) { -#if 0 - struct nouveau_gpuobj *gart = ndev->gart_info.sg_ctxdma; - - if (ndev->gart_info.type != NOUVEAU_GART_HW) { -#endif - nv_wr32(priv, 0x100800, 0x00000001); -#if 0 - return; - } - - nv_wr32(ndev, 0x100800, gart->pinst | 0x00000002); - nv_mask(ndev, 0x10008c, 0x00000100, 0x00000100); - nv_wr32(ndev, 0x100820, 0x00000000); -#endif + nv_wr32(priv, 0x100800, 0x00000001); } static void nv44_fb_init_gart(struct nv40_fb_priv *priv) { -#if 0 - struct nouveau_gpuobj *gart = ndev->gart_info.sg_ctxdma; - u32 vinst; - - if (ndev->gart_info.type != NOUVEAU_GART_HW) { -#endif - nv_wr32(priv, 0x100850, 0x80000000); - nv_wr32(priv, 0x100800, 0x00000001); -#if 0 - return; - } - - /* calculate vram address of this PRAMIN block, object - * must be allocated on 512KiB alignment, and not exceed - * a total size of 512KiB for this to work correctly - */ - vinst = nv_rd32(ndev, 0x10020c); - vinst -= ((gart->pinst >> 19) + 1) << 19; - - nv_wr32(ndev, 0x100850, 0x80000000); - nv_wr32(ndev, 0x100818, ndev->gart_info.dummy.addr); - - nv_wr32(ndev, 0x100804, ndev->gart_info.aper_size); - nv_wr32(ndev, 0x100850, 0x00008000); - nv_mask(ndev, 0x10008c, 0x00000200, 0x00000200); - nv_wr32(ndev, 0x100820, 0x00000000); - nv_wr32(ndev, 0x10082c, 0x00000001); - nv_wr32(ndev, 0x100800, vinst | 0x00000010); -#endif + nv_wr32(priv, 0x100850, 0x80000000); + nv_wr32(priv, 0x100800, 0x00000001); } static int diff --git a/drivers/gpu/drm/nouveau/core/subdev/instmem/base.c b/drivers/gpu/drm/nouveau/core/subdev/instmem/base.c new file mode 100644 index 000000000000..1188227ca6aa --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/subdev/instmem/base.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 + +int +nouveau_instobj_create_(struct nouveau_object *parent, + struct nouveau_object *engine, + struct nouveau_oclass *oclass, + int length, void **pobject) +{ + struct nouveau_instmem *imem = (void *)engine; + struct nouveau_instobj *iobj; + int ret; + + ret = nouveau_object_create_(parent, engine, oclass, NV_MEMOBJ_CLASS, + length, pobject); + iobj = *pobject; + if (ret) + return ret; + + list_add(&iobj->head, &imem->list); + return 0; +} + +void +nouveau_instobj_destroy(struct nouveau_instobj *iobj) +{ + if (iobj->head.prev) + list_del(&iobj->head); + return nouveau_object_destroy(&iobj->base); +} + +void +_nouveau_instobj_dtor(struct nouveau_object *object) +{ + struct nouveau_instobj *iobj = (void *)object; + return nouveau_instobj_destroy(iobj); +} + +int +nouveau_instmem_create_(struct nouveau_object *parent, + struct nouveau_object *engine, + struct nouveau_oclass *oclass, + int length, void **pobject) +{ + struct nouveau_instmem *imem; + int ret; + + ret = nouveau_subdev_create_(parent, engine, oclass, 0, + "INSTMEM", "instmem", length, pobject); + imem = *pobject; + if (ret) + return ret; + + INIT_LIST_HEAD(&imem->list); + return 0; +} + +int +nouveau_instmem_init(struct nouveau_instmem *imem) +{ + struct nouveau_instobj *iobj; + int ret, i; + + ret = nouveau_subdev_init(&imem->base); + if (ret) + return ret; + + list_for_each_entry(iobj, &imem->list, head) { + if (iobj->suspend) { + for (i = 0; i < iobj->size; i += 4) + nv_wo32(iobj, i, iobj->suspend[i / 4]); + vfree(iobj->suspend); + iobj->suspend = NULL; + } + } + + return 0; +} + +int +nouveau_instmem_fini(struct nouveau_instmem *imem, bool suspend) +{ + struct nouveau_instobj *iobj; + int i; + + if (suspend) { + list_for_each_entry(iobj, &imem->list, head) { + iobj->suspend = vmalloc(iobj->size); + if (iobj->suspend) { + for (i = 0; i < iobj->size; i += 4) + iobj->suspend[i / 4] = nv_ro32(iobj, i); + } else + return -ENOMEM; + } + } + + return nouveau_subdev_fini(&imem->base, suspend); +} + +int +_nouveau_instmem_init(struct nouveau_object *object) +{ + struct nouveau_instmem *imem = (void *)object; + return nouveau_instmem_init(imem); +} + +int +_nouveau_instmem_fini(struct nouveau_object *object, bool suspend) +{ + struct nouveau_instmem *imem = (void *)object; + return nouveau_instmem_fini(imem, suspend); +} diff --git a/drivers/gpu/drm/nouveau/core/subdev/instmem/nv04.c b/drivers/gpu/drm/nouveau/core/subdev/instmem/nv04.c index 46b6963b0937..f44f0f096689 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/instmem/nv04.c +++ b/drivers/gpu/drm/nouveau/core/subdev/instmem/nv04.c @@ -1,141 +1,199 @@ -#include "drmP.h" -#include "drm.h" - -#include "nouveau_drv.h" -#include -#include +/* + * Copyright 2012 Red Hat Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: Ben Skeggs + */ + +#include #include "nv04.h" +static int +nv04_instobj_ctor(struct nouveau_object *parent, struct nouveau_object *engine, + struct nouveau_oclass *oclass, void *data, u32 size, + struct nouveau_object **pobject) +{ + struct nv04_instmem_priv *priv = (void *)engine; + struct nv04_instobj_priv *node; + int ret, align; + + align = (unsigned long)data; + if (!align) + align = 1; + + ret = nouveau_instobj_create(parent, engine, oclass, &node); + *pobject = nv_object(node); + if (ret) + return ret; + + ret = nouveau_mm_head(&priv->heap, 1, size, size, align, &node->mem); + if (ret) + return ret; + + node->base.addr = node->mem->offset; + node->base.size = node->mem->length; + return 0; +} + +static void +nv04_instobj_dtor(struct nouveau_object *object) +{ + struct nv04_instmem_priv *priv = (void *)object->engine; + struct nv04_instobj_priv *node = (void *)object; + nouveau_mm_free(&priv->heap, &node->mem); + nouveau_instobj_destroy(&node->base); +} + +static u32 +nv04_instobj_rd32(struct nouveau_object *object, u32 addr) +{ + struct nv04_instobj_priv *node = (void *)object; + return nv_ro32(object->engine, node->mem->offset + addr); +} + +static void +nv04_instobj_wr32(struct nouveau_object *object, u32 addr, u32 data) +{ + struct nv04_instobj_priv *node = (void *)object; + nv_wo32(object->engine, node->mem->offset + addr, data); +} + +static struct nouveau_oclass +nv04_instobj_oclass = { + .ofuncs = &(struct nouveau_ofuncs) { + .ctor = nv04_instobj_ctor, + .dtor = nv04_instobj_dtor, + .init = _nouveau_instobj_init, + .fini = _nouveau_instobj_fini, + .rd32 = nv04_instobj_rd32, + .wr32 = nv04_instobj_wr32, + }, +}; + int -nv04_instmem_init(struct drm_device *dev) +nv04_instmem_alloc(struct nouveau_instmem *imem, struct nouveau_object *parent, + u32 size, u32 align, struct nouveau_object **pobject) { - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nv04_instmem_priv *priv; + struct nouveau_object *engine = nv_object(imem); + struct nv04_instmem_priv *priv = (void *)(imem); int ret; - priv = kzalloc(sizeof(*priv), GFP_KERNEL); - if (!priv) - return -ENOMEM; - dev_priv->engine.instmem.priv = priv; + ret = nouveau_object_ctor(parent, engine, &nv04_instobj_oclass, + (void *)(unsigned long)align, size, pobject); + if (ret) + return ret; + + /* INSTMEM itself creates objects to reserve (and preserve across + * suspend/resume) various fixed data locations, each one of these + * takes a reference on INSTMEM itself, causing it to never be + * freed. We drop all the self-references here to avoid this. + */ + if (unlikely(!priv->created)) + atomic_dec(&engine->refcount); + + return 0; +} - /* PRAMIN aperture maps over the end of vram, reserve the space */ - dev_priv->ramin_available = true; - dev_priv->ramin_rsvd_vram = 512 * 1024; +static int +nv04_instmem_ctor(struct nouveau_object *parent, struct nouveau_object *engine, + struct nouveau_oclass *oclass, void *data, u32 size, + struct nouveau_object **pobject) +{ + struct nv04_instmem_priv *priv; + int ret; - ret = drm_mm_init(&dev_priv->ramin_heap, 0, dev_priv->ramin_rsvd_vram); + ret = nouveau_instmem_create(parent, engine, oclass, &priv); + *pobject = nv_object(priv); if (ret) return ret; - /* 0x00000-0x10000: reserve for probable vbios image */ - ret = nouveau_gpuobj_new(dev, NULL, 0x10000, 0, 0, &priv->vbios); + /* PRAMIN aperture maps over the end of VRAM, reserve it */ + priv->base.reserved = 512 * 1024; + priv->base.alloc = nv04_instmem_alloc; + + ret = nouveau_mm_init(&priv->heap, 0, priv->base.reserved, 1); if (ret) return ret; - /* 0x10000-0x18000: reserve for RAMHT */ - ret = nouveau_gpuobj_new(dev, NULL, 0x08000, 0, NVOBJ_FLAG_ZERO_ALLOC, - &priv->ramht); + /* 0x00000-0x10000: reserve for probable vbios image */ + ret = nouveau_gpuobj_new(parent, NULL, 0x10000, 0, 0, &priv->vbios); if (ret) return ret; - /* 0x18000-0x18200: reserve for RAMRO */ - ret = nouveau_gpuobj_new(dev, NULL, 0x00200, 0, 0, &priv->ramro); + /* 0x10000-0x18000: reserve for RAMHT */ + ret = nouveau_gpuobj_new(parent, NULL, 0x08000, 0, + NVOBJ_FLAG_ZERO_ALLOC, &priv->ramht); if (ret) return ret; - /* 0x18200-0x18a00: reserve for RAMFC (enough for 32 nv30 channels) */ - ret = nouveau_gpuobj_new(dev, NULL, 0x00800, 0, NVOBJ_FLAG_ZERO_ALLOC, - &priv->ramfc); + /* 0x18000-0x18800: reserve for RAMFC (enough for 32 nv30 channels) */ + ret = nouveau_gpuobj_new(parent, NULL, 0x00800, 0, + NVOBJ_FLAG_ZERO_ALLOC, &priv->ramfc); if (ret) return ret; - ret = nouveau_ramht_new(dev, priv->ramht, &dev_priv->ramht); + /* 0x18800-0x18a00: reserve for RAMRO */ + ret = nouveau_gpuobj_new(parent, NULL, 0x00200, 0, 0, &priv->ramro); if (ret) return ret; + priv->created = true; return 0; } void -nv04_instmem_takedown(struct drm_device *dev) +nv04_instmem_dtor(struct nouveau_object *object) { - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nv04_instmem_priv *priv = dev_priv->engine.instmem.priv; - - nouveau_ramht_ref(NULL, &dev_priv->ramht, NULL); + struct nv04_instmem_priv *priv = (void *)object; nouveau_gpuobj_ref(NULL, &priv->ramfc); nouveau_gpuobj_ref(NULL, &priv->ramro); nouveau_gpuobj_ref(NULL, &priv->ramht); - - if (drm_mm_initialized(&dev_priv->ramin_heap)) - drm_mm_takedown(&dev_priv->ramin_heap); - - kfree(priv); - dev_priv->engine.instmem.priv = NULL; + nouveau_gpuobj_ref(NULL, &priv->vbios); + nouveau_mm_fini(&priv->heap); + if (priv->iomem) + iounmap(priv->iomem); + nouveau_instmem_destroy(&priv->base); } -int -nv04_instmem_suspend(struct drm_device *dev) -{ - return 0; -} - -void -nv04_instmem_resume(struct drm_device *dev) +static u32 +nv04_instmem_rd32(struct nouveau_object *object, u32 addr) { + return nv_rd32(object, 0x700000 + addr); } -int -nv04_instmem_get(struct nouveau_gpuobj *gpuobj, struct nouveau_channel *chan, - u32 size, u32 align) +static void +nv04_instmem_wr32(struct nouveau_object *object, u32 addr, u32 data) { - struct drm_nouveau_private *dev_priv = gpuobj->dev->dev_private; - struct drm_mm_node *ramin = NULL; - - do { - if (drm_mm_pre_get(&dev_priv->ramin_heap)) - return -ENOMEM; - - spin_lock(&dev_priv->ramin_lock); - ramin = drm_mm_search_free(&dev_priv->ramin_heap, size, align, 0); - if (ramin == NULL) { - spin_unlock(&dev_priv->ramin_lock); - return -ENOMEM; - } - - ramin = drm_mm_get_block_atomic(ramin, size, align); - spin_unlock(&dev_priv->ramin_lock); - } while (ramin == NULL); - - gpuobj->node = ramin; - gpuobj->vinst = ramin->start; - return 0; + return nv_wr32(object, 0x700000 + addr, data); } -void -nv04_instmem_put(struct nouveau_gpuobj *gpuobj) -{ - struct drm_nouveau_private *dev_priv = gpuobj->dev->dev_private; - - spin_lock(&dev_priv->ramin_lock); - drm_mm_put_block(gpuobj->node); - gpuobj->node = NULL; - spin_unlock(&dev_priv->ramin_lock); -} - -int -nv04_instmem_map(struct nouveau_gpuobj *gpuobj) -{ - gpuobj->pinst = gpuobj->vinst; - return 0; -} - -void -nv04_instmem_unmap(struct nouveau_gpuobj *gpuobj) -{ -} - -void -nv04_instmem_flush(struct drm_device *dev) -{ -} +struct nouveau_oclass +nv04_instmem_oclass = { + .handle = NV_SUBDEV(INSTMEM, 0x04), + .ofuncs = &(struct nouveau_ofuncs) { + .ctor = nv04_instmem_ctor, + .dtor = nv04_instmem_dtor, + .init = _nouveau_instmem_init, + .fini = _nouveau_instmem_fini, + .rd32 = nv04_instmem_rd32, + .wr32 = nv04_instmem_wr32, + }, +}; diff --git a/drivers/gpu/drm/nouveau/core/subdev/instmem/nv04.h b/drivers/gpu/drm/nouveau/core/subdev/instmem/nv04.h index a8c1104a83da..b2f82f9e4e7f 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/instmem/nv04.h +++ b/drivers/gpu/drm/nouveau/core/subdev/instmem/nv04.h @@ -1,11 +1,32 @@ #ifndef __NV04_INSTMEM_H__ #define __NV04_INSTMEM_H__ +#include +#include + +#include + struct nv04_instmem_priv { + struct nouveau_instmem base; + bool created; + + void __iomem *iomem; + struct nouveau_mm heap; + struct nouveau_gpuobj *vbios; struct nouveau_gpuobj *ramht; struct nouveau_gpuobj *ramro; struct nouveau_gpuobj *ramfc; }; +struct nv04_instobj_priv { + struct nouveau_instobj base; + struct nouveau_mm_node *mem; +}; + +void nv04_instmem_dtor(struct nouveau_object *); + +int nv04_instmem_alloc(struct nouveau_instmem *, struct nouveau_object *, + u32 size, u32 align, struct nouveau_object **pobject); + #endif diff --git a/drivers/gpu/drm/nouveau/core/subdev/instmem/nv40.c b/drivers/gpu/drm/nouveau/core/subdev/instmem/nv40.c index 7c938ae8ec93..6a22160324c1 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/instmem/nv40.c +++ b/drivers/gpu/drm/nouveau/core/subdev/instmem/nv40.c @@ -1,165 +1,139 @@ -#include "drmP.h" -#include "drm.h" - -#include "nouveau_drv.h" -#include -#include +/* + * Copyright 2012 Red Hat Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: Ben Skeggs + */ #include "nv04.h" -int nv40_instmem_init(struct drm_device *dev) +static inline int +nv44_graph_class(struct nv04_instmem_priv *priv) { - struct drm_nouveau_private *dev_priv = dev->dev_private; + if ((nv_device(priv)->chipset & 0xf0) == 0x60) + return 1; + return !(0x0baf & (1 << (nv_device(priv)->chipset & 0x0f))); +} + +static int +nv40_instmem_ctor(struct nouveau_object *parent, struct nouveau_object *engine, + struct nouveau_oclass *oclass, void *data, u32 size, + struct nouveau_object **pobject) +{ + struct nouveau_device *device = nv_device(parent); + struct pci_dev *pdev = device->pdev; struct nv04_instmem_priv *priv; - u32 vs, rsvd; - int ret; + int ret, bar, vs; - priv = kzalloc(sizeof(*priv), GFP_KERNEL); - if (!priv) - return -ENOMEM; - dev_priv->engine.instmem.priv = priv; + ret = nouveau_instmem_create(parent, engine, oclass, &priv); + *pobject = nv_object(priv); + if (ret) + return ret; + + /* map bar */ + if (pci_resource_len(pdev, 2)) + bar = 2; + else + bar = 3; + + priv->iomem = ioremap(pci_resource_start(pdev, bar), + pci_resource_len(pdev, bar)); + if (!priv->iomem) { + nv_error(priv, "unable to map PRAMIN BAR\n"); + return -EFAULT; + } /* PRAMIN aperture maps over the end of vram, reserve enough space * to fit graphics contexts for every channel, the magics come * from engine/graph/nv40.c */ - vs = hweight8((nv_rd32(dev, 0x001540) & 0x0000ff00) >> 8); - if (dev_priv->chipset == 0x40) rsvd = 0x6aa0 * vs; - else if (dev_priv->chipset < 0x43) rsvd = 0x4f00 * vs; - else if (nv44_graph_class(dev)) rsvd = 0x4980 * vs; - else rsvd = 0x4a40 * vs; - rsvd += 16 * 1024; - rsvd *= 32; /* per-channel */ - rsvd += 512 * 1024; /* pci(e)gart table */ - rsvd += 512 * 1024; /* object storage */ - dev_priv->ramin_rsvd_vram = round_up(rsvd, 4096); - dev_priv->ramin_available = true; - - ret = drm_mm_init(&dev_priv->ramin_heap, 0, dev_priv->ramin_rsvd_vram); + vs = hweight8((nv_rd32(priv, 0x001540) & 0x0000ff00) >> 8); + if (device->chipset == 0x40) priv->base.reserved = 0x6aa0 * vs; + else if (device->chipset < 0x43) priv->base.reserved = 0x4f00 * vs; + else if (nv44_graph_class(priv)) priv->base.reserved = 0x4980 * vs; + else priv->base.reserved = 0x4a40 * vs; + priv->base.reserved += 16 * 1024; + priv->base.reserved *= 32; /* per-channel */ + priv->base.reserved += 512 * 1024; /* pci(e)gart table */ + priv->base.reserved += 512 * 1024; /* object storage */ + + priv->base.reserved = round_up(priv->base.reserved, 4096); + priv->base.alloc = nv04_instmem_alloc; + + ret = nouveau_mm_init(&priv->heap, 0, priv->base.reserved, 1); if (ret) return ret; /* 0x00000-0x10000: reserve for probable vbios image */ - ret = nouveau_gpuobj_new(dev, NULL, 0x10000, 0, 0, &priv->vbios); + ret = nouveau_gpuobj_new(parent, NULL, 0x10000, 0, 0, &priv->vbios); if (ret) return ret; /* 0x10000-0x18000: reserve for RAMHT */ - ret = nouveau_gpuobj_new(dev, NULL, 0x08000, 0, NVOBJ_FLAG_ZERO_ALLOC, - &priv->ramht); + ret = nouveau_gpuobj_new(parent, NULL, 0x08000, 0, + NVOBJ_FLAG_ZERO_ALLOC, &priv->ramht); if (ret) return ret; /* 0x18000-0x18200: reserve for RAMRO * 0x18200-0x20000: padding */ - ret = nouveau_gpuobj_new(dev, NULL, 0x08000, 0, 0, &priv->ramro); + ret = nouveau_gpuobj_new(parent, NULL, 0x08000, 0, 0, &priv->ramro); if (ret) return ret; /* 0x20000-0x21000: reserve for RAMFC - * 0x21000-0x40000: padding + some unknown stuff (see below) - * - * It appears something is controlled by 0x2220/0x2230 on certain - * NV4x chipsets as well as RAMFC. When 0x2230 == 0 ("new style" - * control) the upper 16-bits of 0x2220 points at this other - * mysterious table that's clobbering important things. - * - * We're now pointing this at RAMIN+0x30000 to avoid RAMFC getting - * smashed to pieces on us, so reserve 0x30000-0x40000 too.. + * 0x21000-0x40000: padding and some unknown crap */ - ret = nouveau_gpuobj_new(dev, NULL, 0x20000, 0, NVOBJ_FLAG_ZERO_ALLOC, - &priv->ramfc); - if (ret) - return ret; - - ret = nouveau_ramht_new(dev, priv->ramht, &dev_priv->ramht); + ret = nouveau_gpuobj_new(parent, NULL, 0x20000, 0, + NVOBJ_FLAG_ZERO_ALLOC, &priv->ramfc); if (ret) return ret; + priv->created = true; return 0; } -void -nv40_instmem_takedown(struct drm_device *dev) +static u32 +nv40_instmem_rd32(struct nouveau_object *object, u32 addr) { - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nv04_instmem_priv *priv = dev_priv->engine.instmem.priv; - - nouveau_ramht_ref(NULL, &dev_priv->ramht, NULL); - nouveau_gpuobj_ref(NULL, &priv->ramfc); - nouveau_gpuobj_ref(NULL, &priv->ramro); - nouveau_gpuobj_ref(NULL, &priv->ramht); - - if (drm_mm_initialized(&dev_priv->ramin_heap)) - drm_mm_takedown(&dev_priv->ramin_heap); - - kfree(priv); - dev_priv->engine.instmem.priv = NULL; -} - -int -nv40_instmem_suspend(struct drm_device *dev) -{ - return 0; + struct nv04_instmem_priv *priv = (void *)object; + return ioread32_native(priv->iomem + addr); } -void -nv40_instmem_resume(struct drm_device *dev) +static void +nv40_instmem_wr32(struct nouveau_object *object, u32 addr, u32 data) { + struct nv04_instmem_priv *priv = (void *)object; + iowrite32_native(data, priv->iomem + addr); } -int -nv40_instmem_get(struct nouveau_gpuobj *gpuobj, struct nouveau_channel *chan, - u32 size, u32 align) -{ - struct drm_nouveau_private *dev_priv = gpuobj->dev->dev_private; - struct drm_mm_node *ramin = NULL; - - do { - if (drm_mm_pre_get(&dev_priv->ramin_heap)) - return -ENOMEM; - - spin_lock(&dev_priv->ramin_lock); - ramin = drm_mm_search_free(&dev_priv->ramin_heap, size, align, 0); - if (ramin == NULL) { - spin_unlock(&dev_priv->ramin_lock); - return -ENOMEM; - } - - ramin = drm_mm_get_block_atomic(ramin, size, align); - spin_unlock(&dev_priv->ramin_lock); - } while (ramin == NULL); - - gpuobj->node = ramin; - gpuobj->vinst = ramin->start; - return 0; -} - -void -nv40_instmem_put(struct nouveau_gpuobj *gpuobj) -{ - struct drm_nouveau_private *dev_priv = gpuobj->dev->dev_private; - - spin_lock(&dev_priv->ramin_lock); - drm_mm_put_block(gpuobj->node); - gpuobj->node = NULL; - spin_unlock(&dev_priv->ramin_lock); -} - -int -nv40_instmem_map(struct nouveau_gpuobj *gpuobj) -{ - gpuobj->pinst = gpuobj->vinst; - return 0; -} - -void -nv40_instmem_unmap(struct nouveau_gpuobj *gpuobj) -{ -} - -void -nv40_instmem_flush(struct drm_device *dev) -{ -} +struct nouveau_oclass +nv40_instmem_oclass = { + .handle = NV_SUBDEV(INSTMEM, 0x40), + .ofuncs = &(struct nouveau_ofuncs) { + .ctor = nv40_instmem_ctor, + .dtor = nv04_instmem_dtor, + .init = _nouveau_instmem_init, + .fini = _nouveau_instmem_fini, + .rd32 = nv40_instmem_rd32, + .wr32 = nv40_instmem_wr32, + }, +}; diff --git a/drivers/gpu/drm/nouveau/core/subdev/instmem/nv50.c b/drivers/gpu/drm/nouveau/core/subdev/instmem/nv50.c index f88530b96ec3..27ef0891d10b 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/instmem/nv50.c +++ b/drivers/gpu/drm/nouveau/core/subdev/instmem/nv50.c @@ -1,390 +1,172 @@ /* - * Copyright (C) 2007 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 */ -#include "drmP.h" -#include "drm.h" - -#include "nouveau_drv.h" -#include +#include +#include -#define BAR1_VM_BASE 0x0020000000ULL -#define BAR1_VM_SIZE pci_resource_len(dev->pdev, 1) -#define BAR3_VM_BASE 0x0000000000ULL -#define BAR3_VM_SIZE pci_resource_len(dev->pdev, 3) +#include struct nv50_instmem_priv { - uint32_t save1700[5]; /* 0x1700->0x1710 */ - - struct nouveau_gpuobj *bar1_dmaobj; - struct nouveau_gpuobj *bar3_dmaobj; + struct nouveau_instmem base; + spinlock_t lock; + u64 addr; }; -static void -nv50_channel_del(struct nouveau_channel **pchan) -{ - struct nouveau_channel *chan; - - chan = *pchan; - *pchan = NULL; - if (!chan) - return; - - nouveau_vm_ref(NULL, &chan->vm, chan->vm_pd); - nouveau_gpuobj_ref(NULL, &chan->vm_pd); - if (drm_mm_initialized(&chan->ramin_heap)) - drm_mm_takedown(&chan->ramin_heap); - nouveau_gpuobj_ref(NULL, &chan->ramin); - kfree(chan); -} +struct nv50_instobj_priv { + struct nouveau_instobj base; + struct nouveau_mem *mem; +}; static int -nv50_channel_new(struct drm_device *dev, u32 size, struct nouveau_vm *vm, - struct nouveau_channel **pchan) -{ - struct drm_nouveau_private *dev_priv = dev->dev_private; - u32 pgd = (dev_priv->chipset == 0x50) ? 0x1400 : 0x0200; - struct nouveau_channel *chan; - int ret, i; - - chan = kzalloc(sizeof(*chan), GFP_KERNEL); - if (!chan) - return -ENOMEM; - chan->dev = dev; - - ret = nouveau_gpuobj_new(dev, NULL, size, 0x1000, 0, &chan->ramin); - if (ret) { - nv50_channel_del(&chan); - return ret; - } - - ret = drm_mm_init(&chan->ramin_heap, pgd, chan->ramin->size - pgd); - if (ret) { - nv50_channel_del(&chan); - return ret; - } - - ret = nouveau_gpuobj_new(dev, chan, 0x4000, 0, 0, &chan->vm_pd); - if (ret) { - nv50_channel_del(&chan); - return ret; - } - - for (i = 0; i < 0x4000; i += 8) { - nv_wo32(chan->vm_pd, i + 0, 0x00000000); - nv_wo32(chan->vm_pd, i + 4, 0xdeadcafe); - } - - ret = nouveau_vm_ref(vm, &chan->vm, chan->vm_pd); - if (ret) { - nv50_channel_del(&chan); - return ret; - } - - *pchan = chan; - return 0; -} - -int -nv50_instmem_init(struct drm_device *dev) +nv50_instobj_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 nv50_instmem_priv *priv; - struct nouveau_channel *chan; - struct nouveau_vm *vm; - int ret, i; - u32 tmp; - - priv = kzalloc(sizeof(*priv), GFP_KERNEL); - if (!priv) - return -ENOMEM; - dev_priv->engine.instmem.priv = priv; - - /* Save state, will restore at takedown. */ - for (i = 0x1700; i <= 0x1710; i += 4) - priv->save1700[(i-0x1700)/4] = nv_rd32(dev, i); - - /* Global PRAMIN heap */ - ret = drm_mm_init(&dev_priv->ramin_heap, 0, dev_priv->ramin_size); - if (ret) { - NV_ERROR(dev, "Failed to init RAMIN heap\n"); - goto error; - } - - /* BAR3 */ - ret = nouveau_vm_new(dev, BAR3_VM_BASE, BAR3_VM_SIZE, BAR3_VM_BASE, - &dev_priv->bar3_vm); - if (ret) - goto error; - - ret = nouveau_gpuobj_new(dev, NULL, (BAR3_VM_SIZE >> 12) * 8, - 0x1000, NVOBJ_FLAG_DONT_MAP | - NVOBJ_FLAG_ZERO_ALLOC, - &dev_priv->bar3_vm->pgt[0].obj[0]); - if (ret) - goto error; - dev_priv->bar3_vm->pgt[0].refcount[0] = 1; - - nv50_instmem_map(dev_priv->bar3_vm->pgt[0].obj[0]); - - ret = nv50_channel_new(dev, 128 * 1024, dev_priv->bar3_vm, &chan); - if (ret) - goto error; - dev_priv->channels.ptr[0] = dev_priv->channels.ptr[127] = chan; - - ret = nv50_gpuobj_dma_new(chan, 0x0000, BAR3_VM_BASE, BAR3_VM_SIZE, - NV_MEM_TARGET_VM, NV_MEM_ACCESS_VM, - NV_MEM_TYPE_VM, NV_MEM_COMP_VM, - &priv->bar3_dmaobj); - if (ret) - goto error; - - nv_wr32(dev, 0x001704, 0x00000000 | (chan->ramin->vinst >> 12)); - nv_wr32(dev, 0x001704, 0x40000000 | (chan->ramin->vinst >> 12)); - nv_wr32(dev, 0x00170c, 0x80000000 | (priv->bar3_dmaobj->cinst >> 4)); - - dev_priv->engine.instmem.flush(dev); - dev_priv->ramin_available = true; - - tmp = nv_ro32(chan->ramin, 0); - nv_wo32(chan->ramin, 0, ~tmp); - if (nv_ro32(chan->ramin, 0) != ~tmp) { - NV_ERROR(dev, "PRAMIN readback failed\n"); - ret = -EIO; - goto error; - } - nv_wo32(chan->ramin, 0, tmp); - - /* BAR1 */ - ret = nouveau_vm_new(dev, BAR1_VM_BASE, BAR1_VM_SIZE, BAR1_VM_BASE, &vm); - if (ret) - goto error; + struct nouveau_fb *pfb = nouveau_fb(parent); + struct nv50_instobj_priv *node; + u32 align = (unsigned long)data; + int ret; - ret = nouveau_vm_ref(vm, &dev_priv->bar1_vm, chan->vm_pd); - if (ret) - goto error; - nouveau_vm_ref(NULL, &vm, NULL); + size = max((size + 4095) & ~4095, (u32)4096); + align = max((align + 4095) & ~4095, (u32)4096); - ret = nv50_gpuobj_dma_new(chan, 0x0000, BAR1_VM_BASE, BAR1_VM_SIZE, - NV_MEM_TARGET_VM, NV_MEM_ACCESS_VM, - NV_MEM_TYPE_VM, NV_MEM_COMP_VM, - &priv->bar1_dmaobj); + ret = nouveau_instobj_create(parent, engine, oclass, &node); + *pobject = nv_object(node); if (ret) - goto error; - - nv_wr32(dev, 0x001708, 0x80000000 | (priv->bar1_dmaobj->cinst >> 4)); - for (i = 0; i < 8; i++) - nv_wr32(dev, 0x1900 + (i*4), 0); + return ret; - /* Create shared channel VM, space is reserved at the beginning - * to catch "NULL pointer" references - */ - ret = nouveau_vm_new(dev, 0, (1ULL << 40), 0x0020000000ULL, - &dev_priv->chan_vm); + ret = pfb->ram.get(pfb, size, align, 0, 0x800, &node->mem); if (ret) return ret; + node->base.addr = node->mem->offset; + node->base.size = node->mem->size << 12; + node->mem->page_shift = 12; return 0; - -error: - nv50_instmem_takedown(dev); - return ret; } -void -nv50_instmem_takedown(struct drm_device *dev) +static void +nv50_instobj_dtor(struct nouveau_object *object) { - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nv50_instmem_priv *priv = dev_priv->engine.instmem.priv; - struct nouveau_channel *chan = dev_priv->channels.ptr[0]; - int i; - - NV_DEBUG(dev, "\n"); - - if (!priv) - return; - - dev_priv->ramin_available = false; - - nouveau_vm_ref(NULL, &dev_priv->chan_vm, NULL); - - for (i = 0x1700; i <= 0x1710; i += 4) - nv_wr32(dev, i, priv->save1700[(i - 0x1700) / 4]); - - nouveau_gpuobj_ref(NULL, &priv->bar3_dmaobj); - nouveau_gpuobj_ref(NULL, &priv->bar1_dmaobj); - - nouveau_vm_ref(NULL, &dev_priv->bar1_vm, chan->vm_pd); - dev_priv->channels.ptr[127] = 0; - nv50_channel_del(&dev_priv->channels.ptr[0]); - - nouveau_gpuobj_ref(NULL, &dev_priv->bar3_vm->pgt[0].obj[0]); - nouveau_vm_ref(NULL, &dev_priv->bar3_vm, NULL); - - if (drm_mm_initialized(&dev_priv->ramin_heap)) - drm_mm_takedown(&dev_priv->ramin_heap); - - dev_priv->engine.instmem.priv = NULL; - kfree(priv); + struct nv50_instobj_priv *node = (void *)object; + struct nouveau_fb *pfb = nouveau_fb(object); + pfb->ram.put(pfb, &node->mem); + nouveau_instobj_destroy(&node->base); } -int -nv50_instmem_suspend(struct drm_device *dev) +static u32 +nv50_instobj_rd32(struct nouveau_object *object, u32 offset) { - struct drm_nouveau_private *dev_priv = dev->dev_private; - - dev_priv->ramin_available = false; - return 0; + struct nv50_instmem_priv *priv = (void *)object->engine; + struct nv50_instobj_priv *node = (void *)object; + unsigned long flags; + u64 base = (node->mem->offset + offset) & 0xffffff00000ULL; + u64 addr = (node->mem->offset + offset) & 0x000000fffffULL; + u32 data; + + spin_lock_irqsave(&priv->lock, flags); + if (unlikely(priv->addr != base)) { + nv_wr32(priv, 0x001700, base >> 16); + priv->addr = base; + } + data = nv_rd32(priv, 0x700000 + addr); + spin_unlock_irqrestore(&priv->lock, flags); + return data; } -void -nv50_instmem_resume(struct drm_device *dev) +static void +nv50_instobj_wr32(struct nouveau_object *object, u32 offset, u32 data) { - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nv50_instmem_priv *priv = dev_priv->engine.instmem.priv; - struct nouveau_channel *chan = dev_priv->channels.ptr[0]; - int i; - - /* Poke the relevant regs, and pray it works :) */ - nv_wr32(dev, NV50_PUNK_BAR_CFG_BASE, (chan->ramin->vinst >> 12)); - nv_wr32(dev, NV50_PUNK_UNK1710, 0); - nv_wr32(dev, NV50_PUNK_BAR_CFG_BASE, (chan->ramin->vinst >> 12) | - NV50_PUNK_BAR_CFG_BASE_VALID); - nv_wr32(dev, NV50_PUNK_BAR1_CTXDMA, (priv->bar1_dmaobj->cinst >> 4) | - NV50_PUNK_BAR1_CTXDMA_VALID); - nv_wr32(dev, NV50_PUNK_BAR3_CTXDMA, (priv->bar3_dmaobj->cinst >> 4) | - NV50_PUNK_BAR3_CTXDMA_VALID); - - for (i = 0; i < 8; i++) - nv_wr32(dev, 0x1900 + (i*4), 0); + struct nv50_instmem_priv *priv = (void *)object->engine; + struct nv50_instobj_priv *node = (void *)object; + unsigned long flags; + u64 base = (node->mem->offset + offset) & 0xffffff00000ULL; + u64 addr = (node->mem->offset + offset) & 0x000000fffffULL; - dev_priv->ramin_available = true; + spin_lock_irqsave(&priv->lock, flags); + if (unlikely(priv->addr != base)) { + nv_wr32(priv, 0x001700, base >> 16); + priv->addr = base; + } + nv_wr32(priv, 0x700000 + addr, data); + spin_unlock_irqrestore(&priv->lock, flags); } -struct nv50_gpuobj_node { - struct nouveau_mem *vram; - struct nouveau_vma chan_vma; - u32 align; +static struct nouveau_oclass +nv50_instobj_oclass = { + .ofuncs = &(struct nouveau_ofuncs) { + .ctor = nv50_instobj_ctor, + .dtor = nv50_instobj_dtor, + .init = _nouveau_instobj_init, + .fini = _nouveau_instobj_fini, + .rd32 = nv50_instobj_rd32, + .wr32 = nv50_instobj_wr32, + }, }; -int -nv50_instmem_get(struct nouveau_gpuobj *gpuobj, struct nouveau_channel *chan, - u32 size, u32 align) -{ - struct drm_device *dev = gpuobj->dev; - struct nv50_gpuobj_node *node = NULL; - int ret; - - node = kzalloc(sizeof(*node), GFP_KERNEL); - if (!node) - return -ENOMEM; - node->align = align; - - size = (size + 4095) & ~4095; - align = max(align, (u32)4096); - - ret = nvfb_vram_get(dev, size, align, 0, 0x800, &node->vram); - if (ret) { - kfree(node); - return ret; - } - - gpuobj->vinst = node->vram->offset; - gpuobj->size = size; - gpuobj->node = node; - return 0; -} - -void -nv50_instmem_put(struct nouveau_gpuobj *gpuobj) +static int +nv50_instmem_alloc(struct nouveau_instmem *imem, struct nouveau_object *parent, + u32 size, u32 align, struct nouveau_object **pobject) { - struct drm_device *dev = gpuobj->dev; - struct nv50_gpuobj_node *node; - - node = gpuobj->node; - gpuobj->node = NULL; - - if (node->chan_vma.node) { - nouveau_vm_unmap(&node->chan_vma); - nouveau_vm_put(&node->chan_vma); - } - nvfb_vram_put(dev, &node->vram); - kfree(node); + struct nouveau_object *engine = nv_object(imem); + return nouveau_object_ctor(parent, engine, &nv50_instobj_oclass, + (void *)(unsigned long)align, size, pobject); } -int -nv50_instmem_map(struct nouveau_gpuobj *gpuobj) +static int +nv50_instmem_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 = gpuobj->dev->dev_private; - struct nv50_gpuobj_node *node = gpuobj->node; + struct nv50_instmem_priv *priv; int ret; - ret = nouveau_vm_get(dev_priv->bar3_vm, gpuobj->size, 12, - NV_MEM_ACCESS_RW, &node->vram->bar_vma); + ret = nouveau_instmem_create(parent, engine, oclass, &priv); + *pobject = nv_object(priv); if (ret) return ret; - nouveau_vm_map(&node->vram->bar_vma, node->vram); - gpuobj->pinst = node->vram->bar_vma.offset; + spin_lock_init(&priv->lock); + priv->base.alloc = nv50_instmem_alloc; return 0; } -void -nv50_instmem_unmap(struct nouveau_gpuobj *gpuobj) +static int +nv50_instmem_fini(struct nouveau_object *object, bool suspend) { - struct nv50_gpuobj_node *node = gpuobj->node; - - if (node->vram->bar_vma.node) { - nouveau_vm_unmap(&node->vram->bar_vma); - nouveau_vm_put(&node->vram->bar_vma); - } + struct nv50_instmem_priv *priv = (void *)object; + priv->addr = ~0ULL; + return nouveau_instmem_fini(&priv->base, suspend); } -void -nv50_instmem_flush(struct drm_device *dev) -{ - struct drm_nouveau_private *dev_priv = dev->dev_private; - unsigned long flags; - - spin_lock_irqsave(&dev_priv->vm_lock, flags); - nv_wr32(dev, 0x00330c, 0x00000001); - if (!nv_wait(dev, 0x00330c, 0x00000002, 0x00000000)) - NV_ERROR(dev, "PRAMIN flush timeout\n"); - spin_unlock_irqrestore(&dev_priv->vm_lock, flags); -} - -void -nv84_instmem_flush(struct drm_device *dev) -{ - struct drm_nouveau_private *dev_priv = dev->dev_private; - unsigned long flags; - - spin_lock_irqsave(&dev_priv->vm_lock, flags); - nv_wr32(dev, 0x070000, 0x00000001); - if (!nv_wait(dev, 0x070000, 0x00000002, 0x00000000)) - NV_ERROR(dev, "PRAMIN flush timeout\n"); - spin_unlock_irqrestore(&dev_priv->vm_lock, flags); -} +struct nouveau_oclass +nv50_instmem_oclass = { + .handle = NV_SUBDEV(INSTMEM, 0x50), + .ofuncs = &(struct nouveau_ofuncs) { + .ctor = nv50_instmem_ctor, + .dtor = _nouveau_instmem_dtor, + .init = _nouveau_instmem_init, + .fini = nv50_instmem_fini, + }, +}; diff --git a/drivers/gpu/drm/nouveau/core/subdev/instmem/nvc0.c b/drivers/gpu/drm/nouveau/core/subdev/instmem/nvc0.c deleted file mode 100644 index 0ce986910cbf..000000000000 --- a/drivers/gpu/drm/nouveau/core/subdev/instmem/nvc0.c +++ /dev/null @@ -1,222 +0,0 @@ -/* - * Copyright 2010 Red Hat Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: Ben Skeggs - */ - -#include "drmP.h" - -#include "nouveau_drv.h" -#include - -struct nvc0_instmem_priv { - struct nouveau_gpuobj *bar1_pgd; - struct nouveau_channel *bar1; - struct nouveau_gpuobj *bar3_pgd; - struct nouveau_channel *bar3; -}; - -int -nvc0_instmem_suspend(struct drm_device *dev) -{ - struct drm_nouveau_private *dev_priv = dev->dev_private; - - dev_priv->ramin_available = false; - return 0; -} - -void -nvc0_instmem_resume(struct drm_device *dev) -{ - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nvc0_instmem_priv *priv = dev_priv->engine.instmem.priv; - - nv_mask(dev, 0x100c80, 0x00000001, 0x00000000); - nv_wr32(dev, 0x001704, 0x80000000 | priv->bar1->ramin->vinst >> 12); - nv_wr32(dev, 0x001714, 0xc0000000 | priv->bar3->ramin->vinst >> 12); - dev_priv->ramin_available = true; -} - -static void -nvc0_channel_del(struct nouveau_channel **pchan) -{ - struct nouveau_channel *chan; - - chan = *pchan; - *pchan = NULL; - if (!chan) - return; - - nouveau_vm_ref(NULL, &chan->vm, NULL); - if (drm_mm_initialized(&chan->ramin_heap)) - drm_mm_takedown(&chan->ramin_heap); - nouveau_gpuobj_ref(NULL, &chan->ramin); - kfree(chan); -} - -static int -nvc0_channel_new(struct drm_device *dev, u32 size, struct nouveau_vm *vm, - struct nouveau_channel **pchan, - struct nouveau_gpuobj *pgd, u64 vm_size) -{ - struct nouveau_channel *chan; - int ret; - - chan = kzalloc(sizeof(*chan), GFP_KERNEL); - if (!chan) - return -ENOMEM; - chan->dev = dev; - - ret = nouveau_gpuobj_new(dev, NULL, size, 0x1000, 0, &chan->ramin); - if (ret) { - nvc0_channel_del(&chan); - return ret; - } - - ret = drm_mm_init(&chan->ramin_heap, 0x1000, size - 0x1000); - if (ret) { - nvc0_channel_del(&chan); - return ret; - } - - ret = nouveau_vm_ref(vm, &chan->vm, NULL); - if (ret) { - nvc0_channel_del(&chan); - return ret; - } - - nv_wo32(chan->ramin, 0x0200, lower_32_bits(pgd->vinst)); - nv_wo32(chan->ramin, 0x0204, upper_32_bits(pgd->vinst)); - nv_wo32(chan->ramin, 0x0208, lower_32_bits(vm_size - 1)); - nv_wo32(chan->ramin, 0x020c, upper_32_bits(vm_size - 1)); - - *pchan = chan; - return 0; -} - -int -nvc0_instmem_init(struct drm_device *dev) -{ - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_instmem_engine *pinstmem = &dev_priv->engine.instmem; - struct pci_dev *pdev = dev->pdev; - struct nvc0_instmem_priv *priv; - struct nouveau_vm *vm = NULL; - int ret; - - priv = kzalloc(sizeof(*priv), GFP_KERNEL); - if (!priv) - return -ENOMEM; - pinstmem->priv = priv; - - /* BAR3 VM */ - ret = nouveau_vm_new(dev, 0, pci_resource_len(pdev, 3), 0, - &dev_priv->bar3_vm); - if (ret) - goto error; - - ret = nouveau_gpuobj_new(dev, NULL, - (pci_resource_len(pdev, 3) >> 12) * 8, 0, - NVOBJ_FLAG_DONT_MAP | - NVOBJ_FLAG_ZERO_ALLOC, - &dev_priv->bar3_vm->pgt[0].obj[0]); - if (ret) - goto error; - dev_priv->bar3_vm->pgt[0].refcount[0] = 1; - - nv50_instmem_map(dev_priv->bar3_vm->pgt[0].obj[0]); - - ret = nouveau_gpuobj_new(dev, NULL, 0x8000, 4096, - NVOBJ_FLAG_ZERO_ALLOC, &priv->bar3_pgd); - if (ret) - goto error; - - ret = nouveau_vm_ref(dev_priv->bar3_vm, &vm, priv->bar3_pgd); - if (ret) - goto error; - nouveau_vm_ref(NULL, &vm, NULL); - - ret = nvc0_channel_new(dev, 8192, dev_priv->bar3_vm, &priv->bar3, - priv->bar3_pgd, pci_resource_len(dev->pdev, 3)); - if (ret) - goto error; - - /* BAR1 VM */ - ret = nouveau_vm_new(dev, 0, pci_resource_len(pdev, 1), 0, &vm); - if (ret) - goto error; - - ret = nouveau_gpuobj_new(dev, NULL, 0x8000, 4096, - NVOBJ_FLAG_ZERO_ALLOC, &priv->bar1_pgd); - if (ret) - goto error; - - ret = nouveau_vm_ref(vm, &dev_priv->bar1_vm, priv->bar1_pgd); - if (ret) - goto error; - nouveau_vm_ref(NULL, &vm, NULL); - - ret = nvc0_channel_new(dev, 8192, dev_priv->bar1_vm, &priv->bar1, - priv->bar1_pgd, pci_resource_len(dev->pdev, 1)); - if (ret) - goto error; - - /* channel vm */ - ret = nouveau_vm_new(dev, 0, (1ULL << 40), 0x0008000000ULL, - &dev_priv->chan_vm); - if (ret) - goto error; - - nvc0_instmem_resume(dev); - return 0; -error: - nvc0_instmem_takedown(dev); - return ret; -} - -void -nvc0_instmem_takedown(struct drm_device *dev) -{ - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nvc0_instmem_priv *priv = dev_priv->engine.instmem.priv; - struct nouveau_vm *vm = NULL; - - nvc0_instmem_suspend(dev); - - nv_wr32(dev, 0x1704, 0x00000000); - nv_wr32(dev, 0x1714, 0x00000000); - - nouveau_vm_ref(NULL, &dev_priv->chan_vm, NULL); - - nvc0_channel_del(&priv->bar1); - nouveau_vm_ref(NULL, &dev_priv->bar1_vm, priv->bar1_pgd); - nouveau_gpuobj_ref(NULL, &priv->bar1_pgd); - - nvc0_channel_del(&priv->bar3); - nouveau_vm_ref(dev_priv->bar3_vm, &vm, NULL); - nouveau_vm_ref(NULL, &vm, priv->bar3_pgd); - nouveau_gpuobj_ref(NULL, &priv->bar3_pgd); - nouveau_gpuobj_ref(NULL, &dev_priv->bar3_vm->pgt[0].obj[0]); - nouveau_vm_ref(NULL, &dev_priv->bar3_vm, NULL); - - dev_priv->engine.instmem.priv = NULL; - kfree(priv); -} diff --git a/drivers/gpu/drm/nouveau/core/subdev/vm/base.c b/drivers/gpu/drm/nouveau/core/subdev/vm/base.c index 9fb858a21abb..b92b3d47c69c 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/vm/base.c +++ b/drivers/gpu/drm/nouveau/core/subdev/vm/base.c @@ -22,22 +22,24 @@ * Authors: Ben Skeggs */ -#include "drmP.h" -#include "nouveau_drv.h" +#include #include + +#include #include void nouveau_vm_map_at(struct nouveau_vma *vma, u64 delta, struct nouveau_mem *node) { struct nouveau_vm *vm = vma->vm; + struct nouveau_vmmgr *vmm = vm->vmm; struct nouveau_mm_node *r; - int big = vma->node->type != vm->spg_shift; + int big = vma->node->type != vmm->spg_shift; u32 offset = vma->node->offset + (delta >> 12); u32 bits = vma->node->type - 12; - u32 pde = (offset >> vm->pgt_bits) - vm->fpde; - u32 pte = (offset & ((1 << vm->pgt_bits) - 1)) >> bits; - u32 max = 1 << (vm->pgt_bits - bits); + u32 pde = (offset >> vmm->pgt_bits) - vm->fpde; + u32 pte = (offset & ((1 << vmm->pgt_bits) - 1)) >> bits; + u32 max = 1 << (vmm->pgt_bits - bits); u32 end, len; delta = 0; @@ -53,7 +55,7 @@ nouveau_vm_map_at(struct nouveau_vma *vma, u64 delta, struct nouveau_mem *node) end = max; len = end - pte; - vm->map(vma, pgt, node, pte, len, phys, delta); + vmm->map(vma, pgt, node, pte, len, phys, delta); num -= len; pte += len; @@ -67,7 +69,7 @@ nouveau_vm_map_at(struct nouveau_vma *vma, u64 delta, struct nouveau_mem *node) } } - vm->flush(vm); + vmm->flush(vm); } void @@ -81,13 +83,14 @@ nouveau_vm_map_sg_table(struct nouveau_vma *vma, u64 delta, u64 length, struct nouveau_mem *mem) { struct nouveau_vm *vm = vma->vm; - int big = vma->node->type != vm->spg_shift; + struct nouveau_vmmgr *vmm = vm->vmm; + int big = vma->node->type != vmm->spg_shift; u32 offset = vma->node->offset + (delta >> 12); u32 bits = vma->node->type - 12; u32 num = length >> vma->node->type; - u32 pde = (offset >> vm->pgt_bits) - vm->fpde; - u32 pte = (offset & ((1 << vm->pgt_bits) - 1)) >> bits; - u32 max = 1 << (vm->pgt_bits - bits); + u32 pde = (offset >> vmm->pgt_bits) - vm->fpde; + u32 pte = (offset & ((1 << vmm->pgt_bits) - 1)) >> bits; + u32 max = 1 << (vmm->pgt_bits - bits); unsigned m, sglen; u32 end, len; int i; @@ -105,7 +108,7 @@ nouveau_vm_map_sg_table(struct nouveau_vma *vma, u64 delta, u64 length, for (m = 0; m < len; m++) { dma_addr_t addr = sg_dma_address(sg) + (m << PAGE_SHIFT); - vm->map_sg(vma, pgt, mem, pte, 1, &addr); + vmm->map_sg(vma, pgt, mem, pte, 1, &addr); num--; pte++; @@ -120,7 +123,7 @@ nouveau_vm_map_sg_table(struct nouveau_vma *vma, u64 delta, u64 length, for (; m < sglen; m++) { dma_addr_t addr = sg_dma_address(sg) + (m << PAGE_SHIFT); - vm->map_sg(vma, pgt, mem, pte, 1, &addr); + vmm->map_sg(vma, pgt, mem, pte, 1, &addr); num--; pte++; if (num == 0) @@ -130,7 +133,7 @@ nouveau_vm_map_sg_table(struct nouveau_vma *vma, u64 delta, u64 length, } finish: - vm->flush(vm); + vmm->flush(vm); } void @@ -138,14 +141,15 @@ nouveau_vm_map_sg(struct nouveau_vma *vma, u64 delta, u64 length, struct nouveau_mem *mem) { struct nouveau_vm *vm = vma->vm; + struct nouveau_vmmgr *vmm = vm->vmm; dma_addr_t *list = mem->pages; - int big = vma->node->type != vm->spg_shift; + int big = vma->node->type != vmm->spg_shift; u32 offset = vma->node->offset + (delta >> 12); u32 bits = vma->node->type - 12; u32 num = length >> vma->node->type; - u32 pde = (offset >> vm->pgt_bits) - vm->fpde; - u32 pte = (offset & ((1 << vm->pgt_bits) - 1)) >> bits; - u32 max = 1 << (vm->pgt_bits - bits); + u32 pde = (offset >> vmm->pgt_bits) - vm->fpde; + u32 pte = (offset & ((1 << vmm->pgt_bits) - 1)) >> bits; + u32 max = 1 << (vmm->pgt_bits - bits); u32 end, len; while (num) { @@ -156,7 +160,7 @@ nouveau_vm_map_sg(struct nouveau_vma *vma, u64 delta, u64 length, end = max; len = end - pte; - vm->map_sg(vma, pgt, mem, pte, len, list); + vmm->map_sg(vma, pgt, mem, pte, len, list); num -= len; pte += len; @@ -167,20 +171,21 @@ nouveau_vm_map_sg(struct nouveau_vma *vma, u64 delta, u64 length, } } - vm->flush(vm); + vmm->flush(vm); } void nouveau_vm_unmap_at(struct nouveau_vma *vma, u64 delta, u64 length) { struct nouveau_vm *vm = vma->vm; - int big = vma->node->type != vm->spg_shift; + struct nouveau_vmmgr *vmm = vm->vmm; + int big = vma->node->type != vmm->spg_shift; u32 offset = vma->node->offset + (delta >> 12); u32 bits = vma->node->type - 12; u32 num = length >> vma->node->type; - u32 pde = (offset >> vm->pgt_bits) - vm->fpde; - u32 pte = (offset & ((1 << vm->pgt_bits) - 1)) >> bits; - u32 max = 1 << (vm->pgt_bits - bits); + u32 pde = (offset >> vmm->pgt_bits) - vm->fpde; + u32 pte = (offset & ((1 << vmm->pgt_bits) - 1)) >> bits; + u32 max = 1 << (vmm->pgt_bits - bits); u32 end, len; while (num) { @@ -191,7 +196,7 @@ nouveau_vm_unmap_at(struct nouveau_vma *vma, u64 delta, u64 length) end = max; len = end - pte; - vm->unmap(pgt, pte, len); + vmm->unmap(pgt, pte, len); num -= len; pte += len; @@ -201,7 +206,7 @@ nouveau_vm_unmap_at(struct nouveau_vma *vma, u64 delta, u64 length) } } - vm->flush(vm); + vmm->flush(vm); } void @@ -213,6 +218,7 @@ nouveau_vm_unmap(struct nouveau_vma *vma) static void nouveau_vm_unmap_pgt(struct nouveau_vm *vm, int big, u32 fpde, u32 lpde) { + struct nouveau_vmmgr *vmm = vm->vmm; struct nouveau_vm_pgd *vpgd; struct nouveau_vm_pgt *vpgt; struct nouveau_gpuobj *pgt; @@ -227,7 +233,7 @@ nouveau_vm_unmap_pgt(struct nouveau_vm *vm, int big, u32 fpde, u32 lpde) vpgt->obj[big] = NULL; list_for_each_entry(vpgd, &vm->pgd_list, head) { - vm->map_pgt(vpgd->obj, pde, vpgt->obj); + vmm->map_pgt(vpgd->obj, pde, vpgt->obj); } mutex_unlock(&vm->mm.mutex); @@ -239,18 +245,19 @@ nouveau_vm_unmap_pgt(struct nouveau_vm *vm, int big, u32 fpde, u32 lpde) static int nouveau_vm_map_pgt(struct nouveau_vm *vm, u32 pde, u32 type) { + struct nouveau_vmmgr *vmm = vm->vmm; struct nouveau_vm_pgt *vpgt = &vm->pgt[pde - vm->fpde]; struct nouveau_vm_pgd *vpgd; struct nouveau_gpuobj *pgt; - int big = (type != vm->spg_shift); + int big = (type != vmm->spg_shift); u32 pgt_size; int ret; - pgt_size = (1 << (vm->pgt_bits + 12)) >> type; + pgt_size = (1 << (vmm->pgt_bits + 12)) >> type; pgt_size *= 8; mutex_unlock(&vm->mm.mutex); - ret = nouveau_gpuobj_new(vm->dev, NULL, pgt_size, 0x1000, + ret = nouveau_gpuobj_new(nv_object(vm->vmm), NULL, pgt_size, 0x1000, NVOBJ_FLAG_ZERO_ALLOC, &pgt); mutex_lock(&vm->mm.mutex); if (unlikely(ret)) @@ -266,7 +273,7 @@ nouveau_vm_map_pgt(struct nouveau_vm *vm, u32 pde, u32 type) vpgt->obj[big] = pgt; list_for_each_entry(vpgd, &vm->pgd_list, head) { - vm->map_pgt(vpgd->obj, pde, vpgt->obj); + vmm->map_pgt(vpgd->obj, pde, vpgt->obj); } return 0; @@ -276,6 +283,7 @@ int nouveau_vm_get(struct nouveau_vm *vm, u64 size, u32 page_shift, u32 access, struct nouveau_vma *vma) { + struct nouveau_vmmgr *vmm = vm->vmm; u32 align = (1 << page_shift) >> 12; u32 msize = size >> 12; u32 fpde, lpde, pde; @@ -289,11 +297,11 @@ nouveau_vm_get(struct nouveau_vm *vm, u64 size, u32 page_shift, return ret; } - fpde = (vma->node->offset >> vm->pgt_bits); - lpde = (vma->node->offset + vma->node->length - 1) >> vm->pgt_bits; + fpde = (vma->node->offset >> vmm->pgt_bits); + lpde = (vma->node->offset + vma->node->length - 1) >> vmm->pgt_bits; for (pde = fpde; pde <= lpde; pde++) { struct nouveau_vm_pgt *vpgt = &vm->pgt[pde - vm->fpde]; - int big = (vma->node->type != vm->spg_shift); + int big = (vma->node->type != vmm->spg_shift); if (likely(vpgt->refcount[big])) { vpgt->refcount[big]++; @@ -321,90 +329,67 @@ void nouveau_vm_put(struct nouveau_vma *vma) { struct nouveau_vm *vm = vma->vm; + struct nouveau_vmmgr *vmm = vm->vmm; u32 fpde, lpde; if (unlikely(vma->node == NULL)) return; - fpde = (vma->node->offset >> vm->pgt_bits); - lpde = (vma->node->offset + vma->node->length - 1) >> vm->pgt_bits; + fpde = (vma->node->offset >> vmm->pgt_bits); + lpde = (vma->node->offset + vma->node->length - 1) >> vmm->pgt_bits; mutex_lock(&vm->mm.mutex); - nouveau_vm_unmap_pgt(vm, vma->node->type != vm->spg_shift, fpde, lpde); + nouveau_vm_unmap_pgt(vm, vma->node->type != vmm->spg_shift, fpde, lpde); nouveau_mm_free(&vm->mm, &vma->node); mutex_unlock(&vm->mm.mutex); } int -nouveau_vm_new(struct drm_device *dev, u64 offset, u64 length, u64 mm_offset, - struct nouveau_vm **pvm) +nouveau_vm_create(struct nouveau_vmmgr *vmm, u64 offset, u64 length, + u64 mm_offset, u32 block, struct nouveau_vm **pvm) { - struct drm_nouveau_private *dev_priv = dev->dev_private; struct nouveau_vm *vm; u64 mm_length = (offset + length) - mm_offset; - u32 block, pgt_bits; int ret; - vm = kzalloc(sizeof(*vm), GFP_KERNEL); + vm = *pvm = kzalloc(sizeof(*vm), GFP_KERNEL); if (!vm) return -ENOMEM; - if (dev_priv->card_type == NV_50) { - vm->map_pgt = nv50_vm_map_pgt; - vm->map = nv50_vm_map; - vm->map_sg = nv50_vm_map_sg; - vm->unmap = nv50_vm_unmap; - vm->flush = nv50_vm_flush; - vm->spg_shift = 12; - vm->lpg_shift = 16; - - pgt_bits = 29; - block = (1 << pgt_bits); - if (length < block) - block = length; - - } else - if (dev_priv->card_type >= NV_C0) { - vm->map_pgt = nvc0_vm_map_pgt; - vm->map = nvc0_vm_map; - vm->map_sg = nvc0_vm_map_sg; - vm->unmap = nvc0_vm_unmap; - vm->flush = nvc0_vm_flush; - vm->spg_shift = 12; - vm->lpg_shift = 17; - pgt_bits = 27; - block = 4096; - } else { - kfree(vm); - return -ENOSYS; - } + INIT_LIST_HEAD(&vm->pgd_list); + vm->vmm = vmm; + vm->refcount = 1; + vm->fpde = offset >> (vmm->pgt_bits + 12); + vm->lpde = (offset + length - 1) >> (vmm->pgt_bits + 12); - vm->fpde = offset >> pgt_bits; - vm->lpde = (offset + length - 1) >> pgt_bits; - vm->pgt = kcalloc(vm->lpde - vm->fpde + 1, sizeof(*vm->pgt), GFP_KERNEL); + vm->pgt = kcalloc(vm->lpde - vm->fpde + 1, sizeof(*vm->pgt), GFP_KERNEL); if (!vm->pgt) { kfree(vm); return -ENOMEM; } - INIT_LIST_HEAD(&vm->pgd_list); - vm->dev = dev; - vm->refcount = 1; - vm->pgt_bits = pgt_bits - 12; - ret = nouveau_mm_init(&vm->mm, mm_offset >> 12, mm_length >> 12, block >> 12); if (ret) { + kfree(vm->pgt); kfree(vm); return ret; } - *pvm = vm; return 0; } +int +nouveau_vm_new(struct nouveau_device *device, u64 offset, u64 length, + u64 mm_offset, struct nouveau_vm **pvm) +{ + struct nouveau_vmmgr *vmm = nouveau_vmmgr(device); + return vmm->create(vmm, offset, length, mm_offset, pvm); +} + static int nouveau_vm_link(struct nouveau_vm *vm, struct nouveau_gpuobj *pgd) { + struct nouveau_vmmgr *vmm = vm->vmm; struct nouveau_vm_pgd *vpgd; int i; @@ -419,7 +404,7 @@ nouveau_vm_link(struct nouveau_vm *vm, struct nouveau_gpuobj *pgd) mutex_lock(&vm->mm.mutex); for (i = vm->fpde; i <= vm->lpde; i++) - vm->map_pgt(pgd, i, vm->pgt[i - vm->fpde].obj); + vmm->map_pgt(pgd, i, vm->pgt[i - vm->fpde].obj); list_add(&vpgd->head, &vm->pgd_list); mutex_unlock(&vm->mm.mutex); return 0; diff --git a/drivers/gpu/drm/nouveau/core/subdev/vm/nv04.c b/drivers/gpu/drm/nouveau/core/subdev/vm/nv04.c new file mode 100644 index 000000000000..6475c0201d01 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/subdev/vm/nv04.c @@ -0,0 +1,150 @@ +/* + * 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 "nv04.h" + +#define NV04_PDMA_SIZE (128 * 1024 * 1024) +#define NV04_PDMA_PAGE ( 4 * 1024) + +/******************************************************************************* + * VM map/unmap callbacks + ******************************************************************************/ + +static void +nv04_vm_map_sg(struct nouveau_vma *vma, struct nouveau_gpuobj *pgt, + struct nouveau_mem *mem, u32 pte, u32 cnt, dma_addr_t *list) +{ + pte = 0x00008 + (pte * 4); + while (cnt) { + u32 page = PAGE_SIZE / NV04_PDMA_PAGE; + u32 phys = (u32)*list++; + while (cnt && page--) { + nv_wo32(pgt, pte, phys | 3); + phys += NV04_PDMA_PAGE; + pte += 4; + cnt -= 1; + } + } +} + +static void +nv04_vm_unmap(struct nouveau_gpuobj *pgt, u32 pte, u32 cnt) +{ + pte = 0x00008 + (pte * 4); + while (cnt--) { + nv_wo32(pgt, pte, 0x00000000); + pte += 4; + } +} + +static void +nv04_vm_flush(struct nouveau_vm *vm) +{ +} + +/******************************************************************************* + * VM object + ******************************************************************************/ + +int +nv04_vm_create(struct nouveau_vmmgr *vmm, u64 offset, u64 length, u64 mmstart, + struct nouveau_vm **pvm) +{ + return -EINVAL; +} + +/******************************************************************************* + * VMMGR subdev + ******************************************************************************/ + +static int +nv04_vmmgr_ctor(struct nouveau_object *parent, struct nouveau_object *engine, + struct nouveau_oclass *oclass, void *data, u32 size, + struct nouveau_object **pobject) +{ + struct nv04_vmmgr_priv *priv; + struct nouveau_gpuobj *dma; + int ret; + + ret = nouveau_vmmgr_create(parent, engine, oclass, "PCIGART", + "pcigart", &priv); + *pobject = nv_object(priv); + if (ret) + return ret; + + priv->base.create = nv04_vm_create; + priv->base.pgt_bits = 32 - 12; + priv->base.spg_shift = 12; + priv->base.lpg_shift = 12; + priv->base.map_sg = nv04_vm_map_sg; + priv->base.unmap = nv04_vm_unmap; + priv->base.flush = nv04_vm_flush; + + ret = nouveau_vm_create(&priv->base, 0, NV04_PDMA_SIZE, 0, 4096, + &priv->vm); + if (ret) + return ret; + + ret = nouveau_gpuobj_new(parent, NULL, + (NV04_PDMA_SIZE / NV04_PDMA_PAGE) * 4 + + 8, 16, NVOBJ_FLAG_ZERO_ALLOC, + &priv->vm->pgt[0].obj[0]); + dma = priv->vm->pgt[0].obj[0]; + priv->vm->pgt[0].refcount[0] = 1; + if (ret) + return ret; + + nv_wo32(dma, 0x00000, 0x0002103d); /* PCI, RW, PT, !LN */ + nv_wo32(dma, 0x00004, NV04_PDMA_SIZE - 1); + return 0; +} + +void +nv04_vmmgr_dtor(struct nouveau_object *object) +{ + struct nv04_vmmgr_priv *priv = (void *)object; + if (priv->vm) { + nouveau_gpuobj_ref(NULL, &priv->vm->pgt[0].obj[0]); + nouveau_vm_ref(NULL, &priv->vm, NULL); + } + if (priv->page) { + pci_unmap_page(nv_device(priv)->pdev, priv->null, + PAGE_SIZE, PCI_DMA_BIDIRECTIONAL); + __free_page(priv->page); + } + nouveau_vmmgr_destroy(&priv->base); +} + +struct nouveau_oclass +nv04_vmmgr_oclass = { + .handle = NV_SUBDEV(VM, 0x04), + .ofuncs = &(struct nouveau_ofuncs) { + .ctor = nv04_vmmgr_ctor, + .dtor = nv04_vmmgr_dtor, + .init = _nouveau_vmmgr_init, + .fini = _nouveau_vmmgr_fini, + }, +}; diff --git a/drivers/gpu/drm/nouveau/core/subdev/vm/nv04.h b/drivers/gpu/drm/nouveau/core/subdev/vm/nv04.h new file mode 100644 index 000000000000..530930320bc4 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/subdev/vm/nv04.h @@ -0,0 +1,13 @@ +#ifndef __NV04_VMMGR_PRIV__ +#define __NV04_VMMGR_PRIV__ + +#include + +struct nv04_vmmgr_priv { + struct nouveau_vmmgr base; + struct nouveau_vm *vm; + struct page *page; + dma_addr_t null; +}; + +#endif diff --git a/drivers/gpu/drm/nouveau/core/subdev/vm/nv41.c b/drivers/gpu/drm/nouveau/core/subdev/vm/nv41.c new file mode 100644 index 000000000000..f0367703dff0 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/subdev/vm/nv41.c @@ -0,0 +1,149 @@ +/* + * 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 "nv04.h" + +#define NV41_GART_SIZE (512 * 1024 * 1024) +#define NV41_GART_PAGE ( 4 * 1024) + +/******************************************************************************* + * VM map/unmap callbacks + ******************************************************************************/ + +static void +nv41_vm_map_sg(struct nouveau_vma *vma, struct nouveau_gpuobj *pgt, + struct nouveau_mem *mem, u32 pte, u32 cnt, dma_addr_t *list) +{ + pte = pte * 4; + while (cnt) { + u32 page = PAGE_SIZE / NV41_GART_PAGE; + u64 phys = (u64)*list++; + while (cnt && page--) { + nv_wo32(pgt, pte, (phys >> 7) | 1); + phys += NV41_GART_PAGE; + pte += 4; + cnt -= 1; + } + } +} + +static void +nv41_vm_unmap(struct nouveau_gpuobj *pgt, u32 pte, u32 cnt) +{ + pte = pte * 4; + while (cnt--) { + nv_wo32(pgt, pte, 0x00000000); + pte += 4; + } +} + +static void +nv41_vm_flush(struct nouveau_vm *vm) +{ + struct nv04_vm_priv *priv = (void *)vm->vmm; + + mutex_lock(&nv_subdev(priv)->mutex); + nv_wr32(priv, 0x100810, 0x00000022); + if (!nv_wait(priv, 0x100810, 0x00000100, 0x00000100)) { + nv_warn(priv, "flush timeout, 0x%08x\n", + nv_rd32(priv, 0x100810)); + } + nv_wr32(priv, 0x100810, 0x00000000); + mutex_unlock(&nv_subdev(priv)->mutex); +} + +/******************************************************************************* + * VMMGR subdev + ******************************************************************************/ + +static int +nv41_vmmgr_ctor(struct nouveau_object *parent, struct nouveau_object *engine, + struct nouveau_oclass *oclass, void *data, u32 size, + struct nouveau_object **pobject) +{ + struct nv04_vmmgr_priv *priv; + int ret; + + ret = nouveau_vmmgr_create(parent, engine, oclass, "PCIEGART", + "pciegart", &priv); + *pobject = nv_object(priv); + if (ret) + return ret; + + priv->base.create = nv04_vm_create; + priv->base.pgt_bits = 32 - 12; + priv->base.spg_shift = 12; + priv->base.lpg_shift = 12; + priv->base.map_sg = nv41_vm_map_sg; + priv->base.unmap = nv41_vm_unmap; + priv->base.flush = nv41_vm_flush; + + ret = nouveau_vm_create(&priv->base, 0, NV41_GART_SIZE, 0, 4096, + &priv->vm); + if (ret) + return ret; + + ret = nouveau_gpuobj_new(parent, NULL, + (NV41_GART_SIZE / NV41_GART_PAGE) * 4, + 16, NVOBJ_FLAG_ZERO_ALLOC, + &priv->vm->pgt[0].obj[0]); + priv->vm->pgt[0].refcount[0] = 1; + if (ret) + return ret; + + return 0; +} + +static int +nv41_vmmgr_init(struct nouveau_object *object) +{ + struct nv04_vmmgr_priv *priv = (void *)object; + struct nouveau_gpuobj *dma = priv->vm->pgt[0].obj[0]; + int ret; + + ret = nouveau_vmmgr_init(&priv->base); + if (ret) + return ret; + + nv_wr32(priv, 0x100800, dma->addr | 0x00000002); + nv_mask(priv, 0x10008c, 0x00000100, 0x00000100); + nv_wr32(priv, 0x100820, 0x00000000); + return 0; +} + +struct nouveau_oclass +nv41_vmmgr_oclass = { + .handle = NV_SUBDEV(VM, 0x41), + .ofuncs = &(struct nouveau_ofuncs) { + .ctor = nv41_vmmgr_ctor, + .dtor = nv04_vmmgr_dtor, + .init = nv41_vmmgr_init, + .fini = _nouveau_vmmgr_fini, + }, +}; diff --git a/drivers/gpu/drm/nouveau/core/subdev/vm/nv44.c b/drivers/gpu/drm/nouveau/core/subdev/vm/nv44.c new file mode 100644 index 000000000000..d17f76120bcd --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/subdev/vm/nv44.c @@ -0,0 +1,257 @@ +/* + * 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 "nv04.h" + +#define NV44_GART_SIZE (512 * 1024 * 1024) +#define NV44_GART_PAGE ( 4 * 1024) + +/******************************************************************************* + * VM map/unmap callbacks + ******************************************************************************/ + +static void +nv44_vm_flush_priv(struct nv04_vmmgr_priv *priv, u32 base, u32 size) +{ + nv_wr32(priv, 0x100814, (size - 1) << 12); + nv_wr32(priv, 0x100808, base | 0x20); + if (!nv_wait(priv, 0x100808, 0x00000001, 0x00000001)) + nv_error(priv, "timeout: 0x%08x\n", nv_rd32(priv, 0x100808)); + nv_wr32(priv, 0x100808, 0x00000000); +} + +static void +nv44_vm_fill(struct nouveau_gpuobj *pgt, dma_addr_t null, + dma_addr_t *list, u32 pte, u32 cnt) +{ + u32 base = (pte << 2) & ~0x0000000f; + u32 tmp[4]; + + tmp[0] = nv_ro32(pgt, base + 0x0); + tmp[1] = nv_ro32(pgt, base + 0x4); + tmp[2] = nv_ro32(pgt, base + 0x8); + tmp[3] = nv_ro32(pgt, base + 0xc); + while (cnt--) { + u32 addr = list ? (*list++ >> 12) : (null >> 12); + switch (pte++ & 0x3) { + case 0: + tmp[0] &= ~0x07ffffff; + tmp[0] |= addr; + break; + case 1: + tmp[0] &= ~0xf8000000; + tmp[0] |= addr << 27; + tmp[1] &= ~0x003fffff; + tmp[1] |= addr >> 5; + break; + case 2: + tmp[1] &= ~0xffc00000; + tmp[1] |= addr << 22; + tmp[2] &= ~0x0001ffff; + tmp[2] |= addr >> 10; + break; + case 3: + tmp[2] &= ~0xfffe0000; + tmp[2] |= addr << 17; + tmp[3] &= ~0x00000fff; + tmp[3] |= addr >> 15; + break; + } + } + + nv_wo32(pgt, base + 0x0, tmp[0]); + nv_wo32(pgt, base + 0x4, tmp[1]); + nv_wo32(pgt, base + 0x8, tmp[2]); + nv_wo32(pgt, base + 0xc, tmp[3] | 0x40000000); +} + +static void +nv44_vm_map_sg(struct nouveau_vma *vma, struct nouveau_gpuobj *pgt, + struct nouveau_mem *mem, u32 pte, u32 cnt, dma_addr_t *list) +{ + struct nv04_vmmgr_priv *priv = (void *)vma->vm->vmm; + u32 base = pte << 12; + u32 size = cnt; + u32 tmp[4]; + int i; + + if (pte & 3) { + u32 max = 4 - (pte & 3); + u32 part = (cnt > max) ? max : cnt; + nv44_vm_fill(pgt, priv->null, list, pte, part); + pte += part; + list += part; + cnt -= part; + } + + while (cnt >= 4) { + for (i = 0; i < 4; i++) + tmp[i] = *list++ >> 12; + nv_wo32(pgt, pte++ * 4, tmp[0] >> 0 | tmp[1] << 27); + nv_wo32(pgt, pte++ * 4, tmp[1] >> 5 | tmp[2] << 22); + nv_wo32(pgt, pte++ * 4, tmp[2] >> 10 | tmp[3] << 17); + nv_wo32(pgt, pte++ * 4, tmp[3] >> 15 | 0x40000000); + cnt -= 4; + } + + if (cnt) + nv44_vm_fill(pgt, priv->null, list, pte, cnt); + nv44_vm_flush_priv(priv, base, size); +} + +static void +nv44_vm_unmap(struct nouveau_gpuobj *pgt, u32 pte, u32 cnt) +{ + struct nv04_vmmgr_priv *priv = (void *)nouveau_vmmgr(pgt); + u32 base = pte << 12; + u32 size = cnt; + + if (pte & 3) { + u32 max = 4 - (pte & 3); + u32 part = (cnt > max) ? max : cnt; + nv44_vm_fill(pgt, priv->null, NULL, pte, part); + pte += part; + cnt -= part; + } + + while (cnt >= 4) { + nv_wo32(pgt, pte++ * 4, 0x00000000); + nv_wo32(pgt, pte++ * 4, 0x00000000); + nv_wo32(pgt, pte++ * 4, 0x00000000); + nv_wo32(pgt, pte++ * 4, 0x00000000); + cnt -= 4; + } + + if (cnt) + nv44_vm_fill(pgt, priv->null, NULL, pte, cnt); + nv44_vm_flush_priv(priv, base, size); +} + +static void +nv44_vm_flush(struct nouveau_vm *vm) +{ +} + +/******************************************************************************* + * VMMGR subdev + ******************************************************************************/ + +static int +nv44_vmmgr_ctor(struct nouveau_object *parent, struct nouveau_object *engine, + struct nouveau_oclass *oclass, void *data, u32 size, + struct nouveau_object **pobject) +{ + struct nouveau_device *device = nv_device(parent); + struct nv04_vmmgr_priv *priv; + int ret; + + ret = nouveau_vmmgr_create(parent, engine, oclass, "PCIEGART", + "pciegart", &priv); + *pobject = nv_object(priv); + if (ret) + return ret; + + priv->base.create = nv04_vm_create; + priv->base.pgt_bits = 32 - 12; + priv->base.spg_shift = 12; + priv->base.lpg_shift = 12; + priv->base.map_sg = nv44_vm_map_sg; + priv->base.unmap = nv44_vm_unmap; + priv->base.flush = nv44_vm_flush; + + priv->page = alloc_page(GFP_DMA32 | GFP_KERNEL); + if (priv->page) { + priv->null = pci_map_page(device->pdev, priv->page, 0, + PAGE_SIZE, PCI_DMA_BIDIRECTIONAL); + if (pci_dma_mapping_error(device->pdev, priv->null)) { + __free_page(priv->page); + priv->page = NULL; + priv->null = 0; + } + } + + if (!priv->page) + nv_warn(priv, "unable to allocate dummy page\n"); + + ret = nouveau_vm_create(&priv->base, 0, NV44_GART_SIZE, 0, 4096, + &priv->vm); + if (ret) + return ret; + + ret = nouveau_gpuobj_new(parent, NULL, + (NV44_GART_SIZE / NV44_GART_PAGE) * 4, + 512 * 1024, NVOBJ_FLAG_ZERO_ALLOC, + &priv->vm->pgt[0].obj[0]); + priv->vm->pgt[0].refcount[0] = 1; + if (ret) + return ret; + + return 0; +} + +static int +nv44_vmmgr_init(struct nouveau_object *object) +{ + struct nv04_vmmgr_priv *priv = (void *)object; + struct nouveau_gpuobj *gart = priv->vm->pgt[0].obj[0]; + u32 addr; + int ret; + + ret = nouveau_vmmgr_init(&priv->base); + if (ret) + return ret; + + /* calculate vram address of this PRAMIN block, object must be + * allocated on 512KiB alignment, and not exceed a total size + * of 512KiB for this to work correctly + */ + addr = nv_rd32(priv, 0x10020c); + addr -= ((gart->addr >> 19) + 1) << 19; + + nv_wr32(priv, 0x100850, 0x80000000); + nv_wr32(priv, 0x100818, priv->null); + nv_wr32(priv, 0x100804, NV44_GART_SIZE); + nv_wr32(priv, 0x100850, 0x00008000); + nv_mask(priv, 0x10008c, 0x00000200, 0x00000200); + nv_wr32(priv, 0x100820, 0x00000000); + nv_wr32(priv, 0x10082c, 0x00000001); + nv_wr32(priv, 0x100800, addr | 0x00000010); + return 0; +} + +struct nouveau_oclass +nv44_vmmgr_oclass = { + .handle = NV_SUBDEV(VM, 0x44), + .ofuncs = &(struct nouveau_ofuncs) { + .ctor = nv44_vmmgr_ctor, + .dtor = nv04_vmmgr_dtor, + .init = nv44_vmmgr_init, + .fini = _nouveau_vmmgr_fini, + }, +}; diff --git a/drivers/gpu/drm/nouveau/core/subdev/vm/nv50.c b/drivers/gpu/drm/nouveau/core/subdev/vm/nv50.c index 7e46826de0e9..6e9bcd212cfc 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/vm/nv50.c +++ b/drivers/gpu/drm/nouveau/core/subdev/vm/nv50.c @@ -22,11 +22,18 @@ * Authors: Ben Skeggs */ -#include "drmP.h" +#include +#include -#include "nouveau_drv.h" +#include +#include #include +struct nv50_vmmgr_priv { + struct nouveau_vmmgr base; + spinlock_t lock; +}; + void nv50_vm_map_pgt(struct nouveau_gpuobj *pgd, u32 pde, struct nouveau_gpuobj *pgt[2]) @@ -35,11 +42,11 @@ nv50_vm_map_pgt(struct nouveau_gpuobj *pgd, u32 pde, u32 coverage = 0; if (pgt[0]) { - phys = 0x00000003 | pgt[0]->vinst; /* present, 4KiB pages */ + phys = 0x00000003 | pgt[0]->addr; /* present, 4KiB pages */ coverage = (pgt[0]->size >> 3) << 12; } else if (pgt[1]) { - phys = 0x00000001 | pgt[1]->vinst; /* present */ + phys = 0x00000001 | pgt[1]->addr; /* present */ coverage = (pgt[1]->size >> 3) << 16; } @@ -73,15 +80,14 @@ void nv50_vm_map(struct nouveau_vma *vma, struct nouveau_gpuobj *pgt, struct nouveau_mem *mem, u32 pte, u32 cnt, u64 phys, u64 delta) { - struct drm_nouveau_private *dev_priv = vma->vm->dev->dev_private; u32 comp = (mem->memtype & 0x180) >> 7; u32 block, target; int i; /* IGPs don't have real VRAM, re-target to stolen system memory */ target = 0; - if (nvfb_vram_sys_base(dev_priv->dev)) { - phys += nvfb_vram_sys_base(dev_priv->dev); + if (nouveau_fb(vma->vm->vmm)->ram.stolen) { + phys += nouveau_fb(vma->vm->vmm)->ram.stolen; target = 3; } @@ -145,33 +151,81 @@ nv50_vm_unmap(struct nouveau_gpuobj *pgt, u32 pte, u32 cnt) void nv50_vm_flush(struct nouveau_vm *vm) { - struct drm_nouveau_private *dev_priv = vm->dev->dev_private; - struct nouveau_instmem_engine *pinstmem = &dev_priv->engine.instmem; + struct nouveau_engine *engine; int i; - pinstmem->flush(vm->dev); - - /* BAR */ - if (vm == dev_priv->bar1_vm || vm == dev_priv->bar3_vm) { - nv50_vm_flush_engine(vm->dev, 6); - return; - } - - for (i = 0; i < NVOBJ_ENGINE_NR; i++) { - if (atomic_read(&vm->engref[i])) - dev_priv->eng[i]->tlb_flush(vm->dev, i); +#if 0 + for (i = 0; i < NVDEV_SUBDEV_NR; i++) { + if (atomic_read(&vm->engref[i])) { + engine = nouveau_engine(vm->vmm, i); + if (engine && engine->tlb_flush) + engine->tlb_flush(engine); + } } +#else + nv50_vm_flush_engine(nv_subdev(vm->vmm), 0x06); /* bar */ + nv50_vm_flush_engine(nv_subdev(vm->vmm), 0x05); /* fifo */ + nv50_vm_flush_engine(nv_subdev(vm->vmm), 0x00); /* gr */ +#endif } void -nv50_vm_flush_engine(struct drm_device *dev, int engine) +nv50_vm_flush_engine(struct nouveau_subdev *subdev, int engine) { - struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nv50_vmmgr_priv *priv = (void *)nouveau_vmmgr(subdev); unsigned long flags; - spin_lock_irqsave(&dev_priv->vm_lock, flags); - nv_wr32(dev, 0x100c80, (engine << 16) | 1); - if (!nv_wait(dev, 0x100c80, 0x00000001, 0x00000000)) - NV_ERROR(dev, "vm flush timeout: engine %d\n", engine); - spin_unlock_irqrestore(&dev_priv->vm_lock, flags); + spin_lock_irqsave(&priv->lock, flags); + nv_wr32(subdev, 0x100c80, (engine << 16) | 1); + if (!nv_wait(subdev, 0x100c80, 0x00000001, 0x00000000)) + nv_error(subdev, "vm flush timeout: engine %d\n", engine); + spin_unlock_irqrestore(&priv->lock, flags); } + +static int +nv50_vm_create(struct nouveau_vmmgr *vmm, u64 offset, u64 length, + u64 mm_offset, struct nouveau_vm **pvm) +{ + u32 block = (1 << (vmm->pgt_bits + 12)); + if (block > length) + block = length; + + return nouveau_vm_create(vmm, offset, length, mm_offset, block, pvm); +} + +static int +nv50_vmmgr_ctor(struct nouveau_object *parent, struct nouveau_object *engine, + struct nouveau_oclass *oclass, void *data, u32 size, + struct nouveau_object **pobject) +{ + struct nv50_vmmgr_priv *priv; + int ret; + + ret = nouveau_vmmgr_create(parent, engine, oclass, "VM", "vm", &priv); + *pobject = nv_object(priv); + if (ret) + return ret; + + priv->base.pgt_bits = 29 - 12; + priv->base.spg_shift = 12; + priv->base.lpg_shift = 16; + priv->base.create = nv50_vm_create; + priv->base.map_pgt = nv50_vm_map_pgt; + priv->base.map = nv50_vm_map; + priv->base.map_sg = nv50_vm_map_sg; + priv->base.unmap = nv50_vm_unmap; + priv->base.flush = nv50_vm_flush; + spin_lock_init(&priv->lock); + return 0; +} + +struct nouveau_oclass +nv50_vmmgr_oclass = { + .handle = NV_SUBDEV(VM, 0x50), + .ofuncs = &(struct nouveau_ofuncs) { + .ctor = nv50_vmmgr_ctor, + .dtor = _nouveau_vmmgr_dtor, + .init = _nouveau_vmmgr_init, + .fini = _nouveau_vmmgr_fini, + }, +}; diff --git a/drivers/gpu/drm/nouveau/core/subdev/vm/nvc0.c b/drivers/gpu/drm/nouveau/core/subdev/vm/nvc0.c index 734877a9aa09..a0bc0f678d12 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/vm/nvc0.c +++ b/drivers/gpu/drm/nouveau/core/subdev/vm/nvc0.c @@ -22,11 +22,18 @@ * Authors: Ben Skeggs */ -#include "drmP.h" +#include +#include -#include "nouveau_drv.h" +#include +#include #include +struct nvc0_vmmgr_priv { + struct nouveau_vmmgr base; + spinlock_t lock; +}; + void nvc0_vm_map_pgt(struct nouveau_gpuobj *pgd, u32 index, struct nouveau_gpuobj *pgt[2]) @@ -34,9 +41,9 @@ nvc0_vm_map_pgt(struct nouveau_gpuobj *pgd, u32 index, u32 pde[2] = { 0, 0 }; if (pgt[0]) - pde[1] = 0x00000001 | (pgt[0]->vinst >> 8); + pde[1] = 0x00000001 | (pgt[0]->addr >> 8); if (pgt[1]) - pde[0] = 0x00000001 | (pgt[1]->vinst >> 8); + pde[0] = 0x00000001 | (pgt[1]->addr >> 8); nv_wo32(pgd, (index * 8) + 0, pde[0]); nv_wo32(pgd, (index * 8) + 4, pde[1]); @@ -100,37 +107,81 @@ nvc0_vm_unmap(struct nouveau_gpuobj *pgt, u32 pte, u32 cnt) } void -nvc0_vm_flush(struct nouveau_vm *vm) +nvc0_vm_flush_engine(struct nouveau_subdev *subdev, u64 addr, int type) { - struct drm_nouveau_private *dev_priv = vm->dev->dev_private; - struct nouveau_instmem_engine *pinstmem = &dev_priv->engine.instmem; - struct drm_device *dev = vm->dev; - struct nouveau_vm_pgd *vpgd; + struct nvc0_vmmgr_priv *priv = (void *)nouveau_vmmgr(subdev); unsigned long flags; - u32 engine; - engine = 1; - if (vm == dev_priv->bar1_vm || vm == dev_priv->bar3_vm) - engine |= 4; + /* looks like maybe a "free flush slots" counter, the + * faster you write to 0x100cbc to more it decreases + */ + spin_lock_irqsave(&priv->lock, flags); + if (!nv_wait_ne(subdev, 0x100c80, 0x00ff0000, 0x00000000)) { + nv_error(subdev, "vm timeout 0: 0x%08x %d\n", + nv_rd32(subdev, 0x100c80), type); + } + + nv_wr32(subdev, 0x100cb8, addr >> 8); + nv_wr32(subdev, 0x100cbc, 0x80000000 | type); - pinstmem->flush(vm->dev); + /* wait for flush to be queued? */ + if (!nv_wait(subdev, 0x100c80, 0x00008000, 0x00008000)) { + nv_error(subdev, "vm timeout 1: 0x%08x %d\n", + nv_rd32(subdev, 0x100c80), type); + } + spin_unlock_irqrestore(&priv->lock, flags); +} + +void +nvc0_vm_flush(struct nouveau_vm *vm) +{ + struct nouveau_vm_pgd *vpgd; - spin_lock_irqsave(&dev_priv->vm_lock, flags); list_for_each_entry(vpgd, &vm->pgd_list, head) { - /* looks like maybe a "free flush slots" counter, the - * faster you write to 0x100cbc to more it decreases - */ - if (!nv_wait_ne(dev, 0x100c80, 0x00ff0000, 0x00000000)) { - NV_ERROR(dev, "vm timeout 0: 0x%08x %d\n", - nv_rd32(dev, 0x100c80), engine); - } - nv_wr32(dev, 0x100cb8, vpgd->obj->vinst >> 8); - nv_wr32(dev, 0x100cbc, 0x80000000 | engine); - /* wait for flush to be queued? */ - if (!nv_wait(dev, 0x100c80, 0x00008000, 0x00008000)) { - NV_ERROR(dev, "vm timeout 1: 0x%08x %d\n", - nv_rd32(dev, 0x100c80), engine); - } + nvc0_vm_flush_engine(nv_subdev(vm->vmm), vpgd->obj->addr, 1); } - spin_unlock_irqrestore(&dev_priv->vm_lock, flags); } + +static int +nvc0_vm_create(struct nouveau_vmmgr *vmm, u64 offset, u64 length, + u64 mm_offset, struct nouveau_vm **pvm) +{ + return nouveau_vm_create(vmm, offset, length, mm_offset, 4096, pvm); +} + +static int +nvc0_vmmgr_ctor(struct nouveau_object *parent, struct nouveau_object *engine, + struct nouveau_oclass *oclass, void *data, u32 size, + struct nouveau_object **pobject) +{ + struct nvc0_vmmgr_priv *priv; + int ret; + + ret = nouveau_vmmgr_create(parent, engine, oclass, "VM", "vm", &priv); + *pobject = nv_object(priv); + if (ret) + return ret; + + priv->base.pgt_bits = 27 - 12; + priv->base.spg_shift = 12; + priv->base.lpg_shift = 17; + priv->base.create = nvc0_vm_create; + priv->base.map_pgt = nvc0_vm_map_pgt; + priv->base.map = nvc0_vm_map; + priv->base.map_sg = nvc0_vm_map_sg; + priv->base.unmap = nvc0_vm_unmap; + priv->base.flush = nvc0_vm_flush; + spin_lock_init(&priv->lock); + return 0; +} + +struct nouveau_oclass +nvc0_vmmgr_oclass = { + .handle = NV_SUBDEV(VM, 0xc0), + .ofuncs = &(struct nouveau_ofuncs) { + .ctor = nvc0_vmmgr_ctor, + .dtor = _nouveau_vmmgr_dtor, + .init = _nouveau_vmmgr_init, + .fini = _nouveau_vmmgr_fini, + }, +}; diff --git a/drivers/gpu/drm/nouveau/nouveau_bo.c b/drivers/gpu/drm/nouveau/nouveau_bo.c index f63785c2aae0..9f5696a1fbb8 100644 --- a/drivers/gpu/drm/nouveau/nouveau_bo.c +++ b/drivers/gpu/drm/nouveau/nouveau_bo.c @@ -34,7 +34,6 @@ #include "nouveau_drv.h" #include "nouveau_dma.h" #include -#include #include "nouveau_fence.h" #include @@ -114,9 +113,9 @@ nouveau_bo_new(struct drm_device *dev, int size, int align, nvbo->bo.bdev = &dev_priv->ttm.bdev; nvbo->page_shift = 12; - if (dev_priv->bar1_vm) { + if (dev_priv->chan_vm) { if (!(flags & TTM_PL_FLAG_TT) && size > 256 * 1024) - nvbo->page_shift = dev_priv->bar1_vm->lpg_shift; + nvbo->page_shift = nvvm_lpg_shift(dev_priv->chan_vm); } nouveau_bo_fixup_align(nvbo, flags, &align, &size); @@ -419,6 +418,9 @@ nouveau_bo_init_mem_type(struct ttm_bo_device *bdev, uint32_t type, case TTM_PL_TT: if (dev_priv->card_type >= NV_50) man->func = &nouveau_gart_manager; + else + if (dev_priv->gart_info.type != NOUVEAU_GART_AGP) + man->func = &nv04_gart_manager; else man->func = &ttm_bo_manager_func; switch (dev_priv->gart_info.type) { @@ -1044,7 +1046,7 @@ nouveau_bo_move_ntfy(struct ttm_buffer_object *bo, struct ttm_mem_reg *new_mem) nouveau_vm_map(vma, new_mem->mm_node); } else if (new_mem && new_mem->mem_type == TTM_PL_TT && - nvbo->page_shift == vma->vm->spg_shift) { + nvbo->page_shift == nvvm_spg_shift(vma->vm)) { if (((struct nouveau_mem *)new_mem->mm_node)->sg) nouveau_vm_map_sg_table(vma, 0, new_mem-> num_pages << PAGE_SHIFT, @@ -1184,40 +1186,19 @@ nouveau_ttm_io_mem_reserve(struct ttm_bo_device *bdev, struct ttm_mem_reg *mem) #endif break; case TTM_PL_VRAM: - { - struct nouveau_mem *node = mem->mm_node; - u8 page_shift; - - if (!dev_priv->bar1_vm) { - mem->bus.offset = mem->start << PAGE_SHIFT; - mem->bus.base = pci_resource_start(dev->pdev, 1); - mem->bus.is_iomem = true; - break; - } - - if (dev_priv->card_type >= NV_C0) - page_shift = node->page_shift; - else - page_shift = 12; + mem->bus.offset = mem->start << PAGE_SHIFT; + mem->bus.base = pci_resource_start(dev->pdev, 1); + mem->bus.is_iomem = true; + if (dev_priv->card_type >= NV_50) { + struct nouveau_mem *node = mem->mm_node; - ret = nouveau_vm_get(dev_priv->bar1_vm, mem->bus.size, - page_shift, NV_MEM_ACCESS_RW, - &node->bar_vma); - if (ret) - return ret; + ret = nvbar_map(dev, node, NV_MEM_ACCESS_RW, + &node->bar_vma); + if (ret) + return ret; - nouveau_vm_map(&node->bar_vma, node); - if (ret) { - nouveau_vm_put(&node->bar_vma); - return ret; + mem->bus.offset = node->bar_vma.offset; } - - mem->bus.offset = node->bar_vma.offset; - if (dev_priv->card_type == NV_50) /*XXX*/ - mem->bus.offset -= 0x0020000000ULL; - mem->bus.base = pci_resource_start(dev->pdev, 1); - mem->bus.is_iomem = true; - } break; default: return -EINVAL; @@ -1231,14 +1212,13 @@ nouveau_ttm_io_mem_free(struct ttm_bo_device *bdev, struct ttm_mem_reg *mem) struct drm_nouveau_private *dev_priv = nouveau_bdev(bdev); struct nouveau_mem *node = mem->mm_node; - if (!dev_priv->bar1_vm || mem->mem_type != TTM_PL_VRAM) + if (mem->mem_type != TTM_PL_VRAM) return; if (!node->bar_vma.node) return; - nouveau_vm_unmap(&node->bar_vma); - nouveau_vm_put(&node->bar_vma); + nvbar_unmap(dev_priv->dev, &node->bar_vma); } static int diff --git a/drivers/gpu/drm/nouveau/nouveau_channel.c b/drivers/gpu/drm/nouveau/nouveau_channel.c index 1dd5232a6d75..b7c2423a2536 100644 --- a/drivers/gpu/drm/nouveau/nouveau_channel.c +++ b/drivers/gpu/drm/nouveau/nouveau_channel.c @@ -145,6 +145,9 @@ nouveau_channel_alloc(struct drm_device *dev, struct nouveau_channel **chan_ret, /* allocate hw channel id */ spin_lock_irqsave(&dev_priv->channels.lock, flags); for (chan->id = 0; chan->id < pfifo->channels; chan->id++) { + if ( dev_priv->card_type == NV_50 && chan->id == 0) + continue; + if (!dev_priv->channels.ptr[chan->id]) { nouveau_channel_ref(chan, &dev_priv->channels.ptr[chan->id]); break; diff --git a/drivers/gpu/drm/nouveau/nouveau_compat.c b/drivers/gpu/drm/nouveau/nouveau_compat.c index 3d65c1763311..0403f2b94fa6 100644 --- a/drivers/gpu/drm/nouveau/nouveau_compat.c +++ b/drivers/gpu/drm/nouveau/nouveau_compat.c @@ -11,6 +11,8 @@ #include #include #include +#include +#include void *nouveau_newpriv(struct drm_device *); @@ -438,3 +440,146 @@ 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; +} diff --git a/drivers/gpu/drm/nouveau/nouveau_compat.h b/drivers/gpu/drm/nouveau/nouveau_compat.h index d047a2046959..d691b2535c72 100644 --- a/drivers/gpu/drm/nouveau/nouveau_compat.h +++ b/drivers/gpu/drm/nouveau/nouveau_compat.h @@ -82,4 +82,46 @@ 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 *); + #endif diff --git a/drivers/gpu/drm/nouveau/nouveau_drv.c b/drivers/gpu/drm/nouveau/nouveau_drv.c index 3f660a94dd18..561bc00c4851 100644 --- a/drivers/gpu/drm/nouveau/nouveau_drv.c +++ b/drivers/gpu/drm/nouveau/nouveau_drv.c @@ -152,7 +152,6 @@ nouveau_pci_suspend(struct pci_dev *pdev, pm_message_t pm_state) { struct drm_device *dev = pci_get_drvdata(pdev); struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_instmem_engine *pinstmem = &dev_priv->engine.instmem; struct nouveau_fifo_priv *pfifo = nv_engine(dev, NVOBJ_ENGINE_FIFO); struct nouveau_channel *chan; struct drm_crtc *crtc; @@ -204,20 +203,6 @@ nouveau_pci_suspend(struct pci_dev *pdev, pm_message_t pm_state) } } - ret = pinstmem->suspend(dev); - if (ret) { - NV_ERROR(dev, "... failed: %d\n", ret); - goto out_abort; - } - - NV_INFO(dev, "Suspending GPU objects...\n"); - ret = nouveau_gpuobj_suspend(dev); - if (ret) { - NV_ERROR(dev, "... failed: %d\n", ret); - pinstmem->resume(dev); - goto out_abort; - } - return 0; out_abort: @@ -247,11 +232,7 @@ nouveau_pci_resume(struct pci_dev *pdev) if (ret) return ret; - NV_INFO(dev, "Restoring GPU objects...\n"); - nouveau_gpuobj_resume(dev); - NV_INFO(dev, "Reinitialising engines...\n"); - engine->instmem.resume(dev); for (i = 0; i < NVOBJ_ENGINE_NR; i++) { if (dev_priv->eng[i]) dev_priv->eng[i]->init(dev, i); diff --git a/drivers/gpu/drm/nouveau/nouveau_drv.h b/drivers/gpu/drm/nouveau/nouveau_drv.h index fad668793fae..f62732dd30ad 100644 --- a/drivers/gpu/drm/nouveau/nouveau_drv.h +++ b/drivers/gpu/drm/nouveau/nouveau_drv.h @@ -46,7 +46,9 @@ #include "ttm/ttm_module.h" #define XXX_THIS_IS_A_HACK +#include #include +#include enum blah { NV_MEM_TYPE_UNKNOWN = 0, @@ -83,11 +85,20 @@ nouveau_fpriv(struct drm_file *file_priv) struct nouveau_grctx; struct nouveau_mem; -#include #include #include "nouveau_compat.h" +#define nouveau_gpuobj_new(d,c,s,a,f,o) \ + _nouveau_gpuobj_new((d), (c) ? ((struct nouveau_channel *)(c))->ramin : 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)) + #define MAX_NUM_DCB_ENTRIES 16 #define NOUVEAU_MAX_CHANNEL_NR 4096 @@ -172,34 +183,6 @@ enum nouveau_flags { #define NVOBJ_ENGINE_NR 16 #define NVOBJ_ENGINE_DISPLAY (NVOBJ_ENGINE_NR + 0) /*XXX*/ -#define NVOBJ_FLAG_DONT_MAP (1 << 0) -#define NVOBJ_FLAG_ZERO_ALLOC (1 << 1) -#define NVOBJ_FLAG_ZERO_FREE (1 << 2) - -#define NVOBJ_CINST_GLOBAL 0xdeadbeef - -struct nouveau_gpuobj { - struct drm_device *dev; - struct kref refcount; - struct list_head list; - - void *node; - u32 *suspend; - - uint32_t flags; - - u32 size; - u32 pinst; /* PRAMIN BAR offset */ - u32 cinst; /* Channel offset */ - u64 vinst; /* VRAM address */ - - uint32_t engine; - uint32_t class; - - void (*dtor)(struct drm_device *, struct nouveau_gpuobj *); - void *priv; -}; - struct nouveau_page_flip_state { struct list_head head; struct drm_pending_vblank_event *event; @@ -259,7 +242,6 @@ struct nouveau_channel { /* Objects */ struct nouveau_gpuobj *ramin; /* Private instmem */ - struct drm_mm ramin_heap; /* Private PRAMIN heap */ struct nouveau_ramht *ramht; /* Hash table */ /* GPU object info for stuff used in-kernel (mm_enabled) */ @@ -301,23 +283,6 @@ struct nouveau_exec_engine { void (*tlb_flush)(struct drm_device *, int engine); }; -struct nouveau_instmem_engine { - void *priv; - - int (*init)(struct drm_device *dev); - void (*takedown)(struct drm_device *dev); - int (*suspend)(struct drm_device *dev); - void (*resume)(struct drm_device *dev); - - int (*get)(struct nouveau_gpuobj *, struct nouveau_channel *, - u32 size, u32 align); - void (*put)(struct nouveau_gpuobj *); - int (*map)(struct nouveau_gpuobj *); - void (*unmap)(struct nouveau_gpuobj *); - - void (*flush)(struct drm_device *); -}; - struct nouveau_display_engine { void *priv; int (*early_init)(struct drm_device *); @@ -499,7 +464,6 @@ struct nouveau_pm_engine { }; struct nouveau_engine { - struct nouveau_instmem_engine instmem; struct nouveau_display_engine display; struct nouveau_pm_engine pm; }; @@ -599,14 +563,7 @@ struct drm_nouveau_private { int flags; u32 crystal; - spinlock_t ramin_lock; - void __iomem *ramin; - u32 ramin_size; - u32 ramin_base; - bool ramin_available; - struct drm_mm ramin_heap; struct nouveau_exec_engine *eng[NVOBJ_ENGINE_NR]; - struct list_head gpuobj_list; struct list_head classes; struct nouveau_bo *vga_ram; @@ -648,8 +605,6 @@ struct drm_nouveau_private { /* RAMIN configuration, RAMFC, RAMHT and RAMRO offsets */ struct nouveau_ramht *ramht; - uint32_t ramin_rsvd_vram; - struct { enum { NOUVEAU_GART_NONE = 0, @@ -663,11 +618,6 @@ struct drm_nouveau_private { struct ttm_backend_func *func; - struct { - struct page *page; - dma_addr_t addr; - } dummy; - struct nouveau_gpuobj *sg_ctxdma; } gart_info; @@ -682,10 +632,6 @@ struct drm_nouveau_private { uint64_t fb_aper_free; int fb_mtrr; - /* BAR control (NV50-) */ - struct nouveau_vm *bar1_vm; - struct nouveau_vm *bar3_vm; - /* G8x/G9x virtual address space */ struct nouveau_vm *chan_vm; @@ -797,6 +743,7 @@ extern void nv10_mem_put_tile_region(struct drm_device *dev, struct nouveau_fence *fence); extern const struct ttm_mem_type_manager_func nouveau_vram_manager; extern const struct ttm_mem_type_manager_func nouveau_gart_manager; +extern const struct ttm_mem_type_manager_func nv04_gart_manager; /* nouveau_notifier.c */ extern int nouveau_notifier_init_channel(struct nouveau_channel *); @@ -844,11 +791,6 @@ extern int nouveau_channel_idle(struct nouveau_channel *chan); return ret; \ } while (0) -extern int nouveau_gpuobj_early_init(struct drm_device *); -extern int nouveau_gpuobj_init(struct drm_device *); -extern void nouveau_gpuobj_takedown(struct drm_device *); -extern int nouveau_gpuobj_suspend(struct drm_device *dev); -extern void nouveau_gpuobj_resume(struct drm_device *dev); extern int nouveau_gpuobj_class_new(struct drm_device *, u32 class, u32 eng); extern int nouveau_gpuobj_mthd_new(struct drm_device *, u32 class, u32 mthd, int (*exec)(struct nouveau_channel *, @@ -858,11 +800,6 @@ extern int nouveau_gpuobj_mthd_call2(struct drm_device *, int, u32, u32, u32); extern int nouveau_gpuobj_channel_init(struct nouveau_channel *, uint32_t vram_h, uint32_t tt_h); extern void nouveau_gpuobj_channel_takedown(struct nouveau_channel *); -extern int nouveau_gpuobj_new(struct drm_device *, struct nouveau_channel *, - uint32_t size, int align, uint32_t flags, - struct nouveau_gpuobj **); -extern void nouveau_gpuobj_ref(struct nouveau_gpuobj *, - struct nouveau_gpuobj **); extern int nouveau_gpuobj_dma_new(struct nouveau_channel *, int class, uint64_t offset, uint64_t size, int access, int target, struct nouveau_gpuobj **); @@ -874,11 +811,8 @@ extern void nv50_gpuobj_dma_init(struct nouveau_gpuobj *, u32 offset, int class, u64 base, u64 size, int target, int access, u32 type, u32 comp); - -int nouveau_gpuobj_map_vm(struct nouveau_gpuobj *gpuobj, u32 flags, - struct nouveau_vm *vm, struct nouveau_vma *vma); -int nouveau_gpuobj_map_bar(struct nouveau_gpuobj *gpuobj, u32 flags, - struct nouveau_vma *vma); +int nouveau_gpuobj_map_vm(struct nouveau_gpuobj *gpuobj, struct nouveau_vm *vm, + u32 flags, struct nouveau_vma *vma); void nouveau_gpuobj_unmap(struct nouveau_vma *vma); /* nouveau_irq.c */ @@ -1060,49 +994,6 @@ extern int nv84_vp_create(struct drm_device *dev); /* nv98_ppp.c */ extern int nv98_ppp_create(struct drm_device *dev); -/* nv04_instmem.c */ -extern int nv04_instmem_init(struct drm_device *); -extern void nv04_instmem_takedown(struct drm_device *); -extern int nv04_instmem_suspend(struct drm_device *); -extern void nv04_instmem_resume(struct drm_device *); -extern int nv04_instmem_get(struct nouveau_gpuobj *, struct nouveau_channel *, - u32 size, u32 align); -extern void nv04_instmem_put(struct nouveau_gpuobj *); -extern int nv04_instmem_map(struct nouveau_gpuobj *); -extern void nv04_instmem_unmap(struct nouveau_gpuobj *); -extern void nv04_instmem_flush(struct drm_device *); - -/* nv40_instmem.c */ -extern int nv40_instmem_init(struct drm_device *); -extern void nv40_instmem_takedown(struct drm_device *); -extern int nv40_instmem_suspend(struct drm_device *); -extern void nv40_instmem_resume(struct drm_device *); -extern int nv40_instmem_get(struct nouveau_gpuobj *, struct nouveau_channel *, - u32 size, u32 align); -extern void nv40_instmem_put(struct nouveau_gpuobj *); -extern int nv40_instmem_map(struct nouveau_gpuobj *); -extern void nv40_instmem_unmap(struct nouveau_gpuobj *); -extern void nv40_instmem_flush(struct drm_device *); - -/* nv50_instmem.c */ -extern int nv50_instmem_init(struct drm_device *); -extern void nv50_instmem_takedown(struct drm_device *); -extern int nv50_instmem_suspend(struct drm_device *); -extern void nv50_instmem_resume(struct drm_device *); -extern int nv50_instmem_get(struct nouveau_gpuobj *, struct nouveau_channel *, - u32 size, u32 align); -extern void nv50_instmem_put(struct nouveau_gpuobj *); -extern int nv50_instmem_map(struct nouveau_gpuobj *); -extern void nv50_instmem_unmap(struct nouveau_gpuobj *); -extern void nv50_instmem_flush(struct drm_device *); -extern void nv84_instmem_flush(struct drm_device *); - -/* nvc0_instmem.c */ -extern int nvc0_instmem_init(struct drm_device *); -extern void nvc0_instmem_takedown(struct drm_device *); -extern int nvc0_instmem_suspend(struct drm_device *); -extern void nvc0_instmem_resume(struct drm_device *); - extern long nouveau_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg); @@ -1260,23 +1151,6 @@ static inline void nvchan_wr32(struct nouveau_channel *chan, #define nv_wait_cb(dev, func, data) \ nouveau_wait_cb(dev, 2000000000ULL, (func), (data)) -/* PRAMIN access */ -static inline u32 nv_ri32(struct drm_device *dev, unsigned offset) -{ - struct drm_nouveau_private *dev_priv = dev->dev_private; - return ioread32_native(dev_priv->ramin + offset); -} - -static inline void nv_wi32(struct drm_device *dev, unsigned offset, u32 val) -{ - struct drm_nouveau_private *dev_priv = dev->dev_private; - iowrite32_native(val, dev_priv->ramin + offset); -} - -/* object access */ -extern u32 nv_ro32(struct nouveau_gpuobj *, u32 offset); -extern void nv_wo32(struct nouveau_gpuobj *, u32 offset, u32 val); - /* * Logging * Argument d is (struct drm_device *). diff --git a/drivers/gpu/drm/nouveau/nouveau_gpuobj.c b/drivers/gpu/drm/nouveau/nouveau_gpuobj.c index 0d370e8c468f..a774b7ad0f21 100644 --- a/drivers/gpu/drm/nouveau/nouveau_gpuobj.c +++ b/drivers/gpu/drm/nouveau/nouveau_gpuobj.c @@ -37,7 +37,6 @@ #include #include #include "nouveau_software.h" -#include struct nouveau_gpuobj_method { struct list_head head; @@ -135,173 +134,12 @@ nouveau_gpuobj_mthd_call2(struct drm_device *dev, int chid, return ret; } -int -nouveau_gpuobj_new(struct drm_device *dev, struct nouveau_channel *chan, - uint32_t size, int align, uint32_t flags, - struct nouveau_gpuobj **gpuobj_ret) -{ - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_instmem_engine *instmem = &dev_priv->engine.instmem; - struct nouveau_gpuobj *gpuobj; - struct drm_mm_node *ramin = NULL; - int ret, i; - - NV_DEBUG(dev, "ch%d size=%u align=%d flags=0x%08x\n", - chan ? chan->id : -1, size, align, flags); - - gpuobj = kzalloc(sizeof(*gpuobj), GFP_KERNEL); - if (!gpuobj) - return -ENOMEM; - NV_DEBUG(dev, "gpuobj %p\n", gpuobj); - gpuobj->dev = dev; - gpuobj->flags = flags; - kref_init(&gpuobj->refcount); - gpuobj->size = size; - - spin_lock(&dev_priv->ramin_lock); - list_add_tail(&gpuobj->list, &dev_priv->gpuobj_list); - spin_unlock(&dev_priv->ramin_lock); - - if (chan) { - ramin = drm_mm_search_free(&chan->ramin_heap, size, align, 0); - if (ramin) - ramin = drm_mm_get_block(ramin, size, align); - if (!ramin) { - nouveau_gpuobj_ref(NULL, &gpuobj); - return -ENOMEM; - } - - gpuobj->pinst = chan->ramin->pinst; - if (gpuobj->pinst != ~0) - gpuobj->pinst += ramin->start; - - gpuobj->cinst = ramin->start; - gpuobj->vinst = ramin->start + chan->ramin->vinst; - gpuobj->node = ramin; - } else { - ret = instmem->get(gpuobj, chan, size, align); - if (ret) { - nouveau_gpuobj_ref(NULL, &gpuobj); - return ret; - } - - ret = -ENOSYS; - if (!(flags & NVOBJ_FLAG_DONT_MAP)) - ret = instmem->map(gpuobj); - if (ret) - gpuobj->pinst = ~0; - - gpuobj->cinst = NVOBJ_CINST_GLOBAL; - } - - if (gpuobj->flags & NVOBJ_FLAG_ZERO_ALLOC) { - for (i = 0; i < gpuobj->size; i += 4) - nv_wo32(gpuobj, i, 0); - instmem->flush(dev); - } - - - *gpuobj_ret = gpuobj; - return 0; -} - -int -nouveau_gpuobj_init(struct drm_device *dev) -{ - struct drm_nouveau_private *dev_priv = dev->dev_private; - - NV_DEBUG(dev, "\n"); - - INIT_LIST_HEAD(&dev_priv->gpuobj_list); - INIT_LIST_HEAD(&dev_priv->classes); - spin_lock_init(&dev_priv->ramin_lock); - dev_priv->ramin_base = ~0; - - return 0; -} - -void -nouveau_gpuobj_takedown(struct drm_device *dev) -{ - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_gpuobj_method *om, *tm; - struct nouveau_gpuobj_class *oc, *tc; - - NV_DEBUG(dev, "\n"); - - list_for_each_entry_safe(oc, tc, &dev_priv->classes, head) { - list_for_each_entry_safe(om, tm, &oc->methods, head) { - list_del(&om->head); - kfree(om); - } - list_del(&oc->head); - kfree(oc); - } - - WARN_ON(!list_empty(&dev_priv->gpuobj_list)); -} - - -static void -nouveau_gpuobj_del(struct kref *ref) -{ - struct nouveau_gpuobj *gpuobj = - container_of(ref, struct nouveau_gpuobj, refcount); - struct drm_device *dev = gpuobj->dev; - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_instmem_engine *instmem = &dev_priv->engine.instmem; - int i; - - NV_DEBUG(dev, "gpuobj %p\n", gpuobj); - - if (gpuobj->node && (gpuobj->flags & NVOBJ_FLAG_ZERO_FREE)) { - for (i = 0; i < gpuobj->size; i += 4) - nv_wo32(gpuobj, i, 0); - instmem->flush(dev); - } - - if (gpuobj->dtor) - gpuobj->dtor(dev, gpuobj); - - if (gpuobj->cinst == NVOBJ_CINST_GLOBAL) { - if (gpuobj->node) { - instmem->unmap(gpuobj); - instmem->put(gpuobj); - } - } else { - if (gpuobj->node) { - spin_lock(&dev_priv->ramin_lock); - drm_mm_put_block(gpuobj->node); - spin_unlock(&dev_priv->ramin_lock); - } - } - - spin_lock(&dev_priv->ramin_lock); - list_del(&gpuobj->list); - spin_unlock(&dev_priv->ramin_lock); - - kfree(gpuobj); -} - -void -nouveau_gpuobj_ref(struct nouveau_gpuobj *ref, struct nouveau_gpuobj **ptr) -{ - if (ref) - kref_get(&ref->refcount); - - if (*ptr) - kref_put(&(*ptr)->refcount, nouveau_gpuobj_del); - - *ptr = ref; -} - void nv50_gpuobj_dma_init(struct nouveau_gpuobj *obj, u32 offset, int class, u64 base, u64 size, int target, int access, u32 type, u32 comp) { struct drm_nouveau_private *dev_priv = obj->dev->dev_private; - struct nouveau_instmem_engine *pinstmem = &dev_priv->engine.instmem; u32 flags0; flags0 = (comp << 29) | (type << 22) | class; @@ -343,7 +181,7 @@ nv50_gpuobj_dma_init(struct nouveau_gpuobj *obj, u32 offset, int class, nv_wo32(obj, offset + 0x10, 0x00000000); nv_wo32(obj, offset + 0x14, 0x00000000); - pinstmem->flush(obj->dev); + nvimem_flush(obj->dev); } int @@ -485,10 +323,6 @@ nv04_gpuobj_channel_init_pramin(struct nouveau_channel *chan) if (ret) return ret; - ret = drm_mm_init(&chan->ramin_heap, 0, chan->ramin->size); - if (ret) - return ret; - return 0; } @@ -503,10 +337,6 @@ nv50_gpuobj_channel_init_pramin(struct nouveau_channel *chan) if (ret) return ret; - ret = drm_mm_init(&chan->ramin_heap, 0, chan->ramin->size); - if (ret) - return ret; - ret = nouveau_gpuobj_new(dev, chan, 0x0200, 0, 0, &chan->ramfc); if (ret) return ret; @@ -533,10 +363,6 @@ nv84_gpuobj_channel_init_pramin(struct nouveau_channel *chan) if (ret) return ret; - ret = drm_mm_init(&chan->ramin_heap, 0, chan->ramin->size); - if (ret) - return ret; - ret = nouveau_gpuobj_new(dev, chan, 0x0200, 0, 0, &chan->engptr); if (ret) return ret; @@ -552,30 +378,20 @@ static int nvc0_gpuobj_channel_init(struct nouveau_channel *chan, struct nouveau_vm *vm) { struct drm_device *dev = chan->dev; - struct nouveau_gpuobj *pgd = NULL; - struct nouveau_vm_pgd *vpgd; int ret; ret = nouveau_gpuobj_new(dev, NULL, 4096, 0x1000, 0, &chan->ramin); if (ret) return ret; - /* create page directory for this vm if none currently exists, - * will be destroyed automagically when last reference to the - * vm is removed - */ - if (list_empty(&vm->pgd_list)) { - ret = nouveau_gpuobj_new(dev, NULL, 65536, 0x1000, 0, &pgd); - if (ret) - return ret; - } - nouveau_vm_ref(vm, &chan->vm, pgd); - nouveau_gpuobj_ref(NULL, &pgd); + ret = nouveau_gpuobj_new(dev, NULL, 65536, 0x1000, 0, &chan->vm_pd); + if (ret) + return ret; - /* point channel at vm's page directory */ - vpgd = list_first_entry(&vm->pgd_list, struct nouveau_vm_pgd, head); - nv_wo32(chan->ramin, 0x0200, lower_32_bits(vpgd->obj->vinst)); - nv_wo32(chan->ramin, 0x0204, upper_32_bits(vpgd->obj->vinst)); + nouveau_vm_ref(vm, &chan->vm, chan->vm_pd); + + nv_wo32(chan->ramin, 0x0200, lower_32_bits(chan->vm_pd->addr)); + nv_wo32(chan->ramin, 0x0204, upper_32_bits(chan->vm_pd->addr)); nv_wo32(chan->ramin, 0x0208, 0xffffffff); nv_wo32(chan->ramin, 0x020c, 0x000000ff); @@ -698,132 +514,5 @@ nouveau_gpuobj_channel_takedown(struct nouveau_channel *chan) nouveau_gpuobj_ref(NULL, &chan->ramfc); nouveau_gpuobj_ref(NULL, &chan->engptr); - if (drm_mm_initialized(&chan->ramin_heap)) - drm_mm_takedown(&chan->ramin_heap); nouveau_gpuobj_ref(NULL, &chan->ramin); } - -int -nouveau_gpuobj_suspend(struct drm_device *dev) -{ - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_gpuobj *gpuobj; - int i; - - list_for_each_entry(gpuobj, &dev_priv->gpuobj_list, list) { - if (gpuobj->cinst != NVOBJ_CINST_GLOBAL) - continue; - - gpuobj->suspend = vmalloc(gpuobj->size); - if (!gpuobj->suspend) { - nouveau_gpuobj_resume(dev); - return -ENOMEM; - } - - for (i = 0; i < gpuobj->size; i += 4) - gpuobj->suspend[i/4] = nv_ro32(gpuobj, i); - } - - return 0; -} - -void -nouveau_gpuobj_resume(struct drm_device *dev) -{ - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_gpuobj *gpuobj; - int i; - - list_for_each_entry(gpuobj, &dev_priv->gpuobj_list, list) { - if (!gpuobj->suspend) - continue; - - for (i = 0; i < gpuobj->size; i += 4) - nv_wo32(gpuobj, i, gpuobj->suspend[i/4]); - - vfree(gpuobj->suspend); - gpuobj->suspend = NULL; - } - - dev_priv->engine.instmem.flush(dev); -} - -u32 -nv_ro32(struct nouveau_gpuobj *gpuobj, u32 offset) -{ - struct drm_nouveau_private *dev_priv = gpuobj->dev->dev_private; - struct drm_device *dev = gpuobj->dev; - unsigned long flags; - - if (gpuobj->pinst == ~0 || !dev_priv->ramin_available) { - u64 ptr = gpuobj->vinst + offset; - u32 base = ptr >> 16; - u32 val; - - spin_lock_irqsave(&dev_priv->vm_lock, flags); - if (dev_priv->ramin_base != base) { - dev_priv->ramin_base = base; - nv_wr32(dev, 0x001700, dev_priv->ramin_base); - } - val = nv_rd32(dev, 0x700000 + (ptr & 0xffff)); - spin_unlock_irqrestore(&dev_priv->vm_lock, flags); - return val; - } - - return nv_ri32(dev, gpuobj->pinst + offset); -} - -void -nv_wo32(struct nouveau_gpuobj *gpuobj, u32 offset, u32 val) -{ - struct drm_nouveau_private *dev_priv = gpuobj->dev->dev_private; - struct drm_device *dev = gpuobj->dev; - unsigned long flags; - - if (gpuobj->pinst == ~0 || !dev_priv->ramin_available) { - u64 ptr = gpuobj->vinst + offset; - u32 base = ptr >> 16; - - spin_lock_irqsave(&dev_priv->vm_lock, flags); - if (dev_priv->ramin_base != base) { - dev_priv->ramin_base = base; - nv_wr32(dev, 0x001700, dev_priv->ramin_base); - } - nv_wr32(dev, 0x700000 + (ptr & 0xffff), val); - spin_unlock_irqrestore(&dev_priv->vm_lock, flags); - return; - } - - nv_wi32(dev, gpuobj->pinst + offset, val); -} - -int -nouveau_gpuobj_map_vm(struct nouveau_gpuobj *gpuobj, u32 flags, - struct nouveau_vm *vm, struct nouveau_vma *vma) -{ - struct nouveau_mem **mem = gpuobj->node; - struct nouveau_mem *node = *mem; - int ret; - - ret = nouveau_vm_get(vm, node->size << 12, 12, flags, vma); - if (ret) - return ret; - - nouveau_vm_map(vma, node); - return 0; -} - -int -nouveau_gpuobj_map_bar(struct nouveau_gpuobj *gpuobj, u32 flags, - struct nouveau_vma *vma) -{ - struct drm_nouveau_private *dev_priv = gpuobj->dev->dev_private; - return nouveau_gpuobj_map_vm(gpuobj, flags, dev_priv->bar1_vm, vma); -} - -void -nouveau_gpuobj_unmap(struct nouveau_vma *vma) -{ - nouveau_vm_unmap(vma); - nouveau_vm_put(vma); -} diff --git a/drivers/gpu/drm/nouveau/nouveau_mem.c b/drivers/gpu/drm/nouveau/nouveau_mem.c index 4aea1c4c46ef..48131ceeeb80 100644 --- a/drivers/gpu/drm/nouveau/nouveau_mem.c +++ b/drivers/gpu/drm/nouveau/nouveau_mem.c @@ -38,7 +38,6 @@ #include "nouveau_drv.h" #include "nouveau_pm.h" #include -#include #include #include "nouveau_fence.h" @@ -220,7 +219,7 @@ nouveau_mem_vram_init(struct drm_device *dev) dev_priv->fb_mappable_pages = pci_resource_len(dev->pdev, 1); dev_priv->fb_mappable_pages >>= PAGE_SHIFT; - dev_priv->fb_available_size -= dev_priv->ramin_rsvd_vram; + dev_priv->fb_available_size -= nvimem_reserved(dev); dev_priv->fb_aper_free = dev_priv->fb_available_size; /* mappable vram */ @@ -1058,3 +1057,71 @@ const struct ttm_mem_type_manager_func nouveau_gart_manager = { nouveau_gart_manager_del, nouveau_gart_manager_debug }; + +static int +nv04_gart_manager_init(struct ttm_mem_type_manager *man, unsigned long psize) +{ + struct drm_nouveau_private *dev_priv = nouveau_bdev(man->bdev); + struct drm_device *dev = dev_priv->dev; + man->priv = nv04vm_ref(dev); + return (man->priv != NULL) ? 0 : -ENODEV; +} + +static int +nv04_gart_manager_fini(struct ttm_mem_type_manager *man) +{ + struct nouveau_vm *vm = man->priv; + nouveau_vm_ref(NULL, &vm, NULL); + man->priv = NULL; + return 0; +} + +static void +nv04_gart_manager_del(struct ttm_mem_type_manager *man, struct ttm_mem_reg *mem) +{ + struct nouveau_mem *node = mem->mm_node; + if (node->vma[0].node) + nouveau_vm_put(&node->vma[0]); + kfree(mem->mm_node); + mem->mm_node = NULL; +} + +static int +nv04_gart_manager_new(struct ttm_mem_type_manager *man, + struct ttm_buffer_object *bo, + struct ttm_placement *placement, + struct ttm_mem_reg *mem) +{ + struct nouveau_mem *node; + int ret; + + node = kzalloc(sizeof(*node), GFP_KERNEL); + if (!node) + return -ENOMEM; + + node->page_shift = 12; + + ret = nouveau_vm_get(man->priv, mem->num_pages << 12, node->page_shift, + NV_MEM_ACCESS_RW, &node->vma[0]); + if (ret) { + kfree(node); + return ret; + } + + mem->mm_node = node; + mem->start = node->vma[0].offset >> PAGE_SHIFT; + return 0; +} + +void +nv04_gart_manager_debug(struct ttm_mem_type_manager *man, const char *prefix) +{ +} + +const struct ttm_mem_type_manager_func nv04_gart_manager = { + nv04_gart_manager_init, + nv04_gart_manager_fini, + nv04_gart_manager_new, + nv04_gart_manager_del, + nv04_gart_manager_debug +}; diff --git a/drivers/gpu/drm/nouveau/nouveau_notifier.c b/drivers/gpu/drm/nouveau/nouveau_notifier.c index 151ffbb411c3..2cc4779b4299 100644 --- a/drivers/gpu/drm/nouveau/nouveau_notifier.c +++ b/drivers/gpu/drm/nouveau/nouveau_notifier.c @@ -96,16 +96,6 @@ nouveau_notifier_takedown_channel(struct nouveau_channel *chan) drm_mm_takedown(&chan->notifier_heap); } -static void -nouveau_notifier_gpuobj_dtor(struct drm_device *dev, - struct nouveau_gpuobj *gpuobj) -{ - NV_DEBUG(dev, "\n"); - - if (gpuobj->priv) - drm_mm_put_block(gpuobj->priv); -} - int nouveau_notifier_alloc(struct nouveau_channel *chan, uint32_t handle, int size, uint32_t start, uint32_t end, @@ -147,8 +137,6 @@ nouveau_notifier_alloc(struct nouveau_channel *chan, uint32_t handle, NV_ERROR(dev, "Error creating notifier ctxdma: %d\n", ret); return ret; } - nobj->dtor = nouveau_notifier_gpuobj_dtor; - nobj->priv = mem; ret = nouveau_ramht_insert(chan, handle, nobj); nouveau_gpuobj_ref(NULL, &nobj); diff --git a/drivers/gpu/drm/nouveau/nouveau_sgdma.c b/drivers/gpu/drm/nouveau/nouveau_sgdma.c index 38483a042bc2..464beda94c58 100644 --- a/drivers/gpu/drm/nouveau/nouveau_sgdma.c +++ b/drivers/gpu/drm/nouveau/nouveau_sgdma.c @@ -13,7 +13,7 @@ struct nouveau_sgdma_be { */ struct ttm_dma_tt ttm; struct drm_device *dev; - u64 offset; + struct nouveau_mem *node; }; static void @@ -32,25 +32,18 @@ static int nv04_sgdma_bind(struct ttm_tt *ttm, struct ttm_mem_reg *mem) { struct nouveau_sgdma_be *nvbe = (struct nouveau_sgdma_be *)ttm; - struct drm_device *dev = nvbe->dev; - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_gpuobj *gpuobj = dev_priv->gart_info.sg_ctxdma; - unsigned i, j, pte; - - NV_DEBUG(dev, "pg=0x%lx\n", mem->start); - - nvbe->offset = mem->start << PAGE_SHIFT; - pte = (nvbe->offset >> NV_CTXDMA_PAGE_SHIFT) + 2; - for (i = 0; i < ttm->num_pages; i++) { - dma_addr_t dma_offset = nvbe->ttm.dma_address[i]; - uint32_t offset_l = lower_32_bits(dma_offset); + struct nouveau_mem *node = mem->mm_node; + u64 size = mem->num_pages << 12; - for (j = 0; j < PAGE_SIZE / NV_CTXDMA_PAGE_SIZE; j++, pte++) { - nv_wo32(gpuobj, (pte * 4) + 0, offset_l | 3); - offset_l += NV_CTXDMA_PAGE_SIZE; - } + if (ttm->sg) { + node->sg = ttm->sg; + nouveau_vm_map_sg_table(&node->vma[0], 0, size, node); + } else { + node->pages = nvbe->ttm.dma_address; + nouveau_vm_map_sg(&node->vma[0], 0, size, node); } + nvbe->node = node; return 0; } @@ -58,22 +51,7 @@ static int nv04_sgdma_unbind(struct ttm_tt *ttm) { struct nouveau_sgdma_be *nvbe = (struct nouveau_sgdma_be *)ttm; - struct drm_device *dev = nvbe->dev; - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_gpuobj *gpuobj = dev_priv->gart_info.sg_ctxdma; - unsigned i, j, pte; - - NV_DEBUG(dev, "\n"); - - if (ttm->state != tt_bound) - return 0; - - pte = (nvbe->offset >> NV_CTXDMA_PAGE_SHIFT) + 2; - for (i = 0; i < ttm->num_pages; i++) { - for (j = 0; j < PAGE_SIZE / NV_CTXDMA_PAGE_SIZE; j++, pte++) - nv_wo32(gpuobj, (pte * 4) + 0, 0x00000000); - } - + nouveau_vm_unmap(&nvbe->node->vma[0]); return 0; } @@ -83,206 +61,6 @@ static struct ttm_backend_func nv04_sgdma_backend = { .destroy = nouveau_sgdma_destroy }; -static void -nv41_sgdma_flush(struct nouveau_sgdma_be *nvbe) -{ - struct drm_device *dev = nvbe->dev; - - nv_wr32(dev, 0x100810, 0x00000022); - if (!nv_wait(dev, 0x100810, 0x00000100, 0x00000100)) - NV_ERROR(dev, "vm flush timeout: 0x%08x\n", - nv_rd32(dev, 0x100810)); - nv_wr32(dev, 0x100810, 0x00000000); -} - -static int -nv41_sgdma_bind(struct ttm_tt *ttm, struct ttm_mem_reg *mem) -{ - struct nouveau_sgdma_be *nvbe = (struct nouveau_sgdma_be *)ttm; - struct drm_nouveau_private *dev_priv = nvbe->dev->dev_private; - struct nouveau_gpuobj *pgt = dev_priv->gart_info.sg_ctxdma; - dma_addr_t *list = nvbe->ttm.dma_address; - u32 pte = mem->start << 2; - u32 cnt = ttm->num_pages; - - nvbe->offset = mem->start << PAGE_SHIFT; - - while (cnt--) { - nv_wo32(pgt, pte, (*list++ >> 7) | 1); - pte += 4; - } - - nv41_sgdma_flush(nvbe); - return 0; -} - -static int -nv41_sgdma_unbind(struct ttm_tt *ttm) -{ - struct nouveau_sgdma_be *nvbe = (struct nouveau_sgdma_be *)ttm; - struct drm_nouveau_private *dev_priv = nvbe->dev->dev_private; - struct nouveau_gpuobj *pgt = dev_priv->gart_info.sg_ctxdma; - u32 pte = (nvbe->offset >> 12) << 2; - u32 cnt = ttm->num_pages; - - while (cnt--) { - nv_wo32(pgt, pte, 0x00000000); - pte += 4; - } - - nv41_sgdma_flush(nvbe); - return 0; -} - -static struct ttm_backend_func nv41_sgdma_backend = { - .bind = nv41_sgdma_bind, - .unbind = nv41_sgdma_unbind, - .destroy = nouveau_sgdma_destroy -}; - -static void -nv44_sgdma_flush(struct ttm_tt *ttm) -{ - struct nouveau_sgdma_be *nvbe = (struct nouveau_sgdma_be *)ttm; - struct drm_device *dev = nvbe->dev; - - nv_wr32(dev, 0x100814, (ttm->num_pages - 1) << 12); - nv_wr32(dev, 0x100808, nvbe->offset | 0x20); - if (!nv_wait(dev, 0x100808, 0x00000001, 0x00000001)) - NV_ERROR(dev, "gart flush timeout: 0x%08x\n", - nv_rd32(dev, 0x100808)); - nv_wr32(dev, 0x100808, 0x00000000); -} - -static void -nv44_sgdma_fill(struct nouveau_gpuobj *pgt, dma_addr_t *list, u32 base, u32 cnt) -{ - struct drm_nouveau_private *dev_priv = pgt->dev->dev_private; - dma_addr_t dummy = dev_priv->gart_info.dummy.addr; - u32 pte, tmp[4]; - - pte = base >> 2; - base &= ~0x0000000f; - - tmp[0] = nv_ro32(pgt, base + 0x0); - tmp[1] = nv_ro32(pgt, base + 0x4); - tmp[2] = nv_ro32(pgt, base + 0x8); - tmp[3] = nv_ro32(pgt, base + 0xc); - while (cnt--) { - u32 addr = list ? (*list++ >> 12) : (dummy >> 12); - switch (pte++ & 0x3) { - case 0: - tmp[0] &= ~0x07ffffff; - tmp[0] |= addr; - break; - case 1: - tmp[0] &= ~0xf8000000; - tmp[0] |= addr << 27; - tmp[1] &= ~0x003fffff; - tmp[1] |= addr >> 5; - break; - case 2: - tmp[1] &= ~0xffc00000; - tmp[1] |= addr << 22; - tmp[2] &= ~0x0001ffff; - tmp[2] |= addr >> 10; - break; - case 3: - tmp[2] &= ~0xfffe0000; - tmp[2] |= addr << 17; - tmp[3] &= ~0x00000fff; - tmp[3] |= addr >> 15; - break; - } - } - - tmp[3] |= 0x40000000; - - nv_wo32(pgt, base + 0x0, tmp[0]); - nv_wo32(pgt, base + 0x4, tmp[1]); - nv_wo32(pgt, base + 0x8, tmp[2]); - nv_wo32(pgt, base + 0xc, tmp[3]); -} - -static int -nv44_sgdma_bind(struct ttm_tt *ttm, struct ttm_mem_reg *mem) -{ - struct nouveau_sgdma_be *nvbe = (struct nouveau_sgdma_be *)ttm; - struct drm_nouveau_private *dev_priv = nvbe->dev->dev_private; - struct nouveau_gpuobj *pgt = dev_priv->gart_info.sg_ctxdma; - dma_addr_t *list = nvbe->ttm.dma_address; - u32 pte = mem->start << 2, tmp[4]; - u32 cnt = ttm->num_pages; - int i; - - nvbe->offset = mem->start << PAGE_SHIFT; - - if (pte & 0x0000000c) { - u32 max = 4 - ((pte >> 2) & 0x3); - u32 part = (cnt > max) ? max : cnt; - nv44_sgdma_fill(pgt, list, pte, part); - pte += (part << 2); - list += part; - cnt -= part; - } - - while (cnt >= 4) { - for (i = 0; i < 4; i++) - tmp[i] = *list++ >> 12; - nv_wo32(pgt, pte + 0x0, tmp[0] >> 0 | tmp[1] << 27); - nv_wo32(pgt, pte + 0x4, tmp[1] >> 5 | tmp[2] << 22); - nv_wo32(pgt, pte + 0x8, tmp[2] >> 10 | tmp[3] << 17); - nv_wo32(pgt, pte + 0xc, tmp[3] >> 15 | 0x40000000); - pte += 0x10; - cnt -= 4; - } - - if (cnt) - nv44_sgdma_fill(pgt, list, pte, cnt); - - nv44_sgdma_flush(ttm); - return 0; -} - -static int -nv44_sgdma_unbind(struct ttm_tt *ttm) -{ - struct nouveau_sgdma_be *nvbe = (struct nouveau_sgdma_be *)ttm; - struct drm_nouveau_private *dev_priv = nvbe->dev->dev_private; - struct nouveau_gpuobj *pgt = dev_priv->gart_info.sg_ctxdma; - u32 pte = (nvbe->offset >> 12) << 2; - u32 cnt = ttm->num_pages; - - if (pte & 0x0000000c) { - u32 max = 4 - ((pte >> 2) & 0x3); - u32 part = (cnt > max) ? max : cnt; - nv44_sgdma_fill(pgt, NULL, pte, part); - pte += (part << 2); - cnt -= part; - } - - while (cnt >= 4) { - nv_wo32(pgt, pte + 0x0, 0x00000000); - nv_wo32(pgt, pte + 0x4, 0x00000000); - nv_wo32(pgt, pte + 0x8, 0x00000000); - nv_wo32(pgt, pte + 0xc, 0x00000000); - pte += 0x10; - cnt -= 4; - } - - if (cnt) - nv44_sgdma_fill(pgt, NULL, pte, cnt); - - nv44_sgdma_flush(ttm); - return 0; -} - -static struct ttm_backend_func nv44_sgdma_backend = { - .bind = nv44_sgdma_bind, - .unbind = nv44_sgdma_unbind, - .destroy = nouveau_sgdma_destroy -}; - static int nv50_sgdma_bind(struct ttm_tt *ttm, struct ttm_mem_reg *mem) { @@ -337,82 +115,24 @@ int nouveau_sgdma_init(struct drm_device *dev) { struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_gpuobj *gpuobj = NULL; - u32 aper_size, align; - int ret; + u32 aper_size; - if (dev_priv->card_type >= NV_40) + if (dev_priv->card_type >= NV_50) aper_size = 512 * 1024 * 1024; else aper_size = 128 * 1024 * 1024; - /* Dear NVIDIA, NV44+ would like proper present bits in PTEs for - * christmas. The cards before it have them, the cards after - * it have them, why is NV44 so unloved? - */ - dev_priv->gart_info.dummy.page = alloc_page(GFP_DMA32 | GFP_KERNEL); - if (!dev_priv->gart_info.dummy.page) - return -ENOMEM; - - dev_priv->gart_info.dummy.addr = - pci_map_page(dev->pdev, dev_priv->gart_info.dummy.page, - 0, PAGE_SIZE, PCI_DMA_BIDIRECTIONAL); - if (pci_dma_mapping_error(dev->pdev, dev_priv->gart_info.dummy.addr)) { - NV_ERROR(dev, "error mapping dummy page\n"); - __free_page(dev_priv->gart_info.dummy.page); - dev_priv->gart_info.dummy.page = NULL; - return -ENOMEM; - } - if (dev_priv->card_type >= NV_50) { dev_priv->gart_info.aper_base = 0; dev_priv->gart_info.aper_size = aper_size; dev_priv->gart_info.type = NOUVEAU_GART_HW; dev_priv->gart_info.func = &nv50_sgdma_backend; - } else - if (0 && pci_is_pcie(dev->pdev) && - dev_priv->chipset > 0x40 && dev_priv->chipset != 0x45) { - if (nv44_graph_class(dev)) { - dev_priv->gart_info.func = &nv44_sgdma_backend; - align = 512 * 1024; - } else { - dev_priv->gart_info.func = &nv41_sgdma_backend; - align = 16; - } - - ret = nouveau_gpuobj_new(dev, NULL, aper_size / 1024, align, - NVOBJ_FLAG_ZERO_ALLOC | - NVOBJ_FLAG_ZERO_FREE, &gpuobj); - if (ret) { - NV_ERROR(dev, "Error creating sgdma object: %d\n", ret); - return ret; - } - - dev_priv->gart_info.sg_ctxdma = gpuobj; - dev_priv->gart_info.aper_base = 0; - dev_priv->gart_info.aper_size = aper_size; - dev_priv->gart_info.type = NOUVEAU_GART_HW; } else { - ret = nouveau_gpuobj_new(dev, NULL, (aper_size / 1024) + 8, 16, - NVOBJ_FLAG_ZERO_ALLOC | - NVOBJ_FLAG_ZERO_FREE, &gpuobj); - if (ret) { - NV_ERROR(dev, "Error creating sgdma object: %d\n", ret); - return ret; - } - - nv_wo32(gpuobj, 0, NV_CLASS_DMA_IN_MEMORY | - (1 << 12) /* PT present */ | - (0 << 13) /* PT *not* linear */ | - (0 << 14) /* RW */ | - (2 << 16) /* PCI */); - nv_wo32(gpuobj, 4, aper_size - 1); - - dev_priv->gart_info.sg_ctxdma = gpuobj; dev_priv->gart_info.aper_base = 0; dev_priv->gart_info.aper_size = aper_size; dev_priv->gart_info.type = NOUVEAU_GART_PDMA; dev_priv->gart_info.func = &nv04_sgdma_backend; + dev_priv->gart_info.sg_ctxdma = nv04vm_refdma(dev); } return 0; @@ -424,13 +144,6 @@ nouveau_sgdma_takedown(struct drm_device *dev) struct drm_nouveau_private *dev_priv = dev->dev_private; nouveau_gpuobj_ref(NULL, &dev_priv->gart_info.sg_ctxdma); - - if (dev_priv->gart_info.dummy.page) { - pci_unmap_page(dev->pdev, dev_priv->gart_info.dummy.addr, - PAGE_SIZE, PCI_DMA_BIDIRECTIONAL); - __free_page(dev_priv->gart_info.dummy.page); - dev_priv->gart_info.dummy.page = NULL; - } } uint32_t diff --git a/drivers/gpu/drm/nouveau/nouveau_state.c b/drivers/gpu/drm/nouveau/nouveau_state.c index 14998ee89c94..f53c6a748200 100644 --- a/drivers/gpu/drm/nouveau/nouveau_state.c +++ b/drivers/gpu/drm/nouveau/nouveau_state.c @@ -52,15 +52,6 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev) switch (dev_priv->chipset & 0xf0) { case 0x00: - engine->instmem.init = nv04_instmem_init; - engine->instmem.takedown = nv04_instmem_takedown; - engine->instmem.suspend = nv04_instmem_suspend; - engine->instmem.resume = nv04_instmem_resume; - engine->instmem.get = nv04_instmem_get; - engine->instmem.put = nv04_instmem_put; - engine->instmem.map = nv04_instmem_map; - engine->instmem.unmap = nv04_instmem_unmap; - engine->instmem.flush = nv04_instmem_flush; engine->display.early_init = nv04_display_early_init; engine->display.late_takedown = nv04_display_late_takedown; engine->display.create = nv04_display_create; @@ -72,15 +63,6 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev) engine->pm.clocks_set = nv04_pm_clocks_set; break; case 0x10: - engine->instmem.init = nv04_instmem_init; - engine->instmem.takedown = nv04_instmem_takedown; - engine->instmem.suspend = nv04_instmem_suspend; - engine->instmem.resume = nv04_instmem_resume; - engine->instmem.get = nv04_instmem_get; - engine->instmem.put = nv04_instmem_put; - engine->instmem.map = nv04_instmem_map; - engine->instmem.unmap = nv04_instmem_unmap; - engine->instmem.flush = nv04_instmem_flush; engine->display.early_init = nv04_display_early_init; engine->display.late_takedown = nv04_display_late_takedown; engine->display.create = nv04_display_create; @@ -92,15 +74,6 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev) engine->pm.clocks_set = nv04_pm_clocks_set; break; case 0x20: - engine->instmem.init = nv04_instmem_init; - engine->instmem.takedown = nv04_instmem_takedown; - engine->instmem.suspend = nv04_instmem_suspend; - engine->instmem.resume = nv04_instmem_resume; - engine->instmem.get = nv04_instmem_get; - engine->instmem.put = nv04_instmem_put; - engine->instmem.map = nv04_instmem_map; - engine->instmem.unmap = nv04_instmem_unmap; - engine->instmem.flush = nv04_instmem_flush; engine->display.early_init = nv04_display_early_init; engine->display.late_takedown = nv04_display_late_takedown; engine->display.create = nv04_display_create; @@ -112,15 +85,6 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev) engine->pm.clocks_set = nv04_pm_clocks_set; break; case 0x30: - engine->instmem.init = nv04_instmem_init; - engine->instmem.takedown = nv04_instmem_takedown; - engine->instmem.suspend = nv04_instmem_suspend; - engine->instmem.resume = nv04_instmem_resume; - engine->instmem.get = nv04_instmem_get; - engine->instmem.put = nv04_instmem_put; - engine->instmem.map = nv04_instmem_map; - engine->instmem.unmap = nv04_instmem_unmap; - engine->instmem.flush = nv04_instmem_flush; engine->display.early_init = nv04_display_early_init; engine->display.late_takedown = nv04_display_late_takedown; engine->display.create = nv04_display_create; @@ -135,15 +99,6 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev) break; case 0x40: case 0x60: - engine->instmem.init = nv40_instmem_init; - engine->instmem.takedown = nv40_instmem_takedown; - engine->instmem.suspend = nv40_instmem_suspend; - engine->instmem.resume = nv40_instmem_resume; - engine->instmem.get = nv40_instmem_get; - engine->instmem.put = nv40_instmem_put; - engine->instmem.map = nv40_instmem_map; - engine->instmem.unmap = nv40_instmem_unmap; - engine->instmem.flush = nv40_instmem_flush; engine->display.early_init = nv04_display_early_init; engine->display.late_takedown = nv04_display_late_takedown; engine->display.create = nv04_display_create; @@ -163,18 +118,6 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev) case 0x80: /* gotta love NVIDIA's consistency.. */ case 0x90: case 0xa0: - engine->instmem.init = nv50_instmem_init; - engine->instmem.takedown = nv50_instmem_takedown; - engine->instmem.suspend = nv50_instmem_suspend; - engine->instmem.resume = nv50_instmem_resume; - engine->instmem.get = nv50_instmem_get; - engine->instmem.put = nv50_instmem_put; - engine->instmem.map = nv50_instmem_map; - engine->instmem.unmap = nv50_instmem_unmap; - if (dev_priv->chipset == 0x50) - engine->instmem.flush = nv50_instmem_flush; - else - engine->instmem.flush = nv84_instmem_flush; engine->display.early_init = nv50_display_early_init; engine->display.late_takedown = nv50_display_late_takedown; engine->display.create = nv50_display_create; @@ -212,15 +155,6 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev) engine->pm.pwm_set = nv50_pm_pwm_set; break; case 0xc0: - engine->instmem.init = nvc0_instmem_init; - engine->instmem.takedown = nvc0_instmem_takedown; - engine->instmem.suspend = nvc0_instmem_suspend; - engine->instmem.resume = nvc0_instmem_resume; - engine->instmem.get = nv50_instmem_get; - engine->instmem.put = nv50_instmem_put; - engine->instmem.map = nv50_instmem_map; - engine->instmem.unmap = nv50_instmem_unmap; - engine->instmem.flush = nv84_instmem_flush; engine->display.early_init = nv50_display_early_init; engine->display.late_takedown = nv50_display_late_takedown; engine->display.create = nv50_display_create; @@ -237,15 +171,6 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev) engine->pm.pwm_set = nv50_pm_pwm_set; break; case 0xd0: - engine->instmem.init = nvc0_instmem_init; - engine->instmem.takedown = nvc0_instmem_takedown; - engine->instmem.suspend = nvc0_instmem_suspend; - engine->instmem.resume = nvc0_instmem_resume; - engine->instmem.get = nv50_instmem_get; - engine->instmem.put = nv50_instmem_put; - engine->instmem.map = nv50_instmem_map; - engine->instmem.unmap = nv50_instmem_unmap; - engine->instmem.flush = nv84_instmem_flush; engine->display.early_init = nouveau_stub_init; engine->display.late_takedown = nouveau_stub_takedown; engine->display.create = nvd0_display_create; @@ -260,15 +185,6 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev) engine->pm.voltage_set = nouveau_voltage_gpio_set; break; case 0xe0: - engine->instmem.init = nvc0_instmem_init; - engine->instmem.takedown = nvc0_instmem_takedown; - engine->instmem.suspend = nvc0_instmem_suspend; - engine->instmem.resume = nvc0_instmem_resume; - engine->instmem.get = nv50_instmem_get; - engine->instmem.put = nv50_instmem_put; - engine->instmem.map = nv50_instmem_map; - engine->instmem.unmap = nv50_instmem_unmap; - engine->instmem.flush = nv84_instmem_flush; engine->display.early_init = nouveau_stub_init; engine->display.late_takedown = nouveau_stub_takedown; engine->display.create = nvd0_display_create; @@ -354,8 +270,10 @@ nouveau_card_channel_fini(struct drm_device *dev) { struct drm_nouveau_private *dev_priv = dev->dev_private; - if (dev_priv->channel) + if (dev_priv->channel) { nouveau_channel_put_unlocked(&dev_priv->channel); + nouveau_vm_ref(NULL, &dev_priv->chan_vm, NULL); + } } static int @@ -365,6 +283,10 @@ nouveau_card_channel_init(struct drm_device *dev) struct nouveau_channel *chan; int ret; + ret = nouveau_vm_new(dev, 0, (1ULL << 40), 0x1000, &dev_priv->chan_vm); + if (ret) + return ret; + ret = nouveau_channel_alloc(dev, &chan, NULL, NvDmaFB, NvDmaTT); dev_priv->channel = chan; if (ret) @@ -400,6 +322,7 @@ nouveau_card_init(struct drm_device *dev) spin_lock_init(&dev_priv->tile.lock); spin_lock_init(&dev_priv->context_switch_lock); spin_lock_init(&dev_priv->vm_lock); + INIT_LIST_HEAD(&dev_priv->classes); /* Make the CRTCs and I2C buses accessible */ ret = engine->display.early_init(dev); @@ -419,17 +342,9 @@ nouveau_card_init(struct drm_device *dev) nv_mask(dev, 0x00088080, 0x00000800, 0x00000000); } - ret = nouveau_gpuobj_init(dev); - if (ret) - goto out_bios; - - ret = engine->instmem.init(dev); - if (ret) - goto out_gpuobj; - ret = nouveau_mem_vram_init(dev); if (ret) - goto out_instmem; + goto out_bios; ret = nouveau_mem_gart_init(dev); if (ret) @@ -652,10 +567,6 @@ out_engine: nouveau_mem_gart_fini(dev); out_ttmvram: nouveau_mem_vram_fini(dev); -out_instmem: - engine->instmem.takedown(dev); -out_gpuobj: - nouveau_gpuobj_takedown(dev); out_bios: nouveau_bios_takedown(dev); out_display_early: @@ -703,9 +614,6 @@ static void nouveau_card_takedown(struct drm_device *dev) nouveau_mem_gart_fini(dev); nouveau_mem_vram_fini(dev); - engine->instmem.takedown(dev); - nouveau_gpuobj_takedown(dev); - nouveau_bios_takedown(dev); engine->display.late_takedown(dev); @@ -955,32 +863,6 @@ int nouveau_load(struct drm_device *dev, unsigned long flags) if (ret) goto err_priv; - /* Map PRAMIN BAR, or on older cards, the aperture within BAR0 */ - if (dev_priv->card_type >= NV_40) { - int ramin_bar = 2; - if (pci_resource_len(dev->pdev, ramin_bar) == 0) - ramin_bar = 3; - - dev_priv->ramin_size = pci_resource_len(dev->pdev, ramin_bar); - dev_priv->ramin = - ioremap(pci_resource_start(dev->pdev, ramin_bar), - dev_priv->ramin_size); - if (!dev_priv->ramin) { - NV_ERROR(dev, "Failed to map PRAMIN BAR\n"); - ret = -ENOMEM; - goto err_priv; - } - } else { - dev_priv->ramin_size = 1 * 1024 * 1024; - dev_priv->ramin = ioremap(pci_resource_start(dev->pdev, 0), - dev_priv->ramin_size); - if (!dev_priv->ramin) { - NV_ERROR(dev, "Failed to map BAR0 PRAMIN.\n"); - ret = -ENOMEM; - goto err_priv; - } - } - nouveau_OF_copy_vbios_to_ramin(dev); /* Special flags */ @@ -992,12 +874,10 @@ int nouveau_load(struct drm_device *dev, unsigned long flags) /* For kernel modesetting, init card now and bring up fbcon */ ret = nouveau_card_init(dev); if (ret) - goto err_ramin; + goto err_priv; return 0; -err_ramin: - iounmap(dev_priv->ramin); err_priv: dev->dev_private = dev_priv->newpriv; kfree(dev_priv); @@ -1016,8 +896,6 @@ int nouveau_unload(struct drm_device *dev) nouveau_card_takedown(dev); - iounmap(dev_priv->ramin); - dev->dev_private = dev_priv->newpriv; kfree(dev_priv); return 0; diff --git a/drivers/gpu/drm/nouveau/nv50_display.c b/drivers/gpu/drm/nouveau/nv50_display.c index ccbb03ead8eb..9c0bb20b0dc3 100644 --- a/drivers/gpu/drm/nouveau/nv50_display.c +++ b/drivers/gpu/drm/nouveau/nv50_display.c @@ -217,7 +217,7 @@ nv50_display_init(struct drm_device *dev) return ret; evo = nv50_display(dev)->master; - nv_wr32(dev, NV50_PDISPLAY_OBJECTS, (evo->ramin->vinst >> 8) | 9); + nv_wr32(dev, NV50_PDISPLAY_OBJECTS, (evo->ramin->addr >> 8) | 9); ret = RING_SPACE(evo, 3); if (ret) diff --git a/drivers/gpu/drm/nouveau/nv50_evo.c b/drivers/gpu/drm/nouveau/nv50_evo.c index 7a1424243665..7e9a6d6d673b 100644 --- a/drivers/gpu/drm/nouveau/nv50_evo.c +++ b/drivers/gpu/drm/nouveau/nv50_evo.c @@ -70,7 +70,7 @@ nv50_evo_dmaobj_init(struct nouveau_gpuobj *obj, u32 memtype, u64 base, u64 size nv50_gpuobj_dma_init(obj, 0, 0x3d, base, size, NV_MEM_TARGET_VRAM, NV_MEM_ACCESS_RW, (memtype >> 8) & 0xff, 0); nv_wo32(obj, 0x14, flags5); - dev_priv->engine.instmem.flush(obj->dev); + nvimem_flush(obj->dev); } int @@ -263,12 +263,6 @@ nv50_evo_create(struct drm_device *dev) goto err; } - ret = drm_mm_init(&evo->ramin_heap, 0, 32768); - if (ret) { - NV_ERROR(dev, "Error initialising EVO PRAMIN heap: %d\n", ret); - goto err; - } - ret = nouveau_gpuobj_new(dev, evo, 4096, 16, 0, &ramht); if (ret) { NV_ERROR(dev, "Unable to allocate EVO RAMHT: %d\n", ret); @@ -294,7 +288,7 @@ nv50_evo_create(struct drm_device *dev) goto err; ret = nv50_evo_dmaobj_new(disp->master, NvEvoSync, 0x0000, - disp->ntfy->vinst, disp->ntfy->size, NULL); + disp->ntfy->addr, disp->ntfy->size, NULL); if (ret) goto err; diff --git a/drivers/gpu/drm/nouveau/nv50_software.c b/drivers/gpu/drm/nouveau/nv50_software.c index 1440a948d0aa..a1c06d44eeb5 100644 --- a/drivers/gpu/drm/nouveau/nv50_software.c +++ b/drivers/gpu/drm/nouveau/nv50_software.c @@ -48,7 +48,7 @@ mthd_dma_vblsem(struct nouveau_channel *chan, u32 class, u32 mthd, u32 data) if (!gpuobj) return -ENOENT; - pch->base.vblank.ctxdma = gpuobj->cinst >> 4; + pch->base.vblank.ctxdma = gpuobj->node->offset >> 4; return 0; } @@ -105,7 +105,7 @@ nv50_software_context_new(struct nouveau_channel *chan, int engine) return -ENOMEM; nouveau_software_context_new(&pch->base); - pch->base.vblank.channel = chan->ramin->vinst >> 12; + pch->base.vblank.channel = chan->ramin->addr >> 12; chan->engctx[engine] = pch; /* dma objects for display sync channel semaphore blocks */ diff --git a/drivers/gpu/drm/nouveau/nv84_fence.c b/drivers/gpu/drm/nouveau/nv84_fence.c index 199c57c669b5..721716aacbe0 100644 --- a/drivers/gpu/drm/nouveau/nv84_fence.c +++ b/drivers/gpu/drm/nouveau/nv84_fence.c @@ -106,7 +106,7 @@ nv84_fence_context_new(struct nouveau_channel *chan, int engine) nouveau_fence_context_new(&fctx->base); ret = nouveau_gpuobj_dma_new(chan, NV_CLASS_DMA_FROM_MEMORY, - priv->mem->vinst, priv->mem->size, + priv->mem->addr, priv->mem->size, NV_MEM_ACCESS_RW, NV_MEM_TARGET_VRAM, &obj); if (ret == 0) { diff --git a/drivers/gpu/drm/nouveau/nvd0_display.c b/drivers/gpu/drm/nouveau/nvd0_display.c index 8d9fc00718f0..715359ef9211 100644 --- a/drivers/gpu/drm/nouveau/nvd0_display.c +++ b/drivers/gpu/drm/nouveau/nvd0_display.c @@ -1903,7 +1903,7 @@ nvd0_display_init(struct drm_device *dev) } /* point at our hash table / objects, enable interrupts */ - nv_wr32(dev, 0x610010, (disp->mem->vinst >> 8) | 9); + nv_wr32(dev, 0x610010, (disp->mem->addr >> 8) | 9); nv_mask(dev, 0x6100b0, 0x00000307, 0x00000307); /* init master */ @@ -1967,7 +1967,6 @@ int nvd0_display_create(struct drm_device *dev) { struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_instmem_engine *pinstmem = &dev_priv->engine.instmem; struct dcb_table *dcb = &dev_priv->vbios.dcb; struct drm_connector *connector, *tmp; struct pci_dev *pdev = dev->pdev; @@ -2106,7 +2105,7 @@ nvd0_display_create(struct drm_device *dev) ((dmao + 0x60) << 9)); } - pinstmem->flush(dev); + nvimem_flush(dev); out: if (ret) -- cgit v1.2.3 From bc9e7b9a61e9e92ddb58920cb2cb5c2e2825ca8a Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Thu, 19 Jul 2012 17:54:21 +1000 Subject: drm/nouveau: move some more code around to more appropriate places Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/nouveau_bo.c | 111 +++++++++++- drivers/gpu/drm/nouveau/nouveau_drv.h | 6 - drivers/gpu/drm/nouveau/nouveau_mem.c | 332 ---------------------------------- drivers/gpu/drm/nouveau/nouveau_ttm.c | 229 ++++++++++++++++++++++- 4 files changed, 336 insertions(+), 342 deletions(-) (limited to 'drivers/gpu/drm/nouveau/nouveau_mem.c') diff --git a/drivers/gpu/drm/nouveau/nouveau_bo.c b/drivers/gpu/drm/nouveau/nouveau_bo.c index 9f5696a1fbb8..c3e66ae04c83 100644 --- a/drivers/gpu/drm/nouveau/nouveau_bo.c +++ b/drivers/gpu/drm/nouveau/nouveau_bo.c @@ -36,10 +36,115 @@ #include #include "nouveau_fence.h" #include +#include #include #include +/* + * NV10-NV40 tiling helpers + */ + +static void +nv10_bo_update_tile_region(struct drm_device *dev, + struct nouveau_tile_reg *tilereg, uint32_t addr, + uint32_t size, uint32_t pitch, uint32_t flags) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + int i = tilereg - dev_priv->tile.reg, j; + struct nouveau_fb_tile *tile = nvfb_tile(dev, i); + unsigned long save; + + nouveau_fence_unref(&tilereg->fence); + + if (tile->pitch) + nvfb_tile_fini(dev, i); + + if (pitch) + nvfb_tile_init(dev, i, addr, size, pitch, flags); + + spin_lock_irqsave(&dev_priv->context_switch_lock, save); + nv_wr32(dev, NV03_PFIFO_CACHES, 0); + nv04_fifo_cache_pull(dev, false); + + nouveau_wait_for_idle(dev); + + nvfb_tile_prog(dev, i); + for (j = 0; j < NVOBJ_ENGINE_NR; j++) { + if (dev_priv->eng[j] && dev_priv->eng[j]->set_tile_region) + dev_priv->eng[j]->set_tile_region(dev, i); + } + + nv04_fifo_cache_pull(dev, true); + nv_wr32(dev, NV03_PFIFO_CACHES, 1); + spin_unlock_irqrestore(&dev_priv->context_switch_lock, save); +} + +static struct nouveau_tile_reg * +nv10_bo_get_tile_region(struct drm_device *dev, int i) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_tile_reg *tile = &dev_priv->tile.reg[i]; + + spin_lock(&dev_priv->tile.lock); + + if (!tile->used && + (!tile->fence || nouveau_fence_done(tile->fence))) + tile->used = true; + else + tile = NULL; + + spin_unlock(&dev_priv->tile.lock); + return tile; +} + +static void +nv10_bo_put_tile_region(struct drm_device *dev, struct nouveau_tile_reg *tile, + struct nouveau_fence *fence) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + + if (tile) { + spin_lock(&dev_priv->tile.lock); + if (fence) { + /* Mark it as pending. */ + tile->fence = fence; + nouveau_fence_ref(fence); + } + + tile->used = false; + spin_unlock(&dev_priv->tile.lock); + } +} + +static struct nouveau_tile_reg * +nv10_bo_set_tiling(struct drm_device *dev, uint32_t addr, uint32_t size, + uint32_t pitch, uint32_t flags) +{ + struct nouveau_tile_reg *tile, *found = NULL; + int i; + + for (i = 0; i < nvfb_tile_nr(dev); i++) { + tile = nv10_bo_get_tile_region(dev, i); + + if (pitch && !found) { + found = tile; + continue; + + } else if (tile && nvfb_tile(dev, i)->pitch) { + /* Kill an unused tile region. */ + nv10_bo_update_tile_region(dev, tile, 0, 0, 0, 0); + } + + nv10_bo_put_tile_region(dev, tile, NULL); + } + + if (found) + nv10_bo_update_tile_region(dev, found, addr, size, + pitch, flags); + return found; +} + static void nouveau_bo_del_ttm(struct ttm_buffer_object *bo) { @@ -50,7 +155,7 @@ nouveau_bo_del_ttm(struct ttm_buffer_object *bo) if (unlikely(nvbo->gem)) DRM_ERROR("bo %p still attached to GEM object\n", bo); - nv10_mem_put_tile_region(dev, nvbo->tile, NULL); + nv10_bo_put_tile_region(dev, nvbo->tile, NULL); kfree(nvbo); } @@ -1075,7 +1180,7 @@ nouveau_bo_vm_bind(struct ttm_buffer_object *bo, struct ttm_mem_reg *new_mem, return 0; if (dev_priv->card_type >= NV_10) { - *new_tile = nv10_mem_set_tiling(dev, offset, new_mem->size, + *new_tile = nv10_bo_set_tiling(dev, offset, new_mem->size, nvbo->tile_mode, nvbo->tile_flags); } @@ -1091,7 +1196,7 @@ nouveau_bo_vm_cleanup(struct ttm_buffer_object *bo, struct drm_nouveau_private *dev_priv = nouveau_bdev(bo->bdev); struct drm_device *dev = dev_priv->dev; - nv10_mem_put_tile_region(dev, *old_tile, bo->sync_obj); + nv10_bo_put_tile_region(dev, *old_tile, bo->sync_obj); *old_tile = new_tile; } diff --git a/drivers/gpu/drm/nouveau/nouveau_drv.h b/drivers/gpu/drm/nouveau/nouveau_drv.h index 42ea8ad5b911..08ce60be3f3c 100644 --- a/drivers/gpu/drm/nouveau/nouveau_drv.h +++ b/drivers/gpu/drm/nouveau/nouveau_drv.h @@ -596,12 +596,6 @@ extern int nouveau_mem_timing_calc(struct drm_device *, u32 freq, extern void nouveau_mem_timing_read(struct drm_device *, struct nouveau_pm_memtiming *); extern int nouveau_mem_vbios_type(struct drm_device *); -extern struct nouveau_tile_reg *nv10_mem_set_tiling( - struct drm_device *dev, uint32_t addr, uint32_t size, - uint32_t pitch, uint32_t flags); -extern void nv10_mem_put_tile_region(struct drm_device *dev, - struct nouveau_tile_reg *tile, - struct nouveau_fence *fence); extern const struct ttm_mem_type_manager_func nouveau_vram_manager; extern const struct ttm_mem_type_manager_func nouveau_gart_manager; extern const struct ttm_mem_type_manager_func nv04_gart_manager; diff --git a/drivers/gpu/drm/nouveau/nouveau_mem.c b/drivers/gpu/drm/nouveau/nouveau_mem.c index 48131ceeeb80..73176bcd1b64 100644 --- a/drivers/gpu/drm/nouveau/nouveau_mem.c +++ b/drivers/gpu/drm/nouveau/nouveau_mem.c @@ -41,110 +41,6 @@ #include #include "nouveau_fence.h" -/* - * NV10-NV40 tiling helpers - */ - -static void -nv10_mem_update_tile_region(struct drm_device *dev, - struct nouveau_tile_reg *tilereg, uint32_t addr, - uint32_t size, uint32_t pitch, uint32_t flags) -{ - struct drm_nouveau_private *dev_priv = dev->dev_private; - int i = tilereg - dev_priv->tile.reg, j; - struct nouveau_fb_tile *tile = nvfb_tile(dev, i); - unsigned long save; - - nouveau_fence_unref(&tilereg->fence); - - if (tile->pitch) - nvfb_tile_fini(dev, i); - - if (pitch) - nvfb_tile_init(dev, i, addr, size, pitch, flags); - - spin_lock_irqsave(&dev_priv->context_switch_lock, save); - nv_wr32(dev, NV03_PFIFO_CACHES, 0); - nv04_fifo_cache_pull(dev, false); - - nouveau_wait_for_idle(dev); - - nvfb_tile_prog(dev, i); - for (j = 0; j < NVOBJ_ENGINE_NR; j++) { - if (dev_priv->eng[j] && dev_priv->eng[j]->set_tile_region) - dev_priv->eng[j]->set_tile_region(dev, i); - } - - nv04_fifo_cache_pull(dev, true); - nv_wr32(dev, NV03_PFIFO_CACHES, 1); - spin_unlock_irqrestore(&dev_priv->context_switch_lock, save); -} - -static struct nouveau_tile_reg * -nv10_mem_get_tile_region(struct drm_device *dev, int i) -{ - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_tile_reg *tile = &dev_priv->tile.reg[i]; - - spin_lock(&dev_priv->tile.lock); - - if (!tile->used && - (!tile->fence || nouveau_fence_done(tile->fence))) - tile->used = true; - else - tile = NULL; - - spin_unlock(&dev_priv->tile.lock); - return tile; -} - -void -nv10_mem_put_tile_region(struct drm_device *dev, struct nouveau_tile_reg *tile, - struct nouveau_fence *fence) -{ - struct drm_nouveau_private *dev_priv = dev->dev_private; - - if (tile) { - spin_lock(&dev_priv->tile.lock); - if (fence) { - /* Mark it as pending. */ - tile->fence = fence; - nouveau_fence_ref(fence); - } - - tile->used = false; - spin_unlock(&dev_priv->tile.lock); - } -} - -struct nouveau_tile_reg * -nv10_mem_set_tiling(struct drm_device *dev, uint32_t addr, uint32_t size, - uint32_t pitch, uint32_t flags) -{ - struct nouveau_tile_reg *tile, *found = NULL; - int i; - - for (i = 0; i < nvfb_tile_nr(dev); i++) { - tile = nv10_mem_get_tile_region(dev, i); - - if (pitch && !found) { - found = tile; - continue; - - } else if (tile && nvfb_tile(dev, i)->pitch) { - /* Kill an unused tile region. */ - nv10_mem_update_tile_region(dev, tile, 0, 0, 0, 0); - } - - nv10_mem_put_tile_region(dev, tile, NULL); - } - - if (found) - nv10_mem_update_tile_region(dev, found, addr, size, - pitch, flags); - return found; -} - /* * Cleanup everything */ @@ -897,231 +793,3 @@ nouveau_mem_vbios_type(struct drm_device *dev) } return NV_MEM_TYPE_UNKNOWN; } - -static int -nouveau_vram_manager_init(struct ttm_mem_type_manager *man, unsigned long psize) -{ - /* nothing to do */ - return 0; -} - -static int -nouveau_vram_manager_fini(struct ttm_mem_type_manager *man) -{ - /* nothing to do */ - return 0; -} - -static inline void -nouveau_mem_node_cleanup(struct nouveau_mem *node) -{ - if (node->vma[0].node) { - nouveau_vm_unmap(&node->vma[0]); - nouveau_vm_put(&node->vma[0]); - } - - if (node->vma[1].node) { - nouveau_vm_unmap(&node->vma[1]); - nouveau_vm_put(&node->vma[1]); - } -} - -static void -nouveau_vram_manager_del(struct ttm_mem_type_manager *man, - struct ttm_mem_reg *mem) -{ - struct drm_nouveau_private *dev_priv = nouveau_bdev(man->bdev); - struct drm_device *dev = dev_priv->dev; - - nouveau_mem_node_cleanup(mem->mm_node); - nvfb_vram_put(dev, (struct nouveau_mem **)&mem->mm_node); -} - -static int -nouveau_vram_manager_new(struct ttm_mem_type_manager *man, - struct ttm_buffer_object *bo, - struct ttm_placement *placement, - struct ttm_mem_reg *mem) -{ - struct drm_nouveau_private *dev_priv = nouveau_bdev(man->bdev); - struct drm_device *dev = dev_priv->dev; - struct nouveau_bo *nvbo = nouveau_bo(bo); - struct nouveau_mem *node; - u32 size_nc = 0; - int ret; - - if (nvbo->tile_flags & NOUVEAU_GEM_TILE_NONCONTIG) - size_nc = 1 << nvbo->page_shift; - - ret = nvfb_vram_get(dev, mem->num_pages << PAGE_SHIFT, - mem->page_alignment << PAGE_SHIFT, size_nc, - (nvbo->tile_flags >> 8) & 0x3ff, &node); - if (ret) { - mem->mm_node = NULL; - return (ret == -ENOSPC) ? 0 : ret; - } - - node->page_shift = nvbo->page_shift; - - mem->mm_node = node; - mem->start = node->offset >> PAGE_SHIFT; - return 0; -} - -void -nouveau_vram_manager_debug(struct ttm_mem_type_manager *man, const char *prefix) -{ - struct nouveau_mm *mm = man->priv; - struct nouveau_mm_node *r; - u32 total = 0, free = 0; - - mutex_lock(&mm->mutex); - list_for_each_entry(r, &mm->nodes, nl_entry) { - printk(KERN_DEBUG "%s %d: 0x%010llx 0x%010llx\n", - prefix, r->type, ((u64)r->offset << 12), - (((u64)r->offset + r->length) << 12)); - - total += r->length; - if (!r->type) - free += r->length; - } - mutex_unlock(&mm->mutex); - - printk(KERN_DEBUG "%s total: 0x%010llx free: 0x%010llx\n", - prefix, (u64)total << 12, (u64)free << 12); - printk(KERN_DEBUG "%s block: 0x%08x\n", - prefix, mm->block_size << 12); -} - -const struct ttm_mem_type_manager_func nouveau_vram_manager = { - nouveau_vram_manager_init, - nouveau_vram_manager_fini, - nouveau_vram_manager_new, - nouveau_vram_manager_del, - nouveau_vram_manager_debug -}; - -static int -nouveau_gart_manager_init(struct ttm_mem_type_manager *man, unsigned long psize) -{ - return 0; -} - -static int -nouveau_gart_manager_fini(struct ttm_mem_type_manager *man) -{ - return 0; -} - -static void -nouveau_gart_manager_del(struct ttm_mem_type_manager *man, - struct ttm_mem_reg *mem) -{ - nouveau_mem_node_cleanup(mem->mm_node); - kfree(mem->mm_node); - mem->mm_node = NULL; -} - -static int -nouveau_gart_manager_new(struct ttm_mem_type_manager *man, - struct ttm_buffer_object *bo, - struct ttm_placement *placement, - struct ttm_mem_reg *mem) -{ - struct drm_nouveau_private *dev_priv = nouveau_bdev(bo->bdev); - struct nouveau_mem *node; - - if (unlikely((mem->num_pages << PAGE_SHIFT) >= - dev_priv->gart_info.aper_size)) - return -ENOMEM; - - node = kzalloc(sizeof(*node), GFP_KERNEL); - if (!node) - return -ENOMEM; - node->page_shift = 12; - - mem->mm_node = node; - mem->start = 0; - return 0; -} - -void -nouveau_gart_manager_debug(struct ttm_mem_type_manager *man, const char *prefix) -{ -} - -const struct ttm_mem_type_manager_func nouveau_gart_manager = { - nouveau_gart_manager_init, - nouveau_gart_manager_fini, - nouveau_gart_manager_new, - nouveau_gart_manager_del, - nouveau_gart_manager_debug -}; - -static int -nv04_gart_manager_init(struct ttm_mem_type_manager *man, unsigned long psize) -{ - struct drm_nouveau_private *dev_priv = nouveau_bdev(man->bdev); - struct drm_device *dev = dev_priv->dev; - man->priv = nv04vm_ref(dev); - return (man->priv != NULL) ? 0 : -ENODEV; -} - -static int -nv04_gart_manager_fini(struct ttm_mem_type_manager *man) -{ - struct nouveau_vm *vm = man->priv; - nouveau_vm_ref(NULL, &vm, NULL); - man->priv = NULL; - return 0; -} - -static void -nv04_gart_manager_del(struct ttm_mem_type_manager *man, struct ttm_mem_reg *mem) -{ - struct nouveau_mem *node = mem->mm_node; - if (node->vma[0].node) - nouveau_vm_put(&node->vma[0]); - kfree(mem->mm_node); - mem->mm_node = NULL; -} - -static int -nv04_gart_manager_new(struct ttm_mem_type_manager *man, - struct ttm_buffer_object *bo, - struct ttm_placement *placement, - struct ttm_mem_reg *mem) -{ - struct nouveau_mem *node; - int ret; - - node = kzalloc(sizeof(*node), GFP_KERNEL); - if (!node) - return -ENOMEM; - - node->page_shift = 12; - - ret = nouveau_vm_get(man->priv, mem->num_pages << 12, node->page_shift, - NV_MEM_ACCESS_RW, &node->vma[0]); - if (ret) { - kfree(node); - return ret; - } - - mem->mm_node = node; - mem->start = node->vma[0].offset >> PAGE_SHIFT; - return 0; -} - -void -nv04_gart_manager_debug(struct ttm_mem_type_manager *man, const char *prefix) -{ -} - -const struct ttm_mem_type_manager_func nv04_gart_manager = { - nv04_gart_manager_init, - nv04_gart_manager_fini, - nv04_gart_manager_new, - nv04_gart_manager_del, - nv04_gart_manager_debug -}; diff --git a/drivers/gpu/drm/nouveau/nouveau_ttm.c b/drivers/gpu/drm/nouveau/nouveau_ttm.c index bd35f930568c..e729535e9b26 100644 --- a/drivers/gpu/drm/nouveau/nouveau_ttm.c +++ b/drivers/gpu/drm/nouveau/nouveau_ttm.c @@ -28,6 +28,234 @@ #include "nouveau_drv.h" +static int +nouveau_vram_manager_init(struct ttm_mem_type_manager *man, unsigned long psize) +{ + /* nothing to do */ + return 0; +} + +static int +nouveau_vram_manager_fini(struct ttm_mem_type_manager *man) +{ + /* nothing to do */ + return 0; +} + +static inline void +nouveau_mem_node_cleanup(struct nouveau_mem *node) +{ + if (node->vma[0].node) { + nouveau_vm_unmap(&node->vma[0]); + nouveau_vm_put(&node->vma[0]); + } + + if (node->vma[1].node) { + nouveau_vm_unmap(&node->vma[1]); + nouveau_vm_put(&node->vma[1]); + } +} + +static void +nouveau_vram_manager_del(struct ttm_mem_type_manager *man, + struct ttm_mem_reg *mem) +{ + struct drm_nouveau_private *dev_priv = nouveau_bdev(man->bdev); + struct drm_device *dev = dev_priv->dev; + + nouveau_mem_node_cleanup(mem->mm_node); + nvfb_vram_put(dev, (struct nouveau_mem **)&mem->mm_node); +} + +static int +nouveau_vram_manager_new(struct ttm_mem_type_manager *man, + struct ttm_buffer_object *bo, + struct ttm_placement *placement, + struct ttm_mem_reg *mem) +{ + struct drm_nouveau_private *dev_priv = nouveau_bdev(man->bdev); + struct drm_device *dev = dev_priv->dev; + struct nouveau_bo *nvbo = nouveau_bo(bo); + struct nouveau_mem *node; + u32 size_nc = 0; + int ret; + + if (nvbo->tile_flags & NOUVEAU_GEM_TILE_NONCONTIG) + size_nc = 1 << nvbo->page_shift; + + ret = nvfb_vram_get(dev, mem->num_pages << PAGE_SHIFT, + mem->page_alignment << PAGE_SHIFT, size_nc, + (nvbo->tile_flags >> 8) & 0x3ff, &node); + if (ret) { + mem->mm_node = NULL; + return (ret == -ENOSPC) ? 0 : ret; + } + + node->page_shift = nvbo->page_shift; + + mem->mm_node = node; + mem->start = node->offset >> PAGE_SHIFT; + return 0; +} + +void +nouveau_vram_manager_debug(struct ttm_mem_type_manager *man, const char *prefix) +{ + struct nouveau_mm *mm = man->priv; + struct nouveau_mm_node *r; + u32 total = 0, free = 0; + + mutex_lock(&mm->mutex); + list_for_each_entry(r, &mm->nodes, nl_entry) { + printk(KERN_DEBUG "%s %d: 0x%010llx 0x%010llx\n", + prefix, r->type, ((u64)r->offset << 12), + (((u64)r->offset + r->length) << 12)); + + total += r->length; + if (!r->type) + free += r->length; + } + mutex_unlock(&mm->mutex); + + printk(KERN_DEBUG "%s total: 0x%010llx free: 0x%010llx\n", + prefix, (u64)total << 12, (u64)free << 12); + printk(KERN_DEBUG "%s block: 0x%08x\n", + prefix, mm->block_size << 12); +} + +const struct ttm_mem_type_manager_func nouveau_vram_manager = { + nouveau_vram_manager_init, + nouveau_vram_manager_fini, + nouveau_vram_manager_new, + nouveau_vram_manager_del, + nouveau_vram_manager_debug +}; + +static int +nouveau_gart_manager_init(struct ttm_mem_type_manager *man, unsigned long psize) +{ + return 0; +} + +static int +nouveau_gart_manager_fini(struct ttm_mem_type_manager *man) +{ + return 0; +} + +static void +nouveau_gart_manager_del(struct ttm_mem_type_manager *man, + struct ttm_mem_reg *mem) +{ + nouveau_mem_node_cleanup(mem->mm_node); + kfree(mem->mm_node); + mem->mm_node = NULL; +} + +static int +nouveau_gart_manager_new(struct ttm_mem_type_manager *man, + struct ttm_buffer_object *bo, + struct ttm_placement *placement, + struct ttm_mem_reg *mem) +{ + struct drm_nouveau_private *dev_priv = nouveau_bdev(bo->bdev); + struct nouveau_mem *node; + + if (unlikely((mem->num_pages << PAGE_SHIFT) >= + dev_priv->gart_info.aper_size)) + return -ENOMEM; + + node = kzalloc(sizeof(*node), GFP_KERNEL); + if (!node) + return -ENOMEM; + node->page_shift = 12; + + mem->mm_node = node; + mem->start = 0; + return 0; +} + +void +nouveau_gart_manager_debug(struct ttm_mem_type_manager *man, const char *prefix) +{ +} + +const struct ttm_mem_type_manager_func nouveau_gart_manager = { + nouveau_gart_manager_init, + nouveau_gart_manager_fini, + nouveau_gart_manager_new, + nouveau_gart_manager_del, + nouveau_gart_manager_debug +}; + +static int +nv04_gart_manager_init(struct ttm_mem_type_manager *man, unsigned long psize) +{ + struct drm_nouveau_private *dev_priv = nouveau_bdev(man->bdev); + struct drm_device *dev = dev_priv->dev; + man->priv = nv04vm_ref(dev); + return (man->priv != NULL) ? 0 : -ENODEV; +} + +static int +nv04_gart_manager_fini(struct ttm_mem_type_manager *man) +{ + struct nouveau_vm *vm = man->priv; + nouveau_vm_ref(NULL, &vm, NULL); + man->priv = NULL; + return 0; +} + +static void +nv04_gart_manager_del(struct ttm_mem_type_manager *man, struct ttm_mem_reg *mem) +{ + struct nouveau_mem *node = mem->mm_node; + if (node->vma[0].node) + nouveau_vm_put(&node->vma[0]); + kfree(mem->mm_node); + mem->mm_node = NULL; +} + +static int +nv04_gart_manager_new(struct ttm_mem_type_manager *man, + struct ttm_buffer_object *bo, + struct ttm_placement *placement, + struct ttm_mem_reg *mem) +{ + struct nouveau_mem *node; + int ret; + + node = kzalloc(sizeof(*node), GFP_KERNEL); + if (!node) + return -ENOMEM; + + node->page_shift = 12; + + ret = nouveau_vm_get(man->priv, mem->num_pages << 12, node->page_shift, + NV_MEM_ACCESS_RW, &node->vma[0]); + if (ret) { + kfree(node); + return ret; + } + + mem->mm_node = node; + mem->start = node->vma[0].offset >> PAGE_SHIFT; + return 0; +} + +void +nv04_gart_manager_debug(struct ttm_mem_type_manager *man, const char *prefix) +{ +} + +const struct ttm_mem_type_manager_func nv04_gart_manager = { + nv04_gart_manager_init, + nv04_gart_manager_fini, + nv04_gart_manager_new, + nv04_gart_manager_del, + nv04_gart_manager_debug +}; + int nouveau_ttm_mmap(struct file *filp, struct vm_area_struct *vma) { @@ -100,4 +328,3 @@ nouveau_ttm_global_release(struct drm_nouveau_private *dev_priv) drm_global_item_unref(&dev_priv->ttm.mem_global_ref); dev_priv->ttm.mem_global_ref.release = NULL; } - -- cgit v1.2.3 From ebb945a94bba2ce8dff7b0942ff2b3f2a52a0a69 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Fri, 20 Jul 2012 08:17:34 +1000 Subject: drm/nouveau: port all engines to new engine module format This is a HUGE commit, but it's not nearly as bad as it looks - any problems can be isolated to a particular chipset and engine combination. It was simply too difficult to port each one at a time, the compat layers are *already* ridiculous. Most of the changes here are simply to the glue, the process for each of the engine modules was to start with a standard skeleton and copy+paste the old code into the appropriate places, fixing up variable names etc as needed. v2: Marcin Slusarz - fix find/replace bug in license header v3: Ben Skeggs - bump indirect pushbuf size to 8KiB, 4KiB barely enough for userspace and left no space for kernel's requirements during GEM pushbuf submission. - fix duplicate assignments noticed by clang v4: Marcin Slusarz - add sparse annotations to nv04_fifo_pause/nv04_fifo_start - use ioread32_native/iowrite32_native for fifo control registers v5: Ben Skeggs - rebase on v3.6-rc4, modified to keep copy engine fix intact - nv10/fence: unmap fence bo before destroying - fixed fermi regression when using nvidia gr fuc - fixed typo in supported dma_mask checking Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/Makefile | 99 +- drivers/gpu/drm/nouveau/core/core/ramht.c | 297 +---- drivers/gpu/drm/nouveau/core/engine/bsp/nv84.c | 157 ++- drivers/gpu/drm/nouveau/core/engine/copy/nva3.c | 268 ++-- drivers/gpu/drm/nouveau/core/engine/copy/nvc0.c | 350 +++--- drivers/gpu/drm/nouveau/core/engine/crypt/nv84.c | 252 ++-- drivers/gpu/drm/nouveau/core/engine/crypt/nv98.c | 255 ++-- drivers/gpu/drm/nouveau/core/engine/disp/nv04.c | 90 ++ drivers/gpu/drm/nouveau/core/engine/disp/nv50.c | 125 ++ drivers/gpu/drm/nouveau/core/engine/disp/nvd0.c | 118 ++ drivers/gpu/drm/nouveau/core/engine/dmaobj/base.c | 87 ++ drivers/gpu/drm/nouveau/core/engine/dmaobj/nv04.c | 176 +++ drivers/gpu/drm/nouveau/core/engine/dmaobj/nv50.c | 168 +++ drivers/gpu/drm/nouveau/core/engine/dmaobj/nvc0.c | 99 ++ drivers/gpu/drm/nouveau/core/engine/fifo/base.c | 165 +++ drivers/gpu/drm/nouveau/core/engine/fifo/nv04.c | 736 ++++++----- drivers/gpu/drm/nouveau/core/engine/fifo/nv04.h | 178 +++ drivers/gpu/drm/nouveau/core/engine/fifo/nv10.c | 228 ++-- drivers/gpu/drm/nouveau/core/engine/fifo/nv17.c | 279 +++-- drivers/gpu/drm/nouveau/core/engine/fifo/nv40.c | 394 ++++-- drivers/gpu/drm/nouveau/core/engine/fifo/nv50.c | 554 +++++--- drivers/gpu/drm/nouveau/core/engine/fifo/nv50.h | 36 + drivers/gpu/drm/nouveau/core/engine/fifo/nv84.c | 490 +++++--- drivers/gpu/drm/nouveau/core/engine/fifo/nvc0.c | 604 +++++---- drivers/gpu/drm/nouveau/core/engine/fifo/nve0.c | 594 +++++---- drivers/gpu/drm/nouveau/core/engine/graph/ctx.h | 26 +- .../gpu/drm/nouveau/core/engine/graph/ctxnv40.c | 131 +- .../gpu/drm/nouveau/core/engine/graph/ctxnv50.c | 559 ++++----- .../gpu/drm/nouveau/core/engine/graph/ctxnvc0.c | 202 ++- .../gpu/drm/nouveau/core/engine/graph/ctxnve0.c | 94 +- drivers/gpu/drm/nouveau/core/engine/graph/nv04.c | 1325 ++++++++++---------- drivers/gpu/drm/nouveau/core/engine/graph/nv10.c | 1053 +++++++++------- drivers/gpu/drm/nouveau/core/engine/graph/nv20.c | 1072 +++++----------- drivers/gpu/drm/nouveau/core/engine/graph/nv20.h | 31 + drivers/gpu/drm/nouveau/core/engine/graph/nv25.c | 167 +++ drivers/gpu/drm/nouveau/core/engine/graph/nv2a.c | 134 ++ drivers/gpu/drm/nouveau/core/engine/graph/nv30.c | 238 ++++ drivers/gpu/drm/nouveau/core/engine/graph/nv34.c | 168 +++ drivers/gpu/drm/nouveau/core/engine/graph/nv35.c | 166 +++ drivers/gpu/drm/nouveau/core/engine/graph/nv40.c | 681 +++++----- drivers/gpu/drm/nouveau/core/engine/graph/nv40.h | 21 + drivers/gpu/drm/nouveau/core/engine/graph/nv50.c | 907 +++++++------- drivers/gpu/drm/nouveau/core/engine/graph/nv50.h | 7 + drivers/gpu/drm/nouveau/core/engine/graph/nvc0.c | 1074 ++++++++-------- drivers/gpu/drm/nouveau/core/engine/graph/nvc0.h | 43 +- drivers/gpu/drm/nouveau/core/engine/graph/nve0.c | 843 ++++++------- drivers/gpu/drm/nouveau/core/engine/graph/regs.h | 269 ++++ drivers/gpu/drm/nouveau/core/engine/mpeg/nv31.c | 448 +++---- drivers/gpu/drm/nouveau/core/engine/mpeg/nv40.c | 144 +++ drivers/gpu/drm/nouveau/core/engine/mpeg/nv50.c | 305 ++--- drivers/gpu/drm/nouveau/core/engine/mpeg/nv84.c | 104 ++ drivers/gpu/drm/nouveau/core/engine/ppp/nv98.c | 154 ++- .../gpu/drm/nouveau/core/engine/software/nv04.c | 140 +++ .../gpu/drm/nouveau/core/engine/software/nv10.c | 128 ++ .../gpu/drm/nouveau/core/engine/software/nv50.c | 198 +++ .../gpu/drm/nouveau/core/engine/software/nvc0.c | 180 +++ drivers/gpu/drm/nouveau/core/engine/vp/nv84.c | 157 ++- drivers/gpu/drm/nouveau/core/include/core/ramht.h | 56 +- drivers/gpu/drm/nouveau/core/include/engine/bsp.h | 45 + drivers/gpu/drm/nouveau/core/include/engine/copy.h | 47 + .../gpu/drm/nouveau/core/include/engine/crypt.h | 46 + drivers/gpu/drm/nouveau/core/include/engine/disp.h | 44 + .../gpu/drm/nouveau/core/include/engine/dmaobj.h | 57 + drivers/gpu/drm/nouveau/core/include/engine/fifo.h | 123 +- .../gpu/drm/nouveau/core/include/engine/graph.h | 72 ++ drivers/gpu/drm/nouveau/core/include/engine/mpeg.h | 61 + drivers/gpu/drm/nouveau/core/include/engine/ppp.h | 45 + .../gpu/drm/nouveau/core/include/engine/software.h | 58 + drivers/gpu/drm/nouveau/core/include/engine/vp.h | 45 + .../gpu/drm/nouveau/core/include/subdev/device.h | 1 - .../gpu/drm/nouveau/core/include/subdev/instmem.h | 1 - drivers/gpu/drm/nouveau/core/include/subdev/vm.h | 1 + drivers/gpu/drm/nouveau/core/subdev/device/base.c | 33 +- drivers/gpu/drm/nouveau/core/subdev/device/nv04.c | 16 + drivers/gpu/drm/nouveau/core/subdev/device/nv10.c | 44 + drivers/gpu/drm/nouveau/core/subdev/device/nv20.c | 26 + drivers/gpu/drm/nouveau/core/subdev/device/nv30.c | 35 + drivers/gpu/drm/nouveau/core/subdev/device/nv40.c | 103 ++ drivers/gpu/drm/nouveau/core/subdev/device/nv50.c | 136 ++ drivers/gpu/drm/nouveau/core/subdev/device/nvc0.c | 89 ++ drivers/gpu/drm/nouveau/core/subdev/device/nve0.c | 16 + drivers/gpu/drm/nouveau/core/subdev/instmem/nv04.c | 5 +- drivers/gpu/drm/nouveau/core/subdev/instmem/nv04.h | 9 +- drivers/gpu/drm/nouveau/core/subdev/instmem/nv40.c | 3 +- drivers/gpu/drm/nouveau/core/subdev/vm/base.c | 1 + drivers/gpu/drm/nouveau/core/subdev/vm/nv04.c | 1 + drivers/gpu/drm/nouveau/core/subdev/vm/nv04.h | 6 + drivers/gpu/drm/nouveau/core/subdev/vm/nv41.c | 1 + drivers/gpu/drm/nouveau/core/subdev/vm/nv44.c | 1 + drivers/gpu/drm/nouveau/core/subdev/vm/nv50.c | 7 +- drivers/gpu/drm/nouveau/core/subdev/vm/nvc0.c | 1 + drivers/gpu/drm/nouveau/nouveau_abi16.c | 421 +++++-- drivers/gpu/drm/nouveau/nouveau_abi16.h | 32 + drivers/gpu/drm/nouveau/nouveau_acpi.c | 1 - drivers/gpu/drm/nouveau/nouveau_bo.c | 347 +++-- drivers/gpu/drm/nouveau/nouveau_bo.h | 19 +- drivers/gpu/drm/nouveau/nouveau_chan.c | 387 ++++++ drivers/gpu/drm/nouveau/nouveau_chan.h | 47 + drivers/gpu/drm/nouveau/nouveau_channel.c | 408 ------ drivers/gpu/drm/nouveau/nouveau_compat.c | 28 +- drivers/gpu/drm/nouveau/nouveau_compat.h | 14 + drivers/gpu/drm/nouveau/nouveau_debugfs.c | 195 --- drivers/gpu/drm/nouveau/nouveau_display.c | 51 +- drivers/gpu/drm/nouveau/nouveau_dma.c | 56 +- drivers/gpu/drm/nouveau/nouveau_dma.h | 51 +- drivers/gpu/drm/nouveau/nouveau_drm.c | 211 +++- drivers/gpu/drm/nouveau/nouveau_drm.h | 68 + drivers/gpu/drm/nouveau/nouveau_drv.c | 86 +- drivers/gpu/drm/nouveau/nouveau_drv.h | 407 +----- drivers/gpu/drm/nouveau/nouveau_fbcon.c | 225 ++-- drivers/gpu/drm/nouveau/nouveau_fbcon.h | 1 + drivers/gpu/drm/nouveau/nouveau_fence.c | 23 +- drivers/gpu/drm/nouveau/nouveau_fence.h | 24 +- drivers/gpu/drm/nouveau/nouveau_gem.c | 170 +-- drivers/gpu/drm/nouveau/nouveau_gpuobj.c | 518 -------- drivers/gpu/drm/nouveau/nouveau_irq.c | 1 - drivers/gpu/drm/nouveau/nouveau_mem.c | 140 --- drivers/gpu/drm/nouveau/nouveau_notifier.c | 151 --- drivers/gpu/drm/nouveau/nouveau_prime.c | 1 - drivers/gpu/drm/nouveau/nouveau_revcompat.c | 22 + drivers/gpu/drm/nouveau/nouveau_revcompat.h | 12 + drivers/gpu/drm/nouveau/nouveau_sgdma.c | 68 +- drivers/gpu/drm/nouveau/nouveau_software.h | 60 - drivers/gpu/drm/nouveau/nouveau_state.c | 391 +----- drivers/gpu/drm/nouveau/nouveau_ttm.c | 163 ++- drivers/gpu/drm/nouveau/nouveau_ttm.h | 21 + drivers/gpu/drm/nouveau/nouveau_util.c | 39 - drivers/gpu/drm/nouveau/nouveau_util.h | 35 - drivers/gpu/drm/nouveau/nv04_display.c | 22 - drivers/gpu/drm/nouveau/nv04_fbcon.c | 70 +- drivers/gpu/drm/nouveau/nv04_fence.c | 37 +- drivers/gpu/drm/nouveau/nv04_software.c | 139 -- drivers/gpu/drm/nouveau/nv10_fence.c | 63 +- drivers/gpu/drm/nouveau/nv40_pm.c | 3 +- drivers/gpu/drm/nouveau/nv50_display.c | 55 +- drivers/gpu/drm/nouveau/nv50_display.h | 6 +- drivers/gpu/drm/nouveau/nv50_evo.c | 174 ++- drivers/gpu/drm/nouveau/nv50_fbcon.c | 36 +- drivers/gpu/drm/nouveau/nv50_fence.c | 75 +- drivers/gpu/drm/nouveau/nv50_pm.c | 1 - drivers/gpu/drm/nouveau/nv50_software.c | 181 --- drivers/gpu/drm/nouveau/nv84_fence.c | 106 +- drivers/gpu/drm/nouveau/nvc0_fbcon.c | 31 +- drivers/gpu/drm/nouveau/nvc0_fence.c | 102 +- drivers/gpu/drm/nouveau/nvc0_software.c | 109 -- drivers/gpu/drm/nouveau/nvd0_display.c | 11 +- 146 files changed, 14219 insertions(+), 11099 deletions(-) create mode 100644 drivers/gpu/drm/nouveau/core/engine/disp/nv04.c create mode 100644 drivers/gpu/drm/nouveau/core/engine/disp/nv50.c create mode 100644 drivers/gpu/drm/nouveau/core/engine/disp/nvd0.c create mode 100644 drivers/gpu/drm/nouveau/core/engine/dmaobj/base.c create mode 100644 drivers/gpu/drm/nouveau/core/engine/dmaobj/nv04.c create mode 100644 drivers/gpu/drm/nouveau/core/engine/dmaobj/nv50.c create mode 100644 drivers/gpu/drm/nouveau/core/engine/dmaobj/nvc0.c create mode 100644 drivers/gpu/drm/nouveau/core/engine/fifo/base.c create mode 100644 drivers/gpu/drm/nouveau/core/engine/fifo/nv04.h create mode 100644 drivers/gpu/drm/nouveau/core/engine/fifo/nv50.h create mode 100644 drivers/gpu/drm/nouveau/core/engine/graph/nv20.h create mode 100644 drivers/gpu/drm/nouveau/core/engine/graph/nv25.c create mode 100644 drivers/gpu/drm/nouveau/core/engine/graph/nv2a.c create mode 100644 drivers/gpu/drm/nouveau/core/engine/graph/nv30.c create mode 100644 drivers/gpu/drm/nouveau/core/engine/graph/nv34.c create mode 100644 drivers/gpu/drm/nouveau/core/engine/graph/nv35.c create mode 100644 drivers/gpu/drm/nouveau/core/engine/graph/nv40.h create mode 100644 drivers/gpu/drm/nouveau/core/engine/graph/nv50.h create mode 100644 drivers/gpu/drm/nouveau/core/engine/graph/regs.h create mode 100644 drivers/gpu/drm/nouveau/core/engine/mpeg/nv40.c create mode 100644 drivers/gpu/drm/nouveau/core/engine/mpeg/nv84.c create mode 100644 drivers/gpu/drm/nouveau/core/engine/software/nv04.c create mode 100644 drivers/gpu/drm/nouveau/core/engine/software/nv10.c create mode 100644 drivers/gpu/drm/nouveau/core/engine/software/nv50.c create mode 100644 drivers/gpu/drm/nouveau/core/engine/software/nvc0.c create mode 100644 drivers/gpu/drm/nouveau/core/include/engine/bsp.h create mode 100644 drivers/gpu/drm/nouveau/core/include/engine/copy.h create mode 100644 drivers/gpu/drm/nouveau/core/include/engine/crypt.h create mode 100644 drivers/gpu/drm/nouveau/core/include/engine/disp.h create mode 100644 drivers/gpu/drm/nouveau/core/include/engine/dmaobj.h create mode 100644 drivers/gpu/drm/nouveau/core/include/engine/graph.h create mode 100644 drivers/gpu/drm/nouveau/core/include/engine/mpeg.h create mode 100644 drivers/gpu/drm/nouveau/core/include/engine/ppp.h create mode 100644 drivers/gpu/drm/nouveau/core/include/engine/software.h create mode 100644 drivers/gpu/drm/nouveau/core/include/engine/vp.h create mode 100644 drivers/gpu/drm/nouveau/nouveau_chan.c create mode 100644 drivers/gpu/drm/nouveau/nouveau_chan.h delete mode 100644 drivers/gpu/drm/nouveau/nouveau_channel.c delete mode 100644 drivers/gpu/drm/nouveau/nouveau_debugfs.c delete mode 100644 drivers/gpu/drm/nouveau/nouveau_gpuobj.c delete mode 100644 drivers/gpu/drm/nouveau/nouveau_notifier.c create mode 100644 drivers/gpu/drm/nouveau/nouveau_revcompat.c create mode 100644 drivers/gpu/drm/nouveau/nouveau_revcompat.h delete mode 100644 drivers/gpu/drm/nouveau/nouveau_software.h create mode 100644 drivers/gpu/drm/nouveau/nouveau_ttm.h delete mode 100644 drivers/gpu/drm/nouveau/nouveau_util.c delete mode 100644 drivers/gpu/drm/nouveau/nouveau_util.h delete mode 100644 drivers/gpu/drm/nouveau/nv04_software.c delete mode 100644 drivers/gpu/drm/nouveau/nv50_software.c delete mode 100644 drivers/gpu/drm/nouveau/nvc0_software.c (limited to 'drivers/gpu/drm/nouveau/nouveau_mem.c') diff --git a/drivers/gpu/drm/nouveau/Makefile b/drivers/gpu/drm/nouveau/Makefile index 1855699a1ef1..d8f3ad4285d2 100644 --- a/drivers/gpu/drm/nouveau/Makefile +++ b/drivers/gpu/drm/nouveau/Makefile @@ -4,9 +4,11 @@ ccflags-y := -Iinclude/drm -DCONFIG_NOUVEAU_DEBUG=7 -DCONFIG_NOUVEAU_DEBUG_DEFAULT=3 ccflags-y += -I$(src)/core/include +ccflags-y += -I$(src)/core ccflags-y += -I$(src) nouveau-y := core/core/client.o +nouveau-y += core/core/engctx.o nouveau-y += core/core/engine.o nouveau-y += core/core/enum.o nouveau-y += core/core/gpuobj.o @@ -90,12 +92,20 @@ nouveau-y += core/subdev/vm/nv44.o nouveau-y += core/subdev/vm/nv50.o nouveau-y += core/subdev/vm/nvc0.o +nouveau-y += core/engine/dmaobj/base.o +nouveau-y += core/engine/dmaobj/nv04.o +nouveau-y += core/engine/dmaobj/nv50.o +nouveau-y += core/engine/dmaobj/nvc0.o nouveau-y += core/engine/bsp/nv84.o 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/nv04.o +nouveau-y += core/engine/disp/nv50.o +nouveau-y += core/engine/disp/nvd0.o nouveau-y += core/engine/disp/vga.o +nouveau-y += core/engine/fifo/base.o nouveau-y += core/engine/fifo/nv04.o nouveau-y += core/engine/fifo/nv10.o nouveau-y += core/engine/fifo/nv17.o @@ -111,41 +121,82 @@ nouveau-y += core/engine/graph/ctxnve0.o nouveau-y += core/engine/graph/nv04.o nouveau-y += core/engine/graph/nv10.o nouveau-y += core/engine/graph/nv20.o +nouveau-y += core/engine/graph/nv25.o +nouveau-y += core/engine/graph/nv2a.o +nouveau-y += core/engine/graph/nv30.o +nouveau-y += core/engine/graph/nv34.o +nouveau-y += core/engine/graph/nv35.o nouveau-y += core/engine/graph/nv40.o nouveau-y += core/engine/graph/nv50.o nouveau-y += core/engine/graph/nvc0.o nouveau-y += core/engine/graph/nve0.o nouveau-y += core/engine/mpeg/nv31.o +nouveau-y += core/engine/mpeg/nv40.o nouveau-y += core/engine/mpeg/nv50.o +nouveau-y += core/engine/mpeg/nv84.o nouveau-y += core/engine/ppp/nv98.o +nouveau-y += core/engine/software/nv04.o +nouveau-y += core/engine/software/nv10.o +nouveau-y += core/engine/software/nv50.o +nouveau-y += core/engine/software/nvc0.o nouveau-y += core/engine/vp/nv84.o -nouveau-y += nouveau_drm.o nouveau_compat.o \ - nouveau_drv.o nouveau_state.o nouveau_channel.o nouveau_mem.o \ - nouveau_gpuobj.o nouveau_irq.o nouveau_notifier.o \ - nouveau_sgdma.o nouveau_dma.o nouveau_util.o \ - nouveau_bo.o nouveau_fence.o nouveau_gem.o nouveau_ttm.o \ - nouveau_hw.o nouveau_calc.o \ - nouveau_display.o nouveau_connector.o nouveau_fbcon.o \ - nouveau_hdmi.o nouveau_dp.o \ - nouveau_pm.o nouveau_volt.o nouveau_perf.o nouveau_temp.o \ - nouveau_mxm.o nouveau_agp.o \ - nouveau_abi16.o \ - nouveau_bios.o \ - nv04_fence.o nv10_fence.o nv50_fence.o nv84_fence.o nvc0_fence.o \ - nv04_software.o nv50_software.o nvc0_software.o \ - nv04_dac.o nv04_dfp.o nv04_tv.o nv17_tv.o nv17_tv_modes.o \ - nv04_crtc.o nv04_display.o nv04_cursor.o \ - nv50_evo.o nv50_crtc.o nv50_dac.o nv50_sor.o \ - nv50_cursor.o nv50_display.o \ - nvd0_display.o \ - nv04_fbcon.o nv50_fbcon.o nvc0_fbcon.o \ - nv04_pm.o nv40_pm.o nv50_pm.o nva3_pm.o nvc0_pm.o \ - nouveau_prime.o - -nouveau-$(CONFIG_DRM_NOUVEAU_DEBUG) += nouveau_debugfs.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_ttm.o nouveau_sgdma.o nouveau_bo.o nouveau_gem.o + +nouveau-y += 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- + +## +## 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_mxm.o nouveau_bios.o + +# drm/kms/common +nouveau-y += nouveau_display.o nouveau_connector.o +nouveau-y += nouveau_hdmi.o nouveau_dp.o + +# drm/kms/nv04:nv50 +nouveau-y += nouveau_hw.o nouveau_calc.o +nouveau-y += nv04_dac.o nv04_dfp.o nv04_tv.o nv17_tv.o nv17_tv_modes.o +nouveau-y += nv04_crtc.o nv04_display.o nv04_cursor.o + +# drm/kms/nv50- +nouveau-y += nv50_display.o nvd0_display.o +nouveau-y += nv50_crtc.o nv50_dac.o nv50_sor.o nv50_cursor.o +nouveau-y += nv50_evo.o + +# drm/pm +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 + +# optional stuff nouveau-$(CONFIG_COMPAT) += nouveau_ioc32.o nouveau-$(CONFIG_DRM_NOUVEAU_BACKLIGHT) += nouveau_backlight.o nouveau-$(CONFIG_ACPI) += nouveau_acpi.o + obj-$(CONFIG_DRM_NOUVEAU)+= nouveau.o diff --git a/drivers/gpu/drm/nouveau/core/core/ramht.c b/drivers/gpu/drm/nouveau/core/core/ramht.c index 5c22864fbd2c..86a64045dd60 100644 --- a/drivers/gpu/drm/nouveau/core/core/ramht.c +++ b/drivers/gpu/drm/nouveau/core/core/ramht.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"), @@ -18,289 +18,92 @@ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: Ben Skeggs */ -#include "drmP.h" - -#include "nouveau_drv.h" +#include #include +#include + +#include static u32 -nouveau_ramht_hash_handle(struct nouveau_channel *chan, u32 handle) +nouveau_ramht_hash(struct nouveau_ramht *ramht, int chid, u32 handle) { - struct drm_device *dev = chan->dev; - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_ramht *ramht = chan->ramht; u32 hash = 0; - int i; - NV_DEBUG(dev, "ch%d handle=0x%08x\n", chan->id, handle); - - for (i = 32; i > 0; i -= ramht->bits) { + while (handle) { hash ^= (handle & ((1 << ramht->bits) - 1)); handle >>= ramht->bits; } - if (dev_priv->card_type < NV_50) - hash ^= chan->id << (ramht->bits - 4); - hash <<= 3; - - NV_DEBUG(dev, "hash=0x%08x\n", hash); + hash ^= chid << (ramht->bits - 4); + hash = hash << 3; return hash; } -static int -nouveau_ramht_entry_valid(struct drm_device *dev, struct nouveau_gpuobj *ramht, - u32 offset) -{ - struct drm_nouveau_private *dev_priv = dev->dev_private; - u32 ctx = nv_ro32(ramht, offset + 4); - - if (dev_priv->card_type < NV_40) - return ((ctx & NV_RAMHT_CONTEXT_VALID) != 0); - return (ctx != 0); -} - -static int -nouveau_ramht_entry_same_channel(struct nouveau_channel *chan, - struct nouveau_gpuobj *ramht, u32 offset) -{ - struct drm_nouveau_private *dev_priv = chan->dev->dev_private; - u32 ctx = nv_ro32(ramht, offset + 4); - - if (dev_priv->card_type >= NV_50) - return true; - else if (dev_priv->card_type >= NV_40) - return chan->id == - ((ctx >> NV40_RAMHT_CONTEXT_CHANNEL_SHIFT) & 0x1f); - else - return chan->id == - ((ctx >> NV_RAMHT_CONTEXT_CHANNEL_SHIFT) & 0x1f); -} - int -nouveau_ramht_insert(struct nouveau_channel *chan, u32 handle, - struct nouveau_gpuobj *gpuobj) +nouveau_ramht_insert(struct nouveau_ramht *ramht, int chid, + u32 handle, u32 context) { - struct drm_device *dev = chan->dev; - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_ramht_entry *entry; - struct nouveau_gpuobj *ramht = chan->ramht->gpuobj; - unsigned long flags; - u32 ctx, co, ho; - - if (nouveau_ramht_find(chan, handle)) - return -EEXIST; - - entry = kmalloc(sizeof(*entry), GFP_KERNEL); - if (!entry) - return -ENOMEM; - entry->channel = chan; - entry->gpuobj = NULL; - entry->handle = handle; - nouveau_gpuobj_ref(gpuobj, &entry->gpuobj); - - if (dev_priv->card_type < NV_40) { - ctx = NV_RAMHT_CONTEXT_VALID | (gpuobj->addr >> 4) | - (chan->id << NV_RAMHT_CONTEXT_CHANNEL_SHIFT) | - (gpuobj->engine << NV_RAMHT_CONTEXT_ENGINE_SHIFT); - } else - if (dev_priv->card_type < NV_50) { - ctx = (gpuobj->addr >> 4) | - (chan->id << NV40_RAMHT_CONTEXT_CHANNEL_SHIFT) | - (gpuobj->engine << NV40_RAMHT_CONTEXT_ENGINE_SHIFT); - } else { - if (gpuobj->engine == NVOBJ_ENGINE_DISPLAY) { - ctx = (gpuobj->node->offset << 10) | - (chan->id << 28) | - chan->id; /* HASH_TAG */ - } else { - ctx = (gpuobj->node->offset >> 4) | - ((gpuobj->engine << - NV40_RAMHT_CONTEXT_ENGINE_SHIFT)); - } - } - - spin_lock_irqsave(&chan->ramht->lock, flags); - list_add(&entry->head, &chan->ramht->entries); + struct nouveau_bar *bar = nouveau_bar(ramht); + u32 co, ho; - co = ho = nouveau_ramht_hash_handle(chan, handle); + co = ho = nouveau_ramht_hash(ramht, chid, handle); do { - if (!nouveau_ramht_entry_valid(dev, ramht, co)) { - NV_DEBUG(dev, - "insert ch%d 0x%08x: h=0x%08x, c=0x%08x\n", - chan->id, co, handle, ctx); + if (!nv_ro32(ramht, co + 4)) { nv_wo32(ramht, co + 0, handle); - nv_wo32(ramht, co + 4, ctx); - - spin_unlock_irqrestore(&chan->ramht->lock, flags); - nvimem_flush(dev); - return 0; + nv_wo32(ramht, co + 4, context); + if (bar) + bar->flush(bar); + return co; } - NV_DEBUG(dev, "collision ch%d 0x%08x: h=0x%08x\n", - chan->id, co, nv_ro32(ramht, co)); co += 8; - if (co >= ramht->size) + if (co >= nv_gpuobj(ramht)->size) co = 0; } while (co != ho); - NV_ERROR(dev, "RAMHT space exhausted. ch=%d\n", chan->id); - list_del(&entry->head); - spin_unlock_irqrestore(&chan->ramht->lock, flags); - kfree(entry); return -ENOMEM; } -static struct nouveau_ramht_entry * -nouveau_ramht_remove_entry(struct nouveau_channel *chan, u32 handle) -{ - struct nouveau_ramht *ramht = chan ? chan->ramht : NULL; - struct nouveau_ramht_entry *entry; - unsigned long flags; - - if (!ramht) - return NULL; - - spin_lock_irqsave(&ramht->lock, flags); - list_for_each_entry(entry, &ramht->entries, head) { - if (entry->channel == chan && - (!handle || entry->handle == handle)) { - list_del(&entry->head); - spin_unlock_irqrestore(&ramht->lock, flags); - - return entry; - } - } - spin_unlock_irqrestore(&ramht->lock, flags); - - return NULL; -} - -static void -nouveau_ramht_remove_hash(struct nouveau_channel *chan, u32 handle) -{ - struct drm_device *dev = chan->dev; - struct nouveau_gpuobj *ramht = chan->ramht->gpuobj; - unsigned long flags; - u32 co, ho; - - spin_lock_irqsave(&chan->ramht->lock, flags); - co = ho = nouveau_ramht_hash_handle(chan, handle); - do { - if (nouveau_ramht_entry_valid(dev, ramht, co) && - nouveau_ramht_entry_same_channel(chan, ramht, co) && - (handle == nv_ro32(ramht, co))) { - NV_DEBUG(dev, - "remove ch%d 0x%08x: h=0x%08x, c=0x%08x\n", - chan->id, co, handle, nv_ro32(ramht, co + 4)); - nv_wo32(ramht, co + 0, 0x00000000); - nv_wo32(ramht, co + 4, 0x00000000); - nvimem_flush(dev); - goto out; - } - - co += 8; - if (co >= ramht->size) - co = 0; - } while (co != ho); - - NV_ERROR(dev, "RAMHT entry not found. ch=%d, handle=0x%08x\n", - chan->id, handle); -out: - spin_unlock_irqrestore(&chan->ramht->lock, flags); -} - -int -nouveau_ramht_remove(struct nouveau_channel *chan, u32 handle) +void +nouveau_ramht_remove(struct nouveau_ramht *ramht, int cookie) { - struct nouveau_ramht_entry *entry; - - entry = nouveau_ramht_remove_entry(chan, handle); - if (!entry) - return -ENOENT; - - nouveau_ramht_remove_hash(chan, entry->handle); - nouveau_gpuobj_ref(NULL, &entry->gpuobj); - kfree(entry); - return 0; + struct nouveau_bar *bar = nouveau_bar(ramht); + nv_wo32(ramht, cookie + 0, 0x00000000); + nv_wo32(ramht, cookie + 4, 0x00000000); + if (bar) + bar->flush(bar); } -struct nouveau_gpuobj * -nouveau_ramht_find(struct nouveau_channel *chan, u32 handle) -{ - struct nouveau_ramht *ramht = chan->ramht; - struct nouveau_ramht_entry *entry; - struct nouveau_gpuobj *gpuobj = NULL; - unsigned long flags; - - if (unlikely(!chan->ramht)) - return NULL; - - spin_lock_irqsave(&ramht->lock, flags); - list_for_each_entry(entry, &chan->ramht->entries, head) { - if (entry->channel == chan && entry->handle == handle) { - gpuobj = entry->gpuobj; - break; - } - } - spin_unlock_irqrestore(&ramht->lock, flags); - - return gpuobj; -} +static struct nouveau_oclass +nouveau_ramht_oclass = { + .handle = 0x0000abcd, + .ofuncs = &(struct nouveau_ofuncs) { + .ctor = NULL, + .dtor = _nouveau_gpuobj_dtor, + .init = _nouveau_gpuobj_init, + .fini = _nouveau_gpuobj_fini, + .rd32 = _nouveau_gpuobj_rd32, + .wr32 = _nouveau_gpuobj_wr32, + }, +}; int -nouveau_ramht_new(struct drm_device *dev, struct nouveau_gpuobj *gpuobj, - struct nouveau_ramht **pramht) +nouveau_ramht_new(struct nouveau_object *parent, struct nouveau_object *pargpu, + u32 size, u32 align, struct nouveau_ramht **pramht) { struct nouveau_ramht *ramht; + int ret; - ramht = kzalloc(sizeof(*ramht), GFP_KERNEL); - if (!ramht) - return -ENOMEM; - - ramht->dev = dev; - kref_init(&ramht->refcount); - ramht->bits = drm_order(gpuobj->size / 8); - INIT_LIST_HEAD(&ramht->entries); - spin_lock_init(&ramht->lock); - nouveau_gpuobj_ref(gpuobj, &ramht->gpuobj); - + ret = nouveau_gpuobj_create(parent, parent->engine ? + parent->engine : parent, /* gpuobj); - kfree(ramht); -} - -void -nouveau_ramht_ref(struct nouveau_ramht *ref, struct nouveau_ramht **ptr, - struct nouveau_channel *chan) -{ - struct nouveau_ramht_entry *entry; - struct nouveau_ramht *ramht; - - if (ref) - kref_get(&ref->refcount); - - ramht = *ptr; - if (ramht) { - while ((entry = nouveau_ramht_remove_entry(chan, 0))) { - nouveau_ramht_remove_hash(chan, entry->handle); - nouveau_gpuobj_ref(NULL, &entry->gpuobj); - kfree(entry); - } - - kref_put(&ramht->refcount, nouveau_ramht_del); - } - *ptr = ref; + ramht->bits = log2i(nv_gpuobj(ramht)->size >> 3); + return 0; } diff --git a/drivers/gpu/drm/nouveau/core/engine/bsp/nv84.c b/drivers/gpu/drm/nouveau/core/engine/bsp/nv84.c index 4b809319e831..66f7dfd907ee 100644 --- a/drivers/gpu/drm/nouveau/core/engine/bsp/nv84.c +++ b/drivers/gpu/drm/nouveau/core/engine/bsp/nv84.c @@ -1,5 +1,5 @@ /* - * Copyright 2011 Red Hat Inc. + * Copyright 2012 Red Hat Inc. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -22,61 +22,154 @@ * Authors: Ben Skeggs */ -#include "drmP.h" -#include "nouveau_drv.h" -#include "nouveau_util.h" -#include +#include +#include +#include -/*XXX: This stub is currently used on NV98+ also, as soon as this becomes - * more than just an enable/disable stub this needs to be split out to - * nv98_bsp.c... - */ +#include + +struct nv84_bsp_priv { + struct nouveau_bsp base; +}; -struct nv84_bsp_engine { - struct nouveau_exec_engine base; +struct nv84_bsp_chan { + struct nouveau_bsp_chan base; }; +/******************************************************************************* + * BSP object classes + ******************************************************************************/ + +static struct nouveau_oclass +nv84_bsp_sclass[] = { + {}, +}; + +/******************************************************************************* + * BSP context + ******************************************************************************/ + static int -nv84_bsp_fini(struct drm_device *dev, int engine, bool suspend) +nv84_bsp_context_ctor(struct nouveau_object *parent, + struct nouveau_object *engine, + struct nouveau_oclass *oclass, void *data, u32 size, + struct nouveau_object **pobject) { - if (!(nv_rd32(dev, 0x000200) & 0x00008000)) - return 0; + struct nv84_bsp_chan *priv; + int ret; + + ret = nouveau_bsp_context_create(parent, engine, oclass, NULL, + 0, 0, 0, &priv); + *pobject = nv_object(priv); + if (ret) + return ret; - nv_mask(dev, 0x000200, 0x00008000, 0x00000000); return 0; } +static void +nv84_bsp_context_dtor(struct nouveau_object *object) +{ + struct nv84_bsp_chan *priv = (void *)object; + nouveau_bsp_context_destroy(&priv->base); +} + static int -nv84_bsp_init(struct drm_device *dev, int engine) +nv84_bsp_context_init(struct nouveau_object *object) { - nv_mask(dev, 0x000200, 0x00008000, 0x00000000); - nv_mask(dev, 0x000200, 0x00008000, 0x00008000); + struct nv84_bsp_chan *priv = (void *)object; + int ret; + + ret = nouveau_bsp_context_init(&priv->base); + if (ret) + return ret; + return 0; } +static int +nv84_bsp_context_fini(struct nouveau_object *object, bool suspend) +{ + struct nv84_bsp_chan *priv = (void *)object; + return nouveau_bsp_context_fini(&priv->base, suspend); +} + +static struct nouveau_oclass +nv84_bsp_cclass = { + .handle = NV_ENGCTX(BSP, 0x84), + .ofuncs = &(struct nouveau_ofuncs) { + .ctor = nv84_bsp_context_ctor, + .dtor = nv84_bsp_context_dtor, + .init = nv84_bsp_context_init, + .fini = nv84_bsp_context_fini, + .rd32 = _nouveau_bsp_context_rd32, + .wr32 = _nouveau_bsp_context_wr32, + }, +}; + +/******************************************************************************* + * BSP engine/subdev functions + ******************************************************************************/ + static void -nv84_bsp_destroy(struct drm_device *dev, int engine) +nv84_bsp_intr(struct nouveau_subdev *subdev) { - struct nv84_bsp_engine *pbsp = nv_engine(dev, engine); +} - NVOBJ_ENGINE_DEL(dev, BSP); +static int +nv84_bsp_ctor(struct nouveau_object *parent, struct nouveau_object *engine, + struct nouveau_oclass *oclass, void *data, u32 size, + struct nouveau_object **pobject) +{ + struct nv84_bsp_priv *priv; + int ret; + + ret = nouveau_bsp_create(parent, engine, oclass, &priv); + *pobject = nv_object(priv); + if (ret) + return ret; - kfree(pbsp); + nv_subdev(priv)->unit = 0x04008000; + nv_subdev(priv)->intr = nv84_bsp_intr; + nv_engine(priv)->cclass = &nv84_bsp_cclass; + nv_engine(priv)->sclass = nv84_bsp_sclass; + return 0; } -int -nv84_bsp_create(struct drm_device *dev) +static void +nv84_bsp_dtor(struct nouveau_object *object) { - struct nv84_bsp_engine *pbsp; + struct nv84_bsp_priv *priv = (void *)object; + nouveau_bsp_destroy(&priv->base); +} - pbsp = kzalloc(sizeof(*pbsp), GFP_KERNEL); - if (!pbsp) - return -ENOMEM; +static int +nv84_bsp_init(struct nouveau_object *object) +{ + struct nv84_bsp_priv *priv = (void *)object; + int ret; - pbsp->base.destroy = nv84_bsp_destroy; - pbsp->base.init = nv84_bsp_init; - pbsp->base.fini = nv84_bsp_fini; + ret = nouveau_bsp_init(&priv->base); + if (ret) + return ret; - NVOBJ_ENGINE_ADD(dev, BSP, &pbsp->base); return 0; } + +static int +nv84_bsp_fini(struct nouveau_object *object, bool suspend) +{ + struct nv84_bsp_priv *priv = (void *)object; + return nouveau_bsp_fini(&priv->base, suspend); +} + +struct nouveau_oclass +nv84_bsp_oclass = { + .handle = NV_ENGINE(BSP, 0x84), + .ofuncs = &(struct nouveau_ofuncs) { + .ctor = nv84_bsp_ctor, + .dtor = nv84_bsp_dtor, + .init = nv84_bsp_init, + .fini = nv84_bsp_fini, + }, +}; diff --git a/drivers/gpu/drm/nouveau/core/engine/copy/nva3.c b/drivers/gpu/drm/nouveau/core/engine/copy/nva3.c index 9150c5ed16c3..debb82830b66 100644 --- a/drivers/gpu/drm/nouveau/core/engine/copy/nva3.c +++ b/drivers/gpu/drm/nouveau/core/engine/copy/nva3.c @@ -1,5 +1,5 @@ /* - * Copyright 2011 Red Hat Inc. + * Copyright 2012 Red Hat Inc. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -22,112 +22,75 @@ * Authors: Ben Skeggs */ -#include -#include "drmP.h" -#include "nouveau_drv.h" -#include "nouveau_util.h" -#include -#include "fuc/nva3.fuc.h" - -struct nva3_copy_engine { - struct nouveau_exec_engine base; -}; - -static int -nva3_copy_context_new(struct nouveau_channel *chan, int engine) -{ - struct drm_device *dev = chan->dev; - struct nouveau_gpuobj *ramin = chan->ramin; - struct nouveau_gpuobj *ctx = NULL; - int ret; - - NV_DEBUG(dev, "ch%d\n", chan->id); +#include +#include +#include +#include - ret = nouveau_gpuobj_new(dev, chan, 256, 0, NVOBJ_FLAG_ZERO_ALLOC | - NVOBJ_FLAG_ZERO_FREE, &ctx); - if (ret) - return ret; +#include +#include - nv_wo32(ramin, 0xc0, 0x00190000); - nv_wo32(ramin, 0xc4, ctx->addr + ctx->size - 1); - nv_wo32(ramin, 0xc8, ctx->addr); - nv_wo32(ramin, 0xcc, 0x00000000); - nv_wo32(ramin, 0xd0, 0x00000000); - nv_wo32(ramin, 0xd4, 0x00000000); - nvimem_flush(dev); +#include - nvvm_engref(chan->vm, engine, 1); - chan->engctx[engine] = ctx; - return 0; -} - -static int -nva3_copy_object_new(struct nouveau_channel *chan, int engine, - u32 handle, u16 class) -{ - struct nouveau_gpuobj *ctx = chan->engctx[engine]; +#include "fuc/nva3.fuc.h" - /* fuc engine doesn't need an object, our ramht code does.. */ - ctx->engine = 3; - ctx->class = class; - return nouveau_ramht_insert(chan, handle, ctx); -} +struct nva3_copy_priv { + struct nouveau_copy base; +}; -static void -nva3_copy_context_del(struct nouveau_channel *chan, int engine) -{ - struct nouveau_gpuobj *ctx = chan->engctx[engine]; - int i; +struct nva3_copy_chan { + struct nouveau_copy_chan base; +}; - for (i = 0xc0; i <= 0xd4; i += 4) - nv_wo32(chan->ramin, i, 0x00000000); +/******************************************************************************* + * Copy object classes + ******************************************************************************/ - nvvm_engref(chan->vm, engine, -1); - nouveau_gpuobj_ref(NULL, &ctx); - chan->engctx[engine] = ctx; -} +static struct nouveau_oclass +nva3_copy_sclass[] = { + { 0x85b5, &nouveau_object_ofuncs }, + {} +}; -static void -nva3_copy_tlb_flush(struct drm_device *dev, int engine) -{ - nv50_vm_flush_engine(dev, 0x0d); -} +/******************************************************************************* + * PCOPY context + ******************************************************************************/ static int -nva3_copy_init(struct drm_device *dev, int engine) +nva3_copy_context_ctor(struct nouveau_object *parent, + struct nouveau_object *engine, + struct nouveau_oclass *oclass, void *data, u32 size, + struct nouveau_object **pobject) { - int i; - - nv_mask(dev, 0x000200, 0x00002000, 0x00000000); - nv_mask(dev, 0x000200, 0x00002000, 0x00002000); - nv_wr32(dev, 0x104014, 0xffffffff); /* disable all interrupts */ - - /* upload ucode */ - nv_wr32(dev, 0x1041c0, 0x01000000); - for (i = 0; i < sizeof(nva3_pcopy_data) / 4; i++) - nv_wr32(dev, 0x1041c4, nva3_pcopy_data[i]); + struct nva3_copy_chan *priv; + int ret; - nv_wr32(dev, 0x104180, 0x01000000); - for (i = 0; i < sizeof(nva3_pcopy_code) / 4; i++) { - if ((i & 0x3f) == 0) - nv_wr32(dev, 0x104188, i >> 6); - nv_wr32(dev, 0x104184, nva3_pcopy_code[i]); - } + ret = nouveau_copy_context_create(parent, engine, oclass, NULL, 256, 0, + NVOBJ_FLAG_ZERO_ALLOC, &priv); + *pobject = nv_object(priv); + if (ret) + return ret; - /* start it running */ - nv_wr32(dev, 0x10410c, 0x00000000); - nv_wr32(dev, 0x104104, 0x00000000); /* ENTRY */ - nv_wr32(dev, 0x104100, 0x00000002); /* TRIGGER */ return 0; } -static int -nva3_copy_fini(struct drm_device *dev, int engine, bool suspend) -{ - nv_mask(dev, 0x104048, 0x00000003, 0x00000000); - nv_wr32(dev, 0x104014, 0xffffffff); - return 0; -} +static struct nouveau_oclass +nva3_copy_cclass = { + .handle = NV_ENGCTX(COPY0, 0xa3), + .ofuncs = &(struct nouveau_ofuncs) { + .ctor = nva3_copy_context_ctor, + .dtor = _nouveau_copy_context_dtor, + .init = _nouveau_copy_context_init, + .fini = _nouveau_copy_context_fini, + .rd32 = _nouveau_copy_context_rd32, + .wr32 = _nouveau_copy_context_wr32, + + }, +}; + +/******************************************************************************* + * PCOPY engine/subdev functions + ******************************************************************************/ static struct nouveau_enum nva3_copy_isr_error_name[] = { { 0x0001, "ILLEGAL_MTHD" }, @@ -137,65 +100,114 @@ static struct nouveau_enum nva3_copy_isr_error_name[] = { }; static void -nva3_copy_isr(struct drm_device *dev) +nva3_copy_intr(struct nouveau_subdev *subdev) { - u32 dispatch = nv_rd32(dev, 0x10401c); - u32 stat = nv_rd32(dev, 0x104008) & dispatch & ~(dispatch >> 16); - u32 inst = nv_rd32(dev, 0x104050) & 0x3fffffff; - u32 ssta = nv_rd32(dev, 0x104040) & 0x0000ffff; - u32 addr = nv_rd32(dev, 0x104040) >> 16; + struct nva3_copy_priv *priv = (void *)subdev; + u32 dispatch = nv_rd32(priv, 0x10401c); + u32 stat = nv_rd32(priv, 0x104008) & dispatch & ~(dispatch >> 16); + u32 inst = nv_rd32(priv, 0x104050) & 0x3fffffff; + u32 ssta = nv_rd32(priv, 0x104040) & 0x0000ffff; + u32 addr = nv_rd32(priv, 0x104040) >> 16; u32 mthd = (addr & 0x07ff) << 2; u32 subc = (addr & 0x3800) >> 11; - u32 data = nv_rd32(dev, 0x104044); - int chid = nv50_graph_isr_chid(dev, inst); + u32 data = nv_rd32(priv, 0x104044); if (stat & 0x00000040) { - NV_INFO(dev, "PCOPY: DISPATCH_ERROR ["); + nv_error(priv, "DISPATCH_ERROR ["); nouveau_enum_print(nva3_copy_isr_error_name, ssta); - printk("] ch %d [0x%08x] subc %d mthd 0x%04x data 0x%08x\n", - chid, inst, subc, mthd, data); - nv_wr32(dev, 0x104004, 0x00000040); + printk("] ch 0x%08x subc %d mthd 0x%04x data 0x%08x\n", + inst, subc, mthd, data); + nv_wr32(priv, 0x104004, 0x00000040); stat &= ~0x00000040; } if (stat) { - NV_INFO(dev, "PCOPY: unhandled intr 0x%08x\n", stat); - nv_wr32(dev, 0x104004, stat); + nv_error(priv, "unhandled intr 0x%08x\n", stat); + nv_wr32(priv, 0x104004, stat); } - nv50_fb_vm_trap(dev, 1); + + nv50_fb_trap(nouveau_fb(priv), 1); } -static void -nva3_copy_destroy(struct drm_device *dev, int engine) +static int +nva3_copy_tlb_flush(struct nouveau_engine *engine) { - struct nva3_copy_engine *pcopy = nv_engine(dev, engine); + nv50_vm_flush_engine(&engine->base, 0x0d); + return 0; +} - nouveau_irq_unregister(dev, 22); +static int +nva3_copy_ctor(struct nouveau_object *parent, struct nouveau_object *engine, + struct nouveau_oclass *oclass, void *data, u32 size, + struct nouveau_object **pobject) +{ + bool enable = (nv_device(parent)->chipset != 0xaf); + struct nva3_copy_priv *priv; + int ret; - NVOBJ_ENGINE_DEL(dev, COPY0); - kfree(pcopy); + ret = nouveau_copy_create(parent, engine, oclass, enable, 0, &priv); + *pobject = nv_object(priv); + if (ret) + return ret; + + nv_subdev(priv)->unit = 0x00802000; + nv_subdev(priv)->intr = nva3_copy_intr; + nv_engine(priv)->cclass = &nva3_copy_cclass; + nv_engine(priv)->sclass = nva3_copy_sclass; + nv_engine(priv)->tlb_flush = nva3_copy_tlb_flush; + return 0; } -int -nva3_copy_create(struct drm_device *dev) +static int +nva3_copy_init(struct nouveau_object *object) { - struct nva3_copy_engine *pcopy; + struct nva3_copy_priv *priv = (void *)object; + int ret, i; - pcopy = kzalloc(sizeof(*pcopy), GFP_KERNEL); - if (!pcopy) - return -ENOMEM; + ret = nouveau_copy_init(&priv->base); + if (ret) + return ret; - pcopy->base.destroy = nva3_copy_destroy; - pcopy->base.init = nva3_copy_init; - pcopy->base.fini = nva3_copy_fini; - pcopy->base.context_new = nva3_copy_context_new; - pcopy->base.context_del = nva3_copy_context_del; - pcopy->base.object_new = nva3_copy_object_new; - pcopy->base.tlb_flush = nva3_copy_tlb_flush; + /* disable all interrupts */ + nv_wr32(priv, 0x104014, 0xffffffff); - nouveau_irq_register(dev, 22, nva3_copy_isr); + /* upload ucode */ + nv_wr32(priv, 0x1041c0, 0x01000000); + for (i = 0; i < sizeof(nva3_pcopy_data) / 4; i++) + nv_wr32(priv, 0x1041c4, nva3_pcopy_data[i]); + + nv_wr32(priv, 0x104180, 0x01000000); + for (i = 0; i < sizeof(nva3_pcopy_code) / 4; i++) { + if ((i & 0x3f) == 0) + nv_wr32(priv, 0x104188, i >> 6); + nv_wr32(priv, 0x104184, nva3_pcopy_code[i]); + } - NVOBJ_ENGINE_ADD(dev, COPY0, &pcopy->base); - NVOBJ_CLASS(dev, 0x85b5, COPY0); + /* start it running */ + nv_wr32(priv, 0x10410c, 0x00000000); + nv_wr32(priv, 0x104104, 0x00000000); /* ENTRY */ + nv_wr32(priv, 0x104100, 0x00000002); /* TRIGGER */ return 0; } + +static int +nva3_copy_fini(struct nouveau_object *object, bool suspend) +{ + struct nva3_copy_priv *priv = (void *)object; + + nv_mask(priv, 0x104048, 0x00000003, 0x00000000); + nv_wr32(priv, 0x104014, 0xffffffff); + + return nouveau_copy_fini(&priv->base, suspend); +} + +struct nouveau_oclass +nva3_copy_oclass = { + .handle = NV_ENGINE(COPY0, 0xa3), + .ofuncs = &(struct nouveau_ofuncs) { + .ctor = nva3_copy_ctor, + .dtor = _nouveau_copy_dtor, + .init = nva3_copy_init, + .fini = nva3_copy_fini, + }, +}; diff --git a/drivers/gpu/drm/nouveau/core/engine/copy/nvc0.c b/drivers/gpu/drm/nouveau/core/engine/copy/nvc0.c index f39de5a593d6..ecc8faac3a2a 100644 --- a/drivers/gpu/drm/nouveau/core/engine/copy/nvc0.c +++ b/drivers/gpu/drm/nouveau/core/engine/copy/nvc0.c @@ -1,5 +1,5 @@ /* - * Copyright 2011 Red Hat Inc. + * Copyright 2012 Red Hat Inc. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -22,138 +22,86 @@ * Authors: Ben Skeggs */ -#include -#include "drmP.h" -#include "nouveau_drv.h" -#include "nouveau_util.h" -#include +#include +#include +#include +#include + +#include + #include "fuc/nvc0.fuc.h" -struct nvc0_copy_engine { - struct nouveau_exec_engine base; - u32 irq; - u32 pmc; - u32 fuc; - u32 ctx; +struct nvc0_copy_priv { + struct nouveau_copy base; }; struct nvc0_copy_chan { - struct nouveau_gpuobj *mem; - struct nouveau_vma vma; + struct nouveau_copy_chan base; }; -static int -nvc0_copy_context_new(struct nouveau_channel *chan, int engine) -{ - struct nvc0_copy_engine *pcopy = nv_engine(chan->dev, engine); - struct nvc0_copy_chan *cctx; - struct drm_device *dev = chan->dev; - struct nouveau_gpuobj *ramin = chan->ramin; - int ret; - - cctx = chan->engctx[engine] = kzalloc(sizeof(*cctx), GFP_KERNEL); - if (!cctx) - return -ENOMEM; +/******************************************************************************* + * Copy object classes + ******************************************************************************/ - ret = nouveau_gpuobj_new(dev, NULL, 256, 256, - NVOBJ_FLAG_ZERO_ALLOC, &cctx->mem); - if (ret) - return ret; +static struct nouveau_oclass +nvc0_copy0_sclass[] = { + { 0x90b5, &nouveau_object_ofuncs }, + {}, +}; - ret = nouveau_gpuobj_map_vm(cctx->mem, chan->vm, NV_MEM_ACCESS_RW, - &cctx->vma); - if (ret) - return ret; +static struct nouveau_oclass +nvc0_copy1_sclass[] = { + { 0x90b8, &nouveau_object_ofuncs }, + {}, +}; - nv_wo32(ramin, pcopy->ctx + 0, lower_32_bits(cctx->vma.offset)); - nv_wo32(ramin, pcopy->ctx + 4, upper_32_bits(cctx->vma.offset)); - nvimem_flush(dev); - return 0; -} +/******************************************************************************* + * PCOPY context + ******************************************************************************/ static int -nvc0_copy_object_new(struct nouveau_channel *chan, int engine, - u32 handle, u16 class) -{ - return 0; -} - -static void -nvc0_copy_context_del(struct nouveau_channel *chan, int engine) +nvc0_copy_context_ctor(struct nouveau_object *parent, + struct nouveau_object *engine, + struct nouveau_oclass *oclass, void *data, u32 size, + struct nouveau_object **pobject) { - struct nvc0_copy_engine *pcopy = nv_engine(chan->dev, engine); - struct nvc0_copy_chan *cctx = chan->engctx[engine]; - struct drm_device *dev = chan->dev; - u32 inst; - - inst = (chan->ramin->addr >> 12); - inst |= 0x40000000; - - /* disable fifo access */ - nv_wr32(dev, pcopy->fuc + 0x048, 0x00000000); - /* mark channel as unloaded if it's currently active */ - if (nv_rd32(dev, pcopy->fuc + 0x050) == inst) - nv_mask(dev, pcopy->fuc + 0x050, 0x40000000, 0x00000000); - /* mark next channel as invalid if it's about to be loaded */ - if (nv_rd32(dev, pcopy->fuc + 0x054) == inst) - nv_mask(dev, pcopy->fuc + 0x054, 0x40000000, 0x00000000); - /* restore fifo access */ - nv_wr32(dev, pcopy->fuc + 0x048, 0x00000003); - - nv_wo32(chan->ramin, pcopy->ctx + 0, 0x00000000); - nv_wo32(chan->ramin, pcopy->ctx + 4, 0x00000000); - - nouveau_gpuobj_unmap(&cctx->vma); - nouveau_gpuobj_ref(NULL, &cctx->mem); - - kfree(cctx); - chan->engctx[engine] = NULL; -} - -static int -nvc0_copy_init(struct drm_device *dev, int engine) -{ - struct nvc0_copy_engine *pcopy = nv_engine(dev, engine); - int i; - - nv_mask(dev, 0x000200, pcopy->pmc, 0x00000000); - nv_mask(dev, 0x000200, pcopy->pmc, pcopy->pmc); - nv_wr32(dev, pcopy->fuc + 0x014, 0xffffffff); - - nv_wr32(dev, pcopy->fuc + 0x1c0, 0x01000000); - for (i = 0; i < sizeof(nvc0_pcopy_data) / 4; i++) - nv_wr32(dev, pcopy->fuc + 0x1c4, nvc0_pcopy_data[i]); + struct nvc0_copy_chan *priv; + int ret; - nv_wr32(dev, pcopy->fuc + 0x180, 0x01000000); - for (i = 0; i < sizeof(nvc0_pcopy_code) / 4; i++) { - if ((i & 0x3f) == 0) - nv_wr32(dev, pcopy->fuc + 0x188, i >> 6); - nv_wr32(dev, pcopy->fuc + 0x184, nvc0_pcopy_code[i]); - } + ret = nouveau_copy_context_create(parent, engine, oclass, NULL, 256, + 256, NVOBJ_FLAG_ZERO_ALLOC, &priv); + *pobject = nv_object(priv); + if (ret) + return ret; - nv_wr32(dev, pcopy->fuc + 0x084, engine - NVOBJ_ENGINE_COPY0); - nv_wr32(dev, pcopy->fuc + 0x10c, 0x00000000); - nv_wr32(dev, pcopy->fuc + 0x104, 0x00000000); /* ENTRY */ - nv_wr32(dev, pcopy->fuc + 0x100, 0x00000002); /* TRIGGER */ return 0; } -static int -nvc0_copy_fini(struct drm_device *dev, int engine, bool suspend) -{ - struct nvc0_copy_engine *pcopy = nv_engine(dev, engine); +static struct nouveau_ofuncs +nvc0_copy_context_ofuncs = { + .ctor = nvc0_copy_context_ctor, + .dtor = _nouveau_copy_context_dtor, + .init = _nouveau_copy_context_init, + .fini = _nouveau_copy_context_fini, + .rd32 = _nouveau_copy_context_rd32, + .wr32 = _nouveau_copy_context_wr32, +}; - nv_mask(dev, pcopy->fuc + 0x048, 0x00000003, 0x00000000); +static struct nouveau_oclass +nvc0_copy0_cclass = { + .handle = NV_ENGCTX(COPY0, 0xc0), + .ofuncs = &nvc0_copy_context_ofuncs, +}; - /* trigger fuc context unload */ - nv_wait(dev, pcopy->fuc + 0x008, 0x0000000c, 0x00000000); - nv_mask(dev, pcopy->fuc + 0x054, 0x40000000, 0x00000000); - nv_wr32(dev, pcopy->fuc + 0x000, 0x00000008); - nv_wait(dev, pcopy->fuc + 0x008, 0x00000008, 0x00000000); +static struct nouveau_oclass +nvc0_copy1_cclass = { + .handle = NV_ENGCTX(COPY1, 0xc0), + .ofuncs = &nvc0_copy_context_ofuncs, +}; - nv_wr32(dev, pcopy->fuc + 0x014, 0xffffffff); - return 0; -} +/******************************************************************************* + * PCOPY engine/subdev functions + ******************************************************************************/ static struct nouveau_enum nvc0_copy_isr_error_name[] = { { 0x0001, "ILLEGAL_MTHD" }, @@ -163,93 +111,145 @@ static struct nouveau_enum nvc0_copy_isr_error_name[] = { }; static void -nvc0_copy_isr(struct drm_device *dev, int engine) +nvc0_copy_intr(struct nouveau_subdev *subdev) { - struct nvc0_copy_engine *pcopy = nv_engine(dev, engine); - u32 disp = nv_rd32(dev, pcopy->fuc + 0x01c); - u32 stat = nv_rd32(dev, pcopy->fuc + 0x008) & disp & ~(disp >> 16); - u64 inst = (u64)(nv_rd32(dev, pcopy->fuc + 0x050) & 0x0fffffff) << 12; - u32 chid = nvc0_graph_isr_chid(dev, inst); - u32 ssta = nv_rd32(dev, pcopy->fuc + 0x040) & 0x0000ffff; - u32 addr = nv_rd32(dev, pcopy->fuc + 0x040) >> 16; + int idx = nv_engidx(nv_object(subdev)) - NVDEV_ENGINE_COPY0; + struct nvc0_copy_priv *priv = (void *)subdev; + u32 disp = nv_rd32(priv, 0x10401c + (idx * 0x1000)); + u32 intr = nv_rd32(priv, 0x104008 + (idx * 0x1000)); + u32 stat = intr & disp & ~(disp >> 16); + u64 inst = nv_rd32(priv, 0x104050 + (idx * 0x1000)) & 0x0fffffff; + u32 ssta = nv_rd32(priv, 0x104040 + (idx * 0x1000)) & 0x0000ffff; + u32 addr = nv_rd32(priv, 0x104040 + (idx * 0x1000)) >> 16; u32 mthd = (addr & 0x07ff) << 2; u32 subc = (addr & 0x3800) >> 11; - u32 data = nv_rd32(dev, pcopy->fuc + 0x044); + u32 data = nv_rd32(priv, 0x104044 + (idx * 0x1000)); if (stat & 0x00000040) { - NV_INFO(dev, "PCOPY: DISPATCH_ERROR ["); + nv_error(priv, "DISPATCH_ERROR ["); nouveau_enum_print(nvc0_copy_isr_error_name, ssta); - printk("] ch %d [0x%010llx] subc %d mthd 0x%04x data 0x%08x\n", - chid, inst, subc, mthd, data); - nv_wr32(dev, pcopy->fuc + 0x004, 0x00000040); + printk("] ch 0x%010llx subc %d mthd 0x%04x data 0x%08x\n", + (u64)inst << 12, subc, mthd, data); + nv_wr32(priv, 0x104004 + (idx * 0x1000), 0x00000040); stat &= ~0x00000040; } if (stat) { - NV_INFO(dev, "PCOPY: unhandled intr 0x%08x\n", stat); - nv_wr32(dev, pcopy->fuc + 0x004, stat); + nv_error(priv, "unhandled intr 0x%08x\n", stat); + nv_wr32(priv, 0x104004 + (idx * 0x1000), stat); } } -static void -nvc0_copy_isr_0(struct drm_device *dev) +static int +nvc0_copy0_ctor(struct nouveau_object *parent, struct nouveau_object *engine, + struct nouveau_oclass *oclass, void *data, u32 size, + struct nouveau_object **pobject) { - nvc0_copy_isr(dev, NVOBJ_ENGINE_COPY0); -} + struct nvc0_copy_priv *priv; + int ret; -static void -nvc0_copy_isr_1(struct drm_device *dev) -{ - nvc0_copy_isr(dev, NVOBJ_ENGINE_COPY1); + if (nv_rd32(parent, 0x022500) & 0x00000100) + return -ENODEV; + + ret = nouveau_copy_create(parent, engine, oclass, true, 0, &priv); + *pobject = nv_object(priv); + if (ret) + return ret; + + nv_subdev(priv)->unit = 0x00000040; + nv_subdev(priv)->intr = nvc0_copy_intr; + nv_engine(priv)->cclass = &nvc0_copy0_cclass; + nv_engine(priv)->sclass = nvc0_copy0_sclass; + return 0; } -static void -nvc0_copy_destroy(struct drm_device *dev, int engine) +static int +nvc0_copy1_ctor(struct nouveau_object *parent, struct nouveau_object *engine, + struct nouveau_oclass *oclass, void *data, u32 size, + struct nouveau_object **pobject) { - struct nvc0_copy_engine *pcopy = nv_engine(dev, engine); + struct nvc0_copy_priv *priv; + int ret; - nouveau_irq_unregister(dev, pcopy->irq); + if (nv_rd32(parent, 0x022500) & 0x00000200) + return -ENODEV; - if (engine == NVOBJ_ENGINE_COPY0) - NVOBJ_ENGINE_DEL(dev, COPY0); - else - NVOBJ_ENGINE_DEL(dev, COPY1); - kfree(pcopy); + ret = nouveau_copy_create(parent, engine, oclass, true, 1, &priv); + *pobject = nv_object(priv); + if (ret) + return ret; + + nv_subdev(priv)->unit = 0x00000080; + nv_subdev(priv)->intr = nvc0_copy_intr; + nv_engine(priv)->cclass = &nvc0_copy1_cclass; + nv_engine(priv)->sclass = nvc0_copy1_sclass; + return 0; } -int -nvc0_copy_create(struct drm_device *dev, int engine) +static int +nvc0_copy_init(struct nouveau_object *object) { - struct nvc0_copy_engine *pcopy; - - pcopy = kzalloc(sizeof(*pcopy), GFP_KERNEL); - if (!pcopy) - return -ENOMEM; - - pcopy->base.destroy = nvc0_copy_destroy; - pcopy->base.init = nvc0_copy_init; - pcopy->base.fini = nvc0_copy_fini; - pcopy->base.context_new = nvc0_copy_context_new; - pcopy->base.context_del = nvc0_copy_context_del; - pcopy->base.object_new = nvc0_copy_object_new; - - if (engine == 0) { - pcopy->irq = 5; - pcopy->pmc = 0x00000040; - pcopy->fuc = 0x104000; - pcopy->ctx = 0x0230; - nouveau_irq_register(dev, pcopy->irq, nvc0_copy_isr_0); - NVOBJ_ENGINE_ADD(dev, COPY0, &pcopy->base); - NVOBJ_CLASS(dev, 0x90b5, COPY0); - } else { - pcopy->irq = 6; - pcopy->pmc = 0x00000080; - pcopy->fuc = 0x105000; - pcopy->ctx = 0x0240; - nouveau_irq_register(dev, pcopy->irq, nvc0_copy_isr_1); - NVOBJ_ENGINE_ADD(dev, COPY1, &pcopy->base); - NVOBJ_CLASS(dev, 0x90b8, COPY1); + int idx = nv_engidx(object) - NVDEV_ENGINE_COPY0; + struct nvc0_copy_priv *priv = (void *)object; + int ret, i; + + ret = nouveau_copy_init(&priv->base); + if (ret) + return ret; + + /* disable all interrupts */ + nv_wr32(priv, 0x104014 + (idx * 0x1000), 0xffffffff); + + /* upload ucode */ + nv_wr32(priv, 0x1041c0 + (idx * 0x1000), 0x01000000); + for (i = 0; i < sizeof(nvc0_pcopy_data) / 4; i++) + nv_wr32(priv, 0x1041c4 + (idx * 0x1000), nvc0_pcopy_data[i]); + + nv_wr32(priv, 0x104180 + (idx * 0x1000), 0x01000000); + for (i = 0; i < sizeof(nvc0_pcopy_code) / 4; i++) { + if ((i & 0x3f) == 0) + nv_wr32(priv, 0x104188 + (idx * 0x1000), i >> 6); + nv_wr32(priv, 0x104184 + (idx * 0x1000), nvc0_pcopy_code[i]); } + /* start it running */ + nv_wr32(priv, 0x104084 + (idx * 0x1000), idx); + nv_wr32(priv, 0x10410c + (idx * 0x1000), 0x00000000); + nv_wr32(priv, 0x104104 + (idx * 0x1000), 0x00000000); /* ENTRY */ + nv_wr32(priv, 0x104100 + (idx * 0x1000), 0x00000002); /* TRIGGER */ return 0; } + +static int +nvc0_copy_fini(struct nouveau_object *object, bool suspend) +{ + int idx = nv_engidx(object) - NVDEV_ENGINE_COPY0; + struct nvc0_copy_priv *priv = (void *)object; + + nv_mask(priv, 0x104048 + (idx * 0x1000), 0x00000003, 0x00000000); + nv_wr32(priv, 0x104014 + (idx * 0x1000), 0xffffffff); + + return nouveau_copy_fini(&priv->base, suspend); +} + +struct nouveau_oclass +nvc0_copy0_oclass = { + .handle = NV_ENGINE(COPY0, 0xc0), + .ofuncs = &(struct nouveau_ofuncs) { + .ctor = nvc0_copy0_ctor, + .dtor = _nouveau_copy_dtor, + .init = nvc0_copy_init, + .fini = nvc0_copy_fini, + }, +}; + +struct nouveau_oclass +nvc0_copy1_oclass = { + .handle = NV_ENGINE(COPY1, 0xc0), + .ofuncs = &(struct nouveau_ofuncs) { + .ctor = nvc0_copy1_ctor, + .dtor = _nouveau_copy_dtor, + .init = nvc0_copy_init, + .fini = nvc0_copy_fini, + }, +}; diff --git a/drivers/gpu/drm/nouveau/core/engine/crypt/nv84.c b/drivers/gpu/drm/nouveau/core/engine/crypt/nv84.c index 63051ab0ecca..a0e5e39638bc 100644 --- a/drivers/gpu/drm/nouveau/core/engine/crypt/nv84.c +++ b/drivers/gpu/drm/nouveau/core/engine/crypt/nv84.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,99 +22,106 @@ * Authors: Ben Skeggs */ -#include "drmP.h" -#include "nouveau_drv.h" -#include "nouveau_util.h" -#include +#include +#include +#include +#include +#include -struct nv84_crypt_engine { - struct nouveau_exec_engine base; +#include + +#include + +struct nv84_crypt_priv { + struct nouveau_crypt base; }; +struct nv84_crypt_chan { + struct nouveau_crypt_chan base; +}; + +/******************************************************************************* + * Crypt object classes + ******************************************************************************/ + static int -nv84_crypt_context_new(struct nouveau_channel *chan, int engine) +nv84_crypt_object_ctor(struct nouveau_object *parent, + struct nouveau_object *engine, + struct nouveau_oclass *oclass, void *data, u32 size, + struct nouveau_object **pobject) { - struct drm_device *dev = chan->dev; - struct nouveau_gpuobj *ramin = chan->ramin; - struct nouveau_gpuobj *ctx; + struct nouveau_gpuobj *obj; int ret; - NV_DEBUG(dev, "ch%d\n", chan->id); - - ret = nouveau_gpuobj_new(dev, chan, 256, 0, NVOBJ_FLAG_ZERO_ALLOC | - NVOBJ_FLAG_ZERO_FREE, &ctx); + ret = nouveau_gpuobj_create(parent, engine, oclass, 0, parent, + 16, 16, 0, &obj); + *pobject = nv_object(obj); if (ret) return ret; - nv_wo32(ramin, 0xa0, 0x00190000); - nv_wo32(ramin, 0xa4, ctx->addr + ctx->size - 1); - nv_wo32(ramin, 0xa8, ctx->addr); - nv_wo32(ramin, 0xac, 0); - nv_wo32(ramin, 0xb0, 0); - nv_wo32(ramin, 0xb4, 0); - nvimem_flush(dev); - - nvvm_engref(chan->vm, engine, 1); - chan->engctx[engine] = ctx; + nv_wo32(obj, 0x00, nv_mclass(obj)); + nv_wo32(obj, 0x04, 0x00000000); + nv_wo32(obj, 0x08, 0x00000000); + nv_wo32(obj, 0x0c, 0x00000000); return 0; } -static void -nv84_crypt_context_del(struct nouveau_channel *chan, int engine) -{ - struct nouveau_gpuobj *ctx = chan->engctx[engine]; - struct drm_device *dev = chan->dev; - u32 inst; - - inst = (chan->ramin->addr >> 12); - inst |= 0x80000000; - - /* mark context as invalid if still on the hardware, not - * doing this causes issues the next time PCRYPT is used, - * unsurprisingly :) - */ - nv_wr32(dev, 0x10200c, 0x00000000); - if (nv_rd32(dev, 0x102188) == inst) - nv_mask(dev, 0x102188, 0x80000000, 0x00000000); - if (nv_rd32(dev, 0x10218c) == inst) - nv_mask(dev, 0x10218c, 0x80000000, 0x00000000); - nv_wr32(dev, 0x10200c, 0x00000010); - - nouveau_gpuobj_ref(NULL, &ctx); - - nvvm_engref(chan->vm, engine, -1); - chan->engctx[engine] = NULL; -} +static struct nouveau_ofuncs +nv84_crypt_ofuncs = { + .ctor = nv84_crypt_object_ctor, + .dtor = _nouveau_gpuobj_dtor, + .init = _nouveau_gpuobj_init, + .fini = _nouveau_gpuobj_fini, + .rd32 = _nouveau_gpuobj_rd32, + .wr32 = _nouveau_gpuobj_wr32, +}; + +static struct nouveau_oclass +nv84_crypt_sclass[] = { + { 0x74c1, &nv84_crypt_ofuncs }, + {} +}; + +/******************************************************************************* + * PCRYPT context + ******************************************************************************/ static int -nv84_crypt_object_new(struct nouveau_channel *chan, int engine, - u32 handle, u16 class) +nv84_crypt_context_ctor(struct nouveau_object *parent, + struct nouveau_object *engine, + struct nouveau_oclass *oclass, void *data, u32 size, + struct nouveau_object **pobject) { - struct drm_device *dev = chan->dev; - struct nouveau_gpuobj *obj = NULL; + struct nv84_crypt_chan *priv; int ret; - ret = nouveau_gpuobj_new(dev, chan, 16, 16, NVOBJ_FLAG_ZERO_FREE, &obj); + ret = nouveau_crypt_context_create(parent, engine, oclass, NULL, 256, + 0, NVOBJ_FLAG_ZERO_ALLOC, &priv); + *pobject = nv_object(priv); if (ret) return ret; - obj->engine = 5; - obj->class = class; - nv_wo32(obj, 0x00, class); - nvimem_flush(dev); - - ret = nouveau_ramht_insert(chan, handle, obj); - nouveau_gpuobj_ref(NULL, &obj); - return ret; + return 0; } -static void -nv84_crypt_tlb_flush(struct drm_device *dev, int engine) -{ - nv50_vm_flush_engine(dev, 0x0a); -} +static struct nouveau_oclass +nv84_crypt_cclass = { + .handle = NV_ENGCTX(CRYPT, 0x84), + .ofuncs = &(struct nouveau_ofuncs) { + .ctor = nv84_crypt_context_ctor, + .dtor = _nouveau_crypt_context_dtor, + .init = _nouveau_crypt_context_init, + .fini = _nouveau_crypt_context_fini, + .rd32 = _nouveau_crypt_context_rd32, + .wr32 = _nouveau_crypt_context_wr32, + }, +}; + +/******************************************************************************* + * PCRYPT engine/subdev functions + ******************************************************************************/ -static struct nouveau_bitfield nv84_crypt_intr[] = { +static struct nouveau_bitfield nv84_crypt_intr_mask[] = { { 0x00000001, "INVALID_STATE" }, { 0x00000002, "ILLEGAL_MTHD" }, { 0x00000004, "ILLEGAL_CLASS" }, @@ -124,79 +131,78 @@ static struct nouveau_bitfield nv84_crypt_intr[] = { }; static void -nv84_crypt_isr(struct drm_device *dev) +nv84_crypt_intr(struct nouveau_subdev *subdev) { - u32 stat = nv_rd32(dev, 0x102130); - u32 mthd = nv_rd32(dev, 0x102190); - u32 data = nv_rd32(dev, 0x102194); - u64 inst = (u64)(nv_rd32(dev, 0x102188) & 0x7fffffff) << 12; - int show = nouveau_ratelimit(); - int chid = nv50_graph_isr_chid(dev, inst); - - if (show) { - NV_INFO(dev, "PCRYPT:"); - nouveau_bitfield_print(nv84_crypt_intr, stat); - printk(KERN_CONT " ch %d (0x%010llx) mthd 0x%04x data 0x%08x\n", - chid, inst, mthd, data); + struct nv84_crypt_priv *priv = (void *)subdev; + u32 stat = nv_rd32(priv, 0x102130); + u32 mthd = nv_rd32(priv, 0x102190); + u32 data = nv_rd32(priv, 0x102194); + u32 inst = nv_rd32(priv, 0x102188) & 0x7fffffff; + + if (stat) { + nv_error(priv, ""); + nouveau_bitfield_print(nv84_crypt_intr_mask, stat); + printk(" ch 0x%010llx mthd 0x%04x data 0x%08x\n", + (u64)inst << 12, mthd, data); } - nv_wr32(dev, 0x102130, stat); - nv_wr32(dev, 0x10200c, 0x10); + nv_wr32(priv, 0x102130, stat); + nv_wr32(priv, 0x10200c, 0x10); - nv50_fb_vm_trap(dev, show); + nv50_fb_trap(nouveau_fb(priv), 1); } static int -nv84_crypt_fini(struct drm_device *dev, int engine, bool suspend) +nv84_crypt_tlb_flush(struct nouveau_engine *engine) { - nv_wr32(dev, 0x102140, 0x00000000); + nv50_vm_flush_engine(&engine->base, 0x0a); return 0; } static int -nv84_crypt_init(struct drm_device *dev, int engine) +nv84_crypt_ctor(struct nouveau_object *parent, struct nouveau_object *engine, + struct nouveau_oclass *oclass, void *data, u32 size, + struct nouveau_object **pobject) { - nv_mask(dev, 0x000200, 0x00004000, 0x00000000); - nv_mask(dev, 0x000200, 0x00004000, 0x00004000); + struct nv84_crypt_priv *priv; + int ret; - nv_wr32(dev, 0x102130, 0xffffffff); - nv_wr32(dev, 0x102140, 0xffffffbf); + ret = nouveau_crypt_create(parent, engine, oclass, &priv); + *pobject = nv_object(priv); + if (ret) + return ret; - nv_wr32(dev, 0x10200c, 0x00000010); + nv_subdev(priv)->unit = 0x00004000; + nv_subdev(priv)->intr = nv84_crypt_intr; + nv_engine(priv)->cclass = &nv84_crypt_cclass; + nv_engine(priv)->sclass = nv84_crypt_sclass; + nv_engine(priv)->tlb_flush = nv84_crypt_tlb_flush; return 0; } -static void -nv84_crypt_destroy(struct drm_device *dev, int engine) -{ - struct nv84_crypt_engine *pcrypt = nv_engine(dev, engine); - - NVOBJ_ENGINE_DEL(dev, CRYPT); - - nouveau_irq_unregister(dev, 14); - kfree(pcrypt); -} - -int -nv84_crypt_create(struct drm_device *dev) +static int +nv84_crypt_init(struct nouveau_object *object) { - struct nv84_crypt_engine *pcrypt; - - pcrypt = kzalloc(sizeof(*pcrypt), GFP_KERNEL); - if (!pcrypt) - return -ENOMEM; - - pcrypt->base.destroy = nv84_crypt_destroy; - pcrypt->base.init = nv84_crypt_init; - pcrypt->base.fini = nv84_crypt_fini; - pcrypt->base.context_new = nv84_crypt_context_new; - pcrypt->base.context_del = nv84_crypt_context_del; - pcrypt->base.object_new = nv84_crypt_object_new; - pcrypt->base.tlb_flush = nv84_crypt_tlb_flush; + struct nv84_crypt_priv *priv = (void *)object; + int ret; - nouveau_irq_register(dev, 14, nv84_crypt_isr); + ret = nouveau_crypt_init(&priv->base); + if (ret) + return ret; - NVOBJ_ENGINE_ADD(dev, CRYPT, &pcrypt->base); - NVOBJ_CLASS (dev, 0x74c1, CRYPT); + nv_wr32(priv, 0x102130, 0xffffffff); + nv_wr32(priv, 0x102140, 0xffffffbf); + nv_wr32(priv, 0x10200c, 0x00000010); return 0; } + +struct nouveau_oclass +nv84_crypt_oclass = { + .handle = NV_ENGINE(CRYPT, 0x84), + .ofuncs = &(struct nouveau_ofuncs) { + .ctor = nv84_crypt_ctor, + .dtor = _nouveau_crypt_dtor, + .init = nv84_crypt_init, + .fini = _nouveau_crypt_fini, + }, +}; diff --git a/drivers/gpu/drm/nouveau/core/engine/crypt/nv98.c b/drivers/gpu/drm/nouveau/core/engine/crypt/nv98.c index c9adc1b8a7db..559a1b1d7082 100644 --- a/drivers/gpu/drm/nouveau/core/engine/crypt/nv98.c +++ b/drivers/gpu/drm/nouveau/core/engine/crypt/nv98.c @@ -1,5 +1,5 @@ /* - * Copyright 2011 Red Hat Inc. + * Copyright 2012 Red Hat Inc. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -22,124 +22,74 @@ * Authors: Ben Skeggs */ -#include "drmP.h" +#include +#include +#include +#include -#include "nouveau_drv.h" -#include "nouveau_util.h" -#include +#include +#include + +#include #include "fuc/nv98.fuc.h" struct nv98_crypt_priv { - struct nouveau_exec_engine base; + struct nouveau_crypt base; }; struct nv98_crypt_chan { - struct nouveau_gpuobj *mem; + struct nouveau_crypt_chan base; }; -static int -nv98_crypt_context_new(struct nouveau_channel *chan, int engine) -{ - struct drm_device *dev = chan->dev; - struct nv98_crypt_priv *priv = nv_engine(dev, engine); - struct nv98_crypt_chan *cctx; - int ret; - - cctx = chan->engctx[engine] = kzalloc(sizeof(*cctx), GFP_KERNEL); - if (!cctx) - return -ENOMEM; - - nvvm_engref(chan->vm, engine, 1); - - ret = nouveau_gpuobj_new(dev, chan, 256, 0, NVOBJ_FLAG_ZERO_ALLOC | - NVOBJ_FLAG_ZERO_FREE, &cctx->mem); - if (ret) - goto error; - - nv_wo32(chan->ramin, 0xa0, 0x00190000); - nv_wo32(chan->ramin, 0xa4, cctx->mem->addr + cctx->mem->size - 1); - nv_wo32(chan->ramin, 0xa8, cctx->mem->addr); - nv_wo32(chan->ramin, 0xac, 0x00000000); - nv_wo32(chan->ramin, 0xb0, 0x00000000); - nv_wo32(chan->ramin, 0xb4, 0x00000000); - nvimem_flush(dev); - -error: - if (ret) - priv->base.context_del(chan, engine); - return ret; -} - -static void -nv98_crypt_context_del(struct nouveau_channel *chan, int engine) -{ - struct nv98_crypt_chan *cctx = chan->engctx[engine]; - int i; - - for (i = 0xa0; i < 0xb4; i += 4) - nv_wo32(chan->ramin, i, 0x00000000); +/******************************************************************************* + * Crypt object classes + ******************************************************************************/ - nouveau_gpuobj_ref(NULL, &cctx->mem); +static struct nouveau_oclass +nv98_crypt_sclass[] = { + { 0x88b4, &nouveau_object_ofuncs }, + {}, +}; - nvvm_engref(chan->vm, engine, -1); - chan->engctx[engine] = NULL; - kfree(cctx); -} +/******************************************************************************* + * PCRYPT context + ******************************************************************************/ static int -nv98_crypt_object_new(struct nouveau_channel *chan, int engine, - u32 handle, u16 class) +nv98_crypt_context_ctor(struct nouveau_object *parent, + struct nouveau_object *engine, + struct nouveau_oclass *oclass, void *data, u32 size, + struct nouveau_object **pobject) { - struct nv98_crypt_chan *cctx = chan->engctx[engine]; - - /* fuc engine doesn't need an object, our ramht code does.. */ - cctx->mem->engine = 5; - cctx->mem->class = class; - return nouveau_ramht_insert(chan, handle, cctx->mem); -} + struct nv98_crypt_chan *priv; + int ret; -static void -nv98_crypt_tlb_flush(struct drm_device *dev, int engine) -{ - nv50_vm_flush_engine(dev, 0x0a); -} + ret = nouveau_crypt_context_create(parent, engine, oclass, NULL, 256, + 256, NVOBJ_FLAG_ZERO_ALLOC, &priv); + *pobject = nv_object(priv); + if (ret) + return ret; -static int -nv98_crypt_fini(struct drm_device *dev, int engine, bool suspend) -{ - nv_mask(dev, 0x000200, 0x00004000, 0x00000000); return 0; } -static int -nv98_crypt_init(struct drm_device *dev, int engine) -{ - int i; - - /* reset! */ - nv_mask(dev, 0x000200, 0x00004000, 0x00000000); - nv_mask(dev, 0x000200, 0x00004000, 0x00004000); - - /* wait for exit interrupt to signal */ - nv_wait(dev, 0x087008, 0x00000010, 0x00000010); - nv_wr32(dev, 0x087004, 0x00000010); - - /* upload microcode code and data segments */ - nv_wr32(dev, 0x087ff8, 0x00100000); - for (i = 0; i < ARRAY_SIZE(nv98_pcrypt_code); i++) - nv_wr32(dev, 0x087ff4, nv98_pcrypt_code[i]); - - nv_wr32(dev, 0x087ff8, 0x00000000); - for (i = 0; i < ARRAY_SIZE(nv98_pcrypt_data); i++) - nv_wr32(dev, 0x087ff4, nv98_pcrypt_data[i]); +static struct nouveau_oclass +nv98_crypt_cclass = { + .handle = NV_ENGCTX(CRYPT, 0x98), + .ofuncs = &(struct nouveau_ofuncs) { + .ctor = nv98_crypt_context_ctor, + .dtor = _nouveau_crypt_context_dtor, + .init = _nouveau_crypt_context_init, + .fini = _nouveau_crypt_context_fini, + .rd32 = _nouveau_crypt_context_rd32, + .wr32 = _nouveau_crypt_context_wr32, + }, +}; - /* start it running */ - nv_wr32(dev, 0x08710c, 0x00000000); - nv_wr32(dev, 0x087104, 0x00000000); /* ENTRY */ - nv_wr32(dev, 0x087100, 0x00000002); /* TRIGGER */ - return 0; -} +/******************************************************************************* + * PCRYPT engine/subdev functions + ******************************************************************************/ static struct nouveau_enum nv98_crypt_isr_error_name[] = { { 0x0000, "ILLEGAL_MTHD" }, @@ -150,65 +100,100 @@ static struct nouveau_enum nv98_crypt_isr_error_name[] = { }; static void -nv98_crypt_isr(struct drm_device *dev) +nv98_crypt_intr(struct nouveau_subdev *subdev) { - u32 disp = nv_rd32(dev, 0x08701c); - u32 stat = nv_rd32(dev, 0x087008) & disp & ~(disp >> 16); - u32 inst = nv_rd32(dev, 0x087050) & 0x3fffffff; - u32 ssta = nv_rd32(dev, 0x087040) & 0x0000ffff; - u32 addr = nv_rd32(dev, 0x087040) >> 16; + struct nv98_crypt_priv *priv = (void *)subdev; + u32 disp = nv_rd32(priv, 0x08701c); + u32 stat = nv_rd32(priv, 0x087008) & disp & ~(disp >> 16); + u32 inst = nv_rd32(priv, 0x087050) & 0x3fffffff; + u32 ssta = nv_rd32(priv, 0x087040) & 0x0000ffff; + u32 addr = nv_rd32(priv, 0x087040) >> 16; u32 mthd = (addr & 0x07ff) << 2; u32 subc = (addr & 0x3800) >> 11; - u32 data = nv_rd32(dev, 0x087044); - int chid = nv50_graph_isr_chid(dev, inst); + u32 data = nv_rd32(priv, 0x087044); if (stat & 0x00000040) { - NV_INFO(dev, "PCRYPT: DISPATCH_ERROR ["); + nv_error(priv, "DISPATCH_ERROR ["); nouveau_enum_print(nv98_crypt_isr_error_name, ssta); - printk("] ch %d [0x%08x] subc %d mthd 0x%04x data 0x%08x\n", - chid, inst, subc, mthd, data); - nv_wr32(dev, 0x087004, 0x00000040); + printk("] ch 0x%08x subc %d mthd 0x%04x data 0x%08x\n", + inst, subc, mthd, data); + nv_wr32(priv, 0x087004, 0x00000040); stat &= ~0x00000040; } if (stat) { - NV_INFO(dev, "PCRYPT: unhandled intr 0x%08x\n", stat); - nv_wr32(dev, 0x087004, stat); + nv_error(priv, "unhandled intr 0x%08x\n", stat); + nv_wr32(priv, 0x087004, stat); } - nv50_fb_vm_trap(dev, 1); + nv50_fb_trap(nouveau_fb(priv), 1); } -static void -nv98_crypt_destroy(struct drm_device *dev, int engine) +static int +nv98_crypt_tlb_flush(struct nouveau_engine *engine) { - struct nv98_crypt_priv *priv = nv_engine(dev, engine); - - nouveau_irq_unregister(dev, 14); - NVOBJ_ENGINE_DEL(dev, CRYPT); - kfree(priv); + nv50_vm_flush_engine(&engine->base, 0x0a); + return 0; } -int -nv98_crypt_create(struct drm_device *dev) +static int +nv98_crypt_ctor(struct nouveau_object *parent, struct nouveau_object *engine, + struct nouveau_oclass *oclass, void *data, u32 size, + struct nouveau_object **pobject) { struct nv98_crypt_priv *priv; + int ret; + + ret = nouveau_crypt_create(parent, engine, oclass, &priv); + *pobject = nv_object(priv); + if (ret) + return ret; + + nv_subdev(priv)->unit = 0x00004000; + nv_subdev(priv)->intr = nv98_crypt_intr; + nv_engine(priv)->cclass = &nv98_crypt_cclass; + nv_engine(priv)->sclass = nv98_crypt_sclass; + nv_engine(priv)->tlb_flush = nv98_crypt_tlb_flush; + return 0; +} + +static int +nv98_crypt_init(struct nouveau_object *object) +{ + struct nv98_crypt_priv *priv = (void *)object; + int ret, i; + + ret = nouveau_crypt_init(&priv->base); + if (ret) + return ret; - priv = kzalloc(sizeof(*priv), GFP_KERNEL); - if (!priv) - return -ENOMEM; + /* wait for exit interrupt to signal */ + nv_wait(priv, 0x087008, 0x00000010, 0x00000010); + nv_wr32(priv, 0x087004, 0x00000010); - priv->base.destroy = nv98_crypt_destroy; - priv->base.init = nv98_crypt_init; - priv->base.fini = nv98_crypt_fini; - priv->base.context_new = nv98_crypt_context_new; - priv->base.context_del = nv98_crypt_context_del; - priv->base.object_new = nv98_crypt_object_new; - priv->base.tlb_flush = nv98_crypt_tlb_flush; + /* upload microcode code and data segments */ + nv_wr32(priv, 0x087ff8, 0x00100000); + for (i = 0; i < ARRAY_SIZE(nv98_pcrypt_code); i++) + nv_wr32(priv, 0x087ff4, nv98_pcrypt_code[i]); - nouveau_irq_register(dev, 14, nv98_crypt_isr); + nv_wr32(priv, 0x087ff8, 0x00000000); + for (i = 0; i < ARRAY_SIZE(nv98_pcrypt_data); i++) + nv_wr32(priv, 0x087ff4, nv98_pcrypt_data[i]); - NVOBJ_ENGINE_ADD(dev, CRYPT, &priv->base); - NVOBJ_CLASS(dev, 0x88b4, CRYPT); + /* start it running */ + nv_wr32(priv, 0x08710c, 0x00000000); + nv_wr32(priv, 0x087104, 0x00000000); /* ENTRY */ + nv_wr32(priv, 0x087100, 0x00000002); /* TRIGGER */ return 0; } + +struct nouveau_oclass +nv98_crypt_oclass = { + .handle = NV_ENGINE(CRYPT, 0x98), + .ofuncs = &(struct nouveau_ofuncs) { + .ctor = nv98_crypt_ctor, + .dtor = _nouveau_crypt_dtor, + .init = nv98_crypt_init, + .fini = _nouveau_crypt_fini, + }, +}; diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/nv04.c b/drivers/gpu/drm/nouveau/core/engine/disp/nv04.c new file mode 100644 index 000000000000..1c919f2af89f --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/engine/disp/nv04.c @@ -0,0 +1,90 @@ +/* + * 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 nv04_disp_priv { + struct nouveau_disp base; +}; + +static struct nouveau_oclass +nv04_disp_sclass[] = { + {}, +}; + +static void +nv04_disp_intr_vblank(struct nv04_disp_priv *priv, int crtc) +{ + struct nouveau_disp *disp = &priv->base; + if (disp->vblank.notify) + disp->vblank.notify(disp->vblank.data, crtc); +} + +static void +nv04_disp_intr(struct nouveau_subdev *subdev) +{ + struct nv04_disp_priv *priv = (void *)subdev; + u32 crtc0 = nv_rd32(priv, 0x600100); + u32 crtc1 = nv_rd32(priv, 0x602100); + + if (crtc0 & 0x00000001) { + nv04_disp_intr_vblank(priv, 0); + nv_wr32(priv, 0x600100, 0x00000001); + } + + if (crtc1 & 0x00000001) { + nv04_disp_intr_vblank(priv, 1); + nv_wr32(priv, 0x602100, 0x00000001); + } +} + +static int +nv04_disp_ctor(struct nouveau_object *parent, struct nouveau_object *engine, + struct nouveau_oclass *oclass, void *data, u32 size, + struct nouveau_object **pobject) +{ + struct nv04_disp_priv *priv; + int ret; + + ret = nouveau_disp_create(parent, engine, oclass, "DISPLAY", + "display", &priv); + *pobject = nv_object(priv); + if (ret) + return ret; + + nv_engine(priv)->sclass = nv04_disp_sclass; + nv_subdev(priv)->intr = nv04_disp_intr; + return 0; +} + +struct nouveau_oclass +nv04_disp_oclass = { + .handle = NV_ENGINE(DISP, 0x04), + .ofuncs = &(struct nouveau_ofuncs) { + .ctor = nv04_disp_ctor, + .dtor = _nouveau_disp_dtor, + .init = _nouveau_disp_init, + .fini = _nouveau_disp_fini, + }, +}; diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/nv50.c b/drivers/gpu/drm/nouveau/core/engine/disp/nv50.c new file mode 100644 index 000000000000..16a9afb1060b --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/engine/disp/nv50.c @@ -0,0 +1,125 @@ +/* + * 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_disp_priv { + struct nouveau_disp base; +}; + +static struct nouveau_oclass +nv50_disp_sclass[] = { + {}, +}; + +static void +nv50_disp_intr_vblank(struct nv50_disp_priv *priv, int crtc) +{ + struct nouveau_disp *disp = &priv->base; + struct nouveau_software_chan *chan, *temp; + unsigned long flags; + + spin_lock_irqsave(&disp->vblank.lock, flags); + list_for_each_entry_safe(chan, temp, &disp->vblank.list, vblank.head) { + if (chan->vblank.crtc != crtc) + continue; + + nv_wr32(priv, 0x001704, chan->vblank.channel); + nv_wr32(priv, 0x001710, 0x80000000 | chan->vblank.ctxdma); + + if (nv_device(priv)->chipset == 0x50) { + nv_wr32(priv, 0x001570, chan->vblank.offset); + nv_wr32(priv, 0x001574, chan->vblank.value); + } else { + if (nv_device(priv)->chipset >= 0xc0) { + nv_wr32(priv, 0x06000c, + upper_32_bits(chan->vblank.offset)); + } + nv_wr32(priv, 0x060010, chan->vblank.offset); + nv_wr32(priv, 0x060014, chan->vblank.value); + } + + list_del(&chan->vblank.head); + if (disp->vblank.put) + disp->vblank.put(disp->vblank.data, crtc); + } + spin_unlock_irqrestore(&disp->vblank.lock, flags); + + if (disp->vblank.notify) + disp->vblank.notify(disp->vblank.data, crtc); +} + +static void +nv50_disp_intr(struct nouveau_subdev *subdev) +{ + struct nv50_disp_priv *priv = (void *)subdev; + u32 stat1 = nv_rd32(priv, 0x610024); + + if (stat1 & 0x00000004) { + nv50_disp_intr_vblank(priv, 0); + nv_wr32(priv, 0x610024, 0x00000004); + stat1 &= ~0x00000004; + } + + if (stat1 & 0x00000008) { + nv50_disp_intr_vblank(priv, 1); + nv_wr32(priv, 0x610024, 0x00000008); + stat1 &= ~0x00000008; + } + +} + +static int +nv50_disp_ctor(struct nouveau_object *parent, struct nouveau_object *engine, + struct nouveau_oclass *oclass, void *data, u32 size, + struct nouveau_object **pobject) +{ + struct nv50_disp_priv *priv; + int ret; + + ret = nouveau_disp_create(parent, engine, oclass, "PDISP", + "display", &priv); + *pobject = nv_object(priv); + if (ret) + return ret; + + nv_engine(priv)->sclass = nv50_disp_sclass; + nv_subdev(priv)->intr = nv50_disp_intr; + + INIT_LIST_HEAD(&priv->base.vblank.list); + spin_lock_init(&priv->base.vblank.lock); + return 0; +} + +struct nouveau_oclass +nv50_disp_oclass = { + .handle = NV_ENGINE(DISP, 0x50), + .ofuncs = &(struct nouveau_ofuncs) { + .ctor = nv50_disp_ctor, + .dtor = _nouveau_disp_dtor, + .init = _nouveau_disp_init, + .fini = _nouveau_disp_fini, + }, +}; diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/nvd0.c b/drivers/gpu/drm/nouveau/core/engine/disp/nvd0.c new file mode 100644 index 000000000000..d93efbcf75b8 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/engine/disp/nvd0.c @@ -0,0 +1,118 @@ +/* + * 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 + +struct nvd0_disp_priv { + struct nouveau_disp base; +}; + +static struct nouveau_oclass +nvd0_disp_sclass[] = { + {}, +}; + +static void +nvd0_disp_intr_vblank(struct nvd0_disp_priv *priv, int crtc) +{ + struct nouveau_bar *bar = nouveau_bar(priv); + struct nouveau_disp *disp = &priv->base; + struct nouveau_software_chan *chan, *temp; + unsigned long flags; + + spin_lock_irqsave(&disp->vblank.lock, flags); + list_for_each_entry_safe(chan, temp, &disp->vblank.list, vblank.head) { + if (chan->vblank.crtc != crtc) + continue; + + nv_wr32(priv, 0x001718, 0x80000000 | chan->vblank.channel); + bar->flush(bar); + nv_wr32(priv, 0x06000c, upper_32_bits(chan->vblank.offset)); + nv_wr32(priv, 0x060010, lower_32_bits(chan->vblank.offset)); + nv_wr32(priv, 0x060014, chan->vblank.value); + + list_del(&chan->vblank.head); + if (disp->vblank.put) + disp->vblank.put(disp->vblank.data, crtc); + } + spin_unlock_irqrestore(&disp->vblank.lock, flags); + + if (disp->vblank.notify) + disp->vblank.notify(disp->vblank.data, crtc); +} + +static void +nvd0_disp_intr(struct nouveau_subdev *subdev) +{ + struct nvd0_disp_priv *priv = (void *)subdev; + u32 intr = nv_rd32(priv, 0x610088); + int i; + + for (i = 0; i < 4; i++) { + u32 mask = 0x01000000 << i; + if (mask & intr) { + u32 stat = nv_rd32(priv, 0x6100bc + (i * 0x800)); + if (stat & 0x00000001) + nvd0_disp_intr_vblank(priv, i); + nv_mask(priv, 0x6100bc + (i * 0x800), 0, 0); + nv_rd32(priv, 0x6100c0 + (i * 0x800)); + } + } +} + +static int +nvd0_disp_ctor(struct nouveau_object *parent, struct nouveau_object *engine, + struct nouveau_oclass *oclass, void *data, u32 size, + struct nouveau_object **pobject) +{ + struct nvd0_disp_priv *priv; + int ret; + + ret = nouveau_disp_create(parent, engine, oclass, "PDISP", + "display", &priv); + *pobject = nv_object(priv); + if (ret) + return ret; + + nv_engine(priv)->sclass = nvd0_disp_sclass; + nv_subdev(priv)->intr = nvd0_disp_intr; + + INIT_LIST_HEAD(&priv->base.vblank.list); + spin_lock_init(&priv->base.vblank.lock); + return 0; +} + +struct nouveau_oclass +nvd0_disp_oclass = { + .handle = NV_ENGINE(DISP, 0xd0), + .ofuncs = &(struct nouveau_ofuncs) { + .ctor = nvd0_disp_ctor, + .dtor = _nouveau_disp_dtor, + .init = _nouveau_disp_init, + .fini = _nouveau_disp_fini, + }, +}; diff --git a/drivers/gpu/drm/nouveau/core/engine/dmaobj/base.c b/drivers/gpu/drm/nouveau/core/engine/dmaobj/base.c new file mode 100644 index 000000000000..e1f013d39768 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/engine/dmaobj/base.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 + +#include +#include + +int +nouveau_dmaobj_create_(struct nouveau_object *parent, + struct nouveau_object *engine, + struct nouveau_oclass *oclass, + void *data, u32 size, int len, void **pobject) +{ + struct nv_dma_class *args = data; + struct nouveau_dmaobj *object; + int ret; + + if (size < sizeof(*args)) + return -EINVAL; + + ret = nouveau_object_create_(parent, engine, oclass, 0, len, pobject); + object = *pobject; + if (ret) + return ret; + + switch (args->flags & NV_DMA_TARGET_MASK) { + case NV_DMA_TARGET_VM: + object->target = NV_MEM_TARGET_VM; + break; + case NV_DMA_TARGET_VRAM: + object->target = NV_MEM_TARGET_VRAM; + break; + case NV_DMA_TARGET_PCI: + object->target = NV_MEM_TARGET_PCI; + break; + case NV_DMA_TARGET_PCI_US: + case NV_DMA_TARGET_AGP: + object->target = NV_MEM_TARGET_PCI_NOSNOOP; + break; + default: + return -EINVAL; + } + + switch (args->flags & NV_DMA_ACCESS_MASK) { + case NV_DMA_ACCESS_VM: + object->access = NV_MEM_ACCESS_VM; + break; + case NV_DMA_ACCESS_RD: + object->access = NV_MEM_ACCESS_RO; + break; + case NV_DMA_ACCESS_WR: + object->access = NV_MEM_ACCESS_WO; + break; + case NV_DMA_ACCESS_RDWR: + object->access = NV_MEM_ACCESS_RW; + break; + default: + return -EINVAL; + } + + object->start = args->start; + object->limit = args->limit; + return 0; +} diff --git a/drivers/gpu/drm/nouveau/core/engine/dmaobj/nv04.c b/drivers/gpu/drm/nouveau/core/engine/dmaobj/nv04.c new file mode 100644 index 000000000000..b0d3651fcaba --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/engine/dmaobj/nv04.c @@ -0,0 +1,176 @@ +/* + * Copyright 2012 Red Hat Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: Ben Skeggs + */ + +#include + +#include +#include + +#include + +struct nv04_dmaeng_priv { + struct nouveau_dmaeng base; +}; + +struct nv04_dmaobj_priv { + struct nouveau_dmaobj base; +}; + +static int +nv04_dmaobj_bind(struct nouveau_dmaeng *dmaeng, + struct nouveau_object *parent, + struct nouveau_dmaobj *dmaobj, + struct nouveau_gpuobj **pgpuobj) +{ + struct nouveau_gpuobj *gpuobj; + u32 flags0 = nv_mclass(dmaobj); + u32 flags2 = 0x00000000; + u32 offset = (dmaobj->start & 0xfffff000); + u32 adjust = (dmaobj->start & 0x00000fff); + u32 length = dmaobj->limit - dmaobj->start; + int ret; + + if (dmaobj->target == NV_MEM_TARGET_VM) { + gpuobj = nv04_vmmgr(dmaeng)->vm->pgt[0].obj[0]; + if (dmaobj->start == 0) + return nouveau_gpuobj_dup(parent, gpuobj, pgpuobj); + + offset = nv_ro32(gpuobj, 8 + (offset >> 10)); + offset &= 0xfffff000; + dmaobj->target = NV_MEM_TARGET_PCI; + dmaobj->access = NV_MEM_ACCESS_RW; + } + + switch (dmaobj->target) { + case NV_MEM_TARGET_VRAM: + flags0 |= 0x00003000; + break; + case NV_MEM_TARGET_PCI: + flags0 |= 0x00023000; + break; + case NV_MEM_TARGET_PCI_NOSNOOP: + flags0 |= 0x00033000; + break; + default: + return -EINVAL; + } + + switch (dmaobj->access) { + case NV_MEM_ACCESS_RO: + flags0 |= 0x00004000; + break; + case NV_MEM_ACCESS_WO: + flags0 |= 0x00008000; + case NV_MEM_ACCESS_RW: + flags2 |= 0x00000002; + break; + default: + return -EINVAL; + } + + ret = nouveau_gpuobj_new(parent, parent, 16, 16, 0, &gpuobj); + *pgpuobj = gpuobj; + if (ret == 0) { + nv_wo32(*pgpuobj, 0x00, flags0 | (adjust << 20)); + nv_wo32(*pgpuobj, 0x04, length); + nv_wo32(*pgpuobj, 0x08, flags2 | offset); + nv_wo32(*pgpuobj, 0x0c, flags2 | offset); + } + + return ret; +} + +static int +nv04_dmaobj_ctor(struct nouveau_object *parent, struct nouveau_object *engine, + struct nouveau_oclass *oclass, void *data, u32 size, + struct nouveau_object **pobject) +{ + struct nouveau_dmaeng *dmaeng = (void *)engine; + struct nv04_dmaobj_priv *dmaobj; + struct nouveau_gpuobj *gpuobj; + int ret; + + ret = nouveau_dmaobj_create(parent, engine, oclass, + data, size, &dmaobj); + *pobject = nv_object(dmaobj); + if (ret) + return ret; + + switch (nv_mclass(parent)) { + case 0x006e: + ret = dmaeng->bind(dmaeng, *pobject, &dmaobj->base, &gpuobj); + nouveau_object_ref(NULL, pobject); + *pobject = nv_object(gpuobj); + break; + default: + break; + } + + return ret; +} + +static struct nouveau_ofuncs +nv04_dmaobj_ofuncs = { + .ctor = nv04_dmaobj_ctor, + .dtor = _nouveau_dmaobj_dtor, + .init = _nouveau_dmaobj_init, + .fini = _nouveau_dmaobj_fini, +}; + +static struct nouveau_oclass +nv04_dmaobj_sclass[] = { + { 0x0002, &nv04_dmaobj_ofuncs }, + { 0x0003, &nv04_dmaobj_ofuncs }, + { 0x003d, &nv04_dmaobj_ofuncs }, + {} +}; + +static int +nv04_dmaeng_ctor(struct nouveau_object *parent, struct nouveau_object *engine, + struct nouveau_oclass *oclass, void *data, u32 size, + struct nouveau_object **pobject) +{ + struct nv04_dmaeng_priv *priv; + int ret; + + ret = nouveau_dmaeng_create(parent, engine, oclass, &priv); + *pobject = nv_object(priv); + if (ret) + return ret; + + priv->base.base.sclass = nv04_dmaobj_sclass; + priv->base.bind = nv04_dmaobj_bind; + return 0; +} + +struct nouveau_oclass +nv04_dmaeng_oclass = { + .handle = NV_ENGINE(DMAOBJ, 0x04), + .ofuncs = &(struct nouveau_ofuncs) { + .ctor = nv04_dmaeng_ctor, + .dtor = _nouveau_dmaeng_dtor, + .init = _nouveau_dmaeng_init, + .fini = _nouveau_dmaeng_fini, + }, +}; diff --git a/drivers/gpu/drm/nouveau/core/engine/dmaobj/nv50.c b/drivers/gpu/drm/nouveau/core/engine/dmaobj/nv50.c new file mode 100644 index 000000000000..8207ac9a0bb9 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/engine/dmaobj/nv50.c @@ -0,0 +1,168 @@ +/* + * 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 + +struct nv50_dmaeng_priv { + struct nouveau_dmaeng base; +}; + +struct nv50_dmaobj_priv { + struct nouveau_dmaobj base; +}; + +static int +nv50_dmaobj_bind(struct nouveau_dmaeng *dmaeng, + struct nouveau_object *parent, + struct nouveau_dmaobj *dmaobj, + struct nouveau_gpuobj **pgpuobj) +{ + u32 flags = nv_mclass(dmaobj); + int ret; + + switch (dmaobj->target) { + case NV_MEM_TARGET_VM: + flags |= 0x00000000; + flags |= 0x60000000; /* COMPRESSION_USEVM */ + flags |= 0x1fc00000; /* STORAGE_TYPE_USEVM */ + break; + case NV_MEM_TARGET_VRAM: + flags |= 0x00010000; + flags |= 0x00100000; /* ACCESSUS_USER_SYSTEM */ + break; + case NV_MEM_TARGET_PCI: + flags |= 0x00020000; + flags |= 0x00100000; /* ACCESSUS_USER_SYSTEM */ + break; + case NV_MEM_TARGET_PCI_NOSNOOP: + flags |= 0x00030000; + flags |= 0x00100000; /* ACCESSUS_USER_SYSTEM */ + break; + default: + return -EINVAL; + } + + switch (dmaobj->access) { + case NV_MEM_ACCESS_VM: + break; + case NV_MEM_ACCESS_RO: + flags |= 0x00040000; + break; + case NV_MEM_ACCESS_WO: + case NV_MEM_ACCESS_RW: + flags |= 0x00080000; + break; + } + + ret = nouveau_gpuobj_new(parent, parent, 24, 32, 0, pgpuobj); + if (ret == 0) { + nv_wo32(*pgpuobj, 0x00, flags); + nv_wo32(*pgpuobj, 0x04, lower_32_bits(dmaobj->limit)); + nv_wo32(*pgpuobj, 0x08, lower_32_bits(dmaobj->start)); + nv_wo32(*pgpuobj, 0x0c, upper_32_bits(dmaobj->limit) << 24 | + upper_32_bits(dmaobj->start)); + nv_wo32(*pgpuobj, 0x10, 0x00000000); + nv_wo32(*pgpuobj, 0x14, 0x00000000); + } + + return ret; +} + +static int +nv50_dmaobj_ctor(struct nouveau_object *parent, struct nouveau_object *engine, + struct nouveau_oclass *oclass, void *data, u32 size, + struct nouveau_object **pobject) +{ + struct nouveau_dmaeng *dmaeng = (void *)engine; + struct nv50_dmaobj_priv *dmaobj; + struct nouveau_gpuobj *gpuobj; + int ret; + + ret = nouveau_dmaobj_create(parent, engine, oclass, + data, size, &dmaobj); + *pobject = nv_object(dmaobj); + if (ret) + return ret; + + switch (nv_mclass(parent)) { + case 0x506f: + case 0x826f: + ret = dmaeng->bind(dmaeng, *pobject, &dmaobj->base, &gpuobj); + nouveau_object_ref(NULL, pobject); + *pobject = nv_object(gpuobj); + break; + default: + break; + } + + return ret; +} + +static struct nouveau_ofuncs +nv50_dmaobj_ofuncs = { + .ctor = nv50_dmaobj_ctor, + .dtor = _nouveau_dmaobj_dtor, + .init = _nouveau_dmaobj_init, + .fini = _nouveau_dmaobj_fini, +}; + +static struct nouveau_oclass +nv50_dmaobj_sclass[] = { + { 0x0002, &nv50_dmaobj_ofuncs }, + { 0x0003, &nv50_dmaobj_ofuncs }, + { 0x003d, &nv50_dmaobj_ofuncs }, + {} +}; + +static int +nv50_dmaeng_ctor(struct nouveau_object *parent, struct nouveau_object *engine, + struct nouveau_oclass *oclass, void *data, u32 size, + struct nouveau_object **pobject) +{ + struct nv50_dmaeng_priv *priv; + int ret; + + ret = nouveau_dmaeng_create(parent, engine, oclass, &priv); + *pobject = nv_object(priv); + if (ret) + return ret; + + priv->base.base.sclass = nv50_dmaobj_sclass; + priv->base.bind = nv50_dmaobj_bind; + return 0; +} + +struct nouveau_oclass +nv50_dmaeng_oclass = { + .handle = NV_ENGINE(DMAOBJ, 0x50), + .ofuncs = &(struct nouveau_ofuncs) { + .ctor = nv50_dmaeng_ctor, + .dtor = _nouveau_dmaeng_dtor, + .init = _nouveau_dmaeng_init, + .fini = _nouveau_dmaeng_fini, + }, +}; diff --git a/drivers/gpu/drm/nouveau/core/engine/dmaobj/nvc0.c b/drivers/gpu/drm/nouveau/core/engine/dmaobj/nvc0.c new file mode 100644 index 000000000000..5baa08695535 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/engine/dmaobj/nvc0.c @@ -0,0 +1,99 @@ +/* + * 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 + +struct nvc0_dmaeng_priv { + struct nouveau_dmaeng base; +}; + +struct nvc0_dmaobj_priv { + struct nouveau_dmaobj base; +}; + +static int +nvc0_dmaobj_ctor(struct nouveau_object *parent, struct nouveau_object *engine, + struct nouveau_oclass *oclass, void *data, u32 size, + struct nouveau_object **pobject) +{ + struct nvc0_dmaobj_priv *dmaobj; + int ret; + + ret = nouveau_dmaobj_create(parent, engine, oclass, data, size, &dmaobj); + *pobject = nv_object(dmaobj); + if (ret) + return ret; + + if (dmaobj->base.target != NV_MEM_TARGET_VM || dmaobj->base.start) + return -EINVAL; + + return 0; +} + +static struct nouveau_ofuncs +nvc0_dmaobj_ofuncs = { + .ctor = nvc0_dmaobj_ctor, + .dtor = _nouveau_dmaobj_dtor, + .init = _nouveau_dmaobj_init, + .fini = _nouveau_dmaobj_fini, +}; + +static struct nouveau_oclass +nvc0_dmaobj_sclass[] = { + { 0x0002, &nvc0_dmaobj_ofuncs }, + { 0x0003, &nvc0_dmaobj_ofuncs }, + { 0x003d, &nvc0_dmaobj_ofuncs }, + {} +}; + +static int +nvc0_dmaeng_ctor(struct nouveau_object *parent, struct nouveau_object *engine, + struct nouveau_oclass *oclass, void *data, u32 size, + struct nouveau_object **pobject) +{ + struct nvc0_dmaeng_priv *priv; + int ret; + + ret = nouveau_dmaeng_create(parent, engine, oclass, &priv); + *pobject = nv_object(priv); + if (ret) + return ret; + + priv->base.base.sclass = nvc0_dmaobj_sclass; + return 0; +} + +struct nouveau_oclass +nvc0_dmaeng_oclass = { + .handle = NV_ENGINE(DMAOBJ, 0xc0), + .ofuncs = &(struct nouveau_ofuncs) { + .ctor = nvc0_dmaeng_ctor, + .dtor = _nouveau_dmaeng_dtor, + .init = _nouveau_dmaeng_init, + .fini = _nouveau_dmaeng_fini, + }, +}; diff --git a/drivers/gpu/drm/nouveau/core/engine/fifo/base.c b/drivers/gpu/drm/nouveau/core/engine/fifo/base.c new file mode 100644 index 000000000000..edeb76ee648c --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/engine/fifo/base.c @@ -0,0 +1,165 @@ +/* + * 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_fifo_channel_create_(struct nouveau_object *parent, + struct nouveau_object *engine, + struct nouveau_oclass *oclass, + int bar, u32 addr, u32 size, u32 pushbuf, + u32 engmask, int len, void **ptr) +{ + struct nouveau_device *device = nv_device(engine); + struct nouveau_fifo *priv = (void *)engine; + struct nouveau_fifo_chan *chan; + struct nouveau_dmaeng *dmaeng; + unsigned long flags; + int ret; + + /* create base object class */ + ret = nouveau_namedb_create_(parent, engine, oclass, 0, NULL, + engmask, len, ptr); + chan = *ptr; + if (ret) + return ret; + + /* validate dma object representing push buffer */ + chan->pushdma = (void *)nouveau_handle_ref(parent, pushbuf); + if (!chan->pushdma) + return -ENOENT; + + dmaeng = (void *)chan->pushdma->base.engine; + switch (chan->pushdma->base.oclass->handle) { + case 0x0002: + case 0x003d: + break; + default: + return -EINVAL; + } + + if (dmaeng->bind) { + ret = dmaeng->bind(dmaeng, parent, chan->pushdma, &chan->pushgpu); + if (ret) + return ret; + } + + /* find a free fifo channel */ + spin_lock_irqsave(&priv->lock, flags); + for (chan->chid = priv->min; chan->chid < priv->max; chan->chid++) { + if (!priv->channel[chan->chid]) { + priv->channel[chan->chid] = nv_object(chan); + break; + } + } + spin_unlock_irqrestore(&priv->lock, flags); + + if (chan->chid == priv->max) { + nv_error(priv, "no free channels\n"); + return -ENOSPC; + } + + /* map fifo control registers */ + chan->user = ioremap(pci_resource_start(device->pdev, bar) + addr + + (chan->chid * size), size); + if (!chan->user) + return -EFAULT; + + chan->size = size; + return 0; +} + +void +nouveau_fifo_channel_destroy(struct nouveau_fifo_chan *chan) +{ + struct nouveau_fifo *priv = (void *)nv_object(chan)->engine; + unsigned long flags; + + iounmap(chan->user); + + spin_lock_irqsave(&priv->lock, flags); + priv->channel[chan->chid] = NULL; + spin_unlock_irqrestore(&priv->lock, flags); + + nouveau_gpuobj_ref(NULL, &chan->pushgpu); + nouveau_object_ref(NULL, (struct nouveau_object **)&chan->pushdma); + nouveau_namedb_destroy(&chan->base); +} + +void +_nouveau_fifo_channel_dtor(struct nouveau_object *object) +{ + struct nouveau_fifo_chan *chan = (void *)object; + nouveau_fifo_channel_destroy(chan); +} + +u32 +_nouveau_fifo_channel_rd32(struct nouveau_object *object, u32 addr) +{ + struct nouveau_fifo_chan *chan = (void *)object; + return ioread32_native(chan->user + addr); +} + +void +_nouveau_fifo_channel_wr32(struct nouveau_object *object, u32 addr, u32 data) +{ + struct nouveau_fifo_chan *chan = (void *)object; + iowrite32_native(data, chan->user + addr); +} + +void +nouveau_fifo_destroy(struct nouveau_fifo *priv) +{ + kfree(priv->channel); + nouveau_engine_destroy(&priv->base); +} + +int +nouveau_fifo_create_(struct nouveau_object *parent, + struct nouveau_object *engine, + struct nouveau_oclass *oclass, + int min, int max, int length, void **pobject) +{ + struct nouveau_fifo *priv; + int ret; + + ret = nouveau_engine_create_(parent, engine, oclass, true, "PFIFO", + "fifo", length, pobject); + priv = *pobject; + if (ret) + return ret; + + priv->min = min; + priv->max = max; + priv->channel = kzalloc(sizeof(*priv->channel) * (max + 1), GFP_KERNEL); + if (!priv->channel) + return -ENOMEM; + + spin_lock_init(&priv->lock); + return 0; +} diff --git a/drivers/gpu/drm/nouveau/core/engine/fifo/nv04.c b/drivers/gpu/drm/nouveau/core/engine/fifo/nv04.c index 6ab7eb0dd9bb..8b7513f4dc8f 100644 --- a/drivers/gpu/drm/nouveau/core/engine/fifo/nv04.c +++ b/drivers/gpu/drm/nouveau/core/engine/fifo/nv04.c @@ -1,44 +1,45 @@ /* - * Copyright (C) 2012 Ben Skeggs. - * All Rights Reserved. + * 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: + * 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 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 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 */ -#include "drmP.h" -#include "drm.h" -#include "nouveau_drv.h" -#include -#include "nouveau_util.h" +#include +#include +#include +#include +#include #include -#include "nouveau_software.h" - -static struct ramfc_desc { - unsigned bits:6; - unsigned ctxs:5; - unsigned ctxp:8; - unsigned regs:5; - unsigned regp; -} nv04_ramfc[] = { + +#include +#include +#include +#include + +#include + +#include "nv04.h" + +static struct ramfc_desc +nv04_ramfc[] = { { 32, 0, 0x00, 0, NV04_PFIFO_CACHE1_DMA_PUT }, { 32, 0, 0x04, 0, NV04_PFIFO_CACHE1_DMA_GET }, { 16, 0, 0x08, 0, NV04_PFIFO_CACHE1_DMA_INSTANCE }, @@ -50,283 +51,360 @@ static struct ramfc_desc { {} }; -struct nv04_fifo_priv { - struct nouveau_fifo_priv base; - struct ramfc_desc *ramfc_desc; - struct nouveau_gpuobj *ramro; - struct nouveau_gpuobj *ramfc; -}; +/******************************************************************************* + * FIFO channel objects + ******************************************************************************/ -struct nv04_fifo_chan { - struct nouveau_fifo_chan base; - u32 ramfc; -}; - -bool -nv04_fifo_cache_pull(struct drm_device *dev, bool enable) +int +nv04_fifo_object_attach(struct nouveau_object *parent, + struct nouveau_object *object, u32 handle) { - int pull = nv_mask(dev, NV04_PFIFO_CACHE1_PULL0, 1, enable); - - if (!enable) { - /* In some cases the PFIFO puller may be left in an - * inconsistent state if you try to stop it when it's - * busy translating handles. Sometimes you get a - * PFIFO_CACHE_ERROR, sometimes it just fails silently - * sending incorrect instance offsets to PGRAPH after - * it's started up again. To avoid the latter we - * invalidate the most recently calculated instance. - */ - if (!nv_wait(dev, NV04_PFIFO_CACHE1_PULL0, - NV04_PFIFO_CACHE1_PULL0_HASH_BUSY, 0)) - NV_ERROR(dev, "Timeout idling the PFIFO puller.\n"); - - if (nv_rd32(dev, NV04_PFIFO_CACHE1_PULL0) & - NV04_PFIFO_CACHE1_PULL0_HASH_FAILED) - nv_wr32(dev, NV03_PFIFO_INTR_0, - NV_PFIFO_INTR_CACHE_ERROR); - - nv_wr32(dev, NV04_PFIFO_CACHE1_HASH, 0); + struct nv04_fifo_priv *priv = (void *)parent->engine; + struct nv04_fifo_chan *chan = (void *)parent; + u32 context, chid = chan->base.chid; + int ret; + + if (nv_iclass(object, NV_GPUOBJ_CLASS)) + context = nv_gpuobj(object)->addr >> 4; + else + context = 0x00000004; /* just non-zero */ + + switch (nv_engidx(object->engine)) { + case NVDEV_ENGINE_DMAOBJ: + case NVDEV_ENGINE_SW: + context |= 0x00000000; + break; + case NVDEV_ENGINE_GR: + context |= 0x00010000; + break; + case NVDEV_ENGINE_MPEG: + context |= 0x00020000; + break; + default: + return -EINVAL; } - return pull & 1; + context |= 0x80000000; /* valid */ + context |= chid << 24; + + mutex_lock(&nv_subdev(priv)->mutex); + ret = nouveau_ramht_insert(priv->ramht, chid, handle, context); + mutex_unlock(&nv_subdev(priv)->mutex); + return ret; +} + +void +nv04_fifo_object_detach(struct nouveau_object *parent, int cookie) +{ + struct nv04_fifo_priv *priv = (void *)parent->engine; + mutex_lock(&nv_subdev(priv)->mutex); + nouveau_ramht_remove(priv->ramht, cookie); + mutex_unlock(&nv_subdev(priv)->mutex); } static int -nv04_fifo_context_new(struct nouveau_channel *chan, int engine) +nv04_fifo_chan_ctor(struct nouveau_object *parent, + struct nouveau_object *engine, + struct nouveau_oclass *oclass, void *data, u32 size, + struct nouveau_object **pobject) { - struct drm_device *dev = chan->dev; - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nv04_fifo_priv *priv = nv_engine(dev, engine); - struct nv04_fifo_chan *fctx; - unsigned long flags; + struct nv04_fifo_priv *priv = (void *)engine; + struct nv04_fifo_chan *chan; + struct nv_channel_dma_class *args = data; int ret; - fctx = chan->engctx[engine] = kzalloc(sizeof(*fctx), GFP_KERNEL); - if (!fctx) - return -ENOMEM; + if (size < sizeof(*args)) + return -EINVAL; - fctx->ramfc = chan->id * 32; + ret = nouveau_fifo_channel_create(parent, engine, oclass, 0, 0x800000, + 0x10000, args->pushbuf, + (1 << NVDEV_ENGINE_DMAOBJ) | + (1 << NVDEV_ENGINE_SW) | + (1 << NVDEV_ENGINE_GR), &chan); + *pobject = nv_object(chan); + if (ret) + return ret; - /* map channel control registers */ - chan->user = ioremap(pci_resource_start(dev->pdev, 0) + - NV03_USER(chan->id), PAGE_SIZE); - if (!chan->user) { - ret = -ENOMEM; - goto error; - } + nv_parent(chan)->object_attach = nv04_fifo_object_attach; + nv_parent(chan)->object_detach = nv04_fifo_object_detach; + chan->ramfc = chan->base.chid * 32; - /* initialise default fifo context */ - nv_wo32(priv->ramfc, fctx->ramfc + 0x00, chan->pushbuf_base); - nv_wo32(priv->ramfc, fctx->ramfc + 0x04, chan->pushbuf_base); - nv_wo32(priv->ramfc, fctx->ramfc + 0x08, chan->pushbuf->addr >> 4); - nv_wo32(priv->ramfc, fctx->ramfc + 0x10, + nv_wo32(priv->ramfc, chan->ramfc + 0x00, args->offset); + nv_wo32(priv->ramfc, chan->ramfc + 0x04, args->offset); + nv_wo32(priv->ramfc, chan->ramfc + 0x08, chan->base.pushgpu->addr >> 4); + nv_wo32(priv->ramfc, chan->ramfc + 0x10, NV_PFIFO_CACHE1_DMA_FETCH_TRIG_128_BYTES | NV_PFIFO_CACHE1_DMA_FETCH_SIZE_128_BYTES | #ifdef __BIG_ENDIAN NV_PFIFO_CACHE1_BIG_ENDIAN | #endif NV_PFIFO_CACHE1_DMA_FETCH_MAX_REQS_8); + return 0; +} + +void +nv04_fifo_chan_dtor(struct nouveau_object *object) +{ + struct nv04_fifo_priv *priv = (void *)object->engine; + struct nv04_fifo_chan *chan = (void *)object; + struct ramfc_desc *c = priv->ramfc_desc; - /* enable dma mode on the channel */ - spin_lock_irqsave(&dev_priv->context_switch_lock, flags); - nv_mask(dev, NV04_PFIFO_MODE, (1 << chan->id), (1 << chan->id)); - spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags); + do { + nv_wo32(priv->ramfc, chan->ramfc + c->ctxp, 0x00000000); + } while ((++c)->bits); + + nouveau_fifo_channel_destroy(&chan->base); +} -error: +int +nv04_fifo_chan_init(struct nouveau_object *object) +{ + struct nv04_fifo_priv *priv = (void *)object->engine; + struct nv04_fifo_chan *chan = (void *)object; + u32 mask = 1 << chan->base.chid; + unsigned long flags; + int ret; + + ret = nouveau_fifo_channel_init(&chan->base); if (ret) - priv->base.base.context_del(chan, engine); - return ret; + return ret; + + spin_lock_irqsave(&priv->base.lock, flags); + nv_mask(priv, NV04_PFIFO_MODE, mask, mask); + spin_unlock_irqrestore(&priv->base.lock, flags); + return 0; } -void -nv04_fifo_context_del(struct nouveau_channel *chan, int engine) +int +nv04_fifo_chan_fini(struct nouveau_object *object, bool suspend) { - struct drm_device *dev = chan->dev; - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nv04_fifo_priv *priv = nv_engine(chan->dev, engine); - struct nv04_fifo_chan *fctx = chan->engctx[engine]; - struct ramfc_desc *c = priv->ramfc_desc; + struct nv04_fifo_priv *priv = (void *)object->engine; + struct nv04_fifo_chan *chan = (void *)object; + struct nouveau_gpuobj *fctx = priv->ramfc; + struct ramfc_desc *c; unsigned long flags; - int chid; + u32 data = chan->ramfc; + u32 chid; /* prevent fifo context switches */ - spin_lock_irqsave(&dev_priv->context_switch_lock, flags); - nv_wr32(dev, NV03_PFIFO_CACHES, 0); + spin_lock_irqsave(&priv->base.lock, flags); + nv_wr32(priv, NV03_PFIFO_CACHES, 0); /* if this channel is active, replace it with a null context */ - chid = nv_rd32(dev, NV03_PFIFO_CACHE1_PUSH1) & priv->base.channels; - if (chid == chan->id) { - nv_mask(dev, NV04_PFIFO_CACHE1_DMA_PUSH, 0x00000001, 0); - nv_wr32(dev, NV03_PFIFO_CACHE1_PUSH0, 0); - nv_mask(dev, NV04_PFIFO_CACHE1_PULL0, 0x00000001, 0); + chid = nv_rd32(priv, NV03_PFIFO_CACHE1_PUSH1) & priv->base.max; + if (chid == chan->base.chid) { + nv_mask(priv, NV04_PFIFO_CACHE1_DMA_PUSH, 0x00000001, 0); + nv_wr32(priv, NV03_PFIFO_CACHE1_PUSH0, 0); + nv_mask(priv, NV04_PFIFO_CACHE1_PULL0, 0x00000001, 0); + c = priv->ramfc_desc; do { - u32 mask = ((1ULL << c->bits) - 1) << c->regs; - nv_mask(dev, c->regp, mask, 0x00000000); - nv_wo32(priv->ramfc, fctx->ramfc + c->ctxp, 0x00000000); + u32 rm = ((1ULL << c->bits) - 1) << c->regs; + u32 cm = ((1ULL << c->bits) - 1) << c->ctxs; + u32 rv = (nv_rd32(priv, c->regp) & rm) >> c->regs; + u32 cv = (nv_ro32(fctx, c->ctxp + data) & ~cm); + nv_wo32(fctx, c->ctxp + data, cv | (rv << c->ctxs)); + } while ((++c)->bits); + + c = priv->ramfc_desc; + do { + nv_wr32(priv, c->regp, 0x00000000); } while ((++c)->bits); - nv_wr32(dev, NV03_PFIFO_CACHE1_GET, 0); - nv_wr32(dev, NV03_PFIFO_CACHE1_PUT, 0); - nv_wr32(dev, NV03_PFIFO_CACHE1_PUSH1, priv->base.channels); - nv_wr32(dev, NV03_PFIFO_CACHE1_PUSH0, 1); - nv_wr32(dev, NV04_PFIFO_CACHE1_PULL0, 1); + nv_wr32(priv, NV03_PFIFO_CACHE1_GET, 0); + nv_wr32(priv, NV03_PFIFO_CACHE1_PUT, 0); + nv_wr32(priv, NV03_PFIFO_CACHE1_PUSH1, priv->base.max); + nv_wr32(priv, NV03_PFIFO_CACHE1_PUSH0, 1); + nv_wr32(priv, NV04_PFIFO_CACHE1_PULL0, 1); } /* restore normal operation, after disabling dma mode */ - nv_mask(dev, NV04_PFIFO_MODE, 1 << chan->id, 0); - nv_wr32(dev, NV03_PFIFO_CACHES, 1); - spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags); - - /* clean up */ - nouveau_gpuobj_ref(NULL, &chan->ramfc); /*XXX: nv40 */ - if (chan->user) { - iounmap(chan->user); - chan->user = NULL; - } + nv_mask(priv, NV04_PFIFO_MODE, 1 << chan->base.chid, 0); + nv_wr32(priv, NV03_PFIFO_CACHES, 1); + spin_unlock_irqrestore(&priv->base.lock, flags); + + return nouveau_fifo_channel_fini(&chan->base, suspend); } +static struct nouveau_ofuncs +nv04_fifo_ofuncs = { + .ctor = nv04_fifo_chan_ctor, + .dtor = nv04_fifo_chan_dtor, + .init = nv04_fifo_chan_init, + .fini = nv04_fifo_chan_fini, + .rd32 = _nouveau_fifo_channel_rd32, + .wr32 = _nouveau_fifo_channel_wr32, +}; + +static struct nouveau_oclass +nv04_fifo_sclass[] = { + { 0x006e, &nv04_fifo_ofuncs }, + {} +}; + +/******************************************************************************* + * FIFO context - basically just the instmem reserved for the channel + ******************************************************************************/ + int -nv04_fifo_init(struct drm_device *dev, int engine) +nv04_fifo_context_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 nv04_fifo_priv *priv = nv_engine(dev, engine); - int i; + struct nv04_fifo_base *base; + int ret; - nv_mask(dev, NV03_PMC_ENABLE, NV_PMC_ENABLE_PFIFO, 0); - nv_mask(dev, NV03_PMC_ENABLE, NV_PMC_ENABLE_PFIFO, NV_PMC_ENABLE_PFIFO); + ret = nouveau_fifo_context_create(parent, engine, oclass, NULL, 0x1000, + 0x1000, NVOBJ_FLAG_HEAP, &base); + *pobject = nv_object(base); + if (ret) + return ret; - nv_wr32(dev, NV04_PFIFO_DELAY_0, 0x000000ff); - nv_wr32(dev, NV04_PFIFO_DMA_TIMESLICE, 0x0101ffff); + return 0; +} - nv_wr32(dev, NV03_PFIFO_RAMHT, (0x03 << 24) /* search 128 */ | - ((dev_priv->ramht->bits - 9) << 16) | - (dev_priv->ramht->gpuobj->addr >> 8)); - nv_wr32(dev, NV03_PFIFO_RAMRO, priv->ramro->addr >> 8); - nv_wr32(dev, NV03_PFIFO_RAMFC, priv->ramfc->addr >> 8); +static struct nouveau_oclass +nv04_fifo_cclass = { + .handle = NV_ENGCTX(FIFO, 0x04), + .ofuncs = &(struct nouveau_ofuncs) { + .ctor = nv04_fifo_context_ctor, + .dtor = _nouveau_fifo_context_dtor, + .init = _nouveau_fifo_context_init, + .fini = _nouveau_fifo_context_fini, + .rd32 = _nouveau_fifo_context_rd32, + .wr32 = _nouveau_fifo_context_wr32, + }, +}; - nv_wr32(dev, NV03_PFIFO_CACHE1_PUSH1, priv->base.channels); +/******************************************************************************* + * PFIFO engine + ******************************************************************************/ - nv_wr32(dev, NV03_PFIFO_INTR_0, 0xffffffff); - nv_wr32(dev, NV03_PFIFO_INTR_EN_0, 0xffffffff); +void +nv04_fifo_pause(struct nouveau_fifo *pfifo, unsigned long *pflags) +__acquires(priv->base.lock) +{ + struct nv04_fifo_priv *priv = (void *)pfifo; + unsigned long flags; - nv_wr32(dev, NV03_PFIFO_CACHE1_PUSH0, 1); - nv_wr32(dev, NV04_PFIFO_CACHE1_PULL0, 1); - nv_wr32(dev, NV03_PFIFO_CACHES, 1); + spin_lock_irqsave(&priv->base.lock, flags); + *pflags = flags; + + nv_wr32(priv, NV03_PFIFO_CACHES, 0x00000000); + nv_mask(priv, NV04_PFIFO_CACHE1_PULL0, 0x00000001, 0x00000000); + + /* in some cases the puller may be left in an inconsistent state + * if you try to stop it while it's busy translating handles. + * sometimes you get a CACHE_ERROR, sometimes it just fails + * silently; sending incorrect instance offsets to PGRAPH after + * it's started up again. + * + * to avoid this, we invalidate the most recently calculated + * instance. + */ + if (!nv_wait(priv, NV04_PFIFO_CACHE1_PULL0, + NV04_PFIFO_CACHE1_PULL0_HASH_BUSY, 0x00000000)) + nv_warn(priv, "timeout idling puller\n"); + + if (nv_rd32(priv, NV04_PFIFO_CACHE1_PULL0) & + NV04_PFIFO_CACHE1_PULL0_HASH_FAILED) + nv_wr32(priv, NV03_PFIFO_INTR_0, NV_PFIFO_INTR_CACHE_ERROR); + + nv_wr32(priv, NV04_PFIFO_CACHE1_HASH, 0x00000000); +} - for (i = 0; i < priv->base.channels; i++) { - if (dev_priv->channels.ptr[i]) - nv_mask(dev, NV04_PFIFO_MODE, (1 << i), (1 << i)); - } +void +nv04_fifo_start(struct nouveau_fifo *pfifo, unsigned long *pflags) +__releases(priv->base.lock) +{ + struct nv04_fifo_priv *priv = (void *)pfifo; + unsigned long flags = *pflags; - return 0; + nv_mask(priv, NV04_PFIFO_CACHE1_PULL0, 0x00000001, 0x00000001); + nv_wr32(priv, NV03_PFIFO_CACHES, 0x00000001); + + spin_unlock_irqrestore(&priv->base.lock, flags); } -int -nv04_fifo_fini(struct drm_device *dev, int engine, bool suspend) +static const char * +nv_dma_state_err(u32 state) { - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nv04_fifo_priv *priv = nv_engine(dev, engine); - struct nouveau_channel *chan; - int chid; - - /* prevent context switches and halt fifo operation */ - nv_wr32(dev, NV03_PFIFO_CACHES, 0); - nv_wr32(dev, NV04_PFIFO_CACHE1_DMA_PUSH, 0); - nv_wr32(dev, NV03_PFIFO_CACHE1_PUSH0, 0); - nv_wr32(dev, NV04_PFIFO_CACHE1_PULL0, 0); - - /* store current fifo context in ramfc */ - chid = nv_rd32(dev, NV03_PFIFO_CACHE1_PUSH1) & priv->base.channels; - chan = dev_priv->channels.ptr[chid]; - if (suspend && chid != priv->base.channels && chan) { - struct nv04_fifo_chan *fctx = chan->engctx[engine]; - struct nouveau_gpuobj *ctx = priv->ramfc; - struct ramfc_desc *c = priv->ramfc_desc; - do { - u32 rm = ((1ULL << c->bits) - 1) << c->regs; - u32 cm = ((1ULL << c->bits) - 1) << c->ctxs; - u32 rv = (nv_rd32(dev, c->regp) & rm) >> c->regs; - u32 cv = (nv_ro32(ctx, c->ctxp + fctx->ramfc) & ~cm); - nv_wo32(ctx, c->ctxp + fctx->ramfc, cv | (rv << c->ctxs)); - } while ((++c)->bits); - } - - nv_wr32(dev, NV03_PFIFO_INTR_EN_0, 0x00000000); - return 0; + static const char * const desc[] = { + "NONE", "CALL_SUBR_ACTIVE", "INVALID_MTHD", "RET_SUBR_INACTIVE", + "INVALID_CMD", "IB_EMPTY"/* NV50+ */, "MEM_FAULT", "UNK" + }; + return desc[(state >> 29) & 0x7]; } static bool -nouveau_fifo_swmthd(struct drm_device *dev, u32 chid, u32 addr, u32 data) +nv04_fifo_swmthd(struct nv04_fifo_priv *priv, u32 chid, u32 addr, u32 data) { - struct nouveau_fifo_priv *pfifo = nv_engine(dev, NVOBJ_ENGINE_FIFO); - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_channel *chan = NULL; - struct nouveau_gpuobj *obj; - unsigned long flags; + struct nv04_fifo_chan *chan = NULL; + struct nouveau_handle *bind; const int subc = (addr >> 13) & 0x7; const int mthd = addr & 0x1ffc; bool handled = false; + unsigned long flags; u32 engine; - spin_lock_irqsave(&dev_priv->channels.lock, flags); - if (likely(chid >= 0 && chid < pfifo->channels)) - chan = dev_priv->channels.ptr[chid]; + spin_lock_irqsave(&priv->base.lock, flags); + if (likely(chid >= priv->base.min && chid <= priv->base.max)) + chan = (void *)priv->base.channel[chid]; if (unlikely(!chan)) goto out; switch (mthd) { - case 0x0000: /* bind object to subchannel */ - obj = nouveau_ramht_find(chan, data); - if (unlikely(!obj || obj->engine != NVOBJ_ENGINE_SW)) + case 0x0000: + bind = nouveau_namedb_get(nv_namedb(chan), data); + if (unlikely(!bind)) break; - engine = 0x0000000f << (subc * 4); + if (nv_engidx(bind->object->engine) == NVDEV_ENGINE_SW) { + engine = 0x0000000f << (subc * 4); + chan->subc[subc] = data; + handled = true; + + nv_mask(priv, NV04_PFIFO_CACHE1_ENGINE, engine, 0); + } - nv_mask(dev, NV04_PFIFO_CACHE1_ENGINE, engine, 0x00000000); - handled = true; + nouveau_namedb_put(bind); break; default: - engine = nv_rd32(dev, NV04_PFIFO_CACHE1_ENGINE); + engine = nv_rd32(priv, NV04_PFIFO_CACHE1_ENGINE); if (unlikely(((engine >> (subc * 4)) & 0xf) != 0)) break; - if (!nouveau_gpuobj_mthd_call(chan, nouveau_software_class(dev), - mthd, data)) - handled = true; + bind = nouveau_namedb_get(nv_namedb(chan), chan->subc[subc]); + if (likely(bind)) { + if (!nv_call(bind->object, mthd, data)) + handled = true; + nouveau_namedb_put(bind); + } break; } out: - spin_unlock_irqrestore(&dev_priv->channels.lock, flags); + spin_unlock_irqrestore(&priv->base.lock, flags); return handled; } -static const char *nv_dma_state_err(u32 state) -{ - static const char * const desc[] = { - "NONE", "CALL_SUBR_ACTIVE", "INVALID_MTHD", "RET_SUBR_INACTIVE", - "INVALID_CMD", "IB_EMPTY"/* NV50+ */, "MEM_FAULT", "UNK" - }; - return desc[(state >> 29) & 0x7]; -} - void -nv04_fifo_isr(struct drm_device *dev) +nv04_fifo_intr(struct nouveau_subdev *subdev) { - struct nouveau_fifo_priv *pfifo = nv_engine(dev, NVOBJ_ENGINE_FIFO); - struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_device *device = nv_device(subdev); + struct nv04_fifo_priv *priv = (void *)subdev; uint32_t status, reassign; int cnt = 0; - reassign = nv_rd32(dev, NV03_PFIFO_CACHES) & 1; - while ((status = nv_rd32(dev, NV03_PFIFO_INTR_0)) && (cnt++ < 100)) { + reassign = nv_rd32(priv, NV03_PFIFO_CACHES) & 1; + while ((status = nv_rd32(priv, NV03_PFIFO_INTR_0)) && (cnt++ < 100)) { uint32_t chid, get; - nv_wr32(dev, NV03_PFIFO_CACHES, 0); + nv_wr32(priv, NV03_PFIFO_CACHES, 0); - chid = nv_rd32(dev, NV03_PFIFO_CACHE1_PUSH1) & pfifo->channels; - get = nv_rd32(dev, NV03_PFIFO_CACHE1_GET); + chid = nv_rd32(priv, NV03_PFIFO_CACHE1_PUSH1) & priv->base.max; + get = nv_rd32(priv, NV03_PFIFO_CACHE1_GET); if (status & NV_PFIFO_INTR_CACHE_ERROR) { uint32_t mthd, data; @@ -340,86 +418,85 @@ nv04_fifo_isr(struct drm_device *dev) */ ptr = (get & 0x7ff) >> 2; - if (dev_priv->card_type < NV_40) { - mthd = nv_rd32(dev, + if (device->card_type < NV_40) { + mthd = nv_rd32(priv, NV04_PFIFO_CACHE1_METHOD(ptr)); - data = nv_rd32(dev, + data = nv_rd32(priv, NV04_PFIFO_CACHE1_DATA(ptr)); } else { - mthd = nv_rd32(dev, + mthd = nv_rd32(priv, NV40_PFIFO_CACHE1_METHOD(ptr)); - data = nv_rd32(dev, + data = nv_rd32(priv, NV40_PFIFO_CACHE1_DATA(ptr)); } - if (!nouveau_fifo_swmthd(dev, chid, mthd, data)) { - NV_INFO(dev, "PFIFO_CACHE_ERROR - Ch %d/%d " - "Mthd 0x%04x Data 0x%08x\n", + if (!nv04_fifo_swmthd(priv, chid, mthd, data)) { + nv_info(priv, "CACHE_ERROR - Ch %d/%d " + "Mthd 0x%04x Data 0x%08x\n", chid, (mthd >> 13) & 7, mthd & 0x1ffc, data); } - nv_wr32(dev, NV04_PFIFO_CACHE1_DMA_PUSH, 0); - nv_wr32(dev, NV03_PFIFO_INTR_0, + nv_wr32(priv, NV04_PFIFO_CACHE1_DMA_PUSH, 0); + nv_wr32(priv, NV03_PFIFO_INTR_0, NV_PFIFO_INTR_CACHE_ERROR); - nv_wr32(dev, NV03_PFIFO_CACHE1_PUSH0, - nv_rd32(dev, NV03_PFIFO_CACHE1_PUSH0) & ~1); - nv_wr32(dev, NV03_PFIFO_CACHE1_GET, get + 4); - nv_wr32(dev, NV03_PFIFO_CACHE1_PUSH0, - nv_rd32(dev, NV03_PFIFO_CACHE1_PUSH0) | 1); - nv_wr32(dev, NV04_PFIFO_CACHE1_HASH, 0); + nv_wr32(priv, NV03_PFIFO_CACHE1_PUSH0, + nv_rd32(priv, NV03_PFIFO_CACHE1_PUSH0) & ~1); + nv_wr32(priv, NV03_PFIFO_CACHE1_GET, get + 4); + nv_wr32(priv, NV03_PFIFO_CACHE1_PUSH0, + nv_rd32(priv, NV03_PFIFO_CACHE1_PUSH0) | 1); + nv_wr32(priv, NV04_PFIFO_CACHE1_HASH, 0); - nv_wr32(dev, NV04_PFIFO_CACHE1_DMA_PUSH, - nv_rd32(dev, NV04_PFIFO_CACHE1_DMA_PUSH) | 1); - nv_wr32(dev, NV04_PFIFO_CACHE1_PULL0, 1); + nv_wr32(priv, NV04_PFIFO_CACHE1_DMA_PUSH, + nv_rd32(priv, NV04_PFIFO_CACHE1_DMA_PUSH) | 1); + nv_wr32(priv, NV04_PFIFO_CACHE1_PULL0, 1); status &= ~NV_PFIFO_INTR_CACHE_ERROR; } if (status & NV_PFIFO_INTR_DMA_PUSHER) { - u32 dma_get = nv_rd32(dev, 0x003244); - u32 dma_put = nv_rd32(dev, 0x003240); - u32 push = nv_rd32(dev, 0x003220); - u32 state = nv_rd32(dev, 0x003228); - - if (dev_priv->card_type == NV_50) { - u32 ho_get = nv_rd32(dev, 0x003328); - u32 ho_put = nv_rd32(dev, 0x003320); - u32 ib_get = nv_rd32(dev, 0x003334); - u32 ib_put = nv_rd32(dev, 0x003330); - - if (nouveau_ratelimit()) - NV_INFO(dev, "PFIFO_DMA_PUSHER - Ch %d Get 0x%02x%08x " - "Put 0x%02x%08x IbGet 0x%08x IbPut 0x%08x " - "State 0x%08x (err: %s) Push 0x%08x\n", - chid, ho_get, dma_get, ho_put, - dma_put, ib_get, ib_put, state, - nv_dma_state_err(state), - push); + u32 dma_get = nv_rd32(priv, 0x003244); + u32 dma_put = nv_rd32(priv, 0x003240); + u32 push = nv_rd32(priv, 0x003220); + u32 state = nv_rd32(priv, 0x003228); + + if (device->card_type == NV_50) { + u32 ho_get = nv_rd32(priv, 0x003328); + u32 ho_put = nv_rd32(priv, 0x003320); + u32 ib_get = nv_rd32(priv, 0x003334); + u32 ib_put = nv_rd32(priv, 0x003330); + + nv_info(priv, "DMA_PUSHER - Ch %d Get 0x%02x%08x " + "Put 0x%02x%08x IbGet 0x%08x IbPut 0x%08x " + "State 0x%08x (err: %s) Push 0x%08x\n", + chid, ho_get, dma_get, ho_put, + dma_put, ib_get, ib_put, state, + nv_dma_state_err(state), + push); /* METHOD_COUNT, in DMA_STATE on earlier chipsets */ - nv_wr32(dev, 0x003364, 0x00000000); + nv_wr32(priv, 0x003364, 0x00000000); if (dma_get != dma_put || ho_get != ho_put) { - nv_wr32(dev, 0x003244, dma_put); - nv_wr32(dev, 0x003328, ho_put); + nv_wr32(priv, 0x003244, dma_put); + nv_wr32(priv, 0x003328, ho_put); } else if (ib_get != ib_put) { - nv_wr32(dev, 0x003334, ib_put); + nv_wr32(priv, 0x003334, ib_put); } } else { - NV_INFO(dev, "PFIFO_DMA_PUSHER - Ch %d Get 0x%08x " + nv_info(priv, "DMA_PUSHER - Ch %d Get 0x%08x " "Put 0x%08x State 0x%08x (err: %s) Push 0x%08x\n", chid, dma_get, dma_put, state, nv_dma_state_err(state), push); if (dma_get != dma_put) - nv_wr32(dev, 0x003244, dma_put); + nv_wr32(priv, 0x003244, dma_put); } - nv_wr32(dev, 0x003228, 0x00000000); - nv_wr32(dev, 0x003220, 0x00000001); - nv_wr32(dev, 0x002100, NV_PFIFO_INTR_DMA_PUSHER); + nv_wr32(priv, 0x003228, 0x00000000); + nv_wr32(priv, 0x003220, 0x00000001); + nv_wr32(priv, 0x002100, NV_PFIFO_INTR_DMA_PUSHER); status &= ~NV_PFIFO_INTR_DMA_PUSHER; } @@ -427,81 +504,118 @@ nv04_fifo_isr(struct drm_device *dev) uint32_t sem; status &= ~NV_PFIFO_INTR_SEMAPHORE; - nv_wr32(dev, NV03_PFIFO_INTR_0, + nv_wr32(priv, NV03_PFIFO_INTR_0, NV_PFIFO_INTR_SEMAPHORE); - sem = nv_rd32(dev, NV10_PFIFO_CACHE1_SEMAPHORE); - nv_wr32(dev, NV10_PFIFO_CACHE1_SEMAPHORE, sem | 0x1); + sem = nv_rd32(priv, NV10_PFIFO_CACHE1_SEMAPHORE); + nv_wr32(priv, NV10_PFIFO_CACHE1_SEMAPHORE, sem | 0x1); - nv_wr32(dev, NV03_PFIFO_CACHE1_GET, get + 4); - nv_wr32(dev, NV04_PFIFO_CACHE1_PULL0, 1); + nv_wr32(priv, NV03_PFIFO_CACHE1_GET, get + 4); + nv_wr32(priv, NV04_PFIFO_CACHE1_PULL0, 1); } - if (dev_priv->card_type == NV_50) { + if (device->card_type == NV_50) { if (status & 0x00000010) { - nv50_fb_vm_trap(dev, nouveau_ratelimit()); + nv50_fb_trap(nouveau_fb(priv), 1); status &= ~0x00000010; - nv_wr32(dev, 0x002100, 0x00000010); + nv_wr32(priv, 0x002100, 0x00000010); } } if (status) { - if (nouveau_ratelimit()) - NV_INFO(dev, "PFIFO_INTR 0x%08x - Ch %d\n", - status, chid); - nv_wr32(dev, NV03_PFIFO_INTR_0, status); + nv_info(priv, "unknown intr 0x%08x, ch %d\n", + status, chid); + nv_wr32(priv, NV03_PFIFO_INTR_0, status); status = 0; } - nv_wr32(dev, NV03_PFIFO_CACHES, reassign); + nv_wr32(priv, NV03_PFIFO_CACHES, reassign); } if (status) { - NV_INFO(dev, "PFIFO still angry after %d spins, halt\n", cnt); - nv_wr32(dev, 0x2140, 0); - nv_wr32(dev, 0x140, 0); + nv_info(priv, "still angry after %d spins, halt\n", cnt); + nv_wr32(priv, 0x002140, 0); + nv_wr32(priv, 0x000140, 0); } - nv_wr32(dev, NV03_PMC_INTR_0, NV_PMC_INTR_0_PFIFO_PENDING); + nv_wr32(priv, 0x000100, 0x00000100); } -void -nv04_fifo_destroy(struct drm_device *dev, int engine) +static int +nv04_fifo_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 nv04_fifo_priv *priv = nv_engine(dev, engine); + struct nv04_instmem_priv *imem = nv04_instmem(parent); + struct nv04_fifo_priv *priv; + int ret; - nouveau_irq_unregister(dev, 8); + ret = nouveau_fifo_create(parent, engine, oclass, 0, 15, &priv); + *pobject = nv_object(priv); + if (ret) + return ret; + + nouveau_ramht_ref(imem->ramht, &priv->ramht); + nouveau_gpuobj_ref(imem->ramro, &priv->ramro); + nouveau_gpuobj_ref(imem->ramfc, &priv->ramfc); + + nv_subdev(priv)->unit = 0x00000100; + nv_subdev(priv)->intr = nv04_fifo_intr; + nv_engine(priv)->cclass = &nv04_fifo_cclass; + nv_engine(priv)->sclass = nv04_fifo_sclass; + priv->base.pause = nv04_fifo_pause; + priv->base.start = nv04_fifo_start; + priv->ramfc_desc = nv04_ramfc; + return 0; +} +void +nv04_fifo_dtor(struct nouveau_object *object) +{ + struct nv04_fifo_priv *priv = (void *)object; nouveau_gpuobj_ref(NULL, &priv->ramfc); nouveau_gpuobj_ref(NULL, &priv->ramro); - - dev_priv->eng[engine] = NULL; - kfree(priv); + nouveau_ramht_ref(NULL, &priv->ramht); + nouveau_fifo_destroy(&priv->base); } int -nv04_fifo_create(struct drm_device *dev) +nv04_fifo_init(struct nouveau_object *object) { - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nv04_fifo_priv *priv; + struct nv04_fifo_priv *priv = (void *)object; + int ret; + + ret = nouveau_fifo_init(&priv->base); + if (ret) + return ret; - priv = kzalloc(sizeof(*priv), GFP_KERNEL); - if (!priv) - return -ENOMEM; + nv_wr32(priv, NV04_PFIFO_DELAY_0, 0x000000ff); + nv_wr32(priv, NV04_PFIFO_DMA_TIMESLICE, 0x0101ffff); - nouveau_gpuobj_ref(nvimem_ramro(dev), &priv->ramro); - nouveau_gpuobj_ref(nvimem_ramfc(dev), &priv->ramfc); + nv_wr32(priv, NV03_PFIFO_RAMHT, (0x03 << 24) /* search 128 */ | + ((priv->ramht->bits - 9) << 16) | + (priv->ramht->base.addr >> 8)); + nv_wr32(priv, NV03_PFIFO_RAMRO, priv->ramro->addr >> 8); + nv_wr32(priv, NV03_PFIFO_RAMFC, priv->ramfc->addr >> 8); - priv->base.base.destroy = nv04_fifo_destroy; - priv->base.base.init = nv04_fifo_init; - priv->base.base.fini = nv04_fifo_fini; - priv->base.base.context_new = nv04_fifo_context_new; - priv->base.base.context_del = nv04_fifo_context_del; - priv->base.channels = 15; - priv->ramfc_desc = nv04_ramfc; - dev_priv->eng[NVOBJ_ENGINE_FIFO] = &priv->base.base; + nv_wr32(priv, NV03_PFIFO_CACHE1_PUSH1, priv->base.max); - nouveau_irq_register(dev, 8, nv04_fifo_isr); + nv_wr32(priv, NV03_PFIFO_INTR_0, 0xffffffff); + nv_wr32(priv, NV03_PFIFO_INTR_EN_0, 0xffffffff); + + nv_wr32(priv, NV03_PFIFO_CACHE1_PUSH0, 1); + nv_wr32(priv, NV04_PFIFO_CACHE1_PULL0, 1); + nv_wr32(priv, NV03_PFIFO_CACHES, 1); return 0; } + +struct nouveau_oclass +nv04_fifo_oclass = { + .handle = NV_ENGINE(FIFO, 0x04), + .ofuncs = &(struct nouveau_ofuncs) { + .ctor = nv04_fifo_ctor, + .dtor = nv04_fifo_dtor, + .init = nv04_fifo_init, + .fini = _nouveau_fifo_fini, + }, +}; diff --git a/drivers/gpu/drm/nouveau/core/engine/fifo/nv04.h b/drivers/gpu/drm/nouveau/core/engine/fifo/nv04.h new file mode 100644 index 000000000000..496a4b4fdfaf --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/engine/fifo/nv04.h @@ -0,0 +1,178 @@ +#ifndef __NV04_FIFO_H__ +#define __NV04_FIFO_H__ + +#include + +#define NV04_PFIFO_DELAY_0 0x00002040 +#define NV04_PFIFO_DMA_TIMESLICE 0x00002044 +#define NV04_PFIFO_NEXT_CHANNEL 0x00002050 +#define NV03_PFIFO_INTR_0 0x00002100 +#define NV03_PFIFO_INTR_EN_0 0x00002140 +# define NV_PFIFO_INTR_CACHE_ERROR (1<<0) +# define NV_PFIFO_INTR_RUNOUT (1<<4) +# define NV_PFIFO_INTR_RUNOUT_OVERFLOW (1<<8) +# define NV_PFIFO_INTR_DMA_PUSHER (1<<12) +# define NV_PFIFO_INTR_DMA_PT (1<<16) +# define NV_PFIFO_INTR_SEMAPHORE (1<<20) +# define NV_PFIFO_INTR_ACQUIRE_TIMEOUT (1<<24) +#define NV03_PFIFO_RAMHT 0x00002210 +#define NV03_PFIFO_RAMFC 0x00002214 +#define NV03_PFIFO_RAMRO 0x00002218 +#define NV40_PFIFO_RAMFC 0x00002220 +#define NV03_PFIFO_CACHES 0x00002500 +#define NV04_PFIFO_MODE 0x00002504 +#define NV04_PFIFO_DMA 0x00002508 +#define NV04_PFIFO_SIZE 0x0000250c +#define NV50_PFIFO_CTX_TABLE(c) (0x2600+(c)*4) +#define NV50_PFIFO_CTX_TABLE__SIZE 128 +#define NV50_PFIFO_CTX_TABLE_CHANNEL_ENABLED (1<<31) +#define NV50_PFIFO_CTX_TABLE_UNK30_BAD (1<<30) +#define NV50_PFIFO_CTX_TABLE_INSTANCE_MASK_G80 0x0FFFFFFF +#define NV50_PFIFO_CTX_TABLE_INSTANCE_MASK_G84 0x00FFFFFF +#define NV03_PFIFO_CACHE0_PUSH0 0x00003000 +#define NV03_PFIFO_CACHE0_PULL0 0x00003040 +#define NV04_PFIFO_CACHE0_PULL0 0x00003050 +#define NV04_PFIFO_CACHE0_PULL1 0x00003054 +#define NV03_PFIFO_CACHE1_PUSH0 0x00003200 +#define NV03_PFIFO_CACHE1_PUSH1 0x00003204 +#define NV03_PFIFO_CACHE1_PUSH1_DMA (1<<8) +#define NV40_PFIFO_CACHE1_PUSH1_DMA (1<<16) +#define NV03_PFIFO_CACHE1_PUSH1_CHID_MASK 0x0000000f +#define NV10_PFIFO_CACHE1_PUSH1_CHID_MASK 0x0000001f +#define NV50_PFIFO_CACHE1_PUSH1_CHID_MASK 0x0000007f +#define NV03_PFIFO_CACHE1_PUT 0x00003210 +#define NV04_PFIFO_CACHE1_DMA_PUSH 0x00003220 +#define NV04_PFIFO_CACHE1_DMA_FETCH 0x00003224 +# define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_8_BYTES 0x00000000 +# define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_16_BYTES 0x00000008 +# define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_24_BYTES 0x00000010 +# define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_32_BYTES 0x00000018 +# define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_40_BYTES 0x00000020 +# define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_48_BYTES 0x00000028 +# define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_56_BYTES 0x00000030 +# define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_64_BYTES 0x00000038 +# define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_72_BYTES 0x00000040 +# define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_80_BYTES 0x00000048 +# define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_88_BYTES 0x00000050 +# define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_96_BYTES 0x00000058 +# define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_104_BYTES 0x00000060 +# define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_112_BYTES 0x00000068 +# define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_120_BYTES 0x00000070 +# define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_128_BYTES 0x00000078 +# define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_136_BYTES 0x00000080 +# define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_144_BYTES 0x00000088 +# define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_152_BYTES 0x00000090 +# define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_160_BYTES 0x00000098 +# define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_168_BYTES 0x000000A0 +# define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_176_BYTES 0x000000A8 +# define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_184_BYTES 0x000000B0 +# define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_192_BYTES 0x000000B8 +# define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_200_BYTES 0x000000C0 +# define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_208_BYTES 0x000000C8 +# define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_216_BYTES 0x000000D0 +# define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_224_BYTES 0x000000D8 +# define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_232_BYTES 0x000000E0 +# define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_240_BYTES 0x000000E8 +# define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_248_BYTES 0x000000F0 +# define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_256_BYTES 0x000000F8 +# define NV_PFIFO_CACHE1_DMA_FETCH_SIZE 0x0000E000 +# define NV_PFIFO_CACHE1_DMA_FETCH_SIZE_32_BYTES 0x00000000 +# define NV_PFIFO_CACHE1_DMA_FETCH_SIZE_64_BYTES 0x00002000 +# define NV_PFIFO_CACHE1_DMA_FETCH_SIZE_96_BYTES 0x00004000 +# define NV_PFIFO_CACHE1_DMA_FETCH_SIZE_128_BYTES 0x00006000 +# define NV_PFIFO_CACHE1_DMA_FETCH_SIZE_160_BYTES 0x00008000 +# define NV_PFIFO_CACHE1_DMA_FETCH_SIZE_192_BYTES 0x0000A000 +# define NV_PFIFO_CACHE1_DMA_FETCH_SIZE_224_BYTES 0x0000C000 +# define NV_PFIFO_CACHE1_DMA_FETCH_SIZE_256_BYTES 0x0000E000 +# define NV_PFIFO_CACHE1_DMA_FETCH_MAX_REQS 0x001F0000 +# define NV_PFIFO_CACHE1_DMA_FETCH_MAX_REQS_0 0x00000000 +# define NV_PFIFO_CACHE1_DMA_FETCH_MAX_REQS_1 0x00010000 +# define NV_PFIFO_CACHE1_DMA_FETCH_MAX_REQS_2 0x00020000 +# define NV_PFIFO_CACHE1_DMA_FETCH_MAX_REQS_3 0x00030000 +# define NV_PFIFO_CACHE1_DMA_FETCH_MAX_REQS_4 0x00040000 +# define NV_PFIFO_CACHE1_DMA_FETCH_MAX_REQS_5 0x00050000 +# define NV_PFIFO_CACHE1_DMA_FETCH_MAX_REQS_6 0x00060000 +# define NV_PFIFO_CACHE1_DMA_FETCH_MAX_REQS_7 0x00070000 +# define NV_PFIFO_CACHE1_DMA_FETCH_MAX_REQS_8 0x00080000 +# define NV_PFIFO_CACHE1_DMA_FETCH_MAX_REQS_9 0x00090000 +# define NV_PFIFO_CACHE1_DMA_FETCH_MAX_REQS_10 0x000A0000 +# define NV_PFIFO_CACHE1_DMA_FETCH_MAX_REQS_11 0x000B0000 +# define NV_PFIFO_CACHE1_DMA_FETCH_MAX_REQS_12 0x000C0000 +# define NV_PFIFO_CACHE1_DMA_FETCH_MAX_REQS_13 0x000D0000 +# define NV_PFIFO_CACHE1_DMA_FETCH_MAX_REQS_14 0x000E0000 +# define NV_PFIFO_CACHE1_DMA_FETCH_MAX_REQS_15 0x000F0000 +# define NV_PFIFO_CACHE1_ENDIAN 0x80000000 +# define NV_PFIFO_CACHE1_LITTLE_ENDIAN 0x7FFFFFFF +# define NV_PFIFO_CACHE1_BIG_ENDIAN 0x80000000 +#define NV04_PFIFO_CACHE1_DMA_STATE 0x00003228 +#define NV04_PFIFO_CACHE1_DMA_INSTANCE 0x0000322c +#define NV04_PFIFO_CACHE1_DMA_CTL 0x00003230 +#define NV04_PFIFO_CACHE1_DMA_PUT 0x00003240 +#define NV04_PFIFO_CACHE1_DMA_GET 0x00003244 +#define NV10_PFIFO_CACHE1_REF_CNT 0x00003248 +#define NV10_PFIFO_CACHE1_DMA_SUBROUTINE 0x0000324C +#define NV03_PFIFO_CACHE1_PULL0 0x00003240 +#define NV04_PFIFO_CACHE1_PULL0 0x00003250 +# define NV04_PFIFO_CACHE1_PULL0_HASH_FAILED 0x00000010 +# define NV04_PFIFO_CACHE1_PULL0_HASH_BUSY 0x00001000 +#define NV03_PFIFO_CACHE1_PULL1 0x00003250 +#define NV04_PFIFO_CACHE1_PULL1 0x00003254 +#define NV04_PFIFO_CACHE1_HASH 0x00003258 +#define NV10_PFIFO_CACHE1_ACQUIRE_TIMEOUT 0x00003260 +#define NV10_PFIFO_CACHE1_ACQUIRE_TIMESTAMP 0x00003264 +#define NV10_PFIFO_CACHE1_ACQUIRE_VALUE 0x00003268 +#define NV10_PFIFO_CACHE1_SEMAPHORE 0x0000326C +#define NV03_PFIFO_CACHE1_GET 0x00003270 +#define NV04_PFIFO_CACHE1_ENGINE 0x00003280 +#define NV04_PFIFO_CACHE1_DMA_DCOUNT 0x000032A0 +#define NV40_PFIFO_GRCTX_INSTANCE 0x000032E0 +#define NV40_PFIFO_UNK32E4 0x000032E4 +#define NV04_PFIFO_CACHE1_METHOD(i) (0x00003800+(i*8)) +#define NV04_PFIFO_CACHE1_DATA(i) (0x00003804+(i*8)) +#define NV40_PFIFO_CACHE1_METHOD(i) (0x00090000+(i*8)) +#define NV40_PFIFO_CACHE1_DATA(i) (0x00090004+(i*8)) + +struct ramfc_desc { + unsigned bits:6; + unsigned ctxs:5; + unsigned ctxp:8; + unsigned regs:5; + unsigned regp; +}; + +struct nv04_fifo_priv { + struct nouveau_fifo base; + struct ramfc_desc *ramfc_desc; + struct nouveau_ramht *ramht; + struct nouveau_gpuobj *ramro; + struct nouveau_gpuobj *ramfc; +}; + +struct nv04_fifo_base { + struct nouveau_fifo_base base; +}; + +struct nv04_fifo_chan { + struct nouveau_fifo_chan base; + u32 subc[8]; + u32 ramfc; +}; + +int nv04_fifo_object_attach(struct nouveau_object *, + struct nouveau_object *, u32); +void nv04_fifo_object_detach(struct nouveau_object *, int); + +void nv04_fifo_chan_dtor(struct nouveau_object *); +int nv04_fifo_chan_init(struct nouveau_object *); +int nv04_fifo_chan_fini(struct nouveau_object *, bool suspend); + +int nv04_fifo_context_ctor(struct nouveau_object *, struct nouveau_object *, + struct nouveau_oclass *, void *, u32, + struct nouveau_object **); + +void nv04_fifo_dtor(struct nouveau_object *); +int nv04_fifo_init(struct nouveau_object *); +void nv04_fifo_pause(struct nouveau_fifo *, unsigned long *); +void nv04_fifo_start(struct nouveau_fifo *, unsigned long *); + +#endif diff --git a/drivers/gpu/drm/nouveau/core/engine/fifo/nv10.c b/drivers/gpu/drm/nouveau/core/engine/fifo/nv10.c index 2d38fa88f9c7..391fefa7c472 100644 --- a/drivers/gpu/drm/nouveau/core/engine/fifo/nv10.c +++ b/drivers/gpu/drm/nouveau/core/engine/fifo/nv10.c @@ -1,43 +1,42 @@ /* - * Copyright (C) 2012 Ben Skeggs. - * All Rights Reserved. + * 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: + * 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 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 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 */ -#include "drmP.h" -#include "drm.h" -#include "nouveau_drv.h" -#include -#include "nouveau_util.h" +#include +#include +#include #include -static struct ramfc_desc { - unsigned bits:6; - unsigned ctxs:5; - unsigned ctxp:8; - unsigned regs:5; - unsigned regp; -} nv10_ramfc[] = { +#include +#include +#include + +#include + +#include "nv04.h" + +static struct ramfc_desc +nv10_ramfc[] = { { 32, 0, 0x00, 0, NV04_PFIFO_CACHE1_DMA_PUT }, { 32, 0, 0x04, 0, NV04_PFIFO_CACHE1_DMA_GET }, { 32, 0, 0x08, 0, NV10_PFIFO_CACHE1_REF_CNT }, @@ -50,87 +49,122 @@ static struct ramfc_desc { {} }; -struct nv10_fifo_priv { - struct nouveau_fifo_priv base; - struct ramfc_desc *ramfc_desc; - struct nouveau_gpuobj *ramro; - struct nouveau_gpuobj *ramfc; -}; - -struct nv10_fifo_chan { - struct nouveau_fifo_chan base; - u32 ramfc; -}; +/******************************************************************************* + * FIFO channel objects + ******************************************************************************/ static int -nv10_fifo_context_new(struct nouveau_channel *chan, int engine) +nv10_fifo_chan_ctor(struct nouveau_object *parent, + struct nouveau_object *engine, + struct nouveau_oclass *oclass, void *data, u32 size, + struct nouveau_object **pobject) { - struct drm_device *dev = chan->dev; - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nv10_fifo_priv *priv = nv_engine(dev, engine); - struct nv10_fifo_chan *fctx; - unsigned long flags; + struct nv04_fifo_priv *priv = (void *)engine; + struct nv04_fifo_chan *chan; + struct nv_channel_dma_class *args = data; int ret; - fctx = chan->engctx[engine] = kzalloc(sizeof(*fctx), GFP_KERNEL); - if (!fctx) - return -ENOMEM; - - fctx->ramfc = chan->id * 32; - - /* map channel control registers */ - chan->user = ioremap(pci_resource_start(dev->pdev, 0) + - NV03_USER(chan->id), PAGE_SIZE); - if (!chan->user) { - ret = -ENOMEM; - goto error; - } - - /* initialise default fifo context */ - nv_wo32(priv->ramfc, fctx->ramfc + 0x00, chan->pushbuf_base); - nv_wo32(priv->ramfc, fctx->ramfc + 0x04, chan->pushbuf_base); - nv_wo32(priv->ramfc, fctx->ramfc + 0x0c, chan->pushbuf->addr >> 4); - nv_wo32(priv->ramfc, fctx->ramfc + 0x14, + if (size < sizeof(*args)) + return -EINVAL; + + ret = nouveau_fifo_channel_create(parent, engine, oclass, 0, 0x800000, + 0x10000, args->pushbuf, + (1 << NVDEV_ENGINE_DMAOBJ) | + (1 << NVDEV_ENGINE_SW) | + (1 << NVDEV_ENGINE_GR), &chan); + *pobject = nv_object(chan); + if (ret) + return ret; + + nv_parent(chan)->object_attach = nv04_fifo_object_attach; + nv_parent(chan)->object_detach = nv04_fifo_object_detach; + chan->ramfc = chan->base.chid * 32; + + nv_wo32(priv->ramfc, chan->ramfc + 0x00, args->offset); + nv_wo32(priv->ramfc, chan->ramfc + 0x04, args->offset); + nv_wo32(priv->ramfc, chan->ramfc + 0x0c, chan->base.pushgpu->addr >> 4); + nv_wo32(priv->ramfc, chan->ramfc + 0x14, NV_PFIFO_CACHE1_DMA_FETCH_TRIG_128_BYTES | NV_PFIFO_CACHE1_DMA_FETCH_SIZE_128_BYTES | #ifdef __BIG_ENDIAN NV_PFIFO_CACHE1_BIG_ENDIAN | #endif NV_PFIFO_CACHE1_DMA_FETCH_MAX_REQS_8); + return 0; +} - /* enable dma mode on the channel */ - spin_lock_irqsave(&dev_priv->context_switch_lock, flags); - nv_mask(dev, NV04_PFIFO_MODE, (1 << chan->id), (1 << chan->id)); - spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags); +static struct nouveau_ofuncs +nv10_fifo_ofuncs = { + .ctor = nv10_fifo_chan_ctor, + .dtor = nv04_fifo_chan_dtor, + .init = nv04_fifo_chan_init, + .fini = nv04_fifo_chan_fini, + .rd32 = _nouveau_fifo_channel_rd32, + .wr32 = _nouveau_fifo_channel_wr32, +}; -error: - if (ret) - priv->base.base.context_del(chan, engine); - return ret; -} +static struct nouveau_oclass +nv10_fifo_sclass[] = { + { 0x006e, &nv10_fifo_ofuncs }, + {} +}; + +/******************************************************************************* + * FIFO context - basically just the instmem reserved for the channel + ******************************************************************************/ + +static struct nouveau_oclass +nv10_fifo_cclass = { + .handle = NV_ENGCTX(FIFO, 0x10), + .ofuncs = &(struct nouveau_ofuncs) { + .ctor = nv04_fifo_context_ctor, + .dtor = _nouveau_fifo_context_dtor, + .init = _nouveau_fifo_context_init, + .fini = _nouveau_fifo_context_fini, + .rd32 = _nouveau_fifo_context_rd32, + .wr32 = _nouveau_fifo_context_wr32, + }, +}; + +/******************************************************************************* + * PFIFO engine + ******************************************************************************/ -int -nv10_fifo_create(struct drm_device *dev) +static int +nv10_fifo_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 nv10_fifo_priv *priv; - - priv = kzalloc(sizeof(*priv), GFP_KERNEL); - if (!priv) - return -ENOMEM; - - nouveau_gpuobj_ref(nvimem_ramro(dev), &priv->ramro); - nouveau_gpuobj_ref(nvimem_ramfc(dev), &priv->ramfc); - - priv->base.base.destroy = nv04_fifo_destroy; - priv->base.base.init = nv04_fifo_init; - priv->base.base.fini = nv04_fifo_fini; - priv->base.base.context_new = nv10_fifo_context_new; - priv->base.base.context_del = nv04_fifo_context_del; - priv->base.channels = 31; - priv->ramfc_desc = nv10_ramfc; - dev_priv->eng[NVOBJ_ENGINE_FIFO] = &priv->base.base; + struct nv04_instmem_priv *imem = nv04_instmem(parent); + struct nv04_fifo_priv *priv; + int ret; - nouveau_irq_register(dev, 8, nv04_fifo_isr); + ret = nouveau_fifo_create(parent, engine, oclass, 0, 31, &priv); + *pobject = nv_object(priv); + if (ret) + return ret; + + nouveau_ramht_ref(imem->ramht, &priv->ramht); + nouveau_gpuobj_ref(imem->ramro, &priv->ramro); + nouveau_gpuobj_ref(imem->ramfc, &priv->ramfc); + + nv_subdev(priv)->unit = 0x00000100; + nv_subdev(priv)->intr = nv04_fifo_intr; + nv_engine(priv)->cclass = &nv10_fifo_cclass; + nv_engine(priv)->sclass = nv10_fifo_sclass; + priv->base.pause = nv04_fifo_pause; + priv->base.start = nv04_fifo_start; + priv->ramfc_desc = nv10_ramfc; return 0; } + +struct nouveau_oclass +nv10_fifo_oclass = { + .handle = NV_ENGINE(FIFO, 0x10), + .ofuncs = &(struct nouveau_ofuncs) { + .ctor = nv10_fifo_ctor, + .dtor = nv04_fifo_dtor, + .init = nv04_fifo_init, + .fini = _nouveau_fifo_fini, + }, +}; diff --git a/drivers/gpu/drm/nouveau/core/engine/fifo/nv17.c b/drivers/gpu/drm/nouveau/core/engine/fifo/nv17.c index 2f700a15e286..3b9d6c97f9ba 100644 --- a/drivers/gpu/drm/nouveau/core/engine/fifo/nv17.c +++ b/drivers/gpu/drm/nouveau/core/engine/fifo/nv17.c @@ -1,43 +1,42 @@ /* - * Copyright (C) 2012 Ben Skeggs. - * All Rights Reserved. + * 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: + * 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 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 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 */ -#include "drmP.h" -#include "drm.h" -#include "nouveau_drv.h" -#include -#include "nouveau_util.h" +#include +#include +#include #include -static struct ramfc_desc { - unsigned bits:6; - unsigned ctxs:5; - unsigned ctxp:8; - unsigned regs:5; - unsigned regp; -} nv17_ramfc[] = { +#include +#include +#include + +#include + +#include "nv04.h" + +static struct ramfc_desc +nv17_ramfc[] = { { 32, 0, 0x00, 0, NV04_PFIFO_CACHE1_DMA_PUT }, { 32, 0, 0x04, 0, NV04_PFIFO_CACHE1_DMA_GET }, { 32, 0, 0x08, 0, NV10_PFIFO_CACHE1_REF_CNT }, @@ -55,124 +54,154 @@ static struct ramfc_desc { {} }; -struct nv17_fifo_priv { - struct nouveau_fifo_priv base; - struct ramfc_desc *ramfc_desc; - struct nouveau_gpuobj *ramro; - struct nouveau_gpuobj *ramfc; -}; - -struct nv17_fifo_chan { - struct nouveau_fifo_chan base; - u32 ramfc; -}; +/******************************************************************************* + * FIFO channel objects + ******************************************************************************/ static int -nv17_fifo_context_new(struct nouveau_channel *chan, int engine) +nv17_fifo_chan_ctor(struct nouveau_object *parent, + struct nouveau_object *engine, + struct nouveau_oclass *oclass, void *data, u32 size, + struct nouveau_object **pobject) { - struct drm_device *dev = chan->dev; - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nv17_fifo_priv *priv = nv_engine(dev, engine); - struct nv17_fifo_chan *fctx; - unsigned long flags; + struct nv04_fifo_priv *priv = (void *)engine; + struct nv04_fifo_chan *chan; + struct nv_channel_dma_class *args = data; int ret; - fctx = chan->engctx[engine] = kzalloc(sizeof(*fctx), GFP_KERNEL); - if (!fctx) - return -ENOMEM; - - fctx->ramfc = chan->id * 64; - - /* map channel control registers */ - chan->user = ioremap(pci_resource_start(dev->pdev, 0) + - NV03_USER(chan->id), PAGE_SIZE); - if (!chan->user) { - ret = -ENOMEM; - goto error; - } - - /* initialise default fifo context */ - nv_wo32(priv->ramfc, fctx->ramfc + 0x00, chan->pushbuf_base); - nv_wo32(priv->ramfc, fctx->ramfc + 0x04, chan->pushbuf_base); - nv_wo32(priv->ramfc, fctx->ramfc + 0x0c, chan->pushbuf->addr >> 4); - nv_wo32(priv->ramfc, fctx->ramfc + 0x14, + if (size < sizeof(*args)) + return -EINVAL; + + ret = nouveau_fifo_channel_create(parent, engine, oclass, 0, 0x800000, + 0x10000, args->pushbuf, + (1 << NVDEV_ENGINE_DMAOBJ) | + (1 << NVDEV_ENGINE_SW) | + (1 << NVDEV_ENGINE_GR) | + (1 << NVDEV_ENGINE_MPEG), /* NV31- */ + &chan); + *pobject = nv_object(chan); + if (ret) + return ret; + + nv_parent(chan)->object_attach = nv04_fifo_object_attach; + nv_parent(chan)->object_detach = nv04_fifo_object_detach; + chan->ramfc = chan->base.chid * 64; + + nv_wo32(priv->ramfc, chan->ramfc + 0x00, args->offset); + nv_wo32(priv->ramfc, chan->ramfc + 0x04, args->offset); + nv_wo32(priv->ramfc, chan->ramfc + 0x0c, chan->base.pushgpu->addr >> 4); + nv_wo32(priv->ramfc, chan->ramfc + 0x14, NV_PFIFO_CACHE1_DMA_FETCH_TRIG_128_BYTES | NV_PFIFO_CACHE1_DMA_FETCH_SIZE_128_BYTES | #ifdef __BIG_ENDIAN NV_PFIFO_CACHE1_BIG_ENDIAN | #endif NV_PFIFO_CACHE1_DMA_FETCH_MAX_REQS_8); + return 0; +} - /* enable dma mode on the channel */ - spin_lock_irqsave(&dev_priv->context_switch_lock, flags); - nv_mask(dev, NV04_PFIFO_MODE, (1 << chan->id), (1 << chan->id)); - spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags); +static struct nouveau_ofuncs +nv17_fifo_ofuncs = { + .ctor = nv17_fifo_chan_ctor, + .dtor = nv04_fifo_chan_dtor, + .init = nv04_fifo_chan_init, + .fini = nv04_fifo_chan_fini, + .rd32 = _nouveau_fifo_channel_rd32, + .wr32 = _nouveau_fifo_channel_wr32, +}; -error: - if (ret) - priv->base.base.context_del(chan, engine); - return ret; -} +static struct nouveau_oclass +nv17_fifo_sclass[] = { + { 0x006e, &nv17_fifo_ofuncs }, + {} +}; + +/******************************************************************************* + * FIFO context - basically just the instmem reserved for the channel + ******************************************************************************/ + +static struct nouveau_oclass +nv17_fifo_cclass = { + .handle = NV_ENGCTX(FIFO, 0x17), + .ofuncs = &(struct nouveau_ofuncs) { + .ctor = nv04_fifo_context_ctor, + .dtor = _nouveau_fifo_context_dtor, + .init = _nouveau_fifo_context_init, + .fini = _nouveau_fifo_context_fini, + .rd32 = _nouveau_fifo_context_rd32, + .wr32 = _nouveau_fifo_context_wr32, + }, +}; + +/******************************************************************************* + * PFIFO engine + ******************************************************************************/ static int -nv17_fifo_init(struct drm_device *dev, int engine) +nv17_fifo_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 nv17_fifo_priv *priv = nv_engine(dev, engine); - int i; + struct nv04_instmem_priv *imem = nv04_instmem(parent); + struct nv04_fifo_priv *priv; + int ret; - nv_mask(dev, NV03_PMC_ENABLE, NV_PMC_ENABLE_PFIFO, 0); - nv_mask(dev, NV03_PMC_ENABLE, NV_PMC_ENABLE_PFIFO, NV_PMC_ENABLE_PFIFO); + ret = nouveau_fifo_create(parent, engine, oclass, 0, 31, &priv); + *pobject = nv_object(priv); + if (ret) + return ret; + + nouveau_ramht_ref(imem->ramht, &priv->ramht); + nouveau_gpuobj_ref(imem->ramro, &priv->ramro); + nouveau_gpuobj_ref(imem->ramfc, &priv->ramfc); + + nv_subdev(priv)->unit = 0x00000100; + nv_subdev(priv)->intr = nv04_fifo_intr; + nv_engine(priv)->cclass = &nv17_fifo_cclass; + nv_engine(priv)->sclass = nv17_fifo_sclass; + priv->base.pause = nv04_fifo_pause; + priv->base.start = nv04_fifo_start; + priv->ramfc_desc = nv17_ramfc; + return 0; +} - nv_wr32(dev, NV04_PFIFO_DELAY_0, 0x000000ff); - nv_wr32(dev, NV04_PFIFO_DMA_TIMESLICE, 0x0101ffff); +static int +nv17_fifo_init(struct nouveau_object *object) +{ + struct nv04_fifo_priv *priv = (void *)object; + int ret; - nv_wr32(dev, NV03_PFIFO_RAMHT, (0x03 << 24) /* search 128 */ | - ((dev_priv->ramht->bits - 9) << 16) | - (dev_priv->ramht->gpuobj->addr >> 8)); - nv_wr32(dev, NV03_PFIFO_RAMRO, priv->ramro->addr >> 8); - nv_wr32(dev, NV03_PFIFO_RAMFC, 0x00010000 | - priv->ramfc->addr >> 8); + ret = nouveau_fifo_init(&priv->base); + if (ret) + return ret; - nv_wr32(dev, NV03_PFIFO_CACHE1_PUSH1, priv->base.channels); + nv_wr32(priv, NV04_PFIFO_DELAY_0, 0x000000ff); + nv_wr32(priv, NV04_PFIFO_DMA_TIMESLICE, 0x0101ffff); - nv_wr32(dev, NV03_PFIFO_INTR_0, 0xffffffff); - nv_wr32(dev, NV03_PFIFO_INTR_EN_0, 0xffffffff); + nv_wr32(priv, NV03_PFIFO_RAMHT, (0x03 << 24) /* search 128 */ | + ((priv->ramht->bits - 9) << 16) | + (priv->ramht->base.addr >> 8)); + nv_wr32(priv, NV03_PFIFO_RAMRO, priv->ramro->addr >> 8); + nv_wr32(priv, NV03_PFIFO_RAMFC, priv->ramfc->addr >> 8 | 0x00010000); - nv_wr32(dev, NV03_PFIFO_CACHE1_PUSH0, 1); - nv_wr32(dev, NV04_PFIFO_CACHE1_PULL0, 1); - nv_wr32(dev, NV03_PFIFO_CACHES, 1); + nv_wr32(priv, NV03_PFIFO_CACHE1_PUSH1, priv->base.max); - for (i = 0; i < priv->base.channels; i++) { - if (dev_priv->channels.ptr[i]) - nv_mask(dev, NV04_PFIFO_MODE, (1 << i), (1 << i)); - } + nv_wr32(priv, NV03_PFIFO_INTR_0, 0xffffffff); + nv_wr32(priv, NV03_PFIFO_INTR_EN_0, 0xffffffff); + nv_wr32(priv, NV03_PFIFO_CACHE1_PUSH0, 1); + nv_wr32(priv, NV04_PFIFO_CACHE1_PULL0, 1); + nv_wr32(priv, NV03_PFIFO_CACHES, 1); return 0; } -int -nv17_fifo_create(struct drm_device *dev) -{ - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nv17_fifo_priv *priv; - - priv = kzalloc(sizeof(*priv), GFP_KERNEL); - if (!priv) - return -ENOMEM; - - nouveau_gpuobj_ref(nvimem_ramro(dev), &priv->ramro); - nouveau_gpuobj_ref(nvimem_ramfc(dev), &priv->ramfc); - - priv->base.base.destroy = nv04_fifo_destroy; - priv->base.base.init = nv17_fifo_init; - priv->base.base.fini = nv04_fifo_fini; - priv->base.base.context_new = nv17_fifo_context_new; - priv->base.base.context_del = nv04_fifo_context_del; - priv->base.channels = 31; - priv->ramfc_desc = nv17_ramfc; - dev_priv->eng[NVOBJ_ENGINE_FIFO] = &priv->base.base; - - nouveau_irq_register(dev, 8, nv04_fifo_isr); - return 0; -} +struct nouveau_oclass +nv17_fifo_oclass = { + .handle = NV_ENGINE(FIFO, 0x17), + .ofuncs = &(struct nouveau_ofuncs) { + .ctor = nv17_fifo_ctor, + .dtor = nv04_fifo_dtor, + .init = nv17_fifo_init, + .fini = _nouveau_fifo_fini, + }, +}; diff --git a/drivers/gpu/drm/nouveau/core/engine/fifo/nv40.c b/drivers/gpu/drm/nouveau/core/engine/fifo/nv40.c index 65a670f92a07..43d5c9eea865 100644 --- a/drivers/gpu/drm/nouveau/core/engine/fifo/nv40.c +++ b/drivers/gpu/drm/nouveau/core/engine/fifo/nv40.c @@ -1,43 +1,42 @@ /* - * Copyright (C) 2012 Ben Skeggs. - * All Rights Reserved. + * 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: + * 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 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 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 */ -#include "drmP.h" -#include "drm.h" -#include "nouveau_drv.h" -#include -#include "nouveau_util.h" +#include +#include +#include #include -static struct ramfc_desc { - unsigned bits:6; - unsigned ctxs:5; - unsigned ctxp:8; - unsigned regs:5; - unsigned regp; -} nv40_ramfc[] = { +#include +#include +#include + +#include + +#include "nv04.h" + +static struct ramfc_desc +nv40_ramfc[] = { { 32, 0, 0x00, 0, NV04_PFIFO_CACHE1_DMA_PUT }, { 32, 0, 0x04, 0, NV04_PFIFO_CACHE1_DMA_GET }, { 32, 0, 0x08, 0, NV10_PFIFO_CACHE1_REF_CNT }, @@ -63,148 +62,287 @@ static struct ramfc_desc { {} }; -struct nv40_fifo_priv { - struct nouveau_fifo_priv base; - struct ramfc_desc *ramfc_desc; - struct nouveau_gpuobj *ramro; - struct nouveau_gpuobj *ramfc; -}; +/******************************************************************************* + * FIFO channel objects + ******************************************************************************/ -struct nv40_fifo_chan { - struct nouveau_fifo_chan base; - u32 ramfc; -}; +static int +nv40_fifo_object_attach(struct nouveau_object *parent, + struct nouveau_object *object, u32 handle) +{ + struct nv04_fifo_priv *priv = (void *)parent->engine; + struct nv04_fifo_chan *chan = (void *)parent; + u32 context, chid = chan->base.chid; + int ret; + + if (nv_iclass(object, NV_GPUOBJ_CLASS)) + context = nv_gpuobj(object)->addr >> 4; + else + context = 0x00000004; /* just non-zero */ + + switch (nv_engidx(object->engine)) { + case NVDEV_ENGINE_DMAOBJ: + case NVDEV_ENGINE_SW: + context |= 0x00000000; + break; + case NVDEV_ENGINE_GR: + context |= 0x00100000; + break; + case NVDEV_ENGINE_MPEG: + context |= 0x00200000; + break; + default: + return -EINVAL; + } + + context |= chid << 23; + + mutex_lock(&nv_subdev(priv)->mutex); + ret = nouveau_ramht_insert(priv->ramht, chid, handle, context); + mutex_unlock(&nv_subdev(priv)->mutex); + return ret; +} static int -nv40_fifo_context_new(struct nouveau_channel *chan, int engine) +nv40_fifo_context_attach(struct nouveau_object *parent, + struct nouveau_object *engctx) { - struct drm_device *dev = chan->dev; - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nv40_fifo_priv *priv = nv_engine(dev, engine); - struct nv40_fifo_chan *fctx; + struct nv04_fifo_priv *priv = (void *)parent->engine; + struct nv04_fifo_chan *chan = (void *)parent; unsigned long flags; - int ret; + u32 reg, ctx; + + switch (nv_engidx(engctx->engine)) { + case NVDEV_ENGINE_SW: + return 0; + case NVDEV_ENGINE_GR: + reg = 0x32e0; + ctx = 0x38; + break; + case NVDEV_ENGINE_MPEG: + reg = 0x330c; + ctx = 0x54; + break; + default: + return -EINVAL; + } + + spin_lock_irqsave(&priv->base.lock, flags); + nv_mask(priv, 0x002500, 0x00000001, 0x00000000); - fctx = chan->engctx[engine] = kzalloc(sizeof(*fctx), GFP_KERNEL); - if (!fctx) - return -ENOMEM; + if ((nv_rd32(priv, 0x003204) & priv->base.max) == chan->base.chid) + nv_wr32(priv, reg, nv_gpuobj(engctx)->addr >> 4); + nv_wo32(priv->ramfc, chan->ramfc + ctx, nv_gpuobj(engctx)->addr >> 4); + + nv_mask(priv, 0x002500, 0x00000001, 0x00000001); + spin_unlock_irqrestore(&priv->base.lock, flags); + return 0; +} - fctx->ramfc = chan->id * 128; +static int +nv40_fifo_context_detach(struct nouveau_object *parent, bool suspend, + struct nouveau_object *engctx) +{ + struct nv04_fifo_priv *priv = (void *)parent->engine; + struct nv04_fifo_chan *chan = (void *)parent; + unsigned long flags; + u32 reg, ctx; - /* map channel control registers */ - chan->user = ioremap(pci_resource_start(dev->pdev, 0) + - NV03_USER(chan->id), PAGE_SIZE); - if (!chan->user) { - ret = -ENOMEM; - goto error; + switch (nv_engidx(engctx->engine)) { + case NVDEV_ENGINE_SW: + return 0; + case NVDEV_ENGINE_GR: + reg = 0x32e0; + ctx = 0x38; + break; + case NVDEV_ENGINE_MPEG: + reg = 0x330c; + ctx = 0x54; + break; + default: + return -EINVAL; } - /* initialise default fifo context */ - nv_wo32(priv->ramfc, fctx->ramfc + 0x00, chan->pushbuf_base); - nv_wo32(priv->ramfc, fctx->ramfc + 0x04, chan->pushbuf_base); - nv_wo32(priv->ramfc, fctx->ramfc + 0x0c, chan->pushbuf->addr >> 4); - nv_wo32(priv->ramfc, fctx->ramfc + 0x18, 0x30000000 | + spin_lock_irqsave(&priv->base.lock, flags); + nv_mask(priv, 0x002500, 0x00000001, 0x00000000); + + if ((nv_rd32(priv, 0x003204) & priv->base.max) == chan->base.chid) + nv_wr32(priv, reg, 0x00000000); + nv_wo32(priv->ramfc, chan->ramfc + ctx, 0x00000000); + + nv_mask(priv, 0x002500, 0x00000001, 0x00000001); + spin_unlock_irqrestore(&priv->base.lock, flags); + return 0; +} + +static int +nv40_fifo_chan_ctor(struct nouveau_object *parent, + struct nouveau_object *engine, + struct nouveau_oclass *oclass, void *data, u32 size, + struct nouveau_object **pobject) +{ + struct nv04_fifo_priv *priv = (void *)engine; + struct nv04_fifo_chan *chan; + struct nv_channel_dma_class *args = data; + int ret; + + if (size < sizeof(*args)) + return -EINVAL; + + ret = nouveau_fifo_channel_create(parent, engine, oclass, 0, 0xc00000, + 0x1000, args->pushbuf, + (1 << NVDEV_ENGINE_DMAOBJ) | + (1 << NVDEV_ENGINE_SW) | + (1 << NVDEV_ENGINE_GR) | + (1 << NVDEV_ENGINE_MPEG), &chan); + *pobject = nv_object(chan); + if (ret) + return ret; + + nv_parent(chan)->context_attach = nv40_fifo_context_attach; + nv_parent(chan)->context_detach = nv40_fifo_context_detach; + nv_parent(chan)->object_attach = nv40_fifo_object_attach; + nv_parent(chan)->object_detach = nv04_fifo_object_detach; + chan->ramfc = chan->base.chid * 128; + + nv_wo32(priv->ramfc, chan->ramfc + 0x00, args->offset); + nv_wo32(priv->ramfc, chan->ramfc + 0x04, args->offset); + nv_wo32(priv->ramfc, chan->ramfc + 0x0c, chan->base.pushgpu->addr >> 4); + nv_wo32(priv->ramfc, chan->ramfc + 0x18, 0x30000000 | NV_PFIFO_CACHE1_DMA_FETCH_TRIG_128_BYTES | NV_PFIFO_CACHE1_DMA_FETCH_SIZE_128_BYTES | #ifdef __BIG_ENDIAN NV_PFIFO_CACHE1_BIG_ENDIAN | #endif NV_PFIFO_CACHE1_DMA_FETCH_MAX_REQS_8); - nv_wo32(priv->ramfc, fctx->ramfc + 0x3c, 0x0001ffff); + nv_wo32(priv->ramfc, chan->ramfc + 0x3c, 0x0001ffff); + return 0; +} + +static struct nouveau_ofuncs +nv40_fifo_ofuncs = { + .ctor = nv40_fifo_chan_ctor, + .dtor = nv04_fifo_chan_dtor, + .init = nv04_fifo_chan_init, + .fini = nv04_fifo_chan_fini, + .rd32 = _nouveau_fifo_channel_rd32, + .wr32 = _nouveau_fifo_channel_wr32, +}; + +static struct nouveau_oclass +nv40_fifo_sclass[] = { + { 0x006e, &nv40_fifo_ofuncs }, + {} +}; - /* enable dma mode on the channel */ - spin_lock_irqsave(&dev_priv->context_switch_lock, flags); - nv_mask(dev, NV04_PFIFO_MODE, (1 << chan->id), (1 << chan->id)); - spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags); +/******************************************************************************* + * FIFO context - basically just the instmem reserved for the channel + ******************************************************************************/ - /*XXX: remove this later, need fifo engine context commit hook */ - nouveau_gpuobj_ref(priv->ramfc, &chan->ramfc); +static struct nouveau_oclass +nv40_fifo_cclass = { + .handle = NV_ENGCTX(FIFO, 0x40), + .ofuncs = &(struct nouveau_ofuncs) { + .ctor = nv04_fifo_context_ctor, + .dtor = _nouveau_fifo_context_dtor, + .init = _nouveau_fifo_context_init, + .fini = _nouveau_fifo_context_fini, + .rd32 = _nouveau_fifo_context_rd32, + .wr32 = _nouveau_fifo_context_wr32, + }, +}; -error: +/******************************************************************************* + * PFIFO engine + ******************************************************************************/ + +static int +nv40_fifo_ctor(struct nouveau_object *parent, struct nouveau_object *engine, + struct nouveau_oclass *oclass, void *data, u32 size, + struct nouveau_object **pobject) +{ + struct nv04_instmem_priv *imem = nv04_instmem(parent); + struct nv04_fifo_priv *priv; + int ret; + + ret = nouveau_fifo_create(parent, engine, oclass, 0, 31, &priv); + *pobject = nv_object(priv); if (ret) - priv->base.base.context_del(chan, engine); - return ret; + return ret; + + nouveau_ramht_ref(imem->ramht, &priv->ramht); + nouveau_gpuobj_ref(imem->ramro, &priv->ramro); + nouveau_gpuobj_ref(imem->ramfc, &priv->ramfc); + + nv_subdev(priv)->unit = 0x00000100; + nv_subdev(priv)->intr = nv04_fifo_intr; + nv_engine(priv)->cclass = &nv40_fifo_cclass; + nv_engine(priv)->sclass = nv40_fifo_sclass; + priv->base.pause = nv04_fifo_pause; + priv->base.start = nv04_fifo_start; + priv->ramfc_desc = nv40_ramfc; + return 0; } static int -nv40_fifo_init(struct drm_device *dev, int engine) +nv40_fifo_init(struct nouveau_object *object) { - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nv40_fifo_priv *priv = nv_engine(dev, engine); - int i; + struct nv04_fifo_priv *priv = (void *)object; + struct nouveau_fb *pfb = nouveau_fb(object); + int ret; - nv_mask(dev, NV03_PMC_ENABLE, NV_PMC_ENABLE_PFIFO, 0); - nv_mask(dev, NV03_PMC_ENABLE, NV_PMC_ENABLE_PFIFO, NV_PMC_ENABLE_PFIFO); + ret = nouveau_fifo_init(&priv->base); + if (ret) + return ret; - nv_wr32(dev, 0x002040, 0x000000ff); - nv_wr32(dev, 0x002044, 0x2101ffff); - nv_wr32(dev, 0x002058, 0x00000001); + nv_wr32(priv, 0x002040, 0x000000ff); + nv_wr32(priv, 0x002044, 0x2101ffff); + nv_wr32(priv, 0x002058, 0x00000001); - nv_wr32(dev, NV03_PFIFO_RAMHT, (0x03 << 24) /* search 128 */ | - ((dev_priv->ramht->bits - 9) << 16) | - (dev_priv->ramht->gpuobj->addr >> 8)); - nv_wr32(dev, NV03_PFIFO_RAMRO, priv->ramro->addr >> 8); + nv_wr32(priv, NV03_PFIFO_RAMHT, (0x03 << 24) /* search 128 */ | + ((priv->ramht->bits - 9) << 16) | + (priv->ramht->base.addr >> 8)); + nv_wr32(priv, NV03_PFIFO_RAMRO, priv->ramro->addr >> 8); - switch (dev_priv->chipset) { + switch (nv_device(priv)->chipset) { case 0x47: case 0x49: case 0x4b: - nv_wr32(dev, 0x002230, 0x00000001); + nv_wr32(priv, 0x002230, 0x00000001); case 0x40: case 0x41: case 0x42: case 0x43: case 0x45: case 0x48: - nv_wr32(dev, 0x002220, 0x00030002); + nv_wr32(priv, 0x002220, 0x00030002); break; default: - nv_wr32(dev, 0x002230, 0x00000000); - nv_wr32(dev, 0x002220, ((nvfb_vram_size(dev) - 512 * 1024 + + nv_wr32(priv, 0x002230, 0x00000000); + nv_wr32(priv, 0x002220, ((pfb->ram.size - 512 * 1024 + priv->ramfc->addr) >> 16) | - 0x00030000); + 0x00030000); break; } - nv_wr32(dev, NV03_PFIFO_CACHE1_PUSH1, priv->base.channels); + nv_wr32(priv, NV03_PFIFO_CACHE1_PUSH1, priv->base.max); - nv_wr32(dev, NV03_PFIFO_INTR_0, 0xffffffff); - nv_wr32(dev, NV03_PFIFO_INTR_EN_0, 0xffffffff); - - nv_wr32(dev, NV03_PFIFO_CACHE1_PUSH0, 1); - nv_wr32(dev, NV04_PFIFO_CACHE1_PULL0, 1); - nv_wr32(dev, NV03_PFIFO_CACHES, 1); - - for (i = 0; i < priv->base.channels; i++) { - if (dev_priv->channels.ptr[i]) - nv_mask(dev, NV04_PFIFO_MODE, (1 << i), (1 << i)); - } + nv_wr32(priv, NV03_PFIFO_INTR_0, 0xffffffff); + nv_wr32(priv, NV03_PFIFO_INTR_EN_0, 0xffffffff); + nv_wr32(priv, NV03_PFIFO_CACHE1_PUSH0, 1); + nv_wr32(priv, NV04_PFIFO_CACHE1_PULL0, 1); + nv_wr32(priv, NV03_PFIFO_CACHES, 1); return 0; } -int -nv40_fifo_create(struct drm_device *dev) -{ - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nv40_fifo_priv *priv; - - priv = kzalloc(sizeof(*priv), GFP_KERNEL); - if (!priv) - return -ENOMEM; - - nouveau_gpuobj_ref(nvimem_ramro(dev), &priv->ramro); - nouveau_gpuobj_ref(nvimem_ramfc(dev), &priv->ramfc); - - priv->base.base.destroy = nv04_fifo_destroy; - priv->base.base.init = nv40_fifo_init; - priv->base.base.fini = nv04_fifo_fini; - priv->base.base.context_new = nv40_fifo_context_new; - priv->base.base.context_del = nv04_fifo_context_del; - priv->base.channels = 31; - priv->ramfc_desc = nv40_ramfc; - dev_priv->eng[NVOBJ_ENGINE_FIFO] = &priv->base.base; - - nouveau_irq_register(dev, 8, nv04_fifo_isr); - return 0; -} +struct nouveau_oclass +nv40_fifo_oclass = { + .handle = NV_ENGINE(FIFO, 0x40), + .ofuncs = &(struct nouveau_ofuncs) { + .ctor = nv40_fifo_ctor, + .dtor = nv04_fifo_dtor, + .init = nv40_fifo_init, + .fini = _nouveau_fifo_fini, + }, +}; diff --git a/drivers/gpu/drm/nouveau/core/engine/fifo/nv50.c b/drivers/gpu/drm/nouveau/core/engine/fifo/nv50.c index 7b5b1592bf61..4914c3b94413 100644 --- a/drivers/gpu/drm/nouveau/core/engine/fifo/nv50.c +++ b/drivers/gpu/drm/nouveau/core/engine/fifo/nv50.c @@ -1,126 +1,123 @@ /* - * Copyright (C) 2012 Ben Skeggs. - * All Rights Reserved. + * 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: + * 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 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 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 */ -#include "drmP.h" -#include "drm.h" -#include "nouveau_drv.h" -#include +#include +#include #include +#include +#include -struct nv50_fifo_priv { - struct nouveau_fifo_priv base; - struct nouveau_gpuobj *playlist[2]; - int cur_playlist; -}; +#include +#include -struct nv50_fifo_chan { - struct nouveau_fifo_chan base; -}; +#include +#include + +#include "nv50.h" + +/******************************************************************************* + * FIFO channel objects + ******************************************************************************/ void -nv50_fifo_playlist_update(struct drm_device *dev) +nv50_fifo_playlist_update(struct nv50_fifo_priv *priv) { - struct nv50_fifo_priv *priv = nv_engine(dev, NVOBJ_ENGINE_FIFO); + struct nouveau_bar *bar = nouveau_bar(priv); struct nouveau_gpuobj *cur; int i, p; cur = priv->playlist[priv->cur_playlist]; priv->cur_playlist = !priv->cur_playlist; - for (i = 0, p = 0; i < priv->base.channels; i++) { - if (nv_rd32(dev, 0x002600 + (i * 4)) & 0x80000000) + for (i = priv->base.min, p = 0; i < priv->base.max; i++) { + if (nv_rd32(priv, 0x002600 + (i * 4)) & 0x80000000) nv_wo32(cur, p++ * 4, i); } - nvimem_flush(dev); + bar->flush(bar); - nv_wr32(dev, 0x0032f4, cur->addr >> 12); - nv_wr32(dev, 0x0032ec, p); - nv_wr32(dev, 0x002500, 0x00000101); + nv_wr32(priv, 0x0032f4, cur->addr >> 12); + nv_wr32(priv, 0x0032ec, p); + nv_wr32(priv, 0x002500, 0x00000101); } static int -nv50_fifo_context_new(struct nouveau_channel *chan, int engine) +nv50_fifo_context_attach(struct nouveau_object *parent, + struct nouveau_object *object) { - struct nv50_fifo_priv *priv = nv_engine(chan->dev, engine); - struct nv50_fifo_chan *fctx; - struct drm_device *dev = chan->dev; - struct drm_nouveau_private *dev_priv = dev->dev_private; - u64 ib_offset = chan->pushbuf_base + chan->dma.ib_base * 4; - u64 instance = chan->ramin->addr >> 12; - unsigned long flags; - int ret = 0, i; - - fctx = chan->engctx[engine] = kzalloc(sizeof(*fctx), GFP_KERNEL); - if (!fctx) - return -ENOMEM; - nvvm_engref(chan->vm, engine, 1); - - chan->user = ioremap(pci_resource_start(dev->pdev, 0) + - NV50_USER(chan->id), PAGE_SIZE); - if (!chan->user) { - ret = -ENOMEM; - goto error; + struct nouveau_bar *bar = nouveau_bar(parent); + struct nv50_fifo_base *base = (void *)parent->parent; + struct nouveau_gpuobj *ectx = (void *)object; + u64 limit = ectx->addr + ectx->size - 1; + u64 start = ectx->addr; + u32 addr; + + switch (nv_engidx(object->engine)) { + case NVDEV_ENGINE_SW : return 0; + case NVDEV_ENGINE_GR : addr = 0x0000; break; + case NVDEV_ENGINE_MPEG : addr = 0x0060; break; + default: + return -EINVAL; } - for (i = 0; i < 0x100; i += 4) - nv_wo32(chan->ramin, i, 0x00000000); - nv_wo32(chan->ramin, 0x3c, 0x403f6078); - nv_wo32(chan->ramin, 0x40, 0x00000000); - nv_wo32(chan->ramin, 0x44, 0x01003fff); - nv_wo32(chan->ramin, 0x48, chan->pushbuf->node->offset >> 4); - nv_wo32(chan->ramin, 0x50, lower_32_bits(ib_offset)); - nv_wo32(chan->ramin, 0x54, upper_32_bits(ib_offset) | - drm_order(chan->dma.ib_max + 1) << 16); - nv_wo32(chan->ramin, 0x60, 0x7fffffff); - nv_wo32(chan->ramin, 0x78, 0x00000000); - nv_wo32(chan->ramin, 0x7c, 0x30000001); - nv_wo32(chan->ramin, 0x80, ((chan->ramht->bits - 9) << 27) | - (4 << 24) /* SEARCH_FULL */ | - (chan->ramht->gpuobj->node->offset >> 4)); - - nvimem_flush(dev); - - spin_lock_irqsave(&dev_priv->context_switch_lock, flags); - nv_wr32(dev, 0x002600 + (chan->id * 4), 0x80000000 | instance); - nv50_fifo_playlist_update(dev); - spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags); - -error: - if (ret) - priv->base.base.context_del(chan, engine); - return ret; + nv_wo32(base->eng, addr + 0x00, 0x00190000); + nv_wo32(base->eng, addr + 0x04, lower_32_bits(limit)); + nv_wo32(base->eng, addr + 0x08, lower_32_bits(start)); + nv_wo32(base->eng, addr + 0x0c, upper_32_bits(limit) << 24 | + upper_32_bits(start)); + nv_wo32(base->eng, addr + 0x10, 0x00000000); + nv_wo32(base->eng, addr + 0x14, 0x00000000); + bar->flush(bar); + return 0; } -static bool -nv50_fifo_kickoff(struct nouveau_channel *chan) +static int +nv50_fifo_context_detach(struct nouveau_object *parent, bool suspend, + struct nouveau_object *object) { - struct drm_device *dev = chan->dev; - bool done = true; - u32 me; + struct nouveau_bar *bar = nouveau_bar(parent); + struct nv50_fifo_priv *priv = (void *)parent->engine; + struct nv50_fifo_base *base = (void *)parent->parent; + struct nv50_fifo_chan *chan = (void *)parent; + u32 addr, me; + int ret = 0; + + switch (nv_engidx(object->engine)) { + case NVDEV_ENGINE_SW : return 0; + case NVDEV_ENGINE_GR : addr = 0x0000; break; + case NVDEV_ENGINE_MPEG : addr = 0x0060; break; + default: + return -EINVAL; + } + + nv_wo32(base->eng, addr + 0x00, 0x00000000); + nv_wo32(base->eng, addr + 0x04, 0x00000000); + nv_wo32(base->eng, addr + 0x08, 0x00000000); + nv_wo32(base->eng, addr + 0x0c, 0x00000000); + nv_wo32(base->eng, addr + 0x10, 0x00000000); + nv_wo32(base->eng, addr + 0x14, 0x00000000); + bar->flush(bar); /* HW bug workaround: * @@ -134,159 +131,308 @@ nv50_fifo_kickoff(struct nouveau_channel *chan) * there's also a "ignore these engines" bitmask reg we can use * if we hit the issue there.. */ - - /* PME: make sure engine is enabled */ - me = nv_mask(dev, 0x00b860, 0x00000001, 0x00000001); + me = nv_mask(priv, 0x00b860, 0x00000001, 0x00000001); /* do the kickoff... */ - nv_wr32(dev, 0x0032fc, chan->ramin->addr >> 12); - if (!nv_wait_ne(dev, 0x0032fc, 0xffffffff, 0xffffffff)) { - NV_INFO(dev, "PFIFO: channel %d unload timeout\n", chan->id); - done = false; + nv_wr32(priv, 0x0032fc, nv_gpuobj(base)->addr >> 12); + if (!nv_wait_ne(priv, 0x0032fc, 0xffffffff, 0xffffffff)) { + nv_error(priv, "channel %d unload timeout\n", chan->base.chid); + if (suspend) + ret = -EBUSY; } - /* restore any engine states we changed, and exit */ - nv_wr32(dev, 0x00b860, me); - return done; + nv_wr32(priv, 0x00b860, me); + return ret; } -static void -nv50_fifo_context_del(struct nouveau_channel *chan, int engine) +static int +nv50_fifo_object_attach(struct nouveau_object *parent, + struct nouveau_object *object, u32 handle) { - struct nv50_fifo_chan *fctx = chan->engctx[engine]; - struct drm_device *dev = chan->dev; - struct drm_nouveau_private *dev_priv = dev->dev_private; - unsigned long flags; - - /* remove channel from playlist, will context switch if active */ - spin_lock_irqsave(&dev_priv->context_switch_lock, flags); - nv_mask(dev, 0x002600 + (chan->id * 4), 0x80000000, 0x00000000); - nv50_fifo_playlist_update(dev); - - /* tell any engines on this channel to unload their contexts */ - nv50_fifo_kickoff(chan); - - nv_wr32(dev, 0x002600 + (chan->id * 4), 0x00000000); - spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags); - - /* clean up */ - if (chan->user) { - iounmap(chan->user); - chan->user = NULL; + struct nv50_fifo_chan *chan = (void *)parent; + u32 context; + + if (nv_iclass(object, NV_GPUOBJ_CLASS)) + context = nv_gpuobj(object)->node->offset >> 4; + else + context = 0x00000004; /* just non-zero */ + + switch (nv_engidx(object->engine)) { + case NVDEV_ENGINE_DMAOBJ: + case NVDEV_ENGINE_SW : context |= 0x00000000; break; + case NVDEV_ENGINE_GR : context |= 0x00100000; break; + case NVDEV_ENGINE_MPEG : context |= 0x00200000; break; + default: + return -EINVAL; } - nvvm_engref(chan->vm, engine, -1); - chan->engctx[engine] = NULL; - kfree(fctx); + return nouveau_ramht_insert(chan->ramht, 0, handle, context); +} + +void +nv50_fifo_object_detach(struct nouveau_object *parent, int cookie) +{ + struct nv50_fifo_chan *chan = (void *)parent; + nouveau_ramht_remove(chan->ramht, cookie); } static int -nv50_fifo_init(struct drm_device *dev, int engine) +nv50_fifo_chan_ctor(struct nouveau_object *parent, + struct nouveau_object *engine, + struct nouveau_oclass *oclass, void *data, u32 size, + struct nouveau_object **pobject) { - struct drm_nouveau_private *dev_priv = dev->dev_private; - u32 instance; - int i; - - nv_mask(dev, 0x000200, 0x00000100, 0x00000000); - nv_mask(dev, 0x000200, 0x00000100, 0x00000100); - nv_wr32(dev, 0x00250c, 0x6f3cfc34); - nv_wr32(dev, 0x002044, 0x01003fff); - - nv_wr32(dev, 0x002100, 0xffffffff); - nv_wr32(dev, 0x002140, 0xffffffff); - - for (i = 0; i < 128; i++) { - struct nouveau_channel *chan = dev_priv->channels.ptr[i]; - if (chan && chan->engctx[engine]) - instance = 0x80000000 | chan->ramin->addr >> 12; - else - instance = 0x00000000; - nv_wr32(dev, 0x002600 + (i * 4), instance); - } + struct nv_channel_ind_class *args = data; + struct nouveau_bar *bar = nouveau_bar(parent); + struct nv50_fifo_base *base = (void *)parent; + struct nv50_fifo_chan *chan; + u64 ioffset, ilength; + int ret; + + if (size < sizeof(*args)) + return -EINVAL; + + ret = nouveau_fifo_channel_create(parent, engine, oclass, 0, 0xc00000, + 0x2000, args->pushbuf, + (1 << NVDEV_ENGINE_DMAOBJ) | + (1 << NVDEV_ENGINE_SW) | + (1 << NVDEV_ENGINE_GR) | + (1 << NVDEV_ENGINE_MPEG), &chan); + *pobject = nv_object(chan); + if (ret) + return ret; - nv50_fifo_playlist_update(dev); + nv_parent(chan)->context_attach = nv50_fifo_context_attach; + nv_parent(chan)->context_detach = nv50_fifo_context_detach; + nv_parent(chan)->object_attach = nv50_fifo_object_attach; + nv_parent(chan)->object_detach = nv50_fifo_object_detach; - nv_wr32(dev, 0x003200, 1); - nv_wr32(dev, 0x003250, 1); - nv_wr32(dev, 0x002500, 1); + ret = nouveau_ramht_new(parent, parent, 0x8000, 16, &chan->ramht); + if (ret) + return ret; + + ioffset = args->ioffset; + ilength = log2i(args->ilength / 8); + + nv_wo32(base->ramfc, 0x3c, 0x403f6078); + nv_wo32(base->ramfc, 0x44, 0x01003fff); + nv_wo32(base->ramfc, 0x48, chan->base.pushgpu->node->offset >> 4); + nv_wo32(base->ramfc, 0x50, lower_32_bits(ioffset)); + nv_wo32(base->ramfc, 0x54, upper_32_bits(ioffset) | (ilength << 16)); + nv_wo32(base->ramfc, 0x60, 0x7fffffff); + nv_wo32(base->ramfc, 0x78, 0x00000000); + nv_wo32(base->ramfc, 0x7c, 0x30000001); + nv_wo32(base->ramfc, 0x80, ((chan->ramht->bits - 9) << 27) | + (4 << 24) /* SEARCH_FULL */ | + (chan->ramht->base.node->offset >> 4)); + bar->flush(bar); return 0; } +void +nv50_fifo_chan_dtor(struct nouveau_object *object) +{ + struct nv50_fifo_chan *chan = (void *)object; + nouveau_ramht_ref(NULL, &chan->ramht); + nouveau_fifo_channel_destroy(&chan->base); +} + static int -nv50_fifo_fini(struct drm_device *dev, int engine, bool suspend) +nv50_fifo_chan_init(struct nouveau_object *object) { - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nv50_fifo_priv *priv = nv_engine(dev, engine); - int i; - - /* set playlist length to zero, fifo will unload context */ - nv_wr32(dev, 0x0032ec, 0); - - /* tell all connected engines to unload their contexts */ - for (i = 0; i < priv->base.channels; i++) { - struct nouveau_channel *chan = dev_priv->channels.ptr[i]; - if (chan && !nv50_fifo_kickoff(chan)) - return -EBUSY; - } + struct nv50_fifo_priv *priv = (void *)object->engine; + struct nv50_fifo_base *base = (void *)object->parent; + struct nv50_fifo_chan *chan = (void *)object; + struct nouveau_gpuobj *ramfc = base->ramfc; + u32 chid = chan->base.chid; + int ret; - nv_wr32(dev, 0x002140, 0); + ret = nouveau_fifo_channel_init(&chan->base); + if (ret) + return ret; + + nv_wr32(priv, 0x002600 + (chid * 4), 0x80000000 | ramfc->addr >> 12); + nv50_fifo_playlist_update(priv); return 0; } -void -nv50_fifo_tlb_flush(struct drm_device *dev, int engine) +int +nv50_fifo_chan_fini(struct nouveau_object *object, bool suspend) { - nv50_vm_flush_engine(dev, 5); + struct nv50_fifo_priv *priv = (void *)object->engine; + struct nv50_fifo_chan *chan = (void *)object; + u32 chid = chan->base.chid; + + /* remove channel from playlist, fifo will unload context */ + nv_mask(priv, 0x002600 + (chid * 4), 0x80000000, 0x00000000); + nv50_fifo_playlist_update(priv); + nv_wr32(priv, 0x002600 + (chid * 4), 0x00000000); + + return nouveau_fifo_channel_fini(&chan->base, suspend); } -void -nv50_fifo_destroy(struct drm_device *dev, int engine) +static struct nouveau_ofuncs +nv50_fifo_ofuncs = { + .ctor = nv50_fifo_chan_ctor, + .dtor = nv50_fifo_chan_dtor, + .init = nv50_fifo_chan_init, + .fini = nv50_fifo_chan_fini, + .rd32 = _nouveau_fifo_channel_rd32, + .wr32 = _nouveau_fifo_channel_wr32, +}; + +static struct nouveau_oclass +nv50_fifo_sclass[] = { + { 0x506f, &nv50_fifo_ofuncs }, + {} +}; + +/******************************************************************************* + * FIFO context - basically just the instmem reserved for the channel + ******************************************************************************/ + +static int +nv50_fifo_context_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 nv50_fifo_priv *priv = nv_engine(dev, engine); + struct nv50_fifo_base *base; + int ret; - nouveau_irq_unregister(dev, 8); + ret = nouveau_fifo_context_create(parent, engine, oclass, NULL, 0x10000, + 0x1000, NVOBJ_FLAG_HEAP, &base); + *pobject = nv_object(base); + if (ret) + return ret; - nouveau_gpuobj_ref(NULL, &priv->playlist[0]); - nouveau_gpuobj_ref(NULL, &priv->playlist[1]); + ret = nouveau_gpuobj_new(parent, nv_object(base), 0x0200, 0x1000, + NVOBJ_FLAG_ZERO_ALLOC, &base->ramfc); + if (ret) + return ret; + + ret = nouveau_gpuobj_new(parent, nv_object(base), 0x1200, 0, + NVOBJ_FLAG_ZERO_ALLOC, &base->eng); + if (ret) + return ret; + + ret = nouveau_gpuobj_new(parent, nv_object(base), 0x4000, 0, 0, + &base->pgd); + if (ret) + return ret; + + ret = nouveau_vm_ref(nouveau_client(parent)->vm, &base->vm, base->pgd); + if (ret) + return ret; - dev_priv->eng[engine] = NULL; - kfree(priv); + return 0; } -int -nv50_fifo_create(struct drm_device *dev) +void +nv50_fifo_context_dtor(struct nouveau_object *object) +{ + struct nv50_fifo_base *base = (void *)object; + nouveau_vm_ref(NULL, &base->vm, base->pgd); + nouveau_gpuobj_ref(NULL, &base->pgd); + nouveau_gpuobj_ref(NULL, &base->eng); + nouveau_gpuobj_ref(NULL, &base->ramfc); + nouveau_gpuobj_ref(NULL, &base->cache); + nouveau_fifo_context_destroy(&base->base); +} + +static struct nouveau_oclass +nv50_fifo_cclass = { + .handle = NV_ENGCTX(FIFO, 0x50), + .ofuncs = &(struct nouveau_ofuncs) { + .ctor = nv50_fifo_context_ctor, + .dtor = nv50_fifo_context_dtor, + .init = _nouveau_fifo_context_init, + .fini = _nouveau_fifo_context_fini, + .rd32 = _nouveau_fifo_context_rd32, + .wr32 = _nouveau_fifo_context_wr32, + }, +}; + +/******************************************************************************* + * PFIFO engine + ******************************************************************************/ + +static int +nv50_fifo_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 nv50_fifo_priv *priv; int ret; - priv = kzalloc(sizeof(*priv), GFP_KERNEL); - if (!priv) - return -ENOMEM; - - priv->base.base.destroy = nv50_fifo_destroy; - priv->base.base.init = nv50_fifo_init; - priv->base.base.fini = nv50_fifo_fini; - priv->base.base.context_new = nv50_fifo_context_new; - priv->base.base.context_del = nv50_fifo_context_del; - priv->base.base.tlb_flush = nv50_fifo_tlb_flush; - priv->base.channels = 127; - dev_priv->eng[NVOBJ_ENGINE_FIFO] = &priv->base.base; - - ret = nouveau_gpuobj_new(dev, NULL, priv->base.channels * 4, 0x1000, - NVOBJ_FLAG_ZERO_ALLOC, &priv->playlist[0]); + ret = nouveau_fifo_create(parent, engine, oclass, 1, 127, &priv); + *pobject = nv_object(priv); if (ret) - goto error; + return ret; - ret = nouveau_gpuobj_new(dev, NULL, priv->base.channels * 4, 0x1000, - NVOBJ_FLAG_ZERO_ALLOC, &priv->playlist[1]); + ret = nouveau_gpuobj_new(parent, NULL, 128 * 4, 0x1000, 0, + &priv->playlist[0]); if (ret) - goto error; + return ret; - nouveau_irq_register(dev, 8, nv04_fifo_isr); -error: + ret = nouveau_gpuobj_new(parent, NULL, 128 * 4, 0x1000, 0, + &priv->playlist[1]); if (ret) - priv->base.base.destroy(dev, NVOBJ_ENGINE_FIFO); - return ret; + return ret; + + nv_subdev(priv)->unit = 0x00000100; + nv_subdev(priv)->intr = nv04_fifo_intr; + nv_engine(priv)->cclass = &nv50_fifo_cclass; + nv_engine(priv)->sclass = nv50_fifo_sclass; + return 0; +} + +void +nv50_fifo_dtor(struct nouveau_object *object) +{ + struct nv50_fifo_priv *priv = (void *)object; + + nouveau_gpuobj_ref(NULL, &priv->playlist[1]); + nouveau_gpuobj_ref(NULL, &priv->playlist[0]); + + nouveau_fifo_destroy(&priv->base); } + +int +nv50_fifo_init(struct nouveau_object *object) +{ + struct nv50_fifo_priv *priv = (void *)object; + int ret, i; + + ret = nouveau_fifo_init(&priv->base); + if (ret) + return ret; + + nv_mask(priv, 0x000200, 0x00000100, 0x00000000); + nv_mask(priv, 0x000200, 0x00000100, 0x00000100); + nv_wr32(priv, 0x00250c, 0x6f3cfc34); + nv_wr32(priv, 0x002044, 0x01003fff); + + nv_wr32(priv, 0x002100, 0xffffffff); + nv_wr32(priv, 0x002140, 0xffffffff); + + for (i = 0; i < 128; i++) + nv_wr32(priv, 0x002600 + (i * 4), 0x00000000); + nv50_fifo_playlist_update(priv); + + nv_wr32(priv, 0x003200, 0x00000001); + nv_wr32(priv, 0x003250, 0x00000001); + nv_wr32(priv, 0x002500, 0x00000001); + return 0; +} + +struct nouveau_oclass +nv50_fifo_oclass = { + .handle = NV_ENGINE(FIFO, 0x50), + .ofuncs = &(struct nouveau_ofuncs) { + .ctor = nv50_fifo_ctor, + .dtor = nv50_fifo_dtor, + .init = nv50_fifo_init, + .fini = _nouveau_fifo_fini, + }, +}; diff --git a/drivers/gpu/drm/nouveau/core/engine/fifo/nv50.h b/drivers/gpu/drm/nouveau/core/engine/fifo/nv50.h new file mode 100644 index 000000000000..3a9ceb315c20 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/engine/fifo/nv50.h @@ -0,0 +1,36 @@ +#ifndef __NV50_FIFO_H__ +#define __NV50_FIFO_H__ + +struct nv50_fifo_priv { + struct nouveau_fifo base; + struct nouveau_gpuobj *playlist[2]; + int cur_playlist; +}; + +struct nv50_fifo_base { + struct nouveau_fifo_base base; + struct nouveau_gpuobj *ramfc; + struct nouveau_gpuobj *cache; + struct nouveau_gpuobj *eng; + struct nouveau_gpuobj *pgd; + struct nouveau_vm *vm; +}; + +struct nv50_fifo_chan { + struct nouveau_fifo_chan base; + u32 subc[8]; + struct nouveau_ramht *ramht; +}; + +void nv50_fifo_playlist_update(struct nv50_fifo_priv *); + +void nv50_fifo_object_detach(struct nouveau_object *, int); +void nv50_fifo_chan_dtor(struct nouveau_object *); +int nv50_fifo_chan_fini(struct nouveau_object *, bool); + +void nv50_fifo_context_dtor(struct nouveau_object *); + +void nv50_fifo_dtor(struct nouveau_object *); +int nv50_fifo_init(struct nouveau_object *); + +#endif diff --git a/drivers/gpu/drm/nouveau/core/engine/fifo/nv84.c b/drivers/gpu/drm/nouveau/core/engine/fifo/nv84.c index 63a4941e285c..765affb12666 100644 --- a/drivers/gpu/drm/nouveau/core/engine/fifo/nv84.c +++ b/drivers/gpu/drm/nouveau/core/engine/fifo/nv84.c @@ -1,249 +1,343 @@ /* - * Copyright (C) 2012 Ben Skeggs. - * All Rights Reserved. + * 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: + * 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 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 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 */ -#include "drmP.h" -#include "drm.h" -#include "nouveau_drv.h" -#include +#include +#include +#include #include +#include +#include -struct nv84_fifo_priv { - struct nouveau_fifo_priv base; - struct nouveau_gpuobj *playlist[2]; - int cur_playlist; -}; +#include +#include -struct nv84_fifo_chan { - struct nouveau_fifo_chan base; - struct nouveau_gpuobj *ramfc; - struct nouveau_gpuobj *cache; -}; +#include +#include + +#include "nv50.h" + +/******************************************************************************* + * FIFO channel objects + ******************************************************************************/ static int -nv84_fifo_context_new(struct nouveau_channel *chan, int engine) +nv84_fifo_context_attach(struct nouveau_object *parent, + struct nouveau_object *object) { - struct nv84_fifo_priv *priv = nv_engine(chan->dev, engine); - struct nv84_fifo_chan *fctx; - struct drm_device *dev = chan->dev; - struct drm_nouveau_private *dev_priv = dev->dev_private; - u64 ib_offset = chan->pushbuf_base + chan->dma.ib_base * 4; - u64 instance; - unsigned long flags; - int ret; + struct nouveau_bar *bar = nouveau_bar(parent); + struct nv50_fifo_base *base = (void *)parent->parent; + struct nouveau_gpuobj *ectx = (void *)object; + u64 limit = ectx->addr + ectx->size - 1; + u64 start = ectx->addr; + u32 addr; + + switch (nv_engidx(object->engine)) { + case NVDEV_ENGINE_SW : return 0; + case NVDEV_ENGINE_GR : addr = 0x0020; break; + case NVDEV_ENGINE_MPEG : addr = 0x0060; break; + case NVDEV_ENGINE_CRYPT: addr = 0x00a0; break; + case NVDEV_ENGINE_COPY0: addr = 0x00c0; break; + default: + return -EINVAL; + } - fctx = chan->engctx[engine] = kzalloc(sizeof(*fctx), GFP_KERNEL); - if (!fctx) - return -ENOMEM; - nvvm_engref(chan->vm, engine, 1); + nv_wo32(base->eng, addr + 0x00, 0x00190000); + nv_wo32(base->eng, addr + 0x04, lower_32_bits(limit)); + nv_wo32(base->eng, addr + 0x08, lower_32_bits(start)); + nv_wo32(base->eng, addr + 0x0c, upper_32_bits(limit) << 24 | + upper_32_bits(start)); + nv_wo32(base->eng, addr + 0x10, 0x00000000); + nv_wo32(base->eng, addr + 0x14, 0x00000000); + bar->flush(bar); + return 0; +} - chan->user = ioremap(pci_resource_start(dev->pdev, 0) + - NV50_USER(chan->id), PAGE_SIZE); - if (!chan->user) { - ret = -ENOMEM; - goto error; +static int +nv84_fifo_context_detach(struct nouveau_object *parent, bool suspend, + struct nouveau_object *object) +{ + struct nouveau_bar *bar = nouveau_bar(parent); + struct nv50_fifo_priv *priv = (void *)parent->engine; + struct nv50_fifo_base *base = (void *)parent->parent; + struct nv50_fifo_chan *chan = (void *)parent; + u32 addr; + + switch (nv_engidx(object->engine)) { + case NVDEV_ENGINE_SW : return 0; + case NVDEV_ENGINE_GR : addr = 0x0020; break; + case NVDEV_ENGINE_MPEG : addr = 0x0060; break; + case NVDEV_ENGINE_CRYPT: addr = 0x00a0; break; + case NVDEV_ENGINE_COPY0: addr = 0x00c0; break; + default: + return -EINVAL; } - ret = nouveau_gpuobj_new(dev, chan, 256, 256, NVOBJ_FLAG_ZERO_ALLOC | - NVOBJ_FLAG_ZERO_FREE, &fctx->ramfc); - if (ret) - goto error; - - instance = fctx->ramfc->addr >> 8; + nv_wo32(base->eng, addr + 0x00, 0x00000000); + nv_wo32(base->eng, addr + 0x04, 0x00000000); + nv_wo32(base->eng, addr + 0x08, 0x00000000); + nv_wo32(base->eng, addr + 0x0c, 0x00000000); + nv_wo32(base->eng, addr + 0x10, 0x00000000); + nv_wo32(base->eng, addr + 0x14, 0x00000000); + bar->flush(bar); + + nv_wr32(priv, 0x0032fc, nv_gpuobj(base)->addr >> 12); + if (!nv_wait_ne(priv, 0x0032fc, 0xffffffff, 0xffffffff)) { + nv_error(priv, "channel %d unload timeout\n", chan->base.chid); + if (suspend) + return -EBUSY; + } + return 0; +} - ret = nouveau_gpuobj_new(dev, chan, 4096, 1024, 0, &fctx->cache); - if (ret) - goto error; - - nv_wo32(fctx->ramfc, 0x3c, 0x403f6078); - nv_wo32(fctx->ramfc, 0x40, 0x00000000); - nv_wo32(fctx->ramfc, 0x44, 0x01003fff); - nv_wo32(fctx->ramfc, 0x48, chan->pushbuf->node->offset >> 4); - nv_wo32(fctx->ramfc, 0x50, lower_32_bits(ib_offset)); - nv_wo32(fctx->ramfc, 0x54, upper_32_bits(ib_offset) | - drm_order(chan->dma.ib_max + 1) << 16); - nv_wo32(fctx->ramfc, 0x60, 0x7fffffff); - nv_wo32(fctx->ramfc, 0x78, 0x00000000); - nv_wo32(fctx->ramfc, 0x7c, 0x30000001); - nv_wo32(fctx->ramfc, 0x80, ((chan->ramht->bits - 9) << 27) | - (4 << 24) /* SEARCH_FULL */ | - (chan->ramht->gpuobj->node->offset >> 4)); - nv_wo32(fctx->ramfc, 0x88, fctx->cache->addr >> 10); - nv_wo32(fctx->ramfc, 0x98, chan->ramin->addr >> 12); +static int +nv84_fifo_object_attach(struct nouveau_object *parent, + struct nouveau_object *object, u32 handle) +{ + struct nv50_fifo_chan *chan = (void *)parent; + u32 context; + + if (nv_iclass(object, NV_GPUOBJ_CLASS)) + context = nv_gpuobj(object)->node->offset >> 4; + else + context = 0x00000004; /* just non-zero */ + + switch (nv_engidx(object->engine)) { + case NVDEV_ENGINE_DMAOBJ: + case NVDEV_ENGINE_SW : context |= 0x00000000; break; + case NVDEV_ENGINE_GR : context |= 0x00100000; break; + case NVDEV_ENGINE_MPEG : + case NVDEV_ENGINE_PPP : context |= 0x00200000; break; + case NVDEV_ENGINE_ME : + case NVDEV_ENGINE_COPY0 : context |= 0x00300000; break; + case NVDEV_ENGINE_VP : context |= 0x00400000; break; + case NVDEV_ENGINE_CRYPT : + case NVDEV_ENGINE_UNK1C1: context |= 0x00500000; break; + case NVDEV_ENGINE_BSP : context |= 0x00600000; break; + default: + return -EINVAL; + } - nv_wo32(chan->ramin, 0x00, chan->id); - nv_wo32(chan->ramin, 0x04, fctx->ramfc->addr >> 8); + return nouveau_ramht_insert(chan->ramht, 0, handle, context); +} - nvimem_flush(dev); +static int +nv84_fifo_chan_ctor(struct nouveau_object *parent, + struct nouveau_object *engine, + struct nouveau_oclass *oclass, void *data, u32 size, + struct nouveau_object **pobject) +{ + struct nouveau_bar *bar = nouveau_bar(parent); + struct nv50_fifo_base *base = (void *)parent; + struct nv50_fifo_chan *chan; + struct nv_channel_ind_class *args = data; + u64 ioffset, ilength; + int ret; - spin_lock_irqsave(&dev_priv->context_switch_lock, flags); - nv_wr32(dev, 0x002600 + (chan->id * 4), 0x80000000 | instance); - nv50_fifo_playlist_update(dev); - spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags); + if (size < sizeof(*args)) + return -EINVAL; + + ret = nouveau_fifo_channel_create(parent, engine, oclass, 0, 0xc00000, + 0x2000, args->pushbuf, + (1 << NVDEV_ENGINE_DMAOBJ) | + (1 << NVDEV_ENGINE_SW) | + (1 << NVDEV_ENGINE_GR) | + (1 << NVDEV_ENGINE_MPEG) | + (1 << NVDEV_ENGINE_ME) | + (1 << NVDEV_ENGINE_VP) | + (1 << NVDEV_ENGINE_CRYPT) | + (1 << NVDEV_ENGINE_BSP) | + (1 << NVDEV_ENGINE_PPP) | + (1 << NVDEV_ENGINE_COPY0) | + (1 << NVDEV_ENGINE_UNK1C1), &chan); + *pobject = nv_object(chan); + if (ret) + return ret; -error: + ret = nouveau_ramht_new(parent, parent, 0x8000, 16, &chan->ramht); if (ret) - priv->base.base.context_del(chan, engine); - return ret; + return ret; + + nv_parent(chan)->context_attach = nv84_fifo_context_attach; + nv_parent(chan)->context_detach = nv84_fifo_context_detach; + nv_parent(chan)->object_attach = nv84_fifo_object_attach; + nv_parent(chan)->object_detach = nv50_fifo_object_detach; + + ioffset = args->ioffset; + ilength = log2i(args->ilength / 8); + + nv_wo32(base->ramfc, 0x3c, 0x403f6078); + nv_wo32(base->ramfc, 0x44, 0x01003fff); + nv_wo32(base->ramfc, 0x48, chan->base.pushgpu->node->offset >> 4); + nv_wo32(base->ramfc, 0x50, lower_32_bits(ioffset)); + nv_wo32(base->ramfc, 0x54, upper_32_bits(ioffset) | (ilength << 16)); + nv_wo32(base->ramfc, 0x60, 0x7fffffff); + nv_wo32(base->ramfc, 0x78, 0x00000000); + nv_wo32(base->ramfc, 0x7c, 0x30000001); + nv_wo32(base->ramfc, 0x80, ((chan->ramht->bits - 9) << 27) | + (4 << 24) /* SEARCH_FULL */ | + (chan->ramht->base.node->offset >> 4)); + nv_wo32(base->ramfc, 0x88, base->cache->addr >> 10); + nv_wo32(base->ramfc, 0x98, nv_gpuobj(base)->addr >> 12); + bar->flush(bar); + return 0; } -static void -nv84_fifo_context_del(struct nouveau_channel *chan, int engine) +static int +nv84_fifo_chan_init(struct nouveau_object *object) { - struct nv84_fifo_chan *fctx = chan->engctx[engine]; - struct drm_device *dev = chan->dev; - struct drm_nouveau_private *dev_priv = dev->dev_private; - unsigned long flags; - u32 save; + struct nv50_fifo_priv *priv = (void *)object->engine; + struct nv50_fifo_base *base = (void *)object->parent; + struct nv50_fifo_chan *chan = (void *)object; + struct nouveau_gpuobj *ramfc = base->ramfc; + u32 chid = chan->base.chid; + int ret; + + ret = nouveau_fifo_channel_init(&chan->base); + if (ret) + return ret; - /* remove channel from playlist, will context switch if active */ - spin_lock_irqsave(&dev_priv->context_switch_lock, flags); - nv_mask(dev, 0x002600 + (chan->id * 4), 0x80000000, 0x00000000); - nv50_fifo_playlist_update(dev); + nv_wr32(priv, 0x002600 + (chid * 4), 0x80000000 | ramfc->addr >> 8); + nv50_fifo_playlist_update(priv); + return 0; +} - save = nv_mask(dev, 0x002520, 0x0000003f, 0x15); +static struct nouveau_ofuncs +nv84_fifo_ofuncs = { + .ctor = nv84_fifo_chan_ctor, + .dtor = nv50_fifo_chan_dtor, + .init = nv84_fifo_chan_init, + .fini = nv50_fifo_chan_fini, + .rd32 = _nouveau_fifo_channel_rd32, + .wr32 = _nouveau_fifo_channel_wr32, +}; - /* tell any engines on this channel to unload their contexts */ - nv_wr32(dev, 0x0032fc, chan->ramin->addr >> 12); - if (!nv_wait_ne(dev, 0x0032fc, 0xffffffff, 0xffffffff)) - NV_INFO(dev, "PFIFO: channel %d unload timeout\n", chan->id); +static struct nouveau_oclass +nv84_fifo_sclass[] = { + { 0x826f, &nv84_fifo_ofuncs }, + {} +}; - nv_wr32(dev, 0x002520, save); +/******************************************************************************* + * FIFO context - basically just the instmem reserved for the channel + ******************************************************************************/ - nv_wr32(dev, 0x002600 + (chan->id * 4), 0x00000000); - spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags); +int +nv84_fifo_context_ctor(struct nouveau_object *parent, + struct nouveau_object *engine, + struct nouveau_oclass *oclass, void *data, u32 size, + struct nouveau_object **pobject) +{ + struct nv50_fifo_base *base; + int ret; - /* clean up */ - if (chan->user) { - iounmap(chan->user); - chan->user = NULL; - } + ret = nouveau_fifo_context_create(parent, engine, oclass, NULL, 0x10000, + 0x1000, NVOBJ_FLAG_HEAP, &base); + *pobject = nv_object(base); + if (ret) + return ret; - nouveau_gpuobj_ref(NULL, &fctx->ramfc); - nouveau_gpuobj_ref(NULL, &fctx->cache); + ret = nouveau_gpuobj_new(parent, nv_object(base), 0x0200, 0, + NVOBJ_FLAG_ZERO_ALLOC, &base->eng); + if (ret) + return ret; - nvvm_engref(chan->vm, engine, -1); - chan->engctx[engine] = NULL; - kfree(fctx); -} + ret = nouveau_gpuobj_new(parent, nv_object(base), 0x4000, 0, + 0, &base->pgd); + if (ret) + return ret; -static int -nv84_fifo_init(struct drm_device *dev, int engine) -{ - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nv84_fifo_chan *fctx; - u32 instance; - int i; - - nv_mask(dev, 0x000200, 0x00000100, 0x00000000); - nv_mask(dev, 0x000200, 0x00000100, 0x00000100); - nv_wr32(dev, 0x00250c, 0x6f3cfc34); - nv_wr32(dev, 0x002044, 0x01003fff); - - nv_wr32(dev, 0x002100, 0xffffffff); - nv_wr32(dev, 0x002140, 0xffffffff); - - for (i = 0; i < 128; i++) { - struct nouveau_channel *chan = dev_priv->channels.ptr[i]; - if (chan && (fctx = chan->engctx[engine])) - instance = 0x80000000 | fctx->ramfc->addr >> 8; - else - instance = 0x00000000; - nv_wr32(dev, 0x002600 + (i * 4), instance); - } + ret = nouveau_vm_ref(nouveau_client(parent)->vm, &base->vm, base->pgd); + if (ret) + return ret; - nv50_fifo_playlist_update(dev); + ret = nouveau_gpuobj_new(parent, nv_object(base), 0x1000, 0x400, + NVOBJ_FLAG_ZERO_ALLOC, &base->cache); + if (ret) + return ret; + + ret = nouveau_gpuobj_new(parent, nv_object(base), 0x0100, 0x100, + NVOBJ_FLAG_ZERO_ALLOC, &base->ramfc); + if (ret) + return ret; - nv_wr32(dev, 0x003200, 1); - nv_wr32(dev, 0x003250, 1); - nv_wr32(dev, 0x002500, 1); return 0; } -static int -nv84_fifo_fini(struct drm_device *dev, int engine, bool suspend) -{ - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nv84_fifo_priv *priv = nv_engine(dev, engine); - int i; - u32 save; - - /* set playlist length to zero, fifo will unload context */ - nv_wr32(dev, 0x0032ec, 0); - - save = nv_mask(dev, 0x002520, 0x0000003f, 0x15); - - /* tell all connected engines to unload their contexts */ - for (i = 0; i < priv->base.channels; i++) { - struct nouveau_channel *chan = dev_priv->channels.ptr[i]; - if (chan) - nv_wr32(dev, 0x0032fc, chan->ramin->addr >> 12); - if (!nv_wait_ne(dev, 0x0032fc, 0xffffffff, 0xffffffff)) { - NV_INFO(dev, "PFIFO: channel %d unload timeout\n", i); - return -EBUSY; - } - } +static struct nouveau_oclass +nv84_fifo_cclass = { + .handle = NV_ENGCTX(FIFO, 0x84), + .ofuncs = &(struct nouveau_ofuncs) { + .ctor = nv84_fifo_context_ctor, + .dtor = nv50_fifo_context_dtor, + .init = _nouveau_fifo_context_init, + .fini = _nouveau_fifo_context_fini, + .rd32 = _nouveau_fifo_context_rd32, + .wr32 = _nouveau_fifo_context_wr32, + }, +}; - nv_wr32(dev, 0x002520, save); - nv_wr32(dev, 0x002140, 0); - return 0; -} +/******************************************************************************* + * PFIFO engine + ******************************************************************************/ -int -nv84_fifo_create(struct drm_device *dev) +static int +nv84_fifo_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 nv84_fifo_priv *priv; + struct nv50_fifo_priv *priv; int ret; - priv = kzalloc(sizeof(*priv), GFP_KERNEL); - if (!priv) - return -ENOMEM; - - priv->base.base.destroy = nv50_fifo_destroy; - priv->base.base.init = nv84_fifo_init; - priv->base.base.fini = nv84_fifo_fini; - priv->base.base.context_new = nv84_fifo_context_new; - priv->base.base.context_del = nv84_fifo_context_del; - priv->base.base.tlb_flush = nv50_fifo_tlb_flush; - priv->base.channels = 127; - dev_priv->eng[NVOBJ_ENGINE_FIFO] = &priv->base.base; - - ret = nouveau_gpuobj_new(dev, NULL, priv->base.channels * 4, 0x1000, - NVOBJ_FLAG_ZERO_ALLOC, &priv->playlist[0]); + ret = nouveau_fifo_create(parent, engine, oclass, 1, 127, &priv); + *pobject = nv_object(priv); if (ret) - goto error; + return ret; - ret = nouveau_gpuobj_new(dev, NULL, priv->base.channels * 4, 0x1000, - NVOBJ_FLAG_ZERO_ALLOC, &priv->playlist[1]); + ret = nouveau_gpuobj_new(parent, NULL, 128 * 4, 0x1000, 0, + &priv->playlist[0]); if (ret) - goto error; + return ret; - nouveau_irq_register(dev, 8, nv04_fifo_isr); -error: + ret = nouveau_gpuobj_new(parent, NULL, 128 * 4, 0x1000, 0, + &priv->playlist[1]); if (ret) - priv->base.base.destroy(dev, NVOBJ_ENGINE_FIFO); - return ret; + return ret; + + nv_subdev(priv)->unit = 0x00000100; + nv_subdev(priv)->intr = nv04_fifo_intr; + nv_engine(priv)->cclass = &nv84_fifo_cclass; + nv_engine(priv)->sclass = nv84_fifo_sclass; + return 0; } + +struct nouveau_oclass +nv84_fifo_oclass = { + .handle = NV_ENGINE(FIFO, 0x84), + .ofuncs = &(struct nouveau_ofuncs) { + .ctor = nv84_fifo_ctor, + .dtor = nv50_fifo_dtor, + .init = nv50_fifo_init, + .fini = _nouveau_fifo_fini, + }, +}; diff --git a/drivers/gpu/drm/nouveau/core/engine/fifo/nvc0.c b/drivers/gpu/drm/nouveau/core/engine/fifo/nvc0.c index b99d976011d1..ef403fe66ce0 100644 --- a/drivers/gpu/drm/nouveau/core/engine/fifo/nvc0.c +++ b/drivers/gpu/drm/nouveau/core/engine/fifo/nvc0.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,17 +22,24 @@ * Authors: Ben Skeggs */ -#include "drmP.h" +#include +#include +#include +#include +#include +#include +#include +#include -#include "nouveau_drv.h" -#include -#include -#include "nouveau_software.h" +#include +#include +#include -static void nvc0_fifo_isr(struct drm_device *); +#include +#include struct nvc0_fifo_priv { - struct nouveau_fifo_priv base; + struct nouveau_fifo base; struct nouveau_gpuobj *playlist[2]; int cur_playlist; struct { @@ -42,14 +49,24 @@ struct nvc0_fifo_priv { int spoon_nr; }; +struct nvc0_fifo_base { + struct nouveau_fifo_base base; + struct nouveau_gpuobj *pgd; + struct nouveau_vm *vm; +}; + struct nvc0_fifo_chan { struct nouveau_fifo_chan base; }; +/******************************************************************************* + * FIFO channel objects + ******************************************************************************/ + static void -nvc0_fifo_playlist_update(struct drm_device *dev) +nvc0_fifo_playlist_update(struct nvc0_fifo_priv *priv) { - struct nvc0_fifo_priv *priv = nv_engine(dev, NVOBJ_ENGINE_FIFO); + struct nouveau_bar *bar = nouveau_bar(priv); struct nouveau_gpuobj *cur; int i, p; @@ -57,174 +74,253 @@ nvc0_fifo_playlist_update(struct drm_device *dev) priv->cur_playlist = !priv->cur_playlist; for (i = 0, p = 0; i < 128; i++) { - if (!(nv_rd32(dev, 0x3004 + (i * 8)) & 1)) + if (!(nv_rd32(priv, 0x003004 + (i * 8)) & 1)) continue; nv_wo32(cur, p + 0, i); nv_wo32(cur, p + 4, 0x00000004); p += 8; } - nvimem_flush(dev); + bar->flush(bar); - nv_wr32(dev, 0x002270, cur->addr >> 12); - nv_wr32(dev, 0x002274, 0x01f00000 | (p >> 3)); - if (!nv_wait(dev, 0x00227c, 0x00100000, 0x00000000)) - NV_ERROR(dev, "PFIFO - playlist update failed\n"); + nv_wr32(priv, 0x002270, cur->addr >> 12); + nv_wr32(priv, 0x002274, 0x01f00000 | (p >> 3)); + if (!nv_wait(priv, 0x00227c, 0x00100000, 0x00000000)) + nv_error(priv, "playlist update failed\n"); } static int -nvc0_fifo_context_new(struct nouveau_channel *chan, int engine) +nvc0_fifo_context_attach(struct nouveau_object *parent, + struct nouveau_object *object) { - struct drm_device *dev = chan->dev; - struct nvc0_fifo_priv *priv = nv_engine(dev, engine); - struct nvc0_fifo_chan *fctx; - u64 usermem = priv->user.mem->addr + chan->id * 0x1000; - u64 ib_virt = chan->pushbuf_base + chan->dma.ib_base * 4; - int ret, i; + struct nouveau_bar *bar = nouveau_bar(parent); + struct nvc0_fifo_base *base = (void *)parent->parent; + struct nouveau_engctx *ectx = (void *)object; + u32 addr; + int ret; - fctx = chan->engctx[engine] = kzalloc(sizeof(*fctx), GFP_KERNEL); - if (!fctx) - return -ENOMEM; + switch (nv_engidx(object->engine)) { + case NVDEV_ENGINE_SW : return 0; + case NVDEV_ENGINE_GR : addr = 0x0210; break; + case NVDEV_ENGINE_COPY0: addr = 0x0230; break; + case NVDEV_ENGINE_COPY1: addr = 0x0240; break; + default: + return -EINVAL; + } - chan->user = ioremap_wc(pci_resource_start(dev->pdev, 1) + - priv->user.bar.offset + (chan->id * 0x1000), - PAGE_SIZE); - if (!chan->user) { - ret = -ENOMEM; - goto error; + if (!ectx->vma.node) { + ret = nouveau_gpuobj_map_vm(nv_gpuobj(ectx), base->vm, + NV_MEM_ACCESS_RW, &ectx->vma); + if (ret) + return ret; } - for (i = 0; i < 0x100; i += 4) - nv_wo32(chan->ramin, i, 0x00000000); - nv_wo32(chan->ramin, 0x08, lower_32_bits(usermem)); - nv_wo32(chan->ramin, 0x0c, upper_32_bits(usermem)); - nv_wo32(chan->ramin, 0x10, 0x0000face); - nv_wo32(chan->ramin, 0x30, 0xfffff902); - nv_wo32(chan->ramin, 0x48, lower_32_bits(ib_virt)); - nv_wo32(chan->ramin, 0x4c, drm_order(chan->dma.ib_max + 1) << 16 | - upper_32_bits(ib_virt)); - nv_wo32(chan->ramin, 0x54, 0x00000002); - nv_wo32(chan->ramin, 0x84, 0x20400000); - nv_wo32(chan->ramin, 0x94, 0x30000001); - nv_wo32(chan->ramin, 0x9c, 0x00000100); - nv_wo32(chan->ramin, 0xa4, 0x1f1f1f1f); - nv_wo32(chan->ramin, 0xa8, 0x1f1f1f1f); - nv_wo32(chan->ramin, 0xac, 0x0000001f); - nv_wo32(chan->ramin, 0xb8, 0xf8000000); - nv_wo32(chan->ramin, 0xf8, 0x10003080); /* 0x002310 */ - nv_wo32(chan->ramin, 0xfc, 0x10000010); /* 0x002350 */ - nvimem_flush(dev); - - nv_wr32(dev, 0x003000 + (chan->id * 8), 0xc0000000 | - (chan->ramin->addr >> 12)); - nv_wr32(dev, 0x003004 + (chan->id * 8), 0x001f0001); - nvc0_fifo_playlist_update(dev); - -error: - if (ret) - priv->base.base.context_del(chan, engine); - return ret; + nv_wo32(base, addr + 0x00, lower_32_bits(ectx->vma.offset) | 4); + nv_wo32(base, addr + 0x04, upper_32_bits(ectx->vma.offset)); + bar->flush(bar); + return 0; } -static void -nvc0_fifo_context_del(struct nouveau_channel *chan, int engine) +static int +nvc0_fifo_context_detach(struct nouveau_object *parent, bool suspend, + struct nouveau_object *object) { - struct nvc0_fifo_chan *fctx = chan->engctx[engine]; - struct drm_device *dev = chan->dev; - - nv_mask(dev, 0x003004 + (chan->id * 8), 0x00000001, 0x00000000); - nv_wr32(dev, 0x002634, chan->id); - if (!nv_wait(dev, 0x0002634, 0xffffffff, chan->id)) - NV_WARN(dev, "0x2634 != chid: 0x%08x\n", nv_rd32(dev, 0x2634)); - nvc0_fifo_playlist_update(dev); - nv_wr32(dev, 0x003000 + (chan->id * 8), 0x00000000); - - if (chan->user) { - iounmap(chan->user); - chan->user = NULL; + struct nouveau_bar *bar = nouveau_bar(parent); + struct nvc0_fifo_priv *priv = (void *)parent->engine; + struct nvc0_fifo_base *base = (void *)parent->parent; + struct nvc0_fifo_chan *chan = (void *)parent; + u32 addr; + + switch (nv_engidx(object->engine)) { + case NVDEV_ENGINE_SW : return 0; + case NVDEV_ENGINE_GR : addr = 0x0210; break; + case NVDEV_ENGINE_COPY0: addr = 0x0230; break; + case NVDEV_ENGINE_COPY1: addr = 0x0240; break; + default: + return -EINVAL; } - chan->engctx[engine] = NULL; - kfree(fctx); + nv_wo32(base, addr + 0x00, 0x00000000); + nv_wo32(base, addr + 0x04, 0x00000000); + bar->flush(bar); + + nv_wr32(priv, 0x002634, chan->base.chid); + if (!nv_wait(priv, 0x002634, 0xffffffff, chan->base.chid)) { + nv_error(priv, "channel %d kick timeout\n", chan->base.chid); + if (suspend) + return -EBUSY; + } + + return 0; } static int -nvc0_fifo_init(struct drm_device *dev, int engine) +nvc0_fifo_chan_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 nvc0_fifo_priv *priv = nv_engine(dev, engine); - struct nouveau_channel *chan; - int i; + struct nouveau_bar *bar = nouveau_bar(parent); + struct nvc0_fifo_priv *priv = (void *)engine; + struct nvc0_fifo_base *base = (void *)parent; + struct nvc0_fifo_chan *chan; + struct nv_channel_ind_class *args = data; + u64 usermem, ioffset, ilength; + int ret, i; - /* reset PFIFO, enable all available PSUBFIFO areas */ - nv_mask(dev, 0x000200, 0x00000100, 0x00000000); - nv_mask(dev, 0x000200, 0x00000100, 0x00000100); - nv_wr32(dev, 0x000204, 0xffffffff); - nv_wr32(dev, 0x002204, 0xffffffff); + if (size < sizeof(*args)) + return -EINVAL; + + ret = nouveau_fifo_channel_create(parent, engine, oclass, 1, + priv->user.bar.offset, 0x1000, + args->pushbuf, + (1 << NVDEV_ENGINE_SW) | + (1 << NVDEV_ENGINE_GR) | + (1 << NVDEV_ENGINE_COPY0) | + (1 << NVDEV_ENGINE_COPY1), &chan); + *pobject = nv_object(chan); + if (ret) + return ret; + + nv_parent(chan)->context_attach = nvc0_fifo_context_attach; + nv_parent(chan)->context_detach = nvc0_fifo_context_detach; + + usermem = chan->base.chid * 0x1000; + ioffset = args->ioffset; + ilength = log2i(args->ilength / 8); + + for (i = 0; i < 0x1000; i += 4) + nv_wo32(priv->user.mem, usermem + i, 0x00000000); + + nv_wo32(base, 0x08, lower_32_bits(priv->user.mem->addr + usermem)); + nv_wo32(base, 0x0c, upper_32_bits(priv->user.mem->addr + usermem)); + nv_wo32(base, 0x10, 0x0000face); + nv_wo32(base, 0x30, 0xfffff902); + nv_wo32(base, 0x48, lower_32_bits(ioffset)); + nv_wo32(base, 0x4c, upper_32_bits(ioffset) | (ilength << 16)); + nv_wo32(base, 0x54, 0x00000002); + nv_wo32(base, 0x84, 0x20400000); + nv_wo32(base, 0x94, 0x30000001); + nv_wo32(base, 0x9c, 0x00000100); + nv_wo32(base, 0xa4, 0x1f1f1f1f); + nv_wo32(base, 0xa8, 0x1f1f1f1f); + nv_wo32(base, 0xac, 0x0000001f); + nv_wo32(base, 0xb8, 0xf8000000); + nv_wo32(base, 0xf8, 0x10003080); /* 0x002310 */ + nv_wo32(base, 0xfc, 0x10000010); /* 0x002350 */ + bar->flush(bar); + return 0; +} - priv->spoon_nr = hweight32(nv_rd32(dev, 0x002204)); - NV_DEBUG(dev, "PFIFO: %d subfifo(s)\n", priv->spoon_nr); +static int +nvc0_fifo_chan_init(struct nouveau_object *object) +{ + struct nouveau_gpuobj *base = nv_gpuobj(object->parent); + struct nvc0_fifo_priv *priv = (void *)object->engine; + struct nvc0_fifo_chan *chan = (void *)object; + u32 chid = chan->base.chid; + int ret; - /* assign engines to subfifos */ - if (priv->spoon_nr >= 3) { - nv_wr32(dev, 0x002208, ~(1 << 0)); /* PGRAPH */ - nv_wr32(dev, 0x00220c, ~(1 << 1)); /* PVP */ - nv_wr32(dev, 0x002210, ~(1 << 1)); /* PPP */ - nv_wr32(dev, 0x002214, ~(1 << 1)); /* PBSP */ - nv_wr32(dev, 0x002218, ~(1 << 2)); /* PCE0 */ - nv_wr32(dev, 0x00221c, ~(1 << 1)); /* PCE1 */ - } + ret = nouveau_fifo_channel_init(&chan->base); + if (ret) + return ret; - /* PSUBFIFO[n] */ - for (i = 0; i < priv->spoon_nr; i++) { - nv_mask(dev, 0x04013c + (i * 0x2000), 0x10000100, 0x00000000); - nv_wr32(dev, 0x040108 + (i * 0x2000), 0xffffffff); /* INTR */ - nv_wr32(dev, 0x04010c + (i * 0x2000), 0xfffffeff); /* INTR_EN */ - } + nv_wr32(priv, 0x003000 + (chid * 8), 0xc0000000 | base->addr >> 12); + nv_wr32(priv, 0x003004 + (chid * 8), 0x001f0001); + nvc0_fifo_playlist_update(priv); + return 0; +} - nv_mask(dev, 0x002200, 0x00000001, 0x00000001); - nv_wr32(dev, 0x002254, 0x10000000 | priv->user.bar.offset >> 12); +static int +nvc0_fifo_chan_fini(struct nouveau_object *object, bool suspend) +{ + struct nvc0_fifo_priv *priv = (void *)object->engine; + struct nvc0_fifo_chan *chan = (void *)object; + u32 chid = chan->base.chid; - nv_wr32(dev, 0x002a00, 0xffffffff); /* clears PFIFO.INTR bit 30 */ - nv_wr32(dev, 0x002100, 0xffffffff); - nv_wr32(dev, 0x002140, 0xbfffffff); + nv_mask(priv, 0x003004 + (chid * 8), 0x00000001, 0x00000000); + nvc0_fifo_playlist_update(priv); + nv_wr32(priv, 0x003000 + (chid * 8), 0x00000000); - /* restore PFIFO context table */ - for (i = 0; i < 128; i++) { - chan = dev_priv->channels.ptr[i]; - if (!chan || !chan->engctx[engine]) - continue; + return nouveau_fifo_channel_fini(&chan->base, suspend); +} - nv_wr32(dev, 0x003000 + (i * 8), 0xc0000000 | - (chan->ramin->addr >> 12)); - nv_wr32(dev, 0x003004 + (i * 8), 0x001f0001); - } - nvc0_fifo_playlist_update(dev); +static struct nouveau_ofuncs +nvc0_fifo_ofuncs = { + .ctor = nvc0_fifo_chan_ctor, + .dtor = _nouveau_fifo_channel_dtor, + .init = nvc0_fifo_chan_init, + .fini = nvc0_fifo_chan_fini, + .rd32 = _nouveau_fifo_channel_rd32, + .wr32 = _nouveau_fifo_channel_wr32, +}; - return 0; -} +static struct nouveau_oclass +nvc0_fifo_sclass[] = { + { 0x906f, &nvc0_fifo_ofuncs }, + {} +}; + +/******************************************************************************* + * FIFO context - instmem heap and vm setup + ******************************************************************************/ static int -nvc0_fifo_fini(struct drm_device *dev, int engine, bool suspend) +nvc0_fifo_context_ctor(struct nouveau_object *parent, + struct nouveau_object *engine, + struct nouveau_oclass *oclass, void *data, u32 size, + struct nouveau_object **pobject) { - int i; + struct nvc0_fifo_base *base; + int ret; - for (i = 0; i < 128; i++) { - if (!(nv_rd32(dev, 0x003004 + (i * 8)) & 1)) - continue; + ret = nouveau_fifo_context_create(parent, engine, oclass, NULL, 0x1000, + 0x1000, NVOBJ_FLAG_ZERO_ALLOC | + NVOBJ_FLAG_HEAP, &base); + *pobject = nv_object(base); + if (ret) + return ret; - nv_mask(dev, 0x003004 + (i * 8), 0x00000001, 0x00000000); - nv_wr32(dev, 0x002634, i); - if (!nv_wait(dev, 0x002634, 0xffffffff, i)) { - NV_INFO(dev, "PFIFO: kick ch %d failed: 0x%08x\n", - i, nv_rd32(dev, 0x002634)); - return -EBUSY; - } - } + ret = nouveau_gpuobj_new(parent, NULL, 0x10000, 0x1000, 0, &base->pgd); + if (ret) + return ret; + + nv_wo32(base, 0x0200, lower_32_bits(base->pgd->addr)); + nv_wo32(base, 0x0204, upper_32_bits(base->pgd->addr)); + nv_wo32(base, 0x0208, 0xffffffff); + nv_wo32(base, 0x020c, 0x000000ff); + + ret = nouveau_vm_ref(nouveau_client(parent)->vm, &base->vm, base->pgd); + if (ret) + return ret; - nv_wr32(dev, 0x002140, 0x00000000); return 0; } +static void +nvc0_fifo_context_dtor(struct nouveau_object *object) +{ + struct nvc0_fifo_base *base = (void *)object; + nouveau_vm_ref(NULL, &base->vm, base->pgd); + nouveau_gpuobj_ref(NULL, &base->pgd); + nouveau_fifo_context_destroy(&base->base); +} + +static struct nouveau_oclass +nvc0_fifo_cclass = { + .handle = NV_ENGCTX(FIFO, 0xc0), + .ofuncs = &(struct nouveau_ofuncs) { + .ctor = nvc0_fifo_context_ctor, + .dtor = nvc0_fifo_context_dtor, + .init = _nouveau_fifo_context_init, + .fini = _nouveau_fifo_context_fini, + .rd32 = _nouveau_fifo_context_rd32, + .wr32 = _nouveau_fifo_context_wr32, + }, +}; + +/******************************************************************************* + * PFIFO engine + ******************************************************************************/ struct nouveau_enum nvc0_fifo_fault_unit[] = { { 0x00, "PGRAPH" }, @@ -289,16 +385,16 @@ struct nouveau_bitfield nvc0_fifo_subfifo_intr[] = { }; static void -nvc0_fifo_isr_vm_fault(struct drm_device *dev, int unit) +nvc0_fifo_isr_vm_fault(struct nvc0_fifo_priv *priv, int unit) { - u32 inst = nv_rd32(dev, 0x2800 + (unit * 0x10)); - u32 valo = nv_rd32(dev, 0x2804 + (unit * 0x10)); - u32 vahi = nv_rd32(dev, 0x2808 + (unit * 0x10)); - u32 stat = nv_rd32(dev, 0x280c + (unit * 0x10)); + u32 inst = nv_rd32(priv, 0x2800 + (unit * 0x10)); + u32 valo = nv_rd32(priv, 0x2804 + (unit * 0x10)); + u32 vahi = nv_rd32(priv, 0x2808 + (unit * 0x10)); + u32 stat = nv_rd32(priv, 0x280c + (unit * 0x10)); u32 client = (stat & 0x00001f00) >> 8; - NV_INFO(dev, "PFIFO: %s fault at 0x%010llx [", - (stat & 0x00000080) ? "write" : "read", (u64)vahi << 32 | valo); + nv_error(priv, "%s fault at 0x%010llx [", (stat & 0x00000080) ? + "write" : "read", (u64)vahi << 32 | valo); nouveau_enum_print(nvc0_fifo_fault_reason, stat & 0x0000000f); printk("] from "); nouveau_enum_print(nvc0_fifo_fault_unit, unit); @@ -313,165 +409,223 @@ nvc0_fifo_isr_vm_fault(struct drm_device *dev, int unit) } static int -nvc0_fifo_page_flip(struct drm_device *dev, u32 chid) +nvc0_fifo_swmthd(struct nvc0_fifo_priv *priv, u32 chid, u32 mthd, u32 data) { - struct nvc0_fifo_priv *priv = nv_engine(dev, NVOBJ_ENGINE_FIFO); - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_channel *chan = NULL; + struct nvc0_fifo_chan *chan = NULL; + struct nouveau_handle *bind; unsigned long flags; int ret = -EINVAL; - spin_lock_irqsave(&dev_priv->channels.lock, flags); - if (likely(chid >= 0 && chid < priv->base.channels)) { - chan = dev_priv->channels.ptr[chid]; - if (likely(chan)) { - struct nouveau_software_chan *swch = - chan->engctx[NVOBJ_ENGINE_SW]; - ret = swch->flip(swch->flip_data); - } + spin_lock_irqsave(&priv->base.lock, flags); + if (likely(chid >= priv->base.min && chid <= priv->base.max)) + chan = (void *)priv->base.channel[chid]; + if (unlikely(!chan)) + goto out; + + bind = nouveau_namedb_get_class(nv_namedb(chan), 0x906e); + if (likely(bind)) { + if (!mthd || !nv_call(bind->object, mthd, data)) + ret = 0; + nouveau_namedb_put(bind); } - spin_unlock_irqrestore(&dev_priv->channels.lock, flags); + +out: + spin_unlock_irqrestore(&priv->base.lock, flags); return ret; } static void -nvc0_fifo_isr_subfifo_intr(struct drm_device *dev, int unit) +nvc0_fifo_isr_subfifo_intr(struct nvc0_fifo_priv *priv, int unit) { - u32 stat = nv_rd32(dev, 0x040108 + (unit * 0x2000)); - u32 addr = nv_rd32(dev, 0x0400c0 + (unit * 0x2000)); - u32 data = nv_rd32(dev, 0x0400c4 + (unit * 0x2000)); - u32 chid = nv_rd32(dev, 0x040120 + (unit * 0x2000)) & 0x7f; - u32 subc = (addr & 0x00070000); + u32 stat = nv_rd32(priv, 0x040108 + (unit * 0x2000)); + u32 addr = nv_rd32(priv, 0x0400c0 + (unit * 0x2000)); + u32 data = nv_rd32(priv, 0x0400c4 + (unit * 0x2000)); + u32 chid = nv_rd32(priv, 0x040120 + (unit * 0x2000)) & 0x7f; + u32 subc = (addr & 0x00070000) >> 16; u32 mthd = (addr & 0x00003ffc); u32 show = stat; if (stat & 0x00200000) { if (mthd == 0x0054) { - if (!nvc0_fifo_page_flip(dev, chid)) + if (!nvc0_fifo_swmthd(priv, chid, 0x0500, 0x00000000)) show &= ~0x00200000; } } + if (stat & 0x00800000) { + if (!nvc0_fifo_swmthd(priv, chid, mthd, data)) + show &= ~0x00800000; + } + if (show) { - NV_INFO(dev, "PFIFO%d:", unit); + nv_error(priv, "SUBFIFO%d:", unit); nouveau_bitfield_print(nvc0_fifo_subfifo_intr, show); - NV_INFO(dev, "PFIFO%d: ch %d subc %d mthd 0x%04x data 0x%08x\n", - unit, chid, subc, mthd, data); + printk("\n"); + nv_error(priv, "SUBFIFO%d: ch %d subc %d mthd 0x%04x " + "data 0x%08x\n", + unit, chid, subc, mthd, data); } - nv_wr32(dev, 0x0400c0 + (unit * 0x2000), 0x80600008); - nv_wr32(dev, 0x040108 + (unit * 0x2000), stat); + nv_wr32(priv, 0x0400c0 + (unit * 0x2000), 0x80600008); + nv_wr32(priv, 0x040108 + (unit * 0x2000), stat); } static void -nvc0_fifo_isr(struct drm_device *dev) +nvc0_fifo_intr(struct nouveau_subdev *subdev) { - u32 mask = nv_rd32(dev, 0x002140); - u32 stat = nv_rd32(dev, 0x002100) & mask; + struct nvc0_fifo_priv *priv = (void *)subdev; + u32 mask = nv_rd32(priv, 0x002140); + u32 stat = nv_rd32(priv, 0x002100) & mask; if (stat & 0x00000100) { - NV_INFO(dev, "PFIFO: unknown status 0x00000100\n"); - nv_wr32(dev, 0x002100, 0x00000100); + nv_info(priv, "unknown status 0x00000100\n"); + nv_wr32(priv, 0x002100, 0x00000100); stat &= ~0x00000100; } if (stat & 0x10000000) { - u32 units = nv_rd32(dev, 0x00259c); + u32 units = nv_rd32(priv, 0x00259c); u32 u = units; while (u) { int i = ffs(u) - 1; - nvc0_fifo_isr_vm_fault(dev, i); + nvc0_fifo_isr_vm_fault(priv, i); u &= ~(1 << i); } - nv_wr32(dev, 0x00259c, units); + nv_wr32(priv, 0x00259c, units); stat &= ~0x10000000; } if (stat & 0x20000000) { - u32 units = nv_rd32(dev, 0x0025a0); + u32 units = nv_rd32(priv, 0x0025a0); u32 u = units; while (u) { int i = ffs(u) - 1; - nvc0_fifo_isr_subfifo_intr(dev, i); + nvc0_fifo_isr_subfifo_intr(priv, i); u &= ~(1 << i); } - nv_wr32(dev, 0x0025a0, units); + nv_wr32(priv, 0x0025a0, units); stat &= ~0x20000000; } if (stat & 0x40000000) { - NV_INFO(dev, "PFIFO: unknown status 0x40000000\n"); - nv_mask(dev, 0x002a00, 0x00000000, 0x00000000); + nv_warn(priv, "unknown status 0x40000000\n"); + nv_mask(priv, 0x002a00, 0x00000000, 0x00000000); stat &= ~0x40000000; } if (stat) { - NV_INFO(dev, "PFIFO: unhandled status 0x%08x\n", stat); - nv_wr32(dev, 0x002100, stat); - nv_wr32(dev, 0x002140, 0); + nv_fatal(priv, "unhandled status 0x%08x\n", stat); + nv_wr32(priv, 0x002100, stat); + nv_wr32(priv, 0x002140, 0); } } +static int +nvc0_fifo_ctor(struct nouveau_object *parent, struct nouveau_object *engine, + struct nouveau_oclass *oclass, void *data, u32 size, + struct nouveau_object **pobject) +{ + struct nvc0_fifo_priv *priv; + int ret; + + ret = nouveau_fifo_create(parent, engine, oclass, 0, 127, &priv); + *pobject = nv_object(priv); + if (ret) + return ret; + + ret = nouveau_gpuobj_new(parent, NULL, 0x1000, 0x1000, 0, + &priv->playlist[0]); + if (ret) + return ret; + + ret = nouveau_gpuobj_new(parent, NULL, 0x1000, 0x1000, 0, + &priv->playlist[1]); + if (ret) + return ret; + + ret = nouveau_gpuobj_new(parent, NULL, 128 * 0x1000, 0x1000, 0, + &priv->user.mem); + if (ret) + return ret; + + ret = nouveau_gpuobj_map(priv->user.mem, NV_MEM_ACCESS_RW, + &priv->user.bar); + if (ret) + return ret; + + nv_subdev(priv)->unit = 0x00000100; + nv_subdev(priv)->intr = nvc0_fifo_intr; + nv_engine(priv)->cclass = &nvc0_fifo_cclass; + nv_engine(priv)->sclass = nvc0_fifo_sclass; + return 0; +} + static void -nvc0_fifo_destroy(struct drm_device *dev, int engine) +nvc0_fifo_dtor(struct nouveau_object *object) { - struct nvc0_fifo_priv *priv = nv_engine(dev, NVOBJ_ENGINE_FIFO); - struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nvc0_fifo_priv *priv = (void *)object; nouveau_gpuobj_unmap(&priv->user.bar); nouveau_gpuobj_ref(NULL, &priv->user.mem); - nouveau_gpuobj_ref(NULL, &priv->playlist[1]); nouveau_gpuobj_ref(NULL, &priv->playlist[0]); - dev_priv->eng[engine] = NULL; - kfree(priv); + nouveau_fifo_destroy(&priv->base); } -int -nvc0_fifo_create(struct drm_device *dev) +static int +nvc0_fifo_init(struct nouveau_object *object) { - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nvc0_fifo_priv *priv; - int ret; + struct nvc0_fifo_priv *priv = (void *)object; + int ret, i; - priv = kzalloc(sizeof(*priv), GFP_KERNEL); - if (!priv) - return -ENOMEM; + ret = nouveau_fifo_init(&priv->base); + if (ret) + return ret; - priv->base.base.destroy = nvc0_fifo_destroy; - priv->base.base.init = nvc0_fifo_init; - priv->base.base.fini = nvc0_fifo_fini; - priv->base.base.context_new = nvc0_fifo_context_new; - priv->base.base.context_del = nvc0_fifo_context_del; - priv->base.channels = 128; - dev_priv->eng[NVOBJ_ENGINE_FIFO] = &priv->base.base; + nv_wr32(priv, 0x000204, 0xffffffff); + nv_wr32(priv, 0x002204, 0xffffffff); - ret = nouveau_gpuobj_new(dev, NULL, 4096, 4096, 0, &priv->playlist[0]); - if (ret) - goto error; + priv->spoon_nr = hweight32(nv_rd32(priv, 0x002204)); + nv_debug(priv, "%d subfifo(s)\n", priv->spoon_nr); - ret = nouveau_gpuobj_new(dev, NULL, 4096, 4096, 0, &priv->playlist[1]); - if (ret) - goto error; + /* assign engines to subfifos */ + if (priv->spoon_nr >= 3) { + nv_wr32(priv, 0x002208, ~(1 << 0)); /* PGRAPH */ + nv_wr32(priv, 0x00220c, ~(1 << 1)); /* PVP */ + nv_wr32(priv, 0x002210, ~(1 << 1)); /* PPP */ + nv_wr32(priv, 0x002214, ~(1 << 1)); /* PBSP */ + nv_wr32(priv, 0x002218, ~(1 << 2)); /* PCE0 */ + nv_wr32(priv, 0x00221c, ~(1 << 1)); /* PCE1 */ + } - ret = nouveau_gpuobj_new(dev, NULL, priv->base.channels * 4096, 0x1000, - NVOBJ_FLAG_ZERO_ALLOC, &priv->user.mem); - if (ret) - goto error; + /* PSUBFIFO[n] */ + for (i = 0; i < priv->spoon_nr; i++) { + nv_mask(priv, 0x04013c + (i * 0x2000), 0x10000100, 0x00000000); + nv_wr32(priv, 0x040108 + (i * 0x2000), 0xffffffff); /* INTR */ + nv_wr32(priv, 0x04010c + (i * 0x2000), 0xfffffeff); /* INTREN */ + } - ret = nouveau_gpuobj_map_bar(priv->user.mem, NV_MEM_ACCESS_RW, - &priv->user.bar); - if (ret) - goto error; + nv_mask(priv, 0x002200, 0x00000001, 0x00000001); + nv_wr32(priv, 0x002254, 0x10000000 | priv->user.bar.offset >> 12); - nouveau_irq_register(dev, 8, nvc0_fifo_isr); -error: - if (ret) - priv->base.base.destroy(dev, NVOBJ_ENGINE_FIFO); - return ret; + nv_wr32(priv, 0x002a00, 0xffffffff); /* clears PFIFO.INTR bit 30 */ + nv_wr32(priv, 0x002100, 0xffffffff); + nv_wr32(priv, 0x002140, 0xbfffffff); + return 0; } + +struct nouveau_oclass +nvc0_fifo_oclass = { + .handle = NV_ENGINE(FIFO, 0xc0), + .ofuncs = &(struct nouveau_ofuncs) { + .ctor = nvc0_fifo_ctor, + .dtor = nvc0_fifo_dtor, + .init = nvc0_fifo_init, + .fini = _nouveau_fifo_fini, + }, +}; diff --git a/drivers/gpu/drm/nouveau/core/engine/fifo/nve0.c b/drivers/gpu/drm/nouveau/core/engine/fifo/nve0.c index 0b356f1b6864..aaff086dfd2a 100644 --- a/drivers/gpu/drm/nouveau/core/engine/fifo/nve0.c +++ b/drivers/gpu/drm/nouveau/core/engine/fifo/nve0.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,25 +22,30 @@ * Authors: Ben Skeggs */ -#include "drmP.h" +#include +#include +#include +#include +#include +#include +#include +#include -#include "nouveau_drv.h" -#include -#include -#include "nouveau_software.h" - -#define NVE0_FIFO_ENGINE_NUM 32 +#include +#include +#include -static void nve0_fifo_isr(struct drm_device *); +#include +#include -struct nve0_fifo_engine { +struct nve0_fifo_engn { struct nouveau_gpuobj *playlist[2]; int cur_playlist; }; struct nve0_fifo_priv { - struct nouveau_fifo_priv base; - struct nve0_fifo_engine engine[NVE0_FIFO_ENGINE_NUM]; + struct nouveau_fifo base; + struct nve0_fifo_engn engine[16]; struct { struct nouveau_gpuobj *mem; struct nouveau_vma bar; @@ -48,194 +53,286 @@ struct nve0_fifo_priv { int spoon_nr; }; +struct nve0_fifo_base { + struct nouveau_fifo_base base; + struct nouveau_gpuobj *pgd; + struct nouveau_vm *vm; +}; + struct nve0_fifo_chan { struct nouveau_fifo_chan base; u32 engine; }; +/******************************************************************************* + * FIFO channel objects + ******************************************************************************/ + static void -nve0_fifo_playlist_update(struct drm_device *dev, u32 engine) +nve0_fifo_playlist_update(struct nve0_fifo_priv *priv, u32 engine) { - struct nve0_fifo_priv *priv = nv_engine(dev, NVOBJ_ENGINE_FIFO); - struct nve0_fifo_engine *peng = &priv->engine[engine]; + struct nouveau_bar *bar = nouveau_bar(priv); + struct nve0_fifo_engn *engn = &priv->engine[engine]; struct nouveau_gpuobj *cur; u32 match = (engine << 16) | 0x00000001; - int ret, i, p; + int i, p; - cur = peng->playlist[peng->cur_playlist]; + cur = engn->playlist[engn->cur_playlist]; if (unlikely(cur == NULL)) { - ret = nouveau_gpuobj_new(dev, NULL, 0x8000, 0x1000, 0, &cur); + int ret = nouveau_gpuobj_new(nv_object(priv)->parent, NULL, + 0x8000, 0x1000, 0, &cur); if (ret) { - NV_ERROR(dev, "PFIFO: playlist alloc failed\n"); + nv_error(priv, "playlist alloc failed\n"); return; } - peng->playlist[peng->cur_playlist] = cur; + engn->playlist[engn->cur_playlist] = cur; } - peng->cur_playlist = !peng->cur_playlist; + engn->cur_playlist = !engn->cur_playlist; - for (i = 0, p = 0; i < priv->base.channels; i++) { - u32 ctrl = nv_rd32(dev, 0x800004 + (i * 8)) & 0x001f0001; + for (i = 0, p = 0; i < priv->base.max; i++) { + u32 ctrl = nv_rd32(priv, 0x800004 + (i * 8)) & 0x001f0001; if (ctrl != match) continue; nv_wo32(cur, p + 0, i); nv_wo32(cur, p + 4, 0x00000000); p += 8; } - nvimem_flush(dev); + bar->flush(bar); - nv_wr32(dev, 0x002270, cur->addr >> 12); - nv_wr32(dev, 0x002274, (engine << 20) | (p >> 3)); - if (!nv_wait(dev, 0x002284 + (engine * 4), 0x00100000, 0x00000000)) - NV_ERROR(dev, "PFIFO: playlist %d update timeout\n", engine); + nv_wr32(priv, 0x002270, cur->addr >> 12); + nv_wr32(priv, 0x002274, (engine << 20) | (p >> 3)); + if (!nv_wait(priv, 0x002284 + (engine * 4), 0x00100000, 0x00000000)) + nv_error(priv, "playlist %d update timeout\n", engine); } static int -nve0_fifo_context_new(struct nouveau_channel *chan, int engine) +nve0_fifo_context_attach(struct nouveau_object *parent, + struct nouveau_object *object) { - struct drm_device *dev = chan->dev; - struct nve0_fifo_priv *priv = nv_engine(dev, engine); - struct nve0_fifo_chan *fctx; - u64 usermem = priv->user.mem->addr + chan->id * 512; - u64 ib_virt = chan->pushbuf_base + chan->dma.ib_base * 4; - int ret = 0, i; - - fctx = chan->engctx[engine] = kzalloc(sizeof(*fctx), GFP_KERNEL); - if (!fctx) - return -ENOMEM; - - fctx->engine = 0; /* PGRAPH */ - - /* allocate vram for control regs, map into polling area */ - chan->user = ioremap_wc(pci_resource_start(dev->pdev, 1) + - priv->user.bar.offset + (chan->id * 512), 512); - if (!chan->user) { - ret = -ENOMEM; - goto error; + struct nouveau_bar *bar = nouveau_bar(parent); + struct nve0_fifo_base *base = (void *)parent->parent; + struct nouveau_engctx *ectx = (void *)object; + u32 addr; + int ret; + + switch (nv_engidx(object->engine)) { + case NVDEV_ENGINE_SW : return 0; + case NVDEV_ENGINE_GR : addr = 0x0210; break; + default: + return -EINVAL; } - for (i = 0; i < 0x100; i += 4) - nv_wo32(chan->ramin, i, 0x00000000); - nv_wo32(chan->ramin, 0x08, lower_32_bits(usermem)); - nv_wo32(chan->ramin, 0x0c, upper_32_bits(usermem)); - nv_wo32(chan->ramin, 0x10, 0x0000face); - nv_wo32(chan->ramin, 0x30, 0xfffff902); - nv_wo32(chan->ramin, 0x48, lower_32_bits(ib_virt)); - nv_wo32(chan->ramin, 0x4c, drm_order(chan->dma.ib_max + 1) << 16 | - upper_32_bits(ib_virt)); - nv_wo32(chan->ramin, 0x84, 0x20400000); - nv_wo32(chan->ramin, 0x94, 0x30000001); - nv_wo32(chan->ramin, 0x9c, 0x00000100); - nv_wo32(chan->ramin, 0xac, 0x0000001f); - nv_wo32(chan->ramin, 0xe4, 0x00000000); - nv_wo32(chan->ramin, 0xe8, chan->id); - nv_wo32(chan->ramin, 0xf8, 0x10003080); /* 0x002310 */ - nv_wo32(chan->ramin, 0xfc, 0x10000010); /* 0x002350 */ - nvimem_flush(dev); - - nv_wr32(dev, 0x800000 + (chan->id * 8), 0x80000000 | - (chan->ramin->addr >> 12)); - nv_mask(dev, 0x800004 + (chan->id * 8), 0x00000400, 0x00000400); - nve0_fifo_playlist_update(dev, fctx->engine); - nv_mask(dev, 0x800004 + (chan->id * 8), 0x00000400, 0x00000400); - -error: - if (ret) - priv->base.base.context_del(chan, engine); - return ret; + if (!ectx->vma.node) { + ret = nouveau_gpuobj_map_vm(nv_gpuobj(ectx), base->vm, + NV_MEM_ACCESS_RW, &ectx->vma); + if (ret) + return ret; + } + + nv_wo32(base, addr + 0x00, lower_32_bits(ectx->vma.offset) | 4); + nv_wo32(base, addr + 0x04, upper_32_bits(ectx->vma.offset)); + bar->flush(bar); + return 0; } -static void -nve0_fifo_context_del(struct nouveau_channel *chan, int engine) +static int +nve0_fifo_context_detach(struct nouveau_object *parent, bool suspend, + struct nouveau_object *object) { - struct nve0_fifo_chan *fctx = chan->engctx[engine]; - struct drm_device *dev = chan->dev; - - nv_mask(dev, 0x800004 + (chan->id * 8), 0x00000800, 0x00000800); - nv_wr32(dev, 0x002634, chan->id); - if (!nv_wait(dev, 0x0002634, 0xffffffff, chan->id)) - NV_WARN(dev, "0x2634 != chid: 0x%08x\n", nv_rd32(dev, 0x2634)); - nve0_fifo_playlist_update(dev, fctx->engine); - nv_wr32(dev, 0x800000 + (chan->id * 8), 0x00000000); - - if (chan->user) { - iounmap(chan->user); - chan->user = NULL; + struct nouveau_bar *bar = nouveau_bar(parent); + struct nve0_fifo_priv *priv = (void *)parent->engine; + struct nve0_fifo_base *base = (void *)parent->parent; + struct nve0_fifo_chan *chan = (void *)parent; + u32 addr; + + switch (nv_engidx(object->engine)) { + case NVDEV_ENGINE_SW : return 0; + case NVDEV_ENGINE_GR : addr = 0x0210; break; + default: + return -EINVAL; + } + + nv_wo32(base, addr + 0x00, 0x00000000); + nv_wo32(base, addr + 0x04, 0x00000000); + bar->flush(bar); + + nv_wr32(priv, 0x002634, chan->base.chid); + if (!nv_wait(priv, 0x002634, 0xffffffff, chan->base.chid)) { + nv_error(priv, "channel %d kick timeout\n", chan->base.chid); + if (suspend) + return -EBUSY; } - chan->engctx[NVOBJ_ENGINE_FIFO] = NULL; - kfree(fctx); + return 0; } static int -nve0_fifo_init(struct drm_device *dev, int engine) +nve0_fifo_chan_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 nve0_fifo_priv *priv = nv_engine(dev, engine); - struct nve0_fifo_chan *fctx; - int i; + struct nouveau_bar *bar = nouveau_bar(parent); + struct nve0_fifo_priv *priv = (void *)engine; + struct nve0_fifo_base *base = (void *)parent; + struct nve0_fifo_chan *chan; + struct nv_channel_ind_class *args = data; + u64 usermem, ioffset, ilength; + int ret, i; + + if (size < sizeof(*args)) + return -EINVAL; + + ret = nouveau_fifo_channel_create(parent, engine, oclass, 1, + priv->user.bar.offset, 0x200, + args->pushbuf, + (1 << NVDEV_ENGINE_SW) | + (1 << NVDEV_ENGINE_GR), &chan); + *pobject = nv_object(chan); + if (ret) + return ret; + + nv_parent(chan)->context_attach = nve0_fifo_context_attach; + nv_parent(chan)->context_detach = nve0_fifo_context_detach; + + usermem = chan->base.chid * 0x200; + ioffset = args->ioffset; + ilength = log2i(args->ilength / 8); + + for (i = 0; i < 0x200; i += 4) + nv_wo32(priv->user.mem, usermem + i, 0x00000000); + + nv_wo32(base, 0x08, lower_32_bits(priv->user.mem->addr + usermem)); + nv_wo32(base, 0x0c, upper_32_bits(priv->user.mem->addr + usermem)); + nv_wo32(base, 0x10, 0x0000face); + nv_wo32(base, 0x30, 0xfffff902); + nv_wo32(base, 0x48, lower_32_bits(ioffset)); + nv_wo32(base, 0x4c, upper_32_bits(ioffset) | (ilength << 16)); + nv_wo32(base, 0x84, 0x20400000); + nv_wo32(base, 0x94, 0x30000001); + nv_wo32(base, 0x9c, 0x00000100); + nv_wo32(base, 0xac, 0x0000001f); + nv_wo32(base, 0xe8, chan->base.chid); + nv_wo32(base, 0xb8, 0xf8000000); + nv_wo32(base, 0xf8, 0x10003080); /* 0x002310 */ + nv_wo32(base, 0xfc, 0x10000010); /* 0x002350 */ + bar->flush(bar); + return 0; +} - /* reset PFIFO, enable all available PSUBFIFO areas */ - nv_mask(dev, 0x000200, 0x00000100, 0x00000000); - nv_mask(dev, 0x000200, 0x00000100, 0x00000100); - nv_wr32(dev, 0x000204, 0xffffffff); +static int +nve0_fifo_chan_init(struct nouveau_object *object) +{ + struct nouveau_gpuobj *base = nv_gpuobj(object->parent); + struct nve0_fifo_priv *priv = (void *)object->engine; + struct nve0_fifo_chan *chan = (void *)object; + u32 chid = chan->base.chid; + int ret; - priv->spoon_nr = hweight32(nv_rd32(dev, 0x000204)); - NV_DEBUG(dev, "PFIFO: %d subfifo(s)\n", priv->spoon_nr); + ret = nouveau_fifo_channel_init(&chan->base); + if (ret) + return ret; - /* PSUBFIFO[n] */ - for (i = 0; i < priv->spoon_nr; i++) { - nv_mask(dev, 0x04013c + (i * 0x2000), 0x10000100, 0x00000000); - nv_wr32(dev, 0x040108 + (i * 0x2000), 0xffffffff); /* INTR */ - nv_wr32(dev, 0x04010c + (i * 0x2000), 0xfffffeff); /* INTR_EN */ - } + nv_wr32(priv, 0x800000 + (chid * 8), 0x80000000 | base->addr >> 12); + nv_mask(priv, 0x800004 + (chid * 8), 0x00000400, 0x00000400); + nve0_fifo_playlist_update(priv, chan->engine); + nv_mask(priv, 0x800004 + (chid * 8), 0x00000400, 0x00000400); + return 0; +} - nv_wr32(dev, 0x002254, 0x10000000 | priv->user.bar.offset >> 12); +static int +nve0_fifo_chan_fini(struct nouveau_object *object, bool suspend) +{ + struct nve0_fifo_priv *priv = (void *)object->engine; + struct nve0_fifo_chan *chan = (void *)object; + u32 chid = chan->base.chid; - nv_wr32(dev, 0x002a00, 0xffffffff); - nv_wr32(dev, 0x002100, 0xffffffff); - nv_wr32(dev, 0x002140, 0xbfffffff); + nv_mask(priv, 0x800004 + (chid * 8), 0x00000800, 0x00000800); + nve0_fifo_playlist_update(priv, chan->engine); + nv_wr32(priv, 0x800000 + (chid * 8), 0x00000000); - /* restore PFIFO context table */ - for (i = 0; i < priv->base.channels; i++) { - struct nouveau_channel *chan = dev_priv->channels.ptr[i]; - if (!chan || !(fctx = chan->engctx[engine])) - continue; + return nouveau_fifo_channel_fini(&chan->base, suspend); +} - nv_wr32(dev, 0x800000 + (i * 8), 0x80000000 | - (chan->ramin->addr >> 12)); - nv_mask(dev, 0x800004 + (i * 8), 0x00000400, 0x00000400); - nve0_fifo_playlist_update(dev, fctx->engine); - nv_mask(dev, 0x800004 + (i * 8), 0x00000400, 0x00000400); - } +static struct nouveau_ofuncs +nve0_fifo_ofuncs = { + .ctor = nve0_fifo_chan_ctor, + .dtor = _nouveau_fifo_channel_dtor, + .init = nve0_fifo_chan_init, + .fini = nve0_fifo_chan_fini, + .rd32 = _nouveau_fifo_channel_rd32, + .wr32 = _nouveau_fifo_channel_wr32, +}; - return 0; -} +static struct nouveau_oclass +nve0_fifo_sclass[] = { + { 0xa06f, &nve0_fifo_ofuncs }, + {} +}; + +/******************************************************************************* + * FIFO context - instmem heap and vm setup + ******************************************************************************/ static int -nve0_fifo_fini(struct drm_device *dev, int engine, bool suspend) +nve0_fifo_context_ctor(struct nouveau_object *parent, + struct nouveau_object *engine, + struct nouveau_oclass *oclass, void *data, u32 size, + struct nouveau_object **pobject) { - struct nve0_fifo_priv *priv = nv_engine(dev, engine); - int i; + struct nve0_fifo_base *base; + int ret; - for (i = 0; i < priv->base.channels; i++) { - if (!(nv_rd32(dev, 0x800004 + (i * 8)) & 1)) - continue; + ret = nouveau_fifo_context_create(parent, engine, oclass, NULL, 0x1000, + 0x1000, NVOBJ_FLAG_ZERO_ALLOC, &base); + *pobject = nv_object(base); + if (ret) + return ret; - nv_mask(dev, 0x800004 + (i * 8), 0x00000800, 0x00000800); - nv_wr32(dev, 0x002634, i); - if (!nv_wait(dev, 0x002634, 0xffffffff, i)) { - NV_INFO(dev, "PFIFO: kick ch %d failed: 0x%08x\n", - i, nv_rd32(dev, 0x002634)); - return -EBUSY; - } - } + ret = nouveau_gpuobj_new(parent, NULL, 0x10000, 0x1000, 0, &base->pgd); + if (ret) + return ret; + + nv_wo32(base, 0x0200, lower_32_bits(base->pgd->addr)); + nv_wo32(base, 0x0204, upper_32_bits(base->pgd->addr)); + nv_wo32(base, 0x0208, 0xffffffff); + nv_wo32(base, 0x020c, 0x000000ff); + + ret = nouveau_vm_ref(nouveau_client(parent)->vm, &base->vm, base->pgd); + if (ret) + return ret; - nv_wr32(dev, 0x002140, 0x00000000); return 0; } +static void +nve0_fifo_context_dtor(struct nouveau_object *object) +{ + struct nve0_fifo_base *base = (void *)object; + nouveau_vm_ref(NULL, &base->vm, base->pgd); + nouveau_gpuobj_ref(NULL, &base->pgd); + nouveau_fifo_context_destroy(&base->base); +} + +static struct nouveau_oclass +nve0_fifo_cclass = { + .handle = NV_ENGCTX(FIFO, 0xe0), + .ofuncs = &(struct nouveau_ofuncs) { + .ctor = nve0_fifo_context_ctor, + .dtor = nve0_fifo_context_dtor, + .init = _nouveau_fifo_context_init, + .fini = _nouveau_fifo_context_fini, + .rd32 = _nouveau_fifo_context_rd32, + .wr32 = _nouveau_fifo_context_wr32, + }, +}; + +/******************************************************************************* + * PFIFO engine + ******************************************************************************/ + struct nouveau_enum nve0_fifo_fault_unit[] = { {} }; @@ -268,16 +365,16 @@ struct nouveau_bitfield nve0_fifo_subfifo_intr[] = { }; static void -nve0_fifo_isr_vm_fault(struct drm_device *dev, int unit) +nve0_fifo_isr_vm_fault(struct nve0_fifo_priv *priv, int unit) { - u32 inst = nv_rd32(dev, 0x2800 + (unit * 0x10)); - u32 valo = nv_rd32(dev, 0x2804 + (unit * 0x10)); - u32 vahi = nv_rd32(dev, 0x2808 + (unit * 0x10)); - u32 stat = nv_rd32(dev, 0x280c + (unit * 0x10)); + u32 inst = nv_rd32(priv, 0x2800 + (unit * 0x10)); + u32 valo = nv_rd32(priv, 0x2804 + (unit * 0x10)); + u32 vahi = nv_rd32(priv, 0x2808 + (unit * 0x10)); + u32 stat = nv_rd32(priv, 0x280c + (unit * 0x10)); u32 client = (stat & 0x00001f00) >> 8; - NV_INFO(dev, "PFIFO: %s fault at 0x%010llx [", - (stat & 0x00000080) ? "write" : "read", (u64)vahi << 32 | valo); + nv_error(priv, "PFIFO: %s fault at 0x%010llx [", (stat & 0x00000080) ? + "write" : "read", (u64)vahi << 32 | valo); nouveau_enum_print(nve0_fifo_fault_reason, stat & 0x0000000f); printk("] from "); nouveau_enum_print(nve0_fifo_fault_unit, unit); @@ -292,160 +389,205 @@ nve0_fifo_isr_vm_fault(struct drm_device *dev, int unit) } static int -nve0_fifo_page_flip(struct drm_device *dev, u32 chid) +nve0_fifo_swmthd(struct nve0_fifo_priv *priv, u32 chid, u32 mthd, u32 data) { - struct nve0_fifo_priv *priv = nv_engine(dev, NVOBJ_ENGINE_FIFO); - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_channel *chan = NULL; + struct nve0_fifo_chan *chan = NULL; + struct nouveau_handle *bind; unsigned long flags; int ret = -EINVAL; - spin_lock_irqsave(&dev_priv->channels.lock, flags); - if (likely(chid >= 0 && chid < priv->base.channels)) { - chan = dev_priv->channels.ptr[chid]; - if (likely(chan)) { - struct nouveau_software_chan *swch = - chan->engctx[NVOBJ_ENGINE_SW]; - ret = swch->flip(swch->flip_data); - } + spin_lock_irqsave(&priv->base.lock, flags); + if (likely(chid >= priv->base.min && chid <= priv->base.max)) + chan = (void *)priv->base.channel[chid]; + if (unlikely(!chan)) + goto out; + + bind = nouveau_namedb_get_class(nv_namedb(chan), 0x906e); + if (likely(bind)) { + if (!mthd || !nv_call(bind->object, mthd, data)) + ret = 0; + nouveau_namedb_put(bind); } - spin_unlock_irqrestore(&dev_priv->channels.lock, flags); + +out: + spin_unlock_irqrestore(&priv->base.lock, flags); return ret; } static void -nve0_fifo_isr_subfifo_intr(struct drm_device *dev, int unit) +nve0_fifo_isr_subfifo_intr(struct nve0_fifo_priv *priv, int unit) { - u32 stat = nv_rd32(dev, 0x040108 + (unit * 0x2000)); - u32 addr = nv_rd32(dev, 0x0400c0 + (unit * 0x2000)); - u32 data = nv_rd32(dev, 0x0400c4 + (unit * 0x2000)); - u32 chid = nv_rd32(dev, 0x040120 + (unit * 0x2000)) & 0xfff; - u32 subc = (addr & 0x00070000); + u32 stat = nv_rd32(priv, 0x040108 + (unit * 0x2000)); + u32 addr = nv_rd32(priv, 0x0400c0 + (unit * 0x2000)); + u32 data = nv_rd32(priv, 0x0400c4 + (unit * 0x2000)); + u32 chid = nv_rd32(priv, 0x040120 + (unit * 0x2000)) & 0xfff; + u32 subc = (addr & 0x00070000) >> 16; u32 mthd = (addr & 0x00003ffc); u32 show = stat; if (stat & 0x00200000) { if (mthd == 0x0054) { - if (!nve0_fifo_page_flip(dev, chid)) + if (!nve0_fifo_swmthd(priv, chid, 0x0500, 0x00000000)) show &= ~0x00200000; } } + if (stat & 0x00800000) { + if (!nve0_fifo_swmthd(priv, chid, mthd, data)) + show &= ~0x00800000; + } + if (show) { - NV_INFO(dev, "PFIFO%d:", unit); + nv_error(priv, "SUBFIFO%d:", unit); nouveau_bitfield_print(nve0_fifo_subfifo_intr, show); - NV_INFO(dev, "PFIFO%d: ch %d subc %d mthd 0x%04x data 0x%08x\n", - unit, chid, subc, mthd, data); + printk("\n"); + nv_error(priv, "SUBFIFO%d: ch %d subc %d mthd 0x%04x " + "data 0x%08x\n", + unit, chid, subc, mthd, data); } - nv_wr32(dev, 0x0400c0 + (unit * 0x2000), 0x80600008); - nv_wr32(dev, 0x040108 + (unit * 0x2000), stat); + nv_wr32(priv, 0x0400c0 + (unit * 0x2000), 0x80600008); + nv_wr32(priv, 0x040108 + (unit * 0x2000), stat); } static void -nve0_fifo_isr(struct drm_device *dev) +nve0_fifo_intr(struct nouveau_subdev *subdev) { - u32 mask = nv_rd32(dev, 0x002140); - u32 stat = nv_rd32(dev, 0x002100) & mask; + struct nve0_fifo_priv *priv = (void *)subdev; + u32 mask = nv_rd32(priv, 0x002140); + u32 stat = nv_rd32(priv, 0x002100) & mask; if (stat & 0x00000100) { - NV_INFO(dev, "PFIFO: unknown status 0x00000100\n"); - nv_wr32(dev, 0x002100, 0x00000100); + nv_warn(priv, "unknown status 0x00000100\n"); + nv_wr32(priv, 0x002100, 0x00000100); stat &= ~0x00000100; } if (stat & 0x10000000) { - u32 units = nv_rd32(dev, 0x00259c); + u32 units = nv_rd32(priv, 0x00259c); u32 u = units; while (u) { int i = ffs(u) - 1; - nve0_fifo_isr_vm_fault(dev, i); + nve0_fifo_isr_vm_fault(priv, i); u &= ~(1 << i); } - nv_wr32(dev, 0x00259c, units); + nv_wr32(priv, 0x00259c, units); stat &= ~0x10000000; } if (stat & 0x20000000) { - u32 units = nv_rd32(dev, 0x0025a0); + u32 units = nv_rd32(priv, 0x0025a0); u32 u = units; while (u) { int i = ffs(u) - 1; - nve0_fifo_isr_subfifo_intr(dev, i); + nve0_fifo_isr_subfifo_intr(priv, i); u &= ~(1 << i); } - nv_wr32(dev, 0x0025a0, units); + nv_wr32(priv, 0x0025a0, units); stat &= ~0x20000000; } if (stat & 0x40000000) { - NV_INFO(dev, "PFIFO: unknown status 0x40000000\n"); - nv_mask(dev, 0x002a00, 0x00000000, 0x00000000); + nv_warn(priv, "unknown status 0x40000000\n"); + nv_mask(priv, 0x002a00, 0x00000000, 0x00000000); stat &= ~0x40000000; } if (stat) { - NV_INFO(dev, "PFIFO: unhandled status 0x%08x\n", stat); - nv_wr32(dev, 0x002100, stat); - nv_wr32(dev, 0x002140, 0); + nv_fatal(priv, "unhandled status 0x%08x\n", stat); + nv_wr32(priv, 0x002100, stat); + nv_wr32(priv, 0x002140, 0); } } +static int +nve0_fifo_ctor(struct nouveau_object *parent, struct nouveau_object *engine, + struct nouveau_oclass *oclass, void *data, u32 size, + struct nouveau_object **pobject) +{ + struct nve0_fifo_priv *priv; + int ret; + + ret = nouveau_fifo_create(parent, engine, oclass, 0, 4095, &priv); + *pobject = nv_object(priv); + if (ret) + return ret; + + ret = nouveau_gpuobj_new(parent, NULL, 4096 * 0x200, 0x1000, + NVOBJ_FLAG_ZERO_ALLOC, &priv->user.mem); + if (ret) + return ret; + + ret = nouveau_gpuobj_map(priv->user.mem, NV_MEM_ACCESS_RW, + &priv->user.bar); + if (ret) + return ret; + + nv_subdev(priv)->unit = 0x00000100; + nv_subdev(priv)->intr = nve0_fifo_intr; + nv_engine(priv)->cclass = &nve0_fifo_cclass; + nv_engine(priv)->sclass = nve0_fifo_sclass; + return 0; +} + static void -nve0_fifo_destroy(struct drm_device *dev, int engine) +nve0_fifo_dtor(struct nouveau_object *object) { - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nve0_fifo_priv *priv = nv_engine(dev, engine); + struct nve0_fifo_priv *priv = (void *)object; int i; nouveau_gpuobj_unmap(&priv->user.bar); nouveau_gpuobj_ref(NULL, &priv->user.mem); - for (i = 0; i < NVE0_FIFO_ENGINE_NUM; i++) { - nouveau_gpuobj_ref(NULL, &priv->engine[i].playlist[0]); + for (i = 0; i < ARRAY_SIZE(priv->engine); i++) { nouveau_gpuobj_ref(NULL, &priv->engine[i].playlist[1]); + nouveau_gpuobj_ref(NULL, &priv->engine[i].playlist[0]); } - dev_priv->eng[engine] = NULL; - kfree(priv); + nouveau_fifo_destroy(&priv->base); } -int -nve0_fifo_create(struct drm_device *dev) +static int +nve0_fifo_init(struct nouveau_object *object) { - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nve0_fifo_priv *priv; - int ret; + struct nve0_fifo_priv *priv = (void *)object; + int ret, i; - priv = kzalloc(sizeof(*priv), GFP_KERNEL); - if (!priv) - return -ENOMEM; + ret = nouveau_fifo_init(&priv->base); + if (ret) + return ret; - priv->base.base.destroy = nve0_fifo_destroy; - priv->base.base.init = nve0_fifo_init; - priv->base.base.fini = nve0_fifo_fini; - priv->base.base.context_new = nve0_fifo_context_new; - priv->base.base.context_del = nve0_fifo_context_del; - priv->base.channels = 4096; - dev_priv->eng[NVOBJ_ENGINE_FIFO] = &priv->base.base; + /* enable all available PSUBFIFOs */ + nv_wr32(priv, 0x000204, 0xffffffff); + priv->spoon_nr = hweight32(nv_rd32(priv, 0x000204)); + nv_debug(priv, "%d subfifo(s)\n", priv->spoon_nr); - ret = nouveau_gpuobj_new(dev, NULL, priv->base.channels * 512, 0x1000, - NVOBJ_FLAG_ZERO_ALLOC, &priv->user.mem); - if (ret) - goto error; + /* PSUBFIFO[n] */ + for (i = 0; i < priv->spoon_nr; i++) { + nv_mask(priv, 0x04013c + (i * 0x2000), 0x10000100, 0x00000000); + nv_wr32(priv, 0x040108 + (i * 0x2000), 0xffffffff); /* INTR */ + nv_wr32(priv, 0x04010c + (i * 0x2000), 0xfffffeff); /* INTREN */ + } - ret = nouveau_gpuobj_map_bar(priv->user.mem, NV_MEM_ACCESS_RW, - &priv->user.bar); - if (ret) - goto error; + nv_wr32(priv, 0x002254, 0x10000000 | priv->user.bar.offset >> 12); - nouveau_irq_register(dev, 8, nve0_fifo_isr); -error: - if (ret) - priv->base.base.destroy(dev, NVOBJ_ENGINE_FIFO); - return ret; + nv_wr32(priv, 0x002a00, 0xffffffff); + nv_wr32(priv, 0x002100, 0xffffffff); + nv_wr32(priv, 0x002140, 0xbfffffff); + return 0; } + +struct nouveau_oclass +nve0_fifo_oclass = { + .handle = NV_ENGINE(FIFO, 0xe0), + .ofuncs = &(struct nouveau_ofuncs) { + .ctor = nve0_fifo_ctor, + .dtor = nve0_fifo_dtor, + .init = nve0_fifo_init, + .fini = _nouveau_fifo_fini, + }, +}; diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/ctx.h b/drivers/gpu/drm/nouveau/core/engine/graph/ctx.h index b0795ececbda..e1947013d3bc 100644 --- a/drivers/gpu/drm/nouveau/core/engine/graph/ctx.h +++ b/drivers/gpu/drm/nouveau/core/engine/graph/ctx.h @@ -2,7 +2,7 @@ #define __NOUVEAU_GRCTX_H__ struct nouveau_grctx { - struct drm_device *dev; + struct nouveau_device *device; enum { NOUVEAU_GRCTX_PROG, @@ -10,18 +10,18 @@ struct nouveau_grctx { } mode; void *data; - uint32_t ctxprog_max; - uint32_t ctxprog_len; - uint32_t ctxprog_reg; - int ctxprog_label[32]; - uint32_t ctxvals_pos; - uint32_t ctxvals_base; + u32 ctxprog_max; + u32 ctxprog_len; + u32 ctxprog_reg; + int ctxprog_label[32]; + u32 ctxvals_pos; + u32 ctxvals_base; }; static inline void -cp_out(struct nouveau_grctx *ctx, uint32_t inst) +cp_out(struct nouveau_grctx *ctx, u32 inst) { - uint32_t *ctxprog = ctx->data; + u32 *ctxprog = ctx->data; if (ctx->mode != NOUVEAU_GRCTX_PROG) return; @@ -31,13 +31,13 @@ cp_out(struct nouveau_grctx *ctx, uint32_t inst) } static inline void -cp_lsr(struct nouveau_grctx *ctx, uint32_t val) +cp_lsr(struct nouveau_grctx *ctx, u32 val) { cp_out(ctx, CP_LOAD_SR | val); } static inline void -cp_ctx(struct nouveau_grctx *ctx, uint32_t reg, uint32_t length) +cp_ctx(struct nouveau_grctx *ctx, u32 reg, u32 length) { ctx->ctxprog_reg = (reg - 0x00400000) >> 2; @@ -55,7 +55,7 @@ cp_ctx(struct nouveau_grctx *ctx, uint32_t reg, uint32_t length) static inline void cp_name(struct nouveau_grctx *ctx, int name) { - uint32_t *ctxprog = ctx->data; + u32 *ctxprog = ctx->data; int i; if (ctx->mode != NOUVEAU_GRCTX_PROG) @@ -115,7 +115,7 @@ cp_pos(struct nouveau_grctx *ctx, int offset) } static inline void -gr_def(struct nouveau_grctx *ctx, uint32_t reg, uint32_t val) +gr_def(struct nouveau_grctx *ctx, u32 reg, u32 val) { if (ctx->mode != NOUVEAU_GRCTX_VALS) return; diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/ctxnv40.c b/drivers/gpu/drm/nouveau/core/engine/graph/ctxnv40.c index b17506d7eb60..e45035efb8ca 100644 --- a/drivers/gpu/drm/nouveau/core/engine/graph/ctxnv40.c +++ b/drivers/gpu/drm/nouveau/core/engine/graph/ctxnv40.c @@ -22,6 +22,8 @@ * Authors: Ben Skeggs */ +#include + /* NVIDIA context programs handle a number of other conditions which are * not implemented in our versions. It's not clear why NVIDIA context * programs have this code, nor whether it's strictly necessary for @@ -109,8 +111,7 @@ #define CP_LOAD_MAGIC_NV44TCL 0x00800029 /* per-vs state (0x4497) */ #define CP_LOAD_MAGIC_NV40TCL 0x00800041 /* per-vs state (0x4097) */ -#include "drmP.h" -#include "nouveau_drv.h" +#include "nv40.h" #include "ctx.h" /* TODO: @@ -118,11 +119,10 @@ */ static int -nv40_graph_vs_count(struct drm_device *dev) +nv40_graph_vs_count(struct nouveau_device *device) { - struct drm_nouveau_private *dev_priv = dev->dev_private; - switch (dev_priv->chipset) { + switch (device->chipset) { case 0x47: case 0x49: case 0x4b: @@ -160,7 +160,7 @@ enum cp_label { static void nv40_graph_construct_general(struct nouveau_grctx *ctx) { - struct drm_nouveau_private *dev_priv = ctx->dev->dev_private; + struct nouveau_device *device = ctx->device; int i; cp_ctx(ctx, 0x4000a4, 1); @@ -187,7 +187,7 @@ nv40_graph_construct_general(struct nouveau_grctx *ctx) cp_ctx(ctx, 0x400724, 1); gr_def(ctx, 0x400724, 0x02008821); cp_ctx(ctx, 0x400770, 3); - if (dev_priv->chipset == 0x40) { + if (device->chipset == 0x40) { cp_ctx(ctx, 0x400814, 4); cp_ctx(ctx, 0x400828, 5); cp_ctx(ctx, 0x400840, 5); @@ -208,7 +208,7 @@ nv40_graph_construct_general(struct nouveau_grctx *ctx) gr_def(ctx, 0x4009dc, 0x80000000); } else { cp_ctx(ctx, 0x400840, 20); - if (nv44_graph_class(ctx->dev)) { + if (nv44_graph_class(ctx->device)) { for (i = 0; i < 8; i++) gr_def(ctx, 0x400860 + (i * 4), 0x00000001); } @@ -217,21 +217,21 @@ nv40_graph_construct_general(struct nouveau_grctx *ctx) gr_def(ctx, 0x400888, 0x00000040); cp_ctx(ctx, 0x400894, 11); gr_def(ctx, 0x400894, 0x00000040); - if (!nv44_graph_class(ctx->dev)) { + if (!nv44_graph_class(ctx->device)) { for (i = 0; i < 8; i++) gr_def(ctx, 0x4008a0 + (i * 4), 0x80000000); } cp_ctx(ctx, 0x4008e0, 2); cp_ctx(ctx, 0x4008f8, 2); - if (dev_priv->chipset == 0x4c || - (dev_priv->chipset & 0xf0) == 0x60) + if (device->chipset == 0x4c || + (device->chipset & 0xf0) == 0x60) cp_ctx(ctx, 0x4009f8, 1); } cp_ctx(ctx, 0x400a00, 73); gr_def(ctx, 0x400b0c, 0x0b0b0b0c); cp_ctx(ctx, 0x401000, 4); cp_ctx(ctx, 0x405004, 1); - switch (dev_priv->chipset) { + switch (device->chipset) { case 0x47: case 0x49: case 0x4b: @@ -240,7 +240,7 @@ nv40_graph_construct_general(struct nouveau_grctx *ctx) break; default: cp_ctx(ctx, 0x403440, 1); - switch (dev_priv->chipset) { + switch (device->chipset) { case 0x40: gr_def(ctx, 0x403440, 0x00000010); break; @@ -266,19 +266,19 @@ nv40_graph_construct_general(struct nouveau_grctx *ctx) static void nv40_graph_construct_state3d(struct nouveau_grctx *ctx) { - struct drm_nouveau_private *dev_priv = ctx->dev->dev_private; + struct nouveau_device *device = ctx->device; int i; - if (dev_priv->chipset == 0x40) { + if (device->chipset == 0x40) { cp_ctx(ctx, 0x401880, 51); gr_def(ctx, 0x401940, 0x00000100); } else - if (dev_priv->chipset == 0x46 || dev_priv->chipset == 0x47 || - dev_priv->chipset == 0x49 || dev_priv->chipset == 0x4b) { + if (device->chipset == 0x46 || device->chipset == 0x47 || + device->chipset == 0x49 || device->chipset == 0x4b) { cp_ctx(ctx, 0x401880, 32); for (i = 0; i < 16; i++) gr_def(ctx, 0x401880 + (i * 4), 0x00000111); - if (dev_priv->chipset == 0x46) + if (device->chipset == 0x46) cp_ctx(ctx, 0x401900, 16); cp_ctx(ctx, 0x401940, 3); } @@ -289,7 +289,7 @@ nv40_graph_construct_state3d(struct nouveau_grctx *ctx) gr_def(ctx, 0x401978, 0xffff0000); gr_def(ctx, 0x40197c, 0x00000001); gr_def(ctx, 0x401990, 0x46400000); - if (dev_priv->chipset == 0x40) { + if (device->chipset == 0x40) { cp_ctx(ctx, 0x4019a0, 2); cp_ctx(ctx, 0x4019ac, 5); } else { @@ -297,7 +297,7 @@ nv40_graph_construct_state3d(struct nouveau_grctx *ctx) cp_ctx(ctx, 0x4019b4, 3); } gr_def(ctx, 0x4019bc, 0xffff0000); - switch (dev_priv->chipset) { + switch (device->chipset) { case 0x46: case 0x47: case 0x49: @@ -316,7 +316,7 @@ nv40_graph_construct_state3d(struct nouveau_grctx *ctx) for (i = 0; i < 16; i++) gr_def(ctx, 0x401a44 + (i * 4), 0x07ff0000); gr_def(ctx, 0x401a8c, 0x4b7fffff); - if (dev_priv->chipset == 0x40) { + if (device->chipset == 0x40) { cp_ctx(ctx, 0x401ab8, 3); } else { cp_ctx(ctx, 0x401ab8, 1); @@ -327,10 +327,10 @@ nv40_graph_construct_state3d(struct nouveau_grctx *ctx) gr_def(ctx, 0x401ad4, 0x70605040); gr_def(ctx, 0x401ad8, 0xb8a89888); gr_def(ctx, 0x401adc, 0xf8e8d8c8); - cp_ctx(ctx, 0x401b10, dev_priv->chipset == 0x40 ? 2 : 1); + cp_ctx(ctx, 0x401b10, device->chipset == 0x40 ? 2 : 1); gr_def(ctx, 0x401b10, 0x40100000); - cp_ctx(ctx, 0x401b18, dev_priv->chipset == 0x40 ? 6 : 5); - gr_def(ctx, 0x401b28, dev_priv->chipset == 0x40 ? + cp_ctx(ctx, 0x401b18, device->chipset == 0x40 ? 6 : 5); + gr_def(ctx, 0x401b28, device->chipset == 0x40 ? 0x00000004 : 0x00000000); cp_ctx(ctx, 0x401b30, 25); gr_def(ctx, 0x401b34, 0x0000ffff); @@ -341,8 +341,8 @@ nv40_graph_construct_state3d(struct nouveau_grctx *ctx) gr_def(ctx, 0x401b84, 0xffffffff); gr_def(ctx, 0x401b88, 0x00ff7000); gr_def(ctx, 0x401b8c, 0x0000ffff); - if (dev_priv->chipset != 0x44 && dev_priv->chipset != 0x4a && - dev_priv->chipset != 0x4e) + if (device->chipset != 0x44 && device->chipset != 0x4a && + device->chipset != 0x4e) cp_ctx(ctx, 0x401b94, 1); cp_ctx(ctx, 0x401b98, 8); gr_def(ctx, 0x401b9c, 0x00ff0000); @@ -371,12 +371,12 @@ nv40_graph_construct_state3d(struct nouveau_grctx *ctx) static void nv40_graph_construct_state3d_2(struct nouveau_grctx *ctx) { - struct drm_nouveau_private *dev_priv = ctx->dev->dev_private; + struct nouveau_device *device = ctx->device; int i; cp_ctx(ctx, 0x402000, 1); - cp_ctx(ctx, 0x402404, dev_priv->chipset == 0x40 ? 1 : 2); - switch (dev_priv->chipset) { + cp_ctx(ctx, 0x402404, device->chipset == 0x40 ? 1 : 2); + switch (device->chipset) { case 0x40: gr_def(ctx, 0x402404, 0x00000001); break; @@ -393,9 +393,9 @@ nv40_graph_construct_state3d_2(struct nouveau_grctx *ctx) default: gr_def(ctx, 0x402404, 0x00000021); } - if (dev_priv->chipset != 0x40) + if (device->chipset != 0x40) gr_def(ctx, 0x402408, 0x030c30c3); - switch (dev_priv->chipset) { + switch (device->chipset) { case 0x44: case 0x46: case 0x4a: @@ -408,10 +408,10 @@ nv40_graph_construct_state3d_2(struct nouveau_grctx *ctx) default: break; } - cp_ctx(ctx, 0x402480, dev_priv->chipset == 0x40 ? 8 : 9); + cp_ctx(ctx, 0x402480, device->chipset == 0x40 ? 8 : 9); gr_def(ctx, 0x402488, 0x3e020200); gr_def(ctx, 0x40248c, 0x00ffffff); - switch (dev_priv->chipset) { + switch (device->chipset) { case 0x40: gr_def(ctx, 0x402490, 0x60103f00); break; @@ -428,16 +428,16 @@ nv40_graph_construct_state3d_2(struct nouveau_grctx *ctx) gr_def(ctx, 0x402490, 0x0c103f00); break; } - gr_def(ctx, 0x40249c, dev_priv->chipset <= 0x43 ? + gr_def(ctx, 0x40249c, device->chipset <= 0x43 ? 0x00020000 : 0x00040000); cp_ctx(ctx, 0x402500, 31); gr_def(ctx, 0x402530, 0x00008100); - if (dev_priv->chipset == 0x40) + if (device->chipset == 0x40) cp_ctx(ctx, 0x40257c, 6); cp_ctx(ctx, 0x402594, 16); cp_ctx(ctx, 0x402800, 17); gr_def(ctx, 0x402800, 0x00000001); - switch (dev_priv->chipset) { + switch (device->chipset) { case 0x47: case 0x49: case 0x4b: @@ -445,7 +445,7 @@ nv40_graph_construct_state3d_2(struct nouveau_grctx *ctx) gr_def(ctx, 0x402864, 0x00001001); cp_ctx(ctx, 0x402870, 3); gr_def(ctx, 0x402878, 0x00000003); - if (dev_priv->chipset != 0x47) { /* belong at end!! */ + if (device->chipset != 0x47) { /* belong at end!! */ cp_ctx(ctx, 0x402900, 1); cp_ctx(ctx, 0x402940, 1); cp_ctx(ctx, 0x402980, 1); @@ -470,9 +470,9 @@ nv40_graph_construct_state3d_2(struct nouveau_grctx *ctx) } cp_ctx(ctx, 0x402c00, 4); - gr_def(ctx, 0x402c00, dev_priv->chipset == 0x40 ? + gr_def(ctx, 0x402c00, device->chipset == 0x40 ? 0x80800001 : 0x00888001); - switch (dev_priv->chipset) { + switch (device->chipset) { case 0x47: case 0x49: case 0x4b: @@ -485,30 +485,30 @@ nv40_graph_construct_state3d_2(struct nouveau_grctx *ctx) break; default: cp_ctx(ctx, 0x402c10, 4); - if (dev_priv->chipset == 0x40) + if (device->chipset == 0x40) cp_ctx(ctx, 0x402c20, 36); else - if (dev_priv->chipset <= 0x42) + if (device->chipset <= 0x42) cp_ctx(ctx, 0x402c20, 24); else - if (dev_priv->chipset <= 0x4a) + if (device->chipset <= 0x4a) cp_ctx(ctx, 0x402c20, 16); else cp_ctx(ctx, 0x402c20, 8); - cp_ctx(ctx, 0x402cb0, dev_priv->chipset == 0x40 ? 12 : 13); + cp_ctx(ctx, 0x402cb0, device->chipset == 0x40 ? 12 : 13); gr_def(ctx, 0x402cd4, 0x00000005); - if (dev_priv->chipset != 0x40) + if (device->chipset != 0x40) gr_def(ctx, 0x402ce0, 0x0000ffff); break; } - cp_ctx(ctx, 0x403400, dev_priv->chipset == 0x40 ? 4 : 3); - cp_ctx(ctx, 0x403410, dev_priv->chipset == 0x40 ? 4 : 3); - cp_ctx(ctx, 0x403420, nv40_graph_vs_count(ctx->dev)); - for (i = 0; i < nv40_graph_vs_count(ctx->dev); i++) + cp_ctx(ctx, 0x403400, device->chipset == 0x40 ? 4 : 3); + cp_ctx(ctx, 0x403410, device->chipset == 0x40 ? 4 : 3); + cp_ctx(ctx, 0x403420, nv40_graph_vs_count(ctx->device)); + for (i = 0; i < nv40_graph_vs_count(ctx->device); i++) gr_def(ctx, 0x403420 + (i * 4), 0x00005555); - if (dev_priv->chipset != 0x40) { + if (device->chipset != 0x40) { cp_ctx(ctx, 0x403600, 1); gr_def(ctx, 0x403600, 0x00000001); } @@ -516,7 +516,7 @@ nv40_graph_construct_state3d_2(struct nouveau_grctx *ctx) cp_ctx(ctx, 0x403c18, 1); gr_def(ctx, 0x403c18, 0x00000001); - switch (dev_priv->chipset) { + switch (device->chipset) { case 0x46: case 0x47: case 0x49: @@ -527,7 +527,7 @@ nv40_graph_construct_state3d_2(struct nouveau_grctx *ctx) gr_def(ctx, 0x405c24, 0x000e3000); break; } - if (dev_priv->chipset != 0x4e) + if (device->chipset != 0x4e) cp_ctx(ctx, 0x405800, 11); cp_ctx(ctx, 0x407000, 1); } @@ -535,7 +535,7 @@ nv40_graph_construct_state3d_2(struct nouveau_grctx *ctx) static void nv40_graph_construct_state3d_3(struct nouveau_grctx *ctx) { - int len = nv44_graph_class(ctx->dev) ? 0x0084 : 0x0684; + int len = nv44_graph_class(ctx->device) ? 0x0084 : 0x0684; cp_out (ctx, 0x300000); cp_lsr (ctx, len - 4); @@ -550,32 +550,31 @@ nv40_graph_construct_state3d_3(struct nouveau_grctx *ctx) static void nv40_graph_construct_shader(struct nouveau_grctx *ctx) { - struct drm_device *dev = ctx->dev; - struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_device *device = ctx->device; struct nouveau_gpuobj *obj = ctx->data; int vs, vs_nr, vs_len, vs_nr_b0, vs_nr_b1, b0_offset, b1_offset; int offset, i; - vs_nr = nv40_graph_vs_count(ctx->dev); + vs_nr = nv40_graph_vs_count(ctx->device); vs_nr_b0 = 363; - vs_nr_b1 = dev_priv->chipset == 0x40 ? 128 : 64; - if (dev_priv->chipset == 0x40) { + vs_nr_b1 = device->chipset == 0x40 ? 128 : 64; + if (device->chipset == 0x40) { b0_offset = 0x2200/4; /* 33a0 */ b1_offset = 0x55a0/4; /* 1500 */ vs_len = 0x6aa0/4; } else - if (dev_priv->chipset == 0x41 || dev_priv->chipset == 0x42) { + if (device->chipset == 0x41 || device->chipset == 0x42) { b0_offset = 0x2200/4; /* 2200 */ b1_offset = 0x4400/4; /* 0b00 */ vs_len = 0x4f00/4; } else { b0_offset = 0x1d40/4; /* 2200 */ b1_offset = 0x3f40/4; /* 0b00 : 0a40 */ - vs_len = nv44_graph_class(dev) ? 0x4980/4 : 0x4a40/4; + vs_len = nv44_graph_class(device) ? 0x4980/4 : 0x4a40/4; } cp_lsr(ctx, vs_len * vs_nr + 0x300/4); - cp_out(ctx, nv44_graph_class(dev) ? 0x800029 : 0x800041); + cp_out(ctx, nv44_graph_class(device) ? 0x800029 : 0x800041); offset = ctx->ctxvals_pos; ctx->ctxvals_pos += (0x0300/4 + (vs_nr * vs_len)); @@ -661,21 +660,21 @@ nv40_grctx_generate(struct nouveau_grctx *ctx) } void -nv40_grctx_fill(struct drm_device *dev, struct nouveau_gpuobj *mem) +nv40_grctx_fill(struct nouveau_device *device, struct nouveau_gpuobj *mem) { nv40_grctx_generate(&(struct nouveau_grctx) { - .dev = dev, + .device = device, .mode = NOUVEAU_GRCTX_VALS, .data = mem, }); } void -nv40_grctx_init(struct drm_device *dev, u32 *size) +nv40_grctx_init(struct nouveau_device *device, u32 *size) { u32 ctxprog[256], i; struct nouveau_grctx ctx = { - .dev = dev, + .device = device, .mode = NOUVEAU_GRCTX_PROG, .data = ctxprog, .ctxprog_max = ARRAY_SIZE(ctxprog) @@ -683,8 +682,8 @@ nv40_grctx_init(struct drm_device *dev, u32 *size) nv40_grctx_generate(&ctx); - nv_wr32(dev, NV40_PGRAPH_CTXCTL_UCODE_INDEX, 0); + nv_wr32(device, 0x400324, 0); for (i = 0; i < ctx.ctxprog_len; i++) - nv_wr32(dev, NV40_PGRAPH_CTXCTL_UCODE_DATA, ctxprog[i]); + nv_wr32(device, 0x400328, ctxprog[i]); *size = ctx.ctxvals_pos * 4; } diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/ctxnv50.c b/drivers/gpu/drm/nouveau/core/engine/graph/ctxnv50.c index e17c17bfd89e..552fdbd45ebe 100644 --- a/drivers/gpu/drm/nouveau/core/engine/graph/ctxnv50.c +++ b/drivers/gpu/drm/nouveau/core/engine/graph/ctxnv50.c @@ -20,6 +20,8 @@ * OTHER DEALINGS IN THE SOFTWARE. */ +#include + #define CP_FLAG_CLEAR 0 #define CP_FLAG_SET 1 #define CP_FLAG_SWAP_DIRECTION ((0 * 32) + 0) @@ -105,8 +107,7 @@ #define CP_SEEK_1 0x00c000ff #define CP_SEEK_2 0x00c800ff -#include "drmP.h" -#include "nouveau_drv.h" +#include "nv50.h" #include "ctx.h" #define IS_NVA3F(x) (((x) > 0xa0 && (x) < 0xaa) || (x) == 0xaf) @@ -175,32 +176,6 @@ static void nv50_graph_construct_xfer2(struct nouveau_grctx *ctx); static int nv50_grctx_generate(struct nouveau_grctx *ctx) { - struct drm_nouveau_private *dev_priv = ctx->dev->dev_private; - - switch (dev_priv->chipset) { - case 0x50: - case 0x84: - case 0x86: - case 0x92: - case 0x94: - case 0x96: - case 0x98: - case 0xa0: - case 0xa3: - case 0xa5: - case 0xa8: - case 0xaa: - case 0xac: - case 0xaf: - break; - default: - NV_ERROR(ctx->dev, "I don't know how to make a ctxprog for " - "your NV%x card.\n", dev_priv->chipset); - NV_ERROR(ctx->dev, "Disabling acceleration. Please contact " - "the devs.\n"); - return -ENOSYS; - } - cp_set (ctx, STATE, RUNNING); cp_set (ctx, XFER_SWITCH, ENABLE); /* decide whether we're loading/unloading the context */ @@ -278,30 +253,36 @@ nv50_grctx_generate(struct nouveau_grctx *ctx) } void -nv50_grctx_fill(struct drm_device *dev, struct nouveau_gpuobj *mem) +nv50_grctx_fill(struct nouveau_device *device, struct nouveau_gpuobj *mem) { nv50_grctx_generate(&(struct nouveau_grctx) { - .dev = dev, + .device = device, .mode = NOUVEAU_GRCTX_VALS, .data = mem, }); } int -nv50_grctx_init(struct drm_device *dev, u32 *data, u32 max, u32 *len, u32 *cnt) +nv50_grctx_init(struct nouveau_device *device, u32 *size) { + u32 *ctxprog = kmalloc(512 * 4, GFP_KERNEL), i; struct nouveau_grctx ctx = { - .dev = dev, + .device = device, .mode = NOUVEAU_GRCTX_PROG, - .data = data, - .ctxprog_max = max + .data = ctxprog, + .ctxprog_max = 512, }; - int ret; - ret = nv50_grctx_generate(&ctx); - *cnt = ctx.ctxvals_pos * 4; - *len = ctx.ctxprog_len; - return ret; + if (!ctxprog) + return -ENOMEM; + nv50_grctx_generate(&ctx); + + nv_wr32(device, 0x400324, 0); + for (i = 0; i < ctx.ctxprog_len; i++) + nv_wr32(device, 0x400328, ctxprog[i]); + *size = ctx.ctxvals_pos * 4; + kfree(ctxprog); + return 0; } /* @@ -315,36 +296,36 @@ nv50_graph_construct_mmio_ddata(struct nouveau_grctx *ctx); static void nv50_graph_construct_mmio(struct nouveau_grctx *ctx) { - struct drm_nouveau_private *dev_priv = ctx->dev->dev_private; + struct nouveau_device *device = ctx->device; int i, j; int offset, base; - uint32_t units = nv_rd32 (ctx->dev, 0x1540); + u32 units = nv_rd32 (ctx->device, 0x1540); /* 0800: DISPATCH */ cp_ctx(ctx, 0x400808, 7); gr_def(ctx, 0x400814, 0x00000030); cp_ctx(ctx, 0x400834, 0x32); - if (dev_priv->chipset == 0x50) { + if (device->chipset == 0x50) { gr_def(ctx, 0x400834, 0xff400040); gr_def(ctx, 0x400838, 0xfff00080); gr_def(ctx, 0x40083c, 0xfff70090); gr_def(ctx, 0x400840, 0xffe806a8); } gr_def(ctx, 0x400844, 0x00000002); - if (IS_NVA3F(dev_priv->chipset)) + if (IS_NVA3F(device->chipset)) gr_def(ctx, 0x400894, 0x00001000); gr_def(ctx, 0x4008e8, 0x00000003); gr_def(ctx, 0x4008ec, 0x00001000); - if (dev_priv->chipset == 0x50) + if (device->chipset == 0x50) cp_ctx(ctx, 0x400908, 0xb); - else if (dev_priv->chipset < 0xa0) + else if (device->chipset < 0xa0) cp_ctx(ctx, 0x400908, 0xc); else cp_ctx(ctx, 0x400908, 0xe); - if (dev_priv->chipset >= 0xa0) + if (device->chipset >= 0xa0) cp_ctx(ctx, 0x400b00, 0x1); - if (IS_NVA3F(dev_priv->chipset)) { + if (IS_NVA3F(device->chipset)) { cp_ctx(ctx, 0x400b10, 0x1); gr_def(ctx, 0x400b10, 0x0001629d); cp_ctx(ctx, 0x400b20, 0x1); @@ -358,10 +339,10 @@ nv50_graph_construct_mmio(struct nouveau_grctx *ctx) gr_def(ctx, 0x400c08, 0x0000fe0c); /* 1000 */ - if (dev_priv->chipset < 0xa0) { + if (device->chipset < 0xa0) { cp_ctx(ctx, 0x401008, 0x4); gr_def(ctx, 0x401014, 0x00001000); - } else if (!IS_NVA3F(dev_priv->chipset)) { + } else if (!IS_NVA3F(device->chipset)) { cp_ctx(ctx, 0x401008, 0x5); gr_def(ctx, 0x401018, 0x00001000); } else { @@ -372,7 +353,7 @@ nv50_graph_construct_mmio(struct nouveau_grctx *ctx) /* 1400 */ cp_ctx(ctx, 0x401400, 0x8); cp_ctx(ctx, 0x401424, 0x3); - if (dev_priv->chipset == 0x50) + if (device->chipset == 0x50) gr_def(ctx, 0x40142c, 0x0001fd87); else gr_def(ctx, 0x40142c, 0x00000187); @@ -382,10 +363,10 @@ nv50_graph_construct_mmio(struct nouveau_grctx *ctx) /* 1800: STREAMOUT */ cp_ctx(ctx, 0x401814, 0x1); gr_def(ctx, 0x401814, 0x000000ff); - if (dev_priv->chipset == 0x50) { + if (device->chipset == 0x50) { cp_ctx(ctx, 0x40181c, 0xe); gr_def(ctx, 0x401850, 0x00000004); - } else if (dev_priv->chipset < 0xa0) { + } else if (device->chipset < 0xa0) { cp_ctx(ctx, 0x40181c, 0xf); gr_def(ctx, 0x401854, 0x00000004); } else { @@ -395,7 +376,7 @@ nv50_graph_construct_mmio(struct nouveau_grctx *ctx) /* 1C00 */ cp_ctx(ctx, 0x401c00, 0x1); - switch (dev_priv->chipset) { + switch (device->chipset) { case 0x50: gr_def(ctx, 0x401c00, 0x0001005f); break; @@ -424,7 +405,7 @@ nv50_graph_construct_mmio(struct nouveau_grctx *ctx) /* 2400 */ cp_ctx(ctx, 0x402400, 0x1); - if (dev_priv->chipset == 0x50) + if (device->chipset == 0x50) cp_ctx(ctx, 0x402408, 0x1); else cp_ctx(ctx, 0x402408, 0x2); @@ -432,21 +413,21 @@ nv50_graph_construct_mmio(struct nouveau_grctx *ctx) /* 2800: CSCHED */ cp_ctx(ctx, 0x402800, 0x1); - if (dev_priv->chipset == 0x50) + if (device->chipset == 0x50) gr_def(ctx, 0x402800, 0x00000006); /* 2C00: ZCULL */ cp_ctx(ctx, 0x402c08, 0x6); - if (dev_priv->chipset != 0x50) + if (device->chipset != 0x50) gr_def(ctx, 0x402c14, 0x01000000); gr_def(ctx, 0x402c18, 0x000000ff); - if (dev_priv->chipset == 0x50) + if (device->chipset == 0x50) cp_ctx(ctx, 0x402ca0, 0x1); else cp_ctx(ctx, 0x402ca0, 0x2); - if (dev_priv->chipset < 0xa0) + if (device->chipset < 0xa0) gr_def(ctx, 0x402ca0, 0x00000400); - else if (!IS_NVA3F(dev_priv->chipset)) + else if (!IS_NVA3F(device->chipset)) gr_def(ctx, 0x402ca0, 0x00000800); else gr_def(ctx, 0x402ca0, 0x00000400); @@ -457,14 +438,14 @@ nv50_graph_construct_mmio(struct nouveau_grctx *ctx) gr_def(ctx, 0x403004, 0x00000001); /* 3400 */ - if (dev_priv->chipset >= 0xa0) { + if (device->chipset >= 0xa0) { cp_ctx(ctx, 0x403404, 0x1); gr_def(ctx, 0x403404, 0x00000001); } /* 5000: CCACHE */ cp_ctx(ctx, 0x405000, 0x1); - switch (dev_priv->chipset) { + switch (device->chipset) { case 0x50: gr_def(ctx, 0x405000, 0x00300080); break; @@ -493,22 +474,22 @@ nv50_graph_construct_mmio(struct nouveau_grctx *ctx) cp_ctx(ctx, 0x40502c, 0x1); /* 6000? */ - if (dev_priv->chipset == 0x50) + if (device->chipset == 0x50) cp_ctx(ctx, 0x4063e0, 0x1); /* 6800: M2MF */ - if (dev_priv->chipset < 0x90) { + if (device->chipset < 0x90) { cp_ctx(ctx, 0x406814, 0x2b); gr_def(ctx, 0x406818, 0x00000f80); gr_def(ctx, 0x406860, 0x007f0080); gr_def(ctx, 0x40689c, 0x007f0080); } else { cp_ctx(ctx, 0x406814, 0x4); - if (dev_priv->chipset == 0x98) + if (device->chipset == 0x98) gr_def(ctx, 0x406818, 0x00000f80); else gr_def(ctx, 0x406818, 0x00001f80); - if (IS_NVA3F(dev_priv->chipset)) + if (IS_NVA3F(device->chipset)) gr_def(ctx, 0x40681c, 0x00000030); cp_ctx(ctx, 0x406830, 0x3); } @@ -517,43 +498,43 @@ nv50_graph_construct_mmio(struct nouveau_grctx *ctx) for (i = 0; i < 8; i++) { if (units & (1<<(i+16))) { cp_ctx(ctx, 0x407000 + (i<<8), 3); - if (dev_priv->chipset == 0x50) + if (device->chipset == 0x50) gr_def(ctx, 0x407000 + (i<<8), 0x1b74f820); - else if (dev_priv->chipset != 0xa5) + else if (device->chipset != 0xa5) gr_def(ctx, 0x407000 + (i<<8), 0x3b74f821); else gr_def(ctx, 0x407000 + (i<<8), 0x7b74f821); gr_def(ctx, 0x407004 + (i<<8), 0x89058001); - if (dev_priv->chipset == 0x50) { + if (device->chipset == 0x50) { cp_ctx(ctx, 0x407010 + (i<<8), 1); - } else if (dev_priv->chipset < 0xa0) { + } else if (device->chipset < 0xa0) { cp_ctx(ctx, 0x407010 + (i<<8), 2); gr_def(ctx, 0x407010 + (i<<8), 0x00001000); gr_def(ctx, 0x407014 + (i<<8), 0x0000001f); } else { cp_ctx(ctx, 0x407010 + (i<<8), 3); gr_def(ctx, 0x407010 + (i<<8), 0x00001000); - if (dev_priv->chipset != 0xa5) + if (device->chipset != 0xa5) gr_def(ctx, 0x407014 + (i<<8), 0x000000ff); else gr_def(ctx, 0x407014 + (i<<8), 0x000001ff); } cp_ctx(ctx, 0x407080 + (i<<8), 4); - if (dev_priv->chipset != 0xa5) + if (device->chipset != 0xa5) gr_def(ctx, 0x407080 + (i<<8), 0x027c10fa); else gr_def(ctx, 0x407080 + (i<<8), 0x827c10fa); - if (dev_priv->chipset == 0x50) + if (device->chipset == 0x50) gr_def(ctx, 0x407084 + (i<<8), 0x000000c0); else gr_def(ctx, 0x407084 + (i<<8), 0x400000c0); gr_def(ctx, 0x407088 + (i<<8), 0xb7892080); - if (dev_priv->chipset < 0xa0) + if (device->chipset < 0xa0) cp_ctx(ctx, 0x407094 + (i<<8), 1); - else if (!IS_NVA3F(dev_priv->chipset)) + else if (!IS_NVA3F(device->chipset)) cp_ctx(ctx, 0x407094 + (i<<8), 3); else { cp_ctx(ctx, 0x407094 + (i<<8), 4); @@ -563,30 +544,30 @@ nv50_graph_construct_mmio(struct nouveau_grctx *ctx) } cp_ctx(ctx, 0x407c00, 0x3); - if (dev_priv->chipset < 0x90) + if (device->chipset < 0x90) gr_def(ctx, 0x407c00, 0x00010040); - else if (dev_priv->chipset < 0xa0) + else if (device->chipset < 0xa0) gr_def(ctx, 0x407c00, 0x00390040); else gr_def(ctx, 0x407c00, 0x003d0040); gr_def(ctx, 0x407c08, 0x00000022); - if (dev_priv->chipset >= 0xa0) { + if (device->chipset >= 0xa0) { cp_ctx(ctx, 0x407c10, 0x3); cp_ctx(ctx, 0x407c20, 0x1); cp_ctx(ctx, 0x407c2c, 0x1); } - if (dev_priv->chipset < 0xa0) { + if (device->chipset < 0xa0) { cp_ctx(ctx, 0x407d00, 0x9); } else { cp_ctx(ctx, 0x407d00, 0x15); } - if (dev_priv->chipset == 0x98) + if (device->chipset == 0x98) gr_def(ctx, 0x407d08, 0x00380040); else { - if (dev_priv->chipset < 0x90) + if (device->chipset < 0x90) gr_def(ctx, 0x407d08, 0x00010040); - else if (dev_priv->chipset < 0xa0) + else if (device->chipset < 0xa0) gr_def(ctx, 0x407d08, 0x00390040); else gr_def(ctx, 0x407d08, 0x003d0040); @@ -596,11 +577,11 @@ nv50_graph_construct_mmio(struct nouveau_grctx *ctx) /* 8000+: per-TP state */ for (i = 0; i < 10; i++) { if (units & (1<chipset < 0xa0) + if (device->chipset < 0xa0) base = 0x408000 + (i<<12); else base = 0x408000 + (i<<11); - if (dev_priv->chipset < 0xa0) + if (device->chipset < 0xa0) offset = base + 0xc00; else offset = base + 0x80; @@ -609,9 +590,9 @@ nv50_graph_construct_mmio(struct nouveau_grctx *ctx) cp_ctx(ctx, offset + 0x08, 1); /* per-MP state */ - for (j = 0; j < (dev_priv->chipset < 0xa0 ? 2 : 4); j++) { + for (j = 0; j < (device->chipset < 0xa0 ? 2 : 4); j++) { if (!(units & (1 << (j+24)))) continue; - if (dev_priv->chipset < 0xa0) + if (device->chipset < 0xa0) offset = base + 0x200 + (j<<7); else offset = base + 0x100 + (j<<7); @@ -620,7 +601,7 @@ nv50_graph_construct_mmio(struct nouveau_grctx *ctx) gr_def(ctx, offset + 0x04, 0x00160000); gr_def(ctx, offset + 0x08, 0x01800000); gr_def(ctx, offset + 0x18, 0x0003ffff); - switch (dev_priv->chipset) { + switch (device->chipset) { case 0x50: gr_def(ctx, offset + 0x1c, 0x00080000); break; @@ -651,53 +632,53 @@ nv50_graph_construct_mmio(struct nouveau_grctx *ctx) break; } gr_def(ctx, offset + 0x40, 0x00010401); - if (dev_priv->chipset == 0x50) + if (device->chipset == 0x50) gr_def(ctx, offset + 0x48, 0x00000040); else gr_def(ctx, offset + 0x48, 0x00000078); gr_def(ctx, offset + 0x50, 0x000000bf); gr_def(ctx, offset + 0x58, 0x00001210); - if (dev_priv->chipset == 0x50) + if (device->chipset == 0x50) gr_def(ctx, offset + 0x5c, 0x00000080); else gr_def(ctx, offset + 0x5c, 0x08000080); - if (dev_priv->chipset >= 0xa0) + if (device->chipset >= 0xa0) gr_def(ctx, offset + 0x68, 0x0000003e); } - if (dev_priv->chipset < 0xa0) + if (device->chipset < 0xa0) cp_ctx(ctx, base + 0x300, 0x4); else cp_ctx(ctx, base + 0x300, 0x5); - if (dev_priv->chipset == 0x50) + if (device->chipset == 0x50) gr_def(ctx, base + 0x304, 0x00007070); - else if (dev_priv->chipset < 0xa0) + else if (device->chipset < 0xa0) gr_def(ctx, base + 0x304, 0x00027070); - else if (!IS_NVA3F(dev_priv->chipset)) + else if (!IS_NVA3F(device->chipset)) gr_def(ctx, base + 0x304, 0x01127070); else gr_def(ctx, base + 0x304, 0x05127070); - if (dev_priv->chipset < 0xa0) + if (device->chipset < 0xa0) cp_ctx(ctx, base + 0x318, 1); else cp_ctx(ctx, base + 0x320, 1); - if (dev_priv->chipset == 0x50) + if (device->chipset == 0x50) gr_def(ctx, base + 0x318, 0x0003ffff); - else if (dev_priv->chipset < 0xa0) + else if (device->chipset < 0xa0) gr_def(ctx, base + 0x318, 0x03ffffff); else gr_def(ctx, base + 0x320, 0x07ffffff); - if (dev_priv->chipset < 0xa0) + if (device->chipset < 0xa0) cp_ctx(ctx, base + 0x324, 5); else cp_ctx(ctx, base + 0x328, 4); - if (dev_priv->chipset < 0xa0) { + if (device->chipset < 0xa0) { cp_ctx(ctx, base + 0x340, 9); offset = base + 0x340; - } else if (!IS_NVA3F(dev_priv->chipset)) { + } else if (!IS_NVA3F(device->chipset)) { cp_ctx(ctx, base + 0x33c, 0xb); offset = base + 0x344; } else { @@ -706,12 +687,12 @@ nv50_graph_construct_mmio(struct nouveau_grctx *ctx) } gr_def(ctx, offset + 0x0, 0x00120407); gr_def(ctx, offset + 0x4, 0x05091507); - if (dev_priv->chipset == 0x84) + if (device->chipset == 0x84) gr_def(ctx, offset + 0x8, 0x05100202); else gr_def(ctx, offset + 0x8, 0x05010202); gr_def(ctx, offset + 0xc, 0x00030201); - if (dev_priv->chipset == 0xa3) + if (device->chipset == 0xa3) cp_ctx(ctx, base + 0x36c, 1); cp_ctx(ctx, base + 0x400, 2); @@ -720,7 +701,7 @@ nv50_graph_construct_mmio(struct nouveau_grctx *ctx) gr_def(ctx, base + 0x40c, 0x0d0c0b0a); gr_def(ctx, base + 0x410, 0x00141210); - if (dev_priv->chipset < 0xa0) + if (device->chipset < 0xa0) offset = base + 0x800; else offset = base + 0x500; @@ -728,55 +709,55 @@ nv50_graph_construct_mmio(struct nouveau_grctx *ctx) gr_def(ctx, offset + 0x0, 0x000001f0); gr_def(ctx, offset + 0x4, 0x00000001); gr_def(ctx, offset + 0x8, 0x00000003); - if (dev_priv->chipset == 0x50 || IS_NVAAF(dev_priv->chipset)) + if (device->chipset == 0x50 || IS_NVAAF(device->chipset)) gr_def(ctx, offset + 0xc, 0x00008000); gr_def(ctx, offset + 0x14, 0x00039e00); cp_ctx(ctx, offset + 0x1c, 2); - if (dev_priv->chipset == 0x50) + if (device->chipset == 0x50) gr_def(ctx, offset + 0x1c, 0x00000040); else gr_def(ctx, offset + 0x1c, 0x00000100); gr_def(ctx, offset + 0x20, 0x00003800); - if (dev_priv->chipset >= 0xa0) { + if (device->chipset >= 0xa0) { cp_ctx(ctx, base + 0x54c, 2); - if (!IS_NVA3F(dev_priv->chipset)) + if (!IS_NVA3F(device->chipset)) gr_def(ctx, base + 0x54c, 0x003fe006); else gr_def(ctx, base + 0x54c, 0x003fe007); gr_def(ctx, base + 0x550, 0x003fe000); } - if (dev_priv->chipset < 0xa0) + if (device->chipset < 0xa0) offset = base + 0xa00; else offset = base + 0x680; cp_ctx(ctx, offset, 1); gr_def(ctx, offset, 0x00404040); - if (dev_priv->chipset < 0xa0) + if (device->chipset < 0xa0) offset = base + 0xe00; else offset = base + 0x700; cp_ctx(ctx, offset, 2); - if (dev_priv->chipset < 0xa0) + if (device->chipset < 0xa0) gr_def(ctx, offset, 0x0077f005); - else if (dev_priv->chipset == 0xa5) + else if (device->chipset == 0xa5) gr_def(ctx, offset, 0x6cf7f007); - else if (dev_priv->chipset == 0xa8) + else if (device->chipset == 0xa8) gr_def(ctx, offset, 0x6cfff007); - else if (dev_priv->chipset == 0xac) + else if (device->chipset == 0xac) gr_def(ctx, offset, 0x0cfff007); else gr_def(ctx, offset, 0x0cf7f007); - if (dev_priv->chipset == 0x50) + if (device->chipset == 0x50) gr_def(ctx, offset + 0x4, 0x00007fff); - else if (dev_priv->chipset < 0xa0) + else if (device->chipset < 0xa0) gr_def(ctx, offset + 0x4, 0x003f7fff); else gr_def(ctx, offset + 0x4, 0x02bf7fff); cp_ctx(ctx, offset + 0x2c, 1); - if (dev_priv->chipset == 0x50) { + if (device->chipset == 0x50) { cp_ctx(ctx, offset + 0x50, 9); gr_def(ctx, offset + 0x54, 0x000003ff); gr_def(ctx, offset + 0x58, 0x00000003); @@ -785,7 +766,7 @@ nv50_graph_construct_mmio(struct nouveau_grctx *ctx) gr_def(ctx, offset + 0x64, 0x0000001f); gr_def(ctx, offset + 0x68, 0x0000000f); gr_def(ctx, offset + 0x6c, 0x0000000f); - } else if (dev_priv->chipset < 0xa0) { + } else if (device->chipset < 0xa0) { cp_ctx(ctx, offset + 0x50, 1); cp_ctx(ctx, offset + 0x70, 1); } else { @@ -797,7 +778,7 @@ nv50_graph_construct_mmio(struct nouveau_grctx *ctx) } static void -dd_emit(struct nouveau_grctx *ctx, int num, uint32_t val) { +dd_emit(struct nouveau_grctx *ctx, int num, u32 val) { int i; if (val && ctx->mode == NOUVEAU_GRCTX_VALS) for (i = 0; i < num; i++) @@ -808,7 +789,7 @@ dd_emit(struct nouveau_grctx *ctx, int num, uint32_t val) { static void nv50_graph_construct_mmio_ddata(struct nouveau_grctx *ctx) { - struct drm_nouveau_private *dev_priv = ctx->dev->dev_private; + struct nouveau_device *device = ctx->device; int base, num; base = ctx->ctxvals_pos; @@ -822,7 +803,7 @@ nv50_graph_construct_mmio_ddata(struct nouveau_grctx *ctx) dd_emit(ctx, 1, 1); /* 00000001 SRC_LINEAR #1 */ dd_emit(ctx, 1, 0); /* 000000ff SRC_ADDRESS_HIGH */ dd_emit(ctx, 1, 0); /* 00000001 SRC_SRGB */ - if (dev_priv->chipset >= 0x94) + if (device->chipset >= 0x94) dd_emit(ctx, 1, 0); /* 00000003 eng2d UNK0258 */ dd_emit(ctx, 1, 1); /* 00000fff SRC_DEPTH */ dd_emit(ctx, 1, 0x100); /* 0000ffff SRC_HEIGHT */ @@ -851,7 +832,7 @@ nv50_graph_construct_mmio_ddata(struct nouveau_grctx *ctx) dd_emit(ctx, 1, 1); /* 0000007f BLOCKDIM_Z */ dd_emit(ctx, 1, 4); /* 000000ff CP_REG_ALLOC_TEMP */ dd_emit(ctx, 1, 1); /* 00000001 BLOCKDIM_DIRTY */ - if (IS_NVA3F(dev_priv->chipset)) + if (IS_NVA3F(device->chipset)) dd_emit(ctx, 1, 0); /* 00000003 UNK03E8 */ dd_emit(ctx, 1, 1); /* 0000007f BLOCK_ALLOC_HALFWARPS */ dd_emit(ctx, 1, 1); /* 00000007 LOCAL_WARPS_NO_CLAMP */ @@ -863,7 +844,7 @@ nv50_graph_construct_mmio_ddata(struct nouveau_grctx *ctx) dd_emit(ctx, 1, 1); /* 000007ff BLOCK_ALLOC_THREADS */ /* compat 2d state */ - if (dev_priv->chipset == 0x50) { + if (device->chipset == 0x50) { dd_emit(ctx, 4, 0); /* 0000ffff clip X, Y, W, H */ dd_emit(ctx, 1, 1); /* ffffffff chroma COLOR_FORMAT */ @@ -923,7 +904,7 @@ nv50_graph_construct_mmio_ddata(struct nouveau_grctx *ctx) dd_emit(ctx, 1, 0x100); /* ffffffff m2mf TILING_PITCH_IN */ /* more compat 2d state */ - if (dev_priv->chipset == 0x50) { + if (device->chipset == 0x50) { dd_emit(ctx, 1, 1); /* ffffffff line COLOR_FORMAT */ dd_emit(ctx, 1, 0); /* ffffffff line OPERATION */ @@ -957,18 +938,18 @@ nv50_graph_construct_mmio_ddata(struct nouveau_grctx *ctx) dd_emit(ctx, 1, 0); /* 000000ff UNK12B0_2 */ dd_emit(ctx, 1, 0); /* 0000000f FP_TEXTURES_LOG2 */ dd_emit(ctx, 1, 0); /* 0000000f FP_SAMPLERS_LOG2 */ - if (IS_NVA3F(dev_priv->chipset)) { + if (IS_NVA3F(device->chipset)) { dd_emit(ctx, 1, 0); /* ffffffff */ dd_emit(ctx, 1, 0); /* 0000007f MULTISAMPLE_SAMPLES_LOG2 */ } else { dd_emit(ctx, 1, 0); /* 0000000f MULTISAMPLE_SAMPLES_LOG2 */ } dd_emit(ctx, 1, 0xc); /* 000000ff SEMANTIC_COLOR.BFC0_ID */ - if (dev_priv->chipset != 0x50) + if (device->chipset != 0x50) dd_emit(ctx, 1, 0); /* 00000001 SEMANTIC_COLOR.CLMP_EN */ dd_emit(ctx, 1, 8); /* 000000ff SEMANTIC_COLOR.COLR_NR */ dd_emit(ctx, 1, 0x14); /* 000000ff SEMANTIC_COLOR.FFC0_ID */ - if (dev_priv->chipset == 0x50) { + if (device->chipset == 0x50) { dd_emit(ctx, 1, 0); /* 000000ff SEMANTIC_LAYER */ dd_emit(ctx, 1, 0); /* 00000001 */ } else { @@ -994,7 +975,7 @@ nv50_graph_construct_mmio_ddata(struct nouveau_grctx *ctx) dd_emit(ctx, 8, 0); /* ffffffff RT_ADDRESS_LOW */ dd_emit(ctx, 1, 0xcf); /* 000000ff RT_FORMAT */ dd_emit(ctx, 7, 0); /* 000000ff RT_FORMAT */ - if (dev_priv->chipset != 0x50) + if (device->chipset != 0x50) dd_emit(ctx, 3, 0); /* 1, 1, 1 */ else dd_emit(ctx, 2, 0); /* 1, 1 */ @@ -1002,15 +983,15 @@ nv50_graph_construct_mmio_ddata(struct nouveau_grctx *ctx) dd_emit(ctx, 1, 0x80); /* 0000ffff GP_VERTEX_OUTPUT_COUNT*/ dd_emit(ctx, 1, 4); /* 000000ff GP_REG_ALLOC_RESULT */ dd_emit(ctx, 1, 4); /* 000000ff GP_RESULT_MAP_SIZE */ - if (IS_NVA3F(dev_priv->chipset)) { + if (IS_NVA3F(device->chipset)) { dd_emit(ctx, 1, 3); /* 00000003 */ dd_emit(ctx, 1, 0); /* 00000001 UNK1418. Alone. */ } - if (dev_priv->chipset != 0x50) + if (device->chipset != 0x50) dd_emit(ctx, 1, 3); /* 00000003 UNK15AC */ dd_emit(ctx, 1, 1); /* ffffffff RASTERIZE_ENABLE */ dd_emit(ctx, 1, 0); /* 00000001 FP_CONTROL.EXPORTS_Z */ - if (dev_priv->chipset != 0x50) + if (device->chipset != 0x50) dd_emit(ctx, 1, 0); /* 00000001 FP_CONTROL.MULTIPLE_RESULTS */ dd_emit(ctx, 1, 0x12); /* 000000ff FP_INTERPOLANT_CTRL.COUNT */ dd_emit(ctx, 1, 0x10); /* 000000ff FP_INTERPOLANT_CTRL.COUNT_NONFLAT */ @@ -1022,16 +1003,16 @@ nv50_graph_construct_mmio_ddata(struct nouveau_grctx *ctx) dd_emit(ctx, 1, 4); /* 000000ff FP_RESULT_COUNT */ dd_emit(ctx, 1, 2); /* ffffffff REG_MODE */ dd_emit(ctx, 1, 4); /* 000000ff FP_REG_ALLOC_TEMP */ - if (dev_priv->chipset >= 0xa0) + if (device->chipset >= 0xa0) dd_emit(ctx, 1, 0); /* ffffffff */ dd_emit(ctx, 1, 0); /* 00000001 GP_BUILTIN_RESULT_EN.LAYER_IDX */ dd_emit(ctx, 1, 0); /* ffffffff STRMOUT_ENABLE */ dd_emit(ctx, 1, 0x3fffff); /* 003fffff TIC_LIMIT */ dd_emit(ctx, 1, 0x1fff); /* 000fffff TSC_LIMIT */ dd_emit(ctx, 1, 0); /* 00000001 VERTEX_TWO_SIDE_ENABLE*/ - if (dev_priv->chipset != 0x50) + if (device->chipset != 0x50) dd_emit(ctx, 8, 0); /* 00000001 */ - if (dev_priv->chipset >= 0xa0) { + if (device->chipset >= 0xa0) { dd_emit(ctx, 1, 1); /* 00000007 VTX_ATTR_DEFINE.COMP */ dd_emit(ctx, 1, 1); /* 00000007 VTX_ATTR_DEFINE.SIZE */ dd_emit(ctx, 1, 2); /* 00000007 VTX_ATTR_DEFINE.TYPE */ @@ -1042,20 +1023,20 @@ nv50_graph_construct_mmio_ddata(struct nouveau_grctx *ctx) dd_emit(ctx, 1, 1); /* 00000001 ZETA_ENABLE */ dd_emit(ctx, 1, 0); /* 0000000f VP_TEXTURES_LOG2 */ dd_emit(ctx, 1, 0); /* 0000000f VP_SAMPLERS_LOG2 */ - if (IS_NVA3F(dev_priv->chipset)) + if (IS_NVA3F(device->chipset)) dd_emit(ctx, 1, 0); /* 00000001 */ dd_emit(ctx, 1, 2); /* 00000003 POLYGON_MODE_BACK */ - if (dev_priv->chipset >= 0xa0) + if (device->chipset >= 0xa0) dd_emit(ctx, 1, 0); /* 00000003 VTX_ATTR_DEFINE.SIZE - 1 */ dd_emit(ctx, 1, 0); /* 0000ffff CB_ADDR_INDEX */ - if (dev_priv->chipset >= 0xa0) + if (device->chipset >= 0xa0) dd_emit(ctx, 1, 0); /* 00000003 */ dd_emit(ctx, 1, 0); /* 00000001 CULL_FACE_ENABLE */ dd_emit(ctx, 1, 1); /* 00000003 CULL_FACE */ dd_emit(ctx, 1, 0); /* 00000001 FRONT_FACE */ dd_emit(ctx, 1, 2); /* 00000003 POLYGON_MODE_FRONT */ dd_emit(ctx, 1, 0x1000); /* 00007fff UNK141C */ - if (dev_priv->chipset != 0x50) { + if (device->chipset != 0x50) { dd_emit(ctx, 1, 0xe00); /* 7fff */ dd_emit(ctx, 1, 0x1000); /* 7fff */ dd_emit(ctx, 1, 0x1e00); /* 7fff */ @@ -1070,10 +1051,10 @@ nv50_graph_construct_mmio_ddata(struct nouveau_grctx *ctx) dd_emit(ctx, 1, 0); /* 00000001 VTX_ATTR_MASK_UNK0 nonempty */ dd_emit(ctx, 1, 0); /* 00000001 VTX_ATTR_MASK_UNK1 nonempty */ dd_emit(ctx, 1, 0x200); /* 0003ffff GP_VERTEX_OUTPUT_COUNT*GP_REG_ALLOC_RESULT */ - if (IS_NVA3F(dev_priv->chipset)) + if (IS_NVA3F(device->chipset)) dd_emit(ctx, 1, 0x200); dd_emit(ctx, 1, 0); /* 00000001 */ - if (dev_priv->chipset < 0xa0) { + if (device->chipset < 0xa0) { dd_emit(ctx, 1, 1); /* 00000001 */ dd_emit(ctx, 1, 0x70); /* 000000ff */ dd_emit(ctx, 1, 0x80); /* 000000ff */ @@ -1120,7 +1101,7 @@ nv50_graph_construct_mmio_ddata(struct nouveau_grctx *ctx) num = ctx->ctxvals_pos - base; ctx->ctxvals_pos = base; - if (IS_NVA3F(dev_priv->chipset)) + if (IS_NVA3F(device->chipset)) cp_ctx(ctx, 0x404800, num); else cp_ctx(ctx, 0x405400, num); @@ -1169,7 +1150,7 @@ nv50_graph_construct_mmio_ddata(struct nouveau_grctx *ctx) */ static void -xf_emit(struct nouveau_grctx *ctx, int num, uint32_t val) { +xf_emit(struct nouveau_grctx *ctx, int num, u32 val) { int i; if (val && ctx->mode == NOUVEAU_GRCTX_VALS) for (i = 0; i < num; i++) @@ -1201,16 +1182,16 @@ static void nv50_graph_construct_xfer_tp(struct nouveau_grctx *ctx); static void nv50_graph_construct_xfer1(struct nouveau_grctx *ctx) { - struct drm_nouveau_private *dev_priv = ctx->dev->dev_private; + struct nouveau_device *device = ctx->device; int i; int offset; int size = 0; - uint32_t units = nv_rd32 (ctx->dev, 0x1540); + u32 units = nv_rd32 (ctx->device, 0x1540); offset = (ctx->ctxvals_pos+0x3f)&~0x3f; ctx->ctxvals_base = offset; - if (dev_priv->chipset < 0xa0) { + if (device->chipset < 0xa0) { /* Strand 0 */ ctx->ctxvals_pos = offset; nv50_graph_construct_gene_dispatch(ctx); @@ -1280,7 +1261,7 @@ nv50_graph_construct_xfer1(struct nouveau_grctx *ctx) /* Strand 2 */ ctx->ctxvals_pos = offset + 2; - if (dev_priv->chipset == 0xa0) + if (device->chipset == 0xa0) nv50_graph_construct_gene_unk14xx(ctx); nv50_graph_construct_gene_unk24xx(ctx); if ((ctx->ctxvals_pos-offset)/8 > size) @@ -1327,7 +1308,7 @@ nv50_graph_construct_xfer1(struct nouveau_grctx *ctx) /* Strand 7 */ ctx->ctxvals_pos = offset + 7; - if (dev_priv->chipset == 0xa0) { + if (device->chipset == 0xa0) { if (units & (1 << 4)) nv50_graph_construct_xfer_tp(ctx); if (units & (1 << 5)) @@ -1365,24 +1346,24 @@ static void nv50_graph_construct_gene_dispatch(struct nouveau_grctx *ctx) { /* start of strand 0 */ - struct drm_nouveau_private *dev_priv = ctx->dev->dev_private; + struct nouveau_device *device = ctx->device; /* SEEK */ - if (dev_priv->chipset == 0x50) + if (device->chipset == 0x50) xf_emit(ctx, 5, 0); - else if (!IS_NVA3F(dev_priv->chipset)) + else if (!IS_NVA3F(device->chipset)) xf_emit(ctx, 6, 0); else xf_emit(ctx, 4, 0); /* SEEK */ /* the PGRAPH's internal FIFO */ - if (dev_priv->chipset == 0x50) + if (device->chipset == 0x50) xf_emit(ctx, 8*3, 0); else xf_emit(ctx, 0x100*3, 0); /* and another bonus slot?!? */ xf_emit(ctx, 3, 0); /* and YET ANOTHER bonus slot? */ - if (IS_NVA3F(dev_priv->chipset)) + if (IS_NVA3F(device->chipset)) xf_emit(ctx, 3, 0); /* SEEK */ /* CTX_SWITCH: caches of gr objects bound to subchannels. 8 values, last used index */ @@ -1394,7 +1375,7 @@ nv50_graph_construct_gene_dispatch(struct nouveau_grctx *ctx) /* SEEK */ xf_emit(ctx, 9, 0); /* SEEK */ - if (dev_priv->chipset < 0x90) + if (device->chipset < 0x90) xf_emit(ctx, 4, 0); /* SEEK */ xf_emit(ctx, 2, 0); @@ -1407,9 +1388,9 @@ nv50_graph_construct_gene_dispatch(struct nouveau_grctx *ctx) xf_emit(ctx, 6*2, 0); xf_emit(ctx, 2, 0); /* SEEK */ - if (dev_priv->chipset == 0x50) + if (device->chipset == 0x50) xf_emit(ctx, 0x1c, 0); - else if (dev_priv->chipset < 0xa0) + else if (device->chipset < 0xa0) xf_emit(ctx, 0x1e, 0); else xf_emit(ctx, 0x22, 0); @@ -1421,9 +1402,9 @@ static void nv50_graph_construct_gene_m2mf(struct nouveau_grctx *ctx) { /* Strand 0, right after dispatch */ - struct drm_nouveau_private *dev_priv = ctx->dev->dev_private; + struct nouveau_device *device = ctx->device; int smallm2mf = 0; - if (dev_priv->chipset < 0x92 || dev_priv->chipset == 0x98) + if (device->chipset < 0x92 || device->chipset == 0x98) smallm2mf = 1; /* SEEK */ xf_emit (ctx, 1, 0); /* DMA_NOTIFY instance >> 4 */ @@ -1472,10 +1453,10 @@ nv50_graph_construct_gene_m2mf(struct nouveau_grctx *ctx) static void nv50_graph_construct_gene_ccache(struct nouveau_grctx *ctx) { - struct drm_nouveau_private *dev_priv = ctx->dev->dev_private; + struct nouveau_device *device = ctx->device; xf_emit(ctx, 2, 0); /* RO */ xf_emit(ctx, 0x800, 0); /* ffffffff */ - switch (dev_priv->chipset) { + switch (device->chipset) { case 0x50: case 0x92: case 0xa0: @@ -1540,7 +1521,7 @@ nv50_graph_construct_gene_ccache(struct nouveau_grctx *ctx) static void nv50_graph_construct_gene_unk10xx(struct nouveau_grctx *ctx) { - struct drm_nouveau_private *dev_priv = ctx->dev->dev_private; + struct nouveau_device *device = ctx->device; int i; /* end of area 2 on pre-NVA0, area 1 on NVAx */ xf_emit(ctx, 1, 4); /* 000000ff GP_RESULT_MAP_SIZE */ @@ -1550,14 +1531,14 @@ nv50_graph_construct_gene_unk10xx(struct nouveau_grctx *ctx) xf_emit(ctx, 1, 4); /* 000000ff GP_REG_ALLOC_RESULT */ xf_emit(ctx, 1, 0x80c14); /* 01ffffff SEMANTIC_COLOR */ xf_emit(ctx, 1, 0); /* 00000001 VERTEX_TWO_SIDE_ENABLE */ - if (dev_priv->chipset == 0x50) + if (device->chipset == 0x50) xf_emit(ctx, 1, 0x3ff); else xf_emit(ctx, 1, 0x7ff); /* 000007ff */ xf_emit(ctx, 1, 0); /* 111/113 */ xf_emit(ctx, 1, 0); /* ffffffff tesla UNK1A30 */ for (i = 0; i < 8; i++) { - switch (dev_priv->chipset) { + switch (device->chipset) { case 0x50: case 0x86: case 0x98: @@ -1600,7 +1581,7 @@ nv50_graph_construct_gene_unk10xx(struct nouveau_grctx *ctx) static void nv50_graph_construct_gene_unk34xx(struct nouveau_grctx *ctx) { - struct drm_nouveau_private *dev_priv = ctx->dev->dev_private; + struct nouveau_device *device = ctx->device; /* end of area 2 on pre-NVA0, area 1 on NVAx */ xf_emit(ctx, 1, 0); /* 00000001 VIEWPORT_CLIP_RECTS_EN */ xf_emit(ctx, 1, 0); /* 00000003 VIEWPORT_CLIP_MODE */ @@ -1614,9 +1595,9 @@ nv50_graph_construct_gene_unk34xx(struct nouveau_grctx *ctx) xf_emit(ctx, 1, 0); /* 00000003 WINDOW_ORIGIN */ xf_emit(ctx, 1, 0); /* 00000007 */ xf_emit(ctx, 1, 0x1fe21); /* 0001ffff tesla UNK0FAC */ - if (dev_priv->chipset >= 0xa0) + if (device->chipset >= 0xa0) xf_emit(ctx, 1, 0x0fac6881); - if (IS_NVA3F(dev_priv->chipset)) { + if (IS_NVA3F(device->chipset)) { xf_emit(ctx, 1, 1); xf_emit(ctx, 3, 0); } @@ -1625,9 +1606,9 @@ nv50_graph_construct_gene_unk34xx(struct nouveau_grctx *ctx) static void nv50_graph_construct_gene_unk14xx(struct nouveau_grctx *ctx) { - struct drm_nouveau_private *dev_priv = ctx->dev->dev_private; + struct nouveau_device *device = ctx->device; /* middle of area 2 on pre-NVA0, beginning of area 2 on NVA0, area 7 on >NVA0 */ - if (dev_priv->chipset != 0x50) { + if (device->chipset != 0x50) { xf_emit(ctx, 5, 0); /* ffffffff */ xf_emit(ctx, 1, 0x80c14); /* 01ffffff SEMANTIC_COLOR */ xf_emit(ctx, 1, 0); /* 00000001 */ @@ -1643,14 +1624,14 @@ nv50_graph_construct_gene_unk14xx(struct nouveau_grctx *ctx) xf_emit(ctx, 1, 0); /* 00000001 GP_ENABLE */ xf_emit(ctx, 1, 0x10); /* 7f/ff VIEW_VOLUME_CLIP_CTRL */ xf_emit(ctx, 1, 0); /* 000000ff VP_CLIP_DISTANCE_ENABLE */ - if (dev_priv->chipset != 0x50) + if (device->chipset != 0x50) xf_emit(ctx, 1, 0); /* 3ff */ xf_emit(ctx, 1, 0); /* 000000ff tesla UNK1940 */ xf_emit(ctx, 1, 0); /* 00000001 tesla UNK0D7C */ xf_emit(ctx, 1, 0x804); /* 00000fff SEMANTIC_CLIP */ xf_emit(ctx, 1, 1); /* 00000001 VIEWPORT_TRANSFORM_EN */ xf_emit(ctx, 1, 0x1a); /* 0000001f POLYGON_MODE */ - if (dev_priv->chipset != 0x50) + if (device->chipset != 0x50) xf_emit(ctx, 1, 0x7f); /* 000000ff tesla UNK0FFC */ xf_emit(ctx, 1, 0); /* ffffffff tesla UNK1A30 */ xf_emit(ctx, 1, 1); /* 00000001 SHADE_MODEL */ @@ -1669,7 +1650,7 @@ nv50_graph_construct_gene_unk14xx(struct nouveau_grctx *ctx) xf_emit(ctx, 4, 0); /* ffffffff NOPERSPECTIVE_BITMAP */ xf_emit(ctx, 1, 0); /* 00000001 tesla UNK1900 */ xf_emit(ctx, 1, 0); /* 0000000f */ - if (dev_priv->chipset == 0x50) + if (device->chipset == 0x50) xf_emit(ctx, 1, 0x3ff); /* 000003ff tesla UNK0D68 */ else xf_emit(ctx, 1, 0x7ff); /* 000007ff tesla UNK0D68 */ @@ -1704,11 +1685,11 @@ nv50_graph_construct_gene_unk14xx(struct nouveau_grctx *ctx) xf_emit(ctx, 1, 0); /* 00000001 LINE_STIPPLE_ENABLE */ xf_emit(ctx, 1, 0); /* 00000001 LINE_SMOOTH_ENABLE */ xf_emit(ctx, 1, 0); /* 00000007 MULTISAMPLE_SAMPLES_LOG2 */ - if (IS_NVA3F(dev_priv->chipset)) + if (IS_NVA3F(device->chipset)) xf_emit(ctx, 1, 0); /* 00000001 */ xf_emit(ctx, 1, 0x1a); /* 0000001f POLYGON_MODE */ xf_emit(ctx, 1, 0x10); /* 000000ff VIEW_VOLUME_CLIP_CTRL */ - if (dev_priv->chipset != 0x50) { + if (device->chipset != 0x50) { xf_emit(ctx, 1, 0); /* ffffffff */ xf_emit(ctx, 1, 0); /* 00000001 */ xf_emit(ctx, 1, 0); /* 000003ff */ @@ -1736,7 +1717,7 @@ nv50_graph_construct_gene_unk14xx(struct nouveau_grctx *ctx) static void nv50_graph_construct_gene_zcull(struct nouveau_grctx *ctx) { - struct drm_nouveau_private *dev_priv = ctx->dev->dev_private; + struct nouveau_device *device = ctx->device; /* end of strand 0 on pre-NVA0, beginning of strand 6 on NVAx */ /* SEEK */ xf_emit(ctx, 1, 0x3f); /* 0000003f UNK1590 */ @@ -1774,7 +1755,7 @@ nv50_graph_construct_gene_zcull(struct nouveau_grctx *ctx) xf_emit(ctx, 1, 0); /* 00000001 STENCIL_BACK_ENABLE */ xf_emit(ctx, 1, 0); /* ffffffff CLEAR_DEPTH */ xf_emit(ctx, 1, 0); /* 00000007 */ - if (dev_priv->chipset != 0x50) + if (device->chipset != 0x50) xf_emit(ctx, 1, 0); /* 00000003 tesla UNK1108 */ xf_emit(ctx, 1, 0); /* 00000001 SAMPLECNT_ENABLE */ xf_emit(ctx, 1, 0); /* 0000000f ZETA_FORMAT */ @@ -1789,7 +1770,7 @@ nv50_graph_construct_gene_zcull(struct nouveau_grctx *ctx) xf_emit(ctx, 1, 0); /* 00000001 VIEWPORT_CLIP_RECTS_EN */ xf_emit(ctx, 1, 3); /* 00000003 FP_CTRL_UNK196C */ xf_emit(ctx, 1, 0); /* 00000003 tesla UNK1968 */ - if (dev_priv->chipset != 0x50) + if (device->chipset != 0x50) xf_emit(ctx, 1, 0); /* 0fffffff tesla UNK1104 */ xf_emit(ctx, 1, 0); /* 00000001 tesla UNK151C */ } @@ -1817,7 +1798,7 @@ nv50_graph_construct_gene_clipid(struct nouveau_grctx *ctx) static void nv50_graph_construct_gene_unk24xx(struct nouveau_grctx *ctx) { - struct drm_nouveau_private *dev_priv = ctx->dev->dev_private; + struct nouveau_device *device = ctx->device; int i; /* middle of strand 0 on pre-NVA0 [after m2mf], end of strand 2 on NVAx */ /* SEEK */ @@ -1829,7 +1810,7 @@ nv50_graph_construct_gene_unk24xx(struct nouveau_grctx *ctx) xf_emit(ctx, 1, 4); /* 0000007f VP_RESULT_MAP_SIZE */ xf_emit(ctx, 1, 4); /* 000000ff GP_RESULT_MAP_SIZE */ /* SEEK */ - if (IS_NVA3F(dev_priv->chipset)) { + if (IS_NVA3F(device->chipset)) { xf_emit(ctx, 4, 0); /* RO */ xf_emit(ctx, 0xe10, 0); /* 190 * 9: 8*ffffffff, 7ff */ xf_emit(ctx, 1, 0); /* 1ff */ @@ -1860,7 +1841,7 @@ nv50_graph_construct_gene_unk24xx(struct nouveau_grctx *ctx) xf_emit(ctx, 1, 4); /* 000000ff GP_RESULT_MAP_SIZE */ xf_emit(ctx, 1, 4); /* 0000007f VP_RESULT_MAP_SIZE */ xf_emit(ctx, 1, 0x8100c12); /* 1fffffff FP_INTERPOLANT_CTRL */ - if (dev_priv->chipset != 0x50) + if (device->chipset != 0x50) xf_emit(ctx, 1, 3); /* 00000003 tesla UNK1100 */ /* SEEK */ xf_emit(ctx, 1, 0); /* 00000001 GP_ENABLE */ @@ -1869,7 +1850,7 @@ nv50_graph_construct_gene_unk24xx(struct nouveau_grctx *ctx) xf_emit(ctx, 1, 0x80c14); /* 01ffffff SEMANTIC_COLOR */ xf_emit(ctx, 1, 1); /* 00000001 */ /* SEEK */ - if (dev_priv->chipset >= 0xa0) + if (device->chipset >= 0xa0) xf_emit(ctx, 2, 4); /* 000000ff */ xf_emit(ctx, 1, 0x80c14); /* 01ffffff SEMANTIC_COLOR */ xf_emit(ctx, 1, 0); /* 00000001 VERTEX_TWO_SIDE_ENABLE */ @@ -1893,20 +1874,20 @@ nv50_graph_construct_gene_unk24xx(struct nouveau_grctx *ctx) xf_emit(ctx, 0x10, 0); /* 00ffffff POINT_COORD_REPLACE_MAP */ xf_emit(ctx, 1, 0); /* 00000003 WINDOW_ORIGIN */ xf_emit(ctx, 1, 0x8100c12); /* 1fffffff FP_INTERPOLANT_CTRL */ - if (dev_priv->chipset != 0x50) + if (device->chipset != 0x50) xf_emit(ctx, 1, 0); /* 000003ff */ } static void nv50_graph_construct_gene_vfetch(struct nouveau_grctx *ctx) { - struct drm_nouveau_private *dev_priv = ctx->dev->dev_private; + struct nouveau_device *device = ctx->device; int acnt = 0x10, rep, i; /* beginning of strand 1 on pre-NVA0, strand 3 on NVAx */ - if (IS_NVA3F(dev_priv->chipset)) + if (IS_NVA3F(device->chipset)) acnt = 0x20; /* SEEK */ - if (dev_priv->chipset >= 0xa0) { + if (device->chipset >= 0xa0) { xf_emit(ctx, 1, 0); /* ffffffff tesla UNK13A4 */ xf_emit(ctx, 1, 1); /* 00000fff tesla UNK1318 */ } @@ -1923,9 +1904,9 @@ nv50_graph_construct_gene_vfetch(struct nouveau_grctx *ctx) xf_emit(ctx, 1, 0); /* 0000ffff turing USER_PARAM_COUNT */ xf_emit(ctx, 1, 0); /* ffffffff tesla UNK1A30 */ /* SEEK */ - if (IS_NVA3F(dev_priv->chipset)) + if (IS_NVA3F(device->chipset)) xf_emit(ctx, 0xb, 0); /* RO */ - else if (dev_priv->chipset >= 0xa0) + else if (device->chipset >= 0xa0) xf_emit(ctx, 0x9, 0); /* RO */ else xf_emit(ctx, 0x8, 0); /* RO */ @@ -1944,11 +1925,11 @@ nv50_graph_construct_gene_vfetch(struct nouveau_grctx *ctx) xf_emit(ctx, 1, 4); /* 000001ff UNK1A28 */ xf_emit(ctx, 1, 8); /* 000001ff UNK0DF0 */ xf_emit(ctx, 1, 0); /* 00000001 GP_ENABLE */ - if (dev_priv->chipset == 0x50) + if (device->chipset == 0x50) xf_emit(ctx, 1, 0x3ff); /* 3ff tesla UNK0D68 */ else xf_emit(ctx, 1, 0x7ff); /* 7ff tesla UNK0D68 */ - if (dev_priv->chipset == 0xa8) + if (device->chipset == 0xa8) xf_emit(ctx, 1, 0x1e00); /* 7fff */ /* SEEK */ xf_emit(ctx, 0xc, 0); /* RO or close */ @@ -1956,13 +1937,13 @@ nv50_graph_construct_gene_vfetch(struct nouveau_grctx *ctx) xf_emit(ctx, 1, 0xf); /* ffffffff VP_ATTR_EN */ xf_emit(ctx, (acnt/8)-1, 0); /* ffffffff VP_ATTR_EN */ xf_emit(ctx, 1, 0); /* 0000000f VP_GP_BUILTIN_ATTR_EN */ - if (dev_priv->chipset > 0x50 && dev_priv->chipset < 0xa0) + if (device->chipset > 0x50 && device->chipset < 0xa0) xf_emit(ctx, 2, 0); /* ffffffff */ else xf_emit(ctx, 1, 0); /* ffffffff */ xf_emit(ctx, 1, 0); /* 00000003 tesla UNK0FD8 */ /* SEEK */ - if (IS_NVA3F(dev_priv->chipset)) { + if (IS_NVA3F(device->chipset)) { xf_emit(ctx, 0x10, 0); /* 0? */ xf_emit(ctx, 2, 0); /* weird... */ xf_emit(ctx, 2, 0); /* RO */ @@ -1975,7 +1956,7 @@ nv50_graph_construct_gene_vfetch(struct nouveau_grctx *ctx) xf_emit(ctx, 1, 0); /* ffffffff VB_ELEMENT_BASE */ xf_emit(ctx, 1, 0); /* ffffffff UNK1438 */ xf_emit(ctx, acnt, 0); /* 1 tesla UNK1000 */ - if (dev_priv->chipset >= 0xa0) + if (device->chipset >= 0xa0) xf_emit(ctx, 1, 0); /* ffffffff tesla UNK1118? */ /* SEEK */ xf_emit(ctx, acnt, 0); /* ffffffff VERTEX_ARRAY_UNK90C */ @@ -2013,23 +1994,23 @@ nv50_graph_construct_gene_vfetch(struct nouveau_grctx *ctx) xf_emit(ctx, acnt, 0); /* 000000ff VERTEX_LIMIT_HIGH */ xf_emit(ctx, 3, 0); /* f/1f */ /* SEEK */ - if (IS_NVA3F(dev_priv->chipset)) { + if (IS_NVA3F(device->chipset)) { xf_emit(ctx, acnt, 0); /* f */ xf_emit(ctx, 3, 0); /* f/1f */ } /* SEEK */ - if (IS_NVA3F(dev_priv->chipset)) + if (IS_NVA3F(device->chipset)) xf_emit(ctx, 2, 0); /* RO */ else xf_emit(ctx, 5, 0); /* RO */ /* SEEK */ xf_emit(ctx, 1, 0); /* ffff DMA_VTXBUF */ /* SEEK */ - if (dev_priv->chipset < 0xa0) { + if (device->chipset < 0xa0) { xf_emit(ctx, 0x41, 0); /* RO */ /* SEEK */ xf_emit(ctx, 0x11, 0); /* RO */ - } else if (!IS_NVA3F(dev_priv->chipset)) + } else if (!IS_NVA3F(device->chipset)) xf_emit(ctx, 0x50, 0); /* RO */ else xf_emit(ctx, 0x58, 0); /* RO */ @@ -2041,7 +2022,7 @@ nv50_graph_construct_gene_vfetch(struct nouveau_grctx *ctx) xf_emit(ctx, acnt*4, 0); /* ffffffff VTX_ATTR */ xf_emit(ctx, 4, 0); /* f/1f, 0, 0, 0 */ /* SEEK */ - if (IS_NVA3F(dev_priv->chipset)) + if (IS_NVA3F(device->chipset)) xf_emit(ctx, 0x1d, 0); /* RO */ else xf_emit(ctx, 0x16, 0); /* RO */ @@ -2049,21 +2030,21 @@ nv50_graph_construct_gene_vfetch(struct nouveau_grctx *ctx) xf_emit(ctx, 1, 0xf); /* ffffffff VP_ATTR_EN */ xf_emit(ctx, (acnt/8)-1, 0); /* ffffffff VP_ATTR_EN */ /* SEEK */ - if (dev_priv->chipset < 0xa0) + if (device->chipset < 0xa0) xf_emit(ctx, 8, 0); /* RO */ - else if (IS_NVA3F(dev_priv->chipset)) + else if (IS_NVA3F(device->chipset)) xf_emit(ctx, 0xc, 0); /* RO */ else xf_emit(ctx, 7, 0); /* RO */ /* SEEK */ xf_emit(ctx, 0xa, 0); /* RO */ - if (dev_priv->chipset == 0xa0) + if (device->chipset == 0xa0) rep = 0xc; else rep = 4; for (i = 0; i < rep; i++) { /* SEEK */ - if (IS_NVA3F(dev_priv->chipset)) + if (IS_NVA3F(device->chipset)) xf_emit(ctx, 0x20, 0); /* ffffffff */ xf_emit(ctx, 0x200, 0); /* ffffffff */ xf_emit(ctx, 4, 0); /* 7f/ff, 0, 0, 0 */ @@ -2077,7 +2058,7 @@ nv50_graph_construct_gene_vfetch(struct nouveau_grctx *ctx) xf_emit(ctx, 1, 0); /* 0000000f VP_GP_BUILTIN_ATTR_EN */ xf_emit(ctx, 1, 0); /* ffffffff tesla UNK1A30 */ /* SEEK */ - if (IS_NVA3F(dev_priv->chipset)) + if (IS_NVA3F(device->chipset)) xf_emit(ctx, 7, 0); /* weird... */ else xf_emit(ctx, 5, 0); /* weird... */ @@ -2086,13 +2067,13 @@ nv50_graph_construct_gene_vfetch(struct nouveau_grctx *ctx) static void nv50_graph_construct_gene_eng2d(struct nouveau_grctx *ctx) { - struct drm_nouveau_private *dev_priv = ctx->dev->dev_private; + struct nouveau_device *device = ctx->device; /* middle of strand 1 on pre-NVA0 [after vfetch], middle of strand 6 on NVAx */ /* SEEK */ xf_emit(ctx, 2, 0); /* 0001ffff CLIP_X, CLIP_Y */ xf_emit(ctx, 2, 0); /* 0000ffff CLIP_W, CLIP_H */ xf_emit(ctx, 1, 0); /* 00000001 CLIP_ENABLE */ - if (dev_priv->chipset < 0xa0) { + if (device->chipset < 0xa0) { /* this is useless on everything but the original NV50, * guess they forgot to nuke it. Or just didn't bother. */ xf_emit(ctx, 2, 0); /* 0000ffff IFC_CLIP_X, Y */ @@ -2148,7 +2129,7 @@ nv50_graph_construct_gene_eng2d(struct nouveau_grctx *ctx) static void nv50_graph_construct_gene_csched(struct nouveau_grctx *ctx) { - struct drm_nouveau_private *dev_priv = ctx->dev->dev_private; + struct nouveau_device *device = ctx->device; /* middle of strand 1 on pre-NVA0 [after eng2d], middle of strand 0 on NVAx */ /* SEEK */ xf_emit(ctx, 2, 0); /* 00007fff WINDOW_OFFSET_XY... what is it doing here??? */ @@ -2173,7 +2154,7 @@ nv50_graph_construct_gene_csched(struct nouveau_grctx *ctx) xf_emit(ctx, 1, 2); /* 00000003 REG_MODE */ /* SEEK */ xf_emit(ctx, 0x40, 0); /* ffffffff USER_PARAM */ - switch (dev_priv->chipset) { + switch (device->chipset) { case 0x50: case 0x92: xf_emit(ctx, 8, 0); /* 7, 0, 0, 0, ... */ @@ -2247,7 +2228,7 @@ nv50_graph_construct_gene_csched(struct nouveau_grctx *ctx) static void nv50_graph_construct_gene_unk1cxx(struct nouveau_grctx *ctx) { - struct drm_nouveau_private *dev_priv = ctx->dev->dev_private; + struct nouveau_device *device = ctx->device; xf_emit(ctx, 2, 0); /* 00007fff WINDOW_OFFSET_XY */ xf_emit(ctx, 1, 0x3f800000); /* ffffffff LINE_WIDTH */ xf_emit(ctx, 1, 0); /* 00000001 LINE_SMOOTH_ENABLE */ @@ -2277,9 +2258,9 @@ nv50_graph_construct_gene_unk1cxx(struct nouveau_grctx *ctx) xf_emit(ctx, 1, 4); /* 00000007 FP_CONTROL */ xf_emit(ctx, 1, 0); /* 00000001 ALPHA_TEST_ENABLE */ xf_emit(ctx, 1, 0); /* 00000007 ALPHA_TEST_FUNC */ - if (IS_NVA3F(dev_priv->chipset)) + if (IS_NVA3F(device->chipset)) xf_emit(ctx, 1, 3); /* 00000003 UNK16B4 */ - else if (dev_priv->chipset >= 0xa0) + else if (device->chipset >= 0xa0) xf_emit(ctx, 1, 1); /* 00000001 UNK16B4 */ xf_emit(ctx, 1, 0); /* 00000003 MULTISAMPLE_CTRL */ xf_emit(ctx, 1, 0); /* 00000003 tesla UNK0F90 */ @@ -2293,11 +2274,11 @@ nv50_graph_construct_gene_unk1cxx(struct nouveau_grctx *ctx) xf_emit(ctx, 1, 0); /* ffffffff POINT_SIZE */ xf_emit(ctx, 1, 0); /* 00000001 */ xf_emit(ctx, 1, 0); /* 00000007 tesla UNK0FB4 */ - if (dev_priv->chipset != 0x50) { + if (device->chipset != 0x50) { xf_emit(ctx, 1, 0); /* 3ff */ xf_emit(ctx, 1, 1); /* 00000001 tesla UNK1110 */ } - if (IS_NVA3F(dev_priv->chipset)) + if (IS_NVA3F(device->chipset)) xf_emit(ctx, 1, 0); /* 00000003 tesla UNK1928 */ xf_emit(ctx, 0x10, 0); /* ffffffff DEPTH_RANGE_NEAR */ xf_emit(ctx, 0x10, 0x3f800000); /* ffffffff DEPTH_RANGE_FAR */ @@ -2316,11 +2297,11 @@ nv50_graph_construct_gene_unk1cxx(struct nouveau_grctx *ctx) xf_emit(ctx, 1, 1); /* 00000001 ZETA_ENABLE */ xf_emit(ctx, 1, 0); /* 00000001 VERTEX_TWO_SIDE_ENABLE */ xf_emit(ctx, 4, 0xffff); /* 0000ffff MSAA_MASK */ - if (dev_priv->chipset != 0x50) + if (device->chipset != 0x50) xf_emit(ctx, 1, 3); /* 00000003 tesla UNK1100 */ - if (dev_priv->chipset < 0xa0) + if (device->chipset < 0xa0) xf_emit(ctx, 0x1c, 0); /* RO */ - else if (IS_NVA3F(dev_priv->chipset)) + else if (IS_NVA3F(device->chipset)) xf_emit(ctx, 0x9, 0); xf_emit(ctx, 1, 0); /* 00000001 UNK1534 */ xf_emit(ctx, 1, 0); /* 00000001 LINE_SMOOTH_ENABLE */ @@ -2328,13 +2309,13 @@ nv50_graph_construct_gene_unk1cxx(struct nouveau_grctx *ctx) xf_emit(ctx, 1, 0x00ffff00); /* 00ffffff LINE_STIPPLE_PATTERN */ xf_emit(ctx, 1, 0x1a); /* 0000001f POLYGON_MODE */ xf_emit(ctx, 1, 0); /* 00000003 WINDOW_ORIGIN */ - if (dev_priv->chipset != 0x50) { + if (device->chipset != 0x50) { xf_emit(ctx, 1, 3); /* 00000003 tesla UNK1100 */ xf_emit(ctx, 1, 0); /* 3ff */ } /* XXX: the following block could belong either to unk1cxx, or * to STRMOUT. Rather hard to tell. */ - if (dev_priv->chipset < 0xa0) + if (device->chipset < 0xa0) xf_emit(ctx, 0x25, 0); else xf_emit(ctx, 0x3b, 0); @@ -2343,18 +2324,18 @@ nv50_graph_construct_gene_unk1cxx(struct nouveau_grctx *ctx) static void nv50_graph_construct_gene_strmout(struct nouveau_grctx *ctx) { - struct drm_nouveau_private *dev_priv = ctx->dev->dev_private; + struct nouveau_device *device = ctx->device; xf_emit(ctx, 1, 0x102); /* 0000ffff STRMOUT_BUFFER_CTRL */ xf_emit(ctx, 1, 0); /* ffffffff STRMOUT_PRIMITIVE_COUNT */ xf_emit(ctx, 4, 4); /* 000000ff STRMOUT_NUM_ATTRIBS */ - if (dev_priv->chipset >= 0xa0) { + if (device->chipset >= 0xa0) { xf_emit(ctx, 4, 0); /* ffffffff UNK1A8C */ xf_emit(ctx, 4, 0); /* ffffffff UNK1780 */ } xf_emit(ctx, 1, 4); /* 000000ff GP_RESULT_MAP_SIZE */ xf_emit(ctx, 1, 4); /* 0000007f VP_RESULT_MAP_SIZE */ xf_emit(ctx, 1, 0); /* 00000001 GP_ENABLE */ - if (dev_priv->chipset == 0x50) + if (device->chipset == 0x50) xf_emit(ctx, 1, 0x3ff); /* 000003ff tesla UNK0D68 */ else xf_emit(ctx, 1, 0x7ff); /* 000007ff tesla UNK0D68 */ @@ -2365,7 +2346,7 @@ nv50_graph_construct_gene_strmout(struct nouveau_grctx *ctx) xf_emit(ctx, 4, 0); /* 000000ff STRMOUT_ADDRESS_HIGH */ xf_emit(ctx, 4, 0); /* ffffffff STRMOUT_ADDRESS_LOW */ xf_emit(ctx, 4, 4); /* 000000ff STRMOUT_NUM_ATTRIBS */ - if (dev_priv->chipset >= 0xa0) { + if (device->chipset >= 0xa0) { xf_emit(ctx, 4, 0); /* ffffffff UNK1A8C */ xf_emit(ctx, 4, 0); /* ffffffff UNK1780 */ } @@ -2385,12 +2366,12 @@ nv50_graph_construct_gene_strmout(struct nouveau_grctx *ctx) static void nv50_graph_construct_gene_ropm1(struct nouveau_grctx *ctx) { - struct drm_nouveau_private *dev_priv = ctx->dev->dev_private; + struct nouveau_device *device = ctx->device; xf_emit(ctx, 1, 0x4e3bfdf); /* ffffffff UNK0D64 */ xf_emit(ctx, 1, 0x4e3bfdf); /* ffffffff UNK0DF4 */ xf_emit(ctx, 1, 0); /* 00000007 */ xf_emit(ctx, 1, 0); /* 000003ff */ - if (IS_NVA3F(dev_priv->chipset)) + if (IS_NVA3F(device->chipset)) xf_emit(ctx, 1, 0x11); /* 000000ff tesla UNK1968 */ xf_emit(ctx, 1, 0); /* ffffffff tesla UNK1A3C */ } @@ -2398,7 +2379,7 @@ nv50_graph_construct_gene_ropm1(struct nouveau_grctx *ctx) static void nv50_graph_construct_gene_ropm2(struct nouveau_grctx *ctx) { - struct drm_nouveau_private *dev_priv = ctx->dev->dev_private; + struct nouveau_device *device = ctx->device; /* SEEK */ xf_emit(ctx, 1, 0); /* 0000ffff DMA_QUERY */ xf_emit(ctx, 1, 0x0fac6881); /* 0fffffff RT_CONTROL */ @@ -2416,7 +2397,7 @@ nv50_graph_construct_gene_ropm2(struct nouveau_grctx *ctx) xf_emit(ctx, 1, 0); /* 00000001 eng2d UNK260 */ xf_emit(ctx, 1, 0); /* ff/3ff */ xf_emit(ctx, 1, 0); /* 00000007 */ - if (IS_NVA3F(dev_priv->chipset)) + if (IS_NVA3F(device->chipset)) xf_emit(ctx, 1, 0x11); /* 000000ff tesla UNK1968 */ xf_emit(ctx, 1, 0); /* ffffffff tesla UNK1A3C */ } @@ -2424,11 +2405,11 @@ nv50_graph_construct_gene_ropm2(struct nouveau_grctx *ctx) static void nv50_graph_construct_gene_ropc(struct nouveau_grctx *ctx) { - struct drm_nouveau_private *dev_priv = ctx->dev->dev_private; + struct nouveau_device *device = ctx->device; int magic2; - if (dev_priv->chipset == 0x50) { + if (device->chipset == 0x50) { magic2 = 0x00003e60; - } else if (!IS_NVA3F(dev_priv->chipset)) { + } else if (!IS_NVA3F(device->chipset)) { magic2 = 0x001ffe67; } else { magic2 = 0x00087e67; @@ -2446,14 +2427,14 @@ nv50_graph_construct_gene_ropc(struct nouveau_grctx *ctx) xf_emit(ctx, 1, 0); /* 00000007 DEPTH_TEST_FUNC */ xf_emit(ctx, 1, 0); /* 00000001 DEPTH_TEST_ENABLE */ xf_emit(ctx, 1, 0); /* 00000001 DEPTH_WRITE_ENABLE */ - if (IS_NVA3F(dev_priv->chipset)) + if (IS_NVA3F(device->chipset)) xf_emit(ctx, 1, 1); /* 0000001f tesla UNK169C */ xf_emit(ctx, 1, 0); /* 00000007 STENCIL_FRONT_FUNC_FUNC */ xf_emit(ctx, 1, 0); /* 000000ff STENCIL_FRONT_FUNC_MASK */ xf_emit(ctx, 1, 0); /* 000000ff STENCIL_FRONT_MASK */ xf_emit(ctx, 3, 0); /* 00000007 STENCIL_FRONT_OP_FAIL, ZFAIL, ZPASS */ xf_emit(ctx, 1, 0); /* 00000001 STENCIL_FRONT_ENABLE */ - if (dev_priv->chipset >= 0xa0 && !IS_NVAAF(dev_priv->chipset)) + if (device->chipset >= 0xa0 && !IS_NVAAF(device->chipset)) xf_emit(ctx, 1, 0x15); /* 000000ff */ xf_emit(ctx, 1, 0); /* 00000001 STENCIL_BACK_ENABLE */ xf_emit(ctx, 1, 1); /* 00000001 tesla UNK15B4 */ @@ -2462,14 +2443,14 @@ nv50_graph_construct_gene_ropc(struct nouveau_grctx *ctx) xf_emit(ctx, 1, 0); /* 0000000f ZETA_FORMAT */ xf_emit(ctx, 1, 1); /* 00000001 ZETA_ENABLE */ xf_emit(ctx, 1, 0); /* ffffffff tesla UNK1A3C */ - if (dev_priv->chipset == 0x86 || dev_priv->chipset == 0x92 || dev_priv->chipset == 0x98 || dev_priv->chipset >= 0xa0) { + if (device->chipset == 0x86 || device->chipset == 0x92 || device->chipset == 0x98 || device->chipset >= 0xa0) { xf_emit(ctx, 3, 0); /* ff, ffffffff, ffffffff */ xf_emit(ctx, 1, 4); /* 7 */ xf_emit(ctx, 1, 0x400); /* fffffff */ xf_emit(ctx, 1, 0x300); /* ffff */ xf_emit(ctx, 1, 0x1001); /* 1fff */ - if (dev_priv->chipset != 0xa0) { - if (IS_NVA3F(dev_priv->chipset)) + if (device->chipset != 0xa0) { + if (IS_NVA3F(device->chipset)) xf_emit(ctx, 1, 0); /* 0000000f UNK15C8 */ else xf_emit(ctx, 1, 0x15); /* ff */ @@ -2547,7 +2528,7 @@ nv50_graph_construct_gene_ropc(struct nouveau_grctx *ctx) xf_emit(ctx, 1, 1); /* 00000001 ZETA_ENABLE */ xf_emit(ctx, 1, 0); /* ffffffff CLEAR_DEPTH */ xf_emit(ctx, 1, 1); /* 00000001 tesla UNK19CC */ - if (dev_priv->chipset >= 0xa0) { + if (device->chipset >= 0xa0) { xf_emit(ctx, 2, 0); xf_emit(ctx, 1, 0x1001); xf_emit(ctx, 0xb, 0); @@ -2564,7 +2545,7 @@ nv50_graph_construct_gene_ropc(struct nouveau_grctx *ctx) xf_emit(ctx, 7, 0); /* 0000000f COLOR_MASK */ xf_emit(ctx, 1, 0x11); /* 3f/7f */ xf_emit(ctx, 1, 0); /* 00000001 LOGIC_OP_ENABLE */ - if (dev_priv->chipset != 0x50) { + if (device->chipset != 0x50) { xf_emit(ctx, 1, 0); /* 0000000f LOGIC_OP */ xf_emit(ctx, 1, 0); /* 000000ff */ } @@ -2581,7 +2562,7 @@ nv50_graph_construct_gene_ropc(struct nouveau_grctx *ctx) xf_emit(ctx, 1, magic2); /* 001fffff tesla UNK0F78 */ xf_emit(ctx, 1, 0); /* ffffffff tesla UNK1A3C */ xf_emit(ctx, 1, 0x0fac6881); /* 0fffffff RT_CONTROL */ - if (IS_NVA3F(dev_priv->chipset)) { + if (IS_NVA3F(device->chipset)) { xf_emit(ctx, 1, 0); /* 00000001 tesla UNK12E4 */ xf_emit(ctx, 8, 1); /* 00000007 IBLEND_EQUATION_RGB */ xf_emit(ctx, 8, 1); /* 00000007 IBLEND_EQUATION_ALPHA */ @@ -2600,7 +2581,7 @@ nv50_graph_construct_gene_ropc(struct nouveau_grctx *ctx) xf_emit(ctx, 1, 1); /* 0000001f tesla UNK169C */ xf_emit(ctx, 1, 0); /* 00000001 */ xf_emit(ctx, 1, 0); /* 000003ff */ - } else if (dev_priv->chipset >= 0xa0) { + } else if (device->chipset >= 0xa0) { xf_emit(ctx, 2, 0); /* 00000001 */ xf_emit(ctx, 1, 0); /* 00000007 */ xf_emit(ctx, 1, 0); /* 00000003 */ @@ -2614,7 +2595,7 @@ nv50_graph_construct_gene_ropc(struct nouveau_grctx *ctx) xf_emit(ctx, 4, 0); /* ffffffff CLEAR_COLOR */ xf_emit(ctx, 4, 0); /* ffffffff BLEND_COLOR A R G B */ xf_emit(ctx, 1, 0); /* 00000fff eng2d UNK2B0 */ - if (dev_priv->chipset >= 0xa0) + if (device->chipset >= 0xa0) xf_emit(ctx, 2, 0); /* 00000001 */ xf_emit(ctx, 1, 0); /* 000003ff */ xf_emit(ctx, 8, 0); /* 00000001 BLEND_ENABLE */ @@ -2628,9 +2609,9 @@ nv50_graph_construct_gene_ropc(struct nouveau_grctx *ctx) xf_emit(ctx, 1, 0); /* 00000001 UNK19C0 */ xf_emit(ctx, 1, 0); /* 00000001 LOGIC_OP_ENABLE */ xf_emit(ctx, 1, 0); /* 0000000f LOGIC_OP */ - if (dev_priv->chipset >= 0xa0) + if (device->chipset >= 0xa0) xf_emit(ctx, 1, 0); /* 00000001 UNK12E4? NVA3+ only? */ - if (IS_NVA3F(dev_priv->chipset)) { + if (IS_NVA3F(device->chipset)) { xf_emit(ctx, 8, 1); /* 00000001 IBLEND_UNK00 */ xf_emit(ctx, 8, 1); /* 00000007 IBLEND_EQUATION_RGB */ xf_emit(ctx, 8, 2); /* 0000001f IBLEND_FUNC_SRC_RGB */ @@ -2659,9 +2640,9 @@ nv50_graph_construct_gene_ropc(struct nouveau_grctx *ctx) static void nv50_graph_construct_xfer_unk84xx(struct nouveau_grctx *ctx) { - struct drm_nouveau_private *dev_priv = ctx->dev->dev_private; + struct nouveau_device *device = ctx->device; int magic3; - switch (dev_priv->chipset) { + switch (device->chipset) { case 0x50: magic3 = 0x1000; break; @@ -2681,16 +2662,16 @@ nv50_graph_construct_xfer_unk84xx(struct nouveau_grctx *ctx) xf_emit(ctx, 1, 0); /* 00000001 GP_ENABLE */ xf_emit(ctx, 1, 0); /* ffffffff tesla UNK1A30 */ xf_emit(ctx, 1, 0); /* 111/113[NVA0+] */ - if (IS_NVA3F(dev_priv->chipset)) + if (IS_NVA3F(device->chipset)) xf_emit(ctx, 0x1f, 0); /* ffffffff */ - else if (dev_priv->chipset >= 0xa0) + else if (device->chipset >= 0xa0) xf_emit(ctx, 0x0f, 0); /* ffffffff */ else xf_emit(ctx, 0x10, 0); /* fffffff VP_RESULT_MAP_1 up */ xf_emit(ctx, 2, 0); /* f/1f[NVA3], fffffff/ffffffff[NVA0+] */ xf_emit(ctx, 1, 4); /* 7f/ff VP_REG_ALLOC_RESULT */ xf_emit(ctx, 1, 4); /* 7f/ff VP_RESULT_MAP_SIZE */ - if (dev_priv->chipset >= 0xa0) + if (device->chipset >= 0xa0) xf_emit(ctx, 1, 0x03020100); /* ffffffff */ else xf_emit(ctx, 1, 0x00608080); /* fffffff VP_RESULT_MAP_0 */ @@ -2733,11 +2714,11 @@ nv50_graph_construct_xfer_unk84xx(struct nouveau_grctx *ctx) xf_emit(ctx, 1, 0); /* 00000001 GP_ENABLE */ xf_emit(ctx, 1, 0); /* ffffffff tesla UNK1A30 */ xf_emit(ctx, 1, 0); /* 111/113 */ - if (dev_priv->chipset == 0x94 || dev_priv->chipset == 0x96) + if (device->chipset == 0x94 || device->chipset == 0x96) xf_emit(ctx, 0x1020, 0); /* 4 x (0x400 x 0xffffffff, ff, 0, 0, 0, 4 x ffffffff) */ - else if (dev_priv->chipset < 0xa0) + else if (device->chipset < 0xa0) xf_emit(ctx, 0xa20, 0); /* 4 x (0x280 x 0xffffffff, ff, 0, 0, 0, 4 x ffffffff) */ - else if (!IS_NVA3F(dev_priv->chipset)) + else if (!IS_NVA3F(device->chipset)) xf_emit(ctx, 0x210, 0); /* ffffffff */ else xf_emit(ctx, 0x410, 0); /* ffffffff */ @@ -2751,12 +2732,12 @@ nv50_graph_construct_xfer_unk84xx(struct nouveau_grctx *ctx) static void nv50_graph_construct_xfer_tprop(struct nouveau_grctx *ctx) { - struct drm_nouveau_private *dev_priv = ctx->dev->dev_private; + struct nouveau_device *device = ctx->device; int magic1, magic2; - if (dev_priv->chipset == 0x50) { + if (device->chipset == 0x50) { magic1 = 0x3ff; magic2 = 0x00003e60; - } else if (!IS_NVA3F(dev_priv->chipset)) { + } else if (!IS_NVA3F(device->chipset)) { magic1 = 0x7ff; magic2 = 0x001ffe67; } else { @@ -2766,7 +2747,7 @@ nv50_graph_construct_xfer_tprop(struct nouveau_grctx *ctx) xf_emit(ctx, 1, 0); /* 00000007 ALPHA_TEST_FUNC */ xf_emit(ctx, 1, 0); /* ffffffff ALPHA_TEST_REF */ xf_emit(ctx, 1, 0); /* 00000001 ALPHA_TEST_ENABLE */ - if (IS_NVA3F(dev_priv->chipset)) + if (IS_NVA3F(device->chipset)) xf_emit(ctx, 1, 1); /* 0000000f UNK16A0 */ xf_emit(ctx, 1, 0); /* 7/f MULTISAMPLE_SAMPLES_LOG2 */ xf_emit(ctx, 1, 0); /* 00000001 tesla UNK1534 */ @@ -2800,11 +2781,11 @@ nv50_graph_construct_xfer_tprop(struct nouveau_grctx *ctx) xf_emit(ctx, 1, 1); /* 00000001 SIFC_BITMAP_WRITE_BIT0_ENABLE */ xf_emit(ctx, 1, 0); /* 00000007 ALPHA_TEST_FUNC */ xf_emit(ctx, 1, 0); /* 00000001 ALPHA_TEST_ENABLE */ - if (IS_NVA3F(dev_priv->chipset)) { + if (IS_NVA3F(device->chipset)) { xf_emit(ctx, 1, 3); /* 00000003 tesla UNK16B4 */ xf_emit(ctx, 1, 0); /* 00000003 */ xf_emit(ctx, 1, 0); /* 00000003 tesla UNK1298 */ - } else if (dev_priv->chipset >= 0xa0) { + } else if (device->chipset >= 0xa0) { xf_emit(ctx, 1, 1); /* 00000001 tesla UNK16B4 */ xf_emit(ctx, 1, 0); /* 00000003 */ } else { @@ -2818,7 +2799,7 @@ nv50_graph_construct_xfer_tprop(struct nouveau_grctx *ctx) xf_emit(ctx, 1, 1); /* 0000001f BLEND_FUNC_DST_RGB */ xf_emit(ctx, 1, 1); /* 00000007 BLEND_EQUATION_RGB */ xf_emit(ctx, 1, 2); /* 0000001f BLEND_FUNC_SRC_RGB */ - if (IS_NVA3F(dev_priv->chipset)) { + if (IS_NVA3F(device->chipset)) { xf_emit(ctx, 1, 0); /* 00000001 UNK12E4 */ xf_emit(ctx, 8, 1); /* 00000007 IBLEND_EQUATION_RGB */ xf_emit(ctx, 8, 1); /* 00000007 IBLEND_EQUATION_ALPHA */ @@ -2846,7 +2827,7 @@ nv50_graph_construct_xfer_tprop(struct nouveau_grctx *ctx) xf_emit(ctx, 1, 0xcf); /* 000000ff SIFC_FORMAT */ xf_emit(ctx, 1, 0xcf); /* 000000ff DRAW_COLOR_FORMAT */ xf_emit(ctx, 1, 0xcf); /* 000000ff SRC_FORMAT */ - if (IS_NVA3F(dev_priv->chipset)) + if (IS_NVA3F(device->chipset)) xf_emit(ctx, 1, 1); /* 0000001f tesla UNK169C */ xf_emit(ctx, 1, 0); /* ffffffff tesla UNK1A3C */ xf_emit(ctx, 1, 0); /* 7/f[NVA3] MULTISAMPLE_SAMPLES_LOG2 */ @@ -2870,9 +2851,9 @@ nv50_graph_construct_xfer_tprop(struct nouveau_grctx *ctx) xf_emit(ctx, 1, 0); /* 00000001 DEPTH_TEST_ENABLE */ xf_emit(ctx, 1, 0x11); /* 3f/7f DST_FORMAT */ xf_emit(ctx, 1, 1); /* 00000001 DST_LINEAR */ - if (IS_NVA3F(dev_priv->chipset)) + if (IS_NVA3F(device->chipset)) xf_emit(ctx, 1, 1); /* 0000001f tesla UNK169C */ - if (dev_priv->chipset == 0x50) + if (device->chipset == 0x50) xf_emit(ctx, 1, 0); /* ff */ else xf_emit(ctx, 3, 0); /* 1, 7, 3ff */ @@ -2907,7 +2888,7 @@ nv50_graph_construct_xfer_tprop(struct nouveau_grctx *ctx) xf_emit(ctx, 1, 1); /* 00000001 ZETA_ENABLE */ xf_emit(ctx, 1, 0); /* 00000007 */ xf_emit(ctx, 1, 0); /* ffffffff tesla UNK1A3C */ - if (IS_NVA3F(dev_priv->chipset)) + if (IS_NVA3F(device->chipset)) xf_emit(ctx, 1, 1); /* 0000001f tesla UNK169C */ xf_emit(ctx, 8, 0); /* 0000ffff DMA_COLOR */ xf_emit(ctx, 1, 0); /* 0000ffff DMA_GLOBAL */ @@ -2945,7 +2926,7 @@ nv50_graph_construct_xfer_tprop(struct nouveau_grctx *ctx) xf_emit(ctx, 1, 0); /* 0001ffff GP_BUILTIN_RESULT_EN */ xf_emit(ctx, 1, 0); /* 00000003 UNK0F90 */ xf_emit(ctx, 1, 0); /* 00000007 */ - if (IS_NVA3F(dev_priv->chipset)) + if (IS_NVA3F(device->chipset)) xf_emit(ctx, 1, 1); /* 0000001f tesla UNK169C */ xf_emit(ctx, 1, magic2); /* 001fffff tesla UNK0F78 */ xf_emit(ctx, 1, 0); /* 7/f MULTISAMPLE_SAMPLES_LOG2 */ @@ -2974,7 +2955,7 @@ nv50_graph_construct_xfer_tprop(struct nouveau_grctx *ctx) xf_emit(ctx, 1, 0x1001); /* 00001fff ZETA_ARRAY_MODE */ xf_emit(ctx, 1, 0); /* ffffffff tesla UNK1A3C */ xf_emit(ctx, 1, 0); /* 7/f MULTISAMPLE_SAMPLES_LOG2 */ - if (IS_NVA3F(dev_priv->chipset)) + if (IS_NVA3F(device->chipset)) xf_emit(ctx, 1, 0); /* 00000001 */ xf_emit(ctx, 1, 0); /* ffff0ff3 */ xf_emit(ctx, 1, 0x11); /* 3f/7f RT_FORMAT */ @@ -2988,14 +2969,14 @@ nv50_graph_construct_xfer_tprop(struct nouveau_grctx *ctx) xf_emit(ctx, 1, 0); /* 00000001 FRAMEBUFFER_SRGB */ xf_emit(ctx, 1, 0); /* 7 */ xf_emit(ctx, 1, 0); /* 00000001 LOGIC_OP_ENABLE */ - if (IS_NVA3F(dev_priv->chipset)) { + if (IS_NVA3F(device->chipset)) { xf_emit(ctx, 1, 0); /* 00000001 UNK1140 */ xf_emit(ctx, 1, 1); /* 0000001f tesla UNK169C */ } xf_emit(ctx, 1, 0); /* 7/f MULTISAMPLE_SAMPLES_LOG2 */ xf_emit(ctx, 1, 0); /* 00000001 UNK1534 */ xf_emit(ctx, 1, 0); /* ffff0ff3 */ - if (dev_priv->chipset >= 0xa0) + if (device->chipset >= 0xa0) xf_emit(ctx, 1, 0x0fac6881); /* fffffff */ xf_emit(ctx, 1, magic2); /* 001fffff tesla UNK0F78 */ xf_emit(ctx, 1, 0); /* 00000001 DEPTH_BOUNDS_EN */ @@ -3012,12 +2993,12 @@ nv50_graph_construct_xfer_tprop(struct nouveau_grctx *ctx) xf_emit(ctx, 1, 0); /* 00000001 SAMPLECNT_ENABLE */ xf_emit(ctx, 1, 0); /* 0000000f ZETA_FORMAT */ xf_emit(ctx, 1, 1); /* 00000001 ZETA_ENABLE */ - if (IS_NVA3F(dev_priv->chipset)) { + if (IS_NVA3F(device->chipset)) { xf_emit(ctx, 1, 1); /* 0000001f tesla UNK169C */ xf_emit(ctx, 1, 0); /* 0000000f tesla UNK15C8 */ } xf_emit(ctx, 1, 0); /* ffffffff tesla UNK1A3C */ - if (dev_priv->chipset >= 0xa0) { + if (device->chipset >= 0xa0) { xf_emit(ctx, 3, 0); /* 7/f, 1, ffff0ff3 */ xf_emit(ctx, 1, 0xfac6881); /* fffffff */ xf_emit(ctx, 4, 0); /* 1, 1, 1, 3ff */ @@ -3027,7 +3008,7 @@ nv50_graph_construct_xfer_tprop(struct nouveau_grctx *ctx) xf_emit(ctx, 2, 0); /* 7, f */ xf_emit(ctx, 1, 1); /* 1 */ xf_emit(ctx, 1, 0); /* 7/f */ - if (IS_NVA3F(dev_priv->chipset)) + if (IS_NVA3F(device->chipset)) xf_emit(ctx, 0x9, 0); /* 1 */ else xf_emit(ctx, 0x8, 0); /* 1 */ @@ -3041,7 +3022,7 @@ nv50_graph_construct_xfer_tprop(struct nouveau_grctx *ctx) xf_emit(ctx, 1, 0x11); /* 7f */ xf_emit(ctx, 1, 1); /* 1 */ xf_emit(ctx, 5, 0); /* 1, 7, 3ff, 3, 7 */ - if (IS_NVA3F(dev_priv->chipset)) { + if (IS_NVA3F(device->chipset)) { xf_emit(ctx, 1, 0); /* 00000001 UNK1140 */ xf_emit(ctx, 1, 1); /* 0000001f tesla UNK169C */ } @@ -3051,15 +3032,15 @@ nv50_graph_construct_xfer_tprop(struct nouveau_grctx *ctx) static void nv50_graph_construct_xfer_tex(struct nouveau_grctx *ctx) { - struct drm_nouveau_private *dev_priv = ctx->dev->dev_private; + struct nouveau_device *device = ctx->device; xf_emit(ctx, 2, 0); /* 1 LINKED_TSC. yes, 2. */ - if (dev_priv->chipset != 0x50) + if (device->chipset != 0x50) xf_emit(ctx, 1, 0); /* 3 */ xf_emit(ctx, 1, 1); /* 1ffff BLIT_DU_DX_INT */ xf_emit(ctx, 1, 0); /* fffff BLIT_DU_DX_FRACT */ xf_emit(ctx, 1, 1); /* 1ffff BLIT_DV_DY_INT */ xf_emit(ctx, 1, 0); /* fffff BLIT_DV_DY_FRACT */ - if (dev_priv->chipset == 0x50) + if (device->chipset == 0x50) xf_emit(ctx, 1, 0); /* 3 BLIT_CONTROL */ else xf_emit(ctx, 2, 0); /* 3ff, 1 */ @@ -3071,13 +3052,13 @@ nv50_graph_construct_xfer_tex(struct nouveau_grctx *ctx) xf_emit(ctx, 1, 0x10100); /* ffffffff SRC_TIC_5 */ xf_emit(ctx, 1, 0x02800000); /* ffffffff SRC_TIC_6 */ xf_emit(ctx, 1, 0); /* ffffffff SRC_TIC_7 */ - if (dev_priv->chipset == 0x50) { + if (device->chipset == 0x50) { xf_emit(ctx, 1, 0); /* 00000001 turing UNK358 */ xf_emit(ctx, 1, 0); /* ffffffff tesla UNK1A34? */ xf_emit(ctx, 1, 0); /* 00000003 turing UNK37C tesla UNK1690 */ xf_emit(ctx, 1, 0); /* 00000003 BLIT_CONTROL */ xf_emit(ctx, 1, 0); /* 00000001 turing UNK32C tesla UNK0F94 */ - } else if (!IS_NVAAF(dev_priv->chipset)) { + } else if (!IS_NVAAF(device->chipset)) { xf_emit(ctx, 1, 0); /* ffffffff tesla UNK1A34? */ xf_emit(ctx, 1, 0); /* 00000003 */ xf_emit(ctx, 1, 0); /* 000003ff */ @@ -3097,7 +3078,7 @@ nv50_graph_construct_xfer_tex(struct nouveau_grctx *ctx) static void nv50_graph_construct_xfer_unk8cxx(struct nouveau_grctx *ctx) { - struct drm_nouveau_private *dev_priv = ctx->dev->dev_private; + struct nouveau_device *device = ctx->device; xf_emit(ctx, 1, 0); /* 00000001 UNK1534 */ xf_emit(ctx, 1, 0); /* 7/f MULTISAMPLE_SAMPLES_LOG2 */ xf_emit(ctx, 2, 0); /* 7, ffff0ff3 */ @@ -3109,7 +3090,7 @@ nv50_graph_construct_xfer_unk8cxx(struct nouveau_grctx *ctx) xf_emit(ctx, 1, 0); /* 00000001 LINE_STIPPLE_ENABLE */ xf_emit(ctx, 1, 0x00ffff00); /* 00ffffff LINE_STIPPLE_PATTERN */ xf_emit(ctx, 1, 1); /* 00000001 tesla UNK0F98 */ - if (IS_NVA3F(dev_priv->chipset)) + if (IS_NVA3F(device->chipset)) xf_emit(ctx, 1, 1); /* 0000001f tesla UNK169C */ xf_emit(ctx, 1, 0); /* 00000003 tesla UNK1668 */ xf_emit(ctx, 1, 0); /* 00000001 LINE_STIPPLE_ENABLE */ @@ -3136,8 +3117,8 @@ nv50_graph_construct_xfer_unk8cxx(struct nouveau_grctx *ctx) static void nv50_graph_construct_xfer_tp(struct nouveau_grctx *ctx) { - struct drm_nouveau_private *dev_priv = ctx->dev->dev_private; - if (dev_priv->chipset < 0xa0) { + struct nouveau_device *device = ctx->device; + if (device->chipset < 0xa0) { nv50_graph_construct_xfer_unk84xx(ctx); nv50_graph_construct_xfer_tprop(ctx); nv50_graph_construct_xfer_tex(ctx); @@ -3153,9 +3134,9 @@ nv50_graph_construct_xfer_tp(struct nouveau_grctx *ctx) static void nv50_graph_construct_xfer_mpc(struct nouveau_grctx *ctx) { - struct drm_nouveau_private *dev_priv = ctx->dev->dev_private; + struct nouveau_device *device = ctx->device; int i, mpcnt = 2; - switch (dev_priv->chipset) { + switch (device->chipset) { case 0x98: case 0xaa: mpcnt = 1; @@ -3182,34 +3163,34 @@ nv50_graph_construct_xfer_mpc(struct nouveau_grctx *ctx) xf_emit(ctx, 1, 0x80); /* ffffffff tesla UNK1404 */ xf_emit(ctx, 1, 0x80007004); /* ffffffff tesla UNK12B0 */ xf_emit(ctx, 1, 0x04000400); /* ffffffff */ - if (dev_priv->chipset >= 0xa0) + if (device->chipset >= 0xa0) xf_emit(ctx, 1, 0xc0); /* 00007fff tesla UNK152C */ xf_emit(ctx, 1, 0x1000); /* 0000ffff tesla UNK0D60 */ xf_emit(ctx, 1, 0); /* ff/3ff */ xf_emit(ctx, 1, 0); /* ffffffff tesla UNK1A30 */ - if (dev_priv->chipset == 0x86 || dev_priv->chipset == 0x98 || dev_priv->chipset == 0xa8 || IS_NVAAF(dev_priv->chipset)) { + if (device->chipset == 0x86 || device->chipset == 0x98 || device->chipset == 0xa8 || IS_NVAAF(device->chipset)) { xf_emit(ctx, 1, 0xe00); /* 7fff */ xf_emit(ctx, 1, 0x1e00); /* 7fff */ } xf_emit(ctx, 1, 1); /* 000000ff VP_REG_ALLOC_TEMP */ xf_emit(ctx, 1, 0); /* 00000001 LINKED_TSC */ xf_emit(ctx, 1, 0); /* 00000001 GP_ENABLE */ - if (dev_priv->chipset == 0x50) + if (device->chipset == 0x50) xf_emit(ctx, 2, 0x1000); /* 7fff tesla UNK141C */ xf_emit(ctx, 1, 1); /* 000000ff GP_REG_ALLOC_TEMP */ xf_emit(ctx, 1, 0); /* 00000001 GP_ENABLE */ xf_emit(ctx, 1, 4); /* 000000ff FP_REG_ALLOC_TEMP */ xf_emit(ctx, 1, 2); /* 00000003 REG_MODE */ - if (IS_NVAAF(dev_priv->chipset)) + if (IS_NVAAF(device->chipset)) xf_emit(ctx, 0xb, 0); /* RO */ - else if (dev_priv->chipset >= 0xa0) + else if (device->chipset >= 0xa0) xf_emit(ctx, 0xc, 0); /* RO */ else xf_emit(ctx, 0xa, 0); /* RO */ } xf_emit(ctx, 1, 0x08100c12); /* 1fffffff FP_INTERPOLANT_CTRL */ xf_emit(ctx, 1, 0); /* ff/3ff */ - if (dev_priv->chipset >= 0xa0) { + if (device->chipset >= 0xa0) { xf_emit(ctx, 1, 0x1fe21); /* 0003ffff tesla UNK0FAC */ } xf_emit(ctx, 3, 0); /* 7fff, 0, 0 */ @@ -3223,7 +3204,7 @@ nv50_graph_construct_xfer_mpc(struct nouveau_grctx *ctx) xf_emit(ctx, 1, 0); /* ffffffff SHARED_SIZE */ xf_emit(ctx, 1, 0x1fe21); /* 1ffff/3ffff[NVA0+] tesla UNk0FAC */ xf_emit(ctx, 1, 0); /* ffffffff tesla UNK1A34 */ - if (IS_NVA3F(dev_priv->chipset)) + if (IS_NVA3F(device->chipset)) xf_emit(ctx, 1, 1); /* 0000001f tesla UNK169C */ xf_emit(ctx, 1, 0); /* ff/3ff */ xf_emit(ctx, 1, 0); /* 1 LINKED_TSC */ @@ -3238,7 +3219,7 @@ nv50_graph_construct_xfer_mpc(struct nouveau_grctx *ctx) xf_emit(ctx, 1, 0); /* 00000007 */ xf_emit(ctx, 1, 0xfac6881); /* 0fffffff RT_CONTROL */ xf_emit(ctx, 1, 0); /* 00000003 MULTISAMPLE_CTRL */ - if (IS_NVA3F(dev_priv->chipset)) + if (IS_NVA3F(device->chipset)) xf_emit(ctx, 1, 3); /* 00000003 tesla UNK16B4 */ xf_emit(ctx, 1, 0); /* 00000001 ALPHA_TEST_ENABLE */ xf_emit(ctx, 1, 0); /* 00000007 ALPHA_TEST_FUNC */ @@ -3253,7 +3234,7 @@ nv50_graph_construct_xfer_mpc(struct nouveau_grctx *ctx) xf_emit(ctx, 1, 1); /* 0000001f BLEND_FUNC_DST_ALPHA */ xf_emit(ctx, 1, 1); /* 00000007 BLEND_EQUATION_ALPHA */ xf_emit(ctx, 1, 1); /* 00000001 UNK133C */ - if (IS_NVA3F(dev_priv->chipset)) { + if (IS_NVA3F(device->chipset)) { xf_emit(ctx, 1, 0); /* 00000001 UNK12E4 */ xf_emit(ctx, 8, 2); /* 0000001f IBLEND_FUNC_SRC_RGB */ xf_emit(ctx, 8, 1); /* 0000001f IBLEND_FUNC_DST_RGB */ @@ -3268,11 +3249,11 @@ nv50_graph_construct_xfer_mpc(struct nouveau_grctx *ctx) xf_emit(ctx, 1, 0); /* 00000003 tesla UNK0F90 */ xf_emit(ctx, 1, 4); /* 000000ff FP_RESULT_COUNT */ /* XXX: demagic this part some day */ - if (dev_priv->chipset == 0x50) + if (device->chipset == 0x50) xf_emit(ctx, 0x3a0, 0); - else if (dev_priv->chipset < 0x94) + else if (device->chipset < 0x94) xf_emit(ctx, 0x3a2, 0); - else if (dev_priv->chipset == 0x98 || dev_priv->chipset == 0xaa) + else if (device->chipset == 0x98 || device->chipset == 0xaa) xf_emit(ctx, 0x39f, 0); else xf_emit(ctx, 0x3a3, 0); @@ -3285,15 +3266,15 @@ nv50_graph_construct_xfer_mpc(struct nouveau_grctx *ctx) static void nv50_graph_construct_xfer2(struct nouveau_grctx *ctx) { - struct drm_nouveau_private *dev_priv = ctx->dev->dev_private; + struct nouveau_device *device = ctx->device; int i; - uint32_t offset; - uint32_t units = nv_rd32 (ctx->dev, 0x1540); + u32 offset; + u32 units = nv_rd32 (ctx->device, 0x1540); int size = 0; offset = (ctx->ctxvals_pos+0x3f)&~0x3f; - if (dev_priv->chipset < 0xa0) { + if (device->chipset < 0xa0) { for (i = 0; i < 8; i++) { ctx->ctxvals_pos = offset + i; /* that little bugger belongs to csched. No idea diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/ctxnvc0.c b/drivers/gpu/drm/nouveau/core/engine/graph/ctxnvc0.c index b19a406e55d9..c12e7668dbfe 100644 --- a/drivers/gpu/drm/nouveau/core/engine/graph/ctxnvc0.c +++ b/drivers/gpu/drm/nouveau/core/engine/graph/ctxnvc0.c @@ -22,13 +22,10 @@ * Authors: Ben Skeggs */ -#include "drmP.h" -#include "nouveau_drv.h" -#include #include "nvc0.h" void -nv_icmd(struct drm_device *priv, u32 icmd, u32 data) +nv_icmd(struct nvc0_graph_priv *priv, u32 icmd, u32 data) { nv_wr32(priv, 0x400204, data); nv_wr32(priv, 0x400200, icmd); @@ -36,21 +33,22 @@ nv_icmd(struct drm_device *priv, u32 icmd, u32 data) } int -nvc0_grctx_init(struct drm_device *priv, struct nvc0_graph_priv *oprv, - struct nvc0_grctx *info) +nvc0_grctx_init(struct nvc0_graph_priv *priv, struct nvc0_grctx *info) { + struct nouveau_bar *bar = nouveau_bar(priv); + struct nouveau_object *parent = nv_object(priv); struct nouveau_gpuobj *chan; - u32 size = (0x80000 + oprv->size + 4095) & ~4095; + u32 size = (0x80000 + priv->size + 4095) & ~4095; int ret, i; /* allocate memory to for a "channel", which we'll use to generate * the default context values */ - ret = nouveau_gpuobj_new(priv, NULL, size, 0x1000, + ret = nouveau_gpuobj_new(parent, NULL, size, 0x1000, NVOBJ_FLAG_ZERO_ALLOC, &info->chan); chan = info->chan; if (ret) { - NV_ERROR(priv, "failed to allocate channel memory, %d\n", ret); + nv_error(priv, "failed to allocate channel memory, %d\n", ret); return ret; } @@ -75,32 +73,31 @@ nvc0_grctx_init(struct drm_device *priv, struct nvc0_graph_priv *oprv, nv_wo32(chan, 0x0210, 0x00080004); nv_wo32(chan, 0x0214, 0x00000000); - nvimem_flush(priv); + bar->flush(bar); nv_wr32(priv, 0x100cb8, (chan->addr + 0x1000) >> 8); nv_wr32(priv, 0x100cbc, 0x80000001); nv_wait(priv, 0x100c80, 0x00008000, 0x00008000); /* setup default state for mmio list construction */ - info->dev = priv; - info->data = oprv->mmio_data; - info->mmio = oprv->mmio_list; + info->data = priv->mmio_data; + info->mmio = priv->mmio_list; info->addr = 0x2000 + (i * 8); - info->priv = oprv; + info->priv = priv; info->buffer_nr = 0; - if (oprv->firmware) { + if (priv->firmware) { nv_wr32(priv, 0x409840, 0x00000030); nv_wr32(priv, 0x409500, 0x80000000 | chan->addr >> 12); nv_wr32(priv, 0x409504, 0x00000003); if (!nv_wait(priv, 0x409800, 0x00000010, 0x00000010)) - NV_ERROR(priv, "load_ctx timeout\n"); + nv_error(priv, "load_ctx timeout\n"); nv_wo32(chan, 0x8001c, 1); nv_wo32(chan, 0x80020, 0); nv_wo32(chan, 0x80028, 0); nv_wo32(chan, 0x8002c, 0); - nvimem_flush(priv); + bar->flush(bar); return 0; } @@ -109,7 +106,7 @@ nvc0_grctx_init(struct drm_device *priv, struct nvc0_graph_priv *oprv, nv_wr32(priv, 0x409500, 0x80000000 | chan->addr >> 12); nv_wr32(priv, 0x409504, 0x00000001); if (!nv_wait(priv, 0x409800, 0x80000000, 0x80000000)) { - NV_ERROR(priv, "HUB_SET_CHAN timeout\n"); + nv_error(priv, "HUB_SET_CHAN timeout\n"); nvc0_graph_ctxctl_debug(priv); nouveau_gpuobj_ref(NULL, &info->chan); return -EBUSY; @@ -135,6 +132,8 @@ nvc0_grctx_data(struct nvc0_grctx *info, u32 size, u32 align, u32 access) void nvc0_grctx_mmio(struct nvc0_grctx *info, u32 addr, u32 data, u32 shift, u32 buf) { + struct nvc0_graph_priv *priv = info->priv; + info->mmio->addr = addr; info->mmio->data = data; info->mmio->shift = shift; @@ -143,7 +142,7 @@ nvc0_grctx_mmio(struct nvc0_grctx *info, u32 addr, u32 data, u32 shift, u32 buf) if (shift) data |= info->buffer[buf] >> shift; - nv_wr32(info->dev, addr, data); + nv_wr32(priv, addr, data); } int @@ -153,11 +152,11 @@ nvc0_grctx_fini(struct nvc0_grctx *info) int i; if (priv->firmware) { - nv_wr32(info->dev, 0x409840, 0x00000003); - nv_wr32(info->dev, 0x409500, 0x80000000 | info->chan->addr >> 12); - nv_wr32(info->dev, 0x409504, 0x00000009); - if (!nv_wait(info->dev, 0x409800, 0x00000001, 0x00000000)) { - NV_ERROR(info->dev, "unload_ctx timeout\n"); + nv_wr32(priv, 0x409840, 0x00000003); + nv_wr32(priv, 0x409500, 0x80000000 | info->chan->addr >> 12); + nv_wr32(priv, 0x409504, 0x00000009); + if (!nv_wait(priv, 0x409800, 0x00000001, 0x00000000)) { + nv_error(priv, "unload_ctx timeout\n"); return -EBUSY; } @@ -165,12 +164,12 @@ nvc0_grctx_fini(struct nvc0_grctx *info) } /* HUB_FUC(CTX_SAVE) */ - nv_wr32(info->dev, 0x409840, 0x80000000); - nv_wr32(info->dev, 0x409500, 0x80000000 | info->chan->addr >> 12); - nv_wr32(info->dev, 0x409504, 0x00000002); - if (!nv_wait(info->dev, 0x409800, 0x80000000, 0x80000000)) { - NV_ERROR(info->dev, "HUB_CTX_SAVE timeout\n"); - nvc0_graph_ctxctl_debug(info->dev); + nv_wr32(priv, 0x409840, 0x80000000); + nv_wr32(priv, 0x409500, 0x80000000 | info->chan->addr >> 12); + nv_wr32(priv, 0x409504, 0x00000002); + if (!nv_wait(priv, 0x409800, 0x80000000, 0x80000000)) { + nv_error(priv, "HUB_CTX_SAVE timeout\n"); + nvc0_graph_ctxctl_debug(priv); return -EBUSY; } @@ -186,7 +185,7 @@ save: } static void -nvc0_grctx_generate_9097(struct drm_device *priv) +nvc0_grctx_generate_9097(struct nvc0_graph_priv *priv) { u32 fermi = nvc0_graph_class(priv); u32 mthd; @@ -1343,7 +1342,7 @@ nvc0_grctx_generate_9097(struct drm_device *priv) } static void -nvc0_grctx_generate_9197(struct drm_device *priv) +nvc0_grctx_generate_9197(struct nvc0_graph_priv *priv) { u32 fermi = nvc0_graph_class(priv); u32 mthd; @@ -1356,7 +1355,7 @@ nvc0_grctx_generate_9197(struct drm_device *priv) } static void -nvc0_grctx_generate_9297(struct drm_device *priv) +nvc0_grctx_generate_9297(struct nvc0_graph_priv *priv) { u32 fermi = nvc0_graph_class(priv); u32 mthd; @@ -1374,7 +1373,7 @@ nvc0_grctx_generate_9297(struct drm_device *priv) } static void -nvc0_grctx_generate_902d(struct drm_device *priv) +nvc0_grctx_generate_902d(struct nvc0_graph_priv *priv) { nv_mthd(priv, 0x902d, 0x0200, 0x000000cf); nv_mthd(priv, 0x902d, 0x0204, 0x00000001); @@ -1396,7 +1395,7 @@ nvc0_grctx_generate_902d(struct drm_device *priv) } static void -nvc0_grctx_generate_9039(struct drm_device *priv) +nvc0_grctx_generate_9039(struct nvc0_graph_priv *priv) { nv_mthd(priv, 0x9039, 0x030c, 0x00000000); nv_mthd(priv, 0x9039, 0x0310, 0x00000000); @@ -1409,12 +1408,11 @@ nvc0_grctx_generate_9039(struct drm_device *priv) } static void -nvc0_grctx_generate_90c0(struct drm_device *priv) +nvc0_grctx_generate_90c0(struct nvc0_graph_priv *priv) { - struct drm_nouveau_private *dev_priv = priv->dev_private; int i; - for (i = 0; dev_priv->chipset == 0xd9 && i < 4; i++) { + for (i = 0; nv_device(priv)->chipset == 0xd9 && i < 4; i++) { nv_mthd(priv, 0x90c0, 0x2700 + (i * 0x40), 0x00000000); nv_mthd(priv, 0x90c0, 0x2720 + (i * 0x40), 0x00000000); nv_mthd(priv, 0x90c0, 0x2704 + (i * 0x40), 0x00000000); @@ -1430,7 +1428,7 @@ nvc0_grctx_generate_90c0(struct drm_device *priv) nv_mthd(priv, 0x90c0, 0x27ac, 0x00000000); nv_mthd(priv, 0x90c0, 0x27cc, 0x00000000); nv_mthd(priv, 0x90c0, 0x27ec, 0x00000000); - for (i = 0; dev_priv->chipset == 0xd9 && i < 4; i++) { + for (i = 0; nv_device(priv)->chipset == 0xd9 && i < 4; i++) { nv_mthd(priv, 0x90c0, 0x2710 + (i * 0x40), 0x00014000); nv_mthd(priv, 0x90c0, 0x2730 + (i * 0x40), 0x00014000); nv_mthd(priv, 0x90c0, 0x2714 + (i * 0x40), 0x00000040); @@ -1458,7 +1456,7 @@ nvc0_grctx_generate_90c0(struct drm_device *priv) } static void -nvc0_grctx_generate_dispatch(struct drm_device *priv) +nvc0_grctx_generate_dispatch(struct nvc0_graph_priv *priv) { int i; @@ -1511,7 +1509,7 @@ nvc0_grctx_generate_dispatch(struct drm_device *priv) } static void -nvc0_grctx_generate_macro(struct drm_device *priv) +nvc0_grctx_generate_macro(struct nvc0_graph_priv *priv) { nv_wr32(priv, 0x404404, 0x00000000); nv_wr32(priv, 0x404408, 0x00000000); @@ -1536,7 +1534,7 @@ nvc0_grctx_generate_macro(struct drm_device *priv) } static void -nvc0_grctx_generate_m2mf(struct drm_device *priv) +nvc0_grctx_generate_m2mf(struct nvc0_graph_priv *priv) { nv_wr32(priv, 0x404604, 0x00000015); nv_wr32(priv, 0x404608, 0x00000000); @@ -1600,7 +1598,7 @@ nvc0_grctx_generate_m2mf(struct drm_device *priv) } static void -nvc0_grctx_generate_unk47xx(struct drm_device *priv) +nvc0_grctx_generate_unk47xx(struct nvc0_graph_priv *priv) { nv_wr32(priv, 0x404700, 0x00000000); nv_wr32(priv, 0x404704, 0x00000000); @@ -1627,16 +1625,15 @@ nvc0_grctx_generate_unk47xx(struct drm_device *priv) } static void -nvc0_grctx_generate_shaders(struct drm_device *priv) +nvc0_grctx_generate_shaders(struct nvc0_graph_priv *priv) { - struct drm_nouveau_private *dev_priv = priv->dev_private; - if (dev_priv->chipset == 0xd9) { + if (nv_device(priv)->chipset == 0xd9) { nv_wr32(priv, 0x405800, 0x0f8000bf); nv_wr32(priv, 0x405830, 0x02180218); nv_wr32(priv, 0x405834, 0x08000000); } else - if (dev_priv->chipset == 0xc1) { + if (nv_device(priv)->chipset == 0xc1) { nv_wr32(priv, 0x405800, 0x0f8000bf); nv_wr32(priv, 0x405830, 0x02180218); nv_wr32(priv, 0x405834, 0x00000000); @@ -1657,7 +1654,7 @@ nvc0_grctx_generate_shaders(struct drm_device *priv) } static void -nvc0_grctx_generate_unk60xx(struct drm_device *priv) +nvc0_grctx_generate_unk60xx(struct nvc0_graph_priv *priv) { nv_wr32(priv, 0x406020, 0x000103c1); nv_wr32(priv, 0x406028, 0x00000001); @@ -1667,25 +1664,24 @@ nvc0_grctx_generate_unk60xx(struct drm_device *priv) } static void -nvc0_grctx_generate_unk64xx(struct drm_device *priv) +nvc0_grctx_generate_unk64xx(struct nvc0_graph_priv *priv) { - struct drm_nouveau_private *dev_priv = priv->dev_private; nv_wr32(priv, 0x4064a8, 0x00000000); nv_wr32(priv, 0x4064ac, 0x00003fff); nv_wr32(priv, 0x4064b4, 0x00000000); nv_wr32(priv, 0x4064b8, 0x00000000); - if (dev_priv->chipset == 0xd9) + if (nv_device(priv)->chipset == 0xd9) nv_wr32(priv, 0x4064bc, 0x00000000); - if (dev_priv->chipset == 0xc1 || - dev_priv->chipset == 0xd9) { + if (nv_device(priv)->chipset == 0xc1 || + nv_device(priv)->chipset == 0xd9) { nv_wr32(priv, 0x4064c0, 0x80140078); nv_wr32(priv, 0x4064c4, 0x0086ffff); } } static void -nvc0_grctx_generate_tpbus(struct drm_device *priv) +nvc0_grctx_generate_tpbus(struct nvc0_graph_priv *priv) { nv_wr32(priv, 0x407804, 0x00000023); nv_wr32(priv, 0x40780c, 0x0a418820); @@ -1698,7 +1694,7 @@ nvc0_grctx_generate_tpbus(struct drm_device *priv) } static void -nvc0_grctx_generate_ccache(struct drm_device *priv) +nvc0_grctx_generate_ccache(struct nvc0_graph_priv *priv) { nv_wr32(priv, 0x408000, 0x00000000); nv_wr32(priv, 0x408004, 0x00000000); @@ -1711,10 +1707,9 @@ nvc0_grctx_generate_ccache(struct drm_device *priv) } static void -nvc0_grctx_generate_rop(struct drm_device *priv) +nvc0_grctx_generate_rop(struct nvc0_graph_priv *priv) { - struct drm_nouveau_private *dev_priv = priv->dev_private; - int chipset = dev_priv->chipset; + int chipset = nv_device(priv)->chipset; /* ROPC_BROADCAST */ nv_wr32(priv, 0x408800, 0x02802a3c); @@ -1741,10 +1736,9 @@ nvc0_grctx_generate_rop(struct drm_device *priv) } static void -nvc0_grctx_generate_gpc(struct drm_device *priv) +nvc0_grctx_generate_gpc(struct nvc0_graph_priv *priv) { - struct drm_nouveau_private *dev_priv = priv->dev_private; - int chipset = dev_priv->chipset; + int chipset = nv_device(priv)->chipset; int i; /* GPC_BROADCAST */ @@ -1834,10 +1828,9 @@ nvc0_grctx_generate_gpc(struct drm_device *priv) } static void -nvc0_grctx_generate_tp(struct drm_device *priv) +nvc0_grctx_generate_tp(struct nvc0_graph_priv *priv) { - struct drm_nouveau_private *dev_priv = priv->dev_private; - int chipset = dev_priv->chipset; + int chipset = nv_device(priv)->chipset; /* GPC_BROADCAST.TP_BROADCAST */ nv_wr32(priv, 0x419818, 0x00000000); @@ -1876,7 +1869,7 @@ nvc0_grctx_generate_tp(struct drm_device *priv) nv_wr32(priv, 0x419c04, 0x00000006); nv_wr32(priv, 0x419c08, 0x00000002); nv_wr32(priv, 0x419c20, 0x00000000); - if (dev_priv->chipset == 0xd9) { + if (nv_device(priv)->chipset == 0xd9) { nv_wr32(priv, 0x419c24, 0x00084210); nv_wr32(priv, 0x419c28, 0x3cf3cf3c); nv_wr32(priv, 0x419cb0, 0x00020048); @@ -1929,16 +1922,14 @@ nvc0_grctx_generate_tp(struct drm_device *priv) } int -nvc0_grctx_generate(struct drm_device *priv) +nvc0_grctx_generate(struct nvc0_graph_priv *priv) { - struct drm_nouveau_private *dev_priv = priv->dev_private; - struct nvc0_graph_priv *oprv = nv_engine(priv, NVOBJ_ENGINE_GR); struct nvc0_grctx info; int ret, i, gpc, tpc, id; u32 fermi = nvc0_graph_class(priv); u32 r000260, tmp; - ret = nvc0_grctx_init(priv, oprv, &info); + ret = nvc0_grctx_init(priv, &info); if (ret) return ret; @@ -1975,11 +1966,11 @@ nvc0_grctx_generate(struct drm_device *priv) mmio_list(0x419008, 0x00000000, 0, 0); mmio_list(0x418808, 0x00000000, 8, 0); mmio_list(0x41880c, 0x80000018, 0, 0); - if (dev_priv->chipset != 0xc1) { + if (nv_device(priv)->chipset != 0xc1) { tmp = 0x02180000; mmio_list(0x405830, tmp, 0, 0); - for (gpc = 0; gpc < oprv->gpc_nr; gpc++) { - for (tpc = 0; tpc < oprv->tpc_nr[gpc]; tpc++) { + for (gpc = 0; gpc < priv->gpc_nr; gpc++) { + for (tpc = 0; tpc < priv->tpc_nr[gpc]; tpc++) { u32 reg = TPC_UNIT(gpc, tpc, 0x0520); mmio_list(reg, tmp, 0, 0); tmp += 0x0324; @@ -1989,13 +1980,13 @@ nvc0_grctx_generate(struct drm_device *priv) tmp = 0x02180000; mmio_list(0x405830, 0x00000218 | tmp, 0, 0); mmio_list(0x4064c4, 0x0086ffff, 0, 0); - for (gpc = 0; gpc < oprv->gpc_nr; gpc++) { - for (tpc = 0; tpc < oprv->tpc_nr[gpc]; tpc++) { + for (gpc = 0; gpc < priv->gpc_nr; gpc++) { + for (tpc = 0; tpc < priv->tpc_nr[gpc]; tpc++) { u32 reg = TPC_UNIT(gpc, tpc, 0x0520); mmio_list(reg, 0x10000000 | tmp, 0, 0); tmp += 0x0324; } - for (tpc = 0; tpc < oprv->tpc_nr[gpc]; tpc++) { + for (tpc = 0; tpc < priv->tpc_nr[gpc]; tpc++) { u32 reg = TPC_UNIT(gpc, tpc, 0x0544); mmio_list(reg, tmp, 0, 0); tmp += 0x0324; @@ -2004,8 +1995,8 @@ nvc0_grctx_generate(struct drm_device *priv) } for (tpc = 0, id = 0; tpc < 4; tpc++) { - for (gpc = 0; gpc < oprv->gpc_nr; gpc++) { - if (tpc < oprv->tpc_nr[gpc]) { + for (gpc = 0; gpc < priv->gpc_nr; gpc++) { + if (tpc < priv->tpc_nr[gpc]) { nv_wr32(priv, TPC_UNIT(gpc, tpc, 0x698), id); nv_wr32(priv, TPC_UNIT(gpc, tpc, 0x4e8), id); nv_wr32(priv, GPC_UNIT(gpc, 0x0c10 + tpc * 4), id); @@ -2013,14 +2004,14 @@ nvc0_grctx_generate(struct drm_device *priv) id++; } - nv_wr32(priv, GPC_UNIT(gpc, 0x0c08), oprv->tpc_nr[gpc]); - nv_wr32(priv, GPC_UNIT(gpc, 0x0c8c), oprv->tpc_nr[gpc]); + nv_wr32(priv, GPC_UNIT(gpc, 0x0c08), priv->tpc_nr[gpc]); + nv_wr32(priv, GPC_UNIT(gpc, 0x0c8c), priv->tpc_nr[gpc]); } } tmp = 0; - for (i = 0; i < oprv->gpc_nr; i++) - tmp |= oprv->tpc_nr[i] << (i * 4); + for (i = 0; i < priv->gpc_nr; i++) + tmp |= priv->tpc_nr[i] << (i * 4); nv_wr32(priv, 0x406028, tmp); nv_wr32(priv, 0x405870, tmp); @@ -2034,13 +2025,13 @@ nvc0_grctx_generate(struct drm_device *priv) if (1) { u8 tpcnr[GPC_MAX], data[TPC_MAX]; - memcpy(tpcnr, oprv->tpc_nr, sizeof(oprv->tpc_nr)); + memcpy(tpcnr, priv->tpc_nr, sizeof(priv->tpc_nr)); memset(data, 0x1f, sizeof(data)); gpc = -1; - for (tpc = 0; tpc < oprv->tpc_total; tpc++) { + for (tpc = 0; tpc < priv->tpc_total; tpc++) { do { - gpc = (gpc + 1) % oprv->gpc_nr; + gpc = (gpc + 1) % priv->gpc_nr; } while (!tpcnr[gpc]); tpcnr[gpc]--; data[tpc] = gpc; @@ -2056,12 +2047,12 @@ nvc0_grctx_generate(struct drm_device *priv) u8 shift, ntpcv; /* calculate first set of magics */ - memcpy(tpcnr, oprv->tpc_nr, sizeof(oprv->tpc_nr)); + memcpy(tpcnr, priv->tpc_nr, sizeof(priv->tpc_nr)); gpc = -1; - for (tpc = 0; tpc < oprv->tpc_total; tpc++) { + for (tpc = 0; tpc < priv->tpc_total; tpc++) { do { - gpc = (gpc + 1) % oprv->gpc_nr; + gpc = (gpc + 1) % priv->gpc_nr; } while (!tpcnr[gpc]); tpcnr[gpc]--; @@ -2073,7 +2064,7 @@ nvc0_grctx_generate(struct drm_device *priv) /* and the second... */ shift = 0; - ntpcv = oprv->tpc_total; + ntpcv = priv->tpc_total; while (!(ntpcv & (1 << 4))) { ntpcv <<= 1; shift++; @@ -2086,22 +2077,22 @@ nvc0_grctx_generate(struct drm_device *priv) data2[1] |= ((1 << (i + 5)) % ntpcv) << ((i - 1) * 5); /* GPC_BROADCAST */ - nv_wr32(priv, 0x418bb8, (oprv->tpc_total << 8) | - oprv->magic_not_rop_nr); + nv_wr32(priv, 0x418bb8, (priv->tpc_total << 8) | + priv->magic_not_rop_nr); for (i = 0; i < 6; i++) nv_wr32(priv, 0x418b08 + (i * 4), data[i]); /* GPC_BROADCAST.TP_BROADCAST */ - nv_wr32(priv, 0x419bd0, (oprv->tpc_total << 8) | - oprv->magic_not_rop_nr | + nv_wr32(priv, 0x419bd0, (priv->tpc_total << 8) | + priv->magic_not_rop_nr | data2[0]); nv_wr32(priv, 0x419be4, data2[1]); for (i = 0; i < 6; i++) nv_wr32(priv, 0x419b00 + (i * 4), data[i]); /* UNK78xx */ - nv_wr32(priv, 0x4078bc, (oprv->tpc_total << 8) | - oprv->magic_not_rop_nr); + nv_wr32(priv, 0x4078bc, (priv->tpc_total << 8) | + priv->magic_not_rop_nr); for (i = 0; i < 6; i++) nv_wr32(priv, 0x40780c + (i * 4), data[i]); } @@ -2110,18 +2101,18 @@ nvc0_grctx_generate(struct drm_device *priv) u32 tpc_mask = 0, tpc_set = 0; u8 tpcnr[GPC_MAX], a, b; - memcpy(tpcnr, oprv->tpc_nr, sizeof(oprv->tpc_nr)); - for (gpc = 0; gpc < oprv->gpc_nr; gpc++) - tpc_mask |= ((1 << oprv->tpc_nr[gpc]) - 1) << (gpc * 8); + memcpy(tpcnr, priv->tpc_nr, sizeof(priv->tpc_nr)); + for (gpc = 0; gpc < priv->gpc_nr; gpc++) + tpc_mask |= ((1 << priv->tpc_nr[gpc]) - 1) << (gpc * 8); for (i = 0, gpc = -1, b = -1; i < 32; i++) { - a = (i * (oprv->tpc_total - 1)) / 32; + a = (i * (priv->tpc_total - 1)) / 32; if (a != b) { b = a; do { - gpc = (gpc + 1) % oprv->gpc_nr; + gpc = (gpc + 1) % priv->gpc_nr; } while (!tpcnr[gpc]); - tpc = oprv->tpc_nr[gpc] - tpcnr[gpc]--; + tpc = priv->tpc_nr[gpc] - tpcnr[gpc]--; tpc_set |= 1 << ((gpc * 8) + tpc); } @@ -2232,7 +2223,7 @@ nvc0_grctx_generate(struct drm_device *priv) nv_icmd(priv, 0x00000215, 0x00000040); nv_icmd(priv, 0x00000216, 0x00000040); nv_icmd(priv, 0x00000217, 0x00000040); - if (dev_priv->chipset == 0xd9) { + if (nv_device(priv)->chipset == 0xd9) { for (i = 0x0400; i <= 0x0417; i++) nv_icmd(priv, i, 0x00000040); } @@ -2244,7 +2235,7 @@ nvc0_grctx_generate(struct drm_device *priv) nv_icmd(priv, 0x0000021d, 0x0000c080); nv_icmd(priv, 0x0000021e, 0x0000c080); nv_icmd(priv, 0x0000021f, 0x0000c080); - if (dev_priv->chipset == 0xd9) { + if (nv_device(priv)->chipset == 0xd9) { for (i = 0x0440; i <= 0x0457; i++) nv_icmd(priv, i, 0x0000c080); } @@ -2810,8 +2801,8 @@ nvc0_grctx_generate(struct drm_device *priv) nv_icmd(priv, 0x0000053f, 0xffff0000); nv_icmd(priv, 0x00000585, 0x0000003f); nv_icmd(priv, 0x00000576, 0x00000003); - if (dev_priv->chipset == 0xc1 || - dev_priv->chipset == 0xd9) + if (nv_device(priv)->chipset == 0xc1 || + nv_device(priv)->chipset == 0xd9) nv_icmd(priv, 0x0000057b, 0x00000059); nv_icmd(priv, 0x00000586, 0x00000040); nv_icmd(priv, 0x00000582, 0x00000080); @@ -2913,7 +2904,7 @@ nvc0_grctx_generate(struct drm_device *priv) nv_icmd(priv, 0x00000957, 0x00000003); nv_icmd(priv, 0x0000095e, 0x20164010); nv_icmd(priv, 0x0000095f, 0x00000020); - if (dev_priv->chipset == 0xd9) + if (nv_device(priv)->chipset == 0xd9) nv_icmd(priv, 0x0000097d, 0x00000020); nv_icmd(priv, 0x00000683, 0x00000006); nv_icmd(priv, 0x00000685, 0x003fffff); @@ -3056,5 +3047,6 @@ nvc0_grctx_generate(struct drm_device *priv) nvc0_grctx_generate_90c0(priv); nv_wr32(priv, 0x000260, r000260); + return nvc0_grctx_fini(&info); } diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/ctxnve0.c b/drivers/gpu/drm/nouveau/core/engine/graph/ctxnve0.c index e5503170d68c..6d8c63931ee6 100644 --- a/drivers/gpu/drm/nouveau/core/engine/graph/ctxnve0.c +++ b/drivers/gpu/drm/nouveau/core/engine/graph/ctxnve0.c @@ -22,13 +22,10 @@ * Authors: Ben Skeggs */ -#include "drmP.h" -#include "nouveau_drv.h" -#include #include "nvc0.h" static void -nve0_grctx_generate_icmd(struct drm_device *priv) +nve0_grctx_generate_icmd(struct nvc0_graph_priv *priv) { nv_wr32(priv, 0x400208, 0x80000000); nv_icmd(priv, 0x001000, 0x00000004); @@ -916,7 +913,7 @@ nve0_grctx_generate_icmd(struct drm_device *priv) } static void -nve0_grctx_generate_a097(struct drm_device *priv) +nve0_grctx_generate_a097(struct nvc0_graph_priv *priv) { nv_mthd(priv, 0xa097, 0x0800, 0x00000000); nv_mthd(priv, 0xa097, 0x0840, 0x00000000); @@ -2146,7 +2143,7 @@ nve0_grctx_generate_a097(struct drm_device *priv) } static void -nve0_grctx_generate_902d(struct drm_device *priv) +nve0_grctx_generate_902d(struct nvc0_graph_priv *priv) { nv_mthd(priv, 0x902d, 0x0200, 0x000000cf); nv_mthd(priv, 0x902d, 0x0204, 0x00000001); @@ -2169,7 +2166,7 @@ nve0_grctx_generate_902d(struct drm_device *priv) } static void -nve0_graph_generate_unk40xx(struct drm_device *priv) +nve0_graph_generate_unk40xx(struct nvc0_graph_priv *priv) { nv_wr32(priv, 0x404010, 0x0); nv_wr32(priv, 0x404014, 0x0); @@ -2213,7 +2210,7 @@ nve0_graph_generate_unk40xx(struct drm_device *priv) } static void -nve0_graph_generate_unk44xx(struct drm_device *priv) +nve0_graph_generate_unk44xx(struct nvc0_graph_priv *priv) { nv_wr32(priv, 0x404404, 0x0); nv_wr32(priv, 0x404408, 0x0); @@ -2238,7 +2235,7 @@ nve0_graph_generate_unk44xx(struct drm_device *priv) } static void -nve0_graph_generate_unk46xx(struct drm_device *priv) +nve0_graph_generate_unk46xx(struct nvc0_graph_priv *priv) { nv_wr32(priv, 0x404604, 0x14); nv_wr32(priv, 0x404608, 0x0); @@ -2278,7 +2275,7 @@ nve0_graph_generate_unk46xx(struct drm_device *priv) } static void -nve0_graph_generate_unk47xx(struct drm_device *priv) +nve0_graph_generate_unk47xx(struct nvc0_graph_priv *priv) { nv_wr32(priv, 0x404700, 0x0); nv_wr32(priv, 0x404704, 0x0); @@ -2299,7 +2296,7 @@ nve0_graph_generate_unk47xx(struct drm_device *priv) } static void -nve0_graph_generate_unk58xx(struct drm_device *priv) +nve0_graph_generate_unk58xx(struct nvc0_graph_priv *priv) { nv_wr32(priv, 0x405800, 0xf8000bf); nv_wr32(priv, 0x405830, 0x2180648); @@ -2318,7 +2315,7 @@ nve0_graph_generate_unk58xx(struct drm_device *priv) } static void -nve0_graph_generate_unk60xx(struct drm_device *priv) +nve0_graph_generate_unk60xx(struct nvc0_graph_priv *priv) { nv_wr32(priv, 0x406020, 0x4103c1); nv_wr32(priv, 0x406028, 0x1); @@ -2328,7 +2325,7 @@ nve0_graph_generate_unk60xx(struct drm_device *priv) } static void -nve0_graph_generate_unk64xx(struct drm_device *priv) +nve0_graph_generate_unk64xx(struct nvc0_graph_priv *priv) { nv_wr32(priv, 0x4064a8, 0x0); nv_wr32(priv, 0x4064ac, 0x3fff); @@ -2350,13 +2347,13 @@ nve0_graph_generate_unk64xx(struct drm_device *priv) } static void -nve0_graph_generate_unk70xx(struct drm_device *priv) +nve0_graph_generate_unk70xx(struct nvc0_graph_priv *priv) { nv_wr32(priv, 0x407040, 0x0); } static void -nve0_graph_generate_unk78xx(struct drm_device *priv) +nve0_graph_generate_unk78xx(struct nvc0_graph_priv *priv) { nv_wr32(priv, 0x407804, 0x23); nv_wr32(priv, 0x40780c, 0xa418820); @@ -2369,7 +2366,7 @@ nve0_graph_generate_unk78xx(struct drm_device *priv) } static void -nve0_graph_generate_unk80xx(struct drm_device *priv) +nve0_graph_generate_unk80xx(struct nvc0_graph_priv *priv) { nv_wr32(priv, 0x408000, 0x0); nv_wr32(priv, 0x408004, 0x0); @@ -2382,7 +2379,7 @@ nve0_graph_generate_unk80xx(struct drm_device *priv) } static void -nve0_graph_generate_unk88xx(struct drm_device *priv) +nve0_graph_generate_unk88xx(struct nvc0_graph_priv *priv) { nv_wr32(priv, 0x408800, 0x2802a3c); nv_wr32(priv, 0x408804, 0x40); @@ -2395,7 +2392,7 @@ nve0_graph_generate_unk88xx(struct drm_device *priv) } static void -nve0_graph_generate_gpc(struct drm_device *priv) +nve0_graph_generate_gpc(struct nvc0_graph_priv *priv) { nv_wr32(priv, 0x418380, 0x16); nv_wr32(priv, 0x418400, 0x38004e00); @@ -2521,7 +2518,7 @@ nve0_graph_generate_gpc(struct drm_device *priv) } static void -nve0_graph_generate_tpc(struct drm_device *priv) +nve0_graph_generate_tpc(struct nvc0_graph_priv *priv) { nv_wr32(priv, 0x419848, 0x0); nv_wr32(priv, 0x419864, 0x129); @@ -2586,7 +2583,7 @@ nve0_graph_generate_tpc(struct drm_device *priv) } static void -nve0_graph_generate_tpcunk(struct drm_device *priv) +nve0_graph_generate_tpcunk(struct nvc0_graph_priv *priv) { nv_wr32(priv, 0x41be24, 0x6); nv_wr32(priv, 0x41bec0, 0x12180000); @@ -2604,9 +2601,8 @@ nve0_graph_generate_tpcunk(struct drm_device *priv) } int -nve0_grctx_generate(struct drm_device *priv) +nve0_grctx_generate(struct nvc0_graph_priv *priv) { - struct nvc0_graph_priv *oprv = nv_engine(priv, NVOBJ_ENGINE_GR); struct nvc0_grctx info; int ret, i, gpc, tpc, id; u32 data[6] = {}, data2[2] = {}, tmp; @@ -2615,7 +2611,7 @@ nve0_grctx_generate(struct drm_device *priv) u8 tpcnr[GPC_MAX], a, b; u8 shift, ntpcv; - ret = nvc0_grctx_init(priv, oprv, &info); + ret = nvc0_grctx_init(priv, &info); if (ret) return ret; @@ -2657,17 +2653,17 @@ nve0_grctx_generate(struct drm_device *priv) mmio_list(0x419848, 0x10000000, 12, 2); mmio_list(0x405830, 0x02180648, 0, 0); mmio_list(0x4064c4, 0x0192ffff, 0, 0); - for (gpc = 0, offset = 0; gpc < oprv->gpc_nr; gpc++) { - u16 magic0 = 0x0218 * oprv->tpc_nr[gpc]; - u16 magic1 = 0x0648 * oprv->tpc_nr[gpc]; + for (gpc = 0, offset = 0; gpc < priv->gpc_nr; gpc++) { + u16 magic0 = 0x0218 * priv->tpc_nr[gpc]; + u16 magic1 = 0x0648 * priv->tpc_nr[gpc]; magic[gpc][0] = 0x10000000 | (magic0 << 16) | offset; magic[gpc][1] = 0x00000000 | (magic1 << 16); - offset += 0x0324 * oprv->tpc_nr[gpc]; + offset += 0x0324 * priv->tpc_nr[gpc]; } - for (gpc = 0; gpc < oprv->gpc_nr; gpc++) { + for (gpc = 0; gpc < priv->gpc_nr; gpc++) { mmio_list(GPC_UNIT(gpc, 0x30c0), magic[gpc][0], 0, 0); mmio_list(GPC_UNIT(gpc, 0x30e4), magic[gpc][1] | offset, 0, 0); - offset += 0x07ff * oprv->tpc_nr[gpc]; + offset += 0x07ff * priv->tpc_nr[gpc]; } mmio_list(0x17e91c, 0x06060609, 0, 0); mmio_list(0x17e920, 0x00090a05, 0, 0); @@ -2680,22 +2676,22 @@ nve0_grctx_generate(struct drm_device *priv) nv_wr32(priv, 0x419c00, 0xa); for (tpc = 0, id = 0; tpc < 4; tpc++) { - for (gpc = 0; gpc < oprv->gpc_nr; gpc++) { - if (tpc < oprv->tpc_nr[gpc]) { + for (gpc = 0; gpc < priv->gpc_nr; gpc++) { + if (tpc < priv->tpc_nr[gpc]) { nv_wr32(priv, TPC_UNIT(gpc, tpc, 0x0698), id); nv_wr32(priv, TPC_UNIT(gpc, tpc, 0x04e8), id); nv_wr32(priv, GPC_UNIT(gpc, 0x0c10 + tpc * 4), id); nv_wr32(priv, TPC_UNIT(gpc, tpc, 0x0088), id++); } - nv_wr32(priv, GPC_UNIT(gpc, 0x0c08), oprv->tpc_nr[gpc]); - nv_wr32(priv, GPC_UNIT(gpc, 0x0c8c), oprv->tpc_nr[gpc]); + nv_wr32(priv, GPC_UNIT(gpc, 0x0c08), priv->tpc_nr[gpc]); + nv_wr32(priv, GPC_UNIT(gpc, 0x0c8c), priv->tpc_nr[gpc]); } } tmp = 0; - for (i = 0; i < oprv->gpc_nr; i++) - tmp |= oprv->tpc_nr[i] << (i * 4); + for (i = 0; i < priv->gpc_nr; i++) + tmp |= priv->tpc_nr[i] << (i * 4); nv_wr32(priv, 0x406028, tmp); nv_wr32(priv, 0x405870, tmp); @@ -2707,12 +2703,12 @@ nve0_grctx_generate(struct drm_device *priv) nv_wr32(priv, 0x40587c, 0x0); /* calculate first set of magics */ - memcpy(tpcnr, oprv->tpc_nr, sizeof(oprv->tpc_nr)); + memcpy(tpcnr, priv->tpc_nr, sizeof(priv->tpc_nr)); gpc = -1; - for (tpc = 0; tpc < oprv->tpc_total; tpc++) { + for (tpc = 0; tpc < priv->tpc_total; tpc++) { do { - gpc = (gpc + 1) % oprv->gpc_nr; + gpc = (gpc + 1) % priv->gpc_nr; } while (!tpcnr[gpc]); tpcnr[gpc]--; @@ -2724,7 +2720,7 @@ nve0_grctx_generate(struct drm_device *priv) /* and the second... */ shift = 0; - ntpcv = oprv->tpc_total; + ntpcv = priv->tpc_total; while (!(ntpcv & (1 << 4))) { ntpcv <<= 1; shift++; @@ -2733,13 +2729,13 @@ nve0_grctx_generate(struct drm_device *priv) data2[0] = ntpcv << 16; data2[0] |= shift << 21; data2[0] |= (((1 << (0 + 5)) % ntpcv) << 24); - data2[0] |= oprv->tpc_total << 8; - data2[0] |= oprv->magic_not_rop_nr; + data2[0] |= priv->tpc_total << 8; + data2[0] |= priv->magic_not_rop_nr; for (i = 1; i < 7; i++) data2[1] |= ((1 << (i + 5)) % ntpcv) << ((i - 1) * 5); /* and write it all the various parts of PGRAPH */ - nv_wr32(priv, 0x418bb8, (oprv->tpc_total << 8) | oprv->magic_not_rop_nr); + nv_wr32(priv, 0x418bb8, (priv->tpc_total << 8) | priv->magic_not_rop_nr); for (i = 0; i < 6; i++) nv_wr32(priv, 0x418b08 + (i * 4), data[i]); @@ -2748,23 +2744,23 @@ nve0_grctx_generate(struct drm_device *priv) for (i = 0; i < 6; i++) nv_wr32(priv, 0x41bf00 + (i * 4), data[i]); - nv_wr32(priv, 0x4078bc, (oprv->tpc_total << 8) | oprv->magic_not_rop_nr); + nv_wr32(priv, 0x4078bc, (priv->tpc_total << 8) | priv->magic_not_rop_nr); for (i = 0; i < 6; i++) nv_wr32(priv, 0x40780c + (i * 4), data[i]); - memcpy(tpcnr, oprv->tpc_nr, sizeof(oprv->tpc_nr)); - for (gpc = 0; gpc < oprv->gpc_nr; gpc++) - tpc_mask |= ((1 << oprv->tpc_nr[gpc]) - 1) << (gpc * 8); + memcpy(tpcnr, priv->tpc_nr, sizeof(priv->tpc_nr)); + for (gpc = 0; gpc < priv->gpc_nr; gpc++) + tpc_mask |= ((1 << priv->tpc_nr[gpc]) - 1) << (gpc * 8); for (i = 0, gpc = -1, b = -1; i < 32; i++) { - a = (i * (oprv->tpc_total - 1)) / 32; + a = (i * (priv->tpc_total - 1)) / 32; if (a != b) { b = a; do { - gpc = (gpc + 1) % oprv->gpc_nr; + gpc = (gpc + 1) % priv->gpc_nr; } while (!tpcnr[gpc]); - tpc = oprv->tpc_nr[gpc] - tpcnr[gpc]--; + tpc = priv->tpc_nr[gpc] - tpcnr[gpc]--; tpc_set |= 1 << ((gpc * 8) + tpc); } diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/nv04.c b/drivers/gpu/drm/nouveau/core/engine/graph/nv04.c index 7f3a275157bb..e5b01899dece 100644 --- a/drivers/gpu/drm/nouveau/core/engine/graph/nv04.c +++ b/drivers/gpu/drm/nouveau/core/engine/graph/nv04.c @@ -22,19 +22,22 @@ * DEALINGS IN THE SOFTWARE. */ -#include "drmP.h" -#include "drm.h" -#include -#include "nouveau_drv.h" -#include "nouveau_hw.h" -#include "nouveau_util.h" -#include - -struct nv04_graph_engine { - struct nouveau_exec_engine base; -}; +#include +#include +#include +#include + +#include +#include +#include + +#include +#include -static uint32_t nv04_graph_ctx_regs[] = { +#include "regs.h" + +static u32 +nv04_graph_ctx_regs[] = { 0x0040053c, 0x00400544, 0x00400540, @@ -348,205 +351,28 @@ static uint32_t nv04_graph_ctx_regs[] = { NV04_PGRAPH_DEBUG_3 }; -struct graph_state { - uint32_t nv04[ARRAY_SIZE(nv04_graph_ctx_regs)]; +struct nv04_graph_priv { + struct nouveau_graph base; + struct nv04_graph_chan *chan[16]; + spinlock_t lock; }; -static struct nouveau_channel * -nv04_graph_channel(struct drm_device *dev) -{ - struct drm_nouveau_private *dev_priv = dev->dev_private; - int chid = 15; - - if (nv_rd32(dev, NV04_PGRAPH_CTX_CONTROL) & 0x00010000) - chid = nv_rd32(dev, NV04_PGRAPH_CTX_USER) >> 24; - - if (chid > 15) - return NULL; - - return dev_priv->channels.ptr[chid]; -} - -static uint32_t *ctx_reg(struct graph_state *ctx, uint32_t reg) -{ - int i; - - for (i = 0; i < ARRAY_SIZE(nv04_graph_ctx_regs); i++) { - if (nv04_graph_ctx_regs[i] == reg) - return &ctx->nv04[i]; - } - - return NULL; -} - -static int -nv04_graph_load_context(struct nouveau_channel *chan) -{ - struct graph_state *pgraph_ctx = chan->engctx[NVOBJ_ENGINE_GR]; - struct drm_device *dev = chan->dev; - uint32_t tmp; - int i; - - for (i = 0; i < ARRAY_SIZE(nv04_graph_ctx_regs); i++) - nv_wr32(dev, nv04_graph_ctx_regs[i], pgraph_ctx->nv04[i]); - - nv_wr32(dev, NV04_PGRAPH_CTX_CONTROL, 0x10010100); - - tmp = nv_rd32(dev, NV04_PGRAPH_CTX_USER) & 0x00ffffff; - nv_wr32(dev, NV04_PGRAPH_CTX_USER, tmp | chan->id << 24); - - tmp = nv_rd32(dev, NV04_PGRAPH_FFINTFC_ST2); - nv_wr32(dev, NV04_PGRAPH_FFINTFC_ST2, tmp & 0x000fffff); - - return 0; -} - -static int -nv04_graph_unload_context(struct drm_device *dev) -{ - struct nouveau_channel *chan = NULL; - struct graph_state *ctx; - uint32_t tmp; - int i; - - chan = nv04_graph_channel(dev); - if (!chan) - return 0; - ctx = chan->engctx[NVOBJ_ENGINE_GR]; - - for (i = 0; i < ARRAY_SIZE(nv04_graph_ctx_regs); i++) - ctx->nv04[i] = nv_rd32(dev, nv04_graph_ctx_regs[i]); - - nv_wr32(dev, NV04_PGRAPH_CTX_CONTROL, 0x10000000); - tmp = nv_rd32(dev, NV04_PGRAPH_CTX_USER) & 0x00ffffff; - tmp |= 15 << 24; - nv_wr32(dev, NV04_PGRAPH_CTX_USER, tmp); - return 0; -} - -static int -nv04_graph_context_new(struct nouveau_channel *chan, int engine) -{ - struct graph_state *pgraph_ctx; - NV_DEBUG(chan->dev, "nv04_graph_context_create %d\n", chan->id); - - pgraph_ctx = kzalloc(sizeof(*pgraph_ctx), GFP_KERNEL); - if (pgraph_ctx == NULL) - return -ENOMEM; - - *ctx_reg(pgraph_ctx, NV04_PGRAPH_DEBUG_3) = 0xfad4ff31; - - chan->engctx[engine] = pgraph_ctx; - return 0; -} - -static void -nv04_graph_context_del(struct nouveau_channel *chan, int engine) -{ - struct drm_device *dev = chan->dev; - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct graph_state *pgraph_ctx = chan->engctx[engine]; - unsigned long flags; - - spin_lock_irqsave(&dev_priv->context_switch_lock, flags); - nv_mask(dev, NV04_PGRAPH_FIFO, 0x00000001, 0x00000000); - - /* Unload the context if it's the currently active one */ - if (nv04_graph_channel(dev) == chan) - nv04_graph_unload_context(dev); - - nv_mask(dev, NV04_PGRAPH_FIFO, 0x00000001, 0x00000001); - spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags); - - /* Free the context resources */ - kfree(pgraph_ctx); - chan->engctx[engine] = NULL; -} - -int -nv04_graph_object_new(struct nouveau_channel *chan, int engine, - u32 handle, u16 class) -{ - struct drm_device *dev = chan->dev; - struct nouveau_gpuobj *obj = NULL; - int ret; - - ret = nouveau_gpuobj_new(dev, chan, 16, 16, NVOBJ_FLAG_ZERO_FREE, &obj); - if (ret) - return ret; - obj->engine = 1; - obj->class = class; - -#ifdef __BIG_ENDIAN - nv_wo32(obj, 0x00, 0x00080000 | class); -#else - nv_wo32(obj, 0x00, class); -#endif - nv_wo32(obj, 0x04, 0x00000000); - nv_wo32(obj, 0x08, 0x00000000); - nv_wo32(obj, 0x0c, 0x00000000); +struct nv04_graph_chan { + struct nouveau_object base; + int chid; + u32 nv04[ARRAY_SIZE(nv04_graph_ctx_regs)]; +}; - ret = nouveau_ramht_insert(chan, handle, obj); - nouveau_gpuobj_ref(NULL, &obj); - return ret; -} -static int -nv04_graph_init(struct drm_device *dev, int engine) +static inline struct nv04_graph_priv * +nv04_graph_priv(struct nv04_graph_chan *chan) { - uint32_t tmp; - - nv_wr32(dev, NV03_PMC_ENABLE, nv_rd32(dev, NV03_PMC_ENABLE) & - ~NV_PMC_ENABLE_PGRAPH); - nv_wr32(dev, NV03_PMC_ENABLE, nv_rd32(dev, NV03_PMC_ENABLE) | - NV_PMC_ENABLE_PGRAPH); - - /* Enable PGRAPH interrupts */ - nv_wr32(dev, NV03_PGRAPH_INTR, 0xFFFFFFFF); - nv_wr32(dev, NV03_PGRAPH_INTR_EN, 0xFFFFFFFF); - - nv_wr32(dev, NV04_PGRAPH_VALID1, 0); - nv_wr32(dev, NV04_PGRAPH_VALID2, 0); - /*nv_wr32(dev, NV04_PGRAPH_DEBUG_0, 0x000001FF); - nv_wr32(dev, NV04_PGRAPH_DEBUG_0, 0x001FFFFF);*/ - nv_wr32(dev, NV04_PGRAPH_DEBUG_0, 0x1231c000); - /*1231C000 blob, 001 haiku*/ - /*V_WRITE(NV04_PGRAPH_DEBUG_1, 0xf2d91100);*/ - nv_wr32(dev, NV04_PGRAPH_DEBUG_1, 0x72111100); - /*0x72111100 blob , 01 haiku*/ - /*nv_wr32(dev, NV04_PGRAPH_DEBUG_2, 0x11d5f870);*/ - nv_wr32(dev, NV04_PGRAPH_DEBUG_2, 0x11d5f071); - /*haiku same*/ - - /*nv_wr32(dev, NV04_PGRAPH_DEBUG_3, 0xfad4ff31);*/ - nv_wr32(dev, NV04_PGRAPH_DEBUG_3, 0xf0d4ff31); - /*haiku and blob 10d4*/ - - nv_wr32(dev, NV04_PGRAPH_STATE , 0xFFFFFFFF); - nv_wr32(dev, NV04_PGRAPH_CTX_CONTROL , 0x10000100); - tmp = nv_rd32(dev, NV04_PGRAPH_CTX_USER) & 0x00ffffff; - tmp |= 15 << 24; - nv_wr32(dev, NV04_PGRAPH_CTX_USER, tmp); - - /* These don't belong here, they're part of a per-channel context */ - nv_wr32(dev, NV04_PGRAPH_PATTERN_SHAPE, 0x00000000); - nv_wr32(dev, NV04_PGRAPH_BETA_AND , 0xFFFFFFFF); - - return 0; + return (void *)nv_object(chan)->engine; } -static int -nv04_graph_fini(struct drm_device *dev, int engine, bool suspend) -{ - nv_mask(dev, NV04_PGRAPH_FIFO, 0x00000001, 0x00000000); - if (!nv_wait(dev, NV04_PGRAPH_STATUS, ~0, 0) && suspend) { - nv_mask(dev, NV04_PGRAPH_FIFO, 0x00000001, 0x00000001); - return -EBUSY; - } - nv04_graph_unload_context(dev); - nv_wr32(dev, NV03_PGRAPH_INTR_EN, 0x00000000); - return 0; -} +/******************************************************************************* + * Graphics object classes + ******************************************************************************/ /* * Software methods, why they are needed, and how they all work: @@ -623,37 +449,35 @@ nv04_graph_fini(struct drm_device *dev, int engine, bool suspend) */ static void -nv04_graph_set_ctx1(struct nouveau_channel *chan, u32 mask, u32 value) +nv04_graph_set_ctx1(struct nouveau_object *object, u32 mask, u32 value) { - struct drm_device *dev = chan->dev; - u32 instance = (nv_rd32(dev, NV04_PGRAPH_CTX_SWITCH4) & 0xffff) << 4; - int subc = (nv_rd32(dev, NV04_PGRAPH_TRAPPED_ADDR) >> 13) & 0x7; + struct nv04_graph_priv *priv = (void *)object->engine; + int subc = (nv_rd32(priv, NV04_PGRAPH_TRAPPED_ADDR) >> 13) & 0x7; u32 tmp; - tmp = nv_ri32(dev, instance); + tmp = nv_ro32(object, 0x00); tmp &= ~mask; tmp |= value; + nv_wo32(object, 0x00, tmp); - nv_wi32(dev, instance, tmp); - nv_wr32(dev, NV04_PGRAPH_CTX_SWITCH1, tmp); - nv_wr32(dev, NV04_PGRAPH_CTX_CACHE1 + (subc<<2), tmp); + nv_wr32(priv, NV04_PGRAPH_CTX_SWITCH1, tmp); + nv_wr32(priv, NV04_PGRAPH_CTX_CACHE1 + (subc<<2), tmp); } static void -nv04_graph_set_ctx_val(struct nouveau_channel *chan, u32 mask, u32 value) +nv04_graph_set_ctx_val(struct nouveau_object *object, u32 mask, u32 value) { - struct drm_device *dev = chan->dev; - u32 instance = (nv_rd32(dev, NV04_PGRAPH_CTX_SWITCH4) & 0xffff) << 4; - u32 tmp, ctx1; int class, op, valid = 1; + u32 tmp, ctx1; - ctx1 = nv_ri32(dev, instance); + ctx1 = nv_ro32(object, 0x00); class = ctx1 & 0xff; op = (ctx1 >> 15) & 7; - tmp = nv_ri32(dev, instance + 0xc); + + tmp = nv_ro32(object, 0x0c); tmp &= ~mask; tmp |= value; - nv_wi32(dev, instance + 0xc, tmp); + nv_wo32(object, 0x0c, tmp); /* check for valid surf2d/surf_dst/surf_color */ if (!(tmp & 0x02000000)) @@ -685,30 +509,34 @@ nv04_graph_set_ctx_val(struct nouveau_channel *chan, u32 mask, u32 value) break; } - nv04_graph_set_ctx1(chan, 0x01000000, valid << 24); + nv04_graph_set_ctx1(object, 0x01000000, valid << 24); } static int -nv04_graph_mthd_set_operation(struct nouveau_channel *chan, - u32 class, u32 mthd, u32 data) +nv04_graph_mthd_set_operation(struct nouveau_object *object, u32 mthd, + void *args, u32 size) { + u32 class = nv_ro32(object, 0) & 0xff; + u32 data = *(u32 *)args; if (data > 5) return 1; /* Old versions of the objects only accept first three operations. */ if (data > 2 && class < 0x40) return 1; - nv04_graph_set_ctx1(chan, 0x00038000, data << 15); + nv04_graph_set_ctx1(object, 0x00038000, data << 15); /* changing operation changes set of objects needed for validation */ - nv04_graph_set_ctx_val(chan, 0, 0); + nv04_graph_set_ctx_val(object, 0, 0); return 0; } static int -nv04_graph_mthd_surf3d_clip_h(struct nouveau_channel *chan, - u32 class, u32 mthd, u32 data) +nv04_graph_mthd_surf3d_clip_h(struct nouveau_object *object, u32 mthd, + void *args, u32 size) { - uint32_t min = data & 0xffff, max; - uint32_t w = data >> 16; + struct nv04_graph_priv *priv = (void *)object->engine; + u32 data = *(u32 *)args; + u32 min = data & 0xffff, max; + u32 w = data >> 16; if (min & 0x8000) /* too large */ return 1; @@ -717,17 +545,19 @@ nv04_graph_mthd_surf3d_clip_h(struct nouveau_channel *chan, w |= 0xffff0000; max = min + w; max &= 0x3ffff; - nv_wr32(chan->dev, 0x40053c, min); - nv_wr32(chan->dev, 0x400544, max); + nv_wr32(priv, 0x40053c, min); + nv_wr32(priv, 0x400544, max); return 0; } static int -nv04_graph_mthd_surf3d_clip_v(struct nouveau_channel *chan, - u32 class, u32 mthd, u32 data) +nv04_graph_mthd_surf3d_clip_v(struct nouveau_object *object, u32 mthd, + void *args, u32 size) { - uint32_t min = data & 0xffff, max; - uint32_t w = data >> 16; + struct nv04_graph_priv *priv = (void *)object->engine; + u32 data = *(u32 *)args; + u32 min = data & 0xffff, max; + u32 w = data >> 16; if (min & 0x8000) /* too large */ return 1; @@ -736,223 +566,661 @@ nv04_graph_mthd_surf3d_clip_v(struct nouveau_channel *chan, w |= 0xffff0000; max = min + w; max &= 0x3ffff; - nv_wr32(chan->dev, 0x400540, min); - nv_wr32(chan->dev, 0x400548, max); + nv_wr32(priv, 0x400540, min); + nv_wr32(priv, 0x400548, max); return 0; } +static u16 +nv04_graph_mthd_bind_class(struct nouveau_object *object, u32 *args, u32 size) +{ + struct nouveau_instmem *imem = nouveau_instmem(object); + u32 inst = *(u32 *)args << 4; + return nv_ro32(imem, inst); +} + static int -nv04_graph_mthd_bind_surf2d(struct nouveau_channel *chan, - u32 class, u32 mthd, u32 data) +nv04_graph_mthd_bind_surf2d(struct nouveau_object *object, u32 mthd, + void *args, u32 size) { - switch (nv_ri32(chan->dev, data << 4) & 0xff) { + switch (nv04_graph_mthd_bind_class(object, args, size)) { case 0x30: - nv04_graph_set_ctx1(chan, 0x00004000, 0); - nv04_graph_set_ctx_val(chan, 0x02000000, 0); + nv04_graph_set_ctx1(object, 0x00004000, 0); + nv04_graph_set_ctx_val(object, 0x02000000, 0); return 0; case 0x42: - nv04_graph_set_ctx1(chan, 0x00004000, 0); - nv04_graph_set_ctx_val(chan, 0x02000000, 0x02000000); + nv04_graph_set_ctx1(object, 0x00004000, 0); + nv04_graph_set_ctx_val(object, 0x02000000, 0x02000000); return 0; } return 1; } static int -nv04_graph_mthd_bind_surf2d_swzsurf(struct nouveau_channel *chan, - u32 class, u32 mthd, u32 data) +nv04_graph_mthd_bind_surf2d_swzsurf(struct nouveau_object *object, u32 mthd, + void *args, u32 size) { - switch (nv_ri32(chan->dev, data << 4) & 0xff) { + switch (nv04_graph_mthd_bind_class(object, args, size)) { case 0x30: - nv04_graph_set_ctx1(chan, 0x00004000, 0); - nv04_graph_set_ctx_val(chan, 0x02000000, 0); + nv04_graph_set_ctx1(object, 0x00004000, 0); + nv04_graph_set_ctx_val(object, 0x02000000, 0); return 0; case 0x42: - nv04_graph_set_ctx1(chan, 0x00004000, 0); - nv04_graph_set_ctx_val(chan, 0x02000000, 0x02000000); + nv04_graph_set_ctx1(object, 0x00004000, 0); + nv04_graph_set_ctx_val(object, 0x02000000, 0x02000000); return 0; case 0x52: - nv04_graph_set_ctx1(chan, 0x00004000, 0x00004000); - nv04_graph_set_ctx_val(chan, 0x02000000, 0x02000000); + nv04_graph_set_ctx1(object, 0x00004000, 0x00004000); + nv04_graph_set_ctx_val(object, 0x02000000, 0x02000000); return 0; } return 1; } static int -nv04_graph_mthd_bind_nv01_patt(struct nouveau_channel *chan, - u32 class, u32 mthd, u32 data) +nv01_graph_mthd_bind_patt(struct nouveau_object *object, u32 mthd, + void *args, u32 size) { - switch (nv_ri32(chan->dev, data << 4) & 0xff) { + switch (nv04_graph_mthd_bind_class(object, args, size)) { case 0x30: - nv04_graph_set_ctx_val(chan, 0x08000000, 0); + nv04_graph_set_ctx_val(object, 0x08000000, 0); return 0; case 0x18: - nv04_graph_set_ctx_val(chan, 0x08000000, 0x08000000); + nv04_graph_set_ctx_val(object, 0x08000000, 0x08000000); return 0; } return 1; } static int -nv04_graph_mthd_bind_nv04_patt(struct nouveau_channel *chan, - u32 class, u32 mthd, u32 data) +nv04_graph_mthd_bind_patt(struct nouveau_object *object, u32 mthd, + void *args, u32 size) { - switch (nv_ri32(chan->dev, data << 4) & 0xff) { + switch (nv04_graph_mthd_bind_class(object, args, size)) { case 0x30: - nv04_graph_set_ctx_val(chan, 0x08000000, 0); + nv04_graph_set_ctx_val(object, 0x08000000, 0); return 0; case 0x44: - nv04_graph_set_ctx_val(chan, 0x08000000, 0x08000000); + nv04_graph_set_ctx_val(object, 0x08000000, 0x08000000); return 0; } return 1; } static int -nv04_graph_mthd_bind_rop(struct nouveau_channel *chan, - u32 class, u32 mthd, u32 data) +nv04_graph_mthd_bind_rop(struct nouveau_object *object, u32 mthd, + void *args, u32 size) { - switch (nv_ri32(chan->dev, data << 4) & 0xff) { + switch (nv04_graph_mthd_bind_class(object, args, size)) { case 0x30: - nv04_graph_set_ctx_val(chan, 0x10000000, 0); + nv04_graph_set_ctx_val(object, 0x10000000, 0); return 0; case 0x43: - nv04_graph_set_ctx_val(chan, 0x10000000, 0x10000000); + nv04_graph_set_ctx_val(object, 0x10000000, 0x10000000); return 0; } return 1; } static int -nv04_graph_mthd_bind_beta1(struct nouveau_channel *chan, - u32 class, u32 mthd, u32 data) +nv04_graph_mthd_bind_beta1(struct nouveau_object *object, u32 mthd, + void *args, u32 size) { - switch (nv_ri32(chan->dev, data << 4) & 0xff) { + switch (nv04_graph_mthd_bind_class(object, args, size)) { case 0x30: - nv04_graph_set_ctx_val(chan, 0x20000000, 0); + nv04_graph_set_ctx_val(object, 0x20000000, 0); return 0; case 0x12: - nv04_graph_set_ctx_val(chan, 0x20000000, 0x20000000); + nv04_graph_set_ctx_val(object, 0x20000000, 0x20000000); return 0; } return 1; } static int -nv04_graph_mthd_bind_beta4(struct nouveau_channel *chan, - u32 class, u32 mthd, u32 data) +nv04_graph_mthd_bind_beta4(struct nouveau_object *object, u32 mthd, + void *args, u32 size) { - switch (nv_ri32(chan->dev, data << 4) & 0xff) { + switch (nv04_graph_mthd_bind_class(object, args, size)) { case 0x30: - nv04_graph_set_ctx_val(chan, 0x40000000, 0); + nv04_graph_set_ctx_val(object, 0x40000000, 0); return 0; case 0x72: - nv04_graph_set_ctx_val(chan, 0x40000000, 0x40000000); + nv04_graph_set_ctx_val(object, 0x40000000, 0x40000000); return 0; } return 1; } static int -nv04_graph_mthd_bind_surf_dst(struct nouveau_channel *chan, - u32 class, u32 mthd, u32 data) +nv04_graph_mthd_bind_surf_dst(struct nouveau_object *object, u32 mthd, + void *args, u32 size) { - switch (nv_ri32(chan->dev, data << 4) & 0xff) { + switch (nv04_graph_mthd_bind_class(object, args, size)) { case 0x30: - nv04_graph_set_ctx_val(chan, 0x02000000, 0); + nv04_graph_set_ctx_val(object, 0x02000000, 0); return 0; case 0x58: - nv04_graph_set_ctx_val(chan, 0x02000000, 0x02000000); + nv04_graph_set_ctx_val(object, 0x02000000, 0x02000000); return 0; } return 1; } static int -nv04_graph_mthd_bind_surf_src(struct nouveau_channel *chan, - u32 class, u32 mthd, u32 data) +nv04_graph_mthd_bind_surf_src(struct nouveau_object *object, u32 mthd, + void *args, u32 size) { - switch (nv_ri32(chan->dev, data << 4) & 0xff) { + switch (nv04_graph_mthd_bind_class(object, args, size)) { case 0x30: - nv04_graph_set_ctx_val(chan, 0x04000000, 0); + nv04_graph_set_ctx_val(object, 0x04000000, 0); return 0; case 0x59: - nv04_graph_set_ctx_val(chan, 0x04000000, 0x04000000); + nv04_graph_set_ctx_val(object, 0x04000000, 0x04000000); return 0; } return 1; } static int -nv04_graph_mthd_bind_surf_color(struct nouveau_channel *chan, - u32 class, u32 mthd, u32 data) +nv04_graph_mthd_bind_surf_color(struct nouveau_object *object, u32 mthd, + void *args, u32 size) { - switch (nv_ri32(chan->dev, data << 4) & 0xff) { + switch (nv04_graph_mthd_bind_class(object, args, size)) { case 0x30: - nv04_graph_set_ctx_val(chan, 0x02000000, 0); + nv04_graph_set_ctx_val(object, 0x02000000, 0); return 0; case 0x5a: - nv04_graph_set_ctx_val(chan, 0x02000000, 0x02000000); + nv04_graph_set_ctx_val(object, 0x02000000, 0x02000000); return 0; } return 1; } static int -nv04_graph_mthd_bind_surf_zeta(struct nouveau_channel *chan, - u32 class, u32 mthd, u32 data) +nv04_graph_mthd_bind_surf_zeta(struct nouveau_object *object, u32 mthd, + void *args, u32 size) { - switch (nv_ri32(chan->dev, data << 4) & 0xff) { + switch (nv04_graph_mthd_bind_class(object, args, size)) { case 0x30: - nv04_graph_set_ctx_val(chan, 0x04000000, 0); + nv04_graph_set_ctx_val(object, 0x04000000, 0); return 0; case 0x5b: - nv04_graph_set_ctx_val(chan, 0x04000000, 0x04000000); + nv04_graph_set_ctx_val(object, 0x04000000, 0x04000000); return 0; } return 1; } static int -nv04_graph_mthd_bind_clip(struct nouveau_channel *chan, - u32 class, u32 mthd, u32 data) +nv01_graph_mthd_bind_clip(struct nouveau_object *object, u32 mthd, + void *args, u32 size) { - switch (nv_ri32(chan->dev, data << 4) & 0xff) { + switch (nv04_graph_mthd_bind_class(object, args, size)) { case 0x30: - nv04_graph_set_ctx1(chan, 0x2000, 0); + nv04_graph_set_ctx1(object, 0x2000, 0); return 0; case 0x19: - nv04_graph_set_ctx1(chan, 0x2000, 0x2000); + nv04_graph_set_ctx1(object, 0x2000, 0x2000); return 0; } return 1; } static int -nv04_graph_mthd_bind_chroma(struct nouveau_channel *chan, - u32 class, u32 mthd, u32 data) +nv01_graph_mthd_bind_chroma(struct nouveau_object *object, u32 mthd, + void *args, u32 size) { - switch (nv_ri32(chan->dev, data << 4) & 0xff) { + switch (nv04_graph_mthd_bind_class(object, args, size)) { case 0x30: - nv04_graph_set_ctx1(chan, 0x1000, 0); + nv04_graph_set_ctx1(object, 0x1000, 0); return 0; /* Yes, for some reason even the old versions of objects * accept 0x57 and not 0x17. Consistency be damned. */ case 0x57: - nv04_graph_set_ctx1(chan, 0x1000, 0x1000); + nv04_graph_set_ctx1(object, 0x1000, 0x1000); return 0; } return 1; } -static struct nouveau_bitfield nv04_graph_intr[] = { +static struct nouveau_omthds +nv03_graph_gdi_omthds[] = { + { 0x0184, nv01_graph_mthd_bind_patt }, + { 0x0188, nv04_graph_mthd_bind_rop }, + { 0x018c, nv04_graph_mthd_bind_beta1 }, + { 0x0190, nv04_graph_mthd_bind_surf_dst }, + { 0x02fc, nv04_graph_mthd_set_operation }, + {} +}; + +static struct nouveau_omthds +nv04_graph_gdi_omthds[] = { + { 0x0188, nv04_graph_mthd_bind_patt }, + { 0x018c, nv04_graph_mthd_bind_rop }, + { 0x0190, nv04_graph_mthd_bind_beta1 }, + { 0x0194, nv04_graph_mthd_bind_beta4 }, + { 0x0198, nv04_graph_mthd_bind_surf2d }, + { 0x02fc, nv04_graph_mthd_set_operation }, + {} +}; + +static struct nouveau_omthds +nv01_graph_blit_omthds[] = { + { 0x0184, nv01_graph_mthd_bind_chroma }, + { 0x0188, nv01_graph_mthd_bind_clip }, + { 0x018c, nv01_graph_mthd_bind_patt }, + { 0x0190, nv04_graph_mthd_bind_rop }, + { 0x0194, nv04_graph_mthd_bind_beta1 }, + { 0x0198, nv04_graph_mthd_bind_surf_dst }, + { 0x019c, nv04_graph_mthd_bind_surf_src }, + { 0x02fc, nv04_graph_mthd_set_operation }, + {} +}; + +static struct nouveau_omthds +nv04_graph_blit_omthds[] = { + { 0x0184, nv01_graph_mthd_bind_chroma }, + { 0x0188, nv01_graph_mthd_bind_clip }, + { 0x018c, nv04_graph_mthd_bind_patt }, + { 0x0190, nv04_graph_mthd_bind_rop }, + { 0x0194, nv04_graph_mthd_bind_beta1 }, + { 0x0198, nv04_graph_mthd_bind_beta4 }, + { 0x019c, nv04_graph_mthd_bind_surf2d }, + { 0x02fc, nv04_graph_mthd_set_operation }, + {} +}; + +static struct nouveau_omthds +nv04_graph_iifc_omthds[] = { + { 0x0188, nv01_graph_mthd_bind_chroma }, + { 0x018c, nv01_graph_mthd_bind_clip }, + { 0x0190, nv04_graph_mthd_bind_patt }, + { 0x0194, nv04_graph_mthd_bind_rop }, + { 0x0198, nv04_graph_mthd_bind_beta1 }, + { 0x019c, nv04_graph_mthd_bind_beta4 }, + { 0x01a0, nv04_graph_mthd_bind_surf2d_swzsurf }, + { 0x03e4, nv04_graph_mthd_set_operation }, + {} +}; + +static struct nouveau_omthds +nv01_graph_ifc_omthds[] = { + { 0x0184, nv01_graph_mthd_bind_chroma }, + { 0x0188, nv01_graph_mthd_bind_clip }, + { 0x018c, nv01_graph_mthd_bind_patt }, + { 0x0190, nv04_graph_mthd_bind_rop }, + { 0x0194, nv04_graph_mthd_bind_beta1 }, + { 0x0198, nv04_graph_mthd_bind_surf_dst }, + { 0x02fc, nv04_graph_mthd_set_operation }, + {} +}; + +static struct nouveau_omthds +nv04_graph_ifc_omthds[] = { + { 0x0184, nv01_graph_mthd_bind_chroma }, + { 0x0188, nv01_graph_mthd_bind_clip }, + { 0x018c, nv04_graph_mthd_bind_patt }, + { 0x0190, nv04_graph_mthd_bind_rop }, + { 0x0194, nv04_graph_mthd_bind_beta1 }, + { 0x0198, nv04_graph_mthd_bind_beta4 }, + { 0x019c, nv04_graph_mthd_bind_surf2d }, + { 0x02fc, nv04_graph_mthd_set_operation }, + {} +}; + +static struct nouveau_omthds +nv03_graph_sifc_omthds[] = { + { 0x0184, nv01_graph_mthd_bind_chroma }, + { 0x0188, nv01_graph_mthd_bind_patt }, + { 0x018c, nv04_graph_mthd_bind_rop }, + { 0x0190, nv04_graph_mthd_bind_beta1 }, + { 0x0194, nv04_graph_mthd_bind_surf_dst }, + { 0x02fc, nv04_graph_mthd_set_operation }, + {} +}; + +static struct nouveau_omthds +nv04_graph_sifc_omthds[] = { + { 0x0184, nv01_graph_mthd_bind_chroma }, + { 0x0188, nv04_graph_mthd_bind_patt }, + { 0x018c, nv04_graph_mthd_bind_rop }, + { 0x0190, nv04_graph_mthd_bind_beta1 }, + { 0x0194, nv04_graph_mthd_bind_beta4 }, + { 0x0198, nv04_graph_mthd_bind_surf2d }, + { 0x02fc, nv04_graph_mthd_set_operation }, + {} +}; + +static struct nouveau_omthds +nv03_graph_sifm_omthds[] = { + { 0x0188, nv01_graph_mthd_bind_patt }, + { 0x018c, nv04_graph_mthd_bind_rop }, + { 0x0190, nv04_graph_mthd_bind_beta1 }, + { 0x0194, nv04_graph_mthd_bind_surf_dst }, + { 0x0304, nv04_graph_mthd_set_operation }, + {} +}; + +static struct nouveau_omthds +nv04_graph_sifm_omthds[] = { + { 0x0188, nv04_graph_mthd_bind_patt }, + { 0x018c, nv04_graph_mthd_bind_rop }, + { 0x0190, nv04_graph_mthd_bind_beta1 }, + { 0x0194, nv04_graph_mthd_bind_beta4 }, + { 0x0198, nv04_graph_mthd_bind_surf2d }, + { 0x0304, nv04_graph_mthd_set_operation }, + {} +}; + +static struct nouveau_omthds +nv04_graph_surf3d_omthds[] = { + { 0x02f8, nv04_graph_mthd_surf3d_clip_h }, + { 0x02fc, nv04_graph_mthd_surf3d_clip_v }, + {} +}; + +static struct nouveau_omthds +nv03_graph_ttri_omthds[] = { + { 0x0188, nv01_graph_mthd_bind_clip }, + { 0x018c, nv04_graph_mthd_bind_surf_color }, + { 0x0190, nv04_graph_mthd_bind_surf_zeta }, + {} +}; + +static struct nouveau_omthds +nv01_graph_prim_omthds[] = { + { 0x0184, nv01_graph_mthd_bind_clip }, + { 0x0188, nv01_graph_mthd_bind_patt }, + { 0x018c, nv04_graph_mthd_bind_rop }, + { 0x0190, nv04_graph_mthd_bind_beta1 }, + { 0x0194, nv04_graph_mthd_bind_surf_dst }, + { 0x02fc, nv04_graph_mthd_set_operation }, + {} +}; + +static struct nouveau_omthds +nv04_graph_prim_omthds[] = { + { 0x0184, nv01_graph_mthd_bind_clip }, + { 0x0188, nv04_graph_mthd_bind_patt }, + { 0x018c, nv04_graph_mthd_bind_rop }, + { 0x0190, nv04_graph_mthd_bind_beta1 }, + { 0x0194, nv04_graph_mthd_bind_beta4 }, + { 0x0198, nv04_graph_mthd_bind_surf2d }, + { 0x02fc, nv04_graph_mthd_set_operation }, + {} +}; + +static int +nv04_graph_object_ctor(struct nouveau_object *parent, + struct nouveau_object *engine, + struct nouveau_oclass *oclass, void *data, u32 size, + struct nouveau_object **pobject) +{ + struct nouveau_gpuobj *obj; + int ret; + + ret = nouveau_gpuobj_create(parent, engine, oclass, 0, parent, + 16, 16, 0, &obj); + *pobject = nv_object(obj); + if (ret) + return ret; + + nv_wo32(obj, 0x00, nv_mclass(obj)); +#ifdef __BIG_ENDIAN + nv_mo32(obj, 0x00, 0x00080000, 0x00080000); +#endif + nv_wo32(obj, 0x04, 0x00000000); + nv_wo32(obj, 0x08, 0x00000000); + nv_wo32(obj, 0x0c, 0x00000000); + return 0; +} + +struct nouveau_ofuncs +nv04_graph_ofuncs = { + .ctor = nv04_graph_object_ctor, + .dtor = _nouveau_gpuobj_dtor, + .init = _nouveau_gpuobj_init, + .fini = _nouveau_gpuobj_fini, + .rd32 = _nouveau_gpuobj_rd32, + .wr32 = _nouveau_gpuobj_wr32, +}; + +static struct nouveau_oclass +nv04_graph_sclass[] = { + { 0x0012, &nv04_graph_ofuncs }, /* beta1 */ + { 0x0017, &nv04_graph_ofuncs }, /* chroma */ + { 0x0018, &nv04_graph_ofuncs }, /* pattern (nv01) */ + { 0x0019, &nv04_graph_ofuncs }, /* clip */ + { 0x001c, &nv04_graph_ofuncs, nv01_graph_prim_omthds }, /* line */ + { 0x001d, &nv04_graph_ofuncs, nv01_graph_prim_omthds }, /* tri */ + { 0x001e, &nv04_graph_ofuncs, nv01_graph_prim_omthds }, /* rect */ + { 0x001f, &nv04_graph_ofuncs, nv01_graph_blit_omthds }, + { 0x0021, &nv04_graph_ofuncs, nv01_graph_ifc_omthds }, + { 0x0030, &nv04_graph_ofuncs }, /* null */ + { 0x0036, &nv04_graph_ofuncs, nv03_graph_sifc_omthds }, + { 0x0037, &nv04_graph_ofuncs, nv03_graph_sifm_omthds }, + { 0x0038, &nv04_graph_ofuncs }, /* dvd subpicture */ + { 0x0039, &nv04_graph_ofuncs }, /* m2mf */ + { 0x0042, &nv04_graph_ofuncs }, /* surf2d */ + { 0x0043, &nv04_graph_ofuncs }, /* rop */ + { 0x0044, &nv04_graph_ofuncs }, /* pattern */ + { 0x0048, &nv04_graph_ofuncs, nv03_graph_ttri_omthds }, + { 0x004a, &nv04_graph_ofuncs, nv04_graph_gdi_omthds }, + { 0x004b, &nv04_graph_ofuncs, nv03_graph_gdi_omthds }, + { 0x0052, &nv04_graph_ofuncs }, /* swzsurf */ + { 0x0053, &nv04_graph_ofuncs, nv04_graph_surf3d_omthds }, + { 0x0054, &nv04_graph_ofuncs }, /* ttri */ + { 0x0055, &nv04_graph_ofuncs }, /* mtri */ + { 0x0057, &nv04_graph_ofuncs }, /* chroma */ + { 0x0058, &nv04_graph_ofuncs }, /* surf_dst */ + { 0x0059, &nv04_graph_ofuncs }, /* surf_src */ + { 0x005a, &nv04_graph_ofuncs }, /* surf_color */ + { 0x005b, &nv04_graph_ofuncs }, /* surf_zeta */ + { 0x005c, &nv04_graph_ofuncs, nv04_graph_prim_omthds }, /* line */ + { 0x005d, &nv04_graph_ofuncs, nv04_graph_prim_omthds }, /* tri */ + { 0x005e, &nv04_graph_ofuncs, nv04_graph_prim_omthds }, /* rect */ + { 0x005f, &nv04_graph_ofuncs, nv04_graph_blit_omthds }, + { 0x0060, &nv04_graph_ofuncs, nv04_graph_iifc_omthds }, + { 0x0061, &nv04_graph_ofuncs, nv04_graph_ifc_omthds }, + { 0x0064, &nv04_graph_ofuncs }, /* iifc (nv05) */ + { 0x0065, &nv04_graph_ofuncs }, /* ifc (nv05) */ + { 0x0066, &nv04_graph_ofuncs }, /* sifc (nv05) */ + { 0x0072, &nv04_graph_ofuncs }, /* beta4 */ + { 0x0076, &nv04_graph_ofuncs, nv04_graph_sifc_omthds }, + { 0x0077, &nv04_graph_ofuncs, nv04_graph_sifm_omthds }, + {}, +}; + +/******************************************************************************* + * PGRAPH context + ******************************************************************************/ + +static struct nv04_graph_chan * +nv04_graph_channel(struct nv04_graph_priv *priv) +{ + struct nv04_graph_chan *chan = NULL; + if (nv_rd32(priv, NV04_PGRAPH_CTX_CONTROL) & 0x00010000) { + int chid = nv_rd32(priv, NV04_PGRAPH_CTX_USER) >> 24; + if (chid < ARRAY_SIZE(priv->chan)) + chan = priv->chan[chid]; + } + return chan; +} + +static int +nv04_graph_load_context(struct nv04_graph_chan *chan, int chid) +{ + struct nv04_graph_priv *priv = nv04_graph_priv(chan); + int i; + + for (i = 0; i < ARRAY_SIZE(nv04_graph_ctx_regs); i++) + nv_wr32(priv, nv04_graph_ctx_regs[i], chan->nv04[i]); + + nv_wr32(priv, NV04_PGRAPH_CTX_CONTROL, 0x10010100); + nv_mask(priv, NV04_PGRAPH_CTX_USER, 0xff000000, chid << 24); + nv_mask(priv, NV04_PGRAPH_FFINTFC_ST2, 0xfff00000, 0x00000000); + return 0; +} + +static int +nv04_graph_unload_context(struct nv04_graph_chan *chan) +{ + struct nv04_graph_priv *priv = nv04_graph_priv(chan); + int i; + + for (i = 0; i < ARRAY_SIZE(nv04_graph_ctx_regs); i++) + chan->nv04[i] = nv_rd32(priv, nv04_graph_ctx_regs[i]); + + nv_wr32(priv, NV04_PGRAPH_CTX_CONTROL, 0x10000000); + nv_mask(priv, NV04_PGRAPH_CTX_USER, 0xff000000, 0x0f000000); + return 0; +} + +static void +nv04_graph_context_switch(struct nv04_graph_priv *priv) +{ + struct nv04_graph_chan *prev = NULL; + struct nv04_graph_chan *next = NULL; + unsigned long flags; + int chid; + + spin_lock_irqsave(&priv->lock, flags); + nv04_graph_idle(priv); + + /* If previous context is valid, we need to save it */ + prev = nv04_graph_channel(priv); + if (prev) + nv04_graph_unload_context(prev); + + /* load context for next channel */ + chid = (nv_rd32(priv, NV04_PGRAPH_TRAPPED_ADDR) >> 24) & 0x0f; + next = priv->chan[chid]; + if (next) + nv04_graph_load_context(next, chid); + + spin_unlock_irqrestore(&priv->lock, flags); +} + +static u32 *ctx_reg(struct nv04_graph_chan *chan, u32 reg) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(nv04_graph_ctx_regs); i++) { + if (nv04_graph_ctx_regs[i] == reg) + return &chan->nv04[i]; + } + + return NULL; +} + +static int +nv04_graph_context_ctor(struct nouveau_object *parent, + struct nouveau_object *engine, + struct nouveau_oclass *oclass, void *data, u32 size, + struct nouveau_object **pobject) +{ + struct nouveau_fifo_chan *fifo = (void *)parent; + struct nv04_graph_priv *priv = (void *)engine; + struct nv04_graph_chan *chan; + unsigned long flags; + int ret; + + ret = nouveau_object_create(parent, engine, oclass, 0, &chan); + *pobject = nv_object(chan); + if (ret) + return ret; + + spin_lock_irqsave(&priv->lock, flags); + if (priv->chan[fifo->chid]) { + *pobject = nv_object(priv->chan[fifo->chid]); + atomic_inc(&(*pobject)->refcount); + spin_unlock_irqrestore(&priv->lock, flags); + nouveau_object_destroy(&chan->base); + return 1; + } + + *ctx_reg(chan, NV04_PGRAPH_DEBUG_3) = 0xfad4ff31; + + priv->chan[fifo->chid] = chan; + chan->chid = fifo->chid; + spin_unlock_irqrestore(&priv->lock, flags); + return 0; +} + +static void +nv04_graph_context_dtor(struct nouveau_object *object) +{ + struct nv04_graph_priv *priv = (void *)object->engine; + struct nv04_graph_chan *chan = (void *)object; + unsigned long flags; + + spin_lock_irqsave(&priv->lock, flags); + priv->chan[chan->chid] = NULL; + spin_unlock_irqrestore(&priv->lock, flags); + + nouveau_object_destroy(&chan->base); +} + +static int +nv04_graph_context_fini(struct nouveau_object *object, bool suspend) +{ + struct nv04_graph_priv *priv = (void *)object->engine; + struct nv04_graph_chan *chan = (void *)object; + unsigned long flags; + + spin_lock_irqsave(&priv->lock, flags); + nv_mask(priv, NV04_PGRAPH_FIFO, 0x00000001, 0x00000000); + if (nv04_graph_channel(priv) == chan) + nv04_graph_unload_context(chan); + nv_mask(priv, NV04_PGRAPH_FIFO, 0x00000001, 0x00000001); + spin_unlock_irqrestore(&priv->lock, flags); + + return nouveau_object_fini(&chan->base, suspend); +} + +static struct nouveau_oclass +nv04_graph_cclass = { + .handle = NV_ENGCTX(GR, 0x04), + .ofuncs = &(struct nouveau_ofuncs) { + .ctor = nv04_graph_context_ctor, + .dtor = nv04_graph_context_dtor, + .init = nouveau_object_init, + .fini = nv04_graph_context_fini, + }, +}; + +/******************************************************************************* + * PGRAPH engine/subdev functions + ******************************************************************************/ + +bool +nv04_graph_idle(void *obj) +{ + struct nouveau_graph *graph = nouveau_graph(obj); + u32 mask = 0xffffffff; + + if (nv_device(obj)->card_type == NV_40) + mask &= ~NV40_PGRAPH_STATUS_SYNC_STALL; + + if (!nv_wait(graph, NV04_PGRAPH_STATUS, mask, 0)) { + nv_error(graph, "idle timed out with status 0x%08x\n", + nv_rd32(graph, NV04_PGRAPH_STATUS)); + return false; + } + + return true; +} + +static struct nouveau_bitfield +nv04_graph_intr_name[] = { { NV_PGRAPH_INTR_NOTIFY, "NOTIFY" }, {} }; -static struct nouveau_bitfield nv04_graph_nstatus[] = { +static struct nouveau_bitfield +nv04_graph_nstatus[] = { { NV04_PGRAPH_NSTATUS_STATE_IN_USE, "STATE_IN_USE" }, { NV04_PGRAPH_NSTATUS_INVALID_STATE, "INVALID_STATE" }, { NV04_PGRAPH_NSTATUS_BAD_ARGUMENT, "BAD_ARGUMENT" }, @@ -960,7 +1228,8 @@ static struct nouveau_bitfield nv04_graph_nstatus[] = { {} }; -struct nouveau_bitfield nv04_graph_nsource[] = { +struct nouveau_bitfield +nv04_graph_nsource[] = { { NV03_PGRAPH_NSOURCE_NOTIFICATION, "NOTIFICATION" }, { NV03_PGRAPH_NSOURCE_DATA_ERROR, "DATA_ERROR" }, { NV03_PGRAPH_NSOURCE_PROTECTION_ERROR, "PROTECTION_ERROR" }, @@ -984,343 +1253,135 @@ struct nouveau_bitfield nv04_graph_nsource[] = { }; static void -nv04_graph_context_switch(struct drm_device *dev) +nv04_graph_intr(struct nouveau_subdev *subdev) { - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_channel *chan = NULL; - int chid; - - nouveau_wait_for_idle(dev); - - /* If previous context is valid, we need to save it */ - nv04_graph_unload_context(dev); + struct nv04_graph_priv *priv = (void *)subdev; + struct nv04_graph_chan *chan = NULL; + struct nouveau_namedb *namedb = NULL; + struct nouveau_handle *handle = NULL; + u32 stat = nv_rd32(priv, NV03_PGRAPH_INTR); + u32 nsource = nv_rd32(priv, NV03_PGRAPH_NSOURCE); + u32 nstatus = nv_rd32(priv, NV03_PGRAPH_NSTATUS); + u32 addr = nv_rd32(priv, NV04_PGRAPH_TRAPPED_ADDR); + u32 chid = (addr & 0x0f000000) >> 24; + u32 subc = (addr & 0x0000e000) >> 13; + u32 mthd = (addr & 0x00001ffc); + u32 data = nv_rd32(priv, NV04_PGRAPH_TRAPPED_DATA); + u32 class = nv_rd32(priv, 0x400180 + subc * 4) & 0xff; + u32 inst = (nv_rd32(priv, 0x40016c) & 0xffff) << 4; + u32 show = stat; + unsigned long flags; - /* Load context for next channel */ - chid = nv_rd32(dev, NV03_PFIFO_CACHE1_PUSH1) & - NV03_PFIFO_CACHE1_PUSH1_CHID_MASK; - chan = dev_priv->channels.ptr[chid]; + spin_lock_irqsave(&priv->lock, flags); + chan = priv->chan[chid]; if (chan) - nv04_graph_load_context(chan); -} - -static void -nv04_graph_isr(struct drm_device *dev) -{ - u32 stat; - - while ((stat = nv_rd32(dev, NV03_PGRAPH_INTR))) { - u32 nsource = nv_rd32(dev, NV03_PGRAPH_NSOURCE); - u32 nstatus = nv_rd32(dev, NV03_PGRAPH_NSTATUS); - u32 addr = nv_rd32(dev, NV04_PGRAPH_TRAPPED_ADDR); - u32 chid = (addr & 0x0f000000) >> 24; - u32 subc = (addr & 0x0000e000) >> 13; - u32 mthd = (addr & 0x00001ffc); - u32 data = nv_rd32(dev, NV04_PGRAPH_TRAPPED_DATA); - u32 class = nv_rd32(dev, 0x400180 + subc * 4) & 0xff; - u32 show = stat; - - if (stat & NV_PGRAPH_INTR_NOTIFY) { - if (nsource & NV03_PGRAPH_NSOURCE_ILLEGAL_MTHD) { - if (!nouveau_gpuobj_mthd_call2(dev, chid, class, mthd, data)) - show &= ~NV_PGRAPH_INTR_NOTIFY; - } + namedb = (void *)nv_pclass(nv_object(chan), NV_NAMEDB_CLASS); + spin_unlock_irqrestore(&priv->lock, flags); + + if (stat & NV_PGRAPH_INTR_NOTIFY) { + if (chan && (nsource & NV03_PGRAPH_NSOURCE_ILLEGAL_MTHD)) { + handle = nouveau_namedb_get_vinst(namedb, inst); + if (handle && !nv_call(handle->object, mthd, data)) + show &= ~NV_PGRAPH_INTR_NOTIFY; } + } - if (stat & NV_PGRAPH_INTR_CONTEXT_SWITCH) { - nv_wr32(dev, NV03_PGRAPH_INTR, NV_PGRAPH_INTR_CONTEXT_SWITCH); - stat &= ~NV_PGRAPH_INTR_CONTEXT_SWITCH; - show &= ~NV_PGRAPH_INTR_CONTEXT_SWITCH; - nv04_graph_context_switch(dev); - } + if (stat & NV_PGRAPH_INTR_CONTEXT_SWITCH) { + nv_wr32(priv, NV03_PGRAPH_INTR, NV_PGRAPH_INTR_CONTEXT_SWITCH); + stat &= ~NV_PGRAPH_INTR_CONTEXT_SWITCH; + show &= ~NV_PGRAPH_INTR_CONTEXT_SWITCH; + nv04_graph_context_switch(priv); + } - nv_wr32(dev, NV03_PGRAPH_INTR, stat); - nv_wr32(dev, NV04_PGRAPH_FIFO, 0x00000001); - - if (show && nouveau_ratelimit()) { - NV_INFO(dev, "PGRAPH -"); - nouveau_bitfield_print(nv04_graph_intr, show); - printk(" nsource:"); - nouveau_bitfield_print(nv04_graph_nsource, nsource); - printk(" nstatus:"); - nouveau_bitfield_print(nv04_graph_nstatus, nstatus); - printk("\n"); - NV_INFO(dev, "PGRAPH - ch %d/%d class 0x%04x " - "mthd 0x%04x data 0x%08x\n", - chid, subc, class, mthd, data); - } + nv_wr32(priv, NV03_PGRAPH_INTR, stat); + nv_wr32(priv, NV04_PGRAPH_FIFO, 0x00000001); + + if (show) { + nv_error(priv, ""); + nouveau_bitfield_print(nv04_graph_intr_name, show); + printk(" nsource:"); + nouveau_bitfield_print(nv04_graph_nsource, nsource); + printk(" nstatus:"); + nouveau_bitfield_print(nv04_graph_nstatus, nstatus); + printk("\n"); + nv_error(priv, "ch %d/%d class 0x%04x " + "mthd 0x%04x data 0x%08x\n", + chid, subc, class, mthd, data); } + + nouveau_namedb_put(handle); } -static void -nv04_graph_destroy(struct drm_device *dev, int engine) +static int +nv04_graph_ctor(struct nouveau_object *parent, struct nouveau_object *engine, + struct nouveau_oclass *oclass, void *data, u32 size, + struct nouveau_object **pobject) { - struct nv04_graph_engine *pgraph = nv_engine(dev, engine); + struct nv04_graph_priv *priv; + int ret; - nouveau_irq_unregister(dev, 12); + ret = nouveau_graph_create(parent, engine, oclass, true, &priv); + *pobject = nv_object(priv); + if (ret) + return ret; - NVOBJ_ENGINE_DEL(dev, GR); - kfree(pgraph); + nv_subdev(priv)->unit = 0x00001000; + nv_subdev(priv)->intr = nv04_graph_intr; + nv_engine(priv)->cclass = &nv04_graph_cclass; + nv_engine(priv)->sclass = nv04_graph_sclass; + spin_lock_init(&priv->lock); + return 0; } -int -nv04_graph_create(struct drm_device *dev) +static int +nv04_graph_init(struct nouveau_object *object) { - struct nv04_graph_engine *pgraph; - - pgraph = kzalloc(sizeof(*pgraph), GFP_KERNEL); - if (!pgraph) - return -ENOMEM; - - pgraph->base.destroy = nv04_graph_destroy; - pgraph->base.init = nv04_graph_init; - pgraph->base.fini = nv04_graph_fini; - pgraph->base.context_new = nv04_graph_context_new; - pgraph->base.context_del = nv04_graph_context_del; - pgraph->base.object_new = nv04_graph_object_new; - - NVOBJ_ENGINE_ADD(dev, GR, &pgraph->base); - nouveau_irq_register(dev, 12, nv04_graph_isr); - - /* dvd subpicture */ - NVOBJ_CLASS(dev, 0x0038, GR); - - /* m2mf */ - NVOBJ_CLASS(dev, 0x0039, GR); - - /* nv03 gdirect */ - NVOBJ_CLASS(dev, 0x004b, GR); - NVOBJ_MTHD (dev, 0x004b, 0x0184, nv04_graph_mthd_bind_nv01_patt); - NVOBJ_MTHD (dev, 0x004b, 0x0188, nv04_graph_mthd_bind_rop); - NVOBJ_MTHD (dev, 0x004b, 0x018c, nv04_graph_mthd_bind_beta1); - NVOBJ_MTHD (dev, 0x004b, 0x0190, nv04_graph_mthd_bind_surf_dst); - NVOBJ_MTHD (dev, 0x004b, 0x02fc, nv04_graph_mthd_set_operation); - - /* nv04 gdirect */ - NVOBJ_CLASS(dev, 0x004a, GR); - NVOBJ_MTHD (dev, 0x004a, 0x0188, nv04_graph_mthd_bind_nv04_patt); - NVOBJ_MTHD (dev, 0x004a, 0x018c, nv04_graph_mthd_bind_rop); - NVOBJ_MTHD (dev, 0x004a, 0x0190, nv04_graph_mthd_bind_beta1); - NVOBJ_MTHD (dev, 0x004a, 0x0194, nv04_graph_mthd_bind_beta4); - NVOBJ_MTHD (dev, 0x004a, 0x0198, nv04_graph_mthd_bind_surf2d); - NVOBJ_MTHD (dev, 0x004a, 0x02fc, nv04_graph_mthd_set_operation); - - /* nv01 imageblit */ - NVOBJ_CLASS(dev, 0x001f, GR); - NVOBJ_MTHD (dev, 0x001f, 0x0184, nv04_graph_mthd_bind_chroma); - NVOBJ_MTHD (dev, 0x001f, 0x0188, nv04_graph_mthd_bind_clip); - NVOBJ_MTHD (dev, 0x001f, 0x018c, nv04_graph_mthd_bind_nv01_patt); - NVOBJ_MTHD (dev, 0x001f, 0x0190, nv04_graph_mthd_bind_rop); - NVOBJ_MTHD (dev, 0x001f, 0x0194, nv04_graph_mthd_bind_beta1); - NVOBJ_MTHD (dev, 0x001f, 0x0198, nv04_graph_mthd_bind_surf_dst); - NVOBJ_MTHD (dev, 0x001f, 0x019c, nv04_graph_mthd_bind_surf_src); - NVOBJ_MTHD (dev, 0x001f, 0x02fc, nv04_graph_mthd_set_operation); - - /* nv04 imageblit */ - NVOBJ_CLASS(dev, 0x005f, GR); - NVOBJ_MTHD (dev, 0x005f, 0x0184, nv04_graph_mthd_bind_chroma); - NVOBJ_MTHD (dev, 0x005f, 0x0188, nv04_graph_mthd_bind_clip); - NVOBJ_MTHD (dev, 0x005f, 0x018c, nv04_graph_mthd_bind_nv04_patt); - NVOBJ_MTHD (dev, 0x005f, 0x0190, nv04_graph_mthd_bind_rop); - NVOBJ_MTHD (dev, 0x005f, 0x0194, nv04_graph_mthd_bind_beta1); - NVOBJ_MTHD (dev, 0x005f, 0x0198, nv04_graph_mthd_bind_beta4); - NVOBJ_MTHD (dev, 0x005f, 0x019c, nv04_graph_mthd_bind_surf2d); - NVOBJ_MTHD (dev, 0x005f, 0x02fc, nv04_graph_mthd_set_operation); - - /* nv04 iifc */ - NVOBJ_CLASS(dev, 0x0060, GR); - NVOBJ_MTHD (dev, 0x0060, 0x0188, nv04_graph_mthd_bind_chroma); - NVOBJ_MTHD (dev, 0x0060, 0x018c, nv04_graph_mthd_bind_clip); - NVOBJ_MTHD (dev, 0x0060, 0x0190, nv04_graph_mthd_bind_nv04_patt); - NVOBJ_MTHD (dev, 0x0060, 0x0194, nv04_graph_mthd_bind_rop); - NVOBJ_MTHD (dev, 0x0060, 0x0198, nv04_graph_mthd_bind_beta1); - NVOBJ_MTHD (dev, 0x0060, 0x019c, nv04_graph_mthd_bind_beta4); - NVOBJ_MTHD (dev, 0x0060, 0x01a0, nv04_graph_mthd_bind_surf2d_swzsurf); - NVOBJ_MTHD (dev, 0x0060, 0x03e4, nv04_graph_mthd_set_operation); - - /* nv05 iifc */ - NVOBJ_CLASS(dev, 0x0064, GR); - - /* nv01 ifc */ - NVOBJ_CLASS(dev, 0x0021, GR); - NVOBJ_MTHD (dev, 0x0021, 0x0184, nv04_graph_mthd_bind_chroma); - NVOBJ_MTHD (dev, 0x0021, 0x0188, nv04_graph_mthd_bind_clip); - NVOBJ_MTHD (dev, 0x0021, 0x018c, nv04_graph_mthd_bind_nv01_patt); - NVOBJ_MTHD (dev, 0x0021, 0x0190, nv04_graph_mthd_bind_rop); - NVOBJ_MTHD (dev, 0x0021, 0x0194, nv04_graph_mthd_bind_beta1); - NVOBJ_MTHD (dev, 0x0021, 0x0198, nv04_graph_mthd_bind_surf_dst); - NVOBJ_MTHD (dev, 0x0021, 0x02fc, nv04_graph_mthd_set_operation); - - /* nv04 ifc */ - NVOBJ_CLASS(dev, 0x0061, GR); - NVOBJ_MTHD (dev, 0x0061, 0x0184, nv04_graph_mthd_bind_chroma); - NVOBJ_MTHD (dev, 0x0061, 0x0188, nv04_graph_mthd_bind_clip); - NVOBJ_MTHD (dev, 0x0061, 0x018c, nv04_graph_mthd_bind_nv04_patt); - NVOBJ_MTHD (dev, 0x0061, 0x0190, nv04_graph_mthd_bind_rop); - NVOBJ_MTHD (dev, 0x0061, 0x0194, nv04_graph_mthd_bind_beta1); - NVOBJ_MTHD (dev, 0x0061, 0x0198, nv04_graph_mthd_bind_beta4); - NVOBJ_MTHD (dev, 0x0061, 0x019c, nv04_graph_mthd_bind_surf2d); - NVOBJ_MTHD (dev, 0x0061, 0x02fc, nv04_graph_mthd_set_operation); - - /* nv05 ifc */ - NVOBJ_CLASS(dev, 0x0065, GR); - - /* nv03 sifc */ - NVOBJ_CLASS(dev, 0x0036, GR); - NVOBJ_MTHD (dev, 0x0036, 0x0184, nv04_graph_mthd_bind_chroma); - NVOBJ_MTHD (dev, 0x0036, 0x0188, nv04_graph_mthd_bind_nv01_patt); - NVOBJ_MTHD (dev, 0x0036, 0x018c, nv04_graph_mthd_bind_rop); - NVOBJ_MTHD (dev, 0x0036, 0x0190, nv04_graph_mthd_bind_beta1); - NVOBJ_MTHD (dev, 0x0036, 0x0194, nv04_graph_mthd_bind_surf_dst); - NVOBJ_MTHD (dev, 0x0036, 0x02fc, nv04_graph_mthd_set_operation); - - /* nv04 sifc */ - NVOBJ_CLASS(dev, 0x0076, GR); - NVOBJ_MTHD (dev, 0x0076, 0x0184, nv04_graph_mthd_bind_chroma); - NVOBJ_MTHD (dev, 0x0076, 0x0188, nv04_graph_mthd_bind_nv04_patt); - NVOBJ_MTHD (dev, 0x0076, 0x018c, nv04_graph_mthd_bind_rop); - NVOBJ_MTHD (dev, 0x0076, 0x0190, nv04_graph_mthd_bind_beta1); - NVOBJ_MTHD (dev, 0x0076, 0x0194, nv04_graph_mthd_bind_beta4); - NVOBJ_MTHD (dev, 0x0076, 0x0198, nv04_graph_mthd_bind_surf2d); - NVOBJ_MTHD (dev, 0x0076, 0x02fc, nv04_graph_mthd_set_operation); - - /* nv05 sifc */ - NVOBJ_CLASS(dev, 0x0066, GR); - - /* nv03 sifm */ - NVOBJ_CLASS(dev, 0x0037, GR); - NVOBJ_MTHD (dev, 0x0037, 0x0188, nv04_graph_mthd_bind_nv01_patt); - NVOBJ_MTHD (dev, 0x0037, 0x018c, nv04_graph_mthd_bind_rop); - NVOBJ_MTHD (dev, 0x0037, 0x0190, nv04_graph_mthd_bind_beta1); - NVOBJ_MTHD (dev, 0x0037, 0x0194, nv04_graph_mthd_bind_surf_dst); - NVOBJ_MTHD (dev, 0x0037, 0x0304, nv04_graph_mthd_set_operation); - - /* nv04 sifm */ - NVOBJ_CLASS(dev, 0x0077, GR); - NVOBJ_MTHD (dev, 0x0077, 0x0188, nv04_graph_mthd_bind_nv04_patt); - NVOBJ_MTHD (dev, 0x0077, 0x018c, nv04_graph_mthd_bind_rop); - NVOBJ_MTHD (dev, 0x0077, 0x0190, nv04_graph_mthd_bind_beta1); - NVOBJ_MTHD (dev, 0x0077, 0x0194, nv04_graph_mthd_bind_beta4); - NVOBJ_MTHD (dev, 0x0077, 0x0198, nv04_graph_mthd_bind_surf2d_swzsurf); - NVOBJ_MTHD (dev, 0x0077, 0x0304, nv04_graph_mthd_set_operation); - - /* null */ - NVOBJ_CLASS(dev, 0x0030, GR); - - /* surf2d */ - NVOBJ_CLASS(dev, 0x0042, GR); - - /* rop */ - NVOBJ_CLASS(dev, 0x0043, GR); - - /* beta1 */ - NVOBJ_CLASS(dev, 0x0012, GR); - - /* beta4 */ - NVOBJ_CLASS(dev, 0x0072, GR); - - /* cliprect */ - NVOBJ_CLASS(dev, 0x0019, GR); - - /* nv01 pattern */ - NVOBJ_CLASS(dev, 0x0018, GR); - - /* nv04 pattern */ - NVOBJ_CLASS(dev, 0x0044, GR); - - /* swzsurf */ - NVOBJ_CLASS(dev, 0x0052, GR); - - /* surf3d */ - NVOBJ_CLASS(dev, 0x0053, GR); - NVOBJ_MTHD (dev, 0x0053, 0x02f8, nv04_graph_mthd_surf3d_clip_h); - NVOBJ_MTHD (dev, 0x0053, 0x02fc, nv04_graph_mthd_surf3d_clip_v); - - /* nv03 tex_tri */ - NVOBJ_CLASS(dev, 0x0048, GR); - NVOBJ_MTHD (dev, 0x0048, 0x0188, nv04_graph_mthd_bind_clip); - NVOBJ_MTHD (dev, 0x0048, 0x018c, nv04_graph_mthd_bind_surf_color); - NVOBJ_MTHD (dev, 0x0048, 0x0190, nv04_graph_mthd_bind_surf_zeta); - - /* tex_tri */ - NVOBJ_CLASS(dev, 0x0054, GR); - - /* multitex_tri */ - NVOBJ_CLASS(dev, 0x0055, GR); - - /* nv01 chroma */ - NVOBJ_CLASS(dev, 0x0017, GR); - - /* nv04 chroma */ - NVOBJ_CLASS(dev, 0x0057, GR); - - /* surf_dst */ - NVOBJ_CLASS(dev, 0x0058, GR); - - /* surf_src */ - NVOBJ_CLASS(dev, 0x0059, GR); - - /* surf_color */ - NVOBJ_CLASS(dev, 0x005a, GR); - - /* surf_zeta */ - NVOBJ_CLASS(dev, 0x005b, GR); - - /* nv01 line */ - NVOBJ_CLASS(dev, 0x001c, GR); - NVOBJ_MTHD (dev, 0x001c, 0x0184, nv04_graph_mthd_bind_clip); - NVOBJ_MTHD (dev, 0x001c, 0x0188, nv04_graph_mthd_bind_nv01_patt); - NVOBJ_MTHD (dev, 0x001c, 0x018c, nv04_graph_mthd_bind_rop); - NVOBJ_MTHD (dev, 0x001c, 0x0190, nv04_graph_mthd_bind_beta1); - NVOBJ_MTHD (dev, 0x001c, 0x0194, nv04_graph_mthd_bind_surf_dst); - NVOBJ_MTHD (dev, 0x001c, 0x02fc, nv04_graph_mthd_set_operation); - - /* nv04 line */ - NVOBJ_CLASS(dev, 0x005c, GR); - NVOBJ_MTHD (dev, 0x005c, 0x0184, nv04_graph_mthd_bind_clip); - NVOBJ_MTHD (dev, 0x005c, 0x0188, nv04_graph_mthd_bind_nv04_patt); - NVOBJ_MTHD (dev, 0x005c, 0x018c, nv04_graph_mthd_bind_rop); - NVOBJ_MTHD (dev, 0x005c, 0x0190, nv04_graph_mthd_bind_beta1); - NVOBJ_MTHD (dev, 0x005c, 0x0194, nv04_graph_mthd_bind_beta4); - NVOBJ_MTHD (dev, 0x005c, 0x0198, nv04_graph_mthd_bind_surf2d); - NVOBJ_MTHD (dev, 0x005c, 0x02fc, nv04_graph_mthd_set_operation); - - /* nv01 tri */ - NVOBJ_CLASS(dev, 0x001d, GR); - NVOBJ_MTHD (dev, 0x001d, 0x0184, nv04_graph_mthd_bind_clip); - NVOBJ_MTHD (dev, 0x001d, 0x0188, nv04_graph_mthd_bind_nv01_patt); - NVOBJ_MTHD (dev, 0x001d, 0x018c, nv04_graph_mthd_bind_rop); - NVOBJ_MTHD (dev, 0x001d, 0x0190, nv04_graph_mthd_bind_beta1); - NVOBJ_MTHD (dev, 0x001d, 0x0194, nv04_graph_mthd_bind_surf_dst); - NVOBJ_MTHD (dev, 0x001d, 0x02fc, nv04_graph_mthd_set_operation); - - /* nv04 tri */ - NVOBJ_CLASS(dev, 0x005d, GR); - NVOBJ_MTHD (dev, 0x005d, 0x0184, nv04_graph_mthd_bind_clip); - NVOBJ_MTHD (dev, 0x005d, 0x0188, nv04_graph_mthd_bind_nv04_patt); - NVOBJ_MTHD (dev, 0x005d, 0x018c, nv04_graph_mthd_bind_rop); - NVOBJ_MTHD (dev, 0x005d, 0x0190, nv04_graph_mthd_bind_beta1); - NVOBJ_MTHD (dev, 0x005d, 0x0194, nv04_graph_mthd_bind_beta4); - NVOBJ_MTHD (dev, 0x005d, 0x0198, nv04_graph_mthd_bind_surf2d); - NVOBJ_MTHD (dev, 0x005d, 0x02fc, nv04_graph_mthd_set_operation); - - /* nv01 rect */ - NVOBJ_CLASS(dev, 0x001e, GR); - NVOBJ_MTHD (dev, 0x001e, 0x0184, nv04_graph_mthd_bind_clip); - NVOBJ_MTHD (dev, 0x001e, 0x0188, nv04_graph_mthd_bind_nv01_patt); - NVOBJ_MTHD (dev, 0x001e, 0x018c, nv04_graph_mthd_bind_rop); - NVOBJ_MTHD (dev, 0x001e, 0x0190, nv04_graph_mthd_bind_beta1); - NVOBJ_MTHD (dev, 0x001e, 0x0194, nv04_graph_mthd_bind_surf_dst); - NVOBJ_MTHD (dev, 0x001e, 0x02fc, nv04_graph_mthd_set_operation); - - /* nv04 rect */ - NVOBJ_CLASS(dev, 0x005e, GR); - NVOBJ_MTHD (dev, 0x005e, 0x0184, nv04_graph_mthd_bind_clip); - NVOBJ_MTHD (dev, 0x005e, 0x0188, nv04_graph_mthd_bind_nv04_patt); - NVOBJ_MTHD (dev, 0x005e, 0x018c, nv04_graph_mthd_bind_rop); - NVOBJ_MTHD (dev, 0x005e, 0x0190, nv04_graph_mthd_bind_beta1); - NVOBJ_MTHD (dev, 0x005e, 0x0194, nv04_graph_mthd_bind_beta4); - NVOBJ_MTHD (dev, 0x005e, 0x0198, nv04_graph_mthd_bind_surf2d); - NVOBJ_MTHD (dev, 0x005e, 0x02fc, nv04_graph_mthd_set_operation); + struct nouveau_engine *engine = nv_engine(object); + struct nv04_graph_priv *priv = (void *)engine; + int ret; + + ret = nouveau_graph_init(&priv->base); + if (ret) + return ret; + /* Enable PGRAPH interrupts */ + nv_wr32(priv, NV03_PGRAPH_INTR, 0xFFFFFFFF); + nv_wr32(priv, NV03_PGRAPH_INTR_EN, 0xFFFFFFFF); + + nv_wr32(priv, NV04_PGRAPH_VALID1, 0); + nv_wr32(priv, NV04_PGRAPH_VALID2, 0); + /*nv_wr32(priv, NV04_PGRAPH_DEBUG_0, 0x000001FF); + nv_wr32(priv, NV04_PGRAPH_DEBUG_0, 0x001FFFFF);*/ + nv_wr32(priv, NV04_PGRAPH_DEBUG_0, 0x1231c000); + /*1231C000 blob, 001 haiku*/ + /*V_WRITE(NV04_PGRAPH_DEBUG_1, 0xf2d91100);*/ + nv_wr32(priv, NV04_PGRAPH_DEBUG_1, 0x72111100); + /*0x72111100 blob , 01 haiku*/ + /*nv_wr32(priv, NV04_PGRAPH_DEBUG_2, 0x11d5f870);*/ + nv_wr32(priv, NV04_PGRAPH_DEBUG_2, 0x11d5f071); + /*haiku same*/ + + /*nv_wr32(priv, NV04_PGRAPH_DEBUG_3, 0xfad4ff31);*/ + nv_wr32(priv, NV04_PGRAPH_DEBUG_3, 0xf0d4ff31); + /*haiku and blob 10d4*/ + + nv_wr32(priv, NV04_PGRAPH_STATE , 0xFFFFFFFF); + nv_wr32(priv, NV04_PGRAPH_CTX_CONTROL , 0x10000100); + nv_mask(priv, NV04_PGRAPH_CTX_USER, 0xff000000, 0x0f000000); + + /* These don't belong here, they're part of a per-channel context */ + nv_wr32(priv, NV04_PGRAPH_PATTERN_SHAPE, 0x00000000); + nv_wr32(priv, NV04_PGRAPH_BETA_AND , 0xFFFFFFFF); return 0; } + +struct nouveau_oclass +nv04_graph_oclass = { + .handle = NV_ENGINE(GR, 0x04), + .ofuncs = &(struct nouveau_ofuncs) { + .ctor = nv04_graph_ctor, + .dtor = _nouveau_graph_dtor, + .init = nv04_graph_init, + .fini = _nouveau_graph_fini, + }, +}; diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/nv10.c b/drivers/gpu/drm/nouveau/core/engine/graph/nv10.c index d006658e6468..ce38196634df 100644 --- a/drivers/gpu/drm/nouveau/core/engine/graph/nv10.c +++ b/drivers/gpu/drm/nouveau/core/engine/graph/nv10.c @@ -22,27 +22,28 @@ * DEALINGS IN THE SOFTWARE. */ -#include "drmP.h" -#include "drm.h" -#include -#include "nouveau_drv.h" -#include "nouveau_util.h" - -struct nv10_graph_engine { - struct nouveau_exec_engine base; -}; +#include +#include +#include + +#include + +#include +#include + +#include "regs.h" struct pipe_state { - uint32_t pipe_0x0000[0x040/4]; - uint32_t pipe_0x0040[0x010/4]; - uint32_t pipe_0x0200[0x0c0/4]; - uint32_t pipe_0x4400[0x080/4]; - uint32_t pipe_0x6400[0x3b0/4]; - uint32_t pipe_0x6800[0x2f0/4]; - uint32_t pipe_0x6c00[0x030/4]; - uint32_t pipe_0x7000[0x130/4]; - uint32_t pipe_0x7400[0x0c0/4]; - uint32_t pipe_0x7800[0x0c0/4]; + u32 pipe_0x0000[0x040/4]; + u32 pipe_0x0040[0x010/4]; + u32 pipe_0x0200[0x0c0/4]; + u32 pipe_0x4400[0x080/4]; + u32 pipe_0x6400[0x3b0/4]; + u32 pipe_0x6800[0x2f0/4]; + u32 pipe_0x6c00[0x030/4]; + u32 pipe_0x7000[0x130/4]; + u32 pipe_0x7400[0x0c0/4]; + u32 pipe_0x7800[0x0c0/4]; }; static int nv10_graph_ctx_regs[] = { @@ -388,117 +389,322 @@ static int nv17_graph_ctx_regs[] = { 0x00400a04, }; -struct graph_state { +struct nv10_graph_priv { + struct nouveau_graph base; + struct nv10_graph_chan *chan[32]; + spinlock_t lock; +}; + +struct nv10_graph_chan { + struct nouveau_object base; + int chid; int nv10[ARRAY_SIZE(nv10_graph_ctx_regs)]; int nv17[ARRAY_SIZE(nv17_graph_ctx_regs)]; struct pipe_state pipe_state; - uint32_t lma_window[4]; + u32 lma_window[4]; }; -#define PIPE_SAVE(dev, state, addr) \ + +static inline struct nv10_graph_priv * +nv10_graph_priv(struct nv10_graph_chan *chan) +{ + return (void *)nv_object(chan)->engine; +} + +/******************************************************************************* + * Graphics object classes + ******************************************************************************/ + +#define PIPE_SAVE(priv, state, addr) \ do { \ int __i; \ - nv_wr32(dev, NV10_PGRAPH_PIPE_ADDRESS, addr); \ + nv_wr32(priv, NV10_PGRAPH_PIPE_ADDRESS, addr); \ for (__i = 0; __i < ARRAY_SIZE(state); __i++) \ - state[__i] = nv_rd32(dev, NV10_PGRAPH_PIPE_DATA); \ + state[__i] = nv_rd32(priv, NV10_PGRAPH_PIPE_DATA); \ } while (0) -#define PIPE_RESTORE(dev, state, addr) \ +#define PIPE_RESTORE(priv, state, addr) \ do { \ int __i; \ - nv_wr32(dev, NV10_PGRAPH_PIPE_ADDRESS, addr); \ + nv_wr32(priv, NV10_PGRAPH_PIPE_ADDRESS, addr); \ for (__i = 0; __i < ARRAY_SIZE(state); __i++) \ - nv_wr32(dev, NV10_PGRAPH_PIPE_DATA, state[__i]); \ + nv_wr32(priv, NV10_PGRAPH_PIPE_DATA, state[__i]); \ } while (0) -static void nv10_graph_save_pipe(struct nouveau_channel *chan) +static struct nouveau_oclass +nv10_graph_sclass[] = { + { 0x0012, &nv04_graph_ofuncs }, /* beta1 */ + { 0x0019, &nv04_graph_ofuncs }, /* clip */ + { 0x0030, &nv04_graph_ofuncs }, /* null */ + { 0x0039, &nv04_graph_ofuncs }, /* m2mf */ + { 0x0043, &nv04_graph_ofuncs }, /* rop */ + { 0x0044, &nv04_graph_ofuncs }, /* pattern */ + { 0x004a, &nv04_graph_ofuncs }, /* gdi */ + { 0x0052, &nv04_graph_ofuncs }, /* swzsurf */ + { 0x005f, &nv04_graph_ofuncs }, /* blit */ + { 0x0062, &nv04_graph_ofuncs }, /* surf2d */ + { 0x0072, &nv04_graph_ofuncs }, /* beta4 */ + { 0x0089, &nv04_graph_ofuncs }, /* sifm */ + { 0x008a, &nv04_graph_ofuncs }, /* ifc */ + { 0x009f, &nv04_graph_ofuncs }, /* blit */ + { 0x0093, &nv04_graph_ofuncs }, /* surf3d */ + { 0x0094, &nv04_graph_ofuncs }, /* ttri */ + { 0x0095, &nv04_graph_ofuncs }, /* mtri */ + { 0x0056, &nv04_graph_ofuncs }, /* celcius */ + {}, +}; + +static struct nouveau_oclass +nv15_graph_sclass[] = { + { 0x0012, &nv04_graph_ofuncs }, /* beta1 */ + { 0x0019, &nv04_graph_ofuncs }, /* clip */ + { 0x0030, &nv04_graph_ofuncs }, /* null */ + { 0x0039, &nv04_graph_ofuncs }, /* m2mf */ + { 0x0043, &nv04_graph_ofuncs }, /* rop */ + { 0x0044, &nv04_graph_ofuncs }, /* pattern */ + { 0x004a, &nv04_graph_ofuncs }, /* gdi */ + { 0x0052, &nv04_graph_ofuncs }, /* swzsurf */ + { 0x005f, &nv04_graph_ofuncs }, /* blit */ + { 0x0062, &nv04_graph_ofuncs }, /* surf2d */ + { 0x0072, &nv04_graph_ofuncs }, /* beta4 */ + { 0x0089, &nv04_graph_ofuncs }, /* sifm */ + { 0x008a, &nv04_graph_ofuncs }, /* ifc */ + { 0x009f, &nv04_graph_ofuncs }, /* blit */ + { 0x0093, &nv04_graph_ofuncs }, /* surf3d */ + { 0x0094, &nv04_graph_ofuncs }, /* ttri */ + { 0x0095, &nv04_graph_ofuncs }, /* mtri */ + { 0x0096, &nv04_graph_ofuncs }, /* celcius */ + {}, +}; + +static int +nv17_graph_mthd_lma_window(struct nouveau_object *object, u32 mthd, + void *args, u32 size) +{ + struct nv10_graph_chan *chan = (void *)object->parent; + struct nv10_graph_priv *priv = nv10_graph_priv(chan); + struct pipe_state *pipe = &chan->pipe_state; + u32 pipe_0x0040[1], pipe_0x64c0[8], pipe_0x6a80[3], pipe_0x6ab0[3]; + u32 xfmode0, xfmode1; + u32 data = *(u32 *)args; + int i; + + chan->lma_window[(mthd - 0x1638) / 4] = data; + + if (mthd != 0x1644) + return 0; + + nv04_graph_idle(priv); + + PIPE_SAVE(priv, pipe_0x0040, 0x0040); + PIPE_SAVE(priv, pipe->pipe_0x0200, 0x0200); + + PIPE_RESTORE(priv, chan->lma_window, 0x6790); + + nv04_graph_idle(priv); + + xfmode0 = nv_rd32(priv, NV10_PGRAPH_XFMODE0); + xfmode1 = nv_rd32(priv, NV10_PGRAPH_XFMODE1); + + PIPE_SAVE(priv, pipe->pipe_0x4400, 0x4400); + PIPE_SAVE(priv, pipe_0x64c0, 0x64c0); + PIPE_SAVE(priv, pipe_0x6ab0, 0x6ab0); + PIPE_SAVE(priv, pipe_0x6a80, 0x6a80); + + nv04_graph_idle(priv); + + nv_wr32(priv, NV10_PGRAPH_XFMODE0, 0x10000000); + nv_wr32(priv, NV10_PGRAPH_XFMODE1, 0x00000000); + nv_wr32(priv, NV10_PGRAPH_PIPE_ADDRESS, 0x000064c0); + for (i = 0; i < 4; i++) + nv_wr32(priv, NV10_PGRAPH_PIPE_DATA, 0x3f800000); + for (i = 0; i < 4; i++) + nv_wr32(priv, NV10_PGRAPH_PIPE_DATA, 0x00000000); + + nv_wr32(priv, NV10_PGRAPH_PIPE_ADDRESS, 0x00006ab0); + for (i = 0; i < 3; i++) + nv_wr32(priv, NV10_PGRAPH_PIPE_DATA, 0x3f800000); + + nv_wr32(priv, NV10_PGRAPH_PIPE_ADDRESS, 0x00006a80); + for (i = 0; i < 3; i++) + nv_wr32(priv, NV10_PGRAPH_PIPE_DATA, 0x00000000); + + nv_wr32(priv, NV10_PGRAPH_PIPE_ADDRESS, 0x00000040); + nv_wr32(priv, NV10_PGRAPH_PIPE_DATA, 0x00000008); + + PIPE_RESTORE(priv, pipe->pipe_0x0200, 0x0200); + + nv04_graph_idle(priv); + + PIPE_RESTORE(priv, pipe_0x0040, 0x0040); + + nv_wr32(priv, NV10_PGRAPH_XFMODE0, xfmode0); + nv_wr32(priv, NV10_PGRAPH_XFMODE1, xfmode1); + + PIPE_RESTORE(priv, pipe_0x64c0, 0x64c0); + PIPE_RESTORE(priv, pipe_0x6ab0, 0x6ab0); + PIPE_RESTORE(priv, pipe_0x6a80, 0x6a80); + PIPE_RESTORE(priv, pipe->pipe_0x4400, 0x4400); + + nv_wr32(priv, NV10_PGRAPH_PIPE_ADDRESS, 0x000000c0); + nv_wr32(priv, NV10_PGRAPH_PIPE_DATA, 0x00000000); + + nv04_graph_idle(priv); + + return 0; +} + +static int +nv17_graph_mthd_lma_enable(struct nouveau_object *object, u32 mthd, + void *args, u32 size) { - struct graph_state *pgraph_ctx = chan->engctx[NVOBJ_ENGINE_GR]; - struct pipe_state *pipe = &pgraph_ctx->pipe_state; - struct drm_device *dev = chan->dev; - - PIPE_SAVE(dev, pipe->pipe_0x4400, 0x4400); - PIPE_SAVE(dev, pipe->pipe_0x0200, 0x0200); - PIPE_SAVE(dev, pipe->pipe_0x6400, 0x6400); - PIPE_SAVE(dev, pipe->pipe_0x6800, 0x6800); - PIPE_SAVE(dev, pipe->pipe_0x6c00, 0x6c00); - PIPE_SAVE(dev, pipe->pipe_0x7000, 0x7000); - PIPE_SAVE(dev, pipe->pipe_0x7400, 0x7400); - PIPE_SAVE(dev, pipe->pipe_0x7800, 0x7800); - PIPE_SAVE(dev, pipe->pipe_0x0040, 0x0040); - PIPE_SAVE(dev, pipe->pipe_0x0000, 0x0000); + struct nv10_graph_chan *chan = (void *)object->parent; + struct nv10_graph_priv *priv = nv10_graph_priv(chan); + + nv04_graph_idle(priv); + + nv_mask(priv, NV10_PGRAPH_DEBUG_4, 0x00000100, 0x00000100); + nv_mask(priv, 0x4006b0, 0x08000000, 0x08000000); + return 0; } -static void nv10_graph_load_pipe(struct nouveau_channel *chan) +static struct nouveau_omthds +nv17_celcius_omthds[] = { + { 0x1638, nv17_graph_mthd_lma_window }, + { 0x163c, nv17_graph_mthd_lma_window }, + { 0x1640, nv17_graph_mthd_lma_window }, + { 0x1644, nv17_graph_mthd_lma_window }, + { 0x1658, nv17_graph_mthd_lma_enable }, + {} +}; + +static struct nouveau_oclass +nv17_graph_sclass[] = { + { 0x0012, &nv04_graph_ofuncs }, /* beta1 */ + { 0x0019, &nv04_graph_ofuncs }, /* clip */ + { 0x0030, &nv04_graph_ofuncs }, /* null */ + { 0x0039, &nv04_graph_ofuncs }, /* m2mf */ + { 0x0043, &nv04_graph_ofuncs }, /* rop */ + { 0x0044, &nv04_graph_ofuncs }, /* pattern */ + { 0x004a, &nv04_graph_ofuncs }, /* gdi */ + { 0x0052, &nv04_graph_ofuncs }, /* swzsurf */ + { 0x005f, &nv04_graph_ofuncs }, /* blit */ + { 0x0062, &nv04_graph_ofuncs }, /* surf2d */ + { 0x0072, &nv04_graph_ofuncs }, /* beta4 */ + { 0x0089, &nv04_graph_ofuncs }, /* sifm */ + { 0x008a, &nv04_graph_ofuncs }, /* ifc */ + { 0x009f, &nv04_graph_ofuncs }, /* blit */ + { 0x0093, &nv04_graph_ofuncs }, /* surf3d */ + { 0x0094, &nv04_graph_ofuncs }, /* ttri */ + { 0x0095, &nv04_graph_ofuncs }, /* mtri */ + { 0x0099, &nv04_graph_ofuncs, nv17_celcius_omthds }, + {}, +}; + +/******************************************************************************* + * PGRAPH context + ******************************************************************************/ + +static struct nv10_graph_chan * +nv10_graph_channel(struct nv10_graph_priv *priv) { - struct graph_state *pgraph_ctx = chan->engctx[NVOBJ_ENGINE_GR]; - struct pipe_state *pipe = &pgraph_ctx->pipe_state; - struct drm_device *dev = chan->dev; - uint32_t xfmode0, xfmode1; + struct nv10_graph_chan *chan = NULL; + if (nv_rd32(priv, 0x400144) & 0x00010000) { + int chid = nv_rd32(priv, 0x400148) >> 24; + if (chid < ARRAY_SIZE(priv->chan)) + chan = priv->chan[chid]; + } + return chan; +} + +static void +nv10_graph_save_pipe(struct nv10_graph_chan *chan) +{ + struct nv10_graph_priv *priv = nv10_graph_priv(chan); + struct pipe_state *pipe = &chan->pipe_state; + + PIPE_SAVE(priv, pipe->pipe_0x4400, 0x4400); + PIPE_SAVE(priv, pipe->pipe_0x0200, 0x0200); + PIPE_SAVE(priv, pipe->pipe_0x6400, 0x6400); + PIPE_SAVE(priv, pipe->pipe_0x6800, 0x6800); + PIPE_SAVE(priv, pipe->pipe_0x6c00, 0x6c00); + PIPE_SAVE(priv, pipe->pipe_0x7000, 0x7000); + PIPE_SAVE(priv, pipe->pipe_0x7400, 0x7400); + PIPE_SAVE(priv, pipe->pipe_0x7800, 0x7800); + PIPE_SAVE(priv, pipe->pipe_0x0040, 0x0040); + PIPE_SAVE(priv, pipe->pipe_0x0000, 0x0000); +} + +static void +nv10_graph_load_pipe(struct nv10_graph_chan *chan) +{ + struct nv10_graph_priv *priv = nv10_graph_priv(chan); + struct pipe_state *pipe = &chan->pipe_state; + u32 xfmode0, xfmode1; int i; - nouveau_wait_for_idle(dev); + nv04_graph_idle(priv); /* XXX check haiku comments */ - xfmode0 = nv_rd32(dev, NV10_PGRAPH_XFMODE0); - xfmode1 = nv_rd32(dev, NV10_PGRAPH_XFMODE1); - nv_wr32(dev, NV10_PGRAPH_XFMODE0, 0x10000000); - nv_wr32(dev, NV10_PGRAPH_XFMODE1, 0x00000000); - nv_wr32(dev, NV10_PGRAPH_PIPE_ADDRESS, 0x000064c0); + xfmode0 = nv_rd32(priv, NV10_PGRAPH_XFMODE0); + xfmode1 = nv_rd32(priv, NV10_PGRAPH_XFMODE1); + nv_wr32(priv, NV10_PGRAPH_XFMODE0, 0x10000000); + nv_wr32(priv, NV10_PGRAPH_XFMODE1, 0x00000000); + nv_wr32(priv, NV10_PGRAPH_PIPE_ADDRESS, 0x000064c0); for (i = 0; i < 4; i++) - nv_wr32(dev, NV10_PGRAPH_PIPE_DATA, 0x3f800000); + nv_wr32(priv, NV10_PGRAPH_PIPE_DATA, 0x3f800000); for (i = 0; i < 4; i++) - nv_wr32(dev, NV10_PGRAPH_PIPE_DATA, 0x00000000); + nv_wr32(priv, NV10_PGRAPH_PIPE_DATA, 0x00000000); - nv_wr32(dev, NV10_PGRAPH_PIPE_ADDRESS, 0x00006ab0); + nv_wr32(priv, NV10_PGRAPH_PIPE_ADDRESS, 0x00006ab0); for (i = 0; i < 3; i++) - nv_wr32(dev, NV10_PGRAPH_PIPE_DATA, 0x3f800000); + nv_wr32(priv, NV10_PGRAPH_PIPE_DATA, 0x3f800000); - nv_wr32(dev, NV10_PGRAPH_PIPE_ADDRESS, 0x00006a80); + nv_wr32(priv, NV10_PGRAPH_PIPE_ADDRESS, 0x00006a80); for (i = 0; i < 3; i++) - nv_wr32(dev, NV10_PGRAPH_PIPE_DATA, 0x00000000); + nv_wr32(priv, NV10_PGRAPH_PIPE_DATA, 0x00000000); - nv_wr32(dev, NV10_PGRAPH_PIPE_ADDRESS, 0x00000040); - nv_wr32(dev, NV10_PGRAPH_PIPE_DATA, 0x00000008); + nv_wr32(priv, NV10_PGRAPH_PIPE_ADDRESS, 0x00000040); + nv_wr32(priv, NV10_PGRAPH_PIPE_DATA, 0x00000008); - PIPE_RESTORE(dev, pipe->pipe_0x0200, 0x0200); - nouveau_wait_for_idle(dev); + PIPE_RESTORE(priv, pipe->pipe_0x0200, 0x0200); + nv04_graph_idle(priv); /* restore XFMODE */ - nv_wr32(dev, NV10_PGRAPH_XFMODE0, xfmode0); - nv_wr32(dev, NV10_PGRAPH_XFMODE1, xfmode1); - PIPE_RESTORE(dev, pipe->pipe_0x6400, 0x6400); - PIPE_RESTORE(dev, pipe->pipe_0x6800, 0x6800); - PIPE_RESTORE(dev, pipe->pipe_0x6c00, 0x6c00); - PIPE_RESTORE(dev, pipe->pipe_0x7000, 0x7000); - PIPE_RESTORE(dev, pipe->pipe_0x7400, 0x7400); - PIPE_RESTORE(dev, pipe->pipe_0x7800, 0x7800); - PIPE_RESTORE(dev, pipe->pipe_0x4400, 0x4400); - PIPE_RESTORE(dev, pipe->pipe_0x0000, 0x0000); - PIPE_RESTORE(dev, pipe->pipe_0x0040, 0x0040); - nouveau_wait_for_idle(dev); + nv_wr32(priv, NV10_PGRAPH_XFMODE0, xfmode0); + nv_wr32(priv, NV10_PGRAPH_XFMODE1, xfmode1); + PIPE_RESTORE(priv, pipe->pipe_0x6400, 0x6400); + PIPE_RESTORE(priv, pipe->pipe_0x6800, 0x6800); + PIPE_RESTORE(priv, pipe->pipe_0x6c00, 0x6c00); + PIPE_RESTORE(priv, pipe->pipe_0x7000, 0x7000); + PIPE_RESTORE(priv, pipe->pipe_0x7400, 0x7400); + PIPE_RESTORE(priv, pipe->pipe_0x7800, 0x7800); + PIPE_RESTORE(priv, pipe->pipe_0x4400, 0x4400); + PIPE_RESTORE(priv, pipe->pipe_0x0000, 0x0000); + PIPE_RESTORE(priv, pipe->pipe_0x0040, 0x0040); + nv04_graph_idle(priv); } -static void nv10_graph_create_pipe(struct nouveau_channel *chan) +static void +nv10_graph_create_pipe(struct nv10_graph_chan *chan) { - struct graph_state *pgraph_ctx = chan->engctx[NVOBJ_ENGINE_GR]; - struct pipe_state *fifo_pipe_state = &pgraph_ctx->pipe_state; - struct drm_device *dev = chan->dev; - uint32_t *fifo_pipe_state_addr; + struct nv10_graph_priv *priv = nv10_graph_priv(chan); + struct pipe_state *pipe_state = &chan->pipe_state; + u32 *pipe_state_addr; int i; #define PIPE_INIT(addr) \ do { \ - fifo_pipe_state_addr = fifo_pipe_state->pipe_##addr; \ + pipe_state_addr = pipe_state->pipe_##addr; \ } while (0) #define PIPE_INIT_END(addr) \ do { \ - uint32_t *__end_addr = fifo_pipe_state->pipe_##addr + \ - ARRAY_SIZE(fifo_pipe_state->pipe_##addr); \ - if (fifo_pipe_state_addr != __end_addr) \ - NV_ERROR(dev, "incomplete pipe init for 0x%x : %p/%p\n", \ - addr, fifo_pipe_state_addr, __end_addr); \ + u32 *__end_addr = pipe_state->pipe_##addr + \ + ARRAY_SIZE(pipe_state->pipe_##addr); \ + if (pipe_state_addr != __end_addr) \ + nv_error(priv, "incomplete pipe init for 0x%x : %p/%p\n", \ + addr, pipe_state_addr, __end_addr); \ } while (0) -#define NV_WRITE_PIPE_INIT(value) *(fifo_pipe_state_addr++) = value +#define NV_WRITE_PIPE_INIT(value) *(pipe_state_addr++) = value PIPE_INIT(0x0200); for (i = 0; i < 48; i++) @@ -634,34 +840,36 @@ static void nv10_graph_create_pipe(struct nouveau_channel *chan) #undef NV_WRITE_PIPE_INIT } -static int nv10_graph_ctx_regs_find_offset(struct drm_device *dev, int reg) +static int +nv10_graph_ctx_regs_find_offset(struct nv10_graph_priv *priv, int reg) { int i; for (i = 0; i < ARRAY_SIZE(nv10_graph_ctx_regs); i++) { if (nv10_graph_ctx_regs[i] == reg) return i; } - NV_ERROR(dev, "unknow offset nv10_ctx_regs %d\n", reg); + nv_error(priv, "unknow offset nv10_ctx_regs %d\n", reg); return -1; } -static int nv17_graph_ctx_regs_find_offset(struct drm_device *dev, int reg) +static int +nv17_graph_ctx_regs_find_offset(struct nv10_graph_priv *priv, int reg) { int i; for (i = 0; i < ARRAY_SIZE(nv17_graph_ctx_regs); i++) { if (nv17_graph_ctx_regs[i] == reg) return i; } - NV_ERROR(dev, "unknow offset nv17_ctx_regs %d\n", reg); + nv_error(priv, "unknow offset nv17_ctx_regs %d\n", reg); return -1; } -static void nv10_graph_load_dma_vtxbuf(struct nouveau_channel *chan, - uint32_t inst) +static void +nv10_graph_load_dma_vtxbuf(struct nv10_graph_chan *chan, int chid, u32 inst) { - struct drm_device *dev = chan->dev; - uint32_t st2, st2_dl, st2_dh, fifo_ptr, fifo[0x60/4]; - uint32_t ctx_user, ctx_switch[5]; + struct nv10_graph_priv *priv = nv10_graph_priv(chan); + u32 st2, st2_dl, st2_dh, fifo_ptr, fifo[0x60/4]; + u32 ctx_user, ctx_switch[5]; int i, subchan = -1; /* NV10TCL_DMA_VTXBUF (method 0x18c) modifies hidden state @@ -671,7 +879,7 @@ static void nv10_graph_load_dma_vtxbuf(struct nouveau_channel *chan, /* Look for a celsius object */ for (i = 0; i < 8; i++) { - int class = nv_rd32(dev, NV10_PGRAPH_CTX_CACHE(i, 0)) & 0xfff; + int class = nv_rd32(priv, NV10_PGRAPH_CTX_CACHE(i, 0)) & 0xfff; if (class == 0x56 || class == 0x96 || class == 0x99) { subchan = i; @@ -683,168 +891,158 @@ static void nv10_graph_load_dma_vtxbuf(struct nouveau_channel *chan, return; /* Save the current ctx object */ - ctx_user = nv_rd32(dev, NV10_PGRAPH_CTX_USER); + ctx_user = nv_rd32(priv, NV10_PGRAPH_CTX_USER); for (i = 0; i < 5; i++) - ctx_switch[i] = nv_rd32(dev, NV10_PGRAPH_CTX_SWITCH(i)); + ctx_switch[i] = nv_rd32(priv, NV10_PGRAPH_CTX_SWITCH(i)); /* Save the FIFO state */ - st2 = nv_rd32(dev, NV10_PGRAPH_FFINTFC_ST2); - st2_dl = nv_rd32(dev, NV10_PGRAPH_FFINTFC_ST2_DL); - st2_dh = nv_rd32(dev, NV10_PGRAPH_FFINTFC_ST2_DH); - fifo_ptr = nv_rd32(dev, NV10_PGRAPH_FFINTFC_FIFO_PTR); + st2 = nv_rd32(priv, NV10_PGRAPH_FFINTFC_ST2); + st2_dl = nv_rd32(priv, NV10_PGRAPH_FFINTFC_ST2_DL); + st2_dh = nv_rd32(priv, NV10_PGRAPH_FFINTFC_ST2_DH); + fifo_ptr = nv_rd32(priv, NV10_PGRAPH_FFINTFC_FIFO_PTR); for (i = 0; i < ARRAY_SIZE(fifo); i++) - fifo[i] = nv_rd32(dev, 0x4007a0 + 4 * i); + fifo[i] = nv_rd32(priv, 0x4007a0 + 4 * i); /* Switch to the celsius subchannel */ for (i = 0; i < 5; i++) - nv_wr32(dev, NV10_PGRAPH_CTX_SWITCH(i), - nv_rd32(dev, NV10_PGRAPH_CTX_CACHE(subchan, i))); - nv_mask(dev, NV10_PGRAPH_CTX_USER, 0xe000, subchan << 13); + nv_wr32(priv, NV10_PGRAPH_CTX_SWITCH(i), + nv_rd32(priv, NV10_PGRAPH_CTX_CACHE(subchan, i))); + nv_mask(priv, NV10_PGRAPH_CTX_USER, 0xe000, subchan << 13); /* Inject NV10TCL_DMA_VTXBUF */ - nv_wr32(dev, NV10_PGRAPH_FFINTFC_FIFO_PTR, 0); - nv_wr32(dev, NV10_PGRAPH_FFINTFC_ST2, - 0x2c000000 | chan->id << 20 | subchan << 16 | 0x18c); - nv_wr32(dev, NV10_PGRAPH_FFINTFC_ST2_DL, inst); - nv_mask(dev, NV10_PGRAPH_CTX_CONTROL, 0, 0x10000); - nv_mask(dev, NV04_PGRAPH_FIFO, 0x00000001, 0x00000001); - nv_mask(dev, NV04_PGRAPH_FIFO, 0x00000001, 0x00000000); + nv_wr32(priv, NV10_PGRAPH_FFINTFC_FIFO_PTR, 0); + nv_wr32(priv, NV10_PGRAPH_FFINTFC_ST2, + 0x2c000000 | chid << 20 | subchan << 16 | 0x18c); + nv_wr32(priv, NV10_PGRAPH_FFINTFC_ST2_DL, inst); + nv_mask(priv, NV10_PGRAPH_CTX_CONTROL, 0, 0x10000); + nv_mask(priv, NV04_PGRAPH_FIFO, 0x00000001, 0x00000001); + nv_mask(priv, NV04_PGRAPH_FIFO, 0x00000001, 0x00000000); /* Restore the FIFO state */ for (i = 0; i < ARRAY_SIZE(fifo); i++) - nv_wr32(dev, 0x4007a0 + 4 * i, fifo[i]); + nv_wr32(priv, 0x4007a0 + 4 * i, fifo[i]); - nv_wr32(dev, NV10_PGRAPH_FFINTFC_FIFO_PTR, fifo_ptr); - nv_wr32(dev, NV10_PGRAPH_FFINTFC_ST2, st2); - nv_wr32(dev, NV10_PGRAPH_FFINTFC_ST2_DL, st2_dl); - nv_wr32(dev, NV10_PGRAPH_FFINTFC_ST2_DH, st2_dh); + nv_wr32(priv, NV10_PGRAPH_FFINTFC_FIFO_PTR, fifo_ptr); + nv_wr32(priv, NV10_PGRAPH_FFINTFC_ST2, st2); + nv_wr32(priv, NV10_PGRAPH_FFINTFC_ST2_DL, st2_dl); + nv_wr32(priv, NV10_PGRAPH_FFINTFC_ST2_DH, st2_dh); /* Restore the current ctx object */ for (i = 0; i < 5; i++) - nv_wr32(dev, NV10_PGRAPH_CTX_SWITCH(i), ctx_switch[i]); - nv_wr32(dev, NV10_PGRAPH_CTX_USER, ctx_user); + nv_wr32(priv, NV10_PGRAPH_CTX_SWITCH(i), ctx_switch[i]); + nv_wr32(priv, NV10_PGRAPH_CTX_USER, ctx_user); } static int -nv10_graph_load_context(struct nouveau_channel *chan) +nv10_graph_load_context(struct nv10_graph_chan *chan, int chid) { - struct drm_device *dev = chan->dev; - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct graph_state *pgraph_ctx = chan->engctx[NVOBJ_ENGINE_GR]; - uint32_t tmp; + struct nv10_graph_priv *priv = nv10_graph_priv(chan); + u32 inst; int i; for (i = 0; i < ARRAY_SIZE(nv10_graph_ctx_regs); i++) - nv_wr32(dev, nv10_graph_ctx_regs[i], pgraph_ctx->nv10[i]); - if (dev_priv->chipset >= 0x17) { + nv_wr32(priv, nv10_graph_ctx_regs[i], chan->nv10[i]); + + if (nv_device(priv)->chipset >= 0x17) { for (i = 0; i < ARRAY_SIZE(nv17_graph_ctx_regs); i++) - nv_wr32(dev, nv17_graph_ctx_regs[i], - pgraph_ctx->nv17[i]); + nv_wr32(priv, nv17_graph_ctx_regs[i], chan->nv17[i]); } nv10_graph_load_pipe(chan); - nv10_graph_load_dma_vtxbuf(chan, (nv_rd32(dev, NV10_PGRAPH_GLOBALSTATE1) - & 0xffff)); - - nv_wr32(dev, NV10_PGRAPH_CTX_CONTROL, 0x10010100); - tmp = nv_rd32(dev, NV10_PGRAPH_CTX_USER); - nv_wr32(dev, NV10_PGRAPH_CTX_USER, (tmp & 0xffffff) | chan->id << 24); - tmp = nv_rd32(dev, NV10_PGRAPH_FFINTFC_ST2); - nv_wr32(dev, NV10_PGRAPH_FFINTFC_ST2, tmp & 0xcfffffff); + + inst = nv_rd32(priv, NV10_PGRAPH_GLOBALSTATE1) & 0xffff; + nv10_graph_load_dma_vtxbuf(chan, chid, inst); + + nv_wr32(priv, NV10_PGRAPH_CTX_CONTROL, 0x10010100); + nv_mask(priv, NV10_PGRAPH_CTX_USER, 0xff000000, chid << 24); + nv_mask(priv, NV10_PGRAPH_FFINTFC_ST2, 0x30000000, 0x00000000); return 0; } static int -nv10_graph_unload_context(struct drm_device *dev) +nv10_graph_unload_context(struct nv10_graph_chan *chan) { - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_channel *chan; - struct graph_state *ctx; - uint32_t tmp; + struct nv10_graph_priv *priv = nv10_graph_priv(chan); int i; - chan = nv10_graph_channel(dev); - if (!chan) - return 0; - ctx = chan->engctx[NVOBJ_ENGINE_GR]; - for (i = 0; i < ARRAY_SIZE(nv10_graph_ctx_regs); i++) - ctx->nv10[i] = nv_rd32(dev, nv10_graph_ctx_regs[i]); + chan->nv10[i] = nv_rd32(priv, nv10_graph_ctx_regs[i]); - if (dev_priv->chipset >= 0x17) { + if (nv_device(priv)->chipset >= 0x17) { for (i = 0; i < ARRAY_SIZE(nv17_graph_ctx_regs); i++) - ctx->nv17[i] = nv_rd32(dev, nv17_graph_ctx_regs[i]); + chan->nv17[i] = nv_rd32(priv, nv17_graph_ctx_regs[i]); } nv10_graph_save_pipe(chan); - nv_wr32(dev, NV10_PGRAPH_CTX_CONTROL, 0x10000000); - tmp = nv_rd32(dev, NV10_PGRAPH_CTX_USER) & 0x00ffffff; - tmp |= 31 << 24; - nv_wr32(dev, NV10_PGRAPH_CTX_USER, tmp); + nv_wr32(priv, NV10_PGRAPH_CTX_CONTROL, 0x10000000); + nv_mask(priv, NV10_PGRAPH_CTX_USER, 0xff000000, 0x1f000000); return 0; } static void -nv10_graph_context_switch(struct drm_device *dev) +nv10_graph_context_switch(struct nv10_graph_priv *priv) { - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_channel *chan = NULL; + struct nv10_graph_chan *prev = NULL; + struct nv10_graph_chan *next = NULL; + unsigned long flags; int chid; - nouveau_wait_for_idle(dev); + spin_lock_irqsave(&priv->lock, flags); + nv04_graph_idle(priv); /* If previous context is valid, we need to save it */ - nv10_graph_unload_context(dev); + prev = nv10_graph_channel(priv); + if (prev) + nv10_graph_unload_context(prev); + + /* load context for next channel */ + chid = (nv_rd32(priv, NV04_PGRAPH_TRAPPED_ADDR) >> 20) & 0x1f; + next = priv->chan[chid]; + if (next) + nv10_graph_load_context(next, chid); - /* Load context for next channel */ - chid = (nv_rd32(dev, NV04_PGRAPH_TRAPPED_ADDR) >> 20) & 0x1f; - chan = dev_priv->channels.ptr[chid]; - if (chan && chan->engctx[NVOBJ_ENGINE_GR]) - nv10_graph_load_context(chan); + spin_unlock_irqrestore(&priv->lock, flags); } #define NV_WRITE_CTX(reg, val) do { \ - int offset = nv10_graph_ctx_regs_find_offset(dev, reg); \ + int offset = nv10_graph_ctx_regs_find_offset(priv, reg); \ if (offset > 0) \ - pgraph_ctx->nv10[offset] = val; \ + chan->nv10[offset] = val; \ } while (0) #define NV17_WRITE_CTX(reg, val) do { \ - int offset = nv17_graph_ctx_regs_find_offset(dev, reg); \ + int offset = nv17_graph_ctx_regs_find_offset(priv, reg); \ if (offset > 0) \ - pgraph_ctx->nv17[offset] = val; \ + chan->nv17[offset] = val; \ } while (0) -struct nouveau_channel * -nv10_graph_channel(struct drm_device *dev) -{ - struct drm_nouveau_private *dev_priv = dev->dev_private; - int chid = 31; - - if (nv_rd32(dev, NV10_PGRAPH_CTX_CONTROL) & 0x00010000) - chid = nv_rd32(dev, NV10_PGRAPH_CTX_USER) >> 24; - - if (chid >= 31) - return NULL; - - return dev_priv->channels.ptr[chid]; -} - static int -nv10_graph_context_new(struct nouveau_channel *chan, int engine) +nv10_graph_context_ctor(struct nouveau_object *parent, + struct nouveau_object *engine, + struct nouveau_oclass *oclass, void *data, u32 size, + struct nouveau_object **pobject) { - struct drm_device *dev = chan->dev; - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct graph_state *pgraph_ctx; - - NV_DEBUG(dev, "nv10_graph_context_create %d\n", chan->id); - - pgraph_ctx = kzalloc(sizeof(*pgraph_ctx), GFP_KERNEL); - if (pgraph_ctx == NULL) - return -ENOMEM; - chan->engctx[engine] = pgraph_ctx; + struct nouveau_fifo_chan *fifo = (void *)parent; + struct nv10_graph_priv *priv = (void *)engine; + struct nv10_graph_chan *chan; + unsigned long flags; + int ret; + + ret = nouveau_object_create(parent, engine, oclass, 0, &chan); + *pobject = nv_object(chan); + if (ret) + return ret; + + spin_lock_irqsave(&priv->lock, flags); + if (priv->chan[fifo->chid]) { + *pobject = nv_object(priv->chan[fifo->chid]); + atomic_inc(&(*pobject)->refcount); + spin_unlock_irqrestore(&priv->lock, flags); + nouveau_object_destroy(&chan->base); + return 1; + } NV_WRITE_CTX(0x00400e88, 0x08000000); NV_WRITE_CTX(0x00400e9c, 0x4b7fffff); @@ -853,212 +1051,91 @@ nv10_graph_context_new(struct nouveau_channel *chan, int engine) NV_WRITE_CTX(0x00400e14, 0x00001000); NV_WRITE_CTX(0x00400e30, 0x00080008); NV_WRITE_CTX(0x00400e34, 0x00080008); - if (dev_priv->chipset >= 0x17) { + if (nv_device(priv)->chipset >= 0x17) { /* is it really needed ??? */ NV17_WRITE_CTX(NV10_PGRAPH_DEBUG_4, - nv_rd32(dev, NV10_PGRAPH_DEBUG_4)); - NV17_WRITE_CTX(0x004006b0, nv_rd32(dev, 0x004006b0)); + nv_rd32(priv, NV10_PGRAPH_DEBUG_4)); + NV17_WRITE_CTX(0x004006b0, nv_rd32(priv, 0x004006b0)); NV17_WRITE_CTX(0x00400eac, 0x0fff0000); NV17_WRITE_CTX(0x00400eb0, 0x0fff0000); NV17_WRITE_CTX(0x00400ec0, 0x00000080); NV17_WRITE_CTX(0x00400ed0, 0x00000080); } - NV_WRITE_CTX(NV10_PGRAPH_CTX_USER, chan->id << 24); + NV_WRITE_CTX(NV10_PGRAPH_CTX_USER, chan->chid << 24); nv10_graph_create_pipe(chan); + + priv->chan[fifo->chid] = chan; + chan->chid = fifo->chid; + spin_unlock_irqrestore(&priv->lock, flags); return 0; } static void -nv10_graph_context_del(struct nouveau_channel *chan, int engine) +nv10_graph_context_dtor(struct nouveau_object *object) { - struct drm_device *dev = chan->dev; - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct graph_state *pgraph_ctx = chan->engctx[engine]; + struct nv10_graph_priv *priv = (void *)object->engine; + struct nv10_graph_chan *chan = (void *)object; unsigned long flags; - spin_lock_irqsave(&dev_priv->context_switch_lock, flags); - nv_mask(dev, NV04_PGRAPH_FIFO, 0x00000001, 0x00000000); - - /* Unload the context if it's the currently active one */ - if (nv10_graph_channel(dev) == chan) - nv10_graph_unload_context(dev); + spin_lock_irqsave(&priv->lock, flags); + priv->chan[chan->chid] = NULL; + spin_unlock_irqrestore(&priv->lock, flags); - nv_mask(dev, NV04_PGRAPH_FIFO, 0x00000001, 0x00000001); - spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags); - - /* Free the context resources */ - chan->engctx[engine] = NULL; - kfree(pgraph_ctx); -} - -static void -nv10_graph_set_tile_region(struct drm_device *dev, int i) -{ - struct nouveau_fb_tile *tile = nvfb_tile(dev, i); - nv_wr32(dev, NV10_PGRAPH_TLIMIT(i), tile->limit); - nv_wr32(dev, NV10_PGRAPH_TSIZE(i), tile->pitch); - nv_wr32(dev, NV10_PGRAPH_TILE(i), tile->addr); + nouveau_object_destroy(&chan->base); } static int -nv10_graph_init(struct drm_device *dev, int engine) +nv10_graph_context_fini(struct nouveau_object *object, bool suspend) { - struct drm_nouveau_private *dev_priv = dev->dev_private; - u32 tmp; - int i; - - nv_wr32(dev, NV03_PMC_ENABLE, nv_rd32(dev, NV03_PMC_ENABLE) & - ~NV_PMC_ENABLE_PGRAPH); - nv_wr32(dev, NV03_PMC_ENABLE, nv_rd32(dev, NV03_PMC_ENABLE) | - NV_PMC_ENABLE_PGRAPH); - - nv_wr32(dev, NV03_PGRAPH_INTR , 0xFFFFFFFF); - nv_wr32(dev, NV03_PGRAPH_INTR_EN, 0xFFFFFFFF); - - nv_wr32(dev, NV04_PGRAPH_DEBUG_0, 0xFFFFFFFF); - nv_wr32(dev, NV04_PGRAPH_DEBUG_0, 0x00000000); - nv_wr32(dev, NV04_PGRAPH_DEBUG_1, 0x00118700); - /* nv_wr32(dev, NV04_PGRAPH_DEBUG_2, 0x24E00810); */ /* 0x25f92ad9 */ - nv_wr32(dev, NV04_PGRAPH_DEBUG_2, 0x25f92ad9); - nv_wr32(dev, NV04_PGRAPH_DEBUG_3, 0x55DE0830 | - (1<<29) | - (1<<31)); - if (dev_priv->chipset >= 0x17) { - nv_wr32(dev, NV10_PGRAPH_DEBUG_4, 0x1f000000); - nv_wr32(dev, 0x400a10, 0x3ff3fb6); - nv_wr32(dev, 0x400838, 0x2f8684); - nv_wr32(dev, 0x40083c, 0x115f3f); - nv_wr32(dev, 0x004006b0, 0x40000020); - } else - nv_wr32(dev, NV10_PGRAPH_DEBUG_4, 0x00000000); + struct nv10_graph_priv *priv = (void *)object->engine; + struct nv10_graph_chan *chan = (void *)object; + unsigned long flags; - /* Turn all the tiling regions off. */ - for (i = 0; i < NV10_PFB_TILE__SIZE; i++) - nv10_graph_set_tile_region(dev, i); - - nv_wr32(dev, NV10_PGRAPH_CTX_SWITCH(0), 0x00000000); - nv_wr32(dev, NV10_PGRAPH_CTX_SWITCH(1), 0x00000000); - nv_wr32(dev, NV10_PGRAPH_CTX_SWITCH(2), 0x00000000); - nv_wr32(dev, NV10_PGRAPH_CTX_SWITCH(3), 0x00000000); - nv_wr32(dev, NV10_PGRAPH_CTX_SWITCH(4), 0x00000000); - nv_wr32(dev, NV10_PGRAPH_STATE, 0xFFFFFFFF); - - tmp = nv_rd32(dev, NV10_PGRAPH_CTX_USER) & 0x00ffffff; - tmp |= 31 << 24; - nv_wr32(dev, NV10_PGRAPH_CTX_USER, tmp); - nv_wr32(dev, NV10_PGRAPH_CTX_CONTROL, 0x10000100); - nv_wr32(dev, NV10_PGRAPH_FFINTFC_ST2, 0x08000000); + spin_lock_irqsave(&priv->lock, flags); + nv_mask(priv, NV04_PGRAPH_FIFO, 0x00000001, 0x00000000); + if (nv10_graph_channel(priv) == chan) + nv10_graph_unload_context(chan); + nv_mask(priv, NV04_PGRAPH_FIFO, 0x00000001, 0x00000001); + spin_unlock_irqrestore(&priv->lock, flags); - return 0; + return nouveau_object_fini(&chan->base, suspend); } -static int -nv10_graph_fini(struct drm_device *dev, int engine, bool suspend) -{ - nv_mask(dev, NV04_PGRAPH_FIFO, 0x00000001, 0x00000000); - if (!nv_wait(dev, NV04_PGRAPH_STATUS, ~0, 0) && suspend) { - nv_mask(dev, NV04_PGRAPH_FIFO, 0x00000001, 0x00000001); - return -EBUSY; - } - nv10_graph_unload_context(dev); - nv_wr32(dev, NV03_PGRAPH_INTR_EN, 0x00000000); - return 0; -} - -static int -nv17_graph_mthd_lma_window(struct nouveau_channel *chan, - u32 class, u32 mthd, u32 data) -{ - struct graph_state *ctx = chan->engctx[NVOBJ_ENGINE_GR]; - struct drm_device *dev = chan->dev; - struct pipe_state *pipe = &ctx->pipe_state; - uint32_t pipe_0x0040[1], pipe_0x64c0[8], pipe_0x6a80[3], pipe_0x6ab0[3]; - uint32_t xfmode0, xfmode1; - int i; - - ctx->lma_window[(mthd - 0x1638) / 4] = data; - - if (mthd != 0x1644) - return 0; - - nouveau_wait_for_idle(dev); - - PIPE_SAVE(dev, pipe_0x0040, 0x0040); - PIPE_SAVE(dev, pipe->pipe_0x0200, 0x0200); - - PIPE_RESTORE(dev, ctx->lma_window, 0x6790); - - nouveau_wait_for_idle(dev); - - xfmode0 = nv_rd32(dev, NV10_PGRAPH_XFMODE0); - xfmode1 = nv_rd32(dev, NV10_PGRAPH_XFMODE1); - - PIPE_SAVE(dev, pipe->pipe_0x4400, 0x4400); - PIPE_SAVE(dev, pipe_0x64c0, 0x64c0); - PIPE_SAVE(dev, pipe_0x6ab0, 0x6ab0); - PIPE_SAVE(dev, pipe_0x6a80, 0x6a80); - - nouveau_wait_for_idle(dev); - - nv_wr32(dev, NV10_PGRAPH_XFMODE0, 0x10000000); - nv_wr32(dev, NV10_PGRAPH_XFMODE1, 0x00000000); - nv_wr32(dev, NV10_PGRAPH_PIPE_ADDRESS, 0x000064c0); - for (i = 0; i < 4; i++) - nv_wr32(dev, NV10_PGRAPH_PIPE_DATA, 0x3f800000); - for (i = 0; i < 4; i++) - nv_wr32(dev, NV10_PGRAPH_PIPE_DATA, 0x00000000); - - nv_wr32(dev, NV10_PGRAPH_PIPE_ADDRESS, 0x00006ab0); - for (i = 0; i < 3; i++) - nv_wr32(dev, NV10_PGRAPH_PIPE_DATA, 0x3f800000); - - nv_wr32(dev, NV10_PGRAPH_PIPE_ADDRESS, 0x00006a80); - for (i = 0; i < 3; i++) - nv_wr32(dev, NV10_PGRAPH_PIPE_DATA, 0x00000000); - - nv_wr32(dev, NV10_PGRAPH_PIPE_ADDRESS, 0x00000040); - nv_wr32(dev, NV10_PGRAPH_PIPE_DATA, 0x00000008); - - PIPE_RESTORE(dev, pipe->pipe_0x0200, 0x0200); - - nouveau_wait_for_idle(dev); - - PIPE_RESTORE(dev, pipe_0x0040, 0x0040); - - nv_wr32(dev, NV10_PGRAPH_XFMODE0, xfmode0); - nv_wr32(dev, NV10_PGRAPH_XFMODE1, xfmode1); - - PIPE_RESTORE(dev, pipe_0x64c0, 0x64c0); - PIPE_RESTORE(dev, pipe_0x6ab0, 0x6ab0); - PIPE_RESTORE(dev, pipe_0x6a80, 0x6a80); - PIPE_RESTORE(dev, pipe->pipe_0x4400, 0x4400); - - nv_wr32(dev, NV10_PGRAPH_PIPE_ADDRESS, 0x000000c0); - nv_wr32(dev, NV10_PGRAPH_PIPE_DATA, 0x00000000); - - nouveau_wait_for_idle(dev); +static struct nouveau_oclass +nv10_graph_cclass = { + .handle = NV_ENGCTX(GR, 0x10), + .ofuncs = &(struct nouveau_ofuncs) { + .ctor = nv10_graph_context_ctor, + .dtor = nv10_graph_context_dtor, + .init = nouveau_object_init, + .fini = nv10_graph_context_fini, + }, +}; - return 0; -} +/******************************************************************************* + * PGRAPH engine/subdev functions + ******************************************************************************/ -static int -nv17_graph_mthd_lma_enable(struct nouveau_channel *chan, - u32 class, u32 mthd, u32 data) +static void +nv10_graph_tile_prog(struct nouveau_engine *engine, int i) { - struct drm_device *dev = chan->dev; + struct nouveau_fb_tile *tile = &nouveau_fb(engine)->tile.region[i]; + struct nouveau_fifo *pfifo = nouveau_fifo(engine); + struct nv10_graph_priv *priv = (void *)engine; + unsigned long flags; - nouveau_wait_for_idle(dev); + pfifo->pause(pfifo, &flags); + nv04_graph_idle(priv); - nv_wr32(dev, NV10_PGRAPH_DEBUG_4, - nv_rd32(dev, NV10_PGRAPH_DEBUG_4) | 0x1 << 8); - nv_wr32(dev, 0x004006b0, - nv_rd32(dev, 0x004006b0) | 0x8 << 24); + nv_wr32(priv, NV10_PGRAPH_TLIMIT(i), tile->limit); + nv_wr32(priv, NV10_PGRAPH_TSIZE(i), tile->pitch); + nv_wr32(priv, NV10_PGRAPH_TILE(i), tile->addr); - return 0; + pfifo->start(pfifo, &flags); } -struct nouveau_bitfield nv10_graph_intr[] = { +struct nouveau_bitfield nv10_graph_intr_name[] = { { NV_PGRAPH_INTR_NOTIFY, "NOTIFY" }, { NV_PGRAPH_INTR_ERROR, "ERROR" }, {} @@ -1073,115 +1150,165 @@ struct nouveau_bitfield nv10_graph_nstatus[] = { }; static void -nv10_graph_isr(struct drm_device *dev) +nv10_graph_intr(struct nouveau_subdev *subdev) { - u32 stat; - - while ((stat = nv_rd32(dev, NV03_PGRAPH_INTR))) { - u32 nsource = nv_rd32(dev, NV03_PGRAPH_NSOURCE); - u32 nstatus = nv_rd32(dev, NV03_PGRAPH_NSTATUS); - u32 addr = nv_rd32(dev, NV04_PGRAPH_TRAPPED_ADDR); - u32 chid = (addr & 0x01f00000) >> 20; - u32 subc = (addr & 0x00070000) >> 16; - u32 mthd = (addr & 0x00001ffc); - u32 data = nv_rd32(dev, NV04_PGRAPH_TRAPPED_DATA); - u32 class = nv_rd32(dev, 0x400160 + subc * 4) & 0xfff; - u32 show = stat; - - if (stat & NV_PGRAPH_INTR_ERROR) { - if (nsource & NV03_PGRAPH_NSOURCE_ILLEGAL_MTHD) { - if (!nouveau_gpuobj_mthd_call2(dev, chid, class, mthd, data)) - show &= ~NV_PGRAPH_INTR_ERROR; - } - } + struct nv10_graph_priv *priv = (void *)subdev; + struct nv10_graph_chan *chan = NULL; + struct nouveau_namedb *namedb = NULL; + struct nouveau_handle *handle = NULL; + u32 stat = nv_rd32(priv, NV03_PGRAPH_INTR); + u32 nsource = nv_rd32(priv, NV03_PGRAPH_NSOURCE); + u32 nstatus = nv_rd32(priv, NV03_PGRAPH_NSTATUS); + u32 addr = nv_rd32(priv, NV04_PGRAPH_TRAPPED_ADDR); + u32 chid = (addr & 0x01f00000) >> 20; + u32 subc = (addr & 0x00070000) >> 16; + u32 mthd = (addr & 0x00001ffc); + u32 data = nv_rd32(priv, NV04_PGRAPH_TRAPPED_DATA); + u32 class = nv_rd32(priv, 0x400160 + subc * 4) & 0xfff; + u32 show = stat; + unsigned long flags; - if (stat & NV_PGRAPH_INTR_CONTEXT_SWITCH) { - nv_wr32(dev, NV03_PGRAPH_INTR, NV_PGRAPH_INTR_CONTEXT_SWITCH); - stat &= ~NV_PGRAPH_INTR_CONTEXT_SWITCH; - show &= ~NV_PGRAPH_INTR_CONTEXT_SWITCH; - nv10_graph_context_switch(dev); + spin_lock_irqsave(&priv->lock, flags); + chan = priv->chan[chid]; + if (chan) + namedb = (void *)nv_pclass(nv_object(chan), NV_NAMEDB_CLASS); + spin_unlock_irqrestore(&priv->lock, flags); + + if (stat & NV_PGRAPH_INTR_ERROR) { + if (chan && (nsource & NV03_PGRAPH_NSOURCE_ILLEGAL_MTHD)) { + handle = nouveau_namedb_get_class(namedb, class); + if (handle && !nv_call(handle->object, mthd, data)) + show &= ~NV_PGRAPH_INTR_ERROR; } + } - nv_wr32(dev, NV03_PGRAPH_INTR, stat); - nv_wr32(dev, NV04_PGRAPH_FIFO, 0x00000001); - - if (show && nouveau_ratelimit()) { - NV_INFO(dev, "PGRAPH -"); - nouveau_bitfield_print(nv10_graph_intr, show); - printk(" nsource:"); - nouveau_bitfield_print(nv04_graph_nsource, nsource); - printk(" nstatus:"); - nouveau_bitfield_print(nv10_graph_nstatus, nstatus); - printk("\n"); - NV_INFO(dev, "PGRAPH - ch %d/%d class 0x%04x " - "mthd 0x%04x data 0x%08x\n", - chid, subc, class, mthd, data); - } + if (stat & NV_PGRAPH_INTR_CONTEXT_SWITCH) { + nv_wr32(priv, NV03_PGRAPH_INTR, NV_PGRAPH_INTR_CONTEXT_SWITCH); + stat &= ~NV_PGRAPH_INTR_CONTEXT_SWITCH; + show &= ~NV_PGRAPH_INTR_CONTEXT_SWITCH; + nv10_graph_context_switch(priv); + } + + nv_wr32(priv, NV03_PGRAPH_INTR, stat); + nv_wr32(priv, NV04_PGRAPH_FIFO, 0x00000001); + + if (show) { + nv_error(priv, ""); + nouveau_bitfield_print(nv10_graph_intr_name, show); + printk(" nsource:"); + nouveau_bitfield_print(nv04_graph_nsource, nsource); + printk(" nstatus:"); + nouveau_bitfield_print(nv10_graph_nstatus, nstatus); + printk("\n"); + nv_error(priv, "ch %d/%d class 0x%04x " + "mthd 0x%04x data 0x%08x\n", + chid, subc, class, mthd, data); } + + nouveau_namedb_put(handle); } -static void -nv10_graph_destroy(struct drm_device *dev, int engine) +static int +nv10_graph_ctor(struct nouveau_object *parent, struct nouveau_object *engine, + struct nouveau_oclass *oclass, void *data, u32 size, + struct nouveau_object **pobject) { - struct nv10_graph_engine *pgraph = nv_engine(dev, engine); + struct nv10_graph_priv *priv; + int ret; + + ret = nouveau_graph_create(parent, engine, oclass, true, &priv); + *pobject = nv_object(priv); + if (ret) + return ret; + + nv_subdev(priv)->unit = 0x00001000; + nv_subdev(priv)->intr = nv10_graph_intr; + nv_engine(priv)->cclass = &nv10_graph_cclass; + + if (nv_device(priv)->chipset <= 0x10) + nv_engine(priv)->sclass = nv10_graph_sclass; + else + if (nv_device(priv)->chipset < 0x17 || + nv_device(priv)->chipset == 0x1a) + nv_engine(priv)->sclass = nv15_graph_sclass; + else + nv_engine(priv)->sclass = nv17_graph_sclass; + + nv_engine(priv)->tile_prog = nv10_graph_tile_prog; + spin_lock_init(&priv->lock); + return 0; +} - nouveau_irq_unregister(dev, 12); - kfree(pgraph); +static void +nv10_graph_dtor(struct nouveau_object *object) +{ + struct nv10_graph_priv *priv = (void *)object; + nouveau_graph_destroy(&priv->base); } -int -nv10_graph_create(struct drm_device *dev) +static int +nv10_graph_init(struct nouveau_object *object) { - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nv10_graph_engine *pgraph; - - pgraph = kzalloc(sizeof(*pgraph), GFP_KERNEL); - if (!pgraph) - return -ENOMEM; - - pgraph->base.destroy = nv10_graph_destroy; - pgraph->base.init = nv10_graph_init; - pgraph->base.fini = nv10_graph_fini; - pgraph->base.context_new = nv10_graph_context_new; - pgraph->base.context_del = nv10_graph_context_del; - pgraph->base.object_new = nv04_graph_object_new; - pgraph->base.set_tile_region = nv10_graph_set_tile_region; - - NVOBJ_ENGINE_ADD(dev, GR, &pgraph->base); - nouveau_irq_register(dev, 12, nv10_graph_isr); - - NVOBJ_CLASS(dev, 0x0030, GR); /* null */ - NVOBJ_CLASS(dev, 0x0039, GR); /* m2mf */ - NVOBJ_CLASS(dev, 0x004a, GR); /* gdirect */ - NVOBJ_CLASS(dev, 0x005f, GR); /* imageblit */ - NVOBJ_CLASS(dev, 0x009f, GR); /* imageblit (nv12) */ - NVOBJ_CLASS(dev, 0x008a, GR); /* ifc */ - NVOBJ_CLASS(dev, 0x0089, GR); /* sifm */ - NVOBJ_CLASS(dev, 0x0062, GR); /* surf2d */ - NVOBJ_CLASS(dev, 0x0043, GR); /* rop */ - NVOBJ_CLASS(dev, 0x0012, GR); /* beta1 */ - NVOBJ_CLASS(dev, 0x0072, GR); /* beta4 */ - NVOBJ_CLASS(dev, 0x0019, GR); /* cliprect */ - NVOBJ_CLASS(dev, 0x0044, GR); /* pattern */ - NVOBJ_CLASS(dev, 0x0052, GR); /* swzsurf */ - NVOBJ_CLASS(dev, 0x0093, GR); /* surf3d */ - NVOBJ_CLASS(dev, 0x0094, GR); /* tex_tri */ - NVOBJ_CLASS(dev, 0x0095, GR); /* multitex_tri */ - - /* celcius */ - if (dev_priv->chipset <= 0x10) { - NVOBJ_CLASS(dev, 0x0056, GR); - } else - if (dev_priv->chipset < 0x17 || dev_priv->chipset == 0x1a) { - NVOBJ_CLASS(dev, 0x0096, GR); + struct nouveau_engine *engine = nv_engine(object); + struct nouveau_fb *pfb = nouveau_fb(object); + struct nv10_graph_priv *priv = (void *)engine; + int ret, i; + + ret = nouveau_graph_init(&priv->base); + if (ret) + return ret; + + nv_wr32(priv, NV03_PGRAPH_INTR , 0xFFFFFFFF); + nv_wr32(priv, NV03_PGRAPH_INTR_EN, 0xFFFFFFFF); + + nv_wr32(priv, NV04_PGRAPH_DEBUG_0, 0xFFFFFFFF); + nv_wr32(priv, NV04_PGRAPH_DEBUG_0, 0x00000000); + nv_wr32(priv, NV04_PGRAPH_DEBUG_1, 0x00118700); + /* nv_wr32(priv, NV04_PGRAPH_DEBUG_2, 0x24E00810); */ /* 0x25f92ad9 */ + nv_wr32(priv, NV04_PGRAPH_DEBUG_2, 0x25f92ad9); + nv_wr32(priv, NV04_PGRAPH_DEBUG_3, 0x55DE0830 | (1 << 29) | (1 << 31)); + + if (nv_device(priv)->chipset >= 0x17) { + nv_wr32(priv, NV10_PGRAPH_DEBUG_4, 0x1f000000); + nv_wr32(priv, 0x400a10, 0x03ff3fb6); + nv_wr32(priv, 0x400838, 0x002f8684); + nv_wr32(priv, 0x40083c, 0x00115f3f); + nv_wr32(priv, 0x4006b0, 0x40000020); } else { - NVOBJ_CLASS(dev, 0x0099, GR); - NVOBJ_MTHD (dev, 0x0099, 0x1638, nv17_graph_mthd_lma_window); - NVOBJ_MTHD (dev, 0x0099, 0x163c, nv17_graph_mthd_lma_window); - NVOBJ_MTHD (dev, 0x0099, 0x1640, nv17_graph_mthd_lma_window); - NVOBJ_MTHD (dev, 0x0099, 0x1644, nv17_graph_mthd_lma_window); - NVOBJ_MTHD (dev, 0x0099, 0x1658, nv17_graph_mthd_lma_enable); + nv_wr32(priv, NV10_PGRAPH_DEBUG_4, 0x00000000); } + /* Turn all the tiling regions off. */ + for (i = 0; i < pfb->tile.regions; i++) + engine->tile_prog(engine, i); + + nv_wr32(priv, NV10_PGRAPH_CTX_SWITCH(0), 0x00000000); + nv_wr32(priv, NV10_PGRAPH_CTX_SWITCH(1), 0x00000000); + nv_wr32(priv, NV10_PGRAPH_CTX_SWITCH(2), 0x00000000); + nv_wr32(priv, NV10_PGRAPH_CTX_SWITCH(3), 0x00000000); + nv_wr32(priv, NV10_PGRAPH_CTX_SWITCH(4), 0x00000000); + nv_wr32(priv, NV10_PGRAPH_STATE, 0xFFFFFFFF); + + nv_mask(priv, NV10_PGRAPH_CTX_USER, 0xff000000, 0x1f000000); + nv_wr32(priv, NV10_PGRAPH_CTX_CONTROL, 0x10000100); + nv_wr32(priv, NV10_PGRAPH_FFINTFC_ST2, 0x08000000); return 0; } + +static int +nv10_graph_fini(struct nouveau_object *object, bool suspend) +{ + struct nv10_graph_priv *priv = (void *)object; + return nouveau_graph_fini(&priv->base, suspend); +} + +struct nouveau_oclass +nv10_graph_oclass = { + .handle = NV_ENGINE(GR, 0x10), + .ofuncs = &(struct nouveau_ofuncs) { + .ctor = nv10_graph_ctor, + .dtor = nv10_graph_dtor, + .init = nv10_graph_init, + .fini = nv10_graph_fini, + }, +}; diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/nv20.c b/drivers/gpu/drm/nouveau/core/engine/graph/nv20.c index 0d874b8b18e5..61faef976aee 100644 --- a/drivers/gpu/drm/nouveau/core/engine/graph/nv20.c +++ b/drivers/gpu/drm/nouveau/core/engine/graph/nv20.c @@ -1,836 +1,378 @@ -#include "drmP.h" -#include "drm.h" -#include "nouveau_drv.h" -#include - -/* - * NV20 - * ----- - * There are 3 families : - * NV20 is 0x10de:0x020* - * NV25/28 is 0x10de:0x025* / 0x10de:0x028* - * NV2A is 0x10de:0x02A0 - * - * NV30 - * ----- - * There are 3 families : - * NV30/31 is 0x10de:0x030* / 0x10de:0x031* - * NV34 is 0x10de:0x032* - * NV35/36 is 0x10de:0x033* / 0x10de:0x034* - * - * Not seen in the wild, no dumps (probably NV35) : - * NV37 is 0x10de:0x00fc, 0x10de:0x00fd - * NV38 is 0x10de:0x0333, 0x10de:0x00fe - * - */ - -struct nv20_graph_engine { - struct nouveau_exec_engine base; - struct nouveau_gpuobj *ctxtab; - void (*grctx_init)(struct nouveau_gpuobj *); - u32 grctx_size; - u32 grctx_user; +#include +#include +#include +#include +#include + +#include +#include + +#include +#include + +#include "nv20.h" +#include "regs.h" + +/******************************************************************************* + * Graphics object classes + ******************************************************************************/ + +static struct nouveau_oclass +nv20_graph_sclass[] = { + { 0x0012, &nv04_graph_ofuncs, NULL }, /* beta1 */ + { 0x0019, &nv04_graph_ofuncs, NULL }, /* clip */ + { 0x0030, &nv04_graph_ofuncs, NULL }, /* null */ + { 0x0039, &nv04_graph_ofuncs, NULL }, /* m2mf */ + { 0x0043, &nv04_graph_ofuncs, NULL }, /* rop */ + { 0x0044, &nv04_graph_ofuncs, NULL }, /* patt */ + { 0x004a, &nv04_graph_ofuncs, NULL }, /* gdi */ + { 0x0062, &nv04_graph_ofuncs, NULL }, /* surf2d */ + { 0x0072, &nv04_graph_ofuncs, NULL }, /* beta4 */ + { 0x0089, &nv04_graph_ofuncs, NULL }, /* sifm */ + { 0x008a, &nv04_graph_ofuncs, NULL }, /* ifc */ + { 0x0096, &nv04_graph_ofuncs, NULL }, /* celcius */ + { 0x0097, &nv04_graph_ofuncs, NULL }, /* kelvin */ + { 0x009e, &nv04_graph_ofuncs, NULL }, /* swzsurf */ + { 0x009f, &nv04_graph_ofuncs, NULL }, /* imageblit */ + {}, }; -#define NV20_GRCTX_SIZE (3580*4) -#define NV25_GRCTX_SIZE (3529*4) -#define NV2A_GRCTX_SIZE (3500*4) +/******************************************************************************* + * PGRAPH context + ******************************************************************************/ -#define NV30_31_GRCTX_SIZE (24392) -#define NV34_GRCTX_SIZE (18140) -#define NV35_36_GRCTX_SIZE (22396) - -int -nv20_graph_unload_context(struct drm_device *dev) +static int +nv20_graph_context_ctor(struct nouveau_object *parent, + struct nouveau_object *engine, + struct nouveau_oclass *oclass, void *data, u32 size, + struct nouveau_object **pobject) { - struct nouveau_channel *chan; - struct nouveau_gpuobj *grctx; - u32 tmp; - - chan = nv10_graph_channel(dev); - if (!chan) - return 0; - grctx = chan->engctx[NVOBJ_ENGINE_GR]; - - nv_wr32(dev, NV20_PGRAPH_CHANNEL_CTX_POINTER, grctx->addr >> 4); - nv_wr32(dev, NV20_PGRAPH_CHANNEL_CTX_XFER, - NV20_PGRAPH_CHANNEL_CTX_XFER_SAVE); - - nouveau_wait_for_idle(dev); - - nv_wr32(dev, NV10_PGRAPH_CTX_CONTROL, 0x10000000); - tmp = nv_rd32(dev, NV10_PGRAPH_CTX_USER) & 0x00ffffff; - tmp |= 31 << 24; - nv_wr32(dev, NV10_PGRAPH_CTX_USER, tmp); - return 0; -} + struct nv20_graph_chan *chan; + int ret, i; -static void -nv20_graph_rdi(struct drm_device *dev) -{ - struct drm_nouveau_private *dev_priv = dev->dev_private; - int i, writecount = 32; - uint32_t rdi_index = 0x2c80000; - - if (dev_priv->chipset == 0x20) { - rdi_index = 0x3d0000; - writecount = 15; - } - - nv_wr32(dev, NV10_PGRAPH_RDI_INDEX, rdi_index); - for (i = 0; i < writecount; i++) - nv_wr32(dev, NV10_PGRAPH_RDI_DATA, 0); + ret = nouveau_graph_context_create(parent, engine, oclass, NULL, + 0x37f0, 16, NVOBJ_FLAG_ZERO_ALLOC, + &chan); + *pobject = nv_object(chan); + if (ret) + return ret; - nouveau_wait_for_idle(dev); -} + chan->chid = nouveau_fifo_chan(parent)->chid; -static void -nv20_graph_context_init(struct nouveau_gpuobj *ctx) -{ - int i; - - nv_wo32(ctx, 0x033c, 0xffff0000); - nv_wo32(ctx, 0x03a0, 0x0fff0000); - nv_wo32(ctx, 0x03a4, 0x0fff0000); - nv_wo32(ctx, 0x047c, 0x00000101); - nv_wo32(ctx, 0x0490, 0x00000111); - nv_wo32(ctx, 0x04a8, 0x44400000); + nv_wo32(chan, 0x0000, 0x00000001 | (chan->chid << 24)); + nv_wo32(chan, 0x033c, 0xffff0000); + nv_wo32(chan, 0x03a0, 0x0fff0000); + nv_wo32(chan, 0x03a4, 0x0fff0000); + nv_wo32(chan, 0x047c, 0x00000101); + nv_wo32(chan, 0x0490, 0x00000111); + nv_wo32(chan, 0x04a8, 0x44400000); for (i = 0x04d4; i <= 0x04e0; i += 4) - nv_wo32(ctx, i, 0x00030303); + nv_wo32(chan, i, 0x00030303); for (i = 0x04f4; i <= 0x0500; i += 4) - nv_wo32(ctx, i, 0x00080000); + nv_wo32(chan, i, 0x00080000); for (i = 0x050c; i <= 0x0518; i += 4) - nv_wo32(ctx, i, 0x01012000); + nv_wo32(chan, i, 0x01012000); for (i = 0x051c; i <= 0x0528; i += 4) - nv_wo32(ctx, i, 0x000105b8); + nv_wo32(chan, i, 0x000105b8); for (i = 0x052c; i <= 0x0538; i += 4) - nv_wo32(ctx, i, 0x00080008); + nv_wo32(chan, i, 0x00080008); for (i = 0x055c; i <= 0x0598; i += 4) - nv_wo32(ctx, i, 0x07ff0000); - nv_wo32(ctx, 0x05a4, 0x4b7fffff); - nv_wo32(ctx, 0x05fc, 0x00000001); - nv_wo32(ctx, 0x0604, 0x00004000); - nv_wo32(ctx, 0x0610, 0x00000001); - nv_wo32(ctx, 0x0618, 0x00040000); - nv_wo32(ctx, 0x061c, 0x00010000); + nv_wo32(chan, i, 0x07ff0000); + nv_wo32(chan, 0x05a4, 0x4b7fffff); + nv_wo32(chan, 0x05fc, 0x00000001); + nv_wo32(chan, 0x0604, 0x00004000); + nv_wo32(chan, 0x0610, 0x00000001); + nv_wo32(chan, 0x0618, 0x00040000); + nv_wo32(chan, 0x061c, 0x00010000); for (i = 0x1c1c; i <= 0x248c; i += 16) { - nv_wo32(ctx, (i + 0), 0x10700ff9); - nv_wo32(ctx, (i + 4), 0x0436086c); - nv_wo32(ctx, (i + 8), 0x000c001b); + nv_wo32(chan, (i + 0), 0x10700ff9); + nv_wo32(chan, (i + 4), 0x0436086c); + nv_wo32(chan, (i + 8), 0x000c001b); } - nv_wo32(ctx, 0x281c, 0x3f800000); - nv_wo32(ctx, 0x2830, 0x3f800000); - nv_wo32(ctx, 0x285c, 0x40000000); - nv_wo32(ctx, 0x2860, 0x3f800000); - nv_wo32(ctx, 0x2864, 0x3f000000); - nv_wo32(ctx, 0x286c, 0x40000000); - nv_wo32(ctx, 0x2870, 0x3f800000); - nv_wo32(ctx, 0x2878, 0xbf800000); - nv_wo32(ctx, 0x2880, 0xbf800000); - nv_wo32(ctx, 0x34a4, 0x000fe000); - nv_wo32(ctx, 0x3530, 0x000003f8); - nv_wo32(ctx, 0x3540, 0x002fe000); + nv_wo32(chan, 0x281c, 0x3f800000); + nv_wo32(chan, 0x2830, 0x3f800000); + nv_wo32(chan, 0x285c, 0x40000000); + nv_wo32(chan, 0x2860, 0x3f800000); + nv_wo32(chan, 0x2864, 0x3f000000); + nv_wo32(chan, 0x286c, 0x40000000); + nv_wo32(chan, 0x2870, 0x3f800000); + nv_wo32(chan, 0x2878, 0xbf800000); + nv_wo32(chan, 0x2880, 0xbf800000); + nv_wo32(chan, 0x34a4, 0x000fe000); + nv_wo32(chan, 0x3530, 0x000003f8); + nv_wo32(chan, 0x3540, 0x002fe000); for (i = 0x355c; i <= 0x3578; i += 4) - nv_wo32(ctx, i, 0x001c527c); + nv_wo32(chan, i, 0x001c527c); + return 0; } -static void -nv25_graph_context_init(struct nouveau_gpuobj *ctx) +int +nv20_graph_context_init(struct nouveau_object *object) { - int i; - - nv_wo32(ctx, 0x035c, 0xffff0000); - nv_wo32(ctx, 0x03c0, 0x0fff0000); - nv_wo32(ctx, 0x03c4, 0x0fff0000); - nv_wo32(ctx, 0x049c, 0x00000101); - nv_wo32(ctx, 0x04b0, 0x00000111); - nv_wo32(ctx, 0x04c8, 0x00000080); - nv_wo32(ctx, 0x04cc, 0xffff0000); - nv_wo32(ctx, 0x04d0, 0x00000001); - nv_wo32(ctx, 0x04e4, 0x44400000); - nv_wo32(ctx, 0x04fc, 0x4b800000); - for (i = 0x0510; i <= 0x051c; i += 4) - nv_wo32(ctx, i, 0x00030303); - for (i = 0x0530; i <= 0x053c; i += 4) - nv_wo32(ctx, i, 0x00080000); - for (i = 0x0548; i <= 0x0554; i += 4) - nv_wo32(ctx, i, 0x01012000); - for (i = 0x0558; i <= 0x0564; i += 4) - nv_wo32(ctx, i, 0x000105b8); - for (i = 0x0568; i <= 0x0574; i += 4) - nv_wo32(ctx, i, 0x00080008); - for (i = 0x0598; i <= 0x05d4; i += 4) - nv_wo32(ctx, i, 0x07ff0000); - nv_wo32(ctx, 0x05e0, 0x4b7fffff); - nv_wo32(ctx, 0x0620, 0x00000080); - nv_wo32(ctx, 0x0624, 0x30201000); - nv_wo32(ctx, 0x0628, 0x70605040); - nv_wo32(ctx, 0x062c, 0xb0a09080); - nv_wo32(ctx, 0x0630, 0xf0e0d0c0); - nv_wo32(ctx, 0x0664, 0x00000001); - nv_wo32(ctx, 0x066c, 0x00004000); - nv_wo32(ctx, 0x0678, 0x00000001); - nv_wo32(ctx, 0x0680, 0x00040000); - nv_wo32(ctx, 0x0684, 0x00010000); - for (i = 0x1b04; i <= 0x2374; i += 16) { - nv_wo32(ctx, (i + 0), 0x10700ff9); - nv_wo32(ctx, (i + 4), 0x0436086c); - nv_wo32(ctx, (i + 8), 0x000c001b); - } - nv_wo32(ctx, 0x2704, 0x3f800000); - nv_wo32(ctx, 0x2718, 0x3f800000); - nv_wo32(ctx, 0x2744, 0x40000000); - nv_wo32(ctx, 0x2748, 0x3f800000); - nv_wo32(ctx, 0x274c, 0x3f000000); - nv_wo32(ctx, 0x2754, 0x40000000); - nv_wo32(ctx, 0x2758, 0x3f800000); - nv_wo32(ctx, 0x2760, 0xbf800000); - nv_wo32(ctx, 0x2768, 0xbf800000); - nv_wo32(ctx, 0x308c, 0x000fe000); - nv_wo32(ctx, 0x3108, 0x000003f8); - nv_wo32(ctx, 0x3468, 0x002fe000); - for (i = 0x3484; i <= 0x34a0; i += 4) - nv_wo32(ctx, i, 0x001c527c); -} + struct nv20_graph_priv *priv = (void *)object->engine; + struct nv20_graph_chan *chan = (void *)object; + int ret; -static void -nv2a_graph_context_init(struct nouveau_gpuobj *ctx) -{ - int i; - - nv_wo32(ctx, 0x033c, 0xffff0000); - nv_wo32(ctx, 0x03a0, 0x0fff0000); - nv_wo32(ctx, 0x03a4, 0x0fff0000); - nv_wo32(ctx, 0x047c, 0x00000101); - nv_wo32(ctx, 0x0490, 0x00000111); - nv_wo32(ctx, 0x04a8, 0x44400000); - for (i = 0x04d4; i <= 0x04e0; i += 4) - nv_wo32(ctx, i, 0x00030303); - for (i = 0x04f4; i <= 0x0500; i += 4) - nv_wo32(ctx, i, 0x00080000); - for (i = 0x050c; i <= 0x0518; i += 4) - nv_wo32(ctx, i, 0x01012000); - for (i = 0x051c; i <= 0x0528; i += 4) - nv_wo32(ctx, i, 0x000105b8); - for (i = 0x052c; i <= 0x0538; i += 4) - nv_wo32(ctx, i, 0x00080008); - for (i = 0x055c; i <= 0x0598; i += 4) - nv_wo32(ctx, i, 0x07ff0000); - nv_wo32(ctx, 0x05a4, 0x4b7fffff); - nv_wo32(ctx, 0x05fc, 0x00000001); - nv_wo32(ctx, 0x0604, 0x00004000); - nv_wo32(ctx, 0x0610, 0x00000001); - nv_wo32(ctx, 0x0618, 0x00040000); - nv_wo32(ctx, 0x061c, 0x00010000); - for (i = 0x1a9c; i <= 0x22fc; i += 16) { /*XXX: check!! */ - nv_wo32(ctx, (i + 0), 0x10700ff9); - nv_wo32(ctx, (i + 4), 0x0436086c); - nv_wo32(ctx, (i + 8), 0x000c001b); - } - nv_wo32(ctx, 0x269c, 0x3f800000); - nv_wo32(ctx, 0x26b0, 0x3f800000); - nv_wo32(ctx, 0x26dc, 0x40000000); - nv_wo32(ctx, 0x26e0, 0x3f800000); - nv_wo32(ctx, 0x26e4, 0x3f000000); - nv_wo32(ctx, 0x26ec, 0x40000000); - nv_wo32(ctx, 0x26f0, 0x3f800000); - nv_wo32(ctx, 0x26f8, 0xbf800000); - nv_wo32(ctx, 0x2700, 0xbf800000); - nv_wo32(ctx, 0x3024, 0x000fe000); - nv_wo32(ctx, 0x30a0, 0x000003f8); - nv_wo32(ctx, 0x33fc, 0x002fe000); - for (i = 0x341c; i <= 0x3438; i += 4) - nv_wo32(ctx, i, 0x001c527c); -} + ret = nouveau_graph_context_init(&chan->base); + if (ret) + return ret; -static void -nv30_31_graph_context_init(struct nouveau_gpuobj *ctx) -{ - int i; - - nv_wo32(ctx, 0x0410, 0x00000101); - nv_wo32(ctx, 0x0424, 0x00000111); - nv_wo32(ctx, 0x0428, 0x00000060); - nv_wo32(ctx, 0x0444, 0x00000080); - nv_wo32(ctx, 0x0448, 0xffff0000); - nv_wo32(ctx, 0x044c, 0x00000001); - nv_wo32(ctx, 0x0460, 0x44400000); - nv_wo32(ctx, 0x048c, 0xffff0000); - for (i = 0x04e0; i < 0x04e8; i += 4) - nv_wo32(ctx, i, 0x0fff0000); - nv_wo32(ctx, 0x04ec, 0x00011100); - for (i = 0x0508; i < 0x0548; i += 4) - nv_wo32(ctx, i, 0x07ff0000); - nv_wo32(ctx, 0x0550, 0x4b7fffff); - nv_wo32(ctx, 0x058c, 0x00000080); - nv_wo32(ctx, 0x0590, 0x30201000); - nv_wo32(ctx, 0x0594, 0x70605040); - nv_wo32(ctx, 0x0598, 0xb8a89888); - nv_wo32(ctx, 0x059c, 0xf8e8d8c8); - nv_wo32(ctx, 0x05b0, 0xb0000000); - for (i = 0x0600; i < 0x0640; i += 4) - nv_wo32(ctx, i, 0x00010588); - for (i = 0x0640; i < 0x0680; i += 4) - nv_wo32(ctx, i, 0x00030303); - for (i = 0x06c0; i < 0x0700; i += 4) - nv_wo32(ctx, i, 0x0008aae4); - for (i = 0x0700; i < 0x0740; i += 4) - nv_wo32(ctx, i, 0x01012000); - for (i = 0x0740; i < 0x0780; i += 4) - nv_wo32(ctx, i, 0x00080008); - nv_wo32(ctx, 0x085c, 0x00040000); - nv_wo32(ctx, 0x0860, 0x00010000); - for (i = 0x0864; i < 0x0874; i += 4) - nv_wo32(ctx, i, 0x00040004); - for (i = 0x1f18; i <= 0x3088 ; i += 16) { - nv_wo32(ctx, i + 0, 0x10700ff9); - nv_wo32(ctx, i + 1, 0x0436086c); - nv_wo32(ctx, i + 2, 0x000c001b); - } - for (i = 0x30b8; i < 0x30c8; i += 4) - nv_wo32(ctx, i, 0x0000ffff); - nv_wo32(ctx, 0x344c, 0x3f800000); - nv_wo32(ctx, 0x3808, 0x3f800000); - nv_wo32(ctx, 0x381c, 0x3f800000); - nv_wo32(ctx, 0x3848, 0x40000000); - nv_wo32(ctx, 0x384c, 0x3f800000); - nv_wo32(ctx, 0x3850, 0x3f000000); - nv_wo32(ctx, 0x3858, 0x40000000); - nv_wo32(ctx, 0x385c, 0x3f800000); - nv_wo32(ctx, 0x3864, 0xbf800000); - nv_wo32(ctx, 0x386c, 0xbf800000); + nv_wo32(priv->ctxtab, chan->chid * 4, nv_gpuobj(chan)->addr >> 4); + return 0; } -static void -nv34_graph_context_init(struct nouveau_gpuobj *ctx) +int +nv20_graph_context_fini(struct nouveau_object *object, bool suspend) { - int i; - - nv_wo32(ctx, 0x040c, 0x01000101); - nv_wo32(ctx, 0x0420, 0x00000111); - nv_wo32(ctx, 0x0424, 0x00000060); - nv_wo32(ctx, 0x0440, 0x00000080); - nv_wo32(ctx, 0x0444, 0xffff0000); - nv_wo32(ctx, 0x0448, 0x00000001); - nv_wo32(ctx, 0x045c, 0x44400000); - nv_wo32(ctx, 0x0480, 0xffff0000); - for (i = 0x04d4; i < 0x04dc; i += 4) - nv_wo32(ctx, i, 0x0fff0000); - nv_wo32(ctx, 0x04e0, 0x00011100); - for (i = 0x04fc; i < 0x053c; i += 4) - nv_wo32(ctx, i, 0x07ff0000); - nv_wo32(ctx, 0x0544, 0x4b7fffff); - nv_wo32(ctx, 0x057c, 0x00000080); - nv_wo32(ctx, 0x0580, 0x30201000); - nv_wo32(ctx, 0x0584, 0x70605040); - nv_wo32(ctx, 0x0588, 0xb8a89888); - nv_wo32(ctx, 0x058c, 0xf8e8d8c8); - nv_wo32(ctx, 0x05a0, 0xb0000000); - for (i = 0x05f0; i < 0x0630; i += 4) - nv_wo32(ctx, i, 0x00010588); - for (i = 0x0630; i < 0x0670; i += 4) - nv_wo32(ctx, i, 0x00030303); - for (i = 0x06b0; i < 0x06f0; i += 4) - nv_wo32(ctx, i, 0x0008aae4); - for (i = 0x06f0; i < 0x0730; i += 4) - nv_wo32(ctx, i, 0x01012000); - for (i = 0x0730; i < 0x0770; i += 4) - nv_wo32(ctx, i, 0x00080008); - nv_wo32(ctx, 0x0850, 0x00040000); - nv_wo32(ctx, 0x0854, 0x00010000); - for (i = 0x0858; i < 0x0868; i += 4) - nv_wo32(ctx, i, 0x00040004); - for (i = 0x15ac; i <= 0x271c ; i += 16) { - nv_wo32(ctx, i + 0, 0x10700ff9); - nv_wo32(ctx, i + 1, 0x0436086c); - nv_wo32(ctx, i + 2, 0x000c001b); + struct nv20_graph_priv *priv = (void *)object->engine; + struct nv20_graph_chan *chan = (void *)object; + int chid = -1; + + nv_mask(priv, 0x400720, 0x00000001, 0x00000000); + if (nv_rd32(priv, 0x400144) & 0x00010000) + chid = (nv_rd32(priv, 0x400148) & 0x1f000000) >> 24; + if (chan->chid == chid) { + nv_wr32(priv, 0x400784, nv_gpuobj(chan)->addr >> 4); + nv_wr32(priv, 0x400788, 0x00000002); + nv_wait(priv, 0x400700, 0xffffffff, 0x00000000); + nv_wr32(priv, 0x400144, 0x10000000); + nv_mask(priv, 0x400148, 0xff000000, 0x1f000000); } - for (i = 0x274c; i < 0x275c; i += 4) - nv_wo32(ctx, i, 0x0000ffff); - nv_wo32(ctx, 0x2ae0, 0x3f800000); - nv_wo32(ctx, 0x2e9c, 0x3f800000); - nv_wo32(ctx, 0x2eb0, 0x3f800000); - nv_wo32(ctx, 0x2edc, 0x40000000); - nv_wo32(ctx, 0x2ee0, 0x3f800000); - nv_wo32(ctx, 0x2ee4, 0x3f000000); - nv_wo32(ctx, 0x2eec, 0x40000000); - nv_wo32(ctx, 0x2ef0, 0x3f800000); - nv_wo32(ctx, 0x2ef8, 0xbf800000); - nv_wo32(ctx, 0x2f00, 0xbf800000); -} + nv_mask(priv, 0x400720, 0x00000001, 0x00000001); -static void -nv35_36_graph_context_init(struct nouveau_gpuobj *ctx) -{ - int i; - - nv_wo32(ctx, 0x040c, 0x00000101); - nv_wo32(ctx, 0x0420, 0x00000111); - nv_wo32(ctx, 0x0424, 0x00000060); - nv_wo32(ctx, 0x0440, 0x00000080); - nv_wo32(ctx, 0x0444, 0xffff0000); - nv_wo32(ctx, 0x0448, 0x00000001); - nv_wo32(ctx, 0x045c, 0x44400000); - nv_wo32(ctx, 0x0488, 0xffff0000); - for (i = 0x04dc; i < 0x04e4; i += 4) - nv_wo32(ctx, i, 0x0fff0000); - nv_wo32(ctx, 0x04e8, 0x00011100); - for (i = 0x0504; i < 0x0544; i += 4) - nv_wo32(ctx, i, 0x07ff0000); - nv_wo32(ctx, 0x054c, 0x4b7fffff); - nv_wo32(ctx, 0x0588, 0x00000080); - nv_wo32(ctx, 0x058c, 0x30201000); - nv_wo32(ctx, 0x0590, 0x70605040); - nv_wo32(ctx, 0x0594, 0xb8a89888); - nv_wo32(ctx, 0x0598, 0xf8e8d8c8); - nv_wo32(ctx, 0x05ac, 0xb0000000); - for (i = 0x0604; i < 0x0644; i += 4) - nv_wo32(ctx, i, 0x00010588); - for (i = 0x0644; i < 0x0684; i += 4) - nv_wo32(ctx, i, 0x00030303); - for (i = 0x06c4; i < 0x0704; i += 4) - nv_wo32(ctx, i, 0x0008aae4); - for (i = 0x0704; i < 0x0744; i += 4) - nv_wo32(ctx, i, 0x01012000); - for (i = 0x0744; i < 0x0784; i += 4) - nv_wo32(ctx, i, 0x00080008); - nv_wo32(ctx, 0x0860, 0x00040000); - nv_wo32(ctx, 0x0864, 0x00010000); - for (i = 0x0868; i < 0x0878; i += 4) - nv_wo32(ctx, i, 0x00040004); - for (i = 0x1f1c; i <= 0x308c ; i += 16) { - nv_wo32(ctx, i + 0, 0x10700ff9); - nv_wo32(ctx, i + 4, 0x0436086c); - nv_wo32(ctx, i + 8, 0x000c001b); - } - for (i = 0x30bc; i < 0x30cc; i += 4) - nv_wo32(ctx, i, 0x0000ffff); - nv_wo32(ctx, 0x3450, 0x3f800000); - nv_wo32(ctx, 0x380c, 0x3f800000); - nv_wo32(ctx, 0x3820, 0x3f800000); - nv_wo32(ctx, 0x384c, 0x40000000); - nv_wo32(ctx, 0x3850, 0x3f800000); - nv_wo32(ctx, 0x3854, 0x3f000000); - nv_wo32(ctx, 0x385c, 0x40000000); - nv_wo32(ctx, 0x3860, 0x3f800000); - nv_wo32(ctx, 0x3868, 0xbf800000); - nv_wo32(ctx, 0x3870, 0xbf800000); + nv_wo32(priv->ctxtab, chan->chid * 4, 0x00000000); + return nouveau_graph_context_fini(&chan->base, suspend); } -int -nv20_graph_context_new(struct nouveau_channel *chan, int engine) -{ - struct nv20_graph_engine *pgraph = nv_engine(chan->dev, engine); - struct nouveau_gpuobj *grctx = NULL; - struct drm_device *dev = chan->dev; - int ret; - - ret = nouveau_gpuobj_new(dev, NULL, pgraph->grctx_size, 16, - NVOBJ_FLAG_ZERO_ALLOC, &grctx); - if (ret) - return ret; - - /* Initialise default context values */ - pgraph->grctx_init(grctx); - - /* nv20: nv_wo32(dev, chan->ramin_grctx->gpuobj, 10, chan->id<<24); */ - /* CTX_USER */ - nv_wo32(grctx, pgraph->grctx_user, (chan->id << 24) | 0x1); +static struct nouveau_oclass +nv20_graph_cclass = { + .handle = NV_ENGCTX(GR, 0x20), + .ofuncs = &(struct nouveau_ofuncs) { + .ctor = nv20_graph_context_ctor, + .dtor = _nouveau_graph_context_dtor, + .init = nv20_graph_context_init, + .fini = nv20_graph_context_fini, + .rd32 = _nouveau_graph_context_rd32, + .wr32 = _nouveau_graph_context_wr32, + }, +}; - nv_wo32(pgraph->ctxtab, chan->id * 4, grctx->addr >> 4); - chan->engctx[engine] = grctx; - return 0; -} +/******************************************************************************* + * PGRAPH engine/subdev functions + ******************************************************************************/ void -nv20_graph_context_del(struct nouveau_channel *chan, int engine) +nv20_graph_tile_prog(struct nouveau_engine *engine, int i) { - struct nv20_graph_engine *pgraph = nv_engine(chan->dev, engine); - struct nouveau_gpuobj *grctx = chan->engctx[engine]; - struct drm_device *dev = chan->dev; - struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_fb_tile *tile = &nouveau_fb(engine)->tile.region[i]; + struct nouveau_fifo *pfifo = nouveau_fifo(engine); + struct nv20_graph_priv *priv = (void *)engine; unsigned long flags; - spin_lock_irqsave(&dev_priv->context_switch_lock, flags); - nv_mask(dev, NV04_PGRAPH_FIFO, 0x00000001, 0x00000000); + pfifo->pause(pfifo, &flags); + nv04_graph_idle(priv); - /* Unload the context if it's the currently active one */ - if (nv10_graph_channel(dev) == chan) - nv20_graph_unload_context(dev); + nv_wr32(priv, NV20_PGRAPH_TLIMIT(i), tile->limit); + nv_wr32(priv, NV20_PGRAPH_TSIZE(i), tile->pitch); + nv_wr32(priv, NV20_PGRAPH_TILE(i), tile->addr); - nv_mask(dev, NV04_PGRAPH_FIFO, 0x00000001, 0x00000001); - spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags); + nv_wr32(priv, NV10_PGRAPH_RDI_INDEX, 0x00EA0030 + 4 * i); + nv_wr32(priv, NV10_PGRAPH_RDI_DATA, tile->limit); + nv_wr32(priv, NV10_PGRAPH_RDI_INDEX, 0x00EA0050 + 4 * i); + nv_wr32(priv, NV10_PGRAPH_RDI_DATA, tile->pitch); + nv_wr32(priv, NV10_PGRAPH_RDI_INDEX, 0x00EA0010 + 4 * i); + nv_wr32(priv, NV10_PGRAPH_RDI_DATA, tile->addr); - /* Free the context resources */ - nv_wo32(pgraph->ctxtab, chan->id * 4, 0); + if (nv_device(engine)->card_type == NV_20) { + nv_wr32(priv, NV20_PGRAPH_ZCOMP(i), tile->zcomp); + nv_wr32(priv, NV10_PGRAPH_RDI_INDEX, 0x00ea0090 + 4 * i); + nv_wr32(priv, NV10_PGRAPH_RDI_DATA, tile->zcomp); + } - nouveau_gpuobj_ref(NULL, &grctx); - chan->engctx[engine] = NULL; + pfifo->start(pfifo, &flags); } -static void -nv20_graph_set_tile_region(struct drm_device *dev, int i) +void +nv20_graph_intr(struct nouveau_subdev *subdev) { - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_fb_tile *tile = nvfb_tile(dev, i); - - nv_wr32(dev, NV20_PGRAPH_TLIMIT(i), tile->limit); - nv_wr32(dev, NV20_PGRAPH_TSIZE(i), tile->pitch); - nv_wr32(dev, NV20_PGRAPH_TILE(i), tile->addr); - - nv_wr32(dev, NV10_PGRAPH_RDI_INDEX, 0x00EA0030 + 4 * i); - nv_wr32(dev, NV10_PGRAPH_RDI_DATA, tile->limit); - nv_wr32(dev, NV10_PGRAPH_RDI_INDEX, 0x00EA0050 + 4 * i); - nv_wr32(dev, NV10_PGRAPH_RDI_DATA, tile->pitch); - nv_wr32(dev, NV10_PGRAPH_RDI_INDEX, 0x00EA0010 + 4 * i); - nv_wr32(dev, NV10_PGRAPH_RDI_DATA, tile->addr); - - if (dev_priv->card_type == NV_20) { - nv_wr32(dev, NV20_PGRAPH_ZCOMP(i), tile->zcomp); - nv_wr32(dev, NV10_PGRAPH_RDI_INDEX, 0x00ea0090 + 4 * i); - nv_wr32(dev, NV10_PGRAPH_RDI_DATA, tile->zcomp); + struct nv20_graph_priv *priv = (void *)subdev; + struct nouveau_engine *engine = nv_engine(subdev); + struct nouveau_handle *handle = NULL; + u32 stat = nv_rd32(priv, NV03_PGRAPH_INTR); + u32 nsource = nv_rd32(priv, NV03_PGRAPH_NSOURCE); + u32 nstatus = nv_rd32(priv, NV03_PGRAPH_NSTATUS); + u32 addr = nv_rd32(priv, NV04_PGRAPH_TRAPPED_ADDR); + u32 chid = (addr & 0x01f00000) >> 20; + u32 subc = (addr & 0x00070000) >> 16; + u32 mthd = (addr & 0x00001ffc); + u32 data = nv_rd32(priv, NV04_PGRAPH_TRAPPED_DATA); + u32 class = nv_rd32(priv, 0x400160 + subc * 4) & 0xfff; + u32 inst = nv_ro32(priv->ctxtab, (chid * 4)) << 4; + u32 show = stat; + + if (stat & NV_PGRAPH_INTR_ERROR) { + if (nsource & NV03_PGRAPH_NSOURCE_ILLEGAL_MTHD) { + handle = nouveau_engctx_lookup_class(engine, inst, class); + if (handle && !nv_call(handle->object, mthd, data)) + show &= ~NV_PGRAPH_INTR_ERROR; + nouveau_engctx_handle_put(handle); + } } -} - -int -nv20_graph_init(struct drm_device *dev, int engine) -{ - struct nv20_graph_engine *pgraph = nv_engine(dev, engine); - struct drm_nouveau_private *dev_priv = dev->dev_private; - uint32_t tmp, vramsz; - int i; - - nv_wr32(dev, NV03_PMC_ENABLE, - nv_rd32(dev, NV03_PMC_ENABLE) & ~NV_PMC_ENABLE_PGRAPH); - nv_wr32(dev, NV03_PMC_ENABLE, - nv_rd32(dev, NV03_PMC_ENABLE) | NV_PMC_ENABLE_PGRAPH); - - nv_wr32(dev, NV20_PGRAPH_CHANNEL_CTX_TABLE, pgraph->ctxtab->addr >> 4); - - nv20_graph_rdi(dev); - - nv_wr32(dev, NV03_PGRAPH_INTR , 0xFFFFFFFF); - nv_wr32(dev, NV03_PGRAPH_INTR_EN, 0xFFFFFFFF); - - nv_wr32(dev, NV04_PGRAPH_DEBUG_0, 0xFFFFFFFF); - nv_wr32(dev, NV04_PGRAPH_DEBUG_0, 0x00000000); - nv_wr32(dev, NV04_PGRAPH_DEBUG_1, 0x00118700); - nv_wr32(dev, NV04_PGRAPH_DEBUG_3, 0xF3CE0475); /* 0x4 = auto ctx switch */ - nv_wr32(dev, NV10_PGRAPH_DEBUG_4, 0x00000000); - nv_wr32(dev, 0x40009C , 0x00000040); - - if (dev_priv->chipset >= 0x25) { - nv_wr32(dev, 0x400890, 0x00a8cfff); - nv_wr32(dev, 0x400610, 0x304B1FB6); - nv_wr32(dev, 0x400B80, 0x1cbd3883); - nv_wr32(dev, 0x400B84, 0x44000000); - nv_wr32(dev, 0x400098, 0x40000080); - nv_wr32(dev, 0x400B88, 0x000000ff); - } else { - nv_wr32(dev, 0x400880, 0x0008c7df); - nv_wr32(dev, 0x400094, 0x00000005); - nv_wr32(dev, 0x400B80, 0x45eae20e); - nv_wr32(dev, 0x400B84, 0x24000000); - nv_wr32(dev, 0x400098, 0x00000040); - nv_wr32(dev, NV10_PGRAPH_RDI_INDEX, 0x00E00038); - nv_wr32(dev, NV10_PGRAPH_RDI_DATA , 0x00000030); - nv_wr32(dev, NV10_PGRAPH_RDI_INDEX, 0x00E10038); - nv_wr32(dev, NV10_PGRAPH_RDI_DATA , 0x00000030); + nv_wr32(priv, NV03_PGRAPH_INTR, stat); + nv_wr32(priv, NV04_PGRAPH_FIFO, 0x00000001); + + if (show) { + nv_info(priv, ""); + nouveau_bitfield_print(nv10_graph_intr_name, show); + printk(" nsource:"); + nouveau_bitfield_print(nv04_graph_nsource, nsource); + printk(" nstatus:"); + nouveau_bitfield_print(nv10_graph_nstatus, nstatus); + printk("\n"); + nv_info(priv, "ch %d/%d class 0x%04x mthd 0x%04x data 0x%08x\n", + chid, subc, class, mthd, data); } +} - /* Turn all the tiling regions off. */ - for (i = 0; i < NV10_PFB_TILE__SIZE; i++) - nv20_graph_set_tile_region(dev, i); - - nv_wr32(dev, 0x4009a0, nv_rd32(dev, 0x100324)); - nv_wr32(dev, NV10_PGRAPH_RDI_INDEX, 0x00EA000C); - nv_wr32(dev, NV10_PGRAPH_RDI_DATA, nv_rd32(dev, 0x100324)); - - nv_wr32(dev, NV10_PGRAPH_CTX_CONTROL, 0x10000100); - nv_wr32(dev, NV10_PGRAPH_STATE , 0xFFFFFFFF); - - tmp = nv_rd32(dev, NV10_PGRAPH_SURFACE) & 0x0007ff00; - nv_wr32(dev, NV10_PGRAPH_SURFACE, tmp); - tmp = nv_rd32(dev, NV10_PGRAPH_SURFACE) | 0x00020100; - nv_wr32(dev, NV10_PGRAPH_SURFACE, tmp); - - /* begin RAM config */ - vramsz = pci_resource_len(dev->pdev, 0) - 1; - nv_wr32(dev, 0x4009A4, nv_rd32(dev, NV04_PFB_CFG0)); - nv_wr32(dev, 0x4009A8, nv_rd32(dev, NV04_PFB_CFG1)); - nv_wr32(dev, NV10_PGRAPH_RDI_INDEX, 0x00EA0000); - nv_wr32(dev, NV10_PGRAPH_RDI_DATA , nv_rd32(dev, NV04_PFB_CFG0)); - nv_wr32(dev, NV10_PGRAPH_RDI_INDEX, 0x00EA0004); - nv_wr32(dev, NV10_PGRAPH_RDI_DATA , nv_rd32(dev, NV04_PFB_CFG1)); - nv_wr32(dev, 0x400820, 0); - nv_wr32(dev, 0x400824, 0); - nv_wr32(dev, 0x400864, vramsz - 1); - nv_wr32(dev, 0x400868, vramsz - 1); +static int +nv20_graph_ctor(struct nouveau_object *parent, struct nouveau_object *engine, + struct nouveau_oclass *oclass, void *data, u32 size, + struct nouveau_object **pobject) +{ + struct nv20_graph_priv *priv; + int ret; - /* interesting.. the below overwrites some of the tile setup above.. */ - nv_wr32(dev, 0x400B20, 0x00000000); - nv_wr32(dev, 0x400B04, 0xFFFFFFFF); + ret = nouveau_graph_create(parent, engine, oclass, true, &priv); + *pobject = nv_object(priv); + if (ret) + return ret; - nv_wr32(dev, NV03_PGRAPH_ABS_UCLIP_XMIN, 0); - nv_wr32(dev, NV03_PGRAPH_ABS_UCLIP_YMIN, 0); - nv_wr32(dev, NV03_PGRAPH_ABS_UCLIP_XMAX, 0x7fff); - nv_wr32(dev, NV03_PGRAPH_ABS_UCLIP_YMAX, 0x7fff); + ret = nouveau_gpuobj_new(parent, NULL, 32 * 4, 16, + NVOBJ_FLAG_ZERO_ALLOC, &priv->ctxtab); + if (ret) + return ret; + nv_subdev(priv)->unit = 0x00001000; + nv_subdev(priv)->intr = nv20_graph_intr; + nv_engine(priv)->cclass = &nv20_graph_cclass; + nv_engine(priv)->sclass = nv20_graph_sclass; + nv_engine(priv)->tile_prog = nv20_graph_tile_prog; return 0; } -int -nv30_graph_init(struct drm_device *dev, int engine) +void +nv20_graph_dtor(struct nouveau_object *object) { - struct nv20_graph_engine *pgraph = nv_engine(dev, engine); - struct drm_nouveau_private *dev_priv = dev->dev_private; - int i; - - nv_wr32(dev, NV03_PMC_ENABLE, - nv_rd32(dev, NV03_PMC_ENABLE) & ~NV_PMC_ENABLE_PGRAPH); - nv_wr32(dev, NV03_PMC_ENABLE, - nv_rd32(dev, NV03_PMC_ENABLE) | NV_PMC_ENABLE_PGRAPH); - - nv_wr32(dev, NV20_PGRAPH_CHANNEL_CTX_TABLE, pgraph->ctxtab->addr >> 4); - - nv_wr32(dev, NV03_PGRAPH_INTR , 0xFFFFFFFF); - nv_wr32(dev, NV03_PGRAPH_INTR_EN, 0xFFFFFFFF); - - nv_wr32(dev, NV04_PGRAPH_DEBUG_0, 0xFFFFFFFF); - nv_wr32(dev, NV04_PGRAPH_DEBUG_0, 0x00000000); - nv_wr32(dev, NV04_PGRAPH_DEBUG_1, 0x401287c0); - nv_wr32(dev, 0x400890, 0x01b463ff); - nv_wr32(dev, NV04_PGRAPH_DEBUG_3, 0xf2de0475); - nv_wr32(dev, NV10_PGRAPH_DEBUG_4, 0x00008000); - nv_wr32(dev, NV04_PGRAPH_LIMIT_VIOL_PIX, 0xf04bdff6); - nv_wr32(dev, 0x400B80, 0x1003d888); - nv_wr32(dev, 0x400B84, 0x0c000000); - nv_wr32(dev, 0x400098, 0x00000000); - nv_wr32(dev, 0x40009C, 0x0005ad00); - nv_wr32(dev, 0x400B88, 0x62ff00ff); /* suspiciously like PGRAPH_DEBUG_2 */ - nv_wr32(dev, 0x4000a0, 0x00000000); - nv_wr32(dev, 0x4000a4, 0x00000008); - nv_wr32(dev, 0x4008a8, 0xb784a400); - nv_wr32(dev, 0x400ba0, 0x002f8685); - nv_wr32(dev, 0x400ba4, 0x00231f3f); - nv_wr32(dev, 0x4008a4, 0x40000020); - - if (dev_priv->chipset == 0x34) { - nv_wr32(dev, NV10_PGRAPH_RDI_INDEX, 0x00EA0004); - nv_wr32(dev, NV10_PGRAPH_RDI_DATA , 0x00200201); - nv_wr32(dev, NV10_PGRAPH_RDI_INDEX, 0x00EA0008); - nv_wr32(dev, NV10_PGRAPH_RDI_DATA , 0x00000008); - nv_wr32(dev, NV10_PGRAPH_RDI_INDEX, 0x00EA0000); - nv_wr32(dev, NV10_PGRAPH_RDI_DATA , 0x00000032); - nv_wr32(dev, NV10_PGRAPH_RDI_INDEX, 0x00E00004); - nv_wr32(dev, NV10_PGRAPH_RDI_DATA , 0x00000002); - } + struct nv20_graph_priv *priv = (void *)object; + nouveau_gpuobj_ref(NULL, &priv->ctxtab); + nouveau_graph_destroy(&priv->base); +} - nv_wr32(dev, 0x4000c0, 0x00000016); +int +nv20_graph_init(struct nouveau_object *object) +{ + struct nouveau_engine *engine = nv_engine(object); + struct nv20_graph_priv *priv = (void *)engine; + struct nouveau_fb *pfb = nouveau_fb(object); + u32 tmp, vramsz; + int ret, i; - /* Turn all the tiling regions off. */ - for (i = 0; i < NV10_PFB_TILE__SIZE; i++) - nv20_graph_set_tile_region(dev, i); + ret = nouveau_graph_init(&priv->base); + if (ret) + return ret; - nv_wr32(dev, NV10_PGRAPH_CTX_CONTROL, 0x10000100); - nv_wr32(dev, NV10_PGRAPH_STATE , 0xFFFFFFFF); - nv_wr32(dev, 0x0040075c , 0x00000001); + nv_wr32(priv, NV20_PGRAPH_CHANNEL_CTX_TABLE, priv->ctxtab->addr >> 4); - /* begin RAM config */ - /* vramsz = pci_resource_len(dev->pdev, 0) - 1; */ - nv_wr32(dev, 0x4009A4, nv_rd32(dev, NV04_PFB_CFG0)); - nv_wr32(dev, 0x4009A8, nv_rd32(dev, NV04_PFB_CFG1)); - if (dev_priv->chipset != 0x34) { - nv_wr32(dev, 0x400750, 0x00EA0000); - nv_wr32(dev, 0x400754, nv_rd32(dev, NV04_PFB_CFG0)); - nv_wr32(dev, 0x400750, 0x00EA0004); - nv_wr32(dev, 0x400754, nv_rd32(dev, NV04_PFB_CFG1)); + if (nv_device(priv)->chipset == 0x20) { + nv_wr32(priv, NV10_PGRAPH_RDI_INDEX, 0x003d0000); + for (i = 0; i < 15; i++) + nv_wr32(priv, NV10_PGRAPH_RDI_DATA, 0x00000000); + nv_wait(priv, 0x400700, 0xffffffff, 0x00000000); + } else { + nv_wr32(priv, NV10_PGRAPH_RDI_INDEX, 0x02c80000); + for (i = 0; i < 32; i++) + nv_wr32(priv, NV10_PGRAPH_RDI_DATA, 0x00000000); + nv_wait(priv, 0x400700, 0xffffffff, 0x00000000); } - return 0; -} + nv_wr32(priv, NV03_PGRAPH_INTR , 0xFFFFFFFF); + nv_wr32(priv, NV03_PGRAPH_INTR_EN, 0xFFFFFFFF); -int -nv20_graph_fini(struct drm_device *dev, int engine, bool suspend) -{ - nv_mask(dev, NV04_PGRAPH_FIFO, 0x00000001, 0x00000000); - if (!nv_wait(dev, NV04_PGRAPH_STATUS, ~0, 0) && suspend) { - nv_mask(dev, NV04_PGRAPH_FIFO, 0x00000001, 0x00000001); - return -EBUSY; - } - nv20_graph_unload_context(dev); - nv_wr32(dev, NV03_PGRAPH_INTR_EN, 0x00000000); - return 0; -} + nv_wr32(priv, NV04_PGRAPH_DEBUG_0, 0xFFFFFFFF); + nv_wr32(priv, NV04_PGRAPH_DEBUG_0, 0x00000000); + nv_wr32(priv, NV04_PGRAPH_DEBUG_1, 0x00118700); + nv_wr32(priv, NV04_PGRAPH_DEBUG_3, 0xF3CE0475); /* 0x4 = auto ctx switch */ + nv_wr32(priv, NV10_PGRAPH_DEBUG_4, 0x00000000); + nv_wr32(priv, 0x40009C , 0x00000040); -static void -nv20_graph_isr(struct drm_device *dev) -{ - u32 stat; - - while ((stat = nv_rd32(dev, NV03_PGRAPH_INTR))) { - u32 nsource = nv_rd32(dev, NV03_PGRAPH_NSOURCE); - u32 nstatus = nv_rd32(dev, NV03_PGRAPH_NSTATUS); - u32 addr = nv_rd32(dev, NV04_PGRAPH_TRAPPED_ADDR); - u32 chid = (addr & 0x01f00000) >> 20; - u32 subc = (addr & 0x00070000) >> 16; - u32 mthd = (addr & 0x00001ffc); - u32 data = nv_rd32(dev, NV04_PGRAPH_TRAPPED_DATA); - u32 class = nv_rd32(dev, 0x400160 + subc * 4) & 0xfff; - u32 show = stat; - - if (stat & NV_PGRAPH_INTR_ERROR) { - if (nsource & NV03_PGRAPH_NSOURCE_ILLEGAL_MTHD) { - if (!nouveau_gpuobj_mthd_call2(dev, chid, class, mthd, data)) - show &= ~NV_PGRAPH_INTR_ERROR; - } - } + if (nv_device(priv)->chipset >= 0x25) { + nv_wr32(priv, 0x400890, 0x00a8cfff); + nv_wr32(priv, 0x400610, 0x304B1FB6); + nv_wr32(priv, 0x400B80, 0x1cbd3883); + nv_wr32(priv, 0x400B84, 0x44000000); + nv_wr32(priv, 0x400098, 0x40000080); + nv_wr32(priv, 0x400B88, 0x000000ff); - nv_wr32(dev, NV03_PGRAPH_INTR, stat); - nv_wr32(dev, NV04_PGRAPH_FIFO, 0x00000001); - - if (show && nouveau_ratelimit()) { - NV_INFO(dev, "PGRAPH -"); - nouveau_bitfield_print(nv10_graph_intr, show); - printk(" nsource:"); - nouveau_bitfield_print(nv04_graph_nsource, nsource); - printk(" nstatus:"); - nouveau_bitfield_print(nv10_graph_nstatus, nstatus); - printk("\n"); - NV_INFO(dev, "PGRAPH - ch %d/%d class 0x%04x " - "mthd 0x%04x data 0x%08x\n", - chid, subc, class, mthd, data); - } + } else { + nv_wr32(priv, 0x400880, 0x0008c7df); + nv_wr32(priv, 0x400094, 0x00000005); + nv_wr32(priv, 0x400B80, 0x45eae20e); + nv_wr32(priv, 0x400B84, 0x24000000); + nv_wr32(priv, 0x400098, 0x00000040); + nv_wr32(priv, NV10_PGRAPH_RDI_INDEX, 0x00E00038); + nv_wr32(priv, NV10_PGRAPH_RDI_DATA , 0x00000030); + nv_wr32(priv, NV10_PGRAPH_RDI_INDEX, 0x00E10038); + nv_wr32(priv, NV10_PGRAPH_RDI_DATA , 0x00000030); } -} - -static void -nv20_graph_destroy(struct drm_device *dev, int engine) -{ - struct nv20_graph_engine *pgraph = nv_engine(dev, engine); - nouveau_irq_unregister(dev, 12); - nouveau_gpuobj_ref(NULL, &pgraph->ctxtab); + /* Turn all the tiling regions off. */ + for (i = 0; i < pfb->tile.regions; i++) + engine->tile_prog(engine, i); - NVOBJ_ENGINE_DEL(dev, GR); - kfree(pgraph); -} + nv_wr32(priv, 0x4009a0, nv_rd32(priv, 0x100324)); + nv_wr32(priv, NV10_PGRAPH_RDI_INDEX, 0x00EA000C); + nv_wr32(priv, NV10_PGRAPH_RDI_DATA, nv_rd32(priv, 0x100324)); -int -nv20_graph_create(struct drm_device *dev) -{ - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nv20_graph_engine *pgraph; - int ret; + nv_wr32(priv, NV10_PGRAPH_CTX_CONTROL, 0x10000100); + nv_wr32(priv, NV10_PGRAPH_STATE , 0xFFFFFFFF); - pgraph = kzalloc(sizeof(*pgraph), GFP_KERNEL); - if (!pgraph) - return -ENOMEM; - - pgraph->base.destroy = nv20_graph_destroy; - pgraph->base.fini = nv20_graph_fini; - pgraph->base.context_new = nv20_graph_context_new; - pgraph->base.context_del = nv20_graph_context_del; - pgraph->base.object_new = nv04_graph_object_new; - pgraph->base.set_tile_region = nv20_graph_set_tile_region; - - pgraph->grctx_user = 0x0028; - if (dev_priv->card_type == NV_20) { - pgraph->base.init = nv20_graph_init; - switch (dev_priv->chipset) { - case 0x20: - pgraph->grctx_init = nv20_graph_context_init; - pgraph->grctx_size = NV20_GRCTX_SIZE; - pgraph->grctx_user = 0x0000; - break; - case 0x25: - case 0x28: - pgraph->grctx_init = nv25_graph_context_init; - pgraph->grctx_size = NV25_GRCTX_SIZE; - break; - case 0x2a: - pgraph->grctx_init = nv2a_graph_context_init; - pgraph->grctx_size = NV2A_GRCTX_SIZE; - pgraph->grctx_user = 0x0000; - break; - default: - NV_ERROR(dev, "PGRAPH: unknown chipset\n"); - kfree(pgraph); - return 0; - } - } else { - pgraph->base.init = nv30_graph_init; - switch (dev_priv->chipset) { - case 0x30: - case 0x31: - pgraph->grctx_init = nv30_31_graph_context_init; - pgraph->grctx_size = NV30_31_GRCTX_SIZE; - break; - case 0x34: - pgraph->grctx_init = nv34_graph_context_init; - pgraph->grctx_size = NV34_GRCTX_SIZE; - break; - case 0x35: - case 0x36: - pgraph->grctx_init = nv35_36_graph_context_init; - pgraph->grctx_size = NV35_36_GRCTX_SIZE; - break; - default: - NV_ERROR(dev, "PGRAPH: unknown chipset\n"); - kfree(pgraph); - return 0; - } - } + tmp = nv_rd32(priv, NV10_PGRAPH_SURFACE) & 0x0007ff00; + nv_wr32(priv, NV10_PGRAPH_SURFACE, tmp); + tmp = nv_rd32(priv, NV10_PGRAPH_SURFACE) | 0x00020100; + nv_wr32(priv, NV10_PGRAPH_SURFACE, tmp); - /* Create Context Pointer Table */ - ret = nouveau_gpuobj_new(dev, NULL, 32 * 4, 16, NVOBJ_FLAG_ZERO_ALLOC, - &pgraph->ctxtab); - if (ret) { - kfree(pgraph); - return ret; - } + /* begin RAM config */ + vramsz = pci_resource_len(nv_device(priv)->pdev, 0) - 1; + nv_wr32(priv, 0x4009A4, nv_rd32(priv, 0x100200)); + nv_wr32(priv, 0x4009A8, nv_rd32(priv, 0x100204)); + nv_wr32(priv, NV10_PGRAPH_RDI_INDEX, 0x00EA0000); + nv_wr32(priv, NV10_PGRAPH_RDI_DATA , nv_rd32(priv, 0x100200)); + nv_wr32(priv, NV10_PGRAPH_RDI_INDEX, 0x00EA0004); + nv_wr32(priv, NV10_PGRAPH_RDI_DATA , nv_rd32(priv, 0x100204)); + nv_wr32(priv, 0x400820, 0); + nv_wr32(priv, 0x400824, 0); + nv_wr32(priv, 0x400864, vramsz - 1); + nv_wr32(priv, 0x400868, vramsz - 1); - NVOBJ_ENGINE_ADD(dev, GR, &pgraph->base); - nouveau_irq_register(dev, 12, nv20_graph_isr); - - NVOBJ_CLASS(dev, 0x0030, GR); /* null */ - NVOBJ_CLASS(dev, 0x0039, GR); /* m2mf */ - NVOBJ_CLASS(dev, 0x004a, GR); /* gdirect */ - NVOBJ_CLASS(dev, 0x009f, GR); /* imageblit (nv12) */ - NVOBJ_CLASS(dev, 0x008a, GR); /* ifc */ - NVOBJ_CLASS(dev, 0x0089, GR); /* sifm */ - NVOBJ_CLASS(dev, 0x0062, GR); /* surf2d */ - NVOBJ_CLASS(dev, 0x0043, GR); /* rop */ - NVOBJ_CLASS(dev, 0x0012, GR); /* beta1 */ - NVOBJ_CLASS(dev, 0x0072, GR); /* beta4 */ - NVOBJ_CLASS(dev, 0x0019, GR); /* cliprect */ - NVOBJ_CLASS(dev, 0x0044, GR); /* pattern */ - if (dev_priv->card_type == NV_20) { - NVOBJ_CLASS(dev, 0x009e, GR); /* swzsurf */ - NVOBJ_CLASS(dev, 0x0096, GR); /* celcius */ - - /* kelvin */ - if (dev_priv->chipset < 0x25) - NVOBJ_CLASS(dev, 0x0097, GR); - else - NVOBJ_CLASS(dev, 0x0597, GR); - } else { - NVOBJ_CLASS(dev, 0x038a, GR); /* ifc (nv30) */ - NVOBJ_CLASS(dev, 0x0389, GR); /* sifm (nv30) */ - NVOBJ_CLASS(dev, 0x0362, GR); /* surf2d (nv30) */ - NVOBJ_CLASS(dev, 0x039e, GR); /* swzsurf */ - - /* rankine */ - if (0x00000003 & (1 << (dev_priv->chipset & 0x0f))) - NVOBJ_CLASS(dev, 0x0397, GR); - else - if (0x00000010 & (1 << (dev_priv->chipset & 0x0f))) - NVOBJ_CLASS(dev, 0x0697, GR); - else - if (0x000001e0 & (1 << (dev_priv->chipset & 0x0f))) - NVOBJ_CLASS(dev, 0x0497, GR); - } + /* interesting.. the below overwrites some of the tile setup above.. */ + nv_wr32(priv, 0x400B20, 0x00000000); + nv_wr32(priv, 0x400B04, 0xFFFFFFFF); + nv_wr32(priv, NV03_PGRAPH_ABS_UCLIP_XMIN, 0); + nv_wr32(priv, NV03_PGRAPH_ABS_UCLIP_YMIN, 0); + nv_wr32(priv, NV03_PGRAPH_ABS_UCLIP_XMAX, 0x7fff); + nv_wr32(priv, NV03_PGRAPH_ABS_UCLIP_YMAX, 0x7fff); return 0; } + +struct nouveau_oclass +nv20_graph_oclass = { + .handle = NV_ENGINE(GR, 0x20), + .ofuncs = &(struct nouveau_ofuncs) { + .ctor = nv20_graph_ctor, + .dtor = nv20_graph_dtor, + .init = nv20_graph_init, + .fini = _nouveau_graph_fini, + }, +}; diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/nv20.h b/drivers/gpu/drm/nouveau/core/engine/graph/nv20.h new file mode 100644 index 000000000000..2bea7313e03f --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/engine/graph/nv20.h @@ -0,0 +1,31 @@ +#ifndef __NV20_GRAPH_H__ +#define __NV20_GRAPH_H__ + +#include + +#include +#include + +struct nv20_graph_priv { + struct nouveau_graph base; + struct nouveau_gpuobj *ctxtab; +}; + +struct nv20_graph_chan { + struct nouveau_graph_chan base; + int chid; +}; + +extern struct nouveau_oclass nv25_graph_sclass[]; +int nv20_graph_context_init(struct nouveau_object *); +int nv20_graph_context_fini(struct nouveau_object *, bool); + +void nv20_graph_tile_prog(struct nouveau_engine *, int); +void nv20_graph_intr(struct nouveau_subdev *); + +void nv20_graph_dtor(struct nouveau_object *); +int nv20_graph_init(struct nouveau_object *); + +int nv30_graph_init(struct nouveau_object *); + +#endif diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/nv25.c b/drivers/gpu/drm/nouveau/core/engine/graph/nv25.c new file mode 100644 index 000000000000..b2b650dd8b28 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/engine/graph/nv25.c @@ -0,0 +1,167 @@ +#include +#include +#include +#include + +#include +#include + +#include + +#include "nv20.h" +#include "regs.h" + +/******************************************************************************* + * Graphics object classes + ******************************************************************************/ + +struct nouveau_oclass +nv25_graph_sclass[] = { + { 0x0012, &nv04_graph_ofuncs, NULL }, /* beta1 */ + { 0x0019, &nv04_graph_ofuncs, NULL }, /* clip */ + { 0x0030, &nv04_graph_ofuncs, NULL }, /* null */ + { 0x0039, &nv04_graph_ofuncs, NULL }, /* m2mf */ + { 0x0043, &nv04_graph_ofuncs, NULL }, /* rop */ + { 0x0044, &nv04_graph_ofuncs, NULL }, /* patt */ + { 0x004a, &nv04_graph_ofuncs, NULL }, /* gdi */ + { 0x0062, &nv04_graph_ofuncs, NULL }, /* surf2d */ + { 0x0072, &nv04_graph_ofuncs, NULL }, /* beta4 */ + { 0x0089, &nv04_graph_ofuncs, NULL }, /* sifm */ + { 0x008a, &nv04_graph_ofuncs, NULL }, /* ifc */ + { 0x0096, &nv04_graph_ofuncs, NULL }, /* celcius */ + { 0x009e, &nv04_graph_ofuncs, NULL }, /* swzsurf */ + { 0x009f, &nv04_graph_ofuncs, NULL }, /* imageblit */ + { 0x0597, &nv04_graph_ofuncs, NULL }, /* kelvin */ + {}, +}; + +/******************************************************************************* + * PGRAPH context + ******************************************************************************/ + +static int +nv25_graph_context_ctor(struct nouveau_object *parent, + struct nouveau_object *engine, + struct nouveau_oclass *oclass, void *data, u32 size, + struct nouveau_object **pobject) +{ + struct nv20_graph_chan *chan; + int ret, i; + + ret = nouveau_graph_context_create(parent, engine, oclass, NULL, 0x3724, + 16, NVOBJ_FLAG_ZERO_ALLOC, &chan); + *pobject = nv_object(chan); + if (ret) + return ret; + + chan->chid = nouveau_fifo_chan(parent)->chid; + + nv_wo32(chan, 0x0028, 0x00000001 | (chan->chid << 24)); + nv_wo32(chan, 0x035c, 0xffff0000); + nv_wo32(chan, 0x03c0, 0x0fff0000); + nv_wo32(chan, 0x03c4, 0x0fff0000); + nv_wo32(chan, 0x049c, 0x00000101); + nv_wo32(chan, 0x04b0, 0x00000111); + nv_wo32(chan, 0x04c8, 0x00000080); + nv_wo32(chan, 0x04cc, 0xffff0000); + nv_wo32(chan, 0x04d0, 0x00000001); + nv_wo32(chan, 0x04e4, 0x44400000); + nv_wo32(chan, 0x04fc, 0x4b800000); + for (i = 0x0510; i <= 0x051c; i += 4) + nv_wo32(chan, i, 0x00030303); + for (i = 0x0530; i <= 0x053c; i += 4) + nv_wo32(chan, i, 0x00080000); + for (i = 0x0548; i <= 0x0554; i += 4) + nv_wo32(chan, i, 0x01012000); + for (i = 0x0558; i <= 0x0564; i += 4) + nv_wo32(chan, i, 0x000105b8); + for (i = 0x0568; i <= 0x0574; i += 4) + nv_wo32(chan, i, 0x00080008); + for (i = 0x0598; i <= 0x05d4; i += 4) + nv_wo32(chan, i, 0x07ff0000); + nv_wo32(chan, 0x05e0, 0x4b7fffff); + nv_wo32(chan, 0x0620, 0x00000080); + nv_wo32(chan, 0x0624, 0x30201000); + nv_wo32(chan, 0x0628, 0x70605040); + nv_wo32(chan, 0x062c, 0xb0a09080); + nv_wo32(chan, 0x0630, 0xf0e0d0c0); + nv_wo32(chan, 0x0664, 0x00000001); + nv_wo32(chan, 0x066c, 0x00004000); + nv_wo32(chan, 0x0678, 0x00000001); + nv_wo32(chan, 0x0680, 0x00040000); + nv_wo32(chan, 0x0684, 0x00010000); + for (i = 0x1b04; i <= 0x2374; i += 16) { + nv_wo32(chan, (i + 0), 0x10700ff9); + nv_wo32(chan, (i + 4), 0x0436086c); + nv_wo32(chan, (i + 8), 0x000c001b); + } + nv_wo32(chan, 0x2704, 0x3f800000); + nv_wo32(chan, 0x2718, 0x3f800000); + nv_wo32(chan, 0x2744, 0x40000000); + nv_wo32(chan, 0x2748, 0x3f800000); + nv_wo32(chan, 0x274c, 0x3f000000); + nv_wo32(chan, 0x2754, 0x40000000); + nv_wo32(chan, 0x2758, 0x3f800000); + nv_wo32(chan, 0x2760, 0xbf800000); + nv_wo32(chan, 0x2768, 0xbf800000); + nv_wo32(chan, 0x308c, 0x000fe000); + nv_wo32(chan, 0x3108, 0x000003f8); + nv_wo32(chan, 0x3468, 0x002fe000); + for (i = 0x3484; i <= 0x34a0; i += 4) + nv_wo32(chan, i, 0x001c527c); + return 0; +} + +static struct nouveau_oclass +nv25_graph_cclass = { + .handle = NV_ENGCTX(GR, 0x25), + .ofuncs = &(struct nouveau_ofuncs) { + .ctor = nv25_graph_context_ctor, + .dtor = _nouveau_graph_context_dtor, + .init = nv20_graph_context_init, + .fini = nv20_graph_context_fini, + .rd32 = _nouveau_graph_context_rd32, + .wr32 = _nouveau_graph_context_wr32, + }, +}; + +/******************************************************************************* + * PGRAPH engine/subdev functions + ******************************************************************************/ + +static int +nv25_graph_ctor(struct nouveau_object *parent, struct nouveau_object *engine, + struct nouveau_oclass *oclass, void *data, u32 size, + struct nouveau_object **pobject) +{ + struct nv20_graph_priv *priv; + int ret; + + ret = nouveau_graph_create(parent, engine, oclass, true, &priv); + *pobject = nv_object(priv); + if (ret) + return ret; + + ret = nouveau_gpuobj_new(parent, NULL, 32 * 4, 16, + NVOBJ_FLAG_ZERO_ALLOC, &priv->ctxtab); + if (ret) + return ret; + + nv_subdev(priv)->unit = 0x00001000; + nv_subdev(priv)->intr = nv20_graph_intr; + nv_engine(priv)->cclass = &nv25_graph_cclass; + nv_engine(priv)->sclass = nv25_graph_sclass; + nv_engine(priv)->tile_prog = nv20_graph_tile_prog; + return 0; +} + +struct nouveau_oclass +nv25_graph_oclass = { + .handle = NV_ENGINE(GR, 0x25), + .ofuncs = &(struct nouveau_ofuncs) { + .ctor = nv25_graph_ctor, + .dtor = nv20_graph_dtor, + .init = nv20_graph_init, + .fini = _nouveau_graph_fini, + }, +}; diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/nv2a.c b/drivers/gpu/drm/nouveau/core/engine/graph/nv2a.c new file mode 100644 index 000000000000..700462fa0ae0 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/engine/graph/nv2a.c @@ -0,0 +1,134 @@ +#include +#include +#include +#include + +#include +#include + +#include + +#include "nv20.h" +#include "regs.h" + +/******************************************************************************* + * PGRAPH context + ******************************************************************************/ + +static int +nv2a_graph_context_ctor(struct nouveau_object *parent, + struct nouveau_object *engine, + struct nouveau_oclass *oclass, void *data, u32 size, + struct nouveau_object **pobject) +{ + struct nv20_graph_chan *chan; + int ret, i; + + ret = nouveau_graph_context_create(parent, engine, oclass, NULL, 0x36b0, + 16, NVOBJ_FLAG_ZERO_ALLOC, &chan); + *pobject = nv_object(chan); + if (ret) + return ret; + + chan->chid = nouveau_fifo_chan(parent)->chid; + + nv_wo32(chan, 0x0000, 0x00000001 | (chan->chid << 24)); + nv_wo32(chan, 0x033c, 0xffff0000); + nv_wo32(chan, 0x03a0, 0x0fff0000); + nv_wo32(chan, 0x03a4, 0x0fff0000); + nv_wo32(chan, 0x047c, 0x00000101); + nv_wo32(chan, 0x0490, 0x00000111); + nv_wo32(chan, 0x04a8, 0x44400000); + for (i = 0x04d4; i <= 0x04e0; i += 4) + nv_wo32(chan, i, 0x00030303); + for (i = 0x04f4; i <= 0x0500; i += 4) + nv_wo32(chan, i, 0x00080000); + for (i = 0x050c; i <= 0x0518; i += 4) + nv_wo32(chan, i, 0x01012000); + for (i = 0x051c; i <= 0x0528; i += 4) + nv_wo32(chan, i, 0x000105b8); + for (i = 0x052c; i <= 0x0538; i += 4) + nv_wo32(chan, i, 0x00080008); + for (i = 0x055c; i <= 0x0598; i += 4) + nv_wo32(chan, i, 0x07ff0000); + nv_wo32(chan, 0x05a4, 0x4b7fffff); + nv_wo32(chan, 0x05fc, 0x00000001); + nv_wo32(chan, 0x0604, 0x00004000); + nv_wo32(chan, 0x0610, 0x00000001); + nv_wo32(chan, 0x0618, 0x00040000); + nv_wo32(chan, 0x061c, 0x00010000); + for (i = 0x1a9c; i <= 0x22fc; i += 16) { /*XXX: check!! */ + nv_wo32(chan, (i + 0), 0x10700ff9); + nv_wo32(chan, (i + 4), 0x0436086c); + nv_wo32(chan, (i + 8), 0x000c001b); + } + nv_wo32(chan, 0x269c, 0x3f800000); + nv_wo32(chan, 0x26b0, 0x3f800000); + nv_wo32(chan, 0x26dc, 0x40000000); + nv_wo32(chan, 0x26e0, 0x3f800000); + nv_wo32(chan, 0x26e4, 0x3f000000); + nv_wo32(chan, 0x26ec, 0x40000000); + nv_wo32(chan, 0x26f0, 0x3f800000); + nv_wo32(chan, 0x26f8, 0xbf800000); + nv_wo32(chan, 0x2700, 0xbf800000); + nv_wo32(chan, 0x3024, 0x000fe000); + nv_wo32(chan, 0x30a0, 0x000003f8); + nv_wo32(chan, 0x33fc, 0x002fe000); + for (i = 0x341c; i <= 0x3438; i += 4) + nv_wo32(chan, i, 0x001c527c); + return 0; +} + +static struct nouveau_oclass +nv2a_graph_cclass = { + .handle = NV_ENGCTX(GR, 0x2a), + .ofuncs = &(struct nouveau_ofuncs) { + .ctor = nv2a_graph_context_ctor, + .dtor = _nouveau_graph_context_dtor, + .init = nv20_graph_context_init, + .fini = nv20_graph_context_fini, + .rd32 = _nouveau_graph_context_rd32, + .wr32 = _nouveau_graph_context_wr32, + }, +}; + +/******************************************************************************* + * PGRAPH engine/subdev functions + ******************************************************************************/ + +static int +nv2a_graph_ctor(struct nouveau_object *parent, struct nouveau_object *engine, + struct nouveau_oclass *oclass, void *data, u32 size, + struct nouveau_object **pobject) +{ + struct nv20_graph_priv *priv; + int ret; + + ret = nouveau_graph_create(parent, engine, oclass, true, &priv); + *pobject = nv_object(priv); + if (ret) + return ret; + + ret = nouveau_gpuobj_new(parent, NULL, 32 * 4, 16, + NVOBJ_FLAG_ZERO_ALLOC, &priv->ctxtab); + if (ret) + return ret; + + nv_subdev(priv)->unit = 0x00001000; + nv_subdev(priv)->intr = nv20_graph_intr; + nv_engine(priv)->cclass = &nv2a_graph_cclass; + nv_engine(priv)->sclass = nv25_graph_sclass; + nv_engine(priv)->tile_prog = nv20_graph_tile_prog; + return 0; +} + +struct nouveau_oclass +nv2a_graph_oclass = { + .handle = NV_ENGINE(GR, 0x2a), + .ofuncs = &(struct nouveau_ofuncs) { + .ctor = nv2a_graph_ctor, + .dtor = nv20_graph_dtor, + .init = nv20_graph_init, + .fini = _nouveau_graph_fini, + }, +}; diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/nv30.c b/drivers/gpu/drm/nouveau/core/engine/graph/nv30.c new file mode 100644 index 000000000000..cedadaa92d3f --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/engine/graph/nv30.c @@ -0,0 +1,238 @@ +#include +#include +#include +#include + +#include +#include + +#include + +#include "nv20.h" +#include "regs.h" + +/******************************************************************************* + * Graphics object classes + ******************************************************************************/ + +static struct nouveau_oclass +nv30_graph_sclass[] = { + { 0x0012, &nv04_graph_ofuncs, NULL }, /* beta1 */ + { 0x0019, &nv04_graph_ofuncs, NULL }, /* clip */ + { 0x0030, &nv04_graph_ofuncs, NULL }, /* null */ + { 0x0039, &nv04_graph_ofuncs, NULL }, /* m2mf */ + { 0x0043, &nv04_graph_ofuncs, NULL }, /* rop */ + { 0x0044, &nv04_graph_ofuncs, NULL }, /* patt */ + { 0x004a, &nv04_graph_ofuncs, NULL }, /* gdi */ + { 0x0062, &nv04_graph_ofuncs, NULL }, /* surf2d */ + { 0x0072, &nv04_graph_ofuncs, NULL }, /* beta4 */ + { 0x0089, &nv04_graph_ofuncs, NULL }, /* sifm */ + { 0x008a, &nv04_graph_ofuncs, NULL }, /* ifc */ + { 0x009f, &nv04_graph_ofuncs, NULL }, /* imageblit */ + { 0x0362, &nv04_graph_ofuncs, NULL }, /* surf2d (nv30) */ + { 0x0389, &nv04_graph_ofuncs, NULL }, /* sifm (nv30) */ + { 0x038a, &nv04_graph_ofuncs, NULL }, /* ifc (nv30) */ + { 0x039e, &nv04_graph_ofuncs, NULL }, /* swzsurf (nv30) */ + { 0x0397, &nv04_graph_ofuncs, NULL }, /* rankine */ + {}, +}; + +/******************************************************************************* + * PGRAPH context + ******************************************************************************/ + +static int +nv30_graph_context_ctor(struct nouveau_object *parent, + struct nouveau_object *engine, + struct nouveau_oclass *oclass, void *data, u32 size, + struct nouveau_object **pobject) +{ + struct nv20_graph_chan *chan; + int ret, i; + + ret = nouveau_graph_context_create(parent, engine, oclass, NULL, 0x5f48, + 16, NVOBJ_FLAG_ZERO_ALLOC, &chan); + *pobject = nv_object(chan); + if (ret) + return ret; + + chan->chid = nouveau_fifo_chan(parent)->chid; + + nv_wo32(chan, 0x0028, 0x00000001 | (chan->chid << 24)); + nv_wo32(chan, 0x0410, 0x00000101); + nv_wo32(chan, 0x0424, 0x00000111); + nv_wo32(chan, 0x0428, 0x00000060); + nv_wo32(chan, 0x0444, 0x00000080); + nv_wo32(chan, 0x0448, 0xffff0000); + nv_wo32(chan, 0x044c, 0x00000001); + nv_wo32(chan, 0x0460, 0x44400000); + nv_wo32(chan, 0x048c, 0xffff0000); + for (i = 0x04e0; i < 0x04e8; i += 4) + nv_wo32(chan, i, 0x0fff0000); + nv_wo32(chan, 0x04ec, 0x00011100); + for (i = 0x0508; i < 0x0548; i += 4) + nv_wo32(chan, i, 0x07ff0000); + nv_wo32(chan, 0x0550, 0x4b7fffff); + nv_wo32(chan, 0x058c, 0x00000080); + nv_wo32(chan, 0x0590, 0x30201000); + nv_wo32(chan, 0x0594, 0x70605040); + nv_wo32(chan, 0x0598, 0xb8a89888); + nv_wo32(chan, 0x059c, 0xf8e8d8c8); + nv_wo32(chan, 0x05b0, 0xb0000000); + for (i = 0x0600; i < 0x0640; i += 4) + nv_wo32(chan, i, 0x00010588); + for (i = 0x0640; i < 0x0680; i += 4) + nv_wo32(chan, i, 0x00030303); + for (i = 0x06c0; i < 0x0700; i += 4) + nv_wo32(chan, i, 0x0008aae4); + for (i = 0x0700; i < 0x0740; i += 4) + nv_wo32(chan, i, 0x01012000); + for (i = 0x0740; i < 0x0780; i += 4) + nv_wo32(chan, i, 0x00080008); + nv_wo32(chan, 0x085c, 0x00040000); + nv_wo32(chan, 0x0860, 0x00010000); + for (i = 0x0864; i < 0x0874; i += 4) + nv_wo32(chan, i, 0x00040004); + for (i = 0x1f18; i <= 0x3088 ; i += 16) { + nv_wo32(chan, i + 0, 0x10700ff9); + nv_wo32(chan, i + 1, 0x0436086c); + nv_wo32(chan, i + 2, 0x000c001b); + } + for (i = 0x30b8; i < 0x30c8; i += 4) + nv_wo32(chan, i, 0x0000ffff); + nv_wo32(chan, 0x344c, 0x3f800000); + nv_wo32(chan, 0x3808, 0x3f800000); + nv_wo32(chan, 0x381c, 0x3f800000); + nv_wo32(chan, 0x3848, 0x40000000); + nv_wo32(chan, 0x384c, 0x3f800000); + nv_wo32(chan, 0x3850, 0x3f000000); + nv_wo32(chan, 0x3858, 0x40000000); + nv_wo32(chan, 0x385c, 0x3f800000); + nv_wo32(chan, 0x3864, 0xbf800000); + nv_wo32(chan, 0x386c, 0xbf800000); + return 0; +} + +static struct nouveau_oclass +nv30_graph_cclass = { + .handle = NV_ENGCTX(GR, 0x30), + .ofuncs = &(struct nouveau_ofuncs) { + .ctor = nv30_graph_context_ctor, + .dtor = _nouveau_graph_context_dtor, + .init = nv20_graph_context_init, + .fini = nv20_graph_context_fini, + .rd32 = _nouveau_graph_context_rd32, + .wr32 = _nouveau_graph_context_wr32, + }, +}; + +/******************************************************************************* + * PGRAPH engine/subdev functions + ******************************************************************************/ + +static int +nv30_graph_ctor(struct nouveau_object *parent, struct nouveau_object *engine, + struct nouveau_oclass *oclass, void *data, u32 size, + struct nouveau_object **pobject) +{ + struct nv20_graph_priv *priv; + int ret; + + ret = nouveau_graph_create(parent, engine, oclass, true, &priv); + *pobject = nv_object(priv); + if (ret) + return ret; + + ret = nouveau_gpuobj_new(parent, NULL, 32 * 4, 16, + NVOBJ_FLAG_ZERO_ALLOC, &priv->ctxtab); + if (ret) + return ret; + + nv_subdev(priv)->unit = 0x00001000; + nv_subdev(priv)->intr = nv20_graph_intr; + nv_engine(priv)->cclass = &nv30_graph_cclass; + nv_engine(priv)->sclass = nv30_graph_sclass; + nv_engine(priv)->tile_prog = nv20_graph_tile_prog; + return 0; +} + +int +nv30_graph_init(struct nouveau_object *object) +{ + struct nouveau_engine *engine = nv_engine(object); + struct nv20_graph_priv *priv = (void *)engine; + struct nouveau_fb *pfb = nouveau_fb(object); + int ret, i; + + ret = nouveau_graph_init(&priv->base); + if (ret) + return ret; + + nv_wr32(priv, NV20_PGRAPH_CHANNEL_CTX_TABLE, priv->ctxtab->addr >> 4); + + nv_wr32(priv, NV03_PGRAPH_INTR , 0xFFFFFFFF); + nv_wr32(priv, NV03_PGRAPH_INTR_EN, 0xFFFFFFFF); + + nv_wr32(priv, NV04_PGRAPH_DEBUG_0, 0xFFFFFFFF); + nv_wr32(priv, NV04_PGRAPH_DEBUG_0, 0x00000000); + nv_wr32(priv, NV04_PGRAPH_DEBUG_1, 0x401287c0); + nv_wr32(priv, 0x400890, 0x01b463ff); + nv_wr32(priv, NV04_PGRAPH_DEBUG_3, 0xf2de0475); + nv_wr32(priv, NV10_PGRAPH_DEBUG_4, 0x00008000); + nv_wr32(priv, NV04_PGRAPH_LIMIT_VIOL_PIX, 0xf04bdff6); + nv_wr32(priv, 0x400B80, 0x1003d888); + nv_wr32(priv, 0x400B84, 0x0c000000); + nv_wr32(priv, 0x400098, 0x00000000); + nv_wr32(priv, 0x40009C, 0x0005ad00); + nv_wr32(priv, 0x400B88, 0x62ff00ff); /* suspiciously like PGRAPH_DEBUG_2 */ + nv_wr32(priv, 0x4000a0, 0x00000000); + nv_wr32(priv, 0x4000a4, 0x00000008); + nv_wr32(priv, 0x4008a8, 0xb784a400); + nv_wr32(priv, 0x400ba0, 0x002f8685); + nv_wr32(priv, 0x400ba4, 0x00231f3f); + nv_wr32(priv, 0x4008a4, 0x40000020); + + if (nv_device(priv)->chipset == 0x34) { + nv_wr32(priv, NV10_PGRAPH_RDI_INDEX, 0x00EA0004); + nv_wr32(priv, NV10_PGRAPH_RDI_DATA , 0x00200201); + nv_wr32(priv, NV10_PGRAPH_RDI_INDEX, 0x00EA0008); + nv_wr32(priv, NV10_PGRAPH_RDI_DATA , 0x00000008); + nv_wr32(priv, NV10_PGRAPH_RDI_INDEX, 0x00EA0000); + nv_wr32(priv, NV10_PGRAPH_RDI_DATA , 0x00000032); + nv_wr32(priv, NV10_PGRAPH_RDI_INDEX, 0x00E00004); + nv_wr32(priv, NV10_PGRAPH_RDI_DATA , 0x00000002); + } + + nv_wr32(priv, 0x4000c0, 0x00000016); + + /* Turn all the tiling regions off. */ + for (i = 0; i < pfb->tile.regions; i++) + engine->tile_prog(engine, i); + + nv_wr32(priv, NV10_PGRAPH_CTX_CONTROL, 0x10000100); + nv_wr32(priv, NV10_PGRAPH_STATE , 0xFFFFFFFF); + nv_wr32(priv, 0x0040075c , 0x00000001); + + /* begin RAM config */ + /* vramsz = pci_resource_len(priv->dev->pdev, 0) - 1; */ + nv_wr32(priv, 0x4009A4, nv_rd32(priv, 0x100200)); + nv_wr32(priv, 0x4009A8, nv_rd32(priv, 0x100204)); + if (nv_device(priv)->chipset != 0x34) { + nv_wr32(priv, 0x400750, 0x00EA0000); + nv_wr32(priv, 0x400754, nv_rd32(priv, 0x100200)); + nv_wr32(priv, 0x400750, 0x00EA0004); + nv_wr32(priv, 0x400754, nv_rd32(priv, 0x100204)); + } + return 0; +} + +struct nouveau_oclass +nv30_graph_oclass = { + .handle = NV_ENGINE(GR, 0x30), + .ofuncs = &(struct nouveau_ofuncs) { + .ctor = nv30_graph_ctor, + .dtor = nv20_graph_dtor, + .init = nv30_graph_init, + .fini = _nouveau_graph_fini, + }, +}; diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/nv34.c b/drivers/gpu/drm/nouveau/core/engine/graph/nv34.c new file mode 100644 index 000000000000..273f6320027b --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/engine/graph/nv34.c @@ -0,0 +1,168 @@ +#include +#include +#include +#include + +#include +#include + +#include + +#include "nv20.h" +#include "regs.h" + +/******************************************************************************* + * Graphics object classes + ******************************************************************************/ + +static struct nouveau_oclass +nv34_graph_sclass[] = { + { 0x0012, &nv04_graph_ofuncs, NULL }, /* beta1 */ + { 0x0019, &nv04_graph_ofuncs, NULL }, /* clip */ + { 0x0030, &nv04_graph_ofuncs, NULL }, /* null */ + { 0x0039, &nv04_graph_ofuncs, NULL }, /* m2mf */ + { 0x0043, &nv04_graph_ofuncs, NULL }, /* rop */ + { 0x0044, &nv04_graph_ofuncs, NULL }, /* patt */ + { 0x004a, &nv04_graph_ofuncs, NULL }, /* gdi */ + { 0x0062, &nv04_graph_ofuncs, NULL }, /* surf2d */ + { 0x0072, &nv04_graph_ofuncs, NULL }, /* beta4 */ + { 0x0089, &nv04_graph_ofuncs, NULL }, /* sifm */ + { 0x008a, &nv04_graph_ofuncs, NULL }, /* ifc */ + { 0x009f, &nv04_graph_ofuncs, NULL }, /* imageblit */ + { 0x0362, &nv04_graph_ofuncs, NULL }, /* surf2d (nv30) */ + { 0x0389, &nv04_graph_ofuncs, NULL }, /* sifm (nv30) */ + { 0x038a, &nv04_graph_ofuncs, NULL }, /* ifc (nv30) */ + { 0x039e, &nv04_graph_ofuncs, NULL }, /* swzsurf (nv30) */ + { 0x0697, &nv04_graph_ofuncs, NULL }, /* rankine */ + {}, +}; + +/******************************************************************************* + * PGRAPH context + ******************************************************************************/ + +static int +nv34_graph_context_ctor(struct nouveau_object *parent, + struct nouveau_object *engine, + struct nouveau_oclass *oclass, void *data, u32 size, + struct nouveau_object **pobject) +{ + struct nv20_graph_chan *chan; + int ret, i; + + ret = nouveau_graph_context_create(parent, engine, oclass, NULL, 0x46dc, + 16, NVOBJ_FLAG_ZERO_ALLOC, &chan); + *pobject = nv_object(chan); + if (ret) + return ret; + + chan->chid = nouveau_fifo_chan(parent)->chid; + + nv_wo32(chan, 0x0028, 0x00000001 | (chan->chid << 24)); + nv_wo32(chan, 0x040c, 0x01000101); + nv_wo32(chan, 0x0420, 0x00000111); + nv_wo32(chan, 0x0424, 0x00000060); + nv_wo32(chan, 0x0440, 0x00000080); + nv_wo32(chan, 0x0444, 0xffff0000); + nv_wo32(chan, 0x0448, 0x00000001); + nv_wo32(chan, 0x045c, 0x44400000); + nv_wo32(chan, 0x0480, 0xffff0000); + for (i = 0x04d4; i < 0x04dc; i += 4) + nv_wo32(chan, i, 0x0fff0000); + nv_wo32(chan, 0x04e0, 0x00011100); + for (i = 0x04fc; i < 0x053c; i += 4) + nv_wo32(chan, i, 0x07ff0000); + nv_wo32(chan, 0x0544, 0x4b7fffff); + nv_wo32(chan, 0x057c, 0x00000080); + nv_wo32(chan, 0x0580, 0x30201000); + nv_wo32(chan, 0x0584, 0x70605040); + nv_wo32(chan, 0x0588, 0xb8a89888); + nv_wo32(chan, 0x058c, 0xf8e8d8c8); + nv_wo32(chan, 0x05a0, 0xb0000000); + for (i = 0x05f0; i < 0x0630; i += 4) + nv_wo32(chan, i, 0x00010588); + for (i = 0x0630; i < 0x0670; i += 4) + nv_wo32(chan, i, 0x00030303); + for (i = 0x06b0; i < 0x06f0; i += 4) + nv_wo32(chan, i, 0x0008aae4); + for (i = 0x06f0; i < 0x0730; i += 4) + nv_wo32(chan, i, 0x01012000); + for (i = 0x0730; i < 0x0770; i += 4) + nv_wo32(chan, i, 0x00080008); + nv_wo32(chan, 0x0850, 0x00040000); + nv_wo32(chan, 0x0854, 0x00010000); + for (i = 0x0858; i < 0x0868; i += 4) + nv_wo32(chan, i, 0x00040004); + for (i = 0x15ac; i <= 0x271c ; i += 16) { + nv_wo32(chan, i + 0, 0x10700ff9); + nv_wo32(chan, i + 1, 0x0436086c); + nv_wo32(chan, i + 2, 0x000c001b); + } + for (i = 0x274c; i < 0x275c; i += 4) + nv_wo32(chan, i, 0x0000ffff); + nv_wo32(chan, 0x2ae0, 0x3f800000); + nv_wo32(chan, 0x2e9c, 0x3f800000); + nv_wo32(chan, 0x2eb0, 0x3f800000); + nv_wo32(chan, 0x2edc, 0x40000000); + nv_wo32(chan, 0x2ee0, 0x3f800000); + nv_wo32(chan, 0x2ee4, 0x3f000000); + nv_wo32(chan, 0x2eec, 0x40000000); + nv_wo32(chan, 0x2ef0, 0x3f800000); + nv_wo32(chan, 0x2ef8, 0xbf800000); + nv_wo32(chan, 0x2f00, 0xbf800000); + return 0; +} + +static struct nouveau_oclass +nv34_graph_cclass = { + .handle = NV_ENGCTX(GR, 0x34), + .ofuncs = &(struct nouveau_ofuncs) { + .ctor = nv34_graph_context_ctor, + .dtor = _nouveau_graph_context_dtor, + .init = nv20_graph_context_init, + .fini = nv20_graph_context_fini, + .rd32 = _nouveau_graph_context_rd32, + .wr32 = _nouveau_graph_context_wr32, + }, +}; + +/******************************************************************************* + * PGRAPH engine/subdev functions + ******************************************************************************/ + +static int +nv34_graph_ctor(struct nouveau_object *parent, struct nouveau_object *engine, + struct nouveau_oclass *oclass, void *data, u32 size, + struct nouveau_object **pobject) +{ + struct nv20_graph_priv *priv; + int ret; + + ret = nouveau_graph_create(parent, engine, oclass, true, &priv); + *pobject = nv_object(priv); + if (ret) + return ret; + + ret = nouveau_gpuobj_new(parent, NULL, 32 * 4, 16, + NVOBJ_FLAG_ZERO_ALLOC, &priv->ctxtab); + if (ret) + return ret; + + nv_subdev(priv)->unit = 0x00001000; + nv_subdev(priv)->intr = nv20_graph_intr; + nv_engine(priv)->cclass = &nv34_graph_cclass; + nv_engine(priv)->sclass = nv34_graph_sclass; + nv_engine(priv)->tile_prog = nv20_graph_tile_prog; + return 0; +} + +struct nouveau_oclass +nv34_graph_oclass = { + .handle = NV_ENGINE(GR, 0x34), + .ofuncs = &(struct nouveau_ofuncs) { + .ctor = nv34_graph_ctor, + .dtor = nv20_graph_dtor, + .init = nv30_graph_init, + .fini = _nouveau_graph_fini, + }, +}; diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/nv35.c b/drivers/gpu/drm/nouveau/core/engine/graph/nv35.c new file mode 100644 index 000000000000..f40ee2116ee1 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/engine/graph/nv35.c @@ -0,0 +1,166 @@ +#include +#include +#include +#include + +#include +#include + +#include "nv20.h" +#include "regs.h" + +/******************************************************************************* + * Graphics object classes + ******************************************************************************/ + +static struct nouveau_oclass +nv35_graph_sclass[] = { + { 0x0012, &nv04_graph_ofuncs, NULL }, /* beta1 */ + { 0x0019, &nv04_graph_ofuncs, NULL }, /* clip */ + { 0x0030, &nv04_graph_ofuncs, NULL }, /* null */ + { 0x0039, &nv04_graph_ofuncs, NULL }, /* m2mf */ + { 0x0043, &nv04_graph_ofuncs, NULL }, /* rop */ + { 0x0044, &nv04_graph_ofuncs, NULL }, /* patt */ + { 0x004a, &nv04_graph_ofuncs, NULL }, /* gdi */ + { 0x0062, &nv04_graph_ofuncs, NULL }, /* surf2d */ + { 0x0072, &nv04_graph_ofuncs, NULL }, /* beta4 */ + { 0x0089, &nv04_graph_ofuncs, NULL }, /* sifm */ + { 0x008a, &nv04_graph_ofuncs, NULL }, /* ifc */ + { 0x009f, &nv04_graph_ofuncs, NULL }, /* imageblit */ + { 0x0362, &nv04_graph_ofuncs, NULL }, /* surf2d (nv30) */ + { 0x0389, &nv04_graph_ofuncs, NULL }, /* sifm (nv30) */ + { 0x038a, &nv04_graph_ofuncs, NULL }, /* ifc (nv30) */ + { 0x039e, &nv04_graph_ofuncs, NULL }, /* swzsurf (nv30) */ + { 0x0497, &nv04_graph_ofuncs, NULL }, /* rankine */ + {}, +}; + +/******************************************************************************* + * PGRAPH context + ******************************************************************************/ + +static int +nv35_graph_context_ctor(struct nouveau_object *parent, + struct nouveau_object *engine, + struct nouveau_oclass *oclass, void *data, u32 size, + struct nouveau_object **pobject) +{ + struct nv20_graph_chan *chan; + int ret, i; + + ret = nouveau_graph_context_create(parent, engine, oclass, NULL, 0x577c, + 16, NVOBJ_FLAG_ZERO_ALLOC, &chan); + *pobject = nv_object(chan); + if (ret) + return ret; + + chan->chid = nouveau_fifo_chan(parent)->chid; + + nv_wo32(chan, 0x0028, 0x00000001 | (chan->chid << 24)); + nv_wo32(chan, 0x040c, 0x00000101); + nv_wo32(chan, 0x0420, 0x00000111); + nv_wo32(chan, 0x0424, 0x00000060); + nv_wo32(chan, 0x0440, 0x00000080); + nv_wo32(chan, 0x0444, 0xffff0000); + nv_wo32(chan, 0x0448, 0x00000001); + nv_wo32(chan, 0x045c, 0x44400000); + nv_wo32(chan, 0x0488, 0xffff0000); + for (i = 0x04dc; i < 0x04e4; i += 4) + nv_wo32(chan, i, 0x0fff0000); + nv_wo32(chan, 0x04e8, 0x00011100); + for (i = 0x0504; i < 0x0544; i += 4) + nv_wo32(chan, i, 0x07ff0000); + nv_wo32(chan, 0x054c, 0x4b7fffff); + nv_wo32(chan, 0x0588, 0x00000080); + nv_wo32(chan, 0x058c, 0x30201000); + nv_wo32(chan, 0x0590, 0x70605040); + nv_wo32(chan, 0x0594, 0xb8a89888); + nv_wo32(chan, 0x0598, 0xf8e8d8c8); + nv_wo32(chan, 0x05ac, 0xb0000000); + for (i = 0x0604; i < 0x0644; i += 4) + nv_wo32(chan, i, 0x00010588); + for (i = 0x0644; i < 0x0684; i += 4) + nv_wo32(chan, i, 0x00030303); + for (i = 0x06c4; i < 0x0704; i += 4) + nv_wo32(chan, i, 0x0008aae4); + for (i = 0x0704; i < 0x0744; i += 4) + nv_wo32(chan, i, 0x01012000); + for (i = 0x0744; i < 0x0784; i += 4) + nv_wo32(chan, i, 0x00080008); + nv_wo32(chan, 0x0860, 0x00040000); + nv_wo32(chan, 0x0864, 0x00010000); + for (i = 0x0868; i < 0x0878; i += 4) + nv_wo32(chan, i, 0x00040004); + for (i = 0x1f1c; i <= 0x308c ; i += 16) { + nv_wo32(chan, i + 0, 0x10700ff9); + nv_wo32(chan, i + 4, 0x0436086c); + nv_wo32(chan, i + 8, 0x000c001b); + } + for (i = 0x30bc; i < 0x30cc; i += 4) + nv_wo32(chan, i, 0x0000ffff); + nv_wo32(chan, 0x3450, 0x3f800000); + nv_wo32(chan, 0x380c, 0x3f800000); + nv_wo32(chan, 0x3820, 0x3f800000); + nv_wo32(chan, 0x384c, 0x40000000); + nv_wo32(chan, 0x3850, 0x3f800000); + nv_wo32(chan, 0x3854, 0x3f000000); + nv_wo32(chan, 0x385c, 0x40000000); + nv_wo32(chan, 0x3860, 0x3f800000); + nv_wo32(chan, 0x3868, 0xbf800000); + nv_wo32(chan, 0x3870, 0xbf800000); + return 0; +} + +static struct nouveau_oclass +nv35_graph_cclass = { + .handle = NV_ENGCTX(GR, 0x35), + .ofuncs = &(struct nouveau_ofuncs) { + .ctor = nv35_graph_context_ctor, + .dtor = _nouveau_graph_context_dtor, + .init = nv20_graph_context_init, + .fini = nv20_graph_context_fini, + .rd32 = _nouveau_graph_context_rd32, + .wr32 = _nouveau_graph_context_wr32, + }, +}; + +/******************************************************************************* + * PGRAPH engine/subdev functions + ******************************************************************************/ + +static int +nv35_graph_ctor(struct nouveau_object *parent, struct nouveau_object *engine, + struct nouveau_oclass *oclass, void *data, u32 size, + struct nouveau_object **pobject) +{ + struct nv20_graph_priv *priv; + int ret; + + ret = nouveau_graph_create(parent, engine, oclass, true, &priv); + *pobject = nv_object(priv); + if (ret) + return ret; + + ret = nouveau_gpuobj_new(parent, NULL, 32 * 4, 16, + NVOBJ_FLAG_ZERO_ALLOC, &priv->ctxtab); + if (ret) + return ret; + + nv_subdev(priv)->unit = 0x00001000; + nv_subdev(priv)->intr = nv20_graph_intr; + nv_engine(priv)->cclass = &nv35_graph_cclass; + nv_engine(priv)->sclass = nv35_graph_sclass; + nv_engine(priv)->tile_prog = nv20_graph_tile_prog; + return 0; +} + +struct nouveau_oclass +nv35_graph_oclass = { + .handle = NV_ENGINE(GR, 0x35), + .ofuncs = &(struct nouveau_ofuncs) { + .ctor = nv35_graph_ctor, + .dtor = nv20_graph_dtor, + .init = nv30_graph_init, + .fini = _nouveau_graph_fini, + }, +}; diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/nv40.c b/drivers/gpu/drm/nouveau/core/engine/graph/nv40.c index 466d21514b2c..2f9f2c69d1e3 100644 --- a/drivers/gpu/drm/nouveau/core/engine/graph/nv40.c +++ b/drivers/gpu/drm/nouveau/core/engine/graph/nv40.c @@ -1,151 +1,238 @@ /* - * Copyright (C) 2007 Ben Skeggs. - * All Rights Reserved. + * 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: + * 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 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 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 */ -#include "drmP.h" -#include "drm.h" -#include "nouveau_drv.h" +#include +#include +#include +#include + +#include +#include + +#include #include -#include -struct nv40_graph_engine { - struct nouveau_exec_engine base; - u32 grctx_size; +#include "nv40.h" +#include "regs.h" + +struct nv40_graph_priv { + struct nouveau_graph base; + u32 size; }; +struct nv40_graph_chan { + struct nouveau_graph_chan base; +}; + +/******************************************************************************* + * Graphics object classes + ******************************************************************************/ + static int -nv40_graph_context_new(struct nouveau_channel *chan, int engine) +nv40_graph_object_ctor(struct nouveau_object *parent, + struct nouveau_object *engine, + struct nouveau_oclass *oclass, void *data, u32 size, + struct nouveau_object **pobject) { - struct nv40_graph_engine *pgraph = nv_engine(chan->dev, engine); - struct drm_device *dev = chan->dev; - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_gpuobj *grctx = NULL; - unsigned long flags; + struct nouveau_gpuobj *obj; int ret; - ret = nouveau_gpuobj_new(dev, NULL, pgraph->grctx_size, 16, - NVOBJ_FLAG_ZERO_ALLOC, &grctx); + ret = nouveau_gpuobj_create(parent, engine, oclass, 0, parent, + 20, 16, 0, &obj); + *pobject = nv_object(obj); if (ret) return ret; - /* Initialise default context values */ - nv40_grctx_fill(dev, grctx); - nv_wo32(grctx, 0, grctx->addr); - - /* init grctx pointer in ramfc, and on PFIFO if channel is - * already active there - */ - spin_lock_irqsave(&dev_priv->context_switch_lock, flags); - nv_wo32(chan->ramfc, 0x38, grctx->addr >> 4); - nv_mask(dev, 0x002500, 0x00000001, 0x00000000); - if ((nv_rd32(dev, 0x003204) & 0x0000001f) == chan->id) - nv_wr32(dev, 0x0032e0, grctx->addr >> 4); - nv_mask(dev, 0x002500, 0x00000001, 0x00000001); - spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags); - - chan->engctx[engine] = grctx; + nv_wo32(obj, 0x00, nv_mclass(obj)); + nv_wo32(obj, 0x04, 0x00000000); + nv_wo32(obj, 0x08, 0x00000000); +#ifdef __BIG_ENDIAN + nv_mo32(obj, 0x08, 0x01000000, 0x01000000); +#endif + nv_wo32(obj, 0x0c, 0x00000000); + nv_wo32(obj, 0x10, 0x00000000); return 0; } -static void -nv40_graph_context_del(struct nouveau_channel *chan, int engine) -{ - struct nouveau_gpuobj *grctx = chan->engctx[engine]; - struct drm_device *dev = chan->dev; - struct drm_nouveau_private *dev_priv = dev->dev_private; - u32 inst = 0x01000000 | (grctx->addr >> 4); - unsigned long flags; +struct nouveau_ofuncs +nv40_graph_ofuncs = { + .ctor = nv40_graph_object_ctor, + .dtor = _nouveau_gpuobj_dtor, + .init = _nouveau_gpuobj_init, + .fini = _nouveau_gpuobj_fini, + .rd32 = _nouveau_gpuobj_rd32, + .wr32 = _nouveau_gpuobj_wr32, +}; - spin_lock_irqsave(&dev_priv->context_switch_lock, flags); - nv_mask(dev, 0x400720, 0x00000000, 0x00000001); - if (nv_rd32(dev, 0x40032c) == inst) - nv_mask(dev, 0x40032c, 0x01000000, 0x00000000); - if (nv_rd32(dev, 0x400330) == inst) - nv_mask(dev, 0x400330, 0x01000000, 0x00000000); - nv_mask(dev, 0x400720, 0x00000001, 0x00000001); - spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags); - - /* Free the context resources */ - nouveau_gpuobj_ref(NULL, &grctx); - chan->engctx[engine] = NULL; -} +static struct nouveau_oclass +nv40_graph_sclass[] = { + { 0x0012, &nv40_graph_ofuncs, NULL }, /* beta1 */ + { 0x0019, &nv40_graph_ofuncs, NULL }, /* clip */ + { 0x0030, &nv40_graph_ofuncs, NULL }, /* null */ + { 0x0039, &nv40_graph_ofuncs, NULL }, /* m2mf */ + { 0x0043, &nv40_graph_ofuncs, NULL }, /* rop */ + { 0x0044, &nv40_graph_ofuncs, NULL }, /* patt */ + { 0x004a, &nv40_graph_ofuncs, NULL }, /* gdi */ + { 0x0062, &nv40_graph_ofuncs, NULL }, /* surf2d */ + { 0x0072, &nv40_graph_ofuncs, NULL }, /* beta4 */ + { 0x0089, &nv40_graph_ofuncs, NULL }, /* sifm */ + { 0x008a, &nv40_graph_ofuncs, NULL }, /* ifc */ + { 0x009f, &nv40_graph_ofuncs, NULL }, /* imageblit */ + { 0x3062, &nv40_graph_ofuncs, NULL }, /* surf2d (nv40) */ + { 0x3089, &nv40_graph_ofuncs, NULL }, /* sifm (nv40) */ + { 0x309e, &nv40_graph_ofuncs, NULL }, /* swzsurf (nv40) */ + { 0x4097, &nv40_graph_ofuncs, NULL }, /* curie */ + {}, +}; + +static struct nouveau_oclass +nv44_graph_sclass[] = { + { 0x0012, &nv40_graph_ofuncs, NULL }, /* beta1 */ + { 0x0019, &nv40_graph_ofuncs, NULL }, /* clip */ + { 0x0030, &nv40_graph_ofuncs, NULL }, /* null */ + { 0x0039, &nv40_graph_ofuncs, NULL }, /* m2mf */ + { 0x0043, &nv40_graph_ofuncs, NULL }, /* rop */ + { 0x0044, &nv40_graph_ofuncs, NULL }, /* patt */ + { 0x004a, &nv40_graph_ofuncs, NULL }, /* gdi */ + { 0x0062, &nv40_graph_ofuncs, NULL }, /* surf2d */ + { 0x0072, &nv40_graph_ofuncs, NULL }, /* beta4 */ + { 0x0089, &nv40_graph_ofuncs, NULL }, /* sifm */ + { 0x008a, &nv40_graph_ofuncs, NULL }, /* ifc */ + { 0x009f, &nv40_graph_ofuncs, NULL }, /* imageblit */ + { 0x3062, &nv40_graph_ofuncs, NULL }, /* surf2d (nv40) */ + { 0x3089, &nv40_graph_ofuncs, NULL }, /* sifm (nv40) */ + { 0x309e, &nv40_graph_ofuncs, NULL }, /* swzsurf (nv40) */ + { 0x4497, &nv40_graph_ofuncs, NULL }, /* curie */ + {}, +}; + +/******************************************************************************* + * PGRAPH context + ******************************************************************************/ -int -nv40_graph_object_new(struct nouveau_channel *chan, int engine, - u32 handle, u16 class) +static int +nv40_graph_context_ctor(struct nouveau_object *parent, + struct nouveau_object *engine, + struct nouveau_oclass *oclass, void *data, u32 size, + struct nouveau_object **pobject) { - struct drm_device *dev = chan->dev; - struct nouveau_gpuobj *obj = NULL; + struct nv40_graph_priv *priv = (void *)engine; + struct nv40_graph_chan *chan; int ret; - ret = nouveau_gpuobj_new(dev, chan, 20, 16, NVOBJ_FLAG_ZERO_FREE, &obj); + ret = nouveau_graph_context_create(parent, engine, oclass, NULL, + priv->size, 16, + NVOBJ_FLAG_ZERO_ALLOC, &chan); + *pobject = nv_object(chan); if (ret) return ret; - obj->engine = 1; - obj->class = class; - nv_wo32(obj, 0x00, class); - nv_wo32(obj, 0x04, 0x00000000); -#ifndef __BIG_ENDIAN - nv_wo32(obj, 0x08, 0x00000000); -#else - nv_wo32(obj, 0x08, 0x01000000); -#endif - nv_wo32(obj, 0x0c, 0x00000000); - nv_wo32(obj, 0x10, 0x00000000); + nv40_grctx_fill(nv_device(priv), nv_gpuobj(chan)); + nv_wo32(chan, 0x00000, nv_gpuobj(chan)->addr >> 4); + return 0; +} + +static int +nv40_graph_context_fini(struct nouveau_object *object, bool suspend) +{ + struct nv04_graph_priv *priv = (void *)object->engine; + struct nv04_graph_chan *chan = (void *)object; + u32 inst = 0x01000000 | nv_gpuobj(chan)->addr >> 4; + int ret = 0; + + nv_mask(priv, 0x400720, 0x00000001, 0x00000000); + + if (nv_rd32(priv, 0x40032c) == inst) { + if (suspend) { + nv_wr32(priv, 0x400720, 0x00000000); + nv_wr32(priv, 0x400784, inst); + nv_mask(priv, 0x400310, 0x00000020, 0x00000020); + nv_mask(priv, 0x400304, 0x00000001, 0x00000001); + if (!nv_wait(priv, 0x400300, 0x00000001, 0x00000000)) { + u32 insn = nv_rd32(priv, 0x400308); + nv_warn(priv, "ctxprog timeout 0x%08x\n", insn); + ret = -EBUSY; + } + } - ret = nouveau_ramht_insert(chan, handle, obj); - nouveau_gpuobj_ref(NULL, &obj); + nv_mask(priv, 0x40032c, 0x01000000, 0x00000000); + } + + if (nv_rd32(priv, 0x400330) == inst) + nv_mask(priv, 0x400330, 0x01000000, 0x00000000); + + nv_mask(priv, 0x400720, 0x00000001, 0x00000001); return ret; } +static struct nouveau_oclass +nv40_graph_cclass = { + .handle = NV_ENGCTX(GR, 0x40), + .ofuncs = &(struct nouveau_ofuncs) { + .ctor = nv40_graph_context_ctor, + .dtor = _nouveau_graph_context_dtor, + .init = _nouveau_graph_context_init, + .fini = nv40_graph_context_fini, + .rd32 = _nouveau_graph_context_rd32, + .wr32 = _nouveau_graph_context_wr32, + }, +}; + +/******************************************************************************* + * PGRAPH engine/subdev functions + ******************************************************************************/ + static void -nv40_graph_set_tile_region(struct drm_device *dev, int i) +nv40_graph_tile_prog(struct nouveau_engine *engine, int i) { - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_fb_tile *tile = nvfb_tile(dev, i); + struct nouveau_fb_tile *tile = &nouveau_fb(engine)->tile.region[i]; + struct nouveau_fifo *pfifo = nouveau_fifo(engine); + struct nv40_graph_priv *priv = (void *)engine; + unsigned long flags; + + pfifo->pause(pfifo, &flags); + nv04_graph_idle(priv); - switch (dev_priv->chipset) { + switch (nv_device(priv)->chipset) { case 0x40: case 0x41: /* guess */ case 0x42: case 0x43: case 0x45: /* guess */ case 0x4e: - nv_wr32(dev, NV20_PGRAPH_TSIZE(i), tile->pitch); - nv_wr32(dev, NV20_PGRAPH_TLIMIT(i), tile->limit); - nv_wr32(dev, NV20_PGRAPH_TILE(i), tile->addr); - nv_wr32(dev, NV40_PGRAPH_TSIZE1(i), tile->pitch); - nv_wr32(dev, NV40_PGRAPH_TLIMIT1(i), tile->limit); - nv_wr32(dev, NV40_PGRAPH_TILE1(i), tile->addr); + nv_wr32(priv, NV20_PGRAPH_TSIZE(i), tile->pitch); + nv_wr32(priv, NV20_PGRAPH_TLIMIT(i), tile->limit); + nv_wr32(priv, NV20_PGRAPH_TILE(i), tile->addr); + nv_wr32(priv, NV40_PGRAPH_TSIZE1(i), tile->pitch); + nv_wr32(priv, NV40_PGRAPH_TLIMIT1(i), tile->limit); + nv_wr32(priv, NV40_PGRAPH_TILE1(i), tile->addr); break; case 0x44: case 0x4a: - nv_wr32(dev, NV20_PGRAPH_TSIZE(i), tile->pitch); - nv_wr32(dev, NV20_PGRAPH_TLIMIT(i), tile->limit); - nv_wr32(dev, NV20_PGRAPH_TILE(i), tile->addr); + nv_wr32(priv, NV20_PGRAPH_TSIZE(i), tile->pitch); + nv_wr32(priv, NV20_PGRAPH_TLIMIT(i), tile->limit); + nv_wr32(priv, NV20_PGRAPH_TILE(i), tile->addr); break; case 0x46: case 0x47: @@ -154,149 +241,213 @@ nv40_graph_set_tile_region(struct drm_device *dev, int i) case 0x4c: case 0x67: default: - nv_wr32(dev, NV47_PGRAPH_TSIZE(i), tile->pitch); - nv_wr32(dev, NV47_PGRAPH_TLIMIT(i), tile->limit); - nv_wr32(dev, NV47_PGRAPH_TILE(i), tile->addr); - nv_wr32(dev, NV40_PGRAPH_TSIZE1(i), tile->pitch); - nv_wr32(dev, NV40_PGRAPH_TLIMIT1(i), tile->limit); - nv_wr32(dev, NV40_PGRAPH_TILE1(i), tile->addr); + nv_wr32(priv, NV47_PGRAPH_TSIZE(i), tile->pitch); + nv_wr32(priv, NV47_PGRAPH_TLIMIT(i), tile->limit); + nv_wr32(priv, NV47_PGRAPH_TILE(i), tile->addr); + nv_wr32(priv, NV40_PGRAPH_TSIZE1(i), tile->pitch); + nv_wr32(priv, NV40_PGRAPH_TLIMIT1(i), tile->limit); + nv_wr32(priv, NV40_PGRAPH_TILE1(i), tile->addr); break; } + + pfifo->start(pfifo, &flags); } -/* - * G70 0x47 - * G71 0x49 - * NV45 0x48 - * G72[M] 0x46 - * G73 0x4b - * C51_G7X 0x4c - * C51 0x4e - */ -int -nv40_graph_init(struct drm_device *dev, int engine) +static void +nv40_graph_intr(struct nouveau_subdev *subdev) +{ + struct nv40_graph_priv *priv = (void *)subdev; + struct nouveau_engine *engine = nv_engine(subdev); + struct nouveau_handle *handle = NULL; + u32 stat = nv_rd32(priv, NV03_PGRAPH_INTR); + u32 nsource = nv_rd32(priv, NV03_PGRAPH_NSOURCE); + u32 nstatus = nv_rd32(priv, NV03_PGRAPH_NSTATUS); + u32 inst = (nv_rd32(priv, 0x40032c) & 0x000fffff) << 4; + u32 addr = nv_rd32(priv, NV04_PGRAPH_TRAPPED_ADDR); + u32 subc = (addr & 0x00070000) >> 16; + u32 mthd = (addr & 0x00001ffc); + u32 data = nv_rd32(priv, NV04_PGRAPH_TRAPPED_DATA); + u32 class = nv_rd32(priv, 0x400160 + subc * 4) & 0xffff; + u32 show = stat; + + if (stat & NV_PGRAPH_INTR_ERROR) { + if (nsource & NV03_PGRAPH_NSOURCE_ILLEGAL_MTHD) { + handle = nouveau_engctx_lookup_class(engine, inst, class); + if (handle && !nv_call(handle->object, mthd, data)) + show &= ~NV_PGRAPH_INTR_ERROR; + nouveau_engctx_handle_put(handle); + } + + if (nsource & NV03_PGRAPH_NSOURCE_DMA_VTX_PROTECTION) { + nv_mask(priv, 0x402000, 0, 0); + } + } + + nv_wr32(priv, NV03_PGRAPH_INTR, stat); + nv_wr32(priv, NV04_PGRAPH_FIFO, 0x00000001); + + if (show) { + nv_info(priv, ""); + nouveau_bitfield_print(nv10_graph_intr_name, show); + printk(" nsource:"); + nouveau_bitfield_print(nv04_graph_nsource, nsource); + printk(" nstatus:"); + nouveau_bitfield_print(nv10_graph_nstatus, nstatus); + printk("\n"); + nv_error(priv, "ch 0x%08x subc %d class 0x%04x " + "mthd 0x%04x data 0x%08x\n", + inst, subc, class, mthd, data); + } +} + +static int +nv40_graph_ctor(struct nouveau_object *parent, struct nouveau_object *engine, + struct nouveau_oclass *oclass, void *data, u32 size, + struct nouveau_object **pobject) { - struct nv40_graph_engine *pgraph = nv_engine(dev, engine); - struct drm_nouveau_private *dev_priv = dev->dev_private; - uint32_t vramsz; - int i, j; + struct nv40_graph_priv *priv; + int ret; + + ret = nouveau_graph_create(parent, engine, oclass, true, &priv); + *pobject = nv_object(priv); + if (ret) + return ret; - nv_wr32(dev, NV03_PMC_ENABLE, nv_rd32(dev, NV03_PMC_ENABLE) & - ~NV_PMC_ENABLE_PGRAPH); - nv_wr32(dev, NV03_PMC_ENABLE, nv_rd32(dev, NV03_PMC_ENABLE) | - NV_PMC_ENABLE_PGRAPH); + nv_subdev(priv)->unit = 0x00001000; + nv_subdev(priv)->intr = nv40_graph_intr; + nv_engine(priv)->cclass = &nv40_graph_cclass; + if (nv44_graph_class(priv)) + nv_engine(priv)->sclass = nv44_graph_sclass; + else + nv_engine(priv)->sclass = nv40_graph_sclass; + nv_engine(priv)->tile_prog = nv40_graph_tile_prog; + return 0; +} + +static int +nv40_graph_init(struct nouveau_object *object) +{ + struct nouveau_engine *engine = nv_engine(object); + struct nouveau_fb *pfb = nouveau_fb(object); + struct nv40_graph_priv *priv = (void *)engine; + int ret, i, j; + u32 vramsz; + + ret = nouveau_graph_init(&priv->base); + if (ret) + return ret; /* generate and upload context program */ - nv40_grctx_init(dev, &pgraph->grctx_size); + nv40_grctx_init(nv_device(priv), &priv->size); /* No context present currently */ - nv_wr32(dev, NV40_PGRAPH_CTXCTL_CUR, 0x00000000); + nv_wr32(priv, NV40_PGRAPH_CTXCTL_CUR, 0x00000000); - nv_wr32(dev, NV03_PGRAPH_INTR , 0xFFFFFFFF); - nv_wr32(dev, NV40_PGRAPH_INTR_EN, 0xFFFFFFFF); + nv_wr32(priv, NV03_PGRAPH_INTR , 0xFFFFFFFF); + nv_wr32(priv, NV40_PGRAPH_INTR_EN, 0xFFFFFFFF); - nv_wr32(dev, NV04_PGRAPH_DEBUG_0, 0xFFFFFFFF); - nv_wr32(dev, NV04_PGRAPH_DEBUG_0, 0x00000000); - nv_wr32(dev, NV04_PGRAPH_DEBUG_1, 0x401287c0); - nv_wr32(dev, NV04_PGRAPH_DEBUG_3, 0xe0de8055); - nv_wr32(dev, NV10_PGRAPH_DEBUG_4, 0x00008000); - nv_wr32(dev, NV04_PGRAPH_LIMIT_VIOL_PIX, 0x00be3c5f); + nv_wr32(priv, NV04_PGRAPH_DEBUG_0, 0xFFFFFFFF); + nv_wr32(priv, NV04_PGRAPH_DEBUG_0, 0x00000000); + nv_wr32(priv, NV04_PGRAPH_DEBUG_1, 0x401287c0); + nv_wr32(priv, NV04_PGRAPH_DEBUG_3, 0xe0de8055); + nv_wr32(priv, NV10_PGRAPH_DEBUG_4, 0x00008000); + nv_wr32(priv, NV04_PGRAPH_LIMIT_VIOL_PIX, 0x00be3c5f); - nv_wr32(dev, NV10_PGRAPH_CTX_CONTROL, 0x10010100); - nv_wr32(dev, NV10_PGRAPH_STATE , 0xFFFFFFFF); + nv_wr32(priv, NV10_PGRAPH_CTX_CONTROL, 0x10010100); + nv_wr32(priv, NV10_PGRAPH_STATE , 0xFFFFFFFF); - j = nv_rd32(dev, 0x1540) & 0xff; + j = nv_rd32(priv, 0x1540) & 0xff; if (j) { for (i = 0; !(j & 1); j >>= 1, i++) ; - nv_wr32(dev, 0x405000, i); + nv_wr32(priv, 0x405000, i); } - if (dev_priv->chipset == 0x40) { - nv_wr32(dev, 0x4009b0, 0x83280fff); - nv_wr32(dev, 0x4009b4, 0x000000a0); + if (nv_device(priv)->chipset == 0x40) { + nv_wr32(priv, 0x4009b0, 0x83280fff); + nv_wr32(priv, 0x4009b4, 0x000000a0); } else { - nv_wr32(dev, 0x400820, 0x83280eff); - nv_wr32(dev, 0x400824, 0x000000a0); + nv_wr32(priv, 0x400820, 0x83280eff); + nv_wr32(priv, 0x400824, 0x000000a0); } - switch (dev_priv->chipset) { + switch (nv_device(priv)->chipset) { case 0x40: case 0x45: - nv_wr32(dev, 0x4009b8, 0x0078e366); - nv_wr32(dev, 0x4009bc, 0x0000014c); + nv_wr32(priv, 0x4009b8, 0x0078e366); + nv_wr32(priv, 0x4009bc, 0x0000014c); break; case 0x41: case 0x42: /* pciid also 0x00Cx */ /* case 0x0120: XXX (pciid) */ - nv_wr32(dev, 0x400828, 0x007596ff); - nv_wr32(dev, 0x40082c, 0x00000108); + nv_wr32(priv, 0x400828, 0x007596ff); + nv_wr32(priv, 0x40082c, 0x00000108); break; case 0x43: - nv_wr32(dev, 0x400828, 0x0072cb77); - nv_wr32(dev, 0x40082c, 0x00000108); + nv_wr32(priv, 0x400828, 0x0072cb77); + nv_wr32(priv, 0x40082c, 0x00000108); break; case 0x44: case 0x46: /* G72 */ case 0x4a: case 0x4c: /* G7x-based C51 */ case 0x4e: - nv_wr32(dev, 0x400860, 0); - nv_wr32(dev, 0x400864, 0); + nv_wr32(priv, 0x400860, 0); + nv_wr32(priv, 0x400864, 0); break; case 0x47: /* G70 */ case 0x49: /* G71 */ case 0x4b: /* G73 */ - nv_wr32(dev, 0x400828, 0x07830610); - nv_wr32(dev, 0x40082c, 0x0000016A); + nv_wr32(priv, 0x400828, 0x07830610); + nv_wr32(priv, 0x40082c, 0x0000016A); break; default: break; } - nv_wr32(dev, 0x400b38, 0x2ffff800); - nv_wr32(dev, 0x400b3c, 0x00006000); + nv_wr32(priv, 0x400b38, 0x2ffff800); + nv_wr32(priv, 0x400b3c, 0x00006000); /* Tiling related stuff. */ - switch (dev_priv->chipset) { + switch (nv_device(priv)->chipset) { case 0x44: case 0x4a: - nv_wr32(dev, 0x400bc4, 0x1003d888); - nv_wr32(dev, 0x400bbc, 0xb7a7b500); + nv_wr32(priv, 0x400bc4, 0x1003d888); + nv_wr32(priv, 0x400bbc, 0xb7a7b500); break; case 0x46: - nv_wr32(dev, 0x400bc4, 0x0000e024); - nv_wr32(dev, 0x400bbc, 0xb7a7b520); + nv_wr32(priv, 0x400bc4, 0x0000e024); + nv_wr32(priv, 0x400bbc, 0xb7a7b520); break; case 0x4c: case 0x4e: case 0x67: - nv_wr32(dev, 0x400bc4, 0x1003d888); - nv_wr32(dev, 0x400bbc, 0xb7a7b540); + nv_wr32(priv, 0x400bc4, 0x1003d888); + nv_wr32(priv, 0x400bbc, 0xb7a7b540); break; default: break; } /* Turn all the tiling regions off. */ - for (i = 0; i < nvfb_tile_nr(dev); i++) - nv40_graph_set_tile_region(dev, i); + for (i = 0; i < pfb->tile.regions; i++) + engine->tile_prog(engine, i); /* begin RAM config */ - vramsz = pci_resource_len(dev->pdev, 0) - 1; - switch (dev_priv->chipset) { + vramsz = pci_resource_len(nv_device(priv)->pdev, 0) - 1; + switch (nv_device(priv)->chipset) { case 0x40: - nv_wr32(dev, 0x4009A4, nv_rd32(dev, NV04_PFB_CFG0)); - nv_wr32(dev, 0x4009A8, nv_rd32(dev, NV04_PFB_CFG1)); - nv_wr32(dev, 0x4069A4, nv_rd32(dev, NV04_PFB_CFG0)); - nv_wr32(dev, 0x4069A8, nv_rd32(dev, NV04_PFB_CFG1)); - nv_wr32(dev, 0x400820, 0); - nv_wr32(dev, 0x400824, 0); - nv_wr32(dev, 0x400864, vramsz); - nv_wr32(dev, 0x400868, vramsz); + nv_wr32(priv, 0x4009A4, nv_rd32(priv, 0x100200)); + nv_wr32(priv, 0x4009A8, nv_rd32(priv, 0x100204)); + nv_wr32(priv, 0x4069A4, nv_rd32(priv, 0x100200)); + nv_wr32(priv, 0x4069A8, nv_rd32(priv, 0x100204)); + nv_wr32(priv, 0x400820, 0); + nv_wr32(priv, 0x400824, 0); + nv_wr32(priv, 0x400864, vramsz); + nv_wr32(priv, 0x400868, vramsz); break; default: - switch (dev_priv->chipset) { + switch (nv_device(priv)->chipset) { case 0x41: case 0x42: case 0x43: @@ -304,163 +455,33 @@ nv40_graph_init(struct drm_device *dev, int engine) case 0x4e: case 0x44: case 0x4a: - nv_wr32(dev, 0x4009F0, nv_rd32(dev, NV04_PFB_CFG0)); - nv_wr32(dev, 0x4009F4, nv_rd32(dev, NV04_PFB_CFG1)); + nv_wr32(priv, 0x4009F0, nv_rd32(priv, 0x100200)); + nv_wr32(priv, 0x4009F4, nv_rd32(priv, 0x100204)); break; default: - nv_wr32(dev, 0x400DF0, nv_rd32(dev, NV04_PFB_CFG0)); - nv_wr32(dev, 0x400DF4, nv_rd32(dev, NV04_PFB_CFG1)); + nv_wr32(priv, 0x400DF0, nv_rd32(priv, 0x100200)); + nv_wr32(priv, 0x400DF4, nv_rd32(priv, 0x100204)); break; } - nv_wr32(dev, 0x4069F0, nv_rd32(dev, NV04_PFB_CFG0)); - nv_wr32(dev, 0x4069F4, nv_rd32(dev, NV04_PFB_CFG1)); - nv_wr32(dev, 0x400840, 0); - nv_wr32(dev, 0x400844, 0); - nv_wr32(dev, 0x4008A0, vramsz); - nv_wr32(dev, 0x4008A4, vramsz); + nv_wr32(priv, 0x4069F0, nv_rd32(priv, 0x100200)); + nv_wr32(priv, 0x4069F4, nv_rd32(priv, 0x100204)); + nv_wr32(priv, 0x400840, 0); + nv_wr32(priv, 0x400844, 0); + nv_wr32(priv, 0x4008A0, vramsz); + nv_wr32(priv, 0x4008A4, vramsz); break; } return 0; } -static int -nv40_graph_fini(struct drm_device *dev, int engine, bool suspend) -{ - u32 inst = nv_rd32(dev, 0x40032c); - if (inst & 0x01000000) { - nv_wr32(dev, 0x400720, 0x00000000); - nv_wr32(dev, 0x400784, inst); - nv_mask(dev, 0x400310, 0x00000020, 0x00000020); - nv_mask(dev, 0x400304, 0x00000001, 0x00000001); - if (!nv_wait(dev, 0x400300, 0x00000001, 0x00000000)) { - u32 insn = nv_rd32(dev, 0x400308); - NV_ERROR(dev, "PGRAPH: ctxprog timeout 0x%08x\n", insn); - } - nv_mask(dev, 0x40032c, 0x01000000, 0x00000000); - } - return 0; -} - -static int -nv40_graph_isr_chid(struct drm_device *dev, u32 inst) -{ - struct nouveau_fifo_priv *pfifo = nv_engine(dev, NVOBJ_ENGINE_FIFO); - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_gpuobj *grctx; - unsigned long flags; - int i; - - spin_lock_irqsave(&dev_priv->channels.lock, flags); - for (i = 0; i < pfifo->channels; i++) { - if (!dev_priv->channels.ptr[i]) - continue; - grctx = dev_priv->channels.ptr[i]->engctx[NVOBJ_ENGINE_GR]; - - if (grctx && grctx->addr == inst) - break; - } - spin_unlock_irqrestore(&dev_priv->channels.lock, flags); - return i; -} - -static void -nv40_graph_isr(struct drm_device *dev) -{ - u32 stat; - - while ((stat = nv_rd32(dev, NV03_PGRAPH_INTR))) { - u32 nsource = nv_rd32(dev, NV03_PGRAPH_NSOURCE); - u32 nstatus = nv_rd32(dev, NV03_PGRAPH_NSTATUS); - u32 inst = (nv_rd32(dev, 0x40032c) & 0x000fffff) << 4; - u32 chid = nv40_graph_isr_chid(dev, inst); - u32 addr = nv_rd32(dev, NV04_PGRAPH_TRAPPED_ADDR); - u32 subc = (addr & 0x00070000) >> 16; - u32 mthd = (addr & 0x00001ffc); - u32 data = nv_rd32(dev, NV04_PGRAPH_TRAPPED_DATA); - u32 class = nv_rd32(dev, 0x400160 + subc * 4) & 0xffff; - u32 show = stat; - - if (stat & NV_PGRAPH_INTR_ERROR) { - if (nsource & NV03_PGRAPH_NSOURCE_ILLEGAL_MTHD) { - if (!nouveau_gpuobj_mthd_call2(dev, chid, class, mthd, data)) - show &= ~NV_PGRAPH_INTR_ERROR; - } else - if (nsource & NV03_PGRAPH_NSOURCE_DMA_VTX_PROTECTION) { - nv_mask(dev, 0x402000, 0, 0); - } - } - - nv_wr32(dev, NV03_PGRAPH_INTR, stat); - nv_wr32(dev, NV04_PGRAPH_FIFO, 0x00000001); - - if (show && nouveau_ratelimit()) { - NV_INFO(dev, "PGRAPH -"); - nouveau_bitfield_print(nv10_graph_intr, show); - printk(" nsource:"); - nouveau_bitfield_print(nv04_graph_nsource, nsource); - printk(" nstatus:"); - nouveau_bitfield_print(nv10_graph_nstatus, nstatus); - printk("\n"); - NV_INFO(dev, "PGRAPH - ch %d (0x%08x) subc %d " - "class 0x%04x mthd 0x%04x data 0x%08x\n", - chid, inst, subc, class, mthd, data); - } - } -} - -static void -nv40_graph_destroy(struct drm_device *dev, int engine) -{ - struct nv40_graph_engine *pgraph = nv_engine(dev, engine); - - nouveau_irq_unregister(dev, 12); - - NVOBJ_ENGINE_DEL(dev, GR); - kfree(pgraph); -} - -int -nv40_graph_create(struct drm_device *dev) -{ - struct nv40_graph_engine *pgraph; - - pgraph = kzalloc(sizeof(*pgraph), GFP_KERNEL); - if (!pgraph) - return -ENOMEM; - - pgraph->base.destroy = nv40_graph_destroy; - pgraph->base.init = nv40_graph_init; - pgraph->base.fini = nv40_graph_fini; - pgraph->base.context_new = nv40_graph_context_new; - pgraph->base.context_del = nv40_graph_context_del; - pgraph->base.object_new = nv40_graph_object_new; - pgraph->base.set_tile_region = nv40_graph_set_tile_region; - - NVOBJ_ENGINE_ADD(dev, GR, &pgraph->base); - nouveau_irq_register(dev, 12, nv40_graph_isr); - - NVOBJ_CLASS(dev, 0x0030, GR); /* null */ - NVOBJ_CLASS(dev, 0x0039, GR); /* m2mf */ - NVOBJ_CLASS(dev, 0x004a, GR); /* gdirect */ - NVOBJ_CLASS(dev, 0x009f, GR); /* imageblit (nv12) */ - NVOBJ_CLASS(dev, 0x008a, GR); /* ifc */ - NVOBJ_CLASS(dev, 0x0089, GR); /* sifm */ - NVOBJ_CLASS(dev, 0x3089, GR); /* sifm (nv40) */ - NVOBJ_CLASS(dev, 0x0062, GR); /* surf2d */ - NVOBJ_CLASS(dev, 0x3062, GR); /* surf2d (nv40) */ - NVOBJ_CLASS(dev, 0x0043, GR); /* rop */ - NVOBJ_CLASS(dev, 0x0012, GR); /* beta1 */ - NVOBJ_CLASS(dev, 0x0072, GR); /* beta4 */ - NVOBJ_CLASS(dev, 0x0019, GR); /* cliprect */ - NVOBJ_CLASS(dev, 0x0044, GR); /* pattern */ - NVOBJ_CLASS(dev, 0x309e, GR); /* swzsurf */ - - /* curie */ - if (nv44_graph_class(dev)) - NVOBJ_CLASS(dev, 0x4497, GR); - else - NVOBJ_CLASS(dev, 0x4097, GR); - - return 0; -} +struct nouveau_oclass +nv40_graph_oclass = { + .handle = NV_ENGINE(GR, 0x40), + .ofuncs = &(struct nouveau_ofuncs) { + .ctor = nv40_graph_ctor, + .dtor = _nouveau_graph_dtor, + .init = nv40_graph_init, + .fini = _nouveau_graph_fini, + }, +}; diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/nv40.h b/drivers/gpu/drm/nouveau/core/engine/graph/nv40.h new file mode 100644 index 000000000000..d2ac975afc2e --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/engine/graph/nv40.h @@ -0,0 +1,21 @@ +#ifndef __NV40_GRAPH_H__ +#define __NV40_GRAPH_H__ + +/* returns 1 if device is one of the nv4x using the 0x4497 object class, + * helpful to determine a number of other hardware features + */ +static inline int +nv44_graph_class(void *priv) +{ + struct nouveau_device *device = nv_device(priv); + + if ((device->chipset & 0xf0) == 0x60) + return 1; + + return !(0x0baf & (1 << (device->chipset & 0x0f))); +} + +void nv40_grctx_init(struct nouveau_device *, u32 *size); +void nv40_grctx_fill(struct nouveau_device *, struct nouveau_gpuobj *); + +#endif diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/nv50.c b/drivers/gpu/drm/nouveau/core/engine/graph/nv50.c index 28932c4662e9..8955bdd3551c 100644 --- a/drivers/gpu/drm/nouveau/core/engine/graph/nv50.c +++ b/drivers/gpu/drm/nouveau/core/engine/graph/nv50.c @@ -1,266 +1,234 @@ /* - * Copyright (C) 2007 Ben Skeggs. - * All Rights Reserved. + * 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: + * 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 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 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 */ -#include "drmP.h" -#include "drm.h" -#include "nouveau_drv.h" -#include -#include -#include "nouveau_dma.h" -#include "nv50_evo.h" - -struct nv50_graph_engine { - struct nouveau_exec_engine base; - u32 ctxprog[512]; - u32 ctxprog_size; - u32 grctx_size; -}; - -static int -nv50_graph_init(struct drm_device *dev, int engine) -{ - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nv50_graph_engine *pgraph = nv_engine(dev, engine); - u32 units = nv_rd32(dev, 0x001540); - int i; +#include +#include +#include +#include +#include - NV_DEBUG(dev, "\n"); +#include +#include +#include - /* master reset */ - nv_mask(dev, 0x000200, 0x00201000, 0x00000000); - nv_mask(dev, 0x000200, 0x00201000, 0x00201000); - nv_wr32(dev, 0x40008c, 0x00000004); /* HW_CTX_SWITCH_ENABLED */ - - /* reset/enable traps and interrupts */ - nv_wr32(dev, 0x400804, 0xc0000000); - nv_wr32(dev, 0x406800, 0xc0000000); - nv_wr32(dev, 0x400c04, 0xc0000000); - nv_wr32(dev, 0x401800, 0xc0000000); - nv_wr32(dev, 0x405018, 0xc0000000); - nv_wr32(dev, 0x402000, 0xc0000000); - for (i = 0; i < 16; i++) { - if (!(units & (1 << i))) - continue; +#include - if (dev_priv->chipset < 0xa0) { - nv_wr32(dev, 0x408900 + (i << 12), 0xc0000000); - nv_wr32(dev, 0x408e08 + (i << 12), 0xc0000000); - nv_wr32(dev, 0x408314 + (i << 12), 0xc0000000); - } else { - nv_wr32(dev, 0x408600 + (i << 11), 0xc0000000); - nv_wr32(dev, 0x408708 + (i << 11), 0xc0000000); - nv_wr32(dev, 0x40831c + (i << 11), 0xc0000000); - } - } +#include "nv50.h" - nv_wr32(dev, 0x400108, 0xffffffff); - nv_wr32(dev, 0x400138, 0xffffffff); - nv_wr32(dev, 0x400100, 0xffffffff); - nv_wr32(dev, 0x40013c, 0xffffffff); - nv_wr32(dev, 0x400500, 0x00010001); +struct nv50_graph_priv { + struct nouveau_graph base; + spinlock_t lock; + u32 size; +}; - /* upload context program, initialise ctxctl defaults */ - nv_wr32(dev, 0x400324, 0x00000000); - for (i = 0; i < pgraph->ctxprog_size; i++) - nv_wr32(dev, 0x400328, pgraph->ctxprog[i]); - nv_wr32(dev, 0x400824, 0x00000000); - nv_wr32(dev, 0x400828, 0x00000000); - nv_wr32(dev, 0x40082c, 0x00000000); - nv_wr32(dev, 0x400830, 0x00000000); - nv_wr32(dev, 0x400724, 0x00000000); - nv_wr32(dev, 0x40032c, 0x00000000); - nv_wr32(dev, 0x400320, 4); /* CTXCTL_CMD = NEWCTXDMA */ +struct nv50_graph_chan { + struct nouveau_graph_chan base; +}; - /* some unknown zcull magic */ - switch (dev_priv->chipset & 0xf0) { - case 0x50: - case 0x80: - case 0x90: - nv_wr32(dev, 0x402ca8, 0x00000800); - break; - case 0xa0: - default: - nv_wr32(dev, 0x402cc0, 0x00000000); - if (dev_priv->chipset == 0xa0 || - dev_priv->chipset == 0xaa || - dev_priv->chipset == 0xac) { - nv_wr32(dev, 0x402ca8, 0x00000802); - } else { - nv_wr32(dev, 0x402cc0, 0x00000000); - nv_wr32(dev, 0x402ca8, 0x00000002); - } +/******************************************************************************* + * Graphics object classes + ******************************************************************************/ - break; - } +static int +nv50_graph_object_ctor(struct nouveau_object *parent, + struct nouveau_object *engine, + struct nouveau_oclass *oclass, void *data, u32 size, + struct nouveau_object **pobject) +{ + struct nouveau_gpuobj *obj; + int ret; - /* zero out zcull regions */ - for (i = 0; i < 8; i++) { - nv_wr32(dev, 0x402c20 + (i * 8), 0x00000000); - nv_wr32(dev, 0x402c24 + (i * 8), 0x00000000); - nv_wr32(dev, 0x402c28 + (i * 8), 0x00000000); - nv_wr32(dev, 0x402c2c + (i * 8), 0x00000000); - } + ret = nouveau_gpuobj_create(parent, engine, oclass, 0, parent, + 16, 16, 0, &obj); + *pobject = nv_object(obj); + if (ret) + return ret; + nv_wo32(obj, 0x00, nv_mclass(obj)); + nv_wo32(obj, 0x04, 0x00000000); + nv_wo32(obj, 0x08, 0x00000000); + nv_wo32(obj, 0x0c, 0x00000000); return 0; } -static int -nv50_graph_fini(struct drm_device *dev, int engine, bool suspend) -{ - nv_wr32(dev, 0x40013c, 0x00000000); - return 0; -} +struct nouveau_ofuncs +nv50_graph_ofuncs = { + .ctor = nv50_graph_object_ctor, + .dtor = _nouveau_gpuobj_dtor, + .init = _nouveau_gpuobj_init, + .fini = _nouveau_gpuobj_fini, + .rd32 = _nouveau_gpuobj_rd32, + .wr32 = _nouveau_gpuobj_wr32, +}; -static int -nv50_graph_context_new(struct nouveau_channel *chan, int engine) -{ - struct drm_device *dev = chan->dev; - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_gpuobj *ramin = chan->ramin; - struct nouveau_gpuobj *grctx = NULL; - struct nv50_graph_engine *pgraph = nv_engine(dev, engine); - int hdr, ret; - - NV_DEBUG(dev, "ch%d\n", chan->id); - - ret = nouveau_gpuobj_new(dev, NULL, pgraph->grctx_size, 0, - NVOBJ_FLAG_ZERO_ALLOC | - NVOBJ_FLAG_ZERO_FREE, &grctx); - if (ret) - return ret; +static struct nouveau_oclass +nv50_graph_sclass[] = { + { 0x0030, &nv50_graph_ofuncs }, + { 0x502d, &nv50_graph_ofuncs }, + { 0x5039, &nv50_graph_ofuncs }, + { 0x5097, &nv50_graph_ofuncs }, + { 0x50c0, &nv50_graph_ofuncs }, + {} +}; - hdr = (dev_priv->chipset == 0x50) ? 0x200 : 0x20; - nv_wo32(ramin, hdr + 0x00, 0x00190002); - nv_wo32(ramin, hdr + 0x04, grctx->addr + grctx->size - 1); - nv_wo32(ramin, hdr + 0x08, grctx->addr); - nv_wo32(ramin, hdr + 0x0c, 0); - nv_wo32(ramin, hdr + 0x10, 0); - nv_wo32(ramin, hdr + 0x14, 0x00010000); +static struct nouveau_oclass +nv84_graph_sclass[] = { + { 0x0030, &nv50_graph_ofuncs }, + { 0x502d, &nv50_graph_ofuncs }, + { 0x5039, &nv50_graph_ofuncs }, + { 0x50c0, &nv50_graph_ofuncs }, + { 0x8297, &nv50_graph_ofuncs }, + {} +}; - nv50_grctx_fill(dev, grctx); - nv_wo32(grctx, 0x00000, chan->ramin->addr >> 12); +static struct nouveau_oclass +nva0_graph_sclass[] = { + { 0x0030, &nv50_graph_ofuncs }, + { 0x502d, &nv50_graph_ofuncs }, + { 0x5039, &nv50_graph_ofuncs }, + { 0x50c0, &nv50_graph_ofuncs }, + { 0x8397, &nv50_graph_ofuncs }, + {} +}; - nvimem_flush(dev); +static struct nouveau_oclass +nva3_graph_sclass[] = { + { 0x0030, &nv50_graph_ofuncs }, + { 0x502d, &nv50_graph_ofuncs }, + { 0x5039, &nv50_graph_ofuncs }, + { 0x50c0, &nv50_graph_ofuncs }, + { 0x8597, &nv50_graph_ofuncs }, + { 0x85c0, &nv50_graph_ofuncs }, + {} +}; - nvvm_engref(chan->vm, engine, 1); - chan->engctx[NVOBJ_ENGINE_GR] = grctx; - return 0; -} +static struct nouveau_oclass +nvaf_graph_sclass[] = { + { 0x0030, &nv50_graph_ofuncs }, + { 0x502d, &nv50_graph_ofuncs }, + { 0x5039, &nv50_graph_ofuncs }, + { 0x50c0, &nv50_graph_ofuncs }, + { 0x85c0, &nv50_graph_ofuncs }, + { 0x8697, &nv50_graph_ofuncs }, + {} +}; -static void -nv50_graph_context_del(struct nouveau_channel *chan, int engine) -{ - struct nouveau_gpuobj *grctx = chan->engctx[engine]; - struct drm_device *dev = chan->dev; - struct drm_nouveau_private *dev_priv = dev->dev_private; - int i, hdr = (dev_priv->chipset == 0x50) ? 0x200 : 0x20; - - for (i = hdr; i < hdr + 24; i += 4) - nv_wo32(chan->ramin, i, 0); - nvimem_flush(dev); - - nvvm_engref(chan->vm, engine, -1); - nouveau_gpuobj_ref(NULL, &grctx); - chan->engctx[engine] = NULL; -} +/******************************************************************************* + * PGRAPH context + ******************************************************************************/ static int -nv50_graph_object_new(struct nouveau_channel *chan, int engine, - u32 handle, u16 class) +nv50_graph_context_ctor(struct nouveau_object *parent, + struct nouveau_object *engine, + struct nouveau_oclass *oclass, void *data, u32 size, + struct nouveau_object **pobject) { - struct drm_device *dev = chan->dev; - struct nouveau_gpuobj *obj = NULL; + struct nv50_graph_priv *priv = (void *)engine; + struct nv50_graph_chan *chan; int ret; - ret = nouveau_gpuobj_new(dev, chan, 16, 16, NVOBJ_FLAG_ZERO_FREE, &obj); + ret = nouveau_graph_context_create(parent, engine, oclass, NULL, + priv->size, 0, + NVOBJ_FLAG_ZERO_ALLOC, &chan); + *pobject = nv_object(chan); if (ret) return ret; - obj->engine = 1; - obj->class = class; - - nv_wo32(obj, 0x00, class); - nv_wo32(obj, 0x04, 0x00000000); - nv_wo32(obj, 0x08, 0x00000000); - nv_wo32(obj, 0x0c, 0x00000000); - nvimem_flush(dev); - ret = nouveau_ramht_insert(chan, handle, obj); - nouveau_gpuobj_ref(NULL, &obj); - return ret; + nv50_grctx_fill(nv_device(priv), nv_gpuobj(chan)); + return 0; } -static void -nv50_graph_tlb_flush(struct drm_device *dev, int engine) +static struct nouveau_oclass +nv50_graph_cclass = { + .handle = NV_ENGCTX(GR, 0x50), + .ofuncs = &(struct nouveau_ofuncs) { + .ctor = nv50_graph_context_ctor, + .dtor = _nouveau_graph_context_dtor, + .init = _nouveau_graph_context_init, + .fini = _nouveau_graph_context_fini, + .rd32 = _nouveau_graph_context_rd32, + .wr32 = _nouveau_graph_context_wr32, + }, +}; + +/******************************************************************************* + * PGRAPH engine/subdev functions + ******************************************************************************/ + +static int +nv50_graph_tlb_flush(struct nouveau_engine *engine) { - nv50_vm_flush_engine(dev, 0); + nv50_vm_flush_engine(&engine->base, 0x00); + return 0; } -static void -nv84_graph_tlb_flush(struct drm_device *dev, int engine) +static int +nv84_graph_tlb_flush(struct nouveau_engine *engine) { - struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_timer *ptimer = nouveau_timer(engine); + struct nv50_graph_priv *priv = (void *)engine; bool idle, timeout = false; unsigned long flags; u64 start; u32 tmp; - spin_lock_irqsave(&dev_priv->context_switch_lock, flags); - nv_mask(dev, 0x400500, 0x00000001, 0x00000000); + spin_lock_irqsave(&priv->lock, flags); + nv_mask(priv, 0x400500, 0x00000001, 0x00000000); - start = nv_timer_read(dev); + start = ptimer->read(ptimer); do { idle = true; - for (tmp = nv_rd32(dev, 0x400380); tmp && idle; tmp >>= 3) { + for (tmp = nv_rd32(priv, 0x400380); tmp && idle; tmp >>= 3) { if ((tmp & 7) == 1) idle = false; } - for (tmp = nv_rd32(dev, 0x400384); tmp && idle; tmp >>= 3) { + for (tmp = nv_rd32(priv, 0x400384); tmp && idle; tmp >>= 3) { if ((tmp & 7) == 1) idle = false; } - for (tmp = nv_rd32(dev, 0x400388); tmp && idle; tmp >>= 3) { + for (tmp = nv_rd32(priv, 0x400388); tmp && idle; tmp >>= 3) { if ((tmp & 7) == 1) idle = false; } - } while (!idle && !(timeout = nv_timer_read(dev) - start > 2000000000)); + } while (!idle && + !(timeout = ptimer->read(ptimer) - start > 2000000000)); if (timeout) { - NV_ERROR(dev, "PGRAPH TLB flush idle timeout fail: " + nv_error(priv, "PGRAPH TLB flush idle timeout fail: " "0x%08x 0x%08x 0x%08x 0x%08x\n", - nv_rd32(dev, 0x400700), nv_rd32(dev, 0x400380), - nv_rd32(dev, 0x400384), nv_rd32(dev, 0x400388)); + nv_rd32(priv, 0x400700), nv_rd32(priv, 0x400380), + nv_rd32(priv, 0x400384), nv_rd32(priv, 0x400388)); } - nv50_vm_flush_engine(dev, 0); + nv50_vm_flush_engine(&engine->base, 0x00); - nv_mask(dev, 0x400500, 0x00000001, 0x00000001); - spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags); + nv_mask(priv, 0x400500, 0x00000001, 0x00000001); + spin_unlock_irqrestore(&priv->lock, flags); + return timeout ? -EBUSY : 0; } static struct nouveau_enum nv50_mp_exec_error_names[] = { @@ -341,7 +309,7 @@ struct nouveau_enum nv50_data_error_names[] = { {} }; -static struct nouveau_bitfield nv50_graph_intr[] = { +static struct nouveau_bitfield nv50_graph_intr_name[] = { { 0x00000001, "NOTIFY" }, { 0x00000002, "COMPUTE_QUERY" }, { 0x00000010, "ILLEGAL_MTHD" }, @@ -356,95 +324,93 @@ static struct nouveau_bitfield nv50_graph_intr[] = { }; static void -nv50_pgraph_mp_trap(struct drm_device *dev, int tpid, int display) +nv50_priv_mp_trap(struct nv50_graph_priv *priv, int tpid, int display) { - struct drm_nouveau_private *dev_priv = dev->dev_private; - uint32_t units = nv_rd32(dev, 0x1540); - uint32_t addr, mp10, status, pc, oplow, ophigh; + u32 units = nv_rd32(priv, 0x1540); + u32 addr, mp10, status, pc, oplow, ophigh; int i; int mps = 0; for (i = 0; i < 4; i++) { if (!(units & 1 << (i+24))) continue; - if (dev_priv->chipset < 0xa0) + if (nv_device(priv)->chipset < 0xa0) addr = 0x408200 + (tpid << 12) + (i << 7); else addr = 0x408100 + (tpid << 11) + (i << 7); - mp10 = nv_rd32(dev, addr + 0x10); - status = nv_rd32(dev, addr + 0x14); + mp10 = nv_rd32(priv, addr + 0x10); + status = nv_rd32(priv, addr + 0x14); if (!status) continue; if (display) { - nv_rd32(dev, addr + 0x20); - pc = nv_rd32(dev, addr + 0x24); - oplow = nv_rd32(dev, addr + 0x70); - ophigh = nv_rd32(dev, addr + 0x74); - NV_INFO(dev, "PGRAPH_TRAP_MP_EXEC - " + nv_rd32(priv, addr + 0x20); + pc = nv_rd32(priv, addr + 0x24); + oplow = nv_rd32(priv, addr + 0x70); + ophigh = nv_rd32(priv, addr + 0x74); + nv_error(priv, "TRAP_MP_EXEC - " "TP %d MP %d: ", tpid, i); nouveau_enum_print(nv50_mp_exec_error_names, status); printk(" at %06x warp %d, opcode %08x %08x\n", pc&0xffffff, pc >> 24, oplow, ophigh); } - nv_wr32(dev, addr + 0x10, mp10); - nv_wr32(dev, addr + 0x14, 0); + nv_wr32(priv, addr + 0x10, mp10); + nv_wr32(priv, addr + 0x14, 0); mps++; } if (!mps && display) - NV_INFO(dev, "PGRAPH_TRAP_MP_EXEC - TP %d: " + nv_error(priv, "TRAP_MP_EXEC - TP %d: " "No MPs claiming errors?\n", tpid); } static void -nv50_pgraph_tp_trap(struct drm_device *dev, int type, uint32_t ustatus_old, - uint32_t ustatus_new, int display, const char *name) +nv50_priv_tp_trap(struct nv50_graph_priv *priv, int type, u32 ustatus_old, + u32 ustatus_new, int display, const char *name) { - struct drm_nouveau_private *dev_priv = dev->dev_private; int tps = 0; - uint32_t units = nv_rd32(dev, 0x1540); + u32 units = nv_rd32(priv, 0x1540); int i, r; - uint32_t ustatus_addr, ustatus; + u32 ustatus_addr, ustatus; for (i = 0; i < 16; i++) { if (!(units & (1 << i))) continue; - if (dev_priv->chipset < 0xa0) + if (nv_device(priv)->chipset < 0xa0) ustatus_addr = ustatus_old + (i << 12); else ustatus_addr = ustatus_new + (i << 11); - ustatus = nv_rd32(dev, ustatus_addr) & 0x7fffffff; + ustatus = nv_rd32(priv, ustatus_addr) & 0x7fffffff; if (!ustatus) continue; tps++; switch (type) { case 6: /* texture error... unknown for now */ if (display) { - NV_ERROR(dev, "magic set %d:\n", i); + nv_error(priv, "magic set %d:\n", i); for (r = ustatus_addr + 4; r <= ustatus_addr + 0x10; r += 4) - NV_ERROR(dev, "\t0x%08x: 0x%08x\n", r, - nv_rd32(dev, r)); + nv_error(priv, "\t0x%08x: 0x%08x\n", r, + nv_rd32(priv, r)); } break; case 7: /* MP error */ if (ustatus & 0x04030000) { - nv50_pgraph_mp_trap(dev, i, display); + nv50_priv_mp_trap(priv, i, display); ustatus &= ~0x04030000; } break; case 8: /* TPDMA error */ { - uint32_t e0c = nv_rd32(dev, ustatus_addr + 4); - uint32_t e10 = nv_rd32(dev, ustatus_addr + 8); - uint32_t e14 = nv_rd32(dev, ustatus_addr + 0xc); - uint32_t e18 = nv_rd32(dev, ustatus_addr + 0x10); - uint32_t e1c = nv_rd32(dev, ustatus_addr + 0x14); - uint32_t e20 = nv_rd32(dev, ustatus_addr + 0x18); - uint32_t e24 = nv_rd32(dev, ustatus_addr + 0x1c); + u32 e0c = nv_rd32(priv, ustatus_addr + 4); + u32 e10 = nv_rd32(priv, ustatus_addr + 8); + u32 e14 = nv_rd32(priv, ustatus_addr + 0xc); + u32 e18 = nv_rd32(priv, ustatus_addr + 0x10); + u32 e1c = nv_rd32(priv, ustatus_addr + 0x14); + u32 e20 = nv_rd32(priv, ustatus_addr + 0x18); + u32 e24 = nv_rd32(priv, ustatus_addr + 0x1c); /* 2d engine destination */ if (ustatus & 0x00000010) { if (display) { - NV_INFO(dev, "PGRAPH_TRAP_TPDMA_2D - TP %d - Unknown fault at address %02x%08x\n", + nv_error(priv, "TRAP_TPDMA_2D - TP %d - Unknown fault at address %02x%08x\n", i, e14, e10); - NV_INFO(dev, "PGRAPH_TRAP_TPDMA_2D - TP %d - e0c: %08x, e18: %08x, e1c: %08x, e20: %08x, e24: %08x\n", + nv_error(priv, "TRAP_TPDMA_2D - TP %d - e0c: %08x, e18: %08x, e1c: %08x, e20: %08x, e24: %08x\n", i, e0c, e18, e1c, e20, e24); } ustatus &= ~0x00000010; @@ -452,9 +418,9 @@ nv50_pgraph_tp_trap(struct drm_device *dev, int type, uint32_t ustatus_old, /* Render target */ if (ustatus & 0x00000040) { if (display) { - NV_INFO(dev, "PGRAPH_TRAP_TPDMA_RT - TP %d - Unknown fault at address %02x%08x\n", + nv_error(priv, "TRAP_TPDMA_RT - TP %d - Unknown fault at address %02x%08x\n", i, e14, e10); - NV_INFO(dev, "PGRAPH_TRAP_TPDMA_RT - TP %d - e0c: %08x, e18: %08x, e1c: %08x, e20: %08x, e24: %08x\n", + nv_error(priv, "TRAP_TPDMA_RT - TP %d - e0c: %08x, e18: %08x, e1c: %08x, e20: %08x, e24: %08x\n", i, e0c, e18, e1c, e20, e24); } ustatus &= ~0x00000040; @@ -464,19 +430,19 @@ nv50_pgraph_tp_trap(struct drm_device *dev, int type, uint32_t ustatus_old, if (display) { if (e18 & 0x80000000) { /* g[] read fault? */ - NV_INFO(dev, "PGRAPH_TRAP_TPDMA - TP %d - Global read fault at address %02x%08x\n", + nv_error(priv, "TRAP_TPDMA - TP %d - Global read fault at address %02x%08x\n", i, e14, e10 | ((e18 >> 24) & 0x1f)); e18 &= ~0x1f000000; } else if (e18 & 0xc) { /* g[] write fault? */ - NV_INFO(dev, "PGRAPH_TRAP_TPDMA - TP %d - Global write fault at address %02x%08x\n", + nv_error(priv, "TRAP_TPDMA - TP %d - Global write fault at address %02x%08x\n", i, e14, e10 | ((e18 >> 7) & 0x1f)); e18 &= ~0x00000f80; } else { - NV_INFO(dev, "PGRAPH_TRAP_TPDMA - TP %d - Unknown CUDA fault at address %02x%08x\n", + nv_error(priv, "TRAP_TPDMA - TP %d - Unknown CUDA fault at address %02x%08x\n", i, e14, e10); } - NV_INFO(dev, "PGRAPH_TRAP_TPDMA - TP %d - e0c: %08x, e18: %08x, e1c: %08x, e20: %08x, e24: %08x\n", + nv_error(priv, "TRAP_TPDMA - TP %d - e0c: %08x, e18: %08x, e1c: %08x, e20: %08x, e24: %08x\n", i, e0c, e18, e1c, e20, e24); } ustatus &= ~0x00000080; @@ -486,23 +452,23 @@ nv50_pgraph_tp_trap(struct drm_device *dev, int type, uint32_t ustatus_old, } if (ustatus) { if (display) - NV_INFO(dev, "%s - TP%d: Unhandled ustatus 0x%08x\n", name, i, ustatus); + nv_info(priv, "%s - TP%d: Unhandled ustatus 0x%08x\n", name, i, ustatus); } - nv_wr32(dev, ustatus_addr, 0xc0000000); + nv_wr32(priv, ustatus_addr, 0xc0000000); } if (!tps && display) - NV_INFO(dev, "%s - No TPs claiming errors?\n", name); + nv_info(priv, "%s - No TPs claiming errors?\n", name); } static int -nv50_pgraph_trap_handler(struct drm_device *dev, u32 display, u64 inst, u32 chid) +nv50_graph_trap_handler(struct nv50_graph_priv *priv, u32 display, u64 inst) { - u32 status = nv_rd32(dev, 0x400108); + u32 status = nv_rd32(priv, 0x400108); u32 ustatus; if (!status && display) { - NV_INFO(dev, "PGRAPH - TRAP: no units reporting traps?\n"); + nv_error(priv, "TRAP: no units reporting traps?\n"); return 1; } @@ -510,72 +476,72 @@ nv50_pgraph_trap_handler(struct drm_device *dev, u32 display, u64 inst, u32 chid * COND, QUERY. If you get a trap from it, the command is still stuck * in DISPATCH and you need to do something about it. */ if (status & 0x001) { - ustatus = nv_rd32(dev, 0x400804) & 0x7fffffff; + ustatus = nv_rd32(priv, 0x400804) & 0x7fffffff; if (!ustatus && display) { - NV_INFO(dev, "PGRAPH_TRAP_DISPATCH - no ustatus?\n"); + nv_error(priv, "TRAP_DISPATCH - no ustatus?\n"); } - nv_wr32(dev, 0x400500, 0x00000000); + nv_wr32(priv, 0x400500, 0x00000000); /* Known to be triggered by screwed up NOTIFY and COND... */ if (ustatus & 0x00000001) { - u32 addr = nv_rd32(dev, 0x400808); + u32 addr = nv_rd32(priv, 0x400808); u32 subc = (addr & 0x00070000) >> 16; u32 mthd = (addr & 0x00001ffc); - u32 datal = nv_rd32(dev, 0x40080c); - u32 datah = nv_rd32(dev, 0x400810); - u32 class = nv_rd32(dev, 0x400814); - u32 r848 = nv_rd32(dev, 0x400848); + u32 datal = nv_rd32(priv, 0x40080c); + u32 datah = nv_rd32(priv, 0x400810); + u32 class = nv_rd32(priv, 0x400814); + u32 r848 = nv_rd32(priv, 0x400848); - NV_INFO(dev, "PGRAPH - TRAP DISPATCH_FAULT\n"); + nv_error(priv, "TRAP DISPATCH_FAULT\n"); if (display && (addr & 0x80000000)) { - NV_INFO(dev, "PGRAPH - ch %d (0x%010llx) " + nv_error(priv, "ch 0x%010llx " "subc %d class 0x%04x mthd 0x%04x " "data 0x%08x%08x " "400808 0x%08x 400848 0x%08x\n", - chid, inst, subc, class, mthd, datah, + inst, subc, class, mthd, datah, datal, addr, r848); } else if (display) { - NV_INFO(dev, "PGRAPH - no stuck command?\n"); + nv_error(priv, "no stuck command?\n"); } - nv_wr32(dev, 0x400808, 0); - nv_wr32(dev, 0x4008e8, nv_rd32(dev, 0x4008e8) & 3); - nv_wr32(dev, 0x400848, 0); + nv_wr32(priv, 0x400808, 0); + nv_wr32(priv, 0x4008e8, nv_rd32(priv, 0x4008e8) & 3); + nv_wr32(priv, 0x400848, 0); ustatus &= ~0x00000001; } if (ustatus & 0x00000002) { - u32 addr = nv_rd32(dev, 0x40084c); + u32 addr = nv_rd32(priv, 0x40084c); u32 subc = (addr & 0x00070000) >> 16; u32 mthd = (addr & 0x00001ffc); - u32 data = nv_rd32(dev, 0x40085c); - u32 class = nv_rd32(dev, 0x400814); + u32 data = nv_rd32(priv, 0x40085c); + u32 class = nv_rd32(priv, 0x400814); - NV_INFO(dev, "PGRAPH - TRAP DISPATCH_QUERY\n"); + nv_error(priv, "TRAP DISPATCH_QUERY\n"); if (display && (addr & 0x80000000)) { - NV_INFO(dev, "PGRAPH - ch %d (0x%010llx) " + nv_error(priv, "ch 0x%010llx " "subc %d class 0x%04x mthd 0x%04x " "data 0x%08x 40084c 0x%08x\n", - chid, inst, subc, class, mthd, + inst, subc, class, mthd, data, addr); } else if (display) { - NV_INFO(dev, "PGRAPH - no stuck command?\n"); + nv_error(priv, "no stuck command?\n"); } - nv_wr32(dev, 0x40084c, 0); + nv_wr32(priv, 0x40084c, 0); ustatus &= ~0x00000002; } if (ustatus && display) { - NV_INFO(dev, "PGRAPH - TRAP_DISPATCH (unknown " + nv_error(priv, "TRAP_DISPATCH (unknown " "0x%08x)\n", ustatus); } - nv_wr32(dev, 0x400804, 0xc0000000); - nv_wr32(dev, 0x400108, 0x001); + nv_wr32(priv, 0x400804, 0xc0000000); + nv_wr32(priv, 0x400108, 0x001); status &= ~0x001; if (!status) return 0; @@ -583,81 +549,81 @@ nv50_pgraph_trap_handler(struct drm_device *dev, u32 display, u64 inst, u32 chid /* M2MF: Memory to memory copy engine. */ if (status & 0x002) { - u32 ustatus = nv_rd32(dev, 0x406800) & 0x7fffffff; + u32 ustatus = nv_rd32(priv, 0x406800) & 0x7fffffff; if (display) { - NV_INFO(dev, "PGRAPH - TRAP_M2MF"); + nv_error(priv, "TRAP_M2MF"); nouveau_bitfield_print(nv50_graph_trap_m2mf, ustatus); printk("\n"); - NV_INFO(dev, "PGRAPH - TRAP_M2MF %08x %08x %08x %08x\n", - nv_rd32(dev, 0x406804), nv_rd32(dev, 0x406808), - nv_rd32(dev, 0x40680c), nv_rd32(dev, 0x406810)); + nv_error(priv, "TRAP_M2MF %08x %08x %08x %08x\n", + nv_rd32(priv, 0x406804), nv_rd32(priv, 0x406808), + nv_rd32(priv, 0x40680c), nv_rd32(priv, 0x406810)); } /* No sane way found yet -- just reset the bugger. */ - nv_wr32(dev, 0x400040, 2); - nv_wr32(dev, 0x400040, 0); - nv_wr32(dev, 0x406800, 0xc0000000); - nv_wr32(dev, 0x400108, 0x002); + nv_wr32(priv, 0x400040, 2); + nv_wr32(priv, 0x400040, 0); + nv_wr32(priv, 0x406800, 0xc0000000); + nv_wr32(priv, 0x400108, 0x002); status &= ~0x002; } /* VFETCH: Fetches data from vertex buffers. */ if (status & 0x004) { - u32 ustatus = nv_rd32(dev, 0x400c04) & 0x7fffffff; + u32 ustatus = nv_rd32(priv, 0x400c04) & 0x7fffffff; if (display) { - NV_INFO(dev, "PGRAPH - TRAP_VFETCH"); + nv_error(priv, "TRAP_VFETCH"); nouveau_bitfield_print(nv50_graph_trap_vfetch, ustatus); printk("\n"); - NV_INFO(dev, "PGRAPH - TRAP_VFETCH %08x %08x %08x %08x\n", - nv_rd32(dev, 0x400c00), nv_rd32(dev, 0x400c08), - nv_rd32(dev, 0x400c0c), nv_rd32(dev, 0x400c10)); + nv_error(priv, "TRAP_VFETCH %08x %08x %08x %08x\n", + nv_rd32(priv, 0x400c00), nv_rd32(priv, 0x400c08), + nv_rd32(priv, 0x400c0c), nv_rd32(priv, 0x400c10)); } - nv_wr32(dev, 0x400c04, 0xc0000000); - nv_wr32(dev, 0x400108, 0x004); + nv_wr32(priv, 0x400c04, 0xc0000000); + nv_wr32(priv, 0x400108, 0x004); status &= ~0x004; } /* STRMOUT: DirectX streamout / OpenGL transform feedback. */ if (status & 0x008) { - ustatus = nv_rd32(dev, 0x401800) & 0x7fffffff; + ustatus = nv_rd32(priv, 0x401800) & 0x7fffffff; if (display) { - NV_INFO(dev, "PGRAPH - TRAP_STRMOUT"); + nv_error(priv, "TRAP_STRMOUT"); nouveau_bitfield_print(nv50_graph_trap_strmout, ustatus); printk("\n"); - NV_INFO(dev, "PGRAPH - TRAP_STRMOUT %08x %08x %08x %08x\n", - nv_rd32(dev, 0x401804), nv_rd32(dev, 0x401808), - nv_rd32(dev, 0x40180c), nv_rd32(dev, 0x401810)); + nv_error(priv, "TRAP_STRMOUT %08x %08x %08x %08x\n", + nv_rd32(priv, 0x401804), nv_rd32(priv, 0x401808), + nv_rd32(priv, 0x40180c), nv_rd32(priv, 0x401810)); } /* No sane way found yet -- just reset the bugger. */ - nv_wr32(dev, 0x400040, 0x80); - nv_wr32(dev, 0x400040, 0); - nv_wr32(dev, 0x401800, 0xc0000000); - nv_wr32(dev, 0x400108, 0x008); + nv_wr32(priv, 0x400040, 0x80); + nv_wr32(priv, 0x400040, 0); + nv_wr32(priv, 0x401800, 0xc0000000); + nv_wr32(priv, 0x400108, 0x008); status &= ~0x008; } /* CCACHE: Handles code and c[] caches and fills them. */ if (status & 0x010) { - ustatus = nv_rd32(dev, 0x405018) & 0x7fffffff; + ustatus = nv_rd32(priv, 0x405018) & 0x7fffffff; if (display) { - NV_INFO(dev, "PGRAPH - TRAP_CCACHE"); + nv_error(priv, "TRAP_CCACHE"); nouveau_bitfield_print(nv50_graph_trap_ccache, ustatus); printk("\n"); - NV_INFO(dev, "PGRAPH - TRAP_CCACHE %08x %08x %08x %08x" + nv_error(priv, "TRAP_CCACHE %08x %08x %08x %08x" " %08x %08x %08x\n", - nv_rd32(dev, 0x405000), nv_rd32(dev, 0x405004), - nv_rd32(dev, 0x405008), nv_rd32(dev, 0x40500c), - nv_rd32(dev, 0x405010), nv_rd32(dev, 0x405014), - nv_rd32(dev, 0x40501c)); + nv_rd32(priv, 0x405000), nv_rd32(priv, 0x405004), + nv_rd32(priv, 0x405008), nv_rd32(priv, 0x40500c), + nv_rd32(priv, 0x405010), nv_rd32(priv, 0x405014), + nv_rd32(priv, 0x40501c)); } - nv_wr32(dev, 0x405018, 0xc0000000); - nv_wr32(dev, 0x400108, 0x010); + nv_wr32(priv, 0x405018, 0xc0000000); + nv_wr32(priv, 0x400108, 0x010); status &= ~0x010; } @@ -665,201 +631,248 @@ nv50_pgraph_trap_handler(struct drm_device *dev, u32 display, u64 inst, u32 chid * remaining, so try to handle it anyway. Perhaps related to that * unknown DMA slot on tesla? */ if (status & 0x20) { - ustatus = nv_rd32(dev, 0x402000) & 0x7fffffff; + ustatus = nv_rd32(priv, 0x402000) & 0x7fffffff; if (display) - NV_INFO(dev, "PGRAPH - TRAP_UNKC04 0x%08x\n", ustatus); - nv_wr32(dev, 0x402000, 0xc0000000); + nv_error(priv, "TRAP_UNKC04 0x%08x\n", ustatus); + nv_wr32(priv, 0x402000, 0xc0000000); /* no status modifiction on purpose */ } /* TEXTURE: CUDA texturing units */ if (status & 0x040) { - nv50_pgraph_tp_trap(dev, 6, 0x408900, 0x408600, display, - "PGRAPH - TRAP_TEXTURE"); - nv_wr32(dev, 0x400108, 0x040); + nv50_priv_tp_trap(priv, 6, 0x408900, 0x408600, display, + "TRAP_TEXTURE"); + nv_wr32(priv, 0x400108, 0x040); status &= ~0x040; } /* MP: CUDA execution engines. */ if (status & 0x080) { - nv50_pgraph_tp_trap(dev, 7, 0x408314, 0x40831c, display, - "PGRAPH - TRAP_MP"); - nv_wr32(dev, 0x400108, 0x080); + nv50_priv_tp_trap(priv, 7, 0x408314, 0x40831c, display, + "TRAP_MP"); + nv_wr32(priv, 0x400108, 0x080); status &= ~0x080; } /* TPDMA: Handles TP-initiated uncached memory accesses: * l[], g[], stack, 2d surfaces, render targets. */ if (status & 0x100) { - nv50_pgraph_tp_trap(dev, 8, 0x408e08, 0x408708, display, - "PGRAPH - TRAP_TPDMA"); - nv_wr32(dev, 0x400108, 0x100); + nv50_priv_tp_trap(priv, 8, 0x408e08, 0x408708, display, + "TRAP_TPDMA"); + nv_wr32(priv, 0x400108, 0x100); status &= ~0x100; } if (status) { if (display) - NV_INFO(dev, "PGRAPH - TRAP: unknown 0x%08x\n", status); - nv_wr32(dev, 0x400108, status); + nv_error(priv, "TRAP: unknown 0x%08x\n", status); + nv_wr32(priv, 0x400108, status); } return 1; } -int -nv50_graph_isr_chid(struct drm_device *dev, u64 inst) +static void +nv50_graph_intr(struct nouveau_subdev *subdev) { - struct nouveau_fifo_priv *pfifo = nv_engine(dev, NVOBJ_ENGINE_FIFO); - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_channel *chan; - unsigned long flags; - int i; + struct nv50_graph_priv *priv = (void *)subdev; + struct nouveau_engine *engine = nv_engine(subdev); + struct nouveau_handle *handle = NULL; + u32 stat = nv_rd32(priv, 0x400100); + u64 inst = (u64)(nv_rd32(priv, 0x40032c) & 0x0fffffff) << 12; + u32 addr = nv_rd32(priv, 0x400704); + u32 subc = (addr & 0x00070000) >> 16; + u32 mthd = (addr & 0x00001ffc); + u32 data = nv_rd32(priv, 0x400708); + u32 class = nv_rd32(priv, 0x400814); + u32 show = stat; + + if (stat & 0x00000010) { + handle = nouveau_engctx_lookup_class(engine, inst, class); + if (handle && !nv_call(handle->object, mthd, data)) + show &= ~0x00000010; + nouveau_engctx_handle_put(handle); + } - spin_lock_irqsave(&dev_priv->channels.lock, flags); - for (i = 0; i < pfifo->channels; i++) { - chan = dev_priv->channels.ptr[i]; - if (!chan || !chan->ramin) - continue; + if (show & 0x00100000) { + u32 ecode = nv_rd32(priv, 0x400110); + nv_error(priv, "DATA_ERROR "); + nouveau_enum_print(nv50_data_error_names, ecode); + printk("\n"); + } - if (inst == chan->ramin->addr) - break; + if (stat & 0x00200000) { + if (!nv50_graph_trap_handler(priv, show, inst)) + show &= ~0x00200000; + } + + nv_wr32(priv, 0x400100, stat); + nv_wr32(priv, 0x400500, 0x00010001); + + if (show) { + nv_info(priv, ""); + nouveau_bitfield_print(nv50_graph_intr_name, show); + printk("\n"); + nv_error(priv, "ch 0x%010llx subc %d class 0x%04x " + "mthd 0x%04x data 0x%08x\n", + inst, subc, class, mthd, data); + nv50_fb_trap(nouveau_fb(priv), 1); } - spin_unlock_irqrestore(&dev_priv->channels.lock, flags); - return i; + + if (nv_rd32(priv, 0x400824) & (1 << 31)) + nv_wr32(priv, 0x400824, nv_rd32(priv, 0x400824) & ~(1 << 31)); } -static void -nv50_graph_isr(struct drm_device *dev) +static int +nv50_graph_ctor(struct nouveau_object *parent, struct nouveau_object *engine, + struct nouveau_oclass *oclass, void *data, u32 size, + struct nouveau_object **pobject) { - u32 stat; - - while ((stat = nv_rd32(dev, 0x400100))) { - u64 inst = (u64)(nv_rd32(dev, 0x40032c) & 0x0fffffff) << 12; - u32 chid = nv50_graph_isr_chid(dev, inst); - u32 addr = nv_rd32(dev, NV04_PGRAPH_TRAPPED_ADDR); - u32 subc = (addr & 0x00070000) >> 16; - u32 mthd = (addr & 0x00001ffc); - u32 data = nv_rd32(dev, NV04_PGRAPH_TRAPPED_DATA); - u32 class = nv_rd32(dev, 0x400814); - u32 show = stat; - - if (stat & 0x00000010) { - if (!nouveau_gpuobj_mthd_call2(dev, chid, class, - mthd, data)) - show &= ~0x00000010; - } + struct nv50_graph_priv *priv; + int ret; - show = (show && nouveau_ratelimit()) ? show : 0; + ret = nouveau_graph_create(parent, engine, oclass, true, &priv); + *pobject = nv_object(priv); + if (ret) + return ret; - if (show & 0x00100000) { - u32 ecode = nv_rd32(dev, 0x400110); - NV_INFO(dev, "PGRAPH - DATA_ERROR "); - nouveau_enum_print(nv50_data_error_names, ecode); - printk("\n"); - } + nv_subdev(priv)->unit = 0x00201000; + nv_subdev(priv)->intr = nv50_graph_intr; + nv_engine(priv)->cclass = &nv50_graph_cclass; - if (stat & 0x00200000) { - if (!nv50_pgraph_trap_handler(dev, show, inst, chid)) - show &= ~0x00200000; - } + switch (nv_device(priv)->chipset) { + case 0x50: + nv_engine(priv)->sclass = nv50_graph_sclass; + break; + case 0x84: + case 0x86: + case 0x92: + case 0x94: + case 0x96: + case 0x98: + nv_engine(priv)->sclass = nv84_graph_sclass; + break; + case 0xa0: + case 0xaa: + case 0xac: + nv_engine(priv)->sclass = nva0_graph_sclass; + break; + case 0xa3: + case 0xa5: + case 0xa8: + nv_engine(priv)->sclass = nva3_graph_sclass; + break; + case 0xaf: + nv_engine(priv)->sclass = nvaf_graph_sclass; + break; - nv_wr32(dev, 0x400100, stat); - nv_wr32(dev, 0x400500, 0x00010001); + }; - if (show) { - NV_INFO(dev, "PGRAPH -"); - nouveau_bitfield_print(nv50_graph_intr, show); - printk("\n"); - NV_INFO(dev, "PGRAPH - ch %d (0x%010llx) subc %d " - "class 0x%04x mthd 0x%04x data 0x%08x\n", - chid, inst, subc, class, mthd, data); - nv50_fb_vm_trap(dev, 1); - } - } + if (nv_device(priv)->chipset == 0x50 || + nv_device(priv)->chipset == 0xac) + nv_engine(priv)->tlb_flush = nv50_graph_tlb_flush; + else + nv_engine(priv)->tlb_flush = nv84_graph_tlb_flush; - if (nv_rd32(dev, 0x400824) & (1 << 31)) - nv_wr32(dev, 0x400824, nv_rd32(dev, 0x400824) & ~(1 << 31)); + spin_lock_init(&priv->lock); + return 0; } -static void -nv50_graph_destroy(struct drm_device *dev, int engine) +static int +nv50_graph_init(struct nouveau_object *object) { - struct nv50_graph_engine *pgraph = nv_engine(dev, engine); + struct nv50_graph_priv *priv = (void *)object; + int ret, units, i; - NVOBJ_ENGINE_DEL(dev, GR); + ret = nouveau_graph_init(&priv->base); + if (ret) + return ret; - nouveau_irq_unregister(dev, 12); - kfree(pgraph); -} + /* NV_PGRAPH_DEBUG_3_HW_CTX_SWITCH_ENABLED */ + nv_wr32(priv, 0x40008c, 0x00000004); -int -nv50_graph_create(struct drm_device *dev) -{ - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nv50_graph_engine *pgraph; - int ret; + /* reset/enable traps and interrupts */ + nv_wr32(priv, 0x400804, 0xc0000000); + nv_wr32(priv, 0x406800, 0xc0000000); + nv_wr32(priv, 0x400c04, 0xc0000000); + nv_wr32(priv, 0x401800, 0xc0000000); + nv_wr32(priv, 0x405018, 0xc0000000); + nv_wr32(priv, 0x402000, 0xc0000000); + + units = nv_rd32(priv, 0x001540); + for (i = 0; i < 16; i++) { + if (!(units & (1 << i))) + continue; - pgraph = kzalloc(sizeof(*pgraph),GFP_KERNEL); - if (!pgraph) - return -ENOMEM; - - ret = nv50_grctx_init(dev, pgraph->ctxprog, ARRAY_SIZE(pgraph->ctxprog), - &pgraph->ctxprog_size, - &pgraph->grctx_size); - if (ret) { - NV_ERROR(dev, "PGRAPH: ctxprog build failed\n"); - kfree(pgraph); - return 0; + if (nv_device(priv)->chipset < 0xa0) { + nv_wr32(priv, 0x408900 + (i << 12), 0xc0000000); + nv_wr32(priv, 0x408e08 + (i << 12), 0xc0000000); + nv_wr32(priv, 0x408314 + (i << 12), 0xc0000000); + } else { + nv_wr32(priv, 0x408600 + (i << 11), 0xc0000000); + nv_wr32(priv, 0x408708 + (i << 11), 0xc0000000); + nv_wr32(priv, 0x40831c + (i << 11), 0xc0000000); + } } - pgraph->base.destroy = nv50_graph_destroy; - pgraph->base.init = nv50_graph_init; - pgraph->base.fini = nv50_graph_fini; - pgraph->base.context_new = nv50_graph_context_new; - pgraph->base.context_del = nv50_graph_context_del; - pgraph->base.object_new = nv50_graph_object_new; - if (dev_priv->chipset == 0x50 || dev_priv->chipset == 0xac) - pgraph->base.tlb_flush = nv50_graph_tlb_flush; - else - pgraph->base.tlb_flush = nv84_graph_tlb_flush; + nv_wr32(priv, 0x400108, 0xffffffff); + nv_wr32(priv, 0x400138, 0xffffffff); + nv_wr32(priv, 0x400100, 0xffffffff); + nv_wr32(priv, 0x40013c, 0xffffffff); + nv_wr32(priv, 0x400500, 0x00010001); - nouveau_irq_register(dev, 12, nv50_graph_isr); + /* upload context program, initialise ctxctl defaults */ + ret = nv50_grctx_init(nv_device(priv), &priv->size); + if (ret) + return ret; - NVOBJ_ENGINE_ADD(dev, GR, &pgraph->base); - NVOBJ_CLASS(dev, 0x0030, GR); /* null */ - NVOBJ_CLASS(dev, 0x5039, GR); /* m2mf */ - NVOBJ_CLASS(dev, 0x502d, GR); /* 2d */ + nv_wr32(priv, 0x400824, 0x00000000); + nv_wr32(priv, 0x400828, 0x00000000); + nv_wr32(priv, 0x40082c, 0x00000000); + nv_wr32(priv, 0x400830, 0x00000000); + nv_wr32(priv, 0x400724, 0x00000000); + nv_wr32(priv, 0x40032c, 0x00000000); + nv_wr32(priv, 0x400320, 4); /* CTXCTL_CMD = NEWCTXDMA */ - /* tesla */ - if (dev_priv->chipset == 0x50) - NVOBJ_CLASS(dev, 0x5097, GR); /* tesla (nv50) */ - else - if (dev_priv->chipset < 0xa0) - NVOBJ_CLASS(dev, 0x8297, GR); /* tesla (nv8x/nv9x) */ - else { - switch (dev_priv->chipset) { - case 0xa0: - case 0xaa: - case 0xac: - NVOBJ_CLASS(dev, 0x8397, GR); - break; - case 0xa3: - case 0xa5: - case 0xa8: - NVOBJ_CLASS(dev, 0x8597, GR); - break; - case 0xaf: - NVOBJ_CLASS(dev, 0x8697, GR); - break; + /* some unknown zcull magic */ + switch (nv_device(priv)->chipset & 0xf0) { + case 0x50: + case 0x80: + case 0x90: + nv_wr32(priv, 0x402ca8, 0x00000800); + break; + case 0xa0: + default: + nv_wr32(priv, 0x402cc0, 0x00000000); + if (nv_device(priv)->chipset == 0xa0 || + nv_device(priv)->chipset == 0xaa || + nv_device(priv)->chipset == 0xac) { + nv_wr32(priv, 0x402ca8, 0x00000802); + } else { + nv_wr32(priv, 0x402cc0, 0x00000000); + nv_wr32(priv, 0x402ca8, 0x00000002); } - } - /* compute */ - NVOBJ_CLASS(dev, 0x50c0, GR); - if (dev_priv->chipset > 0xa0 && - dev_priv->chipset != 0xaa && - dev_priv->chipset != 0xac) - NVOBJ_CLASS(dev, 0x85c0, GR); + break; + } + /* zero out zcull regions */ + for (i = 0; i < 8; i++) { + nv_wr32(priv, 0x402c20 + (i * 8), 0x00000000); + nv_wr32(priv, 0x402c24 + (i * 8), 0x00000000); + nv_wr32(priv, 0x402c28 + (i * 8), 0x00000000); + nv_wr32(priv, 0x402c2c + (i * 8), 0x00000000); + } return 0; } + +struct nouveau_oclass +nv50_graph_oclass = { + .handle = NV_ENGINE(GR, 0x50), + .ofuncs = &(struct nouveau_ofuncs) { + .ctor = nv50_graph_ctor, + .dtor = _nouveau_graph_dtor, + .init = nv50_graph_init, + .fini = _nouveau_graph_fini, + }, +}; diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/nv50.h b/drivers/gpu/drm/nouveau/core/engine/graph/nv50.h new file mode 100644 index 000000000000..0505fb419bde --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/engine/graph/nv50.h @@ -0,0 +1,7 @@ +#ifndef __NV50_GRAPH_H__ +#define __NV50_GRAPH_H__ + +int nv50_grctx_init(struct nouveau_device *, u32 *size); +void nv50_grctx_fill(struct nouveau_device *, struct nouveau_gpuobj *); + +#endif diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/nvc0.c b/drivers/gpu/drm/nouveau/core/engine/graph/nvc0.c index f994d2f7e8d5..db8aefc3cf3e 100644 --- a/drivers/gpu/drm/nouveau/core/engine/graph/nvc0.c +++ b/drivers/gpu/drm/nouveau/core/engine/graph/nvc0.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,94 +22,92 @@ * Authors: Ben Skeggs */ -#include -#include - -#include "drmP.h" - -#include "nouveau_drv.h" -#include -#include - #include "nvc0.h" #include "fuc/hubnvc0.fuc.h" #include "fuc/gpcnvc0.fuc.h" -static void -nvc0_graph_ctxctl_debug_unit(struct drm_device *dev, u32 base) -{ - NV_INFO(dev, "PGRAPH: %06x - done 0x%08x\n", base, - nv_rd32(dev, base + 0x400)); - NV_INFO(dev, "PGRAPH: %06x - stat 0x%08x 0x%08x 0x%08x 0x%08x\n", base, - nv_rd32(dev, base + 0x800), nv_rd32(dev, base + 0x804), - nv_rd32(dev, base + 0x808), nv_rd32(dev, base + 0x80c)); - NV_INFO(dev, "PGRAPH: %06x - stat 0x%08x 0x%08x 0x%08x 0x%08x\n", base, - nv_rd32(dev, base + 0x810), nv_rd32(dev, base + 0x814), - nv_rd32(dev, base + 0x818), nv_rd32(dev, base + 0x81c)); -} - -void -nvc0_graph_ctxctl_debug(struct drm_device *dev) -{ - u32 gpcnr = nv_rd32(dev, 0x409604) & 0xffff; - u32 gpc; - - nvc0_graph_ctxctl_debug_unit(dev, 0x409000); - for (gpc = 0; gpc < gpcnr; gpc++) - nvc0_graph_ctxctl_debug_unit(dev, 0x502000 + (gpc * 0x8000)); -} +/******************************************************************************* + * Graphics object classes + ******************************************************************************/ + +static struct nouveau_oclass +nvc0_graph_sclass[] = { + { 0x902d, &nouveau_object_ofuncs }, + { 0x9039, &nouveau_object_ofuncs }, + { 0x9097, &nouveau_object_ofuncs }, + { 0x90c0, &nouveau_object_ofuncs }, + {} +}; + +static struct nouveau_oclass +nvc1_graph_sclass[] = { + { 0x902d, &nouveau_object_ofuncs }, + { 0x9039, &nouveau_object_ofuncs }, + { 0x9097, &nouveau_object_ofuncs }, + { 0x90c0, &nouveau_object_ofuncs }, + { 0x9197, &nouveau_object_ofuncs }, + {} +}; + +static struct nouveau_oclass +nvc8_graph_sclass[] = { + { 0x902d, &nouveau_object_ofuncs }, + { 0x9039, &nouveau_object_ofuncs }, + { 0x9097, &nouveau_object_ofuncs }, + { 0x90c0, &nouveau_object_ofuncs }, + { 0x9197, &nouveau_object_ofuncs }, + { 0x9297, &nouveau_object_ofuncs }, + {} +}; + +/******************************************************************************* + * PGRAPH context + ******************************************************************************/ int -nvc0_graph_context_new(struct nouveau_channel *chan, int engine) +nvc0_graph_context_ctor(struct nouveau_object *parent, + struct nouveau_object *engine, + struct nouveau_oclass *oclass, void *args, u32 size, + struct nouveau_object **pobject) { - struct drm_device *dev = chan->dev; - struct nvc0_graph_priv *priv = nv_engine(dev, engine); + struct nouveau_vm *vm = nouveau_client(parent)->vm; + struct nvc0_graph_priv *priv = (void *)engine; struct nvc0_graph_data *data = priv->mmio_data; struct nvc0_graph_mmio *mmio = priv->mmio_list; - struct nvc0_graph_chan *grch; - struct nouveau_gpuobj *grctx; + struct nvc0_graph_chan *chan; int ret, i; - grch = kzalloc(sizeof(*grch), GFP_KERNEL); - if (!grch) - return -ENOMEM; - chan->engctx[NVOBJ_ENGINE_GR] = grch; - - ret = nouveau_gpuobj_new(dev, NULL, priv->size, 256, 0, &grch->grctx); - if (ret) - goto error; - - ret = nouveau_gpuobj_map_vm(grch->grctx, chan->vm, NV_MEM_ACCESS_RW | - NV_MEM_ACCESS_SYS, &grch->grctx_vma); + /* allocate memory for context, and fill with default values */ + ret = nouveau_graph_context_create(parent, engine, oclass, NULL, + priv->size, 0x100, + NVOBJ_FLAG_ZERO_ALLOC, &chan); + *pobject = nv_object(chan); if (ret) return ret; - grctx = grch->grctx; - /* allocate memory for a "mmio list" buffer that's used by the HUB * fuc to modify some per-context register settings on first load * of the context. */ - ret = nouveau_gpuobj_new(dev, NULL, 0x1000, 0x100, 0, &grch->mmio); + ret = nouveau_gpuobj_new(parent, NULL, 0x1000, 0x100, 0, &chan->mmio); if (ret) return ret; - ret = nouveau_gpuobj_map_vm(grch->mmio, chan->vm, + ret = nouveau_gpuobj_map_vm(nv_gpuobj(chan->mmio), vm, NV_MEM_ACCESS_RW | NV_MEM_ACCESS_SYS, - &grch->mmio_vma); + &chan->mmio_vma); if (ret) return ret; /* allocate buffers referenced by mmio list */ for (i = 0; data->size && i < ARRAY_SIZE(priv->mmio_data); i++) { - ret = nouveau_gpuobj_new(dev, NULL, data->size, data->align, - 0, &grch->data[i].mem); + ret = nouveau_gpuobj_new(parent, NULL, data->size, data->align, + 0, &chan->data[i].mem); if (ret) return ret; - ret = nouveau_gpuobj_map_vm(grch->data[i].mem, chan->vm, - data->access, - &grch->data[i].vma); + ret = nouveau_gpuobj_map_vm(chan->data[i].mem, vm, data->access, + &chan->data[i].vma); if (ret) return ret; @@ -122,117 +120,378 @@ nvc0_graph_context_new(struct nouveau_channel *chan, int engine) u32 data = mmio->data; if (mmio->shift) { - u64 info = grch->data[mmio->buffer].vma.offset; + u64 info = chan->data[mmio->buffer].vma.offset; data |= info >> mmio->shift; } - nv_wo32(grch->mmio, grch->mmio_nr++ * 4, addr); - nv_wo32(grch->mmio, grch->mmio_nr++ * 4, data); + nv_wo32(chan->mmio, chan->mmio_nr++ * 4, addr); + nv_wo32(chan->mmio, chan->mmio_nr++ * 4, data); mmio++; } for (i = 0; i < priv->size; i += 4) - nv_wo32(grch->grctx, i, priv->data[i / 4]); - - nv_wo32(chan->ramin, 0x0210, lower_32_bits(grch->grctx_vma.offset) | 4); - nv_wo32(chan->ramin, 0x0214, upper_32_bits(grch->grctx_vma.offset)); - nvimem_flush(dev); + nv_wo32(chan, i, priv->data[i / 4]); if (!priv->firmware) { - nv_wo32(grctx, 0x00, grch->mmio_nr / 2); - nv_wo32(grctx, 0x04, grch->mmio_vma.offset >> 8); + nv_wo32(chan, 0x00, chan->mmio_nr / 2); + nv_wo32(chan, 0x04, chan->mmio_vma.offset >> 8); } else { - nv_wo32(grctx, 0xf4, 0); - nv_wo32(grctx, 0xf8, 0); - nv_wo32(grctx, 0x10, grch->mmio_nr / 2); - nv_wo32(grctx, 0x14, lower_32_bits(grch->mmio_vma.offset)); - nv_wo32(grctx, 0x18, upper_32_bits(grch->mmio_vma.offset)); - nv_wo32(grctx, 0x1c, 1); - nv_wo32(grctx, 0x20, 0); - nv_wo32(grctx, 0x28, 0); - nv_wo32(grctx, 0x2c, 0); + nv_wo32(chan, 0xf4, 0); + nv_wo32(chan, 0xf8, 0); + nv_wo32(chan, 0x10, chan->mmio_nr / 2); + nv_wo32(chan, 0x14, lower_32_bits(chan->mmio_vma.offset)); + nv_wo32(chan, 0x18, upper_32_bits(chan->mmio_vma.offset)); + nv_wo32(chan, 0x1c, 1); + nv_wo32(chan, 0x20, 0); + nv_wo32(chan, 0x28, 0); + nv_wo32(chan, 0x2c, 0); } - nvimem_flush(dev); - return 0; -error: - priv->base.context_del(chan, engine); - return ret; + return 0; } void -nvc0_graph_context_del(struct nouveau_channel *chan, int engine) +nvc0_graph_context_dtor(struct nouveau_object *object) { - struct nvc0_graph_chan *grch = chan->engctx[engine]; + struct nvc0_graph_chan *chan = (void *)object; int i; - for (i = 0; i < ARRAY_SIZE(grch->data); i++) { - nouveau_gpuobj_unmap(&grch->data[i].vma); - nouveau_gpuobj_ref(NULL, &grch->data[i].mem); + for (i = 0; i < ARRAY_SIZE(chan->data); i++) { + nouveau_gpuobj_unmap(&chan->data[i].vma); + nouveau_gpuobj_ref(NULL, &chan->data[i].mem); } - nouveau_gpuobj_unmap(&grch->mmio_vma); - nouveau_gpuobj_ref(NULL, &grch->mmio); + nouveau_gpuobj_unmap(&chan->mmio_vma); + nouveau_gpuobj_ref(NULL, &chan->mmio); - nouveau_gpuobj_unmap(&grch->grctx_vma); - nouveau_gpuobj_ref(NULL, &grch->grctx); - chan->engctx[engine] = NULL; + nouveau_graph_context_destroy(&chan->base); } -static int -nvc0_graph_object_new(struct nouveau_channel *chan, int engine, - u32 handle, u16 class) +static struct nouveau_oclass +nvc0_graph_cclass = { + .ofuncs = &(struct nouveau_ofuncs) { + .ctor = nvc0_graph_context_ctor, + .dtor = nvc0_graph_context_dtor, + .init = _nouveau_graph_context_init, + .fini = _nouveau_graph_context_fini, + .rd32 = _nouveau_graph_context_rd32, + .wr32 = _nouveau_graph_context_wr32, + }, +}; + +/******************************************************************************* + * PGRAPH engine/subdev functions + ******************************************************************************/ + +static void +nvc0_graph_ctxctl_debug_unit(struct nvc0_graph_priv *priv, u32 base) { - return 0; + nv_error(priv, "%06x - done 0x%08x\n", base, + nv_rd32(priv, base + 0x400)); + nv_error(priv, "%06x - stat 0x%08x 0x%08x 0x%08x 0x%08x\n", base, + nv_rd32(priv, base + 0x800), nv_rd32(priv, base + 0x804), + nv_rd32(priv, base + 0x808), nv_rd32(priv, base + 0x80c)); + nv_error(priv, "%06x - stat 0x%08x 0x%08x 0x%08x 0x%08x\n", base, + nv_rd32(priv, base + 0x810), nv_rd32(priv, base + 0x814), + nv_rd32(priv, base + 0x818), nv_rd32(priv, base + 0x81c)); +} + +void +nvc0_graph_ctxctl_debug(struct nvc0_graph_priv *priv) +{ + u32 gpcnr = nv_rd32(priv, 0x409604) & 0xffff; + u32 gpc; + + nvc0_graph_ctxctl_debug_unit(priv, 0x409000); + for (gpc = 0; gpc < gpcnr; gpc++) + nvc0_graph_ctxctl_debug_unit(priv, 0x502000 + (gpc * 0x8000)); +} + +static void +nvc0_graph_ctxctl_isr(struct nvc0_graph_priv *priv) +{ + u32 ustat = nv_rd32(priv, 0x409c18); + + if (ustat & 0x00000001) + nv_error(priv, "CTXCTRL ucode error\n"); + if (ustat & 0x00080000) + nv_error(priv, "CTXCTRL watchdog timeout\n"); + if (ustat & ~0x00080001) + nv_error(priv, "CTXCTRL 0x%08x\n", ustat); + + nvc0_graph_ctxctl_debug(priv); + nv_wr32(priv, 0x409c20, ustat); +} + +static void +nvc0_graph_intr(struct nouveau_subdev *subdev) +{ + struct nvc0_graph_priv *priv = (void *)subdev; + struct nouveau_engine *engine = nv_engine(subdev); + struct nouveau_handle *handle = NULL; + u64 inst = (u64)(nv_rd32(priv, 0x409b00) & 0x0fffffff) << 12; + u32 stat = nv_rd32(priv, 0x400100); + u32 addr = nv_rd32(priv, 0x400704); + u32 mthd = (addr & 0x00003ffc); + u32 subc = (addr & 0x00070000) >> 16; + u32 data = nv_rd32(priv, 0x400708); + u32 code = nv_rd32(priv, 0x400110); + u32 class = nv_rd32(priv, 0x404200 + (subc * 4)); + + if (stat & 0x00000010) { + handle = nouveau_engctx_lookup_class(engine, inst, class); + if (!handle || nv_call(handle->object, mthd, data)) { + nv_error(priv, "ILLEGAL_MTHD ch 0x%010llx " + "subc %d class 0x%04x mthd 0x%04x " + "data 0x%08x\n", + inst, subc, class, mthd, data); + } + nouveau_engctx_handle_put(handle); + nv_wr32(priv, 0x400100, 0x00000010); + stat &= ~0x00000010; + } + + if (stat & 0x00000020) { + nv_error(priv, "ILLEGAL_CLASS ch 0x%010llx subc %d " + "class 0x%04x mthd 0x%04x data 0x%08x\n", + inst, subc, class, mthd, data); + nv_wr32(priv, 0x400100, 0x00000020); + stat &= ~0x00000020; + } + + if (stat & 0x00100000) { + nv_error(priv, "DATA_ERROR ["); + nouveau_enum_print(nv50_data_error_names, code); + printk("] ch 0x%010llx subc %d class 0x%04x " + "mthd 0x%04x data 0x%08x\n", + inst, subc, class, mthd, data); + nv_wr32(priv, 0x400100, 0x00100000); + stat &= ~0x00100000; + } + + if (stat & 0x00200000) { + u32 trap = nv_rd32(priv, 0x400108); + nv_error(priv, "TRAP ch 0x%010llx status 0x%08x\n", inst, trap); + nv_wr32(priv, 0x400108, trap); + nv_wr32(priv, 0x400100, 0x00200000); + stat &= ~0x00200000; + } + + if (stat & 0x00080000) { + nvc0_graph_ctxctl_isr(priv); + nv_wr32(priv, 0x400100, 0x00080000); + stat &= ~0x00080000; + } + + if (stat) { + nv_error(priv, "unknown stat 0x%08x\n", stat); + nv_wr32(priv, 0x400100, stat); + } + + nv_wr32(priv, 0x400500, 0x00010001); +} + +int +nvc0_graph_ctor_fw(struct nvc0_graph_priv *priv, const char *fwname, + struct nvc0_graph_fuc *fuc) +{ + struct nouveau_device *device = nv_device(priv); + const struct firmware *fw; + char f[32]; + int ret; + + snprintf(f, sizeof(f), "nouveau/nv%02x_%s", device->chipset, fwname); + ret = request_firmware(&fw, f, &device->pdev->dev); + if (ret) { + snprintf(f, sizeof(f), "nouveau/%s", fwname); + ret = request_firmware(&fw, f, &device->pdev->dev); + if (ret) { + nv_error(priv, "failed to load %s\n", fwname); + return ret; + } + } + + fuc->size = fw->size; + fuc->data = kmemdup(fw->data, fuc->size, GFP_KERNEL); + release_firmware(fw); + return (fuc->data != NULL) ? 0 : -ENOMEM; } static int -nvc0_graph_fini(struct drm_device *dev, int engine, bool suspend) +nvc0_graph_ctor(struct nouveau_object *parent, struct nouveau_object *engine, + struct nouveau_oclass *oclass, void *data, u32 size, + struct nouveau_object **pobject) { + struct nouveau_device *device = nv_device(parent); + struct nvc0_graph_priv *priv; + bool enable = true; + int ret, i; + + switch (device->chipset) { + case 0xd9: /* known broken without binary driver firmware */ + enable = false; + break; + default: + break; + } + + ret = nouveau_graph_create(parent, engine, oclass, enable, &priv); + *pobject = nv_object(priv); + if (ret) + return ret; + + nv_subdev(priv)->unit = 0x18001000; + nv_subdev(priv)->intr = nvc0_graph_intr; + nv_engine(priv)->cclass = &nvc0_graph_cclass; + + if (nouveau_boolopt(device->cfgopt, "NvGrUseFW", false)) { + nv_info(priv, "using external firmware\n"); + if (nvc0_graph_ctor_fw(priv, "fuc409c", &priv->fuc409c) || + nvc0_graph_ctor_fw(priv, "fuc409d", &priv->fuc409d) || + nvc0_graph_ctor_fw(priv, "fuc41ac", &priv->fuc41ac) || + nvc0_graph_ctor_fw(priv, "fuc41ad", &priv->fuc41ad)) + return -EINVAL; + priv->firmware = true; + } + + switch (nvc0_graph_class(priv)) { + case 0x9097: + nv_engine(priv)->sclass = nvc0_graph_sclass; + break; + case 0x9197: + nv_engine(priv)->sclass = nvc1_graph_sclass; + break; + case 0x9297: + nv_engine(priv)->sclass = nvc8_graph_sclass; + break; + } + + ret = nouveau_gpuobj_new(parent, NULL, 0x1000, 256, 0, &priv->unk4188b4); + if (ret) + return ret; + + ret = nouveau_gpuobj_new(parent, NULL, 0x1000, 256, 0, &priv->unk4188b8); + if (ret) + return ret; + + for (i = 0; i < 0x1000; i += 4) { + nv_wo32(priv->unk4188b4, i, 0x00000010); + nv_wo32(priv->unk4188b8, i, 0x00000010); + } + + priv->rop_nr = (nv_rd32(priv, 0x409604) & 0x001f0000) >> 16; + priv->gpc_nr = nv_rd32(priv, 0x409604) & 0x0000001f; + for (i = 0; i < priv->gpc_nr; i++) { + priv->tpc_nr[i] = nv_rd32(priv, GPC_UNIT(i, 0x2608)); + priv->tpc_total += priv->tpc_nr[i]; + } + + /*XXX: these need figuring out... though it might not even matter */ + switch (nv_device(priv)->chipset) { + case 0xc0: + if (priv->tpc_total == 11) { /* 465, 3/4/4/0, 4 */ + priv->magic_not_rop_nr = 0x07; + } else + if (priv->tpc_total == 14) { /* 470, 3/3/4/4, 5 */ + priv->magic_not_rop_nr = 0x05; + } else + if (priv->tpc_total == 15) { /* 480, 3/4/4/4, 6 */ + priv->magic_not_rop_nr = 0x06; + } + break; + case 0xc3: /* 450, 4/0/0/0, 2 */ + priv->magic_not_rop_nr = 0x03; + break; + case 0xc4: /* 460, 3/4/0/0, 4 */ + priv->magic_not_rop_nr = 0x01; + break; + case 0xc1: /* 2/0/0/0, 1 */ + priv->magic_not_rop_nr = 0x01; + break; + case 0xc8: /* 4/4/3/4, 5 */ + priv->magic_not_rop_nr = 0x06; + break; + case 0xce: /* 4/4/0/0, 4 */ + priv->magic_not_rop_nr = 0x03; + break; + case 0xcf: /* 4/0/0/0, 3 */ + priv->magic_not_rop_nr = 0x03; + break; + case 0xd9: /* 1/0/0/0, 1 */ + priv->magic_not_rop_nr = 0x01; + break; + } + return 0; } static void -nvc0_graph_init_obj418880(struct drm_device *dev) +nvc0_graph_dtor_fw(struct nvc0_graph_fuc *fuc) +{ + if (fuc->data) { + kfree(fuc->data); + fuc->data = NULL; + } +} + +void +nvc0_graph_dtor(struct nouveau_object *object) +{ + struct nvc0_graph_priv *priv = (void *)object; + + if (priv->data) + kfree(priv->data); + + nvc0_graph_dtor_fw(&priv->fuc409c); + nvc0_graph_dtor_fw(&priv->fuc409d); + nvc0_graph_dtor_fw(&priv->fuc41ac); + nvc0_graph_dtor_fw(&priv->fuc41ad); + + nouveau_gpuobj_ref(NULL, &priv->unk4188b8); + nouveau_gpuobj_ref(NULL, &priv->unk4188b4); + + nouveau_graph_destroy(&priv->base); +} + +static void +nvc0_graph_init_obj418880(struct nvc0_graph_priv *priv) { - struct nvc0_graph_priv *priv = nv_engine(dev, NVOBJ_ENGINE_GR); int i; - nv_wr32(dev, GPC_BCAST(0x0880), 0x00000000); - nv_wr32(dev, GPC_BCAST(0x08a4), 0x00000000); + nv_wr32(priv, GPC_BCAST(0x0880), 0x00000000); + nv_wr32(priv, GPC_BCAST(0x08a4), 0x00000000); for (i = 0; i < 4; i++) - nv_wr32(dev, GPC_BCAST(0x0888) + (i * 4), 0x00000000); - nv_wr32(dev, GPC_BCAST(0x08b4), priv->unk4188b4->addr >> 8); - nv_wr32(dev, GPC_BCAST(0x08b8), priv->unk4188b8->addr >> 8); + nv_wr32(priv, GPC_BCAST(0x0888) + (i * 4), 0x00000000); + nv_wr32(priv, GPC_BCAST(0x08b4), priv->unk4188b4->addr >> 8); + nv_wr32(priv, GPC_BCAST(0x08b8), priv->unk4188b8->addr >> 8); } static void -nvc0_graph_init_regs(struct drm_device *dev) +nvc0_graph_init_regs(struct nvc0_graph_priv *priv) { - nv_wr32(dev, 0x400080, 0x003083c2); - nv_wr32(dev, 0x400088, 0x00006fe7); - nv_wr32(dev, 0x40008c, 0x00000000); - nv_wr32(dev, 0x400090, 0x00000030); - nv_wr32(dev, 0x40013c, 0x013901f7); - nv_wr32(dev, 0x400140, 0x00000100); - nv_wr32(dev, 0x400144, 0x00000000); - nv_wr32(dev, 0x400148, 0x00000110); - nv_wr32(dev, 0x400138, 0x00000000); - nv_wr32(dev, 0x400130, 0x00000000); - nv_wr32(dev, 0x400134, 0x00000000); - nv_wr32(dev, 0x400124, 0x00000002); + nv_wr32(priv, 0x400080, 0x003083c2); + nv_wr32(priv, 0x400088, 0x00006fe7); + nv_wr32(priv, 0x40008c, 0x00000000); + nv_wr32(priv, 0x400090, 0x00000030); + nv_wr32(priv, 0x40013c, 0x013901f7); + nv_wr32(priv, 0x400140, 0x00000100); + nv_wr32(priv, 0x400144, 0x00000000); + nv_wr32(priv, 0x400148, 0x00000110); + nv_wr32(priv, 0x400138, 0x00000000); + nv_wr32(priv, 0x400130, 0x00000000); + nv_wr32(priv, 0x400134, 0x00000000); + nv_wr32(priv, 0x400124, 0x00000002); } static void -nvc0_graph_init_gpc_0(struct drm_device *dev) +nvc0_graph_init_gpc_0(struct nvc0_graph_priv *priv) { - struct nvc0_graph_priv *priv = nv_engine(dev, NVOBJ_ENGINE_GR); const u32 magicgpc918 = DIV_ROUND_UP(0x00800000, priv->tpc_total); u32 data[TPC_MAX / 8]; - u8 tpnr[GPC_MAX]; + u8 tpcnr[GPC_MAX]; int i, gpc, tpc; - nv_wr32(dev, TPC_UNIT(0, 0, 0x5c), 1); /* affects TFB offset queries */ + nv_wr32(priv, TPC_UNIT(0, 0, 0x5c), 1); /* affects TFB offset queries */ /* * TP ROP UNKVAL(magic_not_rop_nr) @@ -244,205 +503,208 @@ nvc0_graph_init_gpc_0(struct drm_device *dev) */ memset(data, 0x00, sizeof(data)); - memcpy(tpnr, priv->tpc_nr, sizeof(priv->tpc_nr)); + memcpy(tpcnr, priv->tpc_nr, sizeof(priv->tpc_nr)); for (i = 0, gpc = -1; i < priv->tpc_total; i++) { do { gpc = (gpc + 1) % priv->gpc_nr; - } while (!tpnr[gpc]); - tpc = priv->tpc_nr[gpc] - tpnr[gpc]--; + } while (!tpcnr[gpc]); + tpc = priv->tpc_nr[gpc] - tpcnr[gpc]--; data[i / 8] |= tpc << ((i % 8) * 4); } - nv_wr32(dev, GPC_BCAST(0x0980), data[0]); - nv_wr32(dev, GPC_BCAST(0x0984), data[1]); - nv_wr32(dev, GPC_BCAST(0x0988), data[2]); - nv_wr32(dev, GPC_BCAST(0x098c), data[3]); + nv_wr32(priv, GPC_BCAST(0x0980), data[0]); + nv_wr32(priv, GPC_BCAST(0x0984), data[1]); + nv_wr32(priv, GPC_BCAST(0x0988), data[2]); + nv_wr32(priv, GPC_BCAST(0x098c), data[3]); for (gpc = 0; gpc < priv->gpc_nr; gpc++) { - nv_wr32(dev, GPC_UNIT(gpc, 0x0914), priv->magic_not_rop_nr << 8 | + nv_wr32(priv, GPC_UNIT(gpc, 0x0914), priv->magic_not_rop_nr << 8 | priv->tpc_nr[gpc]); - nv_wr32(dev, GPC_UNIT(gpc, 0x0910), 0x00040000 | priv->tpc_total); - nv_wr32(dev, GPC_UNIT(gpc, 0x0918), magicgpc918); + nv_wr32(priv, GPC_UNIT(gpc, 0x0910), 0x00040000 | priv->tpc_total); + nv_wr32(priv, GPC_UNIT(gpc, 0x0918), magicgpc918); } - nv_wr32(dev, GPC_BCAST(0x1bd4), magicgpc918); - nv_wr32(dev, GPC_BCAST(0x08ac), nv_rd32(dev, 0x100800)); + nv_wr32(priv, GPC_BCAST(0x1bd4), magicgpc918); + nv_wr32(priv, GPC_BCAST(0x08ac), nv_rd32(priv, 0x100800)); } static void -nvc0_graph_init_units(struct drm_device *dev) +nvc0_graph_init_units(struct nvc0_graph_priv *priv) { - nv_wr32(dev, 0x409c24, 0x000f0000); - nv_wr32(dev, 0x404000, 0xc0000000); /* DISPATCH */ - nv_wr32(dev, 0x404600, 0xc0000000); /* M2MF */ - nv_wr32(dev, 0x408030, 0xc0000000); - nv_wr32(dev, 0x40601c, 0xc0000000); - nv_wr32(dev, 0x404490, 0xc0000000); /* MACRO */ - nv_wr32(dev, 0x406018, 0xc0000000); - nv_wr32(dev, 0x405840, 0xc0000000); - nv_wr32(dev, 0x405844, 0x00ffffff); - nv_mask(dev, 0x419cc0, 0x00000008, 0x00000008); - nv_mask(dev, 0x419eb4, 0x00001000, 0x00001000); + nv_wr32(priv, 0x409c24, 0x000f0000); + nv_wr32(priv, 0x404000, 0xc0000000); /* DISPATCH */ + nv_wr32(priv, 0x404600, 0xc0000000); /* M2MF */ + nv_wr32(priv, 0x408030, 0xc0000000); + nv_wr32(priv, 0x40601c, 0xc0000000); + nv_wr32(priv, 0x404490, 0xc0000000); /* MACRO */ + nv_wr32(priv, 0x406018, 0xc0000000); + nv_wr32(priv, 0x405840, 0xc0000000); + nv_wr32(priv, 0x405844, 0x00ffffff); + nv_mask(priv, 0x419cc0, 0x00000008, 0x00000008); + nv_mask(priv, 0x419eb4, 0x00001000, 0x00001000); } static void -nvc0_graph_init_gpc_1(struct drm_device *dev) +nvc0_graph_init_gpc_1(struct nvc0_graph_priv *priv) { - struct nvc0_graph_priv *priv = nv_engine(dev, NVOBJ_ENGINE_GR); - int gpc, tp; + int gpc, tpc; for (gpc = 0; gpc < priv->gpc_nr; gpc++) { - nv_wr32(dev, GPC_UNIT(gpc, 0x0420), 0xc0000000); - nv_wr32(dev, GPC_UNIT(gpc, 0x0900), 0xc0000000); - nv_wr32(dev, GPC_UNIT(gpc, 0x1028), 0xc0000000); - nv_wr32(dev, GPC_UNIT(gpc, 0x0824), 0xc0000000); - for (tp = 0; tp < priv->tpc_nr[gpc]; tp++) { - nv_wr32(dev, TPC_UNIT(gpc, tp, 0x508), 0xffffffff); - nv_wr32(dev, TPC_UNIT(gpc, tp, 0x50c), 0xffffffff); - nv_wr32(dev, TPC_UNIT(gpc, tp, 0x224), 0xc0000000); - nv_wr32(dev, TPC_UNIT(gpc, tp, 0x48c), 0xc0000000); - nv_wr32(dev, TPC_UNIT(gpc, tp, 0x084), 0xc0000000); - nv_wr32(dev, TPC_UNIT(gpc, tp, 0x644), 0x001ffffe); - nv_wr32(dev, TPC_UNIT(gpc, tp, 0x64c), 0x0000000f); + nv_wr32(priv, GPC_UNIT(gpc, 0x0420), 0xc0000000); + nv_wr32(priv, GPC_UNIT(gpc, 0x0900), 0xc0000000); + nv_wr32(priv, GPC_UNIT(gpc, 0x1028), 0xc0000000); + nv_wr32(priv, GPC_UNIT(gpc, 0x0824), 0xc0000000); + for (tpc = 0; tpc < priv->tpc_nr[gpc]; tpc++) { + nv_wr32(priv, TPC_UNIT(gpc, tpc, 0x508), 0xffffffff); + nv_wr32(priv, TPC_UNIT(gpc, tpc, 0x50c), 0xffffffff); + nv_wr32(priv, TPC_UNIT(gpc, tpc, 0x224), 0xc0000000); + nv_wr32(priv, TPC_UNIT(gpc, tpc, 0x48c), 0xc0000000); + nv_wr32(priv, TPC_UNIT(gpc, tpc, 0x084), 0xc0000000); + nv_wr32(priv, TPC_UNIT(gpc, tpc, 0x644), 0x001ffffe); + nv_wr32(priv, TPC_UNIT(gpc, tpc, 0x64c), 0x0000000f); } - nv_wr32(dev, GPC_UNIT(gpc, 0x2c90), 0xffffffff); - nv_wr32(dev, GPC_UNIT(gpc, 0x2c94), 0xffffffff); + nv_wr32(priv, GPC_UNIT(gpc, 0x2c90), 0xffffffff); + nv_wr32(priv, GPC_UNIT(gpc, 0x2c94), 0xffffffff); } } static void -nvc0_graph_init_rop(struct drm_device *dev) +nvc0_graph_init_rop(struct nvc0_graph_priv *priv) { - struct nvc0_graph_priv *priv = nv_engine(dev, NVOBJ_ENGINE_GR); int rop; for (rop = 0; rop < priv->rop_nr; rop++) { - nv_wr32(dev, ROP_UNIT(rop, 0x144), 0xc0000000); - nv_wr32(dev, ROP_UNIT(rop, 0x070), 0xc0000000); - nv_wr32(dev, ROP_UNIT(rop, 0x204), 0xffffffff); - nv_wr32(dev, ROP_UNIT(rop, 0x208), 0xffffffff); + nv_wr32(priv, ROP_UNIT(rop, 0x144), 0xc0000000); + nv_wr32(priv, ROP_UNIT(rop, 0x070), 0xc0000000); + nv_wr32(priv, ROP_UNIT(rop, 0x204), 0xffffffff); + nv_wr32(priv, ROP_UNIT(rop, 0x208), 0xffffffff); } } -static void -nvc0_graph_init_fuc(struct drm_device *dev, u32 fuc_base, - struct nvc0_graph_fuc *code, struct nvc0_graph_fuc *data) +void +nvc0_graph_init_fw(struct nvc0_graph_priv *priv, u32 fuc_base, + struct nvc0_graph_fuc *code, struct nvc0_graph_fuc *data) { int i; - nv_wr32(dev, fuc_base + 0x01c0, 0x01000000); + nv_wr32(priv, fuc_base + 0x01c0, 0x01000000); for (i = 0; i < data->size / 4; i++) - nv_wr32(dev, fuc_base + 0x01c4, data->data[i]); + nv_wr32(priv, fuc_base + 0x01c4, data->data[i]); - nv_wr32(dev, fuc_base + 0x0180, 0x01000000); + nv_wr32(priv, fuc_base + 0x0180, 0x01000000); for (i = 0; i < code->size / 4; i++) { if ((i & 0x3f) == 0) - nv_wr32(dev, fuc_base + 0x0188, i >> 6); - nv_wr32(dev, fuc_base + 0x0184, code->data[i]); + nv_wr32(priv, fuc_base + 0x0188, i >> 6); + nv_wr32(priv, fuc_base + 0x0184, code->data[i]); } } static int -nvc0_graph_init_ctxctl(struct drm_device *dev) +nvc0_graph_init_ctxctl(struct nvc0_graph_priv *priv) { - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nvc0_graph_priv *priv = nv_engine(dev, NVOBJ_ENGINE_GR); u32 r000260; int i; if (priv->firmware) { /* load fuc microcode */ - r000260 = nv_mask(dev, 0x000260, 0x00000001, 0x00000000); - nvc0_graph_init_fuc(dev, 0x409000, &priv->fuc409c, + r000260 = nv_mask(priv, 0x000260, 0x00000001, 0x00000000); + nvc0_graph_init_fw(priv, 0x409000, &priv->fuc409c, &priv->fuc409d); - nvc0_graph_init_fuc(dev, 0x41a000, &priv->fuc41ac, + nvc0_graph_init_fw(priv, 0x41a000, &priv->fuc41ac, &priv->fuc41ad); - nv_wr32(dev, 0x000260, r000260); + nv_wr32(priv, 0x000260, r000260); /* start both of them running */ - nv_wr32(dev, 0x409840, 0xffffffff); - nv_wr32(dev, 0x41a10c, 0x00000000); - nv_wr32(dev, 0x40910c, 0x00000000); - nv_wr32(dev, 0x41a100, 0x00000002); - nv_wr32(dev, 0x409100, 0x00000002); - if (!nv_wait(dev, 0x409800, 0x00000001, 0x00000001)) - NV_INFO(dev, "0x409800 wait failed\n"); - - nv_wr32(dev, 0x409840, 0xffffffff); - nv_wr32(dev, 0x409500, 0x7fffffff); - nv_wr32(dev, 0x409504, 0x00000021); - - nv_wr32(dev, 0x409840, 0xffffffff); - nv_wr32(dev, 0x409500, 0x00000000); - nv_wr32(dev, 0x409504, 0x00000010); - if (!nv_wait_ne(dev, 0x409800, 0xffffffff, 0x00000000)) { - NV_ERROR(dev, "fuc09 req 0x10 timeout\n"); + nv_wr32(priv, 0x409840, 0xffffffff); + nv_wr32(priv, 0x41a10c, 0x00000000); + nv_wr32(priv, 0x40910c, 0x00000000); + nv_wr32(priv, 0x41a100, 0x00000002); + nv_wr32(priv, 0x409100, 0x00000002); + if (!nv_wait(priv, 0x409800, 0x00000001, 0x00000001)) + nv_info(priv, "0x409800 wait failed\n"); + + nv_wr32(priv, 0x409840, 0xffffffff); + nv_wr32(priv, 0x409500, 0x7fffffff); + nv_wr32(priv, 0x409504, 0x00000021); + + nv_wr32(priv, 0x409840, 0xffffffff); + nv_wr32(priv, 0x409500, 0x00000000); + nv_wr32(priv, 0x409504, 0x00000010); + if (!nv_wait_ne(priv, 0x409800, 0xffffffff, 0x00000000)) { + nv_error(priv, "fuc09 req 0x10 timeout\n"); return -EBUSY; } - priv->size = nv_rd32(dev, 0x409800); + priv->size = nv_rd32(priv, 0x409800); - nv_wr32(dev, 0x409840, 0xffffffff); - nv_wr32(dev, 0x409500, 0x00000000); - nv_wr32(dev, 0x409504, 0x00000016); - if (!nv_wait_ne(dev, 0x409800, 0xffffffff, 0x00000000)) { - NV_ERROR(dev, "fuc09 req 0x16 timeout\n"); + nv_wr32(priv, 0x409840, 0xffffffff); + nv_wr32(priv, 0x409500, 0x00000000); + nv_wr32(priv, 0x409504, 0x00000016); + if (!nv_wait_ne(priv, 0x409800, 0xffffffff, 0x00000000)) { + nv_error(priv, "fuc09 req 0x16 timeout\n"); return -EBUSY; } - nv_wr32(dev, 0x409840, 0xffffffff); - nv_wr32(dev, 0x409500, 0x00000000); - nv_wr32(dev, 0x409504, 0x00000025); - if (!nv_wait_ne(dev, 0x409800, 0xffffffff, 0x00000000)) { - NV_ERROR(dev, "fuc09 req 0x25 timeout\n"); + nv_wr32(priv, 0x409840, 0xffffffff); + nv_wr32(priv, 0x409500, 0x00000000); + nv_wr32(priv, 0x409504, 0x00000025); + if (!nv_wait_ne(priv, 0x409800, 0xffffffff, 0x00000000)) { + nv_error(priv, "fuc09 req 0x25 timeout\n"); return -EBUSY; } - goto done; + if (priv->data == NULL) { + int ret = nvc0_grctx_generate(priv); + if (ret) { + nv_error(priv, "failed to construct context\n"); + return ret; + } + } + + return 0; } /* load HUB microcode */ - r000260 = nv_mask(dev, 0x000260, 0x00000001, 0x00000000); - nv_wr32(dev, 0x4091c0, 0x01000000); + r000260 = nv_mask(priv, 0x000260, 0x00000001, 0x00000000); + nv_wr32(priv, 0x4091c0, 0x01000000); for (i = 0; i < sizeof(nvc0_grhub_data) / 4; i++) - nv_wr32(dev, 0x4091c4, nvc0_grhub_data[i]); + nv_wr32(priv, 0x4091c4, nvc0_grhub_data[i]); - nv_wr32(dev, 0x409180, 0x01000000); + nv_wr32(priv, 0x409180, 0x01000000); for (i = 0; i < sizeof(nvc0_grhub_code) / 4; i++) { if ((i & 0x3f) == 0) - nv_wr32(dev, 0x409188, i >> 6); - nv_wr32(dev, 0x409184, nvc0_grhub_code[i]); + nv_wr32(priv, 0x409188, i >> 6); + nv_wr32(priv, 0x409184, nvc0_grhub_code[i]); } /* load GPC microcode */ - nv_wr32(dev, 0x41a1c0, 0x01000000); + nv_wr32(priv, 0x41a1c0, 0x01000000); for (i = 0; i < sizeof(nvc0_grgpc_data) / 4; i++) - nv_wr32(dev, 0x41a1c4, nvc0_grgpc_data[i]); + nv_wr32(priv, 0x41a1c4, nvc0_grgpc_data[i]); - nv_wr32(dev, 0x41a180, 0x01000000); + nv_wr32(priv, 0x41a180, 0x01000000); for (i = 0; i < sizeof(nvc0_grgpc_code) / 4; i++) { if ((i & 0x3f) == 0) - nv_wr32(dev, 0x41a188, i >> 6); - nv_wr32(dev, 0x41a184, nvc0_grgpc_code[i]); + nv_wr32(priv, 0x41a188, i >> 6); + nv_wr32(priv, 0x41a184, nvc0_grgpc_code[i]); } - nv_wr32(dev, 0x000260, r000260); + nv_wr32(priv, 0x000260, r000260); /* start HUB ucode running, it'll init the GPCs */ - nv_wr32(dev, 0x409800, dev_priv->chipset); - nv_wr32(dev, 0x40910c, 0x00000000); - nv_wr32(dev, 0x409100, 0x00000002); - if (!nv_wait(dev, 0x409800, 0x80000000, 0x80000000)) { - NV_ERROR(dev, "PGRAPH: HUB_INIT timed out\n"); - nvc0_graph_ctxctl_debug(dev); + nv_wr32(priv, 0x409800, nv_device(priv)->chipset); + nv_wr32(priv, 0x40910c, 0x00000000); + nv_wr32(priv, 0x409100, 0x00000002); + if (!nv_wait(priv, 0x409800, 0x80000000, 0x80000000)) { + nv_error(priv, "HUB_INIT timed out\n"); + nvc0_graph_ctxctl_debug(priv); return -EBUSY; } - priv->size = nv_rd32(dev, 0x409804); -done: + priv->size = nv_rd32(priv, 0x409804); if (priv->data == NULL) { - int ret = nvc0_grctx_generate(dev); + int ret = nvc0_grctx_generate(priv); if (ret) { - NV_ERROR(dev, "PGRAPH: failed to construct context\n"); + nv_error(priv, "failed to construct context\n"); return ret; } @@ -453,37 +715,39 @@ done: } static int -nvc0_graph_init(struct drm_device *dev, int engine) +nvc0_graph_init(struct nouveau_object *object) { + struct nvc0_graph_priv *priv = (void *)object; int ret; reset: - nv_mask(dev, 0x000200, 0x18001000, 0x00000000); - nv_mask(dev, 0x000200, 0x18001000, 0x18001000); - - nvc0_graph_init_obj418880(dev); - nvc0_graph_init_regs(dev); - /*nvc0_graph_init_unitplemented_magics(dev);*/ - nvc0_graph_init_gpc_0(dev); - /*nvc0_graph_init_unitplemented_c242(dev);*/ - - nv_wr32(dev, 0x400500, 0x00010001); - nv_wr32(dev, 0x400100, 0xffffffff); - nv_wr32(dev, 0x40013c, 0xffffffff); - - nvc0_graph_init_units(dev); - nvc0_graph_init_gpc_1(dev); - nvc0_graph_init_rop(dev); - - nv_wr32(dev, 0x400108, 0xffffffff); - nv_wr32(dev, 0x400138, 0xffffffff); - nv_wr32(dev, 0x400118, 0xffffffff); - nv_wr32(dev, 0x400130, 0xffffffff); - nv_wr32(dev, 0x40011c, 0xffffffff); - nv_wr32(dev, 0x400134, 0xffffffff); - nv_wr32(dev, 0x400054, 0x34ce3464); - - ret = nvc0_graph_init_ctxctl(dev); + ret = nouveau_graph_init(&priv->base); + if (ret) + return ret; + + nvc0_graph_init_obj418880(priv); + nvc0_graph_init_regs(priv); + /*nvc0_graph_init_unitplemented_magics(priv);*/ + nvc0_graph_init_gpc_0(priv); + /*nvc0_graph_init_unitplemented_c242(priv);*/ + + nv_wr32(priv, 0x400500, 0x00010001); + nv_wr32(priv, 0x400100, 0xffffffff); + nv_wr32(priv, 0x40013c, 0xffffffff); + + nvc0_graph_init_units(priv); + nvc0_graph_init_gpc_1(priv); + nvc0_graph_init_rop(priv); + + nv_wr32(priv, 0x400108, 0xffffffff); + nv_wr32(priv, 0x400138, 0xffffffff); + nv_wr32(priv, 0x400118, 0xffffffff); + nv_wr32(priv, 0x400130, 0xffffffff); + nv_wr32(priv, 0x40011c, 0xffffffff); + nv_wr32(priv, 0x400134, 0xffffffff); + nv_wr32(priv, 0x400054, 0x34ce3464); + + ret = nvc0_graph_init_ctxctl(priv); if (ret) { if (ret == 1) goto reset; @@ -493,279 +757,13 @@ reset: return 0; } -int -nvc0_graph_isr_chid(struct drm_device *dev, u64 inst) -{ - struct nouveau_fifo_priv *pfifo = nv_engine(dev, NVOBJ_ENGINE_FIFO); - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_channel *chan; - unsigned long flags; - int i; - - spin_lock_irqsave(&dev_priv->channels.lock, flags); - for (i = 0; i < pfifo->channels; i++) { - chan = dev_priv->channels.ptr[i]; - if (!chan || !chan->ramin) - continue; - - if (inst == chan->ramin->addr) - break; - } - spin_unlock_irqrestore(&dev_priv->channels.lock, flags); - return i; -} - -static void -nvc0_graph_ctxctl_isr(struct drm_device *dev) -{ - u32 ustat = nv_rd32(dev, 0x409c18); - - if (ustat & 0x00000001) - NV_INFO(dev, "PGRAPH: CTXCTRL ucode error\n"); - if (ustat & 0x00080000) - NV_INFO(dev, "PGRAPH: CTXCTRL watchdog timeout\n"); - if (ustat & ~0x00080001) - NV_INFO(dev, "PGRAPH: CTXCTRL 0x%08x\n", ustat); - - nvc0_graph_ctxctl_debug(dev); - nv_wr32(dev, 0x409c20, ustat); -} - -static void -nvc0_graph_isr(struct drm_device *dev) -{ - u64 inst = (u64)(nv_rd32(dev, 0x409b00) & 0x0fffffff) << 12; - u32 chid = nvc0_graph_isr_chid(dev, inst); - u32 stat = nv_rd32(dev, 0x400100); - u32 addr = nv_rd32(dev, 0x400704); - u32 mthd = (addr & 0x00003ffc); - u32 subc = (addr & 0x00070000) >> 16; - u32 data = nv_rd32(dev, 0x400708); - u32 code = nv_rd32(dev, 0x400110); - u32 class = nv_rd32(dev, 0x404200 + (subc * 4)); - - if (stat & 0x00000010) { - if (nouveau_gpuobj_mthd_call2(dev, chid, class, mthd, data)) { - NV_INFO(dev, "PGRAPH: ILLEGAL_MTHD ch %d [0x%010llx] " - "subc %d class 0x%04x mthd 0x%04x " - "data 0x%08x\n", - chid, inst, subc, class, mthd, data); - } - nv_wr32(dev, 0x400100, 0x00000010); - stat &= ~0x00000010; - } - - if (stat & 0x00000020) { - NV_INFO(dev, "PGRAPH: ILLEGAL_CLASS ch %d [0x%010llx] subc %d " - "class 0x%04x mthd 0x%04x data 0x%08x\n", - chid, inst, subc, class, mthd, data); - nv_wr32(dev, 0x400100, 0x00000020); - stat &= ~0x00000020; - } - - if (stat & 0x00100000) { - NV_INFO(dev, "PGRAPH: DATA_ERROR ["); - nouveau_enum_print(nv50_data_error_names, code); - printk("] ch %d [0x%010llx] subc %d class 0x%04x " - "mthd 0x%04x data 0x%08x\n", - chid, inst, subc, class, mthd, data); - nv_wr32(dev, 0x400100, 0x00100000); - stat &= ~0x00100000; - } - - if (stat & 0x00200000) { - u32 trap = nv_rd32(dev, 0x400108); - NV_INFO(dev, "PGRAPH: TRAP ch %d status 0x%08x\n", chid, trap); - nv_wr32(dev, 0x400108, trap); - nv_wr32(dev, 0x400100, 0x00200000); - stat &= ~0x00200000; - } - - if (stat & 0x00080000) { - nvc0_graph_ctxctl_isr(dev); - nv_wr32(dev, 0x400100, 0x00080000); - stat &= ~0x00080000; - } - - if (stat) { - NV_INFO(dev, "PGRAPH: unknown stat 0x%08x\n", stat); - nv_wr32(dev, 0x400100, stat); - } - - nv_wr32(dev, 0x400500, 0x00010001); -} - -static int -nvc0_graph_create_fw(struct drm_device *dev, const char *fwname, - struct nvc0_graph_fuc *fuc) -{ - struct drm_nouveau_private *dev_priv = dev->dev_private; - const struct firmware *fw; - char f[32]; - int ret; - - snprintf(f, sizeof(f), "nouveau/nv%02x_%s", dev_priv->chipset, fwname); - ret = request_firmware(&fw, f, &dev->pdev->dev); - if (ret) { - snprintf(f, sizeof(f), "nouveau/%s", fwname); - ret = request_firmware(&fw, f, &dev->pdev->dev); - if (ret) { - NV_ERROR(dev, "failed to load %s\n", fwname); - return ret; - } - } - - fuc->size = fw->size; - fuc->data = kmemdup(fw->data, fuc->size, GFP_KERNEL); - release_firmware(fw); - return (fuc->data != NULL) ? 0 : -ENOMEM; -} - -static void -nvc0_graph_destroy_fw(struct nvc0_graph_fuc *fuc) -{ - if (fuc->data) { - kfree(fuc->data); - fuc->data = NULL; - } -} - -static void -nvc0_graph_destroy(struct drm_device *dev, int engine) -{ - struct nvc0_graph_priv *priv = nv_engine(dev, engine); - - nvc0_graph_destroy_fw(&priv->fuc409c); - nvc0_graph_destroy_fw(&priv->fuc409d); - nvc0_graph_destroy_fw(&priv->fuc41ac); - nvc0_graph_destroy_fw(&priv->fuc41ad); - - nouveau_irq_unregister(dev, 12); - - nouveau_gpuobj_ref(NULL, &priv->unk4188b8); - nouveau_gpuobj_ref(NULL, &priv->unk4188b4); - - if (priv->data) - kfree(priv->data); - - NVOBJ_ENGINE_DEL(dev, GR); - kfree(priv); -} - -int -nvc0_graph_create(struct drm_device *dev) -{ - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nvc0_graph_priv *priv; - int ret, gpc, i; - u32 fermi; - - fermi = nvc0_graph_class(dev); - if (!fermi) { - NV_ERROR(dev, "PGRAPH: unsupported chipset, please report!\n"); - return 0; - } - - priv = kzalloc(sizeof(*priv), GFP_KERNEL); - if (!priv) - return -ENOMEM; - - priv->base.destroy = nvc0_graph_destroy; - priv->base.init = nvc0_graph_init; - priv->base.fini = nvc0_graph_fini; - priv->base.context_new = nvc0_graph_context_new; - priv->base.context_del = nvc0_graph_context_del; - priv->base.object_new = nvc0_graph_object_new; - - NVOBJ_ENGINE_ADD(dev, GR, &priv->base); - nouveau_irq_register(dev, 12, nvc0_graph_isr); - - if (nouveau_ctxfw) { - NV_INFO(dev, "PGRAPH: using external firmware\n"); - if (nvc0_graph_create_fw(dev, "fuc409c", &priv->fuc409c) || - nvc0_graph_create_fw(dev, "fuc409d", &priv->fuc409d) || - nvc0_graph_create_fw(dev, "fuc41ac", &priv->fuc41ac) || - nvc0_graph_create_fw(dev, "fuc41ad", &priv->fuc41ad)) { - ret = 0; - goto error; - } - priv->firmware = true; - } - - ret = nouveau_gpuobj_new(dev, NULL, 0x1000, 256, 0, &priv->unk4188b4); - if (ret) - goto error; - - ret = nouveau_gpuobj_new(dev, NULL, 0x1000, 256, 0, &priv->unk4188b8); - if (ret) - goto error; - - for (i = 0; i < 0x1000; i += 4) { - nv_wo32(priv->unk4188b4, i, 0x00000010); - nv_wo32(priv->unk4188b8, i, 0x00000010); - } - - priv->gpc_nr = nv_rd32(dev, 0x409604) & 0x0000001f; - priv->rop_nr = (nv_rd32(dev, 0x409604) & 0x001f0000) >> 16; - for (gpc = 0; gpc < priv->gpc_nr; gpc++) { - priv->tpc_nr[gpc] = nv_rd32(dev, GPC_UNIT(gpc, 0x2608)); - priv->tpc_total += priv->tpc_nr[gpc]; - } - - /*XXX: these need figuring out... */ - switch (dev_priv->chipset) { - case 0xc0: - if (priv->tpc_total == 11) { /* 465, 3/4/4/0, 4 */ - priv->magic_not_rop_nr = 0x07; - } else - if (priv->tpc_total == 14) { /* 470, 3/3/4/4, 5 */ - priv->magic_not_rop_nr = 0x05; - } else - if (priv->tpc_total == 15) { /* 480, 3/4/4/4, 6 */ - priv->magic_not_rop_nr = 0x06; - } - break; - case 0xc3: /* 450, 4/0/0/0, 2 */ - priv->magic_not_rop_nr = 0x03; - break; - case 0xc4: /* 460, 3/4/0/0, 4 */ - priv->magic_not_rop_nr = 0x01; - break; - case 0xc1: /* 2/0/0/0, 1 */ - priv->magic_not_rop_nr = 0x01; - break; - case 0xc8: /* 4/4/3/4, 5 */ - priv->magic_not_rop_nr = 0x06; - break; - case 0xce: /* 4/4/0/0, 4 */ - priv->magic_not_rop_nr = 0x03; - break; - case 0xcf: /* 4/0/0/0, 3 */ - priv->magic_not_rop_nr = 0x03; - break; - case 0xd9: /* 1/0/0/0, 1 */ - priv->magic_not_rop_nr = 0x01; - break; - } - - if (!priv->magic_not_rop_nr) { - NV_ERROR(dev, "PGRAPH: unknown config: %d/%d/%d/%d, %d\n", - priv->tpc_nr[0], priv->tpc_nr[1], priv->tpc_nr[2], - priv->tpc_nr[3], priv->rop_nr); - priv->magic_not_rop_nr = 0x00; - } - - NVOBJ_CLASS(dev, 0x902d, GR); /* 2D */ - NVOBJ_CLASS(dev, 0x9039, GR); /* M2MF */ - NVOBJ_CLASS(dev, 0x9097, GR); /* 3D */ - if (fermi >= 0x9197) - NVOBJ_CLASS(dev, 0x9197, GR); /* 3D (NVC1-) */ - if (fermi >= 0x9297) - NVOBJ_CLASS(dev, 0x9297, GR); /* 3D (NVC8-) */ - NVOBJ_CLASS(dev, 0x90c0, GR); /* COMPUTE */ - return 0; - -error: - nvc0_graph_destroy(dev, NVOBJ_ENGINE_GR); - return ret; -} +struct nouveau_oclass +nvc0_graph_oclass = { + .handle = NV_ENGINE(GR, 0xc0), + .ofuncs = &(struct nouveau_ofuncs) { + .ctor = nvc0_graph_ctor, + .dtor = nvc0_graph_dtor, + .init = nvc0_graph_init, + .fini = _nouveau_graph_fini, + }, +}; diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/nvc0.h b/drivers/gpu/drm/nouveau/core/engine/graph/nvc0.h index 30ea3ab135c6..26f8268cc8c2 100644 --- a/drivers/gpu/drm/nouveau/core/engine/graph/nvc0.h +++ b/drivers/gpu/drm/nouveau/core/engine/graph/nvc0.h @@ -25,6 +25,18 @@ #ifndef __NVC0_GRAPH_H__ #define __NVC0_GRAPH_H__ +#include +#include +#include +#include + +#include +#include +#include +#include + +#include + #define GPC_MAX 4 #define TPC_MAX 32 @@ -53,7 +65,7 @@ struct nvc0_graph_fuc { }; struct nvc0_graph_priv { - struct nouveau_exec_engine base; + struct nouveau_graph base; struct nvc0_graph_fuc fuc409c; struct nvc0_graph_fuc fuc409d; @@ -78,11 +90,10 @@ struct nvc0_graph_priv { }; struct nvc0_graph_chan { - struct nouveau_gpuobj *grctx; - struct nouveau_vma grctx_vma; + struct nouveau_graph_chan base; struct nouveau_gpuobj *mmio; - struct nouveau_vma mmio_vma; + struct nouveau_vma mmio_vma; int mmio_nr; struct { struct nouveau_gpuobj *mem; @@ -91,11 +102,11 @@ struct nvc0_graph_chan { }; static inline u32 -nvc0_graph_class(struct drm_device *priv) +nvc0_graph_class(void *obj) { - struct drm_nouveau_private *dev_priv = priv->dev_private; + struct nouveau_device *device = nv_device(obj); - switch (dev_priv->chipset) { + switch (device->chipset) { case 0xc0: case 0xc3: case 0xc4: @@ -115,17 +126,16 @@ nvc0_graph_class(struct drm_device *priv) } } -void nv_icmd(struct drm_device *priv, u32 icmd, u32 data); +void nv_icmd(struct nvc0_graph_priv *priv, u32 icmd, u32 data); static inline void -nv_mthd(struct drm_device *priv, u32 class, u32 mthd, u32 data) +nv_mthd(struct nvc0_graph_priv *priv, u32 class, u32 mthd, u32 data) { nv_wr32(priv, 0x40448c, data); nv_wr32(priv, 0x404488, 0x80000000 | (mthd << 14) | class); } struct nvc0_grctx { - struct drm_device *dev; struct nvc0_graph_priv *priv; struct nvc0_graph_data *data; struct nvc0_graph_mmio *mmio; @@ -135,18 +145,18 @@ struct nvc0_grctx { u64 addr; }; -int nvc0_grctx_generate(struct drm_device *); -int nvc0_grctx_init(struct drm_device *, struct nvc0_graph_priv *, - struct nvc0_grctx *); +int nvc0_grctx_generate(struct nvc0_graph_priv *); +int nvc0_grctx_init(struct nvc0_graph_priv *, struct nvc0_grctx *); void nvc0_grctx_data(struct nvc0_grctx *, u32, u32, u32); void nvc0_grctx_mmio(struct nvc0_grctx *, u32, u32, u32, u32); int nvc0_grctx_fini(struct nvc0_grctx *); -int nve0_grctx_generate(struct drm_device *); +int nve0_grctx_generate(struct nvc0_graph_priv *); #define mmio_data(s,a,p) nvc0_grctx_data(&info, (s), (a), (p)) #define mmio_list(r,d,s,b) nvc0_grctx_mmio(&info, (r), (d), (s), (b)) +void nvc0_graph_ctxctl_debug(struct nvc0_graph_priv *); int nvc0_graph_ctor_fw(struct nvc0_graph_priv *, const char *, struct nvc0_graph_fuc *); void nvc0_graph_dtor(struct nouveau_object *); @@ -157,9 +167,4 @@ int nvc0_graph_context_ctor(struct nouveau_object *, struct nouveau_object *, struct nouveau_object **); void nvc0_graph_context_dtor(struct nouveau_object *); -void nvc0_graph_ctxctl_debug(struct drm_device *); - -int nvc0_graph_context_new(struct nouveau_channel *, int); -void nvc0_graph_context_del(struct nouveau_channel *, int); - #endif diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/nve0.c b/drivers/gpu/drm/nouveau/core/engine/graph/nve0.c index a3a4ee7c0b2e..c79748a6fa2b 100644 --- a/drivers/gpu/drm/nouveau/core/engine/graph/nve0.c +++ b/drivers/gpu/drm/nouveau/core/engine/graph/nve0.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,116 +22,290 @@ * Authors: Ben Skeggs */ -#include -#include - -#include "drmP.h" - -#include "nouveau_drv.h" -#include -#include - #include "nvc0.h" +/******************************************************************************* + * Graphics object classes + ******************************************************************************/ + +static struct nouveau_oclass +nve0_graph_sclass[] = { + { 0x902d, &nouveau_object_ofuncs }, + { 0xa040, &nouveau_object_ofuncs }, + { 0xa097, &nouveau_object_ofuncs }, + { 0xa0c0, &nouveau_object_ofuncs }, + { 0xa0b5, &nouveau_object_ofuncs }, + {} +}; + +/******************************************************************************* + * PGRAPH context + ******************************************************************************/ + +static struct nouveau_oclass +nve0_graph_cclass = { + .handle = NV_ENGCTX(GR, 0xe0), + .ofuncs = &(struct nouveau_ofuncs) { + .ctor = nvc0_graph_context_ctor, + .dtor = nvc0_graph_context_dtor, + .init = _nouveau_graph_context_init, + .fini = _nouveau_graph_context_fini, + .rd32 = _nouveau_graph_context_rd32, + .wr32 = _nouveau_graph_context_wr32, + }, +}; + +/******************************************************************************* + * PGRAPH engine/subdev functions + ******************************************************************************/ + static void -nve0_graph_ctxctl_debug_unit(struct drm_device *dev, u32 base) +nve0_graph_ctxctl_isr(struct nvc0_graph_priv *priv) { - NV_INFO(dev, "PGRAPH: %06x - done 0x%08x\n", base, - nv_rd32(dev, base + 0x400)); - NV_INFO(dev, "PGRAPH: %06x - stat 0x%08x 0x%08x 0x%08x 0x%08x\n", base, - nv_rd32(dev, base + 0x800), nv_rd32(dev, base + 0x804), - nv_rd32(dev, base + 0x808), nv_rd32(dev, base + 0x80c)); - NV_INFO(dev, "PGRAPH: %06x - stat 0x%08x 0x%08x 0x%08x 0x%08x\n", base, - nv_rd32(dev, base + 0x810), nv_rd32(dev, base + 0x814), - nv_rd32(dev, base + 0x818), nv_rd32(dev, base + 0x81c)); + u32 ustat = nv_rd32(priv, 0x409c18); + + if (ustat & 0x00000001) + nv_error(priv, "CTXCTRL ucode error\n"); + if (ustat & 0x00080000) + nv_error(priv, "CTXCTRL watchdog timeout\n"); + if (ustat & ~0x00080001) + nv_error(priv, "CTXCTRL 0x%08x\n", ustat); + + nvc0_graph_ctxctl_debug(priv); + nv_wr32(priv, 0x409c20, ustat); } static void -nve0_graph_ctxctl_debug(struct drm_device *dev) +nve0_graph_trap_isr(struct nvc0_graph_priv *priv, u64 inst) { - u32 gpcnr = nv_rd32(dev, 0x409604) & 0xffff; - u32 gpc; + u32 trap = nv_rd32(priv, 0x400108); + int rop; + + if (trap & 0x00000001) { + u32 stat = nv_rd32(priv, 0x404000); + nv_error(priv, "DISPATCH ch 0x%010llx 0x%08x\n", inst, stat); + nv_wr32(priv, 0x404000, 0xc0000000); + nv_wr32(priv, 0x400108, 0x00000001); + trap &= ~0x00000001; + } - nve0_graph_ctxctl_debug_unit(dev, 0x409000); - for (gpc = 0; gpc < gpcnr; gpc++) - nve0_graph_ctxctl_debug_unit(dev, 0x502000 + (gpc * 0x8000)); + if (trap & 0x00000010) { + u32 stat = nv_rd32(priv, 0x405840); + nv_error(priv, "SHADER ch 0x%010llx 0x%08x\n", inst, stat); + nv_wr32(priv, 0x405840, 0xc0000000); + nv_wr32(priv, 0x400108, 0x00000010); + trap &= ~0x00000010; + } + + if (trap & 0x02000000) { + for (rop = 0; rop < priv->rop_nr; rop++) { + u32 statz = nv_rd32(priv, ROP_UNIT(rop, 0x070)); + u32 statc = nv_rd32(priv, ROP_UNIT(rop, 0x144)); + nv_error(priv, "ROP%d ch 0x%010llx 0x%08x 0x%08x\n", + rop, inst, statz, statc); + nv_wr32(priv, ROP_UNIT(rop, 0x070), 0xc0000000); + nv_wr32(priv, ROP_UNIT(rop, 0x144), 0xc0000000); + } + nv_wr32(priv, 0x400108, 0x02000000); + trap &= ~0x02000000; + } + + if (trap) { + nv_error(priv, "TRAP ch 0x%010llx 0x%08x\n", inst, trap); + nv_wr32(priv, 0x400108, trap); + } } -static int -nve0_graph_object_new(struct nouveau_channel *chan, int engine, - u32 handle, u16 class) +static void +nve0_graph_intr(struct nouveau_subdev *subdev) { - return 0; + struct nvc0_graph_priv *priv = (void *)subdev; + struct nouveau_engine *engine = nv_engine(subdev); + struct nouveau_handle *handle = NULL; + u64 inst = (u64)(nv_rd32(priv, 0x409b00) & 0x0fffffff) << 12; + u32 stat = nv_rd32(priv, 0x400100); + u32 addr = nv_rd32(priv, 0x400704); + u32 mthd = (addr & 0x00003ffc); + u32 subc = (addr & 0x00070000) >> 16; + u32 data = nv_rd32(priv, 0x400708); + u32 code = nv_rd32(priv, 0x400110); + u32 class = nv_rd32(priv, 0x404200 + (subc * 4)); + + if (stat & 0x00000010) { + handle = nouveau_engctx_lookup_class(engine, inst, class); + if (!handle || nv_call(handle->object, mthd, data)) { + nv_error(priv, "ILLEGAL_MTHD ch 0x%010llx " + "subc %d class 0x%04x mthd 0x%04x " + "data 0x%08x\n", + inst, subc, class, mthd, data); + } + nouveau_engctx_handle_put(handle); + nv_wr32(priv, 0x400100, 0x00000010); + stat &= ~0x00000010; + } + + if (stat & 0x00000020) { + nv_error(priv, "ILLEGAL_CLASS ch 0x%010llx subc %d " + "class 0x%04x mthd 0x%04x data 0x%08x\n", + inst, subc, class, mthd, data); + nv_wr32(priv, 0x400100, 0x00000020); + stat &= ~0x00000020; + } + + if (stat & 0x00100000) { + nv_error(priv, "DATA_ERROR ["); + nouveau_enum_print(nv50_data_error_names, code); + printk("] ch 0x%010llx subc %d class 0x%04x " + "mthd 0x%04x data 0x%08x\n", + inst, subc, class, mthd, data); + nv_wr32(priv, 0x400100, 0x00100000); + stat &= ~0x00100000; + } + + if (stat & 0x00200000) { + nve0_graph_trap_isr(priv, inst); + nv_wr32(priv, 0x400100, 0x00200000); + stat &= ~0x00200000; + } + + if (stat & 0x00080000) { + nve0_graph_ctxctl_isr(priv); + nv_wr32(priv, 0x400100, 0x00080000); + stat &= ~0x00080000; + } + + if (stat) { + nv_error(priv, "unknown stat 0x%08x\n", stat); + nv_wr32(priv, 0x400100, stat); + } + + nv_wr32(priv, 0x400500, 0x00010001); } static int -nve0_graph_fini(struct drm_device *dev, int engine, bool suspend) +nve0_graph_ctor(struct nouveau_object *parent, struct nouveau_object *engine, + struct nouveau_oclass *oclass, void *data, u32 size, + struct nouveau_object **pobject) { + struct nvc0_graph_priv *priv; + int ret, i; + + ret = nouveau_graph_create(parent, engine, oclass, false, &priv); + *pobject = nv_object(priv); + if (ret) + return ret; + + nv_subdev(priv)->unit = 0x18001000; + nv_subdev(priv)->intr = nve0_graph_intr; + nv_engine(priv)->cclass = &nve0_graph_cclass; + nv_engine(priv)->sclass = nve0_graph_sclass; + + nv_info(priv, "using external firmware\n"); + if (nvc0_graph_ctor_fw(priv, "fuc409c", &priv->fuc409c) || + nvc0_graph_ctor_fw(priv, "fuc409d", &priv->fuc409d) || + nvc0_graph_ctor_fw(priv, "fuc41ac", &priv->fuc41ac) || + nvc0_graph_ctor_fw(priv, "fuc41ad", &priv->fuc41ad)) + return -EINVAL; + priv->firmware = true; + + ret = nouveau_gpuobj_new(parent, NULL, 0x1000, 256, 0, &priv->unk4188b4); + if (ret) + return ret; + + ret = nouveau_gpuobj_new(parent, NULL, 0x1000, 256, 0, &priv->unk4188b8); + if (ret) + return ret; + + for (i = 0; i < 0x1000; i += 4) { + nv_wo32(priv->unk4188b4, i, 0x00000010); + nv_wo32(priv->unk4188b8, i, 0x00000010); + } + + priv->gpc_nr = nv_rd32(priv, 0x409604) & 0x0000001f; + priv->rop_nr = (nv_rd32(priv, 0x409604) & 0x001f0000) >> 16; + for (i = 0; i < priv->gpc_nr; i++) { + priv->tpc_nr[i] = nv_rd32(priv, GPC_UNIT(i, 0x2608)); + priv->tpc_total += priv->tpc_nr[i]; + } + + switch (nv_device(priv)->chipset) { + case 0xe4: + if (priv->tpc_total == 8) + priv->magic_not_rop_nr = 3; + else + if (priv->tpc_total == 7) + priv->magic_not_rop_nr = 1; + break; + case 0xe7: + priv->magic_not_rop_nr = 1; + break; + default: + break; + } + return 0; } static void -nve0_graph_init_obj418880(struct drm_device *dev) +nve0_graph_init_obj418880(struct nvc0_graph_priv *priv) { - struct nvc0_graph_priv *priv = nv_engine(dev, NVOBJ_ENGINE_GR); int i; - nv_wr32(dev, GPC_BCAST(0x0880), 0x00000000); - nv_wr32(dev, GPC_BCAST(0x08a4), 0x00000000); + nv_wr32(priv, GPC_BCAST(0x0880), 0x00000000); + nv_wr32(priv, GPC_BCAST(0x08a4), 0x00000000); for (i = 0; i < 4; i++) - nv_wr32(dev, GPC_BCAST(0x0888) + (i * 4), 0x00000000); - nv_wr32(dev, GPC_BCAST(0x08b4), priv->unk4188b4->addr >> 8); - nv_wr32(dev, GPC_BCAST(0x08b8), priv->unk4188b8->addr >> 8); + nv_wr32(priv, GPC_BCAST(0x0888) + (i * 4), 0x00000000); + nv_wr32(priv, GPC_BCAST(0x08b4), priv->unk4188b4->addr >> 8); + nv_wr32(priv, GPC_BCAST(0x08b8), priv->unk4188b8->addr >> 8); } static void -nve0_graph_init_regs(struct drm_device *dev) +nve0_graph_init_regs(struct nvc0_graph_priv *priv) { - nv_wr32(dev, 0x400080, 0x003083c2); - nv_wr32(dev, 0x400088, 0x0001ffe7); - nv_wr32(dev, 0x40008c, 0x00000000); - nv_wr32(dev, 0x400090, 0x00000030); - nv_wr32(dev, 0x40013c, 0x003901f7); - nv_wr32(dev, 0x400140, 0x00000100); - nv_wr32(dev, 0x400144, 0x00000000); - nv_wr32(dev, 0x400148, 0x00000110); - nv_wr32(dev, 0x400138, 0x00000000); - nv_wr32(dev, 0x400130, 0x00000000); - nv_wr32(dev, 0x400134, 0x00000000); - nv_wr32(dev, 0x400124, 0x00000002); + nv_wr32(priv, 0x400080, 0x003083c2); + nv_wr32(priv, 0x400088, 0x0001ffe7); + nv_wr32(priv, 0x40008c, 0x00000000); + nv_wr32(priv, 0x400090, 0x00000030); + nv_wr32(priv, 0x40013c, 0x003901f7); + nv_wr32(priv, 0x400140, 0x00000100); + nv_wr32(priv, 0x400144, 0x00000000); + nv_wr32(priv, 0x400148, 0x00000110); + nv_wr32(priv, 0x400138, 0x00000000); + nv_wr32(priv, 0x400130, 0x00000000); + nv_wr32(priv, 0x400134, 0x00000000); + nv_wr32(priv, 0x400124, 0x00000002); } static void -nve0_graph_init_units(struct drm_device *dev) +nve0_graph_init_units(struct nvc0_graph_priv *priv) { - nv_wr32(dev, 0x409ffc, 0x00000000); - nv_wr32(dev, 0x409c14, 0x00003e3e); - nv_wr32(dev, 0x409c24, 0x000f0000); - - nv_wr32(dev, 0x404000, 0xc0000000); - nv_wr32(dev, 0x404600, 0xc0000000); - nv_wr32(dev, 0x408030, 0xc0000000); - nv_wr32(dev, 0x404490, 0xc0000000); - nv_wr32(dev, 0x406018, 0xc0000000); - nv_wr32(dev, 0x407020, 0xc0000000); - nv_wr32(dev, 0x405840, 0xc0000000); - nv_wr32(dev, 0x405844, 0x00ffffff); - - nv_mask(dev, 0x419cc0, 0x00000008, 0x00000008); - nv_mask(dev, 0x419eb4, 0x00001000, 0x00001000); + nv_wr32(priv, 0x409ffc, 0x00000000); + nv_wr32(priv, 0x409c14, 0x00003e3e); + nv_wr32(priv, 0x409c24, 0x000f0000); + + nv_wr32(priv, 0x404000, 0xc0000000); + nv_wr32(priv, 0x404600, 0xc0000000); + nv_wr32(priv, 0x408030, 0xc0000000); + nv_wr32(priv, 0x404490, 0xc0000000); + nv_wr32(priv, 0x406018, 0xc0000000); + nv_wr32(priv, 0x407020, 0xc0000000); + nv_wr32(priv, 0x405840, 0xc0000000); + nv_wr32(priv, 0x405844, 0x00ffffff); + + nv_mask(priv, 0x419cc0, 0x00000008, 0x00000008); + nv_mask(priv, 0x419eb4, 0x00001000, 0x00001000); } static void -nve0_graph_init_gpc_0(struct drm_device *dev) +nve0_graph_init_gpc_0(struct nvc0_graph_priv *priv) { - struct nvc0_graph_priv *priv = nv_engine(dev, NVOBJ_ENGINE_GR); const u32 magicgpc918 = DIV_ROUND_UP(0x00800000, priv->tpc_total); u32 data[TPC_MAX / 8]; u8 tpcnr[GPC_MAX]; int i, gpc, tpc; - nv_wr32(dev, GPC_UNIT(0, 0x3018), 0x00000001); + nv_wr32(priv, GPC_UNIT(0, 0x3018), 0x00000001); memset(data, 0x00, sizeof(data)); memcpy(tpcnr, priv->tpc_nr, sizeof(priv->tpc_nr)); @@ -144,164 +318,143 @@ nve0_graph_init_gpc_0(struct drm_device *dev) data[i / 8] |= tpc << ((i % 8) * 4); } - nv_wr32(dev, GPC_BCAST(0x0980), data[0]); - nv_wr32(dev, GPC_BCAST(0x0984), data[1]); - nv_wr32(dev, GPC_BCAST(0x0988), data[2]); - nv_wr32(dev, GPC_BCAST(0x098c), data[3]); + nv_wr32(priv, GPC_BCAST(0x0980), data[0]); + nv_wr32(priv, GPC_BCAST(0x0984), data[1]); + nv_wr32(priv, GPC_BCAST(0x0988), data[2]); + nv_wr32(priv, GPC_BCAST(0x098c), data[3]); for (gpc = 0; gpc < priv->gpc_nr; gpc++) { - nv_wr32(dev, GPC_UNIT(gpc, 0x0914), priv->magic_not_rop_nr << 8 | + nv_wr32(priv, GPC_UNIT(gpc, 0x0914), priv->magic_not_rop_nr << 8 | priv->tpc_nr[gpc]); - nv_wr32(dev, GPC_UNIT(gpc, 0x0910), 0x00040000 | priv->tpc_total); - nv_wr32(dev, GPC_UNIT(gpc, 0x0918), magicgpc918); + nv_wr32(priv, GPC_UNIT(gpc, 0x0910), 0x00040000 | priv->tpc_total); + nv_wr32(priv, GPC_UNIT(gpc, 0x0918), magicgpc918); } - nv_wr32(dev, GPC_BCAST(0x1bd4), magicgpc918); - nv_wr32(dev, GPC_BCAST(0x08ac), nv_rd32(dev, 0x100800)); + nv_wr32(priv, GPC_BCAST(0x1bd4), magicgpc918); + nv_wr32(priv, GPC_BCAST(0x08ac), nv_rd32(priv, 0x100800)); } static void -nve0_graph_init_gpc_1(struct drm_device *dev) +nve0_graph_init_gpc_1(struct nvc0_graph_priv *priv) { - struct nvc0_graph_priv *priv = nv_engine(dev, NVOBJ_ENGINE_GR); int gpc, tpc; for (gpc = 0; gpc < priv->gpc_nr; gpc++) { - nv_wr32(dev, GPC_UNIT(gpc, 0x3038), 0xc0000000); - nv_wr32(dev, GPC_UNIT(gpc, 0x0420), 0xc0000000); - nv_wr32(dev, GPC_UNIT(gpc, 0x0900), 0xc0000000); - nv_wr32(dev, GPC_UNIT(gpc, 0x1028), 0xc0000000); - nv_wr32(dev, GPC_UNIT(gpc, 0x0824), 0xc0000000); + nv_wr32(priv, GPC_UNIT(gpc, 0x3038), 0xc0000000); + nv_wr32(priv, GPC_UNIT(gpc, 0x0420), 0xc0000000); + nv_wr32(priv, GPC_UNIT(gpc, 0x0900), 0xc0000000); + nv_wr32(priv, GPC_UNIT(gpc, 0x1028), 0xc0000000); + nv_wr32(priv, GPC_UNIT(gpc, 0x0824), 0xc0000000); for (tpc = 0; tpc < priv->tpc_nr[gpc]; tpc++) { - nv_wr32(dev, TPC_UNIT(gpc, tpc, 0x508), 0xffffffff); - nv_wr32(dev, TPC_UNIT(gpc, tpc, 0x50c), 0xffffffff); - nv_wr32(dev, TPC_UNIT(gpc, tpc, 0x224), 0xc0000000); - nv_wr32(dev, TPC_UNIT(gpc, tpc, 0x48c), 0xc0000000); - nv_wr32(dev, TPC_UNIT(gpc, tpc, 0x084), 0xc0000000); - nv_wr32(dev, TPC_UNIT(gpc, tpc, 0x644), 0x001ffffe); - nv_wr32(dev, TPC_UNIT(gpc, tpc, 0x64c), 0x0000000f); + nv_wr32(priv, TPC_UNIT(gpc, tpc, 0x508), 0xffffffff); + nv_wr32(priv, TPC_UNIT(gpc, tpc, 0x50c), 0xffffffff); + nv_wr32(priv, TPC_UNIT(gpc, tpc, 0x224), 0xc0000000); + nv_wr32(priv, TPC_UNIT(gpc, tpc, 0x48c), 0xc0000000); + nv_wr32(priv, TPC_UNIT(gpc, tpc, 0x084), 0xc0000000); + nv_wr32(priv, TPC_UNIT(gpc, tpc, 0x644), 0x001ffffe); + nv_wr32(priv, TPC_UNIT(gpc, tpc, 0x64c), 0x0000000f); } - nv_wr32(dev, GPC_UNIT(gpc, 0x2c90), 0xffffffff); - nv_wr32(dev, GPC_UNIT(gpc, 0x2c94), 0xffffffff); + nv_wr32(priv, GPC_UNIT(gpc, 0x2c90), 0xffffffff); + nv_wr32(priv, GPC_UNIT(gpc, 0x2c94), 0xffffffff); } } static void -nve0_graph_init_rop(struct drm_device *dev) +nve0_graph_init_rop(struct nvc0_graph_priv *priv) { - struct nvc0_graph_priv *priv = nv_engine(dev, NVOBJ_ENGINE_GR); int rop; for (rop = 0; rop < priv->rop_nr; rop++) { - nv_wr32(dev, ROP_UNIT(rop, 0x144), 0xc0000000); - nv_wr32(dev, ROP_UNIT(rop, 0x070), 0xc0000000); - nv_wr32(dev, ROP_UNIT(rop, 0x204), 0xffffffff); - nv_wr32(dev, ROP_UNIT(rop, 0x208), 0xffffffff); - } -} - -static void -nve0_graph_init_fuc(struct drm_device *dev, u32 fuc_base, - struct nvc0_graph_fuc *code, struct nvc0_graph_fuc *data) -{ - int i; - - nv_wr32(dev, fuc_base + 0x01c0, 0x01000000); - for (i = 0; i < data->size / 4; i++) - nv_wr32(dev, fuc_base + 0x01c4, data->data[i]); - - nv_wr32(dev, fuc_base + 0x0180, 0x01000000); - for (i = 0; i < code->size / 4; i++) { - if ((i & 0x3f) == 0) - nv_wr32(dev, fuc_base + 0x0188, i >> 6); - nv_wr32(dev, fuc_base + 0x0184, code->data[i]); + nv_wr32(priv, ROP_UNIT(rop, 0x144), 0xc0000000); + nv_wr32(priv, ROP_UNIT(rop, 0x070), 0xc0000000); + nv_wr32(priv, ROP_UNIT(rop, 0x204), 0xffffffff); + nv_wr32(priv, ROP_UNIT(rop, 0x208), 0xffffffff); } } static int -nve0_graph_init_ctxctl(struct drm_device *dev) +nve0_graph_init_ctxctl(struct nvc0_graph_priv *priv) { - struct nvc0_graph_priv *priv = nv_engine(dev, NVOBJ_ENGINE_GR); u32 r000260; /* load fuc microcode */ - r000260 = nv_mask(dev, 0x000260, 0x00000001, 0x00000000); - nve0_graph_init_fuc(dev, 0x409000, &priv->fuc409c, &priv->fuc409d); - nve0_graph_init_fuc(dev, 0x41a000, &priv->fuc41ac, &priv->fuc41ad); - nv_wr32(dev, 0x000260, r000260); + r000260 = nv_mask(priv, 0x000260, 0x00000001, 0x00000000); + nvc0_graph_init_fw(priv, 0x409000, &priv->fuc409c, &priv->fuc409d); + nvc0_graph_init_fw(priv, 0x41a000, &priv->fuc41ac, &priv->fuc41ad); + nv_wr32(priv, 0x000260, r000260); /* start both of them running */ - nv_wr32(dev, 0x409840, 0xffffffff); - nv_wr32(dev, 0x41a10c, 0x00000000); - nv_wr32(dev, 0x40910c, 0x00000000); - nv_wr32(dev, 0x41a100, 0x00000002); - nv_wr32(dev, 0x409100, 0x00000002); - if (!nv_wait(dev, 0x409800, 0x00000001, 0x00000001)) - NV_INFO(dev, "0x409800 wait failed\n"); - - nv_wr32(dev, 0x409840, 0xffffffff); - nv_wr32(dev, 0x409500, 0x7fffffff); - nv_wr32(dev, 0x409504, 0x00000021); - - nv_wr32(dev, 0x409840, 0xffffffff); - nv_wr32(dev, 0x409500, 0x00000000); - nv_wr32(dev, 0x409504, 0x00000010); - if (!nv_wait_ne(dev, 0x409800, 0xffffffff, 0x00000000)) { - NV_ERROR(dev, "fuc09 req 0x10 timeout\n"); + nv_wr32(priv, 0x409840, 0xffffffff); + nv_wr32(priv, 0x41a10c, 0x00000000); + nv_wr32(priv, 0x40910c, 0x00000000); + nv_wr32(priv, 0x41a100, 0x00000002); + nv_wr32(priv, 0x409100, 0x00000002); + if (!nv_wait(priv, 0x409800, 0x00000001, 0x00000001)) + nv_error(priv, "0x409800 wait failed\n"); + + nv_wr32(priv, 0x409840, 0xffffffff); + nv_wr32(priv, 0x409500, 0x7fffffff); + nv_wr32(priv, 0x409504, 0x00000021); + + nv_wr32(priv, 0x409840, 0xffffffff); + nv_wr32(priv, 0x409500, 0x00000000); + nv_wr32(priv, 0x409504, 0x00000010); + if (!nv_wait_ne(priv, 0x409800, 0xffffffff, 0x00000000)) { + nv_error(priv, "fuc09 req 0x10 timeout\n"); return -EBUSY; } - priv->size = nv_rd32(dev, 0x409800); + priv->size = nv_rd32(priv, 0x409800); - nv_wr32(dev, 0x409840, 0xffffffff); - nv_wr32(dev, 0x409500, 0x00000000); - nv_wr32(dev, 0x409504, 0x00000016); - if (!nv_wait_ne(dev, 0x409800, 0xffffffff, 0x00000000)) { - NV_ERROR(dev, "fuc09 req 0x16 timeout\n"); + nv_wr32(priv, 0x409840, 0xffffffff); + nv_wr32(priv, 0x409500, 0x00000000); + nv_wr32(priv, 0x409504, 0x00000016); + if (!nv_wait_ne(priv, 0x409800, 0xffffffff, 0x00000000)) { + nv_error(priv, "fuc09 req 0x16 timeout\n"); return -EBUSY; } - nv_wr32(dev, 0x409840, 0xffffffff); - nv_wr32(dev, 0x409500, 0x00000000); - nv_wr32(dev, 0x409504, 0x00000025); - if (!nv_wait_ne(dev, 0x409800, 0xffffffff, 0x00000000)) { - NV_ERROR(dev, "fuc09 req 0x25 timeout\n"); + nv_wr32(priv, 0x409840, 0xffffffff); + nv_wr32(priv, 0x409500, 0x00000000); + nv_wr32(priv, 0x409504, 0x00000025); + if (!nv_wait_ne(priv, 0x409800, 0xffffffff, 0x00000000)) { + nv_error(priv, "fuc09 req 0x25 timeout\n"); return -EBUSY; } - nv_wr32(dev, 0x409800, 0x00000000); - nv_wr32(dev, 0x409500, 0x00000001); - nv_wr32(dev, 0x409504, 0x00000030); - if (!nv_wait_ne(dev, 0x409800, 0xffffffff, 0x00000000)) { - NV_ERROR(dev, "fuc09 req 0x30 timeout\n"); + nv_wr32(priv, 0x409800, 0x00000000); + nv_wr32(priv, 0x409500, 0x00000001); + nv_wr32(priv, 0x409504, 0x00000030); + if (!nv_wait_ne(priv, 0x409800, 0xffffffff, 0x00000000)) { + nv_error(priv, "fuc09 req 0x30 timeout\n"); return -EBUSY; } - nv_wr32(dev, 0x409810, 0xb00095c8); - nv_wr32(dev, 0x409800, 0x00000000); - nv_wr32(dev, 0x409500, 0x00000001); - nv_wr32(dev, 0x409504, 0x00000031); - if (!nv_wait_ne(dev, 0x409800, 0xffffffff, 0x00000000)) { - NV_ERROR(dev, "fuc09 req 0x31 timeout\n"); + nv_wr32(priv, 0x409810, 0xb00095c8); + nv_wr32(priv, 0x409800, 0x00000000); + nv_wr32(priv, 0x409500, 0x00000001); + nv_wr32(priv, 0x409504, 0x00000031); + if (!nv_wait_ne(priv, 0x409800, 0xffffffff, 0x00000000)) { + nv_error(priv, "fuc09 req 0x31 timeout\n"); return -EBUSY; } - nv_wr32(dev, 0x409810, 0x00080420); - nv_wr32(dev, 0x409800, 0x00000000); - nv_wr32(dev, 0x409500, 0x00000001); - nv_wr32(dev, 0x409504, 0x00000032); - if (!nv_wait_ne(dev, 0x409800, 0xffffffff, 0x00000000)) { - NV_ERROR(dev, "fuc09 req 0x32 timeout\n"); + nv_wr32(priv, 0x409810, 0x00080420); + nv_wr32(priv, 0x409800, 0x00000000); + nv_wr32(priv, 0x409500, 0x00000001); + nv_wr32(priv, 0x409504, 0x00000032); + if (!nv_wait_ne(priv, 0x409800, 0xffffffff, 0x00000000)) { + nv_error(priv, "fuc09 req 0x32 timeout\n"); return -EBUSY; } - nv_wr32(dev, 0x409614, 0x00000070); - nv_wr32(dev, 0x409614, 0x00000770); - nv_wr32(dev, 0x40802c, 0x00000001); + nv_wr32(priv, 0x409614, 0x00000070); + nv_wr32(priv, 0x409614, 0x00000770); + nv_wr32(priv, 0x40802c, 0x00000001); if (priv->data == NULL) { - int ret = nve0_grctx_generate(dev); + int ret = nve0_grctx_generate(priv); if (ret) { - NV_ERROR(dev, "PGRAPH: failed to construct context\n"); + nv_error(priv, "failed to construct context\n"); return ret; } @@ -312,325 +465,53 @@ nve0_graph_init_ctxctl(struct drm_device *dev) } static int -nve0_graph_init(struct drm_device *dev, int engine) +nve0_graph_init(struct nouveau_object *object) { + struct nvc0_graph_priv *priv = (void *)object; int ret; reset: - nv_mask(dev, 0x000200, 0x18001000, 0x00000000); - nv_mask(dev, 0x000200, 0x18001000, 0x18001000); - - nve0_graph_init_obj418880(dev); - nve0_graph_init_regs(dev); - nve0_graph_init_gpc_0(dev); - - nv_wr32(dev, 0x400500, 0x00010001); - nv_wr32(dev, 0x400100, 0xffffffff); - nv_wr32(dev, 0x40013c, 0xffffffff); - - nve0_graph_init_units(dev); - nve0_graph_init_gpc_1(dev); - nve0_graph_init_rop(dev); - - nv_wr32(dev, 0x400108, 0xffffffff); - nv_wr32(dev, 0x400138, 0xffffffff); - nv_wr32(dev, 0x400118, 0xffffffff); - nv_wr32(dev, 0x400130, 0xffffffff); - nv_wr32(dev, 0x40011c, 0xffffffff); - nv_wr32(dev, 0x400134, 0xffffffff); - nv_wr32(dev, 0x400054, 0x34ce3464); - - ret = nve0_graph_init_ctxctl(dev); - if (ret) { - if (ret == 1) - goto reset; - return ret; - } - - return 0; -} - -int -nve0_graph_isr_chid(struct drm_device *dev, u64 inst) -{ - struct nouveau_fifo_priv *pfifo = nv_engine(dev, NVOBJ_ENGINE_FIFO); - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_channel *chan; - unsigned long flags; - int i; - - spin_lock_irqsave(&dev_priv->channels.lock, flags); - for (i = 0; i < pfifo->channels; i++) { - chan = dev_priv->channels.ptr[i]; - if (!chan || !chan->ramin) - continue; - - if (inst == chan->ramin->addr) - break; - } - spin_unlock_irqrestore(&dev_priv->channels.lock, flags); - return i; -} - -static void -nve0_graph_ctxctl_isr(struct drm_device *dev) -{ - u32 ustat = nv_rd32(dev, 0x409c18); - - if (ustat & 0x00000001) - NV_INFO(dev, "PGRAPH: CTXCTRL ucode error\n"); - if (ustat & 0x00080000) - NV_INFO(dev, "PGRAPH: CTXCTRL watchdog timeout\n"); - if (ustat & ~0x00080001) - NV_INFO(dev, "PGRAPH: CTXCTRL 0x%08x\n", ustat); - - nve0_graph_ctxctl_debug(dev); - nv_wr32(dev, 0x409c20, ustat); -} - -static void -nve0_graph_trap_isr(struct drm_device *dev, int chid) -{ - struct nvc0_graph_priv *priv = nv_engine(dev, NVOBJ_ENGINE_GR); - u32 trap = nv_rd32(dev, 0x400108); - int rop; - - if (trap & 0x00000001) { - u32 stat = nv_rd32(dev, 0x404000); - NV_INFO(dev, "PGRAPH: DISPATCH ch %d 0x%08x\n", chid, stat); - nv_wr32(dev, 0x404000, 0xc0000000); - nv_wr32(dev, 0x400108, 0x00000001); - trap &= ~0x00000001; - } - - if (trap & 0x00000010) { - u32 stat = nv_rd32(dev, 0x405840); - NV_INFO(dev, "PGRAPH: SHADER ch %d 0x%08x\n", chid, stat); - nv_wr32(dev, 0x405840, 0xc0000000); - nv_wr32(dev, 0x400108, 0x00000010); - trap &= ~0x00000010; - } - - if (trap & 0x02000000) { - for (rop = 0; rop < priv->rop_nr; rop++) { - u32 statz = nv_rd32(dev, ROP_UNIT(rop, 0x070)); - u32 statc = nv_rd32(dev, ROP_UNIT(rop, 0x144)); - NV_INFO(dev, "PGRAPH: ROP%d ch %d 0x%08x 0x%08x\n", - rop, chid, statz, statc); - nv_wr32(dev, ROP_UNIT(rop, 0x070), 0xc0000000); - nv_wr32(dev, ROP_UNIT(rop, 0x144), 0xc0000000); - } - nv_wr32(dev, 0x400108, 0x02000000); - trap &= ~0x02000000; - } - - if (trap) { - NV_INFO(dev, "PGRAPH: TRAP ch %d 0x%08x\n", chid, trap); - nv_wr32(dev, 0x400108, trap); - } -} - -static void -nve0_graph_isr(struct drm_device *dev) -{ - u64 inst = (u64)(nv_rd32(dev, 0x409b00) & 0x0fffffff) << 12; - u32 chid = nve0_graph_isr_chid(dev, inst); - u32 stat = nv_rd32(dev, 0x400100); - u32 addr = nv_rd32(dev, 0x400704); - u32 mthd = (addr & 0x00003ffc); - u32 subc = (addr & 0x00070000) >> 16; - u32 data = nv_rd32(dev, 0x400708); - u32 code = nv_rd32(dev, 0x400110); - u32 class = nv_rd32(dev, 0x404200 + (subc * 4)); - - if (stat & 0x00000010) { - if (nouveau_gpuobj_mthd_call2(dev, chid, class, mthd, data)) { - NV_INFO(dev, "PGRAPH: ILLEGAL_MTHD ch %d [0x%010llx] " - "subc %d class 0x%04x mthd 0x%04x " - "data 0x%08x\n", - chid, inst, subc, class, mthd, data); - } - nv_wr32(dev, 0x400100, 0x00000010); - stat &= ~0x00000010; - } - - if (stat & 0x00000020) { - NV_INFO(dev, "PGRAPH: ILLEGAL_CLASS ch %d [0x%010llx] subc %d " - "class 0x%04x mthd 0x%04x data 0x%08x\n", - chid, inst, subc, class, mthd, data); - nv_wr32(dev, 0x400100, 0x00000020); - stat &= ~0x00000020; - } - - if (stat & 0x00100000) { - NV_INFO(dev, "PGRAPH: DATA_ERROR ["); - nouveau_enum_print(nv50_data_error_names, code); - printk("] ch %d [0x%010llx] subc %d class 0x%04x " - "mthd 0x%04x data 0x%08x\n", - chid, inst, subc, class, mthd, data); - nv_wr32(dev, 0x400100, 0x00100000); - stat &= ~0x00100000; - } - - if (stat & 0x00200000) { - nve0_graph_trap_isr(dev, chid); - nv_wr32(dev, 0x400100, 0x00200000); - stat &= ~0x00200000; - } - - if (stat & 0x00080000) { - nve0_graph_ctxctl_isr(dev); - nv_wr32(dev, 0x400100, 0x00080000); - stat &= ~0x00080000; - } - - if (stat) { - NV_INFO(dev, "PGRAPH: unknown stat 0x%08x\n", stat); - nv_wr32(dev, 0x400100, stat); - } - - nv_wr32(dev, 0x400500, 0x00010001); -} - -static int -nve0_graph_create_fw(struct drm_device *dev, const char *fwname, - struct nvc0_graph_fuc *fuc) -{ - struct drm_nouveau_private *dev_priv = dev->dev_private; - const struct firmware *fw; - char f[32]; - int ret; - - snprintf(f, sizeof(f), "nouveau/nv%02x_%s", dev_priv->chipset, fwname); - ret = request_firmware(&fw, f, &dev->pdev->dev); + ret = nouveau_graph_init(&priv->base); if (ret) return ret; - fuc->size = fw->size; - fuc->data = kmemdup(fw->data, fuc->size, GFP_KERNEL); - release_firmware(fw); - return (fuc->data != NULL) ? 0 : -ENOMEM; -} - -static void -nve0_graph_destroy_fw(struct nvc0_graph_fuc *fuc) -{ - if (fuc->data) { - kfree(fuc->data); - fuc->data = NULL; - } -} - -static void -nve0_graph_destroy(struct drm_device *dev, int engine) -{ - struct nvc0_graph_priv *priv = nv_engine(dev, engine); - - nve0_graph_destroy_fw(&priv->fuc409c); - nve0_graph_destroy_fw(&priv->fuc409d); - nve0_graph_destroy_fw(&priv->fuc41ac); - nve0_graph_destroy_fw(&priv->fuc41ad); - - nouveau_irq_unregister(dev, 12); - - nouveau_gpuobj_ref(NULL, &priv->unk4188b8); - nouveau_gpuobj_ref(NULL, &priv->unk4188b4); - - if (priv->data) - kfree(priv->data); - - NVOBJ_ENGINE_DEL(dev, GR); - kfree(priv); -} - -int -nve0_graph_create(struct drm_device *dev) -{ - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nvc0_graph_priv *priv; - int ret, gpc, i; - u32 kepler; - - kepler = nvc0_graph_class(dev); - if (!kepler) { - NV_ERROR(dev, "PGRAPH: unsupported chipset, please report!\n"); - return 0; - } - - priv = kzalloc(sizeof(*priv), GFP_KERNEL); - if (!priv) - return -ENOMEM; - - priv->base.destroy = nve0_graph_destroy; - priv->base.init = nve0_graph_init; - priv->base.fini = nve0_graph_fini; - priv->base.context_new = nvc0_graph_context_new; - priv->base.context_del = nvc0_graph_context_del; - priv->base.object_new = nve0_graph_object_new; - - NVOBJ_ENGINE_ADD(dev, GR, &priv->base); - nouveau_irq_register(dev, 12, nve0_graph_isr); - - NV_INFO(dev, "PGRAPH: using external firmware\n"); - if (nve0_graph_create_fw(dev, "fuc409c", &priv->fuc409c) || - nve0_graph_create_fw(dev, "fuc409d", &priv->fuc409d) || - nve0_graph_create_fw(dev, "fuc41ac", &priv->fuc41ac) || - nve0_graph_create_fw(dev, "fuc41ad", &priv->fuc41ad)) { - ret = 0; - goto error; - } - priv->firmware = true; - - ret = nouveau_gpuobj_new(dev, NULL, 0x1000, 256, 0, &priv->unk4188b4); - if (ret) - goto error; + nve0_graph_init_obj418880(priv); + nve0_graph_init_regs(priv); + nve0_graph_init_gpc_0(priv); - ret = nouveau_gpuobj_new(dev, NULL, 0x1000, 256, 0, &priv->unk4188b8); - if (ret) - goto error; + nv_wr32(priv, 0x400500, 0x00010001); + nv_wr32(priv, 0x400100, 0xffffffff); + nv_wr32(priv, 0x40013c, 0xffffffff); - for (i = 0; i < 0x1000; i += 4) { - nv_wo32(priv->unk4188b4, i, 0x00000010); - nv_wo32(priv->unk4188b8, i, 0x00000010); - } + nve0_graph_init_units(priv); + nve0_graph_init_gpc_1(priv); + nve0_graph_init_rop(priv); - priv->gpc_nr = nv_rd32(dev, 0x409604) & 0x0000001f; - priv->rop_nr = (nv_rd32(dev, 0x409604) & 0x001f0000) >> 16; - for (gpc = 0; gpc < priv->gpc_nr; gpc++) { - priv->tpc_nr[gpc] = nv_rd32(dev, GPC_UNIT(gpc, 0x2608)); - priv->tpc_total += priv->tpc_nr[gpc]; - } - - switch (dev_priv->chipset) { - case 0xe4: - if (priv->tpc_total == 8) - priv->magic_not_rop_nr = 3; - else - if (priv->tpc_total == 7) - priv->magic_not_rop_nr = 1; - break; - case 0xe7: - priv->magic_not_rop_nr = 1; - break; - default: - break; - } + nv_wr32(priv, 0x400108, 0xffffffff); + nv_wr32(priv, 0x400138, 0xffffffff); + nv_wr32(priv, 0x400118, 0xffffffff); + nv_wr32(priv, 0x400130, 0xffffffff); + nv_wr32(priv, 0x40011c, 0xffffffff); + nv_wr32(priv, 0x400134, 0xffffffff); + nv_wr32(priv, 0x400054, 0x34ce3464); - if (!priv->magic_not_rop_nr) { - NV_ERROR(dev, "PGRAPH: unknown config: %d/%d/%d/%d, %d\n", - priv->tpc_nr[0], priv->tpc_nr[1], priv->tpc_nr[2], - priv->tpc_nr[3], priv->rop_nr); - priv->magic_not_rop_nr = 0x00; + ret = nve0_graph_init_ctxctl(priv); + if (ret) { + if (ret == 1) + goto reset; + return ret; } - NVOBJ_CLASS(dev, 0xa097, GR); /* subc 0: 3D */ - NVOBJ_CLASS(dev, 0xa0c0, GR); /* subc 1: COMPUTE */ - NVOBJ_CLASS(dev, 0xa040, GR); /* subc 2: P2MF */ - NVOBJ_CLASS(dev, 0x902d, GR); /* subc 3: 2D */ - NVOBJ_CLASS(dev, 0xa0b5, GR); /* subc 4: COPY */ return 0; - -error: - nve0_graph_destroy(dev, NVOBJ_ENGINE_GR); - return ret; } + +struct nouveau_oclass +nve0_graph_oclass = { + .handle = NV_ENGINE(GR, 0xe0), + .ofuncs = &(struct nouveau_ofuncs) { + .ctor = nve0_graph_ctor, + .dtor = nvc0_graph_dtor, + .init = nve0_graph_init, + .fini = _nouveau_graph_fini, + }, +}; diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/regs.h b/drivers/gpu/drm/nouveau/core/engine/graph/regs.h new file mode 100644 index 000000000000..9c715a25cecb --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/engine/graph/regs.h @@ -0,0 +1,269 @@ +#ifndef __NOUVEAU_GRAPH_REGS_H__ +#define __NOUVEAU_GRAPH_REGS_H__ + +#define NV04_PGRAPH_DEBUG_0 0x00400080 +#define NV04_PGRAPH_DEBUG_1 0x00400084 +#define NV04_PGRAPH_DEBUG_2 0x00400088 +#define NV04_PGRAPH_DEBUG_3 0x0040008c +#define NV10_PGRAPH_DEBUG_4 0x00400090 +#define NV03_PGRAPH_INTR 0x00400100 +#define NV03_PGRAPH_NSTATUS 0x00400104 +# define NV04_PGRAPH_NSTATUS_STATE_IN_USE (1<<11) +# define NV04_PGRAPH_NSTATUS_INVALID_STATE (1<<12) +# define NV04_PGRAPH_NSTATUS_BAD_ARGUMENT (1<<13) +# define NV04_PGRAPH_NSTATUS_PROTECTION_FAULT (1<<14) +# define NV10_PGRAPH_NSTATUS_STATE_IN_USE (1<<23) +# define NV10_PGRAPH_NSTATUS_INVALID_STATE (1<<24) +# define NV10_PGRAPH_NSTATUS_BAD_ARGUMENT (1<<25) +# define NV10_PGRAPH_NSTATUS_PROTECTION_FAULT (1<<26) +#define NV03_PGRAPH_NSOURCE 0x00400108 +# define NV03_PGRAPH_NSOURCE_NOTIFICATION (1<<0) +# define NV03_PGRAPH_NSOURCE_DATA_ERROR (1<<1) +# define NV03_PGRAPH_NSOURCE_PROTECTION_ERROR (1<<2) +# define NV03_PGRAPH_NSOURCE_RANGE_EXCEPTION (1<<3) +# define NV03_PGRAPH_NSOURCE_LIMIT_COLOR (1<<4) +# define NV03_PGRAPH_NSOURCE_LIMIT_ZETA (1<<5) +# define NV03_PGRAPH_NSOURCE_ILLEGAL_MTHD (1<<6) +# define NV03_PGRAPH_NSOURCE_DMA_R_PROTECTION (1<<7) +# define NV03_PGRAPH_NSOURCE_DMA_W_PROTECTION (1<<8) +# define NV03_PGRAPH_NSOURCE_FORMAT_EXCEPTION (1<<9) +# define NV03_PGRAPH_NSOURCE_PATCH_EXCEPTION (1<<10) +# define NV03_PGRAPH_NSOURCE_STATE_INVALID (1<<11) +# define NV03_PGRAPH_NSOURCE_DOUBLE_NOTIFY (1<<12) +# define NV03_PGRAPH_NSOURCE_NOTIFY_IN_USE (1<<13) +# define NV03_PGRAPH_NSOURCE_METHOD_CNT (1<<14) +# define NV03_PGRAPH_NSOURCE_BFR_NOTIFICATION (1<<15) +# define NV03_PGRAPH_NSOURCE_DMA_VTX_PROTECTION (1<<16) +# define NV03_PGRAPH_NSOURCE_DMA_WIDTH_A (1<<17) +# define NV03_PGRAPH_NSOURCE_DMA_WIDTH_B (1<<18) +#define NV03_PGRAPH_INTR_EN 0x00400140 +#define NV40_PGRAPH_INTR_EN 0x0040013C +# define NV_PGRAPH_INTR_NOTIFY (1<<0) +# define NV_PGRAPH_INTR_MISSING_HW (1<<4) +# define NV_PGRAPH_INTR_CONTEXT_SWITCH (1<<12) +# define NV_PGRAPH_INTR_BUFFER_NOTIFY (1<<16) +# define NV_PGRAPH_INTR_ERROR (1<<20) +#define NV10_PGRAPH_CTX_CONTROL 0x00400144 +#define NV10_PGRAPH_CTX_USER 0x00400148 +#define NV10_PGRAPH_CTX_SWITCH(i) (0x0040014C + 0x4*(i)) +#define NV04_PGRAPH_CTX_SWITCH1 0x00400160 +#define NV10_PGRAPH_CTX_CACHE(i, j) (0x00400160 \ + + 0x4*(i) + 0x20*(j)) +#define NV04_PGRAPH_CTX_SWITCH2 0x00400164 +#define NV04_PGRAPH_CTX_SWITCH3 0x00400168 +#define NV04_PGRAPH_CTX_SWITCH4 0x0040016C +#define NV04_PGRAPH_CTX_CONTROL 0x00400170 +#define NV04_PGRAPH_CTX_USER 0x00400174 +#define NV04_PGRAPH_CTX_CACHE1 0x00400180 +#define NV03_PGRAPH_CTX_CONTROL 0x00400190 +#define NV03_PGRAPH_CTX_USER 0x00400194 +#define NV04_PGRAPH_CTX_CACHE2 0x004001A0 +#define NV04_PGRAPH_CTX_CACHE3 0x004001C0 +#define NV04_PGRAPH_CTX_CACHE4 0x004001E0 +#define NV40_PGRAPH_CTXCTL_0304 0x00400304 +#define NV40_PGRAPH_CTXCTL_0304_XFER_CTX 0x00000001 +#define NV40_PGRAPH_CTXCTL_UCODE_STAT 0x00400308 +#define NV40_PGRAPH_CTXCTL_UCODE_STAT_IP_MASK 0xff000000 +#define NV40_PGRAPH_CTXCTL_UCODE_STAT_IP_SHIFT 24 +#define NV40_PGRAPH_CTXCTL_UCODE_STAT_OP_MASK 0x00ffffff +#define NV40_PGRAPH_CTXCTL_0310 0x00400310 +#define NV40_PGRAPH_CTXCTL_0310_XFER_SAVE 0x00000020 +#define NV40_PGRAPH_CTXCTL_0310_XFER_LOAD 0x00000040 +#define NV40_PGRAPH_CTXCTL_030C 0x0040030c +#define NV40_PGRAPH_CTXCTL_UCODE_INDEX 0x00400324 +#define NV40_PGRAPH_CTXCTL_UCODE_DATA 0x00400328 +#define NV40_PGRAPH_CTXCTL_CUR 0x0040032c +#define NV40_PGRAPH_CTXCTL_CUR_LOADED 0x01000000 +#define NV40_PGRAPH_CTXCTL_CUR_INSTANCE 0x000FFFFF +#define NV40_PGRAPH_CTXCTL_NEXT 0x00400330 +#define NV40_PGRAPH_CTXCTL_NEXT_INSTANCE 0x000fffff +#define NV50_PGRAPH_CTXCTL_CUR 0x0040032c +#define NV50_PGRAPH_CTXCTL_CUR_LOADED 0x80000000 +#define NV50_PGRAPH_CTXCTL_CUR_INSTANCE 0x00ffffff +#define NV50_PGRAPH_CTXCTL_NEXT 0x00400330 +#define NV50_PGRAPH_CTXCTL_NEXT_INSTANCE 0x00ffffff +#define NV03_PGRAPH_ABS_X_RAM 0x00400400 +#define NV03_PGRAPH_ABS_Y_RAM 0x00400480 +#define NV03_PGRAPH_X_MISC 0x00400500 +#define NV03_PGRAPH_Y_MISC 0x00400504 +#define NV04_PGRAPH_VALID1 0x00400508 +#define NV04_PGRAPH_SOURCE_COLOR 0x0040050C +#define NV04_PGRAPH_MISC24_0 0x00400510 +#define NV03_PGRAPH_XY_LOGIC_MISC0 0x00400514 +#define NV03_PGRAPH_XY_LOGIC_MISC1 0x00400518 +#define NV03_PGRAPH_XY_LOGIC_MISC2 0x0040051C +#define NV03_PGRAPH_XY_LOGIC_MISC3 0x00400520 +#define NV03_PGRAPH_CLIPX_0 0x00400524 +#define NV03_PGRAPH_CLIPX_1 0x00400528 +#define NV03_PGRAPH_CLIPY_0 0x0040052C +#define NV03_PGRAPH_CLIPY_1 0x00400530 +#define NV03_PGRAPH_ABS_ICLIP_XMAX 0x00400534 +#define NV03_PGRAPH_ABS_ICLIP_YMAX 0x00400538 +#define NV03_PGRAPH_ABS_UCLIP_XMIN 0x0040053C +#define NV03_PGRAPH_ABS_UCLIP_YMIN 0x00400540 +#define NV03_PGRAPH_ABS_UCLIP_XMAX 0x00400544 +#define NV03_PGRAPH_ABS_UCLIP_YMAX 0x00400548 +#define NV03_PGRAPH_ABS_UCLIPA_XMIN 0x00400560 +#define NV03_PGRAPH_ABS_UCLIPA_YMIN 0x00400564 +#define NV03_PGRAPH_ABS_UCLIPA_XMAX 0x00400568 +#define NV03_PGRAPH_ABS_UCLIPA_YMAX 0x0040056C +#define NV04_PGRAPH_MISC24_1 0x00400570 +#define NV04_PGRAPH_MISC24_2 0x00400574 +#define NV04_PGRAPH_VALID2 0x00400578 +#define NV04_PGRAPH_PASSTHRU_0 0x0040057C +#define NV04_PGRAPH_PASSTHRU_1 0x00400580 +#define NV04_PGRAPH_PASSTHRU_2 0x00400584 +#define NV10_PGRAPH_DIMX_TEXTURE 0x00400588 +#define NV10_PGRAPH_WDIMX_TEXTURE 0x0040058C +#define NV04_PGRAPH_COMBINE_0_ALPHA 0x00400590 +#define NV04_PGRAPH_COMBINE_0_COLOR 0x00400594 +#define NV04_PGRAPH_COMBINE_1_ALPHA 0x00400598 +#define NV04_PGRAPH_COMBINE_1_COLOR 0x0040059C +#define NV04_PGRAPH_FORMAT_0 0x004005A8 +#define NV04_PGRAPH_FORMAT_1 0x004005AC +#define NV04_PGRAPH_FILTER_0 0x004005B0 +#define NV04_PGRAPH_FILTER_1 0x004005B4 +#define NV03_PGRAPH_MONO_COLOR0 0x00400600 +#define NV04_PGRAPH_ROP3 0x00400604 +#define NV04_PGRAPH_BETA_AND 0x00400608 +#define NV04_PGRAPH_BETA_PREMULT 0x0040060C +#define NV04_PGRAPH_LIMIT_VIOL_PIX 0x00400610 +#define NV04_PGRAPH_FORMATS 0x00400618 +#define NV10_PGRAPH_DEBUG_2 0x00400620 +#define NV04_PGRAPH_BOFFSET0 0x00400640 +#define NV04_PGRAPH_BOFFSET1 0x00400644 +#define NV04_PGRAPH_BOFFSET2 0x00400648 +#define NV04_PGRAPH_BOFFSET3 0x0040064C +#define NV04_PGRAPH_BOFFSET4 0x00400650 +#define NV04_PGRAPH_BOFFSET5 0x00400654 +#define NV04_PGRAPH_BBASE0 0x00400658 +#define NV04_PGRAPH_BBASE1 0x0040065C +#define NV04_PGRAPH_BBASE2 0x00400660 +#define NV04_PGRAPH_BBASE3 0x00400664 +#define NV04_PGRAPH_BBASE4 0x00400668 +#define NV04_PGRAPH_BBASE5 0x0040066C +#define NV04_PGRAPH_BPITCH0 0x00400670 +#define NV04_PGRAPH_BPITCH1 0x00400674 +#define NV04_PGRAPH_BPITCH2 0x00400678 +#define NV04_PGRAPH_BPITCH3 0x0040067C +#define NV04_PGRAPH_BPITCH4 0x00400680 +#define NV04_PGRAPH_BLIMIT0 0x00400684 +#define NV04_PGRAPH_BLIMIT1 0x00400688 +#define NV04_PGRAPH_BLIMIT2 0x0040068C +#define NV04_PGRAPH_BLIMIT3 0x00400690 +#define NV04_PGRAPH_BLIMIT4 0x00400694 +#define NV04_PGRAPH_BLIMIT5 0x00400698 +#define NV04_PGRAPH_BSWIZZLE2 0x0040069C +#define NV04_PGRAPH_BSWIZZLE5 0x004006A0 +#define NV03_PGRAPH_STATUS 0x004006B0 +#define NV04_PGRAPH_STATUS 0x00400700 +# define NV40_PGRAPH_STATUS_SYNC_STALL 0x00004000 +#define NV04_PGRAPH_TRAPPED_ADDR 0x00400704 +#define NV04_PGRAPH_TRAPPED_DATA 0x00400708 +#define NV04_PGRAPH_SURFACE 0x0040070C +#define NV10_PGRAPH_TRAPPED_DATA_HIGH 0x0040070C +#define NV04_PGRAPH_STATE 0x00400710 +#define NV10_PGRAPH_SURFACE 0x00400710 +#define NV04_PGRAPH_NOTIFY 0x00400714 +#define NV10_PGRAPH_STATE 0x00400714 +#define NV10_PGRAPH_NOTIFY 0x00400718 + +#define NV04_PGRAPH_FIFO 0x00400720 + +#define NV04_PGRAPH_BPIXEL 0x00400724 +#define NV10_PGRAPH_RDI_INDEX 0x00400750 +#define NV04_PGRAPH_FFINTFC_ST2 0x00400754 +#define NV10_PGRAPH_RDI_DATA 0x00400754 +#define NV04_PGRAPH_DMA_PITCH 0x00400760 +#define NV10_PGRAPH_FFINTFC_FIFO_PTR 0x00400760 +#define NV04_PGRAPH_DVD_COLORFMT 0x00400764 +#define NV10_PGRAPH_FFINTFC_ST2 0x00400764 +#define NV04_PGRAPH_SCALED_FORMAT 0x00400768 +#define NV10_PGRAPH_FFINTFC_ST2_DL 0x00400768 +#define NV10_PGRAPH_FFINTFC_ST2_DH 0x0040076c +#define NV10_PGRAPH_DMA_PITCH 0x00400770 +#define NV10_PGRAPH_DVD_COLORFMT 0x00400774 +#define NV10_PGRAPH_SCALED_FORMAT 0x00400778 +#define NV20_PGRAPH_CHANNEL_CTX_TABLE 0x00400780 +#define NV20_PGRAPH_CHANNEL_CTX_POINTER 0x00400784 +#define NV20_PGRAPH_CHANNEL_CTX_XFER 0x00400788 +#define NV20_PGRAPH_CHANNEL_CTX_XFER_LOAD 0x00000001 +#define NV20_PGRAPH_CHANNEL_CTX_XFER_SAVE 0x00000002 +#define NV04_PGRAPH_PATT_COLOR0 0x00400800 +#define NV04_PGRAPH_PATT_COLOR1 0x00400804 +#define NV04_PGRAPH_PATTERN 0x00400808 +#define NV04_PGRAPH_PATTERN_SHAPE 0x00400810 +#define NV04_PGRAPH_CHROMA 0x00400814 +#define NV04_PGRAPH_CONTROL0 0x00400818 +#define NV04_PGRAPH_CONTROL1 0x0040081C +#define NV04_PGRAPH_CONTROL2 0x00400820 +#define NV04_PGRAPH_BLEND 0x00400824 +#define NV04_PGRAPH_STORED_FMT 0x00400830 +#define NV04_PGRAPH_PATT_COLORRAM 0x00400900 +#define NV20_PGRAPH_TILE(i) (0x00400900 + (i*16)) +#define NV20_PGRAPH_TLIMIT(i) (0x00400904 + (i*16)) +#define NV20_PGRAPH_TSIZE(i) (0x00400908 + (i*16)) +#define NV20_PGRAPH_TSTATUS(i) (0x0040090C + (i*16)) +#define NV20_PGRAPH_ZCOMP(i) (0x00400980 + 4*(i)) +#define NV10_PGRAPH_TILE(i) (0x00400B00 + (i*16)) +#define NV10_PGRAPH_TLIMIT(i) (0x00400B04 + (i*16)) +#define NV10_PGRAPH_TSIZE(i) (0x00400B08 + (i*16)) +#define NV10_PGRAPH_TSTATUS(i) (0x00400B0C + (i*16)) +#define NV04_PGRAPH_U_RAM 0x00400D00 +#define NV47_PGRAPH_TILE(i) (0x00400D00 + (i*16)) +#define NV47_PGRAPH_TLIMIT(i) (0x00400D04 + (i*16)) +#define NV47_PGRAPH_TSIZE(i) (0x00400D08 + (i*16)) +#define NV47_PGRAPH_TSTATUS(i) (0x00400D0C + (i*16)) +#define NV04_PGRAPH_V_RAM 0x00400D40 +#define NV04_PGRAPH_W_RAM 0x00400D80 +#define NV10_PGRAPH_COMBINER0_IN_ALPHA 0x00400E40 +#define NV10_PGRAPH_COMBINER1_IN_ALPHA 0x00400E44 +#define NV10_PGRAPH_COMBINER0_IN_RGB 0x00400E48 +#define NV10_PGRAPH_COMBINER1_IN_RGB 0x00400E4C +#define NV10_PGRAPH_COMBINER_COLOR0 0x00400E50 +#define NV10_PGRAPH_COMBINER_COLOR1 0x00400E54 +#define NV10_PGRAPH_COMBINER0_OUT_ALPHA 0x00400E58 +#define NV10_PGRAPH_COMBINER1_OUT_ALPHA 0x00400E5C +#define NV10_PGRAPH_COMBINER0_OUT_RGB 0x00400E60 +#define NV10_PGRAPH_COMBINER1_OUT_RGB 0x00400E64 +#define NV10_PGRAPH_COMBINER_FINAL0 0x00400E68 +#define NV10_PGRAPH_COMBINER_FINAL1 0x00400E6C +#define NV10_PGRAPH_WINDOWCLIP_HORIZONTAL 0x00400F00 +#define NV10_PGRAPH_WINDOWCLIP_VERTICAL 0x00400F20 +#define NV10_PGRAPH_XFMODE0 0x00400F40 +#define NV10_PGRAPH_XFMODE1 0x00400F44 +#define NV10_PGRAPH_GLOBALSTATE0 0x00400F48 +#define NV10_PGRAPH_GLOBALSTATE1 0x00400F4C +#define NV10_PGRAPH_PIPE_ADDRESS 0x00400F50 +#define NV10_PGRAPH_PIPE_DATA 0x00400F54 +#define NV04_PGRAPH_DMA_START_0 0x00401000 +#define NV04_PGRAPH_DMA_START_1 0x00401004 +#define NV04_PGRAPH_DMA_LENGTH 0x00401008 +#define NV04_PGRAPH_DMA_MISC 0x0040100C +#define NV04_PGRAPH_DMA_DATA_0 0x00401020 +#define NV04_PGRAPH_DMA_DATA_1 0x00401024 +#define NV04_PGRAPH_DMA_RM 0x00401030 +#define NV04_PGRAPH_DMA_A_XLATE_INST 0x00401040 +#define NV04_PGRAPH_DMA_A_CONTROL 0x00401044 +#define NV04_PGRAPH_DMA_A_LIMIT 0x00401048 +#define NV04_PGRAPH_DMA_A_TLB_PTE 0x0040104C +#define NV04_PGRAPH_DMA_A_TLB_TAG 0x00401050 +#define NV04_PGRAPH_DMA_A_ADJ_OFFSET 0x00401054 +#define NV04_PGRAPH_DMA_A_OFFSET 0x00401058 +#define NV04_PGRAPH_DMA_A_SIZE 0x0040105C +#define NV04_PGRAPH_DMA_A_Y_SIZE 0x00401060 +#define NV04_PGRAPH_DMA_B_XLATE_INST 0x00401080 +#define NV04_PGRAPH_DMA_B_CONTROL 0x00401084 +#define NV04_PGRAPH_DMA_B_LIMIT 0x00401088 +#define NV04_PGRAPH_DMA_B_TLB_PTE 0x0040108C +#define NV04_PGRAPH_DMA_B_TLB_TAG 0x00401090 +#define NV04_PGRAPH_DMA_B_ADJ_OFFSET 0x00401094 +#define NV04_PGRAPH_DMA_B_OFFSET 0x00401098 +#define NV04_PGRAPH_DMA_B_SIZE 0x0040109C +#define NV04_PGRAPH_DMA_B_Y_SIZE 0x004010A0 +#define NV40_PGRAPH_TILE1(i) (0x00406900 + (i*16)) +#define NV40_PGRAPH_TLIMIT1(i) (0x00406904 + (i*16)) +#define NV40_PGRAPH_TSIZE1(i) (0x00406908 + (i*16)) +#define NV40_PGRAPH_TSTATUS1(i) (0x0040690C + (i*16)) + +#endif diff --git a/drivers/gpu/drm/nouveau/core/engine/mpeg/nv31.c b/drivers/gpu/drm/nouveau/core/engine/mpeg/nv31.c index a0258c766850..7a1bc7641b58 100644 --- a/drivers/gpu/drm/nouveau/core/engine/mpeg/nv31.c +++ b/drivers/gpu/drm/nouveau/core/engine/mpeg/nv31.c @@ -1,5 +1,5 @@ /* - * Copyright 2011 Red Hat Inc. + * Copyright 2012 Red Hat Inc. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -22,159 +22,62 @@ * Authors: Ben Skeggs */ -#include "drmP.h" -#include "nouveau_drv.h" -#include -#include +#include +#include +#include +#include +#include -struct nv31_mpeg_engine { - struct nouveau_exec_engine base; - atomic_t refcount; -}; - - -static int -nv31_mpeg_context_new(struct nouveau_channel *chan, int engine) -{ - struct nv31_mpeg_engine *pmpeg = nv_engine(chan->dev, engine); - - if (!atomic_add_unless(&pmpeg->refcount, 1, 1)) - return -EBUSY; - - chan->engctx[engine] = (void *)0xdeadcafe; - return 0; -} - -static void -nv31_mpeg_context_del(struct nouveau_channel *chan, int engine) -{ - struct nv31_mpeg_engine *pmpeg = nv_engine(chan->dev, engine); - atomic_dec(&pmpeg->refcount); - chan->engctx[engine] = NULL; -} +#include +#include +#include -static int -nv40_mpeg_context_new(struct nouveau_channel *chan, int engine) -{ - struct drm_device *dev = chan->dev; - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_gpuobj *ctx = NULL; - unsigned long flags; - int ret; - - NV_DEBUG(dev, "ch%d\n", chan->id); +#include - ret = nouveau_gpuobj_new(dev, NULL, 264 * 4, 16, NVOBJ_FLAG_ZERO_ALLOC | - NVOBJ_FLAG_ZERO_FREE, &ctx); - if (ret) - return ret; - - nv_wo32(ctx, 0x78, 0x02001ec1); - - spin_lock_irqsave(&dev_priv->context_switch_lock, flags); - nv_mask(dev, 0x002500, 0x00000001, 0x00000000); - if ((nv_rd32(dev, 0x003204) & 0x1f) == chan->id) - nv_wr32(dev, 0x00330c, ctx->addr >> 4); - nv_wo32(chan->ramfc, 0x54, ctx->addr >> 4); - nv_mask(dev, 0x002500, 0x00000001, 0x00000001); - spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags); +struct nv31_mpeg_priv { + struct nouveau_mpeg base; + atomic_t refcount; +}; - chan->engctx[engine] = ctx; - return 0; -} +struct nv31_mpeg_chan { + struct nouveau_object base; +}; -static void -nv40_mpeg_context_del(struct nouveau_channel *chan, int engine) -{ - struct drm_nouveau_private *dev_priv = chan->dev->dev_private; - struct nouveau_gpuobj *ctx = chan->engctx[engine]; - struct drm_device *dev = chan->dev; - unsigned long flags; - u32 inst = 0x80000000 | (ctx->addr >> 4); - - spin_lock_irqsave(&dev_priv->context_switch_lock, flags); - nv_mask(dev, 0x00b32c, 0x00000001, 0x00000000); - if (nv_rd32(dev, 0x00b318) == inst) - nv_mask(dev, 0x00b318, 0x80000000, 0x00000000); - nv_mask(dev, 0x00b32c, 0x00000001, 0x00000001); - spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags); - - nouveau_gpuobj_ref(NULL, &ctx); - chan->engctx[engine] = NULL; -} +/******************************************************************************* + * MPEG object classes + ******************************************************************************/ static int -nv31_mpeg_object_new(struct nouveau_channel *chan, int engine, - u32 handle, u16 class) +nv31_mpeg_object_ctor(struct nouveau_object *parent, + struct nouveau_object *engine, + struct nouveau_oclass *oclass, void *data, u32 size, + struct nouveau_object **pobject) { - struct drm_device *dev = chan->dev; - struct nouveau_gpuobj *obj = NULL; + struct nouveau_gpuobj *obj; int ret; - ret = nouveau_gpuobj_new(dev, chan, 20, 16, NVOBJ_FLAG_ZERO_ALLOC | - NVOBJ_FLAG_ZERO_FREE, &obj); + ret = nouveau_gpuobj_create(parent, engine, oclass, 0, parent, + 20, 16, 0, &obj); + *pobject = nv_object(obj); if (ret) return ret; - obj->engine = 2; - obj->class = class; - - nv_wo32(obj, 0x00, class); - - ret = nouveau_ramht_insert(chan, handle, obj); - nouveau_gpuobj_ref(NULL, &obj); - return ret; -} - -static int -nv31_mpeg_init(struct drm_device *dev, int engine) -{ - struct nv31_mpeg_engine *pmpeg = nv_engine(dev, engine); - int i; - - /* VPE init */ - nv_mask(dev, 0x000200, 0x00000002, 0x00000000); - nv_mask(dev, 0x000200, 0x00000002, 0x00000002); - nv_wr32(dev, 0x00b0e0, 0x00000020); /* nvidia: rd 0x01, wr 0x20 */ - nv_wr32(dev, 0x00b0e8, 0x00000020); /* nvidia: rd 0x01, wr 0x20 */ - for (i = 0; i < nvfb_tile_nr(dev); i++) - pmpeg->base.set_tile_region(dev, i); - - /* PMPEG init */ - nv_wr32(dev, 0x00b32c, 0x00000000); - nv_wr32(dev, 0x00b314, 0x00000100); - nv_wr32(dev, 0x00b220, nv44_graph_class(dev) ? 0x00000044 : 0x00000031); - nv_wr32(dev, 0x00b300, 0x02001ec1); - nv_mask(dev, 0x00b32c, 0x00000001, 0x00000001); - - nv_wr32(dev, 0x00b100, 0xffffffff); - nv_wr32(dev, 0x00b140, 0xffffffff); - - if (!nv_wait(dev, 0x00b200, 0x00000001, 0x00000000)) { - NV_ERROR(dev, "PMPEG init: 0x%08x\n", nv_rd32(dev, 0x00b200)); - return -EBUSY; - } - - return 0; -} - -static int -nv31_mpeg_fini(struct drm_device *dev, int engine, bool suspend) -{ - /*XXX: context save? */ - nv_mask(dev, 0x00b32c, 0x00000001, 0x00000000); - nv_wr32(dev, 0x00b140, 0x00000000); + nv_wo32(obj, 0x00, nv_mclass(obj)); + nv_wo32(obj, 0x04, 0x00000000); + nv_wo32(obj, 0x08, 0x00000000); + nv_wo32(obj, 0x0c, 0x00000000); return 0; } static int -nv31_mpeg_mthd_dma(struct nouveau_channel *chan, u32 class, u32 mthd, u32 data) +nv31_mpeg_mthd_dma(struct nouveau_object *object, u32 mthd, void *arg, u32 len) { - struct drm_device *dev = chan->dev; - u32 inst = data << 4; - u32 dma0 = nv_ri32(dev, inst + 0); - u32 dma1 = nv_ri32(dev, inst + 4); - u32 dma2 = nv_ri32(dev, inst + 8); + struct nouveau_instmem *imem = nouveau_instmem(object); + struct nv31_mpeg_priv *priv = (void *)object->engine; + u32 inst = *(u32 *)arg << 4; + u32 dma0 = nv_ro32(imem, inst + 0); + u32 dma1 = nv_ro32(imem, inst + 4); + u32 dma2 = nv_ro32(imem, inst + 8); u32 base = (dma2 & 0xfffff000) | (dma0 >> 20); u32 size = dma1 + 1; @@ -184,160 +87,215 @@ nv31_mpeg_mthd_dma(struct nouveau_channel *chan, u32 class, u32 mthd, u32 data) if (mthd == 0x0190) { /* DMA_CMD */ - nv_mask(dev, 0x00b300, 0x00030000, (dma0 & 0x00030000)); - nv_wr32(dev, 0x00b334, base); - nv_wr32(dev, 0x00b324, size); + nv_mask(priv, 0x00b300, 0x00030000, (dma0 & 0x00030000)); + nv_wr32(priv, 0x00b334, base); + nv_wr32(priv, 0x00b324, size); } else if (mthd == 0x01a0) { /* DMA_DATA */ - nv_mask(dev, 0x00b300, 0x000c0000, (dma0 & 0x00030000) << 2); - nv_wr32(dev, 0x00b360, base); - nv_wr32(dev, 0x00b364, size); + nv_mask(priv, 0x00b300, 0x000c0000, (dma0 & 0x00030000) << 2); + nv_wr32(priv, 0x00b360, base); + nv_wr32(priv, 0x00b364, size); } else { /* DMA_IMAGE, VRAM only */ if (dma0 & 0x000c0000) return -EINVAL; - nv_wr32(dev, 0x00b370, base); - nv_wr32(dev, 0x00b374, size); + nv_wr32(priv, 0x00b370, base); + nv_wr32(priv, 0x00b374, size); } return 0; } +struct nouveau_ofuncs +nv31_mpeg_ofuncs = { + .ctor = nv31_mpeg_object_ctor, + .dtor = _nouveau_gpuobj_dtor, + .init = _nouveau_gpuobj_init, + .fini = _nouveau_gpuobj_fini, + .rd32 = _nouveau_gpuobj_rd32, + .wr32 = _nouveau_gpuobj_wr32, +}; + +struct nouveau_omthds +nv31_mpeg_omthds[] = { + { 0x0190, nv31_mpeg_mthd_dma }, + { 0x01a0, nv31_mpeg_mthd_dma }, + { 0x01b0, nv31_mpeg_mthd_dma }, + {} +}; + +struct nouveau_oclass +nv31_mpeg_sclass[] = { + { 0x3174, &nv31_mpeg_ofuncs, nv31_mpeg_omthds }, + {} +}; + +/******************************************************************************* + * PMPEG context + ******************************************************************************/ + static int -nv31_mpeg_isr_chid(struct drm_device *dev, u32 inst) +nv31_mpeg_context_ctor(struct nouveau_object *parent, + struct nouveau_object *engine, + struct nouveau_oclass *oclass, void *data, u32 size, + struct nouveau_object **pobject) { - struct nouveau_fifo_priv *pfifo = nv_engine(dev, NVOBJ_ENGINE_FIFO); - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_gpuobj *ctx; - unsigned long flags; - int i; - - /* hardcode drm channel id on nv3x, so swmthd lookup works */ - if (dev_priv->card_type < NV_40) - return 0; - - spin_lock_irqsave(&dev_priv->channels.lock, flags); - for (i = 0; i < pfifo->channels; i++) { - if (!dev_priv->channels.ptr[i]) - continue; - - ctx = dev_priv->channels.ptr[i]->engctx[NVOBJ_ENGINE_MPEG]; - if (ctx && ctx->addr == inst) - break; - } - spin_unlock_irqrestore(&dev_priv->channels.lock, flags); - return i; + struct nv31_mpeg_priv *priv = (void *)engine; + struct nv31_mpeg_chan *chan; + int ret; + + if (!atomic_add_unless(&priv->refcount, 1, 1)) + return -EBUSY; + + ret = nouveau_object_create(parent, engine, oclass, 0, &chan); + *pobject = nv_object(chan); + if (ret) + return ret; + + return 0; } static void -nv31_vpe_set_tile_region(struct drm_device *dev, int i) +nv31_mpeg_context_dtor(struct nouveau_object *object) { - struct nouveau_fb_tile *tile = nvfb_tile(dev, i); - nv_wr32(dev, 0x00b008 + (i * 0x10), tile->pitch); - nv_wr32(dev, 0x00b004 + (i * 0x10), tile->limit); - nv_wr32(dev, 0x00b000 + (i * 0x10), tile->addr); + struct nv31_mpeg_priv *priv = (void *)object->engine; + struct nv31_mpeg_chan *chan = (void *)object; + atomic_dec(&priv->refcount); + nouveau_object_destroy(&chan->base); } -static void -nv31_mpeg_isr(struct drm_device *dev) +static struct nouveau_oclass +nv31_mpeg_cclass = { + .handle = NV_ENGCTX(MPEG, 0x31), + .ofuncs = &(struct nouveau_ofuncs) { + .ctor = nv31_mpeg_context_ctor, + .dtor = nv31_mpeg_context_dtor, + .init = nouveau_object_init, + .fini = nouveau_object_fini, + }, +}; + +/******************************************************************************* + * PMPEG engine/subdev functions + ******************************************************************************/ + +void +nv31_mpeg_tile_prog(struct nouveau_engine *engine, int i) { - u32 inst = (nv_rd32(dev, 0x00b318) & 0x000fffff) << 4; - u32 chid = nv31_mpeg_isr_chid(dev, inst); - u32 stat = nv_rd32(dev, 0x00b100); - u32 type = nv_rd32(dev, 0x00b230); - u32 mthd = nv_rd32(dev, 0x00b234); - u32 data = nv_rd32(dev, 0x00b238); + struct nouveau_fb_tile *tile = &nouveau_fb(engine)->tile.region[i]; + struct nv31_mpeg_priv *priv = (void *)engine; + + nv_wr32(priv, 0x00b008 + (i * 0x10), tile->pitch); + nv_wr32(priv, 0x00b004 + (i * 0x10), tile->limit); + nv_wr32(priv, 0x00b000 + (i * 0x10), tile->addr); +} + +void +nv31_mpeg_intr(struct nouveau_subdev *subdev) +{ + struct nv31_mpeg_priv *priv = (void *)subdev; + struct nouveau_engine *engine = nv_engine(subdev); + struct nouveau_handle *handle = NULL; + u32 inst = (nv_rd32(priv, 0x00b318) & 0x000fffff) << 4; + u32 stat = nv_rd32(priv, 0x00b100); + u32 type = nv_rd32(priv, 0x00b230); + u32 mthd = nv_rd32(priv, 0x00b234); + u32 data = nv_rd32(priv, 0x00b238); u32 show = stat; if (stat & 0x01000000) { /* happens on initial binding of the object */ - if (type == 0x00000020 && mthd == 0x0000) { - nv_mask(dev, 0x00b308, 0x00000000, 0x00000000); + if (handle && type == 0x00000020 && mthd == 0x0000) { + nv_mask(priv, 0x00b308, 0x00000000, 0x00000000); show &= ~0x01000000; } - if (type == 0x00000010) { - if (!nouveau_gpuobj_mthd_call2(dev, chid, 0x3174, mthd, data)) + if (handle && type == 0x00000010) { + handle = nouveau_engctx_lookup_class(engine, inst, 0x3174); + + if (handle && !nv_call(handle->object, mthd, data)) { + nouveau_engctx_handle_put(handle); show &= ~0x01000000; + } } } - nv_wr32(dev, 0x00b100, stat); - nv_wr32(dev, 0x00b230, 0x00000001); + nv_wr32(priv, 0x00b100, stat); + nv_wr32(priv, 0x00b230, 0x00000001); - if (show && nouveau_ratelimit()) { - NV_INFO(dev, "PMPEG: Ch %d [0x%08x] 0x%08x 0x%08x 0x%08x 0x%08x\n", - chid, inst, stat, type, mthd, data); + if (show) { + nv_error(priv, "ch %d [0x%08x] 0x%08x 0x%08x 0x%08x 0x%08x\n", + inst, stat, type, mthd, data); } } -static void -nv31_vpe_isr(struct drm_device *dev) +static int +nv31_mpeg_ctor(struct nouveau_object *parent, struct nouveau_object *engine, + struct nouveau_oclass *oclass, void *data, u32 size, + struct nouveau_object **pobject) { - if (nv_rd32(dev, 0x00b100)) - nv31_mpeg_isr(dev); + struct nv31_mpeg_priv *priv; + int ret; - if (nv_rd32(dev, 0x00b800)) { - u32 stat = nv_rd32(dev, 0x00b800); - NV_INFO(dev, "PMSRCH: 0x%08x\n", stat); - nv_wr32(dev, 0xb800, stat); - } + ret = nouveau_mpeg_create(parent, engine, oclass, &priv); + *pobject = nv_object(priv); + if (ret) + return ret; + + nv_subdev(priv)->unit = 0x00000002; + nv_subdev(priv)->intr = nv31_mpeg_intr; + nv_engine(priv)->cclass = &nv31_mpeg_cclass; + nv_engine(priv)->sclass = nv31_mpeg_sclass; + nv_engine(priv)->tile_prog = nv31_mpeg_tile_prog; + return 0; } -static void -nv31_mpeg_destroy(struct drm_device *dev, int engine) +int +nv31_mpeg_init(struct nouveau_object *object) { - struct nv31_mpeg_engine *pmpeg = nv_engine(dev, engine); + struct nouveau_engine *engine = nv_engine(object->engine); + struct nv31_mpeg_priv *priv = (void *)engine; + struct nouveau_fb *pfb = nouveau_fb(object); + int ret, i; - nouveau_irq_unregister(dev, 0); + ret = nouveau_mpeg_init(&priv->base); + if (ret) + return ret; - NVOBJ_ENGINE_DEL(dev, MPEG); - kfree(pmpeg); -} + /* VPE init */ + nv_wr32(priv, 0x00b0e0, 0x00000020); /* nvidia: rd 0x01, wr 0x20 */ + nv_wr32(priv, 0x00b0e8, 0x00000020); /* nvidia: rd 0x01, wr 0x20 */ -int -nv31_mpeg_create(struct drm_device *dev) -{ - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nv31_mpeg_engine *pmpeg; - - pmpeg = kzalloc(sizeof(*pmpeg), GFP_KERNEL); - if (!pmpeg) - return -ENOMEM; - atomic_set(&pmpeg->refcount, 0); - - pmpeg->base.destroy = nv31_mpeg_destroy; - pmpeg->base.init = nv31_mpeg_init; - pmpeg->base.fini = nv31_mpeg_fini; - if (dev_priv->card_type < NV_40) { - pmpeg->base.context_new = nv31_mpeg_context_new; - pmpeg->base.context_del = nv31_mpeg_context_del; - } else { - pmpeg->base.context_new = nv40_mpeg_context_new; - pmpeg->base.context_del = nv40_mpeg_context_del; + for (i = 0; i < pfb->tile.regions; i++) + engine->tile_prog(engine, i); + + /* PMPEG init */ + nv_wr32(priv, 0x00b32c, 0x00000000); + nv_wr32(priv, 0x00b314, 0x00000100); + nv_wr32(priv, 0x00b220, nv44_graph_class(priv) ? 0x00000044 : 0x00000031); + nv_wr32(priv, 0x00b300, 0x02001ec1); + nv_mask(priv, 0x00b32c, 0x00000001, 0x00000001); + + nv_wr32(priv, 0x00b100, 0xffffffff); + nv_wr32(priv, 0x00b140, 0xffffffff); + + if (!nv_wait(priv, 0x00b200, 0x00000001, 0x00000000)) { + nv_error(priv, "timeout 0x%08x\n", nv_rd32(priv, 0x00b200)); + return -EBUSY; } - pmpeg->base.object_new = nv31_mpeg_object_new; - - /* ISR vector, PMC_ENABLE bit, and TILE regs are shared between - * all VPE engines, for this driver's purposes the PMPEG engine - * will be treated as the "master" and handle the global VPE - * bits too - */ - pmpeg->base.set_tile_region = nv31_vpe_set_tile_region; - nouveau_irq_register(dev, 0, nv31_vpe_isr); - - NVOBJ_ENGINE_ADD(dev, MPEG, &pmpeg->base); - NVOBJ_CLASS(dev, 0x3174, MPEG); - NVOBJ_MTHD (dev, 0x3174, 0x0190, nv31_mpeg_mthd_dma); - NVOBJ_MTHD (dev, 0x3174, 0x01a0, nv31_mpeg_mthd_dma); - NVOBJ_MTHD (dev, 0x3174, 0x01b0, nv31_mpeg_mthd_dma); - -#if 0 - NVOBJ_ENGINE_ADD(dev, ME, &pme->base); - NVOBJ_CLASS(dev, 0x4075, ME); -#endif - return 0; + return 0; } + +struct nouveau_oclass +nv31_mpeg_oclass = { + .handle = NV_ENGINE(MPEG, 0x31), + .ofuncs = &(struct nouveau_ofuncs) { + .ctor = nv31_mpeg_ctor, + .dtor = _nouveau_mpeg_dtor, + .init = nv31_mpeg_init, + .fini = _nouveau_mpeg_fini, + }, +}; diff --git a/drivers/gpu/drm/nouveau/core/engine/mpeg/nv40.c b/drivers/gpu/drm/nouveau/core/engine/mpeg/nv40.c new file mode 100644 index 000000000000..12418574efea --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/engine/mpeg/nv40.c @@ -0,0 +1,144 @@ +/* + * 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 +#include +#include + +#include +#include + +struct nv40_mpeg_priv { + struct nouveau_mpeg base; +}; + +struct nv40_mpeg_chan { + struct nouveau_mpeg base; +}; + +/******************************************************************************* + * PMPEG context + ******************************************************************************/ + +static int +nv40_mpeg_context_ctor(struct nouveau_object *parent, + struct nouveau_object *engine, + struct nouveau_oclass *oclass, void *data, u32 size, + struct nouveau_object **pobject) +{ + struct nv40_mpeg_chan *chan; + int ret; + + ret = nouveau_mpeg_context_create(parent, engine, oclass, NULL, + 264 * 4, 16, + NVOBJ_FLAG_ZERO_ALLOC, &chan); + *pobject = nv_object(chan); + if (ret) + return ret; + + return 0; +} + +static int +nv40_mpeg_context_fini(struct nouveau_object *object, bool suspend) +{ + + struct nv40_mpeg_priv *priv = (void *)object->engine; + struct nv40_mpeg_chan *chan = (void *)object; + u32 inst = 0x80000000 | nv_gpuobj(chan)->addr >> 4; + + nv_mask(priv, 0x00b32c, 0x00000001, 0x00000000); + if (nv_rd32(priv, 0x00b318) == inst) + nv_mask(priv, 0x00b318, 0x80000000, 0x00000000); + nv_mask(priv, 0x00b32c, 0x00000001, 0x00000001); + return 0; +} + +static struct nouveau_oclass +nv40_mpeg_cclass = { + .handle = NV_ENGCTX(MPEG, 0x40), + .ofuncs = &(struct nouveau_ofuncs) { + .ctor = nv40_mpeg_context_ctor, + .dtor = _nouveau_mpeg_context_dtor, + .init = _nouveau_mpeg_context_init, + .fini = nv40_mpeg_context_fini, + .rd32 = _nouveau_mpeg_context_rd32, + .wr32 = _nouveau_mpeg_context_wr32, + }, +}; + +/******************************************************************************* + * PMPEG engine/subdev functions + ******************************************************************************/ + +static void +nv40_mpeg_intr(struct nouveau_subdev *subdev) +{ + struct nv40_mpeg_priv *priv = (void *)subdev; + u32 stat; + + if ((stat = nv_rd32(priv, 0x00b100))) + nv31_mpeg_intr(subdev); + + if ((stat = nv_rd32(priv, 0x00b800))) { + nv_error(priv, "PMSRCH 0x%08x\n", stat); + nv_wr32(priv, 0x00b800, stat); + } +} + +static int +nv40_mpeg_ctor(struct nouveau_object *parent, struct nouveau_object *engine, + struct nouveau_oclass *oclass, void *data, u32 size, + struct nouveau_object **pobject) +{ + struct nv40_mpeg_priv *priv; + int ret; + + ret = nouveau_mpeg_create(parent, engine, oclass, &priv); + *pobject = nv_object(priv); + if (ret) + return ret; + + nv_subdev(priv)->unit = 0x00000002; + nv_subdev(priv)->intr = nv40_mpeg_intr; + nv_engine(priv)->cclass = &nv40_mpeg_cclass; + nv_engine(priv)->sclass = nv31_mpeg_sclass; + nv_engine(priv)->tile_prog = nv31_mpeg_tile_prog; + return 0; +} + +struct nouveau_oclass +nv40_mpeg_oclass = { + .handle = NV_ENGINE(MPEG, 0x40), + .ofuncs = &(struct nouveau_ofuncs) { + .ctor = nv40_mpeg_ctor, + .dtor = _nouveau_mpeg_dtor, + .init = nv31_mpeg_init, + .fini = _nouveau_mpeg_fini, + }, +}; diff --git a/drivers/gpu/drm/nouveau/core/engine/mpeg/nv50.c b/drivers/gpu/drm/nouveau/core/engine/mpeg/nv50.c index 4e3292ed80c1..8678a9996d57 100644 --- a/drivers/gpu/drm/nouveau/core/engine/mpeg/nv50.c +++ b/drivers/gpu/drm/nouveau/core/engine/mpeg/nv50.c @@ -1,5 +1,5 @@ /* - * Copyright 2011 Red Hat Inc. + * Copyright 2012 Red Hat Inc. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -22,218 +22,219 @@ * Authors: Ben Skeggs */ -#include "drmP.h" -#include "nouveau_drv.h" -#include +#include +#include +#include -struct nv50_mpeg_engine { - struct nouveau_exec_engine base; -}; +#include +#include +#include -static inline u32 -CTX_PTR(struct drm_device *dev, u32 offset) -{ - struct drm_nouveau_private *dev_priv = dev->dev_private; +#include - if (dev_priv->chipset == 0x50) - offset += 0x0260; - else - offset += 0x0060; +struct nv50_mpeg_priv { + struct nouveau_mpeg base; +}; - return offset; -} +struct nv50_mpeg_chan { + struct nouveau_mpeg_chan base; +}; + +/******************************************************************************* + * MPEG object classes + ******************************************************************************/ static int -nv50_mpeg_context_new(struct nouveau_channel *chan, int engine) +nv50_mpeg_object_ctor(struct nouveau_object *parent, + struct nouveau_object *engine, + struct nouveau_oclass *oclass, void *data, u32 size, + struct nouveau_object **pobject) { - struct drm_device *dev = chan->dev; - struct nouveau_gpuobj *ramin = chan->ramin; - struct nouveau_gpuobj *ctx = NULL; + struct nouveau_gpuobj *obj; int ret; - NV_DEBUG(dev, "ch%d\n", chan->id); - - ret = nouveau_gpuobj_new(dev, chan, 128 * 4, 0, NVOBJ_FLAG_ZERO_ALLOC | - NVOBJ_FLAG_ZERO_FREE, &ctx); + ret = nouveau_gpuobj_create(parent, engine, oclass, 0, parent, + 16, 16, 0, &obj); + *pobject = nv_object(obj); if (ret) return ret; - nv_wo32(ramin, CTX_PTR(dev, 0x00), 0x80190002); - nv_wo32(ramin, CTX_PTR(dev, 0x04), ctx->addr + ctx->size - 1); - nv_wo32(ramin, CTX_PTR(dev, 0x08), ctx->addr); - nv_wo32(ramin, CTX_PTR(dev, 0x0c), 0); - nv_wo32(ramin, CTX_PTR(dev, 0x10), 0); - nv_wo32(ramin, CTX_PTR(dev, 0x14), 0x00010000); - - nv_wo32(ctx, 0x70, 0x00801ec1); - nv_wo32(ctx, 0x7c, 0x0000037c); - nvimem_flush(dev); - - chan->engctx[engine] = ctx; + nv_wo32(obj, 0x00, nv_mclass(obj)); + nv_wo32(obj, 0x04, 0x00000000); + nv_wo32(obj, 0x08, 0x00000000); + nv_wo32(obj, 0x0c, 0x00000000); return 0; } -static void -nv50_mpeg_context_del(struct nouveau_channel *chan, int engine) -{ - struct nouveau_gpuobj *ctx = chan->engctx[engine]; - struct drm_device *dev = chan->dev; - int i; +struct nouveau_ofuncs +nv50_mpeg_ofuncs = { + .ctor = nv50_mpeg_object_ctor, + .dtor = _nouveau_gpuobj_dtor, + .init = _nouveau_gpuobj_init, + .fini = _nouveau_gpuobj_fini, + .rd32 = _nouveau_gpuobj_rd32, + .wr32 = _nouveau_gpuobj_wr32, +}; - for (i = 0x00; i <= 0x14; i += 4) - nv_wo32(chan->ramin, CTX_PTR(dev, i), 0x00000000); +static struct nouveau_oclass +nv50_mpeg_sclass[] = { + { 0x3174, &nv50_mpeg_ofuncs }, + {} +}; - nouveau_gpuobj_ref(NULL, &ctx); - chan->engctx[engine] = NULL; -} +/******************************************************************************* + * PMPEG context + ******************************************************************************/ -static int -nv50_mpeg_object_new(struct nouveau_channel *chan, int engine, - u32 handle, u16 class) +int +nv50_mpeg_context_ctor(struct nouveau_object *parent, + struct nouveau_object *engine, + struct nouveau_oclass *oclass, void *data, u32 size, + struct nouveau_object **pobject) { - struct drm_device *dev = chan->dev; - struct nouveau_gpuobj *obj = NULL; + struct nouveau_bar *bar = nouveau_bar(parent); + struct nv50_mpeg_chan *chan; int ret; - ret = nouveau_gpuobj_new(dev, chan, 16, 16, NVOBJ_FLAG_ZERO_FREE, &obj); + ret = nouveau_mpeg_context_create(parent, engine, oclass, NULL, 128 * 4, + 0, NVOBJ_FLAG_ZERO_ALLOC, &chan); + *pobject = nv_object(chan); if (ret) return ret; - obj->engine = 2; - obj->class = class; - - nv_wo32(obj, 0x00, class); - nv_wo32(obj, 0x04, 0x00000000); - nv_wo32(obj, 0x08, 0x00000000); - nv_wo32(obj, 0x0c, 0x00000000); - nvimem_flush(dev); - - ret = nouveau_ramht_insert(chan, handle, obj); - nouveau_gpuobj_ref(NULL, &obj); - return ret; -} -static void -nv50_mpeg_tlb_flush(struct drm_device *dev, int engine) -{ - nv50_vm_flush_engine(dev, 0x08); + nv_wo32(chan, 0x0070, 0x00801ec1); + nv_wo32(chan, 0x007c, 0x0000037c); + bar->flush(bar); + return 0; } -static int -nv50_mpeg_init(struct drm_device *dev, int engine) -{ - nv_wr32(dev, 0x00b32c, 0x00000000); - nv_wr32(dev, 0x00b314, 0x00000100); - nv_wr32(dev, 0x00b0e0, 0x0000001a); - - nv_wr32(dev, 0x00b220, 0x00000044); - nv_wr32(dev, 0x00b300, 0x00801ec1); - nv_wr32(dev, 0x00b390, 0x00000000); - nv_wr32(dev, 0x00b394, 0x00000000); - nv_wr32(dev, 0x00b398, 0x00000000); - nv_mask(dev, 0x00b32c, 0x00000001, 0x00000001); - - nv_wr32(dev, 0x00b100, 0xffffffff); - nv_wr32(dev, 0x00b140, 0xffffffff); - - if (!nv_wait(dev, 0x00b200, 0x00000001, 0x00000000)) { - NV_ERROR(dev, "PMPEG init: 0x%08x\n", nv_rd32(dev, 0x00b200)); - return -EBUSY; - } +static struct nouveau_oclass +nv50_mpeg_cclass = { + .handle = NV_ENGCTX(MPEG, 0x50), + .ofuncs = &(struct nouveau_ofuncs) { + .ctor = nv50_mpeg_context_ctor, + .dtor = _nouveau_mpeg_context_dtor, + .init = _nouveau_mpeg_context_init, + .fini = _nouveau_mpeg_context_fini, + .rd32 = _nouveau_mpeg_context_rd32, + .wr32 = _nouveau_mpeg_context_wr32, + }, +}; - return 0; -} +/******************************************************************************* + * PMPEG engine/subdev functions + ******************************************************************************/ -static int -nv50_mpeg_fini(struct drm_device *dev, int engine, bool suspend) +int +nv50_mpeg_tlb_flush(struct nouveau_engine *engine) { - nv_mask(dev, 0x00b32c, 0x00000001, 0x00000000); - nv_wr32(dev, 0x00b140, 0x00000000); + nv50_vm_flush_engine(&engine->base, 0x08); return 0; } -static void -nv50_mpeg_isr(struct drm_device *dev) +void +nv50_mpeg_intr(struct nouveau_subdev *subdev) { - u32 stat = nv_rd32(dev, 0x00b100); - u32 type = nv_rd32(dev, 0x00b230); - u32 mthd = nv_rd32(dev, 0x00b234); - u32 data = nv_rd32(dev, 0x00b238); + struct nv50_mpeg_priv *priv = (void *)subdev; + u32 stat = nv_rd32(priv, 0x00b100); + u32 type = nv_rd32(priv, 0x00b230); + u32 mthd = nv_rd32(priv, 0x00b234); + u32 data = nv_rd32(priv, 0x00b238); u32 show = stat; if (stat & 0x01000000) { /* happens on initial binding of the object */ if (type == 0x00000020 && mthd == 0x0000) { - nv_wr32(dev, 0x00b308, 0x00000100); + nv_wr32(priv, 0x00b308, 0x00000100); show &= ~0x01000000; } } - if (show && nouveau_ratelimit()) { - NV_INFO(dev, "PMPEG - 0x%08x 0x%08x 0x%08x 0x%08x\n", + if (show) { + nv_info(priv, "0x%08x 0x%08x 0x%08x 0x%08x\n", stat, type, mthd, data); } - nv_wr32(dev, 0x00b100, stat); - nv_wr32(dev, 0x00b230, 0x00000001); - nv50_fb_vm_trap(dev, 1); + nv_wr32(priv, 0x00b100, stat); + nv_wr32(priv, 0x00b230, 0x00000001); + nv50_fb_trap(nouveau_fb(priv), 1); } static void -nv50_vpe_isr(struct drm_device *dev) +nv50_vpe_intr(struct nouveau_subdev *subdev) { - if (nv_rd32(dev, 0x00b100)) - nv50_mpeg_isr(dev); + struct nv50_mpeg_priv *priv = (void *)subdev; - if (nv_rd32(dev, 0x00b800)) { - u32 stat = nv_rd32(dev, 0x00b800); - NV_INFO(dev, "PMSRCH: 0x%08x\n", stat); - nv_wr32(dev, 0xb800, stat); + if (nv_rd32(priv, 0x00b100)) + nv50_mpeg_intr(subdev); + + if (nv_rd32(priv, 0x00b800)) { + u32 stat = nv_rd32(priv, 0x00b800); + nv_info(priv, "PMSRCH: 0x%08x\n", stat); + nv_wr32(priv, 0xb800, stat); } } -static void -nv50_mpeg_destroy(struct drm_device *dev, int engine) +static int +nv50_mpeg_ctor(struct nouveau_object *parent, struct nouveau_object *engine, + struct nouveau_oclass *oclass, void *data, u32 size, + struct nouveau_object **pobject) { - struct nv50_mpeg_engine *pmpeg = nv_engine(dev, engine); + struct nv50_mpeg_priv *priv; + int ret; - nouveau_irq_unregister(dev, 0); + ret = nouveau_mpeg_create(parent, engine, oclass, &priv); + *pobject = nv_object(priv); + if (ret) + return ret; - NVOBJ_ENGINE_DEL(dev, MPEG); - kfree(pmpeg); + nv_subdev(priv)->unit = 0x00400002; + nv_subdev(priv)->intr = nv50_vpe_intr; + nv_engine(priv)->cclass = &nv50_mpeg_cclass; + nv_engine(priv)->sclass = nv50_mpeg_sclass; + nv_engine(priv)->tlb_flush = nv50_mpeg_tlb_flush; + return 0; } int -nv50_mpeg_create(struct drm_device *dev) +nv50_mpeg_init(struct nouveau_object *object) { - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nv50_mpeg_engine *pmpeg; - - pmpeg = kzalloc(sizeof(*pmpeg), GFP_KERNEL); - if (!pmpeg) - return -ENOMEM; - - pmpeg->base.destroy = nv50_mpeg_destroy; - pmpeg->base.init = nv50_mpeg_init; - pmpeg->base.fini = nv50_mpeg_fini; - pmpeg->base.context_new = nv50_mpeg_context_new; - pmpeg->base.context_del = nv50_mpeg_context_del; - pmpeg->base.object_new = nv50_mpeg_object_new; - pmpeg->base.tlb_flush = nv50_mpeg_tlb_flush; - - if (dev_priv->chipset == 0x50) { - nouveau_irq_register(dev, 0, nv50_vpe_isr); - NVOBJ_ENGINE_ADD(dev, MPEG, &pmpeg->base); - NVOBJ_CLASS(dev, 0x3174, MPEG); -#if 0 - NVOBJ_ENGINE_ADD(dev, ME, &pme->base); - NVOBJ_CLASS(dev, 0x4075, ME); -#endif - } else { - nouveau_irq_register(dev, 0, nv50_mpeg_isr); - NVOBJ_ENGINE_ADD(dev, MPEG, &pmpeg->base); - NVOBJ_CLASS(dev, 0x8274, MPEG); + struct nv50_mpeg_priv *priv = (void *)object; + int ret; + + ret = nouveau_mpeg_init(&priv->base); + if (ret) + return ret; + + nv_wr32(priv, 0x00b32c, 0x00000000); + nv_wr32(priv, 0x00b314, 0x00000100); + nv_wr32(priv, 0x00b0e0, 0x0000001a); + + nv_wr32(priv, 0x00b220, 0x00000044); + nv_wr32(priv, 0x00b300, 0x00801ec1); + nv_wr32(priv, 0x00b390, 0x00000000); + nv_wr32(priv, 0x00b394, 0x00000000); + nv_wr32(priv, 0x00b398, 0x00000000); + nv_mask(priv, 0x00b32c, 0x00000001, 0x00000001); + + nv_wr32(priv, 0x00b100, 0xffffffff); + nv_wr32(priv, 0x00b140, 0xffffffff); + + if (!nv_wait(priv, 0x00b200, 0x00000001, 0x00000000)) { + nv_error(priv, "timeout 0x%08x\n", nv_rd32(priv, 0x00b200)); + return -EBUSY; } return 0; - } + +struct nouveau_oclass +nv50_mpeg_oclass = { + .handle = NV_ENGINE(MPEG, 0x50), + .ofuncs = &(struct nouveau_ofuncs) { + .ctor = nv50_mpeg_ctor, + .dtor = _nouveau_mpeg_dtor, + .init = nv50_mpeg_init, + .fini = _nouveau_mpeg_fini, + }, +}; diff --git a/drivers/gpu/drm/nouveau/core/engine/mpeg/nv84.c b/drivers/gpu/drm/nouveau/core/engine/mpeg/nv84.c new file mode 100644 index 000000000000..8f805b44d59e --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/engine/mpeg/nv84.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 +#include +#include + +#include +#include +#include + +#include + +struct nv84_mpeg_priv { + struct nouveau_mpeg base; +}; + +struct nv84_mpeg_chan { + struct nouveau_mpeg_chan base; +}; + +/******************************************************************************* + * MPEG object classes + ******************************************************************************/ + +static struct nouveau_oclass +nv84_mpeg_sclass[] = { + { 0x8274, &nv50_mpeg_ofuncs }, + {} +}; + +/******************************************************************************* + * PMPEG context + ******************************************************************************/ + +static struct nouveau_oclass +nv84_mpeg_cclass = { + .handle = NV_ENGCTX(MPEG, 0x84), + .ofuncs = &(struct nouveau_ofuncs) { + .ctor = nv50_mpeg_context_ctor, + .dtor = _nouveau_mpeg_context_dtor, + .init = _nouveau_mpeg_context_init, + .fini = _nouveau_mpeg_context_fini, + .rd32 = _nouveau_mpeg_context_rd32, + .wr32 = _nouveau_mpeg_context_wr32, + }, +}; + +/******************************************************************************* + * PMPEG engine/subdev functions + ******************************************************************************/ + +static int +nv84_mpeg_ctor(struct nouveau_object *parent, struct nouveau_object *engine, + struct nouveau_oclass *oclass, void *data, u32 size, + struct nouveau_object **pobject) +{ + struct nv84_mpeg_priv *priv; + int ret; + + ret = nouveau_mpeg_create(parent, engine, oclass, &priv); + *pobject = nv_object(priv); + if (ret) + return ret; + + nv_subdev(priv)->unit = 0x00000002; + nv_subdev(priv)->intr = nv50_mpeg_intr; + nv_engine(priv)->cclass = &nv84_mpeg_cclass; + nv_engine(priv)->sclass = nv84_mpeg_sclass; + nv_engine(priv)->tlb_flush = nv50_mpeg_tlb_flush; + return 0; +} + +struct nouveau_oclass +nv84_mpeg_oclass = { + .handle = NV_ENGINE(MPEG, 0x84), + .ofuncs = &(struct nouveau_ofuncs) { + .ctor = nv84_mpeg_ctor, + .dtor = _nouveau_mpeg_dtor, + .init = nv50_mpeg_init, + .fini = _nouveau_mpeg_fini, + }, +}; diff --git a/drivers/gpu/drm/nouveau/core/engine/ppp/nv98.c b/drivers/gpu/drm/nouveau/core/engine/ppp/nv98.c index 384de6deeeea..50e7e0da1981 100644 --- a/drivers/gpu/drm/nouveau/core/engine/ppp/nv98.c +++ b/drivers/gpu/drm/nouveau/core/engine/ppp/nv98.c @@ -1,5 +1,5 @@ /* - * Copyright 2011 Red Hat Inc. + * Copyright 2012 Red Hat Inc. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -22,56 +22,154 @@ * Authors: Ben Skeggs */ -#include "drmP.h" -#include "nouveau_drv.h" -#include "nouveau_util.h" -#include +#include +#include +#include -struct nv98_ppp_engine { - struct nouveau_exec_engine base; +#include + +struct nv98_ppp_priv { + struct nouveau_ppp base; +}; + +struct nv98_ppp_chan { + struct nouveau_ppp_chan base; }; +/******************************************************************************* + * PPP object classes + ******************************************************************************/ + +static struct nouveau_oclass +nv98_ppp_sclass[] = { + {}, +}; + +/******************************************************************************* + * PPPP context + ******************************************************************************/ + static int -nv98_ppp_fini(struct drm_device *dev, int engine, bool suspend) +nv98_ppp_context_ctor(struct nouveau_object *parent, + struct nouveau_object *engine, + struct nouveau_oclass *oclass, void *data, u32 size, + struct nouveau_object **pobject) { - if (!(nv_rd32(dev, 0x000200) & 0x00000002)) - return 0; + struct nv98_ppp_chan *priv; + int ret; + + ret = nouveau_ppp_context_create(parent, engine, oclass, NULL, + 0, 0, 0, &priv); + *pobject = nv_object(priv); + if (ret) + return ret; - nv_mask(dev, 0x000200, 0x00000002, 0x00000000); return 0; } +static void +nv98_ppp_context_dtor(struct nouveau_object *object) +{ + struct nv98_ppp_chan *priv = (void *)object; + nouveau_ppp_context_destroy(&priv->base); +} + static int -nv98_ppp_init(struct drm_device *dev, int engine) +nv98_ppp_context_init(struct nouveau_object *object) { - nv_mask(dev, 0x000200, 0x00000002, 0x00000000); - nv_mask(dev, 0x000200, 0x00000002, 0x00000002); + struct nv98_ppp_chan *priv = (void *)object; + int ret; + + ret = nouveau_ppp_context_init(&priv->base); + if (ret) + return ret; + return 0; } +static int +nv98_ppp_context_fini(struct nouveau_object *object, bool suspend) +{ + struct nv98_ppp_chan *priv = (void *)object; + return nouveau_ppp_context_fini(&priv->base, suspend); +} + +static struct nouveau_oclass +nv98_ppp_cclass = { + .handle = NV_ENGCTX(PPP, 0x98), + .ofuncs = &(struct nouveau_ofuncs) { + .ctor = nv98_ppp_context_ctor, + .dtor = nv98_ppp_context_dtor, + .init = nv98_ppp_context_init, + .fini = nv98_ppp_context_fini, + .rd32 = _nouveau_ppp_context_rd32, + .wr32 = _nouveau_ppp_context_wr32, + }, +}; + +/******************************************************************************* + * PPPP engine/subdev functions + ******************************************************************************/ + static void -nv98_ppp_destroy(struct drm_device *dev, int engine) +nv98_ppp_intr(struct nouveau_subdev *subdev) { - struct nv98_ppp_engine *pppp = nv_engine(dev, engine); +} - NVOBJ_ENGINE_DEL(dev, PPP); +static int +nv98_ppp_ctor(struct nouveau_object *parent, struct nouveau_object *engine, + struct nouveau_oclass *oclass, void *data, u32 size, + struct nouveau_object **pobject) +{ + struct nv98_ppp_priv *priv; + int ret; + + ret = nouveau_ppp_create(parent, engine, oclass, &priv); + *pobject = nv_object(priv); + if (ret) + return ret; - kfree(pppp); + nv_subdev(priv)->unit = 0x00400002; + nv_subdev(priv)->intr = nv98_ppp_intr; + nv_engine(priv)->cclass = &nv98_ppp_cclass; + nv_engine(priv)->sclass = nv98_ppp_sclass; + return 0; } -int -nv98_ppp_create(struct drm_device *dev) +static void +nv98_ppp_dtor(struct nouveau_object *object) { - struct nv98_ppp_engine *pppp; + struct nv98_ppp_priv *priv = (void *)object; + nouveau_ppp_destroy(&priv->base); +} - pppp = kzalloc(sizeof(*pppp), GFP_KERNEL); - if (!pppp) - return -ENOMEM; +static int +nv98_ppp_init(struct nouveau_object *object) +{ + struct nv98_ppp_priv *priv = (void *)object; + int ret; - pppp->base.destroy = nv98_ppp_destroy; - pppp->base.init = nv98_ppp_init; - pppp->base.fini = nv98_ppp_fini; + ret = nouveau_ppp_init(&priv->base); + if (ret) + return ret; - NVOBJ_ENGINE_ADD(dev, PPP, &pppp->base); return 0; } + +static int +nv98_ppp_fini(struct nouveau_object *object, bool suspend) +{ + struct nv98_ppp_priv *priv = (void *)object; + return nouveau_ppp_fini(&priv->base, suspend); +} + +struct nouveau_oclass +nv98_ppp_oclass = { + .handle = NV_ENGINE(PPP, 0x98), + .ofuncs = &(struct nouveau_ofuncs) { + .ctor = nv98_ppp_ctor, + .dtor = nv98_ppp_dtor, + .init = nv98_ppp_init, + .fini = nv98_ppp_fini, + }, +}; diff --git a/drivers/gpu/drm/nouveau/core/engine/software/nv04.c b/drivers/gpu/drm/nouveau/core/engine/software/nv04.c new file mode 100644 index 000000000000..f48da7577cc6 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/engine/software/nv04.c @@ -0,0 +1,140 @@ +/* + * 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 +#include + +struct nv04_software_priv { + struct nouveau_software base; +}; + +struct nv04_software_chan { + struct nouveau_software_chan base; +}; + +/******************************************************************************* + * software object classes + ******************************************************************************/ + +static int +nv04_software_set_ref(struct nouveau_object *object, u32 mthd, + void *data, u32 size) +{ + struct nouveau_object *channel = (void *)nv_engctx(object->parent); + struct nouveau_fifo_chan *fifo = (void *)channel->parent; + atomic_set(&fifo->refcnt, *(u32*)data); + return 0; +} + +static int +nv04_software_flip(struct nouveau_object *object, u32 mthd, + void *args, u32 size) +{ + struct nv04_software_chan *chan = (void *)nv_engctx(object->parent); + if (chan->base.flip) + return chan->base.flip(chan->base.flip_data); + return -EINVAL; +} + +static struct nouveau_omthds +nv04_software_omthds[] = { + { 0x0150, nv04_software_set_ref }, + { 0x0500, nv04_software_flip }, + {} +}; + +static struct nouveau_oclass +nv04_software_sclass[] = { + { 0x006e, &nouveau_object_ofuncs, nv04_software_omthds }, + {} +}; + +/******************************************************************************* + * software context + ******************************************************************************/ + +static int +nv04_software_context_ctor(struct nouveau_object *parent, + struct nouveau_object *engine, + struct nouveau_oclass *oclass, void *data, u32 size, + struct nouveau_object **pobject) +{ + struct nv04_software_chan *chan; + int ret; + + ret = nouveau_software_context_create(parent, engine, oclass, &chan); + *pobject = nv_object(chan); + if (ret) + return ret; + + return 0; +} + +static struct nouveau_oclass +nv04_software_cclass = { + .handle = NV_ENGCTX(SW, 0x04), + .ofuncs = &(struct nouveau_ofuncs) { + .ctor = nv04_software_context_ctor, + .dtor = _nouveau_software_context_dtor, + .init = _nouveau_software_context_init, + .fini = _nouveau_software_context_fini, + }, +}; + +/******************************************************************************* + * software engine/subdev functions + ******************************************************************************/ + +static int +nv04_software_ctor(struct nouveau_object *parent, struct nouveau_object *engine, + struct nouveau_oclass *oclass, void *data, u32 size, + struct nouveau_object **pobject) +{ + struct nv04_software_priv *priv; + int ret; + + ret = nouveau_software_create(parent, engine, oclass, &priv); + *pobject = nv_object(priv); + if (ret) + return ret; + + nv_engine(priv)->cclass = &nv04_software_cclass; + nv_engine(priv)->sclass = nv04_software_sclass; + return 0; +} + +struct nouveau_oclass +nv04_software_oclass = { + .handle = NV_ENGINE(SW, 0x04), + .ofuncs = &(struct nouveau_ofuncs) { + .ctor = nv04_software_ctor, + .dtor = _nouveau_software_dtor, + .init = _nouveau_software_init, + .fini = _nouveau_software_fini, + }, +}; diff --git a/drivers/gpu/drm/nouveau/core/engine/software/nv10.c b/drivers/gpu/drm/nouveau/core/engine/software/nv10.c new file mode 100644 index 000000000000..46dada53d272 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/engine/software/nv10.c @@ -0,0 +1,128 @@ +/* + * Copyright 2012 Red Hat Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: Ben Skeggs + */ + +#include +#include +#include + +#include + +struct nv10_software_priv { + struct nouveau_software base; +}; + +struct nv10_software_chan { + struct nouveau_software_chan base; +}; + +/******************************************************************************* + * software object classes + ******************************************************************************/ + +static int +nv10_software_flip(struct nouveau_object *object, u32 mthd, + void *args, u32 size) +{ + struct nv10_software_chan *chan = (void *)nv_engctx(object->parent); + if (chan->base.flip) + return chan->base.flip(chan->base.flip_data); + return -EINVAL; +} + +static struct nouveau_omthds +nv10_software_omthds[] = { + { 0x0500, nv10_software_flip }, + {} +}; + +static struct nouveau_oclass +nv10_software_sclass[] = { + { 0x016e, &nouveau_object_ofuncs, nv10_software_omthds }, + {} +}; + +/******************************************************************************* + * software context + ******************************************************************************/ + +static int +nv10_software_context_ctor(struct nouveau_object *parent, + struct nouveau_object *engine, + struct nouveau_oclass *oclass, void *data, u32 size, + struct nouveau_object **pobject) +{ + struct nv10_software_chan *chan; + int ret; + + ret = nouveau_software_context_create(parent, engine, oclass, &chan); + *pobject = nv_object(chan); + if (ret) + return ret; + + return 0; +} + +static struct nouveau_oclass +nv10_software_cclass = { + .handle = NV_ENGCTX(SW, 0x04), + .ofuncs = &(struct nouveau_ofuncs) { + .ctor = nv10_software_context_ctor, + .dtor = _nouveau_software_context_dtor, + .init = _nouveau_software_context_init, + .fini = _nouveau_software_context_fini, + }, +}; + +/******************************************************************************* + * software engine/subdev functions + ******************************************************************************/ + +static int +nv10_software_ctor(struct nouveau_object *parent, struct nouveau_object *engine, + struct nouveau_oclass *oclass, void *data, u32 size, + struct nouveau_object **pobject) +{ + struct nv10_software_priv *priv; + int ret; + + ret = nouveau_software_create(parent, engine, oclass, &priv); + *pobject = nv_object(priv); + if (ret) + return ret; + + nv_engine(priv)->cclass = &nv10_software_cclass; + nv_engine(priv)->sclass = nv10_software_sclass; + return 0; +} + +struct nouveau_oclass +nv10_software_oclass = { + .handle = NV_ENGINE(SW, 0x10), + .ofuncs = &(struct nouveau_ofuncs) { + .ctor = nv10_software_ctor, + .dtor = _nouveau_software_dtor, + .init = _nouveau_software_init, + .fini = _nouveau_software_fini, + }, +}; diff --git a/drivers/gpu/drm/nouveau/core/engine/software/nv50.c b/drivers/gpu/drm/nouveau/core/engine/software/nv50.c new file mode 100644 index 000000000000..6b889713480d --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/engine/software/nv50.c @@ -0,0 +1,198 @@ +/* + * 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 +#include +#include + +#include +#include + +struct nv50_software_priv { + struct nouveau_software base; +}; + +struct nv50_software_chan { + struct nouveau_software_chan base; +}; + +/******************************************************************************* + * software object classes + ******************************************************************************/ + +static int +nv50_software_mthd_dma_vblsem(struct nouveau_object *object, u32 mthd, + void *args, u32 size) +{ + struct nv50_software_chan *chan = (void *)nv_engctx(object->parent); + struct nouveau_fifo_chan *fifo = (void *)nv_object(chan)->parent; + struct nouveau_handle *handle; + int ret = -EINVAL; + + handle = nouveau_namedb_get(nv_namedb(fifo), *(u32 *)args); + if (!handle) + return -ENOENT; + + if (nv_iclass(handle->object, NV_GPUOBJ_CLASS)) { + struct nouveau_gpuobj *gpuobj = nv_gpuobj(handle->object); + chan->base.vblank.ctxdma = gpuobj->node->offset >> 4; + ret = 0; + } + nouveau_namedb_put(handle); + return ret; +} + +static int +nv50_software_mthd_vblsem_offset(struct nouveau_object *object, u32 mthd, + void *args, u32 size) +{ + struct nv50_software_chan *chan = (void *)nv_engctx(object->parent); + chan->base.vblank.offset = *(u32 *)args; + return 0; +} + +static int +nv50_software_mthd_vblsem_value(struct nouveau_object *object, u32 mthd, + void *args, u32 size) +{ + struct nv50_software_chan *chan = (void *)nv_engctx(object->parent); + chan->base.vblank.value = *(u32 *)args; + return 0; +} + +static int +nv50_software_mthd_vblsem_release(struct nouveau_object *object, u32 mthd, + void *args, u32 size) +{ + struct nv50_software_chan *chan = (void *)nv_engctx(object->parent); + struct nouveau_disp *disp = nouveau_disp(object); + unsigned long flags; + u32 crtc = *(u32 *)args; + + if (crtc > 1) + return -EINVAL; + + disp->vblank.get(disp->vblank.data, crtc); + + spin_lock_irqsave(&disp->vblank.lock, flags); + list_add(&chan->base.vblank.head, &disp->vblank.list); + chan->base.vblank.crtc = crtc; + spin_unlock_irqrestore(&disp->vblank.lock, flags); + return 0; +} + +static int +nv50_software_mthd_flip(struct nouveau_object *object, u32 mthd, + void *args, u32 size) +{ + struct nv50_software_chan *chan = (void *)nv_engctx(object->parent); + if (chan->base.flip) + return chan->base.flip(chan->base.flip_data); + return -EINVAL; +} + +static struct nouveau_omthds +nv50_software_omthds[] = { + { 0x018c, nv50_software_mthd_dma_vblsem }, + { 0x0400, nv50_software_mthd_vblsem_offset }, + { 0x0404, nv50_software_mthd_vblsem_value }, + { 0x0408, nv50_software_mthd_vblsem_release }, + { 0x0500, nv50_software_mthd_flip }, + {} +}; + +static struct nouveau_oclass +nv50_software_sclass[] = { + { 0x506e, &nouveau_object_ofuncs, nv50_software_omthds }, + {} +}; + +/******************************************************************************* + * software context + ******************************************************************************/ + +static int +nv50_software_context_ctor(struct nouveau_object *parent, + struct nouveau_object *engine, + struct nouveau_oclass *oclass, void *data, u32 size, + struct nouveau_object **pobject) +{ + struct nv50_software_chan *chan; + int ret; + + ret = nouveau_software_context_create(parent, engine, oclass, &chan); + *pobject = nv_object(chan); + if (ret) + return ret; + + chan->base.vblank.channel = nv_gpuobj(parent->parent)->addr >> 12; + return 0; +} + +static struct nouveau_oclass +nv50_software_cclass = { + .handle = NV_ENGCTX(SW, 0x50), + .ofuncs = &(struct nouveau_ofuncs) { + .ctor = nv50_software_context_ctor, + .dtor = _nouveau_software_context_dtor, + .init = _nouveau_software_context_init, + .fini = _nouveau_software_context_fini, + }, +}; + +/******************************************************************************* + * software engine/subdev functions + ******************************************************************************/ + +static int +nv50_software_ctor(struct nouveau_object *parent, struct nouveau_object *engine, + struct nouveau_oclass *oclass, void *data, u32 size, + struct nouveau_object **pobject) +{ + struct nv50_software_priv *priv; + int ret; + + ret = nouveau_software_create(parent, engine, oclass, &priv); + *pobject = nv_object(priv); + if (ret) + return ret; + + nv_engine(priv)->cclass = &nv50_software_cclass; + nv_engine(priv)->sclass = nv50_software_sclass; + return 0; +} + +struct nouveau_oclass +nv50_software_oclass = { + .handle = NV_ENGINE(SW, 0x50), + .ofuncs = &(struct nouveau_ofuncs) { + .ctor = nv50_software_ctor, + .dtor = _nouveau_software_dtor, + .init = _nouveau_software_init, + .fini = _nouveau_software_fini, + }, +}; diff --git a/drivers/gpu/drm/nouveau/core/engine/software/nvc0.c b/drivers/gpu/drm/nouveau/core/engine/software/nvc0.c new file mode 100644 index 000000000000..e3be78f3a5d8 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/engine/software/nvc0.c @@ -0,0 +1,180 @@ +/* + * 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 +#include + +struct nvc0_software_priv { + struct nouveau_software base; +}; + +struct nvc0_software_chan { + struct nouveau_software_chan base; +}; + +/******************************************************************************* + * software object classes + ******************************************************************************/ + +static int +nvc0_software_mthd_vblsem_offset(struct nouveau_object *object, u32 mthd, + void *args, u32 size) +{ + struct nvc0_software_chan *chan = (void *)nv_engctx(object->parent); + u64 data = *(u32 *)args; + if (mthd == 0x0400) { + chan->base.vblank.offset &= 0x00ffffffffULL; + chan->base.vblank.offset |= data << 32; + } else { + chan->base.vblank.offset &= 0xff00000000ULL; + chan->base.vblank.offset |= data; + } + return 0; +} + +static int +nvc0_software_mthd_vblsem_value(struct nouveau_object *object, u32 mthd, + void *args, u32 size) +{ + struct nvc0_software_chan *chan = (void *)nv_engctx(object->parent); + chan->base.vblank.value = *(u32 *)args; + return 0; +} + +static int +nvc0_software_mthd_vblsem_release(struct nouveau_object *object, u32 mthd, + void *args, u32 size) +{ + struct nvc0_software_chan *chan = (void *)nv_engctx(object->parent); + struct nouveau_disp *disp = nouveau_disp(object); + unsigned long flags; + u32 crtc = *(u32 *)args; + + if ((nv_device(object)->card_type < NV_E0 && crtc > 1) || crtc > 3) + return -EINVAL; + + disp->vblank.get(disp->vblank.data, crtc); + + spin_lock_irqsave(&disp->vblank.lock, flags); + list_add(&chan->base.vblank.head, &disp->vblank.list); + chan->base.vblank.crtc = crtc; + spin_unlock_irqrestore(&disp->vblank.lock, flags); + return 0; +} + +static int +nvc0_software_mthd_flip(struct nouveau_object *object, u32 mthd, + void *args, u32 size) +{ + struct nvc0_software_chan *chan = (void *)nv_engctx(object->parent); + if (chan->base.flip) + return chan->base.flip(chan->base.flip_data); + return -EINVAL; +} + +static struct nouveau_omthds +nvc0_software_omthds[] = { + { 0x0400, nvc0_software_mthd_vblsem_offset }, + { 0x0404, nvc0_software_mthd_vblsem_offset }, + { 0x0408, nvc0_software_mthd_vblsem_value }, + { 0x040c, nvc0_software_mthd_vblsem_release }, + { 0x0500, nvc0_software_mthd_flip }, + {} +}; + +static struct nouveau_oclass +nvc0_software_sclass[] = { + { 0x906e, &nouveau_object_ofuncs, nvc0_software_omthds }, + {} +}; + +/******************************************************************************* + * software context + ******************************************************************************/ + +static int +nvc0_software_context_ctor(struct nouveau_object *parent, + struct nouveau_object *engine, + struct nouveau_oclass *oclass, void *data, u32 size, + struct nouveau_object **pobject) +{ + struct nvc0_software_chan *chan; + int ret; + + ret = nouveau_software_context_create(parent, engine, oclass, &chan); + *pobject = nv_object(chan); + if (ret) + return ret; + + chan->base.vblank.channel = nv_gpuobj(parent->parent)->addr >> 12; + return 0; +} + +static struct nouveau_oclass +nvc0_software_cclass = { + .handle = NV_ENGCTX(SW, 0xc0), + .ofuncs = &(struct nouveau_ofuncs) { + .ctor = nvc0_software_context_ctor, + .dtor = _nouveau_software_context_dtor, + .init = _nouveau_software_context_init, + .fini = _nouveau_software_context_fini, + }, +}; + +/******************************************************************************* + * software engine/subdev functions + ******************************************************************************/ + +static int +nvc0_software_ctor(struct nouveau_object *parent, struct nouveau_object *engine, + struct nouveau_oclass *oclass, void *data, u32 size, + struct nouveau_object **pobject) +{ + struct nvc0_software_priv *priv; + int ret; + + ret = nouveau_software_create(parent, engine, oclass, &priv); + *pobject = nv_object(priv); + if (ret) + return ret; + + nv_engine(priv)->cclass = &nvc0_software_cclass; + nv_engine(priv)->sclass = nvc0_software_sclass; + return 0; +} + +struct nouveau_oclass +nvc0_software_oclass = { + .handle = NV_ENGINE(SW, 0xc0), + .ofuncs = &(struct nouveau_ofuncs) { + .ctor = nvc0_software_ctor, + .dtor = _nouveau_software_dtor, + .init = _nouveau_software_init, + .fini = _nouveau_software_fini, + }, +}; diff --git a/drivers/gpu/drm/nouveau/core/engine/vp/nv84.c b/drivers/gpu/drm/nouveau/core/engine/vp/nv84.c index 5e164a684aec..dd23c80e5405 100644 --- a/drivers/gpu/drm/nouveau/core/engine/vp/nv84.c +++ b/drivers/gpu/drm/nouveau/core/engine/vp/nv84.c @@ -1,5 +1,5 @@ /* - * Copyright 2011 Red Hat Inc. + * Copyright 2012 Red Hat Inc. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -22,61 +22,154 @@ * Authors: Ben Skeggs */ -#include "drmP.h" -#include "nouveau_drv.h" -#include "nouveau_util.h" -#include +#include +#include +#include -/*XXX: This stub is currently used on NV98+ also, as soon as this becomes - * more than just an enable/disable stub this needs to be split out to - * nv98_vp.c... - */ +#include + +struct nv84_vp_priv { + struct nouveau_vp base; +}; -struct nv84_vp_engine { - struct nouveau_exec_engine base; +struct nv84_vp_chan { + struct nouveau_vp_chan base; }; +/******************************************************************************* + * VP object classes + ******************************************************************************/ + +static struct nouveau_oclass +nv84_vp_sclass[] = { + {}, +}; + +/******************************************************************************* + * PVP context + ******************************************************************************/ + static int -nv84_vp_fini(struct drm_device *dev, int engine, bool suspend) +nv84_vp_context_ctor(struct nouveau_object *parent, + struct nouveau_object *engine, + struct nouveau_oclass *oclass, void *data, u32 size, + struct nouveau_object **pobject) { - if (!(nv_rd32(dev, 0x000200) & 0x00020000)) - return 0; + struct nv84_vp_chan *priv; + int ret; + + ret = nouveau_vp_context_create(parent, engine, oclass, NULL, + 0, 0, 0, &priv); + *pobject = nv_object(priv); + if (ret) + return ret; - nv_mask(dev, 0x000200, 0x00020000, 0x00000000); return 0; } +static void +nv84_vp_context_dtor(struct nouveau_object *object) +{ + struct nv84_vp_chan *priv = (void *)object; + nouveau_vp_context_destroy(&priv->base); +} + static int -nv84_vp_init(struct drm_device *dev, int engine) +nv84_vp_context_init(struct nouveau_object *object) { - nv_mask(dev, 0x000200, 0x00020000, 0x00000000); - nv_mask(dev, 0x000200, 0x00020000, 0x00020000); + struct nv84_vp_chan *priv = (void *)object; + int ret; + + ret = nouveau_vp_context_init(&priv->base); + if (ret) + return ret; + return 0; } +static int +nv84_vp_context_fini(struct nouveau_object *object, bool suspend) +{ + struct nv84_vp_chan *priv = (void *)object; + return nouveau_vp_context_fini(&priv->base, suspend); +} + +static struct nouveau_oclass +nv84_vp_cclass = { + .handle = NV_ENGCTX(VP, 0x84), + .ofuncs = &(struct nouveau_ofuncs) { + .ctor = nv84_vp_context_ctor, + .dtor = nv84_vp_context_dtor, + .init = nv84_vp_context_init, + .fini = nv84_vp_context_fini, + .rd32 = _nouveau_vp_context_rd32, + .wr32 = _nouveau_vp_context_wr32, + }, +}; + +/******************************************************************************* + * PVP engine/subdev functions + ******************************************************************************/ + static void -nv84_vp_destroy(struct drm_device *dev, int engine) +nv84_vp_intr(struct nouveau_subdev *subdev) { - struct nv84_vp_engine *pvp = nv_engine(dev, engine); +} - NVOBJ_ENGINE_DEL(dev, VP); +static int +nv84_vp_ctor(struct nouveau_object *parent, struct nouveau_object *engine, + struct nouveau_oclass *oclass, void *data, u32 size, + struct nouveau_object **pobject) +{ + struct nv84_vp_priv *priv; + int ret; + + ret = nouveau_vp_create(parent, engine, oclass, &priv); + *pobject = nv_object(priv); + if (ret) + return ret; - kfree(pvp); + nv_subdev(priv)->unit = 0x01020000; + nv_subdev(priv)->intr = nv84_vp_intr; + nv_engine(priv)->cclass = &nv84_vp_cclass; + nv_engine(priv)->sclass = nv84_vp_sclass; + return 0; } -int -nv84_vp_create(struct drm_device *dev) +static void +nv84_vp_dtor(struct nouveau_object *object) { - struct nv84_vp_engine *pvp; + struct nv84_vp_priv *priv = (void *)object; + nouveau_vp_destroy(&priv->base); +} - pvp = kzalloc(sizeof(*pvp), GFP_KERNEL); - if (!pvp) - return -ENOMEM; +static int +nv84_vp_init(struct nouveau_object *object) +{ + struct nv84_vp_priv *priv = (void *)object; + int ret; - pvp->base.destroy = nv84_vp_destroy; - pvp->base.init = nv84_vp_init; - pvp->base.fini = nv84_vp_fini; + ret = nouveau_vp_init(&priv->base); + if (ret) + return ret; - NVOBJ_ENGINE_ADD(dev, VP, &pvp->base); return 0; } + +static int +nv84_vp_fini(struct nouveau_object *object, bool suspend) +{ + struct nv84_vp_priv *priv = (void *)object; + return nouveau_vp_fini(&priv->base, suspend); +} + +struct nouveau_oclass +nv84_vp_oclass = { + .handle = NV_ENGINE(VP, 0x84), + .ofuncs = &(struct nouveau_ofuncs) { + .ctor = nv84_vp_ctor, + .dtor = nv84_vp_dtor, + .init = nv84_vp_init, + .fini = nv84_vp_fini, + }, +}; diff --git a/drivers/gpu/drm/nouveau/core/include/core/ramht.h b/drivers/gpu/drm/nouveau/core/include/core/ramht.h index c82de98fee0e..47e4cacbca37 100644 --- a/drivers/gpu/drm/nouveau/core/include/core/ramht.h +++ b/drivers/gpu/drm/nouveau/core/include/core/ramht.h @@ -1,55 +1,23 @@ -/* - * Copyright 2010 Red Hat Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: Ben Skeggs - */ - #ifndef __NOUVEAU_RAMHT_H__ #define __NOUVEAU_RAMHT_H__ -struct nouveau_ramht_entry { - struct list_head head; - struct nouveau_channel *channel; - struct nouveau_gpuobj *gpuobj; - u32 handle; -}; +#include struct nouveau_ramht { - struct drm_device *dev; - struct kref refcount; - spinlock_t lock; - struct nouveau_gpuobj *gpuobj; - struct list_head entries; + struct nouveau_gpuobj base; int bits; }; -extern int nouveau_ramht_new(struct drm_device *, struct nouveau_gpuobj *, - struct nouveau_ramht **); -extern void nouveau_ramht_ref(struct nouveau_ramht *, struct nouveau_ramht **, - struct nouveau_channel *unref_channel); +int nouveau_ramht_insert(struct nouveau_ramht *, int chid, + u32 handle, u32 context); +void nouveau_ramht_remove(struct nouveau_ramht *, int cookie); +int nouveau_ramht_new(struct nouveau_object *, struct nouveau_object *, + u32 size, u32 align, struct nouveau_ramht **); -extern int nouveau_ramht_insert(struct nouveau_channel *, u32 handle, - struct nouveau_gpuobj *); -extern int nouveau_ramht_remove(struct nouveau_channel *, u32 handle); -extern struct nouveau_gpuobj * -nouveau_ramht_find(struct nouveau_channel *chan, u32 handle); +static inline void +nouveau_ramht_ref(struct nouveau_ramht *obj, struct nouveau_ramht **ref) +{ + nouveau_gpuobj_ref(&obj->base, (struct nouveau_gpuobj **)ref); +} #endif diff --git a/drivers/gpu/drm/nouveau/core/include/engine/bsp.h b/drivers/gpu/drm/nouveau/core/include/engine/bsp.h new file mode 100644 index 000000000000..75d1ed5f85fd --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/include/engine/bsp.h @@ -0,0 +1,45 @@ +#ifndef __NOUVEAU_BSP_H__ +#define __NOUVEAU_BSP_H__ + +#include +#include + +struct nouveau_bsp_chan { + struct nouveau_engctx base; +}; + +#define nouveau_bsp_context_create(p,e,c,g,s,a,f,d) \ + nouveau_engctx_create((p), (e), (c), (g), (s), (a), (f), (d)) +#define nouveau_bsp_context_destroy(d) \ + nouveau_engctx_destroy(&(d)->base) +#define nouveau_bsp_context_init(d) \ + nouveau_engctx_init(&(d)->base) +#define nouveau_bsp_context_fini(d,s) \ + nouveau_engctx_fini(&(d)->base, (s)) + +#define _nouveau_bsp_context_dtor _nouveau_engctx_dtor +#define _nouveau_bsp_context_init _nouveau_engctx_init +#define _nouveau_bsp_context_fini _nouveau_engctx_fini +#define _nouveau_bsp_context_rd32 _nouveau_engctx_rd32 +#define _nouveau_bsp_context_wr32 _nouveau_engctx_wr32 + +struct nouveau_bsp { + struct nouveau_engine base; +}; + +#define nouveau_bsp_create(p,e,c,d) \ + nouveau_engine_create((p), (e), (c), true, "PBSP", "bsp", (d)) +#define nouveau_bsp_destroy(d) \ + nouveau_engine_destroy(&(d)->base) +#define nouveau_bsp_init(d) \ + nouveau_engine_init(&(d)->base) +#define nouveau_bsp_fini(d,s) \ + nouveau_engine_fini(&(d)->base, (s)) + +#define _nouveau_bsp_dtor _nouveau_engine_dtor +#define _nouveau_bsp_init _nouveau_engine_init +#define _nouveau_bsp_fini _nouveau_engine_fini + +extern struct nouveau_oclass nv84_bsp_oclass; + +#endif diff --git a/drivers/gpu/drm/nouveau/core/include/engine/copy.h b/drivers/gpu/drm/nouveau/core/include/engine/copy.h new file mode 100644 index 000000000000..23bb9dfeaf67 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/include/engine/copy.h @@ -0,0 +1,47 @@ +#ifndef __NOUVEAU_COPY_H__ +#define __NOUVEAU_COPY_H__ + +#include +#include + +struct nouveau_copy_chan { + struct nouveau_engctx base; +}; + +#define nouveau_copy_context_create(p,e,c,g,s,a,f,d) \ + nouveau_engctx_create((p), (e), (c), (g), (s), (a), (f), (d)) +#define nouveau_copy_context_destroy(d) \ + nouveau_engctx_destroy(&(d)->base) +#define nouveau_copy_context_init(d) \ + nouveau_engctx_init(&(d)->base) +#define nouveau_copy_context_fini(d,s) \ + nouveau_engctx_fini(&(d)->base, (s)) + +#define _nouveau_copy_context_dtor _nouveau_engctx_dtor +#define _nouveau_copy_context_init _nouveau_engctx_init +#define _nouveau_copy_context_fini _nouveau_engctx_fini +#define _nouveau_copy_context_rd32 _nouveau_engctx_rd32 +#define _nouveau_copy_context_wr32 _nouveau_engctx_wr32 + +struct nouveau_copy { + struct nouveau_engine base; +}; + +#define nouveau_copy_create(p,e,c,y,i,d) \ + nouveau_engine_create((p), (e), (c), (y), "PCE"#i, "copy"#i, (d)) +#define nouveau_copy_destroy(d) \ + nouveau_engine_destroy(&(d)->base) +#define nouveau_copy_init(d) \ + nouveau_engine_init(&(d)->base) +#define nouveau_copy_fini(d,s) \ + nouveau_engine_fini(&(d)->base, (s)) + +#define _nouveau_copy_dtor _nouveau_engine_dtor +#define _nouveau_copy_init _nouveau_engine_init +#define _nouveau_copy_fini _nouveau_engine_fini + +extern struct nouveau_oclass nva3_copy_oclass; +extern struct nouveau_oclass nvc0_copy0_oclass; +extern struct nouveau_oclass nvc0_copy1_oclass; + +#endif diff --git a/drivers/gpu/drm/nouveau/core/include/engine/crypt.h b/drivers/gpu/drm/nouveau/core/include/engine/crypt.h new file mode 100644 index 000000000000..e3674743baaa --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/include/engine/crypt.h @@ -0,0 +1,46 @@ +#ifndef __NOUVEAU_CRYPT_H__ +#define __NOUVEAU_CRYPT_H__ + +#include +#include + +struct nouveau_crypt_chan { + struct nouveau_engctx base; +}; + +#define nouveau_crypt_context_create(p,e,c,g,s,a,f,d) \ + nouveau_engctx_create((p), (e), (c), (g), (s), (a), (f), (d)) +#define nouveau_crypt_context_destroy(d) \ + nouveau_engctx_destroy(&(d)->base) +#define nouveau_crypt_context_init(d) \ + nouveau_engctx_init(&(d)->base) +#define nouveau_crypt_context_fini(d,s) \ + nouveau_engctx_fini(&(d)->base, (s)) + +#define _nouveau_crypt_context_dtor _nouveau_engctx_dtor +#define _nouveau_crypt_context_init _nouveau_engctx_init +#define _nouveau_crypt_context_fini _nouveau_engctx_fini +#define _nouveau_crypt_context_rd32 _nouveau_engctx_rd32 +#define _nouveau_crypt_context_wr32 _nouveau_engctx_wr32 + +struct nouveau_crypt { + struct nouveau_engine base; +}; + +#define nouveau_crypt_create(p,e,c,d) \ + nouveau_engine_create((p), (e), (c), true, "PCRYPT", "crypt", (d)) +#define nouveau_crypt_destroy(d) \ + nouveau_engine_destroy(&(d)->base) +#define nouveau_crypt_init(d) \ + nouveau_engine_init(&(d)->base) +#define nouveau_crypt_fini(d,s) \ + nouveau_engine_fini(&(d)->base, (s)) + +#define _nouveau_crypt_dtor _nouveau_engine_dtor +#define _nouveau_crypt_init _nouveau_engine_init +#define _nouveau_crypt_fini _nouveau_engine_fini + +extern struct nouveau_oclass nv84_crypt_oclass; +extern struct nouveau_oclass nv98_crypt_oclass; + +#endif diff --git a/drivers/gpu/drm/nouveau/core/include/engine/disp.h b/drivers/gpu/drm/nouveau/core/include/engine/disp.h new file mode 100644 index 000000000000..38ec1252cbaa --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/include/engine/disp.h @@ -0,0 +1,44 @@ +#ifndef __NOUVEAU_DISP_H__ +#define __NOUVEAU_DISP_H__ + +#include +#include +#include + +struct nouveau_disp { + struct nouveau_engine base; + + struct { + struct list_head list; + spinlock_t lock; + void (*notify)(void *, int); + void (*get)(void *, int); + void (*put)(void *, int); + void *data; + } vblank; +}; + +static inline struct nouveau_disp * +nouveau_disp(void *obj) +{ + return (void *)nv_device(obj)->subdev[NVDEV_ENGINE_DISP]; +} + +#define nouveau_disp_create(p,e,c,i,x,d) \ + nouveau_engine_create((p), (e), (c), true, (i), (x), (d)) +#define nouveau_disp_destroy(d) \ + nouveau_engine_destroy(&(d)->base) +#define nouveau_disp_init(d) \ + nouveau_engine_init(&(d)->base) +#define nouveau_disp_fini(d,s) \ + nouveau_engine_fini(&(d)->base, (s)) + +#define _nouveau_disp_dtor _nouveau_engine_dtor +#define _nouveau_disp_init _nouveau_engine_init +#define _nouveau_disp_fini _nouveau_engine_fini + +extern struct nouveau_oclass nv04_disp_oclass; +extern struct nouveau_oclass nv50_disp_oclass; +extern struct nouveau_oclass nvd0_disp_oclass; + +#endif diff --git a/drivers/gpu/drm/nouveau/core/include/engine/dmaobj.h b/drivers/gpu/drm/nouveau/core/include/engine/dmaobj.h new file mode 100644 index 000000000000..700ccbb1941f --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/include/engine/dmaobj.h @@ -0,0 +1,57 @@ +#ifndef __NOUVEAU_DMAOBJ_H__ +#define __NOUVEAU_DMAOBJ_H__ + +#include +#include + +struct nouveau_gpuobj; + +struct nouveau_dmaobj { + struct nouveau_object base; + u32 target; + u32 access; + u64 start; + u64 limit; +}; + +#define nouveau_dmaobj_create(p,e,c,a,s,d) \ + nouveau_dmaobj_create_((p), (e), (c), (a), (s), sizeof(**d), (void **)d) +#define nouveau_dmaobj_destroy(p) \ + nouveau_object_destroy(&(p)->base) +#define nouveau_dmaobj_init(p) \ + nouveau_object_init(&(p)->base) +#define nouveau_dmaobj_fini(p,s) \ + nouveau_object_fini(&(p)->base, (s)) + +int nouveau_dmaobj_create_(struct nouveau_object *, struct nouveau_object *, + struct nouveau_oclass *, void *data, u32 size, + int length, void **); + +#define _nouveau_dmaobj_dtor nouveau_object_destroy +#define _nouveau_dmaobj_init nouveau_object_init +#define _nouveau_dmaobj_fini nouveau_object_fini + +struct nouveau_dmaeng { + struct nouveau_engine base; + int (*bind)(struct nouveau_dmaeng *, struct nouveau_object *parent, + struct nouveau_dmaobj *, struct nouveau_gpuobj **); +}; + +#define nouveau_dmaeng_create(p,e,c,d) \ + nouveau_engine_create((p), (e), (c), true, "DMAOBJ", "dmaobj", (d)) +#define nouveau_dmaeng_destroy(p) \ + nouveau_engine_destroy(&(p)->base) +#define nouveau_dmaeng_init(p) \ + nouveau_engine_init(&(p)->base) +#define nouveau_dmaeng_fini(p,s) \ + nouveau_engine_fini(&(p)->base, (s)) + +#define _nouveau_dmaeng_dtor _nouveau_engine_dtor +#define _nouveau_dmaeng_init _nouveau_engine_init +#define _nouveau_dmaeng_fini _nouveau_engine_fini + +extern struct nouveau_oclass nv04_dmaeng_oclass; +extern struct nouveau_oclass nv50_dmaeng_oclass; +extern struct nouveau_oclass nvc0_dmaeng_oclass; + +#endif diff --git a/drivers/gpu/drm/nouveau/core/include/engine/fifo.h b/drivers/gpu/drm/nouveau/core/include/engine/fifo.h index ce99cab2f257..65ee929a75f0 100644 --- a/drivers/gpu/drm/nouveau/core/include/engine/fifo.h +++ b/drivers/gpu/drm/nouveau/core/include/engine/fifo.h @@ -1,32 +1,109 @@ #ifndef __NOUVEAU_FIFO_H__ #define __NOUVEAU_FIFO_H__ -struct nouveau_fifo_priv { - struct nouveau_exec_engine base; - u32 channels; -}; +#include +#include +#include struct nouveau_fifo_chan { + struct nouveau_namedb base; + struct nouveau_dmaobj *pushdma; + struct nouveau_gpuobj *pushgpu; + void __iomem *user; + u32 size; + u16 chid; + atomic_t refcnt; /* NV04_NVSW_SET_REF */ +}; + +static inline struct nouveau_fifo_chan * +nouveau_fifo_chan(void *obj) +{ + return (void *)nv_namedb(obj); +} + +#define nouveau_fifo_channel_create(p,e,c,b,a,s,n,m,d) \ + nouveau_fifo_channel_create_((p), (e), (c), (b), (a), (s), (n), \ + (m), sizeof(**d), (void **)d) +#define nouveau_fifo_channel_init(p) \ + nouveau_namedb_init(&(p)->base) +#define nouveau_fifo_channel_fini(p,s) \ + nouveau_namedb_fini(&(p)->base, (s)) + +int nouveau_fifo_channel_create_(struct nouveau_object *, + struct nouveau_object *, + struct nouveau_oclass *, + int bar, u32 addr, u32 size, u32 push, + u32 engmask, int len, void **); +void nouveau_fifo_channel_destroy(struct nouveau_fifo_chan *); + +#define _nouveau_fifo_channel_init _nouveau_namedb_init +#define _nouveau_fifo_channel_fini _nouveau_namedb_fini + +void _nouveau_fifo_channel_dtor(struct nouveau_object *); +u32 _nouveau_fifo_channel_rd32(struct nouveau_object *, u32); +void _nouveau_fifo_channel_wr32(struct nouveau_object *, u32, u32); + +struct nouveau_fifo_base { + struct nouveau_gpuobj base; }; -bool nv04_fifo_cache_pull(struct drm_device *, bool); -void nv04_fifo_context_del(struct nouveau_channel *, int); -int nv04_fifo_fini(struct drm_device *, int, bool); -int nv04_fifo_init(struct drm_device *, int); -void nv04_fifo_isr(struct drm_device *); -void nv04_fifo_destroy(struct drm_device *, int); - -void nv50_fifo_playlist_update(struct drm_device *); -void nv50_fifo_destroy(struct drm_device *, int); -void nv50_fifo_tlb_flush(struct drm_device *, int); - -int nv04_fifo_create(struct drm_device *); -int nv10_fifo_create(struct drm_device *); -int nv17_fifo_create(struct drm_device *); -int nv40_fifo_create(struct drm_device *); -int nv50_fifo_create(struct drm_device *); -int nv84_fifo_create(struct drm_device *); -int nvc0_fifo_create(struct drm_device *); -int nve0_fifo_create(struct drm_device *); +#define nouveau_fifo_context_create(p,e,c,g,s,a,f,d) \ + nouveau_gpuobj_create((p), (e), (c), 0, (g), (s), (a), (f), (d)) +#define nouveau_fifo_context_destroy(p) \ + nouveau_gpuobj_destroy(&(p)->base) +#define nouveau_fifo_context_init(p) \ + nouveau_gpuobj_init(&(p)->base) +#define nouveau_fifo_context_fini(p,s) \ + nouveau_gpuobj_fini(&(p)->base, (s)) + +#define _nouveau_fifo_context_dtor _nouveau_gpuobj_dtor +#define _nouveau_fifo_context_init _nouveau_gpuobj_init +#define _nouveau_fifo_context_fini _nouveau_gpuobj_fini +#define _nouveau_fifo_context_rd32 _nouveau_gpuobj_rd32 +#define _nouveau_fifo_context_wr32 _nouveau_gpuobj_wr32 + +struct nouveau_fifo { + struct nouveau_engine base; + + struct nouveau_object **channel; + spinlock_t lock; + u16 min; + u16 max; + + void (*pause)(struct nouveau_fifo *, unsigned long *); + void (*start)(struct nouveau_fifo *, unsigned long *); +}; + +static inline struct nouveau_fifo * +nouveau_fifo(void *obj) +{ + return (void *)nv_device(obj)->subdev[NVDEV_ENGINE_FIFO]; +} + +#define nouveau_fifo_create(o,e,c,fc,lc,d) \ + nouveau_fifo_create_((o), (e), (c), (fc), (lc), sizeof(**d), (void **)d) +#define nouveau_fifo_init(p) \ + nouveau_engine_init(&(p)->base) +#define nouveau_fifo_fini(p,s) \ + nouveau_engine_fini(&(p)->base, (s)) + +int nouveau_fifo_create_(struct nouveau_object *, struct nouveau_object *, + struct nouveau_oclass *, int min, int max, + int size, void **); +void nouveau_fifo_destroy(struct nouveau_fifo *); + +#define _nouveau_fifo_init _nouveau_engine_init +#define _nouveau_fifo_fini _nouveau_engine_fini + +extern struct nouveau_oclass nv04_fifo_oclass; +extern struct nouveau_oclass nv10_fifo_oclass; +extern struct nouveau_oclass nv17_fifo_oclass; +extern struct nouveau_oclass nv40_fifo_oclass; +extern struct nouveau_oclass nv50_fifo_oclass; +extern struct nouveau_oclass nv84_fifo_oclass; +extern struct nouveau_oclass nvc0_fifo_oclass; +extern struct nouveau_oclass nve0_fifo_oclass; + +void nv04_fifo_intr(struct nouveau_subdev *); #endif diff --git a/drivers/gpu/drm/nouveau/core/include/engine/graph.h b/drivers/gpu/drm/nouveau/core/include/engine/graph.h new file mode 100644 index 000000000000..388cfcff7bd0 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/include/engine/graph.h @@ -0,0 +1,72 @@ +#ifndef __NOUVEAU_GRAPH_H__ +#define __NOUVEAU_GRAPH_H__ + +#include +#include +#include + +struct nouveau_graph_chan { + struct nouveau_engctx base; +}; + +#define nouveau_graph_context_create(p,e,c,g,s,a,f,d) \ + nouveau_engctx_create((p), (e), (c), (g), (s), (a), (f), (d)) +#define nouveau_graph_context_destroy(d) \ + nouveau_engctx_destroy(&(d)->base) +#define nouveau_graph_context_init(d) \ + nouveau_engctx_init(&(d)->base) +#define nouveau_graph_context_fini(d,s) \ + nouveau_engctx_fini(&(d)->base, (s)) + +#define _nouveau_graph_context_dtor _nouveau_engctx_dtor +#define _nouveau_graph_context_init _nouveau_engctx_init +#define _nouveau_graph_context_fini _nouveau_engctx_fini +#define _nouveau_graph_context_rd32 _nouveau_engctx_rd32 +#define _nouveau_graph_context_wr32 _nouveau_engctx_wr32 + +struct nouveau_graph { + struct nouveau_engine base; +}; + +static inline struct nouveau_graph * +nouveau_graph(void *obj) +{ + return (void *)nv_device(obj)->subdev[NVDEV_ENGINE_GR]; +} + +#define nouveau_graph_create(p,e,c,y,d) \ + nouveau_engine_create((p), (e), (c), (y), "PGRAPH", "graphics", (d)) +#define nouveau_graph_destroy(d) \ + nouveau_engine_destroy(&(d)->base) +#define nouveau_graph_init(d) \ + nouveau_engine_init(&(d)->base) +#define nouveau_graph_fini(d,s) \ + nouveau_engine_fini(&(d)->base, (s)) + +#define _nouveau_graph_dtor _nouveau_engine_dtor +#define _nouveau_graph_init _nouveau_engine_init +#define _nouveau_graph_fini _nouveau_engine_fini + +extern struct nouveau_oclass nv04_graph_oclass; +extern struct nouveau_oclass nv10_graph_oclass; +extern struct nouveau_oclass nv20_graph_oclass; +extern struct nouveau_oclass nv25_graph_oclass; +extern struct nouveau_oclass nv2a_graph_oclass; +extern struct nouveau_oclass nv30_graph_oclass; +extern struct nouveau_oclass nv34_graph_oclass; +extern struct nouveau_oclass nv35_graph_oclass; +extern struct nouveau_oclass nv40_graph_oclass; +extern struct nouveau_oclass nv50_graph_oclass; +extern struct nouveau_oclass nvc0_graph_oclass; +extern struct nouveau_oclass nve0_graph_oclass; + +extern struct nouveau_bitfield nv04_graph_nsource[]; +extern struct nouveau_ofuncs nv04_graph_ofuncs; +bool nv04_graph_idle(void *obj); + +extern struct nouveau_bitfield nv10_graph_intr_name[]; +extern struct nouveau_bitfield nv10_graph_nstatus[]; + +extern struct nouveau_enum nv50_data_error_names[]; + +#endif diff --git a/drivers/gpu/drm/nouveau/core/include/engine/mpeg.h b/drivers/gpu/drm/nouveau/core/include/engine/mpeg.h new file mode 100644 index 000000000000..bbf0d4a5bbd7 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/include/engine/mpeg.h @@ -0,0 +1,61 @@ +#ifndef __NOUVEAU_MPEG_H__ +#define __NOUVEAU_MPEG_H__ + +#include +#include + +struct nouveau_mpeg_chan { + struct nouveau_engctx base; +}; + +#define nouveau_mpeg_context_create(p,e,c,g,s,a,f,d) \ + nouveau_engctx_create((p), (e), (c), (g), (s), (a), (f), (d)) +#define nouveau_mpeg_context_destroy(d) \ + nouveau_engctx_destroy(&(d)->base) +#define nouveau_mpeg_context_init(d) \ + nouveau_engctx_init(&(d)->base) +#define nouveau_mpeg_context_fini(d,s) \ + nouveau_engctx_fini(&(d)->base, (s)) + +#define _nouveau_mpeg_context_dtor _nouveau_engctx_dtor +#define _nouveau_mpeg_context_init _nouveau_engctx_init +#define _nouveau_mpeg_context_fini _nouveau_engctx_fini +#define _nouveau_mpeg_context_rd32 _nouveau_engctx_rd32 +#define _nouveau_mpeg_context_wr32 _nouveau_engctx_wr32 + +struct nouveau_mpeg { + struct nouveau_engine base; +}; + +#define nouveau_mpeg_create(p,e,c,d) \ + nouveau_engine_create((p), (e), (c), true, "PMPEG", "mpeg", (d)) +#define nouveau_mpeg_destroy(d) \ + nouveau_engine_destroy(&(d)->base) +#define nouveau_mpeg_init(d) \ + nouveau_engine_init(&(d)->base) +#define nouveau_mpeg_fini(d,s) \ + nouveau_engine_fini(&(d)->base, (s)) + +#define _nouveau_mpeg_dtor _nouveau_engine_dtor +#define _nouveau_mpeg_init _nouveau_engine_init +#define _nouveau_mpeg_fini _nouveau_engine_fini + +extern struct nouveau_oclass nv31_mpeg_oclass; +extern struct nouveau_oclass nv40_mpeg_oclass; +extern struct nouveau_oclass nv50_mpeg_oclass; +extern struct nouveau_oclass nv84_mpeg_oclass; + +extern struct nouveau_oclass nv31_mpeg_sclass[]; +void nv31_mpeg_intr(struct nouveau_subdev *); +void nv31_mpeg_tile_prog(struct nouveau_engine *, int); +int nv31_mpeg_init(struct nouveau_object *); + +extern struct nouveau_ofuncs nv50_mpeg_ofuncs; +int nv50_mpeg_context_ctor(struct nouveau_object *, struct nouveau_object *, + struct nouveau_oclass *, void *, u32, + struct nouveau_object **); +int nv50_mpeg_tlb_flush(struct nouveau_engine *); +void nv50_mpeg_intr(struct nouveau_subdev *); +int nv50_mpeg_init(struct nouveau_object *); + +#endif diff --git a/drivers/gpu/drm/nouveau/core/include/engine/ppp.h b/drivers/gpu/drm/nouveau/core/include/engine/ppp.h new file mode 100644 index 000000000000..74d554fb3281 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/include/engine/ppp.h @@ -0,0 +1,45 @@ +#ifndef __NOUVEAU_PPP_H__ +#define __NOUVEAU_PPP_H__ + +#include +#include + +struct nouveau_ppp_chan { + struct nouveau_engctx base; +}; + +#define nouveau_ppp_context_create(p,e,c,g,s,a,f,d) \ + nouveau_engctx_create((p), (e), (c), (g), (s), (a), (f), (d)) +#define nouveau_ppp_context_destroy(d) \ + nouveau_engctx_destroy(&(d)->base) +#define nouveau_ppp_context_init(d) \ + nouveau_engctx_init(&(d)->base) +#define nouveau_ppp_context_fini(d,s) \ + nouveau_engctx_fini(&(d)->base, (s)) + +#define _nouveau_ppp_context_dtor _nouveau_engctx_dtor +#define _nouveau_ppp_context_init _nouveau_engctx_init +#define _nouveau_ppp_context_fini _nouveau_engctx_fini +#define _nouveau_ppp_context_rd32 _nouveau_engctx_rd32 +#define _nouveau_ppp_context_wr32 _nouveau_engctx_wr32 + +struct nouveau_ppp { + struct nouveau_engine base; +}; + +#define nouveau_ppp_create(p,e,c,d) \ + nouveau_engine_create((p), (e), (c), true, "PPPP", "ppp", (d)) +#define nouveau_ppp_destroy(d) \ + nouveau_engine_destroy(&(d)->base) +#define nouveau_ppp_init(d) \ + nouveau_engine_init(&(d)->base) +#define nouveau_ppp_fini(d,s) \ + nouveau_engine_fini(&(d)->base, (s)) + +#define _nouveau_ppp_dtor _nouveau_engine_dtor +#define _nouveau_ppp_init _nouveau_engine_init +#define _nouveau_ppp_fini _nouveau_engine_fini + +extern struct nouveau_oclass nv98_ppp_oclass; + +#endif diff --git a/drivers/gpu/drm/nouveau/core/include/engine/software.h b/drivers/gpu/drm/nouveau/core/include/engine/software.h new file mode 100644 index 000000000000..8d740793cf8a --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/include/engine/software.h @@ -0,0 +1,58 @@ +#ifndef __NOUVEAU_SOFTWARE_H__ +#define __NOUVEAU_SOFTWARE_H__ + +#include +#include + +struct nouveau_software_chan { + struct nouveau_engctx base; + + struct { + struct list_head head; + u32 channel; + u32 ctxdma; + u64 offset; + u32 value; + u32 crtc; + } vblank; + + int (*flip)(void *); + void *flip_data; +}; + +#define nouveau_software_context_create(p,e,c,d) \ + nouveau_engctx_create((p), (e), (c), (p), 0, 0, 0, (d)) +#define nouveau_software_context_destroy(d) \ + nouveau_engctx_destroy(&(d)->base) +#define nouveau_software_context_init(d) \ + nouveau_engctx_init(&(d)->base) +#define nouveau_software_context_fini(d,s) \ + nouveau_engctx_fini(&(d)->base, (s)) + +#define _nouveau_software_context_dtor _nouveau_engctx_dtor +#define _nouveau_software_context_init _nouveau_engctx_init +#define _nouveau_software_context_fini _nouveau_engctx_fini + +struct nouveau_software { + struct nouveau_engine base; +}; + +#define nouveau_software_create(p,e,c,d) \ + nouveau_engine_create((p), (e), (c), true, "SW", "software", (d)) +#define nouveau_software_destroy(d) \ + nouveau_engine_destroy(&(d)->base) +#define nouveau_software_init(d) \ + nouveau_engine_init(&(d)->base) +#define nouveau_software_fini(d,s) \ + nouveau_engine_fini(&(d)->base, (s)) + +#define _nouveau_software_dtor _nouveau_engine_dtor +#define _nouveau_software_init _nouveau_engine_init +#define _nouveau_software_fini _nouveau_engine_fini + +extern struct nouveau_oclass nv04_software_oclass; +extern struct nouveau_oclass nv10_software_oclass; +extern struct nouveau_oclass nv50_software_oclass; +extern struct nouveau_oclass nvc0_software_oclass; + +#endif diff --git a/drivers/gpu/drm/nouveau/core/include/engine/vp.h b/drivers/gpu/drm/nouveau/core/include/engine/vp.h new file mode 100644 index 000000000000..05cd08fba377 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/include/engine/vp.h @@ -0,0 +1,45 @@ +#ifndef __NOUVEAU_VP_H__ +#define __NOUVEAU_VP_H__ + +#include +#include + +struct nouveau_vp_chan { + struct nouveau_engctx base; +}; + +#define nouveau_vp_context_create(p,e,c,g,s,a,f,d) \ + nouveau_engctx_create((p), (e), (c), (g), (s), (a), (f), (d)) +#define nouveau_vp_context_destroy(d) \ + nouveau_engctx_destroy(&(d)->base) +#define nouveau_vp_context_init(d) \ + nouveau_engctx_init(&(d)->base) +#define nouveau_vp_context_fini(d,s) \ + nouveau_engctx_fini(&(d)->base, (s)) + +#define _nouveau_vp_context_dtor _nouveau_engctx_dtor +#define _nouveau_vp_context_init _nouveau_engctx_init +#define _nouveau_vp_context_fini _nouveau_engctx_fini +#define _nouveau_vp_context_rd32 _nouveau_engctx_rd32 +#define _nouveau_vp_context_wr32 _nouveau_engctx_wr32 + +struct nouveau_vp { + struct nouveau_engine base; +}; + +#define nouveau_vp_create(p,e,c,d) \ + nouveau_engine_create((p), (e), (c), true, "PVP", "vp", (d)) +#define nouveau_vp_destroy(d) \ + nouveau_engine_destroy(&(d)->base) +#define nouveau_vp_init(d) \ + nouveau_engine_init(&(d)->base) +#define nouveau_vp_fini(d,s) \ + nouveau_engine_fini(&(d)->base, (s)) + +#define _nouveau_vp_dtor _nouveau_engine_dtor +#define _nouveau_vp_init _nouveau_engine_init +#define _nouveau_vp_fini _nouveau_engine_fini + +extern struct nouveau_oclass nv84_vp_oclass; + +#endif diff --git a/drivers/gpu/drm/nouveau/core/include/subdev/device.h b/drivers/gpu/drm/nouveau/core/include/subdev/device.h index 5eec03a40f6d..c9e4c4afa50e 100644 --- a/drivers/gpu/drm/nouveau/core/include/subdev/device.h +++ b/drivers/gpu/drm/nouveau/core/include/subdev/device.h @@ -8,7 +8,6 @@ int nouveau_device_create_(struct pci_dev *, u64 name, const char *sname, const char *cfg, const char *dbg, int, void **); -void nouveau_device_destroy(struct nouveau_device **); int nv04_identify(struct nouveau_device *); int nv10_identify(struct nouveau_device *); diff --git a/drivers/gpu/drm/nouveau/core/include/subdev/instmem.h b/drivers/gpu/drm/nouveau/core/include/subdev/instmem.h index 2adfcafa4478..ec7a54e91a08 100644 --- a/drivers/gpu/drm/nouveau/core/include/subdev/instmem.h +++ b/drivers/gpu/drm/nouveau/core/include/subdev/instmem.h @@ -8,7 +8,6 @@ struct nouveau_instobj { struct nouveau_object base; struct list_head head; - struct nouveau_mm heap; u32 *suspend; u64 addr; u32 size; diff --git a/drivers/gpu/drm/nouveau/core/include/subdev/vm.h b/drivers/gpu/drm/nouveau/core/include/subdev/vm.h index 81577bb783e8..747781c2371d 100644 --- a/drivers/gpu/drm/nouveau/core/include/subdev/vm.h +++ b/drivers/gpu/drm/nouveau/core/include/subdev/vm.h @@ -73,6 +73,7 @@ struct nouveau_vm { struct nouveau_vmmgr { struct nouveau_subdev base; + u64 limit; u32 pgt_bits; u8 spg_shift; u8 lpg_shift; diff --git a/drivers/gpu/drm/nouveau/core/subdev/device/base.c b/drivers/gpu/drm/nouveau/core/subdev/device/base.c index 40456b99cb5f..d8d101630e46 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/device/base.c +++ b/drivers/gpu/drm/nouveau/core/subdev/device/base.c @@ -241,6 +241,8 @@ nouveau_devobj_ctor(struct nouveau_object *parent, if (!device->subdev[i]) { ret = nouveau_object_ctor(nv_object(device), NULL, oclass, NULL, i, &subdev); + if (ret == -ENODEV) + continue; if (ret) return ret; @@ -404,10 +406,26 @@ nouveau_device_sclass[] = { {} }; +static void +nouveau_device_dtor(struct nouveau_object *object) +{ + struct nouveau_device *device = (void *)object; + + mutex_lock(&nv_devices_mutex); + list_del(&device->head); + mutex_unlock(&nv_devices_mutex); + + if (device->base.mmio) + iounmap(device->base.mmio); + + nouveau_subdev_destroy(&device->base); +} + static struct nouveau_oclass nouveau_device_oclass = { .handle = NV_SUBDEV(DEVICE, 0x00), .ofuncs = &(struct nouveau_ofuncs) { + .dtor = nouveau_device_dtor, }, }; @@ -444,18 +462,3 @@ done: mutex_unlock(&nv_devices_mutex); return ret; } - -void -nouveau_device_destroy(struct nouveau_device **pdevice) -{ - struct nouveau_device *device = *pdevice; - if (device) { - mutex_lock(&nv_devices_mutex); - list_del(&device->head); - mutex_unlock(&nv_devices_mutex); - if (device->base.mmio) - iounmap(device->base.mmio); - nouveau_subdev_destroy(&device->base); - } - *pdevice = NULL; -} diff --git a/drivers/gpu/drm/nouveau/core/subdev/device/nv04.c b/drivers/gpu/drm/nouveau/core/subdev/device/nv04.c index 5173c785b061..693d200a3e22 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/device/nv04.c +++ b/drivers/gpu/drm/nouveau/core/subdev/device/nv04.c @@ -33,6 +33,12 @@ #include #include +#include +#include +#include +#include +#include + int nv04_identify(struct nouveau_device *device) { @@ -47,6 +53,11 @@ nv04_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_FB ] = &nv04_fb_oclass; device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv04_instmem_oclass; device->oclass[NVDEV_SUBDEV_VM ] = &nv04_vmmgr_oclass; + device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass; + device->oclass[NVDEV_ENGINE_FIFO ] = &nv04_fifo_oclass; + device->oclass[NVDEV_ENGINE_SW ] = &nv04_software_oclass; + device->oclass[NVDEV_ENGINE_GR ] = &nv04_graph_oclass; + device->oclass[NVDEV_ENGINE_DISP ] = &nv04_disp_oclass; break; case 0x05: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -58,6 +69,11 @@ nv04_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_FB ] = &nv04_fb_oclass; device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv04_instmem_oclass; device->oclass[NVDEV_SUBDEV_VM ] = &nv04_vmmgr_oclass; + device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass; + device->oclass[NVDEV_ENGINE_FIFO ] = &nv04_fifo_oclass; + device->oclass[NVDEV_ENGINE_SW ] = &nv04_software_oclass; + device->oclass[NVDEV_ENGINE_GR ] = &nv04_graph_oclass; + device->oclass[NVDEV_ENGINE_DISP ] = &nv04_disp_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 c4f2c2d3eaec..de6ce890e842 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/device/nv10.c +++ b/drivers/gpu/drm/nouveau/core/subdev/device/nv10.c @@ -34,6 +34,12 @@ #include #include +#include +#include +#include +#include +#include + int nv10_identify(struct nouveau_device *device) { @@ -49,6 +55,9 @@ nv10_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_FB ] = &nv10_fb_oclass; device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv04_instmem_oclass; device->oclass[NVDEV_SUBDEV_VM ] = &nv04_vmmgr_oclass; + device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass; + device->oclass[NVDEV_ENGINE_GR ] = &nv10_graph_oclass; + device->oclass[NVDEV_ENGINE_DISP ] = &nv04_disp_oclass; break; case 0x15: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -61,6 +70,11 @@ nv10_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_FB ] = &nv10_fb_oclass; device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv04_instmem_oclass; device->oclass[NVDEV_SUBDEV_VM ] = &nv04_vmmgr_oclass; + device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass; + device->oclass[NVDEV_ENGINE_FIFO ] = &nv10_fifo_oclass; + device->oclass[NVDEV_ENGINE_SW ] = &nv10_software_oclass; + device->oclass[NVDEV_ENGINE_GR ] = &nv10_graph_oclass; + device->oclass[NVDEV_ENGINE_DISP ] = &nv04_disp_oclass; break; case 0x16: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -73,6 +87,11 @@ nv10_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_FB ] = &nv10_fb_oclass; device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv04_instmem_oclass; device->oclass[NVDEV_SUBDEV_VM ] = &nv04_vmmgr_oclass; + device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass; + device->oclass[NVDEV_ENGINE_FIFO ] = &nv10_fifo_oclass; + device->oclass[NVDEV_ENGINE_SW ] = &nv10_software_oclass; + device->oclass[NVDEV_ENGINE_GR ] = &nv10_graph_oclass; + device->oclass[NVDEV_ENGINE_DISP ] = &nv04_disp_oclass; break; case 0x1a: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -85,6 +104,11 @@ nv10_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_FB ] = &nv10_fb_oclass; device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv04_instmem_oclass; device->oclass[NVDEV_SUBDEV_VM ] = &nv04_vmmgr_oclass; + device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass; + device->oclass[NVDEV_ENGINE_FIFO ] = &nv10_fifo_oclass; + device->oclass[NVDEV_ENGINE_SW ] = &nv10_software_oclass; + device->oclass[NVDEV_ENGINE_GR ] = &nv10_graph_oclass; + device->oclass[NVDEV_ENGINE_DISP ] = &nv04_disp_oclass; break; case 0x11: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -97,6 +121,11 @@ nv10_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_FB ] = &nv10_fb_oclass; device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv04_instmem_oclass; device->oclass[NVDEV_SUBDEV_VM ] = &nv04_vmmgr_oclass; + device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass; + device->oclass[NVDEV_ENGINE_FIFO ] = &nv10_fifo_oclass; + device->oclass[NVDEV_ENGINE_SW ] = &nv10_software_oclass; + device->oclass[NVDEV_ENGINE_GR ] = &nv10_graph_oclass; + device->oclass[NVDEV_ENGINE_DISP ] = &nv04_disp_oclass; break; case 0x17: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -109,6 +138,11 @@ nv10_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_FB ] = &nv10_fb_oclass; device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv04_instmem_oclass; device->oclass[NVDEV_SUBDEV_VM ] = &nv04_vmmgr_oclass; + device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass; + device->oclass[NVDEV_ENGINE_FIFO ] = &nv17_fifo_oclass; + device->oclass[NVDEV_ENGINE_SW ] = &nv10_software_oclass; + device->oclass[NVDEV_ENGINE_GR ] = &nv10_graph_oclass; + device->oclass[NVDEV_ENGINE_DISP ] = &nv04_disp_oclass; break; case 0x1f: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -121,6 +155,11 @@ nv10_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_FB ] = &nv10_fb_oclass; device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv04_instmem_oclass; device->oclass[NVDEV_SUBDEV_VM ] = &nv04_vmmgr_oclass; + device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass; + device->oclass[NVDEV_ENGINE_FIFO ] = &nv17_fifo_oclass; + device->oclass[NVDEV_ENGINE_SW ] = &nv10_software_oclass; + device->oclass[NVDEV_ENGINE_GR ] = &nv10_graph_oclass; + device->oclass[NVDEV_ENGINE_DISP ] = &nv04_disp_oclass; break; case 0x18: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -133,6 +172,11 @@ nv10_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_FB ] = &nv10_fb_oclass; device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv04_instmem_oclass; device->oclass[NVDEV_SUBDEV_VM ] = &nv04_vmmgr_oclass; + device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass; + device->oclass[NVDEV_ENGINE_FIFO ] = &nv17_fifo_oclass; + device->oclass[NVDEV_ENGINE_SW ] = &nv10_software_oclass; + device->oclass[NVDEV_ENGINE_GR ] = &nv10_graph_oclass; + device->oclass[NVDEV_ENGINE_DISP ] = &nv04_disp_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 719b72a43e47..0b30143d0114 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/device/nv20.c +++ b/drivers/gpu/drm/nouveau/core/subdev/device/nv20.c @@ -34,6 +34,12 @@ #include #include +#include +#include +#include +#include +#include + int nv20_identify(struct nouveau_device *device) { @@ -49,6 +55,11 @@ nv20_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_FB ] = &nv20_fb_oclass; device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv04_instmem_oclass; device->oclass[NVDEV_SUBDEV_VM ] = &nv04_vmmgr_oclass; + device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass; + device->oclass[NVDEV_ENGINE_FIFO ] = &nv17_fifo_oclass; + device->oclass[NVDEV_ENGINE_SW ] = &nv10_software_oclass; + device->oclass[NVDEV_ENGINE_GR ] = &nv20_graph_oclass; + device->oclass[NVDEV_ENGINE_DISP ] = &nv04_disp_oclass; break; case 0x25: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -61,6 +72,11 @@ nv20_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_FB ] = &nv20_fb_oclass; device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv04_instmem_oclass; device->oclass[NVDEV_SUBDEV_VM ] = &nv04_vmmgr_oclass; + device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass; + device->oclass[NVDEV_ENGINE_FIFO ] = &nv17_fifo_oclass; + device->oclass[NVDEV_ENGINE_SW ] = &nv10_software_oclass; + device->oclass[NVDEV_ENGINE_GR ] = &nv25_graph_oclass; + device->oclass[NVDEV_ENGINE_DISP ] = &nv04_disp_oclass; break; case 0x28: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -73,6 +89,11 @@ nv20_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_FB ] = &nv20_fb_oclass; device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv04_instmem_oclass; device->oclass[NVDEV_SUBDEV_VM ] = &nv04_vmmgr_oclass; + device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass; + device->oclass[NVDEV_ENGINE_FIFO ] = &nv17_fifo_oclass; + device->oclass[NVDEV_ENGINE_SW ] = &nv10_software_oclass; + device->oclass[NVDEV_ENGINE_GR ] = &nv25_graph_oclass; + device->oclass[NVDEV_ENGINE_DISP ] = &nv04_disp_oclass; break; case 0x2a: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -85,6 +106,11 @@ nv20_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_FB ] = &nv20_fb_oclass; device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv04_instmem_oclass; device->oclass[NVDEV_SUBDEV_VM ] = &nv04_vmmgr_oclass; + device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass; + device->oclass[NVDEV_ENGINE_FIFO ] = &nv17_fifo_oclass; + device->oclass[NVDEV_ENGINE_SW ] = &nv10_software_oclass; + device->oclass[NVDEV_ENGINE_GR ] = &nv2a_graph_oclass; + device->oclass[NVDEV_ENGINE_DISP ] = &nv04_disp_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 0a1a72809d82..1d5c6977c86a 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/device/nv30.c +++ b/drivers/gpu/drm/nouveau/core/subdev/device/nv30.c @@ -34,6 +34,13 @@ #include #include +#include +#include +#include +#include +#include +#include + int nv30_identify(struct nouveau_device *device) { @@ -49,6 +56,11 @@ nv30_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_FB ] = &nv30_fb_oclass; device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv04_instmem_oclass; device->oclass[NVDEV_SUBDEV_VM ] = &nv04_vmmgr_oclass; + device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass; + device->oclass[NVDEV_ENGINE_FIFO ] = &nv17_fifo_oclass; + device->oclass[NVDEV_ENGINE_SW ] = &nv10_software_oclass; + device->oclass[NVDEV_ENGINE_GR ] = &nv30_graph_oclass; + device->oclass[NVDEV_ENGINE_DISP ] = &nv04_disp_oclass; break; case 0x35: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -61,6 +73,11 @@ nv30_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_FB ] = &nv30_fb_oclass; device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv04_instmem_oclass; device->oclass[NVDEV_SUBDEV_VM ] = &nv04_vmmgr_oclass; + device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass; + device->oclass[NVDEV_ENGINE_FIFO ] = &nv17_fifo_oclass; + device->oclass[NVDEV_ENGINE_SW ] = &nv10_software_oclass; + device->oclass[NVDEV_ENGINE_GR ] = &nv35_graph_oclass; + device->oclass[NVDEV_ENGINE_DISP ] = &nv04_disp_oclass; break; case 0x31: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -73,6 +90,12 @@ nv30_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_FB ] = &nv30_fb_oclass; device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv04_instmem_oclass; device->oclass[NVDEV_SUBDEV_VM ] = &nv04_vmmgr_oclass; + device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass; + device->oclass[NVDEV_ENGINE_FIFO ] = &nv17_fifo_oclass; + device->oclass[NVDEV_ENGINE_SW ] = &nv10_software_oclass; + device->oclass[NVDEV_ENGINE_GR ] = &nv30_graph_oclass; + device->oclass[NVDEV_ENGINE_MPEG ] = &nv31_mpeg_oclass; + device->oclass[NVDEV_ENGINE_DISP ] = &nv04_disp_oclass; break; case 0x36: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -85,6 +108,12 @@ nv30_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_FB ] = &nv30_fb_oclass; device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv04_instmem_oclass; device->oclass[NVDEV_SUBDEV_VM ] = &nv04_vmmgr_oclass; + device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass; + device->oclass[NVDEV_ENGINE_FIFO ] = &nv17_fifo_oclass; + device->oclass[NVDEV_ENGINE_SW ] = &nv10_software_oclass; + device->oclass[NVDEV_ENGINE_GR ] = &nv35_graph_oclass; + device->oclass[NVDEV_ENGINE_MPEG ] = &nv31_mpeg_oclass; + device->oclass[NVDEV_ENGINE_DISP ] = &nv04_disp_oclass; break; case 0x34: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -97,6 +126,12 @@ nv30_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_FB ] = &nv30_fb_oclass; device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv04_instmem_oclass; device->oclass[NVDEV_SUBDEV_VM ] = &nv04_vmmgr_oclass; + device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass; + device->oclass[NVDEV_ENGINE_FIFO ] = &nv17_fifo_oclass; + device->oclass[NVDEV_ENGINE_SW ] = &nv10_software_oclass; + device->oclass[NVDEV_ENGINE_GR ] = &nv34_graph_oclass; + device->oclass[NVDEV_ENGINE_MPEG ] = &nv31_mpeg_oclass; + device->oclass[NVDEV_ENGINE_DISP ] = &nv04_disp_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 5e1ef5e4cf7f..2e071fa9fca0 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/device/nv40.c +++ b/drivers/gpu/drm/nouveau/core/subdev/device/nv40.c @@ -34,6 +34,13 @@ #include #include +#include +#include +#include +#include +#include +#include + int nv40_identify(struct nouveau_device *device) { @@ -49,6 +56,12 @@ nv40_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_FB ] = &nv40_fb_oclass; device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv40_instmem_oclass; device->oclass[NVDEV_SUBDEV_VM ] = &nv04_vmmgr_oclass; + device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass; + device->oclass[NVDEV_ENGINE_FIFO ] = &nv40_fifo_oclass; + device->oclass[NVDEV_ENGINE_SW ] = &nv10_software_oclass; + device->oclass[NVDEV_ENGINE_GR ] = &nv40_graph_oclass; + device->oclass[NVDEV_ENGINE_MPEG ] = &nv40_mpeg_oclass; + device->oclass[NVDEV_ENGINE_DISP ] = &nv04_disp_oclass; break; case 0x41: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -61,6 +74,12 @@ nv40_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_FB ] = &nv40_fb_oclass; device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv40_instmem_oclass; device->oclass[NVDEV_SUBDEV_VM ] = &nv04_vmmgr_oclass; + device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass; + device->oclass[NVDEV_ENGINE_FIFO ] = &nv40_fifo_oclass; + device->oclass[NVDEV_ENGINE_SW ] = &nv10_software_oclass; + device->oclass[NVDEV_ENGINE_GR ] = &nv40_graph_oclass; + device->oclass[NVDEV_ENGINE_MPEG ] = &nv40_mpeg_oclass; + device->oclass[NVDEV_ENGINE_DISP ] = &nv04_disp_oclass; break; case 0x42: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -73,6 +92,12 @@ nv40_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_FB ] = &nv40_fb_oclass; device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv40_instmem_oclass; device->oclass[NVDEV_SUBDEV_VM ] = &nv04_vmmgr_oclass; + device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass; + device->oclass[NVDEV_ENGINE_FIFO ] = &nv40_fifo_oclass; + device->oclass[NVDEV_ENGINE_SW ] = &nv10_software_oclass; + device->oclass[NVDEV_ENGINE_GR ] = &nv40_graph_oclass; + device->oclass[NVDEV_ENGINE_MPEG ] = &nv40_mpeg_oclass; + device->oclass[NVDEV_ENGINE_DISP ] = &nv04_disp_oclass; break; case 0x43: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -85,6 +110,12 @@ nv40_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_FB ] = &nv40_fb_oclass; device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv40_instmem_oclass; device->oclass[NVDEV_SUBDEV_VM ] = &nv04_vmmgr_oclass; + device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass; + device->oclass[NVDEV_ENGINE_FIFO ] = &nv40_fifo_oclass; + device->oclass[NVDEV_ENGINE_SW ] = &nv10_software_oclass; + device->oclass[NVDEV_ENGINE_GR ] = &nv40_graph_oclass; + device->oclass[NVDEV_ENGINE_MPEG ] = &nv40_mpeg_oclass; + device->oclass[NVDEV_ENGINE_DISP ] = &nv04_disp_oclass; break; case 0x45: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -97,6 +128,12 @@ nv40_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_FB ] = &nv40_fb_oclass; device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv40_instmem_oclass; device->oclass[NVDEV_SUBDEV_VM ] = &nv04_vmmgr_oclass; + device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass; + device->oclass[NVDEV_ENGINE_FIFO ] = &nv40_fifo_oclass; + device->oclass[NVDEV_ENGINE_SW ] = &nv10_software_oclass; + device->oclass[NVDEV_ENGINE_GR ] = &nv40_graph_oclass; + device->oclass[NVDEV_ENGINE_MPEG ] = &nv40_mpeg_oclass; + device->oclass[NVDEV_ENGINE_DISP ] = &nv04_disp_oclass; break; case 0x47: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -109,6 +146,12 @@ nv40_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_FB ] = &nv40_fb_oclass; device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv40_instmem_oclass; device->oclass[NVDEV_SUBDEV_VM ] = &nv04_vmmgr_oclass; + device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass; + device->oclass[NVDEV_ENGINE_FIFO ] = &nv40_fifo_oclass; + device->oclass[NVDEV_ENGINE_SW ] = &nv10_software_oclass; + device->oclass[NVDEV_ENGINE_GR ] = &nv40_graph_oclass; + device->oclass[NVDEV_ENGINE_MPEG ] = &nv40_mpeg_oclass; + device->oclass[NVDEV_ENGINE_DISP ] = &nv04_disp_oclass; break; case 0x49: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -121,6 +164,12 @@ nv40_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_FB ] = &nv40_fb_oclass; device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv40_instmem_oclass; device->oclass[NVDEV_SUBDEV_VM ] = &nv04_vmmgr_oclass; + device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass; + device->oclass[NVDEV_ENGINE_FIFO ] = &nv40_fifo_oclass; + device->oclass[NVDEV_ENGINE_SW ] = &nv10_software_oclass; + device->oclass[NVDEV_ENGINE_GR ] = &nv40_graph_oclass; + device->oclass[NVDEV_ENGINE_MPEG ] = &nv40_mpeg_oclass; + device->oclass[NVDEV_ENGINE_DISP ] = &nv04_disp_oclass; break; case 0x4b: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -133,6 +182,12 @@ nv40_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_FB ] = &nv40_fb_oclass; device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv40_instmem_oclass; device->oclass[NVDEV_SUBDEV_VM ] = &nv04_vmmgr_oclass; + device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass; + device->oclass[NVDEV_ENGINE_FIFO ] = &nv40_fifo_oclass; + device->oclass[NVDEV_ENGINE_SW ] = &nv10_software_oclass; + device->oclass[NVDEV_ENGINE_GR ] = &nv40_graph_oclass; + device->oclass[NVDEV_ENGINE_MPEG ] = &nv40_mpeg_oclass; + device->oclass[NVDEV_ENGINE_DISP ] = &nv04_disp_oclass; break; case 0x44: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -145,6 +200,12 @@ nv40_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_FB ] = &nv40_fb_oclass; device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv40_instmem_oclass; device->oclass[NVDEV_SUBDEV_VM ] = &nv04_vmmgr_oclass; + device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass; + device->oclass[NVDEV_ENGINE_FIFO ] = &nv40_fifo_oclass; + device->oclass[NVDEV_ENGINE_SW ] = &nv10_software_oclass; + device->oclass[NVDEV_ENGINE_GR ] = &nv40_graph_oclass; + device->oclass[NVDEV_ENGINE_MPEG ] = &nv40_mpeg_oclass; + device->oclass[NVDEV_ENGINE_DISP ] = &nv04_disp_oclass; break; case 0x46: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -157,6 +218,12 @@ nv40_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_FB ] = &nv40_fb_oclass; device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv40_instmem_oclass; device->oclass[NVDEV_SUBDEV_VM ] = &nv04_vmmgr_oclass; + device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass; + device->oclass[NVDEV_ENGINE_FIFO ] = &nv40_fifo_oclass; + device->oclass[NVDEV_ENGINE_SW ] = &nv10_software_oclass; + device->oclass[NVDEV_ENGINE_GR ] = &nv40_graph_oclass; + device->oclass[NVDEV_ENGINE_MPEG ] = &nv40_mpeg_oclass; + device->oclass[NVDEV_ENGINE_DISP ] = &nv04_disp_oclass; break; case 0x4a: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -169,6 +236,12 @@ nv40_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_FB ] = &nv40_fb_oclass; device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv40_instmem_oclass; device->oclass[NVDEV_SUBDEV_VM ] = &nv04_vmmgr_oclass; + device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass; + device->oclass[NVDEV_ENGINE_FIFO ] = &nv40_fifo_oclass; + device->oclass[NVDEV_ENGINE_SW ] = &nv10_software_oclass; + device->oclass[NVDEV_ENGINE_GR ] = &nv40_graph_oclass; + device->oclass[NVDEV_ENGINE_MPEG ] = &nv40_mpeg_oclass; + device->oclass[NVDEV_ENGINE_DISP ] = &nv04_disp_oclass; break; case 0x4c: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -181,6 +254,12 @@ nv40_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_FB ] = &nv40_fb_oclass; device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv40_instmem_oclass; device->oclass[NVDEV_SUBDEV_VM ] = &nv04_vmmgr_oclass; + device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass; + device->oclass[NVDEV_ENGINE_FIFO ] = &nv40_fifo_oclass; + device->oclass[NVDEV_ENGINE_SW ] = &nv10_software_oclass; + device->oclass[NVDEV_ENGINE_GR ] = &nv40_graph_oclass; + device->oclass[NVDEV_ENGINE_MPEG ] = &nv40_mpeg_oclass; + device->oclass[NVDEV_ENGINE_DISP ] = &nv04_disp_oclass; break; case 0x4e: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -193,6 +272,12 @@ nv40_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_FB ] = &nv40_fb_oclass; device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv40_instmem_oclass; device->oclass[NVDEV_SUBDEV_VM ] = &nv04_vmmgr_oclass; + device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass; + device->oclass[NVDEV_ENGINE_FIFO ] = &nv40_fifo_oclass; + device->oclass[NVDEV_ENGINE_SW ] = &nv10_software_oclass; + device->oclass[NVDEV_ENGINE_GR ] = &nv40_graph_oclass; + device->oclass[NVDEV_ENGINE_MPEG ] = &nv40_mpeg_oclass; + device->oclass[NVDEV_ENGINE_DISP ] = &nv04_disp_oclass; break; case 0x63: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -205,6 +290,12 @@ nv40_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_FB ] = &nv40_fb_oclass; device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv40_instmem_oclass; device->oclass[NVDEV_SUBDEV_VM ] = &nv04_vmmgr_oclass; + device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass; + device->oclass[NVDEV_ENGINE_FIFO ] = &nv40_fifo_oclass; + device->oclass[NVDEV_ENGINE_SW ] = &nv10_software_oclass; + device->oclass[NVDEV_ENGINE_GR ] = &nv40_graph_oclass; + device->oclass[NVDEV_ENGINE_MPEG ] = &nv40_mpeg_oclass; + device->oclass[NVDEV_ENGINE_DISP ] = &nv04_disp_oclass; break; case 0x67: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -217,6 +308,12 @@ nv40_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_FB ] = &nv40_fb_oclass; device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv40_instmem_oclass; device->oclass[NVDEV_SUBDEV_VM ] = &nv04_vmmgr_oclass; + device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass; + device->oclass[NVDEV_ENGINE_FIFO ] = &nv40_fifo_oclass; + device->oclass[NVDEV_ENGINE_SW ] = &nv10_software_oclass; + device->oclass[NVDEV_ENGINE_GR ] = &nv40_graph_oclass; + device->oclass[NVDEV_ENGINE_MPEG ] = &nv40_mpeg_oclass; + device->oclass[NVDEV_ENGINE_DISP ] = &nv04_disp_oclass; break; case 0x68: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -229,6 +326,12 @@ nv40_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_FB ] = &nv40_fb_oclass; device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv40_instmem_oclass; device->oclass[NVDEV_SUBDEV_VM ] = &nv04_vmmgr_oclass; + device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass; + device->oclass[NVDEV_ENGINE_FIFO ] = &nv40_fifo_oclass; + device->oclass[NVDEV_ENGINE_SW ] = &nv10_software_oclass; + device->oclass[NVDEV_ENGINE_GR ] = &nv40_graph_oclass; + device->oclass[NVDEV_ENGINE_MPEG ] = &nv40_mpeg_oclass; + device->oclass[NVDEV_ENGINE_DISP ] = &nv04_disp_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 5e86a2f6ad8a..5d44b2a5bfa9 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/device/nv50.c +++ b/drivers/gpu/drm/nouveau/core/subdev/device/nv50.c @@ -35,6 +35,18 @@ #include #include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + int nv50_identify(struct nouveau_device *device) { @@ -51,6 +63,12 @@ nv50_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass; device->oclass[NVDEV_SUBDEV_VM ] = &nv50_vmmgr_oclass; device->oclass[NVDEV_SUBDEV_BAR ] = &nv50_bar_oclass; + device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv50_dmaeng_oclass; + device->oclass[NVDEV_ENGINE_FIFO ] = &nv50_fifo_oclass; + device->oclass[NVDEV_ENGINE_SW ] = &nv50_software_oclass; + device->oclass[NVDEV_ENGINE_GR ] = &nv50_graph_oclass; + device->oclass[NVDEV_ENGINE_MPEG ] = &nv50_mpeg_oclass; + device->oclass[NVDEV_ENGINE_DISP ] = &nv50_disp_oclass; break; case 0x84: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -64,6 +82,15 @@ nv50_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass; device->oclass[NVDEV_SUBDEV_VM ] = &nv50_vmmgr_oclass; device->oclass[NVDEV_SUBDEV_BAR ] = &nv50_bar_oclass; + device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv50_dmaeng_oclass; + device->oclass[NVDEV_ENGINE_FIFO ] = &nv84_fifo_oclass; + device->oclass[NVDEV_ENGINE_SW ] = &nv50_software_oclass; + device->oclass[NVDEV_ENGINE_GR ] = &nv50_graph_oclass; + device->oclass[NVDEV_ENGINE_MPEG ] = &nv84_mpeg_oclass; + device->oclass[NVDEV_ENGINE_VP ] = &nv84_vp_oclass; + device->oclass[NVDEV_ENGINE_CRYPT ] = &nv84_crypt_oclass; + device->oclass[NVDEV_ENGINE_BSP ] = &nv84_bsp_oclass; + device->oclass[NVDEV_ENGINE_DISP ] = &nv50_disp_oclass; break; case 0x86: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -77,6 +104,15 @@ nv50_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass; device->oclass[NVDEV_SUBDEV_VM ] = &nv50_vmmgr_oclass; device->oclass[NVDEV_SUBDEV_BAR ] = &nv50_bar_oclass; + device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv50_dmaeng_oclass; + device->oclass[NVDEV_ENGINE_FIFO ] = &nv84_fifo_oclass; + device->oclass[NVDEV_ENGINE_SW ] = &nv50_software_oclass; + device->oclass[NVDEV_ENGINE_GR ] = &nv50_graph_oclass; + device->oclass[NVDEV_ENGINE_MPEG ] = &nv84_mpeg_oclass; + device->oclass[NVDEV_ENGINE_VP ] = &nv84_vp_oclass; + device->oclass[NVDEV_ENGINE_CRYPT ] = &nv84_crypt_oclass; + device->oclass[NVDEV_ENGINE_BSP ] = &nv84_bsp_oclass; + device->oclass[NVDEV_ENGINE_DISP ] = &nv50_disp_oclass; break; case 0x92: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -90,6 +126,15 @@ nv50_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass; device->oclass[NVDEV_SUBDEV_VM ] = &nv50_vmmgr_oclass; device->oclass[NVDEV_SUBDEV_BAR ] = &nv50_bar_oclass; + device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv50_dmaeng_oclass; + device->oclass[NVDEV_ENGINE_FIFO ] = &nv84_fifo_oclass; + device->oclass[NVDEV_ENGINE_SW ] = &nv50_software_oclass; + device->oclass[NVDEV_ENGINE_GR ] = &nv50_graph_oclass; + device->oclass[NVDEV_ENGINE_MPEG ] = &nv84_mpeg_oclass; + device->oclass[NVDEV_ENGINE_VP ] = &nv84_vp_oclass; + device->oclass[NVDEV_ENGINE_CRYPT ] = &nv84_crypt_oclass; + device->oclass[NVDEV_ENGINE_BSP ] = &nv84_bsp_oclass; + device->oclass[NVDEV_ENGINE_DISP ] = &nv50_disp_oclass; break; case 0x94: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -103,6 +148,15 @@ nv50_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass; device->oclass[NVDEV_SUBDEV_VM ] = &nv50_vmmgr_oclass; device->oclass[NVDEV_SUBDEV_BAR ] = &nv50_bar_oclass; + device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv50_dmaeng_oclass; + device->oclass[NVDEV_ENGINE_FIFO ] = &nv84_fifo_oclass; + device->oclass[NVDEV_ENGINE_SW ] = &nv50_software_oclass; + device->oclass[NVDEV_ENGINE_GR ] = &nv50_graph_oclass; + device->oclass[NVDEV_ENGINE_MPEG ] = &nv84_mpeg_oclass; + device->oclass[NVDEV_ENGINE_VP ] = &nv84_vp_oclass; + device->oclass[NVDEV_ENGINE_CRYPT ] = &nv84_crypt_oclass; + device->oclass[NVDEV_ENGINE_BSP ] = &nv84_bsp_oclass; + device->oclass[NVDEV_ENGINE_DISP ] = &nv50_disp_oclass; break; case 0x96: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -116,6 +170,15 @@ nv50_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass; device->oclass[NVDEV_SUBDEV_VM ] = &nv50_vmmgr_oclass; device->oclass[NVDEV_SUBDEV_BAR ] = &nv50_bar_oclass; + device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv50_dmaeng_oclass; + device->oclass[NVDEV_ENGINE_FIFO ] = &nv84_fifo_oclass; + device->oclass[NVDEV_ENGINE_SW ] = &nv50_software_oclass; + device->oclass[NVDEV_ENGINE_GR ] = &nv50_graph_oclass; + device->oclass[NVDEV_ENGINE_MPEG ] = &nv84_mpeg_oclass; + device->oclass[NVDEV_ENGINE_VP ] = &nv84_vp_oclass; + device->oclass[NVDEV_ENGINE_CRYPT ] = &nv84_crypt_oclass; + device->oclass[NVDEV_ENGINE_BSP ] = &nv84_bsp_oclass; + device->oclass[NVDEV_ENGINE_DISP ] = &nv50_disp_oclass; break; case 0x98: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -129,6 +192,15 @@ nv50_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass; device->oclass[NVDEV_SUBDEV_VM ] = &nv50_vmmgr_oclass; device->oclass[NVDEV_SUBDEV_BAR ] = &nv50_bar_oclass; + device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv50_dmaeng_oclass; + device->oclass[NVDEV_ENGINE_FIFO ] = &nv84_fifo_oclass; + device->oclass[NVDEV_ENGINE_SW ] = &nv50_software_oclass; + device->oclass[NVDEV_ENGINE_GR ] = &nv50_graph_oclass; + device->oclass[NVDEV_ENGINE_VP ] = &nv84_vp_oclass; + device->oclass[NVDEV_ENGINE_CRYPT ] = &nv98_crypt_oclass; + device->oclass[NVDEV_ENGINE_BSP ] = &nv84_bsp_oclass; + device->oclass[NVDEV_ENGINE_PPP ] = &nv98_ppp_oclass; + device->oclass[NVDEV_ENGINE_DISP ] = &nv50_disp_oclass; break; case 0xa0: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -142,6 +214,15 @@ nv50_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass; device->oclass[NVDEV_SUBDEV_VM ] = &nv50_vmmgr_oclass; device->oclass[NVDEV_SUBDEV_BAR ] = &nv50_bar_oclass; + device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv50_dmaeng_oclass; + device->oclass[NVDEV_ENGINE_FIFO ] = &nv84_fifo_oclass; + device->oclass[NVDEV_ENGINE_SW ] = &nv50_software_oclass; + device->oclass[NVDEV_ENGINE_GR ] = &nv50_graph_oclass; + device->oclass[NVDEV_ENGINE_MPEG ] = &nv84_mpeg_oclass; + device->oclass[NVDEV_ENGINE_VP ] = &nv84_vp_oclass; + device->oclass[NVDEV_ENGINE_CRYPT ] = &nv84_crypt_oclass; + device->oclass[NVDEV_ENGINE_BSP ] = &nv84_bsp_oclass; + device->oclass[NVDEV_ENGINE_DISP ] = &nv50_disp_oclass; break; case 0xaa: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -155,6 +236,15 @@ nv50_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass; device->oclass[NVDEV_SUBDEV_VM ] = &nv50_vmmgr_oclass; device->oclass[NVDEV_SUBDEV_BAR ] = &nv50_bar_oclass; + device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv50_dmaeng_oclass; + device->oclass[NVDEV_ENGINE_FIFO ] = &nv84_fifo_oclass; + device->oclass[NVDEV_ENGINE_SW ] = &nv50_software_oclass; + device->oclass[NVDEV_ENGINE_GR ] = &nv50_graph_oclass; + device->oclass[NVDEV_ENGINE_VP ] = &nv84_vp_oclass; + device->oclass[NVDEV_ENGINE_CRYPT ] = &nv98_crypt_oclass; + device->oclass[NVDEV_ENGINE_BSP ] = &nv84_bsp_oclass; + device->oclass[NVDEV_ENGINE_PPP ] = &nv98_ppp_oclass; + device->oclass[NVDEV_ENGINE_DISP ] = &nv50_disp_oclass; break; case 0xac: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -168,6 +258,15 @@ nv50_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass; device->oclass[NVDEV_SUBDEV_VM ] = &nv50_vmmgr_oclass; device->oclass[NVDEV_SUBDEV_BAR ] = &nv50_bar_oclass; + device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv50_dmaeng_oclass; + device->oclass[NVDEV_ENGINE_FIFO ] = &nv84_fifo_oclass; + device->oclass[NVDEV_ENGINE_SW ] = &nv50_software_oclass; + device->oclass[NVDEV_ENGINE_GR ] = &nv50_graph_oclass; + device->oclass[NVDEV_ENGINE_VP ] = &nv84_vp_oclass; + device->oclass[NVDEV_ENGINE_CRYPT ] = &nv98_crypt_oclass; + device->oclass[NVDEV_ENGINE_BSP ] = &nv84_bsp_oclass; + device->oclass[NVDEV_ENGINE_PPP ] = &nv98_ppp_oclass; + device->oclass[NVDEV_ENGINE_DISP ] = &nv50_disp_oclass; break; case 0xa3: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -181,6 +280,16 @@ nv50_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass; device->oclass[NVDEV_SUBDEV_VM ] = &nv50_vmmgr_oclass; device->oclass[NVDEV_SUBDEV_BAR ] = &nv50_bar_oclass; + device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv50_dmaeng_oclass; + device->oclass[NVDEV_ENGINE_FIFO ] = &nv84_fifo_oclass; + device->oclass[NVDEV_ENGINE_SW ] = &nv50_software_oclass; + device->oclass[NVDEV_ENGINE_GR ] = &nv50_graph_oclass; + device->oclass[NVDEV_ENGINE_MPEG ] = &nv84_mpeg_oclass; + device->oclass[NVDEV_ENGINE_VP ] = &nv84_vp_oclass; + device->oclass[NVDEV_ENGINE_BSP ] = &nv84_bsp_oclass; + device->oclass[NVDEV_ENGINE_PPP ] = &nv98_ppp_oclass; + device->oclass[NVDEV_ENGINE_COPY0 ] = &nva3_copy_oclass; + device->oclass[NVDEV_ENGINE_DISP ] = &nv50_disp_oclass; break; case 0xa5: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -194,6 +303,15 @@ nv50_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass; device->oclass[NVDEV_SUBDEV_VM ] = &nv50_vmmgr_oclass; device->oclass[NVDEV_SUBDEV_BAR ] = &nv50_bar_oclass; + device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv50_dmaeng_oclass; + device->oclass[NVDEV_ENGINE_FIFO ] = &nv84_fifo_oclass; + device->oclass[NVDEV_ENGINE_SW ] = &nv50_software_oclass; + device->oclass[NVDEV_ENGINE_GR ] = &nv50_graph_oclass; + device->oclass[NVDEV_ENGINE_VP ] = &nv84_vp_oclass; + device->oclass[NVDEV_ENGINE_BSP ] = &nv84_bsp_oclass; + device->oclass[NVDEV_ENGINE_PPP ] = &nv98_ppp_oclass; + device->oclass[NVDEV_ENGINE_COPY0 ] = &nva3_copy_oclass; + device->oclass[NVDEV_ENGINE_DISP ] = &nv50_disp_oclass; break; case 0xa8: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -207,6 +325,15 @@ nv50_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass; device->oclass[NVDEV_SUBDEV_VM ] = &nv50_vmmgr_oclass; device->oclass[NVDEV_SUBDEV_BAR ] = &nv50_bar_oclass; + device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv50_dmaeng_oclass; + device->oclass[NVDEV_ENGINE_FIFO ] = &nv84_fifo_oclass; + device->oclass[NVDEV_ENGINE_SW ] = &nv50_software_oclass; + device->oclass[NVDEV_ENGINE_GR ] = &nv50_graph_oclass; + device->oclass[NVDEV_ENGINE_VP ] = &nv84_vp_oclass; + device->oclass[NVDEV_ENGINE_BSP ] = &nv84_bsp_oclass; + device->oclass[NVDEV_ENGINE_PPP ] = &nv98_ppp_oclass; + device->oclass[NVDEV_ENGINE_COPY0 ] = &nva3_copy_oclass; + device->oclass[NVDEV_ENGINE_DISP ] = &nv50_disp_oclass; break; case 0xaf: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -220,6 +347,15 @@ nv50_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass; device->oclass[NVDEV_SUBDEV_VM ] = &nv50_vmmgr_oclass; device->oclass[NVDEV_SUBDEV_BAR ] = &nv50_bar_oclass; + device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv50_dmaeng_oclass; + device->oclass[NVDEV_ENGINE_FIFO ] = &nv84_fifo_oclass; + device->oclass[NVDEV_ENGINE_SW ] = &nv50_software_oclass; + device->oclass[NVDEV_ENGINE_GR ] = &nv50_graph_oclass; + device->oclass[NVDEV_ENGINE_VP ] = &nv84_vp_oclass; + device->oclass[NVDEV_ENGINE_BSP ] = &nv84_bsp_oclass; + device->oclass[NVDEV_ENGINE_PPP ] = &nv98_ppp_oclass; + device->oclass[NVDEV_ENGINE_COPY0 ] = &nva3_copy_oclass; + device->oclass[NVDEV_ENGINE_DISP ] = &nv50_disp_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 87f4e16379c6..81d6ed593428 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/device/nvc0.c +++ b/drivers/gpu/drm/nouveau/core/subdev/device/nvc0.c @@ -36,6 +36,16 @@ #include #include +#include +#include +#include +#include +#include +#include +#include +#include +#include + int nvc0_identify(struct nouveau_device *device) { @@ -53,6 +63,16 @@ nvc0_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass; device->oclass[NVDEV_SUBDEV_VM ] = &nvc0_vmmgr_oclass; device->oclass[NVDEV_SUBDEV_BAR ] = &nvc0_bar_oclass; + device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nvc0_dmaeng_oclass; + device->oclass[NVDEV_ENGINE_FIFO ] = &nvc0_fifo_oclass; + device->oclass[NVDEV_ENGINE_SW ] = &nvc0_software_oclass; + device->oclass[NVDEV_ENGINE_GR ] = &nvc0_graph_oclass; + device->oclass[NVDEV_ENGINE_VP ] = &nv84_vp_oclass; + device->oclass[NVDEV_ENGINE_BSP ] = &nv84_bsp_oclass; + device->oclass[NVDEV_ENGINE_PPP ] = &nv98_ppp_oclass; + device->oclass[NVDEV_ENGINE_COPY0 ] = &nvc0_copy0_oclass; + device->oclass[NVDEV_ENGINE_COPY1 ] = &nvc0_copy1_oclass; + device->oclass[NVDEV_ENGINE_DISP ] = &nv50_disp_oclass; break; case 0xc4: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -67,6 +87,16 @@ nvc0_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass; device->oclass[NVDEV_SUBDEV_VM ] = &nvc0_vmmgr_oclass; device->oclass[NVDEV_SUBDEV_BAR ] = &nvc0_bar_oclass; + device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nvc0_dmaeng_oclass; + device->oclass[NVDEV_ENGINE_FIFO ] = &nvc0_fifo_oclass; + device->oclass[NVDEV_ENGINE_SW ] = &nvc0_software_oclass; + device->oclass[NVDEV_ENGINE_GR ] = &nvc0_graph_oclass; + device->oclass[NVDEV_ENGINE_VP ] = &nv84_vp_oclass; + device->oclass[NVDEV_ENGINE_BSP ] = &nv84_bsp_oclass; + device->oclass[NVDEV_ENGINE_PPP ] = &nv98_ppp_oclass; + device->oclass[NVDEV_ENGINE_COPY0 ] = &nvc0_copy0_oclass; + device->oclass[NVDEV_ENGINE_COPY1 ] = &nvc0_copy1_oclass; + device->oclass[NVDEV_ENGINE_DISP ] = &nv50_disp_oclass; break; case 0xc3: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -81,6 +111,16 @@ nvc0_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass; device->oclass[NVDEV_SUBDEV_VM ] = &nvc0_vmmgr_oclass; device->oclass[NVDEV_SUBDEV_BAR ] = &nvc0_bar_oclass; + device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nvc0_dmaeng_oclass; + device->oclass[NVDEV_ENGINE_FIFO ] = &nvc0_fifo_oclass; + device->oclass[NVDEV_ENGINE_SW ] = &nvc0_software_oclass; + device->oclass[NVDEV_ENGINE_GR ] = &nvc0_graph_oclass; + device->oclass[NVDEV_ENGINE_VP ] = &nv84_vp_oclass; + device->oclass[NVDEV_ENGINE_BSP ] = &nv84_bsp_oclass; + device->oclass[NVDEV_ENGINE_PPP ] = &nv98_ppp_oclass; + device->oclass[NVDEV_ENGINE_COPY0 ] = &nvc0_copy0_oclass; + device->oclass[NVDEV_ENGINE_COPY1 ] = &nvc0_copy1_oclass; + device->oclass[NVDEV_ENGINE_DISP ] = &nv50_disp_oclass; break; case 0xce: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -95,6 +135,16 @@ nvc0_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass; device->oclass[NVDEV_SUBDEV_VM ] = &nvc0_vmmgr_oclass; device->oclass[NVDEV_SUBDEV_BAR ] = &nvc0_bar_oclass; + device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nvc0_dmaeng_oclass; + device->oclass[NVDEV_ENGINE_FIFO ] = &nvc0_fifo_oclass; + device->oclass[NVDEV_ENGINE_SW ] = &nvc0_software_oclass; + device->oclass[NVDEV_ENGINE_GR ] = &nvc0_graph_oclass; + device->oclass[NVDEV_ENGINE_VP ] = &nv84_vp_oclass; + device->oclass[NVDEV_ENGINE_BSP ] = &nv84_bsp_oclass; + device->oclass[NVDEV_ENGINE_PPP ] = &nv98_ppp_oclass; + device->oclass[NVDEV_ENGINE_COPY0 ] = &nvc0_copy0_oclass; + device->oclass[NVDEV_ENGINE_COPY1 ] = &nvc0_copy1_oclass; + device->oclass[NVDEV_ENGINE_DISP ] = &nv50_disp_oclass; break; case 0xcf: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -109,6 +159,16 @@ nvc0_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass; device->oclass[NVDEV_SUBDEV_VM ] = &nvc0_vmmgr_oclass; device->oclass[NVDEV_SUBDEV_BAR ] = &nvc0_bar_oclass; + device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nvc0_dmaeng_oclass; + device->oclass[NVDEV_ENGINE_FIFO ] = &nvc0_fifo_oclass; + device->oclass[NVDEV_ENGINE_SW ] = &nvc0_software_oclass; + device->oclass[NVDEV_ENGINE_GR ] = &nvc0_graph_oclass; + device->oclass[NVDEV_ENGINE_VP ] = &nv84_vp_oclass; + device->oclass[NVDEV_ENGINE_BSP ] = &nv84_bsp_oclass; + device->oclass[NVDEV_ENGINE_PPP ] = &nv98_ppp_oclass; + device->oclass[NVDEV_ENGINE_COPY0 ] = &nvc0_copy0_oclass; + device->oclass[NVDEV_ENGINE_COPY1 ] = &nvc0_copy1_oclass; + device->oclass[NVDEV_ENGINE_DISP ] = &nv50_disp_oclass; break; case 0xc1: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -123,6 +183,16 @@ nvc0_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass; device->oclass[NVDEV_SUBDEV_VM ] = &nvc0_vmmgr_oclass; device->oclass[NVDEV_SUBDEV_BAR ] = &nvc0_bar_oclass; + device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nvc0_dmaeng_oclass; + device->oclass[NVDEV_ENGINE_FIFO ] = &nvc0_fifo_oclass; + device->oclass[NVDEV_ENGINE_SW ] = &nvc0_software_oclass; + device->oclass[NVDEV_ENGINE_GR ] = &nvc0_graph_oclass; + device->oclass[NVDEV_ENGINE_VP ] = &nv84_vp_oclass; + device->oclass[NVDEV_ENGINE_BSP ] = &nv84_bsp_oclass; + device->oclass[NVDEV_ENGINE_PPP ] = &nv98_ppp_oclass; + device->oclass[NVDEV_ENGINE_COPY0 ] = &nvc0_copy0_oclass; + device->oclass[NVDEV_ENGINE_COPY1 ] = &nvc0_copy1_oclass; + device->oclass[NVDEV_ENGINE_DISP ] = &nv50_disp_oclass; break; case 0xc8: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -137,6 +207,16 @@ nvc0_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass; device->oclass[NVDEV_SUBDEV_VM ] = &nvc0_vmmgr_oclass; device->oclass[NVDEV_SUBDEV_BAR ] = &nvc0_bar_oclass; + device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nvc0_dmaeng_oclass; + device->oclass[NVDEV_ENGINE_FIFO ] = &nvc0_fifo_oclass; + device->oclass[NVDEV_ENGINE_SW ] = &nvc0_software_oclass; + device->oclass[NVDEV_ENGINE_GR ] = &nvc0_graph_oclass; + device->oclass[NVDEV_ENGINE_VP ] = &nv84_vp_oclass; + device->oclass[NVDEV_ENGINE_BSP ] = &nv84_bsp_oclass; + device->oclass[NVDEV_ENGINE_PPP ] = &nv98_ppp_oclass; + device->oclass[NVDEV_ENGINE_COPY0 ] = &nvc0_copy0_oclass; + device->oclass[NVDEV_ENGINE_COPY1 ] = &nvc0_copy1_oclass; + device->oclass[NVDEV_ENGINE_DISP ] = &nv50_disp_oclass; break; case 0xd9: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -151,6 +231,15 @@ nvc0_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass; device->oclass[NVDEV_SUBDEV_VM ] = &nvc0_vmmgr_oclass; device->oclass[NVDEV_SUBDEV_BAR ] = &nvc0_bar_oclass; + device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nvc0_dmaeng_oclass; + device->oclass[NVDEV_ENGINE_FIFO ] = &nvc0_fifo_oclass; + device->oclass[NVDEV_ENGINE_SW ] = &nvc0_software_oclass; + device->oclass[NVDEV_ENGINE_GR ] = &nvc0_graph_oclass; + device->oclass[NVDEV_ENGINE_VP ] = &nv84_vp_oclass; + device->oclass[NVDEV_ENGINE_BSP ] = &nv84_bsp_oclass; + device->oclass[NVDEV_ENGINE_PPP ] = &nv98_ppp_oclass; + device->oclass[NVDEV_ENGINE_COPY0 ] = &nvc0_copy0_oclass; + device->oclass[NVDEV_ENGINE_DISP ] = &nvd0_disp_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 ab8346b8bde0..f4f5a5af3c06 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/device/nve0.c +++ b/drivers/gpu/drm/nouveau/core/subdev/device/nve0.c @@ -36,6 +36,12 @@ #include #include +#include +#include +#include +#include +#include + int nve0_identify(struct nouveau_device *device) { @@ -53,6 +59,11 @@ nve0_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass; device->oclass[NVDEV_SUBDEV_VM ] = &nvc0_vmmgr_oclass; device->oclass[NVDEV_SUBDEV_BAR ] = &nvc0_bar_oclass; + device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nvc0_dmaeng_oclass; + device->oclass[NVDEV_ENGINE_FIFO ] = &nve0_fifo_oclass; + device->oclass[NVDEV_ENGINE_SW ] = &nvc0_software_oclass; + device->oclass[NVDEV_ENGINE_GR ] = &nve0_graph_oclass; + device->oclass[NVDEV_ENGINE_DISP ] = &nvd0_disp_oclass; break; case 0xe7: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -67,6 +78,11 @@ nve0_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass; device->oclass[NVDEV_SUBDEV_VM ] = &nvc0_vmmgr_oclass; device->oclass[NVDEV_SUBDEV_BAR ] = &nvc0_bar_oclass; + device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nvc0_dmaeng_oclass; + device->oclass[NVDEV_ENGINE_FIFO ] = &nve0_fifo_oclass; + device->oclass[NVDEV_ENGINE_SW ] = &nvc0_software_oclass; + device->oclass[NVDEV_ENGINE_GR ] = &nve0_graph_oclass; + device->oclass[NVDEV_ENGINE_DISP ] = &nvd0_disp_oclass; break; default: nv_fatal(device, "unknown Kepler chipset\n"); diff --git a/drivers/gpu/drm/nouveau/core/subdev/instmem/nv04.c b/drivers/gpu/drm/nouveau/core/subdev/instmem/nv04.c index f44f0f096689..ba4d28b50368 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/instmem/nv04.c +++ b/drivers/gpu/drm/nouveau/core/subdev/instmem/nv04.c @@ -139,8 +139,7 @@ nv04_instmem_ctor(struct nouveau_object *parent, struct nouveau_object *engine, return ret; /* 0x10000-0x18000: reserve for RAMHT */ - ret = nouveau_gpuobj_new(parent, NULL, 0x08000, 0, - NVOBJ_FLAG_ZERO_ALLOC, &priv->ramht); + ret = nouveau_ramht_new(parent, NULL, 0x08000, 0, &priv->ramht); if (ret) return ret; @@ -165,7 +164,7 @@ nv04_instmem_dtor(struct nouveau_object *object) struct nv04_instmem_priv *priv = (void *)object; nouveau_gpuobj_ref(NULL, &priv->ramfc); nouveau_gpuobj_ref(NULL, &priv->ramro); - nouveau_gpuobj_ref(NULL, &priv->ramht); + nouveau_ramht_ref(NULL, &priv->ramht); nouveau_gpuobj_ref(NULL, &priv->vbios); nouveau_mm_fini(&priv->heap); if (priv->iomem) diff --git a/drivers/gpu/drm/nouveau/core/subdev/instmem/nv04.h b/drivers/gpu/drm/nouveau/core/subdev/instmem/nv04.h index b2f82f9e4e7f..7983d8d9b358 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/instmem/nv04.h +++ b/drivers/gpu/drm/nouveau/core/subdev/instmem/nv04.h @@ -2,6 +2,7 @@ #define __NV04_INSTMEM_H__ #include +#include #include #include @@ -14,11 +15,17 @@ struct nv04_instmem_priv { struct nouveau_mm heap; struct nouveau_gpuobj *vbios; - struct nouveau_gpuobj *ramht; + struct nouveau_ramht *ramht; struct nouveau_gpuobj *ramro; struct nouveau_gpuobj *ramfc; }; +static inline struct nv04_instmem_priv * +nv04_instmem(void *obj) +{ + return (void *)nouveau_instmem(obj); +} + struct nv04_instobj_priv { struct nouveau_instobj base; struct nouveau_mm_node *mem; diff --git a/drivers/gpu/drm/nouveau/core/subdev/instmem/nv40.c b/drivers/gpu/drm/nouveau/core/subdev/instmem/nv40.c index 6a22160324c1..73c52ebd5932 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/instmem/nv40.c +++ b/drivers/gpu/drm/nouveau/core/subdev/instmem/nv40.c @@ -87,8 +87,7 @@ nv40_instmem_ctor(struct nouveau_object *parent, struct nouveau_object *engine, return ret; /* 0x10000-0x18000: reserve for RAMHT */ - ret = nouveau_gpuobj_new(parent, NULL, 0x08000, 0, - NVOBJ_FLAG_ZERO_ALLOC, &priv->ramht); + ret = nouveau_ramht_new(parent, NULL, 0x08000, 0, &priv->ramht); if (ret) return ret; diff --git a/drivers/gpu/drm/nouveau/core/subdev/vm/base.c b/drivers/gpu/drm/nouveau/core/subdev/vm/base.c index b92b3d47c69c..082c11b75acb 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/vm/base.c +++ b/drivers/gpu/drm/nouveau/core/subdev/vm/base.c @@ -299,6 +299,7 @@ nouveau_vm_get(struct nouveau_vm *vm, u64 size, u32 page_shift, fpde = (vma->node->offset >> vmm->pgt_bits); lpde = (vma->node->offset + vma->node->length - 1) >> vmm->pgt_bits; + for (pde = fpde; pde <= lpde; pde++) { struct nouveau_vm_pgt *vpgt = &vm->pgt[pde - vm->fpde]; int big = (vma->node->type != vmm->spg_shift); diff --git a/drivers/gpu/drm/nouveau/core/subdev/vm/nv04.c b/drivers/gpu/drm/nouveau/core/subdev/vm/nv04.c index 6475c0201d01..bfe6766d36ec 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/vm/nv04.c +++ b/drivers/gpu/drm/nouveau/core/subdev/vm/nv04.c @@ -96,6 +96,7 @@ nv04_vmmgr_ctor(struct nouveau_object *parent, struct nouveau_object *engine, return ret; priv->base.create = nv04_vm_create; + priv->base.limit = NV04_PDMA_SIZE; priv->base.pgt_bits = 32 - 12; priv->base.spg_shift = 12; priv->base.lpg_shift = 12; diff --git a/drivers/gpu/drm/nouveau/core/subdev/vm/nv04.h b/drivers/gpu/drm/nouveau/core/subdev/vm/nv04.h index 530930320bc4..e21369cd09c0 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/vm/nv04.h +++ b/drivers/gpu/drm/nouveau/core/subdev/vm/nv04.h @@ -10,4 +10,10 @@ struct nv04_vmmgr_priv { dma_addr_t null; }; +static inline struct nv04_vmmgr_priv * +nv04_vmmgr(void *obj) +{ + return (void *)nouveau_vmmgr(obj); +} + #endif diff --git a/drivers/gpu/drm/nouveau/core/subdev/vm/nv41.c b/drivers/gpu/drm/nouveau/core/subdev/vm/nv41.c index f0367703dff0..bbeac8d296ed 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/vm/nv41.c +++ b/drivers/gpu/drm/nouveau/core/subdev/vm/nv41.c @@ -97,6 +97,7 @@ nv41_vmmgr_ctor(struct nouveau_object *parent, struct nouveau_object *engine, return ret; priv->base.create = nv04_vm_create; + priv->base.limit = NV41_GART_SIZE; priv->base.pgt_bits = 32 - 12; priv->base.spg_shift = 12; priv->base.lpg_shift = 12; diff --git a/drivers/gpu/drm/nouveau/core/subdev/vm/nv44.c b/drivers/gpu/drm/nouveau/core/subdev/vm/nv44.c index d17f76120bcd..d099cde3a7f5 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/vm/nv44.c +++ b/drivers/gpu/drm/nouveau/core/subdev/vm/nv44.c @@ -178,6 +178,7 @@ nv44_vmmgr_ctor(struct nouveau_object *parent, struct nouveau_object *engine, return ret; priv->base.create = nv04_vm_create; + priv->base.limit = NV44_GART_SIZE; priv->base.pgt_bits = 32 - 12; priv->base.spg_shift = 12; priv->base.lpg_shift = 12; diff --git a/drivers/gpu/drm/nouveau/core/subdev/vm/nv50.c b/drivers/gpu/drm/nouveau/core/subdev/vm/nv50.c index 6e9bcd212cfc..0f0d3a5de5c2 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/vm/nv50.c +++ b/drivers/gpu/drm/nouveau/core/subdev/vm/nv50.c @@ -154,7 +154,6 @@ nv50_vm_flush(struct nouveau_vm *vm) struct nouveau_engine *engine; int i; -#if 0 for (i = 0; i < NVDEV_SUBDEV_NR; i++) { if (atomic_read(&vm->engref[i])) { engine = nouveau_engine(vm->vmm, i); @@ -162,11 +161,6 @@ nv50_vm_flush(struct nouveau_vm *vm) engine->tlb_flush(engine); } } -#else - nv50_vm_flush_engine(nv_subdev(vm->vmm), 0x06); /* bar */ - nv50_vm_flush_engine(nv_subdev(vm->vmm), 0x05); /* fifo */ - nv50_vm_flush_engine(nv_subdev(vm->vmm), 0x00); /* gr */ -#endif } void @@ -206,6 +200,7 @@ nv50_vmmgr_ctor(struct nouveau_object *parent, struct nouveau_object *engine, if (ret) return ret; + priv->base.limit = 1ULL << 40; priv->base.pgt_bits = 29 - 12; priv->base.spg_shift = 12; priv->base.lpg_shift = 16; diff --git a/drivers/gpu/drm/nouveau/core/subdev/vm/nvc0.c b/drivers/gpu/drm/nouveau/core/subdev/vm/nvc0.c index a0bc0f678d12..e48ece297511 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/vm/nvc0.c +++ b/drivers/gpu/drm/nouveau/core/subdev/vm/nvc0.c @@ -162,6 +162,7 @@ nvc0_vmmgr_ctor(struct nouveau_object *parent, struct nouveau_object *engine, if (ret) return ret; + priv->base.limit = 1ULL << 40; priv->base.pgt_bits = 27 - 12; priv->base.spg_shift = 12; priv->base.lpg_shift = 17; diff --git a/drivers/gpu/drm/nouveau/nouveau_abi16.c b/drivers/gpu/drm/nouveau/nouveau_abi16.c index 9b3a4617bffa..9e6ced3b941a 100644 --- a/drivers/gpu/drm/nouveau/nouveau_abi16.c +++ b/drivers/gpu/drm/nouveau/nouveau_abi16.c @@ -21,23 +21,153 @@ * */ -#include "drmP.h" +#include +#include +#include +#include +#include -#include "nouveau_drv.h" +#include +#include +#include + +#include "nouveau_drm.h" #include "nouveau_dma.h" +#include "nouveau_gem.h" +#include "nouveau_chan.h" #include "nouveau_abi16.h" -#include -#include "nouveau_software.h" + +struct nouveau_abi16 * +nouveau_abi16_get(struct drm_file *file_priv, struct drm_device *dev) +{ + struct nouveau_cli *cli = nouveau_cli(file_priv); + mutex_lock(&cli->mutex); + if (!cli->abi16) { + struct nouveau_abi16 *abi16; + cli->abi16 = abi16 = kzalloc(sizeof(*abi16), GFP_KERNEL); + if (cli->abi16) { + INIT_LIST_HEAD(&abi16->channels); + abi16->client = nv_object(cli); + + /* allocate device object targeting client's default + * device (ie. the one that belongs to the fd it + * opened) + */ + if (nouveau_object_new(abi16->client, NVDRM_CLIENT, + NVDRM_DEVICE, 0x0080, + &(struct nv_device_class) { + .device = ~0ULL, + }, + sizeof(struct nv_device_class), + &abi16->device) == 0) + return cli->abi16; + + kfree(cli->abi16); + cli->abi16 = NULL; + } + + mutex_unlock(&cli->mutex); + } + return cli->abi16; +} + +int +nouveau_abi16_put(struct nouveau_abi16 *abi16, int ret) +{ + struct nouveau_cli *cli = (void *)abi16->client; + mutex_unlock(&cli->mutex); + return ret; +} + +u16 +nouveau_abi16_swclass(struct nouveau_drm *drm) +{ + switch (nv_device(drm->device)->card_type) { + case NV_04: + return 0x006e; + case NV_10: + case NV_20: + case NV_30: + case NV_40: + return 0x016e; + case NV_50: + return 0x506e; + case NV_C0: + case NV_D0: + case NV_E0: + return 0x906e; + } + + return 0x0000; +} + +static void +nouveau_abi16_ntfy_fini(struct nouveau_abi16_chan *chan, + struct nouveau_abi16_ntfy *ntfy) +{ + nouveau_mm_free(&chan->heap, &ntfy->node); + list_del(&ntfy->head); + kfree(ntfy); +} + +static void +nouveau_abi16_chan_fini(struct nouveau_abi16 *abi16, + struct nouveau_abi16_chan *chan) +{ + struct nouveau_abi16_ntfy *ntfy, *temp; + + /* cleanup notifier state */ + list_for_each_entry_safe(ntfy, temp, &chan->notifiers, head) { + nouveau_abi16_ntfy_fini(chan, ntfy); + } + + if (chan->ntfy) { + nouveau_bo_vma_del(chan->ntfy, &chan->ntfy_vma); + drm_gem_object_unreference_unlocked(chan->ntfy->gem); + } + + if (chan->heap.block_size) + nouveau_mm_fini(&chan->heap); + + /* destroy channel object, all children will be killed too */ + if (chan->chan) { + abi16->handles &= ~(1 << (chan->chan->handle & 0xffff)); + nouveau_channel_del(&chan->chan); + } + + list_del(&chan->head); + kfree(chan); +} + +void +nouveau_abi16_fini(struct nouveau_abi16 *abi16) +{ + struct nouveau_cli *cli = (void *)abi16->client; + struct nouveau_abi16_chan *chan, *temp; + + /* cleanup channels */ + list_for_each_entry_safe(chan, temp, &abi16->channels, head) { + nouveau_abi16_chan_fini(abi16, chan); + } + + /* destroy the device object */ + nouveau_object_del(abi16->client, NVDRM_CLIENT, NVDRM_DEVICE); + + kfree(cli->abi16); + cli->abi16 = NULL; +} int nouveau_abi16_ioctl_getparam(ABI16_IOCTL_ARGS) { - 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 drm_nouveau_getparam *getparam = data; switch (getparam->param) { case NOUVEAU_GETPARAM_CHIPSET_ID: - getparam->value = dev_priv->chipset; + getparam->value = device->chipset; break; case NOUVEAU_GETPARAM_PCI_VENDOR: getparam->value = dev->pci_vendor; @@ -55,16 +185,16 @@ nouveau_abi16_ioctl_getparam(ABI16_IOCTL_ARGS) getparam->value = 2; break; case NOUVEAU_GETPARAM_FB_SIZE: - getparam->value = dev_priv->fb_available_size; + getparam->value = drm->gem.vram_available; break; case NOUVEAU_GETPARAM_AGP_SIZE: - getparam->value = dev_priv->gart_info.aper_size; + getparam->value = drm->gem.gart_available; break; case NOUVEAU_GETPARAM_VM_VRAM_BASE: getparam->value = 0; /* deprecated */ break; case NOUVEAU_GETPARAM_PTIMER_TIME: - getparam->value = nv_timer_read(dev); + getparam->value = ptimer->read(ptimer); break; case NOUVEAU_GETPARAM_HAS_BO_USAGE: getparam->value = 1; @@ -76,13 +206,13 @@ nouveau_abi16_ioctl_getparam(ABI16_IOCTL_ARGS) /* NV40 and NV50 versions are quite different, but register * address is the same. User is supposed to know the card * family anyway... */ - if (dev_priv->chipset >= 0x40) { - getparam->value = nv_rd32(dev, NV40_PMC_GRAPH_UNITS); + if (device->chipset >= 0x40) { + getparam->value = nv_rd32(device, 0x001540); break; } /* FALLTHRU */ default: - NV_DEBUG(dev, "unknown parameter %lld\n", getparam->param); + nv_debug(device, "unknown parameter %lld\n", getparam->param); return -EINVAL; } @@ -98,148 +228,247 @@ nouveau_abi16_ioctl_setparam(ABI16_IOCTL_ARGS) int nouveau_abi16_ioctl_channel_alloc(ABI16_IOCTL_ARGS) { - struct drm_nouveau_private *dev_priv = dev->dev_private; struct drm_nouveau_channel_alloc *init = data; - struct nouveau_channel *chan; + struct nouveau_cli *cli = nouveau_cli(file_priv); + struct nouveau_drm *drm = nouveau_drm(dev); + struct nouveau_abi16 *abi16 = nouveau_abi16_get(file_priv, dev); + struct nouveau_abi16_chan *chan; + struct nouveau_client *client; + struct nouveau_device *device; + struct nouveau_instmem *imem; + struct nouveau_fb *pfb; int ret; - if (!dev_priv->eng[NVOBJ_ENGINE_GR]) - return -ENODEV; + if (unlikely(!abi16)) + return -ENOMEM; + client = nv_client(abi16->client); if (init->fb_ctxdma_handle == ~0 || init->tt_ctxdma_handle == ~0) - return -EINVAL; + return nouveau_abi16_put(abi16, -EINVAL); + + device = nv_device(abi16->device); + imem = nouveau_instmem(device); + pfb = nouveau_fb(device); + + /* allocate "abi16 channel" data and make up a handle for it */ + init->channel = ffsll(~abi16->handles); + if (!init->channel--) + return nouveau_abi16_put(abi16, -ENOSPC); + + chan = kzalloc(sizeof(*chan), GFP_KERNEL); + if (!chan) + return nouveau_abi16_put(abi16, -ENOMEM); + + INIT_LIST_HEAD(&chan->notifiers); + list_add(&chan->head, &abi16->channels); + abi16->handles |= (1 << init->channel); - ret = nouveau_channel_alloc(dev, &chan, file_priv, - init->fb_ctxdma_handle, - init->tt_ctxdma_handle); + /* create channel object and initialise dma and fence management */ + ret = nouveau_channel_new(drm, cli, NVDRM_DEVICE, NVDRM_CHAN | + init->channel, init->fb_ctxdma_handle, + init->tt_ctxdma_handle, &chan->chan); if (ret) - return ret; - init->channel = chan->id; - - if (nouveau_vram_pushbuf == 0) { - if (chan->dma.ib_max) - init->pushbuf_domains = NOUVEAU_GEM_DOMAIN_VRAM | - NOUVEAU_GEM_DOMAIN_GART; - else if (chan->pushbuf_bo->bo.mem.mem_type == TTM_PL_VRAM) - init->pushbuf_domains = NOUVEAU_GEM_DOMAIN_VRAM; - else - init->pushbuf_domains = NOUVEAU_GEM_DOMAIN_GART; - } else { + goto done; + + if (device->card_type >= NV_50) + init->pushbuf_domains = NOUVEAU_GEM_DOMAIN_VRAM | + NOUVEAU_GEM_DOMAIN_GART; + else + if (chan->chan->push.buffer->bo.mem.mem_type == TTM_PL_VRAM) init->pushbuf_domains = NOUVEAU_GEM_DOMAIN_VRAM; - } + else + init->pushbuf_domains = NOUVEAU_GEM_DOMAIN_GART; - if (dev_priv->card_type < NV_C0) { + if (device->card_type < NV_C0) { init->subchan[0].handle = 0x00000000; init->subchan[0].grclass = 0x0000; init->subchan[1].handle = NvSw; - init->subchan[1].grclass = NV_SW; + init->subchan[1].grclass = 0x506e; init->nr_subchan = 2; } /* Named memory object area */ - ret = drm_gem_handle_create(file_priv, chan->notifier_bo->gem, + ret = nouveau_gem_new(dev, PAGE_SIZE, 0, NOUVEAU_GEM_DOMAIN_GART, + 0, 0, &chan->ntfy); + if (ret == 0) + ret = nouveau_bo_pin(chan->ntfy, TTM_PL_FLAG_TT); + if (ret) + goto done; + + if (device->card_type >= NV_50) { + ret = nouveau_bo_vma_add(chan->ntfy, client->vm, + &chan->ntfy_vma); + if (ret) + goto done; + } + + ret = drm_gem_handle_create(file_priv, chan->ntfy->gem, &init->notifier_handle); + if (ret) + goto done; - if (ret == 0) - atomic_inc(&chan->users); /* userspace reference */ - nouveau_channel_put(&chan); - return ret; + ret = nouveau_mm_init(&chan->heap, 0, PAGE_SIZE, 1); +done: + if (ret) + nouveau_abi16_chan_fini(abi16, chan); + return nouveau_abi16_put(abi16, ret); } + int nouveau_abi16_ioctl_channel_free(ABI16_IOCTL_ARGS) { struct drm_nouveau_channel_free *req = data; - struct nouveau_channel *chan; + struct nouveau_abi16 *abi16 = nouveau_abi16_get(file_priv, dev); + struct nouveau_abi16_chan *chan; + int ret = -ENOENT; - chan = nouveau_channel_get(file_priv, req->channel); - if (IS_ERR(chan)) - return PTR_ERR(chan); + if (unlikely(!abi16)) + return -ENOMEM; - list_del(&chan->list); - atomic_dec(&chan->users); - nouveau_channel_put(&chan); - return 0; + list_for_each_entry(chan, &abi16->channels, head) { + if (chan->chan->handle == (NVDRM_CHAN | req->channel)) { + nouveau_abi16_chan_fini(abi16, chan); + return nouveau_abi16_put(abi16, 0); + } + } + + return nouveau_abi16_put(abi16, ret); } int nouveau_abi16_ioctl_grobj_alloc(ABI16_IOCTL_ARGS) { struct drm_nouveau_grobj_alloc *init = data; - struct nouveau_channel *chan; + struct nouveau_abi16 *abi16 = nouveau_abi16_get(file_priv, dev); + struct nouveau_drm *drm = nouveau_drm(dev); + struct nouveau_object *object; int ret; + if (unlikely(!abi16)) + return -ENOMEM; + if (init->handle == ~0) - return -EINVAL; + return nouveau_abi16_put(abi16, -EINVAL); /* compatibility with userspace that assumes 506e for all chipsets */ if (init->class == 0x506e) { - init->class = nouveau_software_class(dev); + init->class = nouveau_abi16_swclass(drm); if (init->class == 0x906e) - return 0; - } else - if (init->class == 0x906e) { - NV_DEBUG(dev, "906e not supported yet\n"); - return -EINVAL; - } - - chan = nouveau_channel_get(file_priv, init->channel); - if (IS_ERR(chan)) - return PTR_ERR(chan); - - if (nouveau_ramht_find(chan, init->handle)) { - ret = -EEXIST; - goto out; + return nouveau_abi16_put(abi16, 0); } - ret = nouveau_gpuobj_gr_new(chan, init->handle, init->class); - if (ret) { - NV_ERROR(dev, "Error creating object: %d (%d/0x%08x)\n", - ret, init->channel, init->handle); - } - -out: - nouveau_channel_put(&chan); - return ret; + ret = nouveau_object_new(abi16->client, NVDRM_CHAN | init->channel, + init->handle, init->class, NULL, 0, &object); + return nouveau_abi16_put(abi16, ret); } int nouveau_abi16_ioctl_notifierobj_alloc(ABI16_IOCTL_ARGS) { - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct drm_nouveau_notifierobj_alloc *na = data; - struct nouveau_channel *chan; + struct drm_nouveau_notifierobj_alloc *info = data; + struct nouveau_drm *drm = nouveau_drm(dev); + struct nouveau_device *device = nv_device(drm->device); + struct nouveau_abi16 *abi16 = nouveau_abi16_get(file_priv, dev); + struct nouveau_abi16_chan *chan, *temp; + struct nouveau_abi16_ntfy *ntfy; + struct nouveau_object *object; + struct nv_dma_class args; int ret; + if (unlikely(!abi16)) + return -ENOMEM; + /* completely unnecessary for these chipsets... */ - if (unlikely(dev_priv->card_type >= NV_C0)) - return -EINVAL; + if (unlikely(nv_device(abi16->device)->card_type >= NV_C0)) + return nouveau_abi16_put(abi16, -EINVAL); - chan = nouveau_channel_get(file_priv, na->channel); - if (IS_ERR(chan)) - return PTR_ERR(chan); + list_for_each_entry_safe(chan, temp, &abi16->channels, head) { + if (chan->chan->handle == (NVDRM_CHAN | info->channel)) + break; + chan = NULL; + } - ret = nouveau_notifier_alloc(chan, na->handle, na->size, 0, 0x1000, - &na->offset); - nouveau_channel_put(&chan); - return ret; + if (!chan) + return nouveau_abi16_put(abi16, -ENOENT); + + ntfy = kzalloc(sizeof(*ntfy), GFP_KERNEL); + if (!ntfy) + return nouveau_abi16_put(abi16, -ENOMEM); + + list_add(&ntfy->head, &chan->notifiers); + ntfy->handle = info->handle; + + ret = nouveau_mm_head(&chan->heap, 1, info->size, info->size, 1, + &ntfy->node); + if (ret) + goto done; + + args.start = ntfy->node->offset; + args.limit = ntfy->node->offset + ntfy->node->length - 1; + if (device->card_type >= NV_50) { + args.flags = NV_DMA_TARGET_VM | NV_DMA_ACCESS_VM; + args.start += chan->ntfy_vma.offset; + args.limit += chan->ntfy_vma.offset; + } else + if (drm->agp.stat == ENABLED) { + args.flags = NV_DMA_TARGET_AGP | NV_DMA_ACCESS_RDWR; + args.start += drm->agp.base + chan->ntfy->bo.offset; + args.limit += drm->agp.base + chan->ntfy->bo.offset; + } else { + args.flags = NV_DMA_TARGET_VM | NV_DMA_ACCESS_RDWR; + args.start += chan->ntfy->bo.offset; + args.limit += chan->ntfy->bo.offset; + } + + ret = nouveau_object_new(abi16->client, chan->chan->handle, + ntfy->handle, 0x003d, &args, + sizeof(args), &object); + if (ret) + goto done; + +done: + if (ret) + nouveau_abi16_ntfy_fini(chan, ntfy); + return nouveau_abi16_put(abi16, ret); } int nouveau_abi16_ioctl_gpuobj_free(ABI16_IOCTL_ARGS) { - struct drm_nouveau_gpuobj_free *objfree = data; - struct nouveau_channel *chan; + struct drm_nouveau_gpuobj_free *fini = data; + struct nouveau_abi16 *abi16 = nouveau_abi16_get(file_priv, dev); + struct nouveau_abi16_chan *chan, *temp; + struct nouveau_abi16_ntfy *ntfy; int ret; - chan = nouveau_channel_get(file_priv, objfree->channel); - if (IS_ERR(chan)) - return PTR_ERR(chan); + if (unlikely(!abi16)) + return -ENOMEM; + + list_for_each_entry_safe(chan, temp, &abi16->channels, head) { + if (chan->chan->handle == (NVDRM_CHAN | fini->channel)) + break; + chan = NULL; + } + + if (!chan) + return nouveau_abi16_put(abi16, -ENOENT); - /* Synchronize with the user channel */ - nouveau_channel_idle(chan); + /* synchronize with the user channel and destroy the gpu object */ + nouveau_channel_idle(chan->chan); - ret = nouveau_ramht_remove(chan, objfree->handle); - nouveau_channel_put(&chan); - return ret; + ret = nouveau_object_del(abi16->client, chan->chan->handle, fini->handle); + if (ret) + return nouveau_abi16_put(abi16, ret); + + /* cleanup extra state if this object was a notifier */ + list_for_each_entry(ntfy, &chan->notifiers, head) { + if (ntfy->handle == fini->handle) { + nouveau_mm_free(&chan->heap, &ntfy->node); + list_del(&ntfy->head); + break; + } + } + + return nouveau_abi16_put(abi16, 0); } diff --git a/drivers/gpu/drm/nouveau/nouveau_abi16.h b/drivers/gpu/drm/nouveau/nouveau_abi16.h index e6328b008a8c..90004081a501 100644 --- a/drivers/gpu/drm/nouveau/nouveau_abi16.h +++ b/drivers/gpu/drm/nouveau/nouveau_abi16.h @@ -3,6 +3,7 @@ #define ABI16_IOCTL_ARGS \ struct drm_device *dev, void *data, struct drm_file *file_priv + int nouveau_abi16_ioctl_getparam(ABI16_IOCTL_ARGS); int nouveau_abi16_ioctl_setparam(ABI16_IOCTL_ARGS); int nouveau_abi16_ioctl_channel_alloc(ABI16_IOCTL_ARGS); @@ -11,6 +12,37 @@ int nouveau_abi16_ioctl_grobj_alloc(ABI16_IOCTL_ARGS); int nouveau_abi16_ioctl_notifierobj_alloc(ABI16_IOCTL_ARGS); int nouveau_abi16_ioctl_gpuobj_free(ABI16_IOCTL_ARGS); +struct nouveau_abi16_ntfy { + struct list_head head; + struct nouveau_mm_node *node; + u32 handle; +}; + +struct nouveau_abi16_chan { + struct list_head head; + struct nouveau_channel *chan; + struct list_head notifiers; + struct nouveau_bo *ntfy; + struct nouveau_vma ntfy_vma; + struct nouveau_mm heap; +}; + +struct nouveau_abi16 { + struct nouveau_object *client; + struct nouveau_object *device; + struct list_head channels; + u64 handles; +}; + +struct nouveau_drm; +struct nouveau_abi16 *nouveau_abi16_get(struct drm_file *, struct drm_device *); +int nouveau_abi16_put(struct nouveau_abi16 *, int); +void nouveau_abi16_fini(struct nouveau_abi16 *); +u16 nouveau_abi16_swclass(struct nouveau_drm *); + +#define NOUVEAU_GEM_DOMAIN_VRAM (1 << 1) +#define NOUVEAU_GEM_DOMAIN_GART (1 << 2) + struct drm_nouveau_channel_alloc { uint32_t fb_ctxdma_handle; uint32_t tt_ctxdma_handle; diff --git a/drivers/gpu/drm/nouveau/nouveau_acpi.c b/drivers/gpu/drm/nouveau/nouveau_acpi.c index 778cd149f7cd..83686ef75d04 100644 --- a/drivers/gpu/drm/nouveau/nouveau_acpi.c +++ b/drivers/gpu/drm/nouveau/nouveau_acpi.c @@ -13,7 +13,6 @@ #include "drm_crtc_helper.h" #include "nouveau_drv.h" #include -#include "nv50_display.h" #include "nouveau_connector.h" #include diff --git a/drivers/gpu/drm/nouveau/nouveau_bo.c b/drivers/gpu/drm/nouveau/nouveau_bo.c index c3e66ae04c83..3465df327227 100644 --- a/drivers/gpu/drm/nouveau/nouveau_bo.c +++ b/drivers/gpu/drm/nouveau/nouveau_bo.c @@ -27,66 +27,57 @@ * Jeremy Kolb */ -#include "drmP.h" -#include "ttm/ttm_page_alloc.h" +#include -#include -#include "nouveau_drv.h" +#include +#include +#include + +#include "nouveau_drm.h" #include "nouveau_dma.h" -#include #include "nouveau_fence.h" -#include -#include -#include -#include +#include "nouveau_bo.h" +#include "nouveau_ttm.h" +#include "nouveau_gem.h" /* * NV10-NV40 tiling helpers */ static void -nv10_bo_update_tile_region(struct drm_device *dev, - struct nouveau_tile_reg *tilereg, uint32_t addr, - uint32_t size, uint32_t pitch, uint32_t flags) +nv10_bo_update_tile_region(struct drm_device *dev, struct nouveau_drm_tile *reg, + u32 addr, u32 size, u32 pitch, u32 flags) { - struct drm_nouveau_private *dev_priv = dev->dev_private; - int i = tilereg - dev_priv->tile.reg, j; - struct nouveau_fb_tile *tile = nvfb_tile(dev, i); - unsigned long save; + struct nouveau_drm *drm = nouveau_newpriv(dev); + int i = reg - drm->tile.reg; + struct nouveau_fb *pfb = nouveau_fb(drm->device); + struct nouveau_fb_tile *tile = &pfb->tile.region[i]; + struct nouveau_engine *engine; - nouveau_fence_unref(&tilereg->fence); + nouveau_fence_unref(®->fence); if (tile->pitch) - nvfb_tile_fini(dev, i); + pfb->tile.fini(pfb, i, tile); if (pitch) - nvfb_tile_init(dev, i, addr, size, pitch, flags); - - spin_lock_irqsave(&dev_priv->context_switch_lock, save); - nv_wr32(dev, NV03_PFIFO_CACHES, 0); - nv04_fifo_cache_pull(dev, false); + pfb->tile.init(pfb, i, addr, size, pitch, flags, tile); - nouveau_wait_for_idle(dev); - - nvfb_tile_prog(dev, i); - for (j = 0; j < NVOBJ_ENGINE_NR; j++) { - if (dev_priv->eng[j] && dev_priv->eng[j]->set_tile_region) - dev_priv->eng[j]->set_tile_region(dev, i); - } + pfb->tile.prog(pfb, i, tile); - nv04_fifo_cache_pull(dev, true); - nv_wr32(dev, NV03_PFIFO_CACHES, 1); - spin_unlock_irqrestore(&dev_priv->context_switch_lock, save); + if ((engine = nouveau_engine(pfb, NVDEV_ENGINE_GR))) + engine->tile_prog(engine, i); + if ((engine = nouveau_engine(pfb, NVDEV_ENGINE_MPEG))) + engine->tile_prog(engine, i); } -static struct nouveau_tile_reg * +static struct nouveau_drm_tile * nv10_bo_get_tile_region(struct drm_device *dev, int i) { - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_tile_reg *tile = &dev_priv->tile.reg[i]; + struct nouveau_drm *drm = nouveau_newpriv(dev); + struct nouveau_drm_tile *tile = &drm->tile.reg[i]; - spin_lock(&dev_priv->tile.lock); + spin_lock(&drm->tile.lock); if (!tile->used && (!tile->fence || nouveau_fence_done(tile->fence))) @@ -94,18 +85,18 @@ nv10_bo_get_tile_region(struct drm_device *dev, int i) else tile = NULL; - spin_unlock(&dev_priv->tile.lock); + spin_unlock(&drm->tile.lock); return tile; } static void -nv10_bo_put_tile_region(struct drm_device *dev, struct nouveau_tile_reg *tile, - struct nouveau_fence *fence) +nv10_bo_put_tile_region(struct drm_device *dev, struct nouveau_drm_tile *tile, + struct nouveau_fence *fence) { - struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_drm *drm = nouveau_newpriv(dev); if (tile) { - spin_lock(&dev_priv->tile.lock); + spin_lock(&drm->tile.lock); if (fence) { /* Mark it as pending. */ tile->fence = fence; @@ -113,25 +104,27 @@ nv10_bo_put_tile_region(struct drm_device *dev, struct nouveau_tile_reg *tile, } tile->used = false; - spin_unlock(&dev_priv->tile.lock); + spin_unlock(&drm->tile.lock); } } -static struct nouveau_tile_reg * -nv10_bo_set_tiling(struct drm_device *dev, uint32_t addr, uint32_t size, - uint32_t pitch, uint32_t flags) +static struct nouveau_drm_tile * +nv10_bo_set_tiling(struct drm_device *dev, u32 addr, + u32 size, u32 pitch, u32 flags) { - struct nouveau_tile_reg *tile, *found = NULL; + struct nouveau_drm *drm = nouveau_newpriv(dev); + struct nouveau_fb *pfb = nouveau_fb(drm->device); + struct nouveau_drm_tile *tile, *found = NULL; int i; - for (i = 0; i < nvfb_tile_nr(dev); i++) { + for (i = 0; i < pfb->tile.regions; i++) { tile = nv10_bo_get_tile_region(dev, i); if (pitch && !found) { found = tile; continue; - } else if (tile && nvfb_tile(dev, i)->pitch) { + } else if (tile && pfb->tile.region[i].pitch) { /* Kill an unused tile region. */ nv10_bo_update_tile_region(dev, tile, 0, 0, 0, 0); } @@ -148,13 +141,12 @@ nv10_bo_set_tiling(struct drm_device *dev, uint32_t addr, uint32_t size, static void nouveau_bo_del_ttm(struct ttm_buffer_object *bo) { - struct drm_nouveau_private *dev_priv = nouveau_bdev(bo->bdev); - struct drm_device *dev = dev_priv->dev; + struct nouveau_drm *drm = nouveau_bdev(bo->bdev); + struct drm_device *dev = drm->dev; struct nouveau_bo *nvbo = nouveau_bo(bo); if (unlikely(nvbo->gem)) DRM_ERROR("bo %p still attached to GEM object\n", bo); - nv10_bo_put_tile_region(dev, nvbo->tile, NULL); kfree(nvbo); } @@ -163,23 +155,24 @@ static void nouveau_bo_fixup_align(struct nouveau_bo *nvbo, u32 flags, int *align, int *size) { - struct drm_nouveau_private *dev_priv = nouveau_bdev(nvbo->bo.bdev); + struct nouveau_drm *drm = nouveau_bdev(nvbo->bo.bdev); + struct nouveau_device *device = nv_device(drm->device); - if (dev_priv->card_type < NV_50) { + if (device->card_type < NV_50) { if (nvbo->tile_mode) { - if (dev_priv->chipset >= 0x40) { + if (device->chipset >= 0x40) { *align = 65536; *size = roundup(*size, 64 * nvbo->tile_mode); - } else if (dev_priv->chipset >= 0x30) { + } else if (device->chipset >= 0x30) { *align = 32768; *size = roundup(*size, 64 * nvbo->tile_mode); - } else if (dev_priv->chipset >= 0x20) { + } else if (device->chipset >= 0x20) { *align = 16384; *size = roundup(*size, 64 * nvbo->tile_mode); - } else if (dev_priv->chipset >= 0x10) { + } else if (device->chipset >= 0x10) { *align = 16384; *size = roundup(*size, 32 * nvbo->tile_mode); } @@ -198,7 +191,7 @@ nouveau_bo_new(struct drm_device *dev, int size, int align, struct sg_table *sg, struct nouveau_bo **pnvbo) { - struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_drm *drm = nouveau_newpriv(dev); struct nouveau_bo *nvbo; size_t acc_size; int ret; @@ -215,22 +208,22 @@ nouveau_bo_new(struct drm_device *dev, int size, int align, INIT_LIST_HEAD(&nvbo->vma_list); nvbo->tile_mode = tile_mode; nvbo->tile_flags = tile_flags; - nvbo->bo.bdev = &dev_priv->ttm.bdev; + nvbo->bo.bdev = &drm->ttm.bdev; nvbo->page_shift = 12; - if (dev_priv->chan_vm) { + if (drm->client.base.vm) { if (!(flags & TTM_PL_FLAG_TT) && size > 256 * 1024) - nvbo->page_shift = nvvm_lpg_shift(dev_priv->chan_vm); + nvbo->page_shift = drm->client.base.vm->vmm->lpg_shift; } nouveau_bo_fixup_align(nvbo, flags, &align, &size); nvbo->bo.mem.num_pages = size >> PAGE_SHIFT; nouveau_bo_placement_set(nvbo, flags, 0); - acc_size = ttm_bo_dma_acc_size(&dev_priv->ttm.bdev, size, + acc_size = ttm_bo_dma_acc_size(&drm->ttm.bdev, size, sizeof(struct nouveau_bo)); - ret = ttm_bo_init(&dev_priv->ttm.bdev, &nvbo->bo, size, + ret = ttm_bo_init(&drm->ttm.bdev, &nvbo->bo, size, type, &nvbo->placement, align >> PAGE_SHIFT, 0, false, NULL, acc_size, sg, nouveau_bo_del_ttm); @@ -259,10 +252,11 @@ set_placement_list(uint32_t *pl, unsigned *n, uint32_t type, uint32_t flags) static void set_placement_range(struct nouveau_bo *nvbo, uint32_t type) { - struct drm_nouveau_private *dev_priv = nouveau_bdev(nvbo->bo.bdev); - int vram_pages = nvfb_vram_size(dev_priv->dev) >> PAGE_SHIFT; + struct nouveau_drm *drm = nouveau_bdev(nvbo->bo.bdev); + struct nouveau_fb *pfb = nouveau_fb(drm->device); + u32 vram_pages = pfb->ram.size >> PAGE_SHIFT; - if (dev_priv->card_type == NV_10 && + if (nv_device(drm->device)->card_type == NV_10 && nvbo->tile_mode && (type & TTM_PL_FLAG_VRAM) && nvbo->bo.mem.num_pages < vram_pages / 4) { /* @@ -302,13 +296,12 @@ nouveau_bo_placement_set(struct nouveau_bo *nvbo, uint32_t type, uint32_t busy) int nouveau_bo_pin(struct nouveau_bo *nvbo, uint32_t memtype) { - struct drm_nouveau_private *dev_priv = nouveau_bdev(nvbo->bo.bdev); + struct nouveau_drm *drm = nouveau_bdev(nvbo->bo.bdev); struct ttm_buffer_object *bo = &nvbo->bo; int ret; if (nvbo->pin_refcnt && !(memtype & (1 << bo->mem.mem_type))) { - NV_ERROR(nouveau_bdev(bo->bdev)->dev, - "bo %p pinned elsewhere: 0x%08x vs 0x%08x\n", bo, + NV_ERROR(drm, "bo %p pinned elsewhere: 0x%08x vs 0x%08x\n", bo, 1 << bo->mem.mem_type, memtype); return -EINVAL; } @@ -326,10 +319,10 @@ nouveau_bo_pin(struct nouveau_bo *nvbo, uint32_t memtype) if (ret == 0) { switch (bo->mem.mem_type) { case TTM_PL_VRAM: - dev_priv->fb_aper_free -= bo->mem.size; + drm->gem.vram_available -= bo->mem.size; break; case TTM_PL_TT: - dev_priv->gart_info.aper_free -= bo->mem.size; + drm->gem.gart_available -= bo->mem.size; break; default: break; @@ -345,7 +338,7 @@ out: int nouveau_bo_unpin(struct nouveau_bo *nvbo) { - struct drm_nouveau_private *dev_priv = nouveau_bdev(nvbo->bo.bdev); + struct nouveau_drm *drm = nouveau_bdev(nvbo->bo.bdev); struct ttm_buffer_object *bo = &nvbo->bo; int ret; @@ -362,10 +355,10 @@ nouveau_bo_unpin(struct nouveau_bo *nvbo) if (ret == 0) { switch (bo->mem.mem_type) { case TTM_PL_VRAM: - dev_priv->fb_aper_free += bo->mem.size; + drm->gem.vram_available += bo->mem.size; break; case TTM_PL_TT: - dev_priv->gart_info.aper_free += bo->mem.size; + drm->gem.gart_available += bo->mem.size; break; default: break; @@ -460,30 +453,18 @@ nouveau_bo_wr32(struct nouveau_bo *nvbo, unsigned index, u32 val) } static struct ttm_tt * -nouveau_ttm_tt_create(struct ttm_bo_device *bdev, - unsigned long size, uint32_t page_flags, - struct page *dummy_read_page) +nouveau_ttm_tt_create(struct ttm_bo_device *bdev, unsigned long size, + uint32_t page_flags, struct page *dummy_read) { - struct drm_nouveau_private *dev_priv = nouveau_bdev(bdev); - struct drm_device *dev = dev_priv->dev; + struct nouveau_drm *drm = nouveau_bdev(bdev); + struct drm_device *dev = drm->dev; - switch (dev_priv->gart_info.type) { -#if __OS_HAS_AGP - case NOUVEAU_GART_AGP: - return ttm_agp_tt_create(bdev, dev->agp->bridge, - size, page_flags, dummy_read_page); -#endif - case NOUVEAU_GART_PDMA: - case NOUVEAU_GART_HW: - return nouveau_sgdma_create_ttm(bdev, size, page_flags, - dummy_read_page); - default: - NV_ERROR(dev, "Unknown GART type %d\n", - dev_priv->gart_info.type); - break; + if (drm->agp.stat == ENABLED) { + return ttm_agp_tt_create(bdev, dev->agp->bridge, size, + page_flags, dummy_read); } - return NULL; + return nouveau_sgdma_create_ttm(bdev, size, page_flags, dummy_read); } static int @@ -497,8 +478,7 @@ static int nouveau_bo_init_mem_type(struct ttm_bo_device *bdev, uint32_t type, struct ttm_mem_type_manager *man) { - struct drm_nouveau_private *dev_priv = nouveau_bdev(bdev); - struct drm_device *dev = dev_priv->dev; + struct nouveau_drm *drm = nouveau_bdev(bdev); switch (type) { case TTM_PL_SYSTEM: @@ -507,7 +487,7 @@ nouveau_bo_init_mem_type(struct ttm_bo_device *bdev, uint32_t type, man->default_caching = TTM_PL_FLAG_CACHED; break; case TTM_PL_VRAM: - if (dev_priv->card_type >= NV_50) { + if (nv_device(drm->device)->card_type >= NV_50) { man->func = &nouveau_vram_manager; man->io_reserve_fastpath = false; man->use_io_reserve_lru = true; @@ -521,35 +501,28 @@ nouveau_bo_init_mem_type(struct ttm_bo_device *bdev, uint32_t type, man->default_caching = TTM_PL_FLAG_WC; break; case TTM_PL_TT: - if (dev_priv->card_type >= NV_50) + if (nv_device(drm->device)->card_type >= NV_50) man->func = &nouveau_gart_manager; else - if (dev_priv->gart_info.type != NOUVEAU_GART_AGP) + if (drm->agp.stat != ENABLED) man->func = &nv04_gart_manager; else man->func = &ttm_bo_manager_func; - switch (dev_priv->gart_info.type) { - case NOUVEAU_GART_AGP: + + if (drm->agp.stat == ENABLED) { man->flags = TTM_MEMTYPE_FLAG_MAPPABLE; man->available_caching = TTM_PL_FLAG_UNCACHED | TTM_PL_FLAG_WC; man->default_caching = TTM_PL_FLAG_WC; - break; - case NOUVEAU_GART_PDMA: - case NOUVEAU_GART_HW: + } else { man->flags = TTM_MEMTYPE_FLAG_MAPPABLE | TTM_MEMTYPE_FLAG_CMA; man->available_caching = TTM_PL_MASK_CACHING; man->default_caching = TTM_PL_FLAG_CACHED; - break; - default: - NV_ERROR(dev, "Unknown GART type: %d\n", - dev_priv->gart_info.type); - return -EINVAL; } + break; default: - NV_ERROR(dev, "Unsupported memory type %u\n", (unsigned)type); return -EINVAL; } return 0; @@ -783,20 +756,14 @@ nv84_bo_move_exec(struct nouveau_channel *chan, struct ttm_buffer_object *bo, static int nv50_bo_move_init(struct nouveau_channel *chan, u32 handle) { - int ret = nouveau_notifier_alloc(chan, NvNotify0, 32, 0xfe0, 0x1000, - &chan->m2mf_ntfy); + int ret = RING_SPACE(chan, 6); if (ret == 0) { - ret = RING_SPACE(chan, 6); - if (ret == 0) { - BEGIN_NV04(chan, NvSubCopy, 0x0000, 1); - OUT_RING (chan, handle); - BEGIN_NV04(chan, NvSubCopy, 0x0180, 3); - OUT_RING (chan, NvNotify0); - OUT_RING (chan, NvDmaFB); - OUT_RING (chan, NvDmaFB); - } else { - nouveau_ramht_remove(chan, NvNotify0); - } + BEGIN_NV04(chan, NvSubCopy, 0x0000, 1); + OUT_RING (chan, handle); + BEGIN_NV04(chan, NvSubCopy, 0x0180, 3); + OUT_RING (chan, NvNotify0); + OUT_RING (chan, NvDmaFB); + OUT_RING (chan, NvDmaFB); } return ret; @@ -895,16 +862,12 @@ nv50_bo_move_m2mf(struct nouveau_channel *chan, struct ttm_buffer_object *bo, static int nv04_bo_move_init(struct nouveau_channel *chan, u32 handle) { - int ret = nouveau_notifier_alloc(chan, NvNotify0, 32, 0xfe0, 0x1000, - &chan->m2mf_ntfy); + int ret = RING_SPACE(chan, 4); if (ret == 0) { - ret = RING_SPACE(chan, 4); - if (ret == 0) { - BEGIN_NV04(chan, NvSubCopy, 0x0000, 1); - OUT_RING (chan, handle); - BEGIN_NV04(chan, NvSubCopy, 0x0180, 1); - OUT_RING (chan, NvNotify0); - } + BEGIN_NV04(chan, NvSubCopy, 0x0000, 1); + OUT_RING (chan, handle); + BEGIN_NV04(chan, NvSubCopy, 0x0180, 1); + OUT_RING (chan, NvNotify0); } return ret; @@ -915,8 +878,8 @@ nouveau_bo_mem_ctxdma(struct ttm_buffer_object *bo, struct nouveau_channel *chan, struct ttm_mem_reg *mem) { if (mem->mem_type == TTM_PL_TT) - return chan->gart_handle; - return chan->vram_handle; + return NvDmaTT; + return NvDmaFB; } static int @@ -972,8 +935,9 @@ nouveau_vma_getmap(struct nouveau_channel *chan, struct nouveau_bo *nvbo, struct nouveau_mem *node = mem->mm_node; int ret; - ret = nouveau_vm_get(chan->vm, mem->num_pages << PAGE_SHIFT, - node->page_shift, NV_MEM_ACCESS_RO, vma); + ret = nouveau_vm_get(nv_client(chan->cli)->vm, mem->num_pages << + PAGE_SHIFT, node->page_shift, + NV_MEM_ACCESS_RW, vma); if (ret) return ret; @@ -990,19 +954,19 @@ nouveau_bo_move_m2mf(struct ttm_buffer_object *bo, int evict, bool intr, bool no_wait_reserve, bool no_wait_gpu, struct ttm_mem_reg *new_mem) { - struct drm_nouveau_private *dev_priv = nouveau_bdev(bo->bdev); - struct nouveau_channel *chan = chan = dev_priv->channel; + struct nouveau_drm *drm = nouveau_bdev(bo->bdev); + struct nouveau_channel *chan = chan = drm->channel; struct nouveau_bo *nvbo = nouveau_bo(bo); struct ttm_mem_reg *old_mem = &bo->mem; int ret; - mutex_lock_nested(&chan->mutex, NOUVEAU_KCHANNEL_MUTEX); + mutex_lock(&chan->cli->mutex); /* create temporary vmas for the transfer and attach them to the * old nouveau_mem node, these will get cleaned up after ttm has * destroyed the ttm_mem_reg */ - if (dev_priv->card_type >= NV_50) { + if (nv_device(drm->device)->card_type >= NV_50) { struct nouveau_mem *node = old_mem->mm_node; ret = nouveau_vma_getmap(chan, nvbo, old_mem, &node->vma[0]); @@ -1014,7 +978,7 @@ nouveau_bo_move_m2mf(struct ttm_buffer_object *bo, int evict, bool intr, goto out; } - ret = dev_priv->ttm.move(chan, bo, &bo->mem, new_mem); + ret = drm->ttm.move(chan, bo, &bo->mem, new_mem); if (ret == 0) { ret = nouveau_bo_move_accel_cleanup(chan, nvbo, evict, no_wait_reserve, @@ -1022,14 +986,15 @@ nouveau_bo_move_m2mf(struct ttm_buffer_object *bo, int evict, bool intr, } out: - mutex_unlock(&chan->mutex); + mutex_unlock(&chan->cli->mutex); return ret; } void nouveau_bo_move_init(struct nouveau_channel *chan) { - struct drm_nouveau_private *dev_priv = chan->dev->dev_private; + struct nouveau_cli *cli = chan->cli; + struct nouveau_drm *drm = chan->drm; static const struct { const char *name; int engine; @@ -1054,19 +1019,26 @@ nouveau_bo_move_init(struct nouveau_channel *chan) int ret; do { + struct nouveau_object *object; u32 handle = (mthd->engine << 16) | mthd->oclass; - ret = nouveau_gpuobj_gr_new(chan, handle, mthd->oclass); + + ret = nouveau_object_new(nv_object(cli), chan->handle, handle, + mthd->oclass, NULL, 0, &object); if (ret == 0) { ret = mthd->init(chan, handle); - if (ret == 0) { - dev_priv->ttm.move = mthd->exec; - name = mthd->name; - break; + if (ret) { + nouveau_object_del(nv_object(cli), + chan->handle, handle); + continue; } + + drm->ttm.move = mthd->exec; + name = mthd->name; + break; } } while ((++mthd)->exec); - NV_INFO(chan->dev, "MM: using %s for buffer copies\n", name); + NV_INFO(drm, "MM: using %s for buffer copies\n", name); } static int @@ -1151,7 +1123,7 @@ nouveau_bo_move_ntfy(struct ttm_buffer_object *bo, struct ttm_mem_reg *new_mem) nouveau_vm_map(vma, new_mem->mm_node); } else if (new_mem && new_mem->mem_type == TTM_PL_TT && - nvbo->page_shift == nvvm_spg_shift(vma->vm)) { + nvbo->page_shift == vma->vm->vmm->spg_shift) { if (((struct nouveau_mem *)new_mem->mm_node)->sg) nouveau_vm_map_sg_table(vma, 0, new_mem-> num_pages << PAGE_SHIFT, @@ -1168,10 +1140,10 @@ nouveau_bo_move_ntfy(struct ttm_buffer_object *bo, struct ttm_mem_reg *new_mem) static int nouveau_bo_vm_bind(struct ttm_buffer_object *bo, struct ttm_mem_reg *new_mem, - struct nouveau_tile_reg **new_tile) + struct nouveau_drm_tile **new_tile) { - struct drm_nouveau_private *dev_priv = nouveau_bdev(bo->bdev); - struct drm_device *dev = dev_priv->dev; + struct nouveau_drm *drm = nouveau_bdev(bo->bdev); + struct drm_device *dev = drm->dev; struct nouveau_bo *nvbo = nouveau_bo(bo); u64 offset = new_mem->start << PAGE_SHIFT; @@ -1179,7 +1151,7 @@ nouveau_bo_vm_bind(struct ttm_buffer_object *bo, struct ttm_mem_reg *new_mem, if (new_mem->mem_type != TTM_PL_VRAM) return 0; - if (dev_priv->card_type >= NV_10) { + if (nv_device(drm->device)->card_type >= NV_10) { *new_tile = nv10_bo_set_tiling(dev, offset, new_mem->size, nvbo->tile_mode, nvbo->tile_flags); @@ -1190,11 +1162,11 @@ nouveau_bo_vm_bind(struct ttm_buffer_object *bo, struct ttm_mem_reg *new_mem, static void nouveau_bo_vm_cleanup(struct ttm_buffer_object *bo, - struct nouveau_tile_reg *new_tile, - struct nouveau_tile_reg **old_tile) + struct nouveau_drm_tile *new_tile, + struct nouveau_drm_tile **old_tile) { - struct drm_nouveau_private *dev_priv = nouveau_bdev(bo->bdev); - struct drm_device *dev = dev_priv->dev; + struct nouveau_drm *drm = nouveau_bdev(bo->bdev); + struct drm_device *dev = drm->dev; nv10_bo_put_tile_region(dev, *old_tile, bo->sync_obj); *old_tile = new_tile; @@ -1205,13 +1177,13 @@ nouveau_bo_move(struct ttm_buffer_object *bo, bool evict, bool intr, bool no_wait_reserve, bool no_wait_gpu, struct ttm_mem_reg *new_mem) { - struct drm_nouveau_private *dev_priv = nouveau_bdev(bo->bdev); + struct nouveau_drm *drm = nouveau_bdev(bo->bdev); struct nouveau_bo *nvbo = nouveau_bo(bo); struct ttm_mem_reg *old_mem = &bo->mem; - struct nouveau_tile_reg *new_tile = NULL; + struct nouveau_drm_tile *new_tile = NULL; int ret = 0; - if (dev_priv->card_type < NV_50) { + if (nv_device(drm->device)->card_type < NV_50) { ret = nouveau_bo_vm_bind(bo, new_mem, &new_tile); if (ret) return ret; @@ -1226,7 +1198,7 @@ nouveau_bo_move(struct ttm_buffer_object *bo, bool evict, bool intr, } /* CPU copy if we have no accelerated method available */ - if (!dev_priv->ttm.move) { + if (!drm->ttm.move) { ret = ttm_bo_move_memcpy(bo, evict, no_wait_reserve, no_wait_gpu, new_mem); goto out; } @@ -1246,7 +1218,7 @@ nouveau_bo_move(struct ttm_buffer_object *bo, bool evict, bool intr, ret = ttm_bo_move_memcpy(bo, evict, no_wait_reserve, no_wait_gpu, new_mem); out: - if (dev_priv->card_type < NV_50) { + if (nv_device(drm->device)->card_type < NV_50) { if (ret) nouveau_bo_vm_cleanup(bo, NULL, &new_tile); else @@ -1266,8 +1238,8 @@ static int nouveau_ttm_io_mem_reserve(struct ttm_bo_device *bdev, struct ttm_mem_reg *mem) { struct ttm_mem_type_manager *man = &bdev->man[mem->mem_type]; - struct drm_nouveau_private *dev_priv = nouveau_bdev(bdev); - struct drm_device *dev = dev_priv->dev; + struct nouveau_drm *drm = nouveau_bdev(bdev); + struct drm_device *dev = drm->dev; int ret; mem->bus.addr = NULL; @@ -1283,9 +1255,9 @@ nouveau_ttm_io_mem_reserve(struct ttm_bo_device *bdev, struct ttm_mem_reg *mem) return 0; case TTM_PL_TT: #if __OS_HAS_AGP - if (dev_priv->gart_info.type == NOUVEAU_GART_AGP) { + if (drm->agp.stat == ENABLED) { mem->bus.offset = mem->start << PAGE_SHIFT; - mem->bus.base = dev_priv->gart_info.aper_base; + mem->bus.base = drm->agp.base; mem->bus.is_iomem = true; } #endif @@ -1294,10 +1266,11 @@ nouveau_ttm_io_mem_reserve(struct ttm_bo_device *bdev, struct ttm_mem_reg *mem) mem->bus.offset = mem->start << PAGE_SHIFT; mem->bus.base = pci_resource_start(dev->pdev, 1); mem->bus.is_iomem = true; - if (dev_priv->card_type >= NV_50) { + if (nv_device(drm->device)->card_type >= NV_50) { + struct nouveau_bar *bar = nouveau_bar(drm->device); struct nouveau_mem *node = mem->mm_node; - ret = nvbar_map(dev, node, NV_MEM_ACCESS_RW, + ret = bar->umap(bar, node, NV_MEM_ACCESS_RW, &node->bar_vma); if (ret) return ret; @@ -1314,40 +1287,40 @@ nouveau_ttm_io_mem_reserve(struct ttm_bo_device *bdev, struct ttm_mem_reg *mem) static void nouveau_ttm_io_mem_free(struct ttm_bo_device *bdev, struct ttm_mem_reg *mem) { - struct drm_nouveau_private *dev_priv = nouveau_bdev(bdev); + struct nouveau_drm *drm = nouveau_bdev(bdev); + struct nouveau_bar *bar = nouveau_bar(drm->device); struct nouveau_mem *node = mem->mm_node; - if (mem->mem_type != TTM_PL_VRAM) - return; - if (!node->bar_vma.node) return; - nvbar_unmap(dev_priv->dev, &node->bar_vma); + bar->unmap(bar, &node->bar_vma); } static int nouveau_ttm_fault_reserve_notify(struct ttm_buffer_object *bo) { - struct drm_nouveau_private *dev_priv = nouveau_bdev(bo->bdev); + struct nouveau_drm *drm = nouveau_bdev(bo->bdev); struct nouveau_bo *nvbo = nouveau_bo(bo); + struct nouveau_device *device = nv_device(drm->device); + u32 mappable = pci_resource_len(device->pdev, 1) >> PAGE_SHIFT; /* as long as the bo isn't in vram, and isn't tiled, we've got * nothing to do here. */ if (bo->mem.mem_type != TTM_PL_VRAM) { - if (dev_priv->card_type < NV_50 || + if (nv_device(drm->device)->card_type < NV_50 || !nouveau_bo_tile_layout(nvbo)) return 0; } /* make sure bo is in mappable vram */ - if (bo->mem.start + bo->mem.num_pages < dev_priv->fb_mappable_pages) + if (bo->mem.start + bo->mem.num_pages < mappable) return 0; nvbo->placement.fpfn = 0; - nvbo->placement.lpfn = dev_priv->fb_mappable_pages; + nvbo->placement.lpfn = mappable; nouveau_bo_placement_set(nvbo, TTM_PL_FLAG_VRAM, 0); return nouveau_bo_validate(nvbo, false, true, false); } @@ -1356,7 +1329,7 @@ static int nouveau_ttm_tt_populate(struct ttm_tt *ttm) { struct ttm_dma_tt *ttm_dma = (void *)ttm; - struct drm_nouveau_private *dev_priv; + struct nouveau_drm *drm; struct drm_device *dev; unsigned i; int r; @@ -1373,11 +1346,11 @@ nouveau_ttm_tt_populate(struct ttm_tt *ttm) return 0; } - dev_priv = nouveau_bdev(ttm->bdev); - dev = dev_priv->dev; + drm = nouveau_bdev(ttm->bdev); + dev = drm->dev; #if __OS_HAS_AGP - if (dev_priv->gart_info.type == NOUVEAU_GART_AGP) { + if (drm->agp.stat == ENABLED) { return ttm_agp_tt_populate(ttm); } #endif @@ -1414,7 +1387,7 @@ static void nouveau_ttm_tt_unpopulate(struct ttm_tt *ttm) { struct ttm_dma_tt *ttm_dma = (void *)ttm; - struct drm_nouveau_private *dev_priv; + struct nouveau_drm *drm; struct drm_device *dev; unsigned i; bool slave = !!(ttm->page_flags & TTM_PAGE_FLAG_SG); @@ -1422,11 +1395,11 @@ nouveau_ttm_tt_unpopulate(struct ttm_tt *ttm) if (slave) return; - dev_priv = nouveau_bdev(ttm->bdev); - dev = dev_priv->dev; + drm = nouveau_bdev(ttm->bdev); + dev = drm->dev; #if __OS_HAS_AGP - if (dev_priv->gart_info.type == NOUVEAU_GART_AGP) { + if (drm->agp.stat == ENABLED) { ttm_agp_tt_unpopulate(ttm); return; } diff --git a/drivers/gpu/drm/nouveau/nouveau_bo.h b/drivers/gpu/drm/nouveau/nouveau_bo.h index a0a889cbf5ca..c42aea9fb546 100644 --- a/drivers/gpu/drm/nouveau/nouveau_bo.h +++ b/drivers/gpu/drm/nouveau/nouveau_bo.h @@ -2,13 +2,9 @@ #define __NOUVEAU_BO_H__ struct nouveau_channel; +struct nouveau_fence; struct nouveau_vma; -struct nouveau_tile_reg { - bool used; - struct nouveau_fence *fence; -}; - struct nouveau_bo { struct ttm_buffer_object bo; struct ttm_placement placement; @@ -29,7 +25,7 @@ struct nouveau_bo { u32 tile_mode; u32 tile_flags; - struct nouveau_tile_reg *tile; + struct nouveau_drm_tile *tile; struct drm_gem_object *gem; int pin_refcnt; @@ -89,4 +85,15 @@ int nouveau_bo_vma_add(struct nouveau_bo *, struct nouveau_vm *, struct nouveau_vma *); void nouveau_bo_vma_del(struct nouveau_bo *, struct nouveau_vma *); +/* TODO: submit equivalent to TTM generic API upstream? */ +static inline void __iomem * +nvbo_kmap_obj_iovirtual(struct nouveau_bo *nvbo) +{ + bool is_iomem; + void __iomem *ioptr = (void __force __iomem *)ttm_kmap_obj_virtual( + &nvbo->kmap, &is_iomem); + WARN_ON_ONCE(ioptr && !is_iomem); + return ioptr; +} + #endif diff --git a/drivers/gpu/drm/nouveau/nouveau_chan.c b/drivers/gpu/drm/nouveau/nouveau_chan.c new file mode 100644 index 000000000000..3dd5f712b98c --- /dev/null +++ b/drivers/gpu/drm/nouveau/nouveau_chan.c @@ -0,0 +1,387 @@ +/* + * 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 + +#include +#include +#include + +#include + +#include "nouveau_drm.h" +#include "nouveau_dma.h" +#include "nouveau_bo.h" +#include "nouveau_chan.h" +#include "nouveau_fence.h" +#include "nouveau_abi16.h" + +MODULE_PARM_DESC(vram_pushbuf, "Create DMA push buffers in VRAM"); +static int nouveau_vram_pushbuf; +module_param_named(vram_pushbuf, nouveau_vram_pushbuf, int, 0400); + +int +nouveau_channel_idle(struct nouveau_channel *chan) +{ + struct nouveau_drm *drm = chan->drm; + struct nouveau_fence *fence = NULL; + int ret; + + ret = nouveau_fence_new(chan, &fence); + if (!ret) { + ret = nouveau_fence_wait(fence, false, false); + nouveau_fence_unref(&fence); + } + + if (ret) + NV_ERROR(drm, "failed to idle channel 0x%08x\n", chan->handle); + return ret; +} + +void +nouveau_channel_del(struct nouveau_channel **pchan) +{ + struct nouveau_channel *chan = *pchan; + if (chan) { + struct nouveau_object *client = nv_object(chan->cli); + if (chan->fence) { + nouveau_channel_idle(chan); + nouveau_fence(chan->drm)->context_del(chan); + } + nouveau_object_del(client, NVDRM_DEVICE, chan->handle); + nouveau_object_del(client, NVDRM_DEVICE, chan->push.handle); + nouveau_bo_vma_del(chan->push.buffer, &chan->push.vma); + nouveau_bo_unmap(chan->push.buffer); + nouveau_bo_ref(NULL, &chan->push.buffer); + kfree(chan); + } + *pchan = NULL; +} + +static int +nouveau_channel_prep(struct nouveau_drm *drm, struct nouveau_cli *cli, + u32 parent, u32 handle, u32 size, + struct nouveau_channel **pchan) +{ + struct nouveau_device *device = nv_device(drm->device); + struct nouveau_instmem *imem = nouveau_instmem(device); + struct nouveau_vmmgr *vmm = nouveau_vmmgr(device); + struct nouveau_fb *pfb = nouveau_fb(device); + struct nouveau_client *client = &cli->base; + struct nv_dma_class args = {}; + struct nouveau_channel *chan; + struct nouveau_object *push; + u32 target; + int ret; + + chan = *pchan = kzalloc(sizeof(*chan), GFP_KERNEL); + if (!chan) + return -ENOMEM; + + chan->cli = cli; + chan->drm = drm; + chan->handle = handle; + + /* allocate memory for dma push buffer */ + target = TTM_PL_FLAG_TT; + if (nouveau_vram_pushbuf) + target = TTM_PL_FLAG_VRAM; + + ret = nouveau_bo_new(drm->dev, size, 0, target, 0, 0, NULL, + &chan->push.buffer); + if (ret == 0) { + ret = nouveau_bo_pin(chan->push.buffer, target); + if (ret == 0) + ret = nouveau_bo_map(chan->push.buffer); + } + + if (ret) { + nouveau_channel_del(pchan); + return ret; + } + + /* create dma object covering the *entire* memory space that the + * pushbuf lives in, this is because the GEM code requires that + * we be able to call out to other (indirect) push buffers + */ + chan->push.vma.offset = chan->push.buffer->bo.offset; + chan->push.handle = NVDRM_PUSH | (handle & 0xffff); + + if (device->card_type >= NV_50) { + ret = nouveau_bo_vma_add(chan->push.buffer, client->vm, + &chan->push.vma); + if (ret) { + nouveau_channel_del(pchan); + return ret; + } + + args.flags = NV_DMA_TARGET_VM | NV_DMA_ACCESS_VM; + args.start = 0; + args.limit = client->vm->vmm->limit - 1; + } else + if (chan->push.buffer->bo.mem.mem_type == TTM_PL_VRAM) { + u64 limit = pfb->ram.size - imem->reserved - 1; + if (device->card_type == NV_04) { + /* nv04 vram pushbuf hack, retarget to its location in + * the framebuffer bar rather than direct vram access.. + * nfi why this exists, it came from the -nv ddx. + */ + args.flags = NV_DMA_TARGET_PCI | NV_DMA_ACCESS_RDWR; + args.start = pci_resource_start(device->pdev, 1); + args.limit = args.start + limit; + } else { + args.flags = NV_DMA_TARGET_VRAM | NV_DMA_ACCESS_RDWR; + args.start = 0; + args.limit = limit; + } + } else { + if (chan->drm->agp.stat == ENABLED) { + args.flags = NV_DMA_TARGET_AGP | NV_DMA_ACCESS_RDWR; + args.start = chan->drm->agp.base; + args.limit = chan->drm->agp.base + + chan->drm->agp.size - 1; + } else { + args.flags = NV_DMA_TARGET_VM | NV_DMA_ACCESS_RDWR; + args.start = 0; + args.limit = vmm->limit - 1; + } + } + + ret = nouveau_object_new(nv_object(chan->cli), parent, + chan->push.handle, 0x0002, + &args, sizeof(args), &push); + if (ret) { + nouveau_channel_del(pchan); + return ret; + } + + return 0; +} + +int +nouveau_channel_ind(struct nouveau_drm *drm, struct nouveau_cli *cli, + u32 parent, u32 handle, struct nouveau_channel **pchan) +{ + static const u16 oclasses[] = { 0xa06f, 0x906f, 0x826f, 0x506f, 0 }; + const u16 *oclass = oclasses; + struct nv_channel_ind_class args; + struct nouveau_channel *chan; + int ret; + + /* allocate dma push buffer */ + ret = nouveau_channel_prep(drm, cli, parent, handle, 0x12000, &chan); + *pchan = chan; + if (ret) + return ret; + + /* create channel object */ + args.pushbuf = chan->push.handle; + args.ioffset = 0x10000 + chan->push.vma.offset; + args.ilength = 0x02000; + + do { + ret = nouveau_object_new(nv_object(cli), parent, handle, + *oclass++, &args, sizeof(args), + &chan->object); + if (ret == 0) + return ret; + } while (*oclass); + + nouveau_channel_del(pchan); + return ret; +} + +static int +nouveau_channel_dma(struct nouveau_drm *drm, struct nouveau_cli *cli, + u32 parent, u32 handle, struct nouveau_channel **pchan) +{ + static const u16 oclasses[] = { 0x006e, 0 }; + const u16 *oclass = oclasses; + struct nv_channel_dma_class args; + struct nouveau_channel *chan; + int ret; + + /* allocate dma push buffer */ + ret = nouveau_channel_prep(drm, cli, parent, handle, 0x10000, &chan); + *pchan = chan; + if (ret) + return ret; + + /* create channel object */ + args.pushbuf = chan->push.handle; + args.offset = chan->push.vma.offset; + + do { + ret = nouveau_object_new(nv_object(cli), parent, handle, + *oclass++, &args, sizeof(args), + &chan->object); + if (ret == 0) + return ret; + } while (ret && *oclass); + + nouveau_channel_del(pchan); + return ret; +} + +static int +nouveau_channel_init(struct nouveau_channel *chan, u32 vram, u32 gart) +{ + struct nouveau_client *client = nv_client(chan->cli); + struct nouveau_device *device = nv_device(chan->drm->device); + struct nouveau_instmem *imem = nouveau_instmem(device); + struct nouveau_vmmgr *vmm = nouveau_vmmgr(device); + struct nouveau_fb *pfb = nouveau_fb(device); + struct nouveau_software_chan *swch; + struct nouveau_object *object; + struct nv_dma_class args; + int ret, i; + + chan->vram = vram; + chan->gart = gart; + + /* allocate dma objects to cover all allowed vram, and gart */ + if (device->card_type < NV_C0) { + if (device->card_type >= NV_50) { + args.flags = NV_DMA_TARGET_VM | NV_DMA_ACCESS_VM; + args.start = 0; + args.limit = client->vm->vmm->limit - 1; + } else { + args.flags = NV_DMA_TARGET_VRAM | NV_DMA_ACCESS_RDWR; + args.start = 0; + args.limit = pfb->ram.size - imem->reserved - 1; + } + + ret = nouveau_object_new(nv_object(client), chan->handle, vram, + 0x003d, &args, sizeof(args), &object); + if (ret) + return ret; + + if (device->card_type >= NV_50) { + args.flags = NV_DMA_TARGET_VM | NV_DMA_ACCESS_VM; + args.start = 0; + args.limit = client->vm->vmm->limit - 1; + } else + if (chan->drm->agp.stat == ENABLED) { + args.flags = NV_DMA_TARGET_AGP | NV_DMA_ACCESS_RDWR; + args.start = chan->drm->agp.base; + args.limit = chan->drm->agp.base + + chan->drm->agp.size - 1; + } else { + args.flags = NV_DMA_TARGET_VM | NV_DMA_ACCESS_RDWR; + args.start = 0; + args.limit = vmm->limit - 1; + } + + ret = nouveau_object_new(nv_object(client), chan->handle, gart, + 0x003d, &args, sizeof(args), &object); + if (ret) + return ret; + } + + /* initialise dma tracking parameters */ + switch (nv_hclass(chan->object) & 0xffff) { + case 0x006e: + chan->user_put = 0x40; + chan->user_get = 0x44; + chan->dma.max = (0x10000 / 4) - 2; + break; + default: + chan->user_put = 0x40; + chan->user_get = 0x44; + chan->user_get_hi = 0x60; + chan->dma.ib_base = 0x10000 / 4; + chan->dma.ib_max = (0x02000 / 8) - 1; + chan->dma.ib_put = 0; + chan->dma.ib_free = chan->dma.ib_max - chan->dma.ib_put; + chan->dma.max = chan->dma.ib_base; + break; + } + + chan->dma.put = 0; + chan->dma.cur = chan->dma.put; + chan->dma.free = chan->dma.max - chan->dma.cur; + + ret = RING_SPACE(chan, NOUVEAU_DMA_SKIPS); + if (ret) + return ret; + + for (i = 0; i < NOUVEAU_DMA_SKIPS; i++) + OUT_RING(chan, 0x00000000); + + /* allocate software object class (used for fences on <= nv05, and + * to signal flip completion), bind it to a subchannel. + */ + ret = nouveau_object_new(nv_object(client), chan->handle, + NvSw, nouveau_abi16_swclass(chan->drm), + NULL, 0, &object); + if (ret) + return ret; + + swch = (void *)object->parent; + swch->flip = nouveau_flip_complete; + swch->flip_data = chan; + + if (device->card_type < NV_C0) { + ret = RING_SPACE(chan, 2); + if (ret) + return ret; + + BEGIN_NV04(chan, NvSubSw, 0x0000, 1); + OUT_RING (chan, NvSw); + FIRE_RING (chan); + } + + /* initialise synchronisation */ + return nouveau_fence(chan->drm)->context_new(chan); +} + +int +nouveau_channel_new(struct nouveau_drm *drm, struct nouveau_cli *cli, + u32 parent, u32 handle, u32 vram, u32 gart, + struct nouveau_channel **pchan) +{ + int ret; + + ret = nouveau_channel_ind(drm, cli, parent, handle, pchan); + if (ret) { + NV_DEBUG(drm, "ib channel create, %d\n", ret); + ret = nouveau_channel_dma(drm, cli, parent, handle, pchan); + if (ret) { + NV_DEBUG(drm, "dma channel create, %d\n", ret); + return ret; + } + } + + ret = nouveau_channel_init(*pchan, vram, gart); + if (ret) { + NV_ERROR(drm, "channel failed to initialise, %d\n", ret); + nouveau_channel_del(pchan); + return ret; + } + + return 0; +} diff --git a/drivers/gpu/drm/nouveau/nouveau_chan.h b/drivers/gpu/drm/nouveau/nouveau_chan.h new file mode 100644 index 000000000000..0fa94244bed1 --- /dev/null +++ b/drivers/gpu/drm/nouveau/nouveau_chan.h @@ -0,0 +1,47 @@ +#ifndef __NOUVEAU_CHAN_H__ +#define __NOUVEAU_CHAN_H__ + +struct nouveau_cli; + +struct nouveau_channel { + struct nouveau_cli *cli; + struct nouveau_drm *drm; + + u32 handle; + u32 vram; + u32 gart; + + struct { + struct nouveau_bo *buffer; + struct nouveau_vma vma; + u32 handle; + } push; + + /* TODO: this will be reworked in the near future */ + bool accel_done; + void *fence; + struct { + int max; + int free; + int cur; + int put; + int ib_base; + int ib_max; + int ib_free; + int ib_put; + } dma; + u32 user_get_hi; + u32 user_get; + u32 user_put; + + struct nouveau_object *object; +}; + + +int nouveau_channel_new(struct nouveau_drm *, struct nouveau_cli *, + u32 parent, u32 handle, u32 vram, u32 gart, + struct nouveau_channel **); +void nouveau_channel_del(struct nouveau_channel **); +int nouveau_channel_idle(struct nouveau_channel *); + +#endif diff --git a/drivers/gpu/drm/nouveau/nouveau_channel.c b/drivers/gpu/drm/nouveau/nouveau_channel.c deleted file mode 100644 index 285fde8ed3e3..000000000000 --- a/drivers/gpu/drm/nouveau/nouveau_channel.c +++ /dev/null @@ -1,408 +0,0 @@ -/* - * Copyright 2005-2006 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 - * 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 "drmP.h" -#include "drm.h" -#include "nouveau_drv.h" -#include -#include "nouveau_dma.h" -#include -#include -#include "nouveau_fence.h" -#include "nouveau_software.h" - -MODULE_PARM_DESC(vram_pushbuf, "Force DMA push buffers to be in VRAM"); -int nouveau_vram_pushbuf; -module_param_named(vram_pushbuf, nouveau_vram_pushbuf, int, 0400); - -static int -nouveau_channel_pushbuf_init(struct nouveau_channel *chan) -{ - u32 mem = nouveau_vram_pushbuf ? TTM_PL_FLAG_VRAM : TTM_PL_FLAG_TT; - struct drm_device *dev = chan->dev; - struct drm_nouveau_private *dev_priv = dev->dev_private; - int ret; - - /* allocate buffer object */ - ret = nouveau_bo_new(dev, 65536, 0, mem, 0, 0, NULL, &chan->pushbuf_bo); - if (ret) - goto out; - - ret = nouveau_bo_pin(chan->pushbuf_bo, mem); - if (ret) - goto out; - - ret = nouveau_bo_map(chan->pushbuf_bo); - if (ret) - goto out; - - /* create DMA object covering the entire memtype where the push - * buffer resides, userspace can submit its own push buffers from - * anywhere within the same memtype. - */ - chan->pushbuf_base = chan->pushbuf_bo->bo.offset; - if (dev_priv->card_type >= NV_50) { - ret = nouveau_bo_vma_add(chan->pushbuf_bo, chan->vm, - &chan->pushbuf_vma); - if (ret) - goto out; - - if (dev_priv->card_type < NV_C0) { - ret = nouveau_gpuobj_dma_new(chan, - NV_CLASS_DMA_IN_MEMORY, 0, - (1ULL << 40), - NV_MEM_ACCESS_RO, - NV_MEM_TARGET_VM, - &chan->pushbuf); - } - chan->pushbuf_base = chan->pushbuf_vma.offset; - } else - if (chan->pushbuf_bo->bo.mem.mem_type == TTM_PL_TT) { - ret = nouveau_gpuobj_dma_new(chan, NV_CLASS_DMA_IN_MEMORY, 0, - dev_priv->gart_info.aper_size, - NV_MEM_ACCESS_RO, - NV_MEM_TARGET_GART, - &chan->pushbuf); - } else - if (dev_priv->card_type != NV_04) { - ret = nouveau_gpuobj_dma_new(chan, NV_CLASS_DMA_IN_MEMORY, 0, - dev_priv->fb_available_size, - NV_MEM_ACCESS_RO, - NV_MEM_TARGET_VRAM, - &chan->pushbuf); - } else { - /* NV04 cmdbuf hack, from original ddx.. not sure of it's - * exact reason for existing :) PCI access to cmdbuf in - * VRAM. - */ - ret = nouveau_gpuobj_dma_new(chan, NV_CLASS_DMA_IN_MEMORY, - pci_resource_start(dev->pdev, 1), - dev_priv->fb_available_size, - NV_MEM_ACCESS_RO, - NV_MEM_TARGET_PCI, - &chan->pushbuf); - } - -out: - if (ret) { - NV_ERROR(dev, "error initialising pushbuf: %d\n", ret); - nouveau_bo_vma_del(chan->pushbuf_bo, &chan->pushbuf_vma); - nouveau_gpuobj_ref(NULL, &chan->pushbuf); - if (chan->pushbuf_bo) { - nouveau_bo_unmap(chan->pushbuf_bo); - nouveau_bo_ref(NULL, &chan->pushbuf_bo); - } - } - - return 0; -} - -/* allocates and initializes a fifo for user space consumption */ -int -nouveau_channel_alloc(struct drm_device *dev, struct nouveau_channel **chan_ret, - struct drm_file *file_priv, - uint32_t vram_handle, uint32_t gart_handle) -{ - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_fifo_priv *pfifo = nv_engine(dev, NVOBJ_ENGINE_FIFO); - struct nouveau_fence_priv *fence = dev_priv->fence.func; - struct nouveau_fpriv *fpriv = nouveau_fpriv(file_priv); - struct nouveau_channel *chan; - unsigned long flags; - int ret, i; - - /* allocate and lock channel structure */ - chan = kzalloc(sizeof(*chan), GFP_KERNEL); - if (!chan) - return -ENOMEM; - chan->dev = dev; - chan->file_priv = file_priv; - chan->vram_handle = vram_handle; - chan->gart_handle = gart_handle; - - kref_init(&chan->ref); - atomic_set(&chan->users, 1); - mutex_init(&chan->mutex); - mutex_lock(&chan->mutex); - - /* allocate hw channel id */ - spin_lock_irqsave(&dev_priv->channels.lock, flags); - for (chan->id = 0; chan->id < pfifo->channels; chan->id++) { - if ( dev_priv->card_type == NV_50 && chan->id == 0) - continue; - - if (!dev_priv->channels.ptr[chan->id]) { - nouveau_channel_ref(chan, &dev_priv->channels.ptr[chan->id]); - break; - } - } - spin_unlock_irqrestore(&dev_priv->channels.lock, flags); - - if (chan->id == pfifo->channels) { - mutex_unlock(&chan->mutex); - kfree(chan); - return -ENODEV; - } - - NV_DEBUG(dev, "initialising channel %d\n", chan->id); - - /* setup channel's memory and vm */ - ret = nouveau_gpuobj_channel_init(chan, vram_handle, gart_handle); - if (ret) { - NV_ERROR(dev, "gpuobj %d\n", ret); - nouveau_channel_put(&chan); - return ret; - } - - /* Allocate space for per-channel fixed notifier memory */ - ret = nouveau_notifier_init_channel(chan); - if (ret) { - NV_ERROR(dev, "ntfy %d\n", ret); - nouveau_channel_put(&chan); - return ret; - } - - /* Allocate DMA push buffer */ - ret = nouveau_channel_pushbuf_init(chan); - if (ret) { - NV_ERROR(dev, "pushbuf %d\n", ret); - nouveau_channel_put(&chan); - return ret; - } - - nouveau_dma_init(chan); - chan->user_put = 0x40; - chan->user_get = 0x44; - if (dev_priv->card_type >= NV_50) - chan->user_get_hi = 0x60; - - /* create fifo context */ - ret = pfifo->base.context_new(chan, NVOBJ_ENGINE_FIFO); - if (ret) { - nouveau_channel_put(&chan); - return ret; - } - - /* Insert NOPs for NOUVEAU_DMA_SKIPS */ - ret = RING_SPACE(chan, NOUVEAU_DMA_SKIPS); - if (ret) { - nouveau_channel_put(&chan); - return ret; - } - - for (i = 0; i < NOUVEAU_DMA_SKIPS; i++) - OUT_RING (chan, 0x00000000); - - ret = nouveau_gpuobj_gr_new(chan, NvSw, nouveau_software_class(dev)); - if (ret) { - nouveau_channel_put(&chan); - return ret; - } - - if (dev_priv->card_type < NV_C0) { - ret = RING_SPACE(chan, 2); - if (ret) { - nouveau_channel_put(&chan); - return ret; - } - - BEGIN_NV04(chan, NvSubSw, NV01_SUBCHAN_OBJECT, 1); - OUT_RING (chan, NvSw); - FIRE_RING (chan); - } - - FIRE_RING(chan); - - ret = fence->context_new(chan); - if (ret) { - nouveau_channel_put(&chan); - return ret; - } - - nouveau_debugfs_channel_init(chan); - - NV_DEBUG(dev, "channel %d initialised\n", chan->id); - if (fpriv) { - spin_lock(&fpriv->lock); - list_add(&chan->list, &fpriv->channels); - spin_unlock(&fpriv->lock); - } - *chan_ret = chan; - return 0; -} - -struct nouveau_channel * -nouveau_channel_get_unlocked(struct nouveau_channel *ref) -{ - struct nouveau_channel *chan = NULL; - - if (likely(ref && atomic_inc_not_zero(&ref->users))) - nouveau_channel_ref(ref, &chan); - - return chan; -} - -struct nouveau_channel * -nouveau_channel_get(struct drm_file *file_priv, int id) -{ - struct nouveau_fpriv *fpriv = nouveau_fpriv(file_priv); - struct nouveau_channel *chan; - - spin_lock(&fpriv->lock); - list_for_each_entry(chan, &fpriv->channels, list) { - if (chan->id == id) { - chan = nouveau_channel_get_unlocked(chan); - spin_unlock(&fpriv->lock); - mutex_lock(&chan->mutex); - return chan; - } - } - spin_unlock(&fpriv->lock); - - return ERR_PTR(-EINVAL); -} - -void -nouveau_channel_put_unlocked(struct nouveau_channel **pchan) -{ - struct nouveau_channel *chan = *pchan; - struct drm_device *dev = chan->dev; - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_fence_priv *fence = dev_priv->fence.func; - unsigned long flags; - int i; - - /* decrement the refcount, and we're done if there's still refs */ - if (likely(!atomic_dec_and_test(&chan->users))) { - nouveau_channel_ref(NULL, pchan); - return; - } - - /* no one wants the channel anymore */ - NV_DEBUG(dev, "freeing channel %d\n", chan->id); - nouveau_debugfs_channel_fini(chan); - - /* give it chance to idle */ - nouveau_channel_idle(chan); - - /* destroy the engine specific contexts */ - for (i = NVOBJ_ENGINE_NR - 1; i >= 0; i--) { - if (chan->engctx[i]) - dev_priv->eng[i]->context_del(chan, i); - } - - if (chan->fence) - fence->context_del(chan); - - /* aside from its resources, the channel should now be dead, - * remove it from the channel list - */ - spin_lock_irqsave(&dev_priv->channels.lock, flags); - nouveau_channel_ref(NULL, &dev_priv->channels.ptr[chan->id]); - spin_unlock_irqrestore(&dev_priv->channels.lock, flags); - - /* destroy any resources the channel owned */ - nouveau_gpuobj_ref(NULL, &chan->pushbuf); - if (chan->pushbuf_bo) { - nouveau_bo_vma_del(chan->pushbuf_bo, &chan->pushbuf_vma); - nouveau_bo_unmap(chan->pushbuf_bo); - nouveau_bo_unpin(chan->pushbuf_bo); - nouveau_bo_ref(NULL, &chan->pushbuf_bo); - } - nouveau_ramht_ref(NULL, &chan->ramht, chan); - nouveau_notifier_takedown_channel(chan); - nouveau_gpuobj_channel_takedown(chan); - - nouveau_channel_ref(NULL, pchan); -} - -void -nouveau_channel_put(struct nouveau_channel **pchan) -{ - mutex_unlock(&(*pchan)->mutex); - nouveau_channel_put_unlocked(pchan); -} - -static void -nouveau_channel_del(struct kref *ref) -{ - struct nouveau_channel *chan = - container_of(ref, struct nouveau_channel, ref); - - kfree(chan); -} - -void -nouveau_channel_ref(struct nouveau_channel *chan, - struct nouveau_channel **pchan) -{ - if (chan) - kref_get(&chan->ref); - - if (*pchan) - kref_put(&(*pchan)->ref, nouveau_channel_del); - - *pchan = chan; -} - -int -nouveau_channel_idle(struct nouveau_channel *chan) -{ - struct drm_device *dev = chan->dev; - struct nouveau_fence *fence = NULL; - int ret; - - ret = nouveau_fence_new(chan, &fence); - if (!ret) { - ret = nouveau_fence_wait(fence, false, false); - nouveau_fence_unref(&fence); - } - - if (ret) - NV_ERROR(dev, "Failed to idle channel %d.\n", chan->id); - return ret; -} - -/* cleans up all the fifos from file_priv */ -void -nouveau_channel_cleanup(struct drm_device *dev, struct drm_file *file_priv) -{ - struct nouveau_fifo_priv *pfifo = nv_engine(dev, NVOBJ_ENGINE_FIFO); - struct nouveau_channel *chan; - int i; - - if (!pfifo) - return; - - NV_DEBUG(dev, "clearing FIFO enables from file_priv\n"); - for (i = 0; i < pfifo->channels; i++) { - chan = nouveau_channel_get(file_priv, i); - if (IS_ERR(chan)) - continue; - - list_del(&chan->list); - atomic_dec(&chan->users); - nouveau_channel_put(&chan); - } -} diff --git a/drivers/gpu/drm/nouveau/nouveau_compat.c b/drivers/gpu/drm/nouveau/nouveau_compat.c index 0403f2b94fa6..3db23496dff6 100644 --- a/drivers/gpu/drm/nouveau/nouveau_compat.c +++ b/drivers/gpu/drm/nouveau/nouveau_compat.c @@ -1,4 +1,5 @@ #include "nouveau_drm.h" +#include "nouveau_chan.h" #include "nouveau_compat.h" #include @@ -14,8 +15,6 @@ #include #include -void *nouveau_newpriv(struct drm_device *); - int nvdrm_gart_init(struct drm_device *dev, u64 *base, u64 *size) { @@ -583,3 +582,28 @@ 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 index d691b2535c72..9f42d1d0f868 100644 --- a/drivers/gpu/drm/nouveau/nouveau_compat.h +++ b/drivers/gpu/drm/nouveau/nouveau_compat.h @@ -124,4 +124,18 @@ 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_debugfs.c b/drivers/gpu/drm/nouveau/nouveau_debugfs.c deleted file mode 100644 index 6564b547973e..000000000000 --- a/drivers/gpu/drm/nouveau/nouveau_debugfs.c +++ /dev/null @@ -1,195 +0,0 @@ -/* - * Copyright (C) 2009 Red Hat - * - * 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. - * - */ - -/* - * Authors: - * Ben Skeggs - */ - -#include - -#include "drmP.h" -#include "nouveau_drv.h" - -#include - -static int -nouveau_debugfs_channel_info(struct seq_file *m, void *data) -{ - struct drm_info_node *node = (struct drm_info_node *) m->private; - struct nouveau_channel *chan = node->info_ent->data; - - seq_printf(m, "channel id : %d\n", chan->id); - - seq_printf(m, "cpu fifo state:\n"); - seq_printf(m, " base: 0x%10llx\n", chan->pushbuf_base); - seq_printf(m, " max: 0x%08x\n", chan->dma.max << 2); - seq_printf(m, " cur: 0x%08x\n", chan->dma.cur << 2); - seq_printf(m, " put: 0x%08x\n", chan->dma.put << 2); - seq_printf(m, " free: 0x%08x\n", chan->dma.free << 2); - if (chan->dma.ib_max) { - seq_printf(m, " ib max: 0x%08x\n", chan->dma.ib_max); - seq_printf(m, " ib put: 0x%08x\n", chan->dma.ib_put); - seq_printf(m, " ib free: 0x%08x\n", chan->dma.ib_free); - } - - seq_printf(m, "gpu fifo state:\n"); - seq_printf(m, " get: 0x%08x\n", - nvchan_rd32(chan, chan->user_get)); - seq_printf(m, " put: 0x%08x\n", - nvchan_rd32(chan, chan->user_put)); - if (chan->dma.ib_max) { - seq_printf(m, " ib get: 0x%08x\n", - nvchan_rd32(chan, 0x88)); - seq_printf(m, " ib put: 0x%08x\n", - nvchan_rd32(chan, 0x8c)); - } - - return 0; -} - -int -nouveau_debugfs_channel_init(struct nouveau_channel *chan) -{ - struct drm_nouveau_private *dev_priv = chan->dev->dev_private; - struct drm_minor *minor = chan->dev->primary; - int ret; - - if (!dev_priv->debugfs.channel_root) { - dev_priv->debugfs.channel_root = - debugfs_create_dir("channel", minor->debugfs_root); - if (!dev_priv->debugfs.channel_root) - return -ENOENT; - } - - snprintf(chan->debugfs.name, 32, "%d", chan->id); - chan->debugfs.info.name = chan->debugfs.name; - chan->debugfs.info.show = nouveau_debugfs_channel_info; - chan->debugfs.info.driver_features = 0; - chan->debugfs.info.data = chan; - - ret = drm_debugfs_create_files(&chan->debugfs.info, 1, - dev_priv->debugfs.channel_root, - chan->dev->primary); - if (ret == 0) - chan->debugfs.active = true; - return ret; -} - -void -nouveau_debugfs_channel_fini(struct nouveau_channel *chan) -{ - struct drm_nouveau_private *dev_priv = chan->dev->dev_private; - - if (!chan->debugfs.active) - return; - - drm_debugfs_remove_files(&chan->debugfs.info, 1, chan->dev->primary); - chan->debugfs.active = false; - - if (chan == dev_priv->channel) { - debugfs_remove(dev_priv->debugfs.channel_root); - dev_priv->debugfs.channel_root = NULL; - } -} - -static int -nouveau_debugfs_chipset_info(struct seq_file *m, void *data) -{ - struct drm_info_node *node = (struct drm_info_node *) m->private; - struct drm_minor *minor = node->minor; - struct drm_device *dev = minor->dev; - struct drm_nouveau_private *dev_priv = dev->dev_private; - uint32_t ppci_0; - - ppci_0 = nv_rd32(dev, dev_priv->chipset >= 0x40 ? 0x88000 : 0x1800); - - seq_printf(m, "PMC_BOOT_0: 0x%08x\n", nv_rd32(dev, NV03_PMC_BOOT_0)); - seq_printf(m, "PCI ID : 0x%04x:0x%04x\n", - ppci_0 & 0xffff, ppci_0 >> 16); - return 0; -} - -static int -nouveau_debugfs_memory_info(struct seq_file *m, void *data) -{ - struct drm_info_node *node = (struct drm_info_node *) m->private; - struct drm_minor *minor = node->minor; - - seq_printf(m, "VRAM total: %dKiB\n", (int)(nvfb_vram_size(minor->dev) >> 10)); - return 0; -} - -static int -nouveau_debugfs_vbios_image(struct seq_file *m, void *data) -{ - struct drm_info_node *node = (struct drm_info_node *) m->private; - struct drm_nouveau_private *dev_priv = node->minor->dev->dev_private; - int i; - - for (i = 0; i < dev_priv->vbios.length; i++) - seq_printf(m, "%c", dev_priv->vbios.data[i]); - return 0; -} - -static int -nouveau_debugfs_evict_vram(struct seq_file *m, void *data) -{ - struct drm_info_node *node = (struct drm_info_node *) m->private; - struct drm_nouveau_private *dev_priv = node->minor->dev->dev_private; - int ret; - - ret = ttm_bo_evict_mm(&dev_priv->ttm.bdev, TTM_PL_VRAM); - if (ret) - seq_printf(m, "failed: %d", ret); - else - seq_printf(m, "succeeded\n"); - return 0; -} - -static struct drm_info_list nouveau_debugfs_list[] = { - { "evict_vram", nouveau_debugfs_evict_vram, 0, NULL }, - { "chipset", nouveau_debugfs_chipset_info, 0, NULL }, - { "memory", nouveau_debugfs_memory_info, 0, NULL }, - { "vbios.rom", nouveau_debugfs_vbios_image, 0, NULL }, - { "ttm_page_pool", ttm_page_alloc_debugfs, 0, NULL }, - { "ttm_dma_page_pool", ttm_dma_page_alloc_debugfs, 0, NULL }, -}; -#define NOUVEAU_DEBUGFS_ENTRIES ARRAY_SIZE(nouveau_debugfs_list) - -int -nouveau_debugfs_init(struct drm_minor *minor) -{ - drm_debugfs_create_files(nouveau_debugfs_list, NOUVEAU_DEBUGFS_ENTRIES, - minor->debugfs_root, minor); - return 0; -} - -void -nouveau_debugfs_takedown(struct drm_minor *minor) -{ - drm_debugfs_remove_files(nouveau_debugfs_list, NOUVEAU_DEBUGFS_ENTRIES, - minor); -} diff --git a/drivers/gpu/drm/nouveau/nouveau_display.c b/drivers/gpu/drm/nouveau/nouveau_display.c index e0a56b277884..a60a9f51e890 100644 --- a/drivers/gpu/drm/nouveau/nouveau_display.c +++ b/drivers/gpu/drm/nouveau/nouveau_display.c @@ -33,10 +33,10 @@ #include "nouveau_crtc.h" #include "nouveau_dma.h" #include "nouveau_connector.h" -#include "nouveau_software.h" -#include "nouveau_fence.h" #include "nv50_display.h" +#include "nouveau_fence.h" + #include static void @@ -260,6 +260,24 @@ nouveau_display_fini(struct drm_device *dev) disp->fini(dev); } +static void +nouveau_display_vblank_notify(void *data, int crtc) +{ + drm_handle_vblank(data, crtc); +} + +static void +nouveau_display_vblank_get(void *data, int crtc) +{ + drm_vblank_get(data, crtc); +} + +static void +nouveau_display_vblank_put(void *data, int crtc) +{ + drm_vblank_put(data, crtc); +} + int nouveau_display_create(struct drm_device *dev) { @@ -365,6 +383,10 @@ nouveau_vblank_enable(struct drm_device *dev, int crtc) { struct drm_nouveau_private *dev_priv = dev->dev_private; + if (dev_priv->card_type >= NV_D0) + nv_mask(dev, 0x6100c0 + (crtc * 0x800), 1, 1); + else + if (dev_priv->card_type >= NV_50) nv_mask(dev, NV50_PDISPLAY_INTR_EN_1, 0, NV50_PDISPLAY_INTR_EN_1_VBLANK_CRTC_(crtc)); @@ -380,6 +402,9 @@ nouveau_vblank_disable(struct drm_device *dev, int crtc) { struct drm_nouveau_private *dev_priv = dev->dev_private; + if (dev_priv->card_type >= NV_D0) + nv_mask(dev, 0x6100c0 + (crtc * 0x800), 1, 0); + else if (dev_priv->card_type >= NV_50) nv_mask(dev, NV50_PDISPLAY_INTR_EN_1, NV50_PDISPLAY_INTR_EN_1_VBLANK_CRTC_(crtc), 0); @@ -436,8 +461,8 @@ nouveau_page_flip_emit(struct nouveau_channel *chan, struct nouveau_fence **pfence) { struct nouveau_fence_chan *fctx = chan->fence; - struct drm_nouveau_private *dev_priv = chan->dev->dev_private; - struct drm_device *dev = chan->dev; + struct drm_device *dev = nouveau_drv(chan->drm); + struct drm_nouveau_private *dev_priv = dev->dev_private; unsigned long flags; int ret; @@ -492,7 +517,7 @@ nouveau_crtc_page_flip(struct drm_crtc *crtc, struct drm_framebuffer *fb, struct nouveau_fence *fence; int ret; - if (!dev_priv->channel) + if (!nvdrm_channel(dev)) return -ENODEV; s = kzalloc(sizeof(*s), GFP_KERNEL); @@ -513,10 +538,10 @@ nouveau_crtc_page_flip(struct drm_crtc *crtc, struct drm_framebuffer *fb, /* Choose the channel the flip will be handled in */ fence = new_bo->bo.sync_obj; if (fence) - chan = nouveau_channel_get_unlocked(fence->channel); + chan = fence->channel; if (!chan) - chan = nouveau_channel_get_unlocked(dev_priv->channel); - mutex_lock(&chan->mutex); + chan = nvdrm_channel(dev); + mutex_lock(nvchan_mutex(chan)); /* Emit a page flip */ if (dev_priv->card_type >= NV_50) { @@ -525,13 +550,13 @@ nouveau_crtc_page_flip(struct drm_crtc *crtc, struct drm_framebuffer *fb, else ret = nv50_display_flip_next(crtc, fb, chan); if (ret) { - nouveau_channel_put(&chan); + mutex_unlock(nvchan_mutex(chan)); goto fail_unreserve; } } ret = nouveau_page_flip_emit(chan, old_bo, new_bo, s, &fence); - nouveau_channel_put(&chan); + mutex_unlock(nvchan_mutex(chan)); if (ret) goto fail_unreserve; @@ -554,14 +579,14 @@ 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 = chan->dev; + struct drm_device *dev = nouveau_drv(chan->drm); 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 in channel %d.\n", chan->id); + NV_ERROR(dev, "unexpected pageflip\n"); spin_unlock_irqrestore(&dev->event_lock, flags); return -EINVAL; } @@ -592,7 +617,7 @@ int nouveau_flip_complete(void *data) { struct nouveau_channel *chan = data; - struct drm_device *dev = chan->dev; + struct drm_device *dev = nouveau_drv(chan->drm); struct drm_nouveau_private *dev_priv = dev->dev_private; struct nouveau_page_flip_state state; diff --git a/drivers/gpu/drm/nouveau/nouveau_dma.c b/drivers/gpu/drm/nouveau/nouveau_dma.c index efd082323405..40f91e1e5842 100644 --- a/drivers/gpu/drm/nouveau/nouveau_dma.c +++ b/drivers/gpu/drm/nouveau/nouveau_dma.c @@ -24,41 +24,16 @@ * */ -#include "drmP.h" -#include "drm.h" -#include "nouveau_drv.h" -#include "nouveau_dma.h" -#include - -void -nouveau_dma_init(struct nouveau_channel *chan) -{ - struct drm_nouveau_private *dev_priv = chan->dev->dev_private; - struct nouveau_bo *pushbuf = chan->pushbuf_bo; - - if (dev_priv->card_type >= NV_50) { - const int ib_size = pushbuf->bo.mem.size / 2; - - chan->dma.ib_base = (pushbuf->bo.mem.size - ib_size) >> 2; - chan->dma.ib_max = (ib_size / 8) - 1; - chan->dma.ib_put = 0; - chan->dma.ib_free = chan->dma.ib_max - chan->dma.ib_put; +#include - chan->dma.max = (pushbuf->bo.mem.size - ib_size) >> 2; - } else { - chan->dma.max = (pushbuf->bo.mem.size >> 2) - 2; - } - - chan->dma.put = 0; - chan->dma.cur = chan->dma.put; - chan->dma.free = chan->dma.max - chan->dma.cur; -} +#include "nouveau_drm.h" +#include "nouveau_dma.h" void OUT_RINGp(struct nouveau_channel *chan, const void *data, unsigned nr_dwords) { bool is_iomem; - u32 *mem = ttm_kmap_obj_virtual(&chan->pushbuf_bo->kmap, &is_iomem); + u32 *mem = ttm_kmap_obj_virtual(&chan->push.buffer->kmap, &is_iomem); mem = &mem[chan->dma.cur]; if (is_iomem) memcpy_toio((void __force __iomem *)mem, data, nr_dwords * 4); @@ -79,9 +54,9 @@ READ_GET(struct nouveau_channel *chan, uint64_t *prev_get, int *timeout) { uint64_t val; - val = nvchan_rd32(chan, chan->user_get); + val = nv_ro32(chan->object, chan->user_get); if (chan->user_get_hi) - val |= (uint64_t)nvchan_rd32(chan, chan->user_get_hi) << 32; + val |= (uint64_t)nv_ro32(chan->object, chan->user_get_hi) << 32; /* reset counter as long as GET is still advancing, this is * to avoid misdetecting a GPU lockup if the GPU happens to @@ -93,32 +68,33 @@ READ_GET(struct nouveau_channel *chan, uint64_t *prev_get, int *timeout) } if ((++*timeout & 0xff) == 0) { - DRM_UDELAY(1); + udelay(1); if (*timeout > 100000) return -EBUSY; } - if (val < chan->pushbuf_base || - val > chan->pushbuf_base + (chan->dma.max << 2)) + if (val < chan->push.vma.offset || + val > chan->push.vma.offset + (chan->dma.max << 2)) return -EINVAL; - return (val - chan->pushbuf_base) >> 2; + return (val - chan->push.vma.offset) >> 2; } void nv50_dma_push(struct nouveau_channel *chan, struct nouveau_bo *bo, int delta, int length) { - struct nouveau_bo *pb = chan->pushbuf_bo; + struct nouveau_bo *pb = chan->push.buffer; struct nouveau_vma *vma; int ip = (chan->dma.ib_put * 2) + chan->dma.ib_base; u64 offset; - vma = nouveau_bo_vma_find(bo, chan->vm); + vma = nouveau_bo_vma_find(bo, nv_client(chan->cli)->vm); BUG_ON(!vma); offset = vma->offset + delta; BUG_ON(chan->dma.ib_free < 1); + nouveau_bo_wr32(pb, ip++, lower_32_bits(offset)); nouveau_bo_wr32(pb, ip++, upper_32_bits(offset) | length << 8); @@ -128,7 +104,7 @@ nv50_dma_push(struct nouveau_channel *chan, struct nouveau_bo *bo, /* Flush writes. */ nouveau_bo_rd32(pb, 0); - nvchan_wr32(chan, 0x8c, chan->dma.ib_put); + nv_wo32(chan->object, 0x8c, chan->dma.ib_put); chan->dma.ib_free--; } @@ -138,7 +114,7 @@ nv50_dma_push_wait(struct nouveau_channel *chan, int count) uint32_t cnt = 0, prev_get = 0; while (chan->dma.ib_free < count) { - uint32_t get = nvchan_rd32(chan, 0x88); + uint32_t get = nv_ro32(chan->object, 0x88); if (get != prev_get) { prev_get = get; cnt = 0; @@ -249,7 +225,7 @@ nouveau_dma_wait(struct nouveau_channel *chan, int slots, int size) * instruct the GPU to jump back to the start right * after processing the currently pending commands. */ - OUT_RING(chan, chan->pushbuf_base | 0x20000000); + OUT_RING(chan, chan->push.vma.offset | 0x20000000); /* wait for GET to depart from the skips area. * prevents writing GET==PUT and causing a race diff --git a/drivers/gpu/drm/nouveau/nouveau_dma.h b/drivers/gpu/drm/nouveau/nouveau_dma.h index 8db68be9544f..5c2e22932d1c 100644 --- a/drivers/gpu/drm/nouveau/nouveau_dma.h +++ b/drivers/gpu/drm/nouveau/nouveau_dma.h @@ -27,10 +27,10 @@ #ifndef __NOUVEAU_DMA_H__ #define __NOUVEAU_DMA_H__ -#ifndef NOUVEAU_DMA_DEBUG -#define NOUVEAU_DMA_DEBUG 0 -#endif +#include "nouveau_bo.h" +#include "nouveau_chan.h" +int nouveau_dma_wait(struct nouveau_channel *, int slots, int size); void nv50_dma_push(struct nouveau_channel *, struct nouveau_bo *, int delta, int length); @@ -116,12 +116,7 @@ RING_SPACE(struct nouveau_channel *chan, int size) static inline void OUT_RING(struct nouveau_channel *chan, int data) { - if (NOUVEAU_DMA_DEBUG) { - NV_INFO(chan->dev, "Ch%d/0x%08x: 0x%08x\n", - chan->id, chan->dma.cur << 2, data); - } - - nouveau_bo_wr32(chan->pushbuf_bo, chan->dma.cur++, data); + nouveau_bo_wr32(chan->push.buffer, chan->dma.cur++, data); } extern void @@ -159,24 +154,19 @@ BEGIN_IMC0(struct nouveau_channel *chan, int subc, int mthd, u16 data) #define WRITE_PUT(val) do { \ DRM_MEMORYBARRIER(); \ - nouveau_bo_rd32(chan->pushbuf_bo, 0); \ - nvchan_wr32(chan, chan->user_put, ((val) << 2) + chan->pushbuf_base); \ + nouveau_bo_rd32(chan->push.buffer, 0); \ + nv_wo32(chan->object, chan->user_put, ((val) << 2) + chan->push.vma.offset); \ } while (0) static inline void FIRE_RING(struct nouveau_channel *chan) { - if (NOUVEAU_DMA_DEBUG) { - NV_INFO(chan->dev, "Ch%d/0x%08x: PUSH!\n", - chan->id, chan->dma.cur << 2); - } - if (chan->dma.cur == chan->dma.put) return; chan->accel_done = true; if (chan->dma.ib_max) { - nv50_dma_push(chan, chan->pushbuf_bo, chan->dma.put << 2, + nv50_dma_push(chan, chan->push.buffer, chan->dma.put << 2, (chan->dma.cur - chan->dma.put) << 2); } else { WRITE_PUT(chan->dma.cur); @@ -191,4 +181,31 @@ WIND_RING(struct nouveau_channel *chan) chan->dma.cur = chan->dma.put; } +/* FIFO methods */ +#define NV01_SUBCHAN_OBJECT 0x00000000 +#define NV84_SUBCHAN_SEMAPHORE_ADDRESS_HIGH 0x00000010 +#define NV84_SUBCHAN_SEMAPHORE_ADDRESS_LOW 0x00000014 +#define NV84_SUBCHAN_SEMAPHORE_SEQUENCE 0x00000018 +#define NV84_SUBCHAN_SEMAPHORE_TRIGGER 0x0000001c +#define NV84_SUBCHAN_SEMAPHORE_TRIGGER_ACQUIRE_EQUAL 0x00000001 +#define NV84_SUBCHAN_SEMAPHORE_TRIGGER_WRITE_LONG 0x00000002 +#define NV84_SUBCHAN_SEMAPHORE_TRIGGER_ACQUIRE_GEQUAL 0x00000004 +#define NVC0_SUBCHAN_SEMAPHORE_TRIGGER_YIELD 0x00001000 +#define NV84_SUBCHAN_NOTIFY_INTR 0x00000020 +#define NV84_SUBCHAN_WRCACHE_FLUSH 0x00000024 +#define NV10_SUBCHAN_REF_CNT 0x00000050 +#define NVSW_SUBCHAN_PAGE_FLIP 0x00000054 +#define NV11_SUBCHAN_DMA_SEMAPHORE 0x00000060 +#define NV11_SUBCHAN_SEMAPHORE_OFFSET 0x00000064 +#define NV11_SUBCHAN_SEMAPHORE_ACQUIRE 0x00000068 +#define NV11_SUBCHAN_SEMAPHORE_RELEASE 0x0000006c +#define NV40_SUBCHAN_YIELD 0x00000080 + +/* NV_SW object class */ +#define NV_SW_DMA_VBLSEM 0x0000018c +#define NV_SW_VBLSEM_OFFSET 0x00000400 +#define NV_SW_VBLSEM_RELEASE_VALUE 0x00000404 +#define NV_SW_VBLSEM_RELEASE 0x00000408 +#define NV_SW_PAGE_FLIP 0x00000500 + #endif diff --git a/drivers/gpu/drm/nouveau/nouveau_drm.c b/drivers/gpu/drm/nouveau/nouveau_drm.c index 3b4e65d5122b..92ecf50a39d3 100644 --- a/drivers/gpu/drm/nouveau/nouveau_drm.c +++ b/drivers/gpu/drm/nouveau/nouveau_drm.c @@ -27,12 +27,20 @@ #include #include +#include #include #include +#include #include "nouveau_drm.h" +#include "nouveau_dma.h" #include "nouveau_agp.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 *); @@ -43,7 +51,6 @@ void __exit nouveau_exit(struct pci_driver *); int nouveau_load(struct drm_device *, unsigned long); int nouveau_unload(struct drm_device *); -void *nouveau_newpriv(struct drm_device *); MODULE_PARM_DESC(config, "option string to pass to driver core"); static char *nouveau_config; @@ -53,6 +60,10 @@ MODULE_PARM_DESC(debug, "debug string to pass to driver core"); static char *nouveau_debug; module_param_named(debug, nouveau_debug, charp, 0400); +MODULE_PARM_DESC(noaccel, "disable kernel/abi16 acceleration"); +static int nouveau_noaccel = 0; +module_param_named(noaccel, nouveau_noaccel, int, 0400); + static u64 nouveau_name(struct pci_dev *pdev) { @@ -82,17 +93,112 @@ static void nouveau_cli_destroy(struct nouveau_cli *cli) { struct nouveau_object *client = nv_object(cli); + nouveau_vm_ref(NULL, &cli->base.vm, NULL); nouveau_client_fini(&cli->base, false); atomic_set(&client->refcount, 1); nouveau_object_ref(NULL, &client); } +static void +nouveau_accel_fini(struct nouveau_drm *drm) +{ + nouveau_gpuobj_ref(NULL, &drm->notify); + nouveau_channel_del(&drm->channel); + if (drm->fence) + nouveau_fence(drm)->dtor(drm); +} + +static void +nouveau_accel_init(struct nouveau_drm *drm) +{ + struct nouveau_device *device = nv_device(drm->device); + struct nouveau_object *object; + int ret; + + if (nouveau_noaccel) + return; + + /* initialise synchronisation routines */ + if (device->card_type < NV_10) ret = nv04_fence_create(drm); + else if (device->chipset < 0x84) ret = nv10_fence_create(drm); + else if (device->card_type < NV_C0) ret = nv84_fence_create(drm); + else ret = nvc0_fence_create(drm); + if (ret) { + NV_ERROR(drm, "failed to initialise sync subsystem, %d\n", ret); + nouveau_accel_fini(drm); + return; + } + + ret = nouveau_channel_new(drm, &drm->client, NVDRM_DEVICE, NVDRM_CHAN, + NvDmaFB, NvDmaTT, &drm->channel); + if (ret) { + NV_ERROR(drm, "failed to create kernel channel, %d\n", ret); + nouveau_accel_fini(drm); + return; + } + + if (device->card_type < NV_C0) { + ret = nouveau_gpuobj_new(drm->device, NULL, 32, 0, 0, + &drm->notify); + if (ret) { + NV_ERROR(drm, "failed to allocate notifier, %d\n", ret); + nouveau_accel_fini(drm); + return; + } + + ret = nouveau_object_new(nv_object(drm), + drm->channel->handle, NvNotify0, + 0x003d, &(struct nv_dma_class) { + .flags = NV_DMA_TARGET_VRAM | + NV_DMA_ACCESS_RDWR, + .start = drm->notify->addr, + .limit = drm->notify->addr + 31 + }, sizeof(struct nv_dma_class), + &object); + if (ret) { + nouveau_accel_fini(drm); + return; + } + } + + + nouveau_bo_move_init(drm->channel); +} + static int __devinit nouveau_drm_probe(struct pci_dev *pdev, const struct pci_device_id *pent) { struct nouveau_device *device; + struct apertures_struct *aper; + bool boot = false; int ret; + /* remove conflicting drivers (vesafb, efifb etc) */ + aper = alloc_apertures(3); + if (!aper) + return -ENOMEM; + + aper->ranges[0].base = pci_resource_start(pdev, 1); + aper->ranges[0].size = pci_resource_len(pdev, 1); + aper->count = 1; + + if (pci_resource_len(pdev, 2)) { + aper->ranges[aper->count].base = pci_resource_start(pdev, 2); + aper->ranges[aper->count].size = pci_resource_len(pdev, 2); + aper->count++; + } + + if (pci_resource_len(pdev, 3)) { + aper->ranges[aper->count].base = pci_resource_start(pdev, 3); + aper->ranges[aper->count].size = pci_resource_len(pdev, 3); + aper->count++; + } + +#ifdef CONFIG_X86 + boot = pdev->resource[PCI_ROM_RESOURCE].flags & IORESOURCE_ROM_SHADOW; +#endif + remove_conflicting_framebuffers(aper, "nouveaufb", boot); + ret = nouveau_device_create(pdev, nouveau_name(pdev), pci_name(pdev), nouveau_config, nouveau_debug, &device); if (ret) @@ -102,7 +208,7 @@ nouveau_drm_probe(struct pci_dev *pdev, const struct pci_device_id *pent) ret = nouveau_pci_probe(pdev, pent); if (ret) { - nouveau_device_destroy(&device); + nouveau_object_ref(NULL, (struct nouveau_object **)&device); return ret; } @@ -113,6 +219,7 @@ int nouveau_drm_load(struct drm_device *dev, unsigned long flags) { struct pci_dev *pdev = dev->pdev; + struct nouveau_device *device; struct nouveau_drm *drm; int ret; @@ -122,6 +229,7 @@ nouveau_drm_load(struct drm_device *dev, unsigned long flags) return ret; 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 @@ -142,7 +250,7 @@ nouveau_drm_load(struct drm_device *dev, unsigned long flags) }, sizeof(struct nv_device_class), &drm->device); if (ret) - return ret; + goto fail_device; nouveau_agp_reset(drm); nouveau_object_del(nv_object(drm), NVDRM_CLIENT, NVDRM_DEVICE); @@ -158,15 +266,32 @@ nouveau_drm_load(struct drm_device *dev, unsigned long flags) if (ret) goto fail_device; + device = nv_device(drm->device); + /* initialise AGP */ nouveau_agp_init(drm); - ret = nouveau_load(dev, flags); + if (device->card_type >= NV_50) { + ret = nouveau_vm_new(nv_device(drm->device), 0, (1ULL << 40), + 0x1000, &drm->client.base.vm); + if (ret) + goto fail_device; + } + + ret = nouveau_ttm_init(drm); if (ret) goto fail_device; + ret = nouveau_load(dev, flags); + if (ret) + goto fail_load; + + nouveau_accel_init(drm); + nouveau_fbcon_init(dev); return 0; +fail_load: + nouveau_ttm_fini(drm); fail_device: nouveau_cli_destroy(&drm->client); return ret; @@ -179,10 +304,14 @@ nouveau_drm_unload(struct drm_device *dev) struct pci_dev *pdev = dev->pdev; int ret; + nouveau_fbcon_fini(dev); + nouveau_accel_fini(drm); + ret = nouveau_unload(dev); if (ret) return ret; + nouveau_ttm_fini(drm); nouveau_agp_fini(drm); pci_set_drvdata(pdev, drm->client.base.device); @@ -193,10 +322,11 @@ nouveau_drm_unload(struct drm_device *dev) static void nouveau_drm_remove(struct pci_dev *pdev) { - struct nouveau_device *device; + struct nouveau_object *device; nouveau_pci_remove(pdev); device = pci_get_drvdata(pdev); - nouveau_device_destroy(&device); + nouveau_object_ref(NULL, &device); + nouveau_object_debug(); } int @@ -211,10 +341,23 @@ nouveau_drm_suspend(struct pci_dev *pdev, pm_message_t pm_state) pm_state.event == PM_EVENT_PRETHAW) return 0; + 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); if (ret) return ret; + NV_INFO(drm, "evicting buffers...\n"); + ttm_bo_evict_mm(&drm->ttm.bdev, TTM_PL_VRAM); + + if (drm->fence && nouveau_fence(drm)->suspend) { + if (!nouveau_fence(drm)->suspend(drm)) + return -ENOMEM; + } + + NV_INFO(drm, "suspending client object trees...\n"); list_for_each_entry(cli, &drm->clients, head) { ret = nouveau_client_fini(&cli->base, true); if (ret) @@ -255,6 +398,7 @@ nouveau_drm_resume(struct pci_dev *pdev) if (dev->switch_power_state == DRM_SWITCH_POWER_OFF) return 0; + NV_INFO(drm, "re-enabling device...\n"); pci_set_power_state(pdev, PCI_D0); pci_restore_state(pdev); ret = pci_enable_device(pdev); @@ -264,17 +408,70 @@ nouveau_drm_resume(struct pci_dev *pdev) nouveau_agp_reset(drm); + NV_INFO(drm, "resuming client object trees...\n"); nouveau_client_init(&drm->client.base); + nouveau_agp_init(drm); list_for_each_entry(cli, &drm->clients, head) { nouveau_client_init(&cli->base); } - nouveau_agp_init(drm); + if (drm->fence && nouveau_fence(drm)->resume) + nouveau_fence(drm)->resume(drm); return nouveau_pci_resume(pdev); } +int +nouveau_drm_open(struct drm_device *dev, struct drm_file *fpriv) +{ + struct pci_dev *pdev = dev->pdev; + struct nouveau_drm *drm = nouveau_drm(dev); + struct nouveau_cli *cli; + int ret; + + ret = nouveau_cli_create(pdev, fpriv->pid, sizeof(*cli), (void **)&cli); + if (ret) + return ret; + + if (nv_device(drm->device)->card_type >= NV_50) { + ret = nouveau_vm_new(nv_device(drm->device), 0, (1ULL << 40), + 0x1000, &cli->base.vm); + if (ret) { + nouveau_cli_destroy(cli); + return ret; + } + } + + fpriv->driver_priv = cli; + + mutex_lock(&drm->client.mutex); + list_add(&cli->head, &drm->clients); + mutex_unlock(&drm->client.mutex); + return 0; +} + +void +nouveau_drm_preclose(struct drm_device *dev, struct drm_file *fpriv) +{ + struct nouveau_cli *cli = nouveau_cli(fpriv); + struct nouveau_drm *drm = nouveau_drm(dev); + + if (cli->abi16) + nouveau_abi16_fini(cli->abi16); + + mutex_lock(&drm->client.mutex); + list_del(&cli->head); + mutex_unlock(&drm->client.mutex); +} + +void +nouveau_drm_postclose(struct drm_device *dev, struct drm_file *fpriv) +{ + struct nouveau_cli *cli = nouveau_cli(fpriv); + nouveau_cli_destroy(cli); +} + static struct pci_device_id nouveau_drm_pci_table[] = { { diff --git a/drivers/gpu/drm/nouveau/nouveau_drm.h b/drivers/gpu/drm/nouveau/nouveau_drm.h index 87698067244b..2e3364d50ca0 100644 --- a/drivers/gpu/drm/nouveau/nouveau_drm.h +++ b/drivers/gpu/drm/nouveau/nouveau_drm.h @@ -3,20 +3,50 @@ #include +#include + #include #include +#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" +#include "ttm/ttm_page_alloc.h" + +struct nouveau_channel; + +#define DRM_FILE_PAGE_OFFSET (0x100000000ULL >> PAGE_SHIFT) + +#include "nouveau_revcompat.h" +#include "nouveau_fence.h" + +struct nouveau_drm_tile { + struct nouveau_fence *fence; + bool used; +}; + enum nouveau_drm_handle { NVDRM_CLIENT = 0xffffffff, NVDRM_DEVICE = 0xdddddddd, + NVDRM_PUSH = 0xbbbb0000, /* |= client chid */ + NVDRM_CHAN = 0xcccc0000, /* |= client chid */ }; struct nouveau_cli { struct nouveau_client base; struct list_head head; struct mutex mutex; + void *abi16; }; +static inline struct nouveau_cli * +nouveau_cli(struct drm_file *fpriv) +{ + return fpriv ? fpriv->driver_priv : NULL; +} + struct nouveau_drm { struct nouveau_cli client; struct drm_device *dev; @@ -33,8 +63,46 @@ struct nouveau_drm { u32 base; u32 size; } agp; + + /* TTM interface support */ + struct { + struct drm_global_reference mem_global_ref; + struct ttm_bo_global_ref bo_global_ref; + struct ttm_bo_device bdev; + atomic_t validate_sequence; + int (*move)(struct nouveau_channel *, + struct ttm_buffer_object *, + struct ttm_mem_reg *, struct ttm_mem_reg *); + int mtrr; + } ttm; + + /* GEM interface support */ + struct { + u64 vram_available; + u64 gart_available; + } gem; + + /* synchronisation */ + void *fence; + + /* context for accelerated drm-internal operations */ + struct nouveau_channel *channel; + struct nouveau_gpuobj *notify; + struct nouveau_fbdev *fbcon; + + /* nv10-nv40 tiling regions */ + struct { + struct nouveau_drm_tile reg[15]; + spinlock_t lock; + } tile; }; +static inline struct nouveau_drm * +nouveau_drm(struct drm_device *dev) +{ + return nouveau_newpriv(dev); +} + int nouveau_drm_suspend(struct pci_dev *, pm_message_t); int nouveau_drm_resume(struct pci_dev *); diff --git a/drivers/gpu/drm/nouveau/nouveau_drv.c b/drivers/gpu/drm/nouveau/nouveau_drv.c index db150d9e0cd4..2294cb8848f7 100644 --- a/drivers/gpu/drm/nouveau/nouveau_drv.c +++ b/drivers/gpu/drm/nouveau/nouveau_drv.c @@ -35,7 +35,6 @@ #include "nouveau_fbcon.h" #include "nouveau_fence.h" #include "nouveau_pm.h" -#include #include "nv50_display.h" #include "drm_pciids.h" @@ -68,14 +67,6 @@ MODULE_PARM_DESC(ignorelid, "Ignore ACPI lid status"); int nouveau_ignorelid = 0; module_param_named(ignorelid, nouveau_ignorelid, int, 0400); -MODULE_PARM_DESC(noaccel, "Disable all acceleration"); -int nouveau_noaccel = -1; -module_param_named(noaccel, nouveau_noaccel, int, 0400); - -MODULE_PARM_DESC(nofbaccel, "Disable fbcon acceleration"); -int nouveau_nofbaccel = 0; -module_param_named(nofbaccel, nouveau_nofbaccel, int, 0400); - MODULE_PARM_DESC(force_post, "Force POST"); int nouveau_force_post = 0; module_param_named(force_post, nouveau_force_post, int, 0400); @@ -148,19 +139,11 @@ int nouveau_pci_suspend(struct pci_dev *pdev, pm_message_t pm_state) { struct drm_device *dev = pci_get_drvdata(pdev); - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_fifo_priv *pfifo = nv_engine(dev, NVOBJ_ENGINE_FIFO); - struct nouveau_fence_priv *fence = dev_priv->fence.func; - struct nouveau_channel *chan; struct drm_crtc *crtc; - int ret, i, e; NV_INFO(dev, "Disabling display...\n"); nouveau_display_fini(dev); - NV_INFO(dev, "Disabling fbcon...\n"); - nouveau_fbcon_set_suspend(dev, 1); - NV_INFO(dev, "Unpinning framebuffer(s)...\n"); list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { struct nouveau_framebuffer *nouveau_fb; @@ -179,74 +162,23 @@ nouveau_pci_suspend(struct pci_dev *pdev, pm_message_t pm_state) nouveau_bo_unpin(nv_crtc->cursor.nvbo); } - NV_INFO(dev, "Evicting buffers...\n"); - ttm_bo_evict_mm(&dev_priv->ttm.bdev, TTM_PL_VRAM); - - NV_INFO(dev, "Idling channels...\n"); - for (i = 0; i < (pfifo ? pfifo->channels : 0); i++) { - chan = dev_priv->channels.ptr[i]; - - if (chan && chan->pushbuf_bo) - nouveau_channel_idle(chan); - } - - if (fence->suspend) { - if (!fence->suspend(dev)) - return -ENOMEM; - } - - for (e = NVOBJ_ENGINE_NR - 1; e >= 0; e--) { - if (!dev_priv->eng[e]) - continue; - - ret = dev_priv->eng[e]->fini(dev, e, true); - if (ret) { - NV_ERROR(dev, "... engine %d failed: %d\n", e, ret); - goto out_abort; - } - } - return 0; - -out_abort: - NV_INFO(dev, "Re-enabling acceleration..\n"); - for (e = e + 1; e < NVOBJ_ENGINE_NR; e++) { - if (dev_priv->eng[e]) - dev_priv->eng[e]->init(dev, e); - } - return ret; } int nouveau_pci_resume(struct pci_dev *pdev) { struct drm_device *dev = pci_get_drvdata(pdev); - struct nouveau_fifo_priv *pfifo = nv_engine(dev, NVOBJ_ENGINE_FIFO); - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_fence_priv *fence = dev_priv->fence.func; - struct nouveau_engine *engine = &dev_priv->engine; struct drm_crtc *crtc; - int ret, i; - - /* Make the CRTCs accessible */ - engine->display.early_init(dev); + int ret; - NV_INFO(dev, "POSTing device...\n"); ret = nouveau_run_vbios_init(dev); if (ret) return ret; - NV_INFO(dev, "Reinitialising engines...\n"); - for (i = 0; i < NVOBJ_ENGINE_NR; i++) { - if (dev_priv->eng[i]) - dev_priv->eng[i]->init(dev, i); - } - - if (fence->resume) - fence->resume(dev); - 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; @@ -261,6 +193,7 @@ nouveau_pci_resume(struct pci_dev *pdev) nouveau_bo_wr32(chan->pushbuf_bo, i, 0); } } +#endif nouveau_pm_resume(dev); @@ -343,6 +276,9 @@ static const struct file_operations nouveau_driver_fops = { 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 = @@ -353,13 +289,9 @@ static struct drm_driver driver = { .firstopen = nouveau_firstopen, .lastclose = nouveau_lastclose, .unload = nouveau_drm_unload, - .open = nouveau_open, - .preclose = nouveau_preclose, - .postclose = nouveau_postclose, -#if defined(CONFIG_DRM_NOUVEAU_DEBUG) - .debugfs_init = nouveau_debugfs_init, - .debugfs_cleanup = nouveau_debugfs_takedown, -#endif + .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, diff --git a/drivers/gpu/drm/nouveau/nouveau_drv.h b/drivers/gpu/drm/nouveau/nouveau_drv.h index 08ce60be3f3c..f1cce652a2a9 100644 --- a/drivers/gpu/drm/nouveau/nouveau_drv.h +++ b/drivers/gpu/drm/nouveau/nouveau_drv.h @@ -64,24 +64,11 @@ enum blah { NV_MEM_TYPE_GDDR5 }; -struct nouveau_fpriv { - spinlock_t lock; - struct list_head channels; - struct nouveau_vm *vm; -}; - -static inline struct nouveau_fpriv * -nouveau_fpriv(struct drm_file *file_priv) -{ - return file_priv ? file_priv->driver_priv : NULL; -} - #define DRM_FILE_PAGE_OFFSET (0x100000000ULL >> PAGE_SHIFT) #include #include "nouveau_reg.h" #include -#include "nouveau_util.h" struct nouveau_grctx; struct nouveau_mem; @@ -90,8 +77,7 @@ struct nouveau_mem; #include "nouveau_compat.h" #define nouveau_gpuobj_new(d,c,s,a,f,o) \ - _nouveau_gpuobj_new((d), (c) ? ((struct nouveau_channel *)(c))->ramin : NULL, \ - (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)) @@ -102,40 +88,15 @@ struct nouveau_mem; #define MAX_NUM_DCB_ENTRIES 16 #define NOUVEAU_MAX_CHANNEL_NR 4096 -#define NOUVEAU_MAX_TILE_NR 15 #include "nouveau_bo.h" #include "nouveau_gem.h" -/* TODO: submit equivalent to TTM generic API upstream? */ -static inline void __iomem * -nvbo_kmap_obj_iovirtual(struct nouveau_bo *nvbo) -{ - bool is_iomem; - void __iomem *ioptr = (void __force __iomem *)ttm_kmap_obj_virtual( - &nvbo->kmap, &is_iomem); - WARN_ON_ONCE(ioptr && !is_iomem); - return ioptr; -} - enum nouveau_flags { NV_NFORCE = 0x10000000, NV_NFORCE2 = 0x20000000 }; -#define NVOBJ_ENGINE_SW 0 -#define NVOBJ_ENGINE_GR 1 -#define NVOBJ_ENGINE_CRYPT 2 -#define NVOBJ_ENGINE_COPY0 3 -#define NVOBJ_ENGINE_COPY1 4 -#define NVOBJ_ENGINE_MPEG 5 -#define NVOBJ_ENGINE_PPP NVOBJ_ENGINE_MPEG -#define NVOBJ_ENGINE_BSP 6 -#define NVOBJ_ENGINE_VP 7 -#define NVOBJ_ENGINE_FIFO 14 -#define NVOBJ_ENGINE_NR 16 -#define NVOBJ_ENGINE_DISPLAY (NVOBJ_ENGINE_NR + 0) /*XXX*/ - struct nouveau_page_flip_state { struct list_head head; struct drm_pending_vblank_event *event; @@ -148,95 +109,6 @@ enum nouveau_channel_mutex_class { NOUVEAU_KCHANNEL_MUTEX }; -struct nouveau_channel { - struct drm_device *dev; - struct list_head list; - int id; - - /* references to the channel data structure */ - struct kref ref; - /* users of the hardware channel resources, the hardware - * context will be kicked off when it reaches zero. */ - atomic_t users; - struct mutex mutex; - - /* owner of this fifo */ - struct drm_file *file_priv; - /* mapping of the fifo itself */ - struct drm_local_map *map; - - /* mapping of the regs controlling the fifo */ - void __iomem *user; - uint32_t user_get; - uint32_t user_get_hi; - uint32_t user_put; - - /* DMA push buffer */ - struct nouveau_gpuobj *pushbuf; - struct nouveau_bo *pushbuf_bo; - struct nouveau_vma pushbuf_vma; - uint64_t pushbuf_base; - - /* Notifier memory */ - struct nouveau_bo *notifier_bo; - struct nouveau_vma notifier_vma; - struct drm_mm notifier_heap; - - /* PFIFO context */ - struct nouveau_gpuobj *engptr; - struct nouveau_gpuobj *ramfc; - - /* Execution engine contexts */ - void *engctx[NVOBJ_ENGINE_NR]; - void *fence; - - /* NV50 VM */ - struct nouveau_vm *vm; - struct nouveau_gpuobj *vm_pd; - - /* Objects */ - struct nouveau_gpuobj *ramin; /* Private instmem */ - struct nouveau_ramht *ramht; /* Hash table */ - - /* GPU object info for stuff used in-kernel (mm_enabled) */ - uint32_t m2mf_ntfy; - uint32_t vram_handle; - uint32_t gart_handle; - bool accel_done; - - /* Push buffer state (only for drm's channel on !mm_enabled) */ - struct { - int max; - int free; - int cur; - int put; - /* access via pushbuf_bo */ - - int ib_base; - int ib_max; - int ib_free; - int ib_put; - } dma; - - struct { - bool active; - char name[32]; - struct drm_info_list info; - } debugfs; -}; - -struct nouveau_exec_engine { - void (*destroy)(struct drm_device *, int engine); - int (*init)(struct drm_device *, int engine); - int (*fini)(struct drm_device *, int engine, bool suspend); - int (*context_new)(struct nouveau_channel *, int engine); - void (*context_del)(struct nouveau_channel *, int engine); - int (*object_new)(struct nouveau_channel *, int engine, - u32 handle, u16 class); - void (*set_tile_region)(struct drm_device *dev, int i); - void (*tlb_flush)(struct drm_device *, int engine); -}; - struct nouveau_display_engine { void *priv; int (*early_init)(struct drm_device *); @@ -434,6 +306,8 @@ enum nouveau_card_type { NV_E0 = 0xe0, }; +struct nouveau_channel; + struct drm_nouveau_private { struct drm_device *dev; bool noaccel; @@ -447,92 +321,29 @@ struct drm_nouveau_private { int flags; u32 crystal; - struct nouveau_exec_engine *eng[NVOBJ_ENGINE_NR]; - - struct list_head classes; - struct nouveau_bo *vga_ram; /* interrupt handling */ void (*irq_handler[32])(struct drm_device *); bool msi_enabled; - struct { - struct drm_global_reference mem_global_ref; - struct ttm_bo_global_ref bo_global_ref; - struct ttm_bo_device bdev; - atomic_t validate_sequence; - int (*move)(struct nouveau_channel *, - struct ttm_buffer_object *, - struct ttm_mem_reg *, struct ttm_mem_reg *); - } ttm; - - struct { - void *func; - spinlock_t lock; - struct drm_mm heap; - struct nouveau_bo *bo; - } fence; - - struct { - spinlock_t lock; - struct nouveau_channel *ptr[NOUVEAU_MAX_CHANNEL_NR]; - } channels; - struct nouveau_engine engine; - struct nouveau_channel *channel; /* For PFIFO and PGRAPH. */ spinlock_t context_switch_lock; - /* VM/PRAMIN flush, legacy PRAMIN aperture */ - spinlock_t vm_lock; - /* RAMIN configuration, RAMFC, RAMHT and RAMRO offsets */ struct nouveau_ramht *ramht; - struct { - enum { - NOUVEAU_GART_NONE = 0, - NOUVEAU_GART_AGP, /* AGP */ - NOUVEAU_GART_PDMA, /* paged dma object */ - NOUVEAU_GART_HW /* on-chip gart/vm */ - } type; - uint64_t aper_base; - uint64_t aper_size; - uint64_t aper_free; - - struct ttm_backend_func *func; - - struct nouveau_gpuobj *sg_ctxdma; - } gart_info; - - /* nv10-nv40 tiling regions */ - struct { - struct nouveau_tile_reg reg[NOUVEAU_MAX_TILE_NR]; - spinlock_t lock; - } tile; - uint64_t fb_available_size; uint64_t fb_mappable_pages; - uint64_t fb_aper_free; int fb_mtrr; - /* G8x/G9x virtual address space */ - struct nouveau_vm *chan_vm; - struct nvbios vbios; u8 *mxms; struct list_head i2c_ports; struct backlight_device *backlight; - - struct { - struct dentry *channel_root; - } debugfs; - - struct nouveau_fbdev *nfbdev; - struct apertures_struct *apertures; }; static inline struct drm_nouveau_private * @@ -541,12 +352,6 @@ nouveau_private(struct drm_device *dev) return dev->dev_private; } -static inline struct drm_nouveau_private * -nouveau_bdev(struct ttm_bo_device *bd) -{ - return container_of(bd, struct drm_nouveau_private, ttm.bdev); -} - /* nouveau_drv.c */ extern int nouveau_modeset; extern int nouveau_duallink; @@ -560,7 +365,6 @@ extern int nouveau_tv_disable; extern char *nouveau_tv_norm; extern int nouveau_reg_debug; extern int nouveau_ignorelid; -extern int nouveau_nofbaccel; extern int nouveau_noaccel; extern int nouveau_force_post; extern int nouveau_override_conntype; @@ -574,9 +378,6 @@ 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_open(struct drm_device *, struct drm_file *); -extern void nouveau_preclose(struct drm_device *dev, struct drm_file *); -extern void nouveau_postclose(struct drm_device *, struct drm_file *); extern int nouveau_load(struct drm_device *, unsigned long flags); extern int nouveau_firstopen(struct drm_device *); extern void nouveau_lastclose(struct drm_device *); @@ -596,76 +397,16 @@ extern int nouveau_mem_timing_calc(struct drm_device *, u32 freq, extern void nouveau_mem_timing_read(struct drm_device *, struct nouveau_pm_memtiming *); extern int nouveau_mem_vbios_type(struct drm_device *); -extern const struct ttm_mem_type_manager_func nouveau_vram_manager; -extern const struct ttm_mem_type_manager_func nouveau_gart_manager; -extern const struct ttm_mem_type_manager_func nv04_gart_manager; - -/* nouveau_notifier.c */ -extern int nouveau_notifier_init_channel(struct nouveau_channel *); -extern void nouveau_notifier_takedown_channel(struct nouveau_channel *); -extern int nouveau_notifier_alloc(struct nouveau_channel *, uint32_t handle, - int cout, uint32_t start, uint32_t end, - uint32_t *offset); - -/* nouveau_channel.c */ -extern void nouveau_channel_cleanup(struct drm_device *, struct drm_file *); -extern int nouveau_channel_alloc(struct drm_device *dev, - struct nouveau_channel **chan, - struct drm_file *file_priv, - uint32_t fb_ctxdma, uint32_t tt_ctxdma); -extern struct nouveau_channel * -nouveau_channel_get_unlocked(struct nouveau_channel *); -extern struct nouveau_channel * -nouveau_channel_get(struct drm_file *, int id); -extern void nouveau_channel_put_unlocked(struct nouveau_channel **); -extern void nouveau_channel_put(struct nouveau_channel **); -extern void nouveau_channel_ref(struct nouveau_channel *chan, - struct nouveau_channel **pchan); +extern struct nouveau_tile_reg *nv10_mem_set_tiling( + struct drm_device *dev, uint32_t addr, uint32_t size, + uint32_t pitch, uint32_t flags); +extern void nv10_mem_put_tile_region(struct drm_device *dev, + struct nouveau_tile_reg *tile, + struct nouveau_fence *fence); + extern int nouveau_channel_idle(struct nouveau_channel *chan); /* nouveau_gpuobj.c */ -#define NVOBJ_ENGINE_ADD(d, e, p) do { \ - struct drm_nouveau_private *dev_priv = (d)->dev_private; \ - dev_priv->eng[NVOBJ_ENGINE_##e] = (p); \ -} while (0) - -#define NVOBJ_ENGINE_DEL(d, e) do { \ - struct drm_nouveau_private *dev_priv = (d)->dev_private; \ - dev_priv->eng[NVOBJ_ENGINE_##e] = NULL; \ -} while (0) - -#define NVOBJ_CLASS(d, c, e) do { \ - int ret = nouveau_gpuobj_class_new((d), (c), NVOBJ_ENGINE_##e); \ - if (ret) \ - return ret; \ -} while (0) - -#define NVOBJ_MTHD(d, c, m, e) do { \ - int ret = nouveau_gpuobj_mthd_new((d), (c), (m), (e)); \ - if (ret) \ - return ret; \ -} while (0) - -extern int nouveau_gpuobj_class_new(struct drm_device *, u32 class, u32 eng); -extern int nouveau_gpuobj_mthd_new(struct drm_device *, u32 class, u32 mthd, - int (*exec)(struct nouveau_channel *, - u32 class, u32 mthd, u32 data)); -extern int nouveau_gpuobj_mthd_call(struct nouveau_channel *, u32, u32, u32); -extern int nouveau_gpuobj_mthd_call2(struct drm_device *, int, u32, u32, u32); -extern int nouveau_gpuobj_channel_init(struct nouveau_channel *, - uint32_t vram_h, uint32_t tt_h); -extern void nouveau_gpuobj_channel_takedown(struct nouveau_channel *); -extern int nouveau_gpuobj_dma_new(struct nouveau_channel *, int class, - uint64_t offset, uint64_t size, int access, - int target, struct nouveau_gpuobj **); -extern int nouveau_gpuobj_gr_new(struct nouveau_channel *, u32 handle, int class); -extern int nv50_gpuobj_dma_new(struct nouveau_channel *, int class, u64 base, - u64 size, int target, int access, u32 type, - u32 comp, struct nouveau_gpuobj **pobj); -extern void nv50_gpuobj_dma_init(struct nouveau_gpuobj *, u32 offset, - int class, u64 base, u64 size, int target, - int access, u32 type, u32 comp); - int nouveau_gpuobj_map_vm(struct nouveau_gpuobj *gpuobj, struct nouveau_vm *vm, u32 flags, struct nouveau_vma *vma); void nouveau_gpuobj_unmap(struct nouveau_vma *vma); @@ -681,49 +422,6 @@ 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_sgdma.c */ -extern int nouveau_sgdma_init(struct drm_device *); -extern void nouveau_sgdma_takedown(struct drm_device *); -extern uint32_t nouveau_sgdma_get_physical(struct drm_device *, - uint32_t offset); -extern struct ttm_tt *nouveau_sgdma_create_ttm(struct ttm_bo_device *bdev, - unsigned long size, - uint32_t page_flags, - struct page *dummy_read_page); - -/* nouveau_debugfs.c */ -#if defined(CONFIG_DRM_NOUVEAU_DEBUG) -extern int nouveau_debugfs_init(struct drm_minor *); -extern void nouveau_debugfs_takedown(struct drm_minor *); -extern int nouveau_debugfs_channel_init(struct nouveau_channel *); -extern void nouveau_debugfs_channel_fini(struct nouveau_channel *); -#else -static inline int -nouveau_debugfs_init(struct drm_minor *minor) -{ - return 0; -} - -static inline void nouveau_debugfs_takedown(struct drm_minor *minor) -{ -} - -static inline int -nouveau_debugfs_channel_init(struct nouveau_channel *chan) -{ - return 0; -} - -static inline void -nouveau_debugfs_channel_fini(struct nouveau_channel *chan) -{ -} -#endif - -/* nouveau_dma.c */ -extern void nouveau_dma_init(struct nouveau_channel *); -extern int nouveau_dma_wait(struct nouveau_channel *, int slots, int size); - /* nouveau_acpi.c */ #define ROM_BIOS_PAGE 4096 #if defined(CONFIG_ACPI) @@ -785,72 +483,8 @@ int nouveau_ttm_mmap(struct file *, struct vm_area_struct *); /* nouveau_hdmi.c */ void nouveau_hdmi_mode_set(struct drm_encoder *, struct drm_display_mode *); -/* nv04_graph.c */ -extern int nv04_graph_create(struct drm_device *); -extern int nv04_graph_object_new(struct nouveau_channel *, int, u32, u16); -extern int nv04_graph_mthd_page_flip(struct nouveau_channel *chan, - u32 class, u32 mthd, u32 data); -extern struct nouveau_bitfield nv04_graph_nsource[]; - -/* nv10_graph.c */ -extern int nv10_graph_create(struct drm_device *); -extern struct nouveau_channel *nv10_graph_channel(struct drm_device *); -extern struct nouveau_bitfield nv10_graph_intr[]; -extern struct nouveau_bitfield nv10_graph_nstatus[]; - -/* nv20_graph.c */ -extern int nv20_graph_create(struct drm_device *); - -/* nv40_graph.c */ -extern int nv40_graph_create(struct drm_device *); -extern void nv40_grctx_init(struct drm_device *, u32 *size); -extern void nv40_grctx_fill(struct drm_device *, struct nouveau_gpuobj *); - -/* nv50_graph.c */ -extern int nv50_graph_create(struct drm_device *); -extern struct nouveau_enum nv50_data_error_names[]; -extern int nv50_graph_isr_chid(struct drm_device *dev, u64 inst); -extern int nv50_grctx_init(struct drm_device *, u32 *, u32, u32 *, u32 *); -extern void nv50_grctx_fill(struct drm_device *, struct nouveau_gpuobj *); - -/* nvc0_graph.c */ -extern int nvc0_graph_create(struct drm_device *); -extern int nvc0_graph_isr_chid(struct drm_device *dev, u64 inst); - -/* nve0_graph.c */ -extern int nve0_graph_create(struct drm_device *); - -/* nv84_crypt.c */ -extern int nv84_crypt_create(struct drm_device *); - -/* nv98_crypt.c */ -extern int nv98_crypt_create(struct drm_device *dev); - -/* nva3_copy.c */ -extern int nva3_copy_create(struct drm_device *dev); - -/* nvc0_copy.c */ -extern int nvc0_copy_create(struct drm_device *dev, int engine); - -/* nv31_mpeg.c */ -extern int nv31_mpeg_create(struct drm_device *dev); - -/* nv50_mpeg.c */ -extern int nv50_mpeg_create(struct drm_device *dev); - -/* nv84_bsp.c */ -/* nv98_bsp.c */ -extern int nv84_bsp_create(struct drm_device *dev); - -/* nv84_vp.c */ -/* nv98_vp.c */ -extern int nv84_vp_create(struct drm_device *dev); - -/* nv98_ppp.c */ -extern int nv98_ppp_create(struct drm_device *dev); - extern long nouveau_compat_ioctl(struct file *file, unsigned int cmd, - unsigned long arg); + unsigned long arg); /* nvd0_display.c */ extern int nvd0_display_create(struct drm_device *); @@ -895,18 +529,6 @@ int nouveau_display_dumb_destroy(struct drm_file *, struct drm_device *, #endif /* def __BIG_ENDIAN else */ #endif /* !ioread32_native */ -/* channel control reg access */ -static inline u32 nvchan_rd32(struct nouveau_channel *chan, unsigned reg) -{ - return ioread32_native(chan->user + reg); -} - -static inline void nvchan_wr32(struct nouveau_channel *chan, - unsigned reg, u32 val) -{ - iowrite32_native(val, chan->user + reg); -} - /* register access */ #define nv_rd08 _nv_rd08 #define nv_wr08 _nv_wr08 @@ -1023,13 +645,6 @@ nv_match_device(struct drm_device *dev, unsigned device, dev->pdev->subsystem_device == sub_device; } -static inline void * -nv_engine(struct drm_device *dev, int engine) -{ - struct drm_nouveau_private *dev_priv = dev->dev_private; - return (void *)dev_priv->eng[engine]; -} - /* returns 1 if device is one of the nv4x using the 0x4497 object class, * helpful to determine a number of other hardware features */ diff --git a/drivers/gpu/drm/nouveau/nouveau_fbcon.c b/drivers/gpu/drm/nouveau/nouveau_fbcon.c index f3f0b4c362cb..8b8bc8314d92 100644 --- a/drivers/gpu/drm/nouveau/nouveau_fbcon.c +++ b/drivers/gpu/drm/nouveau/nouveau_fbcon.c @@ -43,19 +43,31 @@ #include "drm_crtc.h" #include "drm_crtc_helper.h" #include "drm_fb_helper.h" -#include "nouveau_drv.h" -#include -#include "nouveau_crtc.h" + +#include "nouveau_drm.h" +#include "nouveau_gem.h" +#include "nouveau_bo.h" #include "nouveau_fb.h" #include "nouveau_fbcon.h" -#include "nouveau_dma.h" +#include "nouveau_chan.h" + +#include "nouveau_crtc.h" + +#include +#include + +#include + +MODULE_PARM_DESC(nofbaccel, "Disable fbcon acceleration"); +static int nouveau_nofbaccel = 0; +module_param_named(nofbaccel, nouveau_nofbaccel, int, 0400); static void nouveau_fbcon_fillrect(struct fb_info *info, const struct fb_fillrect *rect) { - struct nouveau_fbdev *nfbdev = info->par; - struct drm_device *dev = nfbdev->dev; - struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_fbdev *fbcon = info->par; + struct nouveau_drm *drm = nouveau_newpriv(fbcon->dev); + struct nouveau_device *device = nv_device(drm->device); int ret; if (info->state != FBINFO_STATE_RUNNING) @@ -63,15 +75,15 @@ nouveau_fbcon_fillrect(struct fb_info *info, const struct fb_fillrect *rect) ret = -ENODEV; if (!in_interrupt() && !(info->flags & FBINFO_HWACCEL_DISABLED) && - mutex_trylock(&dev_priv->channel->mutex)) { - if (dev_priv->card_type < NV_50) + mutex_trylock(&drm->client.mutex)) { + if (device->card_type < NV_50) ret = nv04_fbcon_fillrect(info, rect); else - if (dev_priv->card_type < NV_C0) + if (device->card_type < NV_C0) ret = nv50_fbcon_fillrect(info, rect); else ret = nvc0_fbcon_fillrect(info, rect); - mutex_unlock(&dev_priv->channel->mutex); + mutex_unlock(&drm->client.mutex); } if (ret == 0) @@ -85,9 +97,9 @@ nouveau_fbcon_fillrect(struct fb_info *info, const struct fb_fillrect *rect) static void nouveau_fbcon_copyarea(struct fb_info *info, const struct fb_copyarea *image) { - struct nouveau_fbdev *nfbdev = info->par; - struct drm_device *dev = nfbdev->dev; - struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_fbdev *fbcon = info->par; + struct nouveau_drm *drm = nouveau_newpriv(fbcon->dev); + struct nouveau_device *device = nv_device(drm->device); int ret; if (info->state != FBINFO_STATE_RUNNING) @@ -95,15 +107,15 @@ nouveau_fbcon_copyarea(struct fb_info *info, const struct fb_copyarea *image) ret = -ENODEV; if (!in_interrupt() && !(info->flags & FBINFO_HWACCEL_DISABLED) && - mutex_trylock(&dev_priv->channel->mutex)) { - if (dev_priv->card_type < NV_50) + mutex_trylock(&drm->client.mutex)) { + if (device->card_type < NV_50) ret = nv04_fbcon_copyarea(info, image); else - if (dev_priv->card_type < NV_C0) + if (device->card_type < NV_C0) ret = nv50_fbcon_copyarea(info, image); else ret = nvc0_fbcon_copyarea(info, image); - mutex_unlock(&dev_priv->channel->mutex); + mutex_unlock(&drm->client.mutex); } if (ret == 0) @@ -117,9 +129,9 @@ nouveau_fbcon_copyarea(struct fb_info *info, const struct fb_copyarea *image) static void nouveau_fbcon_imageblit(struct fb_info *info, const struct fb_image *image) { - struct nouveau_fbdev *nfbdev = info->par; - struct drm_device *dev = nfbdev->dev; - struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_fbdev *fbcon = info->par; + struct nouveau_drm *drm = nouveau_newpriv(fbcon->dev); + struct nouveau_device *device = nv_device(drm->device); int ret; if (info->state != FBINFO_STATE_RUNNING) @@ -127,15 +139,15 @@ nouveau_fbcon_imageblit(struct fb_info *info, const struct fb_image *image) ret = -ENODEV; if (!in_interrupt() && !(info->flags & FBINFO_HWACCEL_DISABLED) && - mutex_trylock(&dev_priv->channel->mutex)) { - if (dev_priv->card_type < NV_50) + mutex_trylock(&drm->client.mutex)) { + if (device->card_type < NV_50) ret = nv04_fbcon_imageblit(info, image); else - if (dev_priv->card_type < NV_C0) + if (device->card_type < NV_C0) ret = nv50_fbcon_imageblit(info, image); else ret = nvc0_fbcon_imageblit(info, image); - mutex_unlock(&dev_priv->channel->mutex); + mutex_unlock(&drm->client.mutex); } if (ret == 0) @@ -149,10 +161,9 @@ nouveau_fbcon_imageblit(struct fb_info *info, const struct fb_image *image) static int nouveau_fbcon_sync(struct fb_info *info) { - struct nouveau_fbdev *nfbdev = info->par; - struct drm_device *dev = nfbdev->dev; - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_channel *chan = dev_priv->channel; + struct nouveau_fbdev *fbcon = info->par; + struct nouveau_drm *drm = nouveau_newpriv(fbcon->dev); + struct nouveau_channel *chan = drm->channel; int ret; if (!chan || !chan->accel_done || in_interrupt() || @@ -160,11 +171,11 @@ nouveau_fbcon_sync(struct fb_info *info) info->flags & FBINFO_HWACCEL_DISABLED) return 0; - if (!mutex_trylock(&chan->mutex)) + if (!mutex_trylock(&drm->client.mutex)) return 0; ret = nouveau_channel_idle(chan); - mutex_unlock(&chan->mutex); + mutex_unlock(&drm->client.mutex); if (ret) { nouveau_fbcon_gpu_lockup(info); return 0; @@ -224,9 +235,9 @@ static void nouveau_fbcon_gamma_get(struct drm_crtc *crtc, u16 *red, u16 *green, } static void -nouveau_fbcon_zfill(struct drm_device *dev, struct nouveau_fbdev *nfbdev) +nouveau_fbcon_zfill(struct drm_device *dev, struct nouveau_fbdev *fbcon) { - struct fb_info *info = nfbdev->helper.fbdev; + struct fb_info *info = fbcon->helper.fbdev; struct fb_fillrect rect; /* Clear the entire fbcon. The drm will program every connector @@ -242,11 +253,12 @@ nouveau_fbcon_zfill(struct drm_device *dev, struct nouveau_fbdev *nfbdev) } static int -nouveau_fbcon_create(struct nouveau_fbdev *nfbdev, +nouveau_fbcon_create(struct nouveau_fbdev *fbcon, struct drm_fb_helper_surface_size *sizes) { - struct drm_device *dev = nfbdev->dev; - struct drm_nouveau_private *dev_priv = dev->dev_private; + struct drm_device *dev = fbcon->dev; + struct nouveau_drm *drm = nouveau_newpriv(dev); + struct nouveau_device *device = nv_device(drm->device); struct fb_info *info; struct drm_framebuffer *fb; struct nouveau_framebuffer *nouveau_fb; @@ -254,7 +266,6 @@ nouveau_fbcon_create(struct nouveau_fbdev *nfbdev, struct nouveau_bo *nvbo; struct drm_mode_fb_cmd2 mode_cmd; struct pci_dev *pdev = dev->pdev; - struct device *device = &pdev->dev; int size, ret; mode_cmd.width = sizes->surface_width; @@ -272,37 +283,38 @@ nouveau_fbcon_create(struct nouveau_fbdev *nfbdev, ret = nouveau_gem_new(dev, size, 0, NOUVEAU_GEM_DOMAIN_VRAM, 0, 0x0000, &nvbo); if (ret) { - NV_ERROR(dev, "failed to allocate framebuffer\n"); + NV_ERROR(drm, "failed to allocate framebuffer\n"); goto out; } ret = nouveau_bo_pin(nvbo, TTM_PL_FLAG_VRAM); if (ret) { - NV_ERROR(dev, "failed to pin fb: %d\n", ret); + NV_ERROR(drm, "failed to pin fb: %d\n", ret); nouveau_bo_ref(NULL, &nvbo); goto out; } ret = nouveau_bo_map(nvbo); if (ret) { - NV_ERROR(dev, "failed to map fb: %d\n", ret); + NV_ERROR(drm, "failed to map fb: %d\n", ret); nouveau_bo_unpin(nvbo); nouveau_bo_ref(NULL, &nvbo); goto out; } - chan = nouveau_nofbaccel ? NULL : dev_priv->channel; - if (chan && dev_priv->card_type >= NV_50) { - ret = nouveau_bo_vma_add(nvbo, chan->vm, &nfbdev->nouveau_fb.vma); + chan = nouveau_nofbaccel ? NULL : drm->channel; + if (chan && device->card_type >= NV_50) { + ret = nouveau_bo_vma_add(nvbo, nv_client(chan->cli)->vm, + &fbcon->nouveau_fb.vma); if (ret) { - NV_ERROR(dev, "failed to map fb into chan: %d\n", ret); + NV_ERROR(drm, "failed to map fb into chan: %d\n", ret); chan = NULL; } } mutex_lock(&dev->struct_mutex); - info = framebuffer_alloc(0, device); + info = framebuffer_alloc(0, &pdev->dev); if (!info) { ret = -ENOMEM; goto out_unref; @@ -314,16 +326,16 @@ nouveau_fbcon_create(struct nouveau_fbdev *nfbdev, goto out_unref; } - info->par = nfbdev; + info->par = fbcon; - nouveau_framebuffer_init(dev, &nfbdev->nouveau_fb, &mode_cmd, nvbo); + nouveau_framebuffer_init(dev, &fbcon->nouveau_fb, &mode_cmd, nvbo); - nouveau_fb = &nfbdev->nouveau_fb; + nouveau_fb = &fbcon->nouveau_fb; fb = &nouveau_fb->base; /* setup helper */ - nfbdev->helper.fb = fb; - nfbdev->helper.fbdev = info; + fbcon->helper.fb = fb; + fbcon->helper.fbdev = info; strcpy(info->fix.id, "nouveaufb"); if (nouveau_nofbaccel) @@ -342,25 +354,18 @@ nouveau_fbcon_create(struct nouveau_fbdev *nfbdev, info->screen_size = size; drm_fb_helper_fill_fix(info, fb->pitches[0], fb->depth); - drm_fb_helper_fill_var(info, &nfbdev->helper, sizes->fb_width, sizes->fb_height); - - /* Set aperture base/size for vesafb takeover */ - info->apertures = dev_priv->apertures; - if (!info->apertures) { - ret = -ENOMEM; - goto out_unref; - } + drm_fb_helper_fill_var(info, &fbcon->helper, sizes->fb_width, sizes->fb_height); /* Use default scratch pixmap (info->pixmap.flags = FB_PIXMAP_SYSTEM) */ mutex_unlock(&dev->struct_mutex); - if (dev_priv->channel && !nouveau_nofbaccel) { + if (chan) { ret = -ENODEV; - if (dev_priv->card_type < NV_50) + if (device->card_type < NV_50) ret = nv04_fbcon_accel_init(info); else - if (dev_priv->card_type < NV_C0) + if (device->card_type < NV_C0) ret = nv50_fbcon_accel_init(info); else ret = nvc0_fbcon_accel_init(info); @@ -369,13 +374,12 @@ nouveau_fbcon_create(struct nouveau_fbdev *nfbdev, info->fbops = &nouveau_fbcon_ops; } - nouveau_fbcon_zfill(dev, nfbdev); + nouveau_fbcon_zfill(dev, fbcon); /* To allow resizeing without swapping buffers */ - NV_INFO(dev, "allocated %dx%d fb: 0x%lx, bo %p\n", - nouveau_fb->base.width, - nouveau_fb->base.height, - nvbo->bo.offset, nvbo); + NV_INFO(drm, "allocated %dx%d fb: 0x%lx, bo %p\n", + nouveau_fb->base.width, nouveau_fb->base.height, + nvbo->bo.offset, nvbo); vga_switcheroo_client_fb_set(dev->pdev, info); return 0; @@ -390,12 +394,12 @@ static int nouveau_fbcon_find_or_create_single(struct drm_fb_helper *helper, struct drm_fb_helper_surface_size *sizes) { - struct nouveau_fbdev *nfbdev = (struct nouveau_fbdev *)helper; + struct nouveau_fbdev *fbcon = (struct nouveau_fbdev *)helper; int new_fb = 0; int ret; if (!helper->fb) { - ret = nouveau_fbcon_create(nfbdev, sizes); + ret = nouveau_fbcon_create(fbcon, sizes); if (ret) return ret; new_fb = 1; @@ -406,18 +410,18 @@ nouveau_fbcon_find_or_create_single(struct drm_fb_helper *helper, void nouveau_fbcon_output_poll_changed(struct drm_device *dev) { - struct drm_nouveau_private *dev_priv = dev->dev_private; - drm_fb_helper_hotplug_event(&dev_priv->nfbdev->helper); + struct nouveau_drm *drm = nouveau_newpriv(dev); + drm_fb_helper_hotplug_event(&drm->fbcon->helper); } static int -nouveau_fbcon_destroy(struct drm_device *dev, struct nouveau_fbdev *nfbdev) +nouveau_fbcon_destroy(struct drm_device *dev, struct nouveau_fbdev *fbcon) { - struct nouveau_framebuffer *nouveau_fb = &nfbdev->nouveau_fb; + struct nouveau_framebuffer *nouveau_fb = &fbcon->nouveau_fb; struct fb_info *info; - if (nfbdev->helper.fbdev) { - info = nfbdev->helper.fbdev; + if (fbcon->helper.fbdev) { + info = fbcon->helper.fbdev; unregister_framebuffer(info); if (info->cmap.len) fb_dealloc_cmap(&info->cmap); @@ -430,17 +434,17 @@ nouveau_fbcon_destroy(struct drm_device *dev, struct nouveau_fbdev *nfbdev) drm_gem_object_unreference_unlocked(nouveau_fb->nvbo->gem); nouveau_fb->nvbo = NULL; } - drm_fb_helper_fini(&nfbdev->helper); + drm_fb_helper_fini(&fbcon->helper); drm_framebuffer_cleanup(&nouveau_fb->base); return 0; } void nouveau_fbcon_gpu_lockup(struct fb_info *info) { - struct nouveau_fbdev *nfbdev = info->par; - struct drm_device *dev = nfbdev->dev; + struct nouveau_fbdev *fbcon = info->par; + struct nouveau_drm *drm = nouveau_newpriv(fbcon->dev); - NV_ERROR(dev, "GPU lockup - switching to software fbcon\n"); + NV_ERROR(drm, "GPU lockup - switching to software fbcon\n"); info->flags |= FBINFO_HWACCEL_DISABLED; } @@ -451,74 +455,81 @@ static struct drm_fb_helper_funcs nouveau_fbcon_helper_funcs = { }; -int nouveau_fbcon_init(struct drm_device *dev) +int +nouveau_fbcon_init(struct drm_device *dev) { - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_fbdev *nfbdev; + struct nouveau_drm *drm = nouveau_newpriv(dev); + struct nouveau_fb *pfb = nouveau_fb(drm->device); + struct nouveau_fbdev *fbcon; int preferred_bpp; int ret; - nfbdev = kzalloc(sizeof(struct nouveau_fbdev), GFP_KERNEL); - if (!nfbdev) + if (!dev->mode_config.num_crtc) + return 0; + + fbcon = kzalloc(sizeof(struct nouveau_fbdev), GFP_KERNEL); + if (!fbcon) return -ENOMEM; - nfbdev->dev = dev; - dev_priv->nfbdev = nfbdev; - nfbdev->helper.funcs = &nouveau_fbcon_helper_funcs; + fbcon->dev = dev; + drm->fbcon = fbcon; + fbcon->helper.funcs = &nouveau_fbcon_helper_funcs; - ret = drm_fb_helper_init(dev, &nfbdev->helper, + ret = drm_fb_helper_init(dev, &fbcon->helper, dev->mode_config.num_crtc, 4); if (ret) { - kfree(nfbdev); + kfree(fbcon); return ret; } - drm_fb_helper_single_add_all_connectors(&nfbdev->helper); + drm_fb_helper_single_add_all_connectors(&fbcon->helper); - if (nvfb_vram_size(dev) <= 32 * 1024 * 1024) + if (pfb->ram.size <= 32 * 1024 * 1024) preferred_bpp = 8; - else if (nvfb_vram_size(dev) <= 64 * 1024 * 1024) + else + if (pfb->ram.size <= 64 * 1024 * 1024) preferred_bpp = 16; else preferred_bpp = 32; - drm_fb_helper_initial_config(&nfbdev->helper, preferred_bpp); + drm_fb_helper_initial_config(&fbcon->helper, preferred_bpp); return 0; } -void nouveau_fbcon_fini(struct drm_device *dev) +void +nouveau_fbcon_fini(struct drm_device *dev) { - struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_drm *drm = nouveau_newpriv(dev); - if (!dev_priv->nfbdev) + if (!drm->fbcon) return; - nouveau_fbcon_destroy(dev, dev_priv->nfbdev); - kfree(dev_priv->nfbdev); - dev_priv->nfbdev = NULL; + nouveau_fbcon_destroy(dev, drm->fbcon); + kfree(drm->fbcon); + drm->fbcon = NULL; } void nouveau_fbcon_save_disable_accel(struct drm_device *dev) { - struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_drm *drm = nouveau_newpriv(dev); - dev_priv->nfbdev->saved_flags = dev_priv->nfbdev->helper.fbdev->flags; - dev_priv->nfbdev->helper.fbdev->flags |= FBINFO_HWACCEL_DISABLED; + drm->fbcon->saved_flags = drm->fbcon->helper.fbdev->flags; + drm->fbcon->helper.fbdev->flags |= FBINFO_HWACCEL_DISABLED; } void nouveau_fbcon_restore_accel(struct drm_device *dev) { - struct drm_nouveau_private *dev_priv = dev->dev_private; - dev_priv->nfbdev->helper.fbdev->flags = dev_priv->nfbdev->saved_flags; + struct nouveau_drm *drm = nouveau_newpriv(dev); + drm->fbcon->helper.fbdev->flags = drm->fbcon->saved_flags; } void nouveau_fbcon_set_suspend(struct drm_device *dev, int state) { - struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_drm *drm = nouveau_newpriv(dev); console_lock(); if (state == 0) nouveau_fbcon_save_disable_accel(dev); - fb_set_suspend(dev_priv->nfbdev->helper.fbdev, state); + fb_set_suspend(drm->fbcon->helper.fbdev, state); if (state == 1) nouveau_fbcon_restore_accel(dev); console_unlock(); @@ -526,6 +537,6 @@ void nouveau_fbcon_set_suspend(struct drm_device *dev, int state) void nouveau_fbcon_zfill_all(struct drm_device *dev) { - struct drm_nouveau_private *dev_priv = dev->dev_private; - nouveau_fbcon_zfill(dev, dev_priv->nfbdev); + struct nouveau_drm *drm = nouveau_newpriv(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 b73c29f87fc3..e6404e39eaf1 100644 --- a/drivers/gpu/drm/nouveau/nouveau_fbcon.h +++ b/drivers/gpu/drm/nouveau/nouveau_fbcon.h @@ -30,6 +30,7 @@ #include "drm_fb_helper.h" #include "nouveau_fb.h" + struct nouveau_fbdev { struct drm_fb_helper helper; struct nouveau_framebuffer nouveau_fb; diff --git a/drivers/gpu/drm/nouveau/nouveau_fence.c b/drivers/gpu/drm/nouveau/nouveau_fence.c index a1835d710f73..5b5471ba6eda 100644 --- a/drivers/gpu/drm/nouveau/nouveau_fence.c +++ b/drivers/gpu/drm/nouveau/nouveau_fence.c @@ -30,11 +30,9 @@ #include #include -#include "nouveau_drv.h" -#include -#include "nouveau_fence.h" -#include "nouveau_software.h" +#include "nouveau_drm.h" #include "nouveau_dma.h" +#include "nouveau_fence.h" void nouveau_fence_context_del(struct nouveau_fence_chan *fctx) @@ -59,12 +57,10 @@ nouveau_fence_context_new(struct nouveau_fence_chan *fctx) spin_lock_init(&fctx->lock); } -void +static void nouveau_fence_update(struct nouveau_channel *chan) { - struct drm_device *dev = chan->dev; - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_fence_priv *priv = dev_priv->fence.func; + struct nouveau_fence_priv *priv = chan->drm->fence; struct nouveau_fence_chan *fctx = chan->fence; struct nouveau_fence *fence, *fnext; @@ -85,9 +81,7 @@ nouveau_fence_update(struct nouveau_channel *chan) int nouveau_fence_emit(struct nouveau_fence *fence, struct nouveau_channel *chan) { - struct drm_device *dev = chan->dev; - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_fence_priv *priv = dev_priv->fence.func; + struct nouveau_fence_priv *priv = chan->drm->fence; struct nouveau_fence_chan *fctx = chan->fence; int ret; @@ -150,20 +144,17 @@ nouveau_fence_wait(struct nouveau_fence *fence, bool lazy, bool intr) int nouveau_fence_sync(struct nouveau_fence *fence, struct nouveau_channel *chan) { - struct drm_device *dev = chan->dev; - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_fence_priv *priv = dev_priv->fence.func; + struct nouveau_fence_priv *priv = chan->drm->fence; struct nouveau_channel *prev; int ret = 0; - prev = fence ? nouveau_channel_get_unlocked(fence->channel) : NULL; + prev = fence ? fence->channel : NULL; if (prev) { if (unlikely(prev != chan && !nouveau_fence_done(fence))) { ret = priv->sync(fence, prev, chan); if (unlikely(ret)) ret = nouveau_fence_wait(fence, true, false); } - nouveau_channel_put_unlocked(&prev); } return ret; diff --git a/drivers/gpu/drm/nouveau/nouveau_fence.h b/drivers/gpu/drm/nouveau/nouveau_fence.h index 8ee65758f24f..bedafd1c9539 100644 --- a/drivers/gpu/drm/nouveau/nouveau_fence.h +++ b/drivers/gpu/drm/nouveau/nouveau_fence.h @@ -1,6 +1,8 @@ #ifndef __NOUVEAU_FENCE_H__ #define __NOUVEAU_FENCE_H__ +struct nouveau_drm; + struct nouveau_fence { struct list_head head; struct kref kref; @@ -22,8 +24,6 @@ int nouveau_fence_emit(struct nouveau_fence *, struct nouveau_channel *); bool nouveau_fence_done(struct nouveau_fence *); int nouveau_fence_wait(struct nouveau_fence *, bool lazy, bool intr); int nouveau_fence_sync(struct nouveau_fence *, struct nouveau_channel *); -void nouveau_fence_idle(struct nouveau_channel *); -void nouveau_fence_update(struct nouveau_channel *); struct nouveau_fence_chan { struct list_head pending; @@ -34,9 +34,9 @@ struct nouveau_fence_chan { }; struct nouveau_fence_priv { - void (*dtor)(struct drm_device *); - bool (*suspend)(struct drm_device *); - void (*resume)(struct drm_device *); + void (*dtor)(struct nouveau_drm *); + bool (*suspend)(struct nouveau_drm *); + void (*resume)(struct nouveau_drm *); int (*context_new)(struct nouveau_channel *); void (*context_del)(struct nouveau_channel *); int (*emit)(struct nouveau_fence *); @@ -45,10 +45,12 @@ struct nouveau_fence_priv { u32 (*read)(struct nouveau_channel *); }; +#define nouveau_fence(drm) ((struct nouveau_fence_priv *)(drm)->fence) + void nouveau_fence_context_new(struct nouveau_fence_chan *); void nouveau_fence_context_del(struct nouveau_fence_chan *); -int nv04_fence_create(struct drm_device *dev); +int nv04_fence_create(struct nouveau_drm *); int nv04_fence_mthd(struct nouveau_channel *, u32, u32, u32); int nv10_fence_emit(struct nouveau_fence *); @@ -56,12 +58,12 @@ int nv17_fence_sync(struct nouveau_fence *, struct nouveau_channel *, struct nouveau_channel *); u32 nv10_fence_read(struct nouveau_channel *); void nv10_fence_context_del(struct nouveau_channel *); -void nv10_fence_destroy(struct drm_device *); -int nv10_fence_create(struct drm_device *dev); +void nv10_fence_destroy(struct nouveau_drm *); +int nv10_fence_create(struct nouveau_drm *); -int nv50_fence_create(struct drm_device *dev); -int nv84_fence_create(struct drm_device *dev); -int nvc0_fence_create(struct drm_device *dev); +int nv50_fence_create(struct nouveau_drm *); +int nv84_fence_create(struct nouveau_drm *); +int nvc0_fence_create(struct nouveau_drm *); u64 nvc0_fence_crtc(struct nouveau_channel *, int crtc); int nouveau_flip_complete(void *chan); diff --git a/drivers/gpu/drm/nouveau/nouveau_gem.c b/drivers/gpu/drm/nouveau/nouveau_gem.c index 96a34bce54ce..ba744daeb50e 100644 --- a/drivers/gpu/drm/nouveau/nouveau_gem.c +++ b/drivers/gpu/drm/nouveau/nouveau_gem.c @@ -23,16 +23,19 @@ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * */ -#include -#include "drmP.h" -#include "drm.h" -#include "nouveau_drv.h" +#include #include + +#include + +#include "nouveau_drm.h" #include "nouveau_dma.h" #include "nouveau_fence.h" +#include "nouveau_abi16.h" -#define nouveau_gem_pushbuf_sync(chan) 0 +#include "nouveau_ttm.h" +#include "nouveau_gem.h" int nouveau_gem_object_new(struct drm_gem_object *gem) @@ -67,19 +70,19 @@ nouveau_gem_object_del(struct drm_gem_object *gem) int nouveau_gem_object_open(struct drm_gem_object *gem, struct drm_file *file_priv) { - struct nouveau_fpriv *fpriv = nouveau_fpriv(file_priv); + struct nouveau_cli *cli = nouveau_cli(file_priv); struct nouveau_bo *nvbo = nouveau_gem_object(gem); struct nouveau_vma *vma; int ret; - if (!fpriv->vm) + if (!cli->base.vm) return 0; ret = ttm_bo_reserve(&nvbo->bo, false, false, false, 0); if (ret) return ret; - vma = nouveau_bo_vma_find(nvbo, fpriv->vm); + vma = nouveau_bo_vma_find(nvbo, cli->base.vm); if (!vma) { vma = kzalloc(sizeof(*vma), GFP_KERNEL); if (!vma) { @@ -87,7 +90,7 @@ nouveau_gem_object_open(struct drm_gem_object *gem, struct drm_file *file_priv) goto out; } - ret = nouveau_bo_vma_add(nvbo, fpriv->vm, vma); + ret = nouveau_bo_vma_add(nvbo, cli->base.vm, vma); if (ret) { kfree(vma); goto out; @@ -104,19 +107,19 @@ out: void nouveau_gem_object_close(struct drm_gem_object *gem, struct drm_file *file_priv) { - struct nouveau_fpriv *fpriv = nouveau_fpriv(file_priv); + struct nouveau_cli *cli = nouveau_cli(file_priv); struct nouveau_bo *nvbo = nouveau_gem_object(gem); struct nouveau_vma *vma; int ret; - if (!fpriv->vm) + if (!cli->base.vm) return; ret = ttm_bo_reserve(&nvbo->bo, false, false, false, 0); if (ret) return; - vma = nouveau_bo_vma_find(nvbo, fpriv->vm); + vma = nouveau_bo_vma_find(nvbo, cli->base.vm); if (vma) { if (--vma->refcount == 0) { nouveau_bo_vma_del(nvbo, vma); @@ -131,7 +134,7 @@ nouveau_gem_new(struct drm_device *dev, int size, int align, uint32_t domain, uint32_t tile_mode, uint32_t tile_flags, struct nouveau_bo **pnvbo) { - struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_drm *drm = nouveau_drm(dev); struct nouveau_bo *nvbo; u32 flags = 0; int ret; @@ -155,7 +158,7 @@ nouveau_gem_new(struct drm_device *dev, int size, int align, uint32_t domain, */ nvbo->valid_domains = NOUVEAU_GEM_DOMAIN_VRAM | NOUVEAU_GEM_DOMAIN_GART; - if (dev_priv->card_type >= NV_50) + if (nv_device(drm->device)->card_type >= NV_50) nvbo->valid_domains &= domain; nvbo->gem = drm_gem_object_alloc(dev, nvbo->bo.mem.size); @@ -173,7 +176,7 @@ static int nouveau_gem_info(struct drm_file *file_priv, struct drm_gem_object *gem, struct drm_nouveau_gem_info *rep) { - struct nouveau_fpriv *fpriv = nouveau_fpriv(file_priv); + struct nouveau_cli *cli = nouveau_cli(file_priv); struct nouveau_bo *nvbo = nouveau_gem_object(gem); struct nouveau_vma *vma; @@ -183,8 +186,8 @@ nouveau_gem_info(struct drm_file *file_priv, struct drm_gem_object *gem, rep->domain = NOUVEAU_GEM_DOMAIN_VRAM; rep->offset = nvbo->bo.offset; - if (fpriv->vm) { - vma = nouveau_bo_vma_find(nvbo, fpriv->vm); + if (cli->base.vm) { + vma = nouveau_bo_vma_find(nvbo, cli->base.vm); if (!vma) return -EINVAL; @@ -202,15 +205,16 @@ int nouveau_gem_ioctl_new(struct drm_device *dev, void *data, struct drm_file *file_priv) { - 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 drm_nouveau_gem_new *req = data; struct nouveau_bo *nvbo = NULL; int ret = 0; - dev_priv->ttm.bdev.dev_mapping = dev->dev_mapping; + drm->ttm.bdev.dev_mapping = drm->dev->dev_mapping; - if (!nvfb_flags_valid(dev, req->info.tile_flags)) { - NV_ERROR(dev, "bad page flags: 0x%08x\n", req->info.tile_flags); + if (!pfb->memtype_valid(pfb, req->info.tile_flags)) { + NV_ERROR(drm, "bad page flags: 0x%08x\n", req->info.tile_flags); return -EINVAL; } @@ -312,16 +316,16 @@ validate_init(struct nouveau_channel *chan, struct drm_file *file_priv, struct drm_nouveau_gem_pushbuf_bo *pbbo, int nr_buffers, struct validate_op *op) { - struct drm_device *dev = chan->dev; - struct drm_nouveau_private *dev_priv = dev->dev_private; + struct drm_device *dev = chan->drm->dev; + struct nouveau_drm *drm = nouveau_drm(dev); uint32_t sequence; int trycnt = 0; int ret, i; - sequence = atomic_add_return(1, &dev_priv->ttm.validate_sequence); + sequence = atomic_add_return(1, &drm->ttm.validate_sequence); retry: if (++trycnt > 100000) { - NV_ERROR(dev, "%s failed and gave up.\n", __func__); + NV_ERROR(drm, "%s failed and gave up.\n", __func__); return -EINVAL; } @@ -332,14 +336,14 @@ retry: gem = drm_gem_object_lookup(dev, file_priv, b->handle); if (!gem) { - NV_ERROR(dev, "Unknown handle 0x%08x\n", b->handle); + NV_ERROR(drm, "Unknown handle 0x%08x\n", b->handle); validate_fini(op, NULL); return -ENOENT; } nvbo = gem->driver_private; if (nvbo->reserved_by && nvbo->reserved_by == file_priv) { - NV_ERROR(dev, "multiple instances of buffer %d on " + NV_ERROR(drm, "multiple instances of buffer %d on " "validation list\n", b->handle); drm_gem_object_unreference_unlocked(gem); validate_fini(op, NULL); @@ -354,7 +358,7 @@ retry: drm_gem_object_unreference_unlocked(gem); if (unlikely(ret)) { if (ret != -ERESTARTSYS) - NV_ERROR(dev, "fail reserve\n"); + NV_ERROR(drm, "fail reserve\n"); return ret; } goto retry; @@ -373,7 +377,7 @@ retry: if (b->valid_domains & NOUVEAU_GEM_DOMAIN_GART) list_add_tail(&nvbo->entry, &op->gart_list); else { - NV_ERROR(dev, "invalid valid domains: 0x%08x\n", + NV_ERROR(drm, "invalid valid domains: 0x%08x\n", b->valid_domains); list_add_tail(&nvbo->entry, &op->both_list); validate_fini(op, NULL); @@ -407,10 +411,9 @@ static int validate_list(struct nouveau_channel *chan, struct list_head *list, struct drm_nouveau_gem_pushbuf_bo *pbbo, uint64_t user_pbbo_ptr) { - struct drm_nouveau_private *dev_priv = chan->dev->dev_private; + struct nouveau_drm *drm = chan->drm; struct drm_nouveau_gem_pushbuf_bo __user *upbbo = (void __force __user *)(uintptr_t)user_pbbo_ptr; - struct drm_device *dev = chan->dev; struct nouveau_bo *nvbo; int ret, relocs = 0; @@ -419,7 +422,7 @@ validate_list(struct nouveau_channel *chan, struct list_head *list, ret = validate_sync(chan, nvbo); if (unlikely(ret)) { - NV_ERROR(dev, "fail pre-validate sync\n"); + NV_ERROR(drm, "fail pre-validate sync\n"); return ret; } @@ -427,24 +430,24 @@ validate_list(struct nouveau_channel *chan, struct list_head *list, b->write_domains, b->valid_domains); if (unlikely(ret)) { - NV_ERROR(dev, "fail set_domain\n"); + NV_ERROR(drm, "fail set_domain\n"); return ret; } ret = nouveau_bo_validate(nvbo, true, false, false); if (unlikely(ret)) { if (ret != -ERESTARTSYS) - NV_ERROR(dev, "fail ttm_validate\n"); + NV_ERROR(drm, "fail ttm_validate\n"); return ret; } ret = validate_sync(chan, nvbo); if (unlikely(ret)) { - NV_ERROR(dev, "fail post-validate sync\n"); + NV_ERROR(drm, "fail post-validate sync\n"); return ret; } - if (dev_priv->card_type < NV_50) { + if (nv_device(drm->device)->card_type < NV_50) { if (nvbo->bo.offset == b->presumed.offset && ((nvbo->bo.mem.mem_type == TTM_PL_VRAM && b->presumed.domain & NOUVEAU_GEM_DOMAIN_VRAM) || @@ -476,7 +479,7 @@ nouveau_gem_pushbuf_validate(struct nouveau_channel *chan, uint64_t user_buffers, int nr_buffers, struct validate_op *op, int *apply_relocs) { - struct drm_device *dev = chan->dev; + struct nouveau_drm *drm = chan->drm; int ret, relocs = 0; INIT_LIST_HEAD(&op->vram_list); @@ -489,14 +492,14 @@ nouveau_gem_pushbuf_validate(struct nouveau_channel *chan, ret = validate_init(chan, file_priv, pbbo, nr_buffers, op); if (unlikely(ret)) { if (ret != -ERESTARTSYS) - NV_ERROR(dev, "validate_init\n"); + NV_ERROR(drm, "validate_init\n"); return ret; } ret = validate_list(chan, &op->vram_list, pbbo, user_buffers); if (unlikely(ret < 0)) { if (ret != -ERESTARTSYS) - NV_ERROR(dev, "validate vram_list\n"); + NV_ERROR(drm, "validate vram_list\n"); validate_fini(op, NULL); return ret; } @@ -505,7 +508,7 @@ nouveau_gem_pushbuf_validate(struct nouveau_channel *chan, ret = validate_list(chan, &op->gart_list, pbbo, user_buffers); if (unlikely(ret < 0)) { if (ret != -ERESTARTSYS) - NV_ERROR(dev, "validate gart_list\n"); + NV_ERROR(drm, "validate gart_list\n"); validate_fini(op, NULL); return ret; } @@ -514,7 +517,7 @@ nouveau_gem_pushbuf_validate(struct nouveau_channel *chan, ret = validate_list(chan, &op->both_list, pbbo, user_buffers); if (unlikely(ret < 0)) { if (ret != -ERESTARTSYS) - NV_ERROR(dev, "validate both_list\n"); + NV_ERROR(drm, "validate both_list\n"); validate_fini(op, NULL); return ret; } @@ -547,6 +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 drm_nouveau_gem_pushbuf_reloc *reloc = NULL; int ret = 0; unsigned i; @@ -562,7 +566,7 @@ nouveau_gem_pushbuf_reloc_apply(struct drm_device *dev, uint32_t data; if (unlikely(r->bo_index > req->nr_buffers)) { - NV_ERROR(dev, "reloc bo index invalid\n"); + NV_ERROR(drm, "reloc bo index invalid\n"); ret = -EINVAL; break; } @@ -572,7 +576,7 @@ nouveau_gem_pushbuf_reloc_apply(struct drm_device *dev, continue; if (unlikely(r->reloc_bo_index > req->nr_buffers)) { - NV_ERROR(dev, "reloc container bo index invalid\n"); + NV_ERROR(drm, "reloc container bo index invalid\n"); ret = -EINVAL; break; } @@ -580,7 +584,7 @@ nouveau_gem_pushbuf_reloc_apply(struct drm_device *dev, if (unlikely(r->reloc_bo_offset + 4 > nvbo->bo.mem.num_pages << PAGE_SHIFT)) { - NV_ERROR(dev, "reloc outside of bo\n"); + NV_ERROR(drm, "reloc outside of bo\n"); ret = -EINVAL; break; } @@ -589,7 +593,7 @@ nouveau_gem_pushbuf_reloc_apply(struct drm_device *dev, ret = ttm_bo_kmap(&nvbo->bo, 0, nvbo->bo.mem.num_pages, &nvbo->kmap); if (ret) { - NV_ERROR(dev, "failed kmap for reloc\n"); + NV_ERROR(drm, "failed kmap for reloc\n"); break; } nvbo->validate_mapped = true; @@ -614,7 +618,7 @@ nouveau_gem_pushbuf_reloc_apply(struct drm_device *dev, ret = ttm_bo_wait(&nvbo->bo, false, false, false); spin_unlock(&nvbo->bo.bdev->fence_lock); if (ret) { - NV_ERROR(dev, "reloc wait_idle failed: %d\n", ret); + NV_ERROR(drm, "reloc wait_idle failed: %d\n", ret); break; } @@ -629,62 +633,67 @@ int nouveau_gem_ioctl_pushbuf(struct drm_device *dev, void *data, struct drm_file *file_priv) { - struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_abi16 *abi16 = nouveau_abi16_get(file_priv, dev); + struct nouveau_abi16_chan *temp; + struct nouveau_drm *drm = nouveau_drm(dev); struct drm_nouveau_gem_pushbuf *req = data; struct drm_nouveau_gem_pushbuf_push *push; struct drm_nouveau_gem_pushbuf_bo *bo; - struct nouveau_channel *chan; + struct nouveau_channel *chan = NULL; struct validate_op op; struct nouveau_fence *fence = NULL; int i, j, ret = 0, do_reloc = 0; - chan = nouveau_channel_get(file_priv, req->channel); - if (IS_ERR(chan)) - return PTR_ERR(chan); + if (unlikely(!abi16)) + return -ENOMEM; - req->vram_available = dev_priv->fb_aper_free; - req->gart_available = dev_priv->gart_info.aper_free; + list_for_each_entry(temp, &abi16->channels, head) { + if (temp->chan->handle == (NVDRM_CHAN | req->channel)) { + chan = temp->chan; + break; + } + } + + if (!chan) + return nouveau_abi16_put(abi16, -ENOENT); + + req->vram_available = drm->gem.vram_available; + req->gart_available = drm->gem.gart_available; if (unlikely(req->nr_push == 0)) goto out_next; if (unlikely(req->nr_push > NOUVEAU_GEM_MAX_PUSH)) { - NV_ERROR(dev, "pushbuf push count exceeds limit: %d max %d\n", + NV_ERROR(drm, "pushbuf push count exceeds limit: %d max %d\n", req->nr_push, NOUVEAU_GEM_MAX_PUSH); - nouveau_channel_put(&chan); - return -EINVAL; + return nouveau_abi16_put(abi16, -EINVAL); } if (unlikely(req->nr_buffers > NOUVEAU_GEM_MAX_BUFFERS)) { - NV_ERROR(dev, "pushbuf bo count exceeds limit: %d max %d\n", + NV_ERROR(drm, "pushbuf bo count exceeds limit: %d max %d\n", req->nr_buffers, NOUVEAU_GEM_MAX_BUFFERS); - nouveau_channel_put(&chan); - return -EINVAL; + return nouveau_abi16_put(abi16, -EINVAL); } if (unlikely(req->nr_relocs > NOUVEAU_GEM_MAX_RELOCS)) { - NV_ERROR(dev, "pushbuf reloc count exceeds limit: %d max %d\n", + NV_ERROR(drm, "pushbuf reloc count exceeds limit: %d max %d\n", req->nr_relocs, NOUVEAU_GEM_MAX_RELOCS); - nouveau_channel_put(&chan); - return -EINVAL; + return nouveau_abi16_put(abi16, -EINVAL); } push = u_memcpya(req->push, req->nr_push, sizeof(*push)); - if (IS_ERR(push)) { - nouveau_channel_put(&chan); - return PTR_ERR(push); - } + if (IS_ERR(push)) + return nouveau_abi16_put(abi16, PTR_ERR(push)); bo = u_memcpya(req->buffers, req->nr_buffers, sizeof(*bo)); if (IS_ERR(bo)) { kfree(push); - nouveau_channel_put(&chan); - return PTR_ERR(bo); + return nouveau_abi16_put(abi16, PTR_ERR(bo)); } /* Ensure all push buffers are on validate list */ for (i = 0; i < req->nr_push; i++) { if (push[i].bo_index >= req->nr_buffers) { - NV_ERROR(dev, "push %d buffer not in list\n", i); + NV_ERROR(drm, "push %d buffer not in list\n", i); ret = -EINVAL; goto out_prevalid; } @@ -695,7 +704,7 @@ nouveau_gem_ioctl_pushbuf(struct drm_device *dev, void *data, req->nr_buffers, &op, &do_reloc); if (ret) { if (ret != -ERESTARTSYS) - NV_ERROR(dev, "validate: %d\n", ret); + NV_ERROR(drm, "validate: %d\n", ret); goto out_prevalid; } @@ -703,7 +712,7 @@ nouveau_gem_ioctl_pushbuf(struct drm_device *dev, void *data, if (do_reloc) { ret = nouveau_gem_pushbuf_reloc_apply(dev, req, bo); if (ret) { - NV_ERROR(dev, "reloc apply: %d\n", ret); + NV_ERROR(drm, "reloc apply: %d\n", ret); goto out; } } @@ -711,7 +720,7 @@ nouveau_gem_ioctl_pushbuf(struct drm_device *dev, void *data, if (chan->dma.ib_max) { ret = nouveau_dma_wait(chan, req->nr_push + 1, 16); if (ret) { - NV_INFO(dev, "nv50cal_space: %d\n", ret); + NV_ERROR(drm, "nv50cal_space: %d\n", ret); goto out; } @@ -723,10 +732,10 @@ nouveau_gem_ioctl_pushbuf(struct drm_device *dev, void *data, push[i].length); } } else - if (dev_priv->chipset >= 0x25) { + if (nv_device(drm->device)->chipset >= 0x25) { ret = RING_SPACE(chan, req->nr_push * 2); if (ret) { - NV_ERROR(dev, "cal_space: %d\n", ret); + NV_ERROR(drm, "cal_space: %d\n", ret); goto out; } @@ -740,7 +749,7 @@ nouveau_gem_ioctl_pushbuf(struct drm_device *dev, void *data, } else { ret = RING_SPACE(chan, req->nr_push * (2 + NOUVEAU_DMA_SKIPS)); if (ret) { - NV_ERROR(dev, "jmp_space: %d\n", ret); + NV_ERROR(drm, "jmp_space: %d\n", ret); goto out; } @@ -749,7 +758,7 @@ nouveau_gem_ioctl_pushbuf(struct drm_device *dev, void *data, bo[push[i].bo_index].user_priv; uint32_t cmd; - cmd = chan->pushbuf_base + ((chan->dma.cur + 2) << 2); + cmd = chan->push.vma.offset + ((chan->dma.cur + 2) << 2); cmd |= 0x20000000; if (unlikely(cmd != req->suffix0)) { if (!nvbo->kmap.virtual) { @@ -778,7 +787,7 @@ nouveau_gem_ioctl_pushbuf(struct drm_device *dev, void *data, ret = nouveau_fence_new(chan, &fence); if (ret) { - NV_ERROR(dev, "error fencing pushbuf: %d\n", ret); + NV_ERROR(drm, "error fencing pushbuf: %d\n", ret); WIND_RING(chan); goto out; } @@ -796,17 +805,16 @@ out_next: req->suffix0 = 0x00000000; req->suffix1 = 0x00000000; } else - if (dev_priv->chipset >= 0x25) { + if (nv_device(drm->device)->chipset >= 0x25) { req->suffix0 = 0x00020000; req->suffix1 = 0x00000000; } else { req->suffix0 = 0x20000000 | - (chan->pushbuf_base + ((chan->dma.cur + 2) << 2)); + (chan->push.vma.offset + ((chan->dma.cur + 2) << 2)); req->suffix1 = 0x00000000; } - nouveau_channel_put(&chan); - return ret; + return nouveau_abi16_put(abi16, ret); } static inline uint32_t diff --git a/drivers/gpu/drm/nouveau/nouveau_gpuobj.c b/drivers/gpu/drm/nouveau/nouveau_gpuobj.c deleted file mode 100644 index a774b7ad0f21..000000000000 --- a/drivers/gpu/drm/nouveau/nouveau_gpuobj.c +++ /dev/null @@ -1,518 +0,0 @@ -/* - * Copyright (C) 2006 Ben Skeggs. - * - * 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. - * - */ - -/* - * Authors: - * Ben Skeggs - */ - -#include "drmP.h" -#include "drm.h" -#include "nouveau_drv.h" -#include -#include -#include -#include "nouveau_software.h" - -struct nouveau_gpuobj_method { - struct list_head head; - u32 mthd; - int (*exec)(struct nouveau_channel *, u32 class, u32 mthd, u32 data); -}; - -struct nouveau_gpuobj_class { - struct list_head head; - struct list_head methods; - u32 id; - u32 engine; -}; - -int -nouveau_gpuobj_class_new(struct drm_device *dev, u32 class, u32 engine) -{ - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_gpuobj_class *oc; - - oc = kzalloc(sizeof(*oc), GFP_KERNEL); - if (!oc) - return -ENOMEM; - - INIT_LIST_HEAD(&oc->methods); - oc->id = class; - oc->engine = engine; - list_add(&oc->head, &dev_priv->classes); - return 0; -} - -int -nouveau_gpuobj_mthd_new(struct drm_device *dev, u32 class, u32 mthd, - int (*exec)(struct nouveau_channel *, u32, u32, u32)) -{ - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_gpuobj_method *om; - struct nouveau_gpuobj_class *oc; - - list_for_each_entry(oc, &dev_priv->classes, head) { - if (oc->id == class) - goto found; - } - - return -EINVAL; - -found: - om = kzalloc(sizeof(*om), GFP_KERNEL); - if (!om) - return -ENOMEM; - - om->mthd = mthd; - om->exec = exec; - list_add(&om->head, &oc->methods); - return 0; -} - -int -nouveau_gpuobj_mthd_call(struct nouveau_channel *chan, - u32 class, u32 mthd, u32 data) -{ - struct drm_nouveau_private *dev_priv = chan->dev->dev_private; - struct nouveau_gpuobj_method *om; - struct nouveau_gpuobj_class *oc; - - list_for_each_entry(oc, &dev_priv->classes, head) { - if (oc->id != class) - continue; - - list_for_each_entry(om, &oc->methods, head) { - if (om->mthd == mthd) - return om->exec(chan, class, mthd, data); - } - } - - return -ENOENT; -} - -int -nouveau_gpuobj_mthd_call2(struct drm_device *dev, int chid, - u32 class, u32 mthd, u32 data) -{ - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_fifo_priv *pfifo = nv_engine(dev, NVOBJ_ENGINE_FIFO); - struct nouveau_channel *chan = NULL; - unsigned long flags; - int ret = -EINVAL; - - spin_lock_irqsave(&dev_priv->channels.lock, flags); - if (chid >= 0 && chid < pfifo->channels) - chan = dev_priv->channels.ptr[chid]; - if (chan) - ret = nouveau_gpuobj_mthd_call(chan, class, mthd, data); - spin_unlock_irqrestore(&dev_priv->channels.lock, flags); - return ret; -} - -void -nv50_gpuobj_dma_init(struct nouveau_gpuobj *obj, u32 offset, int class, - u64 base, u64 size, int target, int access, - u32 type, u32 comp) -{ - struct drm_nouveau_private *dev_priv = obj->dev->dev_private; - u32 flags0; - - flags0 = (comp << 29) | (type << 22) | class; - flags0 |= 0x00100000; - - switch (access) { - case NV_MEM_ACCESS_RO: flags0 |= 0x00040000; break; - case NV_MEM_ACCESS_RW: - case NV_MEM_ACCESS_WO: flags0 |= 0x00080000; break; - default: - break; - } - - switch (target) { - case NV_MEM_TARGET_VRAM: - flags0 |= 0x00010000; - break; - case NV_MEM_TARGET_PCI: - flags0 |= 0x00020000; - break; - case NV_MEM_TARGET_PCI_NOSNOOP: - flags0 |= 0x00030000; - break; - case NV_MEM_TARGET_GART: - base += dev_priv->gart_info.aper_base; - default: - flags0 &= ~0x00100000; - break; - } - - /* convert to base + limit */ - size = (base + size) - 1; - - nv_wo32(obj, offset + 0x00, flags0); - nv_wo32(obj, offset + 0x04, lower_32_bits(size)); - nv_wo32(obj, offset + 0x08, lower_32_bits(base)); - nv_wo32(obj, offset + 0x0c, upper_32_bits(size) << 24 | - upper_32_bits(base)); - nv_wo32(obj, offset + 0x10, 0x00000000); - nv_wo32(obj, offset + 0x14, 0x00000000); - - nvimem_flush(obj->dev); -} - -int -nv50_gpuobj_dma_new(struct nouveau_channel *chan, int class, u64 base, u64 size, - int target, int access, u32 type, u32 comp, - struct nouveau_gpuobj **pobj) -{ - struct drm_device *dev = chan->dev; - int ret; - - ret = nouveau_gpuobj_new(dev, chan, 24, 16, NVOBJ_FLAG_ZERO_FREE, pobj); - if (ret) - return ret; - - nv50_gpuobj_dma_init(*pobj, 0, class, base, size, target, - access, type, comp); - return 0; -} - -int -nouveau_gpuobj_dma_new(struct nouveau_channel *chan, int class, u64 base, - u64 size, int access, int target, - struct nouveau_gpuobj **pobj) -{ - struct drm_nouveau_private *dev_priv = chan->dev->dev_private; - struct drm_device *dev = chan->dev; - struct nouveau_gpuobj *obj; - u32 flags0, flags2; - int ret; - - if (dev_priv->card_type >= NV_50) { - u32 comp = (target == NV_MEM_TARGET_VM) ? NV_MEM_COMP_VM : 0; - u32 type = (target == NV_MEM_TARGET_VM) ? NV_MEM_TYPE_VM : 0; - - return nv50_gpuobj_dma_new(chan, class, base, size, - target, access, type, comp, pobj); - } - - if (target == NV_MEM_TARGET_GART) { - struct nouveau_gpuobj *gart = dev_priv->gart_info.sg_ctxdma; - - if (dev_priv->gart_info.type == NOUVEAU_GART_PDMA) { - if (base == 0) { - nouveau_gpuobj_ref(gart, pobj); - return 0; - } - - base = nouveau_sgdma_get_physical(dev, base); - target = NV_MEM_TARGET_PCI; - } else { - base += dev_priv->gart_info.aper_base; - if (dev_priv->gart_info.type == NOUVEAU_GART_AGP) - target = NV_MEM_TARGET_PCI_NOSNOOP; - else - target = NV_MEM_TARGET_PCI; - } - } - - flags0 = class; - flags0 |= 0x00003000; /* PT present, PT linear */ - flags2 = 0; - - switch (target) { - case NV_MEM_TARGET_PCI: - flags0 |= 0x00020000; - break; - case NV_MEM_TARGET_PCI_NOSNOOP: - flags0 |= 0x00030000; - break; - default: - break; - } - - switch (access) { - case NV_MEM_ACCESS_RO: - flags0 |= 0x00004000; - break; - case NV_MEM_ACCESS_WO: - flags0 |= 0x00008000; - default: - flags2 |= 0x00000002; - break; - } - - flags0 |= (base & 0x00000fff) << 20; - flags2 |= (base & 0xfffff000); - - ret = nouveau_gpuobj_new(dev, chan, 16, 16, NVOBJ_FLAG_ZERO_FREE, &obj); - if (ret) - return ret; - - nv_wo32(obj, 0x00, flags0); - nv_wo32(obj, 0x04, size - 1); - nv_wo32(obj, 0x08, flags2); - nv_wo32(obj, 0x0c, flags2); - - obj->engine = NVOBJ_ENGINE_SW; - obj->class = class; - *pobj = obj; - return 0; -} - -int -nouveau_gpuobj_gr_new(struct nouveau_channel *chan, u32 handle, int class) -{ - struct drm_nouveau_private *dev_priv = chan->dev->dev_private; - struct drm_device *dev = chan->dev; - struct nouveau_gpuobj_class *oc; - int ret; - - NV_DEBUG(dev, "ch%d class=0x%04x\n", chan->id, class); - - list_for_each_entry(oc, &dev_priv->classes, head) { - struct nouveau_exec_engine *eng = dev_priv->eng[oc->engine]; - - if (oc->id != class) - continue; - - if (!chan->engctx[oc->engine]) { - ret = eng->context_new(chan, oc->engine); - if (ret) - return ret; - } - - return eng->object_new(chan, oc->engine, handle, class); - } - - return -EINVAL; -} - -static int -nv04_gpuobj_channel_init_pramin(struct nouveau_channel *chan) -{ - struct drm_device *dev = chan->dev; - int ret; - - ret = nouveau_gpuobj_new(dev, NULL, 0x10000, 0x1000, - NVOBJ_FLAG_ZERO_ALLOC, &chan->ramin); - if (ret) - return ret; - - return 0; -} - -static int -nv50_gpuobj_channel_init_pramin(struct nouveau_channel *chan) -{ - struct drm_device *dev = chan->dev; - int ret; - - ret = nouveau_gpuobj_new(dev, NULL, 0x10000, 0x1000, - NVOBJ_FLAG_ZERO_ALLOC, &chan->ramin); - if (ret) - return ret; - - ret = nouveau_gpuobj_new(dev, chan, 0x0200, 0, 0, &chan->ramfc); - if (ret) - return ret; - - ret = nouveau_gpuobj_new(dev, chan, 0x1000, 0, 0, &chan->engptr); - if (ret) - return ret; - - ret = nouveau_gpuobj_new(dev, chan, 0x4000, 0, 0, &chan->vm_pd); - if (ret) - return ret; - - return 0; -} - -static int -nv84_gpuobj_channel_init_pramin(struct nouveau_channel *chan) -{ - struct drm_device *dev = chan->dev; - int ret; - - ret = nouveau_gpuobj_new(dev, NULL, 0x10000, 0x1000, - NVOBJ_FLAG_ZERO_ALLOC, &chan->ramin); - if (ret) - return ret; - - ret = nouveau_gpuobj_new(dev, chan, 0x0200, 0, 0, &chan->engptr); - if (ret) - return ret; - - ret = nouveau_gpuobj_new(dev, chan, 0x4000, 0, 0, &chan->vm_pd); - if (ret) - return ret; - - return 0; -} - -static int -nvc0_gpuobj_channel_init(struct nouveau_channel *chan, struct nouveau_vm *vm) -{ - struct drm_device *dev = chan->dev; - int ret; - - ret = nouveau_gpuobj_new(dev, NULL, 4096, 0x1000, 0, &chan->ramin); - if (ret) - return ret; - - ret = nouveau_gpuobj_new(dev, NULL, 65536, 0x1000, 0, &chan->vm_pd); - if (ret) - return ret; - - nouveau_vm_ref(vm, &chan->vm, chan->vm_pd); - - nv_wo32(chan->ramin, 0x0200, lower_32_bits(chan->vm_pd->addr)); - nv_wo32(chan->ramin, 0x0204, upper_32_bits(chan->vm_pd->addr)); - nv_wo32(chan->ramin, 0x0208, 0xffffffff); - nv_wo32(chan->ramin, 0x020c, 0x000000ff); - - return 0; -} - -int -nouveau_gpuobj_channel_init(struct nouveau_channel *chan, - uint32_t vram_h, uint32_t tt_h) -{ - struct drm_device *dev = chan->dev; - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_fpriv *fpriv = nouveau_fpriv(chan->file_priv); - struct nouveau_vm *vm = fpriv ? fpriv->vm : dev_priv->chan_vm; - struct nouveau_gpuobj *vram = NULL, *tt = NULL; - int ret; - - NV_DEBUG(dev, "ch%d vram=0x%08x tt=0x%08x\n", chan->id, vram_h, tt_h); - if (dev_priv->card_type >= NV_C0) - return nvc0_gpuobj_channel_init(chan, vm); - - /* Allocate a chunk of memory for per-channel object storage */ - if (dev_priv->chipset >= 0x84) - ret = nv84_gpuobj_channel_init_pramin(chan); - else - if (dev_priv->chipset == 0x50) - ret = nv50_gpuobj_channel_init_pramin(chan); - else - ret = nv04_gpuobj_channel_init_pramin(chan); - if (ret) { - NV_ERROR(dev, "init pramin\n"); - return ret; - } - - /* NV50 VM - * - Allocate per-channel page-directory - * - Link with shared channel VM - */ - if (vm) - nouveau_vm_ref(vm, &chan->vm, chan->vm_pd); - - /* RAMHT */ - if (dev_priv->card_type < NV_50) { - nouveau_ramht_ref(dev_priv->ramht, &chan->ramht, NULL); - } else { - struct nouveau_gpuobj *ramht = NULL; - - ret = nouveau_gpuobj_new(dev, chan, 0x8000, 16, - NVOBJ_FLAG_ZERO_ALLOC, &ramht); - if (ret) - return ret; - - ret = nouveau_ramht_new(dev, ramht, &chan->ramht); - nouveau_gpuobj_ref(NULL, &ramht); - if (ret) - return ret; - } - - /* VRAM ctxdma */ - if (dev_priv->card_type >= NV_50) { - ret = nouveau_gpuobj_dma_new(chan, NV_CLASS_DMA_IN_MEMORY, - 0, (1ULL << 40), NV_MEM_ACCESS_RW, - NV_MEM_TARGET_VM, &vram); - if (ret) { - NV_ERROR(dev, "Error creating VRAM ctxdma: %d\n", ret); - return ret; - } - } else { - ret = nouveau_gpuobj_dma_new(chan, NV_CLASS_DMA_IN_MEMORY, - 0, dev_priv->fb_available_size, - NV_MEM_ACCESS_RW, - NV_MEM_TARGET_VRAM, &vram); - if (ret) { - NV_ERROR(dev, "Error creating VRAM ctxdma: %d\n", ret); - return ret; - } - } - - ret = nouveau_ramht_insert(chan, vram_h, vram); - nouveau_gpuobj_ref(NULL, &vram); - if (ret) { - NV_ERROR(dev, "Error adding VRAM ctxdma to RAMHT: %d\n", ret); - return ret; - } - - /* TT memory ctxdma */ - if (dev_priv->card_type >= NV_50) { - ret = nouveau_gpuobj_dma_new(chan, NV_CLASS_DMA_IN_MEMORY, - 0, (1ULL << 40), NV_MEM_ACCESS_RW, - NV_MEM_TARGET_VM, &tt); - } else { - ret = nouveau_gpuobj_dma_new(chan, NV_CLASS_DMA_IN_MEMORY, - 0, dev_priv->gart_info.aper_size, - NV_MEM_ACCESS_RW, - NV_MEM_TARGET_GART, &tt); - } - - if (ret) { - NV_ERROR(dev, "Error creating TT ctxdma: %d\n", ret); - return ret; - } - - ret = nouveau_ramht_insert(chan, tt_h, tt); - nouveau_gpuobj_ref(NULL, &tt); - if (ret) { - NV_ERROR(dev, "Error adding TT ctxdma to RAMHT: %d\n", ret); - return ret; - } - - return 0; -} - -void -nouveau_gpuobj_channel_takedown(struct nouveau_channel *chan) -{ - NV_DEBUG(chan->dev, "ch%d\n", chan->id); - - nouveau_vm_ref(NULL, &chan->vm, chan->vm_pd); - nouveau_gpuobj_ref(NULL, &chan->vm_pd); - nouveau_gpuobj_ref(NULL, &chan->ramfc); - nouveau_gpuobj_ref(NULL, &chan->engptr); - - nouveau_gpuobj_ref(NULL, &chan->ramin); -} diff --git a/drivers/gpu/drm/nouveau/nouveau_irq.c b/drivers/gpu/drm/nouveau/nouveau_irq.c index 1a75a96cef26..25e2e63cc53a 100644 --- a/drivers/gpu/drm/nouveau/nouveau_irq.c +++ b/drivers/gpu/drm/nouveau/nouveau_irq.c @@ -36,7 +36,6 @@ #include "nouveau_drv.h" #include "nouveau_reg.h" #include -#include "nouveau_util.h" void nouveau_irq_preinstall(struct drm_device *dev) diff --git a/drivers/gpu/drm/nouveau/nouveau_mem.c b/drivers/gpu/drm/nouveau/nouveau_mem.c index 73176bcd1b64..9c35d14fe9d6 100644 --- a/drivers/gpu/drm/nouveau/nouveau_mem.c +++ b/drivers/gpu/drm/nouveau/nouveau_mem.c @@ -37,146 +37,6 @@ #include "nouveau_drv.h" #include "nouveau_pm.h" -#include -#include -#include "nouveau_fence.h" - -/* - * Cleanup everything - */ -void -nouveau_mem_vram_fini(struct drm_device *dev) -{ - struct drm_nouveau_private *dev_priv = dev->dev_private; - - ttm_bo_device_release(&dev_priv->ttm.bdev); - - nouveau_ttm_global_release(dev_priv); - - if (dev_priv->fb_mtrr >= 0) { - drm_mtrr_del(dev_priv->fb_mtrr, - pci_resource_start(dev->pdev, 1), - pci_resource_len(dev->pdev, 1), DRM_MTRR_WC); - dev_priv->fb_mtrr = -1; - } -} - -void -nouveau_mem_gart_fini(struct drm_device *dev) -{ - nouveau_sgdma_takedown(dev); -} - -int -nouveau_mem_vram_init(struct drm_device *dev) -{ - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct ttm_bo_device *bdev = &dev_priv->ttm.bdev; - int ret, dma_bits; - - dma_bits = 32; - if (dev_priv->card_type >= NV_50) { - if (pci_dma_supported(dev->pdev, DMA_BIT_MASK(40))) - dma_bits = 40; - } else - if (0 && pci_is_pcie(dev->pdev) && - dev_priv->chipset > 0x40 && - dev_priv->chipset != 0x45) { - if (pci_dma_supported(dev->pdev, DMA_BIT_MASK(39))) - dma_bits = 39; - } - - ret = pci_set_dma_mask(dev->pdev, DMA_BIT_MASK(dma_bits)); - if (ret) - return ret; - ret = pci_set_consistent_dma_mask(dev->pdev, DMA_BIT_MASK(dma_bits)); - if (ret) { - /* Reset to default value. */ - pci_set_consistent_dma_mask(dev->pdev, DMA_BIT_MASK(32)); - } - - - ret = nouveau_ttm_global_init(dev_priv); - if (ret) - return ret; - - ret = ttm_bo_device_init(&dev_priv->ttm.bdev, - dev_priv->ttm.bo_global_ref.ref.object, - &nouveau_bo_driver, DRM_FILE_PAGE_OFFSET, - dma_bits <= 32 ? true : false); - if (ret) { - NV_ERROR(dev, "Error initialising bo driver: %d\n", ret); - return ret; - } - - dev_priv->fb_available_size = nvfb_vram_size(dev); - dev_priv->fb_mappable_pages = dev_priv->fb_available_size; - if (dev_priv->fb_mappable_pages > pci_resource_len(dev->pdev, 1)) - dev_priv->fb_mappable_pages = pci_resource_len(dev->pdev, 1); - dev_priv->fb_mappable_pages >>= PAGE_SHIFT; - - dev_priv->fb_available_size -= nvimem_reserved(dev); - dev_priv->fb_aper_free = dev_priv->fb_available_size; - - /* mappable vram */ - ret = ttm_bo_init_mm(bdev, TTM_PL_VRAM, - dev_priv->fb_available_size >> PAGE_SHIFT); - if (ret) { - NV_ERROR(dev, "Failed VRAM mm init: %d\n", ret); - return ret; - } - - if (dev_priv->card_type < NV_50) { - ret = nouveau_bo_new(dev, 256*1024, 0, TTM_PL_FLAG_VRAM, - 0, 0, NULL, &dev_priv->vga_ram); - if (ret == 0) - ret = nouveau_bo_pin(dev_priv->vga_ram, - TTM_PL_FLAG_VRAM); - - if (ret) { - NV_WARN(dev, "failed to reserve VGA memory\n"); - nouveau_bo_ref(NULL, &dev_priv->vga_ram); - } - } - - dev_priv->fb_mtrr = drm_mtrr_add(pci_resource_start(dev->pdev, 1), - pci_resource_len(dev->pdev, 1), - DRM_MTRR_WC); - return 0; -} - -int -nouveau_mem_gart_init(struct drm_device *dev) -{ - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct ttm_bo_device *bdev = &dev_priv->ttm.bdev; - int ret; - - 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); - if (ret) { - NV_ERROR(dev, "Error initialising PCI(E): %d\n", ret); - return ret; - } - } - - NV_INFO(dev, "%d MiB GART (aperture)\n", - (int)(dev_priv->gart_info.aper_size >> 20)); - dev_priv->gart_info.aper_free = dev_priv->gart_info.aper_size; - - ret = ttm_bo_init_mm(bdev, TTM_PL_TT, - dev_priv->gart_info.aper_size >> PAGE_SHIFT); - if (ret) { - NV_ERROR(dev, "Failed TT mm init: %d\n", ret); - return ret; - } - - return 0; -} static int nv40_mem_timing_calc(struct drm_device *dev, u32 freq, diff --git a/drivers/gpu/drm/nouveau/nouveau_notifier.c b/drivers/gpu/drm/nouveau/nouveau_notifier.c deleted file mode 100644 index 2cc4779b4299..000000000000 --- a/drivers/gpu/drm/nouveau/nouveau_notifier.c +++ /dev/null @@ -1,151 +0,0 @@ -/* - * Copyright (C) 2007 Ben Skeggs. - * - * 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 "drmP.h" -#include "drm.h" -#include "nouveau_drv.h" -#include - -int -nouveau_notifier_init_channel(struct nouveau_channel *chan) -{ - struct drm_device *dev = chan->dev; - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_bo *ntfy = NULL; - uint32_t flags, ttmpl; - int ret; - - if (nouveau_vram_notify) { - flags = NOUVEAU_GEM_DOMAIN_VRAM; - ttmpl = TTM_PL_FLAG_VRAM; - } else { - flags = NOUVEAU_GEM_DOMAIN_GART; - ttmpl = TTM_PL_FLAG_TT; - } - - ret = nouveau_gem_new(dev, PAGE_SIZE, 0, flags, 0, 0, &ntfy); - if (ret) - return ret; - - ret = nouveau_bo_pin(ntfy, ttmpl); - if (ret) - goto out_err; - - ret = nouveau_bo_map(ntfy); - if (ret) - goto out_err; - - if (dev_priv->card_type >= NV_50) { - ret = nouveau_bo_vma_add(ntfy, chan->vm, &chan->notifier_vma); - if (ret) - goto out_err; - } - - ret = drm_mm_init(&chan->notifier_heap, 0, ntfy->bo.mem.size); - if (ret) - goto out_err; - - chan->notifier_bo = ntfy; -out_err: - if (ret) { - nouveau_bo_vma_del(ntfy, &chan->notifier_vma); - drm_gem_object_unreference_unlocked(ntfy->gem); - } - - return ret; -} - -void -nouveau_notifier_takedown_channel(struct nouveau_channel *chan) -{ - struct drm_device *dev = chan->dev; - - if (!chan->notifier_bo) - return; - - nouveau_bo_vma_del(chan->notifier_bo, &chan->notifier_vma); - nouveau_bo_unmap(chan->notifier_bo); - mutex_lock(&dev->struct_mutex); - nouveau_bo_unpin(chan->notifier_bo); - mutex_unlock(&dev->struct_mutex); - drm_gem_object_unreference_unlocked(chan->notifier_bo->gem); - drm_mm_takedown(&chan->notifier_heap); -} - -int -nouveau_notifier_alloc(struct nouveau_channel *chan, uint32_t handle, - int size, uint32_t start, uint32_t end, - uint32_t *b_offset) -{ - struct drm_device *dev = chan->dev; - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_gpuobj *nobj = NULL; - struct drm_mm_node *mem; - uint64_t offset; - int target, ret; - - mem = drm_mm_search_free_in_range(&chan->notifier_heap, size, 0, - start, end, 0); - if (mem) - mem = drm_mm_get_block_range(mem, size, 0, start, end); - if (!mem) { - NV_ERROR(dev, "Channel %d notifier block full\n", chan->id); - return -ENOMEM; - } - - if (dev_priv->card_type < NV_50) { - if (chan->notifier_bo->bo.mem.mem_type == TTM_PL_VRAM) - target = NV_MEM_TARGET_VRAM; - else - target = NV_MEM_TARGET_GART; - offset = chan->notifier_bo->bo.offset; - } else { - target = NV_MEM_TARGET_VM; - offset = chan->notifier_vma.offset; - } - offset += mem->start; - - ret = nouveau_gpuobj_dma_new(chan, NV_CLASS_DMA_IN_MEMORY, offset, - mem->size, NV_MEM_ACCESS_RW, target, - &nobj); - if (ret) { - drm_mm_put_block(mem); - NV_ERROR(dev, "Error creating notifier ctxdma: %d\n", ret); - return ret; - } - - ret = nouveau_ramht_insert(chan, handle, nobj); - nouveau_gpuobj_ref(NULL, &nobj); - if (ret) { - drm_mm_put_block(mem); - NV_ERROR(dev, "Error adding notifier to ramht: %d\n", ret); - return ret; - } - - *b_offset = mem->start; - return 0; -} diff --git a/drivers/gpu/drm/nouveau/nouveau_prime.c b/drivers/gpu/drm/nouveau/nouveau_prime.c index cce47fa7cb52..de0b81fbdcc1 100644 --- a/drivers/gpu/drm/nouveau/nouveau_prime.c +++ b/drivers/gpu/drm/nouveau/nouveau_prime.c @@ -27,7 +27,6 @@ #include "nouveau_drv.h" #include -#include "nouveau_dma.h" #include diff --git a/drivers/gpu/drm/nouveau/nouveau_revcompat.c b/drivers/gpu/drm/nouveau/nouveau_revcompat.c new file mode 100644 index 000000000000..d5c3390503db --- /dev/null +++ b/drivers/gpu/drm/nouveau/nouveau_revcompat.c @@ -0,0 +1,22 @@ +#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 new file mode 100644 index 000000000000..41cf61f1415f --- /dev/null +++ b/drivers/gpu/drm/nouveau/nouveau_revcompat.h @@ -0,0 +1,12 @@ +#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_sgdma.c b/drivers/gpu/drm/nouveau/nouveau_sgdma.c index 464beda94c58..ca5492ac2da5 100644 --- a/drivers/gpu/drm/nouveau/nouveau_sgdma.c +++ b/drivers/gpu/drm/nouveau/nouveau_sgdma.c @@ -1,11 +1,10 @@ -#include "drmP.h" -#include "nouveau_drv.h" #include #include -#define NV_CTXDMA_PAGE_SHIFT 12 -#define NV_CTXDMA_PAGE_SIZE (1 << NV_CTXDMA_PAGE_SHIFT) -#define NV_CTXDMA_PAGE_MASK (NV_CTXDMA_PAGE_SIZE - 1) +#include + +#include "nouveau_drm.h" +#include "nouveau_ttm.h" struct nouveau_sgdma_be { /* this has to be the first field so populate/unpopulated in @@ -22,7 +21,6 @@ nouveau_sgdma_destroy(struct ttm_tt *ttm) struct nouveau_sgdma_be *nvbe = (struct nouveau_sgdma_be *)ttm; if (ttm) { - NV_DEBUG(nvbe->dev, "\n"); ttm_dma_tt_fini(&nvbe->ttm); kfree(nvbe); } @@ -93,16 +91,18 @@ nouveau_sgdma_create_ttm(struct ttm_bo_device *bdev, unsigned long size, uint32_t page_flags, struct page *dummy_read_page) { - struct drm_nouveau_private *dev_priv = nouveau_bdev(bdev); - struct drm_device *dev = dev_priv->dev; + struct nouveau_drm *drm = nouveau_bdev(bdev); struct nouveau_sgdma_be *nvbe; nvbe = kzalloc(sizeof(*nvbe), GFP_KERNEL); if (!nvbe) return NULL; - nvbe->dev = dev; - nvbe->ttm.ttm.func = dev_priv->gart_info.func; + nvbe->dev = drm->dev; + if (nv_device(drm->device)->card_type < NV_50) + nvbe->ttm.ttm.func = &nv04_sgdma_backend; + else + nvbe->ttm.ttm.func = &nv50_sgdma_backend; if (ttm_dma_tt_init(&nvbe->ttm, bdev, size, page_flags, dummy_read_page)) { kfree(nvbe); @@ -110,51 +110,3 @@ nouveau_sgdma_create_ttm(struct ttm_bo_device *bdev, } return &nvbe->ttm.ttm; } - -int -nouveau_sgdma_init(struct drm_device *dev) -{ - struct drm_nouveau_private *dev_priv = dev->dev_private; - u32 aper_size; - - if (dev_priv->card_type >= NV_50) - aper_size = 512 * 1024 * 1024; - else - aper_size = 128 * 1024 * 1024; - - if (dev_priv->card_type >= NV_50) { - dev_priv->gart_info.aper_base = 0; - dev_priv->gart_info.aper_size = aper_size; - dev_priv->gart_info.type = NOUVEAU_GART_HW; - dev_priv->gart_info.func = &nv50_sgdma_backend; - } else { - dev_priv->gart_info.aper_base = 0; - dev_priv->gart_info.aper_size = aper_size; - dev_priv->gart_info.type = NOUVEAU_GART_PDMA; - dev_priv->gart_info.func = &nv04_sgdma_backend; - dev_priv->gart_info.sg_ctxdma = nv04vm_refdma(dev); - } - - return 0; -} - -void -nouveau_sgdma_takedown(struct drm_device *dev) -{ - struct drm_nouveau_private *dev_priv = dev->dev_private; - - nouveau_gpuobj_ref(NULL, &dev_priv->gart_info.sg_ctxdma); -} - -uint32_t -nouveau_sgdma_get_physical(struct drm_device *dev, uint32_t offset) -{ - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_gpuobj *gpuobj = dev_priv->gart_info.sg_ctxdma; - int pte = (offset >> NV_CTXDMA_PAGE_SHIFT) + 2; - - BUG_ON(dev_priv->card_type >= NV_50); - - return (nv_ro32(gpuobj, 4 * pte) & ~NV_CTXDMA_PAGE_MASK) | - (offset & NV_CTXDMA_PAGE_MASK); -} diff --git a/drivers/gpu/drm/nouveau/nouveau_software.h b/drivers/gpu/drm/nouveau/nouveau_software.h deleted file mode 100644 index 2105a9eef52c..000000000000 --- a/drivers/gpu/drm/nouveau/nouveau_software.h +++ /dev/null @@ -1,60 +0,0 @@ -#ifndef __NOUVEAU_SOFTWARE_H__ -#define __NOUVEAU_SOFTWARE_H__ - -#include "nouveau_fence.h" - -struct nouveau_software_priv { - struct nouveau_exec_engine base; - struct list_head vblank; - spinlock_t peephole_lock; -}; - -struct nouveau_software_chan { - int (*flip)(void *data); - void *flip_data; - - struct { - struct list_head list; - u32 channel; - u32 ctxdma; - u32 offset; - u32 value; - u32 head; - } vblank; -}; - -static inline void -nouveau_software_context_new(struct nouveau_channel *chan, - struct nouveau_software_chan *pch) -{ - pch->flip = nouveau_flip_complete; - pch->flip_data = chan; -} - -static inline void -nouveau_software_create(struct nouveau_software_priv *psw) -{ - INIT_LIST_HEAD(&psw->vblank); - spin_lock_init(&psw->peephole_lock); -} - -static inline u16 -nouveau_software_class(struct drm_device *dev) -{ - struct drm_nouveau_private *dev_priv = dev->dev_private; - if (dev_priv->card_type <= NV_04) - return 0x006e; - if (dev_priv->card_type <= NV_40) - return 0x016e; - if (dev_priv->card_type <= NV_50) - return 0x506e; - if (dev_priv->card_type <= NV_E0) - return 0x906e; - return 0x0000; -} - -int nv04_software_create(struct drm_device *); -int nv50_software_create(struct drm_device *); -int nvc0_software_create(struct drm_device *); - -#endif diff --git a/drivers/gpu/drm/nouveau/nouveau_state.c b/drivers/gpu/drm/nouveau/nouveau_state.c index 5c2836fbf01a..4349b337cfdd 100644 --- a/drivers/gpu/drm/nouveau/nouveau_state.c +++ b/drivers/gpu/drm/nouveau/nouveau_state.c @@ -35,13 +35,9 @@ #include "nouveau_drv.h" #include #include "nouveau_fbcon.h" -#include #include "nouveau_pm.h" #include "nv04_display.h" #include "nv50_display.h" -#include -#include "nouveau_fence.h" -#include "nouveau_software.h" static void nouveau_stub_takedown(struct drm_device *dev) {} static int nouveau_stub_init(struct drm_device *dev) { return 0; } @@ -266,38 +262,6 @@ static bool nouveau_switcheroo_can_switch(struct pci_dev *pdev) return can_switch; } -static void -nouveau_card_channel_fini(struct drm_device *dev) -{ - struct drm_nouveau_private *dev_priv = dev->dev_private; - - if (dev_priv->channel) { - nouveau_channel_put_unlocked(&dev_priv->channel); - nouveau_vm_ref(NULL, &dev_priv->chan_vm, NULL); - } -} - -static int -nouveau_card_channel_init(struct drm_device *dev) -{ - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_channel *chan; - int ret; - - ret = nouveau_vm_new(dev, 0, (1ULL << 40), 0x1000, &dev_priv->chan_vm); - if (ret) - return ret; - - ret = nouveau_channel_alloc(dev, &chan, NULL, NvDmaFB, NvDmaTT); - dev_priv->channel = chan; - if (ret) - return ret; - mutex_unlock(&dev_priv->channel->mutex); - - nouveau_bo_move_init(chan); - return 0; -} - static const struct vga_switcheroo_client_ops nouveau_switcheroo_ops = { .set_gpu_state = nouveau_switcheroo_set_state, .reprobe = nouveau_switcheroo_reprobe, @@ -309,7 +273,7 @@ nouveau_card_init(struct drm_device *dev) { struct drm_nouveau_private *dev_priv = dev->dev_private; struct nouveau_engine *engine; - int ret, e = 0; + int ret; vga_client_register(dev->pdev, dev, NULL, nouveau_vga_set_decode); vga_switcheroo_register_client(dev->pdev, &nouveau_switcheroo_ops); @@ -319,11 +283,7 @@ nouveau_card_init(struct drm_device *dev) if (ret) goto out; engine = &dev_priv->engine; - spin_lock_init(&dev_priv->channels.lock); - spin_lock_init(&dev_priv->tile.lock); spin_lock_init(&dev_priv->context_switch_lock); - spin_lock_init(&dev_priv->vm_lock); - INIT_LIST_HEAD(&dev_priv->classes); /* Make the CRTCs and I2C buses accessible */ ret = engine->display.early_init(dev); @@ -343,187 +303,9 @@ nouveau_card_init(struct drm_device *dev) nv_mask(dev, 0x00088080, 0x00000800, 0x00000000); } - ret = nouveau_mem_vram_init(dev); - if (ret) - goto out_bios; - - ret = nouveau_mem_gart_init(dev); - if (ret) - goto out_ttmvram; - - if (!dev_priv->noaccel) { - switch (dev_priv->card_type) { - case NV_04: - nv04_fifo_create(dev); - break; - case NV_10: - case NV_20: - case NV_30: - if (dev_priv->chipset < 0x17) - nv10_fifo_create(dev); - else - nv17_fifo_create(dev); - break; - case NV_40: - nv40_fifo_create(dev); - break; - case NV_50: - if (dev_priv->chipset == 0x50) - nv50_fifo_create(dev); - else - nv84_fifo_create(dev); - break; - case NV_C0: - case NV_D0: - nvc0_fifo_create(dev); - break; - case NV_E0: - nve0_fifo_create(dev); - break; - default: - break; - } - - switch (dev_priv->card_type) { - case NV_04: - nv04_fence_create(dev); - break; - case NV_10: - case NV_20: - case NV_30: - case NV_40: - case NV_50: - if (dev_priv->chipset < 0x84) - nv50_fence_create(dev); - else - nv84_fence_create(dev); - break; - case NV_C0: - case NV_D0: - case NV_E0: - nvc0_fence_create(dev); - break; - default: - break; - } - - switch (dev_priv->card_type) { - case NV_04: - case NV_10: - case NV_20: - case NV_30: - case NV_40: - nv04_software_create(dev); - break; - case NV_50: - nv50_software_create(dev); - break; - case NV_C0: - case NV_D0: - case NV_E0: - nvc0_software_create(dev); - break; - default: - break; - } - - switch (dev_priv->card_type) { - case NV_04: - nv04_graph_create(dev); - break; - case NV_10: - nv10_graph_create(dev); - break; - case NV_20: - case NV_30: - nv20_graph_create(dev); - break; - case NV_40: - nv40_graph_create(dev); - break; - case NV_50: - nv50_graph_create(dev); - break; - case NV_C0: - case NV_D0: - nvc0_graph_create(dev); - break; - case NV_E0: - nve0_graph_create(dev); - break; - default: - break; - } - - switch (dev_priv->chipset) { - case 0x84: - case 0x86: - case 0x92: - case 0x94: - case 0x96: - case 0xa0: - nv84_crypt_create(dev); - break; - case 0x98: - case 0xaa: - case 0xac: - nv98_crypt_create(dev); - break; - } - - switch (dev_priv->card_type) { - case NV_50: - switch (dev_priv->chipset) { - case 0xa3: - case 0xa5: - case 0xa8: - nva3_copy_create(dev); - break; - } - break; - case NV_C0: - if (!(nv_rd32(dev, 0x022500) & 0x00000200)) - nvc0_copy_create(dev, 1); - case NV_D0: - if (!(nv_rd32(dev, 0x022500) & 0x00000100)) - nvc0_copy_create(dev, 0); - break; - default: - break; - } - - if (dev_priv->chipset >= 0xa3 || dev_priv->chipset == 0x98) { - nv84_bsp_create(dev); - nv84_vp_create(dev); - nv98_ppp_create(dev); - } else - if (dev_priv->chipset >= 0x84) { - nv50_mpeg_create(dev); - nv84_bsp_create(dev); - nv84_vp_create(dev); - } else - if (dev_priv->chipset >= 0x50) { - nv50_mpeg_create(dev); - } else - if (dev_priv->card_type == NV_40 || - dev_priv->chipset == 0x31 || - dev_priv->chipset == 0x34 || - dev_priv->chipset == 0x36) { - nv31_mpeg_create(dev); - } - - for (e = 0; e < NVOBJ_ENGINE_NR; e++) { - if (dev_priv->eng[e]) { - ret = dev_priv->eng[e]->init(dev, e); - if (ret) - goto out_engine; - } - } - } - ret = nouveau_irq_init(dev); if (ret) - goto out_engine; + goto out_bios; ret = nouveau_display_create(dev); if (ret) @@ -532,42 +314,20 @@ nouveau_card_init(struct drm_device *dev) nouveau_backlight_init(dev); nouveau_pm_init(dev); - if (dev_priv->eng[NVOBJ_ENGINE_GR]) { - ret = nouveau_card_channel_init(dev); - if (ret) - goto out_pm; - } - if (dev->mode_config.num_crtc) { ret = nouveau_display_init(dev); if (ret) - goto out_chan; - - nouveau_fbcon_init(dev); + goto out_pm; } return 0; -out_chan: - nouveau_card_channel_fini(dev); out_pm: nouveau_pm_fini(dev); nouveau_backlight_exit(dev); nouveau_display_destroy(dev); out_irq: nouveau_irq_fini(dev); -out_engine: - if (!dev_priv->noaccel) { - for (e = e - 1; e >= 0; e--) { - if (!dev_priv->eng[e]) - continue; - dev_priv->eng[e]->fini(dev, e, false); - dev_priv->eng[e]->destroy(dev,e ); - } - } - nouveau_mem_gart_fini(dev); -out_ttmvram: - nouveau_mem_vram_fini(dev); out_bios: nouveau_bios_takedown(dev); out_display_early: @@ -582,39 +342,19 @@ 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; - int e; - if (dev->mode_config.num_crtc) { - nouveau_fbcon_fini(dev); + if (dev->mode_config.num_crtc) nouveau_display_fini(dev); - } - nouveau_card_channel_fini(dev); nouveau_pm_fini(dev); nouveau_backlight_exit(dev); nouveau_display_destroy(dev); - if (!dev_priv->noaccel) { - for (e = NVOBJ_ENGINE_NR - 1; e >= 0; e--) { - if (dev_priv->eng[e]) { - dev_priv->eng[e]->fini(dev, e, false); - dev_priv->eng[e]->destroy(dev,e ); - } - } - } - if (dev_priv->vga_ram) { nouveau_bo_unpin(dev_priv->vga_ram); nouveau_bo_ref(NULL, &dev_priv->vga_ram); } - mutex_lock(&dev->struct_mutex); - ttm_bo_clean_mm(&dev_priv->ttm.bdev, TTM_PL_VRAM); - ttm_bo_clean_mm(&dev_priv->ttm.bdev, TTM_PL_TT); - mutex_unlock(&dev->struct_mutex); - nouveau_mem_gart_fini(dev); - nouveau_mem_vram_fini(dev); - nouveau_bios_takedown(dev); engine->display.late_takedown(dev); @@ -624,56 +364,6 @@ static void nouveau_card_takedown(struct drm_device *dev) vga_client_register(dev->pdev, NULL, NULL, NULL); } -int -nouveau_open(struct drm_device *dev, struct drm_file *file_priv) -{ - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_fpriv *fpriv; - int ret; - - fpriv = kzalloc(sizeof(*fpriv), GFP_KERNEL); - if (unlikely(!fpriv)) - return -ENOMEM; - - spin_lock_init(&fpriv->lock); - INIT_LIST_HEAD(&fpriv->channels); - - if (dev_priv->card_type == NV_50) { - ret = nouveau_vm_new(dev, 0, (1ULL << 40), 0x0020000000ULL, - &fpriv->vm); - if (ret) { - kfree(fpriv); - return ret; - } - } else - if (dev_priv->card_type >= NV_C0) { - ret = nouveau_vm_new(dev, 0, (1ULL << 40), 0x0008000000ULL, - &fpriv->vm); - if (ret) { - kfree(fpriv); - return ret; - } - } - - file_priv->driver_priv = fpriv; - return 0; -} - -/* here a client dies, release the stuff that was allocated for its - * file_priv */ -void nouveau_preclose(struct drm_device *dev, struct drm_file *file_priv) -{ - nouveau_channel_cleanup(dev, file_priv); -} - -void -nouveau_postclose(struct drm_device *dev, struct drm_file *file_priv) -{ - struct nouveau_fpriv *fpriv = nouveau_fpriv(file_priv); - nouveau_vm_ref(NULL, &fpriv->vm, NULL); - kfree(fpriv); -} - /* 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) @@ -704,55 +394,6 @@ static void nouveau_OF_copy_vbios_to_ramin(struct drm_device *dev) #endif } -static struct apertures_struct *nouveau_get_apertures(struct drm_device *dev) -{ - struct pci_dev *pdev = dev->pdev; - struct apertures_struct *aper = alloc_apertures(3); - if (!aper) - return NULL; - - aper->ranges[0].base = pci_resource_start(pdev, 1); - aper->ranges[0].size = pci_resource_len(pdev, 1); - aper->count = 1; - - if (pci_resource_len(pdev, 2)) { - aper->ranges[aper->count].base = pci_resource_start(pdev, 2); - aper->ranges[aper->count].size = pci_resource_len(pdev, 2); - aper->count++; - } - - if (pci_resource_len(pdev, 3)) { - aper->ranges[aper->count].base = pci_resource_start(pdev, 3); - aper->ranges[aper->count].size = pci_resource_len(pdev, 3); - aper->count++; - } - - return aper; -} - -static int nouveau_remove_conflicting_drivers(struct drm_device *dev) -{ - struct drm_nouveau_private *dev_priv = dev->dev_private; - bool primary = false; - dev_priv->apertures = nouveau_get_apertures(dev); - if (!dev_priv->apertures) - return -ENOMEM; - -#ifdef CONFIG_X86 - primary = dev->pdev->resource[PCI_ROM_RESOURCE].flags & IORESOURCE_ROM_SHADOW; -#endif - - remove_conflicting_framebuffers(dev_priv->apertures, "nouveaufb", primary); - return 0; -} - -void * -nouveau_newpriv(struct drm_device *dev) -{ - struct drm_nouveau_private *dev_priv = dev->dev_private; - return dev_priv->newpriv; -} - int nouveau_load(struct drm_device *dev, unsigned long flags) { struct drm_nouveau_private *dev_priv; @@ -840,30 +481,6 @@ int nouveau_load(struct drm_device *dev, unsigned long flags) NV_DEBUG(dev, "crystal freq: %dKHz\n", dev_priv->crystal); - /* Determine whether we'll attempt acceleration or not, some - * cards are disabled by default here due to them being known - * non-functional, or never been tested due to lack of hw. - */ - dev_priv->noaccel = !!nouveau_noaccel; - if (nouveau_noaccel == -1) { - switch (dev_priv->chipset) { - case 0xd9: /* known broken */ - case 0xe4: /* needs binary driver firmware */ - case 0xe7: /* needs binary driver firmware */ - NV_INFO(dev, "acceleration disabled by default, pass " - "noaccel=0 to force enable\n"); - dev_priv->noaccel = true; - break; - default: - dev_priv->noaccel = false; - break; - } - } - - ret = nouveau_remove_conflicting_drivers(dev); - if (ret) - goto err_priv; - nouveau_OF_copy_vbios_to_ramin(dev); /* Special flags */ diff --git a/drivers/gpu/drm/nouveau/nouveau_ttm.c b/drivers/gpu/drm/nouveau/nouveau_ttm.c index e729535e9b26..560e816138eb 100644 --- a/drivers/gpu/drm/nouveau/nouveau_ttm.c +++ b/drivers/gpu/drm/nouveau/nouveau_ttm.c @@ -24,9 +24,13 @@ * USE OR OTHER DEALINGS IN THE SOFTWARE. */ -#include "drmP.h" +#include +#include +#include -#include "nouveau_drv.h" +#include "nouveau_drm.h" +#include "nouveau_ttm.h" +#include "nouveau_gem.h" static int nouveau_vram_manager_init(struct ttm_mem_type_manager *man, unsigned long psize) @@ -60,11 +64,10 @@ static void nouveau_vram_manager_del(struct ttm_mem_type_manager *man, struct ttm_mem_reg *mem) { - struct drm_nouveau_private *dev_priv = nouveau_bdev(man->bdev); - struct drm_device *dev = dev_priv->dev; - + struct nouveau_drm *drm = nouveau_bdev(man->bdev); + struct nouveau_fb *pfb = nouveau_fb(drm->device); nouveau_mem_node_cleanup(mem->mm_node); - nvfb_vram_put(dev, (struct nouveau_mem **)&mem->mm_node); + pfb->ram.put(pfb, (struct nouveau_mem **)&mem->mm_node); } static int @@ -73,8 +76,8 @@ nouveau_vram_manager_new(struct ttm_mem_type_manager *man, struct ttm_placement *placement, struct ttm_mem_reg *mem) { - struct drm_nouveau_private *dev_priv = nouveau_bdev(man->bdev); - struct drm_device *dev = dev_priv->dev; + struct nouveau_drm *drm = nouveau_bdev(man->bdev); + struct nouveau_fb *pfb = nouveau_fb(drm->device); struct nouveau_bo *nvbo = nouveau_bo(bo); struct nouveau_mem *node; u32 size_nc = 0; @@ -83,9 +86,9 @@ nouveau_vram_manager_new(struct ttm_mem_type_manager *man, if (nvbo->tile_flags & NOUVEAU_GEM_TILE_NONCONTIG) size_nc = 1 << nvbo->page_shift; - ret = nvfb_vram_get(dev, mem->num_pages << PAGE_SHIFT, - mem->page_alignment << PAGE_SHIFT, size_nc, - (nvbo->tile_flags >> 8) & 0x3ff, &node); + ret = pfb->ram.get(pfb, mem->num_pages << PAGE_SHIFT, + mem->page_alignment << PAGE_SHIFT, size_nc, + (nvbo->tile_flags >> 8) & 0x3ff, &node); if (ret) { mem->mm_node = NULL; return (ret == -ENOSPC) ? 0 : ret; @@ -158,11 +161,9 @@ nouveau_gart_manager_new(struct ttm_mem_type_manager *man, struct ttm_placement *placement, struct ttm_mem_reg *mem) { - struct drm_nouveau_private *dev_priv = nouveau_bdev(bo->bdev); struct nouveau_mem *node; - if (unlikely((mem->num_pages << PAGE_SHIFT) >= - dev_priv->gart_info.aper_size)) + if (unlikely((mem->num_pages << PAGE_SHIFT) >= 512 * 1024 * 1024)) return -ENOMEM; node = kzalloc(sizeof(*node), GFP_KERNEL); @@ -188,13 +189,17 @@ const struct ttm_mem_type_manager_func nouveau_gart_manager = { nouveau_gart_manager_debug }; +#include static int nv04_gart_manager_init(struct ttm_mem_type_manager *man, unsigned long psize) { - struct drm_nouveau_private *dev_priv = nouveau_bdev(man->bdev); - struct drm_device *dev = dev_priv->dev; - man->priv = nv04vm_ref(dev); - return (man->priv != NULL) ? 0 : -ENODEV; + struct nouveau_drm *drm = nouveau_bdev(man->bdev); + struct nouveau_vmmgr *vmm = nouveau_vmmgr(drm->device); + struct nv04_vmmgr_priv *priv = (void *)vmm; + struct nouveau_vm *vm = NULL; + nouveau_vm_ref(priv->vm, &vm, NULL); + man->priv = vm; + return 0; } static int @@ -260,13 +265,12 @@ int nouveau_ttm_mmap(struct file *filp, struct vm_area_struct *vma) { struct drm_file *file_priv = filp->private_data; - struct drm_nouveau_private *dev_priv = - file_priv->minor->dev->dev_private; + struct nouveau_drm *drm = nouveau_newpriv(file_priv->minor->dev); if (unlikely(vma->vm_pgoff < DRM_FILE_PAGE_OFFSET)) return drm_mmap(filp, vma); - return ttm_bo_mmap(filp, vma, &dev_priv->ttm.bdev); + return ttm_bo_mmap(filp, vma, &drm->ttm.bdev); } static int @@ -282,12 +286,12 @@ nouveau_ttm_mem_global_release(struct drm_global_reference *ref) } int -nouveau_ttm_global_init(struct drm_nouveau_private *dev_priv) +nouveau_ttm_global_init(struct nouveau_drm *drm) { struct drm_global_reference *global_ref; int ret; - global_ref = &dev_priv->ttm.mem_global_ref; + global_ref = &drm->ttm.mem_global_ref; global_ref->global_type = DRM_GLOBAL_TTM_MEM; global_ref->size = sizeof(struct ttm_mem_global); global_ref->init = &nouveau_ttm_mem_global_init; @@ -296,12 +300,12 @@ nouveau_ttm_global_init(struct drm_nouveau_private *dev_priv) ret = drm_global_item_ref(global_ref); if (unlikely(ret != 0)) { DRM_ERROR("Failed setting up TTM memory accounting\n"); - dev_priv->ttm.mem_global_ref.release = NULL; + drm->ttm.mem_global_ref.release = NULL; return ret; } - dev_priv->ttm.bo_global_ref.mem_glob = global_ref->object; - global_ref = &dev_priv->ttm.bo_global_ref.ref; + drm->ttm.bo_global_ref.mem_glob = global_ref->object; + global_ref = &drm->ttm.bo_global_ref.ref; global_ref->global_type = DRM_GLOBAL_TTM_BO; global_ref->size = sizeof(struct ttm_bo_global); global_ref->init = &ttm_bo_global_init; @@ -310,8 +314,8 @@ nouveau_ttm_global_init(struct drm_nouveau_private *dev_priv) ret = drm_global_item_ref(global_ref); if (unlikely(ret != 0)) { DRM_ERROR("Failed setting up TTM BO subsystem\n"); - drm_global_item_unref(&dev_priv->ttm.mem_global_ref); - dev_priv->ttm.mem_global_ref.release = NULL; + drm_global_item_unref(&drm->ttm.mem_global_ref); + drm->ttm.mem_global_ref.release = NULL; return ret; } @@ -319,12 +323,105 @@ nouveau_ttm_global_init(struct drm_nouveau_private *dev_priv) } void -nouveau_ttm_global_release(struct drm_nouveau_private *dev_priv) +nouveau_ttm_global_release(struct nouveau_drm *drm) { - if (dev_priv->ttm.mem_global_ref.release == NULL) + if (drm->ttm.mem_global_ref.release == NULL) return; - drm_global_item_unref(&dev_priv->ttm.bo_global_ref.ref); - drm_global_item_unref(&dev_priv->ttm.mem_global_ref); - dev_priv->ttm.mem_global_ref.release = NULL; + drm_global_item_unref(&drm->ttm.bo_global_ref.ref); + drm_global_item_unref(&drm->ttm.mem_global_ref); + drm->ttm.mem_global_ref.release = NULL; +} + +int +nouveau_ttm_init(struct nouveau_drm *drm) +{ + struct drm_device *dev = drm->dev; + u32 bits; + int ret; + + if (nv_device(drm->device)->card_type >= NV_50) { + if (pci_dma_supported(dev->pdev, DMA_BIT_MASK(40))) + bits = 40; + else + bits = 32; + } else { + bits = 32; + } + + ret = pci_set_dma_mask(dev->pdev, DMA_BIT_MASK(bits)); + if (ret) + return ret; + + ret = pci_set_consistent_dma_mask(dev->pdev, DMA_BIT_MASK(bits)); + if (ret) + pci_set_consistent_dma_mask(dev->pdev, DMA_BIT_MASK(32)); + + ret = nouveau_ttm_global_init(drm); + if (ret) + return ret; + + ret = ttm_bo_device_init(&drm->ttm.bdev, + drm->ttm.bo_global_ref.ref.object, + &nouveau_bo_driver, DRM_FILE_PAGE_OFFSET, + bits <= 32 ? true : false); + if (ret) { + NV_ERROR(drm, "error initialising bo driver, %d\n", ret); + return ret; + } + + /* VRAM init */ + drm->gem.vram_available = nouveau_fb(drm->device)->ram.size; + drm->gem.vram_available -= nouveau_instmem(drm->device)->reserved; + + ret = ttm_bo_init_mm(&drm->ttm.bdev, TTM_PL_VRAM, + drm->gem.vram_available >> PAGE_SHIFT); + if (ret) { + NV_ERROR(drm, "VRAM mm init failed, %d\n", ret); + return ret; + } + + drm->ttm.mtrr = drm_mtrr_add(pci_resource_start(dev->pdev, 1), + pci_resource_len(dev->pdev, 1), + DRM_MTRR_WC); + + /* GART init */ + if (drm->agp.stat != ENABLED) { + drm->gem.gart_available = nouveau_vmmgr(drm->device)->limit; + if (drm->gem.gart_available > 512 * 1024 * 1024) + drm->gem.gart_available = 512 * 1024 * 1024; + } else { + drm->gem.gart_available = drm->agp.size; + } + + ret = ttm_bo_init_mm(&drm->ttm.bdev, TTM_PL_TT, + drm->gem.gart_available >> PAGE_SHIFT); + if (ret) { + NV_ERROR(drm, "GART mm init failed, %d\n", ret); + return ret; + } + + NV_INFO(drm, "VRAM: %d MiB\n", (u32)(drm->gem.vram_available >> 20)); + NV_INFO(drm, "GART: %d MiB\n", (u32)(drm->gem.gart_available >> 20)); + return 0; +} + +void +nouveau_ttm_fini(struct nouveau_drm *drm) +{ + mutex_lock(&drm->dev->struct_mutex); + ttm_bo_clean_mm(&drm->ttm.bdev, TTM_PL_VRAM); + ttm_bo_clean_mm(&drm->ttm.bdev, TTM_PL_TT); + mutex_unlock(&drm->dev->struct_mutex); + + ttm_bo_device_release(&drm->ttm.bdev); + + nouveau_ttm_global_release(drm); + + if (drm->ttm.mtrr >= 0) { + drm_mtrr_del(drm->ttm.mtrr, + pci_resource_start(drm->dev->pdev, 1), + pci_resource_len(drm->dev->pdev, 1), DRM_MTRR_WC); + drm->ttm.mtrr = -1; + } } diff --git a/drivers/gpu/drm/nouveau/nouveau_ttm.h b/drivers/gpu/drm/nouveau/nouveau_ttm.h new file mode 100644 index 000000000000..9f4d2715584b --- /dev/null +++ b/drivers/gpu/drm/nouveau/nouveau_ttm.h @@ -0,0 +1,21 @@ +#ifndef __NOUVEAU_TTM_H__ +#define __NOUVEAU_TTM_H__ + +static inline struct nouveau_drm * +nouveau_bdev(struct ttm_bo_device *bd) +{ + return container_of(bd, struct nouveau_drm, ttm.bdev); +} + +extern const struct ttm_mem_type_manager_func nouveau_vram_manager; +extern const struct ttm_mem_type_manager_func nouveau_gart_manager; +extern const struct ttm_mem_type_manager_func nv04_gart_manager; + +struct ttm_tt *nouveau_sgdma_create_ttm(struct ttm_bo_device *, + unsigned long size, u32 page_flags, + struct page *dummy_read_page); + +int nouveau_ttm_init(struct nouveau_drm *drm); +void nouveau_ttm_fini(struct nouveau_drm *drm); + +#endif diff --git a/drivers/gpu/drm/nouveau/nouveau_util.c b/drivers/gpu/drm/nouveau/nouveau_util.c deleted file mode 100644 index 6bff634c95fe..000000000000 --- a/drivers/gpu/drm/nouveau/nouveau_util.c +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright (C) 2010 Nouveau Project - * - * 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 "nouveau_util.h" - -#include - -static DEFINE_RATELIMIT_STATE(nouveau_ratelimit_state, 3 * HZ, 20); - -int -nouveau_ratelimit(void) -{ - return __ratelimit(&nouveau_ratelimit_state); -} diff --git a/drivers/gpu/drm/nouveau/nouveau_util.h b/drivers/gpu/drm/nouveau/nouveau_util.h deleted file mode 100644 index 114293758f8c..000000000000 --- a/drivers/gpu/drm/nouveau/nouveau_util.h +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright (C) 2010 Nouveau Project - * - * 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_UTIL_H__ -#define __NOUVEAU_UTIL_H__ - -#include - -int nouveau_ratelimit(void); - -#endif diff --git a/drivers/gpu/drm/nouveau/nv04_display.c b/drivers/gpu/drm/nouveau/nv04_display.c index 81947ea0f82d..6ab936376c40 100644 --- a/drivers/gpu/drm/nouveau/nv04_display.c +++ b/drivers/gpu/drm/nouveau/nv04_display.c @@ -32,9 +32,6 @@ #include "nouveau_encoder.h" #include "nouveau_connector.h" -static void nv04_vblank_crtc0_isr(struct drm_device *); -static void nv04_vblank_crtc1_isr(struct drm_device *); - int nv04_display_early_init(struct drm_device *dev) { @@ -126,8 +123,6 @@ nv04_display_create(struct drm_device *dev) func->save(encoder); } - nouveau_irq_register(dev, 24, nv04_vblank_crtc0_isr); - nouveau_irq_register(dev, 25, nv04_vblank_crtc1_isr); return 0; } @@ -141,9 +136,6 @@ nv04_display_destroy(struct drm_device *dev) NV_DEBUG_KMS(dev, "\n"); - nouveau_irq_unregister(dev, 24); - nouveau_irq_unregister(dev, 25); - /* Turn every CRTC off. */ list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { struct drm_mode_set modeset = { @@ -203,17 +195,3 @@ nv04_display_fini(struct drm_device *dev) if (nv_two_heads(dev)) NVWriteCRTC(dev, 1, NV_PCRTC_INTR_EN_0, 0); } - -static void -nv04_vblank_crtc0_isr(struct drm_device *dev) -{ - nv_wr32(dev, NV_CRTC0_INTSTAT, NV_CRTC_INTR_VBLANK); - drm_handle_vblank(dev, 0); -} - -static void -nv04_vblank_crtc1_isr(struct drm_device *dev) -{ - nv_wr32(dev, NV_CRTC1_INTSTAT, NV_CRTC_INTR_VBLANK); - drm_handle_vblank(dev, 1); -} diff --git a/drivers/gpu/drm/nouveau/nv04_fbcon.c b/drivers/gpu/drm/nouveau/nv04_fbcon.c index 06fb68acf813..35480b6776f8 100644 --- a/drivers/gpu/drm/nouveau/nv04_fbcon.c +++ b/drivers/gpu/drm/nouveau/nv04_fbcon.c @@ -22,19 +22,18 @@ * DEALINGS IN THE SOFTWARE. */ -#include "drmP.h" -#include "nouveau_drv.h" +#include + +#include "nouveau_drm.h" #include "nouveau_dma.h" -#include #include "nouveau_fbcon.h" int nv04_fbcon_copyarea(struct fb_info *info, const struct fb_copyarea *region) { struct nouveau_fbdev *nfbdev = info->par; - struct drm_device *dev = nfbdev->dev; - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_channel *chan = dev_priv->channel; + struct nouveau_drm *drm = nouveau_newpriv(nfbdev->dev); + struct nouveau_channel *chan = drm->channel; int ret; ret = RING_SPACE(chan, 4); @@ -53,9 +52,8 @@ int nv04_fbcon_fillrect(struct fb_info *info, const struct fb_fillrect *rect) { struct nouveau_fbdev *nfbdev = info->par; - struct drm_device *dev = nfbdev->dev; - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_channel *chan = dev_priv->channel; + struct nouveau_drm *drm = nouveau_newpriv(nfbdev->dev); + struct nouveau_channel *chan = drm->channel; int ret; ret = RING_SPACE(chan, 7); @@ -81,9 +79,8 @@ int nv04_fbcon_imageblit(struct fb_info *info, const struct fb_image *image) { struct nouveau_fbdev *nfbdev = info->par; - struct drm_device *dev = nfbdev->dev; - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_channel *chan = dev_priv->channel; + struct nouveau_drm *drm = nouveau_newpriv(nfbdev->dev); + struct nouveau_channel *chan = drm->channel; uint32_t fg; uint32_t bg; uint32_t dsize; @@ -142,9 +139,10 @@ nv04_fbcon_accel_init(struct fb_info *info) { struct nouveau_fbdev *nfbdev = info->par; struct drm_device *dev = nfbdev->dev; - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_channel *chan = dev_priv->channel; - const int sub = NvSubCtxSurf2D; + struct nouveau_drm *drm = nouveau_newpriv(dev); + struct nouveau_channel *chan = drm->channel; + struct nouveau_device *device = nv_device(drm->device); + struct nouveau_object *object; int surface_fmt, pattern_fmt, rect_fmt; int ret; @@ -176,31 +174,35 @@ nv04_fbcon_accel_init(struct fb_info *info) return -EINVAL; } - ret = nouveau_gpuobj_gr_new(chan, NvCtxSurf2D, - dev_priv->card_type >= NV_10 ? - 0x0062 : 0x0042); + ret = nouveau_object_new(nv_object(chan->cli), NVDRM_CHAN, NvCtxSurf2D, + device->card_type >= NV_10 ? 0x0062 : 0x0042, + NULL, 0, &object); if (ret) return ret; - ret = nouveau_gpuobj_gr_new(chan, NvClipRect, 0x0019); + ret = nouveau_object_new(nv_object(chan->cli), NVDRM_CHAN, NvClipRect, + 0x0019, NULL, 0, &object); if (ret) return ret; - ret = nouveau_gpuobj_gr_new(chan, NvRop, 0x0043); + ret = nouveau_object_new(nv_object(chan->cli), NVDRM_CHAN, NvRop, + 0x0043, NULL, 0, &object); if (ret) return ret; - ret = nouveau_gpuobj_gr_new(chan, NvImagePatt, 0x0044); + ret = nouveau_object_new(nv_object(chan->cli), NVDRM_CHAN, NvImagePatt, + 0x0044, NULL, 0, &object); if (ret) return ret; - ret = nouveau_gpuobj_gr_new(chan, NvGdiRect, 0x004a); + ret = nouveau_object_new(nv_object(chan->cli), NVDRM_CHAN, NvGdiRect, + 0x004a, NULL, 0, &object); if (ret) return ret; - ret = nouveau_gpuobj_gr_new(chan, NvImageBlit, - dev_priv->chipset >= 0x11 ? - 0x009f : 0x005f); + ret = nouveau_object_new(nv_object(chan->cli), NVDRM_CHAN, NvImageBlit, + device->chipset >= 0x11 ? 0x009f : 0x005f, + NULL, 0, &object); if (ret) return ret; @@ -209,25 +211,25 @@ nv04_fbcon_accel_init(struct fb_info *info) return 0; } - BEGIN_NV04(chan, sub, 0x0000, 1); + BEGIN_NV04(chan, NvSubCtxSurf2D, 0x0000, 1); OUT_RING(chan, NvCtxSurf2D); - BEGIN_NV04(chan, sub, 0x0184, 2); + BEGIN_NV04(chan, NvSubCtxSurf2D, 0x0184, 2); OUT_RING(chan, NvDmaFB); OUT_RING(chan, NvDmaFB); - BEGIN_NV04(chan, sub, 0x0300, 4); + BEGIN_NV04(chan, NvSubCtxSurf2D, 0x0300, 4); OUT_RING(chan, surface_fmt); OUT_RING(chan, info->fix.line_length | (info->fix.line_length << 16)); OUT_RING(chan, info->fix.smem_start - dev->mode_config.fb_base); OUT_RING(chan, info->fix.smem_start - dev->mode_config.fb_base); - BEGIN_NV04(chan, sub, 0x0000, 1); + BEGIN_NV04(chan, NvSubCtxSurf2D, 0x0000, 1); OUT_RING(chan, NvRop); - BEGIN_NV04(chan, sub, 0x0300, 1); + BEGIN_NV04(chan, NvSubCtxSurf2D, 0x0300, 1); OUT_RING(chan, 0x55); - BEGIN_NV04(chan, sub, 0x0000, 1); + BEGIN_NV04(chan, NvSubCtxSurf2D, 0x0000, 1); OUT_RING(chan, NvImagePatt); - BEGIN_NV04(chan, sub, 0x0300, 8); + BEGIN_NV04(chan, NvSubCtxSurf2D, 0x0300, 8); OUT_RING(chan, pattern_fmt); #ifdef __BIG_ENDIAN OUT_RING(chan, 2); @@ -241,9 +243,9 @@ nv04_fbcon_accel_init(struct fb_info *info) OUT_RING(chan, ~0); OUT_RING(chan, ~0); - BEGIN_NV04(chan, sub, 0x0000, 1); + BEGIN_NV04(chan, NvSubCtxSurf2D, 0x0000, 1); OUT_RING(chan, NvClipRect); - BEGIN_NV04(chan, sub, 0x0300, 2); + BEGIN_NV04(chan, NvSubCtxSurf2D, 0x0300, 2); OUT_RING(chan, 0); OUT_RING(chan, (info->var.yres_virtual << 16) | info->var.xres_virtual); diff --git a/drivers/gpu/drm/nouveau/nv04_fence.c b/drivers/gpu/drm/nouveau/nv04_fence.c index 1b45a4f8c0a5..a220b94ba9f2 100644 --- a/drivers/gpu/drm/nouveau/nv04_fence.c +++ b/drivers/gpu/drm/nouveau/nv04_fence.c @@ -22,15 +22,14 @@ * Authors: Ben Skeggs */ -#include "drmP.h" -#include "nouveau_drv.h" +#include + +#include "nouveau_drm.h" #include "nouveau_dma.h" -#include #include "nouveau_fence.h" struct nv04_fence_chan { struct nouveau_fence_chan base; - atomic_t sequence; }; struct nv04_fence_priv { @@ -57,19 +56,11 @@ nv04_fence_sync(struct nouveau_fence *fence, return -ENODEV; } -int -nv04_fence_mthd(struct nouveau_channel *chan, u32 class, u32 mthd, u32 data) -{ - struct nv04_fence_chan *fctx = chan->fence; - atomic_set(&fctx->sequence, data); - return 0; -} - static u32 nv04_fence_read(struct nouveau_channel *chan) { - struct nv04_fence_chan *fctx = chan->fence; - return atomic_read(&fctx->sequence); + struct nouveau_fifo_chan *fifo = (void *)chan->object; + return atomic_read(&fifo->refcnt); } static void @@ -87,7 +78,6 @@ nv04_fence_context_new(struct nouveau_channel *chan) struct nv04_fence_chan *fctx = kzalloc(sizeof(*fctx), GFP_KERNEL); if (fctx) { nouveau_fence_context_new(&fctx->base); - atomic_set(&fctx->sequence, 0); chan->fence = fctx; return 0; } @@ -95,23 +85,19 @@ nv04_fence_context_new(struct nouveau_channel *chan) } static void -nv04_fence_destroy(struct drm_device *dev) +nv04_fence_destroy(struct nouveau_drm *drm) { - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nv04_fence_priv *priv = dev_priv->fence.func; - - dev_priv->fence.func = NULL; + struct nv04_fence_priv *priv = drm->fence; + drm->fence = NULL; kfree(priv); } int -nv04_fence_create(struct drm_device *dev) +nv04_fence_create(struct nouveau_drm *drm) { - struct drm_nouveau_private *dev_priv = dev->dev_private; struct nv04_fence_priv *priv; - int ret; - priv = kzalloc(sizeof(*priv), GFP_KERNEL); + priv = drm->fence = kzalloc(sizeof(*priv), GFP_KERNEL); if (!priv) return -ENOMEM; @@ -121,6 +107,5 @@ nv04_fence_create(struct drm_device *dev) priv->base.emit = nv04_fence_emit; priv->base.sync = nv04_fence_sync; priv->base.read = nv04_fence_read; - dev_priv->fence.func = &priv->base; - return ret; + return 0; } diff --git a/drivers/gpu/drm/nouveau/nv04_software.c b/drivers/gpu/drm/nouveau/nv04_software.c deleted file mode 100644 index ceeb868c7c29..000000000000 --- a/drivers/gpu/drm/nouveau/nv04_software.c +++ /dev/null @@ -1,139 +0,0 @@ -/* - * 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 "drmP.h" - -#include "nouveau_drv.h" -#include -#include "nouveau_fence.h" -#include "nouveau_software.h" -#include "nouveau_hw.h" - -struct nv04_software_priv { - struct nouveau_software_priv base; -}; - -struct nv04_software_chan { - struct nouveau_software_chan base; -}; - -static int -mthd_flip(struct nouveau_channel *chan, u32 class, u32 mthd, u32 data) -{ - struct nv04_software_chan *pch = chan->engctx[NVOBJ_ENGINE_SW]; - return pch->base.flip(pch->base.flip_data); -} - -static int -nv04_software_context_new(struct nouveau_channel *chan, int engine) -{ - struct nv04_software_chan *pch; - - pch = kzalloc(sizeof(*pch), GFP_KERNEL); - if (!pch) - return -ENOMEM; - - nouveau_software_context_new(chan, &pch->base); - chan->engctx[engine] = pch; - return 0; -} - -static void -nv04_software_context_del(struct nouveau_channel *chan, int engine) -{ - struct nv04_software_chan *pch = chan->engctx[engine]; - chan->engctx[engine] = NULL; - kfree(pch); -} - -static int -nv04_software_object_new(struct nouveau_channel *chan, int engine, - u32 handle, u16 class) -{ - struct drm_device *dev = chan->dev; - struct nouveau_gpuobj *obj = NULL; - int ret; - - ret = nouveau_gpuobj_new(dev, chan, 16, 16, 0, &obj); - if (ret) - return ret; - obj->engine = 0; - obj->class = class; - - ret = nouveau_ramht_insert(chan, handle, obj); - nouveau_gpuobj_ref(NULL, &obj); - return ret; -} - -static int -nv04_software_init(struct drm_device *dev, int engine) -{ - return 0; -} - -static int -nv04_software_fini(struct drm_device *dev, int engine, bool suspend) -{ - return 0; -} - -static void -nv04_software_destroy(struct drm_device *dev, int engine) -{ - struct nv04_software_priv *psw = nv_engine(dev, engine); - - NVOBJ_ENGINE_DEL(dev, SW); - kfree(psw); -} - -int -nv04_software_create(struct drm_device *dev) -{ - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nv04_software_priv *psw; - - psw = kzalloc(sizeof(*psw), GFP_KERNEL); - if (!psw) - return -ENOMEM; - - psw->base.base.destroy = nv04_software_destroy; - psw->base.base.init = nv04_software_init; - psw->base.base.fini = nv04_software_fini; - psw->base.base.context_new = nv04_software_context_new; - psw->base.base.context_del = nv04_software_context_del; - psw->base.base.object_new = nv04_software_object_new; - nouveau_software_create(&psw->base); - - NVOBJ_ENGINE_ADD(dev, SW, &psw->base.base); - if (dev_priv->card_type <= NV_04) { - NVOBJ_CLASS(dev, 0x006e, SW); - NVOBJ_MTHD (dev, 0x006e, 0x0150, nv04_fence_mthd); - NVOBJ_MTHD (dev, 0x006e, 0x0500, mthd_flip); - } else { - NVOBJ_CLASS(dev, 0x016e, SW); - NVOBJ_MTHD (dev, 0x016e, 0x0500, mthd_flip); - } - - return 0; -} diff --git a/drivers/gpu/drm/nouveau/nv10_fence.c b/drivers/gpu/drm/nouveau/nv10_fence.c index dd7f17dd9903..ce752bf5cc4e 100644 --- a/drivers/gpu/drm/nouveau/nv10_fence.c +++ b/drivers/gpu/drm/nouveau/nv10_fence.c @@ -22,10 +22,11 @@ * Authors: Ben Skeggs */ -#include "drmP.h" -#include "nouveau_drv.h" +#include +#include + +#include "nouveau_drm.h" #include "nouveau_dma.h" -#include #include "nouveau_fence.h" struct nv10_fence_chan { @@ -64,12 +65,11 @@ int nv17_fence_sync(struct nouveau_fence *fence, struct nouveau_channel *prev, struct nouveau_channel *chan) { - struct drm_nouveau_private *dev_priv = chan->dev->dev_private; - struct nv10_fence_priv *priv = dev_priv->fence.func; + struct nv10_fence_priv *priv = chan->drm->fence; u32 value; int ret; - if (!mutex_trylock(&prev->mutex)) + if (!mutex_trylock(&prev->cli->mutex)) return -EBUSY; spin_lock(&priv->lock); @@ -96,14 +96,14 @@ nv17_fence_sync(struct nouveau_fence *fence, FIRE_RING (chan); } - mutex_unlock(&prev->mutex); + mutex_unlock(&prev->cli->mutex); return 0; } u32 nv10_fence_read(struct nouveau_channel *chan) { - return nvchan_rd32(chan, 0x0048); + return nv_ro32(chan->object, 0x0048); } void @@ -118,10 +118,8 @@ nv10_fence_context_del(struct nouveau_channel *chan) static int nv10_fence_context_new(struct nouveau_channel *chan) { - struct drm_nouveau_private *dev_priv = chan->dev->dev_private; - struct nv10_fence_priv *priv = dev_priv->fence.func; + struct nv10_fence_priv *priv = chan->drm->fence; struct nv10_fence_chan *fctx; - struct nouveau_gpuobj *obj; int ret = 0; fctx = chan->fence = kzalloc(sizeof(*fctx), GFP_KERNEL); @@ -132,15 +130,19 @@ nv10_fence_context_new(struct nouveau_channel *chan) if (priv->bo) { struct ttm_mem_reg *mem = &priv->bo->bo.mem; - - ret = nouveau_gpuobj_dma_new(chan, NV_CLASS_DMA_FROM_MEMORY, - mem->start * PAGE_SIZE, mem->size, - NV_MEM_ACCESS_RW, - NV_MEM_TARGET_VRAM, &obj); - if (!ret) { - ret = nouveau_ramht_insert(chan, NvSema, obj); - nouveau_gpuobj_ref(NULL, &obj); - } + struct nouveau_object *object; + u32 start = mem->start * PAGE_SIZE; + u32 limit = mem->start + mem->size - 1; + + ret = nouveau_object_new(nv_object(chan->cli), chan->handle, + NvSema, 0x0002, + &(struct nv_dma_class) { + .flags = NV_DMA_TARGET_VRAM | + NV_DMA_ACCESS_RDWR, + .start = start, + .limit = limit, + }, sizeof(struct nv_dma_class), + &object); } if (ret) @@ -149,24 +151,22 @@ nv10_fence_context_new(struct nouveau_channel *chan) } void -nv10_fence_destroy(struct drm_device *dev) +nv10_fence_destroy(struct nouveau_drm *drm) { - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nv10_fence_priv *priv = dev_priv->fence.func; - + struct nv10_fence_priv *priv = drm->fence; + nouveau_bo_unmap(priv->bo); nouveau_bo_ref(NULL, &priv->bo); - dev_priv->fence.func = NULL; + drm->fence = NULL; kfree(priv); } int -nv10_fence_create(struct drm_device *dev) +nv10_fence_create(struct nouveau_drm *drm) { - struct drm_nouveau_private *dev_priv = dev->dev_private; struct nv10_fence_priv *priv; int ret = 0; - priv = kzalloc(sizeof(*priv), GFP_KERNEL); + priv = drm->fence = kzalloc(sizeof(*priv), GFP_KERNEL); if (!priv) return -ENOMEM; @@ -176,11 +176,10 @@ nv10_fence_create(struct drm_device *dev) priv->base.emit = nv10_fence_emit; priv->base.read = nv10_fence_read; priv->base.sync = nv10_fence_sync; - dev_priv->fence.func = &priv->base; spin_lock_init(&priv->lock); - if (dev_priv->chipset >= 0x17) { - ret = nouveau_bo_new(dev, 4096, 0x1000, TTM_PL_FLAG_VRAM, + if (nv_device(drm->device)->chipset >= 0x17) { + ret = nouveau_bo_new(drm->dev, 4096, 0x1000, TTM_PL_FLAG_VRAM, 0, 0x0000, NULL, &priv->bo); if (!ret) { ret = nouveau_bo_pin(priv->bo, TTM_PL_FLAG_VRAM); @@ -197,6 +196,6 @@ nv10_fence_create(struct drm_device *dev) } if (ret) - nv10_fence_destroy(dev); + nv10_fence_destroy(drm); return ret; } diff --git a/drivers/gpu/drm/nouveau/nv40_pm.c b/drivers/gpu/drm/nouveau/nv40_pm.c index d857525666ee..93f536de3779 100644 --- a/drivers/gpu/drm/nouveau/nv40_pm.c +++ b/drivers/gpu/drm/nouveau/nv40_pm.c @@ -27,7 +27,6 @@ #include #include "nouveau_pm.h" #include "nouveau_hw.h" -#include #define min2(a,b) ((a) < (b) ? (a) : (b)) @@ -259,7 +258,7 @@ nv40_pm_clocks_set(struct drm_device *dev, void *pre_state) if (!nv_wait(dev, 0x003220, 0x00000010, 0x00000000)) goto resume; nv_mask(dev, 0x003200, 0x00000001, 0x00000000); - nv04_fifo_cache_pull(dev, false); + //XXX: nv04_fifo_cache_pull(dev, false); if (!nv_wait_cb(dev, nv40_pm_gr_idle, dev)) goto resume; diff --git a/drivers/gpu/drm/nouveau/nv50_display.c b/drivers/gpu/drm/nouveau/nv50_display.c index 83419a2daa0b..ae72f7656106 100644 --- a/drivers/gpu/drm/nouveau/nv50_display.c +++ b/drivers/gpu/drm/nouveau/nv50_display.c @@ -31,7 +31,6 @@ #include "nouveau_connector.h" #include "nouveau_fb.h" #include "nouveau_fbcon.h" -#include #include "drm_crtc_helper.h" #include "nouveau_fence.h" @@ -102,17 +101,17 @@ nv50_display_sync(struct drm_device *dev) BEGIN_NV04(evo, 0, 0x0084, 1); OUT_RING (evo, 0x00000000); - nv_wo32(disp->ntfy, 0x000, 0x00000000); + nv_wo32(disp->ramin, 0x2000, 0x00000000); FIRE_RING (evo); start = nv_timer_read(dev); do { - if (nv_ro32(disp->ntfy, 0x000)) + if (nv_ro32(disp->ramin, 0x2000)) return 0; } while (nv_timer_read(dev) - start < 2000000000ULL); } - return -EBUSY; + return 0; } int @@ -217,7 +216,7 @@ nv50_display_init(struct drm_device *dev) return ret; evo = nv50_display(dev)->master; - nv_wr32(dev, NV50_PDISPLAY_OBJECTS, (evo->ramin->addr >> 8) | 9); + nv_wr32(dev, NV50_PDISPLAY_OBJECTS, (nv50_display(dev)->ramin->addr >> 8) | 9); ret = RING_SPACE(evo, 3); if (ret) @@ -444,7 +443,7 @@ nv50_display_flip_next(struct drm_crtc *crtc, struct drm_framebuffer *fb, if (dev_priv->chipset < 0x84) OUT_RING (chan, NvSema); else - OUT_RING (chan, chan->vram_handle); + OUT_RING (chan, chan->vram); } else { u64 offset = nvc0_fence_crtc(chan, nv_crtc->index); offset += dispc->sem.offset; @@ -597,48 +596,6 @@ nv50_display_script_select(struct drm_device *dev, struct dcb_output *dcb, return script; } -static void -nv50_display_vblank_crtc_handler(struct drm_device *dev, int crtc) -{ - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_software_priv *psw = nv_engine(dev, NVOBJ_ENGINE_SW); - struct nouveau_software_chan *pch, *tmp; - - list_for_each_entry_safe(pch, tmp, &psw->vblank, vblank.list) { - if (pch->vblank.head != crtc) - continue; - - spin_lock(&psw->peephole_lock); - nv_wr32(dev, 0x001704, pch->vblank.channel); - nv_wr32(dev, 0x001710, 0x80000000 | pch->vblank.ctxdma); - if (dev_priv->chipset == 0x50) { - nv_wr32(dev, 0x001570, pch->vblank.offset); - nv_wr32(dev, 0x001574, pch->vblank.value); - } else { - nv_wr32(dev, 0x060010, pch->vblank.offset); - nv_wr32(dev, 0x060014, pch->vblank.value); - } - spin_unlock(&psw->peephole_lock); - - list_del(&pch->vblank.list); - drm_vblank_put(dev, crtc); - } - - drm_handle_vblank(dev, crtc); -} - -static void -nv50_display_vblank_handler(struct drm_device *dev, uint32_t intr) -{ - if (intr & NV50_PDISPLAY_INTR_1_VBLANK_CRTC_0) - nv50_display_vblank_crtc_handler(dev, 0); - - if (intr & NV50_PDISPLAY_INTR_1_VBLANK_CRTC_1) - nv50_display_vblank_crtc_handler(dev, 1); - - nv_wr32(dev, NV50_PDISPLAY_INTR_1, NV50_PDISPLAY_INTR_1_VBLANK_CRTC); -} - static void nv50_display_unk10_handler(struct drm_device *dev) { @@ -978,8 +935,8 @@ nv50_display_isr(struct drm_device *dev) } if (intr1 & NV50_PDISPLAY_INTR_1_VBLANK_CRTC) { - nv50_display_vblank_handler(dev, intr1); intr1 &= ~NV50_PDISPLAY_INTR_1_VBLANK_CRTC; + delayed |= NV50_PDISPLAY_INTR_1_VBLANK_CRTC; } clock = (intr1 & (NV50_PDISPLAY_INTR_1_CLK_UNK10 | diff --git a/drivers/gpu/drm/nouveau/nv50_display.h b/drivers/gpu/drm/nouveau/nv50_display.h index 25c301391724..ef12a7afac9c 100644 --- a/drivers/gpu/drm/nouveau/nv50_display.h +++ b/drivers/gpu/drm/nouveau/nv50_display.h @@ -33,7 +33,6 @@ #include "nouveau_dma.h" #include "nouveau_reg.h" #include "nouveau_crtc.h" -#include "nouveau_software.h" #include "nv50_evo.h" struct nv50_display_crtc { @@ -47,7 +46,10 @@ struct nv50_display_crtc { struct nv50_display { struct nouveau_channel *master; - struct nouveau_gpuobj *ntfy; + + struct nouveau_gpuobj *ramin; + u32 dmao; + u32 hash; struct nv50_display_crtc crtc[2]; diff --git a/drivers/gpu/drm/nouveau/nv50_evo.c b/drivers/gpu/drm/nouveau/nv50_evo.c index 7e9a6d6d673b..d7d8080c6a14 100644 --- a/drivers/gpu/drm/nouveau/nv50_evo.c +++ b/drivers/gpu/drm/nouveau/nv50_evo.c @@ -26,9 +26,22 @@ #include "nouveau_drv.h" #include "nouveau_dma.h" -#include #include "nv50_display.h" +static u32 +nv50_evo_rd32(struct nouveau_object *object, u32 addr) +{ + void __iomem *iomem = object->oclass->ofuncs->rd08; + return ioread32_native(iomem + addr); +} + +static void +nv50_evo_wr32(struct nouveau_object *object, u32 addr, u32 data) +{ + void __iomem *iomem = object->oclass->ofuncs->rd08; + iowrite32_native(data, iomem + addr); +} + static void nv50_evo_channel_del(struct nouveau_channel **pevo) { @@ -38,21 +51,24 @@ nv50_evo_channel_del(struct nouveau_channel **pevo) return; *pevo = NULL; - nouveau_ramht_ref(NULL, &evo->ramht, evo); - nouveau_gpuobj_channel_takedown(evo); - nouveau_bo_unmap(evo->pushbuf_bo); - nouveau_bo_ref(NULL, &evo->pushbuf_bo); + nouveau_bo_unmap(evo->push.buffer); + nouveau_bo_ref(NULL, &evo->push.buffer); - if (evo->user) - iounmap(evo->user); + if (evo->object) + iounmap(evo->object->oclass->ofuncs); kfree(evo); } -void -nv50_evo_dmaobj_init(struct nouveau_gpuobj *obj, u32 memtype, u64 base, u64 size) +int +nv50_evo_dmaobj_new(struct nouveau_channel *evo, u32 handle, u32 memtype, + u64 base, u64 size, struct nouveau_gpuobj **pobj) { - struct drm_nouveau_private *dev_priv = obj->dev->dev_private; + struct drm_device *dev = evo->fence; + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nv50_display *disp = nv50_display(dev); + u32 dmao = disp->dmao; + u32 hash = disp->hash; u32 flags5; if (dev_priv->chipset < 0xc0) { @@ -67,36 +83,21 @@ nv50_evo_dmaobj_init(struct nouveau_gpuobj *obj, u32 memtype, u64 base, u64 size flags5 = 0x00020000; } - nv50_gpuobj_dma_init(obj, 0, 0x3d, base, size, NV_MEM_TARGET_VRAM, - NV_MEM_ACCESS_RW, (memtype >> 8) & 0xff, 0); - nv_wo32(obj, 0x14, flags5); - nvimem_flush(obj->dev); -} + nv_wo32(disp->ramin, dmao + 0x00, 0x0019003d | (memtype << 22)); + nv_wo32(disp->ramin, dmao + 0x04, lower_32_bits(base + size - 1)); + nv_wo32(disp->ramin, dmao + 0x08, lower_32_bits(base)); + nv_wo32(disp->ramin, dmao + 0x0c, upper_32_bits(base + size - 1) << 24 | + upper_32_bits(base)); + nv_wo32(disp->ramin, dmao + 0x10, 0x00000000); + nv_wo32(disp->ramin, dmao + 0x14, flags5); -int -nv50_evo_dmaobj_new(struct nouveau_channel *evo, u32 handle, u32 memtype, - u64 base, u64 size, struct nouveau_gpuobj **pobj) -{ - struct nv50_display *disp = nv50_display(evo->dev); - struct nouveau_gpuobj *obj = NULL; - int ret; + nv_wo32(disp->ramin, hash + 0x00, handle); + nv_wo32(disp->ramin, hash + 0x04, (evo->handle << 28) | (dmao << 10) | + evo->handle); - ret = nouveau_gpuobj_new(evo->dev, disp->master, 6*4, 32, 0, &obj); - if (ret) - return ret; - obj->engine = NVOBJ_ENGINE_DISPLAY; - - nv50_evo_dmaobj_init(obj, memtype, base, size); - - ret = nouveau_ramht_insert(evo, handle, obj); - if (ret) - goto out; - - if (pobj) - nouveau_gpuobj_ref(obj, pobj); -out: - nouveau_gpuobj_ref(NULL, &obj); - return ret; + disp->dmao += 0x20; + disp->hash += 0x08; + return 0; } static int @@ -112,49 +113,52 @@ nv50_evo_channel_new(struct drm_device *dev, int chid, return -ENOMEM; *pevo = evo; - evo->id = chid; - evo->dev = dev; + evo->handle = chid; + evo->fence = dev; evo->user_get = 4; evo->user_put = 0; ret = nouveau_bo_new(dev, 4096, 0, TTM_PL_FLAG_VRAM, 0, 0, NULL, - &evo->pushbuf_bo); + &evo->push.buffer); if (ret == 0) - ret = nouveau_bo_pin(evo->pushbuf_bo, TTM_PL_FLAG_VRAM); + 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); nv50_evo_channel_del(pevo); return ret; } - ret = nouveau_bo_map(evo->pushbuf_bo); + ret = nouveau_bo_map(evo->push.buffer); if (ret) { NV_ERROR(dev, "Error mapping EVO DMA push buffer: %d\n", ret); nv50_evo_channel_del(pevo); return ret; } - evo->user = ioremap(pci_resource_start(dev->pdev, 0) + - NV50_PDISPLAY_USER(evo->id), PAGE_SIZE); - if (!evo->user) { - NV_ERROR(dev, "Error mapping EVO control regs.\n"); - nv50_evo_channel_del(pevo); - return -ENOMEM; - } - - /* bind primary evo channel's ramht to the channel */ - if (disp->master && evo != disp->master) - nouveau_ramht_ref(disp->master->ramht, &evo->ramht, NULL); - + evo->object = kzalloc(sizeof(*evo->object), GFP_KERNEL); +#ifdef NOUVEAU_OBJECT_MAGIC + evo->object->_magic = NOUVEAU_OBJECT_MAGIC; +#endif + evo->object->parent = nv_object(disp->ramin)->parent; + evo->object->engine = nv_object(disp->ramin)->engine; + evo->object->oclass = + kzalloc(sizeof(*evo->object->oclass), GFP_KERNEL); + evo->object->oclass->ofuncs = + kzalloc(sizeof(*evo->object->oclass->ofuncs), GFP_KERNEL); + evo->object->oclass->ofuncs->rd32 = nv50_evo_rd32; + evo->object->oclass->ofuncs->wr32 = nv50_evo_wr32; + evo->object->oclass->ofuncs->rd08 = + ioremap(pci_resource_start(dev->pdev, 0) + + NV50_PDISPLAY_USER(evo->handle), PAGE_SIZE); return 0; } static int nv50_evo_channel_init(struct nouveau_channel *evo) { - struct drm_device *dev = evo->dev; - int id = evo->id, ret, i; - u64 pushbuf = evo->pushbuf_bo->bo.offset; + struct drm_device *dev = evo->fence; + int id = evo->handle, ret, i; + u64 pushbuf = evo->push.buffer->bo.offset; u32 tmp; tmp = nv_rd32(dev, NV50_PDISPLAY_EVO_CTRL(id)); @@ -205,8 +209,8 @@ nv50_evo_channel_init(struct nouveau_channel *evo) static void nv50_evo_channel_fini(struct nouveau_channel *evo) { - struct drm_device *dev = evo->dev; - int id = evo->id; + struct drm_device *dev = evo->fence; + int id = evo->handle; nv_mask(dev, 0x610028, 0x00010001 << id, 0x00000000); nv_mask(dev, NV50_PDISPLAY_EVO_CTRL(id), 0x00001010, 0x00001000); @@ -231,8 +235,8 @@ nv50_evo_destroy(struct drm_device *dev) } nv50_evo_channel_del(&disp->crtc[i].sync); } - nouveau_gpuobj_ref(NULL, &disp->ntfy); nv50_evo_channel_del(&disp->master); + nouveau_gpuobj_ref(NULL, &disp->ramin); } int @@ -240,55 +244,33 @@ nv50_evo_create(struct drm_device *dev) { struct drm_nouveau_private *dev_priv = dev->dev_private; struct nv50_display *disp = nv50_display(dev); - struct nouveau_gpuobj *ramht = NULL; struct nouveau_channel *evo; int ret, i, j; - /* create primary evo channel, the one we use for modesetting - * purporses - */ - ret = nv50_evo_channel_new(dev, 0, &disp->master); - if (ret) - return ret; - evo = disp->master; - /* setup object management on it, any other evo channel will * use this also as there's no per-channel support on the * hardware */ ret = nouveau_gpuobj_new(dev, NULL, 32768, 65536, - NVOBJ_FLAG_ZERO_ALLOC, &evo->ramin); + NVOBJ_FLAG_ZERO_ALLOC, &disp->ramin); if (ret) { NV_ERROR(dev, "Error allocating EVO channel memory: %d\n", ret); goto err; } - ret = nouveau_gpuobj_new(dev, evo, 4096, 16, 0, &ramht); - if (ret) { - NV_ERROR(dev, "Unable to allocate EVO RAMHT: %d\n", ret); - goto err; - } - - ret = nouveau_ramht_new(dev, ramht, &evo->ramht); - nouveau_gpuobj_ref(NULL, &ramht); - if (ret) - goto err; + disp->hash = 0x0000; + disp->dmao = 0x1000; - /* not sure exactly what this is.. - * - * the first dword of the structure is used by nvidia to wait on - * full completion of an EVO "update" command. - * - * method 0x8c on the master evo channel will fill a lot more of - * this structure with some undefined info + /* create primary evo channel, the one we use for modesetting + * purporses */ - ret = nouveau_gpuobj_new(dev, disp->master, 0x1000, 0, - NVOBJ_FLAG_ZERO_ALLOC, &disp->ntfy); + ret = nv50_evo_channel_new(dev, 0, &disp->master); if (ret) - goto err; + return ret; + evo = disp->master; ret = nv50_evo_dmaobj_new(disp->master, NvEvoSync, 0x0000, - disp->ntfy->addr, disp->ntfy->size, NULL); + disp->ramin->addr + 0x2000, 0x1000, NULL); if (ret) goto err; @@ -304,13 +286,13 @@ nv50_evo_create(struct drm_device *dev) goto err; ret = nv50_evo_dmaobj_new(disp->master, NvEvoFB32, 0x80000000 | - (dev_priv->chipset < 0xc0 ? 0x7a00 : 0xfe00), + (dev_priv->chipset < 0xc0 ? 0x7a : 0xfe), 0, nvfb_vram_size(dev), NULL); if (ret) goto err; ret = nv50_evo_dmaobj_new(disp->master, NvEvoFB16, 0x80000000 | - (dev_priv->chipset < 0xc0 ? 0x7000 : 0xfe00), + (dev_priv->chipset < 0xc0 ? 0x70 : 0xfe), 0, nvfb_vram_size(dev), NULL); if (ret) goto err; @@ -352,14 +334,14 @@ nv50_evo_create(struct drm_device *dev) ret = nv50_evo_dmaobj_new(dispc->sync, NvEvoFB32, 0x80000000 | (dev_priv->chipset < 0xc0 ? - 0x7a00 : 0xfe00), + 0x7a : 0xfe), 0, nvfb_vram_size(dev), NULL); if (ret) goto err; ret = nv50_evo_dmaobj_new(dispc->sync, NvEvoFB16, 0x80000000 | (dev_priv->chipset < 0xc0 ? - 0x7000 : 0xfe00), + 0x70 : 0xfe), 0, nvfb_vram_size(dev), NULL); if (ret) goto err; diff --git a/drivers/gpu/drm/nouveau/nv50_fbcon.c b/drivers/gpu/drm/nouveau/nv50_fbcon.c index 1593e2402fd2..2028a4447124 100644 --- a/drivers/gpu/drm/nouveau/nv50_fbcon.c +++ b/drivers/gpu/drm/nouveau/nv50_fbcon.c @@ -22,20 +22,16 @@ * Authors: Ben Skeggs */ -#include "drmP.h" -#include "nouveau_drv.h" +#include "nouveau_drm.h" #include "nouveau_dma.h" -#include #include "nouveau_fbcon.h" -#include int nv50_fbcon_fillrect(struct fb_info *info, const struct fb_fillrect *rect) { struct nouveau_fbdev *nfbdev = info->par; - struct drm_device *dev = nfbdev->dev; - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_channel *chan = dev_priv->channel; + struct nouveau_drm *drm = nouveau_newpriv(nfbdev->dev); + struct nouveau_channel *chan = drm->channel; int ret; ret = RING_SPACE(chan, rect->rop == ROP_COPY ? 7 : 11); @@ -69,9 +65,8 @@ int nv50_fbcon_copyarea(struct fb_info *info, const struct fb_copyarea *region) { struct nouveau_fbdev *nfbdev = info->par; - struct drm_device *dev = nfbdev->dev; - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_channel *chan = dev_priv->channel; + struct nouveau_drm *drm = nouveau_newpriv(nfbdev->dev); + struct nouveau_channel *chan = drm->channel; int ret; ret = RING_SPACE(chan, 12); @@ -98,9 +93,8 @@ int nv50_fbcon_imageblit(struct fb_info *info, const struct fb_image *image) { struct nouveau_fbdev *nfbdev = info->par; - struct drm_device *dev = nfbdev->dev; - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_channel *chan = dev_priv->channel; + struct nouveau_drm *drm = nouveau_newpriv(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)); uint32_t *palette = info->pseudo_palette; @@ -156,10 +150,11 @@ int nv50_fbcon_accel_init(struct fb_info *info) { struct nouveau_fbdev *nfbdev = info->par; - struct drm_device *dev = nfbdev->dev; - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_channel *chan = dev_priv->channel; struct nouveau_framebuffer *fb = &nfbdev->nouveau_fb; + struct drm_device *dev = nfbdev->dev; + struct nouveau_drm *drm = nouveau_newpriv(dev); + struct nouveau_channel *chan = drm->channel; + struct nouveau_object *object; int ret, format; switch (info->var.bits_per_pixel) { @@ -189,7 +184,8 @@ nv50_fbcon_accel_init(struct fb_info *info) return -EINVAL; } - ret = nouveau_gpuobj_gr_new(dev_priv->channel, Nv2D, 0x502d); + ret = nouveau_object_new(nv_object(chan->cli), NVDRM_CHAN, Nv2D, + 0x502d, NULL, 0, &object); if (ret) return ret; @@ -202,9 +198,9 @@ nv50_fbcon_accel_init(struct fb_info *info) BEGIN_NV04(chan, NvSub2D, 0x0000, 1); OUT_RING(chan, Nv2D); BEGIN_NV04(chan, NvSub2D, 0x0184, 3); - OUT_RING(chan, chan->vram_handle); - OUT_RING(chan, chan->vram_handle); - OUT_RING(chan, chan->vram_handle); + OUT_RING(chan, NvDmaFB); + OUT_RING(chan, NvDmaFB); + OUT_RING(chan, NvDmaFB); BEGIN_NV04(chan, NvSub2D, 0x0290, 1); OUT_RING(chan, 0); BEGIN_NV04(chan, NvSub2D, 0x0888, 1); diff --git a/drivers/gpu/drm/nouveau/nv50_fence.c b/drivers/gpu/drm/nouveau/nv50_fence.c index 10aa04f26b83..e717aaaf62c6 100644 --- a/drivers/gpu/drm/nouveau/nv50_fence.c +++ b/drivers/gpu/drm/nouveau/nv50_fence.c @@ -22,12 +22,12 @@ * Authors: Ben Skeggs */ -#include "drmP.h" -#include "nouveau_drv.h" +#include +#include + +#include "nouveau_drm.h" #include "nouveau_dma.h" -#include #include "nouveau_fence.h" -#include "nv50_display.h" struct nv50_fence_chan { struct nouveau_fence_chan base; @@ -43,12 +43,11 @@ struct nv50_fence_priv { static int nv50_fence_context_new(struct nouveau_channel *chan) { - struct drm_nouveau_private *dev_priv = chan->dev->dev_private; - struct nv50_fence_priv *priv = dev_priv->fence.func; + struct nv50_fence_priv *priv = chan->drm->fence; struct nv50_fence_chan *fctx; struct ttm_mem_reg *mem = &priv->bo->bo.mem; - struct nouveau_gpuobj *obj; - int ret = 0, i; + struct nouveau_object *object; + int ret, i; fctx = chan->fence = kzalloc(sizeof(*fctx), GFP_KERNEL); if (!fctx) @@ -56,30 +55,29 @@ nv50_fence_context_new(struct nouveau_channel *chan) nouveau_fence_context_new(&fctx->base); - ret = nouveau_gpuobj_dma_new(chan, NV_CLASS_DMA_FROM_MEMORY, - mem->start * PAGE_SIZE, mem->size, - NV_MEM_ACCESS_RW, - NV_MEM_TARGET_VRAM, &obj); - if (!ret) { - ret = nouveau_ramht_insert(chan, NvSema, obj); - nouveau_gpuobj_ref(NULL, &obj); - } + ret = nouveau_object_new(nv_object(chan->cli), chan->handle, + NvSema, 0x0002, + &(struct nv_dma_class) { + .flags = NV_DMA_TARGET_VRAM | + NV_DMA_ACCESS_RDWR, + .start = mem->start * PAGE_SIZE, + .limit = mem->size - 1, + }, sizeof(struct nv_dma_class), + &object); /* dma objects for display sync channel semaphore blocks */ - for (i = 0; i < chan->dev->mode_config.num_crtc; i++) { - struct nv50_display *pdisp = nv50_display(chan->dev); - struct nv50_display_crtc *dispc = &pdisp->crtc[i]; - struct nouveau_gpuobj *obj = NULL; - - ret = nouveau_gpuobj_dma_new(chan, NV_CLASS_DMA_IN_MEMORY, - dispc->sem.bo->bo.offset, 0x1000, - NV_MEM_ACCESS_RW, - NV_MEM_TARGET_VRAM, &obj); - if (ret) - break; - - ret = nouveau_ramht_insert(chan, NvEvoSema0 + i, obj); - nouveau_gpuobj_ref(NULL, &obj); + for (i = 0; !ret && i < chan->drm->dev->mode_config.num_crtc; i++) { + struct nouveau_bo *bo = nv50sema(chan->drm->dev, i); + + ret = nouveau_object_new(nv_object(chan->cli), chan->handle, + NvEvoSema0 + i, 0x003d, + &(struct nv_dma_class) { + .flags = NV_DMA_TARGET_VRAM | + NV_DMA_ACCESS_RDWR, + .start = bo->bo.offset, + .limit = bo->bo.offset + 0xfff, + }, sizeof(struct nv_dma_class), + &object); } if (ret) @@ -88,13 +86,12 @@ nv50_fence_context_new(struct nouveau_channel *chan) } int -nv50_fence_create(struct drm_device *dev) +nv50_fence_create(struct nouveau_drm *drm) { - struct drm_nouveau_private *dev_priv = dev->dev_private; struct nv50_fence_priv *priv; int ret = 0; - priv = kzalloc(sizeof(*priv), GFP_KERNEL); + priv = drm->fence = kzalloc(sizeof(*priv), GFP_KERNEL); if (!priv) return -ENOMEM; @@ -104,10 +101,9 @@ nv50_fence_create(struct drm_device *dev) priv->base.emit = nv10_fence_emit; priv->base.read = nv10_fence_read; priv->base.sync = nv17_fence_sync; - dev_priv->fence.func = &priv->base; spin_lock_init(&priv->lock); - ret = nouveau_bo_new(dev, 4096, 0x1000, TTM_PL_FLAG_VRAM, + ret = nouveau_bo_new(drm->dev, 4096, 0x1000, TTM_PL_FLAG_VRAM, 0, 0x0000, NULL, &priv->bo); if (!ret) { ret = nouveau_bo_pin(priv->bo, TTM_PL_FLAG_VRAM); @@ -117,9 +113,12 @@ nv50_fence_create(struct drm_device *dev) nouveau_bo_ref(NULL, &priv->bo); } - if (ret == 0) + if (ret == 0) { nouveau_bo_wr32(priv->bo, 0x000, 0x00000000); - else - nv10_fence_destroy(dev); + priv->base.sync = nv17_fence_sync; + } + + if (ret) + nv10_fence_destroy(drm); return ret; } diff --git a/drivers/gpu/drm/nouveau/nv50_pm.c b/drivers/gpu/drm/nouveau/nv50_pm.c index 142cd4e83767..ac0208438ace 100644 --- a/drivers/gpu/drm/nouveau/nv50_pm.c +++ b/drivers/gpu/drm/nouveau/nv50_pm.c @@ -28,7 +28,6 @@ #include "nouveau_hw.h" #include "nouveau_pm.h" #include "nouveau_hwsq.h" -#include "nv50_display.h" enum clk_src { clk_src_crystal, diff --git a/drivers/gpu/drm/nouveau/nv50_software.c b/drivers/gpu/drm/nouveau/nv50_software.c deleted file mode 100644 index 7c9dbe862c44..000000000000 --- a/drivers/gpu/drm/nouveau/nv50_software.c +++ /dev/null @@ -1,181 +0,0 @@ -/* - * 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 "drmP.h" - -#include "nouveau_drv.h" -#include -#include "nouveau_software.h" - -#include "nv50_display.h" - -struct nv50_software_priv { - struct nouveau_software_priv base; -}; - -struct nv50_software_chan { - struct nouveau_software_chan base; -}; - -static int -mthd_dma_vblsem(struct nouveau_channel *chan, u32 class, u32 mthd, u32 data) -{ - struct nv50_software_chan *pch = chan->engctx[NVOBJ_ENGINE_SW]; - struct nouveau_gpuobj *gpuobj; - - gpuobj = nouveau_ramht_find(chan, data); - if (!gpuobj) - return -ENOENT; - - pch->base.vblank.ctxdma = gpuobj->node->offset >> 4; - return 0; -} - -static int -mthd_vblsem_offset(struct nouveau_channel *chan, u32 class, u32 mthd, u32 data) -{ - struct nv50_software_chan *pch = chan->engctx[NVOBJ_ENGINE_SW]; - pch->base.vblank.offset = data; - return 0; -} - -static int -mthd_vblsem_value(struct nouveau_channel *chan, u32 class, u32 mthd, u32 data) -{ - struct nv50_software_chan *pch = chan->engctx[NVOBJ_ENGINE_SW]; - pch->base.vblank.value = data; - return 0; -} - -static int -mthd_vblsem_release(struct nouveau_channel *chan, u32 class, u32 mthd, u32 data) -{ - struct nv50_software_priv *psw = nv_engine(chan->dev, NVOBJ_ENGINE_SW); - struct nv50_software_chan *pch = chan->engctx[NVOBJ_ENGINE_SW]; - struct drm_device *dev = chan->dev; - - if (data > 1) - return -EINVAL; - - drm_vblank_get(dev, data); - - pch->base.vblank.head = data; - list_add(&pch->base.vblank.list, &psw->base.vblank); - return 0; -} - -static int -mthd_flip(struct nouveau_channel *chan, u32 class, u32 mthd, u32 data) -{ - struct nv50_software_chan *pch = chan->engctx[NVOBJ_ENGINE_SW]; - return pch->base.flip(pch->base.flip_data); -} - -static int -nv50_software_context_new(struct nouveau_channel *chan, int engine) -{ - struct nv50_software_chan *pch; - - pch = kzalloc(sizeof(*pch), GFP_KERNEL); - if (!pch) - return -ENOMEM; - - nouveau_software_context_new(chan, &pch->base); - pch->base.vblank.channel = chan->ramin->addr >> 12; - chan->engctx[engine] = pch; - return 0; -} - -static void -nv50_software_context_del(struct nouveau_channel *chan, int engine) -{ - struct nv50_software_chan *pch = chan->engctx[engine]; - chan->engctx[engine] = NULL; - kfree(pch); -} - -static int -nv50_software_object_new(struct nouveau_channel *chan, int engine, - u32 handle, u16 class) -{ - struct drm_device *dev = chan->dev; - struct nouveau_gpuobj *obj = NULL; - int ret; - - ret = nouveau_gpuobj_new(dev, chan, 16, 16, 0, &obj); - if (ret) - return ret; - obj->engine = 0; - obj->class = class; - - ret = nouveau_ramht_insert(chan, handle, obj); - nouveau_gpuobj_ref(NULL, &obj); - return ret; -} - -static int -nv50_software_init(struct drm_device *dev, int engine) -{ - return 0; -} - -static int -nv50_software_fini(struct drm_device *dev, int engine, bool suspend) -{ - return 0; -} - -static void -nv50_software_destroy(struct drm_device *dev, int engine) -{ - struct nv50_software_priv *psw = nv_engine(dev, engine); - - NVOBJ_ENGINE_DEL(dev, SW); - kfree(psw); -} - -int -nv50_software_create(struct drm_device *dev) -{ - struct nv50_software_priv *psw = kzalloc(sizeof(*psw), GFP_KERNEL); - if (!psw) - return -ENOMEM; - - psw->base.base.destroy = nv50_software_destroy; - psw->base.base.init = nv50_software_init; - psw->base.base.fini = nv50_software_fini; - psw->base.base.context_new = nv50_software_context_new; - psw->base.base.context_del = nv50_software_context_del; - psw->base.base.object_new = nv50_software_object_new; - nouveau_software_create(&psw->base); - - NVOBJ_ENGINE_ADD(dev, SW, &psw->base.base); - NVOBJ_CLASS(dev, 0x506e, SW); - NVOBJ_MTHD (dev, 0x506e, 0x018c, mthd_dma_vblsem); - NVOBJ_MTHD (dev, 0x506e, 0x0400, mthd_vblsem_offset); - NVOBJ_MTHD (dev, 0x506e, 0x0404, mthd_vblsem_value); - NVOBJ_MTHD (dev, 0x506e, 0x0408, mthd_vblsem_release); - NVOBJ_MTHD (dev, 0x506e, 0x0500, mthd_flip); - return 0; -} diff --git a/drivers/gpu/drm/nouveau/nv84_fence.c b/drivers/gpu/drm/nouveau/nv84_fence.c index 5ef87edb878d..b0d147a675c4 100644 --- a/drivers/gpu/drm/nouveau/nv84_fence.c +++ b/drivers/gpu/drm/nouveau/nv84_fence.c @@ -22,13 +22,14 @@ * Authors: Ben Skeggs */ -#include "drmP.h" -#include "nouveau_drv.h" -#include "nouveau_dma.h" +#include +#include + #include -#include + +#include "nouveau_drm.h" +#include "nouveau_dma.h" #include "nouveau_fence.h" -#include "nv50_display.h" struct nv84_fence_chan { struct nouveau_fence_chan base; @@ -43,13 +44,14 @@ static int nv84_fence_emit(struct nouveau_fence *fence) { struct nouveau_channel *chan = fence->channel; + struct nouveau_fifo_chan *fifo = (void *)chan->object; int ret = RING_SPACE(chan, 7); if (ret == 0) { BEGIN_NV04(chan, 0, NV11_SUBCHAN_DMA_SEMAPHORE, 1); OUT_RING (chan, NvSema); BEGIN_NV04(chan, 0, NV84_SUBCHAN_SEMAPHORE_ADDRESS_HIGH, 4); - OUT_RING (chan, upper_32_bits(chan->id * 16)); - OUT_RING (chan, lower_32_bits(chan->id * 16)); + OUT_RING (chan, upper_32_bits(fifo->chid * 16)); + OUT_RING (chan, lower_32_bits(fifo->chid * 16)); OUT_RING (chan, fence->sequence); OUT_RING (chan, NV84_SUBCHAN_SEMAPHORE_TRIGGER_WRITE_LONG); FIRE_RING (chan); @@ -62,13 +64,14 @@ static int nv84_fence_sync(struct nouveau_fence *fence, struct nouveau_channel *prev, struct nouveau_channel *chan) { + struct nouveau_fifo_chan *fifo = (void *)prev->object; int ret = RING_SPACE(chan, 7); if (ret == 0) { BEGIN_NV04(chan, 0, NV11_SUBCHAN_DMA_SEMAPHORE, 1); OUT_RING (chan, NvSema); BEGIN_NV04(chan, 0, NV84_SUBCHAN_SEMAPHORE_ADDRESS_HIGH, 4); - OUT_RING (chan, upper_32_bits(prev->id * 16)); - OUT_RING (chan, lower_32_bits(prev->id * 16)); + OUT_RING (chan, upper_32_bits(fifo->chid * 16)); + OUT_RING (chan, lower_32_bits(fifo->chid * 16)); OUT_RING (chan, fence->sequence); OUT_RING (chan, NV84_SUBCHAN_SEMAPHORE_TRIGGER_ACQUIRE_GEQUAL); FIRE_RING (chan); @@ -79,9 +82,9 @@ nv84_fence_sync(struct nouveau_fence *fence, static u32 nv84_fence_read(struct nouveau_channel *chan) { - struct drm_nouveau_private *dev_priv = chan->dev->dev_private; - struct nv84_fence_priv *priv = dev_priv->fence.func; - return nv_ro32(priv->mem, chan->id * 16); + struct nouveau_fifo_chan *fifo = (void *)chan->object; + struct nv84_fence_priv *priv = chan->drm->fence; + return nv_ro32(priv->mem, fifo->chid * 16); } static void @@ -96,10 +99,10 @@ nv84_fence_context_del(struct nouveau_channel *chan) static int nv84_fence_context_new(struct nouveau_channel *chan) { - struct drm_nouveau_private *dev_priv = chan->dev->dev_private; - struct nv84_fence_priv *priv = dev_priv->fence.func; + struct nouveau_fifo_chan *fifo = (void *)chan->object; + struct nv84_fence_priv *priv = chan->drm->fence; struct nv84_fence_chan *fctx; - struct nouveau_gpuobj *obj; + struct nouveau_object *object; int ret, i; fctx = chan->fence = kzalloc(sizeof(*fctx), GFP_KERNEL); @@ -108,58 +111,56 @@ nv84_fence_context_new(struct nouveau_channel *chan) nouveau_fence_context_new(&fctx->base); - ret = nouveau_gpuobj_dma_new(chan, NV_CLASS_DMA_FROM_MEMORY, - priv->mem->addr, priv->mem->size, - NV_MEM_ACCESS_RW, - NV_MEM_TARGET_VRAM, &obj); - if (ret == 0) { - ret = nouveau_ramht_insert(chan, NvSema, obj); - nouveau_gpuobj_ref(NULL, &obj); - nv_wo32(priv->mem, chan->id * 16, 0x00000000); - } + ret = nouveau_object_new(nv_object(chan->cli), chan->handle, + NvSema, 0x0002, + &(struct nv_dma_class) { + .flags = NV_DMA_TARGET_VRAM | + NV_DMA_ACCESS_RDWR, + .start = priv->mem->addr, + .limit = priv->mem->addr + + priv->mem->size - 1, + }, sizeof(struct nv_dma_class), + &object); /* dma objects for display sync channel semaphore blocks */ - for (i = 0; i < chan->dev->mode_config.num_crtc; i++) { - struct nv50_display *pdisp = nv50_display(chan->dev); - struct nv50_display_crtc *dispc = &pdisp->crtc[i]; - struct nouveau_gpuobj *obj = NULL; - - ret = nouveau_gpuobj_dma_new(chan, NV_CLASS_DMA_IN_MEMORY, - dispc->sem.bo->bo.offset, 0x1000, - NV_MEM_ACCESS_RW, - NV_MEM_TARGET_VRAM, &obj); - if (ret) - break; - - ret = nouveau_ramht_insert(chan, NvEvoSema0 + i, obj); - nouveau_gpuobj_ref(NULL, &obj); + for (i = 0; !ret && i < chan->drm->dev->mode_config.num_crtc; i++) { + struct nouveau_bo *bo = nv50sema(chan->drm->dev, i); + + ret = nouveau_object_new(nv_object(chan->cli), chan->handle, + NvEvoSema0 + i, 0x003d, + &(struct nv_dma_class) { + .flags = NV_DMA_TARGET_VRAM | + NV_DMA_ACCESS_RDWR, + .start = bo->bo.offset, + .limit = bo->bo.offset + 0xfff, + }, sizeof(struct nv_dma_class), + &object); } if (ret) nv84_fence_context_del(chan); + nv_wo32(priv->mem, fifo->chid * 16, 0x00000000); return ret; } static void -nv84_fence_destroy(struct drm_device *dev) +nv84_fence_destroy(struct nouveau_drm *drm) { - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nv84_fence_priv *priv = dev_priv->fence.func; - + struct nv84_fence_priv *priv = drm->fence; nouveau_gpuobj_ref(NULL, &priv->mem); - dev_priv->fence.func = NULL; + drm->fence = NULL; kfree(priv); } int -nv84_fence_create(struct drm_device *dev) +nv84_fence_create(struct nouveau_drm *drm) { - struct nouveau_fifo_priv *pfifo = nv_engine(dev, NVOBJ_ENGINE_FIFO); - struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_fifo *pfifo = nouveau_fifo(drm->device); struct nv84_fence_priv *priv; + u32 chan = pfifo->max + 1; int ret; - priv = kzalloc(sizeof(*priv), GFP_KERNEL); + priv = drm->fence = kzalloc(sizeof(*priv), GFP_KERNEL); if (!priv) return -ENOMEM; @@ -169,15 +170,10 @@ nv84_fence_create(struct drm_device *dev) priv->base.emit = nv84_fence_emit; priv->base.sync = nv84_fence_sync; priv->base.read = nv84_fence_read; - dev_priv->fence.func = priv; - - ret = nouveau_gpuobj_new(dev, NULL, 16 * pfifo->channels, - 0x1000, 0, &priv->mem); - if (ret) - goto out; -out: + ret = nouveau_gpuobj_new(drm->device, NULL, chan * 16, 0x1000, 0, + &priv->mem); if (ret) - nv84_fence_destroy(dev); + nv84_fence_destroy(drm); return ret; } diff --git a/drivers/gpu/drm/nouveau/nvc0_fbcon.c b/drivers/gpu/drm/nouveau/nvc0_fbcon.c index db26e050c73c..cc88f3649909 100644 --- a/drivers/gpu/drm/nouveau/nvc0_fbcon.c +++ b/drivers/gpu/drm/nouveau/nvc0_fbcon.c @@ -22,20 +22,16 @@ * Authors: Ben Skeggs */ -#include "drmP.h" -#include "nouveau_drv.h" +#include "nouveau_drm.h" #include "nouveau_dma.h" -#include #include "nouveau_fbcon.h" -#include int nvc0_fbcon_fillrect(struct fb_info *info, const struct fb_fillrect *rect) { struct nouveau_fbdev *nfbdev = info->par; - struct drm_device *dev = nfbdev->dev; - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_channel *chan = dev_priv->channel; + struct nouveau_drm *drm = nouveau_newpriv(nfbdev->dev); + struct nouveau_channel *chan = drm->channel; int ret; ret = RING_SPACE(chan, rect->rop == ROP_COPY ? 7 : 11); @@ -69,9 +65,8 @@ int nvc0_fbcon_copyarea(struct fb_info *info, const struct fb_copyarea *region) { struct nouveau_fbdev *nfbdev = info->par; - struct drm_device *dev = nfbdev->dev; - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_channel *chan = dev_priv->channel; + struct nouveau_drm *drm = nouveau_newpriv(nfbdev->dev); + struct nouveau_channel *chan = drm->channel; int ret; ret = RING_SPACE(chan, 12); @@ -98,9 +93,8 @@ int nvc0_fbcon_imageblit(struct fb_info *info, const struct fb_image *image) { struct nouveau_fbdev *nfbdev = info->par; - struct drm_device *dev = nfbdev->dev; - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_channel *chan = dev_priv->channel; + struct nouveau_drm *drm = nouveau_newpriv(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)); uint32_t *palette = info->pseudo_palette; @@ -157,12 +151,14 @@ nvc0_fbcon_accel_init(struct fb_info *info) { struct nouveau_fbdev *nfbdev = info->par; struct drm_device *dev = nfbdev->dev; - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_channel *chan = dev_priv->channel; struct nouveau_framebuffer *fb = &nfbdev->nouveau_fb; + struct nouveau_drm *drm = nouveau_newpriv(dev); + struct nouveau_channel *chan = drm->channel; + struct nouveau_object *object; int ret, format; - ret = nouveau_gpuobj_gr_new(chan, 0x902d, 0x902d); + ret = nouveau_object_new(nv_object(chan->cli), NVDRM_CHAN, Nv2D, + 0x902d, NULL, 0, &object); if (ret) return ret; @@ -202,9 +198,6 @@ nvc0_fbcon_accel_init(struct fb_info *info) BEGIN_NVC0(chan, NvSub2D, 0x0000, 1); OUT_RING (chan, 0x0000902d); - BEGIN_NVC0(chan, NvSub2D, 0x0104, 2); - OUT_RING (chan, upper_32_bits(chan->notifier_vma.offset)); - OUT_RING (chan, lower_32_bits(chan->notifier_vma.offset)); BEGIN_NVC0(chan, NvSub2D, 0x0290, 1); OUT_RING (chan, 0); BEGIN_NVC0(chan, NvSub2D, 0x0888, 1); diff --git a/drivers/gpu/drm/nouveau/nvc0_fence.c b/drivers/gpu/drm/nouveau/nvc0_fence.c index 779c5ff4ed70..ce612ad398ad 100644 --- a/drivers/gpu/drm/nouveau/nvc0_fence.c +++ b/drivers/gpu/drm/nouveau/nvc0_fence.c @@ -22,13 +22,15 @@ * Authors: Ben Skeggs */ -#include "drmP.h" -#include "nouveau_drv.h" -#include "nouveau_dma.h" +#include +#include +#include + #include -#include + +#include "nouveau_drm.h" +#include "nouveau_dma.h" #include "nouveau_fence.h" -#include "nv50_display.h" struct nvc0_fence_priv { struct nouveau_fence_priv base; @@ -54,7 +56,8 @@ nvc0_fence_emit(struct nouveau_fence *fence) { struct nouveau_channel *chan = fence->channel; struct nvc0_fence_chan *fctx = chan->fence; - u64 addr = fctx->vma.offset + chan->id * 16; + struct nouveau_fifo_chan *fifo = (void *)chan->object; + u64 addr = fctx->vma.offset + fifo->chid * 16; int ret; ret = RING_SPACE(chan, 5); @@ -75,7 +78,8 @@ nvc0_fence_sync(struct nouveau_fence *fence, struct nouveau_channel *prev, struct nouveau_channel *chan) { struct nvc0_fence_chan *fctx = chan->fence; - u64 addr = fctx->vma.offset + prev->id * 16; + struct nouveau_fifo_chan *fifo = (void *)prev->object; + u64 addr = fctx->vma.offset + fifo->chid * 16; int ret; ret = RING_SPACE(chan, 5); @@ -95,31 +99,29 @@ nvc0_fence_sync(struct nouveau_fence *fence, static u32 nvc0_fence_read(struct nouveau_channel *chan) { - struct drm_nouveau_private *dev_priv = chan->dev->dev_private; - struct nvc0_fence_priv *priv = dev_priv->fence.func; - return nouveau_bo_rd32(priv->bo, chan->id * 16/4); + struct nouveau_fifo_chan *fifo = (void *)chan->object; + struct nvc0_fence_priv *priv = chan->drm->fence; + return nouveau_bo_rd32(priv->bo, fifo->chid * 16/4); } static void nvc0_fence_context_del(struct nouveau_channel *chan) { - struct drm_device *dev = chan->dev; - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nvc0_fence_priv *priv = dev_priv->fence.func; + struct drm_device *dev = chan->drm->dev; + struct nvc0_fence_priv *priv = chan->drm->fence; struct nvc0_fence_chan *fctx = chan->fence; int i; - if (dev_priv->card_type >= NV_D0) { + if (nv_device(chan->drm->device)->card_type >= NV_D0) { for (i = 0; i < dev->mode_config.num_crtc; i++) { - struct nouveau_bo *bo = nvd0_display_crtc_sema(dev, i); + struct nouveau_bo *bo = nvd0sema(dev, i); nouveau_bo_vma_del(bo, &fctx->dispc_vma[i]); } } else - if (dev_priv->card_type >= NV_50) { - struct nv50_display *disp = nv50_display(dev); + if (nv_device(chan->drm->device)->card_type >= NV_50) { for (i = 0; i < dev->mode_config.num_crtc; i++) { - struct nv50_display_crtc *dispc = &disp->crtc[i]; - nouveau_bo_vma_del(dispc->sem.bo, &fctx->dispc_vma[i]); + struct nouveau_bo *bo = nv50sema(dev, i); + nouveau_bo_vma_del(bo, &fctx->dispc_vma[i]); } } @@ -132,9 +134,9 @@ nvc0_fence_context_del(struct nouveau_channel *chan) static int nvc0_fence_context_new(struct nouveau_channel *chan) { - struct drm_device *dev = chan->dev; - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nvc0_fence_priv *priv = dev_priv->fence.func; + struct nouveau_fifo_chan *fifo = (void *)chan->object; + struct nouveau_client *client = nouveau_client(fifo); + struct nvc0_fence_priv *priv = chan->drm->fence; struct nvc0_fence_chan *fctx; int ret, i; @@ -144,36 +146,35 @@ nvc0_fence_context_new(struct nouveau_channel *chan) nouveau_fence_context_new(&fctx->base); - ret = nouveau_bo_vma_add(priv->bo, chan->vm, &fctx->vma); + ret = nouveau_bo_vma_add(priv->bo, client->vm, &fctx->vma); if (ret) nvc0_fence_context_del(chan); /* map display semaphore buffers into channel's vm */ - for (i = 0; !ret && i < dev->mode_config.num_crtc; i++) { + for (i = 0; !ret && i < chan->drm->dev->mode_config.num_crtc; i++) { struct nouveau_bo *bo; - if (dev_priv->card_type >= NV_D0) - bo = nvd0_display_crtc_sema(dev, i); + if (nv_device(chan->drm->device)->card_type >= NV_D0) + bo = nvd0sema(chan->drm->dev, i); else - bo = nv50_display(dev)->crtc[i].sem.bo; + bo = nv50sema(chan->drm->dev, i); - ret = nouveau_bo_vma_add(bo, chan->vm, &fctx->dispc_vma[i]); + ret = nouveau_bo_vma_add(bo, client->vm, &fctx->dispc_vma[i]); } - nouveau_bo_wr32(priv->bo, chan->id * 16/4, 0x00000000); + nouveau_bo_wr32(priv->bo, fifo->chid * 16/4, 0x00000000); return ret; } static bool -nvc0_fence_suspend(struct drm_device *dev) +nvc0_fence_suspend(struct nouveau_drm *drm) { - struct nouveau_fifo_priv *pfifo = nv_engine(dev, NVOBJ_ENGINE_FIFO); - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nvc0_fence_priv *priv = dev_priv->fence.func; + struct nouveau_fifo *pfifo = nouveau_fifo(drm->device); + struct nvc0_fence_priv *priv = drm->fence; int i; - priv->suspend = vmalloc(pfifo->channels * sizeof(u32)); + priv->suspend = vmalloc((pfifo->max + 1) * sizeof(u32)); if (priv->suspend) { - for (i = 0; i < pfifo->channels; i++) + for (i = 0; i <= pfifo->max; i++) priv->suspend[i] = nouveau_bo_rd32(priv->bo, i); } @@ -181,15 +182,14 @@ nvc0_fence_suspend(struct drm_device *dev) } static void -nvc0_fence_resume(struct drm_device *dev) +nvc0_fence_resume(struct nouveau_drm *drm) { - struct nouveau_fifo_priv *pfifo = nv_engine(dev, NVOBJ_ENGINE_FIFO); - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nvc0_fence_priv *priv = dev_priv->fence.func; + struct nouveau_fifo *pfifo = nouveau_fifo(drm->device); + struct nvc0_fence_priv *priv = drm->fence; int i; if (priv->suspend) { - for (i = 0; i < pfifo->channels; i++) + for (i = 0; i <= pfifo->max; i++) nouveau_bo_wr32(priv->bo, i, priv->suspend[i]); vfree(priv->suspend); priv->suspend = NULL; @@ -197,26 +197,23 @@ nvc0_fence_resume(struct drm_device *dev) } static void -nvc0_fence_destroy(struct drm_device *dev) +nvc0_fence_destroy(struct nouveau_drm *drm) { - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nvc0_fence_priv *priv = dev_priv->fence.func; - + struct nvc0_fence_priv *priv = drm->fence; nouveau_bo_unmap(priv->bo); nouveau_bo_ref(NULL, &priv->bo); - dev_priv->fence.func = NULL; + drm->fence = NULL; kfree(priv); } int -nvc0_fence_create(struct drm_device *dev) +nvc0_fence_create(struct nouveau_drm *drm) { - struct nouveau_fifo_priv *pfifo = nv_engine(dev, NVOBJ_ENGINE_FIFO); - struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_fifo *pfifo = nouveau_fifo(drm->device); struct nvc0_fence_priv *priv; int ret; - priv = kzalloc(sizeof(*priv), GFP_KERNEL); + priv = drm->fence = kzalloc(sizeof(*priv), GFP_KERNEL); if (!priv) return -ENOMEM; @@ -228,10 +225,9 @@ nvc0_fence_create(struct drm_device *dev) priv->base.emit = nvc0_fence_emit; priv->base.sync = nvc0_fence_sync; priv->base.read = nvc0_fence_read; - dev_priv->fence.func = priv; - ret = nouveau_bo_new(dev, 16 * pfifo->channels, 0, TTM_PL_FLAG_VRAM, - 0, 0, NULL, &priv->bo); + ret = nouveau_bo_new(drm->dev, 16 * (pfifo->max + 1), 0, + TTM_PL_FLAG_VRAM, 0, 0, NULL, &priv->bo); if (ret == 0) { ret = nouveau_bo_pin(priv->bo, TTM_PL_FLAG_VRAM); if (ret == 0) @@ -241,6 +237,6 @@ nvc0_fence_create(struct drm_device *dev) } if (ret) - nvc0_fence_destroy(dev); + nvc0_fence_destroy(drm); return ret; } diff --git a/drivers/gpu/drm/nouveau/nvc0_software.c b/drivers/gpu/drm/nouveau/nvc0_software.c deleted file mode 100644 index eaaa5768f4f7..000000000000 --- a/drivers/gpu/drm/nouveau/nvc0_software.c +++ /dev/null @@ -1,109 +0,0 @@ -/* - * 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 "drmP.h" - -#include "nouveau_drv.h" -#include -#include "nouveau_software.h" - -#include "nv50_display.h" - -struct nvc0_software_priv { - struct nouveau_software_priv base; -}; - -struct nvc0_software_chan { - struct nouveau_software_chan base; -}; - -static int -nvc0_software_context_new(struct nouveau_channel *chan, int engine) -{ - struct nvc0_software_chan *pch; - - pch = kzalloc(sizeof(*pch), GFP_KERNEL); - if (!pch) - return -ENOMEM; - - nouveau_software_context_new(chan, &pch->base); - chan->engctx[engine] = pch; - return 0; -} - -static void -nvc0_software_context_del(struct nouveau_channel *chan, int engine) -{ - struct nvc0_software_chan *pch = chan->engctx[engine]; - chan->engctx[engine] = NULL; - kfree(pch); -} - -static int -nvc0_software_object_new(struct nouveau_channel *chan, int engine, - u32 handle, u16 class) -{ - return 0; -} - -static int -nvc0_software_init(struct drm_device *dev, int engine) -{ - return 0; -} - -static int -nvc0_software_fini(struct drm_device *dev, int engine, bool suspend) -{ - return 0; -} - -static void -nvc0_software_destroy(struct drm_device *dev, int engine) -{ - struct nvc0_software_priv *psw = nv_engine(dev, engine); - - NVOBJ_ENGINE_DEL(dev, SW); - kfree(psw); -} - -int -nvc0_software_create(struct drm_device *dev) -{ - struct nvc0_software_priv *psw = kzalloc(sizeof(*psw), GFP_KERNEL); - if (!psw) - return -ENOMEM; - - psw->base.base.destroy = nvc0_software_destroy; - psw->base.base.init = nvc0_software_init; - psw->base.base.fini = nvc0_software_fini; - psw->base.base.context_new = nvc0_software_context_new; - psw->base.base.context_del = nvc0_software_context_del; - psw->base.base.object_new = nvc0_software_object_new; - nouveau_software_create(&psw->base); - - NVOBJ_ENGINE_ADD(dev, SW, &psw->base.base); - NVOBJ_CLASS(dev, 0x906e, SW); - return 0; -} diff --git a/drivers/gpu/drm/nouveau/nvd0_display.c b/drivers/gpu/drm/nouveau/nvd0_display.c index 2da4927b5e06..37b3f3f071d9 100644 --- a/drivers/gpu/drm/nouveau/nvd0_display.c +++ b/drivers/gpu/drm/nouveau/nvd0_display.c @@ -31,7 +31,6 @@ #include "nouveau_connector.h" #include "nouveau_encoder.h" #include "nouveau_crtc.h" -#include "nouveau_dma.h" #include "nouveau_fb.h" #include "nouveau_fence.h" #include "nv50_display.h" @@ -1830,15 +1829,7 @@ nvd0_display_intr(struct drm_device *dev) intr &= ~0x00100000; } - for (i = 0; i < dev->mode_config.num_crtc; i++) { - u32 mask = 0x01000000 << i; - if (intr & mask) { - u32 stat = nv_rd32(dev, 0x6100bc + (i * 0x800)); - nv_wr32(dev, 0x6100bc + (i * 0x800), stat); - intr &= ~mask; - } - } - + intr &= ~0x0f000000; /* vblank, handled in core */ if (intr) NV_INFO(dev, "PDISP: unknown intr 0x%08x\n", intr); } -- cgit v1.2.3 From 08c770969a45361277d556f9fd3e2d70da42be65 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Sun, 22 Jul 2012 15:03:09 +1000 Subject: drm/nouveau: start culling unused code Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/nouveau_drv.c | 7 -- drivers/gpu/drm/nouveau/nouveau_drv.h | 135 -------------------------------- drivers/gpu/drm/nouveau/nouveau_hw.c | 8 +- drivers/gpu/drm/nouveau/nouveau_hw.h | 25 ------ drivers/gpu/drm/nouveau/nouveau_irq.c | 1 - drivers/gpu/drm/nouveau/nouveau_mem.c | 23 ------ drivers/gpu/drm/nouveau/nouveau_state.c | 32 -------- drivers/gpu/drm/nouveau/nvd0_display.c | 12 --- 8 files changed, 4 insertions(+), 239 deletions(-) (limited to 'drivers/gpu/drm/nouveau/nouveau_mem.c') diff --git a/drivers/gpu/drm/nouveau/nouveau_drv.c b/drivers/gpu/drm/nouveau/nouveau_drv.c index 2294cb8848f7..666c178c6022 100644 --- a/drivers/gpu/drm/nouveau/nouveau_drv.c +++ b/drivers/gpu/drm/nouveau/nouveau_drv.c @@ -87,13 +87,6 @@ MODULE_PARM_DESC(tv_norm, "Default TV norm.\n" char *nouveau_tv_norm; module_param_named(tv_norm, nouveau_tv_norm, charp, 0400); -MODULE_PARM_DESC(reg_debug, "Register access debug bitmask:\n" - "\t\t0x1 mc, 0x2 video, 0x4 fb, 0x8 extdev,\n" - "\t\t0x10 crtc, 0x20 ramdac, 0x40 vgacrtc, 0x80 rmvio,\n" - "\t\t0x100 vgaattr, 0x200 EVO (G80+)"); -int nouveau_reg_debug; -module_param_named(reg_debug, nouveau_reg_debug, int, 0600); - MODULE_PARM_DESC(perflvl, "Performance level (default: boot)"); char *nouveau_perflvl; module_param_named(perflvl, nouveau_perflvl, charp, 0400); diff --git a/drivers/gpu/drm/nouveau/nouveau_drv.h b/drivers/gpu/drm/nouveau/nouveau_drv.h index f1cce652a2a9..16b7bb6951cc 100644 --- a/drivers/gpu/drm/nouveau/nouveau_drv.h +++ b/drivers/gpu/drm/nouveau/nouveau_drv.h @@ -64,15 +64,10 @@ enum blah { NV_MEM_TYPE_GDDR5 }; -#define DRM_FILE_PAGE_OFFSET (0x100000000ULL >> PAGE_SHIFT) - #include #include "nouveau_reg.h" #include -struct nouveau_grctx; -struct nouveau_mem; - #include #include "nouveau_compat.h" @@ -85,18 +80,9 @@ struct nouveau_mem; #define nv50_vm_flush_engine(d,e) \ _nv50_vm_flush_engine((d), (e)) -#define MAX_NUM_DCB_ENTRIES 16 - -#define NOUVEAU_MAX_CHANNEL_NR 4096 - #include "nouveau_bo.h" #include "nouveau_gem.h" -enum nouveau_flags { - NV_NFORCE = 0x10000000, - NV_NFORCE2 = 0x20000000 -}; - struct nouveau_page_flip_state { struct list_head head; struct drm_pending_vblank_event *event; @@ -104,11 +90,6 @@ struct nouveau_page_flip_state { uint64_t offset; }; -enum nouveau_channel_mutex_class { - NOUVEAU_UCHANNEL_MUTEX, - NOUVEAU_KCHANNEL_MUTEX -}; - struct nouveau_display_engine { void *priv; int (*early_init)(struct drm_device *); @@ -306,11 +287,8 @@ enum nouveau_card_type { NV_E0 = 0xe0, }; -struct nouveau_channel; - struct drm_nouveau_private { struct drm_device *dev; - bool noaccel; void *newpriv; @@ -318,11 +296,8 @@ struct drm_nouveau_private { enum nouveau_card_type card_type; /* exact chipset, derived from NV_PMC_BOOT_0 */ int chipset; - int flags; u32 crystal; - struct nouveau_bo *vga_ram; - /* interrupt handling */ void (*irq_handler[32])(struct drm_device *); bool msi_enabled; @@ -332,16 +307,8 @@ struct drm_nouveau_private { /* For PFIFO and PGRAPH. */ spinlock_t context_switch_lock; - /* RAMIN configuration, RAMFC, RAMHT and RAMRO offsets */ - struct nouveau_ramht *ramht; - - uint64_t fb_available_size; - uint64_t fb_mappable_pages; - int fb_mtrr; - struct nvbios vbios; u8 *mxms; - struct list_head i2c_ports; struct backlight_device *backlight; }; @@ -363,9 +330,7 @@ extern char *nouveau_vram_type; extern int nouveau_fbpercrtc; extern int nouveau_tv_disable; extern char *nouveau_tv_norm; -extern int nouveau_reg_debug; extern int nouveau_ignorelid; -extern int nouveau_noaccel; extern int nouveau_force_post; extern int nouveau_override_conntype; extern char *nouveau_perflvl; @@ -382,34 +347,13 @@ 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 bool nouveau_wait_for_idle(struct drm_device *); extern int nouveau_card_init(struct drm_device *); /* nouveau_mem.c */ -extern int nouveau_mem_vram_init(struct drm_device *); -extern void nouveau_mem_vram_fini(struct drm_device *); -extern int nouveau_mem_gart_init(struct drm_device *); -extern void nouveau_mem_gart_fini(struct drm_device *); -extern void nouveau_mem_close(struct drm_device *); -extern bool nouveau_mem_flags_valid(struct drm_device *, u32 tile_flags); 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 *); -extern int nouveau_mem_vbios_type(struct drm_device *); -extern struct nouveau_tile_reg *nv10_mem_set_tiling( - struct drm_device *dev, uint32_t addr, uint32_t size, - uint32_t pitch, uint32_t flags); -extern void nv10_mem_put_tile_region(struct drm_device *dev, - struct nouveau_tile_reg *tile, - struct nouveau_fence *fence); - -extern int nouveau_channel_idle(struct nouveau_channel *chan); - -/* nouveau_gpuobj.c */ -int nouveau_gpuobj_map_vm(struct nouveau_gpuobj *gpuobj, struct nouveau_vm *vm, - u32 flags, struct nouveau_vma *vma); -void nouveau_gpuobj_unmap(struct nouveau_vma *vma); /* nouveau_irq.c */ extern int nouveau_irq_init(struct drm_device *); @@ -586,26 +530,6 @@ int nouveau_display_dumb_destroy(struct drm_file *, struct drm_device *, } \ } while(0) -/* nouveau_reg_debug bitmask */ -enum { - NOUVEAU_REG_DEBUG_MC = 0x1, - NOUVEAU_REG_DEBUG_VIDEO = 0x2, - NOUVEAU_REG_DEBUG_FB = 0x4, - NOUVEAU_REG_DEBUG_EXTDEV = 0x8, - NOUVEAU_REG_DEBUG_CRTC = 0x10, - NOUVEAU_REG_DEBUG_RAMDAC = 0x20, - NOUVEAU_REG_DEBUG_VGACRTC = 0x40, - NOUVEAU_REG_DEBUG_RMVIO = 0x80, - NOUVEAU_REG_DEBUG_VGAATTR = 0x100, - NOUVEAU_REG_DEBUG_EVO = 0x200, - NOUVEAU_REG_DEBUG_AUXCH = 0x400 -}; - -#define NV_REG_DEBUG(type, dev, fmt, arg...) do { \ - if (nouveau_reg_debug & NOUVEAU_REG_DEBUG_##type) \ - NV_PRINTK(KERN_DEBUG, dev, "%s: " fmt, __func__, ##arg); \ -} while (0) - static inline bool nv_two_heads(struct drm_device *dev) { @@ -645,63 +569,4 @@ nv_match_device(struct drm_device *dev, unsigned device, dev->pdev->subsystem_device == sub_device; } -/* returns 1 if device is one of the nv4x using the 0x4497 object class, - * helpful to determine a number of other hardware features - */ -static inline int -nv44_graph_class(struct drm_device *dev) -{ - struct drm_nouveau_private *dev_priv = dev->dev_private; - - if ((dev_priv->chipset & 0xf0) == 0x60) - return 1; - - return !(0x0baf & (1 << (dev_priv->chipset & 0x0f))); -} - -/* memory type/access flags, do not match hardware values */ -#define NV_MEM_ACCESS_RO 1 -#define NV_MEM_ACCESS_WO 2 -#define NV_MEM_ACCESS_RW (NV_MEM_ACCESS_RO | NV_MEM_ACCESS_WO) -#define NV_MEM_ACCESS_SYS 4 -#define NV_MEM_ACCESS_VM 8 -#define NV_MEM_ACCESS_NOSNOOP 16 - -#define NV_MEM_TARGET_VRAM 0 -#define NV_MEM_TARGET_PCI 1 -#define NV_MEM_TARGET_PCI_NOSNOOP 2 -#define NV_MEM_TARGET_VM 3 -#define NV_MEM_TARGET_GART 4 - -#define NV_MEM_TYPE_VM 0x7f -#define NV_MEM_COMP_VM 0x03 - -/* FIFO methods */ -#define NV01_SUBCHAN_OBJECT 0x00000000 -#define NV84_SUBCHAN_SEMAPHORE_ADDRESS_HIGH 0x00000010 -#define NV84_SUBCHAN_SEMAPHORE_ADDRESS_LOW 0x00000014 -#define NV84_SUBCHAN_SEMAPHORE_SEQUENCE 0x00000018 -#define NV84_SUBCHAN_SEMAPHORE_TRIGGER 0x0000001c -#define NV84_SUBCHAN_SEMAPHORE_TRIGGER_ACQUIRE_EQUAL 0x00000001 -#define NV84_SUBCHAN_SEMAPHORE_TRIGGER_WRITE_LONG 0x00000002 -#define NV84_SUBCHAN_SEMAPHORE_TRIGGER_ACQUIRE_GEQUAL 0x00000004 -#define NVC0_SUBCHAN_SEMAPHORE_TRIGGER_YIELD 0x00001000 -#define NV84_SUBCHAN_NOTIFY_INTR 0x00000020 -#define NV84_SUBCHAN_WRCACHE_FLUSH 0x00000024 -#define NV10_SUBCHAN_REF_CNT 0x00000050 -#define NVSW_SUBCHAN_PAGE_FLIP 0x00000054 -#define NV11_SUBCHAN_DMA_SEMAPHORE 0x00000060 -#define NV11_SUBCHAN_SEMAPHORE_OFFSET 0x00000064 -#define NV11_SUBCHAN_SEMAPHORE_ACQUIRE 0x00000068 -#define NV11_SUBCHAN_SEMAPHORE_RELEASE 0x0000006c -#define NV40_SUBCHAN_YIELD 0x00000080 - -/* NV_SW object class */ -#define NV_SW 0x0000506e -#define NV_SW_DMA_VBLSEM 0x0000018c -#define NV_SW_VBLSEM_OFFSET 0x00000400 -#define NV_SW_VBLSEM_RELEASE_VALUE 0x00000404 -#define NV_SW_VBLSEM_RELEASE 0x00000408 -#define NV_SW_PAGE_FLIP 0x00000500 - #endif /* __NOUVEAU_DRV_H__ */ diff --git a/drivers/gpu/drm/nouveau/nouveau_hw.c b/drivers/gpu/drm/nouveau/nouveau_hw.c index 9cae3eb508c4..900bfb0c6e9a 100644 --- a/drivers/gpu/drm/nouveau/nouveau_hw.c +++ b/drivers/gpu/drm/nouveau/nouveau_hw.c @@ -674,10 +674,10 @@ nv_load_state_ext(struct drm_device *dev, int head, nvWriteVIDEO(dev, NV_PVIDEO_INTR_EN, 0); nvWriteVIDEO(dev, NV_PVIDEO_OFFSET_BUFF(0), 0); nvWriteVIDEO(dev, NV_PVIDEO_OFFSET_BUFF(1), 0); - nvWriteVIDEO(dev, NV_PVIDEO_LIMIT(0), dev_priv->fb_available_size - 1); - nvWriteVIDEO(dev, NV_PVIDEO_LIMIT(1), dev_priv->fb_available_size - 1); - nvWriteVIDEO(dev, NV_PVIDEO_UVPLANE_LIMIT(0), dev_priv->fb_available_size - 1); - nvWriteVIDEO(dev, NV_PVIDEO_UVPLANE_LIMIT(1), dev_priv->fb_available_size - 1); + nvWriteVIDEO(dev, NV_PVIDEO_LIMIT(0), 0); //dev_priv->fb_available_size - 1); + nvWriteVIDEO(dev, NV_PVIDEO_LIMIT(1), 0); //dev_priv->fb_available_size - 1); + nvWriteVIDEO(dev, NV_PVIDEO_UVPLANE_LIMIT(0), 0); //dev_priv->fb_available_size - 1); + nvWriteVIDEO(dev, NV_PVIDEO_UVPLANE_LIMIT(1), 0); //dev_priv->fb_available_size - 1); nvWriteMC(dev, NV_PBUS_POWERCTRL_2, 0); NVWriteCRTC(dev, head, NV_PCRTC_CURSOR_CONFIG, regp->cursor_cfg); diff --git a/drivers/gpu/drm/nouveau/nouveau_hw.h b/drivers/gpu/drm/nouveau/nouveau_hw.h index feb2a2f7bd42..3febf19a8883 100644 --- a/drivers/gpu/drm/nouveau/nouveau_hw.h +++ b/drivers/gpu/drm/nouveau/nouveau_hw.h @@ -61,14 +61,12 @@ static inline uint32_t nvReadMC(struct drm_device *dev, uint32_t reg) { uint32_t val = nv_rd32(dev, reg); - NV_REG_DEBUG(MC, dev, "reg %08x val %08x\n", reg, val); return val; } static inline void nvWriteMC(struct drm_device *dev, uint32_t reg, uint32_t val) { - NV_REG_DEBUG(MC, dev, "reg %08x val %08x\n", reg, val); nv_wr32(dev, reg, val); } @@ -76,14 +74,12 @@ static inline uint32_t nvReadVIDEO(struct drm_device *dev, uint32_t reg) { uint32_t val = nv_rd32(dev, reg); - NV_REG_DEBUG(VIDEO, dev, "reg %08x val %08x\n", reg, val); return val; } static inline void nvWriteVIDEO(struct drm_device *dev, uint32_t reg, uint32_t val) { - NV_REG_DEBUG(VIDEO, dev, "reg %08x val %08x\n", reg, val); nv_wr32(dev, reg, val); } @@ -91,14 +87,12 @@ static inline uint32_t nvReadFB(struct drm_device *dev, uint32_t reg) { uint32_t val = nv_rd32(dev, reg); - NV_REG_DEBUG(FB, dev, "reg %08x val %08x\n", reg, val); return val; } static inline void nvWriteFB(struct drm_device *dev, uint32_t reg, uint32_t val) { - NV_REG_DEBUG(FB, dev, "reg %08x val %08x\n", reg, val); nv_wr32(dev, reg, val); } @@ -106,14 +100,12 @@ static inline uint32_t nvReadEXTDEV(struct drm_device *dev, uint32_t reg) { uint32_t val = nv_rd32(dev, reg); - NV_REG_DEBUG(EXTDEV, dev, "reg %08x val %08x\n", reg, val); return val; } static inline void nvWriteEXTDEV(struct drm_device *dev, uint32_t reg, uint32_t val) { - NV_REG_DEBUG(EXTDEV, dev, "reg %08x val %08x\n", reg, val); nv_wr32(dev, reg, val); } @@ -124,7 +116,6 @@ static inline uint32_t NVReadCRTC(struct drm_device *dev, if (head) reg += NV_PCRTC0_SIZE; val = nv_rd32(dev, reg); - NV_REG_DEBUG(CRTC, dev, "head %d reg %08x val %08x\n", head, reg, val); return val; } @@ -133,7 +124,6 @@ static inline void NVWriteCRTC(struct drm_device *dev, { if (head) reg += NV_PCRTC0_SIZE; - NV_REG_DEBUG(CRTC, dev, "head %d reg %08x val %08x\n", head, reg, val); nv_wr32(dev, reg, val); } @@ -144,8 +134,6 @@ static inline uint32_t NVReadRAMDAC(struct drm_device *dev, if (head) reg += NV_PRAMDAC0_SIZE; val = nv_rd32(dev, reg); - NV_REG_DEBUG(RAMDAC, dev, "head %d reg %08x val %08x\n", - head, reg, val); return val; } @@ -154,8 +142,6 @@ static inline void NVWriteRAMDAC(struct drm_device *dev, { if (head) reg += NV_PRAMDAC0_SIZE; - NV_REG_DEBUG(RAMDAC, dev, "head %d reg %08x val %08x\n", - head, reg, val); nv_wr32(dev, reg, val); } @@ -182,8 +168,6 @@ 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_REG_DEBUG(VGACRTC, dev, "head %d index 0x%02x data 0x%02x\n", - head, index, 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); } @@ -194,8 +178,6 @@ static inline uint8_t NVReadVgaCrtc(struct drm_device *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_REG_DEBUG(VGACRTC, dev, "head %d index 0x%02x data 0x%02x\n", - head, index, val); return val; } @@ -238,7 +220,6 @@ static inline uint8_t NVReadPRMVIO(struct drm_device *dev, reg += NV_PRMVIO_SIZE; val = nv_rd08(dev, reg); - NV_REG_DEBUG(RMVIO, dev, "head %d reg %08x val %02x\n", head, reg, val); return val; } @@ -252,8 +233,6 @@ static inline void NVWritePRMVIO(struct drm_device *dev, if (head && dev_priv->card_type == NV_40) reg += NV_PRMVIO_SIZE; - NV_REG_DEBUG(RMVIO, dev, "head %d reg %08x val %02x\n", - head, reg, value); nv_wr08(dev, reg, value); } @@ -278,8 +257,6 @@ static inline void NVWriteVgaAttr(struct drm_device *dev, index |= 0x20; nv_rd08(dev, NV_PRMCIO_INP0__COLOR + head * NV_PRMCIO_SIZE); - NV_REG_DEBUG(VGAATTR, dev, "head %d index 0x%02x data 0x%02x\n", - head, index, value); nv_wr08(dev, NV_PRMCIO_ARX + head * NV_PRMCIO_SIZE, index); nv_wr08(dev, NV_PRMCIO_AR__WRITE + head * NV_PRMCIO_SIZE, value); } @@ -296,8 +273,6 @@ static inline uint8_t NVReadVgaAttr(struct drm_device *dev, 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_REG_DEBUG(VGAATTR, dev, "head %d index 0x%02x data 0x%02x\n", - head, index, val); return val; } diff --git a/drivers/gpu/drm/nouveau/nouveau_irq.c b/drivers/gpu/drm/nouveau/nouveau_irq.c index 25e2e63cc53a..d5281499744b 100644 --- a/drivers/gpu/drm/nouveau/nouveau_irq.c +++ b/drivers/gpu/drm/nouveau/nouveau_irq.c @@ -35,7 +35,6 @@ #include #include "nouveau_drv.h" #include "nouveau_reg.h" -#include void nouveau_irq_preinstall(struct drm_device *dev) diff --git a/drivers/gpu/drm/nouveau/nouveau_mem.c b/drivers/gpu/drm/nouveau/nouveau_mem.c index 9c35d14fe9d6..220c1a877ff5 100644 --- a/drivers/gpu/drm/nouveau/nouveau_mem.c +++ b/drivers/gpu/drm/nouveau/nouveau_mem.c @@ -630,26 +630,3 @@ nouveau_mem_exec(struct nouveau_mem_exec_func *exec, return 0; } - -int -nouveau_mem_vbios_type(struct drm_device *dev) -{ - struct bit_entry M; - u8 ramcfg = (nv_rd32(dev, 0x101000) & 0x0000003c) >> 2; - if (!bit_table(dev, 'M', &M) || M.version != 2 || M.length < 5) { - u8 *table = ROMPTR(dev, M.data[3]); - if (table && table[0] == 0x10 && ramcfg < table[3]) { - u8 *entry = table + table[1] + (ramcfg * table[2]); - switch (entry[0] & 0x0f) { - case 0: return NV_MEM_TYPE_DDR2; - case 1: return NV_MEM_TYPE_DDR3; - case 2: return NV_MEM_TYPE_GDDR3; - case 3: return NV_MEM_TYPE_GDDR5; - default: - break; - } - - } - } - return NV_MEM_TYPE_UNKNOWN; -} diff --git a/drivers/gpu/drm/nouveau/nouveau_state.c b/drivers/gpu/drm/nouveau/nouveau_state.c index 4349b337cfdd..047765299c2c 100644 --- a/drivers/gpu/drm/nouveau/nouveau_state.c +++ b/drivers/gpu/drm/nouveau/nouveau_state.c @@ -350,11 +350,6 @@ static void nouveau_card_takedown(struct drm_device *dev) nouveau_backlight_exit(dev); nouveau_display_destroy(dev); - if (dev_priv->vga_ram) { - nouveau_bo_unpin(dev_priv->vga_ram); - nouveau_bo_ref(NULL, &dev_priv->vga_ram); - } - nouveau_bios_takedown(dev); engine->display.late_takedown(dev); @@ -409,8 +404,6 @@ int nouveau_load(struct drm_device *dev, unsigned long flags) dev->dev_private = dev_priv; dev_priv->dev = dev; - dev_priv->flags = flags & NOUVEAU_FLAGS; - NV_DEBUG(dev, "vendor: 0x%X device: 0x%X class: 0x%X\n", dev->pci_vendor, dev->pci_device, dev->pdev->class); @@ -483,12 +476,6 @@ int nouveau_load(struct drm_device *dev, unsigned long flags) nouveau_OF_copy_vbios_to_ramin(dev); - /* Special flags */ - if (dev->pci_device == 0x01a0) - dev_priv->flags |= NV_NFORCE; - else if (dev->pci_device == 0x01f0) - dev_priv->flags |= NV_NFORCE2; - /* For kernel modesetting, init card now and bring up fbcon */ ret = nouveau_card_init(dev); if (ret) @@ -518,22 +505,3 @@ int nouveau_unload(struct drm_device *dev) kfree(dev_priv); return 0; } - -/* Waits for PGRAPH to go completely idle */ -bool nouveau_wait_for_idle(struct drm_device *dev) -{ - struct drm_nouveau_private *dev_priv = dev->dev_private; - uint32_t mask = ~0; - - if (dev_priv->card_type == NV_40) - mask &= ~NV40_PGRAPH_STATUS_SYNC_STALL; - - if (!nv_wait(dev, NV04_PGRAPH_STATUS, mask, 0)) { - NV_ERROR(dev, "PGRAPH idle timed out with status 0x%08x\n", - nv_rd32(dev, NV04_PGRAPH_STATUS)); - return false; - } - - return true; -} - diff --git a/drivers/gpu/drm/nouveau/nvd0_display.c b/drivers/gpu/drm/nouveau/nvd0_display.c index 37b3f3f071d9..77d5ce365bb2 100644 --- a/drivers/gpu/drm/nouveau/nvd0_display.c +++ b/drivers/gpu/drm/nouveau/nvd0_display.c @@ -115,9 +115,6 @@ evo_wait(struct drm_device *dev, int id, int nr) put = 0; } - if (nouveau_reg_debug & NOUVEAU_REG_DEBUG_EVO) - NV_INFO(dev, "Evo%d: %p START\n", id, disp->evo[id].ptr + put); - return disp->evo[id].ptr + put; } @@ -126,15 +123,6 @@ evo_kick(u32 *push, struct drm_device *dev, int id) { struct nvd0_display *disp = nvd0_display(dev); - if (nouveau_reg_debug & NOUVEAU_REG_DEBUG_EVO) { - u32 curp = nv_rd32(dev, 0x640000 + (id * 0x1000)) >> 2; - u32 *cur = disp->evo[id].ptr + curp; - - while (cur < push) - NV_INFO(dev, "Evo%d: 0x%08x\n", id, *cur++); - NV_INFO(dev, "Evo%d: %p KICK!\n", id, push); - } - nv_wr32(dev, 0x640000 + (id * 0x1000), (push - disp->evo[id].ptr) << 2); } -- 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_mem.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_mem.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