nv50.c 22.8 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
/*
 * Copyright 2012 Red Hat Inc.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 * OTHER DEALINGS IN THE SOFTWARE.
 *
 * Authors: Ben Skeggs
 */
24
#include "nv50.h"
25
#include "rootnv50.h"
26

27
#include <core/client.h>
28
#include <core/enum.h>
29
#include <core/gpuobj.h>
30 31 32 33
#include <subdev/bios.h>
#include <subdev/bios/disp.h>
#include <subdev/bios/init.h>
#include <subdev/bios/pll.h>
34
#include <subdev/devinit.h>
35

36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98
static const struct nvkm_disp_oclass *
nv50_disp_root_(struct nvkm_disp *base)
{
	return nv50_disp(base)->func->root;
}

static int
nv50_disp_outp_internal_crt_(struct nvkm_disp *base, int index,
			     struct dcb_output *dcb, struct nvkm_output **poutp)
{
	struct nv50_disp *disp = nv50_disp(base);
	return disp->func->outp.internal.crt(base, index, dcb, poutp);
}

static int
nv50_disp_outp_internal_tmds_(struct nvkm_disp *base, int index,
			      struct dcb_output *dcb,
			      struct nvkm_output **poutp)
{
	struct nv50_disp *disp = nv50_disp(base);
	return disp->func->outp.internal.tmds(base, index, dcb, poutp);
}

static int
nv50_disp_outp_internal_lvds_(struct nvkm_disp *base, int index,
			      struct dcb_output *dcb,
			      struct nvkm_output **poutp)
{
	struct nv50_disp *disp = nv50_disp(base);
	return disp->func->outp.internal.lvds(base, index, dcb, poutp);
}

static int
nv50_disp_outp_internal_dp_(struct nvkm_disp *base, int index,
			    struct dcb_output *dcb, struct nvkm_output **poutp)
{
	struct nv50_disp *disp = nv50_disp(base);
	if (disp->func->outp.internal.dp)
		return disp->func->outp.internal.dp(base, index, dcb, poutp);
	return -ENODEV;
}

static int
nv50_disp_outp_external_tmds_(struct nvkm_disp *base, int index,
			      struct dcb_output *dcb,
			      struct nvkm_output **poutp)
{
	struct nv50_disp *disp = nv50_disp(base);
	if (disp->func->outp.external.tmds)
		return disp->func->outp.external.tmds(base, index, dcb, poutp);
	return -ENODEV;
}

static int
nv50_disp_outp_external_dp_(struct nvkm_disp *base, int index,
			    struct dcb_output *dcb, struct nvkm_output **poutp)
{
	struct nv50_disp *disp = nv50_disp(base);
	if (disp->func->outp.external.dp)
		return disp->func->outp.external.dp(base, index, dcb, poutp);
	return -ENODEV;
}

99
static void
100
nv50_disp_vblank_fini_(struct nvkm_disp *base, int head)
101
{
102 103
	struct nv50_disp *disp = nv50_disp(base);
	disp->func->head.vblank_fini(disp, head);
104 105 106
}

static void
107
nv50_disp_vblank_init_(struct nvkm_disp *base, int head)
108
{
109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125
	struct nv50_disp *disp = nv50_disp(base);
	disp->func->head.vblank_init(disp, head);
}

static void
nv50_disp_intr_(struct nvkm_disp *base)
{
	struct nv50_disp *disp = nv50_disp(base);
	disp->func->intr(disp);
}

static void *
nv50_disp_dtor_(struct nvkm_disp *base)
{
	struct nv50_disp *disp = nv50_disp(base);
	nvkm_event_fini(&disp->uevent);
	return disp;
126 127
}

128 129 130 131 132 133 134 135 136 137 138 139 140
static const struct nvkm_disp_func
nv50_disp_ = {
	.dtor = nv50_disp_dtor_,
	.intr = nv50_disp_intr_,
	.root = nv50_disp_root_,
	.outp.internal.crt = nv50_disp_outp_internal_crt_,
	.outp.internal.tmds = nv50_disp_outp_internal_tmds_,
	.outp.internal.lvds = nv50_disp_outp_internal_lvds_,
	.outp.internal.dp = nv50_disp_outp_internal_dp_,
	.outp.external.tmds = nv50_disp_outp_external_tmds_,
	.outp.external.dp = nv50_disp_outp_external_dp_,
	.head.vblank_init = nv50_disp_vblank_init_,
	.head.vblank_fini = nv50_disp_vblank_fini_,
141 142
};

