Work on amdisplay(4) continues uneventfully. It is very nearly complete,
just need to fix some DMA issues I am having trouble with.

Ian

Index: arch/armv7/conf/GENERIC
===================================================================
RCS file: /cvs/src/sys/arch/armv7/conf/GENERIC,v
retrieving revision 1.45
diff -u -p -r1.45 GENERIC
--- arch/armv7/conf/GENERIC     11 Aug 2016 04:33:06 -0000      1.45
+++ arch/armv7/conf/GENERIC     2 Sep 2016 05:12:54 -0000
@@ -70,6 +70,7 @@ omgpio*               at fdt?                 # user-visible 
GPIO p
 gpio*          at omgpio?
 tiiic*         at fdt?
 iic*           at tiiic?
+nxptda*                at iic?
 gptimer*       at omap?                # general purpose timers
 dmtimer*       at omap?                # am335x dual mode timers
 omusbtll*      at omap?
@@ -77,6 +78,7 @@ cpsw*         at fdt?
 com*           at fdt?                 # onboard uarts
 ommmc*         at fdt?                 # SD/MMC card controller
 sdmmc*         at ommmc?               # SD/MMC bus
+amdisplay*     at fdt?                 # LCD controller
 
 omehci*                at fdt?                 # EHCI
 usb*           at omehci?
Index: arch/armv7/omap/am335x_prcmreg.h
===================================================================
RCS file: /cvs/src/sys/arch/armv7/omap/am335x_prcmreg.h,v
retrieving revision 1.4
diff -u -p -r1.4 am335x_prcmreg.h
--- arch/armv7/omap/am335x_prcmreg.h    18 Mar 2014 07:34:17 -0000      1.4
+++ arch/armv7/omap/am335x_prcmreg.h    2 Sep 2016 05:06:06 -0000
@@ -20,6 +20,7 @@
 #define AM335X_CLKCTRL_MODULEMODE_MASK         0x00000003
 
 #define PRCM_AM335X_CM_PER             0x0000
+#define PRCM_AM335X_LCDC_CLKCTRL       0x0018
 #define PRCM_AM335X_USB0_CLKCTRL       0x001c
 #define PRCM_AM335X_TPTC0_CLKCTRL      0x0024
 #define PRCM_AM335X_MMC0_CLKCTRL       0x003c
@@ -38,6 +39,10 @@
 #define PRCM_AM335X_CM_WKUP            0x0400
 #define PRCM_AM335X_GPIO0_CLKCTRL      0x0408
 #define PRCM_AM335X_TIMER0_CLKCTRL     0x0410
+#define PRCM_AM335X_DISP_IDLEST                0x0448
+#define PRCM_AM335X_DISP_CLKSEL                0x0454
+#define PRCM_AM335X_DISP_CLKMODE       0x0498
+#define PRCM_AM335X_DISP_M2            0x04a4
 #define PRCM_AM335X_I2C0_CLKCTRL       0x04b8
 #define PRCM_AM335X_CM_DPLL            0x0500
 #define PRCM_AM335X_CLKSEL_TIMER2_CLK  0x0508
