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