143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176
int
nv50_disp_new_(const struct nv50_disp_func *func, struct nvkm_device *device,
	       int index, int heads, struct nvkm_disp **pdisp)
{
	struct nv50_disp *disp;
	int ret;

	if (!(disp = kzalloc(sizeof(*disp), GFP_KERNEL)))
		return -ENOMEM;
	INIT_WORK(&disp->supervisor, func->super);
	disp->func = func;
	*pdisp = &disp->base;

	ret = nvkm_disp_ctor(&nv50_disp_, device, index, heads, &disp->base);
	if (ret)
		return ret;

	return nvkm_event_init(func->uevent, 1, 1 + (heads * 4), &disp->uevent);
}

void
nv50_disp_vblank_fini(struct nv50_disp *disp, int head)
{
	struct nvkm_device *device = disp->base.engine.subdev.device;
	nvkm_mask(device, 0x61002c, (4 << head), 0);
}

void
nv50_disp_vblank_init(struct nv50_disp *disp, int head)
{
	struct nvkm_device *device = disp->base.engine.subdev.device;
	nvkm_mask(device, 0x61002c, (4 << head), (4 << head));
}

177
static const struct nvkm_enum
178 179 180 181 182 183 184
nv50_disp_intr_error_type[] = {
	{ 3, "ILLEGAL_MTHD" },
	{ 4, "INVALID_VALUE" },
	{ 5, "INVALID_STATE" },
	{ 7, "INVALID_HANDLE" },
	{}
};
185

186
static const struct nvkm_enum
187 188 189 190
nv50_disp_intr_error_code[] = {
	{ 0x00, "" },
	{}
};
191

192
static void
B
Ben Skeggs 已提交
193
nv50_disp_intr_error(struct nv50_disp *disp, int chid)
194
{
195 196
	struct nvkm_subdev *subdev = &disp->base.engine.subdev;
	struct nvkm_device *device = subdev->device;
197 198
	u32 data = nvkm_rd32(device, 0x610084 + (chid * 0x08));
	u32 addr = nvkm_rd32(device, 0x610080 + (chid * 0x08));
199 200 201
	u32 code = (addr & 0x00ff0000) >> 16;
	u32 type = (addr & 0x00007000) >> 12;
	u32 mthd = (addr & 0x00000ffc);
202
	const struct nvkm_enum *ec, *et;
203

204 205
	et = nvkm_enum_find(nv50_disp_intr_error_type, type);
	ec = nvkm_enum_find(nv50_disp_intr_error_code, code);
206

207 208 209 210
	nvkm_error(subdev,
		   "ERROR %d [%s] %02x [%s] chid %d mthd %04x data %08x\n",
		   type, et ? et->name : "", code, ec ? ec->name : "",
		   chid, mthd, data);
211

212
	if (chid < ARRAY_SIZE(disp->chan)) {
213 214
		switch (mthd) {
		case 0x0080:
215
			nv50_disp_chan_mthd(disp->chan[chid], NV_DBG_ERROR);
216 217 218 219 220 221
			break;
		default:
			break;
		}
	}

222 223
	nvkm_wr32(device, 0x610020, 0x00010000 << chid);
	nvkm_wr32(device, 0x610080 + (chid * 0x08), 0x90000000);
224 225
}

