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