diff options
author | Francisco Jerez <currojerez@riseup.net> | 2010-10-20 17:35:40 -0400 |
---|---|---|
committer | Ben Skeggs <bskeggs@redhat.com> | 2010-12-03 00:11:12 -0500 |
commit | 332b242f47786d1a43bd7a19a0513dd5d493db8e (patch) | |
tree | f6681c1513c58db54f71c64184ebc033a14c49fe /drivers/gpu | |
parent | 042206c0cd4924879c4292c5ffa2bf1e8023ae5a (diff) |
drm/nouveau: Implement the pageflip ioctl.
nv0x-nv4x should be mostly fine, nv50 doesn't work yet.
Signed-off-by: Francisco Jerez <currojerez@riseup.net>
Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
Diffstat (limited to 'drivers/gpu')
-rw-r--r-- | drivers/gpu/drm/nouveau/nouveau_bo.c | 12 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nouveau_channel.c | 1 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nouveau_display.c | 180 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nouveau_drv.h | 16 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nouveau_gem.c | 11 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nouveau_state.c | 3 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nv04_crtc.c | 1 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nv04_graph.c | 16 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nv10_graph.c | 4 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nv20_graph.c | 8 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nv40_graph.c | 4 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nv50_crtc.c | 1 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nv50_graph.c | 16 |
13 files changed, 264 insertions, 9 deletions
diff --git a/drivers/gpu/drm/nouveau/nouveau_bo.c b/drivers/gpu/drm/nouveau/nouveau_bo.c index c09928322eb9..cdc8f544d47f 100644 --- a/drivers/gpu/drm/nouveau/nouveau_bo.c +++ b/drivers/gpu/drm/nouveau/nouveau_bo.c | |||
@@ -942,6 +942,18 @@ nouveau_ttm_fault_reserve_notify(struct ttm_buffer_object *bo) | |||
942 | return ttm_bo_validate(bo, &nvbo->placement, false, true, false); | 942 | return ttm_bo_validate(bo, &nvbo->placement, false, true, false); |
943 | } | 943 | } |
944 | 944 | ||
945 | void | ||
946 | nouveau_bo_fence(struct nouveau_bo *nvbo, struct nouveau_fence *fence) | ||
947 | { | ||
948 | spin_lock(&nvbo->bo.bdev->fence_lock); | ||
949 | __nouveau_fence_unref(&nvbo->bo.sync_obj); | ||
950 | |||
951 | if (likely(fence)) | ||
952 | nvbo->bo.sync_obj = nouveau_fence_ref(fence); | ||
953 | |||
954 | spin_unlock(&nvbo->bo.bdev->fence_lock); | ||
955 | } | ||
956 | |||
945 | struct ttm_bo_driver nouveau_bo_driver = { | 957 | struct ttm_bo_driver nouveau_bo_driver = { |
946 | .create_ttm_backend_entry = nouveau_bo_create_ttm_backend_entry, | 958 | .create_ttm_backend_entry = nouveau_bo_create_ttm_backend_entry, |
947 | .invalidate_caches = nouveau_bo_invalidate_caches, | 959 | .invalidate_caches = nouveau_bo_invalidate_caches, |
diff --git a/drivers/gpu/drm/nouveau/nouveau_channel.c b/drivers/gpu/drm/nouveau/nouveau_channel.c index c9cdbd786dae..11b2370e16da 100644 --- a/drivers/gpu/drm/nouveau/nouveau_channel.c +++ b/drivers/gpu/drm/nouveau/nouveau_channel.c | |||
@@ -148,6 +148,7 @@ nouveau_channel_alloc(struct drm_device *dev, struct nouveau_channel **chan_ret, | |||
148 | 148 | ||
149 | NV_DEBUG(dev, "initialising channel %d\n", chan->id); | 149 | NV_DEBUG(dev, "initialising channel %d\n", chan->id); |
150 | INIT_LIST_HEAD(&chan->nvsw.vbl_wait); | 150 | INIT_LIST_HEAD(&chan->nvsw.vbl_wait); |
151 | INIT_LIST_HEAD(&chan->nvsw.flip); | ||
151 | INIT_LIST_HEAD(&chan->fence.pending); | 152 | INIT_LIST_HEAD(&chan->fence.pending); |
152 | 153 | ||
153 | /* Allocate DMA push buffer */ | 154 | /* Allocate DMA push buffer */ |
diff --git a/drivers/gpu/drm/nouveau/nouveau_display.c b/drivers/gpu/drm/nouveau/nouveau_display.c index f8987bcb7f51..505c6bfb4d75 100644 --- a/drivers/gpu/drm/nouveau/nouveau_display.c +++ b/drivers/gpu/drm/nouveau/nouveau_display.c | |||
@@ -30,6 +30,8 @@ | |||
30 | #include "nouveau_fb.h" | 30 | #include "nouveau_fb.h" |
31 | #include "nouveau_fbcon.h" | 31 | #include "nouveau_fbcon.h" |
32 | #include "nouveau_hw.h" | 32 | #include "nouveau_hw.h" |
33 | #include "nouveau_crtc.h" | ||
34 | #include "nouveau_dma.h" | ||
33 | 35 | ||
34 | static void | 36 | static void |
35 | nouveau_user_framebuffer_destroy(struct drm_framebuffer *drm_fb) | 37 | nouveau_user_framebuffer_destroy(struct drm_framebuffer *drm_fb) |
@@ -131,3 +133,181 @@ nouveau_vblank_disable(struct drm_device *dev, int crtc) | |||
131 | else | 133 | else |
132 | NVWriteCRTC(dev, crtc, NV_PCRTC_INTR_EN_0, 0); | 134 | NVWriteCRTC(dev, crtc, NV_PCRTC_INTR_EN_0, 0); |
133 | } | 135 | } |
136 | |||
137 | static int | ||
138 | nouveau_page_flip_reserve(struct nouveau_bo *old_bo, | ||
139 | struct nouveau_bo *new_bo) | ||
140 | { | ||
141 | int ret; | ||
142 | |||
143 | ret = nouveau_bo_pin(new_bo, TTM_PL_FLAG_VRAM); | ||
144 | if (ret) | ||
145 | return ret; | ||
146 | |||
147 | ret = ttm_bo_reserve(&new_bo->bo, false, false, false, 0); | ||
148 | if (ret) | ||
149 | goto fail; | ||
150 | |||
151 | ret = ttm_bo_reserve(&old_bo->bo, false, false, false, 0); | ||
152 | if (ret) | ||
153 | goto fail_unreserve; | ||
154 | |||
155 | return 0; | ||
156 | |||
157 | fail_unreserve: | ||
158 | ttm_bo_unreserve(&new_bo->bo); | ||
159 | fail: | ||
160 | nouveau_bo_unpin(new_bo); | ||
161 | return ret; | ||
162 | } | ||
163 | |||
164 | static void | ||
165 | nouveau_page_flip_unreserve(struct nouveau_bo *old_bo, | ||
166 | struct nouveau_bo *new_bo, | ||
167 | struct nouveau_fence *fence) | ||
168 | { | ||
169 | nouveau_bo_fence(new_bo, fence); | ||
170 | ttm_bo_unreserve(&new_bo->bo); | ||
171 | |||
172 | nouveau_bo_fence(old_bo, fence); | ||
173 | ttm_bo_unreserve(&old_bo->bo); | ||
174 | |||
175 | nouveau_bo_unpin(old_bo); | ||
176 | } | ||
177 | |||
178 | static int | ||
179 | nouveau_page_flip_emit(struct nouveau_channel *chan, | ||
180 | struct nouveau_bo *old_bo, | ||
181 | struct nouveau_bo *new_bo, | ||
182 | struct nouveau_page_flip_state *s, | ||
183 | struct nouveau_fence **pfence) | ||
184 | { | ||
185 | struct drm_device *dev = chan->dev; | ||
186 | unsigned long flags; | ||
187 | int ret; | ||
188 | |||
189 | /* Queue it to the pending list */ | ||
190 | spin_lock_irqsave(&dev->event_lock, flags); | ||
191 | list_add_tail(&s->head, &chan->nvsw.flip); | ||
192 | spin_unlock_irqrestore(&dev->event_lock, flags); | ||
193 | |||
194 | /* Synchronize with the old framebuffer */ | ||
195 | ret = nouveau_fence_sync(old_bo->bo.sync_obj, chan); | ||
196 | if (ret) | ||
197 | goto fail; | ||
198 | |||
199 | /* Emit the pageflip */ | ||
200 | ret = RING_SPACE(chan, 2); | ||
201 | if (ret) | ||
202 | goto fail; | ||
203 | |||
204 | BEGIN_RING(chan, NvSubSw, NV_SW_PAGE_FLIP, 1); | ||
205 | OUT_RING(chan, 0); | ||
206 | FIRE_RING(chan); | ||
207 | |||
208 | ret = nouveau_fence_new(chan, pfence, true); | ||
209 | if (ret) | ||
210 | goto fail; | ||
211 | |||
212 | return 0; | ||
213 | fail: | ||
214 | spin_lock_irqsave(&dev->event_lock, flags); | ||
215 | list_del(&s->head); | ||
216 | spin_unlock_irqrestore(&dev->event_lock, flags); | ||
217 | return ret; | ||
218 | } | ||
219 | |||
220 | int | ||
221 | nouveau_crtc_page_flip(struct drm_crtc *crtc, struct drm_framebuffer *fb, | ||
222 | struct drm_pending_vblank_event *event) | ||
223 | { | ||
224 | struct drm_device *dev = crtc->dev; | ||
225 | struct drm_nouveau_private *dev_priv = dev->dev_private; | ||
226 | struct nouveau_bo *old_bo = nouveau_framebuffer(crtc->fb)->nvbo; | ||
227 | struct nouveau_bo *new_bo = nouveau_framebuffer(fb)->nvbo; | ||
228 | struct nouveau_page_flip_state *s; | ||
229 | struct nouveau_channel *chan; | ||
230 | struct nouveau_fence *fence; | ||
231 | int ret; | ||
232 | |||
233 | if (dev_priv->engine.graph.accel_blocked) | ||
234 | return -ENODEV; | ||
235 | |||
236 | s = kzalloc(sizeof(*s), GFP_KERNEL); | ||
237 | if (!s) | ||
238 | return -ENOMEM; | ||
239 | |||
240 | /* Don't let the buffers go away while we flip */ | ||
241 | ret = nouveau_page_flip_reserve(old_bo, new_bo); | ||
242 | if (ret) | ||
243 | goto fail_free; | ||
244 | |||
245 | /* Initialize a page flip struct */ | ||
246 | *s = (struct nouveau_page_flip_state) | ||
247 | { { }, s->event, nouveau_crtc(crtc)->index, | ||
248 | fb->bits_per_pixel, fb->pitch, crtc->x, crtc->y, | ||
249 | new_bo->bo.offset }; | ||
250 | |||
251 | /* Choose the channel the flip will be handled in */ | ||
252 | chan = nouveau_fence_channel(new_bo->bo.sync_obj); | ||
253 | if (!chan) | ||
254 | chan = nouveau_channel_get_unlocked(dev_priv->channel); | ||
255 | mutex_lock(&chan->mutex); | ||
256 | |||
257 | /* Emit a page flip */ | ||
258 | ret = nouveau_page_flip_emit(chan, old_bo, new_bo, s, &fence); | ||
259 | nouveau_channel_put(&chan); | ||
260 | if (ret) | ||
261 | goto fail_unreserve; | ||
262 | |||
263 | /* Update the crtc struct and cleanup */ | ||
264 | crtc->fb = fb; | ||
265 | |||
266 | nouveau_page_flip_unreserve(old_bo, new_bo, fence); | ||
267 | nouveau_fence_unref(&fence); | ||
268 | return 0; | ||
269 | |||
270 | fail_unreserve: | ||
271 | nouveau_page_flip_unreserve(old_bo, new_bo, NULL); | ||
272 | fail_free: | ||
273 | kfree(s); | ||
274 | return ret; | ||
275 | } | ||
276 | |||
277 | int | ||
278 | nouveau_finish_page_flip(struct nouveau_channel *chan, | ||
279 | struct nouveau_page_flip_state *ps) | ||
280 | { | ||
281 | struct drm_device *dev = chan->dev; | ||
282 | struct nouveau_page_flip_state *s; | ||
283 | unsigned long flags; | ||
284 | |||
285 | spin_lock_irqsave(&dev->event_lock, flags); | ||
286 | |||
287 | if (list_empty(&chan->nvsw.flip)) { | ||
288 | NV_ERROR(dev, "Unexpected pageflip in channel %d.\n", chan->id); | ||
289 | spin_unlock_irqrestore(&dev->event_lock, flags); | ||
290 | return -EINVAL; | ||
291 | } | ||
292 | |||
293 | s = list_first_entry(&chan->nvsw.flip, | ||
294 | struct nouveau_page_flip_state, head); | ||
295 | if (s->event) { | ||
296 | struct drm_pending_vblank_event *e = s->event; | ||
297 | struct timeval now; | ||
298 | |||
299 | do_gettimeofday(&now); | ||
300 | e->event.sequence = 0; | ||
301 | e->event.tv_sec = now.tv_sec; | ||
302 | e->event.tv_usec = now.tv_usec; | ||
303 | list_add_tail(&e->base.link, &e->base.file_priv->event_list); | ||
304 | wake_up_interruptible(&e->base.file_priv->event_wait); | ||
305 | } | ||
306 | |||
307 | list_del(&s->head); | ||
308 | *ps = *s; | ||
309 | kfree(s); | ||
310 | |||
311 | spin_unlock_irqrestore(&dev->event_lock, flags); | ||
312 | return 0; | ||
313 | } | ||
diff --git a/drivers/gpu/drm/nouveau/nouveau_drv.h b/drivers/gpu/drm/nouveau/nouveau_drv.h index 7cf034fd5cd0..2bb1f1572a55 100644 --- a/drivers/gpu/drm/nouveau/nouveau_drv.h +++ b/drivers/gpu/drm/nouveau/nouveau_drv.h | |||
@@ -166,6 +166,13 @@ struct nouveau_gpuobj { | |||
166 | void *priv; | 166 | void *priv; |
167 | }; | 167 | }; |
168 | 168 | ||
169 | struct nouveau_page_flip_state { | ||
170 | struct list_head head; | ||
171 | struct drm_pending_vblank_event *event; | ||
172 | int crtc, bpp, pitch, x, y; | ||
173 | uint64_t offset; | ||
174 | }; | ||
175 | |||
169 | struct nouveau_channel { | 176 | struct nouveau_channel { |
170 | struct drm_device *dev; | 177 | struct drm_device *dev; |
171 | int id; | 178 | int id; |
@@ -253,6 +260,7 @@ struct nouveau_channel { | |||
253 | uint32_t vblsem_offset; | 260 | uint32_t vblsem_offset; |
254 | uint32_t vblsem_rval; | 261 | uint32_t vblsem_rval; |
255 | struct list_head vbl_wait; | 262 | struct list_head vbl_wait; |
263 | struct list_head flip; | ||
256 | } nvsw; | 264 | } nvsw; |
257 | 265 | ||
258 | struct { | 266 | struct { |
@@ -1076,6 +1084,8 @@ extern void nv04_graph_destroy_context(struct nouveau_channel *); | |||
1076 | extern int nv04_graph_load_context(struct nouveau_channel *); | 1084 | extern int nv04_graph_load_context(struct nouveau_channel *); |
1077 | extern int nv04_graph_unload_context(struct drm_device *); | 1085 | extern int nv04_graph_unload_context(struct drm_device *); |
1078 | extern void nv04_graph_context_switch(struct drm_device *); | 1086 | extern void nv04_graph_context_switch(struct drm_device *); |
1087 | extern int nv04_graph_mthd_page_flip(struct nouveau_channel *chan, | ||
1088 | u32 class, u32 mthd, u32 data); | ||
1079 | 1089 | ||
1080 | /* nv10_graph.c */ | 1090 | /* nv10_graph.c */ |
1081 | extern int nv10_graph_init(struct drm_device *); | 1091 | extern int nv10_graph_init(struct drm_device *); |
@@ -1249,6 +1259,7 @@ extern u16 nouveau_bo_rd16(struct nouveau_bo *nvbo, unsigned index); | |||
1249 | extern void nouveau_bo_wr16(struct nouveau_bo *nvbo, unsigned index, u16 val); | 1259 | extern void nouveau_bo_wr16(struct nouveau_bo *nvbo, unsigned index, u16 val); |
1250 | extern u32 nouveau_bo_rd32(struct nouveau_bo *nvbo, unsigned index); | 1260 | extern u32 nouveau_bo_rd32(struct nouveau_bo *nvbo, unsigned index); |
1251 | extern void nouveau_bo_wr32(struct nouveau_bo *nvbo, unsigned index, u32 val); | 1261 | extern void nouveau_bo_wr32(struct nouveau_bo *nvbo, unsigned index, u32 val); |
1262 | extern void nouveau_bo_fence(struct nouveau_bo *, struct nouveau_fence *); | ||
1252 | 1263 | ||
1253 | /* nouveau_fence.c */ | 1264 | /* nouveau_fence.c */ |
1254 | struct nouveau_fence; | 1265 | struct nouveau_fence; |
@@ -1315,6 +1326,10 @@ extern int nouveau_gem_ioctl_info(struct drm_device *, void *, | |||
1315 | /* nouveau_display.c */ | 1326 | /* nouveau_display.c */ |
1316 | int nouveau_vblank_enable(struct drm_device *dev, int crtc); | 1327 | int nouveau_vblank_enable(struct drm_device *dev, int crtc); |
1317 | void nouveau_vblank_disable(struct drm_device *dev, int crtc); | 1328 | void nouveau_vblank_disable(struct drm_device *dev, int crtc); |
1329 | int nouveau_crtc_page_flip(struct drm_crtc *crtc, struct drm_framebuffer *fb, | ||
1330 | struct drm_pending_vblank_event *event); | ||
1331 | int nouveau_finish_page_flip(struct nouveau_channel *, | ||
1332 | struct nouveau_page_flip_state *); | ||
1318 | 1333 | ||
1319 | /* nv10_gpio.c */ | 1334 | /* nv10_gpio.c */ |
1320 | int nv10_gpio_get(struct drm_device *dev, enum dcb_gpio_tag tag); | 1335 | int nv10_gpio_get(struct drm_device *dev, enum dcb_gpio_tag tag); |
@@ -1514,5 +1529,6 @@ nv_match_device(struct drm_device *dev, unsigned device, | |||
1514 | #define NV_SW_VBLSEM_OFFSET 0x00000400 | 1529 | #define NV_SW_VBLSEM_OFFSET 0x00000400 |
1515 | #define NV_SW_VBLSEM_RELEASE_VALUE 0x00000404 | 1530 | #define NV_SW_VBLSEM_RELEASE_VALUE 0x00000404 |
1516 | #define NV_SW_VBLSEM_RELEASE 0x00000408 | 1531 | #define NV_SW_VBLSEM_RELEASE 0x00000408 |
1532 | #define NV_SW_PAGE_FLIP 0x00000500 | ||
1517 | 1533 | ||
1518 | #endif /* __NOUVEAU_DRV_H__ */ | 1534 | #endif /* __NOUVEAU_DRV_H__ */ |
diff --git a/drivers/gpu/drm/nouveau/nouveau_gem.c b/drivers/gpu/drm/nouveau/nouveau_gem.c index de8535b58710..9886b644f27d 100644 --- a/drivers/gpu/drm/nouveau/nouveau_gem.c +++ b/drivers/gpu/drm/nouveau/nouveau_gem.c | |||
@@ -231,15 +231,8 @@ validate_fini_list(struct list_head *list, struct nouveau_fence *fence) | |||
231 | 231 | ||
232 | list_for_each_safe(entry, tmp, list) { | 232 | list_for_each_safe(entry, tmp, list) { |
233 | nvbo = list_entry(entry, struct nouveau_bo, entry); | 233 | nvbo = list_entry(entry, struct nouveau_bo, entry); |
234 | if (likely(fence)) { | 234 | |
235 | struct nouveau_fence *prev_fence; | 235 | nouveau_bo_fence(nvbo, fence); |
236 | |||
237 | spin_lock(&nvbo->bo.bdev->fence_lock); | ||
238 | prev_fence = nvbo->bo.sync_obj; | ||
239 | nvbo->bo.sync_obj = nouveau_fence_ref(fence); | ||
240 | spin_unlock(&nvbo->bo.bdev->fence_lock); | ||
241 | nouveau_fence_unref(&prev_fence); | ||
242 | } | ||
243 | 236 | ||
244 | if (unlikely(nvbo->validate_mapped)) { | 237 | if (unlikely(nvbo->validate_mapped)) { |
245 | ttm_bo_kunmap(&nvbo->kmap); | 238 | ttm_bo_kunmap(&nvbo->kmap); |
diff --git a/drivers/gpu/drm/nouveau/nouveau_state.c b/drivers/gpu/drm/nouveau/nouveau_state.c index d72aa8d19a19..ec9d193b6f61 100644 --- a/drivers/gpu/drm/nouveau/nouveau_state.c +++ b/drivers/gpu/drm/nouveau/nouveau_state.c | |||
@@ -1090,6 +1090,9 @@ int nouveau_ioctl_getparam(struct drm_device *dev, void *data, | |||
1090 | case NOUVEAU_GETPARAM_HAS_BO_USAGE: | 1090 | case NOUVEAU_GETPARAM_HAS_BO_USAGE: |
1091 | getparam->value = 1; | 1091 | getparam->value = 1; |
1092 | break; | 1092 | break; |
1093 | case NOUVEAU_GETPARAM_HAS_PAGEFLIP: | ||
1094 | getparam->value = (dev_priv->card_type < NV_50); | ||
1095 | break; | ||
1093 | case NOUVEAU_GETPARAM_GRAPH_UNITS: | 1096 | case NOUVEAU_GETPARAM_GRAPH_UNITS: |
1094 | /* NV40 and NV50 versions are quite different, but register | 1097 | /* NV40 and NV50 versions are quite different, but register |
1095 | * address is the same. User is supposed to know the card | 1098 | * address is the same. User is supposed to know the card |
diff --git a/drivers/gpu/drm/nouveau/nv04_crtc.c b/drivers/gpu/drm/nouveau/nv04_crtc.c index b61a7ff8b7b7..e4aea721971f 100644 --- a/drivers/gpu/drm/nouveau/nv04_crtc.c +++ b/drivers/gpu/drm/nouveau/nv04_crtc.c | |||
@@ -989,6 +989,7 @@ static const struct drm_crtc_funcs nv04_crtc_funcs = { | |||
989 | .cursor_move = nv04_crtc_cursor_move, | 989 | .cursor_move = nv04_crtc_cursor_move, |
990 | .gamma_set = nv_crtc_gamma_set, | 990 | .gamma_set = nv_crtc_gamma_set, |
991 | .set_config = drm_crtc_helper_set_config, | 991 | .set_config = drm_crtc_helper_set_config, |
992 | .page_flip = nouveau_crtc_page_flip, | ||
992 | .destroy = nv_crtc_destroy, | 993 | .destroy = nv_crtc_destroy, |
993 | }; | 994 | }; |
994 | 995 | ||
diff --git a/drivers/gpu/drm/nouveau/nv04_graph.c b/drivers/gpu/drm/nouveau/nv04_graph.c index 81aba097ef95..239519aefce6 100644 --- a/drivers/gpu/drm/nouveau/nv04_graph.c +++ b/drivers/gpu/drm/nouveau/nv04_graph.c | |||
@@ -26,6 +26,7 @@ | |||
26 | #include "drm.h" | 26 | #include "drm.h" |
27 | #include "nouveau_drm.h" | 27 | #include "nouveau_drm.h" |
28 | #include "nouveau_drv.h" | 28 | #include "nouveau_drv.h" |
29 | #include "nouveau_hw.h" | ||
29 | 30 | ||
30 | static int nv04_graph_register(struct drm_device *dev); | 31 | static int nv04_graph_register(struct drm_device *dev); |
31 | 32 | ||
@@ -553,6 +554,20 @@ nv04_graph_mthd_set_ref(struct nouveau_channel *chan, | |||
553 | return 0; | 554 | return 0; |
554 | } | 555 | } |
555 | 556 | ||
557 | int | ||
558 | nv04_graph_mthd_page_flip(struct nouveau_channel *chan, | ||
559 | u32 class, u32 mthd, u32 data) | ||
560 | { | ||
561 | struct drm_device *dev = chan->dev; | ||
562 | struct nouveau_page_flip_state s; | ||
563 | |||
564 | if (!nouveau_finish_page_flip(chan, &s)) | ||
565 | nv_set_crtc_base(dev, s.crtc, | ||
566 | s.offset + s.y * s.pitch + s.x * s.bpp / 8); | ||
567 | |||
568 | return 0; | ||
569 | } | ||
570 | |||
556 | /* | 571 | /* |
557 | * Software methods, why they are needed, and how they all work: | 572 | * Software methods, why they are needed, and how they all work: |
558 | * | 573 | * |
@@ -1204,6 +1219,7 @@ nv04_graph_register(struct drm_device *dev) | |||
1204 | /* nvsw */ | 1219 | /* nvsw */ |
1205 | NVOBJ_CLASS(dev, 0x506e, SW); | 1220 | NVOBJ_CLASS(dev, 0x506e, SW); |
1206 | NVOBJ_MTHD (dev, 0x506e, 0x0150, nv04_graph_mthd_set_ref); | 1221 | NVOBJ_MTHD (dev, 0x506e, 0x0150, nv04_graph_mthd_set_ref); |
1222 | NVOBJ_MTHD (dev, 0x506e, 0x0500, nv04_graph_mthd_page_flip); | ||
1207 | 1223 | ||
1208 | dev_priv->engine.graph.registered = true; | 1224 | dev_priv->engine.graph.registered = true; |
1209 | return 0; | 1225 | return 0; |
diff --git a/drivers/gpu/drm/nouveau/nv10_graph.c b/drivers/gpu/drm/nouveau/nv10_graph.c index a571bfd4471b..3fbb49dfc09c 100644 --- a/drivers/gpu/drm/nouveau/nv10_graph.c +++ b/drivers/gpu/drm/nouveau/nv10_graph.c | |||
@@ -1113,6 +1113,10 @@ nv10_graph_register(struct drm_device *dev) | |||
1113 | NVOBJ_MTHD (dev, 0x0099, 0x1658, nv17_graph_mthd_lma_enable); | 1113 | NVOBJ_MTHD (dev, 0x0099, 0x1658, nv17_graph_mthd_lma_enable); |
1114 | } | 1114 | } |
1115 | 1115 | ||
1116 | /* nvsw */ | ||
1117 | NVOBJ_CLASS(dev, 0x506e, SW); | ||
1118 | NVOBJ_MTHD (dev, 0x506e, 0x0500, nv04_graph_mthd_page_flip); | ||
1119 | |||
1116 | dev_priv->engine.graph.registered = true; | 1120 | dev_priv->engine.graph.registered = true; |
1117 | return 0; | 1121 | return 0; |
1118 | } | 1122 | } |
diff --git a/drivers/gpu/drm/nouveau/nv20_graph.c b/drivers/gpu/drm/nouveau/nv20_graph.c index 7720bccb3c98..51b9dd12949d 100644 --- a/drivers/gpu/drm/nouveau/nv20_graph.c +++ b/drivers/gpu/drm/nouveau/nv20_graph.c | |||
@@ -801,6 +801,10 @@ nv20_graph_register(struct drm_device *dev) | |||
801 | else | 801 | else |
802 | NVOBJ_CLASS(dev, 0x0597, GR); | 802 | NVOBJ_CLASS(dev, 0x0597, GR); |
803 | 803 | ||
804 | /* nvsw */ | ||
805 | NVOBJ_CLASS(dev, 0x506e, SW); | ||
806 | NVOBJ_MTHD (dev, 0x506e, 0x0500, nv04_graph_mthd_page_flip); | ||
807 | |||
804 | dev_priv->engine.graph.registered = true; | 808 | dev_priv->engine.graph.registered = true; |
805 | return 0; | 809 | return 0; |
806 | } | 810 | } |
@@ -841,6 +845,10 @@ nv30_graph_register(struct drm_device *dev) | |||
841 | if (0x000001e0 & (1 << (dev_priv->chipset & 0x0f))) | 845 | if (0x000001e0 & (1 << (dev_priv->chipset & 0x0f))) |
842 | NVOBJ_CLASS(dev, 0x0497, GR); | 846 | NVOBJ_CLASS(dev, 0x0497, GR); |
843 | 847 | ||
848 | /* nvsw */ | ||
849 | NVOBJ_CLASS(dev, 0x506e, SW); | ||
850 | NVOBJ_MTHD (dev, 0x506e, 0x0500, nv04_graph_mthd_page_flip); | ||
851 | |||
844 | dev_priv->engine.graph.registered = true; | 852 | dev_priv->engine.graph.registered = true; |
845 | return 0; | 853 | return 0; |
846 | } | 854 | } |
diff --git a/drivers/gpu/drm/nouveau/nv40_graph.c b/drivers/gpu/drm/nouveau/nv40_graph.c index b9361e28687c..159bdcd757d4 100644 --- a/drivers/gpu/drm/nouveau/nv40_graph.c +++ b/drivers/gpu/drm/nouveau/nv40_graph.c | |||
@@ -446,6 +446,10 @@ nv40_graph_register(struct drm_device *dev) | |||
446 | else | 446 | else |
447 | NVOBJ_CLASS(dev, 0x4097, GR); | 447 | NVOBJ_CLASS(dev, 0x4097, GR); |
448 | 448 | ||
449 | /* nvsw */ | ||
450 | NVOBJ_CLASS(dev, 0x506e, SW); | ||
451 | NVOBJ_MTHD (dev, 0x506e, 0x0500, nv04_graph_mthd_page_flip); | ||
452 | |||
449 | dev_priv->engine.graph.registered = true; | 453 | dev_priv->engine.graph.registered = true; |
450 | return 0; | 454 | return 0; |
451 | } | 455 | } |
diff --git a/drivers/gpu/drm/nouveau/nv50_crtc.c b/drivers/gpu/drm/nouveau/nv50_crtc.c index 56476d0c6de8..1225ea0a841b 100644 --- a/drivers/gpu/drm/nouveau/nv50_crtc.c +++ b/drivers/gpu/drm/nouveau/nv50_crtc.c | |||
@@ -437,6 +437,7 @@ static const struct drm_crtc_funcs nv50_crtc_funcs = { | |||
437 | .cursor_move = nv50_crtc_cursor_move, | 437 | .cursor_move = nv50_crtc_cursor_move, |
438 | .gamma_set = nv50_crtc_gamma_set, | 438 | .gamma_set = nv50_crtc_gamma_set, |
439 | .set_config = drm_crtc_helper_set_config, | 439 | .set_config = drm_crtc_helper_set_config, |
440 | .page_flip = nouveau_crtc_page_flip, | ||
440 | .destroy = nv50_crtc_destroy, | 441 | .destroy = nv50_crtc_destroy, |
441 | }; | 442 | }; |
442 | 443 | ||
diff --git a/drivers/gpu/drm/nouveau/nv50_graph.c b/drivers/gpu/drm/nouveau/nv50_graph.c index ac7f62d524bb..6d81f4dab37d 100644 --- a/drivers/gpu/drm/nouveau/nv50_graph.c +++ b/drivers/gpu/drm/nouveau/nv50_graph.c | |||
@@ -29,6 +29,8 @@ | |||
29 | #include "nouveau_drv.h" | 29 | #include "nouveau_drv.h" |
30 | #include "nouveau_ramht.h" | 30 | #include "nouveau_ramht.h" |
31 | #include "nouveau_grctx.h" | 31 | #include "nouveau_grctx.h" |
32 | #include "nouveau_dma.h" | ||
33 | #include "nv50_evo.h" | ||
32 | 34 | ||
33 | static int nv50_graph_register(struct drm_device *); | 35 | static int nv50_graph_register(struct drm_device *); |
34 | 36 | ||
@@ -390,6 +392,19 @@ nv50_graph_nvsw_vblsem_release(struct nouveau_channel *chan, | |||
390 | } | 392 | } |
391 | 393 | ||
392 | static int | 394 | static int |
395 | nv50_graph_nvsw_mthd_page_flip(struct nouveau_channel *chan, | ||
396 | u32 class, u32 mthd, u32 data) | ||
397 | { | ||
398 | struct nouveau_page_flip_state s; | ||
399 | |||
400 | if (!nouveau_finish_page_flip(chan, &s)) { | ||
401 | /* XXX - Do something here */ | ||
402 | } | ||
403 | |||
404 | return 0; | ||
405 | } | ||
406 | |||
407 | static int | ||
393 | nv50_graph_register(struct drm_device *dev) | 408 | nv50_graph_register(struct drm_device *dev) |
394 | { | 409 | { |
395 | struct drm_nouveau_private *dev_priv = dev->dev_private; | 410 | struct drm_nouveau_private *dev_priv = dev->dev_private; |
@@ -402,6 +417,7 @@ nv50_graph_register(struct drm_device *dev) | |||
402 | NVOBJ_MTHD (dev, 0x506e, 0x0400, nv50_graph_nvsw_vblsem_offset); | 417 | NVOBJ_MTHD (dev, 0x506e, 0x0400, nv50_graph_nvsw_vblsem_offset); |
403 | NVOBJ_MTHD (dev, 0x506e, 0x0404, nv50_graph_nvsw_vblsem_release_val); | 418 | NVOBJ_MTHD (dev, 0x506e, 0x0404, nv50_graph_nvsw_vblsem_release_val); |
404 | NVOBJ_MTHD (dev, 0x506e, 0x0408, nv50_graph_nvsw_vblsem_release); | 419 | NVOBJ_MTHD (dev, 0x506e, 0x0408, nv50_graph_nvsw_vblsem_release); |
420 | NVOBJ_MTHD (dev, 0x506e, 0x0500, nv50_graph_nvsw_mthd_page_flip); | ||
405 | 421 | ||
406 | NVOBJ_CLASS(dev, 0x0030, GR); /* null */ | 422 | NVOBJ_CLASS(dev, 0x0030, GR); /* null */ |
407 | NVOBJ_CLASS(dev, 0x5039, GR); /* m2mf */ | 423 | NVOBJ_CLASS(dev, 0x5039, GR); /* m2mf */ |