Merge branch 'for-linus' of git://oss.sgi.com/xfs/xfs
[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                         if (dev_priv->card_type < NV_D0)
110                                 nv_fb->r_pitch = 0x00100000 | fb->pitch;
111                         else
112                                 nv_fb->r_pitch = 0x01000000 | fb->pitch;
113                 } else {
114                         u32 mode = nvbo->tile_mode;
115                         if (dev_priv->card_type >= NV_C0)
116                                 mode >>= 4;
117                         nv_fb->r_pitch = ((fb->pitch / 4) << 4) | mode;
118                 }
119         }
120
121         return 0;
122 }
123
124 static struct drm_framebuffer *
125 nouveau_user_framebuffer_create(struct drm_device *dev,
126                                 struct drm_file *file_priv,
127                                 struct drm_mode_fb_cmd *mode_cmd)
128 {
129         struct nouveau_framebuffer *nouveau_fb;
130         struct drm_gem_object *gem;
131         int ret;
132
133         gem = drm_gem_object_lookup(dev, file_priv, mode_cmd->handle);
134         if (!gem)
135                 return ERR_PTR(-ENOENT);
136
137         nouveau_fb = kzalloc(sizeof(struct nouveau_framebuffer), GFP_KERNEL);
138         if (!nouveau_fb)
139                 return ERR_PTR(-ENOMEM);
140
141         ret = nouveau_framebuffer_init(dev, nouveau_fb, mode_cmd, nouveau_gem_object(gem));
142         if (ret) {
143                 drm_gem_object_unreference(gem);
144                 return ERR_PTR(ret);
145         }
146
147         return &nouveau_fb->base;
148 }
149
150 const struct drm_mode_config_funcs nouveau_mode_config_funcs = {
151         .fb_create = nouveau_user_framebuffer_create,
152         .output_poll_changed = nouveau_fbcon_output_poll_changed,
153 };
154
155 int
156 nouveau_vblank_enable(struct drm_device *dev, int crtc)
157 {
158         struct drm_nouveau_private *dev_priv = dev->dev_private;
159
160         if (dev_priv->card_type >= NV_50)
161                 nv_mask(dev, NV50_PDISPLAY_INTR_EN_1, 0,
162                         NV50_PDISPLAY_INTR_EN_1_VBLANK_CRTC_(crtc));
163         else
164                 NVWriteCRTC(dev, crtc, NV_PCRTC_INTR_EN_0,
165                             NV_PCRTC_INTR_0_VBLANK);
166
167         return 0;
168 }
169
170 void
171 nouveau_vblank_disable(struct drm_device *dev, int crtc)
172 {
173         struct drm_nouveau_private *dev_priv = dev->dev_private;
174
175         if (dev_priv->card_type >= NV_50)
176                 nv_mask(dev, NV50_PDISPLAY_INTR_EN_1,
177                         NV50_PDISPLAY_INTR_EN_1_VBLANK_CRTC_(crtc), 0);
178         else
179                 NVWriteCRTC(dev, crtc, NV_PCRTC_INTR_EN_0, 0);
180 }
181
182 static int
183 nouveau_page_flip_reserve(struct nouveau_bo *old_bo,
184                           struct nouveau_bo *new_bo)
185 {
186         int ret;
187
188         ret = nouveau_bo_pin(new_bo, TTM_PL_FLAG_VRAM);
189         if (ret)
190                 return ret;
191
192         ret = ttm_bo_reserve(&new_bo->bo, false, false, false, 0);
193         if (ret)
194                 goto fail;
195
196         ret = ttm_bo_reserve(&old_bo->bo, false, false, false, 0);
197         if (ret)
198                 goto fail_unreserve;
199
200         return 0;
201
202 fail_unreserve:
203         ttm_bo_unreserve(&new_bo->bo);
204 fail:
205         nouveau_bo_unpin(new_bo);
206         return ret;
207 }
208
209 static void
210 nouveau_page_flip_unreserve(struct nouveau_bo *old_bo,
211                             struct nouveau_bo *new_bo,
212                             struct nouveau_fence *fence)
213 {
214         nouveau_bo_fence(new_bo, fence);
215         ttm_bo_unreserve(&new_bo->bo);
216
217         nouveau_bo_fence(old_bo, fence);
218         ttm_bo_unreserve(&old_bo->bo);
219
220         nouveau_bo_unpin(old_bo);
221 }
222
223 static int
224 nouveau_page_flip_emit(struct nouveau_channel *chan,
225                        struct nouveau_bo *old_bo,
226                        struct nouveau_bo *new_bo,
227                        struct nouveau_page_flip_state *s,
228                        struct nouveau_fence **pfence)
229 {
230         struct drm_nouveau_private *dev_priv = chan->dev->dev_private;
231         struct drm_device *dev = chan->dev;
232         unsigned long flags;
233         int ret;
234
235         /* Queue it to the pending list */
236         spin_lock_irqsave(&dev->event_lock, flags);
237         list_add_tail(&s->head, &chan->nvsw.flip);
238         spin_unlock_irqrestore(&dev->event_lock, flags);
239
240         /* Synchronize with the old framebuffer */
241         ret = nouveau_fence_sync(old_bo->bo.sync_obj, chan);
242         if (ret)
243                 goto fail;
244
245         /* Emit the pageflip */
246         ret = RING_SPACE(chan, 2);
247         if (ret)
248                 goto fail;
249
250         if (dev_priv->card_type < NV_C0)
251                 BEGIN_RING(chan, NvSubSw, NV_SW_PAGE_FLIP, 1);
252         else
253                 BEGIN_NVC0(chan, 2, NvSubM2MF, 0x0500, 1);
254         OUT_RING  (chan, 0);
255         FIRE_RING (chan);
256
257         ret = nouveau_fence_new(chan, pfence, true);
258         if (ret)
259                 goto fail;
260
261         return 0;
262 fail:
263         spin_lock_irqsave(&dev->event_lock, flags);
264         list_del(&s->head);
265         spin_unlock_irqrestore(&dev->event_lock, flags);
266         return ret;
267 }
268
269 int
270 nouveau_crtc_page_flip(struct drm_crtc *crtc, struct drm_framebuffer *fb,
271                        struct drm_pending_vblank_event *event)
272 {
273         struct drm_device *dev = crtc->dev;
274         struct drm_nouveau_private *dev_priv = dev->dev_private;
275         struct nouveau_bo *old_bo = nouveau_framebuffer(crtc->fb)->nvbo;
276         struct nouveau_bo *new_bo = nouveau_framebuffer(fb)->nvbo;
277         struct nouveau_page_flip_state *s;
278         struct nouveau_channel *chan;
279         struct nouveau_fence *fence;
280         int ret;
281
282         if (!dev_priv->channel)
283                 return -ENODEV;
284
285         s = kzalloc(sizeof(*s), GFP_KERNEL);
286         if (!s)
287                 return -ENOMEM;
288
289         /* Don't let the buffers go away while we flip */
290         ret = nouveau_page_flip_reserve(old_bo, new_bo);
291         if (ret)
292                 goto fail_free;
293
294         /* Initialize a page flip struct */
295         *s = (struct nouveau_page_flip_state)
296                 { { }, event, nouveau_crtc(crtc)->index,
297                   fb->bits_per_pixel, fb->pitch, crtc->x, crtc->y,
298                   new_bo->bo.offset };
299
300         /* Choose the channel the flip will be handled in */
301         chan = nouveau_fence_channel(new_bo->bo.sync_obj);
302         if (!chan)
303                 chan = nouveau_channel_get_unlocked(dev_priv->channel);
304         mutex_lock(&chan->mutex);
305
306         /* Emit a page flip */
307         if (dev_priv->card_type >= NV_50) {
308                 ret = nv50_display_flip_next(crtc, fb, chan);
309                 if (ret) {
310                         nouveau_channel_put(&chan);
311                         goto fail_unreserve;
312                 }
313         }
314
315         ret = nouveau_page_flip_emit(chan, old_bo, new_bo, s, &fence);
316         nouveau_channel_put(&chan);
317         if (ret)
318                 goto fail_unreserve;
319
320         /* Update the crtc struct and cleanup */
321         crtc->fb = fb;
322
323         nouveau_page_flip_unreserve(old_bo, new_bo, fence);
324         nouveau_fence_unref(&fence);
325         return 0;
326
327 fail_unreserve:
328         nouveau_page_flip_unreserve(old_bo, new_bo, NULL);
329 fail_free:
330         kfree(s);
331         return ret;
332 }
333
334 int
335 nouveau_finish_page_flip(struct nouveau_channel *chan,
336                          struct nouveau_page_flip_state *ps)
337 {
338         struct drm_device *dev = chan->dev;
339         struct nouveau_page_flip_state *s;
340         unsigned long flags;
341
342         spin_lock_irqsave(&dev->event_lock, flags);
343
344         if (list_empty(&chan->nvsw.flip)) {
345                 NV_ERROR(dev, "Unexpected pageflip in channel %d.\n", chan->id);
346                 spin_unlock_irqrestore(&dev->event_lock, flags);
347                 return -EINVAL;
348         }
349
350         s = list_first_entry(&chan->nvsw.flip,
351                              struct nouveau_page_flip_state, head);
352         if (s->event) {
353                 struct drm_pending_vblank_event *e = s->event;
354                 struct timeval now;
355
356                 do_gettimeofday(&now);
357                 e->event.sequence = 0;
358                 e->event.tv_sec = now.tv_sec;
359                 e->event.tv_usec = now.tv_usec;
360                 list_add_tail(&e->base.link, &e->base.file_priv->event_list);
361                 wake_up_interruptible(&e->base.file_priv->event_wait);
362         }
363
364         list_del(&s->head);
365         if (ps)
366                 *ps = *s;
367         kfree(s);
368
369         spin_unlock_irqrestore(&dev->event_lock, flags);
370         return 0;
371 }
372
373 int
374 nouveau_display_dumb_create(struct drm_file *file_priv, struct drm_device *dev,
375                             struct drm_mode_create_dumb *args)
376 {
377         struct nouveau_bo *bo;
378         int ret;
379
380         args->pitch = roundup(args->width * (args->bpp / 8), 256);
381         args->size = args->pitch * args->height;
382         args->size = roundup(args->size, PAGE_SIZE);
383
384         ret = nouveau_gem_new(dev, args->size, 0, TTM_PL_FLAG_VRAM, 0, 0, &bo);
385         if (ret)
386                 return ret;
387
388         ret = drm_gem_handle_create(file_priv, bo->gem, &args->handle);
389         drm_gem_object_unreference_unlocked(bo->gem);
390         return ret;
391 }
392
393 int
394 nouveau_display_dumb_destroy(struct drm_file *file_priv, struct drm_device *dev,
395                              uint32_t handle)
396 {
397         return drm_gem_handle_delete(file_priv, handle);
398 }
399
400 int
401 nouveau_display_dumb_map_offset(struct drm_file *file_priv,
402                                 struct drm_device *dev,
403                                 uint32_t handle, uint64_t *poffset)
404 {
405         struct drm_gem_object *gem;
406
407         gem = drm_gem_object_lookup(dev, file_priv, handle);
408         if (gem) {
409                 struct nouveau_bo *bo = gem->driver_private;
410                 *poffset = bo->bo.addr_space_offset;
411                 drm_gem_object_unreference_unlocked(gem);
412                 return 0;
413         }
414
415         return -ENOENT;
416 }