From 45cfb9cf089cd56878b1cb5d15391d2470dbeb7c Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Mon, 20 Dec 2010 10:53:44 +1000 Subject: [PATCH] nouveau: split pushbuf macros specific to nv04-nv50 out, and add nvc0 Signed-off-by: Ben Skeggs --- nouveau/Makefile.am | 2 + nouveau/nouveau_grobj.c | 11 ++++- nouveau/nouveau_pushbuf.h | 38 ---------------- nouveau/nv04_pushbuf.h | 66 ++++++++++++++++++++++++++++ nouveau/nvc0_pushbuf.h | 92 +++++++++++++++++++++++++++++++++++++++ 5 files changed, 169 insertions(+), 40 deletions(-) create mode 100644 nouveau/nv04_pushbuf.h create mode 100644 nouveau/nvc0_pushbuf.h diff --git a/nouveau/Makefile.am b/nouveau/Makefile.am index de3f4df0..8b899164 100644 --- a/nouveau/Makefile.am +++ b/nouveau/Makefile.am @@ -28,6 +28,8 @@ libdrm_nouveaucommoninclude_HEADERS = \ nouveau_grobj.h \ nouveau_notifier.h \ nouveau_pushbuf.h \ + nv04_pushbuf.h \ + nvc0_pushbuf.h \ nouveau_bo.h \ nouveau_resource.h \ nouveau_reloc.h diff --git a/nouveau/nouveau_grobj.c b/nouveau/nouveau_grobj.c index df2ffb91..c6b98f16 100644 --- a/nouveau/nouveau_grobj.c +++ b/nouveau/nouveau_grobj.c @@ -112,6 +112,7 @@ nouveau_grobj_free(struct nouveau_grobj **grobj) void nouveau_grobj_autobind(struct nouveau_grobj *grobj) { + struct nouveau_channel *chan = grobj->channel; struct nouveau_subchannel *subc = NULL; int i; @@ -134,7 +135,13 @@ nouveau_grobj_autobind(struct nouveau_grobj *grobj) subc->gr->bound = NOUVEAU_GROBJ_BOUND; subc->gr->subc = subc - &grobj->channel->subc[0]; - BEGIN_RING(grobj->channel, grobj, 0x0000, 1); - OUT_RING (grobj->channel, grobj->handle); + WAIT_RING(chan, 2); + if (chan->device->chipset < 0xc0) { + OUT_RING (chan, (1 << 18) | (grobj->subc << 13)); + OUT_RING (chan, grobj->handle); + } else { + OUT_RING (chan, (2 << 28) | (1 << 16) | (grobj->subc << 13)); + OUT_RING (chan, grobj->grclass); + } } diff --git a/nouveau/nouveau_pushbuf.h b/nouveau/nouveau_pushbuf.h index 52d13a0a..2a98789c 100644 --- a/nouveau/nouveau_pushbuf.h +++ b/nouveau/nouveau_pushbuf.h @@ -95,50 +95,12 @@ WAIT_RING(struct nouveau_channel *chan, unsigned size) nouveau_pushbuf_flush(chan, size); } -static __inline__ void -BEGIN_RING(struct nouveau_channel *chan, struct nouveau_grobj *gr, - unsigned mthd, unsigned size) -{ - if (gr->bound == NOUVEAU_GROBJ_UNBOUND) - nouveau_grobj_autobind(gr); - chan->subc[gr->subc].sequence = chan->subc_sequence++; - - WAIT_RING(chan, size + 1); - OUT_RING(chan, (gr->subc << 13) | (size << 18) | mthd); -} - -/* non-incrementing BEGIN_RING */ -static __inline__ void -BEGIN_RING_NI(struct nouveau_channel *chan, struct nouveau_grobj *gr, - unsigned mthd, unsigned size) -{ - BEGIN_RING(chan, gr, mthd | 0x40000000, size); -} - static __inline__ void FIRE_RING(struct nouveau_channel *chan) { nouveau_pushbuf_flush(chan, 0); } -static __inline__ void -BIND_RING(struct nouveau_channel *chan, struct nouveau_grobj *gr, unsigned sc) -{ - struct nouveau_subchannel *subc = &gr->channel->subc[sc]; - - if (subc->gr) { - if (subc->gr->bound == NOUVEAU_GROBJ_BOUND_EXPLICIT) - assert(0); - subc->gr->bound = NOUVEAU_GROBJ_UNBOUND; - } - subc->gr = gr; - subc->gr->subc = sc; - subc->gr->bound = NOUVEAU_GROBJ_BOUND_EXPLICIT; - - BEGIN_RING(chan, gr, 0x0000, 1); - OUT_RING (chan, gr->handle); -} - static __inline__ int OUT_RELOC(struct nouveau_channel *chan, struct nouveau_bo *bo, unsigned data, unsigned flags, unsigned vor, unsigned tor) diff --git a/nouveau/nv04_pushbuf.h b/nouveau/nv04_pushbuf.h new file mode 100644 index 00000000..586b2847 --- /dev/null +++ b/nouveau/nv04_pushbuf.h @@ -0,0 +1,66 @@ +/* + * Copyright 2007 Nouveau Project + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef __NV04_PUSHBUF_H__ +#define __NV04_PUSHBUF_H__ + +#include "nouveau_pushbuf.h" + +static __inline__ void +BEGIN_RING(struct nouveau_channel *chan, struct nouveau_grobj *gr, + unsigned mthd, unsigned size) +{ + if (gr->bound == NOUVEAU_GROBJ_UNBOUND) + nouveau_grobj_autobind(gr); + chan->subc[gr->subc].sequence = chan->subc_sequence++; + + WAIT_RING(chan, size + 1); + OUT_RING(chan, (gr->subc << 13) | (size << 18) | mthd); +} + +/* non-incrementing BEGIN_RING */ +static __inline__ void +BEGIN_RING_NI(struct nouveau_channel *chan, struct nouveau_grobj *gr, + unsigned mthd, unsigned size) +{ + BEGIN_RING(chan, gr, mthd | 0x40000000, size); +} + +static __inline__ void +BIND_RING(struct nouveau_channel *chan, struct nouveau_grobj *gr, unsigned sc) +{ + struct nouveau_subchannel *subc = &gr->channel->subc[sc]; + + if (subc->gr) { + if (subc->gr->bound == NOUVEAU_GROBJ_BOUND_EXPLICIT) + assert(0); + subc->gr->bound = NOUVEAU_GROBJ_UNBOUND; + } + subc->gr = gr; + subc->gr->subc = sc; + subc->gr->bound = NOUVEAU_GROBJ_BOUND_EXPLICIT; + + BEGIN_RING(chan, gr, 0x0000, 1); + OUT_RING (chan, gr->handle); +} + +#endif diff --git a/nouveau/nvc0_pushbuf.h b/nouveau/nvc0_pushbuf.h new file mode 100644 index 00000000..40dc7e67 --- /dev/null +++ b/nouveau/nvc0_pushbuf.h @@ -0,0 +1,92 @@ +/* + * Copyright 2010 Nouveau Project + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef __NVC0_PUSHBUF_H__ +#define __NVC0_PUSHBUF_H__ + +#include "nouveau_pushbuf.h" + +#define SUBC_BIND(chan, gr) do { \ + if (gr->bound == NOUVEAU_GROBJ_UNBOUND) \ + nouveau_grobj_autobind(gr); \ + chan->subc[gr->subc].sequence = chan->subc_sequence++; \ +} while (0) + +/* incremental methods */ +static __inline__ void +BEGIN_RING(struct nouveau_channel *chan, struct nouveau_grobj *gr, + unsigned mthd, unsigned size) +{ + SUBC_BIND(chan, gr); + WAIT_RING(chan, size + 1); + OUT_RING (chan, (0x2 << 28) | (size << 16) | (gr->subc << 13) | (mthd >> 2)); +} + +/* non-incremental */ +static __inline__ void +BEGIN_RING_NI(struct nouveau_channel *chan, struct nouveau_grobj *gr, + unsigned mthd, unsigned size) +{ + SUBC_BIND(chan, gr); + WAIT_RING(chan, size + 1); + OUT_RING (chan, (0x6 << 28) | (size << 16) | (gr->subc << 13) | (mthd >> 2)); +} + +/* increment-once */ +static __inline__ void +BEGIN_RING_1I(struct nouveau_channel *chan, struct nouveau_grobj *gr, + unsigned mthd, unsigned size) +{ + SUBC_BIND(chan, gr); + WAIT_RING(chan, size + 1); + OUT_RING (chan, (0xa << 28) | (size << 16) | (gr->subc << 13) | (mthd >> 2)); +} + +/* inline-data */ +static __inline__ void +IMMED_RING(struct nouveau_channel *chan, struct nouveau_grobj *gr, + unsigned mthd, unsigned data) +{ + SUBC_BIND(chan, gr); + WAIT_RING(chan, 1); + OUT_RING (chan, (0x8 << 28) | (data << 16) | (gr->subc << 13) | (mthd >> 2)); +} + +static __inline__ void +BIND_RING(struct nouveau_channel *chan, struct nouveau_grobj *gr, unsigned sc) +{ + struct nouveau_subchannel *subc = &gr->channel->subc[sc]; + + if (subc->gr) { + if (subc->gr->bound == NOUVEAU_GROBJ_BOUND_EXPLICIT) + assert(0); + subc->gr->bound = NOUVEAU_GROBJ_UNBOUND; + } + subc->gr = gr; + subc->gr->subc = sc; + subc->gr->bound = NOUVEAU_GROBJ_BOUND_EXPLICIT; + + BEGIN_RING(chan, gr, 0x0000, 1); + OUT_RING (chan, gr->grclass); +} + +#endif