nouveau_nvkm_engine_dma_usernv50.c revision 1.1
1/*	$NetBSD: nouveau_nvkm_engine_dma_usernv50.c,v 1.1 2018/08/27 01:34:56 riastradh Exp $	*/
2
3/*
4 * Copyright 2012 Red Hat Inc.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the "Software"),
8 * to deal in the Software without restriction, including without limitation
9 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10 * and/or sell copies of the Software, and to permit persons to whom the
11 * Software is furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
19 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
20 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
21 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22 * OTHER DEALINGS IN THE SOFTWARE.
23 *
24 * Authors: Ben Skeggs
25 */
26#include <sys/cdefs.h>
27__KERNEL_RCSID(0, "$NetBSD: nouveau_nvkm_engine_dma_usernv50.c,v 1.1 2018/08/27 01:34:56 riastradh Exp $");
28
29#define nv50_dmaobj(p) container_of((p), struct nv50_dmaobj, base)
30#include "user.h"
31
32#include <core/client.h>
33#include <core/gpuobj.h>
34#include <subdev/fb.h>
35
36#include <nvif/class.h>
37#include <nvif/unpack.h>
38
39struct nv50_dmaobj {
40	struct nvkm_dmaobj base;
41	u32 flags0;
42	u32 flags5;
43};
44
45static int
46nv50_dmaobj_bind(struct nvkm_dmaobj *base, struct nvkm_gpuobj *parent,
47		 int align, struct nvkm_gpuobj **pgpuobj)
48{
49	struct nv50_dmaobj *dmaobj = nv50_dmaobj(base);
50	struct nvkm_device *device = dmaobj->base.dma->engine.subdev.device;
51	int ret;
52
53	ret = nvkm_gpuobj_new(device, 24, align, false, parent, pgpuobj);
54	if (ret == 0) {
55		nvkm_kmap(*pgpuobj);
56		nvkm_wo32(*pgpuobj, 0x00, dmaobj->flags0);
57		nvkm_wo32(*pgpuobj, 0x04, lower_32_bits(dmaobj->base.limit));
58		nvkm_wo32(*pgpuobj, 0x08, lower_32_bits(dmaobj->base.start));
59		nvkm_wo32(*pgpuobj, 0x0c, upper_32_bits(dmaobj->base.limit) << 24 |
60					  upper_32_bits(dmaobj->base.start));
61		nvkm_wo32(*pgpuobj, 0x10, 0x00000000);
62		nvkm_wo32(*pgpuobj, 0x14, dmaobj->flags5);
63		nvkm_done(*pgpuobj);
64	}
65
66	return ret;
67}
68
69static const struct nvkm_dmaobj_func
70nv50_dmaobj_func = {
71	.bind = nv50_dmaobj_bind,
72};
73
74int
75nv50_dmaobj_new(struct nvkm_dma *dma, const struct nvkm_oclass *oclass,
76		void *data, u32 size, struct nvkm_dmaobj **pdmaobj)
77{
78	union {
79		struct nv50_dma_v0 v0;
80	} *args;
81	struct nvkm_object *parent = oclass->parent;
82	struct nv50_dmaobj *dmaobj;
83	u32 user, part, comp, kind;
84	int ret;
85
86	if (!(dmaobj = kzalloc(sizeof(*dmaobj), GFP_KERNEL)))
87		return -ENOMEM;
88	*pdmaobj = &dmaobj->base;
89
90	ret = nvkm_dmaobj_ctor(&nv50_dmaobj_func, dma, oclass,
91			       &data, &size, &dmaobj->base);
92	if (ret)
93		return ret;
94
95	args = data;
96
97	nvif_ioctl(parent, "create nv50 dma size %d\n", size);
98	if (nvif_unpack(args->v0, 0, 0, false)) {
99		nvif_ioctl(parent, "create nv50 dma vers %d priv %d part %d "
100				   "comp %d kind %02x\n", args->v0.version,
101			   args->v0.priv, args->v0.part, args->v0.comp,
102			   args->v0.kind);
103		user = args->v0.priv;
104		part = args->v0.part;
105		comp = args->v0.comp;
106		kind = args->v0.kind;
107	} else
108	if (size == 0) {
109		if (dmaobj->base.target != NV_MEM_TARGET_VM) {
110			user = NV50_DMA_V0_PRIV_US;
111			part = NV50_DMA_V0_PART_256;
112			comp = NV50_DMA_V0_COMP_NONE;
113			kind = NV50_DMA_V0_KIND_PITCH;
114		} else {
115			user = NV50_DMA_V0_PRIV_VM;
116			part = NV50_DMA_V0_PART_VM;
117			comp = NV50_DMA_V0_COMP_VM;
118			kind = NV50_DMA_V0_KIND_VM;
119		}
120	} else
121		return ret;
122
123	if (user > 2 || part > 2 || comp > 3 || kind > 0x7f)
124		return -EINVAL;
125	dmaobj->flags0 = (comp << 29) | (kind << 22) | (user << 20) |
126			 oclass->base.oclass;
127	dmaobj->flags5 = (part << 16);
128
129	switch (dmaobj->base.target) {
130	case NV_MEM_TARGET_VM:
131		dmaobj->flags0 |= 0x00000000;
132		break;
133	case NV_MEM_TARGET_VRAM:
134		dmaobj->flags0 |= 0x00010000;
135		break;
136	case NV_MEM_TARGET_PCI:
137		dmaobj->flags0 |= 0x00020000;
138		break;
139	case NV_MEM_TARGET_PCI_NOSNOOP:
140		dmaobj->flags0 |= 0x00030000;
141		break;
142	default:
143		return -EINVAL;
144	}
145
146	switch (dmaobj->base.access) {
147	case NV_MEM_ACCESS_VM:
148		break;
149	case NV_MEM_ACCESS_RO:
150		dmaobj->flags0 |= 0x00040000;
151		break;
152	case NV_MEM_ACCESS_WO:
153	case NV_MEM_ACCESS_RW:
154		dmaobj->flags0 |= 0x00080000;
155		break;
156	default:
157		return -EINVAL;
158	}
159
160	return 0;
161}
162