nouveau_mem.c 13.5 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37
/*
 * Copyright (C) The Weather Channel, Inc.  2002.  All Rights Reserved.
 * Copyright 2005 Stephane Marchesin
 *
 * The Weather Channel (TM) funded Tungsten Graphics to develop the
 * initial release of the Radeon 8500 driver under the XFree86 license.
 * This notice must be preserved.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice (including the next
 * paragraph) shall be included in all copies or substantial portions of the
 * Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
 * THE AUTHORS AND/OR THEIR 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:
 *    Keith Whitwell <keith@tungstengraphics.com>
 */


#include "drmP.h"
#include "drm.h"
#include "drm_sarea.h"
#include "nouveau_drv.h"

38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123
/*
 * 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)
{
	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];

	tile->addr = addr;
	tile->size = size;
	tile->used = !!pitch;
	nouveau_fence_unref((void **)&tile->fence);

	if (!pfifo->cache_flush(dev))
		return;

	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);

	pfifo->cache_pull(dev, true);
	pfifo->reassign(dev, true);
}

struct nouveau_tile_reg *
nv10_mem_set_tiling(struct drm_device *dev, uint32_t addr, uint32_t size,
		    uint32_t pitch)
{
	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;

	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[i].fence &&
		    !nouveau_fence_signalled(tile[i].fence, NULL))
			/* Pending tile region. */
			continue;

		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);

		if (pitch && !found) {
			/* Free tile region. */
			nv10_mem_set_region_tiling(dev, i, addr, size, pitch);
			found = &tile[i];
		}
	}

	spin_unlock(&dev_priv->tile.lock);

	return found;
}

void
nv10_mem_expire_tiling(struct drm_device *dev, struct nouveau_tile_reg *tile,
		       struct nouveau_fence *fence)
{
	if (fence) {
		/* Mark it as pending. */
		tile->fence = fence;
		nouveau_fence_ref(fence);
	}

	tile->used = false;
}

124 125 126 127 128 129 130 131
/*
 * NV50 VM helpers
 */
int
nv50_mem_vm_bind_linear(struct drm_device *dev, uint64_t virt, uint32_t size,
			uint32_t flags, uint64_t phys)
{
	struct drm_nouveau_private *dev_priv = dev->dev_private;
132 133 134
	struct nouveau_gpuobj *pgt;
	unsigned block;
	int i;
135

136 137
	virt = ((virt - dev_priv->vm_vram_base) >> 16) << 1;
	size = (size >> 16) << 1;
138 139 140 141 142 143 144

	phys |= ((uint64_t)flags << 32);
	phys |= 1;
	if (dev_priv->vram_sys_base) {
		phys += dev_priv->vram_sys_base;
		phys |= 0x30;
	}
145

146 147
	while (size) {
		unsigned offset_h = upper_32_bits(phys);
148
		unsigned offset_l = lower_32_bits(phys);
149 150 151 152 153 154 155 156
		unsigned pte, end;

		for (i = 7; i >= 0; i--) {
			block = 1 << (i + 1);
			if (size >= block && !(virt & (block - 1)))
				break;
		}
		offset_l |= (i << 7);
157

158 159
		phys += block << 15;
		size -= block;
160

161 162 163 164 165 166 167 168 169 170 171
		while (block) {
			pgt = dev_priv->vm_vram_pt[virt >> 14];
			pte = virt & 0x3ffe;

			end = pte + block;
			if (end > 16384)
				end = 16384;
			block -= (end - pte);
			virt  += (end - pte);

			while (pte < end) {
172 173 174
				nv_wo32(pgt, (pte * 4) + 0, offset_l);
				nv_wo32(pgt, (pte * 4) + 4, offset_h);
				pte += 2;
175 176
			}
		}
177
	}
178
	dev_priv->engine.instmem.flush(dev);
179

180 181 182 183
	nv50_vm_flush(dev, 5);
	nv50_vm_flush(dev, 0);
	nv50_vm_flush(dev, 4);
	nv50_vm_flush(dev, 6);
184 185 186 187 188 189
	return 0;
}

void
nv50_mem_vm_unbind(struct drm_device *dev, uint64_t virt, uint32_t size)
{
190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206
	struct drm_nouveau_private *dev_priv = dev->dev_private;
	struct nouveau_gpuobj *pgt;
	unsigned pages, pte, end;

	virt -= dev_priv->vm_vram_base;
	pages = (size >> 16) << 1;

	while (pages) {
		pgt = dev_priv->vm_vram_pt[virt >> 29];
		pte = (virt & 0x1ffe0000ULL) >> 15;

		end = pte + pages;
		if (end > 16384)
			end = 16384;
		pages -= (end - pte);
		virt  += (end - pte) << 15;

207 208 209 210
		while (pte < end) {
			nv_wo32(pgt, (pte * 4), 0);
			pte++;
		}
211
	}
212
	dev_priv->engine.instmem.flush(dev);
213

214 215 216 217
	nv50_vm_flush(dev, 5);
	nv50_vm_flush(dev, 0);
	nv50_vm_flush(dev, 4);
	nv50_vm_flush(dev, 6);
218 219 220 221 222
}

