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