Index: arch/armv7/omap/amdisplay.c
===================================================================
RCS file: arch/armv7/omap/amdisplay.c
diff -N arch/armv7/omap/amdisplay.c
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ arch/armv7/omap/amdisplay.c 2 Sep 2016 05:06:06 -0000
@@ -0,0 +1,643 @@
+/*
+ * Copyright (c) 2016 Ian Sutton <[email protected]>
+ *
+ * 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/device.h>
+#include <sys/errno.h>
+#include <sys/malloc.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/videomode/videomode.h>
+#include <dev/videomode/edidvar.h>
+
+#include <dev/ofw/openfirm.h>
+#include <dev/ofw/fdt.h>
+#include <machine/fdt.h>
+
+#include <uvm/uvm_param.h>
+
+#include <armv7/omap/prcmvar.h>
+#include <armv7/omap/amdisplayreg.h>
+#include <armv7/omap/nxptdavar.h>
+
+#define DEVNAME(_s) ((_s)->sc_dev.dv_xname)
+
+#define HREAD4(sc, reg)                                                        
\
+       (bus_space_read_4((sc)->sc_iot, (sc)->sc_ioh, (reg)))
+#define HWRITE4(sc, reg, val)                                          \
+       bus_space_write_4((sc)->sc_iot, (sc)->sc_ioh, (reg), (val))
+#define HSET4(sc, reg, bits)                                           \
+       HWRITE4((sc), (reg), HREAD4((sc), (reg)) | (bits))
+#define HCLR4(sc, reg, bits)                                           \
+       HWRITE4((sc), (reg), HREAD4((sc), (reg)) & ~(bits))
+
+struct amdisplay_softc {
+       struct device           sc_dev;
+       bus_space_tag_t         sc_iot;
+       bus_space_handle_t      sc_ioh;
+       bus_dma_tag_t           sc_dmat;
+       void                    *sc_ih;
+
+       struct edid_info        *sc_edid;
+       struct videomode        *sc_active_mode;
+       int                     sc_active_depth;
+
+       bus_dmamap_t            sc_fb0_dma;
+//     bus_dmamap_t            sc_fb1_dma;
+       bus_dma_segment_t       sc_fb0_dma_segs[1];
+//     bus_dma_segment_t       sc_fb1_dma_segs[1];
+       void                    *sc_fb0;
+//     void                    *sc_fb1;
+       int                     sc_fb_dma_nsegs;
+       bus_size_t              sc_fb_size;
+
+       struct rasops_info      *sc_ro;
+};
+
+#if 0
+/* 
+ * Four scalers control the frequency of the pixel clock, which originates from
+ * the 24MHz crystal (on BBB), travels through the display PLL, and arrives at
+ * the LCDC. We seek to generate appropriate pixel clock freqs. by only
+ * manipulating 'd' as m1/m2/n are all controlled by prcm. See AM335x TRM for
+ * more details.
+ */
+struct amdisplay_scalars {
+       uint16_t m1; /* 2 <= m1 <= 2047 */
+       uint8_t  n;  /* 0 <= n  <= 127  */
+       uint8_t  m2; /* 1 <= m2 <= 31   */
+       uint8_t  d;  /* 2 <= d  <= 255  */
+};
+#endif
+
+struct wsscreen_descr amdisplay_stdscreen = {
+       "std"
+};
+
+const struct wsscreen_descr *amdisplay_scrlist[] = {
+       &amdisplay_stdscreen,
+};
+
+struct wsscreen_list amdisplay_screenlist = {
+       nitems(amdisplay_scrlist), amdisplay_scrlist
+};
+
+int  amdisplay_match(struct device *, void *, void *);
+void amdisplay_attach(struct device *, struct device *, void *);
+int  amdisplay_detach(struct device *, int);
+int  amdisplay_activate(struct device *, int);
+int  amdisplay_intr(void *);
+
+int  amdisplay_ioctl(void *, u_long, caddr_t, int, struct proc *);
+int  amdisplay_alloc_screen(void *, const struct wsscreen_descr *,
+       void **, int *, int *, long *);
+void amdisplay_free_screen(void *, void *);
+int  amdisplay_show_screen(void *, void *, int,
+       void (*)(void *, int, int), void *);
+void amdisplay_doswitch(void *, void *);
+int  amdisplay_load_font(void *, void *, struct wsdisplay_font *);
+int  amdisplay_list_font(void *, struct wsdisplay_font *);
+int  amdisplay_getchar(void *, int, int, struct wsdisplay_charcell *);
+void amdisplay_burner(void *, u_int, u_int);
+paddr_t amdisplay_mmap(void *, off_t, int);
+
+void amdisplay_setup_rasops(struct amdisplay_softc *);
+int  amdisplay_conf_dma(struct amdisplay_softc *);
+int  amdisplay_setup_dma(struct amdisplay_softc *);
+void amdisplay_conf_dev(struct amdisplay_softc *);
+
+struct wsdisplay_accessops amdisplay_accessops = {
+       .ioctl = amdisplay_ioctl,
+       .mmap = amdisplay_mmap,
+       .alloc_screen = amdisplay_alloc_screen,
+       .free_screen = amdisplay_free_screen,
+       .show_screen = amdisplay_show_screen,
+       .getchar = amdisplay_getchar,
+       .load_font = amdisplay_load_font,
+       .list_font = amdisplay_list_font,
+       .burn_screen = amdisplay_burner
+};
+
+struct cfattach amdisplay_ca = {
+       sizeof(struct amdisplay_softc), amdisplay_match, amdisplay_attach, 
amdisplay_detach
+};
+
+struct cfdriver amdisplay_cd = {
+       NULL, "amdisplay", DV_DULL
+};
+
+int
+amdisplay_match(struct device *parent, void *v, void *aux)
+{
+       struct fdt_attach_args *faa = aux;
+       return OF_is_compatible(faa->fa_node, "ti,am33xx-tilcdc");
+}
+
+void
+amdisplay_attach(struct device *parent, struct device *self, void *args)
+{
+       struct amdisplay_softc  *sc = (struct amdisplay_softc *) self;
+       struct fdt_attach_args  *faa = args;
+       struct wsemuldisplaydev_attach_args wsaa;
+       struct edid_info edid;
+
+       uint32_t irq, reg;
+       uint8_t *edid_buf;
+
+       int edid_valid;
+
+       sc->sc_iot  = faa->fa_iot;
+       sc->sc_dmat = faa->fa_dmat;
+       if (bus_space_map(sc->sc_iot, faa->fa_reg[0].addr,
+           faa->fa_reg[0].size, 0, &sc->sc_ioh))
+               panic("%s: bus_space_map failed!", __func__);
+
+       irq = faa->fa_intr[0];
+
+       prcm_enablemodule(PRCM_LCDC);
+
+       /* force ourselves out of standby/idle states */
+       reg = HREAD4(sc, AMDISPLAY_SYSCONFIG);
+       reg &= ~(AMDISPLAY_SYSCONFIG_STANDBYMODE_MASK | 
AMDISPLAY_SYSCONFIG_IDLEMODE_MASK);
+       reg |= (1 << AMDISPLAY_SYSCONFIG_STANDBYMODE_SHAMT);
+       reg |= (1 << AMDISPLAY_SYSCONFIG_IDLEMODE_SHAMT);
+       HWRITE4(sc, AMDISPLAY_SYSCONFIG, reg);
+
+       sc->sc_ih = arm_intr_establish(irq, IPL_BIO, amdisplay_intr, sc, 
DEVNAME(sc));
+
+       printf("\n");
+
+       /* read/parse EDID bits from TDA19988 HDMI PHY */
+       edid_buf = malloc(EDID_LENGTH, M_DEVBUF, M_WAITOK | M_ZERO);
+
+       if (nxptda_get_edid(edid_buf, EDID_LENGTH)) {
+           printf("%s: failed to read edid bits!\n", DEVNAME(sc));
+           amdisplay_detach(self, 0);
+           return;
+       }
+
+       if ((edid_valid = edid_is_valid(edid_buf))) {
+           printf("%s: invalid edid! :: %d\n", DEVNAME(sc), edid_valid);
+           amdisplay_detach(self, 0);
+           return;
+       }
+
+       edid_parse(edid_buf, &edid);
+       sc->sc_edid = &edid;
+       sc->sc_active_mode = sc->sc_edid->edid_preferred_mode;
+
+       prcm_setclock(3, 2 * sc->sc_active_mode->dot_clock);
+
+       sc->sc_active_depth = 24;
+
+       /* allocate DMA-able memory for framebuffers */
+       if (amdisplay_setup_dma(sc)) {
+           printf("%s: could not create framebuffer!\n", DEVNAME(sc));
+           return;
+       }
+
+       /* configure LCDDMA regs with newly allocated DMA mem */
+       if (amdisplay_conf_dma(sc)) {
+           printf("%s: failed to configure DMA registers!\n", DEVNAME(sc));
+           return;
+       }
+
+       /* configure device according to new parameters */
+       amdisplay_conf_dev(sc);
+
+       /* setup rasops object */
+       amdisplay_setup_rasops(sc);
+
+       /* enable all intrs. */
+       reg = 0;
+       reg |= (AMDISPLAY_IRQ_EOF1 | AMDISPLAY_IRQ_EOF0 | AMDISPLAY_IRQ_PL |
+           AMDISPLAY_IRQ_FUF | AMDISPLAY_IRQ_ACB | AMDISPLAY_IRQ_SYNC |
+           AMDISPLAY_IRQ_RR_DONE | AMDISPLAY_IRQ_DONE);
+       HWRITE4(sc, AMDISPLAY_IRQENABLE_SET, reg);
+
+       /* enable LCD controller */
+       HSET4(sc, AMDISPLAY_RASTER_CTRL, AMDISPLAY_RASTER_CTRL_LCDEN_MASK);
+
+       /* configure HDMI transmitter (TDA19988) with our mode details */
+       nxptda_set_videomode(sc->sc_active_mode);
+
+       wsaa.console = 0;
+       wsaa.scrdata = &amdisplay_screenlist;
+       wsaa.accessops = &amdisplay_accessops;
+       wsaa.accesscookie = sc;
+       wsaa.defaultscreens = 0;
+
+//     printf("%s: %dx%d\n", sc->sc_dev.dv_xname, sc->sc_ro->ri_width,
+//         sc->sc_ro->ri_height);
+
+//     config_found(self, &wsaa, wsemuldisplaydevprint);
+}
+
+int
+amdisplay_detach(struct device *self, int flags)
+{
+       struct amdisplay_softc *sc = (struct amdisplay_softc *)self;
+
+       if (sc->sc_ro)
+           free(sc->sc_ro, M_DEVBUF, sizeof(struct rasops_info));
+
+       if(sc->sc_edid)
+           free(sc->sc_edid, M_DEVBUF, sizeof(struct edid_info));
+
+       if (!sc->sc_fb0)
+           return 0;
+
+       bus_dmamap_sync(sc->sc_dmat, sc->sc_fb0_dma, 0, sc->sc_fb_size,
+           BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
+//     bus_dmamap_sync(sc->sc_dmat, sc->sc_fb1_dma, 0, sc->sc_fb_size,
+//         BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
+
+       bus_dmamap_unload(sc->sc_dmat, sc->sc_fb0_dma);
+//     bus_dmamap_unload(sc->sc_dmat, sc->sc_fb1_dma);
+
+       bus_dmamem_unmap(sc->sc_dmat, (caddr_t)(sc->sc_fb0), sc->sc_fb_size);
+//     bus_dmamem_unmap(sc->sc_dmat, (caddr_t)(sc->sc_fb1), sc->sc_fb_size);
+
+       bus_dmamem_free(sc->sc_dmat, sc->sc_fb0_dma_segs, sc->sc_fb_dma_nsegs);
+//     bus_dmamem_free(sc->sc_dmat, sc->sc_fb1_dma_segs, sc->sc_fb_dma_nsegs);
+
+       bus_dmamap_destroy(sc->sc_dmat, sc->sc_fb0_dma);
+//     bus_dmamap_destroy(sc->sc_dmat, sc->sc_fb1_dma);
+
+       return 0;
+}
+
+void
+amdisplay_setup_rasops(struct amdisplay_softc *sc)
+{
+       int stride;
+
+       stride = sc->sc_active_mode->hdisplay * sc->sc_active_depth;
+
+       if (!sc->sc_ro)
+           sc->sc_ro = (struct rasops_info *)malloc(sizeof(struct rasops_info),
+               M_DEVBUF, M_ZERO | M_WAITOK);
+
+       sc->sc_ro->ri_depth  = sc->sc_active_depth;
+       sc->sc_ro->ri_width  = sc->sc_active_mode->hdisplay;
+       sc->sc_ro->ri_height = sc->sc_active_mode->vdisplay;
+       sc->sc_ro->ri_stride = stride;
+       sc->sc_ro->ri_bits   = sc->sc_fb0;
+
+       rasops_init(sc->sc_ro, 100, 100);
+}
+
+int
+amdisplay_setup_dma(struct amdisplay_softc *sc)
+{
+       int dma_flags = BUS_DMA_NOWAIT;
+       struct videomode *mode = sc->sc_active_mode;
+       bus_size_t bsize;
+
+       /* height * width * linebytes */
+       bsize = round_page(mode->hdisplay * mode->vdisplay * 
(sc->sc_active_depth / 8));
+
+       sc->sc_fb_size = bsize;
+       sc->sc_fb_dma_nsegs = 1;
+
+       if (bus_dmamap_create(sc->sc_dmat, sc->sc_fb_size, sc->sc_fb_dma_nsegs,
+           sc->sc_fb_size, 0, dma_flags, &(sc->sc_fb0_dma)))
+               return -1;
+//     if (bus_dmamap_create(sc->sc_dmat, sc->sc_fb_size, sc->sc_fb_dma_nsegs,
+//         sc->sc_fb_size, 0, dma_flags, &(sc->sc_fb1_dma)))
+//             return -2;
+
+       /* XXX check alignment */
+       if (bus_dmamem_alloc(sc->sc_dmat, sc->sc_fb_size, 0x100000, 0,
+           sc->sc_fb0_dma_segs, 1, &(sc->sc_fb_dma_nsegs), dma_flags | 
BUS_DMA_COHERENT))
+               return -1;
+//     if (bus_dmamem_alloc(sc->sc_dmat, sc->sc_fb_size, 0x100000, 0,
+//         sc->sc_fb1_dma_segs, 1, &(sc->sc_fb_dma_nsegs), dma_flags))
+//             return -2;
+
+       if (bus_dmamem_map(sc->sc_dmat, sc->sc_fb0_dma_segs, 
sc->sc_fb_dma_nsegs,
+           sc->sc_fb_size, (caddr_t *)&(sc->sc_fb0), dma_flags | 
BUS_DMA_COHERENT))
+               return -1;
+//     if (bus_dmamem_map(sc->sc_dmat, sc->sc_fb1_dma_segs, 
sc->sc_fb_dma_nsegs,
+//         sc->sc_fb_size, (caddr_t *)&(sc->sc_fb1), dma_flags | 
BUS_DMA_COHERENT))
+//             return -2;
+
+       if (bus_dmamap_load(sc->sc_dmat, sc->sc_fb0_dma, sc->sc_fb0, bsize, 
NULL,
+           dma_flags))
+           return -3;
+//     if (bus_dmamap_load(sc->sc_dmat, sc->sc_fb1_dma, sc->sc_fb1, bsize, 
NULL,
+//         dma_flags))
+//         return -4;
+
+       memset(sc->sc_fb0, 0, bsize);
+//     memset(sc->sc_fb1, 0, bsize);
+
+       bus_dmamap_sync(sc->sc_dmat, sc->sc_fb0_dma, 0, bsize,
+           BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
+
+       return 0;
+}
+
+void
+amdisplay_conf_dev(struct amdisplay_softc *sc)
+{
+       int hsync_active, vsync_active;
+       uint32_t reg, hfp, hbp, hsw, vfp, vbp, vsw, width, height;
+       struct videomode *mode;
+
+       mode = sc->sc_active_mode;
+       hfp = mode->hsync_start - mode->hdisplay - 1;
+       hbp = mode->htotal - mode->hsync_end - 1;
+       hsw = mode->hsync_end - mode->hsync_start - 1;
+       vfp = mode->vsync_start - mode->vdisplay;
+       vbp = mode->vtotal - mode->vsync_end;
+       vsw = mode->vsync_end - mode->vsync_start;
+       width = mode->hdisplay;
+       height = mode->vdisplay;
+
+       if (mode->flags & VID_NHSYNC)
+           hsync_active = 1;
+       else
+           hsync_active = 0;
+
+       if (mode->flags & VID_NVSYNC)
+           vsync_active = 0;
+       else
+           vsync_active = 1;
+
+       /* make sure we are out of reset */
+       HCLR4(sc, AMDISPLAY_CLKC_RESET, AMDISPLAY_CLKC_RESET_MAIN_RST_MASK |
+           AMDISPLAY_CLKC_RESET_DMA_RST_MASK | 
AMDISPLAY_CLKC_RESET_CORE_RST_MASK);
+
+       /* set module clock divider */
+       reg = HREAD4(sc, AMDISPLAY_CTRL);
+       reg &= ~AMDISPLAY_CTRL_CLKDIV_MASK;
+       reg |= (0x2 << AMDISPLAY_CTRL_CLKDIV_SHAMT);
+
+       /* select raster mode */
+       reg |= AMDISPLAY_CTRL_MODESEL_MASK;
+       HWRITE4(sc, AMDISPLAY_CTRL, reg);
+
+       /* enable dma & core clocks */
+       HSET4(sc, AMDISPLAY_CLKC_ENABLE, AMDISPLAY_CLKC_ENABLE_DMA_CLK_EN_MASK
+           | AMDISPLAY_CLKC_ENABLE_CORE_CLK_EN_MASK
+           | AMDISPLAY_CLKC_ENABLE_LIDD_CLK_EN_MASK);
+
+       /* set raster options */
+       reg = HREAD4(sc, AMDISPLAY_RASTER_CTRL);
+       reg &= ~AMDISPLAY_RASTER_CTRL_TFT24UNPACKED_MASK;
+       reg &= ~AMDISPLAY_RASTER_CTRL_TFT24_MASK;
+       reg &= ~AMDISPLAY_RASTER_CTRL_TFTMAP_MASK;
+       reg &= ~AMDISPLAY_RASTER_CTRL_NIBMODE_MASK;
+       reg &= ~AMDISPLAY_RASTER_CTRL_PALMODE_MASK;
+       reg &= ~AMDISPLAY_RASTER_CTRL_REQDLY_MASK;
+       reg &= ~AMDISPLAY_RASTER_CTRL_LCDTFT_MASK;
+       reg &= ~AMDISPLAY_RASTER_CTRL_LCDEN_MASK;
+       reg |= AMDISPLAY_RASTER_CTRL_TFT24UNPACKED_MASK;
+       reg |= AMDISPLAY_RASTER_CTRL_TFT24_MASK;
+       //reg |= AMDISPLAY_RASTER_CTRL_TFTMAP_MASK;
+       reg |= (0x2 << AMDISPLAY_RASTER_CTRL_PALMODE_SHAMT);
+       //reg |= (0xff << AMDISPLAY_RASTER_CTRL_REQDLY_SHAMT);
+       reg |= AMDISPLAY_RASTER_CTRL_LCDTFT_MASK;
+       HWRITE4(sc, AMDISPLAY_RASTER_CTRL, reg);
+
+       /* XXX */
+       reg = HREAD4(sc, AMDISPLAY_RASTER_CTRL);
+       printf("ctrl: 0x%08x\n", reg);
+
+       /* set crt timings */
+       reg = HREAD4(sc, AMDISPLAY_RASTER_TIMING_0);
+       reg &= ~AMDISPLAY_RASTER_TIMING_0_HBP_MASK;
+       reg &= ~AMDISPLAY_RASTER_TIMING_0_HFP_MASK;
+       reg &= ~AMDISPLAY_RASTER_TIMING_0_HSW_MASK;
+       reg &= ~AMDISPLAY_RASTER_TIMING_0_PPLLSB_MASK;
+       reg &= ~AMDISPLAY_RASTER_TIMING_0_PPLMSB_MASK;
+       reg |= ((hbp & 0xff) << AMDISPLAY_RASTER_TIMING_0_HBP_SHAMT);
+       reg |= ((hfp & 0xff) << AMDISPLAY_RASTER_TIMING_0_HFP_SHAMT);
+       reg |= ((hsw & 0x3f) << AMDISPLAY_RASTER_TIMING_0_HSW_SHAMT);
+       reg |= (((width >> 4) & 0x3f) << 
AMDISPLAY_RASTER_TIMING_0_PPLLSB_SHAMT);
+       reg |= (((width >> 10) & 1)  << AMDISPLAY_RASTER_TIMING_0_PPLMSB_SHAMT);
+       HWRITE4(sc, AMDISPLAY_RASTER_TIMING_0, reg);
+
+       /* XXX */
+       reg = HREAD4(sc, AMDISPLAY_RASTER_TIMING_0);
+       printf("timing0: 0x%08x\n", reg);
+
+       reg = 0;
+       reg |= ((vbp & 0xff) << AMDISPLAY_RASTER_TIMING_1_VBP_SHAMT);
+       reg |= ((vfp & 0xff) << AMDISPLAY_RASTER_TIMING_1_VFP_SHAMT);
+       reg |= ((vsw & 0x3f) << AMDISPLAY_RASTER_TIMING_1_VSW_SHAMT);
+       reg |= (height & 0x3ff);
+       HWRITE4(sc, AMDISPLAY_RASTER_TIMING_1, reg);
+
+       /* XXX */
+       reg = HREAD4(sc, AMDISPLAY_RASTER_TIMING_1);
+       printf("timing1: 0x%08x\n", reg);
+
+       reg = HREAD4(sc, AMDISPLAY_RASTER_TIMING_2);
+       reg &= ~AMDISPLAY_RASTER_TIMING_2_HSW_HIGHBITS_MASK;
+       reg &= ~AMDISPLAY_RASTER_TIMING_2_LPP_B10_MASK;
+       reg &= ~AMDISPLAY_RASTER_TIMING_2_PHSVS_ON_OFF_MASK;
+       reg &= ~AMDISPLAY_RASTER_TIMING_2_PHSVS_RF_MASK;
+       reg &= ~AMDISPLAY_RASTER_TIMING_2_IEO_MASK;
+       reg &= ~AMDISPLAY_RASTER_TIMING_2_IPC_MASK;
+       reg &= ~AMDISPLAY_RASTER_TIMING_2_IHS_MASK;
+       reg &= ~AMDISPLAY_RASTER_TIMING_2_IVS_MASK;
+       reg &= ~AMDISPLAY_RASTER_TIMING_2_ACBI_MASK;
+       reg &= ~AMDISPLAY_RASTER_TIMING_2_ACB_MASK;
+       reg &= ~AMDISPLAY_RASTER_TIMING_2_HBP_HIGHBITS_MASK;
+       reg &= ~AMDISPLAY_RASTER_TIMING_2_HFP_HIGHBITS_MASK;
+       reg |= (((hsw >> 6) & 0xf) << 
AMDISPLAY_RASTER_TIMING_2_HSW_HIGHBITS_SHAMT);
+       reg |= AMDISPLAY_RASTER_TIMING_2_PHSVS_ON_OFF_MASK;
+       if (hsync_active == 0)
+           reg |= AMDISPLAY_RASTER_TIMING_2_IHS_MASK;
+       if (vsync_active == 0)
+           reg |= AMDISPLAY_RASTER_TIMING_2_IVS_MASK;
+       reg |= (255 << AMDISPLAY_RASTER_TIMING_2_ACBI_SHAMT);
+       HWRITE4(sc, AMDISPLAY_RASTER_TIMING_2, reg);
+
+       /* XXX */
+       reg = HREAD4(sc, AMDISPLAY_RASTER_TIMING_2);
+       printf("timing2: 0x%08x\n", reg);
+}
+
+int
+amdisplay_conf_dma(struct amdisplay_softc *sc)
+{
+       uint32_t reg, fb0_base, fb0_ceil; 
+       int ret = 0;
+
+       fb0_base = sc->sc_fb0_dma_segs[0].ds_addr;
+       fb0_ceil = (sc->sc_fb0_dma_segs[0].ds_len + fb0_base) - 1;
+//     fb1_base = sc->sc_fb1_dma_segs[0].ds_addr;
+//     fb1_ceil = (sc->sc_fb1_dma_segs[0].ds_len + fb1_base) - 1;
+
+       reg = HREAD4(sc, AMDISPLAY_LCDDMA_CTRL);
+       reg &= ~AMDISPLAY_LCDDMA_CTRL_DMA_MASTER_PRIO_MASK;
+       reg &= ~AMDISPLAY_LCDDMA_CTRL_TH_FIFO_READY_MASK;
+       reg &= ~AMDISPLAY_LCDDMA_CTRL_BURST_SIZE_MASK;
+       reg &= ~AMDISPLAY_LCDDMA_CTRL_BYTE_SWAP_MASK;
+       reg &= ~AMDISPLAY_LCDDMA_CTRL_BIGENDIAN_MASK;
+       reg &= ~AMDISPLAY_LCDDMA_CTRL_FRAME_MODE_MASK;
+       reg |= (0x0 << AMDISPLAY_LCDDMA_CTRL_TH_FIFO_READY_SHAMT);
+       reg |= (0x4 << AMDISPLAY_LCDDMA_CTRL_BURST_SIZE_SHAMT);
+       reg |= AMDISPLAY_LCDDMA_CTRL_FRAME_MODE_MASK;
+       HWRITE4(sc, AMDISPLAY_LCDDMA_CTRL, reg);
+
+       reg = HREAD4(sc, AMDISPLAY_LCDDMA_FB0_BASE);
+       reg &= ~AMDISPLAY_LCDDMA_FB0_BASE_MASK;
+       reg |= (fb0_base << AMDISPLAY_LCDDMA_FB0_BASE_SHAMT);
+       HWRITE4(sc, AMDISPLAY_LCDDMA_FB0_BASE, reg);
+
+       reg = HREAD4(sc, AMDISPLAY_LCDDMA_FB0_CEILING);
+       reg &= ~AMDISPLAY_LCDDMA_FB0_CEILING_MASK;
+       reg |= (fb0_ceil << AMDISPLAY_LCDDMA_FB0_CEILING_SHAMT);
+       HWRITE4(sc, AMDISPLAY_LCDDMA_FB0_CEILING, reg);
+
+       reg = HREAD4(sc, AMDISPLAY_LCDDMA_FB1_BASE);
+       reg &= ~AMDISPLAY_LCDDMA_FB1_BASE_MASK;
+       reg |= (fb0_base << AMDISPLAY_LCDDMA_FB1_BASE_SHAMT);
+       HWRITE4(sc, AMDISPLAY_LCDDMA_FB1_BASE, reg);
+
+       reg = HREAD4(sc, AMDISPLAY_LCDDMA_FB1_CEILING);
+       reg &= ~AMDISPLAY_LCDDMA_FB1_CEILING_MASK;
+       reg |= (fb0_ceil << AMDISPLAY_LCDDMA_FB1_CEILING_SHAMT);
+       HWRITE4(sc, AMDISPLAY_LCDDMA_FB1_CEILING, reg);
+
+       return ret;
+}
+
+int
+amdisplay_intr(void *arg)
+{
+       uint32_t reg, fb0_base, fb0_ceil;
+       struct amdisplay_softc *sc;
+
+       sc = arg;
+       reg = HREAD4(sc, AMDISPLAY_IRQSTATUS);
+       HWRITE4(sc, AMDISPLAY_IRQSTATUS, reg);
+
+       fb0_base = sc->sc_fb0_dma_segs[0].ds_addr;
+       fb0_ceil = (sc->sc_fb0_dma_segs[0].ds_len + fb0_base) - 1;
+
+       if (reg & AMDISPLAY_IRQ_EOF0) {
+           HWRITE4(sc, AMDISPLAY_LCDDMA_FB0_BASE,
+               fb0_base << AMDISPLAY_LCDDMA_FB0_BASE_SHAMT);
+           HWRITE4(sc, AMDISPLAY_LCDDMA_FB0_CEILING,
+               fb0_ceil << AMDISPLAY_LCDDMA_FB0_CEILING_SHAMT);
+       } if (reg & AMDISPLAY_IRQ_EOF1) {
+           HWRITE4(sc, AMDISPLAY_LCDDMA_FB0_BASE,
+               fb0_base << AMDISPLAY_LCDDMA_FB0_BASE_SHAMT);
+           HWRITE4(sc, AMDISPLAY_LCDDMA_FB0_CEILING,
+               fb0_ceil << AMDISPLAY_LCDDMA_FB0_CEILING_SHAMT);
+       } if (reg & AMDISPLAY_IRQ_SYNC) {
+           HCLR4(sc, AMDISPLAY_RASTER_CTRL, AMDISPLAY_RASTER_CTRL_LCDEN_MASK);
+//         delay(100);
+           HSET4(sc, AMDISPLAY_RASTER_CTRL, AMDISPLAY_RASTER_CTRL_LCDEN_MASK);
+       }
+
+       /* XXX */
+       if (reg & AMDISPLAY_IRQ_FUF)
+           printf("%s: underflow!\n", DEVNAME(sc));
+       if (reg & AMDISPLAY_IRQ_PL)
+           printf("%s: pallete loaded!?\n", DEVNAME(sc));
+       if (reg & AMDISPLAY_IRQ_SYNC)
+           printf("%s: sync lost!\n", DEVNAME(sc));
+       if (reg & AMDISPLAY_IRQ_EOF0)
+           printf("%s: eof :)\n", DEVNAME(sc));
+
+       return 0;
+}
+
+int
+amdisplay_ioctl(void *sconf, u_long cmd, caddr_t data, int flat, struct proc 
*p)
+{
+       return -1;
+}
+
+paddr_t
+amdisplay_mmap(void *sconf, off_t off, int prot)
+{
+       return -1;
+}
+
+int
+amdisplay_alloc_screen(void *sconf, const struct wsscreen_descr *type,
+       void **cookiep, int *curxp, int *curyp, long *attrp)
+{
+       struct amdisplay_softc *sc = sconf;
+       struct rasops_info *ri = sc->sc_ro;
+
+       return rasops_alloc_screen(ri, cookiep, curxp, curyp, attrp);
+}
+
+void
+amdisplay_free_screen(void *sconf, void *cookie)
+{
+       struct amdisplay_softc *sc = sconf;
+       struct rasops_info *ri = sc->sc_ro;
+
+       return rasops_free_screen(ri, cookie);
+}
+
+int
+amdisplay_show_screen(void *sconf, void *cookie, int waitok,
+       void (*cb)(void *, int, int), void *cbarg)
+{
+       return (0);
+}
+
+void
+amdisplay_doswitch(void *v, void *dummy)
+{
+}
+
+int
+amdisplay_getchar(void *sconf, int row, int col, struct wsdisplay_charcell 
*cell)
+{
+       struct amdisplay_softc *sc = sconf;
+       struct rasops_info *ri = sc->sc_ro;
+
+       return rasops_getchar(ri, row, col, cell);
+}
+
+int
+amdisplay_load_font(void *sconf, void *cookie, struct wsdisplay_font *font)
+{
+       struct amdisplay_softc *sc = sconf;
+       struct rasops_info *ri = sc->sc_ro;
+
+       return rasops_load_font(ri, cookie, font);
+}
+
+int
+amdisplay_list_font(void *sconf, struct wsdisplay_font *font)
+{
+       struct amdisplay_softc *sc = sconf;
+       struct rasops_info *ri = sc->sc_ro;
+
+       return rasops_list_font(ri, font);
+}
+
+void
+amdisplay_burner(void *sconf, u_int on, u_int flags)
+{
+}
Index: arch/armv7/omap/amdisplayreg.h
===================================================================
RCS file: arch/armv7/omap/amdisplayreg.h
diff -N arch/armv7/omap/amdisplayreg.h
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ arch/armv7/omap/amdisplayreg.h      2 Sep 2016 05:06:06 -0000
@@ -0,0 +1,140 @@
+/*
+ * Copyright (c) 2016 Ian Sutton <[email protected]>
+ *
+ * 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.
+ */
+
+/* AM335x LCDC register offsets */
+#define AMDISPLAY_PID                  0x00
+#define AMDISPLAY_CTRL                 0x04
+#define   AMDISPLAY_CTRL_CLKDIV_MASK           (0xFF << 8)
+#define   AMDISPLAY_CTRL_MODESEL_MASK          (1 << 0)
+#define   AMDISPLAY_CTRL_CLKDIV_SHAMT          8
+#define AMDISPLAY_RASTER_CTRL          0x28
+#define   AMDISPLAY_RASTER_CTRL_TFT24UNPACKED_MASK     (1 << 26)
+#define   AMDISPLAY_RASTER_CTRL_TFT24_MASK             (1 << 25)
+#define   AMDISPLAY_RASTER_CTRL_TFTMAP_MASK            (1 << 23)
+#define   AMDISPLAY_RASTER_CTRL_NIBMODE_MASK           (1 << 22)
+#define   AMDISPLAY_RASTER_CTRL_PALMODE_MASK           (3 << 20)
+#define   AMDISPLAY_RASTER_CTRL_REQDLY_MASK            (0xFF << 12)
+#define   AMDISPLAY_RASTER_CTRL_LCDTFT_MASK            (1 << 7)
+#define   AMDISPLAY_RASTER_CTRL_LCDEN_MASK             (1 << 0)
+#define   AMDISPLAY_RASTER_CTRL_PALMODE_SHAMT          20
+#define   AMDISPLAY_RASTER_CTRL_REQDLY_SHAMT           12
+#define AMDISPLAY_RASTER_TIMING_0      0x2C
+#define   AMDISPLAY_RASTER_TIMING_0_HBP_MASK           (0xFF << 24)
+#define   AMDISPLAY_RASTER_TIMING_0_HFP_MASK           (0xFF << 16)
+#define   AMDISPLAY_RASTER_TIMING_0_HSW_MASK           (0x3F << 10)
+#define   AMDISPLAY_RASTER_TIMING_0_PPLLSB_MASK                (0x3  <<  4)
+#define   AMDISPLAY_RASTER_TIMING_0_PPLMSB_MASK                (0x1  <<  3)
+#define   AMDISPLAY_RASTER_TIMING_0_HBP_SHAMT          24
+#define   AMDISPLAY_RASTER_TIMING_0_HFP_SHAMT          16
+#define   AMDISPLAY_RASTER_TIMING_0_HSW_SHAMT          10
+#define   AMDISPLAY_RASTER_TIMING_0_PPLLSB_SHAMT       4
+#define   AMDISPLAY_RASTER_TIMING_0_PPLMSB_SHAMT       3
+#define AMDISPLAY_RASTER_TIMING_1      0x30
+#define   AMDISPLAY_RASTER_TIMING_1_VBP_MASK           (0xFF  << 24)
+#define   AMDISPLAY_RASTER_TIMING_1_VFP_MASK           (0xFF  << 16)
+#define   AMDISPLAY_RASTER_TIMING_1_VSW_MASK           (0x3C  << 10)
+#define   AMDISPLAY_RASTER_TIMING_1_LPP_MASK           (0x3FF <<  0)
+#define   AMDISPLAY_RASTER_TIMING_1_VBP_SHAMT          24
+#define   AMDISPLAY_RASTER_TIMING_1_VFP_SHAMT          16
+#define   AMDISPLAY_RASTER_TIMING_1_VSW_SHAMT          10
+#define AMDISPLAY_RASTER_TIMING_2      0x34
+#define   AMDISPLAY_RASTER_TIMING_2_HSW_HIGHBITS_MASK  (0xF  << 27)
+#define   AMDISPLAY_RASTER_TIMING_2_LPP_B10_MASK       (0x1  << 26)
+#define   AMDISPLAY_RASTER_TIMING_2_PHSVS_ON_OFF_MASK  (0x1  << 25)
+#define   AMDISPLAY_RASTER_TIMING_2_PHSVS_RF_MASK      (0x1  << 24)
+#define   AMDISPLAY_RASTER_TIMING_2_IEO_MASK           (0x1  << 23)
+#define   AMDISPLAY_RASTER_TIMING_2_IPC_MASK           (0x1  << 22)
+#define   AMDISPLAY_RASTER_TIMING_2_IHS_MASK           (0x1  << 21)
+#define   AMDISPLAY_RASTER_TIMING_2_IVS_MASK           (0x1  << 20)
+#define   AMDISPLAY_RASTER_TIMING_2_ACBI_MASK          (0xF  << 16)
+#define   AMDISPLAY_RASTER_TIMING_2_ACB_MASK           (0xFF <<  8)
+#define   AMDISPLAY_RASTER_TIMING_2_HBP_HIGHBITS_MASK  (0x3  <<  4)
+#define   AMDISPLAY_RASTER_TIMING_2_HFP_HIGHBITS_MASK  (0x3  <<  0)
+#define   AMDISPLAY_RASTER_TIMING_2_HSW_HIGHBITS_SHAMT 27
+#define   AMDISPLAY_RASTER_TIMING_2_ACBI_SHAMT         16
+#define   AMDISPLAY_RASTER_TIMING_2_ACB_SHAMT          8
+#define   AMDISPLAY_RASTER_TIMING_2_HPB_HIGHBITS_SHAMT 4
+#define AMDISPLAY_RASTER_SUBPANEL      0x38
+#define   AMDISPLAY_RASTER_SUBPANEL_SPEN_MASK  (0x1    << 31)
+#define   AMDISPLAY_RASTER_SUBPANEL_HOLS_MASK  (0x1    << 29)
+#define   AMDISPLAY_RASTER_SUBPANEL_LPPT_MASK  (0x2FF  << 16)
+#define   AMDISPLAY_RASTER_SUBPANEL_DPDLSB_MASK        (0xFFFF <<  0)
+#define   AMDISPLAY_RASTER_SUBPANEL_LPPT_SHAMT 
+#define AMDISPLAY_RASTER_SUBPANEL_2    0x3C
+#define   AMDISPLAY_RASTER_SUBPANEL2_LPPT_B10_MASK     (0x1  << 8)
+#define   AMDISPLAY_RASTER_SUBPANEL2_DPDMSB_MASK       (0xFF << 0)
+#define AMDISPLAY_LCDDMA_CTRL          0x40
+#define   AMDISPLAY_LCDDMA_CTRL_DMA_MASTER_PRIO_MASK   (0x7 << 0x10)
+#define   AMDISPLAY_LCDDMA_CTRL_TH_FIFO_READY_MASK     (0x7 << 0x08)
+#define   AMDISPLAY_LCDDMA_CTRL_BURST_SIZE_MASK                (0x7 << 0x04)
+#define   AMDISPLAY_LCDDMA_CTRL_BYTE_SWAP_MASK         (0x1 << 0x03)
+#define   AMDISPLAY_LCDDMA_CTRL_BIGENDIAN_MASK         (0x1 << 0x01)
+#define   AMDISPLAY_LCDDMA_CTRL_FRAME_MODE_MASK                (0x1 << 0x00)
+#define   AMDISPLAY_LCDDMA_CTRL_DMA_MASTER_PRIO_SHAMT  0xFF
+#define   AMDISPLAY_LCDDMA_CTRL_TH_FIFO_READY_SHAMT    0x0F
+#define   AMDISPLAY_LCDDMA_CTRL_BURST_SIZE_SHAMT       0x04
+#define AMDISPLAY_LCDDMA_FB0_BASE      0x44
+#define   AMDISPLAY_LCDDMA_FB0_BASE_MASK       0xFFFC
+#define   AMDISPLAY_LCDDMA_FB0_BASE_SHAMT      2
+#define AMDISPLAY_LCDDMA_FB0_CEILING   0x48
+#define   AMDISPLAY_LCDDMA_FB0_CEILING_MASK    0xFFFC
+#define   AMDISPLAY_LCDDMA_FB0_CEILING_SHAMT   2
+#define AMDISPLAY_LCDDMA_FB1_BASE      0x4C
+#define   AMDISPLAY_LCDDMA_FB1_BASE_MASK       0xFFFC
+#define   AMDISPLAY_LCDDMA_FB1_BASE_SHAMT      2
+#define AMDISPLAY_LCDDMA_FB1_CEILING   0x50
+#define   AMDISPLAY_LCDDMA_FB1_CEILING_MASK    0xFFFC
+#define   AMDISPLAY_LCDDMA_FB1_CEILING_SHAMT   2
+#define AMDISPLAY_SYSCONFIG            0x54
+#define   AMDISPLAY_SYSCONFIG_STANDBYMODE_MASK         (3 << 4)
+#define   AMDISPLAY_SYSCONFIG_IDLEMODE_MASK            (3 << 2)
+#define   AMDISPLAY_SYSCONFIG_STANDBYMODE_SHAMT                4
+#define   AMDISPLAY_SYSCONFIG_IDLEMODE_SHAMT           2
+#define AMDISPLAY_IRQSTATUS_RAW                0x58
+#define AMDISPLAY_IRQSTATUS            0x5C
+#define AMDISPLAY_IRQENABLE_SET                0x60
+#define AMDISPLAY_IRQENABLE_CLEAR      0x64
+#define AMDISPLAY_CLKC_ENABLE          0x6C
+#define   AMDISPLAY_CLKC_ENABLE_DMA_CLK_EN_MASK                (1 << 2)
+#define   AMDISPLAY_CLKC_ENABLE_LIDD_CLK_EN_MASK       (1 << 1)
+#define   AMDISPLAY_CLKC_ENABLE_CORE_CLK_EN_MASK       (1 << 0)
+#define AMDISPLAY_CLKC_RESET           0x70
+#define   AMDISPLAY_CLKC_RESET_MAIN_RST_MASK   (1 << 3)
+#define   AMDISPLAY_CLKC_RESET_DMA_RST_MASK    (1 << 2)
+#define   AMDISPLAY_CLKC_RESET_LIDD_RST_MASK   (1 << 1)
+#define   AMDISPLAY_CLKC_RESET_CORE_RST_MASK   (1 << 0)
+
+/* AM335x LCDC intr. masks */
+#define AMDISPLAY_IRQ_EOF1     (1 << 9)
+#define AMDISPLAY_IRQ_EOF0     (1 << 8)
+#define AMDISPLAY_IRQ_PL       (1 << 6)
+#define AMDISPLAY_IRQ_FUF      (1 << 5)
+#define AMDISPLAY_IRQ_ACB      (1 << 3)
+#define AMDISPLAY_IRQ_SYNC     (1 << 2)
+#define AMDISPLAY_IRQ_RR_DONE  (1 << 1)
+#define AMDISPLAY_IRQ_DONE     (1 << 0)
+
+/*  EDID reading */ 
+#define EDID_LENGTH            0x80
+
+#ifdef I2CDEBUG
+int amdisplay_debug = 20;
+#define DPRINTF(n,s)           do { if ((n) <= amdisplay_debug) printf s; } 
while (0)
+#else
+#define DPRINTF(n,s)           do {} while (0)
+#endif
+
+
Index: arch/armv7/omap/files.omap
===================================================================
RCS file: /cvs/src/sys/arch/armv7/omap/files.omap,v
retrieving revision 1.16
diff -u -p -r1.16 files.omap
--- arch/armv7/omap/files.omap  11 Aug 2016 04:33:06 -0000      1.16
+++ arch/armv7/omap/files.omap  2 Sep 2016 05:06:06 -0000
@@ -42,6 +42,14 @@ device intc
 attach intc at fdt
 file   arch/armv7/omap/intc.c                  intc
 
