Merge branch 'upstream-linus' of git://github.com/jgarzik/libata-dev
[deliverable/linux.git] / drivers / gpu / drm / nouveau / nvc0_vram.c
CommitLineData
8984e046
BS
1/*
2 * Copyright 2010 Red Hat Inc.
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 * OTHER DEALINGS IN THE SOFTWARE.
21 *
22 * Authors: Ben Skeggs
23 */
24
25#include "drmP.h"
26#include "nouveau_drv.h"
27#include "nouveau_mm.h"
28
b5e2f076
BS
29/* 0 = unsupported
30 * 1 = non-compressed
31 * 3 = compressed
32 */
33static const u8 types[256] = {
34 1, 1, 3, 3, 3, 3, 0, 3, 3, 3, 3, 0, 0, 0, 0, 0,
35 0, 1, 0, 0, 0, 0, 0, 3, 3, 3, 3, 0, 0, 0, 0, 0,
36 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0,
37 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 3, 3, 3, 3, 3,
38 3, 3, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0,
39 0, 3, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
40 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
41 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0,
42 0, 0, 0, 0, 0, 0, 3, 3, 3, 3, 0, 1, 1, 1, 1, 0,
43 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
44 0, 0, 0, 3, 3, 3, 3, 1, 1, 1, 1, 0, 0, 0, 0, 0,
45 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3,
12b6d9d8 46 3, 3, 3, 1, 0, 0, 0, 0, 0, 0, 0, 0, 3, 3, 3, 3,
b5e2f076
BS
47 3, 3, 0, 0, 0, 0, 0, 0, 3, 0, 0, 3, 0, 3, 0, 3,
48 3, 0, 3, 3, 3, 3, 3, 0, 0, 3, 0, 3, 0, 3, 3, 0,
49 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 1, 1, 0
50};
51
8984e046
BS
52bool
53nvc0_vram_flags_valid(struct drm_device *dev, u32 tile_flags)
54{
b5e2f076
BS
55 u8 memtype = (tile_flags & NOUVEAU_GEM_TILE_LAYOUT_MASK) >> 8;
56 return likely((types[memtype] == 1));
8984e046
BS
57}
58
59int
60nvc0_vram_new(struct drm_device *dev, u64 size, u32 align, u32 ncmin,
d5f42394 61 u32 type, struct nouveau_mem **pmem)
8984e046
BS
62{
63 struct drm_nouveau_private *dev_priv = dev->dev_private;
987eec10 64 struct nouveau_mm *mm = &dev_priv->engine.vram.mm;
8984e046 65 struct nouveau_mm_node *r;
d5f42394 66 struct nouveau_mem *mem;
8984e046
BS
67 int ret;
68
69 size >>= 12;
70 align >>= 12;
71 ncmin >>= 12;
72
d5f42394
BS
73 mem = kzalloc(sizeof(*mem), GFP_KERNEL);
74 if (!mem)
8984e046
BS
75 return -ENOMEM;
76
d5f42394
BS
77 INIT_LIST_HEAD(&mem->regions);
78 mem->dev = dev_priv->dev;
8f7286f8 79 mem->memtype = (type & 0xff);
d5f42394 80 mem->size = size;
8984e046
BS
81
82 mutex_lock(&mm->mutex);
83 do {
84 ret = nouveau_mm_get(mm, 1, size, ncmin, align, &r);
85 if (ret) {
86 mutex_unlock(&mm->mutex);
d5f42394 87 nv50_vram_del(dev, &mem);
8984e046
BS
88 return ret;
89 }
90
d5f42394 91 list_add_tail(&r->rl_entry, &mem->regions);
8984e046
BS
92 size -= r->length;
93 } while (size);
94 mutex_unlock(&mm->mutex);
95
d5f42394
BS
96 r = list_first_entry(&mem->regions, struct nouveau_mm_node, rl_entry);
97 mem->offset = (u64)r->offset << 12;
98 *pmem = mem;
8984e046
BS
99 return 0;
100}
101
102int
103nvc0_vram_init(struct drm_device *dev)
104{
105 struct drm_nouveau_private *dev_priv = dev->dev_private;
24f246ac
BS
106 struct nouveau_vram_engine *vram = &dev_priv->engine.vram;
107 const u32 rsvd_head = ( 256 * 1024) >> 12; /* vga memory */
108 const u32 rsvd_tail = (1024 * 1024) >> 12; /* vbios etc */
aa650096
BS
109 u32 parts = nv_rd32(dev, 0x121c74);
110 u32 bsize = nv_rd32(dev, 0x10f20c);
111 u32 offset, length;
112 bool uniform = true;
d4547ed8 113 int ret, part;
8984e046 114
aa650096
BS
115 NV_DEBUG(dev, "0x100800: 0x%08x\n", nv_rd32(dev, 0x100800));
116 NV_DEBUG(dev, "parts 0x%08x bcast_mem_amount 0x%08x\n", parts, bsize);
24f246ac 117
aa650096 118 /* read amount of vram attached to each memory controller */
d4547ed8
BS
119 part = 0;
120 while (parts) {
121 u32 psize = nv_rd32(dev, 0x11020c + (part++ * 0x1000));
122 if (psize == 0)
123 continue;
124 parts--;
125
aa650096
BS
126 if (psize != bsize) {
127 if (psize < bsize)
128 bsize = psize;
129 uniform = false;
130 }
131
d4547ed8 132 NV_DEBUG(dev, "%d: mem_amount 0x%08x\n", part, psize);
aa650096
BS
133 dev_priv->vram_size += (u64)psize << 20;
134 }
135
136 /* if all controllers have the same amount attached, there's no holes */
137 if (uniform) {
138 offset = rsvd_head;
139 length = (dev_priv->vram_size >> 12) - rsvd_head - rsvd_tail;
140 return nouveau_mm_init(&vram->mm, offset, length, 1);
141 }
24f246ac 142
aa650096
BS
143 /* otherwise, address lowest common amount from 0GiB */
144 ret = nouveau_mm_init(&vram->mm, rsvd_head, (bsize << 8) * parts, 1);
145 if (ret)
146 return ret;
147
148 /* and the rest starting from (8GiB + common_size) */
149 offset = (0x0200000000ULL >> 12) + (bsize << 8);
150 length = (dev_priv->vram_size >> 12) - (bsize << 8) - rsvd_tail;
151
152 ret = nouveau_mm_init(&vram->mm, offset, length, 0);
153 if (ret) {
154 nouveau_mm_fini(&vram->mm);
155 return ret;
156 }
157
158 return 0;
8984e046 159}
This page took 0.095022 seconds and 5 git commands to generate.