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