Merge branch 'kvm-updates/2.6.39' of git://git.kernel.org/pub/scm/virt/kvm/kvm
[pandora-kernel.git] / drivers / gpu / drm / nouveau / nouveau_display.c
1 /*
2  * Copyright (C) 2008 Maarten Maathuis.
3  * All Rights Reserved.
4  *
5  * Permission is hereby granted, free of charge, to any person obtaining
6  * a copy of this software and associated documentation files (the
7  * "Software"), to deal in the Software without restriction, including
8  * without limitation the rights to use, copy, modify, merge, publish,
9  * distribute, sublicense, and/or sell copies of the Software, and to
10  * permit persons to whom the Software is furnished to do so, subject to
11  * the following conditions:
12  *
13  * The above copyright notice and this permission notice (including the
14  * next paragraph) shall be included in all copies or substantial
15  * portions of the Software.
16  *
17  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
20  * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
21  * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
22  * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
23  * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24  *
25  */
26
27 #include "drmP.h"
28 #include "drm_crtc_helper.h"
29 #include "nouveau_drv.h"
30 #include "nouveau_fb.h"
31 #include "nouveau_fbcon.h"
32 #include "nouveau_hw.h"
33 #include "nouveau_crtc.h"
34 #include "nouveau_dma.h"
35 #include "nv50_display.h"
36
37 static void
38 nouveau_user_framebuffer_destroy(struct drm_framebuffer *drm_fb)
39 {
40         struct nouveau_framebuffer *fb = nouveau_framebuffer(drm_fb);
41
42         if (fb->nvbo)
43                 drm_gem_object_unreference_unlocked(fb->nvbo->gem);
44
45         drm_framebuffer_cleanup(drm_fb);
46         kfree(fb);
47 }
48
49 static int
50 nouveau_user_framebuffer_create_handle(struct drm_framebuffer *drm_fb,
51                                        struct drm_file *file_priv,
52                                        unsigned int *handle)
53 {
54         struct nouveau_framebuffer *fb = nouveau_framebuffer(drm_fb);
55
56         return drm_gem_handle_create(file_priv, fb->nvbo->gem, handle);
57 }
58
59 static const struct drm_framebuffer_funcs nouveau_framebuffer_funcs = {
60         .destroy = nouveau_user_framebuffer_destroy,
61         .create_handle = nouveau_user_framebuffer_create_handle,
62 };
63
64 int
65 nouveau_framebuffer_init(struct drm_device *dev,
66                          struct nouveau_framebuffer *nv_fb,
67                          struct drm_mode_fb_cmd *mode_cmd,
68                          struct nouveau_bo *nvbo)
69 {
70         struct drm_nouveau_private *dev_priv = dev->dev_private;
71         struct drm_framebuffer *fb = &nv_fb->base;
72         int ret;
73
74         ret = drm_framebuffer_init(dev, fb, &nouveau_framebuffer_funcs);
75         if (ret) {
76                 return ret;
77         }
78
79         drm_helper_mode_fill_fb_struct(fb, mode_cmd);
80         nv_fb->nvbo = nvbo;
81
82         if (dev_priv->card_type >= NV_50) {
83                 u32 tile_flags = nouveau_bo_tile_layout(nvbo);
84                 if (tile_flags == 0x7a00 ||
85                     tile_flags == 0xfe00)
86                         nv_fb->r_dma = NvEvoFB32;
87                 else
88                 if (tile_flags == 0x7000)
89                         nv_fb->r_dma = NvEvoFB16;
90                 else
91                         nv_fb->r_dma = NvEvoVRAM_LP;
92
93                 switch (fb->depth) {
94                 case  8: nv_fb->r_format = NV50_EVO_CRTC_FB_DEPTH_8; break;
95                 case 15: nv_fb->r_format = NV50_EVO_CRTC_FB_DEPTH_15; break;
96                 case 16: nv_fb->r_format = NV50_EVO_CRTC_FB_DEPTH_16; break;
97                 case 24:
98                 case 32: nv_fb->r_format = NV50_EVO_CRTC_FB_DEPTH_24; break;
99                 case 30: nv_fb->r_format = NV50_EVO_CRTC_FB_DEPTH_30; break;
100                 default:
101                          NV_ERROR(dev, "unknown depth %d\n", fb->depth);
102                          return -EINVAL;
103                 }
104
105                 if (dev_priv->chipset == 0x50)
106                         nv_fb->r_format |= (tile_flags << 8);
107
108                 if (!tile_flags)
109                         nv_fb->r_pitch = 0x00100000 | fb->pitch;
110                 else {
111                         u32 mode = nvbo->tile_mode;
112                         if (dev_priv->card_type >= NV_C0)
113                                 mode >>= 4;
114                         nv_fb->r_pitch = ((fb->pitch / 4) << 4) | mode;
115                 }
116         }
117
118         return 0;
119 }
120
121 static struct drm_framebuffer *
122 nouveau_user_framebuffer_create(struct drm_device *dev,
123                                 struct drm_file *file_priv,
124                                 struct drm_mode_fb_cmd *mode_cmd)
125 {
126         struct nouveau_framebuffer *nouveau_fb;
127         struct drm_gem_object *gem;
128         int ret;
129
130         gem = drm_gem_object_lookup(dev, file_priv, mode_cmd->handle);
131         if (!gem)
132                 return ERR_PTR(-ENOENT);
133
134         nouveau_fb = kzalloc(sizeof(struct nouveau_framebuffer), GFP_KERNEL);
135         if (!nouveau_fb)
136                 return ERR_PTR(-ENOMEM);
137
138         ret = nouveau_framebuffer_init(dev, nouveau_fb, mode_cmd, nouveau_gem_object(gem));
139         if (ret) {
140                 drm_gem_object_unreference(gem);
141                 return ERR_PTR(ret);
142         }
143
144         return &nouveau_fb->base;
145 }
146
147 const struct drm_mode_config_funcs nouveau_mode_config_funcs = {
148         .fb_create = nouveau_user_framebuffer_create,
149         .output_poll_changed = nouveau_fbcon_output_poll_changed,
150 };
151
152 int
153 nouveau_vblank_enable(struct drm_device *dev, int crtc)
154 {
155         struct drm_nouveau_private *dev_priv = dev->dev_private;
156
157         if (dev_priv->card_type >= NV_50)
158                 nv_mask(dev, NV50_PDISPLAY_INTR_EN_1, 0,
159                         NV50_PDISPLAY_INTR_EN_1_VBLANK_CRTC_(crtc));
160         else
161                 NVWriteCRTC(dev, crtc, NV_PCRTC_INTR_EN_0,
162                             NV_PCRTC_INTR_0_VBLANK);
163
164         return 0;
165 }
166
167 void
168 nouveau_vblank_disable(struct drm_device *dev, int crtc)
169 {
170         struct drm_nouveau_private *dev_priv = dev->dev_private;
171
172         if (dev_priv->card_type >= NV_50)
173                 nv_mask(dev, NV50_PDISPLAY_INTR_EN_1,
174                         NV50_PDISPLAY_INTR_EN_1_VBLANK_CRTC_(crtc), 0);
175         else
176                 NVWriteCRTC(dev, crtc, NV_PCRTC_INTR_EN_0, 0);
177 }
178
179 static int
180 nouveau_page_flip_reserve(struct nouveau_bo *old_bo,
181                           struct nouveau_bo *new_bo)
182 {
183         int ret;
184
185         ret = nouveau_bo_pin(new_bo, TTM_PL_FLAG_VRAM);
186         if (ret)
187                 return ret;
188
189         ret = ttm_bo_reserve(&new_bo->bo, false, false, false, 0);
190         if (ret)
191                 goto fail;
192
193         ret = ttm_bo_reserve(&old_bo->bo, false, false, false, 0);
194         if (ret)
195                 goto fail_unreserve;
196
197         return 0;
198
199 fail_unreserve:
200         ttm_bo_unreserve(&new_bo->bo);
201 fail:
202         nouveau_bo_unpin(new_bo);
203         return ret;
204 }
205
206 static void
207 nouveau_page_flip_unreserve(struct nouveau_bo *old_bo,
208                             struct nouveau_bo *new_bo,
209                             struct nouveau_fence *fence)
210 {
211         nouveau_bo_fence(new_bo, fence);
212         ttm_bo_unreserve(&new_bo->bo);
213
214         nouveau_bo_fence(old_bo, fence);
215         ttm_bo_unreserve(&old_bo->bo);
216
217         nouveau_bo_unpin(old_bo);
218 }
219
220 static int
221 nouveau_page_flip_emit(struct nouveau_channel *chan,
222                        struct nouveau_bo *old_bo,
223                        struct nouveau_bo *new_bo,
224                        struct nouveau_page_flip_state *s,
225                        struct nouveau_fence **pfence)
226 {
227         struct drm_nouveau_private *dev_priv = chan->dev->dev_private;
228         struct drm_device *dev = chan->dev;
229         unsigned long flags;
230         int ret;
231
232         /* Queue it to the pending list */
233         spin_lock_irqsave(&dev->event_lock, flags);
234         list_add_tail(&s->head, &chan->nvsw.flip);
235         spin_unlock_irqrestore(&dev->event_lock, flags);
236
237         /* Synchronize with the old framebuffer */
238         ret = nouveau_fence_sync(old_bo->bo.sync_obj, chan);
239         if (ret)
240                 goto fail;
241
242         /* Emit the pageflip */
243         ret = RING_SPACE(chan, 2);
244         if (ret)
245                 goto fail;
246
247         if (dev_priv->card_type < NV_C0)
248                 BEGIN_RING(chan, NvSubSw, NV_SW_PAGE_FLIP, 1);
249         else
250                 BEGIN_NVC0(chan, 2, NvSubM2MF, 0x0500, 1);
251         OUT_RING  (chan, 0);
252         FIRE_RING (chan);
253
254         ret = nouveau_fence_new(chan, pfence, true);
255         if (ret)
256                 goto fail;
257
258         return 0;
259 fail:
260         spin_lock_irqsave(&dev->event_lock, flags);
261         list_del(&s->head);
262         spin_unlock_irqrestore(&dev->event_lock, flags);
263         return ret;
264 }
265
266 int
267 nouveau_crtc_page_flip(struct drm_crtc *crtc, struct drm_framebuffer *fb,
268                        struct drm_pending_vblank_event *event)
269 {
270         struct drm_device *dev = crtc->dev;
271         struct drm_nouveau_private *dev_priv = dev->dev_private;
272         struct nouveau_bo *old_bo = nouveau_framebuffer(crtc->fb)->nvbo;
273         struct nouveau_bo *new_bo = nouveau_framebuffer(fb)->nvbo;
274         struct nouveau_page_flip_state *s;
275         struct nouveau_channel *chan;
276         struct nouveau_fence *fence;
277         int ret;
278
279         if (dev_priv->engine.graph.accel_blocked)
280                 return -ENODEV;
281
282         s = kzalloc(sizeof(*s), GFP_KERNEL);
283         if (!s)
284                 return -ENOMEM;
285
286         /* Don't let the buffers go away while we flip */
287         ret = nouveau_page_flip_reserve(old_bo, new_bo);
288         if (ret)
289                 goto fail_free;
290
291         /* Initialize a page flip struct */
292         *s = (struct nouveau_page_flip_state)
293                 { { }, event, nouveau_crtc(crtc)->index,
294                   fb->bits_per_pixel, fb->pitch, crtc->x, crtc->y,
295                   new_bo->bo.offset };
296
297         /* Choose the channel the flip will be handled in */
298         chan = nouveau_fence_channel(new_bo->bo.sync_obj);
299         if (!chan)
300                 chan = nouveau_channel_get_unlocked(dev_priv->channel);
301         mutex_lock(&chan->mutex);
302
303         /* Emit a page flip */
304         if (dev_priv->card_type >= NV_50) {
305                 ret = nv50_display_flip_next(crtc, fb, chan);
306                 if (ret) {
307                         nouveau_channel_put(&chan);
308                         goto fail_unreserve;
309                 }
310         }
311
312         ret = nouveau_page_flip_emit(chan, old_bo, new_bo, s, &fence);
313         nouveau_channel_put(&chan);
314         if (ret)
315                 goto fail_unreserve;
316
317         /* Update the crtc struct and cleanup */
318         crtc->fb = fb;
319
320         nouveau_page_flip_unreserve(old_bo, new_bo, fence);
321         nouveau_fence_unref(&fence);
322         return 0;
323
324 fail_unreserve:
325         nouveau_page_flip_unreserve(old_bo, new_bo, NULL);
326 fail_free:
327         kfree(s);
328         return ret;
329 }
330
331 int
332 nouveau_finish_page_flip(struct nouveau_channel *chan,
333                          struct nouveau_page_flip_state *ps)
334 {
335         struct drm_device *dev = chan->dev;
336         struct nouveau_page_flip_state *s;
337         unsigned long flags;
338
339         spin_lock_irqsave(&dev->event_lock, flags);
340
341         if (list_empty(&chan->nvsw.flip)) {
342                 NV_ERROR(dev, "Unexpected pageflip in channel %d.\n", chan->id);
343                 spin_unlock_irqrestore(&dev->event_lock, flags);
344                 return -EINVAL;
345         }
346
347         s = list_first_entry(&chan->nvsw.flip,
348                              struct nouveau_page_flip_state, head);
349         if (s->event) {
350                 struct drm_pending_vblank_event *e = s->event;
351                 struct timeval now;
352
353                 do_gettimeofday(&now);
354                 e->event.sequence = 0;
355                 e->event.tv_sec = now.tv_sec;
356                 e->event.tv_usec = now.tv_usec;
357                 list_add_tail(&e->base.link, &e->base.file_priv->event_list);
358                 wake_up_interruptible(&e->base.file_priv->event_wait);
359         }
360
361         list_del(&s->head);
362         if (ps)
363                 *ps = *s;
364         kfree(s);
365
366         spin_unlock_irqrestore(&dev->event_lock, flags);
367         return 0;
368 }