1/* $NetBSD$ */ 2/* $OpenBSD: tvrx.c,v 1.1 2006/04/14 21:05:43 miod Exp $ */ 3 4/* 5 * Copyright (c) 2006, Miodrag Vallat. 6 * All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 19 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 20 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, 21 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 22 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 23 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 25 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 26 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 27 * POSSIBILITY OF SUCH DAMAGE. 28 * 29 */ 30 31/* 32 * dumb graphics routines for frame buffer on HP362 and HP382 based on tvrx.c 33 */ 34 35#include <sys/param.h> 36#include <sys/systm.h> 37#include <sys/conf.h> 38#include <sys/device.h> 39#include <sys/proc.h> 40#include <sys/ioctl.h> 41#include <sys/bus.h> 42#include <sys/cpu.h> 43 44#include <machine/autoconf.h> 45 46#include <hp300/dev/dioreg.h> 47#include <hp300/dev/diovar.h> 48#include <hp300/dev/diodevs.h> 49 50#include <dev/cons.h> 51 52#include <dev/wscons/wsconsio.h> 53#include <dev/wscons/wsdisplayvar.h> 54#include <dev/rasops/rasops.h> 55 56#include <hp300/dev/diofbreg.h> 57#include <hp300/dev/diofbvar.h> 58 59struct gendiofb_softc { 60 device_t sc_dev; 61 struct diofb *sc_fb; 62 struct diofb sc_fb_store; 63 int sc_scode; 64}; 65 66static int gendiofb_match(device_t, cfdata_t, void *); 67static void gendiofb_attach(device_t, device_t, void *); 68 69CFATTACH_DECL_NEW(gendiofb, sizeof(struct gendiofb_softc), 70 gendiofb_match, gendiofb_attach, NULL, NULL); 71 72static int gendiofb_reset(struct diofb *, int, struct diofbreg *); 73 74static int gendiofb_ioctl(void *, void *, u_long, void *, int, struct lwp *); 75 76static struct wsdisplay_accessops gendiofb_accessops = { 77 gendiofb_ioctl, 78 diofb_mmap, 79 diofb_alloc_screen, 80 diofb_free_screen, 81 diofb_show_screen, 82 NULL, /* load_font */ 83}; 84 85/* 86 * Attachment glue 87 */ 88 89static int 90gendiofb_match(device_t parent, cfdata_t cf, void *aux) 91{ 92 struct dio_attach_args *da = aux; 93 94 if (da->da_id == DIO_DEVICE_ID_FRAMEBUFFER) { 95 switch (da->da_secid) { 96 case DIO_DEVICE_SECID_A147xVGA: 97 case DIO_DEVICE_SECID_A1474MID: 98 return 1; 99 } 100 } 101 102 return 0; 103} 104 105static void 106gendiofb_attach(device_t parent, device_t self, void *aux) 107{ 108 struct gendiofb_softc *sc = device_private(self); 109 struct dio_attach_args *da = aux; 110 bus_space_handle_t bsh; 111 struct diofbreg *fbr; 112 bus_size_t size; 113 114 sc->sc_dev = self; 115 sc->sc_scode = da->da_scode; 116 if (sc->sc_scode == conscode) { 117 fbr = (struct diofbreg *)conaddr; /* already mapped */ 118 sc->sc_fb = &diofb_cn; 119 } else { 120 sc->sc_fb = &sc->sc_fb_store; 121 size = da->da_size; 122 if (size > DIOII_DEVSIZE) /* XXX */ 123 size = DIOII_DEVSIZE; 124 if (bus_space_map(da->da_bst, da->da_addr, size, 0, 125 &bsh)) { 126 aprint_error(": can't map framebuffer\n"); 127 return; 128 } 129 fbr = bus_space_vaddr(da->da_bst, bsh); 130 if (gendiofb_reset(sc->sc_fb, sc->sc_scode, fbr) != 0) { 131 aprint_error(": failed to reset\n"); 132 return; 133 } 134 } 135 136 diofb_end_attach(self, &gendiofb_accessops, sc->sc_fb, 137 sc->sc_scode == conscode, NULL); 138} 139 140/* 141 * Initialize hardware and display routines. 142 */ 143static int 144gendiofb_reset(struct diofb *fb, int scode, struct diofbreg *fbr) 145{ 146 int rc; 147 struct rasops_info *ri = &fb->ri; 148 149 if ((rc = diofb_fbinquire(fb, scode, fbr)) != 0) 150 return (rc); 151 152 /* 153 * We rely on the PROM to initialize the frame buffer in the mode 154 * we expect it: cleared, overlay plane enabled and accessible 155 * at the beginning of the video memory. 156 * 157 * This is NOT the mode we would end up by simply resetting the 158 * board. 159 */ 160 161 ri->ri_depth = 8; 162 ri->ri_stride = (fb->fbwidth * ri->ri_depth) / 8; 163 164 ri->ri_flg = RI_CENTER | RI_FULLCLEAR; 165 if (fb == &diofb_cn) 166 ri->ri_flg |= RI_NO_AUTO; /* XXX */ 167 ri->ri_bits = fb->fbkva; 168 ri->ri_width = fb->dwidth; 169 ri->ri_height = fb->dheight; 170 ri->ri_hw = fb; 171 172 /* 173 * Ask for an unholy big display, rasops will trim this to more 174 * reasonable values. 175 */ 176 rasops_init(ri, 160, 160); 177 ri->ri_flg |= RI_FORCEMONO; /* no colormap */ 178 179 diofb_resetcmap(fb); 180 181 fb->wsd.name = fb->wsdname; 182 fb->wsd.ncols = ri->ri_cols; 183 fb->wsd.nrows = ri->ri_rows; 184 fb->wsd.textops = &ri->ri_ops; 185 fb->wsd.fontwidth = ri->ri_font->fontwidth; 186 fb->wsd.fontheight = ri->ri_font->fontheight; 187 fb->wsd.capabilities = ri->ri_caps; 188 strlcpy(fb->wsdname, "std", sizeof(fb->wsdname)); 189 190 return 0; 191} 192 193static int 194gendiofb_ioctl(void *v, void *vs, u_long cmd, void *data, int flags, 195 struct lwp *l) 196{ 197 struct diofb *fb = v; 198 struct wsdisplay_fbinfo *wdf; 199 200 switch (cmd) { 201 case WSDISPLAYIO_GTYPE: 202 *(u_int *)data = WSDISPLAY_TYPE_UNKNOWN; 203 return 0; 204 case WSDISPLAYIO_SMODE: 205 fb->mapmode = *(u_int *)data; 206 return 0; 207 case WSDISPLAYIO_GINFO: 208 wdf = (void *)data; 209 wdf->width = fb->ri.ri_width; 210 wdf->height = fb->ri.ri_height; 211 wdf->depth = fb->ri.ri_depth; 212 wdf->cmsize = 0; 213 return 0; 214 case WSDISPLAYIO_LINEBYTES: 215 *(u_int *)data = fb->ri.ri_stride; 216 return 0; 217 case WSDISPLAYIO_GETCMAP: 218 case WSDISPLAYIO_PUTCMAP: 219 /* until color support is implemented */ 220 return EPASSTHROUGH; 221 case WSDISPLAYIO_GVIDEO: 222 case WSDISPLAYIO_SVIDEO: 223 /* unsupported */ 224 return EPASSTHROUGH; 225 } 226 227 return EPASSTHROUGH; 228} 229 230 231/* 232 * Console attachment 233 */ 234 235int 236gendiofbcnattach(bus_space_tag_t bst, bus_addr_t addr, int scode) 237{ 238 bus_space_handle_t bsh; 239 void *va; 240 struct diofbreg *fbr; 241 struct diofb *fb = &diofb_cn; 242 bus_size_t size; 243 244 if (bus_space_map(bst, addr, PAGE_SIZE, 0, &bsh)) 245 return 1; 246 va = bus_space_vaddr(bst, bsh); 247 fbr = va; 248 if (badaddr(va) || 249 fbr->id != GRFHWID || 250 (fbr->fbid != DIO_DEVICE_SECID_A1474MID && 251 fbr->fbid != DIO_DEVICE_SECID_A147xVGA)) { 252 bus_space_unmap(bst, bsh, PAGE_SIZE); 253 return 1; 254 } 255 256 size = DIO_SIZE(scode, va); 257 if (size > DIOII_DEVSIZE) /* XXX */ 258 size = DIOII_DEVSIZE; 259 260 bus_space_unmap(bst, bsh, PAGE_SIZE); 261 if (bus_space_map(bst, addr, size, 0, &bsh)) 262 return 1; 263 va = bus_space_vaddr(bst, bsh); 264 265 /* 266 * Initialize the framebuffer hardware. 267 */ 268 conscode = scode; 269 conaddr = va; 270 gendiofb_reset(fb, conscode, (struct diofbreg *)conaddr); 271 272 /* 273 * Initialize the terminal emulator. 274 */ 275 diofb_cnattach(fb); 276 return 0; 277} 278