Commit | Line | Data |
---|---|---|
ebb945a9 BS |
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 | */ | |
0710cc31 | 24 | #define nv04_dmaobj(p) container_of((p), struct nv04_dmaobj, base) |
19fef52d | 25 | #include "user.h" |
ebb945a9 BS |
26 | |
27 | #include <core/gpuobj.h> | |
ebb945a9 | 28 | #include <subdev/fb.h> |
5ce3bf3c | 29 | #include <subdev/mmu/nv04.h> |
ebb945a9 | 30 | |
5b85057a | 31 | #include <nvif/class.h> |
ebb945a9 | 32 | |
a317aa21 | 33 | struct nv04_dmaobj { |
5b85057a | 34 | struct nvkm_dmaobj base; |
b2c81703 BS |
35 | bool clone; |
36 | u32 flags0; | |
37 | u32 flags2; | |
38 | }; | |
39 | ||
0710cc31 BS |
40 | static int |
41 | nv04_dmaobj_bind(struct nvkm_dmaobj *base, struct nvkm_gpuobj *parent, | |
42 | int align, struct nvkm_gpuobj **pgpuobj) | |
ebb945a9 | 43 | { |
0710cc31 BS |
44 | struct nv04_dmaobj *dmaobj = nv04_dmaobj(base); |
45 | struct nvkm_device *device = dmaobj->base.dma->engine.subdev.device; | |
a317aa21 BS |
46 | u64 offset = dmaobj->base.start & 0xfffff000; |
47 | u64 adjust = dmaobj->base.start & 0x00000fff; | |
48 | u32 length = dmaobj->base.limit - dmaobj->base.start; | |
ebb945a9 BS |
49 | int ret; |
50 | ||
a317aa21 | 51 | if (dmaobj->clone) { |
0710cc31 | 52 | struct nv04_mmu *mmu = nv04_mmu(device->mmu); |
d0659d32 | 53 | struct nvkm_memory *pgt = mmu->vm->pgt[0].mem[0]; |
a317aa21 | 54 | if (!dmaobj->base.start) |
f027f491 | 55 | return nvkm_gpuobj_wrap(pgt, pgpuobj); |
3f532ef1 BS |
56 | nvkm_kmap(pgt); |
57 | offset = nvkm_ro32(pgt, 8 + (offset >> 10)); | |
b2c81703 | 58 | offset &= 0xfffff000; |
3f532ef1 | 59 | nvkm_done(pgt); |
b2c81703 BS |
60 | } |
61 | ||
0710cc31 | 62 | ret = nvkm_gpuobj_new(device, 16, align, false, parent, pgpuobj); |
b2c81703 | 63 | if (ret == 0) { |
3f532ef1 BS |
64 | nvkm_kmap(*pgpuobj); |
65 | nvkm_wo32(*pgpuobj, 0x00, dmaobj->flags0 | (adjust << 20)); | |
66 | nvkm_wo32(*pgpuobj, 0x04, length); | |
67 | nvkm_wo32(*pgpuobj, 0x08, dmaobj->flags2 | offset); | |
68 | nvkm_wo32(*pgpuobj, 0x0c, dmaobj->flags2 | offset); | |
69 | nvkm_done(*pgpuobj); | |
b2c81703 BS |
70 | } |
71 | ||
72 | return ret; | |
73 | } | |
74 | ||
0710cc31 BS |
75 | static const struct nvkm_dmaobj_func |
76 | nv04_dmaobj_func = { | |
77 | .bind = nv04_dmaobj_bind, | |
78 | }; | |
79 | ||
80 | int | |
81 | nv04_dmaobj_new(struct nvkm_dma *dma, const struct nvkm_oclass *oclass, | |
82 | void *data, u32 size, struct nvkm_dmaobj **pdmaobj) | |
b2c81703 | 83 | { |
c9582455 | 84 | struct nvkm_device *device = dma->engine.subdev.device; |
a317aa21 | 85 | struct nv04_dmaobj *dmaobj; |
b2c81703 BS |
86 | int ret; |
87 | ||
0710cc31 BS |
88 | if (!(dmaobj = kzalloc(sizeof(*dmaobj), GFP_KERNEL))) |
89 | return -ENOMEM; | |
90 | *pdmaobj = &dmaobj->base; | |
91 | ||
92 | ret = nvkm_dmaobj_ctor(&nv04_dmaobj_func, dma, oclass, | |
93 | &data, &size, &dmaobj->base); | |
94 | if (ret) | |
b2c81703 | 95 | return ret; |
ebb945a9 | 96 | |
a317aa21 | 97 | if (dmaobj->base.target == NV_MEM_TARGET_VM) { |
c9582455 | 98 | if (device->mmu->func == &nv04_mmu) |
a317aa21 BS |
99 | dmaobj->clone = true; |
100 | dmaobj->base.target = NV_MEM_TARGET_PCI; | |
101 | dmaobj->base.access = NV_MEM_ACCESS_RW; | |
ebb945a9 BS |
102 | } |
103 | ||
0710cc31 | 104 | dmaobj->flags0 = oclass->base.oclass; |
a317aa21 | 105 | switch (dmaobj->base.target) { |
ebb945a9 | 106 | case NV_MEM_TARGET_VRAM: |
a317aa21 | 107 | dmaobj->flags0 |= 0x00003000; |
ebb945a9 BS |
108 | break; |
109 | case NV_MEM_TARGET_PCI: | |
a317aa21 | 110 | dmaobj->flags0 |= 0x00023000; |
ebb945a9 BS |
111 | break; |
112 | case NV_MEM_TARGET_PCI_NOSNOOP: | |
a317aa21 | 113 | dmaobj->flags0 |= 0x00033000; |
ebb945a9 BS |
114 | break; |
115 | default: | |
116 | return -EINVAL; | |
117 | } | |
118 | ||
a317aa21 | 119 | switch (dmaobj->base.access) { |
ebb945a9 | 120 | case NV_MEM_ACCESS_RO: |
a317aa21 | 121 | dmaobj->flags0 |= 0x00004000; |
ebb945a9 BS |
122 | break; |
123 | case NV_MEM_ACCESS_WO: | |
a317aa21 | 124 | dmaobj->flags0 |= 0x00008000; |
ebb945a9 | 125 | case NV_MEM_ACCESS_RW: |
a317aa21 | 126 | dmaobj->flags2 |= 0x00000002; |
ebb945a9 BS |
127 | break; |
128 | default: | |
129 | return -EINVAL; | |
130 | } | |
131 | ||
0710cc31 | 132 | return 0; |
ebb945a9 | 133 | } |