Page MenuHomeFreeBSD

D39117.id119001.diff
No OneTemporary

D39117.id119001.diff

diff --git a/sys/arm/allwinner/a10_fb.c b/sys/arm/allwinner/a10_fb.c
deleted file mode 100644
--- a/sys/arm/allwinner/a10_fb.c
+++ /dev/null
@@ -1,660 +0,0 @@
-/*-
- * Copyright (c) 2016 Jared McNeill <jmcneill@invisible.ca>
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
- * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * $FreeBSD$
- */
-
-/*
- * Allwinner A10/A20 Framebuffer
- */
-
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
-#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/bus.h>
-#include <sys/rman.h>
-#include <sys/condvar.h>
-#include <sys/eventhandler.h>
-#include <sys/kernel.h>
-#include <sys/module.h>
-#include <sys/fbio.h>
-#include <vm/vm.h>
-#include <vm/vm_extern.h>
-#include <vm/vm_kern.h>
-#include <vm/pmap.h>
-
-#include <machine/bus.h>
-
-#include <dev/ofw/ofw_bus.h>
-#include <dev/ofw/ofw_bus_subr.h>
-
-#include <dev/videomode/videomode.h>
-#include <dev/videomode/edidvar.h>
-
-#include <dev/extres/clk/clk.h>
-#include <dev/extres/hwreset/hwreset.h>
-
-#include "fb_if.h"
-#include "hdmi_if.h"
-
-#define FB_DEFAULT_W 800
-#define FB_DEFAULT_H 600
-#define FB_DEFAULT_REF 60
-#define FB_BPP 32
-#define FB_ALIGN 0x1000
-
-#define HDMI_ENABLE_DELAY 20000
-#define DEBE_FREQ 300000000
-
-#define DOT_CLOCK_TO_HZ(c) ((c) * 1000)
-
-/* Display backend */
-#define DEBE_REG_START 0x800
-#define DEBE_REG_END 0x1000
-#define DEBE_REG_WIDTH 4
-#define DEBE_MODCTL 0x800
-#define MODCTL_ITLMOD_EN (1 << 28)
-#define MODCTL_OUT_SEL_MASK (0x7 << 20)
-#define MODCTL_OUT_SEL(sel) ((sel) << 20)
-#define OUT_SEL_LCD 0
-#define MODCTL_LAY0_EN (1 << 8)
-#define MODCTL_START_CTL (1 << 1)
-#define MODCTL_EN (1 << 0)
-#define DEBE_DISSIZE 0x808
-#define DIS_HEIGHT(h) (((h) - 1) << 16)
-#define DIS_WIDTH(w) (((w) - 1) << 0)
-#define DEBE_LAYSIZE0 0x810
-#define LAY_HEIGHT(h) (((h) - 1) << 16)
-#define LAY_WIDTH(w) (((w) - 1) << 0)
-#define DEBE_LAYCOOR0 0x820
-#define LAY_XCOOR(x) ((x) << 16)
-#define LAY_YCOOR(y) ((y) << 0)
-#define DEBE_LAYLINEWIDTH0 0x840
-#define DEBE_LAYFB_L32ADD0 0x850
-#define LAYFB_L32ADD(pa) ((pa) << 3)
-#define DEBE_LAYFB_H4ADD 0x860
-#define LAY0FB_H4ADD(pa) ((pa) >> 29)
-#define DEBE_REGBUFFCTL 0x870
-#define REGBUFFCTL_LOAD (1 << 0)
-#define DEBE_ATTCTL1 0x8a0
-#define ATTCTL1_FBFMT(fmt) ((fmt) << 8)
-#define FBFMT_XRGB8888 9
-#define ATTCTL1_FBPS(ps) ((ps) << 0)
-#define FBPS_32BPP_ARGB 0
-
-/* Timing controller */
-#define TCON_GCTL 0x000
-#define GCTL_TCON_EN (1 << 31)
-#define GCTL_IO_MAP_SEL_TCON1 (1 << 0)
-#define TCON_GINT1 0x008
-#define GINT1_TCON1_LINENO(n) (((n) + 2) << 0)
-#define TCON0_DCLK 0x044
-#define DCLK_EN 0xf0000000
-#define TCON1_CTL 0x090
-#define TCON1_EN (1 << 31)
-#define INTERLACE_EN (1 << 20)
-#define TCON1_SRC_SEL(src) ((src) << 0)
-#define TCON1_SRC_CH1 0
-#define TCON1_SRC_CH2 1
-#define TCON1_SRC_BLUE 2
-#define TCON1_START_DELAY(sd) ((sd) << 4)
-#define TCON1_BASIC0 0x094
-#define TCON1_BASIC1 0x098
-#define TCON1_BASIC2 0x09c
-#define TCON1_BASIC3 0x0a0
-#define TCON1_BASIC4 0x0a4
-#define TCON1_BASIC5 0x0a8
-#define BASIC_X(x) (((x) - 1) << 16)
-#define BASIC_Y(y) (((y) - 1) << 0)
-#define BASIC3_HT(ht) (((ht) - 1) << 16)
-#define BASIC3_HBP(hbp) (((hbp) - 1) << 0)
-#define BASIC4_VT(vt) ((vt) << 16)
-#define BASIC4_VBP(vbp) (((vbp) - 1) << 0)
-#define BASIC5_HSPW(hspw) (((hspw) - 1) << 16)
-#define BASIC5_VSPW(vspw) (((vspw) - 1) << 0)
-#define TCON1_IO_POL 0x0f0
-#define IO_POL_IO2_INV (1 << 26)
-#define IO_POL_PHSYNC (1 << 25)
-#define IO_POL_PVSYNC (1 << 24)
-#define TCON1_IO_TRI 0x0f4
-#define IO0_OUTPUT_TRI_EN (1 << 24)
-#define IO1_OUTPUT_TRI_EN (1 << 25)
-#define IO_TRI_MASK 0xffffffff
-#define START_DELAY(vbl) (MIN(32, (vbl)) - 2)
-#define VBLANK_LEN(vt, vd, i) ((((vt) << (i)) >> 1) - (vd) - 2)
-#define VTOTAL(vt) ((vt) * 2)
-#define DIVIDE(x, y) (((x) + ((y) / 2)) / (y))
-
-struct a10fb_softc {
- device_t dev;
- device_t fbdev;
- struct resource *res[2];
-
- /* Framebuffer */
- struct fb_info info;
- size_t fbsize;
- bus_addr_t paddr;
- vm_offset_t vaddr;
-
- /* HDMI */
- eventhandler_tag hdmi_evh;
-};
-
-static struct resource_spec a10fb_spec[] = {
- { SYS_RES_MEMORY, 0, RF_ACTIVE }, /* DEBE */
- { SYS_RES_MEMORY, 1, RF_ACTIVE }, /* TCON */
- { -1, 0 }
-};
-
-#define DEBE_READ(sc, reg) bus_read_4((sc)->res[0], (reg))
-#define DEBE_WRITE(sc, reg, val) bus_write_4((sc)->res[0], (reg), (val))
-
-#define TCON_READ(sc, reg) bus_read_4((sc)->res[1], (reg))
-#define TCON_WRITE(sc, reg, val) bus_write_4((sc)->res[1], (reg), (val))
-
-static int
-a10fb_allocfb(struct a10fb_softc *sc)
-{
- sc->vaddr = kmem_alloc_contig(sc->fbsize, M_NOWAIT | M_ZERO, 0, ~0,
- FB_ALIGN, 0, VM_MEMATTR_WRITE_COMBINING);
- if (sc->vaddr == 0) {
- device_printf(sc->dev, "failed to allocate FB memory\n");
- return (ENOMEM);
- }
- sc->paddr = pmap_kextract(sc->vaddr);
-
- return (0);
-}
-
-static void
-a10fb_freefb(struct a10fb_softc *sc)
-{
- kmem_free(sc->vaddr, sc->fbsize);
-}
-
-static int
-a10fb_setup_debe(struct a10fb_softc *sc, const struct videomode *mode)
-{
- int width, height, interlace, reg;
- clk_t clk_ahb, clk_dram, clk_debe;
- hwreset_t rst;
- uint32_t val;
- int error;
-
- interlace = !!(mode->flags & VID_INTERLACE);
- width = mode->hdisplay;
- height = mode->vdisplay << interlace;
-
- /* Leave reset */
- error = hwreset_get_by_ofw_name(sc->dev, 0, "de_be", &rst);
- if (error != 0) {
- device_printf(sc->dev, "cannot find reset 'de_be'\n");
- return (error);
- }
- error = hwreset_deassert(rst);
- if (error != 0) {
- device_printf(sc->dev, "couldn't de-assert reset 'de_be'\n");
- return (error);
- }
- /* Gating AHB clock for BE */
- error = clk_get_by_ofw_name(sc->dev, 0, "ahb_de_be", &clk_ahb);
- if (error != 0) {
- device_printf(sc->dev, "cannot find clk 'ahb_de_be'\n");
- return (error);
- }
- error = clk_enable(clk_ahb);
- if (error != 0) {
- device_printf(sc->dev, "cannot enable clk 'ahb_de_be'\n");
- return (error);
- }
- /* Enable DRAM clock to BE */
- error = clk_get_by_ofw_name(sc->dev, 0, "dram_de_be", &clk_dram);
- if (error != 0) {
- device_printf(sc->dev, "cannot find clk 'dram_de_be'\n");
- return (error);
- }
- error = clk_enable(clk_dram);
- if (error != 0) {
- device_printf(sc->dev, "cannot enable clk 'dram_de_be'\n");
- return (error);
- }
- /* Set BE clock to 300MHz and enable */
- error = clk_get_by_ofw_name(sc->dev, 0, "de_be", &clk_debe);
- if (error != 0) {
- device_printf(sc->dev, "cannot find clk 'de_be'\n");
- return (error);
- }
- error = clk_set_freq(clk_debe, DEBE_FREQ, CLK_SET_ROUND_DOWN);
- if (error != 0) {
- device_printf(sc->dev, "cannot set 'de_be' frequency\n");
- return (error);
- }
- error = clk_enable(clk_debe);
- if (error != 0) {
- device_printf(sc->dev, "cannot enable clk 'de_be'\n");
- return (error);
- }
-
- /* Initialize all registers to 0 */
- for (reg = DEBE_REG_START; reg < DEBE_REG_END; reg += DEBE_REG_WIDTH)
- DEBE_WRITE(sc, reg, 0);
-
- /* Enable display backend */
- DEBE_WRITE(sc, DEBE_MODCTL, MODCTL_EN);
-
- /* Set display size */
- DEBE_WRITE(sc, DEBE_DISSIZE, DIS_HEIGHT(height) | DIS_WIDTH(width));
-
- /* Set layer 0 size, position, and stride */
- DEBE_WRITE(sc, DEBE_LAYSIZE0, LAY_HEIGHT(height) | LAY_WIDTH(width));
- DEBE_WRITE(sc, DEBE_LAYCOOR0, LAY_XCOOR(0) | LAY_YCOOR(0));
- DEBE_WRITE(sc, DEBE_LAYLINEWIDTH0, width * FB_BPP);
-
- /* Point layer 0 to FB memory */
- DEBE_WRITE(sc, DEBE_LAYFB_L32ADD0, LAYFB_L32ADD(sc->paddr));
- DEBE_WRITE(sc, DEBE_LAYFB_H4ADD, LAY0FB_H4ADD(sc->paddr));
-
- /* Set backend format and pixel sequence */
- DEBE_WRITE(sc, DEBE_ATTCTL1, ATTCTL1_FBFMT(FBFMT_XRGB8888) |
- ATTCTL1_FBPS(FBPS_32BPP_ARGB));
-
- /* Enable layer 0, output to LCD, setup interlace */
- val = DEBE_READ(sc, DEBE_MODCTL);
- val |= MODCTL_LAY0_EN;
- val &= ~MODCTL_OUT_SEL_MASK;
- val |= MODCTL_OUT_SEL(OUT_SEL_LCD);
- if (interlace)
- val |= MODCTL_ITLMOD_EN;
- else
- val &= ~MODCTL_ITLMOD_EN;
- DEBE_WRITE(sc, DEBE_MODCTL, val);
-
- /* Commit settings */
- DEBE_WRITE(sc, DEBE_REGBUFFCTL, REGBUFFCTL_LOAD);
-
- /* Start DEBE */
- val = DEBE_READ(sc, DEBE_MODCTL);
- val |= MODCTL_START_CTL;
- DEBE_WRITE(sc, DEBE_MODCTL, val);
-
- return (0);
-}
-
-static int
-a10fb_setup_pll(struct a10fb_softc *sc, uint64_t freq)
-{
- clk_t clk_sclk1, clk_sclk2;
- int error;
-
- error = clk_get_by_ofw_name(sc->dev, 0, "lcd_ch1_sclk1", &clk_sclk1);
- if (error != 0) {
- device_printf(sc->dev, "cannot find clk 'lcd_ch1_sclk1'\n");
- return (error);
- }
- error = clk_get_by_ofw_name(sc->dev, 0, "lcd_ch1_sclk2", &clk_sclk2);
- if (error != 0) {
- device_printf(sc->dev, "cannot find clk 'lcd_ch1_sclk2'\n");
- return (error);
- }
-
- error = clk_set_freq(clk_sclk2, freq, 0);
- if (error != 0) {
- device_printf(sc->dev, "cannot set lcd ch1 frequency\n");
- return (error);
- }
- error = clk_enable(clk_sclk2);
- if (error != 0) {
- device_printf(sc->dev, "cannot enable lcd ch1 sclk2\n");
- return (error);
- }
- error = clk_enable(clk_sclk1);
- if (error != 0) {
- device_printf(sc->dev, "cannot enable lcd ch1 sclk1\n");
- return (error);
- }
-
- return (0);
-}
-
-static int
-a10fb_setup_tcon(struct a10fb_softc *sc, const struct videomode *mode)
-{
- u_int interlace, hspw, hbp, vspw, vbp, vbl, width, height, start_delay;
- u_int vtotal, framerate, clk;
- clk_t clk_ahb;
- hwreset_t rst;
- uint32_t val;
- int error;
-
- interlace = !!(mode->flags & VID_INTERLACE);
- width = mode->hdisplay;
- height = mode->vdisplay;
- hspw = mode->hsync_end - mode->hsync_start;
- hbp = mode->htotal - mode->hsync_start;
- vspw = mode->vsync_end - mode->vsync_start;
- vbp = mode->vtotal - mode->vsync_start;
- vbl = VBLANK_LEN(mode->vtotal, mode->vdisplay, interlace);
- start_delay = START_DELAY(vbl);
-
- /* Leave reset */
- error = hwreset_get_by_ofw_name(sc->dev, 0, "lcd", &rst);
- if (error != 0) {
- device_printf(sc->dev, "cannot find reset 'lcd'\n");
- return (error);
- }
- error = hwreset_deassert(rst);
- if (error != 0) {
- device_printf(sc->dev, "couldn't de-assert reset 'lcd'\n");
- return (error);
- }
- /* Gating AHB clock for LCD */
- error = clk_get_by_ofw_name(sc->dev, 0, "ahb_lcd", &clk_ahb);
- if (error != 0) {
- device_printf(sc->dev, "cannot find clk 'ahb_lcd'\n");
- return (error);
- }
- error = clk_enable(clk_ahb);
- if (error != 0) {
- device_printf(sc->dev, "cannot enable clk 'ahb_lcd'\n");
- return (error);
- }
-
- /* Disable TCON and TCON1 */
- TCON_WRITE(sc, TCON_GCTL, 0);
- TCON_WRITE(sc, TCON1_CTL, 0);
-
- /* Enable clocks */
- TCON_WRITE(sc, TCON0_DCLK, DCLK_EN);
-
- /* Disable IO and data output ports */
- TCON_WRITE(sc, TCON1_IO_TRI, IO_TRI_MASK);
-
- /* Disable TCON and select TCON1 */
- TCON_WRITE(sc, TCON_GCTL, GCTL_IO_MAP_SEL_TCON1);
-
- /* Source width and height */
- TCON_WRITE(sc, TCON1_BASIC0, BASIC_X(width) | BASIC_Y(height));
- /* Scaler width and height */
- TCON_WRITE(sc, TCON1_BASIC1, BASIC_X(width) | BASIC_Y(height));
- /* Output width and height */
- TCON_WRITE(sc, TCON1_BASIC2, BASIC_X(width) | BASIC_Y(height));
- /* Horizontal total and back porch */
- TCON_WRITE(sc, TCON1_BASIC3, BASIC3_HT(mode->htotal) | BASIC3_HBP(hbp));
- /* Vertical total and back porch */
- vtotal = VTOTAL(mode->vtotal);
- if (interlace) {
- framerate = DIVIDE(DIVIDE(DOT_CLOCK_TO_HZ(mode->dot_clock),
- mode->htotal), mode->vtotal);
- clk = mode->htotal * (VTOTAL(mode->vtotal) + 1) * framerate;
- if ((clk / 2) == DOT_CLOCK_TO_HZ(mode->dot_clock))
- vtotal += 1;
- }
- TCON_WRITE(sc, TCON1_BASIC4, BASIC4_VT(vtotal) | BASIC4_VBP(vbp));
- /* Horizontal and vertical sync */
- TCON_WRITE(sc, TCON1_BASIC5, BASIC5_HSPW(hspw) | BASIC5_VSPW(vspw));
- /* Polarity */
- val = IO_POL_IO2_INV;
- if (mode->flags & VID_PHSYNC)
- val |= IO_POL_PHSYNC;
- if (mode->flags & VID_PVSYNC)
- val |= IO_POL_PVSYNC;
- TCON_WRITE(sc, TCON1_IO_POL, val);
-
- /* Set scan line for TCON1 line trigger */
- TCON_WRITE(sc, TCON_GINT1, GINT1_TCON1_LINENO(start_delay));
-
- /* Enable TCON1 */
- val = TCON1_EN;
- if (interlace)
- val |= INTERLACE_EN;
- val |= TCON1_START_DELAY(start_delay);
- val |= TCON1_SRC_SEL(TCON1_SRC_CH1);
- TCON_WRITE(sc, TCON1_CTL, val);
-
- /* Setup PLL */
- return (a10fb_setup_pll(sc, DOT_CLOCK_TO_HZ(mode->dot_clock)));
-}
-
-static void
-a10fb_enable_tcon(struct a10fb_softc *sc, int onoff)
-{
- uint32_t val;
-
- /* Enable TCON */
- val = TCON_READ(sc, TCON_GCTL);
- if (onoff)
- val |= GCTL_TCON_EN;
- else
- val &= ~GCTL_TCON_EN;
- TCON_WRITE(sc, TCON_GCTL, val);
-
- /* Enable TCON1 IO0/IO1 outputs */
- val = TCON_READ(sc, TCON1_IO_TRI);
- if (onoff)
- val &= ~(IO0_OUTPUT_TRI_EN | IO1_OUTPUT_TRI_EN);
- else
- val |= (IO0_OUTPUT_TRI_EN | IO1_OUTPUT_TRI_EN);
- TCON_WRITE(sc, TCON1_IO_TRI, val);
-}
-
-static int
-a10fb_configure(struct a10fb_softc *sc, const struct videomode *mode)
-{
- size_t fbsize;
- int error;
-
- fbsize = round_page(mode->hdisplay * mode->vdisplay * (FB_BPP / NBBY));
-
- /* Detach the old FB device */
- if (sc->fbdev != NULL) {
- device_delete_child(sc->dev, sc->fbdev);
- sc->fbdev = NULL;
- }
-
- /* If the FB size has changed, free the old FB memory */
- if (sc->fbsize > 0 && sc->fbsize != fbsize) {
- a10fb_freefb(sc);
- sc->vaddr = 0;
- }
-
- /* Allocate the FB if necessary */
- sc->fbsize = fbsize;
- if (sc->vaddr == 0) {
- error = a10fb_allocfb(sc);
- if (error != 0) {
- device_printf(sc->dev, "failed to allocate FB memory\n");
- return (ENXIO);
- }
- }
-
- /* Setup display backend */
- error = a10fb_setup_debe(sc, mode);
- if (error != 0)
- return (error);
-
- /* Setup display timing controller */
- error = a10fb_setup_tcon(sc, mode);
- if (error != 0)
- return (error);
-
- /* Attach framebuffer device */
- sc->info.fb_name = device_get_nameunit(sc->dev);
- sc->info.fb_vbase = (intptr_t)sc->vaddr;
- sc->info.fb_pbase = sc->paddr;
- sc->info.fb_size = sc->fbsize;
- sc->info.fb_bpp = sc->info.fb_depth = FB_BPP;
- sc->info.fb_stride = mode->hdisplay * (FB_BPP / NBBY);
- sc->info.fb_width = mode->hdisplay;
- sc->info.fb_height = mode->vdisplay;
-
- sc->fbdev = device_add_child(sc->dev, "fbd", device_get_unit(sc->dev));
- if (sc->fbdev == NULL) {
- device_printf(sc->dev, "failed to add fbd child\n");
- return (ENOENT);
- }
-
- error = device_probe_and_attach(sc->fbdev);
- if (error != 0) {
- device_printf(sc->dev, "failed to attach fbd device\n");
- return (error);
- }
-
- return (0);
-}
-
-static void
-a10fb_hdmi_event(void *arg, device_t hdmi_dev)
-{
- const struct videomode *mode;
- struct videomode hdmi_mode;
- struct a10fb_softc *sc;
- struct edid_info ei;
- uint8_t *edid;
- uint32_t edid_len;
- int error;
-
- sc = arg;
- edid = NULL;
- edid_len = 0;
- mode = NULL;
-
- error = HDMI_GET_EDID(hdmi_dev, &edid, &edid_len);
- if (error != 0) {
- device_printf(sc->dev, "failed to get EDID: %d\n", error);
- } else {
- error = edid_parse(edid, &ei);
- if (error != 0) {
- device_printf(sc->dev, "failed to parse EDID: %d\n",
- error);
- } else {
- if (bootverbose)
- edid_print(&ei);
- mode = ei.edid_preferred_mode;
- }
- }
-
- /* If the preferred mode could not be determined, use the default */
- if (mode == NULL)
- mode = pick_mode_by_ref(FB_DEFAULT_W, FB_DEFAULT_H,
- FB_DEFAULT_REF);
-
- if (mode == NULL) {
- device_printf(sc->dev, "failed to find usable video mode\n");
- return;
- }
-
- if (bootverbose)
- device_printf(sc->dev, "using %dx%d\n",
- mode->hdisplay, mode->vdisplay);
-
- /* Disable HDMI */
- HDMI_ENABLE(hdmi_dev, 0);
-
- /* Disable timing controller */
- a10fb_enable_tcon(sc, 0);
-
- /* Configure DEBE and TCON */
- error = a10fb_configure(sc, mode);
- if (error != 0) {
- device_printf(sc->dev, "failed to configure FB: %d\n", error);
- return;
- }
-
- hdmi_mode = *mode;
- hdmi_mode.hskew = mode->hsync_end - mode->hsync_start;
- hdmi_mode.flags |= VID_HSKEW;
- HDMI_SET_VIDEOMODE(hdmi_dev, &hdmi_mode);
-
- /* Enable timing controller */
- a10fb_enable_tcon(sc, 1);
-
- DELAY(HDMI_ENABLE_DELAY);
-
- /* Enable HDMI */
- HDMI_ENABLE(hdmi_dev, 1);
-}
-
-static int
-a10fb_probe(device_t dev)
-{
- if (!ofw_bus_status_okay(dev))
- return (ENXIO);
-
- if (!ofw_bus_is_compatible(dev, "allwinner,sun7i-a20-fb"))
- return (ENXIO);
-
- device_set_desc(dev, "Allwinner Framebuffer");
- return (BUS_PROBE_DEFAULT);
-}
-
-static int
-a10fb_attach(device_t dev)
-{
- struct a10fb_softc *sc;
-
- sc = device_get_softc(dev);
-
- sc->dev = dev;
-
- if (bus_alloc_resources(dev, a10fb_spec, sc->res)) {
- device_printf(dev, "cannot allocate resources for device\n");
- return (ENXIO);
- }
-
- sc->hdmi_evh = EVENTHANDLER_REGISTER(hdmi_event,
- a10fb_hdmi_event, sc, 0);
-
- return (0);
-}
-
-static struct fb_info *
-a10fb_fb_getinfo(device_t dev)
-{
- struct a10fb_softc *sc;
-
- sc = device_get_softc(dev);
-
- return (&sc->info);
-}
-
-static device_method_t a10fb_methods[] = {
- /* Device interface */
- DEVMETHOD(device_probe, a10fb_probe),
- DEVMETHOD(device_attach, a10fb_attach),
-
- /* FB interface */
- DEVMETHOD(fb_getinfo, a10fb_fb_getinfo),
-
- DEVMETHOD_END
-};
-
-static driver_t a10fb_driver = {
- "fb",
- a10fb_methods,
- sizeof(struct a10fb_softc),
-};
-
-DRIVER_MODULE(fb, simplebus, a10fb_driver, 0, 0);
diff --git a/sys/arm/allwinner/a10_hdmi.c b/sys/arm/allwinner/a10_hdmi.c
deleted file mode 100644
--- a/sys/arm/allwinner/a10_hdmi.c
+++ /dev/null
@@ -1,723 +0,0 @@
-/*-
- * Copyright (c) 2016 Jared McNeill <jmcneill@invisible.ca>
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
- * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * $FreeBSD$
- */
-
-/*
- * Allwinner A10/A20 HDMI TX
- */
-
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
-#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/bus.h>
-#include <sys/rman.h>
-#include <sys/condvar.h>
-#include <sys/eventhandler.h>
-#include <sys/kernel.h>
-#include <sys/module.h>
-
-#include <machine/bus.h>
-
-#include <dev/ofw/ofw_bus.h>
-#include <dev/ofw/ofw_bus_subr.h>
-
-#include <dev/videomode/videomode.h>
-#include <dev/videomode/edidvar.h>
-
-#include <dev/extres/clk/clk.h>
-
-#include "hdmi_if.h"
-
-#define HDMI_CTRL 0x004
-#define CTRL_MODULE_EN (1 << 31)
-#define HDMI_INT_STATUS 0x008
-#define HDMI_HPD 0x00c
-#define HPD_DET (1 << 0)
-#define HDMI_VID_CTRL 0x010
-#define VID_CTRL_VIDEO_EN (1 << 31)
-#define VID_CTRL_HDMI_MODE (1 << 30)
-#define VID_CTRL_INTERLACE (1 << 4)
-#define VID_CTRL_REPEATER_2X (1 << 0)
-#define HDMI_VID_TIMING0 0x014
-#define VID_ACT_V(v) (((v) - 1) << 16)
-#define VID_ACT_H(h) (((h) - 1) << 0)
-#define HDMI_VID_TIMING1 0x018
-#define VID_VBP(vbp) (((vbp) - 1) << 16)
-#define VID_HBP(hbp) (((hbp) - 1) << 0)
-#define HDMI_VID_TIMING2 0x01c
-#define VID_VFP(vfp) (((vfp) - 1) << 16)
-#define VID_HFP(hfp) (((hfp) - 1) << 0)
-#define HDMI_VID_TIMING3 0x020
-#define VID_VSPW(vspw) (((vspw) - 1) << 16)
-#define VID_HSPW(hspw) (((hspw) - 1) << 0)
-#define HDMI_VID_TIMING4 0x024
-#define TX_CLOCK_NORMAL 0x03e00000
-#define VID_VSYNC_ACTSEL (1 << 1)
-#define VID_HSYNC_ACTSEL (1 << 0)
-#define HDMI_AUD_CTRL 0x040
-#define AUD_CTRL_EN (1 << 31)
-#define AUD_CTRL_RST (1 << 30)
-#define HDMI_ADMA_CTRL 0x044
-#define HDMI_ADMA_MODE (1 << 31)
-#define HDMI_ADMA_MODE_DDMA (0 << 31)
-#define HDMI_ADMA_MODE_NDMA (1 << 31)
-#define HDMI_AUD_FMT 0x048
-#define AUD_FMT_CH(n) ((n) - 1)
-#define HDMI_PCM_CTRL 0x04c
-#define HDMI_AUD_CTS 0x050
-#define HDMI_AUD_N 0x054
-#define HDMI_AUD_CH_STATUS0 0x058
-#define CH_STATUS0_FS_FREQ (0xf << 24)
-#define CH_STATUS0_FS_FREQ_48 (2 << 24)
-#define HDMI_AUD_CH_STATUS1 0x05c
-#define CH_STATUS1_WORD_LEN (0x7 << 1)
-#define CH_STATUS1_WORD_LEN_16 (1 << 1)
-#define HDMI_AUDIO_RESET_RETRY 1000
-#define HDMI_AUDIO_CHANNELS 2
-#define HDMI_AUDIO_CHANNELMAP 0x76543210
-#define HDMI_AUDIO_N 6144 /* 48 kHz */
-#define HDMI_AUDIO_CTS(r, n) ((((r) * 10) * ((n) / 128)) / 480)
-#define HDMI_PADCTRL0 0x200
-#define PADCTRL0_BIASEN (1 << 31)
-#define PADCTRL0_LDOCEN (1 << 30)
-#define PADCTRL0_LDODEN (1 << 29)
-#define PADCTRL0_PWENC (1 << 28)
-#define PADCTRL0_PWEND (1 << 27)
-#define PADCTRL0_PWENG (1 << 26)
-#define PADCTRL0_CKEN (1 << 25)
-#define PADCTRL0_SEN (1 << 24)
-#define PADCTRL0_TXEN (1 << 23)
-#define HDMI_PADCTRL1 0x204
-#define PADCTRL1_AMP_OPT (1 << 23)
-#define PADCTRL1_AMPCK_OPT (1 << 22)
-#define PADCTRL1_DMP_OPT (1 << 21)
-#define PADCTRL1_EMP_OPT (1 << 20)
-#define PADCTRL1_EMPCK_OPT (1 << 19)
-#define PADCTRL1_PWSCK (1 << 18)
-#define PADCTRL1_PWSDT (1 << 17)
-#define PADCTRL1_REG_CSMPS (1 << 16)
-#define PADCTRL1_REG_DEN (1 << 15)
-#define PADCTRL1_REG_DENCK (1 << 14)
-#define PADCTRL1_REG_PLRCK (1 << 13)
-#define PADCTRL1_REG_EMP (0x7 << 10)
-#define PADCTRL1_REG_EMP_EN (0x2 << 10)
-#define PADCTRL1_REG_CD (0x3 << 8)
-#define PADCTRL1_REG_CKSS (0x3 << 6)
-#define PADCTRL1_REG_CKSS_1X (0x1 << 6)
-#define PADCTRL1_REG_CKSS_2X (0x0 << 6)
-#define PADCTRL1_REG_AMP (0x7 << 3)
-#define PADCTRL1_REG_AMP_EN (0x6 << 3)
-#define PADCTRL1_REG_PLR (0x7 << 0)
-#define HDMI_PLLCTRL0 0x208
-#define PLLCTRL0_PLL_EN (1 << 31)
-#define PLLCTRL0_BWS (1 << 30)
-#define PLLCTRL0_HV_IS_33 (1 << 29)
-#define PLLCTRL0_LDO1_EN (1 << 28)
-#define PLLCTRL0_LDO2_EN (1 << 27)
-#define PLLCTRL0_SDIV2 (1 << 25)
-#define PLLCTRL0_VCO_GAIN (0x1 << 22)
-#define PLLCTRL0_S (0x7 << 17)
-#define PLLCTRL0_CP_S (0xf << 12)
-#define PLLCTRL0_CS (0x7 << 8)
-#define PLLCTRL0_PREDIV(x) ((x) << 4)
-#define PLLCTRL0_VCO_S (0x8 << 0)
-#define HDMI_PLLDBG0 0x20c
-#define PLLDBG0_CKIN_SEL (1 << 21)
-#define PLLDBG0_CKIN_SEL_PLL3 (0 << 21)
-#define PLLDBG0_CKIN_SEL_PLL7 (1 << 21)
-#define HDMI_PKTCTRL0 0x2f0
-#define HDMI_PKTCTRL1 0x2f4
-#define PKTCTRL_PACKET(n,t) ((t) << ((n) << 2))
-#define PKT_NULL 0
-#define PKT_GC 1
-#define PKT_AVI 2
-#define PKT_AI 3
-#define PKT_SPD 5
-#define PKT_END 15
-#define DDC_CTRL 0x500
-#define CTRL_DDC_EN (1 << 31)
-#define CTRL_DDC_ACMD_START (1 << 30)
-#define CTRL_DDC_FIFO_DIR (1 << 8)
-#define CTRL_DDC_FIFO_DIR_READ (0 << 8)
-#define CTRL_DDC_FIFO_DIR_WRITE (1 << 8)
-#define CTRL_DDC_SWRST (1 << 0)
-#define DDC_SLAVE_ADDR 0x504
-#define SLAVE_ADDR_SEG_SHIFT 24
-#define SLAVE_ADDR_EDDC_SHIFT 16
-#define SLAVE_ADDR_OFFSET_SHIFT 8
-#define SLAVE_ADDR_SHIFT 0
-#define DDC_INT_STATUS 0x50c
-#define INT_STATUS_XFER_DONE (1 << 0)
-#define DDC_FIFO_CTRL 0x510
-#define FIFO_CTRL_CLEAR (1 << 31)
-#define DDC_BYTE_COUNTER 0x51c
-#define DDC_COMMAND 0x520
-#define COMMAND_EOREAD (4 << 0)
-#define DDC_CLOCK 0x528
-#define DDC_CLOCK_M (1 << 3)
-#define DDC_CLOCK_N (5 << 0)
-#define DDC_FIFO 0x518
-#define SWRST_DELAY 1000
-#define DDC_DELAY 1000
-#define DDC_RETRY 1000
-#define DDC_BLKLEN 16
-#define DDC_ADDR 0x50
-#define EDDC_ADDR 0x60
-#define EDID_LENGTH 128
-#define DDC_CTRL_LINE 0x540
-#define DDC_LINE_SCL_ENABLE (1 << 8)
-#define DDC_LINE_SDA_ENABLE (1 << 9)
-#define HDMI_ENABLE_DELAY 50000
-#define DDC_READ_RETRY 4
-#define EXT_TAG 0x00
-#define CEA_TAG_ID 0x02
-#define CEA_DTD 0x03
-#define DTD_BASIC_AUDIO (1 << 6)
-#define CEA_REV 0x02
-#define CEA_DATA_OFF 0x03
-#define CEA_DATA_START 4
-#define BLOCK_TAG(x) (((x) >> 5) & 0x7)
-#define BLOCK_TAG_VSDB 3
-#define BLOCK_LEN(x) ((x) & 0x1f)
-#define HDMI_VSDB_MINLEN 5
-#define HDMI_OUI "\x03\x0c\x00"
-#define HDMI_OUI_LEN 3
-#define HDMI_DEFAULT_FREQ 297000000
-
-struct a10hdmi_softc {
- struct resource *res;
-
- struct intr_config_hook mode_hook;
-
- uint8_t edid[EDID_LENGTH];
-
- int has_hdmi;
- int has_audio;
-
- clk_t clk_ahb;
- clk_t clk_hdmi;
- clk_t clk_lcd;
-};
-
-static struct resource_spec a10hdmi_spec[] = {
- { SYS_RES_MEMORY, 0, RF_ACTIVE },
- { -1, 0 }
-};
-
-#define HDMI_READ(sc, reg) bus_read_4((sc)->res, (reg))
-#define HDMI_WRITE(sc, reg, val) bus_write_4((sc)->res, (reg), (val))
-
-static void
-a10hdmi_init(struct a10hdmi_softc *sc)
-{
- /* Enable the HDMI module */
- HDMI_WRITE(sc, HDMI_CTRL, CTRL_MODULE_EN);
-
- /* Configure PLL/DRV settings */
- HDMI_WRITE(sc, HDMI_PADCTRL0, PADCTRL0_BIASEN | PADCTRL0_LDOCEN |
- PADCTRL0_LDODEN | PADCTRL0_PWENC | PADCTRL0_PWEND |
- PADCTRL0_PWENG | PADCTRL0_CKEN | PADCTRL0_TXEN);
- HDMI_WRITE(sc, HDMI_PADCTRL1, PADCTRL1_AMP_OPT | PADCTRL1_AMPCK_OPT |
- PADCTRL1_EMP_OPT | PADCTRL1_EMPCK_OPT | PADCTRL1_REG_DEN |
- PADCTRL1_REG_DENCK | PADCTRL1_REG_EMP_EN | PADCTRL1_REG_AMP_EN);
-
- /* Select PLL3 as input clock */
- HDMI_WRITE(sc, HDMI_PLLDBG0, PLLDBG0_CKIN_SEL_PLL3);
-
- DELAY(HDMI_ENABLE_DELAY);
-}
-
-static void
-a10hdmi_hpd(void *arg)
-{
- struct a10hdmi_softc *sc;
- device_t dev;
- uint32_t hpd;
-
- dev = arg;
- sc = device_get_softc(dev);
-
- hpd = HDMI_READ(sc, HDMI_HPD);
- if ((hpd & HPD_DET) == HPD_DET)
- EVENTHANDLER_INVOKE(hdmi_event, dev, HDMI_EVENT_CONNECTED);
-
- config_intrhook_disestablish(&sc->mode_hook);
-}
-
-static int
-a10hdmi_probe(device_t dev)
-{
- if (!ofw_bus_status_okay(dev))
- return (ENXIO);
-
- if (!ofw_bus_is_compatible(dev, "allwinner,sun7i-a20-hdmi"))
- return (ENXIO);
-
- device_set_desc(dev, "Allwinner HDMI TX");
- return (BUS_PROBE_DEFAULT);
-}
-
-static int
-a10hdmi_attach(device_t dev)
-{
- struct a10hdmi_softc *sc;
- int error;
-
- sc = device_get_softc(dev);
-
- if (bus_alloc_resources(dev, a10hdmi_spec, &sc->res)) {
- device_printf(dev, "cannot allocate resources for device\n");
- return (ENXIO);
- }
-
- /* Setup clocks */
- error = clk_get_by_ofw_name(dev, 0, "ahb", &sc->clk_ahb);
- if (error != 0) {
- device_printf(dev, "cannot find ahb clock\n");
- return (error);
- }
- error = clk_get_by_ofw_name(dev, 0, "hdmi", &sc->clk_hdmi);
- if (error != 0) {
- device_printf(dev, "cannot find hdmi clock\n");
- return (error);
- }
- error = clk_get_by_ofw_name(dev, 0, "lcd", &sc->clk_lcd);
- if (error != 0) {
- device_printf(dev, "cannot find lcd clock\n");
- }
- /* Enable HDMI clock */
- error = clk_enable(sc->clk_hdmi);
- if (error != 0) {
- device_printf(dev, "cannot enable hdmi clock\n");
- return (error);
- }
- /* Gating AHB clock for HDMI */
- error = clk_enable(sc->clk_ahb);
- if (error != 0) {
- device_printf(dev, "cannot enable ahb gate\n");
- return (error);
- }
-
- a10hdmi_init(sc);
-
- sc->mode_hook.ich_func = a10hdmi_hpd;
- sc->mode_hook.ich_arg = dev;
-
- error = config_intrhook_establish(&sc->mode_hook);
- if (error != 0)
- return (error);
-
- return (0);
-}
-
-static int
-a10hdmi_ddc_xfer(struct a10hdmi_softc *sc, uint16_t addr, uint8_t seg,
- uint8_t off, int len)
-{
- uint32_t val;
- int retry;
-
- /* Set FIFO direction to read */
- val = HDMI_READ(sc, DDC_CTRL);
- val &= ~CTRL_DDC_FIFO_DIR;
- val |= CTRL_DDC_FIFO_DIR_READ;
- HDMI_WRITE(sc, DDC_CTRL, val);
-
- /* Setup DDC slave address */
- val = (addr << SLAVE_ADDR_SHIFT) | (seg << SLAVE_ADDR_SEG_SHIFT) |
- (EDDC_ADDR << SLAVE_ADDR_EDDC_SHIFT) |
- (off << SLAVE_ADDR_OFFSET_SHIFT);
- HDMI_WRITE(sc, DDC_SLAVE_ADDR, val);
-
- /* Clear FIFO */
- val = HDMI_READ(sc, DDC_FIFO_CTRL);
- val |= FIFO_CTRL_CLEAR;
- HDMI_WRITE(sc, DDC_FIFO_CTRL, val);
-
- /* Set transfer length */
- HDMI_WRITE(sc, DDC_BYTE_COUNTER, len);
-
- /* Set command to "Explicit Offset Address Read" */
- HDMI_WRITE(sc, DDC_COMMAND, COMMAND_EOREAD);
-
- /* Start transfer */
- val = HDMI_READ(sc, DDC_CTRL);
- val |= CTRL_DDC_ACMD_START;
- HDMI_WRITE(sc, DDC_CTRL, val);
-
- /* Wait for command to start */
- retry = DDC_RETRY;
- while (--retry > 0) {
- val = HDMI_READ(sc, DDC_CTRL);
- if ((val & CTRL_DDC_ACMD_START) == 0)
- break;
- DELAY(DDC_DELAY);
- }
- if (retry == 0)
- return (ETIMEDOUT);
-
- /* Ensure that the transfer completed */
- val = HDMI_READ(sc, DDC_INT_STATUS);
- if ((val & INT_STATUS_XFER_DONE) == 0)
- return (EIO);
-
- return (0);
-}
-
-static int
-a10hdmi_ddc_read(struct a10hdmi_softc *sc, int block, uint8_t *edid)
-{
- int resid, off, len, error;
- uint8_t *pbuf;
-
- pbuf = edid;
- resid = EDID_LENGTH;
- off = (block & 1) ? EDID_LENGTH : 0;
-
- while (resid > 0) {
- len = min(resid, DDC_BLKLEN);
- error = a10hdmi_ddc_xfer(sc, DDC_ADDR, block >> 1, off, len);
- if (error != 0)
- return (error);
-
- bus_read_multi_1(sc->res, DDC_FIFO, pbuf, len);
-
- pbuf += len;
- off += len;
- resid -= len;
- }
-
- return (0);
-}
-
-static int
-a10hdmi_detect_hdmi_vsdb(uint8_t *edid)
-{
- int off, p, btag, blen;
-
- if (edid[EXT_TAG] != CEA_TAG_ID)
- return (0);
-
- off = edid[CEA_DATA_OFF];
-
- /* CEA data block collection starts at byte 4 */
- if (off <= CEA_DATA_START)
- return (0);
-
- /* Parse the CEA data blocks */
- for (p = CEA_DATA_START; p < off;) {
- btag = BLOCK_TAG(edid[p]);
- blen = BLOCK_LEN(edid[p]);
-
- /* Make sure the length is sane */
- if (p + blen + 1 > off)
- break;
-
- /* Look for a VSDB with the HDMI 24-bit IEEE registration ID */
- if (btag == BLOCK_TAG_VSDB && blen >= HDMI_VSDB_MINLEN &&
- memcmp(&edid[p + 1], HDMI_OUI, HDMI_OUI_LEN) == 0)
- return (1);
-
- /* Next data block */
- p += (1 + blen);
- }
-
- return (0);
-}
-
-static void
-a10hdmi_detect_hdmi(struct a10hdmi_softc *sc, int *phdmi, int *paudio)
-{
- struct edid_info ei;
- uint8_t edid[EDID_LENGTH];
- int block;
-
- *phdmi = *paudio = 0;
-
- if (edid_parse(sc->edid, &ei) != 0)
- return;
-
- /* Scan through extension blocks, looking for a CEA-861 block. */
- for (block = 1; block <= ei.edid_ext_block_count; block++) {
- if (a10hdmi_ddc_read(sc, block, edid) != 0)
- return;
-
- if (a10hdmi_detect_hdmi_vsdb(edid) != 0) {
- *phdmi = 1;
- *paudio = ((edid[CEA_DTD] & DTD_BASIC_AUDIO) != 0);
- return;
- }
- }
-}
-
-static int
-a10hdmi_get_edid(device_t dev, uint8_t **edid, uint32_t *edid_len)
-{
- struct a10hdmi_softc *sc;
- int error, retry;
-
- sc = device_get_softc(dev);
- retry = DDC_READ_RETRY;
-
- while (--retry > 0) {
- /* I2C software reset */
- HDMI_WRITE(sc, DDC_FIFO_CTRL, 0);
- HDMI_WRITE(sc, DDC_CTRL, CTRL_DDC_EN | CTRL_DDC_SWRST);
- DELAY(SWRST_DELAY);
- if (HDMI_READ(sc, DDC_CTRL) & CTRL_DDC_SWRST) {
- device_printf(dev, "DDC software reset failed\n");
- return (ENXIO);
- }
-
- /* Configure DDC clock */
- HDMI_WRITE(sc, DDC_CLOCK, DDC_CLOCK_M | DDC_CLOCK_N);
-
- /* Enable SDA/SCL */
- HDMI_WRITE(sc, DDC_CTRL_LINE,
- DDC_LINE_SCL_ENABLE | DDC_LINE_SDA_ENABLE);
-
- /* Read EDID block */
- error = a10hdmi_ddc_read(sc, 0, sc->edid);
- if (error == 0) {
- *edid = sc->edid;
- *edid_len = sizeof(sc->edid);
- break;
- }
- }
-
- if (error == 0)
- a10hdmi_detect_hdmi(sc, &sc->has_hdmi, &sc->has_audio);
- else
- sc->has_hdmi = sc->has_audio = 0;
-
- return (error);
-}
-
-static void
-a10hdmi_set_audiomode(device_t dev, const struct videomode *mode)
-{
- struct a10hdmi_softc *sc;
- uint32_t val;
- int retry;
-
- sc = device_get_softc(dev);
-
- /* Disable and reset audio module and wait for reset bit to clear */
- HDMI_WRITE(sc, HDMI_AUD_CTRL, AUD_CTRL_RST);
- for (retry = HDMI_AUDIO_RESET_RETRY; retry > 0; retry--) {
- val = HDMI_READ(sc, HDMI_AUD_CTRL);
- if ((val & AUD_CTRL_RST) == 0)
- break;
- }
- if (retry == 0) {
- device_printf(dev, "timeout waiting for audio module\n");
- return;
- }
-
- if (!sc->has_audio)
- return;
-
- /* DMA and FIFO control */
- HDMI_WRITE(sc, HDMI_ADMA_CTRL, HDMI_ADMA_MODE_DDMA);
-
- /* Audio format control (LPCM, S16LE, stereo) */
- HDMI_WRITE(sc, HDMI_AUD_FMT, AUD_FMT_CH(HDMI_AUDIO_CHANNELS));
-
- /* Channel mappings */
- HDMI_WRITE(sc, HDMI_PCM_CTRL, HDMI_AUDIO_CHANNELMAP);
-
- /* Clocks */
- HDMI_WRITE(sc, HDMI_AUD_CTS,
- HDMI_AUDIO_CTS(mode->dot_clock, HDMI_AUDIO_N));
- HDMI_WRITE(sc, HDMI_AUD_N, HDMI_AUDIO_N);
-
- /* Set sampling frequency to 48 kHz, word length to 16-bit */
- HDMI_WRITE(sc, HDMI_AUD_CH_STATUS0, CH_STATUS0_FS_FREQ_48);
- HDMI_WRITE(sc, HDMI_AUD_CH_STATUS1, CH_STATUS1_WORD_LEN_16);
-
- /* Enable */
- HDMI_WRITE(sc, HDMI_AUD_CTRL, AUD_CTRL_EN);
-}
-
-static int
-a10hdmi_get_tcon_config(struct a10hdmi_softc *sc, int *div, int *dbl)
-{
- uint64_t lcd_fin, lcd_fout;
- clk_t clk_lcd_parent;
- const char *pname;
- int error;
-
- error = clk_get_parent(sc->clk_lcd, &clk_lcd_parent);
- if (error != 0)
- return (error);
-
- /* Get the LCD CH1 special clock 2 divider */
- error = clk_get_freq(sc->clk_lcd, &lcd_fout);
- if (error != 0)
- return (error);
- error = clk_get_freq(clk_lcd_parent, &lcd_fin);
- if (error != 0)
- return (error);
- *div = lcd_fin / lcd_fout;
-
- /* Detect LCD CH1 special clock using a 1X or 2X source */
- /* XXX */
- pname = clk_get_name(clk_lcd_parent);
- if (strcmp(pname, "pll3") == 0 || strcmp(pname, "pll7") == 0)
- *dbl = 0;
- else
- *dbl = 1;
-
- return (0);
-}
-
-static int
-a10hdmi_set_videomode(device_t dev, const struct videomode *mode)
-{
- struct a10hdmi_softc *sc;
- int error, clk_div, clk_dbl;
- int dblscan, hfp, hspw, hbp, vfp, vspw, vbp;
- uint32_t val;
-
- sc = device_get_softc(dev);
- dblscan = !!(mode->flags & VID_DBLSCAN);
- hfp = mode->hsync_start - mode->hdisplay;
- hspw = mode->hsync_end - mode->hsync_start;
- hbp = mode->htotal - mode->hsync_start;
- vfp = mode->vsync_start - mode->vdisplay;
- vspw = mode->vsync_end - mode->vsync_start;
- vbp = mode->vtotal - mode->vsync_start;
-
- error = a10hdmi_get_tcon_config(sc, &clk_div, &clk_dbl);
- if (error != 0) {
- device_printf(dev, "couldn't get tcon config: %d\n", error);
- return (error);
- }
-
- /* Clear interrupt status */
- HDMI_WRITE(sc, HDMI_INT_STATUS, HDMI_READ(sc, HDMI_INT_STATUS));
-
- /* Clock setup */
- val = HDMI_READ(sc, HDMI_PADCTRL1);
- val &= ~PADCTRL1_REG_CKSS;
- val |= (clk_dbl ? PADCTRL1_REG_CKSS_2X : PADCTRL1_REG_CKSS_1X);
- HDMI_WRITE(sc, HDMI_PADCTRL1, val);
- HDMI_WRITE(sc, HDMI_PLLCTRL0, PLLCTRL0_PLL_EN | PLLCTRL0_BWS |
- PLLCTRL0_HV_IS_33 | PLLCTRL0_LDO1_EN | PLLCTRL0_LDO2_EN |
- PLLCTRL0_SDIV2 | PLLCTRL0_VCO_GAIN | PLLCTRL0_S |
- PLLCTRL0_CP_S | PLLCTRL0_CS | PLLCTRL0_PREDIV(clk_div) |
- PLLCTRL0_VCO_S);
-
- /* Setup display settings */
- if (bootverbose)
- device_printf(dev, "HDMI: %s, Audio: %s\n",
- sc->has_hdmi ? "yes" : "no", sc->has_audio ? "yes" : "no");
- val = 0;
- if (sc->has_hdmi)
- val |= VID_CTRL_HDMI_MODE;
- if (mode->flags & VID_INTERLACE)
- val |= VID_CTRL_INTERLACE;
- if (mode->flags & VID_DBLSCAN)
- val |= VID_CTRL_REPEATER_2X;
- HDMI_WRITE(sc, HDMI_VID_CTRL, val);
-
- /* Setup display timings */
- HDMI_WRITE(sc, HDMI_VID_TIMING0,
- VID_ACT_V(mode->vdisplay) | VID_ACT_H(mode->hdisplay << dblscan));
- HDMI_WRITE(sc, HDMI_VID_TIMING1,
- VID_VBP(vbp) | VID_HBP(hbp << dblscan));
- HDMI_WRITE(sc, HDMI_VID_TIMING2,
- VID_VFP(vfp) | VID_HFP(hfp << dblscan));
- HDMI_WRITE(sc, HDMI_VID_TIMING3,
- VID_VSPW(vspw) | VID_HSPW(hspw << dblscan));
- val = TX_CLOCK_NORMAL;
- if (mode->flags & VID_PVSYNC)
- val |= VID_VSYNC_ACTSEL;
- if (mode->flags & VID_PHSYNC)
- val |= VID_HSYNC_ACTSEL;
- HDMI_WRITE(sc, HDMI_VID_TIMING4, val);
-
- /* This is an ordered list of infoframe packets that the HDMI
- * transmitter will send. Transmit packets in the following order:
- * 1. General control packet
- * 2. AVI infoframe
- * 3. Audio infoframe
- * There are 2 registers with 4 slots each. The list is terminated
- * with the special PKT_END marker.
- */
- HDMI_WRITE(sc, HDMI_PKTCTRL0,
- PKTCTRL_PACKET(0, PKT_GC) | PKTCTRL_PACKET(1, PKT_AVI) |
- PKTCTRL_PACKET(2, PKT_AI) | PKTCTRL_PACKET(3, PKT_END));
- HDMI_WRITE(sc, HDMI_PKTCTRL1, 0);
-
- /* Setup audio */
- a10hdmi_set_audiomode(dev, mode);
-
- return (0);
-}
-
-static int
-a10hdmi_enable(device_t dev, int onoff)
-{
- struct a10hdmi_softc *sc;
- uint32_t val;
-
- sc = device_get_softc(dev);
-
- /* Enable or disable video output */
- val = HDMI_READ(sc, HDMI_VID_CTRL);
- if (onoff)
- val |= VID_CTRL_VIDEO_EN;
- else
- val &= ~VID_CTRL_VIDEO_EN;
- HDMI_WRITE(sc, HDMI_VID_CTRL, val);
-
- return (0);
-}
-
-static device_method_t a10hdmi_methods[] = {
- /* Device interface */
- DEVMETHOD(device_probe, a10hdmi_probe),
- DEVMETHOD(device_attach, a10hdmi_attach),
-
- /* HDMI interface */
- DEVMETHOD(hdmi_get_edid, a10hdmi_get_edid),
- DEVMETHOD(hdmi_set_videomode, a10hdmi_set_videomode),
- DEVMETHOD(hdmi_enable, a10hdmi_enable),
-
- DEVMETHOD_END
-};
-
-static driver_t a10hdmi_driver = {
- "a10hdmi",
- a10hdmi_methods,
- sizeof(struct a10hdmi_softc),
-};
-
-DRIVER_MODULE(a10hdmi, simplebus, a10hdmi_driver, 0, 0);
-MODULE_VERSION(a10hdmi, 1);
diff --git a/sys/arm/allwinner/a10_hdmiaudio.c b/sys/arm/allwinner/a10_hdmiaudio.c
deleted file mode 100644
--- a/sys/arm/allwinner/a10_hdmiaudio.c
+++ /dev/null
@@ -1,435 +0,0 @@
-/*-
- * Copyright (c) 2016 Jared McNeill <jmcneill@invisible.ca>
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
- * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * $FreeBSD$
- */
-
-/*
- * Allwinner A10/A20 HDMI Audio
- */
-
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
-#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/bus.h>
-#include <sys/rman.h>
-#include <sys/condvar.h>
-#include <sys/kernel.h>
-#include <sys/module.h>
-
-#include <dev/sound/pcm/sound.h>
-#include <dev/sound/chip.h>
-
-#include <dev/ofw/ofw_bus.h>
-#include <dev/ofw/ofw_bus_subr.h>
-
-#include "sunxi_dma_if.h"
-#include "mixer_if.h"
-
-#define DRQTYPE_HDMIAUDIO 24
-#define DRQTYPE_SDRAM 1
-
-#define DMA_WIDTH 32
-#define DMA_BURST_LEN 8
-#define DDMA_BLKSIZE 32
-#define DDMA_WAIT_CYC 8
-
-#define DMABUF_MIN 4096
-#define DMABUF_DEFAULT 65536
-#define DMABUF_MAX 131072
-
-#define HDMI_SAMPLERATE 48000
-
-#define TX_FIFO 0x01c16400
-
-static uint32_t a10hdmiaudio_fmt[] = {
- SND_FORMAT(AFMT_S16_LE, 2, 0),
- 0
-};
-
-static struct pcmchan_caps a10hdmiaudio_pcaps = {
- HDMI_SAMPLERATE, HDMI_SAMPLERATE, a10hdmiaudio_fmt, 0
-};
-
-struct a10hdmiaudio_info;
-
-struct a10hdmiaudio_chinfo {
- struct snd_dbuf *buffer;
- struct pcm_channel *channel;
- struct a10hdmiaudio_info *parent;
- bus_dmamap_t dmamap;
- void *dmaaddr;
- bus_addr_t physaddr;
- device_t dmac;
- void *dmachan;
-
- int run;
- uint32_t pos;
- uint32_t blocksize;
-};
-
-struct a10hdmiaudio_info {
- device_t dev;
- struct mtx *lock;
- bus_dma_tag_t dmat;
- unsigned dmasize;
-
- struct a10hdmiaudio_chinfo play;
-};
-
-/*
- * Mixer interface
- */
-
-static int
-a10hdmiaudio_mixer_init(struct snd_mixer *m)
-{
- mix_setdevs(m, SOUND_MASK_PCM);
-
- return (0);
-}
-
-static int
-a10hdmiaudio_mixer_set(struct snd_mixer *m, unsigned dev, unsigned left,
- unsigned right)
-{
- return (-1);
-}
-
-static kobj_method_t a10hdmiaudio_mixer_methods[] = {
- KOBJMETHOD(mixer_init, a10hdmiaudio_mixer_init),
- KOBJMETHOD(mixer_set, a10hdmiaudio_mixer_set),
- KOBJMETHOD_END
-};
-MIXER_DECLARE(a10hdmiaudio_mixer);
-
-/*
- * Channel interface
- */
-
-static void
-a10hdmiaudio_dmamap_cb(void *arg, bus_dma_segment_t *segs, int nseg, int error)
-{
- struct a10hdmiaudio_chinfo *ch = arg;
-
- if (error != 0)
- return;
-
- ch->physaddr = segs[0].ds_addr;
-}
-
-static void
-a10hdmiaudio_transfer(struct a10hdmiaudio_chinfo *ch)
-{
- int error;
-
- error = SUNXI_DMA_TRANSFER(ch->dmac, ch->dmachan,
- ch->physaddr + ch->pos, TX_FIFO, ch->blocksize);
- if (error) {
- ch->run = 0;
- device_printf(ch->parent->dev, "DMA transfer failed: %d\n",
- error);
- }
-}
-
-static void
-a10hdmiaudio_dmaconfig(struct a10hdmiaudio_chinfo *ch)
-{
- struct sunxi_dma_config conf;
-
- memset(&conf, 0, sizeof(conf));
- conf.src_width = conf.dst_width = DMA_WIDTH;
- conf.src_burst_len = conf.dst_burst_len = DMA_BURST_LEN;
- conf.src_blksize = conf.dst_blksize = DDMA_BLKSIZE;
- conf.src_wait_cyc = conf.dst_wait_cyc = DDMA_WAIT_CYC;
- conf.src_drqtype = DRQTYPE_SDRAM;
- conf.dst_drqtype = DRQTYPE_HDMIAUDIO;
- conf.dst_noincr = true;
-
- SUNXI_DMA_SET_CONFIG(ch->dmac, ch->dmachan, &conf);
-}
-
-static void
-a10hdmiaudio_dmaintr(void *priv)
-{
- struct a10hdmiaudio_chinfo *ch = priv;
- unsigned bufsize;
-
- bufsize = sndbuf_getsize(ch->buffer);
-
- ch->pos += ch->blocksize;
- if (ch->pos >= bufsize)
- ch->pos -= bufsize;
-
- if (ch->run) {
- chn_intr(ch->channel);
- a10hdmiaudio_transfer(ch);
- }
-}
-
-static void
-a10hdmiaudio_start(struct a10hdmiaudio_chinfo *ch)
-{
- ch->pos = 0;
-
- /* Configure DMA channel */
- a10hdmiaudio_dmaconfig(ch);
-
- /* Start DMA transfer */
- a10hdmiaudio_transfer(ch);
-}
-
-static void
-a10hdmiaudio_stop(struct a10hdmiaudio_chinfo *ch)
-{
- /* Disable DMA channel */
- SUNXI_DMA_HALT(ch->dmac, ch->dmachan);
-}
-
-static void *
-a10hdmiaudio_chan_init(kobj_t obj, void *devinfo, struct snd_dbuf *b,
- struct pcm_channel *c, int dir)
-{
- struct a10hdmiaudio_info *sc = devinfo;
- struct a10hdmiaudio_chinfo *ch = &sc->play;
- int error;
-
- ch->parent = sc;
- ch->channel = c;
- ch->buffer = b;
-
- ch->dmac = devclass_get_device(devclass_find("a10dmac"), 0);
- if (ch->dmac == NULL) {
- device_printf(sc->dev, "cannot find DMA controller\n");
- return (NULL);
- }
- ch->dmachan = SUNXI_DMA_ALLOC(ch->dmac, true, a10hdmiaudio_dmaintr, ch);
- if (ch->dmachan == NULL) {
- device_printf(sc->dev, "cannot allocate DMA channel\n");
- return (NULL);
- }
-
- error = bus_dmamem_alloc(sc->dmat, &ch->dmaaddr,
- BUS_DMA_NOWAIT | BUS_DMA_COHERENT, &ch->dmamap);
- if (error != 0) {
- device_printf(sc->dev, "cannot allocate channel buffer\n");
- return (NULL);
- }
- error = bus_dmamap_load(sc->dmat, ch->dmamap, ch->dmaaddr,
- sc->dmasize, a10hdmiaudio_dmamap_cb, ch, BUS_DMA_NOWAIT);
- if (error != 0) {
- device_printf(sc->dev, "cannot load DMA map\n");
- return (NULL);
- }
- memset(ch->dmaaddr, 0, sc->dmasize);
-
- if (sndbuf_setup(ch->buffer, ch->dmaaddr, sc->dmasize) != 0) {
- device_printf(sc->dev, "cannot setup sndbuf\n");
- return (NULL);
- }
-
- return (ch);
-}
-
-static int
-a10hdmiaudio_chan_free(kobj_t obj, void *data)
-{
- struct a10hdmiaudio_chinfo *ch = data;
- struct a10hdmiaudio_info *sc = ch->parent;
-
- SUNXI_DMA_FREE(ch->dmac, ch->dmachan);
- bus_dmamap_unload(sc->dmat, ch->dmamap);
- bus_dmamem_free(sc->dmat, ch->dmaaddr, ch->dmamap);
-
- return (0);
-}
-
-static int
-a10hdmiaudio_chan_setformat(kobj_t obj, void *data, uint32_t format)
-{
- return (0);
-}
-
-static uint32_t
-a10hdmiaudio_chan_setspeed(kobj_t obj, void *data, uint32_t speed)
-{
- return (HDMI_SAMPLERATE);
-}
-
-static uint32_t
-a10hdmiaudio_chan_setblocksize(kobj_t obj, void *data, uint32_t blocksize)
-{
- struct a10hdmiaudio_chinfo *ch = data;
-
- ch->blocksize = blocksize & ~3;
-
- return (ch->blocksize);
-}
-
-static int
-a10hdmiaudio_chan_trigger(kobj_t obj, void *data, int go)
-{
- struct a10hdmiaudio_chinfo *ch = data;
- struct a10hdmiaudio_info *sc = ch->parent;
-
- if (!PCMTRIG_COMMON(go))
- return (0);
-
- snd_mtxlock(sc->lock);
- switch (go) {
- case PCMTRIG_START:
- ch->run = 1;
- a10hdmiaudio_start(ch);
- break;
- case PCMTRIG_STOP:
- case PCMTRIG_ABORT:
- ch->run = 0;
- a10hdmiaudio_stop(ch);
- break;
- default:
- break;
- }
- snd_mtxunlock(sc->lock);
-
- return (0);
-}
-
-static uint32_t
-a10hdmiaudio_chan_getptr(kobj_t obj, void *data)
-{
- struct a10hdmiaudio_chinfo *ch = data;
-
- return (ch->pos);
-}
-
-static struct pcmchan_caps *
-a10hdmiaudio_chan_getcaps(kobj_t obj, void *data)
-{
- return (&a10hdmiaudio_pcaps);
-}
-
-static kobj_method_t a10hdmiaudio_chan_methods[] = {
- KOBJMETHOD(channel_init, a10hdmiaudio_chan_init),
- KOBJMETHOD(channel_free, a10hdmiaudio_chan_free),
- KOBJMETHOD(channel_setformat, a10hdmiaudio_chan_setformat),
- KOBJMETHOD(channel_setspeed, a10hdmiaudio_chan_setspeed),
- KOBJMETHOD(channel_setblocksize, a10hdmiaudio_chan_setblocksize),
- KOBJMETHOD(channel_trigger, a10hdmiaudio_chan_trigger),
- KOBJMETHOD(channel_getptr, a10hdmiaudio_chan_getptr),
- KOBJMETHOD(channel_getcaps, a10hdmiaudio_chan_getcaps),
- KOBJMETHOD_END
-};
-CHANNEL_DECLARE(a10hdmiaudio_chan);
-
-/*
- * Device interface
- */
-
-static int
-a10hdmiaudio_probe(device_t dev)
-{
- if (!ofw_bus_status_okay(dev))
- return (ENXIO);
-
- if (!ofw_bus_is_compatible(dev, "allwinner,sun7i-a20-hdmiaudio"))
- return (ENXIO);
-
- device_set_desc(dev, "Allwinner HDMI Audio");
- return (BUS_PROBE_DEFAULT);
-}
-
-static int
-a10hdmiaudio_attach(device_t dev)
-{
- struct a10hdmiaudio_info *sc;
- char status[SND_STATUSLEN];
- int error;
-
- sc = malloc(sizeof(*sc), M_DEVBUF, M_WAITOK | M_ZERO);
- sc->dev = dev;
- sc->lock = snd_mtxcreate(device_get_nameunit(dev), "a10hdmiaudio softc");
-
- sc->dmasize = pcm_getbuffersize(dev, DMABUF_MIN,
- DMABUF_DEFAULT, DMABUF_MAX);
- error = bus_dma_tag_create(
- bus_get_dma_tag(dev),
- 4, sc->dmasize, /* alignment, boundary */
- BUS_SPACE_MAXADDR_32BIT, /* lowaddr */
- BUS_SPACE_MAXADDR, /* highaddr */
- NULL, NULL, /* filter, filterarg */
- sc->dmasize, 1, /* maxsize, nsegs */
- sc->dmasize, 0, /* maxsegsize, flags */
- NULL, NULL, /* lockfunc, lockarg */
- &sc->dmat);
- if (error != 0) {
- device_printf(dev, "cannot create DMA tag\n");
- goto fail;
- }
-
- if (mixer_init(dev, &a10hdmiaudio_mixer_class, sc)) {
- device_printf(dev, "mixer_init failed\n");
- goto fail;
- }
-
- pcm_setflags(dev, pcm_getflags(dev) | SD_F_MPSAFE);
- pcm_setflags(dev, pcm_getflags(dev) | SD_F_SOFTPCMVOL);
-
- if (pcm_register(dev, sc, 1, 0)) {
- device_printf(dev, "pcm_register failed\n");
- goto fail;
- }
-
- pcm_addchan(dev, PCMDIR_PLAY, &a10hdmiaudio_chan_class, sc);
-
- snprintf(status, SND_STATUSLEN, "at %s", ofw_bus_get_name(dev));
- pcm_setstatus(dev, status);
-
- return (0);
-
-fail:
- snd_mtxfree(sc->lock);
- free(sc, M_DEVBUF);
-
- return (error);
-}
-
-static device_method_t a10hdmiaudio_pcm_methods[] = {
- /* Device interface */
- DEVMETHOD(device_probe, a10hdmiaudio_probe),
- DEVMETHOD(device_attach, a10hdmiaudio_attach),
-
- DEVMETHOD_END
-};
-
-static driver_t a10hdmiaudio_pcm_driver = {
- "pcm",
- a10hdmiaudio_pcm_methods,
- PCM_SOFTC_SIZE,
-};
-
-DRIVER_MODULE(a10hdmiaudio, simplebus, a10hdmiaudio_pcm_driver, 0, 0);
-MODULE_DEPEND(a10hdmiaudio, sound, SOUND_MINVER, SOUND_PREFVER, SOUND_MAXVER);
-MODULE_VERSION(a10hdmiaudio, 1);

File Metadata

Mime Type
text/plain
Expires
Wed, Jul 22, 1:05 PM (44 m, 59 s)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
35364976
Default Alt Text
D39117.id119001.diff (48 KB)

Event Timeline