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