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