> Date: Mon, 3 Apr 2017 01:33:28 -0400
> From: Ian Sutton <i...@ce.gl>
> 
> This patch introduces preliminary support for the display hardware
> onboard the am335x/BeagleBone Black. Included are two drivers,
> amdisplay(4) and nxptda(4), which run the LCD controller and HDMI PHY
> transmitter respectively. This patch follows work I've mailed to this
> list found here:
> 
> https://marc.info/?t=147047204600001&r=1&w=2
> 
> The code below is a complete (fourth!) rewrite. It completely and
> correctly controls the hardware but still needs to be plugged into the
> rest of the system (wsdisplay for syscons, wsfb for Xorg, etc.) before
> it is useful. In the meantime, I feel that it is review-ready and worth
> the time for a dev to look over.
> 
> Here is a demonstration of my code working where the framebuffer is
> filled with entropy from arc4random_buf() every frame:
> 
> https://www.youtube.com/watch?v=yCzFyZlfbzQ
> 
> Here is the man page in HTML format for convenience:
> 
> https://ce.gl/amdisplay.4.html
> 
> Here is a link to the patch below for when the list mangles it:
> 
> https://ce.gl/amdisplay-apr2.diff.txt
> 
> Note: this driver currently only supports 640x480x16 mode, but is only
> one clock/math problem away from higher modes. Yes, I am aware of fdt
> simple-framebuffer node and yes, this code accomplishes useful things
> which the fdt framebuffer cannot.

Ian,

As you've noticed this diff hasn't seen any real review yet.  One of
the problems is that it adds support for something we don't really
consider to be very important for armv7, on hardware that most of us
consider to be mostly a (very slow) toy which is hard to actually use
as having a framebuffer doesn't really make sense as long as the
serial console is the only actual input device that works in OpenBSD
on the BBB.

The diff itself looks mostly reasonable.  It's probably better to
rename nxptda(4) into something like nxphdmi(4), as nxptda(4) isn't a
very descriptive name.  But before we ask you to make such changes, I
think we really need working USB support.  Without that, this code
really isn't very useful.

Mark

