1 /* $NetBSD: sunxi_mixer.c,v 1.11 2020/02/09 15:22:25 jakllsch Exp $ */ 2 3 /*- 4 * Copyright (c) 2019 Jared D. McNeill <jmcneill@invisible.ca> 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 19 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 21 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 23 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 24 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 * SUCH DAMAGE. 27 */ 28 29 #include <sys/cdefs.h> 30 __KERNEL_RCSID(0, "$NetBSD: sunxi_mixer.c,v 1.11 2020/02/09 15:22:25 jakllsch Exp $"); 31 32 #include <sys/param.h> 33 #include <sys/bus.h> 34 #include <sys/device.h> 35 #include <sys/intr.h> 36 #include <sys/systm.h> 37 #include <sys/kernel.h> 38 #include <sys/conf.h> 39 #include <sys/sysctl.h> 40 41 #include <drm/drmP.h> 42 #include <drm/drm_crtc.h> 43 #include <drm/drm_crtc_helper.h> 44 #include <drm/drm_plane_helper.h> 45 46 #include <dev/fdt/fdtvar.h> 47 #include <dev/fdt/fdt_port.h> 48 49 #include <arm/sunxi/sunxi_drm.h> 50 51 #define MIXER_CURSOR_MAXWIDTH 256 52 #define MIXER_CURSOR_MAXHEIGHT 256 53 54 #define SUNXI_MIXER_FREQ 432000000 55 56 #define GLB_BASE 0x00000 57 #define BLD_BASE 0x01000 58 #define OVL_BASE(n) (0x02000 + (n) * 0x1000) 59 #define VSU_BASE 0x20000 60 #define CSC_BASE(n) ((n) == 0 ? 0xaa050 : 0xa0000) 61 62 /* GLB registers */ 63 #define GLB_CTL 0x000 64 #define GLB_CTL_EN __BIT(0) 65 #define GLB_STS 0x004 66 #define GLB_DBUFFER 0x008 67 #define GLB_DBUFFER_DOUBLE_BUFFER_RDY __BIT(0) 68 #define GLB_SIZE 0x00c 69 70 /* BLD registers */ 71 #define BLD_FILL_COLOR_CTL 0x000 72 #define BLD_FILL_COLOR_CTL_P3_EN __BIT(11) 73 #define BLD_FILL_COLOR_CTL_P2_EN __BIT(10) 74 #define BLD_FILL_COLOR_CTL_P1_EN __BIT(9) 75 #define BLD_FILL_COLOR_CTL_P0_EN __BIT(8) 76 #define BLD_FILL_COLOR_CTL_P3_FCEN __BIT(3) 77 #define BLD_FILL_COLOR_CTL_P2_FCEN __BIT(2) 78 #define BLD_FILL_COLOR_CTL_P1_FCEN __BIT(1) 79 #define BLD_FILL_COLOR_CTL_P0_FCEN __BIT(0) 80 #define BLD_FILL_COLOR(n) (0x004 + (n) * 0x10) 81 #define BLD_CH_ISIZE(n) (0x008 + (n) * 0x10) 82 #define BLD_CH_OFFSET(n) (0x00c + (n) * 0x10) 83 #define BLD_CH_RTCTL 0x080 84 #define BLD_CH_RTCTL_P3 __BITS(15,12) 85 #define BLD_CH_RTCTL_P2 __BITS(11,8) 86 #define BLD_CH_RTCTL_P1 __BITS(7,4) 87 #define BLD_CH_RTCTL_P0 __BITS(3,0) 88 #define BLD_SIZE 0x08c 89 #define BLD_CTL(n) (0x090 + (n) * 0x04) 90 91 /* OVL_V registers */ 92 #define OVL_V_ATTCTL(n) (0x000 + (n) * 0x30) 93 #define OVL_V_ATTCTL_VIDEO_UI_SEL __BIT(15) 94 #define OVL_V_ATTCTL_LAY_FBFMT __BITS(12,8) 95 #define OVL_V_ATTCTL_LAY_FBFMT_VYUY 0x00 96 #define OVL_V_ATTCTL_LAY_FBFMT_YVYU 0x01 97 #define OVL_V_ATTCTL_LAY_FBFMT_UYVY 0x02 98 #define OVL_V_ATTCTL_LAY_FBFMT_YUYV 0x03 99 #define OVL_V_ATTCTL_LAY_FBFMT_YUV422 0x06 100 #define OVL_V_ATTCTL_LAY_FBFMT_YUV420 0x0a 101 #define OVL_V_ATTCTL_LAY_FBFMT_YUV411 0x0e 102 #define OVL_V_ATTCTL_LAY_FBFMT_ARGB_8888 0x00 103 #define OVL_V_ATTCTL_LAY_FBFMT_XRGB_8888 0x04 104 #define OVL_V_ATTCTL_LAY0_EN __BIT(0) 105 #define OVL_V_MBSIZE(n) (0x004 + (n) * 0x30) 106 #define OVL_V_COOR(n) (0x008 + (n) * 0x30) 107 #define OVL_V_PITCH0(n) (0x00c + (n) * 0x30) 108 #define OVL_V_PITCH1(n) (0x010 + (n) * 0x30) 109 #define OVL_V_PITCH2(n) (0x014 + (n) * 0x30) 110 #define OVL_V_TOP_LADD0(n) (0x018 + (n) * 0x30) 111 #define OVL_V_TOP_LADD1(n) (0x01c + (n) * 0x30) 112 #define OVL_V_TOP_LADD2(n) (0x020 + (n) * 0x30) 113 #define OVL_V_FILL_COLOR(n) (0x0c0 + (n) * 0x4) 114 #define OVL_V_TOP_HADD0 0x0d0 115 #define OVL_V_TOP_HADD1 0x0d4 116 #define OVL_V_TOP_HADD2 0x0d8 117 #define OVL_V_TOP_HADD_LAYER0 __BITS(7,0) 118 #define OVL_V_SIZE 0x0e8 119 #define OVL_V_HDS_CTL0 0x0f0 120 #define OVL_V_HDS_CTL1 0x0f4 121 #define OVL_V_VDS_CTL0 0x0f8 122 #define OVL_V_VDS_CTL1 0x0fc 123 124 /* OVL_UI registers */ 125 #define OVL_UI_ATTR_CTL(n) (0x000 + (n) * 0x20) 126 #define OVL_UI_ATTR_CTL_LAY_FBFMT __BITS(12,8) 127 #define OVL_UI_ATTR_CTL_LAY_FBFMT_ARGB_8888 0x00 128 #define OVL_UI_ATTR_CTL_LAY_FBFMT_XRGB_8888 0x04 129 #define OVL_UI_ATTR_CTL_LAY_EN __BIT(0) 130 #define OVL_UI_MBSIZE(n) (0x004 + (n) * 0x20) 131 #define OVL_UI_COOR(n) (0x008 + (n) * 0x20) 132 #define OVL_UI_PITCH(n) (0x00c + (n) * 0x20) 133 #define OVL_UI_TOP_LADD(n) (0x010 + (n) * 0x20) 134 #define OVL_UI_FILL_COLOR(n) (0x018 + (n) * 0x20) 135 #define OVL_UI_TOP_HADD 0x080 136 #define OVL_UI_TOP_HADD_LAYER1 __BITS(15,8) 137 #define OVL_UI_TOP_HADD_LAYER0 __BITS(7,0) 138 #define OVL_UI_SIZE 0x088 139 140 /* VSU registers */ 141 #define VS_CTRL_REG 0x000 142 #define VS_CTRL_COEF_SWITCH_EN __BIT(4) 143 #define VS_CTRL_EN __BIT(0) 144 #define VS_STATUS_REG 0x008 145 #define VS_FIELD_CTRL_REG 0x00c 146 #define VS_OUT_SIZE_REG 0x040 147 #define VS_Y_SIZE_REG 0x080 148 #define VS_Y_HSTEP_REG 0x088 149 #define VS_Y_VSTEP_REG 0x08c 150 #define VS_Y_HPHASE_REG 0x090 151 #define VS_Y_VPHASE0_REG 0x098 152 #define VS_Y_VPHASE1_REG 0x09c 153 #define VS_C_SIZE_REG 0x0c0 154 #define VS_C_HSTEP_REG 0x0c8 155 #define VS_C_VSTEP_REG 0x0cc 156 #define VS_C_HPHASE_REG 0x0d0 157 #define VS_C_VPHASE0_REG 0x0d8 158 #define VS_C_VPHASE1_REG 0x0dc 159 #define VS_Y_HCOEF0_REG(n) (0x200 + (n) * 0x4) 160 #define VS_Y_HCOEF1_REG(n) (0x300 + (n) * 0x4) 161 #define VS_Y_VCOEF_REG(n) (0x400 + (n) * 0x4) 162 #define VS_C_HCOEF0_REG(n) (0x600 + (n) * 0x4) 163 #define VS_C_HCOEF1_REG(n) (0x700 + (n) * 0x4) 164 #define VS_C_VCOEF_REG(n) (0x800 + (n) * 0x4) 165 166 /* CSC registers */ 167 #define CSC_BYPASS_REG 0x000 168 #define CSC_BYPASS_DISABLE __BIT(0) 169 #define CSC_COEFF0_REG(n) (0x10 + 0x10 * (n)) 170 #define GLB_ALPHA_REG 0x040 171 172 enum { 173 MIXER_PORT_OUTPUT = 1, 174 }; 175 176 struct sunxi_mixer_compat_data { 177 uint8_t ovl_ui_count; 178 uint8_t mixer_index; 179 }; 180 181 struct sunxi_mixer_compat_data mixer0_data = { 182 .ovl_ui_count = 3, 183 .mixer_index = 0, 184 }; 185 186 struct sunxi_mixer_compat_data mixer1_data = { 187 .ovl_ui_count = 1, 188 .mixer_index = 1, 189 }; 190 191 static const struct of_compat_data compat_data[] = { 192 { "allwinner,sun8i-h3-de2-mixer-0", (uintptr_t)&mixer0_data }, 193 { "allwinner,sun50i-a64-de2-mixer-0", (uintptr_t)&mixer0_data }, 194 { "allwinner,sun50i-a64-de2-mixer-1", (uintptr_t)&mixer1_data }, 195 { NULL } 196 }; 197 198 struct sunxi_mixer_softc; 199 200 struct sunxi_mixer_crtc { 201 struct drm_crtc base; 202 struct sunxi_mixer_softc *sc; 203 }; 204 205 struct sunxi_mixer_plane { 206 struct drm_plane base; 207 struct sunxi_mixer_softc *sc; 208 }; 209 210 struct sunxi_mixer_softc { 211 device_t sc_dev; 212 bus_space_tag_t sc_bst; 213 bus_space_handle_t sc_bsh; 214 int sc_phandle; 215 216 u_int sc_ovl_ui_count; 217 218 struct sunxi_mixer_crtc sc_crtc; 219 struct sunxi_mixer_plane sc_overlay; 220 221 struct fdt_device_ports sc_ports; 222 }; 223 224 #define GLB_READ(sc, reg) \ 225 bus_space_read_4((sc)->sc_bst, (sc)->sc_bsh, GLB_BASE + (reg)) 226 #define GLB_WRITE(sc, reg, val) \ 227 bus_space_write_4((sc)->sc_bst, (sc)->sc_bsh, GLB_BASE + (reg), (val)) 228 229 #define BLD_READ(sc, reg) \ 230 bus_space_read_4((sc)->sc_bst, (sc)->sc_bsh, BLD_BASE + (reg)) 231 #define BLD_WRITE(sc, reg, val) \ 232 bus_space_write_4((sc)->sc_bst, (sc)->sc_bsh, BLD_BASE + (reg), (val)) 233 234 #define OVL_V_READ(sc, reg) \ 235 bus_space_read_4((sc)->sc_bst, (sc)->sc_bsh, OVL_BASE(0) + (reg)) 236 #define OVL_V_WRITE(sc, reg, val) \ 237 bus_space_write_4((sc)->sc_bst, (sc)->sc_bsh, OVL_BASE(0) + (reg), (val)) 238 239 #define OVL_UI_READ(sc, n, reg) \ 240 bus_space_read_4((sc)->sc_bst, (sc)->sc_bsh, OVL_BASE((n) + 1) + (reg)) 241 #define OVL_UI_WRITE(sc, n, reg, val) \ 242 bus_space_write_4((sc)->sc_bst, (sc)->sc_bsh, OVL_BASE((n) + 1) + (reg), (val)) 243 244 #define VSU_READ(sc, reg) \ 245 bus_space_read_4((sc)->sc_bst, (sc)->sc_bsh, VSU_BASE + (reg)) 246 #define VSU_WRITE(sc, reg, val) \ 247 bus_space_write_4((sc)->sc_bst, (sc)->sc_bsh, VSU_BASE + (reg), (val)) 248 249 #define CSC_READ(sc, n, reg) \ 250 bus_space_read_4((sc)->sc_bst, (sc)->sc_bsh, CSC_BASE(n) + (reg)) 251 #define CSC_WRITE(sc, n, reg, val) \ 252 bus_space_write_4((sc)->sc_bst, (sc)->sc_bsh, CSC_BASE(n) + (reg), (val)) 253 254 #define to_sunxi_mixer_crtc(x) container_of(x, struct sunxi_mixer_crtc, base) 255 #define to_sunxi_mixer_plane(x) container_of(x, struct sunxi_mixer_plane, base) 256 257 static int 258 sunxi_mixer_mode_do_set_base(struct drm_crtc *crtc, struct drm_framebuffer *fb, 259 int x, int y, int atomic) 260 { 261 struct sunxi_mixer_crtc *mixer_crtc = to_sunxi_mixer_crtc(crtc); 262 struct sunxi_mixer_softc * const sc = mixer_crtc->sc; 263 struct sunxi_drm_framebuffer *sfb = atomic? 264 to_sunxi_drm_framebuffer(fb) : 265 to_sunxi_drm_framebuffer(crtc->primary->fb); 266 uint32_t val; 267 268 uint64_t paddr = (uint64_t)sfb->obj->dmamap->dm_segs[0].ds_addr; 269 270 paddr += y * sfb->base.pitches[0]; 271 paddr += x * drm_format_plane_cpp(sfb->base.pixel_format, 0); 272 273 uint32_t haddr = (paddr >> 32) & OVL_UI_TOP_HADD_LAYER0; 274 uint32_t laddr = paddr & 0xffffffff; 275 276 /* Set UI overlay line size */ 277 OVL_UI_WRITE(sc, 0, OVL_UI_PITCH(0), sfb->base.pitches[0]); 278 279 /* Framebuffer start address */ 280 val = OVL_UI_READ(sc, 0, OVL_UI_TOP_HADD); 281 val &= ~OVL_UI_TOP_HADD_LAYER0; 282 val |= __SHIFTIN(haddr, OVL_UI_TOP_HADD_LAYER0); 283 OVL_UI_WRITE(sc, 0, OVL_UI_TOP_HADD, val); 284 OVL_UI_WRITE(sc, 0, OVL_UI_TOP_LADD(0), laddr); 285 286 return 0; 287 } 288 289 static void 290 sunxi_mixer_destroy(struct drm_crtc *crtc) 291 { 292 drm_crtc_cleanup(crtc); 293 } 294 295 static int 296 sunxi_mixer_page_flip(struct drm_crtc *crtc, struct drm_framebuffer *fb, 297 struct drm_pending_vblank_event *event, uint32_t flags) 298 { 299 struct sunxi_mixer_crtc *mixer_crtc = to_sunxi_mixer_crtc(crtc); 300 struct sunxi_mixer_softc * const sc = mixer_crtc->sc; 301 unsigned long irqflags; 302 303 drm_crtc_wait_one_vblank(crtc); 304 305 sunxi_mixer_mode_do_set_base(crtc, fb, 0, 0, true); 306 307 /* Commit settings */ 308 GLB_WRITE(sc, GLB_DBUFFER, GLB_DBUFFER_DOUBLE_BUFFER_RDY); 309 310 if (event) { 311 spin_lock_irqsave(&crtc->dev->event_lock, irqflags); 312 drm_send_vblank_event(crtc->dev, drm_crtc_index(crtc), event); 313 spin_unlock_irqrestore(&crtc->dev->event_lock, irqflags); 314 } 315 316 return 0; 317 } 318 319 static int 320 sunxi_mixer_cursor_set(struct drm_crtc *crtc, struct drm_file *file_priv, 321 uint32_t handle, uint32_t width, uint32_t height) 322 { 323 struct sunxi_mixer_crtc *mixer_crtc = to_sunxi_mixer_crtc(crtc); 324 struct sunxi_mixer_softc * const sc = mixer_crtc->sc; 325 struct drm_gem_object *gem_obj = NULL; 326 struct drm_gem_cma_object *obj; 327 uint32_t val; 328 int error; 329 330 /* Only mixers with more than one UI layer can support hardware cursors */ 331 if (sc->sc_ovl_ui_count <= 1) 332 return -EINVAL; 333 334 if (handle == 0) { 335 val = BLD_READ(sc, BLD_FILL_COLOR_CTL); 336 val &= ~BLD_FILL_COLOR_CTL_P2_EN; 337 val |= BLD_FILL_COLOR_CTL_P2_FCEN; 338 BLD_WRITE(sc, BLD_FILL_COLOR_CTL, val); 339 340 error = 0; 341 goto done; 342 } 343 344 /* Arbitrary limits, the hardware layer can do 8192x8192 */ 345 if (width > MIXER_CURSOR_MAXWIDTH || height > MIXER_CURSOR_MAXHEIGHT) { 346 DRM_ERROR("Cursor dimension %ux%u not supported\n", width, height); 347 error = -EINVAL; 348 goto done; 349 } 350 351 gem_obj = drm_gem_object_lookup(crtc->dev, file_priv, handle); 352 if (gem_obj == NULL) { 353 DRM_ERROR("Cannot find cursor object %#x for crtc %d\n", 354 handle, drm_crtc_index(crtc)); 355 error = -ENOENT; 356 goto done; 357 } 358 obj = to_drm_gem_cma_obj(gem_obj); 359 360 if (obj->base.size < width * height * 4) { 361 DRM_ERROR("Cursor buffer is too small\n"); 362 error = -ENOMEM; 363 goto done; 364 } 365 366 uint64_t paddr = (uint64_t)obj->dmamap->dm_segs[0].ds_addr; 367 uint32_t haddr = (paddr >> 32) & OVL_UI_TOP_HADD_LAYER0; 368 uint32_t laddr = paddr & 0xffffffff; 369 370 /* Framebuffer start address */ 371 val = OVL_UI_READ(sc, 1, OVL_UI_TOP_HADD); 372 val &= ~OVL_UI_TOP_HADD_LAYER0; 373 val |= __SHIFTIN(haddr, OVL_UI_TOP_HADD_LAYER0); 374 OVL_UI_WRITE(sc, 1, OVL_UI_TOP_HADD, val); 375 OVL_UI_WRITE(sc, 1, OVL_UI_TOP_LADD(0), laddr); 376 377 const uint32_t size = ((height - 1) << 16) | (width - 1); 378 const uint32_t offset = (crtc->cursor_y << 16) | crtc->cursor_x; 379 const uint32_t crtc_size = ((crtc->primary->fb->height - 1) << 16) | 380 (crtc->primary->fb->width - 1); 381 382 /* Enable cursor in ARGB8888 mode */ 383 val = OVL_UI_ATTR_CTL_LAY_EN | 384 __SHIFTIN(OVL_UI_ATTR_CTL_LAY_FBFMT_ARGB_8888, OVL_UI_ATTR_CTL_LAY_FBFMT); 385 OVL_UI_WRITE(sc, 1, OVL_UI_ATTR_CTL(0), val); 386 /* Set UI overlay layer size */ 387 OVL_UI_WRITE(sc, 1, OVL_UI_MBSIZE(0), size); 388 /* Set UI overlay offset */ 389 OVL_UI_WRITE(sc, 1, OVL_UI_COOR(0), offset); 390 /* Set UI overlay line size */ 391 OVL_UI_WRITE(sc, 1, OVL_UI_PITCH(0), width * 4); 392 /* Set UI overlay window size */ 393 OVL_UI_WRITE(sc, 1, OVL_UI_SIZE, crtc_size); 394 395 /* Set blender 2 input size */ 396 BLD_WRITE(sc, BLD_CH_ISIZE(2), crtc_size); 397 /* Set blender 2 offset */ 398 BLD_WRITE(sc, BLD_CH_OFFSET(2), 0); 399 /* Route channel 2 to pipe 2 */ 400 val = BLD_READ(sc, BLD_CH_RTCTL); 401 val &= ~BLD_CH_RTCTL_P2; 402 val |= __SHIFTIN(2, BLD_CH_RTCTL_P2); 403 BLD_WRITE(sc, BLD_CH_RTCTL, val); 404 405 /* Enable pipe 2 */ 406 val = BLD_READ(sc, BLD_FILL_COLOR_CTL); 407 val |= BLD_FILL_COLOR_CTL_P2_EN; 408 val &= ~BLD_FILL_COLOR_CTL_P2_FCEN; 409 BLD_WRITE(sc, BLD_FILL_COLOR_CTL, val); 410 411 error = 0; 412 413 done: 414 if (error == 0) { 415 /* Commit settings */ 416 GLB_WRITE(sc, GLB_DBUFFER, GLB_DBUFFER_DOUBLE_BUFFER_RDY); 417 } 418 419 if (gem_obj != NULL) 420 drm_gem_object_unreference_unlocked(gem_obj); 421 422 return error; 423 } 424 425 static int 426 sunxi_mixer_cursor_move(struct drm_crtc *crtc, int x, int y) 427 { 428 struct sunxi_mixer_crtc *mixer_crtc = to_sunxi_mixer_crtc(crtc); 429 struct sunxi_mixer_softc * const sc = mixer_crtc->sc; 430 431 crtc->cursor_x = x & 0xffff; 432 crtc->cursor_y = y & 0xffff; 433 434 const uint32_t offset = (crtc->cursor_y << 16) | crtc->cursor_x; 435 436 OVL_UI_WRITE(sc, 1, OVL_UI_COOR(0), offset); 437 438 /* Commit settings */ 439 GLB_WRITE(sc, GLB_DBUFFER, GLB_DBUFFER_DOUBLE_BUFFER_RDY); 440 441 return 0; 442 } 443 444 static const struct drm_crtc_funcs sunxi_mixer0_crtc_funcs = { 445 .set_config = drm_crtc_helper_set_config, 446 .destroy = sunxi_mixer_destroy, 447 .page_flip = sunxi_mixer_page_flip, 448 .cursor_set = sunxi_mixer_cursor_set, 449 .cursor_move = sunxi_mixer_cursor_move, 450 }; 451 452 static const struct drm_crtc_funcs sunxi_mixer1_crtc_funcs = { 453 .set_config = drm_crtc_helper_set_config, 454 .destroy = sunxi_mixer_destroy, 455 .page_flip = sunxi_mixer_page_flip, 456 }; 457 458 static void 459 sunxi_mixer_dpms(struct drm_crtc *crtc, int mode) 460 { 461 } 462 463 static bool 464 sunxi_mixer_mode_fixup(struct drm_crtc *crtc, 465 const struct drm_display_mode *mode, struct drm_display_mode *adjusted_mode) 466 { 467 return true; 468 } 469 470 static int 471 sunxi_mixer_mode_set(struct drm_crtc *crtc, struct drm_display_mode *mode, 472 struct drm_display_mode *adjusted_mode, int x, int y, 473 struct drm_framebuffer *old_fb) 474 { 475 struct sunxi_mixer_crtc *mixer_crtc = to_sunxi_mixer_crtc(crtc); 476 struct sunxi_mixer_softc * const sc = mixer_crtc->sc; 477 uint32_t val; 478 u_int fbfmt; 479 480 const uint32_t size = ((adjusted_mode->vdisplay - 1) << 16) | 481 (adjusted_mode->hdisplay - 1); 482 483 /* Set global size */ 484 GLB_WRITE(sc, GLB_SIZE, size); 485 486 /* Enable pipe 0 */ 487 val = BLD_READ(sc, BLD_FILL_COLOR_CTL); 488 val |= BLD_FILL_COLOR_CTL_P0_EN; 489 BLD_WRITE(sc, BLD_FILL_COLOR_CTL, val); 490 491 /* Set blender 0 input size */ 492 BLD_WRITE(sc, BLD_CH_ISIZE(0), size); 493 /* Set blender 0 offset */ 494 BLD_WRITE(sc, BLD_CH_OFFSET(0), 0); 495 /* Route channel 1 to pipe 0 */ 496 val = BLD_READ(sc, BLD_CH_RTCTL); 497 val &= ~BLD_CH_RTCTL_P0; 498 val |= __SHIFTIN(1, BLD_CH_RTCTL_P0); 499 BLD_WRITE(sc, BLD_CH_RTCTL, val); 500 /* Set blender output size */ 501 BLD_WRITE(sc, BLD_SIZE, size); 502 503 /* Enable UI overlay */ 504 if (crtc->primary->fb->pixel_format == DRM_FORMAT_XRGB8888) 505 fbfmt = OVL_UI_ATTR_CTL_LAY_FBFMT_XRGB_8888; 506 else 507 fbfmt = OVL_UI_ATTR_CTL_LAY_FBFMT_ARGB_8888; 508 val = OVL_UI_ATTR_CTL_LAY_EN | __SHIFTIN(fbfmt, OVL_UI_ATTR_CTL_LAY_FBFMT); 509 OVL_UI_WRITE(sc, 0, OVL_UI_ATTR_CTL(0), val); 510 /* Set UI overlay layer size */ 511 OVL_UI_WRITE(sc, 0, OVL_UI_MBSIZE(0), size); 512 /* Set UI overlay offset */ 513 OVL_UI_WRITE(sc, 0, OVL_UI_COOR(0), 0); 514 /* Set UI overlay window size */ 515 OVL_UI_WRITE(sc, 0, OVL_UI_SIZE, size); 516 517 sunxi_mixer_mode_do_set_base(crtc, old_fb, x, y, 0); 518 519 return 0; 520 } 521 522 static int 523 sunxi_mixer_mode_set_base(struct drm_crtc *crtc, int x, int y, 524 struct drm_framebuffer *old_fb) 525 { 526 struct sunxi_mixer_crtc *mixer_crtc = to_sunxi_mixer_crtc(crtc); 527 struct sunxi_mixer_softc * const sc = mixer_crtc->sc; 528 529 sunxi_mixer_mode_do_set_base(crtc, old_fb, x, y, 0); 530 531 /* Commit settings */ 532 GLB_WRITE(sc, GLB_DBUFFER, GLB_DBUFFER_DOUBLE_BUFFER_RDY); 533 534 return 0; 535 } 536 537 static int 538 sunxi_mixer_mode_set_base_atomic(struct drm_crtc *crtc, struct drm_framebuffer *fb, 539 int x, int y, enum mode_set_atomic state) 540 { 541 struct sunxi_mixer_crtc *mixer_crtc = to_sunxi_mixer_crtc(crtc); 542 struct sunxi_mixer_softc * const sc = mixer_crtc->sc; 543 544 sunxi_mixer_mode_do_set_base(crtc, fb, x, y, 1); 545 546 /* Commit settings */ 547 GLB_WRITE(sc, GLB_DBUFFER, GLB_DBUFFER_DOUBLE_BUFFER_RDY); 548 549 return 0; 550 } 551 552 static void 553 sunxi_mixer_disable(struct drm_crtc *crtc) 554 { 555 } 556 557 static void 558 sunxi_mixer_prepare(struct drm_crtc *crtc) 559 { 560 struct sunxi_mixer_crtc *mixer_crtc = to_sunxi_mixer_crtc(crtc); 561 struct sunxi_mixer_softc * const sc = mixer_crtc->sc; 562 563 /* RT enable */ 564 GLB_WRITE(sc, GLB_CTL, GLB_CTL_EN); 565 } 566 567 static void 568 sunxi_mixer_commit(struct drm_crtc *crtc) 569 { 570 struct sunxi_mixer_crtc *mixer_crtc = to_sunxi_mixer_crtc(crtc); 571 struct sunxi_mixer_softc * const sc = mixer_crtc->sc; 572 573 /* Commit settings */ 574 GLB_WRITE(sc, GLB_DBUFFER, GLB_DBUFFER_DOUBLE_BUFFER_RDY); 575 } 576 577 static const struct drm_crtc_helper_funcs sunxi_mixer_crtc_helper_funcs = { 578 .dpms = sunxi_mixer_dpms, 579 .mode_fixup = sunxi_mixer_mode_fixup, 580 .mode_set = sunxi_mixer_mode_set, 581 .mode_set_base = sunxi_mixer_mode_set_base, 582 .mode_set_base_atomic = sunxi_mixer_mode_set_base_atomic, 583 .disable = sunxi_mixer_disable, 584 .prepare = sunxi_mixer_prepare, 585 .commit = sunxi_mixer_commit, 586 }; 587 588 static void 589 sunxi_mixer_overlay_destroy(struct drm_plane *plane) 590 { 591 } 592 593 static bool 594 sunxi_mixer_overlay_rgb(uint32_t drm_format) 595 { 596 switch (drm_format) { 597 case DRM_FORMAT_ARGB8888: 598 case DRM_FORMAT_XRGB8888: 599 return true; 600 default: 601 return false; 602 } 603 } 604 605 static u_int 606 sunxi_mixer_overlay_format(uint32_t drm_format) 607 { 608 switch (drm_format) { 609 case DRM_FORMAT_ARGB8888: return OVL_V_ATTCTL_LAY_FBFMT_ARGB_8888; 610 case DRM_FORMAT_XRGB8888: return OVL_V_ATTCTL_LAY_FBFMT_XRGB_8888; 611 case DRM_FORMAT_VYUY: return OVL_V_ATTCTL_LAY_FBFMT_VYUY; 612 case DRM_FORMAT_YVYU: return OVL_V_ATTCTL_LAY_FBFMT_YVYU; 613 case DRM_FORMAT_UYVY: return OVL_V_ATTCTL_LAY_FBFMT_UYVY; 614 case DRM_FORMAT_YUYV: return OVL_V_ATTCTL_LAY_FBFMT_YUYV; 615 case DRM_FORMAT_YUV422: return OVL_V_ATTCTL_LAY_FBFMT_YUV422; 616 case DRM_FORMAT_YUV420: return OVL_V_ATTCTL_LAY_FBFMT_YUV420; 617 case DRM_FORMAT_YUV411: return OVL_V_ATTCTL_LAY_FBFMT_YUV411; 618 default: return 0; /* shouldn't happen */ 619 } 620 } 621 622 static const uint32_t lan3coefftab32_left[512] = { 623 0x40000000, 0x40fe0000, 0x3ffd0100, 0x3efc0100, 624 0x3efb0100, 0x3dfa0200, 0x3cf90200, 0x3bf80200, 625 0x39f70200, 0x37f70200, 0x35f70200, 0x33f70200, 626 0x31f70200, 0x2ef70200, 0x2cf70200, 0x2af70200, 627 0x27f70200, 0x24f80100, 0x22f80100, 0x1ef90100, 628 0x1cf90100, 0x19fa0100, 0x17fa0100, 0x14fb0100, 629 0x11fc0000, 0x0ffc0000, 0x0cfd0000, 0x0afd0000, 630 0x08fe0000, 0x05ff0000, 0x03ff0000, 0x02000000, 631 632 0x40000000, 0x40fe0000, 0x3ffd0100, 0x3efc0100, 633 0x3efb0100, 0x3dfa0200, 0x3cf90200, 0x3bf80200, 634 0x39f70200, 0x37f70200, 0x35f70200, 0x33f70200, 635 0x31f70200, 0x2ef70200, 0x2cf70200, 0x2af70200, 636 0x27f70200, 0x24f80100, 0x22f80100, 0x1ef90100, 637 0x1cf90100, 0x19fa0100, 0x17fa0100, 0x14fb0100, 638 0x11fc0000, 0x0ffc0000, 0x0cfd0000, 0x0afd0000, 639 0x08fe0000, 0x05ff0000, 0x03ff0000, 0x02000000, 640 641 0x3806fc02, 0x3805fc02, 0x3803fd01, 0x3801fe01, 642 0x3700fe01, 0x35ffff01, 0x35fdff01, 0x34fc0001, 643 0x34fb0000, 0x33fa0000, 0x31fa0100, 0x2ff90100, 644 0x2df80200, 0x2bf80200, 0x2af70200, 0x28f70200, 645 0x27f70200, 0x24f70300, 0x22f70300, 0x1ff70300, 646 0x1ef70300, 0x1cf70300, 0x1af70300, 0x18f70300, 647 0x16f80300, 0x13f80300, 0x11f90300, 0x0ef90300, 648 0x0efa0200, 0x0cfa0200, 0x0afb0200, 0x08fb0200, 649 650 0x320bfa02, 0x3309fa02, 0x3208fb02, 0x3206fb02, 651 0x3205fb02, 0x3104fc02, 0x3102fc01, 0x3001fd01, 652 0x3000fd01, 0x2ffffd01, 0x2efefe01, 0x2dfdfe01, 653 0x2bfcff01, 0x29fcff01, 0x28fbff01, 0x27fa0001, 654 0x26fa0000, 0x24f90000, 0x22f90100, 0x20f90100, 655 0x1ff80100, 0x1ef80100, 0x1cf80100, 0x1af80200, 656 0x18f80200, 0x17f80200, 0x15f80200, 0x12f80200, 657 0x11f90200, 0x0ff90200, 0x0df90200, 0x0cfa0200, 658 659 0x2e0efa01, 0x2f0dfa01, 0x2f0bfa01, 0x2e0afa01, 660 0x2e09fa01, 0x2e07fb01, 0x2d06fb01, 0x2d05fb01, 661 0x2c04fb01, 0x2b03fc01, 0x2a02fc01, 0x2a01fc01, 662 0x2800fd01, 0x28fffd01, 0x26fefd01, 0x25fefe01, 663 0x24fdfe01, 0x23fcfe01, 0x21fcff01, 0x20fbff01, 664 0x1efbff01, 0x1efbff00, 0x1cfa0000, 0x1bfa0000, 665 0x19fa0000, 0x18fa0000, 0x17f90000, 0x15f90100, 666 0x14f90100, 0x12f90100, 0x11f90100, 0x0ff90100, 667 668 0x2b10fa00, 0x2b0ffa00, 0x2b0efa00, 0x2b0cfa00, 669 0x2b0bfa00, 0x2a0afb01, 0x2a09fb01, 0x2908fb01, 670 0x2807fb01, 0x2806fb01, 0x2805fb01, 0x2604fc01, 671 0x2503fc01, 0x2502fc01, 0x2401fc01, 0x2301fc01, 672 0x2100fd01, 0x21fffd01, 0x21fffd01, 0x20fefd01, 673 0x1dfefe01, 0x1cfdfe01, 0x1cfdfe00, 0x1bfcfe00, 674 0x19fcff00, 0x19fbff00, 0x17fbff00, 0x16fbff00, 675 0x15fbff00, 0x14fb0000, 0x13fa0000, 0x11fa0000, 676 677 0x2811fcff, 0x2810fcff, 0x280ffbff, 0x280efbff, 678 0x270dfb00, 0x270cfb00, 0x270bfb00, 0x260afb00, 679 0x2609fb00, 0x2508fb00, 0x2507fb00, 0x2407fb00, 680 0x2406fc00, 0x2305fc00, 0x2204fc00, 0x2203fc00, 681 0x2103fc00, 0x2002fc00, 0x1f01fd00, 0x1e01fd00, 682 0x1d00fd00, 0x1dfffd00, 0x1cfffd00, 0x1bfefd00, 683 0x1afefe00, 0x19fefe00, 0x18fdfe00, 0x17fdfe00, 684 0x16fdfe00, 0x15fcff00, 0x13fcff00, 0x12fcff00, 685 686 0x2512fdfe, 0x2511fdff, 0x2410fdff, 0x240ffdff, 687 0x240efcff, 0x240dfcff, 0x240dfcff, 0x240cfcff, 688 0x230bfcff, 0x230afc00, 0x2209fc00, 0x2108fc00, 689 0x2108fc00, 0x2007fc00, 0x2006fc00, 0x2005fc00, 690 0x1f05fc00, 0x1e04fc00, 0x1e03fc00, 0x1c03fd00, 691 0x1c02fd00, 0x1b02fd00, 0x1b01fd00, 0x1a00fd00, 692 0x1900fd00, 0x1800fd00, 0x17fffe00, 0x16fffe00, 693 0x16fefe00, 0x14fefe00, 0x13fefe00, 0x13fdfe00, 694 695 0x2212fffe, 0x2211fefe, 0x2211fefe, 0x2110fefe, 696 0x210ffeff, 0x220efdff, 0x210dfdff, 0x210dfdff, 697 0x210cfdff, 0x210bfdff, 0x200afdff, 0x200afdff, 698 0x1f09fdff, 0x1f08fdff, 0x1d08fd00, 0x1c07fd00, 699 0x1d06fd00, 0x1b06fd00, 0x1b05fd00, 0x1c04fd00, 700 0x1b04fd00, 0x1a03fd00, 0x1a03fd00, 0x1902fd00, 701 0x1802fd00, 0x1801fd00, 0x1701fd00, 0x1600fd00, 702 0x1400fe00, 0x1400fe00, 0x14fffe00, 0x13fffe00, 703 704 0x201200fe, 0x201100fe, 0x1f11fffe, 0x2010fffe, 705 0x1f0ffffe, 0x1e0ffffe, 0x1f0efeff, 0x1f0dfeff, 706 0x1f0dfeff, 0x1e0cfeff, 0x1e0bfeff, 0x1d0bfeff, 707 0x1d0afeff, 0x1d09fdff, 0x1d09fdff, 0x1c08fdff, 708 0x1c07fdff, 0x1b07fd00, 0x1b06fd00, 0x1a06fd00, 709 0x1a05fd00, 0x1805fd00, 0x1904fd00, 0x1804fd00, 710 0x1703fd00, 0x1703fd00, 0x1602fe00, 0x1502fe00, 711 0x1501fe00, 0x1401fe00, 0x1301fe00, 0x1300fe00, 712 713 0x1c1202fe, 0x1c1102fe, 0x1b1102fe, 0x1c1001fe, 714 0x1b1001fe, 0x1b0f01ff, 0x1b0e00ff, 0x1b0e00ff, 715 0x1b0d00ff, 0x1a0d00ff, 0x1a0c00ff, 0x1a0cffff, 716 0x1a0bffff, 0x1a0bffff, 0x1a0affff, 0x180affff, 717 0x1909ffff, 0x1809ffff, 0x1808ffff, 0x1808feff, 718 0x1807feff, 0x1707fe00, 0x1606fe00, 0x1506fe00, 719 0x1605fe00, 0x1505fe00, 0x1504fe00, 0x1304fe00, 720 0x1304fe00, 0x1303fe00, 0x1203fe00, 0x1203fe00, 721 722 0x181104ff, 0x191103ff, 0x191003ff, 0x181003ff, 723 0x180f03ff, 0x190f02ff, 0x190e02ff, 0x180e02ff, 724 0x180d02ff, 0x180d01ff, 0x180d01ff, 0x180c01ff, 725 0x180c01ff, 0x180b00ff, 0x170b00ff, 0x170a00ff, 726 0x170a00ff, 0x170900ff, 0x160900ff, 0x160900ff, 727 0x1608ffff, 0x1508ffff, 0x1507ff00, 0x1507ff00, 728 0x1407ff00, 0x1306ff00, 0x1306ff00, 0x1305ff00, 729 0x1205ff00, 0x1105ff00, 0x1204ff00, 0x1104ff00, 730 731 0x171005ff, 0x171005ff, 0x171004ff, 0x170f04ff, 732 0x160f04ff, 0x170f03ff, 0x170e03ff, 0x160e03ff, 733 0x160d03ff, 0x160d02ff, 0x160d02ff, 0x160c02ff, 734 0x160c02ff, 0x160c02ff, 0x160b01ff, 0x150b01ff, 735 0x150a01ff, 0x150a01ff, 0x150a01ff, 0x140901ff, 736 0x14090000, 0x14090000, 0x14080000, 0x13080000, 737 0x13070000, 0x12070000, 0x12070000, 0x12060000, 738 0x11060000, 0x11060000, 0x11050000, 0x1105ff00, 739 740 0x14100600, 0x15100500, 0x150f0500, 0x150f0500, 741 0x140f0500, 0x150e0400, 0x140e0400, 0x130e0400, 742 0x140d0400, 0x150d0300, 0x130d0300, 0x140c0300, 743 0x140c0300, 0x140c0200, 0x140b0200, 0x130b0200, 744 0x120b0200, 0x130a0200, 0x130a0200, 0x130a0100, 745 0x13090100, 0x12090100, 0x11090100, 0x12080100, 746 0x11080100, 0x10080100, 0x11070100, 0x11070000, 747 0x10070000, 0x11060000, 0x10060000, 0x10060000, 748 749 0x140f0600, 0x140f0600, 0x130f0600, 0x140f0500, 750 0x140e0500, 0x130e0500, 0x130e0500, 0x140d0400, 751 0x140d0400, 0x130d0400, 0x120d0400, 0x130c0400, 752 0x130c0300, 0x130c0300, 0x130b0300, 0x130b0300, 753 0x110b0300, 0x130a0200, 0x120a0200, 0x120a0200, 754 0x120a0200, 0x12090200, 0x10090200, 0x11090100, 755 0x11080100, 0x11080100, 0x10080100, 0x10080100, 756 0x10070100, 0x10070100, 0x0f070100, 0x10060100, 757 758 0x120f0701, 0x130f0601, 0x130e0601, 0x130e0601, 759 0x120e0601, 0x130e0501, 0x130e0500, 0x130d0500, 760 0x120d0500, 0x120d0500, 0x130c0400, 0x130c0400, 761 0x120c0400, 0x110c0400, 0x120b0400, 0x120b0300, 762 0x120b0300, 0x120b0300, 0x120a0300, 0x110a0300, 763 0x110a0200, 0x11090200, 0x11090200, 0x10090200, 764 0x10090200, 0x10080200, 0x10080200, 0x10080100, 765 0x0f080100, 0x10070100, 0x0f070100, 0x0f070100 766 }; 767 768 static const uint32_t lan3coefftab32_right[512] = { 769 0x00000000, 0x00000002, 0x0000ff04, 0x0000ff06, 770 0x0000fe08, 0x0000fd0a, 0x0000fd0c, 0x0000fc0f, 771 0x0000fc12, 0x0001fb14, 0x0001fa17, 0x0001fa19, 772 0x0001f91c, 0x0001f91f, 0x0001f822, 0x0001f824, 773 0x0002f727, 0x0002f72a, 0x0002f72c, 0x0002f72f, 774 0x0002f731, 0x0002f733, 0x0002f735, 0x0002f737, 775 0x0002f73a, 0x0002f83b, 0x0002f93c, 0x0002fa3d, 776 0x0001fb3e, 0x0001fc3f, 0x0001fd40, 0x0000fe40, 777 778 0x00000000, 0x00000002, 0x0000ff04, 0x0000ff06, 779 0x0000fe08, 0x0000fd0a, 0x0000fd0c, 0x0000fc0f, 780 0x0000fc12, 0x0001fb14, 0x0001fa17, 0x0001fa19, 781 0x0001f91c, 0x0001f91f, 0x0001f822, 0x0001f824, 782 0x0002f727, 0x0002f72a, 0x0002f72c, 0x0002f72f, 783 0x0002f731, 0x0002f733, 0x0002f735, 0x0002f737, 784 0x0002f73a, 0x0002f83b, 0x0002f93c, 0x0002fa3d, 785 0x0001fb3e, 0x0001fc3f, 0x0001fd40, 0x0000fe40, 786 787 0x0002fc06, 0x0002fb08, 0x0002fb0a, 0x0002fa0c, 788 0x0002fa0e, 0x0003f910, 0x0003f912, 0x0003f814, 789 0x0003f816, 0x0003f719, 0x0003f71a, 0x0003f71d, 790 0x0003f71f, 0x0003f721, 0x0003f723, 0x0003f725, 791 0x0002f727, 0x0002f729, 0x0002f72b, 0x0002f82d, 792 0x0002f82e, 0x0001f930, 0x0001fa31, 0x0000fa34, 793 0x0000fb34, 0x0100fc35, 0x01fffd36, 0x01ffff37, 794 0x01fe0037, 0x01fe0138, 0x01fd0338, 0x02fc0538, 795 796 0x0002fa0b, 0x0002fa0c, 0x0002f90e, 0x0002f910, 797 0x0002f911, 0x0002f813, 0x0002f816, 0x0002f817, 798 0x0002f818, 0x0002f81a, 0x0001f81c, 0x0001f81e, 799 0x0001f820, 0x0001f921, 0x0001f923, 0x0000f925, 800 0x0000fa26, 0x0100fa28, 0x01fffb29, 0x01fffc2a, 801 0x01fffc2c, 0x01fefd2d, 0x01fefe2e, 0x01fdff2f, 802 0x01fd0030, 0x01fd0130, 0x01fc0232, 0x02fc0432, 803 0x02fb0532, 0x02fb0633, 0x02fb0833, 0x02fa0933, 804 805 0x0001fa0e, 0x0001f90f, 0x0001f911, 0x0001f913, 806 0x0001f914, 0x0001f915, 0x0000f918, 0x0000fa18, 807 0x0000fa1a, 0x0000fa1b, 0x0000fa1d, 0x00fffb1e, 808 0x01fffb1f, 0x01fffb20, 0x01fffc22, 0x01fefc23, 809 0x01fefd24, 0x01fefe25, 0x01fdfe27, 0x01fdff28, 810 0x01fd0029, 0x01fc012a, 0x01fc022b, 0x01fc032b, 811 0x01fb042d, 0x01fb052d, 0x01fb062e, 0x01fb072e, 812 0x01fa092e, 0x01fa0a2f, 0x01fa0b2f, 0x01fa0d2f, 813 814 0x0000fa11, 0x0000fa12, 0x0000fa13, 0x0000fb14, 815 0x00fffb16, 0x00fffb16, 0x00fffb17, 0x00fffb19, 816 0x00fffc1a, 0x00fefc1c, 0x00fefd1c, 0x01fefd1d, 817 0x01fefe1e, 0x01fdfe20, 0x01fdff21, 0x01fdff22, 818 0x01fd0023, 0x01fc0124, 0x01fc0124, 0x01fc0225, 819 0x01fc0326, 0x01fc0427, 0x01fb0528, 0x01fb0629, 820 0x01fb0729, 0x01fb0829, 0x01fb092a, 0x01fb0a2a, 821 0x00fa0b2c, 0x00fa0c2b, 0x00fa0e2b, 0x00fa0f2c, 822 823 0x00fffc11, 0x00fffc12, 0x00fffc14, 0x00fffc15, 824 0x00fefd16, 0x00fefd17, 0x00fefd18, 0x00fefe19, 825 0x00fefe1a, 0x00fdfe1d, 0x00fdff1d, 0x00fdff1e, 826 0x00fd001d, 0x00fd011e, 0x00fd0120, 0x00fc0221, 827 0x00fc0321, 0x00fc0323, 0x00fc0423, 0x00fc0523, 828 0x00fc0624, 0x00fb0725, 0x00fb0726, 0x00fb0827, 829 0x00fb0926, 0x00fb0a26, 0x00fb0b27, 0x00fb0c27, 830 0x00fb0d27, 0xfffb0e28, 0xfffb0f29, 0xfffc1028, 831 832 0x00fefd13, 0x00fefd13, 0x00fefe14, 0x00fefe15, 833 0x00fefe17, 0x00feff17, 0x00feff17, 0x00fd0018, 834 0x00fd001a, 0x00fd001a, 0x00fd011b, 0x00fd021c, 835 0x00fd021c, 0x00fd031d, 0x00fc031f, 0x00fc041f, 836 0x00fc051f, 0x00fc0521, 0x00fc0621, 0x00fc0721, 837 0x00fc0821, 0x00fc0822, 0x00fc0922, 0x00fc0a23, 838 0xfffc0b24, 0xfffc0c24, 0xfffc0d24, 0xfffc0d25, 839 0xfffc0e25, 0xfffd0f25, 0xfffd1025, 0xfffd1125, 840 841 0x00feff12, 0x00feff14, 0x00feff14, 0x00fe0015, 842 0x00fe0015, 0x00fd0017, 0x00fd0118, 0x00fd0118, 843 0x00fd0218, 0x00fd0219, 0x00fd031a, 0x00fd031a, 844 0x00fd041b, 0x00fd041c, 0x00fd051c, 0x00fd061d, 845 0x00fd061d, 0x00fd071e, 0x00fd081e, 0xfffd081f, 846 0xfffd091f, 0xfffd0a20, 0xfffd0a20, 0xfffd0b21, 847 0xfffd0c21, 0xfffd0d21, 0xfffd0d22, 0xfffd0e23, 848 0xfffe0f22, 0xfefe1022, 0xfefe1122, 0xfefe1123, 849 850 0x00fe0012, 0x00fe0013, 0x00fe0114, 0x00fe0114, 851 0x00fe0116, 0x00fe0216, 0x00fe0216, 0x00fd0317, 852 0x00fd0317, 0x00fd0418, 0x00fd0419, 0x00fd0519, 853 0x00fd051a, 0x00fd061b, 0x00fd061b, 0x00fd071c, 854 0xfffd071e, 0xfffd081d, 0xfffd091d, 0xfffd091e, 855 0xfffe0a1d, 0xfffe0b1e, 0xfffe0b1e, 0xfffe0c1e, 856 0xfffe0d1f, 0xfffe0d1f, 0xfffe0e1f, 0xfeff0f1f, 857 0xfeff0f20, 0xfeff1020, 0xfeff1120, 0xfe001120, 858 859 0x00fe0212, 0x00fe0312, 0x00fe0313, 0x00fe0314, 860 0x00fe0414, 0x00fe0414, 0x00fe0416, 0x00fe0515, 861 0x00fe0516, 0x00fe0616, 0x00fe0617, 0x00fe0717, 862 0xfffe0719, 0xfffe0818, 0xffff0818, 0xffff0919, 863 0xffff0919, 0xffff0a19, 0xffff0a1a, 0xffff0b1a, 864 0xffff0b1b, 0xffff0c1a, 0xff000c1b, 0xff000d1b, 865 0xff000d1b, 0xff000e1b, 0xff000e1c, 0xff010f1c, 866 0xfe01101c, 0xfe01101d, 0xfe02111c, 0xfe02111c, 867 868 0x00ff0411, 0x00ff0411, 0x00ff0412, 0x00ff0512, 869 0x00ff0513, 0x00ff0513, 0x00ff0613, 0x00ff0614, 870 0x00ff0714, 0x00ff0715, 0x00ff0715, 0xffff0816, 871 0xffff0816, 0xff000916, 0xff000917, 0xff000918, 872 0xff000a17, 0xff000a18, 0xff000b18, 0xff000b18, 873 0xff010c18, 0xff010c19, 0xff010d18, 0xff010d18, 874 0xff020d18, 0xff020e19, 0xff020e19, 0xff020f19, 875 0xff030f19, 0xff031019, 0xff031019, 0xff031119, 876 877 0x00ff0511, 0x00ff0511, 0x00000511, 0x00000611, 878 0x00000612, 0x00000612, 0x00000712, 0x00000713, 879 0x00000714, 0x00000814, 0x00000814, 0x00000914, 880 0x00000914, 0xff010914, 0xff010a15, 0xff010a16, 881 0xff010a17, 0xff010b16, 0xff010b16, 0xff020c16, 882 0xff020c16, 0xff020c16, 0xff020d16, 0xff020d17, 883 0xff030d17, 0xff030e17, 0xff030e17, 0xff030f17, 884 0xff040f17, 0xff040f17, 0xff041017, 0xff051017, 885 886 0x00000610, 0x00000610, 0x00000611, 0x00000611, 887 0x00000711, 0x00000712, 0x00010712, 0x00010812, 888 0x00010812, 0x00010812, 0x00010913, 0x00010913, 889 0x00010913, 0x00010a13, 0x00020a13, 0x00020a14, 890 0x00020b14, 0x00020b14, 0x00020b14, 0x00020c14, 891 0x00030c14, 0x00030c15, 0x00030d15, 0x00030d15, 892 0x00040d15, 0x00040e15, 0x00040e15, 0x00040e16, 893 0x00050f15, 0x00050f15, 0x00050f16, 0x00051015, 894 895 0x00000611, 0x00010610, 0x00010710, 0x00010710, 896 0x00010711, 0x00010811, 0x00010811, 0x00010812, 897 0x00010812, 0x00010912, 0x00020912, 0x00020912, 898 0x00020a12, 0x00020a12, 0x00020a13, 0x00020a13, 899 0x00030b13, 0x00030b13, 0x00030b14, 0x00030c13, 900 0x00030c13, 0x00040c13, 0x00040d14, 0x00040d14, 901 0x00040d15, 0x00040d15, 0x00050e14, 0x00050e14, 902 0x00050e15, 0x00050f14, 0x00060f14, 0x00060f14, 903 904 0x0001070f, 0x0001070f, 0x00010710, 0x00010710, 905 0x00010810, 0x00010810, 0x00020810, 0x00020811, 906 0x00020911, 0x00020911, 0x00020912, 0x00020912, 907 0x00020a12, 0x00030a12, 0x00030a12, 0x00030b12, 908 0x00030b12, 0x00030b12, 0x00040b12, 0x00040c12, 909 0x00040c13, 0x00040c14, 0x00040c14, 0x00050d13, 910 0x00050d13, 0x00050d14, 0x00050e13, 0x01050e13, 911 0x01060e13, 0x01060e13, 0x01060e14, 0x01060f13 912 }; 913 914 static const uint32_t lan2coefftab32[512] = { 915 0x00004000, 0x000140ff, 0x00033ffe, 0x00043ffd, 0x00063efc, 0xff083dfc, 0x000a3bfb, 0xff0d39fb, 916 0xff0f37fb, 0xff1136fa, 0xfe1433fb, 0xfe1631fb, 0xfd192ffb, 0xfd1c2cfb, 0xfd1f29fb, 0xfc2127fc, 917 0xfc2424fc, 0xfc2721fc, 0xfb291ffd, 0xfb2c1cfd, 0xfb2f19fd, 0xfb3116fe, 0xfb3314fe, 0xfa3611ff, 918 0xfb370fff, 0xfb390dff, 0xfb3b0a00, 0xfc3d08ff, 0xfc3e0600, 0xfd3f0400, 0xfe3f0300, 0xff400100, 919 920 0x00004000, 0x000140ff, 0x00033ffe, 0x00043ffd, 0x00063efc, 0xff083dfc, 0x000a3bfb, 0xff0d39fb, 921 0xff0f37fb, 0xff1136fa, 0xfe1433fb, 0xfe1631fb, 0xfd192ffb, 0xfd1c2cfb, 0xfd1f29fb, 0xfc2127fc, 922 0xfc2424fc, 0xfc2721fc, 0xfb291ffd, 0xfb2c1cfd, 0xfb2f19fd, 0xfb3116fe, 0xfb3314fe, 0xfa3611ff, 923 0xfb370fff, 0xfb390dff, 0xfb3b0a00, 0xfc3d08ff, 0xfc3e0600, 0xfd3f0400, 0xfe3f0300, 0xff400100, 924 925 0xff053804, 0xff063803, 0xff083801, 0xff093701, 0xff0a3700, 0xff0c3500, 0xff0e34ff, 0xff1033fe, 926 0xff1232fd, 0xfe1431fd, 0xfe162ffd, 0xfe182dfd, 0xfd1b2cfc, 0xfd1d2afc, 0xfd1f28fc, 0xfd2126fc, 927 0xfd2323fd, 0xfc2621fd, 0xfc281ffd, 0xfc2a1dfd, 0xfc2c1bfd, 0xfd2d18fe, 0xfd2f16fe, 0xfd3114fe, 928 0xfd3212ff, 0xfe3310ff, 0xff340eff, 0x00350cff, 0x00360a00, 0x01360900, 0x02370700, 0x03370600, 929 930 0xff083207, 0xff093206, 0xff0a3205, 0xff0c3203, 0xff0d3103, 0xff0e3102, 0xfe113001, 0xfe132f00, 931 0xfe142e00, 0xfe162dff, 0xfe182bff, 0xfe192aff, 0xfe1b29fe, 0xfe1d27fe, 0xfe1f25fe, 0xfd2124fe, 932 0xfe2222fe, 0xfe2421fd, 0xfe251ffe, 0xfe271dfe, 0xfe291bfe, 0xff2a19fe, 0xff2b18fe, 0xff2d16fe, 933 0x002e14fe, 0x002f12ff, 0x013010ff, 0x02300fff, 0x03310dff, 0x04310cff, 0x05310a00, 0x06310900, 934 935 0xff0a2e09, 0xff0b2e08, 0xff0c2e07, 0xff0e2d06, 0xff0f2d05, 0xff102d04, 0xff122c03, 0xfe142c02, 936 0xfe152b02, 0xfe172a01, 0xfe182901, 0xfe1a2800, 0xfe1b2700, 0xfe1d2500, 0xff1e24ff, 0xfe2023ff, 937 0xff2121ff, 0xff2320fe, 0xff241eff, 0x00251dfe, 0x00261bff, 0x00281afe, 0x012818ff, 0x012a16ff, 938 0x022a15ff, 0x032b13ff, 0x032c12ff, 0x052c10ff, 0x052d0fff, 0x062d0d00, 0x072d0c00, 0x082d0b00, 939 940 0xff0c2a0b, 0xff0d2a0a, 0xff0e2a09, 0xff0f2a08, 0xff102a07, 0xff112a06, 0xff132905, 0xff142904, 941 0xff162803, 0xff172703, 0xff182702, 0xff1a2601, 0xff1b2501, 0xff1c2401, 0xff1e2300, 0xff1f2200, 942 0x00202000, 0x00211f00, 0x01221d00, 0x01231c00, 0x01251bff, 0x02251aff, 0x032618ff, 0x032717ff, 943 0x042815ff, 0x052814ff, 0x052913ff, 0x06291100, 0x072a10ff, 0x082a0e00, 0x092a0d00, 0x0a2a0c00, 944 945 0xff0d280c, 0xff0e280b, 0xff0f280a, 0xff102809, 0xff112808, 0xff122708, 0xff142706, 0xff152705, 946 0xff162605, 0xff172604, 0xff192503, 0xff1a2403, 0x001b2302, 0x001c2202, 0x001d2201, 0x001e2101, 947 0x011f1f01, 0x01211e00, 0x01221d00, 0x02221c00, 0x02231b00, 0x03241900, 0x04241800, 0x04251700, 948 0x052616ff, 0x06261400, 0x072713ff, 0x08271100, 0x08271100, 0x09271000, 0x0a280e00, 0x0b280d00, 949 950 0xff0e260d, 0xff0f260c, 0xff10260b, 0xff11260a, 0xff122609, 0xff132608, 0xff142508, 0xff152507, 951 0x00152506, 0x00172405, 0x00182305, 0x00192304, 0x001b2203, 0x001c2103, 0x011d2002, 0x011d2002, 952 0x011f1f01, 0x021f1e01, 0x02201d01, 0x03211c00, 0x03221b00, 0x04221a00, 0x04231801, 0x05241700, 953 0x06241600, 0x07241500, 0x08251300, 0x09251200, 0x09261100, 0x0a261000, 0x0b260f00, 0x0c260e00, 954 955 0xff0e250e, 0xff0f250d, 0xff10250c, 0xff11250b, 0x0011250a, 0x00132409, 0x00142408, 0x00152407, 956 0x00162307, 0x00172306, 0x00182206, 0x00192205, 0x011a2104, 0x011b2004, 0x011c2003, 0x021c1f03, 957 0x021e1e02, 0x031e1d02, 0x03201c01, 0x04201b01, 0x04211a01, 0x05221900, 0x05221801, 0x06231700, 958 0x07231600, 0x07241500, 0x08241400, 0x09241300, 0x0a241200, 0x0b241100, 0x0c241000, 0x0d240f00, 959 960 0x000e240e, 0x000f240d, 0x0010240c, 0x0011240b, 0x0013230a, 0x0013230a, 0x00142309, 0x00152308, 961 0x00162208, 0x00172207, 0x01182106, 0x01192105, 0x011a2005, 0x021b1f04, 0x021b1f04, 0x021d1e03, 962 0x031d1d03, 0x031e1d02, 0x041e1c02, 0x041f1b02, 0x05201a01, 0x05211901, 0x06211801, 0x07221700, 963 0x07221601, 0x08231500, 0x09231400, 0x0a231300, 0x0a231300, 0x0b231200, 0x0c231100, 0x0d231000, 964 965 0x000f220f, 0x0010220e, 0x0011220d, 0x0012220c, 0x0013220b, 0x0013220b, 0x0015210a, 0x0015210a, 966 0x01162108, 0x01172008, 0x01182007, 0x02191f06, 0x02191f06, 0x021a1e06, 0x031a1e05, 0x031c1d04, 967 0x041c1c04, 0x041d1c03, 0x051d1b03, 0x051e1a03, 0x061f1902, 0x061f1902, 0x07201801, 0x08201701, 968 0x08211601, 0x09211501, 0x0a211500, 0x0b211400, 0x0b221300, 0x0c221200, 0x0d221100, 0x0e221000, 969 970 0x0010210f, 0x0011210e, 0x0011210e, 0x0012210d, 0x0013210c, 0x0014200c, 0x0114200b, 0x0115200a, 971 0x01161f0a, 0x01171f09, 0x02171f08, 0x02181e08, 0x03181e07, 0x031a1d06, 0x031a1d06, 0x041b1c05, 972 0x041c1c04, 0x051c1b04, 0x051d1a04, 0x061d1a03, 0x071d1903, 0x071e1803, 0x081e1802, 0x081f1702, 973 0x091f1602, 0x0a201501, 0x0b1f1501, 0x0b201401, 0x0c211300, 0x0d211200, 0x0e201200, 0x0e211100, 974 975 0x00102010, 0x0011200f, 0x0012200e, 0x0013200d, 0x0013200d, 0x01141f0c, 0x01151f0b, 0x01151f0b, 976 0x01161f0a, 0x02171e09, 0x02171e09, 0x03181d08, 0x03191d07, 0x03191d07, 0x041a1c06, 0x041b1c05, 977 0x051b1b05, 0x051c1b04, 0x061c1a04, 0x071d1903, 0x071d1903, 0x081d1803, 0x081e1703, 0x091e1702, 978 0x0a1f1601, 0x0a1f1502, 0x0b1f1501, 0x0c1f1401, 0x0d201300, 0x0d201300, 0x0e201200, 0x0f201100, 979 980 0x00102010, 0x0011200f, 0x00121f0f, 0x00131f0e, 0x00141f0d, 0x01141f0c, 0x01141f0c, 0x01151e0c, 981 0x02161e0a, 0x02171e09, 0x03171d09, 0x03181d08, 0x03181d08, 0x04191c07, 0x041a1c06, 0x051a1b06, 982 0x051b1b05, 0x061b1a05, 0x061c1a04, 0x071c1904, 0x081c1903, 0x081d1803, 0x091d1703, 0x091e1702, 983 0x0a1e1602, 0x0b1e1502, 0x0c1e1501, 0x0c1f1401, 0x0d1f1400, 0x0e1f1300, 0x0e1f1201, 0x0f1f1200, 984 985 0x00111e11, 0x00121e10, 0x00131e0f, 0x00131e0f, 0x01131e0e, 0x01141d0e, 0x02151d0c, 0x02151d0c, 986 0x02161d0b, 0x03161c0b, 0x03171c0a, 0x04171c09, 0x04181b09, 0x05181b08, 0x05191b07, 0x06191a07, 987 0x061a1a06, 0x071a1906, 0x071b1905, 0x081b1805, 0x091b1804, 0x091c1704, 0x0a1c1703, 0x0a1c1604, 988 0x0b1d1602, 0x0c1d1502, 0x0c1d1502, 0x0d1d1402, 0x0e1d1401, 0x0e1e1301, 0x0f1e1300, 0x101e1200, 989 990 0x00111e11, 0x00121e10, 0x00131d10, 0x01131d0f, 0x01141d0e, 0x01141d0e, 0x02151c0d, 0x02151c0d, 991 0x03161c0b, 0x03161c0b, 0x04171b0a, 0x04171b0a, 0x05171b09, 0x05181a09, 0x06181a08, 0x06191a07, 992 0x07191907, 0x071a1906, 0x081a1806, 0x081a1806, 0x091a1805, 0x0a1b1704, 0x0a1b1704, 0x0b1c1603, 993 0x0b1c1603, 0x0c1c1503, 0x0d1c1502, 0x0d1d1402, 0x0e1d1401, 0x0f1d1301, 0x0f1d1301, 0x101e1200, 994 }; 995 996 static void 997 sunxi_mixer_vsu_init(struct sunxi_mixer_softc *sc, u_int src_w, u_int src_h, 998 u_int crtc_w, u_int crtc_h, uint32_t pixel_format) 999 { 1000 const u_int hstep = (src_w << 16) / crtc_w; 1001 const u_int vstep = (src_h << 16) / crtc_h; 1002 1003 const int hsub = drm_format_horz_chroma_subsampling(pixel_format); 1004 const int vsub = drm_format_vert_chroma_subsampling(pixel_format); 1005 1006 const u_int src_cw = src_w / hsub; 1007 const u_int src_ch = src_h / vsub; 1008 1009 VSU_WRITE(sc, VS_OUT_SIZE_REG, ((crtc_h - 1) << 16) | (crtc_w - 1)); 1010 VSU_WRITE(sc, VS_Y_SIZE_REG, ((src_h - 1) << 16) | (src_w - 1)); 1011 VSU_WRITE(sc, VS_Y_HSTEP_REG, hstep << 4); 1012 VSU_WRITE(sc, VS_Y_VSTEP_REG, vstep << 4); 1013 VSU_WRITE(sc, VS_Y_HPHASE_REG, 0); 1014 VSU_WRITE(sc, VS_Y_VPHASE0_REG, 0); 1015 VSU_WRITE(sc, VS_Y_VPHASE1_REG, 0); 1016 VSU_WRITE(sc, VS_C_SIZE_REG, ((src_ch - 1) << 16) | (src_cw - 1)); 1017 VSU_WRITE(sc, VS_C_HSTEP_REG, (hstep / hsub) << 4); 1018 VSU_WRITE(sc, VS_C_VSTEP_REG, (vstep / vsub) << 4); 1019 VSU_WRITE(sc, VS_C_HPHASE_REG, 0); 1020 VSU_WRITE(sc, VS_C_VPHASE0_REG, 0); 1021 VSU_WRITE(sc, VS_C_VPHASE1_REG, 0); 1022 1023 /* XXX */ 1024 const u_int coef_base = 0; 1025 1026 for (int i = 0; i < 32; i++) { 1027 VSU_WRITE(sc, VS_Y_HCOEF0_REG(i), lan3coefftab32_left[coef_base + i]); 1028 VSU_WRITE(sc, VS_Y_HCOEF1_REG(i), lan3coefftab32_right[coef_base + i]); 1029 VSU_WRITE(sc, VS_Y_VCOEF_REG(i), lan2coefftab32[coef_base + i]); 1030 VSU_WRITE(sc, VS_C_HCOEF0_REG(i), lan3coefftab32_left[coef_base + i]); 1031 VSU_WRITE(sc, VS_C_HCOEF1_REG(i), lan3coefftab32_right[coef_base + i]); 1032 VSU_WRITE(sc, VS_C_VCOEF_REG(i), lan2coefftab32[coef_base + i]); 1033 } 1034 1035 /* Commit settings and enable scaler */ 1036 VSU_WRITE(sc, VS_CTRL_REG, VS_CTRL_COEF_SWITCH_EN | VS_CTRL_EN); 1037 } 1038 1039 static const u32 yuv2rgb[] = { 1040 0x000004A8, 0x00000000, 0x00000662, 0xFFFC865A, 1041 0x000004A8, 0xFFFFFE6F, 0xFFFFFCBF, 0x00021FF4, 1042 0x000004A8, 0x00000813, 0x00000000, 0xFFFBAE4A, 1043 }; 1044 1045 static void 1046 sunxi_mixer_csc_init(struct sunxi_mixer_softc *sc, uint32_t pixel_format) 1047 { 1048 const u_int crtc_index = drm_crtc_index(&sc->sc_crtc.base); 1049 1050 for (int i = 0; i < __arraycount(yuv2rgb); i++) 1051 CSC_WRITE(sc, crtc_index, CSC_COEFF0_REG(0) + i * 4, yuv2rgb[i]); 1052 1053 CSC_WRITE(sc, crtc_index, CSC_BYPASS_REG, CSC_BYPASS_DISABLE); 1054 } 1055 1056 static void 1057 sunxi_mixer_csc_disable(struct sunxi_mixer_softc *sc) 1058 { 1059 const u_int crtc_index = drm_crtc_index(&sc->sc_crtc.base); 1060 1061 CSC_WRITE(sc, crtc_index, CSC_BYPASS_REG, 0); 1062 } 1063 1064 static int 1065 sunxi_mixer_overlay_update_plane(struct drm_plane *plane, struct drm_crtc *crtc, 1066 struct drm_framebuffer *fb, int crtc_x, int crtc_y, u_int crtc_w, u_int crtc_h, 1067 uint32_t src_x, uint32_t src_y, uint32_t src_w, uint32_t src_h) 1068 { 1069 struct sunxi_mixer_plane *overlay = to_sunxi_mixer_plane(plane); 1070 struct sunxi_mixer_softc * const sc = overlay->sc; 1071 struct sunxi_drm_framebuffer *sfb = to_sunxi_drm_framebuffer(fb); 1072 uint32_t val; 1073 1074 const u_int fbfmt = sunxi_mixer_overlay_format(fb->pixel_format); 1075 const uint64_t paddr = (uint64_t)sfb->obj->dmamap->dm_segs[0].ds_addr; 1076 1077 const uint32_t input_size = (((src_h >> 16) - 1) << 16) | ((src_w >> 16) - 1); 1078 const uint32_t input_pos = ((src_y >> 16) << 16) | (src_x >> 16); 1079 1080 OVL_V_WRITE(sc, OVL_V_MBSIZE(0), input_size); 1081 OVL_V_WRITE(sc, OVL_V_COOR(0), input_pos); 1082 1083 /* Note: DRM and hardware's ideas of pitch 1 and 2 are swapped */ 1084 1085 OVL_V_WRITE(sc, OVL_V_PITCH0(0), fb->pitches[0]); 1086 OVL_V_WRITE(sc, OVL_V_PITCH1(0), fb->pitches[2]); 1087 OVL_V_WRITE(sc, OVL_V_PITCH2(0), fb->pitches[1]); 1088 1089 const uint64_t paddr0 = paddr + fb->offsets[0] + 1090 (src_x >> 16) * drm_format_plane_cpp(fb->pixel_format, 0) + 1091 (src_y >> 16) * fb->pitches[0]; 1092 const uint64_t paddr1 = paddr + fb->offsets[2] + 1093 (src_x >> 16) * drm_format_plane_cpp(fb->pixel_format, 2) + 1094 (src_y >> 16) * fb->pitches[2]; 1095 const uint64_t paddr2 = paddr + fb->offsets[1] + 1096 (src_x >> 16) * drm_format_plane_cpp(fb->pixel_format, 1) + 1097 (src_y >> 16) * fb->pitches[1]; 1098 1099 OVL_V_WRITE(sc, OVL_V_TOP_HADD0, (paddr0 >> 32) & OVL_V_TOP_HADD_LAYER0); 1100 OVL_V_WRITE(sc, OVL_V_TOP_HADD1, (paddr1 >> 32) & OVL_V_TOP_HADD_LAYER0); 1101 OVL_V_WRITE(sc, OVL_V_TOP_HADD2, (paddr2 >> 32) & OVL_V_TOP_HADD_LAYER0); 1102 1103 OVL_V_WRITE(sc, OVL_V_TOP_LADD0(0), paddr0 & 0xffffffff); 1104 OVL_V_WRITE(sc, OVL_V_TOP_LADD1(0), paddr1 & 0xffffffff); 1105 OVL_V_WRITE(sc, OVL_V_TOP_LADD2(0), paddr2 & 0xffffffff); 1106 1107 OVL_V_WRITE(sc, OVL_V_SIZE, input_size); 1108 1109 val = OVL_V_ATTCTL_LAY0_EN; 1110 val |= __SHIFTIN(fbfmt, OVL_V_ATTCTL_LAY_FBFMT); 1111 if (sunxi_mixer_overlay_rgb(fb->pixel_format) == true) 1112 val |= OVL_V_ATTCTL_VIDEO_UI_SEL; 1113 OVL_V_WRITE(sc, OVL_V_ATTCTL(0), val); 1114 1115 /* Enable video scaler */ 1116 sunxi_mixer_vsu_init(sc, src_w >> 16, src_h >> 16, crtc_w, crtc_h, fb->pixel_format); 1117 1118 /* Enable colour space conversion for non-RGB formats */ 1119 if (sunxi_mixer_overlay_rgb(fb->pixel_format) == false) 1120 sunxi_mixer_csc_init(sc, fb->pixel_format); 1121 else 1122 sunxi_mixer_csc_disable(sc); 1123 1124 /* Set blender 1 input size */ 1125 BLD_WRITE(sc, BLD_CH_ISIZE(1), ((crtc_h - 1) << 16) | (crtc_w - 1)); 1126 /* Set blender 1 offset */ 1127 BLD_WRITE(sc, BLD_CH_OFFSET(1), (crtc_y << 16) | crtc_x); 1128 /* Route channel 0 to pipe 1 */ 1129 val = BLD_READ(sc, BLD_CH_RTCTL); 1130 val &= ~BLD_CH_RTCTL_P1; 1131 val |= __SHIFTIN(0, BLD_CH_RTCTL_P1); 1132 BLD_WRITE(sc, BLD_CH_RTCTL, val); 1133 1134 /* Enable pipe 1 */ 1135 val = BLD_READ(sc, BLD_FILL_COLOR_CTL); 1136 val |= BLD_FILL_COLOR_CTL_P1_EN; 1137 BLD_WRITE(sc, BLD_FILL_COLOR_CTL, val); 1138 1139 /* Commit settings */ 1140 GLB_WRITE(sc, GLB_DBUFFER, GLB_DBUFFER_DOUBLE_BUFFER_RDY); 1141 1142 return 0; 1143 } 1144 1145 static int 1146 sunxi_mixer_overlay_disable_plane(struct drm_plane *plane) 1147 { 1148 struct sunxi_mixer_plane *overlay = to_sunxi_mixer_plane(plane); 1149 struct sunxi_mixer_softc * const sc = overlay->sc; 1150 uint32_t val; 1151 1152 sunxi_mixer_csc_disable(sc); 1153 1154 val = BLD_READ(sc, BLD_FILL_COLOR_CTL); 1155 val &= ~BLD_FILL_COLOR_CTL_P1_EN; 1156 BLD_WRITE(sc, BLD_FILL_COLOR_CTL, val); 1157 1158 /* Commit settings */ 1159 GLB_WRITE(sc, GLB_DBUFFER, GLB_DBUFFER_DOUBLE_BUFFER_RDY); 1160 1161 return 0; 1162 } 1163 1164 static const struct drm_plane_funcs sunxi_mixer_overlay_funcs = { 1165 .update_plane = sunxi_mixer_overlay_update_plane, 1166 .disable_plane = sunxi_mixer_overlay_disable_plane, 1167 .destroy = sunxi_mixer_overlay_destroy, 1168 }; 1169 1170 static uint32_t sunxi_mixer_overlay_formats[] = { 1171 DRM_FORMAT_ARGB8888, 1172 DRM_FORMAT_XRGB8888, 1173 #if notyet 1174 DRM_FORMAT_VYUY, 1175 DRM_FORMAT_YVYU, 1176 DRM_FORMAT_UYVY, 1177 DRM_FORMAT_YUYV, 1178 #endif 1179 DRM_FORMAT_YUV422, 1180 DRM_FORMAT_YUV420, 1181 DRM_FORMAT_YUV411, 1182 }; 1183 1184 static int 1185 sunxi_mixer_ep_activate(device_t dev, struct fdt_endpoint *ep, bool activate) 1186 { 1187 struct sunxi_mixer_softc * const sc = device_private(dev); 1188 struct drm_device *ddev; 1189 bus_size_t reg; 1190 1191 if (!activate) 1192 return EINVAL; 1193 1194 ddev = sunxi_drm_endpoint_device(ep); 1195 if (ddev == NULL) { 1196 DRM_ERROR("couldn't find DRM device\n"); 1197 return ENXIO; 1198 } 1199 1200 sc->sc_crtc.sc = sc; 1201 sc->sc_overlay.sc = sc; 1202 1203 /* Initialize registers */ 1204 for (reg = 0; reg < 0xc000; reg += 4) 1205 bus_space_write_4(sc->sc_bst, sc->sc_bsh, reg, 0); 1206 BLD_WRITE(sc, BLD_CTL(0), 0x03010301); 1207 BLD_WRITE(sc, BLD_CTL(1), 0x03010301); 1208 BLD_WRITE(sc, BLD_CTL(2), 0x03010301); 1209 BLD_WRITE(sc, BLD_CTL(3), 0x03010301); 1210 1211 if (sc->sc_ovl_ui_count > 1) 1212 drm_crtc_init(ddev, &sc->sc_crtc.base, &sunxi_mixer0_crtc_funcs); 1213 else 1214 drm_crtc_init(ddev, &sc->sc_crtc.base, &sunxi_mixer1_crtc_funcs); 1215 drm_crtc_helper_add(&sc->sc_crtc.base, &sunxi_mixer_crtc_helper_funcs); 1216 1217 drm_universal_plane_init(ddev, &sc->sc_overlay.base, 1218 1 << drm_crtc_index(&sc->sc_crtc.base), &sunxi_mixer_overlay_funcs, 1219 sunxi_mixer_overlay_formats, __arraycount(sunxi_mixer_overlay_formats), 1220 DRM_PLANE_TYPE_OVERLAY); 1221 1222 return fdt_endpoint_activate(ep, activate); 1223 } 1224 1225 static void * 1226 sunxi_mixer_ep_get_data(device_t dev, struct fdt_endpoint *ep) 1227 { 1228 struct sunxi_mixer_softc * const sc = device_private(dev); 1229 1230 return &sc->sc_crtc; 1231 } 1232 1233 static int 1234 sunxi_mixer_match(device_t parent, cfdata_t cf, void *aux) 1235 { 1236 struct fdt_attach_args * const faa = aux; 1237 1238 return of_match_compat_data(faa->faa_phandle, compat_data); 1239 } 1240 1241 static void 1242 sunxi_mixer_attach(device_t parent, device_t self, void *aux) 1243 { 1244 struct sunxi_mixer_softc * const sc = device_private(self); 1245 struct fdt_attach_args * const faa = aux; 1246 struct fdt_endpoint *out_ep; 1247 const int phandle = faa->faa_phandle; 1248 const struct sunxi_mixer_compat_data * const cd = 1249 (const void *)of_search_compatible(phandle, compat_data)->data; 1250 struct clk *clk_bus, *clk_mod; 1251 struct fdtbus_reset *rst; 1252 bus_addr_t addr; 1253 bus_size_t size; 1254 1255 if (fdtbus_get_reg(phandle, 0, &addr, &size) != 0) { 1256 aprint_error(": couldn't get registers\n"); 1257 return; 1258 } 1259 1260 rst = fdtbus_reset_get_index(phandle, 0); 1261 if (rst == NULL || fdtbus_reset_deassert(rst) != 0) { 1262 aprint_error(": couldn't de-assert reset\n"); 1263 return; 1264 } 1265 1266 clk_bus = fdtbus_clock_get(phandle, "bus"); 1267 if (clk_bus == NULL || clk_enable(clk_bus) != 0) { 1268 aprint_error(": couldn't enable bus clock\n"); 1269 return; 1270 } 1271 1272 clk_mod = fdtbus_clock_get(phandle, "mod"); 1273 if (clk_mod == NULL || 1274 clk_set_rate(clk_mod, SUNXI_MIXER_FREQ) != 0 || 1275 clk_enable(clk_mod) != 0) { 1276 aprint_error(": couldn't enable mod clock\n"); 1277 return; 1278 } 1279 1280 sc->sc_dev = self; 1281 sc->sc_bst = faa->faa_bst; 1282 if (bus_space_map(sc->sc_bst, addr, size, 0, &sc->sc_bsh) != 0) { 1283 aprint_error(": couldn't map registers\n"); 1284 return; 1285 } 1286 sc->sc_phandle = faa->faa_phandle; 1287 sc->sc_ovl_ui_count = cd->ovl_ui_count; 1288 1289 aprint_naive("\n"); 1290 aprint_normal(": Display Engine Mixer\n"); 1291 1292 sc->sc_ports.dp_ep_activate = sunxi_mixer_ep_activate; 1293 sc->sc_ports.dp_ep_get_data = sunxi_mixer_ep_get_data; 1294 fdt_ports_register(&sc->sc_ports, self, phandle, EP_DRM_CRTC); 1295 1296 out_ep = fdt_endpoint_get_from_index(&sc->sc_ports, 1297 MIXER_PORT_OUTPUT, cd->mixer_index); 1298 if (out_ep == NULL) { 1299 /* Couldn't find new-style DE2 endpoint, try old style. */ 1300 out_ep = fdt_endpoint_get_from_index(&sc->sc_ports, 1301 MIXER_PORT_OUTPUT, 0); 1302 } 1303 1304 if (out_ep != NULL) 1305 sunxi_drm_register_endpoint(phandle, out_ep); 1306 } 1307 1308 CFATTACH_DECL_NEW(sunxi_mixer, sizeof(struct sunxi_mixer_softc), 1309 sunxi_mixer_match, sunxi_mixer_attach, NULL, NULL); 1310