226
static struct nvkm_output *
B
Ben Skeggs 已提交
227
exec_lookup(struct nv50_disp *disp, int head, int or, u32 ctrl,
228
	    u32 *data, u8 *ver, u8 *hdr, u8 *cnt, u8 *len,
229 230
	    struct nvbios_outp *info)
{
231 232
	struct nvkm_subdev *subdev = &disp->base.engine.subdev;
	struct nvkm_bios *bios = subdev->device->bios;
233 234
	struct nvkm_output *outp;
	u16 mask, type;
235

236
	if (or < 4) {
237 238
		type = DCB_OUTPUT_ANALOG;
		mask = 0;
239
	} else
240
	if (or < 8) {
241 242 243 244 245 246 247 248
		switch (ctrl & 0x00000f00) {
		case 0x00000000: type = DCB_OUTPUT_LVDS; mask = 1; break;
		case 0x00000100: type = DCB_OUTPUT_TMDS; mask = 1; break;
		case 0x00000200: type = DCB_OUTPUT_TMDS; mask = 2; break;
		case 0x00000500: type = DCB_OUTPUT_TMDS; mask = 3; break;
		case 0x00000800: type = DCB_OUTPUT_DP; mask = 1; break;
		case 0x00000900: type = DCB_OUTPUT_DP; mask = 2; break;
		default:
249
			nvkm_error(subdev, "unknown SOR mc %08x\n", ctrl);
250
			return NULL;
251
		}
252
		or  -= 4;
253
	} else {
254
		or   = or - 8;
255 256 257
		type = 0x0010;
		mask = 0;
		switch (ctrl & 0x00000f00) {
B
Ben Skeggs 已提交
258
		case 0x00000000: type |= disp->pior.type[or]; break;
259
		default:
260
			nvkm_error(subdev, "unknown PIOR mc %08x\n", ctrl);
261
			return NULL;
262
		}
263 264 265
	}

	mask  = 0x00c0 & (mask << 6);
266
	mask |= 0x0001 << or;
267 268
	mask |= 0x0100 << head;

B
Ben Skeggs 已提交
269
	list_for_each_entry(outp, &disp->base.outp, head) {
270 271 272 273 274 275 276 277 278 279
		if ((outp->info.hasht & 0xff) == type &&
		    (outp->info.hashm & mask) == mask) {
			*data = nvbios_outp_match(bios, outp->info.hasht,
							outp->info.hashm,
						  ver, hdr, cnt, len, info);
			if (!*data)
				return NULL;
			return outp;
		}
	}
280

281
	return NULL;
282 283
}

284
static struct nvkm_output *
B
Ben Skeggs 已提交
285
exec_script(struct nv50_disp *disp, int head, int id)
286
{
287 288
	struct nvkm_subdev *subdev = &disp->base.engine.subdev;
	struct nvkm_device *device = subdev->device;
289
	struct nvkm_bios *bios = device->bios;
290
	struct nvkm_output *outp;
291 292
	struct nvbios_outp info;
	u8  ver, hdr, cnt, len;
293
	u32 data, ctrl = 0;
294
	u32 reg;
295 296
	int i;

297
	/* DAC */
298
	for (i = 0; !(ctrl & (1 << head)) && i < disp->func->dac.nr; i++)
299
		ctrl = nvkm_rd32(device, 0x610b5c + (i * 8));
300

301
	/* SOR */
302
	if (!(ctrl & (1 << head))) {
303 304 305
		if (device->chipset  < 0x90 ||
		    device->chipset == 0x92 ||
		    device->chipset == 0xa0) {
306
			reg = 0x610b74;
307
		} else {
308
			reg = 0x610798;
309
		}
310
		for (i = 0; !(ctrl & (1 << head)) && i < disp->func->sor.nr; i++)
311
			ctrl = nvkm_rd32(device, reg + (i * 8));
312
		i += 4;
313 314
	}

315 316
	/* PIOR */
	if (!(ctrl & (1 << head))) {
317
		for (i = 0; !(ctrl & (1 << head)) && i < disp->func->pior.nr; i++)
318
			ctrl = nvkm_rd32(device, 0x610b84 + (i * 8));
319 320 321
		i += 8;
	}

322
	if (!(ctrl & (1 << head)))
323
		return NULL;
324
	i--;
325

B
Ben Skeggs 已提交
326
	outp = exec_lookup(disp, head, i, ctrl, &data, &ver, &hdr, &cnt, &len, &info);
327
	if (outp) {
328
		struct nvbios_init init = {
329
			.subdev = subdev,
330 331
			.bios = bios,
			.offset = info.script[id],
332
			.outp = &outp->info,
333 334 335 336
			.crtc = head,
			.execute = 1,
		};

337
		nvbios_exec(&init);
338 339
	}

340
	return outp;
341 342
}

