vt_fb.c revision 256904
1193323Sed/*- 2193323Sed * Copyright (c) 2013 The FreeBSD Foundation 3193323Sed * All rights reserved. 4193323Sed * 5193323Sed * This software was developed by Aleksandr Rybalko under sponsorship from the 6193323Sed * FreeBSD Foundation. 7193323Sed * 8193323Sed * Redistribution and use in source and binary forms, with or without 9193323Sed * modification, are permitted provided that the following conditions 10193323Sed * are met: 11193323Sed * 1. Redistributions of source code must retain the above copyright 12193323Sed * notice, this list of conditions and the following disclaimer. 13193323Sed * 2. Redistributions in binary form must reproduce the above copyright 14193323Sed * notice, this list of conditions and the following disclaimer in the 15193323Sed * documentation and/or other materials provided with the distribution. 16193323Sed * 17249423Sdim * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 18249423Sdim * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19193323Sed * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20249423Sdim * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 21193323Sed * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22243830Sdim * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23193323Sed * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24193323Sed * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25193323Sed * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26193323Sed * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27193323Sed * SUCH DAMAGE. 28193323Sed * 29193323Sed * $FreeBSD: user/ed/newcons/sys/dev/vt/hw/fb/vt_fb.c 256904 2013-10-22 14:39:32Z ray $ 30193323Sed */ 31193323Sed 32193323Sed#include <sys/cdefs.h> 33193323Sed__FBSDID("$FreeBSD: user/ed/newcons/sys/dev/vt/hw/fb/vt_fb.c 256904 2013-10-22 14:39:32Z ray $"); 34193323Sed 35193323Sed#include <sys/param.h> 36193323Sed#include <sys/systm.h> 37193323Sed#include <sys/malloc.h> 38193323Sed#include <sys/queue.h> 39193323Sed#include <sys/fbio.h> 40193323Sed#include <dev/vt/vt.h> 41193323Sed#include <dev/vt/hw/fb/vt_fb.h> 42193323Sed#include <dev/vt/colors/vt_termcolors.h> 43249423Sdim 44249423Sdimstatic vd_init_t vt_fb_init; 45249423Sdimstatic vd_blank_t vt_fb_blank; 46193323Sedstatic vd_bitbltchr_t vt_fb_bitbltchr; 47249423Sdimstatic vd_postswitch_t vt_fb_postswitch; 48249423Sdim 49193323Sedstatic struct vt_driver vt_fb_driver = { 50249423Sdim .vd_init = vt_fb_init, 51249423Sdim .vd_blank = vt_fb_blank, 52249423Sdim .vd_bitbltchr = vt_fb_bitbltchr, 53193323Sed .vd_postswitch = vt_fb_postswitch, 54249423Sdim .vd_priority = VD_PRIORITY_GENERIC+10, 55249423Sdim}; 56249423Sdim 57193323Sedstatic void 58249423Sdimvt_fb_blank(struct vt_device *vd, term_color_t color) 59249423Sdim{ 60249423Sdim struct fb_info *info; 61193323Sed uint32_t c; 62193323Sed u_int o; 63193323Sed 64193323Sed info = vd->vd_softc; 65193323Sed c = info->fb_cmap[color]; 66193323Sed switch (FBTYPE_GET_BYTESPP(info)) { 67193323Sed case 1: 68193323Sed for (o = 0; o < info->fb_stride; o++) 69193323Sed info->wr1(info, o, c); 70234353Sdim break; 71234353Sdim case 2: 72234353Sdim for (o = 0; o < info->fb_stride; o += 2) 73234353Sdim info->wr2(info, o, c); 74193323Sed break; 75193323Sed case 3: 76249423Sdim /* line 0 */ 77193323Sed for (o = 0; o < info->fb_stride; o += 3) { 78193323Sed info->wr1(info, o, (c >> 16) & 0xff); 79193323Sed info->wr1(info, o + 1, (c >> 8) & 0xff); 80193323Sed info->wr1(info, o + 2, c & 0xff); 81193323Sed } 82198090Srdivacky break; 83198090Srdivacky case 4: 84198090Srdivacky for (o = 0; o < info->fb_stride; o += 4) 85198090Srdivacky info->wr4(info, o, c); 86198090Srdivacky break; 87193323Sed default: 88193323Sed /* panic? */ 89198090Srdivacky return; 90198090Srdivacky } 91193323Sed /* Copy line0 to all other lines. */ 92193323Sed /* XXX will copy with borders. */ 93193323Sed for (o = 1; o < info->fb_height; o++) { 94193323Sed memmove((void *)(info->fb_vbase + o * info->fb_stride), 95193323Sed (void *)info->fb_vbase, info->fb_stride); 96249423Sdim } 97249423Sdim} 98249423Sdim 99249423Sdimstatic void 100249423Sdimvt_fb_bitbltchr(struct vt_device *vd, const uint8_t *src, 101249423Sdim vt_axis_t top, vt_axis_t left, unsigned int width, unsigned int height, 102249423Sdim term_color_t fg, term_color_t bg) 103249423Sdim{ 104249423Sdim struct fb_info *info; 105193323Sed uint32_t fgc, bgc, cc, o; 106249423Sdim int c, l, bpp; 107249423Sdim u_long line; 108249423Sdim uint8_t b; 109249423Sdim 110249423Sdim b = 0; 111193323Sed info = vd->vd_softc; 112249423Sdim bpp = FBTYPE_GET_BYTESPP(info); 113249423Sdim fgc = info->fb_cmap[fg]; 114249423Sdim bgc = info->fb_cmap[bg]; 115249423Sdim 116193323Sed line = (info->fb_stride * top) + (left * bpp); 117193323Sed for (l = 0; l < height; l++) { 118193323Sed for (c = 0; c < width; c++) { 119210299Sed if (c % 8 == 0) 120210299Sed b = *src++; 121221345Sdim else 122210299Sed b <<= 1; 123193323Sed o = line + (c * bpp); 124198090Srdivacky cc = b & 0x80 ? fgc : bgc; 125198090Srdivacky 126193323Sed switch(bpp) { 127249423Sdim case 1: 128249423Sdim info->wr1(info, o, cc); 129249423Sdim break; 130249423Sdim case 2: 131193323Sed info->wr2(info, o, cc); 132249423Sdim break; 133249423Sdim case 3: 134263508Sdim /* Packed mode, so unaligned. Byte access. */ 135249423Sdim info->wr1(info, o, (cc >> 16) & 0xff); 136249423Sdim info->wr1(info, o + 1, (cc >> 8) & 0xff); 137249423Sdim info->wr1(info, o + 2, cc & 0xff); 138249423Sdim break; 139249423Sdim case 4: 140249423Sdim info->wr4(info, o, cc); 141249423Sdim break; 142249423Sdim default: 143249423Sdim /* panic? */ 144263508Sdim break; 145249423Sdim } 146249423Sdim } 147249423Sdim line += info->fb_stride; 148249423Sdim } 149249423Sdim} 150193323Sed 151193323Sedstatic void 152193323Sedvt_fb_postswitch(struct vt_device *vd) 153193323Sed{ 154193323Sed struct fb_info *info; 155193323Sed 156193323Sed info = vd->vd_softc; 157193323Sed 158193323Sed if (info->enter != NULL) 159193323Sed info->enter(info->fb_priv); 160198090Srdivacky} 161198090Srdivacky 162198090Srdivackystatic int 163193323Sedvt_fb_init_cmap(uint32_t *cmap, int depth) 164198090Srdivacky{ 165243830Sdim 166193323Sed switch (depth) { 167249423Sdim case 8: 168249423Sdim return (vt_generate_vga_palette(cmap, COLOR_FORMAT_RGB, 169249423Sdim 0x7, 5, 0x7, 2, 0x3, 0)); 170198090Srdivacky case 15: 171249423Sdim return (vt_generate_vga_palette(cmap, COLOR_FORMAT_RGB, 172249423Sdim 0x1f, 10, 0x1f, 5, 0x1f, 0)); 173234353Sdim case 16: 174198090Srdivacky return (vt_generate_vga_palette(cmap, COLOR_FORMAT_RGB, 175198090Srdivacky 0x1f, 11, 0x3f, 5, 0x1f, 0)); 176198090Srdivacky case 24: 177198090Srdivacky case 32: /* Ignore alpha. */ 178198090Srdivacky return (vt_generate_vga_palette(cmap, COLOR_FORMAT_RGB, 179198090Srdivacky 0xff, 0, 0xff, 8, 0xff, 16)); 180198090Srdivacky default: 181234353Sdim return (1); 182198090Srdivacky } 183198090Srdivacky} 184198090Srdivacky 185198090Srdivackystatic int 186198090Srdivackyvt_fb_init(struct vt_device *vd) 187249423Sdim{ 188249423Sdim struct fb_info *info; 189249423Sdim int err; 190249423Sdim 191198090Srdivacky info = vd->vd_softc; 192198090Srdivacky vd->vd_height = info->fb_height; 193198090Srdivacky vd->vd_width = info->fb_width; 194210299Sed 195210299Sed if (info->fb_cmsize <= 0) { 196210299Sed err = vt_fb_init_cmap(info->fb_cmap, FBTYPE_GET_BPP(info)); 197210299Sed if (err) 198210299Sed return (CN_DEAD); 199210299Sed info->fb_cmsize = 16; 200198090Srdivacky } 201198090Srdivacky 202198090Srdivacky /* Clear the screen. */ 203198090Srdivacky vt_fb_blank(vd, TC_BLACK); 204193323Sed 205198090Srdivacky /* Wakeup screen. KMS need this. */ 206193323Sed vt_fb_postswitch(vd); 207193323Sed 208193323Sed return (CN_INTERNAL); 209} 210 211int 212vt_fb_attach(struct fb_info *info) 213{ 214 215 vt_allocate(&vt_fb_driver, info); 216 return (0); 217} 218