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