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 /drivers | |
parent | 2a259a3d84c4409918c5d094f0969da58283a947 (diff) |
drm/nv50: extend vblank semaphore to generic dmaobj + offset pair
Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
Diffstat (limited to 'drivers')
-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 */ |