vt_fb.c revision 257988
1166255Sdelphij/*- 2166255Sdelphij * Copyright (c) 2013 The FreeBSD Foundation 3166255Sdelphij * All rights reserved. 4166255Sdelphij * 5166255Sdelphij * This software was developed by Aleksandr Rybalko under sponsorship from the 6166255Sdelphij * FreeBSD Foundation. 7166255Sdelphij * 8166255Sdelphij * Redistribution and use in source and binary forms, with or without 9166255Sdelphij * modification, are permitted provided that the following conditions 10166255Sdelphij * are met: 11166255Sdelphij * 1. Redistributions of source code must retain the above copyright 12166255Sdelphij * notice, this list of conditions and the following disclaimer. 13166255Sdelphij * 2. Redistributions in binary form must reproduce the above copyright 14166255Sdelphij * notice, this list of conditions and the following disclaimer in the 15166255Sdelphij * documentation and/or other materials provided with the distribution. 16166255Sdelphij * 17166255Sdelphij * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 18166255Sdelphij * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19166255Sdelphij * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20166255Sdelphij * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 21166255Sdelphij * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22166255Sdelphij * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23166255Sdelphij * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24166255Sdelphij * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25166255Sdelphij * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26166255Sdelphij * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27166255Sdelphij * SUCH DAMAGE. 28166255Sdelphij * 29166255Sdelphij * $FreeBSD: user/ed/newcons/sys/dev/vt/hw/fb/vt_fb.c 257988 2013-11-11 13:25:49Z ray $ 30166255Sdelphij */ 31166255Sdelphij 32166255Sdelphij#include <sys/cdefs.h> 33166255Sdelphij__FBSDID("$FreeBSD: user/ed/newcons/sys/dev/vt/hw/fb/vt_fb.c 257988 2013-11-11 13:25:49Z ray $"); 34166255Sdelphij 35166255Sdelphij#include <sys/param.h> 36166255Sdelphij#include <sys/systm.h> 37166255Sdelphij#include <sys/malloc.h> 38166255Sdelphij#include <sys/queue.h> 39166255Sdelphij#include <sys/fbio.h> 40166255Sdelphij#include <dev/vt/vt.h> 41166255Sdelphij#include <dev/vt/hw/fb/vt_fb.h> 42166255Sdelphij#include <dev/vt/colors/vt_termcolors.h> 43166255Sdelphij 44166255Sdelphijstatic struct vt_driver vt_fb_driver = { 45166255Sdelphij .vd_init = vt_fb_init, 46166255Sdelphij .vd_blank = vt_fb_blank, 47166255Sdelphij .vd_bitbltchr = vt_fb_bitbltchr, 48166255Sdelphij .vd_postswitch = vt_fb_postswitch, 49166255Sdelphij .vd_priority = VD_PRIORITY_GENERIC+10, 50166255Sdelphij}; 51166255Sdelphij 52166255Sdelphijvoid 53166255Sdelphijvt_fb_blank(struct vt_device *vd, term_color_t color) 54166255Sdelphij{ 55166255Sdelphij struct fb_info *info; 56166255Sdelphij uint32_t c; 57166255Sdelphij u_int o; 58166255Sdelphij 59166255Sdelphij info = vd->vd_softc; 60166255Sdelphij c = info->fb_cmap[color]; 61166255Sdelphij 62166255Sdelphij switch (FBTYPE_GET_BYTESPP(info)) { 63166255Sdelphij case 1: 64166255Sdelphij for (o = 0; o < info->fb_stride; o++) 65166255Sdelphij info->wr1(info, o, c); 66166255Sdelphij break; 67166255Sdelphij case 2: 68166255Sdelphij for (o = 0; o < info->fb_stride; o += 2) 69166255Sdelphij info->wr2(info, o, c); 70166255Sdelphij break; 71166255Sdelphij case 3: 72166255Sdelphij /* line 0 */ 73166255Sdelphij for (o = 0; o < info->fb_stride; o += 3) { 74166255Sdelphij info->wr1(info, o, (c >> 16) & 0xff); 75166255Sdelphij info->wr1(info, o + 1, (c >> 8) & 0xff); 76166255Sdelphij info->wr1(info, o + 2, c & 0xff); 77166255Sdelphij } 78166255Sdelphij break; 79166255Sdelphij case 4: 80166255Sdelphij for (o = 0; o < info->fb_stride; o += 4) 81166255Sdelphij info->wr4(info, o, c); 82166255Sdelphij break; 83166255Sdelphij default: 84166255Sdelphij /* panic? */ 85166255Sdelphij return; 86166255Sdelphij } 87166255Sdelphij /* Copy line0 to all other lines. */ 88166255Sdelphij /* XXX will copy with borders. */ 89166255Sdelphij for (o = info->fb_stride; o < info->fb_size; o += info->fb_stride) { 90166255Sdelphij info->copy(info, o, 0, info->fb_stride); 91166255Sdelphij } 92166255Sdelphij} 93166255Sdelphij 94166255Sdelphijvoid 95166255Sdelphijvt_fb_bitbltchr(struct vt_device *vd, const uint8_t *src, const uint8_t *mask, 96166255Sdelphij int bpl, vt_axis_t top, vt_axis_t left, unsigned int width, 97166255Sdelphij unsigned int height, term_color_t fg, term_color_t bg) 98166255Sdelphij{ 99166255Sdelphij struct fb_info *info; 100166255Sdelphij uint32_t fgc, bgc, cc, o; 101166255Sdelphij int c, l, bpp; 102166255Sdelphij u_long line; 103166255Sdelphij uint8_t b, m; 104166255Sdelphij const uint8_t *ch; 105166255Sdelphij 106166255Sdelphij info = vd->vd_softc; 107166255Sdelphij bpp = FBTYPE_GET_BYTESPP(info); 108166255Sdelphij fgc = info->fb_cmap[fg]; 109166255Sdelphij bgc = info->fb_cmap[bg]; 110166255Sdelphij if (bpl == 0) 111166255Sdelphij bpl = (width + 7) >> 3; /* Bytes per sorce line. */ 112166255Sdelphij 113166255Sdelphij /* Don't try to put off screen pixels */ 114166255Sdelphij if (((left + width) > info->fb_width) || ((top + height) > 115166255Sdelphij info->fb_height)) 116166255Sdelphij return; 117166255Sdelphij 118166255Sdelphij line = (info->fb_stride * top) + (left * bpp); 119166255Sdelphij for (l = 0; l < height; l++) { 120166255Sdelphij ch = src; 121166255Sdelphij for (c = 0; c < width; c++) { 122166255Sdelphij if (c % 8 == 0) 123166255Sdelphij b = *ch++; 124166255Sdelphij else 125166255Sdelphij b <<= 1; 126166255Sdelphij if (mask != NULL) { 127166255Sdelphij if (c % 8 == 0) 128166255Sdelphij m = *mask++; 129 else 130 m <<= 1; 131 /* Skip pixel write, if mask has no bit set. */ 132 if ((m & 0x80) == 0) 133 continue; 134 } 135 o = line + (c * bpp); 136 cc = b & 0x80 ? fgc : bgc; 137 138 switch(bpp) { 139 case 1: 140 info->wr1(info, o, cc); 141 break; 142 case 2: 143 info->wr2(info, o, cc); 144 break; 145 case 3: 146 /* Packed mode, so unaligned. Byte access. */ 147 info->wr1(info, o, (cc >> 16) & 0xff); 148 info->wr1(info, o + 1, (cc >> 8) & 0xff); 149 info->wr1(info, o + 2, cc & 0xff); 150 break; 151 case 4: 152 info->wr4(info, o, cc); 153 break; 154 default: 155 /* panic? */ 156 break; 157 } 158 } 159 line += info->fb_stride; 160 src += bpl; 161 } 162} 163 164void 165vt_fb_postswitch(struct vt_device *vd) 166{ 167 struct fb_info *info; 168 169 info = vd->vd_softc; 170 171 if (info->enter != NULL) 172 info->enter(info->fb_priv); 173} 174 175static int 176vt_fb_init_cmap(uint32_t *cmap, int depth) 177{ 178 179 switch (depth) { 180 case 8: 181 return (vt_generate_vga_palette(cmap, COLOR_FORMAT_RGB, 182 0x7, 5, 0x7, 2, 0x3, 0)); 183 case 15: 184 return (vt_generate_vga_palette(cmap, COLOR_FORMAT_RGB, 185 0x1f, 10, 0x1f, 5, 0x1f, 0)); 186 case 16: 187 return (vt_generate_vga_palette(cmap, COLOR_FORMAT_RGB, 188 0x1f, 11, 0x3f, 5, 0x1f, 0)); 189 case 24: 190 case 32: /* Ignore alpha. */ 191 return (vt_generate_vga_palette(cmap, COLOR_FORMAT_RGB, 192 0xff, 0, 0xff, 8, 0xff, 16)); 193 default: 194 return (1); 195 } 196} 197 198int 199vt_fb_init(struct vt_device *vd) 200{ 201 struct fb_info *info; 202 int err; 203 204 info = vd->vd_softc; 205 vd->vd_height = info->fb_height; 206 vd->vd_width = info->fb_width; 207 208 if (info->fb_cmsize <= 0) { 209 err = vt_fb_init_cmap(info->fb_cmap, FBTYPE_GET_BPP(info)); 210 if (err) 211 return (CN_DEAD); 212 info->fb_cmsize = 16; 213 } 214 215 /* Clear the screen. */ 216 vt_fb_blank(vd, TC_BLACK); 217 218 /* Wakeup screen. KMS need this. */ 219 vt_fb_postswitch(vd); 220 221 return (CN_INTERNAL); 222} 223 224int 225vt_fb_attach(struct fb_info *info) 226{ 227 228 vt_allocate(&vt_fb_driver, info); 229 230 return (0); 231} 232 233void 234vt_fb_resume(void) 235{ 236 237 vt_resume(); 238} 239 240void 241vt_fb_suspend(void) 242{ 243 244 vt_suspend(); 245} 246