Work continues on imxdisplay(4). New patch included below further
configures HDMI/IPU/DI clocks.

Ian

Index: conf/GENERIC
===================================================================
RCS file: /cvs/src/sys/arch/armv7/conf/GENERIC,v
retrieving revision 1.31
diff -u -p -r1.31 GENERIC
--- conf/GENERIC        12 Jul 2016 19:17:49 -0000      1.31
+++ conf/GENERIC        5 Aug 2016 06:50:24 -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?                 # IPU/HDMI
+wsdisplay*     at imxdisplay?
 
 # OMAP3xxx/OMAP4xxx SoC
 omap0          at mainbus?
Index: 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
--- imx/files.imx       12 Jul 2016 19:17:49 -0000      1.15
+++ imx/files.imx       5 Aug 2016 06:50:24 -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: 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
--- imx/imxccm.c        30 May 2015 08:09:19 -0000      1.5
+++ imx/imxccm.c        5 Aug 2016 06:50:24 -0000
@@ -75,6 +75,15 @@
 #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_PLL_VIDEO_NUM               0x40B0
+#define CCM_ANALOG_PLL_VIDEO_NUM_SET           0x40B4
+#define CCM_ANALOG_PLL_VIDEO_NUM_CLR           0x40B8
+#define CCM_ANALOG_PLL_VIDEO_DENOM             0x40C0
+#define CCM_ANALOG_PLL_VIDEO_DENOM_SET         0x40C4
+#define CCM_ANALOG_PLL_VIDEO_DENOM_CLR         0x40C8
 #define CCM_ANALOG_USB1_CHRG_DETECT            0x41b0
 #define CCM_ANALOG_USB1_CHRG_DETECT_SET                0x41b4
 #define CCM_ANALOG_USB1_CHRG_DETECT_CLR                0x41b8
@@ -108,12 +117,22 @@
 #define CCM_CBCMR_PERIPH_CLK2_SEL_MASK         0x3
 #define CCM_CBCMR_PRE_PERIPH_CLK_SEL_SHIFT     18
 #define CCM_CBCMR_PRE_PERIPH_CLK_SEL_MASK      0x3
+#define CCM_CHSCCDR_IPU1_DI0_PRE_CLK_SEL_MASK  (7 << 6)
+#define CCM_CHSCCDR_IPU1_DI0_PODF_MASK         (7 << 3)
+#define CCM_CHSCCDR_IPU1_DI0_CLK_SEL_MASK      (7 << 0)
+#define CCM_CHSCCDR_IPU1_DI0_PRE_CLK_SEL_SHIFT 6
+#define CCM_CHSCCDR_IPU1_DI0_PODF_SHIFT                3
+#define CCM_CHSCCDR_IPU1_DI0_CLK_SEL_SHIFT     0
 #define CCM_CSCDR1_USDHCx_CLK_SEL_SHIFT(x)     ((x) + 15)
 #define CCM_CSCDR1_USDHCx_CLK_SEL_MASK         0x1
 #define CCM_CSCDR1_USDHCx_PODF_MASK            0x7
 #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_CCGR3_IPU1_IPU_CLK_MASK            (3 << 0)
+#define CCM_CCGR3_IPU1_DI0_CLK_MASK            (3 << 2)
 #define CCM_CCGR4_125M_PCIE                    (3 << 0)
 #define CCM_CCGR5_100M_SATA                    (3 << 4)
 #define CCM_CCGR6_USBOH3                       (3 << 0)
@@ -151,6 +170,14 @@
 #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 CCM_ANALOG_PLL_VIDEO_DIV_SELECT                (127 << 0)
+#define CCM_ANALOG_PLL_VIDEO_POST_DIV_SELECT   (3 << 19)
+#define CCM_ANALOG_PLL_VIDEO_POST_DIV_SELECT_SHIFT     19
+
 
 #define HCLK_FREQ                              24000
 #define PLL3_80M                               80000
@@ -220,9 +247,12 @@ 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);
+void imxccm_enable_ipu(void);
 
 struct cfattach        imxccm_ca = {
        sizeof (struct imxccm_softc), NULL, imxccm_attach
@@ -518,6 +548,29 @@ imxccm_enable_pll_enet(void)
 }
 
 void
