diff --git a/packages/linux/meta b/packages/linux/meta index 7953dafa85..a09710262e 100644 --- a/packages/linux/meta +++ b/packages/linux/meta @@ -14,6 +14,6 @@ PKG_LONGDESC="This package contains a precompiled kernel image and the modules." PKG_IS_ADDON="no" if [ "$LINUX_NEXT" = "yes" ]; then - PKG_VERSION="2.6.37-rc2" + PKG_VERSION="2.6.37-rc3" PKG_URL="http://www.kernel.org/pub/linux/kernel/v2.6/testing/$PKG_NAME-$PKG_VERSION.tar.bz2" fi diff --git a/packages/linux/patches/linux-2.6.36-110-drm_nouveau_upstream-20101104.patch b/packages/linux/patches/linux-2.6.36-110-drm_nouveau_upstream-20101104.patch deleted file mode 100644 index e1117bffd6..0000000000 --- a/packages/linux/patches/linux-2.6.36-110-drm_nouveau_upstream-20101104.patch +++ /dev/null @@ -1,21613 +0,0 @@ -diff -Naur linux-2.6.36/drivers/gpu/drm/nouveau/Kconfig linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/Kconfig ---- linux-2.6.36/drivers/gpu/drm/nouveau/Kconfig 2010-10-20 22:30:22.000000000 +0200 -+++ linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/Kconfig 2010-11-05 00:40:00.000000000 +0100 -@@ -10,6 +10,7 @@ - select FB - select FRAMEBUFFER_CONSOLE if !EMBEDDED - select FB_BACKLIGHT if DRM_NOUVEAU_BACKLIGHT -+ select ACPI_VIDEO if ACPI - help - Choose this option for open-source nVidia support. - -diff -Naur linux-2.6.36/drivers/gpu/drm/nouveau/Makefile linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/Makefile ---- linux-2.6.36/drivers/gpu/drm/nouveau/Makefile 2010-10-20 22:30:22.000000000 +0200 -+++ linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/Makefile 2010-11-05 00:40:00.000000000 +0100 -@@ -9,7 +9,8 @@ - nouveau_bo.o nouveau_fence.o nouveau_gem.o nouveau_ttm.o \ - nouveau_hw.o nouveau_calc.o nouveau_bios.o nouveau_i2c.o \ - nouveau_display.o nouveau_connector.o nouveau_fbcon.o \ -- nouveau_dp.o \ -+ nouveau_dp.o nouveau_ramht.o \ -+ nouveau_pm.o nouveau_volt.o nouveau_perf.o nouveau_temp.o \ - nv04_timer.o \ - nv04_mc.o nv40_mc.o nv50_mc.o \ - nv04_fb.o nv10_fb.o nv30_fb.o nv40_fb.o nv50_fb.o nvc0_fb.o \ -@@ -17,13 +18,15 @@ - nv04_graph.o nv10_graph.o nv20_graph.o \ - nv40_graph.o nv50_graph.o nvc0_graph.o \ - nv40_grctx.o nv50_grctx.o \ -+ nv84_crypt.o \ - nv04_instmem.o nv50_instmem.o nvc0_instmem.o \ -- nv50_crtc.o nv50_dac.o nv50_sor.o \ -+ nv50_evo.o nv50_crtc.o nv50_dac.o nv50_sor.o \ - nv50_cursor.o nv50_display.o nv50_fbcon.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 nv04_fbcon.o \ - nv10_gpio.o nv50_gpio.o \ -- nv50_calc.o -+ nv50_calc.o \ -+ nv04_pm.o nv50_pm.o nva3_pm.o - - nouveau-$(CONFIG_DRM_NOUVEAU_DEBUG) += nouveau_debugfs.o - nouveau-$(CONFIG_COMPAT) += nouveau_ioc32.o -diff -Naur linux-2.6.36/drivers/gpu/drm/nouveau/nouveau_acpi.c linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nouveau_acpi.c ---- linux-2.6.36/drivers/gpu/drm/nouveau/nouveau_acpi.c 2010-10-20 22:30:22.000000000 +0200 -+++ linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nouveau_acpi.c 2010-11-05 00:40:00.000000000 +0100 -@@ -292,6 +292,6 @@ - if (ret < 0) - return ret; - -- nv_connector->edid = edid; -+ nv_connector->edid = kmemdup(edid, EDID_LENGTH, GFP_KERNEL); - return 0; - } -diff -Naur linux-2.6.36/drivers/gpu/drm/nouveau/nouveau_backlight.c linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nouveau_backlight.c ---- linux-2.6.36/drivers/gpu/drm/nouveau/nouveau_backlight.c 2010-10-20 22:30:22.000000000 +0200 -+++ linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nouveau_backlight.c 2010-11-05 00:40:00.000000000 +0100 -@@ -31,6 +31,7 @@ - */ - - #include -+#include - - #include "drmP.h" - #include "nouveau_drv.h" -@@ -136,6 +137,14 @@ - { - struct drm_nouveau_private *dev_priv = dev->dev_private; - -+#ifdef CONFIG_ACPI -+ if (acpi_video_backlight_support()) { -+ NV_INFO(dev, "ACPI backlight interface available, " -+ "not registering our own\n"); -+ return 0; -+ } -+#endif -+ - switch (dev_priv->card_type) { - case NV_40: - return nouveau_nv40_backlight_init(dev); -diff -Naur linux-2.6.36/drivers/gpu/drm/nouveau/nouveau_bios.c linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nouveau_bios.c ---- linux-2.6.36/drivers/gpu/drm/nouveau/nouveau_bios.c 2010-10-20 22:30:22.000000000 +0200 -+++ linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nouveau_bios.c 2010-11-05 00:40:00.000000000 +0100 -@@ -43,9 +43,6 @@ - #define BIOSLOG(sip, fmt, arg...) NV_DEBUG(sip->dev, fmt, ##arg) - #define LOG_OLD_VALUE(x) - --#define ROM16(x) le16_to_cpu(*(uint16_t *)&(x)) --#define ROM32(x) le32_to_cpu(*(uint32_t *)&(x)) -- - struct init_exec { - bool execute; - bool repeat; -@@ -272,12 +269,6 @@ - int (*handler)(struct nvbios *, uint16_t, struct init_exec *); - }; - --struct bit_entry { -- uint8_t id[2]; -- uint16_t length; -- uint16_t offset; --}; -- - static int parse_init_table(struct nvbios *, unsigned int, struct init_exec *); - - #define MACRO_INDEX_SIZE 2 -@@ -1231,7 +1222,7 @@ - return 3; - } - -- if (cond & 1) -+ if (!(cond & 1)) - iexec->execute = false; - } - break; -@@ -4675,6 +4666,92 @@ - return 0; - } - -+struct pll_mapping { -+ u8 type; -+ u32 reg; -+}; -+ -+static struct pll_mapping nv04_pll_mapping[] = { -+ { PLL_CORE , NV_PRAMDAC_NVPLL_COEFF }, -+ { PLL_MEMORY, NV_PRAMDAC_MPLL_COEFF }, -+ { PLL_VPLL0 , NV_PRAMDAC_VPLL_COEFF }, -+ { PLL_VPLL1 , NV_RAMDAC_VPLL2 }, -+ {} -+}; -+ -+static struct pll_mapping nv40_pll_mapping[] = { -+ { PLL_CORE , 0x004000 }, -+ { PLL_MEMORY, 0x004020 }, -+ { PLL_VPLL0 , NV_PRAMDAC_VPLL_COEFF }, -+ { PLL_VPLL1 , NV_RAMDAC_VPLL2 }, -+ {} -+}; -+ -+static struct pll_mapping nv50_pll_mapping[] = { -+ { PLL_CORE , 0x004028 }, -+ { PLL_SHADER, 0x004020 }, -+ { PLL_UNK03 , 0x004000 }, -+ { PLL_MEMORY, 0x004008 }, -+ { PLL_UNK40 , 0x00e810 }, -+ { PLL_UNK41 , 0x00e818 }, -+ { PLL_UNK42 , 0x00e824 }, -+ { PLL_VPLL0 , 0x614100 }, -+ { PLL_VPLL1 , 0x614900 }, -+ {} -+}; -+ -+static struct pll_mapping nv84_pll_mapping[] = { -+ { PLL_CORE , 0x004028 }, -+ { PLL_SHADER, 0x004020 }, -+ { PLL_MEMORY, 0x004008 }, -+ { PLL_UNK05 , 0x004030 }, -+ { PLL_UNK41 , 0x00e818 }, -+ { PLL_VPLL0 , 0x614100 }, -+ { PLL_VPLL1 , 0x614900 }, -+ {} -+}; -+ -+u32 -+get_pll_register(struct drm_device *dev, enum pll_types type) -+{ -+ struct drm_nouveau_private *dev_priv = dev->dev_private; -+ struct nvbios *bios = &dev_priv->vbios; -+ struct pll_mapping *map; -+ int i; -+ -+ if (dev_priv->card_type < NV_40) -+ map = nv04_pll_mapping; -+ else -+ if (dev_priv->card_type < NV_50) -+ map = nv40_pll_mapping; -+ else { -+ u8 *plim = &bios->data[bios->pll_limit_tbl_ptr]; -+ -+ if (plim[0] >= 0x30) { -+ u8 *entry = plim + plim[1]; -+ for (i = 0; i < plim[3]; i++, entry += plim[2]) { -+ if (entry[0] == type) -+ return ROM32(entry[3]); -+ } -+ -+ return 0; -+ } -+ -+ if (dev_priv->chipset == 0x50) -+ map = nv50_pll_mapping; -+ else -+ map = nv84_pll_mapping; -+ } -+ -+ while (map->reg) { -+ if (map->type == type) -+ return map->reg; -+ map++; -+ } -+ -+ return 0; -+} -+ - int get_pll_limits(struct drm_device *dev, uint32_t limit_match, struct pll_lims *pll_lim) - { - /* -@@ -4750,6 +4827,17 @@ - /* initialize all members to zero */ - memset(pll_lim, 0, sizeof(struct pll_lims)); - -+ /* if we were passed a type rather than a register, figure -+ * out the register and store it -+ */ -+ if (limit_match > PLL_MAX) -+ pll_lim->reg = limit_match; -+ else { -+ pll_lim->reg = get_pll_register(dev, limit_match); -+ if (!pll_lim->reg) -+ return -ENOENT; -+ } -+ - if (pll_lim_ver == 0x10 || pll_lim_ver == 0x11) { - uint8_t *pll_rec = &bios->data[bios->pll_limit_tbl_ptr + headerlen + recordlen * pllindex]; - -@@ -4785,7 +4873,6 @@ - pll_lim->max_usable_log2p = 0x6; - } else if (pll_lim_ver == 0x20 || pll_lim_ver == 0x21) { - uint16_t plloffs = bios->pll_limit_tbl_ptr + headerlen; -- uint32_t reg = 0; /* default match */ - uint8_t *pll_rec; - int i; - -@@ -4797,37 +4884,22 @@ - NV_WARN(dev, "Default PLL limit entry has non-zero " - "register field\n"); - -- if (limit_match > MAX_PLL_TYPES) -- /* we've been passed a reg as the match */ -- reg = limit_match; -- else /* limit match is a pll type */ -- for (i = 1; i < entries && !reg; i++) { -- uint32_t cmpreg = ROM32(bios->data[plloffs + recordlen * i]); -- -- if (limit_match == NVPLL && -- (cmpreg == NV_PRAMDAC_NVPLL_COEFF || cmpreg == 0x4000)) -- reg = cmpreg; -- if (limit_match == MPLL && -- (cmpreg == NV_PRAMDAC_MPLL_COEFF || cmpreg == 0x4020)) -- reg = cmpreg; -- if (limit_match == VPLL1 && -- (cmpreg == NV_PRAMDAC_VPLL_COEFF || cmpreg == 0x4010)) -- reg = cmpreg; -- if (limit_match == VPLL2 && -- (cmpreg == NV_RAMDAC_VPLL2 || cmpreg == 0x4018)) -- reg = cmpreg; -- } -- - for (i = 1; i < entries; i++) -- if (ROM32(bios->data[plloffs + recordlen * i]) == reg) { -+ if (ROM32(bios->data[plloffs + recordlen * i]) == pll_lim->reg) { - pllindex = i; - break; - } - -+ if ((dev_priv->card_type >= NV_50) && (pllindex == 0)) { -+ NV_ERROR(dev, "Register 0x%08x not found in PLL " -+ "limits table", pll_lim->reg); -+ return -ENOENT; -+ } -+ - pll_rec = &bios->data[plloffs + recordlen * pllindex]; - - BIOSLOG(bios, "Loading PLL limits for reg 0x%08x\n", -- pllindex ? reg : 0); -+ pllindex ? pll_lim->reg : 0); - - /* - * Frequencies are stored in tables in MHz, kHz are more -@@ -4877,8 +4949,8 @@ - if (cv == 0x51 && !pll_lim->refclk) { - uint32_t sel_clk = bios_rd32(bios, NV_PRAMDAC_SEL_CLK); - -- if (((limit_match == NV_PRAMDAC_VPLL_COEFF || limit_match == VPLL1) && sel_clk & 0x20) || -- ((limit_match == NV_RAMDAC_VPLL2 || limit_match == VPLL2) && sel_clk & 0x80)) { -+ if ((pll_lim->reg == NV_PRAMDAC_VPLL_COEFF && sel_clk & 0x20) || -+ (pll_lim->reg == NV_RAMDAC_VPLL2 && sel_clk & 0x80)) { - if (bios_idxprt_rd(bios, NV_CIO_CRX__COLOR, NV_CIO_CRE_CHIP_ID_INDEX) < 0xa3) - pll_lim->refclk = 200000; - else -@@ -4891,10 +4963,10 @@ - int i; - - BIOSLOG(bios, "Loading PLL limits for register 0x%08x\n", -- limit_match); -+ pll_lim->reg); - - for (i = 0; i < entries; i++, entry += recordlen) { -- if (ROM32(entry[3]) == limit_match) { -+ if (ROM32(entry[3]) == pll_lim->reg) { - record = &bios->data[ROM16(entry[1])]; - break; - } -@@ -4902,7 +4974,7 @@ - - if (!record) { - NV_ERROR(dev, "Register 0x%08x not found in PLL " -- "limits table", limit_match); -+ "limits table", pll_lim->reg); - return -ENOENT; - } - -@@ -4931,10 +5003,10 @@ - int i; - - BIOSLOG(bios, "Loading PLL limits for register 0x%08x\n", -- limit_match); -+ pll_lim->reg); - - for (i = 0; i < entries; i++, entry += recordlen) { -- if (ROM32(entry[3]) == limit_match) { -+ if (ROM32(entry[3]) == pll_lim->reg) { - record = &bios->data[ROM16(entry[1])]; - break; - } -@@ -4942,7 +5014,7 @@ - - if (!record) { - NV_ERROR(dev, "Register 0x%08x not found in PLL " -- "limits table", limit_match); -+ "limits table", pll_lim->reg); - return -ENOENT; - } - -@@ -5293,7 +5365,7 @@ - if (bitentry->length < 0x5) - return 0; - -- if (bitentry->id[1] < 2) { -+ if (bitentry->version < 2) { - bios->ram_restrict_group_count = bios->data[bitentry->offset + 2]; - bios->ram_restrict_tbl_ptr = ROM16(bios->data[bitentry->offset + 3]); - } else { -@@ -5403,27 +5475,40 @@ - - #define BIT_TABLE(id, funcid) ((struct bit_table){ id, parse_bit_##funcid##_tbl_entry }) - -+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; -+ u8 entries, *entry; -+ -+ entries = bios->data[bios->offset + 10]; -+ entry = &bios->data[bios->offset + 12]; -+ while (entries--) { -+ if (entry[0] == id) { -+ bit->id = entry[0]; -+ bit->version = entry[1]; -+ bit->length = ROM16(entry[2]); -+ bit->offset = ROM16(entry[4]); -+ bit->data = ROMPTR(bios, entry[4]); -+ return 0; -+ } -+ -+ entry += bios->data[bios->offset + 9]; -+ } -+ -+ return -ENOENT; -+} -+ - static int - parse_bit_table(struct nvbios *bios, const uint16_t bitoffset, - struct bit_table *table) - { - struct drm_device *dev = bios->dev; -- uint8_t maxentries = bios->data[bitoffset + 4]; -- int i, offset; - struct bit_entry bitentry; - -- for (i = 0, offset = bitoffset + 6; i < maxentries; i++, offset += 6) { -- bitentry.id[0] = bios->data[offset]; -- -- if (bitentry.id[0] != table->id) -- continue; -- -- bitentry.id[1] = bios->data[offset + 1]; -- bitentry.length = ROM16(bios->data[offset + 2]); -- bitentry.offset = ROM16(bios->data[offset + 4]); -- -+ 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); - return -ENOSYS; -@@ -5683,8 +5768,14 @@ - static struct dcb_gpio_entry * - new_gpio_entry(struct nvbios *bios) - { -+ struct drm_device *dev = bios->dev; - struct dcb_gpio_table *gpio = &bios->dcb.gpio; - -+ if (gpio->entries >= DCB_MAX_NUM_GPIO_ENTRIES) { -+ NV_ERROR(dev, "exceeded maximum number of gpio entries!!\n"); -+ return NULL; -+ } -+ - return &gpio->entry[gpio->entries++]; - } - -@@ -5706,113 +5797,90 @@ - } - - static void --parse_dcb30_gpio_entry(struct nvbios *bios, uint16_t offset) --{ -- struct dcb_gpio_entry *gpio; -- uint16_t ent = ROM16(bios->data[offset]); -- uint8_t line = ent & 0x1f, -- tag = ent >> 5 & 0x3f, -- flags = ent >> 11 & 0x1f; -- -- if (tag == 0x3f) -- return; -- -- gpio = new_gpio_entry(bios); -- -- gpio->tag = tag; -- gpio->line = line; -- gpio->invert = flags != 4; -- gpio->entry = ent; --} -- --static void --parse_dcb40_gpio_entry(struct nvbios *bios, uint16_t offset) --{ -- uint32_t entry = ROM32(bios->data[offset]); -- struct dcb_gpio_entry *gpio; -- -- if ((entry & 0x0000ff00) == 0x0000ff00) -- return; -- -- gpio = new_gpio_entry(bios); -- gpio->tag = (entry & 0x0000ff00) >> 8; -- gpio->line = (entry & 0x0000001f) >> 0; -- gpio->state_default = (entry & 0x01000000) >> 24; -- gpio->state[0] = (entry & 0x18000000) >> 27; -- gpio->state[1] = (entry & 0x60000000) >> 29; -- gpio->entry = entry; --} -- --static void - parse_dcb_gpio_table(struct nvbios *bios) - { - struct drm_device *dev = bios->dev; -- uint16_t gpio_table_ptr = bios->dcb.gpio_table_ptr; -- uint8_t *gpio_table = &bios->data[gpio_table_ptr]; -- int header_len = gpio_table[1], -- entries = gpio_table[2], -- entry_len = gpio_table[3]; -- void (*parse_entry)(struct nvbios *, uint16_t) = NULL; -+ struct dcb_gpio_entry *e; -+ u8 headerlen, entries, recordlen; -+ u8 *dcb, *gpio = NULL, *entry; - int i; - -- if (bios->dcb.version >= 0x40) { -- if (gpio_table_ptr && entry_len != 4) { -- NV_WARN(dev, "Invalid DCB GPIO table entry length.\n"); -- return; -- } -- -- parse_entry = parse_dcb40_gpio_entry; -+ dcb = ROMPTR(bios, bios->data[0x36]); -+ if (dcb[0] >= 0x30) { -+ gpio = ROMPTR(bios, dcb[10]); -+ if (!gpio) -+ goto no_table; -+ -+ headerlen = gpio[1]; -+ entries = gpio[2]; -+ recordlen = gpio[3]; -+ } else -+ if (dcb[0] >= 0x22 && dcb[-1] >= 0x13) { -+ gpio = ROMPTR(bios, dcb[-15]); -+ if (!gpio) -+ goto no_table; -+ -+ headerlen = 3; -+ entries = gpio[2]; -+ recordlen = gpio[1]; -+ } else -+ if (dcb[0] >= 0x22) { -+ /* No GPIO table present, parse the TVDAC GPIO data. */ -+ uint8_t *tvdac_gpio = &dcb[-5]; - -- } else if (bios->dcb.version >= 0x30) { -- if (gpio_table_ptr && entry_len != 2) { -- NV_WARN(dev, "Invalid DCB GPIO table entry length.\n"); -- return; -+ if (tvdac_gpio[0] & 1) { -+ e = new_gpio_entry(bios); -+ e->tag = DCB_GPIO_TVDAC0; -+ e->line = tvdac_gpio[1] >> 4; -+ e->invert = tvdac_gpio[0] & 2; - } - -- parse_entry = parse_dcb30_gpio_entry; -- -- } else if (bios->dcb.version >= 0x22) { -- /* -- * DCBs older than v3.0 don't really have a GPIO -- * table, instead they keep some GPIO info at fixed -- * locations. -- */ -- uint16_t dcbptr = ROM16(bios->data[0x36]); -- uint8_t *tvdac_gpio = &bios->data[dcbptr - 5]; -+ goto no_table; -+ } else { -+ NV_DEBUG(dev, "no/unknown gpio table on DCB 0x%02x\n", dcb[0]); -+ goto no_table; -+ } - -- if (tvdac_gpio[0] & 1) { -- struct dcb_gpio_entry *gpio = new_gpio_entry(bios); -+ entry = gpio + headerlen; -+ for (i = 0; i < entries; i++, entry += recordlen) { -+ e = new_gpio_entry(bios); -+ if (!e) -+ break; - -- gpio->tag = DCB_GPIO_TVDAC0; -- gpio->line = tvdac_gpio[1] >> 4; -- gpio->invert = tvdac_gpio[0] & 2; -- } -- } else { -- /* -- * No systematic way to store GPIO info on pre-v2.2 -- * DCBs, try to match the PCI device IDs. -- */ -+ if (gpio[0] < 0x40) { -+ e->entry = ROM16(entry[0]); -+ e->tag = (e->entry & 0x07e0) >> 5; -+ if (e->tag == 0x3f) { -+ bios->dcb.gpio.entries--; -+ continue; -+ } - -- /* Apple iMac G4 NV18 */ -- if (nv_match_device(dev, 0x0189, 0x10de, 0x0010)) { -- struct dcb_gpio_entry *gpio = new_gpio_entry(bios); -+ e->line = (e->entry & 0x001f); -+ e->invert = ((e->entry & 0xf800) >> 11) != 4; -+ } else { -+ e->entry = ROM32(entry[0]); -+ e->tag = (e->entry & 0x0000ff00) >> 8; -+ if (e->tag == 0xff) { -+ bios->dcb.gpio.entries--; -+ continue; -+ } - -- gpio->tag = DCB_GPIO_TVDAC0; -- gpio->line = 4; -+ e->line = (e->entry & 0x0000001f) >> 0; -+ e->state_default = (e->entry & 0x01000000) >> 24; -+ e->state[0] = (e->entry & 0x18000000) >> 27; -+ e->state[1] = (e->entry & 0x60000000) >> 29; - } -- - } - -- if (!gpio_table_ptr) -- return; -- -- if (entries > DCB_MAX_NUM_GPIO_ENTRIES) { -- NV_WARN(dev, "Too many entries in the DCB GPIO table.\n"); -- entries = DCB_MAX_NUM_GPIO_ENTRIES; -+no_table: -+ /* Apple iMac G4 NV18 */ -+ if (nv_match_device(dev, 0x0189, 0x10de, 0x0010)) { -+ e = new_gpio_entry(bios); -+ if (e) { -+ e->tag = DCB_GPIO_TVDAC0; -+ e->line = 4; -+ } - } -- -- for (i = 0; i < entries; i++) -- parse_entry(bios, gpio_table_ptr + header_len + entry_len * i); - } - - struct dcb_connector_table_entry * -@@ -5971,7 +6039,6 @@ - if (type != cte->type) - NV_WARN(dev, " -> type 0x%02x\n", cte->type); - } -- - } - } - -@@ -6680,6 +6747,8 @@ - bit_signature, sizeof(bit_signature)); - if (offset) { - NV_TRACE(dev, "BIT BIOS found\n"); -+ bios->type = NVBIOS_BIT; -+ bios->offset = offset; - return parse_bit_structure(bios, offset + 6); - } - -@@ -6687,6 +6756,8 @@ - bmp_signature, sizeof(bmp_signature)); - if (offset) { - NV_TRACE(dev, "BMP BIOS found\n"); -+ bios->type = NVBIOS_BMP; -+ bios->offset = offset; - return parse_bmp_structure(dev, bios, offset); - } - -@@ -6806,6 +6877,8 @@ - "running VBIOS init tables.\n"); - bios->execute = true; - } -+ if (nouveau_force_post) -+ bios->execute = true; - - ret = nouveau_run_vbios_init(dev); - if (ret) -diff -Naur linux-2.6.36/drivers/gpu/drm/nouveau/nouveau_bios.h linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nouveau_bios.h ---- linux-2.6.36/drivers/gpu/drm/nouveau/nouveau_bios.h 2010-10-20 22:30:22.000000000 +0200 -+++ linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nouveau_bios.h 2010-11-05 00:40:00.000000000 +0100 -@@ -34,6 +34,20 @@ - - #define DCB_LOC_ON_CHIP 0 - -+#define ROM16(x) le16_to_cpu(*(uint16_t *)&(x)) -+#define ROM32(x) le32_to_cpu(*(uint32_t *)&(x)) -+#define ROMPTR(bios, x) (ROM16(x) ? &(bios)->data[ROM16(x)] : NULL) -+ -+struct bit_entry { -+ uint8_t id; -+ uint8_t version; -+ uint16_t length; -+ uint16_t offset; -+ uint8_t *data; -+}; -+ -+int bit_table(struct drm_device *, u8 id, struct bit_entry *); -+ - struct dcb_i2c_entry { - uint32_t entry; - uint8_t port_type; -@@ -170,16 +184,28 @@ - LVDS_PANEL_OFF - }; - --/* changing these requires matching changes to reg tables in nv_get_clock */ --#define MAX_PLL_TYPES 4 -+/* these match types in pll limits table version 0x40, -+ * nouveau uses them on all chipsets internally where a -+ * specific pll needs to be referenced, but the exact -+ * register isn't known. -+ */ - enum pll_types { -- NVPLL, -- MPLL, -- VPLL1, -- VPLL2 -+ PLL_CORE = 0x01, -+ PLL_SHADER = 0x02, -+ PLL_UNK03 = 0x03, -+ PLL_MEMORY = 0x04, -+ PLL_UNK05 = 0x05, -+ PLL_UNK40 = 0x40, -+ PLL_UNK41 = 0x41, -+ PLL_UNK42 = 0x42, -+ PLL_VPLL0 = 0x80, -+ PLL_VPLL1 = 0x81, -+ PLL_MAX = 0xff - }; - - struct pll_lims { -+ u32 reg; -+ - struct { - int minfreq; - int maxfreq; -@@ -212,6 +238,11 @@ - - struct nvbios { - struct drm_device *dev; -+ enum { -+ NVBIOS_BMP, -+ NVBIOS_BIT -+ } type; -+ uint16_t offset; - - uint8_t chip_version; - -diff -Naur linux-2.6.36/drivers/gpu/drm/nouveau/nouveau_bo.c linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nouveau_bo.c ---- linux-2.6.36/drivers/gpu/drm/nouveau/nouveau_bo.c 2010-10-20 22:30:22.000000000 +0200 -+++ linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nouveau_bo.c 2010-11-05 00:40:00.000000000 +0100 -@@ -36,21 +36,6 @@ - #include - #include - --int --nouveau_bo_sync_gpu(struct nouveau_bo *nvbo, struct nouveau_channel *chan) --{ -- struct nouveau_fence *prev_fence = nvbo->bo.sync_obj; -- int ret; -- -- if (!prev_fence || nouveau_fence_channel(prev_fence) == chan) -- return 0; -- -- spin_lock(&nvbo->bo.lock); -- ret = ttm_bo_wait(&nvbo->bo, false, false, false); -- spin_unlock(&nvbo->bo.lock); -- return ret; --} -- - static void - nouveau_bo_del_ttm(struct ttm_buffer_object *bo) - { -@@ -58,14 +43,10 @@ - struct drm_device *dev = dev_priv->dev; - struct nouveau_bo *nvbo = nouveau_bo(bo); - -- ttm_bo_kunmap(&nvbo->kmap); -- - if (unlikely(nvbo->gem)) - DRM_ERROR("bo %p still attached to GEM object\n", bo); - -- if (nvbo->tile) -- nv10_mem_expire_tiling(dev, nvbo->tile, NULL); -- -+ nv10_mem_put_tile_region(dev, nvbo->tile, NULL); - kfree(nvbo); - } - -@@ -160,12 +141,12 @@ - nvbo->no_vm = no_vm; - nvbo->tile_mode = tile_mode; - nvbo->tile_flags = tile_flags; -+ nvbo->bo.bdev = &dev_priv->ttm.bdev; - -- nouveau_bo_fixup_align(dev, tile_mode, tile_flags, &align, &size); -+ nouveau_bo_fixup_align(dev, tile_mode, nouveau_bo_tile_layout(nvbo), -+ &align, &size); - align >>= PAGE_SHIFT; - -- nvbo->placement.fpfn = 0; -- nvbo->placement.lpfn = mappable ? dev_priv->fb_mappable_pages : 0; - nouveau_bo_placement_set(nvbo, flags, 0); - - nvbo->channel = chan; -@@ -195,6 +176,31 @@ - pl[(*n)++] = TTM_PL_FLAG_SYSTEM | flags; - } - -+static void -+set_placement_range(struct nouveau_bo *nvbo, uint32_t type) -+{ -+ struct drm_nouveau_private *dev_priv = nouveau_bdev(nvbo->bo.bdev); -+ -+ if (dev_priv->card_type == NV_10 && -+ nvbo->tile_mode && (type & TTM_PL_FLAG_VRAM)) { -+ /* -+ * Make sure that the color and depth buffers are handled -+ * by independent memory controller units. Up to a 9x -+ * speed up when alpha-blending and depth-test are enabled -+ * at the same time. -+ */ -+ int vram_pages = dev_priv->vram_size >> PAGE_SHIFT; -+ -+ if (nvbo->tile_flags & NOUVEAU_GEM_TILE_ZETA) { -+ nvbo->placement.fpfn = vram_pages / 2; -+ nvbo->placement.lpfn = ~0; -+ } else { -+ nvbo->placement.fpfn = 0; -+ nvbo->placement.lpfn = vram_pages / 2; -+ } -+ } -+} -+ - void - nouveau_bo_placement_set(struct nouveau_bo *nvbo, uint32_t type, uint32_t busy) - { -@@ -209,6 +215,8 @@ - pl->busy_placement = nvbo->busy_placements; - set_placement_list(nvbo->busy_placements, &pl->num_busy_placement, - type | busy, flags); -+ -+ set_placement_range(nvbo, type); - } - - int -@@ -305,7 +313,8 @@ - void - nouveau_bo_unmap(struct nouveau_bo *nvbo) - { -- ttm_bo_kunmap(&nvbo->kmap); -+ if (nvbo) -+ ttm_bo_kunmap(&nvbo->kmap); - } - - u16 -@@ -399,14 +408,19 @@ - man->default_caching = TTM_PL_FLAG_CACHED; - break; - case TTM_PL_VRAM: -+ man->func = &ttm_bo_manager_func; - man->flags = TTM_MEMTYPE_FLAG_FIXED | - TTM_MEMTYPE_FLAG_MAPPABLE; - man->available_caching = TTM_PL_FLAG_UNCACHED | - TTM_PL_FLAG_WC; - man->default_caching = TTM_PL_FLAG_WC; -- man->gpu_offset = dev_priv->vm_vram_base; -+ if (dev_priv->card_type == NV_50) -+ man->gpu_offset = 0x40000000; -+ else -+ man->gpu_offset = 0; - break; - case TTM_PL_TT: -+ man->func = &ttm_bo_manager_func; - switch (dev_priv->gart_info.type) { - case NOUVEAU_GART_AGP: - man->flags = TTM_MEMTYPE_FLAG_MAPPABLE; -@@ -469,19 +483,19 @@ - if (ret) - return ret; - -- ret = ttm_bo_move_accel_cleanup(&nvbo->bo, fence, NULL, -- evict || (nvbo->channel && -- nvbo->channel != chan), -+ ret = ttm_bo_move_accel_cleanup(&nvbo->bo, fence, NULL, evict, - no_wait_reserve, no_wait_gpu, new_mem); -- nouveau_fence_unref((void *)&fence); -+ nouveau_fence_unref(&fence); - return ret; - } - - static inline uint32_t --nouveau_bo_mem_ctxdma(struct nouveau_bo *nvbo, struct nouveau_channel *chan, -- struct ttm_mem_reg *mem) -+nouveau_bo_mem_ctxdma(struct ttm_buffer_object *bo, -+ struct nouveau_channel *chan, struct ttm_mem_reg *mem) - { -- if (chan == nouveau_bdev(nvbo->bo.bdev)->channel) { -+ struct nouveau_bo *nvbo = nouveau_bo(bo); -+ -+ if (nvbo->no_vm) { - if (mem->mem_type == TTM_PL_TT) - return NvDmaGART; - return NvDmaVRAM; -@@ -493,87 +507,191 @@ - } - - static int --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) -+nv50_bo_move_m2mf(struct nouveau_channel *chan, struct ttm_buffer_object *bo, -+ struct ttm_mem_reg *old_mem, struct ttm_mem_reg *new_mem) - { -- struct nouveau_bo *nvbo = nouveau_bo(bo); - struct drm_nouveau_private *dev_priv = nouveau_bdev(bo->bdev); -- struct ttm_mem_reg *old_mem = &bo->mem; -- struct nouveau_channel *chan; -- uint64_t src_offset, dst_offset; -- uint32_t page_count; -+ struct nouveau_bo *nvbo = nouveau_bo(bo); -+ u64 length = (new_mem->num_pages << PAGE_SHIFT); -+ u64 src_offset, dst_offset; - int ret; - -- chan = nvbo->channel; -- if (!chan || nvbo->tile_flags || nvbo->no_vm) -- chan = dev_priv->channel; -- -- src_offset = old_mem->mm_node->start << PAGE_SHIFT; -- dst_offset = new_mem->mm_node->start << PAGE_SHIFT; -- if (chan != dev_priv->channel) { -- if (old_mem->mem_type == TTM_PL_TT) -- src_offset += dev_priv->vm_gart_base; -- else -+ src_offset = old_mem->start << PAGE_SHIFT; -+ dst_offset = new_mem->start << PAGE_SHIFT; -+ if (!nvbo->no_vm) { -+ if (old_mem->mem_type == TTM_PL_VRAM) - src_offset += dev_priv->vm_vram_base; -- -- if (new_mem->mem_type == TTM_PL_TT) -- dst_offset += dev_priv->vm_gart_base; - else -+ src_offset += dev_priv->vm_gart_base; -+ -+ if (new_mem->mem_type == TTM_PL_VRAM) - dst_offset += dev_priv->vm_vram_base; -+ else -+ dst_offset += dev_priv->vm_gart_base; - } - - ret = RING_SPACE(chan, 3); - if (ret) - return ret; -- BEGIN_RING(chan, NvSubM2MF, NV_MEMORY_TO_MEMORY_FORMAT_DMA_SOURCE, 2); -- OUT_RING(chan, nouveau_bo_mem_ctxdma(nvbo, chan, old_mem)); -- OUT_RING(chan, nouveau_bo_mem_ctxdma(nvbo, chan, new_mem)); - -- if (dev_priv->card_type >= NV_50) { -- ret = RING_SPACE(chan, 4); -+ BEGIN_RING(chan, NvSubM2MF, 0x0184, 2); -+ OUT_RING (chan, nouveau_bo_mem_ctxdma(bo, chan, old_mem)); -+ OUT_RING (chan, nouveau_bo_mem_ctxdma(bo, chan, new_mem)); -+ -+ while (length) { -+ u32 amount, stride, height; -+ -+ amount = min(length, (u64)(4 * 1024 * 1024)); -+ stride = 16 * 4; -+ height = amount / stride; -+ -+ if (new_mem->mem_type == TTM_PL_VRAM && -+ nouveau_bo_tile_layout(nvbo)) { -+ ret = RING_SPACE(chan, 8); -+ if (ret) -+ return ret; -+ -+ BEGIN_RING(chan, NvSubM2MF, 0x0200, 7); -+ OUT_RING (chan, 0); -+ OUT_RING (chan, 0); -+ OUT_RING (chan, stride); -+ OUT_RING (chan, height); -+ OUT_RING (chan, 1); -+ OUT_RING (chan, 0); -+ OUT_RING (chan, 0); -+ } else { -+ ret = RING_SPACE(chan, 2); -+ if (ret) -+ return ret; -+ -+ BEGIN_RING(chan, NvSubM2MF, 0x0200, 1); -+ OUT_RING (chan, 1); -+ } -+ if (old_mem->mem_type == TTM_PL_VRAM && -+ nouveau_bo_tile_layout(nvbo)) { -+ ret = RING_SPACE(chan, 8); -+ if (ret) -+ return ret; -+ -+ BEGIN_RING(chan, NvSubM2MF, 0x021c, 7); -+ OUT_RING (chan, 0); -+ OUT_RING (chan, 0); -+ OUT_RING (chan, stride); -+ OUT_RING (chan, height); -+ OUT_RING (chan, 1); -+ OUT_RING (chan, 0); -+ OUT_RING (chan, 0); -+ } else { -+ ret = RING_SPACE(chan, 2); -+ if (ret) -+ return ret; -+ -+ BEGIN_RING(chan, NvSubM2MF, 0x021c, 1); -+ OUT_RING (chan, 1); -+ } -+ -+ ret = RING_SPACE(chan, 14); - if (ret) - return ret; -- BEGIN_RING(chan, NvSubM2MF, 0x0200, 1); -- OUT_RING(chan, 1); -- BEGIN_RING(chan, NvSubM2MF, 0x021c, 1); -- OUT_RING(chan, 1); -+ -+ BEGIN_RING(chan, NvSubM2MF, 0x0238, 2); -+ OUT_RING (chan, upper_32_bits(src_offset)); -+ OUT_RING (chan, upper_32_bits(dst_offset)); -+ BEGIN_RING(chan, NvSubM2MF, 0x030c, 8); -+ OUT_RING (chan, lower_32_bits(src_offset)); -+ OUT_RING (chan, lower_32_bits(dst_offset)); -+ OUT_RING (chan, stride); -+ OUT_RING (chan, stride); -+ OUT_RING (chan, stride); -+ OUT_RING (chan, height); -+ OUT_RING (chan, 0x00000101); -+ OUT_RING (chan, 0x00000000); -+ BEGIN_RING(chan, NvSubM2MF, NV_MEMORY_TO_MEMORY_FORMAT_NOP, 1); -+ OUT_RING (chan, 0); -+ -+ length -= amount; -+ src_offset += amount; -+ dst_offset += amount; - } - -+ return 0; -+} -+ -+static int -+nv04_bo_move_m2mf(struct nouveau_channel *chan, struct ttm_buffer_object *bo, -+ struct ttm_mem_reg *old_mem, struct ttm_mem_reg *new_mem) -+{ -+ u32 src_offset = old_mem->start << PAGE_SHIFT; -+ u32 dst_offset = new_mem->start << PAGE_SHIFT; -+ u32 page_count = new_mem->num_pages; -+ int ret; -+ -+ ret = RING_SPACE(chan, 3); -+ if (ret) -+ return ret; -+ -+ BEGIN_RING(chan, NvSubM2MF, NV_MEMORY_TO_MEMORY_FORMAT_DMA_SOURCE, 2); -+ OUT_RING (chan, nouveau_bo_mem_ctxdma(bo, chan, old_mem)); -+ OUT_RING (chan, nouveau_bo_mem_ctxdma(bo, chan, new_mem)); -+ - page_count = new_mem->num_pages; - while (page_count) { - int line_count = (page_count > 2047) ? 2047 : page_count; - -- if (dev_priv->card_type >= NV_50) { -- ret = RING_SPACE(chan, 3); -- if (ret) -- return ret; -- BEGIN_RING(chan, NvSubM2MF, 0x0238, 2); -- OUT_RING(chan, upper_32_bits(src_offset)); -- OUT_RING(chan, upper_32_bits(dst_offset)); -- } - ret = RING_SPACE(chan, 11); - if (ret) - return ret; -+ - BEGIN_RING(chan, NvSubM2MF, - NV_MEMORY_TO_MEMORY_FORMAT_OFFSET_IN, 8); -- OUT_RING(chan, lower_32_bits(src_offset)); -- OUT_RING(chan, lower_32_bits(dst_offset)); -- OUT_RING(chan, PAGE_SIZE); /* src_pitch */ -- OUT_RING(chan, PAGE_SIZE); /* dst_pitch */ -- OUT_RING(chan, PAGE_SIZE); /* line_length */ -- OUT_RING(chan, line_count); -- OUT_RING(chan, (1<<8)|(1<<0)); -- OUT_RING(chan, 0); -+ OUT_RING (chan, src_offset); -+ OUT_RING (chan, dst_offset); -+ OUT_RING (chan, PAGE_SIZE); /* src_pitch */ -+ OUT_RING (chan, PAGE_SIZE); /* dst_pitch */ -+ OUT_RING (chan, PAGE_SIZE); /* line_length */ -+ OUT_RING (chan, line_count); -+ OUT_RING (chan, 0x00000101); -+ OUT_RING (chan, 0x00000000); - BEGIN_RING(chan, NvSubM2MF, NV_MEMORY_TO_MEMORY_FORMAT_NOP, 1); -- OUT_RING(chan, 0); -+ OUT_RING (chan, 0); - - page_count -= line_count; - src_offset += (PAGE_SIZE * line_count); - dst_offset += (PAGE_SIZE * line_count); - } - -- return nouveau_bo_move_accel_cleanup(chan, nvbo, evict, no_wait_reserve, no_wait_gpu, new_mem); -+ return 0; -+} -+ -+static int -+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_bo *nvbo = nouveau_bo(bo); -+ struct nouveau_channel *chan; -+ int ret; -+ -+ chan = nvbo->channel; -+ if (!chan || nvbo->no_vm) { -+ chan = dev_priv->channel; -+ mutex_lock_nested(&chan->mutex, NOUVEAU_KCHANNEL_MUTEX); -+ } -+ -+ if (dev_priv->card_type < NV_50) -+ ret = nv04_bo_move_m2mf(chan, bo, &bo->mem, new_mem); -+ else -+ ret = nv50_bo_move_m2mf(chan, bo, &bo->mem, new_mem); -+ if (ret == 0) { -+ ret = nouveau_bo_move_accel_cleanup(chan, nvbo, evict, -+ no_wait_reserve, -+ no_wait_gpu, new_mem); -+ } -+ -+ if (chan == dev_priv->channel) -+ mutex_unlock(&chan->mutex); -+ return ret; - } - - static int -@@ -606,12 +724,7 @@ - - ret = ttm_bo_move_ttm(bo, evict, no_wait_reserve, no_wait_gpu, new_mem); - out: -- if (tmp_mem.mm_node) { -- spin_lock(&bo->bdev->glob->lru_lock); -- drm_mm_put_block(tmp_mem.mm_node); -- spin_unlock(&bo->bdev->glob->lru_lock); -- } -- -+ ttm_bo_mem_put(bo, &tmp_mem); - return ret; - } - -@@ -644,12 +757,7 @@ - goto out; - - out: -- if (tmp_mem.mm_node) { -- spin_lock(&bo->bdev->glob->lru_lock); -- drm_mm_put_block(tmp_mem.mm_node); -- spin_unlock(&bo->bdev->glob->lru_lock); -- } -- -+ ttm_bo_mem_put(bo, &tmp_mem); - return ret; - } - -@@ -669,19 +777,21 @@ - return 0; - } - -- offset = new_mem->mm_node->start << PAGE_SHIFT; -+ offset = new_mem->start << PAGE_SHIFT; - - if (dev_priv->card_type == NV_50) { - ret = nv50_mem_vm_bind_linear(dev, - offset + dev_priv->vm_vram_base, -- new_mem->size, nvbo->tile_flags, -+ new_mem->size, -+ nouveau_bo_tile_layout(nvbo), - offset); - if (ret) - return ret; - - } else if (dev_priv->card_type >= NV_10) { - *new_tile = nv10_mem_set_tiling(dev, offset, new_mem->size, -- nvbo->tile_mode); -+ nvbo->tile_mode, -+ nvbo->tile_flags); - } - - return 0; -@@ -697,9 +807,7 @@ - - if (dev_priv->card_type >= NV_10 && - dev_priv->card_type < NV_50) { -- if (*old_tile) -- nv10_mem_expire_tiling(dev, *old_tile, bo->sync_obj); -- -+ nv10_mem_put_tile_region(dev, *old_tile, bo->sync_obj); - *old_tile = new_tile; - } - } -@@ -719,12 +827,6 @@ - if (ret) - return ret; - -- /* Software copy if the card isn't up and running yet. */ -- if (!dev_priv->channel) { -- ret = ttm_bo_move_memcpy(bo, evict, no_wait_reserve, no_wait_gpu, new_mem); -- goto out; -- } -- - /* Fake bo copy. */ - if (old_mem->mem_type == TTM_PL_SYSTEM && !bo->ttm) { - BUG_ON(bo->mem.mm_node != NULL); -@@ -733,6 +835,12 @@ - goto out; - } - -+ /* Software copy if the card isn't up and running yet. */ -+ if (!dev_priv->channel) { -+ ret = ttm_bo_move_memcpy(bo, evict, no_wait_reserve, no_wait_gpu, new_mem); -+ goto out; -+ } -+ - /* Hardware assisted copy. */ - if (new_mem->mem_type == TTM_PL_SYSTEM) - ret = nouveau_bo_move_flipd(bo, evict, intr, no_wait_reserve, no_wait_gpu, new_mem); -@@ -783,14 +891,14 @@ - case TTM_PL_TT: - #if __OS_HAS_AGP - if (dev_priv->gart_info.type == NOUVEAU_GART_AGP) { -- mem->bus.offset = mem->mm_node->start << PAGE_SHIFT; -+ mem->bus.offset = mem->start << PAGE_SHIFT; - mem->bus.base = dev_priv->gart_info.aper_base; - mem->bus.is_iomem = true; - } - #endif - break; - case TTM_PL_VRAM: -- mem->bus.offset = mem->mm_node->start << PAGE_SHIFT; -+ mem->bus.offset = mem->start << PAGE_SHIFT; - mem->bus.base = pci_resource_start(dev->pdev, 1); - mem->bus.is_iomem = true; - break; -@@ -808,7 +916,43 @@ - static int - nouveau_ttm_fault_reserve_notify(struct ttm_buffer_object *bo) - { -- return 0; -+ struct drm_nouveau_private *dev_priv = nouveau_bdev(bo->bdev); -+ struct nouveau_bo *nvbo = nouveau_bo(bo); -+ -+ /* 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 || -+ !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) -+ return 0; -+ -+ -+ nvbo->placement.fpfn = 0; -+ nvbo->placement.lpfn = dev_priv->fb_mappable_pages; -+ nouveau_bo_placement_set(nvbo, TTM_PL_VRAM, 0); -+ return ttm_bo_validate(bo, &nvbo->placement, false, true, false); -+} -+ -+void -+nouveau_bo_fence(struct nouveau_bo *nvbo, struct nouveau_fence *fence) -+{ -+ struct nouveau_fence *old_fence; -+ -+ if (likely(fence)) -+ nouveau_fence_ref(fence); -+ -+ spin_lock(&nvbo->bo.lock); -+ old_fence = nvbo->bo.sync_obj; -+ nvbo->bo.sync_obj = fence; -+ spin_unlock(&nvbo->bo.lock); -+ -+ nouveau_fence_unref(&old_fence); - } - - struct ttm_bo_driver nouveau_bo_driver = { -@@ -818,11 +962,11 @@ - .evict_flags = nouveau_bo_evict_flags, - .move = nouveau_bo_move, - .verify_access = nouveau_bo_verify_access, -- .sync_obj_signaled = nouveau_fence_signalled, -- .sync_obj_wait = nouveau_fence_wait, -- .sync_obj_flush = nouveau_fence_flush, -- .sync_obj_unref = nouveau_fence_unref, -- .sync_obj_ref = nouveau_fence_ref, -+ .sync_obj_signaled = __nouveau_fence_signalled, -+ .sync_obj_wait = __nouveau_fence_wait, -+ .sync_obj_flush = __nouveau_fence_flush, -+ .sync_obj_unref = __nouveau_fence_unref, -+ .sync_obj_ref = __nouveau_fence_ref, - .fault_reserve_notify = &nouveau_ttm_fault_reserve_notify, - .io_mem_reserve = &nouveau_ttm_io_mem_reserve, - .io_mem_free = &nouveau_ttm_io_mem_free, -diff -Naur linux-2.6.36/drivers/gpu/drm/nouveau/nouveau_calc.c linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nouveau_calc.c ---- linux-2.6.36/drivers/gpu/drm/nouveau/nouveau_calc.c 2010-10-20 22:30:22.000000000 +0200 -+++ linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nouveau_calc.c 2010-11-05 00:40:00.000000000 +0100 -@@ -198,8 +198,8 @@ - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nv_fifo_info fifo_data; - struct nv_sim_state sim_data; -- int MClk = nouveau_hw_get_clock(dev, MPLL); -- int NVClk = nouveau_hw_get_clock(dev, NVPLL); -+ int MClk = nouveau_hw_get_clock(dev, PLL_MEMORY); -+ int NVClk = nouveau_hw_get_clock(dev, PLL_CORE); - uint32_t cfg1 = nvReadFB(dev, NV04_PFB_CFG1); - - sim_data.pclk_khz = VClk; -@@ -234,7 +234,7 @@ - } - - static void --nv30_update_arb(int *burst, int *lwm) -+nv20_update_arb(int *burst, int *lwm) - { - unsigned int fifo_size, burst_size, graphics_lwm; - -@@ -251,14 +251,14 @@ - { - struct drm_nouveau_private *dev_priv = dev->dev_private; - -- if (dev_priv->card_type < NV_30) -+ if (dev_priv->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*/) { - *burst = 128; - *lwm = 0x0480; - } else -- nv30_update_arb(burst, lwm); -+ nv20_update_arb(burst, lwm); - } - - static int -diff -Naur linux-2.6.36/drivers/gpu/drm/nouveau/nouveau_channel.c linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nouveau_channel.c ---- linux-2.6.36/drivers/gpu/drm/nouveau/nouveau_channel.c 2010-10-20 22:30:22.000000000 +0200 -+++ linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nouveau_channel.c 2010-11-05 00:40:00.000000000 +0100 -@@ -48,14 +48,14 @@ - dev_priv->gart_info.aper_size, - NV_DMA_ACCESS_RO, &pushbuf, - NULL); -- chan->pushbuf_base = pb->bo.mem.mm_node->start << PAGE_SHIFT; -+ chan->pushbuf_base = pb->bo.mem.start << PAGE_SHIFT; - } 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_DMA_ACCESS_RO, - NV_DMA_TARGET_VIDMEM, &pushbuf); -- chan->pushbuf_base = pb->bo.mem.mm_node->start << PAGE_SHIFT; -+ chan->pushbuf_base = pb->bo.mem.start << PAGE_SHIFT; - } else { - /* NV04 cmdbuf hack, from original ddx.. not sure of it's - * exact reason for existing :) PCI access to cmdbuf in -@@ -67,17 +67,11 @@ - dev_priv->fb_available_size, - NV_DMA_ACCESS_RO, - NV_DMA_TARGET_PCI, &pushbuf); -- chan->pushbuf_base = pb->bo.mem.mm_node->start << PAGE_SHIFT; -- } -- -- ret = nouveau_gpuobj_ref_add(dev, chan, 0, pushbuf, &chan->pushbuf); -- if (ret) { -- NV_ERROR(dev, "Error referencing pushbuf ctxdma: %d\n", ret); -- if (pushbuf != dev_priv->gart_info.sg_ctxdma) -- nouveau_gpuobj_del(dev, &pushbuf); -- return ret; -+ chan->pushbuf_base = pb->bo.mem.start << PAGE_SHIFT; - } - -+ nouveau_gpuobj_ref(pushbuf, &chan->pushbuf); -+ nouveau_gpuobj_ref(NULL, &pushbuf); - return 0; - } - -@@ -113,53 +107,56 @@ - int - nouveau_channel_alloc(struct drm_device *dev, struct nouveau_channel **chan_ret, - struct drm_file *file_priv, -- uint32_t vram_handle, uint32_t tt_handle) -+ uint32_t vram_handle, uint32_t gart_handle) - { - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_pgraph_engine *pgraph = &dev_priv->engine.graph; - struct nouveau_fifo_engine *pfifo = &dev_priv->engine.fifo; - struct nouveau_channel *chan; -- int channel, user; -- int ret; -+ unsigned long flags; -+ int user, ret; - -- /* -- * Alright, here is the full story -- * Nvidia cards have multiple hw fifo contexts (praise them for that, -- * no complicated crash-prone context switches) -- * We allocate a new context for each app and let it write to it -- * directly (woo, full userspace command submission !) -- * When there are no more contexts, you lost -- */ -- for (channel = 0; channel < pfifo->channels; channel++) { -- if (dev_priv->fifos[channel] == NULL) -+ /* 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->channels.ptr[chan->id]) { -+ nouveau_channel_ref(chan, &dev_priv->channels.ptr[chan->id]); - break; -+ } - } -+ spin_unlock_irqrestore(&dev_priv->channels.lock, flags); - -- /* no more fifos. you lost. */ -- if (channel == pfifo->channels) -- return -EINVAL; -+ if (chan->id == pfifo->channels) { -+ mutex_unlock(&chan->mutex); -+ kfree(chan); -+ return -ENODEV; -+ } - -- dev_priv->fifos[channel] = kzalloc(sizeof(struct nouveau_channel), -- GFP_KERNEL); -- if (!dev_priv->fifos[channel]) -- return -ENOMEM; -- chan = dev_priv->fifos[channel]; -+ NV_DEBUG(dev, "initialising channel %d\n", chan->id); - INIT_LIST_HEAD(&chan->nvsw.vbl_wait); -+ INIT_LIST_HEAD(&chan->nvsw.flip); - INIT_LIST_HEAD(&chan->fence.pending); -- chan->dev = dev; -- chan->id = channel; -- chan->file_priv = file_priv; -- chan->vram_handle = vram_handle; -- chan->gart_handle = tt_handle; -- -- NV_INFO(dev, "Allocating FIFO number %d\n", channel); - - /* Allocate DMA push buffer */ - chan->pushbuf_bo = nouveau_channel_user_pushbuf_alloc(dev); - if (!chan->pushbuf_bo) { - ret = -ENOMEM; - NV_ERROR(dev, "pushbuf %d\n", ret); -- nouveau_channel_free(chan); -+ nouveau_channel_put(&chan); - return ret; - } - -@@ -167,18 +164,18 @@ - - /* Locate channel's user control regs */ - if (dev_priv->card_type < NV_40) -- user = NV03_USER(channel); -+ user = NV03_USER(chan->id); - else - if (dev_priv->card_type < NV_50) -- user = NV40_USER(channel); -+ user = NV40_USER(chan->id); - else -- user = NV50_USER(channel); -+ user = NV50_USER(chan->id); - - chan->user = ioremap(pci_resource_start(dev->pdev, 0) + user, - PAGE_SIZE); - if (!chan->user) { - NV_ERROR(dev, "ioremap of regs failed.\n"); -- nouveau_channel_free(chan); -+ nouveau_channel_put(&chan); - return -ENOMEM; - } - chan->user_put = 0x40; -@@ -188,15 +185,15 @@ - ret = nouveau_notifier_init_channel(chan); - if (ret) { - NV_ERROR(dev, "ntfy %d\n", ret); -- nouveau_channel_free(chan); -+ nouveau_channel_put(&chan); - return ret; - } - - /* Setup channel's default objects */ -- ret = nouveau_gpuobj_channel_init(chan, vram_handle, tt_handle); -+ ret = nouveau_gpuobj_channel_init(chan, vram_handle, gart_handle); - if (ret) { - NV_ERROR(dev, "gpuobj %d\n", ret); -- nouveau_channel_free(chan); -+ nouveau_channel_put(&chan); - return ret; - } - -@@ -204,7 +201,7 @@ - ret = nouveau_channel_pushbuf_ctxdma_init(chan); - if (ret) { - NV_ERROR(dev, "pbctxdma %d\n", ret); -- nouveau_channel_free(chan); -+ nouveau_channel_put(&chan); - return ret; - } - -@@ -212,16 +209,18 @@ - pfifo->reassign(dev, false); - - /* Create a graphics context for new channel */ -- ret = pgraph->create_context(chan); -- if (ret) { -- nouveau_channel_free(chan); -- return ret; -+ if (dev_priv->card_type < NV_50) { -+ ret = pgraph->create_context(chan); -+ if (ret) { -+ nouveau_channel_put(&chan); -+ return ret; -+ } - } - - /* Construct inital RAMFC for new channel */ - ret = pfifo->create_context(chan); - if (ret) { -- nouveau_channel_free(chan); -+ nouveau_channel_put(&chan); - return ret; - } - -@@ -229,130 +228,187 @@ - - ret = nouveau_dma_init(chan); - if (!ret) -- ret = nouveau_fence_init(chan); -+ ret = nouveau_fence_channel_init(chan); - if (ret) { -- nouveau_channel_free(chan); -+ nouveau_channel_put(&chan); - return ret; - } - - nouveau_debugfs_channel_init(chan); - -- NV_INFO(dev, "%s: initialised FIFO %d\n", __func__, channel); -+ NV_DEBUG(dev, "channel %d initialised\n", chan->id); - *chan_ret = chan; - return 0; - } - --/* stops a fifo */ -+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_device *dev, struct drm_file *file_priv, int id) -+{ -+ struct drm_nouveau_private *dev_priv = dev->dev_private; -+ struct nouveau_channel *chan; -+ unsigned long flags; -+ -+ spin_lock_irqsave(&dev_priv->channels.lock, flags); -+ chan = nouveau_channel_get_unlocked(dev_priv->channels.ptr[id]); -+ spin_unlock_irqrestore(&dev_priv->channels.lock, flags); -+ -+ if (unlikely(!chan)) -+ return ERR_PTR(-EINVAL); -+ -+ if (unlikely(file_priv && chan->file_priv != file_priv)) { -+ nouveau_channel_put_unlocked(&chan); -+ return ERR_PTR(-EINVAL); -+ } -+ -+ mutex_lock(&chan->mutex); -+ return chan; -+} -+ - void --nouveau_channel_free(struct nouveau_channel *chan) -+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_pgraph_engine *pgraph = &dev_priv->engine.graph; - struct nouveau_fifo_engine *pfifo = &dev_priv->engine.fifo; -+ struct nouveau_pgraph_engine *pgraph = &dev_priv->engine.graph; -+ struct nouveau_crypt_engine *pcrypt = &dev_priv->engine.crypt; - unsigned long flags; - int ret; - -- NV_INFO(dev, "%s: freeing fifo %d\n", __func__, chan->id); -+ /* 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; -+ } - -+ /* noone wants the channel anymore */ -+ NV_DEBUG(dev, "freeing channel %d\n", chan->id); - nouveau_debugfs_channel_fini(chan); - -- /* Give outstanding push buffers a chance to complete */ -+ /* give it chance to idle */ - nouveau_fence_update(chan); - if (chan->fence.sequence != chan->fence.sequence_ack) { - struct nouveau_fence *fence = NULL; - - ret = nouveau_fence_new(chan, &fence, true); - if (ret == 0) { -- ret = nouveau_fence_wait(fence, NULL, false, false); -- nouveau_fence_unref((void *)&fence); -+ ret = nouveau_fence_wait(fence, false, false); -+ nouveau_fence_unref(&fence); - } - - if (ret) - NV_ERROR(dev, "Failed to idle channel %d.\n", chan->id); - } - -- /* Ensure all outstanding fences are signaled. They should be if the -+ /* ensure all outstanding fences are signaled. they should be if the - * above attempts at idling were OK, but if we failed this'll tell TTM - * we're done with the buffers. - */ -- nouveau_fence_fini(chan); -+ nouveau_fence_channel_fini(chan); - -- /* This will prevent pfifo from switching channels. */ -+ /* boot it off the hardware */ - pfifo->reassign(dev, false); - -- /* We want to give pgraph a chance to idle and get rid of all potential -- * errors. We need to do this before the lock, otherwise the irq handler -- * is unable to process them. -+ /* We want to give pgraph a chance to idle and get rid of all -+ * potential errors. We need to do this without the context -+ * switch lock held, otherwise the irq handler is unable to -+ * process them. - */ - if (pgraph->channel(dev) == chan) - nouveau_wait_for_idle(dev); - -- spin_lock_irqsave(&dev_priv->context_switch_lock, flags); -- -- pgraph->fifo_access(dev, false); -- if (pgraph->channel(dev) == chan) -- pgraph->unload_context(dev); -- pgraph->destroy_context(chan); -- pgraph->fifo_access(dev, true); -- -- if (pfifo->channel_id(dev) == chan->id) { -- pfifo->disable(dev); -- pfifo->unload_context(dev); -- pfifo->enable(dev); -- } -+ /* destroy the engine specific contexts */ - pfifo->destroy_context(chan); -+ pgraph->destroy_context(chan); -+ if (pcrypt->destroy_context) -+ pcrypt->destroy_context(chan); - - pfifo->reassign(dev, true); - -- spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags); -+ /* 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); - -- /* Release the channel's resources */ -- nouveau_gpuobj_ref_del(dev, &chan->pushbuf); -+ /* destroy any resources the channel owned */ -+ nouveau_gpuobj_ref(NULL, &chan->pushbuf); - if (chan->pushbuf_bo) { -+ nouveau_bo_unmap(chan->pushbuf_bo); - nouveau_bo_unpin(chan->pushbuf_bo); - nouveau_bo_ref(NULL, &chan->pushbuf_bo); - } - nouveau_gpuobj_channel_takedown(chan); - nouveau_notifier_takedown_channel(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); -+ - if (chan->user) - iounmap(chan->user); - -- dev_priv->fifos[chan->id] = NULL; - 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; -+} -+ - /* cleans up all the fifos from file_priv */ - void - nouveau_channel_cleanup(struct drm_device *dev, struct drm_file *file_priv) - { - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_engine *engine = &dev_priv->engine; -+ struct nouveau_channel *chan; - int i; - - NV_DEBUG(dev, "clearing FIFO enables from file_priv\n"); - for (i = 0; i < engine->fifo.channels; i++) { -- struct nouveau_channel *chan = dev_priv->fifos[i]; -+ chan = nouveau_channel_get(dev, file_priv, i); -+ if (IS_ERR(chan)) -+ continue; - -- if (chan && chan->file_priv == file_priv) -- nouveau_channel_free(chan); -+ atomic_dec(&chan->users); -+ nouveau_channel_put(&chan); - } - } - --int --nouveau_channel_owner(struct drm_device *dev, struct drm_file *file_priv, -- int channel) --{ -- struct drm_nouveau_private *dev_priv = dev->dev_private; -- struct nouveau_engine *engine = &dev_priv->engine; -- -- if (channel >= engine->fifo.channels) -- return 0; -- if (dev_priv->fifos[channel] == NULL) -- return 0; -- -- return (dev_priv->fifos[channel]->file_priv == file_priv); --} - - /*********************************** - * ioctls wrapping the functions -@@ -400,24 +456,26 @@ - /* Named memory object area */ - ret = drm_gem_handle_create(file_priv, chan->notifier_bo->gem, - &init->notifier_handle); -- if (ret) { -- nouveau_channel_free(chan); -- return ret; -- } - -- return 0; -+ if (ret == 0) -+ atomic_inc(&chan->users); /* userspace reference */ -+ nouveau_channel_put(&chan); -+ return ret; - } - - static int - nouveau_ioctl_fifo_free(struct drm_device *dev, void *data, - struct drm_file *file_priv) - { -- struct drm_nouveau_channel_free *cfree = data; -+ struct drm_nouveau_channel_free *req = data; - struct nouveau_channel *chan; - -- NOUVEAU_GET_USER_CHANNEL_WITH_RETURN(cfree->channel, file_priv, chan); -+ chan = nouveau_channel_get(dev, file_priv, req->channel); -+ if (IS_ERR(chan)) -+ return PTR_ERR(chan); - -- nouveau_channel_free(chan); -+ atomic_dec(&chan->users); -+ nouveau_channel_put(&chan); - return 0; - } - -@@ -426,18 +484,18 @@ - ***********************************/ - - struct drm_ioctl_desc nouveau_ioctls[] = { -- DRM_IOCTL_DEF_DRV(NOUVEAU_GETPARAM, nouveau_ioctl_getparam, DRM_AUTH), -- DRM_IOCTL_DEF_DRV(NOUVEAU_SETPARAM, nouveau_ioctl_setparam, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), -- DRM_IOCTL_DEF_DRV(NOUVEAU_CHANNEL_ALLOC, nouveau_ioctl_fifo_alloc, DRM_AUTH), -- DRM_IOCTL_DEF_DRV(NOUVEAU_CHANNEL_FREE, nouveau_ioctl_fifo_free, DRM_AUTH), -- DRM_IOCTL_DEF_DRV(NOUVEAU_GROBJ_ALLOC, nouveau_ioctl_grobj_alloc, DRM_AUTH), -- DRM_IOCTL_DEF_DRV(NOUVEAU_NOTIFIEROBJ_ALLOC, nouveau_ioctl_notifier_alloc, DRM_AUTH), -- DRM_IOCTL_DEF_DRV(NOUVEAU_GPUOBJ_FREE, nouveau_ioctl_gpuobj_free, DRM_AUTH), -- DRM_IOCTL_DEF_DRV(NOUVEAU_GEM_NEW, nouveau_gem_ioctl_new, DRM_AUTH), -- DRM_IOCTL_DEF_DRV(NOUVEAU_GEM_PUSHBUF, nouveau_gem_ioctl_pushbuf, DRM_AUTH), -- DRM_IOCTL_DEF_DRV(NOUVEAU_GEM_CPU_PREP, nouveau_gem_ioctl_cpu_prep, DRM_AUTH), -- DRM_IOCTL_DEF_DRV(NOUVEAU_GEM_CPU_FINI, nouveau_gem_ioctl_cpu_fini, DRM_AUTH), -- DRM_IOCTL_DEF_DRV(NOUVEAU_GEM_INFO, nouveau_gem_ioctl_info, DRM_AUTH), -+ DRM_IOCTL_DEF_DRV(NOUVEAU_GETPARAM, nouveau_ioctl_getparam, DRM_UNLOCKED|DRM_AUTH), -+ DRM_IOCTL_DEF_DRV(NOUVEAU_SETPARAM, nouveau_ioctl_setparam, DRM_UNLOCKED|DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), -+ DRM_IOCTL_DEF_DRV(NOUVEAU_CHANNEL_ALLOC, nouveau_ioctl_fifo_alloc, DRM_UNLOCKED|DRM_AUTH), -+ DRM_IOCTL_DEF_DRV(NOUVEAU_CHANNEL_FREE, nouveau_ioctl_fifo_free, DRM_UNLOCKED|DRM_AUTH), -+ DRM_IOCTL_DEF_DRV(NOUVEAU_GROBJ_ALLOC, nouveau_ioctl_grobj_alloc, DRM_UNLOCKED|DRM_AUTH), -+ DRM_IOCTL_DEF_DRV(NOUVEAU_NOTIFIEROBJ_ALLOC, nouveau_ioctl_notifier_alloc, DRM_UNLOCKED|DRM_AUTH), -+ DRM_IOCTL_DEF_DRV(NOUVEAU_GPUOBJ_FREE, nouveau_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), - }; - - int nouveau_max_ioctl = DRM_ARRAY_SIZE(nouveau_ioctls); -diff -Naur linux-2.6.36/drivers/gpu/drm/nouveau/nouveau_connector.c linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nouveau_connector.c ---- linux-2.6.36/drivers/gpu/drm/nouveau/nouveau_connector.c 2010-10-20 22:30:22.000000000 +0200 -+++ linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nouveau_connector.c 2010-11-05 00:40:00.000000000 +0100 -@@ -76,6 +76,22 @@ - return NULL; - } - -+/*TODO: This could use improvement, and learn to handle the fixed -+ * BIOS tables etc. It's fine currently, for its only user. -+ */ -+int -+nouveau_connector_bpp(struct drm_connector *connector) -+{ -+ struct nouveau_connector *nv_connector = nouveau_connector(connector); -+ -+ if (nv_connector->edid && nv_connector->edid->revision >= 4) { -+ u8 bpc = ((nv_connector->edid->input & 0x70) >> 3) + 4; -+ if (bpc > 4) -+ return bpc; -+ } -+ -+ return 18; -+} - - static void - nouveau_connector_destroy(struct drm_connector *drm_connector) -@@ -130,6 +146,36 @@ - return NULL; - } - -+static struct nouveau_encoder * -+nouveau_connector_of_detect(struct drm_connector *connector) -+{ -+#ifdef __powerpc__ -+ struct drm_device *dev = connector->dev; -+ struct nouveau_connector *nv_connector = nouveau_connector(connector); -+ struct nouveau_encoder *nv_encoder; -+ struct device_node *cn, *dn = pci_device_to_OF_node(dev->pdev); -+ -+ if (!dn || -+ !((nv_encoder = find_encoder_by_type(connector, OUTPUT_TMDS)) || -+ (nv_encoder = find_encoder_by_type(connector, OUTPUT_ANALOG)))) -+ return NULL; -+ -+ for_each_child_of_node(dn, cn) { -+ const char *name = of_get_property(cn, "name", NULL); -+ const void *edid = of_get_property(cn, "EDID", NULL); -+ int idx = name ? name[strlen(name) - 1] - 'A' : 0; -+ -+ if (nv_encoder->dcb->i2c_index == idx && edid) { -+ nv_connector->edid = -+ kmemdup(edid, EDID_LENGTH, GFP_KERNEL); -+ of_node_put(cn); -+ return nv_encoder; -+ } -+ } -+#endif -+ return NULL; -+} -+ - static void - nouveau_connector_set_encoder(struct drm_connector *connector, - struct nouveau_encoder *nv_encoder) -@@ -225,11 +271,17 @@ - return connector_status_connected; - } - -+ nv_encoder = nouveau_connector_of_detect(connector); -+ if (nv_encoder) { -+ nouveau_connector_set_encoder(connector, nv_encoder); -+ return connector_status_connected; -+ } -+ - detect_analog: - nv_encoder = find_encoder_by_type(connector, OUTPUT_ANALOG); - if (!nv_encoder && !nouveau_tv_disable) - nv_encoder = find_encoder_by_type(connector, OUTPUT_TV); -- if (nv_encoder) { -+ if (nv_encoder && force) { - struct drm_encoder *encoder = to_drm_encoder(nv_encoder); - struct drm_encoder_helper_funcs *helper = - encoder->helper_private; -@@ -589,11 +641,28 @@ - return ret; - } - -+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 dcb_entry *dcb = nv_connector->detected_encoder->dcb; -+ -+ if (dcb->location != DCB_LOC_ON_CHIP || -+ dev_priv->chipset >= 0x46) -+ return 165000; -+ else if (dev_priv->chipset >= 0x40) -+ return 155000; -+ else if (dev_priv->chipset >= 0x18) -+ return 135000; -+ else -+ return 112000; -+} -+ - static int - nouveau_connector_mode_valid(struct drm_connector *connector, - struct drm_display_mode *mode) - { -- struct drm_nouveau_private *dev_priv = connector->dev->dev_private; - 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); -@@ -611,11 +680,9 @@ - max_clock = 400000; - break; - case OUTPUT_TMDS: -- if ((dev_priv->card_type >= NV_50 && !nouveau_duallink) || -- !nv_encoder->dcb->duallink_possible) -- max_clock = 165000; -- else -- max_clock = 330000; -+ max_clock = get_tmds_link_bandwidth(connector); -+ if (nouveau_duallink && nv_encoder->dcb->duallink_possible) -+ max_clock *= 2; - break; - case OUTPUT_ANALOG: - max_clock = nv_encoder->dcb->crtconf.maxfreq; -@@ -630,7 +697,7 @@ - else - max_clock = nv_encoder->dp.link_nr * 162000; - -- clock *= 3; -+ clock = clock * nouveau_connector_bpp(connector) / 8; - break; - default: - BUG_ON(1); -@@ -657,44 +724,6 @@ - return NULL; - } - --void --nouveau_connector_set_polling(struct drm_connector *connector) --{ -- struct drm_device *dev = connector->dev; -- struct drm_nouveau_private *dev_priv = dev->dev_private; -- struct drm_crtc *crtc; -- bool spare_crtc = false; -- -- list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) -- spare_crtc |= !crtc->enabled; -- -- connector->polled = 0; -- -- switch (connector->connector_type) { -- case DRM_MODE_CONNECTOR_VGA: -- case DRM_MODE_CONNECTOR_TV: -- if (dev_priv->card_type >= NV_50 || -- (nv_gf4_disp_arch(dev) && spare_crtc)) -- connector->polled = DRM_CONNECTOR_POLL_CONNECT; -- break; -- -- case DRM_MODE_CONNECTOR_DVII: -- case DRM_MODE_CONNECTOR_DVID: -- case DRM_MODE_CONNECTOR_HDMIA: -- case DRM_MODE_CONNECTOR_DisplayPort: -- case DRM_MODE_CONNECTOR_eDP: -- if (dev_priv->card_type >= NV_50) -- connector->polled = DRM_CONNECTOR_POLL_HPD; -- else if (connector->connector_type == DRM_MODE_CONNECTOR_DVID || -- spare_crtc) -- connector->polled = DRM_CONNECTOR_POLL_CONNECT; -- break; -- -- default: -- break; -- } --} -- - static const struct drm_connector_helper_funcs - nouveau_connector_helper_funcs = { - .get_modes = nouveau_connector_get_modes, -@@ -820,6 +849,7 @@ - dev->mode_config.scaling_mode_property, - nv_connector->scaling_mode); - } -+ connector->polled = DRM_CONNECTOR_POLL_CONNECT; - /* fall-through */ - case DCB_CONNECTOR_TV_0: - case DCB_CONNECTOR_TV_1: -@@ -836,11 +866,16 @@ - dev->mode_config.dithering_mode_property, - nv_connector->use_dithering ? - DRM_MODE_DITHERING_ON : DRM_MODE_DITHERING_OFF); -+ -+ if (dcb->type != DCB_CONNECTOR_LVDS) { -+ if (dev_priv->card_type >= NV_50) -+ connector->polled = DRM_CONNECTOR_POLL_HPD; -+ else -+ connector->polled = DRM_CONNECTOR_POLL_CONNECT; -+ } - break; - } - -- nouveau_connector_set_polling(connector); -- - drm_sysfs_connector_add(connector); - dcb->drm = connector; - return dcb->drm; -diff -Naur linux-2.6.36/drivers/gpu/drm/nouveau/nouveau_connector.h linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nouveau_connector.h ---- linux-2.6.36/drivers/gpu/drm/nouveau/nouveau_connector.h 2010-10-20 22:30:22.000000000 +0200 -+++ linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nouveau_connector.h 2010-11-05 00:40:00.000000000 +0100 -@@ -52,7 +52,7 @@ - struct drm_connector * - nouveau_connector_create(struct drm_device *, int index); - --void --nouveau_connector_set_polling(struct drm_connector *); -+int -+nouveau_connector_bpp(struct drm_connector *); - - #endif /* __NOUVEAU_CONNECTOR_H__ */ -diff -Naur linux-2.6.36/drivers/gpu/drm/nouveau/nouveau_debugfs.c linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nouveau_debugfs.c ---- linux-2.6.36/drivers/gpu/drm/nouveau/nouveau_debugfs.c 2010-10-20 22:30:22.000000000 +0200 -+++ linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nouveau_debugfs.c 2010-11-05 00:40:00.000000000 +0100 -@@ -157,7 +157,23 @@ - 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 }, -diff -Naur linux-2.6.36/drivers/gpu/drm/nouveau/nouveau_display.c linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nouveau_display.c ---- linux-2.6.36/drivers/gpu/drm/nouveau/nouveau_display.c 2010-10-20 22:30:22.000000000 +0200 -+++ linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nouveau_display.c 2010-11-05 00:40:00.000000000 +0100 -@@ -29,6 +29,9 @@ - #include "nouveau_drv.h" - #include "nouveau_fb.h" - #include "nouveau_fbcon.h" -+#include "nouveau_hw.h" -+#include "nouveau_crtc.h" -+#include "nouveau_dma.h" - - static void - nouveau_user_framebuffer_destroy(struct drm_framebuffer *drm_fb) -@@ -104,3 +107,207 @@ - .output_poll_changed = nouveau_fbcon_output_poll_changed, - }; - -+int -+nouveau_vblank_enable(struct drm_device *dev, int crtc) -+{ -+ struct drm_nouveau_private *dev_priv = dev->dev_private; -+ -+ if (dev_priv->card_type >= NV_50) -+ nv_mask(dev, NV50_PDISPLAY_INTR_EN_1, 0, -+ NV50_PDISPLAY_INTR_EN_1_VBLANK_CRTC_(crtc)); -+ else -+ NVWriteCRTC(dev, crtc, NV_PCRTC_INTR_EN_0, -+ NV_PCRTC_INTR_0_VBLANK); -+ -+ return 0; -+} -+ -+void -+nouveau_vblank_disable(struct drm_device *dev, int crtc) -+{ -+ struct drm_nouveau_private *dev_priv = dev->dev_private; -+ -+ if (dev_priv->card_type >= NV_50) -+ nv_mask(dev, NV50_PDISPLAY_INTR_EN_1, -+ NV50_PDISPLAY_INTR_EN_1_VBLANK_CRTC_(crtc), 0); -+ else -+ NVWriteCRTC(dev, crtc, NV_PCRTC_INTR_EN_0, 0); -+} -+ -+static int -+nouveau_page_flip_reserve(struct nouveau_bo *old_bo, -+ struct nouveau_bo *new_bo) -+{ -+ int ret; -+ -+ ret = nouveau_bo_pin(new_bo, TTM_PL_FLAG_VRAM); -+ if (ret) -+ return ret; -+ -+ ret = ttm_bo_reserve(&new_bo->bo, false, false, false, 0); -+ if (ret) -+ goto fail; -+ -+ ret = ttm_bo_reserve(&old_bo->bo, false, false, false, 0); -+ if (ret) -+ goto fail_unreserve; -+ -+ return 0; -+ -+fail_unreserve: -+ ttm_bo_unreserve(&new_bo->bo); -+fail: -+ nouveau_bo_unpin(new_bo); -+ return ret; -+} -+ -+static void -+nouveau_page_flip_unreserve(struct nouveau_bo *old_bo, -+ struct nouveau_bo *new_bo, -+ struct nouveau_fence *fence) -+{ -+ nouveau_bo_fence(new_bo, fence); -+ ttm_bo_unreserve(&new_bo->bo); -+ -+ nouveau_bo_fence(old_bo, fence); -+ ttm_bo_unreserve(&old_bo->bo); -+ -+ nouveau_bo_unpin(old_bo); -+} -+ -+static int -+nouveau_page_flip_emit(struct nouveau_channel *chan, -+ struct nouveau_bo *old_bo, -+ struct nouveau_bo *new_bo, -+ struct nouveau_page_flip_state *s, -+ struct nouveau_fence **pfence) -+{ -+ struct drm_device *dev = chan->dev; -+ unsigned long flags; -+ int ret; -+ -+ /* Queue it to the pending list */ -+ spin_lock_irqsave(&dev->event_lock, flags); -+ list_add_tail(&s->head, &chan->nvsw.flip); -+ spin_unlock_irqrestore(&dev->event_lock, flags); -+ -+ /* Synchronize with the old framebuffer */ -+ ret = nouveau_fence_sync(old_bo->bo.sync_obj, chan); -+ if (ret) -+ goto fail; -+ -+ /* Emit the pageflip */ -+ ret = RING_SPACE(chan, 2); -+ if (ret) -+ goto fail; -+ -+ BEGIN_RING(chan, NvSubSw, NV_SW_PAGE_FLIP, 1); -+ OUT_RING(chan, 0); -+ FIRE_RING(chan); -+ -+ ret = nouveau_fence_new(chan, pfence, true); -+ if (ret) -+ goto fail; -+ -+ return 0; -+fail: -+ spin_lock_irqsave(&dev->event_lock, flags); -+ list_del(&s->head); -+ spin_unlock_irqrestore(&dev->event_lock, flags); -+ return ret; -+} -+ -+int -+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_bo *old_bo = nouveau_framebuffer(crtc->fb)->nvbo; -+ struct nouveau_bo *new_bo = nouveau_framebuffer(fb)->nvbo; -+ struct nouveau_page_flip_state *s; -+ struct nouveau_channel *chan; -+ struct nouveau_fence *fence; -+ int ret; -+ -+ if (dev_priv->engine.graph.accel_blocked) -+ return -ENODEV; -+ -+ s = kzalloc(sizeof(*s), GFP_KERNEL); -+ if (!s) -+ return -ENOMEM; -+ -+ /* Don't let the buffers go away while we flip */ -+ ret = nouveau_page_flip_reserve(old_bo, new_bo); -+ if (ret) -+ goto fail_free; -+ -+ /* Initialize a page flip struct */ -+ *s = (struct nouveau_page_flip_state) -+ { { }, s->event, nouveau_crtc(crtc)->index, -+ fb->bits_per_pixel, fb->pitch, crtc->x, crtc->y, -+ new_bo->bo.offset }; -+ -+ /* Choose the channel the flip will be handled in */ -+ chan = nouveau_fence_channel(new_bo->bo.sync_obj); -+ if (!chan) -+ chan = nouveau_channel_get_unlocked(dev_priv->channel); -+ mutex_lock(&chan->mutex); -+ -+ /* Emit a page flip */ -+ ret = nouveau_page_flip_emit(chan, old_bo, new_bo, s, &fence); -+ nouveau_channel_put(&chan); -+ if (ret) -+ goto fail_unreserve; -+ -+ /* Update the crtc struct and cleanup */ -+ crtc->fb = fb; -+ -+ nouveau_page_flip_unreserve(old_bo, new_bo, fence); -+ nouveau_fence_unref(&fence); -+ return 0; -+ -+fail_unreserve: -+ nouveau_page_flip_unreserve(old_bo, new_bo, NULL); -+fail_free: -+ kfree(s); -+ return ret; -+} -+ -+int -+nouveau_finish_page_flip(struct nouveau_channel *chan, -+ struct nouveau_page_flip_state *ps) -+{ -+ struct drm_device *dev = chan->dev; -+ struct nouveau_page_flip_state *s; -+ unsigned long flags; -+ -+ spin_lock_irqsave(&dev->event_lock, flags); -+ -+ if (list_empty(&chan->nvsw.flip)) { -+ NV_ERROR(dev, "Unexpected pageflip in channel %d.\n", chan->id); -+ spin_unlock_irqrestore(&dev->event_lock, flags); -+ return -EINVAL; -+ } -+ -+ s = list_first_entry(&chan->nvsw.flip, -+ struct nouveau_page_flip_state, head); -+ if (s->event) { -+ struct drm_pending_vblank_event *e = s->event; -+ struct timeval now; -+ -+ do_gettimeofday(&now); -+ e->event.sequence = 0; -+ e->event.tv_sec = now.tv_sec; -+ e->event.tv_usec = now.tv_usec; -+ list_add_tail(&e->base.link, &e->base.file_priv->event_list); -+ wake_up_interruptible(&e->base.file_priv->event_wait); -+ } -+ -+ list_del(&s->head); -+ *ps = *s; -+ kfree(s); -+ -+ spin_unlock_irqrestore(&dev->event_lock, flags); -+ return 0; -+} -diff -Naur linux-2.6.36/drivers/gpu/drm/nouveau/nouveau_dma.c linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nouveau_dma.c ---- linux-2.6.36/drivers/gpu/drm/nouveau/nouveau_dma.c 2010-10-20 22:30:22.000000000 +0200 -+++ linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nouveau_dma.c 2010-11-05 00:40:00.000000000 +0100 -@@ -28,6 +28,7 @@ - #include "drm.h" - #include "nouveau_drv.h" - #include "nouveau_dma.h" -+#include "nouveau_ramht.h" - - void - nouveau_dma_pre_init(struct nouveau_channel *chan) -@@ -58,26 +59,17 @@ - { - struct drm_device *dev = chan->dev; - struct drm_nouveau_private *dev_priv = dev->dev_private; -- struct nouveau_gpuobj *m2mf = NULL; -- struct nouveau_gpuobj *nvsw = NULL; -+ struct nouveau_gpuobj *obj = NULL; - int ret, i; - - /* Create NV_MEMORY_TO_MEMORY_FORMAT for buffer moves */ - ret = nouveau_gpuobj_gr_new(chan, dev_priv->card_type < NV_50 ? -- 0x0039 : 0x5039, &m2mf); -+ 0x0039 : 0x5039, &obj); - if (ret) - return ret; - -- ret = nouveau_gpuobj_ref_add(dev, chan, NvM2MF, m2mf, NULL); -- if (ret) -- return ret; -- -- /* Create an NV_SW object for various sync purposes */ -- ret = nouveau_gpuobj_sw_new(chan, NV_SW, &nvsw); -- if (ret) -- return ret; -- -- ret = nouveau_gpuobj_ref_add(dev, chan, NvSw, nvsw, NULL); -+ ret = nouveau_ramht_insert(chan, NvM2MF, obj); -+ nouveau_gpuobj_ref(NULL, &obj); - if (ret) - return ret; - -@@ -91,11 +83,6 @@ - if (ret) - return ret; - -- /* Map M2MF notifier object - fbcon. */ -- ret = nouveau_bo_map(chan->notifier_bo); -- if (ret) -- return ret; -- - /* Insert NOPS for NOUVEAU_DMA_SKIPS */ - ret = RING_SPACE(chan, NOUVEAU_DMA_SKIPS); - if (ret) -@@ -113,13 +100,6 @@ - BEGIN_RING(chan, NvSubM2MF, NV_MEMORY_TO_MEMORY_FORMAT_DMA_NOTIFY, 1); - OUT_RING(chan, NvNotify0); - -- /* Initialise NV_SW */ -- ret = RING_SPACE(chan, 2); -- if (ret) -- return ret; -- BEGIN_RING(chan, NvSubSw, 0, 1); -- OUT_RING(chan, NvSw); -- - /* Sit back and pray the channel works.. */ - FIRE_RING(chan); - -@@ -217,7 +197,7 @@ - - chan->dma.ib_free = get - chan->dma.ib_put; - if (chan->dma.ib_free <= 0) -- chan->dma.ib_free += chan->dma.ib_max + 1; -+ chan->dma.ib_free += chan->dma.ib_max; - } - - return 0; -diff -Naur linux-2.6.36/drivers/gpu/drm/nouveau/nouveau_dma.h linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nouveau_dma.h ---- linux-2.6.36/drivers/gpu/drm/nouveau/nouveau_dma.h 2010-10-20 22:30:22.000000000 +0200 -+++ linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nouveau_dma.h 2010-11-05 00:40:00.000000000 +0100 -@@ -72,6 +72,7 @@ - NvGdiRect = 0x8000000c, - NvImageBlit = 0x8000000d, - NvSw = 0x8000000e, -+ NvSema = 0x8000000f, - - /* G80+ display objects */ - NvEvoVRAM = 0x01000000, -diff -Naur linux-2.6.36/drivers/gpu/drm/nouveau/nouveau_dp.c linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nouveau_dp.c ---- linux-2.6.36/drivers/gpu/drm/nouveau/nouveau_dp.c 2010-10-20 22:30:22.000000000 +0200 -+++ linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nouveau_dp.c 2010-11-05 00:40:00.000000000 +0100 -@@ -317,7 +317,8 @@ - return false; - - config[0] = nv_encoder->dp.link_nr; -- if (nv_encoder->dp.dpcd_version >= 0x11) -+ if (nv_encoder->dp.dpcd_version >= 0x11 && -+ nv_encoder->dp.enhanced_frame) - config[0] |= DP_LANE_COUNT_ENHANCED_FRAME_EN; - - ret = nouveau_dp_lane_count_set(encoder, config[0]); -@@ -468,10 +469,12 @@ - !nv_encoder->dcb->dpconf.link_bw) - nv_encoder->dp.link_bw = DP_LINK_BW_1_62; - -- nv_encoder->dp.link_nr = dpcd[2] & 0xf; -+ nv_encoder->dp.link_nr = dpcd[2] & DP_MAX_LANE_COUNT_MASK; - if (nv_encoder->dp.link_nr > nv_encoder->dcb->dpconf.link_nr) - nv_encoder->dp.link_nr = nv_encoder->dcb->dpconf.link_nr; - -+ nv_encoder->dp.enhanced_frame = (dpcd[2] & DP_ENHANCED_FRAME_CAP); -+ - return true; - } - -@@ -524,7 +527,8 @@ - nv_wr32(dev, NV50_AUXCH_CTRL(index), ctrl | 0x80000000); - nv_wr32(dev, NV50_AUXCH_CTRL(index), ctrl); - nv_wr32(dev, NV50_AUXCH_CTRL(index), ctrl | 0x00010000); -- if (!nv_wait(NV50_AUXCH_CTRL(index), 0x00010000, 0x00000000)) { -+ if (!nv_wait(dev, NV50_AUXCH_CTRL(index), -+ 0x00010000, 0x00000000)) { - NV_ERROR(dev, "expected bit 16 == 0, got 0x%08x\n", - nv_rd32(dev, NV50_AUXCH_CTRL(index))); - ret = -EBUSY; -diff -Naur linux-2.6.36/drivers/gpu/drm/nouveau/nouveau_drv.c linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nouveau_drv.c ---- linux-2.6.36/drivers/gpu/drm/nouveau/nouveau_drv.c 2010-10-20 22:30:22.000000000 +0200 -+++ linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nouveau_drv.c 2010-11-05 00:40:00.000000000 +0100 -@@ -31,13 +31,14 @@ - #include "nouveau_hw.h" - #include "nouveau_fb.h" - #include "nouveau_fbcon.h" -+#include "nouveau_pm.h" - #include "nv50_display.h" - - #include "drm_pciids.h" - --MODULE_PARM_DESC(noagp, "Disable AGP"); --int nouveau_noagp; --module_param_named(noagp, nouveau_noagp, int, 0400); -+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"); - static int nouveau_modeset = -1; /* kms */ -@@ -79,6 +80,10 @@ - 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); -+ - MODULE_PARM_DESC(override_conntype, "Ignore DCB connector type"); - int nouveau_override_conntype = 0; - module_param_named(override_conntype, nouveau_override_conntype, int, 0400); -@@ -102,6 +107,18 @@ - int nouveau_reg_debug; - module_param_named(reg_debug, nouveau_reg_debug, int, 0600); - -+MODULE_PARM_DESC(perflvl, "Performance level (default: boot)\n"); -+char *nouveau_perflvl; -+module_param_named(perflvl, nouveau_perflvl, charp, 0400); -+ -+MODULE_PARM_DESC(perflvl_wr, "Allow perflvl changes (warning: dangerous!)\n"); -+int nouveau_perflvl_wr; -+module_param_named(perflvl_wr, nouveau_perflvl_wr, int, 0400); -+ -+MODULE_PARM_DESC(msi, "Enable MSI (default: off)\n"); -+int nouveau_msi; -+module_param_named(msi, nouveau_msi, int, 0400); -+ - int nouveau_fbpercrtc; - #if 0 - module_param_named(fbpercrtc, nouveau_fbpercrtc, int, 0400); -@@ -182,15 +199,14 @@ - for (i = 0; i < pfifo->channels; i++) { - struct nouveau_fence *fence = NULL; - -- chan = dev_priv->fifos[i]; -- if (!chan || (dev_priv->card_type >= NV_50 && -- chan == dev_priv->fifos[0])) -+ chan = dev_priv->channels.ptr[i]; -+ if (!chan || !chan->pushbuf_bo) - continue; - - ret = nouveau_fence_new(chan, &fence, true); - if (ret == 0) { -- ret = nouveau_fence_wait(fence, NULL, false, false); -- nouveau_fence_unref((void *)&fence); -+ ret = nouveau_fence_wait(fence, false, false); -+ nouveau_fence_unref(&fence); - } - - if (ret) { -@@ -271,6 +287,8 @@ - if (ret) - return ret; - -+ nouveau_pm_resume(dev); -+ - if (dev_priv->gart_info.type == NOUVEAU_GART_AGP) { - ret = nouveau_mem_init_agp(dev); - if (ret) { -@@ -285,6 +303,7 @@ - engine->timer.init(dev); - engine->fb.init(dev); - engine->graph.init(dev); -+ engine->crypt.init(dev); - engine->fifo.init(dev); - - NV_INFO(dev, "Restoring GPU objects...\n"); -@@ -298,7 +317,7 @@ - int j; - - for (i = 0; i < dev_priv->engine.fifo.channels; i++) { -- chan = dev_priv->fifos[i]; -+ chan = dev_priv->channels.ptr[i]; - if (!chan || !chan->pushbuf_bo) - continue; - -@@ -378,6 +397,9 @@ - .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, - .reclaim_buffers = drm_core_reclaim_buffers, - .get_map_ofs = drm_core_get_map_ofs, - .get_reg_ofs = drm_core_get_reg_ofs, -@@ -390,6 +412,7 @@ - .mmap = nouveau_ttm_mmap, - .poll = drm_poll, - .fasync = drm_fasync, -+ .read = drm_read, - #if defined(CONFIG_COMPAT) - .compat_ioctl = nouveau_compat_ioctl, - #endif -@@ -434,6 +457,12 @@ - if (!nouveau_modeset) - return 0; - -+#if defined(CONFIG_FRAMEBUFFER_CONSOLE_MODULE) -+ request_module("fbcon"); -+#elif !defined(CONFIG_FRAMEBUFFER_CONSOLE) -+ printk(KERN_INFO "CONFIG_FRAMEBUFFER_CONSOLE was not enabled. You won't get any console output.\n"); -+#endif -+ - nouveau_register_dsm_handler(); - return drm_init(&driver); - } -diff -Naur linux-2.6.36/drivers/gpu/drm/nouveau/nouveau_drv.h linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nouveau_drv.h ---- linux-2.6.36/drivers/gpu/drm/nouveau/nouveau_drv.h 2010-10-20 22:30:22.000000000 +0200 -+++ linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nouveau_drv.h 2010-11-05 00:40:00.000000000 +0100 -@@ -66,10 +66,13 @@ - #define NV50_VM_VRAM_NR (NV50_VM_MAX_VRAM / NV50_VM_BLOCK) - - struct nouveau_tile_reg { -- struct nouveau_fence *fence; -- uint32_t addr; -- uint32_t size; - bool used; -+ uint32_t addr; -+ uint32_t limit; -+ uint32_t pitch; -+ uint32_t zcomp; -+ struct drm_mm_node *tag_mem; -+ struct nouveau_fence *fence; - }; - - struct nouveau_bo { -@@ -96,10 +99,12 @@ - struct nouveau_tile_reg *tile; - - struct drm_gem_object *gem; -- struct drm_file *cpu_filp; - int pin_refcnt; - }; - -+#define nouveau_bo_tile_layout(nvbo) \ -+ ((nvbo)->tile_flags & NOUVEAU_GEM_TILE_LAYOUT_MASK) -+ - static inline struct nouveau_bo * - nouveau_bo(struct ttm_buffer_object *bo) - { -@@ -130,25 +135,32 @@ - - #define NVOBJ_ENGINE_SW 0 - #define NVOBJ_ENGINE_GR 1 --#define NVOBJ_ENGINE_DISPLAY 2 -+#define NVOBJ_ENGINE_PPP 2 -+#define NVOBJ_ENGINE_COPY 3 -+#define NVOBJ_ENGINE_VP 4 -+#define NVOBJ_ENGINE_CRYPT 5 -+#define NVOBJ_ENGINE_BSP 6 -+#define NVOBJ_ENGINE_DISPLAY 0xcafe0001 - #define NVOBJ_ENGINE_INT 0xdeadbeef - --#define NVOBJ_FLAG_ALLOW_NO_REFS (1 << 0) - #define NVOBJ_FLAG_ZERO_ALLOC (1 << 1) - #define NVOBJ_FLAG_ZERO_FREE (1 << 2) --#define NVOBJ_FLAG_FAKE (1 << 3) - struct nouveau_gpuobj { -+ struct drm_device *dev; -+ struct kref refcount; - struct list_head list; - -- struct nouveau_channel *im_channel; - struct drm_mm_node *im_pramin; - struct nouveau_bo *im_backing; -- uint32_t im_backing_start; - uint32_t *im_backing_suspend; - int im_bound; - - uint32_t flags; -- int refcount; -+ -+ u32 size; -+ u32 pinst; -+ u32 cinst; -+ u64 vinst; - - uint32_t engine; - uint32_t class; -@@ -157,20 +169,29 @@ - void *priv; - }; - --struct nouveau_gpuobj_ref { -- struct list_head list; -- -- struct nouveau_gpuobj *gpuobj; -- uint32_t instance; -+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_channel *channel; -- int handle; -+enum nouveau_channel_mutex_class { -+ NOUVEAU_UCHANNEL_MUTEX, -+ NOUVEAU_KCHANNEL_MUTEX - }; - - struct nouveau_channel { - struct drm_device *dev; - 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 */ -@@ -192,33 +213,33 @@ - } fence; - - /* DMA push buffer */ -- struct nouveau_gpuobj_ref *pushbuf; -- struct nouveau_bo *pushbuf_bo; -- uint32_t pushbuf_base; -+ struct nouveau_gpuobj *pushbuf; -+ struct nouveau_bo *pushbuf_bo; -+ uint32_t pushbuf_base; - - /* Notifier memory */ - struct nouveau_bo *notifier_bo; - struct drm_mm notifier_heap; - - /* PFIFO context */ -- struct nouveau_gpuobj_ref *ramfc; -- struct nouveau_gpuobj_ref *cache; -+ struct nouveau_gpuobj *ramfc; -+ struct nouveau_gpuobj *cache; - - /* PGRAPH context */ - /* XXX may be merge 2 pointers as private data ??? */ -- struct nouveau_gpuobj_ref *ramin_grctx; -+ struct nouveau_gpuobj *ramin_grctx; -+ struct nouveau_gpuobj *crypt_ctx; - void *pgraph_ctx; - - /* NV50 VM */ -- struct nouveau_gpuobj *vm_pd; -- struct nouveau_gpuobj_ref *vm_gart_pt; -- struct nouveau_gpuobj_ref *vm_vram_pt[NV50_VM_VRAM_NR]; -+ struct nouveau_gpuobj *vm_pd; -+ struct nouveau_gpuobj *vm_gart_pt; -+ struct nouveau_gpuobj *vm_vram_pt[NV50_VM_VRAM_NR]; - - /* Objects */ -- struct nouveau_gpuobj_ref *ramin; /* Private instmem */ -- struct drm_mm ramin_heap; /* Private PRAMIN heap */ -- struct nouveau_gpuobj_ref *ramht; /* Hash table */ -- struct list_head ramht_refs; /* Objects referenced by RAMHT */ -+ 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) */ - uint32_t m2mf_ntfy; -@@ -244,9 +265,11 @@ - - struct { - struct nouveau_gpuobj *vblsem; -+ uint32_t vblsem_head; - uint32_t vblsem_offset; - uint32_t vblsem_rval; - struct list_head vbl_wait; -+ struct list_head flip; - } nvsw; - - struct { -@@ -265,7 +288,7 @@ - void (*resume)(struct drm_device *dev); - - int (*populate)(struct drm_device *, struct nouveau_gpuobj *, -- uint32_t *size); -+ u32 *size, u32 align); - void (*clear)(struct drm_device *, struct nouveau_gpuobj *); - int (*bind)(struct drm_device *, struct nouveau_gpuobj *); - int (*unbind)(struct drm_device *, struct nouveau_gpuobj *); -@@ -285,18 +308,22 @@ - - struct nouveau_fb_engine { - int num_tiles; -+ struct drm_mm tag_heap; - - int (*init)(struct drm_device *dev); - void (*takedown)(struct drm_device *dev); - -- void (*set_region_tiling)(struct drm_device *dev, int i, uint32_t addr, -- uint32_t size, uint32_t pitch); -+ 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_fifo_engine { - int channels; - -- struct nouveau_gpuobj_ref *playlist[2]; -+ struct nouveau_gpuobj *playlist[2]; - int cur_playlist; - - int (*init)(struct drm_device *); -@@ -305,7 +332,6 @@ - void (*disable)(struct drm_device *); - void (*enable)(struct drm_device *); - bool (*reassign)(struct drm_device *, bool enable); -- bool (*cache_flush)(struct drm_device *dev); - bool (*cache_pull)(struct drm_device *dev, bool enable); - - int (*channel_id)(struct drm_device *); -@@ -314,27 +340,16 @@ - void (*destroy_context)(struct nouveau_channel *); - int (*load_context)(struct nouveau_channel *); - int (*unload_context)(struct drm_device *); --}; -- --struct nouveau_pgraph_object_method { -- int id; -- int (*exec)(struct nouveau_channel *chan, int grclass, int mthd, -- uint32_t data); --}; -- --struct nouveau_pgraph_object_class { -- int id; -- bool software; -- struct nouveau_pgraph_object_method *methods; -+ void (*tlb_flush)(struct drm_device *dev); - }; - - struct nouveau_pgraph_engine { -- struct nouveau_pgraph_object_class *grclass; - bool accel_blocked; -+ bool registered; - int grctx_size; - - /* NV2x/NV3x context table (0x400780) */ -- struct nouveau_gpuobj_ref *ctx_table; -+ struct nouveau_gpuobj *ctx_table; - - int (*init)(struct drm_device *); - void (*takedown)(struct drm_device *); -@@ -346,9 +361,9 @@ - void (*destroy_context)(struct nouveau_channel *); - int (*load_context)(struct nouveau_channel *); - int (*unload_context)(struct drm_device *); -+ void (*tlb_flush)(struct drm_device *dev); - -- void (*set_region_tiling)(struct drm_device *dev, int i, uint32_t addr, -- uint32_t size, uint32_t pitch); -+ void (*set_tile_region)(struct drm_device *dev, int i); - }; - - struct nouveau_display_engine { -@@ -369,6 +384,102 @@ - void (*irq_enable)(struct drm_device *, enum dcb_gpio_tag, bool on); - }; - -+struct nouveau_pm_voltage_level { -+ u8 voltage; -+ u8 vid; -+}; -+ -+struct nouveau_pm_voltage { -+ bool supported; -+ u8 vid_mask; -+ -+ struct nouveau_pm_voltage_level *level; -+ int nr_level; -+}; -+ -+#define NOUVEAU_PM_MAX_LEVEL 8 -+struct nouveau_pm_level { -+ struct device_attribute dev_attr; -+ char name[32]; -+ int id; -+ -+ u32 core; -+ u32 memory; -+ u32 shader; -+ u32 unk05; -+ -+ u8 voltage; -+ u8 fanspeed; -+ -+ u16 memscript; -+}; -+ -+struct nouveau_pm_temp_sensor_constants { -+ u16 offset_constant; -+ s16 offset_mult; -+ u16 offset_div; -+ u16 slope_mult; -+ u16 slope_div; -+}; -+ -+struct nouveau_pm_threshold_temp { -+ s16 critical; -+ s16 down_clock; -+ s16 fan_boost; -+}; -+ -+struct nouveau_pm_memtiming { -+ u32 reg_100220; -+ u32 reg_100224; -+ u32 reg_100228; -+ u32 reg_10022c; -+ u32 reg_100230; -+ u32 reg_100234; -+ u32 reg_100238; -+ u32 reg_10023c; -+}; -+ -+struct nouveau_pm_memtimings { -+ bool supported; -+ struct nouveau_pm_memtiming *timing; -+ int nr_timing; -+}; -+ -+struct nouveau_pm_engine { -+ struct nouveau_pm_voltage voltage; -+ struct nouveau_pm_level perflvl[NOUVEAU_PM_MAX_LEVEL]; -+ int nr_perflvl; -+ struct nouveau_pm_memtimings memtimings; -+ struct nouveau_pm_temp_sensor_constants sensor_constants; -+ struct nouveau_pm_threshold_temp threshold_temp; -+ -+ struct nouveau_pm_level boot; -+ struct nouveau_pm_level *cur; -+ -+ struct device *hwmon; -+ struct notifier_block acpi_nb; -+ -+ int (*clock_get)(struct drm_device *, u32 id); -+ void *(*clock_pre)(struct drm_device *, struct nouveau_pm_level *, -+ u32 id, int khz); -+ void (*clock_set)(struct drm_device *, void *); -+ int (*voltage_get)(struct drm_device *); -+ int (*voltage_set)(struct drm_device *, int voltage); -+ int (*fanspeed_get)(struct drm_device *); -+ int (*fanspeed_set)(struct drm_device *, int fanspeed); -+ int (*temp_get)(struct drm_device *); -+}; -+ -+struct nouveau_crypt_engine { -+ bool registered; -+ -+ int (*init)(struct drm_device *); -+ void (*takedown)(struct drm_device *); -+ int (*create_context)(struct nouveau_channel *); -+ void (*destroy_context)(struct nouveau_channel *); -+ void (*tlb_flush)(struct drm_device *dev); -+}; -+ - struct nouveau_engine { - struct nouveau_instmem_engine instmem; - struct nouveau_mc_engine mc; -@@ -378,6 +489,8 @@ - struct nouveau_fifo_engine fifo; - struct nouveau_display_engine display; - struct nouveau_gpio_engine gpio; -+ struct nouveau_pm_engine pm; -+ struct nouveau_crypt_engine crypt; - }; - - struct nouveau_pll_vals { -@@ -409,13 +522,13 @@ - }; - - struct nv04_crtc_reg { -- unsigned char MiscOutReg; /* */ -+ unsigned char MiscOutReg; - uint8_t CRTC[0xa0]; - uint8_t CR58[0x10]; - uint8_t Sequencer[5]; - uint8_t Graphics[9]; - uint8_t Attribute[21]; -- unsigned char DAC[768]; /* Internal Colorlookuptable */ -+ unsigned char DAC[768]; - - /* PCRTC regs */ - uint32_t fb_start; -@@ -463,43 +576,9 @@ - }; - - struct nv04_mode_state { -- uint32_t bpp; -- uint32_t width; -- uint32_t height; -- uint32_t interlace; -- uint32_t repaint0; -- uint32_t repaint1; -- uint32_t screen; -- uint32_t scale; -- uint32_t dither; -- uint32_t extra; -- uint32_t fifo; -- uint32_t pixel; -- uint32_t horiz; -- int arbitration0; -- int arbitration1; -- uint32_t pll; -- uint32_t pllB; -- uint32_t vpll; -- uint32_t vpll2; -- uint32_t vpllB; -- uint32_t vpll2B; -+ struct nv04_crtc_reg crtc_reg[2]; - uint32_t pllsel; - uint32_t sel_clk; -- uint32_t general; -- uint32_t crtcOwner; -- uint32_t head; -- uint32_t head2; -- uint32_t cursorConfig; -- uint32_t cursor0; -- uint32_t cursor1; -- uint32_t cursor2; -- uint32_t timingH; -- uint32_t timingV; -- uint32_t displayV; -- uint32_t crtcSync; -- -- struct nv04_crtc_reg crtc_reg[2]; - }; - - enum nouveau_card_type { -@@ -522,11 +601,20 @@ - int flags; - - void __iomem *mmio; -+ -+ spinlock_t ramin_lock; - void __iomem *ramin; -- uint32_t ramin_size; -+ u32 ramin_size; -+ u32 ramin_base; -+ bool ramin_available; -+ struct drm_mm ramin_heap; -+ struct list_head gpuobj_list; -+ struct list_head classes; - - struct nouveau_bo *vga_ram; - -+ /* interrupt handling */ -+ bool msi_enabled; - struct workqueue_struct *wq; - struct work_struct irq_work; - struct work_struct hpd_work; -@@ -540,8 +628,16 @@ - atomic_t validate_sequence; - } ttm; - -- int fifo_alloc_count; -- struct nouveau_channel *fifos[NOUVEAU_MAX_CHANNEL_NR]; -+ struct { -+ 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; -@@ -550,15 +646,11 @@ - spinlock_t context_switch_lock; - - /* RAMIN configuration, RAMFC, RAMHT and RAMRO offsets */ -- struct nouveau_gpuobj *ramht; -+ struct nouveau_ramht *ramht; -+ struct nouveau_gpuobj *ramfc; -+ struct nouveau_gpuobj *ramro; -+ - uint32_t ramin_rsvd_vram; -- uint32_t ramht_offset; -- uint32_t ramht_size; -- uint32_t ramht_bits; -- uint32_t ramfc_offset; -- uint32_t ramfc_size; -- uint32_t ramro_offset; -- uint32_t ramro_size; - - struct { - enum { -@@ -584,6 +676,7 @@ - /* VRAM/fb configuration */ - uint64_t vram_size; - uint64_t vram_sys_base; -+ u32 vram_rblock_size; - - uint64_t fb_phys; - uint64_t fb_available_size; -@@ -600,10 +693,6 @@ - struct nouveau_gpuobj *vm_vram_pt[NV50_VM_VRAM_NR]; - int vm_vram_pt_nr; - -- struct drm_mm ramin_heap; -- -- struct list_head gpuobj_list; -- - struct nvbios vbios; - - struct nv04_mode_state mode_reg; -@@ -619,6 +708,7 @@ - struct backlight_device *backlight; - - struct nouveau_channel *evo; -+ u32 evo_alloc; - struct { - struct dcb_entry *dcb; - u16 script; -@@ -634,6 +724,12 @@ - }; - - static inline struct drm_nouveau_private * -+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); -@@ -658,18 +754,8 @@ - return 0; - } - --#define NOUVEAU_GET_USER_CHANNEL_WITH_RETURN(id, cl, ch) do { \ -- struct drm_nouveau_private *nv = dev->dev_private; \ -- if (!nouveau_channel_owner(dev, (cl), (id))) { \ -- NV_ERROR(dev, "pid %d doesn't own channel %d\n", \ -- DRM_CURRENTPID, (id)); \ -- return -EPERM; \ -- } \ -- (ch) = nv->fifos[(id)]; \ --} while (0) -- - /* nouveau_drv.c */ --extern int nouveau_noagp; -+extern int nouveau_agpmode; - extern int nouveau_duallink; - extern int nouveau_uscript_lvds; - extern int nouveau_uscript_tmds; -@@ -683,7 +769,11 @@ - extern int nouveau_ignorelid; - extern int nouveau_nofbaccel; - extern int nouveau_noaccel; -+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_pci_suspend(struct pci_dev *pdev, pm_message_t pm_state); - extern int nouveau_pci_resume(struct pci_dev *pdev); -@@ -704,18 +794,19 @@ - extern int nouveau_card_init(struct drm_device *); - - /* nouveau_mem.c */ --extern int nouveau_mem_detect(struct drm_device *dev); --extern int nouveau_mem_init(struct drm_device *); -+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 struct nouveau_tile_reg *nv10_mem_set_tiling(struct drm_device *dev, -- uint32_t addr, -- uint32_t size, -- uint32_t pitch); --extern void nv10_mem_expire_tiling(struct drm_device *dev, -- struct nouveau_tile_reg *tile, -- struct nouveau_fence *fence); -+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 nv50_mem_vm_bind_linear(struct drm_device *, uint64_t virt, - uint32_t size, uint32_t flags, - uint64_t phys); -@@ -737,46 +828,54 @@ - extern struct drm_ioctl_desc nouveau_ioctls[]; - extern int nouveau_max_ioctl; - extern void nouveau_channel_cleanup(struct drm_device *, struct drm_file *); --extern int nouveau_channel_owner(struct drm_device *, struct drm_file *, -- int channel); - 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 void nouveau_channel_free(struct nouveau_channel *); -+extern struct nouveau_channel * -+nouveau_channel_get_unlocked(struct nouveau_channel *); -+extern struct nouveau_channel * -+nouveau_channel_get(struct drm_device *, 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); - - /* nouveau_object.c */ -+#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_early_init(struct drm_device *); - extern int nouveau_gpuobj_init(struct drm_device *); - extern void nouveau_gpuobj_takedown(struct drm_device *); --extern void nouveau_gpuobj_late_takedown(struct drm_device *); - extern int nouveau_gpuobj_suspend(struct drm_device *dev); - extern void nouveau_gpuobj_suspend_cleanup(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 *, -+ u32 class, u32 mthd, u32 data)); -+extern int nouveau_gpuobj_mthd_call(struct nouveau_channel *, 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 int nouveau_gpuobj_del(struct drm_device *, struct nouveau_gpuobj **); --extern int nouveau_gpuobj_ref_add(struct drm_device *, struct nouveau_channel *, -- uint32_t handle, struct nouveau_gpuobj *, -- struct nouveau_gpuobj_ref **); --extern int nouveau_gpuobj_ref_del(struct drm_device *, -- struct nouveau_gpuobj_ref **); --extern int nouveau_gpuobj_ref_find(struct nouveau_channel *, uint32_t handle, -- struct nouveau_gpuobj_ref **ref_ret); --extern int nouveau_gpuobj_new_ref(struct drm_device *, -- struct nouveau_channel *alloc_chan, -- struct nouveau_channel *ref_chan, -- uint32_t handle, uint32_t size, int align, -- uint32_t flags, struct nouveau_gpuobj_ref **); --extern int nouveau_gpuobj_new_fake(struct drm_device *, -- uint32_t p_offset, uint32_t b_offset, -- uint32_t size, uint32_t flags, -- struct nouveau_gpuobj **, -- struct nouveau_gpuobj_ref**); -+extern void nouveau_gpuobj_ref(struct nouveau_gpuobj *, -+ struct nouveau_gpuobj **); -+extern int nouveau_gpuobj_new_fake(struct drm_device *, u32 pinst, u64 vinst, -+ u32 size, u32 flags, -+ 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 **); -@@ -786,14 +885,14 @@ - uint32_t *o_ret); - extern int nouveau_gpuobj_gr_new(struct nouveau_channel *, int class, - struct nouveau_gpuobj **); --extern int nouveau_gpuobj_sw_new(struct nouveau_channel *, int class, -- struct nouveau_gpuobj **); - extern int nouveau_ioctl_grobj_alloc(struct drm_device *, void *data, - struct drm_file *); - extern int nouveau_ioctl_gpuobj_free(struct drm_device *, void *data, - struct drm_file *); - - /* 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_preinstall(struct drm_device *); - extern int nouveau_irq_postinstall(struct drm_device *); -@@ -879,6 +978,7 @@ - enum dcb_gpio_tag); - extern struct dcb_connector_table_entry * - nouveau_bios_connector_entry(struct drm_device *, int index); -+extern u32 get_pll_register(struct drm_device *, enum pll_types); - extern int get_pll_limits(struct drm_device *, uint32_t limit_match, - struct pll_lims *); - extern int nouveau_bios_run_display_table(struct drm_device *, -@@ -913,18 +1013,29 @@ - /* nv10_fb.c */ - extern int nv10_fb_init(struct drm_device *); - extern void nv10_fb_takedown(struct drm_device *); --extern void nv10_fb_set_region_tiling(struct drm_device *, int, uint32_t, -- uint32_t, uint32_t); -+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); - - /* 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_init(struct drm_device *); - extern void nv40_fb_takedown(struct drm_device *); --extern void nv40_fb_set_region_tiling(struct drm_device *, int, uint32_t, -- uint32_t, uint32_t); -+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, const char *); - - /* nv50_fb.c */ - extern int nv50_fb_init(struct drm_device *); -@@ -939,7 +1050,6 @@ - extern void nv04_fifo_disable(struct drm_device *); - extern void nv04_fifo_enable(struct drm_device *); - extern bool nv04_fifo_reassign(struct drm_device *, bool); --extern bool nv04_fifo_cache_flush(struct drm_device *); - extern bool nv04_fifo_cache_pull(struct drm_device *, bool); - extern int nv04_fifo_channel_id(struct drm_device *); - extern int nv04_fifo_create_context(struct nouveau_channel *); -@@ -951,14 +1061,12 @@ - extern int nv10_fifo_init(struct drm_device *); - extern int nv10_fifo_channel_id(struct drm_device *); - extern int nv10_fifo_create_context(struct nouveau_channel *); --extern void nv10_fifo_destroy_context(struct nouveau_channel *); - extern int nv10_fifo_load_context(struct nouveau_channel *); - extern int nv10_fifo_unload_context(struct drm_device *); - - /* nv40_fifo.c */ - extern int nv40_fifo_init(struct drm_device *); - extern int nv40_fifo_create_context(struct nouveau_channel *); --extern void nv40_fifo_destroy_context(struct nouveau_channel *); - extern int nv40_fifo_load_context(struct nouveau_channel *); - extern int nv40_fifo_unload_context(struct drm_device *); - -@@ -970,6 +1078,7 @@ - extern void nv50_fifo_destroy_context(struct nouveau_channel *); - extern int nv50_fifo_load_context(struct nouveau_channel *); - extern int nv50_fifo_unload_context(struct drm_device *); -+extern void nv50_fifo_tlb_flush(struct drm_device *dev); - - /* nvc0_fifo.c */ - extern int nvc0_fifo_init(struct drm_device *); -@@ -977,7 +1086,6 @@ - extern void nvc0_fifo_disable(struct drm_device *); - extern void nvc0_fifo_enable(struct drm_device *); - extern bool nvc0_fifo_reassign(struct drm_device *, bool); --extern bool nvc0_fifo_cache_flush(struct drm_device *); - extern bool nvc0_fifo_cache_pull(struct drm_device *, bool); - extern int nvc0_fifo_channel_id(struct drm_device *); - extern int nvc0_fifo_create_context(struct nouveau_channel *); -@@ -986,7 +1094,6 @@ - extern int nvc0_fifo_unload_context(struct drm_device *); - - /* nv04_graph.c */ --extern struct nouveau_pgraph_object_class nv04_graph_grclass[]; - extern int nv04_graph_init(struct drm_device *); - extern void nv04_graph_takedown(struct drm_device *); - extern void nv04_graph_fifo_access(struct drm_device *, bool); -@@ -996,9 +1103,10 @@ - extern int nv04_graph_load_context(struct nouveau_channel *); - extern int nv04_graph_unload_context(struct drm_device *); - extern void nv04_graph_context_switch(struct drm_device *); -+extern int nv04_graph_mthd_page_flip(struct nouveau_channel *chan, -+ u32 class, u32 mthd, u32 data); - - /* nv10_graph.c */ --extern struct nouveau_pgraph_object_class nv10_graph_grclass[]; - extern int nv10_graph_init(struct drm_device *); - extern void nv10_graph_takedown(struct drm_device *); - extern struct nouveau_channel *nv10_graph_channel(struct drm_device *); -@@ -1007,12 +1115,9 @@ - extern int nv10_graph_load_context(struct nouveau_channel *); - extern int nv10_graph_unload_context(struct drm_device *); - extern void nv10_graph_context_switch(struct drm_device *); --extern void nv10_graph_set_region_tiling(struct drm_device *, int, uint32_t, -- uint32_t, uint32_t); -+extern void nv10_graph_set_tile_region(struct drm_device *dev, int i); - - /* nv20_graph.c */ --extern struct nouveau_pgraph_object_class nv20_graph_grclass[]; --extern struct nouveau_pgraph_object_class nv30_graph_grclass[]; - extern int nv20_graph_create_context(struct nouveau_channel *); - extern void nv20_graph_destroy_context(struct nouveau_channel *); - extern int nv20_graph_load_context(struct nouveau_channel *); -@@ -1020,11 +1125,9 @@ - extern int nv20_graph_init(struct drm_device *); - extern void nv20_graph_takedown(struct drm_device *); - extern int nv30_graph_init(struct drm_device *); --extern void nv20_graph_set_region_tiling(struct drm_device *, int, uint32_t, -- uint32_t, uint32_t); -+extern void nv20_graph_set_tile_region(struct drm_device *dev, int i); - - /* nv40_graph.c */ --extern struct nouveau_pgraph_object_class nv40_graph_grclass[]; - extern int nv40_graph_init(struct drm_device *); - extern void nv40_graph_takedown(struct drm_device *); - extern struct nouveau_channel *nv40_graph_channel(struct drm_device *); -@@ -1033,11 +1136,9 @@ - extern int nv40_graph_load_context(struct nouveau_channel *); - extern int nv40_graph_unload_context(struct drm_device *); - extern void nv40_grctx_init(struct nouveau_grctx *); --extern void nv40_graph_set_region_tiling(struct drm_device *, int, uint32_t, -- uint32_t, uint32_t); -+extern void nv40_graph_set_tile_region(struct drm_device *dev, int i); - - /* nv50_graph.c */ --extern struct nouveau_pgraph_object_class nv50_graph_grclass[]; - extern int nv50_graph_init(struct drm_device *); - extern void nv50_graph_takedown(struct drm_device *); - extern void nv50_graph_fifo_access(struct drm_device *, bool); -@@ -1048,6 +1149,8 @@ - extern int nv50_graph_unload_context(struct drm_device *); - extern void nv50_graph_context_switch(struct drm_device *); - extern int nv50_grctx_init(struct nouveau_grctx *); -+extern void nv50_graph_tlb_flush(struct drm_device *dev); -+extern void nv86_graph_tlb_flush(struct drm_device *dev); - - /* nvc0_graph.c */ - extern int nvc0_graph_init(struct drm_device *); -@@ -1059,13 +1162,20 @@ - extern int nvc0_graph_load_context(struct nouveau_channel *); - extern int nvc0_graph_unload_context(struct drm_device *); - -+/* nv84_crypt.c */ -+extern int nv84_crypt_init(struct drm_device *dev); -+extern void nv84_crypt_fini(struct drm_device *dev); -+extern int nv84_crypt_create_context(struct nouveau_channel *); -+extern void nv84_crypt_destroy_context(struct nouveau_channel *); -+extern void nv84_crypt_tlb_flush(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_populate(struct drm_device *, struct nouveau_gpuobj *, -- uint32_t *size); -+ u32 *size, u32 align); - extern void nv04_instmem_clear(struct drm_device *, struct nouveau_gpuobj *); - extern int nv04_instmem_bind(struct drm_device *, struct nouveau_gpuobj *); - extern int nv04_instmem_unbind(struct drm_device *, struct nouveau_gpuobj *); -@@ -1077,7 +1187,7 @@ - extern int nv50_instmem_suspend(struct drm_device *); - extern void nv50_instmem_resume(struct drm_device *); - extern int nv50_instmem_populate(struct drm_device *, struct nouveau_gpuobj *, -- uint32_t *size); -+ u32 *size, u32 align); - extern void nv50_instmem_clear(struct drm_device *, struct nouveau_gpuobj *); - extern int nv50_instmem_bind(struct drm_device *, struct nouveau_gpuobj *); - extern int nv50_instmem_unbind(struct drm_device *, struct nouveau_gpuobj *); -@@ -1091,7 +1201,7 @@ - extern int nvc0_instmem_suspend(struct drm_device *); - extern void nvc0_instmem_resume(struct drm_device *); - extern int nvc0_instmem_populate(struct drm_device *, struct nouveau_gpuobj *, -- uint32_t *size); -+ u32 *size, u32 align); - extern void nvc0_instmem_clear(struct drm_device *, struct nouveau_gpuobj *); - extern int nvc0_instmem_bind(struct drm_device *, struct nouveau_gpuobj *); - extern int nvc0_instmem_unbind(struct drm_device *, struct nouveau_gpuobj *); -@@ -1165,22 +1275,51 @@ - extern void nouveau_bo_wr16(struct nouveau_bo *nvbo, unsigned index, u16 val); - extern u32 nouveau_bo_rd32(struct nouveau_bo *nvbo, unsigned index); - extern void nouveau_bo_wr32(struct nouveau_bo *nvbo, unsigned index, u32 val); --extern int nouveau_bo_sync_gpu(struct nouveau_bo *, struct nouveau_channel *); -+extern void nouveau_bo_fence(struct nouveau_bo *, struct nouveau_fence *); - - /* nouveau_fence.c */ - struct nouveau_fence; --extern int nouveau_fence_init(struct nouveau_channel *); --extern void nouveau_fence_fini(struct nouveau_channel *); -+extern int nouveau_fence_init(struct drm_device *); -+extern void nouveau_fence_fini(struct drm_device *); -+extern int nouveau_fence_channel_init(struct nouveau_channel *); -+extern void nouveau_fence_channel_fini(struct nouveau_channel *); - extern void nouveau_fence_update(struct nouveau_channel *); - extern int nouveau_fence_new(struct nouveau_channel *, struct nouveau_fence **, - bool emit); - extern int nouveau_fence_emit(struct nouveau_fence *); -+extern void nouveau_fence_work(struct nouveau_fence *fence, -+ void (*work)(void *priv, bool signalled), -+ void *priv); - struct nouveau_channel *nouveau_fence_channel(struct nouveau_fence *); --extern bool nouveau_fence_signalled(void *obj, void *arg); --extern int nouveau_fence_wait(void *obj, void *arg, bool lazy, bool intr); --extern int nouveau_fence_flush(void *obj, void *arg); --extern void nouveau_fence_unref(void **obj); --extern void *nouveau_fence_ref(void *obj); -+ -+extern bool __nouveau_fence_signalled(void *obj, void *arg); -+extern int __nouveau_fence_wait(void *obj, void *arg, bool lazy, bool intr); -+extern int __nouveau_fence_flush(void *obj, void *arg); -+extern void __nouveau_fence_unref(void **obj); -+extern void *__nouveau_fence_ref(void *obj); -+ -+static inline bool nouveau_fence_signalled(struct nouveau_fence *obj) -+{ -+ return __nouveau_fence_signalled(obj, NULL); -+} -+static inline int -+nouveau_fence_wait(struct nouveau_fence *obj, bool lazy, bool intr) -+{ -+ return __nouveau_fence_wait(obj, NULL, lazy, intr); -+} -+extern int nouveau_fence_sync(struct nouveau_fence *, struct nouveau_channel *); -+static inline int nouveau_fence_flush(struct nouveau_fence *obj) -+{ -+ return __nouveau_fence_flush(obj, NULL); -+} -+static inline void nouveau_fence_unref(struct nouveau_fence **obj) -+{ -+ __nouveau_fence_unref((void **)obj); -+} -+static inline struct nouveau_fence *nouveau_fence_ref(struct nouveau_fence *obj) -+{ -+ return __nouveau_fence_ref(obj); -+} - - /* nouveau_gem.c */ - extern int nouveau_gem_new(struct drm_device *, struct nouveau_channel *, -@@ -1200,6 +1339,14 @@ - extern int nouveau_gem_ioctl_info(struct drm_device *, void *, - struct drm_file *); - -+/* nouveau_display.c */ -+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 *); -+ - /* nv10_gpio.c */ - int nv10_gpio_get(struct drm_device *dev, enum dcb_gpio_tag tag); - int nv10_gpio_set(struct drm_device *dev, enum dcb_gpio_tag tag, int state); -@@ -1255,12 +1402,11 @@ - iowrite32_native(val, dev_priv->mmio + reg); - } - --static inline void nv_mask(struct drm_device *dev, u32 reg, u32 mask, u32 val) -+static inline u32 nv_mask(struct drm_device *dev, u32 reg, u32 mask, u32 val) - { - u32 tmp = nv_rd32(dev, reg); -- tmp &= ~mask; -- tmp |= val; -- nv_wr32(dev, reg, tmp); -+ nv_wr32(dev, reg, (tmp & ~mask) | val); -+ return tmp; - } - - static inline u8 nv_rd08(struct drm_device *dev, unsigned reg) -@@ -1275,7 +1421,7 @@ - iowrite8(val, dev_priv->mmio + reg); - } - --#define nv_wait(reg, mask, val) \ -+#define nv_wait(dev, reg, mask, val) \ - nouveau_wait_until(dev, 2000000000ULL, (reg), (mask), (val)) - - /* PRAMIN access */ -@@ -1292,17 +1438,8 @@ - } - - /* object access */ --static inline u32 nv_ro32(struct drm_device *dev, struct nouveau_gpuobj *obj, -- unsigned index) --{ -- return nv_ri32(dev, obj->im_pramin->start + index * 4); --} -- --static inline void nv_wo32(struct drm_device *dev, struct nouveau_gpuobj *obj, -- unsigned index, u32 val) --{ -- nv_wi32(dev, obj->im_pramin->start + index * 4, val); --} -+extern u32 nv_ro32(struct nouveau_gpuobj *, u32 offset); -+extern void nv_wo32(struct nouveau_gpuobj *, u32 offset, u32 val); - - /* - * Logging -@@ -1403,9 +1540,11 @@ - #define NV_SW_SEMAPHORE_OFFSET 0x00000064 - #define NV_SW_SEMAPHORE_ACQUIRE 0x00000068 - #define NV_SW_SEMAPHORE_RELEASE 0x0000006c -+#define NV_SW_YIELD 0x00000080 - #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 -Naur linux-2.6.36/drivers/gpu/drm/nouveau/nouveau_encoder.h linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nouveau_encoder.h ---- linux-2.6.36/drivers/gpu/drm/nouveau/nouveau_encoder.h 2010-10-20 22:30:22.000000000 +0200 -+++ linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nouveau_encoder.h 2010-11-05 00:40:00.000000000 +0100 -@@ -55,6 +55,7 @@ - int dpcd_version; - int link_nr; - int link_bw; -+ bool enhanced_frame; - } dp; - }; - }; -diff -Naur linux-2.6.36/drivers/gpu/drm/nouveau/nouveau_fbcon.c linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nouveau_fbcon.c ---- linux-2.6.36/drivers/gpu/drm/nouveau/nouveau_fbcon.c 2010-10-20 22:30:22.000000000 +0200 -+++ linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nouveau_fbcon.c 2010-11-05 00:40:00.000000000 +0100 -@@ -49,6 +49,96 @@ - #include "nouveau_fbcon.h" - #include "nouveau_dma.h" - -+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; -+ int ret; -+ -+ if (info->state != FBINFO_STATE_RUNNING) -+ return; -+ -+ ret = -ENODEV; -+ if (!in_interrupt() && !(info->flags & FBINFO_HWACCEL_DISABLED) && -+ mutex_trylock(&dev_priv->channel->mutex)) { -+ if (dev_priv->chipset < NV_50) -+ ret = nv04_fbcon_fillrect(info, rect); -+ else -+ if (dev_priv->chipset < NV_C0) -+ ret = nv50_fbcon_fillrect(info, rect); -+ mutex_unlock(&dev_priv->channel->mutex); -+ } -+ -+ if (ret == 0) -+ return; -+ -+ if (ret != -ENODEV) -+ nouveau_fbcon_gpu_lockup(info); -+ cfb_fillrect(info, 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; -+ int ret; -+ -+ if (info->state != FBINFO_STATE_RUNNING) -+ return; -+ -+ ret = -ENODEV; -+ if (!in_interrupt() && !(info->flags & FBINFO_HWACCEL_DISABLED) && -+ mutex_trylock(&dev_priv->channel->mutex)) { -+ if (dev_priv->chipset < NV_50) -+ ret = nv04_fbcon_copyarea(info, image); -+ else -+ if (dev_priv->chipset < NV_C0) -+ ret = nv50_fbcon_copyarea(info, image); -+ mutex_unlock(&dev_priv->channel->mutex); -+ } -+ -+ if (ret == 0) -+ return; -+ -+ if (ret != -ENODEV) -+ nouveau_fbcon_gpu_lockup(info); -+ cfb_copyarea(info, 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; -+ int ret; -+ -+ if (info->state != FBINFO_STATE_RUNNING) -+ return; -+ -+ ret = -ENODEV; -+ if (!in_interrupt() && !(info->flags & FBINFO_HWACCEL_DISABLED) && -+ mutex_trylock(&dev_priv->channel->mutex)) { -+ if (dev_priv->chipset < NV_50) -+ ret = nv04_fbcon_imageblit(info, image); -+ else -+ if (dev_priv->chipset < NV_C0) -+ ret = nv50_fbcon_imageblit(info, image); -+ mutex_unlock(&dev_priv->channel->mutex); -+ } -+ -+ if (ret == 0) -+ return; -+ -+ if (ret != -ENODEV) -+ nouveau_fbcon_gpu_lockup(info); -+ cfb_imageblit(info, image); -+} -+ - static int - nouveau_fbcon_sync(struct fb_info *info) - { -@@ -58,12 +148,17 @@ - struct nouveau_channel *chan = dev_priv->channel; - int ret, i; - -- if (!chan || !chan->accel_done || -+ if (!chan || !chan->accel_done || in_interrupt() || - info->state != FBINFO_STATE_RUNNING || - info->flags & FBINFO_HWACCEL_DISABLED) - return 0; - -- if (RING_SPACE(chan, 4)) { -+ if (!mutex_trylock(&chan->mutex)) -+ return 0; -+ -+ ret = RING_SPACE(chan, 4); -+ if (ret) { -+ mutex_unlock(&chan->mutex); - nouveau_fbcon_gpu_lockup(info); - return 0; - } -@@ -74,6 +169,7 @@ - OUT_RING(chan, 0); - nouveau_bo_wr32(chan->notifier_bo, chan->m2mf_ntfy + 3, 0xffffffff); - FIRE_RING(chan); -+ mutex_unlock(&chan->mutex); - - ret = -EBUSY; - for (i = 0; i < 100000; i++) { -@@ -97,36 +193,22 @@ - .owner = THIS_MODULE, - .fb_check_var = drm_fb_helper_check_var, - .fb_set_par = drm_fb_helper_set_par, -- .fb_fillrect = cfb_fillrect, -- .fb_copyarea = cfb_copyarea, -- .fb_imageblit = cfb_imageblit, -+ .fb_fillrect = nouveau_fbcon_fillrect, -+ .fb_copyarea = nouveau_fbcon_copyarea, -+ .fb_imageblit = nouveau_fbcon_imageblit, - .fb_sync = nouveau_fbcon_sync, - .fb_pan_display = drm_fb_helper_pan_display, - .fb_blank = drm_fb_helper_blank, - .fb_setcmap = drm_fb_helper_setcmap, - }; - --static struct fb_ops nv04_fbcon_ops = { -+static struct fb_ops nouveau_fbcon_sw_ops = { - .owner = THIS_MODULE, - .fb_check_var = drm_fb_helper_check_var, - .fb_set_par = drm_fb_helper_set_par, -- .fb_fillrect = nv04_fbcon_fillrect, -- .fb_copyarea = nv04_fbcon_copyarea, -- .fb_imageblit = nv04_fbcon_imageblit, -- .fb_sync = nouveau_fbcon_sync, -- .fb_pan_display = drm_fb_helper_pan_display, -- .fb_blank = drm_fb_helper_blank, -- .fb_setcmap = drm_fb_helper_setcmap, --}; -- --static struct fb_ops nv50_fbcon_ops = { -- .owner = THIS_MODULE, -- .fb_check_var = drm_fb_helper_check_var, -- .fb_set_par = drm_fb_helper_set_par, -- .fb_fillrect = nv50_fbcon_fillrect, -- .fb_copyarea = nv50_fbcon_copyarea, -- .fb_imageblit = nv50_fbcon_imageblit, -- .fb_sync = nouveau_fbcon_sync, -+ .fb_fillrect = cfb_fillrect, -+ .fb_copyarea = cfb_copyarea, -+ .fb_imageblit = cfb_imageblit, - .fb_pan_display = drm_fb_helper_pan_display, - .fb_blank = drm_fb_helper_blank, - .fb_setcmap = drm_fb_helper_setcmap, -@@ -251,7 +333,7 @@ - FBINFO_HWACCEL_FILLRECT | - FBINFO_HWACCEL_IMAGEBLIT; - info->flags |= FBINFO_CAN_FORCE_OUTPUT; -- info->fbops = &nouveau_fbcon_ops; -+ info->fbops = &nouveau_fbcon_sw_ops; - info->fix.smem_start = dev->mode_config.fb_base + nvbo->bo.offset - - dev_priv->vm_vram_base; - info->fix.smem_len = size; -@@ -279,19 +361,18 @@ - info->pixmap.flags = FB_PIXMAP_SYSTEM; - info->pixmap.scan_align = 1; - -+ mutex_unlock(&dev->struct_mutex); -+ - if (dev_priv->channel && !nouveau_nofbaccel) { -- switch (dev_priv->card_type) { -- case NV_C0: -- break; -- case NV_50: -- nv50_fbcon_accel_init(info); -- info->fbops = &nv50_fbcon_ops; -- break; -- default: -- nv04_fbcon_accel_init(info); -- info->fbops = &nv04_fbcon_ops; -- break; -- }; -+ ret = -ENODEV; -+ if (dev_priv->card_type < NV_50) -+ ret = nv04_fbcon_accel_init(info); -+ else -+ if (dev_priv->card_type < NV_C0) -+ ret = nv50_fbcon_accel_init(info); -+ -+ if (ret == 0) -+ info->fbops = &nouveau_fbcon_ops; - } - - nouveau_fbcon_zfill(dev, nfbdev); -@@ -302,7 +383,6 @@ - nouveau_fb->base.height, - nvbo->bo.offset, nvbo); - -- mutex_unlock(&dev->struct_mutex); - vga_switcheroo_client_fb_set(dev->pdev, info); - return 0; - -diff -Naur linux-2.6.36/drivers/gpu/drm/nouveau/nouveau_fbcon.h linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nouveau_fbcon.h ---- linux-2.6.36/drivers/gpu/drm/nouveau/nouveau_fbcon.h 2010-10-20 22:30:22.000000000 +0200 -+++ linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nouveau_fbcon.h 2010-11-05 00:40:00.000000000 +0100 -@@ -40,13 +40,13 @@ - - void nouveau_fbcon_restore(void); - --void nv04_fbcon_copyarea(struct fb_info *info, const struct fb_copyarea *region); --void nv04_fbcon_fillrect(struct fb_info *info, const struct fb_fillrect *rect); --void nv04_fbcon_imageblit(struct fb_info *info, const struct fb_image *image); -+int nv04_fbcon_copyarea(struct fb_info *info, const struct fb_copyarea *region); -+int nv04_fbcon_fillrect(struct fb_info *info, const struct fb_fillrect *rect); -+int nv04_fbcon_imageblit(struct fb_info *info, const struct fb_image *image); - int nv04_fbcon_accel_init(struct fb_info *info); --void nv50_fbcon_fillrect(struct fb_info *info, const struct fb_fillrect *rect); --void nv50_fbcon_copyarea(struct fb_info *info, const struct fb_copyarea *region); --void nv50_fbcon_imageblit(struct fb_info *info, const struct fb_image *image); -+int nv50_fbcon_fillrect(struct fb_info *info, const struct fb_fillrect *rect); -+int nv50_fbcon_copyarea(struct fb_info *info, const struct fb_copyarea *region); -+int nv50_fbcon_imageblit(struct fb_info *info, const struct fb_image *image); - int nv50_fbcon_accel_init(struct fb_info *info); - - void nouveau_fbcon_gpu_lockup(struct fb_info *info); -diff -Naur linux-2.6.36/drivers/gpu/drm/nouveau/nouveau_fence.c linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nouveau_fence.c ---- linux-2.6.36/drivers/gpu/drm/nouveau/nouveau_fence.c 2010-10-20 22:30:22.000000000 +0200 -+++ linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nouveau_fence.c 2010-11-05 00:40:00.000000000 +0100 -@@ -28,9 +28,11 @@ - #include "drm.h" - - #include "nouveau_drv.h" -+#include "nouveau_ramht.h" - #include "nouveau_dma.h" - --#define USE_REFCNT (dev_priv->card_type >= NV_10) -+#define USE_REFCNT(dev) (nouveau_private(dev)->chipset >= 0x10) -+#define USE_SEMA(dev) (nouveau_private(dev)->chipset >= 0x17) - - struct nouveau_fence { - struct nouveau_channel *channel; -@@ -39,6 +41,15 @@ - - uint32_t sequence; - bool signalled; -+ -+ void (*work)(void *priv, bool signalled); -+ void *priv; -+}; -+ -+struct nouveau_semaphore { -+ struct kref ref; -+ struct drm_device *dev; -+ struct drm_mm_node *mem; - }; - - static inline struct nouveau_fence * -@@ -53,20 +64,20 @@ - struct nouveau_fence *fence = - container_of(ref, struct nouveau_fence, refcount); - -+ nouveau_channel_ref(NULL, &fence->channel); - kfree(fence); - } - - void - nouveau_fence_update(struct nouveau_channel *chan) - { -- struct drm_nouveau_private *dev_priv = chan->dev->dev_private; -- struct list_head *entry, *tmp; -- struct nouveau_fence *fence; -+ struct drm_device *dev = chan->dev; -+ struct nouveau_fence *tmp, *fence; - uint32_t sequence; - - spin_lock(&chan->fence.lock); - -- if (USE_REFCNT) -+ if (USE_REFCNT(dev)) - sequence = nvchan_rd32(chan, 0x48); - else - sequence = atomic_read(&chan->fence.last_sequence_irq); -@@ -75,12 +86,14 @@ - goto out; - chan->fence.sequence_ack = sequence; - -- list_for_each_safe(entry, tmp, &chan->fence.pending) { -- fence = list_entry(entry, struct nouveau_fence, entry); -- -+ list_for_each_entry_safe(fence, tmp, &chan->fence.pending, entry) { - sequence = fence->sequence; - fence->signalled = true; - list_del(&fence->entry); -+ -+ if (unlikely(fence->work)) -+ fence->work(fence->priv, true); -+ - kref_put(&fence->refcount, nouveau_fence_del); - - if (sequence == chan->fence.sequence_ack) -@@ -101,13 +114,13 @@ - if (!fence) - return -ENOMEM; - kref_init(&fence->refcount); -- fence->channel = chan; -+ nouveau_channel_ref(chan, &fence->channel); - - if (emit) - ret = nouveau_fence_emit(fence); - - if (ret) -- nouveau_fence_unref((void *)&fence); -+ nouveau_fence_unref(&fence); - *pfence = fence; - return ret; - } -@@ -115,14 +128,14 @@ - struct nouveau_channel * - nouveau_fence_channel(struct nouveau_fence *fence) - { -- return fence ? fence->channel : NULL; -+ return fence ? nouveau_channel_get_unlocked(fence->channel) : NULL; - } - - int - nouveau_fence_emit(struct nouveau_fence *fence) - { -- struct drm_nouveau_private *dev_priv = fence->channel->dev->dev_private; - struct nouveau_channel *chan = fence->channel; -+ struct drm_device *dev = chan->dev; - int ret; - - ret = RING_SPACE(chan, 2); -@@ -143,7 +156,7 @@ - list_add_tail(&fence->entry, &chan->fence.pending); - spin_unlock(&chan->fence.lock); - -- BEGIN_RING(chan, NvSubSw, USE_REFCNT ? 0x0050 : 0x0150, 1); -+ BEGIN_RING(chan, NvSubSw, USE_REFCNT(dev) ? 0x0050 : 0x0150, 1); - OUT_RING(chan, fence->sequence); - FIRE_RING(chan); - -@@ -151,7 +164,26 @@ - } - - void --nouveau_fence_unref(void **sync_obj) -+nouveau_fence_work(struct nouveau_fence *fence, -+ void (*work)(void *priv, bool signalled), -+ void *priv) -+{ -+ BUG_ON(fence->work); -+ -+ spin_lock(&fence->channel->fence.lock); -+ -+ if (fence->signalled) { -+ work(priv, true); -+ } else { -+ fence->work = work; -+ fence->priv = priv; -+ } -+ -+ spin_unlock(&fence->channel->fence.lock); -+} -+ -+void -+__nouveau_fence_unref(void **sync_obj) - { - struct nouveau_fence *fence = nouveau_fence(*sync_obj); - -@@ -161,7 +193,7 @@ - } - - void * --nouveau_fence_ref(void *sync_obj) -+__nouveau_fence_ref(void *sync_obj) - { - struct nouveau_fence *fence = nouveau_fence(sync_obj); - -@@ -170,7 +202,7 @@ - } - - bool --nouveau_fence_signalled(void *sync_obj, void *sync_arg) -+__nouveau_fence_signalled(void *sync_obj, void *sync_arg) - { - struct nouveau_fence *fence = nouveau_fence(sync_obj); - struct nouveau_channel *chan = fence->channel; -@@ -183,13 +215,13 @@ - } - - int --nouveau_fence_wait(void *sync_obj, void *sync_arg, bool lazy, bool intr) -+__nouveau_fence_wait(void *sync_obj, void *sync_arg, bool lazy, bool intr) - { - unsigned long timeout = jiffies + (3 * DRM_HZ); - int ret = 0; - - while (1) { -- if (nouveau_fence_signalled(sync_obj, sync_arg)) -+ if (__nouveau_fence_signalled(sync_obj, sync_arg)) - break; - - if (time_after_eq(jiffies, timeout)) { -@@ -213,33 +245,311 @@ - return ret; - } - -+static struct nouveau_semaphore * -+alloc_semaphore(struct drm_device *dev) -+{ -+ struct drm_nouveau_private *dev_priv = dev->dev_private; -+ struct nouveau_semaphore *sema; -+ int ret; -+ -+ if (!USE_SEMA(dev)) -+ return NULL; -+ -+ sema = kmalloc(sizeof(*sema), GFP_KERNEL); -+ if (!sema) -+ goto fail; -+ -+ ret = drm_mm_pre_get(&dev_priv->fence.heap); -+ if (ret) -+ goto fail; -+ -+ spin_lock(&dev_priv->fence.lock); -+ sema->mem = drm_mm_search_free(&dev_priv->fence.heap, 4, 0, 0); -+ if (sema->mem) -+ sema->mem = drm_mm_get_block_atomic(sema->mem, 4, 0); -+ spin_unlock(&dev_priv->fence.lock); -+ -+ if (!sema->mem) -+ goto fail; -+ -+ kref_init(&sema->ref); -+ sema->dev = dev; -+ nouveau_bo_wr32(dev_priv->fence.bo, sema->mem->start / 4, 0); -+ -+ return sema; -+fail: -+ kfree(sema); -+ return NULL; -+} -+ -+static void -+free_semaphore(struct kref *ref) -+{ -+ struct nouveau_semaphore *sema = -+ container_of(ref, struct nouveau_semaphore, ref); -+ struct drm_nouveau_private *dev_priv = sema->dev->dev_private; -+ -+ spin_lock(&dev_priv->fence.lock); -+ drm_mm_put_block(sema->mem); -+ spin_unlock(&dev_priv->fence.lock); -+ -+ kfree(sema); -+} -+ -+static void -+semaphore_work(void *priv, bool signalled) -+{ -+ struct nouveau_semaphore *sema = priv; -+ struct drm_nouveau_private *dev_priv = sema->dev->dev_private; -+ -+ if (unlikely(!signalled)) -+ nouveau_bo_wr32(dev_priv->fence.bo, sema->mem->start / 4, 1); -+ -+ kref_put(&sema->ref, free_semaphore); -+} -+ -+static int -+emit_semaphore(struct nouveau_channel *chan, int method, -+ struct nouveau_semaphore *sema) -+{ -+ struct drm_nouveau_private *dev_priv = sema->dev->dev_private; -+ struct nouveau_fence *fence; -+ bool smart = (dev_priv->card_type >= NV_50); -+ int ret; -+ -+ ret = RING_SPACE(chan, smart ? 8 : 4); -+ if (ret) -+ return ret; -+ -+ if (smart) { -+ BEGIN_RING(chan, NvSubSw, NV_SW_DMA_SEMAPHORE, 1); -+ OUT_RING(chan, NvSema); -+ } -+ BEGIN_RING(chan, NvSubSw, NV_SW_SEMAPHORE_OFFSET, 1); -+ OUT_RING(chan, sema->mem->start); -+ -+ if (smart && method == NV_SW_SEMAPHORE_ACQUIRE) { -+ /* -+ * NV50 tries to be too smart and context-switch -+ * between semaphores instead of doing a "first come, -+ * first served" strategy like previous cards -+ * do. -+ * -+ * That's bad because the ACQUIRE latency can get as -+ * large as the PFIFO context time slice in the -+ * typical DRI2 case where you have several -+ * outstanding semaphores at the same moment. -+ * -+ * If we're going to ACQUIRE, force the card to -+ * context switch before, just in case the matching -+ * RELEASE is already scheduled to be executed in -+ * another channel. -+ */ -+ BEGIN_RING(chan, NvSubSw, NV_SW_YIELD, 1); -+ OUT_RING(chan, 0); -+ } -+ -+ BEGIN_RING(chan, NvSubSw, method, 1); -+ OUT_RING(chan, 1); -+ -+ if (smart && method == NV_SW_SEMAPHORE_RELEASE) { -+ /* -+ * Force the card to context switch, there may be -+ * another channel waiting for the semaphore we just -+ * released. -+ */ -+ BEGIN_RING(chan, NvSubSw, NV_SW_YIELD, 1); -+ OUT_RING(chan, 0); -+ } -+ -+ /* Delay semaphore destruction until its work is done */ -+ ret = nouveau_fence_new(chan, &fence, true); -+ if (ret) -+ return ret; -+ -+ kref_get(&sema->ref); -+ nouveau_fence_work(fence, semaphore_work, sema); -+ nouveau_fence_unref(&fence); -+ -+ return 0; -+} -+ - int --nouveau_fence_flush(void *sync_obj, void *sync_arg) -+nouveau_fence_sync(struct nouveau_fence *fence, -+ struct nouveau_channel *wchan) -+{ -+ struct nouveau_channel *chan = nouveau_fence_channel(fence); -+ struct drm_device *dev = wchan->dev; -+ struct nouveau_semaphore *sema; -+ int ret = 0; -+ -+ if (likely(!chan || chan == wchan || -+ nouveau_fence_signalled(fence))) -+ goto out; -+ -+ sema = alloc_semaphore(dev); -+ if (!sema) { -+ /* Early card or broken userspace, fall back to -+ * software sync. */ -+ ret = nouveau_fence_wait(fence, true, false); -+ goto out; -+ } -+ -+ /* try to take chan's mutex, if we can't take it right away -+ * we have to fallback to software sync to prevent locking -+ * order issues -+ */ -+ if (!mutex_trylock(&chan->mutex)) { -+ ret = nouveau_fence_wait(fence, true, false); -+ goto out_unref; -+ } -+ -+ /* Make wchan wait until it gets signalled */ -+ ret = emit_semaphore(wchan, NV_SW_SEMAPHORE_ACQUIRE, sema); -+ if (ret) -+ goto out_unlock; -+ -+ /* Signal the semaphore from chan */ -+ ret = emit_semaphore(chan, NV_SW_SEMAPHORE_RELEASE, sema); -+ -+out_unlock: -+ mutex_unlock(&chan->mutex); -+out_unref: -+ kref_put(&sema->ref, free_semaphore); -+out: -+ if (chan) -+ nouveau_channel_put_unlocked(&chan); -+ return ret; -+} -+ -+int -+__nouveau_fence_flush(void *sync_obj, void *sync_arg) - { - return 0; - } - - int --nouveau_fence_init(struct nouveau_channel *chan) -+nouveau_fence_channel_init(struct nouveau_channel *chan) - { -+ struct drm_device *dev = chan->dev; -+ struct drm_nouveau_private *dev_priv = dev->dev_private; -+ struct nouveau_gpuobj *obj = NULL; -+ int ret; -+ -+ /* Create an NV_SW object for various sync purposes */ -+ ret = nouveau_gpuobj_gr_new(chan, NV_SW, &obj); -+ if (ret) -+ return ret; -+ -+ ret = nouveau_ramht_insert(chan, NvSw, obj); -+ nouveau_gpuobj_ref(NULL, &obj); -+ if (ret) -+ return ret; -+ -+ ret = RING_SPACE(chan, 2); -+ if (ret) -+ return ret; -+ BEGIN_RING(chan, NvSubSw, 0, 1); -+ OUT_RING(chan, NvSw); -+ -+ /* Create a DMA object for the shared cross-channel sync area. */ -+ if (USE_SEMA(dev)) { -+ struct drm_mm_node *mem = dev_priv->fence.bo->bo.mem.mm_node; -+ -+ ret = nouveau_gpuobj_dma_new(chan, NV_CLASS_DMA_IN_MEMORY, -+ mem->start << PAGE_SHIFT, -+ mem->size << PAGE_SHIFT, -+ NV_DMA_ACCESS_RW, -+ NV_DMA_TARGET_VIDMEM, &obj); -+ if (ret) -+ return ret; -+ -+ ret = nouveau_ramht_insert(chan, NvSema, obj); -+ nouveau_gpuobj_ref(NULL, &obj); -+ if (ret) -+ return ret; -+ -+ ret = RING_SPACE(chan, 2); -+ if (ret) -+ return ret; -+ BEGIN_RING(chan, NvSubSw, NV_SW_DMA_SEMAPHORE, 1); -+ OUT_RING(chan, NvSema); -+ } -+ -+ FIRE_RING(chan); -+ - INIT_LIST_HEAD(&chan->fence.pending); - spin_lock_init(&chan->fence.lock); - atomic_set(&chan->fence.last_sequence_irq, 0); -+ - return 0; - } - - void --nouveau_fence_fini(struct nouveau_channel *chan) -+nouveau_fence_channel_fini(struct nouveau_channel *chan) - { -- struct list_head *entry, *tmp; -- struct nouveau_fence *fence; -+ struct nouveau_fence *tmp, *fence; - -- list_for_each_safe(entry, tmp, &chan->fence.pending) { -- fence = list_entry(entry, struct nouveau_fence, entry); -+ spin_lock(&chan->fence.lock); - -+ list_for_each_entry_safe(fence, tmp, &chan->fence.pending, entry) { - fence->signalled = true; - list_del(&fence->entry); -+ -+ if (unlikely(fence->work)) -+ fence->work(fence->priv, false); -+ - kref_put(&fence->refcount, nouveau_fence_del); - } -+ -+ spin_unlock(&chan->fence.lock); - } - -+int -+nouveau_fence_init(struct drm_device *dev) -+{ -+ struct drm_nouveau_private *dev_priv = dev->dev_private; -+ int ret; -+ -+ /* Create a shared VRAM heap for cross-channel sync. */ -+ if (USE_SEMA(dev)) { -+ ret = nouveau_bo_new(dev, NULL, 4096, 0, TTM_PL_FLAG_VRAM, -+ 0, 0, false, true, &dev_priv->fence.bo); -+ if (ret) -+ return ret; -+ -+ ret = nouveau_bo_pin(dev_priv->fence.bo, TTM_PL_FLAG_VRAM); -+ if (ret) -+ goto fail; -+ -+ ret = nouveau_bo_map(dev_priv->fence.bo); -+ if (ret) -+ goto fail; -+ -+ ret = drm_mm_init(&dev_priv->fence.heap, 0, -+ dev_priv->fence.bo->bo.mem.size); -+ if (ret) -+ goto fail; -+ -+ spin_lock_init(&dev_priv->fence.lock); -+ } -+ -+ return 0; -+fail: -+ nouveau_bo_unmap(dev_priv->fence.bo); -+ nouveau_bo_ref(NULL, &dev_priv->fence.bo); -+ return ret; -+} -+ -+void -+nouveau_fence_fini(struct drm_device *dev) -+{ -+ struct drm_nouveau_private *dev_priv = dev->dev_private; -+ -+ if (USE_SEMA(dev)) { -+ drm_mm_takedown(&dev_priv->fence.heap); -+ nouveau_bo_unmap(dev_priv->fence.bo); -+ nouveau_bo_unpin(dev_priv->fence.bo); -+ nouveau_bo_ref(NULL, &dev_priv->fence.bo); -+ } -+} -diff -Naur linux-2.6.36/drivers/gpu/drm/nouveau/nouveau_gem.c linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nouveau_gem.c ---- linux-2.6.36/drivers/gpu/drm/nouveau/nouveau_gem.c 2010-10-20 22:30:22.000000000 +0200 -+++ linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nouveau_gem.c 2010-11-05 00:40:00.000000000 +0100 -@@ -48,9 +48,6 @@ - return; - nvbo->gem = NULL; - -- if (unlikely(nvbo->cpu_filp)) -- ttm_bo_synccpu_write_release(bo); -- - if (unlikely(nvbo->pin_refcnt)) { - nvbo->pin_refcnt = 1; - nouveau_bo_unpin(nvbo); -@@ -107,23 +104,29 @@ - } - - static bool --nouveau_gem_tile_flags_valid(struct drm_device *dev, uint32_t tile_flags) { -- switch (tile_flags) { -- case 0x0000: -- case 0x1800: -- case 0x2800: -- case 0x4800: -- case 0x7000: -- case 0x7400: -- case 0x7a00: -- case 0xe000: -- break; -- default: -- NV_ERROR(dev, "bad page flags: 0x%08x\n", tile_flags); -- return false; -+nouveau_gem_tile_flags_valid(struct drm_device *dev, uint32_t tile_flags) -+{ -+ struct drm_nouveau_private *dev_priv = dev->dev_private; -+ -+ if (dev_priv->card_type >= NV_50) { -+ switch (tile_flags & NOUVEAU_GEM_TILE_LAYOUT_MASK) { -+ case 0x0000: -+ case 0x1800: -+ case 0x2800: -+ case 0x4800: -+ case 0x7000: -+ case 0x7400: -+ case 0x7a00: -+ case 0xe000: -+ return true; -+ } -+ } else { -+ if (!(tile_flags & NOUVEAU_GEM_TILE_LAYOUT_MASK)) -+ return true; - } - -- return true; -+ NV_ERROR(dev, "bad page flags: 0x%08x\n", tile_flags); -+ return false; - } - - int -@@ -140,11 +143,6 @@ - if (unlikely(dev_priv->ttm.bdev.dev_mapping == NULL)) - dev_priv->ttm.bdev.dev_mapping = dev_priv->dev->dev_mapping; - -- if (req->channel_hint) { -- NOUVEAU_GET_USER_CHANNEL_WITH_RETURN(req->channel_hint, -- file_priv, chan); -- } -- - if (req->info.domain & NOUVEAU_GEM_DOMAIN_VRAM) - flags |= TTM_PL_FLAG_VRAM; - if (req->info.domain & NOUVEAU_GEM_DOMAIN_GART) -@@ -155,10 +153,18 @@ - if (!nouveau_gem_tile_flags_valid(dev, req->info.tile_flags)) - return -EINVAL; - -+ if (req->channel_hint) { -+ chan = nouveau_channel_get(dev, file_priv, req->channel_hint); -+ if (IS_ERR(chan)) -+ return PTR_ERR(chan); -+ } -+ - ret = nouveau_gem_new(dev, chan, req->info.size, req->align, flags, - req->info.tile_mode, req->info.tile_flags, false, - (req->info.domain & NOUVEAU_GEM_DOMAIN_MAPPABLE), - &nvbo); -+ if (chan) -+ nouveau_channel_put(&chan); - if (ret) - return ret; - -@@ -225,15 +231,8 @@ - - list_for_each_safe(entry, tmp, list) { - nvbo = list_entry(entry, struct nouveau_bo, entry); -- if (likely(fence)) { -- struct nouveau_fence *prev_fence; - -- spin_lock(&nvbo->bo.lock); -- prev_fence = nvbo->bo.sync_obj; -- nvbo->bo.sync_obj = nouveau_fence_ref(fence); -- spin_unlock(&nvbo->bo.lock); -- nouveau_fence_unref((void *)&prev_fence); -- } -+ nouveau_bo_fence(nvbo, fence); - - if (unlikely(nvbo->validate_mapped)) { - ttm_bo_kunmap(&nvbo->kmap); -@@ -293,14 +292,15 @@ - return -EINVAL; - } - -- ret = ttm_bo_reserve(&nvbo->bo, false, false, true, sequence); -+ ret = ttm_bo_reserve(&nvbo->bo, true, false, true, sequence); - if (ret) { - validate_fini(op, NULL); -- if (ret == -EAGAIN) -- ret = ttm_bo_wait_unreserved(&nvbo->bo, false); -+ if (unlikely(ret == -EAGAIN)) -+ ret = ttm_bo_wait_unreserved(&nvbo->bo, true); - drm_gem_object_unreference_unlocked(gem); -- if (ret) { -- NV_ERROR(dev, "fail reserve\n"); -+ if (unlikely(ret)) { -+ if (ret != -ERESTARTSYS) -+ NV_ERROR(dev, "fail reserve\n"); - return ret; - } - goto retry; -@@ -325,25 +325,6 @@ - validate_fini(op, NULL); - return -EINVAL; - } -- -- if (unlikely(atomic_read(&nvbo->bo.cpu_writers) > 0)) { -- validate_fini(op, NULL); -- -- if (nvbo->cpu_filp == file_priv) { -- NV_ERROR(dev, "bo %p mapped by process trying " -- "to validate it!\n", nvbo); -- return -EINVAL; -- } -- -- mutex_unlock(&drm_global_mutex); -- ret = ttm_bo_wait_cpu(&nvbo->bo, false); -- mutex_lock(&drm_global_mutex); -- if (ret) { -- NV_ERROR(dev, "fail wait_cpu\n"); -- return ret; -- } -- goto retry; -- } - } - - return 0; -@@ -362,7 +343,7 @@ - list_for_each_entry(nvbo, list, entry) { - struct drm_nouveau_gem_pushbuf_bo *b = &pbbo[nvbo->pbbo_index]; - -- ret = nouveau_bo_sync_gpu(nvbo, chan); -+ ret = nouveau_fence_sync(nvbo->bo.sync_obj, chan); - if (unlikely(ret)) { - NV_ERROR(dev, "fail pre-validate sync\n"); - return ret; -@@ -378,14 +359,15 @@ - - nvbo->channel = (b->read_domains & (1 << 31)) ? NULL : chan; - ret = ttm_bo_validate(&nvbo->bo, &nvbo->placement, -- false, false, false); -+ true, false, false); - nvbo->channel = NULL; - if (unlikely(ret)) { -- NV_ERROR(dev, "fail ttm_validate\n"); -+ if (ret != -ERESTARTSYS) -+ NV_ERROR(dev, "fail ttm_validate\n"); - return ret; - } - -- ret = nouveau_bo_sync_gpu(nvbo, chan); -+ ret = nouveau_fence_sync(nvbo->bo.sync_obj, chan); - if (unlikely(ret)) { - NV_ERROR(dev, "fail post-validate sync\n"); - return ret; -@@ -433,13 +415,15 @@ - - ret = validate_init(chan, file_priv, pbbo, nr_buffers, op); - if (unlikely(ret)) { -- NV_ERROR(dev, "validate_init\n"); -+ if (ret != -ERESTARTSYS) -+ NV_ERROR(dev, "validate_init\n"); - return ret; - } - - ret = validate_list(chan, &op->vram_list, pbbo, user_buffers); - if (unlikely(ret < 0)) { -- NV_ERROR(dev, "validate vram_list\n"); -+ if (ret != -ERESTARTSYS) -+ NV_ERROR(dev, "validate vram_list\n"); - validate_fini(op, NULL); - return ret; - } -@@ -447,7 +431,8 @@ - - ret = validate_list(chan, &op->gart_list, pbbo, user_buffers); - if (unlikely(ret < 0)) { -- NV_ERROR(dev, "validate gart_list\n"); -+ if (ret != -ERESTARTSYS) -+ NV_ERROR(dev, "validate gart_list\n"); - validate_fini(op, NULL); - return ret; - } -@@ -455,7 +440,8 @@ - - ret = validate_list(chan, &op->both_list, pbbo, user_buffers); - if (unlikely(ret < 0)) { -- NV_ERROR(dev, "validate both_list\n"); -+ if (ret != -ERESTARTSYS) -+ NV_ERROR(dev, "validate both_list\n"); - validate_fini(op, NULL); - return ret; - } -@@ -579,7 +565,9 @@ - struct nouveau_fence *fence = NULL; - int i, j, ret = 0, do_reloc = 0; - -- NOUVEAU_GET_USER_CHANNEL_WITH_RETURN(req->channel, file_priv, chan); -+ chan = nouveau_channel_get(dev, file_priv, req->channel); -+ if (IS_ERR(chan)) -+ return PTR_ERR(chan); - - req->vram_available = dev_priv->fb_aper_free; - req->gart_available = dev_priv->gart_info.aper_free; -@@ -589,28 +577,34 @@ - if (unlikely(req->nr_push > NOUVEAU_GEM_MAX_PUSH)) { - NV_ERROR(dev, "pushbuf push count exceeds limit: %d max %d\n", - req->nr_push, NOUVEAU_GEM_MAX_PUSH); -+ nouveau_channel_put(&chan); - return -EINVAL; - } - - if (unlikely(req->nr_buffers > NOUVEAU_GEM_MAX_BUFFERS)) { - NV_ERROR(dev, "pushbuf bo count exceeds limit: %d max %d\n", - req->nr_buffers, NOUVEAU_GEM_MAX_BUFFERS); -+ nouveau_channel_put(&chan); - return -EINVAL; - } - - if (unlikely(req->nr_relocs > NOUVEAU_GEM_MAX_RELOCS)) { - NV_ERROR(dev, "pushbuf reloc count exceeds limit: %d max %d\n", - req->nr_relocs, NOUVEAU_GEM_MAX_RELOCS); -+ nouveau_channel_put(&chan); - return -EINVAL; - } - - push = u_memcpya(req->push, req->nr_push, sizeof(*push)); -- if (IS_ERR(push)) -+ if (IS_ERR(push)) { -+ nouveau_channel_put(&chan); - return 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); - } - -@@ -633,7 +627,8 @@ - ret = nouveau_gem_pushbuf_validate(chan, file_priv, bo, req->buffers, - req->nr_buffers, &op, &do_reloc); - if (ret) { -- NV_ERROR(dev, "validate: %d\n", ret); -+ if (ret != -ERESTARTSYS) -+ NV_ERROR(dev, "validate: %d\n", ret); - goto out; - } - -@@ -726,7 +721,7 @@ - - out: - validate_fini(&op, fence); -- nouveau_fence_unref((void**)&fence); -+ nouveau_fence_unref(&fence); - kfree(bo); - kfree(push); - -@@ -744,6 +739,7 @@ - req->suffix1 = 0x00000000; - } - -+ nouveau_channel_put(&chan); - return ret; - } - -@@ -775,26 +771,9 @@ - return -ENOENT; - nvbo = nouveau_gem_object(gem); - -- if (nvbo->cpu_filp) { -- if (nvbo->cpu_filp == file_priv) -- goto out; -- -- ret = ttm_bo_wait_cpu(&nvbo->bo, no_wait); -- if (ret) -- goto out; -- } -- -- if (req->flags & NOUVEAU_GEM_CPU_PREP_NOBLOCK) { -- spin_lock(&nvbo->bo.lock); -- ret = ttm_bo_wait(&nvbo->bo, false, false, no_wait); -- spin_unlock(&nvbo->bo.lock); -- } else { -- ret = ttm_bo_synccpu_write_grab(&nvbo->bo, no_wait); -- if (ret == 0) -- nvbo->cpu_filp = file_priv; -- } -- --out: -+ spin_lock(&nvbo->bo.lock); -+ ret = ttm_bo_wait(&nvbo->bo, true, true, no_wait); -+ spin_unlock(&nvbo->bo.lock); - drm_gem_object_unreference_unlocked(gem); - return ret; - } -@@ -803,26 +782,7 @@ - nouveau_gem_ioctl_cpu_fini(struct drm_device *dev, void *data, - struct drm_file *file_priv) - { -- struct drm_nouveau_gem_cpu_prep *req = data; -- struct drm_gem_object *gem; -- struct nouveau_bo *nvbo; -- int ret = -EINVAL; -- -- gem = drm_gem_object_lookup(dev, file_priv, req->handle); -- if (!gem) -- return -ENOENT; -- nvbo = nouveau_gem_object(gem); -- -- if (nvbo->cpu_filp != file_priv) -- goto out; -- nvbo->cpu_filp = NULL; -- -- ttm_bo_synccpu_write_release(&nvbo->bo); -- ret = 0; -- --out: -- drm_gem_object_unreference_unlocked(gem); -- return ret; -+ return 0; - } - - int -diff -Naur linux-2.6.36/drivers/gpu/drm/nouveau/nouveau_grctx.h linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nouveau_grctx.h ---- linux-2.6.36/drivers/gpu/drm/nouveau/nouveau_grctx.h 2010-10-20 22:30:22.000000000 +0200 -+++ linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nouveau_grctx.h 2010-11-05 00:40:00.000000000 +0100 -@@ -126,7 +126,7 @@ - reg = (reg - 0x00400000) / 4; - reg = (reg - ctx->ctxprog_reg) + ctx->ctxvals_base; - -- nv_wo32(ctx->dev, ctx->data, reg, val); -+ nv_wo32(ctx->data, reg * 4, val); - } - #endif - -diff -Naur linux-2.6.36/drivers/gpu/drm/nouveau/nouveau_hw.c linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nouveau_hw.c ---- linux-2.6.36/drivers/gpu/drm/nouveau/nouveau_hw.c 2010-10-20 22:30:22.000000000 +0200 -+++ linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nouveau_hw.c 2010-11-05 00:40:00.000000000 +0100 -@@ -305,7 +305,7 @@ - bool mpll = Preg == 0x4020; - uint32_t oldPval = nvReadMC(dev, Preg); - uint32_t NMNM = pv->NM2 << 16 | pv->NM1; -- uint32_t Pval = (oldPval & (mpll ? ~(0x11 << 16) : ~(1 << 16))) | -+ uint32_t Pval = (oldPval & (mpll ? ~(0x77 << 16) : ~(7 << 16))) | - 0xc << 28 | pv->log2P << 16; - uint32_t saved4600 = 0; - /* some cards have different maskc040s */ -@@ -427,22 +427,12 @@ - struct nouveau_pll_vals *pllvals) - { - struct drm_nouveau_private *dev_priv = dev->dev_private; -- const uint32_t nv04_regs[MAX_PLL_TYPES] = { NV_PRAMDAC_NVPLL_COEFF, -- NV_PRAMDAC_MPLL_COEFF, -- NV_PRAMDAC_VPLL_COEFF, -- NV_RAMDAC_VPLL2 }; -- const uint32_t nv40_regs[MAX_PLL_TYPES] = { 0x4000, -- 0x4020, -- NV_PRAMDAC_VPLL_COEFF, -- NV_RAMDAC_VPLL2 }; -- uint32_t reg1, pll1, pll2 = 0; -+ uint32_t reg1 = get_pll_register(dev, plltype), pll1, pll2 = 0; - struct pll_lims pll_lim; - int ret; - -- if (dev_priv->card_type < NV_40) -- reg1 = nv04_regs[plltype]; -- else -- reg1 = nv40_regs[plltype]; -+ if (reg1 == 0) -+ return -ENOENT; - - pll1 = nvReadMC(dev, reg1); - -@@ -491,8 +481,10 @@ - nouveau_hw_get_clock(struct drm_device *dev, enum pll_types plltype) - { - struct nouveau_pll_vals pllvals; -+ int ret; - -- if (plltype == MPLL && (dev->pci_device & 0x0ff0) == CHIPSET_NFORCE) { -+ if (plltype == PLL_MEMORY && -+ (dev->pci_device & 0x0ff0) == CHIPSET_NFORCE) { - uint32_t mpllP; - - pci_read_config_dword(pci_get_bus_and_slot(0, 3), 0x6c, &mpllP); -@@ -501,14 +493,17 @@ - - return 400000 / mpllP; - } else -- if (plltype == MPLL && (dev->pci_device & 0xff0) == CHIPSET_NFORCE2) { -+ if (plltype == PLL_MEMORY && -+ (dev->pci_device & 0xff0) == CHIPSET_NFORCE2) { - uint32_t clock; - - pci_read_config_dword(pci_get_bus_and_slot(0, 5), 0x4c, &clock); - return clock; - } - -- nouveau_hw_get_pllvals(dev, plltype, &pllvals); -+ ret = nouveau_hw_get_pllvals(dev, plltype, &pllvals); -+ if (ret) -+ return ret; - - return nouveau_hw_pllvals_to_clk(&pllvals); - } -@@ -524,11 +519,11 @@ - - struct pll_lims pll_lim; - struct nouveau_pll_vals pv; -- uint32_t pllreg = head ? NV_RAMDAC_VPLL2 : NV_PRAMDAC_VPLL_COEFF; -+ enum pll_types pll = head ? PLL_VPLL1 : PLL_VPLL0; - -- if (get_pll_limits(dev, head ? VPLL2 : VPLL1, &pll_lim)) -+ if (get_pll_limits(dev, pll, &pll_lim)) - return; -- nouveau_hw_get_pllvals(dev, head ? VPLL2 : VPLL1, &pv); -+ nouveau_hw_get_pllvals(dev, pll, &pv); - - if (pv.M1 >= pll_lim.vco1.min_m && pv.M1 <= pll_lim.vco1.max_m && - pv.N1 >= pll_lim.vco1.min_n && pv.N1 <= pll_lim.vco1.max_n && -@@ -541,7 +536,7 @@ - pv.M1 = pll_lim.vco1.max_m; - pv.N1 = pll_lim.vco1.min_n; - pv.log2P = pll_lim.max_usable_log2p; -- nouveau_hw_setpll(dev, pllreg, &pv); -+ nouveau_hw_setpll(dev, pll_lim.reg, &pv); - } - - /* -@@ -661,7 +656,7 @@ - if (dev_priv->card_type >= NV_10) - regp->nv10_cursync = NVReadRAMDAC(dev, head, NV_RAMDAC_NV10_CURSYNC); - -- nouveau_hw_get_pllvals(dev, head ? VPLL2 : VPLL1, ®p->pllvals); -+ 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); -@@ -866,10 +861,11 @@ - 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_30) { -+ if (dev_priv->card_type >= NV_20) - rd_cio_state(dev, head, regp, NV_CIO_CRE_47); -+ -+ if (dev_priv->card_type >= NV_30) - rd_cio_state(dev, head, regp, 0x9f); -- } - - rd_cio_state(dev, head, regp, NV_CIO_CRE_49); - rd_cio_state(dev, head, regp, NV_CIO_CRE_HCUR_ADDR0_INDEX); -@@ -957,7 +953,7 @@ - NVWriteCRTC(dev, head, NV_PCRTC_850, regp->crtc_850); - - reg900 = NVReadRAMDAC(dev, head, NV_PRAMDAC_900); -- if (regp->crtc_cfg == NV_PCRTC_CONFIG_START_ADDRESS_HSYNC) -+ if (regp->crtc_cfg == NV10_PCRTC_CONFIG_START_ADDRESS_HSYNC) - NVWriteRAMDAC(dev, head, NV_PRAMDAC_900, reg900 | 0x10000); - else - NVWriteRAMDAC(dev, head, NV_PRAMDAC_900, reg900 & ~0x10000); -@@ -976,10 +972,11 @@ - 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_30) { -+ if (dev_priv->card_type >= NV_20) - wr_cio_state(dev, head, regp, NV_CIO_CRE_47); -+ -+ if (dev_priv->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); -@@ -1020,8 +1017,9 @@ - - NVWriteCRTC(dev, head, NV_PCRTC_START, regp->fb_start); - -- /* Setting 1 on this value gives you interrupts for every vblank period. */ -- NVWriteCRTC(dev, head, NV_PCRTC_INTR_EN_0, 0); -+ /* Enable vblank interrupts. */ -+ NVWriteCRTC(dev, head, NV_PCRTC_INTR_EN_0, -+ (dev->vblank_enabled[head] ? 1 : 0)); - NVWriteCRTC(dev, head, NV_PCRTC_INTR_0, NV_PCRTC_INTR_0_VBLANK); - } - -diff -Naur linux-2.6.36/drivers/gpu/drm/nouveau/nouveau_hw.h linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nouveau_hw.h ---- linux-2.6.36/drivers/gpu/drm/nouveau/nouveau_hw.h 2010-10-20 22:30:22.000000000 +0200 -+++ linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nouveau_hw.h 2010-11-05 00:40:00.000000000 +0100 -@@ -416,6 +416,25 @@ - } - - 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; -+ -+ NVWriteCRTC(dev, head, NV_PCRTC_START, offset); -+ -+ if (dev_priv->card_type == NV_04) { -+ /* -+ * Hilarious, the 24th bit doesn't want to stick to -+ * PCRTC_START... -+ */ -+ int cre_heb = NVReadVgaCrtc(dev, head, NV_CIO_CRE_HEB__INDEX); -+ -+ NVWriteVgaCrtc(dev, head, NV_CIO_CRE_HEB__INDEX, -+ (cre_heb & ~0x40) | ((offset >> 18) & 0x40)); -+ } -+} -+ -+static inline void - nv_show_cursor(struct drm_device *dev, int head, bool show) - { - struct drm_nouveau_private *dev_priv = dev->dev_private; -diff -Naur linux-2.6.36/drivers/gpu/drm/nouveau/nouveau_i2c.c linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nouveau_i2c.c ---- linux-2.6.36/drivers/gpu/drm/nouveau/nouveau_i2c.c 2010-10-20 22:30:22.000000000 +0200 -+++ linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nouveau_i2c.c 2010-11-05 00:40:00.000000000 +0100 -@@ -299,7 +299,10 @@ - - int - nouveau_i2c_identify(struct drm_device *dev, const char *what, -- struct i2c_board_info *info, int index) -+ struct i2c_board_info *info, -+ bool (*match)(struct nouveau_i2c_chan *, -+ struct i2c_board_info *), -+ int index) - { - struct nouveau_i2c_chan *i2c = nouveau_i2c_find(dev, index); - int i; -@@ -307,7 +310,8 @@ - NV_DEBUG(dev, "Probing %ss on I2C bus: %d\n", what, index); - - for (i = 0; info[i].addr; i++) { -- if (nouveau_probe_i2c_addr(i2c, info[i].addr)) { -+ if (nouveau_probe_i2c_addr(i2c, info[i].addr) && -+ (!match || match(i2c, &info[i]))) { - NV_INFO(dev, "Detected %s: %s\n", what, info[i].type); - return i; - } -diff -Naur linux-2.6.36/drivers/gpu/drm/nouveau/nouveau_i2c.h linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nouveau_i2c.h ---- linux-2.6.36/drivers/gpu/drm/nouveau/nouveau_i2c.h 2010-10-20 22:30:22.000000000 +0200 -+++ linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nouveau_i2c.h 2010-11-05 00:40:00.000000000 +0100 -@@ -44,7 +44,10 @@ - struct nouveau_i2c_chan *nouveau_i2c_find(struct drm_device *, int index); - bool nouveau_probe_i2c_addr(struct nouveau_i2c_chan *i2c, int addr); - int nouveau_i2c_identify(struct drm_device *dev, const char *what, -- struct i2c_board_info *info, int index); -+ struct i2c_board_info *info, -+ bool (*match)(struct nouveau_i2c_chan *, -+ struct i2c_board_info *), -+ int index); - - extern const struct i2c_algorithm nouveau_dp_i2c_algo; - -diff -Naur linux-2.6.36/drivers/gpu/drm/nouveau/nouveau_irq.c linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nouveau_irq.c ---- linux-2.6.36/drivers/gpu/drm/nouveau/nouveau_irq.c 2010-10-20 22:30:22.000000000 +0200 -+++ linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nouveau_irq.c 2010-11-05 00:40:00.000000000 +0100 -@@ -35,12 +35,20 @@ - #include "nouveau_drm.h" - #include "nouveau_drv.h" - #include "nouveau_reg.h" -+#include "nouveau_ramht.h" - #include - - /* needed for hotplug irq */ - #include "nouveau_connector.h" - #include "nv50_display.h" - -+static DEFINE_RATELIMIT_STATE(nouveau_ratelimit_state, 3 * HZ, 20); -+ -+static int nouveau_ratelimit(void) -+{ -+ return __ratelimit(&nouveau_ratelimit_state); -+} -+ - void - nouveau_irq_preinstall(struct drm_device *dev) - { -@@ -59,8 +67,13 @@ - 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); -+ - return 0; - } - -@@ -71,63 +84,50 @@ - nv_wr32(dev, NV03_PMC_INTR_EN_0, 0); - } - --static int --nouveau_call_method(struct nouveau_channel *chan, int class, int mthd, int data) --{ -- struct drm_nouveau_private *dev_priv = chan->dev->dev_private; -- struct nouveau_pgraph_object_method *grm; -- struct nouveau_pgraph_object_class *grc; -- -- grc = dev_priv->engine.graph.grclass; -- while (grc->id) { -- if (grc->id == class) -- break; -- grc++; -- } -- -- if (grc->id != class || !grc->methods) -- return -ENOENT; -- -- grm = grc->methods; -- while (grm->id) { -- if (grm->id == mthd) -- return grm->exec(chan, class, mthd, data); -- grm++; -- } -- -- return -ENOENT; --} -- - static bool --nouveau_fifo_swmthd(struct nouveau_channel *chan, uint32_t addr, uint32_t data) -+nouveau_fifo_swmthd(struct drm_device *dev, u32 chid, u32 addr, u32 data) - { -- struct drm_device *dev = chan->dev; -+ struct drm_nouveau_private *dev_priv = dev->dev_private; -+ struct nouveau_channel *chan = NULL; -+ struct nouveau_gpuobj *obj; -+ unsigned long flags; - const int subc = (addr >> 13) & 0x7; - const int mthd = addr & 0x1ffc; -+ bool handled = false; -+ u32 engine; - -- if (mthd == 0x0000) { -- struct nouveau_gpuobj_ref *ref = NULL; -+ spin_lock_irqsave(&dev_priv->channels.lock, flags); -+ if (likely(chid >= 0 && chid < dev_priv->engine.fifo.channels)) -+ chan = dev_priv->channels.ptr[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)) -+ break; - -- if (nouveau_gpuobj_ref_find(chan, data, &ref)) -- return false; -+ chan->sw_subchannel[subc] = obj->class; -+ engine = 0x0000000f << (subc * 4); - -- if (ref->gpuobj->engine != NVOBJ_ENGINE_SW) -- return false; -+ nv_mask(dev, NV04_PFIFO_CACHE1_ENGINE, engine, 0x00000000); -+ handled = true; -+ break; -+ default: -+ engine = nv_rd32(dev, NV04_PFIFO_CACHE1_ENGINE); -+ if (unlikely(((engine >> (subc * 4)) & 0xf) != 0)) -+ break; - -- chan->sw_subchannel[subc] = ref->gpuobj->class; -- nv_wr32(dev, NV04_PFIFO_CACHE1_ENGINE, nv_rd32(dev, -- NV04_PFIFO_CACHE1_ENGINE) & ~(0xf << subc * 4)); -- return true; -+ if (!nouveau_gpuobj_mthd_call(chan, chan->sw_subchannel[subc], -+ mthd, data)) -+ handled = true; -+ break; - } - -- /* hw object */ -- if (nv_rd32(dev, NV04_PFIFO_CACHE1_ENGINE) & (1 << (subc*4))) -- return false; -- -- if (nouveau_call_method(chan, chan->sw_subchannel[subc], mthd, data)) -- return false; -- -- return true; -+out: -+ spin_unlock_irqrestore(&dev_priv->channels.lock, flags); -+ return handled; - } - - static void -@@ -140,14 +140,11 @@ - - reassign = nv_rd32(dev, NV03_PFIFO_CACHES) & 1; - while ((status = nv_rd32(dev, NV03_PFIFO_INTR_0)) && (cnt++ < 100)) { -- struct nouveau_channel *chan = NULL; - uint32_t chid, get; - - nv_wr32(dev, NV03_PFIFO_CACHES, 0); - - chid = engine->fifo.channel_id(dev); -- if (chid >= 0 && chid < engine->fifo.channels) -- chan = dev_priv->fifos[chid]; - get = nv_rd32(dev, NV03_PFIFO_CACHE1_GET); - - if (status & NV_PFIFO_INTR_CACHE_ERROR) { -@@ -174,7 +171,7 @@ - NV40_PFIFO_CACHE1_DATA(ptr)); - } - -- if (!chan || !nouveau_fifo_swmthd(chan, mthd, data)) { -+ if (!nouveau_fifo_swmthd(dev, chid, mthd, data)) { - NV_INFO(dev, "PFIFO_CACHE_ERROR - Ch %d/%d " - "Mthd 0x%04x Data 0x%08x\n", - chid, (mthd >> 13) & 7, mthd & 0x1ffc, -@@ -200,16 +197,47 @@ - } - - if (status & NV_PFIFO_INTR_DMA_PUSHER) { -- NV_INFO(dev, "PFIFO_DMA_PUSHER - Ch %d\n", chid); -+ 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 Push 0x%08x\n", -+ chid, ho_get, dma_get, ho_put, -+ dma_put, ib_get, ib_put, state, -+ push); -+ -+ /* METHOD_COUNT, in DMA_STATE on earlier chipsets */ -+ nv_wr32(dev, 0x003364, 0x00000000); -+ if (dma_get != dma_put || ho_get != ho_put) { -+ nv_wr32(dev, 0x003244, dma_put); -+ nv_wr32(dev, 0x003328, ho_put); -+ } else -+ if (ib_get != ib_put) { -+ nv_wr32(dev, 0x003334, ib_put); -+ } -+ } else { -+ NV_INFO(dev, "PFIFO_DMA_PUSHER - Ch %d Get 0x%08x " -+ "Put 0x%08x State 0x%08x Push 0x%08x\n", -+ chid, dma_get, dma_put, state, push); - -- status &= ~NV_PFIFO_INTR_DMA_PUSHER; -- nv_wr32(dev, NV03_PFIFO_INTR_0, -- NV_PFIFO_INTR_DMA_PUSHER); -+ if (dma_get != dma_put) -+ nv_wr32(dev, 0x003244, dma_put); -+ } - -- nv_wr32(dev, NV04_PFIFO_CACHE1_DMA_STATE, 0x00000000); -- if (nv_rd32(dev, NV04_PFIFO_CACHE1_DMA_PUT) != get) -- nv_wr32(dev, NV04_PFIFO_CACHE1_DMA_GET, -- get + 4); -+ nv_wr32(dev, 0x003228, 0x00000000); -+ nv_wr32(dev, 0x003220, 0x00000001); -+ nv_wr32(dev, 0x002100, NV_PFIFO_INTR_DMA_PUSHER); -+ status &= ~NV_PFIFO_INTR_DMA_PUSHER; - } - - if (status & NV_PFIFO_INTR_SEMAPHORE) { -@@ -226,9 +254,18 @@ - nv_wr32(dev, NV04_PFIFO_CACHE1_PULL0, 1); - } - -+ if (dev_priv->card_type == NV_50) { -+ if (status & 0x00000010) { -+ nv50_fb_vm_trap(dev, 1, "PFIFO_BAR_FAULT"); -+ status &= ~0x00000010; -+ nv_wr32(dev, 0x002100, 0x00000010); -+ } -+ } -+ - if (status) { -- NV_INFO(dev, "PFIFO_INTR 0x%08x - Ch %d\n", -- status, chid); -+ if (nouveau_ratelimit()) -+ NV_INFO(dev, "PFIFO_INTR 0x%08x - Ch %d\n", -+ status, chid); - nv_wr32(dev, NV03_PFIFO_INTR_0, status); - status = 0; - } -@@ -342,6 +379,8 @@ - nouveau_graph_chid_from_grctx(struct drm_device *dev) - { - struct drm_nouveau_private *dev_priv = dev->dev_private; -+ struct nouveau_channel *chan; -+ unsigned long flags; - uint32_t inst; - int i; - -@@ -351,27 +390,29 @@ - if (dev_priv->card_type < NV_50) { - inst = (nv_rd32(dev, 0x40032c) & 0xfffff) << 4; - -+ spin_lock_irqsave(&dev_priv->channels.lock, flags); - for (i = 0; i < dev_priv->engine.fifo.channels; i++) { -- struct nouveau_channel *chan = dev_priv->fifos[i]; -- -+ chan = dev_priv->channels.ptr[i]; - if (!chan || !chan->ramin_grctx) - continue; - -- if (inst == chan->ramin_grctx->instance) -+ if (inst == chan->ramin_grctx->pinst) - break; - } -+ spin_unlock_irqrestore(&dev_priv->channels.lock, flags); - } else { - inst = (nv_rd32(dev, 0x40032c) & 0xfffff) << 12; - -+ spin_lock_irqsave(&dev_priv->channels.lock, flags); - for (i = 0; i < dev_priv->engine.fifo.channels; i++) { -- struct nouveau_channel *chan = dev_priv->fifos[i]; -- -+ chan = dev_priv->channels.ptr[i]; - if (!chan || !chan->ramin) - continue; - -- if (inst == chan->ramin->instance) -+ if (inst == chan->ramin->vinst) - break; - } -+ spin_unlock_irqrestore(&dev_priv->channels.lock, flags); - } - - -@@ -393,7 +434,8 @@ - else - channel = nouveau_graph_chid_from_grctx(dev); - -- if (channel >= engine->fifo.channels || !dev_priv->fifos[channel]) { -+ if (channel >= engine->fifo.channels || -+ !dev_priv->channels.ptr[channel]) { - NV_ERROR(dev, "AIII, invalid/inactive channel id %d\n", channel); - return -EINVAL; - } -@@ -476,14 +518,20 @@ - struct nouveau_pgraph_trap *trap) - { - struct drm_nouveau_private *dev_priv = dev->dev_private; -+ struct nouveau_channel *chan; -+ unsigned long flags; -+ int ret = -EINVAL; - -- if (trap->channel < 0 || -- trap->channel >= dev_priv->engine.fifo.channels || -- !dev_priv->fifos[trap->channel]) -- return -ENODEV; -+ spin_lock_irqsave(&dev_priv->channels.lock, flags); -+ if (trap->channel > 0 && -+ trap->channel < dev_priv->engine.fifo.channels && -+ dev_priv->channels.ptr[trap->channel]) { -+ chan = dev_priv->channels.ptr[trap->channel]; -+ ret = nouveau_gpuobj_mthd_call(chan, trap->class, trap->mthd, trap->data); -+ } -+ spin_unlock_irqrestore(&dev_priv->channels.lock, flags); - -- return nouveau_call_method(dev_priv->fifos[trap->channel], -- trap->class, trap->mthd, trap->data); -+ return ret; - } - - static inline void -@@ -505,13 +553,6 @@ - nouveau_graph_dump_trap_info(dev, "PGRAPH_NOTIFY", &trap); - } - --static DEFINE_RATELIMIT_STATE(nouveau_ratelimit_state, 3 * HZ, 20); -- --static int nouveau_ratelimit(void) --{ -- return __ratelimit(&nouveau_ratelimit_state); --} -- - - static inline void - nouveau_pgraph_intr_error(struct drm_device *dev, uint32_t nsource) -@@ -605,40 +646,6 @@ - nv_wr32(dev, NV03_PMC_INTR_0, NV_PMC_INTR_0_PGRAPH_PENDING); - } - --static void --nv50_pfb_vm_trap(struct drm_device *dev, int display, const char *name) --{ -- struct drm_nouveau_private *dev_priv = dev->dev_private; -- uint32_t trap[6]; -- int i, ch; -- uint32_t idx = nv_rd32(dev, 0x100c90); -- if (idx & 0x80000000) { -- idx &= 0xffffff; -- if (display) { -- for (i = 0; i < 6; i++) { -- nv_wr32(dev, 0x100c90, idx | i << 24); -- trap[i] = nv_rd32(dev, 0x100c94); -- } -- for (ch = 0; ch < dev_priv->engine.fifo.channels; ch++) { -- struct nouveau_channel *chan = dev_priv->fifos[ch]; -- -- if (!chan || !chan->ramin) -- continue; -- -- if (trap[1] == chan->ramin->instance >> 12) -- break; -- } -- NV_INFO(dev, "%s - VM: Trapped %s at %02x%04x%04x status %08x %08x channel %d\n", -- name, (trap[5]&0x100?"read":"write"), -- trap[5]&0xff, trap[4]&0xffff, -- trap[3]&0xffff, trap[0], trap[2], ch); -- } -- nv_wr32(dev, 0x100c90, idx | 0x80000000); -- } else if (display) { -- NV_INFO(dev, "%s - no VM fault?\n", name); -- } --} -- - static struct nouveau_enum_names nv50_mp_exec_error_names[] = - { - { 3, "STACK_UNDERFLOW" }, -@@ -711,7 +718,7 @@ - tps++; - switch (type) { - case 6: /* texture error... unknown for now */ -- nv50_pfb_vm_trap(dev, display, name); -+ nv50_fb_vm_trap(dev, display, name); - if (display) { - NV_ERROR(dev, "magic set %d:\n", i); - for (r = ustatus_addr + 4; r <= ustatus_addr + 0x10; r += 4) -@@ -734,7 +741,7 @@ - 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); -- nv50_pfb_vm_trap(dev, display, name); -+ nv50_fb_vm_trap(dev, display, name); - /* 2d engine destination */ - if (ustatus & 0x00000010) { - if (display) { -@@ -817,7 +824,7 @@ - - /* Known to be triggered by screwed up NOTIFY and COND... */ - if (ustatus & 0x00000001) { -- nv50_pfb_vm_trap(dev, display, "PGRAPH_TRAP_DISPATCH_FAULT"); -+ nv50_fb_vm_trap(dev, display, "PGRAPH_TRAP_DISPATCH_FAULT"); - nv_wr32(dev, 0x400500, 0); - if (nv_rd32(dev, 0x400808) & 0x80000000) { - if (display) { -@@ -842,7 +849,7 @@ - ustatus &= ~0x00000001; - } - if (ustatus & 0x00000002) { -- nv50_pfb_vm_trap(dev, display, "PGRAPH_TRAP_DISPATCH_QUERY"); -+ nv50_fb_vm_trap(dev, display, "PGRAPH_TRAP_DISPATCH_QUERY"); - nv_wr32(dev, 0x400500, 0); - if (nv_rd32(dev, 0x40084c) & 0x80000000) { - if (display) { -@@ -884,15 +891,15 @@ - NV_INFO(dev, "PGRAPH_TRAP_M2MF - no ustatus?\n"); - } - if (ustatus & 0x00000001) { -- nv50_pfb_vm_trap(dev, display, "PGRAPH_TRAP_M2MF_NOTIFY"); -+ nv50_fb_vm_trap(dev, display, "PGRAPH_TRAP_M2MF_NOTIFY"); - ustatus &= ~0x00000001; - } - if (ustatus & 0x00000002) { -- nv50_pfb_vm_trap(dev, display, "PGRAPH_TRAP_M2MF_IN"); -+ nv50_fb_vm_trap(dev, display, "PGRAPH_TRAP_M2MF_IN"); - ustatus &= ~0x00000002; - } - if (ustatus & 0x00000004) { -- nv50_pfb_vm_trap(dev, display, "PGRAPH_TRAP_M2MF_OUT"); -+ nv50_fb_vm_trap(dev, display, "PGRAPH_TRAP_M2MF_OUT"); - ustatus &= ~0x00000004; - } - NV_INFO (dev, "PGRAPH_TRAP_M2MF - %08x %08x %08x %08x\n", -@@ -917,7 +924,7 @@ - NV_INFO(dev, "PGRAPH_TRAP_VFETCH - no ustatus?\n"); - } - if (ustatus & 0x00000001) { -- nv50_pfb_vm_trap(dev, display, "PGRAPH_TRAP_VFETCH_FAULT"); -+ nv50_fb_vm_trap(dev, display, "PGRAPH_TRAP_VFETCH_FAULT"); - NV_INFO (dev, "PGRAPH_TRAP_VFETCH_FAULT - %08x %08x %08x %08x\n", - nv_rd32(dev, 0x400c00), - nv_rd32(dev, 0x400c08), -@@ -939,7 +946,7 @@ - NV_INFO(dev, "PGRAPH_TRAP_STRMOUT - no ustatus?\n"); - } - if (ustatus & 0x00000001) { -- nv50_pfb_vm_trap(dev, display, "PGRAPH_TRAP_STRMOUT_FAULT"); -+ nv50_fb_vm_trap(dev, display, "PGRAPH_TRAP_STRMOUT_FAULT"); - NV_INFO (dev, "PGRAPH_TRAP_STRMOUT_FAULT - %08x %08x %08x %08x\n", - nv_rd32(dev, 0x401804), - nv_rd32(dev, 0x401808), -@@ -964,7 +971,7 @@ - NV_INFO(dev, "PGRAPH_TRAP_CCACHE - no ustatus?\n"); - } - if (ustatus & 0x00000001) { -- nv50_pfb_vm_trap(dev, display, "PGRAPH_TRAP_CCACHE_FAULT"); -+ nv50_fb_vm_trap(dev, display, "PGRAPH_TRAP_CCACHE_FAULT"); - NV_INFO (dev, "PGRAPH_TRAP_CCACHE_FAULT - %08x %08x %08x %08x %08x %08x %08x\n", - nv_rd32(dev, 0x405800), - nv_rd32(dev, 0x405804), -@@ -986,7 +993,7 @@ - * remaining, so try to handle it anyway. Perhaps related to that - * unknown DMA slot on tesla? */ - if (status & 0x20) { -- nv50_pfb_vm_trap(dev, display, "PGRAPH_TRAP_UNKC04"); -+ nv50_fb_vm_trap(dev, display, "PGRAPH_TRAP_UNKC04"); - ustatus = nv_rd32(dev, 0x402000) & 0x7fffffff; - if (display) - NV_INFO(dev, "PGRAPH_TRAP_UNKC04 - Unhandled ustatus 0x%08x\n", ustatus); -@@ -1192,11 +1199,15 @@ - static void - nouveau_crtc_irq_handler(struct drm_device *dev, int crtc) - { -- if (crtc & 1) -+ if (crtc & 1) { - nv_wr32(dev, NV_CRTC0_INTSTAT, NV_CRTC_INTR_VBLANK); -+ drm_handle_vblank(dev, 0); -+ } - -- if (crtc & 2) -+ if (crtc & 2) { - nv_wr32(dev, NV_CRTC1_INTSTAT, NV_CRTC_INTR_VBLANK); -+ drm_handle_vblank(dev, 1); -+ } - } - - irqreturn_t -@@ -1227,6 +1238,22 @@ - status &= ~NV_PMC_INTR_0_PGRAPH_PENDING; - } - -+ if (status & 0x00004000) { -+ u32 stat = nv_rd32(dev, 0x102130); -+ u32 mthd = nv_rd32(dev, 0x102190); -+ u32 data = nv_rd32(dev, 0x102194); -+ u32 inst = nv_rd32(dev, 0x102188) & 0x7fffffff; -+ -+ NV_INFO(dev, "PCRYPT_INTR: 0x%08x 0x%08x 0x%08x 0x%08x\n", -+ stat, mthd, data, inst); -+ nv_wr32(dev, 0x102130, stat); -+ nv_wr32(dev, 0x10200c, 0x10); -+ -+ nv50_fb_vm_trap(dev, nouveau_ratelimit(), "PCRYPT"); -+ status &= ~0x00004000; -+ -+ } -+ - if (status & NV_PMC_INTR_0_CRTCn_PENDING) { - nouveau_crtc_irq_handler(dev, (status>>24)&3); - status &= ~NV_PMC_INTR_0_CRTCn_PENDING; -@@ -1244,5 +1271,35 @@ - - spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags); - -+ if (dev_priv->msi_enabled) -+ nv_wr08(dev, 0x00088068, 0xff); -+ - 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); -+} -diff -Naur linux-2.6.36/drivers/gpu/drm/nouveau/nouveau_mem.c linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nouveau_mem.c ---- linux-2.6.36/drivers/gpu/drm/nouveau/nouveau_mem.c 2010-10-20 22:30:22.000000000 +0200 -+++ linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nouveau_mem.c 2010-11-05 00:40:00.000000000 +0100 -@@ -33,92 +33,113 @@ - #include "drmP.h" - #include "drm.h" - #include "drm_sarea.h" -+ - #include "nouveau_drv.h" -+#include "nouveau_pm.h" - - /* - * NV10-NV40 tiling helpers - */ - - static void --nv10_mem_set_region_tiling(struct drm_device *dev, int i, uint32_t addr, -- uint32_t size, uint32_t pitch) -+nv10_mem_update_tile_region(struct drm_device *dev, -+ struct nouveau_tile_reg *tile, uint32_t addr, -+ uint32_t size, uint32_t pitch, uint32_t flags) - { - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_fifo_engine *pfifo = &dev_priv->engine.fifo; - struct nouveau_fb_engine *pfb = &dev_priv->engine.fb; - struct nouveau_pgraph_engine *pgraph = &dev_priv->engine.graph; -- struct nouveau_tile_reg *tile = &dev_priv->tile.reg[i]; -+ int i = tile - dev_priv->tile.reg; -+ unsigned long save; - -- tile->addr = addr; -- tile->size = size; -- tile->used = !!pitch; -- nouveau_fence_unref((void **)&tile->fence); -+ nouveau_fence_unref(&tile->fence); - -- if (!pfifo->cache_flush(dev)) -- return; -+ if (tile->pitch) -+ pfb->free_tile_region(dev, i); - -+ if (pitch) -+ pfb->init_tile_region(dev, i, addr, size, pitch, flags); -+ -+ spin_lock_irqsave(&dev_priv->context_switch_lock, save); - pfifo->reassign(dev, false); -- pfifo->cache_flush(dev); - pfifo->cache_pull(dev, false); - - nouveau_wait_for_idle(dev); - -- pgraph->set_region_tiling(dev, i, addr, size, pitch); -- pfb->set_region_tiling(dev, i, addr, size, pitch); -+ pfb->set_tile_region(dev, i); -+ pgraph->set_tile_region(dev, i); - - pfifo->cache_pull(dev, true); - pfifo->reassign(dev, true); -+ spin_unlock_irqrestore(&dev_priv->context_switch_lock, save); - } - --struct nouveau_tile_reg * --nv10_mem_set_tiling(struct drm_device *dev, uint32_t addr, uint32_t size, -- uint32_t pitch) -+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_fb_engine *pfb = &dev_priv->engine.fb; -- struct nouveau_tile_reg *tile = dev_priv->tile.reg, *found = NULL; -- int i; -+ struct nouveau_tile_reg *tile = &dev_priv->tile.reg[i]; - - spin_lock(&dev_priv->tile.lock); - -- for (i = 0; i < pfb->num_tiles; i++) { -- if (tile[i].used) -- /* Tile region in use. */ -- continue; -+ if (!tile->used && -+ (!tile->fence || nouveau_fence_signalled(tile->fence))) -+ tile->used = true; -+ else -+ tile = NULL; - -- if (tile[i].fence && -- !nouveau_fence_signalled(tile[i].fence, NULL)) -- /* Pending tile region. */ -- continue; -+ spin_unlock(&dev_priv->tile.lock); -+ return tile; -+} - -- if (max(tile[i].addr, addr) < -- min(tile[i].addr + tile[i].size, addr + size)) -- /* Kill an intersecting tile region. */ -- nv10_mem_set_region_tiling(dev, i, 0, 0, 0); -+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 (pitch && !found) { -- /* Free tile region. */ -- nv10_mem_set_region_tiling(dev, i, addr, size, pitch); -- found = &tile[i]; -+ if (tile) { -+ spin_lock(&dev_priv->tile.lock); -+ if (fence) { -+ /* Mark it as pending. */ -+ tile->fence = fence; -+ nouveau_fence_ref(fence); - } -- } - -- spin_unlock(&dev_priv->tile.lock); -- -- return found; -+ tile->used = false; -+ spin_unlock(&dev_priv->tile.lock); -+ } - } - --void --nv10_mem_expire_tiling(struct drm_device *dev, struct nouveau_tile_reg *tile, -- struct nouveau_fence *fence) -+struct nouveau_tile_reg * -+nv10_mem_set_tiling(struct drm_device *dev, uint32_t addr, uint32_t size, -+ uint32_t pitch, uint32_t flags) - { -- if (fence) { -- /* Mark it as pending. */ -- tile->fence = fence; -- nouveau_fence_ref(fence); -+ 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++) { -+ tile = nv10_mem_get_tile_region(dev, i); -+ -+ if (pitch && !found) { -+ found = tile; -+ continue; -+ -+ } else if (tile && tile->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); - } - -- tile->used = false; -+ if (found) -+ nv10_mem_update_tile_region(dev, found, addr, size, -+ pitch, flags); -+ return found; - } - - /* -@@ -169,16 +190,17 @@ - virt += (end - pte); - - while (pte < end) { -- nv_wo32(dev, pgt, pte++, offset_l); -- nv_wo32(dev, pgt, pte++, offset_h); -+ nv_wo32(pgt, (pte * 4) + 0, offset_l); -+ nv_wo32(pgt, (pte * 4) + 4, offset_h); -+ pte += 2; - } - } - } - dev_priv->engine.instmem.flush(dev); - -- nv50_vm_flush(dev, 5); -- nv50_vm_flush(dev, 0); -- nv50_vm_flush(dev, 4); -+ dev_priv->engine.instmem.flush(dev); -+ dev_priv->engine.fifo.tlb_flush(dev); -+ dev_priv->engine.graph.tlb_flush(dev); - nv50_vm_flush(dev, 6); - return 0; - } -@@ -203,14 +225,15 @@ - pages -= (end - pte); - virt += (end - pte) << 15; - -- while (pte < end) -- nv_wo32(dev, pgt, pte++, 0); -+ while (pte < end) { -+ nv_wo32(pgt, (pte * 4), 0); -+ pte++; -+ } - } -- dev_priv->engine.instmem.flush(dev); - -- nv50_vm_flush(dev, 5); -- nv50_vm_flush(dev, 0); -- nv50_vm_flush(dev, 4); -+ dev_priv->engine.instmem.flush(dev); -+ dev_priv->engine.fifo.tlb_flush(dev); -+ dev_priv->engine.graph.tlb_flush(dev); - nv50_vm_flush(dev, 6); - } - -@@ -218,7 +241,7 @@ - * Cleanup everything - */ - void --nouveau_mem_close(struct drm_device *dev) -+nouveau_mem_vram_fini(struct drm_device *dev) - { - struct drm_nouveau_private *dev_priv = dev->dev_private; - -@@ -229,6 +252,19 @@ - - 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); -+ - if (drm_core_has_AGP(dev) && dev->agp) { - struct drm_agp_mem *entry, *tempe; - -@@ -248,13 +284,6 @@ - dev->agp->acquired = 0; - dev->agp->enabled = 0; - } -- -- if (dev_priv->fb_mtrr) { -- 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; -- } - } - - static uint32_t -@@ -305,8 +334,62 @@ - return 0; - } - --/* returns the amount of FB ram in bytes */ --int -+static void -+nv50_vram_preinit(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; -+ -+ 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 = ((r4 & 0x01000000) ? 8 : 4); -+ -+ 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)); -+ } -+ -+ dev_priv->vram_rblock_size = rowsize >> 12; -+ if (rt & 1) -+ dev_priv->vram_rblock_size *= 3; -+ -+ NV_DEBUG(dev, "rblock %lld bytes\n", -+ (u64)dev_priv->vram_rblock_size << 12); -+} -+ -+static void -+nvaa_vram_preinit(struct drm_device *dev) -+{ -+ struct drm_nouveau_private *dev_priv = dev->dev_private; -+ -+ /* To our knowledge, there's no large scale reordering of pages -+ * that occurs on IGP chipsets. -+ */ -+ dev_priv->vram_rblock_size = 1; -+} -+ -+static int - nouveau_mem_detect(struct drm_device *dev) - { - struct drm_nouveau_private *dev_priv = dev->dev_private; -@@ -325,9 +408,18 @@ - dev_priv->vram_size = nv_rd32(dev, NV04_PFB_FIFO_DATA); - dev_priv->vram_size |= (dev_priv->vram_size & 0xff) << 32; - dev_priv->vram_size &= 0xffffffff00ll; -- if (dev_priv->chipset == 0xaa || dev_priv->chipset == 0xac) { -+ -+ switch (dev_priv->chipset) { -+ case 0xaa: -+ case 0xac: -+ case 0xaf: - dev_priv->vram_sys_base = nv_rd32(dev, 0x100e10); - dev_priv->vram_sys_base <<= 12; -+ nvaa_vram_preinit(dev); -+ break; -+ default: -+ nv50_vram_preinit(dev); -+ break; - } - } else { - dev_priv->vram_size = nv_rd32(dev, 0x10f20c) << 20; -@@ -345,6 +437,33 @@ - return -ENOMEM; - } - -+#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) - { -@@ -355,7 +474,8 @@ - /* 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) & PCI_AGP_COMMAND_FW) { -+ 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; - -@@ -363,7 +483,7 @@ - if (ret) - return ret; - -- mode.mode = info.mode & ~PCI_AGP_COMMAND_FW; -+ mode.mode = get_agp_mode(dev, info.mode) & ~PCI_AGP_COMMAND_FW; - ret = drm_agp_enable(dev, mode); - if (ret) - return ret; -@@ -418,7 +538,7 @@ - } - - /* see agp.h for the AGPSTAT_* modes available */ -- mode.mode = info.mode; -+ 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); -@@ -433,24 +553,27 @@ - } - - int --nouveau_mem_init(struct drm_device *dev) -+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 = 32; -- -- dev_priv->fb_phys = pci_resource_start(dev->pdev, 1); -- dev_priv->gart_info.type = NOUVEAU_GART_NONE; -+ int ret, dma_bits; - - if (dev_priv->card_type >= NV_50 && - pci_dma_supported(dev->pdev, DMA_BIT_MASK(40))) - dma_bits = 40; -+ else -+ dma_bits = 32; - - ret = pci_set_dma_mask(dev->pdev, DMA_BIT_MASK(dma_bits)); -- if (ret) { -- NV_ERROR(dev, "Error setting DMA mask: %d\n", ret); -+ if (ret) - return ret; -- } -+ -+ ret = nouveau_mem_detect(dev); -+ if (ret) -+ return ret; -+ -+ dev_priv->fb_phys = pci_resource_start(dev->pdev, 1); - - ret = nouveau_ttm_global_init(dev_priv); - if (ret) -@@ -465,8 +588,6 @@ - return ret; - } - -- spin_lock_init(&dev_priv->tile.lock); -- - dev_priv->fb_available_size = dev_priv->vram_size; - dev_priv->fb_mappable_pages = dev_priv->fb_available_size; - if (dev_priv->fb_mappable_pages > pci_resource_len(dev->pdev, 1)) -@@ -474,7 +595,16 @@ - pci_resource_len(dev->pdev, 1); - dev_priv->fb_mappable_pages >>= PAGE_SHIFT; - -- /* remove reserved space at end of vram from available amount */ -+ /* reserve space at end of VRAM for PRAMIN */ -+ if (dev_priv->chipset == 0x40 || dev_priv->chipset == 0x47 || -+ dev_priv->chipset == 0x49 || dev_priv->chipset == 0x4b) -+ dev_priv->ramin_rsvd_vram = (2 * 1024 * 1024); -+ else -+ if (dev_priv->card_type >= NV_40) -+ dev_priv->ramin_rsvd_vram = (1 * 1024 * 1024); -+ else -+ dev_priv->ramin_rsvd_vram = (512 * 1024); -+ - dev_priv->fb_available_size -= dev_priv->ramin_rsvd_vram; - dev_priv->fb_aper_free = dev_priv->fb_available_size; - -@@ -495,9 +625,23 @@ - nouveau_bo_ref(NULL, &dev_priv->vga_ram); - } - -- /* GART */ -+ 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; -+ -+ dev_priv->gart_info.type = NOUVEAU_GART_NONE; -+ - #if !defined(__powerpc__) && !defined(__ia64__) -- if (drm_device_is_agp(dev) && dev->agp && !nouveau_noagp) { -+ if (drm_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); -@@ -523,11 +667,157 @@ - return ret; - } - -- dev_priv->fb_mtrr = drm_mtrr_add(pci_resource_start(dev->pdev, 1), -- pci_resource_len(dev->pdev, 1), -- DRM_MTRR_WC); -- - return 0; - } - -+void -+nouveau_mem_timing_init(struct drm_device *dev) -+{ -+ /* cards < NVC0 only */ -+ struct drm_nouveau_private *dev_priv = dev->dev_private; -+ struct nouveau_pm_engine *pm = &dev_priv->engine.pm; -+ struct nouveau_pm_memtimings *memtimings = &pm->memtimings; -+ struct nvbios *bios = &dev_priv->vbios; -+ struct bit_entry P; -+ u8 tUNK_0, tUNK_1, tUNK_2; -+ u8 tRP; /* Byte 3 */ -+ u8 tRAS; /* Byte 5 */ -+ u8 tRFC; /* Byte 7 */ -+ u8 tRC; /* Byte 9 */ -+ u8 tUNK_10, tUNK_11, tUNK_12, tUNK_13, tUNK_14; -+ u8 tUNK_18, tUNK_19, tUNK_20, tUNK_21; -+ u8 *mem = NULL, *entry; -+ int i, recordlen, entries; -+ -+ if (bios->type == NVBIOS_BIT) { -+ if (bit_table(dev, 'P', &P)) -+ return; -+ -+ if (P.version == 1) -+ mem = ROMPTR(bios, P.data[4]); -+ else -+ if (P.version == 2) -+ mem = ROMPTR(bios, P.data[8]); -+ else { -+ NV_WARN(dev, "unknown mem for BIT P %d\n", P.version); -+ } -+ } else { -+ NV_DEBUG(dev, "BMP version too old for memory\n"); -+ return; -+ } -+ -+ if (!mem) { -+ NV_DEBUG(dev, "memory timing table pointer invalid\n"); -+ return; -+ } -+ -+ if (mem[0] != 0x10) { -+ NV_WARN(dev, "memory timing table 0x%02x unknown\n", mem[0]); -+ return; -+ } -+ -+ /* validate record length */ -+ entries = mem[2]; -+ recordlen = mem[3]; -+ if (recordlen < 15) { -+ NV_ERROR(dev, "mem timing table length unknown: %d\n", mem[3]); -+ return; -+ } -+ -+ /* parse vbios entries into common format */ -+ memtimings->timing = -+ kcalloc(entries, sizeof(*memtimings->timing), GFP_KERNEL); -+ if (!memtimings->timing) -+ return; -+ -+ entry = mem + mem[1]; -+ for (i = 0; i < entries; i++, entry += recordlen) { -+ struct nouveau_pm_memtiming *timing = &pm->memtimings.timing[i]; -+ if (entry[0] == 0) -+ continue; -+ -+ tUNK_18 = 1; -+ tUNK_19 = 1; -+ tUNK_20 = 0; -+ tUNK_21 = 0; -+ switch (min(recordlen, 22)) { -+ case 22: -+ tUNK_21 = entry[21]; -+ case 21: -+ tUNK_20 = entry[20]; -+ case 20: -+ tUNK_19 = entry[19]; -+ case 19: -+ tUNK_18 = entry[18]; -+ default: -+ tUNK_0 = entry[0]; -+ tUNK_1 = entry[1]; -+ tUNK_2 = entry[2]; -+ tRP = entry[3]; -+ tRAS = entry[5]; -+ tRFC = entry[7]; -+ tRC = entry[9]; -+ tUNK_10 = entry[10]; -+ tUNK_11 = entry[11]; -+ tUNK_12 = entry[12]; -+ tUNK_13 = entry[13]; -+ tUNK_14 = entry[14]; -+ break; -+ } -+ -+ timing->reg_100220 = (tRC << 24 | tRFC << 16 | tRAS << 8 | tRP); -+ -+ /* XXX: I don't trust the -1's and +1's... they must come -+ * from somewhere! */ -+ timing->reg_100224 = ((tUNK_0 + tUNK_19 + 1) << 24 | -+ tUNK_18 << 16 | -+ (tUNK_1 + tUNK_19 + 1) << 8 | -+ (tUNK_2 - 1)); -+ -+ timing->reg_100228 = (tUNK_12 << 16 | tUNK_11 << 8 | tUNK_10); -+ if(recordlen > 19) { -+ timing->reg_100228 += (tUNK_19 - 1) << 24; -+ }/* I cannot back-up this else-statement right now -+ else { -+ timing->reg_100228 += tUNK_12 << 24; -+ }*/ -+ -+ /* XXX: reg_10022c */ -+ timing->reg_10022c = tUNK_2 - 1; -+ -+ timing->reg_100230 = (tUNK_20 << 24 | tUNK_21 << 16 | -+ tUNK_13 << 8 | tUNK_13); -+ -+ /* XXX: +6? */ -+ timing->reg_100234 = (tRAS << 24 | (tUNK_19 + 6) << 8 | tRC); -+ timing->reg_100234 += max(tUNK_10,tUNK_11) << 16; -+ -+ /* XXX; reg_100238, reg_10023c -+ * reg: 0x00?????? -+ * reg_10023c: -+ * 0 for pre-NV50 cards -+ * 0x????0202 for NV50+ cards (empirical evidence) */ -+ if(dev_priv->card_type >= NV_50) { -+ timing->reg_10023c = 0x202; -+ } -+ -+ NV_DEBUG(dev, "Entry %d: 220: %08x %08x %08x %08x\n", i, -+ timing->reg_100220, timing->reg_100224, -+ timing->reg_100228, timing->reg_10022c); -+ NV_DEBUG(dev, " 230: %08x %08x %08x %08x\n", -+ timing->reg_100230, timing->reg_100234, -+ timing->reg_100238, timing->reg_10023c); -+ } -+ -+ memtimings->nr_timing = entries; -+ memtimings->supported = true; -+} -+ -+void -+nouveau_mem_timing_fini(struct drm_device *dev) -+{ -+ struct drm_nouveau_private *dev_priv = dev->dev_private; -+ struct nouveau_pm_memtimings *mem = &dev_priv->engine.pm.memtimings; - -+ kfree(mem->timing); -+} -diff -Naur linux-2.6.36/drivers/gpu/drm/nouveau/nouveau_notifier.c linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nouveau_notifier.c ---- linux-2.6.36/drivers/gpu/drm/nouveau/nouveau_notifier.c 2010-10-20 22:30:22.000000000 +0200 -+++ linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nouveau_notifier.c 2010-11-05 00:40:00.000000000 +0100 -@@ -28,6 +28,7 @@ - #include "drmP.h" - #include "drm.h" - #include "nouveau_drv.h" -+#include "nouveau_ramht.h" - - int - nouveau_notifier_init_channel(struct nouveau_channel *chan) -@@ -112,7 +113,7 @@ - return -ENOMEM; - } - -- offset = chan->notifier_bo->bo.mem.mm_node->start << PAGE_SHIFT; -+ offset = chan->notifier_bo->bo.mem.start << PAGE_SHIFT; - if (chan->notifier_bo->bo.mem.mem_type == TTM_PL_VRAM) { - target = NV_DMA_TARGET_VIDMEM; - } else -@@ -146,11 +147,11 @@ - nobj->dtor = nouveau_notifier_gpuobj_dtor; - nobj->priv = mem; - -- ret = nouveau_gpuobj_ref_add(dev, chan, handle, nobj, NULL); -+ ret = nouveau_ramht_insert(chan, handle, nobj); -+ nouveau_gpuobj_ref(NULL, &nobj); - if (ret) { -- nouveau_gpuobj_del(dev, &nobj); - drm_mm_put_block(mem); -- NV_ERROR(dev, "Error referencing notifier ctxdma: %d\n", ret); -+ NV_ERROR(dev, "Error adding notifier to ramht: %d\n", ret); - return ret; - } - -@@ -184,11 +185,11 @@ - struct nouveau_channel *chan; - int ret; - -- NOUVEAU_GET_USER_CHANNEL_WITH_RETURN(na->channel, file_priv, chan); -+ chan = nouveau_channel_get(dev, file_priv, na->channel); -+ if (IS_ERR(chan)) -+ return PTR_ERR(chan); - - ret = nouveau_notifier_alloc(chan, na->handle, na->size, &na->offset); -- if (ret) -- return ret; -- -- return 0; -+ nouveau_channel_put(&chan); -+ return ret; - } -diff -Naur linux-2.6.36/drivers/gpu/drm/nouveau/nouveau_object.c linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nouveau_object.c ---- linux-2.6.36/drivers/gpu/drm/nouveau/nouveau_object.c 2010-10-20 22:30:22.000000000 +0200 -+++ linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nouveau_object.c 2010-11-05 00:40:00.000000000 +0100 -@@ -34,6 +34,84 @@ - #include "drm.h" - #include "nouveau_drv.h" - #include "nouveau_drm.h" -+#include "nouveau_ramht.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; -+} - - /* NVidia uses context objects to drive drawing operations. - -@@ -65,137 +143,6 @@ - The key into the hash table depends on the object handle and channel id and - is given as: - */ --static uint32_t --nouveau_ramht_hash_handle(struct drm_device *dev, int channel, uint32_t handle) --{ -- struct drm_nouveau_private *dev_priv = dev->dev_private; -- uint32_t hash = 0; -- int i; -- -- NV_DEBUG(dev, "ch%d handle=0x%08x\n", channel, handle); -- -- for (i = 32; i > 0; i -= dev_priv->ramht_bits) { -- hash ^= (handle & ((1 << dev_priv->ramht_bits) - 1)); -- handle >>= dev_priv->ramht_bits; -- } -- -- if (dev_priv->card_type < NV_50) -- hash ^= channel << (dev_priv->ramht_bits - 4); -- hash <<= 3; -- -- NV_DEBUG(dev, "hash=0x%08x\n", hash); -- return hash; --} -- --static int --nouveau_ramht_entry_valid(struct drm_device *dev, struct nouveau_gpuobj *ramht, -- uint32_t offset) --{ -- struct drm_nouveau_private *dev_priv = dev->dev_private; -- uint32_t ctx = nv_ro32(dev, ramht, (offset + 4)/4); -- -- if (dev_priv->card_type < NV_40) -- return ((ctx & NV_RAMHT_CONTEXT_VALID) != 0); -- return (ctx != 0); --} -- --static int --nouveau_ramht_insert(struct drm_device *dev, struct nouveau_gpuobj_ref *ref) --{ -- struct drm_nouveau_private *dev_priv = dev->dev_private; -- struct nouveau_instmem_engine *instmem = &dev_priv->engine.instmem; -- struct nouveau_channel *chan = ref->channel; -- struct nouveau_gpuobj *ramht = chan->ramht ? chan->ramht->gpuobj : NULL; -- uint32_t ctx, co, ho; -- -- if (!ramht) { -- NV_ERROR(dev, "No hash table!\n"); -- return -EINVAL; -- } -- -- if (dev_priv->card_type < NV_40) { -- ctx = NV_RAMHT_CONTEXT_VALID | (ref->instance >> 4) | -- (chan->id << NV_RAMHT_CONTEXT_CHANNEL_SHIFT) | -- (ref->gpuobj->engine << NV_RAMHT_CONTEXT_ENGINE_SHIFT); -- } else -- if (dev_priv->card_type < NV_50) { -- ctx = (ref->instance >> 4) | -- (chan->id << NV40_RAMHT_CONTEXT_CHANNEL_SHIFT) | -- (ref->gpuobj->engine << NV40_RAMHT_CONTEXT_ENGINE_SHIFT); -- } else { -- if (ref->gpuobj->engine == NVOBJ_ENGINE_DISPLAY) { -- ctx = (ref->instance << 10) | 2; -- } else { -- ctx = (ref->instance >> 4) | -- ((ref->gpuobj->engine << -- NV40_RAMHT_CONTEXT_ENGINE_SHIFT)); -- } -- } -- -- co = ho = nouveau_ramht_hash_handle(dev, chan->id, ref->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, ref->handle, ctx); -- nv_wo32(dev, ramht, (co + 0)/4, ref->handle); -- nv_wo32(dev, ramht, (co + 4)/4, ctx); -- -- list_add_tail(&ref->list, &chan->ramht_refs); -- instmem->flush(dev); -- return 0; -- } -- NV_DEBUG(dev, "collision ch%d 0x%08x: h=0x%08x\n", -- chan->id, co, nv_ro32(dev, ramht, co/4)); -- -- co += 8; -- if (co >= dev_priv->ramht_size) -- co = 0; -- } while (co != ho); -- -- NV_ERROR(dev, "RAMHT space exhausted. ch=%d\n", chan->id); -- return -ENOMEM; --} -- --static void --nouveau_ramht_remove(struct drm_device *dev, struct nouveau_gpuobj_ref *ref) --{ -- struct drm_nouveau_private *dev_priv = dev->dev_private; -- struct nouveau_instmem_engine *instmem = &dev_priv->engine.instmem; -- struct nouveau_channel *chan = ref->channel; -- struct nouveau_gpuobj *ramht = chan->ramht ? chan->ramht->gpuobj : NULL; -- uint32_t co, ho; -- -- if (!ramht) { -- NV_ERROR(dev, "No hash table!\n"); -- return; -- } -- -- co = ho = nouveau_ramht_hash_handle(dev, chan->id, ref->handle); -- do { -- if (nouveau_ramht_entry_valid(dev, ramht, co) && -- (ref->handle == nv_ro32(dev, ramht, (co/4)))) { -- NV_DEBUG(dev, -- "remove ch%d 0x%08x: h=0x%08x, c=0x%08x\n", -- chan->id, co, ref->handle, -- nv_ro32(dev, ramht, (co + 4))); -- nv_wo32(dev, ramht, (co + 0)/4, 0x00000000); -- nv_wo32(dev, ramht, (co + 4)/4, 0x00000000); -- -- list_del(&ref->list); -- instmem->flush(dev); -- return; -- } -- -- co += 8; -- if (co >= dev_priv->ramht_size) -- co = 0; -- } while (co != ho); -- list_del(&ref->list); -- -- NV_ERROR(dev, "RAMHT entry not found. ch=%d, handle=0x%08x\n", -- chan->id, ref->handle); --} - - int - nouveau_gpuobj_new(struct drm_device *dev, struct nouveau_channel *chan, -@@ -205,7 +152,7 @@ - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_engine *engine = &dev_priv->engine; - struct nouveau_gpuobj *gpuobj; -- struct drm_mm *pramin = NULL; -+ struct drm_mm_node *ramin = NULL; - int ret; - - NV_DEBUG(dev, "ch%d size=%u align=%d flags=0x%08x\n", -@@ -218,69 +165,102 @@ - if (!gpuobj) - return -ENOMEM; - NV_DEBUG(dev, "gpuobj %p\n", gpuobj); -+ gpuobj->dev = dev; - gpuobj->flags = flags; -- gpuobj->im_channel = chan; -+ 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); - -- /* Choose between global instmem heap, and per-channel private -- * instmem heap. On ramin_heap; -+ -+ 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; -+ } - } else { - NV_DEBUG(dev, "global heap\n"); -- pramin = &dev_priv->ramin_heap; - -- ret = engine->instmem.populate(dev, gpuobj, &size); -+ /* allocate backing pages, sets vinst */ -+ ret = engine->instmem.populate(dev, gpuobj, &size, align); - if (ret) { -- nouveau_gpuobj_del(dev, &gpuobj); -+ nouveau_gpuobj_ref(NULL, &gpuobj); - return ret; - } -- } - -- /* Allocate a chunk of the PRAMIN aperture */ -- gpuobj->im_pramin = drm_mm_search_free(pramin, size, align, 0); -- if (gpuobj->im_pramin) -- gpuobj->im_pramin = drm_mm_get_block(gpuobj->im_pramin, size, align); -+ /* try and get aperture space */ -+ 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); -+ nouveau_gpuobj_ref(NULL, &gpuobj); -+ return -ENOMEM; -+ } - -- if (!gpuobj->im_pramin) { -- nouveau_gpuobj_del(dev, &gpuobj); -- return -ENOMEM; -+ ramin = drm_mm_get_block_atomic(ramin, size, align); -+ spin_unlock(&dev_priv->ramin_lock); -+ } while (ramin == NULL); -+ -+ /* on nv50 it's ok to fail, we have a fallback path */ -+ if (!ramin && dev_priv->card_type < NV_50) { -+ nouveau_gpuobj_ref(NULL, &gpuobj); -+ return -ENOMEM; -+ } - } - -- if (!chan) { -+ /* if we got a chunk of the aperture, map pages into it */ -+ gpuobj->im_pramin = ramin; -+ if (!chan && gpuobj->im_pramin && dev_priv->ramin_available) { - ret = engine->instmem.bind(dev, gpuobj); - if (ret) { -- nouveau_gpuobj_del(dev, &gpuobj); -+ nouveau_gpuobj_ref(NULL, &gpuobj); - return ret; - } - } - -+ /* calculate the various different addresses for the object */ -+ if (chan) { -+ gpuobj->pinst = chan->ramin->pinst; -+ if (gpuobj->pinst != ~0) -+ gpuobj->pinst += gpuobj->im_pramin->start; -+ -+ if (dev_priv->card_type < NV_50) { -+ gpuobj->cinst = gpuobj->pinst; -+ } else { -+ gpuobj->cinst = gpuobj->im_pramin->start; -+ gpuobj->vinst = gpuobj->im_pramin->start + -+ chan->ramin->vinst; -+ } -+ } else { -+ if (gpuobj->im_pramin) -+ gpuobj->pinst = gpuobj->im_pramin->start; -+ else -+ gpuobj->pinst = ~0; -+ gpuobj->cinst = 0xdeadbeef; -+ } -+ - if (gpuobj->flags & NVOBJ_FLAG_ZERO_ALLOC) { - int i; - -- for (i = 0; i < gpuobj->im_pramin->size; i += 4) -- nv_wo32(dev, gpuobj, i/4, 0); -+ for (i = 0; i < gpuobj->size; i += 4) -+ nv_wo32(gpuobj, i, 0); - engine->instmem.flush(dev); - } - -- *gpuobj_ret = gpuobj; -- return 0; --} -- --int --nouveau_gpuobj_early_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); - -+ *gpuobj_ret = gpuobj; - return 0; - } - -@@ -288,18 +268,13 @@ - nouveau_gpuobj_init(struct drm_device *dev) - { - struct drm_nouveau_private *dev_priv = dev->dev_private; -- int ret; - - NV_DEBUG(dev, "\n"); - -- if (dev_priv->card_type < NV_50) { -- ret = nouveau_gpuobj_new_fake(dev, -- dev_priv->ramht_offset, ~0, dev_priv->ramht_size, -- NVOBJ_FLAG_ZERO_ALLOC | NVOBJ_FLAG_ALLOW_NO_REFS, -- &dev_priv->ramht, NULL); -- if (ret) -- return ret; -- } -+ 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; - } -@@ -308,300 +283,103 @@ - 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"); - -- nouveau_gpuobj_del(dev, &dev_priv->ramht); --} -- --void --nouveau_gpuobj_late_takedown(struct drm_device *dev) --{ -- struct drm_nouveau_private *dev_priv = dev->dev_private; -- struct nouveau_gpuobj *gpuobj = NULL; -- struct list_head *entry, *tmp; -- -- NV_DEBUG(dev, "\n"); -- -- list_for_each_safe(entry, tmp, &dev_priv->gpuobj_list) { -- gpuobj = list_entry(entry, struct nouveau_gpuobj, list); -- -- NV_ERROR(dev, "gpuobj %p still exists at takedown, refs=%d\n", -- gpuobj, gpuobj->refcount); -- gpuobj->refcount = 0; -- nouveau_gpuobj_del(dev, &gpuobj); -+ 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); - } -+ -+ BUG_ON(!list_empty(&dev_priv->gpuobj_list)); - } - --int --nouveau_gpuobj_del(struct drm_device *dev, struct nouveau_gpuobj **pgpuobj) -+ -+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_engine *engine = &dev_priv->engine; -- struct nouveau_gpuobj *gpuobj; - int i; - -- NV_DEBUG(dev, "gpuobj %p\n", pgpuobj ? *pgpuobj : NULL); -- -- if (!dev_priv || !pgpuobj || !(*pgpuobj)) -- return -EINVAL; -- gpuobj = *pgpuobj; -- -- if (gpuobj->refcount != 0) { -- NV_ERROR(dev, "gpuobj refcount is %d\n", gpuobj->refcount); -- return -EINVAL; -- } -+ NV_DEBUG(dev, "gpuobj %p\n", gpuobj); - - if (gpuobj->im_pramin && (gpuobj->flags & NVOBJ_FLAG_ZERO_FREE)) { -- for (i = 0; i < gpuobj->im_pramin->size; i += 4) -- nv_wo32(dev, gpuobj, i/4, 0); -+ for (i = 0; i < gpuobj->size; i += 4) -+ nv_wo32(gpuobj, i, 0); - engine->instmem.flush(dev); - } - - if (gpuobj->dtor) - gpuobj->dtor(dev, gpuobj); - -- if (gpuobj->im_backing && !(gpuobj->flags & NVOBJ_FLAG_FAKE)) -+ if (gpuobj->im_backing) - engine->instmem.clear(dev, gpuobj); - -- if (gpuobj->im_pramin) { -- if (gpuobj->flags & NVOBJ_FLAG_FAKE) -- kfree(gpuobj->im_pramin); -- else -- drm_mm_put_block(gpuobj->im_pramin); -- } -- -+ spin_lock(&dev_priv->ramin_lock); -+ if (gpuobj->im_pramin) -+ drm_mm_put_block(gpuobj->im_pramin); - list_del(&gpuobj->list); -+ spin_unlock(&dev_priv->ramin_lock); - -- *pgpuobj = NULL; - kfree(gpuobj); -- return 0; --} -- --static int --nouveau_gpuobj_instance_get(struct drm_device *dev, -- struct nouveau_channel *chan, -- struct nouveau_gpuobj *gpuobj, uint32_t *inst) --{ -- struct drm_nouveau_private *dev_priv = dev->dev_private; -- struct nouveau_gpuobj *cpramin; -- -- /* card_type < NV_50) { -- *inst = gpuobj->im_pramin->start; -- return 0; -- } -- -- if (chan && gpuobj->im_channel != chan) { -- NV_ERROR(dev, "Channel mismatch: obj %d, ref %d\n", -- gpuobj->im_channel->id, chan->id); -- return -EINVAL; -- } -- -- /* NV50 channel-local instance */ -- if (chan) { -- cpramin = chan->ramin->gpuobj; -- *inst = gpuobj->im_pramin->start - cpramin->im_pramin->start; -- return 0; -- } -- -- /* NV50 global (VRAM) instance */ -- if (!gpuobj->im_channel) { -- /* ...from global heap */ -- if (!gpuobj->im_backing) { -- NV_ERROR(dev, "AII, no VRAM backing gpuobj\n"); -- return -EINVAL; -- } -- *inst = gpuobj->im_backing_start; -- return 0; -- } else { -- /* ...from local heap */ -- cpramin = gpuobj->im_channel->ramin->gpuobj; -- *inst = cpramin->im_backing_start + -- (gpuobj->im_pramin->start - cpramin->im_pramin->start); -- return 0; -- } -- -- return -EINVAL; --} -- --int --nouveau_gpuobj_ref_add(struct drm_device *dev, struct nouveau_channel *chan, -- uint32_t handle, struct nouveau_gpuobj *gpuobj, -- struct nouveau_gpuobj_ref **ref_ret) --{ -- struct drm_nouveau_private *dev_priv = dev->dev_private; -- struct nouveau_gpuobj_ref *ref; -- uint32_t instance; -- int ret; -- -- NV_DEBUG(dev, "ch%d h=0x%08x gpuobj=%p\n", -- chan ? chan->id : -1, handle, gpuobj); -- -- if (!dev_priv || !gpuobj || (ref_ret && *ref_ret != NULL)) -- return -EINVAL; -- -- if (!chan && !ref_ret) -- return -EINVAL; -- -- if (gpuobj->engine == NVOBJ_ENGINE_SW && !gpuobj->im_pramin) { -- /* sw object */ -- instance = 0x40; -- } else { -- ret = nouveau_gpuobj_instance_get(dev, chan, gpuobj, &instance); -- if (ret) -- return ret; -- } -- -- ref = kzalloc(sizeof(*ref), GFP_KERNEL); -- if (!ref) -- return -ENOMEM; -- INIT_LIST_HEAD(&ref->list); -- ref->gpuobj = gpuobj; -- ref->channel = chan; -- ref->instance = instance; -- -- if (!ref_ret) { -- ref->handle = handle; -- -- ret = nouveau_ramht_insert(dev, ref); -- if (ret) { -- kfree(ref); -- return ret; -- } -- } else { -- ref->handle = ~0; -- *ref_ret = ref; -- } -- -- ref->gpuobj->refcount++; -- return 0; --} -- --int nouveau_gpuobj_ref_del(struct drm_device *dev, struct nouveau_gpuobj_ref **pref) --{ -- struct nouveau_gpuobj_ref *ref; -- -- NV_DEBUG(dev, "ref %p\n", pref ? *pref : NULL); -- -- if (!dev || !pref || *pref == NULL) -- return -EINVAL; -- ref = *pref; -- -- if (ref->handle != ~0) -- nouveau_ramht_remove(dev, ref); -- -- if (ref->gpuobj) { -- ref->gpuobj->refcount--; -- -- if (ref->gpuobj->refcount == 0) { -- if (!(ref->gpuobj->flags & NVOBJ_FLAG_ALLOW_NO_REFS)) -- nouveau_gpuobj_del(dev, &ref->gpuobj); -- } -- } -- -- *pref = NULL; -- kfree(ref); -- return 0; --} -- --int --nouveau_gpuobj_new_ref(struct drm_device *dev, -- struct nouveau_channel *oc, struct nouveau_channel *rc, -- uint32_t handle, uint32_t size, int align, -- uint32_t flags, struct nouveau_gpuobj_ref **ref) --{ -- struct nouveau_gpuobj *gpuobj = NULL; -- int ret; -- -- ret = nouveau_gpuobj_new(dev, oc, size, align, flags, &gpuobj); -- if (ret) -- return ret; -- -- ret = nouveau_gpuobj_ref_add(dev, rc, handle, gpuobj, ref); -- if (ret) { -- nouveau_gpuobj_del(dev, &gpuobj); -- return ret; -- } -- -- return 0; - } - --int --nouveau_gpuobj_ref_find(struct nouveau_channel *chan, uint32_t handle, -- struct nouveau_gpuobj_ref **ref_ret) -+void -+nouveau_gpuobj_ref(struct nouveau_gpuobj *ref, struct nouveau_gpuobj **ptr) - { -- struct nouveau_gpuobj_ref *ref; -- struct list_head *entry, *tmp; -- -- list_for_each_safe(entry, tmp, &chan->ramht_refs) { -- ref = list_entry(entry, struct nouveau_gpuobj_ref, list); -+ if (ref) -+ kref_get(&ref->refcount); - -- if (ref->handle == handle) { -- if (ref_ret) -- *ref_ret = ref; -- return 0; -- } -- } -+ if (*ptr) -+ kref_put(&(*ptr)->refcount, nouveau_gpuobj_del); - -- return -EINVAL; -+ *ptr = ref; - } - - int --nouveau_gpuobj_new_fake(struct drm_device *dev, uint32_t p_offset, -- uint32_t b_offset, uint32_t size, -- uint32_t flags, struct nouveau_gpuobj **pgpuobj, -- struct nouveau_gpuobj_ref **pref) -+nouveau_gpuobj_new_fake(struct drm_device *dev, u32 pinst, u64 vinst, -+ u32 size, u32 flags, struct nouveau_gpuobj **pgpuobj) - { - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_gpuobj *gpuobj = NULL; - int i; - - NV_DEBUG(dev, -- "p_offset=0x%08x b_offset=0x%08x size=0x%08x flags=0x%08x\n", -- p_offset, b_offset, size, flags); -+ "pinst=0x%08x vinst=0x%010llx size=0x%08x flags=0x%08x\n", -+ pinst, vinst, size, flags); - - gpuobj = kzalloc(sizeof(*gpuobj), GFP_KERNEL); - if (!gpuobj) - return -ENOMEM; - NV_DEBUG(dev, "gpuobj %p\n", gpuobj); -- gpuobj->im_channel = NULL; -- gpuobj->flags = flags | NVOBJ_FLAG_FAKE; -- -- list_add_tail(&gpuobj->list, &dev_priv->gpuobj_list); -- -- if (p_offset != ~0) { -- gpuobj->im_pramin = kzalloc(sizeof(struct drm_mm_node), -- GFP_KERNEL); -- if (!gpuobj->im_pramin) { -- nouveau_gpuobj_del(dev, &gpuobj); -- return -ENOMEM; -- } -- gpuobj->im_pramin->start = p_offset; -- gpuobj->im_pramin->size = size; -- } -- -- if (b_offset != ~0) { -- gpuobj->im_backing = (struct nouveau_bo *)-1; -- gpuobj->im_backing_start = b_offset; -- } -+ gpuobj->dev = dev; -+ gpuobj->flags = flags; -+ kref_init(&gpuobj->refcount); -+ gpuobj->size = size; -+ gpuobj->pinst = pinst; -+ gpuobj->cinst = 0xdeadbeef; -+ gpuobj->vinst = vinst; - - if (gpuobj->flags & NVOBJ_FLAG_ZERO_ALLOC) { -- for (i = 0; i < gpuobj->im_pramin->size; i += 4) -- nv_wo32(dev, gpuobj, i/4, 0); -+ for (i = 0; i < gpuobj->size; i += 4) -+ nv_wo32(gpuobj, i, 0); - dev_priv->engine.instmem.flush(dev); - } - -- if (pref) { -- i = nouveau_gpuobj_ref_add(dev, NULL, 0, gpuobj, pref); -- if (i) { -- nouveau_gpuobj_del(dev, &gpuobj); -- return i; -- } -- } -- -- if (pgpuobj) -- *pgpuobj = gpuobj; -+ spin_lock(&dev_priv->ramin_lock); -+ list_add_tail(&gpuobj->list, &dev_priv->gpuobj_list); -+ spin_unlock(&dev_priv->ramin_lock); -+ *pgpuobj = gpuobj; - return 0; - } - -@@ -685,14 +463,12 @@ - adjust = offset & 0x00000fff; - frame = offset & ~0x00000fff; - -- nv_wo32(dev, *gpuobj, 0, ((1<<12) | (1<<13) | -- (adjust << 20) | -- (access << 14) | -- (target << 16) | -- class)); -- nv_wo32(dev, *gpuobj, 1, size - 1); -- nv_wo32(dev, *gpuobj, 2, frame | pte_flags); -- nv_wo32(dev, *gpuobj, 3, frame | pte_flags); -+ nv_wo32(*gpuobj, 0, ((1<<12) | (1<<13) | (adjust << 20) | -+ (access << 14) | (target << 16) | -+ class)); -+ nv_wo32(*gpuobj, 4, size - 1); -+ nv_wo32(*gpuobj, 8, frame | pte_flags); -+ nv_wo32(*gpuobj, 12, frame | pte_flags); - } else { - uint64_t limit = offset + size - 1; - uint32_t flags0, flags5; -@@ -705,12 +481,12 @@ - flags5 = 0x00080000; - } - -- nv_wo32(dev, *gpuobj, 0, flags0 | class); -- nv_wo32(dev, *gpuobj, 1, lower_32_bits(limit)); -- nv_wo32(dev, *gpuobj, 2, lower_32_bits(offset)); -- nv_wo32(dev, *gpuobj, 3, ((upper_32_bits(limit) & 0xff) << 24) | -- (upper_32_bits(offset) & 0xff)); -- nv_wo32(dev, *gpuobj, 5, flags5); -+ nv_wo32(*gpuobj, 0, flags0 | class); -+ nv_wo32(*gpuobj, 4, lower_32_bits(limit)); -+ nv_wo32(*gpuobj, 8, lower_32_bits(offset)); -+ nv_wo32(*gpuobj, 12, ((upper_32_bits(limit) & 0xff) << 24) | -+ (upper_32_bits(offset) & 0xff)); -+ nv_wo32(*gpuobj, 20, flags5); - } - - instmem->flush(dev); -@@ -741,7 +517,7 @@ - *o_ret = 0; - } else - if (dev_priv->gart_info.type == NOUVEAU_GART_SGDMA) { -- *gpuobj = dev_priv->gart_info.sg_ctxdma; -+ nouveau_gpuobj_ref(dev_priv->gart_info.sg_ctxdma, gpuobj); - if (offset & ~0xffffffffULL) { - NV_ERROR(dev, "obj offset exceeds 32-bits\n"); - return -EINVAL; -@@ -808,76 +584,117 @@ - entry[5]: - set to 0? - */ -+static int -+nouveau_gpuobj_sw_new(struct nouveau_channel *chan, int class, -+ struct nouveau_gpuobj **gpuobj_ret) -+{ -+ struct drm_nouveau_private *dev_priv; -+ struct nouveau_gpuobj *gpuobj; -+ -+ if (!chan || !gpuobj_ret || *gpuobj_ret != NULL) -+ return -EINVAL; -+ dev_priv = chan->dev->dev_private; -+ -+ gpuobj = kzalloc(sizeof(*gpuobj), GFP_KERNEL); -+ if (!gpuobj) -+ return -ENOMEM; -+ gpuobj->dev = chan->dev; -+ gpuobj->engine = NVOBJ_ENGINE_SW; -+ gpuobj->class = class; -+ kref_init(&gpuobj->refcount); -+ gpuobj->cinst = 0x40; -+ -+ spin_lock(&dev_priv->ramin_lock); -+ list_add_tail(&gpuobj->list, &dev_priv->gpuobj_list); -+ spin_unlock(&dev_priv->ramin_lock); -+ *gpuobj_ret = gpuobj; -+ return 0; -+} -+ - int - nouveau_gpuobj_gr_new(struct nouveau_channel *chan, int class, - struct nouveau_gpuobj **gpuobj) - { -+ struct drm_nouveau_private *dev_priv = chan->dev->dev_private; - struct drm_device *dev = chan->dev; -- struct drm_nouveau_private *dev_priv = dev->dev_private; -+ 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) { -+ if (oc->id == class) -+ goto found; -+ } -+ -+ NV_ERROR(dev, "illegal object class: 0x%x\n", class); -+ return -EINVAL; -+ -+found: -+ if (oc->engine == NVOBJ_ENGINE_SW) -+ return nouveau_gpuobj_sw_new(chan, class, gpuobj); -+ -+ switch (oc->engine) { -+ case NVOBJ_ENGINE_GR: -+ if (dev_priv->chipset >= NV_50 && !chan->ramin_grctx) { -+ struct nouveau_pgraph_engine *pgraph = -+ &dev_priv->engine.graph; -+ -+ ret = pgraph->create_context(chan); -+ if (ret) -+ return ret; -+ } -+ break; -+ case NVOBJ_ENGINE_CRYPT: -+ if (!chan->crypt_ctx) { -+ struct nouveau_crypt_engine *pcrypt = -+ &dev_priv->engine.crypt; -+ -+ ret = pcrypt->create_context(chan); -+ if (ret) -+ return ret; -+ } -+ break; -+ } -+ - ret = nouveau_gpuobj_new(dev, chan, - nouveau_gpuobj_class_instmem_size(dev, class), - 16, - NVOBJ_FLAG_ZERO_ALLOC | NVOBJ_FLAG_ZERO_FREE, - gpuobj); - if (ret) { -- NV_ERROR(dev, "Error creating gpuobj: %d\n", ret); -+ NV_ERROR(dev, "error creating gpuobj: %d\n", ret); - return ret; - } - - if (dev_priv->card_type >= NV_50) { -- nv_wo32(dev, *gpuobj, 0, class); -- nv_wo32(dev, *gpuobj, 5, 0x00010000); -+ nv_wo32(*gpuobj, 0, class); -+ nv_wo32(*gpuobj, 20, 0x00010000); - } else { - switch (class) { - case NV_CLASS_NULL: -- nv_wo32(dev, *gpuobj, 0, 0x00001030); -- nv_wo32(dev, *gpuobj, 1, 0xFFFFFFFF); -+ nv_wo32(*gpuobj, 0, 0x00001030); -+ nv_wo32(*gpuobj, 4, 0xFFFFFFFF); - break; - default: - if (dev_priv->card_type >= NV_40) { -- nv_wo32(dev, *gpuobj, 0, class); -+ nv_wo32(*gpuobj, 0, class); - #ifdef __BIG_ENDIAN -- nv_wo32(dev, *gpuobj, 2, 0x01000000); -+ nv_wo32(*gpuobj, 8, 0x01000000); - #endif - } else { - #ifdef __BIG_ENDIAN -- nv_wo32(dev, *gpuobj, 0, class | 0x00080000); -+ nv_wo32(*gpuobj, 0, class | 0x00080000); - #else -- nv_wo32(dev, *gpuobj, 0, class); -+ nv_wo32(*gpuobj, 0, class); - #endif - } - } - } - dev_priv->engine.instmem.flush(dev); - -- (*gpuobj)->engine = NVOBJ_ENGINE_GR; -- (*gpuobj)->class = class; -- return 0; --} -- --int --nouveau_gpuobj_sw_new(struct nouveau_channel *chan, int class, -- struct nouveau_gpuobj **gpuobj_ret) --{ -- struct drm_nouveau_private *dev_priv; -- struct nouveau_gpuobj *gpuobj; -- -- if (!chan || !gpuobj_ret || *gpuobj_ret != NULL) -- return -EINVAL; -- dev_priv = chan->dev->dev_private; -- -- gpuobj = kzalloc(sizeof(*gpuobj), GFP_KERNEL); -- if (!gpuobj) -- return -ENOMEM; -- gpuobj->engine = NVOBJ_ENGINE_SW; -- gpuobj->class = class; -- -- list_add_tail(&gpuobj->list, &dev_priv->gpuobj_list); -- *gpuobj_ret = gpuobj; -+ (*gpuobj)->engine = oc->engine; -+ (*gpuobj)->class = oc->id; - return 0; - } - -@@ -886,7 +703,6 @@ - { - struct drm_device *dev = chan->dev; - struct drm_nouveau_private *dev_priv = dev->dev_private; -- struct nouveau_gpuobj *pramin = NULL; - uint32_t size; - uint32_t base; - int ret; -@@ -894,7 +710,7 @@ - NV_DEBUG(dev, "ch%d\n", chan->id); - - /* Base amount for object storage (4KiB enough?) */ -- size = 0x1000; -+ size = 0x2000; - base = 0; - - /* PGRAPH context */ -@@ -911,18 +727,16 @@ - size += 0x1000; - } - -- ret = nouveau_gpuobj_new_ref(dev, NULL, NULL, 0, size, 0x1000, 0, -- &chan->ramin); -+ ret = nouveau_gpuobj_new(dev, NULL, size, 0x1000, 0, &chan->ramin); - if (ret) { - NV_ERROR(dev, "Error allocating channel PRAMIN: %d\n", ret); - return ret; - } -- pramin = chan->ramin->gpuobj; - -- ret = drm_mm_init(&chan->ramin_heap, pramin->im_pramin->start + base, size); -+ ret = drm_mm_init(&chan->ramin_heap, base, size); - if (ret) { - NV_ERROR(dev, "Error creating PRAMIN heap: %d\n", ret); -- nouveau_gpuobj_ref_del(dev, &chan->ramin); -+ nouveau_gpuobj_ref(NULL, &chan->ramin); - return ret; - } - -@@ -939,8 +753,6 @@ - struct nouveau_gpuobj *vram = NULL, *tt = NULL; - int ret, i; - -- INIT_LIST_HEAD(&chan->ramht_refs); -- - NV_DEBUG(dev, "ch%d vram=0x%08x tt=0x%08x\n", chan->id, vram_h, tt_h); - - /* Allocate a chunk of memory for per-channel object storage */ -@@ -956,41 +768,38 @@ - * locations determined during init. - */ - if (dev_priv->card_type >= NV_50) { -- uint32_t vm_offset, pde; -+ u32 pgd_offs = (dev_priv->chipset == 0x50) ? 0x1400 : 0x0200; -+ u64 vm_vinst = chan->ramin->vinst + pgd_offs; -+ u32 vm_pinst = chan->ramin->pinst; -+ u32 pde; - -- vm_offset = (dev_priv->chipset & 0xf0) == 0x50 ? 0x1400 : 0x200; -- vm_offset += chan->ramin->gpuobj->im_pramin->start; -+ if (vm_pinst != ~0) -+ vm_pinst += pgd_offs; - -- ret = nouveau_gpuobj_new_fake(dev, vm_offset, ~0, 0x4000, -- 0, &chan->vm_pd, NULL); -+ ret = nouveau_gpuobj_new_fake(dev, vm_pinst, vm_vinst, 0x4000, -+ 0, &chan->vm_pd); - if (ret) - return ret; - for (i = 0; i < 0x4000; i += 8) { -- nv_wo32(dev, chan->vm_pd, (i+0)/4, 0x00000000); -- nv_wo32(dev, chan->vm_pd, (i+4)/4, 0xdeadcafe); -+ nv_wo32(chan->vm_pd, i + 0, 0x00000000); -+ nv_wo32(chan->vm_pd, i + 4, 0xdeadcafe); - } - -- pde = (dev_priv->vm_gart_base / (512*1024*1024)) * 2; -- ret = nouveau_gpuobj_ref_add(dev, NULL, 0, -- dev_priv->gart_info.sg_ctxdma, -- &chan->vm_gart_pt); -- if (ret) -- return ret; -- nv_wo32(dev, chan->vm_pd, pde++, -- chan->vm_gart_pt->instance | 0x03); -- nv_wo32(dev, chan->vm_pd, pde++, 0x00000000); -+ nouveau_gpuobj_ref(dev_priv->gart_info.sg_ctxdma, -+ &chan->vm_gart_pt); -+ pde = (dev_priv->vm_gart_base / (512*1024*1024)) * 8; -+ nv_wo32(chan->vm_pd, pde + 0, chan->vm_gart_pt->vinst | 3); -+ nv_wo32(chan->vm_pd, pde + 4, 0x00000000); - -- pde = (dev_priv->vm_vram_base / (512*1024*1024)) * 2; -+ pde = (dev_priv->vm_vram_base / (512*1024*1024)) * 8; - for (i = 0; i < dev_priv->vm_vram_pt_nr; i++) { -- ret = nouveau_gpuobj_ref_add(dev, NULL, 0, -- dev_priv->vm_vram_pt[i], -- &chan->vm_vram_pt[i]); -- if (ret) -- return ret; -+ nouveau_gpuobj_ref(dev_priv->vm_vram_pt[i], -+ &chan->vm_vram_pt[i]); - -- nv_wo32(dev, chan->vm_pd, pde++, -- chan->vm_vram_pt[i]->instance | 0x61); -- nv_wo32(dev, chan->vm_pd, pde++, 0x00000000); -+ nv_wo32(chan->vm_pd, pde + 0, -+ chan->vm_vram_pt[i]->vinst | 0x61); -+ nv_wo32(chan->vm_pd, pde + 4, 0x00000000); -+ pde += 8; - } - - instmem->flush(dev); -@@ -998,15 +807,17 @@ - - /* RAMHT */ - if (dev_priv->card_type < NV_50) { -- ret = nouveau_gpuobj_ref_add(dev, NULL, 0, dev_priv->ramht, -- &chan->ramht); -+ 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; -- } else { -- ret = nouveau_gpuobj_new_ref(dev, chan, chan, 0, -- 0x8000, 16, -- NVOBJ_FLAG_ZERO_ALLOC, -- &chan->ramht); -+ -+ ret = nouveau_ramht_new(dev, ramht, &chan->ramht); -+ nouveau_gpuobj_ref(NULL, &ramht); - if (ret) - return ret; - } -@@ -1023,24 +834,32 @@ - } - } else { - ret = nouveau_gpuobj_dma_new(chan, NV_CLASS_DMA_IN_MEMORY, -- 0, dev_priv->fb_available_size, -- NV_DMA_ACCESS_RW, -- NV_DMA_TARGET_VIDMEM, &vram); -+ 0, dev_priv->fb_available_size, -+ NV_DMA_ACCESS_RW, -+ NV_DMA_TARGET_VIDMEM, &vram); - if (ret) { - NV_ERROR(dev, "Error creating VRAM ctxdma: %d\n", ret); - return ret; - } - } - -- ret = nouveau_gpuobj_ref_add(dev, chan, vram_h, vram, NULL); -+ ret = nouveau_ramht_insert(chan, vram_h, vram); -+ nouveau_gpuobj_ref(NULL, &vram); - if (ret) { -- NV_ERROR(dev, "Error referencing VRAM ctxdma: %d\n", 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) { -- tt = vram; -+ ret = nouveau_gpuobj_dma_new(chan, NV_CLASS_DMA_IN_MEMORY, -+ 0, dev_priv->vm_end, -+ NV_DMA_ACCESS_RW, -+ NV_DMA_TARGET_AGP, &tt); -+ if (ret) { -+ NV_ERROR(dev, "Error creating VRAM ctxdma: %d\n", ret); -+ return ret; -+ } - } else - if (dev_priv->gart_info.type != NOUVEAU_GART_NONE) { - ret = nouveau_gpuobj_gart_dma_new(chan, 0, -@@ -1056,9 +875,10 @@ - return ret; - } - -- ret = nouveau_gpuobj_ref_add(dev, chan, tt_h, tt, NULL); -+ ret = nouveau_ramht_insert(chan, tt_h, tt); -+ nouveau_gpuobj_ref(NULL, &tt); - if (ret) { -- NV_ERROR(dev, "Error referencing TT ctxdma: %d\n", ret); -+ NV_ERROR(dev, "Error adding TT ctxdma to RAMHT: %d\n", ret); - return ret; - } - -@@ -1070,33 +890,23 @@ - { - struct drm_nouveau_private *dev_priv = chan->dev->dev_private; - struct drm_device *dev = chan->dev; -- struct list_head *entry, *tmp; -- struct nouveau_gpuobj_ref *ref; - int i; - - NV_DEBUG(dev, "ch%d\n", chan->id); - -- if (!chan->ramht_refs.next) -+ if (!chan->ramht) - return; - -- list_for_each_safe(entry, tmp, &chan->ramht_refs) { -- ref = list_entry(entry, struct nouveau_gpuobj_ref, list); -- -- nouveau_gpuobj_ref_del(dev, &ref); -- } -- -- nouveau_gpuobj_ref_del(dev, &chan->ramht); -+ nouveau_ramht_ref(NULL, &chan->ramht, chan); - -- nouveau_gpuobj_del(dev, &chan->vm_pd); -- nouveau_gpuobj_ref_del(dev, &chan->vm_gart_pt); -+ nouveau_gpuobj_ref(NULL, &chan->vm_pd); -+ nouveau_gpuobj_ref(NULL, &chan->vm_gart_pt); - for (i = 0; i < dev_priv->vm_vram_pt_nr; i++) -- nouveau_gpuobj_ref_del(dev, &chan->vm_vram_pt[i]); -+ nouveau_gpuobj_ref(NULL, &chan->vm_vram_pt[i]); - - if (chan->ramin_heap.free_stack.next) - drm_mm_takedown(&chan->ramin_heap); -- if (chan->ramin) -- nouveau_gpuobj_ref_del(dev, &chan->ramin); -- -+ nouveau_gpuobj_ref(NULL, &chan->ramin); - } - - int -@@ -1117,17 +927,17 @@ - } - - list_for_each_entry(gpuobj, &dev_priv->gpuobj_list, list) { -- if (!gpuobj->im_backing || (gpuobj->flags & NVOBJ_FLAG_FAKE)) -+ if (!gpuobj->im_backing) - continue; - -- gpuobj->im_backing_suspend = vmalloc(gpuobj->im_pramin->size); -+ gpuobj->im_backing_suspend = vmalloc(gpuobj->size); - if (!gpuobj->im_backing_suspend) { - nouveau_gpuobj_resume(dev); - return -ENOMEM; - } - -- for (i = 0; i < gpuobj->im_pramin->size / 4; i++) -- gpuobj->im_backing_suspend[i] = nv_ro32(dev, gpuobj, i); -+ for (i = 0; i < gpuobj->size; i += 4) -+ gpuobj->im_backing_suspend[i/4] = nv_ro32(gpuobj, i); - } - - return 0; -@@ -1172,8 +982,8 @@ - if (!gpuobj->im_backing_suspend) - continue; - -- for (i = 0; i < gpuobj->im_pramin->size / 4; i++) -- nv_wo32(dev, gpuobj, i, gpuobj->im_backing_suspend[i]); -+ for (i = 0; i < gpuobj->size; i += 4) -+ nv_wo32(gpuobj, i, gpuobj->im_backing_suspend[i/4]); - dev_priv->engine.instmem.flush(dev); - } - -@@ -1183,70 +993,101 @@ - int nouveau_ioctl_grobj_alloc(struct drm_device *dev, void *data, - struct drm_file *file_priv) - { -- struct drm_nouveau_private *dev_priv = dev->dev_private; - struct drm_nouveau_grobj_alloc *init = data; -- struct nouveau_pgraph_engine *pgraph = &dev_priv->engine.graph; -- struct nouveau_pgraph_object_class *grc; - struct nouveau_gpuobj *gr = NULL; - struct nouveau_channel *chan; - int ret; - -- NOUVEAU_GET_USER_CHANNEL_WITH_RETURN(init->channel, file_priv, chan); -- - if (init->handle == ~0) - return -EINVAL; - -- grc = pgraph->grclass; -- while (grc->id) { -- if (grc->id == init->class) -- break; -- grc++; -- } -+ chan = nouveau_channel_get(dev, file_priv, init->channel); -+ if (IS_ERR(chan)) -+ return PTR_ERR(chan); - -- if (!grc->id) { -- NV_ERROR(dev, "Illegal object class: 0x%x\n", init->class); -- return -EPERM; -+ if (nouveau_ramht_find(chan, init->handle)) { -+ ret = -EEXIST; -+ goto out; - } - -- if (nouveau_gpuobj_ref_find(chan, init->handle, NULL) == 0) -- return -EEXIST; -- -- if (!grc->software) -- ret = nouveau_gpuobj_gr_new(chan, grc->id, &gr); -- else -- ret = nouveau_gpuobj_sw_new(chan, grc->id, &gr); -- -+ ret = nouveau_gpuobj_gr_new(chan, init->class, &gr); - if (ret) { - NV_ERROR(dev, "Error creating object: %d (%d/0x%08x)\n", - ret, init->channel, init->handle); -- return ret; -+ goto out; - } - -- ret = nouveau_gpuobj_ref_add(dev, chan, init->handle, gr, NULL); -+ ret = nouveau_ramht_insert(chan, init->handle, gr); -+ nouveau_gpuobj_ref(NULL, &gr); - if (ret) { - NV_ERROR(dev, "Error referencing object: %d (%d/0x%08x)\n", - ret, init->channel, init->handle); -- nouveau_gpuobj_del(dev, &gr); -- return ret; - } - -- return 0; -+out: -+ nouveau_channel_put(&chan); -+ return ret; - } - - int nouveau_ioctl_gpuobj_free(struct drm_device *dev, void *data, - struct drm_file *file_priv) - { - struct drm_nouveau_gpuobj_free *objfree = data; -- struct nouveau_gpuobj_ref *ref; - struct nouveau_channel *chan; - int ret; - -- NOUVEAU_GET_USER_CHANNEL_WITH_RETURN(objfree->channel, file_priv, chan); -+ chan = nouveau_channel_get(dev, file_priv, objfree->channel); -+ if (IS_ERR(chan)) -+ return PTR_ERR(chan); - -- ret = nouveau_gpuobj_ref_find(chan, objfree->handle, &ref); -- if (ret) -- return ret; -- nouveau_gpuobj_ref_del(dev, &ref); -+ ret = nouveau_ramht_remove(chan, objfree->handle); -+ nouveau_channel_put(&chan); -+ return ret; -+} - -- return 0; -+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; -+ -+ if (gpuobj->pinst == ~0 || !dev_priv->ramin_available) { -+ u64 ptr = gpuobj->vinst + offset; -+ u32 base = ptr >> 16; -+ u32 val; -+ -+ spin_lock(&dev_priv->ramin_lock); -+ 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(&dev_priv->ramin_lock); -+ 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; -+ -+ if (gpuobj->pinst == ~0 || !dev_priv->ramin_available) { -+ u64 ptr = gpuobj->vinst + offset; -+ u32 base = ptr >> 16; -+ -+ spin_lock(&dev_priv->ramin_lock); -+ 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(&dev_priv->ramin_lock); -+ return; -+ } -+ -+ nv_wi32(dev, gpuobj->pinst + offset, val); - } -diff -Naur linux-2.6.36/drivers/gpu/drm/nouveau/nouveau_perf.c linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nouveau_perf.c ---- linux-2.6.36/drivers/gpu/drm/nouveau/nouveau_perf.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nouveau_perf.c 2010-11-05 00:40:00.000000000 +0100 -@@ -0,0 +1,205 @@ -+/* -+ * Copyright 2010 Red Hat Inc. -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included in -+ * all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR -+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -+ * OTHER DEALINGS IN THE SOFTWARE. -+ * -+ * Authors: Ben Skeggs -+ */ -+ -+#include "drmP.h" -+ -+#include "nouveau_drv.h" -+#include "nouveau_pm.h" -+ -+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; -+ 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"); -+ return; -+ } -+ -+ perf = ROMPTR(bios, bmp[0x73]); -+ if (!perf) { -+ NV_DEBUG(dev, "No memclock table pointer found.\n"); -+ return; -+ } -+ -+ switch (perf[0]) { -+ case 0x12: -+ case 0x14: -+ case 0x18: -+ use_straps = 0; -+ headerlen = 1; -+ break; -+ case 0x01: -+ use_straps = perf[1] & 1; -+ headerlen = (use_straps ? 8 : 2); -+ break; -+ default: -+ NV_WARN(dev, "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; -+ -+ sprintf(pm->perflvl[0].name, "performance_level_0"); -+ pm->perflvl[0].memory = ROM16(entry[0]) * 20; -+ pm->nr_perflvl = 1; -+} -+ -+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 bit_entry P; -+ u8 version, headerlen, recordlen, entries; -+ u8 *perf, *entry; -+ int vid, i; -+ -+ if (bios->type == NVBIOS_BIT) { -+ if (bit_table(dev, 'P', &P)) -+ return; -+ -+ if (P.version != 1 && P.version != 2) { -+ NV_WARN(dev, "unknown perf for BIT P %d\n", P.version); -+ return; -+ } -+ -+ perf = ROMPTR(bios, P.data[0]); -+ version = perf[0]; -+ headerlen = perf[1]; -+ if (version < 0x40) { -+ recordlen = perf[3] + (perf[4] * perf[5]); -+ entries = perf[2]; -+ } else { -+ recordlen = perf[2] + (perf[3] * perf[4]); -+ entries = perf[5]; -+ } -+ } else { -+ if (bios->data[bios->offset + 6] < 0x25) { -+ legacy_perf_init(dev); -+ return; -+ } -+ -+ perf = ROMPTR(bios, bios->data[bios->offset + 0x94]); -+ if (!perf) { -+ NV_DEBUG(dev, "perf table pointer invalid\n"); -+ return; -+ } -+ -+ version = perf[1]; -+ headerlen = perf[0]; -+ recordlen = perf[3]; -+ entries = perf[2]; -+ } -+ -+ entry = perf + headerlen; -+ for (i = 0; i < entries; i++) { -+ struct nouveau_pm_level *perflvl = &pm->perflvl[pm->nr_perflvl]; -+ -+ if (entry[0] == 0xff) { -+ entry += recordlen; -+ continue; -+ } -+ -+ switch (version) { -+ case 0x12: -+ case 0x13: -+ case 0x15: -+ perflvl->fanspeed = entry[55]; -+ perflvl->voltage = entry[56]; -+ perflvl->core = ROM32(entry[1]) * 10; -+ perflvl->memory = ROM32(entry[5]) * 20; -+ break; -+ case 0x21: -+ case 0x23: -+ case 0x24: -+ perflvl->fanspeed = entry[4]; -+ perflvl->voltage = entry[5]; -+ perflvl->core = ROM16(entry[6]) * 1000; -+ -+ if (dev_priv->chipset == 0x49 || -+ dev_priv->chipset == 0x4b) -+ perflvl->memory = ROM16(entry[11]) * 1000; -+ else -+ perflvl->memory = ROM16(entry[11]) * 2000; -+ -+ break; -+ case 0x25: -+ perflvl->fanspeed = entry[4]; -+ perflvl->voltage = entry[5]; -+ perflvl->core = ROM16(entry[6]) * 1000; -+ perflvl->shader = ROM16(entry[10]) * 1000; -+ perflvl->memory = ROM16(entry[12]) * 1000; -+ break; -+ case 0x30: -+ perflvl->memscript = ROM16(entry[2]); -+ case 0x35: -+ perflvl->fanspeed = entry[6]; -+ perflvl->voltage = entry[7]; -+ perflvl->core = ROM16(entry[8]) * 1000; -+ perflvl->shader = ROM16(entry[10]) * 1000; -+ perflvl->memory = ROM16(entry[12]) * 1000; -+ /*XXX: confirm on 0x35 */ -+ perflvl->unk05 = ROM16(entry[16]) * 1000; -+ break; -+ case 0x40: -+#define subent(n) entry[perf[2] + ((n) * perf[3])] -+ perflvl->fanspeed = 0; /*XXX*/ -+ perflvl->voltage = entry[2]; -+ perflvl->core = (ROM16(subent(0)) & 0xfff) * 1000; -+ perflvl->shader = (ROM16(subent(1)) & 0xfff) * 1000; -+ perflvl->memory = (ROM16(subent(2)) & 0xfff) * 1000; -+ break; -+ } -+ -+ /* make sure vid is valid */ -+ if (pm->voltage.supported && perflvl->voltage) { -+ vid = nouveau_volt_vid_lookup(dev, perflvl->voltage); -+ if (vid < 0) { -+ NV_DEBUG(dev, "drop perflvl %d, bad vid\n", i); -+ entry += recordlen; -+ continue; -+ } -+ } -+ -+ snprintf(perflvl->name, sizeof(perflvl->name), -+ "performance_level_%d", i); -+ perflvl->id = i; -+ pm->nr_perflvl++; -+ -+ entry += recordlen; -+ } -+} -+ -+void -+nouveau_perf_fini(struct drm_device *dev) -+{ -+} -diff -Naur linux-2.6.36/drivers/gpu/drm/nouveau/nouveau_pm.c linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nouveau_pm.c ---- linux-2.6.36/drivers/gpu/drm/nouveau/nouveau_pm.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nouveau_pm.c 2010-11-05 00:40:00.000000000 +0100 -@@ -0,0 +1,553 @@ -+/* -+ * Copyright 2010 Red Hat Inc. -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included in -+ * all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR -+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -+ * OTHER DEALINGS IN THE SOFTWARE. -+ * -+ * Authors: Ben Skeggs -+ */ -+ -+#include "drmP.h" -+ -+#include "nouveau_drv.h" -+#include "nouveau_pm.h" -+ -+#ifdef CONFIG_ACPI -+#include -+#endif -+#include -+#include -+#include -+ -+static int -+nouveau_pm_clock_set(struct drm_device *dev, struct nouveau_pm_level *perflvl, -+ u8 id, u32 khz) -+{ -+ struct drm_nouveau_private *dev_priv = dev->dev_private; -+ struct nouveau_pm_engine *pm = &dev_priv->engine.pm; -+ void *pre_state; -+ -+ if (khz == 0) -+ return 0; -+ -+ pre_state = pm->clock_pre(dev, perflvl, id, khz); -+ if (IS_ERR(pre_state)) -+ return PTR_ERR(pre_state); -+ -+ if (pre_state) -+ pm->clock_set(dev, pre_state); -+ return 0; -+} -+ -+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; -+ int ret; -+ -+ if (perflvl == pm->cur) -+ return 0; -+ -+ if (pm->voltage.supported && pm->voltage_set && perflvl->voltage) { -+ ret = pm->voltage_set(dev, perflvl->voltage); -+ if (ret) { -+ NV_ERROR(dev, "voltage_set %d failed: %d\n", -+ perflvl->voltage, ret); -+ } -+ } -+ -+ nouveau_pm_clock_set(dev, perflvl, PLL_CORE, perflvl->core); -+ nouveau_pm_clock_set(dev, perflvl, PLL_SHADER, perflvl->shader); -+ nouveau_pm_clock_set(dev, perflvl, PLL_MEMORY, perflvl->memory); -+ nouveau_pm_clock_set(dev, perflvl, PLL_UNK05, perflvl->unk05); -+ -+ pm->cur = perflvl; -+ return 0; -+} -+ -+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_level *perflvl = NULL; -+ -+ /* safety precaution, for now */ -+ if (nouveau_perflvl_wr != 7777) -+ return -EPERM; -+ -+ if (!pm->clock_set) -+ return -EINVAL; -+ -+ if (!strncmp(profile, "boot", 4)) -+ perflvl = &pm->boot; -+ else { -+ int pl = simple_strtol(profile, NULL, 10); -+ int i; -+ -+ for (i = 0; i < pm->nr_perflvl; i++) { -+ if (pm->perflvl[i].id == pl) { -+ perflvl = &pm->perflvl[i]; -+ break; -+ } -+ } -+ -+ if (!perflvl) -+ return -EINVAL; -+ } -+ -+ NV_INFO(dev, "setting performance level: %s\n", profile); -+ return nouveau_pm_perflvl_set(dev, perflvl); -+} -+ -+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; -+ int ret; -+ -+ if (!pm->clock_get) -+ return -EINVAL; -+ -+ memset(perflvl, 0, sizeof(*perflvl)); -+ -+ ret = pm->clock_get(dev, PLL_CORE); -+ if (ret > 0) -+ perflvl->core = ret; -+ -+ ret = pm->clock_get(dev, PLL_MEMORY); -+ if (ret > 0) -+ perflvl->memory = ret; -+ -+ ret = pm->clock_get(dev, PLL_SHADER); -+ if (ret > 0) -+ perflvl->shader = ret; -+ -+ ret = pm->clock_get(dev, PLL_UNK05); -+ if (ret > 0) -+ perflvl->unk05 = ret; -+ -+ if (pm->voltage.supported && pm->voltage_get) { -+ ret = pm->voltage_get(dev); -+ if (ret > 0) -+ perflvl->voltage = ret; -+ } -+ -+ return 0; -+} -+ -+static void -+nouveau_pm_perflvl_info(struct nouveau_pm_level *perflvl, char *ptr, int len) -+{ -+ char c[16], s[16], v[16], f[16]; -+ -+ c[0] = '\0'; -+ if (perflvl->core) -+ snprintf(c, sizeof(c), " core %dMHz", perflvl->core / 1000); -+ -+ s[0] = '\0'; -+ if (perflvl->shader) -+ snprintf(s, sizeof(s), " shader %dMHz", perflvl->shader / 1000); -+ -+ v[0] = '\0'; -+ if (perflvl->voltage) -+ snprintf(v, sizeof(v), " voltage %dmV", perflvl->voltage * 10); -+ -+ f[0] = '\0'; -+ if (perflvl->fanspeed) -+ snprintf(f, sizeof(f), " fanspeed %d%%", perflvl->fanspeed); -+ -+ snprintf(ptr, len, "memory %dMHz%s%s%s%s\n", perflvl->memory / 1000, -+ c, s, v, f); -+} -+ -+static ssize_t -+nouveau_pm_get_perflvl_info(struct device *d, -+ struct device_attribute *a, char *buf) -+{ -+ struct nouveau_pm_level *perflvl = (struct nouveau_pm_level *)a; -+ char *ptr = buf; -+ int len = PAGE_SIZE; -+ -+ snprintf(ptr, len, "%d: ", perflvl->id); -+ ptr += strlen(buf); -+ len -= strlen(buf); -+ -+ nouveau_pm_perflvl_info(perflvl, ptr, len); -+ return strlen(buf); -+} -+ -+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_level cur; -+ int len = PAGE_SIZE, ret; -+ char *ptr = buf; -+ -+ if (!pm->cur) -+ snprintf(ptr, len, "setting: boot\n"); -+ else if (pm->cur == &pm->boot) -+ snprintf(ptr, len, "setting: boot\nc: "); -+ else -+ snprintf(ptr, len, "setting: static %d\nc: ", pm->cur->id); -+ ptr += strlen(buf); -+ len -= strlen(buf); -+ -+ ret = nouveau_pm_perflvl_get(dev, &cur); -+ if (ret == 0) -+ nouveau_pm_perflvl_info(&cur, ptr, len); -+ return strlen(buf); -+} -+ -+static ssize_t -+nouveau_pm_set_perflvl(struct device *d, struct device_attribute *a, -+ const char *buf, size_t count) -+{ -+ struct drm_device *dev = pci_get_drvdata(to_pci_dev(d)); -+ int ret; -+ -+ ret = nouveau_pm_profile_set(dev, buf); -+ if (ret) -+ return ret; -+ return strlen(buf); -+} -+ -+static DEVICE_ATTR(performance_level, S_IRUGO | S_IWUSR, -+ nouveau_pm_get_perflvl, nouveau_pm_set_perflvl); -+ -+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 device *d = &dev->pdev->dev; -+ int ret, i; -+ -+ ret = device_create_file(d, &dev_attr_performance_level); -+ if (ret) -+ return ret; -+ -+ for (i = 0; i < pm->nr_perflvl; i++) { -+ struct nouveau_pm_level *perflvl = &pm->perflvl[i]; -+ -+ perflvl->dev_attr.attr.name = perflvl->name; -+ perflvl->dev_attr.attr.mode = S_IRUGO; -+ perflvl->dev_attr.show = nouveau_pm_get_perflvl_info; -+ perflvl->dev_attr.store = NULL; -+ sysfs_attr_init(&perflvl->dev_attr.attr); -+ -+ ret = device_create_file(d, &perflvl->dev_attr); -+ if (ret) { -+ NV_ERROR(dev, "failed pervlvl %d sysfs: %d\n", -+ perflvl->id, i); -+ perflvl->dev_attr.attr.name = NULL; -+ nouveau_pm_fini(dev); -+ return ret; -+ } -+ } -+ -+ return 0; -+} -+ -+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 device *d = &dev->pdev->dev; -+ int i; -+ -+ device_remove_file(d, &dev_attr_performance_level); -+ for (i = 0; i < pm->nr_perflvl; i++) { -+ struct nouveau_pm_level *pl = &pm->perflvl[i]; -+ -+ if (!pl->dev_attr.attr.name) -+ break; -+ -+ device_remove_file(d, &pl->dev_attr); -+ } -+} -+ -+#ifdef CONFIG_HWMON -+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; -+ -+ return snprintf(buf, PAGE_SIZE, "%d\n", pm->temp_get(dev)*1000); -+} -+static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, nouveau_hwmon_show_temp, -+ NULL, 0); -+ -+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_threshold_temp *temp = &pm->threshold_temp; -+ -+ return snprintf(buf, PAGE_SIZE, "%d\n", temp->down_clock*1000); -+} -+static ssize_t -+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_threshold_temp *temp = &pm->threshold_temp; -+ long value; -+ -+ if (strict_strtol(buf, 10, &value) == -EINVAL) -+ return count; -+ -+ temp->down_clock = value/1000; -+ -+ nouveau_temp_safety_checks(dev); -+ -+ return count; -+} -+static SENSOR_DEVICE_ATTR(temp1_max, S_IRUGO | S_IWUSR, nouveau_hwmon_max_temp, -+ nouveau_hwmon_set_max_temp, -+ 0); -+ -+static ssize_t -+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_threshold_temp *temp = &pm->threshold_temp; -+ -+ return snprintf(buf, PAGE_SIZE, "%d\n", temp->critical*1000); -+} -+static ssize_t -+nouveau_hwmon_set_critical_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_threshold_temp *temp = &pm->threshold_temp; -+ long value; -+ -+ if (strict_strtol(buf, 10, &value) == -EINVAL) -+ return count; -+ -+ temp->critical = value/1000; -+ -+ nouveau_temp_safety_checks(dev); -+ -+ return count; -+} -+static SENSOR_DEVICE_ATTR(temp1_crit, S_IRUGO | S_IWUSR, -+ nouveau_hwmon_critical_temp, -+ nouveau_hwmon_set_critical_temp, -+ 0); -+ -+static ssize_t nouveau_hwmon_show_name(struct device *dev, -+ struct device_attribute *attr, -+ char *buf) -+{ -+ return sprintf(buf, "nouveau\n"); -+} -+static SENSOR_DEVICE_ATTR(name, S_IRUGO, nouveau_hwmon_show_name, NULL, 0); -+ -+static ssize_t nouveau_hwmon_show_update_rate(struct device *dev, -+ struct device_attribute *attr, -+ char *buf) -+{ -+ return sprintf(buf, "1000\n"); -+} -+static SENSOR_DEVICE_ATTR(update_rate, S_IRUGO, -+ nouveau_hwmon_show_update_rate, -+ NULL, 0); -+ -+static struct attribute *hwmon_attributes[] = { -+ &sensor_dev_attr_temp1_input.dev_attr.attr, -+ &sensor_dev_attr_temp1_max.dev_attr.attr, -+ &sensor_dev_attr_temp1_crit.dev_attr.attr, -+ &sensor_dev_attr_name.dev_attr.attr, -+ &sensor_dev_attr_update_rate.dev_attr.attr, -+ NULL -+}; -+ -+static const struct attribute_group hwmon_attrgroup = { -+ .attrs = hwmon_attributes, -+}; -+#endif -+ -+static int -+nouveau_hwmon_init(struct drm_device *dev) -+{ -+#ifdef CONFIG_HWMON -+ struct drm_nouveau_private *dev_priv = dev->dev_private; -+ struct nouveau_pm_engine *pm = &dev_priv->engine.pm; -+ struct device *hwmon_dev; -+ int ret; -+ -+ if (!pm->temp_get) -+ return -ENODEV; -+ -+ 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); -+ return ret; -+ } -+ dev_set_drvdata(hwmon_dev, dev); -+ ret = sysfs_create_group(&hwmon_dev->kobj, -+ &hwmon_attrgroup); -+ if (ret) { -+ NV_ERROR(dev, -+ "Unable to create hwmon sysfs file: %d\n", ret); -+ hwmon_device_unregister(hwmon_dev); -+ return ret; -+ } -+ -+ pm->hwmon = hwmon_dev; -+#endif -+ return 0; -+} -+ -+static void -+nouveau_hwmon_fini(struct drm_device *dev) -+{ -+#ifdef CONFIG_HWMON -+ struct drm_nouveau_private *dev_priv = dev->dev_private; -+ struct nouveau_pm_engine *pm = &dev_priv->engine.pm; -+ -+ if (pm->hwmon) { -+ sysfs_remove_group(&pm->hwmon->kobj, &hwmon_attrgroup); -+ hwmon_device_unregister(pm->hwmon); -+ } -+#endif -+} -+ -+#ifdef CONFIG_ACPI -+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 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"); -+ } -+ -+ return NOTIFY_OK; -+} -+#endif -+ -+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; -+ char info[256]; -+ int ret, i; -+ -+ nouveau_volt_init(dev); -+ nouveau_perf_init(dev); -+ nouveau_temp_init(dev); -+ nouveau_mem_timing_init(dev); -+ -+ NV_INFO(dev, "%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); -+ } -+ -+ /* determine current ("boot") performance level */ -+ ret = nouveau_pm_perflvl_get(dev, &pm->boot); -+ if (ret == 0) { -+ pm->cur = &pm->boot; -+ -+ nouveau_pm_perflvl_info(&pm->boot, info, sizeof(info)); -+ NV_INFO(dev, "c: %s", info); -+ } -+ -+ /* switch performance levels now if requested */ -+ if (nouveau_perflvl != NULL) { -+ ret = nouveau_pm_profile_set(dev, nouveau_perflvl); -+ if (ret) { -+ NV_ERROR(dev, "error setting perflvl \"%s\": %d\n", -+ nouveau_perflvl, ret); -+ } -+ } -+ -+ nouveau_sysfs_init(dev); -+ nouveau_hwmon_init(dev); -+#ifdef CONFIG_ACPI -+ pm->acpi_nb.notifier_call = nouveau_pm_acpi_event; -+ register_acpi_notifier(&pm->acpi_nb); -+#endif -+ -+ return 0; -+} -+ -+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; -+ -+ if (pm->cur != &pm->boot) -+ nouveau_pm_perflvl_set(dev, &pm->boot); -+ -+ nouveau_mem_timing_fini(dev); -+ nouveau_temp_fini(dev); -+ nouveau_perf_fini(dev); -+ nouveau_volt_fini(dev); -+ -+#ifdef CONFIG_ACPI -+ unregister_acpi_notifier(&pm->acpi_nb); -+#endif -+ nouveau_hwmon_fini(dev); -+ nouveau_sysfs_fini(dev); -+} -+ -+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_level *perflvl; -+ -+ if (pm->cur == &pm->boot) -+ return; -+ -+ perflvl = pm->cur; -+ pm->cur = &pm->boot; -+ nouveau_pm_perflvl_set(dev, perflvl); -+} -diff -Naur linux-2.6.36/drivers/gpu/drm/nouveau/nouveau_pm.h linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nouveau_pm.h ---- linux-2.6.36/drivers/gpu/drm/nouveau/nouveau_pm.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nouveau_pm.h 2010-11-05 00:40:00.000000000 +0100 -@@ -0,0 +1,74 @@ -+/* -+ * 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_PM_H__ -+#define __NOUVEAU_PM_H__ -+ -+/* nouveau_pm.c */ -+int nouveau_pm_init(struct drm_device *dev); -+void nouveau_pm_fini(struct drm_device *dev); -+void nouveau_pm_resume(struct drm_device *dev); -+ -+/* nouveau_volt.c */ -+void nouveau_volt_init(struct drm_device *); -+void nouveau_volt_fini(struct drm_device *); -+int nouveau_volt_vid_lookup(struct drm_device *, int voltage); -+int nouveau_volt_lvl_lookup(struct drm_device *, int vid); -+int nouveau_voltage_gpio_get(struct drm_device *); -+int nouveau_voltage_gpio_set(struct drm_device *, int voltage); -+ -+/* nouveau_perf.c */ -+void nouveau_perf_init(struct drm_device *); -+void nouveau_perf_fini(struct drm_device *); -+ -+/* nouveau_mem.c */ -+void nouveau_mem_timing_init(struct drm_device *); -+void nouveau_mem_timing_fini(struct drm_device *); -+ -+/* nv04_pm.c */ -+int nv04_pm_clock_get(struct drm_device *, u32 id); -+void *nv04_pm_clock_pre(struct drm_device *, struct nouveau_pm_level *, -+ u32 id, int khz); -+void nv04_pm_clock_set(struct drm_device *, void *); -+ -+/* nv50_pm.c */ -+int nv50_pm_clock_get(struct drm_device *, u32 id); -+void *nv50_pm_clock_pre(struct drm_device *, struct nouveau_pm_level *, -+ u32 id, int khz); -+void nv50_pm_clock_set(struct drm_device *, void *); -+ -+/* nva3_pm.c */ -+int nva3_pm_clock_get(struct drm_device *, u32 id); -+void *nva3_pm_clock_pre(struct drm_device *, struct nouveau_pm_level *, -+ u32 id, int khz); -+void nva3_pm_clock_set(struct drm_device *, void *); -+ -+/* nouveau_temp.c */ -+void nouveau_temp_init(struct drm_device *dev); -+void nouveau_temp_fini(struct drm_device *dev); -+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); -+ -+#endif -diff -Naur linux-2.6.36/drivers/gpu/drm/nouveau/nouveau_ramht.c linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nouveau_ramht.c ---- linux-2.6.36/drivers/gpu/drm/nouveau/nouveau_ramht.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nouveau_ramht.c 2010-11-05 00:40:00.000000000 +0100 -@@ -0,0 +1,307 @@ -+/* -+ * Copyright 2010 Red Hat Inc. -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included in -+ * all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR -+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -+ * OTHER DEALINGS IN THE SOFTWARE. -+ * -+ * Authors: Ben Skeggs -+ */ -+ -+#include "drmP.h" -+ -+#include "nouveau_drv.h" -+#include "nouveau_ramht.h" -+ -+static u32 -+nouveau_ramht_hash_handle(struct nouveau_channel *chan, 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) { -+ 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); -+ 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) -+{ -+ 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; -+ 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->cinst >> 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->cinst >> 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) | chan->id; -+ } else { -+ ctx = (gpuobj->cinst >> 4) | -+ ((gpuobj->engine << -+ NV40_RAMHT_CONTEXT_ENGINE_SHIFT)); -+ } -+ } -+ -+ spin_lock_irqsave(&chan->ramht->lock, flags); -+ list_add(&entry->head, &chan->ramht->entries); -+ -+ co = ho = nouveau_ramht_hash_handle(chan, 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); -+ nv_wo32(ramht, co + 0, handle); -+ nv_wo32(ramht, co + 4, ctx); -+ -+ spin_unlock_irqrestore(&chan->ramht->lock, flags); -+ instmem->flush(dev); -+ return 0; -+ } -+ 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) -+ 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 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; -+ -+ 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); -+ instmem->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) -+{ -+ 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_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; -+} -+ -+int -+nouveau_ramht_new(struct drm_device *dev, struct nouveau_gpuobj *gpuobj, -+ struct nouveau_ramht **pramht) -+{ -+ struct nouveau_ramht *ramht; -+ -+ 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); -+ -+ *pramht = ramht; -+ return 0; -+} -+ -+static void -+nouveau_ramht_del(struct kref *ref) -+{ -+ struct nouveau_ramht *ramht = -+ container_of(ref, struct nouveau_ramht, refcount); -+ -+ nouveau_gpuobj_ref(NULL, &ramht->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; -+} -diff -Naur linux-2.6.36/drivers/gpu/drm/nouveau/nouveau_ramht.h linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nouveau_ramht.h ---- linux-2.6.36/drivers/gpu/drm/nouveau/nouveau_ramht.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nouveau_ramht.h 2010-11-05 00:40:00.000000000 +0100 -@@ -0,0 +1,55 @@ -+/* -+ * 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; -+}; -+ -+struct nouveau_ramht { -+ struct drm_device *dev; -+ struct kref refcount; -+ spinlock_t lock; -+ struct nouveau_gpuobj *gpuobj; -+ struct list_head entries; -+ 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); -+ -+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); -+ -+#endif -diff -Naur linux-2.6.36/drivers/gpu/drm/nouveau/nouveau_reg.h linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nouveau_reg.h ---- linux-2.6.36/drivers/gpu/drm/nouveau/nouveau_reg.h 2010-10-20 22:30:22.000000000 +0200 -+++ linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nouveau_reg.h 2010-11-05 00:40:00.000000000 +0100 -@@ -45,6 +45,11 @@ - # define NV04_PFB_REF_CMD_REFRESH (1 << 0) - #define NV04_PFB_PRE 0x001002d4 - # define NV04_PFB_PRE_CMD_PRECHARGE (1 << 0) -+#define NV20_PFB_ZCOMP(i) (0x00100300 + 4*(i)) -+# define NV20_PFB_ZCOMP_MODE_32 (4 << 24) -+# define NV20_PFB_ZCOMP_EN (1 << 31) -+# define NV25_PFB_ZCOMP_MODE_16 (1 << 20) -+# define NV25_PFB_ZCOMP_MODE_32 (2 << 20) - #define NV10_PFB_CLOSE_PAGE2 0x0010033c - #define NV04_PFB_SCRAMBLE(i) (0x00100400 + 4 * (i)) - #define NV40_PFB_TILE(i) (0x00100600 + (i*16)) -@@ -332,6 +337,7 @@ - #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 -@@ -378,6 +384,7 @@ - #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)) -@@ -551,6 +558,8 @@ - #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 -@@ -712,31 +721,32 @@ - #define NV50_PDISPLAY_INTR_1_CLK_UNK10 0x00000010 - #define NV50_PDISPLAY_INTR_1_CLK_UNK20 0x00000020 - #define NV50_PDISPLAY_INTR_1_CLK_UNK40 0x00000040 --#define NV50_PDISPLAY_INTR_EN 0x0061002c --#define NV50_PDISPLAY_INTR_EN_VBLANK_CRTC 0x0000000c --#define NV50_PDISPLAY_INTR_EN_VBLANK_CRTC_(n) (1 << ((n) + 2)) --#define NV50_PDISPLAY_INTR_EN_VBLANK_CRTC_0 0x00000004 --#define NV50_PDISPLAY_INTR_EN_VBLANK_CRTC_1 0x00000008 --#define NV50_PDISPLAY_INTR_EN_CLK_UNK10 0x00000010 --#define NV50_PDISPLAY_INTR_EN_CLK_UNK20 0x00000020 --#define NV50_PDISPLAY_INTR_EN_CLK_UNK40 0x00000040 -+#define NV50_PDISPLAY_INTR_EN_0 0x00610028 -+#define NV50_PDISPLAY_INTR_EN_1 0x0061002c -+#define NV50_PDISPLAY_INTR_EN_1_VBLANK_CRTC 0x0000000c -+#define NV50_PDISPLAY_INTR_EN_1_VBLANK_CRTC_(n) (1 << ((n) + 2)) -+#define NV50_PDISPLAY_INTR_EN_1_VBLANK_CRTC_0 0x00000004 -+#define NV50_PDISPLAY_INTR_EN_1_VBLANK_CRTC_1 0x00000008 -+#define NV50_PDISPLAY_INTR_EN_1_CLK_UNK10 0x00000010 -+#define NV50_PDISPLAY_INTR_EN_1_CLK_UNK20 0x00000020 -+#define NV50_PDISPLAY_INTR_EN_1_CLK_UNK40 0x00000040 - #define NV50_PDISPLAY_UNK30_CTRL 0x00610030 - #define NV50_PDISPLAY_UNK30_CTRL_UPDATE_VCLK0 0x00000200 - #define NV50_PDISPLAY_UNK30_CTRL_UPDATE_VCLK1 0x00000400 - #define NV50_PDISPLAY_UNK30_CTRL_PENDING 0x80000000 --#define NV50_PDISPLAY_TRAPPED_ADDR 0x00610080 --#define NV50_PDISPLAY_TRAPPED_DATA 0x00610084 --#define NV50_PDISPLAY_CHANNEL_STAT(i) ((i) * 0x10 + 0x00610200) --#define NV50_PDISPLAY_CHANNEL_STAT_DMA 0x00000010 --#define NV50_PDISPLAY_CHANNEL_STAT_DMA_DISABLED 0x00000000 --#define NV50_PDISPLAY_CHANNEL_STAT_DMA_ENABLED 0x00000010 --#define NV50_PDISPLAY_CHANNEL_DMA_CB(i) ((i) * 0x10 + 0x00610204) --#define NV50_PDISPLAY_CHANNEL_DMA_CB_LOCATION 0x00000002 --#define NV50_PDISPLAY_CHANNEL_DMA_CB_LOCATION_VRAM 0x00000000 --#define NV50_PDISPLAY_CHANNEL_DMA_CB_LOCATION_SYSTEM 0x00000002 --#define NV50_PDISPLAY_CHANNEL_DMA_CB_VALID 0x00000001 --#define NV50_PDISPLAY_CHANNEL_UNK2(i) ((i) * 0x10 + 0x00610208) --#define NV50_PDISPLAY_CHANNEL_UNK3(i) ((i) * 0x10 + 0x0061020c) -+#define NV50_PDISPLAY_TRAPPED_ADDR(i) ((i) * 0x08 + 0x00610080) -+#define NV50_PDISPLAY_TRAPPED_DATA(i) ((i) * 0x08 + 0x00610084) -+#define NV50_PDISPLAY_EVO_CTRL(i) ((i) * 0x10 + 0x00610200) -+#define NV50_PDISPLAY_EVO_CTRL_DMA 0x00000010 -+#define NV50_PDISPLAY_EVO_CTRL_DMA_DISABLED 0x00000000 -+#define NV50_PDISPLAY_EVO_CTRL_DMA_ENABLED 0x00000010 -+#define NV50_PDISPLAY_EVO_DMA_CB(i) ((i) * 0x10 + 0x00610204) -+#define NV50_PDISPLAY_EVO_DMA_CB_LOCATION 0x00000002 -+#define NV50_PDISPLAY_EVO_DMA_CB_LOCATION_VRAM 0x00000000 -+#define NV50_PDISPLAY_EVO_DMA_CB_LOCATION_SYSTEM 0x00000002 -+#define NV50_PDISPLAY_EVO_DMA_CB_VALID 0x00000001 -+#define NV50_PDISPLAY_EVO_UNK2(i) ((i) * 0x10 + 0x00610208) -+#define NV50_PDISPLAY_EVO_HASH_TAG(i) ((i) * 0x10 + 0x0061020c) - - #define NV50_PDISPLAY_CURSOR 0x00610270 - #define NV50_PDISPLAY_CURSOR_CURSOR_CTRL2(i) ((i) * 0x10 + 0x00610270) -@@ -744,15 +754,11 @@ - #define NV50_PDISPLAY_CURSOR_CURSOR_CTRL2_STATUS 0x00030000 - #define NV50_PDISPLAY_CURSOR_CURSOR_CTRL2_STATUS_ACTIVE 0x00010000 - --#define NV50_PDISPLAY_CTRL_STATE 0x00610300 --#define NV50_PDISPLAY_CTRL_STATE_PENDING 0x80000000 --#define NV50_PDISPLAY_CTRL_STATE_METHOD 0x00001ffc --#define NV50_PDISPLAY_CTRL_STATE_ENABLE 0x00000001 --#define NV50_PDISPLAY_CTRL_VAL 0x00610304 --#define NV50_PDISPLAY_UNK_380 0x00610380 --#define NV50_PDISPLAY_RAM_AMOUNT 0x00610384 --#define NV50_PDISPLAY_UNK_388 0x00610388 --#define NV50_PDISPLAY_UNK_38C 0x0061038c -+#define NV50_PDISPLAY_PIO_CTRL 0x00610300 -+#define NV50_PDISPLAY_PIO_CTRL_PENDING 0x80000000 -+#define NV50_PDISPLAY_PIO_CTRL_MTHD 0x00001ffc -+#define NV50_PDISPLAY_PIO_CTRL_ENABLED 0x00000001 -+#define NV50_PDISPLAY_PIO_DATA 0x00610304 - - #define NV50_PDISPLAY_CRTC_P(i, r) ((i) * 0x540 + NV50_PDISPLAY_CRTC_##r) - #define NV50_PDISPLAY_CRTC_C(i, r) (4 + (i) * 0x540 + NV50_PDISPLAY_CRTC_##r) -@@ -785,15 +791,12 @@ - #define NV50_PDISPLAY_DAC_MODE_CTRL_C(i) (0x00610b5c + (i) * 0x8) - #define NV50_PDISPLAY_SOR_MODE_CTRL_P(i) (0x00610b70 + (i) * 0x8) - #define NV50_PDISPLAY_SOR_MODE_CTRL_C(i) (0x00610b74 + (i) * 0x8) -+#define NV50_PDISPLAY_EXT_MODE_CTRL_P(i) (0x00610b80 + (i) * 0x8) -+#define NV50_PDISPLAY_EXT_MODE_CTRL_C(i) (0x00610b84 + (i) * 0x8) - #define NV50_PDISPLAY_DAC_MODE_CTRL2_P(i) (0x00610bdc + (i) * 0x8) - #define NV50_PDISPLAY_DAC_MODE_CTRL2_C(i) (0x00610be0 + (i) * 0x8) -- - #define NV90_PDISPLAY_SOR_MODE_CTRL_P(i) (0x00610794 + (i) * 0x8) - #define NV90_PDISPLAY_SOR_MODE_CTRL_C(i) (0x00610798 + (i) * 0x8) --#define NV90_PDISPLAY_DAC_MODE_CTRL_P(i) (0x00610b58 + (i) * 0x8) --#define NV90_PDISPLAY_DAC_MODE_CTRL_C(i) (0x00610b5c + (i) * 0x8) --#define NV90_PDISPLAY_DAC_MODE_CTRL2_P(i) (0x00610b80 + (i) * 0x8) --#define NV90_PDISPLAY_DAC_MODE_CTRL2_C(i) (0x00610b84 + (i) * 0x8) - - #define NV50_PDISPLAY_CRTC_CLK 0x00614000 - #define NV50_PDISPLAY_CRTC_CLK_CTRL1(i) ((i) * 0x800 + 0x614100) -diff -Naur linux-2.6.36/drivers/gpu/drm/nouveau/nouveau_sgdma.c linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nouveau_sgdma.c ---- linux-2.6.36/drivers/gpu/drm/nouveau/nouveau_sgdma.c 2010-10-20 22:30:22.000000000 +0200 -+++ linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nouveau_sgdma.c 2010-11-05 00:40:00.000000000 +0100 -@@ -95,9 +95,9 @@ - struct nouveau_gpuobj *gpuobj = dev_priv->gart_info.sg_ctxdma; - unsigned i, j, pte; - -- NV_DEBUG(dev, "pg=0x%lx\n", mem->mm_node->start); -+ NV_DEBUG(dev, "pg=0x%lx\n", mem->start); - -- pte = nouveau_sgdma_pte(nvbe->dev, mem->mm_node->start << PAGE_SHIFT); -+ pte = nouveau_sgdma_pte(nvbe->dev, mem->start << PAGE_SHIFT); - nvbe->pte_start = pte; - for (i = 0; i < nvbe->nr_pages; i++) { - dma_addr_t dma_offset = nvbe->pages[i]; -@@ -105,11 +105,13 @@ - uint32_t offset_h = upper_32_bits(dma_offset); - - for (j = 0; j < PAGE_SIZE / NV_CTXDMA_PAGE_SIZE; j++) { -- if (dev_priv->card_type < NV_50) -- nv_wo32(dev, gpuobj, pte++, offset_l | 3); -- else { -- nv_wo32(dev, gpuobj, pte++, offset_l | 0x21); -- nv_wo32(dev, gpuobj, pte++, offset_h & 0xff); -+ if (dev_priv->card_type < NV_50) { -+ nv_wo32(gpuobj, (pte * 4) + 0, offset_l | 3); -+ pte += 1; -+ } else { -+ nv_wo32(gpuobj, (pte * 4) + 0, offset_l | 0x21); -+ nv_wo32(gpuobj, (pte * 4) + 4, offset_h & 0xff); -+ pte += 2; - } - - dma_offset += NV_CTXDMA_PAGE_SIZE; -@@ -118,8 +120,8 @@ - dev_priv->engine.instmem.flush(nvbe->dev); - - if (dev_priv->card_type == NV_50) { -- nv50_vm_flush(dev, 5); /* PGRAPH */ -- nv50_vm_flush(dev, 0); /* PFIFO */ -+ dev_priv->engine.fifo.tlb_flush(dev); -+ dev_priv->engine.graph.tlb_flush(dev); - } - - nvbe->bound = true; -@@ -145,11 +147,13 @@ - dma_addr_t dma_offset = dev_priv->gart_info.sg_dummy_bus; - - for (j = 0; j < PAGE_SIZE / NV_CTXDMA_PAGE_SIZE; j++) { -- if (dev_priv->card_type < NV_50) -- nv_wo32(dev, gpuobj, pte++, dma_offset | 3); -- else { -- nv_wo32(dev, gpuobj, pte++, dma_offset | 0x21); -- nv_wo32(dev, gpuobj, pte++, 0x00000000); -+ if (dev_priv->card_type < NV_50) { -+ nv_wo32(gpuobj, (pte * 4) + 0, dma_offset | 3); -+ pte += 1; -+ } else { -+ nv_wo32(gpuobj, (pte * 4) + 0, 0x00000000); -+ nv_wo32(gpuobj, (pte * 4) + 4, 0x00000000); -+ pte += 2; - } - - dma_offset += NV_CTXDMA_PAGE_SIZE; -@@ -158,8 +162,8 @@ - dev_priv->engine.instmem.flush(nvbe->dev); - - if (dev_priv->card_type == NV_50) { -- nv50_vm_flush(dev, 5); -- nv50_vm_flush(dev, 0); -+ dev_priv->engine.fifo.tlb_flush(dev); -+ dev_priv->engine.graph.tlb_flush(dev); - } - - nvbe->bound = false; -@@ -220,7 +224,11 @@ - int i, ret; - - if (dev_priv->card_type < NV_50) { -- aper_size = (64 * 1024 * 1024); -+ if(dev_priv->ramin_rsvd_vram < 2 * 1024 * 1024) -+ aper_size = 64 * 1024 * 1024; -+ else -+ aper_size = 512 * 1024 * 1024; -+ - obj_size = (aper_size >> NV_CTXDMA_PAGE_SHIFT) * 4; - obj_size += 8; /* ctxdma header */ - } else { -@@ -230,7 +238,6 @@ - } - - ret = nouveau_gpuobj_new(dev, NULL, obj_size, 16, -- NVOBJ_FLAG_ALLOW_NO_REFS | - NVOBJ_FLAG_ZERO_ALLOC | - NVOBJ_FLAG_ZERO_FREE, &gpuobj); - if (ret) { -@@ -239,9 +246,9 @@ - } - - dev_priv->gart_info.sg_dummy_page = -- alloc_page(GFP_KERNEL|__GFP_DMA32); -+ alloc_page(GFP_KERNEL|__GFP_DMA32|__GFP_ZERO); - if (!dev_priv->gart_info.sg_dummy_page) { -- nouveau_gpuobj_del(dev, &gpuobj); -+ nouveau_gpuobj_ref(NULL, &gpuobj); - return -ENOMEM; - } - -@@ -250,29 +257,34 @@ - pci_map_page(pdev, dev_priv->gart_info.sg_dummy_page, 0, - PAGE_SIZE, PCI_DMA_BIDIRECTIONAL); - if (pci_dma_mapping_error(pdev, dev_priv->gart_info.sg_dummy_bus)) { -- nouveau_gpuobj_del(dev, &gpuobj); -+ nouveau_gpuobj_ref(NULL, &gpuobj); - return -EFAULT; - } - - if (dev_priv->card_type < NV_50) { -+ /* special case, allocated from global instmem heap so -+ * cinst is invalid, we use it on all channels though so -+ * cinst needs to be valid, set it the same as pinst -+ */ -+ gpuobj->cinst = gpuobj->pinst; -+ - /* Maybe use NV_DMA_TARGET_AGP for PCIE? NVIDIA do this, and - * confirmed to work on c51. Perhaps means NV_DMA_TARGET_PCIE - * on those cards? */ -- nv_wo32(dev, gpuobj, 0, NV_CLASS_DMA_IN_MEMORY | -- (1 << 12) /* PT present */ | -- (0 << 13) /* PT *not* linear */ | -- (NV_DMA_ACCESS_RW << 14) | -- (NV_DMA_TARGET_PCI << 16)); -- nv_wo32(dev, gpuobj, 1, aper_size - 1); -+ nv_wo32(gpuobj, 0, NV_CLASS_DMA_IN_MEMORY | -+ (1 << 12) /* PT present */ | -+ (0 << 13) /* PT *not* linear */ | -+ (NV_DMA_ACCESS_RW << 14) | -+ (NV_DMA_TARGET_PCI << 16)); -+ nv_wo32(gpuobj, 4, aper_size - 1); - for (i = 2; i < 2 + (aper_size >> 12); i++) { -- nv_wo32(dev, gpuobj, i, -- dev_priv->gart_info.sg_dummy_bus | 3); -+ nv_wo32(gpuobj, i * 4, -+ dev_priv->gart_info.sg_dummy_bus | 3); - } - } else { - for (i = 0; i < obj_size; i += 8) { -- nv_wo32(dev, gpuobj, (i+0)/4, -- dev_priv->gart_info.sg_dummy_bus | 0x21); -- nv_wo32(dev, gpuobj, (i+4)/4, 0); -+ nv_wo32(gpuobj, i + 0, 0x00000000); -+ nv_wo32(gpuobj, i + 4, 0x00000000); - } - } - dev_priv->engine.instmem.flush(dev); -@@ -298,7 +310,7 @@ - dev_priv->gart_info.sg_dummy_bus = 0; - } - -- nouveau_gpuobj_del(dev, &dev_priv->gart_info.sg_ctxdma); -+ nouveau_gpuobj_ref(NULL, &dev_priv->gart_info.sg_ctxdma); - } - - int -@@ -308,9 +320,9 @@ - struct nouveau_gpuobj *gpuobj = dev_priv->gart_info.sg_ctxdma; - int pte; - -- pte = (offset >> NV_CTXDMA_PAGE_SHIFT); -+ pte = (offset >> NV_CTXDMA_PAGE_SHIFT) << 2; - if (dev_priv->card_type < NV_50) { -- *page = nv_ro32(dev, gpuobj, (pte + 2)) & ~NV_CTXDMA_PAGE_MASK; -+ *page = nv_ro32(gpuobj, (pte + 8)) & ~NV_CTXDMA_PAGE_MASK; - return 0; - } - -diff -Naur linux-2.6.36/drivers/gpu/drm/nouveau/nouveau_state.c linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nouveau_state.c ---- linux-2.6.36/drivers/gpu/drm/nouveau/nouveau_state.c 2010-10-20 22:30:22.000000000 +0200 -+++ linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nouveau_state.c 2010-11-05 00:40:00.000000000 +0100 -@@ -35,6 +35,8 @@ - #include "nouveau_drv.h" - #include "nouveau_drm.h" - #include "nouveau_fbcon.h" -+#include "nouveau_ramht.h" -+#include "nouveau_pm.h" - #include "nv50_display.h" - - static void nouveau_stub_takedown(struct drm_device *dev) {} -@@ -63,7 +65,6 @@ - engine->timer.takedown = nv04_timer_takedown; - engine->fb.init = nv04_fb_init; - engine->fb.takedown = nv04_fb_takedown; -- engine->graph.grclass = nv04_graph_grclass; - engine->graph.init = nv04_graph_init; - engine->graph.takedown = nv04_graph_takedown; - engine->graph.fifo_access = nv04_graph_fifo_access; -@@ -78,7 +79,6 @@ - engine->fifo.disable = nv04_fifo_disable; - engine->fifo.enable = nv04_fifo_enable; - engine->fifo.reassign = nv04_fifo_reassign; -- engine->fifo.cache_flush = nv04_fifo_cache_flush; - engine->fifo.cache_pull = nv04_fifo_cache_pull; - engine->fifo.channel_id = nv04_fifo_channel_id; - engine->fifo.create_context = nv04_fifo_create_context; -@@ -95,6 +95,11 @@ - engine->gpio.get = NULL; - engine->gpio.set = NULL; - engine->gpio.irq_enable = NULL; -+ engine->pm.clock_get = nv04_pm_clock_get; -+ engine->pm.clock_pre = nv04_pm_clock_pre; -+ engine->pm.clock_set = nv04_pm_clock_set; -+ engine->crypt.init = nouveau_stub_init; -+ engine->crypt.takedown = nouveau_stub_takedown; - break; - case 0x10: - engine->instmem.init = nv04_instmem_init; -@@ -113,8 +118,9 @@ - engine->timer.takedown = nv04_timer_takedown; - engine->fb.init = nv10_fb_init; - engine->fb.takedown = nv10_fb_takedown; -- engine->fb.set_region_tiling = nv10_fb_set_region_tiling; -- engine->graph.grclass = nv10_graph_grclass; -+ 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->graph.init = nv10_graph_init; - engine->graph.takedown = nv10_graph_takedown; - engine->graph.channel = nv10_graph_channel; -@@ -123,18 +129,17 @@ - engine->graph.fifo_access = nv04_graph_fifo_access; - engine->graph.load_context = nv10_graph_load_context; - engine->graph.unload_context = nv10_graph_unload_context; -- engine->graph.set_region_tiling = nv10_graph_set_region_tiling; -+ engine->graph.set_tile_region = nv10_graph_set_tile_region; - engine->fifo.channels = 32; - engine->fifo.init = nv10_fifo_init; - engine->fifo.takedown = nouveau_stub_takedown; - engine->fifo.disable = nv04_fifo_disable; - engine->fifo.enable = nv04_fifo_enable; - engine->fifo.reassign = nv04_fifo_reassign; -- engine->fifo.cache_flush = nv04_fifo_cache_flush; - engine->fifo.cache_pull = nv04_fifo_cache_pull; - engine->fifo.channel_id = nv10_fifo_channel_id; - engine->fifo.create_context = nv10_fifo_create_context; -- engine->fifo.destroy_context = nv10_fifo_destroy_context; -+ engine->fifo.destroy_context = nv04_fifo_destroy_context; - engine->fifo.load_context = nv10_fifo_load_context; - engine->fifo.unload_context = nv10_fifo_unload_context; - engine->display.early_init = nv04_display_early_init; -@@ -147,6 +152,11 @@ - engine->gpio.get = nv10_gpio_get; - engine->gpio.set = nv10_gpio_set; - engine->gpio.irq_enable = NULL; -+ engine->pm.clock_get = nv04_pm_clock_get; -+ engine->pm.clock_pre = nv04_pm_clock_pre; -+ engine->pm.clock_set = nv04_pm_clock_set; -+ engine->crypt.init = nouveau_stub_init; -+ engine->crypt.takedown = nouveau_stub_takedown; - break; - case 0x20: - engine->instmem.init = nv04_instmem_init; -@@ -165,8 +175,9 @@ - engine->timer.takedown = nv04_timer_takedown; - engine->fb.init = nv10_fb_init; - engine->fb.takedown = nv10_fb_takedown; -- engine->fb.set_region_tiling = nv10_fb_set_region_tiling; -- engine->graph.grclass = nv20_graph_grclass; -+ 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->graph.init = nv20_graph_init; - engine->graph.takedown = nv20_graph_takedown; - engine->graph.channel = nv10_graph_channel; -@@ -175,18 +186,17 @@ - engine->graph.fifo_access = nv04_graph_fifo_access; - engine->graph.load_context = nv20_graph_load_context; - engine->graph.unload_context = nv20_graph_unload_context; -- engine->graph.set_region_tiling = nv20_graph_set_region_tiling; -+ engine->graph.set_tile_region = nv20_graph_set_tile_region; - engine->fifo.channels = 32; - engine->fifo.init = nv10_fifo_init; - engine->fifo.takedown = nouveau_stub_takedown; - engine->fifo.disable = nv04_fifo_disable; - engine->fifo.enable = nv04_fifo_enable; - engine->fifo.reassign = nv04_fifo_reassign; -- engine->fifo.cache_flush = nv04_fifo_cache_flush; - engine->fifo.cache_pull = nv04_fifo_cache_pull; - engine->fifo.channel_id = nv10_fifo_channel_id; - engine->fifo.create_context = nv10_fifo_create_context; -- engine->fifo.destroy_context = nv10_fifo_destroy_context; -+ engine->fifo.destroy_context = nv04_fifo_destroy_context; - engine->fifo.load_context = nv10_fifo_load_context; - engine->fifo.unload_context = nv10_fifo_unload_context; - engine->display.early_init = nv04_display_early_init; -@@ -199,6 +209,11 @@ - engine->gpio.get = nv10_gpio_get; - engine->gpio.set = nv10_gpio_set; - engine->gpio.irq_enable = NULL; -+ engine->pm.clock_get = nv04_pm_clock_get; -+ engine->pm.clock_pre = nv04_pm_clock_pre; -+ engine->pm.clock_set = nv04_pm_clock_set; -+ engine->crypt.init = nouveau_stub_init; -+ engine->crypt.takedown = nouveau_stub_takedown; - break; - case 0x30: - engine->instmem.init = nv04_instmem_init; -@@ -217,8 +232,9 @@ - engine->timer.takedown = nv04_timer_takedown; - engine->fb.init = nv30_fb_init; - engine->fb.takedown = nv30_fb_takedown; -- engine->fb.set_region_tiling = nv10_fb_set_region_tiling; -- engine->graph.grclass = nv30_graph_grclass; -+ 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->graph.init = nv30_graph_init; - engine->graph.takedown = nv20_graph_takedown; - engine->graph.fifo_access = nv04_graph_fifo_access; -@@ -227,18 +243,17 @@ - engine->graph.destroy_context = nv20_graph_destroy_context; - engine->graph.load_context = nv20_graph_load_context; - engine->graph.unload_context = nv20_graph_unload_context; -- engine->graph.set_region_tiling = nv20_graph_set_region_tiling; -+ engine->graph.set_tile_region = nv20_graph_set_tile_region; - engine->fifo.channels = 32; - engine->fifo.init = nv10_fifo_init; - engine->fifo.takedown = nouveau_stub_takedown; - engine->fifo.disable = nv04_fifo_disable; - engine->fifo.enable = nv04_fifo_enable; - engine->fifo.reassign = nv04_fifo_reassign; -- engine->fifo.cache_flush = nv04_fifo_cache_flush; - engine->fifo.cache_pull = nv04_fifo_cache_pull; - engine->fifo.channel_id = nv10_fifo_channel_id; - engine->fifo.create_context = nv10_fifo_create_context; -- engine->fifo.destroy_context = nv10_fifo_destroy_context; -+ engine->fifo.destroy_context = nv04_fifo_destroy_context; - engine->fifo.load_context = nv10_fifo_load_context; - engine->fifo.unload_context = nv10_fifo_unload_context; - engine->display.early_init = nv04_display_early_init; -@@ -251,6 +266,13 @@ - engine->gpio.get = nv10_gpio_get; - engine->gpio.set = nv10_gpio_set; - engine->gpio.irq_enable = NULL; -+ engine->pm.clock_get = nv04_pm_clock_get; -+ engine->pm.clock_pre = nv04_pm_clock_pre; -+ engine->pm.clock_set = nv04_pm_clock_set; -+ engine->pm.voltage_get = nouveau_voltage_gpio_get; -+ engine->pm.voltage_set = nouveau_voltage_gpio_set; -+ engine->crypt.init = nouveau_stub_init; -+ engine->crypt.takedown = nouveau_stub_takedown; - break; - case 0x40: - case 0x60: -@@ -270,8 +292,9 @@ - engine->timer.takedown = nv04_timer_takedown; - engine->fb.init = nv40_fb_init; - engine->fb.takedown = nv40_fb_takedown; -- engine->fb.set_region_tiling = nv40_fb_set_region_tiling; -- engine->graph.grclass = nv40_graph_grclass; -+ 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->graph.init = nv40_graph_init; - engine->graph.takedown = nv40_graph_takedown; - engine->graph.fifo_access = nv04_graph_fifo_access; -@@ -280,18 +303,17 @@ - engine->graph.destroy_context = nv40_graph_destroy_context; - engine->graph.load_context = nv40_graph_load_context; - engine->graph.unload_context = nv40_graph_unload_context; -- engine->graph.set_region_tiling = nv40_graph_set_region_tiling; -+ engine->graph.set_tile_region = nv40_graph_set_tile_region; - engine->fifo.channels = 32; - engine->fifo.init = nv40_fifo_init; - engine->fifo.takedown = nouveau_stub_takedown; - engine->fifo.disable = nv04_fifo_disable; - engine->fifo.enable = nv04_fifo_enable; - engine->fifo.reassign = nv04_fifo_reassign; -- engine->fifo.cache_flush = nv04_fifo_cache_flush; - engine->fifo.cache_pull = nv04_fifo_cache_pull; - engine->fifo.channel_id = nv10_fifo_channel_id; - engine->fifo.create_context = nv40_fifo_create_context; -- engine->fifo.destroy_context = nv40_fifo_destroy_context; -+ engine->fifo.destroy_context = nv04_fifo_destroy_context; - engine->fifo.load_context = nv40_fifo_load_context; - engine->fifo.unload_context = nv40_fifo_unload_context; - engine->display.early_init = nv04_display_early_init; -@@ -304,6 +326,14 @@ - engine->gpio.get = nv10_gpio_get; - engine->gpio.set = nv10_gpio_set; - engine->gpio.irq_enable = NULL; -+ engine->pm.clock_get = nv04_pm_clock_get; -+ engine->pm.clock_pre = nv04_pm_clock_pre; -+ engine->pm.clock_set = nv04_pm_clock_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->crypt.init = nouveau_stub_init; -+ engine->crypt.takedown = nouveau_stub_takedown; - break; - case 0x50: - case 0x80: /* gotta love NVIDIA's consistency.. */ -@@ -328,7 +358,6 @@ - engine->timer.takedown = nv04_timer_takedown; - engine->fb.init = nv50_fb_init; - engine->fb.takedown = nv50_fb_takedown; -- engine->graph.grclass = nv50_graph_grclass; - engine->graph.init = nv50_graph_init; - engine->graph.takedown = nv50_graph_takedown; - engine->graph.fifo_access = nv50_graph_fifo_access; -@@ -337,6 +366,15 @@ - engine->graph.destroy_context = nv50_graph_destroy_context; - engine->graph.load_context = nv50_graph_load_context; - engine->graph.unload_context = nv50_graph_unload_context; -+ if (dev_priv->chipset != 0x86) -+ engine->graph.tlb_flush = nv50_graph_tlb_flush; -+ else { -+ /* from what i can see nvidia do this on every -+ * pre-NVA3 board except NVAC, but, we've only -+ * ever seen problems on NV86 -+ */ -+ engine->graph.tlb_flush = nv86_graph_tlb_flush; -+ } - engine->fifo.channels = 128; - engine->fifo.init = nv50_fifo_init; - engine->fifo.takedown = nv50_fifo_takedown; -@@ -348,6 +386,7 @@ - engine->fifo.destroy_context = nv50_fifo_destroy_context; - engine->fifo.load_context = nv50_fifo_load_context; - engine->fifo.unload_context = nv50_fifo_unload_context; -+ engine->fifo.tlb_flush = nv50_fifo_tlb_flush; - engine->display.early_init = nv50_display_early_init; - engine->display.late_takedown = nv50_display_late_takedown; - engine->display.create = nv50_display_create; -@@ -358,6 +397,50 @@ - engine->gpio.get = nv50_gpio_get; - engine->gpio.set = nv50_gpio_set; - engine->gpio.irq_enable = nv50_gpio_irq_enable; -+ 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.clock_get = nv50_pm_clock_get; -+ engine->pm.clock_pre = nv50_pm_clock_pre; -+ engine->pm.clock_set = nv50_pm_clock_set; -+ break; -+ default: -+ engine->pm.clock_get = nva3_pm_clock_get; -+ engine->pm.clock_pre = nva3_pm_clock_pre; -+ engine->pm.clock_set = nva3_pm_clock_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; -+ switch (dev_priv->chipset) { -+ case 0x84: -+ case 0x86: -+ case 0x92: -+ case 0x94: -+ case 0x96: -+ case 0xa0: -+ engine->crypt.init = nv84_crypt_init; -+ engine->crypt.takedown = nv84_crypt_fini; -+ engine->crypt.create_context = nv84_crypt_create_context; -+ engine->crypt.destroy_context = nv84_crypt_destroy_context; -+ break; -+ default: -+ engine->crypt.init = nouveau_stub_init; -+ engine->crypt.takedown = nouveau_stub_takedown; -+ break; -+ } - break; - case 0xC0: - engine->instmem.init = nvc0_instmem_init; -@@ -376,7 +459,6 @@ - engine->timer.takedown = nv04_timer_takedown; - engine->fb.init = nvc0_fb_init; - engine->fb.takedown = nvc0_fb_takedown; -- engine->graph.grclass = NULL; //nvc0_graph_grclass; - engine->graph.init = nvc0_graph_init; - engine->graph.takedown = nvc0_graph_takedown; - engine->graph.fifo_access = nvc0_graph_fifo_access; -@@ -406,6 +488,8 @@ - engine->gpio.get = nv50_gpio_get; - engine->gpio.set = nv50_gpio_set; - engine->gpio.irq_enable = nv50_gpio_irq_enable; -+ engine->crypt.init = nouveau_stub_init; -+ engine->crypt.takedown = nouveau_stub_takedown; - break; - default: - NV_ERROR(dev, "NV%02x unsupported\n", dev_priv->chipset); -@@ -437,16 +521,14 @@ - nouveau_card_init_channel(struct drm_device *dev) - { - struct drm_nouveau_private *dev_priv = dev->dev_private; -- struct nouveau_gpuobj *gpuobj; -+ struct nouveau_gpuobj *gpuobj = NULL; - int ret; - - ret = nouveau_channel_alloc(dev, &dev_priv->channel, -- (struct drm_file *)-2, -- NvDmaFB, NvDmaTT); -+ (struct drm_file *)-2, NvDmaFB, NvDmaTT); - if (ret) - return ret; - -- gpuobj = NULL; - ret = nouveau_gpuobj_dma_new(dev_priv->channel, NV_CLASS_DMA_IN_MEMORY, - 0, dev_priv->vram_size, - NV_DMA_ACCESS_RW, NV_DMA_TARGET_VIDMEM, -@@ -454,28 +536,27 @@ - if (ret) - goto out_err; - -- ret = nouveau_gpuobj_ref_add(dev, dev_priv->channel, NvDmaVRAM, -- gpuobj, NULL); -+ ret = nouveau_ramht_insert(dev_priv->channel, NvDmaVRAM, gpuobj); -+ nouveau_gpuobj_ref(NULL, &gpuobj); - if (ret) - goto out_err; - -- gpuobj = NULL; - ret = nouveau_gpuobj_gart_dma_new(dev_priv->channel, 0, - dev_priv->gart_info.aper_size, - NV_DMA_ACCESS_RW, &gpuobj, NULL); - if (ret) - goto out_err; - -- ret = nouveau_gpuobj_ref_add(dev, dev_priv->channel, NvDmaGART, -- gpuobj, NULL); -+ ret = nouveau_ramht_insert(dev_priv->channel, NvDmaGART, gpuobj); -+ nouveau_gpuobj_ref(NULL, &gpuobj); - if (ret) - goto out_err; - -+ mutex_unlock(&dev_priv->channel->mutex); - return 0; -+ - out_err: -- nouveau_gpuobj_del(dev, &gpuobj); -- nouveau_channel_free(dev_priv->channel); -- dev_priv->channel = NULL; -+ nouveau_channel_put(&dev_priv->channel); - return ret; - } - -@@ -522,6 +603,8 @@ - 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); - - /* Make the CRTCs and I2C buses accessible */ -@@ -534,35 +617,28 @@ - if (ret) - goto out_display_early; - -- ret = nouveau_mem_detect(dev); -+ nouveau_pm_init(dev); -+ -+ ret = nouveau_mem_vram_init(dev); - if (ret) - goto out_bios; - -- ret = nouveau_gpuobj_early_init(dev); -+ ret = nouveau_gpuobj_init(dev); - if (ret) -- goto out_bios; -+ goto out_vram; - -- /* Initialise instance memory, must happen before mem_init so we -- * know exactly how much VRAM we're able to use for "normal" -- * purposes. -- */ - ret = engine->instmem.init(dev); - if (ret) -- goto out_gpuobj_early; -+ goto out_gpuobj; - -- /* Setup the memory manager */ -- ret = nouveau_mem_init(dev); -+ ret = nouveau_mem_gart_init(dev); - if (ret) - goto out_instmem; - -- ret = nouveau_gpuobj_init(dev); -- if (ret) -- goto out_mem; -- - /* PMC */ - ret = engine->mc.init(dev); - if (ret) -- goto out_gpuobj; -+ goto out_gart; - - /* PGPIO */ - ret = engine->gpio.init(dev); -@@ -587,33 +663,39 @@ - if (ret) - goto out_fb; - -+ /* PCRYPT */ -+ ret = engine->crypt.init(dev); -+ if (ret) -+ goto out_graph; -+ - /* PFIFO */ - ret = engine->fifo.init(dev); - if (ret) -- goto out_graph; -+ goto out_crypt; - } - - ret = engine->display.create(dev); - if (ret) - goto out_fifo; - -- /* this call irq_preinstall, register irq handler and -- * call irq_postinstall -- */ -- ret = drm_irq_install(dev); -+ ret = drm_vblank_init(dev, nv_two_heads(dev) ? 2 : 1); - if (ret) -- goto out_display; -+ goto out_vblank; - -- ret = drm_vblank_init(dev, 0); -+ ret = nouveau_irq_init(dev); - if (ret) -- goto out_irq; -+ goto out_vblank; - - /* what about PVIDEO/PCRTC/PRAMDAC etc? */ - - if (!engine->graph.accel_blocked) { -- ret = nouveau_card_init_channel(dev); -+ ret = nouveau_fence_init(dev); - if (ret) - goto out_irq; -+ -+ ret = nouveau_card_init_channel(dev); -+ if (ret) -+ goto out_fence; - } - - ret = nouveau_backlight_init(dev); -@@ -624,13 +706,19 @@ - drm_kms_helper_poll_init(dev); - return 0; - -+out_fence: -+ nouveau_fence_fini(dev); - out_irq: -- drm_irq_uninstall(dev); --out_display: -+ nouveau_irq_fini(dev); -+out_vblank: -+ drm_vblank_cleanup(dev); - engine->display.destroy(dev); - out_fifo: - if (!nouveau_noaccel) - engine->fifo.takedown(dev); -+out_crypt: -+ if (!nouveau_noaccel) -+ engine->crypt.takedown(dev); - out_graph: - if (!nouveau_noaccel) - engine->graph.takedown(dev); -@@ -642,16 +730,16 @@ - engine->gpio.takedown(dev); - out_mc: - engine->mc.takedown(dev); --out_gpuobj: -- nouveau_gpuobj_takedown(dev); --out_mem: -- nouveau_sgdma_takedown(dev); -- nouveau_mem_close(dev); -+out_gart: -+ nouveau_mem_gart_fini(dev); - out_instmem: - engine->instmem.takedown(dev); --out_gpuobj_early: -- nouveau_gpuobj_late_takedown(dev); -+out_gpuobj: -+ nouveau_gpuobj_takedown(dev); -+out_vram: -+ nouveau_mem_vram_fini(dev); - out_bios: -+ nouveau_pm_fini(dev); - nouveau_bios_takedown(dev); - out_display_early: - engine->display.late_takedown(dev); -@@ -667,13 +755,14 @@ - - nouveau_backlight_exit(dev); - -- if (dev_priv->channel) { -- nouveau_channel_free(dev_priv->channel); -- dev_priv->channel = NULL; -+ if (!engine->graph.accel_blocked) { -+ nouveau_fence_fini(dev); -+ nouveau_channel_put_unlocked(&dev_priv->channel); - } - - if (!nouveau_noaccel) { - engine->fifo.takedown(dev); -+ engine->crypt.takedown(dev); - engine->graph.takedown(dev); - } - engine->fb.takedown(dev); -@@ -686,15 +775,16 @@ - 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_sgdma_takedown(dev); -+ nouveau_mem_gart_fini(dev); - -- nouveau_gpuobj_takedown(dev); -- nouveau_mem_close(dev); - engine->instmem.takedown(dev); -+ nouveau_gpuobj_takedown(dev); -+ nouveau_mem_vram_fini(dev); - -- drm_irq_uninstall(dev); -+ nouveau_irq_fini(dev); -+ drm_vblank_cleanup(dev); - -- nouveau_gpuobj_late_takedown(dev); -+ nouveau_pm_fini(dev); - nouveau_bios_takedown(dev); - - vga_client_register(dev->pdev, NULL, NULL, NULL); -@@ -1006,6 +1096,12 @@ - case NOUVEAU_GETPARAM_PTIMER_TIME: - getparam->value = dev_priv->engine.timer.read(dev); - break; -+ case NOUVEAU_GETPARAM_HAS_BO_USAGE: -+ getparam->value = 1; -+ break; -+ case NOUVEAU_GETPARAM_HAS_PAGEFLIP: -+ getparam->value = (dev_priv->card_type < NV_50); -+ break; - case NOUVEAU_GETPARAM_GRAPH_UNITS: - /* NV40 and NV50 versions are quite different, but register - * address is the same. User is supposed to know the card -@@ -1016,7 +1112,7 @@ - } - /* FALLTHRU */ - default: -- NV_ERROR(dev, "unknown parameter %lld\n", getparam->param); -+ NV_DEBUG(dev, "unknown parameter %lld\n", getparam->param); - return -EINVAL; - } - -@@ -1031,7 +1127,7 @@ - - switch (setparam->param) { - default: -- NV_ERROR(dev, "unknown parameter %lld\n", setparam->param); -+ NV_DEBUG(dev, "unknown parameter %lld\n", setparam->param); - return -EINVAL; - } - -@@ -1057,7 +1153,13 @@ - /* Waits for PGRAPH to go completely idle */ - bool nouveau_wait_for_idle(struct drm_device *dev) - { -- if (!nv_wait(NV04_PGRAPH_STATUS, 0xffffffff, 0x00000000)) { -+ 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; -diff -Naur linux-2.6.36/drivers/gpu/drm/nouveau/nouveau_temp.c linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nouveau_temp.c ---- linux-2.6.36/drivers/gpu/drm/nouveau/nouveau_temp.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nouveau_temp.c 2010-11-05 00:40:00.000000000 +0100 -@@ -0,0 +1,309 @@ -+/* -+ * Copyright 2010 PathScale 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: Martin Peres -+ */ -+ -+#include "drmP.h" -+ -+#include "nouveau_drv.h" -+#include "nouveau_pm.h" -+ -+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_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"); -+ return; -+ } -+ -+ /* Set the default sensor's contants */ -+ sensor->offset_constant = 0; -+ sensor->offset_mult = 1; -+ sensor->offset_div = 1; -+ sensor->slope_mult = 1; -+ sensor->slope_div = 1; -+ -+ /* Set the default temperature thresholds */ -+ temps->critical = 110; -+ temps->down_clock = 100; -+ temps->fan_boost = 90; -+ -+ /* Set the known default values to setup the temperature sensor */ -+ if (dev_priv->card_type >= NV_40) { -+ switch (dev_priv->chipset) { -+ case 0x43: -+ sensor->offset_mult = 32060; -+ sensor->offset_div = 1000; -+ sensor->slope_mult = 792; -+ sensor->slope_div = 1000; -+ break; -+ -+ case 0x44: -+ case 0x47: -+ case 0x4a: -+ sensor->offset_mult = 27839; -+ sensor->offset_div = 1000; -+ sensor->slope_mult = 780; -+ sensor->slope_div = 1000; -+ break; -+ -+ case 0x46: -+ sensor->offset_mult = -24775; -+ sensor->offset_div = 100; -+ sensor->slope_mult = 467; -+ sensor->slope_div = 10000; -+ break; -+ -+ case 0x49: -+ sensor->offset_mult = -25051; -+ sensor->offset_div = 100; -+ sensor->slope_mult = 458; -+ sensor->slope_div = 10000; -+ break; -+ -+ case 0x4b: -+ sensor->offset_mult = -24088; -+ sensor->offset_div = 100; -+ sensor->slope_mult = 442; -+ sensor->slope_div = 10000; -+ break; -+ -+ case 0x50: -+ sensor->offset_mult = -22749; -+ sensor->offset_div = 100; -+ sensor->slope_mult = 431; -+ sensor->slope_div = 10000; -+ break; -+ } -+ } -+ -+ headerlen = temp[1]; -+ recordlen = temp[2]; -+ entries = temp[3]; -+ temp = temp + headerlen; -+ -+ /* Read the entries from the table */ -+ for (i = 0; i < entries; i++) { -+ u16 value = ROM16(temp[1]); -+ -+ switch (temp[0]) { -+ case 0x01: -+ if ((value & 0x8f) == 0) -+ sensor->offset_constant = (value >> 9) & 0x7f; -+ break; -+ -+ case 0x04: -+ if ((value & 0xf00f) == 0xa000) /* core */ -+ temps->critical = (value&0x0ff0) >> 4; -+ break; -+ -+ case 0x07: -+ if ((value & 0xf00f) == 0xa000) /* core */ -+ temps->down_clock = (value&0x0ff0) >> 4; -+ break; -+ -+ case 0x08: -+ if ((value & 0xf00f) == 0xa000) /* core */ -+ temps->fan_boost = (value&0x0ff0) >> 4; -+ break; -+ -+ case 0x10: -+ sensor->offset_mult = value; -+ break; -+ -+ case 0x11: -+ sensor->offset_div = value; -+ break; -+ -+ case 0x12: -+ sensor->slope_mult = value; -+ break; -+ -+ case 0x13: -+ sensor->slope_div = value; -+ break; -+ } -+ temp += recordlen; -+ } -+ -+ nouveau_temp_safety_checks(dev); -+} -+ -+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_pm_temp_sensor_constants *sensor = &pm->sensor_constants; -+ u32 offset = sensor->offset_mult / sensor->offset_div; -+ u32 sensor_calibration; -+ -+ /* set up the sensors */ -+ sensor_calibration = 120 - offset - sensor->offset_constant; -+ sensor_calibration = sensor_calibration * sensor->slope_div / -+ sensor->slope_mult; -+ -+ if (dev_priv->chipset >= 0x46) -+ sensor_calibration |= 0x80000000; -+ else -+ sensor_calibration |= 0x10000000; -+ -+ nv_wr32(dev, 0x0015b0, sensor_calibration); -+ -+ /* Wait for the sensor to update */ -+ msleep(5); -+ -+ /* read */ -+ return nv_rd32(dev, 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_pm_temp_sensor_constants *sensor = &pm->sensor_constants; -+ int offset = sensor->offset_mult / sensor->offset_div; -+ int core_temp; -+ -+ if (dev_priv->chipset >= 0x50) { -+ core_temp = nv_rd32(dev, 0x20008); -+ } else { -+ core_temp = nv_rd32(dev, 0x0015b4) & 0x1fff; -+ /* Setup the sensor if the temperature is 0 */ -+ if (core_temp == 0) -+ core_temp = nv40_sensor_setup(dev); -+ } -+ -+ core_temp = core_temp * sensor->slope_mult / sensor->slope_div; -+ core_temp = core_temp + offset + sensor->offset_constant; -+ -+ return core_temp; -+} -+ -+int -+nv84_temp_get(struct drm_device *dev) -+{ -+ return nv_rd32(dev, 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_threshold_temp *temps = &pm->threshold_temp; -+ -+ if (temps->critical > 120) -+ temps->critical = 120; -+ else if (temps->critical < 80) -+ temps->critical = 80; -+ -+ if (temps->down_clock > 110) -+ temps->down_clock = 110; -+ else if (temps->down_clock < 60) -+ temps->down_clock = 60; -+ -+ if (temps->fan_boost > 100) -+ temps->fan_boost = 100; -+ else if (temps->fan_boost < 40) -+ temps->fan_boost = 40; -+} -+ -+static bool -+probe_monitoring_device(struct nouveau_i2c_chan *i2c, -+ struct i2c_board_info *info) -+{ -+ char modalias[16] = "i2c:"; -+ struct i2c_client *client; -+ -+ strlcat(modalias, info->type, sizeof(modalias)); -+ request_module(modalias); -+ -+ client = i2c_new_device(&i2c->adapter, info); -+ if (!client) -+ return false; -+ -+ if (!client->driver || client->driver->detect(client, info)) { -+ i2c_unregister_device(client); -+ return false; -+ } -+ -+ return true; -+} -+ -+static void -+nouveau_temp_probe_i2c(struct drm_device *dev) -+{ -+ struct drm_nouveau_private *dev_priv = dev->dev_private; -+ struct dcb_table *dcb = &dev_priv->vbios.dcb; -+ struct i2c_board_info info[] = { -+ { I2C_BOARD_INFO("w83l785ts", 0x2d) }, -+ { I2C_BOARD_INFO("w83781d", 0x2d) }, -+ { I2C_BOARD_INFO("f75375", 0x2e) }, -+ { I2C_BOARD_INFO("adt7473", 0x2e) }, -+ { I2C_BOARD_INFO("lm99", 0x4c) }, -+ { } -+ }; -+ int idx = (dcb->version >= 0x40 ? -+ dcb->i2c_default_indices & 0xf : 2); -+ -+ nouveau_i2c_identify(dev, "monitoring device", info, -+ probe_monitoring_device, idx); -+} -+ -+void -+nouveau_temp_init(struct drm_device *dev) -+{ -+ struct drm_nouveau_private *dev_priv = dev->dev_private; -+ struct nvbios *bios = &dev_priv->vbios; -+ struct bit_entry P; -+ u8 *temp = NULL; -+ -+ if (bios->type == NVBIOS_BIT) { -+ if (bit_table(dev, 'P', &P)) -+ return; -+ -+ if (P.version == 1) -+ temp = ROMPTR(bios, P.data[12]); -+ else if (P.version == 2) -+ temp = ROMPTR(bios, P.data[16]); -+ else -+ NV_WARN(dev, "unknown temp for BIT P %d\n", P.version); -+ -+ nouveau_temp_vbios_parse(dev, temp); -+ } -+ -+ nouveau_temp_probe_i2c(dev); -+} -+ -+void -+nouveau_temp_fini(struct drm_device *dev) -+{ -+ -+} -diff -Naur linux-2.6.36/drivers/gpu/drm/nouveau/nouveau_volt.c linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nouveau_volt.c ---- linux-2.6.36/drivers/gpu/drm/nouveau/nouveau_volt.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nouveau_volt.c 2010-11-05 00:40:00.000000000 +0100 -@@ -0,0 +1,212 @@ -+/* -+ * Copyright 2010 Red Hat Inc. -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included in -+ * all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR -+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -+ * OTHER DEALINGS IN THE SOFTWARE. -+ * -+ * Authors: Ben Skeggs -+ */ -+ -+#include "drmP.h" -+ -+#include "nouveau_drv.h" -+#include "nouveau_pm.h" -+ -+static const enum dcb_gpio_tag vidtag[] = { 0x04, 0x05, 0x06, 0x1a }; -+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_gpio_engine *gpio = &dev_priv->engine.gpio; -+ struct nouveau_pm_voltage *volt = &dev_priv->engine.pm.voltage; -+ u8 vid = 0; -+ int i; -+ -+ for (i = 0; i < nr_vidtag; i++) { -+ if (!(volt->vid_mask & (1 << i))) -+ continue; -+ -+ vid |= gpio->get(dev, vidtag[i]) << i; -+ } -+ -+ return nouveau_volt_lvl_lookup(dev, vid); -+} -+ -+int -+nouveau_voltage_gpio_set(struct drm_device *dev, int voltage) -+{ -+ struct drm_nouveau_private *dev_priv = dev->dev_private; -+ struct nouveau_gpio_engine *gpio = &dev_priv->engine.gpio; -+ struct nouveau_pm_voltage *volt = &dev_priv->engine.pm.voltage; -+ int vid, i; -+ -+ vid = nouveau_volt_vid_lookup(dev, voltage); -+ if (vid < 0) -+ return vid; -+ -+ for (i = 0; i < nr_vidtag; i++) { -+ if (!(volt->vid_mask & (1 << i))) -+ continue; -+ -+ gpio->set(dev, vidtag[i], !!(vid & (1 << i))); -+ } -+ -+ return 0; -+} -+ -+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; -+ int i; -+ -+ for (i = 0; i < volt->nr_level; i++) { -+ if (volt->level[i].voltage == voltage) -+ return volt->level[i].vid; -+ } -+ -+ return -ENOENT; -+} -+ -+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; -+ int i; -+ -+ for (i = 0; i < volt->nr_level; i++) { -+ if (volt->level[i].vid == vid) -+ return volt->level[i].voltage; -+ } -+ -+ return -ENOENT; -+} -+ -+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_pm_voltage *voltage = &pm->voltage; -+ struct nvbios *bios = &dev_priv->vbios; -+ struct bit_entry P; -+ u8 *volt = NULL, *entry; -+ int i, headerlen, recordlen, entries, vidmask, vidshift; -+ -+ if (bios->type == NVBIOS_BIT) { -+ if (bit_table(dev, 'P', &P)) -+ return; -+ -+ if (P.version == 1) -+ volt = ROMPTR(bios, P.data[16]); -+ else -+ if (P.version == 2) -+ volt = ROMPTR(bios, P.data[12]); -+ else { -+ NV_WARN(dev, "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"); -+ return; -+ } -+ -+ volt = ROMPTR(bios, bios->data[bios->offset + 0x98]); -+ } -+ -+ if (!volt) { -+ NV_DEBUG(dev, "voltage table pointer invalid\n"); -+ return; -+ } -+ -+ switch (volt[0]) { -+ case 0x10: -+ case 0x11: -+ case 0x12: -+ headerlen = 5; -+ recordlen = volt[1]; -+ entries = volt[2]; -+ vidshift = 0; -+ vidmask = volt[4]; -+ break; -+ case 0x20: -+ headerlen = volt[1]; -+ recordlen = volt[3]; -+ entries = volt[2]; -+ vidshift = 0; /* could be vidshift like 0x30? */ -+ vidmask = volt[5]; -+ break; -+ case 0x30: -+ headerlen = volt[1]; -+ recordlen = volt[2]; -+ entries = volt[3]; -+ vidshift = hweight8(volt[5]); -+ vidmask = volt[4]; -+ break; -+ default: -+ NV_WARN(dev, "voltage table 0x%02x unknown\n", volt[0]); -+ return; -+ } -+ -+ /* validate vid mask */ -+ voltage->vid_mask = vidmask; -+ if (!voltage->vid_mask) -+ return; -+ -+ i = 0; -+ while (vidmask) { -+ if (i > nr_vidtag) { -+ NV_DEBUG(dev, "vid bit %d unknown\n", i); -+ return; -+ } -+ -+ if (!nouveau_bios_gpio_entry(dev, vidtag[i])) { -+ NV_DEBUG(dev, "vid bit %d has no gpio tag\n", i); -+ return; -+ } -+ -+ vidmask >>= 1; -+ i++; -+ } -+ -+ /* parse vbios entries into common format */ -+ voltage->level = kcalloc(entries, sizeof(*voltage->level), GFP_KERNEL); -+ if (!voltage->level) -+ return; -+ -+ entry = volt + headerlen; -+ for (i = 0; i < entries; i++, entry += recordlen) { -+ voltage->level[i].voltage = entry[0]; -+ voltage->level[i].vid = entry[1] >> vidshift; -+ } -+ voltage->nr_level = entries; -+ voltage->supported = true; -+} -+ -+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; -+ -+ kfree(volt->level); -+} -diff -Naur linux-2.6.36/drivers/gpu/drm/nouveau/nv04_crtc.c linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nv04_crtc.c ---- linux-2.6.36/drivers/gpu/drm/nouveau/nv04_crtc.c 2010-10-20 22:30:22.000000000 +0200 -+++ linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nv04_crtc.c 2010-11-05 00:40:00.000000000 +0100 -@@ -109,7 +109,7 @@ - struct nouveau_pll_vals *pv = ®p->pllvals; - struct pll_lims pll_lim; - -- if (get_pll_limits(dev, nv_crtc->index ? VPLL2 : VPLL1, &pll_lim)) -+ if (get_pll_limits(dev, nv_crtc->index ? PLL_VPLL1 : PLL_VPLL0, &pll_lim)) - return; - - /* NM2 == 0 is used to determine single stage mode on two stage plls */ -@@ -157,7 +157,6 @@ - { - struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); - struct drm_device *dev = crtc->dev; -- struct drm_connector *connector; - unsigned char seq1 = 0, crtc17 = 0; - unsigned char crtc1A; - -@@ -212,10 +211,6 @@ - NVVgaSeqReset(dev, nv_crtc->index, false); - - NVWriteVgaCrtc(dev, nv_crtc->index, NV_CIO_CRE_RPC1_INDEX, crtc1A); -- -- /* Update connector polling modes */ -- list_for_each_entry(connector, &dev->mode_config.connector_list, head) -- nouveau_connector_set_polling(connector); - } - - static bool -@@ -555,7 +550,10 @@ - if (dev_priv->card_type >= NV_30) - regp->gpio_ext = NVReadCRTC(dev, 0, NV_PCRTC_GPIO_EXT); - -- regp->crtc_cfg = NV_PCRTC_CONFIG_START_ADDRESS_HSYNC; -+ if (dev_priv->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) { -@@ -673,6 +671,7 @@ - if (nv_two_heads(dev)) - NVSetOwner(dev, nv_crtc->index); - -+ drm_vblank_pre_modeset(dev, nv_crtc->index); - funcs->dpms(crtc, DRM_MODE_DPMS_OFF); - - NVBlankScreen(dev, nv_crtc->index, true); -@@ -705,6 +704,7 @@ - #endif - - funcs->dpms(crtc, DRM_MODE_DPMS_ON); -+ drm_vblank_post_modeset(dev, nv_crtc->index); - } - - static void nv_crtc_destroy(struct drm_crtc *crtc) -@@ -718,6 +718,7 @@ - - drm_crtc_cleanup(crtc); - -+ nouveau_bo_unmap(nv_crtc->cursor.nvbo); - nouveau_bo_ref(NULL, &nv_crtc->cursor.nvbo); - kfree(nv_crtc); - } -@@ -815,7 +816,7 @@ - /* Update the framebuffer location. */ - regp->fb_start = nv_crtc->fb.offset & ~3; - regp->fb_start += (y * drm_fb->pitch) + (x * drm_fb->bits_per_pixel / 8); -- NVWriteCRTC(dev, nv_crtc->index, NV_PCRTC_START, regp->fb_start); -+ nv_set_crtc_base(dev, nv_crtc->index, regp->fb_start); - - /* Update the arbitration parameters. */ - nouveau_calc_arb(dev, crtc->mode.clock, drm_fb->bits_per_pixel, -@@ -826,7 +827,7 @@ - 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_30) { -+ if (dev_priv->card_type >= NV_20) { - regp->CRTC[NV_CIO_CRE_47] = arb_lwm >> 8; - crtc_wr_cio_state(crtc, regp, NV_CIO_CRE_47); - } -@@ -952,6 +953,7 @@ - .cursor_move = nv04_crtc_cursor_move, - .gamma_set = nv_crtc_gamma_set, - .set_config = drm_crtc_helper_set_config, -+ .page_flip = nouveau_crtc_page_flip, - .destroy = nv_crtc_destroy, - }; - -diff -Naur linux-2.6.36/drivers/gpu/drm/nouveau/nv04_dac.c linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nv04_dac.c ---- linux-2.6.36/drivers/gpu/drm/nouveau/nv04_dac.c 2010-10-20 22:30:22.000000000 +0200 -+++ linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nv04_dac.c 2010-11-05 00:40:00.000000000 +0100 -@@ -291,6 +291,8 @@ - msleep(5); - - sample = NVReadRAMDAC(dev, 0, NV_PRAMDAC_TEST_CONTROL + regoffset); -+ /* do it again just in case it's a residual current */ -+ sample &= NVReadRAMDAC(dev, 0, NV_PRAMDAC_TEST_CONTROL + regoffset); - - temp = NVReadRAMDAC(dev, head, NV_PRAMDAC_TEST_CONTROL); - NVWriteRAMDAC(dev, head, NV_PRAMDAC_TEST_CONTROL, -@@ -343,22 +345,13 @@ - { - struct drm_encoder_helper_funcs *helper = encoder->helper_private; - struct drm_device *dev = encoder->dev; -- struct drm_nouveau_private *dev_priv = dev->dev_private; - int head = nouveau_crtc(encoder->crtc)->index; -- struct nv04_crtc_reg *crtcstate = dev_priv->mode_reg.crtc_reg; - - helper->dpms(encoder, DRM_MODE_DPMS_OFF); - - nv04_dfp_disable(dev, head); -- -- /* Some NV4x have unknown values (0x3f, 0x50, 0x54, 0x6b, 0x79, 0x7f) -- * at LCD__INDEX which we don't alter -- */ -- if (!(crtcstate[head].CRTC[NV_CIO_CRE_LCD__INDEX] & 0x44)) -- crtcstate[head].CRTC[NV_CIO_CRE_LCD__INDEX] = 0; - } - -- - static void nv04_dac_mode_set(struct drm_encoder *encoder, - struct drm_display_mode *mode, - struct drm_display_mode *adjusted_mode) -diff -Naur linux-2.6.36/drivers/gpu/drm/nouveau/nv04_dfp.c linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nv04_dfp.c ---- linux-2.6.36/drivers/gpu/drm/nouveau/nv04_dfp.c 2010-10-20 22:30:22.000000000 +0200 -+++ linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nv04_dfp.c 2010-11-05 00:40:00.000000000 +0100 -@@ -104,6 +104,8 @@ - } - /* don't inadvertently turn it on when state written later */ - crtcstate[head].fp_control = FP_TG_CONTROL_OFF; -+ crtcstate[head].CRTC[NV_CIO_CRE_LCD__INDEX] &= -+ ~NV_CIO_CRE_LCD_ROUTE_MASK; - } - - void nv04_dfp_update_fp_control(struct drm_encoder *encoder, int mode) -@@ -183,14 +185,15 @@ - struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); - struct nouveau_connector *nv_connector = nouveau_encoder_connector_get(nv_encoder); - -- /* For internal panels and gpu scaling on DVI we need the native mode */ -- if (nv_connector->scaling_mode != DRM_MODE_SCALE_NONE) { -- if (!nv_connector->native_mode) -- return false; -+ if (!nv_connector->native_mode || -+ nv_connector->scaling_mode == DRM_MODE_SCALE_NONE || -+ mode->hdisplay > nv_connector->native_mode->hdisplay || -+ mode->vdisplay > nv_connector->native_mode->vdisplay) { -+ nv_encoder->mode = *adjusted_mode; -+ -+ } else { - nv_encoder->mode = *nv_connector->native_mode; - adjusted_mode->clock = nv_connector->native_mode->clock; -- } else { -- nv_encoder->mode = *adjusted_mode; - } - - return true; -@@ -253,26 +256,21 @@ - - nv04_dfp_prepare_sel_clk(dev, nv_encoder, head); - -- /* Some NV4x have unknown values (0x3f, 0x50, 0x54, 0x6b, 0x79, 0x7f) -- * at LCD__INDEX which we don't alter -- */ -- if (!(*cr_lcd & 0x44)) { -- *cr_lcd = 0x3; -+ *cr_lcd = (*cr_lcd & ~NV_CIO_CRE_LCD_ROUTE_MASK) | 0x3; - -- if (nv_two_heads(dev)) { -- if (nv_encoder->dcb->location == DCB_LOC_ON_CHIP) -- *cr_lcd |= head ? 0x0 : 0x8; -- else { -- *cr_lcd |= (nv_encoder->dcb->or << 4) & 0x30; -- if (nv_encoder->dcb->type == OUTPUT_LVDS) -- *cr_lcd |= 0x30; -- if ((*cr_lcd & 0x30) == (*cr_lcd_oth & 0x30)) { -- /* avoid being connected to both crtcs */ -- *cr_lcd_oth &= ~0x30; -- NVWriteVgaCrtc(dev, head ^ 1, -- NV_CIO_CRE_LCD__INDEX, -- *cr_lcd_oth); -- } -+ if (nv_two_heads(dev)) { -+ if (nv_encoder->dcb->location == DCB_LOC_ON_CHIP) -+ *cr_lcd |= head ? 0x0 : 0x8; -+ else { -+ *cr_lcd |= (nv_encoder->dcb->or << 4) & 0x30; -+ if (nv_encoder->dcb->type == OUTPUT_LVDS) -+ *cr_lcd |= 0x30; -+ if ((*cr_lcd & 0x30) == (*cr_lcd_oth & 0x30)) { -+ /* avoid being connected to both crtcs */ -+ *cr_lcd_oth &= ~0x30; -+ NVWriteVgaCrtc(dev, head ^ 1, -+ NV_CIO_CRE_LCD__INDEX, -+ *cr_lcd_oth); - } - } - } -@@ -640,7 +638,7 @@ - get_tmds_slave(encoder)) - return; - -- type = nouveau_i2c_identify(dev, "TMDS transmitter", info, 2); -+ type = nouveau_i2c_identify(dev, "TMDS transmitter", info, NULL, 2); - if (type < 0) - return; - -diff -Naur linux-2.6.36/drivers/gpu/drm/nouveau/nv04_fbcon.c linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nv04_fbcon.c ---- linux-2.6.36/drivers/gpu/drm/nouveau/nv04_fbcon.c 2010-10-20 22:30:22.000000000 +0200 -+++ linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nv04_fbcon.c 2010-11-05 00:40:00.000000000 +0100 -@@ -25,54 +25,42 @@ - #include "drmP.h" - #include "nouveau_drv.h" - #include "nouveau_dma.h" -+#include "nouveau_ramht.h" - #include "nouveau_fbcon.h" - --void -+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; -+ int ret; - -- if (info->state != FBINFO_STATE_RUNNING) -- return; -- -- if (!(info->flags & FBINFO_HWACCEL_DISABLED) && RING_SPACE(chan, 4)) { -- nouveau_fbcon_gpu_lockup(info); -- } -- -- if (info->flags & FBINFO_HWACCEL_DISABLED) { -- cfb_copyarea(info, region); -- return; -- } -+ ret = RING_SPACE(chan, 4); -+ if (ret) -+ return ret; - - BEGIN_RING(chan, NvSubImageBlit, 0x0300, 3); - OUT_RING(chan, (region->sy << 16) | region->sx); - OUT_RING(chan, (region->dy << 16) | region->dx); - OUT_RING(chan, (region->height << 16) | region->width); - FIRE_RING(chan); -+ return 0; - } - --void -+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; -+ int ret; - -- if (info->state != FBINFO_STATE_RUNNING) -- return; -- -- if (!(info->flags & FBINFO_HWACCEL_DISABLED) && RING_SPACE(chan, 7)) { -- nouveau_fbcon_gpu_lockup(info); -- } -- -- if (info->flags & FBINFO_HWACCEL_DISABLED) { -- cfb_fillrect(info, rect); -- return; -- } -+ ret = RING_SPACE(chan, 7); -+ if (ret) -+ return ret; - - BEGIN_RING(chan, NvSubGdiRect, 0x02fc, 1); - OUT_RING(chan, (rect->rop != ROP_COPY) ? 1 : 3); -@@ -86,9 +74,10 @@ - OUT_RING(chan, (rect->dx << 16) | rect->dy); - OUT_RING(chan, (rect->width << 16) | rect->height); - FIRE_RING(chan); -+ return 0; - } - --void -+int - nv04_fbcon_imageblit(struct fb_info *info, const struct fb_image *image) - { - struct nouveau_fbdev *nfbdev = info->par; -@@ -100,23 +89,14 @@ - uint32_t dsize; - uint32_t width; - uint32_t *data = (uint32_t *)image->data; -+ int ret; - -- if (info->state != FBINFO_STATE_RUNNING) -- return; -- -- if (image->depth != 1) { -- cfb_imageblit(info, image); -- return; -- } -- -- if (!(info->flags & FBINFO_HWACCEL_DISABLED) && RING_SPACE(chan, 8)) { -- nouveau_fbcon_gpu_lockup(info); -- } -+ if (image->depth != 1) -+ return -ENODEV; - -- if (info->flags & FBINFO_HWACCEL_DISABLED) { -- cfb_imageblit(info, image); -- return; -- } -+ ret = RING_SPACE(chan, 8); -+ if (ret) -+ return ret; - - width = ALIGN(image->width, 8); - dsize = ALIGN(width * image->height, 32) >> 5; -@@ -143,11 +123,9 @@ - while (dsize) { - int iter_len = dsize > 128 ? 128 : dsize; - -- if (RING_SPACE(chan, iter_len + 1)) { -- nouveau_fbcon_gpu_lockup(info); -- cfb_imageblit(info, image); -- return; -- } -+ ret = RING_SPACE(chan, iter_len + 1); -+ if (ret) -+ return ret; - - BEGIN_RING(chan, NvSubGdiRect, 0x0c00, iter_len); - OUT_RINGp(chan, data, iter_len); -@@ -156,6 +134,7 @@ - } - - FIRE_RING(chan); -+ return 0; - } - - static int -@@ -169,11 +148,9 @@ - if (ret) - return ret; - -- ret = nouveau_gpuobj_ref_add(dev, dev_priv->channel, handle, obj, NULL); -- if (ret) -- return ret; -- -- return 0; -+ ret = nouveau_ramht_insert(dev_priv->channel, handle, obj); -+ nouveau_gpuobj_ref(NULL, &obj); -+ return ret; - } - - int -diff -Naur linux-2.6.36/drivers/gpu/drm/nouveau/nv04_fifo.c linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nv04_fifo.c ---- linux-2.6.36/drivers/gpu/drm/nouveau/nv04_fifo.c 2010-10-20 22:30:22.000000000 +0200 -+++ linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nv04_fifo.c 2010-11-05 00:40:00.000000000 +0100 -@@ -27,8 +27,9 @@ - #include "drmP.h" - #include "drm.h" - #include "nouveau_drv.h" -+#include "nouveau_ramht.h" - --#define NV04_RAMFC(c) (dev_priv->ramfc_offset + ((c) * NV04_RAMFC__SIZE)) -+#define NV04_RAMFC(c) (dev_priv->ramfc->pinst + ((c) * NV04_RAMFC__SIZE)) - #define NV04_RAMFC__SIZE 32 - #define NV04_RAMFC_DMA_PUT 0x00 - #define NV04_RAMFC_DMA_GET 0x04 -@@ -38,10 +39,8 @@ - #define NV04_RAMFC_ENGINE 0x14 - #define NV04_RAMFC_PULL1_ENGINE 0x18 - --#define RAMFC_WR(offset, val) nv_wo32(dev, chan->ramfc->gpuobj, \ -- NV04_RAMFC_##offset/4, (val)) --#define RAMFC_RD(offset) nv_ro32(dev, chan->ramfc->gpuobj, \ -- NV04_RAMFC_##offset/4) -+#define RAMFC_WR(offset, val) nv_wo32(chan->ramfc, NV04_RAMFC_##offset, (val)) -+#define RAMFC_RD(offset) nv_ro32(chan->ramfc, NV04_RAMFC_##offset) - - void - nv04_fifo_disable(struct drm_device *dev) -@@ -72,37 +71,32 @@ - } - - bool --nv04_fifo_cache_flush(struct drm_device *dev) --{ -- struct drm_nouveau_private *dev_priv = dev->dev_private; -- struct nouveau_timer_engine *ptimer = &dev_priv->engine.timer; -- uint64_t start = ptimer->read(dev); -- -- do { -- if (nv_rd32(dev, NV03_PFIFO_CACHE1_GET) == -- nv_rd32(dev, NV03_PFIFO_CACHE1_PUT)) -- return true; -- -- } while (ptimer->read(dev) - start < 100000000); -- -- NV_ERROR(dev, "Timeout flushing the PFIFO cache.\n"); -- -- return false; --} -- --bool - nv04_fifo_cache_pull(struct drm_device *dev, bool enable) - { -- uint32_t pull = nv_rd32(dev, NV04_PFIFO_CACHE1_PULL0); -+ 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); - -- if (enable) { -- nv_wr32(dev, NV04_PFIFO_CACHE1_PULL0, pull | 1); -- } else { -- nv_wr32(dev, NV04_PFIFO_CACHE1_PULL0, pull & ~1); - nv_wr32(dev, NV04_PFIFO_CACHE1_HASH, 0); - } - -- return !!(pull & 1); -+ return pull & 1; - } - - int -@@ -130,7 +124,7 @@ - NV04_RAMFC__SIZE, - NVOBJ_FLAG_ZERO_ALLOC | - NVOBJ_FLAG_ZERO_FREE, -- NULL, &chan->ramfc); -+ &chan->ramfc); - if (ret) - return ret; - -@@ -139,7 +133,7 @@ - /* Setup initial state */ - RAMFC_WR(DMA_PUT, chan->pushbuf_base); - RAMFC_WR(DMA_GET, chan->pushbuf_base); -- RAMFC_WR(DMA_INSTANCE, chan->pushbuf->instance >> 4); -+ RAMFC_WR(DMA_INSTANCE, chan->pushbuf->pinst >> 4); - RAMFC_WR(DMA_FETCH, (NV_PFIFO_CACHE1_DMA_FETCH_TRIG_128_BYTES | - NV_PFIFO_CACHE1_DMA_FETCH_SIZE_128_BYTES | - NV_PFIFO_CACHE1_DMA_FETCH_MAX_REQS_8 | -@@ -157,11 +151,28 @@ - nv04_fifo_destroy_context(struct nouveau_channel *chan) - { - struct drm_device *dev = chan->dev; -+ struct drm_nouveau_private *dev_priv = dev->dev_private; -+ struct nouveau_fifo_engine *pfifo = &dev_priv->engine.fifo; -+ unsigned long flags; - -- nv_wr32(dev, NV04_PFIFO_MODE, -- nv_rd32(dev, NV04_PFIFO_MODE) & ~(1 << chan->id)); -+ spin_lock_irqsave(&dev_priv->context_switch_lock, flags); -+ pfifo->reassign(dev, false); -+ -+ /* Unload the context if it's the currently active one */ -+ if (pfifo->channel_id(dev) == chan->id) { -+ pfifo->disable(dev); -+ pfifo->unload_context(dev); -+ pfifo->enable(dev); -+ } -+ -+ /* Keep it from being rescheduled */ -+ nv_mask(dev, NV04_PFIFO_MODE, 1 << chan->id, 0); -+ -+ pfifo->reassign(dev, true); -+ spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags); - -- nouveau_gpuobj_ref_del(dev, &chan->ramfc); -+ /* Free the channel resources */ -+ nouveau_gpuobj_ref(NULL, &chan->ramfc); - } - - static void -@@ -214,7 +225,7 @@ - if (chid < 0 || chid >= dev_priv->engine.fifo.channels) - return 0; - -- chan = dev_priv->fifos[chid]; -+ chan = dev_priv->channels.ptr[chid]; - if (!chan) { - NV_ERROR(dev, "Inactive channel on PFIFO: %d\n", chid); - return -EINVAL; -@@ -264,10 +275,10 @@ - struct drm_nouveau_private *dev_priv = dev->dev_private; - - nv_wr32(dev, NV03_PFIFO_RAMHT, (0x03 << 24) /* search 128 */ | -- ((dev_priv->ramht_bits - 9) << 16) | -- (dev_priv->ramht_offset >> 8)); -- nv_wr32(dev, NV03_PFIFO_RAMRO, dev_priv->ramro_offset>>8); -- nv_wr32(dev, NV03_PFIFO_RAMFC, dev_priv->ramfc_offset >> 8); -+ ((dev_priv->ramht->bits - 9) << 16) | -+ (dev_priv->ramht->gpuobj->pinst >> 8)); -+ nv_wr32(dev, NV03_PFIFO_RAMRO, dev_priv->ramro->pinst >> 8); -+ nv_wr32(dev, NV03_PFIFO_RAMFC, dev_priv->ramfc->pinst >> 8); - } - - static void -@@ -295,7 +306,7 @@ - pfifo->reassign(dev, true); - - for (i = 0; i < dev_priv->engine.fifo.channels; i++) { -- if (dev_priv->fifos[i]) { -+ if (dev_priv->channels.ptr[i]) { - uint32_t mode = nv_rd32(dev, NV04_PFIFO_MODE); - nv_wr32(dev, NV04_PFIFO_MODE, mode | (1 << i)); - } -diff -Naur linux-2.6.36/drivers/gpu/drm/nouveau/nv04_graph.c linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nv04_graph.c ---- linux-2.6.36/drivers/gpu/drm/nouveau/nv04_graph.c 2010-10-20 22:30:22.000000000 +0200 -+++ linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nv04_graph.c 2010-11-05 00:40:00.000000000 +0100 -@@ -26,6 +26,9 @@ - #include "drm.h" - #include "nouveau_drm.h" - #include "nouveau_drv.h" -+#include "nouveau_hw.h" -+ -+static int nv04_graph_register(struct drm_device *dev); - - static uint32_t nv04_graph_ctx_regs[] = { - 0x0040053c, -@@ -357,7 +360,7 @@ - if (chid >= dev_priv->engine.fifo.channels) - return NULL; - -- return dev_priv->fifos[chid]; -+ return dev_priv->channels.ptr[chid]; - } - - void -@@ -376,7 +379,7 @@ - - /* Load context for next channel */ - chid = dev_priv->engine.fifo.channel_id(dev); -- chan = dev_priv->fifos[chid]; -+ chan = dev_priv->channels.ptr[chid]; - if (chan) - nv04_graph_load_context(chan); - -@@ -412,10 +415,25 @@ - - void nv04_graph_destroy_context(struct nouveau_channel *chan) - { -+ struct drm_device *dev = chan->dev; -+ struct drm_nouveau_private *dev_priv = dev->dev_private; -+ struct nouveau_pgraph_engine *pgraph = &dev_priv->engine.graph; - struct graph_state *pgraph_ctx = chan->pgraph_ctx; -+ unsigned long flags; -+ -+ spin_lock_irqsave(&dev_priv->context_switch_lock, flags); -+ pgraph->fifo_access(dev, false); -+ -+ /* Unload the context if it's the currently active one */ -+ if (pgraph->channel(dev) == chan) -+ pgraph->unload_context(dev); - -+ /* Free the context resources */ - kfree(pgraph_ctx); - chan->pgraph_ctx = NULL; -+ -+ pgraph->fifo_access(dev, true); -+ spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags); - } - - int nv04_graph_load_context(struct nouveau_channel *chan) -@@ -468,12 +486,17 @@ - { - struct drm_nouveau_private *dev_priv = dev->dev_private; - uint32_t tmp; -+ int 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); - -+ ret = nv04_graph_register(dev); -+ if (ret) -+ return ret; -+ - /* Enable PGRAPH interrupts */ - nv_wr32(dev, NV03_PGRAPH_INTR, 0xFFFFFFFF); - nv_wr32(dev, NV03_PGRAPH_INTR_EN, 0xFFFFFFFF); -@@ -524,13 +547,27 @@ - } - - static int --nv04_graph_mthd_set_ref(struct nouveau_channel *chan, int grclass, -- int mthd, uint32_t data) -+nv04_graph_mthd_set_ref(struct nouveau_channel *chan, -+ u32 class, u32 mthd, u32 data) - { - atomic_set(&chan->fence.last_sequence_irq, data); - return 0; - } - -+int -+nv04_graph_mthd_page_flip(struct nouveau_channel *chan, -+ u32 class, u32 mthd, u32 data) -+{ -+ struct drm_device *dev = chan->dev; -+ struct nouveau_page_flip_state s; -+ -+ if (!nouveau_finish_page_flip(chan, &s)) -+ nv_set_crtc_base(dev, s.crtc, -+ s.offset + s.y * s.pitch + s.x * s.bpp / 8); -+ -+ return 0; -+} -+ - /* - * Software methods, why they are needed, and how they all work: - * -@@ -606,12 +643,12 @@ - */ - - static void --nv04_graph_set_ctx1(struct nouveau_channel *chan, uint32_t mask, uint32_t value) -+nv04_graph_set_ctx1(struct nouveau_channel *chan, u32 mask, u32 value) - { - struct drm_device *dev = chan->dev; -- uint32_t instance = (nv_rd32(dev, NV04_PGRAPH_CTX_SWITCH4) & 0xffff) << 4; -+ u32 instance = (nv_rd32(dev, NV04_PGRAPH_CTX_SWITCH4) & 0xffff) << 4; - int subc = (nv_rd32(dev, NV04_PGRAPH_TRAPPED_ADDR) >> 13) & 0x7; -- uint32_t tmp; -+ u32 tmp; - - tmp = nv_ri32(dev, instance); - tmp &= ~mask; -@@ -623,11 +660,11 @@ - } - - static void --nv04_graph_set_ctx_val(struct nouveau_channel *chan, uint32_t mask, uint32_t value) -+nv04_graph_set_ctx_val(struct nouveau_channel *chan, u32 mask, u32 value) - { - struct drm_device *dev = chan->dev; -- uint32_t instance = (nv_rd32(dev, NV04_PGRAPH_CTX_SWITCH4) & 0xffff) << 4; -- uint32_t tmp, ctx1; -+ u32 instance = (nv_rd32(dev, NV04_PGRAPH_CTX_SWITCH4) & 0xffff) << 4; -+ u32 tmp, ctx1; - int class, op, valid = 1; - - ctx1 = nv_ri32(dev, instance); -@@ -672,13 +709,13 @@ - } - - static int --nv04_graph_mthd_set_operation(struct nouveau_channel *chan, int grclass, -- int mthd, uint32_t data) -+nv04_graph_mthd_set_operation(struct nouveau_channel *chan, -+ u32 class, u32 mthd, u32 data) - { - if (data > 5) - return 1; - /* Old versions of the objects only accept first three operations. */ -- if (data > 2 && grclass < 0x40) -+ if (data > 2 && class < 0x40) - return 1; - nv04_graph_set_ctx1(chan, 0x00038000, data << 15); - /* changing operation changes set of objects needed for validation */ -@@ -687,8 +724,8 @@ - } - - static int --nv04_graph_mthd_surf3d_clip_h(struct nouveau_channel *chan, int grclass, -- int mthd, uint32_t data) -+nv04_graph_mthd_surf3d_clip_h(struct nouveau_channel *chan, -+ u32 class, u32 mthd, u32 data) - { - uint32_t min = data & 0xffff, max; - uint32_t w = data >> 16; -@@ -706,8 +743,8 @@ - } - - static int --nv04_graph_mthd_surf3d_clip_v(struct nouveau_channel *chan, int grclass, -- int mthd, uint32_t data) -+nv04_graph_mthd_surf3d_clip_v(struct nouveau_channel *chan, -+ u32 class, u32 mthd, u32 data) - { - uint32_t min = data & 0xffff, max; - uint32_t w = data >> 16; -@@ -725,8 +762,8 @@ - } - - static int --nv04_graph_mthd_bind_surf2d(struct nouveau_channel *chan, int grclass, -- int mthd, uint32_t data) -+nv04_graph_mthd_bind_surf2d(struct nouveau_channel *chan, -+ u32 class, u32 mthd, u32 data) - { - switch (nv_ri32(chan->dev, data << 4) & 0xff) { - case 0x30: -@@ -742,8 +779,8 @@ - } - - static int --nv04_graph_mthd_bind_surf2d_swzsurf(struct nouveau_channel *chan, int grclass, -- int mthd, uint32_t data) -+nv04_graph_mthd_bind_surf2d_swzsurf(struct nouveau_channel *chan, -+ u32 class, u32 mthd, u32 data) - { - switch (nv_ri32(chan->dev, data << 4) & 0xff) { - case 0x30: -@@ -763,8 +800,8 @@ - } - - static int --nv04_graph_mthd_bind_nv01_patt(struct nouveau_channel *chan, int grclass, -- int mthd, uint32_t data) -+nv04_graph_mthd_bind_nv01_patt(struct nouveau_channel *chan, -+ u32 class, u32 mthd, u32 data) - { - switch (nv_ri32(chan->dev, data << 4) & 0xff) { - case 0x30: -@@ -778,8 +815,8 @@ - } - - static int --nv04_graph_mthd_bind_nv04_patt(struct nouveau_channel *chan, int grclass, -- int mthd, uint32_t data) -+nv04_graph_mthd_bind_nv04_patt(struct nouveau_channel *chan, -+ u32 class, u32 mthd, u32 data) - { - switch (nv_ri32(chan->dev, data << 4) & 0xff) { - case 0x30: -@@ -793,8 +830,8 @@ - } - - static int --nv04_graph_mthd_bind_rop(struct nouveau_channel *chan, int grclass, -- int mthd, uint32_t data) -+nv04_graph_mthd_bind_rop(struct nouveau_channel *chan, -+ u32 class, u32 mthd, u32 data) - { - switch (nv_ri32(chan->dev, data << 4) & 0xff) { - case 0x30: -@@ -808,8 +845,8 @@ - } - - static int --nv04_graph_mthd_bind_beta1(struct nouveau_channel *chan, int grclass, -- int mthd, uint32_t data) -+nv04_graph_mthd_bind_beta1(struct nouveau_channel *chan, -+ u32 class, u32 mthd, u32 data) - { - switch (nv_ri32(chan->dev, data << 4) & 0xff) { - case 0x30: -@@ -823,8 +860,8 @@ - } - - static int --nv04_graph_mthd_bind_beta4(struct nouveau_channel *chan, int grclass, -- int mthd, uint32_t data) -+nv04_graph_mthd_bind_beta4(struct nouveau_channel *chan, -+ u32 class, u32 mthd, u32 data) - { - switch (nv_ri32(chan->dev, data << 4) & 0xff) { - case 0x30: -@@ -838,8 +875,8 @@ - } - - static int --nv04_graph_mthd_bind_surf_dst(struct nouveau_channel *chan, int grclass, -- int mthd, uint32_t data) -+nv04_graph_mthd_bind_surf_dst(struct nouveau_channel *chan, -+ u32 class, u32 mthd, u32 data) - { - switch (nv_ri32(chan->dev, data << 4) & 0xff) { - case 0x30: -@@ -853,8 +890,8 @@ - } - - static int --nv04_graph_mthd_bind_surf_src(struct nouveau_channel *chan, int grclass, -- int mthd, uint32_t data) -+nv04_graph_mthd_bind_surf_src(struct nouveau_channel *chan, -+ u32 class, u32 mthd, u32 data) - { - switch (nv_ri32(chan->dev, data << 4) & 0xff) { - case 0x30: -@@ -868,8 +905,8 @@ - } - - static int --nv04_graph_mthd_bind_surf_color(struct nouveau_channel *chan, int grclass, -- int mthd, uint32_t data) -+nv04_graph_mthd_bind_surf_color(struct nouveau_channel *chan, -+ u32 class, u32 mthd, u32 data) - { - switch (nv_ri32(chan->dev, data << 4) & 0xff) { - case 0x30: -@@ -883,8 +920,8 @@ - } - - static int --nv04_graph_mthd_bind_surf_zeta(struct nouveau_channel *chan, int grclass, -- int mthd, uint32_t data) -+nv04_graph_mthd_bind_surf_zeta(struct nouveau_channel *chan, -+ u32 class, u32 mthd, u32 data) - { - switch (nv_ri32(chan->dev, data << 4) & 0xff) { - case 0x30: -@@ -898,8 +935,8 @@ - } - - static int --nv04_graph_mthd_bind_clip(struct nouveau_channel *chan, int grclass, -- int mthd, uint32_t data) -+nv04_graph_mthd_bind_clip(struct nouveau_channel *chan, -+ u32 class, u32 mthd, u32 data) - { - switch (nv_ri32(chan->dev, data << 4) & 0xff) { - case 0x30: -@@ -913,8 +950,8 @@ - } - - static int --nv04_graph_mthd_bind_chroma(struct nouveau_channel *chan, int grclass, -- int mthd, uint32_t data) -+nv04_graph_mthd_bind_chroma(struct nouveau_channel *chan, -+ u32 class, u32 mthd, u32 data) - { - switch (nv_ri32(chan->dev, data << 4) & 0xff) { - case 0x30: -@@ -930,194 +967,260 @@ - return 1; - } - --static struct nouveau_pgraph_object_method nv04_graph_mthds_sw[] = { -- { 0x0150, nv04_graph_mthd_set_ref }, -- {} --}; -- --static struct nouveau_pgraph_object_method nv04_graph_mthds_nv03_gdirect[] = { -- { 0x0184, nv04_graph_mthd_bind_nv01_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_pgraph_object_method nv04_graph_mthds_nv04_gdirect[] = { -- { 0x0188, nv04_graph_mthd_bind_nv04_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_pgraph_object_method nv04_graph_mthds_nv01_imageblit[] = { -- { 0x0184, nv04_graph_mthd_bind_chroma }, -- { 0x0188, nv04_graph_mthd_bind_clip }, -- { 0x018c, nv04_graph_mthd_bind_nv01_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_pgraph_object_method nv04_graph_mthds_nv04_imageblit_ifc[] = { -- { 0x0184, nv04_graph_mthd_bind_chroma }, -- { 0x0188, nv04_graph_mthd_bind_clip }, -- { 0x018c, nv04_graph_mthd_bind_nv04_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_pgraph_object_method nv04_graph_mthds_nv04_iifc[] = { -- { 0x0188, nv04_graph_mthd_bind_chroma }, -- { 0x018c, nv04_graph_mthd_bind_clip }, -- { 0x0190, nv04_graph_mthd_bind_nv04_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_pgraph_object_method nv04_graph_mthds_nv01_ifc[] = { -- { 0x0184, nv04_graph_mthd_bind_chroma }, -- { 0x0188, nv04_graph_mthd_bind_clip }, -- { 0x018c, nv04_graph_mthd_bind_nv01_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_pgraph_object_method nv04_graph_mthds_nv03_sifc[] = { -- { 0x0184, nv04_graph_mthd_bind_chroma }, -- { 0x0188, nv04_graph_mthd_bind_nv01_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_pgraph_object_method nv04_graph_mthds_nv04_sifc[] = { -- { 0x0184, nv04_graph_mthd_bind_chroma }, -- { 0x0188, nv04_graph_mthd_bind_nv04_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_pgraph_object_method nv04_graph_mthds_nv03_sifm[] = { -- { 0x0188, nv04_graph_mthd_bind_nv01_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_pgraph_object_method nv04_graph_mthds_nv04_sifm[] = { -- { 0x0188, nv04_graph_mthd_bind_nv04_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_swzsurf }, -- { 0x0304, nv04_graph_mthd_set_operation }, -- {}, --}; -+static int -+nv04_graph_register(struct drm_device *dev) -+{ -+ struct drm_nouveau_private *dev_priv = dev->dev_private; - --static struct nouveau_pgraph_object_method nv04_graph_mthds_nv01_shape[] = { -- { 0x0184, nv04_graph_mthd_bind_clip }, -- { 0x0188, nv04_graph_mthd_bind_nv01_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 }, -- {}, --}; -+ if (dev_priv->engine.graph.registered) -+ return 0; - --static struct nouveau_pgraph_object_method nv04_graph_mthds_nv04_shape[] = { -- { 0x0184, nv04_graph_mthd_bind_clip }, -- { 0x0188, nv04_graph_mthd_bind_nv04_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 }, -- {}, --}; -+ /* dvd subpicture */ -+ NVOBJ_CLASS(dev, 0x0038, GR); - --static struct nouveau_pgraph_object_method nv04_graph_mthds_nv03_tex_tri[] = { -- { 0x0188, nv04_graph_mthd_bind_clip }, -- { 0x018c, nv04_graph_mthd_bind_surf_color }, -- { 0x0190, nv04_graph_mthd_bind_surf_zeta }, -- {}, --}; -+ /* m2mf */ -+ NVOBJ_CLASS(dev, 0x0039, GR); - --static struct nouveau_pgraph_object_method nv04_graph_mthds_surf3d[] = { -- { 0x02f8, nv04_graph_mthd_surf3d_clip_h }, -- { 0x02fc, nv04_graph_mthd_surf3d_clip_v }, -- {}, --}; -+ /* 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); -+ -+ /* nvsw */ -+ NVOBJ_CLASS(dev, 0x506e, SW); -+ NVOBJ_MTHD (dev, 0x506e, 0x0150, nv04_graph_mthd_set_ref); -+ NVOBJ_MTHD (dev, 0x506e, 0x0500, nv04_graph_mthd_page_flip); - --struct nouveau_pgraph_object_class nv04_graph_grclass[] = { -- { 0x0038, false, NULL }, /* dvd subpicture */ -- { 0x0039, false, NULL }, /* m2mf */ -- { 0x004b, false, nv04_graph_mthds_nv03_gdirect }, /* nv03 gdirect */ -- { 0x004a, false, nv04_graph_mthds_nv04_gdirect }, /* nv04 gdirect */ -- { 0x001f, false, nv04_graph_mthds_nv01_imageblit }, /* nv01 imageblit */ -- { 0x005f, false, nv04_graph_mthds_nv04_imageblit_ifc }, /* nv04 imageblit */ -- { 0x0060, false, nv04_graph_mthds_nv04_iifc }, /* nv04 iifc */ -- { 0x0064, false, NULL }, /* nv05 iifc */ -- { 0x0021, false, nv04_graph_mthds_nv01_ifc }, /* nv01 ifc */ -- { 0x0061, false, nv04_graph_mthds_nv04_imageblit_ifc }, /* nv04 ifc */ -- { 0x0065, false, NULL }, /* nv05 ifc */ -- { 0x0036, false, nv04_graph_mthds_nv03_sifc }, /* nv03 sifc */ -- { 0x0076, false, nv04_graph_mthds_nv04_sifc }, /* nv04 sifc */ -- { 0x0066, false, NULL }, /* nv05 sifc */ -- { 0x0037, false, nv04_graph_mthds_nv03_sifm }, /* nv03 sifm */ -- { 0x0077, false, nv04_graph_mthds_nv04_sifm }, /* nv04 sifm */ -- { 0x0030, false, NULL }, /* null */ -- { 0x0042, false, NULL }, /* surf2d */ -- { 0x0043, false, NULL }, /* rop */ -- { 0x0012, false, NULL }, /* beta1 */ -- { 0x0072, false, NULL }, /* beta4 */ -- { 0x0019, false, NULL }, /* cliprect */ -- { 0x0018, false, NULL }, /* nv01 pattern */ -- { 0x0044, false, NULL }, /* nv04 pattern */ -- { 0x0052, false, NULL }, /* swzsurf */ -- { 0x0053, false, nv04_graph_mthds_surf3d }, /* surf3d */ -- { 0x0048, false, nv04_graph_mthds_nv03_tex_tri }, /* nv03 tex_tri */ -- { 0x0054, false, NULL }, /* tex_tri */ -- { 0x0055, false, NULL }, /* multitex_tri */ -- { 0x0017, false, NULL }, /* nv01 chroma */ -- { 0x0057, false, NULL }, /* nv04 chroma */ -- { 0x0058, false, NULL }, /* surf_dst */ -- { 0x0059, false, NULL }, /* surf_src */ -- { 0x005a, false, NULL }, /* surf_color */ -- { 0x005b, false, NULL }, /* surf_zeta */ -- { 0x001c, false, nv04_graph_mthds_nv01_shape }, /* nv01 line */ -- { 0x005c, false, nv04_graph_mthds_nv04_shape }, /* nv04 line */ -- { 0x001d, false, nv04_graph_mthds_nv01_shape }, /* nv01 tri */ -- { 0x005d, false, nv04_graph_mthds_nv04_shape }, /* nv04 tri */ -- { 0x001e, false, nv04_graph_mthds_nv01_shape }, /* nv01 rect */ -- { 0x005e, false, nv04_graph_mthds_nv04_shape }, /* nv04 rect */ -- { 0x506e, true, nv04_graph_mthds_sw }, -- {} -+ dev_priv->engine.graph.registered = true; -+ return 0; - }; -- -diff -Naur linux-2.6.36/drivers/gpu/drm/nouveau/nv04_instmem.c linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nv04_instmem.c ---- linux-2.6.36/drivers/gpu/drm/nouveau/nv04_instmem.c 2010-10-20 22:30:22.000000000 +0200 -+++ linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nv04_instmem.c 2010-11-05 00:40:00.000000000 +0100 -@@ -1,6 +1,7 @@ - #include "drmP.h" - #include "drm.h" - #include "nouveau_drv.h" -+#include "nouveau_ramht.h" - - /* returns the size of fifo context */ - static int -@@ -17,102 +18,51 @@ - return 32; - } - --static void --nv04_instmem_determine_amount(struct drm_device *dev) -+int nv04_instmem_init(struct drm_device *dev) - { - struct drm_nouveau_private *dev_priv = dev->dev_private; -- int i; -+ struct nouveau_gpuobj *ramht = NULL; -+ u32 offset, length; -+ int ret; - -- /* Figure out how much instance memory we need */ -- if (dev_priv->card_type >= NV_40) { -- /* We'll want more instance memory than this on some NV4x cards. -- * There's a 16MB aperture to play with that maps onto the end -- * of vram. For now, only reserve a small piece until we know -- * more about what each chipset requires. -- */ -- switch (dev_priv->chipset) { -- case 0x40: -- case 0x47: -- case 0x49: -- case 0x4b: -- dev_priv->ramin_rsvd_vram = (2 * 1024 * 1024); -- break; -- default: -- dev_priv->ramin_rsvd_vram = (1 * 1024 * 1024); -- break; -- } -- } else { -- /*XXX: what *are* the limits on ramin_rsvd_vram = (512 * 1024); -- } -- NV_DEBUG(dev, "RAMIN size: %dKiB\n", dev_priv->ramin_rsvd_vram >> 10); -+ /* RAMIN always available */ -+ dev_priv->ramin_available = true; - -- /* Clear all of it, except the BIOS image that's in the first 64KiB */ -- for (i = 64 * 1024; i < dev_priv->ramin_rsvd_vram; i += 4) -- nv_wi32(dev, i, 0x00000000); --} -+ /* Setup shared RAMHT */ -+ ret = nouveau_gpuobj_new_fake(dev, 0x10000, ~0, 4096, -+ NVOBJ_FLAG_ZERO_ALLOC, &ramht); -+ if (ret) -+ return ret; - --static void --nv04_instmem_configure_fixed_tables(struct drm_device *dev) --{ -- struct drm_nouveau_private *dev_priv = dev->dev_private; -- struct nouveau_engine *engine = &dev_priv->engine; -+ ret = nouveau_ramht_new(dev, ramht, &dev_priv->ramht); -+ nouveau_gpuobj_ref(NULL, &ramht); -+ if (ret) -+ return ret; - -- /* FIFO hash table (RAMHT) -- * use 4k hash table at RAMIN+0x10000 -- * TODO: extend the hash table -- */ -- dev_priv->ramht_offset = 0x10000; -- dev_priv->ramht_bits = 9; -- dev_priv->ramht_size = (1 << dev_priv->ramht_bits); /* nr entries */ -- dev_priv->ramht_size *= 8; /* 2 32-bit values per entry in RAMHT */ -- NV_DEBUG(dev, "RAMHT offset=0x%x, size=%d\n", dev_priv->ramht_offset, -- dev_priv->ramht_size); -- -- /* FIFO runout table (RAMRO) - 512k at 0x11200 */ -- dev_priv->ramro_offset = 0x11200; -- dev_priv->ramro_size = 512; -- NV_DEBUG(dev, "RAMRO offset=0x%x, size=%d\n", dev_priv->ramro_offset, -- dev_priv->ramro_size); -- -- /* FIFO context table (RAMFC) -- * NV40 : Not sure exactly how to position RAMFC on some cards, -- * 0x30002 seems to position it at RAMIN+0x20000 on these -- * cards. RAMFC is 4kb (32 fifos, 128byte entries). -- * Others: Position RAMFC at RAMIN+0x11400 -- */ -- dev_priv->ramfc_size = engine->fifo.channels * -- nouveau_fifo_ctx_size(dev); -+ /* And RAMRO */ -+ ret = nouveau_gpuobj_new_fake(dev, 0x11200, ~0, 512, -+ NVOBJ_FLAG_ZERO_ALLOC, &dev_priv->ramro); -+ if (ret) -+ return ret; -+ -+ /* And RAMFC */ -+ length = dev_priv->engine.fifo.channels * nouveau_fifo_ctx_size(dev); - switch (dev_priv->card_type) { - case NV_40: -- dev_priv->ramfc_offset = 0x20000; -+ offset = 0x20000; - break; -- case NV_30: -- case NV_20: -- case NV_10: -- case NV_04: - default: -- dev_priv->ramfc_offset = 0x11400; -+ offset = 0x11400; - break; - } -- NV_DEBUG(dev, "RAMFC offset=0x%x, size=%d\n", dev_priv->ramfc_offset, -- dev_priv->ramfc_size); --} - --int nv04_instmem_init(struct drm_device *dev) --{ -- struct drm_nouveau_private *dev_priv = dev->dev_private; -- uint32_t offset; -- int ret; -- -- nv04_instmem_determine_amount(dev); -- nv04_instmem_configure_fixed_tables(dev); -+ ret = nouveau_gpuobj_new_fake(dev, offset, ~0, length, -+ NVOBJ_FLAG_ZERO_ALLOC, &dev_priv->ramfc); -+ if (ret) -+ return ret; - -- /* Create a heap to manage RAMIN allocations, we don't allocate -- * the space that was reserved for RAMHT/FC/RO. -- */ -- offset = dev_priv->ramfc_offset + dev_priv->ramfc_size; -+ /* Only allow space after RAMFC to be used for object allocation */ -+ offset += length; - - /* It appears RAMRO (or something?) is controlled by 0x2220/0x2230 - * on certain NV4x chipsets as well as RAMFC. When 0x2230 == 0 -@@ -140,46 +90,34 @@ - void - nv04_instmem_takedown(struct drm_device *dev) - { -+ struct drm_nouveau_private *dev_priv = dev->dev_private; -+ -+ nouveau_ramht_ref(NULL, &dev_priv->ramht, NULL); -+ nouveau_gpuobj_ref(NULL, &dev_priv->ramro); -+ nouveau_gpuobj_ref(NULL, &dev_priv->ramfc); - } - - int --nv04_instmem_populate(struct drm_device *dev, struct nouveau_gpuobj *gpuobj, uint32_t *sz) -+nv04_instmem_populate(struct drm_device *dev, struct nouveau_gpuobj *gpuobj, -+ u32 *size, u32 align) - { -- if (gpuobj->im_backing) -- return -EINVAL; -- - return 0; - } - - void - nv04_instmem_clear(struct drm_device *dev, struct nouveau_gpuobj *gpuobj) - { -- struct drm_nouveau_private *dev_priv = dev->dev_private; -- -- if (gpuobj && gpuobj->im_backing) { -- if (gpuobj->im_bound) -- dev_priv->engine.instmem.unbind(dev, gpuobj); -- gpuobj->im_backing = NULL; -- } - } - - int - nv04_instmem_bind(struct drm_device *dev, struct nouveau_gpuobj *gpuobj) - { -- if (!gpuobj->im_pramin || gpuobj->im_bound) -- return -EINVAL; -- -- gpuobj->im_bound = 1; - return 0; - } - - int - nv04_instmem_unbind(struct drm_device *dev, struct nouveau_gpuobj *gpuobj) - { -- if (gpuobj->im_bound == 0) -- return -EINVAL; -- -- gpuobj->im_bound = 0; - return 0; - } - -diff -Naur linux-2.6.36/drivers/gpu/drm/nouveau/nv04_pm.c linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nv04_pm.c ---- linux-2.6.36/drivers/gpu/drm/nouveau/nv04_pm.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nv04_pm.c 2010-11-05 00:40:00.000000000 +0100 -@@ -0,0 +1,90 @@ -+/* -+ * Copyright 2010 Red Hat Inc. -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included in -+ * all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR -+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -+ * OTHER DEALINGS IN THE SOFTWARE. -+ * -+ * Authors: Ben Skeggs -+ */ -+ -+#include "drmP.h" -+#include "nouveau_drv.h" -+#include "nouveau_hw.h" -+#include "nouveau_pm.h" -+ -+struct nv04_pm_state { -+ struct pll_lims pll; -+ struct nouveau_pll_vals calc; -+}; -+ -+int -+nv04_pm_clock_get(struct drm_device *dev, u32 id) -+{ -+ return nouveau_hw_get_clock(dev, id); -+} -+ -+void * -+nv04_pm_clock_pre(struct drm_device *dev, struct nouveau_pm_level *perflvl, -+ u32 id, int khz) -+{ -+ struct nv04_pm_state *state; -+ int ret; -+ -+ state = kzalloc(sizeof(*state), GFP_KERNEL); -+ if (!state) -+ return ERR_PTR(-ENOMEM); -+ -+ ret = get_pll_limits(dev, id, &state->pll); -+ if (ret) { -+ kfree(state); -+ return (ret == -ENOENT) ? NULL : ERR_PTR(ret); -+ } -+ -+ ret = nouveau_calc_pll_mnp(dev, &state->pll, khz, &state->calc); -+ if (!ret) { -+ kfree(state); -+ return ERR_PTR(-EINVAL); -+ } -+ -+ return state; -+} -+ -+void -+nv04_pm_clock_set(struct drm_device *dev, void *pre_state) -+{ -+ struct drm_nouveau_private *dev_priv = dev->dev_private; -+ struct nv04_pm_state *state = pre_state; -+ u32 reg = state->pll.reg; -+ -+ /* thank the insane nouveau_hw_setpll() interface for this */ -+ if (dev_priv->card_type >= NV_40) -+ reg += 4; -+ -+ nouveau_hw_setpll(dev, reg, &state->calc); -+ -+ if (dev_priv->card_type < NV_30 && reg == NV_PRAMDAC_MPLL_COEFF) { -+ if (dev_priv->card_type == NV_20) -+ nv_mask(dev, 0x1002c4, 0, 1 << 20); -+ -+ /* Reset the DLLs */ -+ nv_mask(dev, 0x1002c0, 0, 1 << 8); -+ } -+ -+ kfree(state); -+} -+ -diff -Naur linux-2.6.36/drivers/gpu/drm/nouveau/nv04_tv.c linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nv04_tv.c ---- linux-2.6.36/drivers/gpu/drm/nouveau/nv04_tv.c 2010-10-20 22:30:22.000000000 +0200 -+++ linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nv04_tv.c 2010-11-05 00:40:00.000000000 +0100 -@@ -49,8 +49,8 @@ - - int nv04_tv_identify(struct drm_device *dev, int i2c_index) - { -- return nouveau_i2c_identify(dev, "TV encoder", -- nv04_tv_encoder_info, i2c_index); -+ return nouveau_i2c_identify(dev, "TV encoder", nv04_tv_encoder_info, -+ NULL, i2c_index); - } - - -@@ -99,12 +99,10 @@ - - state->tv_setup = 0; - -- if (bind) { -- state->CRTC[NV_CIO_CRE_LCD__INDEX] = 0; -+ if (bind) - state->CRTC[NV_CIO_CRE_49] |= 0x10; -- } else { -+ else - state->CRTC[NV_CIO_CRE_49] &= ~0x10; -- } - - NVWriteVgaCrtc(dev, head, NV_CIO_CRE_LCD__INDEX, - state->CRTC[NV_CIO_CRE_LCD__INDEX]); -diff -Naur linux-2.6.36/drivers/gpu/drm/nouveau/nv10_fb.c linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nv10_fb.c ---- linux-2.6.36/drivers/gpu/drm/nouveau/nv10_fb.c 2010-10-20 22:30:22.000000000 +0200 -+++ linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nv10_fb.c 2010-11-05 00:40:00.000000000 +0100 -@@ -3,23 +3,109 @@ - #include "nouveau_drv.h" - #include "nouveau_drm.h" - -+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; -+} -+ -+static void -+nv20_fb_free_tag(struct drm_device *dev, struct drm_mm_node *mem) -+{ -+ struct drm_nouveau_private *dev_priv = dev->dev_private; -+ -+ spin_lock(&dev_priv->tile.lock); -+ drm_mm_put_block(mem); -+ spin_unlock(&dev_priv->tile.lock); -+} -+ -+void -+nv10_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); -+ -+ tile->addr = addr; -+ tile->limit = max(1u, addr + size) - 1; -+ tile->pitch = pitch; -+ -+ if (dev_priv->card_type == NV_20) { -+ if (flags & NOUVEAU_GEM_TILE_ZETA) { -+ /* -+ * Allocate some of the on-die tag memory, -+ * used to store Z compression meta-data (most -+ * likely just a bitmap determining if a given -+ * tile is compressed or not). -+ */ -+ tile->tag_mem = nv20_fb_alloc_tag(dev, size / 256); -+ -+ if (tile->tag_mem) { -+ /* Enable Z compression */ -+ if (dev_priv->chipset >= 0x25) -+ tile->zcomp = tile->tag_mem->start | -+ (bpp == 16 ? -+ NV25_PFB_ZCOMP_MODE_16 : -+ NV25_PFB_ZCOMP_MODE_32); -+ else -+ tile->zcomp = tile->tag_mem->start | -+ NV20_PFB_ZCOMP_EN | -+ (bpp == 16 ? 0 : -+ NV20_PFB_ZCOMP_MODE_32); -+ } -+ -+ tile->addr |= 3; -+ } else { -+ tile->addr |= 1; -+ } -+ -+ } else { -+ tile->addr |= 1 << 31; -+ } -+} -+ - void --nv10_fb_set_region_tiling(struct drm_device *dev, int i, uint32_t addr, -- uint32_t size, uint32_t pitch) -+nv10_fb_free_tile_region(struct drm_device *dev, int i) - { - struct drm_nouveau_private *dev_priv = dev->dev_private; -- uint32_t limit = max(1u, addr + size) - 1; -+ struct nouveau_tile_reg *tile = &dev_priv->tile.reg[i]; - -- if (pitch) { -- if (dev_priv->card_type >= NV_20) -- addr |= 1; -- else -- addr |= 1 << 31; -+ if (tile->tag_mem) { -+ nv20_fb_free_tag(dev, tile->tag_mem); -+ tile->tag_mem = NULL; - } - -- nv_wr32(dev, NV10_PFB_TLIMIT(i), limit); -- nv_wr32(dev, NV10_PFB_TSIZE(i), pitch); -- nv_wr32(dev, NV10_PFB_TILE(i), addr); -+ tile->addr = tile->limit = tile->pitch = tile->zcomp = 0; -+} -+ -+void -+nv10_fb_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]; -+ -+ 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); -+ -+ if (dev_priv->card_type == NV_20) -+ nv_wr32(dev, NV20_PFB_ZCOMP(i), tile->zcomp); - } - - int -@@ -31,9 +117,14 @@ - - pfb->num_tiles = NV10_PFB_TILE__SIZE; - -+ if (dev_priv->card_type == NV_20) -+ drm_mm_init(&pfb->tag_heap, 0, -+ (dev_priv->chipset >= 0x25 ? -+ 64 * 1024 : 32 * 1024)); -+ - /* Turn all the tiling regions off. */ - for (i = 0; i < pfb->num_tiles; i++) -- pfb->set_region_tiling(dev, i, 0, 0, 0); -+ pfb->set_tile_region(dev, i); - - return 0; - } -@@ -41,4 +132,13 @@ - 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); -+ -+ if (dev_priv->card_type == NV_20) -+ drm_mm_takedown(&pfb->tag_heap); - } -diff -Naur linux-2.6.36/drivers/gpu/drm/nouveau/nv10_fifo.c linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nv10_fifo.c ---- linux-2.6.36/drivers/gpu/drm/nouveau/nv10_fifo.c 2010-10-20 22:30:22.000000000 +0200 -+++ linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nv10_fifo.c 2010-11-05 00:40:00.000000000 +0100 -@@ -27,8 +27,9 @@ - #include "drmP.h" - #include "drm.h" - #include "nouveau_drv.h" -+#include "nouveau_ramht.h" - --#define NV10_RAMFC(c) (dev_priv->ramfc_offset + ((c) * NV10_RAMFC__SIZE)) -+#define NV10_RAMFC(c) (dev_priv->ramfc->pinst + ((c) * NV10_RAMFC__SIZE)) - #define NV10_RAMFC__SIZE ((dev_priv->chipset) >= 0x17 ? 64 : 32) - - int -@@ -48,7 +49,7 @@ - - ret = nouveau_gpuobj_new_fake(dev, NV10_RAMFC(chan->id), ~0, - NV10_RAMFC__SIZE, NVOBJ_FLAG_ZERO_ALLOC | -- NVOBJ_FLAG_ZERO_FREE, NULL, &chan->ramfc); -+ NVOBJ_FLAG_ZERO_FREE, &chan->ramfc); - if (ret) - return ret; - -@@ -57,7 +58,7 @@ - */ - nv_wi32(dev, fc + 0, chan->pushbuf_base); - nv_wi32(dev, fc + 4, chan->pushbuf_base); -- nv_wi32(dev, fc + 12, chan->pushbuf->instance >> 4); -+ nv_wi32(dev, fc + 12, chan->pushbuf->pinst >> 4); - nv_wi32(dev, fc + 20, NV_PFIFO_CACHE1_DMA_FETCH_TRIG_128_BYTES | - NV_PFIFO_CACHE1_DMA_FETCH_SIZE_128_BYTES | - NV_PFIFO_CACHE1_DMA_FETCH_MAX_REQS_8 | -@@ -72,17 +73,6 @@ - return 0; - } - --void --nv10_fifo_destroy_context(struct nouveau_channel *chan) --{ -- struct drm_device *dev = chan->dev; -- -- nv_wr32(dev, NV04_PFIFO_MODE, -- nv_rd32(dev, NV04_PFIFO_MODE) & ~(1 << chan->id)); -- -- nouveau_gpuobj_ref_del(dev, &chan->ramfc); --} -- - static void - nv10_fifo_do_load_context(struct drm_device *dev, int chid) - { -@@ -202,14 +192,14 @@ - struct drm_nouveau_private *dev_priv = dev->dev_private; - - nv_wr32(dev, NV03_PFIFO_RAMHT, (0x03 << 24) /* search 128 */ | -- ((dev_priv->ramht_bits - 9) << 16) | -- (dev_priv->ramht_offset >> 8)); -- nv_wr32(dev, NV03_PFIFO_RAMRO, dev_priv->ramro_offset>>8); -+ ((dev_priv->ramht->bits - 9) << 16) | -+ (dev_priv->ramht->gpuobj->pinst >> 8)); -+ nv_wr32(dev, NV03_PFIFO_RAMRO, dev_priv->ramro->pinst >> 8); - - if (dev_priv->chipset < 0x17) { -- nv_wr32(dev, NV03_PFIFO_RAMFC, dev_priv->ramfc_offset >> 8); -+ nv_wr32(dev, NV03_PFIFO_RAMFC, dev_priv->ramfc->pinst >> 8); - } else { -- nv_wr32(dev, NV03_PFIFO_RAMFC, (dev_priv->ramfc_offset >> 8) | -+ nv_wr32(dev, NV03_PFIFO_RAMFC, (dev_priv->ramfc->pinst >> 8) | - (1 << 16) /* 64 Bytes entry*/); - /* XXX nvidia blob set bit 18, 21,23 for nv20 & nv30 */ - } -@@ -240,7 +230,7 @@ - pfifo->reassign(dev, true); - - for (i = 0; i < dev_priv->engine.fifo.channels; i++) { -- if (dev_priv->fifos[i]) { -+ if (dev_priv->channels.ptr[i]) { - uint32_t mode = nv_rd32(dev, NV04_PFIFO_MODE); - nv_wr32(dev, NV04_PFIFO_MODE, mode | (1 << i)); - } -diff -Naur linux-2.6.36/drivers/gpu/drm/nouveau/nv10_graph.c linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nv10_graph.c ---- linux-2.6.36/drivers/gpu/drm/nouveau/nv10_graph.c 2010-10-20 22:30:22.000000000 +0200 -+++ linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nv10_graph.c 2010-11-05 00:40:00.000000000 +0100 -@@ -27,6 +27,8 @@ - #include "nouveau_drm.h" - #include "nouveau_drv.h" - -+static int nv10_graph_register(struct drm_device *); -+ - #define NV10_FIFO_NUMBER 32 - - struct pipe_state { -@@ -802,8 +804,8 @@ - - /* Load context for next channel */ - chid = (nv_rd32(dev, NV04_PGRAPH_TRAPPED_ADDR) >> 20) & 0x1f; -- chan = dev_priv->fifos[chid]; -- if (chan) -+ chan = dev_priv->channels.ptr[chid]; -+ if (chan && chan->pgraph_ctx) - nv10_graph_load_context(chan); - - pgraph->fifo_access(dev, true); -@@ -833,7 +835,7 @@ - if (chid >= dev_priv->engine.fifo.channels) - return NULL; - -- return dev_priv->fifos[chid]; -+ return dev_priv->channels.ptr[chid]; - } - - int nv10_graph_create_context(struct nouveau_channel *chan) -@@ -875,37 +877,53 @@ - - void nv10_graph_destroy_context(struct nouveau_channel *chan) - { -+ struct drm_device *dev = chan->dev; -+ struct drm_nouveau_private *dev_priv = dev->dev_private; -+ struct nouveau_pgraph_engine *pgraph = &dev_priv->engine.graph; - struct graph_state *pgraph_ctx = chan->pgraph_ctx; -+ unsigned long flags; -+ -+ spin_lock_irqsave(&dev_priv->context_switch_lock, flags); -+ pgraph->fifo_access(dev, false); -+ -+ /* Unload the context if it's the currently active one */ -+ if (pgraph->channel(dev) == chan) -+ pgraph->unload_context(dev); - -+ /* Free the context resources */ - kfree(pgraph_ctx); - chan->pgraph_ctx = NULL; -+ -+ pgraph->fifo_access(dev, true); -+ spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags); - } - - void --nv10_graph_set_region_tiling(struct drm_device *dev, int i, uint32_t addr, -- uint32_t size, uint32_t pitch) -+nv10_graph_set_tile_region(struct drm_device *dev, int i) - { -- uint32_t limit = max(1u, addr + size) - 1; -- -- if (pitch) -- addr |= 1 << 31; -+ struct drm_nouveau_private *dev_priv = dev->dev_private; -+ struct nouveau_tile_reg *tile = &dev_priv->tile.reg[i]; - -- nv_wr32(dev, NV10_PGRAPH_TLIMIT(i), limit); -- nv_wr32(dev, NV10_PGRAPH_TSIZE(i), pitch); -- nv_wr32(dev, NV10_PGRAPH_TILE(i), addr); -+ 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); - } - - int nv10_graph_init(struct drm_device *dev) - { - struct drm_nouveau_private *dev_priv = dev->dev_private; - uint32_t tmp; -- int i; -+ int ret, 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); - -+ ret = nv10_graph_register(dev); -+ if (ret) -+ return ret; -+ - nv_wr32(dev, NV03_PGRAPH_INTR , 0xFFFFFFFF); - nv_wr32(dev, NV03_PGRAPH_INTR_EN, 0xFFFFFFFF); - -@@ -928,7 +946,7 @@ - - /* Turn all the tiling regions off. */ - for (i = 0; i < NV10_PFB_TILE__SIZE; i++) -- nv10_graph_set_region_tiling(dev, i, 0, 0, 0); -+ 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); -@@ -951,8 +969,8 @@ - } - - static int --nv17_graph_mthd_lma_window(struct nouveau_channel *chan, int grclass, -- int mthd, uint32_t data) -+nv17_graph_mthd_lma_window(struct nouveau_channel *chan, -+ u32 class, u32 mthd, u32 data) - { - struct drm_device *dev = chan->dev; - struct graph_state *ctx = chan->pgraph_ctx; -@@ -1031,8 +1049,8 @@ - } - - static int --nv17_graph_mthd_lma_enable(struct nouveau_channel *chan, int grclass, -- int mthd, uint32_t data) -+nv17_graph_mthd_lma_enable(struct nouveau_channel *chan, -+ u32 class, u32 mthd, u32 data) - { - struct drm_device *dev = chan->dev; - struct drm_nouveau_private *dev_priv = dev->dev_private; -@@ -1050,35 +1068,52 @@ - return 0; - } - --static struct nouveau_pgraph_object_method nv17_graph_celsius_mthds[] = { -- { 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 int -+nv10_graph_register(struct drm_device *dev) -+{ -+ struct drm_nouveau_private *dev_priv = dev->dev_private; - --struct nouveau_pgraph_object_class nv10_graph_grclass[] = { -- { 0x0030, false, NULL }, /* null */ -- { 0x0039, false, NULL }, /* m2mf */ -- { 0x004a, false, NULL }, /* gdirect */ -- { 0x005f, false, NULL }, /* imageblit */ -- { 0x009f, false, NULL }, /* imageblit (nv12) */ -- { 0x008a, false, NULL }, /* ifc */ -- { 0x0089, false, NULL }, /* sifm */ -- { 0x0062, false, NULL }, /* surf2d */ -- { 0x0043, false, NULL }, /* rop */ -- { 0x0012, false, NULL }, /* beta1 */ -- { 0x0072, false, NULL }, /* beta4 */ -- { 0x0019, false, NULL }, /* cliprect */ -- { 0x0044, false, NULL }, /* pattern */ -- { 0x0052, false, NULL }, /* swzsurf */ -- { 0x0093, false, NULL }, /* surf3d */ -- { 0x0094, false, NULL }, /* tex_tri */ -- { 0x0095, false, NULL }, /* multitex_tri */ -- { 0x0056, false, NULL }, /* celcius (nv10) */ -- { 0x0096, false, NULL }, /* celcius (nv11) */ -- { 0x0099, false, nv17_graph_celsius_mthds }, /* celcius (nv17) */ -- {} --}; -+ if (dev_priv->engine.graph.registered) -+ return 0; -+ -+ NVOBJ_CLASS(dev, 0x506e, SW); /* nvsw */ -+ 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); -+ } 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); -+ } -+ -+ /* nvsw */ -+ NVOBJ_CLASS(dev, 0x506e, SW); -+ NVOBJ_MTHD (dev, 0x506e, 0x0500, nv04_graph_mthd_page_flip); -+ -+ dev_priv->engine.graph.registered = true; -+ return 0; -+} -diff -Naur linux-2.6.36/drivers/gpu/drm/nouveau/nv17_tv.c linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nv17_tv.c ---- linux-2.6.36/drivers/gpu/drm/nouveau/nv17_tv.c 2010-10-20 22:30:22.000000000 +0200 -+++ linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nv17_tv.c 2010-11-05 00:40:00.000000000 +0100 -@@ -193,55 +193,56 @@ - } - } - --static const struct { -- int hdisplay; -- int vdisplay; --} modes[] = { -- { 640, 400 }, -- { 640, 480 }, -- { 720, 480 }, -- { 720, 576 }, -- { 800, 600 }, -- { 1024, 768 }, -- { 1280, 720 }, -- { 1280, 1024 }, -- { 1920, 1080 } --}; -- --static int nv17_tv_get_modes(struct drm_encoder *encoder, -- struct drm_connector *connector) -+static int nv17_tv_get_ld_modes(struct drm_encoder *encoder, -+ struct drm_connector *connector) - { - struct nv17_tv_norm_params *tv_norm = get_tv_norm(encoder); -- struct drm_display_mode *mode; -- struct drm_display_mode *output_mode; -+ struct drm_display_mode *mode, *tv_mode; - int n = 0; -- int i; -- -- if (tv_norm->kind != CTV_ENC_MODE) { -- struct drm_display_mode *tv_mode; - -- for (tv_mode = nv17_tv_modes; tv_mode->hdisplay; tv_mode++) { -- mode = drm_mode_duplicate(encoder->dev, tv_mode); -+ for (tv_mode = nv17_tv_modes; tv_mode->hdisplay; tv_mode++) { -+ mode = drm_mode_duplicate(encoder->dev, tv_mode); - -- mode->clock = tv_norm->tv_enc_mode.vrefresh * -- mode->htotal / 1000 * -- mode->vtotal / 1000; -+ mode->clock = tv_norm->tv_enc_mode.vrefresh * -+ mode->htotal / 1000 * -+ mode->vtotal / 1000; - -- if (mode->flags & DRM_MODE_FLAG_DBLSCAN) -- mode->clock *= 2; -+ if (mode->flags & DRM_MODE_FLAG_DBLSCAN) -+ mode->clock *= 2; - -- if (mode->hdisplay == tv_norm->tv_enc_mode.hdisplay && -- mode->vdisplay == tv_norm->tv_enc_mode.vdisplay) -- mode->type |= DRM_MODE_TYPE_PREFERRED; -+ if (mode->hdisplay == tv_norm->tv_enc_mode.hdisplay && -+ mode->vdisplay == tv_norm->tv_enc_mode.vdisplay) -+ mode->type |= DRM_MODE_TYPE_PREFERRED; - -- drm_mode_probed_add(connector, mode); -- n++; -- } -- return n; -+ drm_mode_probed_add(connector, mode); -+ n++; - } - -- /* tv_norm->kind == CTV_ENC_MODE */ -- output_mode = &tv_norm->ctv_enc_mode.mode; -+ return n; -+} -+ -+static int nv17_tv_get_hd_modes(struct drm_encoder *encoder, -+ struct drm_connector *connector) -+{ -+ struct nv17_tv_norm_params *tv_norm = get_tv_norm(encoder); -+ struct drm_display_mode *output_mode = &tv_norm->ctv_enc_mode.mode; -+ struct drm_display_mode *mode; -+ const struct { -+ int hdisplay; -+ int vdisplay; -+ } modes[] = { -+ { 640, 400 }, -+ { 640, 480 }, -+ { 720, 480 }, -+ { 720, 576 }, -+ { 800, 600 }, -+ { 1024, 768 }, -+ { 1280, 720 }, -+ { 1280, 1024 }, -+ { 1920, 1080 } -+ }; -+ int i, n = 0; -+ - for (i = 0; i < ARRAY_SIZE(modes); i++) { - if (modes[i].hdisplay > output_mode->hdisplay || - modes[i].vdisplay > output_mode->vdisplay) -@@ -251,11 +252,12 @@ - modes[i].vdisplay == output_mode->vdisplay) { - mode = drm_mode_duplicate(encoder->dev, output_mode); - mode->type |= DRM_MODE_TYPE_PREFERRED; -+ - } else { - mode = drm_cvt_mode(encoder->dev, modes[i].hdisplay, -- modes[i].vdisplay, 60, false, -- output_mode->flags & DRM_MODE_FLAG_INTERLACE, -- false); -+ modes[i].vdisplay, 60, false, -+ (output_mode->flags & -+ DRM_MODE_FLAG_INTERLACE), false); - } - - /* CVT modes are sometimes unsuitable... */ -@@ -266,6 +268,7 @@ - - mode->hdisplay) * 9 / 10) & ~7; - mode->hsync_end = mode->hsync_start + 8; - } -+ - if (output_mode->vdisplay >= 1024) { - mode->vtotal = output_mode->vtotal; - mode->vsync_start = output_mode->vsync_start; -@@ -276,9 +279,21 @@ - drm_mode_probed_add(connector, mode); - n++; - } -+ - return n; - } - -+static int nv17_tv_get_modes(struct drm_encoder *encoder, -+ struct drm_connector *connector) -+{ -+ struct nv17_tv_norm_params *tv_norm = get_tv_norm(encoder); -+ -+ if (tv_norm->kind == CTV_ENC_MODE) -+ return nv17_tv_get_hd_modes(encoder, connector); -+ else -+ return nv17_tv_get_ld_modes(encoder, connector); -+} -+ - static int nv17_tv_mode_valid(struct drm_encoder *encoder, - struct drm_display_mode *mode) - { -@@ -408,15 +423,8 @@ - - } - -- /* Some NV4x have unknown values (0x3f, 0x50, 0x54, 0x6b, 0x79, 0x7f) -- * at LCD__INDEX which we don't alter -- */ -- if (!(*cr_lcd & 0x44)) { -- if (tv_norm->kind == CTV_ENC_MODE) -- *cr_lcd = 0x1 | (head ? 0x0 : 0x8); -- else -- *cr_lcd = 0; -- } -+ if (tv_norm->kind == CTV_ENC_MODE) -+ *cr_lcd |= 0x1 | (head ? 0x0 : 0x8); - - /* Set the DACCLK register */ - dacclk = (NVReadRAMDAC(dev, 0, dacclk_off) & ~0x30) | 0x1; -diff -Naur linux-2.6.36/drivers/gpu/drm/nouveau/nv17_tv.h linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nv17_tv.h ---- linux-2.6.36/drivers/gpu/drm/nouveau/nv17_tv.h 2010-10-20 22:30:22.000000000 +0200 -+++ linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nv17_tv.h 2010-11-05 00:40:00.000000000 +0100 -@@ -127,7 +127,8 @@ - - /* TV hardware access functions */ - --static inline void nv_write_ptv(struct drm_device *dev, uint32_t reg, uint32_t val) -+static inline void nv_write_ptv(struct drm_device *dev, uint32_t reg, -+ uint32_t val) - { - nv_wr32(dev, reg, val); - } -@@ -137,7 +138,8 @@ - return nv_rd32(dev, reg); - } - --static inline void nv_write_tv_enc(struct drm_device *dev, uint8_t reg, uint8_t val) -+static inline void nv_write_tv_enc(struct drm_device *dev, uint8_t reg, -+ uint8_t val) - { - nv_write_ptv(dev, NV_PTV_TV_INDEX, reg); - nv_write_ptv(dev, NV_PTV_TV_DATA, val); -@@ -149,8 +151,11 @@ - return nv_read_ptv(dev, NV_PTV_TV_DATA); - } - --#define nv_load_ptv(dev, state, reg) nv_write_ptv(dev, NV_PTV_OFFSET + 0x##reg, state->ptv_##reg) --#define nv_save_ptv(dev, state, reg) state->ptv_##reg = nv_read_ptv(dev, NV_PTV_OFFSET + 0x##reg) --#define nv_load_tv_enc(dev, state, reg) nv_write_tv_enc(dev, 0x##reg, state->tv_enc[0x##reg]) -+#define nv_load_ptv(dev, state, reg) \ -+ nv_write_ptv(dev, NV_PTV_OFFSET + 0x##reg, state->ptv_##reg) -+#define nv_save_ptv(dev, state, reg) \ -+ state->ptv_##reg = nv_read_ptv(dev, NV_PTV_OFFSET + 0x##reg) -+#define nv_load_tv_enc(dev, state, reg) \ -+ nv_write_tv_enc(dev, 0x##reg, state->tv_enc[0x##reg]) - - #endif -diff -Naur linux-2.6.36/drivers/gpu/drm/nouveau/nv17_tv_modes.c linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nv17_tv_modes.c ---- linux-2.6.36/drivers/gpu/drm/nouveau/nv17_tv_modes.c 2010-10-20 22:30:22.000000000 +0200 -+++ linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nv17_tv_modes.c 2010-11-05 00:40:00.000000000 +0100 -@@ -336,12 +336,17 @@ - struct filter_params *p = &fparams[k][j]; - - for (i = 0; i < 7; i++) { -- int64_t c = (p->k1 + p->ki*i + p->ki2*i*i + p->ki3*i*i*i) -- + (p->kr + p->kir*i + p->ki2r*i*i + p->ki3r*i*i*i)*rs[k] -- + (p->kf + p->kif*i + p->ki2f*i*i + p->ki3f*i*i*i)*flicker -- + (p->krf + p->kirf*i + p->ki2rf*i*i + p->ki3rf*i*i*i)*flicker*rs[k]; -+ int64_t c = (p->k1 + p->ki*i + p->ki2*i*i + -+ p->ki3*i*i*i) -+ + (p->kr + p->kir*i + p->ki2r*i*i + -+ p->ki3r*i*i*i) * rs[k] -+ + (p->kf + p->kif*i + p->ki2f*i*i + -+ p->ki3f*i*i*i) * flicker -+ + (p->krf + p->kirf*i + p->ki2rf*i*i + -+ p->ki3rf*i*i*i) * flicker * rs[k]; - -- (*filters[k])[j][i] = (c + id5/2) >> 39 & (0x1 << 31 | 0x7f << 9); -+ (*filters[k])[j][i] = (c + id5/2) >> 39 -+ & (0x1 << 31 | 0x7f << 9); - } - } - } -@@ -349,7 +354,8 @@ - - /* Hardware state saving/restoring */ - --static void tv_save_filter(struct drm_device *dev, uint32_t base, uint32_t regs[4][7]) -+static void tv_save_filter(struct drm_device *dev, uint32_t base, -+ uint32_t regs[4][7]) - { - int i, j; - uint32_t offsets[] = { base, base + 0x1c, base + 0x40, base + 0x5c }; -@@ -360,7 +366,8 @@ - } - } - --static void tv_load_filter(struct drm_device *dev, uint32_t base, uint32_t regs[4][7]) -+static void tv_load_filter(struct drm_device *dev, uint32_t base, -+ uint32_t regs[4][7]) - { - int i, j; - uint32_t offsets[] = { base, base + 0x1c, base + 0x40, base + 0x5c }; -@@ -504,10 +511,10 @@ - break; - } - -- regs->tv_enc[0x20] = interpolate(0, tv_norm->tv_enc_mode.tv_enc[0x20], 255, -- tv_enc->saturation); -- regs->tv_enc[0x22] = interpolate(0, tv_norm->tv_enc_mode.tv_enc[0x22], 255, -- tv_enc->saturation); -+ regs->tv_enc[0x20] = interpolate(0, tv_norm->tv_enc_mode.tv_enc[0x20], -+ 255, tv_enc->saturation); -+ regs->tv_enc[0x22] = interpolate(0, tv_norm->tv_enc_mode.tv_enc[0x22], -+ 255, tv_enc->saturation); - regs->tv_enc[0x25] = tv_enc->hue * 255 / 100; - - nv_load_ptv(dev, regs, 204); -@@ -541,7 +548,8 @@ - int head = nouveau_crtc(encoder->crtc)->index; - struct nv04_crtc_reg *regs = &dev_priv->mode_reg.crtc_reg[head]; - struct drm_display_mode *crtc_mode = &encoder->crtc->mode; -- struct drm_display_mode *output_mode = &get_tv_norm(encoder)->ctv_enc_mode.mode; -+ struct drm_display_mode *output_mode = -+ &get_tv_norm(encoder)->ctv_enc_mode.mode; - int overscan, hmargin, vmargin, hratio, vratio; - - /* The rescaler doesn't do the right thing for interlaced modes. */ -@@ -553,13 +561,15 @@ - hmargin = (output_mode->hdisplay - crtc_mode->hdisplay) / 2; - vmargin = (output_mode->vdisplay - crtc_mode->vdisplay) / 2; - -- hmargin = interpolate(0, min(hmargin, output_mode->hdisplay/20), hmargin, -- overscan); -- vmargin = interpolate(0, min(vmargin, output_mode->vdisplay/20), vmargin, -- overscan); -- -- hratio = crtc_mode->hdisplay * 0x800 / (output_mode->hdisplay - 2*hmargin); -- vratio = crtc_mode->vdisplay * 0x800 / (output_mode->vdisplay - 2*vmargin) & ~3; -+ hmargin = interpolate(0, min(hmargin, output_mode->hdisplay/20), -+ hmargin, overscan); -+ vmargin = interpolate(0, min(vmargin, output_mode->vdisplay/20), -+ vmargin, overscan); -+ -+ hratio = crtc_mode->hdisplay * 0x800 / -+ (output_mode->hdisplay - 2*hmargin); -+ vratio = crtc_mode->vdisplay * 0x800 / -+ (output_mode->vdisplay - 2*vmargin) & ~3; - - regs->fp_horiz_regs[FP_VALID_START] = hmargin; - regs->fp_horiz_regs[FP_VALID_END] = output_mode->hdisplay - hmargin - 1; -diff -Naur linux-2.6.36/drivers/gpu/drm/nouveau/nv20_graph.c linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nv20_graph.c ---- linux-2.6.36/drivers/gpu/drm/nouveau/nv20_graph.c 2010-10-20 22:30:22.000000000 +0200 -+++ linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nv20_graph.c 2010-11-05 00:40:00.000000000 +0100 -@@ -32,54 +32,57 @@ - #define NV34_GRCTX_SIZE (18140) - #define NV35_36_GRCTX_SIZE (22396) - -+static int nv20_graph_register(struct drm_device *); -+static int nv30_graph_register(struct drm_device *); -+ - static void - nv20_graph_context_init(struct drm_device *dev, struct nouveau_gpuobj *ctx) - { - int i; - -- nv_wo32(dev, ctx, 0x033c/4, 0xffff0000); -- nv_wo32(dev, ctx, 0x03a0/4, 0x0fff0000); -- nv_wo32(dev, ctx, 0x03a4/4, 0x0fff0000); -- nv_wo32(dev, ctx, 0x047c/4, 0x00000101); -- nv_wo32(dev, ctx, 0x0490/4, 0x00000111); -- nv_wo32(dev, ctx, 0x04a8/4, 0x44400000); -+ 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(dev, ctx, i/4, 0x00030303); -+ nv_wo32(ctx, i, 0x00030303); - for (i = 0x04f4; i <= 0x0500; i += 4) -- nv_wo32(dev, ctx, i/4, 0x00080000); -+ nv_wo32(ctx, i, 0x00080000); - for (i = 0x050c; i <= 0x0518; i += 4) -- nv_wo32(dev, ctx, i/4, 0x01012000); -+ nv_wo32(ctx, i, 0x01012000); - for (i = 0x051c; i <= 0x0528; i += 4) -- nv_wo32(dev, ctx, i/4, 0x000105b8); -+ nv_wo32(ctx, i, 0x000105b8); - for (i = 0x052c; i <= 0x0538; i += 4) -- nv_wo32(dev, ctx, i/4, 0x00080008); -+ nv_wo32(ctx, i, 0x00080008); - for (i = 0x055c; i <= 0x0598; i += 4) -- nv_wo32(dev, ctx, i/4, 0x07ff0000); -- nv_wo32(dev, ctx, 0x05a4/4, 0x4b7fffff); -- nv_wo32(dev, ctx, 0x05fc/4, 0x00000001); -- nv_wo32(dev, ctx, 0x0604/4, 0x00004000); -- nv_wo32(dev, ctx, 0x0610/4, 0x00000001); -- nv_wo32(dev, ctx, 0x0618/4, 0x00040000); -- nv_wo32(dev, ctx, 0x061c/4, 0x00010000); -+ 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 = 0x1c1c; i <= 0x248c; i += 16) { -- nv_wo32(dev, ctx, (i + 0)/4, 0x10700ff9); -- nv_wo32(dev, ctx, (i + 4)/4, 0x0436086c); -- nv_wo32(dev, ctx, (i + 8)/4, 0x000c001b); -- } -- nv_wo32(dev, ctx, 0x281c/4, 0x3f800000); -- nv_wo32(dev, ctx, 0x2830/4, 0x3f800000); -- nv_wo32(dev, ctx, 0x285c/4, 0x40000000); -- nv_wo32(dev, ctx, 0x2860/4, 0x3f800000); -- nv_wo32(dev, ctx, 0x2864/4, 0x3f000000); -- nv_wo32(dev, ctx, 0x286c/4, 0x40000000); -- nv_wo32(dev, ctx, 0x2870/4, 0x3f800000); -- nv_wo32(dev, ctx, 0x2878/4, 0xbf800000); -- nv_wo32(dev, ctx, 0x2880/4, 0xbf800000); -- nv_wo32(dev, ctx, 0x34a4/4, 0x000fe000); -- nv_wo32(dev, ctx, 0x3530/4, 0x000003f8); -- nv_wo32(dev, ctx, 0x3540/4, 0x002fe000); -+ nv_wo32(ctx, (i + 0), 0x10700ff9); -+ nv_wo32(ctx, (i + 4), 0x0436086c); -+ nv_wo32(ctx, (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); - for (i = 0x355c; i <= 0x3578; i += 4) -- nv_wo32(dev, ctx, i/4, 0x001c527c); -+ nv_wo32(ctx, i, 0x001c527c); - } - - static void -@@ -87,58 +90,58 @@ - { - int i; - -- nv_wo32(dev, ctx, 0x035c/4, 0xffff0000); -- nv_wo32(dev, ctx, 0x03c0/4, 0x0fff0000); -- nv_wo32(dev, ctx, 0x03c4/4, 0x0fff0000); -- nv_wo32(dev, ctx, 0x049c/4, 0x00000101); -- nv_wo32(dev, ctx, 0x04b0/4, 0x00000111); -- nv_wo32(dev, ctx, 0x04c8/4, 0x00000080); -- nv_wo32(dev, ctx, 0x04cc/4, 0xffff0000); -- nv_wo32(dev, ctx, 0x04d0/4, 0x00000001); -- nv_wo32(dev, ctx, 0x04e4/4, 0x44400000); -- nv_wo32(dev, ctx, 0x04fc/4, 0x4b800000); -+ 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(dev, ctx, i/4, 0x00030303); -+ nv_wo32(ctx, i, 0x00030303); - for (i = 0x0530; i <= 0x053c; i += 4) -- nv_wo32(dev, ctx, i/4, 0x00080000); -+ nv_wo32(ctx, i, 0x00080000); - for (i = 0x0548; i <= 0x0554; i += 4) -- nv_wo32(dev, ctx, i/4, 0x01012000); -+ nv_wo32(ctx, i, 0x01012000); - for (i = 0x0558; i <= 0x0564; i += 4) -- nv_wo32(dev, ctx, i/4, 0x000105b8); -+ nv_wo32(ctx, i, 0x000105b8); - for (i = 0x0568; i <= 0x0574; i += 4) -- nv_wo32(dev, ctx, i/4, 0x00080008); -+ nv_wo32(ctx, i, 0x00080008); - for (i = 0x0598; i <= 0x05d4; i += 4) -- nv_wo32(dev, ctx, i/4, 0x07ff0000); -- nv_wo32(dev, ctx, 0x05e0/4, 0x4b7fffff); -- nv_wo32(dev, ctx, 0x0620/4, 0x00000080); -- nv_wo32(dev, ctx, 0x0624/4, 0x30201000); -- nv_wo32(dev, ctx, 0x0628/4, 0x70605040); -- nv_wo32(dev, ctx, 0x062c/4, 0xb0a09080); -- nv_wo32(dev, ctx, 0x0630/4, 0xf0e0d0c0); -- nv_wo32(dev, ctx, 0x0664/4, 0x00000001); -- nv_wo32(dev, ctx, 0x066c/4, 0x00004000); -- nv_wo32(dev, ctx, 0x0678/4, 0x00000001); -- nv_wo32(dev, ctx, 0x0680/4, 0x00040000); -- nv_wo32(dev, ctx, 0x0684/4, 0x00010000); -+ 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(dev, ctx, (i + 0)/4, 0x10700ff9); -- nv_wo32(dev, ctx, (i + 4)/4, 0x0436086c); -- nv_wo32(dev, ctx, (i + 8)/4, 0x000c001b); -- } -- nv_wo32(dev, ctx, 0x2704/4, 0x3f800000); -- nv_wo32(dev, ctx, 0x2718/4, 0x3f800000); -- nv_wo32(dev, ctx, 0x2744/4, 0x40000000); -- nv_wo32(dev, ctx, 0x2748/4, 0x3f800000); -- nv_wo32(dev, ctx, 0x274c/4, 0x3f000000); -- nv_wo32(dev, ctx, 0x2754/4, 0x40000000); -- nv_wo32(dev, ctx, 0x2758/4, 0x3f800000); -- nv_wo32(dev, ctx, 0x2760/4, 0xbf800000); -- nv_wo32(dev, ctx, 0x2768/4, 0xbf800000); -- nv_wo32(dev, ctx, 0x308c/4, 0x000fe000); -- nv_wo32(dev, ctx, 0x3108/4, 0x000003f8); -- nv_wo32(dev, ctx, 0x3468/4, 0x002fe000); -+ 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(dev, ctx, i/4, 0x001c527c); -+ nv_wo32(ctx, i, 0x001c527c); - } - - static void -@@ -146,49 +149,49 @@ - { - int i; - -- nv_wo32(dev, ctx, 0x033c/4, 0xffff0000); -- nv_wo32(dev, ctx, 0x03a0/4, 0x0fff0000); -- nv_wo32(dev, ctx, 0x03a4/4, 0x0fff0000); -- nv_wo32(dev, ctx, 0x047c/4, 0x00000101); -- nv_wo32(dev, ctx, 0x0490/4, 0x00000111); -- nv_wo32(dev, ctx, 0x04a8/4, 0x44400000); -+ 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(dev, ctx, i/4, 0x00030303); -+ nv_wo32(ctx, i, 0x00030303); - for (i = 0x04f4; i <= 0x0500; i += 4) -- nv_wo32(dev, ctx, i/4, 0x00080000); -+ nv_wo32(ctx, i, 0x00080000); - for (i = 0x050c; i <= 0x0518; i += 4) -- nv_wo32(dev, ctx, i/4, 0x01012000); -+ nv_wo32(ctx, i, 0x01012000); - for (i = 0x051c; i <= 0x0528; i += 4) -- nv_wo32(dev, ctx, i/4, 0x000105b8); -+ nv_wo32(ctx, i, 0x000105b8); - for (i = 0x052c; i <= 0x0538; i += 4) -- nv_wo32(dev, ctx, i/4, 0x00080008); -+ nv_wo32(ctx, i, 0x00080008); - for (i = 0x055c; i <= 0x0598; i += 4) -- nv_wo32(dev, ctx, i/4, 0x07ff0000); -- nv_wo32(dev, ctx, 0x05a4/4, 0x4b7fffff); -- nv_wo32(dev, ctx, 0x05fc/4, 0x00000001); -- nv_wo32(dev, ctx, 0x0604/4, 0x00004000); -- nv_wo32(dev, ctx, 0x0610/4, 0x00000001); -- nv_wo32(dev, ctx, 0x0618/4, 0x00040000); -- nv_wo32(dev, ctx, 0x061c/4, 0x00010000); -+ 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(dev, ctx, (i + 0)/4, 0x10700ff9); -- nv_wo32(dev, ctx, (i + 4)/4, 0x0436086c); -- nv_wo32(dev, ctx, (i + 8)/4, 0x000c001b); -- } -- nv_wo32(dev, ctx, 0x269c/4, 0x3f800000); -- nv_wo32(dev, ctx, 0x26b0/4, 0x3f800000); -- nv_wo32(dev, ctx, 0x26dc/4, 0x40000000); -- nv_wo32(dev, ctx, 0x26e0/4, 0x3f800000); -- nv_wo32(dev, ctx, 0x26e4/4, 0x3f000000); -- nv_wo32(dev, ctx, 0x26ec/4, 0x40000000); -- nv_wo32(dev, ctx, 0x26f0/4, 0x3f800000); -- nv_wo32(dev, ctx, 0x26f8/4, 0xbf800000); -- nv_wo32(dev, ctx, 0x2700/4, 0xbf800000); -- nv_wo32(dev, ctx, 0x3024/4, 0x000fe000); -- nv_wo32(dev, ctx, 0x30a0/4, 0x000003f8); -- nv_wo32(dev, ctx, 0x33fc/4, 0x002fe000); -+ 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(dev, ctx, i/4, 0x001c527c); -+ nv_wo32(ctx, i, 0x001c527c); - } - - static void -@@ -196,57 +199,57 @@ - { - int i; - -- nv_wo32(dev, ctx, 0x0410/4, 0x00000101); -- nv_wo32(dev, ctx, 0x0424/4, 0x00000111); -- nv_wo32(dev, ctx, 0x0428/4, 0x00000060); -- nv_wo32(dev, ctx, 0x0444/4, 0x00000080); -- nv_wo32(dev, ctx, 0x0448/4, 0xffff0000); -- nv_wo32(dev, ctx, 0x044c/4, 0x00000001); -- nv_wo32(dev, ctx, 0x0460/4, 0x44400000); -- nv_wo32(dev, ctx, 0x048c/4, 0xffff0000); -+ 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(dev, ctx, i/4, 0x0fff0000); -- nv_wo32(dev, ctx, 0x04ec/4, 0x00011100); -+ nv_wo32(ctx, i, 0x0fff0000); -+ nv_wo32(ctx, 0x04ec, 0x00011100); - for (i = 0x0508; i < 0x0548; i += 4) -- nv_wo32(dev, ctx, i/4, 0x07ff0000); -- nv_wo32(dev, ctx, 0x0550/4, 0x4b7fffff); -- nv_wo32(dev, ctx, 0x058c/4, 0x00000080); -- nv_wo32(dev, ctx, 0x0590/4, 0x30201000); -- nv_wo32(dev, ctx, 0x0594/4, 0x70605040); -- nv_wo32(dev, ctx, 0x0598/4, 0xb8a89888); -- nv_wo32(dev, ctx, 0x059c/4, 0xf8e8d8c8); -- nv_wo32(dev, ctx, 0x05b0/4, 0xb0000000); -+ 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(dev, ctx, i/4, 0x00010588); -+ nv_wo32(ctx, i, 0x00010588); - for (i = 0x0640; i < 0x0680; i += 4) -- nv_wo32(dev, ctx, i/4, 0x00030303); -+ nv_wo32(ctx, i, 0x00030303); - for (i = 0x06c0; i < 0x0700; i += 4) -- nv_wo32(dev, ctx, i/4, 0x0008aae4); -+ nv_wo32(ctx, i, 0x0008aae4); - for (i = 0x0700; i < 0x0740; i += 4) -- nv_wo32(dev, ctx, i/4, 0x01012000); -+ nv_wo32(ctx, i, 0x01012000); - for (i = 0x0740; i < 0x0780; i += 4) -- nv_wo32(dev, ctx, i/4, 0x00080008); -- nv_wo32(dev, ctx, 0x085c/4, 0x00040000); -- nv_wo32(dev, ctx, 0x0860/4, 0x00010000); -+ nv_wo32(ctx, i, 0x00080008); -+ nv_wo32(ctx, 0x085c, 0x00040000); -+ nv_wo32(ctx, 0x0860, 0x00010000); - for (i = 0x0864; i < 0x0874; i += 4) -- nv_wo32(dev, ctx, i/4, 0x00040004); -+ nv_wo32(ctx, i, 0x00040004); - for (i = 0x1f18; i <= 0x3088 ; i += 16) { -- nv_wo32(dev, ctx, i/4 + 0, 0x10700ff9); -- nv_wo32(dev, ctx, i/4 + 1, 0x0436086c); -- nv_wo32(dev, ctx, i/4 + 2, 0x000c001b); -+ 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(dev, ctx, i/4, 0x0000ffff); -- nv_wo32(dev, ctx, 0x344c/4, 0x3f800000); -- nv_wo32(dev, ctx, 0x3808/4, 0x3f800000); -- nv_wo32(dev, ctx, 0x381c/4, 0x3f800000); -- nv_wo32(dev, ctx, 0x3848/4, 0x40000000); -- nv_wo32(dev, ctx, 0x384c/4, 0x3f800000); -- nv_wo32(dev, ctx, 0x3850/4, 0x3f000000); -- nv_wo32(dev, ctx, 0x3858/4, 0x40000000); -- nv_wo32(dev, ctx, 0x385c/4, 0x3f800000); -- nv_wo32(dev, ctx, 0x3864/4, 0xbf800000); -- nv_wo32(dev, ctx, 0x386c/4, 0xbf800000); -+ 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); - } - - static void -@@ -254,57 +257,57 @@ - { - int i; - -- nv_wo32(dev, ctx, 0x040c/4, 0x01000101); -- nv_wo32(dev, ctx, 0x0420/4, 0x00000111); -- nv_wo32(dev, ctx, 0x0424/4, 0x00000060); -- nv_wo32(dev, ctx, 0x0440/4, 0x00000080); -- nv_wo32(dev, ctx, 0x0444/4, 0xffff0000); -- nv_wo32(dev, ctx, 0x0448/4, 0x00000001); -- nv_wo32(dev, ctx, 0x045c/4, 0x44400000); -- nv_wo32(dev, ctx, 0x0480/4, 0xffff0000); -+ 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(dev, ctx, i/4, 0x0fff0000); -- nv_wo32(dev, ctx, 0x04e0/4, 0x00011100); -+ nv_wo32(ctx, i, 0x0fff0000); -+ nv_wo32(ctx, 0x04e0, 0x00011100); - for (i = 0x04fc; i < 0x053c; i += 4) -- nv_wo32(dev, ctx, i/4, 0x07ff0000); -- nv_wo32(dev, ctx, 0x0544/4, 0x4b7fffff); -- nv_wo32(dev, ctx, 0x057c/4, 0x00000080); -- nv_wo32(dev, ctx, 0x0580/4, 0x30201000); -- nv_wo32(dev, ctx, 0x0584/4, 0x70605040); -- nv_wo32(dev, ctx, 0x0588/4, 0xb8a89888); -- nv_wo32(dev, ctx, 0x058c/4, 0xf8e8d8c8); -- nv_wo32(dev, ctx, 0x05a0/4, 0xb0000000); -+ 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(dev, ctx, i/4, 0x00010588); -+ nv_wo32(ctx, i, 0x00010588); - for (i = 0x0630; i < 0x0670; i += 4) -- nv_wo32(dev, ctx, i/4, 0x00030303); -+ nv_wo32(ctx, i, 0x00030303); - for (i = 0x06b0; i < 0x06f0; i += 4) -- nv_wo32(dev, ctx, i/4, 0x0008aae4); -+ nv_wo32(ctx, i, 0x0008aae4); - for (i = 0x06f0; i < 0x0730; i += 4) -- nv_wo32(dev, ctx, i/4, 0x01012000); -+ nv_wo32(ctx, i, 0x01012000); - for (i = 0x0730; i < 0x0770; i += 4) -- nv_wo32(dev, ctx, i/4, 0x00080008); -- nv_wo32(dev, ctx, 0x0850/4, 0x00040000); -- nv_wo32(dev, ctx, 0x0854/4, 0x00010000); -+ nv_wo32(ctx, i, 0x00080008); -+ nv_wo32(ctx, 0x0850, 0x00040000); -+ nv_wo32(ctx, 0x0854, 0x00010000); - for (i = 0x0858; i < 0x0868; i += 4) -- nv_wo32(dev, ctx, i/4, 0x00040004); -+ nv_wo32(ctx, i, 0x00040004); - for (i = 0x15ac; i <= 0x271c ; i += 16) { -- nv_wo32(dev, ctx, i/4 + 0, 0x10700ff9); -- nv_wo32(dev, ctx, i/4 + 1, 0x0436086c); -- nv_wo32(dev, ctx, i/4 + 2, 0x000c001b); -+ nv_wo32(ctx, i + 0, 0x10700ff9); -+ nv_wo32(ctx, i + 1, 0x0436086c); -+ nv_wo32(ctx, i + 2, 0x000c001b); - } - for (i = 0x274c; i < 0x275c; i += 4) -- nv_wo32(dev, ctx, i/4, 0x0000ffff); -- nv_wo32(dev, ctx, 0x2ae0/4, 0x3f800000); -- nv_wo32(dev, ctx, 0x2e9c/4, 0x3f800000); -- nv_wo32(dev, ctx, 0x2eb0/4, 0x3f800000); -- nv_wo32(dev, ctx, 0x2edc/4, 0x40000000); -- nv_wo32(dev, ctx, 0x2ee0/4, 0x3f800000); -- nv_wo32(dev, ctx, 0x2ee4/4, 0x3f000000); -- nv_wo32(dev, ctx, 0x2eec/4, 0x40000000); -- nv_wo32(dev, ctx, 0x2ef0/4, 0x3f800000); -- nv_wo32(dev, ctx, 0x2ef8/4, 0xbf800000); -- nv_wo32(dev, ctx, 0x2f00/4, 0xbf800000); -+ 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); - } - - static void -@@ -312,57 +315,57 @@ - { - int i; - -- nv_wo32(dev, ctx, 0x040c/4, 0x00000101); -- nv_wo32(dev, ctx, 0x0420/4, 0x00000111); -- nv_wo32(dev, ctx, 0x0424/4, 0x00000060); -- nv_wo32(dev, ctx, 0x0440/4, 0x00000080); -- nv_wo32(dev, ctx, 0x0444/4, 0xffff0000); -- nv_wo32(dev, ctx, 0x0448/4, 0x00000001); -- nv_wo32(dev, ctx, 0x045c/4, 0x44400000); -- nv_wo32(dev, ctx, 0x0488/4, 0xffff0000); -+ 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(dev, ctx, i/4, 0x0fff0000); -- nv_wo32(dev, ctx, 0x04e8/4, 0x00011100); -+ nv_wo32(ctx, i, 0x0fff0000); -+ nv_wo32(ctx, 0x04e8, 0x00011100); - for (i = 0x0504; i < 0x0544; i += 4) -- nv_wo32(dev, ctx, i/4, 0x07ff0000); -- nv_wo32(dev, ctx, 0x054c/4, 0x4b7fffff); -- nv_wo32(dev, ctx, 0x0588/4, 0x00000080); -- nv_wo32(dev, ctx, 0x058c/4, 0x30201000); -- nv_wo32(dev, ctx, 0x0590/4, 0x70605040); -- nv_wo32(dev, ctx, 0x0594/4, 0xb8a89888); -- nv_wo32(dev, ctx, 0x0598/4, 0xf8e8d8c8); -- nv_wo32(dev, ctx, 0x05ac/4, 0xb0000000); -+ 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(dev, ctx, i/4, 0x00010588); -+ nv_wo32(ctx, i, 0x00010588); - for (i = 0x0644; i < 0x0684; i += 4) -- nv_wo32(dev, ctx, i/4, 0x00030303); -+ nv_wo32(ctx, i, 0x00030303); - for (i = 0x06c4; i < 0x0704; i += 4) -- nv_wo32(dev, ctx, i/4, 0x0008aae4); -+ nv_wo32(ctx, i, 0x0008aae4); - for (i = 0x0704; i < 0x0744; i += 4) -- nv_wo32(dev, ctx, i/4, 0x01012000); -+ nv_wo32(ctx, i, 0x01012000); - for (i = 0x0744; i < 0x0784; i += 4) -- nv_wo32(dev, ctx, i/4, 0x00080008); -- nv_wo32(dev, ctx, 0x0860/4, 0x00040000); -- nv_wo32(dev, ctx, 0x0864/4, 0x00010000); -+ nv_wo32(ctx, i, 0x00080008); -+ nv_wo32(ctx, 0x0860, 0x00040000); -+ nv_wo32(ctx, 0x0864, 0x00010000); - for (i = 0x0868; i < 0x0878; i += 4) -- nv_wo32(dev, ctx, i/4, 0x00040004); -+ nv_wo32(ctx, i, 0x00040004); - for (i = 0x1f1c; i <= 0x308c ; i += 16) { -- nv_wo32(dev, ctx, i/4 + 0, 0x10700ff9); -- nv_wo32(dev, ctx, i/4 + 1, 0x0436086c); -- nv_wo32(dev, ctx, i/4 + 2, 0x000c001b); -+ 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(dev, ctx, i/4, 0x0000ffff); -- nv_wo32(dev, ctx, 0x3450/4, 0x3f800000); -- nv_wo32(dev, ctx, 0x380c/4, 0x3f800000); -- nv_wo32(dev, ctx, 0x3820/4, 0x3f800000); -- nv_wo32(dev, ctx, 0x384c/4, 0x40000000); -- nv_wo32(dev, ctx, 0x3850/4, 0x3f800000); -- nv_wo32(dev, ctx, 0x3854/4, 0x3f000000); -- nv_wo32(dev, ctx, 0x385c/4, 0x40000000); -- nv_wo32(dev, ctx, 0x3860/4, 0x3f800000); -- nv_wo32(dev, ctx, 0x3868/4, 0xbf800000); -- nv_wo32(dev, ctx, 0x3870/4, 0xbf800000); -+ 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); - } - - int -@@ -372,7 +375,7 @@ - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_pgraph_engine *pgraph = &dev_priv->engine.graph; - void (*ctx_init)(struct drm_device *, struct nouveau_gpuobj *); -- unsigned int idoffs = 0x28/4; -+ unsigned int idoffs = 0x28; - int ret; - - switch (dev_priv->chipset) { -@@ -403,21 +406,19 @@ - BUG_ON(1); - } - -- ret = nouveau_gpuobj_new_ref(dev, chan, NULL, 0, pgraph->grctx_size, -- 16, NVOBJ_FLAG_ZERO_ALLOC, -- &chan->ramin_grctx); -+ ret = nouveau_gpuobj_new(dev, chan, pgraph->grctx_size, 16, -+ NVOBJ_FLAG_ZERO_ALLOC, &chan->ramin_grctx); - if (ret) - return ret; - - /* Initialise default context values */ -- ctx_init(dev, chan->ramin_grctx->gpuobj); -+ ctx_init(dev, chan->ramin_grctx); - - /* nv20: nv_wo32(dev, chan->ramin_grctx->gpuobj, 10, chan->id<<24); */ -- nv_wo32(dev, chan->ramin_grctx->gpuobj, idoffs, -- (chan->id << 24) | 0x1); /* CTX_USER */ -+ nv_wo32(chan->ramin_grctx, idoffs, -+ (chan->id << 24) | 0x1); /* CTX_USER */ - -- nv_wo32(dev, pgraph->ctx_table->gpuobj, chan->id, -- chan->ramin_grctx->instance >> 4); -+ nv_wo32(pgraph->ctx_table, chan->id * 4, chan->ramin_grctx->pinst >> 4); - return 0; - } - -@@ -427,11 +428,21 @@ - struct drm_device *dev = chan->dev; - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_pgraph_engine *pgraph = &dev_priv->engine.graph; -+ unsigned long flags; -+ -+ spin_lock_irqsave(&dev_priv->context_switch_lock, flags); -+ pgraph->fifo_access(dev, false); - -- if (chan->ramin_grctx) -- nouveau_gpuobj_ref_del(dev, &chan->ramin_grctx); -+ /* Unload the context if it's the currently active one */ -+ if (pgraph->channel(dev) == chan) -+ pgraph->unload_context(dev); - -- nv_wo32(dev, pgraph->ctx_table->gpuobj, chan->id, 0); -+ pgraph->fifo_access(dev, true); -+ spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags); -+ -+ /* Free the context resources */ -+ nv_wo32(pgraph->ctx_table, chan->id * 4, 0); -+ nouveau_gpuobj_ref(NULL, &chan->ramin_grctx); - } - - int -@@ -442,7 +453,7 @@ - - if (!chan->ramin_grctx) - return -EINVAL; -- inst = chan->ramin_grctx->instance >> 4; -+ inst = chan->ramin_grctx->pinst >> 4; - - nv_wr32(dev, NV20_PGRAPH_CHANNEL_CTX_POINTER, inst); - nv_wr32(dev, NV20_PGRAPH_CHANNEL_CTX_XFER, -@@ -465,7 +476,7 @@ - chan = pgraph->channel(dev); - if (!chan) - return 0; -- inst = chan->ramin_grctx->instance >> 4; -+ inst = chan->ramin_grctx->pinst >> 4; - - nv_wr32(dev, NV20_PGRAPH_CHANNEL_CTX_POINTER, inst); - nv_wr32(dev, NV20_PGRAPH_CHANNEL_CTX_XFER, -@@ -500,24 +511,27 @@ - } - - void --nv20_graph_set_region_tiling(struct drm_device *dev, int i, uint32_t addr, -- uint32_t size, uint32_t pitch) -+nv20_graph_set_tile_region(struct drm_device *dev, int i) - { -- uint32_t limit = max(1u, addr + size) - 1; -- -- if (pitch) -- addr |= 1; -+ struct drm_nouveau_private *dev_priv = dev->dev_private; -+ struct nouveau_tile_reg *tile = &dev_priv->tile.reg[i]; - -- nv_wr32(dev, NV20_PGRAPH_TLIMIT(i), limit); -- nv_wr32(dev, NV20_PGRAPH_TSIZE(i), pitch); -- nv_wr32(dev, NV20_PGRAPH_TILE(i), addr); -+ 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, limit); -+ 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, pitch); -+ 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, addr); -+ 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); -+ } - } - - int -@@ -552,18 +566,24 @@ - - if (!pgraph->ctx_table) { - /* Create Context Pointer Table */ -- ret = nouveau_gpuobj_new_ref(dev, NULL, NULL, 0, 32 * 4, 16, -- NVOBJ_FLAG_ZERO_ALLOC, -- &pgraph->ctx_table); -+ ret = nouveau_gpuobj_new(dev, NULL, 32 * 4, 16, -+ NVOBJ_FLAG_ZERO_ALLOC, -+ &pgraph->ctx_table); - if (ret) - return ret; - } - - nv_wr32(dev, NV20_PGRAPH_CHANNEL_CTX_TABLE, -- pgraph->ctx_table->instance >> 4); -+ pgraph->ctx_table->pinst >> 4); - - nv20_graph_rdi(dev); - -+ ret = nv20_graph_register(dev); -+ if (ret) { -+ nouveau_gpuobj_ref(NULL, &pgraph->ctx_table); -+ return ret; -+ } -+ - nv_wr32(dev, NV03_PGRAPH_INTR , 0xFFFFFFFF); - nv_wr32(dev, NV03_PGRAPH_INTR_EN, 0xFFFFFFFF); - -@@ -575,16 +595,17 @@ - nv_wr32(dev, 0x40009C , 0x00000040); - - if (dev_priv->chipset >= 0x25) { -- nv_wr32(dev, 0x400890, 0x00080000); -+ nv_wr32(dev, 0x400890, 0x00a8cfff); - nv_wr32(dev, 0x400610, 0x304B1FB6); -- nv_wr32(dev, 0x400B80, 0x18B82880); -+ 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, 0x00080000); /* 0x0008c7df */ -+ nv_wr32(dev, 0x400880, 0x0008c7df); - nv_wr32(dev, 0x400094, 0x00000005); -- nv_wr32(dev, 0x400B80, 0x45CAA208); /* 0x45eae20e */ -+ nv_wr32(dev, 0x400B80, 0x45eae20e); - nv_wr32(dev, 0x400B84, 0x24000000); - nv_wr32(dev, 0x400098, 0x00000040); - nv_wr32(dev, NV10_PGRAPH_RDI_INDEX, 0x00E00038); -@@ -595,14 +616,8 @@ - - /* Turn all the tiling regions off. */ - for (i = 0; i < NV10_PFB_TILE__SIZE; i++) -- nv20_graph_set_region_tiling(dev, i, 0, 0, 0); -+ nv20_graph_set_tile_region(dev, i); - -- for (i = 0; i < 8; i++) { -- nv_wr32(dev, 0x400980 + i * 4, nv_rd32(dev, 0x100300 + i * 4)); -- nv_wr32(dev, NV10_PGRAPH_RDI_INDEX, 0x00EA0090 + i * 4); -- nv_wr32(dev, NV10_PGRAPH_RDI_DATA, -- nv_rd32(dev, 0x100300 + i * 4)); -- } - 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)); -@@ -646,7 +661,7 @@ - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_pgraph_engine *pgraph = &dev_priv->engine.graph; - -- nouveau_gpuobj_ref_del(dev, &pgraph->ctx_table); -+ nouveau_gpuobj_ref(NULL, &pgraph->ctx_table); - } - - int -@@ -681,15 +696,21 @@ - - if (!pgraph->ctx_table) { - /* Create Context Pointer Table */ -- ret = nouveau_gpuobj_new_ref(dev, NULL, NULL, 0, 32 * 4, 16, -- NVOBJ_FLAG_ZERO_ALLOC, -- &pgraph->ctx_table); -+ ret = nouveau_gpuobj_new(dev, NULL, 32 * 4, 16, -+ NVOBJ_FLAG_ZERO_ALLOC, -+ &pgraph->ctx_table); - if (ret) - return ret; - } - -+ ret = nv30_graph_register(dev); -+ if (ret) { -+ nouveau_gpuobj_ref(NULL, &pgraph->ctx_table); -+ return ret; -+ } -+ - nv_wr32(dev, NV20_PGRAPH_CHANNEL_CTX_TABLE, -- pgraph->ctx_table->instance >> 4); -+ pgraph->ctx_table->pinst >> 4); - - nv_wr32(dev, NV03_PGRAPH_INTR , 0xFFFFFFFF); - nv_wr32(dev, NV03_PGRAPH_INTR_EN, 0xFFFFFFFF); -@@ -728,7 +749,7 @@ - - /* Turn all the tiling regions off. */ - for (i = 0; i < NV10_PFB_TILE__SIZE; i++) -- nv20_graph_set_region_tiling(dev, i, 0, 0, 0); -+ nv20_graph_set_tile_region(dev, i); - - nv_wr32(dev, NV10_PGRAPH_CTX_CONTROL, 0x10000100); - nv_wr32(dev, NV10_PGRAPH_STATE , 0xFFFFFFFF); -@@ -748,46 +769,84 @@ - return 0; - } - --struct nouveau_pgraph_object_class nv20_graph_grclass[] = { -- { 0x0030, false, NULL }, /* null */ -- { 0x0039, false, NULL }, /* m2mf */ -- { 0x004a, false, NULL }, /* gdirect */ -- { 0x009f, false, NULL }, /* imageblit (nv12) */ -- { 0x008a, false, NULL }, /* ifc */ -- { 0x0089, false, NULL }, /* sifm */ -- { 0x0062, false, NULL }, /* surf2d */ -- { 0x0043, false, NULL }, /* rop */ -- { 0x0012, false, NULL }, /* beta1 */ -- { 0x0072, false, NULL }, /* beta4 */ -- { 0x0019, false, NULL }, /* cliprect */ -- { 0x0044, false, NULL }, /* pattern */ -- { 0x009e, false, NULL }, /* swzsurf */ -- { 0x0096, false, NULL }, /* celcius */ -- { 0x0097, false, NULL }, /* kelvin (nv20) */ -- { 0x0597, false, NULL }, /* kelvin (nv25) */ -- {} --}; -- --struct nouveau_pgraph_object_class nv30_graph_grclass[] = { -- { 0x0030, false, NULL }, /* null */ -- { 0x0039, false, NULL }, /* m2mf */ -- { 0x004a, false, NULL }, /* gdirect */ -- { 0x009f, false, NULL }, /* imageblit (nv12) */ -- { 0x008a, false, NULL }, /* ifc */ -- { 0x038a, false, NULL }, /* ifc (nv30) */ -- { 0x0089, false, NULL }, /* sifm */ -- { 0x0389, false, NULL }, /* sifm (nv30) */ -- { 0x0062, false, NULL }, /* surf2d */ -- { 0x0362, false, NULL }, /* surf2d (nv30) */ -- { 0x0043, false, NULL }, /* rop */ -- { 0x0012, false, NULL }, /* beta1 */ -- { 0x0072, false, NULL }, /* beta4 */ -- { 0x0019, false, NULL }, /* cliprect */ -- { 0x0044, false, NULL }, /* pattern */ -- { 0x039e, false, NULL }, /* swzsurf */ -- { 0x0397, false, NULL }, /* rankine (nv30) */ -- { 0x0497, false, NULL }, /* rankine (nv35) */ -- { 0x0697, false, NULL }, /* rankine (nv34) */ -- {} --}; -+static int -+nv20_graph_register(struct drm_device *dev) -+{ -+ struct drm_nouveau_private *dev_priv = dev->dev_private; -+ -+ if (dev_priv->engine.graph.registered) -+ return 0; -+ -+ NVOBJ_CLASS(dev, 0x506e, SW); /* nvsw */ -+ 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 */ -+ 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); -+ -+ /* nvsw */ -+ NVOBJ_CLASS(dev, 0x506e, SW); -+ NVOBJ_MTHD (dev, 0x506e, 0x0500, nv04_graph_mthd_page_flip); - -+ dev_priv->engine.graph.registered = true; -+ return 0; -+} -+ -+static int -+nv30_graph_register(struct drm_device *dev) -+{ -+ struct drm_nouveau_private *dev_priv = dev->dev_private; -+ -+ if (dev_priv->engine.graph.registered) -+ return 0; -+ -+ NVOBJ_CLASS(dev, 0x506e, SW); /* nvsw */ -+ 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, 0x038a, GR); /* ifc (nv30) */ -+ NVOBJ_CLASS(dev, 0x0089, GR); /* sifm */ -+ NVOBJ_CLASS(dev, 0x0389, GR); /* sifm (nv30) */ -+ NVOBJ_CLASS(dev, 0x0062, GR); /* surf2d */ -+ NVOBJ_CLASS(dev, 0x0362, GR); /* surf2d (nv30) */ -+ 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, 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); -+ -+ /* nvsw */ -+ NVOBJ_CLASS(dev, 0x506e, SW); -+ NVOBJ_MTHD (dev, 0x506e, 0x0500, nv04_graph_mthd_page_flip); -+ -+ dev_priv->engine.graph.registered = true; -+ return 0; -+} -diff -Naur linux-2.6.36/drivers/gpu/drm/nouveau/nv30_fb.c linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nv30_fb.c ---- linux-2.6.36/drivers/gpu/drm/nouveau/nv30_fb.c 2010-10-20 22:30:22.000000000 +0200 -+++ linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nv30_fb.c 2010-11-05 00:40:00.000000000 +0100 -@@ -29,6 +29,27 @@ - #include "nouveau_drv.h" - #include "nouveau_drm.h" - -+void -+nv30_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]; -+ -+ 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) -+{ -+ 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; -+} -+ - static int - calc_bias(struct drm_device *dev, int k, int i, int j) - { -@@ -65,7 +86,7 @@ - - /* Turn all the tiling regions off. */ - for (i = 0; i < pfb->num_tiles; i++) -- pfb->set_region_tiling(dev, i, 0, 0, 0); -+ pfb->set_tile_region(dev, i); - - /* Init the memory timing regs at 0x10037c/0x1003ac */ - if (dev_priv->chipset == 0x30 || -diff -Naur linux-2.6.36/drivers/gpu/drm/nouveau/nv40_fb.c linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nv40_fb.c ---- linux-2.6.36/drivers/gpu/drm/nouveau/nv40_fb.c 2010-10-20 22:30:22.000000000 +0200 -+++ linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nv40_fb.c 2010-11-05 00:40:00.000000000 +0100 -@@ -4,26 +4,22 @@ - #include "nouveau_drm.h" - - void --nv40_fb_set_region_tiling(struct drm_device *dev, int i, uint32_t addr, -- uint32_t size, uint32_t pitch) -+nv40_fb_set_tile_region(struct drm_device *dev, int i) - { - struct drm_nouveau_private *dev_priv = dev->dev_private; -- uint32_t limit = max(1u, addr + size) - 1; -- -- if (pitch) -- addr |= 1; -+ struct nouveau_tile_reg *tile = &dev_priv->tile.reg[i]; - - switch (dev_priv->chipset) { - case 0x40: -- nv_wr32(dev, NV10_PFB_TLIMIT(i), limit); -- nv_wr32(dev, NV10_PFB_TSIZE(i), pitch); -- nv_wr32(dev, NV10_PFB_TILE(i), addr); -+ 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; - - default: -- nv_wr32(dev, NV40_PFB_TLIMIT(i), limit); -- nv_wr32(dev, NV40_PFB_TSIZE(i), pitch); -- nv_wr32(dev, NV40_PFB_TILE(i), addr); -+ 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; - } - } -@@ -64,7 +60,7 @@ - - /* Turn all the tiling regions off. */ - for (i = 0; i < pfb->num_tiles; i++) -- pfb->set_region_tiling(dev, i, 0, 0, 0); -+ pfb->set_tile_region(dev, i); - - return 0; - } -diff -Naur linux-2.6.36/drivers/gpu/drm/nouveau/nv40_fifo.c linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nv40_fifo.c ---- linux-2.6.36/drivers/gpu/drm/nouveau/nv40_fifo.c 2010-10-20 22:30:22.000000000 +0200 -+++ linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nv40_fifo.c 2010-11-05 00:40:00.000000000 +0100 -@@ -27,8 +27,9 @@ - #include "drmP.h" - #include "nouveau_drv.h" - #include "nouveau_drm.h" -+#include "nouveau_ramht.h" - --#define NV40_RAMFC(c) (dev_priv->ramfc_offset + ((c) * NV40_RAMFC__SIZE)) -+#define NV40_RAMFC(c) (dev_priv->ramfc->pinst + ((c) * NV40_RAMFC__SIZE)) - #define NV40_RAMFC__SIZE 128 - - int -@@ -42,7 +43,7 @@ - - ret = nouveau_gpuobj_new_fake(dev, NV40_RAMFC(chan->id), ~0, - NV40_RAMFC__SIZE, NVOBJ_FLAG_ZERO_ALLOC | -- NVOBJ_FLAG_ZERO_FREE, NULL, &chan->ramfc); -+ NVOBJ_FLAG_ZERO_FREE, &chan->ramfc); - if (ret) - return ret; - -@@ -50,7 +51,7 @@ - - nv_wi32(dev, fc + 0, chan->pushbuf_base); - nv_wi32(dev, fc + 4, chan->pushbuf_base); -- nv_wi32(dev, fc + 12, chan->pushbuf->instance >> 4); -+ nv_wi32(dev, fc + 12, chan->pushbuf->pinst >> 4); - nv_wi32(dev, fc + 24, NV_PFIFO_CACHE1_DMA_FETCH_TRIG_128_BYTES | - NV_PFIFO_CACHE1_DMA_FETCH_SIZE_128_BYTES | - NV_PFIFO_CACHE1_DMA_FETCH_MAX_REQS_8 | -@@ -58,7 +59,7 @@ - NV_PFIFO_CACHE1_BIG_ENDIAN | - #endif - 0x30000000 /* no idea.. */); -- nv_wi32(dev, fc + 56, chan->ramin_grctx->instance >> 4); -+ nv_wi32(dev, fc + 56, chan->ramin_grctx->pinst >> 4); - nv_wi32(dev, fc + 60, 0x0001FFFF); - - /* enable the fifo dma operation */ -@@ -69,18 +70,6 @@ - return 0; - } - --void --nv40_fifo_destroy_context(struct nouveau_channel *chan) --{ -- struct drm_device *dev = chan->dev; -- -- nv_wr32(dev, NV04_PFIFO_MODE, -- nv_rd32(dev, NV04_PFIFO_MODE) & ~(1 << chan->id)); -- -- if (chan->ramfc) -- nouveau_gpuobj_ref_del(dev, &chan->ramfc); --} -- - static void - nv40_fifo_do_load_context(struct drm_device *dev, int chid) - { -@@ -241,9 +230,9 @@ - struct drm_nouveau_private *dev_priv = dev->dev_private; - - nv_wr32(dev, NV03_PFIFO_RAMHT, (0x03 << 24) /* search 128 */ | -- ((dev_priv->ramht_bits - 9) << 16) | -- (dev_priv->ramht_offset >> 8)); -- nv_wr32(dev, NV03_PFIFO_RAMRO, dev_priv->ramro_offset>>8); -+ ((dev_priv->ramht->bits - 9) << 16) | -+ (dev_priv->ramht->gpuobj->pinst >> 8)); -+ nv_wr32(dev, NV03_PFIFO_RAMRO, dev_priv->ramro->pinst >> 8); - - switch (dev_priv->chipset) { - case 0x47: -@@ -271,7 +260,7 @@ - nv_wr32(dev, 0x2230, 0); - nv_wr32(dev, NV40_PFIFO_RAMFC, - ((dev_priv->vram_size - 512 * 1024 + -- dev_priv->ramfc_offset) >> 16) | (3 << 16)); -+ dev_priv->ramfc->pinst) >> 16) | (3 << 16)); - break; - } - } -@@ -301,7 +290,7 @@ - pfifo->reassign(dev, true); - - for (i = 0; i < dev_priv->engine.fifo.channels; i++) { -- if (dev_priv->fifos[i]) { -+ if (dev_priv->channels.ptr[i]) { - uint32_t mode = nv_rd32(dev, NV04_PFIFO_MODE); - nv_wr32(dev, NV04_PFIFO_MODE, mode | (1 << i)); - } -diff -Naur linux-2.6.36/drivers/gpu/drm/nouveau/nv40_graph.c linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nv40_graph.c ---- linux-2.6.36/drivers/gpu/drm/nouveau/nv40_graph.c 2010-10-20 22:30:22.000000000 +0200 -+++ linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nv40_graph.c 2010-11-05 00:40:00.000000000 +0100 -@@ -29,6 +29,8 @@ - #include "nouveau_drv.h" - #include "nouveau_grctx.h" - -+static int nv40_graph_register(struct drm_device *); -+ - struct nouveau_channel * - nv40_graph_channel(struct drm_device *dev) - { -@@ -42,10 +44,10 @@ - inst = (inst & NV40_PGRAPH_CTXCTL_CUR_INSTANCE) << 4; - - for (i = 0; i < dev_priv->engine.fifo.channels; i++) { -- struct nouveau_channel *chan = dev_priv->fifos[i]; -+ struct nouveau_channel *chan = dev_priv->channels.ptr[i]; - - if (chan && chan->ramin_grctx && -- chan->ramin_grctx->instance == inst) -+ chan->ramin_grctx->pinst == inst) - return chan; - } - -@@ -61,27 +63,41 @@ - struct nouveau_grctx ctx = {}; - int ret; - -- ret = nouveau_gpuobj_new_ref(dev, chan, NULL, 0, pgraph->grctx_size, -- 16, NVOBJ_FLAG_ZERO_ALLOC, -- &chan->ramin_grctx); -+ ret = nouveau_gpuobj_new(dev, chan, pgraph->grctx_size, 16, -+ NVOBJ_FLAG_ZERO_ALLOC, &chan->ramin_grctx); - if (ret) - return ret; - - /* Initialise default context values */ - ctx.dev = chan->dev; - ctx.mode = NOUVEAU_GRCTX_VALS; -- ctx.data = chan->ramin_grctx->gpuobj; -+ ctx.data = chan->ramin_grctx; - nv40_grctx_init(&ctx); - -- nv_wo32(dev, chan->ramin_grctx->gpuobj, 0, -- chan->ramin_grctx->gpuobj->im_pramin->start); -+ nv_wo32(chan->ramin_grctx, 0, chan->ramin_grctx->pinst); - return 0; - } - - void - nv40_graph_destroy_context(struct nouveau_channel *chan) - { -- nouveau_gpuobj_ref_del(chan->dev, &chan->ramin_grctx); -+ struct drm_device *dev = chan->dev; -+ struct drm_nouveau_private *dev_priv = dev->dev_private; -+ struct nouveau_pgraph_engine *pgraph = &dev_priv->engine.graph; -+ unsigned long flags; -+ -+ spin_lock_irqsave(&dev_priv->context_switch_lock, flags); -+ pgraph->fifo_access(dev, false); -+ -+ /* Unload the context if it's the currently active one */ -+ if (pgraph->channel(dev) == chan) -+ pgraph->unload_context(dev); -+ -+ pgraph->fifo_access(dev, true); -+ spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags); -+ -+ /* Free the context resources */ -+ nouveau_gpuobj_ref(NULL, &chan->ramin_grctx); - } - - static int -@@ -135,7 +151,7 @@ - - if (!chan->ramin_grctx) - return -EINVAL; -- inst = chan->ramin_grctx->instance >> 4; -+ inst = chan->ramin_grctx->pinst >> 4; - - ret = nv40_graph_transfer_context(dev, inst, 0); - if (ret) -@@ -176,43 +192,39 @@ - } - - void --nv40_graph_set_region_tiling(struct drm_device *dev, int i, uint32_t addr, -- uint32_t size, uint32_t pitch) -+nv40_graph_set_tile_region(struct drm_device *dev, int i) - { - struct drm_nouveau_private *dev_priv = dev->dev_private; -- uint32_t limit = max(1u, addr + size) - 1; -- -- if (pitch) -- addr |= 1; -+ struct nouveau_tile_reg *tile = &dev_priv->tile.reg[i]; - - switch (dev_priv->chipset) { - case 0x44: - case 0x4a: - case 0x4e: -- nv_wr32(dev, NV20_PGRAPH_TSIZE(i), pitch); -- nv_wr32(dev, NV20_PGRAPH_TLIMIT(i), limit); -- nv_wr32(dev, NV20_PGRAPH_TILE(i), addr); -+ 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); - break; - - case 0x46: - case 0x47: - case 0x49: - case 0x4b: -- nv_wr32(dev, NV47_PGRAPH_TSIZE(i), pitch); -- nv_wr32(dev, NV47_PGRAPH_TLIMIT(i), limit); -- nv_wr32(dev, NV47_PGRAPH_TILE(i), addr); -- nv_wr32(dev, NV40_PGRAPH_TSIZE1(i), pitch); -- nv_wr32(dev, NV40_PGRAPH_TLIMIT1(i), limit); -- nv_wr32(dev, NV40_PGRAPH_TILE1(i), addr); -+ 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); - break; - - default: -- nv_wr32(dev, NV20_PGRAPH_TSIZE(i), pitch); -- nv_wr32(dev, NV20_PGRAPH_TLIMIT(i), limit); -- nv_wr32(dev, NV20_PGRAPH_TILE(i), addr); -- nv_wr32(dev, NV40_PGRAPH_TSIZE1(i), pitch); -- nv_wr32(dev, NV40_PGRAPH_TLIMIT1(i), limit); -- nv_wr32(dev, NV40_PGRAPH_TILE1(i), addr); -+ 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); - break; - } - } -@@ -234,7 +246,7 @@ - struct nouveau_fb_engine *pfb = &dev_priv->engine.fb; - struct nouveau_grctx ctx = {}; - uint32_t vramsz, *cp; -- int i, j; -+ int ret, i, j; - - nv_wr32(dev, NV03_PMC_ENABLE, nv_rd32(dev, NV03_PMC_ENABLE) & - ~NV_PMC_ENABLE_PGRAPH); -@@ -258,6 +270,10 @@ - - kfree(cp); - -+ ret = nv40_graph_register(dev); -+ if (ret) -+ return ret; -+ - /* No context present currently */ - nv_wr32(dev, NV40_PGRAPH_CTXCTL_CUR, 0x00000000); - -@@ -349,7 +365,7 @@ - - /* Turn all the tiling regions off. */ - for (i = 0; i < pfb->num_tiles; i++) -- nv40_graph_set_region_tiling(dev, i, 0, 0, 0); -+ nv40_graph_set_tile_region(dev, i); - - /* begin RAM config */ - vramsz = pci_resource_len(dev->pdev, 0) - 1; -@@ -394,24 +410,42 @@ - { - } - --struct nouveau_pgraph_object_class nv40_graph_grclass[] = { -- { 0x0030, false, NULL }, /* null */ -- { 0x0039, false, NULL }, /* m2mf */ -- { 0x004a, false, NULL }, /* gdirect */ -- { 0x009f, false, NULL }, /* imageblit (nv12) */ -- { 0x008a, false, NULL }, /* ifc */ -- { 0x0089, false, NULL }, /* sifm */ -- { 0x3089, false, NULL }, /* sifm (nv40) */ -- { 0x0062, false, NULL }, /* surf2d */ -- { 0x3062, false, NULL }, /* surf2d (nv40) */ -- { 0x0043, false, NULL }, /* rop */ -- { 0x0012, false, NULL }, /* beta1 */ -- { 0x0072, false, NULL }, /* beta4 */ -- { 0x0019, false, NULL }, /* cliprect */ -- { 0x0044, false, NULL }, /* pattern */ -- { 0x309e, false, NULL }, /* swzsurf */ -- { 0x4097, false, NULL }, /* curie (nv40) */ -- { 0x4497, false, NULL }, /* curie (nv44) */ -- {} --}; -+static int -+nv40_graph_register(struct drm_device *dev) -+{ -+ struct drm_nouveau_private *dev_priv = dev->dev_private; -+ -+ if (dev_priv->engine.graph.registered) -+ return 0; -+ -+ NVOBJ_CLASS(dev, 0x506e, SW); /* nvsw */ -+ 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 (dev_priv->chipset >= 0x60 || -+ 0x00005450 & (1 << (dev_priv->chipset & 0x0f))) -+ NVOBJ_CLASS(dev, 0x4497, GR); -+ else -+ NVOBJ_CLASS(dev, 0x4097, GR); -+ -+ /* nvsw */ -+ NVOBJ_CLASS(dev, 0x506e, SW); -+ NVOBJ_MTHD (dev, 0x506e, 0x0500, nv04_graph_mthd_page_flip); - -+ dev_priv->engine.graph.registered = true; -+ return 0; -+} -diff -Naur linux-2.6.36/drivers/gpu/drm/nouveau/nv40_grctx.c linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nv40_grctx.c ---- linux-2.6.36/drivers/gpu/drm/nouveau/nv40_grctx.c 2010-10-20 22:30:22.000000000 +0200 -+++ linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nv40_grctx.c 2010-11-05 00:40:00.000000000 +0100 -@@ -596,13 +596,13 @@ - - offset += 0x0280/4; - for (i = 0; i < 16; i++, offset += 2) -- nv_wo32(dev, obj, offset, 0x3f800000); -+ nv_wo32(obj, offset * 4, 0x3f800000); - - for (vs = 0; vs < vs_nr; vs++, offset += vs_len) { - for (i = 0; i < vs_nr_b0 * 6; i += 6) -- nv_wo32(dev, obj, offset + b0_offset + i, 0x00000001); -+ nv_wo32(obj, (offset + b0_offset + i) * 4, 0x00000001); - for (i = 0; i < vs_nr_b1 * 4; i += 4) -- nv_wo32(dev, obj, offset + b1_offset + i, 0x3f800000); -+ nv_wo32(obj, (offset + b1_offset + i) * 4, 0x3f800000); - } - } - -diff -Naur linux-2.6.36/drivers/gpu/drm/nouveau/nv50_calc.c linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nv50_calc.c ---- linux-2.6.36/drivers/gpu/drm/nouveau/nv50_calc.c 2010-10-20 22:30:22.000000000 +0200 -+++ linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nv50_calc.c 2010-11-05 00:40:00.000000000 +0100 -@@ -51,24 +51,28 @@ - int *N, int *fN, int *M, int *P) - { - fixed20_12 fb_div, a, b; -+ u32 refclk = pll->refclk / 10; -+ u32 max_vco_freq = pll->vco1.maxfreq / 10; -+ u32 max_vco_inputfreq = pll->vco1.max_inputfreq / 10; -+ clk /= 10; - -- *P = pll->vco1.maxfreq / clk; -+ *P = max_vco_freq / clk; - if (*P > pll->max_p) - *P = pll->max_p; - if (*P < pll->min_p) - *P = pll->min_p; - -- /* *M = ceil(refclk / pll->vco.max_inputfreq); */ -- a.full = dfixed_const(pll->refclk); -- b.full = dfixed_const(pll->vco1.max_inputfreq); -+ /* *M = floor((refclk + max_vco_inputfreq) / max_vco_inputfreq); */ -+ a.full = dfixed_const(refclk + max_vco_inputfreq); -+ b.full = dfixed_const(max_vco_inputfreq); - a.full = dfixed_div(a, b); -- a.full = dfixed_ceil(a); -+ a.full = dfixed_floor(a); - *M = dfixed_trunc(a); - - /* fb_div = (vco * *M) / refclk; */ - fb_div.full = dfixed_const(clk * *P); - fb_div.full = dfixed_mul(fb_div, a); -- a.full = dfixed_const(pll->refclk); -+ a.full = dfixed_const(refclk); - fb_div.full = dfixed_div(fb_div, a); - - /* *N = floor(fb_div); */ -diff -Naur linux-2.6.36/drivers/gpu/drm/nouveau/nv50_crtc.c linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nv50_crtc.c ---- linux-2.6.36/drivers/gpu/drm/nouveau/nv50_crtc.c 2010-10-20 22:30:22.000000000 +0200 -+++ linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nv50_crtc.c 2010-11-05 00:40:00.000000000 +0100 -@@ -104,8 +104,7 @@ - OUT_RING(evo, nv_crtc->lut.depth == 8 ? - NV50_EVO_CRTC_CLUT_MODE_OFF : - NV50_EVO_CRTC_CLUT_MODE_ON); -- OUT_RING(evo, (nv_crtc->lut.nvbo->bo.mem.mm_node->start << -- PAGE_SHIFT) >> 8); -+ OUT_RING(evo, (nv_crtc->lut.nvbo->bo.mem.start << PAGE_SHIFT) >> 8); - if (dev_priv->chipset != 0x50) { - BEGIN_RING(evo, 0, NV84_EVO_CRTC(index, CLUT_DMA), 1); - OUT_RING(evo, NvEvoVRAM); -@@ -266,15 +265,10 @@ - { - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct pll_lims pll; -- uint32_t reg, reg1, reg2; -+ uint32_t reg1, reg2; - int ret, N1, M1, N2, M2, P; - -- if (dev_priv->chipset < NV_C0) -- reg = NV50_PDISPLAY_CRTC_CLK_CTRL1(head); -- else -- reg = 0x614140 + (head * 0x800); -- -- ret = get_pll_limits(dev, reg, &pll); -+ ret = get_pll_limits(dev, PLL_VPLL0 + head, &pll); - if (ret) - return ret; - -@@ -286,11 +280,11 @@ - NV_DEBUG(dev, "pclk %d out %d NM1 %d %d NM2 %d %d P %d\n", - pclk, ret, N1, M1, N2, M2, P); - -- reg1 = nv_rd32(dev, reg + 4) & 0xff00ff00; -- reg2 = nv_rd32(dev, reg + 8) & 0x8000ff00; -- nv_wr32(dev, reg, 0x10000611); -- nv_wr32(dev, reg + 4, reg1 | (M1 << 16) | N1); -- nv_wr32(dev, reg + 8, reg2 | (P << 28) | (M2 << 16) | N2); -+ reg1 = nv_rd32(dev, pll.reg + 4) & 0xff00ff00; -+ reg2 = nv_rd32(dev, pll.reg + 8) & 0x8000ff00; -+ nv_wr32(dev, pll.reg + 0, 0x10000611); -+ nv_wr32(dev, pll.reg + 4, reg1 | (M1 << 16) | N1); -+ nv_wr32(dev, pll.reg + 8, reg2 | (P << 28) | (M2 << 16) | N2); - } else - if (dev_priv->chipset < NV_C0) { - ret = nv50_calc_pll2(dev, &pll, pclk, &N1, &N2, &M1, &P); -@@ -300,10 +294,10 @@ - NV_DEBUG(dev, "pclk %d out %d N %d fN 0x%04x M %d P %d\n", - pclk, ret, N1, N2, M1, P); - -- reg1 = nv_rd32(dev, reg + 4) & 0xffc00000; -- nv_wr32(dev, reg, 0x50000610); -- nv_wr32(dev, reg + 4, reg1 | (P << 16) | (M1 << 8) | N1); -- nv_wr32(dev, reg + 8, N2); -+ reg1 = nv_rd32(dev, pll.reg + 4) & 0xffc00000; -+ nv_wr32(dev, pll.reg + 0, 0x50000610); -+ nv_wr32(dev, pll.reg + 4, reg1 | (P << 16) | (M1 << 8) | N1); -+ nv_wr32(dev, pll.reg + 8, N2); - } else { - ret = nv50_calc_pll2(dev, &pll, pclk, &N1, &N2, &M1, &P); - if (ret <= 0) -@@ -312,9 +306,9 @@ - NV_DEBUG(dev, "pclk %d out %d N %d fN 0x%04x M %d P %d\n", - pclk, ret, N1, N2, M1, P); - -- nv_mask(dev, reg + 0x0c, 0x00000000, 0x00000100); -- nv_wr32(dev, reg + 0x04, (P << 16) | (N1 << 8) | M1); -- nv_wr32(dev, reg + 0x10, N2 << 16); -+ nv_mask(dev, pll.reg + 0x0c, 0x00000000, 0x00000100); -+ nv_wr32(dev, pll.reg + 0x04, (P << 16) | (N1 << 8) | M1); -+ nv_wr32(dev, pll.reg + 0x10, N2 << 16); - } - - return 0; -@@ -338,7 +332,9 @@ - - nv50_cursor_fini(nv_crtc); - -+ nouveau_bo_unmap(nv_crtc->lut.nvbo); - nouveau_bo_ref(NULL, &nv_crtc->lut.nvbo); -+ nouveau_bo_unmap(nv_crtc->cursor.nvbo); - nouveau_bo_ref(NULL, &nv_crtc->cursor.nvbo); - kfree(nv_crtc->mode); - kfree(nv_crtc); -@@ -441,6 +437,7 @@ - .cursor_move = nv50_crtc_cursor_move, - .gamma_set = nv50_crtc_gamma_set, - .set_config = drm_crtc_helper_set_config, -+ .page_flip = nouveau_crtc_page_flip, - .destroy = nv50_crtc_destroy, - }; - -@@ -457,6 +454,7 @@ - - NV_DEBUG_KMS(dev, "index %d\n", nv_crtc->index); - -+ drm_vblank_pre_modeset(dev, nv_crtc->index); - nv50_crtc_blank(nv_crtc, true); - } - -@@ -472,6 +470,7 @@ - NV_DEBUG_KMS(dev, "index %d\n", nv_crtc->index); - - nv50_crtc_blank(nv_crtc, false); -+ drm_vblank_post_modeset(dev, nv_crtc->index); - - ret = RING_SPACE(evo, 2); - if (ret) { -@@ -536,7 +535,7 @@ - } - - nv_crtc->fb.offset = fb->nvbo->bo.offset - dev_priv->vm_vram_base; -- nv_crtc->fb.tile_flags = fb->nvbo->tile_flags; -+ 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) { - ret = RING_SPACE(evo, 2); -@@ -568,7 +567,7 @@ - fb->nvbo->tile_mode); - } - if (dev_priv->chipset == 0x50) -- OUT_RING(evo, (fb->nvbo->tile_flags << 8) | format); -+ OUT_RING(evo, (nv_crtc->fb.tile_flags << 8) | format); - else - OUT_RING(evo, format); - -diff -Naur linux-2.6.36/drivers/gpu/drm/nouveau/nv50_cursor.c linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nv50_cursor.c ---- linux-2.6.36/drivers/gpu/drm/nouveau/nv50_cursor.c 2010-10-20 22:30:22.000000000 +0200 -+++ linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nv50_cursor.c 2010-11-05 00:40:00.000000000 +0100 -@@ -147,7 +147,7 @@ - NV_DEBUG_KMS(dev, "\n"); - - nv_wr32(dev, NV50_PDISPLAY_CURSOR_CURSOR_CTRL2(idx), 0); -- if (!nv_wait(NV50_PDISPLAY_CURSOR_CURSOR_CTRL2(idx), -+ if (!nv_wait(dev, NV50_PDISPLAY_CURSOR_CURSOR_CTRL2(idx), - NV50_PDISPLAY_CURSOR_CURSOR_CTRL2_STATUS, 0)) { - NV_ERROR(dev, "timeout: CURSOR_CTRL2_STATUS == 0\n"); - NV_ERROR(dev, "CURSOR_CTRL2 = 0x%08x\n", -diff -Naur linux-2.6.36/drivers/gpu/drm/nouveau/nv50_dac.c linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nv50_dac.c ---- linux-2.6.36/drivers/gpu/drm/nouveau/nv50_dac.c 2010-10-20 22:30:22.000000000 +0200 -+++ linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nv50_dac.c 2010-11-05 00:40:00.000000000 +0100 -@@ -79,7 +79,7 @@ - - nv_wr32(dev, NV50_PDISPLAY_DAC_DPMS_CTRL(or), - 0x00150000 | NV50_PDISPLAY_DAC_DPMS_CTRL_PENDING); -- if (!nv_wait(NV50_PDISPLAY_DAC_DPMS_CTRL(or), -+ if (!nv_wait(dev, 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, -@@ -130,7 +130,7 @@ - NV_DEBUG_KMS(dev, "or %d mode %d\n", or, mode); - - /* wait for it to be done */ -- if (!nv_wait(NV50_PDISPLAY_DAC_DPMS_CTRL(or), -+ if (!nv_wait(dev, 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, -diff -Naur linux-2.6.36/drivers/gpu/drm/nouveau/nv50_display.c linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nv50_display.c ---- linux-2.6.36/drivers/gpu/drm/nouveau/nv50_display.c 2010-10-20 22:30:22.000000000 +0200 -+++ linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nv50_display.c 2010-11-05 00:40:00.000000000 +0100 -@@ -30,154 +30,20 @@ - #include "nouveau_connector.h" - #include "nouveau_fb.h" - #include "nouveau_fbcon.h" -+#include "nouveau_ramht.h" - #include "drm_crtc_helper.h" - --static void --nv50_evo_channel_del(struct nouveau_channel **pchan) --{ -- struct nouveau_channel *chan = *pchan; -- -- if (!chan) -- return; -- *pchan = NULL; -- -- nouveau_gpuobj_channel_takedown(chan); -- nouveau_bo_ref(NULL, &chan->pushbuf_bo); -- -- if (chan->user) -- iounmap(chan->user); -- -- kfree(chan); --} -- --static int --nv50_evo_dmaobj_new(struct nouveau_channel *evo, uint32_t class, uint32_t name, -- uint32_t tile_flags, uint32_t magic_flags, -- uint32_t offset, uint32_t limit) --{ -- struct drm_nouveau_private *dev_priv = evo->dev->dev_private; -- struct drm_device *dev = evo->dev; -- struct nouveau_gpuobj *obj = NULL; -- int ret; -- -- ret = nouveau_gpuobj_new(dev, evo, 6*4, 32, 0, &obj); -- if (ret) -- return ret; -- obj->engine = NVOBJ_ENGINE_DISPLAY; -- -- ret = nouveau_gpuobj_ref_add(dev, evo, name, obj, NULL); -- if (ret) { -- nouveau_gpuobj_del(dev, &obj); -- return ret; -- } -- -- nv_wo32(dev, obj, 0, (tile_flags << 22) | (magic_flags << 16) | class); -- nv_wo32(dev, obj, 1, limit); -- nv_wo32(dev, obj, 2, offset); -- nv_wo32(dev, obj, 3, 0x00000000); -- nv_wo32(dev, obj, 4, 0x00000000); -- if (dev_priv->card_type < NV_C0) -- nv_wo32(dev, obj, 5, 0x00010000); -- else -- nv_wo32(dev, obj, 5, 0x00020000); -- dev_priv->engine.instmem.flush(dev); -- -- return 0; --} -- --static int --nv50_evo_channel_new(struct drm_device *dev, struct nouveau_channel **pchan) -+static inline int -+nv50_sor_nr(struct drm_device *dev) - { - struct drm_nouveau_private *dev_priv = dev->dev_private; -- struct nouveau_channel *chan; -- int ret; -- -- chan = kzalloc(sizeof(struct nouveau_channel), GFP_KERNEL); -- if (!chan) -- return -ENOMEM; -- *pchan = chan; -- -- chan->id = -1; -- chan->dev = dev; -- chan->user_get = 4; -- chan->user_put = 0; -- -- INIT_LIST_HEAD(&chan->ramht_refs); -- -- ret = nouveau_gpuobj_new_ref(dev, NULL, NULL, 0, 32768, 0x1000, -- NVOBJ_FLAG_ZERO_ALLOC, &chan->ramin); -- if (ret) { -- NV_ERROR(dev, "Error allocating EVO channel memory: %d\n", ret); -- nv50_evo_channel_del(pchan); -- return ret; -- } -- -- ret = drm_mm_init(&chan->ramin_heap, -- chan->ramin->gpuobj->im_pramin->start, 32768); -- if (ret) { -- NV_ERROR(dev, "Error initialising EVO PRAMIN heap: %d\n", ret); -- nv50_evo_channel_del(pchan); -- return ret; -- } -- -- ret = nouveau_gpuobj_new_ref(dev, chan, chan, 0, 4096, 16, -- 0, &chan->ramht); -- if (ret) { -- NV_ERROR(dev, "Unable to allocate EVO RAMHT: %d\n", ret); -- nv50_evo_channel_del(pchan); -- return ret; -- } -- -- if (dev_priv->chipset != 0x50) { -- ret = nv50_evo_dmaobj_new(chan, 0x3d, NvEvoFB16, 0x70, 0x19, -- 0, 0xffffffff); -- if (ret) { -- nv50_evo_channel_del(pchan); -- return ret; -- } -- -- -- ret = nv50_evo_dmaobj_new(chan, 0x3d, NvEvoFB32, 0x7a, 0x19, -- 0, 0xffffffff); -- if (ret) { -- nv50_evo_channel_del(pchan); -- return ret; -- } -- } -- -- ret = nv50_evo_dmaobj_new(chan, 0x3d, NvEvoVRAM, 0, 0x19, -- 0, dev_priv->vram_size); -- if (ret) { -- nv50_evo_channel_del(pchan); -- return ret; -- } -- -- ret = nouveau_bo_new(dev, NULL, 4096, 0, TTM_PL_FLAG_VRAM, 0, 0, -- false, true, &chan->pushbuf_bo); -- if (ret == 0) -- ret = nouveau_bo_pin(chan->pushbuf_bo, TTM_PL_FLAG_VRAM); -- if (ret) { -- NV_ERROR(dev, "Error creating EVO DMA push buffer: %d\n", ret); -- nv50_evo_channel_del(pchan); -- return ret; -- } - -- ret = nouveau_bo_map(chan->pushbuf_bo); -- if (ret) { -- NV_ERROR(dev, "Error mapping EVO DMA push buffer: %d\n", ret); -- nv50_evo_channel_del(pchan); -- return ret; -- } -+ if (dev_priv->chipset < 0x90 || -+ dev_priv->chipset == 0x92 || -+ dev_priv->chipset == 0xa0) -+ return 2; - -- chan->user = ioremap(pci_resource_start(dev->pdev, 0) + -- NV50_PDISPLAY_USER(0), PAGE_SIZE); -- if (!chan->user) { -- NV_ERROR(dev, "Error mapping EVO control regs.\n"); -- nv50_evo_channel_del(pchan); -- return -ENOMEM; -- } -- -- return 0; -+ return 4; - } - - int -@@ -195,17 +61,16 @@ - nv50_display_init(struct drm_device *dev) - { - struct drm_nouveau_private *dev_priv = dev->dev_private; -- struct nouveau_timer_engine *ptimer = &dev_priv->engine.timer; - struct nouveau_gpio_engine *pgpio = &dev_priv->engine.gpio; -- struct nouveau_channel *evo = dev_priv->evo; - struct drm_connector *connector; -- uint32_t val, ram_amount; -- uint64_t start; -+ struct nouveau_channel *evo; - int ret, i; -+ u32 val; - - NV_DEBUG_KMS(dev, "\n"); - - nv_wr32(dev, 0x00610184, nv_rd32(dev, 0x00614004)); -+ - /* - * I think the 0x006101XX range is some kind of main control area - * that enables things. -@@ -221,17 +86,20 @@ - val = nv_rd32(dev, 0x0061610c + (i * 0x800)); - nv_wr32(dev, 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); - } -+ - /* SOR */ -- for (i = 0; i < 4; i++) { -+ for (i = 0; i < nv50_sor_nr(dev); i++) { - val = nv_rd32(dev, 0x0061c000 + (i * 0x800)); - nv_wr32(dev, 0x006101e0 + (i * 0x04), val); - } -- /* Something not yet in use, tv-out maybe. */ -+ -+ /* EXT */ - for (i = 0; i < 3; i++) { - val = nv_rd32(dev, 0x0061e000 + (i * 0x800)); - nv_wr32(dev, 0x006101f0 + (i * 0x04), val); -@@ -243,24 +111,13 @@ - nv_wr32(dev, NV50_PDISPLAY_DAC_CLK_CTRL1(i), 0x00000001); - } - -- /* This used to be in crtc unblank, but seems out of place there. */ -- nv_wr32(dev, NV50_PDISPLAY_UNK_380, 0); -- /* RAM is clamped to 256 MiB. */ -- ram_amount = dev_priv->vram_size; -- NV_DEBUG_KMS(dev, "ram_amount %d\n", ram_amount); -- if (ram_amount > 256*1024*1024) -- ram_amount = 256*1024*1024; -- nv_wr32(dev, NV50_PDISPLAY_RAM_AMOUNT, ram_amount - 1); -- nv_wr32(dev, NV50_PDISPLAY_UNK_388, 0x150000); -- nv_wr32(dev, NV50_PDISPLAY_UNK_38C, 0); -- - /* 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(0x006194e8, 2, 0)) { -+ 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)); -@@ -268,39 +125,9 @@ - } - } - -- /* taken from nv bug #12637, attempts to un-wedge the hw if it's -- * stuck in some unspecified state -- */ -- start = ptimer->read(dev); -- nv_wr32(dev, NV50_PDISPLAY_CHANNEL_STAT(0), 0x2b00); -- while ((val = nv_rd32(dev, NV50_PDISPLAY_CHANNEL_STAT(0))) & 0x1e0000) { -- if ((val & 0x9f0000) == 0x20000) -- nv_wr32(dev, NV50_PDISPLAY_CHANNEL_STAT(0), -- val | 0x800000); -- -- if ((val & 0x3f0000) == 0x30000) -- nv_wr32(dev, NV50_PDISPLAY_CHANNEL_STAT(0), -- val | 0x200000); -- -- if (ptimer->read(dev) - start > 1000000000ULL) { -- NV_ERROR(dev, "timeout: (0x610200 & 0x1e0000) != 0\n"); -- NV_ERROR(dev, "0x610200 = 0x%08x\n", val); -- return -EBUSY; -- } -- } -- -- nv_wr32(dev, NV50_PDISPLAY_CTRL_STATE, NV50_PDISPLAY_CTRL_STATE_ENABLE); -- nv_wr32(dev, NV50_PDISPLAY_CHANNEL_STAT(0), 0x1000b03); -- if (!nv_wait(NV50_PDISPLAY_CHANNEL_STAT(0), 0x40000000, 0x40000000)) { -- NV_ERROR(dev, "timeout: (0x610200 & 0x40000000) == 0x40000000\n"); -- NV_ERROR(dev, "0x610200 = 0x%08x\n", -- nv_rd32(dev, NV50_PDISPLAY_CHANNEL_STAT(0))); -- return -EBUSY; -- } -- - for (i = 0; i < 2; i++) { - nv_wr32(dev, NV50_PDISPLAY_CURSOR_CURSOR_CTRL2(i), 0x2000); -- if (!nv_wait(NV50_PDISPLAY_CURSOR_CURSOR_CTRL2(i), -+ if (!nv_wait(dev, 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", -@@ -310,7 +137,7 @@ - - nv_wr32(dev, NV50_PDISPLAY_CURSOR_CURSOR_CTRL2(i), - NV50_PDISPLAY_CURSOR_CURSOR_CTRL2_ON); -- if (!nv_wait(NV50_PDISPLAY_CURSOR_CURSOR_CTRL2(i), -+ if (!nv_wait(dev, NV50_PDISPLAY_CURSOR_CURSOR_CTRL2(i), - NV50_PDISPLAY_CURSOR_CURSOR_CTRL2_STATUS, - NV50_PDISPLAY_CURSOR_CURSOR_CTRL2_STATUS_ACTIVE)) { - NV_ERROR(dev, "timeout: " -@@ -321,39 +148,31 @@ - } - } - -- nv_wr32(dev, NV50_PDISPLAY_OBJECTS, (evo->ramin->instance >> 8) | 9); -+ 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, -+ NV50_PDISPLAY_INTR_EN_1_CLK_UNK10 | -+ NV50_PDISPLAY_INTR_EN_1_CLK_UNK20 | -+ NV50_PDISPLAY_INTR_EN_1_CLK_UNK40); -+ -+ /* enable hotplug interrupts */ -+ list_for_each_entry(connector, &dev->mode_config.connector_list, head) { -+ struct nouveau_connector *conn = nouveau_connector(connector); -+ -+ if (conn->dcb->gpio_tag == 0xff) -+ continue; - -- /* initialise fifo */ -- nv_wr32(dev, NV50_PDISPLAY_CHANNEL_DMA_CB(0), -- ((evo->pushbuf_bo->bo.mem.mm_node->start << PAGE_SHIFT) >> 8) | -- NV50_PDISPLAY_CHANNEL_DMA_CB_LOCATION_VRAM | -- NV50_PDISPLAY_CHANNEL_DMA_CB_VALID); -- nv_wr32(dev, NV50_PDISPLAY_CHANNEL_UNK2(0), 0x00010000); -- nv_wr32(dev, NV50_PDISPLAY_CHANNEL_UNK3(0), 0x00000002); -- if (!nv_wait(0x610200, 0x80000000, 0x00000000)) { -- NV_ERROR(dev, "timeout: (0x610200 & 0x80000000) == 0\n"); -- NV_ERROR(dev, "0x610200 = 0x%08x\n", nv_rd32(dev, 0x610200)); -- return -EBUSY; -- } -- nv_wr32(dev, NV50_PDISPLAY_CHANNEL_STAT(0), -- (nv_rd32(dev, NV50_PDISPLAY_CHANNEL_STAT(0)) & ~0x00000003) | -- NV50_PDISPLAY_CHANNEL_STAT_DMA_ENABLED); -- nv_wr32(dev, NV50_PDISPLAY_USER_PUT(0), 0); -- nv_wr32(dev, NV50_PDISPLAY_CHANNEL_STAT(0), 0x01000003 | -- NV50_PDISPLAY_CHANNEL_STAT_DMA_ENABLED); -- nv_wr32(dev, 0x610300, nv_rd32(dev, 0x610300) & ~1); -- -- evo->dma.max = (4096/4) - 2; -- evo->dma.put = 0; -- evo->dma.cur = evo->dma.put; -- evo->dma.free = evo->dma.max - evo->dma.cur; -+ pgpio->irq_enable(dev, conn->dcb->gpio_tag, true); -+ } - -- ret = RING_SPACE(evo, NOUVEAU_DMA_SKIPS); -+ ret = nv50_evo_init(dev); - if (ret) - return ret; -+ evo = dev_priv->evo; - -- for (i = 0; i < NOUVEAU_DMA_SKIPS; i++) -- OUT_RING(evo, 0); -+ nv_wr32(dev, NV50_PDISPLAY_OBJECTS, (evo->ramin->vinst >> 8) | 9); - - ret = RING_SPACE(evo, 11); - if (ret) -@@ -370,24 +189,9 @@ - BEGIN_RING(evo, 0, NV50_EVO_CRTC(0, UNK082C), 1); - OUT_RING(evo, 0); - FIRE_RING(evo); -- if (!nv_wait(0x640004, 0xffffffff, evo->dma.put << 2)) -+ if (!nv_wait(dev, 0x640004, 0xffffffff, evo->dma.put << 2)) - NV_ERROR(dev, "evo pushbuf stalled\n"); - -- /* enable clock change interrupts. */ -- nv_wr32(dev, 0x610028, 0x00010001); -- nv_wr32(dev, NV50_PDISPLAY_INTR_EN, (NV50_PDISPLAY_INTR_EN_CLK_UNK10 | -- NV50_PDISPLAY_INTR_EN_CLK_UNK20 | -- NV50_PDISPLAY_INTR_EN_CLK_UNK40)); -- -- /* enable hotplug interrupts */ -- list_for_each_entry(connector, &dev->mode_config.connector_list, head) { -- struct nouveau_connector *conn = nouveau_connector(connector); -- -- if (conn->dcb->gpio_tag == 0xff) -- continue; -- -- pgpio->irq_enable(dev, conn->dcb->gpio_tag, true); -- } - - return 0; - } -@@ -424,7 +228,7 @@ - continue; - - nv_wr32(dev, NV50_PDISPLAY_INTR_1, mask); -- if (!nv_wait(NV50_PDISPLAY_INTR_1, mask, mask)) { -+ if (!nv_wait(dev, NV50_PDISPLAY_INTR_1, mask, mask)) { - NV_ERROR(dev, "timeout: (0x610024 & 0x%08x) == " - "0x%08x\n", mask, mask); - NV_ERROR(dev, "0x610024 = 0x%08x\n", -@@ -432,16 +236,10 @@ - } - } - -- nv_wr32(dev, NV50_PDISPLAY_CHANNEL_STAT(0), 0); -- nv_wr32(dev, NV50_PDISPLAY_CTRL_STATE, 0); -- if (!nv_wait(NV50_PDISPLAY_CHANNEL_STAT(0), 0x1e0000, 0)) { -- NV_ERROR(dev, "timeout: (0x610200 & 0x1e0000) == 0\n"); -- NV_ERROR(dev, "0x610200 = 0x%08x\n", -- nv_rd32(dev, NV50_PDISPLAY_CHANNEL_STAT(0))); -- } -+ nv50_evo_fini(dev); - - for (i = 0; i < 3; i++) { -- if (!nv_wait(NV50_PDISPLAY_SOR_DPMS_STATE(i), -+ if (!nv_wait(dev, 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, -@@ -450,7 +248,7 @@ - } - - /* disable interrupts. */ -- nv_wr32(dev, NV50_PDISPLAY_INTR_EN, 0x00000000); -+ nv_wr32(dev, NV50_PDISPLAY_INTR_EN_1, 0x00000000); - - /* disable hotplug interrupts */ - nv_wr32(dev, 0xe054, 0xffffffff); -@@ -488,13 +286,6 @@ - - dev->mode_config.fb_base = dev_priv->fb_phys; - -- /* Create EVO channel */ -- ret = nv50_evo_channel_new(dev, &dev_priv->evo); -- if (ret) { -- NV_ERROR(dev, "Error creating EVO channel: %d\n", ret); -- return ret; -- } -- - /* Create CRTC objects */ - for (i = 0; i < 2; i++) - nv50_crtc_create(dev, i); -@@ -549,14 +340,11 @@ - void - nv50_display_destroy(struct drm_device *dev) - { -- struct drm_nouveau_private *dev_priv = dev->dev_private; -- - NV_DEBUG_KMS(dev, "\n"); - - drm_mode_config_cleanup(dev); - - nv50_display_disable(dev); -- nv50_evo_channel_del(&dev_priv->evo); - } - - static u16 -@@ -640,32 +428,32 @@ - nv50_display_vblank_crtc_handler(struct drm_device *dev, int crtc) - { - struct drm_nouveau_private *dev_priv = dev->dev_private; -- struct nouveau_channel *chan; -- struct list_head *entry, *tmp; -+ struct nouveau_channel *chan, *tmp; - -- list_for_each_safe(entry, tmp, &dev_priv->vbl_waiting) { -- chan = list_entry(entry, struct nouveau_channel, nvsw.vbl_wait); -+ list_for_each_entry_safe(chan, tmp, &dev_priv->vbl_waiting, -+ nvsw.vbl_wait) { -+ if (chan->nvsw.vblsem_head != crtc) -+ continue; - - nouveau_bo_wr32(chan->notifier_bo, chan->nvsw.vblsem_offset, - chan->nvsw.vblsem_rval); - list_del(&chan->nvsw.vbl_wait); -+ drm_vblank_put(dev, crtc); - } -+ -+ drm_handle_vblank(dev, crtc); - } - - static void - nv50_display_vblank_handler(struct drm_device *dev, uint32_t intr) - { -- intr &= NV50_PDISPLAY_INTR_1_VBLANK_CRTC; -- - 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_EN, nv_rd32(dev, -- NV50_PDISPLAY_INTR_EN) & ~intr); -- nv_wr32(dev, NV50_PDISPLAY_INTR_1, intr); -+ nv_wr32(dev, NV50_PDISPLAY_INTR_1, NV50_PDISPLAY_INTR_1_VBLANK_CRTC); - } - - static void -@@ -710,7 +498,7 @@ - or = i; - } - -- for (i = 0; type == OUTPUT_ANY && i < 4; i++) { -+ for (i = 0; type == OUTPUT_ANY && i < nv50_sor_nr(dev); i++) { - if (dev_priv->chipset < 0x90 || - dev_priv->chipset == 0x92 || - dev_priv->chipset == 0xa0) -@@ -841,7 +629,7 @@ - or = i; - } - -- for (i = 0; type == OUTPUT_ANY && i < 4; i++) { -+ for (i = 0; type == OUTPUT_ANY && i < nv50_sor_nr(dev); i++) { - if (dev_priv->chipset < 0x90 || - dev_priv->chipset == 0x92 || - dev_priv->chipset == 0xa0) -@@ -991,16 +779,23 @@ - static void - nv50_display_error_handler(struct drm_device *dev) - { -- uint32_t addr, data; -+ u32 channels = (nv_rd32(dev, NV50_PDISPLAY_INTR_0) & 0x001f0000) >> 16; -+ u32 addr, data; -+ int chid; -+ -+ for (chid = 0; chid < 5; chid++) { -+ 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 " -+ "(0x%04x 0x%02x)\n", chid, -+ addr & 0xffc, data, addr >> 16, (addr >> 12) & 0xf); - -- nv_wr32(dev, NV50_PDISPLAY_INTR_0, 0x00010000); -- addr = nv_rd32(dev, NV50_PDISPLAY_TRAPPED_ADDR); -- data = nv_rd32(dev, NV50_PDISPLAY_TRAPPED_DATA); -- -- NV_ERROR(dev, "EvoCh %d Mthd 0x%04x Data 0x%08x (0x%04x 0x%02x)\n", -- 0, addr & 0xffc, data, addr >> 16, (addr >> 12) & 0xf); -- -- nv_wr32(dev, NV50_PDISPLAY_TRAPPED_ADDR, 0x90000000); -+ nv_wr32(dev, NV50_PDISPLAY_TRAPPED_ADDR(chid), 0x90000000); -+ } - } - - void -@@ -1086,9 +881,9 @@ - if (!intr0 && !(intr1 & ~delayed)) - break; - -- if (intr0 & 0x00010000) { -+ if (intr0 & 0x001f0000) { - nv50_display_error_handler(dev); -- intr0 &= ~0x00010000; -+ intr0 &= ~0x001f0000; - } - - if (intr1 & NV50_PDISPLAY_INTR_1_VBLANK_CRTC) { -diff -Naur linux-2.6.36/drivers/gpu/drm/nouveau/nv50_evo.c linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nv50_evo.c ---- linux-2.6.36/drivers/gpu/drm/nouveau/nv50_evo.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nv50_evo.c 2010-11-05 00:40:00.000000000 +0100 -@@ -0,0 +1,318 @@ -+/* -+ * Copyright 2010 Red Hat Inc. -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included in -+ * all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR -+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -+ * OTHER DEALINGS IN THE SOFTWARE. -+ * -+ * Authors: Ben Skeggs -+ */ -+ -+#include "drmP.h" -+ -+#include "nouveau_drv.h" -+#include "nouveau_dma.h" -+#include "nouveau_ramht.h" -+ -+static void -+nv50_evo_channel_del(struct nouveau_channel **pevo) -+{ -+ struct drm_nouveau_private *dev_priv; -+ struct nouveau_channel *evo = *pevo; -+ -+ if (!evo) -+ return; -+ *pevo = NULL; -+ -+ dev_priv = evo->dev->dev_private; -+ dev_priv->evo_alloc &= ~(1 << evo->id); -+ -+ nouveau_gpuobj_channel_takedown(evo); -+ nouveau_bo_unmap(evo->pushbuf_bo); -+ nouveau_bo_ref(NULL, &evo->pushbuf_bo); -+ -+ if (evo->user) -+ iounmap(evo->user); -+ -+ kfree(evo); -+} -+ -+int -+nv50_evo_dmaobj_new(struct nouveau_channel *evo, u32 class, u32 name, -+ u32 tile_flags, u32 magic_flags, u32 offset, u32 limit) -+{ -+ struct drm_nouveau_private *dev_priv = evo->dev->dev_private; -+ struct drm_device *dev = evo->dev; -+ struct nouveau_gpuobj *obj = NULL; -+ int ret; -+ -+ ret = nouveau_gpuobj_new(dev, dev_priv->evo, 6*4, 32, 0, &obj); -+ if (ret) -+ return ret; -+ obj->engine = NVOBJ_ENGINE_DISPLAY; -+ -+ nv_wo32(obj, 0, (tile_flags << 22) | (magic_flags << 16) | class); -+ nv_wo32(obj, 4, limit); -+ nv_wo32(obj, 8, offset); -+ nv_wo32(obj, 12, 0x00000000); -+ nv_wo32(obj, 16, 0x00000000); -+ if (dev_priv->card_type < NV_C0) -+ nv_wo32(obj, 20, 0x00010000); -+ else -+ nv_wo32(obj, 20, 0x00020000); -+ dev_priv->engine.instmem.flush(dev); -+ -+ ret = nouveau_ramht_insert(evo, name, obj); -+ nouveau_gpuobj_ref(NULL, &obj); -+ if (ret) { -+ return ret; -+ } -+ -+ return 0; -+} -+ -+static int -+nv50_evo_channel_new(struct drm_device *dev, struct nouveau_channel **pevo) -+{ -+ struct drm_nouveau_private *dev_priv = dev->dev_private; -+ struct nouveau_channel *evo; -+ int ret; -+ -+ evo = kzalloc(sizeof(struct nouveau_channel), GFP_KERNEL); -+ if (!evo) -+ return -ENOMEM; -+ *pevo = evo; -+ -+ for (evo->id = 0; evo->id < 5; evo->id++) { -+ if (dev_priv->evo_alloc & (1 << evo->id)) -+ continue; -+ -+ dev_priv->evo_alloc |= (1 << evo->id); -+ break; -+ } -+ -+ if (evo->id == 5) { -+ kfree(evo); -+ return -ENODEV; -+ } -+ -+ evo->dev = dev; -+ evo->user_get = 4; -+ evo->user_put = 0; -+ -+ ret = nouveau_bo_new(dev, NULL, 4096, 0, TTM_PL_FLAG_VRAM, 0, 0, -+ false, true, &evo->pushbuf_bo); -+ if (ret == 0) -+ ret = nouveau_bo_pin(evo->pushbuf_bo, 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); -+ 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 (dev_priv->evo && evo != dev_priv->evo) -+ nouveau_ramht_ref(dev_priv->evo->ramht, &evo->ramht, NULL); -+ -+ 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.mem.start << PAGE_SHIFT; -+ u32 tmp; -+ -+ tmp = nv_rd32(dev, NV50_PDISPLAY_EVO_CTRL(id)); -+ if ((tmp & 0x009f0000) == 0x00020000) -+ nv_wr32(dev, NV50_PDISPLAY_EVO_CTRL(id), tmp | 0x00800000); -+ -+ tmp = nv_rd32(dev, NV50_PDISPLAY_EVO_CTRL(id)); -+ if ((tmp & 0x003f0000) == 0x00030000) -+ nv_wr32(dev, NV50_PDISPLAY_EVO_CTRL(id), tmp | 0x00600000); -+ -+ /* initialise fifo */ -+ nv_wr32(dev, 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, -+ NV50_PDISPLAY_EVO_CTRL_DMA_ENABLED); -+ -+ nv_wr32(dev, NV50_PDISPLAY_USER_PUT(id), 0x00000000); -+ nv_wr32(dev, 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))); -+ return -EBUSY; -+ } -+ -+ /* enable error reporting on the channel */ -+ nv_mask(dev, 0x610028, 0x00000000, 0x00010001 << id); -+ -+ evo->dma.max = (4096/4) - 2; -+ evo->dma.put = 0; -+ evo->dma.cur = evo->dma.put; -+ evo->dma.free = evo->dma.max - evo->dma.cur; -+ -+ ret = RING_SPACE(evo, NOUVEAU_DMA_SKIPS); -+ if (ret) -+ return ret; -+ -+ for (i = 0; i < NOUVEAU_DMA_SKIPS; i++) -+ OUT_RING(evo, 0); -+ -+ return 0; -+} -+ -+static void -+nv50_evo_channel_fini(struct nouveau_channel *evo) -+{ -+ struct drm_device *dev = evo->dev; -+ int id = evo->id; -+ -+ 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))); -+ } -+} -+ -+static int -+nv50_evo_create(struct drm_device *dev) -+{ -+ struct drm_nouveau_private *dev_priv = dev->dev_private; -+ struct nouveau_gpuobj *ramht = NULL; -+ struct nouveau_channel *evo; -+ int ret; -+ -+ /* create primary evo channel, the one we use for modesetting -+ * purporses -+ */ -+ ret = nv50_evo_channel_new(dev, &dev_priv->evo); -+ if (ret) -+ return ret; -+ evo = dev_priv->evo; -+ -+ /* 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); -+ if (ret) { -+ NV_ERROR(dev, "Error allocating EVO channel memory: %d\n", ret); -+ nv50_evo_channel_del(&dev_priv->evo); -+ return ret; -+ } -+ -+ ret = drm_mm_init(&evo->ramin_heap, 0, 32768); -+ if (ret) { -+ NV_ERROR(dev, "Error initialising EVO PRAMIN heap: %d\n", ret); -+ nv50_evo_channel_del(&dev_priv->evo); -+ return ret; -+ } -+ -+ ret = nouveau_gpuobj_new(dev, evo, 4096, 16, 0, &ramht); -+ if (ret) { -+ NV_ERROR(dev, "Unable to allocate EVO RAMHT: %d\n", ret); -+ nv50_evo_channel_del(&dev_priv->evo); -+ return ret; -+ } -+ -+ ret = nouveau_ramht_new(dev, ramht, &evo->ramht); -+ nouveau_gpuobj_ref(NULL, &ramht); -+ if (ret) { -+ nv50_evo_channel_del(&dev_priv->evo); -+ return ret; -+ } -+ -+ /* create some default objects for the scanout memtypes we support */ -+ if (dev_priv->chipset != 0x50) { -+ ret = nv50_evo_dmaobj_new(evo, 0x3d, NvEvoFB16, 0x70, 0x19, -+ 0, 0xffffffff); -+ if (ret) { -+ nv50_evo_channel_del(&dev_priv->evo); -+ return ret; -+ } -+ -+ -+ ret = nv50_evo_dmaobj_new(evo, 0x3d, NvEvoFB32, 0x7a, 0x19, -+ 0, 0xffffffff); -+ if (ret) { -+ nv50_evo_channel_del(&dev_priv->evo); -+ return ret; -+ } -+ } -+ -+ ret = nv50_evo_dmaobj_new(evo, 0x3d, NvEvoVRAM, 0, 0x19, -+ 0, dev_priv->vram_size); -+ if (ret) { -+ nv50_evo_channel_del(&dev_priv->evo); -+ return ret; -+ } -+ -+ return 0; -+} -+ -+int -+nv50_evo_init(struct drm_device *dev) -+{ -+ struct drm_nouveau_private *dev_priv = dev->dev_private; -+ int ret; -+ -+ if (!dev_priv->evo) { -+ ret = nv50_evo_create(dev); -+ if (ret) -+ return ret; -+ } -+ -+ return nv50_evo_channel_init(dev_priv->evo); -+} -+ -+void -+nv50_evo_fini(struct drm_device *dev) -+{ -+ struct drm_nouveau_private *dev_priv = dev->dev_private; -+ -+ if (dev_priv->evo) { -+ nv50_evo_channel_fini(dev_priv->evo); -+ nv50_evo_channel_del(&dev_priv->evo); -+ } -+} -diff -Naur linux-2.6.36/drivers/gpu/drm/nouveau/nv50_evo.h linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nv50_evo.h ---- linux-2.6.36/drivers/gpu/drm/nouveau/nv50_evo.h 2010-10-20 22:30:22.000000000 +0200 -+++ linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nv50_evo.h 2010-11-05 00:40:00.000000000 +0100 -@@ -24,6 +24,15 @@ - * - */ - -+#ifndef __NV50_EVO_H__ -+#define __NV50_EVO_H__ -+ -+int nv50_evo_init(struct drm_device *dev); -+void nv50_evo_fini(struct drm_device *dev); -+int nv50_evo_dmaobj_new(struct nouveau_channel *, u32 class, u32 name, -+ u32 tile_flags, u32 magic_flags, -+ u32 offset, u32 limit); -+ - #define NV50_EVO_UPDATE 0x00000080 - #define NV50_EVO_UNK84 0x00000084 - #define NV50_EVO_UNK84_NOTIFY 0x40000000 -@@ -111,3 +120,4 @@ - #define NV50_EVO_CRTC_SCALE_RES1 0x000008d8 - #define NV50_EVO_CRTC_SCALE_RES2 0x000008dc - -+#endif -diff -Naur linux-2.6.36/drivers/gpu/drm/nouveau/nv50_fb.c linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nv50_fb.c ---- linux-2.6.36/drivers/gpu/drm/nouveau/nv50_fb.c 2010-10-20 22:30:22.000000000 +0200 -+++ linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nv50_fb.c 2010-11-05 00:40:00.000000000 +0100 -@@ -20,6 +20,7 @@ - case 0x50: - nv_wr32(dev, 0x100c90, 0x0707ff); - break; -+ case 0xa3: - case 0xa5: - case 0xa8: - nv_wr32(dev, 0x100c90, 0x0d0fff); -@@ -36,3 +37,46 @@ - nv50_fb_takedown(struct drm_device *dev) - { - } -+ -+void -+nv50_fb_vm_trap(struct drm_device *dev, int display, const char *name) -+{ -+ struct drm_nouveau_private *dev_priv = dev->dev_private; -+ unsigned long flags; -+ u32 trap[6], idx, chinst; -+ int i, ch; -+ -+ idx = nv_rd32(dev, 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(dev, 0x100c90, idx | 0x80000000); -+ -+ if (!display) -+ return; -+ -+ chinst = (trap[2] << 16) | trap[1]; -+ -+ spin_lock_irqsave(&dev_priv->channels.lock, flags); -+ for (ch = 0; ch < dev_priv->engine.fifo.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); -+ -+ NV_INFO(dev, "%s - VM: Trapped %s at %02x%04x%04x status %08x " -+ "channel %d (0x%08x)\n", -+ name, (trap[5] & 0x100 ? "read" : "write"), -+ trap[5] & 0xff, trap[4] & 0xffff, trap[3] & 0xffff, -+ trap[0], ch, chinst); -+} -diff -Naur linux-2.6.36/drivers/gpu/drm/nouveau/nv50_fbcon.c linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nv50_fbcon.c ---- linux-2.6.36/drivers/gpu/drm/nouveau/nv50_fbcon.c 2010-10-20 22:30:22.000000000 +0200 -+++ linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nv50_fbcon.c 2010-11-05 00:40:00.000000000 +0100 -@@ -1,28 +1,21 @@ - #include "drmP.h" - #include "nouveau_drv.h" - #include "nouveau_dma.h" -+#include "nouveau_ramht.h" - #include "nouveau_fbcon.h" - --void -+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; -+ int ret; - -- if (info->state != FBINFO_STATE_RUNNING) -- return; -- -- if (!(info->flags & FBINFO_HWACCEL_DISABLED) && -- RING_SPACE(chan, rect->rop == ROP_COPY ? 7 : 11)) { -- nouveau_fbcon_gpu_lockup(info); -- } -- -- if (info->flags & FBINFO_HWACCEL_DISABLED) { -- cfb_fillrect(info, rect); -- return; -- } -+ ret = RING_SPACE(chan, rect->rop == ROP_COPY ? 7 : 11); -+ if (ret) -+ return ret; - - if (rect->rop != ROP_COPY) { - BEGIN_RING(chan, NvSub2D, 0x02ac, 1); -@@ -44,27 +37,21 @@ - OUT_RING(chan, 3); - } - FIRE_RING(chan); -+ return 0; - } - --void -+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; -+ int ret; - -- if (info->state != FBINFO_STATE_RUNNING) -- return; -- -- if (!(info->flags & FBINFO_HWACCEL_DISABLED) && RING_SPACE(chan, 12)) { -- nouveau_fbcon_gpu_lockup(info); -- } -- -- if (info->flags & FBINFO_HWACCEL_DISABLED) { -- cfb_copyarea(info, region); -- return; -- } -+ ret = RING_SPACE(chan, 12); -+ if (ret) -+ return ret; - - BEGIN_RING(chan, NvSub2D, 0x0110, 1); - OUT_RING(chan, 0); -@@ -79,9 +66,10 @@ - OUT_RING(chan, 0); - OUT_RING(chan, region->sy); - FIRE_RING(chan); -+ return 0; - } - --void -+int - nv50_fbcon_imageblit(struct fb_info *info, const struct fb_image *image) - { - struct nouveau_fbdev *nfbdev = info->par; -@@ -91,23 +79,14 @@ - 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; -+ int ret; - -- if (info->state != FBINFO_STATE_RUNNING) -- return; -- -- if (image->depth != 1) { -- cfb_imageblit(info, image); -- return; -- } -- -- if (!(info->flags & FBINFO_HWACCEL_DISABLED) && RING_SPACE(chan, 11)) { -- nouveau_fbcon_gpu_lockup(info); -- } -+ if (image->depth != 1) -+ return -ENODEV; - -- if (info->flags & FBINFO_HWACCEL_DISABLED) { -- cfb_imageblit(info, image); -- return; -- } -+ ret = RING_SPACE(chan, 11); -+ if (ret) -+ return ret; - - width = ALIGN(image->width, 32); - dwords = (width * image->height) >> 5; -@@ -133,11 +112,9 @@ - while (dwords) { - int push = dwords > 2047 ? 2047 : dwords; - -- if (RING_SPACE(chan, push + 1)) { -- nouveau_fbcon_gpu_lockup(info); -- cfb_imageblit(info, image); -- return; -- } -+ ret = RING_SPACE(chan, push + 1); -+ if (ret) -+ return ret; - - dwords -= push; - -@@ -147,6 +124,7 @@ - } - - FIRE_RING(chan); -+ return 0; - } - - int -@@ -193,7 +171,8 @@ - if (ret) - return ret; - -- ret = nouveau_gpuobj_ref_add(dev, dev_priv->channel, Nv2D, eng2d, NULL); -+ ret = nouveau_ramht_insert(dev_priv->channel, Nv2D, eng2d); -+ nouveau_gpuobj_ref(NULL, &eng2d); - if (ret) - return ret; - -diff -Naur linux-2.6.36/drivers/gpu/drm/nouveau/nv50_fifo.c linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nv50_fifo.c ---- linux-2.6.36/drivers/gpu/drm/nouveau/nv50_fifo.c 2010-10-20 22:30:22.000000000 +0200 -+++ linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nv50_fifo.c 2010-11-05 00:40:00.000000000 +0100 -@@ -27,13 +27,14 @@ - #include "drmP.h" - #include "drm.h" - #include "nouveau_drv.h" -+#include "nouveau_ramht.h" - - static void - nv50_fifo_playlist_update(struct drm_device *dev) - { - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_fifo_engine *pfifo = &dev_priv->engine.fifo; -- struct nouveau_gpuobj_ref *cur; -+ struct nouveau_gpuobj *cur; - int i, nr; - - NV_DEBUG(dev, "\n"); -@@ -43,12 +44,15 @@ - - /* We never schedule channel 0 or 127 */ - for (i = 1, nr = 0; i < 127; i++) { -- if (dev_priv->fifos[i] && dev_priv->fifos[i]->ramfc) -- nv_wo32(dev, cur->gpuobj, nr++, i); -+ if (dev_priv->channels.ptr[i] && -+ dev_priv->channels.ptr[i]->ramfc) { -+ nv_wo32(cur, (nr * 4), i); -+ nr++; -+ } - } - dev_priv->engine.instmem.flush(dev); - -- nv_wr32(dev, 0x32f4, cur->instance >> 12); -+ nv_wr32(dev, 0x32f4, cur->vinst >> 12); - nv_wr32(dev, 0x32ec, nr); - nv_wr32(dev, 0x2500, 0x101); - } -@@ -57,15 +61,15 @@ - nv50_fifo_channel_enable(struct drm_device *dev, int channel) - { - struct drm_nouveau_private *dev_priv = dev->dev_private; -- struct nouveau_channel *chan = dev_priv->fifos[channel]; -+ struct nouveau_channel *chan = dev_priv->channels.ptr[channel]; - uint32_t inst; - - NV_DEBUG(dev, "ch%d\n", channel); - - if (dev_priv->chipset == 0x50) -- inst = chan->ramfc->instance >> 12; -+ inst = chan->ramfc->vinst >> 12; - else -- inst = chan->ramfc->instance >> 8; -+ inst = chan->ramfc->vinst >> 8; - - nv_wr32(dev, NV50_PFIFO_CTX_TABLE(channel), inst | - NV50_PFIFO_CTX_TABLE_CHANNEL_ENABLED); -@@ -115,7 +119,7 @@ - NV_DEBUG(dev, "\n"); - - for (i = 0; i < NV50_PFIFO_CTX_TABLE__SIZE; i++) { -- if (dev_priv->fifos[i]) -+ if (dev_priv->channels.ptr[i]) - nv50_fifo_channel_enable(dev, i); - else - nv50_fifo_channel_disable(dev, i); -@@ -163,19 +167,19 @@ - goto just_reset; - } - -- ret = nouveau_gpuobj_new_ref(dev, NULL, NULL, 0, 128*4, 0x1000, -- NVOBJ_FLAG_ZERO_ALLOC, -- &pfifo->playlist[0]); -+ ret = nouveau_gpuobj_new(dev, NULL, 128*4, 0x1000, -+ NVOBJ_FLAG_ZERO_ALLOC, -+ &pfifo->playlist[0]); - if (ret) { - NV_ERROR(dev, "error creating playlist 0: %d\n", ret); - return ret; - } - -- ret = nouveau_gpuobj_new_ref(dev, NULL, NULL, 0, 128*4, 0x1000, -- NVOBJ_FLAG_ZERO_ALLOC, -- &pfifo->playlist[1]); -+ ret = nouveau_gpuobj_new(dev, NULL, 128*4, 0x1000, -+ NVOBJ_FLAG_ZERO_ALLOC, -+ &pfifo->playlist[1]); - if (ret) { -- nouveau_gpuobj_ref_del(dev, &pfifo->playlist[0]); -+ nouveau_gpuobj_ref(NULL, &pfifo->playlist[0]); - NV_ERROR(dev, "error creating playlist 1: %d\n", ret); - return ret; - } -@@ -203,8 +207,8 @@ - if (!pfifo->playlist[0]) - return; - -- nouveau_gpuobj_ref_del(dev, &pfifo->playlist[0]); -- nouveau_gpuobj_ref_del(dev, &pfifo->playlist[1]); -+ nouveau_gpuobj_ref(NULL, &pfifo->playlist[0]); -+ nouveau_gpuobj_ref(NULL, &pfifo->playlist[1]); - } - - int -@@ -226,59 +230,54 @@ - NV_DEBUG(dev, "ch%d\n", chan->id); - - if (dev_priv->chipset == 0x50) { -- uint32_t ramin_poffset = chan->ramin->gpuobj->im_pramin->start; -- uint32_t ramin_voffset = chan->ramin->gpuobj->im_backing_start; -- -- ret = nouveau_gpuobj_new_fake(dev, ramin_poffset, ramin_voffset, -- 0x100, NVOBJ_FLAG_ZERO_ALLOC | -- NVOBJ_FLAG_ZERO_FREE, &ramfc, -+ ret = nouveau_gpuobj_new_fake(dev, chan->ramin->pinst, -+ chan->ramin->vinst, 0x100, -+ NVOBJ_FLAG_ZERO_ALLOC | -+ NVOBJ_FLAG_ZERO_FREE, - &chan->ramfc); - if (ret) - return ret; - -- ret = nouveau_gpuobj_new_fake(dev, ramin_poffset + 0x0400, -- ramin_voffset + 0x0400, 4096, -- 0, NULL, &chan->cache); -+ ret = nouveau_gpuobj_new_fake(dev, chan->ramin->pinst + 0x0400, -+ chan->ramin->vinst + 0x0400, -+ 4096, 0, &chan->cache); - if (ret) - return ret; - } else { -- ret = nouveau_gpuobj_new_ref(dev, chan, NULL, 0, 0x100, 256, -- NVOBJ_FLAG_ZERO_ALLOC | -- NVOBJ_FLAG_ZERO_FREE, -- &chan->ramfc); -+ ret = nouveau_gpuobj_new(dev, chan, 0x100, 256, -+ NVOBJ_FLAG_ZERO_ALLOC | -+ NVOBJ_FLAG_ZERO_FREE, &chan->ramfc); - if (ret) - return ret; -- ramfc = chan->ramfc->gpuobj; - -- ret = nouveau_gpuobj_new_ref(dev, chan, NULL, 0, 4096, 1024, -- 0, &chan->cache); -+ ret = nouveau_gpuobj_new(dev, chan, 4096, 1024, -+ 0, &chan->cache); - if (ret) - return ret; - } -+ ramfc = chan->ramfc; - - spin_lock_irqsave(&dev_priv->context_switch_lock, flags); - -- nv_wo32(dev, ramfc, 0x48/4, chan->pushbuf->instance >> 4); -- nv_wo32(dev, ramfc, 0x80/4, (0 << 27) /* 4KiB */ | -- (4 << 24) /* SEARCH_FULL */ | -- (chan->ramht->instance >> 4)); -- nv_wo32(dev, ramfc, 0x44/4, 0x2101ffff); -- nv_wo32(dev, ramfc, 0x60/4, 0x7fffffff); -- nv_wo32(dev, ramfc, 0x40/4, 0x00000000); -- nv_wo32(dev, ramfc, 0x7c/4, 0x30000001); -- nv_wo32(dev, ramfc, 0x78/4, 0x00000000); -- nv_wo32(dev, ramfc, 0x3c/4, 0x403f6078); -- nv_wo32(dev, ramfc, 0x50/4, chan->pushbuf_base + -- chan->dma.ib_base * 4); -- nv_wo32(dev, ramfc, 0x54/4, drm_order(chan->dma.ib_max + 1) << 16); -+ nv_wo32(ramfc, 0x48, chan->pushbuf->cinst >> 4); -+ nv_wo32(ramfc, 0x80, ((chan->ramht->bits - 9) << 27) | -+ (4 << 24) /* SEARCH_FULL */ | -+ (chan->ramht->gpuobj->cinst >> 4)); -+ nv_wo32(ramfc, 0x44, 0x2101ffff); -+ nv_wo32(ramfc, 0x60, 0x7fffffff); -+ nv_wo32(ramfc, 0x40, 0x00000000); -+ nv_wo32(ramfc, 0x7c, 0x30000001); -+ nv_wo32(ramfc, 0x78, 0x00000000); -+ nv_wo32(ramfc, 0x3c, 0x403f6078); -+ nv_wo32(ramfc, 0x50, chan->pushbuf_base + chan->dma.ib_base * 4); -+ nv_wo32(ramfc, 0x54, drm_order(chan->dma.ib_max + 1) << 16); - - if (dev_priv->chipset != 0x50) { -- nv_wo32(dev, chan->ramin->gpuobj, 0, chan->id); -- nv_wo32(dev, chan->ramin->gpuobj, 1, -- chan->ramfc->instance >> 8); -+ nv_wo32(chan->ramin, 0, chan->id); -+ nv_wo32(chan->ramin, 4, chan->ramfc->vinst >> 8); - -- nv_wo32(dev, ramfc, 0x88/4, chan->cache->instance >> 10); -- nv_wo32(dev, ramfc, 0x98/4, chan->ramin->instance >> 12); -+ nv_wo32(ramfc, 0x88, chan->cache->vinst >> 10); -+ nv_wo32(ramfc, 0x98, chan->ramin->vinst >> 12); - } - - dev_priv->engine.instmem.flush(dev); -@@ -293,12 +292,26 @@ - nv50_fifo_destroy_context(struct nouveau_channel *chan) - { - struct drm_device *dev = chan->dev; -- struct nouveau_gpuobj_ref *ramfc = chan->ramfc; -+ struct drm_nouveau_private *dev_priv = dev->dev_private; -+ struct nouveau_fifo_engine *pfifo = &dev_priv->engine.fifo; -+ struct nouveau_gpuobj *ramfc = NULL; -+ unsigned long flags; - - NV_DEBUG(dev, "ch%d\n", chan->id); - -+ spin_lock_irqsave(&dev_priv->context_switch_lock, flags); -+ pfifo->reassign(dev, false); -+ -+ /* Unload the context if it's the currently active one */ -+ if (pfifo->channel_id(dev) == chan->id) { -+ pfifo->disable(dev); -+ pfifo->unload_context(dev); -+ pfifo->enable(dev); -+ } -+ - /* This will ensure the channel is seen as disabled. */ -- chan->ramfc = NULL; -+ nouveau_gpuobj_ref(chan->ramfc, &ramfc); -+ nouveau_gpuobj_ref(NULL, &chan->ramfc); - nv50_fifo_channel_disable(dev, chan->id); - - /* Dummy channel, also used on ch 127 */ -@@ -306,8 +319,12 @@ - nv50_fifo_channel_disable(dev, 127); - nv50_fifo_playlist_update(dev); - -- nouveau_gpuobj_ref_del(dev, &ramfc); -- nouveau_gpuobj_ref_del(dev, &chan->cache); -+ pfifo->reassign(dev, true); -+ spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags); -+ -+ /* Free the channel resources */ -+ nouveau_gpuobj_ref(NULL, &ramfc); -+ nouveau_gpuobj_ref(NULL, &chan->cache); - } - - int -@@ -315,63 +332,63 @@ - { - struct drm_device *dev = chan->dev; - struct drm_nouveau_private *dev_priv = dev->dev_private; -- struct nouveau_gpuobj *ramfc = chan->ramfc->gpuobj; -- struct nouveau_gpuobj *cache = chan->cache->gpuobj; -+ struct nouveau_gpuobj *ramfc = chan->ramfc; -+ struct nouveau_gpuobj *cache = chan->cache; - int ptr, cnt; - - NV_DEBUG(dev, "ch%d\n", chan->id); - -- nv_wr32(dev, 0x3330, nv_ro32(dev, ramfc, 0x00/4)); -- nv_wr32(dev, 0x3334, nv_ro32(dev, ramfc, 0x04/4)); -- nv_wr32(dev, 0x3240, nv_ro32(dev, ramfc, 0x08/4)); -- nv_wr32(dev, 0x3320, nv_ro32(dev, ramfc, 0x0c/4)); -- nv_wr32(dev, 0x3244, nv_ro32(dev, ramfc, 0x10/4)); -- nv_wr32(dev, 0x3328, nv_ro32(dev, ramfc, 0x14/4)); -- nv_wr32(dev, 0x3368, nv_ro32(dev, ramfc, 0x18/4)); -- nv_wr32(dev, 0x336c, nv_ro32(dev, ramfc, 0x1c/4)); -- nv_wr32(dev, 0x3370, nv_ro32(dev, ramfc, 0x20/4)); -- nv_wr32(dev, 0x3374, nv_ro32(dev, ramfc, 0x24/4)); -- nv_wr32(dev, 0x3378, nv_ro32(dev, ramfc, 0x28/4)); -- nv_wr32(dev, 0x337c, nv_ro32(dev, ramfc, 0x2c/4)); -- nv_wr32(dev, 0x3228, nv_ro32(dev, ramfc, 0x30/4)); -- nv_wr32(dev, 0x3364, nv_ro32(dev, ramfc, 0x34/4)); -- nv_wr32(dev, 0x32a0, nv_ro32(dev, ramfc, 0x38/4)); -- nv_wr32(dev, 0x3224, nv_ro32(dev, ramfc, 0x3c/4)); -- nv_wr32(dev, 0x324c, nv_ro32(dev, ramfc, 0x40/4)); -- nv_wr32(dev, 0x2044, nv_ro32(dev, ramfc, 0x44/4)); -- nv_wr32(dev, 0x322c, nv_ro32(dev, ramfc, 0x48/4)); -- nv_wr32(dev, 0x3234, nv_ro32(dev, ramfc, 0x4c/4)); -- nv_wr32(dev, 0x3340, nv_ro32(dev, ramfc, 0x50/4)); -- nv_wr32(dev, 0x3344, nv_ro32(dev, ramfc, 0x54/4)); -- nv_wr32(dev, 0x3280, nv_ro32(dev, ramfc, 0x58/4)); -- nv_wr32(dev, 0x3254, nv_ro32(dev, ramfc, 0x5c/4)); -- nv_wr32(dev, 0x3260, nv_ro32(dev, ramfc, 0x60/4)); -- nv_wr32(dev, 0x3264, nv_ro32(dev, ramfc, 0x64/4)); -- nv_wr32(dev, 0x3268, nv_ro32(dev, ramfc, 0x68/4)); -- nv_wr32(dev, 0x326c, nv_ro32(dev, ramfc, 0x6c/4)); -- nv_wr32(dev, 0x32e4, nv_ro32(dev, ramfc, 0x70/4)); -- nv_wr32(dev, 0x3248, nv_ro32(dev, ramfc, 0x74/4)); -- nv_wr32(dev, 0x2088, nv_ro32(dev, ramfc, 0x78/4)); -- nv_wr32(dev, 0x2058, nv_ro32(dev, ramfc, 0x7c/4)); -- nv_wr32(dev, 0x2210, nv_ro32(dev, ramfc, 0x80/4)); -+ nv_wr32(dev, 0x3330, nv_ro32(ramfc, 0x00)); -+ nv_wr32(dev, 0x3334, nv_ro32(ramfc, 0x04)); -+ nv_wr32(dev, 0x3240, nv_ro32(ramfc, 0x08)); -+ nv_wr32(dev, 0x3320, nv_ro32(ramfc, 0x0c)); -+ nv_wr32(dev, 0x3244, nv_ro32(ramfc, 0x10)); -+ nv_wr32(dev, 0x3328, nv_ro32(ramfc, 0x14)); -+ nv_wr32(dev, 0x3368, nv_ro32(ramfc, 0x18)); -+ nv_wr32(dev, 0x336c, nv_ro32(ramfc, 0x1c)); -+ nv_wr32(dev, 0x3370, nv_ro32(ramfc, 0x20)); -+ nv_wr32(dev, 0x3374, nv_ro32(ramfc, 0x24)); -+ nv_wr32(dev, 0x3378, nv_ro32(ramfc, 0x28)); -+ nv_wr32(dev, 0x337c, nv_ro32(ramfc, 0x2c)); -+ nv_wr32(dev, 0x3228, nv_ro32(ramfc, 0x30)); -+ nv_wr32(dev, 0x3364, nv_ro32(ramfc, 0x34)); -+ nv_wr32(dev, 0x32a0, nv_ro32(ramfc, 0x38)); -+ nv_wr32(dev, 0x3224, nv_ro32(ramfc, 0x3c)); -+ nv_wr32(dev, 0x324c, nv_ro32(ramfc, 0x40)); -+ nv_wr32(dev, 0x2044, nv_ro32(ramfc, 0x44)); -+ nv_wr32(dev, 0x322c, nv_ro32(ramfc, 0x48)); -+ nv_wr32(dev, 0x3234, nv_ro32(ramfc, 0x4c)); -+ nv_wr32(dev, 0x3340, nv_ro32(ramfc, 0x50)); -+ nv_wr32(dev, 0x3344, nv_ro32(ramfc, 0x54)); -+ nv_wr32(dev, 0x3280, nv_ro32(ramfc, 0x58)); -+ nv_wr32(dev, 0x3254, nv_ro32(ramfc, 0x5c)); -+ nv_wr32(dev, 0x3260, nv_ro32(ramfc, 0x60)); -+ nv_wr32(dev, 0x3264, nv_ro32(ramfc, 0x64)); -+ nv_wr32(dev, 0x3268, nv_ro32(ramfc, 0x68)); -+ nv_wr32(dev, 0x326c, nv_ro32(ramfc, 0x6c)); -+ nv_wr32(dev, 0x32e4, nv_ro32(ramfc, 0x70)); -+ nv_wr32(dev, 0x3248, nv_ro32(ramfc, 0x74)); -+ nv_wr32(dev, 0x2088, nv_ro32(ramfc, 0x78)); -+ nv_wr32(dev, 0x2058, nv_ro32(ramfc, 0x7c)); -+ nv_wr32(dev, 0x2210, nv_ro32(ramfc, 0x80)); - -- cnt = nv_ro32(dev, ramfc, 0x84/4); -+ cnt = nv_ro32(ramfc, 0x84); - for (ptr = 0; ptr < cnt; ptr++) { - nv_wr32(dev, NV40_PFIFO_CACHE1_METHOD(ptr), -- nv_ro32(dev, cache, (ptr * 2) + 0)); -+ nv_ro32(cache, (ptr * 8) + 0)); - nv_wr32(dev, NV40_PFIFO_CACHE1_DATA(ptr), -- nv_ro32(dev, cache, (ptr * 2) + 1)); -+ nv_ro32(cache, (ptr * 8) + 4)); - } - nv_wr32(dev, NV03_PFIFO_CACHE1_PUT, cnt << 2); - nv_wr32(dev, NV03_PFIFO_CACHE1_GET, 0); - - /* guessing that all the 0x34xx regs aren't on NV50 */ - if (dev_priv->chipset != 0x50) { -- nv_wr32(dev, 0x340c, nv_ro32(dev, ramfc, 0x88/4)); -- nv_wr32(dev, 0x3400, nv_ro32(dev, ramfc, 0x8c/4)); -- nv_wr32(dev, 0x3404, nv_ro32(dev, ramfc, 0x90/4)); -- nv_wr32(dev, 0x3408, nv_ro32(dev, ramfc, 0x94/4)); -- nv_wr32(dev, 0x3410, nv_ro32(dev, ramfc, 0x98/4)); -+ nv_wr32(dev, 0x340c, nv_ro32(ramfc, 0x88)); -+ nv_wr32(dev, 0x3400, nv_ro32(ramfc, 0x8c)); -+ nv_wr32(dev, 0x3404, nv_ro32(ramfc, 0x90)); -+ nv_wr32(dev, 0x3408, nv_ro32(ramfc, 0x94)); -+ nv_wr32(dev, 0x3410, nv_ro32(ramfc, 0x98)); - } - - nv_wr32(dev, NV03_PFIFO_CACHE1_PUSH1, chan->id | (1<<16)); -@@ -393,68 +410,69 @@ - if (chid < 1 || chid >= dev_priv->engine.fifo.channels - 1) - return 0; - -- chan = dev_priv->fifos[chid]; -+ chan = dev_priv->channels.ptr[chid]; - if (!chan) { - NV_ERROR(dev, "Inactive channel on PFIFO: %d\n", chid); - return -EINVAL; - } - NV_DEBUG(dev, "ch%d\n", chan->id); -- ramfc = chan->ramfc->gpuobj; -- cache = chan->cache->gpuobj; -+ ramfc = chan->ramfc; -+ cache = chan->cache; - -- nv_wo32(dev, ramfc, 0x00/4, nv_rd32(dev, 0x3330)); -- nv_wo32(dev, ramfc, 0x04/4, nv_rd32(dev, 0x3334)); -- nv_wo32(dev, ramfc, 0x08/4, nv_rd32(dev, 0x3240)); -- nv_wo32(dev, ramfc, 0x0c/4, nv_rd32(dev, 0x3320)); -- nv_wo32(dev, ramfc, 0x10/4, nv_rd32(dev, 0x3244)); -- nv_wo32(dev, ramfc, 0x14/4, nv_rd32(dev, 0x3328)); -- nv_wo32(dev, ramfc, 0x18/4, nv_rd32(dev, 0x3368)); -- nv_wo32(dev, ramfc, 0x1c/4, nv_rd32(dev, 0x336c)); -- nv_wo32(dev, ramfc, 0x20/4, nv_rd32(dev, 0x3370)); -- nv_wo32(dev, ramfc, 0x24/4, nv_rd32(dev, 0x3374)); -- nv_wo32(dev, ramfc, 0x28/4, nv_rd32(dev, 0x3378)); -- nv_wo32(dev, ramfc, 0x2c/4, nv_rd32(dev, 0x337c)); -- nv_wo32(dev, ramfc, 0x30/4, nv_rd32(dev, 0x3228)); -- nv_wo32(dev, ramfc, 0x34/4, nv_rd32(dev, 0x3364)); -- nv_wo32(dev, ramfc, 0x38/4, nv_rd32(dev, 0x32a0)); -- nv_wo32(dev, ramfc, 0x3c/4, nv_rd32(dev, 0x3224)); -- nv_wo32(dev, ramfc, 0x40/4, nv_rd32(dev, 0x324c)); -- nv_wo32(dev, ramfc, 0x44/4, nv_rd32(dev, 0x2044)); -- nv_wo32(dev, ramfc, 0x48/4, nv_rd32(dev, 0x322c)); -- nv_wo32(dev, ramfc, 0x4c/4, nv_rd32(dev, 0x3234)); -- nv_wo32(dev, ramfc, 0x50/4, nv_rd32(dev, 0x3340)); -- nv_wo32(dev, ramfc, 0x54/4, nv_rd32(dev, 0x3344)); -- nv_wo32(dev, ramfc, 0x58/4, nv_rd32(dev, 0x3280)); -- nv_wo32(dev, ramfc, 0x5c/4, nv_rd32(dev, 0x3254)); -- nv_wo32(dev, ramfc, 0x60/4, nv_rd32(dev, 0x3260)); -- nv_wo32(dev, ramfc, 0x64/4, nv_rd32(dev, 0x3264)); -- nv_wo32(dev, ramfc, 0x68/4, nv_rd32(dev, 0x3268)); -- nv_wo32(dev, ramfc, 0x6c/4, nv_rd32(dev, 0x326c)); -- nv_wo32(dev, ramfc, 0x70/4, nv_rd32(dev, 0x32e4)); -- nv_wo32(dev, ramfc, 0x74/4, nv_rd32(dev, 0x3248)); -- nv_wo32(dev, ramfc, 0x78/4, nv_rd32(dev, 0x2088)); -- nv_wo32(dev, ramfc, 0x7c/4, nv_rd32(dev, 0x2058)); -- nv_wo32(dev, ramfc, 0x80/4, nv_rd32(dev, 0x2210)); -+ nv_wo32(ramfc, 0x00, nv_rd32(dev, 0x3330)); -+ nv_wo32(ramfc, 0x04, nv_rd32(dev, 0x3334)); -+ nv_wo32(ramfc, 0x08, nv_rd32(dev, 0x3240)); -+ nv_wo32(ramfc, 0x0c, nv_rd32(dev, 0x3320)); -+ nv_wo32(ramfc, 0x10, nv_rd32(dev, 0x3244)); -+ nv_wo32(ramfc, 0x14, nv_rd32(dev, 0x3328)); -+ nv_wo32(ramfc, 0x18, nv_rd32(dev, 0x3368)); -+ nv_wo32(ramfc, 0x1c, nv_rd32(dev, 0x336c)); -+ nv_wo32(ramfc, 0x20, nv_rd32(dev, 0x3370)); -+ nv_wo32(ramfc, 0x24, nv_rd32(dev, 0x3374)); -+ nv_wo32(ramfc, 0x28, nv_rd32(dev, 0x3378)); -+ nv_wo32(ramfc, 0x2c, nv_rd32(dev, 0x337c)); -+ nv_wo32(ramfc, 0x30, nv_rd32(dev, 0x3228)); -+ nv_wo32(ramfc, 0x34, nv_rd32(dev, 0x3364)); -+ nv_wo32(ramfc, 0x38, nv_rd32(dev, 0x32a0)); -+ nv_wo32(ramfc, 0x3c, nv_rd32(dev, 0x3224)); -+ nv_wo32(ramfc, 0x40, nv_rd32(dev, 0x324c)); -+ nv_wo32(ramfc, 0x44, nv_rd32(dev, 0x2044)); -+ nv_wo32(ramfc, 0x48, nv_rd32(dev, 0x322c)); -+ nv_wo32(ramfc, 0x4c, nv_rd32(dev, 0x3234)); -+ nv_wo32(ramfc, 0x50, nv_rd32(dev, 0x3340)); -+ nv_wo32(ramfc, 0x54, nv_rd32(dev, 0x3344)); -+ nv_wo32(ramfc, 0x58, nv_rd32(dev, 0x3280)); -+ nv_wo32(ramfc, 0x5c, nv_rd32(dev, 0x3254)); -+ nv_wo32(ramfc, 0x60, nv_rd32(dev, 0x3260)); -+ nv_wo32(ramfc, 0x64, nv_rd32(dev, 0x3264)); -+ nv_wo32(ramfc, 0x68, nv_rd32(dev, 0x3268)); -+ nv_wo32(ramfc, 0x6c, nv_rd32(dev, 0x326c)); -+ nv_wo32(ramfc, 0x70, nv_rd32(dev, 0x32e4)); -+ nv_wo32(ramfc, 0x74, nv_rd32(dev, 0x3248)); -+ nv_wo32(ramfc, 0x78, nv_rd32(dev, 0x2088)); -+ nv_wo32(ramfc, 0x7c, nv_rd32(dev, 0x2058)); -+ nv_wo32(ramfc, 0x80, nv_rd32(dev, 0x2210)); - - put = (nv_rd32(dev, NV03_PFIFO_CACHE1_PUT) & 0x7ff) >> 2; - get = (nv_rd32(dev, NV03_PFIFO_CACHE1_GET) & 0x7ff) >> 2; - ptr = 0; - while (put != get) { -- nv_wo32(dev, cache, ptr++, -- nv_rd32(dev, NV40_PFIFO_CACHE1_METHOD(get))); -- nv_wo32(dev, cache, ptr++, -- nv_rd32(dev, NV40_PFIFO_CACHE1_DATA(get))); -+ nv_wo32(cache, ptr + 0, -+ nv_rd32(dev, NV40_PFIFO_CACHE1_METHOD(get))); -+ nv_wo32(cache, ptr + 4, -+ nv_rd32(dev, NV40_PFIFO_CACHE1_DATA(get))); - get = (get + 1) & 0x1ff; -+ ptr += 8; - } - - /* guessing that all the 0x34xx regs aren't on NV50 */ - if (dev_priv->chipset != 0x50) { -- nv_wo32(dev, ramfc, 0x84/4, ptr >> 1); -- nv_wo32(dev, ramfc, 0x88/4, nv_rd32(dev, 0x340c)); -- nv_wo32(dev, ramfc, 0x8c/4, nv_rd32(dev, 0x3400)); -- nv_wo32(dev, ramfc, 0x90/4, nv_rd32(dev, 0x3404)); -- nv_wo32(dev, ramfc, 0x94/4, nv_rd32(dev, 0x3408)); -- nv_wo32(dev, ramfc, 0x98/4, nv_rd32(dev, 0x3410)); -+ nv_wo32(ramfc, 0x84, ptr >> 3); -+ nv_wo32(ramfc, 0x88, nv_rd32(dev, 0x340c)); -+ nv_wo32(ramfc, 0x8c, nv_rd32(dev, 0x3400)); -+ nv_wo32(ramfc, 0x90, nv_rd32(dev, 0x3404)); -+ nv_wo32(ramfc, 0x94, nv_rd32(dev, 0x3408)); -+ nv_wo32(ramfc, 0x98, nv_rd32(dev, 0x3410)); - } - - dev_priv->engine.instmem.flush(dev); -@@ -464,3 +482,8 @@ - return 0; - } - -+void -+nv50_fifo_tlb_flush(struct drm_device *dev) -+{ -+ nv50_vm_flush(dev, 5); -+} -diff -Naur linux-2.6.36/drivers/gpu/drm/nouveau/nv50_graph.c linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nv50_graph.c ---- linux-2.6.36/drivers/gpu/drm/nouveau/nv50_graph.c 2010-10-20 22:30:22.000000000 +0200 -+++ linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nv50_graph.c 2010-11-05 00:40:00.000000000 +0100 -@@ -27,8 +27,12 @@ - #include "drmP.h" - #include "drm.h" - #include "nouveau_drv.h" -- -+#include "nouveau_ramht.h" - #include "nouveau_grctx.h" -+#include "nouveau_dma.h" -+#include "nv50_evo.h" -+ -+static int nv50_graph_register(struct drm_device *); - - static void - nv50_graph_init_reset(struct drm_device *dev) -@@ -145,12 +149,15 @@ - nv50_graph_init_reset(dev); - nv50_graph_init_regs__nv(dev); - nv50_graph_init_regs(dev); -- nv50_graph_init_intr(dev); - - ret = nv50_graph_init_ctxctl(dev); - if (ret) - return ret; - -+ ret = nv50_graph_register(dev); -+ if (ret) -+ return ret; -+ nv50_graph_init_intr(dev); - return 0; - } - -@@ -181,7 +188,7 @@ - /* Be sure we're not in the middle of a context switch or bad things - * will happen, such as unloading the wrong pgraph context. - */ -- if (!nv_wait(0x400300, 0x00000001, 0x00000000)) -+ if (!nv_wait(dev, 0x400300, 0x00000001, 0x00000000)) - NV_ERROR(dev, "Ctxprog is still running\n"); - - inst = nv_rd32(dev, NV50_PGRAPH_CTXCTL_CUR); -@@ -190,9 +197,9 @@ - inst = (inst & NV50_PGRAPH_CTXCTL_CUR_INSTANCE) << 12; - - for (i = 0; i < dev_priv->engine.fifo.channels; i++) { -- struct nouveau_channel *chan = dev_priv->fifos[i]; -+ struct nouveau_channel *chan = dev_priv->channels.ptr[i]; - -- if (chan && chan->ramin && chan->ramin->instance == inst) -+ if (chan && chan->ramin && chan->ramin->vinst == inst) - return chan; - } - -@@ -204,36 +211,34 @@ - { - struct drm_device *dev = chan->dev; - struct drm_nouveau_private *dev_priv = dev->dev_private; -- struct nouveau_gpuobj *ramin = chan->ramin->gpuobj; -- struct nouveau_gpuobj *obj; -+ struct nouveau_gpuobj *ramin = chan->ramin; - struct nouveau_pgraph_engine *pgraph = &dev_priv->engine.graph; - struct nouveau_grctx ctx = {}; - int hdr, ret; - - NV_DEBUG(dev, "ch%d\n", chan->id); - -- ret = nouveau_gpuobj_new_ref(dev, chan, NULL, 0, pgraph->grctx_size, -- 0x1000, NVOBJ_FLAG_ZERO_ALLOC | -- NVOBJ_FLAG_ZERO_FREE, &chan->ramin_grctx); -+ ret = nouveau_gpuobj_new(dev, chan, pgraph->grctx_size, 0, -+ NVOBJ_FLAG_ZERO_ALLOC | -+ NVOBJ_FLAG_ZERO_FREE, &chan->ramin_grctx); - if (ret) - return ret; -- obj = chan->ramin_grctx->gpuobj; - - hdr = (dev_priv->chipset == 0x50) ? 0x200 : 0x20; -- nv_wo32(dev, ramin, (hdr + 0x00)/4, 0x00190002); -- nv_wo32(dev, ramin, (hdr + 0x04)/4, chan->ramin_grctx->instance + -- pgraph->grctx_size - 1); -- nv_wo32(dev, ramin, (hdr + 0x08)/4, chan->ramin_grctx->instance); -- nv_wo32(dev, ramin, (hdr + 0x0c)/4, 0); -- nv_wo32(dev, ramin, (hdr + 0x10)/4, 0); -- nv_wo32(dev, ramin, (hdr + 0x14)/4, 0x00010000); -+ nv_wo32(ramin, hdr + 0x00, 0x00190002); -+ nv_wo32(ramin, hdr + 0x04, chan->ramin_grctx->vinst + -+ pgraph->grctx_size - 1); -+ nv_wo32(ramin, hdr + 0x08, chan->ramin_grctx->vinst); -+ nv_wo32(ramin, hdr + 0x0c, 0); -+ nv_wo32(ramin, hdr + 0x10, 0); -+ nv_wo32(ramin, hdr + 0x14, 0x00010000); - - ctx.dev = chan->dev; - ctx.mode = NOUVEAU_GRCTX_VALS; -- ctx.data = obj; -+ ctx.data = chan->ramin_grctx; - nv50_grctx_init(&ctx); - -- nv_wo32(dev, obj, 0x00000/4, chan->ramin->instance >> 12); -+ nv_wo32(chan->ramin_grctx, 0x00000, chan->ramin->vinst >> 12); - - dev_priv->engine.instmem.flush(dev); - return 0; -@@ -244,18 +249,29 @@ - { - struct drm_device *dev = chan->dev; - struct drm_nouveau_private *dev_priv = dev->dev_private; -+ struct nouveau_pgraph_engine *pgraph = &dev_priv->engine.graph; - int i, hdr = (dev_priv->chipset == 0x50) ? 0x200 : 0x20; -+ unsigned long flags; - - NV_DEBUG(dev, "ch%d\n", chan->id); - -- if (!chan->ramin || !chan->ramin->gpuobj) -+ if (!chan->ramin) - return; - -+ spin_lock_irqsave(&dev_priv->context_switch_lock, flags); -+ pgraph->fifo_access(dev, false); -+ -+ if (pgraph->channel(dev) == chan) -+ pgraph->unload_context(dev); -+ - for (i = hdr; i < hdr + 24; i += 4) -- nv_wo32(dev, chan->ramin->gpuobj, i/4, 0); -+ nv_wo32(chan->ramin, i, 0); - dev_priv->engine.instmem.flush(dev); - -- nouveau_gpuobj_ref_del(dev, &chan->ramin_grctx); -+ pgraph->fifo_access(dev, true); -+ spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags); -+ -+ nouveau_gpuobj_ref(NULL, &chan->ramin_grctx); - } - - static int -@@ -282,7 +298,7 @@ - int - nv50_graph_load_context(struct nouveau_channel *chan) - { -- uint32_t inst = chan->ramin->instance >> 12; -+ uint32_t inst = chan->ramin->vinst >> 12; - - NV_DEBUG(chan->dev, "ch%d\n", chan->id); - return nv50_graph_do_load_context(chan->dev, inst); -@@ -324,25 +340,26 @@ - } - - static int --nv50_graph_nvsw_dma_vblsem(struct nouveau_channel *chan, int grclass, -- int mthd, uint32_t data) -+nv50_graph_nvsw_dma_vblsem(struct nouveau_channel *chan, -+ u32 class, u32 mthd, u32 data) - { -- struct nouveau_gpuobj_ref *ref = NULL; -+ struct nouveau_gpuobj *gpuobj; - -- if (nouveau_gpuobj_ref_find(chan, data, &ref)) -+ gpuobj = nouveau_ramht_find(chan, data); -+ if (!gpuobj) - return -ENOENT; - -- if (nouveau_notifier_offset(ref->gpuobj, NULL)) -+ if (nouveau_notifier_offset(gpuobj, NULL)) - return -EINVAL; - -- chan->nvsw.vblsem = ref->gpuobj; -+ chan->nvsw.vblsem = gpuobj; - chan->nvsw.vblsem_offset = ~0; - return 0; - } - - static int --nv50_graph_nvsw_vblsem_offset(struct nouveau_channel *chan, int grclass, -- int mthd, uint32_t data) -+nv50_graph_nvsw_vblsem_offset(struct nouveau_channel *chan, -+ u32 class, u32 mthd, u32 data) - { - if (nouveau_notifier_offset(chan->nvsw.vblsem, &data)) - return -ERANGE; -@@ -352,16 +369,16 @@ - } - - static int --nv50_graph_nvsw_vblsem_release_val(struct nouveau_channel *chan, int grclass, -- int mthd, uint32_t data) -+nv50_graph_nvsw_vblsem_release_val(struct nouveau_channel *chan, -+ u32 class, u32 mthd, u32 data) - { - chan->nvsw.vblsem_rval = data; - return 0; - } - - static int --nv50_graph_nvsw_vblsem_release(struct nouveau_channel *chan, int grclass, -- int mthd, uint32_t data) -+nv50_graph_nvsw_vblsem_release(struct nouveau_channel *chan, -+ u32 class, u32 mthd, u32 data) - { - struct drm_device *dev = chan->dev; - struct drm_nouveau_private *dev_priv = dev->dev_private; -@@ -369,37 +386,129 @@ - if (!chan->nvsw.vblsem || chan->nvsw.vblsem_offset == ~0 || data > 1) - return -EINVAL; - -- if (!(nv_rd32(dev, NV50_PDISPLAY_INTR_EN) & -- NV50_PDISPLAY_INTR_EN_VBLANK_CRTC_(data))) { -- nv_wr32(dev, NV50_PDISPLAY_INTR_1, -- NV50_PDISPLAY_INTR_1_VBLANK_CRTC_(data)); -- nv_wr32(dev, NV50_PDISPLAY_INTR_EN, nv_rd32(dev, -- NV50_PDISPLAY_INTR_EN) | -- NV50_PDISPLAY_INTR_EN_VBLANK_CRTC_(data)); -- } -+ drm_vblank_get(dev, data); - -+ chan->nvsw.vblsem_head = data; - list_add(&chan->nvsw.vbl_wait, &dev_priv->vbl_waiting); -+ -+ return 0; -+} -+ -+static int -+nv50_graph_nvsw_mthd_page_flip(struct nouveau_channel *chan, -+ u32 class, u32 mthd, u32 data) -+{ -+ struct nouveau_page_flip_state s; -+ -+ if (!nouveau_finish_page_flip(chan, &s)) { -+ /* XXX - Do something here */ -+ } -+ - return 0; - } - --static struct nouveau_pgraph_object_method nv50_graph_nvsw_methods[] = { -- { 0x018c, nv50_graph_nvsw_dma_vblsem }, -- { 0x0400, nv50_graph_nvsw_vblsem_offset }, -- { 0x0404, nv50_graph_nvsw_vblsem_release_val }, -- { 0x0408, nv50_graph_nvsw_vblsem_release }, -- {} --}; -- --struct nouveau_pgraph_object_class nv50_graph_grclass[] = { -- { 0x506e, true, nv50_graph_nvsw_methods }, /* nvsw */ -- { 0x0030, false, NULL }, /* null */ -- { 0x5039, false, NULL }, /* m2mf */ -- { 0x502d, false, NULL }, /* 2d */ -- { 0x50c0, false, NULL }, /* compute */ -- { 0x85c0, false, NULL }, /* compute (nva3, nva5, nva8) */ -- { 0x5097, false, NULL }, /* tesla (nv50) */ -- { 0x8297, false, NULL }, /* tesla (nv8x/nv9x) */ -- { 0x8397, false, NULL }, /* tesla (nva0, nvaa, nvac) */ -- { 0x8597, false, NULL }, /* tesla (nva3, nva5, nva8) */ -- {} --}; -+static int -+nv50_graph_register(struct drm_device *dev) -+{ -+ struct drm_nouveau_private *dev_priv = dev->dev_private; -+ -+ if (dev_priv->engine.graph.registered) -+ return 0; -+ -+ NVOBJ_CLASS(dev, 0x506e, SW); /* nvsw */ -+ NVOBJ_MTHD (dev, 0x506e, 0x018c, nv50_graph_nvsw_dma_vblsem); -+ NVOBJ_MTHD (dev, 0x506e, 0x0400, nv50_graph_nvsw_vblsem_offset); -+ NVOBJ_MTHD (dev, 0x506e, 0x0404, nv50_graph_nvsw_vblsem_release_val); -+ NVOBJ_MTHD (dev, 0x506e, 0x0408, nv50_graph_nvsw_vblsem_release); -+ NVOBJ_MTHD (dev, 0x506e, 0x0500, nv50_graph_nvsw_mthd_page_flip); -+ -+ NVOBJ_CLASS(dev, 0x0030, GR); /* null */ -+ NVOBJ_CLASS(dev, 0x5039, GR); /* m2mf */ -+ NVOBJ_CLASS(dev, 0x502d, GR); /* 2d */ -+ -+ /* 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; -+ } -+ } -+ -+ /* compute */ -+ NVOBJ_CLASS(dev, 0x50c0, GR); -+ if (dev_priv->chipset > 0xa0 && -+ dev_priv->chipset != 0xaa && -+ dev_priv->chipset != 0xac) -+ NVOBJ_CLASS(dev, 0x85c0, GR); -+ -+ dev_priv->engine.graph.registered = true; -+ return 0; -+} -+ -+void -+nv50_graph_tlb_flush(struct drm_device *dev) -+{ -+ nv50_vm_flush(dev, 0); -+} -+ -+void -+nv86_graph_tlb_flush(struct drm_device *dev) -+{ -+ struct drm_nouveau_private *dev_priv = dev->dev_private; -+ struct nouveau_timer_engine *ptimer = &dev_priv->engine.timer; -+ 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); -+ -+ start = ptimer->read(dev); -+ do { -+ idle = true; -+ -+ for (tmp = nv_rd32(dev, 0x400380); tmp && idle; tmp >>= 3) { -+ if ((tmp & 7) == 1) -+ idle = false; -+ } -+ -+ for (tmp = nv_rd32(dev, 0x400384); tmp && idle; tmp >>= 3) { -+ if ((tmp & 7) == 1) -+ idle = false; -+ } -+ -+ for (tmp = nv_rd32(dev, 0x400388); tmp && idle; tmp >>= 3) { -+ if ((tmp & 7) == 1) -+ idle = false; -+ } -+ } while (!idle && !(timeout = ptimer->read(dev) - start > 2000000000)); -+ -+ if (timeout) { -+ NV_ERROR(dev, "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)); -+ } -+ -+ nv50_vm_flush(dev, 0); -+ -+ nv_mask(dev, 0x400500, 0x00000001, 0x00000001); -+ spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags); -+} -diff -Naur linux-2.6.36/drivers/gpu/drm/nouveau/nv50_grctx.c linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nv50_grctx.c ---- linux-2.6.36/drivers/gpu/drm/nouveau/nv50_grctx.c 2010-10-20 22:30:22.000000000 +0200 -+++ linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nv50_grctx.c 2010-11-05 00:40:00.000000000 +0100 -@@ -103,6 +103,9 @@ - #include "nouveau_drv.h" - #include "nouveau_grctx.h" - -+#define IS_NVA3F(x) (((x) > 0xa0 && (x) < 0xaa) || (x) == 0xaf) -+#define IS_NVAAF(x) ((x) >= 0xaa && (x) <= 0xac) -+ - /* - * This code deals with PGRAPH contexts on NV50 family cards. Like NV40, it's - * the GPU itself that does context-switching, but it needs a special -@@ -182,6 +185,7 @@ - case 0xa8: - case 0xaa: - case 0xac: -+ case 0xaf: - break; - default: - NV_ERROR(ctx->dev, "I don't know how to make a ctxprog for " -@@ -268,6 +272,9 @@ - */ - - static void -+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; -@@ -286,7 +293,7 @@ - gr_def(ctx, 0x400840, 0xffe806a8); - } - gr_def(ctx, 0x400844, 0x00000002); -- if (dev_priv->chipset > 0xa0 && dev_priv->chipset < 0xaa) -+ if (IS_NVA3F(dev_priv->chipset)) - gr_def(ctx, 0x400894, 0x00001000); - gr_def(ctx, 0x4008e8, 0x00000003); - gr_def(ctx, 0x4008ec, 0x00001000); -@@ -299,13 +306,15 @@ - - if (dev_priv->chipset >= 0xa0) - cp_ctx(ctx, 0x400b00, 0x1); -- if (dev_priv->chipset > 0xa0 && dev_priv->chipset < 0xaa) { -+ if (IS_NVA3F(dev_priv->chipset)) { - cp_ctx(ctx, 0x400b10, 0x1); - gr_def(ctx, 0x400b10, 0x0001629d); - cp_ctx(ctx, 0x400b20, 0x1); - gr_def(ctx, 0x400b20, 0x0001629d); - } - -+ nv50_graph_construct_mmio_ddata(ctx); -+ - /* 0C00: VFETCH */ - cp_ctx(ctx, 0x400c08, 0x2); - gr_def(ctx, 0x400c08, 0x0000fe0c); -@@ -314,7 +323,7 @@ - if (dev_priv->chipset < 0xa0) { - cp_ctx(ctx, 0x401008, 0x4); - gr_def(ctx, 0x401014, 0x00001000); -- } else if (dev_priv->chipset == 0xa0 || dev_priv->chipset >= 0xaa) { -+ } else if (!IS_NVA3F(dev_priv->chipset)) { - cp_ctx(ctx, 0x401008, 0x5); - gr_def(ctx, 0x401018, 0x00001000); - } else { -@@ -368,10 +377,13 @@ - case 0xa3: - case 0xa5: - case 0xa8: -+ case 0xaf: - gr_def(ctx, 0x401c00, 0x142500df); - break; - } - -+ /* 2000 */ -+ - /* 2400 */ - cp_ctx(ctx, 0x402400, 0x1); - if (dev_priv->chipset == 0x50) -@@ -380,12 +392,12 @@ - cp_ctx(ctx, 0x402408, 0x2); - gr_def(ctx, 0x402408, 0x00000600); - -- /* 2800 */ -+ /* 2800: CSCHED */ - cp_ctx(ctx, 0x402800, 0x1); - if (dev_priv->chipset == 0x50) - gr_def(ctx, 0x402800, 0x00000006); - -- /* 2C00 */ -+ /* 2C00: ZCULL */ - cp_ctx(ctx, 0x402c08, 0x6); - if (dev_priv->chipset != 0x50) - gr_def(ctx, 0x402c14, 0x01000000); -@@ -396,23 +408,23 @@ - cp_ctx(ctx, 0x402ca0, 0x2); - if (dev_priv->chipset < 0xa0) - gr_def(ctx, 0x402ca0, 0x00000400); -- else if (dev_priv->chipset == 0xa0 || dev_priv->chipset >= 0xaa) -+ else if (!IS_NVA3F(dev_priv->chipset)) - gr_def(ctx, 0x402ca0, 0x00000800); - else - gr_def(ctx, 0x402ca0, 0x00000400); - cp_ctx(ctx, 0x402cac, 0x4); - -- /* 3000 */ -+ /* 3000: ENG2D */ - cp_ctx(ctx, 0x403004, 0x1); - gr_def(ctx, 0x403004, 0x00000001); - -- /* 3404 */ -+ /* 3400 */ - if (dev_priv->chipset >= 0xa0) { - cp_ctx(ctx, 0x403404, 0x1); - gr_def(ctx, 0x403404, 0x00000001); - } - -- /* 5000 */ -+ /* 5000: CCACHE */ - cp_ctx(ctx, 0x405000, 0x1); - switch (dev_priv->chipset) { - case 0x50: -@@ -425,6 +437,7 @@ - case 0xa8: - case 0xaa: - case 0xac: -+ case 0xaf: - gr_def(ctx, 0x405000, 0x000e0080); - break; - case 0x86: -@@ -441,210 +454,6 @@ - cp_ctx(ctx, 0x405024, 0x1); - cp_ctx(ctx, 0x40502c, 0x1); - -- /* 5400 or maybe 4800 */ -- if (dev_priv->chipset == 0x50) { -- offset = 0x405400; -- cp_ctx(ctx, 0x405400, 0xea); -- } else if (dev_priv->chipset < 0x94) { -- offset = 0x405400; -- cp_ctx(ctx, 0x405400, 0xcb); -- } else if (dev_priv->chipset < 0xa0) { -- offset = 0x405400; -- cp_ctx(ctx, 0x405400, 0xcc); -- } else if (dev_priv->chipset > 0xa0 && dev_priv->chipset < 0xaa) { -- offset = 0x404800; -- cp_ctx(ctx, 0x404800, 0xda); -- } else { -- offset = 0x405400; -- cp_ctx(ctx, 0x405400, 0xd4); -- } -- gr_def(ctx, offset + 0x0c, 0x00000002); -- gr_def(ctx, offset + 0x10, 0x00000001); -- if (dev_priv->chipset >= 0x94) -- offset += 4; -- gr_def(ctx, offset + 0x1c, 0x00000001); -- gr_def(ctx, offset + 0x20, 0x00000100); -- gr_def(ctx, offset + 0x38, 0x00000002); -- gr_def(ctx, offset + 0x3c, 0x00000001); -- gr_def(ctx, offset + 0x40, 0x00000001); -- gr_def(ctx, offset + 0x50, 0x00000001); -- gr_def(ctx, offset + 0x54, 0x003fffff); -- gr_def(ctx, offset + 0x58, 0x00001fff); -- gr_def(ctx, offset + 0x60, 0x00000001); -- gr_def(ctx, offset + 0x64, 0x00000001); -- gr_def(ctx, offset + 0x6c, 0x00000001); -- gr_def(ctx, offset + 0x70, 0x00000001); -- gr_def(ctx, offset + 0x74, 0x00000001); -- gr_def(ctx, offset + 0x78, 0x00000004); -- gr_def(ctx, offset + 0x7c, 0x00000001); -- if (dev_priv->chipset > 0xa0 && dev_priv->chipset < 0xaa) -- offset += 4; -- gr_def(ctx, offset + 0x80, 0x00000001); -- gr_def(ctx, offset + 0x84, 0x00000001); -- gr_def(ctx, offset + 0x88, 0x00000007); -- gr_def(ctx, offset + 0x8c, 0x00000001); -- gr_def(ctx, offset + 0x90, 0x00000007); -- gr_def(ctx, offset + 0x94, 0x00000001); -- gr_def(ctx, offset + 0x98, 0x00000001); -- gr_def(ctx, offset + 0x9c, 0x00000001); -- if (dev_priv->chipset == 0x50) { -- gr_def(ctx, offset + 0xb0, 0x00000001); -- gr_def(ctx, offset + 0xb4, 0x00000001); -- gr_def(ctx, offset + 0xbc, 0x00000001); -- gr_def(ctx, offset + 0xc0, 0x0000000a); -- gr_def(ctx, offset + 0xd0, 0x00000040); -- gr_def(ctx, offset + 0xd8, 0x00000002); -- gr_def(ctx, offset + 0xdc, 0x00000100); -- gr_def(ctx, offset + 0xe0, 0x00000001); -- gr_def(ctx, offset + 0xe4, 0x00000100); -- gr_def(ctx, offset + 0x100, 0x00000001); -- gr_def(ctx, offset + 0x124, 0x00000004); -- gr_def(ctx, offset + 0x13c, 0x00000001); -- gr_def(ctx, offset + 0x140, 0x00000100); -- gr_def(ctx, offset + 0x148, 0x00000001); -- gr_def(ctx, offset + 0x154, 0x00000100); -- gr_def(ctx, offset + 0x158, 0x00000001); -- gr_def(ctx, offset + 0x15c, 0x00000100); -- gr_def(ctx, offset + 0x164, 0x00000001); -- gr_def(ctx, offset + 0x170, 0x00000100); -- gr_def(ctx, offset + 0x174, 0x00000001); -- gr_def(ctx, offset + 0x17c, 0x00000001); -- gr_def(ctx, offset + 0x188, 0x00000002); -- gr_def(ctx, offset + 0x190, 0x00000001); -- gr_def(ctx, offset + 0x198, 0x00000001); -- gr_def(ctx, offset + 0x1ac, 0x00000003); -- offset += 0xd0; -- } else { -- gr_def(ctx, offset + 0xb0, 0x00000001); -- gr_def(ctx, offset + 0xb4, 0x00000100); -- gr_def(ctx, offset + 0xbc, 0x00000001); -- gr_def(ctx, offset + 0xc8, 0x00000100); -- gr_def(ctx, offset + 0xcc, 0x00000001); -- gr_def(ctx, offset + 0xd0, 0x00000100); -- gr_def(ctx, offset + 0xd8, 0x00000001); -- gr_def(ctx, offset + 0xe4, 0x00000100); -- } -- gr_def(ctx, offset + 0xf8, 0x00000004); -- gr_def(ctx, offset + 0xfc, 0x00000070); -- gr_def(ctx, offset + 0x100, 0x00000080); -- if (dev_priv->chipset > 0xa0 && dev_priv->chipset < 0xaa) -- offset += 4; -- gr_def(ctx, offset + 0x114, 0x0000000c); -- if (dev_priv->chipset == 0x50) -- offset -= 4; -- gr_def(ctx, offset + 0x11c, 0x00000008); -- gr_def(ctx, offset + 0x120, 0x00000014); -- if (dev_priv->chipset == 0x50) { -- gr_def(ctx, offset + 0x124, 0x00000026); -- offset -= 0x18; -- } else { -- gr_def(ctx, offset + 0x128, 0x00000029); -- gr_def(ctx, offset + 0x12c, 0x00000027); -- gr_def(ctx, offset + 0x130, 0x00000026); -- gr_def(ctx, offset + 0x134, 0x00000008); -- gr_def(ctx, offset + 0x138, 0x00000004); -- gr_def(ctx, offset + 0x13c, 0x00000027); -- } -- gr_def(ctx, offset + 0x148, 0x00000001); -- gr_def(ctx, offset + 0x14c, 0x00000002); -- gr_def(ctx, offset + 0x150, 0x00000003); -- gr_def(ctx, offset + 0x154, 0x00000004); -- gr_def(ctx, offset + 0x158, 0x00000005); -- gr_def(ctx, offset + 0x15c, 0x00000006); -- gr_def(ctx, offset + 0x160, 0x00000007); -- gr_def(ctx, offset + 0x164, 0x00000001); -- gr_def(ctx, offset + 0x1a8, 0x000000cf); -- if (dev_priv->chipset == 0x50) -- offset -= 4; -- gr_def(ctx, offset + 0x1d8, 0x00000080); -- gr_def(ctx, offset + 0x1dc, 0x00000004); -- gr_def(ctx, offset + 0x1e0, 0x00000004); -- if (dev_priv->chipset == 0x50) -- offset -= 4; -- else -- gr_def(ctx, offset + 0x1e4, 0x00000003); -- if (dev_priv->chipset > 0xa0 && dev_priv->chipset < 0xaa) { -- gr_def(ctx, offset + 0x1ec, 0x00000003); -- offset += 8; -- } -- gr_def(ctx, offset + 0x1e8, 0x00000001); -- if (dev_priv->chipset == 0x50) -- offset -= 4; -- gr_def(ctx, offset + 0x1f4, 0x00000012); -- gr_def(ctx, offset + 0x1f8, 0x00000010); -- gr_def(ctx, offset + 0x1fc, 0x0000000c); -- gr_def(ctx, offset + 0x200, 0x00000001); -- gr_def(ctx, offset + 0x210, 0x00000004); -- gr_def(ctx, offset + 0x214, 0x00000002); -- gr_def(ctx, offset + 0x218, 0x00000004); -- if (dev_priv->chipset >= 0xa0) -- offset += 4; -- gr_def(ctx, offset + 0x224, 0x003fffff); -- gr_def(ctx, offset + 0x228, 0x00001fff); -- if (dev_priv->chipset == 0x50) -- offset -= 0x20; -- else if (dev_priv->chipset >= 0xa0) { -- gr_def(ctx, offset + 0x250, 0x00000001); -- gr_def(ctx, offset + 0x254, 0x00000001); -- gr_def(ctx, offset + 0x258, 0x00000002); -- offset += 0x10; -- } -- gr_def(ctx, offset + 0x250, 0x00000004); -- gr_def(ctx, offset + 0x254, 0x00000014); -- gr_def(ctx, offset + 0x258, 0x00000001); -- if (dev_priv->chipset > 0xa0 && dev_priv->chipset < 0xaa) -- offset += 4; -- gr_def(ctx, offset + 0x264, 0x00000002); -- if (dev_priv->chipset >= 0xa0) -- offset += 8; -- gr_def(ctx, offset + 0x270, 0x00000001); -- gr_def(ctx, offset + 0x278, 0x00000002); -- gr_def(ctx, offset + 0x27c, 0x00001000); -- if (dev_priv->chipset == 0x50) -- offset -= 0xc; -- else { -- gr_def(ctx, offset + 0x280, 0x00000e00); -- gr_def(ctx, offset + 0x284, 0x00001000); -- gr_def(ctx, offset + 0x288, 0x00001e00); -- } -- gr_def(ctx, offset + 0x290, 0x00000001); -- gr_def(ctx, offset + 0x294, 0x00000001); -- gr_def(ctx, offset + 0x298, 0x00000001); -- gr_def(ctx, offset + 0x29c, 0x00000001); -- gr_def(ctx, offset + 0x2a0, 0x00000001); -- gr_def(ctx, offset + 0x2b0, 0x00000200); -- if (dev_priv->chipset > 0xa0 && dev_priv->chipset < 0xaa) { -- gr_def(ctx, offset + 0x2b4, 0x00000200); -- offset += 4; -- } -- if (dev_priv->chipset < 0xa0) { -- gr_def(ctx, offset + 0x2b8, 0x00000001); -- gr_def(ctx, offset + 0x2bc, 0x00000070); -- gr_def(ctx, offset + 0x2c0, 0x00000080); -- gr_def(ctx, offset + 0x2cc, 0x00000001); -- gr_def(ctx, offset + 0x2d0, 0x00000070); -- gr_def(ctx, offset + 0x2d4, 0x00000080); -- } else { -- gr_def(ctx, offset + 0x2b8, 0x00000001); -- gr_def(ctx, offset + 0x2bc, 0x000000f0); -- gr_def(ctx, offset + 0x2c0, 0x000000ff); -- gr_def(ctx, offset + 0x2cc, 0x00000001); -- gr_def(ctx, offset + 0x2d0, 0x000000f0); -- gr_def(ctx, offset + 0x2d4, 0x000000ff); -- gr_def(ctx, offset + 0x2dc, 0x00000009); -- offset += 4; -- } -- gr_def(ctx, offset + 0x2e4, 0x00000001); -- gr_def(ctx, offset + 0x2e8, 0x000000cf); -- gr_def(ctx, offset + 0x2f0, 0x00000001); -- gr_def(ctx, offset + 0x300, 0x000000cf); -- gr_def(ctx, offset + 0x308, 0x00000002); -- gr_def(ctx, offset + 0x310, 0x00000001); -- gr_def(ctx, offset + 0x318, 0x00000001); -- gr_def(ctx, offset + 0x320, 0x000000cf); -- gr_def(ctx, offset + 0x324, 0x000000cf); -- gr_def(ctx, offset + 0x328, 0x00000001); -- - /* 6000? */ - if (dev_priv->chipset == 0x50) - cp_ctx(ctx, 0x4063e0, 0x1); -@@ -661,7 +470,7 @@ - gr_def(ctx, 0x406818, 0x00000f80); - else - gr_def(ctx, 0x406818, 0x00001f80); -- if (dev_priv->chipset > 0xa0 && dev_priv->chipset < 0xaa) -+ if (IS_NVA3F(dev_priv->chipset)) - gr_def(ctx, 0x40681c, 0x00000030); - cp_ctx(ctx, 0x406830, 0x3); - } -@@ -706,7 +515,7 @@ - - if (dev_priv->chipset < 0xa0) - cp_ctx(ctx, 0x407094 + (i<<8), 1); -- else if (dev_priv->chipset <= 0xa0 || dev_priv->chipset >= 0xaa) -+ else if (!IS_NVA3F(dev_priv->chipset)) - cp_ctx(ctx, 0x407094 + (i<<8), 3); - else { - cp_ctx(ctx, 0x407094 + (i<<8), 4); -@@ -799,6 +608,7 @@ - case 0xa8: - case 0xaa: - case 0xac: -+ case 0xaf: - gr_def(ctx, offset + 0x1c, 0x300c0000); - break; - } -@@ -825,7 +635,7 @@ - gr_def(ctx, base + 0x304, 0x00007070); - else if (dev_priv->chipset < 0xa0) - gr_def(ctx, base + 0x304, 0x00027070); -- else if (dev_priv->chipset <= 0xa0 || dev_priv->chipset >= 0xaa) -+ else if (!IS_NVA3F(dev_priv->chipset)) - gr_def(ctx, base + 0x304, 0x01127070); - else - gr_def(ctx, base + 0x304, 0x05127070); -@@ -849,7 +659,7 @@ - if (dev_priv->chipset < 0xa0) { - cp_ctx(ctx, base + 0x340, 9); - offset = base + 0x340; -- } else if (dev_priv->chipset <= 0xa0 || dev_priv->chipset >= 0xaa) { -+ } else if (!IS_NVA3F(dev_priv->chipset)) { - cp_ctx(ctx, base + 0x33c, 0xb); - offset = base + 0x344; - } else { -@@ -880,7 +690,7 @@ - gr_def(ctx, offset + 0x0, 0x000001f0); - gr_def(ctx, offset + 0x4, 0x00000001); - gr_def(ctx, offset + 0x8, 0x00000003); -- if (dev_priv->chipset == 0x50 || dev_priv->chipset >= 0xaa) -+ if (dev_priv->chipset == 0x50 || IS_NVAAF(dev_priv->chipset)) - gr_def(ctx, offset + 0xc, 0x00008000); - gr_def(ctx, offset + 0x14, 0x00039e00); - cp_ctx(ctx, offset + 0x1c, 2); -@@ -892,7 +702,7 @@ - - if (dev_priv->chipset >= 0xa0) { - cp_ctx(ctx, base + 0x54c, 2); -- if (dev_priv->chipset <= 0xa0 || dev_priv->chipset >= 0xaa) -+ if (!IS_NVA3F(dev_priv->chipset)) - gr_def(ctx, base + 0x54c, 0x003fe006); - else - gr_def(ctx, base + 0x54c, 0x003fe007); -@@ -948,6 +758,336 @@ - } - } - -+static void -+dd_emit(struct nouveau_grctx *ctx, int num, uint32_t val) { -+ int i; -+ if (val && ctx->mode == NOUVEAU_GRCTX_VALS) -+ for (i = 0; i < num; i++) -+ nv_wo32(ctx->data, 4 * (ctx->ctxvals_pos + i), val); -+ ctx->ctxvals_pos += num; -+} -+ -+static void -+nv50_graph_construct_mmio_ddata(struct nouveau_grctx *ctx) -+{ -+ struct drm_nouveau_private *dev_priv = ctx->dev->dev_private; -+ int base, num; -+ base = ctx->ctxvals_pos; -+ -+ /* tesla state */ -+ dd_emit(ctx, 1, 0); /* 00000001 UNK0F90 */ -+ dd_emit(ctx, 1, 0); /* 00000001 UNK135C */ -+ -+ /* SRC_TIC state */ -+ dd_emit(ctx, 1, 0); /* 00000007 SRC_TILE_MODE_Z */ -+ dd_emit(ctx, 1, 2); /* 00000007 SRC_TILE_MODE_Y */ -+ 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) -+ dd_emit(ctx, 1, 0); /* 00000003 eng2d UNK0258 */ -+ dd_emit(ctx, 1, 1); /* 00000fff SRC_DEPTH */ -+ dd_emit(ctx, 1, 0x100); /* 0000ffff SRC_HEIGHT */ -+ -+ /* turing state */ -+ dd_emit(ctx, 1, 0); /* 0000000f TEXTURES_LOG2 */ -+ dd_emit(ctx, 1, 0); /* 0000000f SAMPLERS_LOG2 */ -+ dd_emit(ctx, 1, 0); /* 000000ff CB_DEF_ADDRESS_HIGH */ -+ dd_emit(ctx, 1, 0); /* ffffffff CB_DEF_ADDRESS_LOW */ -+ dd_emit(ctx, 1, 0); /* ffffffff SHARED_SIZE */ -+ dd_emit(ctx, 1, 2); /* ffffffff REG_MODE */ -+ dd_emit(ctx, 1, 1); /* 0000ffff BLOCK_ALLOC_THREADS */ -+ dd_emit(ctx, 1, 1); /* 00000001 LANES32 */ -+ dd_emit(ctx, 1, 0); /* 000000ff UNK370 */ -+ dd_emit(ctx, 1, 0); /* 000000ff USER_PARAM_UNK */ -+ dd_emit(ctx, 1, 0); /* 000000ff USER_PARAM_COUNT */ -+ dd_emit(ctx, 1, 1); /* 000000ff UNK384 bits 8-15 */ -+ dd_emit(ctx, 1, 0x3fffff); /* 003fffff TIC_LIMIT */ -+ dd_emit(ctx, 1, 0x1fff); /* 000fffff TSC_LIMIT */ -+ dd_emit(ctx, 1, 0); /* 0000ffff CB_ADDR_INDEX */ -+ dd_emit(ctx, 1, 1); /* 000007ff BLOCKDIM_X */ -+ dd_emit(ctx, 1, 1); /* 000007ff BLOCKDIM_XMY */ -+ dd_emit(ctx, 1, 0); /* 00000001 BLOCKDIM_XMY_OVERFLOW */ -+ dd_emit(ctx, 1, 1); /* 0003ffff BLOCKDIM_XMYMZ */ -+ dd_emit(ctx, 1, 1); /* 000007ff BLOCKDIM_Y */ -+ 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)) -+ 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 */ -+ dd_emit(ctx, 1, 7); /* 00000007 LOCAL_WARPS_LOG_ALLOC */ -+ dd_emit(ctx, 1, 1); /* 00000007 STACK_WARPS_NO_CLAMP */ -+ dd_emit(ctx, 1, 7); /* 00000007 STACK_WARPS_LOG_ALLOC */ -+ dd_emit(ctx, 1, 1); /* 00001fff BLOCK_ALLOC_REGSLOTS_PACKED */ -+ dd_emit(ctx, 1, 1); /* 00001fff BLOCK_ALLOC_REGSLOTS_STRIDED */ -+ dd_emit(ctx, 1, 1); /* 000007ff BLOCK_ALLOC_THREADS */ -+ -+ /* compat 2d state */ -+ if (dev_priv->chipset == 0x50) { -+ dd_emit(ctx, 4, 0); /* 0000ffff clip X, Y, W, H */ -+ -+ dd_emit(ctx, 1, 1); /* ffffffff chroma COLOR_FORMAT */ -+ -+ dd_emit(ctx, 1, 1); /* ffffffff pattern COLOR_FORMAT */ -+ dd_emit(ctx, 1, 0); /* ffffffff pattern SHAPE */ -+ dd_emit(ctx, 1, 1); /* ffffffff pattern PATTERN_SELECT */ -+ -+ dd_emit(ctx, 1, 0xa); /* ffffffff surf2d SRC_FORMAT */ -+ dd_emit(ctx, 1, 0); /* ffffffff surf2d DMA_SRC */ -+ dd_emit(ctx, 1, 0); /* 000000ff surf2d SRC_ADDRESS_HIGH */ -+ dd_emit(ctx, 1, 0); /* ffffffff surf2d SRC_ADDRESS_LOW */ -+ dd_emit(ctx, 1, 0x40); /* 0000ffff surf2d SRC_PITCH */ -+ dd_emit(ctx, 1, 0); /* 0000000f surf2d SRC_TILE_MODE_Z */ -+ dd_emit(ctx, 1, 2); /* 0000000f surf2d SRC_TILE_MODE_Y */ -+ dd_emit(ctx, 1, 0x100); /* ffffffff surf2d SRC_HEIGHT */ -+ dd_emit(ctx, 1, 1); /* 00000001 surf2d SRC_LINEAR */ -+ dd_emit(ctx, 1, 0x100); /* ffffffff surf2d SRC_WIDTH */ -+ -+ dd_emit(ctx, 1, 0); /* 0000ffff gdirect CLIP_B_X */ -+ dd_emit(ctx, 1, 0); /* 0000ffff gdirect CLIP_B_Y */ -+ dd_emit(ctx, 1, 0); /* 0000ffff gdirect CLIP_C_X */ -+ dd_emit(ctx, 1, 0); /* 0000ffff gdirect CLIP_C_Y */ -+ dd_emit(ctx, 1, 0); /* 0000ffff gdirect CLIP_D_X */ -+ dd_emit(ctx, 1, 0); /* 0000ffff gdirect CLIP_D_Y */ -+ dd_emit(ctx, 1, 1); /* ffffffff gdirect COLOR_FORMAT */ -+ dd_emit(ctx, 1, 0); /* ffffffff gdirect OPERATION */ -+ dd_emit(ctx, 1, 0); /* 0000ffff gdirect POINT_X */ -+ dd_emit(ctx, 1, 0); /* 0000ffff gdirect POINT_Y */ -+ -+ dd_emit(ctx, 1, 0); /* 0000ffff blit SRC_Y */ -+ dd_emit(ctx, 1, 0); /* ffffffff blit OPERATION */ -+ -+ dd_emit(ctx, 1, 0); /* ffffffff ifc OPERATION */ -+ -+ dd_emit(ctx, 1, 0); /* ffffffff iifc INDEX_FORMAT */ -+ dd_emit(ctx, 1, 0); /* ffffffff iifc LUT_OFFSET */ -+ dd_emit(ctx, 1, 4); /* ffffffff iifc COLOR_FORMAT */ -+ dd_emit(ctx, 1, 0); /* ffffffff iifc OPERATION */ -+ } -+ -+ /* m2mf state */ -+ dd_emit(ctx, 1, 0); /* ffffffff m2mf LINE_COUNT */ -+ dd_emit(ctx, 1, 0); /* ffffffff m2mf LINE_LENGTH_IN */ -+ dd_emit(ctx, 2, 0); /* ffffffff m2mf OFFSET_IN, OFFSET_OUT */ -+ dd_emit(ctx, 1, 1); /* ffffffff m2mf TILING_DEPTH_OUT */ -+ dd_emit(ctx, 1, 0x100); /* ffffffff m2mf TILING_HEIGHT_OUT */ -+ dd_emit(ctx, 1, 0); /* ffffffff m2mf TILING_POSITION_OUT_Z */ -+ dd_emit(ctx, 1, 1); /* 00000001 m2mf LINEAR_OUT */ -+ dd_emit(ctx, 2, 0); /* 0000ffff m2mf TILING_POSITION_OUT_X, Y */ -+ dd_emit(ctx, 1, 0x100); /* ffffffff m2mf TILING_PITCH_OUT */ -+ dd_emit(ctx, 1, 1); /* ffffffff m2mf TILING_DEPTH_IN */ -+ dd_emit(ctx, 1, 0x100); /* ffffffff m2mf TILING_HEIGHT_IN */ -+ dd_emit(ctx, 1, 0); /* ffffffff m2mf TILING_POSITION_IN_Z */ -+ dd_emit(ctx, 1, 1); /* 00000001 m2mf LINEAR_IN */ -+ dd_emit(ctx, 2, 0); /* 0000ffff m2mf TILING_POSITION_IN_X, Y */ -+ dd_emit(ctx, 1, 0x100); /* ffffffff m2mf TILING_PITCH_IN */ -+ -+ /* more compat 2d state */ -+ if (dev_priv->chipset == 0x50) { -+ dd_emit(ctx, 1, 1); /* ffffffff line COLOR_FORMAT */ -+ dd_emit(ctx, 1, 0); /* ffffffff line OPERATION */ -+ -+ dd_emit(ctx, 1, 1); /* ffffffff triangle COLOR_FORMAT */ -+ dd_emit(ctx, 1, 0); /* ffffffff triangle OPERATION */ -+ -+ dd_emit(ctx, 1, 0); /* 0000000f sifm TILE_MODE_Z */ -+ dd_emit(ctx, 1, 2); /* 0000000f sifm TILE_MODE_Y */ -+ dd_emit(ctx, 1, 0); /* 000000ff sifm FORMAT_FILTER */ -+ dd_emit(ctx, 1, 1); /* 000000ff sifm FORMAT_ORIGIN */ -+ dd_emit(ctx, 1, 0); /* 0000ffff sifm SRC_PITCH */ -+ dd_emit(ctx, 1, 1); /* 00000001 sifm SRC_LINEAR */ -+ dd_emit(ctx, 1, 0); /* 000000ff sifm SRC_OFFSET_HIGH */ -+ dd_emit(ctx, 1, 0); /* ffffffff sifm SRC_OFFSET */ -+ dd_emit(ctx, 1, 0); /* 0000ffff sifm SRC_HEIGHT */ -+ dd_emit(ctx, 1, 0); /* 0000ffff sifm SRC_WIDTH */ -+ dd_emit(ctx, 1, 3); /* ffffffff sifm COLOR_FORMAT */ -+ dd_emit(ctx, 1, 0); /* ffffffff sifm OPERATION */ -+ -+ dd_emit(ctx, 1, 0); /* ffffffff sifc OPERATION */ -+ } -+ -+ /* tesla state */ -+ dd_emit(ctx, 1, 0); /* 0000000f GP_TEXTURES_LOG2 */ -+ dd_emit(ctx, 1, 0); /* 0000000f GP_SAMPLERS_LOG2 */ -+ dd_emit(ctx, 1, 0); /* 000000ff */ -+ dd_emit(ctx, 1, 0); /* ffffffff */ -+ dd_emit(ctx, 1, 4); /* 000000ff UNK12B0_0 */ -+ dd_emit(ctx, 1, 0x70); /* 000000ff UNK12B0_1 */ -+ dd_emit(ctx, 1, 0x80); /* 000000ff UNK12B0_3 */ -+ 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)) { -+ 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) -+ 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) { -+ dd_emit(ctx, 1, 0); /* 000000ff SEMANTIC_LAYER */ -+ dd_emit(ctx, 1, 0); /* 00000001 */ -+ } else { -+ dd_emit(ctx, 1, 0); /* 00000001 SEMANTIC_PTSZ.ENABLE */ -+ dd_emit(ctx, 1, 0x29); /* 000000ff SEMANTIC_PTSZ.PTSZ_ID */ -+ dd_emit(ctx, 1, 0x27); /* 000000ff SEMANTIC_PRIM */ -+ dd_emit(ctx, 1, 0x26); /* 000000ff SEMANTIC_LAYER */ -+ dd_emit(ctx, 1, 8); /* 0000000f SMENATIC_CLIP.CLIP_HIGH */ -+ dd_emit(ctx, 1, 4); /* 000000ff SEMANTIC_CLIP.CLIP_LO */ -+ dd_emit(ctx, 1, 0x27); /* 000000ff UNK0FD4 */ -+ dd_emit(ctx, 1, 0); /* 00000001 UNK1900 */ -+ } -+ dd_emit(ctx, 1, 0); /* 00000007 RT_CONTROL_MAP0 */ -+ dd_emit(ctx, 1, 1); /* 00000007 RT_CONTROL_MAP1 */ -+ dd_emit(ctx, 1, 2); /* 00000007 RT_CONTROL_MAP2 */ -+ dd_emit(ctx, 1, 3); /* 00000007 RT_CONTROL_MAP3 */ -+ dd_emit(ctx, 1, 4); /* 00000007 RT_CONTROL_MAP4 */ -+ dd_emit(ctx, 1, 5); /* 00000007 RT_CONTROL_MAP5 */ -+ dd_emit(ctx, 1, 6); /* 00000007 RT_CONTROL_MAP6 */ -+ dd_emit(ctx, 1, 7); /* 00000007 RT_CONTROL_MAP7 */ -+ dd_emit(ctx, 1, 1); /* 0000000f RT_CONTROL_COUNT */ -+ dd_emit(ctx, 8, 0); /* 00000001 RT_HORIZ_UNK */ -+ 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) -+ dd_emit(ctx, 3, 0); /* 1, 1, 1 */ -+ else -+ dd_emit(ctx, 2, 0); /* 1, 1 */ -+ dd_emit(ctx, 1, 0); /* ffffffff GP_ENABLE */ -+ 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)) { -+ dd_emit(ctx, 1, 3); /* 00000003 */ -+ dd_emit(ctx, 1, 0); /* 00000001 UNK1418. Alone. */ -+ } -+ if (dev_priv->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) -+ 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 */ -+ dd_emit(ctx, 1, 0xc); /* 000000ff FP_INTERPOLANT_CTRL.OFFSET */ -+ dd_emit(ctx, 1, 1); /* 00000001 FP_INTERPOLANT_CTRL.UMASK.W */ -+ dd_emit(ctx, 1, 0); /* 00000001 FP_INTERPOLANT_CTRL.UMASK.X */ -+ dd_emit(ctx, 1, 0); /* 00000001 FP_INTERPOLANT_CTRL.UMASK.Y */ -+ dd_emit(ctx, 1, 0); /* 00000001 FP_INTERPOLANT_CTRL.UMASK.Z */ -+ 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) -+ 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) -+ dd_emit(ctx, 8, 0); /* 00000001 */ -+ if (dev_priv->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 */ -+ dd_emit(ctx, 1, 0); /* 000000ff VTX_ATTR_DEFINE.ATTR */ -+ } -+ dd_emit(ctx, 1, 4); /* 0000007f VP_RESULT_MAP_SIZE */ -+ dd_emit(ctx, 1, 0x14); /* 0000001f ZETA_FORMAT */ -+ 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)) -+ dd_emit(ctx, 1, 0); /* 00000001 */ -+ dd_emit(ctx, 1, 2); /* 00000003 POLYGON_MODE_BACK */ -+ if (dev_priv->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) -+ 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) { -+ dd_emit(ctx, 1, 0xe00); /* 7fff */ -+ dd_emit(ctx, 1, 0x1000); /* 7fff */ -+ dd_emit(ctx, 1, 0x1e00); /* 7fff */ -+ } -+ dd_emit(ctx, 1, 0); /* 00000001 BEGIN_END_ACTIVE */ -+ dd_emit(ctx, 1, 1); /* 00000001 POLYGON_MODE_??? */ -+ dd_emit(ctx, 1, 1); /* 000000ff GP_REG_ALLOC_TEMP / 4 rounded up */ -+ dd_emit(ctx, 1, 1); /* 000000ff FP_REG_ALLOC_TEMP... without /4? */ -+ dd_emit(ctx, 1, 1); /* 000000ff VP_REG_ALLOC_TEMP / 4 rounded up */ -+ dd_emit(ctx, 1, 1); /* 00000001 */ -+ dd_emit(ctx, 1, 0); /* 00000001 */ -+ 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)) -+ dd_emit(ctx, 1, 0x200); -+ dd_emit(ctx, 1, 0); /* 00000001 */ -+ if (dev_priv->chipset < 0xa0) { -+ dd_emit(ctx, 1, 1); /* 00000001 */ -+ dd_emit(ctx, 1, 0x70); /* 000000ff */ -+ dd_emit(ctx, 1, 0x80); /* 000000ff */ -+ dd_emit(ctx, 1, 0); /* 000000ff */ -+ dd_emit(ctx, 1, 0); /* 00000001 */ -+ dd_emit(ctx, 1, 1); /* 00000001 */ -+ dd_emit(ctx, 1, 0x70); /* 000000ff */ -+ dd_emit(ctx, 1, 0x80); /* 000000ff */ -+ dd_emit(ctx, 1, 0); /* 000000ff */ -+ } else { -+ dd_emit(ctx, 1, 1); /* 00000001 */ -+ dd_emit(ctx, 1, 0xf0); /* 000000ff */ -+ dd_emit(ctx, 1, 0xff); /* 000000ff */ -+ dd_emit(ctx, 1, 0); /* 000000ff */ -+ dd_emit(ctx, 1, 0); /* 00000001 */ -+ dd_emit(ctx, 1, 1); /* 00000001 */ -+ dd_emit(ctx, 1, 0xf0); /* 000000ff */ -+ dd_emit(ctx, 1, 0xff); /* 000000ff */ -+ dd_emit(ctx, 1, 0); /* 000000ff */ -+ dd_emit(ctx, 1, 9); /* 0000003f UNK114C.COMP,SIZE */ -+ } -+ -+ /* eng2d state */ -+ dd_emit(ctx, 1, 0); /* 00000001 eng2d COLOR_KEY_ENABLE */ -+ dd_emit(ctx, 1, 0); /* 00000007 eng2d COLOR_KEY_FORMAT */ -+ dd_emit(ctx, 1, 1); /* ffffffff eng2d DST_DEPTH */ -+ dd_emit(ctx, 1, 0xcf); /* 000000ff eng2d DST_FORMAT */ -+ dd_emit(ctx, 1, 0); /* ffffffff eng2d DST_LAYER */ -+ dd_emit(ctx, 1, 1); /* 00000001 eng2d DST_LINEAR */ -+ dd_emit(ctx, 1, 0); /* 00000007 eng2d PATTERN_COLOR_FORMAT */ -+ dd_emit(ctx, 1, 0); /* 00000007 eng2d OPERATION */ -+ dd_emit(ctx, 1, 0); /* 00000003 eng2d PATTERN_SELECT */ -+ dd_emit(ctx, 1, 0xcf); /* 000000ff eng2d SIFC_FORMAT */ -+ dd_emit(ctx, 1, 0); /* 00000001 eng2d SIFC_BITMAP_ENABLE */ -+ dd_emit(ctx, 1, 2); /* 00000003 eng2d SIFC_BITMAP_UNK808 */ -+ dd_emit(ctx, 1, 0); /* ffffffff eng2d BLIT_DU_DX_FRACT */ -+ dd_emit(ctx, 1, 1); /* ffffffff eng2d BLIT_DU_DX_INT */ -+ dd_emit(ctx, 1, 0); /* ffffffff eng2d BLIT_DV_DY_FRACT */ -+ dd_emit(ctx, 1, 1); /* ffffffff eng2d BLIT_DV_DY_INT */ -+ dd_emit(ctx, 1, 0); /* 00000001 eng2d BLIT_CONTROL_FILTER */ -+ dd_emit(ctx, 1, 0xcf); /* 000000ff eng2d DRAW_COLOR_FORMAT */ -+ dd_emit(ctx, 1, 0xcf); /* 000000ff eng2d SRC_FORMAT */ -+ dd_emit(ctx, 1, 1); /* 00000001 eng2d SRC_LINEAR #2 */ -+ -+ num = ctx->ctxvals_pos - base; -+ ctx->ctxvals_pos = base; -+ if (IS_NVA3F(dev_priv->chipset)) -+ cp_ctx(ctx, 0x404800, num); -+ else -+ cp_ctx(ctx, 0x405400, num); -+} -+ - /* - * xfer areas. These are a pain. - * -@@ -990,28 +1130,33 @@ - * without the help of ctxprog. - */ - --static inline void -+static void - xf_emit(struct nouveau_grctx *ctx, int num, uint32_t val) { - int i; - if (val && ctx->mode == NOUVEAU_GRCTX_VALS) - for (i = 0; i < num; i++) -- nv_wo32(ctx->dev, ctx->data, ctx->ctxvals_pos + (i << 3), val); -+ nv_wo32(ctx->data, 4 * (ctx->ctxvals_pos + (i << 3)), val); - ctx->ctxvals_pos += num << 3; - } - - /* Gene declarations... */ - -+static void nv50_graph_construct_gene_dispatch(struct nouveau_grctx *ctx); - static void nv50_graph_construct_gene_m2mf(struct nouveau_grctx *ctx); --static void nv50_graph_construct_gene_unk1(struct nouveau_grctx *ctx); --static void nv50_graph_construct_gene_unk2(struct nouveau_grctx *ctx); --static void nv50_graph_construct_gene_unk3(struct nouveau_grctx *ctx); --static void nv50_graph_construct_gene_unk4(struct nouveau_grctx *ctx); --static void nv50_graph_construct_gene_unk5(struct nouveau_grctx *ctx); --static void nv50_graph_construct_gene_unk6(struct nouveau_grctx *ctx); --static void nv50_graph_construct_gene_unk7(struct nouveau_grctx *ctx); --static void nv50_graph_construct_gene_unk8(struct nouveau_grctx *ctx); --static void nv50_graph_construct_gene_unk9(struct nouveau_grctx *ctx); --static void nv50_graph_construct_gene_unk10(struct nouveau_grctx *ctx); -+static void nv50_graph_construct_gene_ccache(struct nouveau_grctx *ctx); -+static void nv50_graph_construct_gene_unk10xx(struct nouveau_grctx *ctx); -+static void nv50_graph_construct_gene_unk14xx(struct nouveau_grctx *ctx); -+static void nv50_graph_construct_gene_zcull(struct nouveau_grctx *ctx); -+static void nv50_graph_construct_gene_clipid(struct nouveau_grctx *ctx); -+static void nv50_graph_construct_gene_unk24xx(struct nouveau_grctx *ctx); -+static void nv50_graph_construct_gene_vfetch(struct nouveau_grctx *ctx); -+static void nv50_graph_construct_gene_eng2d(struct nouveau_grctx *ctx); -+static void nv50_graph_construct_gene_csched(struct nouveau_grctx *ctx); -+static void nv50_graph_construct_gene_unk1cxx(struct nouveau_grctx *ctx); -+static void nv50_graph_construct_gene_strmout(struct nouveau_grctx *ctx); -+static void nv50_graph_construct_gene_unk34xx(struct nouveau_grctx *ctx); -+static void nv50_graph_construct_gene_ropm1(struct nouveau_grctx *ctx); -+static void nv50_graph_construct_gene_ropm2(struct nouveau_grctx *ctx); - static void nv50_graph_construct_gene_ropc(struct nouveau_grctx *ctx); - static void nv50_graph_construct_xfer_tp(struct nouveau_grctx *ctx); - -@@ -1030,102 +1175,32 @@ - if (dev_priv->chipset < 0xa0) { - /* Strand 0 */ - ctx->ctxvals_pos = offset; -- switch (dev_priv->chipset) { -- case 0x50: -- xf_emit(ctx, 0x99, 0); -- break; -- case 0x84: -- case 0x86: -- xf_emit(ctx, 0x384, 0); -- break; -- case 0x92: -- case 0x94: -- case 0x96: -- case 0x98: -- xf_emit(ctx, 0x380, 0); -- break; -- } -- nv50_graph_construct_gene_m2mf (ctx); -- switch (dev_priv->chipset) { -- case 0x50: -- case 0x84: -- case 0x86: -- case 0x98: -- xf_emit(ctx, 0x4c4, 0); -- break; -- case 0x92: -- case 0x94: -- case 0x96: -- xf_emit(ctx, 0x984, 0); -- break; -- } -- nv50_graph_construct_gene_unk5(ctx); -- if (dev_priv->chipset == 0x50) -- xf_emit(ctx, 0xa, 0); -- else -- xf_emit(ctx, 0xb, 0); -- nv50_graph_construct_gene_unk4(ctx); -- nv50_graph_construct_gene_unk3(ctx); -+ nv50_graph_construct_gene_dispatch(ctx); -+ nv50_graph_construct_gene_m2mf(ctx); -+ nv50_graph_construct_gene_unk24xx(ctx); -+ nv50_graph_construct_gene_clipid(ctx); -+ nv50_graph_construct_gene_zcull(ctx); - if ((ctx->ctxvals_pos-offset)/8 > size) - size = (ctx->ctxvals_pos-offset)/8; - - /* Strand 1 */ - ctx->ctxvals_pos = offset + 0x1; -- nv50_graph_construct_gene_unk6(ctx); -- nv50_graph_construct_gene_unk7(ctx); -- nv50_graph_construct_gene_unk8(ctx); -- switch (dev_priv->chipset) { -- case 0x50: -- case 0x92: -- xf_emit(ctx, 0xfb, 0); -- break; -- case 0x84: -- xf_emit(ctx, 0xd3, 0); -- break; -- case 0x94: -- case 0x96: -- xf_emit(ctx, 0xab, 0); -- break; -- case 0x86: -- case 0x98: -- xf_emit(ctx, 0x6b, 0); -- break; -- } -- xf_emit(ctx, 2, 0x4e3bfdf); -- xf_emit(ctx, 4, 0); -- xf_emit(ctx, 1, 0x0fac6881); -- xf_emit(ctx, 0xb, 0); -- xf_emit(ctx, 2, 0x4e3bfdf); -+ nv50_graph_construct_gene_vfetch(ctx); -+ nv50_graph_construct_gene_eng2d(ctx); -+ nv50_graph_construct_gene_csched(ctx); -+ nv50_graph_construct_gene_ropm1(ctx); -+ nv50_graph_construct_gene_ropm2(ctx); - if ((ctx->ctxvals_pos-offset)/8 > size) - size = (ctx->ctxvals_pos-offset)/8; - - /* Strand 2 */ - ctx->ctxvals_pos = offset + 0x2; -- switch (dev_priv->chipset) { -- case 0x50: -- case 0x92: -- xf_emit(ctx, 0xa80, 0); -- break; -- case 0x84: -- xf_emit(ctx, 0xa7e, 0); -- break; -- case 0x94: -- case 0x96: -- xf_emit(ctx, 0xa7c, 0); -- break; -- case 0x86: -- case 0x98: -- xf_emit(ctx, 0xa7a, 0); -- break; -- } -- xf_emit(ctx, 1, 0x3fffff); -- xf_emit(ctx, 2, 0); -- xf_emit(ctx, 1, 0x1fff); -- xf_emit(ctx, 0xe, 0); -- nv50_graph_construct_gene_unk9(ctx); -- nv50_graph_construct_gene_unk2(ctx); -- nv50_graph_construct_gene_unk1(ctx); -- nv50_graph_construct_gene_unk10(ctx); -+ nv50_graph_construct_gene_ccache(ctx); -+ nv50_graph_construct_gene_unk1cxx(ctx); -+ nv50_graph_construct_gene_strmout(ctx); -+ nv50_graph_construct_gene_unk14xx(ctx); -+ nv50_graph_construct_gene_unk10xx(ctx); -+ nv50_graph_construct_gene_unk34xx(ctx); - if ((ctx->ctxvals_pos-offset)/8 > size) - size = (ctx->ctxvals_pos-offset)/8; - -@@ -1150,86 +1225,46 @@ - } else { - /* Strand 0 */ - ctx->ctxvals_pos = offset; -- if (dev_priv->chipset > 0xa0 && dev_priv->chipset < 0xaa) -- xf_emit(ctx, 0x385, 0); -- else -- xf_emit(ctx, 0x384, 0); -+ nv50_graph_construct_gene_dispatch(ctx); - nv50_graph_construct_gene_m2mf(ctx); -- xf_emit(ctx, 0x950, 0); -- nv50_graph_construct_gene_unk10(ctx); -- xf_emit(ctx, 1, 0x0fac6881); -- if (dev_priv->chipset > 0xa0 && dev_priv->chipset < 0xaa) { -- xf_emit(ctx, 1, 1); -- xf_emit(ctx, 3, 0); -- } -- nv50_graph_construct_gene_unk8(ctx); -- if (dev_priv->chipset == 0xa0) -- xf_emit(ctx, 0x189, 0); -- else if (dev_priv->chipset == 0xa3) -- xf_emit(ctx, 0xd5, 0); -- else if (dev_priv->chipset == 0xa5) -- xf_emit(ctx, 0x99, 0); -- else if (dev_priv->chipset == 0xaa) -- xf_emit(ctx, 0x65, 0); -- else -- xf_emit(ctx, 0x6d, 0); -- nv50_graph_construct_gene_unk9(ctx); -+ nv50_graph_construct_gene_unk34xx(ctx); -+ nv50_graph_construct_gene_csched(ctx); -+ nv50_graph_construct_gene_unk1cxx(ctx); -+ nv50_graph_construct_gene_strmout(ctx); - if ((ctx->ctxvals_pos-offset)/8 > size) - size = (ctx->ctxvals_pos-offset)/8; - - /* Strand 1 */ - ctx->ctxvals_pos = offset + 1; -- nv50_graph_construct_gene_unk1(ctx); -+ nv50_graph_construct_gene_unk10xx(ctx); - if ((ctx->ctxvals_pos-offset)/8 > size) - size = (ctx->ctxvals_pos-offset)/8; - - /* Strand 2 */ - ctx->ctxvals_pos = offset + 2; -- if (dev_priv->chipset == 0xa0) { -- nv50_graph_construct_gene_unk2(ctx); -- } -- xf_emit(ctx, 0x36, 0); -- nv50_graph_construct_gene_unk5(ctx); -+ if (dev_priv->chipset == 0xa0) -+ nv50_graph_construct_gene_unk14xx(ctx); -+ nv50_graph_construct_gene_unk24xx(ctx); - if ((ctx->ctxvals_pos-offset)/8 > size) - size = (ctx->ctxvals_pos-offset)/8; - - /* Strand 3 */ - ctx->ctxvals_pos = offset + 3; -- xf_emit(ctx, 1, 0); -- xf_emit(ctx, 1, 1); -- nv50_graph_construct_gene_unk6(ctx); -+ nv50_graph_construct_gene_vfetch(ctx); - if ((ctx->ctxvals_pos-offset)/8 > size) - size = (ctx->ctxvals_pos-offset)/8; - - /* Strand 4 */ - ctx->ctxvals_pos = offset + 4; -- if (dev_priv->chipset == 0xa0) -- xf_emit(ctx, 0xa80, 0); -- else if (dev_priv->chipset == 0xa3) -- xf_emit(ctx, 0xa7c, 0); -- else -- xf_emit(ctx, 0xa7a, 0); -- xf_emit(ctx, 1, 0x3fffff); -- xf_emit(ctx, 2, 0); -- xf_emit(ctx, 1, 0x1fff); -+ nv50_graph_construct_gene_ccache(ctx); - if ((ctx->ctxvals_pos-offset)/8 > size) - size = (ctx->ctxvals_pos-offset)/8; - - /* Strand 5 */ - ctx->ctxvals_pos = offset + 5; -- xf_emit(ctx, 1, 0); -- xf_emit(ctx, 1, 0x0fac6881); -- xf_emit(ctx, 0xb, 0); -- xf_emit(ctx, 2, 0x4e3bfdf); -- xf_emit(ctx, 3, 0); -- if (dev_priv->chipset > 0xa0 && dev_priv->chipset < 0xaa) -- xf_emit(ctx, 1, 0x11); -- xf_emit(ctx, 1, 0); -- xf_emit(ctx, 2, 0x4e3bfdf); -- xf_emit(ctx, 2, 0); -- if (dev_priv->chipset > 0xa0 && dev_priv->chipset < 0xaa) -- xf_emit(ctx, 1, 0x11); -- xf_emit(ctx, 1, 0); -+ nv50_graph_construct_gene_ropm2(ctx); -+ nv50_graph_construct_gene_ropm1(ctx); -+ /* per-ROP context */ - for (i = 0; i < 8; i++) - if (units & (1<<(i+16))) - nv50_graph_construct_gene_ropc(ctx); -@@ -1238,10 +1273,9 @@ - - /* Strand 6 */ - ctx->ctxvals_pos = offset + 6; -- nv50_graph_construct_gene_unk3(ctx); -- xf_emit(ctx, 0xb, 0); -- nv50_graph_construct_gene_unk4(ctx); -- nv50_graph_construct_gene_unk7(ctx); -+ nv50_graph_construct_gene_zcull(ctx); -+ nv50_graph_construct_gene_clipid(ctx); -+ nv50_graph_construct_gene_eng2d(ctx); - if (units & (1 << 0)) - nv50_graph_construct_xfer_tp(ctx); - if (units & (1 << 1)) -@@ -1269,7 +1303,7 @@ - if (units & (1 << 9)) - nv50_graph_construct_xfer_tp(ctx); - } else { -- nv50_graph_construct_gene_unk2(ctx); -+ nv50_graph_construct_gene_unk14xx(ctx); - } - if ((ctx->ctxvals_pos-offset)/8 > size) - size = (ctx->ctxvals_pos-offset)/8; -@@ -1290,9 +1324,70 @@ - */ - - 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; -+ /* SEEK */ -+ if (dev_priv->chipset == 0x50) -+ xf_emit(ctx, 5, 0); -+ else if (!IS_NVA3F(dev_priv->chipset)) -+ xf_emit(ctx, 6, 0); -+ else -+ xf_emit(ctx, 4, 0); -+ /* SEEK */ -+ /* the PGRAPH's internal FIFO */ -+ if (dev_priv->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)) -+ xf_emit(ctx, 3, 0); -+ /* SEEK */ -+ /* CTX_SWITCH: caches of gr objects bound to subchannels. 8 values, last used index */ -+ xf_emit(ctx, 9, 0); -+ /* SEEK */ -+ xf_emit(ctx, 9, 0); -+ /* SEEK */ -+ xf_emit(ctx, 9, 0); -+ /* SEEK */ -+ xf_emit(ctx, 9, 0); -+ /* SEEK */ -+ if (dev_priv->chipset < 0x90) -+ xf_emit(ctx, 4, 0); -+ /* SEEK */ -+ xf_emit(ctx, 2, 0); -+ /* SEEK */ -+ xf_emit(ctx, 6*2, 0); -+ xf_emit(ctx, 2, 0); -+ /* SEEK */ -+ xf_emit(ctx, 2, 0); -+ /* SEEK */ -+ xf_emit(ctx, 6*2, 0); -+ xf_emit(ctx, 2, 0); -+ /* SEEK */ -+ if (dev_priv->chipset == 0x50) -+ xf_emit(ctx, 0x1c, 0); -+ else if (dev_priv->chipset < 0xa0) -+ xf_emit(ctx, 0x1e, 0); -+ else -+ xf_emit(ctx, 0x22, 0); -+ /* SEEK */ -+ xf_emit(ctx, 0x15, 0); -+} -+ -+static void - nv50_graph_construct_gene_m2mf(struct nouveau_grctx *ctx) - { -- /* m2mf state */ -+ /* Strand 0, right after dispatch */ -+ struct drm_nouveau_private *dev_priv = ctx->dev->dev_private; -+ int smallm2mf = 0; -+ if (dev_priv->chipset < 0x92 || dev_priv->chipset == 0x98) -+ smallm2mf = 1; -+ /* SEEK */ - xf_emit (ctx, 1, 0); /* DMA_NOTIFY instance >> 4 */ - xf_emit (ctx, 1, 0); /* DMA_BUFFER_IN instance >> 4 */ - xf_emit (ctx, 1, 0); /* DMA_BUFFER_OUT instance >> 4 */ -@@ -1319,427 +1414,975 @@ - xf_emit (ctx, 1, 0); /* TILING_POSITION_OUT */ - xf_emit (ctx, 1, 0); /* OFFSET_IN_HIGH */ - xf_emit (ctx, 1, 0); /* OFFSET_OUT_HIGH */ -+ /* SEEK */ -+ if (smallm2mf) -+ xf_emit(ctx, 0x40, 0); /* 20 * ffffffff, 3ffff */ -+ else -+ xf_emit(ctx, 0x100, 0); /* 80 * ffffffff, 3ffff */ -+ xf_emit(ctx, 4, 0); /* 1f/7f, 0, 1f/7f, 0 [1f for smallm2mf, 7f otherwise] */ -+ /* SEEK */ -+ if (smallm2mf) -+ xf_emit(ctx, 0x400, 0); /* ffffffff */ -+ else -+ xf_emit(ctx, 0x800, 0); /* ffffffff */ -+ xf_emit(ctx, 4, 0); /* ff/1ff, 0, 0, 0 [ff for smallm2mf, 1ff otherwise] */ -+ /* SEEK */ -+ xf_emit(ctx, 0x40, 0); /* 20 * bits ffffffff, 3ffff */ -+ xf_emit(ctx, 0x6, 0); /* 1f, 0, 1f, 0, 1f, 0 */ - } - - static void --nv50_graph_construct_gene_unk1(struct nouveau_grctx *ctx) -+nv50_graph_construct_gene_ccache(struct nouveau_grctx *ctx) - { - struct drm_nouveau_private *dev_priv = ctx->dev->dev_private; -- /* end of area 2 on pre-NVA0, area 1 on NVAx */ -- xf_emit(ctx, 2, 4); -- xf_emit(ctx, 1, 0); -- xf_emit(ctx, 1, 0x80); -- xf_emit(ctx, 1, 4); -- xf_emit(ctx, 1, 0x80c14); -- xf_emit(ctx, 1, 0); -- if (dev_priv->chipset == 0x50) -- xf_emit(ctx, 1, 0x3ff); -- else -- xf_emit(ctx, 1, 0x7ff); -+ xf_emit(ctx, 2, 0); /* RO */ -+ xf_emit(ctx, 0x800, 0); /* ffffffff */ - switch (dev_priv->chipset) { - case 0x50: -- case 0x86: -- case 0x98: -- case 0xaa: -- case 0xac: -- xf_emit(ctx, 0x542, 0); -+ case 0x92: -+ case 0xa0: -+ xf_emit(ctx, 0x2b, 0); - break; - case 0x84: -- case 0x92: -+ xf_emit(ctx, 0x29, 0); -+ break; - case 0x94: - case 0x96: -- xf_emit(ctx, 0x942, 0); -- break; -- case 0xa0: - case 0xa3: -- xf_emit(ctx, 0x2042, 0); -+ xf_emit(ctx, 0x27, 0); - break; -+ case 0x86: -+ case 0x98: - case 0xa5: - case 0xa8: -- xf_emit(ctx, 0x842, 0); -+ case 0xaa: -+ case 0xac: -+ case 0xaf: -+ xf_emit(ctx, 0x25, 0); - break; - } -- xf_emit(ctx, 2, 4); -- xf_emit(ctx, 1, 0); -- xf_emit(ctx, 1, 0x80); -- xf_emit(ctx, 1, 4); -- xf_emit(ctx, 1, 1); -- xf_emit(ctx, 1, 0); -- xf_emit(ctx, 1, 0x27); -- xf_emit(ctx, 1, 0); -- xf_emit(ctx, 1, 0x26); -- xf_emit(ctx, 3, 0); -+ /* CB bindings, 0x80 of them. first word is address >> 8, second is -+ * size >> 4 | valid << 24 */ -+ xf_emit(ctx, 0x100, 0); /* ffffffff CB_DEF */ -+ xf_emit(ctx, 1, 0); /* 0000007f CB_ADDR_BUFFER */ -+ xf_emit(ctx, 1, 0); /* 0 */ -+ xf_emit(ctx, 0x30, 0); /* ff SET_PROGRAM_CB */ -+ xf_emit(ctx, 1, 0); /* 3f last SET_PROGRAM_CB */ -+ xf_emit(ctx, 4, 0); /* RO */ -+ xf_emit(ctx, 0x100, 0); /* ffffffff */ -+ xf_emit(ctx, 8, 0); /* 1f, 0, 0, ... */ -+ xf_emit(ctx, 8, 0); /* ffffffff */ -+ xf_emit(ctx, 4, 0); /* ffffffff */ -+ xf_emit(ctx, 1, 0); /* 3 */ -+ xf_emit(ctx, 1, 0); /* ffffffff */ -+ xf_emit(ctx, 1, 0); /* 0000ffff DMA_CODE_CB */ -+ xf_emit(ctx, 1, 0); /* 0000ffff DMA_TIC */ -+ xf_emit(ctx, 1, 0); /* 0000ffff DMA_TSC */ -+ xf_emit(ctx, 1, 0); /* 00000001 LINKED_TSC */ -+ xf_emit(ctx, 1, 0); /* 000000ff TIC_ADDRESS_HIGH */ -+ xf_emit(ctx, 1, 0); /* ffffffff TIC_ADDRESS_LOW */ -+ xf_emit(ctx, 1, 0x3fffff); /* 003fffff TIC_LIMIT */ -+ xf_emit(ctx, 1, 0); /* 000000ff TSC_ADDRESS_HIGH */ -+ xf_emit(ctx, 1, 0); /* ffffffff TSC_ADDRESS_LOW */ -+ xf_emit(ctx, 1, 0x1fff); /* 000fffff TSC_LIMIT */ -+ xf_emit(ctx, 1, 0); /* 000000ff VP_ADDRESS_HIGH */ -+ xf_emit(ctx, 1, 0); /* ffffffff VP_ADDRESS_LOW */ -+ xf_emit(ctx, 1, 0); /* 00ffffff VP_START_ID */ -+ xf_emit(ctx, 1, 0); /* 000000ff CB_DEF_ADDRESS_HIGH */ -+ xf_emit(ctx, 1, 0); /* ffffffff CB_DEF_ADDRESS_LOW */ -+ xf_emit(ctx, 1, 0); /* 00000001 GP_ENABLE */ -+ xf_emit(ctx, 1, 0); /* 000000ff GP_ADDRESS_HIGH */ -+ xf_emit(ctx, 1, 0); /* ffffffff GP_ADDRESS_LOW */ -+ xf_emit(ctx, 1, 0); /* 00ffffff GP_START_ID */ -+ xf_emit(ctx, 1, 0); /* 000000ff FP_ADDRESS_HIGH */ -+ xf_emit(ctx, 1, 0); /* ffffffff FP_ADDRESS_LOW */ -+ xf_emit(ctx, 1, 0); /* 00ffffff FP_START_ID */ - } - - static void --nv50_graph_construct_gene_unk10(struct nouveau_grctx *ctx) -+nv50_graph_construct_gene_unk10xx(struct nouveau_grctx *ctx) - { -+ struct drm_nouveau_private *dev_priv = ctx->dev->dev_private; -+ int i; - /* end of area 2 on pre-NVA0, area 1 on NVAx */ -- xf_emit(ctx, 0x10, 0x04000000); -- xf_emit(ctx, 0x24, 0); -- xf_emit(ctx, 2, 0x04e3bfdf); -- xf_emit(ctx, 2, 0); -- xf_emit(ctx, 1, 0x1fe21); -+ 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 */ -+ xf_emit(ctx, 1, 0x80); /* 0000ffff GP_VERTEX_OUTPUT_COUNT */ -+ 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) -+ 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) { -+ case 0x50: -+ case 0x86: -+ case 0x98: -+ case 0xaa: -+ case 0xac: -+ xf_emit(ctx, 0xa0, 0); /* ffffffff */ -+ break; -+ case 0x84: -+ case 0x92: -+ case 0x94: -+ case 0x96: -+ xf_emit(ctx, 0x120, 0); -+ break; -+ case 0xa5: -+ case 0xa8: -+ xf_emit(ctx, 0x100, 0); /* ffffffff */ -+ break; -+ case 0xa0: -+ case 0xa3: -+ case 0xaf: -+ xf_emit(ctx, 0x400, 0); /* ffffffff */ -+ break; -+ } -+ xf_emit(ctx, 4, 0); /* 3f, 0, 0, 0 */ -+ xf_emit(ctx, 4, 0); /* ffffffff */ -+ } -+ 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 */ -+ xf_emit(ctx, 1, 0x80); /* 0000ffff GP_VERTEX_OUTPUT_COUNT */ -+ xf_emit(ctx, 1, 4); /* 000000ff GP_REG_ALLOC_TEMP */ -+ xf_emit(ctx, 1, 1); /* 00000001 RASTERIZE_ENABLE */ -+ xf_emit(ctx, 1, 0); /* 00000001 tesla UNK1900 */ -+ xf_emit(ctx, 1, 0x27); /* 000000ff UNK0FD4 */ -+ xf_emit(ctx, 1, 0); /* 0001ffff GP_BUILTIN_RESULT_EN */ -+ xf_emit(ctx, 1, 0x26); /* 000000ff SEMANTIC_LAYER */ -+ xf_emit(ctx, 1, 0); /* ffffffff tesla UNK1A30 */ -+} -+ -+static void -+nv50_graph_construct_gene_unk34xx(struct nouveau_grctx *ctx) -+{ -+ struct drm_nouveau_private *dev_priv = ctx->dev->dev_private; -+ /* 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 */ -+ xf_emit(ctx, 0x10, 0x04000000); /* 07ffffff VIEWPORT_CLIP_HORIZ*8, VIEWPORT_CLIP_VERT*8 */ -+ xf_emit(ctx, 1, 0); /* 00000001 POLYGON_STIPPLE_ENABLE */ -+ xf_emit(ctx, 0x20, 0); /* ffffffff POLYGON_STIPPLE */ -+ xf_emit(ctx, 2, 0); /* 00007fff WINDOW_OFFSET_XY */ -+ xf_emit(ctx, 1, 0); /* ffff0ff3 */ -+ xf_emit(ctx, 1, 0x04e3bfdf); /* ffffffff UNK0D64 */ -+ xf_emit(ctx, 1, 0x04e3bfdf); /* ffffffff UNK0DF4 */ -+ 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) -+ xf_emit(ctx, 1, 0x0fac6881); -+ if (IS_NVA3F(dev_priv->chipset)) { -+ xf_emit(ctx, 1, 1); -+ xf_emit(ctx, 3, 0); -+ } - } - - static void --nv50_graph_construct_gene_unk2(struct nouveau_grctx *ctx) -+nv50_graph_construct_gene_unk14xx(struct nouveau_grctx *ctx) - { - struct drm_nouveau_private *dev_priv = ctx->dev->dev_private; - /* middle of area 2 on pre-NVA0, beginning of area 2 on NVA0, area 7 on >NVA0 */ - if (dev_priv->chipset != 0x50) { -- xf_emit(ctx, 5, 0); -- xf_emit(ctx, 1, 0x80c14); -- xf_emit(ctx, 2, 0); -- xf_emit(ctx, 1, 0x804); -- xf_emit(ctx, 1, 0); -- xf_emit(ctx, 2, 4); -- xf_emit(ctx, 1, 0x8100c12); -- } -- xf_emit(ctx, 1, 0); -- xf_emit(ctx, 2, 4); -- xf_emit(ctx, 1, 0); -- xf_emit(ctx, 1, 0x10); -- if (dev_priv->chipset == 0x50) -- xf_emit(ctx, 3, 0); -- else -- xf_emit(ctx, 4, 0); -- xf_emit(ctx, 1, 0x804); -- xf_emit(ctx, 1, 1); -- xf_emit(ctx, 1, 0x1a); -+ xf_emit(ctx, 5, 0); /* ffffffff */ -+ xf_emit(ctx, 1, 0x80c14); /* 01ffffff SEMANTIC_COLOR */ -+ xf_emit(ctx, 1, 0); /* 00000001 */ -+ xf_emit(ctx, 1, 0); /* 000003ff */ -+ xf_emit(ctx, 1, 0x804); /* 00000fff SEMANTIC_CLIP */ -+ xf_emit(ctx, 1, 0); /* 00000001 */ -+ xf_emit(ctx, 2, 4); /* 7f, ff */ -+ xf_emit(ctx, 1, 0x8100c12); /* 1fffffff FP_INTERPOLANT_CTRL */ -+ } -+ xf_emit(ctx, 1, 0); /* ffffffff tesla UNK1A30 */ -+ xf_emit(ctx, 1, 4); /* 0000007f VP_RESULT_MAP_SIZE */ -+ xf_emit(ctx, 1, 4); /* 000000ff GP_RESULT_MAP_SIZE */ -+ 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) -- xf_emit(ctx, 1, 0x7f); -- xf_emit(ctx, 1, 0); -- xf_emit(ctx, 1, 1); -- xf_emit(ctx, 1, 0x80c14); -- xf_emit(ctx, 1, 0); -- xf_emit(ctx, 1, 0x8100c12); -- xf_emit(ctx, 2, 4); -- xf_emit(ctx, 1, 0); -- xf_emit(ctx, 1, 0x10); -- xf_emit(ctx, 3, 0); -- xf_emit(ctx, 1, 1); -- xf_emit(ctx, 1, 0x8100c12); -- xf_emit(ctx, 6, 0); -- if (dev_priv->chipset == 0x50) -- xf_emit(ctx, 1, 0x3ff); -- else -- xf_emit(ctx, 1, 0x7ff); -- xf_emit(ctx, 1, 0x80c14); -- xf_emit(ctx, 0x38, 0); -- xf_emit(ctx, 1, 1); -- xf_emit(ctx, 2, 0); -- xf_emit(ctx, 1, 0x10); -- xf_emit(ctx, 0x38, 0); -- xf_emit(ctx, 2, 0x88); -- xf_emit(ctx, 2, 0); -- xf_emit(ctx, 1, 4); -- xf_emit(ctx, 0x16, 0); -- xf_emit(ctx, 1, 0x26); -- xf_emit(ctx, 2, 0); -- xf_emit(ctx, 1, 0x3f800000); -- if (dev_priv->chipset > 0xa0 && dev_priv->chipset < 0xaa) -- xf_emit(ctx, 4, 0); -- else -- xf_emit(ctx, 3, 0); -- xf_emit(ctx, 1, 0x1a); -- xf_emit(ctx, 1, 0x10); -+ 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) -- xf_emit(ctx, 0x28, 0); -- else -- xf_emit(ctx, 0x25, 0); -- xf_emit(ctx, 1, 0x52); -- xf_emit(ctx, 1, 0); -- xf_emit(ctx, 1, 0x26); -- xf_emit(ctx, 1, 0); -- xf_emit(ctx, 2, 4); -- xf_emit(ctx, 1, 0); -- xf_emit(ctx, 1, 0x1a); -- xf_emit(ctx, 2, 0); -- xf_emit(ctx, 1, 0x00ffff00); -- xf_emit(ctx, 1, 0); -+ xf_emit(ctx, 1, 0x7f); /* 000000ff tesla UNK0FFC */ -+ xf_emit(ctx, 1, 0); /* ffffffff tesla UNK1A30 */ -+ xf_emit(ctx, 1, 1); /* 00000001 SHADE_MODEL */ -+ xf_emit(ctx, 1, 0x80c14); /* 01ffffff SEMANTIC_COLOR */ -+ xf_emit(ctx, 1, 0); /* 00000001 tesla UNK1900 */ -+ xf_emit(ctx, 1, 0x8100c12); /* 1fffffff FP_INTERPOLANT_CTRL */ -+ xf_emit(ctx, 1, 4); /* 0000007f VP_RESULT_MAP_SIZE */ -+ xf_emit(ctx, 1, 4); /* 000000ff GP_RESULT_MAP_SIZE */ -+ xf_emit(ctx, 1, 0); /* 00000001 GP_ENABLE */ -+ xf_emit(ctx, 1, 0x10); /* 7f/ff VIEW_VOLUME_CLIP_CTRL */ -+ xf_emit(ctx, 1, 0); /* 00000001 tesla UNK0D7C */ -+ xf_emit(ctx, 1, 0); /* 00000001 tesla UNK0F8C */ -+ xf_emit(ctx, 1, 0); /* ffffffff tesla UNK1A30 */ -+ xf_emit(ctx, 1, 1); /* 00000001 VIEWPORT_TRANSFORM_EN */ -+ xf_emit(ctx, 1, 0x8100c12); /* 1fffffff FP_INTERPOLANT_CTRL */ -+ 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) -+ xf_emit(ctx, 1, 0x3ff); /* 000003ff tesla UNK0D68 */ -+ else -+ xf_emit(ctx, 1, 0x7ff); /* 000007ff tesla UNK0D68 */ -+ xf_emit(ctx, 1, 0x80c14); /* 01ffffff SEMANTIC_COLOR */ -+ xf_emit(ctx, 1, 0); /* 00000001 VERTEX_TWO_SIDE_ENABLE */ -+ xf_emit(ctx, 0x30, 0); /* ffffffff VIEWPORT_SCALE: X0, Y0, Z0, X1, Y1, ... */ -+ xf_emit(ctx, 3, 0); /* f, 0, 0 */ -+ xf_emit(ctx, 3, 0); /* ffffffff last VIEWPORT_SCALE? */ -+ xf_emit(ctx, 1, 0); /* ffffffff tesla UNK1A30 */ -+ xf_emit(ctx, 1, 1); /* 00000001 VIEWPORT_TRANSFORM_EN */ -+ xf_emit(ctx, 1, 0); /* 00000001 tesla UNK1900 */ -+ xf_emit(ctx, 1, 0); /* 00000001 tesla UNK1924 */ -+ xf_emit(ctx, 1, 0x10); /* 000000ff VIEW_VOLUME_CLIP_CTRL */ -+ xf_emit(ctx, 1, 0); /* 00000001 */ -+ xf_emit(ctx, 0x30, 0); /* ffffffff VIEWPORT_TRANSLATE */ -+ xf_emit(ctx, 3, 0); /* f, 0, 0 */ -+ xf_emit(ctx, 3, 0); /* ffffffff */ -+ xf_emit(ctx, 1, 0); /* ffffffff tesla UNK1A30 */ -+ xf_emit(ctx, 2, 0x88); /* 000001ff tesla UNK19D8 */ -+ xf_emit(ctx, 1, 0); /* 00000001 tesla UNK1924 */ -+ xf_emit(ctx, 1, 0); /* ffffffff tesla UNK1A30 */ -+ xf_emit(ctx, 1, 4); /* 0000000f CULL_MODE */ -+ xf_emit(ctx, 2, 0); /* 07ffffff SCREEN_SCISSOR */ -+ xf_emit(ctx, 2, 0); /* 00007fff WINDOW_OFFSET_XY */ -+ xf_emit(ctx, 1, 0); /* 00000003 WINDOW_ORIGIN */ -+ xf_emit(ctx, 0x10, 0); /* 00000001 SCISSOR_ENABLE */ -+ xf_emit(ctx, 1, 0); /* 0001ffff GP_BUILTIN_RESULT_EN */ -+ xf_emit(ctx, 1, 0x26); /* 000000ff SEMANTIC_LAYER */ -+ xf_emit(ctx, 1, 0); /* 00000001 tesla UNK1900 */ -+ xf_emit(ctx, 1, 0); /* 0000000f */ -+ xf_emit(ctx, 1, 0x3f800000); /* ffffffff LINE_WIDTH */ -+ 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)) -+ 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) { -+ xf_emit(ctx, 1, 0); /* ffffffff */ -+ xf_emit(ctx, 1, 0); /* 00000001 */ -+ xf_emit(ctx, 1, 0); /* 000003ff */ -+ } -+ xf_emit(ctx, 0x20, 0); /* 10xbits ffffffff, 3fffff. SCISSOR_* */ -+ xf_emit(ctx, 1, 0); /* f */ -+ xf_emit(ctx, 1, 0); /* 0? */ -+ xf_emit(ctx, 1, 0); /* ffffffff */ -+ xf_emit(ctx, 1, 0); /* 003fffff */ -+ xf_emit(ctx, 1, 0); /* ffffffff tesla UNK1A30 */ -+ xf_emit(ctx, 1, 0x52); /* 000001ff SEMANTIC_PTSZ */ -+ xf_emit(ctx, 1, 0); /* 0001ffff GP_BUILTIN_RESULT_EN */ -+ xf_emit(ctx, 1, 0x26); /* 000000ff SEMANTIC_LAYER */ -+ xf_emit(ctx, 1, 0); /* 00000001 tesla UNK1900 */ -+ xf_emit(ctx, 1, 4); /* 0000007f VP_RESULT_MAP_SIZE */ -+ xf_emit(ctx, 1, 4); /* 000000ff GP_RESULT_MAP_SIZE */ -+ xf_emit(ctx, 1, 0); /* 00000001 GP_ENABLE */ -+ xf_emit(ctx, 1, 0x1a); /* 0000001f POLYGON_MODE */ -+ xf_emit(ctx, 1, 0); /* 00000001 LINE_SMOOTH_ENABLE */ -+ xf_emit(ctx, 1, 0); /* 00000001 LINE_STIPPLE_ENABLE */ -+ xf_emit(ctx, 1, 0x00ffff00); /* 00ffffff LINE_STIPPLE_PATTERN */ -+ xf_emit(ctx, 1, 0); /* 0000000f */ - } - - static void --nv50_graph_construct_gene_unk3(struct nouveau_grctx *ctx) -+nv50_graph_construct_gene_zcull(struct nouveau_grctx *ctx) - { - struct drm_nouveau_private *dev_priv = ctx->dev->dev_private; -- /* end of area 0 on pre-NVA0, beginning of area 6 on NVAx */ -- xf_emit(ctx, 1, 0x3f); -- xf_emit(ctx, 0xa, 0); -- xf_emit(ctx, 1, 2); -- xf_emit(ctx, 2, 0x04000000); -- xf_emit(ctx, 8, 0); -- xf_emit(ctx, 1, 4); -- xf_emit(ctx, 3, 0); -- xf_emit(ctx, 1, 4); -- if (dev_priv->chipset == 0x50) -- xf_emit(ctx, 0x10, 0); -- else -- xf_emit(ctx, 0x11, 0); -- xf_emit(ctx, 1, 1); -- xf_emit(ctx, 1, 0x1001); -- xf_emit(ctx, 4, 0xffff); -- xf_emit(ctx, 0x20, 0); -- xf_emit(ctx, 0x10, 0x3f800000); -- xf_emit(ctx, 1, 0x10); -- if (dev_priv->chipset == 0x50) -- xf_emit(ctx, 1, 0); -- else -- xf_emit(ctx, 2, 0); -- xf_emit(ctx, 1, 3); -- xf_emit(ctx, 2, 0); -+ /* end of strand 0 on pre-NVA0, beginning of strand 6 on NVAx */ -+ /* SEEK */ -+ xf_emit(ctx, 1, 0x3f); /* 0000003f UNK1590 */ -+ xf_emit(ctx, 1, 0); /* 00000001 ALPHA_TEST_ENABLE */ -+ xf_emit(ctx, 1, 0); /* 00000007 MULTISAMPLE_SAMPLES_LOG2 */ -+ xf_emit(ctx, 1, 0); /* 00000001 tesla UNK1534 */ -+ xf_emit(ctx, 1, 0); /* 00000007 STENCIL_BACK_FUNC_FUNC */ -+ xf_emit(ctx, 1, 0); /* 000000ff STENCIL_BACK_FUNC_MASK */ -+ xf_emit(ctx, 1, 0); /* 000000ff STENCIL_BACK_FUNC_REF */ -+ xf_emit(ctx, 1, 0); /* 000000ff STENCIL_BACK_MASK */ -+ xf_emit(ctx, 3, 0); /* 00000007 STENCIL_BACK_OP_FAIL, ZFAIL, ZPASS */ -+ xf_emit(ctx, 1, 2); /* 00000003 tesla UNK143C */ -+ xf_emit(ctx, 2, 0x04000000); /* 07ffffff tesla UNK0D6C */ -+ xf_emit(ctx, 1, 0); /* ffff0ff3 */ -+ xf_emit(ctx, 1, 0); /* 00000001 CLIPID_ENABLE */ -+ xf_emit(ctx, 2, 0); /* ffffffff DEPTH_BOUNDS */ -+ xf_emit(ctx, 1, 0); /* 00000001 */ -+ 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 */ -+ xf_emit(ctx, 1, 4); /* 0000000f CULL_MODE */ -+ xf_emit(ctx, 1, 0); /* 0000ffff */ -+ xf_emit(ctx, 1, 0); /* 00000001 UNK0FB0 */ -+ xf_emit(ctx, 1, 0); /* 00000001 POLYGON_STIPPLE_ENABLE */ -+ xf_emit(ctx, 1, 4); /* 00000007 FP_CONTROL */ -+ xf_emit(ctx, 1, 0); /* ffffffff */ -+ xf_emit(ctx, 1, 0); /* 0001ffff GP_BUILTIN_RESULT_EN */ -+ xf_emit(ctx, 1, 0); /* 000000ff CLEAR_STENCIL */ -+ 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_FUNC_REF */ -+ 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 */ -+ 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) -+ xf_emit(ctx, 1, 0); /* 00000003 tesla UNK1108 */ -+ xf_emit(ctx, 1, 0); /* 00000001 SAMPLECNT_ENABLE */ -+ xf_emit(ctx, 1, 0); /* 0000000f ZETA_FORMAT */ -+ xf_emit(ctx, 1, 1); /* 00000001 ZETA_ENABLE */ -+ xf_emit(ctx, 1, 0x1001); /* 00001fff ZETA_ARRAY_MODE */ -+ /* SEEK */ -+ xf_emit(ctx, 4, 0xffff); /* 0000ffff MSAA_MASK */ -+ xf_emit(ctx, 0x10, 0); /* 00000001 SCISSOR_ENABLE */ -+ xf_emit(ctx, 0x10, 0); /* ffffffff DEPTH_RANGE_NEAR */ -+ xf_emit(ctx, 0x10, 0x3f800000); /* ffffffff DEPTH_RANGE_FAR */ -+ xf_emit(ctx, 1, 0x10); /* 7f/ff/3ff VIEW_VOLUME_CLIP_CTRL */ -+ 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) -+ xf_emit(ctx, 1, 0); /* 0fffffff tesla UNK1104 */ -+ xf_emit(ctx, 1, 0); /* 00000001 tesla UNK151C */ - } - - static void --nv50_graph_construct_gene_unk4(struct nouveau_grctx *ctx) -+nv50_graph_construct_gene_clipid(struct nouveau_grctx *ctx) - { -- /* middle of area 0 on pre-NVA0, middle of area 6 on NVAx */ -- xf_emit(ctx, 2, 0x04000000); -- xf_emit(ctx, 1, 0); -- xf_emit(ctx, 1, 0x80); -- xf_emit(ctx, 3, 0); -- xf_emit(ctx, 1, 0x80); -- xf_emit(ctx, 1, 0); -+ /* middle of strand 0 on pre-NVA0 [after 24xx], middle of area 6 on NVAx */ -+ /* SEEK */ -+ xf_emit(ctx, 1, 0); /* 00000007 UNK0FB4 */ -+ /* SEEK */ -+ xf_emit(ctx, 4, 0); /* 07ffffff CLIPID_REGION_HORIZ */ -+ xf_emit(ctx, 4, 0); /* 07ffffff CLIPID_REGION_VERT */ -+ xf_emit(ctx, 2, 0); /* 07ffffff SCREEN_SCISSOR */ -+ xf_emit(ctx, 2, 0x04000000); /* 07ffffff UNK1508 */ -+ xf_emit(ctx, 1, 0); /* 00000001 CLIPID_ENABLE */ -+ xf_emit(ctx, 1, 0x80); /* 00003fff CLIPID_WIDTH */ -+ xf_emit(ctx, 1, 0); /* 000000ff CLIPID_ID */ -+ xf_emit(ctx, 1, 0); /* 000000ff CLIPID_ADDRESS_HIGH */ -+ xf_emit(ctx, 1, 0); /* ffffffff CLIPID_ADDRESS_LOW */ -+ xf_emit(ctx, 1, 0x80); /* 00003fff CLIPID_HEIGHT */ -+ xf_emit(ctx, 1, 0); /* 0000ffff DMA_CLIPID */ - } - - static void --nv50_graph_construct_gene_unk5(struct nouveau_grctx *ctx) -+nv50_graph_construct_gene_unk24xx(struct nouveau_grctx *ctx) - { - struct drm_nouveau_private *dev_priv = ctx->dev->dev_private; -- /* middle of area 0 on pre-NVA0 [after m2mf], end of area 2 on NVAx */ -- xf_emit(ctx, 2, 4); -- if (dev_priv->chipset > 0xa0 && dev_priv->chipset < 0xaa) -- xf_emit(ctx, 0x1c4d, 0); -- else -- xf_emit(ctx, 0x1c4b, 0); -- xf_emit(ctx, 2, 4); -- xf_emit(ctx, 1, 0x8100c12); -+ int i; -+ /* middle of strand 0 on pre-NVA0 [after m2mf], end of strand 2 on NVAx */ -+ /* SEEK */ -+ xf_emit(ctx, 0x33, 0); -+ /* SEEK */ -+ xf_emit(ctx, 2, 0); -+ /* SEEK */ -+ xf_emit(ctx, 1, 0); /* 00000001 GP_ENABLE */ -+ 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)) { -+ xf_emit(ctx, 4, 0); /* RO */ -+ xf_emit(ctx, 0xe10, 0); /* 190 * 9: 8*ffffffff, 7ff */ -+ xf_emit(ctx, 1, 0); /* 1ff */ -+ xf_emit(ctx, 8, 0); /* 0? */ -+ xf_emit(ctx, 9, 0); /* ffffffff, 7ff */ -+ -+ xf_emit(ctx, 4, 0); /* RO */ -+ xf_emit(ctx, 0xe10, 0); /* 190 * 9: 8*ffffffff, 7ff */ -+ xf_emit(ctx, 1, 0); /* 1ff */ -+ xf_emit(ctx, 8, 0); /* 0? */ -+ xf_emit(ctx, 9, 0); /* ffffffff, 7ff */ -+ } -+ else -+ { -+ xf_emit(ctx, 0xc, 0); /* RO */ -+ /* SEEK */ -+ xf_emit(ctx, 0xe10, 0); /* 190 * 9: 8*ffffffff, 7ff */ -+ xf_emit(ctx, 1, 0); /* 1ff */ -+ xf_emit(ctx, 8, 0); /* 0? */ -+ -+ /* SEEK */ -+ xf_emit(ctx, 0xc, 0); /* RO */ -+ /* SEEK */ -+ xf_emit(ctx, 0xe10, 0); /* 190 * 9: 8*ffffffff, 7ff */ -+ xf_emit(ctx, 1, 0); /* 1ff */ -+ xf_emit(ctx, 8, 0); /* 0? */ -+ } -+ /* SEEK */ -+ xf_emit(ctx, 1, 0); /* 00000001 GP_ENABLE */ -+ 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) -- xf_emit(ctx, 1, 3); -- xf_emit(ctx, 1, 0); -- xf_emit(ctx, 1, 0x8100c12); -- xf_emit(ctx, 1, 0); -- xf_emit(ctx, 1, 0x80c14); -- xf_emit(ctx, 1, 1); -+ xf_emit(ctx, 1, 3); /* 00000003 tesla UNK1100 */ -+ /* SEEK */ -+ xf_emit(ctx, 1, 0); /* 00000001 GP_ENABLE */ -+ xf_emit(ctx, 1, 0x8100c12); /* 1fffffff FP_INTERPOLANT_CTRL */ -+ xf_emit(ctx, 1, 0); /* 0000000f VP_GP_BUILTIN_ATTR_EN */ -+ xf_emit(ctx, 1, 0x80c14); /* 01ffffff SEMANTIC_COLOR */ -+ xf_emit(ctx, 1, 1); /* 00000001 */ -+ /* SEEK */ - if (dev_priv->chipset >= 0xa0) -- xf_emit(ctx, 2, 4); -- xf_emit(ctx, 1, 0x80c14); -- xf_emit(ctx, 2, 0); -- xf_emit(ctx, 1, 0x8100c12); -- xf_emit(ctx, 1, 0x27); -- xf_emit(ctx, 2, 0); -- xf_emit(ctx, 1, 1); -- xf_emit(ctx, 0x3c1, 0); -- xf_emit(ctx, 1, 1); -- xf_emit(ctx, 0x16, 0); -- xf_emit(ctx, 1, 0x8100c12); -- xf_emit(ctx, 1, 0); -+ xf_emit(ctx, 2, 4); /* 000000ff */ -+ xf_emit(ctx, 1, 0x80c14); /* 01ffffff SEMANTIC_COLOR */ -+ xf_emit(ctx, 1, 0); /* 00000001 VERTEX_TWO_SIDE_ENABLE */ -+ xf_emit(ctx, 1, 0); /* 00000001 POINT_SPRITE_ENABLE */ -+ xf_emit(ctx, 1, 0x8100c12); /* 1fffffff FP_INTERPOLANT_CTRL */ -+ xf_emit(ctx, 1, 0x27); /* 000000ff SEMANTIC_PRIM_ID */ -+ xf_emit(ctx, 1, 0); /* 00000001 GP_ENABLE */ -+ xf_emit(ctx, 1, 0); /* 0000000f */ -+ xf_emit(ctx, 1, 1); /* 00000001 */ -+ for (i = 0; i < 10; i++) { -+ /* SEEK */ -+ xf_emit(ctx, 0x40, 0); /* ffffffff */ -+ xf_emit(ctx, 0x10, 0); /* 3, 0, 0.... */ -+ xf_emit(ctx, 0x10, 0); /* ffffffff */ -+ } -+ /* SEEK */ -+ xf_emit(ctx, 1, 0); /* 00000001 POINT_SPRITE_CTRL */ -+ xf_emit(ctx, 1, 1); /* 00000001 */ -+ xf_emit(ctx, 1, 0); /* ffffffff */ -+ xf_emit(ctx, 4, 0); /* ffffffff NOPERSPECTIVE_BITMAP */ -+ 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) -+ xf_emit(ctx, 1, 0); /* 000003ff */ - } - - static void --nv50_graph_construct_gene_unk6(struct nouveau_grctx *ctx) -+nv50_graph_construct_gene_vfetch(struct nouveau_grctx *ctx) - { - struct drm_nouveau_private *dev_priv = ctx->dev->dev_private; -- /* beginning of area 1 on pre-NVA0 [after m2mf], area 3 on NVAx */ -- xf_emit(ctx, 4, 0); -- xf_emit(ctx, 1, 0xf); -- if (dev_priv->chipset > 0xa0 && dev_priv->chipset < 0xaa) -- xf_emit(ctx, 8, 0); -- else -- xf_emit(ctx, 4, 0); -- xf_emit(ctx, 1, 0x20); -- if (dev_priv->chipset > 0xa0 && dev_priv->chipset < 0xaa) -- xf_emit(ctx, 0x11, 0); -+ int acnt = 0x10, rep, i; -+ /* beginning of strand 1 on pre-NVA0, strand 3 on NVAx */ -+ if (IS_NVA3F(dev_priv->chipset)) -+ acnt = 0x20; -+ /* SEEK */ -+ if (dev_priv->chipset >= 0xa0) { -+ xf_emit(ctx, 1, 0); /* ffffffff tesla UNK13A4 */ -+ xf_emit(ctx, 1, 1); /* 00000fff tesla UNK1318 */ -+ } -+ xf_emit(ctx, 1, 0); /* ffffffff VERTEX_BUFFER_FIRST */ -+ xf_emit(ctx, 1, 0); /* 00000001 PRIMITIVE_RESTART_ENABLE */ -+ xf_emit(ctx, 1, 0); /* 00000001 UNK0DE8 */ -+ xf_emit(ctx, 1, 0); /* ffffffff PRIMITIVE_RESTART_INDEX */ -+ xf_emit(ctx, 1, 0xf); /* ffffffff VP_ATTR_EN */ -+ xf_emit(ctx, (acnt/8)-1, 0); /* ffffffff VP_ATTR_EN */ -+ xf_emit(ctx, acnt/8, 0); /* ffffffff VTX_ATR_MASK_UNK0DD0 */ -+ xf_emit(ctx, 1, 0); /* 0000000f VP_GP_BUILTIN_ATTR_EN */ -+ xf_emit(ctx, 1, 0x20); /* 0000ffff tesla UNK129C */ -+ xf_emit(ctx, 1, 0); /* 000000ff turing UNK370??? */ -+ 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)) -+ xf_emit(ctx, 0xb, 0); /* RO */ - else if (dev_priv->chipset >= 0xa0) -- xf_emit(ctx, 0xf, 0); -+ xf_emit(ctx, 0x9, 0); /* RO */ - else -- xf_emit(ctx, 0xe, 0); -- xf_emit(ctx, 1, 0x1a); -- xf_emit(ctx, 0xd, 0); -- xf_emit(ctx, 2, 4); -- xf_emit(ctx, 1, 0); -- xf_emit(ctx, 1, 4); -- xf_emit(ctx, 1, 8); -- xf_emit(ctx, 1, 0); -+ xf_emit(ctx, 0x8, 0); /* RO */ -+ /* SEEK */ -+ xf_emit(ctx, 1, 0); /* 00000001 EDGE_FLAG */ -+ xf_emit(ctx, 1, 0); /* 00000001 PROVOKING_VERTEX_LAST */ -+ xf_emit(ctx, 1, 0); /* 00000001 GP_ENABLE */ -+ xf_emit(ctx, 1, 0x1a); /* 0000001f POLYGON_MODE */ -+ /* SEEK */ -+ xf_emit(ctx, 0xc, 0); /* RO */ -+ /* SEEK */ -+ xf_emit(ctx, 1, 0); /* 7f/ff */ -+ xf_emit(ctx, 1, 4); /* 7f/ff VP_REG_ALLOC_RESULT */ -+ xf_emit(ctx, 1, 4); /* 7f/ff VP_RESULT_MAP_SIZE */ -+ xf_emit(ctx, 1, 0); /* 0000000f VP_GP_BUILTIN_ATTR_EN */ -+ 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) -- xf_emit(ctx, 1, 0x3ff); -+ xf_emit(ctx, 1, 0x3ff); /* 3ff tesla UNK0D68 */ - else -- xf_emit(ctx, 1, 0x7ff); -+ xf_emit(ctx, 1, 0x7ff); /* 7ff tesla UNK0D68 */ - if (dev_priv->chipset == 0xa8) -- xf_emit(ctx, 1, 0x1e00); -- xf_emit(ctx, 0xc, 0); -- xf_emit(ctx, 1, 0xf); -- if (dev_priv->chipset == 0x50) -- xf_emit(ctx, 0x125, 0); -- else if (dev_priv->chipset < 0xa0) -- xf_emit(ctx, 0x126, 0); -- else if (dev_priv->chipset == 0xa0 || dev_priv->chipset >= 0xaa) -- xf_emit(ctx, 0x124, 0); -- else -- xf_emit(ctx, 0x1f7, 0); -- xf_emit(ctx, 1, 0xf); -- if (dev_priv->chipset > 0xa0 && dev_priv->chipset < 0xaa) -- xf_emit(ctx, 3, 0); -- else -- xf_emit(ctx, 1, 0); -- xf_emit(ctx, 1, 1); -- if (dev_priv->chipset > 0xa0 && dev_priv->chipset < 0xaa) -- xf_emit(ctx, 0xa1, 0); -- else -- xf_emit(ctx, 0x5a, 0); -- xf_emit(ctx, 1, 0xf); -+ xf_emit(ctx, 1, 0x1e00); /* 7fff */ -+ /* SEEK */ -+ xf_emit(ctx, 0xc, 0); /* RO or close */ -+ /* SEEK */ -+ 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) -+ 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)) { -+ xf_emit(ctx, 0x10, 0); /* 0? */ -+ xf_emit(ctx, 2, 0); /* weird... */ -+ xf_emit(ctx, 2, 0); /* RO */ -+ } else { -+ xf_emit(ctx, 8, 0); /* 0? */ -+ xf_emit(ctx, 1, 0); /* weird... */ -+ xf_emit(ctx, 2, 0); /* RO */ -+ } -+ /* SEEK */ -+ 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) -+ xf_emit(ctx, 1, 0); /* ffffffff tesla UNK1118? */ -+ /* SEEK */ -+ xf_emit(ctx, acnt, 0); /* ffffffff VERTEX_ARRAY_UNK90C */ -+ xf_emit(ctx, 1, 0); /* f/1f */ -+ /* SEEK */ -+ xf_emit(ctx, acnt, 0); /* ffffffff VERTEX_ARRAY_UNK90C */ -+ xf_emit(ctx, 1, 0); /* f/1f */ -+ /* SEEK */ -+ xf_emit(ctx, acnt, 0); /* RO */ -+ xf_emit(ctx, 2, 0); /* RO */ -+ /* SEEK */ -+ xf_emit(ctx, 1, 0); /* ffffffff tesla UNK111C? */ -+ xf_emit(ctx, 1, 0); /* RO */ -+ /* SEEK */ -+ xf_emit(ctx, 1, 0); /* 000000ff UNK15F4_ADDRESS_HIGH */ -+ xf_emit(ctx, 1, 0); /* ffffffff UNK15F4_ADDRESS_LOW */ -+ xf_emit(ctx, 1, 0); /* 000000ff UNK0F84_ADDRESS_HIGH */ -+ xf_emit(ctx, 1, 0); /* ffffffff UNK0F84_ADDRESS_LOW */ -+ /* SEEK */ -+ xf_emit(ctx, acnt, 0); /* 00003fff VERTEX_ARRAY_ATTRIB_OFFSET */ -+ xf_emit(ctx, 3, 0); /* f/1f */ -+ /* SEEK */ -+ xf_emit(ctx, acnt, 0); /* 00000fff VERTEX_ARRAY_STRIDE */ -+ xf_emit(ctx, 3, 0); /* f/1f */ -+ /* SEEK */ -+ xf_emit(ctx, acnt, 0); /* ffffffff VERTEX_ARRAY_LOW */ -+ xf_emit(ctx, 3, 0); /* f/1f */ -+ /* SEEK */ -+ xf_emit(ctx, acnt, 0); /* 000000ff VERTEX_ARRAY_HIGH */ -+ xf_emit(ctx, 3, 0); /* f/1f */ -+ /* SEEK */ -+ xf_emit(ctx, acnt, 0); /* ffffffff VERTEX_LIMIT_LOW */ -+ xf_emit(ctx, 3, 0); /* f/1f */ -+ /* SEEK */ -+ xf_emit(ctx, acnt, 0); /* 000000ff VERTEX_LIMIT_HIGH */ -+ xf_emit(ctx, 3, 0); /* f/1f */ -+ /* SEEK */ -+ if (IS_NVA3F(dev_priv->chipset)) { -+ xf_emit(ctx, acnt, 0); /* f */ -+ xf_emit(ctx, 3, 0); /* f/1f */ -+ } -+ /* SEEK */ -+ if (IS_NVA3F(dev_priv->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) { -+ xf_emit(ctx, 0x41, 0); /* RO */ -+ /* SEEK */ -+ xf_emit(ctx, 0x11, 0); /* RO */ -+ } else if (!IS_NVA3F(dev_priv->chipset)) -+ xf_emit(ctx, 0x50, 0); /* RO */ -+ else -+ xf_emit(ctx, 0x58, 0); /* RO */ -+ /* SEEK */ -+ xf_emit(ctx, 1, 0xf); /* ffffffff VP_ATTR_EN */ -+ xf_emit(ctx, (acnt/8)-1, 0); /* ffffffff VP_ATTR_EN */ -+ xf_emit(ctx, 1, 1); /* 1 UNK0DEC */ -+ /* SEEK */ -+ 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)) -+ xf_emit(ctx, 0x1d, 0); /* RO */ -+ else -+ xf_emit(ctx, 0x16, 0); /* RO */ -+ /* SEEK */ -+ 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) -- xf_emit(ctx, 0x834, 0); -- else if (dev_priv->chipset == 0xa0) -- xf_emit(ctx, 0x1873, 0); -- else if (dev_priv->chipset > 0xa0 && dev_priv->chipset < 0xaa) -- xf_emit(ctx, 0x8ba, 0); -+ xf_emit(ctx, 8, 0); /* RO */ -+ else if (IS_NVA3F(dev_priv->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) -+ rep = 0xc; -+ else -+ rep = 4; -+ for (i = 0; i < rep; i++) { -+ /* SEEK */ -+ if (IS_NVA3F(dev_priv->chipset)) -+ xf_emit(ctx, 0x20, 0); /* ffffffff */ -+ xf_emit(ctx, 0x200, 0); /* ffffffff */ -+ xf_emit(ctx, 4, 0); /* 7f/ff, 0, 0, 0 */ -+ xf_emit(ctx, 4, 0); /* ffffffff */ -+ } -+ /* SEEK */ -+ xf_emit(ctx, 1, 0); /* 113/111 */ -+ xf_emit(ctx, 1, 0xf); /* ffffffff VP_ATTR_EN */ -+ xf_emit(ctx, (acnt/8)-1, 0); /* ffffffff VP_ATTR_EN */ -+ xf_emit(ctx, acnt/8, 0); /* ffffffff VTX_ATTR_MASK_UNK0DD0 */ -+ 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)) -+ xf_emit(ctx, 7, 0); /* weird... */ - else -- xf_emit(ctx, 0x833, 0); -- xf_emit(ctx, 1, 0xf); -- xf_emit(ctx, 0xf, 0); -+ xf_emit(ctx, 5, 0); /* weird... */ - } - - static void --nv50_graph_construct_gene_unk7(struct nouveau_grctx *ctx) -+nv50_graph_construct_gene_eng2d(struct nouveau_grctx *ctx) - { - struct drm_nouveau_private *dev_priv = ctx->dev->dev_private; -- /* middle of area 1 on pre-NVA0 [after m2mf], middle of area 6 on NVAx */ -- xf_emit(ctx, 2, 0); -- if (dev_priv->chipset == 0x50) -- xf_emit(ctx, 2, 1); -- else -- xf_emit(ctx, 2, 0); -- xf_emit(ctx, 1, 0); -- xf_emit(ctx, 1, 1); -- xf_emit(ctx, 2, 0x100); -- xf_emit(ctx, 1, 0x11); -- xf_emit(ctx, 1, 0); -- xf_emit(ctx, 1, 8); -- xf_emit(ctx, 5, 0); -- xf_emit(ctx, 1, 1); -- xf_emit(ctx, 1, 0); -- xf_emit(ctx, 3, 1); -- xf_emit(ctx, 1, 0xcf); -- xf_emit(ctx, 1, 2); -- xf_emit(ctx, 6, 0); -- xf_emit(ctx, 1, 1); -- xf_emit(ctx, 1, 0); -- xf_emit(ctx, 3, 1); -- xf_emit(ctx, 4, 0); -- xf_emit(ctx, 1, 4); -- xf_emit(ctx, 1, 0); -- xf_emit(ctx, 1, 1); -- xf_emit(ctx, 1, 0x15); -- xf_emit(ctx, 3, 0); -- xf_emit(ctx, 1, 0x4444480); -- xf_emit(ctx, 0x37, 0); -+ /* 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) { -+ /* 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 */ -+ xf_emit(ctx, 2, 1); /* 0000ffff IFC_CLIP_W, H */ -+ xf_emit(ctx, 1, 0); /* 00000001 IFC_CLIP_ENABLE */ -+ } -+ xf_emit(ctx, 1, 1); /* 00000001 DST_LINEAR */ -+ xf_emit(ctx, 1, 0x100); /* 0001ffff DST_WIDTH */ -+ xf_emit(ctx, 1, 0x100); /* 0001ffff DST_HEIGHT */ -+ xf_emit(ctx, 1, 0x11); /* 3f[NV50]/7f[NV84+] DST_FORMAT */ -+ xf_emit(ctx, 1, 0); /* 0001ffff DRAW_POINT_X */ -+ xf_emit(ctx, 1, 8); /* 0000000f DRAW_UNK58C */ -+ xf_emit(ctx, 1, 0); /* 000fffff SIFC_DST_X_FRACT */ -+ xf_emit(ctx, 1, 0); /* 0001ffff SIFC_DST_X_INT */ -+ xf_emit(ctx, 1, 0); /* 000fffff SIFC_DST_Y_FRACT */ -+ xf_emit(ctx, 1, 0); /* 0001ffff SIFC_DST_Y_INT */ -+ xf_emit(ctx, 1, 0); /* 000fffff SIFC_DX_DU_FRACT */ -+ xf_emit(ctx, 1, 1); /* 0001ffff SIFC_DX_DU_INT */ -+ xf_emit(ctx, 1, 0); /* 000fffff SIFC_DY_DV_FRACT */ -+ xf_emit(ctx, 1, 1); /* 0001ffff SIFC_DY_DV_INT */ -+ xf_emit(ctx, 1, 1); /* 0000ffff SIFC_WIDTH */ -+ xf_emit(ctx, 1, 1); /* 0000ffff SIFC_HEIGHT */ -+ xf_emit(ctx, 1, 0xcf); /* 000000ff SIFC_FORMAT */ -+ xf_emit(ctx, 1, 2); /* 00000003 SIFC_BITMAP_UNK808 */ -+ xf_emit(ctx, 1, 0); /* 00000003 SIFC_BITMAP_LINE_PACK_MODE */ -+ xf_emit(ctx, 1, 0); /* 00000001 SIFC_BITMAP_LSB_FIRST */ -+ xf_emit(ctx, 1, 0); /* 00000001 SIFC_BITMAP_ENABLE */ -+ xf_emit(ctx, 1, 0); /* 0000ffff BLIT_DST_X */ -+ xf_emit(ctx, 1, 0); /* 0000ffff BLIT_DST_Y */ -+ xf_emit(ctx, 1, 0); /* 000fffff BLIT_DU_DX_FRACT */ -+ xf_emit(ctx, 1, 1); /* 0001ffff BLIT_DU_DX_INT */ -+ xf_emit(ctx, 1, 0); /* 000fffff BLIT_DV_DY_FRACT */ -+ xf_emit(ctx, 1, 1); /* 0001ffff BLIT_DV_DY_INT */ -+ xf_emit(ctx, 1, 1); /* 0000ffff BLIT_DST_W */ -+ xf_emit(ctx, 1, 1); /* 0000ffff BLIT_DST_H */ -+ xf_emit(ctx, 1, 0); /* 000fffff BLIT_SRC_X_FRACT */ -+ xf_emit(ctx, 1, 0); /* 0001ffff BLIT_SRC_X_INT */ -+ xf_emit(ctx, 1, 0); /* 000fffff BLIT_SRC_Y_FRACT */ -+ xf_emit(ctx, 1, 0); /* 00000001 UNK888 */ -+ xf_emit(ctx, 1, 4); /* 0000003f UNK884 */ -+ xf_emit(ctx, 1, 0); /* 00000007 UNK880 */ -+ xf_emit(ctx, 1, 1); /* 0000001f tesla UNK0FB8 */ -+ xf_emit(ctx, 1, 0x15); /* 000000ff tesla UNK128C */ -+ xf_emit(ctx, 2, 0); /* 00000007, ffff0ff3 */ -+ xf_emit(ctx, 1, 0); /* 00000001 UNK260 */ -+ xf_emit(ctx, 1, 0x4444480); /* 1fffffff UNK870 */ -+ /* SEEK */ -+ xf_emit(ctx, 0x10, 0); -+ /* SEEK */ -+ xf_emit(ctx, 0x27, 0); - } - - static void --nv50_graph_construct_gene_unk8(struct nouveau_grctx *ctx) -+nv50_graph_construct_gene_csched(struct nouveau_grctx *ctx) - { -- /* middle of area 1 on pre-NVA0 [after m2mf], middle of area 0 on NVAx */ -- xf_emit(ctx, 4, 0); -- xf_emit(ctx, 1, 0x8100c12); -- xf_emit(ctx, 4, 0); -- xf_emit(ctx, 1, 0x100); -- xf_emit(ctx, 2, 0); -- xf_emit(ctx, 1, 0x10001); -- xf_emit(ctx, 1, 0); -- xf_emit(ctx, 1, 0x10001); -- xf_emit(ctx, 1, 1); -- xf_emit(ctx, 1, 0x10001); -- xf_emit(ctx, 1, 1); -- xf_emit(ctx, 1, 4); -- xf_emit(ctx, 1, 2); -+ struct drm_nouveau_private *dev_priv = ctx->dev->dev_private; -+ /* 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??? */ -+ xf_emit(ctx, 1, 0); /* 00000001 tesla UNK1924 */ -+ xf_emit(ctx, 1, 0); /* 00000003 WINDOW_ORIGIN */ -+ xf_emit(ctx, 1, 0x8100c12); /* 1fffffff FP_INTERPOLANT_CTRL */ -+ xf_emit(ctx, 1, 0); /* 000003ff */ -+ /* SEEK */ -+ xf_emit(ctx, 1, 0); /* ffffffff turing UNK364 */ -+ xf_emit(ctx, 1, 0); /* 0000000f turing UNK36C */ -+ xf_emit(ctx, 1, 0); /* 0000ffff USER_PARAM_COUNT */ -+ xf_emit(ctx, 1, 0x100); /* 00ffffff turing UNK384 */ -+ xf_emit(ctx, 1, 0); /* 0000000f turing UNK2A0 */ -+ xf_emit(ctx, 1, 0); /* 0000ffff GRIDID */ -+ xf_emit(ctx, 1, 0x10001); /* ffffffff GRIDDIM_XY */ -+ xf_emit(ctx, 1, 0); /* ffffffff */ -+ xf_emit(ctx, 1, 0x10001); /* ffffffff BLOCKDIM_XY */ -+ xf_emit(ctx, 1, 1); /* 0000ffff BLOCKDIM_Z */ -+ xf_emit(ctx, 1, 0x10001); /* 00ffffff BLOCK_ALLOC */ -+ xf_emit(ctx, 1, 1); /* 00000001 LANES32 */ -+ xf_emit(ctx, 1, 4); /* 000000ff FP_REG_ALLOC_TEMP */ -+ xf_emit(ctx, 1, 2); /* 00000003 REG_MODE */ -+ /* SEEK */ -+ xf_emit(ctx, 0x40, 0); /* ffffffff USER_PARAM */ -+ switch (dev_priv->chipset) { -+ case 0x50: -+ case 0x92: -+ xf_emit(ctx, 8, 0); /* 7, 0, 0, 0, ... */ -+ xf_emit(ctx, 0x80, 0); /* fff */ -+ xf_emit(ctx, 2, 0); /* ff, fff */ -+ xf_emit(ctx, 0x10*2, 0); /* ffffffff, 1f */ -+ break; -+ case 0x84: -+ xf_emit(ctx, 8, 0); /* 7, 0, 0, 0, ... */ -+ xf_emit(ctx, 0x60, 0); /* fff */ -+ xf_emit(ctx, 2, 0); /* ff, fff */ -+ xf_emit(ctx, 0xc*2, 0); /* ffffffff, 1f */ -+ break; -+ case 0x94: -+ case 0x96: -+ xf_emit(ctx, 8, 0); /* 7, 0, 0, 0, ... */ -+ xf_emit(ctx, 0x40, 0); /* fff */ -+ xf_emit(ctx, 2, 0); /* ff, fff */ -+ xf_emit(ctx, 8*2, 0); /* ffffffff, 1f */ -+ break; -+ case 0x86: -+ case 0x98: -+ xf_emit(ctx, 4, 0); /* f, 0, 0, 0 */ -+ xf_emit(ctx, 0x10, 0); /* fff */ -+ xf_emit(ctx, 2, 0); /* ff, fff */ -+ xf_emit(ctx, 2*2, 0); /* ffffffff, 1f */ -+ break; -+ case 0xa0: -+ xf_emit(ctx, 8, 0); /* 7, 0, 0, 0, ... */ -+ xf_emit(ctx, 0xf0, 0); /* fff */ -+ xf_emit(ctx, 2, 0); /* ff, fff */ -+ xf_emit(ctx, 0x1e*2, 0); /* ffffffff, 1f */ -+ break; -+ case 0xa3: -+ xf_emit(ctx, 8, 0); /* 7, 0, 0, 0, ... */ -+ xf_emit(ctx, 0x60, 0); /* fff */ -+ xf_emit(ctx, 2, 0); /* ff, fff */ -+ xf_emit(ctx, 0xc*2, 0); /* ffffffff, 1f */ -+ break; -+ case 0xa5: -+ case 0xaf: -+ xf_emit(ctx, 8, 0); /* 7, 0, 0, 0, ... */ -+ xf_emit(ctx, 0x30, 0); /* fff */ -+ xf_emit(ctx, 2, 0); /* ff, fff */ -+ xf_emit(ctx, 6*2, 0); /* ffffffff, 1f */ -+ break; -+ case 0xaa: -+ xf_emit(ctx, 0x12, 0); -+ break; -+ case 0xa8: -+ case 0xac: -+ xf_emit(ctx, 4, 0); /* f, 0, 0, 0 */ -+ xf_emit(ctx, 0x10, 0); /* fff */ -+ xf_emit(ctx, 2, 0); /* ff, fff */ -+ xf_emit(ctx, 2*2, 0); /* ffffffff, 1f */ -+ break; -+ } -+ xf_emit(ctx, 1, 0); /* 0000000f */ -+ xf_emit(ctx, 1, 0); /* 00000000 */ -+ xf_emit(ctx, 1, 0); /* ffffffff */ -+ xf_emit(ctx, 1, 0); /* 0000001f */ -+ xf_emit(ctx, 4, 0); /* ffffffff */ -+ xf_emit(ctx, 1, 0); /* 00000003 turing UNK35C */ -+ xf_emit(ctx, 1, 0); /* ffffffff */ -+ xf_emit(ctx, 4, 0); /* ffffffff */ -+ xf_emit(ctx, 1, 0); /* 00000003 turing UNK35C */ -+ xf_emit(ctx, 1, 0); /* ffffffff */ -+ xf_emit(ctx, 1, 0); /* 000000ff */ - } - - static void --nv50_graph_construct_gene_unk9(struct nouveau_grctx *ctx) -+nv50_graph_construct_gene_unk1cxx(struct nouveau_grctx *ctx) - { - struct drm_nouveau_private *dev_priv = ctx->dev->dev_private; -- /* middle of area 2 on pre-NVA0 [after m2mf], end of area 0 on NVAx */ -- xf_emit(ctx, 1, 0x3f800000); -- xf_emit(ctx, 6, 0); -- xf_emit(ctx, 1, 4); -- xf_emit(ctx, 1, 0x1a); -- xf_emit(ctx, 2, 0); -- xf_emit(ctx, 1, 1); -- xf_emit(ctx, 0x12, 0); -- xf_emit(ctx, 1, 0x00ffff00); -- xf_emit(ctx, 6, 0); -- xf_emit(ctx, 1, 0xf); -- xf_emit(ctx, 7, 0); -- xf_emit(ctx, 1, 0x0fac6881); -- xf_emit(ctx, 1, 0x11); -- xf_emit(ctx, 0xf, 0); -- xf_emit(ctx, 1, 4); -- xf_emit(ctx, 2, 0); -- if (dev_priv->chipset > 0xa0 && dev_priv->chipset < 0xaa) -- xf_emit(ctx, 1, 3); -+ 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 */ -+ xf_emit(ctx, 1, 0); /* 00000001 tesla UNK1658 */ -+ xf_emit(ctx, 1, 0); /* 00000001 POLYGON_SMOOTH_ENABLE */ -+ xf_emit(ctx, 3, 0); /* 00000001 POLYGON_OFFSET_*_ENABLE */ -+ xf_emit(ctx, 1, 4); /* 0000000f CULL_MODE */ -+ xf_emit(ctx, 1, 0x1a); /* 0000001f POLYGON_MODE */ -+ xf_emit(ctx, 1, 0); /* 0000000f ZETA_FORMAT */ -+ xf_emit(ctx, 1, 0); /* 00000001 POINT_SPRITE_ENABLE */ -+ xf_emit(ctx, 1, 1); /* 00000001 tesla UNK165C */ -+ xf_emit(ctx, 0x10, 0); /* 00000001 SCISSOR_ENABLE */ -+ xf_emit(ctx, 1, 0); /* 00000001 tesla UNK1534 */ -+ xf_emit(ctx, 1, 0); /* 00000001 LINE_STIPPLE_ENABLE */ -+ xf_emit(ctx, 1, 0x00ffff00); /* 00ffffff LINE_STIPPLE_PATTERN */ -+ xf_emit(ctx, 1, 0); /* ffffffff POLYGON_OFFSET_UNITS */ -+ xf_emit(ctx, 1, 0); /* ffffffff POLYGON_OFFSET_FACTOR */ -+ xf_emit(ctx, 1, 0); /* 00000003 tesla UNK1668 */ -+ xf_emit(ctx, 2, 0); /* 07ffffff SCREEN_SCISSOR */ -+ xf_emit(ctx, 1, 0); /* 00000001 tesla UNK1900 */ -+ xf_emit(ctx, 1, 0xf); /* 0000000f COLOR_MASK */ -+ xf_emit(ctx, 7, 0); /* 0000000f COLOR_MASK */ -+ xf_emit(ctx, 1, 0x0fac6881); /* 0fffffff RT_CONTROL */ -+ xf_emit(ctx, 1, 0x11); /* 0000007f RT_FORMAT */ -+ xf_emit(ctx, 7, 0); /* 0000007f RT_FORMAT */ -+ xf_emit(ctx, 8, 0); /* 00000001 RT_HORIZ_LINEAR */ -+ 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)) -+ xf_emit(ctx, 1, 3); /* 00000003 UNK16B4 */ - else if (dev_priv->chipset >= 0xa0) -- xf_emit(ctx, 1, 1); -- xf_emit(ctx, 2, 0); -- xf_emit(ctx, 1, 2); -- xf_emit(ctx, 2, 0x04000000); -- xf_emit(ctx, 3, 0); -- xf_emit(ctx, 1, 5); -- xf_emit(ctx, 1, 0x52); -- if (dev_priv->chipset == 0x50) { -- xf_emit(ctx, 0x13, 0); -- } else { -- xf_emit(ctx, 4, 0); -- xf_emit(ctx, 1, 1); -- if (dev_priv->chipset > 0xa0 && dev_priv->chipset < 0xaa) -- xf_emit(ctx, 0x11, 0); -- else -- xf_emit(ctx, 0x10, 0); -+ xf_emit(ctx, 1, 1); /* 00000001 UNK16B4 */ -+ xf_emit(ctx, 1, 0); /* 00000003 MULTISAMPLE_CTRL */ -+ xf_emit(ctx, 1, 0); /* 00000003 tesla UNK0F90 */ -+ xf_emit(ctx, 1, 2); /* 00000003 tesla UNK143C */ -+ xf_emit(ctx, 2, 0x04000000); /* 07ffffff tesla UNK0D6C */ -+ xf_emit(ctx, 1, 0); /* 000000ff STENCIL_FRONT_MASK */ -+ xf_emit(ctx, 1, 0); /* 00000001 DEPTH_WRITE_ENABLE */ -+ xf_emit(ctx, 1, 0); /* 00000001 SAMPLECNT_ENABLE */ -+ xf_emit(ctx, 1, 5); /* 0000000f UNK1408 */ -+ xf_emit(ctx, 1, 0x52); /* 000001ff SEMANTIC_PTSZ */ -+ 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) { -+ xf_emit(ctx, 1, 0); /* 3ff */ -+ xf_emit(ctx, 1, 1); /* 00000001 tesla UNK1110 */ - } -- xf_emit(ctx, 0x10, 0x3f800000); -- xf_emit(ctx, 1, 0x10); -- xf_emit(ctx, 0x26, 0); -- xf_emit(ctx, 1, 0x8100c12); -- xf_emit(ctx, 1, 5); -- xf_emit(ctx, 2, 0); -- xf_emit(ctx, 1, 1); -- xf_emit(ctx, 1, 0); -- xf_emit(ctx, 4, 0xffff); -+ if (IS_NVA3F(dev_priv->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 */ -+ xf_emit(ctx, 1, 0x10); /* 000000ff VIEW_VOLUME_CLIP_CTRL */ -+ xf_emit(ctx, 0x20, 0); /* 07ffffff VIEWPORT_HORIZ, then VIEWPORT_VERT. (W&0x3fff)<<13 | (X&0x1fff). */ -+ xf_emit(ctx, 1, 0); /* ffffffff tesla UNK187C */ -+ xf_emit(ctx, 1, 0); /* 00000003 WINDOW_ORIGIN */ -+ xf_emit(ctx, 1, 0); /* 00000001 STENCIL_FRONT_ENABLE */ -+ xf_emit(ctx, 1, 0); /* 00000001 DEPTH_TEST_ENABLE */ -+ xf_emit(ctx, 1, 0); /* 00000001 STENCIL_BACK_ENABLE */ -+ xf_emit(ctx, 1, 0); /* 000000ff STENCIL_BACK_MASK */ -+ xf_emit(ctx, 1, 0x8100c12); /* 1fffffff FP_INTERPOLANT_CTRL */ -+ xf_emit(ctx, 1, 5); /* 0000000f tesla UNK1220 */ -+ xf_emit(ctx, 1, 0); /* 00000007 MULTISAMPLE_SAMPLES_LOG2 */ -+ xf_emit(ctx, 1, 0); /* 000000ff tesla UNK1A20 */ -+ 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) -- xf_emit(ctx, 1, 3); -+ xf_emit(ctx, 1, 3); /* 00000003 tesla UNK1100 */ - if (dev_priv->chipset < 0xa0) -- xf_emit(ctx, 0x1f, 0); -- else if (dev_priv->chipset > 0xa0 && dev_priv->chipset < 0xaa) -- xf_emit(ctx, 0xc, 0); -- else -- xf_emit(ctx, 3, 0); -- xf_emit(ctx, 1, 0x00ffff00); -- xf_emit(ctx, 1, 0x1a); -+ xf_emit(ctx, 0x1c, 0); /* RO */ -+ else if (IS_NVA3F(dev_priv->chipset)) -+ xf_emit(ctx, 0x9, 0); -+ xf_emit(ctx, 1, 0); /* 00000001 UNK1534 */ -+ xf_emit(ctx, 1, 0); /* 00000001 LINE_SMOOTH_ENABLE */ -+ xf_emit(ctx, 1, 0); /* 00000001 LINE_STIPPLE_ENABLE */ -+ 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) { -- xf_emit(ctx, 1, 0); -- xf_emit(ctx, 1, 3); -+ 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) -- xf_emit(ctx, 0x26, 0); -- else -- xf_emit(ctx, 0x3c, 0); -- xf_emit(ctx, 1, 0x102); -- xf_emit(ctx, 1, 0); -- xf_emit(ctx, 4, 4); -- if (dev_priv->chipset >= 0xa0) -- xf_emit(ctx, 8, 0); -- xf_emit(ctx, 2, 4); -- xf_emit(ctx, 1, 0); -- if (dev_priv->chipset == 0x50) -- xf_emit(ctx, 1, 0x3ff); -+ xf_emit(ctx, 0x25, 0); - else -- xf_emit(ctx, 1, 0x7ff); -- xf_emit(ctx, 1, 0); -- xf_emit(ctx, 1, 0x102); -- xf_emit(ctx, 9, 0); -- xf_emit(ctx, 4, 4); -- xf_emit(ctx, 0x2c, 0); -+ xf_emit(ctx, 0x3b, 0); -+} -+ -+static void -+nv50_graph_construct_gene_strmout(struct nouveau_grctx *ctx) -+{ -+ struct drm_nouveau_private *dev_priv = ctx->dev->dev_private; -+ 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) { -+ 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) -+ xf_emit(ctx, 1, 0x3ff); /* 000003ff tesla UNK0D68 */ -+ else -+ xf_emit(ctx, 1, 0x7ff); /* 000007ff tesla UNK0D68 */ -+ xf_emit(ctx, 1, 0); /* ffffffff tesla UNK1A30 */ -+ /* SEEK */ -+ xf_emit(ctx, 1, 0x102); /* 0000ffff STRMOUT_BUFFER_CTRL */ -+ xf_emit(ctx, 1, 0); /* ffffffff STRMOUT_PRIMITIVE_COUNT */ -+ 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) { -+ xf_emit(ctx, 4, 0); /* ffffffff UNK1A8C */ -+ xf_emit(ctx, 4, 0); /* ffffffff UNK1780 */ -+ } -+ xf_emit(ctx, 1, 0); /* 0000ffff DMA_STRMOUT */ -+ xf_emit(ctx, 1, 0); /* 0000ffff DMA_QUERY */ -+ xf_emit(ctx, 1, 0); /* 000000ff QUERY_ADDRESS_HIGH */ -+ xf_emit(ctx, 2, 0); /* ffffffff QUERY_ADDRESS_LOW QUERY_COUNTER */ -+ xf_emit(ctx, 2, 0); /* ffffffff */ -+ xf_emit(ctx, 1, 0); /* ffffffff tesla UNK1A30 */ -+ /* SEEK */ -+ xf_emit(ctx, 0x20, 0); /* ffffffff STRMOUT_MAP */ -+ xf_emit(ctx, 1, 0); /* 0000000f */ -+ xf_emit(ctx, 1, 0); /* 00000000? */ -+ xf_emit(ctx, 2, 0); /* ffffffff */ -+} -+ -+static void -+nv50_graph_construct_gene_ropm1(struct nouveau_grctx *ctx) -+{ -+ struct drm_nouveau_private *dev_priv = ctx->dev->dev_private; -+ 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)) -+ xf_emit(ctx, 1, 0x11); /* 000000ff tesla UNK1968 */ -+ xf_emit(ctx, 1, 0); /* ffffffff tesla UNK1A3C */ -+} -+ -+static void -+nv50_graph_construct_gene_ropm2(struct nouveau_grctx *ctx) -+{ -+ struct drm_nouveau_private *dev_priv = ctx->dev->dev_private; -+ /* SEEK */ -+ xf_emit(ctx, 1, 0); /* 0000ffff DMA_QUERY */ -+ xf_emit(ctx, 1, 0x0fac6881); /* 0fffffff RT_CONTROL */ -+ xf_emit(ctx, 2, 0); /* ffffffff */ -+ xf_emit(ctx, 1, 0); /* 000000ff QUERY_ADDRESS_HIGH */ -+ xf_emit(ctx, 2, 0); /* ffffffff QUERY_ADDRESS_LOW, COUNTER */ -+ xf_emit(ctx, 1, 0); /* 00000001 SAMPLECNT_ENABLE */ -+ xf_emit(ctx, 1, 0); /* 7 */ -+ /* SEEK */ -+ xf_emit(ctx, 1, 0); /* 0000ffff DMA_QUERY */ -+ xf_emit(ctx, 1, 0); /* 000000ff QUERY_ADDRESS_HIGH */ -+ xf_emit(ctx, 2, 0); /* ffffffff QUERY_ADDRESS_LOW, COUNTER */ -+ xf_emit(ctx, 1, 0x4e3bfdf); /* ffffffff UNK0D64 */ -+ xf_emit(ctx, 1, 0x4e3bfdf); /* ffffffff UNK0DF4 */ -+ 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)) -+ xf_emit(ctx, 1, 0x11); /* 000000ff tesla UNK1968 */ -+ xf_emit(ctx, 1, 0); /* ffffffff tesla UNK1A3C */ - } - - static void -@@ -1749,443 +2392,709 @@ - int magic2; - if (dev_priv->chipset == 0x50) { - magic2 = 0x00003e60; -- } else if (dev_priv->chipset <= 0xa0 || dev_priv->chipset >= 0xaa) { -+ } else if (!IS_NVA3F(dev_priv->chipset)) { - magic2 = 0x001ffe67; - } else { - magic2 = 0x00087e67; - } -- xf_emit(ctx, 8, 0); -- xf_emit(ctx, 1, 2); -- xf_emit(ctx, 1, 0); -- xf_emit(ctx, 1, magic2); -- xf_emit(ctx, 4, 0); -- if (dev_priv->chipset > 0xa0 && dev_priv->chipset < 0xaa) -- xf_emit(ctx, 1, 1); -- xf_emit(ctx, 7, 0); -- if (dev_priv->chipset >= 0xa0 && dev_priv->chipset < 0xaa) -- xf_emit(ctx, 1, 0x15); -- xf_emit(ctx, 1, 0); -- xf_emit(ctx, 1, 1); -- xf_emit(ctx, 1, 0x10); -- xf_emit(ctx, 2, 0); -- xf_emit(ctx, 1, 1); -- xf_emit(ctx, 4, 0); -+ xf_emit(ctx, 1, 0); /* f/7 MUTISAMPLE_SAMPLES_LOG2 */ -+ xf_emit(ctx, 1, 0); /* 00000001 tesla UNK1534 */ -+ xf_emit(ctx, 1, 0); /* 00000007 STENCIL_BACK_FUNC_FUNC */ -+ xf_emit(ctx, 1, 0); /* 000000ff STENCIL_BACK_FUNC_MASK */ -+ xf_emit(ctx, 1, 0); /* 000000ff STENCIL_BACK_MASK */ -+ xf_emit(ctx, 3, 0); /* 00000007 STENCIL_BACK_OP_FAIL, ZFAIL, ZPASS */ -+ xf_emit(ctx, 1, 2); /* 00000003 tesla UNK143C */ -+ xf_emit(ctx, 1, 0); /* ffff0ff3 */ -+ xf_emit(ctx, 1, magic2); /* 001fffff tesla UNK0F78 */ -+ xf_emit(ctx, 1, 0); /* 00000001 DEPTH_BOUNDS_EN */ -+ 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)) -+ 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)) -+ xf_emit(ctx, 1, 0x15); /* 000000ff */ -+ xf_emit(ctx, 1, 0); /* 00000001 STENCIL_BACK_ENABLE */ -+ xf_emit(ctx, 1, 1); /* 00000001 tesla UNK15B4 */ -+ xf_emit(ctx, 1, 0x10); /* 3ff/ff VIEW_VOLUME_CLIP_CTRL */ -+ xf_emit(ctx, 1, 0); /* ffffffff CLEAR_DEPTH */ -+ 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) { -- xf_emit(ctx, 1, 4); -- xf_emit(ctx, 1, 0x400); -- xf_emit(ctx, 1, 0x300); -- xf_emit(ctx, 1, 0x1001); -+ 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 (dev_priv->chipset > 0xa0 && dev_priv->chipset < 0xaa) -- xf_emit(ctx, 1, 0); -+ if (IS_NVA3F(dev_priv->chipset)) -+ xf_emit(ctx, 1, 0); /* 0000000f UNK15C8 */ - else -- xf_emit(ctx, 1, 0x15); -+ xf_emit(ctx, 1, 0x15); /* ff */ - } -- xf_emit(ctx, 3, 0); - } -- xf_emit(ctx, 2, 0); -- xf_emit(ctx, 1, 2); -- xf_emit(ctx, 8, 0); -- xf_emit(ctx, 1, 1); -- xf_emit(ctx, 1, 0x10); -- xf_emit(ctx, 1, 0); -- xf_emit(ctx, 1, 1); -- xf_emit(ctx, 0x13, 0); -- xf_emit(ctx, 1, 0x10); -- xf_emit(ctx, 0x10, 0); -- xf_emit(ctx, 0x10, 0x3f800000); -- xf_emit(ctx, 0x19, 0); -- xf_emit(ctx, 1, 0x10); -- xf_emit(ctx, 1, 0); -- xf_emit(ctx, 1, 0x3f); -- xf_emit(ctx, 6, 0); -- xf_emit(ctx, 1, 1); -- xf_emit(ctx, 1, 0); -- xf_emit(ctx, 1, 1); -- xf_emit(ctx, 1, 0); -- xf_emit(ctx, 1, 1); -+ xf_emit(ctx, 1, 0); /* 00000007 MULTISAMPLE_SAMPLES_LOG2 */ -+ xf_emit(ctx, 1, 0); /* 00000001 tesla UNK1534 */ -+ xf_emit(ctx, 1, 0); /* 00000007 STENCIL_BACK_FUNC_FUNC */ -+ xf_emit(ctx, 1, 0); /* 000000ff STENCIL_BACK_FUNC_MASK */ -+ xf_emit(ctx, 1, 0); /* ffff0ff3 */ -+ xf_emit(ctx, 1, 2); /* 00000003 tesla UNK143C */ -+ xf_emit(ctx, 1, 0); /* 00000001 DEPTH_BOUNDS_EN */ -+ 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 */ -+ 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); /* 00000001 STENCIL_FRONT_ENABLE */ -+ xf_emit(ctx, 1, 0); /* 00000001 STENCIL_BACK_ENABLE */ -+ xf_emit(ctx, 1, 1); /* 00000001 tesla UNK15B4 */ -+ xf_emit(ctx, 1, 0x10); /* 7f/ff VIEW_VOLUME_CLIP_CTRL */ -+ xf_emit(ctx, 1, 0); /* 0000000f ZETA_FORMAT */ -+ xf_emit(ctx, 1, 1); /* 00000001 ZETA_ENABLE */ -+ xf_emit(ctx, 1, 0); /* ffffffff tesla UNK1A3C */ -+ xf_emit(ctx, 1, 0); /* 00000001 tesla UNK1534 */ -+ xf_emit(ctx, 1, 0); /* 00000001 tesla UNK1900 */ -+ xf_emit(ctx, 1, 0); /* 00000007 STENCIL_BACK_FUNC_FUNC */ -+ xf_emit(ctx, 1, 0); /* 000000ff STENCIL_BACK_FUNC_MASK */ -+ xf_emit(ctx, 1, 0); /* 000000ff STENCIL_BACK_FUNC_REF */ -+ xf_emit(ctx, 2, 0); /* ffffffff DEPTH_BOUNDS */ -+ xf_emit(ctx, 1, 0); /* 00000001 DEPTH_BOUNDS_EN */ -+ 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 */ -+ xf_emit(ctx, 1, 0); /* 0000000f */ -+ xf_emit(ctx, 1, 0); /* 00000001 tesla UNK0FB0 */ -+ 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_FUNC_REF */ -+ xf_emit(ctx, 1, 0); /* 00000001 STENCIL_FRONT_ENABLE */ -+ xf_emit(ctx, 1, 0); /* 00000001 STENCIL_BACK_ENABLE */ -+ xf_emit(ctx, 1, 0x10); /* 7f/ff VIEW_VOLUME_CLIP_CTRL */ -+ xf_emit(ctx, 0x10, 0); /* ffffffff DEPTH_RANGE_NEAR */ -+ xf_emit(ctx, 0x10, 0x3f800000); /* ffffffff DEPTH_RANGE_FAR */ -+ xf_emit(ctx, 1, 0); /* 0000000f ZETA_FORMAT */ -+ xf_emit(ctx, 1, 0); /* 00000007 MULTISAMPLE_SAMPLES_LOG2 */ -+ xf_emit(ctx, 1, 0); /* 00000007 STENCIL_BACK_FUNC_FUNC */ -+ xf_emit(ctx, 1, 0); /* 000000ff STENCIL_BACK_FUNC_MASK */ -+ xf_emit(ctx, 1, 0); /* 000000ff STENCIL_BACK_FUNC_REF */ -+ xf_emit(ctx, 1, 0); /* 000000ff STENCIL_BACK_MASK */ -+ xf_emit(ctx, 3, 0); /* 00000007 STENCIL_BACK_OP_FAIL, ZFAIL, ZPASS */ -+ xf_emit(ctx, 2, 0); /* ffffffff DEPTH_BOUNDS */ -+ xf_emit(ctx, 1, 0); /* 00000001 DEPTH_BOUNDS_EN */ -+ 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 */ -+ xf_emit(ctx, 1, 0); /* 000000ff CLEAR_STENCIL */ -+ 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_FUNC_REF */ -+ 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 */ -+ xf_emit(ctx, 1, 0); /* 00000001 STENCIL_BACK_ENABLE */ -+ xf_emit(ctx, 1, 0x10); /* 7f/ff VIEW_VOLUME_CLIP_CTRL */ -+ xf_emit(ctx, 1, 0); /* 0000000f ZETA_FORMAT */ -+ xf_emit(ctx, 1, 0x3f); /* 0000003f UNK1590 */ -+ xf_emit(ctx, 1, 0); /* 00000007 MULTISAMPLE_SAMPLES_LOG2 */ -+ xf_emit(ctx, 1, 0); /* 00000001 tesla UNK1534 */ -+ xf_emit(ctx, 2, 0); /* ffff0ff3, ffff */ -+ xf_emit(ctx, 1, 0); /* 00000001 tesla UNK0FB0 */ -+ xf_emit(ctx, 1, 0); /* 0001ffff GP_BUILTIN_RESULT_EN */ -+ xf_emit(ctx, 1, 1); /* 00000001 tesla UNK15B4 */ -+ xf_emit(ctx, 1, 0); /* 0000000f ZETA_FORMAT */ -+ 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) { - xf_emit(ctx, 2, 0); - xf_emit(ctx, 1, 0x1001); - xf_emit(ctx, 0xb, 0); - } else { -- xf_emit(ctx, 0xc, 0); -+ xf_emit(ctx, 1, 0); /* 00000007 */ -+ xf_emit(ctx, 1, 0); /* 00000001 tesla UNK1534 */ -+ xf_emit(ctx, 1, 0); /* 00000007 MULTISAMPLE_SAMPLES_LOG2 */ -+ xf_emit(ctx, 8, 0); /* 00000001 BLEND_ENABLE */ -+ xf_emit(ctx, 1, 0); /* ffff0ff3 */ -+ } -+ xf_emit(ctx, 1, 0x11); /* 3f/7f RT_FORMAT */ -+ xf_emit(ctx, 7, 0); /* 3f/7f RT_FORMAT */ -+ xf_emit(ctx, 1, 0xf); /* 0000000f COLOR_MASK */ -+ 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) { -+ xf_emit(ctx, 1, 0); /* 0000000f LOGIC_OP */ -+ xf_emit(ctx, 1, 0); /* 000000ff */ - } -- xf_emit(ctx, 1, 0x11); -- xf_emit(ctx, 7, 0); -- xf_emit(ctx, 1, 0xf); -- xf_emit(ctx, 7, 0); -- xf_emit(ctx, 1, 0x11); -- if (dev_priv->chipset == 0x50) -- xf_emit(ctx, 4, 0); -- else -- xf_emit(ctx, 6, 0); -- xf_emit(ctx, 3, 1); -- xf_emit(ctx, 1, 2); -- xf_emit(ctx, 1, 1); -- xf_emit(ctx, 1, 2); -- xf_emit(ctx, 1, 1); -- xf_emit(ctx, 1, 0); -- xf_emit(ctx, 1, magic2); -- xf_emit(ctx, 1, 0); -- xf_emit(ctx, 1, 0x0fac6881); -- if (dev_priv->chipset > 0xa0 && dev_priv->chipset < 0xaa) { -- xf_emit(ctx, 1, 0); -- xf_emit(ctx, 0x18, 1); -- xf_emit(ctx, 8, 2); -- xf_emit(ctx, 8, 1); -- xf_emit(ctx, 8, 2); -- xf_emit(ctx, 8, 1); -- xf_emit(ctx, 3, 0); -- xf_emit(ctx, 1, 1); -- xf_emit(ctx, 5, 0); -- xf_emit(ctx, 1, 1); -- xf_emit(ctx, 0x16, 0); -+ xf_emit(ctx, 1, 0); /* 00000007 OPERATION */ -+ xf_emit(ctx, 1, 0); /* ff/3ff */ -+ xf_emit(ctx, 1, 0); /* 00000003 UNK0F90 */ -+ xf_emit(ctx, 2, 1); /* 00000007 BLEND_EQUATION_RGB, ALPHA */ -+ xf_emit(ctx, 1, 1); /* 00000001 UNK133C */ -+ xf_emit(ctx, 1, 2); /* 0000001f BLEND_FUNC_SRC_RGB */ -+ xf_emit(ctx, 1, 1); /* 0000001f BLEND_FUNC_DST_RGB */ -+ xf_emit(ctx, 1, 2); /* 0000001f BLEND_FUNC_SRC_ALPHA */ -+ xf_emit(ctx, 1, 1); /* 0000001f BLEND_FUNC_DST_ALPHA */ -+ xf_emit(ctx, 1, 0); /* 00000001 */ -+ 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)) { -+ 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 */ -+ xf_emit(ctx, 8, 1); /* 00000001 IBLEND_UNK00 */ -+ xf_emit(ctx, 8, 2); /* 0000001f IBLEND_FUNC_SRC_RGB */ -+ xf_emit(ctx, 8, 1); /* 0000001f IBLEND_FUNC_DST_RGB */ -+ xf_emit(ctx, 8, 2); /* 0000001f IBLEND_FUNC_SRC_ALPHA */ -+ xf_emit(ctx, 8, 1); /* 0000001f IBLEND_FUNC_DST_ALPHA */ -+ xf_emit(ctx, 1, 0); /* 00000001 tesla UNK1140 */ -+ xf_emit(ctx, 2, 0); /* 00000001 */ -+ xf_emit(ctx, 1, 1); /* 0000001f tesla UNK169C */ -+ xf_emit(ctx, 1, 0); /* 0000000f */ -+ xf_emit(ctx, 1, 0); /* 00000003 */ -+ xf_emit(ctx, 1, 0); /* ffffffff */ -+ xf_emit(ctx, 2, 0); /* 00000001 */ -+ 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) { -+ xf_emit(ctx, 2, 0); /* 00000001 */ -+ xf_emit(ctx, 1, 0); /* 00000007 */ -+ xf_emit(ctx, 1, 0); /* 00000003 */ -+ xf_emit(ctx, 1, 0); /* ffffffff */ -+ xf_emit(ctx, 2, 0); /* 00000001 */ - } else { -- if (dev_priv->chipset >= 0xa0) -- xf_emit(ctx, 0x1b, 0); -- else -- xf_emit(ctx, 0x15, 0); -- } -- xf_emit(ctx, 1, 1); -- xf_emit(ctx, 1, 2); -- xf_emit(ctx, 2, 1); -- xf_emit(ctx, 1, 2); -- xf_emit(ctx, 2, 1); -+ xf_emit(ctx, 1, 0); /* 00000007 MULTISAMPLE_SAMPLES_LOG2 */ -+ xf_emit(ctx, 1, 0); /* 00000003 tesla UNK1430 */ -+ xf_emit(ctx, 1, 0); /* ffffffff tesla UNK1A3C */ -+ } -+ 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) -- xf_emit(ctx, 4, 0); -- else -- xf_emit(ctx, 3, 0); -- if (dev_priv->chipset > 0xa0 && dev_priv->chipset < 0xaa) { -- xf_emit(ctx, 0x10, 1); -- xf_emit(ctx, 8, 2); -- xf_emit(ctx, 0x10, 1); -- xf_emit(ctx, 8, 2); -- xf_emit(ctx, 8, 1); -- xf_emit(ctx, 3, 0); -- } -- xf_emit(ctx, 1, 0x11); -- xf_emit(ctx, 1, 1); -- xf_emit(ctx, 0x5b, 0); -+ xf_emit(ctx, 2, 0); /* 00000001 */ -+ xf_emit(ctx, 1, 0); /* 000003ff */ -+ xf_emit(ctx, 8, 0); /* 00000001 BLEND_ENABLE */ -+ xf_emit(ctx, 1, 1); /* 00000001 UNK133C */ -+ xf_emit(ctx, 1, 2); /* 0000001f BLEND_FUNC_SRC_RGB */ -+ 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_ALPHA */ -+ xf_emit(ctx, 1, 1); /* 0000001f BLEND_FUNC_DST_ALPHA */ -+ xf_emit(ctx, 1, 1); /* 00000007 BLEND_EQUATION_ALPHA */ -+ 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) -+ xf_emit(ctx, 1, 0); /* 00000001 UNK12E4? NVA3+ only? */ -+ if (IS_NVA3F(dev_priv->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 */ -+ xf_emit(ctx, 8, 1); /* 0000001f IBLEND_FUNC_DST_RGB */ -+ xf_emit(ctx, 8, 1); /* 00000007 IBLEND_EQUATION_ALPHA */ -+ xf_emit(ctx, 8, 2); /* 0000001f IBLEND_FUNC_SRC_ALPHA */ -+ xf_emit(ctx, 8, 1); /* 0000001f IBLEND_FUNC_DST_ALPHA */ -+ xf_emit(ctx, 1, 0); /* 00000001 tesla UNK15C4 */ -+ xf_emit(ctx, 1, 0); /* 00000001 */ -+ xf_emit(ctx, 1, 0); /* 00000001 tesla UNK1140 */ -+ } -+ xf_emit(ctx, 1, 0x11); /* 3f/7f DST_FORMAT */ -+ xf_emit(ctx, 1, 1); /* 00000001 DST_LINEAR */ -+ xf_emit(ctx, 1, 0); /* 00000007 PATTERN_COLOR_FORMAT */ -+ xf_emit(ctx, 2, 0); /* ffffffff PATTERN_MONO_COLOR */ -+ xf_emit(ctx, 1, 0); /* 00000001 PATTERN_MONO_FORMAT */ -+ xf_emit(ctx, 2, 0); /* ffffffff PATTERN_MONO_BITMAP */ -+ xf_emit(ctx, 1, 0); /* 00000003 PATTERN_SELECT */ -+ xf_emit(ctx, 1, 0); /* 000000ff ROP */ -+ xf_emit(ctx, 1, 0); /* ffffffff BETA1 */ -+ xf_emit(ctx, 1, 0); /* ffffffff BETA4 */ -+ xf_emit(ctx, 1, 0); /* 00000007 OPERATION */ -+ xf_emit(ctx, 0x50, 0); /* 10x ffffff, ffffff, ffffff, ffffff, 3 PATTERN */ - } - - static void --nv50_graph_construct_xfer_tp_x1(struct nouveau_grctx *ctx) -+nv50_graph_construct_xfer_unk84xx(struct nouveau_grctx *ctx) - { - struct drm_nouveau_private *dev_priv = ctx->dev->dev_private; - int magic3; -- if (dev_priv->chipset == 0x50) -+ switch (dev_priv->chipset) { -+ case 0x50: - magic3 = 0x1000; -- else if (dev_priv->chipset == 0x86 || dev_priv->chipset == 0x98 || dev_priv->chipset >= 0xa8) -+ break; -+ case 0x86: -+ case 0x98: -+ case 0xa8: -+ case 0xaa: -+ case 0xac: -+ case 0xaf: - magic3 = 0x1e00; -- else -+ break; -+ default: - magic3 = 0; -- xf_emit(ctx, 1, 0); -- xf_emit(ctx, 1, 4); -- if (dev_priv->chipset > 0xa0 && dev_priv->chipset < 0xaa) -- xf_emit(ctx, 0x24, 0); -+ } -+ xf_emit(ctx, 1, 0); /* 00000001 GP_ENABLE */ -+ xf_emit(ctx, 1, 4); /* 7f/ff[NVA0+] VP_REG_ALLOC_RESULT */ -+ 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)) -+ xf_emit(ctx, 0x1f, 0); /* ffffffff */ - else if (dev_priv->chipset >= 0xa0) -- xf_emit(ctx, 0x14, 0); -+ xf_emit(ctx, 0x0f, 0); /* ffffffff */ - else -- xf_emit(ctx, 0x15, 0); -- xf_emit(ctx, 2, 4); -+ 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) -- xf_emit(ctx, 1, 0x03020100); -+ xf_emit(ctx, 1, 0x03020100); /* ffffffff */ - else -- xf_emit(ctx, 1, 0x00608080); -- xf_emit(ctx, 4, 0); -- xf_emit(ctx, 1, 4); -- xf_emit(ctx, 2, 0); -- xf_emit(ctx, 2, 4); -- xf_emit(ctx, 1, 0x80); -+ xf_emit(ctx, 1, 0x00608080); /* fffffff VP_RESULT_MAP_0 */ -+ xf_emit(ctx, 1, 0); /* 00000001 GP_ENABLE */ -+ xf_emit(ctx, 1, 0); /* ffffffff tesla UNK1A30 */ -+ xf_emit(ctx, 2, 0); /* 111/113, 7f/ff */ -+ xf_emit(ctx, 1, 4); /* 7f/ff VP_RESULT_MAP_SIZE */ -+ xf_emit(ctx, 1, 0); /* ffffffff tesla UNK1A30 */ -+ xf_emit(ctx, 1, 0); /* 00000001 GP_ENABLE */ -+ xf_emit(ctx, 1, 4); /* 000000ff GP_REG_ALLOC_RESULT */ -+ xf_emit(ctx, 1, 4); /* 000000ff GP_RESULT_MAP_SIZE */ -+ xf_emit(ctx, 1, 0x80); /* 0000ffff GP_VERTEX_OUTPUT_COUNT */ - if (magic3) -- xf_emit(ctx, 1, magic3); -- xf_emit(ctx, 1, 4); -- xf_emit(ctx, 0x24, 0); -- xf_emit(ctx, 1, 4); -- xf_emit(ctx, 1, 0x80); -- xf_emit(ctx, 1, 4); -- xf_emit(ctx, 1, 0x03020100); -- xf_emit(ctx, 1, 3); -+ xf_emit(ctx, 1, magic3); /* 00007fff tesla UNK141C */ -+ xf_emit(ctx, 1, 4); /* 7f/ff VP_RESULT_MAP_SIZE */ -+ xf_emit(ctx, 1, 0); /* ffffffff tesla UNK1A30 */ -+ xf_emit(ctx, 1, 0); /* 111/113 */ -+ xf_emit(ctx, 0x1f, 0); /* ffffffff GP_RESULT_MAP_1 up */ -+ xf_emit(ctx, 1, 0); /* 0000001f */ -+ xf_emit(ctx, 1, 0); /* ffffffff */ -+ xf_emit(ctx, 1, 0); /* 00000001 GP_ENABLE */ -+ xf_emit(ctx, 1, 4); /* 000000ff GP_REG_ALLOC_RESULT */ -+ xf_emit(ctx, 1, 0x80); /* 0000ffff GP_VERTEX_OUTPUT_COUNT */ -+ xf_emit(ctx, 1, 4); /* 000000ff GP_RESULT_MAP_SIZE */ -+ xf_emit(ctx, 1, 0x03020100); /* ffffffff GP_RESULT_MAP_0 */ -+ xf_emit(ctx, 1, 3); /* 00000003 GP_OUTPUT_PRIMITIVE_TYPE */ - if (magic3) -- xf_emit(ctx, 1, magic3); -- xf_emit(ctx, 1, 4); -- xf_emit(ctx, 4, 0); -- xf_emit(ctx, 1, 4); -- xf_emit(ctx, 1, 3); -- xf_emit(ctx, 3, 0); -- xf_emit(ctx, 1, 4); -+ xf_emit(ctx, 1, magic3); /* 7fff tesla UNK141C */ -+ xf_emit(ctx, 1, 4); /* 7f/ff VP_RESULT_MAP_SIZE */ -+ xf_emit(ctx, 1, 0); /* 00000001 PROVOKING_VERTEX_LAST */ -+ xf_emit(ctx, 1, 0); /* ffffffff tesla UNK1A30 */ -+ xf_emit(ctx, 1, 0); /* 111/113 */ -+ xf_emit(ctx, 1, 0); /* 00000001 GP_ENABLE */ -+ xf_emit(ctx, 1, 4); /* 000000ff GP_RESULT_MAP_SIZE */ -+ xf_emit(ctx, 1, 3); /* 00000003 GP_OUTPUT_PRIMITIVE_TYPE */ -+ xf_emit(ctx, 1, 0); /* 00000001 PROVOKING_VERTEX_LAST */ -+ xf_emit(ctx, 1, 0); /* ffffffff tesla UNK1A30 */ -+ xf_emit(ctx, 1, 0); /* 00000003 tesla UNK13A0 */ -+ xf_emit(ctx, 1, 4); /* 7f/ff VP_REG_ALLOC_RESULT */ -+ 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) -- xf_emit(ctx, 0x1024, 0); -+ xf_emit(ctx, 0x1020, 0); /* 4 x (0x400 x 0xffffffff, ff, 0, 0, 0, 4 x ffffffff) */ - else if (dev_priv->chipset < 0xa0) -- xf_emit(ctx, 0xa24, 0); -- else if (dev_priv->chipset == 0xa0 || dev_priv->chipset >= 0xaa) -- xf_emit(ctx, 0x214, 0); -- else -- xf_emit(ctx, 0x414, 0); -- xf_emit(ctx, 1, 4); -- xf_emit(ctx, 1, 3); -- xf_emit(ctx, 2, 0); -+ xf_emit(ctx, 0xa20, 0); /* 4 x (0x280 x 0xffffffff, ff, 0, 0, 0, 4 x ffffffff) */ -+ else if (!IS_NVA3F(dev_priv->chipset)) -+ xf_emit(ctx, 0x210, 0); /* ffffffff */ -+ else -+ xf_emit(ctx, 0x410, 0); /* ffffffff */ -+ xf_emit(ctx, 1, 0); /* 00000001 GP_ENABLE */ -+ xf_emit(ctx, 1, 4); /* 000000ff GP_RESULT_MAP_SIZE */ -+ xf_emit(ctx, 1, 3); /* 00000003 GP_OUTPUT_PRIMITIVE_TYPE */ -+ xf_emit(ctx, 1, 0); /* 00000001 PROVOKING_VERTEX_LAST */ -+ xf_emit(ctx, 1, 0); /* ffffffff tesla UNK1A30 */ - } - - static void --nv50_graph_construct_xfer_tp_x2(struct nouveau_grctx *ctx) -+nv50_graph_construct_xfer_tprop(struct nouveau_grctx *ctx) - { - struct drm_nouveau_private *dev_priv = ctx->dev->dev_private; - int magic1, magic2; - if (dev_priv->chipset == 0x50) { - magic1 = 0x3ff; - magic2 = 0x00003e60; -- } else if (dev_priv->chipset <= 0xa0 || dev_priv->chipset >= 0xaa) { -+ } else if (!IS_NVA3F(dev_priv->chipset)) { - magic1 = 0x7ff; - magic2 = 0x001ffe67; - } else { - magic1 = 0x7ff; - magic2 = 0x00087e67; - } -- xf_emit(ctx, 3, 0); -- if (dev_priv->chipset > 0xa0 && dev_priv->chipset < 0xaa) -- xf_emit(ctx, 1, 1); -- xf_emit(ctx, 0xc, 0); -- xf_emit(ctx, 1, 0xf); -- xf_emit(ctx, 0xb, 0); -- xf_emit(ctx, 1, 4); -- xf_emit(ctx, 4, 0xffff); -- xf_emit(ctx, 8, 0); -- xf_emit(ctx, 1, 1); -- xf_emit(ctx, 3, 0); -- xf_emit(ctx, 1, 1); -- xf_emit(ctx, 5, 0); -- xf_emit(ctx, 1, 1); -- xf_emit(ctx, 2, 0); -- if (dev_priv->chipset > 0xa0 && dev_priv->chipset < 0xaa) { -- xf_emit(ctx, 1, 3); -- xf_emit(ctx, 1, 0); -- } else if (dev_priv->chipset >= 0xa0) -- xf_emit(ctx, 1, 1); -- xf_emit(ctx, 0xa, 0); -- xf_emit(ctx, 2, 1); -- xf_emit(ctx, 1, 2); -- xf_emit(ctx, 2, 1); -- xf_emit(ctx, 1, 2); -- if (dev_priv->chipset > 0xa0 && dev_priv->chipset < 0xaa) { -- xf_emit(ctx, 1, 0); -- xf_emit(ctx, 0x18, 1); -- xf_emit(ctx, 8, 2); -- xf_emit(ctx, 8, 1); -- xf_emit(ctx, 8, 2); -- xf_emit(ctx, 8, 1); -- xf_emit(ctx, 1, 0); -- } -- xf_emit(ctx, 1, 1); -- xf_emit(ctx, 1, 0); -- xf_emit(ctx, 1, 0x11); -- xf_emit(ctx, 7, 0); -- xf_emit(ctx, 1, 0x0fac6881); -- xf_emit(ctx, 2, 0); -- xf_emit(ctx, 1, 4); -- xf_emit(ctx, 3, 0); -- xf_emit(ctx, 1, 0x11); -- xf_emit(ctx, 1, 1); -- xf_emit(ctx, 1, 0); -- xf_emit(ctx, 3, 0xcf); -- if (dev_priv->chipset > 0xa0 && dev_priv->chipset < 0xaa) -- xf_emit(ctx, 1, 1); -- xf_emit(ctx, 0xa, 0); -- xf_emit(ctx, 2, 1); -- xf_emit(ctx, 1, 2); -- xf_emit(ctx, 2, 1); -- xf_emit(ctx, 1, 2); -- xf_emit(ctx, 1, 1); -- xf_emit(ctx, 1, 0); -- xf_emit(ctx, 8, 1); -- xf_emit(ctx, 1, 0x11); -- xf_emit(ctx, 7, 0); -- xf_emit(ctx, 1, 0x0fac6881); -- xf_emit(ctx, 1, 0xf); -- xf_emit(ctx, 7, 0); -- xf_emit(ctx, 1, magic2); -- xf_emit(ctx, 2, 0); -- xf_emit(ctx, 1, 0x11); -- if (dev_priv->chipset > 0xa0 && dev_priv->chipset < 0xaa) -- xf_emit(ctx, 2, 1); -- else -- xf_emit(ctx, 1, 1); -+ 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)) -+ 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 */ -+ xf_emit(ctx, 1, 0); /* 000000ff STENCIL_BACK_MASK */ -+ xf_emit(ctx, 3, 0); /* 00000007 STENCIL_BACK_OP_FAIL, ZFAIL, ZPASS */ -+ xf_emit(ctx, 4, 0); /* ffffffff BLEND_COLOR */ -+ xf_emit(ctx, 1, 0); /* 00000001 UNK19C0 */ -+ xf_emit(ctx, 1, 0); /* 00000001 UNK0FDC */ -+ xf_emit(ctx, 1, 0xf); /* 0000000f COLOR_MASK */ -+ xf_emit(ctx, 7, 0); /* 0000000f COLOR_MASK */ -+ xf_emit(ctx, 1, 0); /* 00000001 DEPTH_TEST_ENABLE */ -+ xf_emit(ctx, 1, 0); /* 00000001 DEPTH_WRITE_ENABLE */ -+ xf_emit(ctx, 1, 0); /* 00000001 LOGIC_OP_ENABLE */ -+ xf_emit(ctx, 1, 0); /* ff[NV50]/3ff[NV84+] */ -+ xf_emit(ctx, 1, 4); /* 00000007 FP_CONTROL */ -+ xf_emit(ctx, 4, 0xffff); /* 0000ffff MSAA_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 */ -+ xf_emit(ctx, 1, 0); /* 00000001 STENCIL_BACK_ENABLE */ -+ xf_emit(ctx, 2, 0); /* 00007fff WINDOW_OFFSET_XY */ -+ xf_emit(ctx, 1, 1); /* 00000001 tesla UNK19CC */ -+ xf_emit(ctx, 1, 0); /* 7 */ -+ xf_emit(ctx, 1, 0); /* 00000001 SAMPLECNT_ENABLE */ -+ xf_emit(ctx, 1, 0); /* 0000000f ZETA_FORMAT */ -+ xf_emit(ctx, 1, 1); /* 00000001 ZETA_ENABLE */ -+ xf_emit(ctx, 1, 0); /* ffffffff COLOR_KEY */ -+ xf_emit(ctx, 1, 0); /* 00000001 COLOR_KEY_ENABLE */ -+ xf_emit(ctx, 1, 0); /* 00000007 COLOR_KEY_FORMAT */ -+ xf_emit(ctx, 2, 0); /* ffffffff SIFC_BITMAP_COLOR */ -+ 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)) { -+ 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) { -+ xf_emit(ctx, 1, 1); /* 00000001 tesla UNK16B4 */ -+ xf_emit(ctx, 1, 0); /* 00000003 */ -+ } else { -+ xf_emit(ctx, 1, 0); /* 00000003 MULTISAMPLE_CTRL */ -+ } -+ xf_emit(ctx, 1, 0); /* 00000001 tesla UNK1534 */ -+ xf_emit(ctx, 8, 0); /* 00000001 BLEND_ENABLE */ -+ xf_emit(ctx, 1, 1); /* 0000001f BLEND_FUNC_DST_ALPHA */ -+ xf_emit(ctx, 1, 1); /* 00000007 BLEND_EQUATION_ALPHA */ -+ xf_emit(ctx, 1, 2); /* 0000001f BLEND_FUNC_SRC_ALPHA */ -+ 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)) { -+ 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 */ -+ xf_emit(ctx, 8, 1); /* 00000001 IBLEND_UNK00 */ -+ xf_emit(ctx, 8, 2); /* 0000001f IBLEND_SRC_RGB */ -+ xf_emit(ctx, 8, 1); /* 0000001f IBLEND_DST_RGB */ -+ xf_emit(ctx, 8, 2); /* 0000001f IBLEND_SRC_ALPHA */ -+ xf_emit(ctx, 8, 1); /* 0000001f IBLEND_DST_ALPHA */ -+ xf_emit(ctx, 1, 0); /* 00000001 UNK1140 */ -+ } -+ xf_emit(ctx, 1, 1); /* 00000001 UNK133C */ -+ xf_emit(ctx, 1, 0); /* ffff0ff3 */ -+ xf_emit(ctx, 1, 0x11); /* 3f/7f RT_FORMAT */ -+ xf_emit(ctx, 7, 0); /* 3f/7f RT_FORMAT */ -+ xf_emit(ctx, 1, 0x0fac6881); /* 0fffffff RT_CONTROL */ -+ xf_emit(ctx, 1, 0); /* 00000001 LOGIC_OP_ENABLE */ -+ xf_emit(ctx, 1, 0); /* ff/3ff */ -+ xf_emit(ctx, 1, 4); /* 00000007 FP_CONTROL */ -+ xf_emit(ctx, 1, 0); /* 00000003 UNK0F90 */ -+ xf_emit(ctx, 1, 0); /* 00000001 FRAMEBUFFER_SRGB */ -+ xf_emit(ctx, 1, 0); /* 7 */ -+ xf_emit(ctx, 1, 0x11); /* 3f/7f DST_FORMAT */ -+ xf_emit(ctx, 1, 1); /* 00000001 DST_LINEAR */ -+ xf_emit(ctx, 1, 0); /* 00000007 OPERATION */ -+ 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)) -+ 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 */ -+ xf_emit(ctx, 8, 0); /* 00000001 BLEND_ENABLE */ -+ xf_emit(ctx, 1, 1); /* 0000001f BLEND_FUNC_DST_ALPHA */ -+ xf_emit(ctx, 1, 1); /* 00000007 BLEND_EQUATION_ALPHA */ -+ xf_emit(ctx, 1, 2); /* 0000001f BLEND_FUNC_SRC_ALPHA */ -+ 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 */ -+ xf_emit(ctx, 1, 1); /* 00000001 UNK133C */ -+ xf_emit(ctx, 1, 0); /* ffff0ff3 */ -+ xf_emit(ctx, 8, 1); /* 00000001 UNK19E0 */ -+ xf_emit(ctx, 1, 0x11); /* 3f/7f RT_FORMAT */ -+ xf_emit(ctx, 7, 0); /* 3f/7f RT_FORMAT */ -+ xf_emit(ctx, 1, 0x0fac6881); /* 0fffffff RT_CONTROL */ -+ xf_emit(ctx, 1, 0xf); /* 0000000f COLOR_MASK */ -+ xf_emit(ctx, 7, 0); /* 0000000f COLOR_MASK */ -+ xf_emit(ctx, 1, magic2); /* 001fffff tesla UNK0F78 */ -+ xf_emit(ctx, 1, 0); /* 00000001 DEPTH_BOUNDS_EN */ -+ 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)) -+ xf_emit(ctx, 1, 1); /* 0000001f tesla UNK169C */ - if(dev_priv->chipset == 0x50) -- xf_emit(ctx, 1, 0); -- else -- xf_emit(ctx, 3, 0); -- xf_emit(ctx, 1, 4); -- xf_emit(ctx, 5, 0); -- xf_emit(ctx, 1, 1); -- xf_emit(ctx, 4, 0); -- xf_emit(ctx, 1, 0x11); -- xf_emit(ctx, 7, 0); -- xf_emit(ctx, 1, 0x0fac6881); -- xf_emit(ctx, 3, 0); -- xf_emit(ctx, 1, 0x11); -- xf_emit(ctx, 1, 1); -- xf_emit(ctx, 1, 0); -- xf_emit(ctx, 1, 1); -- xf_emit(ctx, 1, 0); -- xf_emit(ctx, 1, 1); -- xf_emit(ctx, 1, 0); -- xf_emit(ctx, 1, magic1); -- xf_emit(ctx, 1, 0); -- xf_emit(ctx, 1, 1); -- xf_emit(ctx, 1, 0); -- xf_emit(ctx, 1, 1); -- xf_emit(ctx, 2, 0); -- if (dev_priv->chipset > 0xa0 && dev_priv->chipset < 0xaa) -- xf_emit(ctx, 1, 1); -- xf_emit(ctx, 0x28, 0); -- xf_emit(ctx, 8, 8); -- xf_emit(ctx, 1, 0x11); -- xf_emit(ctx, 7, 0); -- xf_emit(ctx, 1, 0x0fac6881); -- xf_emit(ctx, 8, 0x400); -- xf_emit(ctx, 8, 0x300); -- xf_emit(ctx, 1, 1); -- xf_emit(ctx, 1, 0xf); -- xf_emit(ctx, 7, 0); -- xf_emit(ctx, 1, 0x20); -- xf_emit(ctx, 1, 0x11); -- xf_emit(ctx, 1, 0x100); -- xf_emit(ctx, 1, 0); -- xf_emit(ctx, 1, 1); -- xf_emit(ctx, 2, 0); -- xf_emit(ctx, 1, 0x40); -- xf_emit(ctx, 1, 0x100); -- xf_emit(ctx, 1, 0); -- xf_emit(ctx, 1, 3); -- xf_emit(ctx, 4, 0); -- if (dev_priv->chipset > 0xa0 && dev_priv->chipset < 0xaa) -- xf_emit(ctx, 1, 1); -- xf_emit(ctx, 1, magic2); -- xf_emit(ctx, 3, 0); -- xf_emit(ctx, 1, 2); -- xf_emit(ctx, 1, 0x0fac6881); -- xf_emit(ctx, 9, 0); -- xf_emit(ctx, 1, 1); -- xf_emit(ctx, 4, 0); -- xf_emit(ctx, 1, 4); -- xf_emit(ctx, 1, 0); -- xf_emit(ctx, 1, 1); -- xf_emit(ctx, 1, 0x400); -- xf_emit(ctx, 1, 0x300); -- xf_emit(ctx, 1, 0x1001); -- if (dev_priv->chipset > 0xa0 && dev_priv->chipset < 0xaa) -- xf_emit(ctx, 4, 0); -+ xf_emit(ctx, 1, 0); /* ff */ - else -- xf_emit(ctx, 3, 0); -- xf_emit(ctx, 1, 0x11); -- xf_emit(ctx, 7, 0); -- xf_emit(ctx, 1, 0x0fac6881); -- xf_emit(ctx, 1, 0xf); -- if (dev_priv->chipset > 0xa0 && dev_priv->chipset < 0xaa) { -- xf_emit(ctx, 0x15, 0); -- xf_emit(ctx, 1, 1); -- xf_emit(ctx, 3, 0); -- } else -- xf_emit(ctx, 0x17, 0); -+ xf_emit(ctx, 3, 0); /* 1, 7, 3ff */ -+ xf_emit(ctx, 1, 4); /* 00000007 FP_CONTROL */ -+ xf_emit(ctx, 1, 0); /* 00000003 UNK0F90 */ -+ xf_emit(ctx, 1, 0); /* 00000001 STENCIL_FRONT_ENABLE */ -+ xf_emit(ctx, 1, 0); /* 00000007 */ -+ xf_emit(ctx, 1, 0); /* 00000001 SAMPLECNT_ENABLE */ -+ xf_emit(ctx, 1, 0); /* 0000000f ZETA_FORMAT */ -+ xf_emit(ctx, 1, 1); /* 00000001 ZETA_ENABLE */ -+ xf_emit(ctx, 1, 0); /* ffffffff tesla UNK1A3C */ -+ xf_emit(ctx, 1, 0); /* 7/f MULTISAMPLE_SAMPLES_LOG2 */ -+ xf_emit(ctx, 1, 0); /* 00000001 tesla UNK1534 */ -+ xf_emit(ctx, 1, 0); /* ffff0ff3 */ -+ xf_emit(ctx, 1, 0x11); /* 3f/7f RT_FORMAT */ -+ xf_emit(ctx, 7, 0); /* 3f/7f RT_FORMAT */ -+ xf_emit(ctx, 1, 0x0fac6881); /* 0fffffff RT_CONTROL */ -+ xf_emit(ctx, 1, 0); /* 00000001 DEPTH_BOUNDS_EN */ -+ xf_emit(ctx, 1, 0); /* 00000001 DEPTH_TEST_ENABLE */ -+ xf_emit(ctx, 1, 0); /* 00000001 DEPTH_WRITE_ENABLE */ -+ xf_emit(ctx, 1, 0x11); /* 3f/7f DST_FORMAT */ -+ xf_emit(ctx, 1, 1); /* 00000001 DST_LINEAR */ -+ xf_emit(ctx, 1, 0); /* 000fffff BLIT_DU_DX_FRACT */ -+ xf_emit(ctx, 1, 1); /* 0001ffff BLIT_DU_DX_INT */ -+ xf_emit(ctx, 1, 0); /* 000fffff BLIT_DV_DY_FRACT */ -+ xf_emit(ctx, 1, 1); /* 0001ffff BLIT_DV_DY_INT */ -+ xf_emit(ctx, 1, 0); /* ff/3ff */ -+ xf_emit(ctx, 1, magic1); /* 3ff/7ff tesla UNK0D68 */ -+ xf_emit(ctx, 1, 0); /* 00000001 STENCIL_FRONT_ENABLE */ -+ xf_emit(ctx, 1, 1); /* 00000001 tesla UNK15B4 */ -+ xf_emit(ctx, 1, 0); /* 0000000f ZETA_FORMAT */ -+ 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)) -+ xf_emit(ctx, 1, 1); /* 0000001f tesla UNK169C */ -+ xf_emit(ctx, 8, 0); /* 0000ffff DMA_COLOR */ -+ xf_emit(ctx, 1, 0); /* 0000ffff DMA_GLOBAL */ -+ xf_emit(ctx, 1, 0); /* 0000ffff DMA_LOCAL */ -+ xf_emit(ctx, 1, 0); /* 0000ffff DMA_STACK */ -+ xf_emit(ctx, 1, 0); /* ff/3ff */ -+ xf_emit(ctx, 1, 0); /* 0000ffff DMA_DST */ -+ xf_emit(ctx, 1, 0); /* 7 */ -+ xf_emit(ctx, 1, 0); /* 7/f MULTISAMPLE_SAMPLES_LOG2 */ -+ xf_emit(ctx, 1, 0); /* ffff0ff3 */ -+ xf_emit(ctx, 8, 0); /* 000000ff RT_ADDRESS_HIGH */ -+ xf_emit(ctx, 8, 0); /* ffffffff RT_LAYER_STRIDE */ -+ xf_emit(ctx, 8, 0); /* ffffffff RT_ADDRESS_LOW */ -+ xf_emit(ctx, 8, 8); /* 0000007f RT_TILE_MODE */ -+ xf_emit(ctx, 1, 0x11); /* 3f/7f RT_FORMAT */ -+ xf_emit(ctx, 7, 0); /* 3f/7f RT_FORMAT */ -+ xf_emit(ctx, 1, 0x0fac6881); /* 0fffffff RT_CONTROL */ -+ xf_emit(ctx, 8, 0x400); /* 0fffffff RT_HORIZ */ -+ xf_emit(ctx, 8, 0x300); /* 0000ffff RT_VERT */ -+ xf_emit(ctx, 1, 1); /* 00001fff RT_ARRAY_MODE */ -+ xf_emit(ctx, 1, 0xf); /* 0000000f COLOR_MASK */ -+ xf_emit(ctx, 7, 0); /* 0000000f COLOR_MASK */ -+ xf_emit(ctx, 1, 0x20); /* 00000fff DST_TILE_MODE */ -+ xf_emit(ctx, 1, 0x11); /* 3f/7f DST_FORMAT */ -+ xf_emit(ctx, 1, 0x100); /* 0001ffff DST_HEIGHT */ -+ xf_emit(ctx, 1, 0); /* 000007ff DST_LAYER */ -+ xf_emit(ctx, 1, 1); /* 00000001 DST_LINEAR */ -+ xf_emit(ctx, 1, 0); /* ffffffff DST_ADDRESS_LOW */ -+ xf_emit(ctx, 1, 0); /* 000000ff DST_ADDRESS_HIGH */ -+ xf_emit(ctx, 1, 0x40); /* 0007ffff DST_PITCH */ -+ xf_emit(ctx, 1, 0x100); /* 0001ffff DST_WIDTH */ -+ xf_emit(ctx, 1, 0); /* 0000ffff */ -+ xf_emit(ctx, 1, 3); /* 00000003 tesla UNK15AC */ -+ xf_emit(ctx, 1, 0); /* ff/3ff */ -+ 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)) -+ 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 */ -+ xf_emit(ctx, 1, 0); /* 00000001 tesla UNK1534 */ -+ xf_emit(ctx, 1, 0); /* ffff0ff3 */ -+ xf_emit(ctx, 1, 2); /* 00000003 tesla UNK143C */ -+ xf_emit(ctx, 1, 0x0fac6881); /* 0fffffff RT_CONTROL */ -+ xf_emit(ctx, 1, 0); /* 0000ffff DMA_ZETA */ -+ xf_emit(ctx, 1, 0); /* 00000001 DEPTH_BOUNDS_EN */ -+ xf_emit(ctx, 1, 0); /* 00000001 DEPTH_TEST_ENABLE */ -+ xf_emit(ctx, 1, 0); /* 00000001 DEPTH_WRITE_ENABLE */ -+ xf_emit(ctx, 2, 0); /* ffff, ff/3ff */ -+ xf_emit(ctx, 1, 0); /* 0001ffff GP_BUILTIN_RESULT_EN */ -+ xf_emit(ctx, 1, 0); /* 00000001 STENCIL_FRONT_ENABLE */ -+ xf_emit(ctx, 1, 0); /* 000000ff STENCIL_FRONT_MASK */ -+ xf_emit(ctx, 1, 1); /* 00000001 tesla UNK15B4 */ -+ xf_emit(ctx, 1, 0); /* 00000007 */ -+ xf_emit(ctx, 1, 0); /* ffffffff ZETA_LAYER_STRIDE */ -+ xf_emit(ctx, 1, 0); /* 000000ff ZETA_ADDRESS_HIGH */ -+ xf_emit(ctx, 1, 0); /* ffffffff ZETA_ADDRESS_LOW */ -+ xf_emit(ctx, 1, 4); /* 00000007 ZETA_TILE_MODE */ -+ xf_emit(ctx, 1, 0); /* 0000000f ZETA_FORMAT */ -+ xf_emit(ctx, 1, 1); /* 00000001 ZETA_ENABLE */ -+ xf_emit(ctx, 1, 0x400); /* 0fffffff ZETA_HORIZ */ -+ xf_emit(ctx, 1, 0x300); /* 0000ffff ZETA_VERT */ -+ 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)) -+ xf_emit(ctx, 1, 0); /* 00000001 */ -+ xf_emit(ctx, 1, 0); /* ffff0ff3 */ -+ xf_emit(ctx, 1, 0x11); /* 3f/7f RT_FORMAT */ -+ xf_emit(ctx, 7, 0); /* 3f/7f RT_FORMAT */ -+ xf_emit(ctx, 1, 0x0fac6881); /* 0fffffff RT_CONTROL */ -+ xf_emit(ctx, 1, 0xf); /* 0000000f COLOR_MASK */ -+ xf_emit(ctx, 7, 0); /* 0000000f COLOR_MASK */ -+ xf_emit(ctx, 1, 0); /* ff/3ff */ -+ xf_emit(ctx, 8, 0); /* 00000001 BLEND_ENABLE */ -+ xf_emit(ctx, 1, 0); /* 00000003 UNK0F90 */ -+ 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)) { -+ 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) -- xf_emit(ctx, 1, 0x0fac6881); -- xf_emit(ctx, 1, magic2); -- xf_emit(ctx, 3, 0); -- xf_emit(ctx, 1, 0x11); -- xf_emit(ctx, 2, 0); -- xf_emit(ctx, 1, 4); -- xf_emit(ctx, 1, 0); -- xf_emit(ctx, 2, 1); -- xf_emit(ctx, 3, 0); -- if (dev_priv->chipset > 0xa0 && dev_priv->chipset < 0xaa) -- xf_emit(ctx, 2, 1); -- else -- xf_emit(ctx, 1, 1); -- if (dev_priv->chipset > 0xa0 && dev_priv->chipset < 0xaa) -- xf_emit(ctx, 2, 0); -- else if (dev_priv->chipset != 0x50) -- xf_emit(ctx, 1, 0); --} -- --static void --nv50_graph_construct_xfer_tp_x3(struct nouveau_grctx *ctx) --{ -- struct drm_nouveau_private *dev_priv = ctx->dev->dev_private; -- xf_emit(ctx, 3, 0); -- xf_emit(ctx, 1, 1); -- xf_emit(ctx, 1, 0); -- xf_emit(ctx, 1, 1); -- if (dev_priv->chipset == 0x50) -- xf_emit(ctx, 2, 0); -- else -- xf_emit(ctx, 3, 0); -- xf_emit(ctx, 1, 0x2a712488); -- xf_emit(ctx, 1, 0); -- xf_emit(ctx, 1, 0x4085c000); -- xf_emit(ctx, 1, 0x40); -- xf_emit(ctx, 1, 0x100); -- xf_emit(ctx, 1, 0x10100); -- xf_emit(ctx, 1, 0x02800000); -+ xf_emit(ctx, 1, 0x0fac6881); /* fffffff */ -+ xf_emit(ctx, 1, magic2); /* 001fffff tesla UNK0F78 */ -+ xf_emit(ctx, 1, 0); /* 00000001 DEPTH_BOUNDS_EN */ -+ xf_emit(ctx, 1, 0); /* 00000001 DEPTH_TEST_ENABLE */ -+ xf_emit(ctx, 1, 0); /* 00000001 DEPTH_WRITE_ENABLE */ -+ xf_emit(ctx, 1, 0x11); /* 3f/7f DST_FORMAT */ -+ xf_emit(ctx, 1, 0); /* 00000001 tesla UNK0FB0 */ -+ xf_emit(ctx, 1, 0); /* ff/3ff */ -+ xf_emit(ctx, 1, 4); /* 00000007 FP_CONTROL */ -+ xf_emit(ctx, 1, 0); /* 00000001 STENCIL_FRONT_ENABLE */ -+ xf_emit(ctx, 1, 1); /* 00000001 tesla UNK15B4 */ -+ xf_emit(ctx, 1, 1); /* 00000001 tesla UNK19CC */ -+ xf_emit(ctx, 1, 0); /* 00000007 */ -+ 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)) { -+ 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) { -+ xf_emit(ctx, 3, 0); /* 7/f, 1, ffff0ff3 */ -+ xf_emit(ctx, 1, 0xfac6881); /* fffffff */ -+ xf_emit(ctx, 4, 0); /* 1, 1, 1, 3ff */ -+ xf_emit(ctx, 1, 4); /* 7 */ -+ xf_emit(ctx, 1, 0); /* 1 */ -+ xf_emit(ctx, 2, 1); /* 1 */ -+ 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)) -+ xf_emit(ctx, 0x9, 0); /* 1 */ -+ else -+ xf_emit(ctx, 0x8, 0); /* 1 */ -+ xf_emit(ctx, 1, 0); /* ffff0ff3 */ -+ xf_emit(ctx, 8, 1); /* 1 */ -+ xf_emit(ctx, 1, 0x11); /* 7f */ -+ xf_emit(ctx, 7, 0); /* 7f */ -+ xf_emit(ctx, 1, 0xfac6881); /* fffffff */ -+ xf_emit(ctx, 1, 0xf); /* f */ -+ xf_emit(ctx, 7, 0); /* f */ -+ 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)) { -+ xf_emit(ctx, 1, 0); /* 00000001 UNK1140 */ -+ xf_emit(ctx, 1, 1); /* 0000001f tesla UNK169C */ -+ } -+ } - } - - static void --nv50_graph_construct_xfer_tp_x4(struct nouveau_grctx *ctx) -+nv50_graph_construct_xfer_tex(struct nouveau_grctx *ctx) - { - struct drm_nouveau_private *dev_priv = ctx->dev->dev_private; -- xf_emit(ctx, 2, 0x04e3bfdf); -- xf_emit(ctx, 1, 1); -- xf_emit(ctx, 1, 0); -- xf_emit(ctx, 1, 0x00ffff00); -- if (dev_priv->chipset > 0xa0 && dev_priv->chipset < 0xaa) -- xf_emit(ctx, 2, 1); -- else -- xf_emit(ctx, 1, 1); -- xf_emit(ctx, 2, 0); -- xf_emit(ctx, 1, 0x00ffff00); -- xf_emit(ctx, 8, 0); -- xf_emit(ctx, 1, 1); -- xf_emit(ctx, 1, 0); -- xf_emit(ctx, 1, 1); -- xf_emit(ctx, 1, 0x30201000); -- xf_emit(ctx, 1, 0x70605040); -- xf_emit(ctx, 1, 0xb8a89888); -- xf_emit(ctx, 1, 0xf8e8d8c8); -- xf_emit(ctx, 1, 0); -- xf_emit(ctx, 1, 0x1a); -+ xf_emit(ctx, 2, 0); /* 1 LINKED_TSC. yes, 2. */ -+ if (dev_priv->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) -+ xf_emit(ctx, 1, 0); /* 3 BLIT_CONTROL */ -+ else -+ xf_emit(ctx, 2, 0); /* 3ff, 1 */ -+ xf_emit(ctx, 1, 0x2a712488); /* ffffffff SRC_TIC_0 */ -+ xf_emit(ctx, 1, 0); /* ffffffff SRC_TIC_1 */ -+ xf_emit(ctx, 1, 0x4085c000); /* ffffffff SRC_TIC_2 */ -+ xf_emit(ctx, 1, 0x40); /* ffffffff SRC_TIC_3 */ -+ xf_emit(ctx, 1, 0x100); /* ffffffff SRC_TIC_4 */ -+ 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) { -+ 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)) { -+ xf_emit(ctx, 1, 0); /* ffffffff tesla UNK1A34? */ -+ xf_emit(ctx, 1, 0); /* 00000003 */ -+ xf_emit(ctx, 1, 0); /* 000003ff */ -+ xf_emit(ctx, 1, 0); /* 00000003 */ -+ xf_emit(ctx, 1, 0); /* 000003ff */ -+ xf_emit(ctx, 1, 0); /* 00000003 tesla UNK1664 / turing UNK03E8 */ -+ xf_emit(ctx, 1, 0); /* 00000003 */ -+ xf_emit(ctx, 1, 0); /* 000003ff */ -+ } else { -+ xf_emit(ctx, 0x6, 0); -+ } -+ xf_emit(ctx, 1, 0); /* ffffffff tesla UNK1A34 */ -+ xf_emit(ctx, 1, 0); /* 0000ffff DMA_TEXTURE */ -+ xf_emit(ctx, 1, 0); /* 0000ffff DMA_SRC */ - } - - static void --nv50_graph_construct_xfer_tp_x5(struct nouveau_grctx *ctx) -+nv50_graph_construct_xfer_unk8cxx(struct nouveau_grctx *ctx) - { - struct drm_nouveau_private *dev_priv = ctx->dev->dev_private; -- xf_emit(ctx, 3, 0); -- xf_emit(ctx, 1, 0xfac6881); -- xf_emit(ctx, 4, 0); -- xf_emit(ctx, 1, 4); -- xf_emit(ctx, 1, 0); -- xf_emit(ctx, 2, 1); -- xf_emit(ctx, 2, 0); -- xf_emit(ctx, 1, 1); -- if (dev_priv->chipset > 0xa0 && dev_priv->chipset < 0xaa) -- xf_emit(ctx, 0xb, 0); -- else -- xf_emit(ctx, 0xa, 0); -- xf_emit(ctx, 8, 1); -- xf_emit(ctx, 1, 0x11); -- xf_emit(ctx, 7, 0); -- xf_emit(ctx, 1, 0xfac6881); -- xf_emit(ctx, 1, 0xf); -- xf_emit(ctx, 7, 0); -- xf_emit(ctx, 1, 0x11); -- xf_emit(ctx, 1, 1); -- if (dev_priv->chipset > 0xa0 && dev_priv->chipset < 0xaa) { -- xf_emit(ctx, 6, 0); -- xf_emit(ctx, 1, 1); -- xf_emit(ctx, 6, 0); -- } else { -- xf_emit(ctx, 0xb, 0); -- } -+ xf_emit(ctx, 1, 0); /* 00000001 UNK1534 */ -+ xf_emit(ctx, 1, 0); /* 7/f MULTISAMPLE_SAMPLES_LOG2 */ -+ xf_emit(ctx, 2, 0); /* 7, ffff0ff3 */ -+ xf_emit(ctx, 1, 0); /* 00000001 DEPTH_TEST_ENABLE */ -+ xf_emit(ctx, 1, 0); /* 00000001 DEPTH_WRITE */ -+ xf_emit(ctx, 1, 0x04e3bfdf); /* ffffffff UNK0D64 */ -+ xf_emit(ctx, 1, 0x04e3bfdf); /* ffffffff UNK0DF4 */ -+ xf_emit(ctx, 1, 1); /* 00000001 UNK15B4 */ -+ 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)) -+ 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 */ -+ xf_emit(ctx, 1, 0x00ffff00); /* 00ffffff LINE_STIPPLE_PATTERN */ -+ xf_emit(ctx, 1, 0); /* 00000001 POLYGON_SMOOTH_ENABLE */ -+ xf_emit(ctx, 1, 0); /* 00000001 UNK1534 */ -+ xf_emit(ctx, 1, 0); /* 7/f MULTISAMPLE_SAMPLES_LOG2 */ -+ xf_emit(ctx, 1, 0); /* 00000001 tesla UNK1658 */ -+ xf_emit(ctx, 1, 0); /* 00000001 LINE_SMOOTH_ENABLE */ -+ xf_emit(ctx, 1, 0); /* ffff0ff3 */ -+ xf_emit(ctx, 1, 0); /* 00000001 DEPTH_TEST_ENABLE */ -+ xf_emit(ctx, 1, 0); /* 00000001 DEPTH_WRITE */ -+ xf_emit(ctx, 1, 1); /* 00000001 UNK15B4 */ -+ xf_emit(ctx, 1, 0); /* 00000001 POINT_SPRITE_ENABLE */ -+ xf_emit(ctx, 1, 1); /* 00000001 tesla UNK165C */ -+ xf_emit(ctx, 1, 0x30201000); /* ffffffff tesla UNK1670 */ -+ xf_emit(ctx, 1, 0x70605040); /* ffffffff tesla UNK1670 */ -+ xf_emit(ctx, 1, 0xb8a89888); /* ffffffff tesla UNK1670 */ -+ xf_emit(ctx, 1, 0xf8e8d8c8); /* ffffffff tesla UNK1670 */ -+ xf_emit(ctx, 1, 0); /* 00000001 VERTEX_TWO_SIDE_ENABLE */ -+ xf_emit(ctx, 1, 0x1a); /* 0000001f POLYGON_MODE */ - } - - static void -@@ -2193,108 +3102,136 @@ - { - struct drm_nouveau_private *dev_priv = ctx->dev->dev_private; - if (dev_priv->chipset < 0xa0) { -- nv50_graph_construct_xfer_tp_x1(ctx); -- nv50_graph_construct_xfer_tp_x2(ctx); -- nv50_graph_construct_xfer_tp_x3(ctx); -- if (dev_priv->chipset == 0x50) -- xf_emit(ctx, 0xf, 0); -- else -- xf_emit(ctx, 0x12, 0); -- nv50_graph_construct_xfer_tp_x4(ctx); -+ nv50_graph_construct_xfer_unk84xx(ctx); -+ nv50_graph_construct_xfer_tprop(ctx); -+ nv50_graph_construct_xfer_tex(ctx); -+ nv50_graph_construct_xfer_unk8cxx(ctx); - } else { -- nv50_graph_construct_xfer_tp_x3(ctx); -- if (dev_priv->chipset < 0xaa) -- xf_emit(ctx, 0xc, 0); -- else -- xf_emit(ctx, 0xa, 0); -- nv50_graph_construct_xfer_tp_x2(ctx); -- nv50_graph_construct_xfer_tp_x5(ctx); -- nv50_graph_construct_xfer_tp_x4(ctx); -- nv50_graph_construct_xfer_tp_x1(ctx); -+ nv50_graph_construct_xfer_tex(ctx); -+ nv50_graph_construct_xfer_tprop(ctx); -+ nv50_graph_construct_xfer_unk8cxx(ctx); -+ nv50_graph_construct_xfer_unk84xx(ctx); - } - } - - static void --nv50_graph_construct_xfer_tp2(struct nouveau_grctx *ctx) -+nv50_graph_construct_xfer_mpc(struct nouveau_grctx *ctx) - { - struct drm_nouveau_private *dev_priv = ctx->dev->dev_private; -- int i, mpcnt; -- if (dev_priv->chipset == 0x98 || dev_priv->chipset == 0xaa) -- mpcnt = 1; -- else if (dev_priv->chipset < 0xa0 || dev_priv->chipset >= 0xa8) -- mpcnt = 2; -- else -- mpcnt = 3; -+ int i, mpcnt = 2; -+ switch (dev_priv->chipset) { -+ case 0x98: -+ case 0xaa: -+ mpcnt = 1; -+ break; -+ case 0x50: -+ case 0x84: -+ case 0x86: -+ case 0x92: -+ case 0x94: -+ case 0x96: -+ case 0xa8: -+ case 0xac: -+ mpcnt = 2; -+ break; -+ case 0xa0: -+ case 0xa3: -+ case 0xa5: -+ case 0xaf: -+ mpcnt = 3; -+ break; -+ } - for (i = 0; i < mpcnt; i++) { -- xf_emit(ctx, 1, 0); -- xf_emit(ctx, 1, 0x80); -- xf_emit(ctx, 1, 0x80007004); -- xf_emit(ctx, 1, 0x04000400); -+ xf_emit(ctx, 1, 0); /* ff */ -+ 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) -- xf_emit(ctx, 1, 0xc0); -- xf_emit(ctx, 1, 0x1000); -- xf_emit(ctx, 2, 0); -- if (dev_priv->chipset == 0x86 || dev_priv->chipset == 0x98 || dev_priv->chipset >= 0xa8) { -- xf_emit(ctx, 1, 0xe00); -- xf_emit(ctx, 1, 0x1e00); -+ 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)) { -+ xf_emit(ctx, 1, 0xe00); /* 7fff */ -+ xf_emit(ctx, 1, 0x1e00); /* 7fff */ - } -- xf_emit(ctx, 1, 1); -- xf_emit(ctx, 2, 0); -+ 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) -- xf_emit(ctx, 2, 0x1000); -- xf_emit(ctx, 1, 1); -- xf_emit(ctx, 1, 0); -- xf_emit(ctx, 1, 4); -- xf_emit(ctx, 1, 2); -- if (dev_priv->chipset >= 0xaa) -- xf_emit(ctx, 0xb, 0); -+ 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)) -+ xf_emit(ctx, 0xb, 0); /* RO */ - else if (dev_priv->chipset >= 0xa0) -- xf_emit(ctx, 0xc, 0); -+ xf_emit(ctx, 0xc, 0); /* RO */ - else -- xf_emit(ctx, 0xa, 0); -+ xf_emit(ctx, 0xa, 0); /* RO */ - } -- xf_emit(ctx, 1, 0x08100c12); -- xf_emit(ctx, 1, 0); -+ xf_emit(ctx, 1, 0x08100c12); /* 1fffffff FP_INTERPOLANT_CTRL */ -+ xf_emit(ctx, 1, 0); /* ff/3ff */ - if (dev_priv->chipset >= 0xa0) { -- xf_emit(ctx, 1, 0x1fe21); -- } -- xf_emit(ctx, 5, 0); -- xf_emit(ctx, 4, 0xffff); -- xf_emit(ctx, 1, 1); -- xf_emit(ctx, 2, 0x10001); -- xf_emit(ctx, 1, 1); -- xf_emit(ctx, 1, 0); -- xf_emit(ctx, 1, 0x1fe21); -- xf_emit(ctx, 1, 0); -- if (dev_priv->chipset > 0xa0 && dev_priv->chipset < 0xaa) -- xf_emit(ctx, 1, 1); -- xf_emit(ctx, 4, 0); -- xf_emit(ctx, 1, 0x08100c12); -- xf_emit(ctx, 1, 4); -- xf_emit(ctx, 1, 0); -- xf_emit(ctx, 1, 2); -- xf_emit(ctx, 1, 0x11); -- xf_emit(ctx, 8, 0); -- xf_emit(ctx, 1, 0xfac6881); -- xf_emit(ctx, 1, 0); -- if (dev_priv->chipset > 0xa0 && dev_priv->chipset < 0xaa) -- xf_emit(ctx, 1, 3); -- xf_emit(ctx, 3, 0); -- xf_emit(ctx, 1, 4); -- xf_emit(ctx, 9, 0); -- xf_emit(ctx, 1, 2); -- xf_emit(ctx, 2, 1); -- xf_emit(ctx, 1, 2); -- xf_emit(ctx, 3, 1); -- xf_emit(ctx, 1, 0); -- if (dev_priv->chipset > 0xa0 && dev_priv->chipset < 0xaa) { -- xf_emit(ctx, 8, 2); -- xf_emit(ctx, 0x10, 1); -- xf_emit(ctx, 8, 2); -- xf_emit(ctx, 0x18, 1); -- xf_emit(ctx, 3, 0); -+ xf_emit(ctx, 1, 0x1fe21); /* 0003ffff tesla UNK0FAC */ - } -- xf_emit(ctx, 1, 4); -+ xf_emit(ctx, 3, 0); /* 7fff, 0, 0 */ -+ xf_emit(ctx, 1, 0); /* 00000001 tesla UNK1534 */ -+ xf_emit(ctx, 1, 0); /* 7/f MULTISAMPLE_SAMPLES_LOG2 */ -+ xf_emit(ctx, 4, 0xffff); /* 0000ffff MSAA_MASK */ -+ xf_emit(ctx, 1, 1); /* 00000001 LANES32 */ -+ xf_emit(ctx, 1, 0x10001); /* 00ffffff BLOCK_ALLOC */ -+ xf_emit(ctx, 1, 0x10001); /* ffffffff BLOCKDIM_XY */ -+ xf_emit(ctx, 1, 1); /* 0000ffff BLOCKDIM_Z */ -+ 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)) -+ xf_emit(ctx, 1, 1); /* 0000001f tesla UNK169C */ -+ xf_emit(ctx, 1, 0); /* ff/3ff */ -+ xf_emit(ctx, 1, 0); /* 1 LINKED_TSC */ -+ xf_emit(ctx, 1, 0); /* ff FP_ADDRESS_HIGH */ -+ xf_emit(ctx, 1, 0); /* ffffffff FP_ADDRESS_LOW */ -+ xf_emit(ctx, 1, 0x08100c12); /* 1fffffff FP_INTERPOLANT_CTRL */ -+ xf_emit(ctx, 1, 4); /* 00000007 FP_CONTROL */ -+ xf_emit(ctx, 1, 0); /* 000000ff FRAG_COLOR_CLAMP_EN */ -+ xf_emit(ctx, 1, 2); /* 00000003 REG_MODE */ -+ xf_emit(ctx, 1, 0x11); /* 0000007f RT_FORMAT */ -+ xf_emit(ctx, 7, 0); /* 0000007f RT_FORMAT */ -+ 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)) -+ 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 */ -+ xf_emit(ctx, 1, 0); /* 00000001 FRAMEBUFFER_SRGB */ -+ xf_emit(ctx, 1, 4); /* ffffffff tesla UNK1400 */ -+ xf_emit(ctx, 8, 0); /* 00000001 BLEND_ENABLE */ -+ xf_emit(ctx, 1, 0); /* 00000001 LOGIC_OP_ENABLE */ -+ xf_emit(ctx, 1, 2); /* 0000001f BLEND_FUNC_SRC_RGB */ -+ 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_ALPHA */ -+ 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)) { -+ 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 */ -+ xf_emit(ctx, 8, 1); /* 00000007 IBLEND_EQUATION_RGB */ -+ xf_emit(ctx, 8, 2); /* 0000001f IBLEND_FUNC_SRC_ALPHA */ -+ xf_emit(ctx, 8, 1); /* 0000001f IBLEND_FUNC_DST_ALPHA */ -+ xf_emit(ctx, 8, 1); /* 00000007 IBLEND_EQUATION_ALPHA */ -+ xf_emit(ctx, 8, 1); /* 00000001 IBLEND_UNK00 */ -+ xf_emit(ctx, 1, 0); /* 00000003 tesla UNK1928 */ -+ xf_emit(ctx, 1, 0); /* 00000001 UNK1140 */ -+ } -+ 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) - xf_emit(ctx, 0x3a0, 0); - else if (dev_priv->chipset < 0x94) -@@ -2303,9 +3240,9 @@ - xf_emit(ctx, 0x39f, 0); - else - xf_emit(ctx, 0x3a3, 0); -- xf_emit(ctx, 1, 0x11); -- xf_emit(ctx, 1, 0); -- xf_emit(ctx, 1, 1); -+ xf_emit(ctx, 1, 0x11); /* 3f/7f DST_FORMAT */ -+ xf_emit(ctx, 1, 0); /* 7 OPERATION */ -+ xf_emit(ctx, 1, 1); /* 1 DST_LINEAR */ - xf_emit(ctx, 0x2d, 0); - } - -@@ -2323,52 +3260,56 @@ - if (dev_priv->chipset < 0xa0) { - for (i = 0; i < 8; i++) { - ctx->ctxvals_pos = offset + i; -+ /* that little bugger belongs to csched. No idea -+ * what it's doing here. */ - if (i == 0) -- xf_emit(ctx, 1, 0x08100c12); -+ xf_emit(ctx, 1, 0x08100c12); /* FP_INTERPOLANT_CTRL */ - if (units & (1 << i)) -- nv50_graph_construct_xfer_tp2(ctx); -+ nv50_graph_construct_xfer_mpc(ctx); - if ((ctx->ctxvals_pos-offset)/8 > size) - size = (ctx->ctxvals_pos-offset)/8; - } - } else { - /* Strand 0: TPs 0, 1 */ - ctx->ctxvals_pos = offset; -- xf_emit(ctx, 1, 0x08100c12); -+ /* that little bugger belongs to csched. No idea -+ * what it's doing here. */ -+ xf_emit(ctx, 1, 0x08100c12); /* FP_INTERPOLANT_CTRL */ - if (units & (1 << 0)) -- nv50_graph_construct_xfer_tp2(ctx); -+ nv50_graph_construct_xfer_mpc(ctx); - if (units & (1 << 1)) -- nv50_graph_construct_xfer_tp2(ctx); -+ nv50_graph_construct_xfer_mpc(ctx); - if ((ctx->ctxvals_pos-offset)/8 > size) - size = (ctx->ctxvals_pos-offset)/8; - -- /* Strand 0: TPs 2, 3 */ -+ /* Strand 1: TPs 2, 3 */ - ctx->ctxvals_pos = offset + 1; - if (units & (1 << 2)) -- nv50_graph_construct_xfer_tp2(ctx); -+ nv50_graph_construct_xfer_mpc(ctx); - if (units & (1 << 3)) -- nv50_graph_construct_xfer_tp2(ctx); -+ nv50_graph_construct_xfer_mpc(ctx); - if ((ctx->ctxvals_pos-offset)/8 > size) - size = (ctx->ctxvals_pos-offset)/8; - -- /* Strand 0: TPs 4, 5, 6 */ -+ /* Strand 2: TPs 4, 5, 6 */ - ctx->ctxvals_pos = offset + 2; - if (units & (1 << 4)) -- nv50_graph_construct_xfer_tp2(ctx); -+ nv50_graph_construct_xfer_mpc(ctx); - if (units & (1 << 5)) -- nv50_graph_construct_xfer_tp2(ctx); -+ nv50_graph_construct_xfer_mpc(ctx); - if (units & (1 << 6)) -- nv50_graph_construct_xfer_tp2(ctx); -+ nv50_graph_construct_xfer_mpc(ctx); - if ((ctx->ctxvals_pos-offset)/8 > size) - size = (ctx->ctxvals_pos-offset)/8; - -- /* Strand 0: TPs 7, 8, 9 */ -+ /* Strand 3: TPs 7, 8, 9 */ - ctx->ctxvals_pos = offset + 3; - if (units & (1 << 7)) -- nv50_graph_construct_xfer_tp2(ctx); -+ nv50_graph_construct_xfer_mpc(ctx); - if (units & (1 << 8)) -- nv50_graph_construct_xfer_tp2(ctx); -+ nv50_graph_construct_xfer_mpc(ctx); - if (units & (1 << 9)) -- nv50_graph_construct_xfer_tp2(ctx); -+ nv50_graph_construct_xfer_mpc(ctx); - if ((ctx->ctxvals_pos-offset)/8 > size) - size = (ctx->ctxvals_pos-offset)/8; - } -diff -Naur linux-2.6.36/drivers/gpu/drm/nouveau/nv50_instmem.c linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nv50_instmem.c ---- linux-2.6.36/drivers/gpu/drm/nouveau/nv50_instmem.c 2010-10-20 22:30:22.000000000 +0200 -+++ linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nv50_instmem.c 2010-11-05 00:40:00.000000000 +0100 -@@ -32,39 +32,87 @@ - struct nv50_instmem_priv { - uint32_t save1700[5]; /* 0x1700->0x1710 */ - -- struct nouveau_gpuobj_ref *pramin_pt; -- struct nouveau_gpuobj_ref *pramin_bar; -- struct nouveau_gpuobj_ref *fb_bar; -+ struct nouveau_gpuobj *pramin_pt; -+ struct nouveau_gpuobj *pramin_bar; -+ struct nouveau_gpuobj *fb_bar; - }; - --#define NV50_INSTMEM_PAGE_SHIFT 12 --#define NV50_INSTMEM_PAGE_SIZE (1 << NV50_INSTMEM_PAGE_SHIFT) --#define NV50_INSTMEM_PT_SIZE(a) (((a) >> 12) << 3) -- --/*NOTE: - Assumes 0x1700 already covers the correct MiB of PRAMIN -- */ --#define BAR0_WI32(g, o, v) do { \ -- uint32_t offset; \ -- if ((g)->im_backing) { \ -- offset = (g)->im_backing_start; \ -- } else { \ -- offset = chan->ramin->gpuobj->im_backing_start; \ -- offset += (g)->im_pramin->start; \ -- } \ -- offset += (o); \ -- nv_wr32(dev, NV_RAMIN + (offset & 0xfffff), (v)); \ --} while (0) -+static void -+nv50_channel_del(struct nouveau_channel **pchan) -+{ -+ struct nouveau_channel *chan; -+ -+ chan = *pchan; -+ *pchan = NULL; -+ if (!chan) -+ return; -+ -+ nouveau_gpuobj_ref(NULL, &chan->ramfc); -+ nouveau_gpuobj_ref(NULL, &chan->vm_pd); -+ if (chan->ramin_heap.free_stack.next) -+ drm_mm_takedown(&chan->ramin_heap); -+ nouveau_gpuobj_ref(NULL, &chan->ramin); -+ kfree(chan); -+} -+ -+static int -+nv50_channel_new(struct drm_device *dev, u32 size, -+ struct nouveau_channel **pchan) -+{ -+ struct drm_nouveau_private *dev_priv = dev->dev_private; -+ u32 pgd = (dev_priv->chipset == 0x50) ? 0x1400 : 0x0200; -+ u32 fc = (dev_priv->chipset == 0x50) ? 0x0000 : 0x4200; -+ 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) { -+ nv50_channel_del(&chan); -+ return ret; -+ } -+ -+ ret = drm_mm_init(&chan->ramin_heap, 0x6000, chan->ramin->size); -+ if (ret) { -+ nv50_channel_del(&chan); -+ return ret; -+ } -+ -+ ret = nouveau_gpuobj_new_fake(dev, chan->ramin->pinst == ~0 ? ~0 : -+ chan->ramin->pinst + pgd, -+ chan->ramin->vinst + pgd, -+ 0x4000, NVOBJ_FLAG_ZERO_ALLOC, -+ &chan->vm_pd); -+ if (ret) { -+ nv50_channel_del(&chan); -+ return ret; -+ } -+ -+ ret = nouveau_gpuobj_new_fake(dev, chan->ramin->pinst == ~0 ? ~0 : -+ chan->ramin->pinst + fc, -+ chan->ramin->vinst + fc, 0x100, -+ NVOBJ_FLAG_ZERO_ALLOC, &chan->ramfc); -+ if (ret) { -+ nv50_channel_del(&chan); -+ return ret; -+ } -+ -+ *pchan = chan; -+ return 0; -+} - - int - nv50_instmem_init(struct drm_device *dev) - { - struct drm_nouveau_private *dev_priv = dev->dev_private; -- struct nouveau_channel *chan; -- uint32_t c_offset, c_size, c_ramfc, c_vmpd, c_base, pt_size; -- uint32_t save_nv001700; -- uint64_t v; - struct nv50_instmem_priv *priv; -+ struct nouveau_channel *chan; - int ret, i; -+ u32 tmp; - - priv = kzalloc(sizeof(*priv), GFP_KERNEL); - if (!priv) -@@ -75,212 +123,115 @@ - for (i = 0x1700; i <= 0x1710; i += 4) - priv->save1700[(i-0x1700)/4] = nv_rd32(dev, i); - -- /* Reserve the last MiB of VRAM, we should probably try to avoid -- * setting up the below tables over the top of the VBIOS image at -- * some point. -- */ -- dev_priv->ramin_rsvd_vram = 1 << 20; -- c_offset = dev_priv->vram_size - dev_priv->ramin_rsvd_vram; -- c_size = 128 << 10; -- c_vmpd = ((dev_priv->chipset & 0xf0) == 0x50) ? 0x1400 : 0x200; -- c_ramfc = ((dev_priv->chipset & 0xf0) == 0x50) ? 0x0 : 0x20; -- c_base = c_vmpd + 0x4000; -- pt_size = NV50_INSTMEM_PT_SIZE(dev_priv->ramin_size); -- -- NV_DEBUG(dev, " Rsvd VRAM base: 0x%08x\n", c_offset); -- NV_DEBUG(dev, " VBIOS image: 0x%08x\n", -- (nv_rd32(dev, 0x619f04) & ~0xff) << 8); -- NV_DEBUG(dev, " Aperture size: %d MiB\n", dev_priv->ramin_size >> 20); -- NV_DEBUG(dev, " PT size: %d KiB\n", pt_size >> 10); -- -- /* Determine VM layout, we need to do this first to make sure -- * we allocate enough memory for all the page tables. -- */ -- dev_priv->vm_gart_base = roundup(NV50_VM_BLOCK, NV50_VM_BLOCK); -- dev_priv->vm_gart_size = NV50_VM_BLOCK; -- -- dev_priv->vm_vram_base = dev_priv->vm_gart_base + dev_priv->vm_gart_size; -- dev_priv->vm_vram_size = dev_priv->vram_size; -- if (dev_priv->vm_vram_size > NV50_VM_MAX_VRAM) -- dev_priv->vm_vram_size = NV50_VM_MAX_VRAM; -- dev_priv->vm_vram_size = roundup(dev_priv->vm_vram_size, NV50_VM_BLOCK); -- dev_priv->vm_vram_pt_nr = dev_priv->vm_vram_size / NV50_VM_BLOCK; -- -- dev_priv->vm_end = dev_priv->vm_vram_base + dev_priv->vm_vram_size; -- -- NV_DEBUG(dev, "NV50VM: GART 0x%016llx-0x%016llx\n", -- dev_priv->vm_gart_base, -- dev_priv->vm_gart_base + dev_priv->vm_gart_size - 1); -- NV_DEBUG(dev, "NV50VM: VRAM 0x%016llx-0x%016llx\n", -- dev_priv->vm_vram_base, -- dev_priv->vm_vram_base + dev_priv->vm_vram_size - 1); -- -- c_size += dev_priv->vm_vram_pt_nr * (NV50_VM_BLOCK / 65536 * 8); -- -- /* Map BAR0 PRAMIN aperture over the memory we want to use */ -- save_nv001700 = nv_rd32(dev, NV50_PUNK_BAR0_PRAMIN); -- nv_wr32(dev, NV50_PUNK_BAR0_PRAMIN, (c_offset >> 16)); -- -- /* Create a fake channel, and use it as our "dummy" channels 0/127. -- * The main reason for creating a channel is so we can use the gpuobj -- * code. However, it's probably worth noting that NVIDIA also setup -- * their channels 0/127 with the same values they configure here. -- * So, there may be some other reason for doing this. -- * -- * Have to create the entire channel manually, as the real channel -- * creation code assumes we have PRAMIN access, and we don't until -- * we're done here. -- */ -- chan = kzalloc(sizeof(*chan), GFP_KERNEL); -- if (!chan) -+ /* 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"); - return -ENOMEM; -- chan->id = 0; -- chan->dev = dev; -- chan->file_priv = (struct drm_file *)-2; -- dev_priv->fifos[0] = dev_priv->fifos[127] = chan; -- -- INIT_LIST_HEAD(&chan->ramht_refs); -+ } - -- /* Channel's PRAMIN object + heap */ -- ret = nouveau_gpuobj_new_fake(dev, 0, c_offset, c_size, 0, -- NULL, &chan->ramin); -+ /* we need a channel to plug into the hw to control the BARs */ -+ ret = nv50_channel_new(dev, 128*1024, &dev_priv->channels.ptr[0]); - if (ret) - return ret; -+ chan = dev_priv->channels.ptr[127] = dev_priv->channels.ptr[0]; - -- if (drm_mm_init(&chan->ramin_heap, c_base, c_size - c_base)) -- return -ENOMEM; -- -- /* RAMFC + zero channel's PRAMIN up to start of VM pagedir */ -- ret = nouveau_gpuobj_new_fake(dev, c_ramfc, c_offset + c_ramfc, -- 0x4000, 0, NULL, &chan->ramfc); -+ /* allocate page table for PRAMIN BAR */ -+ ret = nouveau_gpuobj_new(dev, chan, (dev_priv->ramin_size >> 12) * 8, -+ 0x1000, NVOBJ_FLAG_ZERO_ALLOC, -+ &priv->pramin_pt); - if (ret) - return ret; - -- for (i = 0; i < c_vmpd; i += 4) -- BAR0_WI32(chan->ramin->gpuobj, i, 0); -+ nv_wo32(chan->vm_pd, 0x0000, priv->pramin_pt->vinst | 0x63); -+ nv_wo32(chan->vm_pd, 0x0004, 0); - -- /* VM page directory */ -- ret = nouveau_gpuobj_new_fake(dev, c_vmpd, c_offset + c_vmpd, -- 0x4000, 0, &chan->vm_pd, NULL); -+ /* DMA object for PRAMIN BAR */ -+ ret = nouveau_gpuobj_new(dev, chan, 6*4, 16, 0, &priv->pramin_bar); - if (ret) - return ret; -- for (i = 0; i < 0x4000; i += 8) { -- BAR0_WI32(chan->vm_pd, i + 0x00, 0x00000000); -- BAR0_WI32(chan->vm_pd, i + 0x04, 0x00000000); -- } -+ nv_wo32(priv->pramin_bar, 0x00, 0x7fc00000); -+ nv_wo32(priv->pramin_bar, 0x04, dev_priv->ramin_size - 1); -+ nv_wo32(priv->pramin_bar, 0x08, 0x00000000); -+ nv_wo32(priv->pramin_bar, 0x0c, 0x00000000); -+ nv_wo32(priv->pramin_bar, 0x10, 0x00000000); -+ nv_wo32(priv->pramin_bar, 0x14, 0x00000000); - -- /* PRAMIN page table, cheat and map into VM at 0x0000000000. -- * We map the entire fake channel into the start of the PRAMIN BAR -- */ -- ret = nouveau_gpuobj_new_ref(dev, chan, NULL, 0, pt_size, 0x1000, -- 0, &priv->pramin_pt); -+ /* map channel into PRAMIN, gpuobj didn't do it for us */ -+ ret = nv50_instmem_bind(dev, chan->ramin); - if (ret) - return ret; - -- v = c_offset | 1; -- if (dev_priv->vram_sys_base) { -- v += dev_priv->vram_sys_base; -- v |= 0x30; -+ /* poke regs... */ -+ nv_wr32(dev, 0x001704, 0x00000000 | (chan->ramin->vinst >> 12)); -+ nv_wr32(dev, 0x001704, 0x40000000 | (chan->ramin->vinst >> 12)); -+ nv_wr32(dev, 0x00170c, 0x80000000 | (priv->pramin_bar->cinst >> 4)); -+ -+ tmp = nv_ri32(dev, 0); -+ nv_wi32(dev, 0, ~tmp); -+ if (nv_ri32(dev, 0) != ~tmp) { -+ NV_ERROR(dev, "PRAMIN readback failed\n"); -+ return -EIO; - } -+ nv_wi32(dev, 0, tmp); - -- i = 0; -- while (v < dev_priv->vram_sys_base + c_offset + c_size) { -- BAR0_WI32(priv->pramin_pt->gpuobj, i + 0, lower_32_bits(v)); -- BAR0_WI32(priv->pramin_pt->gpuobj, i + 4, upper_32_bits(v)); -- v += 0x1000; -- i += 8; -- } -+ dev_priv->ramin_available = true; - -- while (i < pt_size) { -- BAR0_WI32(priv->pramin_pt->gpuobj, i + 0, 0x00000000); -- BAR0_WI32(priv->pramin_pt->gpuobj, i + 4, 0x00000000); -- i += 8; -- } -+ /* Determine VM layout */ -+ dev_priv->vm_gart_base = roundup(NV50_VM_BLOCK, NV50_VM_BLOCK); -+ dev_priv->vm_gart_size = NV50_VM_BLOCK; -+ -+ dev_priv->vm_vram_base = dev_priv->vm_gart_base + dev_priv->vm_gart_size; -+ dev_priv->vm_vram_size = dev_priv->vram_size; -+ if (dev_priv->vm_vram_size > NV50_VM_MAX_VRAM) -+ dev_priv->vm_vram_size = NV50_VM_MAX_VRAM; -+ dev_priv->vm_vram_size = roundup(dev_priv->vm_vram_size, NV50_VM_BLOCK); -+ dev_priv->vm_vram_pt_nr = dev_priv->vm_vram_size / NV50_VM_BLOCK; - -- BAR0_WI32(chan->vm_pd, 0x00, priv->pramin_pt->instance | 0x63); -- BAR0_WI32(chan->vm_pd, 0x04, 0x00000000); -+ dev_priv->vm_end = dev_priv->vm_vram_base + dev_priv->vm_vram_size; -+ -+ NV_DEBUG(dev, "NV50VM: GART 0x%016llx-0x%016llx\n", -+ dev_priv->vm_gart_base, -+ dev_priv->vm_gart_base + dev_priv->vm_gart_size - 1); -+ NV_DEBUG(dev, "NV50VM: VRAM 0x%016llx-0x%016llx\n", -+ dev_priv->vm_vram_base, -+ dev_priv->vm_vram_base + dev_priv->vm_vram_size - 1); - - /* VRAM page table(s), mapped into VM at +1GiB */ - for (i = 0; i < dev_priv->vm_vram_pt_nr; i++) { -- ret = nouveau_gpuobj_new_ref(dev, chan, NULL, 0, -- NV50_VM_BLOCK/65536*8, 0, 0, -- &chan->vm_vram_pt[i]); -+ ret = nouveau_gpuobj_new(dev, NULL, NV50_VM_BLOCK / 0x10000 * 8, -+ 0, NVOBJ_FLAG_ZERO_ALLOC, -+ &chan->vm_vram_pt[i]); - if (ret) { -- NV_ERROR(dev, "Error creating VRAM page tables: %d\n", -- ret); -+ NV_ERROR(dev, "Error creating VRAM PGT: %d\n", ret); - dev_priv->vm_vram_pt_nr = i; - return ret; - } -- dev_priv->vm_vram_pt[i] = chan->vm_vram_pt[i]->gpuobj; -+ dev_priv->vm_vram_pt[i] = chan->vm_vram_pt[i]; - -- for (v = 0; v < dev_priv->vm_vram_pt[i]->im_pramin->size; -- v += 4) -- BAR0_WI32(dev_priv->vm_vram_pt[i], v, 0); -- -- BAR0_WI32(chan->vm_pd, 0x10 + (i*8), -- chan->vm_vram_pt[i]->instance | 0x61); -- BAR0_WI32(chan->vm_pd, 0x14 + (i*8), 0); -+ nv_wo32(chan->vm_pd, 0x10 + (i*8), -+ chan->vm_vram_pt[i]->vinst | 0x61); -+ nv_wo32(chan->vm_pd, 0x14 + (i*8), 0); - } - -- /* DMA object for PRAMIN BAR */ -- ret = nouveau_gpuobj_new_ref(dev, chan, chan, 0, 6*4, 16, 0, -- &priv->pramin_bar); -- if (ret) -- return ret; -- BAR0_WI32(priv->pramin_bar->gpuobj, 0x00, 0x7fc00000); -- BAR0_WI32(priv->pramin_bar->gpuobj, 0x04, dev_priv->ramin_size - 1); -- BAR0_WI32(priv->pramin_bar->gpuobj, 0x08, 0x00000000); -- BAR0_WI32(priv->pramin_bar->gpuobj, 0x0c, 0x00000000); -- BAR0_WI32(priv->pramin_bar->gpuobj, 0x10, 0x00000000); -- BAR0_WI32(priv->pramin_bar->gpuobj, 0x14, 0x00000000); -- - /* DMA object for FB BAR */ -- ret = nouveau_gpuobj_new_ref(dev, chan, chan, 0, 6*4, 16, 0, -- &priv->fb_bar); -+ ret = nouveau_gpuobj_new(dev, chan, 6*4, 16, 0, &priv->fb_bar); - if (ret) - return ret; -- BAR0_WI32(priv->fb_bar->gpuobj, 0x00, 0x7fc00000); -- BAR0_WI32(priv->fb_bar->gpuobj, 0x04, 0x40000000 + -- pci_resource_len(dev->pdev, 1) - 1); -- BAR0_WI32(priv->fb_bar->gpuobj, 0x08, 0x40000000); -- BAR0_WI32(priv->fb_bar->gpuobj, 0x0c, 0x00000000); -- BAR0_WI32(priv->fb_bar->gpuobj, 0x10, 0x00000000); -- BAR0_WI32(priv->fb_bar->gpuobj, 0x14, 0x00000000); -+ nv_wo32(priv->fb_bar, 0x00, 0x7fc00000); -+ nv_wo32(priv->fb_bar, 0x04, 0x40000000 + -+ pci_resource_len(dev->pdev, 1) - 1); -+ nv_wo32(priv->fb_bar, 0x08, 0x40000000); -+ nv_wo32(priv->fb_bar, 0x0c, 0x00000000); -+ nv_wo32(priv->fb_bar, 0x10, 0x00000000); -+ nv_wo32(priv->fb_bar, 0x14, 0x00000000); - -- /* Poke the relevant regs, and pray it works :) */ -- nv_wr32(dev, NV50_PUNK_BAR_CFG_BASE, (chan->ramin->instance >> 12)); -- nv_wr32(dev, NV50_PUNK_UNK1710, 0); -- nv_wr32(dev, NV50_PUNK_BAR_CFG_BASE, (chan->ramin->instance >> 12) | -- NV50_PUNK_BAR_CFG_BASE_VALID); -- nv_wr32(dev, NV50_PUNK_BAR1_CTXDMA, (priv->fb_bar->instance >> 4) | -- NV50_PUNK_BAR1_CTXDMA_VALID); -- nv_wr32(dev, NV50_PUNK_BAR3_CTXDMA, (priv->pramin_bar->instance >> 4) | -- NV50_PUNK_BAR3_CTXDMA_VALID); -+ dev_priv->engine.instmem.flush(dev); - -+ nv_wr32(dev, 0x001708, 0x80000000 | (priv->fb_bar->cinst >> 4)); - for (i = 0; i < 8; i++) - nv_wr32(dev, 0x1900 + (i*4), 0); - -- /* Assume that praying isn't enough, check that we can re-read the -- * entire fake channel back from the PRAMIN BAR */ -- for (i = 0; i < c_size; i += 4) { -- if (nv_rd32(dev, NV_RAMIN + i) != nv_ri32(dev, i)) { -- NV_ERROR(dev, "Error reading back PRAMIN at 0x%08x\n", -- i); -- return -EINVAL; -- } -- } -- -- nv_wr32(dev, NV50_PUNK_BAR0_PRAMIN, save_nv001700); -- -- /* Global PRAMIN heap */ -- if (drm_mm_init(&dev_priv->ramin_heap, c_size, dev_priv->ramin_size - c_size)) { -- NV_ERROR(dev, "Failed to init RAMIN heap\n"); -- } -- -- /*XXX: incorrect, but needed to make hash func "work" */ -- dev_priv->ramht_offset = 0x10000; -- dev_priv->ramht_bits = 9; -- dev_priv->ramht_size = (1 << dev_priv->ramht_bits) * 8; - return 0; - } - -@@ -289,7 +240,7 @@ - { - 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->fifos[0]; -+ struct nouveau_channel *chan = dev_priv->channels.ptr[0]; - int i; - - NV_DEBUG(dev, "\n"); -@@ -297,29 +248,24 @@ - if (!priv) - return; - -+ dev_priv->ramin_available = false; -+ - /* Restore state from before init */ - for (i = 0x1700; i <= 0x1710; i += 4) - nv_wr32(dev, i, priv->save1700[(i - 0x1700) / 4]); - -- nouveau_gpuobj_ref_del(dev, &priv->fb_bar); -- nouveau_gpuobj_ref_del(dev, &priv->pramin_bar); -- nouveau_gpuobj_ref_del(dev, &priv->pramin_pt); -+ nouveau_gpuobj_ref(NULL, &priv->fb_bar); -+ nouveau_gpuobj_ref(NULL, &priv->pramin_bar); -+ nouveau_gpuobj_ref(NULL, &priv->pramin_pt); - - /* Destroy dummy channel */ - if (chan) { -- for (i = 0; i < dev_priv->vm_vram_pt_nr; i++) { -- nouveau_gpuobj_ref_del(dev, &chan->vm_vram_pt[i]); -- dev_priv->vm_vram_pt[i] = NULL; -- } -+ for (i = 0; i < dev_priv->vm_vram_pt_nr; i++) -+ nouveau_gpuobj_ref(NULL, &chan->vm_vram_pt[i]); - dev_priv->vm_vram_pt_nr = 0; - -- nouveau_gpuobj_del(dev, &chan->vm_pd); -- nouveau_gpuobj_ref_del(dev, &chan->ramfc); -- nouveau_gpuobj_ref_del(dev, &chan->ramin); -- drm_mm_takedown(&chan->ramin_heap); -- -- dev_priv->fifos[0] = dev_priv->fifos[127] = NULL; -- kfree(chan); -+ nv50_channel_del(&dev_priv->channels.ptr[0]); -+ dev_priv->channels.ptr[127] = NULL; - } - - dev_priv->engine.instmem.priv = NULL; -@@ -330,15 +276,15 @@ - nv50_instmem_suspend(struct drm_device *dev) - { - struct drm_nouveau_private *dev_priv = dev->dev_private; -- struct nouveau_channel *chan = dev_priv->fifos[0]; -- struct nouveau_gpuobj *ramin = chan->ramin->gpuobj; -+ struct nouveau_channel *chan = dev_priv->channels.ptr[0]; -+ struct nouveau_gpuobj *ramin = chan->ramin; - int i; - -- ramin->im_backing_suspend = vmalloc(ramin->im_pramin->size); -+ ramin->im_backing_suspend = vmalloc(ramin->size); - if (!ramin->im_backing_suspend) - return -ENOMEM; - -- for (i = 0; i < ramin->im_pramin->size; i += 4) -+ for (i = 0; i < ramin->size; i += 4) - ramin->im_backing_suspend[i/4] = nv_ri32(dev, i); - return 0; - } -@@ -348,24 +294,26 @@ - { - 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->fifos[0]; -- struct nouveau_gpuobj *ramin = chan->ramin->gpuobj; -+ struct nouveau_channel *chan = dev_priv->channels.ptr[0]; -+ struct nouveau_gpuobj *ramin = chan->ramin; - int i; - -- nv_wr32(dev, NV50_PUNK_BAR0_PRAMIN, (ramin->im_backing_start >> 16)); -- for (i = 0; i < ramin->im_pramin->size; i += 4) -- BAR0_WI32(ramin, i, ramin->im_backing_suspend[i/4]); -+ dev_priv->ramin_available = false; -+ dev_priv->ramin_base = ~0; -+ for (i = 0; i < ramin->size; i += 4) -+ nv_wo32(ramin, i, ramin->im_backing_suspend[i/4]); -+ dev_priv->ramin_available = true; - vfree(ramin->im_backing_suspend); - ramin->im_backing_suspend = NULL; - - /* Poke the relevant regs, and pray it works :) */ -- nv_wr32(dev, NV50_PUNK_BAR_CFG_BASE, (chan->ramin->instance >> 12)); -+ 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->instance >> 12) | -+ 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->fb_bar->instance >> 4) | -+ nv_wr32(dev, NV50_PUNK_BAR1_CTXDMA, (priv->fb_bar->cinst >> 4) | - NV50_PUNK_BAR1_CTXDMA_VALID); -- nv_wr32(dev, NV50_PUNK_BAR3_CTXDMA, (priv->pramin_bar->instance >> 4) | -+ nv_wr32(dev, NV50_PUNK_BAR3_CTXDMA, (priv->pramin_bar->cinst >> 4) | - NV50_PUNK_BAR3_CTXDMA_VALID); - - for (i = 0; i < 8; i++) -@@ -374,19 +322,19 @@ - - int - nv50_instmem_populate(struct drm_device *dev, struct nouveau_gpuobj *gpuobj, -- uint32_t *sz) -+ u32 *size, u32 align) - { - int ret; - - if (gpuobj->im_backing) - return -EINVAL; - -- *sz = ALIGN(*sz, NV50_INSTMEM_PAGE_SIZE); -- if (*sz == 0) -+ *size = ALIGN(*size, 4096); -+ if (*size == 0) - return -EINVAL; - -- ret = nouveau_bo_new(dev, NULL, *sz, 0, TTM_PL_FLAG_VRAM, 0, 0x0000, -- true, false, &gpuobj->im_backing); -+ ret = nouveau_bo_new(dev, NULL, *size, align, TTM_PL_FLAG_VRAM, -+ 0, 0x0000, true, false, &gpuobj->im_backing); - if (ret) { - NV_ERROR(dev, "error getting PRAMIN backing pages: %d\n", ret); - return ret; -@@ -399,9 +347,7 @@ - return ret; - } - -- gpuobj->im_backing_start = gpuobj->im_backing->bo.mem.mm_node->start; -- gpuobj->im_backing_start <<= PAGE_SHIFT; -- -+ gpuobj->vinst = gpuobj->im_backing->bo.mem.start << PAGE_SHIFT; - return 0; - } - -@@ -424,7 +370,7 @@ - { - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nv50_instmem_priv *priv = dev_priv->engine.instmem.priv; -- struct nouveau_gpuobj *pramin_pt = priv->pramin_pt->gpuobj; -+ struct nouveau_gpuobj *pramin_pt = priv->pramin_pt; - uint32_t pte, pte_end; - uint64_t vram; - -@@ -436,11 +382,11 @@ - - pte = (gpuobj->im_pramin->start >> 12) << 1; - pte_end = ((gpuobj->im_pramin->size >> 12) << 1) + pte; -- vram = gpuobj->im_backing_start; -+ vram = gpuobj->vinst; - - NV_DEBUG(dev, "pramin=0x%lx, pte=%d, pte_end=%d\n", - gpuobj->im_pramin->start, pte, pte_end); -- NV_DEBUG(dev, "first vram page: 0x%08x\n", gpuobj->im_backing_start); -+ NV_DEBUG(dev, "first vram page: 0x%010llx\n", gpuobj->vinst); - - vram |= 1; - if (dev_priv->vram_sys_base) { -@@ -449,13 +395,13 @@ - } - - while (pte < pte_end) { -- nv_wo32(dev, pramin_pt, pte++, lower_32_bits(vram)); -- nv_wo32(dev, pramin_pt, pte++, upper_32_bits(vram)); -- vram += NV50_INSTMEM_PAGE_SIZE; -+ nv_wo32(pramin_pt, (pte * 4) + 0, lower_32_bits(vram)); -+ nv_wo32(pramin_pt, (pte * 4) + 4, upper_32_bits(vram)); -+ vram += 0x1000; -+ pte += 2; - } - dev_priv->engine.instmem.flush(dev); - -- nv50_vm_flush(dev, 4); - nv50_vm_flush(dev, 6); - - gpuobj->im_bound = 1; -@@ -472,12 +418,17 @@ - if (gpuobj->im_bound == 0) - return -EINVAL; - -+ /* can happen during late takedown */ -+ if (unlikely(!dev_priv->ramin_available)) -+ return 0; -+ - pte = (gpuobj->im_pramin->start >> 12) << 1; - pte_end = ((gpuobj->im_pramin->size >> 12) << 1) + pte; - - while (pte < pte_end) { -- nv_wo32(dev, priv->pramin_pt->gpuobj, pte++, 0x00000000); -- nv_wo32(dev, priv->pramin_pt->gpuobj, pte++, 0x00000000); -+ nv_wo32(priv->pramin_pt, (pte * 4) + 0, 0x00000000); -+ nv_wo32(priv->pramin_pt, (pte * 4) + 4, 0x00000000); -+ pte += 2; - } - dev_priv->engine.instmem.flush(dev); - -@@ -489,7 +440,7 @@ - nv50_instmem_flush(struct drm_device *dev) - { - nv_wr32(dev, 0x00330c, 0x00000001); -- if (!nv_wait(0x00330c, 0x00000002, 0x00000000)) -+ if (!nv_wait(dev, 0x00330c, 0x00000002, 0x00000000)) - NV_ERROR(dev, "PRAMIN flush timeout\n"); - } - -@@ -497,7 +448,7 @@ - nv84_instmem_flush(struct drm_device *dev) - { - nv_wr32(dev, 0x070000, 0x00000001); -- if (!nv_wait(0x070000, 0x00000002, 0x00000000)) -+ if (!nv_wait(dev, 0x070000, 0x00000002, 0x00000000)) - NV_ERROR(dev, "PRAMIN flush timeout\n"); - } - -@@ -505,7 +456,7 @@ - nv50_vm_flush(struct drm_device *dev, int engine) - { - nv_wr32(dev, 0x100c80, (engine << 16) | 1); -- if (!nv_wait(0x100c80, 0x00000001, 0x00000000)) -+ if (!nv_wait(dev, 0x100c80, 0x00000001, 0x00000000)) - NV_ERROR(dev, "vm flush timeout: engine %d\n", engine); - } - -diff -Naur linux-2.6.36/drivers/gpu/drm/nouveau/nv50_pm.c linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nv50_pm.c ---- linux-2.6.36/drivers/gpu/drm/nouveau/nv50_pm.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nv50_pm.c 2010-11-05 00:40:00.000000000 +0100 -@@ -0,0 +1,131 @@ -+/* -+ * Copyright 2010 Red Hat Inc. -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included in -+ * all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR -+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -+ * OTHER DEALINGS IN THE SOFTWARE. -+ * -+ * Authors: Ben Skeggs -+ */ -+ -+#include "drmP.h" -+#include "nouveau_drv.h" -+#include "nouveau_bios.h" -+#include "nouveau_pm.h" -+ -+struct nv50_pm_state { -+ struct nouveau_pm_level *perflvl; -+ struct pll_lims pll; -+ enum pll_types type; -+ int N, M, P; -+}; -+ -+int -+nv50_pm_clock_get(struct drm_device *dev, u32 id) -+{ -+ struct pll_lims pll; -+ int P, N, M, ret; -+ u32 reg0, reg1; -+ -+ ret = get_pll_limits(dev, id, &pll); -+ if (ret) -+ return ret; -+ -+ reg0 = nv_rd32(dev, pll.reg + 0); -+ reg1 = nv_rd32(dev, pll.reg + 4); -+ P = (reg0 & 0x00070000) >> 16; -+ N = (reg1 & 0x0000ff00) >> 8; -+ M = (reg1 & 0x000000ff); -+ -+ return ((pll.refclk * N / M) >> P); -+} -+ -+void * -+nv50_pm_clock_pre(struct drm_device *dev, struct nouveau_pm_level *perflvl, -+ u32 id, int khz) -+{ -+ struct nv50_pm_state *state; -+ int dummy, ret; -+ -+ state = kzalloc(sizeof(*state), GFP_KERNEL); -+ if (!state) -+ return ERR_PTR(-ENOMEM); -+ state->type = id; -+ state->perflvl = perflvl; -+ -+ ret = get_pll_limits(dev, id, &state->pll); -+ if (ret < 0) { -+ kfree(state); -+ return (ret == -ENOENT) ? NULL : ERR_PTR(ret); -+ } -+ -+ ret = nv50_calc_pll(dev, &state->pll, khz, &state->N, &state->M, -+ &dummy, &dummy, &state->P); -+ if (ret < 0) { -+ kfree(state); -+ return ERR_PTR(ret); -+ } -+ -+ return state; -+} -+ -+void -+nv50_pm_clock_set(struct drm_device *dev, void *pre_state) -+{ -+ struct nv50_pm_state *state = pre_state; -+ struct nouveau_pm_level *perflvl = state->perflvl; -+ u32 reg = state->pll.reg, tmp; -+ struct bit_entry BIT_M; -+ u16 script; -+ int N = state->N; -+ int M = state->M; -+ int P = state->P; -+ -+ if (state->type == PLL_MEMORY && perflvl->memscript && -+ bit_table(dev, 'M', &BIT_M) == 0 && -+ BIT_M.version == 1 && BIT_M.length >= 0x0b) { -+ script = ROM16(BIT_M.data[0x05]); -+ if (script) -+ nouveau_bios_run_init_table(dev, script, NULL); -+ script = ROM16(BIT_M.data[0x07]); -+ if (script) -+ nouveau_bios_run_init_table(dev, script, NULL); -+ script = ROM16(BIT_M.data[0x09]); -+ if (script) -+ nouveau_bios_run_init_table(dev, script, NULL); -+ -+ nouveau_bios_run_init_table(dev, perflvl->memscript, NULL); -+ } -+ -+ if (state->type == PLL_MEMORY) { -+ nv_wr32(dev, 0x100210, 0); -+ nv_wr32(dev, 0x1002dc, 1); -+ } -+ -+ tmp = nv_rd32(dev, reg + 0) & 0xfff8ffff; -+ tmp |= 0x80000000 | (P << 16); -+ nv_wr32(dev, reg + 0, tmp); -+ nv_wr32(dev, reg + 4, (N << 8) | M); -+ -+ if (state->type == PLL_MEMORY) { -+ nv_wr32(dev, 0x1002dc, 0); -+ nv_wr32(dev, 0x100210, 0x80000000); -+ } -+ -+ kfree(state); -+} -+ -diff -Naur linux-2.6.36/drivers/gpu/drm/nouveau/nv50_sor.c linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nv50_sor.c ---- linux-2.6.36/drivers/gpu/drm/nouveau/nv50_sor.c 2010-10-20 22:30:22.000000000 +0200 -+++ linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nv50_sor.c 2010-11-05 00:40:00.000000000 +0100 -@@ -92,7 +92,7 @@ - } - - /* wait for it to be done */ -- if (!nv_wait(NV50_PDISPLAY_SOR_DPMS_CTRL(or), -+ if (!nv_wait(dev, 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, -@@ -108,7 +108,7 @@ - - nv_wr32(dev, NV50_PDISPLAY_SOR_DPMS_CTRL(or), val | - NV50_PDISPLAY_SOR_DPMS_CTRL_PENDING); -- if (!nv_wait(NV50_PDISPLAY_SOR_DPMS_STATE(or), -+ if (!nv_wait(dev, 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, -diff -Naur linux-2.6.36/drivers/gpu/drm/nouveau/nv84_crypt.c linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nv84_crypt.c ---- linux-2.6.36/drivers/gpu/drm/nouveau/nv84_crypt.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nv84_crypt.c 2010-11-05 00:40:00.000000000 +0100 -@@ -0,0 +1,110 @@ -+/* -+ * 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" -+ -+int -+nv84_crypt_create_context(struct nouveau_channel *chan) -+{ -+ struct drm_device *dev = chan->dev; -+ struct drm_nouveau_private *dev_priv = dev->dev_private; -+ struct nouveau_gpuobj *ramin = chan->ramin; -+ 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, -+ &chan->crypt_ctx); -+ if (ret) -+ return ret; -+ -+ nv_wo32(ramin, 0xa0, 0x00190000); -+ nv_wo32(ramin, 0xa4, chan->crypt_ctx->vinst + 0xff); -+ nv_wo32(ramin, 0xa8, chan->crypt_ctx->vinst); -+ nv_wo32(ramin, 0xac, 0); -+ nv_wo32(ramin, 0xb0, 0); -+ nv_wo32(ramin, 0xb4, 0); -+ -+ dev_priv->engine.instmem.flush(dev); -+ return 0; -+} -+ -+void -+nv84_crypt_destroy_context(struct nouveau_channel *chan) -+{ -+ struct drm_device *dev = chan->dev; -+ u32 inst; -+ -+ if (!chan->ramin) -+ return; -+ -+ inst = (chan->ramin->vinst >> 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, &chan->crypt_ctx); -+} -+ -+void -+nv84_crypt_tlb_flush(struct drm_device *dev) -+{ -+ nv50_vm_flush(dev, 0x0a); -+} -+ -+int -+nv84_crypt_init(struct drm_device *dev) -+{ -+ struct drm_nouveau_private *dev_priv = dev->dev_private; -+ struct nouveau_crypt_engine *pcrypt = &dev_priv->engine.crypt; -+ -+ if (!pcrypt->registered) { -+ NVOBJ_CLASS(dev, 0x74c1, CRYPT); -+ pcrypt->registered = true; -+ } -+ -+ nv_mask(dev, 0x000200, 0x00004000, 0x00000000); -+ nv_mask(dev, 0x000200, 0x00004000, 0x00004000); -+ nv_wr32(dev, 0x102130, 0xffffffff); -+ nv_wr32(dev, 0x102140, 0xffffffbf); -+ nv_wr32(dev, 0x10200c, 0x00000010); -+ return 0; -+} -+ -+void -+nv84_crypt_fini(struct drm_device *dev) -+{ -+ nv_wr32(dev, 0x102140, 0x00000000); -+} -diff -Naur linux-2.6.36/drivers/gpu/drm/nouveau/nva3_pm.c linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nva3_pm.c ---- linux-2.6.36/drivers/gpu/drm/nouveau/nva3_pm.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nva3_pm.c 2010-11-05 00:40:00.000000000 +0100 -@@ -0,0 +1,95 @@ -+/* -+ * Copyright 2010 Red Hat Inc. -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included in -+ * all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR -+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -+ * OTHER DEALINGS IN THE SOFTWARE. -+ * -+ * Authors: Ben Skeggs -+ */ -+ -+#include "drmP.h" -+#include "nouveau_drv.h" -+#include "nouveau_bios.h" -+#include "nouveau_pm.h" -+ -+/*XXX: boards using limits 0x40 need fixing, the register layout -+ * is correct here, but, there's some other funny magic -+ * that modifies things, so it's not likely we'll set/read -+ * the correct timings yet.. working on it... -+ */ -+ -+struct nva3_pm_state { -+ struct pll_lims pll; -+ int N, M, P; -+}; -+ -+int -+nva3_pm_clock_get(struct drm_device *dev, u32 id) -+{ -+ struct pll_lims pll; -+ int P, N, M, ret; -+ u32 reg; -+ -+ ret = get_pll_limits(dev, id, &pll); -+ if (ret) -+ return ret; -+ -+ reg = nv_rd32(dev, pll.reg + 4); -+ P = (reg & 0x003f0000) >> 16; -+ N = (reg & 0x0000ff00) >> 8; -+ M = (reg & 0x000000ff); -+ return pll.refclk * N / M / P; -+} -+ -+void * -+nva3_pm_clock_pre(struct drm_device *dev, struct nouveau_pm_level *perflvl, -+ u32 id, int khz) -+{ -+ struct nva3_pm_state *state; -+ int dummy, ret; -+ -+ state = kzalloc(sizeof(*state), GFP_KERNEL); -+ if (!state) -+ return ERR_PTR(-ENOMEM); -+ -+ ret = get_pll_limits(dev, id, &state->pll); -+ if (ret < 0) { -+ kfree(state); -+ return (ret == -ENOENT) ? NULL : ERR_PTR(ret); -+ } -+ -+ ret = nv50_calc_pll2(dev, &state->pll, khz, &state->N, &dummy, -+ &state->M, &state->P); -+ if (ret < 0) { -+ kfree(state); -+ return ERR_PTR(ret); -+ } -+ -+ return state; -+} -+ -+void -+nva3_pm_clock_set(struct drm_device *dev, void *pre_state) -+{ -+ struct nva3_pm_state *state = pre_state; -+ u32 reg = state->pll.reg; -+ -+ nv_wr32(dev, reg + 4, (state->P << 16) | (state->N << 8) | state->M); -+ kfree(state); -+} -+ -diff -Naur linux-2.6.36/drivers/gpu/drm/nouveau/nvc0_fifo.c linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nvc0_fifo.c ---- linux-2.6.36/drivers/gpu/drm/nouveau/nvc0_fifo.c 2010-10-20 22:30:22.000000000 +0200 -+++ linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nvc0_fifo.c 2010-11-05 00:40:00.000000000 +0100 -@@ -43,12 +43,6 @@ - } - - bool --nvc0_fifo_cache_flush(struct drm_device *dev) --{ -- return true; --} -- --bool - nvc0_fifo_cache_pull(struct drm_device *dev, bool enable) - { - return false; -diff -Naur linux-2.6.36/drivers/gpu/drm/nouveau/nvc0_instmem.c linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nvc0_instmem.c ---- linux-2.6.36/drivers/gpu/drm/nouveau/nvc0_instmem.c 2010-10-20 22:30:22.000000000 +0200 -+++ linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nvc0_instmem.c 2010-11-05 00:40:00.000000000 +0100 -@@ -28,7 +28,7 @@ - - int - nvc0_instmem_populate(struct drm_device *dev, struct nouveau_gpuobj *gpuobj, -- uint32_t *size) -+ u32 *size, u32 align) - { - int ret; - -@@ -36,8 +36,8 @@ - if (*size == 0) - return -EINVAL; - -- ret = nouveau_bo_new(dev, NULL, *size, 0, TTM_PL_FLAG_VRAM, 0, 0x0000, -- true, false, &gpuobj->im_backing); -+ ret = nouveau_bo_new(dev, NULL, *size, align, TTM_PL_FLAG_VRAM, -+ 0, 0x0000, true, false, &gpuobj->im_backing); - if (ret) { - NV_ERROR(dev, "error getting PRAMIN backing pages: %d\n", ret); - return ret; -@@ -50,8 +50,7 @@ - return ret; - } - -- gpuobj->im_backing_start = gpuobj->im_backing->bo.mem.mm_node->start; -- gpuobj->im_backing_start <<= PAGE_SHIFT; -+ gpuobj->vinst = gpuobj->im_backing->bo.mem.start << PAGE_SHIFT; - return 0; - } - -@@ -84,11 +83,11 @@ - - pte = gpuobj->im_pramin->start >> 12; - pte_end = (gpuobj->im_pramin->size >> 12) + pte; -- vram = gpuobj->im_backing_start; -+ vram = gpuobj->vinst; - - NV_DEBUG(dev, "pramin=0x%lx, pte=%d, pte_end=%d\n", - gpuobj->im_pramin->start, pte, pte_end); -- NV_DEBUG(dev, "first vram page: 0x%08x\n", gpuobj->im_backing_start); -+ NV_DEBUG(dev, "first vram page: 0x%010llx\n", gpuobj->vinst); - - while (pte < pte_end) { - nv_wr32(dev, 0x702000 + (pte * 8), (vram >> 8) | 1); -@@ -134,7 +133,7 @@ - nvc0_instmem_flush(struct drm_device *dev) - { - nv_wr32(dev, 0x070000, 1); -- if (!nv_wait(0x070000, 0x00000002, 0x00000000)) -+ if (!nv_wait(dev, 0x070000, 0x00000002, 0x00000000)) - NV_ERROR(dev, "PRAMIN flush timeout\n"); - } - -@@ -221,10 +220,6 @@ - return -ENOMEM; - } - -- /*XXX: incorrect, but needed to make hash func "work" */ -- dev_priv->ramht_offset = 0x10000; -- dev_priv->ramht_bits = 9; -- dev_priv->ramht_size = (1 << dev_priv->ramht_bits) * 8; - return 0; - } - -diff -Naur linux-2.6.36/drivers/gpu/drm/nouveau/nvreg.h linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nvreg.h ---- linux-2.6.36/drivers/gpu/drm/nouveau/nvreg.h 2010-10-20 22:30:22.000000000 +0200 -+++ linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nvreg.h 2010-11-05 00:40:00.000000000 +0100 -@@ -153,7 +153,8 @@ - #define NV_PCRTC_START 0x00600800 - #define NV_PCRTC_CONFIG 0x00600804 - # define NV_PCRTC_CONFIG_START_ADDRESS_NON_VGA (1 << 0) --# define NV_PCRTC_CONFIG_START_ADDRESS_HSYNC (2 << 0) -+# define NV04_PCRTC_CONFIG_START_ADDRESS_HSYNC (4 << 0) -+# define NV10_PCRTC_CONFIG_START_ADDRESS_HSYNC (2 << 0) - #define NV_PCRTC_CURSOR_CONFIG 0x00600810 - # define NV_PCRTC_CURSOR_CONFIG_ENABLE_ENABLE (1 << 0) - # define NV_PCRTC_CURSOR_CONFIG_DOUBLE_SCAN_ENABLE (1 << 4) -@@ -263,6 +264,7 @@ - # define NV_CIO_CRE_HCUR_ADDR1_ADR 7:2 - # define NV_CIO_CRE_LCD__INDEX 0x33 - # define NV_CIO_CRE_LCD_LCD_SELECT 0:0 -+# define NV_CIO_CRE_LCD_ROUTE_MASK 0x3b - # define NV_CIO_CRE_DDC0_STATUS__INDEX 0x36 - # define NV_CIO_CRE_DDC0_WR__INDEX 0x37 - # define NV_CIO_CRE_ILACE__INDEX 0x39 /* interlace */ -diff -Naur linux-2.6.36/drivers/gpu/drm/radeon/radeon_object.c linux-2.6.36.nouveau/drivers/gpu/drm/radeon/radeon_object.c ---- linux-2.6.36/drivers/gpu/drm/radeon/radeon_object.c 2010-10-20 22:30:22.000000000 +0200 -+++ linux-2.6.36.nouveau/drivers/gpu/drm/radeon/radeon_object.c 2010-11-05 00:40:00.000000000 +0100 -@@ -435,7 +435,7 @@ - - out: - radeon_set_surface_reg(rdev, i, bo->tiling_flags, bo->pitch, -- bo->tbo.mem.mm_node->start << PAGE_SHIFT, -+ bo->tbo.mem.start << PAGE_SHIFT, - bo->tbo.num_pages << PAGE_SHIFT); - return 0; - } -@@ -532,7 +532,7 @@ - rdev = rbo->rdev; - if (bo->mem.mem_type == TTM_PL_VRAM) { - size = bo->mem.num_pages << PAGE_SHIFT; -- offset = bo->mem.mm_node->start << PAGE_SHIFT; -+ offset = bo->mem.start << PAGE_SHIFT; - if ((offset + size) > rdev->mc.visible_vram_size) { - /* hurrah the memory is not visible ! */ - radeon_ttm_placement_from_domain(rbo, RADEON_GEM_DOMAIN_VRAM); -@@ -540,7 +540,7 @@ - r = ttm_bo_validate(bo, &rbo->placement, false, true, false); - if (unlikely(r != 0)) - return r; -- offset = bo->mem.mm_node->start << PAGE_SHIFT; -+ offset = bo->mem.start << PAGE_SHIFT; - /* this should not happen */ - if ((offset + size) > rdev->mc.visible_vram_size) - return -EINVAL; -diff -Naur linux-2.6.36/drivers/gpu/drm/radeon/radeon_ttm.c linux-2.6.36.nouveau/drivers/gpu/drm/radeon/radeon_ttm.c ---- linux-2.6.36/drivers/gpu/drm/radeon/radeon_ttm.c 2010-10-20 22:30:22.000000000 +0200 -+++ linux-2.6.36.nouveau/drivers/gpu/drm/radeon/radeon_ttm.c 2010-11-05 00:40:00.000000000 +0100 -@@ -152,6 +152,7 @@ - man->default_caching = TTM_PL_FLAG_CACHED; - break; - case TTM_PL_TT: -+ man->func = &ttm_bo_manager_func; - man->gpu_offset = rdev->mc.gtt_start; - man->available_caching = TTM_PL_MASK_CACHING; - man->default_caching = TTM_PL_FLAG_CACHED; -@@ -173,6 +174,7 @@ - break; - case TTM_PL_VRAM: - /* "On-card" video ram */ -+ man->func = &ttm_bo_manager_func; - man->gpu_offset = rdev->mc.vram_start; - man->flags = TTM_MEMTYPE_FLAG_FIXED | - TTM_MEMTYPE_FLAG_MAPPABLE; -@@ -246,8 +248,8 @@ - if (unlikely(r)) { - return r; - } -- old_start = old_mem->mm_node->start << PAGE_SHIFT; -- new_start = new_mem->mm_node->start << PAGE_SHIFT; -+ old_start = old_mem->start << PAGE_SHIFT; -+ new_start = new_mem->start << PAGE_SHIFT; - - switch (old_mem->mem_type) { - case TTM_PL_VRAM: -@@ -326,14 +328,7 @@ - } - r = ttm_bo_move_ttm(bo, true, no_wait_reserve, no_wait_gpu, new_mem); - out_cleanup: -- if (tmp_mem.mm_node) { -- struct ttm_bo_global *glob = rdev->mman.bdev.glob; -- -- spin_lock(&glob->lru_lock); -- drm_mm_put_block(tmp_mem.mm_node); -- spin_unlock(&glob->lru_lock); -- return r; -- } -+ ttm_bo_mem_put(bo, &tmp_mem); - return r; - } - -@@ -372,14 +367,7 @@ - goto out_cleanup; - } - out_cleanup: -- if (tmp_mem.mm_node) { -- struct ttm_bo_global *glob = rdev->mman.bdev.glob; -- -- spin_lock(&glob->lru_lock); -- drm_mm_put_block(tmp_mem.mm_node); -- spin_unlock(&glob->lru_lock); -- return r; -- } -+ ttm_bo_mem_put(bo, &tmp_mem); - return r; - } - -@@ -449,14 +437,14 @@ - #if __OS_HAS_AGP - if (rdev->flags & RADEON_IS_AGP) { - /* RADEON_IS_AGP is set only if AGP is active */ -- mem->bus.offset = mem->mm_node->start << PAGE_SHIFT; -+ mem->bus.offset = mem->start << PAGE_SHIFT; - mem->bus.base = rdev->mc.agp_base; - mem->bus.is_iomem = !rdev->ddev->agp->cant_use_aperture; - } - #endif - break; - case TTM_PL_VRAM: -- mem->bus.offset = mem->mm_node->start << PAGE_SHIFT; -+ mem->bus.offset = mem->start << PAGE_SHIFT; - /* check if it's visible */ - if ((mem->bus.offset + mem->bus.size) > rdev->mc.visible_vram_size) - return -EINVAL; -@@ -699,7 +687,7 @@ - int r; - - gtt = container_of(backend, struct radeon_ttm_backend, backend); -- gtt->offset = bo_mem->mm_node->start << PAGE_SHIFT; -+ gtt->offset = bo_mem->start << PAGE_SHIFT; - if (!gtt->num_pages) { - WARN(1, "nothing to bind %lu pages for mreg %p back %p!\n", gtt->num_pages, bo_mem, backend); - } -@@ -798,9 +786,9 @@ - radeon_mem_types_list[i].show = &radeon_mm_dump_table; - radeon_mem_types_list[i].driver_features = 0; - if (i == 0) -- radeon_mem_types_list[i].data = &rdev->mman.bdev.man[TTM_PL_VRAM].manager; -+ radeon_mem_types_list[i].data = &rdev->mman.bdev.man[TTM_PL_VRAM].priv; - else -- radeon_mem_types_list[i].data = &rdev->mman.bdev.man[TTM_PL_TT].manager; -+ radeon_mem_types_list[i].data = &rdev->mman.bdev.man[TTM_PL_TT].priv; - - } - /* Add ttm page pool to debugfs */ -diff -Naur linux-2.6.36/drivers/gpu/drm/ttm/Makefile linux-2.6.36.nouveau/drivers/gpu/drm/ttm/Makefile ---- linux-2.6.36/drivers/gpu/drm/ttm/Makefile 2010-10-20 22:30:22.000000000 +0200 -+++ linux-2.6.36.nouveau/drivers/gpu/drm/ttm/Makefile 2010-11-05 00:40:00.000000000 +0100 -@@ -4,6 +4,7 @@ - ccflags-y := -Iinclude/drm - ttm-y := ttm_agp_backend.o ttm_memory.o ttm_tt.o ttm_bo.o \ - ttm_bo_util.o ttm_bo_vm.o ttm_module.o \ -- ttm_object.o ttm_lock.o ttm_execbuf_util.o ttm_page_alloc.o -+ ttm_object.o ttm_lock.o ttm_execbuf_util.o ttm_page_alloc.o \ -+ ttm_bo_manager.o - - obj-$(CONFIG_DRM_TTM) += ttm.o -diff -Naur linux-2.6.36/drivers/gpu/drm/ttm/ttm_agp_backend.c linux-2.6.36.nouveau/drivers/gpu/drm/ttm/ttm_agp_backend.c ---- linux-2.6.36/drivers/gpu/drm/ttm/ttm_agp_backend.c 2010-10-20 22:30:22.000000000 +0200 -+++ linux-2.6.36.nouveau/drivers/gpu/drm/ttm/ttm_agp_backend.c 2010-11-05 00:40:00.000000000 +0100 -@@ -74,6 +74,7 @@ - { - struct ttm_agp_backend *agp_be = - container_of(backend, struct ttm_agp_backend, backend); -+ struct drm_mm_node *node = bo_mem->mm_node; - struct agp_memory *mem = agp_be->mem; - int cached = (bo_mem->placement & TTM_PL_FLAG_CACHED); - int ret; -@@ -81,7 +82,7 @@ - mem->is_flushed = 1; - mem->type = (cached) ? AGP_USER_CACHED_MEMORY : AGP_USER_MEMORY; - -- ret = agp_bind_memory(mem, bo_mem->mm_node->start); -+ ret = agp_bind_memory(mem, node->start); - if (ret) - printk(KERN_ERR TTM_PFX "AGP Bind memory failed.\n"); - -diff -Naur linux-2.6.36/drivers/gpu/drm/ttm/ttm_bo.c linux-2.6.36.nouveau/drivers/gpu/drm/ttm/ttm_bo.c ---- linux-2.6.36/drivers/gpu/drm/ttm/ttm_bo.c 2010-10-20 22:30:22.000000000 +0200 -+++ linux-2.6.36.nouveau/drivers/gpu/drm/ttm/ttm_bo.c 2010-11-05 00:40:00.000000000 +0100 -@@ -84,11 +84,8 @@ - man->available_caching); - printk(KERN_ERR TTM_PFX " default_caching: 0x%08X\n", - man->default_caching); -- if (mem_type != TTM_PL_SYSTEM) { -- spin_lock(&bdev->glob->lru_lock); -- drm_mm_debug_table(&man->manager, TTM_PFX); -- spin_unlock(&bdev->glob->lru_lock); -- } -+ if (mem_type != TTM_PL_SYSTEM) -+ (*man->func->debug)(man, TTM_PFX); - } - - static void ttm_bo_mem_space_debug(struct ttm_buffer_object *bo, -@@ -421,7 +418,7 @@ - - if (bo->mem.mm_node) { - spin_lock(&bo->lock); -- bo->offset = (bo->mem.mm_node->start << PAGE_SHIFT) + -+ bo->offset = (bo->mem.start << PAGE_SHIFT) + - bdev->man[bo->mem.mem_type].gpu_offset; - bo->cur_placement = bo->mem.placement; - spin_unlock(&bo->lock); -@@ -452,6 +449,7 @@ - static void ttm_bo_cleanup_memtype_use(struct ttm_buffer_object *bo) - { - struct ttm_bo_global *glob = bo->glob; -+ struct ttm_mem_reg tmp_mem; - - if (bo->ttm) { - -@@ -467,14 +465,14 @@ - spin_lock(&glob->lru_lock); - } - -- if (bo->mem.mm_node) { -- drm_mm_put_block(bo->mem.mm_node); -- bo->mem.mm_node = NULL; -- } -+ tmp_mem = bo->mem; -+ bo->mem.mm_node = NULL; - - atomic_set(&bo->reserved, 0); - wake_up_all(&bo->event_queue); - spin_unlock(&glob->lru_lock); -+ -+ ttm_bo_mem_put(bo, &tmp_mem); - } - - -@@ -680,7 +678,6 @@ - bool no_wait_reserve, bool no_wait_gpu) - { - struct ttm_bo_device *bdev = bo->bdev; -- struct ttm_bo_global *glob = bo->glob; - struct ttm_mem_reg evict_mem; - struct ttm_placement placement; - int ret = 0; -@@ -726,12 +723,7 @@ - if (ret) { - if (ret != -ERESTARTSYS) - printk(KERN_ERR TTM_PFX "Buffer eviction failed\n"); -- spin_lock(&glob->lru_lock); -- if (evict_mem.mm_node) { -- drm_mm_put_block(evict_mem.mm_node); -- evict_mem.mm_node = NULL; -- } -- spin_unlock(&glob->lru_lock); -+ ttm_bo_mem_put(bo, &evict_mem); - goto out; - } - bo->evicted = true; -@@ -792,41 +784,14 @@ - return ret; - } - --static int ttm_bo_man_get_node(struct ttm_buffer_object *bo, -- struct ttm_mem_type_manager *man, -- struct ttm_placement *placement, -- struct ttm_mem_reg *mem, -- struct drm_mm_node **node) -+void ttm_bo_mem_put(struct ttm_buffer_object *bo, struct ttm_mem_reg *mem) - { -- struct ttm_bo_global *glob = bo->glob; -- unsigned long lpfn; -- int ret; -- -- lpfn = placement->lpfn; -- if (!lpfn) -- lpfn = man->size; -- *node = NULL; -- do { -- ret = drm_mm_pre_get(&man->manager); -- if (unlikely(ret)) -- return ret; -+ struct ttm_mem_type_manager *man = &bo->bdev->man[mem->mem_type]; - -- spin_lock(&glob->lru_lock); -- *node = drm_mm_search_free_in_range(&man->manager, -- mem->num_pages, mem->page_alignment, -- placement->fpfn, lpfn, 1); -- if (unlikely(*node == NULL)) { -- spin_unlock(&glob->lru_lock); -- return 0; -- } -- *node = drm_mm_get_block_atomic_range(*node, mem->num_pages, -- mem->page_alignment, -- placement->fpfn, -- lpfn); -- spin_unlock(&glob->lru_lock); -- } while (*node == NULL); -- return 0; -+ if (mem->mm_node) -+ (*man->func->put_node)(man, mem); - } -+EXPORT_SYMBOL(ttm_bo_mem_put); - - /** - * Repeatedly evict memory from the LRU for @mem_type until we create enough -@@ -843,14 +808,13 @@ - struct ttm_bo_device *bdev = bo->bdev; - struct ttm_bo_global *glob = bdev->glob; - struct ttm_mem_type_manager *man = &bdev->man[mem_type]; -- struct drm_mm_node *node; - int ret; - - do { -- ret = ttm_bo_man_get_node(bo, man, placement, mem, &node); -+ ret = (*man->func->get_node)(man, bo, placement, mem); - if (unlikely(ret != 0)) - return ret; -- if (node) -+ if (mem->mm_node) - break; - spin_lock(&glob->lru_lock); - if (list_empty(&man->lru)) { -@@ -863,9 +827,8 @@ - if (unlikely(ret != 0)) - return ret; - } while (1); -- if (node == NULL) -+ if (mem->mm_node == NULL) - return -ENOMEM; -- mem->mm_node = node; - mem->mem_type = mem_type; - return 0; - } -@@ -939,7 +902,6 @@ - bool type_found = false; - bool type_ok = false; - bool has_erestartsys = false; -- struct drm_mm_node *node = NULL; - int i, ret; - - mem->mm_node = NULL; -@@ -973,17 +935,15 @@ - - if (man->has_type && man->use_type) { - type_found = true; -- ret = ttm_bo_man_get_node(bo, man, placement, mem, -- &node); -+ ret = (*man->func->get_node)(man, bo, placement, mem); - if (unlikely(ret)) - return ret; - } -- if (node) -+ if (mem->mm_node) - break; - } - -- if ((type_ok && (mem_type == TTM_PL_SYSTEM)) || node) { -- mem->mm_node = node; -+ if ((type_ok && (mem_type == TTM_PL_SYSTEM)) || mem->mm_node) { - mem->mem_type = mem_type; - mem->placement = cur_flags; - return 0; -@@ -1053,7 +1013,6 @@ - bool interruptible, bool no_wait_reserve, - bool no_wait_gpu) - { -- struct ttm_bo_global *glob = bo->glob; - int ret = 0; - struct ttm_mem_reg mem; - -@@ -1081,11 +1040,8 @@ - goto out_unlock; - ret = ttm_bo_handle_move_mem(bo, &mem, false, interruptible, no_wait_reserve, no_wait_gpu); - out_unlock: -- if (ret && mem.mm_node) { -- spin_lock(&glob->lru_lock); -- drm_mm_put_block(mem.mm_node); -- spin_unlock(&glob->lru_lock); -- } -+ if (ret && mem.mm_node) -+ ttm_bo_mem_put(bo, &mem); - return ret; - } - -@@ -1093,11 +1049,10 @@ - struct ttm_mem_reg *mem) - { - int i; -- struct drm_mm_node *node = mem->mm_node; - -- if (node && placement->lpfn != 0 && -- (node->start < placement->fpfn || -- node->start + node->size > placement->lpfn)) -+ if (mem->mm_node && placement->lpfn != 0 && -+ (mem->start < placement->fpfn || -+ mem->start + mem->num_pages > placement->lpfn)) - return -1; - - for (i = 0; i < placement->num_placement; i++) { -@@ -1341,7 +1296,6 @@ - - int ttm_bo_clean_mm(struct ttm_bo_device *bdev, unsigned mem_type) - { -- struct ttm_bo_global *glob = bdev->glob; - struct ttm_mem_type_manager *man; - int ret = -EINVAL; - -@@ -1364,13 +1318,7 @@ - if (mem_type > 0) { - ttm_bo_force_list_clean(bdev, mem_type, false); - -- spin_lock(&glob->lru_lock); -- if (drm_mm_clean(&man->manager)) -- drm_mm_takedown(&man->manager); -- else -- ret = -EBUSY; -- -- spin_unlock(&glob->lru_lock); -+ ret = (*man->func->takedown)(man); - } - - return ret; -@@ -1421,6 +1369,7 @@ - ret = bdev->driver->init_mem_type(bdev, type, man); - if (ret) - return ret; -+ man->bdev = bdev; - - ret = 0; - if (type != TTM_PL_SYSTEM) { -@@ -1430,7 +1379,8 @@ - type); - return ret; - } -- ret = drm_mm_init(&man->manager, 0, p_size); -+ -+ ret = (*man->func->init)(man, p_size); - if (ret) - return ret; - } -diff -Naur linux-2.6.36/drivers/gpu/drm/ttm/ttm_bo_manager.c linux-2.6.36.nouveau/drivers/gpu/drm/ttm/ttm_bo_manager.c ---- linux-2.6.36/drivers/gpu/drm/ttm/ttm_bo_manager.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.36.nouveau/drivers/gpu/drm/ttm/ttm_bo_manager.c 2010-11-05 00:40:00.000000000 +0100 -@@ -0,0 +1,148 @@ -+/************************************************************************** -+ * -+ * Copyright (c) 2007-2009 VMware, Inc., Palo Alto, CA., USA -+ * 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, sub license, 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 NON-INFRINGEMENT. IN NO EVENT SHALL -+ * THE COPYRIGHT HOLDERS, AUTHORS 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: Thomas Hellstrom -+ */ -+ -+#include "ttm/ttm_module.h" -+#include "ttm/ttm_bo_driver.h" -+#include "ttm/ttm_placement.h" -+#include -+#include -+#include -+#include -+#include -+#include -+ -+static int ttm_bo_man_get_node(struct ttm_mem_type_manager *man, -+ struct ttm_buffer_object *bo, -+ struct ttm_placement *placement, -+ struct ttm_mem_reg *mem) -+{ -+ struct ttm_bo_global *glob = man->bdev->glob; -+ struct drm_mm *mm = man->priv; -+ struct drm_mm_node *node = NULL; -+ unsigned long lpfn; -+ int ret; -+ -+ lpfn = placement->lpfn; -+ if (!lpfn) -+ lpfn = man->size; -+ do { -+ ret = drm_mm_pre_get(mm); -+ if (unlikely(ret)) -+ return ret; -+ -+ spin_lock(&glob->lru_lock); -+ node = drm_mm_search_free_in_range(mm, -+ mem->num_pages, mem->page_alignment, -+ placement->fpfn, lpfn, 1); -+ if (unlikely(node == NULL)) { -+ spin_unlock(&glob->lru_lock); -+ return 0; -+ } -+ node = drm_mm_get_block_atomic_range(node, mem->num_pages, -+ mem->page_alignment, -+ placement->fpfn, -+ lpfn); -+ spin_unlock(&glob->lru_lock); -+ } while (node == NULL); -+ -+ mem->mm_node = node; -+ mem->start = node->start; -+ return 0; -+} -+ -+static void ttm_bo_man_put_node(struct ttm_mem_type_manager *man, -+ struct ttm_mem_reg *mem) -+{ -+ struct ttm_bo_global *glob = man->bdev->glob; -+ -+ if (mem->mm_node) { -+ spin_lock(&glob->lru_lock); -+ drm_mm_put_block(mem->mm_node); -+ spin_unlock(&glob->lru_lock); -+ mem->mm_node = NULL; -+ } -+} -+ -+static int ttm_bo_man_init(struct ttm_mem_type_manager *man, -+ unsigned long p_size) -+{ -+ struct drm_mm *mm; -+ int ret; -+ -+ mm = kzalloc(sizeof(*mm), GFP_KERNEL); -+ if (!mm) -+ return -ENOMEM; -+ -+ ret = drm_mm_init(mm, 0, p_size); -+ if (ret) { -+ kfree(mm); -+ return ret; -+ } -+ -+ man->priv = mm; -+ return 0; -+} -+ -+static int ttm_bo_man_takedown(struct ttm_mem_type_manager *man) -+{ -+ struct ttm_bo_global *glob = man->bdev->glob; -+ struct drm_mm *mm = man->priv; -+ int ret = 0; -+ -+ spin_lock(&glob->lru_lock); -+ if (drm_mm_clean(mm)) { -+ drm_mm_takedown(mm); -+ kfree(mm); -+ man->priv = NULL; -+ } else -+ ret = -EBUSY; -+ spin_unlock(&glob->lru_lock); -+ return ret; -+} -+ -+static void ttm_bo_man_debug(struct ttm_mem_type_manager *man, -+ const char *prefix) -+{ -+ struct ttm_bo_global *glob = man->bdev->glob; -+ struct drm_mm *mm = man->priv; -+ -+ spin_lock(&glob->lru_lock); -+ drm_mm_debug_table(mm, prefix); -+ spin_unlock(&glob->lru_lock); -+} -+ -+const struct ttm_mem_type_manager_func ttm_bo_manager_func = { -+ ttm_bo_man_init, -+ ttm_bo_man_takedown, -+ ttm_bo_man_get_node, -+ ttm_bo_man_put_node, -+ ttm_bo_man_debug -+}; -+EXPORT_SYMBOL(ttm_bo_manager_func); -diff -Naur linux-2.6.36/drivers/gpu/drm/ttm/ttm_bo_util.c linux-2.6.36.nouveau/drivers/gpu/drm/ttm/ttm_bo_util.c ---- linux-2.6.36/drivers/gpu/drm/ttm/ttm_bo_util.c 2010-10-20 22:30:22.000000000 +0200 -+++ linux-2.6.36.nouveau/drivers/gpu/drm/ttm/ttm_bo_util.c 2010-11-05 00:40:00.000000000 +0100 -@@ -39,14 +39,7 @@ - - void ttm_bo_free_old_node(struct ttm_buffer_object *bo) - { -- struct ttm_mem_reg *old_mem = &bo->mem; -- -- if (old_mem->mm_node) { -- spin_lock(&bo->glob->lru_lock); -- drm_mm_put_block(old_mem->mm_node); -- spin_unlock(&bo->glob->lru_lock); -- } -- old_mem->mm_node = NULL; -+ ttm_bo_mem_put(bo, &bo->mem); - } - - int ttm_bo_move_ttm(struct ttm_buffer_object *bo, -@@ -263,8 +256,7 @@ - dir = 1; - - if ((old_mem->mem_type == new_mem->mem_type) && -- (new_mem->mm_node->start < -- old_mem->mm_node->start + old_mem->mm_node->size)) { -+ (new_mem->start < old_mem->start + old_mem->size)) { - dir = -1; - add = new_mem->num_pages - 1; - } -diff -Naur linux-2.6.36/drivers/gpu/drm/vmwgfx/vmwgfx_buffer.c linux-2.6.36.nouveau/drivers/gpu/drm/vmwgfx/vmwgfx_buffer.c ---- linux-2.6.36/drivers/gpu/drm/vmwgfx/vmwgfx_buffer.c 2010-10-20 22:30:22.000000000 +0200 -+++ linux-2.6.36.nouveau/drivers/gpu/drm/vmwgfx/vmwgfx_buffer.c 2010-11-05 00:40:00.000000000 +0100 -@@ -147,6 +147,7 @@ - break; - case TTM_PL_VRAM: - /* "On-card" video ram */ -+ man->func = &ttm_bo_manager_func; - man->gpu_offset = 0; - man->flags = TTM_MEMTYPE_FLAG_FIXED | TTM_MEMTYPE_FLAG_MAPPABLE; - man->available_caching = TTM_PL_MASK_CACHING; -@@ -203,7 +204,7 @@ - /* System memory */ - return 0; - case TTM_PL_VRAM: -- mem->bus.offset = mem->mm_node->start << PAGE_SHIFT; -+ mem->bus.offset = mem->start << PAGE_SHIFT; - mem->bus.base = dev_priv->vram_start; - mem->bus.is_iomem = true; - break; -diff -Naur linux-2.6.36/include/drm/nouveau_drm.h linux-2.6.36.nouveau/include/drm/nouveau_drm.h ---- linux-2.6.36/include/drm/nouveau_drm.h 2010-10-20 22:30:22.000000000 +0200 -+++ linux-2.6.36.nouveau/include/drm/nouveau_drm.h 2010-11-05 00:40:00.000000000 +0100 -@@ -80,6 +80,8 @@ - #define NOUVEAU_GETPARAM_VM_VRAM_BASE 12 - #define NOUVEAU_GETPARAM_GRAPH_UNITS 13 - #define NOUVEAU_GETPARAM_PTIMER_TIME 14 -+#define NOUVEAU_GETPARAM_HAS_BO_USAGE 15 -+#define NOUVEAU_GETPARAM_HAS_PAGEFLIP 16 - struct drm_nouveau_getparam { - uint64_t param; - uint64_t value; -@@ -95,6 +97,12 @@ - #define NOUVEAU_GEM_DOMAIN_GART (1 << 2) - #define NOUVEAU_GEM_DOMAIN_MAPPABLE (1 << 3) - -+#define NOUVEAU_GEM_TILE_LAYOUT_MASK 0x0000ff00 -+#define NOUVEAU_GEM_TILE_16BPP 0x00000001 -+#define NOUVEAU_GEM_TILE_32BPP 0x00000002 -+#define NOUVEAU_GEM_TILE_ZETA 0x00000004 -+#define NOUVEAU_GEM_TILE_NONCONTIG 0x00000008 -+ - struct drm_nouveau_gem_info { - uint32_t handle; - uint32_t domain; -@@ -164,7 +172,6 @@ - }; - - #define NOUVEAU_GEM_CPU_PREP_NOWAIT 0x00000001 --#define NOUVEAU_GEM_CPU_PREP_NOBLOCK 0x00000002 - #define NOUVEAU_GEM_CPU_PREP_WRITE 0x00000004 - struct drm_nouveau_gem_cpu_prep { - uint32_t handle; -diff -Naur linux-2.6.36/include/drm/ttm/ttm_bo_api.h linux-2.6.36.nouveau/include/drm/ttm/ttm_bo_api.h ---- linux-2.6.36/include/drm/ttm/ttm_bo_api.h 2010-10-20 22:30:22.000000000 +0200 -+++ linux-2.6.36.nouveau/include/drm/ttm/ttm_bo_api.h 2010-11-05 00:40:00.000000000 +0100 -@@ -102,7 +102,8 @@ - */ - - struct ttm_mem_reg { -- struct drm_mm_node *mm_node; -+ void *mm_node; -+ unsigned long start; - unsigned long size; - unsigned long num_pages; - uint32_t page_alignment; -diff -Naur linux-2.6.36/include/drm/ttm/ttm_bo_driver.h linux-2.6.36.nouveau/include/drm/ttm/ttm_bo_driver.h ---- linux-2.6.36/include/drm/ttm/ttm_bo_driver.h 2010-10-20 22:30:22.000000000 +0200 -+++ linux-2.6.36.nouveau/include/drm/ttm/ttm_bo_driver.h 2010-11-05 00:40:00.000000000 +0100 -@@ -203,7 +203,22 @@ - * It's set up by the ttm_bo_driver::init_mem_type method. - */ - -+struct ttm_mem_type_manager; -+ -+struct ttm_mem_type_manager_func { -+ int (*init)(struct ttm_mem_type_manager *man, unsigned long p_size); -+ int (*takedown)(struct ttm_mem_type_manager *man); -+ int (*get_node)(struct ttm_mem_type_manager *man, -+ struct ttm_buffer_object *bo, -+ struct ttm_placement *placement, -+ struct ttm_mem_reg *mem); -+ void (*put_node)(struct ttm_mem_type_manager *man, -+ struct ttm_mem_reg *mem); -+ void (*debug)(struct ttm_mem_type_manager *man, const char *prefix); -+}; -+ - struct ttm_mem_type_manager { -+ struct ttm_bo_device *bdev; - - /* - * No protection. Constant from start. -@@ -222,8 +237,8 @@ - * TODO: Consider one lru_lock per ttm_mem_type_manager. - * Plays ill with list removal, though. - */ -- -- struct drm_mm manager; -+ const struct ttm_mem_type_manager_func *func; -+ void *priv; - struct list_head lru; - }; - -@@ -649,6 +664,10 @@ - struct ttm_mem_reg *mem, - bool interruptible, - bool no_wait_reserve, bool no_wait_gpu); -+ -+extern void ttm_bo_mem_put(struct ttm_buffer_object *bo, -+ struct ttm_mem_reg *mem); -+ - /** - * ttm_bo_wait_for_cpu - * -@@ -891,6 +910,8 @@ - */ - extern pgprot_t ttm_io_prot(uint32_t caching_flags, pgprot_t tmp); - -+extern const struct ttm_mem_type_manager_func ttm_bo_manager_func; -+ - #if (defined(CONFIG_AGP) || (defined(CONFIG_AGP_MODULE) && defined(MODULE))) - #define TTM_HAS_AGP - #include diff --git a/packages/linux/patches/linux-2.6.37-rc2-000_crosscompile.patch b/packages/linux/patches/linux-2.6.37-rc3-000_crosscompile.patch similarity index 100% rename from packages/linux/patches/linux-2.6.37-rc2-000_crosscompile.patch rename to packages/linux/patches/linux-2.6.37-rc3-000_crosscompile.patch diff --git a/packages/linux/patches/linux-2.6.37-rc2-000_fix_include.patch b/packages/linux/patches/linux-2.6.37-rc3-000_fix_include.patch similarity index 100% rename from packages/linux/patches/linux-2.6.37-rc2-000_fix_include.patch rename to packages/linux/patches/linux-2.6.37-rc3-000_fix_include.patch diff --git a/packages/linux/patches/linux-2.6.37-rc2-000_fix_userspace_build_of_fs.h.patch b/packages/linux/patches/linux-2.6.37-rc3-000_fix_userspace_build_of_fs.h.patch similarity index 100% rename from packages/linux/patches/linux-2.6.37-rc2-000_fix_userspace_build_of_fs.h.patch rename to packages/linux/patches/linux-2.6.37-rc3-000_fix_userspace_build_of_fs.h.patch diff --git a/packages/linux/patches/linux-2.6.37-rc2-002_bash_only_feature.patch b/packages/linux/patches/linux-2.6.37-rc3-002_bash_only_feature.patch similarity index 100% rename from packages/linux/patches/linux-2.6.37-rc2-002_bash_only_feature.patch rename to packages/linux/patches/linux-2.6.37-rc3-002_bash_only_feature.patch diff --git a/packages/linux/patches/linux-2.6.37-rc2-003-no_dev_console.patch b/packages/linux/patches/linux-2.6.37-rc3-003-no_dev_console.patch similarity index 100% rename from packages/linux/patches/linux-2.6.37-rc2-003-no_dev_console.patch rename to packages/linux/patches/linux-2.6.37-rc3-003-no_dev_console.patch diff --git a/packages/linux/patches/linux-2.6.37-rc2-004_lower_undefined_mode_timeout.patch b/packages/linux/patches/linux-2.6.37-rc3-004_lower_undefined_mode_timeout.patch similarity index 100% rename from packages/linux/patches/linux-2.6.37-rc2-004_lower_undefined_mode_timeout.patch rename to packages/linux/patches/linux-2.6.37-rc3-004_lower_undefined_mode_timeout.patch diff --git a/packages/linux/patches/linux-2.6.37-rc2-005_kconfig_no_timestamp.patch b/packages/linux/patches/linux-2.6.37-rc3-005_kconfig_no_timestamp.patch similarity index 100% rename from packages/linux/patches/linux-2.6.37-rc2-005_kconfig_no_timestamp.patch rename to packages/linux/patches/linux-2.6.37-rc3-005_kconfig_no_timestamp.patch diff --git a/packages/linux/patches/linux-2.6.37-rc2-006_enable_utf8.patch b/packages/linux/patches/linux-2.6.37-rc3-006_enable_utf8.patch similarity index 100% rename from packages/linux/patches/linux-2.6.37-rc2-006_enable_utf8.patch rename to packages/linux/patches/linux-2.6.37-rc3-006_enable_utf8.patch diff --git a/packages/linux/patches/linux-2.6.37-rc2-007_die_floppy_die.patch b/packages/linux/patches/linux-2.6.37-rc3-007_die_floppy_die.patch similarity index 100% rename from packages/linux/patches/linux-2.6.37-rc2-007_die_floppy_die.patch rename to packages/linux/patches/linux-2.6.37-rc3-007_die_floppy_die.patch diff --git a/packages/linux/patches/linux-2.6.37-rc2-008-hda_intel_prealloc_4mb_dmabuffer.patch b/packages/linux/patches/linux-2.6.37-rc3-008-hda_intel_prealloc_4mb_dmabuffer.patch similarity index 100% rename from packages/linux/patches/linux-2.6.37-rc2-008-hda_intel_prealloc_4mb_dmabuffer.patch rename to packages/linux/patches/linux-2.6.37-rc3-008-hda_intel_prealloc_4mb_dmabuffer.patch diff --git a/packages/linux/patches/linux-2.6.37-rc2-009_disable_i8042_check_on_apple_mac.patch b/packages/linux/patches/linux-2.6.37-rc3-009_disable_i8042_check_on_apple_mac.patch similarity index 100% rename from packages/linux/patches/linux-2.6.37-rc2-009_disable_i8042_check_on_apple_mac.patch rename to packages/linux/patches/linux-2.6.37-rc3-009_disable_i8042_check_on_apple_mac.patch diff --git a/packages/linux/patches/linux-2.6.37-rc2-050_add_appleir_usb_driver.patch b/packages/linux/patches/linux-2.6.37-rc3-050_add_appleir_usb_driver.patch similarity index 100% rename from packages/linux/patches/linux-2.6.37-rc2-050_add_appleir_usb_driver.patch rename to packages/linux/patches/linux-2.6.37-rc3-050_add_appleir_usb_driver.patch diff --git a/packages/linux/patches/linux-2.6.37-rc2-052-aureal_remote_quirk-0.1.patch b/packages/linux/patches/linux-2.6.37-rc3-052-aureal_remote_quirk-0.1.patch similarity index 100% rename from packages/linux/patches/linux-2.6.37-rc2-052-aureal_remote_quirk-0.1.patch rename to packages/linux/patches/linux-2.6.37-rc3-052-aureal_remote_quirk-0.1.patch diff --git a/packages/linux/patches/linux-2.6.37-rc2-110-drm_nouveau_upstream-20101121.patch b/packages/linux/patches/linux-2.6.37-rc3-110-drm_nouveau_upstream-20101122.patch similarity index 87% rename from packages/linux/patches/linux-2.6.37-rc2-110-drm_nouveau_upstream-20101121.patch rename to packages/linux/patches/linux-2.6.37-rc3-110-drm_nouveau_upstream-20101122.patch index 27336e0af1..eadd453274 100644 --- a/packages/linux/patches/linux-2.6.37-rc2-110-drm_nouveau_upstream-20101121.patch +++ b/packages/linux/patches/linux-2.6.37-rc3-110-drm_nouveau_upstream-20101122.patch @@ -1,6 +1,6 @@ -diff -Naur linux-2.6.37-rc2/drivers/gpu/drm/nouveau/Makefile linux-2.6.37-rc2.nouveau/drivers/gpu/drm/nouveau/Makefile ---- linux-2.6.37-rc2/drivers/gpu/drm/nouveau/Makefile 2010-11-16 03:31:02.000000000 +0100 -+++ linux-2.6.37-rc2.nouveau/drivers/gpu/drm/nouveau/Makefile 2010-11-20 14:43:51.000000000 +0100 +diff -Naur linux-2.6.37-rc3/drivers/gpu/drm/nouveau/Makefile linux-2.6.37-rc3.nouveau/drivers/gpu/drm/nouveau/Makefile +--- linux-2.6.37-rc3/drivers/gpu/drm/nouveau/Makefile 2010-11-22 00:18:56.000000000 +0100 ++++ linux-2.6.37-rc3.nouveau/drivers/gpu/drm/nouveau/Makefile 2010-11-22 06:33:32.000000000 +0100 @@ -5,7 +5,7 @@ ccflags-y := -Iinclude/drm nouveau-y := nouveau_drv.o nouveau_state.o nouveau_channel.o nouveau_mem.o \ @@ -21,35 +21,9 @@ diff -Naur linux-2.6.37-rc2/drivers/gpu/drm/nouveau/Makefile linux-2.6.37-rc2.no nv50_cursor.o nv50_display.o nv50_fbcon.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 nv04_fbcon.o \ -diff -Naur linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nouveau_backlight.c linux-2.6.37-rc2.nouveau/drivers/gpu/drm/nouveau/nouveau_backlight.c ---- linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nouveau_backlight.c 2010-11-16 03:31:02.000000000 +0100 -+++ linux-2.6.37-rc2.nouveau/drivers/gpu/drm/nouveau/nouveau_backlight.c 2010-11-20 14:43:51.000000000 +0100 -@@ -31,6 +31,7 @@ - */ - - #include -+#include - - #include "drmP.h" - #include "nouveau_drv.h" -@@ -136,6 +137,14 @@ - { - struct drm_nouveau_private *dev_priv = dev->dev_private; - -+#ifdef CONFIG_ACPI -+ if (acpi_video_backlight_support()) { -+ NV_INFO(dev, "ACPI backlight interface available, " -+ "not registering our own\n"); -+ return 0; -+ } -+#endif -+ - switch (dev_priv->card_type) { - case NV_40: - return nouveau_nv40_backlight_init(dev); -diff -Naur linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nouveau_bios.c linux-2.6.37-rc2.nouveau/drivers/gpu/drm/nouveau/nouveau_bios.c ---- linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nouveau_bios.c 2010-11-16 03:31:02.000000000 +0100 -+++ linux-2.6.37-rc2.nouveau/drivers/gpu/drm/nouveau/nouveau_bios.c 2010-11-20 14:43:51.000000000 +0100 +diff -Naur linux-2.6.37-rc3/drivers/gpu/drm/nouveau/nouveau_bios.c linux-2.6.37-rc3.nouveau/drivers/gpu/drm/nouveau/nouveau_bios.c +--- linux-2.6.37-rc3/drivers/gpu/drm/nouveau/nouveau_bios.c 2010-11-22 00:18:56.000000000 +0100 ++++ linux-2.6.37-rc3.nouveau/drivers/gpu/drm/nouveau/nouveau_bios.c 2010-11-22 06:33:32.000000000 +0100 @@ -6039,7 +6039,6 @@ if (type != cte->type) NV_WARN(dev, " -> type 0x%02x\n", cte->type); @@ -192,15 +166,6 @@ diff -Naur linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nouveau_bios.c linux-2.6.37- return 0; } -@@ -6829,7 +6802,7 @@ - struct drm_nouveau_private *dev_priv = dev->dev_private; - unsigned htotal; - -- if (dev_priv->chipset >= NV_50) { -+ if (dev_priv->card_type >= NV_50) { - if (NVReadVgaCrtc(dev, 0, 0x00) == 0 && - NVReadVgaCrtc(dev, 0, 0x1a) == 0) - return false; @@ -6859,7 +6832,7 @@ if (ret) return ret; @@ -210,9 +175,9 @@ diff -Naur linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nouveau_bios.c linux-2.6.37- if (ret) return ret; -diff -Naur linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nouveau_bo.c linux-2.6.37-rc2.nouveau/drivers/gpu/drm/nouveau/nouveau_bo.c ---- linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nouveau_bo.c 2010-11-16 03:31:02.000000000 +0100 -+++ linux-2.6.37-rc2.nouveau/drivers/gpu/drm/nouveau/nouveau_bo.c 2010-11-20 14:43:51.000000000 +0100 +diff -Naur linux-2.6.37-rc3/drivers/gpu/drm/nouveau/nouveau_bo.c linux-2.6.37-rc3.nouveau/drivers/gpu/drm/nouveau/nouveau_bo.c +--- linux-2.6.37-rc3/drivers/gpu/drm/nouveau/nouveau_bo.c 2010-11-22 00:18:56.000000000 +0100 ++++ linux-2.6.37-rc3.nouveau/drivers/gpu/drm/nouveau/nouveau_bo.c 2010-11-22 06:33:32.000000000 +0100 @@ -46,9 +46,7 @@ if (unlikely(nvbo->gem)) DRM_ERROR("bo %p still attached to GEM object\n", bo); @@ -224,60 +189,19 @@ diff -Naur linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nouveau_bo.c linux-2.6.37-rc kfree(nvbo); } -@@ -143,8 +141,10 @@ - nvbo->no_vm = no_vm; - nvbo->tile_mode = tile_mode; - nvbo->tile_flags = tile_flags; -+ nvbo->bo.bdev = &dev_priv->ttm.bdev; - -- nouveau_bo_fixup_align(dev, tile_mode, tile_flags, &align, &size); -+ nouveau_bo_fixup_align(dev, tile_mode, nouveau_bo_tile_layout(nvbo), -+ &align, &size); - align >>= PAGE_SHIFT; - - nouveau_bo_placement_set(nvbo, flags, 0); -@@ -176,6 +176,31 @@ - pl[(*n)++] = TTM_PL_FLAG_SYSTEM | flags; - } - -+static void -+set_placement_range(struct nouveau_bo *nvbo, uint32_t type) -+{ -+ struct drm_nouveau_private *dev_priv = nouveau_bdev(nvbo->bo.bdev); -+ -+ if (dev_priv->card_type == NV_10 && -+ nvbo->tile_mode && (type & TTM_PL_FLAG_VRAM)) { -+ /* -+ * Make sure that the color and depth buffers are handled -+ * by independent memory controller units. Up to a 9x -+ * speed up when alpha-blending and depth-test are enabled -+ * at the same time. -+ */ -+ int vram_pages = dev_priv->vram_size >> PAGE_SHIFT; -+ -+ if (nvbo->tile_flags & NOUVEAU_GEM_TILE_ZETA) { -+ nvbo->placement.fpfn = vram_pages / 2; -+ nvbo->placement.lpfn = ~0; -+ } else { -+ nvbo->placement.fpfn = 0; -+ nvbo->placement.lpfn = vram_pages / 2; -+ } -+ } -+} -+ - void - nouveau_bo_placement_set(struct nouveau_bo *nvbo, uint32_t type, uint32_t busy) - { -@@ -190,6 +215,8 @@ - pl->busy_placement = nvbo->busy_placements; - set_placement_list(nvbo->busy_placements, &pl->num_busy_placement, - type | busy, flags); -+ -+ set_placement_range(nvbo, type); - } - - int -@@ -456,16 +483,9 @@ +@@ -426,8 +424,9 @@ + switch (dev_priv->gart_info.type) { + case NOUVEAU_GART_AGP: + man->flags = TTM_MEMTYPE_FLAG_MAPPABLE; +- man->available_caching = TTM_PL_FLAG_UNCACHED; +- man->default_caching = TTM_PL_FLAG_UNCACHED; ++ man->available_caching = TTM_PL_FLAG_UNCACHED | ++ TTM_PL_FLAG_WC; ++ man->default_caching = TTM_PL_FLAG_WC; + break; + case NOUVEAU_GART_SGDMA: + man->flags = TTM_MEMTYPE_FLAG_MAPPABLE | +@@ -485,16 +484,9 @@ if (ret) return ret; @@ -295,27 +219,7 @@ diff -Naur linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nouveau_bo.c linux-2.6.37-rc return ret; } -@@ -525,7 +545,8 @@ - stride = 16 * 4; - height = amount / stride; - -- if (new_mem->mem_type == TTM_PL_VRAM && nvbo->tile_flags) { -+ if (new_mem->mem_type == TTM_PL_VRAM && -+ nouveau_bo_tile_layout(nvbo)) { - ret = RING_SPACE(chan, 8); - if (ret) - return ret; -@@ -546,7 +567,8 @@ - BEGIN_RING(chan, NvSubM2MF, 0x0200, 1); - OUT_RING (chan, 1); - } -- if (old_mem->mem_type == TTM_PL_VRAM && nvbo->tile_flags) { -+ if (old_mem->mem_type == TTM_PL_VRAM && -+ nouveau_bo_tile_layout(nvbo)) { - ret = RING_SPACE(chan, 8); - if (ret) - return ret; -@@ -652,17 +674,24 @@ +@@ -683,17 +675,24 @@ int ret; chan = nvbo->channel; @@ -344,16 +248,7 @@ diff -Naur linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nouveau_bo.c linux-2.6.37-rc } static int -@@ -753,14 +782,16 @@ - if (dev_priv->card_type == NV_50) { - ret = nv50_mem_vm_bind_linear(dev, - offset + dev_priv->vm_vram_base, -- new_mem->size, nvbo->tile_flags, -+ new_mem->size, -+ nouveau_bo_tile_layout(nvbo), - offset); - if (ret) - return ret; +@@ -792,7 +791,8 @@ } else if (dev_priv->card_type >= NV_10) { *new_tile = nv10_mem_set_tiling(dev, offset, new_mem->size, @@ -363,7 +258,7 @@ diff -Naur linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nouveau_bo.c linux-2.6.37-rc } return 0; -@@ -776,9 +807,7 @@ +@@ -808,9 +808,7 @@ if (dev_priv->card_type >= NV_10 && dev_priv->card_type < NV_50) { @@ -374,17 +269,7 @@ diff -Naur linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nouveau_bo.c linux-2.6.37-rc *old_tile = new_tile; } } -@@ -894,7 +923,8 @@ - * nothing to do here. - */ - if (bo->mem.mem_type != TTM_PL_VRAM) { -- if (dev_priv->card_type < NV_50 || !nvbo->tile_flags) -+ if (dev_priv->card_type < NV_50 || -+ !nouveau_bo_tile_layout(nvbo)) - return 0; - } - -@@ -909,6 +939,22 @@ +@@ -942,6 +940,22 @@ return ttm_bo_validate(bo, &nvbo->placement, false, true, false); } @@ -407,7 +292,7 @@ diff -Naur linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nouveau_bo.c linux-2.6.37-rc struct ttm_bo_driver nouveau_bo_driver = { .create_ttm_backend_entry = nouveau_bo_create_ttm_backend_entry, .invalidate_caches = nouveau_bo_invalidate_caches, -@@ -916,11 +962,11 @@ +@@ -949,11 +963,11 @@ .evict_flags = nouveau_bo_evict_flags, .move = nouveau_bo_move, .verify_access = nouveau_bo_verify_access, @@ -424,9 +309,9 @@ diff -Naur linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nouveau_bo.c linux-2.6.37-rc .fault_reserve_notify = &nouveau_ttm_fault_reserve_notify, .io_mem_reserve = &nouveau_ttm_io_mem_reserve, .io_mem_free = &nouveau_ttm_io_mem_free, -diff -Naur linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nouveau_channel.c linux-2.6.37-rc2.nouveau/drivers/gpu/drm/nouveau/nouveau_channel.c ---- linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nouveau_channel.c 2010-11-16 03:31:02.000000000 +0100 -+++ linux-2.6.37-rc2.nouveau/drivers/gpu/drm/nouveau/nouveau_channel.c 2010-11-20 14:43:51.000000000 +0100 +diff -Naur linux-2.6.37-rc3/drivers/gpu/drm/nouveau/nouveau_channel.c linux-2.6.37-rc3.nouveau/drivers/gpu/drm/nouveau/nouveau_channel.c +--- linux-2.6.37-rc3/drivers/gpu/drm/nouveau/nouveau_channel.c 2010-11-22 00:18:56.000000000 +0100 ++++ linux-2.6.37-rc3.nouveau/drivers/gpu/drm/nouveau/nouveau_channel.c 2010-11-22 06:33:32.000000000 +0100 @@ -39,22 +39,22 @@ if (dev_priv->card_type >= NV_50) { @@ -634,7 +519,7 @@ diff -Naur linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nouveau_channel.c linux-2.6. return ret; } -@@ -225,83 +229,121 @@ +@@ -225,83 +229,108 @@ if (!ret) ret = nouveau_fence_channel_init(chan); if (ret) { @@ -698,7 +583,7 @@ diff -Naur linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nouveau_channel.c linux-2.6. + struct nouveau_pgraph_engine *pgraph = &dev_priv->engine.graph; + struct nouveau_crypt_engine *pcrypt = &dev_priv->engine.crypt; unsigned long flags; - int ret; +- int ret; - NV_INFO(dev, "%s: freeing fifo %d\n", __func__, chan->id); + /* decrement the refcount, and we're done if there's still refs */ @@ -712,22 +597,21 @@ diff -Naur linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nouveau_channel.c linux-2.6. nouveau_debugfs_channel_fini(chan); - /* Give outstanding push buffers a chance to complete */ -+ /* give it chance to idle */ - nouveau_fence_update(chan); - if (chan->fence.sequence != chan->fence.sequence_ack) { - struct nouveau_fence *fence = NULL; - - ret = nouveau_fence_new(chan, &fence, true); - if (ret == 0) { +- nouveau_fence_update(chan); +- if (chan->fence.sequence != chan->fence.sequence_ack) { +- struct nouveau_fence *fence = NULL; +- +- ret = nouveau_fence_new(chan, &fence, true); +- if (ret == 0) { - ret = nouveau_fence_wait(fence, NULL, false, false); - nouveau_fence_unref((void *)&fence); -+ ret = nouveau_fence_wait(fence, false, false); -+ nouveau_fence_unref(&fence); - } - - if (ret) - NV_ERROR(dev, "Failed to idle channel %d.\n", chan->id); - } +- } +- +- if (ret) +- NV_ERROR(dev, "Failed to idle channel %d.\n", chan->id); +- } ++ /* give it chance to idle */ ++ nouveau_channel_idle(chan); - /* Ensure all outstanding fences are signaled. They should be if the + /* ensure all outstanding fences are signaled. they should be if the @@ -785,7 +669,7 @@ diff -Naur linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nouveau_channel.c linux-2.6. nouveau_gpuobj_ref(NULL, &chan->pushbuf); if (chan->pushbuf_bo) { nouveau_bo_unmap(chan->pushbuf_bo); -@@ -310,44 +352,62 @@ +@@ -310,44 +339,83 @@ } nouveau_gpuobj_channel_takedown(chan); nouveau_notifier_takedown_channel(chan); @@ -825,6 +709,27 @@ diff -Naur linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nouveau_channel.c linux-2.6. + + *pchan = chan; +} ++ ++void ++nouveau_channel_idle(struct nouveau_channel *chan) ++{ ++ struct drm_device *dev = chan->dev; ++ struct nouveau_fence *fence = NULL; ++ int ret; ++ ++ nouveau_fence_update(chan); ++ ++ if (chan->fence.sequence != chan->fence.sequence_ack) { ++ ret = nouveau_fence_new(chan, &fence, true); ++ 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); ++ } ++} + /* cleans up all the fifos from file_priv */ void @@ -866,7 +771,7 @@ diff -Naur linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nouveau_channel.c linux-2.6. /*********************************** * ioctls wrapping the functions -@@ -395,24 +455,26 @@ +@@ -395,24 +463,26 @@ /* Named memory object area */ ret = drm_gem_handle_create(file_priv, chan->notifier_bo->gem, &init->notifier_handle); @@ -901,7 +806,7 @@ diff -Naur linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nouveau_channel.c linux-2.6. return 0; } -@@ -421,18 +483,18 @@ +@@ -421,18 +491,18 @@ ***********************************/ struct drm_ioctl_desc nouveau_ioctls[] = { @@ -932,9 +837,9 @@ diff -Naur linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nouveau_channel.c linux-2.6. }; int nouveau_max_ioctl = DRM_ARRAY_SIZE(nouveau_ioctls); -diff -Naur linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nouveau_connector.c linux-2.6.37-rc2.nouveau/drivers/gpu/drm/nouveau/nouveau_connector.c ---- linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nouveau_connector.c 2010-11-16 03:31:02.000000000 +0100 -+++ linux-2.6.37-rc2.nouveau/drivers/gpu/drm/nouveau/nouveau_connector.c 2010-11-20 14:43:51.000000000 +0100 +diff -Naur linux-2.6.37-rc3/drivers/gpu/drm/nouveau/nouveau_connector.c linux-2.6.37-rc3.nouveau/drivers/gpu/drm/nouveau/nouveau_connector.c +--- linux-2.6.37-rc3/drivers/gpu/drm/nouveau/nouveau_connector.c 2010-11-22 00:18:56.000000000 +0100 ++++ linux-2.6.37-rc3.nouveau/drivers/gpu/drm/nouveau/nouveau_connector.c 2010-11-22 06:33:32.000000000 +0100 @@ -37,6 +37,8 @@ #include "nouveau_connector.h" #include "nouveau_hw.h" @@ -981,106 +886,7 @@ diff -Naur linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nouveau_connector.c linux-2. } static struct nouveau_i2c_chan * -@@ -281,7 +291,7 @@ - nv_encoder = find_encoder_by_type(connector, OUTPUT_ANALOG); - if (!nv_encoder && !nouveau_tv_disable) - nv_encoder = find_encoder_by_type(connector, OUTPUT_TV); -- if (nv_encoder) { -+ if (nv_encoder && force) { - struct drm_encoder *encoder = to_drm_encoder(nv_encoder); - struct drm_encoder_helper_funcs *helper = - encoder->helper_private; -@@ -641,11 +651,28 @@ - return ret; - } - -+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 dcb_entry *dcb = nv_connector->detected_encoder->dcb; -+ -+ if (dcb->location != DCB_LOC_ON_CHIP || -+ dev_priv->chipset >= 0x46) -+ return 165000; -+ else if (dev_priv->chipset >= 0x40) -+ return 155000; -+ else if (dev_priv->chipset >= 0x18) -+ return 135000; -+ else -+ return 112000; -+} -+ - static int - nouveau_connector_mode_valid(struct drm_connector *connector, - struct drm_display_mode *mode) - { -- struct drm_nouveau_private *dev_priv = connector->dev->dev_private; - 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); -@@ -663,11 +690,9 @@ - max_clock = 400000; - break; - case OUTPUT_TMDS: -- if ((dev_priv->card_type >= NV_50 && !nouveau_duallink) || -- !nv_encoder->dcb->duallink_possible) -- max_clock = 165000; -- else -- max_clock = 330000; -+ max_clock = get_tmds_link_bandwidth(connector); -+ if (nouveau_duallink && nv_encoder->dcb->duallink_possible) -+ max_clock *= 2; - break; - case OUTPUT_ANALOG: - max_clock = nv_encoder->dcb->crtconf.maxfreq; -@@ -709,44 +734,6 @@ - return NULL; - } - --void --nouveau_connector_set_polling(struct drm_connector *connector) --{ -- struct drm_device *dev = connector->dev; -- struct drm_nouveau_private *dev_priv = dev->dev_private; -- struct drm_crtc *crtc; -- bool spare_crtc = false; -- -- list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) -- spare_crtc |= !crtc->enabled; -- -- connector->polled = 0; -- -- switch (connector->connector_type) { -- case DRM_MODE_CONNECTOR_VGA: -- case DRM_MODE_CONNECTOR_TV: -- if (dev_priv->card_type >= NV_50 || -- (nv_gf4_disp_arch(dev) && spare_crtc)) -- connector->polled = DRM_CONNECTOR_POLL_CONNECT; -- break; -- -- case DRM_MODE_CONNECTOR_DVII: -- case DRM_MODE_CONNECTOR_DVID: -- case DRM_MODE_CONNECTOR_HDMIA: -- case DRM_MODE_CONNECTOR_DisplayPort: -- case DRM_MODE_CONNECTOR_eDP: -- if (dev_priv->card_type >= NV_50) -- connector->polled = DRM_CONNECTOR_POLL_HPD; -- else if (connector->connector_type == DRM_MODE_CONNECTOR_DVID || -- spare_crtc) -- connector->polled = DRM_CONNECTOR_POLL_CONNECT; -- break; -- -- default: -- break; -- } --} -- - static const struct drm_connector_helper_funcs - nouveau_connector_helper_funcs = { - .get_modes = nouveau_connector_get_modes, -@@ -783,6 +770,7 @@ +@@ -760,6 +770,7 @@ { const struct drm_connector_funcs *funcs = &nouveau_connector_funcs; struct drm_nouveau_private *dev_priv = dev->dev_private; @@ -1088,37 +894,19 @@ diff -Naur linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nouveau_connector.c linux-2. struct nouveau_connector *nv_connector = NULL; struct dcb_connector_table_entry *dcb = NULL; struct drm_connector *connector; -@@ -872,6 +860,7 @@ - dev->mode_config.scaling_mode_property, - nv_connector->scaling_mode); - } -+ connector->polled = DRM_CONNECTOR_POLL_CONNECT; - /* fall-through */ - case DCB_CONNECTOR_TV_0: - case DCB_CONNECTOR_TV_1: -@@ -888,10 +877,20 @@ - dev->mode_config.dithering_mode_property, - nv_connector->use_dithering ? - DRM_MODE_DITHERING_ON : DRM_MODE_DITHERING_OFF); -+ -+ if (dcb->type != DCB_CONNECTOR_LVDS) { -+ if (dev_priv->card_type >= NV_50) -+ connector->polled = DRM_CONNECTOR_POLL_HPD; -+ else -+ connector->polled = DRM_CONNECTOR_POLL_CONNECT; -+ } +@@ -876,6 +887,11 @@ break; } -- nouveau_connector_set_polling(connector); + if (pgpio->irq_register) { + pgpio->irq_register(dev, nv_connector->dcb->gpio_tag, + nouveau_connector_hotplug, connector); + } - ++ drm_sysfs_connector_add(connector); dcb->drm = connector; -@@ -903,3 +902,29 @@ + return dcb->drm; +@@ -886,3 +902,29 @@ return ERR_PTR(ret); } @@ -1148,22 +936,9 @@ diff -Naur linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nouveau_connector.c linux-2. + + drm_helper_hpd_irq_event(dev); +} -diff -Naur linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nouveau_connector.h linux-2.6.37-rc2.nouveau/drivers/gpu/drm/nouveau/nouveau_connector.h ---- linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nouveau_connector.h 2010-11-16 03:31:02.000000000 +0100 -+++ linux-2.6.37-rc2.nouveau/drivers/gpu/drm/nouveau/nouveau_connector.h 2010-11-20 14:43:51.000000000 +0100 -@@ -52,9 +52,6 @@ - struct drm_connector * - nouveau_connector_create(struct drm_device *, int index); - --void --nouveau_connector_set_polling(struct drm_connector *); -- - int - nouveau_connector_bpp(struct drm_connector *); - -diff -Naur linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nouveau_display.c linux-2.6.37-rc2.nouveau/drivers/gpu/drm/nouveau/nouveau_display.c ---- linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nouveau_display.c 2010-11-16 03:31:02.000000000 +0100 -+++ linux-2.6.37-rc2.nouveau/drivers/gpu/drm/nouveau/nouveau_display.c 2010-11-20 14:43:51.000000000 +0100 +diff -Naur linux-2.6.37-rc3/drivers/gpu/drm/nouveau/nouveau_display.c linux-2.6.37-rc3.nouveau/drivers/gpu/drm/nouveau/nouveau_display.c +--- linux-2.6.37-rc3/drivers/gpu/drm/nouveau/nouveau_display.c 2010-11-22 00:18:56.000000000 +0100 ++++ linux-2.6.37-rc3.nouveau/drivers/gpu/drm/nouveau/nouveau_display.c 2010-11-22 06:33:32.000000000 +0100 @@ -29,6 +29,9 @@ #include "nouveau_drv.h" #include "nouveau_fb.h" @@ -1382,9 +1157,9 @@ diff -Naur linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nouveau_display.c linux-2.6. + spin_unlock_irqrestore(&dev->event_lock, flags); + return 0; +} -diff -Naur linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nouveau_dp.c linux-2.6.37-rc2.nouveau/drivers/gpu/drm/nouveau/nouveau_dp.c ---- linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nouveau_dp.c 2010-11-16 03:31:02.000000000 +0100 -+++ linux-2.6.37-rc2.nouveau/drivers/gpu/drm/nouveau/nouveau_dp.c 2010-11-20 14:43:51.000000000 +0100 +diff -Naur linux-2.6.37-rc3/drivers/gpu/drm/nouveau/nouveau_dp.c linux-2.6.37-rc3.nouveau/drivers/gpu/drm/nouveau/nouveau_dp.c +--- linux-2.6.37-rc3/drivers/gpu/drm/nouveau/nouveau_dp.c 2010-11-22 00:18:56.000000000 +0100 ++++ linux-2.6.37-rc3.nouveau/drivers/gpu/drm/nouveau/nouveau_dp.c 2010-11-22 06:33:32.000000000 +0100 @@ -279,7 +279,7 @@ struct bit_displayport_encoder_table *dpe; int dpe_headerlen; @@ -1412,9 +1187,9 @@ diff -Naur linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nouveau_dp.c linux-2.6.37-rc return eq_done; } -diff -Naur linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nouveau_drv.c linux-2.6.37-rc2.nouveau/drivers/gpu/drm/nouveau/nouveau_drv.c ---- linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nouveau_drv.c 2010-11-16 03:31:02.000000000 +0100 -+++ linux-2.6.37-rc2.nouveau/drivers/gpu/drm/nouveau/nouveau_drv.c 2010-11-20 14:43:51.000000000 +0100 +diff -Naur linux-2.6.37-rc3/drivers/gpu/drm/nouveau/nouveau_drv.c linux-2.6.37-rc3.nouveau/drivers/gpu/drm/nouveau/nouveau_drv.c +--- linux-2.6.37-rc3/drivers/gpu/drm/nouveau/nouveau_drv.c 2010-11-22 00:18:56.000000000 +0100 ++++ linux-2.6.37-rc3.nouveau/drivers/gpu/drm/nouveau/nouveau_drv.c 2010-11-22 06:33:32.000000000 +0100 @@ -115,6 +115,10 @@ int nouveau_perflvl_wr; module_param_named(perflvl_wr, nouveau_perflvl_wr, int, 0400); @@ -1426,27 +1201,34 @@ diff -Naur linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nouveau_drv.c linux-2.6.37-r int nouveau_fbpercrtc; #if 0 module_param_named(fbpercrtc, nouveau_fbpercrtc, int, 0400); -@@ -195,15 +199,14 @@ - for (i = 0; i < pfifo->channels; i++) { - struct nouveau_fence *fence = NULL; +@@ -193,23 +197,10 @@ + NV_INFO(dev, "Idling channels...\n"); + for (i = 0; i < pfifo->channels; i++) { +- struct nouveau_fence *fence = NULL; +- - chan = dev_priv->fifos[i]; - if (!chan || (dev_priv->card_type >= NV_50 && - chan == dev_priv->fifos[0])) +- continue; + chan = dev_priv->channels.ptr[i]; -+ if (!chan || !chan->pushbuf_bo) - continue; - ret = nouveau_fence_new(chan, &fence, true); - if (ret == 0) { +- ret = nouveau_fence_new(chan, &fence, true); +- if (ret == 0) { - ret = nouveau_fence_wait(fence, NULL, false, false); - nouveau_fence_unref((void *)&fence); -+ ret = nouveau_fence_wait(fence, false, false); -+ nouveau_fence_unref(&fence); - } +- } +- +- if (ret) { +- NV_ERROR(dev, "Failed to idle channel %d for suspend\n", +- chan->id); +- } ++ if (chan && chan->pushbuf_bo) ++ nouveau_channel_idle(chan); + } - if (ret) { -@@ -219,17 +222,17 @@ + pgraph->fifo_access(dev, false); +@@ -219,17 +210,17 @@ pfifo->unload_context(dev); pgraph->unload_context(dev); @@ -1468,7 +1250,7 @@ diff -Naur linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nouveau_drv.c linux-2.6.37-r goto out_abort; } -@@ -294,17 +297,18 @@ +@@ -294,17 +285,18 @@ } } @@ -1490,7 +1272,7 @@ diff -Naur linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nouveau_drv.c linux-2.6.37-r nouveau_irq_postinstall(dev); /* Re-write SKIPS, they'll have been lost over the suspend */ -@@ -313,7 +317,7 @@ +@@ -313,7 +305,7 @@ int j; for (i = 0; i < dev_priv->engine.fifo.channels; i++) { @@ -1499,7 +1281,7 @@ diff -Naur linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nouveau_drv.c linux-2.6.37-r if (!chan || !chan->pushbuf_bo) continue; -@@ -393,6 +397,9 @@ +@@ -393,6 +385,9 @@ .irq_postinstall = nouveau_irq_postinstall, .irq_uninstall = nouveau_irq_uninstall, .irq_handler = nouveau_irq_handler, @@ -1509,7 +1291,7 @@ diff -Naur linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nouveau_drv.c linux-2.6.37-r .reclaim_buffers = drm_core_reclaim_buffers, .ioctls = nouveau_ioctls, .fops = { -@@ -403,6 +410,7 @@ +@@ -403,6 +398,7 @@ .mmap = nouveau_ttm_mmap, .poll = drm_poll, .fasync = drm_fasync, @@ -1517,7 +1299,7 @@ diff -Naur linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nouveau_drv.c linux-2.6.37-r #if defined(CONFIG_COMPAT) .compat_ioctl = nouveau_compat_ioctl, #endif -@@ -448,6 +456,12 @@ +@@ -448,6 +444,12 @@ if (!nouveau_modeset) return 0; @@ -1530,9 +1312,9 @@ diff -Naur linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nouveau_drv.c linux-2.6.37-r nouveau_register_dsm_handler(); return drm_init(&driver); } -diff -Naur linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nouveau_drv.h linux-2.6.37-rc2.nouveau/drivers/gpu/drm/nouveau/nouveau_drv.h ---- linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nouveau_drv.h 2010-11-16 03:31:02.000000000 +0100 -+++ linux-2.6.37-rc2.nouveau/drivers/gpu/drm/nouveau/nouveau_drv.h 2010-11-20 14:43:51.000000000 +0100 +diff -Naur linux-2.6.37-rc3/drivers/gpu/drm/nouveau/nouveau_drv.h linux-2.6.37-rc3.nouveau/drivers/gpu/drm/nouveau/nouveau_drv.h +--- linux-2.6.37-rc3/drivers/gpu/drm/nouveau/nouveau_drv.h 2010-11-22 00:18:56.000000000 +0100 ++++ linux-2.6.37-rc3.nouveau/drivers/gpu/drm/nouveau/nouveau_drv.h 2010-11-22 06:33:32.000000000 +0100 @@ -54,6 +54,7 @@ #include "nouveau_drm.h" #include "nouveau_reg.h" @@ -1558,7 +1340,7 @@ diff -Naur linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nouveau_drv.h linux-2.6.37-r }; struct nouveau_bo { -@@ -96,10 +100,12 @@ +@@ -96,7 +100,6 @@ struct nouveau_tile_reg *tile; struct drm_gem_object *gem; @@ -1566,13 +1348,7 @@ diff -Naur linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nouveau_drv.h linux-2.6.37-r int pin_refcnt; }; -+#define nouveau_bo_tile_layout(nvbo) \ -+ ((nvbo)->tile_flags & NOUVEAU_GEM_TILE_LAYOUT_MASK) -+ - static inline struct nouveau_bo * - nouveau_bo(struct ttm_buffer_object *bo) - { -@@ -130,20 +136,26 @@ +@@ -133,20 +136,26 @@ #define NVOBJ_ENGINE_SW 0 #define NVOBJ_ENGINE_GR 1 @@ -1604,7 +1380,7 @@ diff -Naur linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nouveau_drv.h linux-2.6.37-r uint32_t flags; -@@ -159,10 +171,29 @@ +@@ -162,10 +171,29 @@ void *priv; }; @@ -1634,7 +1410,7 @@ diff -Naur linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nouveau_drv.h linux-2.6.37-r /* owner of this fifo */ struct drm_file *file_priv; /* mapping of the fifo itself */ -@@ -199,6 +230,7 @@ +@@ -202,6 +230,7 @@ /* PGRAPH context */ /* XXX may be merge 2 pointers as private data ??? */ struct nouveau_gpuobj *ramin_grctx; @@ -1642,7 +1418,7 @@ diff -Naur linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nouveau_drv.h linux-2.6.37-r void *pgraph_ctx; /* NV50 VM */ -@@ -235,9 +267,11 @@ +@@ -238,9 +267,11 @@ struct { struct nouveau_gpuobj *vblsem; @@ -1654,7 +1430,7 @@ diff -Naur linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nouveau_drv.h linux-2.6.37-r } nvsw; struct { -@@ -255,11 +289,11 @@ +@@ -258,11 +289,11 @@ int (*suspend)(struct drm_device *dev); void (*resume)(struct drm_device *dev); @@ -1671,7 +1447,7 @@ diff -Naur linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nouveau_drv.h linux-2.6.37-r void (*flush)(struct drm_device *); }; -@@ -276,12 +310,17 @@ +@@ -279,12 +310,17 @@ struct nouveau_fb_engine { int num_tiles; @@ -1691,12 +1467,10 @@ diff -Naur linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nouveau_drv.h linux-2.6.37-r }; struct nouveau_fifo_engine { -@@ -304,23 +343,12 @@ - void (*destroy_context)(struct nouveau_channel *); - int (*load_context)(struct nouveau_channel *); - int (*unload_context)(struct drm_device *); --}; -- +@@ -310,21 +346,9 @@ + void (*tlb_flush)(struct drm_device *dev); + }; + -struct nouveau_pgraph_object_method { - int id; - int (*exec)(struct nouveau_channel *chan, int grclass, int mthd, @@ -1707,9 +1481,8 @@ diff -Naur linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nouveau_drv.h linux-2.6.37-r - int id; - bool software; - struct nouveau_pgraph_object_method *methods; -+ void (*tlb_flush)(struct drm_device *dev); - }; - +-}; +- struct nouveau_pgraph_engine { - struct nouveau_pgraph_object_class *grclass; bool accel_blocked; @@ -1717,11 +1490,9 @@ diff -Naur linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nouveau_drv.h linux-2.6.37-r int grctx_size; /* NV2x/NV3x context table (0x400780) */ -@@ -336,9 +364,9 @@ - void (*destroy_context)(struct nouveau_channel *); - int (*load_context)(struct nouveau_channel *); +@@ -342,8 +366,7 @@ int (*unload_context)(struct drm_device *); -+ void (*tlb_flush)(struct drm_device *dev); + void (*tlb_flush)(struct drm_device *dev); - void (*set_region_tiling)(struct drm_device *dev, int i, uint32_t addr, - uint32_t size, uint32_t pitch); @@ -1729,7 +1500,7 @@ diff -Naur linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nouveau_drv.h linux-2.6.37-r }; struct nouveau_display_engine { -@@ -350,13 +378,19 @@ +@@ -355,13 +378,19 @@ }; struct nouveau_gpio_engine { @@ -1750,7 +1521,7 @@ diff -Naur linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nouveau_drv.h linux-2.6.37-r }; struct nouveau_pm_voltage_level { -@@ -432,6 +466,7 @@ +@@ -437,6 +466,7 @@ struct nouveau_pm_level *cur; struct device *hwmon; @@ -1758,7 +1529,7 @@ diff -Naur linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nouveau_drv.h linux-2.6.37-r int (*clock_get)(struct drm_device *, u32 id); void *(*clock_pre)(struct drm_device *, struct nouveau_pm_level *, -@@ -444,6 +479,16 @@ +@@ -449,6 +479,16 @@ int (*temp_get)(struct drm_device *); }; @@ -1775,7 +1546,7 @@ diff -Naur linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nouveau_drv.h linux-2.6.37-r struct nouveau_engine { struct nouveau_instmem_engine instmem; struct nouveau_mc_engine mc; -@@ -454,6 +499,7 @@ +@@ -459,6 +499,7 @@ struct nouveau_display_engine display; struct nouveau_gpio_engine gpio; struct nouveau_pm_engine pm; @@ -1783,68 +1554,7 @@ diff -Naur linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nouveau_drv.h linux-2.6.37-r }; struct nouveau_pll_vals { -@@ -485,13 +531,13 @@ - }; - - struct nv04_crtc_reg { -- unsigned char MiscOutReg; /* */ -+ unsigned char MiscOutReg; - uint8_t CRTC[0xa0]; - uint8_t CR58[0x10]; - uint8_t Sequencer[5]; - uint8_t Graphics[9]; - uint8_t Attribute[21]; -- unsigned char DAC[768]; /* Internal Colorlookuptable */ -+ unsigned char DAC[768]; - - /* PCRTC regs */ - uint32_t fb_start; -@@ -539,43 +585,9 @@ - }; - - struct nv04_mode_state { -- uint32_t bpp; -- uint32_t width; -- uint32_t height; -- uint32_t interlace; -- uint32_t repaint0; -- uint32_t repaint1; -- uint32_t screen; -- uint32_t scale; -- uint32_t dither; -- uint32_t extra; -- uint32_t fifo; -- uint32_t pixel; -- uint32_t horiz; -- int arbitration0; -- int arbitration1; -- uint32_t pll; -- uint32_t pllB; -- uint32_t vpll; -- uint32_t vpll2; -- uint32_t vpllB; -- uint32_t vpll2B; -+ struct nv04_crtc_reg crtc_reg[2]; - uint32_t pllsel; - uint32_t sel_clk; -- uint32_t general; -- uint32_t crtcOwner; -- uint32_t head; -- uint32_t head2; -- uint32_t cursorConfig; -- uint32_t cursor0; -- uint32_t cursor1; -- uint32_t cursor2; -- uint32_t timingH; -- uint32_t timingV; -- uint32_t displayV; -- uint32_t crtcSync; -- -- struct nv04_crtc_reg crtc_reg[2]; - }; - - enum nouveau_card_type { -@@ -606,12 +618,15 @@ +@@ -577,18 +618,15 @@ bool ramin_available; struct drm_mm ramin_heap; struct list_head gpuobj_list; @@ -1858,10 +1568,16 @@ diff -Naur linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nouveau_drv.h linux-2.6.37-r struct workqueue_struct *wq; struct work_struct irq_work; - struct work_struct hpd_work; +- +- struct { +- spinlock_t lock; +- uint32_t hpd0_bits; +- uint32_t hpd1_bits; +- } hpd_state; struct list_head vbl_waiting; -@@ -628,8 +643,10 @@ +@@ -605,8 +643,10 @@ struct nouveau_bo *bo; } fence; @@ -1874,7 +1590,7 @@ diff -Naur linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nouveau_drv.h linux-2.6.37-r struct nouveau_engine engine; struct nouveau_channel *channel; -@@ -655,12 +672,13 @@ +@@ -632,12 +672,13 @@ uint64_t aper_free; struct nouveau_gpuobj *sg_ctxdma; @@ -1891,7 +1607,7 @@ diff -Naur linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nouveau_drv.h linux-2.6.37-r /* VRAM/fb configuration */ uint64_t vram_size; -@@ -697,6 +715,7 @@ +@@ -674,6 +715,7 @@ struct backlight_device *backlight; struct nouveau_channel *evo; @@ -1899,7 +1615,7 @@ diff -Naur linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nouveau_drv.h linux-2.6.37-r struct { struct dcb_entry *dcb; u16 script; -@@ -742,16 +761,6 @@ +@@ -719,16 +761,6 @@ return 0; } @@ -1916,7 +1632,7 @@ diff -Naur linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nouveau_drv.h linux-2.6.37-r /* nouveau_drv.c */ extern int nouveau_agpmode; extern int nouveau_duallink; -@@ -771,6 +780,7 @@ +@@ -748,6 +780,7 @@ extern int nouveau_override_conntype; extern char *nouveau_perflvl; extern int nouveau_perflvl_wr; @@ -1924,7 +1640,7 @@ diff -Naur linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nouveau_drv.h linux-2.6.37-r extern int nouveau_pci_suspend(struct pci_dev *pdev, pm_message_t pm_state); extern int nouveau_pci_resume(struct pci_dev *pdev); -@@ -798,13 +808,12 @@ +@@ -775,13 +808,12 @@ 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 *); @@ -1944,7 +1660,7 @@ diff -Naur linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nouveau_drv.h linux-2.6.37-r extern int nv50_mem_vm_bind_linear(struct drm_device *, uint64_t virt, uint32_t size, uint32_t flags, uint64_t phys); -@@ -826,21 +835,43 @@ +@@ -803,21 +835,44 @@ extern struct drm_ioctl_desc nouveau_ioctls[]; extern int nouveau_max_ioctl; extern void nouveau_channel_cleanup(struct drm_device *, struct drm_file *); @@ -1963,6 +1679,7 @@ diff -Naur linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nouveau_drv.h linux-2.6.37-r +extern void nouveau_channel_put(struct nouveau_channel **); +extern void nouveau_channel_ref(struct nouveau_channel *chan, + struct nouveau_channel **pchan); ++extern void nouveau_channel_idle(struct nouveau_channel *chan); /* nouveau_object.c */ +#define NVOBJ_CLASS(d,c,e) do { \ @@ -1992,7 +1709,7 @@ diff -Naur linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nouveau_drv.h linux-2.6.37-r 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 *); -@@ -855,21 +886,26 @@ +@@ -832,21 +887,26 @@ extern int nouveau_gpuobj_dma_new(struct nouveau_channel *, int class, uint64_t offset, uint64_t size, int access, int target, struct nouveau_gpuobj **); @@ -2025,7 +1742,7 @@ diff -Naur linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nouveau_drv.h linux-2.6.37-r extern void nouveau_irq_preinstall(struct drm_device *); extern int nouveau_irq_postinstall(struct drm_device *); extern void nouveau_irq_uninstall(struct drm_device *); -@@ -989,18 +1025,25 @@ +@@ -966,18 +1026,25 @@ /* nv10_fb.c */ extern int nv10_fb_init(struct drm_device *); extern void nv10_fb_takedown(struct drm_device *); @@ -2055,7 +1772,7 @@ diff -Naur linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nouveau_drv.h linux-2.6.37-r /* nv50_fb.c */ extern int nv50_fb_init(struct drm_device *); extern void nv50_fb_takedown(struct drm_device *); -@@ -1012,6 +1055,7 @@ +@@ -989,6 +1056,7 @@ /* nv04_fifo.c */ extern int nv04_fifo_init(struct drm_device *); @@ -2063,7 +1780,7 @@ diff -Naur linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nouveau_drv.h linux-2.6.37-r extern void nv04_fifo_disable(struct drm_device *); extern void nv04_fifo_enable(struct drm_device *); extern bool nv04_fifo_reassign(struct drm_device *, bool); -@@ -1021,19 +1065,18 @@ +@@ -998,19 +1066,18 @@ extern void nv04_fifo_destroy_context(struct nouveau_channel *); extern int nv04_fifo_load_context(struct nouveau_channel *); extern int nv04_fifo_unload_context(struct drm_device *); @@ -2084,15 +1801,7 @@ diff -Naur linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nouveau_drv.h linux-2.6.37-r extern int nv40_fifo_load_context(struct nouveau_channel *); extern int nv40_fifo_unload_context(struct drm_device *); -@@ -1045,6 +1088,7 @@ - extern void nv50_fifo_destroy_context(struct nouveau_channel *); - extern int nv50_fifo_load_context(struct nouveau_channel *); - extern int nv50_fifo_unload_context(struct drm_device *); -+extern void nv50_fifo_tlb_flush(struct drm_device *dev); - - /* nvc0_fifo.c */ - extern int nvc0_fifo_init(struct drm_device *); -@@ -1060,7 +1104,6 @@ +@@ -1038,7 +1105,6 @@ extern int nvc0_fifo_unload_context(struct drm_device *); /* nv04_graph.c */ @@ -2100,7 +1809,7 @@ diff -Naur linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nouveau_drv.h linux-2.6.37-r extern int nv04_graph_init(struct drm_device *); extern void nv04_graph_takedown(struct drm_device *); extern void nv04_graph_fifo_access(struct drm_device *, bool); -@@ -1069,10 +1112,11 @@ +@@ -1047,10 +1113,11 @@ extern void nv04_graph_destroy_context(struct nouveau_channel *); extern int nv04_graph_load_context(struct nouveau_channel *); extern int nv04_graph_unload_context(struct drm_device *); @@ -2114,7 +1823,7 @@ diff -Naur linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nouveau_drv.h linux-2.6.37-r extern int nv10_graph_init(struct drm_device *); extern void nv10_graph_takedown(struct drm_device *); extern struct nouveau_channel *nv10_graph_channel(struct drm_device *); -@@ -1080,13 +1124,11 @@ +@@ -1058,13 +1125,11 @@ extern void nv10_graph_destroy_context(struct nouveau_channel *); extern int nv10_graph_load_context(struct nouveau_channel *); extern int nv10_graph_unload_context(struct drm_device *); @@ -2131,7 +1840,7 @@ diff -Naur linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nouveau_drv.h linux-2.6.37-r extern int nv20_graph_create_context(struct nouveau_channel *); extern void nv20_graph_destroy_context(struct nouveau_channel *); extern int nv20_graph_load_context(struct nouveau_channel *); -@@ -1094,11 +1136,9 @@ +@@ -1072,11 +1137,9 @@ extern int nv20_graph_init(struct drm_device *); extern void nv20_graph_takedown(struct drm_device *); extern int nv30_graph_init(struct drm_device *); @@ -2144,7 +1853,7 @@ diff -Naur linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nouveau_drv.h linux-2.6.37-r extern int nv40_graph_init(struct drm_device *); extern void nv40_graph_takedown(struct drm_device *); extern struct nouveau_channel *nv40_graph_channel(struct drm_device *); -@@ -1107,11 +1147,9 @@ +@@ -1085,11 +1148,9 @@ extern int nv40_graph_load_context(struct nouveau_channel *); extern int nv40_graph_unload_context(struct drm_device *); extern void nv40_grctx_init(struct nouveau_grctx *); @@ -2157,18 +1866,15 @@ diff -Naur linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nouveau_drv.h linux-2.6.37-r extern int nv50_graph_init(struct drm_device *); extern void nv50_graph_takedown(struct drm_device *); extern void nv50_graph_fifo_access(struct drm_device *, bool); -@@ -1120,8 +1158,9 @@ +@@ -1098,7 +1159,6 @@ extern void nv50_graph_destroy_context(struct nouveau_channel *); extern int nv50_graph_load_context(struct nouveau_channel *); extern int nv50_graph_unload_context(struct drm_device *); -extern void nv50_graph_context_switch(struct drm_device *); extern int nv50_grctx_init(struct nouveau_grctx *); -+extern void nv50_graph_tlb_flush(struct drm_device *dev); -+extern void nv86_graph_tlb_flush(struct drm_device *dev); - - /* nvc0_graph.c */ - extern int nvc0_graph_init(struct drm_device *); -@@ -1133,16 +1172,22 @@ + extern void nv50_graph_tlb_flush(struct drm_device *dev); + extern void nv86_graph_tlb_flush(struct drm_device *dev); +@@ -1113,16 +1173,22 @@ extern int nvc0_graph_load_context(struct nouveau_channel *); extern int nvc0_graph_unload_context(struct drm_device *); @@ -2196,7 +1902,7 @@ diff -Naur linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nouveau_drv.h linux-2.6.37-r extern void nv04_instmem_flush(struct drm_device *); /* nv50_instmem.c */ -@@ -1150,11 +1195,10 @@ +@@ -1130,11 +1196,10 @@ extern void nv50_instmem_takedown(struct drm_device *); extern int nv50_instmem_suspend(struct drm_device *); extern void nv50_instmem_resume(struct drm_device *); @@ -2212,7 +1918,7 @@ diff -Naur linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nouveau_drv.h linux-2.6.37-r extern void nv50_instmem_flush(struct drm_device *); extern void nv84_instmem_flush(struct drm_device *); extern void nv50_vm_flush(struct drm_device *, int engine); -@@ -1164,11 +1208,10 @@ +@@ -1144,11 +1209,10 @@ extern void nvc0_instmem_takedown(struct drm_device *); extern int nvc0_instmem_suspend(struct drm_device *); extern void nvc0_instmem_resume(struct drm_device *); @@ -2228,16 +1934,15 @@ diff -Naur linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nouveau_drv.h linux-2.6.37-r extern void nvc0_instmem_flush(struct drm_device *); /* nv04_mc.c */ -@@ -1239,7 +1282,7 @@ +@@ -1219,6 +1283,7 @@ extern void nouveau_bo_wr16(struct nouveau_bo *nvbo, unsigned index, u16 val); extern u32 nouveau_bo_rd32(struct nouveau_bo *nvbo, unsigned index); extern void nouveau_bo_wr32(struct nouveau_bo *nvbo, unsigned index, u32 val); --extern int nouveau_bo_sync_gpu(struct nouveau_bo *, struct nouveau_channel *); +extern void nouveau_bo_fence(struct nouveau_bo *, struct nouveau_fence *); /* nouveau_fence.c */ struct nouveau_fence; -@@ -1255,12 +1298,35 @@ +@@ -1234,12 +1299,35 @@ void (*work)(void *priv, bool signalled), void *priv); struct nouveau_channel *nouveau_fence_channel(struct nouveau_fence *); @@ -2278,7 +1983,7 @@ diff -Naur linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nouveau_drv.h linux-2.6.37-r /* nouveau_gem.c */ extern int nouveau_gem_new(struct drm_device *, struct nouveau_channel *, -@@ -1280,15 +1346,28 @@ +@@ -1259,15 +1347,28 @@ extern int nouveau_gem_ioctl_info(struct drm_device *, void *, struct drm_file *); @@ -2308,7 +2013,7 @@ diff -Naur linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nouveau_drv.h linux-2.6.37-r /* nv50_calc. */ int nv50_calc_pll(struct drm_device *, struct pll_lims *, int clk, -@@ -1468,6 +1547,22 @@ +@@ -1447,6 +1548,22 @@ dev->pdev->subsystem_device == sub_device; } @@ -2331,16 +2036,16 @@ diff -Naur linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nouveau_drv.h linux-2.6.37-r #define NV_SW 0x0000506e #define NV_SW_DMA_SEMAPHORE 0x00000060 #define NV_SW_SEMAPHORE_OFFSET 0x00000064 -@@ -1478,5 +1573,6 @@ +@@ -1457,5 +1574,6 @@ #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 -Naur linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nouveau_fbcon.c linux-2.6.37-rc2.nouveau/drivers/gpu/drm/nouveau/nouveau_fbcon.c ---- linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nouveau_fbcon.c 2010-11-16 03:31:02.000000000 +0100 -+++ linux-2.6.37-rc2.nouveau/drivers/gpu/drm/nouveau/nouveau_fbcon.c 2010-11-20 14:43:51.000000000 +0100 +diff -Naur linux-2.6.37-rc3/drivers/gpu/drm/nouveau/nouveau_fbcon.c linux-2.6.37-rc3.nouveau/drivers/gpu/drm/nouveau/nouveau_fbcon.c +--- linux-2.6.37-rc3/drivers/gpu/drm/nouveau/nouveau_fbcon.c 2010-11-22 00:18:56.000000000 +0100 ++++ linux-2.6.37-rc3.nouveau/drivers/gpu/drm/nouveau/nouveau_fbcon.c 2010-11-22 06:33:32.000000000 +0100 @@ -49,6 +49,96 @@ #include "nouveau_fbcon.h" #include "nouveau_dma.h" @@ -2561,9 +2266,9 @@ diff -Naur linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nouveau_fbcon.c linux-2.6.37 vga_switcheroo_client_fb_set(dev->pdev, info); return 0; -diff -Naur linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nouveau_fbcon.h linux-2.6.37-rc2.nouveau/drivers/gpu/drm/nouveau/nouveau_fbcon.h ---- linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nouveau_fbcon.h 2010-11-16 03:31:02.000000000 +0100 -+++ linux-2.6.37-rc2.nouveau/drivers/gpu/drm/nouveau/nouveau_fbcon.h 2010-11-20 14:43:51.000000000 +0100 +diff -Naur linux-2.6.37-rc3/drivers/gpu/drm/nouveau/nouveau_fbcon.h linux-2.6.37-rc3.nouveau/drivers/gpu/drm/nouveau/nouveau_fbcon.h +--- linux-2.6.37-rc3/drivers/gpu/drm/nouveau/nouveau_fbcon.h 2010-11-22 00:18:56.000000000 +0100 ++++ linux-2.6.37-rc3.nouveau/drivers/gpu/drm/nouveau/nouveau_fbcon.h 2010-11-22 06:33:32.000000000 +0100 @@ -40,13 +40,13 @@ void nouveau_fbcon_restore(void); @@ -2584,9 +2289,9 @@ diff -Naur linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nouveau_fbcon.h linux-2.6.37 int nv50_fbcon_accel_init(struct fb_info *info); void nouveau_fbcon_gpu_lockup(struct fb_info *info); -diff -Naur linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nouveau_fence.c linux-2.6.37-rc2.nouveau/drivers/gpu/drm/nouveau/nouveau_fence.c ---- linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nouveau_fence.c 2010-11-16 03:31:02.000000000 +0100 -+++ linux-2.6.37-rc2.nouveau/drivers/gpu/drm/nouveau/nouveau_fence.c 2010-11-20 14:43:51.000000000 +0100 +diff -Naur linux-2.6.37-rc3/drivers/gpu/drm/nouveau/nouveau_fence.c linux-2.6.37-rc3.nouveau/drivers/gpu/drm/nouveau/nouveau_fence.c +--- linux-2.6.37-rc3/drivers/gpu/drm/nouveau/nouveau_fence.c 2010-11-22 00:18:56.000000000 +0100 ++++ linux-2.6.37-rc3.nouveau/drivers/gpu/drm/nouveau/nouveau_fence.c 2010-11-22 06:33:32.000000000 +0100 @@ -64,6 +64,7 @@ struct nouveau_fence *fence = container_of(ref, struct nouveau_fence, refcount); @@ -2663,31 +2368,7 @@ diff -Naur linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nouveau_fence.c linux-2.6.37 break; if (time_after_eq(jiffies, timeout)) { -@@ -249,6 +250,7 @@ - { - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_semaphore *sema; -+ int ret; - - if (!USE_SEMA(dev)) - return NULL; -@@ -257,10 +259,14 @@ - if (!sema) - goto fail; - -+ ret = drm_mm_pre_get(&dev_priv->fence.heap); -+ if (ret) -+ goto fail; -+ - spin_lock(&dev_priv->fence.lock); - sema->mem = drm_mm_search_free(&dev_priv->fence.heap, 4, 0, 0); - if (sema->mem) -- sema->mem = drm_mm_get_block(sema->mem, 4, 0); -+ sema->mem = drm_mm_get_block_atomic(sema->mem, 4, 0); - spin_unlock(&dev_priv->fence.lock); - - if (!sema->mem) -@@ -363,7 +369,7 @@ +@@ -368,7 +369,7 @@ kref_get(&sema->ref); nouveau_fence_work(fence, semaphore_work, sema); @@ -2696,7 +2377,7 @@ diff -Naur linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nouveau_fence.c linux-2.6.37 return 0; } -@@ -375,33 +381,49 @@ +@@ -380,33 +381,49 @@ struct nouveau_channel *chan = nouveau_fence_channel(fence); struct drm_device *dev = wchan->dev; struct nouveau_semaphore *sema; @@ -2754,7 +2435,7 @@ diff -Naur linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nouveau_fence.c linux-2.6.37 { return 0; } -@@ -415,7 +437,7 @@ +@@ -420,7 +437,7 @@ int ret; /* Create an NV_SW object for various sync purposes */ @@ -2763,7 +2444,7 @@ diff -Naur linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nouveau_fence.c linux-2.6.37 if (ret) return ret; -@@ -437,8 +459,8 @@ +@@ -442,8 +459,8 @@ ret = nouveau_gpuobj_dma_new(chan, NV_CLASS_DMA_IN_MEMORY, mem->start << PAGE_SHIFT, mem->size << PAGE_SHIFT, @@ -2774,7 +2455,7 @@ diff -Naur linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nouveau_fence.c linux-2.6.37 if (ret) return ret; -@@ -468,6 +490,8 @@ +@@ -473,6 +490,8 @@ { struct nouveau_fence *tmp, *fence; @@ -2783,7 +2464,7 @@ diff -Naur linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nouveau_fence.c linux-2.6.37 list_for_each_entry_safe(fence, tmp, &chan->fence.pending, entry) { fence->signalled = true; list_del(&fence->entry); -@@ -477,6 +501,8 @@ +@@ -482,6 +501,8 @@ kref_put(&fence->refcount, nouveau_fence_del); } @@ -2792,9 +2473,9 @@ diff -Naur linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nouveau_fence.c linux-2.6.37 } int -diff -Naur linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nouveau_gem.c linux-2.6.37-rc2.nouveau/drivers/gpu/drm/nouveau/nouveau_gem.c ---- linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nouveau_gem.c 2010-11-16 03:31:02.000000000 +0100 -+++ linux-2.6.37-rc2.nouveau/drivers/gpu/drm/nouveau/nouveau_gem.c 2010-11-20 14:43:51.000000000 +0100 +diff -Naur linux-2.6.37-rc3/drivers/gpu/drm/nouveau/nouveau_gem.c linux-2.6.37-rc3.nouveau/drivers/gpu/drm/nouveau/nouveau_gem.c +--- linux-2.6.37-rc3/drivers/gpu/drm/nouveau/nouveau_gem.c 2010-11-22 00:18:56.000000000 +0100 ++++ linux-2.6.37-rc3.nouveau/drivers/gpu/drm/nouveau/nouveau_gem.c 2010-11-22 06:33:32.000000000 +0100 @@ -48,9 +48,6 @@ return; nvbo->gem = NULL; @@ -2805,52 +2486,7 @@ diff -Naur linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nouveau_gem.c linux-2.6.37-r if (unlikely(nvbo->pin_refcnt)) { nvbo->pin_refcnt = 1; nouveau_bo_unpin(nvbo); -@@ -107,23 +104,29 @@ - } - - static bool --nouveau_gem_tile_flags_valid(struct drm_device *dev, uint32_t tile_flags) { -- switch (tile_flags) { -- case 0x0000: -- case 0x1800: -- case 0x2800: -- case 0x4800: -- case 0x7000: -- case 0x7400: -- case 0x7a00: -- case 0xe000: -- break; -- default: -- NV_ERROR(dev, "bad page flags: 0x%08x\n", tile_flags); -- return false; -+nouveau_gem_tile_flags_valid(struct drm_device *dev, uint32_t tile_flags) -+{ -+ struct drm_nouveau_private *dev_priv = dev->dev_private; -+ -+ if (dev_priv->card_type >= NV_50) { -+ switch (tile_flags & NOUVEAU_GEM_TILE_LAYOUT_MASK) { -+ case 0x0000: -+ case 0x1800: -+ case 0x2800: -+ case 0x4800: -+ case 0x7000: -+ case 0x7400: -+ case 0x7a00: -+ case 0xe000: -+ return true; -+ } -+ } else { -+ if (!(tile_flags & NOUVEAU_GEM_TILE_LAYOUT_MASK)) -+ return true; - } - -- return true; -+ NV_ERROR(dev, "bad page flags: 0x%08x\n", tile_flags); -+ return false; - } - - int -@@ -140,11 +143,6 @@ +@@ -146,11 +143,6 @@ if (unlikely(dev_priv->ttm.bdev.dev_mapping == NULL)) dev_priv->ttm.bdev.dev_mapping = dev_priv->dev->dev_mapping; @@ -2862,7 +2498,7 @@ diff -Naur linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nouveau_gem.c linux-2.6.37-r if (req->info.domain & NOUVEAU_GEM_DOMAIN_VRAM) flags |= TTM_PL_FLAG_VRAM; if (req->info.domain & NOUVEAU_GEM_DOMAIN_GART) -@@ -155,10 +153,18 @@ +@@ -161,10 +153,18 @@ if (!nouveau_gem_tile_flags_valid(dev, req->info.tile_flags)) return -EINVAL; @@ -2881,7 +2517,7 @@ diff -Naur linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nouveau_gem.c linux-2.6.37-r if (ret) return ret; -@@ -225,15 +231,8 @@ +@@ -231,15 +231,8 @@ list_for_each_safe(entry, tmp, list) { nvbo = list_entry(entry, struct nouveau_bo, entry); @@ -2898,7 +2534,7 @@ diff -Naur linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nouveau_gem.c linux-2.6.37-r if (unlikely(nvbo->validate_mapped)) { ttm_bo_kunmap(&nvbo->kmap); -@@ -293,14 +292,15 @@ +@@ -299,14 +292,15 @@ return -EINVAL; } @@ -2919,7 +2555,7 @@ diff -Naur linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nouveau_gem.c linux-2.6.37-r return ret; } goto retry; -@@ -325,25 +325,6 @@ +@@ -331,25 +325,6 @@ validate_fini(op, NULL); return -EINVAL; } @@ -2945,7 +2581,7 @@ diff -Naur linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nouveau_gem.c linux-2.6.37-r } return 0; -@@ -378,10 +359,11 @@ +@@ -384,10 +359,11 @@ nvbo->channel = (b->read_domains & (1 << 31)) ? NULL : chan; ret = ttm_bo_validate(&nvbo->bo, &nvbo->placement, @@ -2959,7 +2595,7 @@ diff -Naur linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nouveau_gem.c linux-2.6.37-r return ret; } -@@ -433,13 +415,15 @@ +@@ -439,13 +415,15 @@ ret = validate_init(chan, file_priv, pbbo, nr_buffers, op); if (unlikely(ret)) { @@ -2977,7 +2613,7 @@ diff -Naur linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nouveau_gem.c linux-2.6.37-r validate_fini(op, NULL); return ret; } -@@ -447,7 +431,8 @@ +@@ -453,7 +431,8 @@ ret = validate_list(chan, &op->gart_list, pbbo, user_buffers); if (unlikely(ret < 0)) { @@ -2987,7 +2623,7 @@ diff -Naur linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nouveau_gem.c linux-2.6.37-r validate_fini(op, NULL); return ret; } -@@ -455,7 +440,8 @@ +@@ -461,7 +440,8 @@ ret = validate_list(chan, &op->both_list, pbbo, user_buffers); if (unlikely(ret < 0)) { @@ -2997,7 +2633,7 @@ diff -Naur linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nouveau_gem.c linux-2.6.37-r validate_fini(op, NULL); return ret; } -@@ -579,7 +565,9 @@ +@@ -585,7 +565,9 @@ struct nouveau_fence *fence = NULL; int i, j, ret = 0, do_reloc = 0; @@ -3008,7 +2644,7 @@ diff -Naur linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nouveau_gem.c linux-2.6.37-r req->vram_available = dev_priv->fb_aper_free; req->gart_available = dev_priv->gart_info.aper_free; -@@ -589,28 +577,34 @@ +@@ -595,28 +577,34 @@ if (unlikely(req->nr_push > NOUVEAU_GEM_MAX_PUSH)) { NV_ERROR(dev, "pushbuf push count exceeds limit: %d max %d\n", req->nr_push, NOUVEAU_GEM_MAX_PUSH); @@ -3044,7 +2680,7 @@ diff -Naur linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nouveau_gem.c linux-2.6.37-r return PTR_ERR(bo); } -@@ -633,7 +627,8 @@ +@@ -639,7 +627,8 @@ ret = nouveau_gem_pushbuf_validate(chan, file_priv, bo, req->buffers, req->nr_buffers, &op, &do_reloc); if (ret) { @@ -3054,7 +2690,7 @@ diff -Naur linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nouveau_gem.c linux-2.6.37-r goto out; } -@@ -726,7 +721,7 @@ +@@ -732,7 +721,7 @@ out: validate_fini(&op, fence); @@ -3063,7 +2699,7 @@ diff -Naur linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nouveau_gem.c linux-2.6.37-r kfree(bo); kfree(push); -@@ -744,6 +739,7 @@ +@@ -750,6 +739,7 @@ req->suffix1 = 0x00000000; } @@ -3071,7 +2707,7 @@ diff -Naur linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nouveau_gem.c linux-2.6.37-r return ret; } -@@ -775,26 +771,9 @@ +@@ -781,26 +771,9 @@ return -ENOENT; nvbo = nouveau_gem_object(gem); @@ -3101,7 +2737,7 @@ diff -Naur linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nouveau_gem.c linux-2.6.37-r drm_gem_object_unreference_unlocked(gem); return ret; } -@@ -803,26 +782,7 @@ +@@ -809,26 +782,7 @@ nouveau_gem_ioctl_cpu_fini(struct drm_device *dev, void *data, struct drm_file *file_priv) { @@ -3129,33 +2765,9 @@ diff -Naur linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nouveau_gem.c linux-2.6.37-r } int -diff -Naur linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nouveau_hw.c linux-2.6.37-rc2.nouveau/drivers/gpu/drm/nouveau/nouveau_hw.c ---- linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nouveau_hw.c 2010-11-16 03:31:02.000000000 +0100 -+++ linux-2.6.37-rc2.nouveau/drivers/gpu/drm/nouveau/nouveau_hw.c 2010-11-20 14:43:51.000000000 +0100 -@@ -519,11 +519,11 @@ - - struct pll_lims pll_lim; - struct nouveau_pll_vals pv; -- uint32_t pllreg = head ? NV_RAMDAC_VPLL2 : NV_PRAMDAC_VPLL_COEFF; -+ enum pll_types pll = head ? PLL_VPLL1 : PLL_VPLL0; - -- if (get_pll_limits(dev, pllreg, &pll_lim)) -+ if (get_pll_limits(dev, pll, &pll_lim)) - return; -- nouveau_hw_get_pllvals(dev, pllreg, &pv); -+ nouveau_hw_get_pllvals(dev, pll, &pv); - - if (pv.M1 >= pll_lim.vco1.min_m && pv.M1 <= pll_lim.vco1.max_m && - pv.N1 >= pll_lim.vco1.min_n && pv.N1 <= pll_lim.vco1.max_n && -@@ -536,7 +536,7 @@ - pv.M1 = pll_lim.vco1.max_m; - pv.N1 = pll_lim.vco1.min_n; - pv.log2P = pll_lim.max_usable_log2p; -- nouveau_hw_setpll(dev, pllreg, &pv); -+ nouveau_hw_setpll(dev, pll_lim.reg, &pv); - } - - /* +diff -Naur linux-2.6.37-rc3/drivers/gpu/drm/nouveau/nouveau_hw.c linux-2.6.37-rc3.nouveau/drivers/gpu/drm/nouveau/nouveau_hw.c +--- linux-2.6.37-rc3/drivers/gpu/drm/nouveau/nouveau_hw.c 2010-11-22 00:18:56.000000000 +0100 ++++ linux-2.6.37-rc3.nouveau/drivers/gpu/drm/nouveau/nouveau_hw.c 2010-11-22 06:33:32.000000000 +0100 @@ -953,7 +953,7 @@ NVWriteCRTC(dev, head, NV_PCRTC_850, regp->crtc_850); @@ -3177,51 +2789,10 @@ diff -Naur linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nouveau_hw.c linux-2.6.37-rc NVWriteCRTC(dev, head, NV_PCRTC_INTR_0, NV_PCRTC_INTR_0_VBLANK); } -diff -Naur linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nouveau_hw.h linux-2.6.37-rc2.nouveau/drivers/gpu/drm/nouveau/nouveau_hw.h ---- linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nouveau_hw.h 2010-11-16 03:31:02.000000000 +0100 -+++ linux-2.6.37-rc2.nouveau/drivers/gpu/drm/nouveau/nouveau_hw.h 2010-11-20 14:43:51.000000000 +0100 -@@ -416,6 +416,25 @@ - } - - 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; -+ -+ NVWriteCRTC(dev, head, NV_PCRTC_START, offset); -+ -+ if (dev_priv->card_type == NV_04) { -+ /* -+ * Hilarious, the 24th bit doesn't want to stick to -+ * PCRTC_START... -+ */ -+ int cre_heb = NVReadVgaCrtc(dev, head, NV_CIO_CRE_HEB__INDEX); -+ -+ NVWriteVgaCrtc(dev, head, NV_CIO_CRE_HEB__INDEX, -+ (cre_heb & ~0x40) | ((offset >> 18) & 0x40)); -+ } -+} -+ -+static inline void - nv_show_cursor(struct drm_device *dev, int head, bool show) - { - struct drm_nouveau_private *dev_priv = dev->dev_private; -diff -Naur linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nouveau_i2c.c linux-2.6.37-rc2.nouveau/drivers/gpu/drm/nouveau/nouveau_i2c.c ---- linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nouveau_i2c.c 2010-11-16 03:31:02.000000000 +0100 -+++ linux-2.6.37-rc2.nouveau/drivers/gpu/drm/nouveau/nouveau_i2c.c 2010-11-20 14:43:51.000000000 +0100 -@@ -256,7 +256,7 @@ - if (index >= DCB_MAX_NUM_I2C_ENTRIES) - return NULL; - -- if (dev_priv->chipset >= NV_50 && (i2c->entry & 0x00000100)) { -+ if (dev_priv->card_type >= NV_50 && (i2c->entry & 0x00000100)) { - uint32_t reg = 0xe500, val; - - if (i2c->port_type == 6) { -diff -Naur linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nouveau_irq.c linux-2.6.37-rc2.nouveau/drivers/gpu/drm/nouveau/nouveau_irq.c ---- linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nouveau_irq.c 2010-11-16 03:31:02.000000000 +0100 -+++ linux-2.6.37-rc2.nouveau/drivers/gpu/drm/nouveau/nouveau_irq.c 2010-11-20 14:43:51.000000000 +0100 -@@ -36,11 +36,7 @@ +diff -Naur linux-2.6.37-rc3/drivers/gpu/drm/nouveau/nouveau_irq.c linux-2.6.37-rc3.nouveau/drivers/gpu/drm/nouveau/nouveau_irq.c +--- linux-2.6.37-rc3/drivers/gpu/drm/nouveau/nouveau_irq.c 2010-11-22 00:18:56.000000000 +0100 ++++ linux-2.6.37-rc3.nouveau/drivers/gpu/drm/nouveau/nouveau_irq.c 2010-11-22 06:33:32.000000000 +0100 +@@ -36,18 +36,7 @@ #include "nouveau_drv.h" #include "nouveau_reg.h" #include "nouveau_ramht.h" @@ -3230,17 +2801,25 @@ diff -Naur linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nouveau_irq.c linux-2.6.37-r -/* needed for hotplug irq */ -#include "nouveau_connector.h" -#include "nv50_display.h" +- +-static DEFINE_RATELIMIT_STATE(nouveau_ratelimit_state, 3 * HZ, 20); +- +-static int nouveau_ratelimit(void) +-{ +- return __ratelimit(&nouveau_ratelimit_state); +-} +#include "nouveau_util.h" void nouveau_irq_preinstall(struct drm_device *dev) -@@ -50,18 +46,19 @@ +@@ -57,19 +46,19 @@ /* Master disable */ nv_wr32(dev, NV03_PMC_INTR_EN_0, 0); - if (dev_priv->card_type >= NV_50) { - INIT_WORK(&dev_priv->irq_work, nv50_display_irq_handler_bh); - INIT_WORK(&dev_priv->hpd_work, nv50_display_irq_hotplug_bh); +- spin_lock_init(&dev_priv->hpd_state.lock); - INIT_LIST_HEAD(&dev_priv->vbl_waiting); - } + INIT_LIST_HEAD(&dev_priv->vbl_waiting); @@ -3259,7 +2838,7 @@ diff -Naur linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nouveau_irq.c linux-2.6.37-r return 0; } -@@ -72,1182 +69,83 @@ +@@ -80,1178 +69,83 @@ nv_wr32(dev, NV03_PMC_INTR_EN_0, 0); } @@ -3393,8 +2972,8 @@ diff -Naur linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nouveau_irq.c linux-2.6.37-r - } - - if (status & NV_PFIFO_INTR_DMA_PUSHER) { -- u32 get = nv_rd32(dev, 0x003244); -- u32 put = nv_rd32(dev, 0x003240); +- 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); - @@ -3404,16 +2983,18 @@ diff -Naur linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nouveau_irq.c linux-2.6.37-r - u32 ib_get = nv_rd32(dev, 0x003334); - u32 ib_put = nv_rd32(dev, 0x003330); - -- NV_INFO(dev, "PFIFO_DMA_PUSHER - Ch %d Get 0x%02x%08x " +- 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 Push 0x%08x\n", -- chid, ho_get, get, ho_put, put, ib_get, ib_put, -- state, push); +- chid, ho_get, dma_get, ho_put, +- dma_put, ib_get, ib_put, state, +- push); - - /* METHOD_COUNT, in DMA_STATE on earlier chipsets */ - nv_wr32(dev, 0x003364, 0x00000000); -- if (get != put || ho_get != ho_put) { -- nv_wr32(dev, 0x003244, put); +- if (dma_get != dma_put || ho_get != ho_put) { +- nv_wr32(dev, 0x003244, dma_put); - nv_wr32(dev, 0x003328, ho_put); - } else - if (ib_get != ib_put) { @@ -3422,10 +3003,10 @@ diff -Naur linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nouveau_irq.c linux-2.6.37-r - } else { - NV_INFO(dev, "PFIFO_DMA_PUSHER - Ch %d Get 0x%08x " - "Put 0x%08x State 0x%08x Push 0x%08x\n", -- chid, get, put, state, push); +- chid, dma_get, dma_put, state, push); - -- if (get != put) -- nv_wr32(dev, 0x003244, put); +- if (dma_get != dma_put) +- nv_wr32(dev, 0x003244, dma_put); - } - - nv_wr32(dev, 0x003228, 0x00000000); @@ -3457,8 +3038,9 @@ diff -Naur linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nouveau_irq.c linux-2.6.37-r - } - - if (status) { -- NV_INFO(dev, "PFIFO_INTR 0x%08x - Ch %d\n", -- status, chid); +- if (nouveau_ratelimit()) +- NV_INFO(dev, "PFIFO_INTR 0x%08x - Ch %d\n", +- status, chid); - nv_wr32(dev, NV03_PFIFO_INTR_0, status); - status = 0; - } @@ -3749,13 +3331,6 @@ diff -Naur linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nouveau_irq.c linux-2.6.37-r - nouveau_graph_dump_trap_info(dev, "PGRAPH_NOTIFY", &trap); -} - --static DEFINE_RATELIMIT_STATE(nouveau_ratelimit_state, 3 * HZ, 20); -- --static int nouveau_ratelimit(void) --{ -- return __ratelimit(&nouveau_ratelimit_state); --} -- - -static inline void -nouveau_pgraph_intr_error(struct drm_device *dev, uint32_t nsource) @@ -4487,21 +4062,10 @@ diff -Naur linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nouveau_irq.c linux-2.6.37-r - - return IRQ_HANDLED; } -diff -Naur linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nouveau_mem.c linux-2.6.37-rc2.nouveau/drivers/gpu/drm/nouveau/nouveau_mem.c ---- linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nouveau_mem.c 2010-11-16 03:31:02.000000000 +0100 -+++ linux-2.6.37-rc2.nouveau/drivers/gpu/drm/nouveau/nouveau_mem.c 2010-11-20 14:43:51.000000000 +0100 -@@ -33,92 +33,113 @@ - #include "drmP.h" - #include "drm.h" - #include "drm_sarea.h" --#include "nouveau_drv.h" - --#define MIN(a,b) a < b ? a : b -+#include "nouveau_drv.h" -+#include "nouveau_pm.h" - - /* - * NV10-NV40 tiling helpers +diff -Naur linux-2.6.37-rc3/drivers/gpu/drm/nouveau/nouveau_mem.c linux-2.6.37-rc3.nouveau/drivers/gpu/drm/nouveau/nouveau_mem.c +--- linux-2.6.37-rc3/drivers/gpu/drm/nouveau/nouveau_mem.c 2010-11-22 00:18:56.000000000 +0100 ++++ linux-2.6.37-rc3.nouveau/drivers/gpu/drm/nouveau/nouveau_mem.c 2010-11-22 06:33:32.000000000 +0100 +@@ -42,83 +42,104 @@ */ static void @@ -4518,19 +4082,19 @@ diff -Naur linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nouveau_mem.c linux-2.6.37-r - struct nouveau_tile_reg *tile = &dev_priv->tile[i]; + int i = tile - dev_priv->tile.reg; + unsigned long save; -+ -+ nouveau_fence_unref(&tile->fence); -+ -+ if (tile->pitch) -+ pfb->free_tile_region(dev, i); - tile->addr = addr; - tile->size = size; - tile->used = !!pitch; - nouveau_fence_unref((void **)&tile->fence); ++ nouveau_fence_unref(&tile->fence); + ++ if (tile->pitch) ++ pfb->free_tile_region(dev, i); ++ + if (pitch) + pfb->init_tile_region(dev, i, addr, size, pitch, flags); - ++ + spin_lock_irqsave(&dev_priv->context_switch_lock, save); pfifo->reassign(dev, false); pfifo->cache_pull(dev, false); @@ -4604,9 +4168,9 @@ diff -Naur linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nouveau_mem.c linux-2.6.37-r + nouveau_fence_ref(fence); } - } - -- spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags); - +- spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags); + - return found; + tile->used = false; + spin_unlock(&dev_priv->tile.lock); @@ -4652,103 +4216,9 @@ diff -Naur linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nouveau_mem.c linux-2.6.37-r } /* -@@ -177,9 +198,9 @@ - } - dev_priv->engine.instmem.flush(dev); - -- nv50_vm_flush(dev, 5); -- nv50_vm_flush(dev, 0); -- nv50_vm_flush(dev, 4); -+ dev_priv->engine.instmem.flush(dev); -+ dev_priv->engine.fifo.tlb_flush(dev); -+ dev_priv->engine.graph.tlb_flush(dev); - nv50_vm_flush(dev, 6); - return 0; - } -@@ -209,11 +230,10 @@ - pte++; - } - } -- dev_priv->engine.instmem.flush(dev); - -- nv50_vm_flush(dev, 5); -- nv50_vm_flush(dev, 0); -- nv50_vm_flush(dev, 4); -+ dev_priv->engine.instmem.flush(dev); -+ dev_priv->engine.fifo.tlb_flush(dev); -+ dev_priv->engine.graph.tlb_flush(dev); - nv50_vm_flush(dev, 6); - } - -@@ -653,6 +673,7 @@ - void - nouveau_mem_timing_init(struct drm_device *dev) - { -+ /* cards < NVC0 only */ - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_pm_engine *pm = &dev_priv->engine.pm; - struct nouveau_pm_memtimings *memtimings = &pm->memtimings; -@@ -719,14 +740,14 @@ - tUNK_19 = 1; - tUNK_20 = 0; - tUNK_21 = 0; -- switch (MIN(recordlen,21)) { -- case 21: -+ switch (min(recordlen, 22)) { -+ case 22: - tUNK_21 = entry[21]; -- case 20: -+ case 21: - tUNK_20 = entry[20]; -- case 19: -+ case 20: - tUNK_19 = entry[19]; -- case 18: -+ case 19: - tUNK_18 = entry[18]; - default: - tUNK_0 = entry[0]; -@@ -756,24 +777,30 @@ - timing->reg_100228 = (tUNK_12 << 16 | tUNK_11 << 8 | tUNK_10); - if(recordlen > 19) { - timing->reg_100228 += (tUNK_19 - 1) << 24; -- } else { -+ }/* I cannot back-up this else-statement right now -+ else { - timing->reg_100228 += tUNK_12 << 24; -- } -+ }*/ - - /* XXX: reg_10022c */ -+ timing->reg_10022c = tUNK_2 - 1; - - timing->reg_100230 = (tUNK_20 << 24 | tUNK_21 << 16 | - tUNK_13 << 8 | tUNK_13); - - /* XXX: +6? */ - timing->reg_100234 = (tRAS << 24 | (tUNK_19 + 6) << 8 | tRC); -- if(tUNK_10 > tUNK_11) { -- timing->reg_100234 += tUNK_10 << 16; -- } else { -- timing->reg_100234 += tUNK_11 << 16; -+ timing->reg_100234 += max(tUNK_10,tUNK_11) << 16; -+ -+ /* XXX; reg_100238, reg_10023c -+ * reg: 0x00?????? -+ * reg_10023c: -+ * 0 for pre-NV50 cards -+ * 0x????0202 for NV50+ cards (empirical evidence) */ -+ if(dev_priv->card_type >= NV_50) { -+ timing->reg_10023c = 0x202; - } - -- /* XXX; reg_100238, reg_10023c */ - NV_DEBUG(dev, "Entry %d: 220: %08x %08x %08x %08x\n", i, - timing->reg_100220, timing->reg_100224, - timing->reg_100228, timing->reg_10022c); -diff -Naur linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nouveau_notifier.c linux-2.6.37-rc2.nouveau/drivers/gpu/drm/nouveau/nouveau_notifier.c ---- linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nouveau_notifier.c 2010-11-16 03:31:02.000000000 +0100 -+++ linux-2.6.37-rc2.nouveau/drivers/gpu/drm/nouveau/nouveau_notifier.c 2010-11-20 14:43:51.000000000 +0100 +diff -Naur linux-2.6.37-rc3/drivers/gpu/drm/nouveau/nouveau_notifier.c linux-2.6.37-rc3.nouveau/drivers/gpu/drm/nouveau/nouveau_notifier.c +--- linux-2.6.37-rc3/drivers/gpu/drm/nouveau/nouveau_notifier.c 2010-11-22 00:18:56.000000000 +0100 ++++ linux-2.6.37-rc3.nouveau/drivers/gpu/drm/nouveau/nouveau_notifier.c 2010-11-22 06:33:32.000000000 +0100 @@ -99,7 +99,6 @@ int size, uint32_t *b_offset) { @@ -4812,9 +4282,9 @@ diff -Naur linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nouveau_notifier.c linux-2.6 + nouveau_channel_put(&chan); + return ret; } -diff -Naur linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nouveau_object.c linux-2.6.37-rc2.nouveau/drivers/gpu/drm/nouveau/nouveau_object.c ---- linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nouveau_object.c 2010-11-16 03:31:02.000000000 +0100 -+++ linux-2.6.37-rc2.nouveau/drivers/gpu/drm/nouveau/nouveau_object.c 2010-11-20 14:43:51.000000000 +0100 +diff -Naur linux-2.6.37-rc3/drivers/gpu/drm/nouveau/nouveau_object.c linux-2.6.37-rc3.nouveau/drivers/gpu/drm/nouveau/nouveau_object.c +--- linux-2.6.37-rc3/drivers/gpu/drm/nouveau/nouveau_object.c 2010-11-22 00:18:56.000000000 +0100 ++++ linux-2.6.37-rc3.nouveau/drivers/gpu/drm/nouveau/nouveau_object.c 2010-11-22 06:33:32.000000000 +0100 @@ -36,6 +36,101 @@ #include "nouveau_drm.h" #include "nouveau_ramht.h" @@ -4953,7 +4423,7 @@ diff -Naur linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nouveau_object.c linux-2.6.3 } - } else { - NV_DEBUG(dev, "global heap\n"); - +- - /* allocate backing pages, sets vinst */ - ret = engine->instmem.populate(dev, gpuobj, &size); - if (ret) { @@ -4972,9 +4442,9 @@ diff -Naur linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nouveau_object.c linux-2.6.3 - if (ramin == NULL) { - spin_unlock(&dev_priv->ramin_lock); - nouveau_gpuobj_ref(NULL, &gpuobj); -- return ret; +- return -ENOMEM; - } -- + - ramin = drm_mm_get_block_atomic(ramin, size, align); - spin_unlock(&dev_priv->ramin_lock); - } while (ramin == NULL); @@ -5170,10 +4640,10 @@ diff -Naur linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nouveau_object.c linux-2.6.3 + break; + case NV_MEM_TARGET_PCI: + flags0 |= 0x00020000; -+ break; + break; + case NV_MEM_TARGET_PCI_NOSNOOP: + flags0 |= 0x00030000; - break; ++ break; + case NV_MEM_TARGET_GART: + base += dev_priv->vm_gart_base; default: @@ -5189,18 +4659,11 @@ diff -Naur linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nouveau_object.c linux-2.6.3 - NV_ERROR(dev, "Error creating gpuobj: %d\n", ret); - return ret; - } -+ /* convert to base + limit */ -+ size = (base + size) - 1; - +- - if (dev_priv->card_type < NV_50) { - uint32_t frame, adjust, pte_flags = 0; -+ 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); ++ /* convert to base + limit */ ++ size = (base + size) - 1; - if (access != NV_DMA_ACCESS_RO) - pte_flags |= (1<<1); @@ -5216,7 +4679,14 @@ diff -Naur linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nouveau_object.c linux-2.6.3 - } else { - uint64_t limit = offset + size - 1; - uint32_t flags0, flags5; -- ++ 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); + - if (target == NV_DMA_TARGET_VIDMEM) { - flags0 = 0x00190000; - flags5 = 0x00010000; @@ -5690,7 +5160,7 @@ diff -Naur linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nouveau_object.c linux-2.6.3 } ret = nouveau_ramht_insert(chan, init->handle, gr); -@@ -911,27 +998,27 @@ +@@ -911,27 +998,30 @@ if (ret) { NV_ERROR(dev, "Error referencing object: %d (%d/0x%08x)\n", ret, init->channel, init->handle); @@ -5712,14 +5182,16 @@ diff -Naur linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nouveau_object.c linux-2.6.3 + int ret; - NOUVEAU_GET_USER_CHANNEL_WITH_RETURN(objfree->channel, file_priv, chan); -- -- gpuobj = nouveau_ramht_find(chan, objfree->handle); -- if (!gpuobj) -- return -ENOENT; + chan = nouveau_channel_get(dev, file_priv, objfree->channel); + if (IS_ERR(chan)) + return PTR_ERR(chan); +- gpuobj = nouveau_ramht_find(chan, objfree->handle); +- if (!gpuobj) +- return -ENOENT; ++ /* Synchronize with the user channel */ ++ nouveau_channel_idle(chan); + - nouveau_ramht_remove(chan, objfree->handle); - return 0; + ret = nouveau_ramht_remove(chan, objfree->handle); @@ -5728,9 +5200,9 @@ diff -Naur linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nouveau_object.c linux-2.6.3 } u32 -diff -Naur linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nouveau_pm.c linux-2.6.37-rc2.nouveau/drivers/gpu/drm/nouveau/nouveau_pm.c ---- linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nouveau_pm.c 2010-11-16 03:31:02.000000000 +0100 -+++ linux-2.6.37-rc2.nouveau/drivers/gpu/drm/nouveau/nouveau_pm.c 2010-11-20 14:43:51.000000000 +0100 +diff -Naur linux-2.6.37-rc3/drivers/gpu/drm/nouveau/nouveau_pm.c linux-2.6.37-rc3.nouveau/drivers/gpu/drm/nouveau/nouveau_pm.c +--- linux-2.6.37-rc3/drivers/gpu/drm/nouveau/nouveau_pm.c 2010-11-22 00:18:56.000000000 +0100 ++++ linux-2.6.37-rc3.nouveau/drivers/gpu/drm/nouveau/nouveau_pm.c 2010-11-22 06:33:32.000000000 +0100 @@ -27,6 +27,10 @@ #include "nouveau_drv.h" #include "nouveau_pm.h" @@ -5742,50 +5214,10 @@ diff -Naur linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nouveau_pm.c linux-2.6.37-rc #include #include -@@ -284,6 +288,7 @@ - } +@@ -446,6 +450,25 @@ + #endif } -+#ifdef CONFIG_HWMON - static ssize_t - nouveau_hwmon_show_temp(struct device *d, struct device_attribute *a, char *buf) - { -@@ -395,10 +400,12 @@ - static const struct attribute_group hwmon_attrgroup = { - .attrs = hwmon_attributes, - }; -+#endif - - static int - nouveau_hwmon_init(struct drm_device *dev) - { -+#ifdef CONFIG_HWMON - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_pm_engine *pm = &dev_priv->engine.pm; - struct device *hwmon_dev; -@@ -425,13 +432,14 @@ - } - - pm->hwmon = hwmon_dev; -- -+#endif - return 0; - } - - static void - nouveau_hwmon_fini(struct drm_device *dev) - { -+#ifdef CONFIG_HWMON - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_pm_engine *pm = &dev_priv->engine.pm; - -@@ -439,7 +447,27 @@ - sysfs_remove_group(&pm->hwmon->kobj, &hwmon_attrgroup); - hwmon_device_unregister(pm->hwmon); - } -+#endif -+} -+ +#ifdef CONFIG_ACPI +static int +nouveau_pm_acpi_event(struct notifier_block *nb, unsigned long val, void *data) @@ -5802,12 +5234,13 @@ diff -Naur linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nouveau_pm.c linux-2.6.37-rc + } + + return NOTIFY_OK; - } ++} +#endif - ++ int nouveau_pm_init(struct drm_device *dev) -@@ -480,6 +508,10 @@ + { +@@ -485,6 +508,10 @@ nouveau_sysfs_init(dev); nouveau_hwmon_init(dev); @@ -5818,7 +5251,7 @@ diff -Naur linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nouveau_pm.c linux-2.6.37-rc return 0; } -@@ -498,6 +530,9 @@ +@@ -503,6 +530,9 @@ nouveau_perf_fini(dev); nouveau_volt_fini(dev); @@ -5828,9 +5261,9 @@ diff -Naur linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nouveau_pm.c linux-2.6.37-rc nouveau_hwmon_fini(dev); nouveau_sysfs_fini(dev); } -diff -Naur linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nouveau_ramht.c linux-2.6.37-rc2.nouveau/drivers/gpu/drm/nouveau/nouveau_ramht.c ---- linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nouveau_ramht.c 2010-11-16 03:31:02.000000000 +0100 -+++ linux-2.6.37-rc2.nouveau/drivers/gpu/drm/nouveau/nouveau_ramht.c 2010-11-20 14:43:51.000000000 +0100 +diff -Naur linux-2.6.37-rc3/drivers/gpu/drm/nouveau/nouveau_ramht.c linux-2.6.37-rc3.nouveau/drivers/gpu/drm/nouveau/nouveau_ramht.c +--- linux-2.6.37-rc3/drivers/gpu/drm/nouveau/nouveau_ramht.c 2010-11-22 00:18:56.000000000 +0100 ++++ linux-2.6.37-rc3.nouveau/drivers/gpu/drm/nouveau/nouveau_ramht.c 2010-11-22 06:33:32.000000000 +0100 @@ -104,17 +104,17 @@ nouveau_gpuobj_ref(gpuobj, &entry->gpuobj); @@ -5852,132 +5285,31 @@ diff -Naur linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nouveau_ramht.c linux-2.6.37 } else { ctx = (gpuobj->cinst >> 4) | ((gpuobj->engine << -@@ -153,26 +153,42 @@ - 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_locked(struct nouveau_channel *chan, u32 handle) -+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; -- struct nouveau_ramht_entry *entry, *tmp; -+ unsigned long flags; - u32 co, ho; - -- list_for_each_entry_safe(entry, tmp, &chan->ramht->entries, head) { -- if (entry->channel != chan || entry->handle != handle) -- continue; -- -- nouveau_gpuobj_ref(NULL, &entry->gpuobj); -- list_del(&entry->head); -- kfree(entry); -- break; -- } -- -+ spin_lock_irqsave(&chan->ramht->lock, flags); - co = ho = nouveau_ramht_hash_handle(chan, handle); - do { - if (nouveau_ramht_entry_valid(dev, ramht, co) && -@@ -184,7 +200,7 @@ - nv_wo32(ramht, co + 0, 0x00000000); - nv_wo32(ramht, co + 4, 0x00000000); - instmem->flush(dev); -- return; -+ goto out; - } - - co += 8; -@@ -194,17 +210,23 @@ - - NV_ERROR(dev, "RAMHT entry not found. ch=%d, handle=0x%08x\n", - chan->id, handle); -+out: -+ spin_unlock_irqrestore(&chan->ramht->lock, flags); +@@ -214,18 +214,19 @@ + spin_unlock_irqrestore(&chan->ramht->lock, flags); } -void +int nouveau_ramht_remove(struct nouveau_channel *chan, u32 handle) { -- struct nouveau_ramht *ramht = chan->ramht; -- unsigned long flags; -+ struct nouveau_ramht_entry *entry; + struct nouveau_ramht_entry *entry; -- spin_lock_irqsave(&ramht->lock, flags); -- nouveau_ramht_remove_locked(chan, handle); -- spin_unlock_irqrestore(&ramht->lock, flags); -+ entry = nouveau_ramht_remove_entry(chan, handle); -+ if (!entry) + entry = nouveau_ramht_remove_entry(chan, handle); + if (!entry) +- return; + return -ENOENT; -+ -+ nouveau_ramht_remove_hash(chan, entry->handle); -+ nouveau_gpuobj_ref(NULL, &entry->gpuobj); -+ kfree(entry); + + nouveau_ramht_remove_hash(chan, entry->handle); + nouveau_gpuobj_ref(NULL, &entry->gpuobj); + kfree(entry); + return 0; } struct nouveau_gpuobj * -@@ -265,23 +287,19 @@ - nouveau_ramht_ref(struct nouveau_ramht *ref, struct nouveau_ramht **ptr, - struct nouveau_channel *chan) - { -- struct nouveau_ramht_entry *entry, *tmp; -+ struct nouveau_ramht_entry *entry; - struct nouveau_ramht *ramht; -- unsigned long flags; - - if (ref) - kref_get(&ref->refcount); - - ramht = *ptr; - if (ramht) { -- spin_lock_irqsave(&ramht->lock, flags); -- list_for_each_entry_safe(entry, tmp, &ramht->entries, head) { -- if (entry->channel != chan) -- continue; -- -- nouveau_ramht_remove_locked(chan, entry->handle); -+ while ((entry = nouveau_ramht_remove_entry(chan, 0))) { -+ nouveau_ramht_remove_hash(chan, entry->handle); -+ nouveau_gpuobj_ref(NULL, &entry->gpuobj); -+ kfree(entry); - } -- spin_unlock_irqrestore(&ramht->lock, flags); - - kref_put(&ramht->refcount, nouveau_ramht_del); - } -diff -Naur linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nouveau_ramht.h linux-2.6.37-rc2.nouveau/drivers/gpu/drm/nouveau/nouveau_ramht.h ---- linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nouveau_ramht.h 2010-11-16 03:31:02.000000000 +0100 -+++ linux-2.6.37-rc2.nouveau/drivers/gpu/drm/nouveau/nouveau_ramht.h 2010-11-20 14:43:51.000000000 +0100 +diff -Naur linux-2.6.37-rc3/drivers/gpu/drm/nouveau/nouveau_ramht.h linux-2.6.37-rc3.nouveau/drivers/gpu/drm/nouveau/nouveau_ramht.h +--- linux-2.6.37-rc3/drivers/gpu/drm/nouveau/nouveau_ramht.h 2010-11-22 00:18:56.000000000 +0100 ++++ linux-2.6.37-rc3.nouveau/drivers/gpu/drm/nouveau/nouveau_ramht.h 2010-11-22 06:33:32.000000000 +0100 @@ -48,7 +48,7 @@ extern int nouveau_ramht_insert(struct nouveau_channel *, u32 handle, @@ -5987,9 +5319,9 @@ diff -Naur linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nouveau_ramht.h linux-2.6.37 extern struct nouveau_gpuobj * nouveau_ramht_find(struct nouveau_channel *chan, u32 handle); -diff -Naur linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nouveau_reg.h linux-2.6.37-rc2.nouveau/drivers/gpu/drm/nouveau/nouveau_reg.h ---- linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nouveau_reg.h 2010-11-16 03:31:02.000000000 +0100 -+++ linux-2.6.37-rc2.nouveau/drivers/gpu/drm/nouveau/nouveau_reg.h 2010-11-20 14:43:51.000000000 +0100 +diff -Naur linux-2.6.37-rc3/drivers/gpu/drm/nouveau/nouveau_reg.h linux-2.6.37-rc3.nouveau/drivers/gpu/drm/nouveau/nouveau_reg.h +--- linux-2.6.37-rc3/drivers/gpu/drm/nouveau/nouveau_reg.h 2010-11-22 00:18:56.000000000 +0100 ++++ linux-2.6.37-rc3.nouveau/drivers/gpu/drm/nouveau/nouveau_reg.h 2010-11-22 06:33:32.000000000 +0100 @@ -45,6 +45,11 @@ # define NV04_PFB_REF_CMD_REFRESH (1 << 0) #define NV04_PFB_PRE 0x001002d4 @@ -6111,21 +5443,10 @@ diff -Naur linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nouveau_reg.h linux-2.6.37-r #define NV50_PDISPLAY_CRTC_P(i, r) ((i) * 0x540 + NV50_PDISPLAY_CRTC_##r) #define NV50_PDISPLAY_CRTC_C(i, r) (4 + (i) * 0x540 + NV50_PDISPLAY_CRTC_##r) -diff -Naur linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nouveau_sgdma.c linux-2.6.37-rc2.nouveau/drivers/gpu/drm/nouveau/nouveau_sgdma.c ---- linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nouveau_sgdma.c 2010-11-16 03:31:02.000000000 +0100 -+++ linux-2.6.37-rc2.nouveau/drivers/gpu/drm/nouveau/nouveau_sgdma.c 2010-11-20 14:43:51.000000000 +0100 -@@ -120,8 +120,8 @@ - dev_priv->engine.instmem.flush(nvbe->dev); - - if (dev_priv->card_type == NV_50) { -- nv50_vm_flush(dev, 5); /* PGRAPH */ -- nv50_vm_flush(dev, 0); /* PFIFO */ -+ dev_priv->engine.fifo.tlb_flush(dev); -+ dev_priv->engine.graph.tlb_flush(dev); - } - - nvbe->bound = true; -@@ -144,26 +144,22 @@ +diff -Naur linux-2.6.37-rc3/drivers/gpu/drm/nouveau/nouveau_sgdma.c linux-2.6.37-rc3.nouveau/drivers/gpu/drm/nouveau/nouveau_sgdma.c +--- linux-2.6.37-rc3/drivers/gpu/drm/nouveau/nouveau_sgdma.c 2010-11-22 00:18:56.000000000 +0100 ++++ linux-2.6.37-rc3.nouveau/drivers/gpu/drm/nouveau/nouveau_sgdma.c 2010-11-22 06:33:32.000000000 +0100 +@@ -144,19 +144,15 @@ pte = nvbe->pte_start; for (i = 0; i < nvbe->nr_pages; i++) { @@ -6146,16 +5467,7 @@ diff -Naur linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nouveau_sgdma.c linux-2.6.37 } } dev_priv->engine.instmem.flush(nvbe->dev); - - if (dev_priv->card_type == NV_50) { -- nv50_vm_flush(dev, 5); -- nv50_vm_flush(dev, 0); -+ dev_priv->engine.fifo.tlb_flush(dev); -+ dev_priv->engine.graph.tlb_flush(dev); - } - - nvbe->bound = false; -@@ -218,13 +214,16 @@ +@@ -218,7 +214,6 @@ nouveau_sgdma_init(struct drm_device *dev) { struct drm_nouveau_private *dev_priv = dev->dev_private; @@ -6163,18 +5475,7 @@ diff -Naur linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nouveau_sgdma.c linux-2.6.37 struct nouveau_gpuobj *gpuobj = NULL; uint32_t aper_size, obj_size; int i, ret; - - if (dev_priv->card_type < NV_50) { -- aper_size = (64 * 1024 * 1024); -+ if(dev_priv->ramin_rsvd_vram < 2 * 1024 * 1024) -+ aper_size = 64 * 1024 * 1024; -+ else -+ aper_size = 512 * 1024 * 1024; -+ - obj_size = (aper_size >> NV_CTXDMA_PAGE_SHIFT) * 4; - obj_size += 8; /* ctxdma header */ - } else { -@@ -241,42 +240,15 @@ +@@ -245,42 +240,15 @@ return ret; } @@ -6221,7 +5522,7 @@ diff -Naur linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nouveau_sgdma.c linux-2.6.37 } else { for (i = 0; i < obj_size; i += 8) { nv_wo32(gpuobj, i + 0, 0x00000000); -@@ -297,15 +269,6 @@ +@@ -301,15 +269,6 @@ { struct drm_nouveau_private *dev_priv = dev->dev_private; @@ -6237,9 +5538,9 @@ diff -Naur linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nouveau_sgdma.c linux-2.6.37 nouveau_gpuobj_ref(NULL, &dev_priv->gart_info.sg_ctxdma); } -diff -Naur linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nouveau_state.c linux-2.6.37-rc2.nouveau/drivers/gpu/drm/nouveau/nouveau_state.c ---- linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nouveau_state.c 2010-11-16 03:31:02.000000000 +0100 -+++ linux-2.6.37-rc2.nouveau/drivers/gpu/drm/nouveau/nouveau_state.c 2010-11-20 14:43:51.000000000 +0100 +diff -Naur linux-2.6.37-rc3/drivers/gpu/drm/nouveau/nouveau_state.c linux-2.6.37-rc3.nouveau/drivers/gpu/drm/nouveau/nouveau_state.c +--- linux-2.6.37-rc3/drivers/gpu/drm/nouveau/nouveau_state.c 2010-11-22 00:18:56.000000000 +0100 ++++ linux-2.6.37-rc3.nouveau/drivers/gpu/drm/nouveau/nouveau_state.c 2010-11-22 06:33:32.000000000 +0100 @@ -53,10 +53,10 @@ engine->instmem.takedown = nv04_instmem_takedown; engine->instmem.suspend = nv04_instmem_suspend; @@ -6529,30 +5830,7 @@ diff -Naur linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nouveau_state.c linux-2.6.37 engine->graph.init = nv50_graph_init; engine->graph.takedown = nv50_graph_takedown; engine->graph.fifo_access = nv50_graph_fifo_access; -@@ -354,6 +366,15 @@ - engine->graph.destroy_context = nv50_graph_destroy_context; - engine->graph.load_context = nv50_graph_load_context; - engine->graph.unload_context = nv50_graph_unload_context; -+ if (dev_priv->chipset != 0x86) -+ engine->graph.tlb_flush = nv50_graph_tlb_flush; -+ else { -+ /* from what i can see nvidia do this on every -+ * pre-NVA3 board except NVAC, but, we've only -+ * ever seen problems on NV86 -+ */ -+ engine->graph.tlb_flush = nv86_graph_tlb_flush; -+ } - engine->fifo.channels = 128; - engine->fifo.init = nv50_fifo_init; - engine->fifo.takedown = nv50_fifo_takedown; -@@ -365,30 +386,39 @@ - engine->fifo.destroy_context = nv50_fifo_destroy_context; - engine->fifo.load_context = nv50_fifo_load_context; - engine->fifo.unload_context = nv50_fifo_unload_context; -+ engine->fifo.tlb_flush = nv50_fifo_tlb_flush; - engine->display.early_init = nv50_display_early_init; - engine->display.late_takedown = nv50_display_late_takedown; - engine->display.create = nv50_display_create; +@@ -381,24 +393,32 @@ engine->display.init = nv50_display_init; engine->display.destroy = nv50_display_destroy; engine->gpio.init = nv50_gpio_init; @@ -6595,7 +5873,7 @@ diff -Naur linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nouveau_state.c linux-2.6.37 } engine->pm.voltage_get = nouveau_voltage_gpio_get; engine->pm.voltage_set = nouveau_voltage_gpio_set; -@@ -396,16 +426,34 @@ +@@ -406,16 +426,34 @@ engine->pm.temp_get = nv84_temp_get; else engine->pm.temp_get = nv40_temp_get; @@ -6634,7 +5912,7 @@ diff -Naur linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nouveau_state.c linux-2.6.37 engine->instmem.flush = nvc0_instmem_flush; engine->mc.init = nv50_mc_init; engine->mc.takedown = nv50_mc_takedown; -@@ -414,7 +462,6 @@ +@@ -424,7 +462,6 @@ engine->timer.takedown = nv04_timer_takedown; engine->fb.init = nvc0_fb_init; engine->fb.takedown = nvc0_fb_takedown; @@ -6642,7 +5920,7 @@ diff -Naur linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nouveau_state.c linux-2.6.37 engine->graph.init = nvc0_graph_init; engine->graph.takedown = nvc0_graph_takedown; engine->graph.fifo_access = nvc0_graph_fifo_access; -@@ -443,7 +490,11 @@ +@@ -453,7 +490,11 @@ engine->gpio.takedown = nouveau_stub_takedown; engine->gpio.get = nv50_gpio_get; engine->gpio.set = nv50_gpio_set; @@ -6654,7 +5932,7 @@ diff -Naur linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nouveau_state.c linux-2.6.37 break; default: NV_ERROR(dev, "NV%02x unsupported\n", dev_priv->chipset); -@@ -485,7 +536,7 @@ +@@ -495,7 +536,7 @@ ret = nouveau_gpuobj_dma_new(dev_priv->channel, NV_CLASS_DMA_IN_MEMORY, 0, dev_priv->vram_size, @@ -6663,7 +5941,7 @@ diff -Naur linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nouveau_state.c linux-2.6.37 &gpuobj); if (ret) goto out_err; -@@ -495,9 +546,10 @@ +@@ -505,9 +546,10 @@ if (ret) goto out_err; @@ -6677,7 +5955,7 @@ diff -Naur linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nouveau_state.c linux-2.6.37 if (ret) goto out_err; -@@ -506,11 +558,11 @@ +@@ -516,11 +558,11 @@ if (ret) goto out_err; @@ -6691,7 +5969,7 @@ diff -Naur linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nouveau_state.c linux-2.6.37 return ret; } -@@ -557,6 +609,8 @@ +@@ -567,6 +609,8 @@ if (ret) goto out; engine = &dev_priv->engine; @@ -6700,7 +5978,7 @@ diff -Naur linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nouveau_state.c linux-2.6.37 spin_lock_init(&dev_priv->context_switch_lock); /* Make the CRTCs and I2C buses accessible */ -@@ -615,26 +669,28 @@ +@@ -625,26 +669,28 @@ if (ret) goto out_fb; @@ -6737,7 +6015,7 @@ diff -Naur linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nouveau_state.c linux-2.6.37 /* what about PVIDEO/PCRTC/PRAMDAC etc? */ -@@ -659,12 +715,16 @@ +@@ -669,12 +715,16 @@ out_fence: nouveau_fence_fini(dev); out_irq: @@ -6756,7 +6034,7 @@ diff -Naur linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nouveau_state.c linux-2.6.37 out_graph: if (!nouveau_noaccel) engine->graph.takedown(dev); -@@ -703,12 +763,12 @@ +@@ -713,12 +763,12 @@ if (!engine->graph.accel_blocked) { nouveau_fence_fini(dev); @@ -6771,7 +6049,7 @@ diff -Naur linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nouveau_state.c linux-2.6.37 engine->graph.takedown(dev); } engine->fb.takedown(dev); -@@ -727,7 +787,8 @@ +@@ -737,7 +787,8 @@ nouveau_gpuobj_takedown(dev); nouveau_mem_vram_fini(dev); @@ -6781,7 +6059,7 @@ diff -Naur linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nouveau_state.c linux-2.6.37 nouveau_pm_fini(dev); nouveau_bios_takedown(dev); -@@ -1014,21 +1075,6 @@ +@@ -1024,21 +1075,6 @@ else getparam->value = NV_PCI; break; @@ -6803,7 +6081,7 @@ diff -Naur linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nouveau_state.c linux-2.6.37 case NOUVEAU_GETPARAM_FB_SIZE: getparam->value = dev_priv->fb_available_size; break; -@@ -1036,11 +1082,17 @@ +@@ -1046,7 +1082,7 @@ getparam->value = dev_priv->gart_info.aper_size; break; case NOUVEAU_GETPARAM_VM_VRAM_BASE: @@ -6812,35 +6090,17 @@ diff -Naur linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nouveau_state.c linux-2.6.37 break; case NOUVEAU_GETPARAM_PTIMER_TIME: getparam->value = dev_priv->engine.timer.read(dev); +@@ -1054,6 +1090,9 @@ + case NOUVEAU_GETPARAM_HAS_BO_USAGE: + getparam->value = 1; break; -+ case NOUVEAU_GETPARAM_HAS_BO_USAGE: -+ getparam->value = 1; -+ break; + case NOUVEAU_GETPARAM_HAS_PAGEFLIP: + getparam->value = (dev_priv->card_type < NV_50); + break; case NOUVEAU_GETPARAM_GRAPH_UNITS: /* NV40 and NV50 versions are quite different, but register * address is the same. User is supposed to know the card -@@ -1051,7 +1103,7 @@ - } - /* FALLTHRU */ - default: -- NV_ERROR(dev, "unknown parameter %lld\n", getparam->param); -+ NV_DEBUG(dev, "unknown parameter %lld\n", getparam->param); - return -EINVAL; - } - -@@ -1066,7 +1118,7 @@ - - switch (setparam->param) { - default: -- NV_ERROR(dev, "unknown parameter %lld\n", setparam->param); -+ NV_DEBUG(dev, "unknown parameter %lld\n", setparam->param); - return -EINVAL; - } - -@@ -1092,7 +1144,13 @@ +@@ -1105,7 +1144,13 @@ /* Waits for PGRAPH to go completely idle */ bool nouveau_wait_for_idle(struct drm_device *dev) { @@ -6855,21 +6115,9 @@ diff -Naur linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nouveau_state.c linux-2.6.37 NV_ERROR(dev, "PGRAPH idle timed out with status 0x%08x\n", nv_rd32(dev, NV04_PGRAPH_STATUS)); return false; -diff -Naur linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nouveau_temp.c linux-2.6.37-rc2.nouveau/drivers/gpu/drm/nouveau/nouveau_temp.c ---- linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nouveau_temp.c 2010-11-16 03:31:02.000000000 +0100 -+++ linux-2.6.37-rc2.nouveau/drivers/gpu/drm/nouveau/nouveau_temp.c 2010-11-20 14:43:51.000000000 +0100 -@@ -191,7 +191,7 @@ - int offset = sensor->offset_mult / sensor->offset_div; - int core_temp; - -- if (dev_priv->chipset >= 0x50) { -+ if (dev_priv->card_type >= NV_50) { - core_temp = nv_rd32(dev, 0x20008); - } else { - core_temp = nv_rd32(dev, 0x0015b4) & 0x1fff; -diff -Naur linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nouveau_util.c linux-2.6.37-rc2.nouveau/drivers/gpu/drm/nouveau/nouveau_util.c ---- linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nouveau_util.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.37-rc2.nouveau/drivers/gpu/drm/nouveau/nouveau_util.c 2010-11-20 14:43:51.000000000 +0100 +diff -Naur linux-2.6.37-rc3/drivers/gpu/drm/nouveau/nouveau_util.c linux-2.6.37-rc3.nouveau/drivers/gpu/drm/nouveau/nouveau_util.c +--- linux-2.6.37-rc3/drivers/gpu/drm/nouveau/nouveau_util.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.37-rc3.nouveau/drivers/gpu/drm/nouveau/nouveau_util.c 2010-11-22 06:33:32.000000000 +0100 @@ -0,0 +1,69 @@ +/* + * Copyright (C) 2010 Nouveau Project @@ -6940,9 +6188,9 @@ diff -Naur linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nouveau_util.c linux-2.6.37- +{ + return __ratelimit(&nouveau_ratelimit_state); +} -diff -Naur linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nouveau_util.h linux-2.6.37-rc2.nouveau/drivers/gpu/drm/nouveau/nouveau_util.h ---- linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nouveau_util.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.37-rc2.nouveau/drivers/gpu/drm/nouveau/nouveau_util.h 2010-11-20 14:43:51.000000000 +0100 +diff -Naur linux-2.6.37-rc3/drivers/gpu/drm/nouveau/nouveau_util.h linux-2.6.37-rc3.nouveau/drivers/gpu/drm/nouveau/nouveau_util.h +--- linux-2.6.37-rc3/drivers/gpu/drm/nouveau/nouveau_util.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.37-rc3.nouveau/drivers/gpu/drm/nouveau/nouveau_util.h 2010-11-22 06:33:32.000000000 +0100 @@ -0,0 +1,45 @@ +/* + * Copyright (C) 2010 Nouveau Project @@ -6989,29 +6237,10 @@ diff -Naur linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nouveau_util.h linux-2.6.37- +int nouveau_ratelimit(void); + +#endif -diff -Naur linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nv04_crtc.c linux-2.6.37-rc2.nouveau/drivers/gpu/drm/nouveau/nv04_crtc.c ---- linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nv04_crtc.c 2010-11-16 03:31:02.000000000 +0100 -+++ linux-2.6.37-rc2.nouveau/drivers/gpu/drm/nouveau/nv04_crtc.c 2010-11-20 14:43:51.000000000 +0100 -@@ -158,7 +158,6 @@ - { - struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); - struct drm_device *dev = crtc->dev; -- struct drm_connector *connector; - unsigned char seq1 = 0, crtc17 = 0; - unsigned char crtc1A; - -@@ -213,10 +212,6 @@ - NVVgaSeqReset(dev, nv_crtc->index, false); - - NVWriteVgaCrtc(dev, nv_crtc->index, NV_CIO_CRE_RPC1_INDEX, crtc1A); -- -- /* Update connector polling modes */ -- list_for_each_entry(connector, &dev->mode_config.connector_list, head) -- nouveau_connector_set_polling(connector); - } - - static bool -@@ -556,7 +551,10 @@ +diff -Naur linux-2.6.37-rc3/drivers/gpu/drm/nouveau/nv04_crtc.c linux-2.6.37-rc3.nouveau/drivers/gpu/drm/nouveau/nv04_crtc.c +--- linux-2.6.37-rc3/drivers/gpu/drm/nouveau/nv04_crtc.c 2010-11-22 00:18:56.000000000 +0100 ++++ linux-2.6.37-rc3.nouveau/drivers/gpu/drm/nouveau/nv04_crtc.c 2010-11-22 06:33:32.000000000 +0100 +@@ -551,7 +551,10 @@ if (dev_priv->card_type >= NV_30) regp->gpio_ext = NVReadCRTC(dev, 0, NV_PCRTC_GPIO_EXT); @@ -7023,7 +6252,7 @@ diff -Naur linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nv04_crtc.c linux-2.6.37-rc2 /* Some misc regs */ if (dev_priv->card_type == NV_40) { -@@ -674,6 +672,7 @@ +@@ -669,6 +672,7 @@ if (nv_two_heads(dev)) NVSetOwner(dev, nv_crtc->index); @@ -7031,7 +6260,7 @@ diff -Naur linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nv04_crtc.c linux-2.6.37-rc2 funcs->dpms(crtc, DRM_MODE_DPMS_OFF); NVBlankScreen(dev, nv_crtc->index, true); -@@ -706,6 +705,7 @@ +@@ -701,6 +705,7 @@ #endif funcs->dpms(crtc, DRM_MODE_DPMS_ON); @@ -7039,16 +6268,7 @@ diff -Naur linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nv04_crtc.c linux-2.6.37-rc2 } static void nv_crtc_destroy(struct drm_crtc *crtc) -@@ -831,7 +831,7 @@ - /* Update the framebuffer location. */ - regp->fb_start = nv_crtc->fb.offset & ~3; - regp->fb_start += (y * drm_fb->pitch) + (x * drm_fb->bits_per_pixel / 8); -- NVWriteCRTC(dev, nv_crtc->index, NV_PCRTC_START, regp->fb_start); -+ nv_set_crtc_base(dev, nv_crtc->index, regp->fb_start); - - /* Update the arbitration parameters. */ - nouveau_calc_arb(dev, crtc->mode.clock, drm_fb->bits_per_pixel, -@@ -991,6 +991,7 @@ +@@ -986,6 +991,7 @@ .cursor_move = nv04_crtc_cursor_move, .gamma_set = nv_crtc_gamma_set, .set_config = drm_crtc_helper_set_config, @@ -7056,34 +6276,9 @@ diff -Naur linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nv04_crtc.c linux-2.6.37-rc2 .destroy = nv_crtc_destroy, }; -diff -Naur linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nv04_dfp.c linux-2.6.37-rc2.nouveau/drivers/gpu/drm/nouveau/nv04_dfp.c ---- linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nv04_dfp.c 2010-11-16 03:31:02.000000000 +0100 -+++ linux-2.6.37-rc2.nouveau/drivers/gpu/drm/nouveau/nv04_dfp.c 2010-11-20 14:43:51.000000000 +0100 -@@ -185,14 +185,15 @@ - struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); - struct nouveau_connector *nv_connector = nouveau_encoder_connector_get(nv_encoder); - -- /* For internal panels and gpu scaling on DVI we need the native mode */ -- if (nv_connector->scaling_mode != DRM_MODE_SCALE_NONE) { -- if (!nv_connector->native_mode) -- return false; -+ if (!nv_connector->native_mode || -+ nv_connector->scaling_mode == DRM_MODE_SCALE_NONE || -+ mode->hdisplay > nv_connector->native_mode->hdisplay || -+ mode->vdisplay > nv_connector->native_mode->vdisplay) { -+ nv_encoder->mode = *adjusted_mode; -+ -+ } else { - nv_encoder->mode = *nv_connector->native_mode; - adjusted_mode->clock = nv_connector->native_mode->clock; -- } else { -- nv_encoder->mode = *adjusted_mode; - } - - return true; -diff -Naur linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nv04_display.c linux-2.6.37-rc2.nouveau/drivers/gpu/drm/nouveau/nv04_display.c ---- linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nv04_display.c 2010-11-16 03:31:02.000000000 +0100 -+++ linux-2.6.37-rc2.nouveau/drivers/gpu/drm/nouveau/nv04_display.c 2010-11-20 14:43:51.000000000 +0100 +diff -Naur linux-2.6.37-rc3/drivers/gpu/drm/nouveau/nv04_display.c linux-2.6.37-rc3.nouveau/drivers/gpu/drm/nouveau/nv04_display.c +--- linux-2.6.37-rc3/drivers/gpu/drm/nouveau/nv04_display.c 2010-11-22 00:18:56.000000000 +0100 ++++ linux-2.6.37-rc3.nouveau/drivers/gpu/drm/nouveau/nv04_display.c 2010-11-22 06:33:32.000000000 +0100 @@ -32,6 +32,9 @@ #include "nouveau_encoder.h" #include "nouveau_connector.h" @@ -7130,9 +6325,9 @@ diff -Naur linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nv04_display.c linux-2.6.37- + nv_wr32(dev, NV_CRTC1_INTSTAT, NV_CRTC_INTR_VBLANK); + drm_handle_vblank(dev, 1); +} -diff -Naur linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nv04_fbcon.c linux-2.6.37-rc2.nouveau/drivers/gpu/drm/nouveau/nv04_fbcon.c ---- linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nv04_fbcon.c 2010-11-16 03:31:02.000000000 +0100 -+++ linux-2.6.37-rc2.nouveau/drivers/gpu/drm/nouveau/nv04_fbcon.c 2010-11-20 14:43:51.000000000 +0100 +diff -Naur linux-2.6.37-rc3/drivers/gpu/drm/nouveau/nv04_fbcon.c linux-2.6.37-rc3.nouveau/drivers/gpu/drm/nouveau/nv04_fbcon.c +--- linux-2.6.37-rc3/drivers/gpu/drm/nouveau/nv04_fbcon.c 2010-11-22 00:18:56.000000000 +0100 ++++ linux-2.6.37-rc3.nouveau/drivers/gpu/drm/nouveau/nv04_fbcon.c 2010-11-22 06:33:32.000000000 +0100 @@ -28,52 +28,39 @@ #include "nouveau_ramht.h" #include "nouveau_fbcon.h" @@ -7262,9 +6457,9 @@ diff -Naur linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nv04_fbcon.c linux-2.6.37-rc } static int -diff -Naur linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nv04_fifo.c linux-2.6.37-rc2.nouveau/drivers/gpu/drm/nouveau/nv04_fifo.c ---- linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nv04_fifo.c 2010-11-16 03:31:02.000000000 +0100 -+++ linux-2.6.37-rc2.nouveau/drivers/gpu/drm/nouveau/nv04_fifo.c 2010-11-20 14:43:51.000000000 +0100 +diff -Naur linux-2.6.37-rc3/drivers/gpu/drm/nouveau/nv04_fifo.c linux-2.6.37-rc3.nouveau/drivers/gpu/drm/nouveau/nv04_fifo.c +--- linux-2.6.37-rc3/drivers/gpu/drm/nouveau/nv04_fifo.c 2010-11-22 00:18:56.000000000 +0100 ++++ linux-2.6.37-rc3.nouveau/drivers/gpu/drm/nouveau/nv04_fifo.c 2010-11-22 06:33:32.000000000 +0100 @@ -28,6 +28,7 @@ #include "drm.h" #include "nouveau_drv.h" @@ -7537,9 +6732,9 @@ diff -Naur linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nv04_fifo.c linux-2.6.37-rc2 + + nv_wr32(dev, NV03_PMC_INTR_0, NV_PMC_INTR_0_PFIFO_PENDING); +} -diff -Naur linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nv04_graph.c linux-2.6.37-rc2.nouveau/drivers/gpu/drm/nouveau/nv04_graph.c ---- linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nv04_graph.c 2010-11-16 03:31:02.000000000 +0100 -+++ linux-2.6.37-rc2.nouveau/drivers/gpu/drm/nouveau/nv04_graph.c 2010-11-20 14:43:51.000000000 +0100 +diff -Naur linux-2.6.37-rc3/drivers/gpu/drm/nouveau/nv04_graph.c linux-2.6.37-rc3.nouveau/drivers/gpu/drm/nouveau/nv04_graph.c +--- linux-2.6.37-rc3/drivers/gpu/drm/nouveau/nv04_graph.c 2010-11-22 00:18:56.000000000 +0100 ++++ linux-2.6.37-rc3.nouveau/drivers/gpu/drm/nouveau/nv04_graph.c 2010-11-22 06:33:32.000000000 +0100 @@ -26,6 +26,11 @@ #include "drm.h" #include "nouveau_drm.h" @@ -8408,9 +7603,9 @@ diff -Naur linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nv04_graph.c linux-2.6.37-rc + } + } +} -diff -Naur linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nv04_instmem.c linux-2.6.37-rc2.nouveau/drivers/gpu/drm/nouveau/nv04_instmem.c ---- linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nv04_instmem.c 2010-11-16 03:31:02.000000000 +0100 -+++ linux-2.6.37-rc2.nouveau/drivers/gpu/drm/nouveau/nv04_instmem.c 2010-11-20 14:43:51.000000000 +0100 +diff -Naur linux-2.6.37-rc3/drivers/gpu/drm/nouveau/nv04_instmem.c linux-2.6.37-rc3.nouveau/drivers/gpu/drm/nouveau/nv04_instmem.c +--- linux-2.6.37-rc3/drivers/gpu/drm/nouveau/nv04_instmem.c 2010-11-22 00:18:56.000000000 +0100 ++++ linux-2.6.37-rc3.nouveau/drivers/gpu/drm/nouveau/nv04_instmem.c 2010-11-22 06:33:32.000000000 +0100 @@ -98,42 +98,66 @@ } @@ -8490,28 +7685,9 @@ diff -Naur linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nv04_instmem.c linux-2.6.37- +nv04_instmem_flush(struct drm_device *dev) +{ +} -diff -Naur linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nv04_pm.c linux-2.6.37-rc2.nouveau/drivers/gpu/drm/nouveau/nv04_pm.c ---- linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nv04_pm.c 2010-11-16 03:31:02.000000000 +0100 -+++ linux-2.6.37-rc2.nouveau/drivers/gpu/drm/nouveau/nv04_pm.c 2010-11-20 14:43:51.000000000 +0100 -@@ -76,6 +76,15 @@ - reg += 4; - - nouveau_hw_setpll(dev, reg, &state->calc); -+ -+ if (dev_priv->card_type < NV_30 && reg == NV_PRAMDAC_MPLL_COEFF) { -+ if (dev_priv->card_type == NV_20) -+ nv_mask(dev, 0x1002c4, 0, 1 << 20); -+ -+ /* Reset the DLLs */ -+ nv_mask(dev, 0x1002c0, 0, 1 << 8); -+ } -+ - kfree(state); - } - -diff -Naur linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nv10_fb.c linux-2.6.37-rc2.nouveau/drivers/gpu/drm/nouveau/nv10_fb.c ---- linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nv10_fb.c 2010-11-16 03:31:02.000000000 +0100 -+++ linux-2.6.37-rc2.nouveau/drivers/gpu/drm/nouveau/nv10_fb.c 2010-11-20 14:43:51.000000000 +0100 +diff -Naur linux-2.6.37-rc3/drivers/gpu/drm/nouveau/nv10_fb.c linux-2.6.37-rc3.nouveau/drivers/gpu/drm/nouveau/nv10_fb.c +--- linux-2.6.37-rc3/drivers/gpu/drm/nouveau/nv10_fb.c 2010-11-22 00:18:56.000000000 +0100 ++++ linux-2.6.37-rc3.nouveau/drivers/gpu/drm/nouveau/nv10_fb.c 2010-11-22 06:33:32.000000000 +0100 @@ -3,23 +3,109 @@ #include "nouveau_drv.h" #include "nouveau_drm.h" @@ -8663,9 +7839,9 @@ diff -Naur linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nv10_fb.c linux-2.6.37-rc2.n + if (dev_priv->card_type == NV_20) + drm_mm_takedown(&pfb->tag_heap); } -diff -Naur linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nv10_fifo.c linux-2.6.37-rc2.nouveau/drivers/gpu/drm/nouveau/nv10_fifo.c ---- linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nv10_fifo.c 2010-11-16 03:31:02.000000000 +0100 -+++ linux-2.6.37-rc2.nouveau/drivers/gpu/drm/nouveau/nv10_fifo.c 2010-11-20 14:43:51.000000000 +0100 +diff -Naur linux-2.6.37-rc3/drivers/gpu/drm/nouveau/nv10_fifo.c linux-2.6.37-rc3.nouveau/drivers/gpu/drm/nouveau/nv10_fifo.c +--- linux-2.6.37-rc3/drivers/gpu/drm/nouveau/nv10_fifo.c 2010-11-22 00:18:56.000000000 +0100 ++++ linux-2.6.37-rc3.nouveau/drivers/gpu/drm/nouveau/nv10_fifo.c 2010-11-22 06:33:32.000000000 +0100 @@ -73,17 +73,6 @@ return 0; } @@ -8701,9 +7877,9 @@ diff -Naur linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nv10_fifo.c linux-2.6.37-rc2 uint32_t mode = nv_rd32(dev, NV04_PFIFO_MODE); nv_wr32(dev, NV04_PFIFO_MODE, mode | (1 << i)); } -diff -Naur linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nv10_graph.c linux-2.6.37-rc2.nouveau/drivers/gpu/drm/nouveau/nv10_graph.c ---- linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nv10_graph.c 2010-11-16 03:31:02.000000000 +0100 -+++ linux-2.6.37-rc2.nouveau/drivers/gpu/drm/nouveau/nv10_graph.c 2010-11-20 14:43:51.000000000 +0100 +diff -Naur linux-2.6.37-rc3/drivers/gpu/drm/nouveau/nv10_graph.c linux-2.6.37-rc3.nouveau/drivers/gpu/drm/nouveau/nv10_graph.c +--- linux-2.6.37-rc3/drivers/gpu/drm/nouveau/nv10_graph.c 2010-11-22 00:18:56.000000000 +0100 ++++ linux-2.6.37-rc3.nouveau/drivers/gpu/drm/nouveau/nv10_graph.c 2010-11-22 06:33:32.000000000 +0100 @@ -26,6 +26,10 @@ #include "drm.h" #include "nouveau_drm.h" @@ -9018,9 +8194,9 @@ diff -Naur linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nv10_graph.c linux-2.6.37-rc + } + } +} -diff -Naur linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nv20_graph.c linux-2.6.37-rc2.nouveau/drivers/gpu/drm/nouveau/nv20_graph.c ---- linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nv20_graph.c 2010-11-16 03:31:02.000000000 +0100 -+++ linux-2.6.37-rc2.nouveau/drivers/gpu/drm/nouveau/nv20_graph.c 2010-11-20 14:43:51.000000000 +0100 +diff -Naur linux-2.6.37-rc3/drivers/gpu/drm/nouveau/nv20_graph.c linux-2.6.37-rc3.nouveau/drivers/gpu/drm/nouveau/nv20_graph.c +--- linux-2.6.37-rc3/drivers/gpu/drm/nouveau/nv20_graph.c 2010-11-22 00:18:56.000000000 +0100 ++++ linux-2.6.37-rc3.nouveau/drivers/gpu/drm/nouveau/nv20_graph.c 2010-11-22 06:33:32.000000000 +0100 @@ -32,6 +32,10 @@ #define NV34_GRCTX_SIZE (18140) #define NV35_36_GRCTX_SIZE (22396) @@ -9351,9 +8527,9 @@ diff -Naur linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nv20_graph.c linux-2.6.37-rc + } + } +} -diff -Naur linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nv30_fb.c linux-2.6.37-rc2.nouveau/drivers/gpu/drm/nouveau/nv30_fb.c ---- linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nv30_fb.c 2010-11-16 03:31:02.000000000 +0100 -+++ linux-2.6.37-rc2.nouveau/drivers/gpu/drm/nouveau/nv30_fb.c 2010-11-20 14:43:51.000000000 +0100 +diff -Naur linux-2.6.37-rc3/drivers/gpu/drm/nouveau/nv30_fb.c linux-2.6.37-rc3.nouveau/drivers/gpu/drm/nouveau/nv30_fb.c +--- linux-2.6.37-rc3/drivers/gpu/drm/nouveau/nv30_fb.c 2010-11-22 00:18:56.000000000 +0100 ++++ linux-2.6.37-rc3.nouveau/drivers/gpu/drm/nouveau/nv30_fb.c 2010-11-22 06:33:32.000000000 +0100 @@ -29,6 +29,27 @@ #include "nouveau_drv.h" #include "nouveau_drm.h" @@ -9391,9 +8567,9 @@ diff -Naur linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nv30_fb.c linux-2.6.37-rc2.n /* Init the memory timing regs at 0x10037c/0x1003ac */ if (dev_priv->chipset == 0x30 || -diff -Naur linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nv40_fb.c linux-2.6.37-rc2.nouveau/drivers/gpu/drm/nouveau/nv40_fb.c ---- linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nv40_fb.c 2010-11-16 03:31:02.000000000 +0100 -+++ linux-2.6.37-rc2.nouveau/drivers/gpu/drm/nouveau/nv40_fb.c 2010-11-20 14:43:51.000000000 +0100 +diff -Naur linux-2.6.37-rc3/drivers/gpu/drm/nouveau/nv40_fb.c linux-2.6.37-rc3.nouveau/drivers/gpu/drm/nouveau/nv40_fb.c +--- linux-2.6.37-rc3/drivers/gpu/drm/nouveau/nv40_fb.c 2010-11-22 00:18:56.000000000 +0100 ++++ linux-2.6.37-rc3.nouveau/drivers/gpu/drm/nouveau/nv40_fb.c 2010-11-22 06:33:32.000000000 +0100 @@ -4,26 +4,22 @@ #include "nouveau_drm.h" @@ -9438,9 +8614,9 @@ diff -Naur linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nv40_fb.c linux-2.6.37-rc2.n return 0; } -diff -Naur linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nv40_fifo.c linux-2.6.37-rc2.nouveau/drivers/gpu/drm/nouveau/nv40_fifo.c ---- linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nv40_fifo.c 2010-11-16 03:31:02.000000000 +0100 -+++ linux-2.6.37-rc2.nouveau/drivers/gpu/drm/nouveau/nv40_fifo.c 2010-11-20 14:43:51.000000000 +0100 +diff -Naur linux-2.6.37-rc3/drivers/gpu/drm/nouveau/nv40_fifo.c linux-2.6.37-rc3.nouveau/drivers/gpu/drm/nouveau/nv40_fifo.c +--- linux-2.6.37-rc3/drivers/gpu/drm/nouveau/nv40_fifo.c 2010-11-22 00:18:56.000000000 +0100 ++++ linux-2.6.37-rc3.nouveau/drivers/gpu/drm/nouveau/nv40_fifo.c 2010-11-22 06:33:32.000000000 +0100 @@ -70,17 +70,6 @@ return 0; } @@ -9476,9 +8652,9 @@ diff -Naur linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nv40_fifo.c linux-2.6.37-rc2 uint32_t mode = nv_rd32(dev, NV04_PFIFO_MODE); nv_wr32(dev, NV04_PFIFO_MODE, mode | (1 << i)); } -diff -Naur linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nv40_graph.c linux-2.6.37-rc2.nouveau/drivers/gpu/drm/nouveau/nv40_graph.c ---- linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nv40_graph.c 2010-11-16 03:31:02.000000000 +0100 -+++ linux-2.6.37-rc2.nouveau/drivers/gpu/drm/nouveau/nv40_graph.c 2010-11-20 14:43:51.000000000 +0100 +diff -Naur linux-2.6.37-rc3/drivers/gpu/drm/nouveau/nv40_graph.c linux-2.6.37-rc3.nouveau/drivers/gpu/drm/nouveau/nv40_graph.c +--- linux-2.6.37-rc3/drivers/gpu/drm/nouveau/nv40_graph.c 2010-11-22 00:18:56.000000000 +0100 ++++ linux-2.6.37-rc3.nouveau/drivers/gpu/drm/nouveau/nv40_graph.c 2010-11-22 06:33:32.000000000 +0100 @@ -29,6 +29,9 @@ #include "nouveau_drv.h" #include "nouveau_grctx.h" @@ -9747,47 +8923,9 @@ diff -Naur linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nv40_graph.c linux-2.6.37-rc + } + } +} -diff -Naur linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nv50_calc.c linux-2.6.37-rc2.nouveau/drivers/gpu/drm/nouveau/nv50_calc.c ---- linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nv50_calc.c 2010-11-16 03:31:02.000000000 +0100 -+++ linux-2.6.37-rc2.nouveau/drivers/gpu/drm/nouveau/nv50_calc.c 2010-11-20 14:43:51.000000000 +0100 -@@ -51,24 +51,28 @@ - int *N, int *fN, int *M, int *P) - { - fixed20_12 fb_div, a, b; -+ u32 refclk = pll->refclk / 10; -+ u32 max_vco_freq = pll->vco1.maxfreq / 10; -+ u32 max_vco_inputfreq = pll->vco1.max_inputfreq / 10; -+ clk /= 10; - -- *P = pll->vco1.maxfreq / clk; -+ *P = max_vco_freq / clk; - if (*P > pll->max_p) - *P = pll->max_p; - if (*P < pll->min_p) - *P = pll->min_p; - -- /* *M = ceil(refclk / pll->vco.max_inputfreq); */ -- a.full = dfixed_const(pll->refclk); -- b.full = dfixed_const(pll->vco1.max_inputfreq); -+ /* *M = floor((refclk + max_vco_inputfreq) / max_vco_inputfreq); */ -+ a.full = dfixed_const(refclk + max_vco_inputfreq); -+ b.full = dfixed_const(max_vco_inputfreq); - a.full = dfixed_div(a, b); -- a.full = dfixed_ceil(a); -+ a.full = dfixed_floor(a); - *M = dfixed_trunc(a); - - /* fb_div = (vco * *M) / refclk; */ - fb_div.full = dfixed_const(clk * *P); - fb_div.full = dfixed_mul(fb_div, a); -- a.full = dfixed_const(pll->refclk); -+ a.full = dfixed_const(refclk); - fb_div.full = dfixed_div(fb_div, a); - - /* *N = floor(fb_div); */ -diff -Naur linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nv50_crtc.c linux-2.6.37-rc2.nouveau/drivers/gpu/drm/nouveau/nv50_crtc.c ---- linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nv50_crtc.c 2010-11-16 03:31:02.000000000 +0100 -+++ linux-2.6.37-rc2.nouveau/drivers/gpu/drm/nouveau/nv50_crtc.c 2010-11-20 14:43:51.000000000 +0100 +diff -Naur linux-2.6.37-rc3/drivers/gpu/drm/nouveau/nv50_crtc.c linux-2.6.37-rc3.nouveau/drivers/gpu/drm/nouveau/nv50_crtc.c +--- linux-2.6.37-rc3/drivers/gpu/drm/nouveau/nv50_crtc.c 2010-11-22 00:18:56.000000000 +0100 ++++ linux-2.6.37-rc3.nouveau/drivers/gpu/drm/nouveau/nv50_crtc.c 2010-11-22 06:33:32.000000000 +0100 @@ -437,6 +437,7 @@ .cursor_move = nv50_crtc_cursor_move, .gamma_set = nv50_crtc_gamma_set, @@ -9812,27 +8950,9 @@ diff -Naur linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nv50_crtc.c linux-2.6.37-rc2 ret = RING_SPACE(evo, 2); if (ret) { -@@ -546,7 +549,7 @@ - } - - nv_crtc->fb.offset = fb->nvbo->bo.offset - dev_priv->vm_vram_base; -- nv_crtc->fb.tile_flags = fb->nvbo->tile_flags; -+ 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) { - ret = RING_SPACE(evo, 2); -@@ -578,7 +581,7 @@ - fb->nvbo->tile_mode); - } - if (dev_priv->chipset == 0x50) -- OUT_RING(evo, (fb->nvbo->tile_flags << 8) | format); -+ OUT_RING(evo, (nv_crtc->fb.tile_flags << 8) | format); - else - OUT_RING(evo, format); - -diff -Naur linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nv50_display.c linux-2.6.37-rc2.nouveau/drivers/gpu/drm/nouveau/nv50_display.c ---- linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nv50_display.c 2010-11-16 03:31:02.000000000 +0100 -+++ linux-2.6.37-rc2.nouveau/drivers/gpu/drm/nouveau/nv50_display.c 2010-11-20 14:43:51.000000000 +0100 +diff -Naur linux-2.6.37-rc3/drivers/gpu/drm/nouveau/nv50_display.c linux-2.6.37-rc3.nouveau/drivers/gpu/drm/nouveau/nv50_display.c +--- linux-2.6.37-rc3/drivers/gpu/drm/nouveau/nv50_display.c 2010-11-22 00:18:56.000000000 +0100 ++++ linux-2.6.37-rc3.nouveau/drivers/gpu/drm/nouveau/nv50_display.c 2010-11-22 06:33:32.000000000 +0100 @@ -33,6 +33,8 @@ #include "nouveau_ramht.h" #include "drm_crtc_helper.h" @@ -10112,6 +9232,10 @@ diff -Naur linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nv50_display.c linux-2.6.37- + NV50_PDISPLAY_INTR_EN_1_CLK_UNK10 | + NV50_PDISPLAY_INTR_EN_1_CLK_UNK20 | + NV50_PDISPLAY_INTR_EN_1_CLK_UNK40); ++ ++ /* enable hotplug interrupts */ ++ list_for_each_entry(connector, &dev->mode_config.connector_list, head) { ++ struct nouveau_connector *conn = nouveau_connector(connector); - /* initialise fifo */ - nv_wr32(dev, NV50_PDISPLAY_CHANNEL_DMA_CB(0), @@ -10137,17 +9261,13 @@ diff -Naur linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nv50_display.c linux-2.6.37- - evo->dma.put = 0; - evo->dma.cur = evo->dma.put; - evo->dma.free = evo->dma.max - evo->dma.cur; -+ /* enable hotplug interrupts */ -+ list_for_each_entry(connector, &dev->mode_config.connector_list, head) { -+ struct nouveau_connector *conn = nouveau_connector(connector); -+ + if (conn->dcb->gpio_tag == 0xff) + continue; -+ -+ pgpio->irq_enable(dev, conn->dcb->gpio_tag, true); -+ } - ret = RING_SPACE(evo, NOUVEAU_DMA_SKIPS); ++ pgpio->irq_enable(dev, conn->dcb->gpio_tag, true); ++ } ++ + ret = nv50_evo_init(dev); if (ret) return ret; @@ -10287,7 +9407,7 @@ diff -Naur linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nv50_display.c linux-2.6.37- } static void -@@ -1011,91 +785,31 @@ +@@ -1011,108 +785,31 @@ static void nv50_display_error_handler(struct drm_device *dev) { @@ -10312,11 +9432,18 @@ diff -Naur linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nv50_display.c linux-2.6.37- - struct drm_connector *connector; - const uint32_t gpio_reg[4] = { 0xe104, 0xe108, 0xe280, 0xe284 }; - uint32_t unplug_mask, plug_mask, change_mask; -- uint32_t hpd0, hpd1 = 0; +- uint32_t hpd0, hpd1; - -- hpd0 = nv_rd32(dev, 0xe054) & nv_rd32(dev, 0xe050); +- spin_lock_irq(&dev_priv->hpd_state.lock); +- hpd0 = dev_priv->hpd_state.hpd0_bits; +- dev_priv->hpd_state.hpd0_bits = 0; +- hpd1 = dev_priv->hpd_state.hpd1_bits; +- dev_priv->hpd_state.hpd1_bits = 0; +- spin_unlock_irq(&dev_priv->hpd_state.lock); +- +- hpd0 &= nv_rd32(dev, 0xe050); - if (dev_priv->chipset >= 0x90) -- hpd1 = nv_rd32(dev, 0xe074) & nv_rd32(dev, 0xe070); +- hpd1 &= nv_rd32(dev, 0xe070); - - plug_mask = (hpd0 & 0x0000ffff) | (hpd1 << 16); - unplug_mask = (hpd0 >> 16) | (hpd1 & 0xffff0000); @@ -10330,6 +9457,13 @@ diff -Naur linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nv50_display.c linux-2.6.37- - struct dcb_gpio_entry *gpio; - uint32_t reg; - bool plugged; +- +- if (!nv_connector->dcb) +- continue; +- +- gpio = nouveau_bios_gpio_entry(dev, nv_connector->dcb->gpio_tag); +- if (!gpio || !(change_mask & (1 << gpio->line))) +- continue; + u32 channels = (nv_rd32(dev, NV50_PDISPLAY_INTR_0) & 0x001f0000) >> 16; + u32 addr, data; + int chid; @@ -10345,13 +9479,6 @@ diff -Naur linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nv50_display.c linux-2.6.37- + "(0x%04x 0x%02x)\n", chid, + addr & 0xffc, data, addr >> 16, (addr >> 12) & 0xf); -- if (!nv_connector->dcb) -- continue; -- -- gpio = nouveau_bios_gpio_entry(dev, nv_connector->dcb->gpio_tag); -- if (!gpio || !(change_mask & (1 << gpio->line))) -- continue; -- - reg = nv_rd32(dev, gpio_reg[gpio->line >> 3]); - plugged = !!(reg & (4 << ((gpio->line & 7) << 2))); - NV_INFO(dev, "%splugged %s\n", plugged ? "" : "un", @@ -10373,10 +9500,6 @@ diff -Naur linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nv50_display.c linux-2.6.37- + nv_wr32(dev, NV50_PDISPLAY_TRAPPED_ADDR(chid), 0x90000000); } - -- nv_wr32(dev, 0xe054, nv_rd32(dev, 0xe054)); -- if (dev_priv->chipset >= 0x90) -- nv_wr32(dev, 0xe074, nv_rd32(dev, 0xe074)); -- - drm_helper_hpd_irq_event(dev); } @@ -10389,14 +9512,28 @@ diff -Naur linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nv50_display.c linux-2.6.37- uint32_t delayed = 0; - if (nv_rd32(dev, NV50_PMC_INTR_0) & NV50_PMC_INTR_0_HOTPLUG) { -- if (!work_pending(&dev_priv->hpd_work)) -- queue_work(dev_priv->wq, &dev_priv->hpd_work); +- uint32_t hpd0_bits, hpd1_bits = 0; +- +- hpd0_bits = nv_rd32(dev, 0xe054); +- nv_wr32(dev, 0xe054, hpd0_bits); +- +- if (dev_priv->chipset >= 0x90) { +- hpd1_bits = nv_rd32(dev, 0xe074); +- nv_wr32(dev, 0xe074, hpd1_bits); +- } +- +- spin_lock(&dev_priv->hpd_state.lock); +- dev_priv->hpd_state.hpd0_bits |= hpd0_bits; +- dev_priv->hpd_state.hpd1_bits |= hpd1_bits; +- spin_unlock(&dev_priv->hpd_state.lock); +- +- queue_work(dev_priv->wq, &dev_priv->hpd_work); - } - 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); -@@ -1106,9 +820,9 @@ +@@ -1123,9 +820,9 @@ if (!intr0 && !(intr1 & ~delayed)) break; @@ -10408,14 +9545,14 @@ diff -Naur linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nv50_display.c linux-2.6.37- } if (intr1 & NV50_PDISPLAY_INTR_1_VBLANK_CRTC) { -@@ -1139,4 +853,3 @@ +@@ -1156,4 +853,3 @@ } } } - -diff -Naur linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nv50_display.h linux-2.6.37-rc2.nouveau/drivers/gpu/drm/nouveau/nv50_display.h ---- linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nv50_display.h 2010-11-16 03:31:02.000000000 +0100 -+++ linux-2.6.37-rc2.nouveau/drivers/gpu/drm/nouveau/nv50_display.h 2010-11-20 14:43:51.000000000 +0100 +diff -Naur linux-2.6.37-rc3/drivers/gpu/drm/nouveau/nv50_display.h linux-2.6.37-rc3.nouveau/drivers/gpu/drm/nouveau/nv50_display.h +--- linux-2.6.37-rc3/drivers/gpu/drm/nouveau/nv50_display.h 2010-11-22 00:18:56.000000000 +0100 ++++ linux-2.6.37-rc3.nouveau/drivers/gpu/drm/nouveau/nv50_display.h 2010-11-22 06:33:32.000000000 +0100 @@ -35,9 +35,7 @@ #include "nouveau_crtc.h" #include "nv50_evo.h" @@ -10426,9 +9563,9 @@ diff -Naur linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nv50_display.h linux-2.6.37- int nv50_display_early_init(struct drm_device *dev); void nv50_display_late_takedown(struct drm_device *dev); int nv50_display_create(struct drm_device *dev); -diff -Naur linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nv50_evo.c linux-2.6.37-rc2.nouveau/drivers/gpu/drm/nouveau/nv50_evo.c ---- linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nv50_evo.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.37-rc2.nouveau/drivers/gpu/drm/nouveau/nv50_evo.c 2010-11-20 14:43:51.000000000 +0100 +diff -Naur linux-2.6.37-rc3/drivers/gpu/drm/nouveau/nv50_evo.c linux-2.6.37-rc3.nouveau/drivers/gpu/drm/nouveau/nv50_evo.c +--- linux-2.6.37-rc3/drivers/gpu/drm/nouveau/nv50_evo.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.37-rc3.nouveau/drivers/gpu/drm/nouveau/nv50_evo.c 2010-11-22 06:33:32.000000000 +0100 @@ -0,0 +1,318 @@ +/* + * Copyright 2010 Red Hat Inc. @@ -10748,9 +9885,9 @@ diff -Naur linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nv50_evo.c linux-2.6.37-rc2. + nv50_evo_channel_del(&dev_priv->evo); + } +} -diff -Naur linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nv50_evo.h linux-2.6.37-rc2.nouveau/drivers/gpu/drm/nouveau/nv50_evo.h ---- linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nv50_evo.h 2010-11-16 03:31:02.000000000 +0100 -+++ linux-2.6.37-rc2.nouveau/drivers/gpu/drm/nouveau/nv50_evo.h 2010-11-20 14:43:51.000000000 +0100 +diff -Naur linux-2.6.37-rc3/drivers/gpu/drm/nouveau/nv50_evo.h linux-2.6.37-rc3.nouveau/drivers/gpu/drm/nouveau/nv50_evo.h +--- linux-2.6.37-rc3/drivers/gpu/drm/nouveau/nv50_evo.h 2010-11-22 00:18:56.000000000 +0100 ++++ linux-2.6.37-rc3.nouveau/drivers/gpu/drm/nouveau/nv50_evo.h 2010-11-22 06:33:32.000000000 +0100 @@ -24,6 +24,15 @@ * */ @@ -10772,9 +9909,9 @@ diff -Naur linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nv50_evo.h linux-2.6.37-rc2. #define NV50_EVO_CRTC_SCALE_RES2 0x000008dc +#endif -diff -Naur linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nv50_fb.c linux-2.6.37-rc2.nouveau/drivers/gpu/drm/nouveau/nv50_fb.c ---- linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nv50_fb.c 2010-11-16 03:31:02.000000000 +0100 -+++ linux-2.6.37-rc2.nouveau/drivers/gpu/drm/nouveau/nv50_fb.c 2010-11-20 14:43:51.000000000 +0100 +diff -Naur linux-2.6.37-rc3/drivers/gpu/drm/nouveau/nv50_fb.c linux-2.6.37-rc3.nouveau/drivers/gpu/drm/nouveau/nv50_fb.c +--- linux-2.6.37-rc3/drivers/gpu/drm/nouveau/nv50_fb.c 2010-11-22 00:18:56.000000000 +0100 ++++ linux-2.6.37-rc3.nouveau/drivers/gpu/drm/nouveau/nv50_fb.c 2010-11-22 06:33:32.000000000 +0100 @@ -3,30 +3,75 @@ #include "nouveau_drv.h" #include "nouveau_drm.h" @@ -10901,9 +10038,9 @@ diff -Naur linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nv50_fb.c linux-2.6.37-rc2.n NV_INFO(dev, "%s - VM: Trapped %s at %02x%04x%04x status %08x " "channel %d (0x%08x)\n", -diff -Naur linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nv50_fbcon.c linux-2.6.37-rc2.nouveau/drivers/gpu/drm/nouveau/nv50_fbcon.c ---- linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nv50_fbcon.c 2010-11-16 03:31:02.000000000 +0100 -+++ linux-2.6.37-rc2.nouveau/drivers/gpu/drm/nouveau/nv50_fbcon.c 2010-11-20 14:43:51.000000000 +0100 +diff -Naur linux-2.6.37-rc3/drivers/gpu/drm/nouveau/nv50_fbcon.c linux-2.6.37-rc3.nouveau/drivers/gpu/drm/nouveau/nv50_fbcon.c +--- linux-2.6.37-rc3/drivers/gpu/drm/nouveau/nv50_fbcon.c 2010-11-22 00:18:56.000000000 +0100 ++++ linux-2.6.37-rc3.nouveau/drivers/gpu/drm/nouveau/nv50_fbcon.c 2010-11-22 06:33:32.000000000 +0100 @@ -4,26 +4,18 @@ #include "nouveau_ramht.h" #include "nouveau_fbcon.h" @@ -11035,9 +10172,9 @@ diff -Naur linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nv50_fbcon.c linux-2.6.37-rc } int -diff -Naur linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nv50_fifo.c linux-2.6.37-rc2.nouveau/drivers/gpu/drm/nouveau/nv50_fifo.c ---- linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nv50_fifo.c 2010-11-16 03:31:02.000000000 +0100 -+++ linux-2.6.37-rc2.nouveau/drivers/gpu/drm/nouveau/nv50_fifo.c 2010-11-20 14:43:51.000000000 +0100 +diff -Naur linux-2.6.37-rc3/drivers/gpu/drm/nouveau/nv50_fifo.c linux-2.6.37-rc3.nouveau/drivers/gpu/drm/nouveau/nv50_fifo.c +--- linux-2.6.37-rc3/drivers/gpu/drm/nouveau/nv50_fifo.c 2010-11-22 00:18:56.000000000 +0100 ++++ linux-2.6.37-rc3.nouveau/drivers/gpu/drm/nouveau/nv50_fifo.c 2010-11-22 06:33:32.000000000 +0100 @@ -44,7 +44,8 @@ /* We never schedule channel 0 or 127 */ @@ -11128,18 +10265,9 @@ diff -Naur linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nv50_fifo.c linux-2.6.37-rc2 if (!chan) { NV_ERROR(dev, "Inactive channel on PFIFO: %d\n", chid); return -EINVAL; -@@ -464,3 +486,8 @@ - return 0; - } - -+void -+nv50_fifo_tlb_flush(struct drm_device *dev) -+{ -+ nv50_vm_flush(dev, 5); -+} -diff -Naur linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nv50_gpio.c linux-2.6.37-rc2.nouveau/drivers/gpu/drm/nouveau/nv50_gpio.c ---- linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nv50_gpio.c 2010-11-16 03:31:02.000000000 +0100 -+++ linux-2.6.37-rc2.nouveau/drivers/gpu/drm/nouveau/nv50_gpio.c 2010-11-20 14:43:51.000000000 +0100 +diff -Naur linux-2.6.37-rc3/drivers/gpu/drm/nouveau/nv50_gpio.c linux-2.6.37-rc3.nouveau/drivers/gpu/drm/nouveau/nv50_gpio.c +--- linux-2.6.37-rc3/drivers/gpu/drm/nouveau/nv50_gpio.c 2010-11-22 00:18:56.000000000 +0100 ++++ linux-2.6.37-rc3.nouveau/drivers/gpu/drm/nouveau/nv50_gpio.c 2010-11-22 06:33:32.000000000 +0100 @@ -26,6 +26,28 @@ #include "nouveau_drv.h" #include "nouveau_hw.h" @@ -11376,9 +10504,9 @@ diff -Naur linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nv50_gpio.c linux-2.6.37-rc2 + } + spin_unlock(&priv->lock); +} -diff -Naur linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nv50_graph.c linux-2.6.37-rc2.nouveau/drivers/gpu/drm/nouveau/nv50_graph.c ---- linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nv50_graph.c 2010-11-16 03:31:02.000000000 +0100 -+++ linux-2.6.37-rc2.nouveau/drivers/gpu/drm/nouveau/nv50_graph.c 2010-11-20 14:43:51.000000000 +0100 +diff -Naur linux-2.6.37-rc3/drivers/gpu/drm/nouveau/nv50_graph.c linux-2.6.37-rc3.nouveau/drivers/gpu/drm/nouveau/nv50_graph.c +--- linux-2.6.37-rc3/drivers/gpu/drm/nouveau/nv50_graph.c 2010-11-22 00:18:56.000000000 +0100 ++++ linux-2.6.37-rc3.nouveau/drivers/gpu/drm/nouveau/nv50_graph.c 2010-11-22 06:33:32.000000000 +0100 @@ -29,6 +29,11 @@ #include "nouveau_drv.h" #include "nouveau_ramht.h" @@ -11524,7 +10652,7 @@ diff -Naur linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nv50_graph.c linux-2.6.37-rc { struct drm_device *dev = chan->dev; struct drm_nouveau_private *dev_priv = dev->dev_private; -@@ -368,37 +390,621 @@ +@@ -368,40 +390,80 @@ if (!chan->nvsw.vblsem || chan->nvsw.vblsem_offset == ~0 || data > 1) return -EINVAL; @@ -11541,15 +10669,35 @@ diff -Naur linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nv50_graph.c linux-2.6.37-rc + chan->nvsw.vblsem_head = data; list_add(&chan->nvsw.vbl_wait, &dev_priv->vbl_waiting); + -+ return 0; -+} -+ + return 0; + } + +-static struct nouveau_pgraph_object_method nv50_graph_nvsw_methods[] = { +- { 0x018c, nv50_graph_nvsw_dma_vblsem }, +- { 0x0400, nv50_graph_nvsw_vblsem_offset }, +- { 0x0404, nv50_graph_nvsw_vblsem_release_val }, +- { 0x0408, nv50_graph_nvsw_vblsem_release }, +- {} +-}; +static int +nv50_graph_nvsw_mthd_page_flip(struct nouveau_channel *chan, + u32 class, u32 mthd, u32 data) +{ + struct nouveau_page_flip_state s; -+ + +-struct nouveau_pgraph_object_class nv50_graph_grclass[] = { +- { 0x506e, true, nv50_graph_nvsw_methods }, /* nvsw */ +- { 0x0030, false, NULL }, /* null */ +- { 0x5039, false, NULL }, /* m2mf */ +- { 0x502d, false, NULL }, /* 2d */ +- { 0x50c0, false, NULL }, /* compute */ +- { 0x85c0, false, NULL }, /* compute (nva3, nva5, nva8) */ +- { 0x5097, false, NULL }, /* tesla (nv50) */ +- { 0x8297, false, NULL }, /* tesla (nv8x/nv9x) */ +- { 0x8397, false, NULL }, /* tesla (nva0, nvaa, nvac) */ +- { 0x8597, false, NULL }, /* tesla (nva3, nva5, nva8) */ +- {} +-}; + if (!nouveau_finish_page_flip(chan, &s)) { + /* XXX - Do something here */ + } @@ -11608,65 +10756,15 @@ diff -Naur linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nv50_graph.c linux-2.6.37-rc + NVOBJ_CLASS(dev, 0x85c0, GR); + + dev_priv->engine.graph.registered = true; - return 0; - } ++ return 0; ++} --static struct nouveau_pgraph_object_method nv50_graph_nvsw_methods[] = { -- { 0x018c, nv50_graph_nvsw_dma_vblsem }, -- { 0x0400, nv50_graph_nvsw_vblsem_offset }, -- { 0x0404, nv50_graph_nvsw_vblsem_release_val }, -- { 0x0408, nv50_graph_nvsw_vblsem_release }, -+void -+nv50_graph_tlb_flush(struct drm_device *dev) -+{ -+ nv50_vm_flush(dev, 0); -+} -+ -+void -+nv86_graph_tlb_flush(struct drm_device *dev) -+{ -+ struct drm_nouveau_private *dev_priv = dev->dev_private; -+ struct nouveau_timer_engine *ptimer = &dev_priv->engine.timer; -+ 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); -+ -+ start = ptimer->read(dev); -+ do { -+ idle = true; -+ -+ for (tmp = nv_rd32(dev, 0x400380); tmp && idle; tmp >>= 3) { -+ if ((tmp & 7) == 1) -+ idle = false; -+ } -+ -+ for (tmp = nv_rd32(dev, 0x400384); tmp && idle; tmp >>= 3) { -+ if ((tmp & 7) == 1) -+ idle = false; -+ } -+ -+ for (tmp = nv_rd32(dev, 0x400388); tmp && idle; tmp >>= 3) { -+ if ((tmp & 7) == 1) -+ idle = false; -+ } -+ } while (!idle && !(timeout = ptimer->read(dev) - start > 2000000000)); -+ -+ if (timeout) { -+ NV_ERROR(dev, "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)); -+ } -+ -+ nv50_vm_flush(dev, 0); -+ -+ nv_mask(dev, 0x400500, 0x00000001, 0x00000001); -+ spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags); -+} + void + nv50_graph_tlb_flush(struct drm_device *dev) +@@ -454,3 +516,495 @@ + nv_mask(dev, 0x400500, 0x00000001, 0x00000001); + spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags); + } + +static struct nouveau_enum nv50_mp_exec_error_names[] = +{ @@ -11697,20 +10795,9 @@ diff -Naur linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nv50_graph.c linux-2.6.37-rc + +static struct nouveau_bitfield nv50_graph_trap_ccache[] = { + { 0x00000001, "FAULT" }, - {} - }; - --struct nouveau_pgraph_object_class nv50_graph_grclass[] = { -- { 0x506e, true, nv50_graph_nvsw_methods }, /* nvsw */ -- { 0x0030, false, NULL }, /* null */ -- { 0x5039, false, NULL }, /* m2mf */ -- { 0x502d, false, NULL }, /* 2d */ -- { 0x50c0, false, NULL }, /* compute */ -- { 0x85c0, false, NULL }, /* compute (nva3, nva5, nva8) */ -- { 0x5097, false, NULL }, /* tesla (nv50) */ -- { 0x8297, false, NULL }, /* tesla (nv8x/nv9x) */ -- { 0x8397, false, NULL }, /* tesla (nva0, nvaa, nvac) */ -- { 0x8597, false, NULL }, /* tesla (nva3, nva5, nva8) */ ++ {} ++}; ++ +/* There must be a *lot* of these. Will take some time to gather them up. */ +static struct nouveau_enum nv50_data_error_names[] = { + { 4, "INVALID_VALUE" }, @@ -11719,8 +10806,8 @@ diff -Naur linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nv50_graph.c linux-2.6.37-rc + { 0xc, "INVALID_BITFIELD" }, + { 0x28, "MP_NO_REG_SPACE" }, + { 0x2b, "MP_BLOCK_SIZE_MISMATCH" }, - {} - }; ++ {} ++}; + +static struct nouveau_bitfield nv50_graph_intr[] = { + { 0x00000001, "NOTIFY" }, @@ -12170,9 +11257,9 @@ diff -Naur linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nv50_graph.c linux-2.6.37-rc + if (nv_rd32(dev, 0x400824) & (1 << 31)) + nv_wr32(dev, 0x400824, nv_rd32(dev, 0x400824) & ~(1 << 31)); +} -diff -Naur linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nv50_instmem.c linux-2.6.37-rc2.nouveau/drivers/gpu/drm/nouveau/nv50_instmem.c ---- linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nv50_instmem.c 2010-11-16 03:31:02.000000000 +0100 -+++ linux-2.6.37-rc2.nouveau/drivers/gpu/drm/nouveau/nv50_instmem.c 2010-11-20 14:43:51.000000000 +0100 +diff -Naur linux-2.6.37-rc3/drivers/gpu/drm/nouveau/nv50_instmem.c linux-2.6.37-rc3.nouveau/drivers/gpu/drm/nouveau/nv50_instmem.c +--- linux-2.6.37-rc3/drivers/gpu/drm/nouveau/nv50_instmem.c 2010-11-22 00:18:56.000000000 +0100 ++++ linux-2.6.37-rc3.nouveau/drivers/gpu/drm/nouveau/nv50_instmem.c 2010-11-22 06:33:32.000000000 +0100 @@ -131,10 +131,10 @@ } @@ -12387,7 +11474,7 @@ diff -Naur linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nv50_instmem.c linux-2.6.37- NV_DEBUG(dev, "first vram page: 0x%010llx\n", gpuobj->vinst); vram |= 1; -@@ -395,46 +396,45 @@ +@@ -395,8 +396,8 @@ } while (pte < pte_end) { @@ -12398,9 +11485,8 @@ diff -Naur linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nv50_instmem.c linux-2.6.37- vram += 0x1000; pte += 2; } - dev_priv->engine.instmem.flush(dev); +@@ -404,36 +405,36 @@ -- nv50_vm_flush(dev, 4); nv50_vm_flush(dev, 6); - gpuobj->im_bound = 1; @@ -12452,9 +11538,9 @@ diff -Naur linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nv50_instmem.c linux-2.6.37- } void -diff -Naur linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nv84_crypt.c linux-2.6.37-rc2.nouveau/drivers/gpu/drm/nouveau/nv84_crypt.c ---- linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nv84_crypt.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.37-rc2.nouveau/drivers/gpu/drm/nouveau/nv84_crypt.c 2010-11-20 14:43:51.000000000 +0100 +diff -Naur linux-2.6.37-rc3/drivers/gpu/drm/nouveau/nv84_crypt.c linux-2.6.37-rc3.nouveau/drivers/gpu/drm/nouveau/nv84_crypt.c +--- linux-2.6.37-rc3/drivers/gpu/drm/nouveau/nv84_crypt.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.37-rc3.nouveau/drivers/gpu/drm/nouveau/nv84_crypt.c 2010-11-22 06:33:32.000000000 +0100 @@ -0,0 +1,137 @@ +/* + * Copyright 2010 Red Hat Inc. @@ -12593,9 +11679,9 @@ diff -Naur linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nv84_crypt.c linux-2.6.37-rc + + nv50_fb_vm_trap(dev, show, "PCRYPT"); +} -diff -Naur linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nvc0_instmem.c linux-2.6.37-rc2.nouveau/drivers/gpu/drm/nouveau/nvc0_instmem.c ---- linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nvc0_instmem.c 2010-11-16 03:31:02.000000000 +0100 -+++ linux-2.6.37-rc2.nouveau/drivers/gpu/drm/nouveau/nvc0_instmem.c 2010-11-20 14:43:51.000000000 +0100 +diff -Naur linux-2.6.37-rc3/drivers/gpu/drm/nouveau/nvc0_instmem.c linux-2.6.37-rc3.nouveau/drivers/gpu/drm/nouveau/nvc0_instmem.c +--- linux-2.6.37-rc3/drivers/gpu/drm/nouveau/nvc0_instmem.c 2010-11-22 00:18:56.000000000 +0100 ++++ linux-2.6.37-rc3.nouveau/drivers/gpu/drm/nouveau/nvc0_instmem.c 2010-11-22 06:33:32.000000000 +0100 @@ -26,67 +26,89 @@ #include "nouveau_drv.h" @@ -12768,9 +11854,9 @@ diff -Naur linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nvc0_instmem.c linux-2.6.37- } void -diff -Naur linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nvreg.h linux-2.6.37-rc2.nouveau/drivers/gpu/drm/nouveau/nvreg.h ---- linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nvreg.h 2010-11-16 03:31:02.000000000 +0100 -+++ linux-2.6.37-rc2.nouveau/drivers/gpu/drm/nouveau/nvreg.h 2010-11-20 14:43:51.000000000 +0100 +diff -Naur linux-2.6.37-rc3/drivers/gpu/drm/nouveau/nvreg.h linux-2.6.37-rc3.nouveau/drivers/gpu/drm/nouveau/nvreg.h +--- linux-2.6.37-rc3/drivers/gpu/drm/nouveau/nvreg.h 2010-11-22 00:18:56.000000000 +0100 ++++ linux-2.6.37-rc3.nouveau/drivers/gpu/drm/nouveau/nvreg.h 2010-11-22 06:33:32.000000000 +0100 @@ -153,7 +153,8 @@ #define NV_PCRTC_START 0x00600800 #define NV_PCRTC_CONFIG 0x00600804 @@ -12781,10 +11867,10 @@ diff -Naur linux-2.6.37-rc2/drivers/gpu/drm/nouveau/nvreg.h linux-2.6.37-rc2.nou #define NV_PCRTC_CURSOR_CONFIG 0x00600810 # define NV_PCRTC_CURSOR_CONFIG_ENABLE_ENABLE (1 << 0) # define NV_PCRTC_CURSOR_CONFIG_DOUBLE_SCAN_ENABLE (1 << 4) -diff -Naur linux-2.6.37-rc2/include/drm/nouveau_drm.h linux-2.6.37-rc2.nouveau/include/drm/nouveau_drm.h ---- linux-2.6.37-rc2/include/drm/nouveau_drm.h 2010-11-16 03:31:02.000000000 +0100 -+++ linux-2.6.37-rc2.nouveau/include/drm/nouveau_drm.h 2010-11-20 14:43:51.000000000 +0100 -@@ -71,15 +71,14 @@ +diff -Naur linux-2.6.37-rc3/include/drm/nouveau_drm.h linux-2.6.37-rc3.nouveau/include/drm/nouveau_drm.h +--- linux-2.6.37-rc3/include/drm/nouveau_drm.h 2010-11-22 00:18:56.000000000 +0100 ++++ linux-2.6.37-rc3.nouveau/include/drm/nouveau_drm.h 2010-11-22 06:33:32.000000000 +0100 +@@ -71,16 +71,15 @@ #define NOUVEAU_GETPARAM_PCI_VENDOR 3 #define NOUVEAU_GETPARAM_PCI_DEVICE 4 #define NOUVEAU_GETPARAM_BUS_TYPE 5 @@ -12797,25 +11883,13 @@ diff -Naur linux-2.6.37-rc2/include/drm/nouveau_drm.h linux-2.6.37-rc2.nouveau/i #define NOUVEAU_GETPARAM_VM_VRAM_BASE 12 #define NOUVEAU_GETPARAM_GRAPH_UNITS 13 #define NOUVEAU_GETPARAM_PTIMER_TIME 14 -+#define NOUVEAU_GETPARAM_HAS_BO_USAGE 15 + #define NOUVEAU_GETPARAM_HAS_BO_USAGE 15 +#define NOUVEAU_GETPARAM_HAS_PAGEFLIP 16 ++ struct drm_nouveau_getparam { uint64_t param; uint64_t value; -@@ -95,6 +94,12 @@ - #define NOUVEAU_GEM_DOMAIN_GART (1 << 2) - #define NOUVEAU_GEM_DOMAIN_MAPPABLE (1 << 3) - -+#define NOUVEAU_GEM_TILE_LAYOUT_MASK 0x0000ff00 -+#define NOUVEAU_GEM_TILE_16BPP 0x00000001 -+#define NOUVEAU_GEM_TILE_32BPP 0x00000002 -+#define NOUVEAU_GEM_TILE_ZETA 0x00000004 -+#define NOUVEAU_GEM_TILE_NONCONTIG 0x00000008 -+ - struct drm_nouveau_gem_info { - uint32_t handle; - uint32_t domain; -@@ -164,7 +169,6 @@ +@@ -171,7 +170,6 @@ }; #define NOUVEAU_GEM_CPU_PREP_NOWAIT 0x00000001 diff --git a/packages/linux/patches/linux-2.6.37-rc2-120_RFC-RFT-v3-sched-automated-per-tty-task-groups.patch b/packages/linux/patches/linux-2.6.37-rc3-120_RFC-RFT-v3-sched-automated-per-tty-task-groups.patch similarity index 100% rename from packages/linux/patches/linux-2.6.37-rc2-120_RFC-RFT-v3-sched-automated-per-tty-task-groups.patch rename to packages/linux/patches/linux-2.6.37-rc3-120_RFC-RFT-v3-sched-automated-per-tty-task-groups.patch diff --git a/packages/linux/patches/rename.sh b/packages/linux/patches/rename.sh new file mode 100755 index 0000000000..e78f4eb137 --- /dev/null +++ b/packages/linux/patches/rename.sh @@ -0,0 +1,5 @@ +#!/bin/sh + +for i in `ls linux-$1-*.patch`; do + mv $i `echo $i | sed "s,$1,$2,g"` +done