xref: /linux/drivers/gpu/drm/nouveau/nvkm/engine/dma/usergf100.c (revision 9938b04472d5c59f8bd8152a548533a8599596a2)
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