summaryrefslogtreecommitdiff
path: root/sys/arch
diff options
context:
space:
mode:
Diffstat (limited to 'sys/arch')
-rw-r--r--sys/arch/arm/s3c2xx0/s3c24x0_lcd.c775
-rw-r--r--sys/arch/arm/s3c2xx0/s3c24x0_lcd.h124
-rw-r--r--sys/arch/moko/conf/RAMDISK14
-rw-r--r--sys/arch/moko/conf/files.moko6
-rw-r--r--sys/arch/moko/moko/moko_machdep.c23
5 files changed, 929 insertions, 13 deletions
diff --git a/sys/arch/arm/s3c2xx0/s3c24x0_lcd.c b/sys/arch/arm/s3c2xx0/s3c24x0_lcd.c
new file mode 100644
index 00000000000..df7c268931d
--- /dev/null
+++ b/sys/arch/arm/s3c2xx0/s3c24x0_lcd.c
@@ -0,0 +1,775 @@
+/* $NetBSD: s3c24x0_lcd.c,v 1.6 2007/12/15 00:39:15 perry Exp $ */
+
+/*
+ * Copyright (c) 2004 Genetec Corporation. All rights reserved.
+ * Written by Hiroyuki Bessho for Genetec Corporation.
+ *
+ * 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.
+ * 3. The name of Genetec Corporation may not be used to endorse or
+ * promote products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY GENETEC CORPORATION ``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 GENETEC CORPORATION
+ * 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.
+ */
+
+/*
+ * Support S3C24[10]0's integrated LCD controller.
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/conf.h>
+#include <sys/uio.h>
+#include <sys/malloc.h>
+#include <sys/kernel.h> /* for cold */
+
+#include <uvm/uvm_extern.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/wsfont/wsfont.h>
+
+#include <machine/bus.h>
+#include <machine/cpu.h>
+#include <arm/cpufunc.h>
+
+#include <arm/s3c2xx0/s3c24x0var.h>
+#include <arm/s3c2xx0/s3c24x0reg.h>
+#include <arm/s3c2xx0/s3c24x0_lcd.h>
+
+#include "wsdisplay.h"
+
+int lcdintr(void *);
+static void init_palette(struct s3c24x0_lcd_softc *,
+ struct s3c24x0_lcd_screen *);
+
+#ifdef LCD_DEBUG
+static void
+dump_lcdcon(const char *title, bus_space_tag_t iot, bus_space_handle_t ioh)
+{
+ int i;
+
+ printf("%s\n", title);
+ for(i=LCDC_LCDCON1; i <= LCDC_LCDSADDR3; i+=4) {
+ if (i%16 == 0)
+ printf("\n%03x: ", i);
+ printf("%08x ", bus_space_read_4(iot, ioh, i));
+ }
+
+ printf("\n");
+}
+
+void draw_test_pattern(struct s3c24x0_lcd_softc *,
+ struct s3c24x0_lcd_screen *scr);
+
+#endif
+
+void
+s3c24x0_set_lcd_panel_info(struct s3c24x0_lcd_softc *sc,
+ struct s3c24x0_lcd_panel_info *info)
+{
+ bus_space_tag_t iot = sc->iot;
+ bus_space_handle_t ioh = sc->ioh;
+ uint32_t reg;
+ int clkval;
+ int tft = s3c24x0_lcd_panel_tft(info);
+ int hclk = s3c2xx0_softc->sc_hclk;
+
+ sc->panel_info = info;
+
+ /* Set LCDCON1. BPPMODE and ENVID are set later */
+ if (tft) {
+ clkval = (hclk / info->pixel_clock / 2) - 1;
+ printf("clk %x hclk %x pix %d\n", clkval, hclk, info->pixel_clock);
+ } else {
+ /* STN display */
+ clkval = max(2, hclk / info->pixel_clock / 2);
+ printf("clk %x hclk %x pix %d\n", clkval, hclk, info->pixel_clock);
+ }
+
+ reg = (info->lcdcon1 & ~LCDCON1_CLKVAL_MASK) |
+ (clkval << LCDCON1_CLKVAL_SHIFT);
+ reg &= ~LCDCON1_ENVID;
+ printf("lcdcon1 old %x, new %x\n", bus_space_read_4(iot, ioh, LCDC_LCDCON1), reg);
+ bus_space_write_4(iot, ioh, LCDC_LCDCON1, reg);
+
+#if 0
+ printf("hclk=%d pixel clock=%d, clkval = %x lcdcon1=%x\n",
+ hclk, info->pixel_clock, clkval, reg);
+#endif
+
+ printf("lcdcon2 old %x, new %x\n", bus_space_read_4(iot, ioh, LCDC_LCDCON2), info->lcdcon2);
+ bus_space_write_4(iot, ioh, LCDC_LCDCON2, info->lcdcon2);
+ printf("lcdcon3 old %x, new %x\n", bus_space_read_4(iot, ioh, LCDC_LCDCON3), info->lcdcon3);
+ bus_space_write_4(iot, ioh, LCDC_LCDCON3, info->lcdcon3);
+ printf("lcdcon4 old %x, new %x\n", bus_space_read_4(iot, ioh, LCDC_LCDCON4), info->lcdcon4);
+ bus_space_write_4(iot, ioh, LCDC_LCDCON4, info->lcdcon4);
+ printf("lcdcon5 old %x, new %x\n", bus_space_read_4(iot, ioh, LCDC_LCDCON5), info->lcdcon5);
+ bus_space_write_4(iot, ioh, LCDC_LCDCON5, info->lcdcon5);
+ printf("lpcsel old %x, new %x\n", bus_space_read_4(iot, ioh, LCDC_LPCSEL), info->lpcsel);
+ bus_space_write_4(iot, ioh, LCDC_LPCSEL, info->lpcsel);
+}
+
+void
+s3c24x0_lcd_attach_sub(struct s3c24x0_lcd_softc *sc,
+ struct s3c2xx0_attach_args *sa,
+ struct s3c24x0_lcd_panel_info *panel_info)
+{
+ bus_space_tag_t iot = sa->sa_iot;
+ bus_space_handle_t ioh;
+ int error;
+
+ sc->n_screens = 0;
+ LIST_INIT(&sc->screens);
+
+ /* map controller registers */
+ error = bus_space_map(iot, sa->sa_addr, S3C24X0_LCDC_SIZE, 0, &ioh);
+ if (error) {
+ printf(": failed to map registers %d", error);
+ return;
+ }
+
+ sc->iot = iot;
+ sc->ioh = ioh;
+ sc->dma_tag = sa->sa_dmat;
+
+#ifdef notyet
+ sc->ih = s3c24x0_intr_establish(sa->sa_intr, IPL_BIO, lcdintr, sc);
+ if (sc->ih == NULL)
+ printf("%s: unable to establish interrupt at irq %d",
+ sc->dev.dv_xname, sa->sa_intr);
+#endif
+
+ /* mask LCD interrupts */
+ bus_space_write_4(iot, ioh, LCDC_LCDINTMSK, LCDINT_FICNT|LCDINT_FRSYN);
+
+ /* Initialize controller registers based on panel geometry*/
+ s3c24x0_set_lcd_panel_info(sc, panel_info);
+
+ /* XXX: enable clock to LCD controller */
+}
+
+
+#ifdef notyet
+int
+lcdintr(void *arg)
+{
+ struct s3c24x0_lcd_softc *sc = arg;
+ bus_space_tag_t iot = sc->iot;
+ bus_space_handle_t ioh = sc->ioh;
+
+ static uint32_t status;
+
+ return 1;
+}
+#endif
+
+int
+s3c24x0_lcd_start_dma(struct s3c24x0_lcd_softc *sc,
+ struct s3c24x0_lcd_screen *scr)
+{
+ bus_space_tag_t iot = sc->iot;
+ bus_space_handle_t ioh = sc->ioh;
+ const struct s3c24x0_lcd_panel_info *info = sc->panel_info;
+ int tft = s3c24x0_lcd_panel_tft(info);
+ int dual_panel =
+ (info->lcdcon1 & LCDCON1_PNRMODE_MASK) == LCDCON1_PNRMODE_DUALSTN4;
+ uint32_t lcdcon1, val;
+ paddr_t pa;
+ int depth = scr->depth;
+ int stride = scr->stride;
+ int panel_height = info->panel_height;
+ int panel_width = info->panel_width;
+ int offsize;
+
+ switch (depth) {
+ case 1: val = LCDCON1_BPPMODE_STN1; break;
+ case 2: val = LCDCON1_BPPMODE_STN2; break;
+ case 4: val = LCDCON1_BPPMODE_STN4; break;
+ case 8: val = LCDCON1_BPPMODE_STN8; break;
+ case 12:
+ if (tft)
+ return -1;
+ val = LCDCON1_BPPMODE_STN12;
+ break;
+ case 16:
+ if (!tft)
+ return -1;
+ val = LCDCON1_BPPMODE_TFT16;
+ break;
+ case 24:
+ if (!tft)
+ return -1;
+ val = LCDCON1_BPPMODE_TFT24;
+ break;
+ default:
+ return -1;
+ }
+
+ if (tft)
+ val |= LCDCON1_BPPMODE_TFTX;
+
+ lcdcon1 = bus_space_read_4(iot, ioh, LCDC_LCDCON1);
+ lcdcon1 &= ~(LCDCON1_BPPMODE_MASK|LCDCON1_ENVID);
+ lcdcon1 |= val;
+ bus_space_write_4(iot, ioh, LCDC_LCDCON1, lcdcon1);
+
+ /* Adjust LCDCON3.HOZVAL to meet with restriction */
+ val = roundup(panel_width, 16 / depth);
+ bus_space_write_4(iot, ioh, LCDC_LCDCON3,
+ (info->lcdcon3 & ~LCDCON3_HOZVAL_MASK) |
+ (val - 1) << LCDCON3_HOZVAL_SHIFT);
+
+ pa = scr->segs[0].ds_addr;
+ bus_space_write_4(iot, ioh, LCDC_LCDSADDR1, pa >> 1);
+
+ if (dual_panel) {
+ /* XXX */
+ }
+ else {
+ pa += stride * panel_height;
+ bus_space_write_4(iot, ioh, LCDC_LCDSADDR2, pa >> 1);
+ }
+
+ offsize = stride / sizeof (uint16_t) - (panel_width * depth / 16);
+ printf("offset %x %x %x\n", stride,
+ (panel_width * depth / 16),
+ (offsize << LCDSADDR3_OFFSIZE_SHIFT) |
+ (panel_width * depth / 16));
+
+
+ bus_space_write_4(iot, ioh, LCDC_LCDSADDR3,
+ (offsize << LCDSADDR3_OFFSIZE_SHIFT) |
+ (panel_width * depth / 16));
+
+ /* set byte- or halfword- swap based on the depth */
+ val = bus_space_read_4(iot, ioh, LCDC_LCDCON5);
+ val &= ~(LCDCON5_BSWP|LCDCON5_HWSWP);
+ switch(depth) {
+ case 2:
+ case 4:
+ case 8:
+ val |= LCDCON5_BSWP;
+ break;
+ case 16:
+ val |= LCDCON5_HWSWP;
+ break;
+ }
+ bus_space_write_4(iot, ioh, LCDC_LCDCON5, val);
+
+
+ init_palette(sc, scr);
+
+#if 0
+ bus_space_write_4(iot, ioh, LCDC_TPAL, TPAL_TPALEN|
+ (0xff<<TPAL_BLUE_SHIFT));
+#endif
+
+ /* Enable LCDC */
+ bus_space_write_4(iot, ioh, LCDC_LCDCON1, lcdcon1 | LCDCON1_ENVID);
+
+ sc->lcd_on = 1;
+
+#ifdef LCD_DEBUG
+ dump_lcdcon(__func__, iot, ioh);
+#endif
+
+ return 0;
+}
+
+void
+s3c24x0_lcd_power(struct s3c24x0_lcd_softc *sc, int on)
+{
+ bus_space_tag_t iot = sc->iot;
+ bus_space_handle_t ioh = sc->ioh;
+ uint32_t reg;
+
+ reg = bus_space_read_4(iot, ioh, LCDC_LCDCON5);
+
+ if (on)
+ reg |= LCDCON5_PWREN;
+ else
+ reg &= ~LCDCON5_PWREN;
+
+ bus_space_write_4(iot, ioh, LCDC_LCDCON5, reg);
+}
+
+struct s3c24x0_lcd_screen *
+s3c24x0_lcd_new_screen(struct s3c24x0_lcd_softc *sc,
+ int virtual_width, int virtual_height, int depth)
+{
+ struct s3c24x0_lcd_screen *scr = NULL;
+ int width, height;
+ bus_size_t size;
+ int error, pallet_size;
+ int busdma_flag = (cold ? BUS_DMA_NOWAIT : BUS_DMA_WAITOK) |
+ BUS_DMA_WRITE;
+ paddr_t align;
+ const struct s3c24x0_lcd_panel_info *panel_info = sc->panel_info;
+
+
+#ifdef DIAGNOSTIC
+ if (size > 1 << 22) {
+ printf("%s: too big screen size\n", sc->dev.dv_xname);
+ return NULL;
+ }
+#endif
+
+ width = panel_info->panel_width;
+ height = panel_info->panel_height;
+ pallet_size = 0;
+
+ switch (depth) {
+ case 1: case 2: case 4: case 8:
+ virtual_width = roundup(virtual_width, 16 / depth);
+ break;
+ case 16:
+ break;
+ case 12: case 24:
+ default:
+ printf("%s: Unknown depth (%d)\n",
+ sc->dev.dv_xname, depth);
+ return NULL;
+ }
+
+ scr = malloc(sizeof *scr, M_DEVBUF,
+ M_ZERO | (cold ? M_NOWAIT : M_WAITOK));
+
+ if (scr == NULL)
+ return NULL;
+
+ scr->nsegs = 0;
+ scr->depth = depth;
+ scr->stride = virtual_width * depth / 8;
+ scr->buf_size = size = scr->stride * virtual_height;
+ scr->buf_va = NULL;
+
+ /* calculate the alignment for LCD frame buffer.
+ the buffer can't across 4MB boundary */
+ align = 1 << 20;
+ while (align < size)
+ align <<= 1;
+
+ error = bus_dmamem_alloc(sc->dma_tag, size, align, 0,
+ scr->segs, 1, &(scr->nsegs), busdma_flag);
+
+ if (error || scr->nsegs != 1)
+ goto bad;
+
+ error = bus_dmamem_map(sc->dma_tag, scr->segs, scr->nsegs,
+ size, (caddr_t *)&(scr->buf_va), busdma_flag | BUS_DMA_COHERENT);
+ if (error)
+ goto bad;
+
+
+ memset (scr->buf_va, 0, scr->buf_size);
+
+ /* map memory for DMA */
+ if (bus_dmamap_create(sc->dma_tag, 1024*1024*2, 1,
+ 1024*1024*2, 0, busdma_flag, &scr->dma))
+ goto bad;
+ error = bus_dmamap_load(sc->dma_tag, scr->dma,
+ scr->buf_va, size, NULL, busdma_flag);
+ if (error)
+ goto bad;
+
+ LIST_INSERT_HEAD(&(sc->screens), scr, link);
+ sc->n_screens++;
+
+#ifdef LCD_DEBUG
+ draw_test_pattern(sc, scr);
+ dump_lcdcon(__func__, sc->iot, sc->ioh);
+#endif
+ return scr;
+
+ bad:
+ if (scr) {
+ if (scr->buf_va)
+ bus_dmamem_unmap(sc->dma_tag, scr->buf_va, size);
+ if (scr->nsegs)
+ bus_dmamem_free(sc->dma_tag, scr->segs, scr->nsegs);
+ free(scr, M_DEVBUF);
+ }
+ return NULL;
+}
+
+
+#define _rgb(r,g,b) (((r)<<11) | ((g)<<5) | b)
+#define rgb(r,g,b) _rgb((r)>>1,g,(b)>>1)
+
+#define L 0x30 /* low intensity */
+#define H 0x3f /* hight intensity */
+
+static const uint16_t basic_color_map[] = {
+ rgb( 0, 0, 0), /* black */
+ rgb( L, 0, 0), /* red */
+ rgb( 0, L, 0), /* green */
+ rgb( L, L, 0), /* brown */
+ rgb( 0, 0, L), /* blue */
+ rgb( L, 0, L), /* magenta */
+ rgb( 0, L, L), /* cyan */
+ _rgb(0x1c,0x38,0x1c), /* white */
+
+ rgb( L, L, L), /* black */
+ rgb( H, 0, 0), /* red */
+ rgb( 0, H, 0), /* green */
+ rgb( H, H, 0), /* brown */
+ rgb( 0, 0, H), /* blue */
+ rgb( H, 0, H), /* magenta */
+ rgb( 0, H, H), /* cyan */
+ rgb( H, H, H), /* white */
+};
+
+#define COLORMAP_LEN (sizeof basic_color_map / sizeof basic_color_map[0])
+
+#undef H
+#undef L
+
+static void
+init_palette(struct s3c24x0_lcd_softc *sc, struct s3c24x0_lcd_screen *scr)
+{
+ int depth = scr->depth;
+ bus_space_tag_t iot = sc->iot;
+ bus_space_handle_t ioh = sc->ioh;
+ int i;
+
+ i = 0;
+
+ switch(depth) {
+ default:
+ case 16: /* not using palette */
+ return;
+ case 8:
+ while (i < COLORMAP_LEN) {
+ bus_space_write_4(iot, ioh, LCDC_PALETTE + 4*i,
+ basic_color_map[i]);
+ ++i;
+ }
+ break;
+ case 4:
+ case 2:
+ /* XXX */
+ break;
+ case 1:
+ bus_space_write_4(iot, ioh, LCDC_PALETTE + 4 * i,
+ basic_color_map[i]); /* black */
+ ++i;
+ bus_space_write_4(iot, ioh, LCDC_PALETTE + 4 * i,
+ basic_color_map[7]); /* white */
+ break;
+ }
+
+#ifdef DIAGNOSTIC
+ /* Fill unused entries */
+ for ( ; i < 256; ++i )
+ bus_space_write_4(iot, ioh, LCDC_PALETTE + 4 * i,
+ basic_color_map[1]); /* red */
+#endif
+}
+
+
+#if NWSDISPLAY > 0
+
+static void
+s3c24x0_lcd_stop_dma(struct s3c24x0_lcd_softc *sc)
+{
+ /* Stop LCD output */
+ bus_space_write_4(sc->iot, sc->ioh, LCDC_LCDCON1,
+ ~LCDCON1_ENVID &
+ bus_space_read_4(sc->iot, sc->ioh, LCDC_LCDCON1));
+
+
+ sc->lcd_on = 0;
+}
+
+int
+s3c24x0_lcd_show_screen(void *v, void *cookie, int waitok,
+ void (*cb)(void *, int, int), void *cbarg)
+{
+ struct s3c24x0_lcd_softc *sc = v;
+ struct rasops_info *ri = cookie;
+ struct s3c24x0_lcd_screen *old, *scr = ri->ri_hw;
+
+ /* XXX: make sure the clock is provided for LCD controller */
+
+ old = sc->active;
+ if (old == scr && sc->lcd_on)
+ return 0;
+
+ if (old)
+ s3c24x0_lcd_stop_dma(sc);
+
+ s3c24x0_lcd_start_dma(sc, scr);
+ sc->active = scr;
+ s3c24x0_lcd_power(sc, 1);
+
+ /* XXX: callback */
+
+ return 0;
+}
+
+int
+s3c24x0_lcd_alloc_screen(void *v, const struct wsscreen_descr *_type,
+ void **cookiep, int *curxp, int *curyp, long *attrp)
+{
+ struct s3c24x0_lcd_softc *sc = v;
+ struct s3c24x0_lcd_screen *scr;
+ struct rasops_info *ri;
+ struct s3c24x0_wsscreen_descr *type =
+ (struct s3c24x0_wsscreen_descr *)_type;
+
+ int width, height;
+
+ width = type->c.ncols * type->c.fontwidth;
+ height = type->c.nrows * type->c.fontwidth;
+
+ if (width < sc->panel_info->panel_width)
+ width = sc->panel_info->panel_width;
+ if (height < sc->panel_info->panel_height)
+ height = sc->panel_info->panel_height;
+
+
+ scr = s3c24x0_lcd_new_screen(sc, width, height, type->depth);
+ if (scr == NULL)
+ return -1;
+
+ /*
+ * initialize raster operation for this screen.
+ */
+ ri = &scr->rinfo;
+ ri->ri_flg = 0;
+ ri->ri_depth = type->depth;
+ ri->ri_bits = scr->buf_va;
+ ri->ri_width = width;
+ ri->ri_height = height;
+ ri->ri_stride = scr->stride;
+
+ if (type->c.nrows == 0)
+ rasops_init(ri, 100, 100);
+ else
+ rasops_init(ri, type->c.nrows, type->c.ncols);
+
+ ri->ri_ops.alloc_attr(ri, 0, 0, 0, attrp);
+
+ type->c.nrows = ri->ri_rows;
+ type->c.ncols = ri->ri_cols;
+ type->c.capabilities = ri->ri_caps;
+ type->c.textops = &ri->ri_ops;
+
+ ri->ri_hw = (void *)scr;
+ *cookiep = ri;
+ *curxp = 0;
+ *curyp = 0;
+
+ return 0;
+}
+
+
+void
+s3c24x0_lcd_free_screen(void *v, void *cookie)
+{
+ struct s3c24x0_lcd_softc *sc = v;
+ struct rasops_info *ri = cookie;
+ struct s3c24x0_lcd_screen *scr = ri->ri_hw;
+
+
+ LIST_REMOVE(scr, link);
+ sc->n_screens--;
+ if (scr == sc->active) {
+ sc->active = NULL;
+
+ /* XXX: We need a good procedure to shutdown the LCD. */
+
+ s3c24x0_lcd_stop_dma(sc);
+ s3c24x0_lcd_power(sc, 0);
+ }
+
+ if (scr->buf_va)
+ bus_dmamem_unmap(sc->dma_tag, scr->buf_va, scr->map_size);
+
+ if (scr->nsegs > 0)
+ bus_dmamem_free(sc->dma_tag, scr->segs, scr->nsegs);
+
+ free(scr, M_DEVBUF);
+}
+
+int
+s3c24x0_lcd_ioctl(void *v, u_long cmd, caddr_t data, int flag,
+ struct proc *p)
+{
+ struct s3c24x0_lcd_softc *sc = v;
+ struct wsdisplay_fbinfo *wsdisp_info;
+ struct s3c24x0_lcd_screen *scr;
+
+
+ switch (cmd) {
+ case WSDISPLAYIO_GTYPE:
+ *(u_int *)data = WSDISPLAY_TYPE_UNKNOWN; /* XXX */
+ return 0;
+
+ case WSDISPLAYIO_GINFO:
+ wsdisp_info = (struct wsdisplay_fbinfo *)data;
+
+ wsdisp_info->height = sc->panel_info->panel_height;
+ wsdisp_info->width = sc->panel_info->panel_width;
+ wsdisp_info->depth = 16; /* XXX */
+ wsdisp_info->cmsize = 0;
+ return 0;
+
+ case WSDISPLAYIO_GETCMAP:
+ case WSDISPLAYIO_PUTCMAP:
+ return EINVAL; /* XXX Colormap */
+
+ case WSDISPLAYIO_SVIDEO:
+ if (*(int *)data == WSDISPLAYIO_VIDEO_ON) {
+ scr = sc->active;
+ if (scr == NULL)
+ scr = LIST_FIRST(&sc->screens);
+
+ if (scr == NULL)
+ return ENXIO;
+
+ s3c24x0_lcd_show_screen(sc, scr, 1, NULL, NULL);
+ }
+ else {
+ s3c24x0_lcd_stop_dma(sc);
+ s3c24x0_lcd_power(sc, 0);
+ }
+ return 0;
+
+ case WSDISPLAYIO_GVIDEO:
+ *(u_int *)data = sc->lcd_on;
+ return 0;
+
+ case WSDISPLAYIO_GCURPOS:
+ case WSDISPLAYIO_SCURPOS:
+ case WSDISPLAYIO_GCURMAX:
+ case WSDISPLAYIO_GCURSOR:
+ case WSDISPLAYIO_SCURSOR:
+ return -1; /* not implemented */
+
+ }
+
+ return 0;
+}
+
+paddr_t
+s3c24x0_lcd_mmap(void *v, off_t offset, int prot)
+{
+ struct s3c24x0_lcd_softc *sc = v;
+ struct s3c24x0_lcd_screen *screen = sc->active; /* ??? */
+
+ if (screen == NULL)
+ return -1;
+
+ return bus_dmamem_mmap(sc->dma_tag, screen->segs, screen->nsegs,
+ offset, prot, BUS_DMA_WAITOK|BUS_DMA_COHERENT);
+ return -1;
+}
+
+
+#if 0
+static void
+s3c24x0_lcd_cursor(void *cookie, int on, int row, int col)
+{
+ struct s3c24x0_lcd_screen *scr = cookie;
+
+ (* scr->rinfo.ri_ops.cursor)(&scr->rinfo, on, row, col);
+}
+
+static int
+s3c24x0_lcd_mapchar(void *cookie, int c, unsigned int *cp)
+{
+ struct s3c24x0_lcd_screen *scr = cookie;
+
+ return (* scr->rinfo.ri_ops.mapchar)(&scr->rinfo, c, cp);
+}
+
+static void
+s3c24x0_lcd_putchar(void *cookie, int row, int col, u_int uc, long attr)
+{
+ struct s3c24x0_lcd_screen *scr = cookie;
+
+ (* scr->rinfo.ri_ops.putchar)(&scr->rinfo,
+ row, col, uc, attr);
+}
+
+static void
+s3c24x0_lcd_copycols(void *cookie, int row, int src, int dst, int num)
+{
+ struct s3c24x0_lcd_screen *scr = cookie;
+
+ (* scr->rinfo.ri_ops.copycols)(&scr->rinfo,
+ row, src, dst, num);
+}
+
+static void
+s3c24x0_lcd_erasecols(void *cookie, int row, int col, int num, long attr)
+{
+ struct s3c24x0_lcd_screen *scr = cookie;
+
+ (* scr->rinfo.ri_ops.erasecols)(&scr->rinfo,
+ row, col, num, attr);
+}
+
+static void
+s3c24x0_lcd_copyrows(void *cookie, int src, int dst, int num)
+{
+ struct s3c24x0_lcd_screen *scr = cookie;
+
+ (* scr->rinfo.ri_ops.copyrows)(&scr->rinfo,
+ src, dst, num);
+}
+
+static void
+s3c24x0_lcd_eraserows(void *cookie, int row, int num, long attr)
+{
+ struct s3c24x0_lcd_screen *scr = cookie;
+
+ (* scr->rinfo.ri_ops.eraserows)(&scr->rinfo,
+ row, num, attr);
+}
+
+static int
+s3c24x0_lcd_alloc_attr(void *cookie, int fg, int bg, int flg, long *attr)
+{
+ struct s3c24x0_lcd_screen *scr = cookie;
+
+ return (* scr->rinfo.ri_ops.allocattr)(&scr->rinfo,
+ fg, bg, flg, attr);
+}
+
+
+const struct wsdisplay_emulops s3c24x0_lcd_emulops = {
+ s3c24x0_lcd_cursor,
+ s3c24x0_lcd_mapchar,
+ s3c24x0_lcd_putchar,
+ s3c24x0_lcd_copycols,
+ s3c24x0_lcd_erasecols,
+ s3c24x0_lcd_copyrows,
+ s3c24x0_lcd_eraserows,
+ s3c24x0_lcd_alloc_attr
+};
+#endif
+
+#endif /* NWSDISPLAY > 0 */
diff --git a/sys/arch/arm/s3c2xx0/s3c24x0_lcd.h b/sys/arch/arm/s3c2xx0/s3c24x0_lcd.h
new file mode 100644
index 00000000000..62274421a53
--- /dev/null
+++ b/sys/arch/arm/s3c2xx0/s3c24x0_lcd.h
@@ -0,0 +1,124 @@
+/* $NetBSD: s3c24x0_lcd.h,v 1.4 2007/03/04 05:59:38 christos Exp $ */
+
+/*
+ * Copyright (c) 2004 Genetec Corporation. All rights reserved.
+ * Written by Hiroyuki Bessho for Genetec Corporation.
+ *
+ * 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.
+ * 3. The name of Genetec Corporation may not be used to endorse or
+ * promote products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY GENETEC CORPORATION ``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 GENETEC CORPORATION
+ * 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.
+ */
+
+
+#ifndef _ARM_S3C2XX0_S3C24X0_LCD_H
+#define _ARM_S3C2XX0_S3C24X0_LCD_H
+
+#include <dev/rasops/rasops.h>
+#include <machine/bus.h>
+
+/* LCD Contoroller */
+
+struct s3c24x0_lcd_screen {
+ LIST_ENTRY(s3c24x0_lcd_screen) link;
+
+ /* Frame buffer */
+ bus_dmamap_t dma;
+ bus_dma_segment_t segs[1];
+ int nsegs;
+ size_t buf_size;
+ size_t map_size;
+ void *buf_va;
+ int depth;
+ int stride;
+
+ /* rasterop */
+ struct rasops_info rinfo;
+};
+
+struct s3c24x0_lcd_softc {
+ struct device dev;
+
+ /* control registers */
+ bus_space_tag_t iot;
+ bus_space_handle_t ioh;
+ bus_dma_tag_t dma_tag;
+
+ struct s3c24x0_lcd_panel_info *panel_info;
+
+ LIST_HEAD(, s3c24x0_lcd_screen) screens;
+ struct s3c24x0_lcd_screen *active;
+ void *ih; /* interrupt handler */
+
+ int n_screens;
+ int lcd_on; /* LCD is turned on */
+};
+
+void s3c24x0_lcd_attach_sub(struct s3c24x0_lcd_softc *,
+ struct s3c2xx0_attach_args *, struct s3c24x0_lcd_panel_info *);
+int s3c24x0_lcd_start_dma(struct s3c24x0_lcd_softc *,
+ struct s3c24x0_lcd_screen *);
+
+struct s3c24x0_lcd_panel_info {
+ short panel_width;
+ short panel_height;
+ int pixel_clock; /* in Hz */
+
+ /* Initial values to go to LCD controll registers */
+ uint32_t lcdcon1;
+ uint32_t lcdcon2;
+ uint32_t lcdcon3;
+ uint32_t lcdcon4;
+ uint32_t lcdcon5;
+ uint32_t lpcsel;
+
+#define s3c24x0_lcd_panel_tft(info) \
+ (((info)->lcdcon1 & LCDCON1_PNRMODE_MASK) == LCDCON1_PNRMODE_TFT)
+};
+
+void s3c24x0_set_lcd_panel_info(struct s3c24x0_lcd_softc *,
+ struct s3c24x0_lcd_panel_info *);
+
+struct s3c24x0_lcd_screen *s3c24x0_lcd_new_screen(struct s3c24x0_lcd_softc *,
+ int, int, int);
+
+/*
+ * we need bits-per-pixel value to configure wsdisplay screen
+ */
+struct s3c24x0_wsscreen_descr {
+ struct wsscreen_descr c; /* standard descriptor */
+ int depth; /* bits per pixel */
+};
+
+int s3c24x0_lcd_show_screen(void *, void *, int, void (*)(void *, int, int),
+ void *);
+int s3c24x0_lcd_ioctl(void *v, u_long cmd, caddr_t data, int flag,
+ struct proc *p);
+paddr_t s3c24x0_lcd_mmap(void *, off_t, int);
+int s3c24x0_lcd_alloc_screen(void *, const struct wsscreen_descr *, void **,
+ int *, int *, long *);
+void s3c24x0_lcd_free_screen(void *, void *);
+void s3c24x0_lcd_power(struct s3c24x0_lcd_softc *, int);
+
+extern const struct wsdisplay_emulops s3c24x0_lcd_emulops;
+
+#endif /* _ARM_S3C2XX0_S3C24X0_LCD_H */
diff --git a/sys/arch/moko/conf/RAMDISK b/sys/arch/moko/conf/RAMDISK
index eebc47177b9..00ccad11361 100644
--- a/sys/arch/moko/conf/RAMDISK
+++ b/sys/arch/moko/conf/RAMDISK
@@ -1,4 +1,4 @@
-# $OpenBSD: RAMDISK,v 1.2 2008/12/30 07:34:00 drahn Exp $
+# $OpenBSD: RAMDISK,v 1.3 2009/01/02 06:38:24 drahn Exp $
machine moko arm
@@ -32,10 +32,10 @@ maxusers 32
options CPU_ARM9 # Support the XScale core
#options XSCALE_CACHE_WRITE_THROUGH
-#option WSDISPLAY_COMPAT_USL # VT handling
-#option WSDISPLAY_COMPAT_RAWKBD # provide raw scancodes; needed for X11
-#option WSDISPLAY_DEFAULTSCREENS=2 # initial number of text consoles
-#option WSDISPLAY_COMPAT_PCVT # emulate some ioctls; needed for X11
+option WSDISPLAY_COMPAT_USL # VT handling
+option WSDISPLAY_COMPAT_RAWKBD # provide raw scancodes; needed for X11
+option WSDISPLAY_DEFAULTSCREENS=2 # initial number of text consoles
+option WSDISPLAY_COMPAT_PCVT # emulate some ioctls; needed for X11
config bsd root on rd0a swap on rd0b
@@ -48,6 +48,10 @@ sscom0 at ssio? index 0 # irq 70
sscom1 at ssio? index 1 # irq 73
sscom2 at ssio? index 2 # irq ?
+# LCD
+lcd0 at ssio?
+wsdisplay* at lcd? console ?
+
# Pseudo-Devices
pseudo-device wsmux 2 # mouse & keyboard multiplexor
diff --git a/sys/arch/moko/conf/files.moko b/sys/arch/moko/conf/files.moko
index 68112eafc20..2d4ed4edd85 100644
--- a/sys/arch/moko/conf/files.moko
+++ b/sys/arch/moko/conf/files.moko
@@ -1,4 +1,4 @@
-# $OpenBSD: files.moko,v 1.1 2008/11/26 14:47:50 drahn Exp $
+# $OpenBSD: files.moko,v 1.2 2009/01/02 06:38:24 drahn Exp $
#
# First try for arm-specific configuration info
#
@@ -44,6 +44,10 @@ file arch/arm/fpe-arm/armfpe.s armfpe
# Machine-independent I2O drivers.
include "dev/i2o/files.i2o"
+# LCD
+attach lcd at ssio with lcd_ssio
+file arch/moko/dev/moko_lcd.c lcd_ssio
+
# Include WSCONS stuff
include "dev/wscons/files.wscons"
include "dev/rasops/files.rasops"
diff --git a/sys/arch/moko/moko/moko_machdep.c b/sys/arch/moko/moko/moko_machdep.c
index 0cffeb080b5..b1c13a457e1 100644
--- a/sys/arch/moko/moko/moko_machdep.c
+++ b/sys/arch/moko/moko/moko_machdep.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: moko_machdep.c,v 1.2 2008/12/30 07:03:28 drahn Exp $ */
+/* $OpenBSD: moko_machdep.c,v 1.3 2009/01/02 06:38:25 drahn Exp $ */
/* $NetBSD: lubbock_machdep.c,v 1.2 2003/07/15 00:25:06 lukem Exp $ */
/*
@@ -479,6 +479,13 @@ bootstrap_bs_map(void *t, bus_addr_t bpa, bus_size_t size,
u_int ol1pagetable;
void sscom_dump_init_state(void);
+/*
+ * format is 0xff << 8 is major, 0xff is revision
+ * ie gta01 -> 0x0100 (TODO, find revision info)
+ * ie gta02 -> 0x0200 (TODO, find revision info)
+ */
+uint32_t hardware_type; /* better way of doing this? */
+
u_int
initarm(void *arg)
{
@@ -1116,11 +1123,13 @@ consinit(void)
/* HORRID HACK */
- if (pclk == 66500000)
+ if (pclk == 66500000) {
conunit = 0;
- else if (pclk == 100000000)
+ hardware_type = 0x0100; /* what about revision? */
+ } else if (pclk == 100000000) {
conunit = 2;
- else /* XXX */
+ hardware_type = 0x0200; /* what about revision? */
+ } else /* XXX */
conunit = 0;
#if NSSCOM > 0
@@ -1175,11 +1184,10 @@ void
board_startup(void)
{
extern int lcd_cnattach(void (*)(u_int, int));
-#if NWSDISPLAY > 0
- extern bus_addr_t comconsaddr;
-#endif
+#ifdef ENABLE_LCD_CONSOLE
#if NWSDISPLAY > 0
+ extern bus_addr_t comconsaddr;
/*
* Try to attach the display console now that VM services
* are available.
@@ -1206,6 +1214,7 @@ board_startup(void)
}
}
#endif
+#endif /* ENABLE_LCD_CONSOLE */
if (boothowto & RB_CONFIG) {
#ifdef BOOT_CONFIG