343
static struct nvkm_output *
B
Ben Skeggs 已提交
344
exec_clkcmp(struct nv50_disp *disp, int head, int id, u32 pclk, u32 *conf)
345
{
346 347
	struct nvkm_subdev *subdev = &disp->base.engine.subdev;
	struct nvkm_device *device = subdev->device;
348
	struct nvkm_bios *bios = device->bios;
349
	struct nvkm_output *outp;
350 351 352
	struct nvbios_outp info1;
	struct nvbios_ocfg info2;
	u8  ver, hdr, cnt, len;
353
	u32 data, ctrl = 0;
354
	u32 reg;
355 356
	int i;

357
	/* DAC */
358
	for (i = 0; !(ctrl & (1 << head)) && i < disp->func->dac.nr; i++)
359
		ctrl = nvkm_rd32(device, 0x610b58 + (i * 8));
360

361
	/* SOR */
362
	if (!(ctrl & (1 << head))) {
363 364 365
		if (device->chipset  < 0x90 ||
		    device->chipset == 0x92 ||
		    device->chipset == 0xa0) {
366
			reg = 0x610b70;
367
		} else {
368
			reg = 0x610794;
369
		}
370
		for (i = 0; !(ctrl & (1 << head)) && i < disp->func->sor.nr; i++)
371
			ctrl = nvkm_rd32(device, reg + (i * 8));
372
		i += 4;
373 374
	}

375 376
	/* PIOR */
	if (!(ctrl & (1 << head))) {
377
		for (i = 0; !(ctrl & (1 << head)) && i < disp->func->pior.nr; i++)
378
			ctrl = nvkm_rd32(device, 0x610b80 + (i * 8));
379 380 381
		i += 8;
	}

382
	if (!(ctrl & (1 << head)))
383
		return NULL;
384
	i--;
385

B
Ben Skeggs 已提交
386
	outp = exec_lookup(disp, head, i, ctrl, &data, &ver, &hdr, &cnt, &len, &info1);
387
	if (!outp)
388
		return NULL;
389

390 391
	if (outp->info.location == 0) {
		switch (outp->info.type) {
392
		case DCB_OUTPUT_TMDS:
393
			*conf = (ctrl & 0x00000f00) >> 8;
394
			if (*conf == 5)
395
				*conf |= 0x0100;
396 397
			break;
		case DCB_OUTPUT_LVDS:
B
Ben Skeggs 已提交
398
			*conf = disp->sor.lvdsconf;
399 400
			break;
		case DCB_OUTPUT_DP:
401
			*conf = (ctrl & 0x00000f00) >> 8;
402 403 404
			break;
		case DCB_OUTPUT_ANALOG:
		default:
405
			*conf = 0x00ff;
406 407 408
			break;
		}
	} else {
409
		*conf = (ctrl & 0x00000f00) >> 8;
410
		pclk = pclk / 2;
411 412
	}

413
	data = nvbios_ocfg_match(bios, data, *conf, &ver, &hdr, &cnt, &len, &info2);
414
	if (data && id < 0xff) {
415 416 417
		data = nvbios_oclk_match(bios, info2.clkcmp[id], pclk);
		if (data) {
			struct nvbios_init init = {
418
				.subdev = subdev,
419 420
				.bios = bios,
				.offset = data,
421
				.outp = &outp->info,
422 423 424 425
				.crtc = head,
				.execute = 1,
			};

426
			nvbios_exec(&init);
427 428 429
		}
	}

430
	return outp;
431 432 433
}

static void
B
Ben Skeggs 已提交
434
nv50_disp_intr_unk10_0(struct nv50_disp *disp, int head)
435
{
B
Ben Skeggs 已提交
436
	exec_script(disp, head, 1);
437
}
438

439
static void
B
Ben Skeggs 已提交
440
nv50_disp_intr_unk20_0(struct nv50_disp *disp, int head)
441
{
442
	struct nvkm_subdev *subdev = &disp->base.engine.subdev;
B
Ben Skeggs 已提交
443
	struct nvkm_output *outp = exec_script(disp, head, 2);
444 445 446 447 448 449 450 451 452 453 454 455 456 457 458

	/* the binary driver does this outside of the supervisor handling
	 * (after the third supervisor from a detach).  we (currently?)
	 * allow both detach/attach to happen in the same set of
	 * supervisor interrupts, so it would make sense to execute this
	 * (full power down?) script after all the detach phases of the
	 * supervisor handling.  like with training if needed from the
	 * second supervisor, nvidia doesn't do this, so who knows if it's
	 * entirely safe, but it does appear to work..
	 *
	 * without this script being run, on some configurations i've
	 * seen, switching from DP to TMDS on a DP connector may result
	 * in a blank screen (SOR_PWR off/on can restore it)
	 */
	if (outp && outp->info.type == DCB_OUTPUT_DP) {
459
		struct nvkm_output_dp *outpdp = nvkm_output_dp(outp);
460
		struct nvbios_init init = {
461 462
			.subdev = subdev,
			.bios = subdev->device->bios,
463 464 465 466 467 468 469 470 471
			.outp = &outp->info,
			.crtc = head,
			.offset = outpdp->info.script[4],
			.execute = 1,
		};

		nvbios_exec(&init);
		atomic_set(&outpdp->lt.done, 0);
	}
472 473 474
}

