1 /* $NetBSD: tft_plb.c,v 1.2 2007/03/04 05:59:46 christos Exp $ */
4 * Copyright (c) 2006 Jachym Holecek
7 * Written for DFC Design, s.r.o.
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution.
20 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
21 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
22 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
23 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
24 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
25 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
29 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 #include <sys/cdefs.h>
33 __KERNEL_RCSID(0, "$NetBSD: tft_plb.c,v 1.2 2007/03/04 05:59:46 christos Exp $");
35 #include <sys/param.h>
36 #include <sys/systm.h>
38 #include <sys/kernel.h>
39 #include <sys/socket.h>
40 #include <sys/ioctl.h>
41 #include <sys/device.h>
42 #include <sys/queue.h>
44 #include <uvm/uvm_extern.h>
46 #include <machine/bus.h>
48 #include <dev/wscons/wsdisplayvar.h>
49 #include <dev/wscons/wsconsio.h>
50 #include <dev/rasops/rasops.h>
51 #include <dev/wscons/wsdisplay_vconsvar.h>
53 #include <evbppc/virtex/dev/xcvbusvar.h>
54 #include <evbppc/virtex/dev/tftreg.h>
55 #include <evbppc/virtex/dev/tftvar.h>
58 struct plb_tft_softc
{
59 struct tft_softc psc_sc
;
61 bus_dma_tag_t psc_dmat
;
62 bus_dmamap_t psc_dmap
; /* for psc_sc.sc_image */
63 bus_dma_segment_t psc_seg
;
65 void *sc_sdhook
; /* stop DMA */
68 static void plb_tft_attach(struct device
*, struct device
*, void *);
69 static paddr_t
plb_tft_mmap(void *, void *, off_t
, int);
71 CFATTACH_DECL(plb_tft
, sizeof(struct plb_tft_softc
),
72 xcvbus_child_match
, plb_tft_attach
, NULL
, NULL
);
75 /* Patched by tft_attach(), may be shared by all instances. */
76 static struct wsdisplay_accessops plb_tft_accessops
= {
85 plb_tft_attach(struct device
*parent
, struct device
*self
, void *aux
)
87 struct xcvbus_attach_args
*vaa
= aux
;
88 struct plb_tft_softc
*psc
= device_private(self
);
89 struct tft_softc
*sc
= &psc
->psc_sc
;
92 psc
->psc_dmat
= vaa
->vaa_dmat
;
93 sc
->sc_iot
= vaa
->vaa_iot
;
95 printf(": PLB_TFT\n");
97 if ((error
= bus_space_map(sc
->sc_iot
, vaa
->vaa_addr
, TFT_SIZE
,
98 0, &sc
->sc_ioh
)) != 0) {
99 printf("%s: could not map device registers\n",
104 /* Fill in resolution, depth, size. */
107 /* Allocate and map framebuffer control data. */
108 if ((error
= bus_dmamem_alloc(psc
->psc_dmat
, sc
->sc_size
, ADDR_ALIGN
,
109 0, &psc
->psc_seg
, 1, &nseg
, 0)) != 0) {
110 printf("%s: could not allocate framebuffer\n",
114 if ((error
= bus_dmamem_map(psc
->psc_dmat
, &psc
->psc_seg
, nseg
,
115 sc
->sc_size
, &sc
->sc_image
, BUS_DMA_COHERENT
)) != 0) {
116 printf("%s: could not map framebuffer\n",
120 if ((error
= bus_dmamap_create(psc
->psc_dmat
, sc
->sc_size
, 1,
121 sc
->sc_size
, 0, 0, &psc
->psc_dmap
)) != 0) {
122 printf("%s: could not create framebuffer DMA map\n",
126 if ((error
= bus_dmamap_load(psc
->psc_dmat
, psc
->psc_dmap
,
127 sc
->sc_image
, sc
->sc_size
, NULL
, 0)) != 0) {
128 printf("%s: could not load framebuffer DMA map\n",
132 /* XXX hack, we linear map whole RAM and we have single segment */
133 /* sc->sc_image = (void *)psc->psc_dmap->dm_segs[0].ds_addr; */
134 /* XXX hack, use predefined base addr */
135 sc
->sc_image
= (void *)(uintptr_t)0x3c00000;
137 /* XXX forget the hack above, use "virtex-tft-framebuffer-base" prop */
139 tft_attach(self
, &plb_tft_accessops
);
141 printf("%s: video memory pa 0x%08x\n", device_xname(self
),
142 (uint32_t)psc
->psc_dmap
->dm_segs
[0].ds_addr
);
145 /* XXX powerpc bus_dma doesn't support COHERENT. */
146 bus_dmamap_sync(psc
->psc_dmat
, psc
->psc_dmap
, 0,
147 sc
->sc_size
, BUS_DMASYNC_PREREAD
| BUS_DMASYNC_PREWRITE
);
150 bus_space_write_4(sc
->sc_iot
, sc
->sc_ioh
, TFT_CTRL
, CTRL_RESET
);
151 bus_space_write_4(sc
->sc_iot
, sc
->sc_ioh
, TFT_CTRL
, CTRL_ENABLE
);
154 /* XXX how do we change framebuffer base? */
155 bus_space_write_4(sc
->sc_iot
, sc
->sc_ioh
, TFT_CTRL
, CTRL_RESET
);
156 bus_space_write_4(sc
->sc_iot
, sc
->sc_ioh
, TFT_CTRL
, CTRL_ENABLE
);
157 bus_space_write_4(sc
->sc_iot
, sc
->sc_ioh
, TFT_ADDR
,
158 ADDR_MAKE(psc
->psc_dmap
->dm_segs
[0].ds_addr
));
164 bus_dmamap_destroy(psc
->psc_dmat
, psc
->psc_dmap
);
166 bus_dmamem_unmap(psc
->psc_dmat
, sc
->sc_image
, sc
->sc_size
);
168 bus_dmamem_free(psc
->psc_dmat
, &psc
->psc_seg
, nseg
);
170 bus_space_unmap(sc
->sc_iot
, sc
->sc_ioh
, TFT_SIZE
);
172 printf("%s: error %d\n", device_xname(self
), error
);
176 plb_tft_mmap(void *arg
, void *scr
, off_t offs
, int prot
)
178 struct vcons_data
*vc
= arg
;
179 struct plb_tft_softc
*psc
= vc
->cookie
;
183 if (offs
< psc
->psc_sc
.sc_size
)
184 pa
= bus_dmamem_mmap(psc
->psc_dmat
, &psc
->psc_seg
, 1,
185 offs
, prot
, BUS_DMA_WAITOK
| BUS_DMA_COHERENT
);
187 if (offs
< psc
->psc_sc
.sc_size
)
188 pa
= (paddr_t
)(intptr_t)psc
->psc_sc
.sc_image
+ offs
;