drm/nv50/devinit: reverse the logic for running encoder init scripts
[deliverable/linux.git] / drivers / gpu / drm / nouveau / core / engine / disp / nvd0.c
1 /*
2 * Copyright 2012 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
25 #include <core/object.h>
26 #include <core/parent.h>
27 #include <core/handle.h>
28 #include <core/class.h>
29
30 #include <engine/disp.h>
31
32 #include <subdev/timer.h>
33 #include <subdev/fb.h>
34 #include <subdev/clock.h>
35
36 #include <subdev/bios.h>
37 #include <subdev/bios/dcb.h>
38 #include <subdev/bios/disp.h>
39 #include <subdev/bios/init.h>
40 #include <subdev/bios/pll.h>
41
42 #include "nv50.h"
43
44 /*******************************************************************************
45 * EVO DMA channel base class
46 ******************************************************************************/
47
48 static int
49 nvd0_disp_dmac_object_attach(struct nouveau_object *parent,
50 struct nouveau_object *object, u32 name)
51 {
52 struct nv50_disp_base *base = (void *)parent->parent;
53 struct nv50_disp_chan *chan = (void *)parent;
54 u32 addr = nv_gpuobj(object)->node->offset;
55 u32 data = (chan->chid << 27) | (addr << 9) | 0x00000001;
56 return nouveau_ramht_insert(base->ramht, chan->chid, name, data);
57 }
58
59 static void
60 nvd0_disp_dmac_object_detach(struct nouveau_object *parent, int cookie)
61 {
62 struct nv50_disp_base *base = (void *)parent->parent;
63 nouveau_ramht_remove(base->ramht, cookie);
64 }
65
66 static int
67 nvd0_disp_dmac_init(struct nouveau_object *object)
68 {
69 struct nv50_disp_priv *priv = (void *)object->engine;
70 struct nv50_disp_dmac *dmac = (void *)object;
71 int chid = dmac->base.chid;
72 int ret;
73
74 ret = nv50_disp_chan_init(&dmac->base);
75 if (ret)
76 return ret;
77
78 /* enable error reporting */
79 nv_mask(priv, 0x610090, 0x00000001 << chid, 0x00000001 << chid);
80 nv_mask(priv, 0x6100a0, 0x00000001 << chid, 0x00000001 << chid);
81
82 /* initialise channel for dma command submission */
83 nv_wr32(priv, 0x610494 + (chid * 0x0010), dmac->push);
84 nv_wr32(priv, 0x610498 + (chid * 0x0010), 0x00010000);
85 nv_wr32(priv, 0x61049c + (chid * 0x0010), 0x00000001);
86 nv_mask(priv, 0x610490 + (chid * 0x0010), 0x00000010, 0x00000010);
87 nv_wr32(priv, 0x640000 + (chid * 0x1000), 0x00000000);
88 nv_wr32(priv, 0x610490 + (chid * 0x0010), 0x00000013);
89
90 /* wait for it to go inactive */
91 if (!nv_wait(priv, 0x610490 + (chid * 0x10), 0x80000000, 0x00000000)) {
92 nv_error(dmac, "init: 0x%08x\n",
93 nv_rd32(priv, 0x610490 + (chid * 0x10)));
94 return -EBUSY;
95 }
96
97 return 0;
98 }
99
100 static int
101 nvd0_disp_dmac_fini(struct nouveau_object *object, bool suspend)
102 {
103 struct nv50_disp_priv *priv = (void *)object->engine;
104 struct nv50_disp_dmac *dmac = (void *)object;
105 int chid = dmac->base.chid;
106
107 /* deactivate channel */
108 nv_mask(priv, 0x610490 + (chid * 0x0010), 0x00001010, 0x00001000);
109 nv_mask(priv, 0x610490 + (chid * 0x0010), 0x00000003, 0x00000000);
110 if (!nv_wait(priv, 0x610490 + (chid * 0x10), 0x001e0000, 0x00000000)) {
111 nv_error(dmac, "fini: 0x%08x\n",
112 nv_rd32(priv, 0x610490 + (chid * 0x10)));
113 if (suspend)
114 return -EBUSY;
115 }
116
117 /* disable error reporting */
118 nv_mask(priv, 0x610090, 0x00000001 << chid, 0x00000000);
119 nv_mask(priv, 0x6100a0, 0x00000001 << chid, 0x00000000);
120
121 return nv50_disp_chan_fini(&dmac->base, suspend);
122 }
123
124 /*******************************************************************************
125 * EVO master channel object
126 ******************************************************************************/
127
128 static int
129 nvd0_disp_mast_ctor(struct nouveau_object *parent,
130 struct nouveau_object *engine,
131 struct nouveau_oclass *oclass, void *data, u32 size,
132 struct nouveau_object **pobject)
133 {
134 struct nv50_display_mast_class *args = data;
135 struct nv50_disp_dmac *mast;
136 int ret;
137
138 if (size < sizeof(*args))
139 return -EINVAL;
140
141 ret = nv50_disp_dmac_create_(parent, engine, oclass, args->pushbuf,
142 0, sizeof(*mast), (void **)&mast);
143 *pobject = nv_object(mast);
144 if (ret)
145 return ret;
146
147 nv_parent(mast)->object_attach = nvd0_disp_dmac_object_attach;
148 nv_parent(mast)->object_detach = nvd0_disp_dmac_object_detach;
149 return 0;
150 }
151
152 static int
153 nvd0_disp_mast_init(struct nouveau_object *object)
154 {
155 struct nv50_disp_priv *priv = (void *)object->engine;
156 struct nv50_disp_dmac *mast = (void *)object;
157 int ret;
158
159 ret = nv50_disp_chan_init(&mast->base);
160 if (ret)
161 return ret;
162
163 /* enable error reporting */
164 nv_mask(priv, 0x610090, 0x00000001, 0x00000001);
165 nv_mask(priv, 0x6100a0, 0x00000001, 0x00000001);
166
167 /* initialise channel for dma command submission */
168 nv_wr32(priv, 0x610494, mast->push);
169 nv_wr32(priv, 0x610498, 0x00010000);
170 nv_wr32(priv, 0x61049c, 0x00000001);
171 nv_mask(priv, 0x610490, 0x00000010, 0x00000010);
172 nv_wr32(priv, 0x640000, 0x00000000);
173 nv_wr32(priv, 0x610490, 0x01000013);
174
175 /* wait for it to go inactive */
176 if (!nv_wait(priv, 0x610490, 0x80000000, 0x00000000)) {
177 nv_error(mast, "init: 0x%08x\n", nv_rd32(priv, 0x610490));
178 return -EBUSY;
179 }
180
181 return 0;
182 }
183
184 static int
185 nvd0_disp_mast_fini(struct nouveau_object *object, bool suspend)
186 {
187 struct nv50_disp_priv *priv = (void *)object->engine;
188 struct nv50_disp_dmac *mast = (void *)object;
189
190 /* deactivate channel */
191 nv_mask(priv, 0x610490, 0x00000010, 0x00000000);
192 nv_mask(priv, 0x610490, 0x00000003, 0x00000000);
193 if (!nv_wait(priv, 0x610490, 0x001e0000, 0x00000000)) {
194 nv_error(mast, "fini: 0x%08x\n", nv_rd32(priv, 0x610490));
195 if (suspend)
196 return -EBUSY;
197 }
198
199 /* disable error reporting */
200 nv_mask(priv, 0x610090, 0x00000001, 0x00000000);
201 nv_mask(priv, 0x6100a0, 0x00000001, 0x00000000);
202
203 return nv50_disp_chan_fini(&mast->base, suspend);
204 }
205
206 struct nouveau_ofuncs
207 nvd0_disp_mast_ofuncs = {
208 .ctor = nvd0_disp_mast_ctor,
209 .dtor = nv50_disp_dmac_dtor,
210 .init = nvd0_disp_mast_init,
211 .fini = nvd0_disp_mast_fini,
212 .rd32 = nv50_disp_chan_rd32,
213 .wr32 = nv50_disp_chan_wr32,
214 };
215
216 /*******************************************************************************
217 * EVO sync channel objects
218 ******************************************************************************/
219
220 static int
221 nvd0_disp_sync_ctor(struct nouveau_object *parent,
222 struct nouveau_object *engine,
223 struct nouveau_oclass *oclass, void *data, u32 size,
224 struct nouveau_object **pobject)
225 {
226 struct nv50_display_sync_class *args = data;
227 struct nv50_disp_priv *priv = (void *)engine;
228 struct nv50_disp_dmac *dmac;
229 int ret;
230
231 if (size < sizeof(*args) || args->head >= priv->head.nr)
232 return -EINVAL;
233
234 ret = nv50_disp_dmac_create_(parent, engine, oclass, args->pushbuf,
235 1 + args->head, sizeof(*dmac),
236 (void **)&dmac);
237 *pobject = nv_object(dmac);
238 if (ret)
239 return ret;
240
241 nv_parent(dmac)->object_attach = nvd0_disp_dmac_object_attach;
242 nv_parent(dmac)->object_detach = nvd0_disp_dmac_object_detach;
243 return 0;
244 }
245
246 struct nouveau_ofuncs
247 nvd0_disp_sync_ofuncs = {
248 .ctor = nvd0_disp_sync_ctor,
249 .dtor = nv50_disp_dmac_dtor,
250 .init = nvd0_disp_dmac_init,
251 .fini = nvd0_disp_dmac_fini,
252 .rd32 = nv50_disp_chan_rd32,
253 .wr32 = nv50_disp_chan_wr32,
254 };
255
256 /*******************************************************************************
257 * EVO overlay channel objects
258 ******************************************************************************/
259
260 static int
261 nvd0_disp_ovly_ctor(struct nouveau_object *parent,
262 struct nouveau_object *engine,
263 struct nouveau_oclass *oclass, void *data, u32 size,
264 struct nouveau_object **pobject)
265 {
266 struct nv50_display_ovly_class *args = data;
267 struct nv50_disp_priv *priv = (void *)engine;
268 struct nv50_disp_dmac *dmac;
269 int ret;
270
271 if (size < sizeof(*args) || args->head >= priv->head.nr)
272 return -EINVAL;
273
274 ret = nv50_disp_dmac_create_(parent, engine, oclass, args->pushbuf,
275 5 + args->head, sizeof(*dmac),
276 (void **)&dmac);
277 *pobject = nv_object(dmac);
278 if (ret)
279 return ret;
280
281 nv_parent(dmac)->object_attach = nvd0_disp_dmac_object_attach;
282 nv_parent(dmac)->object_detach = nvd0_disp_dmac_object_detach;
283 return 0;
284 }
285
286 struct nouveau_ofuncs
287 nvd0_disp_ovly_ofuncs = {
288 .ctor = nvd0_disp_ovly_ctor,
289 .dtor = nv50_disp_dmac_dtor,
290 .init = nvd0_disp_dmac_init,
291 .fini = nvd0_disp_dmac_fini,
292 .rd32 = nv50_disp_chan_rd32,
293 .wr32 = nv50_disp_chan_wr32,
294 };
295
296 /*******************************************************************************
297 * EVO PIO channel base class
298 ******************************************************************************/
299
300 static int
301 nvd0_disp_pioc_create_(struct nouveau_object *parent,
302 struct nouveau_object *engine,
303 struct nouveau_oclass *oclass, int chid,
304 int length, void **pobject)
305 {
306 return nv50_disp_chan_create_(parent, engine, oclass, chid,
307 length, pobject);
308 }
309
310 static void
311 nvd0_disp_pioc_dtor(struct nouveau_object *object)
312 {
313 struct nv50_disp_pioc *pioc = (void *)object;
314 nv50_disp_chan_destroy(&pioc->base);
315 }
316
317 static int
318 nvd0_disp_pioc_init(struct nouveau_object *object)
319 {
320 struct nv50_disp_priv *priv = (void *)object->engine;
321 struct nv50_disp_pioc *pioc = (void *)object;
322 int chid = pioc->base.chid;
323 int ret;
324
325 ret = nv50_disp_chan_init(&pioc->base);
326 if (ret)
327 return ret;
328
329 /* enable error reporting */
330 nv_mask(priv, 0x610090, 0x00000001 << chid, 0x00000001 << chid);
331 nv_mask(priv, 0x6100a0, 0x00000001 << chid, 0x00000001 << chid);
332
333 /* activate channel */
334 nv_wr32(priv, 0x610490 + (chid * 0x10), 0x00000001);
335 if (!nv_wait(priv, 0x610490 + (chid * 0x10), 0x00030000, 0x00010000)) {
336 nv_error(pioc, "init: 0x%08x\n",
337 nv_rd32(priv, 0x610490 + (chid * 0x10)));
338 return -EBUSY;
339 }
340
341 return 0;
342 }
343
344 static int
345 nvd0_disp_pioc_fini(struct nouveau_object *object, bool suspend)
346 {
347 struct nv50_disp_priv *priv = (void *)object->engine;
348 struct nv50_disp_pioc *pioc = (void *)object;
349 int chid = pioc->base.chid;
350
351 nv_mask(priv, 0x610490 + (chid * 0x10), 0x00000001, 0x00000000);
352 if (!nv_wait(priv, 0x610490 + (chid * 0x10), 0x00030000, 0x00000000)) {
353 nv_error(pioc, "timeout: 0x%08x\n",
354 nv_rd32(priv, 0x610490 + (chid * 0x10)));
355 if (suspend)
356 return -EBUSY;
357 }
358
359 /* disable error reporting */
360 nv_mask(priv, 0x610090, 0x00000001 << chid, 0x00000000);
361 nv_mask(priv, 0x6100a0, 0x00000001 << chid, 0x00000000);
362
363 return nv50_disp_chan_fini(&pioc->base, suspend);
364 }
365
366 /*******************************************************************************
367 * EVO immediate overlay channel objects
368 ******************************************************************************/
369
370 static int
371 nvd0_disp_oimm_ctor(struct nouveau_object *parent,
372 struct nouveau_object *engine,
373 struct nouveau_oclass *oclass, void *data, u32 size,
374 struct nouveau_object **pobject)
375 {
376 struct nv50_display_oimm_class *args = data;
377 struct nv50_disp_priv *priv = (void *)engine;
378 struct nv50_disp_pioc *pioc;
379 int ret;
380
381 if (size < sizeof(*args) || args->head >= priv->head.nr)
382 return -EINVAL;
383
384 ret = nvd0_disp_pioc_create_(parent, engine, oclass, 9 + args->head,
385 sizeof(*pioc), (void **)&pioc);
386 *pobject = nv_object(pioc);
387 if (ret)
388 return ret;
389
390 return 0;
391 }
392
393 struct nouveau_ofuncs
394 nvd0_disp_oimm_ofuncs = {
395 .ctor = nvd0_disp_oimm_ctor,
396 .dtor = nvd0_disp_pioc_dtor,
397 .init = nvd0_disp_pioc_init,
398 .fini = nvd0_disp_pioc_fini,
399 .rd32 = nv50_disp_chan_rd32,
400 .wr32 = nv50_disp_chan_wr32,
401 };
402
403 /*******************************************************************************
404 * EVO cursor channel objects
405 ******************************************************************************/
406
407 static int
408 nvd0_disp_curs_ctor(struct nouveau_object *parent,
409 struct nouveau_object *engine,
410 struct nouveau_oclass *oclass, void *data, u32 size,
411 struct nouveau_object **pobject)
412 {
413 struct nv50_display_curs_class *args = data;
414 struct nv50_disp_priv *priv = (void *)engine;
415 struct nv50_disp_pioc *pioc;
416 int ret;
417
418 if (size < sizeof(*args) || args->head >= priv->head.nr)
419 return -EINVAL;
420
421 ret = nvd0_disp_pioc_create_(parent, engine, oclass, 13 + args->head,
422 sizeof(*pioc), (void **)&pioc);
423 *pobject = nv_object(pioc);
424 if (ret)
425 return ret;
426
427 return 0;
428 }
429
430 struct nouveau_ofuncs
431 nvd0_disp_curs_ofuncs = {
432 .ctor = nvd0_disp_curs_ctor,
433 .dtor = nvd0_disp_pioc_dtor,
434 .init = nvd0_disp_pioc_init,
435 .fini = nvd0_disp_pioc_fini,
436 .rd32 = nv50_disp_chan_rd32,
437 .wr32 = nv50_disp_chan_wr32,
438 };
439
440 /*******************************************************************************
441 * Base display object
442 ******************************************************************************/
443
444 static void
445 nvd0_disp_base_vblank_enable(struct nouveau_event *event, int head)
446 {
447 nv_mask(event->priv, 0x6100c0 + (head * 0x800), 0x00000001, 0x00000001);
448 }
449
450 static void
451 nvd0_disp_base_vblank_disable(struct nouveau_event *event, int head)
452 {
453 nv_mask(event->priv, 0x6100c0 + (head * 0x800), 0x00000001, 0x00000000);
454 }
455
456 static int
457 nvd0_disp_base_ctor(struct nouveau_object *parent,
458 struct nouveau_object *engine,
459 struct nouveau_oclass *oclass, void *data, u32 size,
460 struct nouveau_object **pobject)
461 {
462 struct nv50_disp_priv *priv = (void *)engine;
463 struct nv50_disp_base *base;
464 int ret;
465
466 ret = nouveau_parent_create(parent, engine, oclass, 0,
467 priv->sclass, 0, &base);
468 *pobject = nv_object(base);
469 if (ret)
470 return ret;
471
472 priv->base.vblank->priv = priv;
473 priv->base.vblank->enable = nvd0_disp_base_vblank_enable;
474 priv->base.vblank->disable = nvd0_disp_base_vblank_disable;
475
476 return nouveau_ramht_new(parent, parent, 0x1000, 0, &base->ramht);
477 }
478
479 static void
480 nvd0_disp_base_dtor(struct nouveau_object *object)
481 {
482 struct nv50_disp_base *base = (void *)object;
483 nouveau_ramht_ref(NULL, &base->ramht);
484 nouveau_parent_destroy(&base->base);
485 }
486
487 static int
488 nvd0_disp_base_init(struct nouveau_object *object)
489 {
490 struct nv50_disp_priv *priv = (void *)object->engine;
491 struct nv50_disp_base *base = (void *)object;
492 int ret, i;
493 u32 tmp;
494
495 ret = nouveau_parent_init(&base->base);
496 if (ret)
497 return ret;
498
499 /* The below segments of code copying values from one register to
500 * another appear to inform EVO of the display capabilities or
501 * something similar.
502 */
503
504 /* ... CRTC caps */
505 for (i = 0; i < priv->head.nr; i++) {
506 tmp = nv_rd32(priv, 0x616104 + (i * 0x800));
507 nv_wr32(priv, 0x6101b4 + (i * 0x800), tmp);
508 tmp = nv_rd32(priv, 0x616108 + (i * 0x800));
509 nv_wr32(priv, 0x6101b8 + (i * 0x800), tmp);
510 tmp = nv_rd32(priv, 0x61610c + (i * 0x800));
511 nv_wr32(priv, 0x6101bc + (i * 0x800), tmp);
512 }
513
514 /* ... DAC caps */
515 for (i = 0; i < priv->dac.nr; i++) {
516 tmp = nv_rd32(priv, 0x61a000 + (i * 0x800));
517 nv_wr32(priv, 0x6101c0 + (i * 0x800), tmp);
518 }
519
520 /* ... SOR caps */
521 for (i = 0; i < priv->sor.nr; i++) {
522 tmp = nv_rd32(priv, 0x61c000 + (i * 0x800));
523 nv_wr32(priv, 0x6301c4 + (i * 0x800), tmp);
524 }
525
526 /* steal display away from vbios, or something like that */
527 if (nv_rd32(priv, 0x6100ac) & 0x00000100) {
528 nv_wr32(priv, 0x6100ac, 0x00000100);
529 nv_mask(priv, 0x6194e8, 0x00000001, 0x00000000);
530 if (!nv_wait(priv, 0x6194e8, 0x00000002, 0x00000000)) {
531 nv_error(priv, "timeout acquiring display\n");
532 return -EBUSY;
533 }
534 }
535
536 /* point at display engine memory area (hash table, objects) */
537 nv_wr32(priv, 0x610010, (nv_gpuobj(object->parent)->addr >> 8) | 9);
538
539 /* enable supervisor interrupts, disable everything else */
540 nv_wr32(priv, 0x610090, 0x00000000);
541 nv_wr32(priv, 0x6100a0, 0x00000000);
542 nv_wr32(priv, 0x6100b0, 0x00000307);
543
544 return 0;
545 }
546
547 static int
548 nvd0_disp_base_fini(struct nouveau_object *object, bool suspend)
549 {
550 struct nv50_disp_priv *priv = (void *)object->engine;
551 struct nv50_disp_base *base = (void *)object;
552
553 /* disable all interrupts */
554 nv_wr32(priv, 0x6100b0, 0x00000000);
555
556 return nouveau_parent_fini(&base->base, suspend);
557 }
558
559 struct nouveau_ofuncs
560 nvd0_disp_base_ofuncs = {
561 .ctor = nvd0_disp_base_ctor,
562 .dtor = nvd0_disp_base_dtor,
563 .init = nvd0_disp_base_init,
564 .fini = nvd0_disp_base_fini,
565 };
566
567 static struct nouveau_oclass
568 nvd0_disp_base_oclass[] = {
569 { NVD0_DISP_CLASS, &nvd0_disp_base_ofuncs, nva3_disp_base_omthds },
570 {}
571 };
572
573 static struct nouveau_oclass
574 nvd0_disp_sclass[] = {
575 { NVD0_DISP_MAST_CLASS, &nvd0_disp_mast_ofuncs },
576 { NVD0_DISP_SYNC_CLASS, &nvd0_disp_sync_ofuncs },
577 { NVD0_DISP_OVLY_CLASS, &nvd0_disp_ovly_ofuncs },
578 { NVD0_DISP_OIMM_CLASS, &nvd0_disp_oimm_ofuncs },
579 { NVD0_DISP_CURS_CLASS, &nvd0_disp_curs_ofuncs },
580 {}
581 };
582
583 /*******************************************************************************
584 * Display engine implementation
585 ******************************************************************************/
586
587 static u16
588 exec_lookup(struct nv50_disp_priv *priv, int head, int outp, u32 ctrl,
589 struct dcb_output *dcb, u8 *ver, u8 *hdr, u8 *cnt, u8 *len,
590 struct nvbios_outp *info)
591 {
592 struct nouveau_bios *bios = nouveau_bios(priv);
593 u16 mask, type, data;
594
595 if (outp < 4) {
596 type = DCB_OUTPUT_ANALOG;
597 mask = 0;
598 } else {
599 outp -= 4;
600 switch (ctrl & 0x00000f00) {
601 case 0x00000000: type = DCB_OUTPUT_LVDS; mask = 1; break;
602 case 0x00000100: type = DCB_OUTPUT_TMDS; mask = 1; break;
603 case 0x00000200: type = DCB_OUTPUT_TMDS; mask = 2; break;
604 case 0x00000500: type = DCB_OUTPUT_TMDS; mask = 3; break;
605 case 0x00000800: type = DCB_OUTPUT_DP; mask = 1; break;
606 case 0x00000900: type = DCB_OUTPUT_DP; mask = 2; break;
607 default:
608 nv_error(priv, "unknown SOR mc 0x%08x\n", ctrl);
609 return 0x0000;
610 }
611 dcb->sorconf.link = mask;
612 }
613
614 mask = 0x00c0 & (mask << 6);
615 mask |= 0x0001 << outp;
616 mask |= 0x0100 << head;
617
618 data = dcb_outp_match(bios, type, mask, ver, hdr, dcb);
619 if (!data)
620 return 0x0000;
621
622 return nvbios_outp_match(bios, type, mask, ver, hdr, cnt, len, info);
623 }
624
625 static bool
626 exec_script(struct nv50_disp_priv *priv, int head, int outp, u32 ctrl, int id)
627 {
628 struct nouveau_bios *bios = nouveau_bios(priv);
629 struct nvbios_outp info;
630 struct dcb_output dcb;
631 u8 ver, hdr, cnt, len;
632 u16 data;
633
634 data = exec_lookup(priv, head, outp, ctrl, &dcb, &ver, &hdr, &cnt, &len, &info);
635 if (data) {
636 struct nvbios_init init = {
637 .subdev = nv_subdev(priv),
638 .bios = bios,
639 .offset = info.script[id],
640 .outp = &dcb,
641 .crtc = head,
642 .execute = 1,
643 };
644
645 return nvbios_exec(&init) == 0;
646 }
647
648 return false;
649 }
650
651 static u32
652 exec_clkcmp(struct nv50_disp_priv *priv, int head, int outp,
653 u32 ctrl, int id, u32 pclk)
654 {
655 struct nouveau_bios *bios = nouveau_bios(priv);
656 struct nvbios_outp info1;
657 struct nvbios_ocfg info2;
658 struct dcb_output dcb;
659 u8 ver, hdr, cnt, len;
660 u16 data, conf;
661
662 data = exec_lookup(priv, head, outp, ctrl, &dcb, &ver, &hdr, &cnt, &len, &info1);
663 if (data == 0x0000)
664 return false;
665
666 switch (dcb.type) {
667 case DCB_OUTPUT_TMDS:
668 conf = (ctrl & 0x00000f00) >> 8;
669 if (pclk >= 165000)
670 conf |= 0x0100;
671 break;
672 case DCB_OUTPUT_LVDS:
673 conf = priv->sor.lvdsconf;
674 break;
675 case DCB_OUTPUT_DP:
676 conf = (ctrl & 0x00000f00) >> 8;
677 break;
678 case DCB_OUTPUT_ANALOG:
679 default:
680 conf = 0x00ff;
681 break;
682 }
683
684 data = nvbios_ocfg_match(bios, data, conf, &ver, &hdr, &cnt, &len, &info2);
685 if (data) {
686 data = nvbios_oclk_match(bios, info2.clkcmp[id], pclk);
687 if (data) {
688 struct nvbios_init init = {
689 .subdev = nv_subdev(priv),
690 .bios = bios,
691 .offset = data,
692 .outp = &dcb,
693 .crtc = head,
694 .execute = 1,
695 };
696
697 if (nvbios_exec(&init))
698 return 0x0000;
699 return conf;
700 }
701 }
702
703 return 0x0000;
704 }
705
706 static void
707 nvd0_display_unk1_handler(struct nv50_disp_priv *priv, u32 head, u32 mask)
708 {
709 int i;
710
711 for (i = 0; mask && i < 8; i++) {
712 u32 mcc = nv_rd32(priv, 0x640180 + (i * 0x20));
713 if (mcc & (1 << head))
714 exec_script(priv, head, i, mcc, 1);
715 }
716
717 nv_wr32(priv, 0x6101d4, 0x00000000);
718 nv_wr32(priv, 0x6109d4, 0x00000000);
719 nv_wr32(priv, 0x6101d0, 0x80000000);
720 }
721
722 static void
723 nvd0_display_unk2_calc_tu(struct nv50_disp_priv *priv, int head, int or)
724 {
725 const u32 ctrl = nv_rd32(priv, 0x660200 + (or * 0x020));
726 const u32 conf = nv_rd32(priv, 0x660404 + (head * 0x300));
727 const u32 pclk = nv_rd32(priv, 0x660450 + (head * 0x300)) / 1000;
728 const u32 link = ((ctrl & 0xf00) == 0x800) ? 0 : 1;
729 const u32 hoff = (head * 0x800);
730 const u32 soff = ( or * 0x800);
731 const u32 loff = (link * 0x080) + soff;
732 const u32 symbol = 100000;
733 const u32 TU = 64;
734 u32 dpctrl = nv_rd32(priv, 0x61c10c + loff) & 0x000f0000;
735 u32 clksor = nv_rd32(priv, 0x612300 + soff);
736 u32 datarate, link_nr, link_bw, bits;
737 u64 ratio, value;
738
739 if ((conf & 0x3c0) == 0x180) bits = 30;
740 else if ((conf & 0x3c0) == 0x140) bits = 24;
741 else bits = 18;
742 datarate = (pclk * bits) / 8;
743
744 if (dpctrl > 0x00030000) link_nr = 4;
745 else if (dpctrl > 0x00010000) link_nr = 2;
746 else link_nr = 1;
747
748 link_bw = (clksor & 0x007c0000) >> 18;
749 link_bw *= 27000;
750
751 ratio = datarate;
752 ratio *= symbol;
753 do_div(ratio, link_nr * link_bw);
754
755 value = (symbol - ratio) * TU;
756 value *= ratio;
757 do_div(value, symbol);
758 do_div(value, symbol);
759
760 value += 5;
761 value |= 0x08000000;
762
763 nv_wr32(priv, 0x616610 + hoff, value);
764 }
765
766 static void
767 nvd0_display_unk2_handler(struct nv50_disp_priv *priv, u32 head, u32 mask)
768 {
769 u32 pclk;
770 int i;
771
772 for (i = 0; mask && i < 8; i++) {
773 u32 mcc = nv_rd32(priv, 0x640180 + (i * 0x20));
774 if (mcc & (1 << head))
775 exec_script(priv, head, i, mcc, 2);
776 }
777
778 pclk = nv_rd32(priv, 0x660450 + (head * 0x300)) / 1000;
779 nv_debug(priv, "head %d pclk %d mask 0x%08x\n", head, pclk, mask);
780 if (pclk && (mask & 0x00010000)) {
781 struct nouveau_clock *clk = nouveau_clock(priv);
782 clk->pll_set(clk, PLL_VPLL0 + head, pclk);
783 }
784
785 nv_wr32(priv, 0x612200 + (head * 0x800), 0x00000000);
786
787 for (i = 0; mask && i < 8; i++) {
788 u32 mcp = nv_rd32(priv, 0x660180 + (i * 0x20)), cfg;
789 if (mcp & (1 << head)) {
790 if ((cfg = exec_clkcmp(priv, head, i, mcp, 0, pclk))) {
791 u32 addr, mask, data = 0x00000000;
792 if (i < 4) {
793 addr = 0x612280 + ((i - 0) * 0x800);
794 mask = 0xffffffff;
795 } else {
796 switch (mcp & 0x00000f00) {
797 case 0x00000800:
798 case 0x00000900:
799 nvd0_display_unk2_calc_tu(priv, head, i - 4);
800 break;
801 default:
802 break;
803 }
804
805 addr = 0x612300 + ((i - 4) * 0x800);
806 mask = 0x00000707;
807 if (cfg & 0x00000100)
808 data = 0x00000101;
809 }
810 nv_mask(priv, addr, mask, data);
811 }
812 break;
813 }
814 }
815
816 nv_wr32(priv, 0x6101d4, 0x00000000);
817 nv_wr32(priv, 0x6109d4, 0x00000000);
818 nv_wr32(priv, 0x6101d0, 0x80000000);
819 }
820
821 static void
822 nvd0_display_unk4_handler(struct nv50_disp_priv *priv, u32 head, u32 mask)
823 {
824 int pclk, i;
825
826 pclk = nv_rd32(priv, 0x660450 + (head * 0x300)) / 1000;
827
828 for (i = 0; mask && i < 8; i++) {
829 u32 mcp = nv_rd32(priv, 0x660180 + (i * 0x20));
830 if (mcp & (1 << head))
831 exec_clkcmp(priv, head, i, mcp, 1, pclk);
832 }
833
834 nv_wr32(priv, 0x6101d4, 0x00000000);
835 nv_wr32(priv, 0x6109d4, 0x00000000);
836 nv_wr32(priv, 0x6101d0, 0x80000000);
837 }
838
839 void
840 nvd0_disp_intr(struct nouveau_subdev *subdev)
841 {
842 struct nv50_disp_priv *priv = (void *)subdev;
843 u32 intr = nv_rd32(priv, 0x610088);
844 int i;
845
846 if (intr & 0x00000001) {
847 u32 stat = nv_rd32(priv, 0x61008c);
848 nv_wr32(priv, 0x61008c, stat);
849 intr &= ~0x00000001;
850 }
851
852 if (intr & 0x00000002) {
853 u32 stat = nv_rd32(priv, 0x61009c);
854 int chid = ffs(stat) - 1;
855 if (chid >= 0) {
856 u32 mthd = nv_rd32(priv, 0x6101f0 + (chid * 12));
857 u32 data = nv_rd32(priv, 0x6101f4 + (chid * 12));
858 u32 unkn = nv_rd32(priv, 0x6101f8 + (chid * 12));
859
860 nv_error(priv, "chid %d mthd 0x%04x data 0x%08x "
861 "0x%08x 0x%08x\n",
862 chid, (mthd & 0x0000ffc), data, mthd, unkn);
863 nv_wr32(priv, 0x61009c, (1 << chid));
864 nv_wr32(priv, 0x6101f0 + (chid * 12), 0x90000000);
865 }
866
867 intr &= ~0x00000002;
868 }
869
870 if (intr & 0x00100000) {
871 u32 stat = nv_rd32(priv, 0x6100ac);
872 u32 mask = 0, crtc = ~0;
873
874 while (!mask && ++crtc < priv->head.nr)
875 mask = nv_rd32(priv, 0x6101d4 + (crtc * 0x800));
876
877 if (stat & 0x00000001) {
878 nv_wr32(priv, 0x6100ac, 0x00000001);
879 nvd0_display_unk1_handler(priv, crtc, mask);
880 stat &= ~0x00000001;
881 }
882
883 if (stat & 0x00000002) {
884 nv_wr32(priv, 0x6100ac, 0x00000002);
885 nvd0_display_unk2_handler(priv, crtc, mask);
886 stat &= ~0x00000002;
887 }
888
889 if (stat & 0x00000004) {
890 nv_wr32(priv, 0x6100ac, 0x00000004);
891 nvd0_display_unk4_handler(priv, crtc, mask);
892 stat &= ~0x00000004;
893 }
894
895 if (stat) {
896 nv_info(priv, "unknown intr24 0x%08x\n", stat);
897 nv_wr32(priv, 0x6100ac, stat);
898 }
899
900 intr &= ~0x00100000;
901 }
902
903 for (i = 0; i < priv->head.nr; i++) {
904 u32 mask = 0x01000000 << i;
905 if (mask & intr) {
906 u32 stat = nv_rd32(priv, 0x6100bc + (i * 0x800));
907 if (stat & 0x00000001)
908 nouveau_event_trigger(priv->base.vblank, i);
909 nv_mask(priv, 0x6100bc + (i * 0x800), 0, 0);
910 nv_rd32(priv, 0x6100c0 + (i * 0x800));
911 }
912 }
913 }
914
915 static int
916 nvd0_disp_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
917 struct nouveau_oclass *oclass, void *data, u32 size,
918 struct nouveau_object **pobject)
919 {
920 struct nv50_disp_priv *priv;
921 int heads = nv_rd32(parent, 0x022448);
922 int ret;
923
924 ret = nouveau_disp_create(parent, engine, oclass, heads,
925 "PDISP", "display", &priv);
926 *pobject = nv_object(priv);
927 if (ret)
928 return ret;
929
930 nv_engine(priv)->sclass = nvd0_disp_base_oclass;
931 nv_engine(priv)->cclass = &nv50_disp_cclass;
932 nv_subdev(priv)->intr = nvd0_disp_intr;
933 priv->sclass = nvd0_disp_sclass;
934 priv->head.nr = heads;
935 priv->dac.nr = 3;
936 priv->sor.nr = 4;
937 priv->dac.power = nv50_dac_power;
938 priv->dac.sense = nv50_dac_sense;
939 priv->sor.power = nv50_sor_power;
940 priv->sor.hda_eld = nvd0_hda_eld;
941 priv->sor.hdmi = nvd0_hdmi_ctrl;
942 priv->sor.dp_train = nvd0_sor_dp_train;
943 priv->sor.dp_train_init = nv94_sor_dp_train_init;
944 priv->sor.dp_train_fini = nv94_sor_dp_train_fini;
945 priv->sor.dp_lnkctl = nvd0_sor_dp_lnkctl;
946 priv->sor.dp_drvctl = nvd0_sor_dp_drvctl;
947 return 0;
948 }
949
950 struct nouveau_oclass
951 nvd0_disp_oclass = {
952 .handle = NV_ENGINE(DISP, 0x90),
953 .ofuncs = &(struct nouveau_ofuncs) {
954 .ctor = nvd0_disp_ctor,
955 .dtor = _nouveau_disp_dtor,
956 .init = _nouveau_disp_init,
957 .fini = _nouveau_disp_fini,
958 },
959 };
This page took 0.06887 seconds and 6 git commands to generate.