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