creator_vt.c revision 271120
1/*- 2 * Copyright (c) 2014 Nathan Whitehorn 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 */ 26 27#include <sys/cdefs.h> 28__FBSDID("$FreeBSD: stable/10/sys/dev/fb/creator_vt.c 271120 2014-09-04 19:13:07Z emaste $"); 29 30#include <sys/param.h> 31#include <sys/kernel.h> 32#include <sys/systm.h> 33#include <sys/fbio.h> 34 35#include <dev/vt/vt.h> 36#include <dev/vt/hw/fb/vt_fb.h> 37#include <dev/vt/colors/vt_termcolors.h> 38 39#include <machine/bus.h> 40#include <machine/bus_private.h> 41 42#include <dev/ofw/openfirm.h> 43#include "creatorreg.h" 44 45static vd_probe_t creatorfb_probe; 46static vd_init_t creatorfb_init; 47static vd_blank_t creatorfb_blank; 48static vd_bitbltchr_t creatorfb_bitbltchr; 49 50static const struct vt_driver vt_creatorfb_driver = { 51 .vd_name = "creatorfb", 52 .vd_probe = creatorfb_probe, 53 .vd_init = creatorfb_init, 54 .vd_blank = creatorfb_blank, 55 .vd_bitbltchr = creatorfb_bitbltchr, 56 .vd_fb_ioctl = vt_fb_ioctl, 57 .vd_fb_mmap = vt_fb_mmap, 58 .vd_priority = VD_PRIORITY_SPECIFIC 59}; 60 61struct creatorfb_softc { 62 struct fb_info fb; 63 struct bus_space_tag memt[1]; 64 bus_space_handle_t memh; 65}; 66 67static struct creatorfb_softc creatorfb_conssoftc; 68VT_DRIVER_DECLARE(vt_creatorfb, vt_creatorfb_driver); 69 70static int 71creatorfb_probe(struct vt_device *vd) 72{ 73 phandle_t chosen, node; 74 ihandle_t stdout; 75 char type[64], name[64]; 76 77 chosen = OF_finddevice("/chosen"); 78 OF_getprop(chosen, "stdout", &stdout, sizeof(stdout)); 79 node = OF_instance_to_package(stdout); 80 if (node == -1) { 81 /* 82 * The "/chosen/stdout" does not exist try 83 * using "screen" directly. 84 */ 85 node = OF_finddevice("screen"); 86 } 87 OF_getprop(node, "device_type", type, sizeof(type)); 88 if (strcmp(type, "display") != 0) 89 return (CN_DEAD); 90 91 OF_getprop(node, "name", name, sizeof(name)); 92 if (strcmp(name, "SUNW,ffb") != 0 && strcmp(name, "SUNW,afb") != 0) 93 return (CN_DEAD); 94 95 /* Looks OK... */ 96 return (CN_INTERNAL); 97} 98 99static int 100creatorfb_init(struct vt_device *vd) 101{ 102 struct creatorfb_softc *sc; 103 phandle_t chosen; 104 phandle_t node; 105 ihandle_t handle; 106 uint32_t height, width; 107 char type[64], name[64]; 108 bus_addr_t phys; 109 int space; 110 111 /* Initialize softc */ 112 vd->vd_softc = sc = &creatorfb_conssoftc; 113 114 chosen = OF_finddevice("/chosen"); 115 OF_getprop(chosen, "stdout", &handle, sizeof(ihandle_t)); 116 node = OF_instance_to_package(handle); 117 if (node == -1) { 118 /* 119 * The "/chosen/stdout" does not exist try 120 * using "screen" directly. 121 */ 122 node = OF_finddevice("screen"); 123 handle = OF_open("screen"); 124 } 125 OF_getprop(node, "device_type", type, sizeof(type)); 126 if (strcmp(type, "display") != 0) 127 return (CN_DEAD); 128 129 OF_getprop(node, "name", name, sizeof(name)); 130 if (strcmp(name, "SUNW,ffb") != 0 && strcmp(name, "SUNW,afb") != 0) 131 return (CN_DEAD); 132 133 /* Make sure we have needed properties */ 134 if (OF_getproplen(node, "height") != sizeof(height) || 135 OF_getproplen(node, "width") != sizeof(width)) 136 return (CN_DEAD); 137 138 OF_getprop(node, "height", &height, sizeof(height)); 139 OF_getprop(node, "width", &width, sizeof(width)); 140 141 sc->fb.fb_height = height; 142 sc->fb.fb_width = width; 143 sc->fb.fb_bpp = sc->fb.fb_depth = 32; 144 sc->fb.fb_stride = 8192; /* Fixed */ 145 sc->fb.fb_size = sc->fb.fb_height * sc->fb.fb_stride; 146 147 /* Map linear framebuffer */ 148 if (OF_decode_addr(node, FFB_DFB24, &space, &phys) != 0) 149 return (CN_DEAD); 150 sc->fb.fb_pbase = phys; 151 sc->memh = sparc64_fake_bustag(space, phys, &sc->memt[0]); 152 153 /* 32-bit VGA palette */ 154 vt_generate_cons_palette(sc->fb.fb_cmap, COLOR_FORMAT_RGB, 155 255, 0, 255, 8, 255, 16); 156 sc->fb.fb_cmsize = 16; 157 158 vt_fb_init(vd); 159 160 return (CN_INTERNAL); 161} 162 163static void 164creatorfb_blank(struct vt_device *vd, term_color_t color) 165{ 166 struct creatorfb_softc *sc; 167 uint32_t c; 168 int i; 169 170 sc = vd->vd_softc; 171 c = sc->fb.fb_cmap[color]; 172 173 for (i = 0; i < sc->fb.fb_height; i++) 174 bus_space_set_region_4(sc->memt, sc->memh, i*sc->fb.fb_stride, 175 c, sc->fb.fb_width); 176} 177 178static void 179creatorfb_bitbltchr(struct vt_device *vd, const uint8_t *src, 180 const uint8_t *mask, int bpl, vt_axis_t top, vt_axis_t left, 181 unsigned int width, unsigned int height, term_color_t fg, term_color_t bg) 182{ 183 struct creatorfb_softc *sc = vd->vd_softc; 184 u_long line; 185 uint32_t fgc, bgc; 186 int c; 187 uint8_t b, m; 188 189 fgc = sc->fb.fb_cmap[fg]; 190 bgc = sc->fb.fb_cmap[bg]; 191 b = m = 0; 192 193 /* Don't try to put off screen pixels */ 194 if (((left + width) > vd->vd_width) || ((top + height) > 195 vd->vd_height)) 196 return; 197 198 line = (sc->fb.fb_stride * top) + 4*left; 199 for (; height > 0; height--) { 200 for (c = 0; c < width; c++) { 201 if (c % 8 == 0) 202 b = *src++; 203 else 204 b <<= 1; 205 if (mask != NULL) { 206 if (c % 8 == 0) 207 m = *mask++; 208 else 209 m <<= 1; 210 /* Skip pixel write if mask not set. */ 211 if ((m & 0x80) == 0) 212 continue; 213 } 214 bus_space_write_4(sc->memt, sc->memh, line + 4*c, 215 (b & 0x80) ? fgc : bgc); 216 } 217 line += sc->fb.fb_stride; 218 } 219} 220 221