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)
71 #define SYNCPT_VBLANK0 26
72 #define SYNCPT_VBLANK1 27
74 #define DC_MAX_PLANES 2 /* Maximum planes */
76 /* DRM Formats supported by DC */
78 static uint32_t dc_plane_formats[] = {
88 /* Complete description of one window (plane) */
90 /* Source (in framebuffer) rectangle, in pixels */
96 /* Destination (on display) rectangle, in pixels */
102 /* Parsed pixel format */
103 u_int bits_per_pixel;
104 bool is_yuv; /* any YUV mode */
105 bool is_yuv_planar; /* planar YUV mode */
106 uint32_t color_mode; /* DC_WIN_COLOR_DEPTH */
107 uint32_t swap; /* DC_WIN_BYTE_SWAP */
108 uint32_t surface_kind; /* DC_WINBUF_SURFACE_KIND */
109 uint32_t block_height; /* DC_WINBUF_SURFACE_KIND */
111 /* Parsed flipping, rotation is not supported for pitched modes */
112 bool flip_x; /* inverted X-axis */
113 bool flip_y; /* inverted Y-axis */
114 bool transpose_xy; /* swap X and Y-axis */
116 /* Color planes base addresses and strides */
118 uint32_t stride[3]; /* stride[2] isn't used by HW */
123 struct resource *mem_res;
124 struct resource *irq_res;
130 hwreset_t hwreset_dc;
134 struct tegra_crtc tegra_crtc;
135 struct drm_pending_vblank_event *event;
136 struct drm_gem_object *cursor_gem;
139 static struct ofw_compat_data compat_data[] = {
140 {"nvidia,tegra124-dc", 1},
144 /* Convert standard drm pixel format to tegra windows parameters. */
146 dc_parse_drm_format(struct tegra_fb *fb, struct dc_window *win)
151 bool is_yuv, is_yuv_planar;
154 switch (fb->drm_fb.pixel_format) {
155 case DRM_FORMAT_XBGR8888:
156 sw = BYTE_SWAP(NOSWAP);
157 cm = WIN_COLOR_DEPTH_R8G8B8A8;
159 is_yuv_planar = false;
162 case DRM_FORMAT_XRGB8888:
163 sw = BYTE_SWAP(NOSWAP);
164 cm = WIN_COLOR_DEPTH_B8G8R8A8;
166 is_yuv_planar = false;
169 case DRM_FORMAT_RGB565:
170 sw = BYTE_SWAP(NOSWAP);
171 cm = WIN_COLOR_DEPTH_B5G6R5;
173 is_yuv_planar = false;
176 case DRM_FORMAT_UYVY:
177 sw = BYTE_SWAP(NOSWAP);
178 cm = WIN_COLOR_DEPTH_YCbCr422;
180 is_yuv_planar = false;
183 case DRM_FORMAT_YUYV:
184 sw = BYTE_SWAP(SWAP2);
185 cm = WIN_COLOR_DEPTH_YCbCr422;
187 is_yuv_planar = false;
190 case DRM_FORMAT_YUV420:
191 sw = BYTE_SWAP(NOSWAP);
192 cm = WIN_COLOR_DEPTH_YCbCr420P;
194 is_yuv_planar = true;
197 case DRM_FORMAT_YUV422:
198 sw = BYTE_SWAP(NOSWAP);
199 cm = WIN_COLOR_DEPTH_YCbCr422P;
201 is_yuv_planar = true;
205 /* Unsupported format */
209 /* Basic check of arguments. */
210 switch (fb->rotation) {
215 case 90: /* Rotation is supported only */
216 case 270: /* for block linear surfaces */
217 if (!fb->block_linear)
224 /* XXX Add more checks (sizes, scaling...) */
230 fb->block_linear ? SURFACE_KIND_BL_16B2: SURFACE_KIND_PITCH;
231 win->block_height = fb->block_height;
232 switch (fb->rotation) {
233 case 0: /* (0,0,0) */
234 win->transpose_xy = false;
239 case 90: /* (1,0,1) */
240 win->transpose_xy = true;
245 case 180: /* (0,1,1) */
246 win->transpose_xy = false;
251 case 270: /* (1,1,0) */
252 win->transpose_xy = true;
257 win->flip_x ^= fb->flip_x;
258 win->flip_y ^= fb->flip_y;
260 win->color_mode = cm;
262 win->bits_per_pixel = fb->drm_fb.bits_per_pixel;
263 win->is_yuv = is_yuv;
264 win->is_yuv_planar = is_yuv_planar;
266 nplanes = drm_format_num_planes(fb->drm_fb.pixel_format);
267 for (i = 0; i < nplanes; i++) {
269 win->base[i] = bo->pbase + fb->drm_fb.offsets[i];
270 win->stride[i] = fb->drm_fb.pitches[i];
278 * It's unclear if we want/must program the fractional portion
279 * (aka bias) of init_dda registers, mainly when mirrored axis
281 * For now, we use 1.0 as recommended by TRM.
283 static inline uint32_t
284 dc_scaling_init(uint32_t start)
290 static inline uint32_t
291 dc_scaling_incr(uint32_t src, uint32_t dst, uint32_t maxscale)
295 val = (src - 1) << 12 ; /* 4.12 fixed float */
297 if (val > (maxscale << 12))
298 val = maxscale << 12;
302 /* -------------------------------------------------------------------
310 * Minimal frequency is pixel clock, but output is free to select
314 dc_setup_clk(struct dc_softc *sc, struct drm_crtc *crtc,
315 struct drm_display_mode *mode, uint32_t *div)
318 struct tegra_drm_encoder *output;
319 struct drm_encoder *encoder;
322 pclk = mode->clock * 1000;
324 /* Find attached encoder */
326 list_for_each_entry(encoder, &crtc->dev->mode_config.encoder_list,
328 if (encoder->crtc == crtc) {
329 output = container_of(encoder, struct tegra_drm_encoder,
337 if (output->setup_clock == NULL)
338 panic("Output have not setup_clock function.\n");
339 rv = output->setup_clock(output, sc->clk_dc, pclk);
341 device_printf(sc->dev, "Cannot setup pixel clock: %llu\n",
346 rv = clk_get_freq(sc->clk_dc, &freq);
347 *div = (freq * 2 / pclk) - 2;
349 DRM_DEBUG_KMS("frequency: %llu, DC divider: %u\n", freq, *div);
355 dc_setup_window(struct dc_softc *sc, unsigned int index, struct dc_window *win)
357 uint32_t h_offset, v_offset, h_size, v_size, bpp;
358 uint32_t h_init_dda, v_init_dda, h_incr_dda, v_incr_dda;
361 #ifdef DMR_DEBUG_WINDOW
362 printf("%s window: %d\n", __func__, index);
363 printf(" src: x: %d, y: %d, w: %d, h: %d\n",
364 win->src_x, win->src_y, win->src_w, win->src_h);
365 printf(" dst: x: %d, y: %d, w: %d, h: %d\n",
366 win->dst_x, win->dst_y, win->dst_w, win->dst_h);
367 printf(" bpp: %d, color_mode: %d, swap: %d\n",
368 win->bits_per_pixel, win->color_mode, win->swap);
372 bpp = win->is_yuv_planar ? 1 : 2;
374 bpp = (win->bits_per_pixel + 7) / 8;
376 if (!win->transpose_xy) {
377 h_size = win->src_w * bpp;
380 h_size = win->src_h * bpp;
384 h_offset = win->src_x * bpp;
385 v_offset = win->src_y;
387 h_offset += win->src_w * bpp - 1;
390 v_offset += win->src_h - 1;
392 /* Adjust offsets for planar yuv modes */
393 if (win->is_yuv_planar) {
403 if (!win->transpose_xy) {
404 h_init_dda = dc_scaling_init(win->src_x);
405 v_init_dda = dc_scaling_init(win->src_y);
406 h_incr_dda = dc_scaling_incr(win->src_w, win->dst_w, 4);
407 v_incr_dda = dc_scaling_incr(win->src_h, win->dst_h, 15);
409 h_init_dda = dc_scaling_init(win->src_y);
410 v_init_dda = dc_scaling_init(win->src_x);
411 h_incr_dda = dc_scaling_incr(win->src_h, win->dst_h, 4);
412 v_incr_dda = dc_scaling_incr(win->src_w, win->dst_w, 15);
414 #ifdef DMR_DEBUG_WINDOW
416 printf(" bpp: %d, size: h: %d v: %d, offset: h:%d v: %d\n",
417 bpp, h_size, v_size, h_offset, v_offset);
418 printf(" init_dda: h: %d v: %d, incr_dda: h: %d v: %d\n",
419 h_init_dda, v_init_dda, h_incr_dda, v_incr_dda);
424 /* Select target window */
425 val = WINDOW_A_SELECT << index;
426 WR4(sc, DC_CMD_DISPLAY_WINDOW_HEADER, val);
429 WR4(sc, DC_WIN_POSITION, WIN_POSITION(win->dst_x, win->dst_y));
430 WR4(sc, DC_WIN_SIZE, WIN_SIZE(win->dst_w, win->dst_h));
431 WR4(sc, DC_WIN_PRESCALED_SIZE, WIN_PRESCALED_SIZE(h_size, v_size));
434 WR4(sc, DC_WIN_DDA_INCREMENT,
435 WIN_DDA_INCREMENT(h_incr_dda, v_incr_dda));
436 WR4(sc, DC_WIN_H_INITIAL_DDA, h_init_dda);
437 WR4(sc, DC_WIN_V_INITIAL_DDA, v_init_dda);
439 /* Color planes base addresses and strides */
440 WR4(sc, DC_WINBUF_START_ADDR, win->base[0]);
441 if (win->is_yuv_planar) {
442 WR4(sc, DC_WINBUF_START_ADDR_U, win->base[1]);
443 WR4(sc, DC_WINBUF_START_ADDR_V, win->base[2]);
444 WR4(sc, DC_WIN_LINE_STRIDE,
445 win->stride[1] << 16 | win->stride[0]);
447 WR4(sc, DC_WIN_LINE_STRIDE, win->stride[0]);
450 /* Offsets for rotation and axis flip */
451 WR4(sc, DC_WINBUF_ADDR_H_OFFSET, h_offset);
452 WR4(sc, DC_WINBUF_ADDR_V_OFFSET, v_offset);
455 WR4(sc, DC_WIN_COLOR_DEPTH, win->color_mode);
456 WR4(sc, DC_WIN_BYTE_SWAP, win->swap);
459 val = win->surface_kind;
460 if (win->surface_kind == SURFACE_KIND_BL_16B2)
461 val |= SURFACE_KIND_BLOCK_HEIGHT(win->block_height);
462 WR4(sc, DC_WINBUF_SURFACE_KIND, val);
464 /* Color space coefs for YUV modes */
466 WR4(sc, DC_WINC_CSC_YOF, 0x00f0);
467 WR4(sc, DC_WINC_CSC_KYRGB, 0x012a);
468 WR4(sc, DC_WINC_CSC_KUR, 0x0000);
469 WR4(sc, DC_WINC_CSC_KVR, 0x0198);
470 WR4(sc, DC_WINC_CSC_KUG, 0x039b);
471 WR4(sc, DC_WINC_CSC_KVG, 0x032f);
472 WR4(sc, DC_WINC_CSC_KUB, 0x0204);
473 WR4(sc, DC_WINC_CSC_KVB, 0x0000);
479 else if (win->bits_per_pixel < 24)
485 if (win->transpose_xy)
487 WR4(sc, DC_WINC_WIN_OPTIONS, val);
489 #ifdef DMR_DEBUG_WINDOW
490 /* Set underflow debug mode -> highlight missing pixels. */
491 WR4(sc, DC_WINBUF_UFLOW_CTRL, UFLOW_CTR_ENABLE);
492 WR4(sc, DC_WINBUF_UFLOW_DBG_PIXEL, 0xFFFF0000);
498 /* -------------------------------------------------------------------
504 dc_plane_update(struct drm_plane *drm_plane, struct drm_crtc *drm_crtc,
505 struct drm_framebuffer *drm_fb,
506 int crtc_x, int crtc_y, unsigned int crtc_w, unsigned int crtc_h,
507 uint32_t src_x, uint32_t src_y, uint32_t src_w, uint32_t src_h)
509 struct tegra_plane *plane;
510 struct tegra_crtc *crtc;
513 struct dc_window win;
516 plane = container_of(drm_plane, struct tegra_plane, drm_plane);
517 fb = container_of(drm_fb, struct tegra_fb, drm_fb);
518 crtc = container_of(drm_crtc, struct tegra_crtc, drm_crtc);
519 sc = device_get_softc(crtc->dev);
521 memset(&win, 0, sizeof(win));
522 win.src_x = src_x >> 16;
523 win.src_y = src_y >> 16;
524 win.src_w = src_w >> 16;
525 win.src_h = src_h >> 16;
531 rv = dc_parse_drm_format(fb, &win);
533 DRM_WARNING("unsupported pixel format %d\n",
534 fb->drm_fb.pixel_format);
538 dc_setup_window(sc, plane->index, &win);
540 WR4(sc, DC_CMD_STATE_CONTROL, WIN_A_UPDATE << plane->index);
541 WR4(sc, DC_CMD_STATE_CONTROL, WIN_A_ACT_REQ << plane->index);
547 dc_plane_disable(struct drm_plane *drm_plane)
549 struct tegra_plane *plane;
550 struct tegra_crtc *crtc;
554 if (drm_plane->crtc == NULL)
556 plane = container_of(drm_plane, struct tegra_plane, drm_plane);
557 crtc = container_of(drm_plane->crtc, struct tegra_crtc, drm_crtc);
559 sc = device_get_softc(crtc->dev);
564 WR4(sc, DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_A_SELECT << idx);
566 val = RD4(sc, DC_WINC_WIN_OPTIONS);
568 WR4(sc, DC_WINC_WIN_OPTIONS, val);
572 WR4(sc, DC_CMD_STATE_CONTROL, WIN_A_UPDATE << idx);
573 WR4(sc, DC_CMD_STATE_CONTROL, WIN_A_ACT_REQ << idx);
579 dc_plane_destroy(struct drm_plane *plane)
582 dc_plane_disable(plane);
583 drm_plane_cleanup(plane);
584 free(plane, DRM_MEM_KMS);
587 static const struct drm_plane_funcs dc_plane_funcs = {
588 .update_plane = dc_plane_update,
589 .disable_plane = dc_plane_disable,
590 .destroy = dc_plane_destroy,
593 /* -------------------------------------------------------------------
595 * CRTC helper functions.
599 dc_crtc_dpms(struct drm_crtc *crtc, int mode)
605 dc_crtc_mode_fixup(struct drm_crtc *crtc, const struct drm_display_mode *mode,
606 struct drm_display_mode *adjusted)
613 dc_set_base(struct dc_softc *sc, int x, int y, struct tegra_fb *fb)
615 struct dc_window win;
618 memset(&win, 0, sizeof(win));
621 win.src_w = fb->drm_fb.width;
622 win.src_h = fb->drm_fb.height;
625 win.dst_w = fb->drm_fb.width;
626 win.dst_h = fb->drm_fb.height;
628 rv = dc_parse_drm_format(fb, &win);
630 DRM_WARNING("unsupported pixel format %d\n",
631 fb->drm_fb.pixel_format);
634 dc_setup_window(sc, 0, &win);
640 dc_crtc_mode_set(struct drm_crtc *drm_crtc, struct drm_display_mode *mode,
641 struct drm_display_mode *adjusted, int x, int y,
642 struct drm_framebuffer *old_fb)
645 struct tegra_crtc *crtc;
647 struct dc_window win;
648 uint32_t div, h_ref_to_sync, v_ref_to_sync;
651 crtc = container_of(drm_crtc, struct tegra_crtc, drm_crtc);
652 sc = device_get_softc(crtc->dev);
653 fb = container_of(drm_crtc->fb, struct tegra_fb, drm_fb);
658 rv = dc_setup_clk(sc, drm_crtc, mode, &div);
660 device_printf(sc->dev, "Cannot set pixel clock\n");
665 WR4(sc, DC_DISP_DISP_TIMING_OPTIONS, 0);
667 WR4(sc, DC_DISP_REF_TO_SYNC,
668 (v_ref_to_sync << 16) |
671 WR4(sc, DC_DISP_SYNC_WIDTH,
672 ((mode->vsync_end - mode->vsync_start) << 16) |
673 ((mode->hsync_end - mode->hsync_start) << 0));
675 WR4(sc, DC_DISP_BACK_PORCH,
676 ((mode->vtotal - mode->vsync_end) << 16) |
677 ((mode->htotal - mode->hsync_end) << 0));
679 WR4(sc, DC_DISP_FRONT_PORCH,
680 ((mode->vsync_start - mode->vdisplay) << 16) |
681 ((mode->hsync_start - mode->hdisplay) << 0));
683 WR4(sc, DC_DISP_DISP_ACTIVE,
684 (mode->vdisplay << 16) | mode->hdisplay);
686 WR4(sc, DC_DISP_DISP_INTERFACE_CONTROL, DISP_DATA_FORMAT(DF1P1C));
688 WR4(sc,DC_DISP_DISP_CLOCK_CONTROL,
689 SHIFT_CLK_DIVIDER(div) | PIXEL_CLK_DIVIDER(PCD1));
691 memset(&win, 0, sizeof(win));
694 win.src_w = mode->hdisplay;
695 win.src_h = mode->vdisplay;
698 win.dst_w = mode->hdisplay;
699 win.dst_h = mode->vdisplay;
701 rv = dc_parse_drm_format(fb, &win);
703 DRM_WARNING("unsupported pixel format %d\n",
704 drm_crtc->fb->pixel_format);
708 dc_setup_window(sc, 0, &win);
715 dc_crtc_mode_set_base(struct drm_crtc *drm_crtc, int x, int y,
716 struct drm_framebuffer *old_fb)
719 struct tegra_crtc *crtc;
723 crtc = container_of(drm_crtc, struct tegra_crtc, drm_crtc);
724 fb = container_of(drm_crtc->fb, struct tegra_fb, drm_fb);
725 sc = device_get_softc(crtc->dev);
727 rv = dc_set_base(sc, x, y, fb);
730 WR4(sc, DC_CMD_STATE_CONTROL, GENERAL_UPDATE | WIN_A_UPDATE);
731 WR4(sc, DC_CMD_STATE_CONTROL, GENERAL_ACT_REQ | WIN_A_ACT_REQ);
736 dc_crtc_prepare(struct drm_crtc *drm_crtc)
740 struct tegra_crtc *crtc;
743 crtc = container_of(drm_crtc, struct tegra_crtc, drm_crtc);
744 sc = device_get_softc(crtc->dev);
746 WR4(sc, DC_CMD_GENERAL_INCR_SYNCPT_CNTRL, SYNCPT_CNTRL_NO_STALL);
747 /* XXX allocate syncpoint from host1x */
748 WR4(sc, DC_CMD_CONT_SYNCPT_VSYNC, SYNCPT_VSYNC_ENABLE |
749 (sc->tegra_crtc.nvidia_head == 0 ? SYNCPT_VBLANK0: SYNCPT_VBLANK1));
751 WR4(sc, DC_CMD_DISPLAY_POWER_CONTROL,
752 PW0_ENABLE | PW1_ENABLE | PW2_ENABLE | PW3_ENABLE |
753 PW4_ENABLE | PM0_ENABLE | PM1_ENABLE);
755 val = RD4(sc, DC_CMD_DISPLAY_COMMAND);
756 val |= DISPLAY_CTRL_MODE(CTRL_MODE_C_DISPLAY);
757 WR4(sc, DC_CMD_DISPLAY_COMMAND, val);
759 WR4(sc, DC_CMD_INT_MASK,
760 WIN_A_UF_INT | WIN_B_UF_INT | WIN_C_UF_INT |
761 WIN_A_OF_INT | WIN_B_OF_INT | WIN_C_OF_INT);
763 WR4(sc, DC_CMD_INT_ENABLE,
764 VBLANK_INT | WIN_A_UF_INT | WIN_B_UF_INT | WIN_C_UF_INT |
765 WIN_A_OF_INT | WIN_B_OF_INT | WIN_C_OF_INT);
769 dc_crtc_commit(struct drm_crtc *drm_crtc)
772 struct tegra_crtc *crtc;
775 crtc = container_of(drm_crtc, struct tegra_crtc, drm_crtc);
776 sc = device_get_softc(crtc->dev);
778 WR4(sc, DC_CMD_STATE_CONTROL, GENERAL_UPDATE | WIN_A_UPDATE);
780 val = RD4(sc, DC_CMD_INT_MASK);
781 val |= FRAME_END_INT;
782 WR4(sc, DC_CMD_INT_MASK, val);
784 val = RD4(sc, DC_CMD_INT_ENABLE);
785 val |= FRAME_END_INT;
786 WR4(sc, DC_CMD_INT_ENABLE, val);
788 WR4(sc, DC_CMD_STATE_CONTROL, GENERAL_ACT_REQ | WIN_A_ACT_REQ);
792 dc_crtc_load_lut(struct drm_crtc *crtc)
798 static const struct drm_crtc_helper_funcs dc_crtc_helper_funcs = {
799 .dpms = dc_crtc_dpms,
800 .mode_fixup = dc_crtc_mode_fixup,
801 .mode_set = dc_crtc_mode_set,
802 .mode_set_base = dc_crtc_mode_set_base,
803 .prepare = dc_crtc_prepare,
804 .commit = dc_crtc_commit,
805 .load_lut = dc_crtc_load_lut,
809 drm_crtc_index(struct drm_crtc *crtc)
812 struct drm_crtc *tmp;
815 list_for_each_entry(tmp, &crtc->dev->mode_config.crtc_list, head) {
820 panic("Cannot find CRTC");
823 /* -------------------------------------------------------------------
825 * Exported functions (mainly vsync related).
827 * XXX revisit this -> convert to bus methods?
830 tegra_dc_get_pipe(struct drm_crtc *drm_crtc)
832 struct tegra_crtc *crtc;
834 crtc = container_of(drm_crtc, struct tegra_crtc, drm_crtc);
835 return (crtc->nvidia_head);
839 tegra_dc_enable_vblank(struct drm_crtc *drm_crtc)
842 struct tegra_crtc *crtc;
845 crtc = container_of(drm_crtc, struct tegra_crtc, drm_crtc);
846 sc = device_get_softc(crtc->dev);
849 val = RD4(sc, DC_CMD_INT_MASK);
851 WR4(sc, DC_CMD_INT_MASK, val);
856 tegra_dc_disable_vblank(struct drm_crtc *drm_crtc)
859 struct tegra_crtc *crtc;
862 crtc = container_of(drm_crtc, struct tegra_crtc, drm_crtc);
863 sc = device_get_softc(crtc->dev);
866 val = RD4(sc, DC_CMD_INT_MASK);
868 WR4(sc, DC_CMD_INT_MASK, val);
873 dc_finish_page_flip(struct dc_softc *sc)
875 struct drm_crtc *drm_crtc;
876 struct drm_device *drm;
882 drm_crtc = &sc->tegra_crtc.drm_crtc;
884 fb = container_of(drm_crtc->fb, struct tegra_fb, drm_fb);
886 mtx_lock(&drm->event_lock);
888 if (sc->event == NULL) {
889 mtx_unlock(&drm->event_lock);
894 /* Read active copy of WINBUF_START_ADDR */
895 WR4(sc, DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_A_SELECT);
896 WR4(sc, DC_CMD_STATE_ACCESS, READ_MUX);
897 base = RD4(sc, DC_WINBUF_START_ADDR);
898 WR4(sc, DC_CMD_STATE_ACCESS, 0);
901 /* Is already active */
902 bo = tegra_fb_get_plane(fb, 0);
903 if (base == (bo->pbase + fb->drm_fb.offsets[0])) {
904 idx = drm_crtc_index(drm_crtc);
905 drm_send_vblank_event(drm, idx, sc->event);
906 drm_vblank_put(drm, idx);
910 mtx_unlock(&drm->event_lock);
914 tegra_dc_cancel_page_flip(struct drm_crtc *drm_crtc, struct drm_file *file)
917 struct tegra_crtc *crtc;
918 struct drm_device *drm;
920 crtc = container_of(drm_crtc, struct tegra_crtc, drm_crtc);
921 sc = device_get_softc(crtc->dev);
923 mtx_lock(&drm->event_lock);
925 if ((sc->event != NULL) && (sc->event->base.file_priv == file)) {
926 sc->event->base.destroy(&sc->event->base);
927 drm_vblank_put(drm, drm_crtc_index(drm_crtc));
930 mtx_unlock(&drm->event_lock);
933 /* -------------------------------------------------------------------
939 dc_page_flip(struct drm_crtc *drm_crtc, struct drm_framebuffer *drm_fb,
940 struct drm_pending_vblank_event *event)
943 struct tegra_crtc *crtc;
945 struct drm_device *drm;
947 crtc = container_of(drm_crtc, struct tegra_crtc, drm_crtc);
948 sc = device_get_softc(crtc->dev);
949 fb = container_of(drm_crtc->fb, struct tegra_fb, drm_fb);
952 if (sc->event != NULL)
956 event->pipe = sc->tegra_crtc.nvidia_head;
958 drm_vblank_get(drm, event->pipe);
961 dc_set_base(sc, drm_crtc->x, drm_crtc->y, fb);
962 drm_crtc->fb = drm_fb;
965 WR4(sc, DC_CMD_STATE_CONTROL, GENERAL_UPDATE | WIN_A_UPDATE);
971 dc_cursor_set(struct drm_crtc *drm_crtc, struct drm_file *file,
972 uint32_t handle, uint32_t width, uint32_t height)
976 struct tegra_crtc *crtc;
977 struct drm_gem_object *gem;
980 uint32_t val, *src, *dst;
982 crtc = container_of(drm_crtc, struct tegra_crtc, drm_crtc);
983 sc = device_get_softc(crtc->dev);
990 val = CURSOR_SIZE(C32x32);
993 val = CURSOR_SIZE(C64x64);
996 val = CURSOR_SIZE(C128x128);
999 val = CURSOR_SIZE(C256x256);
1008 gem = drm_gem_object_lookup(drm_crtc->dev, file, handle);
1011 bo = container_of(gem, struct tegra_bo, gem_obj);
1014 if (sc->cursor_gem != NULL) {
1015 drm_gem_object_unreference(sc->cursor_gem);
1017 sc->cursor_gem = gem;
1021 * Copy cursor into cache and convert it from ARGB to RGBA.
1022 * XXXX - this is broken by design - client can write to BO at
1023 * any time. We can dedicate other window for cursor or switch
1024 * to sw cursor in worst case.
1026 src = (uint32_t *)bo->vbase;
1027 dst = (uint32_t *)crtc->cursor_vbase;
1028 for (i = 0; i < width * height; i++)
1029 dst[i] = (src[i] << 8) | (src[i] >> 24);
1031 val |= CURSOR_CLIP(CC_DISPLAY);
1032 val |= CURSOR_START_ADDR(crtc->cursor_pbase);
1033 WR4(sc, DC_DISP_CURSOR_START_ADDR, val);
1035 val = RD4(sc, DC_DISP_BLEND_CURSOR_CONTROL);
1036 val &= ~CURSOR_DST_BLEND_FACTOR_SELECT(~0);
1037 val &= ~CURSOR_SRC_BLEND_FACTOR_SELECT(~0);
1038 val |= CURSOR_MODE_SELECT;
1039 val |= CURSOR_DST_BLEND_FACTOR_SELECT(DST_NEG_K1_TIMES_SRC);
1040 val |= CURSOR_SRC_BLEND_FACTOR_SELECT(SRC_BLEND_K1_TIMES_SRC);
1041 val |= CURSOR_ALPHA(~0);
1042 WR4(sc, DC_DISP_BLEND_CURSOR_CONTROL, val);
1044 val = RD4(sc, DC_DISP_DISP_WIN_OPTIONS);
1045 val |= CURSOR_ENABLE;
1046 WR4(sc, DC_DISP_DISP_WIN_OPTIONS, val);
1048 val = RD4(sc, DC_DISP_DISP_WIN_OPTIONS);
1049 val &= ~CURSOR_ENABLE;
1050 WR4(sc, DC_DISP_DISP_WIN_OPTIONS, val);
1053 /* XXX This fixes cursor underflow issues, but why ? */
1054 WR4(sc, DC_DISP_CURSOR_UNDERFLOW_CTRL, CURSOR_UFLOW_CYA);
1056 WR4(sc, DC_CMD_STATE_CONTROL, GENERAL_UPDATE | CURSOR_UPDATE );
1057 WR4(sc, DC_CMD_STATE_CONTROL, GENERAL_ACT_REQ | CURSOR_ACT_REQ);
1062 dc_cursor_move(struct drm_crtc *drm_crtc, int x, int y)
1064 struct dc_softc *sc;
1065 struct tegra_crtc *crtc;
1067 crtc = container_of(drm_crtc, struct tegra_crtc, drm_crtc);
1068 sc = device_get_softc(crtc->dev);
1069 WR4(sc, DC_DISP_CURSOR_POSITION, CURSOR_POSITION(x, y));
1071 WR4(sc, DC_CMD_STATE_CONTROL, CURSOR_UPDATE);
1072 WR4(sc, DC_CMD_STATE_CONTROL, CURSOR_ACT_REQ);
1078 dc_destroy(struct drm_crtc *crtc)
1081 drm_crtc_cleanup(crtc);
1082 memset(crtc, 0, sizeof(*crtc));
1085 static const struct drm_crtc_funcs dc_crtc_funcs = {
1086 .page_flip = dc_page_flip,
1087 .cursor_set = dc_cursor_set,
1088 .cursor_move = dc_cursor_move,
1089 .set_config = drm_crtc_helper_set_config,
1090 .destroy = dc_destroy,
1093 /* -------------------------------------------------------------------
1095 * Bus and infrastructure.
1099 dc_init_planes(struct dc_softc *sc, struct tegra_drm *drm)
1102 struct tegra_plane *plane;
1105 for (i = 0; i < DC_MAX_PLANES; i++) {
1106 plane = malloc(sizeof(*plane), DRM_MEM_KMS, M_WAITOK | M_ZERO);
1107 plane->index = i + 1;
1108 rv = drm_plane_init(&drm->drm_dev, &plane->drm_plane,
1109 1 << sc->tegra_crtc.nvidia_head, &dc_plane_funcs,
1110 dc_plane_formats, nitems(dc_plane_formats), false);
1112 free(plane, DRM_MEM_KMS);
1120 dc_display_enable(device_t dev, bool enable)
1122 struct dc_softc *sc;
1125 sc = device_get_softc(dev);
1127 /* Set display mode */
1128 val = enable ? CTRL_MODE_C_DISPLAY: CTRL_MODE_STOP;
1129 WR4(sc, DC_CMD_DISPLAY_COMMAND, DISPLAY_CTRL_MODE(val));
1132 WR4(sc, DC_CMD_STATE_CONTROL, GENERAL_UPDATE);
1133 WR4(sc, DC_CMD_STATE_CONTROL, GENERAL_ACT_REQ);
1137 dc_hdmi_enable(device_t dev, bool enable)
1139 struct dc_softc *sc;
1142 sc = device_get_softc(dev);
1144 val = RD4(sc, DC_DISP_DISP_WIN_OPTIONS);
1148 val &= ~HDMI_ENABLE;
1149 WR4(sc, DC_DISP_DISP_WIN_OPTIONS, val);
1154 dc_setup_timing(device_t dev, int h_pulse_start)
1156 struct dc_softc *sc;
1158 sc = device_get_softc(dev);
1160 /* Setup display timing */
1161 WR4(sc, DC_DISP_DISP_TIMING_OPTIONS, VSYNC_H_POSITION(1));
1162 WR4(sc, DC_DISP_DISP_COLOR_CONTROL,
1163 DITHER_CONTROL(DITHER_DISABLE) | BASE_COLOR_SIZE(SIZE_BASE888));
1165 WR4(sc, DC_DISP_DISP_SIGNAL_OPTIONS0, H_PULSE2_ENABLE);
1166 WR4(sc, DC_DISP_H_PULSE2_CONTROL,
1167 PULSE_CONTROL_QUAL(QUAL_VACTIVE) | PULSE_CONTROL_LAST(LAST_END_A));
1169 WR4(sc, DC_DISP_H_PULSE2_POSITION_A,
1170 PULSE_START(h_pulse_start) | PULSE_END(h_pulse_start + 8));
1176 struct dc_softc *sc;
1181 /* Confirm interrupt */
1182 status = RD4(sc, DC_CMD_INT_STATUS);
1183 WR4(sc, DC_CMD_INT_STATUS, status);
1184 if (status & VBLANK_INT) {
1185 drm_handle_vblank(sc->tegra_crtc.drm_crtc.dev,
1186 sc->tegra_crtc.nvidia_head);
1187 dc_finish_page_flip(sc);
1192 dc_init_client(device_t dev, device_t host1x, struct tegra_drm *drm)
1194 struct dc_softc *sc;
1197 sc = device_get_softc(dev);
1199 if (drm->pitch_align < sc->pitch_align)
1200 drm->pitch_align = sc->pitch_align;
1202 drm_crtc_init(&drm->drm_dev, &sc->tegra_crtc.drm_crtc, &dc_crtc_funcs);
1203 drm_mode_crtc_set_gamma_size(&sc->tegra_crtc.drm_crtc, 256);
1204 drm_crtc_helper_add(&sc->tegra_crtc.drm_crtc, &dc_crtc_helper_funcs);
1206 rv = dc_init_planes(sc, drm);
1208 device_printf(dev, "Cannot init planes\n");
1212 WR4(sc, DC_CMD_INT_TYPE,
1213 WIN_A_UF_INT | WIN_B_UF_INT | WIN_C_UF_INT |
1214 WIN_A_OF_INT | WIN_B_OF_INT | WIN_C_OF_INT);
1216 WR4(sc, DC_CMD_INT_POLARITY,
1217 WIN_A_UF_INT | WIN_B_UF_INT | WIN_C_UF_INT |
1218 WIN_A_OF_INT | WIN_B_OF_INT | WIN_C_OF_INT);
1220 WR4(sc, DC_CMD_INT_ENABLE, 0);
1221 WR4(sc, DC_CMD_INT_MASK, 0);
1223 rv = bus_setup_intr(dev, sc->irq_res, INTR_TYPE_MISC | INTR_MPSAFE,
1224 NULL, dc_intr, sc, &sc->irq_ih);
1226 device_printf(dev, "Cannot register interrupt handler\n");
1230 /* allocate memory for cursor cache */
1231 sc->tegra_crtc.cursor_vbase = kmem_alloc_contig(256 * 256 * 4,
1232 M_WAITOK | M_ZERO, 0, -1UL, PAGE_SIZE, 0,
1233 VM_MEMATTR_WRITE_COMBINING);
1234 sc->tegra_crtc.cursor_pbase = vtophys(sc->tegra_crtc.cursor_vbase);
1239 dc_exit_client(device_t dev, device_t host1x, struct tegra_drm *drm)
1241 struct dc_softc *sc;
1243 sc = device_get_softc(dev);
1245 if (sc->irq_ih != NULL)
1246 bus_teardown_intr(dev, sc->irq_res, sc->irq_ih);
1253 get_fdt_resources(struct dc_softc *sc, phandle_t node)
1257 rv = hwreset_get_by_ofw_name(sc->dev, 0, "dc", &sc->hwreset_dc);
1259 device_printf(sc->dev, "Cannot get 'dc' reset\n");
1262 rv = clk_get_by_ofw_name(sc->dev, 0, "parent", &sc->clk_parent);
1264 device_printf(sc->dev, "Cannot get 'parent' clock\n");
1267 rv = clk_get_by_ofw_name(sc->dev, 0, "dc", &sc->clk_dc);
1269 device_printf(sc->dev, "Cannot get 'dc' clock\n");
1273 rv = OF_getencprop(node, "nvidia,head", &sc->tegra_crtc.nvidia_head,
1274 sizeof(sc->tegra_crtc.nvidia_head));
1276 device_printf(sc->dev,
1277 "Cannot get 'nvidia,head' property\n");
1284 enable_fdt_resources(struct dc_softc *sc)
1288 rv = clk_set_parent_by_clk(sc->clk_dc, sc->clk_parent);
1290 device_printf(sc->dev, "Cannot set parent for 'dc' clock\n");
1294 id = (sc->tegra_crtc.nvidia_head == 0) ?
1295 TEGRA_POWERGATE_DIS: TEGRA_POWERGATE_DISB;
1296 rv = tegra_powergate_sequence_power_up(id, sc->clk_dc, sc->hwreset_dc);
1298 device_printf(sc->dev, "Cannot enable 'DIS' powergate\n");
1306 dc_probe(device_t dev)
1309 if (!ofw_bus_status_okay(dev))
1312 if (ofw_bus_search_compatible(dev, compat_data)->ocd_data == 0)
1315 device_set_desc(dev, "Tegra Display Controller");
1316 return (BUS_PROBE_DEFAULT);
1320 dc_attach(device_t dev)
1322 struct dc_softc *sc;
1326 sc = device_get_softc(dev);
1328 sc->tegra_crtc.dev = dev;
1330 node = ofw_bus_get_node(sc->dev);
1334 sc->mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
1336 if (sc->mem_res == NULL) {
1337 device_printf(dev, "Cannot allocate memory resources\n");
1342 sc->irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, RF_ACTIVE);
1343 if (sc->irq_res == NULL) {
1344 device_printf(dev, "Cannot allocate IRQ resources\n");
1348 rv = get_fdt_resources(sc, node);
1350 device_printf(dev, "Cannot parse FDT resources\n");
1353 rv = enable_fdt_resources(sc);
1355 device_printf(dev, "Cannot enable FDT resources\n");
1361 * - 64 for RGB modes
1362 * - 128 for YUV planar modes
1363 * - 256 for block linear modes
1365 sc->pitch_align = 256;
1367 rv = TEGRA_DRM_REGISTER_CLIENT(device_get_parent(sc->dev), sc->dev);
1369 device_printf(dev, "Cannot register DRM device\n");
1373 return (bus_generic_attach(dev));
1376 TEGRA_DRM_DEREGISTER_CLIENT(device_get_parent(sc->dev), sc->dev);
1377 if (sc->irq_ih != NULL)
1378 bus_teardown_intr(dev, sc->irq_res, sc->irq_ih);
1379 if (sc->clk_parent != NULL)
1380 clk_release(sc->clk_parent);
1381 if (sc->clk_dc != NULL)
1382 clk_release(sc->clk_dc);
1383 if (sc->hwreset_dc != NULL)
1384 hwreset_release(sc->hwreset_dc);
1385 if (sc->irq_res != NULL)
1386 bus_release_resource(dev, SYS_RES_IRQ, 0, sc->irq_res);
1387 if (sc->mem_res != NULL)
1388 bus_release_resource(dev, SYS_RES_MEMORY, 0, sc->mem_res);
1395 dc_detach(device_t dev)
1397 struct dc_softc *sc;
1399 sc = device_get_softc(dev);
1401 TEGRA_DRM_DEREGISTER_CLIENT(device_get_parent(sc->dev), sc->dev);
1403 if (sc->irq_ih != NULL)
1404 bus_teardown_intr(dev, sc->irq_res, sc->irq_ih);
1405 if (sc->clk_parent != NULL)
1406 clk_release(sc->clk_parent);
1407 if (sc->clk_dc != NULL)
1408 clk_release(sc->clk_dc);
1409 if (sc->hwreset_dc != NULL)
1410 hwreset_release(sc->hwreset_dc);
1411 if (sc->irq_res != NULL)
1412 bus_release_resource(dev, SYS_RES_IRQ, 0, sc->irq_res);
1413 if (sc->mem_res != NULL)
1414 bus_release_resource(dev, SYS_RES_MEMORY, 0, sc->mem_res);
1417 return (bus_generic_detach(dev));
1420 static device_method_t tegra_dc_methods[] = {
1421 /* Device interface */
1422 DEVMETHOD(device_probe, dc_probe),
1423 DEVMETHOD(device_attach, dc_attach),
1424 DEVMETHOD(device_detach, dc_detach),
1426 /* tegra drm interface */
1427 DEVMETHOD(tegra_drm_init_client, dc_init_client),
1428 DEVMETHOD(tegra_drm_exit_client, dc_exit_client),
1430 /* tegra dc interface */
1431 DEVMETHOD(tegra_dc_display_enable, dc_display_enable),
1432 DEVMETHOD(tegra_dc_hdmi_enable, dc_hdmi_enable),
1433 DEVMETHOD(tegra_dc_setup_timing, dc_setup_timing),
1438 static devclass_t tegra_dc_devclass;
1439 DEFINE_CLASS_0(tegra_dc, tegra_dc_driver, tegra_dc_methods,
1440 sizeof(struct dc_softc));
1441 DRIVER_MODULE(tegra_dc, host1x, tegra_dc_driver, tegra_dc_devclass, NULL, NULL);