1 /* $NetBSD: tft_ll.c,v 1.1 2006/12/02 22:18:47 freza 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_ll.c,v 1.1 2006/12/02 22:18:47 freza 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>
49 #include <dev/wscons/wsdisplayvar.h>
50 #include <dev/wscons/wsconsio.h>
51 #include <dev/rasops/rasops.h>
52 #include <dev/wscons/wsdisplay_vconsvar.h>
54 #include <evbppc/virtex/dev/xcvbusvar.h>
55 #include <evbppc/virtex/dev/cdmacreg.h>
56 #include <evbppc/virtex/dev/tftreg.h>
57 #include <evbppc/virtex/dev/tftvar.h>
60 struct ll_tft_control
{
61 struct cdmac_descr cd_dsc
;
66 struct tft_softc lsc_sc
;
68 bus_space_tag_t lsc_dma_iot
;
69 bus_space_handle_t lsc_dma_ioh
;
71 bus_dma_tag_t lsc_dmat
;
72 bus_dmamap_t lsc_dmap
;
74 struct ll_tft_control
*lsc_cd
;
75 bus_dma_segment_t lsc_seg
;
78 static void ll_tft_attach(struct device
*, struct device
*, void *);
79 static paddr_t
ll_tft_mmap(void *, void *, off_t
, int);
80 static void ll_tft_shutdown(void *);
82 CFATTACH_DECL(ll_tft
, sizeof(struct ll_tft_softc
),
83 xcvbus_child_match
, ll_tft_attach
, NULL
, NULL
);
86 static struct wsdisplay_accessops ll_tft_accessops
= {
92 ll_tft_attach(struct device
*parent
, struct device
*self
, void *aux
)
94 struct xcvbus_attach_args
*vaa
= aux
;
95 struct ll_dmac
*tx
= vaa
->vaa_tx_dmac
;
96 struct ll_tft_softc
*lsc
= (struct ll_tft_softc
*)self
;
97 struct tft_softc
*sc
= &lsc
->lsc_sc
;
102 lsc
->lsc_dma_iot
= tx
->dmac_iot
;
103 lsc
->lsc_dmat
= vaa
->vaa_dmat
;
104 sc
->sc_iot
= vaa
->vaa_iot
;
106 printf(": LL_TFT\n");
108 if ((error
= bus_space_map(sc
->sc_iot
, vaa
->vaa_addr
, TFT_SIZE
,
109 0, &sc
->sc_ioh
)) != 0) {
110 printf("%s: could not map device registers\n",
114 if ((error
= bus_space_map(lsc
->lsc_dma_iot
, tx
->dmac_ctrl_addr
,
115 CDMAC_CTRL_SIZE
, 0, &lsc
->lsc_dma_ioh
)) != 0) {
116 printf("%s: could not map dmac registers\n",
121 /* Fill in resolution, depth, size. */
122 tft_mode(&sc
->sc_dev
);
124 /* Allocate and map framebuffer control data. */
125 if ((error
= bus_dmamem_alloc(lsc
->lsc_dmat
,
126 sizeof(struct ll_tft_control
) + sc
->sc_size
, 8, 0,
127 &lsc
->lsc_seg
, 1, &nseg
, 0)) != 0) {
128 printf("%s: could not allocate framebuffer\n",
132 if ((error
= bus_dmamem_map(lsc
->lsc_dmat
, &lsc
->lsc_seg
, nseg
,
133 sizeof(struct ll_tft_control
) + sc
->sc_size
,
134 (void **)&lsc
->lsc_cd
, BUS_DMA_COHERENT
)) != 0) {
135 printf("%s: could not map framebuffer\n",
139 if ((error
= bus_dmamap_create(lsc
->lsc_dmat
,
140 sizeof(struct ll_tft_control
) + sc
->sc_size
, 1,
141 sizeof(struct ll_tft_control
) + sc
->sc_size
, 0, 0,
142 &lsc
->lsc_dmap
)) != 0) {
143 printf("%s: could not create framebuffer DMA map\n",
147 if ((error
= bus_dmamap_load(lsc
->lsc_dmat
, lsc
->lsc_dmap
, lsc
->lsc_cd
,
148 sizeof(struct ll_tft_control
) + sc
->sc_size
, NULL
, 0)) != 0) {
149 printf("%s: could not load framebuffer DMA map\n",
154 /* Clear screen, setup descriptor. */
155 memset(lsc
->lsc_cd
, 0x00, sizeof(struct ll_tft_control
));
156 sc
->sc_image
= lsc
->lsc_cd
->cd_img
;
158 lsc
->lsc_cd
->cd_dsc
.desc_next
= lsc
->lsc_dmap
->dm_segs
[0].ds_addr
;
159 lsc
->lsc_cd
->cd_dsc
.desc_addr
= lsc
->lsc_dmap
->dm_segs
[0].ds_addr
+
160 offsetof(struct ll_tft_control
, cd_img
);
161 lsc
->lsc_cd
->cd_dsc
.desc_size
= sc
->sc_size
;
162 lsc
->lsc_cd
->cd_dsc
.desc_stat
= CDMAC_STAT_SOP
;
164 bus_dmamap_sync(lsc
->lsc_dmat
, lsc
->lsc_dmap
, 0,
165 sizeof(struct ll_tft_control
) + sc
->sc_size
,
166 BUS_DMASYNC_PREREAD
| BUS_DMASYNC_PREWRITE
);
168 sc
->sc_sdhook
= shutdownhook_establish(ll_tft_shutdown
, sc
);
169 if (sc
->sc_sdhook
== NULL
)
170 printf("%s: WARNING: unable to establish shutdown hook\n",
173 tft_attach(self
, &ll_tft_accessops
);
175 printf("%s: video memory pa 0x%08x\n", device_xname(self
),
176 (uint32_t)lsc
->lsc_cd
->cd_dsc
.desc_addr
);
178 /* Timing sensitive... */
179 bus_space_write_4(sc
->sc_iot
, sc
->sc_ioh
, TFT_CTRL
, CTRL_RESET
);
180 bus_space_write_4(sc
->sc_iot
, sc
->sc_ioh
, TFT_CTRL
, CTRL_ENABLE
);
181 bus_space_write_4(lsc
->lsc_dma_iot
, lsc
->lsc_dma_ioh
, CDMAC_CURDESC
,
182 lsc
->lsc_dmap
->dm_segs
[0].ds_addr
);
187 bus_dmamap_destroy(lsc
->lsc_dmat
, lsc
->lsc_dmap
);
189 bus_dmamem_unmap(lsc
->lsc_dmat
, (void *)lsc
->lsc_cd
,
190 sizeof(struct ll_tft_control
) + sc
->sc_size
);
192 bus_dmamem_free(lsc
->lsc_dmat
, &lsc
->lsc_seg
, nseg
);
194 bus_space_unmap(lsc
->lsc_dma_iot
, lsc
->lsc_dma_ioh
, CDMAC_CTRL_SIZE
);
196 bus_space_unmap(sc
->sc_iot
, sc
->sc_ioh
, TFT_SIZE
);
198 printf("%s: error %d\n", device_xname(self
), error
);
202 ll_tft_mmap(void *arg
, void *scr
, off_t offs
, int prot
)
204 struct ll_tft_softc
*lsc
= arg
;
207 if (offs
< lsc
->lsc_sc
.sc_size
) {
208 pa
= bus_dmamem_mmap(lsc
->lsc_dmat
, &lsc
->lsc_seg
, 1,
209 offs
+ offsetof(struct ll_tft_control
, cd_img
),
210 prot
, BUS_DMA_WAITOK
| BUS_DMA_COHERENT
);
219 ll_tft_shutdown(void *arg
)
221 struct ll_tft_softc
*lsc
= arg
;
223 bus_space_write_4(lsc
->lsc_dma_iot
, lsc
->lsc_dma_ioh
, 0,
226 tft_shutdown(&lsc
->lsc_sc
);