1 /* $OpenBSD: astfb.c,v 1.3 2020/10/30 13:36:45 kettenis Exp $ */ 2 3 /* 4 * Copyright (c) 2020 Mark Kettenis. 5 * 6 * Permission to use, copy, modify, and distribute this software for any 7 * purpose with or without fee is hereby granted, provided that the above 8 * copyright notice and this permission notice appear in all copies. 9 * 10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 */ 18 19 #include <sys/param.h> 20 #include <sys/device.h> 21 #include <sys/systm.h> 22 23 #include <machine/bus.h> 24 #include <machine/fdt.h> 25 26 #include <dev/ofw/openfirm.h> 27 28 #include <dev/pci/pcireg.h> 29 #include <dev/pci/pcivar.h> 30 #include <dev/pci/pcidevs.h> 31 32 #include <dev/wscons/wsconsio.h> 33 #include <dev/wscons/wsdisplayvar.h> 34 35 #include <dev/rasops/rasops.h> 36 37 #define ASTFB_PCI_FB 0x10 38 39 struct astfb_softc { 40 struct device sc_dev; 41 bus_space_tag_t sc_iot; 42 bus_space_handle_t sc_ioh; 43 44 bus_addr_t sc_fbaddr; 45 bus_size_t sc_fbsize; 46 47 struct rasops_info sc_ri; 48 struct wsscreen_descr sc_wsd; 49 struct wsscreen_list sc_wsl; 50 struct wsscreen_descr *sc_scrlist[1]; 51 }; 52 53 int astfb_wsioctl(void *, u_long, caddr_t, int, struct proc *); 54 paddr_t astfb_wsmmap(void *, off_t, int); 55 int astfb_alloc_screen(void *, const struct wsscreen_descr *, 56 void **, int *, int *, uint32_t *); 57 58 struct wsdisplay_accessops astfb_accessops = { 59 .ioctl = astfb_wsioctl, 60 .mmap = astfb_wsmmap, 61 .alloc_screen = astfb_alloc_screen, 62 .free_screen = rasops_free_screen, 63 .show_screen = rasops_show_screen, 64 .getchar = rasops_getchar, 65 .load_font = rasops_load_font, 66 .list_font = rasops_list_font, 67 .scrollback = rasops_scrollback 68 }; 69 70 int astfb_match(struct device *, void *, void *); 71 void astfb_attach(struct device *, struct device *, void *); 72 73 struct cfattach astfb_ca = { 74 sizeof(struct astfb_softc), astfb_match, astfb_attach 75 }; 76 77 struct cfdriver astfb_cd = { 78 NULL, "astfb", DV_DULL 79 }; 80 81 int 82 astfb_match(struct device *parent, void *cf, void *aux) 83 { 84 struct pci_attach_args *pa = aux; 85 86 if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_ASPEED && 87 PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_ASPEED_AST2000 && 88 PCITAG_NODE(pa->pa_tag) != 0) 89 return 1; 90 91 return 0; 92 } 93 94 void 95 astfb_attach(struct device *parent, struct device *self, void *aux) 96 { 97 struct astfb_softc *sc = (struct astfb_softc *)self; 98 struct pci_attach_args *pa = aux; 99 struct rasops_info *ri = &sc->sc_ri; 100 struct wsemuldisplaydev_attach_args waa; 101 int node = PCITAG_NODE(pa->pa_tag); 102 uint32_t addr[5]; 103 int console = 0; 104 uint32_t defattr; 105 106 if (OF_getpropintarray(node, "assigned-addresses", addr, 107 sizeof(addr)) < sizeof(addr)) { 108 printf(": no framebuffer\n"); 109 return; 110 } 111 112 if (node == stdout_node) 113 console = 1; 114 115 sc->sc_fbaddr = (bus_addr_t)addr[1] << 32 | addr[2]; 116 sc->sc_fbsize = (bus_size_t)addr[3] << 32 | addr[4]; 117 118 sc->sc_iot = pa->pa_memt; 119 if (bus_space_map(sc->sc_iot, sc->sc_fbaddr, sc->sc_fbsize, 120 BUS_SPACE_MAP_LINEAR, &sc->sc_ioh)) { 121 printf(": can't map framebuffer\n"); 122 return; 123 } 124 125 printf("\n"); 126 127 ri->ri_bits = bus_space_vaddr(sc->sc_iot, sc->sc_ioh); 128 ri->ri_hw = sc; 129 130 ri->ri_width = OF_getpropint(node, "width", 0); 131 ri->ri_height = OF_getpropint(node, "height", 0); 132 ri->ri_depth = OF_getpropint(node, "depth", 0); 133 ri->ri_stride = ri->ri_width * ((ri->ri_depth + 7) / 8); 134 ri->ri_flg = RI_CENTER | RI_CLEAR | RI_FULLCLEAR | RI_WRONLY; 135 136 switch (ri->ri_depth) { 137 case 32: 138 ri->ri_rnum = 8; 139 ri->ri_rpos = 8; 140 ri->ri_gnum = 8; 141 ri->ri_gpos = 16; 142 ri->ri_bnum = 8; 143 ri->ri_bpos = 24; 144 break; 145 case 16: 146 ri->ri_rnum = 5; 147 ri->ri_rpos = 0; 148 ri->ri_gnum = 6; 149 ri->ri_gpos = 6; 150 ri->ri_bnum = 5; 151 ri->ri_bpos = 11; 152 break; 153 } 154 155 printf("%s: %dx%d, %dbpp\n", sc->sc_dev.dv_xname, 156 ri->ri_width, ri->ri_height, ri->ri_depth); 157 158 ri->ri_flg |= RI_VCONS; 159 rasops_init(ri, 160, 160); 160 161 strlcpy(sc->sc_wsd.name, "std", sizeof(sc->sc_wsd.name)); 162 sc->sc_wsd.capabilities = ri->ri_caps; 163 sc->sc_wsd.nrows = ri->ri_rows; 164 sc->sc_wsd.ncols = ri->ri_cols; 165 sc->sc_wsd.textops = &ri->ri_ops; 166 sc->sc_wsd.fontwidth = ri->ri_font->fontwidth; 167 sc->sc_wsd.fontheight = ri->ri_font->fontheight; 168 169 sc->sc_scrlist[0] = &sc->sc_wsd; 170 sc->sc_wsl.nscreens = 1; 171 sc->sc_wsl.screens = (const struct wsscreen_descr **)sc->sc_scrlist; 172 173 if (console) { 174 ri->ri_ops.pack_attr(ri->ri_active, 0, 0, 0, &defattr); 175 wsdisplay_cnattach(&sc->sc_wsd, ri->ri_active, 176 0, 0, defattr); 177 } 178 179 memset(&waa, 0, sizeof(waa)); 180 waa.scrdata = &sc->sc_wsl; 181 waa.accessops = &astfb_accessops; 182 waa.accesscookie = ri; 183 waa.console = console; 184 185 config_found_sm(self, &waa, wsemuldisplaydevprint, 186 wsemuldisplaydevsubmatch); 187 } 188 189 int 190 astfb_wsioctl(void *v, u_long cmd, caddr_t data, int flags, struct proc *p) 191 { 192 struct rasops_info *ri = v; 193 struct wsdisplay_fbinfo *wdf; 194 195 switch (cmd) { 196 case WSDISPLAYIO_GTYPE: 197 *(u_int *)data = WSDISPLAY_TYPE_ASTFB; 198 break; 199 case WSDISPLAYIO_GINFO: 200 wdf = (void *)data; 201 wdf->width = ri->ri_width; 202 wdf->height = ri->ri_height; 203 wdf->depth = ri->ri_depth; 204 wdf->cmsize = 0; /* color map is unavailable */ 205 break; 206 case WSDISPLAYIO_LINEBYTES: 207 *(u_int *)data = ri->ri_stride; 208 break; 209 case WSDISPLAYIO_SMODE: 210 break; 211 case WSDISPLAYIO_GETSUPPORTEDDEPTH: 212 switch (ri->ri_depth) { 213 case 32: 214 *(u_int *)data = WSDISPLAYIO_DEPTH_24_32; 215 break; 216 case 16: 217 *(u_int *)data = WSDISPLAYIO_DEPTH_16; 218 break; 219 default: 220 return -1; 221 } 222 break; 223 default: 224 return -1; 225 } 226 227 return 0; 228 } 229 230 paddr_t 231 astfb_wsmmap(void *v, off_t off, int prot) 232 { 233 struct rasops_info *ri = v; 234 struct astfb_softc *sc = ri->ri_hw; 235 236 if (off < 0 || off >= sc->sc_fbaddr) 237 return -1; 238 239 return (bus_space_mmap(sc->sc_iot, sc->sc_fbaddr, 240 off, prot, BUS_SPACE_MAP_LINEAR)); 241 } 242 243 int 244 astfb_alloc_screen(void *v, const struct wsscreen_descr *type, 245 void **cookiep, int *curxp, int *curyp, uint32_t *attrp) 246 { 247 return rasops_alloc_screen(v, cookiep, curxp, curyp, attrp); 248 } 249