static void
B
Ben Skeggs 已提交
475
nv50_disp_intr_unk20_1(struct nv50_disp *disp, int head)
476
{
477 478 479
	struct nvkm_device *device = disp->base.engine.subdev.device;
	struct nvkm_devinit *devinit = device->devinit;
	u32 pclk = nvkm_rd32(device, 0x610ad0 + (head * 0x540)) & 0x3fffff;
480
	if (pclk)
481
		nvkm_devinit_pll_set(devinit, PLL_VPLL0 + head, pclk);
482 483 484
}

static void
B
Ben Skeggs 已提交
485
nv50_disp_intr_unk20_2_dp(struct nv50_disp *disp, int head,
486
			  struct dcb_output *outp, u32 pclk)
487
{
488 489
	struct nvkm_subdev *subdev = &disp->base.engine.subdev;
	struct nvkm_device *device = subdev->device;
490 491 492 493
	const int link = !(outp->sorconf.link & 1);
	const int   or = ffs(outp->or) - 1;
	const u32 soff = (  or * 0x800);
	const u32 loff = (link * 0x080) + soff;
494
	const u32 ctrl = nvkm_rd32(device, 0x610794 + (or * 8));
495
	const u32 symbol = 100000;
496 497 498 499 500
	const s32 vactive = nvkm_rd32(device, 0x610af8 + (head * 0x540)) & 0xffff;
	const s32 vblanke = nvkm_rd32(device, 0x610ae8 + (head * 0x540)) & 0xffff;
	const s32 vblanks = nvkm_rd32(device, 0x610af0 + (head * 0x540)) & 0xffff;
	u32 dpctrl = nvkm_rd32(device, 0x61c10c + loff);
	u32 clksor = nvkm_rd32(device, 0x614300 + soff);
501 502 503 504
	int bestTU = 0, bestVTUi = 0, bestVTUf = 0, bestVTUa = 0;
	int TU, VTUi, VTUf, VTUa;
	u64 link_data_rate, link_ratio, unk;
	u32 best_diff = 64 * symbol;
B
Ben Skeggs 已提交
505
	u32 link_nr, link_bw, bits;
506 507 508 509 510 511 512 513 514 515
	u64 value;

	link_bw = (clksor & 0x000c0000) ? 270000 : 162000;
	link_nr = hweight32(dpctrl & 0x000f0000);

	/* symbols/hblank - algorithm taken from comments in tegra driver */
	value = vblanke + vactive - vblanks - 7;
	value = value * link_bw;
	do_div(value, pclk);
	value = value - (3 * !!(dpctrl & 0x00004000)) - (12 / link_nr);
516
	nvkm_mask(device, 0x61c1e8 + soff, 0x0000ffff, value);
517 518 519 520 521 522

	/* symbols/vblank - algorithm taken from comments in tegra driver */
	value = vblanks - vblanke - 25;
	value = value * link_bw;
	do_div(value, pclk);
	value = value - ((36 / link_nr) + 3) - 1;
523
	nvkm_mask(device, 0x61c1ec + soff, 0x00ffffff, value);
524 525

	/* watermark / activesym */
526 527 528 529
	if      ((ctrl & 0xf0000) == 0x60000) bits = 30;
	else if ((ctrl & 0xf0000) == 0x50000) bits = 24;
	else                                  bits = 18;

530 531 532 533
	link_data_rate = (pclk * bits / 8) / link_nr;

	/* calculate ratio of packed data rate to link symbol rate */
	link_ratio = link_data_rate * symbol;
B
Ben Skeggs 已提交
534
	do_div(link_ratio, link_bw);
535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587

	for (TU = 64; TU >= 32; TU--) {
		/* calculate average number of valid symbols in each TU */
		u32 tu_valid = link_ratio * TU;
		u32 calc, diff;

		/* find a hw representation for the fraction.. */
		VTUi = tu_valid / symbol;
		calc = VTUi * symbol;
		diff = tu_valid - calc;
		if (diff) {
			if (diff >= (symbol / 2)) {
				VTUf = symbol / (symbol - diff);
				if (symbol - (VTUf * diff))
					VTUf++;

				if (VTUf <= 15) {
					VTUa  = 1;
					calc += symbol - (symbol / VTUf);
				} else {
					VTUa  = 0;
					VTUf  = 1;
					calc += symbol;
				}
			} else {
				VTUa  = 0;
				VTUf  = min((int)(symbol / diff), 15);
				calc += symbol / VTUf;
			}

			diff = calc - tu_valid;
		} else {
			/* no remainder, but the hw doesn't like the fractional
			 * part to be zero.  decrement the integer part and
			 * have the fraction add a whole symbol back
			 */
			VTUa = 0;
			VTUf = 1;
			VTUi--;
		}

		if (diff < best_diff) {
			best_diff = diff;
			bestTU = TU;
			bestVTUa = VTUa;
			bestVTUf = VTUf;
			bestVTUi = VTUi;
			if (diff == 0)
				break;
		}
	}

	if (!bestTU) {
588
		nvkm_error(subdev, "unable to find suitable dp config\n");
589 590 591 592 593 594
		return;
	}

	/* XXX close to vbios numbers, but not right */
	unk  = (symbol - link_ratio) * bestTU;
	unk *= link_ratio;
B
Ben Skeggs 已提交
595 596
	do_div(unk, symbol);
	do_div(unk, symbol);
597 598
	unk += 6;

599 600
	nvkm_mask(device, 0x61c10c + loff, 0x000001fc, bestTU << 2);
	nvkm_mask(device, 0x61c128 + loff, 0x010f7f3f, bestVTUa << 24 |
601 602 603 604 605
						   bestVTUf << 16 |
						   bestVTUi << 8 | unk);
}