/*
 * Cleanup everything
 */
223 224
void
nouveau_mem_close(struct drm_device *dev)
225 226 227
{
	struct drm_nouveau_private *dev_priv = dev->dev_private;

228 229 230
	nouveau_bo_unpin(dev_priv->vga_ram);
	nouveau_bo_ref(NULL, &dev_priv->vga_ram);

231 232 233 234
	ttm_bo_device_release(&dev_priv->ttm.bdev);

	nouveau_ttm_global_release(dev_priv);

235
	if (drm_core_has_AGP(dev) && dev->agp) {
236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255
		struct drm_agp_mem *entry, *tempe;

		/* Remove AGP resources, but leave dev->agp
		   intact until drv_cleanup is called. */
		list_for_each_entry_safe(entry, tempe, &dev->agp->memory, head) {
			if (entry->bound)
				drm_unbind_agp(entry->memory);
			drm_free_agp(entry->memory, entry->pages);
			kfree(entry);
		}
		INIT_LIST_HEAD(&dev->agp->memory);

		if (dev->agp->acquired)
			drm_agp_release(dev);

		dev->agp->acquired = 0;
		dev->agp->enabled = 0;
	}

	if (dev_priv->fb_mtrr) {
256 257 258
		drm_mtrr_del(dev_priv->fb_mtrr,
			     pci_resource_start(dev->pdev, 1),
			     pci_resource_len(dev->pdev, 1), DRM_MTRR_WC);
B
Ben Skeggs 已提交
259
		dev_priv->fb_mtrr = -1;
260 261 262 263
	}
}

static uint32_t
264 265
nouveau_mem_detect_nv04(struct drm_device *dev)
{
266
	uint32_t boot0 = nv_rd32(dev, NV04_PFB_BOOT_0);
267 268 269 270

	if (boot0 & 0x00000100)
		return (((boot0 >> 12) & 0xf) * 2 + 2) * 1024 * 1024;

271 272
	switch (boot0 & NV04_PFB_BOOT_0_RAM_AMOUNT) {
	case NV04_PFB_BOOT_0_RAM_AMOUNT_32MB:
273
		return 32 * 1024 * 1024;
274
	case NV04_PFB_BOOT_0_RAM_AMOUNT_16MB:
275
		return 16 * 1024 * 1024;
276
	case NV04_PFB_BOOT_0_RAM_AMOUNT_8MB:
277
		return 8 * 1024 * 1024;
278
	case NV04_PFB_BOOT_0_RAM_AMOUNT_4MB:
279 280 281 282 283 284 285 286
		return 4 * 1024 * 1024;
	}

	return 0;
}

static uint32_t
nouveau_mem_detect_nforce(struct drm_device *dev)
287 288 289 290 291 292 293 294 295 296 297
{
	struct drm_nouveau_private *dev_priv = dev->dev_private;
	struct pci_dev *bridge;
	uint32_t mem;

	bridge = pci_get_bus_and_slot(0, PCI_DEVFN(0, 1));
	if (!bridge) {
		NV_ERROR(dev, "no bridge device\n");
		return 0;
	}

298
	if (dev_priv->flags & NV_NFORCE) {
299 300 301
		pci_read_config_dword(bridge, 0x7C, &mem);
		return (uint64_t)(((mem >> 6) & 31) + 1)*1024*1024;
	} else
302
	if (dev_priv->flags & NV_NFORCE2) {
303 304 305 306 307 308 309 310 311
		pci_read_config_dword(bridge, 0x84, &mem);
		return (uint64_t)(((mem >> 4) & 127) + 1)*1024*1024;
	}

	NV_ERROR(dev, "impossible!\n");
	return 0;
}