+device nxptda
+attach nxptda at i2c
+file   arch/armv7/omap/nxptda.c                nxptda
+
+device amdisplay: wsemuldisplaydev, rasops16
+attach amdisplay at fdt
+file   arch/armv7/omap/amdisplay.c             amdisplay
+
 device gptimer
 attach gptimer at omap
 file   arch/armv7/omap/gptimer.c               gptimer
Index: arch/armv7/omap/nxptda.c
===================================================================
RCS file: arch/armv7/omap/nxptda.c
diff -N arch/armv7/omap/nxptda.c
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ arch/armv7/omap/nxptda.c    2 Sep 2016 05:06:06 -0000
@@ -0,0 +1,763 @@
+/*
+ * Copyright (c) 2016 Ian Sutton <[email protected]>
+ * All rights reserved.
+ *
+ * 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 AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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.
+ */
+
+/*
+ * Copyright (c) 2015 Oleksandr Tymoshenko <[email protected]>
+ * All rights reserved.
+ *
+ * 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 AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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.
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/device.h>
+#include <sys/errno.h>
+
+#include <dev/i2c/i2cvar.h>
+#include <dev/videomode/videomode.h>
+
+#include <arch/armv7/omap/nxptdavar.h>
+
+/* TDA19988 registers */
+#define        MKREG(page, addr)       (((page) << 8) | (addr))
+
+#define        REGPAGE(reg)            (((reg) >> 8) & 0xff)
+#define        REGADDR(reg)            ((reg) & 0xff)
+
+#define TDA_VERSION            MKREG(0x00, 0x00)
+#define TDA_MAIN_CNTRL0                MKREG(0x00, 0x01)
+#define        MAIN_CNTRL0_SR          (1 << 0)
+#define TDA_VERSION_MSB                MKREG(0x00, 0x02)
+#define        TDA_SOFTRESET           MKREG(0x00, 0x0a)
+#define                SOFTRESET_I2C           (1 << 1)
+#define                SOFTRESET_AUDIO         (1 << 0)
+#define        TDA_DDC_CTRL            MKREG(0x00, 0x0b)
+#define                DDC_ENABLE              0
+#define        TDA_CCLK                MKREG(0x00, 0x0c)
+#define                CCLK_ENABLE             1
+#define        TDA_INT_FLAGS_2         MKREG(0x00, 0x11)
+#define                INT_FLAGS_2_EDID_BLK_RD (1 << 1)
+
+#define        TDA_VIP_CNTRL_0         MKREG(0x00, 0x20)
+#define        TDA_VIP_CNTRL_1         MKREG(0x00, 0x21)
+#define        TDA_VIP_CNTRL_2         MKREG(0x00, 0x22)
+#define        TDA_VIP_CNTRL_3         MKREG(0x00, 0x23)
+#define                VIP_CNTRL_3_SYNC_HS     (2 << 4)
+#define                VIP_CNTRL_3_V_TGL       (1 << 2)
+#define                VIP_CNTRL_3_H_TGL       (1 << 1)
+
+#define        TDA_VIP_CNTRL_4         MKREG(0x00, 0x24)
+#define                VIP_CNTRL_4_BLANKIT_NDE         (0 << 2)
+#define                VIP_CNTRL_4_BLANKIT_HS_VS       (1 << 2)
+#define                VIP_CNTRL_4_BLANKIT_NHS_VS      (2 << 2)
+#define                VIP_CNTRL_4_BLANKIT_HE_VE       (3 << 2)
+#define                VIP_CNTRL_4_BLC_NONE            (0 << 0)
+#define                VIP_CNTRL_4_BLC_RGB444          (1 << 0)
+#define                VIP_CNTRL_4_BLC_YUV444          (2 << 0)
+#define                VIP_CNTRL_4_BLC_YUV422          (3 << 0)
+#define        TDA_VIP_CNTRL_5         MKREG(0x00, 0x25)
+#define                VIP_CNTRL_5_SP_CNT(n)   (((n) & 3) << 1)
+#define        TDA_MUX_VP_VIP_OUT      MKREG(0x00, 0x27)
+#define TDA_MAT_CONTRL         MKREG(0x00, 0x80)
+#define                MAT_CONTRL_MAT_BP       (1 << 2)
+#define        TDA_VIDFORMAT           MKREG(0x00, 0xa0)
+#define        TDA_REFPIX_MSB          MKREG(0x00, 0xa1)
+#define        TDA_REFPIX_LSB          MKREG(0x00, 0xa2)
+#define        TDA_REFLINE_MSB         MKREG(0x00, 0xa3)
+#define        TDA_REFLINE_LSB         MKREG(0x00, 0xa4)
+#define        TDA_NPIX_MSB            MKREG(0x00, 0xa5)
+#define        TDA_NPIX_LSB            MKREG(0x00, 0xa6)
+#define        TDA_NLINE_MSB           MKREG(0x00, 0xa7)
+#define        TDA_NLINE_LSB           MKREG(0x00, 0xa8)
+#define        TDA_VS_LINE_STRT_1_MSB  MKREG(0x00, 0xa9)
+#define        TDA_VS_LINE_STRT_1_LSB  MKREG(0x00, 0xaa)
+#define        TDA_VS_PIX_STRT_1_MSB   MKREG(0x00, 0xab)
+#define        TDA_VS_PIX_STRT_1_LSB   MKREG(0x00, 0xac)
+#define        TDA_VS_LINE_END_1_MSB   MKREG(0x00, 0xad)
+#define        TDA_VS_LINE_END_1_LSB   MKREG(0x00, 0xae)
+#define        TDA_VS_PIX_END_1_MSB    MKREG(0x00, 0xaf)
+#define        TDA_VS_PIX_END_1_LSB    MKREG(0x00, 0xb0)
+#define        TDA_VS_LINE_STRT_2_MSB  MKREG(0x00, 0xb1)
+#define        TDA_VS_LINE_STRT_2_LSB  MKREG(0x00, 0xb2)
+#define        TDA_VS_PIX_STRT_2_MSB   MKREG(0x00, 0xb3)
+#define        TDA_VS_PIX_STRT_2_LSB   MKREG(0x00, 0xb4)
+#define        TDA_VS_LINE_END_2_MSB   MKREG(0x00, 0xb5)
+#define        TDA_VS_LINE_END_2_LSB   MKREG(0x00, 0xb6)
+#define        TDA_VS_PIX_END_2_MSB    MKREG(0x00, 0xb7)
+#define        TDA_VS_PIX_END_2_LSB    MKREG(0x00, 0xb8)
+#define        TDA_HS_PIX_START_MSB    MKREG(0x00, 0xb9)
+#define        TDA_HS_PIX_START_LSB    MKREG(0x00, 0xba)
+#define        TDA_HS_PIX_STOP_MSB     MKREG(0x00, 0xbb)
+#define        TDA_HS_PIX_STOP_LSB     MKREG(0x00, 0xbc)
+#define        TDA_VWIN_START_1_MSB    MKREG(0x00, 0xbd)
+#define        TDA_VWIN_START_1_LSB    MKREG(0x00, 0xbe)
+#define        TDA_VWIN_END_1_MSB      MKREG(0x00, 0xbf)
+#define        TDA_VWIN_END_1_LSB      MKREG(0x00, 0xc0)
+#define        TDA_VWIN_START_2_MSB    MKREG(0x00, 0xc1)
+#define        TDA_VWIN_START_2_LSB    MKREG(0x00, 0xc2)
+#define        TDA_VWIN_END_2_MSB      MKREG(0x00, 0xc3)
+#define        TDA_VWIN_END_2_LSB      MKREG(0x00, 0xc4)
+#define        TDA_DE_START_MSB        MKREG(0x00, 0xc5)
+#define        TDA_DE_START_LSB        MKREG(0x00, 0xc6)
+#define        TDA_DE_STOP_MSB         MKREG(0x00, 0xc7)
+#define        TDA_DE_STOP_LSB         MKREG(0x00, 0xc8)
+
+#define        TDA_TBG_CNTRL_0         MKREG(0x00, 0xca)
+#define                TBG_CNTRL_0_SYNC_ONCE   (1 << 7)
+#define                TBG_CNTRL_0_SYNC_MTHD   (1 << 6)
+
+#define        TDA_TBG_CNTRL_1         MKREG(0x00, 0xcb)
+#define                TBG_CNTRL_1_DWIN_DIS    (1 << 6)
+#define                TBG_CNTRL_1_TGL_EN      (1 << 2)
+#define                TBG_CNTRL_1_V_TGL       (1 << 1)
+#define                TBG_CNTRL_1_H_TGL       (1 << 0)
+
+#define        TDA_HVF_CNTRL_0         MKREG(0x00, 0xe4)
+#define                HVF_CNTRL_0_PREFIL_NONE         (0 << 2)
+#define                HVF_CNTRL_0_INTPOL_BYPASS       (0 << 0)
+#define        TDA_HVF_CNTRL_1         MKREG(0x00, 0xe5)
+#define                HVF_CNTRL_1_VQR(x)      (((x) & 3) << 2)
+#define                HVF_CNTRL_1_VQR_FULL    HVF_CNTRL_1_VQR(0)
+#define        TDA_ENABLE_SPACE        MKREG(0x00, 0xd6)
+#define        TDA_RPT_CNTRL           MKREG(0x00, 0xf0)
+
+#define        TDA_PLL_SERIAL_1        MKREG(0x02, 0x00)
+#define                PLL_SERIAL_1_SRL_MAN_IP (1 << 6)
+#define        TDA_PLL_SERIAL_2        MKREG(0x02, 0x01)
+#define                PLL_SERIAL_2_SRL_PR(x)          (((x) & 0xf) << 4)
+#define                PLL_SERIAL_2_SRL_NOSC(x)        (((x) & 0x3) << 0)
+#define        TDA_PLL_SERIAL_3        MKREG(0x02, 0x02)
+#define                PLL_SERIAL_3_SRL_PXIN_SEL       (1 << 4)
+#define                PLL_SERIAL_3_SRL_DE             (1 << 2)
+#define                PLL_SERIAL_3_SRL_CCIR           (1 << 0)
+#define        TDA_SERIALIZER          MKREG(0x02, 0x03)
+#define        TDA_BUFFER_OUT          MKREG(0x02, 0x04)
+#define        TDA_PLL_SCG1            MKREG(0x02, 0x05)
+#define        TDA_PLL_SCG2            MKREG(0x02, 0x06)
+#define        TDA_PLL_SCGN1           MKREG(0x02, 0x07)
+#define        TDA_PLL_SCGN2           MKREG(0x02, 0x08)
+#define        TDA_PLL_SCGR1           MKREG(0x02, 0x09)
+#define        TDA_PLL_SCGR2           MKREG(0x02, 0x0a)
+
+#define        TDA_SEL_CLK             MKREG(0x02, 0x11)
+#define                SEL_CLK_ENA_SC_CLK      (1 << 3)
+#define                SEL_CLK_SEL_VRF_CLK(x)  (((x) & 3) << 1)
+#define                SEL_CLK_SEL_CLK1        (1 << 0)
+#define        TDA_ANA_GENERAL         MKREG(0x02, 0x12)
+
+#define        TDA_EDID_DATA0          MKREG(0x09, 0x00)
+#define        TDA_EDID_CTRL           MKREG(0x09, 0xfa)
+#define        TDA_DDC_ADDR            MKREG(0x09, 0xfb)
+#define        TDA_DDC_OFFS            MKREG(0x09, 0xfc)
+#define        TDA_DDC_SEGM_ADDR       MKREG(0x09, 0xfd)
+#define        TDA_DDC_SEGM            MKREG(0x09, 0xfe)
+
+#define        TDA_IF_VSP              MKREG(0x10, 0x20)
+#define        TDA_IF_AVI              MKREG(0x10, 0x40)
+#define        TDA_IF_SPD              MKREG(0x10, 0x60)
+#define        TDA_IF_AUD              MKREG(0x10, 0x80)
+#define        TDA_IF_MPS              MKREG(0x10, 0xa0)
+
+#define        TDA_ENC_CNTRL           MKREG(0x11, 0x0d)
+#define                ENC_CNTRL_DVI_MODE      (0 << 2)
+#define                ENC_CNTRL_HDMI_MODE     (1 << 2)
+#define        TDA_DIP_IF_FLAGS        MKREG(0x11, 0x0f)
+#define                DIP_IF_FLAGS_IF5        (1 << 5)
+#define                DIP_IF_FLAGS_IF4        (1 << 4)
+#define                DIP_IF_FLAGS_IF3        (1 << 3)
+#define                DIP_IF_FLAGS_IF2        (1 << 2) /*  AVI IF on page 10h 
*/
+#define                DIP_IF_FLAGS_IF1        (1 << 1)
+
+#define        TDA_TX3                 MKREG(0x12, 0x9a)
+#define        TDA_TX4                 MKREG(0x12, 0x9b)
+#define                TX4_PD_RAM              (1 << 1)
+#define        TDA_HDCP_TX33           MKREG(0x12, 0xb8)
+#define                HDCP_TX33_HDMI          (1 << 1)
+
+#define        TDA_CURPAGE_ADDR        0xff
+
+#define        TDA_CEC_ENAMODS         0xff
+#define                ENAMODS_RXSENS          (1 << 2)
+#define                ENAMODS_HDMI            (1 << 1)
+#define        TDA_CEC_FRO_IM_CLK_CTRL 0xfb
+#define                CEC_FRO_IM_CLK_CTRL_GHOST_DIS   (1 << 7)
+#define                CEC_FRO_IM_CLK_CTRL_IMCLK_SEL   (1 << 1)
+
+/*  EDID reading */ 
+#define EDID_LENGTH            0x80
+#define        MAX_READ_ATTEMPTS       100
+
+/*  EDID fields */
+#define        EDID_MODES0             35
+#define        EDID_MODES1             36
+#define        EDID_TIMING_START       38
+#define        EDID_TIMING_END         54
+#define        EDID_TIMING_X(v)        (((v) + 31) * 8)
+#define        EDID_FREQ(v)            (((v) & 0x3f) + 60)
+#define        EDID_RATIO(v)           (((v) >> 6) & 0x3)
+#define        EDID_RATIO_10x16        0
+#define        EDID_RATIO_3x4          1       
+#define        EDID_RATIO_4x5          2       
+#define        EDID_RATIO_9x16         3
+
+/* NXP TDA19988 slave addrs. */
+#define TDA_HDMI               0x70
+#define TDA_CEC                        0x34
+
+/* debug/etc macros */
+#define DEVNAME(s)             ((s)->sc_dev.dv_xname)
+#ifdef I2CDEBUG
+int nxptda_debug = 20;
+#define DPRINTF(n,s)           do { if ((n) <= nxptda_debug) printf s; } while 
(0)
+#else
+#define DPRINTF(n,s)           do {} while (0)
+#endif
+
+struct nxptda_softc {
+       struct device   sc_dev;
+       i2c_tag_t       sc_tag;
+       i2c_addr_t      sc_addr;
+
+       uint8_t         sc_curpage;
+       uint8_t         sc_edid[EDID_LENGTH];
+};
+
+int    nxptda_match(struct device *, void *, void *);
+void   nxptda_attach(struct device *, struct device *, void *);
+
+int    nxptda_cec_read(struct nxptda_softc *, uint8_t, uint8_t *);
+int    nxptda_cec_write(struct nxptda_softc *, uint8_t, uint8_t);
+int    nxptda_read(struct nxptda_softc *, uint16_t, uint8_t *);
+int    nxptda_write(struct nxptda_softc *, uint16_t, uint8_t);
+int    nxptda_write2(struct nxptda_softc *, uint16_t, uint16_t);
+int    nxptda_set(struct nxptda_softc *, uint16_t, uint8_t);
+int    nxptda_clear(struct nxptda_softc *, uint16_t, uint8_t);
+int    nxptda_set_page(struct nxptda_softc *, uint8_t);
+int    nxptda_read_edid(struct nxptda_softc *);
+int    nxptda_reset(struct nxptda_softc *);
+int    nxptda_init_encoder(struct nxptda_softc *, struct videomode *);
+
+int    nxptda_get_edid(uint8_t *, int);
+int    nxptda_set_videomode(struct videomode *);
+
+struct cfattach nxptda_ca = {
+       sizeof(struct nxptda_softc), nxptda_match, nxptda_attach
+};
+
+struct cfdriver nxptda_cd = {
+       NULL, "nxptda", DV_DULL
+};
+
+int
+nxptda_match(struct device *parent, void *match, void *aux)
+{
+       struct i2c_attach_args *ia = aux;
+
+       if (strcmp(ia->ia_name, "nxp,tda998x") == 0)
+           return 1;
+
+       return 0;
+}
+
+void
+nxptda_attach(struct device *parent, struct device *self, void *aux)
+{
+       struct nxptda_softc *sc = (struct nxptda_softc *)self;
+       struct i2c_attach_args *ia = aux;
+       uint8_t data = 0;
+       uint16_t version = 0;
+       int res = 0;
+
+       sc->sc_tag = ia->ia_tag;
+       sc->sc_addr = ia->ia_addr;
+       sc->sc_curpage = 0xff;
+
+       iic_acquire_bus(sc->sc_tag, 0);
+
+       DPRINTF(3,("\n"));
+
+       /* enable HDMI core */
+       nxptda_cec_write(sc, TDA_CEC_ENAMODS, ENAMODS_RXSENS | ENAMODS_HDMI);
+       delay(1000);
+
+       if (!(nxptda_reset(sc)))
+           DPRINTF(3,("%s: software reset OK\n", DEVNAME(sc)));
+       else
+           DPRINTF(3,("%s: software reset failed!\n", DEVNAME(sc)));
+
+       /*  PLL registers common configuration */
+       nxptda_write(sc, TDA_PLL_SERIAL_1, 0x00);
+       nxptda_write(sc, TDA_PLL_SERIAL_2, PLL_SERIAL_2_SRL_NOSC(1));
+       nxptda_write(sc, TDA_PLL_SERIAL_3, 0x00);
+       nxptda_write(sc, TDA_SERIALIZER, 0x00);
+       nxptda_write(sc, TDA_BUFFER_OUT, 0x00);
+       nxptda_write(sc, TDA_PLL_SCG1, 0x00);
+       nxptda_write(sc, TDA_SEL_CLK, SEL_CLK_SEL_CLK1 | SEL_CLK_ENA_SC_CLK);
+       nxptda_write(sc, TDA_PLL_SCGN1, 0xfa);
+       nxptda_write(sc, TDA_PLL_SCGN2, 0x00);
+       nxptda_write(sc, TDA_PLL_SCGR1, 0x5b);
+       nxptda_write(sc, TDA_PLL_SCGR2, 0x00);
+       nxptda_write(sc, TDA_PLL_SCG2, 0x10);
+
+       /*  Write the default value MUX register */
+       nxptda_write(sc, TDA_MUX_VP_VIP_OUT, 0x24);
+
+       res |= nxptda_read(sc, TDA_VERSION, &data);
+       version |= data;
+       res |= nxptda_read(sc, TDA_VERSION_MSB, &data);
+       version |= (data << 8);
+       version &= ~0x30;
+
+       if (!res) {
+           DPRINTF(3,("%s: ", DEVNAME(sc)));
+           printf(": rev 0x%04x\n", version);
+       } else {
+           DPRINTF(3,("%s: ", DEVNAME(sc)));
+           printf(": failed to enable HDMI core, exiting...\n");
+           iic_release_bus(sc->sc_tag, 0);
+           return;
+       }
+
+       nxptda_write(sc, TDA_DDC_CTRL, DDC_ENABLE);
+       nxptda_write(sc, TDA_TX3, 39);
+
+       nxptda_cec_write(sc, TDA_CEC_FRO_IM_CLK_CTRL,
+           CEC_FRO_IM_CLK_CTRL_GHOST_DIS | CEC_FRO_IM_CLK_CTRL_IMCLK_SEL);
+
+       if (nxptda_read_edid(sc)) {
+           DPRINTF(3,("%s: failed to read EDID bits, exiting!\n", 
DEVNAME(sc)));
+           return;
+       }
+
+       /*  Default values for RGB 4:4:4 mapping */
+       nxptda_write(sc, TDA_VIP_CNTRL_0, 0x23);
+       nxptda_write(sc, TDA_VIP_CNTRL_1, 0x01);
+       nxptda_write(sc, TDA_VIP_CNTRL_2, 0x45);
+
+       iic_release_bus(sc->sc_tag, 0);
+}
+
+int
+nxptda_cec_read(struct nxptda_softc *sc, uint8_t addr, uint8_t *buf)
+{
+       int ret = 0;
+
+       if ((ret |= iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP, TDA_CEC, &addr, 
1,
+           NULL, 0, 0))) {
+               DPRINTF(3,("%s: (CEC) failed to read addr 0x%02x, errno %d\n", 
DEVNAME(sc),
+                   addr, ret));
+               return ret;
+       }
+
+       DPRINTF(3,("%s: (CEC) read 0x%02x from 0x%02x\n", DEVNAME(sc), *buf, 
addr));
+
+       return ret;
+}
+
+int
+nxptda_cec_write(struct nxptda_softc *sc, uint8_t addr, uint8_t val)
+{
+       int ret = 0;
+       uint8_t sendbuf[] = { addr, val };
+
+       if ((ret |= iic_exec(sc->sc_tag, I2C_OP_WRITE_WITH_STOP, TDA_CEC, 
&sendbuf, 2,
+           NULL, 0, 0))) {
+               DPRINTF(3,("%s: (CEC) failed to write 0x%02x to 0x%02x, errno 
%d\n",
+                   DEVNAME(sc), val, addr, ret));
+               return ret;
+       }
+
+       DPRINTF(3,("%s: (CEC) wrote 0x%02x to 0x%02x\n", DEVNAME(sc), val, 
addr));
+
+       return ret;
+}
+
+int
+nxptda_read(struct nxptda_softc *sc, uint16_t reg, uint8_t *buf)
+{
+       int ret = 0;
+
+       nxptda_set_page(sc, REGPAGE(reg));
+
+       if ((ret = iic_smbus_read_byte(sc->sc_tag, TDA_HDMI, REGADDR(reg), buf, 
0))) {
+           DPRINTF(3,("%s: failed to read addr 0x%02x on page 0x%02x, errno 
%d\n",
+               DEVNAME(sc), REGADDR(reg), REGPAGE(reg), ret));
+           return ret;
+       }
+
+       DPRINTF(3,("%s: read  0x%02x from 0x%02x on page 0x%02x\n", 
DEVNAME(sc), *buf,
+           REGADDR(reg), REGPAGE(reg)));
+
+       return ret;
+}
+
+int
+nxptda_write(struct nxptda_softc *sc, uint16_t reg, uint8_t val)
+{
+       int ret = 0;
+       uint8_t sendbuf[] = { REGADDR(reg), val };
+
+       nxptda_set_page(sc, REGPAGE(reg));
+
+       if ((ret = iic_exec(sc->sc_tag, I2C_OP_WRITE_WITH_STOP, TDA_HDMI, 
&sendbuf, 2,
+           NULL, 0, 0))) {
+               DPRINTF(3,("%s: failed to write 0x%02x to 0x%02x on page 
0x%02x, errno %d\n",
+                   DEVNAME(sc), val, REGADDR(reg), REGPAGE(reg), ret));
+               return ret;
+       }
+
+       DPRINTF(3,("%s: wrote 0x%02x  to  0x%02x on page 0x%02x\n", 
DEVNAME(sc), val,
+           REGADDR(reg), REGPAGE(reg)));
+
+       return ret;
+}
+
+int
+nxptda_write2(struct nxptda_softc *sc, uint16_t reg, uint16_t val)
+{
+       int ret = 0;
+       uint8_t sendbuf[] = { REGADDR(reg), val >> 8, val & 0xff };
+
+       nxptda_set_page(sc, REGPAGE(reg));
+
+       if ((ret = iic_exec(sc->sc_tag, I2C_OP_WRITE_WITH_STOP, TDA_HDMI, 
&sendbuf, 3,
+           NULL, 0, 0))) {
+               DPRINTF(3,("%s: failed to write 0x%04x to 0x%02x on page 
0x%02x, errno %d\n",
+                   DEVNAME(sc), val, REGADDR(reg), REGPAGE(reg), ret));
+               return ret;
+       }
+
+       DPRINTF(3,("%s: wrote 0x%04x  to  0x%02x on page 0x%02x\n", 
DEVNAME(sc), val,
+           REGADDR(reg), REGPAGE(reg)));
+
+       return ret;
+
+}
+
+int
+nxptda_set(struct nxptda_softc *sc, uint16_t reg, uint8_t bits)
+{
+       int ret = 0;
+       uint8_t buf;
+
+       ret |= nxptda_read(sc, reg, &buf);
+       buf |= bits;
+       ret |= nxptda_write(sc, reg, buf);
+
+       return ret;
+}
+
+int
+nxptda_clear(struct nxptda_softc *sc, uint16_t reg, uint8_t bits)
+{
+       int ret = 0;
+       uint8_t buf;
+
+       ret |= nxptda_read(sc, reg, &buf);
+       buf &= ~bits;
+       ret |= nxptda_write(sc, reg, buf);
+
+       return ret;
+}
+
+int
+nxptda_set_page(struct nxptda_softc *sc, uint8_t page)
+{
+       int ret = 0;
+       uint8_t sendbuf[] = { TDA_CURPAGE_ADDR, page };
+
+       if (sc->sc_curpage == page)
+           return ret;
+
+       if ((ret = iic_exec(sc->sc_tag, I2C_OP_WRITE_WITH_STOP, TDA_HDMI, 
&sendbuf,
+           sizeof(sendbuf), NULL, 0, 0))) {
+               DPRINTF(3,("%s: failed to set memory page 0x%02x, errno %d\n", 
DEVNAME(sc),
+               page, ret));
+               return ret;
+       }
+
+       sc->sc_curpage = page;
+       DPRINTF(3,("%s: set page to 0x%02x\n", DEVNAME(sc), page));
+
+       return ret;
+}
+
+int
+nxptda_read_edid(struct nxptda_softc *sc)
+{
+       int i = 0, ret = 0;
+       uint8_t reg;
+
+       nxptda_set(sc, TDA_INT_FLAGS_2, INT_FLAGS_2_EDID_BLK_RD);
+
+       /*  Block 0 */
+       nxptda_write(sc, TDA_DDC_ADDR, 0xa0);
+       nxptda_write(sc, TDA_DDC_OFFS, 0x00);
+       nxptda_write(sc, TDA_DDC_SEGM_ADDR, 0x60);
+       nxptda_write(sc, TDA_DDC_SEGM, 0x00);
+
+       nxptda_write(sc, TDA_EDID_CTRL, 1);
+       nxptda_write(sc, TDA_EDID_CTRL, 0);
+
+       for (; i < MAX_READ_ATTEMPTS; i++) {
+           nxptda_read(sc, TDA_INT_FLAGS_2, &reg);
+           if (reg & INT_FLAGS_2_EDID_BLK_RD) {
+               DPRINTF(3,("%s: EDID-ready IRQ fired\n", DEVNAME(sc)));
+               break;
+           }
+       }
+
+       if (i == MAX_READ_ATTEMPTS) {
+           printf("%s: no display detected\n", DEVNAME(sc));
+           ret = ENXIO;
+           return ret;
+       }
+
+       nxptda_set_page(sc, 0x09);
+
+       reg = 0x00;
+       DPRINTF(3,("%s: ------------- EDID -------------", DEVNAME(sc)));
+       for (i = 0; i < EDID_LENGTH; i++) {
+           iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP, TDA_HDMI, &reg, 1,
+               &sc->sc_edid[i], 1, 0);
+           if (!(i % 16))
+               DPRINTF(3,("\n%s: ", DEVNAME(sc)));
+           DPRINTF(3,("%02x", sc->sc_edid[i]));
+           reg++;
+       }
+       DPRINTF(3,("\n%s: --------------------------------\n", DEVNAME(sc)));
+
+       nxptda_clear(sc, TDA_INT_FLAGS_2, INT_FLAGS_2_EDID_BLK_RD);
+       nxptda_set(sc, TDA_TX4, TX4_PD_RAM);
+
+       return ret;
+}
+
+int
+nxptda_reset(struct nxptda_softc *sc)
+{
+       int ret = 0;
+
+       /* reset core */
+       ret |= nxptda_set(sc, TDA_SOFTRESET, 3);
+       delay(100);
+       ret |= nxptda_clear(sc, TDA_SOFTRESET, 3);
+       delay(100);
+
+       /* reset transmitter */
+       ret |= nxptda_set(sc, TDA_MAIN_CNTRL0, MAIN_CNTRL0_SR);
+       ret |= nxptda_clear(sc, TDA_MAIN_CNTRL0, MAIN_CNTRL0_SR);
+
+       return ret;
+}
+
+int
+nxptda_init_encoder(struct nxptda_softc *sc, struct videomode *mode)
+{
+       int ret = 0;
+
+       uint16_t ref_pix, ref_line, n_pix, n_line;
+       uint16_t hs_pix_start, hs_pix_stop;
+       uint16_t vs1_pix_start, vs1_pix_stop;
+       uint16_t vs1_line_start, vs1_line_end;
+       uint16_t vs2_pix_start, vs2_pix_stop;
+       uint16_t vs2_line_start, vs2_line_end;
+       uint16_t vwin1_line_start, vwin1_line_end;
+       uint16_t vwin2_line_start, vwin2_line_end;
+       uint16_t de_start, de_stop;
+       uint8_t reg, div;
+
+       n_pix = mode->htotal;
+       n_line = mode->vtotal;
+
+       hs_pix_stop = mode->hsync_end - mode->hdisplay;
+       hs_pix_start = mode->hsync_start - mode->hdisplay;
+
+       de_stop = mode->htotal;
+       de_start = mode->htotal - mode->hdisplay;
+       ref_pix = hs_pix_start + 3;
+
+       if ((mode->flags & VID_INTERLACE) == 0) {
+               ref_line = 1 + mode->vsync_start - mode->vdisplay;
+               vwin1_line_start = mode->vtotal - mode->vdisplay - 1;
+               vwin1_line_end = vwin1_line_start + mode->vdisplay;
+
+               vs1_pix_start = vs1_pix_stop = hs_pix_start;
+               vs1_line_start = mode->vsync_start - mode->vdisplay;
+               vs1_line_end = vs1_line_start + mode->vsync_end - 
mode->vsync_start;
+
+               vwin2_line_start = vwin2_line_end = 0;
+               vs2_pix_start = vs2_pix_stop = 0;
+               vs2_line_start = vs2_line_end = 0;
+       } else {
+               ref_line = 1 + (mode->vsync_start - mode->vdisplay)/2;
+               vwin1_line_start = (mode->vtotal - mode->vdisplay)/2;
+               vwin1_line_end = vwin1_line_start + mode->vdisplay/2;
+
+               vs1_pix_start = vs1_pix_stop = hs_pix_start;
+               vs1_line_start = (mode->vsync_start - mode->vdisplay)/2;
+               vs1_line_end = vs1_line_start + (mode->vsync_end - 
mode->vsync_start)/2;
+
+               vwin2_line_start = vwin1_line_start + mode->vtotal/2;
+               vwin2_line_end = vwin2_line_start + mode->vdisplay/2;
+
+               vs2_pix_start = vs2_pix_stop = hs_pix_start + mode->htotal/2;
+               vs2_line_start = vs1_line_start + mode->vtotal/2 ;
+               vs2_line_end = vs2_line_start + (mode->vsync_end - 
mode->vsync_start)/2;
+       }
+
+       div = 148500 / mode->dot_clock;
+       if (div != 0) {
+               div--;
+               if (div > 3)
+                       div = 3;
+       }
+
+       /*  set HDMI HDCP mode off */
+       nxptda_set(sc, TDA_TBG_CNTRL_1, TBG_CNTRL_1_DWIN_DIS);
+       nxptda_clear(sc, TDA_HDCP_TX33, HDCP_TX33_HDMI);
+       nxptda_write(sc, TDA_ENC_CNTRL, ENC_CNTRL_DVI_MODE);
+
+       /*  no pre-filter or interpolator */
+       nxptda_write(sc, TDA_HVF_CNTRL_0,
+           HVF_CNTRL_0_INTPOL_BYPASS | HVF_CNTRL_0_PREFIL_NONE);
+       nxptda_write(sc, TDA_VIP_CNTRL_5, VIP_CNTRL_5_SP_CNT(0));
+       nxptda_write(sc, TDA_VIP_CNTRL_4,
+           VIP_CNTRL_4_BLANKIT_NDE | VIP_CNTRL_4_BLC_NONE);
+
+       nxptda_clear(sc, TDA_PLL_SERIAL_3, PLL_SERIAL_3_SRL_CCIR);
+       nxptda_clear(sc, TDA_PLL_SERIAL_1, PLL_SERIAL_1_SRL_MAN_IP);
+       nxptda_clear(sc, TDA_PLL_SERIAL_3, PLL_SERIAL_3_SRL_DE);
+       nxptda_write(sc, TDA_SERIALIZER, 0);
+       nxptda_write(sc, TDA_HVF_CNTRL_1, HVF_CNTRL_1_VQR_FULL);
+
+       nxptda_write(sc, TDA_RPT_CNTRL, 0);
+       nxptda_write(sc, TDA_SEL_CLK, SEL_CLK_SEL_VRF_CLK(0) |
+                       SEL_CLK_SEL_CLK1 | SEL_CLK_ENA_SC_CLK);
+
+       nxptda_write(sc, TDA_PLL_SERIAL_2, PLL_SERIAL_2_SRL_NOSC(div) |
+                       PLL_SERIAL_2_SRL_PR(0));
+
+       nxptda_set(sc, TDA_MAT_CONTRL, MAT_CONTRL_MAT_BP);
+
+       nxptda_write(sc, TDA_ANA_GENERAL, 0x09);
+
+       nxptda_clear(sc, TDA_TBG_CNTRL_0, TBG_CNTRL_0_SYNC_MTHD);
+
+       /*
+        * Sync on rising HSYNC/VSYNC
+        */
+       reg = VIP_CNTRL_3_SYNC_HS;
+       if (mode->flags & VID_NHSYNC)
+               reg |= VIP_CNTRL_3_H_TGL;
+       if (mode->flags & VID_NVSYNC)
+               reg |= VIP_CNTRL_3_V_TGL;
+       nxptda_write(sc, TDA_VIP_CNTRL_3, reg);
+
+       reg = TBG_CNTRL_1_TGL_EN;
+       if (mode->flags & VID_NHSYNC)
+               reg |= TBG_CNTRL_1_H_TGL;
+       if (mode->flags & VID_NVSYNC)
+               reg |= TBG_CNTRL_1_V_TGL;
+       nxptda_write(sc, TDA_TBG_CNTRL_1, reg);
+
+       /*  Program timing */
+       nxptda_write(sc, TDA_VIDFORMAT, 0x00);
+
+       nxptda_write2(sc, TDA_REFPIX_MSB, ref_pix);
+       nxptda_write2(sc, TDA_REFLINE_MSB, ref_line);
+       nxptda_write2(sc, TDA_NPIX_MSB, n_pix);
+       nxptda_write2(sc, TDA_NLINE_MSB, n_line);
+
+       nxptda_write2(sc, TDA_VS_LINE_STRT_1_MSB, vs1_line_start);
+       nxptda_write2(sc, TDA_VS_PIX_STRT_1_MSB, vs1_pix_start);
+       nxptda_write2(sc, TDA_VS_LINE_END_1_MSB, vs1_line_end);
+       nxptda_write2(sc, TDA_VS_PIX_END_1_MSB, vs1_pix_stop);
+       nxptda_write2(sc, TDA_VS_LINE_STRT_2_MSB, vs2_line_start);
+       nxptda_write2(sc, TDA_VS_PIX_STRT_2_MSB, vs2_pix_start);
+       nxptda_write2(sc, TDA_VS_LINE_END_2_MSB, vs2_line_end);
+       nxptda_write2(sc, TDA_VS_PIX_END_2_MSB, vs2_pix_stop);
+       nxptda_write2(sc, TDA_HS_PIX_START_MSB, hs_pix_start);
+       nxptda_write2(sc, TDA_HS_PIX_STOP_MSB, hs_pix_stop);
+       nxptda_write2(sc, TDA_VWIN_START_1_MSB, vwin1_line_start);
+       nxptda_write2(sc, TDA_VWIN_END_1_MSB, vwin1_line_end);
+       nxptda_write2(sc, TDA_VWIN_START_2_MSB, vwin2_line_start);
+       nxptda_write2(sc, TDA_VWIN_END_2_MSB, vwin2_line_end);
+       nxptda_write2(sc, TDA_DE_START_MSB, de_start);
+       nxptda_write2(sc, TDA_DE_STOP_MSB, de_stop);
+
+       nxptda_write(sc, TDA_ENABLE_SPACE, 0x00);
+
+       /*  must be last register set */
+       nxptda_clear(sc, TDA_TBG_CNTRL_0, TBG_CNTRL_0_SYNC_ONCE);
+
+       return ret;
+}
+
+int
+nxptda_get_edid(uint8_t *buf, int buflen)
+{
+       int ret = 0, i;
+       struct nxptda_softc *sc = nxptda_cd.cd_devs[0];
+
+       if (buflen < EDID_LENGTH || sc->sc_edid == NULL)
+           return -1;
+
+       for (i = 0; i < EDID_LENGTH; i++)
+           buf[i] = sc->sc_edid[i];
+
+       return ret;
+}
+
+int
+nxptda_set_videomode(struct videomode *mode)
+{
+       int ret = 0;
+       struct nxptda_softc *sc = nxptda_cd.cd_devs[0];
+
+       ret = nxptda_init_encoder(sc, mode);
+
+       return ret;
+}
Index: arch/armv7/omap/nxptdavar.h
===================================================================
RCS file: arch/armv7/omap/nxptdavar.h
diff -N arch/armv7/omap/nxptdavar.h
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ arch/armv7/omap/nxptdavar.h 2 Sep 2016 05:06:06 -0000
@@ -0,0 +1,18 @@
+/*
+ * Copyright (c) 2016 Ian Sutton <[email protected]>
+ *
+ * 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.
+ */
+
+int    nxptda_get_edid(uint8_t *, int);
+int    nxptda_set_videomode(struct videomode *);
Index: arch/armv7/omap/prcm.c
===================================================================
RCS file: /cvs/src/sys/arch/armv7/omap/prcm.c,v
retrieving revision 1.11
diff -u -p -r1.11 prcm.c
--- arch/armv7/omap/prcm.c      18 Jul 2016 15:03:01 -0000      1.11
+++ arch/armv7/omap/prcm.c      2 Sep 2016 05:06:06 -0000
@@ -70,6 +70,8 @@
 #define PRCM_REVISION          0x0800
 #define PRCM_SYSCONFIG         0x0810
 