static void
B
Ben Skeggs 已提交
606
nv50_disp_intr_unk20_2(struct nv50_disp *disp, int head)
607
{
608
	struct nvkm_device *device = disp->base.engine.subdev.device;
609
	struct nvkm_output *outp;
610
	u32 pclk = nvkm_rd32(device, 0x610ad0 + (head * 0x540)) & 0x3fffff;
611 612
	u32 hval, hreg = 0x614200 + (head * 0x800);
	u32 oval, oreg;
613
	u32 mask, conf;
614

B
Ben Skeggs 已提交
615
	outp = exec_clkcmp(disp, head, 0xff, pclk, &conf);
616 617
	if (!outp)
		return;
618

619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636
	/* we allow both encoder attach and detach operations to occur
	 * within a single supervisor (ie. modeset) sequence.  the
	 * encoder detach scripts quite often switch off power to the
	 * lanes, which requires the link to be re-trained.
	 *
	 * this is not generally an issue as the sink "must" (heh)
	 * signal an irq when it's lost sync so the driver can
	 * re-train.
	 *
	 * however, on some boards, if one does not configure at least
	 * the gpu side of the link *before* attaching, then various
	 * things can go horribly wrong (PDISP disappearing from mmio,
	 * third supervisor never happens, etc).
	 *
	 * the solution is simply to retrain here, if necessary.  last
	 * i checked, the binary driver userspace does not appear to
	 * trigger this situation (it forces an UPDATE between steps).
	 */
637
	if (outp->info.type == DCB_OUTPUT_DP) {
638
		u32 soff = (ffs(outp->info.or) - 1) * 0x08;
639 640 641
		u32 ctrl, datarate;

		if (outp->info.location == 0) {
642
			ctrl = nvkm_rd32(device, 0x610794 + soff);
643 644
			soff = 1;
		} else {
645
			ctrl = nvkm_rd32(device, 0x610b80 + soff);
646 647
			soff = 2;
		}
648 649

		switch ((ctrl & 0x000f0000) >> 16) {
650 651
		case 6: datarate = pclk * 30; break;
		case 5: datarate = pclk * 24; break;
652 653
		case 2:
		default:
654
			datarate = pclk * 18;
655
			break;
656 657
		}

658
		if (nvkm_output_dp_train(outp, datarate / soff, true))
659
			OUTP_ERR(outp, "link not trained before attach");
660 661
	}

B
Ben Skeggs 已提交
662
	exec_clkcmp(disp, head, 0, pclk, &conf);
663 664 665 666 667 668 669 670 671

	if (!outp->info.location && outp->info.type == DCB_OUTPUT_ANALOG) {
		oreg = 0x614280 + (ffs(outp->info.or) - 1) * 0x800;
		oval = 0x00000000;
		hval = 0x00000000;
		mask = 0xffffffff;
	} else
	if (!outp->info.location) {
		if (outp->info.type == DCB_OUTPUT_DP)
B
Ben Skeggs 已提交
672
			nv50_disp_intr_unk20_2_dp(disp, head, &outp->info, pclk);
673 674 675 676 677 678 679 680 681
		oreg = 0x614300 + (ffs(outp->info.or) - 1) * 0x800;
		oval = (conf & 0x0100) ? 0x00000101 : 0x00000000;
		hval = 0x00000000;
		mask = 0x00000707;
	} else {
		oreg = 0x614380 + (ffs(outp->info.or) - 1) * 0x800;
		oval = 0x00000001;
		hval = 0x00000001;
		mask = 0x00000707;
682
	}
683

684 685
	nvkm_mask(device, hreg, 0x0000000f, hval);
	nvkm_mask(device, oreg, mask, oval);
686 687 688 689 690 691 692 693 694 695 696
}

