aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/nouveau/core/engine/disp
diff options
context:
space:
mode:
authorBen Skeggs <bskeggs@redhat.com>2012-08-28 00:10:39 -0400
committerBen Skeggs <bskeggs@redhat.com>2012-11-28 18:57:40 -0500
commit46654061bbf62ead0a7cbbaae9f95908a692adce (patch)
treeefa3594af92f9b7a9e02afe2ad7ef02f10105469 /drivers/gpu/drm/nouveau/core/engine/disp
parent944234d6a2c46a4666533904b7ea8c79807e9072 (diff)
drm/nvd0-nve0/disp: initial implementation of evo channel classes
Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
Diffstat (limited to 'drivers/gpu/drm/nouveau/core/engine/disp')
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/disp/nv50.h9
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/disp/nvd0.c556
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/disp/nve0.c84
3 files changed, 637 insertions, 12 deletions
diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/nv50.h b/drivers/gpu/drm/nouveau/core/engine/disp/nv50.h
index 6128bc4b4cb..f269138ade6 100644
--- a/drivers/gpu/drm/nouveau/core/engine/disp/nv50.h
+++ b/drivers/gpu/drm/nouveau/core/engine/disp/nv50.h
@@ -67,4 +67,13 @@ extern struct nouveau_ofuncs nv50_disp_base_ofuncs;
67extern struct nouveau_oclass nv50_disp_cclass; 67extern struct nouveau_oclass nv50_disp_cclass;
68void nv50_disp_intr(struct nouveau_subdev *); 68void nv50_disp_intr(struct nouveau_subdev *);
69 69
70extern struct nouveau_ofuncs nvd0_disp_mast_ofuncs;
71extern struct nouveau_ofuncs nvd0_disp_sync_ofuncs;
72extern struct nouveau_ofuncs nvd0_disp_ovly_ofuncs;
73extern struct nouveau_ofuncs nvd0_disp_oimm_ofuncs;
74extern struct nouveau_ofuncs nvd0_disp_curs_ofuncs;
75extern struct nouveau_ofuncs nvd0_disp_base_ofuncs;
76extern struct nouveau_oclass nvd0_disp_cclass;
77void nvd0_disp_intr(struct nouveau_subdev *);
78
70#endif 79#endif
diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/nvd0.c b/drivers/gpu/drm/nouveau/core/engine/disp/nvd0.c
index d93efbcf75b..fa1b9709f1c 100644
--- a/drivers/gpu/drm/nouveau/core/engine/disp/nvd0.c
+++ b/drivers/gpu/drm/nouveau/core/engine/disp/nvd0.c
@@ -22,22 +22,549 @@
22 * Authors: Ben Skeggs 22 * Authors: Ben Skeggs
23 */ 23 */
24 24
25#include <subdev/bar.h> 25#include <core/object.h>
26#include <core/parent.h>
27#include <core/handle.h>
28#include <core/class.h>
26 29
27#include <engine/software.h> 30#include <engine/software.h>
28#include <engine/disp.h> 31#include <engine/disp.h>
29 32
30struct nvd0_disp_priv { 33#include <subdev/timer.h>
31 struct nouveau_disp base; 34#include <subdev/fb.h>
35#include <subdev/bar.h>
36
37#include "nv50.h"
38
39/*******************************************************************************
40 * EVO DMA channel base class
41 ******************************************************************************/
42
43static int
44nvd0_disp_dmac_object_attach(struct nouveau_object *parent,
45 struct nouveau_object *object, u32 name)
46{
47 struct nv50_disp_base *base = (void *)parent->parent;
48 struct nv50_disp_chan *chan = (void *)parent;
49 u32 addr = nv_gpuobj(object)->node->offset;
50 u32 data = (chan->chid << 27) | (addr << 9) | 0x00000001;
51 return nouveau_ramht_insert(base->ramht, chan->chid, name, data);
52}
53
54static void
55nvd0_disp_dmac_object_detach(struct nouveau_object *parent, int cookie)
56{
57 struct nv50_disp_base *base = (void *)parent->parent;
58 nouveau_ramht_remove(base->ramht, cookie);
59}
60
61static int
62nvd0_disp_dmac_init(struct nouveau_object *object)
63{
64 struct nv50_disp_priv *priv = (void *)object->engine;
65 struct nv50_disp_dmac *dmac = (void *)object;
66 int chid = dmac->base.chid;
67 int ret;
68
69 ret = nv50_disp_chan_init(&dmac->base);
70 if (ret)
71 return ret;
72
73 /* enable error reporting */
74 nv_mask(priv, 0x610090, 0x00000001 << chid, 0x00000001 << chid);
75 nv_mask(priv, 0x6100a0, 0x00000001 << chid, 0x00000001 << chid);
76
77 /* initialise channel for dma command submission */
78 nv_wr32(priv, 0x610494 + (chid * 0x0010), dmac->push);
79 nv_wr32(priv, 0x610498 + (chid * 0x0010), 0x00010000);
80 nv_wr32(priv, 0x61049c + (chid * 0x0010), 0x00000001);
81 nv_mask(priv, 0x610490 + (chid * 0x0010), 0x00000010, 0x00000010);
82 nv_wr32(priv, 0x640000 + (chid * 0x1000), 0x00000000);
83 nv_wr32(priv, 0x610490 + (chid * 0x0010), 0x00000013);
84
85 /* wait for it to go inactive */
86 if (!nv_wait(priv, 0x610490 + (chid * 0x10), 0x80000000, 0x00000000)) {
87 nv_error(dmac, "init: 0x%08x\n",
88 nv_rd32(priv, 0x610490 + (chid * 0x10)));
89 return -EBUSY;
90 }
91
92 return 0;
93}
94
95static int
96nvd0_disp_dmac_fini(struct nouveau_object *object, bool suspend)
97{
98 struct nv50_disp_priv *priv = (void *)object->engine;
99 struct nv50_disp_dmac *dmac = (void *)object;
100 int chid = dmac->base.chid;
101
102 /* deactivate channel */
103 nv_mask(priv, 0x610490 + (chid * 0x0010), 0x00001010, 0x00001000);
104 nv_mask(priv, 0x610490 + (chid * 0x0010), 0x00000003, 0x00000000);
105 if (!nv_wait(priv, 0x610490 + (chid * 0x10), 0x001e0000, 0x00000000)) {
106 nv_error(dmac, "fini: 0x%08x\n",
107 nv_rd32(priv, 0x610490 + (chid * 0x10)));
108 if (suspend)
109 return -EBUSY;
110 }
111
112 /* disable error reporting */
113 nv_mask(priv, 0x610090, 0x00000001 << chid, 0x00000000);
114 nv_mask(priv, 0x6100a0, 0x00000001 << chid, 0x00000000);
115
116 return nv50_disp_chan_fini(&dmac->base, suspend);
117}
118
119/*******************************************************************************
120 * EVO master channel object
121 ******************************************************************************/
122
123static int
124nvd0_disp_mast_ctor(struct nouveau_object *parent,
125 struct nouveau_object *engine,
126 struct nouveau_oclass *oclass, void *data, u32 size,
127 struct nouveau_object **pobject)
128{
129 struct nv50_display_mast_class *args = data;
130 struct nv50_disp_dmac *mast;
131 int ret;
132
133 if (size < sizeof(*args))
134 return -EINVAL;
135
136 ret = nv50_disp_dmac_create_(parent, engine, oclass, args->pushbuf,
137 0, sizeof(*mast), (void **)&mast);
138 *pobject = nv_object(mast);
139 if (ret)
140 return ret;
141
142 nv_parent(mast)->object_attach = nvd0_disp_dmac_object_attach;
143 nv_parent(mast)->object_detach = nvd0_disp_dmac_object_detach;
144 return 0;
145}
146
147static int
148nvd0_disp_mast_init(struct nouveau_object *object)
149{
150 struct nv50_disp_priv *priv = (void *)object->engine;
151 struct nv50_disp_dmac *mast = (void *)object;
152 int ret;
153
154 ret = nv50_disp_chan_init(&mast->base);
155 if (ret)
156 return ret;
157
158 /* enable error reporting */
159 nv_mask(priv, 0x610090, 0x00000001, 0x00000001);
160 nv_mask(priv, 0x6100a0, 0x00000001, 0x00000001);
161
162 /* initialise channel for dma command submission */
163 nv_wr32(priv, 0x610494, mast->push);
164 nv_wr32(priv, 0x610498, 0x00010000);
165 nv_wr32(priv, 0x61049c, 0x00000001);
166 nv_mask(priv, 0x610490, 0x00000010, 0x00000010);
167 nv_wr32(priv, 0x640000, 0x00000000);
168 nv_wr32(priv, 0x610490, 0x01000013);
169
170 /* wait for it to go inactive */
171 if (!nv_wait(priv, 0x610490, 0x80000000, 0x00000000)) {
172 nv_error(mast, "init: 0x%08x\n", nv_rd32(priv, 0x610490));
173 return -EBUSY;
174 }
175
176 return 0;
177}
178
179static int
180nvd0_disp_mast_fini(struct nouveau_object *object, bool suspend)
181{
182 struct nv50_disp_priv *priv = (void *)object->engine;
183 struct nv50_disp_dmac *mast = (void *)object;
184
185 /* deactivate channel */
186 nv_mask(priv, 0x610490, 0x00000010, 0x00000000);
187 nv_mask(priv, 0x610490, 0x00000003, 0x00000000);
188 if (!nv_wait(priv, 0x610490, 0x001e0000, 0x00000000)) {
189 nv_error(mast, "fini: 0x%08x\n", nv_rd32(priv, 0x610490));
190 if (suspend)
191 return -EBUSY;
192 }
193
194 /* disable error reporting */
195 nv_mask(priv, 0x610090, 0x00000001, 0x00000000);
196 nv_mask(priv, 0x6100a0, 0x00000001, 0x00000000);
197
198 return nv50_disp_chan_fini(&mast->base, suspend);
199}
200
201struct nouveau_ofuncs
202nvd0_disp_mast_ofuncs = {
203 .ctor = nvd0_disp_mast_ctor,
204 .dtor = nv50_disp_dmac_dtor,
205 .init = nvd0_disp_mast_init,
206 .fini = nvd0_disp_mast_fini,
207 .rd32 = nv50_disp_chan_rd32,
208 .wr32 = nv50_disp_chan_wr32,
209};
210
211/*******************************************************************************
212 * EVO sync channel objects
213 ******************************************************************************/
214
215static int
216nvd0_disp_sync_ctor(struct nouveau_object *parent,
217 struct nouveau_object *engine,
218 struct nouveau_oclass *oclass, void *data, u32 size,
219 struct nouveau_object **pobject)
220{
221 struct nv50_display_sync_class *args = data;
222 struct nv50_disp_priv *priv = (void *)engine;
223 struct nv50_disp_dmac *dmac;
224 int ret;
225
226 if (size < sizeof(*data) || args->head >= priv->head.nr)
227 return -EINVAL;
228
229 ret = nv50_disp_dmac_create_(parent, engine, oclass, args->pushbuf,
230 1 + args->head, sizeof(*dmac),
231 (void **)&dmac);
232 *pobject = nv_object(dmac);
233 if (ret)
234 return ret;
235
236 nv_parent(dmac)->object_attach = nvd0_disp_dmac_object_attach;
237 nv_parent(dmac)->object_detach = nvd0_disp_dmac_object_detach;
238 return 0;
239}
240
241struct nouveau_ofuncs
242nvd0_disp_sync_ofuncs = {
243 .ctor = nvd0_disp_sync_ctor,
244 .dtor = nv50_disp_dmac_dtor,
245 .init = nvd0_disp_dmac_init,
246 .fini = nvd0_disp_dmac_fini,
247 .rd32 = nv50_disp_chan_rd32,
248 .wr32 = nv50_disp_chan_wr32,
249};
250
251/*******************************************************************************
252 * EVO overlay channel objects
253 ******************************************************************************/
254
255static int
256nvd0_disp_ovly_ctor(struct nouveau_object *parent,
257 struct nouveau_object *engine,
258 struct nouveau_oclass *oclass, void *data, u32 size,
259 struct nouveau_object **pobject)
260{
261 struct nv50_display_ovly_class *args = data;
262 struct nv50_disp_priv *priv = (void *)engine;
263 struct nv50_disp_dmac *dmac;
264 int ret;
265
266 if (size < sizeof(*data) || args->head >= priv->head.nr)
267 return -EINVAL;
268
269 ret = nv50_disp_dmac_create_(parent, engine, oclass, args->pushbuf,
270 5 + args->head, sizeof(*dmac),
271 (void **)&dmac);
272 *pobject = nv_object(dmac);
273 if (ret)
274 return ret;
275
276 nv_parent(dmac)->object_attach = nvd0_disp_dmac_object_attach;
277 nv_parent(dmac)->object_detach = nvd0_disp_dmac_object_detach;
278 return 0;
279}
280
281struct nouveau_ofuncs
282nvd0_disp_ovly_ofuncs = {
283 .ctor = nvd0_disp_ovly_ctor,
284 .dtor = nv50_disp_dmac_dtor,
285 .init = nvd0_disp_dmac_init,
286 .fini = nvd0_disp_dmac_fini,
287 .rd32 = nv50_disp_chan_rd32,
288 .wr32 = nv50_disp_chan_wr32,
289};
290
291/*******************************************************************************
292 * EVO PIO channel base class
293 ******************************************************************************/
294
295static int
296nvd0_disp_pioc_create_(struct nouveau_object *parent,
297 struct nouveau_object *engine,
298 struct nouveau_oclass *oclass, int chid,
299 int length, void **pobject)
300{
301 return nv50_disp_chan_create_(parent, engine, oclass, chid,
302 length, pobject);
303}
304
305static void
306nvd0_disp_pioc_dtor(struct nouveau_object *object)
307{
308 struct nv50_disp_pioc *pioc = (void *)object;
309 nv50_disp_chan_destroy(&pioc->base);
310}
311
312static int
313nvd0_disp_pioc_init(struct nouveau_object *object)
314{
315 struct nv50_disp_priv *priv = (void *)object->engine;
316 struct nv50_disp_pioc *pioc = (void *)object;
317 int chid = pioc->base.chid;
318 int ret;
319
320 ret = nv50_disp_chan_init(&pioc->base);
321 if (ret)
322 return ret;
323
324 /* enable error reporting */
325 nv_mask(priv, 0x610090, 0x00000001 << chid, 0x00000001 << chid);
326 nv_mask(priv, 0x6100a0, 0x00000001 << chid, 0x00000001 << chid);
327
328 /* activate channel */
329 nv_wr32(priv, 0x610490 + (chid * 0x10), 0x00000001);
330 if (!nv_wait(priv, 0x610490 + (chid * 0x10), 0x00030000, 0x00010000)) {
331 nv_error(pioc, "init: 0x%08x\n",
332 nv_rd32(priv, 0x610490 + (chid * 0x10)));
333 return -EBUSY;
334 }
335
336 return 0;
337}
338
339static int
340nvd0_disp_pioc_fini(struct nouveau_object *object, bool suspend)
341{
342 struct nv50_disp_priv *priv = (void *)object->engine;
343 struct nv50_disp_pioc *pioc = (void *)object;
344 int chid = pioc->base.chid;
345
346 nv_mask(priv, 0x610490 + (chid * 0x10), 0x00000001, 0x00000000);
347 if (!nv_wait(priv, 0x610490 + (chid * 0x10), 0x00030000, 0x00000000)) {
348 nv_error(pioc, "timeout: 0x%08x\n",
349 nv_rd32(priv, 0x610490 + (chid * 0x10)));
350 if (suspend)
351 return -EBUSY;
352 }
353
354 /* disable error reporting */
355 nv_mask(priv, 0x610090, 0x00000001 << chid, 0x00000000);
356 nv_mask(priv, 0x6100a0, 0x00000001 << chid, 0x00000000);
357
358 return nv50_disp_chan_fini(&pioc->base, suspend);
359}
360
361/*******************************************************************************
362 * EVO immediate overlay channel objects
363 ******************************************************************************/
364
365static int
366nvd0_disp_oimm_ctor(struct nouveau_object *parent,
367 struct nouveau_object *engine,
368 struct nouveau_oclass *oclass, void *data, u32 size,
369 struct nouveau_object **pobject)
370{
371 struct nv50_display_oimm_class *args = data;
372 struct nv50_disp_priv *priv = (void *)engine;
373 struct nv50_disp_pioc *pioc;
374 int ret;
375
376 if (size < sizeof(*args) || args->head >= priv->head.nr)
377 return -EINVAL;
378
379 ret = nvd0_disp_pioc_create_(parent, engine, oclass, 9 + args->head,
380 sizeof(*pioc), (void **)&pioc);
381 *pobject = nv_object(pioc);
382 if (ret)
383 return ret;
384
385 return 0;
386}
387
388struct nouveau_ofuncs
389nvd0_disp_oimm_ofuncs = {
390 .ctor = nvd0_disp_oimm_ctor,
391 .dtor = nvd0_disp_pioc_dtor,
392 .init = nvd0_disp_pioc_init,
393 .fini = nvd0_disp_pioc_fini,
394 .rd32 = nv50_disp_chan_rd32,
395 .wr32 = nv50_disp_chan_wr32,
396};
397
398/*******************************************************************************
399 * EVO cursor channel objects
400 ******************************************************************************/
401
402static int
403nvd0_disp_curs_ctor(struct nouveau_object *parent,
404 struct nouveau_object *engine,
405 struct nouveau_oclass *oclass, void *data, u32 size,
406 struct nouveau_object **pobject)
407{
408 struct nv50_display_curs_class *args = data;
409 struct nv50_disp_priv *priv = (void *)engine;
410 struct nv50_disp_pioc *pioc;
411 int ret;
412
413 if (size < sizeof(*args) || args->head >= priv->head.nr)
414 return -EINVAL;
415
416 ret = nvd0_disp_pioc_create_(parent, engine, oclass, 13 + args->head,
417 sizeof(*pioc), (void **)&pioc);
418 *pobject = nv_object(pioc);
419 if (ret)
420 return ret;
421
422 return 0;
423}
424
425struct nouveau_ofuncs
426nvd0_disp_curs_ofuncs = {
427 .ctor = nvd0_disp_curs_ctor,
428 .dtor = nvd0_disp_pioc_dtor,
429 .init = nvd0_disp_pioc_init,
430 .fini = nvd0_disp_pioc_fini,
431 .rd32 = nv50_disp_chan_rd32,
432 .wr32 = nv50_disp_chan_wr32,
433};
434
435/*******************************************************************************
436 * Base display object
437 ******************************************************************************/
438
439static int
440nvd0_disp_base_ctor(struct nouveau_object *parent,
441 struct nouveau_object *engine,
442 struct nouveau_oclass *oclass, void *data, u32 size,
443 struct nouveau_object **pobject)
444{
445 struct nv50_disp_priv *priv = (void *)engine;
446 struct nv50_disp_base *base;
447 int ret;
448
449 ret = nouveau_parent_create(parent, engine, oclass, 0,
450 priv->sclass, 0, &base);
451 *pobject = nv_object(base);
452 if (ret)
453 return ret;
454
455 return nouveau_ramht_new(parent, parent, 0x1000, 0, &base->ramht);
456}
457
458static void
459nvd0_disp_base_dtor(struct nouveau_object *object)
460{
461 struct nv50_disp_base *base = (void *)object;
462 nouveau_ramht_ref(NULL, &base->ramht);
463 nouveau_parent_destroy(&base->base);
464}
465
466static int
467nvd0_disp_base_init(struct nouveau_object *object)
468{
469 struct nv50_disp_priv *priv = (void *)object->engine;
470 struct nv50_disp_base *base = (void *)object;
471 int ret, i;
472 u32 tmp;
473
474 ret = nouveau_parent_init(&base->base);
475 if (ret)
476 return ret;
477
478 /* The below segments of code copying values from one register to
479 * another appear to inform EVO of the display capabilities or
480 * something similar.
481 */
482
483 /* ... CRTC caps */
484 for (i = 0; i < priv->head.nr; i++) {
485 tmp = nv_rd32(priv, 0x616104 + (i * 0x800));
486 nv_wr32(priv, 0x6101b4 + (i * 0x800), tmp);
487 tmp = nv_rd32(priv, 0x616108 + (i * 0x800));
488 nv_wr32(priv, 0x6101b8 + (i * 0x800), tmp);
489 tmp = nv_rd32(priv, 0x61610c + (i * 0x800));
490 nv_wr32(priv, 0x6101bc + (i * 0x800), tmp);
491 }
492
493 /* ... DAC caps */
494 for (i = 0; i < priv->dac.nr; i++) {
495 tmp = nv_rd32(priv, 0x61a000 + (i * 0x800));
496 nv_wr32(priv, 0x6101c0 + (i * 0x800), tmp);
497 }
498
499 /* ... SOR caps */
500 for (i = 0; i < priv->sor.nr; i++) {
501 tmp = nv_rd32(priv, 0x61c000 + (i * 0x800));
502 nv_wr32(priv, 0x6301c4 + (i * 0x800), tmp);
503 }
504
505 /* steal display away from vbios, or something like that */
506 if (nv_rd32(priv, 0x6100ac) & 0x00000100) {
507 nv_wr32(priv, 0x6100ac, 0x00000100);
508 nv_mask(priv, 0x6194e8, 0x00000001, 0x00000000);
509 if (!nv_wait(priv, 0x6194e8, 0x00000002, 0x00000000)) {
510 nv_error(priv, "timeout acquiring display\n");
511 return -EBUSY;
512 }
513 }
514
515 /* point at display engine memory area (hash table, objects) */
516 nv_wr32(priv, 0x610010, (nv_gpuobj(object->parent)->addr >> 8) | 9);
517
518 /* enable supervisor interrupts, disable everything else */
519 nv_wr32(priv, 0x610090, 0x00000000);
520 nv_wr32(priv, 0x6100a0, 0x00000000);
521 nv_wr32(priv, 0x6100b0, 0x00000307);
522
523 return 0;
524}
525
526static int
527nvd0_disp_base_fini(struct nouveau_object *object, bool suspend)
528{
529 struct nv50_disp_priv *priv = (void *)object->engine;
530 struct nv50_disp_base *base = (void *)object;
531
532 /* disable all interrupts */
533 nv_wr32(priv, 0x6100b0, 0x00000000);
534
535 return nouveau_parent_fini(&base->base, suspend);
536}
537
538struct nouveau_ofuncs
539nvd0_disp_base_ofuncs = {
540 .ctor = nvd0_disp_base_ctor,
541 .dtor = nvd0_disp_base_dtor,
542 .init = nvd0_disp_base_init,
543 .fini = nvd0_disp_base_fini,
544};
545
546static struct nouveau_oclass
547nvd0_disp_base_oclass[] = {
548 { NVD0_DISP_CLASS, &nvd0_disp_base_ofuncs },
549 {}
32}; 550};
33 551
34static struct nouveau_oclass 552static struct nouveau_oclass
35nvd0_disp_sclass[] = { 553nvd0_disp_sclass[] = {
36 {}, 554 { NVD0_DISP_MAST_CLASS, &nvd0_disp_mast_ofuncs },
555 { NVD0_DISP_SYNC_CLASS, &nvd0_disp_sync_ofuncs },
556 { NVD0_DISP_OVLY_CLASS, &nvd0_disp_ovly_ofuncs },
557 { NVD0_DISP_OIMM_CLASS, &nvd0_disp_oimm_ofuncs },
558 { NVD0_DISP_CURS_CLASS, &nvd0_disp_curs_ofuncs },
559 {}
37}; 560};
38 561
562/*******************************************************************************
563 * Display engine implementation
564 ******************************************************************************/
565
39static void 566static void
40nvd0_disp_intr_vblank(struct nvd0_disp_priv *priv, int crtc) 567nvd0_disp_intr_vblank(struct nv50_disp_priv *priv, int crtc)
41{ 568{
42 struct nouveau_bar *bar = nouveau_bar(priv); 569 struct nouveau_bar *bar = nouveau_bar(priv);
43 struct nouveau_disp *disp = &priv->base; 570 struct nouveau_disp *disp = &priv->base;
@@ -65,10 +592,10 @@ nvd0_disp_intr_vblank(struct nvd0_disp_priv *priv, int crtc)
65 disp->vblank.notify(disp->vblank.data, crtc); 592 disp->vblank.notify(disp->vblank.data, crtc);
66} 593}
67 594
68static void 595void
69nvd0_disp_intr(struct nouveau_subdev *subdev) 596nvd0_disp_intr(struct nouveau_subdev *subdev)
70{ 597{
71 struct nvd0_disp_priv *priv = (void *)subdev; 598 struct nv50_disp_priv *priv = (void *)subdev;
72 u32 intr = nv_rd32(priv, 0x610088); 599 u32 intr = nv_rd32(priv, 0x610088);
73 int i; 600 int i;
74 601
@@ -86,10 +613,10 @@ nvd0_disp_intr(struct nouveau_subdev *subdev)
86 613
87static int 614static int
88nvd0_disp_ctor(struct nouveau_object *parent, struct nouveau_object *engine, 615nvd0_disp_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
89 struct nouveau_oclass *oclass, void *data, u32 size, 616 struct nouveau_oclass *oclass, void *data, u32 size,
90 struct nouveau_object **pobject) 617 struct nouveau_object **pobject)
91{ 618{
92 struct nvd0_disp_priv *priv; 619 struct nv50_disp_priv *priv;
93 int ret; 620 int ret;
94 621
95 ret = nouveau_disp_create(parent, engine, oclass, "PDISP", 622 ret = nouveau_disp_create(parent, engine, oclass, "PDISP",
@@ -98,8 +625,13 @@ nvd0_disp_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
98 if (ret) 625 if (ret)
99 return ret; 626 return ret;
100 627
101 nv_engine(priv)->sclass = nvd0_disp_sclass; 628 nv_engine(priv)->sclass = nvd0_disp_base_oclass;
629 nv_engine(priv)->cclass = &nv50_disp_cclass;
102 nv_subdev(priv)->intr = nvd0_disp_intr; 630 nv_subdev(priv)->intr = nvd0_disp_intr;
631 priv->sclass = nvd0_disp_sclass;
632 priv->head.nr = nv_rd32(priv, 0x022448);
633 priv->dac.nr = 3;
634 priv->sor.nr = 4;
103 635
104 INIT_LIST_HEAD(&priv->base.vblank.list); 636 INIT_LIST_HEAD(&priv->base.vblank.list);
105 spin_lock_init(&priv->base.vblank.lock); 637 spin_lock_init(&priv->base.vblank.lock);
@@ -108,7 +640,7 @@ nvd0_disp_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
108 640
109struct nouveau_oclass 641struct nouveau_oclass
110nvd0_disp_oclass = { 642nvd0_disp_oclass = {
111 .handle = NV_ENGINE(DISP, 0xd0), 643 .handle = NV_ENGINE(DISP, 0x90),
112 .ofuncs = &(struct nouveau_ofuncs) { 644 .ofuncs = &(struct nouveau_ofuncs) {
113 .ctor = nvd0_disp_ctor, 645 .ctor = nvd0_disp_ctor,
114 .dtor = _nouveau_disp_dtor, 646 .dtor = _nouveau_disp_dtor,
diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/nve0.c b/drivers/gpu/drm/nouveau/core/engine/disp/nve0.c
new file mode 100644
index 00000000000..2fbad90f2f3
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/core/engine/disp/nve0.c
@@ -0,0 +1,84 @@
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 <engine/software.h>
26#include <engine/disp.h>
27
28#include <core/class.h>
29
30#include "nv50.h"
31
32static struct nouveau_oclass
33nve0_disp_sclass[] = {
34 { NVE0_DISP_MAST_CLASS, &nvd0_disp_mast_ofuncs },
35 { NVE0_DISP_SYNC_CLASS, &nvd0_disp_sync_ofuncs },
36 { NVE0_DISP_OVLY_CLASS, &nvd0_disp_ovly_ofuncs },
37 { NVE0_DISP_OIMM_CLASS, &nvd0_disp_oimm_ofuncs },
38 { NVE0_DISP_CURS_CLASS, &nvd0_disp_curs_ofuncs },
39 {}
40};
41
42static struct nouveau_oclass
43nve0_disp_base_oclass[] = {
44 { NVE0_DISP_CLASS, &nvd0_disp_base_ofuncs },
45 {}
46};
47
48static int
49nve0_disp_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
50 struct nouveau_oclass *oclass, void *data, u32 size,
51 struct nouveau_object **pobject)
52{
53 struct nv50_disp_priv *priv;
54 int ret;
55
56 ret = nouveau_disp_create(parent, engine, oclass, "PDISP",
57 "display", &priv);
58 *pobject = nv_object(priv);
59 if (ret)
60 return ret;
61
62 nv_engine(priv)->sclass = nve0_disp_base_oclass;
63 nv_engine(priv)->cclass = &nv50_disp_cclass;
64 nv_subdev(priv)->intr = nvd0_disp_intr;
65 priv->sclass = nve0_disp_sclass;
66 priv->head.nr = nv_rd32(priv, 0x022448);
67 priv->dac.nr = 3;
68 priv->sor.nr = 4;
69
70 INIT_LIST_HEAD(&priv->base.vblank.list);
71 spin_lock_init(&priv->base.vblank.lock);
72 return 0;
73}
74
75struct nouveau_oclass
76nve0_disp_oclass = {
77 .handle = NV_ENGINE(DISP, 0x91),
78 .ofuncs = &(struct nouveau_ofuncs) {
79 .ctor = nve0_disp_ctor,
80 .dtor = _nouveau_disp_dtor,
81 .init = _nouveau_disp_init,
82 .fini = _nouveau_disp_fini,
83 },
84};