diff options
author | Ben Skeggs <bskeggs@redhat.com> | 2011-02-06 22:29:23 -0500 |
---|---|---|
committer | Ben Skeggs <bskeggs@redhat.com> | 2011-02-24 15:45:11 -0500 |
commit | cdccc70eff1eaf3627a716374f9ebc115fc4621c (patch) | |
tree | 744a5a9e35c5749326d3bfb85336afceb24c2b4d /drivers/gpu/drm/nouveau/nv50_evo.c | |
parent | 45c4e0aae96c6354bf5131a282a74fe38d032de3 (diff) |
drm/nv50-nvc0: initialise display sync channels
Also imports a couple of helper functions that'll be used to implement
page flipping in the following commits..
Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
Diffstat (limited to 'drivers/gpu/drm/nouveau/nv50_evo.c')
-rw-r--r-- | drivers/gpu/drm/nouveau/nv50_evo.c | 88 |
1 files changed, 84 insertions, 4 deletions
diff --git a/drivers/gpu/drm/nouveau/nv50_evo.c b/drivers/gpu/drm/nouveau/nv50_evo.c index b70208e981fb..18fbf27376c1 100644 --- a/drivers/gpu/drm/nouveau/nv50_evo.c +++ b/drivers/gpu/drm/nouveau/nv50_evo.c | |||
@@ -220,7 +220,15 @@ static void | |||
220 | nv50_evo_destroy(struct drm_device *dev) | 220 | nv50_evo_destroy(struct drm_device *dev) |
221 | { | 221 | { |
222 | struct nv50_display *disp = nv50_display(dev); | 222 | struct nv50_display *disp = nv50_display(dev); |
223 | 223 | int i; | |
224 | |||
225 | for (i = 0; i < 2; i++) { | ||
226 | if (disp->crtc[i].sem.bo) { | ||
227 | nouveau_bo_unmap(disp->crtc[i].sem.bo); | ||
228 | nouveau_bo_ref(NULL, &disp->crtc[i].sem.bo); | ||
229 | } | ||
230 | nv50_evo_channel_del(&disp->crtc[i].sync); | ||
231 | } | ||
224 | nouveau_gpuobj_ref(NULL, &disp->ntfy); | 232 | nouveau_gpuobj_ref(NULL, &disp->ntfy); |
225 | nv50_evo_channel_del(&disp->master); | 233 | nv50_evo_channel_del(&disp->master); |
226 | } | 234 | } |
@@ -232,7 +240,7 @@ nv50_evo_create(struct drm_device *dev) | |||
232 | struct nv50_display *disp = nv50_display(dev); | 240 | struct nv50_display *disp = nv50_display(dev); |
233 | struct nouveau_gpuobj *ramht = NULL; | 241 | struct nouveau_gpuobj *ramht = NULL; |
234 | struct nouveau_channel *evo; | 242 | struct nouveau_channel *evo; |
235 | int ret; | 243 | int ret, i, j; |
236 | 244 | ||
237 | /* create primary evo channel, the one we use for modesetting | 245 | /* create primary evo channel, the one we use for modesetting |
238 | * purporses | 246 | * purporses |
@@ -311,6 +319,61 @@ nv50_evo_create(struct drm_device *dev) | |||
311 | if (ret) | 319 | if (ret) |
312 | goto err; | 320 | goto err; |
313 | 321 | ||
322 | /* create "display sync" channels and other structures we need | ||
323 | * to implement page flipping | ||
324 | */ | ||
325 | for (i = 0; i < 2; i++) { | ||
326 | struct nv50_display_crtc *dispc = &disp->crtc[i]; | ||
327 | u64 offset; | ||
328 | |||
329 | ret = nv50_evo_channel_new(dev, 1 + i, &dispc->sync); | ||
330 | if (ret) | ||
331 | goto err; | ||
332 | |||
333 | ret = nouveau_bo_new(dev, NULL, 4096, 0x1000, TTM_PL_FLAG_VRAM, | ||
334 | 0, 0x0000, false, true, &dispc->sem.bo); | ||
335 | if (!ret) { | ||
336 | offset = dispc->sem.bo->bo.mem.start << PAGE_SHIFT; | ||
337 | |||
338 | ret = nouveau_bo_pin(dispc->sem.bo, TTM_PL_FLAG_VRAM); | ||
339 | if (!ret) | ||
340 | ret = nouveau_bo_map(dispc->sem.bo); | ||
341 | if (ret) | ||
342 | nouveau_bo_ref(NULL, &dispc->sem.bo); | ||
343 | } | ||
344 | |||
345 | if (ret) | ||
346 | goto err; | ||
347 | |||
348 | ret = nv50_evo_dmaobj_new(dispc->sync, NvEvoSync, 0x0000, | ||
349 | offset, 4096, NULL); | ||
350 | if (ret) | ||
351 | goto err; | ||
352 | |||
353 | ret = nv50_evo_dmaobj_new(dispc->sync, NvEvoVRAM_LP, 0x80000000, | ||
354 | 0, dev_priv->vram_size, NULL); | ||
355 | if (ret) | ||
356 | goto err; | ||
357 | |||
358 | ret = nv50_evo_dmaobj_new(dispc->sync, NvEvoFB32, 0x80000000 | | ||
359 | (dev_priv->chipset < 0xc0 ? | ||
360 | 0x7a00 : 0xfe00), | ||
361 | 0, dev_priv->vram_size, NULL); | ||
362 | if (ret) | ||
363 | goto err; | ||
364 | |||
365 | ret = nv50_evo_dmaobj_new(dispc->sync, NvEvoFB16, 0x80000000 | | ||
366 | (dev_priv->chipset < 0xc0 ? | ||
367 | 0x7000 : 0xfe00), | ||
368 | 0, dev_priv->vram_size, NULL); | ||
369 | if (ret) | ||
370 | goto err; | ||
371 | |||
372 | for (j = 0; j < 4096; j += 4) | ||
373 | nouveau_bo_wr32(dispc->sem.bo, j / 4, 0x74b1e000); | ||
374 | dispc->sem.offset = 0; | ||
375 | } | ||
376 | |||
314 | return 0; | 377 | return 0; |
315 | 378 | ||
316 | err: | 379 | err: |
@@ -322,7 +385,7 @@ int | |||
322 | nv50_evo_init(struct drm_device *dev) | 385 | nv50_evo_init(struct drm_device *dev) |
323 | { | 386 | { |
324 | struct nv50_display *disp = nv50_display(dev); | 387 | struct nv50_display *disp = nv50_display(dev); |
325 | int ret; | 388 | int ret, i; |
326 | 389 | ||
327 | if (!disp->master) { | 390 | if (!disp->master) { |
328 | ret = nv50_evo_create(dev); | 391 | ret = nv50_evo_create(dev); |
@@ -330,15 +393,32 @@ nv50_evo_init(struct drm_device *dev) | |||
330 | return ret; | 393 | return ret; |
331 | } | 394 | } |
332 | 395 | ||
333 | return nv50_evo_channel_init(disp->master); | 396 | ret = nv50_evo_channel_init(disp->master); |
397 | if (ret) | ||
398 | return ret; | ||
399 | |||
400 | for (i = 0; i < 2; i++) { | ||
401 | ret = nv50_evo_channel_init(disp->crtc[i].sync); | ||
402 | if (ret) | ||
403 | return ret; | ||
404 | } | ||
405 | |||
406 | return 0; | ||
334 | } | 407 | } |
335 | 408 | ||
336 | void | 409 | void |
337 | nv50_evo_fini(struct drm_device *dev) | 410 | nv50_evo_fini(struct drm_device *dev) |
338 | { | 411 | { |
339 | struct nv50_display *disp = nv50_display(dev); | 412 | struct nv50_display *disp = nv50_display(dev); |
413 | int i; | ||
414 | |||
415 | for (i = 0; i < 2; i++) { | ||
416 | if (disp->crtc[i].sync) | ||
417 | nv50_evo_channel_fini(disp->crtc[i].sync); | ||
418 | } | ||
340 | 419 | ||
341 | if (disp->master) | 420 | if (disp->master) |
342 | nv50_evo_channel_fini(disp->master); | 421 | nv50_evo_channel_fini(disp->master); |
422 | |||
343 | nv50_evo_destroy(dev); | 423 | nv50_evo_destroy(dev); |
344 | } | 424 | } |