vt_fb.c revision 257013
1/*- 2 * Copyright (c) 2013 The FreeBSD Foundation 3 * All rights reserved. 4 * 5 * This software was developed by Aleksandr Rybalko under sponsorship from the 6 * FreeBSD Foundation. 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 AND CONTRIBUTORS ``AS IS'' AND 18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27 * SUCH DAMAGE. 28 * 29 * $FreeBSD: user/ed/newcons/sys/dev/vt/hw/fb/vt_fb.c 257013 2013-10-23 19:45:14Z ray $ 30 */ 31 32#include <sys/cdefs.h> 33__FBSDID("$FreeBSD: user/ed/newcons/sys/dev/vt/hw/fb/vt_fb.c 257013 2013-10-23 19:45:14Z ray $"); 34 35#include <sys/param.h> 36#include <sys/systm.h> 37#include <sys/malloc.h> 38#include <sys/queue.h> 39#include <sys/fbio.h> 40#include <dev/vt/vt.h> 41#include <dev/vt/hw/fb/vt_fb.h> 42#include <dev/vt/colors/vt_termcolors.h> 43 44static vd_init_t vt_fb_init; 45static vd_blank_t vt_fb_blank; 46static vd_bitbltchr_t vt_fb_bitbltchr; 47static vd_postswitch_t vt_fb_postswitch; 48 49static struct vt_driver vt_fb_driver = { 50 .vd_init = vt_fb_init, 51 .vd_blank = vt_fb_blank, 52 .vd_bitbltchr = vt_fb_bitbltchr, 53 .vd_postswitch = vt_fb_postswitch, 54 .vd_priority = VD_PRIORITY_GENERIC+10, 55}; 56 57static void 58vt_fb_blank(struct vt_device *vd, term_color_t color) 59{ 60 struct fb_info *info; 61 uint32_t c; 62 u_int o; 63 64 info = vd->vd_softc; 65 c = info->fb_cmap[color]; 66 switch (FBTYPE_GET_BYTESPP(info)) { 67 case 1: 68 for (o = 0; o < info->fb_stride; o++) 69 info->wr1(info, o, c); 70 break; 71 case 2: 72 for (o = 0; o < info->fb_stride; o += 2) 73 info->wr2(info, o, c); 74 break; 75 case 3: 76 /* line 0 */ 77 for (o = 0; o < info->fb_stride; o += 3) { 78 info->wr1(info, o, (c >> 16) & 0xff); 79 info->wr1(info, o + 1, (c >> 8) & 0xff); 80 info->wr1(info, o + 2, c & 0xff); 81 } 82 break; 83 case 4: 84 for (o = 0; o < info->fb_stride; o += 4) 85 info->wr4(info, o, c); 86 break; 87 default: 88 /* panic? */ 89 return; 90 } 91 /* Copy line0 to all other lines. */ 92 /* XXX will copy with borders. */ 93 for (o = info->fb_stride; o < info->fb_size; o += info->fb_stride) { 94 info->copy(info, o, 0, info->fb_stride); 95 } 96} 97 98static void 99vt_fb_bitbltchr(struct vt_device *vd, const uint8_t *src, 100 vt_axis_t top, vt_axis_t left, unsigned int width, unsigned int height, 101 term_color_t fg, term_color_t bg) 102{ 103 struct fb_info *info; 104 uint32_t fgc, bgc, cc, o; 105 int c, l, bpp; 106 u_long line; 107 uint8_t b; 108 109 b = 0; 110 info = vd->vd_softc; 111 bpp = FBTYPE_GET_BYTESPP(info); 112 fgc = info->fb_cmap[fg]; 113 bgc = info->fb_cmap[bg]; 114 115 line = (info->fb_stride * top) + (left * bpp); 116 for (l = 0; l < height; l++) { 117 for (c = 0; c < width; c++) { 118 if (c % 8 == 0) 119 b = *src++; 120 else 121 b <<= 1; 122 o = line + (c * bpp); 123 cc = b & 0x80 ? fgc : bgc; 124 125 switch(bpp) { 126 case 1: 127 info->wr1(info, o, cc); 128 break; 129 case 2: 130 info->wr2(info, o, cc); 131 break; 132 case 3: 133 /* Packed mode, so unaligned. Byte access. */ 134 info->wr1(info, o, (cc >> 16) & 0xff); 135 info->wr1(info, o + 1, (cc >> 8) & 0xff); 136 info->wr1(info, o + 2, cc & 0xff); 137 break; 138 case 4: 139 info->wr4(info, o, cc); 140 break; 141 default: 142 /* panic? */ 143 break; 144 } 145 } 146 line += info->fb_stride; 147 } 148} 149 150static void 151vt_fb_postswitch(struct vt_device *vd) 152{ 153 struct fb_info *info; 154 155 info = vd->vd_softc; 156 157 if (info->enter != NULL) 158 info->enter(info->fb_priv); 159} 160 161static int 162vt_fb_init_cmap(uint32_t *cmap, int depth) 163{ 164 165 switch (depth) { 166 case 8: 167 return (vt_generate_vga_palette(cmap, COLOR_FORMAT_RGB, 168 0x7, 5, 0x7, 2, 0x3, 0)); 169 case 15: 170 return (vt_generate_vga_palette(cmap, COLOR_FORMAT_RGB, 171 0x1f, 10, 0x1f, 5, 0x1f, 0)); 172 case 16: 173 return (vt_generate_vga_palette(cmap, COLOR_FORMAT_RGB, 174 0x1f, 11, 0x3f, 5, 0x1f, 0)); 175 case 24: 176 case 32: /* Ignore alpha. */ 177 return (vt_generate_vga_palette(cmap, COLOR_FORMAT_RGB, 178 0xff, 0, 0xff, 8, 0xff, 16)); 179 default: 180 return (1); 181 } 182} 183 184static int 185vt_fb_init(struct vt_device *vd) 186{ 187 struct fb_info *info; 188 int err; 189 190 info = vd->vd_softc; 191 vd->vd_height = info->fb_height; 192 vd->vd_width = info->fb_width; 193 194 if (info->fb_cmsize <= 0) { 195 err = vt_fb_init_cmap(info->fb_cmap, FBTYPE_GET_BPP(info)); 196 if (err) 197 return (CN_DEAD); 198 info->fb_cmsize = 16; 199 } 200 201 /* Clear the screen. */ 202 vt_fb_blank(vd, TC_BLACK); 203 204 /* Wakeup screen. KMS need this. */ 205 vt_fb_postswitch(vd); 206 207 return (CN_INTERNAL); 208} 209 210int 211vt_fb_attach(struct fb_info *info) 212{ 213 214 vt_allocate(&vt_fb_driver, info); 215 return (0); 216} 217