]> git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/blame - drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv50.c
drm/nouveau/devinit: convert to new-style nvkm_subdev
[mirror_ubuntu-bionic-kernel.git] / drivers / gpu / drm / nouveau / nvkm / subdev / fb / nv50.c
CommitLineData
861d2107
BS
1/*
2 * Copyright 2012 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 */
639c308e 24#include "nv50.h"
d36a99d2 25#include "ram.h"
861d2107 26
93260d3c 27#include <core/client.h>
639c308e 28#include <core/enum.h>
344c2d42 29#include <engine/fifo.h>
20f63afe 30
dceef5d8
BS
31int
32nv50_fb_memtype[0x80] = {
861d2107
BS
33 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
34 1, 1, 1, 1, 0, 0, 0, 0, 2, 2, 2, 2, 0, 0, 0, 0,
35 1, 1, 1, 1, 1, 1, 1, 0, 2, 2, 2, 2, 2, 2, 2, 0,
36 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
37 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 0, 0,
38 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0,
39 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 2, 2, 2, 2,
40 1, 0, 2, 0, 1, 0, 2, 0, 1, 1, 2, 2, 1, 1, 0, 0
41};
42
20cdeaf9 43bool
b1e4553c 44nv50_fb_memtype_valid(struct nvkm_fb *fb, u32 memtype)
8f7286f8 45{
dceef5d8 46 return nv50_fb_memtype[(memtype & 0xff00) >> 8] != 0;
861d2107
BS
47}
48
639c308e 49static const struct nvkm_enum vm_dispatch_subclients[] = {
344c2d42
BS
50 { 0x00000000, "GRCTX" },
51 { 0x00000001, "NOTIFY" },
52 { 0x00000002, "QUERY" },
53 { 0x00000003, "COND" },
54 { 0x00000004, "M2M_IN" },
55 { 0x00000005, "M2M_OUT" },
56 { 0x00000006, "M2M_NOTIFY" },
312d1d5f
BS
57 {}
58};
59
639c308e 60static const struct nvkm_enum vm_ccache_subclients[] = {
344c2d42
BS
61 { 0x00000000, "CB" },
62 { 0x00000001, "TIC" },
63 { 0x00000002, "TSC" },
312d1d5f
BS
64 {}
65};
66
639c308e 67static const struct nvkm_enum vm_prop_subclients[] = {
344c2d42
BS
68 { 0x00000000, "RT0" },
69 { 0x00000001, "RT1" },
70 { 0x00000002, "RT2" },
71 { 0x00000003, "RT3" },
72 { 0x00000004, "RT4" },
73 { 0x00000005, "RT5" },
74 { 0x00000006, "RT6" },
75 { 0x00000007, "RT7" },
76 { 0x00000008, "ZETA" },
77 { 0x00000009, "LOCAL" },
78 { 0x0000000a, "GLOBAL" },
79 { 0x0000000b, "STACK" },
80 { 0x0000000c, "DST2D" },
312d1d5f
BS
81 {}
82};
83
639c308e 84static const struct nvkm_enum vm_pfifo_subclients[] = {
344c2d42
BS
85 { 0x00000000, "PUSHBUF" },
86 { 0x00000001, "SEMAPHORE" },
312d1d5f
BS
87 {}
88};
89
639c308e 90static const struct nvkm_enum vm_bar_subclients[] = {
344c2d42
BS
91 { 0x00000000, "FB" },
92 { 0x00000001, "IN" },
312d1d5f
BS
93 {}
94};
95
639c308e 96static const struct nvkm_enum vm_client[] = {
344c2d42 97 { 0x00000000, "STRMOUT" },
312d1d5f 98 { 0x00000003, "DISPATCH", vm_dispatch_subclients },
344c2d42 99 { 0x00000004, "PFIFO_WRITE" },
312d1d5f 100 { 0x00000005, "CCACHE", vm_ccache_subclients },
344c2d42
BS
101 { 0x00000006, "PMSPPP" },
102 { 0x00000007, "CLIPID" },
103 { 0x00000008, "PFIFO_READ" },
104 { 0x00000009, "VFETCH" },
105 { 0x0000000a, "TEXTURE" },
312d1d5f 106 { 0x0000000b, "PROP", vm_prop_subclients },
344c2d42
BS
107 { 0x0000000c, "PVP" },
108 { 0x0000000d, "PBSP" },
109 { 0x0000000e, "PCRYPT" },
110 { 0x0000000f, "PCOUNTER" },
111 { 0x00000011, "PDAEMON" },
312d1d5f
BS
112 {}
113};
114
639c308e 115static const struct nvkm_enum vm_engine[] = {
344c2d42
BS
116 { 0x00000000, "PGRAPH" },
117 { 0x00000001, "PVP" },
118 { 0x00000004, "PEEPHOLE" },
119 { 0x00000005, "PFIFO", vm_pfifo_subclients },
312d1d5f 120 { 0x00000006, "BAR", vm_bar_subclients },
344c2d42
BS
121 { 0x00000008, "PMSPPP" },
122 { 0x00000008, "PMPEG" },
123 { 0x00000009, "PBSP" },
124 { 0x0000000a, "PCRYPT" },
125 { 0x0000000b, "PCOUNTER" },
126 { 0x0000000c, "SEMAPHORE_BG" },
127 { 0x0000000d, "PCE0" },
128 { 0x0000000e, "PDAEMON" },
312d1d5f
BS
129 {}
130};
131
639c308e 132static const struct nvkm_enum vm_fault[] = {
344c2d42
BS
133 { 0x00000000, "PT_NOT_PRESENT" },
134 { 0x00000001, "PT_TOO_SHORT" },
135 { 0x00000002, "PAGE_NOT_PRESENT" },
136 { 0x00000003, "PAGE_SYSTEM_ONLY" },
137 { 0x00000004, "PAGE_READ_ONLY" },
138 { 0x00000006, "NULL_DMAOBJ" },
139 { 0x00000007, "WRONG_MEMTYPE" },
140 { 0x0000000b, "VRAM_LIMIT" },
141 { 0x0000000f, "DMAOBJ_LIMIT" },
312d1d5f
BS
142 {}
143};
144
874309a5 145static void
639c308e 146nv50_fb_intr(struct nvkm_subdev *subdev)
d96773e7 147{
b1e4553c 148 struct nv50_fb *fb = (void *)subdev;
3ecd329b 149 struct nvkm_device *device = fb->base.subdev.device;
344c2d42
BS
150 struct nvkm_fifo *fifo = device->fifo;
151 struct nvkm_fifo_chan *chan;
3ecd329b 152 const struct nvkm_enum *en, *re, *cl, *sc;
344c2d42 153 u32 trap[6], idx, inst;
312d1d5f 154 u8 st0, st1, st2, st3;
344c2d42 155 unsigned long flags;
861d2107 156 int i;
d96773e7 157
6758745b 158 idx = nvkm_rd32(device, 0x100c90);
d96773e7
BS
159 if (!(idx & 0x80000000))
160 return;
161 idx &= 0x00ffffff;
162
163 for (i = 0; i < 6; i++) {
6758745b
BS
164 nvkm_wr32(device, 0x100c90, idx | i << 24);
165 trap[i] = nvkm_rd32(device, 0x100c94);
d96773e7 166 }
6758745b 167 nvkm_wr32(device, 0x100c90, idx | 0x80000000);
d96773e7 168
312d1d5f 169 /* decode status bits into something more useful */
861d2107
BS
170 if (device->chipset < 0xa3 ||
171 device->chipset == 0xaa || device->chipset == 0xac) {
312d1d5f
BS
172 st0 = (trap[0] & 0x0000000f) >> 0;
173 st1 = (trap[0] & 0x000000f0) >> 4;
174 st2 = (trap[0] & 0x00000f00) >> 8;
175 st3 = (trap[0] & 0x0000f000) >> 12;
176 } else {
177 st0 = (trap[0] & 0x000000ff) >> 0;
178 st1 = (trap[0] & 0x0000ff00) >> 8;
179 st2 = (trap[0] & 0x00ff0000) >> 16;
180 st3 = (trap[0] & 0xff000000) >> 24;
181 }
344c2d42 182 inst = ((trap[2] << 16) | trap[1]) << 12;
312d1d5f 183
639c308e 184 en = nvkm_enum_find(vm_engine, st0);
3ecd329b 185 re = nvkm_enum_find(vm_fault , st1);
639c308e 186 cl = nvkm_enum_find(vm_client, st2);
3ecd329b
BS
187 if (cl && cl->data) sc = nvkm_enum_find(cl->data, st3);
188 else if (en && en->data) sc = nvkm_enum_find(en->data, st3);
189 else sc = NULL;
312d1d5f 190
344c2d42 191 chan = nvkm_fifo_chan_inst(fifo, inst, &flags);
8f0649b5
BS
192 nvkm_error(subdev, "trapped %s at %02x%04x%04x on channel %d [%08x %s] "
193 "engine %02x [%s] client %02x [%s] "
3ecd329b
BS
194 "subclient %02x [%s] reason %08x [%s]\n",
195 (trap[5] & 0x00000100) ? "read" : "write",
8f0649b5
BS
196 trap[5] & 0xff, trap[4] & 0xffff, trap[3] & 0xffff,
197 chan ? chan->chid : -1, inst,
198 chan ? chan->object.client->name : "unknown",
199 st0, en ? en->name : "",
3ecd329b
BS
200 st2, cl ? cl->name : "", st3, sc ? sc->name : "",
201 st1, re ? re->name : "");
344c2d42 202 nvkm_fifo_chan_put(fifo, flags, &chan);
d96773e7 203}
874309a5 204
9ca3037e 205int
639c308e
BS
206nv50_fb_ctor(struct nvkm_object *parent, struct nvkm_object *engine,
207 struct nvkm_oclass *oclass, void *data, u32 size,
208 struct nvkm_object **pobject)
874309a5 209{
639c308e 210 struct nvkm_device *device = nv_device(parent);
b1e4553c 211 struct nv50_fb *fb;
874309a5
BS
212 int ret;
213
b1e4553c
BS
214 ret = nvkm_fb_create(parent, engine, oclass, &fb);
215 *pobject = nv_object(fb);
874309a5
BS
216 if (ret)
217 return ret;
218
b1e4553c
BS
219 fb->r100c08_page = alloc_page(GFP_KERNEL | __GFP_ZERO);
220 if (fb->r100c08_page) {
221 fb->r100c08 = dma_map_page(nv_device_base(device),
222 fb->r100c08_page, 0, PAGE_SIZE,
fd1496a0 223 DMA_BIDIRECTIONAL);
b1e4553c 224 if (dma_mapping_error(nv_device_base(device), fb->r100c08))
838f6fe7 225 return -EFAULT;
874309a5 226 } else {
3ecd329b 227 nvkm_warn(&fb->base.subdev, "failed 100c08 page alloc\n");
874309a5
BS
228 }
229
b1e4553c 230 nv_subdev(fb)->intr = nv50_fb_intr;
dceef5d8 231 return 0;
874309a5
BS
232}
233
9ca3037e 234void
639c308e 235nv50_fb_dtor(struct nvkm_object *object)
874309a5 236{
639c308e 237 struct nvkm_device *device = nv_device(object);
b1e4553c 238 struct nv50_fb *fb = (void *)object;
874309a5 239
b1e4553c
BS
240 if (fb->r100c08_page) {
241 dma_unmap_page(nv_device_base(device), fb->r100c08, PAGE_SIZE,
fd1496a0 242 DMA_BIDIRECTIONAL);
b1e4553c 243 __free_page(fb->r100c08_page);
874309a5
BS
244 }
245
b1e4553c 246 nvkm_fb_destroy(&fb->base);
874309a5
BS
247}
248
9ca3037e 249int
639c308e 250nv50_fb_init(struct nvkm_object *object)
874309a5 251{
9ca3037e 252 struct nv50_fb_impl *impl = (void *)object->oclass;
b1e4553c 253 struct nv50_fb *fb = (void *)object;
6758745b 254 struct nvkm_device *device = fb->base.subdev.device;
874309a5
BS
255 int ret;
256
b1e4553c 257 ret = nvkm_fb_init(&fb->base);
874309a5
BS
258 if (ret)
259 return ret;
260
261 /* Not a clue what this is exactly. Without pointing it at a
262 * scratch page, VRAM->GART blits with M2MF (as in DDX DFS)
263 * cause IOMMU "read from address 0" errors (rh#561267)
264 */
6758745b 265 nvkm_wr32(device, 0x100c08, fb->r100c08 >> 8);
874309a5
BS
266
267 /* This is needed to get meaningful information from 100c90
268 * on traps. No idea what these values mean exactly. */
6758745b 269 nvkm_wr32(device, 0x100c90, impl->trap);
874309a5
BS
270 return 0;
271}
272
639c308e 273struct nvkm_oclass *
9ca3037e 274nv50_fb_oclass = &(struct nv50_fb_impl) {
8613e731 275 .base.base.handle = NV_SUBDEV(FB, 0x50),
639c308e 276 .base.base.ofuncs = &(struct nvkm_ofuncs) {
874309a5
BS
277 .ctor = nv50_fb_ctor,
278 .dtor = nv50_fb_dtor,
279 .init = nv50_fb_init,
639c308e 280 .fini = _nvkm_fb_fini,
874309a5 281 },
20cdeaf9 282 .base.memtype = nv50_fb_memtype_valid,
d36a99d2 283 .base.ram_new = nv50_ram_new,
9ca3037e 284 .trap = 0x000707ff,
8613e731 285}.base.base;