blob: b6a8c6def64cd7cfc353b0b28d31b2c61ca16ea7 [file] [log] [blame]
Ben Skeggs26f6d882011-07-04 16:25:18 +10001/*
2 * Copyright 2011 Red Hat Inc.
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 * OTHER DEALINGS IN THE SOFTWARE.
21 *
22 * Authors: Ben Skeggs
23 */
24
Ben Skeggs51beb422011-07-05 10:33:08 +100025#include <linux/dma-mapping.h>
Ben Skeggs83fc0832011-07-05 13:08:40 +100026
Ben Skeggs26f6d882011-07-04 16:25:18 +100027#include "drmP.h"
Ben Skeggs83fc0832011-07-05 13:08:40 +100028#include "drm_crtc_helper.h"
Ben Skeggs26f6d882011-07-04 16:25:18 +100029
30#include "nouveau_drv.h"
31#include "nouveau_connector.h"
32#include "nouveau_encoder.h"
33#include "nouveau_crtc.h"
Ben Skeggs438d99e2011-07-05 16:48:06 +100034#include "nouveau_fb.h"
Ben Skeggs3a89cd02011-07-07 10:47:10 +100035#include "nv50_display.h"
Ben Skeggs26f6d882011-07-04 16:25:18 +100036
Ben Skeggsefd272a2011-07-05 11:58:58 +100037#define MEM_SYNC 0xe0000001
38#define MEM_VRAM 0xe0010000
Ben Skeggsc0cc92a2011-07-06 11:40:45 +100039#include "nouveau_dma.h"
Ben Skeggsefd272a2011-07-05 11:58:58 +100040
Ben Skeggs26f6d882011-07-04 16:25:18 +100041struct nvd0_display {
42 struct nouveau_gpuobj *mem;
Ben Skeggs51beb422011-07-05 10:33:08 +100043 struct {
44 dma_addr_t handle;
45 u32 *ptr;
46 } evo[1];
Ben Skeggsf20ce962011-07-08 13:17:01 +100047
48 struct tasklet_struct tasklet;
Ben Skeggs3a89cd02011-07-07 10:47:10 +100049 struct {
50 struct dcb_entry *dis;
51 struct dcb_entry *ena;
Ben Skeggsf20ce962011-07-08 13:17:01 +100052 u32 modeset;
Ben Skeggs3a89cd02011-07-07 10:47:10 +100053 int crtc;
54 int pclk;
Ben Skeggsff8ff502011-07-08 11:53:37 +100055 u16 cfg;
Ben Skeggs3a89cd02011-07-07 10:47:10 +100056 } irq;
Ben Skeggs26f6d882011-07-04 16:25:18 +100057};
58
59static struct nvd0_display *
60nvd0_display(struct drm_device *dev)
61{
62 struct drm_nouveau_private *dev_priv = dev->dev_private;
63 return dev_priv->engine.display.priv;
64}
65
Ben Skeggs51beb422011-07-05 10:33:08 +100066static int
67evo_icmd(struct drm_device *dev, int id, u32 mthd, u32 data)
68{
69 int ret = 0;
70 nv_mask(dev, 0x610700 + (id * 0x10), 0x00000001, 0x00000001);
71 nv_wr32(dev, 0x610704 + (id * 0x10), data);
72 nv_mask(dev, 0x610704 + (id * 0x10), 0x80000ffc, 0x80000000 | mthd);
73 if (!nv_wait(dev, 0x610704 + (id * 0x10), 0x80000000, 0x00000000))
74 ret = -EBUSY;
75 nv_mask(dev, 0x610700 + (id * 0x10), 0x00000001, 0x00000000);
76 return ret;
77}
78
79static u32 *
80evo_wait(struct drm_device *dev, int id, int nr)
81{
82 struct nvd0_display *disp = nvd0_display(dev);
83 u32 put = nv_rd32(dev, 0x640000 + (id * 0x1000)) / 4;
84
85 if (put + nr >= (PAGE_SIZE / 4)) {
86 disp->evo[id].ptr[put] = 0x20000000;
87
88 nv_wr32(dev, 0x640000 + (id * 0x1000), 0x00000000);
89 if (!nv_wait(dev, 0x640004 + (id * 0x1000), ~0, 0x00000000)) {
90 NV_ERROR(dev, "evo %d dma stalled\n", id);
91 return NULL;
92 }
93
94 put = 0;
95 }
96
97 return disp->evo[id].ptr + put;
98}
99
100static void
101evo_kick(u32 *push, struct drm_device *dev, int id)
102{
103 struct nvd0_display *disp = nvd0_display(dev);
104 nv_wr32(dev, 0x640000 + (id * 0x1000), (push - disp->evo[id].ptr) << 2);
105}
106
107#define evo_mthd(p,m,s) *((p)++) = (((s) << 18) | (m))
108#define evo_data(p,d) *((p)++) = (d)
109
Ben Skeggs83fc0832011-07-05 13:08:40 +1000110static struct drm_crtc *
111nvd0_display_crtc_get(struct drm_encoder *encoder)
112{
113 return nouveau_encoder(encoder)->crtc;
114}
115
Ben Skeggs26f6d882011-07-04 16:25:18 +1000116/******************************************************************************
Ben Skeggs438d99e2011-07-05 16:48:06 +1000117 * CRTC
118 *****************************************************************************/
119static int
120nvd0_crtc_set_dither(struct nouveau_crtc *nv_crtc, bool on, bool update)
121{
122 struct drm_device *dev = nv_crtc->base.dev;
123 u32 *push, mode;
124
125 mode = 0x00000000;
126 if (on) {
127 /* 0x11: 6bpc dynamic 2x2
128 * 0x13: 8bpc dynamic 2x2
129 * 0x19: 6bpc static 2x2
130 * 0x1b: 8bpc static 2x2
131 * 0x21: 6bpc temporal
132 * 0x23: 8bpc temporal
133 */
134 mode = 0x00000011;
135 }
136
137 push = evo_wait(dev, 0, 4);
138 if (push) {
139 evo_mthd(push, 0x0490 + (nv_crtc->index * 0x300), 1);
140 evo_data(push, mode);
141 if (update) {
142 evo_mthd(push, 0x0080, 1);
143 evo_data(push, 0x00000000);
144 }
145 evo_kick(push, dev, 0);
146 }
147
148 return 0;
149}
150
151static int
152nvd0_crtc_set_scale(struct nouveau_crtc *nv_crtc, int type, bool update)
153{
154 struct drm_display_mode *mode = &nv_crtc->base.mode;
155 struct drm_device *dev = nv_crtc->base.dev;
Ben Skeggsf3fdc522011-07-07 16:01:57 +1000156 struct nouveau_connector *nv_connector;
157 u32 *push, outX, outY;
Ben Skeggs438d99e2011-07-05 16:48:06 +1000158
Ben Skeggsf3fdc522011-07-07 16:01:57 +1000159 outX = mode->hdisplay;
160 outY = mode->vdisplay;
161
162 nv_connector = nouveau_crtc_connector_get(nv_crtc);
163 if (nv_connector && nv_connector->native_mode) {
164 struct drm_display_mode *native = nv_connector->native_mode;
165 u32 xratio = (native->hdisplay << 19) / mode->hdisplay;
166 u32 yratio = (native->vdisplay << 19) / mode->vdisplay;
167
168 switch (type) {
169 case DRM_MODE_SCALE_ASPECT:
170 if (xratio > yratio) {
171 outX = (mode->hdisplay * yratio) >> 19;
172 outY = (mode->vdisplay * yratio) >> 19;
173 } else {
174 outX = (mode->hdisplay * xratio) >> 19;
175 outY = (mode->vdisplay * xratio) >> 19;
176 }
177 break;
178 case DRM_MODE_SCALE_FULLSCREEN:
179 outX = native->hdisplay;
180 outY = native->vdisplay;
181 break;
182 default:
183 break;
184 }
185 }
Ben Skeggs438d99e2011-07-05 16:48:06 +1000186
187 push = evo_wait(dev, 0, 16);
188 if (push) {
189 evo_mthd(push, 0x04c0 + (nv_crtc->index * 0x300), 3);
Ben Skeggsf3fdc522011-07-07 16:01:57 +1000190 evo_data(push, (outY << 16) | outX);
191 evo_data(push, (outY << 16) | outX);
192 evo_data(push, (outY << 16) | outX);
Ben Skeggs438d99e2011-07-05 16:48:06 +1000193 evo_mthd(push, 0x0494 + (nv_crtc->index * 0x300), 1);
194 evo_data(push, 0x00000000);
Ben Skeggs438d99e2011-07-05 16:48:06 +1000195 evo_mthd(push, 0x04b8 + (nv_crtc->index * 0x300), 1);
196 evo_data(push, (mode->vdisplay << 16) | mode->hdisplay);
197 if (update) {
198 evo_mthd(push, 0x0080, 1);
199 evo_data(push, 0x00000000);
200 }
201 evo_kick(push, dev, 0);
202 }
203
204 return 0;
205}
206
207static int
208nvd0_crtc_set_image(struct nouveau_crtc *nv_crtc, struct drm_framebuffer *fb,
209 int x, int y, bool update)
210{
211 struct nouveau_framebuffer *nvfb = nouveau_framebuffer(fb);
212 u32 *push;
213
Ben Skeggs438d99e2011-07-05 16:48:06 +1000214 push = evo_wait(fb->dev, 0, 16);
215 if (push) {
216 evo_mthd(push, 0x0460 + (nv_crtc->index * 0x300), 1);
217 evo_data(push, nvfb->nvbo->bo.offset >> 8);
218 evo_mthd(push, 0x0468 + (nv_crtc->index * 0x300), 4);
219 evo_data(push, (fb->height << 16) | fb->width);
220 evo_data(push, nvfb->r_pitch);
221 evo_data(push, nvfb->r_format);
Ben Skeggsc0cc92a2011-07-06 11:40:45 +1000222 evo_data(push, nvfb->r_dma);
Ben Skeggsc6f2f712011-07-08 12:11:58 +1000223 evo_mthd(push, 0x04b0 + (nv_crtc->index * 0x300), 1);
224 evo_data(push, (y << 16) | x);
Ben Skeggsa46232e2011-07-07 15:23:48 +1000225 if (update) {
226 evo_mthd(push, 0x0080, 1);
227 evo_data(push, 0x00000000);
228 }
Ben Skeggs438d99e2011-07-05 16:48:06 +1000229 evo_kick(push, fb->dev, 0);
230 }
231
Ben Skeggsc0cc92a2011-07-06 11:40:45 +1000232 nv_crtc->fb.tile_flags = nvfb->r_dma;
Ben Skeggs438d99e2011-07-05 16:48:06 +1000233 return 0;
234}
235
236static void
237nvd0_crtc_cursor_show(struct nouveau_crtc *nv_crtc, bool show, bool update)
238{
239 struct drm_device *dev = nv_crtc->base.dev;
240 u32 *push = evo_wait(dev, 0, 16);
241 if (push) {
242 if (show) {
243 evo_mthd(push, 0x0480 + (nv_crtc->index * 0x300), 2);
244 evo_data(push, 0x85000000);
245 evo_data(push, nv_crtc->cursor.nvbo->bo.offset >> 8);
246 evo_mthd(push, 0x048c + (nv_crtc->index * 0x300), 1);
247 evo_data(push, MEM_VRAM);
248 } else {
249 evo_mthd(push, 0x0480 + (nv_crtc->index * 0x300), 1);
250 evo_data(push, 0x05000000);
251 evo_mthd(push, 0x048c + (nv_crtc->index * 0x300), 1);
252 evo_data(push, 0x00000000);
253 }
254
255 if (update) {
256 evo_mthd(push, 0x0080, 1);
257 evo_data(push, 0x00000000);
258 }
259
260 evo_kick(push, dev, 0);
261 }
262}
263
264static void
265nvd0_crtc_dpms(struct drm_crtc *crtc, int mode)
266{
267}
268
269static void
270nvd0_crtc_prepare(struct drm_crtc *crtc)
271{
272 struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
273 u32 *push;
274
275 push = evo_wait(crtc->dev, 0, 2);
276 if (push) {
277 evo_mthd(push, 0x0474 + (nv_crtc->index * 0x300), 1);
278 evo_data(push, 0x00000000);
279 evo_mthd(push, 0x0440 + (nv_crtc->index * 0x300), 1);
280 evo_data(push, 0x03000000);
281 evo_mthd(push, 0x045c + (nv_crtc->index * 0x300), 1);
282 evo_data(push, 0x00000000);
283 evo_kick(push, crtc->dev, 0);
284 }
285
286 nvd0_crtc_cursor_show(nv_crtc, false, false);
287}
288
289static void
290nvd0_crtc_commit(struct drm_crtc *crtc)
291{
292 struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
293 u32 *push;
294
295 push = evo_wait(crtc->dev, 0, 32);
296 if (push) {
297 evo_mthd(push, 0x0474 + (nv_crtc->index * 0x300), 1);
298 evo_data(push, nv_crtc->fb.tile_flags);
299 evo_mthd(push, 0x0440 + (nv_crtc->index * 0x300), 4);
300 evo_data(push, 0x83000000);
301 evo_data(push, nv_crtc->lut.nvbo->bo.offset >> 8);
302 evo_data(push, 0x00000000);
303 evo_data(push, 0x00000000);
304 evo_mthd(push, 0x045c + (nv_crtc->index * 0x300), 1);
305 evo_data(push, MEM_VRAM);
Ben Skeggs8ea0d4a2011-07-07 14:49:24 +1000306 evo_mthd(push, 0x0430 + (nv_crtc->index * 0x300), 1);
307 evo_data(push, 0xffffff00);
Ben Skeggs438d99e2011-07-05 16:48:06 +1000308 evo_kick(push, crtc->dev, 0);
309 }
310
311 nvd0_crtc_cursor_show(nv_crtc, nv_crtc->cursor.visible, true);
312}
313
314static bool
315nvd0_crtc_mode_fixup(struct drm_crtc *crtc, struct drm_display_mode *mode,
316 struct drm_display_mode *adjusted_mode)
317{
318 return true;
319}
320
321static int
322nvd0_crtc_swap_fbs(struct drm_crtc *crtc, struct drm_framebuffer *old_fb)
323{
324 struct nouveau_framebuffer *nvfb = nouveau_framebuffer(crtc->fb);
325 int ret;
326
327 ret = nouveau_bo_pin(nvfb->nvbo, TTM_PL_FLAG_VRAM);
328 if (ret)
329 return ret;
330
331 if (old_fb) {
332 nvfb = nouveau_framebuffer(old_fb);
333 nouveau_bo_unpin(nvfb->nvbo);
334 }
335
336 return 0;
337}
338
339static int
340nvd0_crtc_mode_set(struct drm_crtc *crtc, struct drm_display_mode *umode,
341 struct drm_display_mode *mode, int x, int y,
342 struct drm_framebuffer *old_fb)
343{
344 struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
345 struct nouveau_connector *nv_connector;
346 u32 htotal = mode->htotal;
347 u32 vtotal = mode->vtotal;
348 u32 hsyncw = mode->hsync_end - mode->hsync_start - 1;
349 u32 vsyncw = mode->vsync_end - mode->vsync_start - 1;
350 u32 hfrntp = mode->hsync_start - mode->hdisplay;
351 u32 vfrntp = mode->vsync_start - mode->vdisplay;
352 u32 hbackp = mode->htotal - mode->hsync_end;
353 u32 vbackp = mode->vtotal - mode->vsync_end;
354 u32 hss2be = hsyncw + hbackp;
355 u32 vss2be = vsyncw + vbackp;
356 u32 hss2de = htotal - hfrntp;
357 u32 vss2de = vtotal - vfrntp;
Ben Skeggs629c1b92011-07-08 09:43:20 +1000358 u32 syncs, *push;
Ben Skeggs438d99e2011-07-05 16:48:06 +1000359 int ret;
360
Ben Skeggs629c1b92011-07-08 09:43:20 +1000361 syncs = 0x00000001;
362 if (mode->flags & DRM_MODE_FLAG_NHSYNC)
363 syncs |= 0x00000008;
364 if (mode->flags & DRM_MODE_FLAG_NVSYNC)
365 syncs |= 0x00000010;
366
Ben Skeggs438d99e2011-07-05 16:48:06 +1000367 ret = nvd0_crtc_swap_fbs(crtc, old_fb);
368 if (ret)
369 return ret;
370
371 push = evo_wait(crtc->dev, 0, 64);
372 if (push) {
373 evo_mthd(push, 0x0410 + (nv_crtc->index * 0x300), 5);
Ben Skeggs629c1b92011-07-08 09:43:20 +1000374 evo_data(push, 0x00000000);
Ben Skeggs438d99e2011-07-05 16:48:06 +1000375 evo_data(push, (vtotal << 16) | htotal);
376 evo_data(push, (vsyncw << 16) | hsyncw);
377 evo_data(push, (vss2be << 16) | hss2be);
378 evo_data(push, (vss2de << 16) | hss2de);
379 evo_mthd(push, 0x042c + (nv_crtc->index * 0x300), 1);
380 evo_data(push, 0x00000000); /* ??? */
381 evo_mthd(push, 0x0450 + (nv_crtc->index * 0x300), 3);
382 evo_data(push, mode->clock * 1000);
383 evo_data(push, 0x00200000); /* ??? */
384 evo_data(push, mode->clock * 1000);
Ben Skeggs629c1b92011-07-08 09:43:20 +1000385 evo_mthd(push, 0x0404 + (nv_crtc->index * 0x300), 1);
386 evo_data(push, syncs);
Ben Skeggs438d99e2011-07-05 16:48:06 +1000387 evo_kick(push, crtc->dev, 0);
388 }
389
390 nv_connector = nouveau_crtc_connector_get(nv_crtc);
391 nvd0_crtc_set_dither(nv_crtc, nv_connector->use_dithering, false);
392 nvd0_crtc_set_scale(nv_crtc, nv_connector->scaling_mode, false);
393 nvd0_crtc_set_image(nv_crtc, crtc->fb, x, y, false);
394 return 0;
395}
396
397static int
398nvd0_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y,
399 struct drm_framebuffer *old_fb)
400{
401 struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
402 int ret;
403
404 ret = nvd0_crtc_swap_fbs(crtc, old_fb);
405 if (ret)
406 return ret;
407
408 nvd0_crtc_set_image(nv_crtc, crtc->fb, x, y, true);
409 return 0;
410}
411
412static int
413nvd0_crtc_mode_set_base_atomic(struct drm_crtc *crtc,
414 struct drm_framebuffer *fb, int x, int y,
415 enum mode_set_atomic state)
416{
417 struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
418 nvd0_crtc_set_image(nv_crtc, fb, x, y, true);
419 return 0;
420}
421
422static void
423nvd0_crtc_lut_load(struct drm_crtc *crtc)
424{
425 struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
426 void __iomem *lut = nvbo_kmap_obj_iovirtual(nv_crtc->lut.nvbo);
427 int i;
428
429 for (i = 0; i < 256; i++) {
Ben Skeggs8ea0d4a2011-07-07 14:49:24 +1000430 writew(0x6000 + (nv_crtc->lut.r[i] >> 2), lut + (i * 0x20) + 0);
431 writew(0x6000 + (nv_crtc->lut.g[i] >> 2), lut + (i * 0x20) + 2);
432 writew(0x6000 + (nv_crtc->lut.b[i] >> 2), lut + (i * 0x20) + 4);
Ben Skeggs438d99e2011-07-05 16:48:06 +1000433 }
434}
435
436static int
437nvd0_crtc_cursor_set(struct drm_crtc *crtc, struct drm_file *file_priv,
438 uint32_t handle, uint32_t width, uint32_t height)
439{
440 struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
441 struct drm_device *dev = crtc->dev;
442 struct drm_gem_object *gem;
443 struct nouveau_bo *nvbo;
444 bool visible = (handle != 0);
445 int i, ret = 0;
446
447 if (visible) {
448 if (width != 64 || height != 64)
449 return -EINVAL;
450
451 gem = drm_gem_object_lookup(dev, file_priv, handle);
452 if (unlikely(!gem))
453 return -ENOENT;
454 nvbo = nouveau_gem_object(gem);
455
456 ret = nouveau_bo_map(nvbo);
457 if (ret == 0) {
458 for (i = 0; i < 64 * 64; i++) {
459 u32 v = nouveau_bo_rd32(nvbo, i);
460 nouveau_bo_wr32(nv_crtc->cursor.nvbo, i, v);
461 }
462 nouveau_bo_unmap(nvbo);
463 }
464
465 drm_gem_object_unreference_unlocked(gem);
466 }
467
468 if (visible != nv_crtc->cursor.visible) {
469 nvd0_crtc_cursor_show(nv_crtc, visible, true);
470 nv_crtc->cursor.visible = visible;
471 }
472
473 return ret;
474}
475
476static int
477nvd0_crtc_cursor_move(struct drm_crtc *crtc, int x, int y)
478{
479 struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
480 const u32 data = (y << 16) | x;
481
482 nv_wr32(crtc->dev, 0x64d084 + (nv_crtc->index * 0x1000), data);
483 nv_wr32(crtc->dev, 0x64d080 + (nv_crtc->index * 0x1000), 0x00000000);
484 return 0;
485}
486
487static void
488nvd0_crtc_gamma_set(struct drm_crtc *crtc, u16 *r, u16 *g, u16 *b,
489 uint32_t start, uint32_t size)
490{
491 struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
492 u32 end = max(start + size, (u32)256);
493 u32 i;
494
495 for (i = start; i < end; i++) {
496 nv_crtc->lut.r[i] = r[i];
497 nv_crtc->lut.g[i] = g[i];
498 nv_crtc->lut.b[i] = b[i];
499 }
500
501 nvd0_crtc_lut_load(crtc);
502}
503
504static void
505nvd0_crtc_destroy(struct drm_crtc *crtc)
506{
507 struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
508 nouveau_bo_unmap(nv_crtc->cursor.nvbo);
509 nouveau_bo_ref(NULL, &nv_crtc->cursor.nvbo);
510 nouveau_bo_unmap(nv_crtc->lut.nvbo);
511 nouveau_bo_ref(NULL, &nv_crtc->lut.nvbo);
512 drm_crtc_cleanup(crtc);
513 kfree(crtc);
514}
515
516static const struct drm_crtc_helper_funcs nvd0_crtc_hfunc = {
517 .dpms = nvd0_crtc_dpms,
518 .prepare = nvd0_crtc_prepare,
519 .commit = nvd0_crtc_commit,
520 .mode_fixup = nvd0_crtc_mode_fixup,
521 .mode_set = nvd0_crtc_mode_set,
522 .mode_set_base = nvd0_crtc_mode_set_base,
523 .mode_set_base_atomic = nvd0_crtc_mode_set_base_atomic,
524 .load_lut = nvd0_crtc_lut_load,
525};
526
527static const struct drm_crtc_funcs nvd0_crtc_func = {
528 .cursor_set = nvd0_crtc_cursor_set,
529 .cursor_move = nvd0_crtc_cursor_move,
530 .gamma_set = nvd0_crtc_gamma_set,
531 .set_config = drm_crtc_helper_set_config,
532 .destroy = nvd0_crtc_destroy,
533};
534
535static int
536nvd0_crtc_create(struct drm_device *dev, int index)
537{
538 struct nouveau_crtc *nv_crtc;
539 struct drm_crtc *crtc;
540 int ret, i;
541
542 nv_crtc = kzalloc(sizeof(*nv_crtc), GFP_KERNEL);
543 if (!nv_crtc)
544 return -ENOMEM;
545
546 nv_crtc->index = index;
547 nv_crtc->set_dither = nvd0_crtc_set_dither;
548 nv_crtc->set_scale = nvd0_crtc_set_scale;
549 for (i = 0; i < 256; i++) {
550 nv_crtc->lut.r[i] = i << 8;
551 nv_crtc->lut.g[i] = i << 8;
552 nv_crtc->lut.b[i] = i << 8;
553 }
554
555 crtc = &nv_crtc->base;
556 drm_crtc_init(dev, crtc, &nvd0_crtc_func);
557 drm_crtc_helper_add(crtc, &nvd0_crtc_hfunc);
558 drm_mode_crtc_set_gamma_size(crtc, 256);
559
560 ret = nouveau_bo_new(dev, 64 * 64 * 4, 0x100, TTM_PL_FLAG_VRAM,
561 0, 0x0000, &nv_crtc->cursor.nvbo);
562 if (!ret) {
563 ret = nouveau_bo_pin(nv_crtc->cursor.nvbo, TTM_PL_FLAG_VRAM);
564 if (!ret)
565 ret = nouveau_bo_map(nv_crtc->cursor.nvbo);
566 if (ret)
567 nouveau_bo_ref(NULL, &nv_crtc->cursor.nvbo);
568 }
569
570 if (ret)
571 goto out;
572
Ben Skeggs8ea0d4a2011-07-07 14:49:24 +1000573 ret = nouveau_bo_new(dev, 8192, 0x100, TTM_PL_FLAG_VRAM,
Ben Skeggs438d99e2011-07-05 16:48:06 +1000574 0, 0x0000, &nv_crtc->lut.nvbo);
575 if (!ret) {
576 ret = nouveau_bo_pin(nv_crtc->lut.nvbo, TTM_PL_FLAG_VRAM);
577 if (!ret)
578 ret = nouveau_bo_map(nv_crtc->lut.nvbo);
579 if (ret)
580 nouveau_bo_ref(NULL, &nv_crtc->lut.nvbo);
581 }
582
583 if (ret)
584 goto out;
585
586 nvd0_crtc_lut_load(crtc);
587
588out:
589 if (ret)
590 nvd0_crtc_destroy(crtc);
591 return ret;
592}
593
594/******************************************************************************
Ben Skeggs26f6d882011-07-04 16:25:18 +1000595 * DAC
596 *****************************************************************************/
Ben Skeggs8eaa9662011-07-06 15:25:47 +1000597static void
598nvd0_dac_dpms(struct drm_encoder *encoder, int mode)
599{
600 struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
601 struct drm_device *dev = encoder->dev;
602 int or = nv_encoder->or;
603 u32 dpms_ctrl;
604
605 dpms_ctrl = 0x80000000;
606 if (mode == DRM_MODE_DPMS_STANDBY || mode == DRM_MODE_DPMS_OFF)
607 dpms_ctrl |= 0x00000001;
608 if (mode == DRM_MODE_DPMS_SUSPEND || mode == DRM_MODE_DPMS_OFF)
609 dpms_ctrl |= 0x00000004;
610
611 nv_wait(dev, 0x61a004 + (or * 0x0800), 0x80000000, 0x00000000);
612 nv_mask(dev, 0x61a004 + (or * 0x0800), 0xc000007f, dpms_ctrl);
613 nv_wait(dev, 0x61a004 + (or * 0x0800), 0x80000000, 0x00000000);
614}
615
616static bool
617nvd0_dac_mode_fixup(struct drm_encoder *encoder, struct drm_display_mode *mode,
618 struct drm_display_mode *adjusted_mode)
619{
620 struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
621 struct nouveau_connector *nv_connector;
622
623 nv_connector = nouveau_encoder_connector_get(nv_encoder);
624 if (nv_connector && nv_connector->native_mode) {
625 if (nv_connector->scaling_mode != DRM_MODE_SCALE_NONE) {
626 int id = adjusted_mode->base.id;
627 *adjusted_mode = *nv_connector->native_mode;
628 adjusted_mode->base.id = id;
629 }
630 }
631
632 return true;
633}
634
635static void
636nvd0_dac_prepare(struct drm_encoder *encoder)
637{
638}
639
640static void
641nvd0_dac_commit(struct drm_encoder *encoder)
642{
643}
644
645static void
646nvd0_dac_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode,
647 struct drm_display_mode *adjusted_mode)
648{
649 struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
650 struct nouveau_crtc *nv_crtc = nouveau_crtc(encoder->crtc);
651 u32 *push;
652
653 nvd0_dac_dpms(encoder, DRM_MODE_DPMS_ON);
654
Ben Skeggsff8ff502011-07-08 11:53:37 +1000655 push = evo_wait(encoder->dev, 0, 4);
Ben Skeggs8eaa9662011-07-06 15:25:47 +1000656 if (push) {
Ben Skeggsff8ff502011-07-08 11:53:37 +1000657 evo_mthd(push, 0x0180 + (nv_encoder->or * 0x20), 2);
Ben Skeggs8eaa9662011-07-06 15:25:47 +1000658 evo_data(push, 1 << nv_crtc->index);
Ben Skeggsff8ff502011-07-08 11:53:37 +1000659 evo_data(push, 0x00ff);
Ben Skeggs8eaa9662011-07-06 15:25:47 +1000660 evo_kick(push, encoder->dev, 0);
661 }
662
663 nv_encoder->crtc = encoder->crtc;
664}
665
666static void
667nvd0_dac_disconnect(struct drm_encoder *encoder)
668{
669 struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
670 struct drm_device *dev = encoder->dev;
671 u32 *push;
672
673 if (nv_encoder->crtc) {
674 nvd0_crtc_prepare(nv_encoder->crtc);
675
676 push = evo_wait(dev, 0, 4);
677 if (push) {
678 evo_mthd(push, 0x0180 + (nv_encoder->or * 0x20), 1);
679 evo_data(push, 0x00000000);
680 evo_mthd(push, 0x0080, 1);
681 evo_data(push, 0x00000000);
682 evo_kick(push, dev, 0);
683 }
684
685 nv_encoder->crtc = NULL;
686 }
687}
688
Ben Skeggsb6d8e7e2011-07-07 09:51:29 +1000689static enum drm_connector_status
690nvd0_dac_detect(struct drm_encoder *encoder, struct drm_connector *connector)
691{
Ben Skeggsb6819932011-07-08 11:14:50 +1000692 enum drm_connector_status status = connector_status_disconnected;
693 struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
694 struct drm_device *dev = encoder->dev;
695 int or = nv_encoder->or;
696 u32 load;
697
698 nv_wr32(dev, 0x61a00c + (or * 0x800), 0x00100000);
699 udelay(9500);
700 nv_wr32(dev, 0x61a00c + (or * 0x800), 0x80000000);
701
702 load = nv_rd32(dev, 0x61a00c + (or * 0x800));
703 if ((load & 0x38000000) == 0x38000000)
704 status = connector_status_connected;
705
706 nv_wr32(dev, 0x61a00c + (or * 0x800), 0x00000000);
707 return status;
Ben Skeggsb6d8e7e2011-07-07 09:51:29 +1000708}
709
Ben Skeggs8eaa9662011-07-06 15:25:47 +1000710static void
711nvd0_dac_destroy(struct drm_encoder *encoder)
712{
713 drm_encoder_cleanup(encoder);
714 kfree(encoder);
715}
716
717static const struct drm_encoder_helper_funcs nvd0_dac_hfunc = {
718 .dpms = nvd0_dac_dpms,
719 .mode_fixup = nvd0_dac_mode_fixup,
720 .prepare = nvd0_dac_prepare,
721 .commit = nvd0_dac_commit,
722 .mode_set = nvd0_dac_mode_set,
723 .disable = nvd0_dac_disconnect,
724 .get_crtc = nvd0_display_crtc_get,
Ben Skeggsb6d8e7e2011-07-07 09:51:29 +1000725 .detect = nvd0_dac_detect
Ben Skeggs8eaa9662011-07-06 15:25:47 +1000726};
727
728static const struct drm_encoder_funcs nvd0_dac_func = {
729 .destroy = nvd0_dac_destroy,
730};
731
732static int
733nvd0_dac_create(struct drm_connector *connector, struct dcb_entry *dcbe)
734{
735 struct drm_device *dev = connector->dev;
736 struct nouveau_encoder *nv_encoder;
737 struct drm_encoder *encoder;
738
739 nv_encoder = kzalloc(sizeof(*nv_encoder), GFP_KERNEL);
740 if (!nv_encoder)
741 return -ENOMEM;
742 nv_encoder->dcb = dcbe;
743 nv_encoder->or = ffs(dcbe->or) - 1;
744
745 encoder = to_drm_encoder(nv_encoder);
746 encoder->possible_crtcs = dcbe->heads;
747 encoder->possible_clones = 0;
748 drm_encoder_init(dev, encoder, &nvd0_dac_func, DRM_MODE_ENCODER_DAC);
749 drm_encoder_helper_add(encoder, &nvd0_dac_hfunc);
750
751 drm_mode_connector_attach_encoder(connector, encoder);
752 return 0;
753}
Ben Skeggs26f6d882011-07-04 16:25:18 +1000754
755/******************************************************************************
756 * SOR
757 *****************************************************************************/
Ben Skeggs83fc0832011-07-05 13:08:40 +1000758static void
759nvd0_sor_dpms(struct drm_encoder *encoder, int mode)
760{
761 struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
762 struct drm_device *dev = encoder->dev;
763 struct drm_encoder *partner;
764 int or = nv_encoder->or;
765 u32 dpms_ctrl;
766
767 nv_encoder->last_dpms = mode;
768
769 list_for_each_entry(partner, &dev->mode_config.encoder_list, head) {
770 struct nouveau_encoder *nv_partner = nouveau_encoder(partner);
771
772 if (partner->encoder_type != DRM_MODE_ENCODER_TMDS)
773 continue;
774
775 if (nv_partner != nv_encoder &&
776 nv_partner->dcb->or == nv_encoder->or) {
777 if (nv_partner->last_dpms == DRM_MODE_DPMS_ON)
778 return;
779 break;
780 }
781 }
782
783 dpms_ctrl = (mode == DRM_MODE_DPMS_ON);
784 dpms_ctrl |= 0x80000000;
785
786 nv_wait(dev, 0x61c004 + (or * 0x0800), 0x80000000, 0x00000000);
787 nv_mask(dev, 0x61c004 + (or * 0x0800), 0x80000001, dpms_ctrl);
788 nv_wait(dev, 0x61c004 + (or * 0x0800), 0x80000000, 0x00000000);
789 nv_wait(dev, 0x61c030 + (or * 0x0800), 0x10000000, 0x00000000);
790}
791
792static bool
793nvd0_sor_mode_fixup(struct drm_encoder *encoder, struct drm_display_mode *mode,
794 struct drm_display_mode *adjusted_mode)
795{
796 struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
797 struct nouveau_connector *nv_connector;
798
799 nv_connector = nouveau_encoder_connector_get(nv_encoder);
800 if (nv_connector && nv_connector->native_mode) {
801 if (nv_connector->scaling_mode != DRM_MODE_SCALE_NONE) {
802 int id = adjusted_mode->base.id;
803 *adjusted_mode = *nv_connector->native_mode;
804 adjusted_mode->base.id = id;
805 }
806 }
807
808 return true;
809}
810
811static void
812nvd0_sor_prepare(struct drm_encoder *encoder)
813{
814}
815
816static void
817nvd0_sor_commit(struct drm_encoder *encoder)
818{
819}
820
821static void
Ben Skeggs3b6d83d12011-07-08 12:52:14 +1000822nvd0_sor_mode_set(struct drm_encoder *encoder, struct drm_display_mode *umode,
823 struct drm_display_mode *mode)
Ben Skeggs83fc0832011-07-05 13:08:40 +1000824{
Ben Skeggs3b6d83d12011-07-08 12:52:14 +1000825 struct drm_nouveau_private *dev_priv = encoder->dev->dev_private;
Ben Skeggs83fc0832011-07-05 13:08:40 +1000826 struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
827 struct nouveau_crtc *nv_crtc = nouveau_crtc(encoder->crtc);
Ben Skeggs3b6d83d12011-07-08 12:52:14 +1000828 struct nouveau_connector *nv_connector;
829 struct nvbios *bios = &dev_priv->vbios;
Ben Skeggs83fc0832011-07-05 13:08:40 +1000830 u32 mode_ctrl = (1 << nv_crtc->index);
Ben Skeggsff8ff502011-07-08 11:53:37 +1000831 u32 *push, or_config;
Ben Skeggs83fc0832011-07-05 13:08:40 +1000832
Ben Skeggs3b6d83d12011-07-08 12:52:14 +1000833 nv_connector = nouveau_encoder_connector_get(nv_encoder);
834 switch (nv_encoder->dcb->type) {
835 case OUTPUT_TMDS:
836 if (nv_encoder->dcb->sorconf.link & 1) {
837 if (mode->clock < 165000)
838 mode_ctrl |= 0x00000100;
839 else
840 mode_ctrl |= 0x00000500;
841 } else {
842 mode_ctrl |= 0x00000200;
843 }
Ben Skeggs83fc0832011-07-05 13:08:40 +1000844
Ben Skeggs3b6d83d12011-07-08 12:52:14 +1000845 or_config = (mode_ctrl & 0x00000f00) >> 8;
846 if (mode->clock >= 165000)
847 or_config |= 0x0100;
848 break;
849 case OUTPUT_LVDS:
850 or_config = (mode_ctrl & 0x00000f00) >> 8;
851 if (bios->fp_no_ddc) {
852 if (bios->fp.dual_link)
853 or_config |= 0x0100;
854 if (bios->fp.if_is_24bit)
855 or_config |= 0x0200;
856 } else {
857 if (nv_connector->dcb->type == DCB_CONNECTOR_LVDS_SPWG) {
858 if (((u8 *)nv_connector->edid)[121] == 2)
859 or_config |= 0x0100;
860 } else
861 if (mode->clock >= bios->fp.duallink_transition_clk) {
862 or_config |= 0x0100;
863 }
864
865 if (or_config & 0x0100) {
866 if (bios->fp.strapless_is_24bit & 2)
867 or_config |= 0x0200;
868 } else {
869 if (bios->fp.strapless_is_24bit & 1)
870 or_config |= 0x0200;
871 }
872
873 if (nv_connector->base.display_info.bpc == 8)
874 or_config |= 0x0200;
875
876 }
877 break;
878 default:
879 BUG_ON(1);
880 break;
881 }
Ben Skeggsff8ff502011-07-08 11:53:37 +1000882
Ben Skeggs83fc0832011-07-05 13:08:40 +1000883 nvd0_sor_dpms(encoder, DRM_MODE_DPMS_ON);
884
Ben Skeggsff8ff502011-07-08 11:53:37 +1000885 push = evo_wait(encoder->dev, 0, 4);
Ben Skeggs83fc0832011-07-05 13:08:40 +1000886 if (push) {
Ben Skeggsff8ff502011-07-08 11:53:37 +1000887 evo_mthd(push, 0x0200 + (nv_encoder->or * 0x20), 2);
Ben Skeggs83fc0832011-07-05 13:08:40 +1000888 evo_data(push, mode_ctrl);
Ben Skeggsff8ff502011-07-08 11:53:37 +1000889 evo_data(push, or_config);
Ben Skeggs438d99e2011-07-05 16:48:06 +1000890 evo_kick(push, encoder->dev, 0);
Ben Skeggs83fc0832011-07-05 13:08:40 +1000891 }
892
893 nv_encoder->crtc = encoder->crtc;
894}
895
896static void
897nvd0_sor_disconnect(struct drm_encoder *encoder)
898{
899 struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
900 struct drm_device *dev = encoder->dev;
Ben Skeggs438d99e2011-07-05 16:48:06 +1000901 u32 *push;
Ben Skeggs83fc0832011-07-05 13:08:40 +1000902
903 if (nv_encoder->crtc) {
Ben Skeggs438d99e2011-07-05 16:48:06 +1000904 nvd0_crtc_prepare(nv_encoder->crtc);
905
906 push = evo_wait(dev, 0, 4);
Ben Skeggs83fc0832011-07-05 13:08:40 +1000907 if (push) {
908 evo_mthd(push, 0x0200 + (nv_encoder->or * 0x20), 1);
909 evo_data(push, 0x00000000);
910 evo_mthd(push, 0x0080, 1);
911 evo_data(push, 0x00000000);
912 evo_kick(push, dev, 0);
913 }
914
915 nv_encoder->crtc = NULL;
916 nv_encoder->last_dpms = DRM_MODE_DPMS_OFF;
917 }
918}
919
920static void
921nvd0_sor_destroy(struct drm_encoder *encoder)
922{
923 drm_encoder_cleanup(encoder);
924 kfree(encoder);
925}
926
927static const struct drm_encoder_helper_funcs nvd0_sor_hfunc = {
928 .dpms = nvd0_sor_dpms,
929 .mode_fixup = nvd0_sor_mode_fixup,
930 .prepare = nvd0_sor_prepare,
931 .commit = nvd0_sor_commit,
932 .mode_set = nvd0_sor_mode_set,
933 .disable = nvd0_sor_disconnect,
934 .get_crtc = nvd0_display_crtc_get,
935};
936
937static const struct drm_encoder_funcs nvd0_sor_func = {
938 .destroy = nvd0_sor_destroy,
939};
940
941static int
942nvd0_sor_create(struct drm_connector *connector, struct dcb_entry *dcbe)
943{
944 struct drm_device *dev = connector->dev;
945 struct nouveau_encoder *nv_encoder;
946 struct drm_encoder *encoder;
947
948 nv_encoder = kzalloc(sizeof(*nv_encoder), GFP_KERNEL);
949 if (!nv_encoder)
950 return -ENOMEM;
951 nv_encoder->dcb = dcbe;
952 nv_encoder->or = ffs(dcbe->or) - 1;
953 nv_encoder->last_dpms = DRM_MODE_DPMS_OFF;
954
955 encoder = to_drm_encoder(nv_encoder);
956 encoder->possible_crtcs = dcbe->heads;
957 encoder->possible_clones = 0;
958 drm_encoder_init(dev, encoder, &nvd0_sor_func, DRM_MODE_ENCODER_TMDS);
959 drm_encoder_helper_add(encoder, &nvd0_sor_hfunc);
960
961 drm_mode_connector_attach_encoder(connector, encoder);
962 return 0;
963}
Ben Skeggs26f6d882011-07-04 16:25:18 +1000964
965/******************************************************************************
966 * IRQ
967 *****************************************************************************/
Ben Skeggs3a89cd02011-07-07 10:47:10 +1000968static struct dcb_entry *
969lookup_dcb(struct drm_device *dev, int id, u32 mc)
970{
971 struct drm_nouveau_private *dev_priv = dev->dev_private;
972 int type, or, i;
973
974 if (id < 4) {
975 type = OUTPUT_ANALOG;
976 or = id;
977 } else {
Ben Skeggs3b6d83d12011-07-08 12:52:14 +1000978 switch (mc & 0x00000f00) {
979 case 0x00000000: type = OUTPUT_LVDS; break;
980 case 0x00000100: type = OUTPUT_TMDS; break;
981 case 0x00000200: type = OUTPUT_TMDS; break;
982 case 0x00000500: type = OUTPUT_TMDS; break;
983 default:
984 return NULL;
985 }
986
987 or = id - 4;
Ben Skeggs3a89cd02011-07-07 10:47:10 +1000988 }
989
990 for (i = 0; i < dev_priv->vbios.dcb.entries; i++) {
991 struct dcb_entry *dcb = &dev_priv->vbios.dcb.entry[i];
992 if (dcb->type == type && (dcb->or & (1 << or)))
993 return dcb;
994 }
995
996 NV_INFO(dev, "PDISP: DCB for %d/0x%08x not found\n", id, mc);
997 return NULL;
998}
999
Ben Skeggs46005222011-07-05 11:01:13 +10001000static void
Ben Skeggs270a5742011-07-05 14:16:05 +10001001nvd0_display_unk1_handler(struct drm_device *dev)
1002{
Ben Skeggs3a89cd02011-07-07 10:47:10 +10001003 struct nvd0_display *disp = nvd0_display(dev);
1004 struct dcb_entry *dcb;
1005 u32 unkn, crtc = 0;
1006 int i;
1007
Ben Skeggsa36f04c2011-07-06 14:39:23 +10001008 NV_INFO(dev, "PDISP: 1 0x%08x 0x%08x 0x%08x\n", nv_rd32(dev, 0x6101d0),
1009 nv_rd32(dev, 0x6101d4), nv_rd32(dev, 0x6109d4));
Ben Skeggs270a5742011-07-05 14:16:05 +10001010
Ben Skeggs3a89cd02011-07-07 10:47:10 +10001011 unkn = nv_rd32(dev, 0x6101d4);
1012 if (!unkn) {
1013 unkn = nv_rd32(dev, 0x6109d4);
1014 crtc = 1;
1015 }
1016
1017 disp->irq.ena = NULL;
1018 disp->irq.dis = NULL;
1019 disp->irq.crtc = crtc;
1020 disp->irq.pclk = nv_rd32(dev, 0x660450 + (disp->irq.crtc * 0x300));
1021 disp->irq.pclk /= 1000;
1022
1023 for (i = 0; i < 8; i++) {
1024 u32 mcc = nv_rd32(dev, 0x640180 + (i * 0x20));
1025 u32 mcp = nv_rd32(dev, 0x660180 + (i * 0x20));
1026
1027 if (mcc & (1 << crtc))
1028 disp->irq.dis = lookup_dcb(dev, i, mcc);
1029
1030 if (mcp & (1 << crtc)) {
Ben Skeggsff8ff502011-07-08 11:53:37 +10001031 disp->irq.cfg = nv_rd32(dev, 0x660184 + (i * 0x20));
Ben Skeggs3a89cd02011-07-07 10:47:10 +10001032 disp->irq.ena = lookup_dcb(dev, i, mcp);
Ben Skeggs3a89cd02011-07-07 10:47:10 +10001033 }
1034 }
1035
1036 dcb = disp->irq.dis;
1037 if (dcb)
1038 nouveau_bios_run_display_table(dev, 0x0000, -1, dcb, crtc);
1039
Ben Skeggs270a5742011-07-05 14:16:05 +10001040 nv_wr32(dev, 0x6101d4, 0x00000000);
1041 nv_wr32(dev, 0x6109d4, 0x00000000);
1042 nv_wr32(dev, 0x6101d0, 0x80000000);
1043}
1044
1045static void
1046nvd0_display_unk2_handler(struct drm_device *dev)
1047{
Ben Skeggs3a89cd02011-07-07 10:47:10 +10001048 struct nvd0_display *disp = nvd0_display(dev);
1049 struct dcb_entry *dcb;
1050 int crtc = disp->irq.crtc;
1051 int pclk = disp->irq.pclk;
1052 int or;
1053 u32 tmp;
1054
Ben Skeggsa36f04c2011-07-06 14:39:23 +10001055 NV_INFO(dev, "PDISP: 2 0x%08x 0x%08x 0x%08x\n", nv_rd32(dev, 0x6101d0),
1056 nv_rd32(dev, 0x6101d4), nv_rd32(dev, 0x6109d4));
Ben Skeggs270a5742011-07-05 14:16:05 +10001057
Ben Skeggs3a89cd02011-07-07 10:47:10 +10001058 dcb = disp->irq.dis;
1059 disp->irq.dis = NULL;
1060 if (dcb)
1061 nouveau_bios_run_display_table(dev, 0x0000, -2, dcb, crtc);
1062
1063 nv50_crtc_set_clock(dev, crtc, pclk);
1064
1065 dcb = disp->irq.ena;
1066 if (!dcb)
1067 goto ack;
1068 or = ffs(dcb->or) - 1;
1069
Ben Skeggsff8ff502011-07-08 11:53:37 +10001070 nouveau_bios_run_display_table(dev, disp->irq.cfg, pclk, dcb, crtc);
Ben Skeggs3a89cd02011-07-07 10:47:10 +10001071
1072 nv_wr32(dev, 0x612200 + (crtc * 0x800), 0x00000000);
1073 switch (dcb->type) {
1074 case OUTPUT_ANALOG:
1075 nv_wr32(dev, 0x612280 + (or * 0x800), 0x00000000);
1076 break;
1077 case OUTPUT_TMDS:
Ben Skeggs3b6d83d12011-07-08 12:52:14 +10001078 case OUTPUT_LVDS:
1079 if (disp->irq.cfg & 0x00000100)
Ben Skeggs3a89cd02011-07-07 10:47:10 +10001080 tmp = 0x00000101;
1081 else
1082 tmp = 0x00000000;
1083
1084 nv_mask(dev, 0x612300 + (or * 0x800), 0x00000707, tmp);
1085 break;
1086 default:
1087 break;
1088 }
1089
1090ack:
Ben Skeggs270a5742011-07-05 14:16:05 +10001091 nv_wr32(dev, 0x6101d4, 0x00000000);
1092 nv_wr32(dev, 0x6109d4, 0x00000000);
1093 nv_wr32(dev, 0x6101d0, 0x80000000);
1094}
1095
1096static void
1097nvd0_display_unk4_handler(struct drm_device *dev)
1098{
Ben Skeggs3a89cd02011-07-07 10:47:10 +10001099 struct nvd0_display *disp = nvd0_display(dev);
1100 struct dcb_entry *dcb;
1101 int crtc = disp->irq.crtc;
1102 int pclk = disp->irq.pclk;
1103
Ben Skeggsa36f04c2011-07-06 14:39:23 +10001104 NV_INFO(dev, "PDISP: 4 0x%08x 0x%08x 0x%08x\n", nv_rd32(dev, 0x6101d0),
1105 nv_rd32(dev, 0x6101d4), nv_rd32(dev, 0x6109d4));
Ben Skeggs270a5742011-07-05 14:16:05 +10001106
Ben Skeggs3a89cd02011-07-07 10:47:10 +10001107 dcb = disp->irq.ena;
1108 disp->irq.ena = NULL;
1109 if (!dcb)
1110 goto ack;
1111
Ben Skeggsff8ff502011-07-08 11:53:37 +10001112 nouveau_bios_run_display_table(dev, disp->irq.cfg, pclk, dcb, crtc);
Ben Skeggs3a89cd02011-07-07 10:47:10 +10001113
1114ack:
Ben Skeggs270a5742011-07-05 14:16:05 +10001115 nv_wr32(dev, 0x6101d4, 0x00000000);
1116 nv_wr32(dev, 0x6109d4, 0x00000000);
1117 nv_wr32(dev, 0x6101d0, 0x80000000);
1118}
1119
1120static void
Ben Skeggsf20ce962011-07-08 13:17:01 +10001121nvd0_display_bh(unsigned long data)
1122{
1123 struct drm_device *dev = (struct drm_device *)data;
1124 struct nvd0_display *disp = nvd0_display(dev);
1125
1126 if (disp->irq.modeset & 0x00000001)
1127 nvd0_display_unk1_handler(dev);
1128 if (disp->irq.modeset & 0x00000002)
1129 nvd0_display_unk2_handler(dev);
1130 if (disp->irq.modeset & 0x00000004)
1131 nvd0_display_unk4_handler(dev);
1132}
1133
1134static void
Ben Skeggs46005222011-07-05 11:01:13 +10001135nvd0_display_intr(struct drm_device *dev)
1136{
Ben Skeggsf20ce962011-07-08 13:17:01 +10001137 struct nvd0_display *disp = nvd0_display(dev);
Ben Skeggs46005222011-07-05 11:01:13 +10001138 u32 intr = nv_rd32(dev, 0x610088);
1139
1140 if (intr & 0x00000002) {
1141 u32 stat = nv_rd32(dev, 0x61009c);
1142 int chid = ffs(stat) - 1;
1143 if (chid >= 0) {
1144 u32 mthd = nv_rd32(dev, 0x6101f0 + (chid * 12));
1145 u32 data = nv_rd32(dev, 0x6101f4 + (chid * 12));
1146 u32 unkn = nv_rd32(dev, 0x6101f8 + (chid * 12));
1147
1148 NV_INFO(dev, "EvoCh: chid %d mthd 0x%04x data 0x%08x "
1149 "0x%08x 0x%08x\n",
1150 chid, (mthd & 0x0000ffc), data, mthd, unkn);
1151 nv_wr32(dev, 0x61009c, (1 << chid));
1152 nv_wr32(dev, 0x6101f0 + (chid * 12), 0x90000000);
1153 }
1154
1155 intr &= ~0x00000002;
1156 }
1157
Ben Skeggs270a5742011-07-05 14:16:05 +10001158 if (intr & 0x00100000) {
1159 u32 stat = nv_rd32(dev, 0x6100ac);
1160
1161 if (stat & 0x00000007) {
Ben Skeggsf20ce962011-07-08 13:17:01 +10001162 disp->irq.modeset = stat;
1163 tasklet_schedule(&disp->tasklet);
Ben Skeggs270a5742011-07-05 14:16:05 +10001164
Ben Skeggsf20ce962011-07-08 13:17:01 +10001165 nv_wr32(dev, 0x6100ac, (stat & 0x00000007));
Ben Skeggs270a5742011-07-05 14:16:05 +10001166 stat &= ~0x00000007;
1167 }
1168
1169 if (stat) {
1170 NV_INFO(dev, "PDISP: unknown intr24 0x%08x\n", stat);
1171 nv_wr32(dev, 0x6100ac, stat);
1172 }
1173
1174 intr &= ~0x00100000;
1175 }
1176
Ben Skeggs46005222011-07-05 11:01:13 +10001177 if (intr & 0x01000000) {
1178 u32 stat = nv_rd32(dev, 0x6100bc);
1179 nv_wr32(dev, 0x6100bc, stat);
1180 intr &= ~0x01000000;
1181 }
1182
1183 if (intr & 0x02000000) {
1184 u32 stat = nv_rd32(dev, 0x6108bc);
1185 nv_wr32(dev, 0x6108bc, stat);
1186 intr &= ~0x02000000;
1187 }
1188
1189 if (intr)
1190 NV_INFO(dev, "PDISP: unknown intr 0x%08x\n", intr);
1191}
Ben Skeggs26f6d882011-07-04 16:25:18 +10001192
1193/******************************************************************************
1194 * Init
1195 *****************************************************************************/
1196static void
1197nvd0_display_fini(struct drm_device *dev)
1198{
1199 int i;
1200
1201 /* fini cursors */
1202 for (i = 14; i >= 13; i--) {
1203 if (!(nv_rd32(dev, 0x610490 + (i * 0x10)) & 0x00000001))
1204 continue;
1205
1206 nv_mask(dev, 0x610490 + (i * 0x10), 0x00000001, 0x00000000);
1207 nv_wait(dev, 0x610490 + (i * 0x10), 0x00010000, 0x00000000);
1208 nv_mask(dev, 0x610090, 1 << i, 0x00000000);
1209 nv_mask(dev, 0x6100a0, 1 << i, 0x00000000);
1210 }
1211
1212 /* fini master */
1213 if (nv_rd32(dev, 0x610490) & 0x00000010) {
1214 nv_mask(dev, 0x610490, 0x00000010, 0x00000000);
1215 nv_mask(dev, 0x610490, 0x00000003, 0x00000000);
1216 nv_wait(dev, 0x610490, 0x80000000, 0x00000000);
1217 nv_mask(dev, 0x610090, 0x00000001, 0x00000000);
1218 nv_mask(dev, 0x6100a0, 0x00000001, 0x00000000);
1219 }
1220}
1221
1222int
1223nvd0_display_init(struct drm_device *dev)
1224{
1225 struct nvd0_display *disp = nvd0_display(dev);
Ben Skeggsefd272a2011-07-05 11:58:58 +10001226 u32 *push;
Ben Skeggs26f6d882011-07-04 16:25:18 +10001227 int i;
1228
1229 if (nv_rd32(dev, 0x6100ac) & 0x00000100) {
1230 nv_wr32(dev, 0x6100ac, 0x00000100);
1231 nv_mask(dev, 0x6194e8, 0x00000001, 0x00000000);
1232 if (!nv_wait(dev, 0x6194e8, 0x00000002, 0x00000000)) {
1233 NV_ERROR(dev, "PDISP: 0x6194e8 0x%08x\n",
1234 nv_rd32(dev, 0x6194e8));
1235 return -EBUSY;
1236 }
1237 }
1238
Ben Skeggsa36f04c2011-07-06 14:39:23 +10001239 /* nfi what these are exactly, i do know that SOR_MODE_CTRL won't
1240 * work at all unless you do the SOR part below.
1241 */
1242 for (i = 0; i < 3; i++) {
1243 u32 dac = nv_rd32(dev, 0x61a000 + (i * 0x800));
1244 nv_wr32(dev, 0x6101c0 + (i * 0x800), dac);
1245 }
1246
1247 for (i = 0; i < 4; i++) {
1248 u32 sor = nv_rd32(dev, 0x61c000 + (i * 0x800));
1249 nv_wr32(dev, 0x6301c4 + (i * 0x800), sor);
1250 }
1251
1252 for (i = 0; i < 2; i++) {
1253 u32 crtc0 = nv_rd32(dev, 0x616104 + (i * 0x800));
1254 u32 crtc1 = nv_rd32(dev, 0x616108 + (i * 0x800));
1255 u32 crtc2 = nv_rd32(dev, 0x61610c + (i * 0x800));
1256 nv_wr32(dev, 0x6101b4 + (i * 0x800), crtc0);
1257 nv_wr32(dev, 0x6101b8 + (i * 0x800), crtc1);
1258 nv_wr32(dev, 0x6101bc + (i * 0x800), crtc2);
1259 }
1260
1261 /* point at our hash table / objects, enable interrupts */
Ben Skeggs26f6d882011-07-04 16:25:18 +10001262 nv_wr32(dev, 0x610010, (disp->mem->vinst >> 8) | 9);
Ben Skeggs270a5742011-07-05 14:16:05 +10001263 nv_mask(dev, 0x6100b0, 0x00000307, 0x00000307);
Ben Skeggs26f6d882011-07-04 16:25:18 +10001264
1265 /* init master */
Ben Skeggs51beb422011-07-05 10:33:08 +10001266 nv_wr32(dev, 0x610494, (disp->evo[0].handle >> 8) | 3);
Ben Skeggs26f6d882011-07-04 16:25:18 +10001267 nv_wr32(dev, 0x610498, 0x00010000);
Ben Skeggsefd272a2011-07-05 11:58:58 +10001268 nv_wr32(dev, 0x61049c, 0x00000001);
Ben Skeggs26f6d882011-07-04 16:25:18 +10001269 nv_mask(dev, 0x610490, 0x00000010, 0x00000010);
1270 nv_wr32(dev, 0x640000, 0x00000000);
1271 nv_wr32(dev, 0x610490, 0x01000013);
1272 if (!nv_wait(dev, 0x610490, 0x80000000, 0x00000000)) {
1273 NV_ERROR(dev, "PDISP: master 0x%08x\n",
1274 nv_rd32(dev, 0x610490));
1275 return -EBUSY;
1276 }
1277 nv_mask(dev, 0x610090, 0x00000001, 0x00000001);
1278 nv_mask(dev, 0x6100a0, 0x00000001, 0x00000001);
1279
1280 /* init cursors */
1281 for (i = 13; i <= 14; i++) {
1282 nv_wr32(dev, 0x610490 + (i * 0x10), 0x00000001);
1283 if (!nv_wait(dev, 0x610490 + (i * 0x10), 0x00010000, 0x00010000)) {
1284 NV_ERROR(dev, "PDISP: curs%d 0x%08x\n", i,
1285 nv_rd32(dev, 0x610490 + (i * 0x10)));
1286 return -EBUSY;
1287 }
1288
1289 nv_mask(dev, 0x610090, 1 << i, 1 << i);
1290 nv_mask(dev, 0x6100a0, 1 << i, 1 << i);
1291 }
1292
Ben Skeggsefd272a2011-07-05 11:58:58 +10001293 push = evo_wait(dev, 0, 32);
1294 if (!push)
1295 return -EBUSY;
1296 evo_mthd(push, 0x0088, 1);
1297 evo_data(push, MEM_SYNC);
1298 evo_mthd(push, 0x0084, 1);
1299 evo_data(push, 0x00000000);
1300 evo_mthd(push, 0x0084, 1);
1301 evo_data(push, 0x80000000);
1302 evo_mthd(push, 0x008c, 1);
1303 evo_data(push, 0x00000000);
1304 evo_kick(push, dev, 0);
1305
Ben Skeggs26f6d882011-07-04 16:25:18 +10001306 return 0;
1307}
1308
1309void
1310nvd0_display_destroy(struct drm_device *dev)
1311{
1312 struct drm_nouveau_private *dev_priv = dev->dev_private;
1313 struct nvd0_display *disp = nvd0_display(dev);
Ben Skeggs51beb422011-07-05 10:33:08 +10001314 struct pci_dev *pdev = dev->pdev;
Ben Skeggs26f6d882011-07-04 16:25:18 +10001315
1316 nvd0_display_fini(dev);
1317
Ben Skeggs51beb422011-07-05 10:33:08 +10001318 pci_free_consistent(pdev, PAGE_SIZE, disp->evo[0].ptr, disp->evo[0].handle);
Ben Skeggs26f6d882011-07-04 16:25:18 +10001319 nouveau_gpuobj_ref(NULL, &disp->mem);
Ben Skeggs46005222011-07-05 11:01:13 +10001320 nouveau_irq_unregister(dev, 26);
Ben Skeggs51beb422011-07-05 10:33:08 +10001321
1322 dev_priv->engine.display.priv = NULL;
Ben Skeggs26f6d882011-07-04 16:25:18 +10001323 kfree(disp);
1324}
1325
1326int
1327nvd0_display_create(struct drm_device *dev)
1328{
1329 struct drm_nouveau_private *dev_priv = dev->dev_private;
Ben Skeggsefd272a2011-07-05 11:58:58 +10001330 struct nouveau_instmem_engine *pinstmem = &dev_priv->engine.instmem;
Ben Skeggs83fc0832011-07-05 13:08:40 +10001331 struct dcb_table *dcb = &dev_priv->vbios.dcb;
1332 struct drm_connector *connector, *tmp;
Ben Skeggs51beb422011-07-05 10:33:08 +10001333 struct pci_dev *pdev = dev->pdev;
Ben Skeggs26f6d882011-07-04 16:25:18 +10001334 struct nvd0_display *disp;
Ben Skeggs83fc0832011-07-05 13:08:40 +10001335 struct dcb_entry *dcbe;
1336 int ret, i;
Ben Skeggs26f6d882011-07-04 16:25:18 +10001337
1338 disp = kzalloc(sizeof(*disp), GFP_KERNEL);
1339 if (!disp)
1340 return -ENOMEM;
1341 dev_priv->engine.display.priv = disp;
1342
Ben Skeggs438d99e2011-07-05 16:48:06 +10001343 /* create crtc objects to represent the hw heads */
1344 for (i = 0; i < 2; i++) {
1345 ret = nvd0_crtc_create(dev, i);
1346 if (ret)
1347 goto out;
1348 }
1349
Ben Skeggs83fc0832011-07-05 13:08:40 +10001350 /* create encoder/connector objects based on VBIOS DCB table */
1351 for (i = 0, dcbe = &dcb->entry[0]; i < dcb->entries; i++, dcbe++) {
1352 connector = nouveau_connector_create(dev, dcbe->connector);
1353 if (IS_ERR(connector))
1354 continue;
1355
1356 if (dcbe->location != DCB_LOC_ON_CHIP) {
1357 NV_WARN(dev, "skipping off-chip encoder %d/%d\n",
1358 dcbe->type, ffs(dcbe->or) - 1);
1359 continue;
1360 }
1361
1362 switch (dcbe->type) {
1363 case OUTPUT_TMDS:
Ben Skeggs3b6d83d12011-07-08 12:52:14 +10001364 case OUTPUT_LVDS:
Ben Skeggs83fc0832011-07-05 13:08:40 +10001365 nvd0_sor_create(connector, dcbe);
1366 break;
Ben Skeggs8eaa9662011-07-06 15:25:47 +10001367 case OUTPUT_ANALOG:
1368 nvd0_dac_create(connector, dcbe);
1369 break;
Ben Skeggs83fc0832011-07-05 13:08:40 +10001370 default:
1371 NV_WARN(dev, "skipping unsupported encoder %d/%d\n",
1372 dcbe->type, ffs(dcbe->or) - 1);
1373 continue;
1374 }
1375 }
1376
1377 /* cull any connectors we created that don't have an encoder */
1378 list_for_each_entry_safe(connector, tmp, &dev->mode_config.connector_list, head) {
1379 if (connector->encoder_ids[0])
1380 continue;
1381
1382 NV_WARN(dev, "%s has no encoders, removing\n",
1383 drm_get_connector_name(connector));
1384 connector->funcs->destroy(connector);
1385 }
1386
Ben Skeggs46005222011-07-05 11:01:13 +10001387 /* setup interrupt handling */
Ben Skeggsf20ce962011-07-08 13:17:01 +10001388 tasklet_init(&disp->tasklet, nvd0_display_bh, (unsigned long)dev);
Ben Skeggs46005222011-07-05 11:01:13 +10001389 nouveau_irq_register(dev, 26, nvd0_display_intr);
1390
Ben Skeggs51beb422011-07-05 10:33:08 +10001391 /* hash table and dma objects for the memory areas we care about */
Ben Skeggsefd272a2011-07-05 11:58:58 +10001392 ret = nouveau_gpuobj_new(dev, NULL, 0x4000, 0x10000,
1393 NVOBJ_FLAG_ZERO_ALLOC, &disp->mem);
Ben Skeggs26f6d882011-07-04 16:25:18 +10001394 if (ret)
1395 goto out;
1396
Ben Skeggsefd272a2011-07-05 11:58:58 +10001397 nv_wo32(disp->mem, 0x1000, 0x00000049);
1398 nv_wo32(disp->mem, 0x1004, (disp->mem->vinst + 0x2000) >> 8);
1399 nv_wo32(disp->mem, 0x1008, (disp->mem->vinst + 0x2fff) >> 8);
1400 nv_wo32(disp->mem, 0x100c, 0x00000000);
1401 nv_wo32(disp->mem, 0x1010, 0x00000000);
1402 nv_wo32(disp->mem, 0x1014, 0x00000000);
1403 nv_wo32(disp->mem, 0x0000, MEM_SYNC);
1404 nv_wo32(disp->mem, 0x0004, (0x1000 << 9) | 0x00000001);
1405
Ben Skeggsc0cc92a2011-07-06 11:40:45 +10001406 nv_wo32(disp->mem, 0x1020, 0x00000049);
Ben Skeggsefd272a2011-07-05 11:58:58 +10001407 nv_wo32(disp->mem, 0x1024, 0x00000000);
1408 nv_wo32(disp->mem, 0x1028, (dev_priv->vram_size - 1) >> 8);
1409 nv_wo32(disp->mem, 0x102c, 0x00000000);
1410 nv_wo32(disp->mem, 0x1030, 0x00000000);
1411 nv_wo32(disp->mem, 0x1034, 0x00000000);
1412 nv_wo32(disp->mem, 0x0008, MEM_VRAM);
1413 nv_wo32(disp->mem, 0x000c, (0x1020 << 9) | 0x00000001);
1414
Ben Skeggsc0cc92a2011-07-06 11:40:45 +10001415 nv_wo32(disp->mem, 0x1040, 0x00000009);
1416 nv_wo32(disp->mem, 0x1044, 0x00000000);
1417 nv_wo32(disp->mem, 0x1048, (dev_priv->vram_size - 1) >> 8);
1418 nv_wo32(disp->mem, 0x104c, 0x00000000);
1419 nv_wo32(disp->mem, 0x1050, 0x00000000);
1420 nv_wo32(disp->mem, 0x1054, 0x00000000);
1421 nv_wo32(disp->mem, 0x0010, NvEvoVRAM_LP);
1422 nv_wo32(disp->mem, 0x0014, (0x1040 << 9) | 0x00000001);
1423
1424 nv_wo32(disp->mem, 0x1060, 0x0fe00009);
1425 nv_wo32(disp->mem, 0x1064, 0x00000000);
1426 nv_wo32(disp->mem, 0x1068, (dev_priv->vram_size - 1) >> 8);
1427 nv_wo32(disp->mem, 0x106c, 0x00000000);
1428 nv_wo32(disp->mem, 0x1070, 0x00000000);
1429 nv_wo32(disp->mem, 0x1074, 0x00000000);
1430 nv_wo32(disp->mem, 0x0018, NvEvoFB32);
1431 nv_wo32(disp->mem, 0x001c, (0x1060 << 9) | 0x00000001);
1432
Ben Skeggsefd272a2011-07-05 11:58:58 +10001433 pinstmem->flush(dev);
1434
Ben Skeggs51beb422011-07-05 10:33:08 +10001435 /* push buffers for evo channels */
1436 disp->evo[0].ptr =
1437 pci_alloc_consistent(pdev, PAGE_SIZE, &disp->evo[0].handle);
1438 if (!disp->evo[0].ptr) {
1439 ret = -ENOMEM;
1440 goto out;
1441 }
1442
Ben Skeggs26f6d882011-07-04 16:25:18 +10001443 ret = nvd0_display_init(dev);
1444 if (ret)
1445 goto out;
1446
1447out:
1448 if (ret)
1449 nvd0_display_destroy(dev);
1450 return ret;
1451}