> Index: sys/arch/armv7/conf/GENERIC
> ===================================================================
> RCS file: /cvs/src/sys/arch/armv7/conf/GENERIC,v
> retrieving revision 1.71
> diff -u -p -p -u -r1.71 GENERIC
> --- sys/arch/armv7/conf/GENERIC       23 Jan 2017 22:43:17 -0000      1.71
> +++ sys/arch/armv7/conf/GENERIC       3 Apr 2017 05:24:32 -0000
> @@ -81,6 +81,9 @@ sdmmc*              at ommmc?               # SD/MMC bus
>  
>  omehci*              at fdt?                 # EHCI
>  usb*         at omehci?
> +nxptda*              at iic?                 # TDA19988 HDMI PHY
> +amdisplay*   at fdt?                 # AM335x LCD controller
> +wsdisplay*   at amdisplay?
>  
>  # Sunxi A1x/A20 SoC
>  sxiintc*     at fdt?                 # A1x interrupt controller
> Index: sys/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 -p -u -r1.4 am335x_prcmreg.h
> --- sys/arch/armv7/omap/am335x_prcmreg.h      18 Mar 2014 07:34:17 -0000      
> 1.4
> +++ sys/arch/armv7/omap/am335x_prcmreg.h      3 Apr 2017 05:24:33 -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: sys/arch/armv7/omap/amdisplay.c
> ===================================================================
> RCS file: sys/arch/armv7/omap/amdisplay.c
> diff -N sys/arch/armv7/omap/amdisplay.c
> --- /dev/null 1 Jan 1970 00:00:00 -0000
> +++ sys/arch/armv7/omap/amdisplay.c   3 Apr 2017 05:24:33 -0000
> @@ -0,0 +1,628 @@
> +/*
> + * 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/device.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/ofw_pinctrl.h>
> +#include <dev/ofw/fdt.h>
> +#include <machine/fdt.h>
> +
> +#include <armv7/omap/prcmvar.h>
> +#include <armv7/omap/amdisplayreg.h>
> +#include <armv7/omap/nxptdavar.h>
> +
> +#ifdef LCD_DEBUG
> +int lcd_dbg_thresh = 20;
> +#define DPRINTF(n,s) do { if ((n) <= lcd_dbg_thresh) printf s; } while (0)
> +#else
> +#define DPRINTF(n,s) do {} while (0)
> +#endif
> +
> +#define str(X) #X
> +#define DEVNAME(_s) ((_s)->sc_dev.dv_xname)
> +#define PALETTE_BPP 0x4000
> +
> +#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;
> +
> +     int                     sc_flags;
> +#define LCD_RESET_PENDING (1 << 0)
> +#define LCD_MODE_COMPAT        (1 << 1)
> +#define LCD_MODE_ALLOC         (1 << 2)
> +
> +     struct edid_info        *sc_edid;
> +     struct videomode        *sc_active_mode;
> +     int                     sc_active_depth;
> +
> +     bus_dmamap_t            sc_fb0_dma;
> +     bus_dma_segment_t       sc_fb0_dma_segs[1];
> +     void                    *sc_fb0;
> +     int                     sc_fb_dma_nsegs;
> +     bus_size_t              sc_fb_size;
> +
> +     struct rasops_info      *sc_ro;
> +};
> +
> +struct wsscreen_descr amdisplay_stdscreen = {
> +     "std", 100, 100,
> +     NULL,
> +     0, 0
> +};
> +
> +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);
> +
> +int  amdisplay_setup_dma(struct amdisplay_softc *);
> +void amdisplay_conf_crt_timings(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
> +};
> +
> +void
> +preg(uint32_t reg, char *rn, struct amdisplay_softc *sc)
> +{
> +     uint32_t read;
> +
> +     read = HREAD4(sc, reg);
> +     DPRINTF(16, ("%s: %s: 0x%08x\n", DEVNAME(sc), rn, read));
> +}
> +
> +void
> +dumpregs(struct amdisplay_softc *sc)
> +{
> +     preg(LCD_PID, str(AMDISPLAY_PID), sc);
> +     preg(LCD_CTRL, str(AMDISPLAY_CTRL), sc);
> +     preg(LCD_RASTER_CTRL, str(AMDISPLAY_RASTER_CTRL), sc);
> +     preg(LCD_RASTER_TIMING_0, str(AMDISPLAY_RASTER_TIMING_0), sc);
> +     preg(LCD_RASTER_TIMING_1, str(AMDISPLAY_RASTER_TIMING_1), sc);
> +     preg(LCD_RASTER_TIMING_2, str(AMDISPLAY_RASTER_TIMING_2), sc);
> +     preg(LCD_RASTER_SUBPANEL, str(AMDISPLAY_RASTER_SUBPANEL), sc);
> +     preg(LCD_RASTER_SUBPANEL_2, str(AMDISPLAY_RASTER_SUBPANEL_2), sc);
> +     preg(LCD_LCDDMA_CTRL, str(AMDISPLAY_LCDDMA_CTRL), sc);
> +
> +     /* accessing these regs is liable to occur during CPU lock out period */
> +     #if 0
> +     preg(LCD_LCDDMA_FB0_BASE, str(AMDISPLAY_LCDDMA_FB0_BASE), sc);
> +     preg(LCD_LCDDMA_FB0_CEILING, str(AMDISPLAY_LCDDMA_FB0_CEILING), sc);
> +     preg(LCD_LCDDMA_FB1_BASE, str(AMDISPLAY_LCDDMA_FB1_BASE), sc);
> +     preg(LCD_LCDDMA_FB1_CEILING, str(AMDISPLAY_LCDDMA_FB1_CEILING), sc);
> +     #endif
> +
> +     preg(LCD_SYSCONFIG, str(AMDISPLAY_SYSCONFIG), sc);
> +     preg(LCD_IRQSTATUS_RAW, str(AMDISPLAY_IRQSTATUS_RAW), sc);
> +     preg(LCD_IRQSTATUS, str(AMDISPLAY_IRQSTATUS), sc);
> +     preg(LCD_IRQENABLE_SET, str(AMDISPLAY_IRQENABLE_SET), sc);
> +     preg(LCD_IRQENABLE_CLEAR, str(AMDISPLAY_IRQENABLE_CLEAR), sc);
> +     preg(LCD_CLKC_ENABLE, str(AMDISPLAY_CLKC_ENABLE), sc);
> +     preg(LCD_CLKC_RESET, str(AMDISPLAY_CLKC_RESET), sc);
> +}
> +
> +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 stride, i = 0;
> +
> +     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__);
> +
> +     /* enable clock module */
> +     prcm_enablemodule(PRCM_LCDC);
> +
> +     /* force ourselves out of standby/idle states */
> +     reg = HREAD4(sc, LCD_SYSCONFIG);
> +     reg &= ~(LCD_SYSCONFIG_STANDBYMODE | LCD_SYSCONFIG_IDLEMODE);
> +     reg |= (0x2 << LCD_SYSCONFIG_STANDBYMODE_SHAMT)
> +         |  (0x2 << LCD_SYSCONFIG_IDLEMODE_SHAMT);
> +     HWRITE4(sc, LCD_SYSCONFIG, reg);
> +
> +     irq = faa->fa_intr[0];
> +     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);
> +     sc->sc_active_mode = malloc(sizeof(struct videomode), M_DEVBUF,
> +         M_WAITOK | M_ZERO);
> +     sc->sc_flags |= LCD_MODE_ALLOC;
> +
> +     if (nxptda_get_edid(edid_buf, EDID_LENGTH)
> +         || edid_parse(edid_buf, &edid)) {
> +             printf("%s: no display attached.\n", DEVNAME(sc));
> +             free(edid_buf, M_DEVBUF, EDID_LENGTH);
> +             amdisplay_detach(self, 0);
> +             return;
> +     }
> +
> +     sc->sc_edid = &edid;
> +
> +     /* check to make sure default VGA mode is supported */
> +     for (; i < edid.edid_nmodes - 1; i++)
> +         if (!strcmp(edid.edid_modes[i].name, "640x480x60"))
> +             sc->sc_flags |= LCD_MODE_COMPAT;
> +     i = 0;
> +
> +     if (!ISSET(sc->sc_flags, LCD_MODE_COMPAT)) {
> +         printf("%s: no suitable video modes found\n", DEVNAME(sc));
> +         free(edid_buf, M_DEVBUF, EDID_LENGTH);
> +         amdisplay_detach(self, 0);
> +         return;
> +     }
> +
> +     /* set VGA videomode */
> +     for (; i < videomode_count; i++)
> +         if (!strcmp("640x480x60", videomode_list[i].name))
> +             memcpy(sc->sc_active_mode, &videomode_list[i], sizeof(struct 
> videomode));
> +
> +     sc->sc_active_mode->flags |= VID_HSKEW;
> +     sc->sc_active_depth = 16;
> +
> +     /* configure DMA framebuffer */
> +     if (amdisplay_setup_dma(sc)) {
> +         printf("%s: couldn't allocate DMA framebuffer\n", DEVNAME(sc));
> +         free(edid_buf, M_DEVBUF, EDID_LENGTH);
> +         amdisplay_detach(self, 0);
> +         return;
> +     }
> +
> +     /* setup rasops */
> +     stride = sc->sc_active_mode->hdisplay * sc->sc_active_depth;
> +
> +     sc->sc_ro = 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;
> +     sc->sc_ro->ri_rnum   = 5;
> +     sc->sc_ro->ri_gnum   = 6;
> +     sc->sc_ro->ri_bnum   = 5;
> +     sc->sc_ro->ri_rpos   = 0;
> +     sc->sc_ro->ri_gpos   = 5;
> +     sc->sc_ro->ri_bpos   = 11;
> +
> +     if (rasops_init(sc->sc_ro, 100, 100)) {
> +         printf("%s: no rasops\n", DEVNAME(sc));
> +         amdisplay_detach(self, 0);
> +         return;
> +     }
> +
> +     /* ensure controller is off */
> +     HCLR4(sc, LCD_RASTER_CTRL, LCD_RASTER_CTRL_LCDEN);
> +     delay(100);
> +
> +     /* set clock divisor needed for 640x480 VGA timings */
> +     reg = HREAD4(sc, LCD_CTRL);
> +     reg &= ~LCD_CTRL_CLKDIV;
> +     reg |= (0x2 << LCD_CTRL_CLKDIV_SHAMT);
> +
> +     /* select raster mode & reset-on-underflow, write */
> +     reg |= LCD_CTRL_MODESEL;
> +     HWRITE4(sc, LCD_CTRL, reg);
> +
> +     /* set stn565 + active matrix + pallete loading only mode, delay */
> +     reg = HREAD4(sc, LCD_RASTER_CTRL);
> +     reg &= 0xF8000C7C;
> +     reg |= (LCD_RASTER_CTRL_LCDTFT)
> +         |  (0x02  << LCD_RASTER_CTRL_PALMODE_SHAMT)
> +         |  (0xFF << LCD_RASTER_CTRL_REQDLY_SHAMT);
> +     HWRITE4(sc, LCD_RASTER_CTRL, reg);
> +
> +     /* set timing values */
> +     amdisplay_conf_crt_timings(sc);
> +
> +     /* configure HDMI transmitter (TDA19988) with our mode details */
> +     nxptda_set_videomode(sc->sc_active_mode);
> +
> +     /* latch pins/pads according to fdt node */
> +     pinctrl_byphandle(LCD_FDT_PHANDLE);
> +
> +     /* write bpp empty palette into framebuffer */
> +     memset((void *)sc->sc_fb0, 0, 0x20);
> +     *(unsigned int *)sc->sc_fb0 = PALETTE_BPP;
> +     sc->sc_fb0 += 0x20;
> +
> +     /* configure DMA transfer settings */
> +     reg = HREAD4(sc, LCD_LCDDMA_CTRL);
> +     reg &= ~(LCD_LCDDMA_CTRL_DMA_MASTER_PRIO
> +         | LCD_LCDDMA_CTRL_TH_FIFO_READY
> +         | LCD_LCDDMA_CTRL_BURST_SIZE
> +         | LCD_LCDDMA_CTRL_BYTE_SWAP
> +         | LCD_LCDDMA_CTRL_BIGENDIAN
> +         | LCD_LCDDMA_CTRL_FRAME_MODE);
> +     reg |= (0x4 << LCD_LCDDMA_CTRL_BURST_SIZE_SHAMT);
> +     HWRITE4(sc, LCD_LCDDMA_CTRL, reg); 
> +
> +     /* set framebuffer location + bounds */
> +     HWRITE4(sc, LCD_LCDDMA_FB0, sc->sc_fb0_dma_segs[0].ds_addr);
> +     HWRITE4(sc, LCD_LCDDMA_FB0_CEIL, (sc->sc_fb0_dma_segs[0].ds_addr
> +         + sc->sc_fb_size) - 0);
> +
> +     /* enable all intrs. */
> +     reg = 0;
> +     reg |= (LCD_IRQ_EOF1 | LCD_IRQ_EOF0 | LCD_IRQ_PL | LCD_IRQ_FUF |
> +             LCD_IRQ_ACB | LCD_IRQ_SYNC | LCD_IRQ_RR_DONE | LCD_IRQ_DONE);
> +
> +     HWRITE4(sc, LCD_IRQENABLE_SET, reg);
> +
> +     /* enable dma & core clocks */
> +     HSET4(sc, LCD_CLKC_ENABLE, LCD_CLKC_ENABLE_DMA_CLK_EN
> +         | LCD_CLKC_ENABLE_CORE_CLK_EN
> +         | LCD_CLKC_ENABLE_LIDD_CLK_EN);
> +
> +     /* perform controller clock reset */
> +     HSET4(sc, LCD_CLKC_RESET, LCD_CLKC_RESET_MAIN_RST);
> +     delay(100);
> +     HCLR4(sc, LCD_CLKC_RESET, LCD_CLKC_RESET_MAIN_RST);
> +
> +     /* attach console */
> +     wsaa.console = 0;
> +     wsaa.scrdata = &amdisplay_screenlist;
> +     wsaa.accessops = &amdisplay_accessops;
> +     wsaa.accesscookie = sc;
> +     wsaa.defaultscreens = 0;
> +
> +//   wsdisplay_cnattach(&amdisplay_stdscreen, sc->sc_ro, sc->sc_ro->ri_ccol,
> +//       sc->sc_ro->ri_crow, 0);
> +//   config_found(self, &wsaa, wsemuldisplaydevprint);
> +
> +     /* enable controller */
> +     HSET4(sc, LCD_RASTER_CTRL, LCD_RASTER_CTRL_LCDEN);
> +
> +     dumpregs(sc);
> +}
> +
> +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 (ISSET(sc->sc_flags, LCD_MODE_ALLOC))
> +         free(sc->sc_active_mode, M_DEVBUF, sizeof(struct videomode));
> +
> +     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_unload(sc->sc_dmat, sc->sc_fb0_dma);
> +     bus_dmamem_unmap(sc->sc_dmat, (caddr_t)(sc->sc_fb0), sc->sc_fb_size);
> +     bus_dmamem_free(sc->sc_dmat, sc->sc_fb0_dma_segs, sc->sc_fb_dma_nsegs);
> +     bus_dmamap_destroy(sc->sc_dmat, sc->sc_fb0_dma);
> +
> +     return 0;
> +}
> +
> +int
> +amdisplay_intr(void *arg)
> +{
> +     struct amdisplay_softc *sc = arg;
> +     uint32_t reg, write_through;
> +
> +     reg = HREAD4(sc, LCD_IRQSTATUS);
> +     HWRITE4(sc, LCD_IRQSTATUS, reg);
> +
> +     /* make sure we didn't just cache the ack */
> +     write_through = HREAD4(sc, LCD_IRQSTATUS);
> +
> +     DPRINTF(25, ("%s: intr 0x%08x\n", DEVNAME(sc), reg));
> +
> +     if (ISSET(reg, LCD_IRQ_PL)) {
> +         DPRINTF(10, ("%s: palette loaded, irq: 0x%08x\n",
> +             DEVNAME(sc), reg));
> +         HCLR4(sc, LCD_RASTER_CTRL, LCD_RASTER_CTRL_LCDEN);
> +         delay(100);
> +         memset(sc->sc_fb0, 0, sc->sc_fb_size);
> +         HCLR4(sc, LCD_RASTER_CTRL, LCD_RASTER_CTRL_PALMODE);
> +         HSET4(sc, LCD_RASTER_CTRL, 0x2 << LCD_RASTER_CTRL_PALMODE_SHAMT);
> +         HSET4(sc, LCD_RASTER_CTRL, LCD_RASTER_CTRL_LCDEN);
> +     } if (ISSET(reg, LCD_IRQ_FUF)) { 
> +         DPRINTF(15, ("%s: FIFO underflow\n", DEVNAME(sc)));
> +     } if (ISSET(reg, LCD_IRQ_SYNC)) {
> +         sc->sc_flags |= LCD_RESET_PENDING;
> +         DPRINTF(18, ("%s: sync lost\n", DEVNAME(sc)));
> +     } if (ISSET(reg, LCD_IRQ_RR_DONE)) { /* use ping-pong here XXX */
> +         DPRINTF(21, ("%s: frame done\n", DEVNAME(sc)));
> +         HWRITE4(sc, LCD_LCDDMA_FB0, sc->sc_fb0_dma_segs[0].ds_addr);
> +         HWRITE4(sc, LCD_LCDDMA_FB0_CEIL, (sc->sc_fb0_dma_segs[0].ds_addr
> +             + sc->sc_fb_size) - 1);
> +     } if (ISSET(reg, LCD_IRQ_EOF0)) {
> +         DPRINTF(21, ("%s: framebuffer 0 done\n", DEVNAME(sc)));
> +     } if (ISSET(reg, LCD_IRQ_EOF1)) {
> +         DPRINTF(21, ("%s: framebuffer 1 done\n", DEVNAME(sc)));
> +     } if (ISSET(reg, LCD_IRQ_DONE)) {
> +         if (ISSET(sc->sc_flags, LCD_RESET_PENDING)) {
> +             HWRITE4(sc, LCD_IRQSTATUS, 0xFFFFFFFF); /* XXX */
> +             HSET4(sc, LCD_CLKC_RESET, LCD_CLKC_RESET_MAIN_RST);
> +             delay(10);
> +             HCLR4(sc, LCD_CLKC_RESET, LCD_CLKC_RESET_MAIN_RST);
> +             HSET4(sc, LCD_RASTER_CTRL, LCD_RASTER_CTRL_LCDEN);
> +             sc->sc_flags &= ~LCD_RESET_PENDING;
> +         }
> +         DPRINTF(15, ("%s: last frame done\n", DEVNAME(sc)));
> +     } if (ISSET(reg, LCD_IRQ_ACB)) {
> +         DPRINTF(15, ("%s: AC bias event\n", DEVNAME(sc)));
> +     }
> +
> +     HWRITE4(sc, LCD_IRQ_END, 0);
> +     reg = HREAD4(sc, LCD_IRQ_END);
> +
> +     return 0;
> +}
> +
> +int
> +amdisplay_setup_dma(struct amdisplay_softc *sc)
> +{
> +     bus_size_t bsize;
> +
> +     bsize = (sc->sc_active_mode->hdisplay * sc->sc_active_mode->vdisplay
> +           * sc->sc_active_depth) >> 3;
> +     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, BUS_DMA_NOWAIT, &(sc->sc_fb0_dma)))
> +             return -1;
> +
> +     if (bus_dmamem_alloc(sc->sc_dmat, sc->sc_fb_size, 4, 0,
> +         sc->sc_fb0_dma_segs, 1, &(sc->sc_fb_dma_nsegs),
> +         BUS_DMA_NOWAIT | BUS_DMA_COHERENT))
> +             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),
> +         BUS_DMA_NOWAIT | BUS_DMA_COHERENT | BUS_DMA_NOCACHE))
> +             return -3;
> +
> +     if (bus_dmamap_load(sc->sc_dmat, sc->sc_fb0_dma, sc->sc_fb0, bsize, 
> NULL,
> +         BUS_DMA_NOWAIT))
> +             return -4;
> +
> +     memset(sc->sc_fb0, 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_crt_timings(struct amdisplay_softc *sc)
> +{
> +     uint32_t timing0, timing1, timing2;
> +     uint32_t hbp, hfp, hsw, vbp, vfp, vsw, width, height;
> +     struct videomode *m = sc->sc_active_mode;
> +
> +     timing0 = 0;
> +     timing1 = 0;
> +     timing2 = 0;
> +
> +     hbp = (m->htotal - m->hsync_end) - 1;
> +     hfp = (m->hsync_start - m->hdisplay) - 1;
> +     hsw = (m->hsync_end - m->hsync_start) - 1;
> +
> +     vbp = (m->vtotal - m->vsync_end);
> +     vfp = (m->vsync_start - m->vdisplay);
> +     vsw = (m->vsync_end - m->vsync_start) - 1;
> +     
> +     height = m->vdisplay - 1;
> +     width  = m->hdisplay - 1;
> +
> +     /* Horizontal back porch */
> +     timing0 |= (hbp & 0xff) << LCD_RASTER_TIMING_0_HBP_SHAMT;
> +     timing2 |= ((hbp >> 8) & 3) << LCD_RASTER_TIMING_2_HPB_HIGHBITS_SHAMT;
> +     /* Horizontal front porch */
> +     timing0 |= (hfp & 0xff) << LCD_RASTER_TIMING_0_HFP_SHAMT;
> +     timing2 |= ((hfp >> 8) & 3) << 0;
> +     /* Horizontal sync width */
> +     timing0 |= (hsw & 0x3f) << LCD_RASTER_TIMING_0_HSW_SHAMT;
> +     timing2 |= ((hsw >> 6) & 0xf) << LCD_RASTER_TIMING_2_HSW_HIGHBITS_SHAMT;
> +
> +     /* Vertical back porch, front porch, sync width */
> +     timing1 |= (vbp & 0xff) << LCD_RASTER_TIMING_1_VBP_SHAMT;
> +     timing1 |= (vfp & 0xff) << LCD_RASTER_TIMING_1_VFP_SHAMT;
> +     timing1 |= (vsw & 0x3f) << LCD_RASTER_TIMING_1_VSW_SHAMT;
> +
> +     /* Pixels per line */
> +     timing0 |= ((width >> 10) & 1)
> +         << LCD_RASTER_TIMING_0_PPLMSB_SHAMT;
> +     timing0 |= ((width >> 4) & 0x3f)
> +         << LCD_RASTER_TIMING_0_PPLLSB_SHAMT;
> +
> +     /* Lines per panel */
> +     timing1 |= (height & 0x3ff);
> +     timing2 |= ((height >> 10 ) & 1) 
> +         << LCD_RASTER_TIMING_2_LPP_B10_SHAMT;
> +
> +     /* waveform settings */
> +     timing2 |= LCD_RASTER_TIMING_2_PHSVS_ON_OFF;
> +     timing2 |= (0xff << LCD_RASTER_TIMING_2_ACBI_SHAMT);
> +
> +     if (!ISSET(m->flags, VID_NHSYNC))
> +         timing2 |= LCD_RASTER_TIMING_2_IHS;
> +     if (!ISSET(m->flags, VID_NVSYNC))
> +         timing2 |= LCD_RASTER_TIMING_2_IVS;
> +
> +     HWRITE4(sc, LCD_RASTER_TIMING_0, timing0);
> +     HWRITE4(sc, LCD_RASTER_TIMING_1, timing1);
> +     HWRITE4(sc, LCD_RASTER_TIMING_2, timing2);
> +}
> +
> +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: sys/arch/armv7/omap/amdisplayreg.h
> ===================================================================
> RCS file: sys/arch/armv7/omap/amdisplayreg.h
> diff -N sys/arch/armv7/omap/amdisplayreg.h
> --- /dev/null 1 Jan 1970 00:00:00 -0000
> +++ sys/arch/armv7/omap/amdisplayreg.h        3 Apr 2017 05:24:33 -0000
> @@ -0,0 +1,138 @@
> +/*
> + * 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.
> + */
> +
> +/* AM335x LCDC register offsets */
> +#define LCD_PID                                      0x00
> +#define LCD_CTRL                             0x04
> +#define   LCD_CTRL_CLKDIV                    (0xFF << 8)
> +#define        LCD_CTRL_AUTO_UFLOW_RESTART           (1 << 1)
> +#define   LCD_CTRL_MODESEL                   (1 << 0)
> +#define   LCD_CTRL_CLKDIV_SHAMT                      8
> +#define LCD_RASTER_CTRL                              0x28
> +#define   LCD_RASTER_CTRL_TFT24UNPACKED              (1 << 26)
> +#define   LCD_RASTER_CTRL_TFT24                      (1 << 25)
> +#define        LCD_RASTER_CTRL_STN565                (1 << 24)
> +#define   LCD_RASTER_CTRL_TFTMAP             (1 << 23)
> +#define   LCD_RASTER_CTRL_NIBMODE            (1 << 22)
> +#define   LCD_RASTER_CTRL_PALMODE            (3 << 20)
> +#define   LCD_RASTER_CTRL_REQDLY             (0xFF << 12)
> +#define   LCD_RASTER_CTRL_LCDTFT             (1 << 7)
> +#define   LCD_RASTER_CTRL_LCDEN                      (1 << 0)
> +#define   LCD_RASTER_CTRL_PALMODE_SHAMT              20
> +#define   LCD_RASTER_CTRL_REQDLY_SHAMT               12
> +#define LCD_RASTER_TIMING_0                  0x2C
> +#define   LCD_RASTER_TIMING_0_HBP            (0xFF << 24)
> +#define   LCD_RASTER_TIMING_0_HFP            (0xFF << 16)
> +#define   LCD_RASTER_TIMING_0_HSW            (0x3F << 10)
> +#define   LCD_RASTER_TIMING_0_PPLLSB         (0x3  <<  4)
> +#define   LCD_RASTER_TIMING_0_PPLMSB         (0x1  <<  3)
> +#define   LCD_RASTER_TIMING_0_HBP_SHAMT              24
> +#define   LCD_RASTER_TIMING_0_HFP_SHAMT              16
> +#define   LCD_RASTER_TIMING_0_HSW_SHAMT              10
> +#define   LCD_RASTER_TIMING_0_PPLLSB_SHAMT   4
> +#define   LCD_RASTER_TIMING_0_PPLMSB_SHAMT   3
> +#define LCD_RASTER_TIMING_1                  0x30
> +#define   LCD_RASTER_TIMING_1_VBP            (0xFF  << 24)
> +#define   LCD_RASTER_TIMING_1_VFP            (0xFF  << 16)
> +#define   LCD_RASTER_TIMING_1_VSW            (0x3C  << 10)
> +#define   LCD_RASTER_TIMING_1_LPP            (0x3FF <<  0)
> +#define   LCD_RASTER_TIMING_1_VBP_SHAMT              24
> +#define   LCD_RASTER_TIMING_1_VFP_SHAMT              16
> +#define   LCD_RASTER_TIMING_1_VSW_SHAMT              10
> +#define LCD_RASTER_TIMING_2                  0x34
> +#define   LCD_RASTER_TIMING_2_HSW_HIGHBITS   (0xF  << 27)
> +#define   LCD_RASTER_TIMING_2_LPP_B10                (0x1  << 26)
> +#define   LCD_RASTER_TIMING_2_PHSVS_ON_OFF   (0x1  << 25)
> +#define   LCD_RASTER_TIMING_2_PHSVS_RF               (0x1  << 24)
> +#define   LCD_RASTER_TIMING_2_IEO            (0x1  << 23)
> +#define   LCD_RASTER_TIMING_2_IPC            (0x1  << 22)
> +#define   LCD_RASTER_TIMING_2_IHS            (0x1  << 21)
> +#define   LCD_RASTER_TIMING_2_IVS            (0x1  << 20)
> +#define   LCD_RASTER_TIMING_2_ACBI           (0xF  << 16)
> +#define   LCD_RASTER_TIMING_2_ACB            (0xFF <<  8)
> +#define   LCD_RASTER_TIMING_2_HBP_HIGHBITS   (0x3  <<  4)
> +#define   LCD_RASTER_TIMING_2_HFP_HIGHBITS   (0x3  <<  0)
> +#define   LCD_RASTER_TIMING_2_HSW_HIGHBITS_SHAMT     27
> +#define   LCD_RASTER_TIMING_2_LPP_B10_SHAMT  26
> +#define   LCD_RASTER_TIMING_2_ACBI_SHAMT     16
> +#define   LCD_RASTER_TIMING_2_ACB_SHAMT              8
> +#define   LCD_RASTER_TIMING_2_HPB_HIGHBITS_SHAMT     4
> +#define LCD_RASTER_SUBPANEL                  0x38
> +#define   LCD_RASTER_SUBPANEL_SPEN           (0x1    << 31)
> +#define   LCD_RASTER_SUBPANEL_HOLS           (0x1    << 29)
> +#define   LCD_RASTER_SUBPANEL_LPPT           (0x2FF  << 16)
> +#define   LCD_RASTER_SUBPANEL_DPDLSB         (0xFFFF <<  0)
> +#define   LCD_RASTER_SUBPANEL_LPPT_SHAMT     
> +#define LCD_RASTER_SUBPANEL_2                        0x3C
> +#define   LCD_RASTER_SUBPANEL2_LPPT_B10              (0x1  << 8)
> +#define   LCD_RASTER_SUBPANEL2_DPDMSB                (0xFF << 0)
> +#define LCD_LCDDMA_CTRL                              0x40
> +#define   LCD_LCDDMA_CTRL_DMA_MASTER_PRIO    (0x7 << 0x10)
> +#define   LCD_LCDDMA_CTRL_TH_FIFO_READY              (0x7 << 0x08)
> +#define   LCD_LCDDMA_CTRL_BURST_SIZE         (0x7 << 0x04)
> +#define   LCD_LCDDMA_CTRL_BYTE_SWAP          (0x1 << 0x03)
> +#define   LCD_LCDDMA_CTRL_BIGENDIAN          (0x1 << 0x01)
> +#define   LCD_LCDDMA_CTRL_FRAME_MODE         (0x1 << 0x00)
> +#define   LCD_LCDDMA_CTRL_DMA_MASTER_PRIO_SHAMT      0xFF
> +#define   LCD_LCDDMA_CTRL_TH_FIFO_READY_SHAMT        0x08
> +#define   LCD_LCDDMA_CTRL_BURST_SIZE_SHAMT   0x04
> +#define LCD_LCDDMA_FB0                               0x44
> +#define   LCD_LCDDMA_FB0_BASE                        0xFFFC
> +#define   LCD_LCDDMA_FB0_BASE_SHAMT          0
> +#define LCD_LCDDMA_FB0_CEIL                  0x48
> +#define   LCD_LCDDMA_FB0_CEILING             0xFFFC
> +#define   LCD_LCDDMA_FB0_CEILING_SHAMT               0
> +#define LCD_LCDDMA_FB1                               0x4C
> +#define   LCD_LCDDMA_FB1_BASE                        0xFFFC
> +#define   LCD_LCDDMA_FB1_BASE_SHAMT          0
> +#define LCD_LCDDMA_FB1_CEIL                  0x50
> +#define   LCD_LCDDMA_FB1_CEILING             0xFFFC
> +#define   LCD_LCDDMA_FB1_CEILING_SHAMT               0
> +#define LCD_SYSCONFIG                                0x54
> +#define   LCD_SYSCONFIG_STANDBYMODE          (2 << 4)
> +#define   LCD_SYSCONFIG_IDLEMODE             (2 << 2)
> +#define   LCD_SYSCONFIG_STANDBYMODE_SHAMT    4
> +#define   LCD_SYSCONFIG_IDLEMODE_SHAMT               2
> +#define LCD_IRQSTATUS_RAW                    0x58
> +#define LCD_IRQSTATUS                                0x5C
> +#define LCD_IRQENABLE_SET                    0x60
> +#define LCD_IRQENABLE_CLEAR                  0x64
> +#define LCD_IRQ_END                          0x68
> +#define LCD_CLKC_ENABLE                              0x6C
> +#define   LCD_CLKC_ENABLE_DMA_CLK_EN         (1 << 2)
> +#define   LCD_CLKC_ENABLE_LIDD_CLK_EN                (1 << 1)
> +#define   LCD_CLKC_ENABLE_CORE_CLK_EN                (1 << 0)
> +#define LCD_CLKC_RESET                               0x70
> +#define   LCD_CLKC_RESET_MAIN_RST            (1 << 3)
> +#define   LCD_CLKC_RESET_DMA_RST             (1 << 2)
> +#define   LCD_CLKC_RESET_LIDD_RST            (1 << 1)
> +#define   LCD_CLKC_RESET_CORE_RST            (1 << 0)
> +
> +/* AM335x LCDC intr. masks */
> +#define LCD_IRQ_EOF1 (1 << 9)
> +#define LCD_IRQ_EOF0 (1 << 8)
> +#define LCD_IRQ_PL   (1 << 6)
> +#define LCD_IRQ_FUF  (1 << 5)
> +#define LCD_IRQ_ACB  (1 << 3)
> +#define LCD_IRQ_SYNC (1 << 2)
> +#define LCD_IRQ_RR_DONE      (1 << 1)
> +#define LCD_IRQ_DONE (1 << 0)
> +
> +/* EDID reading */ 
> +#define EDID_LENGTH  0x80
> +
> +/* phandle for pin muxing */
> +#define LCD_FDT_PHANDLE 0x2f
> Index: sys/arch/armv7/omap/files.omap
> ===================================================================
> RCS file: /cvs/src/sys/arch/armv7/omap/files.omap,v
> retrieving revision 1.19
> diff -u -p -p -u -r1.19 files.omap
> --- sys/arch/armv7/omap/files.omap    3 Oct 2016 01:59:20 -0000       1.19
> +++ sys/arch/armv7/omap/files.omap    3 Apr 2017 05:24:33 -0000
> @@ -86,6 +86,10 @@ device omdisplay: wsemuldisplaydev, raso
>  attach omdisplay at omap
>  file arch/armv7/omap/omdisplay.c             omdisplay
>  
> +device amdisplay: wsemuldisplaydev, rasops16
> +attach amdisplay at fdt
> +file arch/armv7/omap/amdisplay.c             amdisplay
> +
>  # MCSPI - spi 
>  device mcspi 
>  attach mcspi at omap
> @@ -95,3 +99,9 @@ file        arch/armv7/omap/mcspi.c                 mcspi
>  device oaudio: audio
>  attach oaudio at omap                                # configure after Atlas 
> Driver
>  file arch/armv7/omap/beagle_audio.c          oaudio
> +
> +# TDA19988 HDMI PHY
> +device nxptda
> +attach nxptda at i2c
> +file arch/armv7/omap/nxptda.c                nxptda
> +
> Index: sys/arch/armv7/omap/nxptda.c
> ===================================================================
> RCS file: sys/arch/armv7/omap/nxptda.c
> diff -N sys/arch/armv7/omap/nxptda.c
> --- /dev/null 1 Jan 1970 00:00:00 -0000
> +++ sys/arch/armv7/omap/nxptda.c      3 Apr 2017 05:24:34 -0000
> @@ -0,0 +1,778 @@
> +/*
> + * Copyright (c) 2016 Ian Sutton <i...@ce.gl>
> + * 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 <go...@freebsd.org>
> + * 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 <dev/ofw/openfirm.h>
> +#include <dev/ofw/ofw_pinctrl.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
> +#ifdef NXPTDA_DEBUG
> +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, node = *(int *)(ia->ia_cookie);
> +
> +     sc->sc_tag = ia->ia_tag;
> +     sc->sc_addr = ia->ia_addr;
> +     sc->sc_curpage = 0xff;
> +
> +     if (!node) {
> +         printf(": not configured\n");
> +         return;
> +     } else if ((pinctrl_byname(node, "default") == -1)) {
> +         printf(": not configured\n");
> +         return;
> +     }
> +
> +     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_HSKEW)
> +         ref_pix += mode->hsync_end - mode->hsync_start;
> +
> +     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: sys/arch/armv7/omap/nxptdavar.h
> ===================================================================
> RCS file: sys/arch/armv7/omap/nxptdavar.h
> diff -N sys/arch/armv7/omap/nxptdavar.h
> --- /dev/null 1 Jan 1970 00:00:00 -0000
> +++ sys/arch/armv7/omap/nxptdavar.h   3 Apr 2017 05:24:34 -0000
> @@ -0,0 +1,18 @@
> +/*
> + * Copyright (c) 2016 Ian Sutton <i...@ce.gl>
> + *
> + * 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: sys/arch/armv7/omap/prcm.c
> ===================================================================
> RCS file: /cvs/src/sys/arch/armv7/omap/prcm.c,v
> retrieving revision 1.11
> diff -u -p -p -u -r1.11 prcm.c
> --- sys/arch/armv7/omap/prcm.c        18 Jul 2016 15:03:01 -0000      1.11
> +++ sys/arch/armv7/omap/prcm.c        3 Apr 2017 05:24:34 -0000
> @@ -75,7 +75,9 @@ uint32_t prcm_fmask_mask[PRCM_REG_MAX];
>  uint32_t prcm_imask_addr[PRCM_REG_MAX];
>  uint32_t prcm_fmask_addr[PRCM_REG_MAX];
>  
> -#define SYS_CLK              13 /* SYS_CLK speed in MHz */
> +#define SYS_CLK                      13    /* SYS_CLK speed in MHz */
> +#define PRCM_AM335X_MASTER_OSC       24000 /* KHz */
> +
>  
>  struct prcm_softc {
>       struct device           sc_dev;
> @@ -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")) {
> @@ -336,6 +339,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__);
>       }
> @@ -350,6 +355,37 @@ prcm_enablemodule(int mod)
>               panic("%s: not initialised!", __func__);
>  
>       sc->sc_enablemodule(sc, mod);
> +}
> +
> +void
> +prcm_am335x_setup(struct prcm_softc *sc)
> +{
> +     uint32_t oreg;
> +
> +     /* Set display PLL for standard VGA resolution (640x480) */
> +     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 |= 0x2F;
> +     oreg |= (0x3EF << 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 |= 0xA;
> +     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
> Index: sys/arch/armv7/omap/prcmvar.h
> ===================================================================
> RCS file: /cvs/src/sys/arch/armv7/omap/prcmvar.h,v
> retrieving revision 1.6
> diff -u -p -p -u -r1.6 prcmvar.h
> --- sys/arch/armv7/omap/prcmvar.h     18 Jul 2016 15:03:01 -0000      1.6
> +++ sys/arch/armv7/omap/prcmvar.h     3 Apr 2017 05:24:34 -0000
> @@ -54,6 +54,7 @@ enum PRCM_MODULES {
>       PRCM_I2C1,
>       PRCM_I2C2,
>       PRCM_I2C3,
> +     PRCM_LCDC,
>  };
>  
>  #define PRCM_REG_MAX 6
> Index: share/man/man4/man4.armv7/amdisplay.4
> ===================================================================
> RCS file: share/man/man4/man4.armv7/amdisplay.4
> diff -N share/man/man4/man4.armv7/amdisplay.4
> --- /dev/null 1 Jan 1970 00:00:00 -0000
> +++ share/man/man4/man4.armv7/amdisplay.4     3 Apr 2017 05:24:42 -0000
> @@ -0,0 +1,73 @@
> +.\" Copyright (c) 2017 Ian Sutton <i...@ce.gl>$
> +.\"
> +.\" 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.
> +.\"
> +.Dd $Mdocdate: April 2 2017 $
> +.Dt AMDISPLAY 4 armv7
> +.Os
> +.Sh NAME
> +.Nm amdisplay ,
> +.Nm nxptda
> +.Nd Texas Instruments am335x LCD display driver
> +.Sh SYNOPSIS
> +.Nm "amdisplay* at simplebus0"
> +.Nm "nxptda* at iic*"
> +.Nm "wsdisplay* at amdisplay*"
> +.Sh DESCRIPTION
> +The
> +.Nm
> +driver supports the LCD controller integrated in Texas Instruments' line of
> +AM335x SoCs.
> +The LCDC reads a framebuffer from memory via DMA and scans it out
> +at the proper frequency to suit a display (along with the nessecary
> +hsync/vsync/etc signals) to a PHY transmitter.
> +The BeagleBone Black uses
> +NXP/Freescale's TDA19988 HDMI transmitter which is additionally supported by 
> the
> +.Nm nxptda
> +driver.
> +.Sh SEE ALSO
> +.Xr intro 4 ,
> +.Xr wsdisplay 4 ,
> +.Xr wsfb 4
> +.Sh HISTORY
> +The
> +.Nm
> +driver does not appear in
> +.Ox 6.1
> +currently.
> +.Sh AUTHORS
> +.An -nosplit
> +The
> +.Nm
> +driver was written by
> +.An Ian Sutton Aq Mt i...@ce.gl .
> +The
> +.Nm nxptda
> +driver was written by
> +.An Oleksandr Tymoshenko Aq Mt go...@freebsd.org
> +and later ported to OpenBSD.
> +.Sh CAVEATS
> +On the BeagleBone Black, the LCDC and onboard eMMC NAND chip share the same 
> set
> +of pads such that only one can be wired and used at a time.
> +If you wish to boot from or use the onboard storage, you must disable
> +.Nm
> +via
> +.Xr config 8
> +in your kernel.
> +.Pp
> +Display must be attached at boot time, otherwise
> +.Nm
> +will fail to configure.
> +Hotplugging is not supported.
> +.Sh BUGS
> +Only VGA mode (640x480) at 16 bit color depth is currently supported.
> 
> 

Reply via email to