diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/gpu/drm/nouveau/nouveau_abi16.c | 5 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nouveau_bo.c | 31 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nouveau_bo.h | 2 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nouveau_chan.c | 35 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nouveau_chan.h | 2 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nouveau_drm.c | 22 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nouveau_drm.h | 1 |
7 files changed, 72 insertions, 26 deletions
diff --git a/drivers/gpu/drm/nouveau/nouveau_abi16.c b/drivers/gpu/drm/nouveau/nouveau_abi16.c index 9e6ced3b941a..cc79c796afee 100644 --- a/drivers/gpu/drm/nouveau/nouveau_abi16.c +++ b/drivers/gpu/drm/nouveau/nouveau_abi16.c | |||
@@ -264,6 +264,11 @@ nouveau_abi16_ioctl_channel_alloc(ABI16_IOCTL_ARGS) | |||
264 | abi16->handles |= (1 << init->channel); | 264 | abi16->handles |= (1 << init->channel); |
265 | 265 | ||
266 | /* create channel object and initialise dma and fence management */ | 266 | /* create channel object and initialise dma and fence management */ |
267 | if (device->card_type >= NV_E0) { | ||
268 | init->fb_ctxdma_handle = NVE0_CHANNEL_IND_ENGINE_GR; | ||
269 | init->tt_ctxdma_handle = 0; | ||
270 | } | ||
271 | |||
267 | ret = nouveau_channel_new(drm, cli, NVDRM_DEVICE, NVDRM_CHAN | | 272 | ret = nouveau_channel_new(drm, cli, NVDRM_DEVICE, NVDRM_CHAN | |
268 | init->channel, init->fb_ctxdma_handle, | 273 | init->channel, init->fb_ctxdma_handle, |
269 | init->tt_ctxdma_handle, &chan->chan); | 274 | init->tt_ctxdma_handle, &chan->chan); |
diff --git a/drivers/gpu/drm/nouveau/nouveau_bo.c b/drivers/gpu/drm/nouveau/nouveau_bo.c index ef96bdbb5255..259e5f1adf47 100644 --- a/drivers/gpu/drm/nouveau/nouveau_bo.c +++ b/drivers/gpu/drm/nouveau/nouveau_bo.c | |||
@@ -571,6 +571,18 @@ nouveau_bo_move_accel_cleanup(struct nouveau_channel *chan, | |||
571 | } | 571 | } |
572 | 572 | ||
573 | static int | 573 | static int |
574 | nve0_bo_move_init(struct nouveau_channel *chan, u32 handle) | ||
575 | { | ||
576 | int ret = RING_SPACE(chan, 2); | ||
577 | if (ret == 0) { | ||
578 | BEGIN_NVC0(chan, NvSubCopy, 0x0000, 1); | ||
579 | OUT_RING (chan, handle); | ||
580 | FIRE_RING (chan); | ||
581 | } | ||
582 | return ret; | ||
583 | } | ||
584 | |||
585 | static int | ||
574 | nve0_bo_move_copy(struct nouveau_channel *chan, struct ttm_buffer_object *bo, | 586 | nve0_bo_move_copy(struct nouveau_channel *chan, struct ttm_buffer_object *bo, |
575 | struct ttm_mem_reg *old_mem, struct ttm_mem_reg *new_mem) | 587 | struct ttm_mem_reg *old_mem, struct ttm_mem_reg *new_mem) |
576 | { | 588 | { |
@@ -991,10 +1003,8 @@ out: | |||
991 | } | 1003 | } |
992 | 1004 | ||
993 | void | 1005 | void |
994 | nouveau_bo_move_init(struct nouveau_channel *chan) | 1006 | nouveau_bo_move_init(struct nouveau_drm *drm) |
995 | { | 1007 | { |
996 | struct nouveau_cli *cli = chan->cli; | ||
997 | struct nouveau_drm *drm = chan->drm; | ||
998 | static const struct { | 1008 | static const struct { |
999 | const char *name; | 1009 | const char *name; |
1000 | int engine; | 1010 | int engine; |
@@ -1004,7 +1014,8 @@ nouveau_bo_move_init(struct nouveau_channel *chan) | |||
1004 | struct ttm_mem_reg *, struct ttm_mem_reg *); | 1014 | struct ttm_mem_reg *, struct ttm_mem_reg *); |
1005 | int (*init)(struct nouveau_channel *, u32 handle); | 1015 | int (*init)(struct nouveau_channel *, u32 handle); |
1006 | } _methods[] = { | 1016 | } _methods[] = { |
1007 | { "COPY", 0, 0xa0b5, nve0_bo_move_copy, nvc0_bo_move_init }, | 1017 | { "COPY", 0, 0xa0b5, nve0_bo_move_copy, nve0_bo_move_init }, |
1018 | { "GRCE", 0, 0xa0b5, nve0_bo_move_copy, nvc0_bo_move_init }, | ||
1008 | { "COPY1", 5, 0x90b8, nvc0_bo_move_copy, nvc0_bo_move_init }, | 1019 | { "COPY1", 5, 0x90b8, nvc0_bo_move_copy, nvc0_bo_move_init }, |
1009 | { "COPY0", 4, 0x90b5, nvc0_bo_move_copy, nvc0_bo_move_init }, | 1020 | { "COPY0", 4, 0x90b5, nvc0_bo_move_copy, nvc0_bo_move_init }, |
1010 | { "COPY", 0, 0x85b5, nva3_bo_move_copy, nv50_bo_move_init }, | 1021 | { "COPY", 0, 0x85b5, nva3_bo_move_copy, nv50_bo_move_init }, |
@@ -1020,14 +1031,22 @@ nouveau_bo_move_init(struct nouveau_channel *chan) | |||
1020 | 1031 | ||
1021 | do { | 1032 | do { |
1022 | struct nouveau_object *object; | 1033 | struct nouveau_object *object; |
1034 | struct nouveau_channel *chan; | ||
1023 | u32 handle = (mthd->engine << 16) | mthd->oclass; | 1035 | u32 handle = (mthd->engine << 16) | mthd->oclass; |
1024 | 1036 | ||
1025 | ret = nouveau_object_new(nv_object(cli), chan->handle, handle, | 1037 | if (mthd->init == nve0_bo_move_init) |
1038 | chan = drm->cechan; | ||
1039 | else | ||
1040 | chan = drm->channel; | ||
1041 | if (chan == NULL) | ||
1042 | continue; | ||
1043 | |||
1044 | ret = nouveau_object_new(nv_object(drm), chan->handle, handle, | ||
1026 | mthd->oclass, NULL, 0, &object); | 1045 | mthd->oclass, NULL, 0, &object); |
1027 | if (ret == 0) { | 1046 | if (ret == 0) { |
1028 | ret = mthd->init(chan, handle); | 1047 | ret = mthd->init(chan, handle); |
1029 | if (ret) { | 1048 | if (ret) { |
1030 | nouveau_object_del(nv_object(cli), | 1049 | nouveau_object_del(nv_object(drm), |
1031 | chan->handle, handle); | 1050 | chan->handle, handle); |
1032 | continue; | 1051 | continue; |
1033 | } | 1052 | } |
diff --git a/drivers/gpu/drm/nouveau/nouveau_bo.h b/drivers/gpu/drm/nouveau/nouveau_bo.h index c42aea9fb546..dec51b1098fe 100644 --- a/drivers/gpu/drm/nouveau/nouveau_bo.h +++ b/drivers/gpu/drm/nouveau/nouveau_bo.h | |||
@@ -61,7 +61,7 @@ nouveau_bo_ref(struct nouveau_bo *ref, struct nouveau_bo **pnvbo) | |||
61 | 61 | ||
62 | extern struct ttm_bo_driver nouveau_bo_driver; | 62 | extern struct ttm_bo_driver nouveau_bo_driver; |
63 | 63 | ||
64 | void nouveau_bo_move_init(struct nouveau_channel *); | 64 | void nouveau_bo_move_init(struct nouveau_drm *); |
65 | int nouveau_bo_new(struct drm_device *, int size, int align, u32 flags, | 65 | int nouveau_bo_new(struct drm_device *, int size, int align, u32 flags, |
66 | u32 tile_mode, u32 tile_flags, struct sg_table *sg, | 66 | u32 tile_mode, u32 tile_flags, struct sg_table *sg, |
67 | struct nouveau_bo **); | 67 | struct nouveau_bo **); |
diff --git a/drivers/gpu/drm/nouveau/nouveau_chan.c b/drivers/gpu/drm/nouveau/nouveau_chan.c index b1eea19d99a6..62c7edf08e5a 100644 --- a/drivers/gpu/drm/nouveau/nouveau_chan.c +++ b/drivers/gpu/drm/nouveau/nouveau_chan.c | |||
@@ -184,7 +184,8 @@ nouveau_channel_prep(struct nouveau_drm *drm, struct nouveau_cli *cli, | |||
184 | 184 | ||
185 | int | 185 | int |
186 | nouveau_channel_ind(struct nouveau_drm *drm, struct nouveau_cli *cli, | 186 | nouveau_channel_ind(struct nouveau_drm *drm, struct nouveau_cli *cli, |
187 | u32 parent, u32 handle, struct nouveau_channel **pchan) | 187 | u32 parent, u32 handle, u32 engine, |
188 | struct nouveau_channel **pchan) | ||
188 | { | 189 | { |
189 | static const u16 oclasses[] = { 0xa06f, 0x906f, 0x826f, 0x506f, 0 }; | 190 | static const u16 oclasses[] = { 0xa06f, 0x906f, 0x826f, 0x506f, 0 }; |
190 | const u16 *oclass = oclasses; | 191 | const u16 *oclass = oclasses; |
@@ -202,7 +203,7 @@ nouveau_channel_ind(struct nouveau_drm *drm, struct nouveau_cli *cli, | |||
202 | args.pushbuf = chan->push.handle; | 203 | args.pushbuf = chan->push.handle; |
203 | args.ioffset = 0x10000 + chan->push.vma.offset; | 204 | args.ioffset = 0x10000 + chan->push.vma.offset; |
204 | args.ilength = 0x02000; | 205 | args.ilength = 0x02000; |
205 | args.engine = NVE0_CHANNEL_IND_ENGINE_GR; | 206 | args.engine = engine; |
206 | 207 | ||
207 | do { | 208 | do { |
208 | ret = nouveau_object_new(nv_object(cli), parent, handle, | 209 | ret = nouveau_object_new(nv_object(cli), parent, handle, |
@@ -261,9 +262,6 @@ nouveau_channel_init(struct nouveau_channel *chan, u32 vram, u32 gart) | |||
261 | struct nv_dma_class args; | 262 | struct nv_dma_class args; |
262 | int ret, i; | 263 | int ret, i; |
263 | 264 | ||
264 | chan->vram = vram; | ||
265 | chan->gart = gart; | ||
266 | |||
267 | /* allocate dma objects to cover all allowed vram, and gart */ | 265 | /* allocate dma objects to cover all allowed vram, and gart */ |
268 | if (device->card_type < NV_C0) { | 266 | if (device->card_type < NV_C0) { |
269 | if (device->card_type >= NV_50) { | 267 | if (device->card_type >= NV_50) { |
@@ -301,6 +299,9 @@ nouveau_channel_init(struct nouveau_channel *chan, u32 vram, u32 gart) | |||
301 | 0x003d, &args, sizeof(args), &object); | 299 | 0x003d, &args, sizeof(args), &object); |
302 | if (ret) | 300 | if (ret) |
303 | return ret; | 301 | return ret; |
302 | |||
303 | chan->vram = vram; | ||
304 | chan->gart = gart; | ||
304 | } | 305 | } |
305 | 306 | ||
306 | /* initialise dma tracking parameters */ | 307 | /* initialise dma tracking parameters */ |
@@ -336,15 +337,17 @@ nouveau_channel_init(struct nouveau_channel *chan, u32 vram, u32 gart) | |||
336 | /* allocate software object class (used for fences on <= nv05, and | 337 | /* allocate software object class (used for fences on <= nv05, and |
337 | * to signal flip completion), bind it to a subchannel. | 338 | * to signal flip completion), bind it to a subchannel. |
338 | */ | 339 | */ |
339 | ret = nouveau_object_new(nv_object(client), chan->handle, | 340 | if (chan != chan->drm->cechan) { |
340 | NvSw, nouveau_abi16_swclass(chan->drm), | 341 | ret = nouveau_object_new(nv_object(client), chan->handle, |
341 | NULL, 0, &object); | 342 | NvSw, nouveau_abi16_swclass(chan->drm), |
342 | if (ret) | 343 | NULL, 0, &object); |
343 | return ret; | 344 | if (ret) |
345 | return ret; | ||
344 | 346 | ||
345 | swch = (void *)object->parent; | 347 | swch = (void *)object->parent; |
346 | swch->flip = nouveau_flip_complete; | 348 | swch->flip = nouveau_flip_complete; |
347 | swch->flip_data = chan; | 349 | swch->flip_data = chan; |
350 | } | ||
348 | 351 | ||
349 | if (device->card_type < NV_C0) { | 352 | if (device->card_type < NV_C0) { |
350 | ret = RING_SPACE(chan, 2); | 353 | ret = RING_SPACE(chan, 2); |
@@ -362,12 +365,12 @@ nouveau_channel_init(struct nouveau_channel *chan, u32 vram, u32 gart) | |||
362 | 365 | ||
363 | int | 366 | int |
364 | nouveau_channel_new(struct nouveau_drm *drm, struct nouveau_cli *cli, | 367 | nouveau_channel_new(struct nouveau_drm *drm, struct nouveau_cli *cli, |
365 | u32 parent, u32 handle, u32 vram, u32 gart, | 368 | u32 parent, u32 handle, u32 arg0, u32 arg1, |
366 | struct nouveau_channel **pchan) | 369 | struct nouveau_channel **pchan) |
367 | { | 370 | { |
368 | int ret; | 371 | int ret; |
369 | 372 | ||
370 | ret = nouveau_channel_ind(drm, cli, parent, handle, pchan); | 373 | ret = nouveau_channel_ind(drm, cli, parent, handle, arg0, pchan); |
371 | if (ret) { | 374 | if (ret) { |
372 | NV_DEBUG(drm, "ib channel create, %d\n", ret); | 375 | NV_DEBUG(drm, "ib channel create, %d\n", ret); |
373 | ret = nouveau_channel_dma(drm, cli, parent, handle, pchan); | 376 | ret = nouveau_channel_dma(drm, cli, parent, handle, pchan); |
@@ -377,7 +380,7 @@ nouveau_channel_new(struct nouveau_drm *drm, struct nouveau_cli *cli, | |||
377 | } | 380 | } |
378 | } | 381 | } |
379 | 382 | ||
380 | ret = nouveau_channel_init(*pchan, vram, gart); | 383 | ret = nouveau_channel_init(*pchan, arg0, arg1); |
381 | if (ret) { | 384 | if (ret) { |
382 | NV_ERROR(drm, "channel failed to initialise, %d\n", ret); | 385 | NV_ERROR(drm, "channel failed to initialise, %d\n", ret); |
383 | nouveau_channel_del(pchan); | 386 | nouveau_channel_del(pchan); |
diff --git a/drivers/gpu/drm/nouveau/nouveau_chan.h b/drivers/gpu/drm/nouveau/nouveau_chan.h index 0fa94244bed1..40f97e2c47b6 100644 --- a/drivers/gpu/drm/nouveau/nouveau_chan.h +++ b/drivers/gpu/drm/nouveau/nouveau_chan.h | |||
@@ -39,7 +39,7 @@ struct nouveau_channel { | |||
39 | 39 | ||
40 | 40 | ||
41 | int nouveau_channel_new(struct nouveau_drm *, struct nouveau_cli *, | 41 | int nouveau_channel_new(struct nouveau_drm *, struct nouveau_cli *, |
42 | u32 parent, u32 handle, u32 vram, u32 gart, | 42 | u32 parent, u32 handle, u32 arg0, u32 arg1, |
43 | struct nouveau_channel **); | 43 | struct nouveau_channel **); |
44 | void nouveau_channel_del(struct nouveau_channel **); | 44 | void nouveau_channel_del(struct nouveau_channel **); |
45 | int nouveau_channel_idle(struct nouveau_channel *); | 45 | int nouveau_channel_idle(struct nouveau_channel *); |
diff --git a/drivers/gpu/drm/nouveau/nouveau_drm.c b/drivers/gpu/drm/nouveau/nouveau_drm.c index 8b508cec65a2..4dfc40e3dabe 100644 --- a/drivers/gpu/drm/nouveau/nouveau_drm.c +++ b/drivers/gpu/drm/nouveau/nouveau_drm.c | |||
@@ -109,6 +109,7 @@ nouveau_accel_fini(struct nouveau_drm *drm) | |||
109 | { | 109 | { |
110 | nouveau_gpuobj_ref(NULL, &drm->notify); | 110 | nouveau_gpuobj_ref(NULL, &drm->notify); |
111 | nouveau_channel_del(&drm->channel); | 111 | nouveau_channel_del(&drm->channel); |
112 | nouveau_channel_del(&drm->cechan); | ||
112 | if (drm->fence) | 113 | if (drm->fence) |
113 | nouveau_fence(drm)->dtor(drm); | 114 | nouveau_fence(drm)->dtor(drm); |
114 | } | 115 | } |
@@ -118,6 +119,7 @@ nouveau_accel_init(struct nouveau_drm *drm) | |||
118 | { | 119 | { |
119 | struct nouveau_device *device = nv_device(drm->device); | 120 | struct nouveau_device *device = nv_device(drm->device); |
120 | struct nouveau_object *object; | 121 | struct nouveau_object *object; |
122 | u32 arg0, arg1; | ||
121 | int ret; | 123 | int ret; |
122 | 124 | ||
123 | if (nouveau_noaccel) | 125 | if (nouveau_noaccel) |
@@ -134,8 +136,24 @@ nouveau_accel_init(struct nouveau_drm *drm) | |||
134 | return; | 136 | return; |
135 | } | 137 | } |
136 | 138 | ||
139 | if (device->card_type >= NV_E0) { | ||
140 | ret = nouveau_channel_new(drm, &drm->client, NVDRM_DEVICE, | ||
141 | NVDRM_CHAN + 1, | ||
142 | NVE0_CHANNEL_IND_ENGINE_CE0 | | ||
143 | NVE0_CHANNEL_IND_ENGINE_CE1, 0, | ||
144 | &drm->cechan); | ||
145 | if (ret) | ||
146 | NV_ERROR(drm, "failed to create ce channel, %d\n", ret); | ||
147 | |||
148 | arg0 = NVE0_CHANNEL_IND_ENGINE_GR; | ||
149 | arg1 = 0; | ||
150 | } else { | ||
151 | arg0 = NvDmaFB; | ||
152 | arg1 = NvDmaTT; | ||
153 | } | ||
154 | |||
137 | ret = nouveau_channel_new(drm, &drm->client, NVDRM_DEVICE, NVDRM_CHAN, | 155 | ret = nouveau_channel_new(drm, &drm->client, NVDRM_DEVICE, NVDRM_CHAN, |
138 | NvDmaFB, NvDmaTT, &drm->channel); | 156 | arg0, arg1, &drm->channel); |
139 | if (ret) { | 157 | if (ret) { |
140 | NV_ERROR(drm, "failed to create kernel channel, %d\n", ret); | 158 | NV_ERROR(drm, "failed to create kernel channel, %d\n", ret); |
141 | nouveau_accel_fini(drm); | 159 | nouveau_accel_fini(drm); |
@@ -167,7 +185,7 @@ nouveau_accel_init(struct nouveau_drm *drm) | |||
167 | } | 185 | } |
168 | 186 | ||
169 | 187 | ||
170 | nouveau_bo_move_init(drm->channel); | 188 | nouveau_bo_move_init(drm); |
171 | } | 189 | } |
172 | 190 | ||
173 | static int __devinit | 191 | static int __devinit |
diff --git a/drivers/gpu/drm/nouveau/nouveau_drm.h b/drivers/gpu/drm/nouveau/nouveau_drm.h index 6abd1a15e742..ab0c17430c66 100644 --- a/drivers/gpu/drm/nouveau/nouveau_drm.h +++ b/drivers/gpu/drm/nouveau/nouveau_drm.h | |||
@@ -97,6 +97,7 @@ struct nouveau_drm { | |||
97 | void *fence; | 97 | void *fence; |
98 | 98 | ||
99 | /* context for accelerated drm-internal operations */ | 99 | /* context for accelerated drm-internal operations */ |
100 | struct nouveau_channel *cechan; | ||
100 | struct nouveau_channel *channel; | 101 | struct nouveau_channel *channel; |
101 | struct nouveau_gpuobj *notify; | 102 | struct nouveau_gpuobj *notify; |
102 | struct nouveau_fbdev *fbcon; | 103 | struct nouveau_fbdev *fbcon; |