]> git.karo-electronics.de Git - karo-tx-linux.git/blob - drivers/gpu/drm/nouveau/nv50_crtc.c
drm/nouveau: port remainder of drm code, and rip out compat layer
[karo-tx-linux.git] / drivers / gpu / drm / nouveau / nv50_crtc.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_mode.h"
29 #include "drm_crtc_helper.h"
30
31 #include "nouveau_reg.h"
32 #include "nouveau_drm.h"
33 #include "nouveau_dma.h"
34 #include "nouveau_gem.h"
35 #include "nouveau_hw.h"
36 #include "nouveau_encoder.h"
37 #include "nouveau_crtc.h"
38 #include "nouveau_connector.h"
39 #include "nv50_display.h"
40
41 #include <subdev/clock.h>
42
43 static void
44 nv50_crtc_lut_load(struct drm_crtc *crtc)
45 {
46         struct nouveau_drm *drm = nouveau_drm(crtc->dev);
47         struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
48         void __iomem *lut = nvbo_kmap_obj_iovirtual(nv_crtc->lut.nvbo);
49         int i;
50
51         NV_DEBUG(drm, "\n");
52
53         for (i = 0; i < 256; i++) {
54                 writew(nv_crtc->lut.r[i] >> 2, lut + 8*i + 0);
55                 writew(nv_crtc->lut.g[i] >> 2, lut + 8*i + 2);
56                 writew(nv_crtc->lut.b[i] >> 2, lut + 8*i + 4);
57         }
58
59         if (nv_crtc->lut.depth == 30) {
60                 writew(nv_crtc->lut.r[i - 1] >> 2, lut + 8*i + 0);
61                 writew(nv_crtc->lut.g[i - 1] >> 2, lut + 8*i + 2);
62                 writew(nv_crtc->lut.b[i - 1] >> 2, lut + 8*i + 4);
63         }
64 }
65
66 int
67 nv50_crtc_blank(struct nouveau_crtc *nv_crtc, bool blanked)
68 {
69         struct drm_device *dev = nv_crtc->base.dev;
70         struct nouveau_drm *drm = nouveau_drm(dev);
71         struct nouveau_channel *evo = nv50_display(dev)->master;
72         int index = nv_crtc->index, ret;
73
74         NV_DEBUG(drm, "index %d\n", nv_crtc->index);
75         NV_DEBUG(drm, "%s\n", blanked ? "blanked" : "unblanked");
76
77         if (blanked) {
78                 nv_crtc->cursor.hide(nv_crtc, false);
79
80                 ret = RING_SPACE(evo, nv_device(drm->device)->chipset != 0x50 ? 7 : 5);
81                 if (ret) {
82                         NV_ERROR(drm, "no space while blanking crtc\n");
83                         return ret;
84                 }
85                 BEGIN_NV04(evo, 0, NV50_EVO_CRTC(index, CLUT_MODE), 2);
86                 OUT_RING(evo, NV50_EVO_CRTC_CLUT_MODE_BLANK);
87                 OUT_RING(evo, 0);
88                 if (nv_device(drm->device)->chipset != 0x50) {
89                         BEGIN_NV04(evo, 0, NV84_EVO_CRTC(index, CLUT_DMA), 1);
90                         OUT_RING(evo, NV84_EVO_CRTC_CLUT_DMA_HANDLE_NONE);
91                 }
92
93                 BEGIN_NV04(evo, 0, NV50_EVO_CRTC(index, FB_DMA), 1);
94                 OUT_RING(evo, NV50_EVO_CRTC_FB_DMA_HANDLE_NONE);
95         } else {
96                 if (nv_crtc->cursor.visible)
97                         nv_crtc->cursor.show(nv_crtc, false);
98                 else
99                         nv_crtc->cursor.hide(nv_crtc, false);
100
101                 ret = RING_SPACE(evo, nv_device(drm->device)->chipset != 0x50 ? 10 : 8);
102                 if (ret) {
103                         NV_ERROR(drm, "no space while unblanking crtc\n");
104                         return ret;
105                 }
106                 BEGIN_NV04(evo, 0, NV50_EVO_CRTC(index, CLUT_MODE), 2);
107                 OUT_RING(evo, nv_crtc->lut.depth == 8 ?
108                                 NV50_EVO_CRTC_CLUT_MODE_OFF :
109                                 NV50_EVO_CRTC_CLUT_MODE_ON);
110                 OUT_RING(evo, nv_crtc->lut.nvbo->bo.offset >> 8);
111                 if (nv_device(drm->device)->chipset != 0x50) {
112                         BEGIN_NV04(evo, 0, NV84_EVO_CRTC(index, CLUT_DMA), 1);
113                         OUT_RING(evo, NvEvoVRAM);
114                 }
115
116                 BEGIN_NV04(evo, 0, NV50_EVO_CRTC(index, FB_OFFSET), 2);
117                 OUT_RING(evo, nv_crtc->fb.offset >> 8);
118                 OUT_RING(evo, 0);
119                 BEGIN_NV04(evo, 0, NV50_EVO_CRTC(index, FB_DMA), 1);
120                 if (nv_device(drm->device)->chipset != 0x50)
121                         if (nv_crtc->fb.tile_flags == 0x7a00 ||
122                             nv_crtc->fb.tile_flags == 0xfe00)
123                                 OUT_RING(evo, NvEvoFB32);
124                         else
125                         if (nv_crtc->fb.tile_flags == 0x7000)
126                                 OUT_RING(evo, NvEvoFB16);
127                         else
128                                 OUT_RING(evo, NvEvoVRAM_LP);
129                 else
130                         OUT_RING(evo, NvEvoVRAM_LP);
131         }
132
133         nv_crtc->fb.blanked = blanked;
134         return 0;
135 }
136
137 static int
138 nv50_crtc_set_dither(struct nouveau_crtc *nv_crtc, bool update)
139 {
140         struct nouveau_channel *evo = nv50_display(nv_crtc->base.dev)->master;
141         struct nouveau_connector *nv_connector;
142         struct drm_connector *connector;
143         int head = nv_crtc->index, ret;
144         u32 mode = 0x00;
145
146         nv_connector = nouveau_crtc_connector_get(nv_crtc);
147         connector = &nv_connector->base;
148         if (nv_connector->dithering_mode == DITHERING_MODE_AUTO) {
149                 if (nv_crtc->base.fb->depth > connector->display_info.bpc * 3)
150                         mode = DITHERING_MODE_DYNAMIC2X2;
151         } else {
152                 mode = nv_connector->dithering_mode;
153         }
154
155         if (nv_connector->dithering_depth == DITHERING_DEPTH_AUTO) {
156                 if (connector->display_info.bpc >= 8)
157                         mode |= DITHERING_DEPTH_8BPC;
158         } else {
159                 mode |= nv_connector->dithering_depth;
160         }
161
162         ret = RING_SPACE(evo, 2 + (update ? 2 : 0));
163         if (ret == 0) {
164                 BEGIN_NV04(evo, 0, NV50_EVO_CRTC(head, DITHER_CTRL), 1);
165                 OUT_RING  (evo, mode);
166                 if (update) {
167                         BEGIN_NV04(evo, 0, NV50_EVO_UPDATE, 1);
168                         OUT_RING  (evo, 0);
169                         FIRE_RING (evo);
170                 }
171         }
172
173         return ret;
174 }
175
176 static int
177 nv50_crtc_set_color_vibrance(struct nouveau_crtc *nv_crtc, bool update)
178 {
179         struct drm_device *dev = nv_crtc->base.dev;
180         struct nouveau_drm *drm = nouveau_drm(dev);
181         struct nouveau_channel *evo = nv50_display(dev)->master;
182         int ret;
183         int adj;
184         u32 hue, vib;
185
186         NV_DEBUG(drm, "vibrance = %i, hue = %i\n",
187                      nv_crtc->color_vibrance, nv_crtc->vibrant_hue);
188
189         ret = RING_SPACE(evo, 2 + (update ? 2 : 0));
190         if (ret) {
191                 NV_ERROR(drm, "no space while setting color vibrance\n");
192                 return ret;
193         }
194
195         adj = (nv_crtc->color_vibrance > 0) ? 50 : 0;
196         vib = ((nv_crtc->color_vibrance * 2047 + adj) / 100) & 0xfff;
197
198         hue = ((nv_crtc->vibrant_hue * 2047) / 100) & 0xfff;
199
200         BEGIN_NV04(evo, 0, NV50_EVO_CRTC(nv_crtc->index, COLOR_CTRL), 1);
201         OUT_RING  (evo, (hue << 20) | (vib << 8));
202
203         if (update) {
204                 BEGIN_NV04(evo, 0, NV50_EVO_UPDATE, 1);
205                 OUT_RING  (evo, 0);
206                 FIRE_RING (evo);
207         }
208
209         return 0;
210 }
211
212 struct nouveau_connector *
213 nouveau_crtc_connector_get(struct nouveau_crtc *nv_crtc)
214 {
215         struct drm_device *dev = nv_crtc->base.dev;
216         struct drm_connector *connector;
217         struct drm_crtc *crtc = to_drm_crtc(nv_crtc);
218
219         /* The safest approach is to find an encoder with the right crtc, that
220          * is also linked to a connector. */
221         list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
222                 if (connector->encoder)
223                         if (connector->encoder->crtc == crtc)
224                                 return nouveau_connector(connector);
225         }
226
227         return NULL;
228 }
229
230 static int
231 nv50_crtc_set_scale(struct nouveau_crtc *nv_crtc, bool update)
232 {
233         struct nouveau_connector *nv_connector;
234         struct drm_crtc *crtc = &nv_crtc->base;
235         struct drm_device *dev = crtc->dev;
236         struct nouveau_drm *drm = nouveau_drm(dev);
237         struct nouveau_channel *evo = nv50_display(dev)->master;
238         struct drm_display_mode *umode = &crtc->mode;
239         struct drm_display_mode *omode;
240         int scaling_mode, ret;
241         u32 ctrl = 0, oX, oY;
242
243         NV_DEBUG(drm, "\n");
244
245         nv_connector = nouveau_crtc_connector_get(nv_crtc);
246         if (!nv_connector || !nv_connector->native_mode) {
247                 NV_ERROR(drm, "no native mode, forcing panel scaling\n");
248                 scaling_mode = DRM_MODE_SCALE_NONE;
249         } else {
250                 scaling_mode = nv_connector->scaling_mode;
251         }
252
253         /* start off at the resolution we programmed the crtc for, this
254          * effectively handles NONE/FULL scaling
255          */
256         if (scaling_mode != DRM_MODE_SCALE_NONE)
257                 omode = nv_connector->native_mode;
258         else
259                 omode = umode;
260
261         oX = omode->hdisplay;
262         oY = omode->vdisplay;
263         if (omode->flags & DRM_MODE_FLAG_DBLSCAN)
264                 oY *= 2;
265
266         /* add overscan compensation if necessary, will keep the aspect
267          * ratio the same as the backend mode unless overridden by the
268          * user setting both hborder and vborder properties.
269          */
270         if (nv_connector && ( nv_connector->underscan == UNDERSCAN_ON ||
271                              (nv_connector->underscan == UNDERSCAN_AUTO &&
272                               nv_connector->edid &&
273                               drm_detect_hdmi_monitor(nv_connector->edid)))) {
274                 u32 bX = nv_connector->underscan_hborder;
275                 u32 bY = nv_connector->underscan_vborder;
276                 u32 aspect = (oY << 19) / oX;
277
278                 if (bX) {
279                         oX -= (bX * 2);
280                         if (bY) oY -= (bY * 2);
281                         else    oY  = ((oX * aspect) + (aspect / 2)) >> 19;
282                 } else {
283                         oX -= (oX >> 4) + 32;
284                         if (bY) oY -= (bY * 2);
285                         else    oY  = ((oX * aspect) + (aspect / 2)) >> 19;
286                 }
287         }
288
289         /* handle CENTER/ASPECT scaling, taking into account the areas
290          * removed already for overscan compensation
291          */
292         switch (scaling_mode) {
293         case DRM_MODE_SCALE_CENTER:
294                 oX = min((u32)umode->hdisplay, oX);
295                 oY = min((u32)umode->vdisplay, oY);
296                 /* fall-through */
297         case DRM_MODE_SCALE_ASPECT:
298                 if (oY < oX) {
299                         u32 aspect = (umode->hdisplay << 19) / umode->vdisplay;
300                         oX = ((oY * aspect) + (aspect / 2)) >> 19;
301                 } else {
302                         u32 aspect = (umode->vdisplay << 19) / umode->hdisplay;
303                         oY = ((oX * aspect) + (aspect / 2)) >> 19;
304                 }
305                 break;
306         default:
307                 break;
308         }
309
310         if (umode->hdisplay != oX || umode->vdisplay != oY ||
311             umode->flags & DRM_MODE_FLAG_INTERLACE ||
312             umode->flags & DRM_MODE_FLAG_DBLSCAN)
313                 ctrl |= NV50_EVO_CRTC_SCALE_CTRL_ACTIVE;
314
315         ret = RING_SPACE(evo, 5);
316         if (ret)
317                 return ret;
318
319         BEGIN_NV04(evo, 0, NV50_EVO_CRTC(nv_crtc->index, SCALE_CTRL), 1);
320         OUT_RING  (evo, ctrl);
321         BEGIN_NV04(evo, 0, NV50_EVO_CRTC(nv_crtc->index, SCALE_RES1), 2);
322         OUT_RING  (evo, oY << 16 | oX);
323         OUT_RING  (evo, oY << 16 | oX);
324
325         if (update) {
326                 nv50_display_flip_stop(crtc);
327                 nv50_display_sync(dev);
328                 nv50_display_flip_next(crtc, crtc->fb, NULL);
329         }
330
331         return 0;
332 }
333
334 int
335 nv50_crtc_set_clock(struct drm_device *dev, int head, int pclk)
336 {
337         struct nouveau_device *device = nouveau_dev(dev);
338         struct nouveau_clock *clk = nouveau_clock(device);
339
340         return clk->pll_set(clk, PLL_VPLL0 + head, pclk);
341 }
342
343 static void
344 nv50_crtc_destroy(struct drm_crtc *crtc)
345 {
346         struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
347         struct nouveau_drm *drm = nouveau_drm(crtc->dev);
348
349         NV_DEBUG(drm, "\n");
350
351         nouveau_bo_unmap(nv_crtc->lut.nvbo);
352         nouveau_bo_ref(NULL, &nv_crtc->lut.nvbo);
353         nouveau_bo_unmap(nv_crtc->cursor.nvbo);
354         nouveau_bo_ref(NULL, &nv_crtc->cursor.nvbo);
355         drm_crtc_cleanup(&nv_crtc->base);
356         kfree(nv_crtc);
357 }
358
359 int
360 nv50_crtc_cursor_set(struct drm_crtc *crtc, struct drm_file *file_priv,
361                      uint32_t buffer_handle, uint32_t width, uint32_t height)
362 {
363         struct drm_device *dev = crtc->dev;
364         struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
365         struct nouveau_bo *cursor = NULL;
366         struct drm_gem_object *gem;
367         int ret = 0, i;
368
369         if (!buffer_handle) {
370                 nv_crtc->cursor.hide(nv_crtc, true);
371                 return 0;
372         }
373
374         if (width != 64 || height != 64)
375                 return -EINVAL;
376
377         gem = drm_gem_object_lookup(dev, file_priv, buffer_handle);
378         if (!gem)
379                 return -ENOENT;
380         cursor = nouveau_gem_object(gem);
381
382         ret = nouveau_bo_map(cursor);
383         if (ret)
384                 goto out;
385
386         /* The simple will do for now. */
387         for (i = 0; i < 64 * 64; i++)
388                 nouveau_bo_wr32(nv_crtc->cursor.nvbo, i, nouveau_bo_rd32(cursor, i));
389
390         nouveau_bo_unmap(cursor);
391
392         nv_crtc->cursor.set_offset(nv_crtc, nv_crtc->cursor.nvbo->bo.offset);
393         nv_crtc->cursor.show(nv_crtc, true);
394
395 out:
396         drm_gem_object_unreference_unlocked(gem);
397         return ret;
398 }
399
400 int
401 nv50_crtc_cursor_move(struct drm_crtc *crtc, int x, int y)
402 {
403         struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
404
405         nv_crtc->cursor.set_pos(nv_crtc, x, y);
406         return 0;
407 }
408
409 static void
410 nv50_crtc_gamma_set(struct drm_crtc *crtc, u16 *r, u16 *g, u16 *b,
411                     uint32_t start, uint32_t size)
412 {
413         int end = (start + size > 256) ? 256 : start + size, i;
414         struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
415
416         for (i = start; i < end; i++) {
417                 nv_crtc->lut.r[i] = r[i];
418                 nv_crtc->lut.g[i] = g[i];
419                 nv_crtc->lut.b[i] = b[i];
420         }
421
422         /* We need to know the depth before we upload, but it's possible to
423          * get called before a framebuffer is bound.  If this is the case,
424          * mark the lut values as dirty by setting depth==0, and it'll be
425          * uploaded on the first mode_set_base()
426          */
427         if (!nv_crtc->base.fb) {
428                 nv_crtc->lut.depth = 0;
429                 return;
430         }
431
432         nv50_crtc_lut_load(crtc);
433 }
434
435 static void
436 nv50_crtc_save(struct drm_crtc *crtc)
437 {
438         struct nouveau_drm *drm = nouveau_drm(crtc->dev);
439         NV_ERROR(drm, "!!\n");
440 }
441
442 static void
443 nv50_crtc_restore(struct drm_crtc *crtc)
444 {
445         struct nouveau_drm *drm = nouveau_drm(crtc->dev);
446         NV_ERROR(drm, "!!\n");
447 }
448
449 static const struct drm_crtc_funcs nv50_crtc_funcs = {
450         .save = nv50_crtc_save,
451         .restore = nv50_crtc_restore,
452         .cursor_set = nv50_crtc_cursor_set,
453         .cursor_move = nv50_crtc_cursor_move,
454         .gamma_set = nv50_crtc_gamma_set,
455         .set_config = drm_crtc_helper_set_config,
456         .page_flip = nouveau_crtc_page_flip,
457         .destroy = nv50_crtc_destroy,
458 };
459
460 static void
461 nv50_crtc_dpms(struct drm_crtc *crtc, int mode)
462 {
463 }
464
465 static void
466 nv50_crtc_prepare(struct drm_crtc *crtc)
467 {
468         struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
469         struct drm_device *dev = crtc->dev;
470         struct nouveau_drm *drm = nouveau_drm(dev);
471
472         NV_DEBUG(drm, "index %d\n", nv_crtc->index);
473
474         nv50_display_flip_stop(crtc);
475         drm_vblank_pre_modeset(dev, nv_crtc->index);
476         nv50_crtc_blank(nv_crtc, true);
477 }
478
479 static void
480 nv50_crtc_commit(struct drm_crtc *crtc)
481 {
482         struct drm_device *dev = crtc->dev;
483         struct nouveau_drm *drm = nouveau_drm(dev);
484         struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
485
486         NV_DEBUG(drm, "index %d\n", nv_crtc->index);
487
488         nv50_crtc_blank(nv_crtc, false);
489         drm_vblank_post_modeset(dev, nv_crtc->index);
490         nv50_display_sync(dev);
491         nv50_display_flip_next(crtc, crtc->fb, NULL);
492 }
493
494 static bool
495 nv50_crtc_mode_fixup(struct drm_crtc *crtc, const struct drm_display_mode *mode,
496                      struct drm_display_mode *adjusted_mode)
497 {
498         return true;
499 }
500
501 static int
502 nv50_crtc_do_mode_set_base(struct drm_crtc *crtc,
503                            struct drm_framebuffer *passed_fb,
504                            int x, int y, bool atomic)
505 {
506         struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
507         struct drm_device *dev = nv_crtc->base.dev;
508         struct nouveau_drm *drm = nouveau_drm(dev);
509         struct nouveau_channel *evo = nv50_display(dev)->master;
510         struct drm_framebuffer *drm_fb;
511         struct nouveau_framebuffer *fb;
512         int ret;
513
514         NV_DEBUG(drm, "index %d\n", nv_crtc->index);
515
516         /* no fb bound */
517         if (!atomic && !crtc->fb) {
518                 NV_DEBUG(drm, "No FB bound\n");
519                 return 0;
520         }
521
522         /* If atomic, we want to switch to the fb we were passed, so
523          * now we update pointers to do that.  (We don't pin; just
524          * assume we're already pinned and update the base address.)
525          */
526         if (atomic) {
527                 drm_fb = passed_fb;
528                 fb = nouveau_framebuffer(passed_fb);
529         } else {
530                 drm_fb = crtc->fb;
531                 fb = nouveau_framebuffer(crtc->fb);
532                 /* If not atomic, we can go ahead and pin, and unpin the
533                  * old fb we were passed.
534                  */
535                 ret = nouveau_bo_pin(fb->nvbo, TTM_PL_FLAG_VRAM);
536                 if (ret)
537                         return ret;
538
539                 if (passed_fb) {
540                         struct nouveau_framebuffer *ofb = nouveau_framebuffer(passed_fb);
541                         nouveau_bo_unpin(ofb->nvbo);
542                 }
543         }
544
545         nv_crtc->fb.offset = fb->nvbo->bo.offset;
546         nv_crtc->fb.tile_flags = nouveau_bo_tile_layout(fb->nvbo);
547         nv_crtc->fb.cpp = drm_fb->bits_per_pixel / 8;
548         if (!nv_crtc->fb.blanked && nv_device(drm->device)->chipset != 0x50) {
549                 ret = RING_SPACE(evo, 2);
550                 if (ret)
551                         return ret;
552
553                 BEGIN_NV04(evo, 0, NV50_EVO_CRTC(nv_crtc->index, FB_DMA), 1);
554                 OUT_RING  (evo, fb->r_dma);
555         }
556
557         ret = RING_SPACE(evo, 12);
558         if (ret)
559                 return ret;
560
561         BEGIN_NV04(evo, 0, NV50_EVO_CRTC(nv_crtc->index, FB_OFFSET), 5);
562         OUT_RING  (evo, nv_crtc->fb.offset >> 8);
563         OUT_RING  (evo, 0);
564         OUT_RING  (evo, (drm_fb->height << 16) | drm_fb->width);
565         OUT_RING  (evo, fb->r_pitch);
566         OUT_RING  (evo, fb->r_format);
567
568         BEGIN_NV04(evo, 0, NV50_EVO_CRTC(nv_crtc->index, CLUT_MODE), 1);
569         OUT_RING  (evo, fb->base.depth == 8 ?
570                    NV50_EVO_CRTC_CLUT_MODE_OFF : NV50_EVO_CRTC_CLUT_MODE_ON);
571
572         BEGIN_NV04(evo, 0, NV50_EVO_CRTC(nv_crtc->index, FB_POS), 1);
573         OUT_RING  (evo, (y << 16) | x);
574
575         if (nv_crtc->lut.depth != fb->base.depth) {
576                 nv_crtc->lut.depth = fb->base.depth;
577                 nv50_crtc_lut_load(crtc);
578         }
579
580         return 0;
581 }
582
583 static int
584 nv50_crtc_mode_set(struct drm_crtc *crtc, struct drm_display_mode *umode,
585                    struct drm_display_mode *mode, int x, int y,
586                    struct drm_framebuffer *old_fb)
587 {
588         struct drm_device *dev = crtc->dev;
589         struct nouveau_channel *evo = nv50_display(dev)->master;
590         struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
591         u32 head = nv_crtc->index * 0x400;
592         u32 ilace = (mode->flags & DRM_MODE_FLAG_INTERLACE) ? 2 : 1;
593         u32 vscan = (mode->flags & DRM_MODE_FLAG_DBLSCAN) ? 2 : 1;
594         u32 hactive, hsynce, hbackp, hfrontp, hblanke, hblanks;
595         u32 vactive, vsynce, vbackp, vfrontp, vblanke, vblanks;
596         u32 vblan2e = 0, vblan2s = 1;
597         int ret;
598
599         /* hw timing description looks like this:
600          *
601          * <sync> <back porch> <---------display---------> <front porch>
602          * ______
603          *       |____________|---------------------------|____________|
604          *
605          *       ^ synce      ^ blanke                    ^ blanks     ^ active
606          *
607          * interlaced modes also have 2 additional values pointing at the end
608          * and start of the next field's blanking period.
609          */
610
611         hactive = mode->htotal;
612         hsynce  = mode->hsync_end - mode->hsync_start - 1;
613         hbackp  = mode->htotal - mode->hsync_end;
614         hblanke = hsynce + hbackp;
615         hfrontp = mode->hsync_start - mode->hdisplay;
616         hblanks = mode->htotal - hfrontp - 1;
617
618         vactive = mode->vtotal * vscan / ilace;
619         vsynce  = ((mode->vsync_end - mode->vsync_start) * vscan / ilace) - 1;
620         vbackp  = (mode->vtotal - mode->vsync_end) * vscan / ilace;
621         vblanke = vsynce + vbackp;
622         vfrontp = (mode->vsync_start - mode->vdisplay) * vscan / ilace;
623         vblanks = vactive - vfrontp - 1;
624         if (mode->flags & DRM_MODE_FLAG_INTERLACE) {
625                 vblan2e = vactive + vsynce + vbackp;
626                 vblan2s = vblan2e + (mode->vdisplay * vscan / ilace);
627                 vactive = (vactive * 2) + 1;
628         }
629
630         ret = RING_SPACE(evo, 18);
631         if (ret == 0) {
632                 BEGIN_NV04(evo, 0, 0x0804 + head, 2);
633                 OUT_RING  (evo, 0x00800000 | mode->clock);
634                 OUT_RING  (evo, (ilace == 2) ? 2 : 0);
635                 BEGIN_NV04(evo, 0, 0x0810 + head, 6);
636                 OUT_RING  (evo, 0x00000000); /* border colour */
637                 OUT_RING  (evo, (vactive << 16) | hactive);
638                 OUT_RING  (evo, ( vsynce << 16) | hsynce);
639                 OUT_RING  (evo, (vblanke << 16) | hblanke);
640                 OUT_RING  (evo, (vblanks << 16) | hblanks);
641                 OUT_RING  (evo, (vblan2e << 16) | vblan2s);
642                 BEGIN_NV04(evo, 0, 0x082c + head, 1);
643                 OUT_RING  (evo, 0x00000000);
644                 BEGIN_NV04(evo, 0, 0x0900 + head, 1);
645                 OUT_RING  (evo, 0x00000311); /* makes sync channel work */
646                 BEGIN_NV04(evo, 0, 0x08c8 + head, 1);
647                 OUT_RING  (evo, (umode->vdisplay << 16) | umode->hdisplay);
648                 BEGIN_NV04(evo, 0, 0x08d4 + head, 1);
649                 OUT_RING  (evo, 0x00000000); /* screen position */
650         }
651
652         nv_crtc->set_dither(nv_crtc, false);
653         nv_crtc->set_scale(nv_crtc, false);
654         nv_crtc->set_color_vibrance(nv_crtc, false);
655
656         return nv50_crtc_do_mode_set_base(crtc, old_fb, x, y, false);
657 }
658
659 static int
660 nv50_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y,
661                         struct drm_framebuffer *old_fb)
662 {
663         int ret;
664
665         nv50_display_flip_stop(crtc);
666         ret = nv50_crtc_do_mode_set_base(crtc, old_fb, x, y, false);
667         if (ret)
668                 return ret;
669
670         ret = nv50_display_sync(crtc->dev);
671         if (ret)
672                 return ret;
673
674         return nv50_display_flip_next(crtc, crtc->fb, NULL);
675 }
676
677 static int
678 nv50_crtc_mode_set_base_atomic(struct drm_crtc *crtc,
679                                struct drm_framebuffer *fb,
680                                int x, int y, enum mode_set_atomic state)
681 {
682         int ret;
683
684         nv50_display_flip_stop(crtc);
685         ret = nv50_crtc_do_mode_set_base(crtc, fb, x, y, true);
686         if (ret)
687                 return ret;
688
689         return nv50_display_sync(crtc->dev);
690 }
691
692 static const struct drm_crtc_helper_funcs nv50_crtc_helper_funcs = {
693         .dpms = nv50_crtc_dpms,
694         .prepare = nv50_crtc_prepare,
695         .commit = nv50_crtc_commit,
696         .mode_fixup = nv50_crtc_mode_fixup,
697         .mode_set = nv50_crtc_mode_set,
698         .mode_set_base = nv50_crtc_mode_set_base,
699         .mode_set_base_atomic = nv50_crtc_mode_set_base_atomic,
700         .load_lut = nv50_crtc_lut_load,
701 };
702
703 int
704 nv50_crtc_create(struct drm_device *dev, int index)
705 {
706         struct nouveau_drm *drm = nouveau_drm(dev);
707         struct nouveau_crtc *nv_crtc = NULL;
708         int ret, i;
709
710         NV_DEBUG(drm, "\n");
711
712         nv_crtc = kzalloc(sizeof(*nv_crtc), GFP_KERNEL);
713         if (!nv_crtc)
714                 return -ENOMEM;
715
716         nv_crtc->index = index;
717         nv_crtc->set_dither = nv50_crtc_set_dither;
718         nv_crtc->set_scale = nv50_crtc_set_scale;
719         nv_crtc->set_color_vibrance = nv50_crtc_set_color_vibrance;
720         nv_crtc->color_vibrance = 50;
721         nv_crtc->vibrant_hue = 0;
722         nv_crtc->lut.depth = 0;
723         for (i = 0; i < 256; i++) {
724                 nv_crtc->lut.r[i] = i << 8;
725                 nv_crtc->lut.g[i] = i << 8;
726                 nv_crtc->lut.b[i] = i << 8;
727         }
728
729         drm_crtc_init(dev, &nv_crtc->base, &nv50_crtc_funcs);
730         drm_crtc_helper_add(&nv_crtc->base, &nv50_crtc_helper_funcs);
731         drm_mode_crtc_set_gamma_size(&nv_crtc->base, 256);
732
733         ret = nouveau_bo_new(dev, 4096, 0x100, TTM_PL_FLAG_VRAM,
734                              0, 0x0000, NULL, &nv_crtc->lut.nvbo);
735         if (!ret) {
736                 ret = nouveau_bo_pin(nv_crtc->lut.nvbo, TTM_PL_FLAG_VRAM);
737                 if (!ret)
738                         ret = nouveau_bo_map(nv_crtc->lut.nvbo);
739                 if (ret)
740                         nouveau_bo_ref(NULL, &nv_crtc->lut.nvbo);
741         }
742
743         if (ret)
744                 goto out;
745
746
747         ret = nouveau_bo_new(dev, 64*64*4, 0x100, TTM_PL_FLAG_VRAM,
748                              0, 0x0000, NULL, &nv_crtc->cursor.nvbo);
749         if (!ret) {
750                 ret = nouveau_bo_pin(nv_crtc->cursor.nvbo, TTM_PL_FLAG_VRAM);
751                 if (!ret)
752                         ret = nouveau_bo_map(nv_crtc->cursor.nvbo);
753                 if (ret)
754                         nouveau_bo_ref(NULL, &nv_crtc->cursor.nvbo);
755         }
756
757         if (ret)
758                 goto out;
759
760         nv50_cursor_init(nv_crtc);
761 out:
762         if (ret)
763                 nv50_crtc_destroy(&nv_crtc->base);
764         return ret;
765 }