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