vt_fb.c revision 257725
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 257725 2013-11-05 23:01:57Z ray $ 30 */ 31 32#include <sys/cdefs.h> 33__FBSDID("$FreeBSD: user/ed/newcons/sys/dev/vt/hw/fb/vt_fb.c 257725 2013-11-05 23:01:57Z 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 struct vt_driver vt_fb_driver = { 45 .vd_init = vt_fb_init, 46 .vd_blank = vt_fb_blank, 47 .vd_bitbltchr = vt_fb_bitbltchr, 48 .vd_postswitch = vt_fb_postswitch, 49 .vd_priority = VD_PRIORITY_GENERIC+10, 50}; 51 52void 53vt_fb_blank(struct vt_device *vd, term_color_t color) 54{ 55 struct fb_info *info; 56 uint32_t c; 57 u_int o; 58 59 info = vd->vd_softc; 60 c = info->fb_cmap[color]; 61 62 switch (FBTYPE_GET_BYTESPP(info)) { 63 case 1: 64 for (o = 0; o < info->fb_stride; o++) 65 info->wr1(info, o, c); 66 break; 67 case 2: 68 for (o = 0; o < info->fb_stride; o += 2) 69 info->wr2(info, o, c); 70 break; 71 case 3: 72 /* line 0 */ 73 for (o = 0; o < info->fb_stride; o += 3) { 74 info->wr1(info, o, (c >> 16) & 0xff); 75 info->wr1(info, o + 1, (c >> 8) & 0xff); 76 info->wr1(info, o + 2, c & 0xff); 77 } 78 break; 79 case 4: 80 for (o = 0; o < info->fb_stride; o += 4) 81 info->wr4(info, o, c); 82 break; 83 default: 84 /* panic? */ 85 return; 86 } 87 /* Copy line0 to all other lines. */ 88 /* XXX will copy with borders. */ 89 for (o = info->fb_stride; o < info->fb_size; o += info->fb_stride) { 90 info->copy(info, o, 0, info->fb_stride); 91 } 92} 93 94void 95vt_fb_bitbltchr(struct vt_device *vd, const uint8_t *src, 96 vt_axis_t top, vt_axis_t left, unsigned int width, unsigned int height, 97 term_color_t fg, term_color_t bg) 98{ 99 struct fb_info *info; 100 uint32_t fgc, bgc, cc, o; 101 int c, l, bpp; 102 u_long line; 103 uint8_t b; 104 105 b = 0; 106 info = vd->vd_softc; 107 bpp = FBTYPE_GET_BYTESPP(info); 108 fgc = info->fb_cmap[fg]; 109 bgc = info->fb_cmap[bg]; 110 111 line = (info->fb_stride * top) + (left * bpp); 112 for (l = 0; l < height; l++) { 113 for (c = 0; c < width; c++) { 114 if (c % 8 == 0) 115 b = *src++; 116 else 117 b <<= 1; 118 o = line + (c * bpp); 119 cc = b & 0x80 ? fgc : bgc; 120 121 switch(bpp) { 122 case 1: 123 info->wr1(info, o, cc); 124 break; 125 case 2: 126 info->wr2(info, o, cc); 127 break; 128 case 3: 129 /* Packed mode, so unaligned. Byte access. */ 130 info->wr1(info, o, (cc >> 16) & 0xff); 131 info->wr1(info, o + 1, (cc >> 8) & 0xff); 132 info->wr1(info, o + 2, cc & 0xff); 133 break; 134 case 4: 135 info->wr4(info, o, cc); 136 break; 137 default: 138 /* panic? */ 139 break; 140 } 141 } 142 line += info->fb_stride; 143 } 144} 145 146void 147vt_fb_postswitch(struct vt_device *vd) 148{ 149 struct fb_info *info; 150 151 info = vd->vd_softc; 152 153 if (info->enter != NULL) 154 info->enter(info->fb_priv); 155} 156 157static int 158vt_fb_init_cmap(uint32_t *cmap, int depth) 159{ 160 161 switch (depth) { 162 case 8: 163 return (vt_generate_vga_palette(cmap, COLOR_FORMAT_RGB, 164 0x7, 5, 0x7, 2, 0x3, 0)); 165 case 15: 166 return (vt_generate_vga_palette(cmap, COLOR_FORMAT_RGB, 167 0x1f, 10, 0x1f, 5, 0x1f, 0)); 168 case 16: 169 return (vt_generate_vga_palette(cmap, COLOR_FORMAT_RGB, 170 0x1f, 11, 0x3f, 5, 0x1f, 0)); 171 case 24: 172 case 32: /* Ignore alpha. */ 173 return (vt_generate_vga_palette(cmap, COLOR_FORMAT_RGB, 174 0xff, 0, 0xff, 8, 0xff, 16)); 175 default: 176 return (1); 177 } 178} 179 180int 181vt_fb_init(struct vt_device *vd) 182{ 183 struct fb_info *info; 184 int err; 185 186 info = vd->vd_softc; 187 vd->vd_height = info->fb_height; 188 vd->vd_width = info->fb_width; 189 190 if (info->fb_cmsize <= 0) { 191 err = vt_fb_init_cmap(info->fb_cmap, FBTYPE_GET_BPP(info)); 192 if (err) 193 return (CN_DEAD); 194 info->fb_cmsize = 16; 195 } 196 197 /* Clear the screen. */ 198 vt_fb_blank(vd, TC_BLACK); 199 200 /* Wakeup screen. KMS need this. */ 201 vt_fb_postswitch(vd); 202 203 return (CN_INTERNAL); 204} 205 206int 207vt_fb_attach(struct fb_info *info) 208{ 209 210 vt_allocate(&vt_fb_driver, info); 211 212 return (0); 213} 214