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