18984e046153eb1d6b0b24626169f9c6e58232e1bBen Skeggs/* 28984e046153eb1d6b0b24626169f9c6e58232e1bBen Skeggs * Copyright 2010 Red Hat Inc. 38984e046153eb1d6b0b24626169f9c6e58232e1bBen Skeggs * 48984e046153eb1d6b0b24626169f9c6e58232e1bBen Skeggs * Permission is hereby granted, free of charge, to any person obtaining a 58984e046153eb1d6b0b24626169f9c6e58232e1bBen Skeggs * copy of this software and associated documentation files (the "Software"), 68984e046153eb1d6b0b24626169f9c6e58232e1bBen Skeggs * to deal in the Software without restriction, including without limitation 78984e046153eb1d6b0b24626169f9c6e58232e1bBen Skeggs * the rights to use, copy, modify, merge, publish, distribute, sublicense, 88984e046153eb1d6b0b24626169f9c6e58232e1bBen Skeggs * and/or sell copies of the Software, and to permit persons to whom the 98984e046153eb1d6b0b24626169f9c6e58232e1bBen Skeggs * Software is furnished to do so, subject to the following conditions: 108984e046153eb1d6b0b24626169f9c6e58232e1bBen Skeggs * 118984e046153eb1d6b0b24626169f9c6e58232e1bBen Skeggs * The above copyright notice and this permission notice shall be included in 128984e046153eb1d6b0b24626169f9c6e58232e1bBen Skeggs * all copies or substantial portions of the Software. 138984e046153eb1d6b0b24626169f9c6e58232e1bBen Skeggs * 148984e046153eb1d6b0b24626169f9c6e58232e1bBen Skeggs * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 158984e046153eb1d6b0b24626169f9c6e58232e1bBen Skeggs * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 168984e046153eb1d6b0b24626169f9c6e58232e1bBen Skeggs * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 178984e046153eb1d6b0b24626169f9c6e58232e1bBen Skeggs * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 188984e046153eb1d6b0b24626169f9c6e58232e1bBen Skeggs * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 198984e046153eb1d6b0b24626169f9c6e58232e1bBen Skeggs * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 208984e046153eb1d6b0b24626169f9c6e58232e1bBen Skeggs * OTHER DEALINGS IN THE SOFTWARE. 218984e046153eb1d6b0b24626169f9c6e58232e1bBen Skeggs * 228984e046153eb1d6b0b24626169f9c6e58232e1bBen Skeggs * Authors: Ben Skeggs 238984e046153eb1d6b0b24626169f9c6e58232e1bBen Skeggs */ 248984e046153eb1d6b0b24626169f9c6e58232e1bBen Skeggs 258984e046153eb1d6b0b24626169f9c6e58232e1bBen Skeggs#include "drmP.h" 268984e046153eb1d6b0b24626169f9c6e58232e1bBen Skeggs#include "nouveau_drv.h" 278984e046153eb1d6b0b24626169f9c6e58232e1bBen Skeggs#include "nouveau_mm.h" 288984e046153eb1d6b0b24626169f9c6e58232e1bBen Skeggs 29b5e2f0769a64046cefbfc307cbe6f7fa40dddf10Ben Skeggs/* 0 = unsupported 30b5e2f0769a64046cefbfc307cbe6f7fa40dddf10Ben Skeggs * 1 = non-compressed 31b5e2f0769a64046cefbfc307cbe6f7fa40dddf10Ben Skeggs * 3 = compressed 32b5e2f0769a64046cefbfc307cbe6f7fa40dddf10Ben Skeggs */ 33b5e2f0769a64046cefbfc307cbe6f7fa40dddf10Ben Skeggsstatic const u8 types[256] = { 34b5e2f0769a64046cefbfc307cbe6f7fa40dddf10Ben Skeggs 1, 1, 3, 3, 3, 3, 0, 3, 3, 3, 3, 0, 0, 0, 0, 0, 35b5e2f0769a64046cefbfc307cbe6f7fa40dddf10Ben Skeggs 0, 1, 0, 0, 0, 0, 0, 3, 3, 3, 3, 0, 0, 0, 0, 0, 36b5e2f0769a64046cefbfc307cbe6f7fa40dddf10Ben Skeggs 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 37b5e2f0769a64046cefbfc307cbe6f7fa40dddf10Ben Skeggs 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 3, 3, 3, 3, 3, 38b5e2f0769a64046cefbfc307cbe6f7fa40dddf10Ben Skeggs 3, 3, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 39b5e2f0769a64046cefbfc307cbe6f7fa40dddf10Ben Skeggs 0, 3, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 40b5e2f0769a64046cefbfc307cbe6f7fa40dddf10Ben Skeggs 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 41b5e2f0769a64046cefbfc307cbe6f7fa40dddf10Ben Skeggs 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 42b5e2f0769a64046cefbfc307cbe6f7fa40dddf10Ben Skeggs 0, 0, 0, 0, 0, 0, 3, 3, 3, 3, 0, 1, 1, 1, 1, 0, 43b5e2f0769a64046cefbfc307cbe6f7fa40dddf10Ben Skeggs 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 44b5e2f0769a64046cefbfc307cbe6f7fa40dddf10Ben Skeggs 0, 0, 0, 3, 3, 3, 3, 1, 1, 1, 1, 0, 0, 0, 0, 0, 45b5e2f0769a64046cefbfc307cbe6f7fa40dddf10Ben Skeggs 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 4612b6d9d881ccb64a833d53565a3579e12ab1d026Christoph Bumiller 3, 3, 3, 1, 0, 0, 0, 0, 0, 0, 0, 0, 3, 3, 3, 3, 47b5e2f0769a64046cefbfc307cbe6f7fa40dddf10Ben Skeggs 3, 3, 0, 0, 0, 0, 0, 0, 3, 0, 0, 3, 0, 3, 0, 3, 48b5e2f0769a64046cefbfc307cbe6f7fa40dddf10Ben Skeggs 3, 0, 3, 3, 3, 3, 3, 0, 0, 3, 0, 3, 0, 3, 3, 0, 49b5e2f0769a64046cefbfc307cbe6f7fa40dddf10Ben Skeggs 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 1, 1, 0 50b5e2f0769a64046cefbfc307cbe6f7fa40dddf10Ben Skeggs}; 51b5e2f0769a64046cefbfc307cbe6f7fa40dddf10Ben Skeggs 528984e046153eb1d6b0b24626169f9c6e58232e1bBen Skeggsbool 538984e046153eb1d6b0b24626169f9c6e58232e1bBen Skeggsnvc0_vram_flags_valid(struct drm_device *dev, u32 tile_flags) 548984e046153eb1d6b0b24626169f9c6e58232e1bBen Skeggs{ 55b5e2f0769a64046cefbfc307cbe6f7fa40dddf10Ben Skeggs u8 memtype = (tile_flags & NOUVEAU_GEM_TILE_LAYOUT_MASK) >> 8; 56b5e2f0769a64046cefbfc307cbe6f7fa40dddf10Ben Skeggs return likely((types[memtype] == 1)); 578984e046153eb1d6b0b24626169f9c6e58232e1bBen Skeggs} 588984e046153eb1d6b0b24626169f9c6e58232e1bBen Skeggs 598984e046153eb1d6b0b24626169f9c6e58232e1bBen Skeggsint 608984e046153eb1d6b0b24626169f9c6e58232e1bBen Skeggsnvc0_vram_new(struct drm_device *dev, u64 size, u32 align, u32 ncmin, 61d5f423947a11103c43ad26ebb680d049c2d8edd6Ben Skeggs u32 type, struct nouveau_mem **pmem) 628984e046153eb1d6b0b24626169f9c6e58232e1bBen Skeggs{ 638984e046153eb1d6b0b24626169f9c6e58232e1bBen Skeggs struct drm_nouveau_private *dev_priv = dev->dev_private; 64987eec10dd76624d0edacdc7ecc7e1a6fc877373Ben Skeggs struct nouveau_mm *mm = &dev_priv->engine.vram.mm; 658984e046153eb1d6b0b24626169f9c6e58232e1bBen Skeggs struct nouveau_mm_node *r; 66d5f423947a11103c43ad26ebb680d049c2d8edd6Ben Skeggs struct nouveau_mem *mem; 678984e046153eb1d6b0b24626169f9c6e58232e1bBen Skeggs int ret; 688984e046153eb1d6b0b24626169f9c6e58232e1bBen Skeggs 698984e046153eb1d6b0b24626169f9c6e58232e1bBen Skeggs size >>= 12; 708984e046153eb1d6b0b24626169f9c6e58232e1bBen Skeggs align >>= 12; 718984e046153eb1d6b0b24626169f9c6e58232e1bBen Skeggs ncmin >>= 12; 728984e046153eb1d6b0b24626169f9c6e58232e1bBen Skeggs 73d5f423947a11103c43ad26ebb680d049c2d8edd6Ben Skeggs mem = kzalloc(sizeof(*mem), GFP_KERNEL); 74d5f423947a11103c43ad26ebb680d049c2d8edd6Ben Skeggs if (!mem) 758984e046153eb1d6b0b24626169f9c6e58232e1bBen Skeggs return -ENOMEM; 768984e046153eb1d6b0b24626169f9c6e58232e1bBen Skeggs 77d5f423947a11103c43ad26ebb680d049c2d8edd6Ben Skeggs INIT_LIST_HEAD(&mem->regions); 78d5f423947a11103c43ad26ebb680d049c2d8edd6Ben Skeggs mem->dev = dev_priv->dev; 798f7286f8e4e80f7b868ba3d117ae900f0d207cbeBen Skeggs mem->memtype = (type & 0xff); 80d5f423947a11103c43ad26ebb680d049c2d8edd6Ben Skeggs mem->size = size; 818984e046153eb1d6b0b24626169f9c6e58232e1bBen Skeggs 828984e046153eb1d6b0b24626169f9c6e58232e1bBen Skeggs mutex_lock(&mm->mutex); 838984e046153eb1d6b0b24626169f9c6e58232e1bBen Skeggs do { 848984e046153eb1d6b0b24626169f9c6e58232e1bBen Skeggs ret = nouveau_mm_get(mm, 1, size, ncmin, align, &r); 858984e046153eb1d6b0b24626169f9c6e58232e1bBen Skeggs if (ret) { 868984e046153eb1d6b0b24626169f9c6e58232e1bBen Skeggs mutex_unlock(&mm->mutex); 87d5f423947a11103c43ad26ebb680d049c2d8edd6Ben Skeggs nv50_vram_del(dev, &mem); 888984e046153eb1d6b0b24626169f9c6e58232e1bBen Skeggs return ret; 898984e046153eb1d6b0b24626169f9c6e58232e1bBen Skeggs } 908984e046153eb1d6b0b24626169f9c6e58232e1bBen Skeggs 91d5f423947a11103c43ad26ebb680d049c2d8edd6Ben Skeggs list_add_tail(&r->rl_entry, &mem->regions); 928984e046153eb1d6b0b24626169f9c6e58232e1bBen Skeggs size -= r->length; 938984e046153eb1d6b0b24626169f9c6e58232e1bBen Skeggs } while (size); 948984e046153eb1d6b0b24626169f9c6e58232e1bBen Skeggs mutex_unlock(&mm->mutex); 958984e046153eb1d6b0b24626169f9c6e58232e1bBen Skeggs 96d5f423947a11103c43ad26ebb680d049c2d8edd6Ben Skeggs r = list_first_entry(&mem->regions, struct nouveau_mm_node, rl_entry); 97d5f423947a11103c43ad26ebb680d049c2d8edd6Ben Skeggs mem->offset = (u64)r->offset << 12; 98d5f423947a11103c43ad26ebb680d049c2d8edd6Ben Skeggs *pmem = mem; 998984e046153eb1d6b0b24626169f9c6e58232e1bBen Skeggs return 0; 1008984e046153eb1d6b0b24626169f9c6e58232e1bBen Skeggs} 1018984e046153eb1d6b0b24626169f9c6e58232e1bBen Skeggs 1028984e046153eb1d6b0b24626169f9c6e58232e1bBen Skeggsint 1038984e046153eb1d6b0b24626169f9c6e58232e1bBen Skeggsnvc0_vram_init(struct drm_device *dev) 1048984e046153eb1d6b0b24626169f9c6e58232e1bBen Skeggs{ 1058984e046153eb1d6b0b24626169f9c6e58232e1bBen Skeggs struct drm_nouveau_private *dev_priv = dev->dev_private; 10624f246ac10ae6a6ae873045387d4501498869f74Ben Skeggs struct nouveau_vram_engine *vram = &dev_priv->engine.vram; 10724f246ac10ae6a6ae873045387d4501498869f74Ben Skeggs const u32 rsvd_head = ( 256 * 1024) >> 12; /* vga memory */ 10824f246ac10ae6a6ae873045387d4501498869f74Ben Skeggs const u32 rsvd_tail = (1024 * 1024) >> 12; /* vbios etc */ 10929181d2f7bec0f51273ceab8c565410d52ef1eb0Ben Skeggs u32 parts = nv_rd32(dev, 0x022438); 11029181d2f7bec0f51273ceab8c565410d52ef1eb0Ben Skeggs u32 pmask = nv_rd32(dev, 0x022554); 111aa6500964c0e5c08e453439a95431ec34b548427Ben Skeggs u32 bsize = nv_rd32(dev, 0x10f20c); 112aa6500964c0e5c08e453439a95431ec34b548427Ben Skeggs u32 offset, length; 113aa6500964c0e5c08e453439a95431ec34b548427Ben Skeggs bool uniform = true; 114d4547ed8cc219f2e06078ac05147a873b2a03d5aBen Skeggs int ret, part; 1158984e046153eb1d6b0b24626169f9c6e58232e1bBen Skeggs 116aa6500964c0e5c08e453439a95431ec34b548427Ben Skeggs NV_DEBUG(dev, "0x100800: 0x%08x\n", nv_rd32(dev, 0x100800)); 11729181d2f7bec0f51273ceab8c565410d52ef1eb0Ben Skeggs NV_DEBUG(dev, "parts 0x%08x mask 0x%08x\n", parts, pmask); 11824f246ac10ae6a6ae873045387d4501498869f74Ben Skeggs 119f3298532f71f163877b9003009d6e1eefe988258Ben Skeggs dev_priv->vram_type = nouveau_mem_vbios_type(dev); 120950c44b6ddc0dfb44e59fdb031e09567a1b391c0Ben Skeggs dev_priv->vram_rank_B = !!(nv_rd32(dev, 0x10f200) & 0x00000004); 121f3298532f71f163877b9003009d6e1eefe988258Ben Skeggs 122aa6500964c0e5c08e453439a95431ec34b548427Ben Skeggs /* read amount of vram attached to each memory controller */ 12329181d2f7bec0f51273ceab8c565410d52ef1eb0Ben Skeggs for (part = 0; part < parts; part++) { 12429181d2f7bec0f51273ceab8c565410d52ef1eb0Ben Skeggs if (!(pmask & (1 << part))) { 12529181d2f7bec0f51273ceab8c565410d52ef1eb0Ben Skeggs u32 psize = nv_rd32(dev, 0x11020c + (part * 0x1000)); 12629181d2f7bec0f51273ceab8c565410d52ef1eb0Ben Skeggs if (psize != bsize) { 12729181d2f7bec0f51273ceab8c565410d52ef1eb0Ben Skeggs if (psize < bsize) 12829181d2f7bec0f51273ceab8c565410d52ef1eb0Ben Skeggs bsize = psize; 12929181d2f7bec0f51273ceab8c565410d52ef1eb0Ben Skeggs uniform = false; 13029181d2f7bec0f51273ceab8c565410d52ef1eb0Ben Skeggs } 13129181d2f7bec0f51273ceab8c565410d52ef1eb0Ben Skeggs 13229181d2f7bec0f51273ceab8c565410d52ef1eb0Ben Skeggs NV_DEBUG(dev, "%d: mem_amount 0x%08x\n", part, psize); 13329181d2f7bec0f51273ceab8c565410d52ef1eb0Ben Skeggs dev_priv->vram_size += (u64)psize << 20; 134aa6500964c0e5c08e453439a95431ec34b548427Ben Skeggs } 135aa6500964c0e5c08e453439a95431ec34b548427Ben Skeggs } 136aa6500964c0e5c08e453439a95431ec34b548427Ben Skeggs 137aa6500964c0e5c08e453439a95431ec34b548427Ben Skeggs /* if all controllers have the same amount attached, there's no holes */ 138aa6500964c0e5c08e453439a95431ec34b548427Ben Skeggs if (uniform) { 139aa6500964c0e5c08e453439a95431ec34b548427Ben Skeggs offset = rsvd_head; 140aa6500964c0e5c08e453439a95431ec34b548427Ben Skeggs length = (dev_priv->vram_size >> 12) - rsvd_head - rsvd_tail; 141aa6500964c0e5c08e453439a95431ec34b548427Ben Skeggs return nouveau_mm_init(&vram->mm, offset, length, 1); 142aa6500964c0e5c08e453439a95431ec34b548427Ben Skeggs } 14324f246ac10ae6a6ae873045387d4501498869f74Ben Skeggs 144aa6500964c0e5c08e453439a95431ec34b548427Ben Skeggs /* otherwise, address lowest common amount from 0GiB */ 145aa6500964c0e5c08e453439a95431ec34b548427Ben Skeggs ret = nouveau_mm_init(&vram->mm, rsvd_head, (bsize << 8) * parts, 1); 146aa6500964c0e5c08e453439a95431ec34b548427Ben Skeggs if (ret) 147aa6500964c0e5c08e453439a95431ec34b548427Ben Skeggs return ret; 148aa6500964c0e5c08e453439a95431ec34b548427Ben Skeggs 149aa6500964c0e5c08e453439a95431ec34b548427Ben Skeggs /* and the rest starting from (8GiB + common_size) */ 150aa6500964c0e5c08e453439a95431ec34b548427Ben Skeggs offset = (0x0200000000ULL >> 12) + (bsize << 8); 151aa6500964c0e5c08e453439a95431ec34b548427Ben Skeggs length = (dev_priv->vram_size >> 12) - (bsize << 8) - rsvd_tail; 152aa6500964c0e5c08e453439a95431ec34b548427Ben Skeggs 153aa6500964c0e5c08e453439a95431ec34b548427Ben Skeggs ret = nouveau_mm_init(&vram->mm, offset, length, 0); 154aa6500964c0e5c08e453439a95431ec34b548427Ben Skeggs if (ret) { 155aa6500964c0e5c08e453439a95431ec34b548427Ben Skeggs nouveau_mm_fini(&vram->mm); 156aa6500964c0e5c08e453439a95431ec34b548427Ben Skeggs return ret; 157aa6500964c0e5c08e453439a95431ec34b548427Ben Skeggs } 158aa6500964c0e5c08e453439a95431ec34b548427Ben Skeggs 159aa6500964c0e5c08e453439a95431ec34b548427Ben Skeggs return 0; 1608984e046153eb1d6b0b24626169f9c6e58232e1bBen Skeggs} 161