linux/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chang84.c
<<
>>
Prefs
   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 */
  24#include "channv50.h"
  25
  26#include <core/client.h>
  27#include <core/ramht.h>
  28#include <subdev/mmu.h>
  29#include <subdev/timer.h>
  30
  31#include <nvif/cl826e.h>
  32
  33int
  34g84_fifo_chan_ntfy(struct nvkm_fifo_chan *chan, u32 type,
  35                   struct nvkm_event **pevent)
  36{
  37        switch (type) {
  38        case G82_CHANNEL_DMA_V0_NTFY_UEVENT:
  39                *pevent = &chan->fifo->uevent;
  40                return 0;
  41        default:
  42                break;
  43        }
  44        return -EINVAL;
  45}
  46
  47static int
  48g84_fifo_chan_engine(struct nvkm_engine *engine)
  49{
  50        switch (engine->subdev.index) {
  51        case NVKM_ENGINE_GR    : return 0;
  52        case NVKM_ENGINE_MPEG  :
  53        case NVKM_ENGINE_MSPPP : return 1;
  54        case NVKM_ENGINE_CE0   : return 2;
  55        case NVKM_ENGINE_VP    :
  56        case NVKM_ENGINE_MSPDEC: return 3;
  57        case NVKM_ENGINE_CIPHER:
  58        case NVKM_ENGINE_SEC   : return 4;
  59        case NVKM_ENGINE_BSP   :
  60        case NVKM_ENGINE_MSVLD : return 5;
  61        default:
  62                WARN_ON(1);
  63                return 0;
  64        }
  65}
  66
  67static int
  68g84_fifo_chan_engine_addr(struct nvkm_engine *engine)
  69{
  70        switch (engine->subdev.index) {
  71        case NVKM_ENGINE_DMAOBJ:
  72        case NVKM_ENGINE_SW    : return -1;
  73        case NVKM_ENGINE_GR    : return 0x0020;
  74        case NVKM_ENGINE_VP    :
  75        case NVKM_ENGINE_MSPDEC: return 0x0040;
  76        case NVKM_ENGINE_MPEG  :
  77        case NVKM_ENGINE_MSPPP : return 0x0060;
  78        case NVKM_ENGINE_BSP   :
  79        case NVKM_ENGINE_MSVLD : return 0x0080;
  80        case NVKM_ENGINE_CIPHER:
  81        case NVKM_ENGINE_SEC   : return 0x00a0;
  82        case NVKM_ENGINE_CE0   : return 0x00c0;
  83        default:
  84                WARN_ON(1);
  85                return -1;
  86        }
  87}
  88
  89static int
  90g84_fifo_chan_engine_fini(struct nvkm_fifo_chan *base,
  91                          struct nvkm_engine *engine, bool suspend)
  92{
  93        struct nv50_fifo_chan *chan = nv50_fifo_chan(base);
  94        struct nv50_fifo *fifo = chan->fifo;
  95        struct nvkm_subdev *subdev = &fifo->base.engine.subdev;
  96        struct nvkm_device *device = subdev->device;
  97        u32 engn, save;
  98        int offset;
  99        bool done;
 100
 101        offset = g84_fifo_chan_engine_addr(engine);
 102        if (offset < 0)
 103                return 0;
 104
 105        engn = g84_fifo_chan_engine(engine);
 106        save = nvkm_mask(device, 0x002520, 0x0000003f, 1 << engn);
 107        nvkm_wr32(device, 0x0032fc, chan->base.inst->addr >> 12);
 108        done = nvkm_msec(device, 2000,
 109                if (nvkm_rd32(device, 0x0032fc) != 0xffffffff)
 110                        break;
 111        ) >= 0;
 112        nvkm_wr32(device, 0x002520, save);
 113        if (!done) {
 114                nvkm_error(subdev, "channel %d [%s] unload timeout\n",
 115                           chan->base.chid, chan->base.object.client->name);
 116                if (suspend)
 117                        return -EBUSY;
 118        }
 119
 120        nvkm_kmap(chan->eng);
 121        nvkm_wo32(chan->eng, offset + 0x00, 0x00000000);
 122        nvkm_wo32(chan->eng, offset + 0x04, 0x00000000);
 123        nvkm_wo32(chan->eng, offset + 0x08, 0x00000000);
 124        nvkm_wo32(chan->eng, offset + 0x0c, 0x00000000);
 125        nvkm_wo32(chan->eng, offset + 0x10, 0x00000000);
 126        nvkm_wo32(chan->eng, offset + 0x14, 0x00000000);
 127        nvkm_done(chan->eng);
 128        return 0;
 129}
 130
 131
 132int
 133g84_fifo_chan_engine_init(struct nvkm_fifo_chan *base,
 134                          struct nvkm_engine *engine)
 135{
 136        struct nv50_fifo_chan *chan = nv50_fifo_chan(base);
 137        struct nvkm_gpuobj *engn = chan->engn[engine->subdev.index];
 138        u64 limit, start;
 139        int offset;
 140
 141        offset = g84_fifo_chan_engine_addr(engine);
 142        if (offset < 0)
 143                return 0;
 144        limit = engn->addr + engn->size - 1;
 145        start = engn->addr;
 146
 147        nvkm_kmap(chan->eng);
 148        nvkm_wo32(chan->eng, offset + 0x00, 0x00190000);
 149        nvkm_wo32(chan->eng, offset + 0x04, lower_32_bits(limit));
 150        nvkm_wo32(chan->eng, offset + 0x08, lower_32_bits(start));
 151        nvkm_wo32(chan->eng, offset + 0x0c, upper_32_bits(limit) << 24 |
 152                                            upper_32_bits(start));
 153        nvkm_wo32(chan->eng, offset + 0x10, 0x00000000);
 154        nvkm_wo32(chan->eng, offset + 0x14, 0x00000000);
 155        nvkm_done(chan->eng);
 156        return 0;
 157}
 158
 159static int
 160g84_fifo_chan_engine_ctor(struct nvkm_fifo_chan *base,
 161                          struct nvkm_engine *engine,
 162                          struct nvkm_object *object)
 163{
 164        struct nv50_fifo_chan *chan = nv50_fifo_chan(base);
 165        int engn = engine->subdev.index;
 166
 167        if (g84_fifo_chan_engine_addr(engine) < 0)
 168                return 0;
 169
 170        return nvkm_object_bind(object, NULL, 0, &chan->engn[engn]);
 171}
 172
 173int
 174g84_fifo_chan_object_ctor(struct nvkm_fifo_chan *base,
 175                          struct nvkm_object *object)
 176{
 177        struct nv50_fifo_chan *chan = nv50_fifo_chan(base);
 178        u32 handle = object->handle;
 179        u32 context;
 180
 181        switch (object->engine->subdev.index) {
 182        case NVKM_ENGINE_DMAOBJ:
 183        case NVKM_ENGINE_SW    : context = 0x00000000; break;
 184        case NVKM_ENGINE_GR    : context = 0x00100000; break;
 185        case NVKM_ENGINE_MPEG  :
 186        case NVKM_ENGINE_MSPPP : context = 0x00200000; break;
 187        case NVKM_ENGINE_ME    :
 188        case NVKM_ENGINE_CE0   : context = 0x00300000; break;
 189        case NVKM_ENGINE_VP    :
 190        case NVKM_ENGINE_MSPDEC: context = 0x00400000; break;
 191        case NVKM_ENGINE_CIPHER:
 192        case NVKM_ENGINE_SEC   :
 193        case NVKM_ENGINE_VIC   : context = 0x00500000; break;
 194        case NVKM_ENGINE_BSP   :
 195        case NVKM_ENGINE_MSVLD : context = 0x00600000; break;
 196        default:
 197                WARN_ON(1);
 198                return -EINVAL;
 199        }
 200
 201        return nvkm_ramht_insert(chan->ramht, object, 0, 4, handle, context);
 202}
 203
 204static void
 205g84_fifo_chan_init(struct nvkm_fifo_chan *base)
 206{
 207        struct nv50_fifo_chan *chan = nv50_fifo_chan(base);
 208        struct nv50_fifo *fifo = chan->fifo;
 209        struct nvkm_device *device = fifo->base.engine.subdev.device;
 210        u64 addr = chan->ramfc->addr >> 8;
 211        u32 chid = chan->base.chid;
 212
 213        nvkm_wr32(device, 0x002600 + (chid * 4), 0x80000000 | addr);
 214        nv50_fifo_runlist_update(fifo);
 215}
 216
 217static const struct nvkm_fifo_chan_func
 218g84_fifo_chan_func = {
 219        .dtor = nv50_fifo_chan_dtor,
 220        .init = g84_fifo_chan_init,
 221        .fini = nv50_fifo_chan_fini,
 222        .ntfy = g84_fifo_chan_ntfy,
 223        .engine_ctor = g84_fifo_chan_engine_ctor,
 224        .engine_dtor = nv50_fifo_chan_engine_dtor,
 225        .engine_init = g84_fifo_chan_engine_init,
 226        .engine_fini = g84_fifo_chan_engine_fini,
 227        .object_ctor = g84_fifo_chan_object_ctor,
 228        .object_dtor = nv50_fifo_chan_object_dtor,
 229};
 230
 231int
 232g84_fifo_chan_ctor(struct nv50_fifo *fifo, u64 vm, u64 push,
 233                   const struct nvkm_oclass *oclass,
 234                   struct nv50_fifo_chan *chan)
 235{
 236        struct nvkm_device *device = fifo->base.engine.subdev.device;
 237        int ret;
 238
 239        ret = nvkm_fifo_chan_ctor(&g84_fifo_chan_func, &fifo->base,
 240                                  0x10000, 0x1000, false, vm, push,
 241                                  (1ULL << NVKM_ENGINE_BSP) |
 242                                  (1ULL << NVKM_ENGINE_CE0) |
 243                                  (1ULL << NVKM_ENGINE_CIPHER) |
 244                                  (1ULL << NVKM_ENGINE_DMAOBJ) |
 245                                  (1ULL << NVKM_ENGINE_GR) |
 246                                  (1ULL << NVKM_ENGINE_ME) |
 247                                  (1ULL << NVKM_ENGINE_MPEG) |
 248                                  (1ULL << NVKM_ENGINE_MSPDEC) |
 249                                  (1ULL << NVKM_ENGINE_MSPPP) |
 250                                  (1ULL << NVKM_ENGINE_MSVLD) |
 251                                  (1ULL << NVKM_ENGINE_SEC) |
 252                                  (1ULL << NVKM_ENGINE_SW) |
 253                                  (1ULL << NVKM_ENGINE_VIC) |
 254                                  (1ULL << NVKM_ENGINE_VP),
 255                                  0, 0xc00000, 0x2000, oclass, &chan->base);
 256        chan->fifo = fifo;
 257        if (ret)
 258                return ret;
 259
 260        ret = nvkm_gpuobj_new(device, 0x0200, 0, true, chan->base.inst,
 261                              &chan->eng);
 262        if (ret)
 263                return ret;
 264
 265        ret = nvkm_gpuobj_new(device, 0x4000, 0, false, chan->base.inst,
 266                              &chan->pgd);
 267        if (ret)
 268                return ret;
 269
 270        ret = nvkm_gpuobj_new(device, 0x1000, 0x400, true, chan->base.inst,
 271                              &chan->cache);
 272        if (ret)
 273                return ret;
 274
 275        ret = nvkm_gpuobj_new(device, 0x100, 0x100, true, chan->base.inst,
 276                              &chan->ramfc);
 277        if (ret)
 278                return ret;
 279
 280        ret = nvkm_ramht_new(device, 0x8000, 16, chan->base.inst, &chan->ramht);
 281        if (ret)
 282                return ret;
 283
 284        return nvkm_vm_ref(chan->base.vm, &chan->vm, chan->pgd);
 285}
 286