2 * Copyright (c) 2015 Michal Meloun
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
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.
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
27 #include <sys/cdefs.h>
28 __FBSDID("$FreeBSD$");
30 #include <sys/param.h>
31 #include <sys/systm.h>
34 #include <sys/kernel.h>
35 #include <sys/module.h>
36 #include <sys/malloc.h>
38 #include <sys/sysctl.h>
40 #include <machine/bus.h>
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>
51 #include <arm/nvidia/drm2/tegra_dc_reg.h>
52 #include <arm/nvidia/drm2/tegra_drm.h>
53 #include <arm/nvidia/tegra_pmc.h>
55 #include "tegra_drm_if.h"
56 #include "tegra_dc_if.h"
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))
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)
72 #define SYNCPT_VBLANK0 26
73 #define SYNCPT_VBLANK1 27
75 #define DC_MAX_PLANES 2 /* Maximum planes */
77 /* DRM Formats supported by DC */
79 static uint32_t dc_plane_formats[] = {
90 /* Complete description of one window (plane) */
92 /* Source (in framebuffer) rectangle, in pixels */
98 /* Destination (on display) rectangle, in pixels */
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 */
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 */
118 /* Color planes base addresses and strides */
120 uint32_t stride[3]; /* stride[2] isn't used by HW */
125 struct resource *mem_res;
126 struct resource *irq_res;
132 hwreset_t hwreset_dc;
136 struct tegra_crtc tegra_crtc;
137 struct drm_pending_vblank_event *event;
138 struct drm_gem_object *cursor_gem;
142 static struct ofw_compat_data compat_data[] = {
143 {"nvidia,tegra124-dc", 1},
147 /* Convert standard drm pixel format to tegra windows parameters. */
149 dc_parse_drm_format(struct tegra_fb *fb, struct dc_window *win)
154 bool is_yuv, is_yuv_planar;
157 switch (fb->drm_fb.pixel_format) {
158 case DRM_FORMAT_XBGR8888:
159 sw = BYTE_SWAP(NOSWAP);
160 cm = WIN_COLOR_DEPTH_R8G8B8A8;
162 is_yuv_planar = false;
165 case DRM_FORMAT_XRGB8888:
166 sw = BYTE_SWAP(NOSWAP);
167 cm = WIN_COLOR_DEPTH_B8G8R8A8;
169 is_yuv_planar = false;
172 case DRM_FORMAT_RGB565:
173 sw = BYTE_SWAP(NOSWAP);
174 cm = WIN_COLOR_DEPTH_B5G6R5;
176 is_yuv_planar = false;
179 case DRM_FORMAT_UYVY:
180 sw = BYTE_SWAP(NOSWAP);
181 cm = WIN_COLOR_DEPTH_YCbCr422;
183 is_yuv_planar = false;
186 case DRM_FORMAT_YUYV:
187 sw = BYTE_SWAP(SWAP2);
188 cm = WIN_COLOR_DEPTH_YCbCr422;
190 is_yuv_planar = false;
193 case DRM_FORMAT_YUV420:
194 sw = BYTE_SWAP(NOSWAP);
195 cm = WIN_COLOR_DEPTH_YCbCr420P;
197 is_yuv_planar = true;
200 case DRM_FORMAT_YUV422:
201 sw = BYTE_SWAP(NOSWAP);
202 cm = WIN_COLOR_DEPTH_YCbCr422P;
204 is_yuv_planar = true;
208 /* Unsupported format */
212 /* Basic check of arguments. */
213 switch (fb->rotation) {
218 case 90: /* Rotation is supported only */
219 case 270: /* for block linear surfaces */
220 if (!fb->block_linear)
227 /* XXX Add more checks (sizes, scaling...) */
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;
242 case 90: /* (1,0,1) */
243 win->transpose_xy = true;
248 case 180: /* (0,1,1) */
249 win->transpose_xy = false;
254 case 270: /* (1,1,0) */
255 win->transpose_xy = true;
260 win->flip_x ^= fb->flip_x;
261 win->flip_y ^= fb->flip_y;
263 win->color_mode = cm;
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;
269 nplanes = drm_format_num_planes(fb->drm_fb.pixel_format);
270 for (i = 0; i < nplanes; i++) {
272 win->base[i] = bo->pbase + fb->drm_fb.offsets[i];
273 win->stride[i] = fb->drm_fb.pitches[i];
281 * It's unclear if we want/must program the fractional portion
282 * (aka bias) of init_dda registers, mainly when mirrored axis
284 * For now, we use 1.0 as recommended by TRM.
286 static inline uint32_t
287 dc_scaling_init(uint32_t start)
293 static inline uint32_t
294 dc_scaling_incr(uint32_t src, uint32_t dst, uint32_t maxscale)
298 val = (src - 1) << 12 ; /* 4.12 fixed float */
300 if (val > (maxscale << 12))
301 val = maxscale << 12;
305 /* -------------------------------------------------------------------
313 * Minimal frequency is pixel clock, but output is free to select
317 dc_setup_clk(struct dc_softc *sc, struct drm_crtc *crtc,
318 struct drm_display_mode *mode, uint32_t *div)
321 struct tegra_drm_encoder *output;
322 struct drm_encoder *encoder;
325 pclk = mode->clock * 1000;
327 /* Find attached encoder */
329 list_for_each_entry(encoder, &crtc->dev->mode_config.encoder_list,
331 if (encoder->crtc == crtc) {
332 output = container_of(encoder, struct tegra_drm_encoder,
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);
344 device_printf(sc->dev, "Cannot setup pixel clock: %llu\n",
349 rv = clk_get_freq(sc->clk_dc, &freq);
350 *div = (freq * 2 / pclk) - 2;
352 DRM_DEBUG_KMS("frequency: %llu, DC divider: %u\n", freq, *div);
358 dc_setup_window(struct dc_softc *sc, unsigned int index, struct dc_window *win)
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;
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);
375 bpp = win->is_yuv_planar ? 1 : 2;
377 bpp = (win->bits_per_pixel + 7) / 8;
379 if (!win->transpose_xy) {
380 h_size = win->src_w * bpp;
383 h_size = win->src_h * bpp;
387 h_offset = win->src_x * bpp;;
388 v_offset = win->src_y;
390 h_offset += win->src_w * bpp - 1;
393 v_offset += win->src_h - 1;
395 /* Adjust offsets for planar yuv modes */
396 if (win->is_yuv_planar) {
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);
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);
417 #ifdef DMR_DEBUG_WINDOW
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);
427 /* Select target window */
428 val = WINDOW_A_SELECT << index;
429 WR4(sc, DC_CMD_DISPLAY_WINDOW_HEADER, val);
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));
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);
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]);
450 WR4(sc, DC_WIN_LINE_STRIDE, win->stride[0]);
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);
458 WR4(sc, DC_WIN_COLOR_DEPTH, win->color_mode);
459 WR4(sc, DC_WIN_BYTE_SWAP, win->swap);
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);
467 /* Color space coefs for YUV modes */
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);
482 else if (win->bits_per_pixel < 24)
488 if (win->transpose_xy)
490 WR4(sc, DC_WINC_WIN_OPTIONS, val);
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);
501 /* -------------------------------------------------------------------
507 dc_plane_update(struct drm_plane *drm_plane, struct drm_crtc *drm_crtc,
508 struct drm_framebuffer *drm_fb,
509 int crtc_x, int crtc_y, unsigned int crtc_w, unsigned int crtc_h,
510 uint32_t src_x, uint32_t src_y, uint32_t src_w, uint32_t src_h)
512 struct tegra_plane *plane;
513 struct tegra_crtc *crtc;
516 struct dc_window win;
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);
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;
534 rv = dc_parse_drm_format(fb, &win);
536 DRM_WARNING("unsupported pixel format %d\n",
537 fb->drm_fb.pixel_format);
541 dc_setup_window(sc, plane->index, &win);
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);
550 dc_plane_disable(struct drm_plane *drm_plane)
552 struct tegra_plane *plane;
553 struct tegra_crtc *crtc;
557 if (drm_plane->crtc == NULL)
559 plane = container_of(drm_plane, struct tegra_plane, drm_plane);
560 crtc = container_of(drm_plane->crtc, struct tegra_crtc, drm_crtc);
562 sc = device_get_softc(crtc->dev);
567 WR4(sc, DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_A_SELECT << idx);
569 val = RD4(sc, DC_WINC_WIN_OPTIONS);
571 WR4(sc, DC_WINC_WIN_OPTIONS, val);
575 WR4(sc, DC_CMD_STATE_CONTROL, WIN_A_UPDATE << idx);
576 WR4(sc, DC_CMD_STATE_CONTROL, WIN_A_ACT_REQ << idx);
582 dc_plane_destroy(struct drm_plane *plane)
585 dc_plane_disable(plane);
586 drm_plane_cleanup(plane);
587 free(plane, DRM_MEM_KMS);
590 static const struct drm_plane_funcs dc_plane_funcs = {
591 .update_plane = dc_plane_update,
592 .disable_plane = dc_plane_disable,
593 .destroy = dc_plane_destroy,
596 /* -------------------------------------------------------------------
598 * CRTC helper functions.
602 dc_crtc_dpms(struct drm_crtc *crtc, int mode)
608 dc_crtc_mode_fixup(struct drm_crtc *crtc, const struct drm_display_mode *mode,
609 struct drm_display_mode *adjusted)
616 dc_set_base(struct dc_softc *sc, int x, int y, struct tegra_fb *fb)
618 struct dc_window win;
621 memset(&win, 0, sizeof(win));
624 win.src_w = fb->drm_fb.width;
625 win.src_h = fb->drm_fb.height;
628 win.dst_w = fb->drm_fb.width;
629 win.dst_h = fb->drm_fb.height;
631 rv = dc_parse_drm_format(fb, &win);
633 DRM_WARNING("unsupported pixel format %d\n",
634 fb->drm_fb.pixel_format);
637 dc_setup_window(sc, 0, &win);
643 dc_crtc_mode_set(struct drm_crtc *drm_crtc, struct drm_display_mode *mode,
644 struct drm_display_mode *adjusted, int x, int y,
645 struct drm_framebuffer *old_fb)
648 struct tegra_crtc *crtc;
650 struct dc_window win;
651 uint32_t div, h_ref_to_sync, v_ref_to_sync;
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);
662 rv = dc_setup_clk(sc, drm_crtc, mode, &div);
664 device_printf(sc->dev, "Cannot set pixel clock\n");
669 WR4(sc, DC_DISP_DISP_TIMING_OPTIONS, 0);
671 WR4(sc, DC_DISP_REF_TO_SYNC,
672 (v_ref_to_sync << 16) |
675 WR4(sc, DC_DISP_SYNC_WIDTH,
676 ((mode->vsync_end - mode->vsync_start) << 16) |
677 ((mode->hsync_end - mode->hsync_start) << 0));
679 WR4(sc, DC_DISP_BACK_PORCH,
680 ((mode->vtotal - mode->vsync_end) << 16) |
681 ((mode->htotal - mode->hsync_end) << 0));
683 WR4(sc, DC_DISP_FRONT_PORCH,
684 ((mode->vsync_start - mode->vdisplay) << 16) |
685 ((mode->hsync_start - mode->hdisplay) << 0));
687 WR4(sc, DC_DISP_DISP_ACTIVE,
688 (mode->vdisplay << 16) | mode->hdisplay);
690 WR4(sc, DC_DISP_DISP_INTERFACE_CONTROL, DISP_DATA_FORMAT(DF1P1C));
692 WR4(sc,DC_DISP_DISP_CLOCK_CONTROL,
693 SHIFT_CLK_DIVIDER(div) | PIXEL_CLK_DIVIDER(PCD1));
695 memset(&win, 0, sizeof(win));
698 win.src_w = mode->hdisplay;
699 win.src_h = mode->vdisplay;
702 win.dst_w = mode->hdisplay;
703 win.dst_h = mode->vdisplay;
705 rv = dc_parse_drm_format(fb, &win);
707 DRM_WARNING("unsupported pixel format %d\n",
708 drm_crtc->fb->pixel_format);
712 dc_setup_window(sc, 0, &win);
719 dc_crtc_mode_set_base(struct drm_crtc *drm_crtc, int x, int y,
720 struct drm_framebuffer *old_fb)
723 struct tegra_crtc *crtc;
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);
731 rv = dc_set_base(sc, x, y, fb);
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);
741 dc_crtc_prepare(struct drm_crtc *drm_crtc)
745 struct tegra_crtc *crtc;
748 crtc = container_of(drm_crtc, struct tegra_crtc, drm_crtc);
749 sc = device_get_softc(crtc->dev);
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));
756 WR4(sc, DC_CMD_DISPLAY_POWER_CONTROL,
757 PW0_ENABLE | PW1_ENABLE | PW2_ENABLE | PW3_ENABLE |
758 PW4_ENABLE | PM0_ENABLE | PM1_ENABLE);
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);
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);
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);
774 dc_crtc_commit(struct drm_crtc *drm_crtc)
777 struct tegra_crtc *crtc;
780 crtc = container_of(drm_crtc, struct tegra_crtc, drm_crtc);
781 sc = device_get_softc(crtc->dev);
783 WR4(sc, DC_CMD_STATE_CONTROL, GENERAL_UPDATE | WIN_A_UPDATE);
785 val = RD4(sc, DC_CMD_INT_MASK);
786 val |= FRAME_END_INT;
787 WR4(sc, DC_CMD_INT_MASK, val);
789 val = RD4(sc, DC_CMD_INT_ENABLE);
790 val |= FRAME_END_INT;
791 WR4(sc, DC_CMD_INT_ENABLE, val);
793 WR4(sc, DC_CMD_STATE_CONTROL, GENERAL_ACT_REQ | WIN_A_ACT_REQ);
797 dc_crtc_load_lut(struct drm_crtc *crtc)
803 static const struct drm_crtc_helper_funcs dc_crtc_helper_funcs = {
804 .dpms = dc_crtc_dpms,
805 .mode_fixup = dc_crtc_mode_fixup,
806 .mode_set = dc_crtc_mode_set,
807 .mode_set_base = dc_crtc_mode_set_base,
808 .prepare = dc_crtc_prepare,
809 .commit = dc_crtc_commit,
810 .load_lut = dc_crtc_load_lut,
814 drm_crtc_index(struct drm_crtc *crtc)
817 struct drm_crtc *tmp;
820 list_for_each_entry(tmp, &crtc->dev->mode_config.crtc_list, head) {
825 panic("Cannot find CRTC");
828 /* -------------------------------------------------------------------
830 * Exported functions (mainly vsync related).
832 * XXX revisit this -> convert to bus methods?
835 tegra_dc_get_pipe(struct drm_crtc *drm_crtc)
837 struct tegra_crtc *crtc;
839 crtc = container_of(drm_crtc, struct tegra_crtc, drm_crtc);
840 return (crtc->nvidia_head);
844 tegra_dc_enable_vblank(struct drm_crtc *drm_crtc)
847 struct tegra_crtc *crtc;
850 crtc = container_of(drm_crtc, struct tegra_crtc, drm_crtc);
851 sc = device_get_softc(crtc->dev);
854 val = RD4(sc, DC_CMD_INT_MASK);
856 WR4(sc, DC_CMD_INT_MASK, val);
861 tegra_dc_disable_vblank(struct drm_crtc *drm_crtc)
864 struct tegra_crtc *crtc;
867 crtc = container_of(drm_crtc, struct tegra_crtc, drm_crtc);
868 sc = device_get_softc(crtc->dev);
871 val = RD4(sc, DC_CMD_INT_MASK);
873 WR4(sc, DC_CMD_INT_MASK, val);
878 dc_finish_page_flip(struct dc_softc *sc)
880 struct drm_crtc *drm_crtc;
881 struct drm_device *drm;
887 drm_crtc = &sc->tegra_crtc.drm_crtc;
889 fb = container_of(drm_crtc->fb, struct tegra_fb, drm_fb);
891 mtx_lock(&drm->event_lock);
893 if (sc->event == NULL) {
894 mtx_unlock(&drm->event_lock);
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);
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);
915 mtx_unlock(&drm->event_lock);
920 tegra_dc_cancel_page_flip(struct drm_crtc *drm_crtc, struct drm_file *file)
923 struct tegra_crtc *crtc;
924 struct drm_device *drm;
926 crtc = container_of(drm_crtc, struct tegra_crtc, drm_crtc);
927 sc = device_get_softc(crtc->dev);
929 mtx_lock(&drm->event_lock);
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));
936 mtx_unlock(&drm->event_lock);
939 /* -------------------------------------------------------------------
945 dc_page_flip(struct drm_crtc *drm_crtc, struct drm_framebuffer *drm_fb,
946 struct drm_pending_vblank_event *event)
949 struct tegra_crtc *crtc;
951 struct drm_device *drm;
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);
958 if (sc->event != NULL)
962 event->pipe = sc->tegra_crtc.nvidia_head;
964 drm_vblank_get(drm, event->pipe);
967 dc_set_base(sc, drm_crtc->x, drm_crtc->y, fb);
968 drm_crtc->fb = drm_fb;
971 WR4(sc, DC_CMD_STATE_CONTROL, GENERAL_UPDATE | WIN_A_UPDATE);
977 dc_cursor_set(struct drm_crtc *drm_crtc, struct drm_file *file,
978 uint32_t handle, uint32_t width, uint32_t height)
982 struct tegra_crtc *crtc;
983 struct drm_gem_object *gem;
986 uint32_t val, *src, *dst;
988 crtc = container_of(drm_crtc, struct tegra_crtc, drm_crtc);
989 sc = device_get_softc(crtc->dev);
996 val = CURSOR_SIZE(C32x32);
999 val = CURSOR_SIZE(C64x64);
1002 val = CURSOR_SIZE(C128x128);
1005 val = CURSOR_SIZE(C256x256);
1014 gem = drm_gem_object_lookup(drm_crtc->dev, file, handle);
1017 bo = container_of(gem, struct tegra_bo, gem_obj);
1020 if (sc->cursor_gem != NULL) {
1021 drm_gem_object_unreference(sc->cursor_gem);
1023 sc->cursor_gem = gem;
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.
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);
1037 val |= CURSOR_CLIP(CC_DISPLAY);
1038 val |= CURSOR_START_ADDR(crtc->cursor_pbase);
1039 WR4(sc, DC_DISP_CURSOR_START_ADDR, val);
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);
1050 val = RD4(sc, DC_DISP_DISP_WIN_OPTIONS);
1051 val |= CURSOR_ENABLE;
1052 WR4(sc, DC_DISP_DISP_WIN_OPTIONS, val);
1054 val = RD4(sc, DC_DISP_DISP_WIN_OPTIONS);
1055 val &= ~CURSOR_ENABLE;
1056 WR4(sc, DC_DISP_DISP_WIN_OPTIONS, val);
1059 /* XXX This fixes cursor underflow issues, but why ? */
1060 WR4(sc, DC_DISP_CURSOR_UNDERFLOW_CTRL, CURSOR_UFLOW_CYA);
1062 WR4(sc, DC_CMD_STATE_CONTROL, GENERAL_UPDATE | CURSOR_UPDATE );
1063 WR4(sc, DC_CMD_STATE_CONTROL, GENERAL_ACT_REQ | CURSOR_ACT_REQ);
1068 dc_cursor_move(struct drm_crtc *drm_crtc, int x, int y)
1070 struct dc_softc *sc;
1071 struct tegra_crtc *crtc;
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));
1077 WR4(sc, DC_CMD_STATE_CONTROL, CURSOR_UPDATE);
1078 WR4(sc, DC_CMD_STATE_CONTROL, CURSOR_ACT_REQ);
1084 dc_destroy(struct drm_crtc *crtc)
1087 drm_crtc_cleanup(crtc);
1088 memset(crtc, 0, sizeof(*crtc));
1091 static const struct drm_crtc_funcs dc_crtc_funcs = {
1092 .page_flip = dc_page_flip,
1093 .cursor_set = dc_cursor_set,
1094 .cursor_move = dc_cursor_move,
1095 .set_config = drm_crtc_helper_set_config,
1096 .destroy = dc_destroy,
1099 /* -------------------------------------------------------------------
1101 * Bus and infrastructure.
1105 dc_init_planes(struct dc_softc *sc, struct tegra_drm *drm)
1108 struct tegra_plane *plane;
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);
1118 free(plane, DRM_MEM_KMS);
1126 dc_display_enable(device_t dev, bool enable)
1128 struct dc_softc *sc;
1131 sc = device_get_softc(dev);
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));
1138 WR4(sc, DC_CMD_STATE_CONTROL, GENERAL_UPDATE);
1139 WR4(sc, DC_CMD_STATE_CONTROL, GENERAL_ACT_REQ);
1143 dc_hdmi_enable(device_t dev, bool enable)
1145 struct dc_softc *sc;
1148 sc = device_get_softc(dev);
1150 val = RD4(sc, DC_DISP_DISP_WIN_OPTIONS);
1154 val &= ~HDMI_ENABLE;
1155 WR4(sc, DC_DISP_DISP_WIN_OPTIONS, val);
1160 dc_setup_timing(device_t dev, int h_pulse_start)
1162 struct dc_softc *sc;
1164 sc = device_get_softc(dev);
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));
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));
1175 WR4(sc, DC_DISP_H_PULSE2_POSITION_A,
1176 PULSE_START(h_pulse_start) | PULSE_END(h_pulse_start + 8));
1182 struct dc_softc *sc;
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);
1198 dc_init_client(device_t dev, device_t host1x, struct tegra_drm *drm)
1200 struct dc_softc *sc;
1203 sc = device_get_softc(dev);
1205 if (drm->pitch_align < sc->pitch_align)
1206 drm->pitch_align = sc->pitch_align;
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);
1212 rv = dc_init_planes(sc, drm);
1214 device_printf(dev, "Cannot init planes\n");
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);
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);
1226 WR4(sc, DC_CMD_INT_ENABLE, 0);
1227 WR4(sc, DC_CMD_INT_MASK, 0);
1229 rv = bus_setup_intr(dev, sc->irq_res, INTR_TYPE_MISC | INTR_MPSAFE,
1230 NULL, dc_intr, sc, &sc->irq_ih);
1232 device_printf(dev, "Cannot register interrupt handler\n");
1236 /* allocate memory for cursor cache */
1237 sc->tegra_crtc.cursor_vbase = kmem_alloc_contig(256 * 256 * 4,
1238 M_WAITOK | M_ZERO, 0, -1UL, PAGE_SIZE, 0,
1239 VM_MEMATTR_WRITE_COMBINING);
1240 sc->tegra_crtc.cursor_pbase = vtophys(sc->tegra_crtc.cursor_vbase);
1245 dc_exit_client(device_t dev, device_t host1x, struct tegra_drm *drm)
1247 struct dc_softc *sc;
1249 sc = device_get_softc(dev);
1251 if (sc->irq_ih != NULL)
1252 bus_teardown_intr(dev, sc->irq_res, sc->irq_ih);
1259 get_fdt_resources(struct dc_softc *sc, phandle_t node)
1263 rv = hwreset_get_by_ofw_name(sc->dev, 0, "dc", &sc->hwreset_dc);
1265 device_printf(sc->dev, "Cannot get 'dc' reset\n");
1268 rv = clk_get_by_ofw_name(sc->dev, 0, "parent", &sc->clk_parent);
1270 device_printf(sc->dev, "Cannot get 'parent' clock\n");
1273 rv = clk_get_by_ofw_name(sc->dev, 0, "dc", &sc->clk_dc);
1275 device_printf(sc->dev, "Cannot get 'dc' clock\n");
1279 rv = OF_getencprop(node, "nvidia,head", &sc->tegra_crtc.nvidia_head,
1280 sizeof(sc->tegra_crtc.nvidia_head));
1282 device_printf(sc->dev,
1283 "Cannot get 'nvidia,head' property\n");
1290 enable_fdt_resources(struct dc_softc *sc)
1294 rv = clk_set_parent_by_clk(sc->clk_dc, sc->clk_parent);
1296 device_printf(sc->dev, "Cannot set parent for 'dc' clock\n");
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);
1304 device_printf(sc->dev, "Cannot enable 'DIS' powergate\n");
1312 dc_probe(device_t dev)
1315 if (!ofw_bus_status_okay(dev))
1318 if (ofw_bus_search_compatible(dev, compat_data)->ocd_data == 0)
1321 device_set_desc(dev, "Tegra Display Controller");
1322 return (BUS_PROBE_DEFAULT);
1326 dc_attach(device_t dev)
1328 struct dc_softc *sc;
1332 sc = device_get_softc(dev);
1334 sc->tegra_crtc.dev = dev;
1336 node = ofw_bus_get_node(sc->dev);
1340 sc->mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
1342 if (sc->mem_res == NULL) {
1343 device_printf(dev, "Cannot allocate memory resources\n");
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");
1354 rv = get_fdt_resources(sc, node);
1356 device_printf(dev, "Cannot parse FDT resources\n");
1359 rv = enable_fdt_resources(sc);
1361 device_printf(dev, "Cannot enable FDT resources\n");
1367 * - 64 for RGB modes
1368 * - 128 for YUV planar modes
1369 * - 256 for block linear modes
1371 sc->pitch_align = 256;
1373 rv = TEGRA_DRM_REGISTER_CLIENT(device_get_parent(sc->dev), sc->dev);
1375 device_printf(dev, "Cannot register DRM device\n");
1379 return (bus_generic_attach(dev));
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);
1401 dc_detach(device_t dev)
1403 struct dc_softc *sc;
1405 sc = device_get_softc(dev);
1407 TEGRA_DRM_DEREGISTER_CLIENT(device_get_parent(sc->dev), sc->dev);
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);
1423 return (bus_generic_detach(dev));
1426 static device_method_t tegra_dc_methods[] = {
1427 /* Device interface */
1428 DEVMETHOD(device_probe, dc_probe),
1429 DEVMETHOD(device_attach, dc_attach),
1430 DEVMETHOD(device_detach, dc_detach),
1432 /* tegra drm interface */
1433 DEVMETHOD(tegra_drm_init_client, dc_init_client),
1434 DEVMETHOD(tegra_drm_exit_client, dc_exit_client),
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),
1444 static devclass_t tegra_dc_devclass;
1445 DEFINE_CLASS_0(tegra_dc, tegra_dc_driver, tegra_dc_methods,
1446 sizeof(struct dc_softc));
1447 DRIVER_MODULE(tegra_dc, host1x, tegra_dc_driver, tegra_dc_devclass, NULL, NULL);