119fef52dSBen Skeggs /*
219fef52dSBen Skeggs * Copyright 2012 Red Hat Inc.
319fef52dSBen Skeggs *
419fef52dSBen Skeggs * Permission is hereby granted, free of charge, to any person obtaining a
519fef52dSBen Skeggs * copy of this software and associated documentation files (the "Software"),
619fef52dSBen Skeggs * to deal in the Software without restriction, including without limitation
719fef52dSBen Skeggs * the rights to use, copy, modify, merge, publish, distribute, sublicense,
819fef52dSBen Skeggs * and/or sell copies of the Software, and to permit persons to whom the
919fef52dSBen Skeggs * Software is furnished to do so, subject to the following conditions:
1019fef52dSBen Skeggs *
1119fef52dSBen Skeggs * The above copyright notice and this permission notice shall be included in
1219fef52dSBen Skeggs * all copies or substantial portions of the Software.
1319fef52dSBen Skeggs *
1419fef52dSBen Skeggs * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1519fef52dSBen Skeggs * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1619fef52dSBen Skeggs * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
1719fef52dSBen Skeggs * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
1819fef52dSBen Skeggs * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
1919fef52dSBen Skeggs * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
2019fef52dSBen Skeggs * OTHER DEALINGS IN THE SOFTWARE.
2119fef52dSBen Skeggs *
2219fef52dSBen Skeggs * Authors: Ben Skeggs
2319fef52dSBen Skeggs */
240710cc31SBen Skeggs #define gf100_dmaobj(p) container_of((p), struct gf100_dmaobj, base)
2519fef52dSBen Skeggs #include "user.h"
2619fef52dSBen Skeggs
2719fef52dSBen Skeggs #include <core/client.h>
2819fef52dSBen Skeggs #include <core/gpuobj.h>
2919fef52dSBen Skeggs #include <subdev/fb.h>
3019fef52dSBen Skeggs
31845f2725SBen Skeggs #include <nvif/cl0002.h>
3219fef52dSBen Skeggs #include <nvif/unpack.h>
3319fef52dSBen Skeggs
3419fef52dSBen Skeggs struct gf100_dmaobj {
3519fef52dSBen Skeggs struct nvkm_dmaobj base;
3619fef52dSBen Skeggs u32 flags0;
3719fef52dSBen Skeggs u32 flags5;
3819fef52dSBen Skeggs };
3919fef52dSBen Skeggs
400710cc31SBen Skeggs static int
gf100_dmaobj_bind(struct nvkm_dmaobj * base,struct nvkm_gpuobj * parent,int align,struct nvkm_gpuobj ** pgpuobj)410710cc31SBen Skeggs gf100_dmaobj_bind(struct nvkm_dmaobj *base, struct nvkm_gpuobj *parent,
420710cc31SBen Skeggs int align, struct nvkm_gpuobj **pgpuobj)
4319fef52dSBen Skeggs {
440710cc31SBen Skeggs struct gf100_dmaobj *dmaobj = gf100_dmaobj(base);
450710cc31SBen Skeggs struct nvkm_device *device = dmaobj->base.dma->engine.subdev.device;
4619fef52dSBen Skeggs int ret;
4719fef52dSBen Skeggs
480710cc31SBen Skeggs ret = nvkm_gpuobj_new(device, 24, align, false, parent, pgpuobj);
4919fef52dSBen Skeggs if (ret == 0) {
5019fef52dSBen Skeggs nvkm_kmap(*pgpuobj);
510710cc31SBen Skeggs nvkm_wo32(*pgpuobj, 0x00, dmaobj->flags0);
5219fef52dSBen Skeggs nvkm_wo32(*pgpuobj, 0x04, lower_32_bits(dmaobj->base.limit));
5319fef52dSBen Skeggs nvkm_wo32(*pgpuobj, 0x08, lower_32_bits(dmaobj->base.start));
5419fef52dSBen Skeggs nvkm_wo32(*pgpuobj, 0x0c, upper_32_bits(dmaobj->base.limit) << 24 |
5519fef52dSBen Skeggs upper_32_bits(dmaobj->base.start));
5619fef52dSBen Skeggs nvkm_wo32(*pgpuobj, 0x10, 0x00000000);
5719fef52dSBen Skeggs nvkm_wo32(*pgpuobj, 0x14, dmaobj->flags5);
5819fef52dSBen Skeggs nvkm_done(*pgpuobj);
5919fef52dSBen Skeggs }
6019fef52dSBen Skeggs
6119fef52dSBen Skeggs return ret;
6219fef52dSBen Skeggs }
6319fef52dSBen Skeggs
640710cc31SBen Skeggs static const struct nvkm_dmaobj_func
650710cc31SBen Skeggs gf100_dmaobj_func = {
660710cc31SBen Skeggs .bind = gf100_dmaobj_bind,
670710cc31SBen Skeggs };
680710cc31SBen Skeggs
690710cc31SBen Skeggs int
gf100_dmaobj_new(struct nvkm_dma * dma,const struct nvkm_oclass * oclass,void * data,u32 size,struct nvkm_dmaobj ** pdmaobj)700710cc31SBen Skeggs gf100_dmaobj_new(struct nvkm_dma *dma, const struct nvkm_oclass *oclass,
710710cc31SBen Skeggs void *data, u32 size, struct nvkm_dmaobj **pdmaobj)
7219fef52dSBen Skeggs {
7319fef52dSBen Skeggs union {
7419fef52dSBen Skeggs struct gf100_dma_v0 v0;
7519fef52dSBen Skeggs } *args;
760710cc31SBen Skeggs struct nvkm_object *parent = oclass->parent;
7719fef52dSBen Skeggs struct gf100_dmaobj *dmaobj;
7819fef52dSBen Skeggs u32 kind, user, unkn;
7919fef52dSBen Skeggs int ret;
8019fef52dSBen Skeggs
810710cc31SBen Skeggs if (!(dmaobj = kzalloc(sizeof(*dmaobj), GFP_KERNEL)))
820710cc31SBen Skeggs return -ENOMEM;
830710cc31SBen Skeggs *pdmaobj = &dmaobj->base;
840710cc31SBen Skeggs
850710cc31SBen Skeggs ret = nvkm_dmaobj_ctor(&gf100_dmaobj_func, dma, oclass,
860710cc31SBen Skeggs &data, &size, &dmaobj->base);
8719fef52dSBen Skeggs if (ret)
8819fef52dSBen Skeggs return ret;
890710cc31SBen Skeggs
90*f01c4e68SBen Skeggs ret = -ENOSYS;
9119fef52dSBen Skeggs args = data;
9219fef52dSBen Skeggs
9319fef52dSBen Skeggs nvif_ioctl(parent, "create gf100 dma size %d\n", size);
94*f01c4e68SBen Skeggs if (!(ret = nvif_unpack(ret, &data, &size, args->v0, 0, 0, false))) {
9519fef52dSBen Skeggs nvif_ioctl(parent,
9619fef52dSBen Skeggs "create gf100 dma vers %d priv %d kind %02x\n",
9719fef52dSBen Skeggs args->v0.version, args->v0.priv, args->v0.kind);
9819fef52dSBen Skeggs kind = args->v0.kind;
9919fef52dSBen Skeggs user = args->v0.priv;
10019fef52dSBen Skeggs unkn = 0;
10119fef52dSBen Skeggs } else
10219fef52dSBen Skeggs if (size == 0) {
10319fef52dSBen Skeggs if (dmaobj->base.target != NV_MEM_TARGET_VM) {
10419fef52dSBen Skeggs kind = GF100_DMA_V0_KIND_PITCH;
10519fef52dSBen Skeggs user = GF100_DMA_V0_PRIV_US;
10619fef52dSBen Skeggs unkn = 2;
10719fef52dSBen Skeggs } else {
10819fef52dSBen Skeggs kind = GF100_DMA_V0_KIND_VM;
10919fef52dSBen Skeggs user = GF100_DMA_V0_PRIV_VM;
11019fef52dSBen Skeggs unkn = 0;
11119fef52dSBen Skeggs }
11219fef52dSBen Skeggs } else
11319fef52dSBen Skeggs return ret;
11419fef52dSBen Skeggs
11519fef52dSBen Skeggs if (user > 2)
11619fef52dSBen Skeggs return -EINVAL;
1170710cc31SBen Skeggs dmaobj->flags0 |= (kind << 22) | (user << 20) | oclass->base.oclass;
11819fef52dSBen Skeggs dmaobj->flags5 |= (unkn << 16);
11919fef52dSBen Skeggs
12019fef52dSBen Skeggs switch (dmaobj->base.target) {
12119fef52dSBen Skeggs case NV_MEM_TARGET_VM:
12219fef52dSBen Skeggs dmaobj->flags0 |= 0x00000000;
12319fef52dSBen Skeggs break;
12419fef52dSBen Skeggs case NV_MEM_TARGET_VRAM:
12519fef52dSBen Skeggs dmaobj->flags0 |= 0x00010000;
12619fef52dSBen Skeggs break;
12719fef52dSBen Skeggs case NV_MEM_TARGET_PCI:
12819fef52dSBen Skeggs dmaobj->flags0 |= 0x00020000;
12919fef52dSBen Skeggs break;
13019fef52dSBen Skeggs case NV_MEM_TARGET_PCI_NOSNOOP:
13119fef52dSBen Skeggs dmaobj->flags0 |= 0x00030000;
13219fef52dSBen Skeggs break;
13319fef52dSBen Skeggs default:
13419fef52dSBen Skeggs return -EINVAL;
13519fef52dSBen Skeggs }
13619fef52dSBen Skeggs
13719fef52dSBen Skeggs switch (dmaobj->base.access) {
13819fef52dSBen Skeggs case NV_MEM_ACCESS_VM:
13919fef52dSBen Skeggs break;
14019fef52dSBen Skeggs case NV_MEM_ACCESS_RO:
14119fef52dSBen Skeggs dmaobj->flags0 |= 0x00040000;
14219fef52dSBen Skeggs break;
14319fef52dSBen Skeggs case NV_MEM_ACCESS_WO:
14419fef52dSBen Skeggs case NV_MEM_ACCESS_RW:
14519fef52dSBen Skeggs dmaobj->flags0 |= 0x00080000;
14619fef52dSBen Skeggs break;
14719fef52dSBen Skeggs }
14819fef52dSBen Skeggs
1490710cc31SBen Skeggs return 0;
15019fef52dSBen Skeggs }
151