Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
nv04.c
Go to the documentation of this file.
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/gpuobj.h>
26 #include <core/class.h>
27 
28 #include <subdev/fb.h>
29 #include <subdev/vm/nv04.h>
30 
31 #include <engine/dmaobj.h>
32 
35 };
36 
39 };
40 
41 static int
42 nv04_dmaobj_bind(struct nouveau_dmaeng *dmaeng,
43  struct nouveau_object *parent,
44  struct nouveau_dmaobj *dmaobj,
45  struct nouveau_gpuobj **pgpuobj)
46 {
47  struct nv04_vmmgr_priv *vmm = nv04_vmmgr(dmaeng);
48  struct nouveau_gpuobj *gpuobj;
49  u32 flags0 = nv_mclass(dmaobj);
50  u32 flags2 = 0x00000000;
51  u64 offset = dmaobj->start & 0xfffff000;
52  u64 adjust = dmaobj->start & 0x00000fff;
53  u32 length = dmaobj->limit - dmaobj->start;
54  int ret;
55 
56  if (dmaobj->target == NV_MEM_TARGET_VM) {
57  if (nv_object(vmm)->oclass == &nv04_vmmgr_oclass) {
58  struct nouveau_gpuobj *pgt = vmm->vm->pgt[0].obj[0];
59  if (!dmaobj->start)
60  return nouveau_gpuobj_dup(parent, pgt, pgpuobj);
61  offset = nv_ro32(pgt, 8 + (offset >> 10));
62  offset &= 0xfffff000;
63  }
64 
65  dmaobj->target = NV_MEM_TARGET_PCI;
66  dmaobj->access = NV_MEM_ACCESS_RW;
67  }
68 
69  switch (dmaobj->target) {
70  case NV_MEM_TARGET_VRAM:
71  flags0 |= 0x00003000;
72  break;
73  case NV_MEM_TARGET_PCI:
74  flags0 |= 0x00023000;
75  break;
77  flags0 |= 0x00033000;
78  break;
79  default:
80  return -EINVAL;
81  }
82 
83  switch (dmaobj->access) {
84  case NV_MEM_ACCESS_RO:
85  flags0 |= 0x00004000;
86  break;
87  case NV_MEM_ACCESS_WO:
88  flags0 |= 0x00008000;
89  case NV_MEM_ACCESS_RW:
90  flags2 |= 0x00000002;
91  break;
92  default:
93  return -EINVAL;
94  }
95 
96  ret = nouveau_gpuobj_new(parent, parent, 16, 16, 0, &gpuobj);
97  *pgpuobj = gpuobj;
98  if (ret == 0) {
99  nv_wo32(*pgpuobj, 0x00, flags0 | (adjust << 20));
100  nv_wo32(*pgpuobj, 0x04, length);
101  nv_wo32(*pgpuobj, 0x08, flags2 | offset);
102  nv_wo32(*pgpuobj, 0x0c, flags2 | offset);
103  }
104 
105  return ret;
106 }
107 
108 static int
109 nv04_dmaobj_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
110  struct nouveau_oclass *oclass, void *data, u32 size,
111  struct nouveau_object **pobject)
112 {
113  struct nouveau_dmaeng *dmaeng = (void *)engine;
114  struct nv04_dmaobj_priv *dmaobj;
115  struct nouveau_gpuobj *gpuobj;
116  int ret;
117 
118  ret = nouveau_dmaobj_create(parent, engine, oclass,
119  data, size, &dmaobj);
120  *pobject = nv_object(dmaobj);
121  if (ret)
122  return ret;
123 
124  switch (nv_mclass(parent)) {
125  case NV_DEVICE_CLASS:
126  break;
131  ret = dmaeng->bind(dmaeng, *pobject, &dmaobj->base, &gpuobj);
132  nouveau_object_ref(NULL, pobject);
133  *pobject = nv_object(gpuobj);
134  break;
135  default:
136  return -EINVAL;
137  }
138 
139  return ret;
140 }
141 
142 static struct nouveau_ofuncs
143 nv04_dmaobj_ofuncs = {
144  .ctor = nv04_dmaobj_ctor,
145  .dtor = _nouveau_dmaobj_dtor,
146  .init = _nouveau_dmaobj_init,
147  .fini = _nouveau_dmaobj_fini,
148 };
149 
150 static struct nouveau_oclass
151 nv04_dmaobj_sclass[] = {
152  { 0x0002, &nv04_dmaobj_ofuncs },
153  { 0x0003, &nv04_dmaobj_ofuncs },
154  { 0x003d, &nv04_dmaobj_ofuncs },
155  {}
156 };
157 
158 static int
159 nv04_dmaeng_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
160  struct nouveau_oclass *oclass, void *data, u32 size,
161  struct nouveau_object **pobject)
162 {
163  struct nv04_dmaeng_priv *priv;
164  int ret;
165 
166  ret = nouveau_dmaeng_create(parent, engine, oclass, &priv);
167  *pobject = nv_object(priv);
168  if (ret)
169  return ret;
170 
171  priv->base.base.sclass = nv04_dmaobj_sclass;
172  priv->base.bind = nv04_dmaobj_bind;
173  return 0;
174 }
175 
176 struct nouveau_oclass
178  .handle = NV_ENGINE(DMAOBJ, 0x04),
179  .ofuncs = &(struct nouveau_ofuncs) {
180  .ctor = nv04_dmaeng_ctor,
181  .dtor = _nouveau_dmaeng_dtor,
182  .init = _nouveau_dmaeng_init,
183  .fini = _nouveau_dmaeng_fini,
184  },
185 };