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