+imxccm_enable_pll_video(void)
+{
+       struct imxccm_softc *sc = imxccm_sc;
+
+       /*  Set PLL to 455MHz */
+       HSET4(sc, CCM_ANALOG_PLL_VIDEO, CCM_ANALOG_PLL_VIDEO_POWERDOWN);
+       HCLR4(sc, CCM_ANALOG_PLL_VIDEO, CCM_ANALOG_PLL_VIDEO_DIV_SELECT);
+       HSET4(sc, CCM_ANALOG_PLL_VIDEO, 0x25);
+       HCLR4(sc, CCM_ANALOG_PLL_VIDEO, CCM_ANALOG_PLL_VIDEO_POST_DIV_SELECT);
+       HSET4(sc, CCM_ANALOG_PLL_VIDEO, 0x01 << 
CCM_ANALOG_PLL_VIDEO_POST_DIV_SELECT_SHIFT);
+       HCLR4(sc, CCM_ANALOG_PLL_VIDEO_NUM, 0x3FFFFFFF);
+       HSET4(sc, CCM_ANALOG_PLL_VIDEO_NUM, 0xB);
+       HCLR4(sc, CCM_ANALOG_PLL_VIDEO_DENOM, 0x3FFFFFFF);
+       HSET4(sc, CCM_ANALOG_PLL_VIDEO_DENOM, 0xC);
+
+       HCLR4(sc, CCM_ANALOG_PLL_VIDEO, CCM_ANALOG_PLL_VIDEO_POWERDOWN);
+       while(!(HREAD4(sc, CCM_ANALOG_PLL_VIDEO) & CCM_ANALOG_PLL_VIDEO_LOCK));
+
+       HSET4(sc, CCM_ANALOG_PLL_VIDEO, CCM_ANALOG_PLL_VIDEO_ENABLE);
+       HCLR4(sc, CCM_ANALOG_PLL_VIDEO, CCM_ANALOG_PLL_VIDEO_BYPASS);
+}
+
+void
 imxccm_enable_enet(void)
 {
        struct imxccm_softc *sc = imxccm_sc;
@@ -554,6 +607,35 @@ 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_ipu();
+       imxccm_enable_pll_video();
+
+       /* Set display interface clock to 65MHz */
+       HCLR4(sc, CCM_CCGR2, CCM_CCGR3_IPU1_DI0_CLK_MASK);
+       HCLR4(sc, CCM_CHSCCDR, CCM_CHSCCDR_IPU1_DI0_PRE_CLK_SEL_MASK);
+       HCLR4(sc, CCM_CHSCCDR, CCM_CHSCCDR_IPU1_DI0_PODF_MASK);
+       HCLR4(sc, CCM_CHSCCDR, CCM_CHSCCDR_IPU1_DI0_CLK_SEL_MASK);
+       HSET4(sc, CCM_CHSCCDR, 0x2 << CCM_CHSCCDR_IPU1_DI0_PRE_CLK_SEL_SHIFT);
+       HSET4(sc, CCM_CHSCCDR, 0x6 << CCM_CHSCCDR_IPU1_DI0_PODF_SHIFT);
+       HSET4(sc, CCM_CCGR2, CCM_CCGR3_IPU1_DI0_CLK_MASK);
+
+       HSET4(sc, CCM_CCGR2, CCM_CCGR2_HDMI_TX_ISFRCLK);
+       HSET4(sc, CCM_CCGR2, CCM_CCGR2_HDMI_TX_IAHBCLK);
+}
+
+void
+imxccm_enable_ipu(void)
+{
+       struct imxccm_softc *sc = imxccm_sc;
+
+       HSET4(sc, CCM_CCGR3, CCM_CCGR3_IPU1_IPU_CLK_MASK);
 }
 
 void 
Index: 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
--- imx/imxccmvar.h     30 May 2015 08:09:19 -0000      1.2
+++ imx/imxccmvar.h     5 Aug 2016 06:50:24 -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: imx/imxdisplay.c
===================================================================
RCS file: imx/imxdisplay.c
diff -N imx/imxdisplay.c
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ imx/imxdisplay.c    5 Aug 2016 06:50:24 -0000
@@ -0,0 +1,239 @@
+/*
+ * 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 <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/fdt.h>
+
+#include <armv7/imx/imxccmvar.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__);
+
+       imxccm_enable_hdmi();
+
+       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)
+{
+}

Reply via email to