nouveau: expose channel engine selection on kepler chipsets
authorBen Skeggs <bskeggs@redhat.com>
Fri, 23 Nov 2012 02:40:30 +0000 (12:40 +1000)
committerBen Skeggs <bskeggs@redhat.com>
Wed, 16 Jan 2013 09:48:49 +0000 (19:48 +1000)
v2: Take Maarten Lankhorst's suggestion of nesting the struct to prevent
    sizeof() issues due to padding on older revisions.

Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
Signed-off-by: Maarten Lankhorst <maarten.lankhorst@canonical.com>
nouveau/abi16.c
nouveau/nouveau.c
nouveau/nouveau.h
nouveau/private.h

index a67fbc1..f34175e 100644 (file)
 
 #include <stdlib.h>
 #include <stdint.h>
+#include <stddef.h>
 
 #include "private.h"
 
+
 int
 abi16_chan_nv04(struct nouveau_object *obj)
 {
@@ -70,6 +72,32 @@ abi16_chan_nvc0(struct nouveau_object *obj)
 }
 
 int
+abi16_chan_nve0(struct nouveau_object *obj)
+{
+       struct nouveau_device *dev = (struct nouveau_device *)obj->parent;
+       struct drm_nouveau_channel_alloc req = {};
+       struct nve0_fifo *nve0 = obj->data;
+       int ret;
+
+       if (obj->length > offsetof(struct nve0_fifo, engine)) {
+               req.fb_ctxdma_handle = 0xffffffff;
+               req.tt_ctxdma_handle = nve0->engine;
+       }
+
+       ret = drmCommandWriteRead(dev->fd, DRM_NOUVEAU_CHANNEL_ALLOC,
+                                 &req, sizeof(req));
+       if (ret)
+               return ret;
+
+       nve0->base.channel = req.channel;
+       nve0->base.pushbuf = req.pushbuf_domains;
+       nve0->notify = req.notifier_handle;
+       nve0->base.object->handle = req.channel;
+       nve0->base.object->length = sizeof(*nve0);
+       return 0;
+}
+
+int
 abi16_engobj(struct nouveau_object *obj)
 {
        struct drm_nouveau_grobj_alloc req = {
index 940d933..9b32e31 100644 (file)
@@ -247,7 +247,10 @@ nouveau_object_new(struct nouveau_object *parent, uint64_t handle,
                        if (dev->chipset < 0xc0)
                                ret = abi16_chan_nv04(obj);
                        else
+                       if (dev->chipset < 0xe0)
                                ret = abi16_chan_nvc0(obj);
+                       else
+                               ret = abi16_chan_nve0(obj);
                }
                        break;
                default:
index c42eea7..a55e2b0 100644 (file)
@@ -41,6 +41,22 @@ struct nvc0_fifo {
        uint32_t notify;
 };
 
+#define NVE0_FIFO_ENGINE_GR  0x00000001
+#define NVE0_FIFO_ENGINE_VP  0x00000002
+#define NVE0_FIFO_ENGINE_PPP 0x00000004
+#define NVE0_FIFO_ENGINE_BSP 0x00000008
+#define NVE0_FIFO_ENGINE_CE0 0x00000010
+#define NVE0_FIFO_ENGINE_CE1 0x00000020
+#define NVE0_FIFO_ENGINE_ENC 0x00000040
+
+struct nve0_fifo {
+       struct {
+               struct nouveau_fifo base;
+               uint32_t notify;
+       };
+       uint32_t engine;
+};
+
 struct nv04_notify {
        struct nouveau_object *object;
        uint32_t offset;
index b409cc8..8a5cb26 100644 (file)
@@ -113,6 +113,7 @@ nouveau_device_open_existing(struct nouveau_device **, int, int, drm_context_t);
 /* abi16.c */
 int  abi16_chan_nv04(struct nouveau_object *);
 int  abi16_chan_nvc0(struct nouveau_object *);
+int  abi16_chan_nve0(struct nouveau_object *);
 int  abi16_engobj(struct nouveau_object *);
 int  abi16_ntfy(struct nouveau_object *);
 void abi16_bo_info(struct nouveau_bo *, struct drm_nouveau_gem_info *);