freebsd-skq/sys/arm/freescale/imx/imx51_ipuv3.c
Ian Lepore add35ed5b8 Follow r261352 by updating all drivers which are children of simplebus
to check the status property in their probe routines.

Simplebus used to only instantiate its children whose status="okay"
but that was improper behavior, fixed in r261352.  Now that it doesn't
check anymore and probes all its children; the children all have to
do the check because really only the children know how to properly
interpret their status property strings.

Right now all existing drivers only understand "okay" versus something-
that's-not-okay, so they all use the new ofw_bus_status_okay() helper.
2014-02-02 19:17:28 +00:00

881 lines
20 KiB
C

/*-
* Copyright (c) 2012 Oleksandr Tymoshenko <gonzo@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/fdt.h>
#include <machine/resource.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/fb/fbreg.h>
#include <dev/syscons/syscons.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;
bus_addr_t pbase;
bus_addr_t vbase;
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;
};
struct video_adapter_softc {
/* Videoadpater part */
video_adapter_t va;
intptr_t fb_addr;
intptr_t fb_paddr;
unsigned int fb_size;
int bpp;
int depth;
unsigned int height;
unsigned int width;
unsigned int stride;
unsigned int xmargin;
unsigned int ymargin;
unsigned char *font;
int initialized;
};
static struct ipu3sc_softc *ipu3sc_softc;
static struct video_adapter_softc va_softc;
/* 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 */
};
#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->vbase = (uint32_t)contigmalloc(size, M_DEVBUF, M_ZERO, 0, ~0,
PAGE_SIZE, 0);
sc->pbase = vtophys(sc->vbase);
return (0);
}
static void
ipu3_fb_init(void *arg)
{
struct ipu3sc_softc *sc = arg;
struct video_adapter_softc *va_sc = &va_softc;
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));
va_sc->width = ((w0sh96 >> 29) & 0x1fff) + 1;
va_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));
va_sc->stride = ((w1sh96 >> 6) & 0x3fff) + 1;
printf("%dx%d [%d]\n", va_sc->width, va_sc->height, va_sc->stride);
va_sc->fb_size = va_sc->height * va_sc->stride;
ipu3_fb_malloc(sc, va_sc->fb_size);
/* DP1 + config_ch_23 + word_2 */
IPUV3_WRITE(sc, cpmem, CPMEM_OFFSET(IMX_IPU_DP1, 23, 1, 0),
((sc->pbase >> 3) | ((sc->pbase >> 3) << 29)) & 0xffffffff);
IPUV3_WRITE(sc, cpmem, CPMEM_OFFSET(IMX_IPU_DP1, 23, 1, 4),
((sc->pbase >> 3) >> 3) & 0xffffffff);
va_sc->fb_addr = (intptr_t)sc->vbase;
va_sc->fb_paddr = (intptr_t)sc->pbase;
va_sc->bpp = va_sc->stride / va_sc->width;
va_sc->depth = va_sc->bpp * 8;
}
static int
ipu3_fb_probe(device_t dev)
{
int error;
if (!ofw_bus_status_okay(dev))
return (ENXIO);
if (!ofw_bus_is_compatible(dev, "fsl,ipu3"))
return (ENXIO);
device_set_desc(dev, "i.MX515 Image Processing Unit (FB)");
error = sc_probe_unit(device_get_unit(dev),
device_get_flags(dev) | SC_AUTODETECT_KBD);
if (error != 0)
return (error);
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;
if (ipu3sc_softc)
return (ENXIO);
ipu3sc_softc = sc;
device_printf(dev, "\tclock gate status is %d\n",
imx51_get_clk_gating(IMX51CLK_IPU_HSP_CLK_ROOT));
sc->dev = dev;
err = (sc_attach_unit(device_get_unit(dev),
device_get_flags(dev) | SC_AUTODETECT_KBD));
if (err) {
device_printf(dev, "failed to attach syscons\n");
goto fail;
}
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);
return (0);
fail:
return (ENXIO);
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);
/*
* Video driver routines and glue.
*/
static int ipu3fb_configure(int);
static vi_probe_t ipu3fb_probe;
static vi_init_t ipu3fb_init;
static vi_get_info_t ipu3fb_get_info;
static vi_query_mode_t ipu3fb_query_mode;
static vi_set_mode_t ipu3fb_set_mode;
static vi_save_font_t ipu3fb_save_font;
static vi_load_font_t ipu3fb_load_font;
static vi_show_font_t ipu3fb_show_font;
static vi_save_palette_t ipu3fb_save_palette;
static vi_load_palette_t ipu3fb_load_palette;
static vi_set_border_t ipu3fb_set_border;
static vi_save_state_t ipu3fb_save_state;
static vi_load_state_t ipu3fb_load_state;
static vi_set_win_org_t ipu3fb_set_win_org;
static vi_read_hw_cursor_t ipu3fb_read_hw_cursor;
static vi_set_hw_cursor_t ipu3fb_set_hw_cursor;
static vi_set_hw_cursor_shape_t ipu3fb_set_hw_cursor_shape;
static vi_blank_display_t ipu3fb_blank_display;
static vi_mmap_t ipu3fb_mmap;
static vi_ioctl_t ipu3fb_ioctl;
static vi_clear_t ipu3fb_clear;
static vi_fill_rect_t ipu3fb_fill_rect;
static vi_bitblt_t ipu3fb_bitblt;
static vi_diag_t ipu3fb_diag;
static vi_save_cursor_palette_t ipu3fb_save_cursor_palette;
static vi_load_cursor_palette_t ipu3fb_load_cursor_palette;
static vi_copy_t ipu3fb_copy;
static vi_putp_t ipu3fb_putp;
static vi_putc_t ipu3fb_putc;
static vi_puts_t ipu3fb_puts;
static vi_putm_t ipu3fb_putm;
static video_switch_t ipu3fbvidsw = {
.probe = ipu3fb_probe,
.init = ipu3fb_init,
.get_info = ipu3fb_get_info,
.query_mode = ipu3fb_query_mode,
.set_mode = ipu3fb_set_mode,
.save_font = ipu3fb_save_font,
.load_font = ipu3fb_load_font,
.show_font = ipu3fb_show_font,
.save_palette = ipu3fb_save_palette,
.load_palette = ipu3fb_load_palette,
.set_border = ipu3fb_set_border,
.save_state = ipu3fb_save_state,
.load_state = ipu3fb_load_state,
.set_win_org = ipu3fb_set_win_org,
.read_hw_cursor = ipu3fb_read_hw_cursor,
.set_hw_cursor = ipu3fb_set_hw_cursor,
.set_hw_cursor_shape = ipu3fb_set_hw_cursor_shape,
.blank_display = ipu3fb_blank_display,
.mmap = ipu3fb_mmap,
.ioctl = ipu3fb_ioctl,
.clear = ipu3fb_clear,
.fill_rect = ipu3fb_fill_rect,
.bitblt = ipu3fb_bitblt,
.diag = ipu3fb_diag,
.save_cursor_palette = ipu3fb_save_cursor_palette,
.load_cursor_palette = ipu3fb_load_cursor_palette,
.copy = ipu3fb_copy,
.putp = ipu3fb_putp,
.putc = ipu3fb_putc,
.puts = ipu3fb_puts,
.putm = ipu3fb_putm,
};
VIDEO_DRIVER(ipu3fb, ipu3fbvidsw, ipu3fb_configure);
extern sc_rndr_sw_t txtrndrsw;
RENDERER(ipu3fb, 0, txtrndrsw, gfb_set);
RENDERER_MODULE(ipu3fb, gfb_set);
static uint16_t ipu3fb_static_window[ROW*COL];
extern u_char dflt_font_16[];
static int
ipu3fb_configure(int flags)
{
struct video_adapter_softc *sc;
sc = &va_softc;
if (sc->initialized)
return 0;
sc->width = 640;
sc->height = 480;
sc->bpp = 2;
sc->stride = sc->width * sc->bpp;
ipu3fb_init(0, &sc->va, 0);
sc->initialized = 1;
return (0);
}
static int
ipu3fb_probe(int unit, video_adapter_t **adp, void *arg, int flags)
{
return (0);
}
static int
ipu3fb_init(int unit, video_adapter_t *adp, int flags)
{
struct video_adapter_softc *sc;
video_info_t *vi;
sc = (struct video_adapter_softc *)adp;
vi = &adp->va_info;
vid_init_struct(adp, "ipu3fb", -1, unit);
sc->font = dflt_font_16;
vi->vi_cheight = IPU3FB_FONT_HEIGHT;
vi->vi_cwidth = 8;
vi->vi_width = sc->width/8;
vi->vi_height = sc->height/vi->vi_cheight;
/*
* Clamp width/height to syscons maximums
*/
if (vi->vi_width > COL)
vi->vi_width = COL;
if (vi->vi_height > ROW)
vi->vi_height = ROW;
sc->xmargin = (sc->width - (vi->vi_width * vi->vi_cwidth)) / 2;
sc->ymargin = (sc->height - (vi->vi_height * vi->vi_cheight))/2;
adp->va_window = (vm_offset_t) ipu3fb_static_window;
adp->va_flags |= V_ADP_FONT /* | V_ADP_COLOR | V_ADP_MODECHANGE */;
adp->va_line_width = sc->stride;
adp->va_buffer_size = sc->fb_size;
vid_register(&sc->va);
return (0);
}
static int
ipu3fb_get_info(video_adapter_t *adp, int mode, video_info_t *info)
{
bcopy(&adp->va_info, info, sizeof(*info));
return (0);
}
static int
ipu3fb_query_mode(video_adapter_t *adp, video_info_t *info)
{
return (0);
}
static int
ipu3fb_set_mode(video_adapter_t *adp, int mode)
{
return (0);
}
static int
ipu3fb_save_font(video_adapter_t *adp, int page, int size, int width,
u_char *data, int c, int count)
{
return (0);
}
static int
ipu3fb_load_font(video_adapter_t *adp, int page, int size, int width,
u_char *data, int c, int count)
{
struct video_adapter_softc *sc;
sc = (struct video_adapter_softc *)adp;
sc->font = data;
return (0);
}
static int
ipu3fb_show_font(video_adapter_t *adp, int page)
{
return (0);
}
static int
ipu3fb_save_palette(video_adapter_t *adp, u_char *palette)
{
return (0);
}
static int
ipu3fb_load_palette(video_adapter_t *adp, u_char *palette)
{
return (0);
}
static int
ipu3fb_set_border(video_adapter_t *adp, int border)
{
return (ipu3fb_blank_display(adp, border));
}
static int
ipu3fb_save_state(video_adapter_t *adp, void *p, size_t size)
{
return (0);
}
static int
ipu3fb_load_state(video_adapter_t *adp, void *p)
{
return (0);
}
static int
ipu3fb_set_win_org(video_adapter_t *adp, off_t offset)
{
return (0);
}
static int
ipu3fb_read_hw_cursor(video_adapter_t *adp, int *col, int *row)
{
*col = *row = 0;
return (0);
}
static int
ipu3fb_set_hw_cursor(video_adapter_t *adp, int col, int row)
{
return (0);
}
static int
ipu3fb_set_hw_cursor_shape(video_adapter_t *adp, int base, int height,
int celsize, int blink)
{
return (0);
}
static int
ipu3fb_blank_display(video_adapter_t *adp, int mode)
{
return (0);
}
static int
ipu3fb_mmap(video_adapter_t *adp, vm_ooffset_t offset, vm_paddr_t *paddr,
int prot, vm_memattr_t *memattr)
{
struct video_adapter_softc *sc;
sc = (struct video_adapter_softc *)adp;
/*
* This might be a legacy VGA mem request: if so, just point it at the
* framebuffer, since it shouldn't be touched
*/
if (offset < sc->stride * sc->height) {
*paddr = sc->fb_paddr + offset;
return (0);
}
return (EINVAL);
}
static int
ipu3fb_ioctl(video_adapter_t *adp, u_long cmd, caddr_t data)
{
struct video_adapter_softc *sc;
struct fbtype *fb;
sc = (struct video_adapter_softc *)adp;
switch (cmd) {
case FBIOGTYPE:
fb = (struct fbtype *)data;
fb->fb_type = FBTYPE_PCIMISC;
fb->fb_height = sc->height;
fb->fb_width = sc->width;
fb->fb_depth = sc->depth;
if (sc->depth <= 1 || sc->depth > 8)
fb->fb_cmsize = 0;
else
fb->fb_cmsize = 1 << sc->depth;
fb->fb_size = sc->fb_size;
break;
case FBIOSCURSOR:
return (ENODEV);
default:
return (fb_commonioctl(adp, cmd, data));
}
return (0);
}
static int
ipu3fb_clear(video_adapter_t *adp)
{
return (ipu3fb_blank_display(adp, 0));
}
static int
ipu3fb_fill_rect(video_adapter_t *adp, int val, int x, int y, int cx, int cy)
{
return (0);
}
static int
ipu3fb_bitblt(video_adapter_t *adp, ...)
{
return (0);
}
static int
ipu3fb_diag(video_adapter_t *adp, int level)
{
return (0);
}
static int
ipu3fb_save_cursor_palette(video_adapter_t *adp, u_char *palette)
{
return (0);
}
static int
ipu3fb_load_cursor_palette(video_adapter_t *adp, u_char *palette)
{
return (0);
}
static int
ipu3fb_copy(video_adapter_t *adp, vm_offset_t src, vm_offset_t dst, int n)
{
return (0);
}
static int
ipu3fb_putp(video_adapter_t *adp, vm_offset_t off, uint32_t p, uint32_t a,
int size, int bpp, int bit_ltor, int byte_ltor)
{
return (0);
}
static int
ipu3fb_putc(video_adapter_t *adp, vm_offset_t off, uint8_t c, uint8_t a)
{
struct video_adapter_softc *sc;
int col, row, bpp;
int b, i, j, k;
uint8_t *addr;
u_char *p;
uint32_t fg, bg, color;
sc = (struct video_adapter_softc *)adp;
bpp = sc->bpp;
if (sc->fb_addr == 0)
return (0);
row = (off / adp->va_info.vi_width) * adp->va_info.vi_cheight;
col = (off % adp->va_info.vi_width) * adp->va_info.vi_cwidth;
p = sc->font + c * IPU3FB_FONT_HEIGHT;
addr = (uint8_t *)sc->fb_addr
+ (row + sc->ymargin) * (sc->stride)
+ bpp * (col + sc->xmargin);
if (bpp == 2) {
bg = colors[(a >> 4) & 0x0f];
fg = colors[a & 0x0f];
} else if (bpp == 3) {
bg = colors_24[(a >> 4) & 0x0f];
fg = colors_24[a & 0x0f];
} else {
return (ENXIO);
}
for (i = 0; i < IPU3FB_FONT_HEIGHT; i++) {
for (j = 0, k = 7; j < 8; j++, k--) {
if ((p[i] & (1 << k)) == 0)
color = bg;
else
color = fg;
/* FIXME: BPP maybe different */
for (b = 0; b < bpp; b ++)
addr[bpp * j + b] =
(color >> (b << 3)) & 0xff;
}
addr += (sc->stride);
}
return (0);
}
static int
ipu3fb_puts(video_adapter_t *adp, vm_offset_t off, u_int16_t *s, int len)
{
int i;
for (i = 0; i < len; i++)
ipu3fb_putc(adp, off + i, s[i] & 0xff, (s[i] & 0xff00) >> 8);
return (0);
}
static int
ipu3fb_putm(video_adapter_t *adp, int x, int y, uint8_t *pixel_image,
uint32_t pixel_mask, int size, int width)
{
return (0);
}
/*
* Define a stub keyboard driver in case one hasn't been
* compiled into the kernel
*/
#include <sys/kbio.h>
#include <dev/kbd/kbdreg.h>
static int dummy_kbd_configure(int flags);
keyboard_switch_t ipu3dummysw;
static int
dummy_kbd_configure(int flags)
{
return (0);
}
KEYBOARD_DRIVER(ipu3dummy, ipu3dummysw, dummy_kbd_configure);