1248557Sray/*- 2248557Sray * Copyright (c) 2012 Oleksandr Tymoshenko <gonzo@freebsd.org> 3250357Sray * Copyright (c) 2012, 2013 The FreeBSD Foundation 4248557Sray * All rights reserved. 5248557Sray * 6248557Sray * Portions of this software were developed by Oleksandr Rybalko 7248557Sray * under sponsorship from the FreeBSD Foundation. 8248557Sray * 9248557Sray * Redistribution and use in source and binary forms, with or without 10248557Sray * modification, are permitted provided that the following conditions 11248557Sray * are met: 12248557Sray * 1. Redistributions of source code must retain the above copyright 13248557Sray * notice, this list of conditions and the following disclaimer. 14248557Sray * 2. Redistributions in binary form must reproduce the above copyright 15248557Sray * notice, this list of conditions and the following disclaimer in the 16248557Sray * documentation and/or other materials provided with the distribution. 17248557Sray * 18248557Sray * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 19248557Sray * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20248557Sray * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21248557Sray * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 22248557Sray * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23248557Sray * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 24248557Sray * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 25248557Sray * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 26248557Sray * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 27248557Sray * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 28248557Sray * SUCH DAMAGE. 29248557Sray * 30248557Sray */ 31248557Sray#include <sys/cdefs.h> 32248557Sray__FBSDID("$FreeBSD$"); 33248557Sray 34248557Sray#include <sys/param.h> 35248557Sray#include <sys/systm.h> 36248557Sray#include <sys/bio.h> 37248557Sray#include <sys/bus.h> 38248557Sray#include <sys/conf.h> 39248557Sray#include <sys/endian.h> 40248557Sray#include <sys/kernel.h> 41248557Sray#include <sys/kthread.h> 42248557Sray#include <sys/lock.h> 43248557Sray#include <sys/malloc.h> 44248557Sray#include <sys/module.h> 45248557Sray#include <sys/mutex.h> 46248557Sray#include <sys/queue.h> 47248557Sray#include <sys/resource.h> 48248557Sray#include <sys/rman.h> 49248557Sray#include <sys/time.h> 50248557Sray#include <sys/timetc.h> 51248557Sray#include <sys/fbio.h> 52248557Sray#include <sys/consio.h> 53248557Sray 54248557Sray#include <sys/kdb.h> 55248557Sray 56248557Sray#include <machine/bus.h> 57248557Sray#include <machine/cpu.h> 58248557Sray#include <machine/cpufunc.h> 59266084Sian#include <machine/fdt.h> 60248557Sray#include <machine/resource.h> 61248557Sray#include <machine/intr.h> 62248557Sray 63248557Sray#include <dev/fdt/fdt_common.h> 64248557Sray#include <dev/ofw/ofw_bus.h> 65248557Sray#include <dev/ofw/ofw_bus_subr.h> 66248557Sray 67248557Sray#include <dev/fb/fbreg.h> 68248557Sray#include <dev/syscons/syscons.h> 69248557Sray 70248557Sray#include <arm/freescale/imx/imx51_ccmvar.h> 71248557Sray 72248557Sray#include <arm/freescale/imx/imx51_ipuv3reg.h> 73248557Sray 74248557Sray#define IMX51_IPU_HSP_CLOCK 665000000 75248557Sray#define IPU3FB_FONT_HEIGHT 16 76248557Sray 77248557Sraystruct ipu3sc_softc { 78248557Sray device_t dev; 79248557Sray bus_addr_t pbase; 80248557Sray bus_addr_t vbase; 81248557Sray 82248557Sray bus_space_tag_t iot; 83248557Sray bus_space_handle_t ioh; 84248557Sray bus_space_handle_t cm_ioh; 85248557Sray bus_space_handle_t dp_ioh; 86248557Sray bus_space_handle_t di0_ioh; 87248557Sray bus_space_handle_t di1_ioh; 88248557Sray bus_space_handle_t dctmpl_ioh; 89248557Sray bus_space_handle_t dc_ioh; 90248557Sray bus_space_handle_t dmfc_ioh; 91248557Sray bus_space_handle_t idmac_ioh; 92248557Sray bus_space_handle_t cpmem_ioh; 93248557Sray}; 94248557Sray 95248557Sraystruct video_adapter_softc { 96248557Sray /* Videoadpater part */ 97248557Sray video_adapter_t va; 98248557Sray 99248557Sray intptr_t fb_addr; 100248557Sray intptr_t fb_paddr; 101248557Sray unsigned int fb_size; 102248557Sray 103248557Sray int bpp; 104248557Sray int depth; 105248557Sray unsigned int height; 106248557Sray unsigned int width; 107248557Sray unsigned int stride; 108248557Sray 109248557Sray unsigned int xmargin; 110248557Sray unsigned int ymargin; 111248557Sray 112248557Sray unsigned char *font; 113248557Sray int initialized; 114248557Sray}; 115248557Sray 116248557Sraystatic struct ipu3sc_softc *ipu3sc_softc; 117248557Sraystatic struct video_adapter_softc va_softc; 118248557Sray 119248557Sray/* FIXME: not only 2 bytes color supported */ 120248557Sraystatic uint16_t colors[16] = { 121248557Sray 0x0000, /* black */ 122248557Sray 0x001f, /* blue */ 123248557Sray 0x07e0, /* green */ 124248557Sray 0x07ff, /* cyan */ 125248557Sray 0xf800, /* red */ 126248557Sray 0xf81f, /* magenta */ 127248557Sray 0x3800, /* brown */ 128248557Sray 0xc618, /* light grey */ 129248557Sray 0xc618, /* XXX: dark grey */ 130248557Sray 0x001f, /* XXX: light blue */ 131248557Sray 0x07e0, /* XXX: light green */ 132248557Sray 0x07ff, /* XXX: light cyan */ 133248557Sray 0xf800, /* XXX: light red */ 134248557Sray 0xf81f, /* XXX: light magenta */ 135248557Sray 0xffe0, /* yellow */ 136248557Sray 0xffff, /* white */ 137248557Sray}; 138248557Sraystatic uint32_t colors_24[16] = { 139248557Sray 0x000000,/* Black */ 140248557Sray 0x000080,/* Blue */ 141248557Sray 0x008000,/* Green */ 142248557Sray 0x008080,/* Cyan */ 143248557Sray 0x800000,/* Red */ 144248557Sray 0x800080,/* Magenta */ 145248557Sray 0xcc6600,/* brown */ 146248557Sray 0xC0C0C0,/* Silver */ 147248557Sray 0x808080,/* Gray */ 148248557Sray 0x0000FF,/* Light Blue */ 149248557Sray 0x00FF00,/* Light Green */ 150248557Sray 0x00FFFF,/* Light Cyan */ 151248557Sray 0xFF0000,/* Light Red */ 152248557Sray 0xFF00FF,/* Light Magenta */ 153248557Sray 0xFFFF00,/* Yellow */ 154248557Sray 0xFFFFFF,/* White */ 155248557Sray 156248557Sray 157248557Sray}; 158248557Sray 159248557Sray#define IPUV3_READ(ipuv3, module, reg) \ 160248557Sray bus_space_read_4((ipuv3)->iot, (ipuv3)->module##_ioh, (reg)) 161248557Sray#define IPUV3_WRITE(ipuv3, module, reg, val) \ 162248557Sray bus_space_write_4((ipuv3)->iot, (ipuv3)->module##_ioh, (reg), (val)) 163248557Sray 164248557Sray#define CPMEM_CHANNEL_OFFSET(_c) ((_c) * 0x40) 165248557Sray#define CPMEM_WORD_OFFSET(_w) ((_w) * 0x20) 166248557Sray#define CPMEM_DP_OFFSET(_d) ((_d) * 0x10000) 167248557Sray#define IMX_IPU_DP0 0 168248557Sray#define IMX_IPU_DP1 1 169248557Sray#define CPMEM_CHANNEL(_dp, _ch, _w) \ 170248557Sray (CPMEM_DP_OFFSET(_dp) + CPMEM_CHANNEL_OFFSET(_ch) + \ 171248557Sray CPMEM_WORD_OFFSET(_w)) 172248557Sray#define CPMEM_OFFSET(_dp, _ch, _w, _o) \ 173248557Sray (CPMEM_CHANNEL((_dp), (_ch), (_w)) + (_o)) 174248557Sray 175248557Sray#define IPUV3_DEBUG 100 176248557Sray 177248557Sray#ifdef IPUV3_DEBUG 178248557Sray#define SUBMOD_DUMP_REG(_sc, _m, _l) \ 179248557Sray { \ 180248557Sray int i; \ 181248557Sray printf("*** " #_m " ***\n"); \ 182248557Sray for (i = 0; i <= (_l); i += 4) { \ 183248557Sray if ((i % 32) == 0) \ 184248557Sray printf("%04x: ", i & 0xffff); \ 185248557Sray printf("0x%08x%c", IPUV3_READ((_sc), _m, i), \ 186248557Sray ((i + 4) % 32)?' ':'\n'); \ 187248557Sray } \ 188248557Sray printf("\n"); \ 189248557Sray } 190248557Sray#endif 191248557Sray 192248557Sray#ifdef IPUV3_DEBUG 193248557Srayint ipuv3_debug = IPUV3_DEBUG; 194248557Sray#define DPRINTFN(n,x) if (ipuv3_debug>(n)) printf x; else 195248557Sray#else 196248557Sray#define DPRINTFN(n,x) 197248557Sray#endif 198248557Sray 199248557Sraystatic int ipu3_fb_probe(device_t); 200248557Sraystatic int ipu3_fb_attach(device_t); 201248557Sray 202248557Sraystatic int 203248557Srayipu3_fb_malloc(struct ipu3sc_softc *sc, size_t size) 204248557Sray{ 205248557Sray 206248557Sray sc->vbase = (uint32_t)contigmalloc(size, M_DEVBUF, M_ZERO, 0, ~0, 207248557Sray PAGE_SIZE, 0); 208248557Sray sc->pbase = vtophys(sc->vbase); 209248557Sray 210248557Sray return (0); 211248557Sray} 212248557Sray 213248557Sraystatic void 214248557Srayipu3_fb_init(void *arg) 215248557Sray{ 216248557Sray struct ipu3sc_softc *sc = arg; 217248557Sray struct video_adapter_softc *va_sc = &va_softc; 218248557Sray uint64_t w0sh96; 219248557Sray uint32_t w1sh96; 220248557Sray 221248557Sray /* FW W0[137:125] - 96 = [41:29] */ 222248557Sray /* FH W0[149:138] - 96 = [53:42] */ 223248557Sray w0sh96 = IPUV3_READ(sc, cpmem, CPMEM_OFFSET(IMX_IPU_DP1, 23, 0, 16)); 224248557Sray w0sh96 <<= 32; 225248557Sray w0sh96 |= IPUV3_READ(sc, cpmem, CPMEM_OFFSET(IMX_IPU_DP1, 23, 0, 12)); 226248557Sray 227248557Sray va_sc->width = ((w0sh96 >> 29) & 0x1fff) + 1; 228248557Sray va_sc->height = ((w0sh96 >> 42) & 0x0fff) + 1; 229248557Sray 230248557Sray /* SLY W1[115:102] - 96 = [19:6] */ 231248557Sray w1sh96 = IPUV3_READ(sc, cpmem, CPMEM_OFFSET(IMX_IPU_DP1, 23, 1, 12)); 232248557Sray va_sc->stride = ((w1sh96 >> 6) & 0x3fff) + 1; 233248557Sray 234248557Sray printf("%dx%d [%d]\n", va_sc->width, va_sc->height, va_sc->stride); 235248557Sray va_sc->fb_size = va_sc->height * va_sc->stride; 236248557Sray 237248557Sray ipu3_fb_malloc(sc, va_sc->fb_size); 238248557Sray 239248557Sray /* DP1 + config_ch_23 + word_2 */ 240248557Sray IPUV3_WRITE(sc, cpmem, CPMEM_OFFSET(IMX_IPU_DP1, 23, 1, 0), 241248557Sray ((sc->pbase >> 3) | ((sc->pbase >> 3) << 29)) & 0xffffffff); 242248557Sray 243248557Sray IPUV3_WRITE(sc, cpmem, CPMEM_OFFSET(IMX_IPU_DP1, 23, 1, 4), 244248557Sray ((sc->pbase >> 3) >> 3) & 0xffffffff); 245248557Sray 246248557Sray va_sc->fb_addr = (intptr_t)sc->vbase; 247248557Sray va_sc->fb_paddr = (intptr_t)sc->pbase; 248248557Sray va_sc->bpp = va_sc->stride / va_sc->width; 249248557Sray va_sc->depth = va_sc->bpp * 8; 250248557Sray} 251248557Sray 252248557Sraystatic int 253248557Srayipu3_fb_probe(device_t dev) 254248557Sray{ 255248557Sray int error; 256248557Sray 257266152Sian if (!ofw_bus_status_okay(dev)) 258266152Sian return (ENXIO); 259266152Sian 260248557Sray if (!ofw_bus_is_compatible(dev, "fsl,ipu3")) 261248557Sray return (ENXIO); 262248557Sray 263266365Sian device_set_desc(dev, "i.MX5x Image Processing Unit v3 (FB)"); 264248557Sray 265248557Sray error = sc_probe_unit(device_get_unit(dev), 266248557Sray device_get_flags(dev) | SC_AUTODETECT_KBD); 267248557Sray 268248557Sray if (error != 0) 269248557Sray return (error); 270248557Sray 271248557Sray return (BUS_PROBE_DEFAULT); 272248557Sray} 273248557Sray 274248557Sraystatic int 275248557Srayipu3_fb_attach(device_t dev) 276248557Sray{ 277248557Sray struct ipu3sc_softc *sc = device_get_softc(dev); 278248557Sray bus_space_tag_t iot; 279248557Sray bus_space_handle_t ioh; 280266365Sian phandle_t node; 281266365Sian pcell_t reg; 282248557Sray int err; 283266365Sian uintptr_t base; 284248557Sray 285248557Sray if (ipu3sc_softc) 286248557Sray return (ENXIO); 287248557Sray 288248557Sray ipu3sc_softc = sc; 289248557Sray 290266365Sian if (bootverbose) 291266365Sian device_printf(dev, "clock gate status is %d\n", 292266365Sian imx51_get_clk_gating(IMX51CLK_IPU_HSP_CLK_ROOT)); 293248557Sray 294248557Sray sc->dev = dev; 295248557Sray 296248557Sray err = (sc_attach_unit(device_get_unit(dev), 297248557Sray device_get_flags(dev) | SC_AUTODETECT_KBD)); 298248557Sray 299248557Sray if (err) { 300248557Sray device_printf(dev, "failed to attach syscons\n"); 301248557Sray goto fail; 302248557Sray } 303248557Sray 304248557Sray sc = device_get_softc(dev); 305248557Sray sc->iot = iot = fdtbus_bs_tag; 306248557Sray 307266365Sian /* 308266365Sian * Retrieve the device address based on the start address in the 309266365Sian * DTS. The DTS for i.MX51 specifies 0x5e000000 as the first register 310266365Sian * address, so we just subtract IPU_CM_BASE to get the offset at which 311266365Sian * the IPU device was memory mapped. 312266365Sian * On i.MX53, the offset is 0. 313266365Sian */ 314266365Sian node = ofw_bus_get_node(dev); 315266365Sian if ((OF_getprop(node, "reg", ®, sizeof(reg))) <= 0) 316266365Sian base = 0; 317266365Sian else 318266365Sian base = fdt32_to_cpu(reg) - IPU_CM_BASE(0); 319248557Sray /* map controller registers */ 320266365Sian err = bus_space_map(iot, IPU_CM_BASE(base), IPU_CM_SIZE, 0, &ioh); 321248557Sray if (err) 322248557Sray goto fail_retarn_cm; 323248557Sray sc->cm_ioh = ioh; 324248557Sray 325248557Sray /* map Display Multi FIFO Controller registers */ 326266365Sian err = bus_space_map(iot, IPU_DMFC_BASE(base), IPU_DMFC_SIZE, 0, &ioh); 327248557Sray if (err) 328248557Sray goto fail_retarn_dmfc; 329248557Sray sc->dmfc_ioh = ioh; 330248557Sray 331248557Sray /* map Display Interface 0 registers */ 332266365Sian err = bus_space_map(iot, IPU_DI0_BASE(base), IPU_DI0_SIZE, 0, &ioh); 333248557Sray if (err) 334248557Sray goto fail_retarn_di0; 335248557Sray sc->di0_ioh = ioh; 336248557Sray 337248557Sray /* map Display Interface 1 registers */ 338266365Sian err = bus_space_map(iot, IPU_DI1_BASE(base), IPU_DI0_SIZE, 0, &ioh); 339248557Sray if (err) 340248557Sray goto fail_retarn_di1; 341248557Sray sc->di1_ioh = ioh; 342248557Sray 343248557Sray /* map Display Processor registers */ 344266365Sian err = bus_space_map(iot, IPU_DP_BASE(base), IPU_DP_SIZE, 0, &ioh); 345248557Sray if (err) 346248557Sray goto fail_retarn_dp; 347248557Sray sc->dp_ioh = ioh; 348248557Sray 349248557Sray /* map Display Controller registers */ 350266365Sian err = bus_space_map(iot, IPU_DC_BASE(base), IPU_DC_SIZE, 0, &ioh); 351248557Sray if (err) 352248557Sray goto fail_retarn_dc; 353248557Sray sc->dc_ioh = ioh; 354248557Sray 355248557Sray /* map Image DMA Controller registers */ 356266365Sian err = bus_space_map(iot, IPU_IDMAC_BASE(base), IPU_IDMAC_SIZE, 0, 357266365Sian &ioh); 358248557Sray if (err) 359248557Sray goto fail_retarn_idmac; 360248557Sray sc->idmac_ioh = ioh; 361248557Sray 362248557Sray /* map CPMEM registers */ 363266365Sian err = bus_space_map(iot, IPU_CPMEM_BASE(base), IPU_CPMEM_SIZE, 0, 364266365Sian &ioh); 365248557Sray if (err) 366248557Sray goto fail_retarn_cpmem; 367248557Sray sc->cpmem_ioh = ioh; 368248557Sray 369248557Sray /* map DCTEMPL registers */ 370266365Sian err = bus_space_map(iot, IPU_DCTMPL_BASE(base), IPU_DCTMPL_SIZE, 0, 371266365Sian &ioh); 372248557Sray if (err) 373248557Sray goto fail_retarn_dctmpl; 374248557Sray sc->dctmpl_ioh = ioh; 375248557Sray 376248557Sray#ifdef notyet 377248557Sray sc->ih = imx51_ipuv3_intr_establish(IMX51_INT_IPUV3, IPL_BIO, 378248557Sray ipuv3intr, sc); 379248557Sray if (sc->ih == NULL) { 380248557Sray device_printf(sc->dev, 381248557Sray "unable to establish interrupt at irq %d\n", 382248557Sray IMX51_INT_IPUV3); 383248557Sray return (ENXIO); 384248557Sray } 385248557Sray#endif 386248557Sray 387248557Sray /* 388248557Sray * We have to wait until interrupts are enabled. 389248557Sray * Mailbox relies on it to get data from VideoCore 390248557Sray */ 391248557Sray ipu3_fb_init(sc); 392248557Sray 393248557Sray return (0); 394248557Sray 395248557Srayfail: 396248557Sray return (ENXIO); 397248557Srayfail_retarn_dctmpl: 398248557Sray bus_space_unmap(sc->iot, sc->cpmem_ioh, IPU_CPMEM_SIZE); 399248557Srayfail_retarn_cpmem: 400248557Sray bus_space_unmap(sc->iot, sc->idmac_ioh, IPU_IDMAC_SIZE); 401248557Srayfail_retarn_idmac: 402248557Sray bus_space_unmap(sc->iot, sc->dc_ioh, IPU_DC_SIZE); 403248557Srayfail_retarn_dp: 404248557Sray bus_space_unmap(sc->iot, sc->dp_ioh, IPU_DP_SIZE); 405248557Srayfail_retarn_dc: 406248557Sray bus_space_unmap(sc->iot, sc->di1_ioh, IPU_DI1_SIZE); 407248557Srayfail_retarn_di1: 408248557Sray bus_space_unmap(sc->iot, sc->di0_ioh, IPU_DI0_SIZE); 409248557Srayfail_retarn_di0: 410248557Sray bus_space_unmap(sc->iot, sc->dmfc_ioh, IPU_DMFC_SIZE); 411248557Srayfail_retarn_dmfc: 412248557Sray bus_space_unmap(sc->iot, sc->dc_ioh, IPU_CM_SIZE); 413248557Srayfail_retarn_cm: 414248557Sray device_printf(sc->dev, 415248557Sray "failed to map registers (errno=%d)\n", err); 416248557Sray return (err); 417248557Sray} 418248557Sray 419248557Sraystatic device_method_t ipu3_fb_methods[] = { 420248557Sray /* Device interface */ 421248557Sray DEVMETHOD(device_probe, ipu3_fb_probe), 422248557Sray DEVMETHOD(device_attach, ipu3_fb_attach), 423248557Sray 424248557Sray { 0, 0 } 425248557Sray}; 426248557Sray 427248557Sraystatic devclass_t ipu3_fb_devclass; 428248557Sray 429248557Sraystatic driver_t ipu3_fb_driver = { 430248557Sray "fb", 431248557Sray ipu3_fb_methods, 432248557Sray sizeof(struct ipu3sc_softc), 433248557Sray}; 434248557Sray 435248557SrayDRIVER_MODULE(ipu3fb, simplebus, ipu3_fb_driver, ipu3_fb_devclass, 0, 0); 436248557Sray 437248557Sray/* 438248557Sray * Video driver routines and glue. 439248557Sray */ 440248557Sraystatic int ipu3fb_configure(int); 441248557Sraystatic vi_probe_t ipu3fb_probe; 442248557Sraystatic vi_init_t ipu3fb_init; 443248557Sraystatic vi_get_info_t ipu3fb_get_info; 444248557Sraystatic vi_query_mode_t ipu3fb_query_mode; 445248557Sraystatic vi_set_mode_t ipu3fb_set_mode; 446248557Sraystatic vi_save_font_t ipu3fb_save_font; 447248557Sraystatic vi_load_font_t ipu3fb_load_font; 448248557Sraystatic vi_show_font_t ipu3fb_show_font; 449248557Sraystatic vi_save_palette_t ipu3fb_save_palette; 450248557Sraystatic vi_load_palette_t ipu3fb_load_palette; 451248557Sraystatic vi_set_border_t ipu3fb_set_border; 452248557Sraystatic vi_save_state_t ipu3fb_save_state; 453248557Sraystatic vi_load_state_t ipu3fb_load_state; 454248557Sraystatic vi_set_win_org_t ipu3fb_set_win_org; 455248557Sraystatic vi_read_hw_cursor_t ipu3fb_read_hw_cursor; 456248557Sraystatic vi_set_hw_cursor_t ipu3fb_set_hw_cursor; 457248557Sraystatic vi_set_hw_cursor_shape_t ipu3fb_set_hw_cursor_shape; 458248557Sraystatic vi_blank_display_t ipu3fb_blank_display; 459248557Sraystatic vi_mmap_t ipu3fb_mmap; 460248557Sraystatic vi_ioctl_t ipu3fb_ioctl; 461248557Sraystatic vi_clear_t ipu3fb_clear; 462248557Sraystatic vi_fill_rect_t ipu3fb_fill_rect; 463248557Sraystatic vi_bitblt_t ipu3fb_bitblt; 464248557Sraystatic vi_diag_t ipu3fb_diag; 465248557Sraystatic vi_save_cursor_palette_t ipu3fb_save_cursor_palette; 466248557Sraystatic vi_load_cursor_palette_t ipu3fb_load_cursor_palette; 467248557Sraystatic vi_copy_t ipu3fb_copy; 468248557Sraystatic vi_putp_t ipu3fb_putp; 469248557Sraystatic vi_putc_t ipu3fb_putc; 470248557Sraystatic vi_puts_t ipu3fb_puts; 471248557Sraystatic vi_putm_t ipu3fb_putm; 472248557Sray 473248557Sraystatic video_switch_t ipu3fbvidsw = { 474248557Sray .probe = ipu3fb_probe, 475248557Sray .init = ipu3fb_init, 476248557Sray .get_info = ipu3fb_get_info, 477248557Sray .query_mode = ipu3fb_query_mode, 478248557Sray .set_mode = ipu3fb_set_mode, 479248557Sray .save_font = ipu3fb_save_font, 480248557Sray .load_font = ipu3fb_load_font, 481248557Sray .show_font = ipu3fb_show_font, 482248557Sray .save_palette = ipu3fb_save_palette, 483248557Sray .load_palette = ipu3fb_load_palette, 484248557Sray .set_border = ipu3fb_set_border, 485248557Sray .save_state = ipu3fb_save_state, 486248557Sray .load_state = ipu3fb_load_state, 487248557Sray .set_win_org = ipu3fb_set_win_org, 488248557Sray .read_hw_cursor = ipu3fb_read_hw_cursor, 489248557Sray .set_hw_cursor = ipu3fb_set_hw_cursor, 490248557Sray .set_hw_cursor_shape = ipu3fb_set_hw_cursor_shape, 491248557Sray .blank_display = ipu3fb_blank_display, 492248557Sray .mmap = ipu3fb_mmap, 493248557Sray .ioctl = ipu3fb_ioctl, 494248557Sray .clear = ipu3fb_clear, 495248557Sray .fill_rect = ipu3fb_fill_rect, 496248557Sray .bitblt = ipu3fb_bitblt, 497248557Sray .diag = ipu3fb_diag, 498248557Sray .save_cursor_palette = ipu3fb_save_cursor_palette, 499248557Sray .load_cursor_palette = ipu3fb_load_cursor_palette, 500248557Sray .copy = ipu3fb_copy, 501248557Sray .putp = ipu3fb_putp, 502248557Sray .putc = ipu3fb_putc, 503248557Sray .puts = ipu3fb_puts, 504248557Sray .putm = ipu3fb_putm, 505248557Sray}; 506248557Sray 507248557SrayVIDEO_DRIVER(ipu3fb, ipu3fbvidsw, ipu3fb_configure); 508248557Sray 509248557Srayextern sc_rndr_sw_t txtrndrsw; 510248557SrayRENDERER(ipu3fb, 0, txtrndrsw, gfb_set); 511248557SrayRENDERER_MODULE(ipu3fb, gfb_set); 512248557Sray 513248557Sraystatic uint16_t ipu3fb_static_window[ROW*COL]; 514248557Srayextern u_char dflt_font_16[]; 515248557Sray 516248557Sraystatic int 517248557Srayipu3fb_configure(int flags) 518248557Sray{ 519248557Sray struct video_adapter_softc *sc; 520248557Sray 521248557Sray sc = &va_softc; 522248557Sray 523248557Sray if (sc->initialized) 524248557Sray return 0; 525248557Sray 526248557Sray sc->width = 640; 527248557Sray sc->height = 480; 528248557Sray sc->bpp = 2; 529248557Sray sc->stride = sc->width * sc->bpp; 530248557Sray 531248557Sray ipu3fb_init(0, &sc->va, 0); 532248557Sray 533248557Sray sc->initialized = 1; 534248557Sray 535248557Sray return (0); 536248557Sray} 537248557Sray 538248557Sraystatic int 539248557Srayipu3fb_probe(int unit, video_adapter_t **adp, void *arg, int flags) 540248557Sray{ 541248557Sray 542248557Sray return (0); 543248557Sray} 544248557Sray 545248557Sraystatic int 546248557Srayipu3fb_init(int unit, video_adapter_t *adp, int flags) 547248557Sray{ 548248557Sray struct video_adapter_softc *sc; 549248557Sray video_info_t *vi; 550248557Sray 551248557Sray sc = (struct video_adapter_softc *)adp; 552248557Sray vi = &adp->va_info; 553248557Sray 554248557Sray vid_init_struct(adp, "ipu3fb", -1, unit); 555248557Sray 556248557Sray sc->font = dflt_font_16; 557248557Sray vi->vi_cheight = IPU3FB_FONT_HEIGHT; 558248557Sray vi->vi_cwidth = 8; 559248557Sray vi->vi_width = sc->width/8; 560248557Sray vi->vi_height = sc->height/vi->vi_cheight; 561248557Sray 562248557Sray /* 563248557Sray * Clamp width/height to syscons maximums 564248557Sray */ 565248557Sray if (vi->vi_width > COL) 566248557Sray vi->vi_width = COL; 567248557Sray if (vi->vi_height > ROW) 568248557Sray vi->vi_height = ROW; 569248557Sray 570248557Sray sc->xmargin = (sc->width - (vi->vi_width * vi->vi_cwidth)) / 2; 571248557Sray sc->ymargin = (sc->height - (vi->vi_height * vi->vi_cheight))/2; 572248557Sray 573248557Sray adp->va_window = (vm_offset_t) ipu3fb_static_window; 574248557Sray adp->va_flags |= V_ADP_FONT /* | V_ADP_COLOR | V_ADP_MODECHANGE */; 575248557Sray adp->va_line_width = sc->stride; 576248557Sray adp->va_buffer_size = sc->fb_size; 577248557Sray 578248557Sray vid_register(&sc->va); 579248557Sray 580248557Sray return (0); 581248557Sray} 582248557Sray 583248557Sraystatic int 584248557Srayipu3fb_get_info(video_adapter_t *adp, int mode, video_info_t *info) 585248557Sray{ 586248557Sray 587248557Sray bcopy(&adp->va_info, info, sizeof(*info)); 588248557Sray return (0); 589248557Sray} 590248557Sray 591248557Sraystatic int 592248557Srayipu3fb_query_mode(video_adapter_t *adp, video_info_t *info) 593248557Sray{ 594248557Sray 595248557Sray return (0); 596248557Sray} 597248557Sray 598248557Sraystatic int 599248557Srayipu3fb_set_mode(video_adapter_t *adp, int mode) 600248557Sray{ 601248557Sray 602248557Sray return (0); 603248557Sray} 604248557Sray 605248557Sraystatic int 606248557Srayipu3fb_save_font(video_adapter_t *adp, int page, int size, int width, 607248557Sray u_char *data, int c, int count) 608248557Sray{ 609248557Sray 610248557Sray return (0); 611248557Sray} 612248557Sray 613248557Sraystatic int 614248557Srayipu3fb_load_font(video_adapter_t *adp, int page, int size, int width, 615248557Sray u_char *data, int c, int count) 616248557Sray{ 617248557Sray struct video_adapter_softc *sc; 618248557Sray 619248557Sray sc = (struct video_adapter_softc *)adp; 620248557Sray sc->font = data; 621248557Sray 622248557Sray return (0); 623248557Sray} 624248557Sray 625248557Sraystatic int 626248557Srayipu3fb_show_font(video_adapter_t *adp, int page) 627248557Sray{ 628248557Sray 629248557Sray return (0); 630248557Sray} 631248557Sray 632248557Sraystatic int 633248557Srayipu3fb_save_palette(video_adapter_t *adp, u_char *palette) 634248557Sray{ 635248557Sray 636248557Sray return (0); 637248557Sray} 638248557Sray 639248557Sraystatic int 640248557Srayipu3fb_load_palette(video_adapter_t *adp, u_char *palette) 641248557Sray{ 642248557Sray 643248557Sray return (0); 644248557Sray} 645248557Sray 646248557Sraystatic int 647248557Srayipu3fb_set_border(video_adapter_t *adp, int border) 648248557Sray{ 649248557Sray 650248557Sray return (ipu3fb_blank_display(adp, border)); 651248557Sray} 652248557Sray 653248557Sraystatic int 654248557Srayipu3fb_save_state(video_adapter_t *adp, void *p, size_t size) 655248557Sray{ 656248557Sray 657248557Sray return (0); 658248557Sray} 659248557Sray 660248557Sraystatic int 661248557Srayipu3fb_load_state(video_adapter_t *adp, void *p) 662248557Sray{ 663248557Sray 664248557Sray return (0); 665248557Sray} 666248557Sray 667248557Sraystatic int 668248557Srayipu3fb_set_win_org(video_adapter_t *adp, off_t offset) 669248557Sray{ 670248557Sray 671248557Sray return (0); 672248557Sray} 673248557Sray 674248557Sraystatic int 675248557Srayipu3fb_read_hw_cursor(video_adapter_t *adp, int *col, int *row) 676248557Sray{ 677248557Sray 678248557Sray *col = *row = 0; 679248557Sray return (0); 680248557Sray} 681248557Sray 682248557Sraystatic int 683248557Srayipu3fb_set_hw_cursor(video_adapter_t *adp, int col, int row) 684248557Sray{ 685248557Sray 686248557Sray return (0); 687248557Sray} 688248557Sray 689248557Sraystatic int 690248557Srayipu3fb_set_hw_cursor_shape(video_adapter_t *adp, int base, int height, 691248557Sray int celsize, int blink) 692248557Sray{ 693248557Sray 694248557Sray return (0); 695248557Sray} 696248557Sray 697248557Sraystatic int 698248557Srayipu3fb_blank_display(video_adapter_t *adp, int mode) 699248557Sray{ 700248557Sray 701248557Sray return (0); 702248557Sray} 703248557Sray 704248557Sraystatic int 705248557Srayipu3fb_mmap(video_adapter_t *adp, vm_ooffset_t offset, vm_paddr_t *paddr, 706248557Sray int prot, vm_memattr_t *memattr) 707248557Sray{ 708248557Sray struct video_adapter_softc *sc; 709248557Sray 710248557Sray sc = (struct video_adapter_softc *)adp; 711248557Sray 712248557Sray /* 713248557Sray * This might be a legacy VGA mem request: if so, just point it at the 714248557Sray * framebuffer, since it shouldn't be touched 715248557Sray */ 716248557Sray if (offset < sc->stride * sc->height) { 717248557Sray *paddr = sc->fb_paddr + offset; 718248557Sray return (0); 719248557Sray } 720248557Sray 721248557Sray return (EINVAL); 722248557Sray} 723248557Sray 724248557Sraystatic int 725248557Srayipu3fb_ioctl(video_adapter_t *adp, u_long cmd, caddr_t data) 726248557Sray{ 727248557Sray struct video_adapter_softc *sc; 728248557Sray struct fbtype *fb; 729248557Sray 730248557Sray sc = (struct video_adapter_softc *)adp; 731248557Sray 732248557Sray switch (cmd) { 733248557Sray case FBIOGTYPE: 734248557Sray fb = (struct fbtype *)data; 735248557Sray fb->fb_type = FBTYPE_PCIMISC; 736248557Sray fb->fb_height = sc->height; 737248557Sray fb->fb_width = sc->width; 738248557Sray fb->fb_depth = sc->depth; 739248557Sray if (sc->depth <= 1 || sc->depth > 8) 740248557Sray fb->fb_cmsize = 0; 741248557Sray else 742248557Sray fb->fb_cmsize = 1 << sc->depth; 743248557Sray fb->fb_size = sc->fb_size; 744248557Sray break; 745248557Sray case FBIOSCURSOR: 746248557Sray return (ENODEV); 747248557Sray default: 748248557Sray return (fb_commonioctl(adp, cmd, data)); 749248557Sray } 750248557Sray 751248557Sray return (0); 752248557Sray} 753248557Sray 754248557Sraystatic int 755248557Srayipu3fb_clear(video_adapter_t *adp) 756248557Sray{ 757248557Sray 758248557Sray return (ipu3fb_blank_display(adp, 0)); 759248557Sray} 760248557Sray 761248557Sraystatic int 762248557Srayipu3fb_fill_rect(video_adapter_t *adp, int val, int x, int y, int cx, int cy) 763248557Sray{ 764248557Sray 765248557Sray return (0); 766248557Sray} 767248557Sray 768248557Sraystatic int 769248557Srayipu3fb_bitblt(video_adapter_t *adp, ...) 770248557Sray{ 771248557Sray 772248557Sray return (0); 773248557Sray} 774248557Sray 775248557Sraystatic int 776248557Srayipu3fb_diag(video_adapter_t *adp, int level) 777248557Sray{ 778248557Sray 779248557Sray return (0); 780248557Sray} 781248557Sray 782248557Sraystatic int 783248557Srayipu3fb_save_cursor_palette(video_adapter_t *adp, u_char *palette) 784248557Sray{ 785248557Sray 786248557Sray return (0); 787248557Sray} 788248557Sray 789248557Sraystatic int 790248557Srayipu3fb_load_cursor_palette(video_adapter_t *adp, u_char *palette) 791248557Sray{ 792248557Sray 793248557Sray return (0); 794248557Sray} 795248557Sray 796248557Sraystatic int 797248557Srayipu3fb_copy(video_adapter_t *adp, vm_offset_t src, vm_offset_t dst, int n) 798248557Sray{ 799248557Sray 800248557Sray return (0); 801248557Sray} 802248557Sray 803248557Sraystatic int 804248557Srayipu3fb_putp(video_adapter_t *adp, vm_offset_t off, uint32_t p, uint32_t a, 805248557Sray int size, int bpp, int bit_ltor, int byte_ltor) 806248557Sray{ 807248557Sray 808248557Sray return (0); 809248557Sray} 810248557Sray 811248557Sraystatic int 812248557Srayipu3fb_putc(video_adapter_t *adp, vm_offset_t off, uint8_t c, uint8_t a) 813248557Sray{ 814248557Sray struct video_adapter_softc *sc; 815248557Sray int col, row, bpp; 816248557Sray int b, i, j, k; 817248557Sray uint8_t *addr; 818248557Sray u_char *p; 819248557Sray uint32_t fg, bg, color; 820248557Sray 821248557Sray sc = (struct video_adapter_softc *)adp; 822248557Sray bpp = sc->bpp; 823248557Sray 824248557Sray if (sc->fb_addr == 0) 825248557Sray return (0); 826248557Sray row = (off / adp->va_info.vi_width) * adp->va_info.vi_cheight; 827248557Sray col = (off % adp->va_info.vi_width) * adp->va_info.vi_cwidth; 828248557Sray p = sc->font + c * IPU3FB_FONT_HEIGHT; 829248557Sray addr = (uint8_t *)sc->fb_addr 830248557Sray + (row + sc->ymargin) * (sc->stride) 831248557Sray + bpp * (col + sc->xmargin); 832248557Sray 833248557Sray if (bpp == 2) { 834248557Sray bg = colors[(a >> 4) & 0x0f]; 835248557Sray fg = colors[a & 0x0f]; 836248557Sray } else if (bpp == 3) { 837248557Sray bg = colors_24[(a >> 4) & 0x0f]; 838248557Sray fg = colors_24[a & 0x0f]; 839248557Sray } else { 840248557Sray return (ENXIO); 841248557Sray } 842248557Sray 843248557Sray for (i = 0; i < IPU3FB_FONT_HEIGHT; i++) { 844248557Sray for (j = 0, k = 7; j < 8; j++, k--) { 845248557Sray if ((p[i] & (1 << k)) == 0) 846248557Sray color = bg; 847248557Sray else 848248557Sray color = fg; 849248557Sray /* FIXME: BPP maybe different */ 850248557Sray for (b = 0; b < bpp; b ++) 851248557Sray addr[bpp * j + b] = 852248557Sray (color >> (b << 3)) & 0xff; 853248557Sray } 854248557Sray 855248557Sray addr += (sc->stride); 856248557Sray } 857248557Sray 858248557Sray return (0); 859248557Sray} 860248557Sray 861248557Sraystatic int 862248557Srayipu3fb_puts(video_adapter_t *adp, vm_offset_t off, u_int16_t *s, int len) 863248557Sray{ 864248557Sray int i; 865248557Sray 866248557Sray for (i = 0; i < len; i++) 867248557Sray ipu3fb_putc(adp, off + i, s[i] & 0xff, (s[i] & 0xff00) >> 8); 868248557Sray 869248557Sray return (0); 870248557Sray} 871248557Sray 872248557Sraystatic int 873248557Srayipu3fb_putm(video_adapter_t *adp, int x, int y, uint8_t *pixel_image, 874248557Sray uint32_t pixel_mask, int size, int width) 875248557Sray{ 876248557Sray 877248557Sray return (0); 878248557Sray} 879248557Sray 880248557Sray/* 881248557Sray * Define a stub keyboard driver in case one hasn't been 882248557Sray * compiled into the kernel 883248557Sray */ 884248557Sray#include <sys/kbio.h> 885248557Sray#include <dev/kbd/kbdreg.h> 886248557Sray 887248557Sraystatic int dummy_kbd_configure(int flags); 888248557Sray 889248557Sraykeyboard_switch_t ipu3dummysw; 890248557Sray 891248557Sraystatic int 892248557Sraydummy_kbd_configure(int flags) 893248557Sray{ 894248557Sray 895248557Sray return (0); 896248557Sray} 897248557SrayKEYBOARD_DRIVER(ipu3dummy, ipu3dummysw, dummy_kbd_configure); 898