/* returns the amount of FB ram in bytes */
312 313
int
nouveau_mem_detect(struct drm_device *dev)
314 315
{
	struct drm_nouveau_private *dev_priv = dev->dev_private;
316 317 318 319 320 321

	if (dev_priv->card_type == NV_04) {
		dev_priv->vram_size = nouveau_mem_detect_nv04(dev);
	} else
	if (dev_priv->flags & (NV_NFORCE | NV_NFORCE2)) {
		dev_priv->vram_size = nouveau_mem_detect_nforce(dev);
322 323
	} else
	if (dev_priv->card_type < NV_50) {
324 325
		dev_priv->vram_size  = nv_rd32(dev, NV04_PFB_FIFO_DATA);
		dev_priv->vram_size &= NV10_PFB_FIFO_DATA_RAM_AMOUNT_MB_MASK;
326 327
	} else
	if (dev_priv->card_type < NV_C0) {
328
		dev_priv->vram_size = nv_rd32(dev, NV04_PFB_FIFO_DATA);
329
		dev_priv->vram_size |= (dev_priv->vram_size & 0xff) << 32;
330
		dev_priv->vram_size &= 0xffffffff00ll;
B
Ben Skeggs 已提交
331
		if (dev_priv->chipset == 0xaa || dev_priv->chipset == 0xac) {
332 333
			dev_priv->vram_sys_base = nv_rd32(dev, 0x100e10);
			dev_priv->vram_sys_base <<= 12;
B
Ben Skeggs 已提交
334
		}
335 336 337
	} else {
		dev_priv->vram_size  = nv_rd32(dev, 0x10f20c) << 20;
		dev_priv->vram_size *= nv_rd32(dev, 0x121c74);
338 339
	}

340 341 342 343 344 345 346 347 348
	NV_INFO(dev, "Detected %dMiB VRAM\n", (int)(dev_priv->vram_size >> 20));
	if (dev_priv->vram_sys_base) {
		NV_INFO(dev, "Stolen system memory at: 0x%010llx\n",
			dev_priv->vram_sys_base);
	}

	if (dev_priv->vram_size)
		return 0;
	return -ENOMEM;
349 350
}

351 352
int
nouveau_mem_reset_agp(struct drm_device *dev)
353
{
354 355 356 357 358 359 360
#if __OS_HAS_AGP
	uint32_t saved_pci_nv_1, pmc_enable;
	int ret;

	/* First of all, disable fast writes, otherwise if it's
	 * already enabled in the AGP bridge and we disable the card's
	 * AGP controller we might be locking ourselves out of it. */
361 362
	if ((nv_rd32(dev, NV04_PBUS_PCI_NV_19) |
	     dev->agp->mode) & PCI_AGP_COMMAND_FW) {
363 364 365 366 367 368 369
		struct drm_agp_info info;
		struct drm_agp_mode mode;

		ret = drm_agp_info(dev, &info);
		if (ret)
			return ret;

370
		mode.mode = info.mode & ~PCI_AGP_COMMAND_FW;
371 372 373 374
		ret = drm_agp_enable(dev, mode);
		if (ret)
			return ret;
	}
375 376 377 378 379

	saved_pci_nv_1 = nv_rd32(dev, NV04_PBUS_PCI_NV_1);

	/* clear busmaster bit */
	nv_wr32(dev, NV04_PBUS_PCI_NV_1, saved_pci_nv_1 & ~0x4);
380 381
	/* disable AGP */
	nv_wr32(dev, NV04_PBUS_PCI_NV_19, 0);
382 383 384 385 386 387 388 389 390 391 392 393

	/* power cycle pgraph, if enabled */
	pmc_enable = nv_rd32(dev, NV03_PMC_ENABLE);
	if (pmc_enable & NV_PMC_ENABLE_PGRAPH) {
		nv_wr32(dev, NV03_PMC_ENABLE,
				pmc_enable & ~NV_PMC_ENABLE_PGRAPH);
		nv_wr32(dev, NV03_PMC_ENABLE, nv_rd32(dev, NV03_PMC_ENABLE) |
				NV_PMC_ENABLE_PGRAPH);
	}

	/* and restore (gives effect of resetting AGP) */
	nv_wr32(dev, NV04_PBUS_PCI_NV_1, saved_pci_nv_1);
394
#endif
395

396 397 398
	return 0;
}

399 400 401
int
nouveau_mem_init_agp(struct drm_device *dev)
{
402
#if __OS_HAS_AGP
403 404 405 406 407 408 409 410 411 412 413 414 415
	struct drm_nouveau_private *dev_priv = dev->dev_private;
	struct drm_agp_info info;
	struct drm_agp_mode mode;
	int ret;

	if (!dev->agp->acquired) {
		ret = drm_agp_acquire(dev);
		if (ret) {
			NV_ERROR(dev, "Unable to acquire AGP: %d\n", ret);
			return ret;
		}
	}

416 417
	nouveau_mem_reset_agp(dev);

418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434
	ret = drm_agp_info(dev, &info);
	if (ret) {
		NV_ERROR(dev, "Unable to get AGP info: %d\n", ret);
		return ret;
	}

	/* see agp.h for the AGPSTAT_* modes available */
	mode.mode = info.mode;
	ret = drm_agp_enable(dev, mode);
	if (ret) {
		NV_ERROR(dev, "Unable to enable AGP: %d\n", ret);
		return ret;
	}

	dev_priv->gart_info.type	= NOUVEAU_GART_AGP;
	dev_priv->gart_info.aper_base	= info.aperture_base;
	dev_priv->gart_info.aper_size	= info.aperture_size;
435
#endif
436 437 438 439 440 441 442 443 444 445
	return 0;
}

