blob: 5d01f1b64e267ab8e2d51acdd6cbfaa34c14c929 [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 Skeggs37b034a2011-07-08 14:43:19 +100034#include "nouveau_dma.h"
Ben Skeggs438d99e2011-07-05 16:48:06 +100035#include "nouveau_fb.h"
Ben Skeggs3a89cd02011-07-07 10:47:10 +100036#include "nv50_display.h"
Ben Skeggs26f6d882011-07-04 16:25:18 +100037
38struct nvd0_display {
39 struct nouveau_gpuobj *mem;
Ben Skeggs51beb422011-07-05 10:33:08 +100040 struct {
41 dma_addr_t handle;
42 u32 *ptr;
43 } evo[1];
Ben Skeggsf20ce962011-07-08 13:17:01 +100044
45 struct tasklet_struct tasklet;
Ben Skeggsee417792011-07-08 14:34:45 +100046 u32 modeset;
Ben Skeggs26f6d882011-07-04 16:25:18 +100047};
48
49static struct nvd0_display *
50nvd0_display(struct drm_device *dev)
51{
52 struct drm_nouveau_private *dev_priv = dev->dev_private;
53 return dev_priv->engine.display.priv;
54}
55
Ben Skeggs37b034a2011-07-08 14:43:19 +100056static inline int
Ben Skeggs51beb422011-07-05 10:33:08 +100057evo_icmd(struct drm_device *dev, int id, u32 mthd, u32 data)
58{
59 int ret = 0;
60 nv_mask(dev, 0x610700 + (id * 0x10), 0x00000001, 0x00000001);
61 nv_wr32(dev, 0x610704 + (id * 0x10), data);
62 nv_mask(dev, 0x610704 + (id * 0x10), 0x80000ffc, 0x80000000 | mthd);
63 if (!nv_wait(dev, 0x610704 + (id * 0x10), 0x80000000, 0x00000000))
64 ret = -EBUSY;
65 nv_mask(dev, 0x610700 + (id * 0x10), 0x00000001, 0x00000000);
66 return ret;
67}
68
69static u32 *
70evo_wait(struct drm_device *dev, int id, int nr)
71{
72 struct nvd0_display *disp = nvd0_display(dev);
73 u32 put = nv_rd32(dev, 0x640000 + (id * 0x1000)) / 4;
74
75 if (put + nr >= (PAGE_SIZE / 4)) {
76 disp->evo[id].ptr[put] = 0x20000000;
77
78 nv_wr32(dev, 0x640000 + (id * 0x1000), 0x00000000);
79 if (!nv_wait(dev, 0x640004 + (id * 0x1000), ~0, 0x00000000)) {
80 NV_ERROR(dev, "evo %d dma stalled\n", id);
81 return NULL;
82 }
83
84 put = 0;
85 }
86
Ben Skeggs27517dd2011-11-11 20:26:44 +100087 if (nouveau_reg_debug & NOUVEAU_REG_DEBUG_EVO)
88 NV_INFO(dev, "Evo%d: %p START\n", id, disp->evo[id].ptr + put);
89
Ben Skeggs51beb422011-07-05 10:33:08 +100090 return disp->evo[id].ptr + put;
91}
92
93static void
94evo_kick(u32 *push, struct drm_device *dev, int id)
95{
96 struct nvd0_display *disp = nvd0_display(dev);
Ben Skeggs27517dd2011-11-11 20:26:44 +100097
98 if (nouveau_reg_debug & NOUVEAU_REG_DEBUG_EVO) {
99 u32 curp = nv_rd32(dev, 0x640000 + (id * 0x1000)) >> 2;
100 u32 *cur = disp->evo[id].ptr + curp;
101
102 while (cur < push)
103 NV_INFO(dev, "Evo%d: 0x%08x\n", id, *cur++);
104 NV_INFO(dev, "Evo%d: %p KICK!\n", id, push);
105 }
106
Ben Skeggs51beb422011-07-05 10:33:08 +1000107 nv_wr32(dev, 0x640000 + (id * 0x1000), (push - disp->evo[id].ptr) << 2);
108}
109
110#define evo_mthd(p,m,s) *((p)++) = (((s) << 18) | (m))
111#define evo_data(p,d) *((p)++) = (d)
112
Ben Skeggs83fc0832011-07-05 13:08:40 +1000113static struct drm_crtc *
114nvd0_display_crtc_get(struct drm_encoder *encoder)
115{
116 return nouveau_encoder(encoder)->crtc;
117}
118
Ben Skeggs26f6d882011-07-04 16:25:18 +1000119/******************************************************************************
Ben Skeggs438d99e2011-07-05 16:48:06 +1000120 * CRTC
121 *****************************************************************************/
122static int
Ben Skeggs488ff202011-10-17 10:38:10 +1000123nvd0_crtc_set_dither(struct nouveau_crtc *nv_crtc, bool update)
Ben Skeggs438d99e2011-07-05 16:48:06 +1000124{
125 struct drm_device *dev = nv_crtc->base.dev;
Ben Skeggsde691852011-10-17 12:23:41 +1000126 struct nouveau_connector *nv_connector;
127 struct drm_connector *connector;
128 u32 *push, mode = 0x00;
Ben Skeggs438d99e2011-07-05 16:48:06 +1000129
Ben Skeggs488ff202011-10-17 10:38:10 +1000130 nv_connector = nouveau_crtc_connector_get(nv_crtc);
Ben Skeggsde691852011-10-17 12:23:41 +1000131 connector = &nv_connector->base;
132 if (nv_connector->dithering_mode == DITHERING_MODE_AUTO) {
133 if (nv_crtc->base.fb->depth > connector->display_info.bpc * 3)
134 mode = DITHERING_MODE_DYNAMIC2X2;
135 } else {
136 mode = nv_connector->dithering_mode;
137 }
138
139 if (nv_connector->dithering_depth == DITHERING_DEPTH_AUTO) {
140 if (connector->display_info.bpc >= 8)
141 mode |= DITHERING_DEPTH_8BPC;
142 } else {
143 mode |= nv_connector->dithering_depth;
Ben Skeggs438d99e2011-07-05 16:48:06 +1000144 }
145
146 push = evo_wait(dev, 0, 4);
147 if (push) {
148 evo_mthd(push, 0x0490 + (nv_crtc->index * 0x300), 1);
149 evo_data(push, mode);
150 if (update) {
151 evo_mthd(push, 0x0080, 1);
152 evo_data(push, 0x00000000);
153 }
154 evo_kick(push, dev, 0);
155 }
156
157 return 0;
158}
159
160static int
Ben Skeggs488ff202011-10-17 10:38:10 +1000161nvd0_crtc_set_scale(struct nouveau_crtc *nv_crtc, bool update)
Ben Skeggs438d99e2011-07-05 16:48:06 +1000162{
163 struct drm_display_mode *mode = &nv_crtc->base.mode;
164 struct drm_device *dev = nv_crtc->base.dev;
Ben Skeggsf3fdc522011-07-07 16:01:57 +1000165 struct nouveau_connector *nv_connector;
166 u32 *push, outX, outY;
Ben Skeggs438d99e2011-07-05 16:48:06 +1000167
Ben Skeggsf3fdc522011-07-07 16:01:57 +1000168 outX = mode->hdisplay;
169 outY = mode->vdisplay;
170
171 nv_connector = nouveau_crtc_connector_get(nv_crtc);
172 if (nv_connector && nv_connector->native_mode) {
173 struct drm_display_mode *native = nv_connector->native_mode;
174 u32 xratio = (native->hdisplay << 19) / mode->hdisplay;
175 u32 yratio = (native->vdisplay << 19) / mode->vdisplay;
176
Ben Skeggs488ff202011-10-17 10:38:10 +1000177 switch (nv_connector->scaling_mode) {
Ben Skeggsf3fdc522011-07-07 16:01:57 +1000178 case DRM_MODE_SCALE_ASPECT:
179 if (xratio > yratio) {
180 outX = (mode->hdisplay * yratio) >> 19;
181 outY = (mode->vdisplay * yratio) >> 19;
182 } else {
183 outX = (mode->hdisplay * xratio) >> 19;
184 outY = (mode->vdisplay * xratio) >> 19;
185 }
186 break;
187 case DRM_MODE_SCALE_FULLSCREEN:
188 outX = native->hdisplay;
189 outY = native->vdisplay;
190 break;
191 default:
192 break;
193 }
194 }
Ben Skeggs438d99e2011-07-05 16:48:06 +1000195
196 push = evo_wait(dev, 0, 16);
197 if (push) {
198 evo_mthd(push, 0x04c0 + (nv_crtc->index * 0x300), 3);
Ben Skeggsf3fdc522011-07-07 16:01:57 +1000199 evo_data(push, (outY << 16) | outX);
200 evo_data(push, (outY << 16) | outX);
201 evo_data(push, (outY << 16) | outX);
Ben Skeggs438d99e2011-07-05 16:48:06 +1000202 evo_mthd(push, 0x0494 + (nv_crtc->index * 0x300), 1);
203 evo_data(push, 0x00000000);
Ben Skeggs438d99e2011-07-05 16:48:06 +1000204 evo_mthd(push, 0x04b8 + (nv_crtc->index * 0x300), 1);
205 evo_data(push, (mode->vdisplay << 16) | mode->hdisplay);
206 if (update) {
207 evo_mthd(push, 0x0080, 1);
208 evo_data(push, 0x00000000);
209 }
210 evo_kick(push, dev, 0);
211 }
212
213 return 0;
214}
215
216static int
217nvd0_crtc_set_image(struct nouveau_crtc *nv_crtc, struct drm_framebuffer *fb,
218 int x, int y, bool update)
219{
220 struct nouveau_framebuffer *nvfb = nouveau_framebuffer(fb);
221 u32 *push;
222
Ben Skeggs438d99e2011-07-05 16:48:06 +1000223 push = evo_wait(fb->dev, 0, 16);
224 if (push) {
225 evo_mthd(push, 0x0460 + (nv_crtc->index * 0x300), 1);
226 evo_data(push, nvfb->nvbo->bo.offset >> 8);
227 evo_mthd(push, 0x0468 + (nv_crtc->index * 0x300), 4);
228 evo_data(push, (fb->height << 16) | fb->width);
229 evo_data(push, nvfb->r_pitch);
230 evo_data(push, nvfb->r_format);
Ben Skeggsc0cc92a2011-07-06 11:40:45 +1000231 evo_data(push, nvfb->r_dma);
Ben Skeggsc6f2f712011-07-08 12:11:58 +1000232 evo_mthd(push, 0x04b0 + (nv_crtc->index * 0x300), 1);
233 evo_data(push, (y << 16) | x);
Ben Skeggsa46232e2011-07-07 15:23:48 +1000234 if (update) {
235 evo_mthd(push, 0x0080, 1);
236 evo_data(push, 0x00000000);
237 }
Ben Skeggs438d99e2011-07-05 16:48:06 +1000238 evo_kick(push, fb->dev, 0);
239 }
240
Ben Skeggsc0cc92a2011-07-06 11:40:45 +1000241 nv_crtc->fb.tile_flags = nvfb->r_dma;
Ben Skeggs438d99e2011-07-05 16:48:06 +1000242 return 0;
243}
244
245static void
246nvd0_crtc_cursor_show(struct nouveau_crtc *nv_crtc, bool show, bool update)
247{
248 struct drm_device *dev = nv_crtc->base.dev;
249 u32 *push = evo_wait(dev, 0, 16);
250 if (push) {
251 if (show) {
252 evo_mthd(push, 0x0480 + (nv_crtc->index * 0x300), 2);
253 evo_data(push, 0x85000000);
254 evo_data(push, nv_crtc->cursor.nvbo->bo.offset >> 8);
255 evo_mthd(push, 0x048c + (nv_crtc->index * 0x300), 1);
Ben Skeggs37b034a2011-07-08 14:43:19 +1000256 evo_data(push, NvEvoVRAM);
Ben Skeggs438d99e2011-07-05 16:48:06 +1000257 } else {
258 evo_mthd(push, 0x0480 + (nv_crtc->index * 0x300), 1);
259 evo_data(push, 0x05000000);
260 evo_mthd(push, 0x048c + (nv_crtc->index * 0x300), 1);
261 evo_data(push, 0x00000000);
262 }
263
264 if (update) {
265 evo_mthd(push, 0x0080, 1);
266 evo_data(push, 0x00000000);
267 }
268
269 evo_kick(push, dev, 0);
270 }
271}
272
273static void
274nvd0_crtc_dpms(struct drm_crtc *crtc, int mode)
275{
276}
277
278static void
279nvd0_crtc_prepare(struct drm_crtc *crtc)
280{
281 struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
282 u32 *push;
283
284 push = evo_wait(crtc->dev, 0, 2);
285 if (push) {
286 evo_mthd(push, 0x0474 + (nv_crtc->index * 0x300), 1);
287 evo_data(push, 0x00000000);
288 evo_mthd(push, 0x0440 + (nv_crtc->index * 0x300), 1);
289 evo_data(push, 0x03000000);
290 evo_mthd(push, 0x045c + (nv_crtc->index * 0x300), 1);
291 evo_data(push, 0x00000000);
292 evo_kick(push, crtc->dev, 0);
293 }
294
295 nvd0_crtc_cursor_show(nv_crtc, false, false);
296}
297
298static void
299nvd0_crtc_commit(struct drm_crtc *crtc)
300{
301 struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
302 u32 *push;
303
304 push = evo_wait(crtc->dev, 0, 32);
305 if (push) {
306 evo_mthd(push, 0x0474 + (nv_crtc->index * 0x300), 1);
307 evo_data(push, nv_crtc->fb.tile_flags);
308 evo_mthd(push, 0x0440 + (nv_crtc->index * 0x300), 4);
309 evo_data(push, 0x83000000);
310 evo_data(push, nv_crtc->lut.nvbo->bo.offset >> 8);
311 evo_data(push, 0x00000000);
312 evo_data(push, 0x00000000);
313 evo_mthd(push, 0x045c + (nv_crtc->index * 0x300), 1);
Ben Skeggs37b034a2011-07-08 14:43:19 +1000314 evo_data(push, NvEvoVRAM);
Ben Skeggs8ea0d4a2011-07-07 14:49:24 +1000315 evo_mthd(push, 0x0430 + (nv_crtc->index * 0x300), 1);
316 evo_data(push, 0xffffff00);
Ben Skeggs438d99e2011-07-05 16:48:06 +1000317 evo_kick(push, crtc->dev, 0);
318 }
319
320 nvd0_crtc_cursor_show(nv_crtc, nv_crtc->cursor.visible, true);
321}
322
323static bool
324nvd0_crtc_mode_fixup(struct drm_crtc *crtc, struct drm_display_mode *mode,
325 struct drm_display_mode *adjusted_mode)
326{
327 return true;
328}
329
330static int
331nvd0_crtc_swap_fbs(struct drm_crtc *crtc, struct drm_framebuffer *old_fb)
332{
333 struct nouveau_framebuffer *nvfb = nouveau_framebuffer(crtc->fb);
334 int ret;
335
336 ret = nouveau_bo_pin(nvfb->nvbo, TTM_PL_FLAG_VRAM);
337 if (ret)
338 return ret;
339
340 if (old_fb) {
341 nvfb = nouveau_framebuffer(old_fb);
342 nouveau_bo_unpin(nvfb->nvbo);
343 }
344
345 return 0;
346}
347
348static int
349nvd0_crtc_mode_set(struct drm_crtc *crtc, struct drm_display_mode *umode,
350 struct drm_display_mode *mode, int x, int y,
351 struct drm_framebuffer *old_fb)
352{
353 struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
354 struct nouveau_connector *nv_connector;
355 u32 htotal = mode->htotal;
356 u32 vtotal = mode->vtotal;
357 u32 hsyncw = mode->hsync_end - mode->hsync_start - 1;
358 u32 vsyncw = mode->vsync_end - mode->vsync_start - 1;
359 u32 hfrntp = mode->hsync_start - mode->hdisplay;
360 u32 vfrntp = mode->vsync_start - mode->vdisplay;
361 u32 hbackp = mode->htotal - mode->hsync_end;
362 u32 vbackp = mode->vtotal - mode->vsync_end;
363 u32 hss2be = hsyncw + hbackp;
364 u32 vss2be = vsyncw + vbackp;
365 u32 hss2de = htotal - hfrntp;
366 u32 vss2de = vtotal - vfrntp;
Ben Skeggs629c1b92011-07-08 09:43:20 +1000367 u32 syncs, *push;
Ben Skeggs438d99e2011-07-05 16:48:06 +1000368 int ret;
369
Ben Skeggs629c1b92011-07-08 09:43:20 +1000370 syncs = 0x00000001;
371 if (mode->flags & DRM_MODE_FLAG_NHSYNC)
372 syncs |= 0x00000008;
373 if (mode->flags & DRM_MODE_FLAG_NVSYNC)
374 syncs |= 0x00000010;
375
Ben Skeggs438d99e2011-07-05 16:48:06 +1000376 ret = nvd0_crtc_swap_fbs(crtc, old_fb);
377 if (ret)
378 return ret;
379
380 push = evo_wait(crtc->dev, 0, 64);
381 if (push) {
382 evo_mthd(push, 0x0410 + (nv_crtc->index * 0x300), 5);
Ben Skeggs629c1b92011-07-08 09:43:20 +1000383 evo_data(push, 0x00000000);
Ben Skeggs438d99e2011-07-05 16:48:06 +1000384 evo_data(push, (vtotal << 16) | htotal);
385 evo_data(push, (vsyncw << 16) | hsyncw);
386 evo_data(push, (vss2be << 16) | hss2be);
387 evo_data(push, (vss2de << 16) | hss2de);
388 evo_mthd(push, 0x042c + (nv_crtc->index * 0x300), 1);
389 evo_data(push, 0x00000000); /* ??? */
390 evo_mthd(push, 0x0450 + (nv_crtc->index * 0x300), 3);
391 evo_data(push, mode->clock * 1000);
392 evo_data(push, 0x00200000); /* ??? */
393 evo_data(push, mode->clock * 1000);
Ben Skeggs629c1b92011-07-08 09:43:20 +1000394 evo_mthd(push, 0x0404 + (nv_crtc->index * 0x300), 1);
395 evo_data(push, syncs);
Ben Skeggs438d99e2011-07-05 16:48:06 +1000396 evo_kick(push, crtc->dev, 0);
397 }
398
399 nv_connector = nouveau_crtc_connector_get(nv_crtc);
Ben Skeggs488ff202011-10-17 10:38:10 +1000400 nvd0_crtc_set_dither(nv_crtc, false);
401 nvd0_crtc_set_scale(nv_crtc, false);
Ben Skeggs438d99e2011-07-05 16:48:06 +1000402 nvd0_crtc_set_image(nv_crtc, crtc->fb, x, y, false);
403 return 0;
404}
405
406static int
407nvd0_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y,
408 struct drm_framebuffer *old_fb)
409{
410 struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
411 int ret;
412
Ben Skeggs84e2ad82011-08-26 09:40:39 +1000413 if (!crtc->fb) {
414 NV_DEBUG_KMS(crtc->dev, "No FB bound\n");
415 return 0;
416 }
417
Ben Skeggs438d99e2011-07-05 16:48:06 +1000418 ret = nvd0_crtc_swap_fbs(crtc, old_fb);
419 if (ret)
420 return ret;
421
422 nvd0_crtc_set_image(nv_crtc, crtc->fb, x, y, true);
423 return 0;
424}
425
426static int
427nvd0_crtc_mode_set_base_atomic(struct drm_crtc *crtc,
428 struct drm_framebuffer *fb, int x, int y,
429 enum mode_set_atomic state)
430{
431 struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
432 nvd0_crtc_set_image(nv_crtc, fb, x, y, true);
433 return 0;
434}
435
436static void
437nvd0_crtc_lut_load(struct drm_crtc *crtc)
438{
439 struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
440 void __iomem *lut = nvbo_kmap_obj_iovirtual(nv_crtc->lut.nvbo);
441 int i;
442
443 for (i = 0; i < 256; i++) {
Ben Skeggs8ea0d4a2011-07-07 14:49:24 +1000444 writew(0x6000 + (nv_crtc->lut.r[i] >> 2), lut + (i * 0x20) + 0);
445 writew(0x6000 + (nv_crtc->lut.g[i] >> 2), lut + (i * 0x20) + 2);
446 writew(0x6000 + (nv_crtc->lut.b[i] >> 2), lut + (i * 0x20) + 4);
Ben Skeggs438d99e2011-07-05 16:48:06 +1000447 }
448}
449
450static int
451nvd0_crtc_cursor_set(struct drm_crtc *crtc, struct drm_file *file_priv,
452 uint32_t handle, uint32_t width, uint32_t height)
453{
454 struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
455 struct drm_device *dev = crtc->dev;
456 struct drm_gem_object *gem;
457 struct nouveau_bo *nvbo;
458 bool visible = (handle != 0);
459 int i, ret = 0;
460
461 if (visible) {
462 if (width != 64 || height != 64)
463 return -EINVAL;
464
465 gem = drm_gem_object_lookup(dev, file_priv, handle);
466 if (unlikely(!gem))
467 return -ENOENT;
468 nvbo = nouveau_gem_object(gem);
469
470 ret = nouveau_bo_map(nvbo);
471 if (ret == 0) {
472 for (i = 0; i < 64 * 64; i++) {
473 u32 v = nouveau_bo_rd32(nvbo, i);
474 nouveau_bo_wr32(nv_crtc->cursor.nvbo, i, v);
475 }
476 nouveau_bo_unmap(nvbo);
477 }
478
479 drm_gem_object_unreference_unlocked(gem);
480 }
481
482 if (visible != nv_crtc->cursor.visible) {
483 nvd0_crtc_cursor_show(nv_crtc, visible, true);
484 nv_crtc->cursor.visible = visible;
485 }
486
487 return ret;
488}
489
490static int
491nvd0_crtc_cursor_move(struct drm_crtc *crtc, int x, int y)
492{
493 struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
494 const u32 data = (y << 16) | x;
495
496 nv_wr32(crtc->dev, 0x64d084 + (nv_crtc->index * 0x1000), data);
497 nv_wr32(crtc->dev, 0x64d080 + (nv_crtc->index * 0x1000), 0x00000000);
498 return 0;
499}
500
501static void
502nvd0_crtc_gamma_set(struct drm_crtc *crtc, u16 *r, u16 *g, u16 *b,
503 uint32_t start, uint32_t size)
504{
505 struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
506 u32 end = max(start + size, (u32)256);
507 u32 i;
508
509 for (i = start; i < end; i++) {
510 nv_crtc->lut.r[i] = r[i];
511 nv_crtc->lut.g[i] = g[i];
512 nv_crtc->lut.b[i] = b[i];
513 }
514
515 nvd0_crtc_lut_load(crtc);
516}
517
518static void
519nvd0_crtc_destroy(struct drm_crtc *crtc)
520{
521 struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
522 nouveau_bo_unmap(nv_crtc->cursor.nvbo);
523 nouveau_bo_ref(NULL, &nv_crtc->cursor.nvbo);
524 nouveau_bo_unmap(nv_crtc->lut.nvbo);
525 nouveau_bo_ref(NULL, &nv_crtc->lut.nvbo);
526 drm_crtc_cleanup(crtc);
527 kfree(crtc);
528}
529
530static const struct drm_crtc_helper_funcs nvd0_crtc_hfunc = {
531 .dpms = nvd0_crtc_dpms,
532 .prepare = nvd0_crtc_prepare,
533 .commit = nvd0_crtc_commit,
534 .mode_fixup = nvd0_crtc_mode_fixup,
535 .mode_set = nvd0_crtc_mode_set,
536 .mode_set_base = nvd0_crtc_mode_set_base,
537 .mode_set_base_atomic = nvd0_crtc_mode_set_base_atomic,
538 .load_lut = nvd0_crtc_lut_load,
539};
540
541static const struct drm_crtc_funcs nvd0_crtc_func = {
542 .cursor_set = nvd0_crtc_cursor_set,
543 .cursor_move = nvd0_crtc_cursor_move,
544 .gamma_set = nvd0_crtc_gamma_set,
545 .set_config = drm_crtc_helper_set_config,
546 .destroy = nvd0_crtc_destroy,
547};
548
Ben Skeggsc20ab3e2011-08-25 14:09:43 +1000549static void
550nvd0_cursor_set_pos(struct nouveau_crtc *nv_crtc, int x, int y)
551{
552}
553
554static void
555nvd0_cursor_set_offset(struct nouveau_crtc *nv_crtc, uint32_t offset)
556{
557}
558
Ben Skeggs438d99e2011-07-05 16:48:06 +1000559static int
560nvd0_crtc_create(struct drm_device *dev, int index)
561{
562 struct nouveau_crtc *nv_crtc;
563 struct drm_crtc *crtc;
564 int ret, i;
565
566 nv_crtc = kzalloc(sizeof(*nv_crtc), GFP_KERNEL);
567 if (!nv_crtc)
568 return -ENOMEM;
569
570 nv_crtc->index = index;
571 nv_crtc->set_dither = nvd0_crtc_set_dither;
572 nv_crtc->set_scale = nvd0_crtc_set_scale;
Ben Skeggsc20ab3e2011-08-25 14:09:43 +1000573 nv_crtc->cursor.set_offset = nvd0_cursor_set_offset;
574 nv_crtc->cursor.set_pos = nvd0_cursor_set_pos;
Ben Skeggs438d99e2011-07-05 16:48:06 +1000575 for (i = 0; i < 256; i++) {
576 nv_crtc->lut.r[i] = i << 8;
577 nv_crtc->lut.g[i] = i << 8;
578 nv_crtc->lut.b[i] = i << 8;
579 }
580
581 crtc = &nv_crtc->base;
582 drm_crtc_init(dev, crtc, &nvd0_crtc_func);
583 drm_crtc_helper_add(crtc, &nvd0_crtc_hfunc);
584 drm_mode_crtc_set_gamma_size(crtc, 256);
585
586 ret = nouveau_bo_new(dev, 64 * 64 * 4, 0x100, TTM_PL_FLAG_VRAM,
587 0, 0x0000, &nv_crtc->cursor.nvbo);
588 if (!ret) {
589 ret = nouveau_bo_pin(nv_crtc->cursor.nvbo, TTM_PL_FLAG_VRAM);
590 if (!ret)
591 ret = nouveau_bo_map(nv_crtc->cursor.nvbo);
592 if (ret)
593 nouveau_bo_ref(NULL, &nv_crtc->cursor.nvbo);
594 }
595
596 if (ret)
597 goto out;
598
Ben Skeggs8ea0d4a2011-07-07 14:49:24 +1000599 ret = nouveau_bo_new(dev, 8192, 0x100, TTM_PL_FLAG_VRAM,
Ben Skeggs438d99e2011-07-05 16:48:06 +1000600 0, 0x0000, &nv_crtc->lut.nvbo);
601 if (!ret) {
602 ret = nouveau_bo_pin(nv_crtc->lut.nvbo, TTM_PL_FLAG_VRAM);
603 if (!ret)
604 ret = nouveau_bo_map(nv_crtc->lut.nvbo);
605 if (ret)
606 nouveau_bo_ref(NULL, &nv_crtc->lut.nvbo);
607 }
608
609 if (ret)
610 goto out;
611
612 nvd0_crtc_lut_load(crtc);
613
614out:
615 if (ret)
616 nvd0_crtc_destroy(crtc);
617 return ret;
618}
619
620/******************************************************************************
Ben Skeggs26f6d882011-07-04 16:25:18 +1000621 * DAC
622 *****************************************************************************/
Ben Skeggs8eaa9662011-07-06 15:25:47 +1000623static void
624nvd0_dac_dpms(struct drm_encoder *encoder, int mode)
625{
626 struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
627 struct drm_device *dev = encoder->dev;
628 int or = nv_encoder->or;
629 u32 dpms_ctrl;
630
631 dpms_ctrl = 0x80000000;
632 if (mode == DRM_MODE_DPMS_STANDBY || mode == DRM_MODE_DPMS_OFF)
633 dpms_ctrl |= 0x00000001;
634 if (mode == DRM_MODE_DPMS_SUSPEND || mode == DRM_MODE_DPMS_OFF)
635 dpms_ctrl |= 0x00000004;
636
637 nv_wait(dev, 0x61a004 + (or * 0x0800), 0x80000000, 0x00000000);
638 nv_mask(dev, 0x61a004 + (or * 0x0800), 0xc000007f, dpms_ctrl);
639 nv_wait(dev, 0x61a004 + (or * 0x0800), 0x80000000, 0x00000000);
640}
641
642static bool
643nvd0_dac_mode_fixup(struct drm_encoder *encoder, struct drm_display_mode *mode,
644 struct drm_display_mode *adjusted_mode)
645{
646 struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
647 struct nouveau_connector *nv_connector;
648
649 nv_connector = nouveau_encoder_connector_get(nv_encoder);
650 if (nv_connector && nv_connector->native_mode) {
651 if (nv_connector->scaling_mode != DRM_MODE_SCALE_NONE) {
652 int id = adjusted_mode->base.id;
653 *adjusted_mode = *nv_connector->native_mode;
654 adjusted_mode->base.id = id;
655 }
656 }
657
658 return true;
659}
660
661static void
662nvd0_dac_prepare(struct drm_encoder *encoder)
663{
664}
665
666static void
667nvd0_dac_commit(struct drm_encoder *encoder)
668{
669}
670
671static void
672nvd0_dac_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode,
673 struct drm_display_mode *adjusted_mode)
674{
675 struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
676 struct nouveau_crtc *nv_crtc = nouveau_crtc(encoder->crtc);
677 u32 *push;
678
679 nvd0_dac_dpms(encoder, DRM_MODE_DPMS_ON);
680
Ben Skeggsff8ff502011-07-08 11:53:37 +1000681 push = evo_wait(encoder->dev, 0, 4);
Ben Skeggs8eaa9662011-07-06 15:25:47 +1000682 if (push) {
Ben Skeggsff8ff502011-07-08 11:53:37 +1000683 evo_mthd(push, 0x0180 + (nv_encoder->or * 0x20), 2);
Ben Skeggs8eaa9662011-07-06 15:25:47 +1000684 evo_data(push, 1 << nv_crtc->index);
Ben Skeggsff8ff502011-07-08 11:53:37 +1000685 evo_data(push, 0x00ff);
Ben Skeggs8eaa9662011-07-06 15:25:47 +1000686 evo_kick(push, encoder->dev, 0);
687 }
688
689 nv_encoder->crtc = encoder->crtc;
690}
691
692static void
693nvd0_dac_disconnect(struct drm_encoder *encoder)
694{
695 struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
696 struct drm_device *dev = encoder->dev;
697 u32 *push;
698
699 if (nv_encoder->crtc) {
700 nvd0_crtc_prepare(nv_encoder->crtc);
701
702 push = evo_wait(dev, 0, 4);
703 if (push) {
704 evo_mthd(push, 0x0180 + (nv_encoder->or * 0x20), 1);
705 evo_data(push, 0x00000000);
706 evo_mthd(push, 0x0080, 1);
707 evo_data(push, 0x00000000);
708 evo_kick(push, dev, 0);
709 }
710
711 nv_encoder->crtc = NULL;
712 }
713}
714
Ben Skeggsb6d8e7e2011-07-07 09:51:29 +1000715static enum drm_connector_status
716nvd0_dac_detect(struct drm_encoder *encoder, struct drm_connector *connector)
717{
Ben Skeggsb6819932011-07-08 11:14:50 +1000718 enum drm_connector_status status = connector_status_disconnected;
719 struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
720 struct drm_device *dev = encoder->dev;
721 int or = nv_encoder->or;
722 u32 load;
723
724 nv_wr32(dev, 0x61a00c + (or * 0x800), 0x00100000);
725 udelay(9500);
726 nv_wr32(dev, 0x61a00c + (or * 0x800), 0x80000000);
727
728 load = nv_rd32(dev, 0x61a00c + (or * 0x800));
729 if ((load & 0x38000000) == 0x38000000)
730 status = connector_status_connected;
731
732 nv_wr32(dev, 0x61a00c + (or * 0x800), 0x00000000);
733 return status;
Ben Skeggsb6d8e7e2011-07-07 09:51:29 +1000734}
735
Ben Skeggs8eaa9662011-07-06 15:25:47 +1000736static void
737nvd0_dac_destroy(struct drm_encoder *encoder)
738{
739 drm_encoder_cleanup(encoder);
740 kfree(encoder);
741}
742
743static const struct drm_encoder_helper_funcs nvd0_dac_hfunc = {
744 .dpms = nvd0_dac_dpms,
745 .mode_fixup = nvd0_dac_mode_fixup,
746 .prepare = nvd0_dac_prepare,
747 .commit = nvd0_dac_commit,
748 .mode_set = nvd0_dac_mode_set,
749 .disable = nvd0_dac_disconnect,
750 .get_crtc = nvd0_display_crtc_get,
Ben Skeggsb6d8e7e2011-07-07 09:51:29 +1000751 .detect = nvd0_dac_detect
Ben Skeggs8eaa9662011-07-06 15:25:47 +1000752};
753
754static const struct drm_encoder_funcs nvd0_dac_func = {
755 .destroy = nvd0_dac_destroy,
756};
757
758static int
759nvd0_dac_create(struct drm_connector *connector, struct dcb_entry *dcbe)
760{
761 struct drm_device *dev = connector->dev;
762 struct nouveau_encoder *nv_encoder;
763 struct drm_encoder *encoder;
764
765 nv_encoder = kzalloc(sizeof(*nv_encoder), GFP_KERNEL);
766 if (!nv_encoder)
767 return -ENOMEM;
768 nv_encoder->dcb = dcbe;
769 nv_encoder->or = ffs(dcbe->or) - 1;
770
771 encoder = to_drm_encoder(nv_encoder);
772 encoder->possible_crtcs = dcbe->heads;
773 encoder->possible_clones = 0;
774 drm_encoder_init(dev, encoder, &nvd0_dac_func, DRM_MODE_ENCODER_DAC);
775 drm_encoder_helper_add(encoder, &nvd0_dac_hfunc);
776
777 drm_mode_connector_attach_encoder(connector, encoder);
778 return 0;
779}
Ben Skeggs26f6d882011-07-04 16:25:18 +1000780
781/******************************************************************************
Ben Skeggs78951d22011-11-11 18:13:13 +1000782 * Audio
783 *****************************************************************************/
784static void
785nvd0_audio_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode)
786{
787 struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
788 struct nouveau_connector *nv_connector;
789 struct drm_device *dev = encoder->dev;
790 int i, or = nv_encoder->or * 0x30;
791
792 nv_connector = nouveau_encoder_connector_get(nv_encoder);
793 if (!drm_detect_monitor_audio(nv_connector->edid))
794 return;
795
796 nv_mask(dev, 0x10ec10 + or, 0x80000003, 0x80000001);
797
798 drm_edid_to_eld(&nv_connector->base, nv_connector->edid);
799 if (nv_connector->base.eld[0]) {
800 u8 *eld = nv_connector->base.eld;
801
802 for (i = 0; i < eld[2] * 4; i++)
803 nv_wr32(dev, 0x10ec00 + or, (i << 8) | eld[i]);
804 for (i = eld[2] * 4; i < 0x60; i++)
805 nv_wr32(dev, 0x10ec00 + or, (i << 8) | 0x00);
806
807 nv_mask(dev, 0x10ec10 + or, 0x80000002, 0x80000002);
808 }
809}
810
811static void
812nvd0_audio_disconnect(struct drm_encoder *encoder)
813{
814 struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
815 struct drm_device *dev = encoder->dev;
816 int or = nv_encoder->or * 0x30;
817
818 nv_mask(dev, 0x10ec10 + or, 0x80000003, 0x80000000);
819}
820
821/******************************************************************************
822 * HDMI
823 *****************************************************************************/
824static void
825nvd0_hdmi_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode)
826{
Ben Skeggs64d9cc02011-11-11 19:51:20 +1000827 struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
828 struct nouveau_crtc *nv_crtc = nouveau_crtc(encoder->crtc);
829 struct nouveau_connector *nv_connector;
830 struct drm_device *dev = encoder->dev;
831 int head = nv_crtc->index * 0x800;
832 u32 rekey = 56; /* binary driver, and tegra constant */
833 u32 max_ac_packet;
834
835 nv_connector = nouveau_encoder_connector_get(nv_encoder);
836 if (!drm_detect_hdmi_monitor(nv_connector->edid))
837 return;
838
839 max_ac_packet = mode->htotal - mode->hdisplay;
840 max_ac_packet -= rekey;
841 max_ac_packet -= 18; /* constant from tegra */
842 max_ac_packet /= 32;
843
844 /* AVI InfoFrame */
845 nv_mask(dev, 0x616714 + head, 0x00000001, 0x00000000);
846 nv_wr32(dev, 0x61671c + head, 0x000d0282);
847 nv_wr32(dev, 0x616720 + head, 0x0000006f);
848 nv_wr32(dev, 0x616724 + head, 0x00000000);
849 nv_wr32(dev, 0x616728 + head, 0x00000000);
850 nv_wr32(dev, 0x61672c + head, 0x00000000);
851 nv_mask(dev, 0x616714 + head, 0x00000001, 0x00000001);
852
853 /* ??? InfoFrame? */
854 nv_mask(dev, 0x6167a4 + head, 0x00000001, 0x00000000);
855 nv_wr32(dev, 0x6167ac + head, 0x00000010);
856 nv_mask(dev, 0x6167a4 + head, 0x00000001, 0x00000001);
857
858 /* HDMI_CTRL */
859 nv_mask(dev, 0x616798 + head, 0x401f007f, 0x40000000 | rekey |
860 max_ac_packet << 16);
861
Ben Skeggs78951d22011-11-11 18:13:13 +1000862 nvd0_audio_mode_set(encoder, mode);
863}
864
865static void
866nvd0_hdmi_disconnect(struct drm_encoder *encoder)
867{
Ben Skeggs64d9cc02011-11-11 19:51:20 +1000868 struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
869 struct nouveau_crtc *nv_crtc = nouveau_crtc(nv_encoder->crtc);
870 struct drm_device *dev = encoder->dev;
871 int head = nv_crtc->index * 0x800;
872
Ben Skeggs78951d22011-11-11 18:13:13 +1000873 nvd0_audio_disconnect(encoder);
Ben Skeggs64d9cc02011-11-11 19:51:20 +1000874
875 nv_mask(dev, 0x616798 + head, 0x40000000, 0x00000000);
876 nv_mask(dev, 0x6167a4 + head, 0x00000001, 0x00000000);
877 nv_mask(dev, 0x616714 + head, 0x00000001, 0x00000000);
Ben Skeggs78951d22011-11-11 18:13:13 +1000878}
879
880/******************************************************************************
Ben Skeggs26f6d882011-07-04 16:25:18 +1000881 * SOR
882 *****************************************************************************/
Ben Skeggs83fc0832011-07-05 13:08:40 +1000883static void
884nvd0_sor_dpms(struct drm_encoder *encoder, int mode)
885{
886 struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
887 struct drm_device *dev = encoder->dev;
888 struct drm_encoder *partner;
889 int or = nv_encoder->or;
890 u32 dpms_ctrl;
891
892 nv_encoder->last_dpms = mode;
893
894 list_for_each_entry(partner, &dev->mode_config.encoder_list, head) {
895 struct nouveau_encoder *nv_partner = nouveau_encoder(partner);
896
897 if (partner->encoder_type != DRM_MODE_ENCODER_TMDS)
898 continue;
899
900 if (nv_partner != nv_encoder &&
Ben Skeggs26cfa812011-11-17 09:10:02 +1000901 nv_partner->dcb->or == nv_encoder->dcb->or) {
Ben Skeggs83fc0832011-07-05 13:08:40 +1000902 if (nv_partner->last_dpms == DRM_MODE_DPMS_ON)
903 return;
904 break;
905 }
906 }
907
908 dpms_ctrl = (mode == DRM_MODE_DPMS_ON);
909 dpms_ctrl |= 0x80000000;
910
911 nv_wait(dev, 0x61c004 + (or * 0x0800), 0x80000000, 0x00000000);
912 nv_mask(dev, 0x61c004 + (or * 0x0800), 0x80000001, dpms_ctrl);
913 nv_wait(dev, 0x61c004 + (or * 0x0800), 0x80000000, 0x00000000);
914 nv_wait(dev, 0x61c030 + (or * 0x0800), 0x10000000, 0x00000000);
915}
916
917static bool
918nvd0_sor_mode_fixup(struct drm_encoder *encoder, struct drm_display_mode *mode,
919 struct drm_display_mode *adjusted_mode)
920{
921 struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
922 struct nouveau_connector *nv_connector;
923
924 nv_connector = nouveau_encoder_connector_get(nv_encoder);
925 if (nv_connector && nv_connector->native_mode) {
926 if (nv_connector->scaling_mode != DRM_MODE_SCALE_NONE) {
927 int id = adjusted_mode->base.id;
928 *adjusted_mode = *nv_connector->native_mode;
929 adjusted_mode->base.id = id;
930 }
931 }
932
933 return true;
934}
935
936static void
937nvd0_sor_prepare(struct drm_encoder *encoder)
938{
939}
940
941static void
942nvd0_sor_commit(struct drm_encoder *encoder)
943{
944}
945
946static void
Ben Skeggs3b6d83d12011-07-08 12:52:14 +1000947nvd0_sor_mode_set(struct drm_encoder *encoder, struct drm_display_mode *umode,
948 struct drm_display_mode *mode)
Ben Skeggs83fc0832011-07-05 13:08:40 +1000949{
Ben Skeggs78951d22011-11-11 18:13:13 +1000950 struct drm_device *dev = encoder->dev;
951 struct drm_nouveau_private *dev_priv = dev->dev_private;
Ben Skeggs83fc0832011-07-05 13:08:40 +1000952 struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
953 struct nouveau_crtc *nv_crtc = nouveau_crtc(encoder->crtc);
Ben Skeggs3b6d83d12011-07-08 12:52:14 +1000954 struct nouveau_connector *nv_connector;
955 struct nvbios *bios = &dev_priv->vbios;
Ben Skeggs83fc0832011-07-05 13:08:40 +1000956 u32 mode_ctrl = (1 << nv_crtc->index);
Ben Skeggsff8ff502011-07-08 11:53:37 +1000957 u32 *push, or_config;
Ben Skeggs83fc0832011-07-05 13:08:40 +1000958
Ben Skeggs3b6d83d12011-07-08 12:52:14 +1000959 nv_connector = nouveau_encoder_connector_get(nv_encoder);
960 switch (nv_encoder->dcb->type) {
961 case OUTPUT_TMDS:
962 if (nv_encoder->dcb->sorconf.link & 1) {
963 if (mode->clock < 165000)
964 mode_ctrl |= 0x00000100;
965 else
966 mode_ctrl |= 0x00000500;
967 } else {
968 mode_ctrl |= 0x00000200;
969 }
Ben Skeggs83fc0832011-07-05 13:08:40 +1000970
Ben Skeggs3b6d83d12011-07-08 12:52:14 +1000971 or_config = (mode_ctrl & 0x00000f00) >> 8;
972 if (mode->clock >= 165000)
973 or_config |= 0x0100;
Ben Skeggs78951d22011-11-11 18:13:13 +1000974
975 nvd0_hdmi_mode_set(encoder, mode);
Ben Skeggs3b6d83d12011-07-08 12:52:14 +1000976 break;
977 case OUTPUT_LVDS:
978 or_config = (mode_ctrl & 0x00000f00) >> 8;
979 if (bios->fp_no_ddc) {
980 if (bios->fp.dual_link)
981 or_config |= 0x0100;
982 if (bios->fp.if_is_24bit)
983 or_config |= 0x0200;
984 } else {
985 if (nv_connector->dcb->type == DCB_CONNECTOR_LVDS_SPWG) {
986 if (((u8 *)nv_connector->edid)[121] == 2)
987 or_config |= 0x0100;
988 } else
989 if (mode->clock >= bios->fp.duallink_transition_clk) {
990 or_config |= 0x0100;
991 }
992
993 if (or_config & 0x0100) {
994 if (bios->fp.strapless_is_24bit & 2)
995 or_config |= 0x0200;
996 } else {
997 if (bios->fp.strapless_is_24bit & 1)
998 or_config |= 0x0200;
999 }
1000
1001 if (nv_connector->base.display_info.bpc == 8)
1002 or_config |= 0x0200;
1003
1004 }
1005 break;
1006 default:
1007 BUG_ON(1);
1008 break;
1009 }
Ben Skeggsff8ff502011-07-08 11:53:37 +10001010
Ben Skeggs83fc0832011-07-05 13:08:40 +10001011 nvd0_sor_dpms(encoder, DRM_MODE_DPMS_ON);
1012
Ben Skeggs78951d22011-11-11 18:13:13 +10001013 push = evo_wait(dev, 0, 4);
Ben Skeggs83fc0832011-07-05 13:08:40 +10001014 if (push) {
Ben Skeggsff8ff502011-07-08 11:53:37 +10001015 evo_mthd(push, 0x0200 + (nv_encoder->or * 0x20), 2);
Ben Skeggs83fc0832011-07-05 13:08:40 +10001016 evo_data(push, mode_ctrl);
Ben Skeggsff8ff502011-07-08 11:53:37 +10001017 evo_data(push, or_config);
Ben Skeggs78951d22011-11-11 18:13:13 +10001018 evo_kick(push, dev, 0);
Ben Skeggs83fc0832011-07-05 13:08:40 +10001019 }
1020
1021 nv_encoder->crtc = encoder->crtc;
1022}
1023
1024static void
1025nvd0_sor_disconnect(struct drm_encoder *encoder)
1026{
1027 struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
1028 struct drm_device *dev = encoder->dev;
Ben Skeggs438d99e2011-07-05 16:48:06 +10001029 u32 *push;
Ben Skeggs83fc0832011-07-05 13:08:40 +10001030
1031 if (nv_encoder->crtc) {
Ben Skeggs438d99e2011-07-05 16:48:06 +10001032 nvd0_crtc_prepare(nv_encoder->crtc);
1033
1034 push = evo_wait(dev, 0, 4);
Ben Skeggs83fc0832011-07-05 13:08:40 +10001035 if (push) {
1036 evo_mthd(push, 0x0200 + (nv_encoder->or * 0x20), 1);
1037 evo_data(push, 0x00000000);
1038 evo_mthd(push, 0x0080, 1);
1039 evo_data(push, 0x00000000);
1040 evo_kick(push, dev, 0);
1041 }
1042
Ben Skeggs78951d22011-11-11 18:13:13 +10001043 nvd0_hdmi_disconnect(encoder);
1044
Ben Skeggs83fc0832011-07-05 13:08:40 +10001045 nv_encoder->crtc = NULL;
1046 nv_encoder->last_dpms = DRM_MODE_DPMS_OFF;
1047 }
1048}
1049
1050static void
1051nvd0_sor_destroy(struct drm_encoder *encoder)
1052{
1053 drm_encoder_cleanup(encoder);
1054 kfree(encoder);
1055}
1056
1057static const struct drm_encoder_helper_funcs nvd0_sor_hfunc = {
1058 .dpms = nvd0_sor_dpms,
1059 .mode_fixup = nvd0_sor_mode_fixup,
1060 .prepare = nvd0_sor_prepare,
1061 .commit = nvd0_sor_commit,
1062 .mode_set = nvd0_sor_mode_set,
1063 .disable = nvd0_sor_disconnect,
1064 .get_crtc = nvd0_display_crtc_get,
1065};
1066
1067static const struct drm_encoder_funcs nvd0_sor_func = {
1068 .destroy = nvd0_sor_destroy,
1069};
1070
1071static int
1072nvd0_sor_create(struct drm_connector *connector, struct dcb_entry *dcbe)
1073{
1074 struct drm_device *dev = connector->dev;
1075 struct nouveau_encoder *nv_encoder;
1076 struct drm_encoder *encoder;
1077
1078 nv_encoder = kzalloc(sizeof(*nv_encoder), GFP_KERNEL);
1079 if (!nv_encoder)
1080 return -ENOMEM;
1081 nv_encoder->dcb = dcbe;
1082 nv_encoder->or = ffs(dcbe->or) - 1;
1083 nv_encoder->last_dpms = DRM_MODE_DPMS_OFF;
1084
1085 encoder = to_drm_encoder(nv_encoder);
1086 encoder->possible_crtcs = dcbe->heads;
1087 encoder->possible_clones = 0;
1088 drm_encoder_init(dev, encoder, &nvd0_sor_func, DRM_MODE_ENCODER_TMDS);
1089 drm_encoder_helper_add(encoder, &nvd0_sor_hfunc);
1090
1091 drm_mode_connector_attach_encoder(connector, encoder);
1092 return 0;
1093}
Ben Skeggs26f6d882011-07-04 16:25:18 +10001094
1095/******************************************************************************
1096 * IRQ
1097 *****************************************************************************/
Ben Skeggs3a89cd02011-07-07 10:47:10 +10001098static struct dcb_entry *
1099lookup_dcb(struct drm_device *dev, int id, u32 mc)
1100{
1101 struct drm_nouveau_private *dev_priv = dev->dev_private;
1102 int type, or, i;
1103
1104 if (id < 4) {
1105 type = OUTPUT_ANALOG;
1106 or = id;
1107 } else {
Ben Skeggs3b6d83d12011-07-08 12:52:14 +10001108 switch (mc & 0x00000f00) {
1109 case 0x00000000: type = OUTPUT_LVDS; break;
1110 case 0x00000100: type = OUTPUT_TMDS; break;
1111 case 0x00000200: type = OUTPUT_TMDS; break;
1112 case 0x00000500: type = OUTPUT_TMDS; break;
1113 default:
Ben Skeggsee417792011-07-08 14:34:45 +10001114 NV_ERROR(dev, "PDISP: unknown SOR mc 0x%08x\n", mc);
Ben Skeggs3b6d83d12011-07-08 12:52:14 +10001115 return NULL;
1116 }
1117
1118 or = id - 4;
Ben Skeggs3a89cd02011-07-07 10:47:10 +10001119 }
1120
1121 for (i = 0; i < dev_priv->vbios.dcb.entries; i++) {
1122 struct dcb_entry *dcb = &dev_priv->vbios.dcb.entry[i];
1123 if (dcb->type == type && (dcb->or & (1 << or)))
1124 return dcb;
1125 }
1126
Ben Skeggsee417792011-07-08 14:34:45 +10001127 NV_ERROR(dev, "PDISP: DCB for %d/0x%08x not found\n", id, mc);
Ben Skeggs3a89cd02011-07-07 10:47:10 +10001128 return NULL;
1129}
1130
Ben Skeggs46005222011-07-05 11:01:13 +10001131static void
Ben Skeggs37b034a2011-07-08 14:43:19 +10001132nvd0_display_unk1_handler(struct drm_device *dev, u32 crtc, u32 mask)
Ben Skeggs270a5742011-07-05 14:16:05 +10001133{
Ben Skeggs3a89cd02011-07-07 10:47:10 +10001134 struct dcb_entry *dcb;
Ben Skeggs3a89cd02011-07-07 10:47:10 +10001135 int i;
1136
Ben Skeggsee417792011-07-08 14:34:45 +10001137 for (i = 0; mask && i < 8; i++) {
Ben Skeggs3a89cd02011-07-07 10:47:10 +10001138 u32 mcc = nv_rd32(dev, 0x640180 + (i * 0x20));
Ben Skeggsee417792011-07-08 14:34:45 +10001139 if (!(mcc & (1 << crtc)))
1140 continue;
Ben Skeggs3a89cd02011-07-07 10:47:10 +10001141
Ben Skeggsee417792011-07-08 14:34:45 +10001142 dcb = lookup_dcb(dev, i, mcc);
1143 if (!dcb)
1144 continue;
Ben Skeggs3a89cd02011-07-07 10:47:10 +10001145
Ben Skeggs3a89cd02011-07-07 10:47:10 +10001146 nouveau_bios_run_display_table(dev, 0x0000, -1, dcb, crtc);
Ben Skeggsee417792011-07-08 14:34:45 +10001147 }
Ben Skeggs3a89cd02011-07-07 10:47:10 +10001148
Ben Skeggs270a5742011-07-05 14:16:05 +10001149 nv_wr32(dev, 0x6101d4, 0x00000000);
1150 nv_wr32(dev, 0x6109d4, 0x00000000);
1151 nv_wr32(dev, 0x6101d0, 0x80000000);
1152}
1153
1154static void
Ben Skeggs37b034a2011-07-08 14:43:19 +10001155nvd0_display_unk2_handler(struct drm_device *dev, u32 crtc, u32 mask)
Ben Skeggs270a5742011-07-05 14:16:05 +10001156{
Ben Skeggs3a89cd02011-07-07 10:47:10 +10001157 struct dcb_entry *dcb;
Ben Skeggs37b034a2011-07-08 14:43:19 +10001158 u32 or, tmp, pclk;
Ben Skeggsee417792011-07-08 14:34:45 +10001159 int i;
Ben Skeggs3a89cd02011-07-07 10:47:10 +10001160
Ben Skeggsee417792011-07-08 14:34:45 +10001161 for (i = 0; mask && i < 8; i++) {
1162 u32 mcc = nv_rd32(dev, 0x640180 + (i * 0x20));
1163 if (!(mcc & (1 << crtc)))
1164 continue;
1165
1166 dcb = lookup_dcb(dev, i, mcc);
1167 if (!dcb)
1168 continue;
1169
Ben Skeggs3a89cd02011-07-07 10:47:10 +10001170 nouveau_bios_run_display_table(dev, 0x0000, -2, dcb, crtc);
Ben Skeggsee417792011-07-08 14:34:45 +10001171 }
Ben Skeggs3a89cd02011-07-07 10:47:10 +10001172
Ben Skeggsee417792011-07-08 14:34:45 +10001173 pclk = nv_rd32(dev, 0x660450 + (crtc * 0x300)) / 1000;
1174 if (mask & 0x00010000) {
1175 nv50_crtc_set_clock(dev, crtc, pclk);
1176 }
Ben Skeggs3a89cd02011-07-07 10:47:10 +10001177
Ben Skeggsee417792011-07-08 14:34:45 +10001178 for (i = 0; mask && i < 8; i++) {
1179 u32 mcp = nv_rd32(dev, 0x660180 + (i * 0x20));
1180 u32 cfg = nv_rd32(dev, 0x660184 + (i * 0x20));
1181 if (!(mcp & (1 << crtc)))
1182 continue;
Ben Skeggs3a89cd02011-07-07 10:47:10 +10001183
Ben Skeggsee417792011-07-08 14:34:45 +10001184 dcb = lookup_dcb(dev, i, mcp);
1185 if (!dcb)
1186 continue;
1187 or = ffs(dcb->or) - 1;
Ben Skeggs3a89cd02011-07-07 10:47:10 +10001188
Ben Skeggsee417792011-07-08 14:34:45 +10001189 nouveau_bios_run_display_table(dev, cfg, pclk, dcb, crtc);
Ben Skeggs3a89cd02011-07-07 10:47:10 +10001190
Ben Skeggsee417792011-07-08 14:34:45 +10001191 nv_wr32(dev, 0x612200 + (crtc * 0x800), 0x00000000);
1192 switch (dcb->type) {
1193 case OUTPUT_ANALOG:
1194 nv_wr32(dev, 0x612280 + (or * 0x800), 0x00000000);
1195 break;
1196 case OUTPUT_TMDS:
1197 case OUTPUT_LVDS:
1198 if (cfg & 0x00000100)
1199 tmp = 0x00000101;
1200 else
1201 tmp = 0x00000000;
1202
1203 nv_mask(dev, 0x612300 + (or * 0x800), 0x00000707, tmp);
1204 break;
1205 default:
1206 break;
1207 }
1208
Ben Skeggs3a89cd02011-07-07 10:47:10 +10001209 break;
1210 }
1211
Ben Skeggs270a5742011-07-05 14:16:05 +10001212 nv_wr32(dev, 0x6101d4, 0x00000000);
1213 nv_wr32(dev, 0x6109d4, 0x00000000);
1214 nv_wr32(dev, 0x6101d0, 0x80000000);
1215}
1216
1217static void
Ben Skeggs37b034a2011-07-08 14:43:19 +10001218nvd0_display_unk4_handler(struct drm_device *dev, u32 crtc, u32 mask)
Ben Skeggs270a5742011-07-05 14:16:05 +10001219{
Ben Skeggs3a89cd02011-07-07 10:47:10 +10001220 struct dcb_entry *dcb;
Ben Skeggsee417792011-07-08 14:34:45 +10001221 int pclk, i;
Ben Skeggs3a89cd02011-07-07 10:47:10 +10001222
Ben Skeggsee417792011-07-08 14:34:45 +10001223 pclk = nv_rd32(dev, 0x660450 + (crtc * 0x300)) / 1000;
Ben Skeggs3a89cd02011-07-07 10:47:10 +10001224
Ben Skeggsee417792011-07-08 14:34:45 +10001225 for (i = 0; mask && i < 8; i++) {
1226 u32 mcp = nv_rd32(dev, 0x660180 + (i * 0x20));
1227 u32 cfg = nv_rd32(dev, 0x660184 + (i * 0x20));
1228 if (!(mcp & (1 << crtc)))
1229 continue;
Ben Skeggs3a89cd02011-07-07 10:47:10 +10001230
Ben Skeggsee417792011-07-08 14:34:45 +10001231 dcb = lookup_dcb(dev, i, mcp);
1232 if (!dcb)
1233 continue;
1234
1235 nouveau_bios_run_display_table(dev, cfg, -pclk, dcb, crtc);
1236 }
1237
Ben Skeggs270a5742011-07-05 14:16:05 +10001238 nv_wr32(dev, 0x6101d4, 0x00000000);
1239 nv_wr32(dev, 0x6109d4, 0x00000000);
1240 nv_wr32(dev, 0x6101d0, 0x80000000);
1241}
1242
1243static void
Ben Skeggsf20ce962011-07-08 13:17:01 +10001244nvd0_display_bh(unsigned long data)
1245{
1246 struct drm_device *dev = (struct drm_device *)data;
1247 struct nvd0_display *disp = nvd0_display(dev);
Ben Skeggs37b034a2011-07-08 14:43:19 +10001248 u32 mask, crtc;
1249 int i;
1250
1251 if (drm_debug & (DRM_UT_DRIVER | DRM_UT_KMS)) {
1252 NV_INFO(dev, "PDISP: modeset req %d\n", disp->modeset);
1253 NV_INFO(dev, " STAT: 0x%08x 0x%08x 0x%08x\n",
1254 nv_rd32(dev, 0x6101d0),
1255 nv_rd32(dev, 0x6101d4), nv_rd32(dev, 0x6109d4));
1256 for (i = 0; i < 8; i++) {
1257 NV_INFO(dev, " %s%d: 0x%08x 0x%08x\n",
1258 i < 4 ? "DAC" : "SOR", i,
1259 nv_rd32(dev, 0x640180 + (i * 0x20)),
1260 nv_rd32(dev, 0x660180 + (i * 0x20)));
1261 }
1262 }
1263
1264 mask = nv_rd32(dev, 0x6101d4);
1265 crtc = 0;
1266 if (!mask) {
1267 mask = nv_rd32(dev, 0x6109d4);
1268 crtc = 1;
1269 }
Ben Skeggsf20ce962011-07-08 13:17:01 +10001270
Ben Skeggsee417792011-07-08 14:34:45 +10001271 if (disp->modeset & 0x00000001)
Ben Skeggs37b034a2011-07-08 14:43:19 +10001272 nvd0_display_unk1_handler(dev, crtc, mask);
Ben Skeggsee417792011-07-08 14:34:45 +10001273 if (disp->modeset & 0x00000002)
Ben Skeggs37b034a2011-07-08 14:43:19 +10001274 nvd0_display_unk2_handler(dev, crtc, mask);
Ben Skeggsee417792011-07-08 14:34:45 +10001275 if (disp->modeset & 0x00000004)
Ben Skeggs37b034a2011-07-08 14:43:19 +10001276 nvd0_display_unk4_handler(dev, crtc, mask);
Ben Skeggsf20ce962011-07-08 13:17:01 +10001277}
1278
1279static void
Ben Skeggs46005222011-07-05 11:01:13 +10001280nvd0_display_intr(struct drm_device *dev)
1281{
Ben Skeggsf20ce962011-07-08 13:17:01 +10001282 struct nvd0_display *disp = nvd0_display(dev);
Ben Skeggs46005222011-07-05 11:01:13 +10001283 u32 intr = nv_rd32(dev, 0x610088);
1284
1285 if (intr & 0x00000002) {
1286 u32 stat = nv_rd32(dev, 0x61009c);
1287 int chid = ffs(stat) - 1;
1288 if (chid >= 0) {
1289 u32 mthd = nv_rd32(dev, 0x6101f0 + (chid * 12));
1290 u32 data = nv_rd32(dev, 0x6101f4 + (chid * 12));
1291 u32 unkn = nv_rd32(dev, 0x6101f8 + (chid * 12));
1292
1293 NV_INFO(dev, "EvoCh: chid %d mthd 0x%04x data 0x%08x "
1294 "0x%08x 0x%08x\n",
1295 chid, (mthd & 0x0000ffc), data, mthd, unkn);
1296 nv_wr32(dev, 0x61009c, (1 << chid));
1297 nv_wr32(dev, 0x6101f0 + (chid * 12), 0x90000000);
1298 }
1299
1300 intr &= ~0x00000002;
1301 }
1302
Ben Skeggs270a5742011-07-05 14:16:05 +10001303 if (intr & 0x00100000) {
1304 u32 stat = nv_rd32(dev, 0x6100ac);
1305
1306 if (stat & 0x00000007) {
Ben Skeggsee417792011-07-08 14:34:45 +10001307 disp->modeset = stat;
Ben Skeggsf20ce962011-07-08 13:17:01 +10001308 tasklet_schedule(&disp->tasklet);
Ben Skeggs270a5742011-07-05 14:16:05 +10001309
Ben Skeggsf20ce962011-07-08 13:17:01 +10001310 nv_wr32(dev, 0x6100ac, (stat & 0x00000007));
Ben Skeggs270a5742011-07-05 14:16:05 +10001311 stat &= ~0x00000007;
1312 }
1313
1314 if (stat) {
1315 NV_INFO(dev, "PDISP: unknown intr24 0x%08x\n", stat);
1316 nv_wr32(dev, 0x6100ac, stat);
1317 }
1318
1319 intr &= ~0x00100000;
1320 }
1321
Ben Skeggs46005222011-07-05 11:01:13 +10001322 if (intr & 0x01000000) {
1323 u32 stat = nv_rd32(dev, 0x6100bc);
1324 nv_wr32(dev, 0x6100bc, stat);
1325 intr &= ~0x01000000;
1326 }
1327
1328 if (intr & 0x02000000) {
1329 u32 stat = nv_rd32(dev, 0x6108bc);
1330 nv_wr32(dev, 0x6108bc, stat);
1331 intr &= ~0x02000000;
1332 }
1333
1334 if (intr)
1335 NV_INFO(dev, "PDISP: unknown intr 0x%08x\n", intr);
1336}
Ben Skeggs26f6d882011-07-04 16:25:18 +10001337
1338/******************************************************************************
1339 * Init
1340 *****************************************************************************/
1341static void
1342nvd0_display_fini(struct drm_device *dev)
1343{
1344 int i;
1345
1346 /* fini cursors */
1347 for (i = 14; i >= 13; i--) {
1348 if (!(nv_rd32(dev, 0x610490 + (i * 0x10)) & 0x00000001))
1349 continue;
1350
1351 nv_mask(dev, 0x610490 + (i * 0x10), 0x00000001, 0x00000000);
1352 nv_wait(dev, 0x610490 + (i * 0x10), 0x00010000, 0x00000000);
1353 nv_mask(dev, 0x610090, 1 << i, 0x00000000);
1354 nv_mask(dev, 0x6100a0, 1 << i, 0x00000000);
1355 }
1356
1357 /* fini master */
1358 if (nv_rd32(dev, 0x610490) & 0x00000010) {
1359 nv_mask(dev, 0x610490, 0x00000010, 0x00000000);
1360 nv_mask(dev, 0x610490, 0x00000003, 0x00000000);
1361 nv_wait(dev, 0x610490, 0x80000000, 0x00000000);
1362 nv_mask(dev, 0x610090, 0x00000001, 0x00000000);
1363 nv_mask(dev, 0x6100a0, 0x00000001, 0x00000000);
1364 }
1365}
1366
1367int
1368nvd0_display_init(struct drm_device *dev)
1369{
1370 struct nvd0_display *disp = nvd0_display(dev);
Ben Skeggsefd272a2011-07-05 11:58:58 +10001371 u32 *push;
Ben Skeggs26f6d882011-07-04 16:25:18 +10001372 int i;
1373
1374 if (nv_rd32(dev, 0x6100ac) & 0x00000100) {
1375 nv_wr32(dev, 0x6100ac, 0x00000100);
1376 nv_mask(dev, 0x6194e8, 0x00000001, 0x00000000);
1377 if (!nv_wait(dev, 0x6194e8, 0x00000002, 0x00000000)) {
1378 NV_ERROR(dev, "PDISP: 0x6194e8 0x%08x\n",
1379 nv_rd32(dev, 0x6194e8));
1380 return -EBUSY;
1381 }
1382 }
1383
Ben Skeggsa36f04c2011-07-06 14:39:23 +10001384 /* nfi what these are exactly, i do know that SOR_MODE_CTRL won't
1385 * work at all unless you do the SOR part below.
1386 */
1387 for (i = 0; i < 3; i++) {
1388 u32 dac = nv_rd32(dev, 0x61a000 + (i * 0x800));
1389 nv_wr32(dev, 0x6101c0 + (i * 0x800), dac);
1390 }
1391
1392 for (i = 0; i < 4; i++) {
1393 u32 sor = nv_rd32(dev, 0x61c000 + (i * 0x800));
1394 nv_wr32(dev, 0x6301c4 + (i * 0x800), sor);
1395 }
1396
1397 for (i = 0; i < 2; i++) {
1398 u32 crtc0 = nv_rd32(dev, 0x616104 + (i * 0x800));
1399 u32 crtc1 = nv_rd32(dev, 0x616108 + (i * 0x800));
1400 u32 crtc2 = nv_rd32(dev, 0x61610c + (i * 0x800));
1401 nv_wr32(dev, 0x6101b4 + (i * 0x800), crtc0);
1402 nv_wr32(dev, 0x6101b8 + (i * 0x800), crtc1);
1403 nv_wr32(dev, 0x6101bc + (i * 0x800), crtc2);
1404 }
1405
1406 /* point at our hash table / objects, enable interrupts */
Ben Skeggs26f6d882011-07-04 16:25:18 +10001407 nv_wr32(dev, 0x610010, (disp->mem->vinst >> 8) | 9);
Ben Skeggs270a5742011-07-05 14:16:05 +10001408 nv_mask(dev, 0x6100b0, 0x00000307, 0x00000307);
Ben Skeggs26f6d882011-07-04 16:25:18 +10001409
1410 /* init master */
Ben Skeggs51beb422011-07-05 10:33:08 +10001411 nv_wr32(dev, 0x610494, (disp->evo[0].handle >> 8) | 3);
Ben Skeggs26f6d882011-07-04 16:25:18 +10001412 nv_wr32(dev, 0x610498, 0x00010000);
Ben Skeggsefd272a2011-07-05 11:58:58 +10001413 nv_wr32(dev, 0x61049c, 0x00000001);
Ben Skeggs26f6d882011-07-04 16:25:18 +10001414 nv_mask(dev, 0x610490, 0x00000010, 0x00000010);
1415 nv_wr32(dev, 0x640000, 0x00000000);
1416 nv_wr32(dev, 0x610490, 0x01000013);
1417 if (!nv_wait(dev, 0x610490, 0x80000000, 0x00000000)) {
1418 NV_ERROR(dev, "PDISP: master 0x%08x\n",
1419 nv_rd32(dev, 0x610490));
1420 return -EBUSY;
1421 }
1422 nv_mask(dev, 0x610090, 0x00000001, 0x00000001);
1423 nv_mask(dev, 0x6100a0, 0x00000001, 0x00000001);
1424
1425 /* init cursors */
1426 for (i = 13; i <= 14; i++) {
1427 nv_wr32(dev, 0x610490 + (i * 0x10), 0x00000001);
1428 if (!nv_wait(dev, 0x610490 + (i * 0x10), 0x00010000, 0x00010000)) {
1429 NV_ERROR(dev, "PDISP: curs%d 0x%08x\n", i,
1430 nv_rd32(dev, 0x610490 + (i * 0x10)));
1431 return -EBUSY;
1432 }
1433
1434 nv_mask(dev, 0x610090, 1 << i, 1 << i);
1435 nv_mask(dev, 0x6100a0, 1 << i, 1 << i);
1436 }
1437
Ben Skeggsefd272a2011-07-05 11:58:58 +10001438 push = evo_wait(dev, 0, 32);
1439 if (!push)
1440 return -EBUSY;
1441 evo_mthd(push, 0x0088, 1);
Ben Skeggs37b034a2011-07-08 14:43:19 +10001442 evo_data(push, NvEvoSync);
Ben Skeggsefd272a2011-07-05 11:58:58 +10001443 evo_mthd(push, 0x0084, 1);
1444 evo_data(push, 0x00000000);
1445 evo_mthd(push, 0x0084, 1);
1446 evo_data(push, 0x80000000);
1447 evo_mthd(push, 0x008c, 1);
1448 evo_data(push, 0x00000000);
1449 evo_kick(push, dev, 0);
1450
Ben Skeggs26f6d882011-07-04 16:25:18 +10001451 return 0;
1452}
1453
1454void
1455nvd0_display_destroy(struct drm_device *dev)
1456{
1457 struct drm_nouveau_private *dev_priv = dev->dev_private;
1458 struct nvd0_display *disp = nvd0_display(dev);
Ben Skeggs51beb422011-07-05 10:33:08 +10001459 struct pci_dev *pdev = dev->pdev;
Ben Skeggs26f6d882011-07-04 16:25:18 +10001460
1461 nvd0_display_fini(dev);
1462
Ben Skeggs51beb422011-07-05 10:33:08 +10001463 pci_free_consistent(pdev, PAGE_SIZE, disp->evo[0].ptr, disp->evo[0].handle);
Ben Skeggs26f6d882011-07-04 16:25:18 +10001464 nouveau_gpuobj_ref(NULL, &disp->mem);
Ben Skeggs46005222011-07-05 11:01:13 +10001465 nouveau_irq_unregister(dev, 26);
Ben Skeggs51beb422011-07-05 10:33:08 +10001466
1467 dev_priv->engine.display.priv = NULL;
Ben Skeggs26f6d882011-07-04 16:25:18 +10001468 kfree(disp);
1469}
1470
1471int
1472nvd0_display_create(struct drm_device *dev)
1473{
1474 struct drm_nouveau_private *dev_priv = dev->dev_private;
Ben Skeggsefd272a2011-07-05 11:58:58 +10001475 struct nouveau_instmem_engine *pinstmem = &dev_priv->engine.instmem;
Ben Skeggs83fc0832011-07-05 13:08:40 +10001476 struct dcb_table *dcb = &dev_priv->vbios.dcb;
1477 struct drm_connector *connector, *tmp;
Ben Skeggs51beb422011-07-05 10:33:08 +10001478 struct pci_dev *pdev = dev->pdev;
Ben Skeggs26f6d882011-07-04 16:25:18 +10001479 struct nvd0_display *disp;
Ben Skeggs83fc0832011-07-05 13:08:40 +10001480 struct dcb_entry *dcbe;
1481 int ret, i;
Ben Skeggs26f6d882011-07-04 16:25:18 +10001482
1483 disp = kzalloc(sizeof(*disp), GFP_KERNEL);
1484 if (!disp)
1485 return -ENOMEM;
1486 dev_priv->engine.display.priv = disp;
1487
Ben Skeggs438d99e2011-07-05 16:48:06 +10001488 /* create crtc objects to represent the hw heads */
1489 for (i = 0; i < 2; i++) {
1490 ret = nvd0_crtc_create(dev, i);
1491 if (ret)
1492 goto out;
1493 }
1494
Ben Skeggs83fc0832011-07-05 13:08:40 +10001495 /* create encoder/connector objects based on VBIOS DCB table */
1496 for (i = 0, dcbe = &dcb->entry[0]; i < dcb->entries; i++, dcbe++) {
1497 connector = nouveau_connector_create(dev, dcbe->connector);
1498 if (IS_ERR(connector))
1499 continue;
1500
1501 if (dcbe->location != DCB_LOC_ON_CHIP) {
1502 NV_WARN(dev, "skipping off-chip encoder %d/%d\n",
1503 dcbe->type, ffs(dcbe->or) - 1);
1504 continue;
1505 }
1506
1507 switch (dcbe->type) {
1508 case OUTPUT_TMDS:
Ben Skeggs3b6d83d12011-07-08 12:52:14 +10001509 case OUTPUT_LVDS:
Ben Skeggs83fc0832011-07-05 13:08:40 +10001510 nvd0_sor_create(connector, dcbe);
1511 break;
Ben Skeggs8eaa9662011-07-06 15:25:47 +10001512 case OUTPUT_ANALOG:
1513 nvd0_dac_create(connector, dcbe);
1514 break;
Ben Skeggs83fc0832011-07-05 13:08:40 +10001515 default:
1516 NV_WARN(dev, "skipping unsupported encoder %d/%d\n",
1517 dcbe->type, ffs(dcbe->or) - 1);
1518 continue;
1519 }
1520 }
1521
1522 /* cull any connectors we created that don't have an encoder */
1523 list_for_each_entry_safe(connector, tmp, &dev->mode_config.connector_list, head) {
1524 if (connector->encoder_ids[0])
1525 continue;
1526
1527 NV_WARN(dev, "%s has no encoders, removing\n",
1528 drm_get_connector_name(connector));
1529 connector->funcs->destroy(connector);
1530 }
1531
Ben Skeggs46005222011-07-05 11:01:13 +10001532 /* setup interrupt handling */
Ben Skeggsf20ce962011-07-08 13:17:01 +10001533 tasklet_init(&disp->tasklet, nvd0_display_bh, (unsigned long)dev);
Ben Skeggs46005222011-07-05 11:01:13 +10001534 nouveau_irq_register(dev, 26, nvd0_display_intr);
1535
Ben Skeggs51beb422011-07-05 10:33:08 +10001536 /* hash table and dma objects for the memory areas we care about */
Ben Skeggsefd272a2011-07-05 11:58:58 +10001537 ret = nouveau_gpuobj_new(dev, NULL, 0x4000, 0x10000,
1538 NVOBJ_FLAG_ZERO_ALLOC, &disp->mem);
Ben Skeggs26f6d882011-07-04 16:25:18 +10001539 if (ret)
1540 goto out;
1541
Ben Skeggsefd272a2011-07-05 11:58:58 +10001542 nv_wo32(disp->mem, 0x1000, 0x00000049);
1543 nv_wo32(disp->mem, 0x1004, (disp->mem->vinst + 0x2000) >> 8);
1544 nv_wo32(disp->mem, 0x1008, (disp->mem->vinst + 0x2fff) >> 8);
1545 nv_wo32(disp->mem, 0x100c, 0x00000000);
1546 nv_wo32(disp->mem, 0x1010, 0x00000000);
1547 nv_wo32(disp->mem, 0x1014, 0x00000000);
Ben Skeggs37b034a2011-07-08 14:43:19 +10001548 nv_wo32(disp->mem, 0x0000, NvEvoSync);
Ben Skeggsefd272a2011-07-05 11:58:58 +10001549 nv_wo32(disp->mem, 0x0004, (0x1000 << 9) | 0x00000001);
1550
Ben Skeggsc0cc92a2011-07-06 11:40:45 +10001551 nv_wo32(disp->mem, 0x1020, 0x00000049);
Ben Skeggsefd272a2011-07-05 11:58:58 +10001552 nv_wo32(disp->mem, 0x1024, 0x00000000);
1553 nv_wo32(disp->mem, 0x1028, (dev_priv->vram_size - 1) >> 8);
1554 nv_wo32(disp->mem, 0x102c, 0x00000000);
1555 nv_wo32(disp->mem, 0x1030, 0x00000000);
1556 nv_wo32(disp->mem, 0x1034, 0x00000000);
Ben Skeggs37b034a2011-07-08 14:43:19 +10001557 nv_wo32(disp->mem, 0x0008, NvEvoVRAM);
Ben Skeggsefd272a2011-07-05 11:58:58 +10001558 nv_wo32(disp->mem, 0x000c, (0x1020 << 9) | 0x00000001);
1559
Ben Skeggsc0cc92a2011-07-06 11:40:45 +10001560 nv_wo32(disp->mem, 0x1040, 0x00000009);
1561 nv_wo32(disp->mem, 0x1044, 0x00000000);
1562 nv_wo32(disp->mem, 0x1048, (dev_priv->vram_size - 1) >> 8);
1563 nv_wo32(disp->mem, 0x104c, 0x00000000);
1564 nv_wo32(disp->mem, 0x1050, 0x00000000);
1565 nv_wo32(disp->mem, 0x1054, 0x00000000);
1566 nv_wo32(disp->mem, 0x0010, NvEvoVRAM_LP);
1567 nv_wo32(disp->mem, 0x0014, (0x1040 << 9) | 0x00000001);
1568
1569 nv_wo32(disp->mem, 0x1060, 0x0fe00009);
1570 nv_wo32(disp->mem, 0x1064, 0x00000000);
1571 nv_wo32(disp->mem, 0x1068, (dev_priv->vram_size - 1) >> 8);
1572 nv_wo32(disp->mem, 0x106c, 0x00000000);
1573 nv_wo32(disp->mem, 0x1070, 0x00000000);
1574 nv_wo32(disp->mem, 0x1074, 0x00000000);
1575 nv_wo32(disp->mem, 0x0018, NvEvoFB32);
1576 nv_wo32(disp->mem, 0x001c, (0x1060 << 9) | 0x00000001);
1577
Ben Skeggsefd272a2011-07-05 11:58:58 +10001578 pinstmem->flush(dev);
1579
Ben Skeggs51beb422011-07-05 10:33:08 +10001580 /* push buffers for evo channels */
1581 disp->evo[0].ptr =
1582 pci_alloc_consistent(pdev, PAGE_SIZE, &disp->evo[0].handle);
1583 if (!disp->evo[0].ptr) {
1584 ret = -ENOMEM;
1585 goto out;
1586 }
1587
Ben Skeggs26f6d882011-07-04 16:25:18 +10001588 ret = nvd0_display_init(dev);
1589 if (ret)
1590 goto out;
1591
1592out:
1593 if (ret)
1594 nvd0_display_destroy(dev);
1595 return ret;
1596}