127cf7d04SAleksandr Rybalko /*- 227cf7d04SAleksandr Rybalko * Copyright (c) 2013 The FreeBSD Foundation 327cf7d04SAleksandr Rybalko * All rights reserved. 427cf7d04SAleksandr Rybalko * 527cf7d04SAleksandr Rybalko * This software was developed by Aleksandr Rybalko under sponsorship from the 627cf7d04SAleksandr Rybalko * FreeBSD Foundation. 727cf7d04SAleksandr Rybalko * 827cf7d04SAleksandr Rybalko * Redistribution and use in source and binary forms, with or without 927cf7d04SAleksandr Rybalko * modification, are permitted provided that the following conditions 1027cf7d04SAleksandr Rybalko * are met: 1127cf7d04SAleksandr Rybalko * 1. Redistributions of source code must retain the above copyright 1227cf7d04SAleksandr Rybalko * notice, this list of conditions and the following disclaimer. 1327cf7d04SAleksandr Rybalko * 2. Redistributions in binary form must reproduce the above copyright 1427cf7d04SAleksandr Rybalko * notice, this list of conditions and the following disclaimer in the 1527cf7d04SAleksandr Rybalko * documentation and/or other materials provided with the distribution. 1627cf7d04SAleksandr Rybalko * 1727cf7d04SAleksandr Rybalko * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 1827cf7d04SAleksandr Rybalko * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1927cf7d04SAleksandr Rybalko * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2027cf7d04SAleksandr Rybalko * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 2127cf7d04SAleksandr Rybalko * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2227cf7d04SAleksandr Rybalko * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2327cf7d04SAleksandr Rybalko * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2427cf7d04SAleksandr Rybalko * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2527cf7d04SAleksandr Rybalko * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2627cf7d04SAleksandr Rybalko * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2727cf7d04SAleksandr Rybalko * SUCH DAMAGE. 2827cf7d04SAleksandr Rybalko * 2927cf7d04SAleksandr Rybalko * $FreeBSD$ 3027cf7d04SAleksandr Rybalko */ 3127cf7d04SAleksandr Rybalko 3227cf7d04SAleksandr Rybalko #include <sys/cdefs.h> 3327cf7d04SAleksandr Rybalko __FBSDID("$FreeBSD$"); 3427cf7d04SAleksandr Rybalko 3527cf7d04SAleksandr Rybalko #include <sys/param.h> 3627cf7d04SAleksandr Rybalko #include <sys/systm.h> 3727cf7d04SAleksandr Rybalko #include <sys/malloc.h> 3827cf7d04SAleksandr Rybalko #include <sys/queue.h> 3927cf7d04SAleksandr Rybalko #include <sys/fbio.h> 4027cf7d04SAleksandr Rybalko #include <dev/vt/vt.h> 4127cf7d04SAleksandr Rybalko #include <dev/vt/hw/fb/vt_fb.h> 4227cf7d04SAleksandr Rybalko #include <dev/vt/colors/vt_termcolors.h> 4327cf7d04SAleksandr Rybalko 44a985ae9bSHans Petter Selasky #include <vm/vm.h> 45a985ae9bSHans Petter Selasky #include <vm/pmap.h> 46a985ae9bSHans Petter Selasky 4727cf7d04SAleksandr Rybalko static struct vt_driver vt_fb_driver = { 484dde1640SAleksandr Rybalko .vd_name = "fb", 4927cf7d04SAleksandr Rybalko .vd_init = vt_fb_init, 5076e2f976SJean-Sébastien Pédron .vd_fini = vt_fb_fini, 5127cf7d04SAleksandr Rybalko .vd_blank = vt_fb_blank, 52c285e4a5SJean-Sébastien Pédron .vd_bitblt_text = vt_fb_bitblt_text, 53631bb572SJean-Sébastien Pédron .vd_bitblt_bmp = vt_fb_bitblt_bitmap, 549e497e7bSAleksandr Rybalko .vd_drawrect = vt_fb_drawrect, 559e497e7bSAleksandr Rybalko .vd_setpixel = vt_fb_setpixel, 5627cf7d04SAleksandr Rybalko .vd_postswitch = vt_fb_postswitch, 5727cf7d04SAleksandr Rybalko .vd_priority = VD_PRIORITY_GENERIC+10, 587a1a32c4SAleksandr Rybalko .vd_fb_ioctl = vt_fb_ioctl, 597a1a32c4SAleksandr Rybalko .vd_fb_mmap = vt_fb_mmap, 606dfa4578SAndriy Gapon .vd_suspend = vt_fb_suspend, 616dfa4578SAndriy Gapon .vd_resume = vt_fb_resume, 6227cf7d04SAleksandr Rybalko }; 6327cf7d04SAleksandr Rybalko 644dde1640SAleksandr Rybalko VT_DRIVER_DECLARE(vt_fb, vt_fb_driver); 654dde1640SAleksandr Rybalko 669ed297c8SNathan Whitehorn static void 679ed297c8SNathan Whitehorn vt_fb_mem_wr1(struct fb_info *sc, uint32_t o, uint8_t v) 689ed297c8SNathan Whitehorn { 699ed297c8SNathan Whitehorn 709ed297c8SNathan Whitehorn KASSERT((o < sc->fb_size), ("Offset %#08x out of fb size", o)); 719ed297c8SNathan Whitehorn *(uint8_t *)(sc->fb_vbase + o) = v; 729ed297c8SNathan Whitehorn } 739ed297c8SNathan Whitehorn 749ed297c8SNathan Whitehorn static void 759ed297c8SNathan Whitehorn vt_fb_mem_wr2(struct fb_info *sc, uint32_t o, uint16_t v) 769ed297c8SNathan Whitehorn { 779ed297c8SNathan Whitehorn 789ed297c8SNathan Whitehorn KASSERT((o < sc->fb_size), ("Offset %#08x out of fb size", o)); 799ed297c8SNathan Whitehorn *(uint16_t *)(sc->fb_vbase + o) = v; 809ed297c8SNathan Whitehorn } 819ed297c8SNathan Whitehorn 829ed297c8SNathan Whitehorn static void 839ed297c8SNathan Whitehorn vt_fb_mem_wr4(struct fb_info *sc, uint32_t o, uint32_t v) 849ed297c8SNathan Whitehorn { 859ed297c8SNathan Whitehorn 869ed297c8SNathan Whitehorn KASSERT((o < sc->fb_size), ("Offset %#08x out of fb size", o)); 879ed297c8SNathan Whitehorn *(uint32_t *)(sc->fb_vbase + o) = v; 889ed297c8SNathan Whitehorn } 899ed297c8SNathan Whitehorn 9060d7ea3dSNathan Whitehorn int 917a1a32c4SAleksandr Rybalko vt_fb_ioctl(struct vt_device *vd, u_long cmd, caddr_t data, struct thread *td) 927a1a32c4SAleksandr Rybalko { 937a1a32c4SAleksandr Rybalko struct fb_info *info; 9460d7ea3dSNathan Whitehorn int error = 0; 957a1a32c4SAleksandr Rybalko 967a1a32c4SAleksandr Rybalko info = vd->vd_softc; 977a1a32c4SAleksandr Rybalko 9860d7ea3dSNathan Whitehorn switch (cmd) { 9960d7ea3dSNathan Whitehorn case FBIOGTYPE: 10060d7ea3dSNathan Whitehorn bcopy(info, (struct fbtype *)data, sizeof(struct fbtype)); 10160d7ea3dSNathan Whitehorn break; 1027a1a32c4SAleksandr Rybalko 10360d7ea3dSNathan Whitehorn case FBIO_GETWINORG: /* get frame buffer window origin */ 10460d7ea3dSNathan Whitehorn *(u_int *)data = 0; 10560d7ea3dSNathan Whitehorn break; 10660d7ea3dSNathan Whitehorn 10760d7ea3dSNathan Whitehorn case FBIO_GETDISPSTART: /* get display start address */ 10860d7ea3dSNathan Whitehorn ((video_display_start_t *)data)->x = 0; 10960d7ea3dSNathan Whitehorn ((video_display_start_t *)data)->y = 0; 11060d7ea3dSNathan Whitehorn break; 11160d7ea3dSNathan Whitehorn 11260d7ea3dSNathan Whitehorn case FBIO_GETLINEWIDTH: /* get scan line width in bytes */ 11360d7ea3dSNathan Whitehorn *(u_int *)data = info->fb_stride; 11460d7ea3dSNathan Whitehorn break; 11560d7ea3dSNathan Whitehorn 11660d7ea3dSNathan Whitehorn case FBIO_BLANK: /* blank display */ 11760d7ea3dSNathan Whitehorn if (vd->vd_driver->vd_blank == NULL) 11860d7ea3dSNathan Whitehorn return (ENODEV); 11960d7ea3dSNathan Whitehorn vd->vd_driver->vd_blank(vd, TC_BLACK); 12060d7ea3dSNathan Whitehorn break; 12160d7ea3dSNathan Whitehorn 12260d7ea3dSNathan Whitehorn default: 12360d7ea3dSNathan Whitehorn error = ENOIOCTL; 12460d7ea3dSNathan Whitehorn break; 1257a1a32c4SAleksandr Rybalko } 1267a1a32c4SAleksandr Rybalko 12760d7ea3dSNathan Whitehorn return (error); 12860d7ea3dSNathan Whitehorn } 12960d7ea3dSNathan Whitehorn 13060d7ea3dSNathan Whitehorn int 1315beb07abSAleksandr Rybalko vt_fb_mmap(struct vt_device *vd, vm_ooffset_t offset, vm_paddr_t *paddr, 1325beb07abSAleksandr Rybalko int prot, vm_memattr_t *memattr) 1337a1a32c4SAleksandr Rybalko { 1347a1a32c4SAleksandr Rybalko struct fb_info *info; 1357a1a32c4SAleksandr Rybalko 1367a1a32c4SAleksandr Rybalko info = vd->vd_softc; 1377a1a32c4SAleksandr Rybalko 13860d7ea3dSNathan Whitehorn if (info->fb_flags & FB_FLAG_NOMMAP) 13960d7ea3dSNathan Whitehorn return (ENODEV); 1407a1a32c4SAleksandr Rybalko 14160d7ea3dSNathan Whitehorn if (offset >= 0 && offset < info->fb_size) { 142a985ae9bSHans Petter Selasky if (info->fb_pbase == 0) { 143a985ae9bSHans Petter Selasky *paddr = vtophys((uint8_t *)info->fb_vbase + offset); 144a985ae9bSHans Petter Selasky } else { 14560d7ea3dSNathan Whitehorn *paddr = info->fb_pbase + offset; 14660d7ea3dSNathan Whitehorn #ifdef VM_MEMATTR_WRITE_COMBINING 14760d7ea3dSNathan Whitehorn *memattr = VM_MEMATTR_WRITE_COMBINING; 14860d7ea3dSNathan Whitehorn #endif 149a985ae9bSHans Petter Selasky } 15060d7ea3dSNathan Whitehorn return (0); 15160d7ea3dSNathan Whitehorn } 15260d7ea3dSNathan Whitehorn 15360d7ea3dSNathan Whitehorn return (EINVAL); 1547a1a32c4SAleksandr Rybalko } 1557a1a32c4SAleksandr Rybalko 1561365d077SJean-Sébastien Pédron void 1579e497e7bSAleksandr Rybalko vt_fb_setpixel(struct vt_device *vd, int x, int y, term_color_t color) 1589e497e7bSAleksandr Rybalko { 1599e497e7bSAleksandr Rybalko struct fb_info *info; 1609e497e7bSAleksandr Rybalko uint32_t c; 1619e497e7bSAleksandr Rybalko u_int o; 1629e497e7bSAleksandr Rybalko 1639e497e7bSAleksandr Rybalko info = vd->vd_softc; 1649e497e7bSAleksandr Rybalko c = info->fb_cmap[color]; 1659e497e7bSAleksandr Rybalko o = info->fb_stride * y + x * FBTYPE_GET_BYTESPP(info); 1669e497e7bSAleksandr Rybalko 167f1d2752fSNathan Whitehorn if (info->fb_flags & FB_FLAG_NOWRITE) 168f1d2752fSNathan Whitehorn return; 169f1d2752fSNathan Whitehorn 1709ed297c8SNathan Whitehorn KASSERT((info->fb_vbase != 0), ("Unmapped framebuffer")); 1719ed297c8SNathan Whitehorn 1729e497e7bSAleksandr Rybalko switch (FBTYPE_GET_BYTESPP(info)) { 1739e497e7bSAleksandr Rybalko case 1: 1749ed297c8SNathan Whitehorn vt_fb_mem_wr1(info, o, c); 1759e497e7bSAleksandr Rybalko break; 1769e497e7bSAleksandr Rybalko case 2: 1779ed297c8SNathan Whitehorn vt_fb_mem_wr2(info, o, c); 1789e497e7bSAleksandr Rybalko break; 1799e497e7bSAleksandr Rybalko case 3: 1809ed297c8SNathan Whitehorn vt_fb_mem_wr1(info, o, (c >> 16) & 0xff); 1819ed297c8SNathan Whitehorn vt_fb_mem_wr1(info, o + 1, (c >> 8) & 0xff); 1829ed297c8SNathan Whitehorn vt_fb_mem_wr1(info, o + 2, c & 0xff); 1839e497e7bSAleksandr Rybalko break; 1849e497e7bSAleksandr Rybalko case 4: 1859ed297c8SNathan Whitehorn vt_fb_mem_wr4(info, o, c); 1869e497e7bSAleksandr Rybalko break; 1879e497e7bSAleksandr Rybalko default: 1889e497e7bSAleksandr Rybalko /* panic? */ 1899e497e7bSAleksandr Rybalko return; 1909e497e7bSAleksandr Rybalko } 1919e497e7bSAleksandr Rybalko 1929e497e7bSAleksandr Rybalko } 1939e497e7bSAleksandr Rybalko 1941365d077SJean-Sébastien Pédron void 1959e497e7bSAleksandr Rybalko vt_fb_drawrect(struct vt_device *vd, int x1, int y1, int x2, int y2, int fill, 1969e497e7bSAleksandr Rybalko term_color_t color) 1979e497e7bSAleksandr Rybalko { 1989e497e7bSAleksandr Rybalko int x, y; 1999e497e7bSAleksandr Rybalko 2009e497e7bSAleksandr Rybalko for (y = y1; y <= y2; y++) { 2019e497e7bSAleksandr Rybalko if (fill || (y == y1) || (y == y2)) { 2029e497e7bSAleksandr Rybalko for (x = x1; x <= x2; x++) 2039e497e7bSAleksandr Rybalko vt_fb_setpixel(vd, x, y, color); 2049e497e7bSAleksandr Rybalko } else { 2059e497e7bSAleksandr Rybalko vt_fb_setpixel(vd, x1, y, color); 2069e497e7bSAleksandr Rybalko vt_fb_setpixel(vd, x2, y, color); 2079e497e7bSAleksandr Rybalko } 2089e497e7bSAleksandr Rybalko } 2099e497e7bSAleksandr Rybalko } 2109e497e7bSAleksandr Rybalko 2119e497e7bSAleksandr Rybalko void 21227cf7d04SAleksandr Rybalko vt_fb_blank(struct vt_device *vd, term_color_t color) 21327cf7d04SAleksandr Rybalko { 21427cf7d04SAleksandr Rybalko struct fb_info *info; 21527cf7d04SAleksandr Rybalko uint32_t c; 21660d7ea3dSNathan Whitehorn u_int o, h; 21727cf7d04SAleksandr Rybalko 21827cf7d04SAleksandr Rybalko info = vd->vd_softc; 21927cf7d04SAleksandr Rybalko c = info->fb_cmap[color]; 22027cf7d04SAleksandr Rybalko 221f1d2752fSNathan Whitehorn if (info->fb_flags & FB_FLAG_NOWRITE) 222f1d2752fSNathan Whitehorn return; 223f1d2752fSNathan Whitehorn 2249ed297c8SNathan Whitehorn KASSERT((info->fb_vbase != 0), ("Unmapped framebuffer")); 2259ed297c8SNathan Whitehorn 22627cf7d04SAleksandr Rybalko switch (FBTYPE_GET_BYTESPP(info)) { 22727cf7d04SAleksandr Rybalko case 1: 22835e6436eSNathan Whitehorn for (h = 0; h < info->fb_height; h++) 22927cf7d04SAleksandr Rybalko for (o = 0; o < info->fb_stride; o++) 2309ed297c8SNathan Whitehorn vt_fb_mem_wr1(info, h*info->fb_stride + o, c); 23127cf7d04SAleksandr Rybalko break; 23227cf7d04SAleksandr Rybalko case 2: 23335e6436eSNathan Whitehorn for (h = 0; h < info->fb_height; h++) 23427cf7d04SAleksandr Rybalko for (o = 0; o < info->fb_stride; o += 2) 2359ed297c8SNathan Whitehorn vt_fb_mem_wr2(info, h*info->fb_stride + o, c); 23627cf7d04SAleksandr Rybalko break; 23727cf7d04SAleksandr Rybalko case 3: 23835e6436eSNathan Whitehorn for (h = 0; h < info->fb_height; h++) 23927cf7d04SAleksandr Rybalko for (o = 0; o < info->fb_stride; o += 3) { 2409ed297c8SNathan Whitehorn vt_fb_mem_wr1(info, h*info->fb_stride + o, 24160d7ea3dSNathan Whitehorn (c >> 16) & 0xff); 2429ed297c8SNathan Whitehorn vt_fb_mem_wr1(info, h*info->fb_stride + o + 1, 24360d7ea3dSNathan Whitehorn (c >> 8) & 0xff); 2449ed297c8SNathan Whitehorn vt_fb_mem_wr1(info, h*info->fb_stride + o + 2, 24560d7ea3dSNathan Whitehorn c & 0xff); 24627cf7d04SAleksandr Rybalko } 24727cf7d04SAleksandr Rybalko break; 24827cf7d04SAleksandr Rybalko case 4: 24935e6436eSNathan Whitehorn for (h = 0; h < info->fb_height; h++) 25027cf7d04SAleksandr Rybalko for (o = 0; o < info->fb_stride; o += 4) 2519ed297c8SNathan Whitehorn vt_fb_mem_wr4(info, h*info->fb_stride + o, c); 25227cf7d04SAleksandr Rybalko break; 25327cf7d04SAleksandr Rybalko default: 25427cf7d04SAleksandr Rybalko /* panic? */ 25527cf7d04SAleksandr Rybalko return; 25627cf7d04SAleksandr Rybalko } 25727cf7d04SAleksandr Rybalko } 25827cf7d04SAleksandr Rybalko 259631bb572SJean-Sébastien Pédron void 260c285e4a5SJean-Sébastien Pédron vt_fb_bitblt_bitmap(struct vt_device *vd, const struct vt_window *vw, 261c285e4a5SJean-Sébastien Pédron const uint8_t *pattern, const uint8_t *mask, 262c285e4a5SJean-Sébastien Pédron unsigned int width, unsigned int height, 263c285e4a5SJean-Sébastien Pédron unsigned int x, unsigned int y, term_color_t fg, term_color_t bg) 26427cf7d04SAleksandr Rybalko { 26527cf7d04SAleksandr Rybalko struct fb_info *info; 26627cf7d04SAleksandr Rybalko uint32_t fgc, bgc, cc, o; 267*2c48063bSEd Maste int bpp, bpl, xi, yi; 268*2c48063bSEd Maste int bit, byte; 26927cf7d04SAleksandr Rybalko 27027cf7d04SAleksandr Rybalko info = vd->vd_softc; 27127cf7d04SAleksandr Rybalko bpp = FBTYPE_GET_BYTESPP(info); 27227cf7d04SAleksandr Rybalko fgc = info->fb_cmap[fg]; 27327cf7d04SAleksandr Rybalko bgc = info->fb_cmap[bg]; 274*2c48063bSEd Maste bpl = (width + 7) / 8; /* Bytes per source line. */ 27527cf7d04SAleksandr Rybalko 276f1d2752fSNathan Whitehorn if (info->fb_flags & FB_FLAG_NOWRITE) 277f1d2752fSNathan Whitehorn return; 278f1d2752fSNathan Whitehorn 2799ed297c8SNathan Whitehorn KASSERT((info->fb_vbase != 0), ("Unmapped framebuffer")); 2809ed297c8SNathan Whitehorn 281*2c48063bSEd Maste /* Bound by right and bottom edges. */ 282*2c48063bSEd Maste if (y + height > vw->vw_draw_area.tr_end.tp_row) { 283*2c48063bSEd Maste if (y >= vw->vw_draw_area.tr_end.tp_row) 284*2c48063bSEd Maste return; 285*2c48063bSEd Maste height = vw->vw_draw_area.tr_end.tp_row - y; 28627cf7d04SAleksandr Rybalko } 287*2c48063bSEd Maste if (x + width > vw->vw_draw_area.tr_end.tp_col) { 288*2c48063bSEd Maste if (x >= vw->vw_draw_area.tr_end.tp_col) 289*2c48063bSEd Maste return; 290*2c48063bSEd Maste width = vw->vw_draw_area.tr_end.tp_col - x; 291*2c48063bSEd Maste } 292*2c48063bSEd Maste for (yi = 0; yi < height; yi++) { 293*2c48063bSEd Maste for (xi = 0; xi < width; xi++) { 294*2c48063bSEd Maste byte = yi * bpl + xi / 8; 295*2c48063bSEd Maste bit = 0x80 >> (xi % 8); 296*2c48063bSEd Maste /* Skip pixel write, if mask bit not set. */ 297*2c48063bSEd Maste if (mask != NULL && (mask[byte] & bit) == 0) 298*2c48063bSEd Maste continue; 299*2c48063bSEd Maste o = (y + yi) * info->fb_stride + (x + xi) * bpp; 300*2c48063bSEd Maste cc = pattern[byte] & bit ? fgc : bgc; 30127cf7d04SAleksandr Rybalko 30227cf7d04SAleksandr Rybalko switch(bpp) { 30327cf7d04SAleksandr Rybalko case 1: 3049ed297c8SNathan Whitehorn vt_fb_mem_wr1(info, o, cc); 30527cf7d04SAleksandr Rybalko break; 30627cf7d04SAleksandr Rybalko case 2: 3079ed297c8SNathan Whitehorn vt_fb_mem_wr2(info, o, cc); 30827cf7d04SAleksandr Rybalko break; 30927cf7d04SAleksandr Rybalko case 3: 31027cf7d04SAleksandr Rybalko /* Packed mode, so unaligned. Byte access. */ 3119ed297c8SNathan Whitehorn vt_fb_mem_wr1(info, o, (cc >> 16) & 0xff); 3129ed297c8SNathan Whitehorn vt_fb_mem_wr1(info, o + 1, (cc >> 8) & 0xff); 3139ed297c8SNathan Whitehorn vt_fb_mem_wr1(info, o + 2, cc & 0xff); 31427cf7d04SAleksandr Rybalko break; 31527cf7d04SAleksandr Rybalko case 4: 3169ed297c8SNathan Whitehorn vt_fb_mem_wr4(info, o, cc); 31727cf7d04SAleksandr Rybalko break; 31827cf7d04SAleksandr Rybalko default: 31927cf7d04SAleksandr Rybalko /* panic? */ 32027cf7d04SAleksandr Rybalko break; 32127cf7d04SAleksandr Rybalko } 32227cf7d04SAleksandr Rybalko } 32327cf7d04SAleksandr Rybalko } 32427cf7d04SAleksandr Rybalko } 32527cf7d04SAleksandr Rybalko 32627cf7d04SAleksandr Rybalko void 327c285e4a5SJean-Sébastien Pédron vt_fb_bitblt_text(struct vt_device *vd, const struct vt_window *vw, 328c285e4a5SJean-Sébastien Pédron const term_rect_t *area) 329c285e4a5SJean-Sébastien Pédron { 330c285e4a5SJean-Sébastien Pédron unsigned int col, row, x, y; 331c285e4a5SJean-Sébastien Pédron struct vt_font *vf; 332c285e4a5SJean-Sébastien Pédron term_char_t c; 333c285e4a5SJean-Sébastien Pédron term_color_t fg, bg; 334c285e4a5SJean-Sébastien Pédron const uint8_t *pattern; 335c285e4a5SJean-Sébastien Pédron 336c285e4a5SJean-Sébastien Pédron vf = vw->vw_font; 337c285e4a5SJean-Sébastien Pédron 338c285e4a5SJean-Sébastien Pédron for (row = area->tr_begin.tp_row; row < area->tr_end.tp_row; ++row) { 339c285e4a5SJean-Sébastien Pédron for (col = area->tr_begin.tp_col; col < area->tr_end.tp_col; 340c285e4a5SJean-Sébastien Pédron ++col) { 34183fbb296SJean-Sébastien Pédron x = col * vf->vf_width + 34283fbb296SJean-Sébastien Pédron vw->vw_draw_area.tr_begin.tp_col; 34383fbb296SJean-Sébastien Pédron y = row * vf->vf_height + 34483fbb296SJean-Sébastien Pédron vw->vw_draw_area.tr_begin.tp_row; 345c285e4a5SJean-Sébastien Pédron 346c285e4a5SJean-Sébastien Pédron c = VTBUF_GET_FIELD(&vw->vw_buf, row, col); 347c285e4a5SJean-Sébastien Pédron pattern = vtfont_lookup(vf, c); 348c285e4a5SJean-Sébastien Pédron vt_determine_colors(c, 349c285e4a5SJean-Sébastien Pédron VTBUF_ISCURSOR(&vw->vw_buf, row, col), &fg, &bg); 350c285e4a5SJean-Sébastien Pédron 351c285e4a5SJean-Sébastien Pédron vt_fb_bitblt_bitmap(vd, vw, 352c285e4a5SJean-Sébastien Pédron pattern, NULL, vf->vf_width, vf->vf_height, 353c285e4a5SJean-Sébastien Pédron x, y, fg, bg); 354c285e4a5SJean-Sébastien Pédron } 355c285e4a5SJean-Sébastien Pédron } 356c285e4a5SJean-Sébastien Pédron 357c285e4a5SJean-Sébastien Pédron #ifndef SC_NO_CUTPASTE 358c285e4a5SJean-Sébastien Pédron if (!vd->vd_mshown) 359c285e4a5SJean-Sébastien Pédron return; 360c285e4a5SJean-Sébastien Pédron 361c285e4a5SJean-Sébastien Pédron term_rect_t drawn_area; 362c285e4a5SJean-Sébastien Pédron 36384d623c6SJean-Sébastien Pédron drawn_area.tr_begin.tp_col = area->tr_begin.tp_col * vf->vf_width; 36484d623c6SJean-Sébastien Pédron drawn_area.tr_begin.tp_row = area->tr_begin.tp_row * vf->vf_height; 36584d623c6SJean-Sébastien Pédron drawn_area.tr_end.tp_col = area->tr_end.tp_col * vf->vf_width; 36684d623c6SJean-Sébastien Pédron drawn_area.tr_end.tp_row = area->tr_end.tp_row * vf->vf_height; 367c285e4a5SJean-Sébastien Pédron 368c285e4a5SJean-Sébastien Pédron if (vt_is_cursor_in_area(vd, &drawn_area)) { 369c285e4a5SJean-Sébastien Pédron vt_fb_bitblt_bitmap(vd, vw, 370c285e4a5SJean-Sébastien Pédron vd->vd_mcursor->map, vd->vd_mcursor->mask, 371c285e4a5SJean-Sébastien Pédron vd->vd_mcursor->width, vd->vd_mcursor->height, 37284d623c6SJean-Sébastien Pédron vd->vd_mx_drawn + vw->vw_draw_area.tr_begin.tp_col, 37384d623c6SJean-Sébastien Pédron vd->vd_my_drawn + vw->vw_draw_area.tr_begin.tp_row, 374c285e4a5SJean-Sébastien Pédron vd->vd_mcursor_fg, vd->vd_mcursor_bg); 375c285e4a5SJean-Sébastien Pédron } 376c285e4a5SJean-Sébastien Pédron #endif 377c285e4a5SJean-Sébastien Pédron } 378c285e4a5SJean-Sébastien Pédron 379c285e4a5SJean-Sébastien Pédron void 38027cf7d04SAleksandr Rybalko vt_fb_postswitch(struct vt_device *vd) 38127cf7d04SAleksandr Rybalko { 38227cf7d04SAleksandr Rybalko struct fb_info *info; 38327cf7d04SAleksandr Rybalko 38427cf7d04SAleksandr Rybalko info = vd->vd_softc; 38527cf7d04SAleksandr Rybalko 38627cf7d04SAleksandr Rybalko if (info->enter != NULL) 38727cf7d04SAleksandr Rybalko info->enter(info->fb_priv); 38827cf7d04SAleksandr Rybalko } 38927cf7d04SAleksandr Rybalko 39027cf7d04SAleksandr Rybalko static int 39127cf7d04SAleksandr Rybalko vt_fb_init_cmap(uint32_t *cmap, int depth) 39227cf7d04SAleksandr Rybalko { 39327cf7d04SAleksandr Rybalko 39427cf7d04SAleksandr Rybalko switch (depth) { 39527cf7d04SAleksandr Rybalko case 8: 39619e2ce2dSJean-Sébastien Pédron return (vt_generate_cons_palette(cmap, COLOR_FORMAT_RGB, 39727cf7d04SAleksandr Rybalko 0x7, 5, 0x7, 2, 0x3, 0)); 39827cf7d04SAleksandr Rybalko case 15: 39919e2ce2dSJean-Sébastien Pédron return (vt_generate_cons_palette(cmap, COLOR_FORMAT_RGB, 40027cf7d04SAleksandr Rybalko 0x1f, 10, 0x1f, 5, 0x1f, 0)); 40127cf7d04SAleksandr Rybalko case 16: 40219e2ce2dSJean-Sébastien Pédron return (vt_generate_cons_palette(cmap, COLOR_FORMAT_RGB, 40327cf7d04SAleksandr Rybalko 0x1f, 11, 0x3f, 5, 0x1f, 0)); 40427cf7d04SAleksandr Rybalko case 24: 40527cf7d04SAleksandr Rybalko case 32: /* Ignore alpha. */ 40619e2ce2dSJean-Sébastien Pédron return (vt_generate_cons_palette(cmap, COLOR_FORMAT_RGB, 40719e2ce2dSJean-Sébastien Pédron 0xff, 16, 0xff, 8, 0xff, 0)); 40827cf7d04SAleksandr Rybalko default: 40927cf7d04SAleksandr Rybalko return (1); 41027cf7d04SAleksandr Rybalko } 41127cf7d04SAleksandr Rybalko } 41227cf7d04SAleksandr Rybalko 41327cf7d04SAleksandr Rybalko int 41427cf7d04SAleksandr Rybalko vt_fb_init(struct vt_device *vd) 41527cf7d04SAleksandr Rybalko { 41627cf7d04SAleksandr Rybalko struct fb_info *info; 41727cf7d04SAleksandr Rybalko int err; 41827cf7d04SAleksandr Rybalko 41927cf7d04SAleksandr Rybalko info = vd->vd_softc; 42027cf7d04SAleksandr Rybalko vd->vd_height = info->fb_height; 42127cf7d04SAleksandr Rybalko vd->vd_width = info->fb_width; 42276e2f976SJean-Sébastien Pédron vd->vd_video_dev = info->fb_video_dev; 42327cf7d04SAleksandr Rybalko 4249ed297c8SNathan Whitehorn if (info->fb_size == 0) 4259ed297c8SNathan Whitehorn return (CN_DEAD); 4269ed297c8SNathan Whitehorn 427a985ae9bSHans Petter Selasky if (info->fb_pbase == 0 && info->fb_vbase == 0) 4289ed297c8SNathan Whitehorn info->fb_flags |= FB_FLAG_NOMMAP; 4299ed297c8SNathan Whitehorn 43027cf7d04SAleksandr Rybalko if (info->fb_cmsize <= 0) { 43127cf7d04SAleksandr Rybalko err = vt_fb_init_cmap(info->fb_cmap, FBTYPE_GET_BPP(info)); 43227cf7d04SAleksandr Rybalko if (err) 43327cf7d04SAleksandr Rybalko return (CN_DEAD); 43427cf7d04SAleksandr Rybalko info->fb_cmsize = 16; 43527cf7d04SAleksandr Rybalko } 43627cf7d04SAleksandr Rybalko 43727cf7d04SAleksandr Rybalko /* Clear the screen. */ 4382661dd32SNathan Whitehorn vd->vd_driver->vd_blank(vd, TC_BLACK); 43927cf7d04SAleksandr Rybalko 44027cf7d04SAleksandr Rybalko /* Wakeup screen. KMS need this. */ 44127cf7d04SAleksandr Rybalko vt_fb_postswitch(vd); 44227cf7d04SAleksandr Rybalko 44327cf7d04SAleksandr Rybalko return (CN_INTERNAL); 44427cf7d04SAleksandr Rybalko } 44527cf7d04SAleksandr Rybalko 44676e2f976SJean-Sébastien Pédron void 44776e2f976SJean-Sébastien Pédron vt_fb_fini(struct vt_device *vd, void *softc) 44876e2f976SJean-Sébastien Pédron { 44976e2f976SJean-Sébastien Pédron 45076e2f976SJean-Sébastien Pédron vd->vd_video_dev = NULL; 45176e2f976SJean-Sébastien Pédron } 45276e2f976SJean-Sébastien Pédron 45327cf7d04SAleksandr Rybalko int 45427cf7d04SAleksandr Rybalko vt_fb_attach(struct fb_info *info) 45527cf7d04SAleksandr Rybalko { 45627cf7d04SAleksandr Rybalko 45727cf7d04SAleksandr Rybalko vt_allocate(&vt_fb_driver, info); 45827cf7d04SAleksandr Rybalko 45927cf7d04SAleksandr Rybalko return (0); 46027cf7d04SAleksandr Rybalko } 46127cf7d04SAleksandr Rybalko 46276e2f976SJean-Sébastien Pédron int 46376e2f976SJean-Sébastien Pédron vt_fb_detach(struct fb_info *info) 46476e2f976SJean-Sébastien Pédron { 46576e2f976SJean-Sébastien Pédron 46676e2f976SJean-Sébastien Pédron vt_deallocate(&vt_fb_driver, info); 46776e2f976SJean-Sébastien Pédron 46876e2f976SJean-Sébastien Pédron return (0); 46976e2f976SJean-Sébastien Pédron } 47076e2f976SJean-Sébastien Pédron 47127cf7d04SAleksandr Rybalko void 4726dfa4578SAndriy Gapon vt_fb_suspend(struct vt_device *vd) 47327cf7d04SAleksandr Rybalko { 47427cf7d04SAleksandr Rybalko 4756dfa4578SAndriy Gapon vt_suspend(vd); 47627cf7d04SAleksandr Rybalko } 47727cf7d04SAleksandr Rybalko 47827cf7d04SAleksandr Rybalko void 4796dfa4578SAndriy Gapon vt_fb_resume(struct vt_device *vd) 48027cf7d04SAleksandr Rybalko { 48127cf7d04SAleksandr Rybalko 4826dfa4578SAndriy Gapon vt_resume(vd); 48327cf7d04SAleksandr Rybalko } 484