Sun Apr 12 20:00:42 2015 UTC ()
flushing the framebuffer from interrupt has several problems:
- As pointed out by Jared McNeill, this doesn't work for cold
  or ddb. Some specific handing for these cases would be needed,
  but there's no easy way to know if we're in ddb or not.
- periodic bus_dmamap_sync() of the whole framebuffer isn't cheap (about
  3% CPU constant on the beaglebone back).

instead map the framebuffer BUS_DMA_PREFETCHABLE (undocumented flag, but
is MI and properly handled by arm). This allows write-combining,
which, in addition with a shadow framebuffer for rasops(9) gives
a good performance boost too (difference with the cached+sync from intr
isn't noticeable on a boot sequence).
For X11, the framebuffer was already mapped BUS_DMA_PREFETCHABLE.
A few tests shows that mapping it fully cached doesn't make a noticeable
difference either (with or without xorg's shadow framebuffer).


(bouyer)
diff -r1.4 -r1.5 src/sys/arch/arm/omap/tifb.c

cvs diff -r1.4 -r1.5 src/sys/arch/arm/omap/Attic/tifb.c (expand / switch to unified diff)

--- src/sys/arch/arm/omap/Attic/tifb.c 2015/04/11 13:44:14 1.4
+++ src/sys/arch/arm/omap/Attic/tifb.c 2015/04/12 20:00:42 1.5
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: tifb.c,v 1.4 2015/04/11 13:44:14 bouyer Exp $ */ 1/* $NetBSD: tifb.c,v 1.5 2015/04/12 20:00:42 bouyer Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 2010 Michael Lorenz 4 * Copyright (c) 2010 Michael Lorenz
5 * All rights reserved. 5 * All rights reserved.
6 * 6 *
7 * Redistribution and use in source and binary forms, with or without 7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions 8 * modification, are permitted provided that the following conditions
9 * are met: 9 * are met:
10 * 1. Redistributions of source code must retain the above copyright 10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer. 11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright 12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the 13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution. 14 * documentation and/or other materials provided with the distribution.
@@ -47,37 +47,38 @@ @@ -47,37 +47,38 @@
47 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 47 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
48 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 48 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
49 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 49 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
50 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 50 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
51 * SUCH DAMAGE. 51 * SUCH DAMAGE.
52 */ 52 */
53 53
54/* 54/*
55 * A framebuffer driver for TI 35xx built-in video controller 55 * A framebuffer driver for TI 35xx built-in video controller
56 * tested on beaglebone 56 * tested on beaglebone
57 */ 57 */
58 58
59#include <sys/cdefs.h> 59#include <sys/cdefs.h>
60__KERNEL_RCSID(0, "$NetBSD: tifb.c,v 1.4 2015/04/11 13:44:14 bouyer Exp $"); 60__KERNEL_RCSID(0, "$NetBSD: tifb.c,v 1.5 2015/04/12 20:00:42 bouyer Exp $");
61 61
62#include "opt_omap.h" 62#include "opt_omap.h"
63 63
64#include <sys/param.h> 64#include <sys/param.h>
65#include <sys/systm.h> 65#include <sys/systm.h>
66#include <sys/kernel.h> 66#include <sys/kernel.h>
67#include <sys/device.h> 67#include <sys/device.h>
68#include <sys/malloc.h> 68#include <sys/malloc.h>
69#include <sys/lwp.h> 69#include <sys/lwp.h>
70#include <sys/kauth.h> 70#include <sys/kauth.h>
 71#include <sys/kmem.h>
71 72
72#include <uvm/uvm_extern.h> 73#include <uvm/uvm_extern.h>
73 74
74#include <dev/videomode/videomode.h> 75#include <dev/videomode/videomode.h>
75 76
76#include <sys/bus.h> 77#include <sys/bus.h>
77#include <arm/omap/tifbreg.h> 78#include <arm/omap/tifbreg.h>
78#include <arm/omap/omap_var.h> 79#include <arm/omap/omap_var.h>
79#include <arm/omap/omap2_obiovar.h> 80#include <arm/omap/omap2_obiovar.h>
80#include <arm/omap/omap2_obioreg.h> 81#include <arm/omap/omap2_obioreg.h>
81#ifdef TI_AM335X 82#ifdef TI_AM335X
82# include <arm/omap/am335x_prcm.h> 83# include <arm/omap/am335x_prcm.h>
83# include <arm/omap/omap2_prcm.h> 84# include <arm/omap/omap2_prcm.h>
@@ -145,26 +146,27 @@ struct tifb_softc { @@ -145,26 +146,27 @@ struct tifb_softc {
145 146
146 void *sc_ih; 147 void *sc_ih;
147 bus_space_tag_t sc_iot; 148 bus_space_tag_t sc_iot;
148 bus_dma_tag_t sc_dmat; 149 bus_dma_tag_t sc_dmat;
149 bus_space_handle_t sc_regh; 150 bus_space_handle_t sc_regh;
150 bus_dmamap_t sc_dmamap; 151 bus_dmamap_t sc_dmamap;
151 bus_dma_segment_t sc_dmamem[1]; 152 bus_dma_segment_t sc_dmamem[1];
152 size_t sc_vramsize; 153 size_t sc_vramsize;
153 size_t sc_palettesize; 154 size_t sc_palettesize;
154 155
155 int sc_stride; 156 int sc_stride;
156 int sc_locked; 157 int sc_locked;
157 void *sc_fbaddr, *sc_vramaddr; 158 void *sc_fbaddr, *sc_vramaddr;
 159 void *sc_shadowfb;
158 160
159 bus_addr_t sc_fbhwaddr; 161 bus_addr_t sc_fbhwaddr;
160 uint16_t *sc_palette; 162 uint16_t *sc_palette;
161 uint32_t sc_dispc_config; 163 uint32_t sc_dispc_config;
162 struct vcons_screen sc_console_screen; 164 struct vcons_screen sc_console_screen;
163 struct wsscreen_descr sc_defaultscreen_descr; 165 struct wsscreen_descr sc_defaultscreen_descr;
164 const struct wsscreen_descr *sc_screens[1]; 166 const struct wsscreen_descr *sc_screens[1];
165 struct wsscreen_list sc_screenlist; 167 struct wsscreen_list sc_screenlist;
166 struct vcons_data vd; 168 struct vcons_data vd;
167 int sc_mode; 169 int sc_mode;
168 uint8_t sc_cmap_red[256], sc_cmap_green[256], sc_cmap_blue[256]; 170 uint8_t sc_cmap_red[256], sc_cmap_green[256], sc_cmap_blue[256];
169 void (*sc_putchar)(void *, int, int, u_int, long); 171 void (*sc_putchar)(void *, int, int, u_int, long);
170 172
@@ -385,35 +387,41 @@ tifb_attach(device_t parent, device_t se @@ -385,35 +387,41 @@ tifb_attach(device_t parent, device_t se
385 /* setup video DMA */ 387 /* setup video DMA */
386 switch(sc->sc_panel->bpp) { 388 switch(sc->sc_panel->bpp) {
387 case 8: 389 case 8:
388 sc->sc_palettesize = 512; 390 sc->sc_palettesize = 512;
389 break; 391 break;
390 default: 392 default:
391 sc->sc_palettesize = 32; 393 sc->sc_palettesize = 32;
392 break; 394 break;
393 } 395 }
394 396
395 sc->sc_vramsize = sc->sc_palettesize + 397 sc->sc_vramsize = sc->sc_palettesize +
396 sc->sc_stride * sc->sc_panel->panel_height; 398 sc->sc_stride * sc->sc_panel->panel_height;
397 399
 400 sc->sc_shadowfb = kmem_alloc(sc->sc_vramsize - sc->sc_palettesize,
 401 KM_NOSLEEP);
 402 if (sc->sc_shadowfb == NULL) {
 403 aprint_error_dev(sc->sc_dev,
 404 "warning: failed to allocate shadow framebuffer\n");
 405 }
398 if (bus_dmamem_alloc(sc->sc_dmat, sc->sc_vramsize, 0, 0, 406 if (bus_dmamem_alloc(sc->sc_dmat, sc->sc_vramsize, 0, 0,
399 sc->sc_dmamem, 1, &segs, BUS_DMA_NOWAIT) != 0) { 407 sc->sc_dmamem, 1, &segs, BUS_DMA_NOWAIT) != 0) {
400 aprint_error_dev(sc->sc_dev, 408 aprint_error_dev(sc->sc_dev,
401 "failed to allocate video memory\n"); 409 "failed to allocate video memory\n");
402 return; 410 return;
403 } 411 }
404 412
405 if (bus_dmamem_map(sc->sc_dmat, sc->sc_dmamem, 1, sc->sc_vramsize, 413 if (bus_dmamem_map(sc->sc_dmat, sc->sc_dmamem, 1, sc->sc_vramsize,
406 &sc->sc_vramaddr, BUS_DMA_NOWAIT) != 0) { 414 &sc->sc_vramaddr, BUS_DMA_NOWAIT | BUS_DMA_PREFETCHABLE) != 0) {
407 aprint_error_dev(sc->sc_dev, "failed to map video RAM\n"); 415 aprint_error_dev(sc->sc_dev, "failed to map video RAM\n");
408 return; 416 return;
409 } 417 }
410 sc->sc_fbaddr = (uint8_t *)sc->sc_vramaddr + sc->sc_palettesize; 418 sc->sc_fbaddr = (uint8_t *)sc->sc_vramaddr + sc->sc_palettesize;
411 sc->sc_palette = sc->sc_vramaddr; 419 sc->sc_palette = sc->sc_vramaddr;
412 420
413 if (bus_dmamap_create(sc->sc_dmat, sc->sc_vramsize, 1, sc->sc_vramsize, 421 if (bus_dmamap_create(sc->sc_dmat, sc->sc_vramsize, 1, sc->sc_vramsize,
414 0, BUS_DMA_NOWAIT, &sc->sc_dmamap) != 0) { 422 0, BUS_DMA_NOWAIT, &sc->sc_dmamap) != 0) {
415 aprint_error_dev(sc->sc_dev, "failed to create DMA map\n"); 423 aprint_error_dev(sc->sc_dev, "failed to create DMA map\n");
416 return; 424 return;
417 } 425 }
418 426
419 if (bus_dmamap_load(sc->sc_dmat, sc->sc_dmamap, sc->sc_vramaddr, 427 if (bus_dmamap_load(sc->sc_dmat, sc->sc_dmamap, sc->sc_vramaddr,
@@ -533,27 +541,27 @@ tifb_attach(device_t parent, device_t se @@ -533,27 +541,27 @@ tifb_attach(device_t parent, device_t se
533 timing2 |= RASTER_TIMING_2_IPC; 541 timing2 |= RASTER_TIMING_2_IPC;
534 542
535 /* AC bias */ 543 /* AC bias */
536 timing2 |= (sc->sc_panel->ac_bias << RASTER_TIMING_2_ACB_SHIFT); 544 timing2 |= (sc->sc_panel->ac_bias << RASTER_TIMING_2_ACB_SHIFT);
537 timing2 |= (sc->sc_panel->ac_bias_intrpt << RASTER_TIMING_2_ACBI_SHIFT); 545 timing2 |= (sc->sc_panel->ac_bias_intrpt << RASTER_TIMING_2_ACBI_SHIFT);
538 546
539 TIFB_WRITE(sc, LCD_RASTER_TIMING_0, timing0); 547 TIFB_WRITE(sc, LCD_RASTER_TIMING_0, timing0);
540 TIFB_WRITE(sc, LCD_RASTER_TIMING_1, timing1); 548 TIFB_WRITE(sc, LCD_RASTER_TIMING_1, timing1);
541 TIFB_WRITE(sc, LCD_RASTER_TIMING_2, timing2); 549 TIFB_WRITE(sc, LCD_RASTER_TIMING_2, timing2);
542 aprint_debug_dev(self, ": timings 0x%x 0x%x 0x%x\n", 550 aprint_debug_dev(self, ": timings 0x%x 0x%x 0x%x\n",
543 timing0, timing1, timing2); 551 timing0, timing1, timing2);
544 552
545 /* DMA settings */ 553 /* DMA settings */
546 reg = LCDDMA_CTRL_FB0_FB1;  554 reg = 0;
547 /* Find power of 2 for current burst size */ 555 /* Find power of 2 for current burst size */
548 switch (sc->sc_panel->dma_burst_sz) {  556 switch (sc->sc_panel->dma_burst_sz) {
549 case 1: 557 case 1:
550 burst_log = 0; 558 burst_log = 0;
551 break; 559 break;
552 case 2: 560 case 2:
553 burst_log = 1; 561 burst_log = 1;
554 break; 562 break;
555 case 4: 563 case 4:
556 burst_log = 2; 564 burst_log = 2;
557 break; 565 break;
558 case 8: 566 case 8:
559 burst_log = 3; 567 burst_log = 3;
@@ -587,29 +595,27 @@ tifb_attach(device_t parent, device_t se @@ -587,29 +595,27 @@ tifb_attach(device_t parent, device_t se
587 if (sc->sc_panel->bpp == 32) 595 if (sc->sc_panel->bpp == 32)
588 reg |= RASTER_CTRL_TFT24_UNPACKED; 596 reg |= RASTER_CTRL_TFT24_UNPACKED;
589 TIFB_WRITE(sc, LCD_RASTER_CTRL, reg); 597 TIFB_WRITE(sc, LCD_RASTER_CTRL, reg);
590 aprint_debug_dev(self, ": LCD_RASTER_CTRL 0x%x\n", reg); 598 aprint_debug_dev(self, ": LCD_RASTER_CTRL 0x%x\n", reg);
591 599
592 TIFB_WRITE(sc, LCD_CLKC_ENABLE, 600 TIFB_WRITE(sc, LCD_CLKC_ENABLE,
593 CLKC_ENABLE_DMA | CLKC_ENABLE_LDID | CLKC_ENABLE_CORE);  601 CLKC_ENABLE_DMA | CLKC_ENABLE_LDID | CLKC_ENABLE_CORE);
594 602
595 TIFB_WRITE(sc, LCD_CLKC_RESET, CLKC_RESET_MAIN); 603 TIFB_WRITE(sc, LCD_CLKC_RESET, CLKC_RESET_MAIN);
596 DELAY(100); 604 DELAY(100);
597 TIFB_WRITE(sc, LCD_CLKC_RESET, 0); 605 TIFB_WRITE(sc, LCD_CLKC_RESET, 0);
598 aprint_debug_dev(self, ": LCD_CLKC_ENABLE 0x%x\n", TIFB_READ(sc, LCD_CLKC_ENABLE)); 606 aprint_debug_dev(self, ": LCD_CLKC_ENABLE 0x%x\n", TIFB_READ(sc, LCD_CLKC_ENABLE));
599 607
600 reg = IRQ_EOF1 | IRQ_EOF0 | IRQ_FUF | IRQ_PL | 608 reg = IRQ_FUF | IRQ_PL | IRQ_ACB | IRQ_SYNC_LOST;
601 IRQ_ACB | IRQ_SYNC_LOST | IRQ_RASTER_DONE | 
602 IRQ_FRAME_DONE; 
603 TIFB_WRITE(sc, LCD_IRQENABLE_SET, reg); 609 TIFB_WRITE(sc, LCD_IRQENABLE_SET, reg);
604 610
605 reg = TIFB_READ(sc, LCD_RASTER_CTRL); 611 reg = TIFB_READ(sc, LCD_RASTER_CTRL);
606 reg |= RASTER_CTRL_LCDEN;  612 reg |= RASTER_CTRL_LCDEN;
607 TIFB_WRITE(sc, LCD_RASTER_CTRL, reg); 613 TIFB_WRITE(sc, LCD_RASTER_CTRL, reg);
608 aprint_debug_dev(self, ": LCD_RASTER_CTRL 0x%x\n", TIFB_READ(sc, LCD_RASTER_CTRL)); 614 aprint_debug_dev(self, ": LCD_RASTER_CTRL 0x%x\n", TIFB_READ(sc, LCD_RASTER_CTRL));
609 615
610 TIFB_WRITE(sc, LCD_SYSCONFIG,  616 TIFB_WRITE(sc, LCD_SYSCONFIG,
611 SYSCONFIG_STANDBY_SMART | SYSCONFIG_IDLE_SMART); 617 SYSCONFIG_STANDBY_SMART | SYSCONFIG_IDLE_SMART);
612 aprint_debug_dev(self, ": LCD_SYSCONFIG 0x%x\n", TIFB_READ(sc, LCD_SYSCONFIG)); 618 aprint_debug_dev(self, ": LCD_SYSCONFIG 0x%x\n", TIFB_READ(sc, LCD_SYSCONFIG));
613 619
614 /* attach wscons */ 620 /* attach wscons */
615 sc->sc_defaultscreen_descr = (struct wsscreen_descr){ 621 sc->sc_defaultscreen_descr = (struct wsscreen_descr){
@@ -643,26 +649,28 @@ tifb_attach(device_t parent, device_t se @@ -643,26 +649,28 @@ tifb_attach(device_t parent, device_t se
643 wsdisplay_cnattach(&sc->sc_defaultscreen_descr, ri, 0, 0, 649 wsdisplay_cnattach(&sc->sc_defaultscreen_descr, ri, 0, 0,
644 defattr); 650 defattr);
645 vcons_replay_msgbuf(&sc->sc_console_screen); 651 vcons_replay_msgbuf(&sc->sc_console_screen);
646 } 652 }
647 653
648 aa.console = is_console; 654 aa.console = is_console;
649 aa.scrdata = &sc->sc_screenlist; 655 aa.scrdata = &sc->sc_screenlist;
650 aa.accessops = &tifb_accessops; 656 aa.accessops = &tifb_accessops;
651 aa.accesscookie = &sc->vd; 657 aa.accesscookie = &sc->vd;
652 658
653 config_found(sc->sc_dev, &aa, wsemuldisplaydevprint); 659 config_found(sc->sc_dev, &aa, wsemuldisplaydevprint);
654} 660}
655 661
 662uint32_t tifb_intr_unh = 0;
 663
656static int 664static int
657tifb_intr(void *v) 665tifb_intr(void *v)
658{ 666{
659 struct tifb_softc *sc = v; 667 struct tifb_softc *sc = v;
660 uint32_t reg; 668 uint32_t reg;
661 669
662 reg = TIFB_READ(sc, LCD_IRQSTATUS); 670 reg = TIFB_READ(sc, LCD_IRQSTATUS);
663 TIFB_WRITE(sc, LCD_IRQSTATUS, reg); 671 TIFB_WRITE(sc, LCD_IRQSTATUS, reg);
664 672
665 if (reg & IRQ_SYNC_LOST) { 673 if (reg & IRQ_SYNC_LOST) {
666 ev_sync_lost.ev_count ++; 674 ev_sync_lost.ev_count ++;
667 reg = TIFB_READ(sc, LCD_RASTER_CTRL); 675 reg = TIFB_READ(sc, LCD_RASTER_CTRL);
668 reg &= ~RASTER_CTRL_LCDEN; 676 reg &= ~RASTER_CTRL_LCDEN;
@@ -676,32 +684,26 @@ tifb_intr(void *v) @@ -676,32 +684,26 @@ tifb_intr(void *v)
676 684
677 if (reg & IRQ_PL) { 685 if (reg & IRQ_PL) {
678 ev_palette.ev_count ++; 686 ev_palette.ev_count ++;
679 reg = TIFB_READ(sc, LCD_RASTER_CTRL); 687 reg = TIFB_READ(sc, LCD_RASTER_CTRL);
680 reg &= ~RASTER_CTRL_LCDEN; 688 reg &= ~RASTER_CTRL_LCDEN;
681 TIFB_WRITE(sc, LCD_RASTER_CTRL, reg); 689 TIFB_WRITE(sc, LCD_RASTER_CTRL, reg);
682 690
683 reg = TIFB_READ(sc, LCD_RASTER_CTRL); 691 reg = TIFB_READ(sc, LCD_RASTER_CTRL);
684 reg |= RASTER_CTRL_LCDEN; 692 reg |= RASTER_CTRL_LCDEN;
685 TIFB_WRITE(sc, LCD_RASTER_CTRL, reg); 693 TIFB_WRITE(sc, LCD_RASTER_CTRL, reg);
686 return 0; 694 return 0;
687 } 695 }
688 696
689 if (reg & (IRQ_FRAME_DONE|IRQ_EOF0|IRQ_EOF1)) { 
690 /* flush the write-back cache */ 
691 bus_dmamap_sync(sc->sc_dmat, sc->sc_dmamap, 
692 0, sc->sc_vramsize, BUS_DMASYNC_PREWRITE); 
693 } 
694 
695 if (reg & IRQ_FRAME_DONE) { 697 if (reg & IRQ_FRAME_DONE) {
696 ev_frame_done.ev_count ++; 698 ev_frame_done.ev_count ++;
697 reg &= ~IRQ_FRAME_DONE; 699 reg &= ~IRQ_FRAME_DONE;
698 } 700 }
699 701
700 if (reg & IRQ_EOF0) { 702 if (reg & IRQ_EOF0) {
701 ev_eof0.ev_count ++; 703 ev_eof0.ev_count ++;
702 TIFB_WRITE(sc, LCD_LCDDMA_FB0_BASE, sc->sc_dmamem->ds_addr); 704 TIFB_WRITE(sc, LCD_LCDDMA_FB0_BASE, sc->sc_dmamem->ds_addr);
703 TIFB_WRITE(sc, LCD_LCDDMA_FB0_CEILING, 705 TIFB_WRITE(sc, LCD_LCDDMA_FB0_CEILING,
704 sc->sc_dmamem->ds_addr + sc->sc_vramsize - 1); 706 sc->sc_dmamem->ds_addr + sc->sc_vramsize - 1);
705 reg &= ~IRQ_EOF0; 707 reg &= ~IRQ_EOF0;
706 } 708 }
707 709
@@ -714,28 +716,30 @@ tifb_intr(void *v) @@ -714,28 +716,30 @@ tifb_intr(void *v)
714 } 716 }
715 717
716 if (reg & IRQ_FUF) { 718 if (reg & IRQ_FUF) {
717 ev_fifo_underflow.ev_count ++; 719 ev_fifo_underflow.ev_count ++;
718 /* TODO: Handle FUF */ 720 /* TODO: Handle FUF */
719 reg =~ IRQ_FUF; 721 reg =~ IRQ_FUF;
720 } 722 }
721 723
722 if (reg & IRQ_ACB) { 724 if (reg & IRQ_ACB) {
723 ev_ac_bias.ev_count ++; 725 ev_ac_bias.ev_count ++;
724 /* TODO: Handle ACB */ 726 /* TODO: Handle ACB */
725 reg =~ IRQ_ACB; 727 reg =~ IRQ_ACB;
726 } 728 }
727 if (reg) 729 if (reg) {
728 ev_others.ev_count ++; 730 ev_others.ev_count ++;
 731 tifb_intr_unh = reg;
 732 }
729 return 0; 733 return 0;
730} 734}
731 735
732static int 736static int
733tifb_ioctl(void *v, void *vs, u_long cmd, void *data, int flag, 737tifb_ioctl(void *v, void *vs, u_long cmd, void *data, int flag,
734 struct lwp *l) 738 struct lwp *l)
735{ 739{
736 struct vcons_data *vd = v; 740 struct vcons_data *vd = v;
737 struct tifb_softc *sc = vd->cookie; 741 struct tifb_softc *sc = vd->cookie;
738 struct wsdisplay_fbinfo *wdf; 742 struct wsdisplay_fbinfo *wdf;
739 struct vcons_screen *ms = vd->active; 743 struct vcons_screen *ms = vd->active;
740 744
741 switch (cmd) { 745 switch (cmd) {
@@ -840,28 +844,34 @@ tifb_mmap(void *v, void *vs, off_t offse @@ -840,28 +844,34 @@ tifb_mmap(void *v, void *vs, off_t offse
840 844
841static void 845static void
842tifb_init_screen(void *cookie, struct vcons_screen *scr, 846tifb_init_screen(void *cookie, struct vcons_screen *scr,
843 int existing, long *defattr) 847 int existing, long *defattr)
844{ 848{
845 struct tifb_softc *sc = cookie; 849 struct tifb_softc *sc = cookie;
846 struct rasops_info *ri = &scr->scr_ri; 850 struct rasops_info *ri = &scr->scr_ri;
847 851
848 ri->ri_depth = sc->sc_panel->bpp; 852 ri->ri_depth = sc->sc_panel->bpp;
849 ri->ri_width = sc->sc_panel->panel_width; 853 ri->ri_width = sc->sc_panel->panel_width;
850 ri->ri_height = sc->sc_panel->panel_height; 854 ri->ri_height = sc->sc_panel->panel_height;
851 ri->ri_stride = sc->sc_stride; 855 ri->ri_stride = sc->sc_stride;
852 ri->ri_flg = RI_CENTER | RI_FULLCLEAR; 856 ri->ri_flg = RI_CENTER | RI_FULLCLEAR;
853 857
854 ri->ri_bits = (char *)sc->sc_fbaddr; 858 if (sc->sc_shadowfb != NULL) {
 859 ri->ri_bits = (char *)sc->sc_shadowfb;
 860 ri->ri_hwbits = (char *)sc->sc_fbaddr;
 861 } else {
 862 ri->ri_bits = (char *)sc->sc_fbaddr;
 863 ri->ri_hwbits = NULL;
 864 }
855 865
856 if (existing) { 866 if (existing) {
857 ri->ri_flg |= RI_CLEAR; 867 ri->ri_flg |= RI_CLEAR;
858 } 868 }
859 869
860 rasops_init(ri, sc->sc_panel->panel_height / 8, sc->sc_panel->panel_width / 8); 870 rasops_init(ri, sc->sc_panel->panel_height / 8, sc->sc_panel->panel_width / 8);
861 ri->ri_caps = WSSCREEN_WSCOLORS; 871 ri->ri_caps = WSSCREEN_WSCOLORS;
862 872
863 rasops_reconfig(ri, sc->sc_panel->panel_height / ri->ri_font->fontheight, 873 rasops_reconfig(ri, sc->sc_panel->panel_height / ri->ri_font->fontheight,
864 sc->sc_panel->panel_width / ri->ri_font->fontwidth); 874 sc->sc_panel->panel_width / ri->ri_font->fontwidth);
865 875
866 ri->ri_hw = scr; 876 ri->ri_hw = scr;
867} 877}