git: 37531e78df29 - main - arm: allwinner: Garbage collect a10_hdmi driver
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Fri, 17 Mar 2023 11:34:33 UTC
The branch main has been updated by manu: URL: https://cgit.FreeBSD.org/src/commit/?id=37531e78df291720c36641bd503b232187d40776 commit 37531e78df291720c36641bd503b232187d40776 Author: Emmanuel Vadot <manu@FreeBSD.org> AuthorDate: 2023-03-15 12:00:20 +0000 Commit: Emmanuel Vadot <manu@FreeBSD.org> CommitDate: 2023-03-17 12:34:40 +0000 arm: allwinner: Garbage collect a10_hdmi driver It was disconnected 5 years ago in 4573cd3914d7 ("arm: allwinner: Disconnect A10/A20 HDMI driver") as it wasn't working. Sponsored by: Beckhoff Automation GmbH & Co. KG Reviewed by: andrew Differential Revision: https://reviews.freebsd.org/D39117 --- sys/arm/allwinner/a10_fb.c | 660 ---------------------------------- sys/arm/allwinner/a10_hdmi.c | 723 -------------------------------------- sys/arm/allwinner/a10_hdmiaudio.c | 435 ----------------------- 3 files changed, 1818 deletions(-) diff --git a/sys/arm/allwinner/a10_fb.c b/sys/arm/allwinner/a10_fb.c deleted file mode 100644 index 387d5daa10c1..000000000000 --- 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 index ee57c07737de..000000000000 --- 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); *** 873 LINES SKIPPED ***