int
nouveau_mem_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;

446
	dev_priv->fb_phys = pci_resource_start(dev->pdev, 1);
447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471
	dev_priv->gart_info.type = NOUVEAU_GART_NONE;

	if (dev_priv->card_type >= NV_50 &&
	    pci_dma_supported(dev->pdev, DMA_BIT_MASK(40)))
		dma_bits = 40;

	ret = pci_set_dma_mask(dev->pdev, DMA_BIT_MASK(dma_bits));
	if (ret) {
		NV_ERROR(dev, "Error setting DMA mask: %d\n", ret);
		return ret;
	}

	ret = nouveau_ttm_global_init(dev_priv);
	if (ret)
		return ret;

	ret = ttm_bo_device_init(&dev_priv->ttm.bdev,
				 dev_priv->ttm.bo_global_ref.ref.object,
				 &nouveau_bo_driver, DRM_FILE_PAGE_OFFSET,
				 dma_bits <= 32 ? true : false);
	if (ret) {
		NV_ERROR(dev, "Error initialising bo driver: %d\n", ret);
		return ret;
	}

472
	spin_lock_init(&dev_priv->tile.lock);
473

474
	dev_priv->fb_available_size = dev_priv->vram_size;
475
	dev_priv->fb_mappable_pages = dev_priv->fb_available_size;
476 477 478
	if (dev_priv->fb_mappable_pages > pci_resource_len(dev->pdev, 1))
		dev_priv->fb_mappable_pages =
			pci_resource_len(dev->pdev, 1);
479 480 481 482 483 484 485 486 487 488 489 490 491 492
	dev_priv->fb_mappable_pages >>= PAGE_SHIFT;

	/* remove reserved space at end of vram from available amount */
	dev_priv->fb_available_size -= dev_priv->ramin_rsvd_vram;
	dev_priv->fb_aper_free = dev_priv->fb_available_size;

	/* mappable vram */
	ret = ttm_bo_init_mm(bdev, TTM_PL_VRAM,
			     dev_priv->fb_available_size >> PAGE_SHIFT);
	if (ret) {
		NV_ERROR(dev, "Failed VRAM mm init: %d\n", ret);
		return ret;
	}

493 494 495 496 497 498 499 500 501
	ret = nouveau_bo_new(dev, NULL, 256*1024, 0, TTM_PL_FLAG_VRAM,
			     0, 0, true, true, &dev_priv->vga_ram);
	if (ret == 0)
		ret = nouveau_bo_pin(dev_priv->vga_ram, TTM_PL_FLAG_VRAM);
	if (ret) {
		NV_WARN(dev, "failed to reserve VGA memory\n");
		nouveau_bo_ref(NULL, &dev_priv->vga_ram);
	}

502 503
	/* GART */
#if !defined(__powerpc__) && !defined(__ia64__)
504
	if (drm_device_is_agp(dev) && dev->agp && !nouveau_noagp) {
505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529
		ret = nouveau_mem_init_agp(dev);
		if (ret)
			NV_ERROR(dev, "Error initialising AGP: %d\n", ret);
	}
#endif

	if (dev_priv->gart_info.type == NOUVEAU_GART_NONE) {
		ret = nouveau_sgdma_init(dev);
		if (ret) {
			NV_ERROR(dev, "Error initialising PCI(E): %d\n", ret);
			return ret;
		}
	}

	NV_INFO(dev, "%d MiB GART (aperture)\n",
		(int)(dev_priv->gart_info.aper_size >> 20));
	dev_priv->gart_info.aper_free = dev_priv->gart_info.aper_size;

	ret = ttm_bo_init_mm(bdev, TTM_PL_TT,
			     dev_priv->gart_info.aper_size >> PAGE_SHIFT);
	if (ret) {
		NV_ERROR(dev, "Failed TT mm init: %d\n", ret);
		return ret;
	}

530 531
	dev_priv->fb_mtrr = drm_mtrr_add(pci_resource_start(dev->pdev, 1),
					 pci_resource_len(dev->pdev, 1),
532
					 DRM_MTRR_WC);
533

534 535 536 537
	return 0;
}