diff options
| author | Ben Skeggs <bskeggs@redhat.com> | 2012-05-07 21:22:27 -0400 |
|---|---|---|
| committer | Ben Skeggs <bskeggs@redhat.com> | 2012-07-25 20:28:16 -0400 |
| commit | 0ade74b6c6843892b52e6c2a4ac02183242eec27 (patch) | |
| tree | 6457434a0d81236d102dd4453b2ee66240f173a8 | |
| parent | 2a259a3d84c4409918c5d094f0969da58283a947 (diff) | |
drm/nv50: extend vblank semaphore to generic dmaobj + offset pair
Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
| -rw-r--r-- | drivers/gpu/drm/nouveau/nouveau_drv.h | 1 | ||||
| -rw-r--r-- | drivers/gpu/drm/nouveau/nouveau_notifier.c | 18 | ||||
| -rw-r--r-- | drivers/gpu/drm/nouveau/nouveau_software.h | 22 | ||||
| -rw-r--r-- | drivers/gpu/drm/nouveau/nv50_display.c | 25 | ||||
| -rw-r--r-- | drivers/gpu/drm/nouveau/nv50_software.c | 19 |
5 files changed, 32 insertions, 53 deletions
diff --git a/drivers/gpu/drm/nouveau/nouveau_drv.h b/drivers/gpu/drm/nouveau/nouveau_drv.h index a5dc98495125..03da38373552 100644 --- a/drivers/gpu/drm/nouveau/nouveau_drv.h +++ b/drivers/gpu/drm/nouveau/nouveau_drv.h | |||
| @@ -910,7 +910,6 @@ extern void nouveau_notifier_takedown_channel(struct nouveau_channel *); | |||
| 910 | extern int nouveau_notifier_alloc(struct nouveau_channel *, uint32_t handle, | 910 | extern int nouveau_notifier_alloc(struct nouveau_channel *, uint32_t handle, |
| 911 | int cout, uint32_t start, uint32_t end, | 911 | int cout, uint32_t start, uint32_t end, |
| 912 | uint32_t *offset); | 912 | uint32_t *offset); |
| 913 | extern int nouveau_notifier_offset(struct nouveau_gpuobj *, uint32_t *); | ||
| 914 | 913 | ||
| 915 | /* nouveau_channel.c */ | 914 | /* nouveau_channel.c */ |
| 916 | extern void nouveau_channel_cleanup(struct drm_device *, struct drm_file *); | 915 | extern void nouveau_channel_cleanup(struct drm_device *, struct drm_file *); |
diff --git a/drivers/gpu/drm/nouveau/nouveau_notifier.c b/drivers/gpu/drm/nouveau/nouveau_notifier.c index aa549155dcc1..69c93b864519 100644 --- a/drivers/gpu/drm/nouveau/nouveau_notifier.c +++ b/drivers/gpu/drm/nouveau/nouveau_notifier.c | |||
| @@ -161,21 +161,3 @@ nouveau_notifier_alloc(struct nouveau_channel *chan, uint32_t handle, | |||
| 161 | *b_offset = mem->start; | 161 | *b_offset = mem->start; |
| 162 | return 0; | 162 | return 0; |
| 163 | } | 163 | } |
| 164 | |||
| 165 | int | ||
| 166 | nouveau_notifier_offset(struct nouveau_gpuobj *nobj, uint32_t *poffset) | ||
| 167 | { | ||
| 168 | if (!nobj || nobj->dtor != nouveau_notifier_gpuobj_dtor) | ||
| 169 | return -EINVAL; | ||
| 170 | |||
| 171 | if (poffset) { | ||
| 172 | struct drm_mm_node *mem = nobj->priv; | ||
| 173 | |||
| 174 | if (*poffset >= mem->size) | ||
| 175 | return false; | ||
| 176 | |||
| 177 | *poffset += mem->start; | ||
| 178 | } | ||
| 179 | |||
| 180 | return 0; | ||
| 181 | } | ||
diff --git a/drivers/gpu/drm/nouveau/nouveau_software.h b/drivers/gpu/drm/nouveau/nouveau_software.h index e60bc6ce9003..9914cf154f65 100644 --- a/drivers/gpu/drm/nouveau/nouveau_software.h +++ b/drivers/gpu/drm/nouveau/nouveau_software.h | |||
| @@ -4,13 +4,15 @@ | |||
| 4 | struct nouveau_software_priv { | 4 | struct nouveau_software_priv { |
| 5 | struct nouveau_exec_engine base; | 5 | struct nouveau_exec_engine base; |
| 6 | struct list_head vblank; | 6 | struct list_head vblank; |
| 7 | spinlock_t peephole_lock; | ||
| 7 | }; | 8 | }; |
| 8 | 9 | ||
| 9 | struct nouveau_software_chan { | 10 | struct nouveau_software_chan { |
| 10 | struct list_head flip; | 11 | struct list_head flip; |
| 11 | struct { | 12 | struct { |
| 12 | struct list_head list; | 13 | struct list_head list; |
| 13 | struct nouveau_bo *bo; | 14 | u32 channel; |
| 15 | u32 ctxdma; | ||
| 14 | u32 offset; | 16 | u32 offset; |
| 15 | u32 value; | 17 | u32 value; |
| 16 | u32 head; | 18 | u32 head; |
| @@ -18,23 +20,6 @@ struct nouveau_software_chan { | |||
| 18 | }; | 20 | }; |
| 19 | 21 | ||
| 20 | static inline void | 22 | static inline void |
| 21 | nouveau_software_vblank(struct drm_device *dev, int crtc) | ||
| 22 | { | ||
| 23 | struct nouveau_software_priv *psw = nv_engine(dev, NVOBJ_ENGINE_SW); | ||
| 24 | struct nouveau_software_chan *pch, *tmp; | ||
| 25 | |||
| 26 | list_for_each_entry_safe(pch, tmp, &psw->vblank, vblank.list) { | ||
| 27 | if (pch->vblank.head != crtc) | ||
| 28 | continue; | ||
| 29 | |||
| 30 | nouveau_bo_wr32(pch->vblank.bo, pch->vblank.offset, | ||
| 31 | pch->vblank.value); | ||
| 32 | list_del(&pch->vblank.list); | ||
| 33 | drm_vblank_put(dev, crtc); | ||
| 34 | } | ||
| 35 | } | ||
| 36 | |||
| 37 | static inline void | ||
| 38 | nouveau_software_context_new(struct nouveau_software_chan *pch) | 23 | nouveau_software_context_new(struct nouveau_software_chan *pch) |
| 39 | { | 24 | { |
| 40 | INIT_LIST_HEAD(&pch->flip); | 25 | INIT_LIST_HEAD(&pch->flip); |
| @@ -44,6 +29,7 @@ static inline void | |||
| 44 | nouveau_software_create(struct nouveau_software_priv *psw) | 29 | nouveau_software_create(struct nouveau_software_priv *psw) |
| 45 | { | 30 | { |
| 46 | INIT_LIST_HEAD(&psw->vblank); | 31 | INIT_LIST_HEAD(&psw->vblank); |
| 32 | spin_lock_init(&psw->peephole_lock); | ||
| 47 | } | 33 | } |
| 48 | 34 | ||
| 49 | static inline u16 | 35 | static inline u16 |
diff --git a/drivers/gpu/drm/nouveau/nv50_display.c b/drivers/gpu/drm/nouveau/nv50_display.c index 5c41612723b4..b244d9968c5d 100644 --- a/drivers/gpu/drm/nouveau/nv50_display.c +++ b/drivers/gpu/drm/nouveau/nv50_display.c | |||
| @@ -646,7 +646,30 @@ nv50_display_script_select(struct drm_device *dev, struct dcb_entry *dcb, | |||
| 646 | static void | 646 | static void |
| 647 | nv50_display_vblank_crtc_handler(struct drm_device *dev, int crtc) | 647 | nv50_display_vblank_crtc_handler(struct drm_device *dev, int crtc) |
| 648 | { | 648 | { |
| 649 | nouveau_software_vblank(dev, crtc); | 649 | struct drm_nouveau_private *dev_priv = dev->dev_private; |
| 650 | struct nouveau_software_priv *psw = nv_engine(dev, NVOBJ_ENGINE_SW); | ||
| 651 | struct nouveau_software_chan *pch, *tmp; | ||
| 652 | |||
| 653 | list_for_each_entry_safe(pch, tmp, &psw->vblank, vblank.list) { | ||
| 654 | if (pch->vblank.head != crtc) | ||
| 655 | continue; | ||
| 656 | |||
| 657 | spin_lock(&psw->peephole_lock); | ||
| 658 | nv_wr32(dev, 0x001704, pch->vblank.channel); | ||
| 659 | nv_wr32(dev, 0x001710, 0x80000000 | pch->vblank.ctxdma); | ||
| 660 | if (dev_priv->chipset == 0x50) { | ||
| 661 | nv_wr32(dev, 0x001570, pch->vblank.offset); | ||
| 662 | nv_wr32(dev, 0x001574, pch->vblank.value); | ||
| 663 | } else { | ||
| 664 | nv_wr32(dev, 0x060010, pch->vblank.offset); | ||
| 665 | nv_wr32(dev, 0x060014, pch->vblank.value); | ||
| 666 | } | ||
| 667 | spin_unlock(&psw->peephole_lock); | ||
| 668 | |||
| 669 | list_del(&pch->vblank.list); | ||
| 670 | drm_vblank_put(dev, crtc); | ||
| 671 | } | ||
| 672 | |||
| 650 | drm_handle_vblank(dev, crtc); | 673 | drm_handle_vblank(dev, crtc); |
| 651 | } | 674 | } |
| 652 | 675 | ||
diff --git a/drivers/gpu/drm/nouveau/nv50_software.c b/drivers/gpu/drm/nouveau/nv50_software.c index 114d2517d4a8..df554d9dacb8 100644 --- a/drivers/gpu/drm/nouveau/nv50_software.c +++ b/drivers/gpu/drm/nouveau/nv50_software.c | |||
| @@ -36,9 +36,6 @@ struct nv50_software_priv { | |||
| 36 | 36 | ||
| 37 | struct nv50_software_chan { | 37 | struct nv50_software_chan { |
| 38 | struct nouveau_software_chan base; | 38 | struct nouveau_software_chan base; |
| 39 | struct { | ||
| 40 | struct nouveau_gpuobj *object; | ||
| 41 | } vblank; | ||
| 42 | }; | 39 | }; |
| 43 | 40 | ||
| 44 | static int | 41 | static int |
| @@ -51,11 +48,7 @@ mthd_dma_vblsem(struct nouveau_channel *chan, u32 class, u32 mthd, u32 data) | |||
| 51 | if (!gpuobj) | 48 | if (!gpuobj) |
| 52 | return -ENOENT; | 49 | return -ENOENT; |
| 53 | 50 | ||
| 54 | if (nouveau_notifier_offset(gpuobj, NULL)) | 51 | pch->base.vblank.ctxdma = gpuobj->cinst >> 4; |
| 55 | return -EINVAL; | ||
| 56 | |||
| 57 | pch->vblank.object = gpuobj; | ||
| 58 | pch->base.vblank.offset = ~0; | ||
| 59 | return 0; | 52 | return 0; |
| 60 | } | 53 | } |
| 61 | 54 | ||
| @@ -63,11 +56,7 @@ static int | |||
| 63 | mthd_vblsem_offset(struct nouveau_channel *chan, u32 class, u32 mthd, u32 data) | 56 | mthd_vblsem_offset(struct nouveau_channel *chan, u32 class, u32 mthd, u32 data) |
| 64 | { | 57 | { |
| 65 | struct nv50_software_chan *pch = chan->engctx[NVOBJ_ENGINE_SW]; | 58 | struct nv50_software_chan *pch = chan->engctx[NVOBJ_ENGINE_SW]; |
| 66 | 59 | pch->base.vblank.offset = data; | |
| 67 | if (nouveau_notifier_offset(pch->vblank.object, &data)) | ||
| 68 | return -ERANGE; | ||
| 69 | |||
| 70 | pch->base.vblank.offset = data >> 2; | ||
| 71 | return 0; | 60 | return 0; |
| 72 | } | 61 | } |
| 73 | 62 | ||
| @@ -86,7 +75,7 @@ mthd_vblsem_release(struct nouveau_channel *chan, u32 class, u32 mthd, u32 data) | |||
| 86 | struct nv50_software_chan *pch = chan->engctx[NVOBJ_ENGINE_SW]; | 75 | struct nv50_software_chan *pch = chan->engctx[NVOBJ_ENGINE_SW]; |
| 87 | struct drm_device *dev = chan->dev; | 76 | struct drm_device *dev = chan->dev; |
| 88 | 77 | ||
| 89 | if (!pch->vblank.object || pch->base.vblank.offset == ~0 || data > 1) | 78 | if (data > 1) |
| 90 | return -EINVAL; | 79 | return -EINVAL; |
| 91 | 80 | ||
| 92 | drm_vblank_get(dev, data); | 81 | drm_vblank_get(dev, data); |
| @@ -116,7 +105,7 @@ nv50_software_context_new(struct nouveau_channel *chan, int engine) | |||
| 116 | return -ENOMEM; | 105 | return -ENOMEM; |
| 117 | 106 | ||
| 118 | nouveau_software_context_new(&pch->base); | 107 | nouveau_software_context_new(&pch->base); |
| 119 | pch->base.vblank.bo = chan->notifier_bo; | 108 | pch->base.vblank.channel = chan->ramin->vinst >> 12; |
| 120 | chan->engctx[engine] = pch; | 109 | chan->engctx[engine] = pch; |
| 121 | 110 | ||
| 122 | /* dma objects for display sync channel semaphore blocks */ | 111 | /* dma objects for display sync channel semaphore blocks */ |
