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