The following unfinished patch introduces the imxdisplay(4) driver aiming to add HDMI framebuffer support on the armv7/imx6 platform:
imxdisplay0 at simplebus0 imxdisplay0: 240x322 Currently it sets up rasops(9) and adds functions for handling/enabling the clocks and PLLs for the HDMI transmitter through the control module. Ian Index: sys/arch/armv7/conf/GENERIC =================================================================== RCS file: /cvs/src/sys/arch/armv7/conf/GENERIC,v retrieving revision 1.31 diff -u -p -r1.31 GENERIC --- sys/arch/armv7/conf/GENERIC 12 Jul 2016 19:17:49 -0000 1.31 +++ sys/arch/armv7/conf/GENERIC 1 Aug 2016 07:32:00 -0000 @@ -54,6 +54,8 @@ sdmmc* at imxesdhc? # SD/MMC bus imxahci* at fdt? # AHCI/SATA imxehci* at fdt? # EHCI usb* at imxehci? +imxdisplay* at fdt? # HDMI +wsdisplay* at imxdisplay? # OMAP3xxx/OMAP4xxx SoC omap0 at mainbus? Index: sys/arch/armv7/imx/files.imx =================================================================== RCS file: /cvs/src/sys/arch/armv7/imx/files.imx,v retrieving revision 1.15 diff -u -p -r1.15 files.imx --- sys/arch/armv7/imx/files.imx 12 Jul 2016 19:17:49 -0000 1.15 +++ sys/arch/armv7/imx/files.imx 1 Aug 2016 07:32:00 -0000 @@ -51,3 +51,8 @@ file arch/armv7/imx/imxesdhc.c imxesdhc device imxahci: scsi, atascsi attach imxahci at fdt file arch/armv7/imx/imxahci.c imxahci + +device imxdisplay: wsemuldisplaydev, rasops16 +attach imxdisplay at fdt +file arch/armv7/imx/imxdisplay.c imxdisplay + Index: sys/arch/armv7/imx/imxccm.c =================================================================== RCS file: /cvs/src/sys/arch/armv7/imx/imxccm.c,v retrieving revision 1.5 diff -u -p -r1.5 imxccm.c --- sys/arch/armv7/imx/imxccm.c 30 May 2015 08:09:19 -0000 1.5 +++ sys/arch/armv7/imx/imxccm.c 1 Aug 2016 07:32:00 -0000 @@ -75,6 +75,9 @@ #define CCM_ANALOG_PLL_USB2_SET 0x4024 #define CCM_ANALOG_PLL_USB2_CLR 0x4028 #define CCM_ANALOG_PLL_SYS 0x4030 +#define CCM_ANALOG_PLL_VIDEO 0x40A0 +#define CCM_ANALOG_PLL_VIDEO_SET 0x40A4 +#define CCM_ANALOG_PLL_VIDEO_CLR 0x40A8 #define CCM_ANALOG_USB1_CHRG_DETECT 0x41b0 #define CCM_ANALOG_USB1_CHRG_DETECT_SET 0x41b4 #define CCM_ANALOG_USB1_CHRG_DETECT_CLR 0x41b8 @@ -114,6 +117,8 @@ #define CCM_CSCDR1_UART_PODF_MASK 0x7 #define CCM_CCGR1_ENET (3 << 10) #define CCM_CCGR2_I2C(x) (3 << (6 + 2*x)) +#define CCM_CCGR2_HDMI_TX_ISFRCLK (3 << 4) +#define CCM_CCGR2_HDMI_TX_IAHBCLK (3 << 0) #define CCM_CCGR4_125M_PCIE (3 << 0) #define CCM_CCGR5_100M_SATA (3 << 4) #define CCM_CCGR6_USBOH3 (3 << 0) @@ -151,6 +156,10 @@ #define CCM_PMU_MISC1_LVDSCLK1_CLK_SEL_MASK (0x1f << 0) #define CCM_PMU_MISC1_LVDSCLK1_OBEN (1 << 10) #define CCM_PMU_MISC1_LVDSCLK1_IBEN (1 << 12) +#define CCM_ANALOG_PLL_VIDEO_ENABLE (1 << 13) +#define CCM_ANALOG_PLL_VIDEO_LOCK (1U << 31) +#define CCM_ANALOG_PLL_VIDEO_POWERDOWN (1 << 12) +#define CCM_ANALOG_PLL_VIDEO_BYPASS (1 << 16) #define HCLK_FREQ 24000 #define PLL3_80M 80000 @@ -220,9 +229,11 @@ void imxccm_disable_usb2_chrg_detect(voi void imxccm_enable_pll_usb1(void); void imxccm_enable_pll_usb2(void); void imxccm_enable_pll_enet(void); +void imxccm_enable_pll_video(void); void imxccm_enable_enet(void); void imxccm_enable_sata(void); void imxccm_enable_pcie(void); +void imxccm_enable_hdmi(void); struct cfattach imxccm_ca = { sizeof (struct imxccm_softc), NULL, imxccm_attach @@ -518,6 +529,23 @@ imxccm_enable_pll_enet(void) } void +imxccm_enable_pll_video(void) +{ + struct imxccm_softc *sc = imxccm_sc; + + if (HREAD4(sc, CCM_ANALOG_PLL_VIDEO) & CCM_ANALOG_PLL_VIDEO_ENABLE) + return; + + HCLR4(sc, CCM_ANALOG_PLL_VIDEO, CCM_ANALOG_PLL_VIDEO_POWERDOWN); + + HSET4(sc, CCM_ANALOG_PLL_VIDEO, CCM_ANALOG_PLL_VIDEO_ENABLE); + + while(!(HREAD4(sc, CCM_ANALOG_PLL_VIDEO) & CCM_ANALOG_PLL_VIDEO_LOCK)); + + HCLR4(sc, CCM_ANALOG_PLL_VIDEO, CCM_ANALOG_PLL_VIDEO_BYPASS); +} + +void imxccm_enable_enet(void) { struct imxccm_softc *sc = imxccm_sc; @@ -554,6 +582,16 @@ imxccm_enable_pcie(void) HWRITE4(sc, CCM_ANALOG_PLL_ENET_SET, CCM_ANALOG_PLL_ENET_125M_PCIE); HSET4(sc, CCM_CCGR4, CCM_CCGR4_125M_PCIE); +} + +void +imxccm_enable_hdmi(void) +{ + struct imxccm_softc *sc = imxccm_sc; + + imxccm_enable_pll_video(); + HSET4(sc, CCM_CCGR2, CCM_CCGR2_HDMI_TX_ISFRCLK); + HSET4(sc, CCM_CCGR2, CCM_CCGR2_HDMI_TX_IAHBCLK); } void Index: sys/arch/armv7/imx/imxccmvar.h =================================================================== RCS file: /cvs/src/sys/arch/armv7/imx/imxccmvar.h,v retrieving revision 1.2 diff -u -p -r1.2 imxccmvar.h --- sys/arch/armv7/imx/imxccmvar.h 30 May 2015 08:09:19 -0000 1.2 +++ sys/arch/armv7/imx/imxccmvar.h 1 Aug 2016 07:32:00 -0000 @@ -32,5 +32,6 @@ void imxccm_enable_pll_usb2(void); void imxccm_enable_enet(void); void imxccm_enable_sata(void); void imxccm_enable_pcie(void); +void imxccm_enable_hdmi(void); #endif /* IMXCCMVAR_H */ Index: sys/arch/armv7/imx/imxdisplay.c =================================================================== RCS file: sys/arch/armv7/imx/imxdisplay.c diff -N sys/arch/armv7/imx/imxdisplay.c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ sys/arch/armv7/imx/imxdisplay.c 1 Aug 2016 07:32:00 -0000 @@ -0,0 +1,243 @@ +/* + * Copyright (c) 2016 Ian Sutton <i...@kremlin.cc> + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/queue.h> +#include <sys/malloc.h> +#include <sys/device.h> +#include <sys/evcount.h> +#include <sys/conf.h> +#include <sys/uio.h> +#include <machine/bus.h> +#include <machine/fdt.h> + +#include <dev/cons.h> +#include <dev/wscons/wsconsio.h> +#include <dev/wscons/wsdisplayvar.h> +#include <dev/wscons/wscons_callbacks.h> +#include <dev/rasops/rasops.h> + +#include <dev/ofw/openfirm.h> +#include <dev/ofw/ofw_gpio.h> +#include <dev/ofw/fdt.h> + +struct imxdisplay_screen { + LIST_ENTRY(imxdisplay_screen) link; + + size_t buf_size; + size_t map_size; + void *buf_va; + int depth; + struct rasops_info rinfo; + +}; + +struct imxdisplay_softc { + struct device sc_dev; + bus_space_tag_t sc_iot; + bus_space_handle_t sc_ioh; + struct rasops_info *ro; +}; + +int imxdisplay_match(struct device *, void *, void *a); +void imxdisplay_attach(struct device *, struct device *, void *); +int imxdisplay_activate(struct device *, int); + +int imxdisplay_ioctl(void *, u_long, caddr_t, int, struct proc *); +int imxdisplay_alloc_screen(void *, const struct wsscreen_descr *, + void **, int *, int *, long *); +void imxdisplay_free_screen(void *, void *); +int imxdisplay_show_screen(void *, void *, int, + void (*)(void *, int, int), void *); +void imxdisplay_doswitch(void *, void *); +int imxdisplay_load_font(void *, void *, struct wsdisplay_font *); +int imxdisplay_list_font(void *, struct wsdisplay_font *); +int imxdisplay_getchar(void *, int, int, struct wsdisplay_charcell *); +void imxdisplay_burner(void *, u_int, u_int); +paddr_t imxdisplay_mmap(void *, off_t, int); + +void imxdisplay_setup_rasops(struct imxdisplay_softc *, struct rasops_info *); + +struct wsdisplay_accessops imxdisplay_accessops = { + .ioctl = imxdisplay_ioctl, + .mmap = imxdisplay_mmap, + .alloc_screen = imxdisplay_alloc_screen, + .free_screen = imxdisplay_free_screen, + .show_screen = imxdisplay_show_screen, + .getchar = imxdisplay_getchar, + .load_font = imxdisplay_load_font, + .list_font = imxdisplay_list_font, + .burn_screen = imxdisplay_burner +}; + +struct cfattach imxdisplay_ca = { + sizeof(struct imxdisplay_softc), imxdisplay_match, imxdisplay_attach, NULL, + imxdisplay_activate +}; + +struct cfdriver imxdisplay_cd = { + NULL, "imxdisplay", DV_DULL +}; + +struct rasops_info imxdisplay_ri; +struct wsscreen_descr imxdisplay_stdscreen = { + "std" +}; + +const struct wsscreen_descr *imxdisplay_scrlist[] = { + &imxdisplay_stdscreen, +}; + +struct wsscreen_list imxdisplay_screenlist = { + nitems(imxdisplay_scrlist), imxdisplay_scrlist +}; + +int +imxdisplay_match(struct device *parent, void *v, void *aux) +{ + struct fdt_attach_args *faa = aux; + return OF_is_compatible(faa->fa_node, "fsl,imx6q-hdmi"); +} + +void +imxdisplay_attach(struct device *parent, struct device *self, void *args) +{ + struct imxdisplay_softc *sc = (struct imxdisplay_softc *) self; + struct fdt_attach_args *faa = args; + struct wsemuldisplaydev_attach_args wsaa; + struct rasops_info *ri = &imxdisplay_ri; + + sc->sc_iot = faa->fa_iot; + if (bus_space_map(sc->sc_iot, faa->fa_reg[0].addr, + faa->fa_reg[1].size, 0, &sc->sc_ioh)) + panic("%s: bus_space_map failed!", __func__); + + printf("\n"); + + imxdisplay_setup_rasops(sc, ri); + sc->ro = ri; + + wsaa.console = 0; + wsaa.scrdata = &imxdisplay_screenlist; + wsaa.accessops = &imxdisplay_accessops; + wsaa.accesscookie = sc; + wsaa.defaultscreens = 0; + + printf("%s: %dx%d\n", sc->sc_dev.dv_xname, ri->ri_width, ri->ri_height); + + config_found(self, &wsaa, wsemuldisplaydevprint); +} + +void +imxdisplay_setup_rasops(struct imxdisplay_softc *sc, struct rasops_info *rinfo) +{ + /* XXX dummy data for now */ + rinfo->ri_depth = 16; + rinfo->ri_width = 240; + rinfo->ri_height = 322; + rinfo->ri_stride = 240 * 16; + + rasops_init(rinfo, 100, 100); +} + +int +imxdisplay_activate(struct device *self, int act) +{ + /* XXX */ + switch (act) { + case DVACT_SUSPEND: + break; + case DVACT_RESUME: + break; + } + + return 0; +} +int +imxdisplay_ioctl(void *sconf, u_long cmd, caddr_t data, int flat, struct proc *p) +{ + return -1; +} + +paddr_t +imxdisplay_mmap(void *sconf, off_t off, int prot) +{ + return -1; +} + +int +imxdisplay_alloc_screen(void *sconf, const struct wsscreen_descr *type, + void **cookiep, int *curxp, int *curyp, long *attrp) +{ + struct imxdisplay_softc *sc = sconf; + struct rasops_info *ri = sc->ro; + + return rasops_alloc_screen(ri, cookiep, curxp, curyp, attrp); +} + +void +imxdisplay_free_screen(void *sconf, void *cookie) +{ + struct imxdisplay_softc *sc = sconf; + struct rasops_info *ri = sc->ro; + + return rasops_free_screen(ri, cookie); +} + +int +imxdisplay_show_screen(void *sconf, void *cookie, int waitok, + void (*cb)(void *, int, int), void *cbarg) +{ + return (0); +} + +void +imxdisplay_doswitch(void *v, void *dummy) +{ +} + +int +imxdisplay_getchar(void *sconf, int row, int col, struct wsdisplay_charcell *cell) +{ + struct imxdisplay_softc *sc = sconf; + struct rasops_info *ri = sc->ro; + + return rasops_getchar(ri, row, col, cell); +} + +int +imxdisplay_load_font(void *sconf, void *cookie, struct wsdisplay_font *font) +{ + struct imxdisplay_softc *sc = sconf; + struct rasops_info *ri = sc->ro; + + return rasops_load_font(ri, cookie, font); +} + +int +imxdisplay_list_font(void *sconf, struct wsdisplay_font *font) +{ + struct imxdisplay_softc *sc = sconf; + struct rasops_info *ri = sc->ro; + + return rasops_list_font(ri, font); +} + +void +imxdisplay_burner(void *sconf, u_int on, u_int flags) +{ +}