xref: /linux/drivers/gpu/drm/nouveau/nvkm/engine/disp/gf119.c (revision cbdb1f163af2bb90d01be1f0263df1d8d5c9d9d3)
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 #include "priv.h"
25 #include "chan.h"
26 #include "hdmi.h"
27 #include "head.h"
28 #include "ior.h"
29 #include "outp.h"
30 
31 #include <core/ramht.h>
32 #include <subdev/timer.h>
33 
34 #include <nvif/class.h>
35 
36 static void
37 gf119_sor_hda_device_entry(struct nvkm_ior *ior, int head)
38 {
39 	struct nvkm_device *device = ior->disp->engine.subdev.device;
40 	const u32 hoff = 0x800 * head;
41 
42 	nvkm_mask(device, 0x616548 + hoff, 0x00000070, head << 4);
43 }
44 
45 void
46 gf119_sor_hda_eld(struct nvkm_ior *ior, int head, u8 *data, u8 size)
47 {
48 	struct nvkm_device *device = ior->disp->engine.subdev.device;
49 	const u32 soff = 0x030 * ior->id + (head * 0x04);
50 	int i;
51 
52 	for (i = 0; i < size; i++)
53 		nvkm_wr32(device, 0x10ec00 + soff, (i << 8) | data[i]);
54 	for (; i < 0x60; i++)
55 		nvkm_wr32(device, 0x10ec00 + soff, (i << 8));
56 	nvkm_mask(device, 0x10ec10 + soff, 0x80000002, 0x80000002);
57 }
58 
59 void
60 gf119_sor_hda_hpd(struct nvkm_ior *ior, int head, bool present)
61 {
62 	struct nvkm_device *device = ior->disp->engine.subdev.device;
63 	const u32 soff = 0x030 * ior->id + (head * 0x04);
64 	u32 data = 0x80000000;
65 	u32 mask = 0x80000001;
66 
67 	if (present) {
68 		ior->func->hda->device_entry(ior, head);
69 		data |= 0x00000001;
70 	} else {
71 		mask |= 0x00000002;
72 	}
73 
74 	nvkm_mask(device, 0x10ec10 + soff, mask, data);
75 }
76 
77 const struct nvkm_ior_func_hda
78 gf119_sor_hda = {
79 	.hpd = gf119_sor_hda_hpd,
80 	.eld = gf119_sor_hda_eld,
81 	.device_entry = gf119_sor_hda_device_entry,
82 };
83 
84 void
85 gf119_sor_dp_watermark(struct nvkm_ior *sor, int head, u8 watermark)
86 {
87 	struct nvkm_device *device = sor->disp->engine.subdev.device;
88 	const u32 hoff = head * 0x800;
89 
90 	nvkm_mask(device, 0x616610 + hoff, 0x0800003f, 0x08000000 | watermark);
91 }
92 
93 void
94 gf119_sor_dp_audio_sym(struct nvkm_ior *sor, int head, u16 h, u32 v)
95 {
96 	struct nvkm_device *device = sor->disp->engine.subdev.device;
97 	const u32 hoff = head * 0x800;
98 
99 	nvkm_mask(device, 0x616620 + hoff, 0x0000ffff, h);
100 	nvkm_mask(device, 0x616624 + hoff, 0x00ffffff, v);
101 }
102 
103 void
104 gf119_sor_dp_audio(struct nvkm_ior *sor, int head, bool enable)
105 {
106 	struct nvkm_device *device = sor->disp->engine.subdev.device;
107 	const u32 hoff = 0x800 * head;
108 	const u32 data = 0x80000000 | (0x00000001 * enable);
109 	const u32 mask = 0x8000000d;
110 
111 	nvkm_mask(device, 0x616618 + hoff, mask, data);
112 	nvkm_msec(device, 2000,
113 		if (!(nvkm_rd32(device, 0x616618 + hoff) & 0x80000000))
114 			break;
115 	);
116 }
117 
118 void
119 gf119_sor_dp_vcpi(struct nvkm_ior *sor, int head, u8 slot, u8 slot_nr, u16 pbn, u16 aligned)
120 {
121 	struct nvkm_device *device = sor->disp->engine.subdev.device;
122 	const u32 hoff = head * 0x800;
123 
124 	nvkm_mask(device, 0x616588 + hoff, 0x00003f3f, (slot_nr << 8) | slot);
125 	nvkm_mask(device, 0x61658c + hoff, 0xffffffff, (aligned << 16) | pbn);
126 }
127 
128 void
129 gf119_sor_dp_drive(struct nvkm_ior *sor, int ln, int pc, int dc, int pe, int pu)
130 {
131 	struct nvkm_device *device = sor->disp->engine.subdev.device;
132 	const u32  loff = nv50_sor_link(sor);
133 	const u32 shift = sor->func->dp->lanes[ln] * 8;
134 	u32 data[4];
135 
136 	data[0] = nvkm_rd32(device, 0x61c118 + loff) & ~(0x000000ff << shift);
137 	data[1] = nvkm_rd32(device, 0x61c120 + loff) & ~(0x000000ff << shift);
138 	data[2] = nvkm_rd32(device, 0x61c130 + loff);
139 	if ((data[2] & 0x0000ff00) < (pu << 8) || ln == 0)
140 		data[2] = (data[2] & ~0x0000ff00) | (pu << 8);
141 
142 	nvkm_wr32(device, 0x61c118 + loff, data[0] | (dc << shift));
143 	nvkm_wr32(device, 0x61c120 + loff, data[1] | (pe << shift));
144 	nvkm_wr32(device, 0x61c130 + loff, data[2]);
145 
146 	data[3] = nvkm_rd32(device, 0x61c13c + loff) & ~(0x000000ff << shift);
147 	nvkm_wr32(device, 0x61c13c + loff, data[3] | (pc << shift));
148 }
149 
150 static void
151 gf119_sor_dp_pattern(struct nvkm_ior *sor, int pattern)
152 {
153 	struct nvkm_device *device = sor->disp->engine.subdev.device;
154 	const u32 soff = nv50_ior_base(sor);
155 	u32 data;
156 
157 	switch (pattern) {
158 	case 0: data = 0x10101010; break;
159 	case 1: data = 0x01010101; break;
160 	case 2: data = 0x02020202; break;
161 	case 3: data = 0x03030303; break;
162 	default:
163 		WARN_ON(1);
164 		return;
165 	}
166 
167 	nvkm_mask(device, 0x61c110 + soff, 0x1f1f1f1f, data);
168 }
169 
170 int
171 gf119_sor_dp_links(struct nvkm_ior *sor, struct nvkm_i2c_aux *aux)
172 {
173 	struct nvkm_device *device = sor->disp->engine.subdev.device;
174 	const u32 soff = nv50_ior_base(sor);
175 	const u32 loff = nv50_sor_link(sor);
176 	u32 dpctrl = 0x00000000;
177 	u32 clksor = 0x00000000;
178 
179 	clksor |= sor->dp.bw << 18;
180 	dpctrl |= ((1 << sor->dp.nr) - 1) << 16;
181 	if (sor->dp.mst)
182 		dpctrl |= 0x40000000;
183 	if (sor->dp.ef)
184 		dpctrl |= 0x00004000;
185 
186 	nvkm_mask(device, 0x612300 + soff, 0x007c0000, clksor);
187 	nvkm_mask(device, 0x61c10c + loff, 0x401f4000, dpctrl);
188 	return 0;
189 }
190 
191 const struct nvkm_ior_func_dp
192 gf119_sor_dp = {
193 	.lanes = { 2, 1, 0, 3 },
194 	.links = gf119_sor_dp_links,
195 	.power = g94_sor_dp_power,
196 	.pattern = gf119_sor_dp_pattern,
197 	.drive = gf119_sor_dp_drive,
198 	.vcpi = gf119_sor_dp_vcpi,
199 	.audio = gf119_sor_dp_audio,
200 	.audio_sym = gf119_sor_dp_audio_sym,
201 	.watermark = gf119_sor_dp_watermark,
202 };
203 
204 static void
205 gf119_sor_hdmi_infoframe_vsi(struct nvkm_ior *ior, int head, void *data, u32 size)
206 {
207 	struct nvkm_device *device = ior->disp->engine.subdev.device;
208 	struct packed_hdmi_infoframe vsi;
209 	const u32 hoff = head * 0x800;
210 
211 	pack_hdmi_infoframe(&vsi, data, size);
212 
213 	nvkm_mask(device, 0x616730 + hoff, 0x00010001, 0x00010000);
214 	if (!size)
215 		return;
216 
217 	/*
218 	 * These appear to be the audio infoframe registers,
219 	 * but no other set of infoframe registers has yet
220 	 * been found.
221 	 */
222 	nvkm_wr32(device, 0x616738 + hoff, vsi.header);
223 	nvkm_wr32(device, 0x61673c + hoff, vsi.subpack0_low);
224 	nvkm_wr32(device, 0x616740 + hoff, vsi.subpack0_high);
225 	/* Is there a second (or further?) set of subpack registers here? */
226 
227 	nvkm_mask(device, 0x616730 + hoff, 0x00000001, 0x00000001);
228 }
229 
230 static void
231 gf119_sor_hdmi_infoframe_avi(struct nvkm_ior *ior, int head, void *data, u32 size)
232 {
233 	struct nvkm_device *device = ior->disp->engine.subdev.device;
234 	struct packed_hdmi_infoframe avi;
235 	const u32 hoff = head * 0x800;
236 
237 	pack_hdmi_infoframe(&avi, data, size);
238 
239 	nvkm_mask(device, 0x616714 + hoff, 0x00000001, 0x00000000);
240 	if (!size)
241 		return;
242 
243 	nvkm_wr32(device, 0x61671c + hoff, avi.header);
244 	nvkm_wr32(device, 0x616720 + hoff, avi.subpack0_low);
245 	nvkm_wr32(device, 0x616724 + hoff, avi.subpack0_high);
246 	nvkm_wr32(device, 0x616728 + hoff, avi.subpack1_low);
247 	nvkm_wr32(device, 0x61672c + hoff, avi.subpack1_high);
248 
249 	nvkm_mask(device, 0x616714 + hoff, 0x00000001, 0x00000001);
250 }
251 
252 static void
253 gf119_sor_hdmi_ctrl(struct nvkm_ior *ior, int head, bool enable, u8 max_ac_packet, u8 rekey)
254 {
255 	struct nvkm_device *device = ior->disp->engine.subdev.device;
256 	const u32 ctrl = 0x40000000 * enable |
257 			 max_ac_packet << 16 |
258 			 rekey;
259 	const u32 hoff = head * 0x800;
260 
261 	if (!(ctrl & 0x40000000)) {
262 		nvkm_mask(device, 0x616798 + hoff, 0x40000000, 0x00000000);
263 		nvkm_mask(device, 0x616730 + hoff, 0x00000001, 0x00000000);
264 		nvkm_mask(device, 0x6167a4 + hoff, 0x00000001, 0x00000000);
265 		nvkm_mask(device, 0x616714 + hoff, 0x00000001, 0x00000000);
266 		return;
267 	}
268 
269 	/* ??? InfoFrame? */
270 	nvkm_mask(device, 0x6167a4 + hoff, 0x00000001, 0x00000000);
271 	nvkm_wr32(device, 0x6167ac + hoff, 0x00000010);
272 	nvkm_mask(device, 0x6167a4 + hoff, 0x00000001, 0x00000001);
273 
274 	/* HDMI_CTRL */
275 	nvkm_mask(device, 0x616798 + hoff, 0x401f007f, ctrl);
276 }
277 
278 static const struct nvkm_ior_func_hdmi
279 gf119_sor_hdmi = {
280 	.ctrl = gf119_sor_hdmi_ctrl,
281 	.infoframe_avi = gf119_sor_hdmi_infoframe_avi,
282 	.infoframe_vsi = gf119_sor_hdmi_infoframe_vsi,
283 };
284 
285 void
286 gf119_sor_clock(struct nvkm_ior *sor)
287 {
288 	struct nvkm_device *device = sor->disp->engine.subdev.device;
289 	const u32 soff = nv50_ior_base(sor);
290 	u32 div1 = sor->asy.link == 3;
291 	u32 div2 = sor->asy.link == 3;
292 
293 	if (sor->asy.proto == TMDS) {
294 		const u32 speed = sor->tmds.high_speed ? 0x14 : 0x0a;
295 		nvkm_mask(device, 0x612300 + soff, 0x007c0000, speed << 18);
296 		if (sor->tmds.high_speed)
297 			div2 = 1;
298 	}
299 
300 	nvkm_mask(device, 0x612300 + soff, 0x00000707, (div2 << 8) | div1);
301 }
302 
303 void
304 gf119_sor_state(struct nvkm_ior *sor, struct nvkm_ior_state *state)
305 {
306 	struct nvkm_device *device = sor->disp->engine.subdev.device;
307 	const u32 coff = (state == &sor->asy) * 0x20000 + sor->id * 0x20;
308 	u32 ctrl = nvkm_rd32(device, 0x640200 + coff);
309 
310 	state->proto_evo = (ctrl & 0x00000f00) >> 8;
311 	switch (state->proto_evo) {
312 	case 0: state->proto = LVDS; state->link = 1; break;
313 	case 1: state->proto = TMDS; state->link = 1; break;
314 	case 2: state->proto = TMDS; state->link = 2; break;
315 	case 5: state->proto = TMDS; state->link = 3; break;
316 	case 8: state->proto =   DP; state->link = 1; break;
317 	case 9: state->proto =   DP; state->link = 2; break;
318 	default:
319 		state->proto = UNKNOWN;
320 		break;
321 	}
322 
323 	state->head = ctrl & 0x0000000f;
324 }
325 
326 static const struct nvkm_ior_func
327 gf119_sor = {
328 	.state = gf119_sor_state,
329 	.power = nv50_sor_power,
330 	.clock = gf119_sor_clock,
331 	.hdmi = &gf119_sor_hdmi,
332 	.dp = &gf119_sor_dp,
333 	.hda = &gf119_sor_hda,
334 };
335 
336 static int
337 gf119_sor_new(struct nvkm_disp *disp, int id)
338 {
339 	return nvkm_ior_new_(&gf119_sor, disp, SOR, id, true);
340 }
341 
342 int
343 gf119_sor_cnt(struct nvkm_disp *disp, unsigned long *pmask)
344 {
345 	struct nvkm_device *device = disp->engine.subdev.device;
346 	*pmask = (nvkm_rd32(device, 0x612004) & 0x0000ff00) >> 8;
347 	return 8;
348 }
349 
350 static void
351 gf119_dac_clock(struct nvkm_ior *dac)
352 {
353 	struct nvkm_device *device = dac->disp->engine.subdev.device;
354 	const u32 doff = nv50_ior_base(dac);
355 	nvkm_mask(device, 0x612280 + doff, 0x07070707, 0x00000000);
356 }
357 
358 static void
359 gf119_dac_state(struct nvkm_ior *dac, struct nvkm_ior_state *state)
360 {
361 	struct nvkm_device *device = dac->disp->engine.subdev.device;
362 	const u32 coff = (state == &dac->asy) * 0x20000 + dac->id * 0x20;
363 	u32 ctrl = nvkm_rd32(device, 0x640180 + coff);
364 
365 	state->proto_evo = (ctrl & 0x00000f00) >> 8;
366 	switch (state->proto_evo) {
367 	case 0: state->proto = CRT; break;
368 	default:
369 		state->proto = UNKNOWN;
370 		break;
371 	}
372 
373 	state->head = ctrl & 0x0000000f;
374 }
375 
376 static const struct nvkm_ior_func
377 gf119_dac = {
378 	.state = gf119_dac_state,
379 	.power = nv50_dac_power,
380 	.sense = nv50_dac_sense,
381 	.clock = gf119_dac_clock,
382 };
383 
384 int
385 gf119_dac_new(struct nvkm_disp *disp, int id)
386 {
387 	return nvkm_ior_new_(&gf119_dac, disp, DAC, id, false);
388 }
389 
390 int
391 gf119_dac_cnt(struct nvkm_disp *disp, unsigned long *pmask)
392 {
393 	struct nvkm_device *device = disp->engine.subdev.device;
394 	*pmask = (nvkm_rd32(device, 0x612004) & 0x000000f0) >> 4;
395 	return 4;
396 }
397 
398 static void
399 gf119_head_vblank_put(struct nvkm_head *head)
400 {
401 	struct nvkm_device *device = head->disp->engine.subdev.device;
402 	const u32 hoff = head->id * 0x800;
403 	nvkm_mask(device, 0x6100c0 + hoff, 0x00000001, 0x00000000);
404 }
405 
406 static void
407 gf119_head_vblank_get(struct nvkm_head *head)
408 {
409 	struct nvkm_device *device = head->disp->engine.subdev.device;
410 	const u32 hoff = head->id * 0x800;
411 	nvkm_mask(device, 0x6100c0 + hoff, 0x00000001, 0x00000001);
412 }
413 
414 void
415 gf119_head_rgclk(struct nvkm_head *head, int div)
416 {
417 	struct nvkm_device *device = head->disp->engine.subdev.device;
418 	nvkm_mask(device, 0x612200 + (head->id * 0x800), 0x0000000f, div);
419 }
420 
421 static void
422 gf119_head_state(struct nvkm_head *head, struct nvkm_head_state *state)
423 {
424 	struct nvkm_device *device = head->disp->engine.subdev.device;
425 	const u32 hoff = (state == &head->asy) * 0x20000 + head->id * 0x300;
426 	u32 data;
427 
428 	data = nvkm_rd32(device, 0x640414 + hoff);
429 	state->vtotal = (data & 0xffff0000) >> 16;
430 	state->htotal = (data & 0x0000ffff);
431 	data = nvkm_rd32(device, 0x640418 + hoff);
432 	state->vsynce = (data & 0xffff0000) >> 16;
433 	state->hsynce = (data & 0x0000ffff);
434 	data = nvkm_rd32(device, 0x64041c + hoff);
435 	state->vblanke = (data & 0xffff0000) >> 16;
436 	state->hblanke = (data & 0x0000ffff);
437 	data = nvkm_rd32(device, 0x640420 + hoff);
438 	state->vblanks = (data & 0xffff0000) >> 16;
439 	state->hblanks = (data & 0x0000ffff);
440 	state->hz = nvkm_rd32(device, 0x640450 + hoff);
441 
442 	data = nvkm_rd32(device, 0x640404 + hoff);
443 	switch ((data & 0x000003c0) >> 6) {
444 	case 6: state->or.depth = 30; break;
445 	case 5: state->or.depth = 24; break;
446 	case 2: state->or.depth = 18; break;
447 	case 0: state->or.depth = 18; break; /*XXX: "default" */
448 	default:
449 		state->or.depth = 18;
450 		WARN_ON(1);
451 		break;
452 	}
453 }
454 
455 static const struct nvkm_head_func
456 gf119_head = {
457 	.state = gf119_head_state,
458 	.rgpos = nv50_head_rgpos,
459 	.rgclk = gf119_head_rgclk,
460 	.vblank_get = gf119_head_vblank_get,
461 	.vblank_put = gf119_head_vblank_put,
462 };
463 
464 int
465 gf119_head_new(struct nvkm_disp *disp, int id)
466 {
467 	return nvkm_head_new_(&gf119_head, disp, id);
468 }
469 
470 int
471 gf119_head_cnt(struct nvkm_disp *disp, unsigned long *pmask)
472 {
473 	struct nvkm_device *device = disp->engine.subdev.device;
474 	*pmask = nvkm_rd32(device, 0x612004) & 0x0000000f;
475 	return nvkm_rd32(device, 0x022448);
476 }
477 
478 static void
479 gf119_disp_chan_uevent_fini(struct nvkm_event *event, int type, int index)
480 {
481 	struct nvkm_disp *disp = container_of(event, typeof(*disp), uevent);
482 	struct nvkm_device *device = disp->engine.subdev.device;
483 	nvkm_mask(device, 0x610090, 0x00000001 << index, 0x00000000 << index);
484 	nvkm_wr32(device, 0x61008c, 0x00000001 << index);
485 }
486 
487 static void
488 gf119_disp_chan_uevent_init(struct nvkm_event *event, int types, int index)
489 {
490 	struct nvkm_disp *disp = container_of(event, typeof(*disp), uevent);
491 	struct nvkm_device *device = disp->engine.subdev.device;
492 	nvkm_wr32(device, 0x61008c, 0x00000001 << index);
493 	nvkm_mask(device, 0x610090, 0x00000001 << index, 0x00000001 << index);
494 }
495 
496 const struct nvkm_event_func
497 gf119_disp_chan_uevent = {
498 	.init = gf119_disp_chan_uevent_init,
499 	.fini = gf119_disp_chan_uevent_fini,
500 };
501 
502 void
503 gf119_disp_chan_intr(struct nvkm_disp_chan *chan, bool en)
504 {
505 	struct nvkm_device *device = chan->disp->engine.subdev.device;
506 	const u32 mask = 0x00000001 << chan->chid.user;
507 	if (!en) {
508 		nvkm_mask(device, 0x610090, mask, 0x00000000);
509 		nvkm_mask(device, 0x6100a0, mask, 0x00000000);
510 	} else {
511 		nvkm_mask(device, 0x6100a0, mask, mask);
512 	}
513 }
514 
515 static void
516 gf119_disp_pioc_fini(struct nvkm_disp_chan *chan)
517 {
518 	struct nvkm_disp *disp = chan->disp;
519 	struct nvkm_subdev *subdev = &disp->engine.subdev;
520 	struct nvkm_device *device = subdev->device;
521 	int ctrl = chan->chid.ctrl;
522 	int user = chan->chid.user;
523 
524 	nvkm_mask(device, 0x610490 + (ctrl * 0x10), 0x00000001, 0x00000000);
525 	if (nvkm_msec(device, 2000,
526 		if (!(nvkm_rd32(device, 0x610490 + (ctrl * 0x10)) & 0x00030000))
527 			break;
528 	) < 0) {
529 		nvkm_error(subdev, "ch %d fini: %08x\n", user,
530 			   nvkm_rd32(device, 0x610490 + (ctrl * 0x10)));
531 	}
532 }
533 
534 static int
535 gf119_disp_pioc_init(struct nvkm_disp_chan *chan)
536 {
537 	struct nvkm_disp *disp = chan->disp;
538 	struct nvkm_subdev *subdev = &disp->engine.subdev;
539 	struct nvkm_device *device = subdev->device;
540 	int ctrl = chan->chid.ctrl;
541 	int user = chan->chid.user;
542 
543 	/* activate channel */
544 	nvkm_wr32(device, 0x610490 + (ctrl * 0x10), 0x00000001);
545 	if (nvkm_msec(device, 2000,
546 		u32 tmp = nvkm_rd32(device, 0x610490 + (ctrl * 0x10));
547 		if ((tmp & 0x00030000) == 0x00010000)
548 			break;
549 	) < 0) {
550 		nvkm_error(subdev, "ch %d init: %08x\n", user,
551 			   nvkm_rd32(device, 0x610490 + (ctrl * 0x10)));
552 		return -EBUSY;
553 	}
554 
555 	return 0;
556 }
557 
558 const struct nvkm_disp_chan_func
559 gf119_disp_pioc_func = {
560 	.init = gf119_disp_pioc_init,
561 	.fini = gf119_disp_pioc_fini,
562 	.intr = gf119_disp_chan_intr,
563 	.user = nv50_disp_chan_user,
564 };
565 
566 int
567 gf119_disp_dmac_bind(struct nvkm_disp_chan *chan, struct nvkm_object *object, u32 handle)
568 {
569 	return nvkm_ramht_insert(chan->disp->ramht, object, chan->chid.user, -9, handle,
570 				 chan->chid.user << 27 | 0x00000001);
571 }
572 
573 void
574 gf119_disp_dmac_fini(struct nvkm_disp_chan *chan)
575 {
576 	struct nvkm_subdev *subdev = &chan->disp->engine.subdev;
577 	struct nvkm_device *device = subdev->device;
578 	int ctrl = chan->chid.ctrl;
579 	int user = chan->chid.user;
580 
581 	/* deactivate channel */
582 	nvkm_mask(device, 0x610490 + (ctrl * 0x0010), 0x00001010, 0x00001000);
583 	nvkm_mask(device, 0x610490 + (ctrl * 0x0010), 0x00000003, 0x00000000);
584 	if (nvkm_msec(device, 2000,
585 		if (!(nvkm_rd32(device, 0x610490 + (ctrl * 0x10)) & 0x001e0000))
586 			break;
587 	) < 0) {
588 		nvkm_error(subdev, "ch %d fini: %08x\n", user,
589 			   nvkm_rd32(device, 0x610490 + (ctrl * 0x10)));
590 	}
591 
592 	chan->suspend_put = nvkm_rd32(device, 0x640000 + (ctrl * 0x1000));
593 }
594 
595 static int
596 gf119_disp_dmac_init(struct nvkm_disp_chan *chan)
597 {
598 	struct nvkm_subdev *subdev = &chan->disp->engine.subdev;
599 	struct nvkm_device *device = subdev->device;
600 	int ctrl = chan->chid.ctrl;
601 	int user = chan->chid.user;
602 
603 	/* initialise channel for dma command submission */
604 	nvkm_wr32(device, 0x610494 + (ctrl * 0x0010), chan->push);
605 	nvkm_wr32(device, 0x610498 + (ctrl * 0x0010), 0x00010000);
606 	nvkm_wr32(device, 0x61049c + (ctrl * 0x0010), 0x00000001);
607 	nvkm_mask(device, 0x610490 + (ctrl * 0x0010), 0x00000010, 0x00000010);
608 	nvkm_wr32(device, 0x640000 + (ctrl * 0x1000), chan->suspend_put);
609 	nvkm_wr32(device, 0x610490 + (ctrl * 0x0010), 0x00000013);
610 
611 	/* wait for it to go inactive */
612 	if (nvkm_msec(device, 2000,
613 		if (!(nvkm_rd32(device, 0x610490 + (ctrl * 0x10)) & 0x80000000))
614 			break;
615 	) < 0) {
616 		nvkm_error(subdev, "ch %d init: %08x\n", user,
617 			   nvkm_rd32(device, 0x610490 + (ctrl * 0x10)));
618 		return -EBUSY;
619 	}
620 
621 	return 0;
622 }
623 
624 const struct nvkm_disp_chan_func
625 gf119_disp_dmac_func = {
626 	.push = nv50_disp_dmac_push,
627 	.init = gf119_disp_dmac_init,
628 	.fini = gf119_disp_dmac_fini,
629 	.intr = gf119_disp_chan_intr,
630 	.user = nv50_disp_chan_user,
631 	.bind = gf119_disp_dmac_bind,
632 };
633 
634 const struct nvkm_disp_chan_user
635 gf119_disp_curs = {
636 	.func = &gf119_disp_pioc_func,
637 	.ctrl = 13,
638 	.user = 13,
639 };
640 
641 const struct nvkm_disp_chan_user
642 gf119_disp_oimm = {
643 	.func = &gf119_disp_pioc_func,
644 	.ctrl = 9,
645 	.user = 9,
646 };
647 
648 static const struct nvkm_disp_mthd_list
649 gf119_disp_ovly_mthd_base = {
650 	.mthd = 0x0000,
651 	.data = {
652 		{ 0x0080, 0x665080 },
653 		{ 0x0084, 0x665084 },
654 		{ 0x0088, 0x665088 },
655 		{ 0x008c, 0x66508c },
656 		{ 0x0090, 0x665090 },
657 		{ 0x0094, 0x665094 },
658 		{ 0x00a0, 0x6650a0 },
659 		{ 0x00a4, 0x6650a4 },
660 		{ 0x00b0, 0x6650b0 },
661 		{ 0x00b4, 0x6650b4 },
662 		{ 0x00b8, 0x6650b8 },
663 		{ 0x00c0, 0x6650c0 },
664 		{ 0x00e0, 0x6650e0 },
665 		{ 0x00e4, 0x6650e4 },
666 		{ 0x00e8, 0x6650e8 },
667 		{ 0x0100, 0x665100 },
668 		{ 0x0104, 0x665104 },
669 		{ 0x0108, 0x665108 },
670 		{ 0x010c, 0x66510c },
671 		{ 0x0110, 0x665110 },
672 		{ 0x0118, 0x665118 },
673 		{ 0x011c, 0x66511c },
674 		{ 0x0120, 0x665120 },
675 		{ 0x0124, 0x665124 },
676 		{ 0x0130, 0x665130 },
677 		{ 0x0134, 0x665134 },
678 		{ 0x0138, 0x665138 },
679 		{ 0x013c, 0x66513c },
680 		{ 0x0140, 0x665140 },
681 		{ 0x0144, 0x665144 },
682 		{ 0x0148, 0x665148 },
683 		{ 0x014c, 0x66514c },
684 		{ 0x0150, 0x665150 },
685 		{ 0x0154, 0x665154 },
686 		{ 0x0158, 0x665158 },
687 		{ 0x015c, 0x66515c },
688 		{ 0x0160, 0x665160 },
689 		{ 0x0164, 0x665164 },
690 		{ 0x0168, 0x665168 },
691 		{ 0x016c, 0x66516c },
692 		{ 0x0400, 0x665400 },
693 		{ 0x0408, 0x665408 },
694 		{ 0x040c, 0x66540c },
695 		{ 0x0410, 0x665410 },
696 		{}
697 	}
698 };
699 
700 static const struct nvkm_disp_chan_mthd
701 gf119_disp_ovly_mthd = {
702 	.name = "Overlay",
703 	.addr = 0x001000,
704 	.prev = -0x020000,
705 	.data = {
706 		{ "Global", 1, &gf119_disp_ovly_mthd_base },
707 		{}
708 	}
709 };
710 
711 static const struct nvkm_disp_chan_user
712 gf119_disp_ovly = {
713 	.func = &gf119_disp_dmac_func,
714 	.ctrl = 5,
715 	.user = 5,
716 	.mthd = &gf119_disp_ovly_mthd,
717 };
718 
719 static const struct nvkm_disp_mthd_list
720 gf119_disp_base_mthd_base = {
721 	.mthd = 0x0000,
722 	.addr = 0x000000,
723 	.data = {
724 		{ 0x0080, 0x661080 },
725 		{ 0x0084, 0x661084 },
726 		{ 0x0088, 0x661088 },
727 		{ 0x008c, 0x66108c },
728 		{ 0x0090, 0x661090 },
729 		{ 0x0094, 0x661094 },
730 		{ 0x00a0, 0x6610a0 },
731 		{ 0x00a4, 0x6610a4 },
732 		{ 0x00c0, 0x6610c0 },
733 		{ 0x00c4, 0x6610c4 },
734 		{ 0x00c8, 0x6610c8 },
735 		{ 0x00cc, 0x6610cc },
736 		{ 0x00e0, 0x6610e0 },
737 		{ 0x00e4, 0x6610e4 },
738 		{ 0x00e8, 0x6610e8 },
739 		{ 0x00ec, 0x6610ec },
740 		{ 0x00fc, 0x6610fc },
741 		{ 0x0100, 0x661100 },
742 		{ 0x0104, 0x661104 },
743 		{ 0x0108, 0x661108 },
744 		{ 0x010c, 0x66110c },
745 		{ 0x0110, 0x661110 },
746 		{ 0x0114, 0x661114 },
747 		{ 0x0118, 0x661118 },
748 		{ 0x011c, 0x66111c },
749 		{ 0x0130, 0x661130 },
750 		{ 0x0134, 0x661134 },
751 		{ 0x0138, 0x661138 },
752 		{ 0x013c, 0x66113c },
753 		{ 0x0140, 0x661140 },
754 		{ 0x0144, 0x661144 },
755 		{ 0x0148, 0x661148 },
756 		{ 0x014c, 0x66114c },
757 		{ 0x0150, 0x661150 },
758 		{ 0x0154, 0x661154 },
759 		{ 0x0158, 0x661158 },
760 		{ 0x015c, 0x66115c },
761 		{ 0x0160, 0x661160 },
762 		{ 0x0164, 0x661164 },
763 		{ 0x0168, 0x661168 },
764 		{ 0x016c, 0x66116c },
765 		{}
766 	}
767 };
768 
769 static const struct nvkm_disp_mthd_list
770 gf119_disp_base_mthd_image = {
771 	.mthd = 0x0020,
772 	.addr = 0x000020,
773 	.data = {
774 		{ 0x0400, 0x661400 },
775 		{ 0x0404, 0x661404 },
776 		{ 0x0408, 0x661408 },
777 		{ 0x040c, 0x66140c },
778 		{ 0x0410, 0x661410 },
779 		{}
780 	}
781 };
782 
783 const struct nvkm_disp_chan_mthd
784 gf119_disp_base_mthd = {
785 	.name = "Base",
786 	.addr = 0x001000,
787 	.prev = -0x020000,
788 	.data = {
789 		{ "Global", 1, &gf119_disp_base_mthd_base },
790 		{  "Image", 2, &gf119_disp_base_mthd_image },
791 		{}
792 	}
793 };
794 
795 const struct nvkm_disp_chan_user
796 gf119_disp_base = {
797 	.func = &gf119_disp_dmac_func,
798 	.ctrl = 1,
799 	.user = 1,
800 	.mthd = &gf119_disp_base_mthd,
801 };
802 
803 const struct nvkm_disp_mthd_list
804 gf119_disp_core_mthd_base = {
805 	.mthd = 0x0000,
806 	.addr = 0x000000,
807 	.data = {
808 		{ 0x0080, 0x660080 },
809 		{ 0x0084, 0x660084 },
810 		{ 0x0088, 0x660088 },
811 		{ 0x008c, 0x000000 },
812 		{}
813 	}
814 };
815 
816 const struct nvkm_disp_mthd_list
817 gf119_disp_core_mthd_dac = {
818 	.mthd = 0x0020,
819 	.addr = 0x000020,
820 	.data = {
821 		{ 0x0180, 0x660180 },
822 		{ 0x0184, 0x660184 },
823 		{ 0x0188, 0x660188 },
824 		{ 0x0190, 0x660190 },
825 		{}
826 	}
827 };
828 
829 const struct nvkm_disp_mthd_list
830 gf119_disp_core_mthd_sor = {
831 	.mthd = 0x0020,
832 	.addr = 0x000020,
833 	.data = {
834 		{ 0x0200, 0x660200 },
835 		{ 0x0204, 0x660204 },
836 		{ 0x0208, 0x660208 },
837 		{ 0x0210, 0x660210 },
838 		{}
839 	}
840 };
841 
842 const struct nvkm_disp_mthd_list
843 gf119_disp_core_mthd_pior = {
844 	.mthd = 0x0020,
845 	.addr = 0x000020,
846 	.data = {
847 		{ 0x0300, 0x660300 },
848 		{ 0x0304, 0x660304 },
849 		{ 0x0308, 0x660308 },
850 		{ 0x0310, 0x660310 },
851 		{}
852 	}
853 };
854 
855 static const struct nvkm_disp_mthd_list
856 gf119_disp_core_mthd_head = {
857 	.mthd = 0x0300,
858 	.addr = 0x000300,
859 	.data = {
860 		{ 0x0400, 0x660400 },
861 		{ 0x0404, 0x660404 },
862 		{ 0x0408, 0x660408 },
863 		{ 0x040c, 0x66040c },
864 		{ 0x0410, 0x660410 },
865 		{ 0x0414, 0x660414 },
866 		{ 0x0418, 0x660418 },
867 		{ 0x041c, 0x66041c },
868 		{ 0x0420, 0x660420 },
869 		{ 0x0424, 0x660424 },
870 		{ 0x0428, 0x660428 },
871 		{ 0x042c, 0x66042c },
872 		{ 0x0430, 0x660430 },
873 		{ 0x0434, 0x660434 },
874 		{ 0x0438, 0x660438 },
875 		{ 0x0440, 0x660440 },
876 		{ 0x0444, 0x660444 },
877 		{ 0x0448, 0x660448 },
878 		{ 0x044c, 0x66044c },
879 		{ 0x0450, 0x660450 },
880 		{ 0x0454, 0x660454 },
881 		{ 0x0458, 0x660458 },
882 		{ 0x045c, 0x66045c },
883 		{ 0x0460, 0x660460 },
884 		{ 0x0468, 0x660468 },
885 		{ 0x046c, 0x66046c },
886 		{ 0x0470, 0x660470 },
887 		{ 0x0474, 0x660474 },
888 		{ 0x0480, 0x660480 },
889 		{ 0x0484, 0x660484 },
890 		{ 0x048c, 0x66048c },
891 		{ 0x0490, 0x660490 },
892 		{ 0x0494, 0x660494 },
893 		{ 0x0498, 0x660498 },
894 		{ 0x04b0, 0x6604b0 },
895 		{ 0x04b8, 0x6604b8 },
896 		{ 0x04bc, 0x6604bc },
897 		{ 0x04c0, 0x6604c0 },
898 		{ 0x04c4, 0x6604c4 },
899 		{ 0x04c8, 0x6604c8 },
900 		{ 0x04d0, 0x6604d0 },
901 		{ 0x04d4, 0x6604d4 },
902 		{ 0x04e0, 0x6604e0 },
903 		{ 0x04e4, 0x6604e4 },
904 		{ 0x04e8, 0x6604e8 },
905 		{ 0x04ec, 0x6604ec },
906 		{ 0x04f0, 0x6604f0 },
907 		{ 0x04f4, 0x6604f4 },
908 		{ 0x04f8, 0x6604f8 },
909 		{ 0x04fc, 0x6604fc },
910 		{ 0x0500, 0x660500 },
911 		{ 0x0504, 0x660504 },
912 		{ 0x0508, 0x660508 },
913 		{ 0x050c, 0x66050c },
914 		{ 0x0510, 0x660510 },
915 		{ 0x0514, 0x660514 },
916 		{ 0x0518, 0x660518 },
917 		{ 0x051c, 0x66051c },
918 		{ 0x052c, 0x66052c },
919 		{ 0x0530, 0x660530 },
920 		{ 0x054c, 0x66054c },
921 		{ 0x0550, 0x660550 },
922 		{ 0x0554, 0x660554 },
923 		{ 0x0558, 0x660558 },
924 		{ 0x055c, 0x66055c },
925 		{}
926 	}
927 };
928 
929 static const struct nvkm_disp_chan_mthd
930 gf119_disp_core_mthd = {
931 	.name = "Core",
932 	.addr = 0x000000,
933 	.prev = -0x020000,
934 	.data = {
935 		{ "Global", 1, &gf119_disp_core_mthd_base },
936 		{    "DAC", 3, &gf119_disp_core_mthd_dac  },
937 		{    "SOR", 8, &gf119_disp_core_mthd_sor  },
938 		{   "PIOR", 4, &gf119_disp_core_mthd_pior },
939 		{   "HEAD", 4, &gf119_disp_core_mthd_head },
940 		{}
941 	}
942 };
943 
944 void
945 gf119_disp_core_fini(struct nvkm_disp_chan *chan)
946 {
947 	struct nvkm_subdev *subdev = &chan->disp->engine.subdev;
948 	struct nvkm_device *device = subdev->device;
949 
950 	/* deactivate channel */
951 	nvkm_mask(device, 0x610490, 0x00000010, 0x00000000);
952 	nvkm_mask(device, 0x610490, 0x00000003, 0x00000000);
953 	if (nvkm_msec(device, 2000,
954 		if (!(nvkm_rd32(device, 0x610490) & 0x001e0000))
955 			break;
956 	) < 0) {
957 		nvkm_error(subdev, "core fini: %08x\n",
958 			   nvkm_rd32(device, 0x610490));
959 	}
960 
961 	chan->suspend_put = nvkm_rd32(device, 0x640000);
962 }
963 
964 static int
965 gf119_disp_core_init(struct nvkm_disp_chan *chan)
966 {
967 	struct nvkm_subdev *subdev = &chan->disp->engine.subdev;
968 	struct nvkm_device *device = subdev->device;
969 
970 	/* initialise channel for dma command submission */
971 	nvkm_wr32(device, 0x610494, chan->push);
972 	nvkm_wr32(device, 0x610498, 0x00010000);
973 	nvkm_wr32(device, 0x61049c, 0x00000001);
974 	nvkm_mask(device, 0x610490, 0x00000010, 0x00000010);
975 	nvkm_wr32(device, 0x640000, chan->suspend_put);
976 	nvkm_wr32(device, 0x610490, 0x01000013);
977 
978 	/* wait for it to go inactive */
979 	if (nvkm_msec(device, 2000,
980 		if (!(nvkm_rd32(device, 0x610490) & 0x80000000))
981 			break;
982 	) < 0) {
983 		nvkm_error(subdev, "core init: %08x\n",
984 			   nvkm_rd32(device, 0x610490));
985 		return -EBUSY;
986 	}
987 
988 	return 0;
989 }
990 
991 const struct nvkm_disp_chan_func
992 gf119_disp_core_func = {
993 	.push = nv50_disp_dmac_push,
994 	.init = gf119_disp_core_init,
995 	.fini = gf119_disp_core_fini,
996 	.intr = gf119_disp_chan_intr,
997 	.user = nv50_disp_chan_user,
998 	.bind = gf119_disp_dmac_bind,
999 };
1000 
1001 static const struct nvkm_disp_chan_user
1002 gf119_disp_core = {
1003 	.func = &gf119_disp_core_func,
1004 	.ctrl = 0,
1005 	.user = 0,
1006 	.mthd = &gf119_disp_core_mthd,
1007 };
1008 
1009 void
1010 gf119_disp_super(struct work_struct *work)
1011 {
1012 	struct nvkm_disp *disp = container_of(work, struct nvkm_disp, super.work);
1013 	struct nvkm_subdev *subdev = &disp->engine.subdev;
1014 	struct nvkm_device *device = subdev->device;
1015 	struct nvkm_head *head;
1016 	u32 mask[4];
1017 
1018 	nvkm_debug(subdev, "supervisor %d\n", ffs(disp->super.pending));
1019 	mutex_lock(&disp->super.mutex);
1020 
1021 	list_for_each_entry(head, &disp->heads, head) {
1022 		mask[head->id] = nvkm_rd32(device, 0x6101d4 + (head->id * 0x800));
1023 		HEAD_DBG(head, "%08x", mask[head->id]);
1024 	}
1025 
1026 	if (disp->super.pending & 0x00000001) {
1027 		nv50_disp_chan_mthd(disp->chan[0], NV_DBG_DEBUG);
1028 		nv50_disp_super_1(disp);
1029 		list_for_each_entry(head, &disp->heads, head) {
1030 			if (!(mask[head->id] & 0x00001000))
1031 				continue;
1032 			nv50_disp_super_1_0(disp, head);
1033 		}
1034 	} else
1035 	if (disp->super.pending & 0x00000002) {
1036 		list_for_each_entry(head, &disp->heads, head) {
1037 			if (!(mask[head->id] & 0x00001000))
1038 				continue;
1039 			nv50_disp_super_2_0(disp, head);
1040 		}
1041 		nvkm_outp_route(disp);
1042 		list_for_each_entry(head, &disp->heads, head) {
1043 			if (!(mask[head->id] & 0x00010000))
1044 				continue;
1045 			nv50_disp_super_2_1(disp, head);
1046 		}
1047 		list_for_each_entry(head, &disp->heads, head) {
1048 			if (!(mask[head->id] & 0x00001000))
1049 				continue;
1050 			nv50_disp_super_2_2(disp, head);
1051 		}
1052 	} else
1053 	if (disp->super.pending & 0x00000004) {
1054 		list_for_each_entry(head, &disp->heads, head) {
1055 			if (!(mask[head->id] & 0x00001000))
1056 				continue;
1057 			nv50_disp_super_3_0(disp, head);
1058 		}
1059 	}
1060 
1061 	list_for_each_entry(head, &disp->heads, head)
1062 		nvkm_wr32(device, 0x6101d4 + (head->id * 0x800), 0x00000000);
1063 
1064 	nvkm_wr32(device, 0x6101d0, 0x80000000);
1065 	mutex_unlock(&disp->super.mutex);
1066 }
1067 
1068 void
1069 gf119_disp_intr_error(struct nvkm_disp *disp, int chid)
1070 {
1071 	struct nvkm_subdev *subdev = &disp->engine.subdev;
1072 	struct nvkm_device *device = subdev->device;
1073 	u32 stat = nvkm_rd32(device, 0x6101f0 + (chid * 12));
1074 	u32 type = (stat & 0x00007000) >> 12;
1075 	u32 mthd = (stat & 0x00000ffc);
1076 	u32 data = nvkm_rd32(device, 0x6101f4 + (chid * 12));
1077 	u32 code = nvkm_rd32(device, 0x6101f8 + (chid * 12));
1078 	const struct nvkm_enum *reason =
1079 		nvkm_enum_find(nv50_disp_intr_error_type, type);
1080 
1081 	nvkm_error(subdev, "chid %d stat %08x reason %d [%s] mthd %04x "
1082 			   "data %08x code %08x\n",
1083 		   chid, stat, type, reason ? reason->name : "",
1084 		   mthd, data, code);
1085 
1086 	if (chid < ARRAY_SIZE(disp->chan)) {
1087 		switch (mthd) {
1088 		case 0x0080:
1089 			nv50_disp_chan_mthd(disp->chan[chid], NV_DBG_ERROR);
1090 			break;
1091 		default:
1092 			break;
1093 		}
1094 	}
1095 
1096 	nvkm_wr32(device, 0x61009c, (1 << chid));
1097 	nvkm_wr32(device, 0x6101f0 + (chid * 12), 0x90000000);
1098 }
1099 
1100 void
1101 gf119_disp_intr(struct nvkm_disp *disp)
1102 {
1103 	struct nvkm_subdev *subdev = &disp->engine.subdev;
1104 	struct nvkm_device *device = subdev->device;
1105 	struct nvkm_head *head;
1106 	u32 intr = nvkm_rd32(device, 0x610088);
1107 
1108 	if (intr & 0x00000001) {
1109 		u32 stat = nvkm_rd32(device, 0x61008c);
1110 		while (stat) {
1111 			int chid = __ffs(stat); stat &= ~(1 << chid);
1112 			nv50_disp_chan_uevent_send(disp, chid);
1113 			nvkm_wr32(device, 0x61008c, 1 << chid);
1114 		}
1115 		intr &= ~0x00000001;
1116 	}
1117 
1118 	if (intr & 0x00000002) {
1119 		u32 stat = nvkm_rd32(device, 0x61009c);
1120 		int chid = ffs(stat) - 1;
1121 		if (chid >= 0)
1122 			disp->func->intr_error(disp, chid);
1123 		intr &= ~0x00000002;
1124 	}
1125 
1126 	if (intr & 0x00100000) {
1127 		u32 stat = nvkm_rd32(device, 0x6100ac);
1128 		if (stat & 0x00000007) {
1129 			disp->super.pending = (stat & 0x00000007);
1130 			queue_work(disp->super.wq, &disp->super.work);
1131 			nvkm_wr32(device, 0x6100ac, disp->super.pending);
1132 			stat &= ~0x00000007;
1133 		}
1134 
1135 		if (stat) {
1136 			nvkm_warn(subdev, "intr24 %08x\n", stat);
1137 			nvkm_wr32(device, 0x6100ac, stat);
1138 		}
1139 
1140 		intr &= ~0x00100000;
1141 	}
1142 
1143 	list_for_each_entry(head, &disp->heads, head) {
1144 		const u32 hoff = head->id * 0x800;
1145 		u32 mask = 0x01000000 << head->id;
1146 		if (mask & intr) {
1147 			u32 stat = nvkm_rd32(device, 0x6100bc + hoff);
1148 			if (stat & 0x00000001)
1149 				nvkm_disp_vblank(disp, head->id);
1150 			nvkm_mask(device, 0x6100bc + hoff, 0, 0);
1151 			nvkm_rd32(device, 0x6100c0 + hoff);
1152 		}
1153 	}
1154 }
1155 
1156 void
1157 gf119_disp_fini(struct nvkm_disp *disp)
1158 {
1159 	struct nvkm_device *device = disp->engine.subdev.device;
1160 	/* disable all interrupts */
1161 	nvkm_wr32(device, 0x6100b0, 0x00000000);
1162 }
1163 
1164 int
1165 gf119_disp_init(struct nvkm_disp *disp)
1166 {
1167 	struct nvkm_device *device = disp->engine.subdev.device;
1168 	struct nvkm_head *head;
1169 	u32 tmp;
1170 	int i;
1171 
1172 	/* The below segments of code copying values from one register to
1173 	 * another appear to inform EVO of the display capabilities or
1174 	 * something similar.
1175 	 */
1176 
1177 	/* ... CRTC caps */
1178 	list_for_each_entry(head, &disp->heads, head) {
1179 		const u32 hoff = head->id * 0x800;
1180 		tmp = nvkm_rd32(device, 0x616104 + hoff);
1181 		nvkm_wr32(device, 0x6101b4 + hoff, tmp);
1182 		tmp = nvkm_rd32(device, 0x616108 + hoff);
1183 		nvkm_wr32(device, 0x6101b8 + hoff, tmp);
1184 		tmp = nvkm_rd32(device, 0x61610c + hoff);
1185 		nvkm_wr32(device, 0x6101bc + hoff, tmp);
1186 	}
1187 
1188 	/* ... DAC caps */
1189 	for (i = 0; i < disp->dac.nr; i++) {
1190 		tmp = nvkm_rd32(device, 0x61a000 + (i * 0x800));
1191 		nvkm_wr32(device, 0x6101c0 + (i * 0x800), tmp);
1192 	}
1193 
1194 	/* ... SOR caps */
1195 	for (i = 0; i < disp->sor.nr; i++) {
1196 		tmp = nvkm_rd32(device, 0x61c000 + (i * 0x800));
1197 		nvkm_wr32(device, 0x6301c4 + (i * 0x800), tmp);
1198 	}
1199 
1200 	/* steal display away from vbios, or something like that */
1201 	if (nvkm_rd32(device, 0x6100ac) & 0x00000100) {
1202 		nvkm_wr32(device, 0x6100ac, 0x00000100);
1203 		nvkm_mask(device, 0x6194e8, 0x00000001, 0x00000000);
1204 		if (nvkm_msec(device, 2000,
1205 			if (!(nvkm_rd32(device, 0x6194e8) & 0x00000002))
1206 				break;
1207 		) < 0)
1208 			return -EBUSY;
1209 	}
1210 
1211 	/* point at display engine memory area (hash table, objects) */
1212 	nvkm_wr32(device, 0x610010, (disp->inst->addr >> 8) | 9);
1213 
1214 	/* enable supervisor interrupts, disable everything else */
1215 	nvkm_wr32(device, 0x610090, 0x00000000);
1216 	nvkm_wr32(device, 0x6100a0, 0x00000000);
1217 	nvkm_wr32(device, 0x6100b0, 0x00000307);
1218 
1219 	/* disable underflow reporting, preventing an intermittent issue
1220 	 * on some gk104 boards where the production vbios left this
1221 	 * setting enabled by default.
1222 	 *
1223 	 * ftp://download.nvidia.com/open-gpu-doc/gk104-disable-underflow-reporting/1/gk104-disable-underflow-reporting.txt
1224 	 */
1225 	list_for_each_entry(head, &disp->heads, head) {
1226 		const u32 hoff = head->id * 0x800;
1227 		nvkm_mask(device, 0x616308 + hoff, 0x00000111, 0x00000010);
1228 	}
1229 
1230 	return 0;
1231 }
1232 
1233 static const struct nvkm_disp_func
1234 gf119_disp = {
1235 	.oneinit = nv50_disp_oneinit,
1236 	.init = gf119_disp_init,
1237 	.fini = gf119_disp_fini,
1238 	.intr = gf119_disp_intr,
1239 	.intr_error = gf119_disp_intr_error,
1240 	.super = gf119_disp_super,
1241 	.uevent = &gf119_disp_chan_uevent,
1242 	.head = { .cnt = gf119_head_cnt, .new = gf119_head_new },
1243 	.dac = { .cnt = gf119_dac_cnt, .new = gf119_dac_new },
1244 	.sor = { .cnt = gf119_sor_cnt, .new = gf119_sor_new },
1245 	.root = { 0,0,GF110_DISP },
1246 	.user = {
1247 		{{0,0,GF110_DISP_CURSOR             }, nvkm_disp_chan_new, &gf119_disp_curs },
1248 		{{0,0,GF110_DISP_OVERLAY            }, nvkm_disp_chan_new, &gf119_disp_oimm },
1249 		{{0,0,GF110_DISP_BASE_CHANNEL_DMA   }, nvkm_disp_chan_new, &gf119_disp_base },
1250 		{{0,0,GF110_DISP_CORE_CHANNEL_DMA   }, nvkm_disp_core_new, &gf119_disp_core },
1251 		{{0,0,GF110_DISP_OVERLAY_CONTROL_DMA}, nvkm_disp_chan_new, &gf119_disp_ovly },
1252 		{}
1253 	},
1254 };
1255 
1256 int
1257 gf119_disp_new(struct nvkm_device *device, enum nvkm_subdev_type type, int inst,
1258 	       struct nvkm_disp **pdisp)
1259 {
1260 	return nvkm_disp_new_(&gf119_disp, device, type, inst, pdisp);
1261 }
1262