svn commit: r256312 - user/ed/newcons/sys/arm/freescale/imx
Aleksandr Rybalko
ray at FreeBSD.org
Fri Oct 11 11:59:51 UTC 2013
Author: ray
Date: Fri Oct 11 11:59:50 2013
New Revision: 256312
URL: http://svnweb.freebsd.org/changeset/base/256312
Log:
Add newcons driver for i.MX515.
Sponsored by: The FreeBSD Foundation
Added:
user/ed/newcons/sys/arm/freescale/imx/imx51_ipuv3_newcons.c (contents, props changed)
Added: user/ed/newcons/sys/arm/freescale/imx/imx51_ipuv3_newcons.c
==============================================================================
--- /dev/null 00:00:00 1970 (empty, because file is newly added)
+++ user/ed/newcons/sys/arm/freescale/imx/imx51_ipuv3_newcons.c Fri Oct 11 11:59:50 2013 (r256312)
@@ -0,0 +1,519 @@
+/*-
+ * Copyright (c) 2012 Oleksandr Tymoshenko <gonzo at freebsd.org>
+ * Copyright (c) 2012, 2013 The FreeBSD Foundation
+ * All rights reserved.
+ *
+ * Portions of this software were developed by Oleksandr Rybalko
+ * under sponsorship from the FreeBSD Foundation.
+ *
+ * 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/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bio.h>
+#include <sys/bus.h>
+#include <sys/conf.h>
+#include <sys/endian.h>
+#include <sys/kernel.h>
+#include <sys/kthread.h>
+#include <sys/lock.h>
+#include <sys/malloc.h>
+#include <sys/module.h>
+#include <sys/mutex.h>
+#include <sys/queue.h>
+#include <sys/resource.h>
+#include <sys/rman.h>
+#include <sys/time.h>
+#include <sys/timetc.h>
+#include <sys/fbio.h>
+#include <sys/consio.h>
+
+#include <sys/kdb.h>
+
+#include <machine/bus.h>
+#include <machine/cpu.h>
+#include <machine/cpufunc.h>
+#include <machine/resource.h>
+#include <machine/frame.h>
+#include <machine/intr.h>
+
+#include <dev/fdt/fdt_common.h>
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+
+#include <dev/vt/vt.h>
+
+#include <arm/freescale/imx/imx51_ccmvar.h>
+
+#include <arm/freescale/imx/imx51_ipuv3reg.h>
+
+#define IMX51_IPU_HSP_CLOCK 665000000
+#define IPU3FB_FONT_HEIGHT 16
+
+struct ipu3sc_softc {
+ device_t dev;
+
+ intptr_t sc_paddr;
+ intptr_t sc_vaddr;
+ size_t sc_fb_size;
+ int sc_depth;
+ /* Storage for one pixel maybe bigger than color depth. */
+ int sc_bpp;
+ int sc_stride;
+ int sc_width;
+ int sc_height;
+
+ bus_space_tag_t iot;
+ bus_space_handle_t ioh;
+ bus_space_handle_t cm_ioh;
+ bus_space_handle_t dp_ioh;
+ bus_space_handle_t di0_ioh;
+ bus_space_handle_t di1_ioh;
+ bus_space_handle_t dctmpl_ioh;
+ bus_space_handle_t dc_ioh;
+ bus_space_handle_t dmfc_ioh;
+ bus_space_handle_t idmac_ioh;
+ bus_space_handle_t cpmem_ioh;
+};
+
+static struct ipu3sc_softc *ipu3sc_softc;
+
+#if 0
+/* FIXME: not only 2 bytes color supported */
+static uint16_t colors[16] = {
+ 0x0000, /* black */
+ 0x001f, /* blue */
+ 0x07e0, /* green */
+ 0x07ff, /* cyan */
+ 0xf800, /* red */
+ 0xf81f, /* magenta */
+ 0x3800, /* brown */
+ 0xc618, /* light grey */
+ 0xc618, /* XXX: dark grey */
+ 0x001f, /* XXX: light blue */
+ 0x07e0, /* XXX: light green */
+ 0x07ff, /* XXX: light cyan */
+ 0xf800, /* XXX: light red */
+ 0xf81f, /* XXX: light magenta */
+ 0xffe0, /* yellow */
+ 0xffff, /* white */
+};
+static uint32_t colors_24[16] = {
+ 0x000000,/* Black */
+ 0x000080,/* Blue */
+ 0x008000,/* Green */
+ 0x008080,/* Cyan */
+ 0x800000,/* Red */
+ 0x800080,/* Magenta */
+ 0xcc6600,/* brown */
+ 0xC0C0C0,/* Silver */
+ 0x808080,/* Gray */
+ 0x0000FF,/* Light Blue */
+ 0x00FF00,/* Light Green */
+ 0x00FFFF,/* Light Cyan */
+ 0xFF0000,/* Light Red */
+ 0xFF00FF,/* Light Magenta */
+ 0xFFFF00,/* Yellow */
+ 0xFFFFFF,/* White */
+
+
+};
+#endif
+
+static vd_init_t vt_imx_init;
+static vd_blank_t vt_imx_blank;
+static vd_bitblt_t vt_imx_bitblt;
+
+static struct vt_driver vt_imx_driver = {
+ .vd_init = vt_imx_init,
+ .vd_blank = vt_imx_blank,
+ .vd_bitblt = vt_imx_bitblt,
+};
+
+static const uint32_t colormap[] = {
+ 0x00000000, /* Black */
+ 0x00ff0000, /* Red */
+ 0x0000ff00, /* Green */
+ 0x00c0c000, /* Brown */
+ 0x000000ff, /* Blue */
+ 0x00c000c0, /* Magenta */
+ 0x0000c0c0, /* Cyan */
+ 0x00c0c0c0, /* Light grey */
+ 0x00808080, /* Dark grey */
+ 0x00ff8080, /* Light red */
+ 0x0080ff80, /* Light green */
+ 0x00ffff80, /* Yellow */
+ 0x008080ff, /* Light blue */
+ 0x00ff80ff, /* Light magenta */
+ 0x0080ffff, /* Light cyan */
+ 0x00ffffff, /* White */
+};
+
+#define IPUV3_READ(ipuv3, module, reg) \
+ bus_space_read_4((ipuv3)->iot, (ipuv3)->module##_ioh, (reg))
+#define IPUV3_WRITE(ipuv3, module, reg, val) \
+ bus_space_write_4((ipuv3)->iot, (ipuv3)->module##_ioh, (reg), (val))
+
+#define CPMEM_CHANNEL_OFFSET(_c) ((_c) * 0x40)
+#define CPMEM_WORD_OFFSET(_w) ((_w) * 0x20)
+#define CPMEM_DP_OFFSET(_d) ((_d) * 0x10000)
+#define IMX_IPU_DP0 0
+#define IMX_IPU_DP1 1
+#define CPMEM_CHANNEL(_dp, _ch, _w) \
+ (CPMEM_DP_OFFSET(_dp) + CPMEM_CHANNEL_OFFSET(_ch) + \
+ CPMEM_WORD_OFFSET(_w))
+#define CPMEM_OFFSET(_dp, _ch, _w, _o) \
+ (CPMEM_CHANNEL((_dp), (_ch), (_w)) + (_o))
+
+#define IPUV3_DEBUG 100
+
+#ifdef IPUV3_DEBUG
+#define SUBMOD_DUMP_REG(_sc, _m, _l) \
+ { \
+ int i; \
+ printf("*** " #_m " ***\n"); \
+ for (i = 0; i <= (_l); i += 4) { \
+ if ((i % 32) == 0) \
+ printf("%04x: ", i & 0xffff); \
+ printf("0x%08x%c", IPUV3_READ((_sc), _m, i), \
+ ((i + 4) % 32)?' ':'\n'); \
+ } \
+ printf("\n"); \
+ }
+#endif
+
+#ifdef IPUV3_DEBUG
+int ipuv3_debug = IPUV3_DEBUG;
+#define DPRINTFN(n,x) if (ipuv3_debug>(n)) printf x; else
+#else
+#define DPRINTFN(n,x)
+#endif
+
+static int ipu3_fb_probe(device_t);
+static int ipu3_fb_attach(device_t);
+
+static int
+ipu3_fb_malloc(struct ipu3sc_softc *sc, size_t size)
+{
+
+ sc->sc_vaddr = (intptr_t)contigmalloc(size, M_DEVBUF, M_ZERO, 0, ~0,
+ PAGE_SIZE, 0);
+ sc->sc_paddr = (intptr_t)vtophys(sc->sc_vaddr);
+
+ return (0);
+}
+
+static void
+ipu3_fb_init(struct ipu3sc_softc *sc)
+{
+ uint64_t w0sh96;
+ uint32_t w1sh96;
+
+ /* FW W0[137:125] - 96 = [41:29] */
+ /* FH W0[149:138] - 96 = [53:42] */
+ w0sh96 = IPUV3_READ(sc, cpmem, CPMEM_OFFSET(IMX_IPU_DP1, 23, 0, 16));
+ w0sh96 <<= 32;
+ w0sh96 |= IPUV3_READ(sc, cpmem, CPMEM_OFFSET(IMX_IPU_DP1, 23, 0, 12));
+
+ sc->sc_width = ((w0sh96 >> 29) & 0x1fff) + 1;
+ sc->sc_height = ((w0sh96 >> 42) & 0x0fff) + 1;
+
+ /* SLY W1[115:102] - 96 = [19:6] */
+ w1sh96 = IPUV3_READ(sc, cpmem, CPMEM_OFFSET(IMX_IPU_DP1, 23, 1, 12));
+ sc->sc_stride = ((w1sh96 >> 6) & 0x3fff) + 1;
+
+ printf("%dx%d [%d]\n", sc->sc_width, sc->sc_height, sc->sc_stride);
+ sc->sc_fb_size = sc->sc_height * sc->sc_stride;
+
+ ipu3_fb_malloc(sc, sc->sc_fb_size);
+
+ /* DP1 + config_ch_23 + word_2 */
+ IPUV3_WRITE(sc, cpmem, CPMEM_OFFSET(IMX_IPU_DP1, 23, 1, 0),
+ (((uint32_t)sc->sc_paddr >> 3) |
+ (((uint32_t)sc->sc_paddr >> 3) << 29)) & 0xffffffff);
+
+ IPUV3_WRITE(sc, cpmem, CPMEM_OFFSET(IMX_IPU_DP1, 23, 1, 4),
+ (((uint32_t)sc->sc_paddr >> 3) >> 3) & 0xffffffff);
+
+ /* XXX: fetch or set it from/to IPU. */
+ sc->sc_depth = sc->sc_stride / sc->sc_width * 8;
+ sc->sc_bpp = sc->sc_stride / sc->sc_width;
+}
+
+static int
+ipu3_fb_probe(device_t dev)
+{
+
+ if (!ofw_bus_is_compatible(dev, "fsl,ipu3"))
+ return (ENXIO);
+
+ device_set_desc(dev, "i.MX515 Image Processing Unit (FB)");
+
+ return (BUS_PROBE_DEFAULT);
+}
+
+static int
+ipu3_fb_attach(device_t dev)
+{
+ struct ipu3sc_softc *sc = device_get_softc(dev);
+ bus_space_tag_t iot;
+ bus_space_handle_t ioh;
+ int err;
+
+ ipu3sc_softc = sc;
+
+ device_printf(dev, "\tclock gate status is %d\n",
+ imx51_get_clk_gating(IMX51CLK_IPU_HSP_CLK_ROOT));
+
+ sc->dev = dev;
+
+ sc = device_get_softc(dev);
+ sc->iot = iot = fdtbus_bs_tag;
+
+ device_printf(sc->dev, ": i.MX51 IPUV3 controller\n");
+
+ /* map controller registers */
+ err = bus_space_map(iot, IPU_CM_BASE, IPU_CM_SIZE, 0, &ioh);
+ if (err)
+ goto fail_retarn_cm;
+ sc->cm_ioh = ioh;
+
+ /* map Display Multi FIFO Controller registers */
+ err = bus_space_map(iot, IPU_DMFC_BASE, IPU_DMFC_SIZE, 0, &ioh);
+ if (err)
+ goto fail_retarn_dmfc;
+ sc->dmfc_ioh = ioh;
+
+ /* map Display Interface 0 registers */
+ err = bus_space_map(iot, IPU_DI0_BASE, IPU_DI0_SIZE, 0, &ioh);
+ if (err)
+ goto fail_retarn_di0;
+ sc->di0_ioh = ioh;
+
+ /* map Display Interface 1 registers */
+ err = bus_space_map(iot, IPU_DI1_BASE, IPU_DI0_SIZE, 0, &ioh);
+ if (err)
+ goto fail_retarn_di1;
+ sc->di1_ioh = ioh;
+
+ /* map Display Processor registers */
+ err = bus_space_map(iot, IPU_DP_BASE, IPU_DP_SIZE, 0, &ioh);
+ if (err)
+ goto fail_retarn_dp;
+ sc->dp_ioh = ioh;
+
+ /* map Display Controller registers */
+ err = bus_space_map(iot, IPU_DC_BASE, IPU_DC_SIZE, 0, &ioh);
+ if (err)
+ goto fail_retarn_dc;
+ sc->dc_ioh = ioh;
+
+ /* map Image DMA Controller registers */
+ err = bus_space_map(iot, IPU_IDMAC_BASE, IPU_IDMAC_SIZE, 0, &ioh);
+ if (err)
+ goto fail_retarn_idmac;
+ sc->idmac_ioh = ioh;
+
+ /* map CPMEM registers */
+ err = bus_space_map(iot, IPU_CPMEM_BASE, IPU_CPMEM_SIZE, 0, &ioh);
+ if (err)
+ goto fail_retarn_cpmem;
+ sc->cpmem_ioh = ioh;
+
+ /* map DCTEMPL registers */
+ err = bus_space_map(iot, IPU_DCTMPL_BASE, IPU_DCTMPL_SIZE, 0, &ioh);
+ if (err)
+ goto fail_retarn_dctmpl;
+ sc->dctmpl_ioh = ioh;
+
+#ifdef notyet
+ sc->ih = imx51_ipuv3_intr_establish(IMX51_INT_IPUV3, IPL_BIO,
+ ipuv3intr, sc);
+ if (sc->ih == NULL) {
+ device_printf(sc->dev,
+ "unable to establish interrupt at irq %d\n",
+ IMX51_INT_IPUV3);
+ return (ENXIO);
+ }
+#endif
+
+ /*
+ * We have to wait until interrupts are enabled.
+ * Mailbox relies on it to get data from VideoCore
+ */
+ ipu3_fb_init(sc);
+
+ vt_allocate(&vt_imx_driver, sc);
+
+ return (0);
+
+fail_retarn_dctmpl:
+ bus_space_unmap(sc->iot, sc->cpmem_ioh, IPU_CPMEM_SIZE);
+fail_retarn_cpmem:
+ bus_space_unmap(sc->iot, sc->idmac_ioh, IPU_IDMAC_SIZE);
+fail_retarn_idmac:
+ bus_space_unmap(sc->iot, sc->dc_ioh, IPU_DC_SIZE);
+fail_retarn_dp:
+ bus_space_unmap(sc->iot, sc->dp_ioh, IPU_DP_SIZE);
+fail_retarn_dc:
+ bus_space_unmap(sc->iot, sc->di1_ioh, IPU_DI1_SIZE);
+fail_retarn_di1:
+ bus_space_unmap(sc->iot, sc->di0_ioh, IPU_DI0_SIZE);
+fail_retarn_di0:
+ bus_space_unmap(sc->iot, sc->dmfc_ioh, IPU_DMFC_SIZE);
+fail_retarn_dmfc:
+ bus_space_unmap(sc->iot, sc->dc_ioh, IPU_CM_SIZE);
+fail_retarn_cm:
+ device_printf(sc->dev,
+ "failed to map registers (errno=%d)\n", err);
+ return (err);
+}
+
+static device_method_t ipu3_fb_methods[] = {
+ /* Device interface */
+ DEVMETHOD(device_probe, ipu3_fb_probe),
+ DEVMETHOD(device_attach, ipu3_fb_attach),
+
+ { 0, 0 }
+};
+
+static devclass_t ipu3_fb_devclass;
+
+static driver_t ipu3_fb_driver = {
+ "fb",
+ ipu3_fb_methods,
+ sizeof(struct ipu3sc_softc),
+};
+
+DRIVER_MODULE(ipu3fb, simplebus, ipu3_fb_driver, ipu3_fb_devclass, 0, 0);
+
+static void
+vt_imx_blank(struct vt_device *vd, term_color_t color)
+{
+ struct ipu3sc_softc *sc = vd->vd_softc;
+ u_int ofs;
+ uint32_t c;
+
+ c = colormap[color];
+ switch (sc->sc_bpp) {
+ case 1:
+ for (ofs = 0; ofs < (sc->sc_stride * sc->sc_height); ofs++)
+ *(uint8_t *)(sc->sc_vaddr + ofs) = c & 0xff;
+ break;
+ case 2:
+ /* XXX must be 16bits colormap */
+ for (ofs = 0; ofs < (sc->sc_stride * sc->sc_height); ofs++)
+ *(uint16_t *)(sc->sc_vaddr + 2 * ofs) = c 0xffff;
+ break;
+ case 3: /* */
+ /* line 0 */
+ for (ofs = 0; ofs < sc->sc_stride; ofs++) {
+ *(uint8_t *)(sc->sc_vaddr + ofs + 0) = c >> 0& 0xff;
+ *(uint8_t *)(sc->sc_vaddr + ofs + 1) = c >> 8 & 0xff;
+ *(uint8_t *)(sc->sc_vaddr + ofs + 2) = c >> 16 & 0xff;
+ }
+ /* Copy line0 to all other lines. */
+ for (ofs = 1; ofs < sc->sc_height; ofs++) {
+ memmove((void *)(sc->sc_vaddr + ofs * sc->sc_stride),
+ (void *)sc->sc_vaddr, sc->sc_stride);
+ }
+ break;
+ case 4:
+ for (ofs = 0; ofs < (sc->sc_stride * sc->sc_height); ofs++)
+ *(uint32_t *)(sc->sc_vaddr + 4 * ofs) = c;
+ break;
+ default:
+ /* panic? */
+ break;
+ }
+}
+
+static void
+vt_imx_bitblt(struct vt_device *vd, const uint8_t *src,
+ vt_axis_t top, vt_axis_t left, unsigned int width, unsigned int height,
+ term_color_t fg, term_color_t bg)
+{
+ struct ipu3sc_softc *sc = vd->vd_softc;
+ u_long line;
+ uint32_t fgc, bgc, cc, o;
+ int c, l, bpp;
+ uint8_t b = 0;
+
+ bpp = sc->sc_bpp;
+ fgc = colormap[fg];
+ bgc = colormap[bg];
+
+ line = sc->sc_vaddr + (sc->sc_stride * top) + (left * bpp);
+ for (l = 0; l < height; l++) {
+ for (c = 0; c < width; c++) {
+ if (c % 8 == 0)
+ b = *src++;
+ else
+ b <<= 1;
+ o = line + (c * bpp);
+ cc = b & 0x80 ? fgc : bgc;
+
+ switch(bpp) {
+ case 1:
+ *(uint8_t *)(o) = cc;
+ break;
+ case 2:
+ *(uint16_t *)(o) = cc;
+ break;
+ case 3:
+ /* Packed mode, so unaligned. Byte access. */
+ *(uint8_t *)(o + 0) = (cc >> 16) & 0xff;
+ *(uint8_t *)(o + 1) = (cc >> 8) & 0xff;
+ *(uint8_t *)(o + 2) = (cc >> 0) & 0xff;
+ break;
+ case 4:
+ /* Cover both: 32bits and aligned 24bits. */
+ *(uint32_t *)(o) = cc;
+ break;
+ default:
+ /* panic? */
+ break;
+ }
+ }
+ line += sc->sc_stride;
+ }
+}
+
+static int
+vt_imx_init(struct vt_device *vd)
+{
+ struct ipu3sc_softc *sc;
+
+ sc = vd->vd_softc;
+
+ vd->vd_height = sc->sc_height;
+ vd->vd_width = sc->sc_width;
+
+ /* Clear the screen. */
+ vt_imx_blank(vd, TC_BLACK);
+
+ return (CN_INTERNAL);
+}
More information about the svn-src-user
mailing list