/* If programming a TMDS output on a SOR that can also be configured for
 * DisplayPort, make sure NV50_SOR_DP_CTRL_ENABLE is forced off.
 *
 * It looks like the VBIOS TMDS scripts make an attempt at this, however,
 * the VBIOS scripts on at least one board I have only switch it off on
 * link 0, causing a blank display if the output has previously been
 * programmed for DisplayPort.
 */
static void
B
Ben Skeggs 已提交
697
nv50_disp_intr_unk40_0_tmds(struct nv50_disp *disp,
698
			    struct dcb_output *outp)
699
{
700 701
	struct nvkm_device *device = disp->base.engine.subdev.device;
	struct nvkm_bios *bios = device->bios;
702 703 704 705
	const int link = !(outp->sorconf.link & 1);
	const int   or = ffs(outp->or) - 1;
	const u32 loff = (or * 0x800) + (link * 0x80);
	const u16 mask = (outp->sorconf.link << 6) | outp->or;
706
	struct dcb_output match;
707 708
	u8  ver, hdr;

709
	if (dcb_outp_match(bios, DCB_OUTPUT_DP, mask, &ver, &hdr, &match))
710
		nvkm_mask(device, 0x61c10c + loff, 0x00000001, 0x00000000);
711 712 713
}

static void
B
Ben Skeggs 已提交
714
nv50_disp_intr_unk40_0(struct nv50_disp *disp, int head)
715
{
716
	struct nvkm_device *device = disp->base.engine.subdev.device;
717
	struct nvkm_output *outp;
718
	u32 pclk = nvkm_rd32(device, 0x610ad0 + (head * 0x540)) & 0x3fffff;
719
	u32 conf;
720

B
Ben Skeggs 已提交
721
	outp = exec_clkcmp(disp, head, 1, pclk, &conf);
722 723 724 725
	if (!outp)
		return;

	if (outp->info.location == 0 && outp->info.type == DCB_OUTPUT_TMDS)
B
Ben Skeggs 已提交
726
		nv50_disp_intr_unk40_0_tmds(disp, &outp->info);
727 728
}