+#define PRCM_AM335X_MASTER_OSC 24000 /* KHz */
+
 uint32_t prcm_imask_mask[PRCM_REG_MAX];
 uint32_t prcm_fmask_mask[PRCM_REG_MAX];
 uint32_t prcm_imask_addr[PRCM_REG_MAX];
@@ -97,6 +99,7 @@ int   prcm_setup_dpll5(struct prcm_softc *
 uint32_t prcm_v3_bit(int mod);
 uint32_t prcm_am335x_clkctrl(int mod);
 
+void prcm_am335x_setup(struct prcm_softc *);
 void prcm_am335x_enablemodule(struct prcm_softc *, int);
 void prcm_am335x_setclock(struct prcm_softc *, int, int);
 
@@ -132,7 +135,7 @@ prcm_attach(struct device *parent, struc
                    sc->sc_dev.dv_xname);
 
        if (fdt_is_compatible(node, "ti,am33xx")) {
-               sc->sc_setup = NULL;
+               sc->sc_setup = prcm_am335x_setup;
                sc->sc_enablemodule = prcm_am335x_enablemodule;
                sc->sc_setclock = prcm_am335x_setclock;
        } else if (fdt_is_compatible(node, "ti,omap3")) {
@@ -208,6 +211,37 @@ prcm_v3_setup(struct prcm_softc *sc)
 }
 
 void
+prcm_am335x_setup(struct prcm_softc *sc)
+{
+       uint32_t oreg;
+
+       /* Clock up display PLL for higher resolutions */
+       oreg = bus_space_read_4(sc->sc_iot, sc->sc_prcm, 
PRCM_AM335X_DISP_CLKMODE);
+       oreg &= ~0x7;
+       oreg |= 0x4;
+       bus_space_write_4(sc->sc_iot, sc->sc_prcm, PRCM_AM335X_DISP_CLKMODE, 
oreg);
+       while(!(bus_space_read_4(sc->sc_iot, sc->sc_prcm, 
PRCM_AM335X_DISP_IDLEST
+           & 0x10)));
+
+       oreg = bus_space_read_4(sc->sc_iot, sc->sc_prcm, 
PRCM_AM335X_DISP_CLKSEL);
+       oreg &= 0xFFF80000;
+       oreg |= 0x5A;
+       oreg |= (0x333 << 8);
+       bus_space_write_4(sc->sc_iot, sc->sc_prcm, PRCM_AM335X_DISP_CLKSEL, 
oreg);
+
+       oreg = bus_space_read_4(sc->sc_iot, sc->sc_prcm, PRCM_AM335X_DISP_M2);
+       oreg &= ~(0x1F);
+       oreg |= 0x1;
+       bus_space_write_4(sc->sc_iot, sc->sc_prcm, PRCM_AM335X_DISP_M2, oreg);
+
+       oreg = bus_space_read_4(sc->sc_iot, sc->sc_prcm, 
PRCM_AM335X_DISP_CLKMODE);
+       oreg |= 0x7;
+       bus_space_write_4(sc->sc_iot, sc->sc_prcm, PRCM_AM335X_DISP_CLKMODE, 
oreg);
+       while(!(bus_space_read_4(sc->sc_iot, sc->sc_prcm, 
PRCM_AM335X_DISP_IDLEST
+           & 0x10)));
+}
+
+void
 prcm_setclock(int clock, int speed)
 {
        struct prcm_softc *sc = prcm_cd.cd_devs[0];
@@ -221,7 +255,8 @@ prcm_setclock(int clock, int speed)
 void
 prcm_am335x_setclock(struct prcm_softc *sc, int clock, int speed)
 {
-       u_int32_t oreg, reg, mask;
+       u_int32_t oreg, reg, mask, delta, min_delta;
+       int i, j, mul, div;
 
        /* set CLKSEL register */
        if (clock == 1) {
@@ -240,6 +275,32 @@ prcm_am335x_setclock(struct prcm_softc *
                reg |=0x02;
                bus_space_write_4(sc->sc_iot, sc->sc_prcm,
                    PRCM_AM335X_CLKSEL_TIMER3_CLK, reg);
+       } else if (clock == 3) {
+           oreg = bus_space_read_4(sc->sc_iot, sc->sc_prcm, 
PRCM_AM335X_DISP_CLKMODE);
+           oreg &= ~0x7;
+           oreg |= 0x4;
+           bus_space_write_4(sc->sc_iot, sc->sc_prcm, 
PRCM_AM335X_DISP_CLKMODE, oreg);
+           while(!(bus_space_read_4(sc->sc_iot, sc->sc_prcm, 
PRCM_AM335X_DISP_IDLEST
+               & 0x10)));
+
+           min_delta = speed;
+           for (i = 1; i < 0x800; i++) {
+               for (j = 1; j < 0x80; j++) {
+                   delta = abs(speed - i*(PRCM_AM335X_MASTER_OSC/j));
+                   if (delta < min_delta) {
+                       mul = i;
+                       div = j;
+                       min_delta = delta;
+                   }
+                   if (min_delta == 0)
+                       break;
+               }
+           }
+           bus_space_write_4(sc->sc_iot, sc->sc_prcm, PRCM_AM335X_DISP_CLKSEL,
+               (mul << 8) | (div - 1));
+           bus_space_write_4(sc->sc_iot, sc->sc_prcm, 
PRCM_AM335X_DISP_CLKMODE, 0x7);
+           while (!(bus_space_read_4(sc->sc_iot, sc->sc_prcm, 
PRCM_AM335X_DISP_IDLEST
+               & (1 << 0))));
        }
 }
 
@@ -336,6 +397,8 @@ prcm_am335x_clkctrl(int mod)
                return PRCM_AM335X_I2C1_CLKCTRL;
        case PRCM_I2C2:
                return PRCM_AM335X_I2C2_CLKCTRL;
+       case PRCM_LCDC:
+               return PRCM_AM335X_LCDC_CLKCTRL;
        default:
                panic("%s: module not found\n", __func__);
        }
Index: arch/armv7/omap/prcmvar.h
===================================================================
RCS file: /cvs/src/sys/arch/armv7/omap/prcmvar.h,v
retrieving revision 1.6
diff -u -p -r1.6 prcmvar.h
--- arch/armv7/omap/prcmvar.h   18 Jul 2016 15:03:01 -0000      1.6
+++ arch/armv7/omap/prcmvar.h   2 Sep 2016 05:06:06 -0000
@@ -54,6 +54,7 @@ enum PRCM_MODULES {
        PRCM_I2C1,
        PRCM_I2C2,
        PRCM_I2C3,
+       PRCM_LCDC,
 };
 
 #define PRCM_REG_MAX   6


Reply via email to