diff options
author | Ben Skeggs <bskeggs@redhat.com> | 2013-10-14 20:49:39 -0400 |
---|---|---|
committer | Ben Skeggs <bskeggs@redhat.com> | 2013-11-08 00:40:05 -0500 |
commit | 2984506fb6172712f83e573319baf7dbd0eb9028 (patch) | |
tree | 17032d70df48ceabd832c0ffa936aac4239b3842 | |
parent | 48ae0b355f21533145133002854de89a0537408d (diff) |
drm/nouveau/bus: add interfaces/helpers for sequencer
Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
-rw-r--r-- | drivers/gpu/drm/nouveau/Makefile | 1 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/core/engine/device/nv50.c | 20 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/core/include/subdev/bus.h | 12 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/core/subdev/bus/hwsq.c | 145 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/core/subdev/bus/hwsq.h | 113 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/core/subdev/bus/nv04.c | 2 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/core/subdev/bus/nv04.h | 10 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/core/subdev/bus/nv50.c | 24 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/core/subdev/bus/nv94.c | 59 |
9 files changed, 371 insertions, 15 deletions
diff --git a/drivers/gpu/drm/nouveau/Makefile b/drivers/gpu/drm/nouveau/Makefile index fbe33ed5f6cf..3859958581c2 100644 --- a/drivers/gpu/drm/nouveau/Makefile +++ b/drivers/gpu/drm/nouveau/Makefile | |||
@@ -44,6 +44,7 @@ nouveau-y += core/subdev/bios/xpio.o | |||
44 | nouveau-y += core/subdev/bus/nv04.o | 44 | nouveau-y += core/subdev/bus/nv04.o |
45 | nouveau-y += core/subdev/bus/nv31.o | 45 | nouveau-y += core/subdev/bus/nv31.o |
46 | nouveau-y += core/subdev/bus/nv50.o | 46 | nouveau-y += core/subdev/bus/nv50.o |
47 | nouveau-y += core/subdev/bus/nv94.o | ||
47 | nouveau-y += core/subdev/bus/nvc0.o | 48 | nouveau-y += core/subdev/bus/nvc0.o |
48 | nouveau-y += core/subdev/clock/nv04.o | 49 | nouveau-y += core/subdev/clock/nv04.o |
49 | nouveau-y += core/subdev/clock/nv40.o | 50 | nouveau-y += core/subdev/clock/nv40.o |
diff --git a/drivers/gpu/drm/nouveau/core/engine/device/nv50.c b/drivers/gpu/drm/nouveau/core/engine/device/nv50.c index cb6039c01a67..f44a2baecc79 100644 --- a/drivers/gpu/drm/nouveau/core/engine/device/nv50.c +++ b/drivers/gpu/drm/nouveau/core/engine/device/nv50.c | |||
@@ -166,7 +166,7 @@ nv50_identify(struct nouveau_device *device) | |||
166 | device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass; | 166 | device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass; |
167 | device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; | 167 | device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; |
168 | device->oclass[NVDEV_SUBDEV_MC ] = nv94_mc_oclass; | 168 | device->oclass[NVDEV_SUBDEV_MC ] = nv94_mc_oclass; |
169 | device->oclass[NVDEV_SUBDEV_BUS ] = nv50_bus_oclass; | 169 | device->oclass[NVDEV_SUBDEV_BUS ] = nv94_bus_oclass; |
170 | device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; | 170 | device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; |
171 | device->oclass[NVDEV_SUBDEV_FB ] = nv84_fb_oclass; | 171 | device->oclass[NVDEV_SUBDEV_FB ] = nv84_fb_oclass; |
172 | device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass; | 172 | device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass; |
@@ -192,7 +192,7 @@ nv50_identify(struct nouveau_device *device) | |||
192 | device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass; | 192 | device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass; |
193 | device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; | 193 | device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; |
194 | device->oclass[NVDEV_SUBDEV_MC ] = nv94_mc_oclass; | 194 | device->oclass[NVDEV_SUBDEV_MC ] = nv94_mc_oclass; |
195 | device->oclass[NVDEV_SUBDEV_BUS ] = nv50_bus_oclass; | 195 | device->oclass[NVDEV_SUBDEV_BUS ] = nv94_bus_oclass; |
196 | device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; | 196 | device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; |
197 | device->oclass[NVDEV_SUBDEV_FB ] = nv84_fb_oclass; | 197 | device->oclass[NVDEV_SUBDEV_FB ] = nv84_fb_oclass; |
198 | device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass; | 198 | device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass; |
@@ -218,7 +218,7 @@ nv50_identify(struct nouveau_device *device) | |||
218 | device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass; | 218 | device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass; |
219 | device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; | 219 | device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; |
220 | device->oclass[NVDEV_SUBDEV_MC ] = nv98_mc_oclass; | 220 | device->oclass[NVDEV_SUBDEV_MC ] = nv98_mc_oclass; |
221 | device->oclass[NVDEV_SUBDEV_BUS ] = nv50_bus_oclass; | 221 | device->oclass[NVDEV_SUBDEV_BUS ] = nv94_bus_oclass; |
222 | device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; | 222 | device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; |
223 | device->oclass[NVDEV_SUBDEV_FB ] = nv84_fb_oclass; | 223 | device->oclass[NVDEV_SUBDEV_FB ] = nv84_fb_oclass; |
224 | device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass; | 224 | device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass; |
@@ -244,7 +244,7 @@ nv50_identify(struct nouveau_device *device) | |||
244 | device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass; | 244 | device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass; |
245 | device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; | 245 | device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; |
246 | device->oclass[NVDEV_SUBDEV_MC ] = nv98_mc_oclass; | 246 | device->oclass[NVDEV_SUBDEV_MC ] = nv98_mc_oclass; |
247 | device->oclass[NVDEV_SUBDEV_BUS ] = nv50_bus_oclass; | 247 | device->oclass[NVDEV_SUBDEV_BUS ] = nv94_bus_oclass; |
248 | device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; | 248 | device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; |
249 | device->oclass[NVDEV_SUBDEV_FB ] = nv84_fb_oclass; | 249 | device->oclass[NVDEV_SUBDEV_FB ] = nv84_fb_oclass; |
250 | device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass; | 250 | device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass; |
@@ -270,7 +270,7 @@ nv50_identify(struct nouveau_device *device) | |||
270 | device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass; | 270 | device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass; |
271 | device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; | 271 | device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; |
272 | device->oclass[NVDEV_SUBDEV_MC ] = nv98_mc_oclass; | 272 | device->oclass[NVDEV_SUBDEV_MC ] = nv98_mc_oclass; |
273 | device->oclass[NVDEV_SUBDEV_BUS ] = nv50_bus_oclass; | 273 | device->oclass[NVDEV_SUBDEV_BUS ] = nv94_bus_oclass; |
274 | device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; | 274 | device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; |
275 | device->oclass[NVDEV_SUBDEV_FB ] = nvaa_fb_oclass; | 275 | device->oclass[NVDEV_SUBDEV_FB ] = nvaa_fb_oclass; |
276 | device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass; | 276 | device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass; |
@@ -296,7 +296,7 @@ nv50_identify(struct nouveau_device *device) | |||
296 | device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass; | 296 | device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass; |
297 | device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; | 297 | device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; |
298 | device->oclass[NVDEV_SUBDEV_MC ] = nv98_mc_oclass; | 298 | device->oclass[NVDEV_SUBDEV_MC ] = nv98_mc_oclass; |
299 | device->oclass[NVDEV_SUBDEV_BUS ] = nv50_bus_oclass; | 299 | device->oclass[NVDEV_SUBDEV_BUS ] = nv94_bus_oclass; |
300 | device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; | 300 | device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; |
301 | device->oclass[NVDEV_SUBDEV_FB ] = nvaa_fb_oclass; | 301 | device->oclass[NVDEV_SUBDEV_FB ] = nvaa_fb_oclass; |
302 | device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass; | 302 | device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass; |
@@ -322,7 +322,7 @@ nv50_identify(struct nouveau_device *device) | |||
322 | device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass; | 322 | device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass; |
323 | device->oclass[NVDEV_SUBDEV_DEVINIT] = &nva3_devinit_oclass; | 323 | device->oclass[NVDEV_SUBDEV_DEVINIT] = &nva3_devinit_oclass; |
324 | device->oclass[NVDEV_SUBDEV_MC ] = nv98_mc_oclass; | 324 | device->oclass[NVDEV_SUBDEV_MC ] = nv98_mc_oclass; |
325 | device->oclass[NVDEV_SUBDEV_BUS ] = nv50_bus_oclass; | 325 | device->oclass[NVDEV_SUBDEV_BUS ] = nv94_bus_oclass; |
326 | device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; | 326 | device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; |
327 | device->oclass[NVDEV_SUBDEV_FB ] = nva3_fb_oclass; | 327 | device->oclass[NVDEV_SUBDEV_FB ] = nva3_fb_oclass; |
328 | device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass; | 328 | device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass; |
@@ -350,7 +350,7 @@ nv50_identify(struct nouveau_device *device) | |||
350 | device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass; | 350 | device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass; |
351 | device->oclass[NVDEV_SUBDEV_DEVINIT] = &nva3_devinit_oclass; | 351 | device->oclass[NVDEV_SUBDEV_DEVINIT] = &nva3_devinit_oclass; |
352 | device->oclass[NVDEV_SUBDEV_MC ] = nv98_mc_oclass; | 352 | device->oclass[NVDEV_SUBDEV_MC ] = nv98_mc_oclass; |
353 | device->oclass[NVDEV_SUBDEV_BUS ] = nv50_bus_oclass; | 353 | device->oclass[NVDEV_SUBDEV_BUS ] = nv94_bus_oclass; |
354 | device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; | 354 | device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; |
355 | device->oclass[NVDEV_SUBDEV_FB ] = nva3_fb_oclass; | 355 | device->oclass[NVDEV_SUBDEV_FB ] = nva3_fb_oclass; |
356 | device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass; | 356 | device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass; |
@@ -377,7 +377,7 @@ nv50_identify(struct nouveau_device *device) | |||
377 | device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass; | 377 | device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass; |
378 | device->oclass[NVDEV_SUBDEV_DEVINIT] = &nva3_devinit_oclass; | 378 | device->oclass[NVDEV_SUBDEV_DEVINIT] = &nva3_devinit_oclass; |
379 | device->oclass[NVDEV_SUBDEV_MC ] = nv98_mc_oclass; | 379 | device->oclass[NVDEV_SUBDEV_MC ] = nv98_mc_oclass; |
380 | device->oclass[NVDEV_SUBDEV_BUS ] = nv50_bus_oclass; | 380 | device->oclass[NVDEV_SUBDEV_BUS ] = nv94_bus_oclass; |
381 | device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; | 381 | device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; |
382 | device->oclass[NVDEV_SUBDEV_FB ] = nva3_fb_oclass; | 382 | device->oclass[NVDEV_SUBDEV_FB ] = nva3_fb_oclass; |
383 | device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass; | 383 | device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass; |
@@ -404,7 +404,7 @@ nv50_identify(struct nouveau_device *device) | |||
404 | device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass; | 404 | device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass; |
405 | device->oclass[NVDEV_SUBDEV_DEVINIT] = &nva3_devinit_oclass; | 405 | device->oclass[NVDEV_SUBDEV_DEVINIT] = &nva3_devinit_oclass; |
406 | device->oclass[NVDEV_SUBDEV_MC ] = nv98_mc_oclass; | 406 | device->oclass[NVDEV_SUBDEV_MC ] = nv98_mc_oclass; |
407 | device->oclass[NVDEV_SUBDEV_BUS ] = nv50_bus_oclass; | 407 | device->oclass[NVDEV_SUBDEV_BUS ] = nv94_bus_oclass; |
408 | device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; | 408 | device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; |
409 | device->oclass[NVDEV_SUBDEV_FB ] = nvaf_fb_oclass; | 409 | device->oclass[NVDEV_SUBDEV_FB ] = nvaf_fb_oclass; |
410 | device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass; | 410 | device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass; |
diff --git a/drivers/gpu/drm/nouveau/core/include/subdev/bus.h b/drivers/gpu/drm/nouveau/core/include/subdev/bus.h index 837401d41e7d..697f7ce70aab 100644 --- a/drivers/gpu/drm/nouveau/core/include/subdev/bus.h +++ b/drivers/gpu/drm/nouveau/core/include/subdev/bus.h | |||
@@ -11,6 +11,8 @@ struct nouveau_bus_intr { | |||
11 | 11 | ||
12 | struct nouveau_bus { | 12 | struct nouveau_bus { |
13 | struct nouveau_subdev base; | 13 | struct nouveau_subdev base; |
14 | int (*hwsq_exec)(struct nouveau_bus *, u32 *, u32); | ||
15 | u32 hwsq_size; | ||
14 | }; | 16 | }; |
15 | 17 | ||
16 | static inline struct nouveau_bus * | 18 | static inline struct nouveau_bus * |
@@ -36,6 +38,16 @@ nouveau_bus(void *obj) | |||
36 | extern struct nouveau_oclass *nv04_bus_oclass; | 38 | extern struct nouveau_oclass *nv04_bus_oclass; |
37 | extern struct nouveau_oclass *nv31_bus_oclass; | 39 | extern struct nouveau_oclass *nv31_bus_oclass; |
38 | extern struct nouveau_oclass *nv50_bus_oclass; | 40 | extern struct nouveau_oclass *nv50_bus_oclass; |
41 | extern struct nouveau_oclass *nv94_bus_oclass; | ||
39 | extern struct nouveau_oclass *nvc0_bus_oclass; | 42 | extern struct nouveau_oclass *nvc0_bus_oclass; |
40 | 43 | ||
44 | /* interface to sequencer */ | ||
45 | struct nouveau_hwsq; | ||
46 | int nouveau_hwsq_init(struct nouveau_bus *, struct nouveau_hwsq **); | ||
47 | int nouveau_hwsq_fini(struct nouveau_hwsq **, bool exec); | ||
48 | void nouveau_hwsq_wr32(struct nouveau_hwsq *, u32 addr, u32 data); | ||
49 | void nouveau_hwsq_setf(struct nouveau_hwsq *, u8 flag, int data); | ||
50 | void nouveau_hwsq_wait(struct nouveau_hwsq *, u8 flag, u8 data); | ||
51 | void nouveau_hwsq_nsec(struct nouveau_hwsq *, u32 nsec); | ||
52 | |||
41 | #endif | 53 | #endif |
diff --git a/drivers/gpu/drm/nouveau/core/subdev/bus/hwsq.c b/drivers/gpu/drm/nouveau/core/subdev/bus/hwsq.c new file mode 100644 index 000000000000..f757470e2284 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/subdev/bus/hwsq.c | |||
@@ -0,0 +1,145 @@ | |||
1 | /* | ||
2 | * Copyright 2013 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 <bskeggs@redhat.com> | ||
23 | */ | ||
24 | |||
25 | #include <subdev/timer.h> | ||
26 | #include <subdev/bus.h> | ||
27 | |||
28 | struct nouveau_hwsq { | ||
29 | struct nouveau_bus *pbus; | ||
30 | u32 addr; | ||
31 | u32 data; | ||
32 | struct { | ||
33 | u8 data[512]; | ||
34 | u8 size; | ||
35 | } c; | ||
36 | }; | ||
37 | |||
38 | static void | ||
39 | hwsq_cmd(struct nouveau_hwsq *hwsq, int size, u8 data[]) | ||
40 | { | ||
41 | memcpy(&hwsq->c.data[hwsq->c.size], data, size * sizeof(data[0])); | ||
42 | hwsq->c.size += size; | ||
43 | } | ||
44 | |||
45 | int | ||
46 | nouveau_hwsq_init(struct nouveau_bus *pbus, struct nouveau_hwsq **phwsq) | ||
47 | { | ||
48 | struct nouveau_hwsq *hwsq; | ||
49 | |||
50 | hwsq = *phwsq = kmalloc(sizeof(*hwsq), GFP_KERNEL); | ||
51 | if (hwsq) { | ||
52 | hwsq->pbus = pbus; | ||
53 | hwsq->addr = ~0; | ||
54 | hwsq->data = ~0; | ||
55 | memset(hwsq->c.data, 0x7f, sizeof(hwsq->c.data)); | ||
56 | hwsq->c.size = 0; | ||
57 | } | ||
58 | |||
59 | return hwsq ? 0 : -ENOMEM; | ||
60 | } | ||
61 | |||
62 | int | ||
63 | nouveau_hwsq_fini(struct nouveau_hwsq **phwsq, bool exec) | ||
64 | { | ||
65 | struct nouveau_hwsq *hwsq = *phwsq; | ||
66 | int ret = 0, i; | ||
67 | if (hwsq) { | ||
68 | struct nouveau_bus *pbus = hwsq->pbus; | ||
69 | hwsq->c.size = (hwsq->c.size + 4) / 4; | ||
70 | if (hwsq->c.size <= pbus->hwsq_size) { | ||
71 | if (exec) | ||
72 | ret = pbus->hwsq_exec(pbus, (u32 *)hwsq->c.data, | ||
73 | hwsq->c.size); | ||
74 | if (ret) | ||
75 | nv_error(pbus, "hwsq exec failed: %d\n", ret); | ||
76 | } else { | ||
77 | nv_error(pbus, "hwsq ucode too large\n"); | ||
78 | ret = -ENOSPC; | ||
79 | } | ||
80 | |||
81 | for (i = 0; ret && i < hwsq->c.size; i++) | ||
82 | nv_error(pbus, "\t0x%08x\n", ((u32 *)hwsq->c.data)[i]); | ||
83 | |||
84 | *phwsq = NULL; | ||
85 | kfree(hwsq); | ||
86 | } | ||
87 | return ret; | ||
88 | } | ||
89 | |||
90 | void | ||
91 | nouveau_hwsq_wr32(struct nouveau_hwsq *hwsq, u32 addr, u32 data) | ||
92 | { | ||
93 | nv_debug(hwsq->pbus, "R[%06x] = 0x%08x\n", addr, data); | ||
94 | |||
95 | if (hwsq->data != data) { | ||
96 | if ((data & 0xffff0000) != (hwsq->data & 0xffff0000)) { | ||
97 | hwsq_cmd(hwsq, 5, (u8[]){ 0xe2, data, data >> 8, | ||
98 | data >> 16, data >> 24 }); | ||
99 | } else { | ||
100 | hwsq_cmd(hwsq, 3, (u8[]){ 0x42, data, data >> 8 }); | ||
101 | } | ||
102 | } | ||
103 | |||
104 | if ((addr & 0xffff0000) != (hwsq->addr & 0xffff0000)) { | ||
105 | hwsq_cmd(hwsq, 5, (u8[]){ 0xe0, addr, addr >> 8, | ||
106 | addr >> 16, addr >> 24 }); | ||
107 | } else { | ||
108 | hwsq_cmd(hwsq, 3, (u8[]){ 0x40, addr, addr >> 8 }); | ||
109 | } | ||
110 | |||
111 | hwsq->addr = addr; | ||
112 | hwsq->data = data; | ||
113 | } | ||
114 | |||
115 | void | ||
116 | nouveau_hwsq_setf(struct nouveau_hwsq *hwsq, u8 flag, int data) | ||
117 | { | ||
118 | nv_debug(hwsq->pbus, " FLAG[%02x] = %d\n", flag, data); | ||
119 | flag += 0x80; | ||
120 | if (data >= 0) | ||
121 | flag += 0x20; | ||
122 | if (data >= 1) | ||
123 | flag += 0x20; | ||
124 | hwsq_cmd(hwsq, 1, (u8[]){ flag }); | ||
125 | } | ||
126 | |||
127 | void | ||
128 | nouveau_hwsq_wait(struct nouveau_hwsq *hwsq, u8 flag, u8 data) | ||
129 | { | ||
130 | nv_debug(hwsq->pbus, " WAIT[%02x] = %d\n", flag, data); | ||
131 | hwsq_cmd(hwsq, 3, (u8[]){ 0x5f, flag, data }); | ||
132 | } | ||
133 | |||
134 | void | ||
135 | nouveau_hwsq_nsec(struct nouveau_hwsq *hwsq, u32 nsec) | ||
136 | { | ||
137 | u8 shift = 0, usec = nsec / 1000; | ||
138 | while (usec & ~3) { | ||
139 | usec >>= 2; | ||
140 | shift++; | ||
141 | } | ||
142 | |||
143 | nv_debug(hwsq->pbus, " DELAY = %d ns\n", nsec); | ||
144 | hwsq_cmd(hwsq, 1, (u8[]){ 0x00 | (shift << 2) | usec }); | ||
145 | } | ||
diff --git a/drivers/gpu/drm/nouveau/core/subdev/bus/hwsq.h b/drivers/gpu/drm/nouveau/core/subdev/bus/hwsq.h new file mode 100644 index 000000000000..12176f9c1bc6 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/subdev/bus/hwsq.h | |||
@@ -0,0 +1,113 @@ | |||
1 | #ifndef __NVKM_BUS_HWSQ_H__ | ||
2 | #define __NVKM_BUS_HWSQ_H__ | ||
3 | |||
4 | #include <subdev/bus.h> | ||
5 | |||
6 | struct hwsq { | ||
7 | struct nouveau_subdev *subdev; | ||
8 | struct nouveau_hwsq *hwsq; | ||
9 | int sequence; | ||
10 | }; | ||
11 | |||
12 | struct hwsq_reg { | ||
13 | int sequence; | ||
14 | bool force; | ||
15 | u32 addr[2]; | ||
16 | u32 data; | ||
17 | }; | ||
18 | |||
19 | static inline struct hwsq_reg | ||
20 | hwsq_reg2(u32 addr1, u32 addr2) | ||
21 | { | ||
22 | return (struct hwsq_reg) { | ||
23 | .sequence = 0, | ||
24 | .force = 0, | ||
25 | .addr = { addr1, addr2 }, | ||
26 | .data = 0xdeadbeef, | ||
27 | }; | ||
28 | } | ||
29 | |||
30 | static inline struct hwsq_reg | ||
31 | hwsq_reg(u32 addr) | ||
32 | { | ||
33 | return hwsq_reg2(addr, addr); | ||
34 | } | ||
35 | |||
36 | static inline int | ||
37 | hwsq_init(struct hwsq *ram, struct nouveau_subdev *subdev) | ||
38 | { | ||
39 | struct nouveau_bus *pbus = nouveau_bus(subdev); | ||
40 | int ret; | ||
41 | |||
42 | ret = nouveau_hwsq_init(pbus, &ram->hwsq); | ||
43 | if (ret) | ||
44 | return ret; | ||
45 | |||
46 | ram->sequence++; | ||
47 | ram->subdev = subdev; | ||
48 | return 0; | ||
49 | } | ||
50 | |||
51 | static inline int | ||
52 | hwsq_exec(struct hwsq *ram, bool exec) | ||
53 | { | ||
54 | int ret = 0; | ||
55 | if (ram->subdev) { | ||
56 | ret = nouveau_hwsq_fini(&ram->hwsq, exec); | ||
57 | ram->subdev = NULL; | ||
58 | } | ||
59 | return ret; | ||
60 | } | ||
61 | |||
62 | static inline u32 | ||
63 | hwsq_rd32(struct hwsq *ram, struct hwsq_reg *reg) | ||
64 | { | ||
65 | if (reg->sequence != ram->sequence) | ||
66 | reg->data = nv_rd32(ram->subdev, reg->addr[0]); | ||
67 | return reg->data; | ||
68 | } | ||
69 | |||
70 | static inline void | ||
71 | hwsq_wr32(struct hwsq *ram, struct hwsq_reg *reg, u32 data) | ||
72 | { | ||
73 | reg->sequence = ram->sequence; | ||
74 | reg->data = data; | ||
75 | if (reg->addr[0] != reg->addr[1]) | ||
76 | nouveau_hwsq_wr32(ram->hwsq, reg->addr[1], reg->data); | ||
77 | nouveau_hwsq_wr32(ram->hwsq, reg->addr[0], reg->data); | ||
78 | } | ||
79 | |||
80 | static inline void | ||
81 | hwsq_nuke(struct hwsq *ram, struct hwsq_reg *reg) | ||
82 | { | ||
83 | reg->force = true; | ||
84 | } | ||
85 | |||
86 | static inline u32 | ||
87 | hwsq_mask(struct hwsq *ram, struct hwsq_reg *reg, u32 mask, u32 data) | ||
88 | { | ||
89 | u32 temp = hwsq_rd32(ram, reg); | ||
90 | if (temp != ((temp & ~mask) | data) || reg->force) | ||
91 | hwsq_wr32(ram, reg, (temp & ~mask) | data); | ||
92 | return temp; | ||
93 | } | ||
94 | |||
95 | static inline void | ||
96 | hwsq_setf(struct hwsq *ram, u8 flag, int data) | ||
97 | { | ||
98 | nouveau_hwsq_setf(ram->hwsq, flag, data); | ||
99 | } | ||
100 | |||
101 | static inline void | ||
102 | hwsq_wait(struct hwsq *ram, u8 flag, u8 data) | ||
103 | { | ||
104 | nouveau_hwsq_wait(ram->hwsq, flag, data); | ||
105 | } | ||
106 | |||
107 | static inline void | ||
108 | hwsq_nsec(struct hwsq *ram, u32 nsec) | ||
109 | { | ||
110 | nouveau_hwsq_nsec(ram->hwsq, nsec); | ||
111 | } | ||
112 | |||
113 | #endif | ||
diff --git a/drivers/gpu/drm/nouveau/core/subdev/bus/nv04.c b/drivers/gpu/drm/nouveau/core/subdev/bus/nv04.c index 478209930dcd..23921b5351db 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/bus/nv04.c +++ b/drivers/gpu/drm/nouveau/core/subdev/bus/nv04.c | |||
@@ -77,6 +77,8 @@ nv04_bus_ctor(struct nouveau_object *parent, struct nouveau_object *engine, | |||
77 | return ret; | 77 | return ret; |
78 | 78 | ||
79 | nv_subdev(priv)->intr = impl->intr; | 79 | nv_subdev(priv)->intr = impl->intr; |
80 | priv->base.hwsq_exec = impl->hwsq_exec; | ||
81 | priv->base.hwsq_size = impl->hwsq_size; | ||
80 | return 0; | 82 | return 0; |
81 | } | 83 | } |
82 | 84 | ||
diff --git a/drivers/gpu/drm/nouveau/core/subdev/bus/nv04.h b/drivers/gpu/drm/nouveau/core/subdev/bus/nv04.h index 0ac589d26a4c..4d7602450a20 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/bus/nv04.h +++ b/drivers/gpu/drm/nouveau/core/subdev/bus/nv04.h | |||
@@ -7,13 +7,17 @@ struct nv04_bus_priv { | |||
7 | struct nouveau_bus base; | 7 | struct nouveau_bus base; |
8 | }; | 8 | }; |
9 | 9 | ||
10 | int nv04_bus_ctor(struct nouveau_object *, struct nouveau_object *, | 10 | int nv04_bus_ctor(struct nouveau_object *, struct nouveau_object *, |
11 | struct nouveau_oclass *, void *, u32, | 11 | struct nouveau_oclass *, void *, u32, |
12 | struct nouveau_object **); | 12 | struct nouveau_object **); |
13 | int nv50_bus_init(struct nouveau_object *); | ||
14 | void nv50_bus_intr(struct nouveau_subdev *); | ||
13 | 15 | ||
14 | struct nv04_bus_impl { | 16 | struct nv04_bus_impl { |
15 | struct nouveau_oclass base; | 17 | struct nouveau_oclass base; |
16 | void (*intr)(struct nouveau_subdev *); | 18 | void (*intr)(struct nouveau_subdev *); |
19 | int (*hwsq_exec)(struct nouveau_bus *, u32 *, u32); | ||
20 | u32 hwsq_size; | ||
17 | }; | 21 | }; |
18 | 22 | ||
19 | #endif | 23 | #endif |
diff --git a/drivers/gpu/drm/nouveau/core/subdev/bus/nv50.c b/drivers/gpu/drm/nouveau/core/subdev/bus/nv50.c index cda534790d1d..11918f7e2aca 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/bus/nv50.c +++ b/drivers/gpu/drm/nouveau/core/subdev/bus/nv50.c | |||
@@ -23,9 +23,27 @@ | |||
23 | * Ben Skeggs | 23 | * Ben Skeggs |
24 | */ | 24 | */ |
25 | 25 | ||
26 | #include <subdev/timer.h> | ||
27 | |||
26 | #include "nv04.h" | 28 | #include "nv04.h" |
27 | 29 | ||
28 | static void | 30 | static int |
31 | nv50_bus_hwsq_exec(struct nouveau_bus *pbus, u32 *data, u32 size) | ||
32 | { | ||
33 | struct nv50_bus_priv *priv = (void *)pbus; | ||
34 | int i; | ||
35 | |||
36 | nv_mask(pbus, 0x001098, 0x00000008, 0x00000000); | ||
37 | nv_wr32(pbus, 0x001304, 0x00000000); | ||
38 | for (i = 0; i < size; i++) | ||
39 | nv_wr32(priv, 0x001400 + (i * 4), data[i]); | ||
40 | nv_mask(pbus, 0x001098, 0x00000018, 0x00000018); | ||
41 | nv_wr32(pbus, 0x00130c, 0x00000003); | ||
42 | |||
43 | return nv_wait(pbus, 0x001308, 0x00000100, 0x00000000) ? 0 : -ETIMEDOUT; | ||
44 | } | ||
45 | |||
46 | void | ||
29 | nv50_bus_intr(struct nouveau_subdev *subdev) | 47 | nv50_bus_intr(struct nouveau_subdev *subdev) |
30 | { | 48 | { |
31 | struct nouveau_bus *pbus = nouveau_bus(subdev); | 49 | struct nouveau_bus *pbus = nouveau_bus(subdev); |
@@ -57,7 +75,7 @@ nv50_bus_intr(struct nouveau_subdev *subdev) | |||
57 | } | 75 | } |
58 | } | 76 | } |
59 | 77 | ||
60 | static int | 78 | int |
61 | nv50_bus_init(struct nouveau_object *object) | 79 | nv50_bus_init(struct nouveau_object *object) |
62 | { | 80 | { |
63 | struct nv04_bus_priv *priv = (void *)object; | 81 | struct nv04_bus_priv *priv = (void *)object; |
@@ -82,4 +100,6 @@ nv50_bus_oclass = &(struct nv04_bus_impl) { | |||
82 | .fini = _nouveau_bus_fini, | 100 | .fini = _nouveau_bus_fini, |
83 | }, | 101 | }, |
84 | .intr = nv50_bus_intr, | 102 | .intr = nv50_bus_intr, |
103 | .hwsq_exec = nv50_bus_hwsq_exec, | ||
104 | .hwsq_size = 64, | ||
85 | }.base; | 105 | }.base; |
diff --git a/drivers/gpu/drm/nouveau/core/subdev/bus/nv94.c b/drivers/gpu/drm/nouveau/core/subdev/bus/nv94.c new file mode 100644 index 000000000000..d3659055fa4b --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/subdev/bus/nv94.c | |||
@@ -0,0 +1,59 @@ | |||
1 | /* | ||
2 | * Copyright 2012 Nouveau Community | ||
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: Martin Peres <martin.peres@labri.fr> | ||
23 | * Ben Skeggs | ||
24 | */ | ||
25 | |||
26 | #include <subdev/timer.h> | ||
27 | |||
28 | #include "nv04.h" | ||
29 | |||
30 | static int | ||
31 | nv94_bus_hwsq_exec(struct nouveau_bus *pbus, u32 *data, u32 size) | ||
32 | { | ||
33 | struct nv50_bus_priv *priv = (void *)pbus; | ||
34 | int i; | ||
35 | |||
36 | nv_mask(pbus, 0x001098, 0x00000008, 0x00000000); | ||
37 | nv_wr32(pbus, 0x001304, 0x00000000); | ||
38 | nv_wr32(pbus, 0x001318, 0x00000000); | ||
39 | for (i = 0; i < size; i++) | ||
40 | nv_wr32(priv, 0x080000 + (i * 4), data[i]); | ||
41 | nv_mask(pbus, 0x001098, 0x00000018, 0x00000018); | ||
42 | nv_wr32(pbus, 0x00130c, 0x00000001); | ||
43 | |||
44 | return nv_wait(pbus, 0x001308, 0x00000100, 0x00000000) ? 0 : -ETIMEDOUT; | ||
45 | } | ||
46 | |||
47 | struct nouveau_oclass * | ||
48 | nv94_bus_oclass = &(struct nv04_bus_impl) { | ||
49 | .base.handle = NV_SUBDEV(BUS, 0x94), | ||
50 | .base.ofuncs = &(struct nouveau_ofuncs) { | ||
51 | .ctor = nv04_bus_ctor, | ||
52 | .dtor = _nouveau_bus_dtor, | ||
53 | .init = nv50_bus_init, | ||
54 | .fini = _nouveau_bus_fini, | ||
55 | }, | ||
56 | .intr = nv50_bus_intr, | ||
57 | .hwsq_exec = nv94_bus_hwsq_exec, | ||
58 | .hwsq_size = 128, | ||
59 | }.base; | ||