xref: /freebsd/sys/arm/nvidia/drm2/tegra_dc.c (revision d65cd7a57bf0600b722afc770838a5d0c1c3a8e1)
1 /*-
2  * Copyright (c) 2015 Michal Meloun
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24  * SUCH DAMAGE.
25  */
26 
27 #include <sys/cdefs.h>
28 __FBSDID("$FreeBSD$");
29 
30 #include <sys/param.h>
31 #include <sys/systm.h>
32 #include <sys/bus.h>
33 #include <sys/gpio.h>
34 #include <sys/kernel.h>
35 #include <sys/module.h>
36 #include <sys/malloc.h>
37 #include <sys/rman.h>
38 #include <sys/sysctl.h>
39 
40 #include <machine/bus.h>
41 
42 #include <dev/extres/clk/clk.h>
43 #include <dev/extres/hwreset/hwreset.h>
44 #include <dev/drm2/drmP.h>
45 #include <dev/drm2/drm_crtc_helper.h>
46 #include <dev/drm2/drm_fb_helper.h>
47 #include <dev/drm2/drm_fixed.h>
48 #include <dev/ofw/ofw_bus.h>
49 #include <dev/ofw/ofw_bus_subr.h>
50 
51 #include <arm/nvidia/drm2/tegra_dc_reg.h>
52 #include <arm/nvidia/drm2/tegra_drm.h>
53 #include <arm/nvidia/tegra_pmc.h>
54 
55 #include "tegra_drm_if.h"
56 #include "tegra_dc_if.h"
57 
58 #define	WR4(_sc, _r, _v)	bus_write_4((_sc)->mem_res, 4 * (_r), (_v))
59 #define	RD4(_sc, _r)		bus_read_4((_sc)->mem_res, 4 * (_r))
60 
61 #define	LOCK(_sc)		mtx_lock(&(_sc)->mtx)
62 #define	UNLOCK(_sc)		mtx_unlock(&(_sc)->mtx)
63 #define	SLEEP(_sc, timeout)						\
64 	mtx_sleep(sc, &sc->mtx, 0, "tegra_dc_wait", timeout);
65 #define	LOCK_INIT(_sc)							\
66 	mtx_init(&_sc->mtx, device_get_nameunit(_sc->dev), "tegra_dc", MTX_DEF)
67 #define	LOCK_DESTROY(_sc)	mtx_destroy(&_sc->mtx)
68 #define	ASSERT_LOCKED(_sc)	mtx_assert(&_sc->mtx, MA_OWNED)
69 #define	ASSERT_UNLOCKED(_sc)	mtx_assert(&_sc->mtx, MA_NOTOWNED)
70 
71 
72 #define	SYNCPT_VBLANK0 26
73 #define	SYNCPT_VBLANK1 27
74 
75 #define	DC_MAX_PLANES 2		/* Maximum planes */
76 
77 /* DRM Formats supported by DC */
78 /* XXXX expand me */
79 static uint32_t dc_plane_formats[] = {
80 	DRM_FORMAT_XBGR8888,
81 	DRM_FORMAT_XRGB8888,
82 	DRM_FORMAT_RGB565,
83 	DRM_FORMAT_UYVY,
84 	DRM_FORMAT_YUYV,
85 	DRM_FORMAT_YUV420,
86 	DRM_FORMAT_YUV422,
87 };
88 
89 
90 /* Complete description of one window (plane) */
91 struct dc_window {
92 	/* Source (in framebuffer) rectangle, in pixels */
93 	u_int			src_x;
94 	u_int			src_y;
95 	u_int			src_w;
96 	u_int			src_h;
97 
98 	/* Destination (on display) rectangle, in pixels */
99 	u_int			dst_x;
100 	u_int			dst_y;
101 	u_int			dst_w;
102 	u_int			dst_h;
103 
104 	/* Parsed pixel format */
105 	u_int			bits_per_pixel;
106 	bool			is_yuv;		/* any YUV mode */
107 	bool			is_yuv_planar;	/* planar YUV mode */
108 	uint32_t 		color_mode;	/* DC_WIN_COLOR_DEPTH */
109 	uint32_t		swap;		/* DC_WIN_BYTE_SWAP */
110 	uint32_t		surface_kind;	/* DC_WINBUF_SURFACE_KIND */
111 	uint32_t		block_height;	/* DC_WINBUF_SURFACE_KIND */
112 
113 	/* Parsed flipping, rotation is not supported for pitched modes */
114 	bool			flip_x;		/* inverted X-axis */
115 	bool			flip_y;		/* inverted Y-axis */
116 	bool			transpose_xy;	/* swap X and Y-axis */
117 
118 	/* Color planes base addresses and strides */
119 	bus_size_t		base[3];
120 	uint32_t		stride[3];	/* stride[2] isn't used by HW */
121 };
122 
123 struct dc_softc {
124 	device_t		dev;
125 	struct resource		*mem_res;
126 	struct resource		*irq_res;
127 	void			*irq_ih;
128 	struct mtx		mtx;
129 
130 	clk_t			clk_parent;
131 	clk_t			clk_dc;
132 	hwreset_t		hwreset_dc;
133 
134 	int			pitch_align;
135 
136 	struct tegra_crtc 	tegra_crtc;
137 	struct drm_pending_vblank_event *event;
138 	struct drm_gem_object 	*cursor_gem;
139 };
140 
141 
142 static struct ofw_compat_data compat_data[] = {
143 	{"nvidia,tegra124-dc",	1},
144 	{NULL,			0},
145 };
146 
147 /* Convert standard drm pixel format to tegra windows parameters. */
148 static int
149 dc_parse_drm_format(struct tegra_fb *fb, struct dc_window *win)
150 {
151 	struct tegra_bo *bo;
152 	uint32_t cm;
153 	uint32_t sw;
154 	bool is_yuv, is_yuv_planar;
155 	int nplanes, i;
156 
157 	switch (fb->drm_fb.pixel_format) {
158 	case DRM_FORMAT_XBGR8888:
159 		sw = BYTE_SWAP(NOSWAP);
160 		cm = WIN_COLOR_DEPTH_R8G8B8A8;
161 		is_yuv = false;
162 		is_yuv_planar = false;
163 		break;
164 
165 	case DRM_FORMAT_XRGB8888:
166 		sw = BYTE_SWAP(NOSWAP);
167 		cm = WIN_COLOR_DEPTH_B8G8R8A8;
168 		is_yuv = false;
169 		is_yuv_planar = false;
170 		break;
171 
172 	case DRM_FORMAT_RGB565:
173 		sw = BYTE_SWAP(NOSWAP);
174 		cm = WIN_COLOR_DEPTH_B5G6R5;
175 		is_yuv = false;
176 		is_yuv_planar = false;
177 		break;
178 
179 	case DRM_FORMAT_UYVY:
180 		sw = BYTE_SWAP(NOSWAP);
181 		cm = WIN_COLOR_DEPTH_YCbCr422;
182 		is_yuv = true;
183 		is_yuv_planar = false;
184 		break;
185 
186 	case DRM_FORMAT_YUYV:
187 		sw = BYTE_SWAP(SWAP2);
188 		cm = WIN_COLOR_DEPTH_YCbCr422;
189 		is_yuv = true;
190 		is_yuv_planar = false;
191 		break;
192 
193 	case DRM_FORMAT_YUV420:
194 		sw = BYTE_SWAP(NOSWAP);
195 		cm = WIN_COLOR_DEPTH_YCbCr420P;
196 		is_yuv = true;
197 		is_yuv_planar = true;
198 		break;
199 
200 	case DRM_FORMAT_YUV422:
201 		sw = BYTE_SWAP(NOSWAP);
202 		cm = WIN_COLOR_DEPTH_YCbCr422P;
203 		is_yuv = true;
204 		is_yuv_planar = true;
205 		break;
206 
207 	default:
208 		/* Unsupported format */
209 		return (-EINVAL);
210 	}
211 
212 	/* Basic check of arguments. */
213 	switch (fb->rotation) {
214 	case 0:
215 	case 180:
216 		break;
217 
218 	case 90: 		/* Rotation is supported only */
219 	case 270:		/*  for block linear surfaces */
220 		if (!fb->block_linear)
221 			return (-EINVAL);
222 		break;
223 
224 	default:
225 		return (-EINVAL);
226 	}
227 	/* XXX Add more checks (sizes, scaling...) */
228 
229 	if (win == NULL)
230 		return (0);
231 
232 	win->surface_kind =
233 	    fb->block_linear ? SURFACE_KIND_BL_16B2: SURFACE_KIND_PITCH;
234 	win->block_height = fb->block_height;
235 	switch (fb->rotation) {
236 	case 0:					/* (0,0,0) */
237 		win->transpose_xy = false;
238 		win->flip_x = false;
239 		win->flip_y = false;
240 		break;
241 
242 	case 90:				/* (1,0,1) */
243 		win->transpose_xy = true;
244 		win->flip_x = false;
245 		win->flip_y = true;
246 		break;
247 
248 	case 180:				/* (0,1,1) */
249 		win->transpose_xy = false;
250 		win->flip_x = true;
251 		win->flip_y = true;
252 		break;
253 
254 	case 270:				/* (1,1,0) */
255 		win->transpose_xy = true;
256 		win->flip_x = true;
257 		win->flip_y = false;
258 		break;
259 	}
260 	win->flip_x ^= fb->flip_x;
261 	win->flip_y ^= fb->flip_y;
262 
263 	win->color_mode = cm;
264 	win->swap = sw;
265 	win->bits_per_pixel = fb->drm_fb.bits_per_pixel;
266 	win->is_yuv = is_yuv;
267 	win->is_yuv_planar = is_yuv_planar;
268 
269 	nplanes = drm_format_num_planes(fb->drm_fb.pixel_format);
270 	for (i = 0; i < nplanes; i++) {
271 		bo = fb->planes[i];
272 		win->base[i] = bo->pbase + fb->drm_fb.offsets[i];
273 		win->stride[i] = fb->drm_fb.pitches[i];
274 	}
275 	return (0);
276 }
277 
278 /*
279  * Scaling functions.
280  *
281  * It's unclear if we want/must program the fractional portion
282  * (aka bias) of init_dda registers, mainly when mirrored axis
283  * modes are used.
284  * For now, we use 1.0 as recommended by TRM.
285  */
286 static inline uint32_t
287 dc_scaling_init(uint32_t start)
288 {
289 
290 	return (1 << 12);
291 }
292 
293 static inline uint32_t
294 dc_scaling_incr(uint32_t src, uint32_t dst, uint32_t maxscale)
295 {
296 	uint32_t val;
297 
298 	val = (src - 1) << 12 ; /* 4.12 fixed float */
299 	val /= (dst - 1);
300 	if (val  > (maxscale << 12))
301 		val = maxscale << 12;
302 	return val;
303 }
304 
305 /* -------------------------------------------------------------------
306  *
307  *    HW Access.
308  *
309  */
310 
311 /*
312  * Setup pixel clock.
313  * Minimal frequency is pixel clock, but output is free to select
314  * any higher.
315  */
316 static int
317 dc_setup_clk(struct dc_softc *sc, struct drm_crtc *crtc,
318     struct drm_display_mode *mode, uint32_t *div)
319 {
320 	uint64_t pclk, freq;
321 	struct tegra_drm_encoder *output;
322 	struct drm_encoder *encoder;
323 	long rv;
324 
325 	pclk = mode->clock * 1000;
326 
327 	/* Find attached encoder */
328 	output = NULL;
329 	list_for_each_entry(encoder, &crtc->dev->mode_config.encoder_list,
330 	    head) {
331 		if (encoder->crtc == crtc) {
332 			output = container_of(encoder, struct tegra_drm_encoder,
333 			    encoder);
334 			break;
335 		}
336 	}
337 	if (output == NULL)
338 		return (-ENODEV);
339 
340 	if (output->setup_clock == NULL)
341 		panic("Output have not setup_clock function.\n");
342 	rv = output->setup_clock(output, sc->clk_dc, pclk);
343 	if (rv != 0) {
344 		device_printf(sc->dev, "Cannot setup pixel clock: %llu\n",
345 		    pclk);
346 		return (rv);
347 	}
348 
349 	rv = clk_get_freq(sc->clk_dc, &freq);
350 	*div = (freq * 2 / pclk) - 2;
351 
352 	DRM_DEBUG_KMS("frequency: %llu, DC divider: %u\n", freq, *div);
353 
354 	return 0;
355 }
356 
357 static void
358 dc_setup_window(struct dc_softc *sc, unsigned int index, struct dc_window *win)
359 {
360 	uint32_t h_offset, v_offset, h_size, v_size, bpp;
361 	uint32_t h_init_dda, v_init_dda, h_incr_dda, v_incr_dda;
362 	uint32_t val;
363 
364 #ifdef DMR_DEBUG_WINDOW
365 	printf("%s window: %d\n", __func__, index);
366 	printf("  src: x: %d, y: %d, w: %d, h: %d\n",
367 	   win->src_x, win->src_y, win->src_w, win->src_h);
368 	printf("  dst: x: %d, y: %d, w: %d, h: %d\n",
369 	   win->dst_x, win->dst_y, win->dst_w, win->dst_h);
370 	printf("  bpp: %d, color_mode: %d, swap: %d\n",
371 	   win->bits_per_pixel, win->color_mode, win->swap);
372 #endif
373 
374 	if (win->is_yuv)
375 		bpp = win->is_yuv_planar ? 1 : 2;
376 	else
377 		bpp = (win->bits_per_pixel + 7) / 8;
378 
379 	if (!win->transpose_xy) {
380 		h_size = win->src_w * bpp;
381 		v_size = win->src_h;
382 	} else {
383 		h_size = win->src_h * bpp;
384 		v_size = win->src_w;
385 	}
386 
387 	h_offset = win->src_x * bpp;
388 	v_offset = win->src_y;
389 	if (win->flip_x) {
390 		h_offset += win->src_w * bpp - 1;
391 	}
392 	if (win->flip_y)
393 		v_offset += win->src_h - 1;
394 
395 	/* Adjust offsets for planar yuv modes */
396 	if (win->is_yuv_planar) {
397 		h_offset &= ~1;
398 		if (win->flip_x )
399 			h_offset |= 1;
400 		v_offset &= ~1;
401 		if (win->flip_y )
402 			v_offset |= 1;
403 	}
404 
405 	/* Setup scaling. */
406 	if (!win->transpose_xy) {
407 		h_init_dda = dc_scaling_init(win->src_x);
408 		v_init_dda = dc_scaling_init(win->src_y);
409 		h_incr_dda = dc_scaling_incr(win->src_w, win->dst_w, 4);
410 		v_incr_dda = dc_scaling_incr(win->src_h, win->dst_h, 15);
411 	} else {
412 		h_init_dda =  dc_scaling_init(win->src_y);
413 		v_init_dda =  dc_scaling_init(win->src_x);
414 		h_incr_dda = dc_scaling_incr(win->src_h, win->dst_h, 4);
415 		v_incr_dda = dc_scaling_incr(win->src_w, win->dst_w, 15);
416 	}
417 #ifdef DMR_DEBUG_WINDOW
418 	printf("\n");
419 	printf("  bpp: %d, size: h: %d v: %d, offset: h:%d v: %d\n",
420 	   bpp, h_size, v_size, h_offset, v_offset);
421 	printf("  init_dda: h: %d v: %d, incr_dda: h: %d v: %d\n",
422 	   h_init_dda, v_init_dda, h_incr_dda, v_incr_dda);
423 #endif
424 
425 	LOCK(sc);
426 
427 	/* Select target window  */
428 	val = WINDOW_A_SELECT << index;
429 	WR4(sc, DC_CMD_DISPLAY_WINDOW_HEADER, val);
430 
431 	/* Sizes */
432 	WR4(sc, DC_WIN_POSITION, WIN_POSITION(win->dst_x, win->dst_y));
433 	WR4(sc, DC_WIN_SIZE, WIN_SIZE(win->dst_w, win->dst_h));
434 	WR4(sc, DC_WIN_PRESCALED_SIZE, WIN_PRESCALED_SIZE(h_size, v_size));
435 
436 	/* DDA */
437 	WR4(sc, DC_WIN_DDA_INCREMENT,
438 	    WIN_DDA_INCREMENT(h_incr_dda, v_incr_dda));
439 	WR4(sc, DC_WIN_H_INITIAL_DDA, h_init_dda);
440 	WR4(sc, DC_WIN_V_INITIAL_DDA, v_init_dda);
441 
442 	/* Color planes base addresses and strides */
443 	WR4(sc, DC_WINBUF_START_ADDR, win->base[0]);
444 	if (win->is_yuv_planar) {
445 		WR4(sc, DC_WINBUF_START_ADDR_U, win->base[1]);
446 		WR4(sc, DC_WINBUF_START_ADDR_V, win->base[2]);
447 		WR4(sc, DC_WIN_LINE_STRIDE,
448 		     win->stride[1] << 16 | win->stride[0]);
449 	} else {
450 		WR4(sc, DC_WIN_LINE_STRIDE, win->stride[0]);
451 	}
452 
453 	/* Offsets for rotation and axis flip */
454 	WR4(sc, DC_WINBUF_ADDR_H_OFFSET, h_offset);
455 	WR4(sc, DC_WINBUF_ADDR_V_OFFSET, v_offset);
456 
457 	/* Color format */
458 	WR4(sc, DC_WIN_COLOR_DEPTH, win->color_mode);
459 	WR4(sc, DC_WIN_BYTE_SWAP, win->swap);
460 
461 	/* Tiling */
462 	val = win->surface_kind;
463 	if (win->surface_kind == SURFACE_KIND_BL_16B2)
464 		val |= SURFACE_KIND_BLOCK_HEIGHT(win->block_height);
465 	WR4(sc, DC_WINBUF_SURFACE_KIND, val);
466 
467 	/* Color space coefs for YUV modes */
468 	if (win->is_yuv) {
469 		WR4(sc, DC_WINC_CSC_YOF,   0x00f0);
470 		WR4(sc, DC_WINC_CSC_KYRGB, 0x012a);
471 		WR4(sc, DC_WINC_CSC_KUR,   0x0000);
472 		WR4(sc, DC_WINC_CSC_KVR,   0x0198);
473 		WR4(sc, DC_WINC_CSC_KUG,   0x039b);
474 		WR4(sc, DC_WINC_CSC_KVG,   0x032f);
475 		WR4(sc, DC_WINC_CSC_KUB,   0x0204);
476 		WR4(sc, DC_WINC_CSC_KVB,   0x0000);
477 	}
478 
479 	val = WIN_ENABLE;
480 	if (win->is_yuv)
481 		val |= CSC_ENABLE;
482 	else if (win->bits_per_pixel < 24)
483 		val |= COLOR_EXPAND;
484 	if (win->flip_y)
485 		val |= V_DIRECTION;
486 	if (win->flip_x)
487 		val |= H_DIRECTION;
488 	if (win->transpose_xy)
489 		val |= SCAN_COLUMN;
490 	WR4(sc, DC_WINC_WIN_OPTIONS, val);
491 
492 #ifdef DMR_DEBUG_WINDOW
493 	/* Set underflow debug mode -> highlight missing pixels. */
494 	WR4(sc, DC_WINBUF_UFLOW_CTRL, UFLOW_CTR_ENABLE);
495 	WR4(sc, DC_WINBUF_UFLOW_DBG_PIXEL, 0xFFFF0000);
496 #endif
497 
498 	UNLOCK(sc);
499 }
500 
501 /* -------------------------------------------------------------------
502  *
503  *    Plane functions.
504  *
505  */
506 static int
507 dc_plane_update(struct drm_plane *drm_plane, struct drm_crtc *drm_crtc,
508     struct drm_framebuffer *drm_fb,
509     int crtc_x, int crtc_y, unsigned int crtc_w, unsigned int crtc_h,
510     uint32_t src_x, uint32_t src_y, uint32_t src_w, uint32_t src_h)
511 {
512 	struct tegra_plane *plane;
513 	struct tegra_crtc *crtc;
514 	struct tegra_fb *fb;
515 	struct dc_softc *sc;
516 	struct dc_window win;
517 	int rv;
518 
519 	plane = container_of(drm_plane, struct tegra_plane, drm_plane);
520 	fb = container_of(drm_fb, struct tegra_fb, drm_fb);
521 	crtc = container_of(drm_crtc, struct tegra_crtc, drm_crtc);
522 	sc = device_get_softc(crtc->dev);
523 
524 	memset(&win, 0, sizeof(win));
525 	win.src_x = src_x >> 16;
526 	win.src_y = src_y >> 16;
527 	win.src_w = src_w >> 16;
528 	win.src_h = src_h >> 16;
529 	win.dst_x = crtc_x;
530 	win.dst_y = crtc_y;
531 	win.dst_w = crtc_w;
532 	win.dst_h = crtc_h;
533 
534 	rv = dc_parse_drm_format(fb, &win);
535 	if (rv != 0) {
536 		DRM_WARNING("unsupported pixel format %d\n",
537 		    fb->drm_fb.pixel_format);
538 		return (rv);
539 	}
540 
541 	dc_setup_window(sc, plane->index, &win);
542 
543 	WR4(sc, DC_CMD_STATE_CONTROL, WIN_A_UPDATE << plane->index);
544 	WR4(sc, DC_CMD_STATE_CONTROL, WIN_A_ACT_REQ << plane->index);
545 
546 	return (0);
547 }
548 
549 static int
550 dc_plane_disable(struct drm_plane *drm_plane)
551 {
552 	struct tegra_plane *plane;
553 	struct tegra_crtc *crtc;
554 	struct dc_softc *sc;
555 	uint32_t val, idx;
556 
557 	if (drm_plane->crtc == NULL)
558 		return (0);
559 	plane = container_of(drm_plane, struct tegra_plane, drm_plane);
560 	crtc = container_of(drm_plane->crtc, struct tegra_crtc, drm_crtc);
561 
562 	sc = device_get_softc(crtc->dev);
563 	idx = plane->index;
564 
565 	LOCK(sc);
566 
567 	WR4(sc, DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_A_SELECT << idx);
568 
569 	val = RD4(sc, DC_WINC_WIN_OPTIONS);
570 	val &= ~WIN_ENABLE;
571 	WR4(sc, DC_WINC_WIN_OPTIONS, val);
572 
573 	UNLOCK(sc);
574 
575 	WR4(sc, DC_CMD_STATE_CONTROL, WIN_A_UPDATE << idx);
576 	WR4(sc, DC_CMD_STATE_CONTROL, WIN_A_ACT_REQ << idx);
577 
578 	return (0);
579 }
580 
581 static void
582 dc_plane_destroy(struct drm_plane *plane)
583 {
584 
585 	dc_plane_disable(plane);
586 	drm_plane_cleanup(plane);
587 	free(plane, DRM_MEM_KMS);
588 }
589 
590 static const struct drm_plane_funcs dc_plane_funcs = {
591 	.update_plane = dc_plane_update,
592 	.disable_plane = dc_plane_disable,
593 	.destroy = dc_plane_destroy,
594 };
595 
596 /* -------------------------------------------------------------------
597  *
598  *    CRTC helper functions.
599  *
600  */
601 static void
602 dc_crtc_dpms(struct drm_crtc *crtc, int mode)
603 {
604 	/* Empty function */
605 }
606 
607 static bool
608 dc_crtc_mode_fixup(struct drm_crtc *crtc, const struct drm_display_mode *mode,
609     struct drm_display_mode *adjusted)
610 {
611 
612 	return (true);
613 }
614 
615 static int
616 dc_set_base(struct dc_softc *sc, int x, int y, struct tegra_fb *fb)
617 {
618 	struct dc_window win;
619 	int rv;
620 
621 	memset(&win, 0, sizeof(win));
622 	win.src_x = x;
623 	win.src_y = y;
624 	win.src_w = fb->drm_fb.width;
625 	win.src_h = fb->drm_fb.height;
626 	win.dst_x = x;
627 	win.dst_y = y;
628 	win.dst_w = fb->drm_fb.width;
629 	win.dst_h = fb->drm_fb.height;
630 
631 	rv = dc_parse_drm_format(fb, &win);
632 	if (rv != 0) {
633 		DRM_WARNING("unsupported pixel format %d\n",
634 		    fb->drm_fb.pixel_format);
635 		return (rv);
636 	}
637 	dc_setup_window(sc, 0, &win);
638 
639 	return (0);
640 }
641 
642 static int
643 dc_crtc_mode_set(struct drm_crtc *drm_crtc, struct drm_display_mode *mode,
644     struct drm_display_mode *adjusted, int x, int y,
645     struct drm_framebuffer *old_fb)
646 {
647 	struct dc_softc *sc;
648 	struct tegra_crtc *crtc;
649 	struct tegra_fb *fb;
650 	struct dc_window win;
651 	uint32_t div, h_ref_to_sync, v_ref_to_sync;
652 	int rv;
653 
654 	crtc = container_of(drm_crtc, struct tegra_crtc, drm_crtc);
655 	sc = device_get_softc(crtc->dev);
656 	fb = container_of(drm_crtc->fb, struct tegra_fb, drm_fb);
657 
658 
659 	h_ref_to_sync = 1;
660 	v_ref_to_sync = 1;
661 	/* Setup timing */
662 	rv = dc_setup_clk(sc, drm_crtc, mode, &div);
663 	if (rv != 0) {
664 		device_printf(sc->dev, "Cannot set pixel clock\n");
665 		return (rv);
666 	}
667 
668 	/* Timing */
669 	WR4(sc, DC_DISP_DISP_TIMING_OPTIONS, 0);
670 
671 	WR4(sc, DC_DISP_REF_TO_SYNC,
672 	    (v_ref_to_sync << 16) |
673 	     h_ref_to_sync);
674 
675 	WR4(sc, DC_DISP_SYNC_WIDTH,
676 	    ((mode->vsync_end - mode->vsync_start) << 16) |
677 	    ((mode->hsync_end - mode->hsync_start) <<  0));
678 
679 	WR4(sc, DC_DISP_BACK_PORCH,
680 	    ((mode->vtotal - mode->vsync_end) << 16) |
681 	    ((mode->htotal - mode->hsync_end) <<  0));
682 
683 	WR4(sc, DC_DISP_FRONT_PORCH,
684 	    ((mode->vsync_start - mode->vdisplay) << 16) |
685 	    ((mode->hsync_start - mode->hdisplay) <<  0));
686 
687 	WR4(sc, DC_DISP_DISP_ACTIVE,
688 	    (mode->vdisplay << 16) | mode->hdisplay);
689 
690 	WR4(sc, DC_DISP_DISP_INTERFACE_CONTROL, DISP_DATA_FORMAT(DF1P1C));
691 
692 	WR4(sc,DC_DISP_DISP_CLOCK_CONTROL,
693 	    SHIFT_CLK_DIVIDER(div) | PIXEL_CLK_DIVIDER(PCD1));
694 
695 	memset(&win, 0, sizeof(win));
696 	win.src_x = x;
697 	win.src_y = y;
698 	win.src_w = mode->hdisplay;
699 	win.src_h = mode->vdisplay;
700 	win.dst_x = x;
701 	win.dst_y = y;
702 	win.dst_w = mode->hdisplay;
703 	win.dst_h = mode->vdisplay;
704 
705 	rv = dc_parse_drm_format(fb, &win);
706 	if (rv != 0) {
707 		DRM_WARNING("unsupported pixel format %d\n",
708 		    drm_crtc->fb->pixel_format);
709 		return (rv);
710 	}
711 
712 	dc_setup_window(sc, 0, &win);
713 
714 	return (0);
715 
716 }
717 
718 static int
719 dc_crtc_mode_set_base(struct drm_crtc *drm_crtc, int x, int y,
720     struct drm_framebuffer *old_fb)
721 {
722 	struct dc_softc *sc;
723 	struct tegra_crtc *crtc;
724 	struct tegra_fb *fb;
725 	int rv;
726 
727 	crtc = container_of(drm_crtc, struct tegra_crtc, drm_crtc);
728 	fb = container_of(drm_crtc->fb, struct tegra_fb, drm_fb);
729 	sc = device_get_softc(crtc->dev);
730 
731 	rv = dc_set_base(sc, x, y, fb);
732 
733 	/* Commit */
734 	WR4(sc, DC_CMD_STATE_CONTROL, GENERAL_UPDATE | WIN_A_UPDATE);
735 	WR4(sc, DC_CMD_STATE_CONTROL, GENERAL_ACT_REQ | WIN_A_ACT_REQ);
736 	return (rv);
737 }
738 
739 
740 static void
741 dc_crtc_prepare(struct drm_crtc *drm_crtc)
742 {
743 
744 	struct dc_softc *sc;
745 	struct tegra_crtc *crtc;
746 	uint32_t val;
747 
748 	crtc = container_of(drm_crtc, struct tegra_crtc, drm_crtc);
749 	sc = device_get_softc(crtc->dev);
750 
751 	WR4(sc, DC_CMD_GENERAL_INCR_SYNCPT_CNTRL, SYNCPT_CNTRL_NO_STALL);
752 	/* XXX allocate syncpoint from host1x */
753 	WR4(sc, DC_CMD_CONT_SYNCPT_VSYNC, SYNCPT_VSYNC_ENABLE |
754 	    (sc->tegra_crtc.nvidia_head == 0 ? SYNCPT_VBLANK0: SYNCPT_VBLANK1));
755 
756 	WR4(sc, DC_CMD_DISPLAY_POWER_CONTROL,
757 	    PW0_ENABLE | PW1_ENABLE | PW2_ENABLE | PW3_ENABLE |
758 	    PW4_ENABLE | PM0_ENABLE | PM1_ENABLE);
759 
760 	val = RD4(sc, DC_CMD_DISPLAY_COMMAND);
761 	val |= DISPLAY_CTRL_MODE(CTRL_MODE_C_DISPLAY);
762 	WR4(sc, DC_CMD_DISPLAY_COMMAND, val);
763 
764 	WR4(sc, DC_CMD_INT_MASK,
765 	    WIN_A_UF_INT | WIN_B_UF_INT | WIN_C_UF_INT |
766 	    WIN_A_OF_INT | WIN_B_OF_INT | WIN_C_OF_INT);
767 
768 	WR4(sc, DC_CMD_INT_ENABLE,
769 	    VBLANK_INT | WIN_A_UF_INT | WIN_B_UF_INT | WIN_C_UF_INT |
770 	    WIN_A_OF_INT | WIN_B_OF_INT | WIN_C_OF_INT);
771 }
772 
773 static void
774 dc_crtc_commit(struct drm_crtc *drm_crtc)
775 {
776 	struct dc_softc *sc;
777 	struct tegra_crtc *crtc;
778 	uint32_t val;
779 
780 	crtc = container_of(drm_crtc, struct tegra_crtc, drm_crtc);
781 	sc = device_get_softc(crtc->dev);
782 
783 	WR4(sc, DC_CMD_STATE_CONTROL, GENERAL_UPDATE | WIN_A_UPDATE);
784 
785 	val = RD4(sc, DC_CMD_INT_MASK);
786 	val |= FRAME_END_INT;
787 	WR4(sc, DC_CMD_INT_MASK, val);
788 
789 	val = RD4(sc, DC_CMD_INT_ENABLE);
790 	val |= FRAME_END_INT;
791 	WR4(sc, DC_CMD_INT_ENABLE, val);
792 
793 	WR4(sc, DC_CMD_STATE_CONTROL,  GENERAL_ACT_REQ | WIN_A_ACT_REQ);
794 }
795 
796 static void
797 dc_crtc_load_lut(struct drm_crtc *crtc)
798 {
799 
800 	/* empty function */
801 }
802 
803 static const struct drm_crtc_helper_funcs dc_crtc_helper_funcs = {
804 	.dpms = dc_crtc_dpms,
805 	.mode_fixup = dc_crtc_mode_fixup,
806 	.mode_set = dc_crtc_mode_set,
807 	.mode_set_base = dc_crtc_mode_set_base,
808 	.prepare = dc_crtc_prepare,
809 	.commit = dc_crtc_commit,
810 	.load_lut = dc_crtc_load_lut,
811 };
812 
813 static int
814 drm_crtc_index(struct drm_crtc *crtc)
815 {
816 	int idx;
817 	struct drm_crtc *tmp;
818 
819 	idx = 0;
820 	list_for_each_entry(tmp, &crtc->dev->mode_config.crtc_list, head) {
821 		if (tmp == crtc)
822 			return (idx);
823 		idx++;
824 	}
825 	panic("Cannot find CRTC");
826 }
827 
828 /* -------------------------------------------------------------------
829  *
830  *   Exported functions (mainly vsync related).
831  *
832  * XXX revisit this -> convert to bus methods?
833  */
834 int
835 tegra_dc_get_pipe(struct drm_crtc *drm_crtc)
836 {
837 	struct tegra_crtc *crtc;
838 
839 	crtc = container_of(drm_crtc, struct tegra_crtc, drm_crtc);
840 	return (crtc->nvidia_head);
841 }
842 
843 void
844 tegra_dc_enable_vblank(struct drm_crtc *drm_crtc)
845 {
846 	struct dc_softc *sc;
847 	struct tegra_crtc *crtc;
848 	uint32_t val;
849 
850 	crtc = container_of(drm_crtc, struct tegra_crtc, drm_crtc);
851 	sc = device_get_softc(crtc->dev);
852 
853 	LOCK(sc);
854 	val = RD4(sc, DC_CMD_INT_MASK);
855 	val |= VBLANK_INT;
856 	WR4(sc, DC_CMD_INT_MASK, val);
857 	UNLOCK(sc);
858 }
859 
860 void
861 tegra_dc_disable_vblank(struct drm_crtc *drm_crtc)
862 {
863 	struct dc_softc *sc;
864 	struct tegra_crtc *crtc;
865 	uint32_t val;
866 
867 	crtc = container_of(drm_crtc, struct tegra_crtc, drm_crtc);
868 	sc = device_get_softc(crtc->dev);
869 
870 	LOCK(sc);
871 	val = RD4(sc, DC_CMD_INT_MASK);
872 	val &= ~VBLANK_INT;
873 	WR4(sc, DC_CMD_INT_MASK, val);
874 	UNLOCK(sc);
875 }
876 
877 static void
878 dc_finish_page_flip(struct dc_softc *sc)
879 {
880 	struct drm_crtc *drm_crtc;
881 	struct drm_device *drm;
882 	struct tegra_fb *fb;
883 	struct tegra_bo *bo;
884 	uint32_t base;
885 	int idx;
886 
887 	drm_crtc = &sc->tegra_crtc.drm_crtc;
888 	drm = drm_crtc->dev;
889 	fb = container_of(drm_crtc->fb, struct tegra_fb, drm_fb);
890 
891 	mtx_lock(&drm->event_lock);
892 
893 	if (sc->event == NULL) {
894 		mtx_unlock(&drm->event_lock);
895 		return;
896 	}
897 
898 	LOCK(sc);
899 	/* Read active copy of WINBUF_START_ADDR */
900 	WR4(sc, DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_A_SELECT);
901 	WR4(sc, DC_CMD_STATE_ACCESS, READ_MUX);
902 	base = RD4(sc, DC_WINBUF_START_ADDR);
903 	WR4(sc, DC_CMD_STATE_ACCESS, 0);
904 	UNLOCK(sc);
905 
906 	/* Is already active */
907 	bo = tegra_fb_get_plane(fb, 0);
908 	if (base == (bo->pbase + fb->drm_fb.offsets[0])) {
909 		idx = drm_crtc_index(drm_crtc);
910 		drm_send_vblank_event(drm, idx, sc->event);
911 		drm_vblank_put(drm, idx);
912 		sc->event = NULL;
913 	}
914 
915 	mtx_unlock(&drm->event_lock);
916 }
917 
918 
919 void
920 tegra_dc_cancel_page_flip(struct drm_crtc *drm_crtc, struct drm_file *file)
921 {
922 	struct dc_softc *sc;
923 	struct tegra_crtc *crtc;
924 	struct drm_device *drm;
925 
926 	crtc = container_of(drm_crtc, struct tegra_crtc, drm_crtc);
927 	sc = device_get_softc(crtc->dev);
928 	drm = drm_crtc->dev;
929 	mtx_lock(&drm->event_lock);
930 
931 	if ((sc->event != NULL) && (sc->event->base.file_priv == file)) {
932 		sc->event->base.destroy(&sc->event->base);
933 		drm_vblank_put(drm, drm_crtc_index(drm_crtc));
934 		sc->event = NULL;
935 	}
936 	mtx_unlock(&drm->event_lock);
937 }
938 
939 /* -------------------------------------------------------------------
940  *
941  *    CRTC functions.
942  *
943  */
944 static int
945 dc_page_flip(struct drm_crtc *drm_crtc, struct drm_framebuffer *drm_fb,
946     struct drm_pending_vblank_event *event)
947 {
948 	struct dc_softc *sc;
949 	struct tegra_crtc *crtc;
950 	struct tegra_fb *fb;
951 	struct drm_device *drm;
952 
953 	crtc = container_of(drm_crtc, struct tegra_crtc, drm_crtc);
954 	sc = device_get_softc(crtc->dev);
955 	fb = container_of(drm_crtc->fb, struct tegra_fb, drm_fb);
956 	drm = drm_crtc->dev;
957 
958 	if (sc->event != NULL)
959 		return (-EBUSY);
960 
961 	if (event != NULL) {
962 		event->pipe = sc->tegra_crtc.nvidia_head;
963 		sc->event = event;
964 		drm_vblank_get(drm, event->pipe);
965 	}
966 
967 	dc_set_base(sc, drm_crtc->x, drm_crtc->y, fb);
968 	drm_crtc->fb = drm_fb;
969 
970 	/* Commit */
971 	WR4(sc, DC_CMD_STATE_CONTROL, GENERAL_UPDATE | WIN_A_UPDATE);
972 
973 	return (0);
974 }
975 
976 static int
977 dc_cursor_set(struct drm_crtc *drm_crtc, struct drm_file *file,
978     uint32_t handle, uint32_t width, uint32_t height)
979 {
980 
981 	struct dc_softc *sc;
982 	struct tegra_crtc *crtc;
983 	struct drm_gem_object *gem;
984 	struct tegra_bo *bo;
985 	int i;
986 	uint32_t val, *src, *dst;
987 
988 	crtc = container_of(drm_crtc, struct tegra_crtc, drm_crtc);
989 	sc = device_get_softc(crtc->dev);
990 
991 	if (width != height)
992 		return (-EINVAL);
993 
994 	switch (width) {
995 	case 32:
996 		val = CURSOR_SIZE(C32x32);
997 		break;
998 	case 64:
999 		val = CURSOR_SIZE(C64x64);
1000 		break;
1001 	case 128:
1002 		val = CURSOR_SIZE(C128x128);
1003 		break;
1004 	case 256:
1005 		val = CURSOR_SIZE(C256x256);
1006 		break;
1007 	default:
1008 		return (-EINVAL);
1009 	}
1010 
1011 	bo = NULL;
1012 	gem = NULL;
1013 	if (handle != 0) {
1014 		gem = drm_gem_object_lookup(drm_crtc->dev, file, handle);
1015 		if (gem == NULL)
1016 			return (-ENOENT);
1017 		bo = container_of(gem, struct tegra_bo, gem_obj);
1018 	}
1019 
1020 	if (sc->cursor_gem != NULL) {
1021 		drm_gem_object_unreference(sc->cursor_gem);
1022 	}
1023 	sc->cursor_gem = gem;
1024 
1025 	if (bo != NULL) {
1026 		/*
1027 		 * Copy cursor into cache and convert it from ARGB to RGBA.
1028 		 * XXXX - this is broken by design - client can write to BO at
1029 		 * any time. We can dedicate other window for cursor or switch
1030 		 * to sw cursor in worst case.
1031 		 */
1032 		src = (uint32_t *)bo->vbase;
1033 		dst = (uint32_t *)crtc->cursor_vbase;
1034 		for (i = 0; i < width * height; i++)
1035 			dst[i] = (src[i] << 8) | (src[i] >> 24);
1036 
1037 		val |= CURSOR_CLIP(CC_DISPLAY);
1038 		val |= CURSOR_START_ADDR(crtc->cursor_pbase);
1039 		WR4(sc, DC_DISP_CURSOR_START_ADDR, val);
1040 
1041 		val = RD4(sc, DC_DISP_BLEND_CURSOR_CONTROL);
1042 		val &= ~CURSOR_DST_BLEND_FACTOR_SELECT(~0);
1043 		val &= ~CURSOR_SRC_BLEND_FACTOR_SELECT(~0);
1044 		val |= CURSOR_MODE_SELECT;
1045 		val |= CURSOR_DST_BLEND_FACTOR_SELECT(DST_NEG_K1_TIMES_SRC);
1046 		val |= CURSOR_SRC_BLEND_FACTOR_SELECT(SRC_BLEND_K1_TIMES_SRC);
1047 		val |= CURSOR_ALPHA(~0);
1048 		WR4(sc, DC_DISP_BLEND_CURSOR_CONTROL, val);
1049 
1050 		val = RD4(sc, DC_DISP_DISP_WIN_OPTIONS);
1051 		val |= CURSOR_ENABLE;
1052 		WR4(sc, DC_DISP_DISP_WIN_OPTIONS, val);
1053 	} else {
1054 		val = RD4(sc, DC_DISP_DISP_WIN_OPTIONS);
1055 		val &= ~CURSOR_ENABLE;
1056 		WR4(sc, DC_DISP_DISP_WIN_OPTIONS, val);
1057 	}
1058 
1059 	/* XXX This fixes cursor underflow issues, but why ?  */
1060 	WR4(sc, DC_DISP_CURSOR_UNDERFLOW_CTRL, CURSOR_UFLOW_CYA);
1061 
1062 	WR4(sc, DC_CMD_STATE_CONTROL, GENERAL_UPDATE | CURSOR_UPDATE );
1063 	WR4(sc, DC_CMD_STATE_CONTROL, GENERAL_ACT_REQ | CURSOR_ACT_REQ);
1064 	return (0);
1065 }
1066 
1067 static int
1068 dc_cursor_move(struct drm_crtc *drm_crtc, int x, int y)
1069 {
1070 	struct dc_softc *sc;
1071 	struct tegra_crtc *crtc;
1072 
1073 	crtc = container_of(drm_crtc, struct tegra_crtc, drm_crtc);
1074 	sc = device_get_softc(crtc->dev);
1075 	WR4(sc, DC_DISP_CURSOR_POSITION, CURSOR_POSITION(x, y));
1076 
1077 	WR4(sc, DC_CMD_STATE_CONTROL, CURSOR_UPDATE);
1078 	WR4(sc, DC_CMD_STATE_CONTROL, CURSOR_ACT_REQ);
1079 
1080 	return (0);
1081 }
1082 
1083 static void
1084 dc_destroy(struct drm_crtc *crtc)
1085 {
1086 
1087 	drm_crtc_cleanup(crtc);
1088 	memset(crtc, 0, sizeof(*crtc));
1089 }
1090 
1091 static const struct drm_crtc_funcs dc_crtc_funcs = {
1092 	.page_flip = dc_page_flip,
1093 	.cursor_set = dc_cursor_set,
1094 	.cursor_move = dc_cursor_move,
1095 	.set_config = drm_crtc_helper_set_config,
1096 	.destroy = dc_destroy,
1097 };
1098 
1099 /* -------------------------------------------------------------------
1100  *
1101  *    Bus and infrastructure.
1102  *
1103  */
1104 static int
1105 dc_init_planes(struct dc_softc *sc, struct tegra_drm *drm)
1106 {
1107 	int i, rv;
1108 	struct tegra_plane *plane;
1109 
1110 	rv = 0;
1111 	for (i = 0; i < DC_MAX_PLANES; i++) {
1112 		plane = malloc(sizeof(*plane), DRM_MEM_KMS, M_WAITOK | M_ZERO);
1113 		plane->index = i + 1;
1114 		rv = drm_plane_init(&drm->drm_dev, &plane->drm_plane,
1115 		    1 << sc->tegra_crtc.nvidia_head, &dc_plane_funcs,
1116 		    dc_plane_formats, nitems(dc_plane_formats), false);
1117 		if (rv != 0) {
1118 			free(plane, DRM_MEM_KMS);
1119 			return (rv);
1120 		}
1121 	}
1122 	return 0;
1123 }
1124 
1125 static void
1126 dc_display_enable(device_t dev, bool enable)
1127 {
1128 	struct dc_softc *sc;
1129 	uint32_t val;
1130 
1131 	sc = device_get_softc(dev);
1132 
1133 	/* Set display mode */
1134 	val = enable ? CTRL_MODE_C_DISPLAY: CTRL_MODE_STOP;
1135 	WR4(sc, DC_CMD_DISPLAY_COMMAND, DISPLAY_CTRL_MODE(val));
1136 
1137 	/* and commit it*/
1138 	WR4(sc, DC_CMD_STATE_CONTROL, GENERAL_UPDATE);
1139 	WR4(sc, DC_CMD_STATE_CONTROL, GENERAL_ACT_REQ);
1140 }
1141 
1142 static void
1143 dc_hdmi_enable(device_t dev, bool enable)
1144 {
1145 	struct dc_softc *sc;
1146 	uint32_t val;
1147 
1148 	sc = device_get_softc(dev);
1149 
1150 	val = RD4(sc, DC_DISP_DISP_WIN_OPTIONS);
1151 	if (enable)
1152 		val |= HDMI_ENABLE;
1153 	else
1154 		val &= ~HDMI_ENABLE;
1155 	WR4(sc, DC_DISP_DISP_WIN_OPTIONS, val);
1156 
1157 }
1158 
1159 static void
1160 dc_setup_timing(device_t dev, int h_pulse_start)
1161 {
1162 	struct dc_softc *sc;
1163 
1164 	sc = device_get_softc(dev);
1165 
1166 	/* Setup display timing */
1167 	WR4(sc, DC_DISP_DISP_TIMING_OPTIONS, VSYNC_H_POSITION(1));
1168 	WR4(sc, DC_DISP_DISP_COLOR_CONTROL,
1169 	    DITHER_CONTROL(DITHER_DISABLE) | BASE_COLOR_SIZE(SIZE_BASE888));
1170 
1171 	WR4(sc, DC_DISP_DISP_SIGNAL_OPTIONS0, H_PULSE2_ENABLE);
1172 	WR4(sc, DC_DISP_H_PULSE2_CONTROL,
1173 	    PULSE_CONTROL_QUAL(QUAL_VACTIVE) | PULSE_CONTROL_LAST(LAST_END_A));
1174 
1175 	WR4(sc, DC_DISP_H_PULSE2_POSITION_A,
1176 	    PULSE_START(h_pulse_start) | PULSE_END(h_pulse_start + 8));
1177 }
1178 
1179 static void
1180 dc_intr(void *arg)
1181 {
1182 	struct dc_softc *sc;
1183 	uint32_t status;
1184 
1185 	sc = arg;
1186 
1187 	/* Confirm interrupt */
1188 	status = RD4(sc, DC_CMD_INT_STATUS);
1189 	WR4(sc, DC_CMD_INT_STATUS, status);
1190 	if (status & VBLANK_INT) {
1191 		drm_handle_vblank(sc->tegra_crtc.drm_crtc.dev,
1192 		    sc->tegra_crtc.nvidia_head);
1193 		dc_finish_page_flip(sc);
1194 	}
1195 }
1196 
1197 static int
1198 dc_init_client(device_t dev, device_t host1x, struct tegra_drm *drm)
1199 {
1200 	struct dc_softc *sc;
1201 	int rv;
1202 
1203 	sc = device_get_softc(dev);
1204 
1205 	if (drm->pitch_align < sc->pitch_align)
1206 		drm->pitch_align = sc->pitch_align;
1207 
1208 	drm_crtc_init(&drm->drm_dev, &sc->tegra_crtc.drm_crtc, &dc_crtc_funcs);
1209 	drm_mode_crtc_set_gamma_size(&sc->tegra_crtc.drm_crtc, 256);
1210 	drm_crtc_helper_add(&sc->tegra_crtc.drm_crtc, &dc_crtc_helper_funcs);
1211 
1212 	rv = dc_init_planes(sc, drm);
1213 	if (rv!= 0){
1214 		device_printf(dev, "Cannot init planes\n");
1215 		return (rv);
1216 	}
1217 
1218 	WR4(sc, DC_CMD_INT_TYPE,
1219 	    WIN_A_UF_INT | WIN_B_UF_INT | WIN_C_UF_INT |
1220 	    WIN_A_OF_INT | WIN_B_OF_INT | WIN_C_OF_INT);
1221 
1222 	WR4(sc, DC_CMD_INT_POLARITY,
1223 	    WIN_A_UF_INT | WIN_B_UF_INT | WIN_C_UF_INT |
1224 	    WIN_A_OF_INT | WIN_B_OF_INT | WIN_C_OF_INT);
1225 
1226 	WR4(sc, DC_CMD_INT_ENABLE, 0);
1227 	WR4(sc, DC_CMD_INT_MASK, 0);
1228 
1229 	rv = bus_setup_intr(dev, sc->irq_res, INTR_TYPE_MISC | INTR_MPSAFE,
1230 	    NULL, dc_intr, sc, &sc->irq_ih);
1231 	if (rv != 0) {
1232 		device_printf(dev, "Cannot register interrupt handler\n");
1233 		return (rv);
1234 	}
1235 
1236 	/* allocate memory for cursor cache */
1237 	sc->tegra_crtc.cursor_vbase = kmem_alloc_contig(256 * 256 * 4,
1238 	    M_WAITOK | M_ZERO, 0, -1UL, PAGE_SIZE, 0,
1239 	    VM_MEMATTR_WRITE_COMBINING);
1240 	sc->tegra_crtc.cursor_pbase = vtophys(sc->tegra_crtc.cursor_vbase);
1241 	return (0);
1242 }
1243 
1244 static int
1245 dc_exit_client(device_t dev, device_t host1x, struct tegra_drm *drm)
1246 {
1247 	struct dc_softc *sc;
1248 
1249 	sc = device_get_softc(dev);
1250 
1251 	if (sc->irq_ih != NULL)
1252 		bus_teardown_intr(dev, sc->irq_res, sc->irq_ih);
1253 	sc->irq_ih = NULL;
1254 
1255 	return (0);
1256 }
1257 
1258 static int
1259 get_fdt_resources(struct dc_softc *sc, phandle_t node)
1260 {
1261 	int rv;
1262 
1263 	rv = hwreset_get_by_ofw_name(sc->dev, 0, "dc", &sc->hwreset_dc);
1264 	if (rv != 0) {
1265 		device_printf(sc->dev, "Cannot get 'dc' reset\n");
1266 		return (rv);
1267 	}
1268 	rv = clk_get_by_ofw_name(sc->dev, 0, "parent", &sc->clk_parent);
1269 	if (rv != 0) {
1270 		device_printf(sc->dev, "Cannot get 'parent' clock\n");
1271 		return (rv);
1272 	}
1273 	rv = clk_get_by_ofw_name(sc->dev, 0, "dc", &sc->clk_dc);
1274 	if (rv != 0) {
1275 		device_printf(sc->dev, "Cannot get 'dc' clock\n");
1276 		return (rv);
1277 	}
1278 
1279 	rv = OF_getencprop(node, "nvidia,head", &sc->tegra_crtc.nvidia_head,
1280 	    sizeof(sc->tegra_crtc.nvidia_head));
1281 	if (rv <= 0) {
1282 		device_printf(sc->dev,
1283 		    "Cannot get 'nvidia,head' property\n");
1284 		return (rv);
1285 	}
1286 	return (0);
1287 }
1288 
1289 static int
1290 enable_fdt_resources(struct dc_softc *sc)
1291 {
1292 	int id, rv;
1293 
1294 	rv = clk_set_parent_by_clk(sc->clk_dc, sc->clk_parent);
1295 	if (rv != 0) {
1296 		device_printf(sc->dev, "Cannot set parent for 'dc' clock\n");
1297 		return (rv);
1298 	}
1299 
1300 	id = (sc->tegra_crtc.nvidia_head == 0) ?
1301 	    TEGRA_POWERGATE_DIS: TEGRA_POWERGATE_DISB;
1302 	rv = tegra_powergate_sequence_power_up(id, sc->clk_dc, sc->hwreset_dc);
1303 	if (rv != 0) {
1304 		device_printf(sc->dev, "Cannot enable 'DIS' powergate\n");
1305 		return (rv);
1306 	}
1307 
1308 	return (0);
1309 }
1310 
1311 static int
1312 dc_probe(device_t dev)
1313 {
1314 
1315 	if (!ofw_bus_status_okay(dev))
1316 		return (ENXIO);
1317 
1318 	if (ofw_bus_search_compatible(dev, compat_data)->ocd_data == 0)
1319 		return (ENXIO);
1320 
1321 	device_set_desc(dev, "Tegra Display Controller");
1322 	return (BUS_PROBE_DEFAULT);
1323 }
1324 
1325 static int
1326 dc_attach(device_t dev)
1327 {
1328 	struct dc_softc *sc;
1329 	phandle_t node;
1330 	int rid, rv;
1331 
1332 	sc = device_get_softc(dev);
1333 	sc->dev = dev;
1334 	sc->tegra_crtc.dev = dev;
1335 
1336 	node = ofw_bus_get_node(sc->dev);
1337 	LOCK_INIT(sc);
1338 
1339 	rid = 0;
1340 	sc->mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
1341 	    RF_ACTIVE);
1342 	if (sc->mem_res == NULL) {
1343 		device_printf(dev, "Cannot allocate memory resources\n");
1344 		goto fail;
1345 	}
1346 
1347 	rid = 0;
1348 	sc->irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, RF_ACTIVE);
1349 	if (sc->irq_res == NULL) {
1350 		device_printf(dev, "Cannot allocate IRQ resources\n");
1351 		goto fail;
1352 	}
1353 
1354 	rv = get_fdt_resources(sc, node);
1355 	if (rv != 0) {
1356 		device_printf(dev, "Cannot parse FDT resources\n");
1357 		goto fail;
1358 	}
1359 	rv = enable_fdt_resources(sc);
1360 	if (rv != 0) {
1361 		device_printf(dev, "Cannot enable FDT resources\n");
1362 		goto fail;
1363 	}
1364 
1365 	/*
1366 	 * Tegra124
1367 	 *  -  64 for RGB modes
1368 	 *  - 128 for YUV planar modes
1369 	 *  - 256 for block linear modes
1370 	 */
1371 	sc->pitch_align = 256;
1372 
1373 	rv = TEGRA_DRM_REGISTER_CLIENT(device_get_parent(sc->dev), sc->dev);
1374 	if (rv != 0) {
1375 		device_printf(dev, "Cannot register DRM device\n");
1376 		goto fail;
1377 	}
1378 
1379 	return (bus_generic_attach(dev));
1380 
1381 fail:
1382 	TEGRA_DRM_DEREGISTER_CLIENT(device_get_parent(sc->dev), sc->dev);
1383 	if (sc->irq_ih != NULL)
1384 		bus_teardown_intr(dev, sc->irq_res, sc->irq_ih);
1385 	if (sc->clk_parent != NULL)
1386 		clk_release(sc->clk_parent);
1387 	if (sc->clk_dc != NULL)
1388 		clk_release(sc->clk_dc);
1389 	if (sc->hwreset_dc != NULL)
1390 		hwreset_release(sc->hwreset_dc);
1391 	if (sc->irq_res != NULL)
1392 		bus_release_resource(dev, SYS_RES_IRQ, 0, sc->irq_res);
1393 	if (sc->mem_res != NULL)
1394 		bus_release_resource(dev, SYS_RES_MEMORY, 0, sc->mem_res);
1395 	LOCK_DESTROY(sc);
1396 
1397 	return (ENXIO);
1398 }
1399 
1400 static int
1401 dc_detach(device_t dev)
1402 {
1403 	struct dc_softc *sc;
1404 
1405 	sc = device_get_softc(dev);
1406 
1407 	TEGRA_DRM_DEREGISTER_CLIENT(device_get_parent(sc->dev), sc->dev);
1408 
1409 	if (sc->irq_ih != NULL)
1410 		bus_teardown_intr(dev, sc->irq_res, sc->irq_ih);
1411 	if (sc->clk_parent != NULL)
1412 		clk_release(sc->clk_parent);
1413 	if (sc->clk_dc != NULL)
1414 		clk_release(sc->clk_dc);
1415 	if (sc->hwreset_dc != NULL)
1416 		hwreset_release(sc->hwreset_dc);
1417 	if (sc->irq_res != NULL)
1418 		bus_release_resource(dev, SYS_RES_IRQ, 0, sc->irq_res);
1419 	if (sc->mem_res != NULL)
1420 		bus_release_resource(dev, SYS_RES_MEMORY, 0, sc->mem_res);
1421 	LOCK_DESTROY(sc);
1422 
1423 	return (bus_generic_detach(dev));
1424 }
1425 
1426 static device_method_t tegra_dc_methods[] = {
1427 	/* Device interface */
1428 	DEVMETHOD(device_probe,			dc_probe),
1429 	DEVMETHOD(device_attach,		dc_attach),
1430 	DEVMETHOD(device_detach,		dc_detach),
1431 
1432 	/* tegra drm interface */
1433 	DEVMETHOD(tegra_drm_init_client,	dc_init_client),
1434 	DEVMETHOD(tegra_drm_exit_client,	dc_exit_client),
1435 
1436 	/* tegra dc interface */
1437 	DEVMETHOD(tegra_dc_display_enable,	dc_display_enable),
1438 	DEVMETHOD(tegra_dc_hdmi_enable,		dc_hdmi_enable),
1439 	DEVMETHOD(tegra_dc_setup_timing,	dc_setup_timing),
1440 
1441 	DEVMETHOD_END
1442 };
1443 
1444 static devclass_t tegra_dc_devclass;
1445 DEFINE_CLASS_0(tegra_dc, tegra_dc_driver, tegra_dc_methods,
1446     sizeof(struct dc_softc));
1447 DRIVER_MODULE(tegra_dc, host1x, tegra_dc_driver, tegra_dc_devclass, NULL, NULL);
1448