729 730
void
nv50_disp_intr_supervisor(struct work_struct *work)
731
{
B
Ben Skeggs 已提交
732 733
	struct nv50_disp *disp =
		container_of(work, struct nv50_disp, supervisor);
734 735
	struct nvkm_subdev *subdev = &disp->base.engine.subdev;
	struct nvkm_device *device = subdev->device;
736
	u32 super = nvkm_rd32(device, 0x610030);
737
	int head;
738

739
	nvkm_debug(subdev, "supervisor %08x %08x\n", disp->super, super);
740

B
Ben Skeggs 已提交
741
	if (disp->super & 0x00000010) {
742
		nv50_disp_chan_mthd(disp->chan[0], NV_DBG_DEBUG);
743
		for (head = 0; head < disp->base.head.nr; head++) {
744 745 746 747
			if (!(super & (0x00000020 << head)))
				continue;
			if (!(super & (0x00000080 << head)))
				continue;
B
Ben Skeggs 已提交
748
			nv50_disp_intr_unk10_0(disp, head);
749 750
		}
	} else
B
Ben Skeggs 已提交
751
	if (disp->super & 0x00000020) {
752
		for (head = 0; head < disp->base.head.nr; head++) {
753 754
			if (!(super & (0x00000080 << head)))
				continue;
B
Ben Skeggs 已提交
755
			nv50_disp_intr_unk20_0(disp, head);
756
		}
757
		for (head = 0; head < disp->base.head.nr; head++) {
758 759
			if (!(super & (0x00000200 << head)))
				continue;
B
Ben Skeggs 已提交
760
			nv50_disp_intr_unk20_1(disp, head);
761
		}
762
		for (head = 0; head < disp->base.head.nr; head++) {
763 764
			if (!(super & (0x00000080 << head)))
				continue;
B
Ben Skeggs 已提交
765
			nv50_disp_intr_unk20_2(disp, head);
766 767
		}
	} else
B
Ben Skeggs 已提交
768
	if (disp->super & 0x00000040) {
769
		for (head = 0; head < disp->base.head.nr; head++) {
770 771
			if (!(super & (0x00000080 << head)))
				continue;
B
Ben Skeggs 已提交
772
			nv50_disp_intr_unk40_0(disp, head);
773 774 775
		}
	}

776
	nvkm_wr32(device, 0x610030, 0x80000000);
777 778
}

779
void
780
nv50_disp_intr(struct nv50_disp *disp)
781
{
782 783 784
	struct nvkm_device *device = disp->base.engine.subdev.device;
	u32 intr0 = nvkm_rd32(device, 0x610020);
	u32 intr1 = nvkm_rd32(device, 0x610024);
785

786 787
	while (intr0 & 0x001f0000) {
		u32 chid = __ffs(intr0 & 0x001f0000) - 16;
B
Ben Skeggs 已提交
788
		nv50_disp_intr_error(disp, chid);
789
		intr0 &= ~(0x00010000 << chid);
790 791
	}

792 793
	while (intr0 & 0x0000001f) {
		u32 chid = __ffs(intr0 & 0x0000001f);
B
Ben Skeggs 已提交
794
		nv50_disp_chan_uevent_send(disp, chid);
795 796 797
		intr0 &= ~(0x00000001 << chid);
	}

798
	if (intr1 & 0x00000004) {
B
Ben Skeggs 已提交
799
		nvkm_disp_vblank(&disp->base, 0);
800
		nvkm_wr32(device, 0x610024, 0x00000004);
801 802
	}

803
	if (intr1 & 0x00000008) {
B
Ben Skeggs 已提交
804
		nvkm_disp_vblank(&disp->base, 1);
805
		nvkm_wr32(device, 0x610024, 0x00000008);
806 807
	}

808
	if (intr1 & 0x00000070) {
B
Ben Skeggs 已提交
809 810
		disp->super = (intr1 & 0x00000070);
		schedule_work(&disp->supervisor);
811
		nvkm_wr32(device, 0x610024, disp->super);
812
	}
813 814
}

815
static const struct nv50_disp_func
816
nv50_disp = {
817 818 819
	.intr = nv50_disp_intr,
	.uevent = &nv50_disp_chan_uevent,
	.super = nv50_disp_intr_supervisor,
820
	.root = &nv50_disp_root_oclass,
821 822 823 824 825 826 827 828 829 830 831 832 833 834 835
	.head.vblank_init = nv50_disp_vblank_init,
	.head.vblank_fini = nv50_disp_vblank_fini,
	.head.scanoutpos = nv50_disp_root_scanoutpos,
	.outp.internal.crt = nv50_dac_output_new,
	.outp.internal.tmds = nv50_sor_output_new,
	.outp.internal.lvds = nv50_sor_output_new,
	.outp.external.tmds = nv50_pior_output_new,
	.outp.external.dp = nv50_pior_dp_new,
	.dac.nr = 3,
	.dac.power = nv50_dac_power,
	.dac.sense = nv50_dac_sense,
	.sor.nr = 2,
	.sor.power = nv50_sor_power,
	.pior.nr = 3,
	.pior.power = nv50_pior_power,
836 837
};

838 839
int
nv50_disp_new(struct nvkm_device *device, int index, struct nvkm_disp **pdisp)
840
{
841
	return nv50_disp_new_(&nv50_disp, device, index, 2, pdisp);
842
}