Sun Aug 8 11:24:52 2010 UTC ()
Allow pxa2x0_lcd driver mapping screen buffer memory cachable with
write-through map (i.e. map it without BUS_DMA_COHERENT) since
currently all DMA data transfers are memory to device only.

Disabled by default, but enabled by "options PXA2X0_LCD_WRITETHROUGH"
or setting pxa2x0_lcd_writethrough = 1 in a kernel binary.

Tested on WS003SH by me and on WS011SH by jun@, and console output speed
is improved ~three times faster than coherent (uncached) mapping.

XXX: should we have a flag like BUS_DMA_WRITETHROUGH in MI bus_dma(9)?


(tsutsui)
diff -r1.29 -r1.30 src/sys/arch/arm/xscale/pxa2x0_lcd.c

cvs diff -r1.29 -r1.30 src/sys/arch/arm/xscale/pxa2x0_lcd.c (expand / switch to unified diff)

--- src/sys/arch/arm/xscale/pxa2x0_lcd.c 2010/08/08 09:33:35 1.29
+++ src/sys/arch/arm/xscale/pxa2x0_lcd.c 2010/08/08 11:24:52 1.30
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: pxa2x0_lcd.c,v 1.29 2010/08/08 09:33:35 kiyohara Exp $ */ 1/* $NetBSD: pxa2x0_lcd.c,v 1.30 2010/08/08 11:24:52 tsutsui Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 2002 Genetec Corporation. All rights reserved. 4 * Copyright (c) 2002 Genetec Corporation. All rights reserved.
5 * Written by Hiroyuki Bessho for Genetec Corporation. 5 * Written by Hiroyuki Bessho for Genetec Corporation.
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.
@@ -28,27 +28,27 @@ @@ -28,27 +28,27 @@
28 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 28 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
29 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 29 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
30 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 30 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
31 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 31 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
32 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 32 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
33 * POSSIBILITY OF SUCH DAMAGE. 33 * POSSIBILITY OF SUCH DAMAGE.
34 */ 34 */
35 35
36/* 36/*
37 * Support PXA2[15]0's integrated LCD controller. 37 * Support PXA2[15]0's integrated LCD controller.
38 */ 38 */
39 39
40#include <sys/cdefs.h> 40#include <sys/cdefs.h>
41__KERNEL_RCSID(0, "$NetBSD: pxa2x0_lcd.c,v 1.29 2010/08/08 09:33:35 kiyohara Exp $"); 41__KERNEL_RCSID(0, "$NetBSD: pxa2x0_lcd.c,v 1.30 2010/08/08 11:24:52 tsutsui Exp $");
42 42
43#include <sys/param.h> 43#include <sys/param.h>
44#include <sys/systm.h> 44#include <sys/systm.h>
45#include <sys/conf.h> 45#include <sys/conf.h>
46#include <sys/uio.h> 46#include <sys/uio.h>
47#include <sys/malloc.h> 47#include <sys/malloc.h>
48#include <sys/kernel.h> /* for cold */ 48#include <sys/kernel.h> /* for cold */
49 49
50#include <uvm/uvm_extern.h> 50#include <uvm/uvm_extern.h>
51 51
52#include <dev/cons.h>  52#include <dev/cons.h>
53#include <dev/wscons/wsconsio.h> 53#include <dev/wscons/wsconsio.h>
54#include <dev/wscons/wsdisplayvar.h>  54#include <dev/wscons/wsdisplayvar.h>
@@ -68,26 +68,32 @@ __KERNEL_RCSID(0, "$NetBSD: pxa2x0_lcd.c @@ -68,26 +68,32 @@ __KERNEL_RCSID(0, "$NetBSD: pxa2x0_lcd.c
68 68
69#include "wsdisplay.h" 69#include "wsdisplay.h"
70 70
71/* 71/*
72 * Console variables. These are necessary since console is setup very early, 72 * Console variables. These are necessary since console is setup very early,
73 * before devices get attached. 73 * before devices get attached.
74 */ 74 */
75struct { 75struct {
76 int is_console; 76 int is_console;
77 struct pxa2x0_wsscreen_descr *descr; 77 struct pxa2x0_wsscreen_descr *descr;
78 const struct lcd_panel_geometry *geom; 78 const struct lcd_panel_geometry *geom;
79} pxa2x0_lcd_console; 79} pxa2x0_lcd_console;
80 80
 81#ifdef PXA2X0_LCD_WRITETHROUGH
 82int pxa2x0_lcd_writethrough = 1; /* patchable */
 83#else
 84int pxa2x0_lcd_writethrough = 0;
 85#endif
 86
81int lcdintr(void *); 87int lcdintr(void *);
82 88
83static void pxa2x0_lcd_initialize(struct pxa2x0_lcd_softc *,  89static void pxa2x0_lcd_initialize(struct pxa2x0_lcd_softc *,
84 const struct lcd_panel_geometry *); 90 const struct lcd_panel_geometry *);
85#if NWSDISPLAY > 0 91#if NWSDISPLAY > 0
86static void pxa2x0_lcd_setup_rasops(struct pxa2x0_lcd_softc *, 92static void pxa2x0_lcd_setup_rasops(struct pxa2x0_lcd_softc *,
87 struct rasops_info *, struct pxa2x0_wsscreen_descr *, 93 struct rasops_info *, struct pxa2x0_wsscreen_descr *,
88 const struct lcd_panel_geometry *); 94 const struct lcd_panel_geometry *);
89#endif 95#endif
90 96
91void 97void
92pxa2x0_lcd_geometry(struct pxa2x0_lcd_softc *sc, 98pxa2x0_lcd_geometry(struct pxa2x0_lcd_softc *sc,
93 const struct lcd_panel_geometry *info) 99 const struct lcd_panel_geometry *info)
@@ -323,26 +329,29 @@ lcdintr(void *arg) @@ -323,26 +329,29 @@ lcdintr(void *arg)
323 */ 329 */
324void 330void
325pxa2x0_lcd_start_dma(struct pxa2x0_lcd_softc *sc, 331pxa2x0_lcd_start_dma(struct pxa2x0_lcd_softc *sc,
326 struct pxa2x0_lcd_screen *scr) 332 struct pxa2x0_lcd_screen *scr)
327{ 333{
328 bus_space_tag_t iot; 334 bus_space_tag_t iot;
329 bus_space_handle_t ioh; 335 bus_space_handle_t ioh;
330 uint32_t tmp; 336 uint32_t tmp;
331 int val, save; 337 int val, save;
332 338
333 iot = sc->iot; 339 iot = sc->iot;
334 ioh = sc->ioh; 340 ioh = sc->ioh;
335 341
 342 bus_dmamap_sync(sc->dma_tag, scr->dma, 0, scr->buf_size,
 343 BUS_DMASYNC_PREWRITE);
 344
336 save = disable_interrupts(I32_bit); 345 save = disable_interrupts(I32_bit);
337 346
338 switch (scr->depth) { 347 switch (scr->depth) {
339 case 1: val = 0; break; 348 case 1: val = 0; break;
340 case 2: val = 1; break; 349 case 2: val = 1; break;
341 case 4: val = 2; break; 350 case 4: val = 2; break;
342 case 8: val = 3; break; 351 case 8: val = 3; break;
343 case 16: val = 4; break; 352 case 16: val = 4; break;
344 case 18: val = 5; break; 353 case 18: val = 5; break;
345 case 24: val = 33; break; 354 case 24: val = 33; break;
346 default: 355 default:
347 val = 4; break;  356 val = 4; break;
348 } 357 }
@@ -526,30 +535,51 @@ pxa2x0_lcd_new_screen(struct pxa2x0_lcd_ @@ -526,30 +535,51 @@ pxa2x0_lcd_new_screen(struct pxa2x0_lcd_
526 535
527 if (error || scr->nsegs != 1) { 536 if (error || scr->nsegs != 1) {
528 /* XXX: 537 /* XXX:
529 * Actually we can handle nsegs>1 case by means 538 * Actually we can handle nsegs>1 case by means
530 * of multiple DMA descriptors for a panel. It 539 * of multiple DMA descriptors for a panel. It
531 * will make code here a bit hairly. 540 * will make code here a bit hairly.
532 */ 541 */
533 if (error == 0) 542 if (error == 0)
534 error = E2BIG; 543 error = E2BIG;
535 goto bad; 544 goto bad;
536 } 545 }
537 546
538 error = bus_dmamem_map(dma_tag, scr->segs, scr->nsegs, size, 547 error = bus_dmamem_map(dma_tag, scr->segs, scr->nsegs, size,
539 (void **)&scr->buf_va, busdma_flag | BUS_DMA_COHERENT); 548 (void **)&scr->buf_va,
 549 busdma_flag | (pxa2x0_lcd_writethrough ? 0 : BUS_DMA_COHERENT));
540 if (error) 550 if (error)
541 goto bad; 551 goto bad;
542 552
 553 /* XXX: should we have BUS_DMA_WRITETHROUGH in MI bus_dma(9) API? */
 554 if (pxa2x0_lcd_writethrough) {
 555 pt_entry_t *ptep;
 556 vaddr_t va, eva;
 557
 558 va = (vaddr_t)scr->buf_va;
 559 eva = va + size;
 560 while (va < eva) {
 561 /* taken from arm/arm32/bus_dma.c:_bus_dmamem_map() */
 562 cpu_dcache_wbinv_range(va, PAGE_SIZE);
 563 cpu_drain_writebuf();
 564 ptep = vtopte(va);
 565 *ptep &= ~L2_S_CACHE_MASK;
 566 *ptep |= L2_C;
 567 PTE_SYNC(ptep);
 568 tlb_flush();
 569 va += PAGE_SIZE;
 570 }
 571 }
 572
543 memset(scr->buf_va, 0, scr->buf_size); 573 memset(scr->buf_va, 0, scr->buf_size);
544 574
545 /* map memory for DMA */ 575 /* map memory for DMA */
546 error = bus_dmamap_create(dma_tag, 1024*1024*2, 1, 1024*1024*2, 0, 576 error = bus_dmamap_create(dma_tag, 1024*1024*2, 1, 1024*1024*2, 0,
547 busdma_flag, &scr->dma); 577 busdma_flag, &scr->dma);
548 if (error) 578 if (error)
549 goto bad; 579 goto bad;
550 580
551 error = bus_dmamap_load(dma_tag, scr->dma, scr->buf_va, size, 581 error = bus_dmamap_load(dma_tag, scr->dma, scr->buf_va, size,
552 NULL, busdma_flag); 582 NULL, busdma_flag);
553 if (error) 583 if (error)
554 goto bad; 584 goto bad;
555 585
@@ -889,27 +919,28 @@ paddr_t @@ -889,27 +919,28 @@ paddr_t
889pxa2x0_lcd_mmap(void *v, void *vs, off_t offset, int prot) 919pxa2x0_lcd_mmap(void *v, void *vs, off_t offset, int prot)
890{ 920{
891 struct pxa2x0_lcd_softc *sc = v; 921 struct pxa2x0_lcd_softc *sc = v;
892 struct pxa2x0_lcd_screen *scr = sc->active; /* ??? */ 922 struct pxa2x0_lcd_screen *scr = sc->active; /* ??? */
893 923
894 if (scr == NULL) 924 if (scr == NULL)
895 return -1; 925 return -1;
896 926
897 if (offset < 0 || 927 if (offset < 0 ||
898 offset >= scr->rinfo.ri_stride * scr->rinfo.ri_height) 928 offset >= scr->rinfo.ri_stride * scr->rinfo.ri_height)
899 return -1; 929 return -1;
900 930
901 return bus_dmamem_mmap(sc->dma_tag, scr->segs, scr->nsegs, 931 return bus_dmamem_mmap(sc->dma_tag, scr->segs, scr->nsegs,
902 offset, prot, BUS_DMA_WAITOK|BUS_DMA_COHERENT); 932 offset, prot,
 933 BUS_DMA_WAITOK | (pxa2x0_lcd_writethrough ? 0 : BUS_DMA_COHERENT));
903} 934}
904 935
905 936
906static void 937static void
907pxa2x0_lcd_cursor(void *cookie, int on, int row, int col) 938pxa2x0_lcd_cursor(void *cookie, int on, int row, int col)
908{ 939{
909 struct pxa2x0_lcd_screen *scr = cookie; 940 struct pxa2x0_lcd_screen *scr = cookie;
910 941
911 (*scr->rinfo.ri_ops.cursor)(&scr->rinfo, on, row, col); 942 (*scr->rinfo.ri_ops.cursor)(&scr->rinfo, on, row, col);
912} 943}
913 944
914static int 945static int
915pxa2x0_lcd_mapchar(void *cookie, int c, unsigned int *cp) 946pxa2x0_lcd_mapchar(void *cookie, int c, unsigned int *cp)