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