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