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 25#include <core/client.h> 26#include <nvif/unpack.h> 27#include <nvif/class.h> 28#include <core/engctx.h> 29#include <core/ramht.h> 30 31#include <subdev/instmem.h> 32#include <subdev/instmem/nv04.h> 33#include <subdev/fb.h> 34 35#include <engine/fifo.h> 36 37#include "nv04.h" 38 39static struct ramfc_desc 40nv10_ramfc[] = { 41 { 32, 0, 0x00, 0, NV04_PFIFO_CACHE1_DMA_PUT }, 42 { 32, 0, 0x04, 0, NV04_PFIFO_CACHE1_DMA_GET }, 43 { 32, 0, 0x08, 0, NV10_PFIFO_CACHE1_REF_CNT }, 44 { 16, 0, 0x0c, 0, NV04_PFIFO_CACHE1_DMA_INSTANCE }, 45 { 16, 16, 0x0c, 0, NV04_PFIFO_CACHE1_DMA_DCOUNT }, 46 { 32, 0, 0x10, 0, NV04_PFIFO_CACHE1_DMA_STATE }, 47 { 32, 0, 0x14, 0, NV04_PFIFO_CACHE1_DMA_FETCH }, 48 { 32, 0, 0x18, 0, NV04_PFIFO_CACHE1_ENGINE }, 49 { 32, 0, 0x1c, 0, NV04_PFIFO_CACHE1_PULL1 }, 50 {} 51}; 52 53/******************************************************************************* 54 * FIFO channel objects 55 ******************************************************************************/ 56 57static int 58nv10_fifo_chan_ctor(struct nouveau_object *parent, 59 struct nouveau_object *engine, 60 struct nouveau_oclass *oclass, void *data, u32 size, 61 struct nouveau_object **pobject) 62{ 63 union { 64 struct nv03_channel_dma_v0 v0; 65 } *args = data; 66 struct nv04_fifo_priv *priv = (void *)engine; 67 struct nv04_fifo_chan *chan; 68 int ret; 69 70 nv_ioctl(parent, "create channel dma size %d\n", size); 71 if (nvif_unpack(args->v0, 0, 0, false)) { 72 nv_ioctl(parent, "create channel dma vers %d pushbuf %08x " 73 "offset %016llx\n", args->v0.version, 74 args->v0.pushbuf, args->v0.offset); 75 } else 76 return ret; 77 78 ret = nouveau_fifo_channel_create(parent, engine, oclass, 0, 0x800000, 79 0x10000, args->v0.pushbuf, 80 (1ULL << NVDEV_ENGINE_DMAOBJ) | 81 (1ULL << NVDEV_ENGINE_SW) | 82 (1ULL << NVDEV_ENGINE_GR), &chan); 83 *pobject = nv_object(chan); 84 if (ret) 85 return ret; 86 87 args->v0.chid = chan->base.chid; 88 89 nv_parent(chan)->object_attach = nv04_fifo_object_attach; 90 nv_parent(chan)->object_detach = nv04_fifo_object_detach; 91 nv_parent(chan)->context_attach = nv04_fifo_context_attach; 92 chan->ramfc = chan->base.chid * 32; 93 94 nv_wo32(priv->ramfc, chan->ramfc + 0x00, args->v0.offset); 95 nv_wo32(priv->ramfc, chan->ramfc + 0x04, args->v0.offset); 96 nv_wo32(priv->ramfc, chan->ramfc + 0x0c, chan->base.pushgpu->addr >> 4); 97 nv_wo32(priv->ramfc, chan->ramfc + 0x14, 98 NV_PFIFO_CACHE1_DMA_FETCH_TRIG_128_BYTES | 99 NV_PFIFO_CACHE1_DMA_FETCH_SIZE_128_BYTES | 100#ifdef __BIG_ENDIAN 101 NV_PFIFO_CACHE1_BIG_ENDIAN | 102#endif 103 NV_PFIFO_CACHE1_DMA_FETCH_MAX_REQS_8); 104 return 0; 105} 106 107static struct nouveau_ofuncs 108nv10_fifo_ofuncs = { 109 .ctor = nv10_fifo_chan_ctor, 110 .dtor = nv04_fifo_chan_dtor, 111 .init = nv04_fifo_chan_init, 112 .fini = nv04_fifo_chan_fini, 113 .map = _nouveau_fifo_channel_map, 114 .rd32 = _nouveau_fifo_channel_rd32, 115 .wr32 = _nouveau_fifo_channel_wr32, 116 .ntfy = _nouveau_fifo_channel_ntfy 117}; 118 119static struct nouveau_oclass 120nv10_fifo_sclass[] = { 121 { NV10_CHANNEL_DMA, &nv10_fifo_ofuncs }, 122 {} 123}; 124 125/******************************************************************************* 126 * FIFO context - basically just the instmem reserved for the channel 127 ******************************************************************************/ 128 129static struct nouveau_oclass 130nv10_fifo_cclass = { 131 .handle = NV_ENGCTX(FIFO, 0x10), 132 .ofuncs = &(struct nouveau_ofuncs) { 133 .ctor = nv04_fifo_context_ctor, 134 .dtor = _nouveau_fifo_context_dtor, 135 .init = _nouveau_fifo_context_init, 136 .fini = _nouveau_fifo_context_fini, 137 .rd32 = _nouveau_fifo_context_rd32, 138 .wr32 = _nouveau_fifo_context_wr32, 139 }, 140}; 141 142/******************************************************************************* 143 * PFIFO engine 144 ******************************************************************************/ 145 146static int 147nv10_fifo_ctor(struct nouveau_object *parent, struct nouveau_object *engine, 148 struct nouveau_oclass *oclass, void *data, u32 size, 149 struct nouveau_object **pobject) 150{ 151 struct nv04_instmem_priv *imem = nv04_instmem(parent); 152 struct nv04_fifo_priv *priv; 153 int ret; 154 155 ret = nouveau_fifo_create(parent, engine, oclass, 0, 31, &priv); 156 *pobject = nv_object(priv); 157 if (ret) 158 return ret; 159 160 nouveau_ramht_ref(imem->ramht, &priv->ramht); 161 nouveau_gpuobj_ref(imem->ramro, &priv->ramro); 162 nouveau_gpuobj_ref(imem->ramfc, &priv->ramfc); 163 164 nv_subdev(priv)->unit = 0x00000100; 165 nv_subdev(priv)->intr = nv04_fifo_intr; 166 nv_engine(priv)->cclass = &nv10_fifo_cclass; 167 nv_engine(priv)->sclass = nv10_fifo_sclass; 168 priv->base.pause = nv04_fifo_pause; 169 priv->base.start = nv04_fifo_start; 170 priv->ramfc_desc = nv10_ramfc; 171 return 0; 172} 173 174struct nouveau_oclass * 175nv10_fifo_oclass = &(struct nouveau_oclass) { 176 .handle = NV_ENGINE(FIFO, 0x10), 177 .ofuncs = &(struct nouveau_ofuncs) { 178 .ctor = nv10_fifo_ctor, 179 .dtor = nv04_fifo_dtor, 180 .init = nv04_fifo_init, 181 .fini = _nouveau_fifo_fini, 182 }, 183}; 184