| @@ -1,1308 +1,1308 @@ | | | @@ -1,1308 +1,1308 @@ |
1 | /* $NetBSD: ffb.c,v 1.64 2019/12/22 23:23:31 thorpej Exp $ */ | | 1 | /* $NetBSD: ffb.c,v 1.65 2020/07/05 09:55:07 martin Exp $ */ |
2 | /* $OpenBSD: creator.c,v 1.20 2002/07/30 19:48:15 jason Exp $ */ | | 2 | /* $OpenBSD: creator.c,v 1.20 2002/07/30 19:48:15 jason Exp $ */ |
3 | | | 3 | |
4 | /* | | 4 | /* |
5 | * Copyright (c) 2002 Jason L. Wright (jason@thought.net) | | 5 | * Copyright (c) 2002 Jason L. Wright (jason@thought.net) |
6 | * All rights reserved. | | 6 | * All rights reserved. |
7 | * | | 7 | * |
8 | * Redistribution and use in source and binary forms, with or without | | 8 | * Redistribution and use in source and binary forms, with or without |
9 | * modification, are permitted provided that the following conditions | | 9 | * modification, are permitted provided that the following conditions |
10 | * are met: | | 10 | * are met: |
11 | * 1. Redistributions of source code must retain the above copyright | | 11 | * 1. Redistributions of source code must retain the above copyright |
12 | * notice, this list of conditions and the following disclaimer. | | 12 | * notice, this list of conditions and the following disclaimer. |
13 | * 2. Redistributions in binary form must reproduce the above copyright | | 13 | * 2. Redistributions in binary form must reproduce the above copyright |
14 | * notice, this list of conditions and the following disclaimer in the | | 14 | * notice, this list of conditions and the following disclaimer in the |
15 | * documentation and/or other materials provided with the distribution. | | 15 | * documentation and/or other materials provided with the distribution. |
16 | * 3. All advertising materials mentioning features or use of this software | | 16 | * 3. All advertising materials mentioning features or use of this software |
17 | * must display the following acknowledgement: | | 17 | * must display the following acknowledgement: |
18 | * This product includes software developed by Jason L. Wright | | 18 | * This product includes software developed by Jason L. Wright |
19 | * 4. The name of the author may not be used to endorse or promote products | | 19 | * 4. The name of the author may not be used to endorse or promote products |
20 | * derived from this software without specific prior written permission. | | 20 | * derived from this software without specific prior written permission. |
21 | * | | 21 | * |
22 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR | | 22 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
23 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | | 23 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
24 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | | 24 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
25 | * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, | | 25 | * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, |
26 | * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | | 26 | * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |
27 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR | | 27 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR |
28 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | | 28 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
29 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, | | 29 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, |
30 | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN | | 30 | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN |
31 | * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | | 31 | * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
32 | * POSSIBILITY OF SUCH DAMAGE. | | 32 | * POSSIBILITY OF SUCH DAMAGE. |
33 | */ | | 33 | */ |
34 | | | 34 | |
35 | #include <sys/cdefs.h> | | 35 | #include <sys/cdefs.h> |
36 | __KERNEL_RCSID(0, "$NetBSD: ffb.c,v 1.64 2019/12/22 23:23:31 thorpej Exp $"); | | 36 | __KERNEL_RCSID(0, "$NetBSD: ffb.c,v 1.65 2020/07/05 09:55:07 martin Exp $"); |
37 | | | 37 | |
38 | #include <sys/types.h> | | 38 | #include <sys/types.h> |
39 | #include <sys/param.h> | | 39 | #include <sys/param.h> |
40 | #include <sys/systm.h> | | 40 | #include <sys/systm.h> |
41 | #include <sys/kernel.h> | | 41 | #include <sys/kernel.h> |
42 | #include <sys/device.h> | | 42 | #include <sys/device.h> |
43 | #include <sys/conf.h> | | 43 | #include <sys/conf.h> |
44 | #include <sys/ioctl.h> | | 44 | #include <sys/ioctl.h> |
45 | #include <sys/malloc.h> | | 45 | #include <sys/malloc.h> |
46 | #include <sys/mman.h> | | 46 | #include <sys/mman.h> |
47 | | | 47 | |
48 | #include <sys/bus.h> | | 48 | #include <sys/bus.h> |
49 | #include <machine/autoconf.h> | | 49 | #include <machine/autoconf.h> |
50 | #include <machine/openfirm.h> | | 50 | #include <machine/openfirm.h> |
51 | #include <machine/vmparam.h> | | 51 | #include <machine/vmparam.h> |
52 | | | 52 | |
53 | #include <dev/wscons/wsconsio.h> | | 53 | #include <dev/wscons/wsconsio.h> |
54 | #include <dev/sun/fbio.h> | | 54 | #include <dev/sun/fbio.h> |
55 | #include <dev/sun/fbvar.h> | | 55 | #include <dev/sun/fbvar.h> |
56 | | | 56 | |
57 | #include <dev/wsfont/wsfont.h> | | 57 | #include <dev/wsfont/wsfont.h> |
58 | #include <dev/wscons/wsdisplay_vconsvar.h> | | 58 | #include <dev/wscons/wsdisplay_vconsvar.h> |
59 | | | 59 | |
60 | #include <prop/proplib.h> | | 60 | #include <prop/proplib.h> |
61 | | | 61 | |
62 | #include <dev/i2c/i2cvar.h> | | 62 | #include <dev/i2c/i2cvar.h> |
63 | #include <dev/i2c/i2c_bitbang.h> | | 63 | #include <dev/i2c/i2c_bitbang.h> |
64 | #include <dev/i2c/ddcvar.h> | | 64 | #include <dev/i2c/ddcvar.h> |
65 | | | 65 | |
66 | #include <sparc64/dev/ffbreg.h> | | 66 | #include <sparc64/dev/ffbreg.h> |
67 | #include <sparc64/dev/ffbvar.h> | | 67 | #include <sparc64/dev/ffbvar.h> |
68 | | | 68 | |
69 | #include "opt_wsdisplay_compat.h" | | 69 | #include "opt_wsdisplay_compat.h" |
70 | #include "opt_ffb.h" | | 70 | #include "opt_ffb.h" |
71 | | | 71 | |
72 | #ifndef WS_DEFAULT_BG | | 72 | #ifndef WS_DEFAULT_BG |
73 | /* Sun -> background should be white */ | | 73 | /* Sun -> background should be white */ |
74 | #define WS_DEFAULT_BG 0xf | | 74 | #define WS_DEFAULT_BG 0xf |
75 | #endif | | 75 | #endif |
76 | | | 76 | |
77 | #ifdef FFB_SYNC | | 77 | #ifdef FFB_SYNC |
78 | #define SYNC ffb_ras_wait(sc) | | 78 | #define SYNC ffb_ras_wait(sc) |
79 | #else | | 79 | #else |
80 | #define SYNC | | 80 | #define SYNC |
81 | #endif | | 81 | #endif |
82 | | | 82 | |
83 | /* Debugging */ | | 83 | /* Debugging */ |
84 | #if !defined FFB_DEBUG | | 84 | #if !defined FFB_DEBUG |
85 | #define FFB_DEBUG 0 | | 85 | #define FFB_DEBUG 0 |
86 | #endif | | 86 | #endif |
87 | #define DPRINTF(x) if (ffb_debug) printf x | | 87 | #define DPRINTF(x) if (ffb_debug) printf x |
88 | /* Patchable */ | | 88 | /* Patchable */ |
89 | extern int ffb_debug; | | 89 | extern int ffb_debug; |
90 | #if FFB_DEBUG > 0 | | 90 | #if FFB_DEBUG > 0 |
91 | int ffb_debug = 1; | | 91 | int ffb_debug = 1; |
92 | #else | | 92 | #else |
93 | int ffb_debug = 0; | | 93 | int ffb_debug = 0; |
94 | #endif | | 94 | #endif |
95 | | | 95 | |
96 | extern struct cfdriver ffb_cd; | | 96 | extern struct cfdriver ffb_cd; |
97 | | | 97 | |
98 | struct wsscreen_descr ffb_stdscreen = { | | 98 | struct wsscreen_descr ffb_stdscreen = { |
99 | "sunffb", | | 99 | "sunffb", |
100 | 0, 0, /* will be filled in -- XXX shouldn't, it's global. */ | | 100 | 0, 0, /* will be filled in -- XXX shouldn't, it's global. */ |
101 | 0, | | 101 | 0, |
102 | 0, 0, | | 102 | 0, 0, |
103 | WSSCREEN_REVERSE | WSSCREEN_WSCOLORS | WSSCREEN_UNDERLINE | | | 103 | WSSCREEN_REVERSE | WSSCREEN_WSCOLORS | WSSCREEN_UNDERLINE | |
104 | WSSCREEN_RESIZE, | | 104 | WSSCREEN_RESIZE, |
105 | NULL /* modecookie */ | | 105 | NULL /* modecookie */ |
106 | }; | | 106 | }; |
107 | | | 107 | |
108 | const struct wsscreen_descr *ffb_scrlist[] = { | | 108 | const struct wsscreen_descr *ffb_scrlist[] = { |
109 | &ffb_stdscreen, | | 109 | &ffb_stdscreen, |
110 | /* XXX other formats? */ | | 110 | /* XXX other formats? */ |
111 | }; | | 111 | }; |
112 | | | 112 | |
113 | struct wsscreen_list ffb_screenlist = { | | 113 | struct wsscreen_list ffb_screenlist = { |
114 | sizeof(ffb_scrlist) / sizeof(struct wsscreen_descr *), | | 114 | sizeof(ffb_scrlist) / sizeof(struct wsscreen_descr *), |
115 | ffb_scrlist | | 115 | ffb_scrlist |
116 | }; | | 116 | }; |
117 | | | 117 | |
118 | static struct vcons_screen ffb_console_screen; | | 118 | static struct vcons_screen ffb_console_screen; |
119 | | | 119 | |
120 | int ffb_ioctl(void *, void *, u_long, void *, int, struct lwp *); | | 120 | int ffb_ioctl(void *, void *, u_long, void *, int, struct lwp *); |
121 | static int ffb_blank(struct ffb_softc *, u_long, u_int *); | | 121 | static int ffb_blank(struct ffb_softc *, u_long, u_int *); |
122 | paddr_t ffb_mmap(void *, void *, off_t, int); | | 122 | paddr_t ffb_mmap(void *, void *, off_t, int); |
123 | void ffb_ras_fifo_wait(struct ffb_softc *, int); | | 123 | void ffb_ras_fifo_wait(struct ffb_softc *, int); |
124 | void ffb_ras_wait(struct ffb_softc *); | | 124 | void ffb_ras_wait(struct ffb_softc *); |
125 | void ffb_ras_init(struct ffb_softc *); | | 125 | void ffb_ras_init(struct ffb_softc *); |
126 | void ffb_ras_copyrows(void *, int, int, int); | | 126 | void ffb_ras_copyrows(void *, int, int, int); |
127 | void ffb_ras_erasecols(void *, int, int, int, long int); | | 127 | void ffb_ras_erasecols(void *, int, int, int, long int); |
128 | void ffb_ras_eraserows(void *, int, int, long int); | | 128 | void ffb_ras_eraserows(void *, int, int, long int); |
129 | void ffb_ras_fill(struct ffb_softc *); | | 129 | void ffb_ras_fill(struct ffb_softc *); |
130 | void ffb_ras_invert(struct ffb_softc *); | | 130 | void ffb_ras_invert(struct ffb_softc *); |
131 | static void ffb_ras_setfg(struct ffb_softc *, int32_t); | | 131 | static void ffb_ras_setfg(struct ffb_softc *, int32_t); |
132 | static void ffb_ras_setbg(struct ffb_softc *, int32_t); | | 132 | static void ffb_ras_setbg(struct ffb_softc *, int32_t); |
133 | | | 133 | |
134 | void ffb_clearscreen(struct ffb_softc *); | | 134 | void ffb_clearscreen(struct ffb_softc *); |
135 | void ffb_init_screen(void *, struct vcons_screen *, int, | | 135 | void ffb_init_screen(void *, struct vcons_screen *, int, |
136 | long *); | | 136 | long *); |
137 | int ffb_allocattr(void *, int, int, int, long *); | | 137 | int ffb_allocattr(void *, int, int, int, long *); |
138 | void ffb_putchar_mono(void *, int, int, u_int, long); | | 138 | void ffb_putchar_mono(void *, int, int, u_int, long); |
139 | void ffb_putchar_aa(void *, int, int, u_int, long); | | 139 | void ffb_putchar_aa(void *, int, int, u_int, long); |
140 | void ffb_cursor(void *, int, int, int); | | 140 | void ffb_cursor(void *, int, int, int); |
141 | | | 141 | |
142 | /* frame buffer generic driver */ | | 142 | /* frame buffer generic driver */ |
143 | static void ffbfb_unblank(device_t); | | 143 | static void ffbfb_unblank(device_t); |
144 | dev_type_open(ffbfb_open); | | 144 | dev_type_open(ffbfb_open); |
145 | dev_type_close(ffbfb_close); | | 145 | dev_type_close(ffbfb_close); |
146 | dev_type_ioctl(ffbfb_ioctl); | | 146 | dev_type_ioctl(ffbfb_ioctl); |
147 | dev_type_mmap(ffbfb_mmap); | | 147 | dev_type_mmap(ffbfb_mmap); |
148 | | | 148 | |
149 | static struct fbdriver ffb_fbdriver = { | | 149 | static struct fbdriver ffb_fbdriver = { |
150 | ffbfb_unblank, ffbfb_open, ffbfb_close, ffbfb_ioctl, nopoll, | | 150 | ffbfb_unblank, ffbfb_open, ffbfb_close, ffbfb_ioctl, nopoll, |
151 | ffbfb_mmap, nokqfilter | | 151 | ffbfb_mmap, nokqfilter |
152 | }; | | 152 | }; |
153 | | | 153 | |
154 | struct wsdisplay_accessops ffb_accessops = { | | 154 | struct wsdisplay_accessops ffb_accessops = { |
155 | .ioctl = ffb_ioctl, | | 155 | .ioctl = ffb_ioctl, |
156 | .mmap = ffb_mmap, | | 156 | .mmap = ffb_mmap, |
157 | }; | | 157 | }; |
158 | | | 158 | |
159 | /* I2C glue */ | | 159 | /* I2C glue */ |
160 | static int ffb_i2c_send_start(void *, int); | | 160 | static int ffb_i2c_send_start(void *, int); |
161 | static int ffb_i2c_send_stop(void *, int); | | 161 | static int ffb_i2c_send_stop(void *, int); |
162 | static int ffb_i2c_initiate_xfer(void *, i2c_addr_t, int); | | 162 | static int ffb_i2c_initiate_xfer(void *, i2c_addr_t, int); |
163 | static int ffb_i2c_read_byte(void *, uint8_t *, int); | | 163 | static int ffb_i2c_read_byte(void *, uint8_t *, int); |
164 | static int ffb_i2c_write_byte(void *, uint8_t, int); | | 164 | static int ffb_i2c_write_byte(void *, uint8_t, int); |
165 | | | 165 | |
166 | /* I2C bitbang glue */ | | 166 | /* I2C bitbang glue */ |
167 | static void ffb_i2cbb_set_bits(void *, uint32_t); | | 167 | static void ffb_i2cbb_set_bits(void *, uint32_t); |
168 | static void ffb_i2cbb_set_dir(void *, uint32_t); | | 168 | static void ffb_i2cbb_set_dir(void *, uint32_t); |
169 | static uint32_t ffb_i2cbb_read(void *); | | 169 | static uint32_t ffb_i2cbb_read(void *); |
170 | | | 170 | |
171 | static const struct i2c_bitbang_ops ffb_i2cbb_ops = { | | 171 | static const struct i2c_bitbang_ops ffb_i2cbb_ops = { |
172 | ffb_i2cbb_set_bits, | | 172 | ffb_i2cbb_set_bits, |
173 | ffb_i2cbb_set_dir, | | 173 | ffb_i2cbb_set_dir, |
174 | ffb_i2cbb_read, | | 174 | ffb_i2cbb_read, |
175 | { | | 175 | { |
176 | FFB_DAC_CFG_MPDATA_SDA, | | 176 | FFB_DAC_CFG_MPDATA_SDA, |
177 | FFB_DAC_CFG_MPDATA_SCL, | | 177 | FFB_DAC_CFG_MPDATA_SCL, |
178 | 0, | | 178 | 0, |
179 | 0 | | 179 | 0 |
180 | } | | 180 | } |
181 | }; | | 181 | }; |
182 | | | 182 | |
183 | void ffb_attach_i2c(struct ffb_softc *); | | 183 | void ffb_attach_i2c(struct ffb_softc *); |
184 | | | 184 | |
185 | /* Video mode setting */ | | 185 | /* Video mode setting */ |
186 | int ffb_tgc_disable(struct ffb_softc *); | | 186 | int ffb_tgc_disable(struct ffb_softc *); |
187 | void ffb_get_pclk(int, uint32_t *, int *); | | 187 | void ffb_get_pclk(int, uint32_t *, int *); |
188 | int ffb_set_vmode(struct ffb_softc *, struct videomode *, int, int *, int *); | | 188 | int ffb_set_vmode(struct ffb_softc *, struct videomode *, int, int *, int *); |
189 | | | 189 | |
190 | | | 190 | |
191 | void | | 191 | void |
192 | ffb_attach(device_t self) | | 192 | ffb_attach(device_t self) |
193 | { | | 193 | { |
194 | struct ffb_softc *sc = device_private(self); | | 194 | struct ffb_softc *sc = device_private(self); |
195 | struct wsemuldisplaydev_attach_args waa; | | 195 | struct wsemuldisplaydev_attach_args waa; |
196 | struct rasops_info *ri; | | 196 | struct rasops_info *ri; |
197 | long defattr; | | 197 | long defattr; |
198 | const char *model, *out_dev; | | 198 | const char *model, *out_dev; |
199 | int btype; | | 199 | int btype; |
200 | uint32_t dac; | | 200 | uint32_t dac; |
201 | int maxrow; | | 201 | int maxrow; |
202 | u_int blank = WSDISPLAYIO_VIDEO_ON; | | 202 | u_int blank = WSDISPLAYIO_VIDEO_ON; |
203 | char buf[6+1]; | | 203 | char buf[6+1]; |
204 | int i, try_edid; | | 204 | int i, try_edid; |
205 | prop_data_t data; | | 205 | prop_data_t data; |
206 | | | 206 | |
207 | printf(":"); | | 207 | printf(":"); |
208 | | | 208 | |
209 | if (sc->sc_type == FFB_CREATOR) { | | 209 | if (sc->sc_type == FFB_CREATOR) { |
210 | btype = prom_getpropint(sc->sc_node, "board_type", 0); | | 210 | btype = prom_getpropint(sc->sc_node, "board_type", 0); |
211 | if ((btype & 7) == 3) | | 211 | if ((btype & 7) == 3) |
212 | printf(" Creator3D"); | | 212 | printf(" Creator3D"); |
213 | else | | 213 | else |
214 | printf(" Creator"); | | 214 | printf(" Creator"); |
215 | } else { | | 215 | } else { |
216 | printf(" Elite3D"); | | 216 | printf(" Elite3D"); |
217 | btype = 0; | | 217 | btype = 0; |
218 | } | | 218 | } |
219 | | | 219 | |
220 | model = prom_getpropstring(sc->sc_node, "model"); | | 220 | model = prom_getpropstring(sc->sc_node, "model"); |
221 | if (model == NULL || strlen(model) == 0) | | 221 | if (model == NULL || strlen(model) == 0) |
222 | model = "unknown"; | | 222 | model = "unknown"; |
223 | | | 223 | |
224 | sc->sc_depth = 24; | | 224 | sc->sc_depth = 24; |
225 | sc->sc_linebytes = 8192; | | 225 | sc->sc_linebytes = 8192; |
226 | /* We might alter these during EDID mode setting */ | | 226 | /* We might alter these during EDID mode setting */ |
227 | sc->sc_height = prom_getpropint(sc->sc_node, "height", 0); | | 227 | sc->sc_height = prom_getpropint(sc->sc_node, "height", 0); |
228 | sc->sc_width = prom_getpropint(sc->sc_node, "width", 0); | | 228 | sc->sc_width = prom_getpropint(sc->sc_node, "width", 0); |
229 | | | 229 | |
230 | sc->sc_locked = 0; | | 230 | sc->sc_locked = 0; |
231 | sc->sc_mode = WSDISPLAYIO_MODE_EMUL; | | 231 | sc->sc_mode = WSDISPLAYIO_MODE_EMUL; |
232 | | | 232 | |
233 | maxrow = (prom_getoption("screen-#rows", buf, sizeof buf) != 0) | | 233 | maxrow = (prom_getoption("screen-#rows", buf, sizeof buf) != 0) |
234 | ? strtoul(buf, NULL, 10) | | 234 | ? strtoul(buf, NULL, 10) |
235 | : 34; | | 235 | : 34; |
236 | | | 236 | |
237 | /* collect DAC version, as Elite3D cursor enable bit is reversed */ | | 237 | /* collect DAC version, as Elite3D cursor enable bit is reversed */ |
238 | DAC_WRITE(sc, FFB_DAC_TYPE, FFB_DAC_DEVID); | | 238 | DAC_WRITE(sc, FFB_DAC_TYPE, FFB_DAC_DEVID); |
239 | dac = DAC_READ(sc, FFB_DAC_VALUE); | | 239 | dac = DAC_READ(sc, FFB_DAC_VALUE); |
240 | sc->sc_dacrev = (dac >> 28) & 0xf; | | 240 | sc->sc_dacrev = (dac >> 28) & 0xf; |
241 | | | 241 | |
242 | if (sc->sc_type == FFB_AFB) { | | 242 | if (sc->sc_type == FFB_AFB) { |
243 | sc->sc_dacrev = 10; | | 243 | sc->sc_dacrev = 10; |
244 | sc->sc_needredraw = 0; | | 244 | sc->sc_needredraw = 0; |
245 | } else { | | 245 | } else { |
246 | /* see what kind of DAC we have */ | | 246 | /* see what kind of DAC we have */ |
247 | int pnum = (dac & 0x0ffff000) >> 12; | | 247 | int pnum = (dac & 0x0ffff000) >> 12; |
248 | if (pnum == 0x236e) { | | 248 | if (pnum == 0x236e) { |
249 | sc->sc_needredraw = 0; | | 249 | sc->sc_needredraw = 0; |
250 | } else { | | 250 | } else { |
251 | sc->sc_needredraw = 1; | | 251 | sc->sc_needredraw = 1; |
252 | } | | 252 | } |
253 | } | | 253 | } |
254 | printf(", model %s, dac %u\n", model, sc->sc_dacrev); | | 254 | printf(", model %s, dac %u\n", model, sc->sc_dacrev); |
255 | if (sc->sc_needredraw) | | 255 | if (sc->sc_needredraw) |
256 | printf("%s: found old DAC, enabling redraw on unblank\n", | | 256 | printf("%s: found old DAC, enabling redraw on unblank\n", |
257 | device_xname(sc->sc_dev)); | | 257 | device_xname(sc->sc_dev)); |
258 | | | 258 | |
259 | /* Check if a console resolution "<device>:r<res>" is set. */ | | 259 | /* Check if a console resolution "<device>:r<res>" is set. */ |
260 | if (sc->sc_console) { | | 260 | if (sc->sc_console) { |
261 | out_dev = prom_getpropstring(sc->sc_node, "output-device"); | | 261 | out_dev = prom_getpropstring(sc->sc_node, "output-device"); |
262 | if (out_dev != NULL && strlen(out_dev) != 0 && | | 262 | if (out_dev != NULL && strlen(out_dev) != 0 && |
263 | strstr(out_dev, ":r") != NULL) | | 263 | strstr(out_dev, ":r") != NULL) |
264 | try_edid = 0; | | 264 | try_edid = 0; |
265 | else | | 265 | else |
266 | try_edid = 1; | | 266 | try_edid = 1; |
267 | } else | | 267 | } else |
268 | try_edid = 1; | | 268 | try_edid = 1; |
269 | | | 269 | |
270 | #if FFB_DEBUG > 0 | | 270 | #if FFB_DEBUG > 0 |
271 | DAC_WRITE(sc, FFB_DAC_TYPE, FFB_DAC_TGC); | | 271 | DAC_WRITE(sc, FFB_DAC_TYPE, FFB_DAC_TGC); |
272 | printf("tgc: %08x\n", DAC_READ(sc, FFB_DAC_VALUE)); | | 272 | printf("tgc: %08x\n", DAC_READ(sc, FFB_DAC_VALUE)); |
273 | DAC_WRITE(sc, FFB_DAC_TYPE, FFB_DAC_DAC_CTRL); | | 273 | DAC_WRITE(sc, FFB_DAC_TYPE, FFB_DAC_DAC_CTRL); |
274 | printf("dcl: %08x\n", DAC_READ(sc, FFB_DAC_VALUE)); | | 274 | printf("dcl: %08x\n", DAC_READ(sc, FFB_DAC_VALUE)); |
275 | #endif | | 275 | #endif |
276 | ffb_attach_i2c(sc); | | 276 | ffb_attach_i2c(sc); |
277 | | | 277 | |
278 | /* Need to set asynchronous blank during DDC write/read */ | | 278 | /* Need to set asynchronous blank during DDC write/read */ |
279 | DAC_WRITE(sc, FFB_DAC_TYPE, FFB_DAC_USR_CTRL); | | 279 | DAC_WRITE(sc, FFB_DAC_TYPE, FFB_DAC_USR_CTRL); |
280 | dac = DAC_READ(sc, FFB_DAC_VALUE); | | 280 | dac = DAC_READ(sc, FFB_DAC_VALUE); |
281 | DAC_WRITE(sc, FFB_DAC_TYPE, FFB_DAC_USR_CTRL); | | 281 | DAC_WRITE(sc, FFB_DAC_TYPE, FFB_DAC_USR_CTRL); |
282 | DAC_WRITE(sc, FFB_DAC_VALUE, dac | FFB_DAC_USR_CTRL_BLANK); | | 282 | DAC_WRITE(sc, FFB_DAC_VALUE, dac | FFB_DAC_USR_CTRL_BLANK); |
283 | | | 283 | |
284 | /* Some monitors don't respond first time */ | | 284 | /* Some monitors don't respond first time */ |
285 | i = 0; | | 285 | i = 0; |
286 | while (sc->sc_edid_data[1] == 0 && i++ < 3) | | 286 | while (sc->sc_edid_data[1] == 0 && i++ < 3) |
287 | ddc_read_edid(&sc->sc_i2c, sc->sc_edid_data, EDID_DATA_LEN); | | 287 | ddc_read_edid(&sc->sc_i2c, sc->sc_edid_data, EDID_DATA_LEN); |
288 | | | 288 | |
289 | /* Remove asynchronous blank */ | | 289 | /* Remove asynchronous blank */ |
290 | DAC_WRITE(sc, FFB_DAC_TYPE, FFB_DAC_USR_CTRL); | | 290 | DAC_WRITE(sc, FFB_DAC_TYPE, FFB_DAC_USR_CTRL); |
291 | DAC_WRITE(sc, FFB_DAC_VALUE, dac); | | 291 | DAC_WRITE(sc, FFB_DAC_VALUE, dac); |
292 | | | 292 | |
293 | if (edid_parse(&sc->sc_edid_data[0], &sc->sc_edid_info) != -1) { | | 293 | if (edid_parse(&sc->sc_edid_data[0], &sc->sc_edid_info) != -1) { |
294 | sort_modes(sc->sc_edid_info.edid_modes, | | 294 | sort_modes(sc->sc_edid_info.edid_modes, |
295 | &sc->sc_edid_info.edid_preferred_mode, | | 295 | &sc->sc_edid_info.edid_preferred_mode, |
296 | sc->sc_edid_info.edid_nmodes); | | 296 | sc->sc_edid_info.edid_nmodes); |
297 | DPRINTF(("%s: EDID data:\n ", device_xname(sc->sc_dev))); | | 297 | DPRINTF(("%s: EDID data:\n ", device_xname(sc->sc_dev))); |
298 | for (i = 0; i < EDID_DATA_LEN; i++) { | | 298 | for (i = 0; i < EDID_DATA_LEN; i++) { |
299 | if (i && !(i % 32)) | | 299 | if (i && !(i % 32)) |
300 | DPRINTF(("\n ")); | | 300 | DPRINTF(("\n ")); |
301 | if (i && !(i % 4)) | | 301 | if (i && !(i % 4)) |
302 | DPRINTF((" ")); | | 302 | DPRINTF((" ")); |
303 | DPRINTF(("%02x", sc->sc_edid_data[i])); | | 303 | DPRINTF(("%02x", sc->sc_edid_data[i])); |
304 | } | | 304 | } |
305 | DPRINTF(("\n")); | | 305 | DPRINTF(("\n")); |
306 | if (ffb_debug) | | 306 | if (ffb_debug) |
307 | edid_print(&sc->sc_edid_info); | | 307 | edid_print(&sc->sc_edid_info); |
308 | | | 308 | |
309 | data = prop_data_create_data(sc->sc_edid_data, EDID_DATA_LEN); | | 309 | data = prop_data_create_copy(sc->sc_edid_data, EDID_DATA_LEN); |
310 | prop_dictionary_set(device_properties(self), "EDID", data); | | 310 | prop_dictionary_set(device_properties(self), "EDID", data); |
311 | prop_object_release(data); | | 311 | prop_object_release(data); |
312 | | | 312 | |
313 | if (try_edid) | | 313 | if (try_edid) |
314 | for (i = 0; i < sc->sc_edid_info.edid_nmodes; i++) { | | 314 | for (i = 0; i < sc->sc_edid_info.edid_nmodes; i++) { |
315 | if (ffb_set_vmode(sc, | | 315 | if (ffb_set_vmode(sc, |
316 | &(sc->sc_edid_info.edid_modes[i]), btype, | | 316 | &(sc->sc_edid_info.edid_modes[i]), btype, |
317 | &(sc->sc_width), &(sc->sc_height))) | | 317 | &(sc->sc_width), &(sc->sc_height))) |
318 | break; | | 318 | break; |
319 | } | | 319 | } |
320 | } else { | | 320 | } else { |
321 | DPRINTF(("%s: No EDID data.\n", device_xname(sc->sc_dev))); | | 321 | DPRINTF(("%s: No EDID data.\n", device_xname(sc->sc_dev))); |
322 | } | | 322 | } |
323 | | | 323 | |
324 | ffb_ras_init(sc); | | 324 | ffb_ras_init(sc); |
325 | | | 325 | |
326 | ffb_blank(sc, WSDISPLAYIO_SVIDEO, &blank); | | 326 | ffb_blank(sc, WSDISPLAYIO_SVIDEO, &blank); |
327 | | | 327 | |
328 | sc->sc_accel = ((device_cfdata(sc->sc_dev)->cf_flags & | | 328 | sc->sc_accel = ((device_cfdata(sc->sc_dev)->cf_flags & |
329 | FFB_CFFLAG_NOACCEL) == 0); | | 329 | FFB_CFFLAG_NOACCEL) == 0); |
330 | | | 330 | |
331 | wsfont_init(); | | 331 | wsfont_init(); |
332 | | | 332 | |
333 | vcons_init(&sc->vd, sc, &ffb_stdscreen, &ffb_accessops); | | 333 | vcons_init(&sc->vd, sc, &ffb_stdscreen, &ffb_accessops); |
334 | sc->vd.init_screen = ffb_init_screen; | | 334 | sc->vd.init_screen = ffb_init_screen; |
335 | ri = &ffb_console_screen.scr_ri; | | 335 | ri = &ffb_console_screen.scr_ri; |
336 | | | 336 | |
337 | /* we mess with ffb_console_screen only once */ | | 337 | /* we mess with ffb_console_screen only once */ |
338 | if (sc->sc_console) { | | 338 | if (sc->sc_console) { |
339 | ffb_console_screen.scr_flags = VCONS_SCREEN_IS_STATIC; | | 339 | ffb_console_screen.scr_flags = VCONS_SCREEN_IS_STATIC; |
340 | vcons_init_screen(&sc->vd, &ffb_console_screen, 1, &defattr); | | 340 | vcons_init_screen(&sc->vd, &ffb_console_screen, 1, &defattr); |
341 | SCREEN_VISIBLE((&ffb_console_screen)); | | 341 | SCREEN_VISIBLE((&ffb_console_screen)); |
342 | /* | | 342 | /* |
343 | * XXX we shouldn't use a global variable for the console | | 343 | * XXX we shouldn't use a global variable for the console |
344 | * screen | | 344 | * screen |
345 | */ | | 345 | */ |
346 | sc->vd.active = &ffb_console_screen; | | 346 | sc->vd.active = &ffb_console_screen; |
347 | } else { | | 347 | } else { |
348 | if (ffb_console_screen.scr_ri.ri_rows == 0) { | | 348 | if (ffb_console_screen.scr_ri.ri_rows == 0) { |
349 | /* do some minimal setup to avoid weirdnesses later */ | | 349 | /* do some minimal setup to avoid weirdnesses later */ |
350 | vcons_init_screen(&sc->vd, &ffb_console_screen, 1, &defattr); | | 350 | vcons_init_screen(&sc->vd, &ffb_console_screen, 1, &defattr); |
351 | } else | | 351 | } else |
352 | (*ri->ri_ops.allocattr)(ri, 0, 0, 0, &defattr); | | 352 | (*ri->ri_ops.allocattr)(ri, 0, 0, 0, &defattr); |
353 | } | | 353 | } |
354 | | | 354 | |
355 | ffb_stdscreen.nrows = ri->ri_rows; | | 355 | ffb_stdscreen.nrows = ri->ri_rows; |
356 | ffb_stdscreen.ncols = ri->ri_cols; | | 356 | ffb_stdscreen.ncols = ri->ri_cols; |
357 | ffb_stdscreen.textops = &ri->ri_ops; | | 357 | ffb_stdscreen.textops = &ri->ri_ops; |
358 | | | 358 | |
359 | sc->sc_fb.fb_driver = &ffb_fbdriver; | | 359 | sc->sc_fb.fb_driver = &ffb_fbdriver; |
360 | sc->sc_fb.fb_type.fb_cmsize = 0; | | 360 | sc->sc_fb.fb_type.fb_cmsize = 0; |
361 | sc->sc_fb.fb_type.fb_size = maxrow * sc->sc_linebytes; | | 361 | sc->sc_fb.fb_type.fb_size = maxrow * sc->sc_linebytes; |
362 | sc->sc_fb.fb_type.fb_type = FBTYPE_CREATOR; | | 362 | sc->sc_fb.fb_type.fb_type = FBTYPE_CREATOR; |
363 | sc->sc_fb.fb_type.fb_width = sc->sc_width; | | 363 | sc->sc_fb.fb_type.fb_width = sc->sc_width; |
364 | sc->sc_fb.fb_type.fb_depth = sc->sc_depth; | | 364 | sc->sc_fb.fb_type.fb_depth = sc->sc_depth; |
365 | sc->sc_fb.fb_type.fb_height = sc->sc_height; | | 365 | sc->sc_fb.fb_type.fb_height = sc->sc_height; |
366 | sc->sc_fb.fb_device = sc->sc_dev; | | 366 | sc->sc_fb.fb_device = sc->sc_dev; |
367 | fb_attach(&sc->sc_fb, sc->sc_console); | | 367 | fb_attach(&sc->sc_fb, sc->sc_console); |
368 | | | 368 | |
369 | ffb_clearscreen(sc); | | 369 | ffb_clearscreen(sc); |
370 | | | 370 | |
371 | if (sc->sc_console) { | | 371 | if (sc->sc_console) { |
372 | wsdisplay_cnattach(&ffb_stdscreen, ri, 0, 0, defattr); | | 372 | wsdisplay_cnattach(&ffb_stdscreen, ri, 0, 0, defattr); |
373 | vcons_replay_msgbuf(&ffb_console_screen); | | 373 | vcons_replay_msgbuf(&ffb_console_screen); |
374 | } | | 374 | } |
375 | | | 375 | |
376 | waa.console = sc->sc_console; | | 376 | waa.console = sc->sc_console; |
377 | waa.scrdata = &ffb_screenlist; | | 377 | waa.scrdata = &ffb_screenlist; |
378 | waa.accessops = &ffb_accessops; | | 378 | waa.accessops = &ffb_accessops; |
379 | waa.accesscookie = &sc->vd; | | 379 | waa.accesscookie = &sc->vd; |
380 | config_found(sc->sc_dev, &waa, wsemuldisplaydevprint); | | 380 | config_found(sc->sc_dev, &waa, wsemuldisplaydevprint); |
381 | } | | 381 | } |
382 | | | 382 | |
383 | void | | 383 | void |
384 | ffb_attach_i2c(struct ffb_softc *sc) | | 384 | ffb_attach_i2c(struct ffb_softc *sc) |
385 | { | | 385 | { |
386 | | | 386 | |
387 | /* Fill in the i2c tag */ | | 387 | /* Fill in the i2c tag */ |
388 | iic_tag_init(&sc->sc_i2c); | | 388 | iic_tag_init(&sc->sc_i2c); |
389 | sc->sc_i2c.ic_cookie = sc; | | 389 | sc->sc_i2c.ic_cookie = sc; |
390 | sc->sc_i2c.ic_send_start = ffb_i2c_send_start; | | 390 | sc->sc_i2c.ic_send_start = ffb_i2c_send_start; |
391 | sc->sc_i2c.ic_send_stop = ffb_i2c_send_stop; | | 391 | sc->sc_i2c.ic_send_stop = ffb_i2c_send_stop; |
392 | sc->sc_i2c.ic_initiate_xfer = ffb_i2c_initiate_xfer; | | 392 | sc->sc_i2c.ic_initiate_xfer = ffb_i2c_initiate_xfer; |
393 | sc->sc_i2c.ic_read_byte = ffb_i2c_read_byte; | | 393 | sc->sc_i2c.ic_read_byte = ffb_i2c_read_byte; |
394 | sc->sc_i2c.ic_write_byte = ffb_i2c_write_byte; | | 394 | sc->sc_i2c.ic_write_byte = ffb_i2c_write_byte; |
395 | } | | 395 | } |
396 | | | 396 | |
397 | int | | 397 | int |
398 | ffb_ioctl(void *v, void *vs, u_long cmd, void *data, int flags, struct lwp *l) | | 398 | ffb_ioctl(void *v, void *vs, u_long cmd, void *data, int flags, struct lwp *l) |
399 | { | | 399 | { |
400 | struct vcons_data *vd = v; | | 400 | struct vcons_data *vd = v; |
401 | struct ffb_softc *sc = vd->cookie; | | 401 | struct ffb_softc *sc = vd->cookie; |
402 | struct wsdisplay_fbinfo *wdf; | | 402 | struct wsdisplay_fbinfo *wdf; |
403 | struct vcons_screen *ms = vd->active; | | 403 | struct vcons_screen *ms = vd->active; |
404 | | | 404 | |
405 | DPRINTF(("ffb_ioctl: %s cmd _IO%s%s('%c', %lu)\n", | | 405 | DPRINTF(("ffb_ioctl: %s cmd _IO%s%s('%c', %lu)\n", |
406 | device_xname(sc->sc_dev), | | 406 | device_xname(sc->sc_dev), |
407 | (cmd & IOC_IN) ? "W" : "", (cmd & IOC_OUT) ? "R" : "", | | 407 | (cmd & IOC_IN) ? "W" : "", (cmd & IOC_OUT) ? "R" : "", |
408 | (char)IOCGROUP(cmd), cmd & 0xff)); | | 408 | (char)IOCGROUP(cmd), cmd & 0xff)); |
409 | | | 409 | |
410 | switch (cmd) { | | 410 | switch (cmd) { |
411 | case FBIOGTYPE: | | 411 | case FBIOGTYPE: |
412 | *(struct fbtype *)data = sc->sc_fb.fb_type; | | 412 | *(struct fbtype *)data = sc->sc_fb.fb_type; |
413 | break; | | 413 | break; |
414 | case FBIOGATTR: | | 414 | case FBIOGATTR: |
415 | #define fba ((struct fbgattr *)data) | | 415 | #define fba ((struct fbgattr *)data) |
416 | fba->real_type = sc->sc_fb.fb_type.fb_type; | | 416 | fba->real_type = sc->sc_fb.fb_type.fb_type; |
417 | fba->owner = 0; /* XXX ??? */ | | 417 | fba->owner = 0; /* XXX ??? */ |
418 | fba->fbtype = sc->sc_fb.fb_type; | | 418 | fba->fbtype = sc->sc_fb.fb_type; |
419 | fba->sattr.flags = 0; | | 419 | fba->sattr.flags = 0; |
420 | fba->sattr.emu_type = sc->sc_fb.fb_type.fb_type; | | 420 | fba->sattr.emu_type = sc->sc_fb.fb_type.fb_type; |
421 | fba->sattr.dev_specific[0] = -1; | | 421 | fba->sattr.dev_specific[0] = -1; |
422 | fba->emu_types[0] = sc->sc_fb.fb_type.fb_type; | | 422 | fba->emu_types[0] = sc->sc_fb.fb_type.fb_type; |
423 | fba->emu_types[1] = -1; | | 423 | fba->emu_types[1] = -1; |
424 | #undef fba | | 424 | #undef fba |
425 | break; | | 425 | break; |
426 | | | 426 | |
427 | case FBIOGETCMAP: | | 427 | case FBIOGETCMAP: |
428 | case FBIOPUTCMAP: | | 428 | case FBIOPUTCMAP: |
429 | return EIO; | | 429 | return EIO; |
430 | | | 430 | |
431 | case FBIOGVIDEO: | | 431 | case FBIOGVIDEO: |
432 | case FBIOSVIDEO: | | 432 | case FBIOSVIDEO: |
433 | return ffb_blank(sc, cmd == FBIOGVIDEO? | | 433 | return ffb_blank(sc, cmd == FBIOGVIDEO? |
434 | WSDISPLAYIO_GVIDEO : WSDISPLAYIO_SVIDEO, | | 434 | WSDISPLAYIO_GVIDEO : WSDISPLAYIO_SVIDEO, |
435 | (u_int *)data); | | 435 | (u_int *)data); |
436 | break; | | 436 | break; |
437 | case FBIOGCURSOR: | | 437 | case FBIOGCURSOR: |
438 | case FBIOSCURSOR: | | 438 | case FBIOSCURSOR: |
439 | /* the console driver is not using the hardware cursor */ | | 439 | /* the console driver is not using the hardware cursor */ |
440 | break; | | 440 | break; |
441 | case FBIOGCURPOS: | | 441 | case FBIOGCURPOS: |
442 | printf("%s: FBIOGCURPOS not implemented\n", | | 442 | printf("%s: FBIOGCURPOS not implemented\n", |
443 | device_xname(sc->sc_dev)); | | 443 | device_xname(sc->sc_dev)); |
444 | return EIO; | | 444 | return EIO; |
445 | case FBIOSCURPOS: | | 445 | case FBIOSCURPOS: |
446 | printf("%s: FBIOSCURPOS not implemented\n", | | 446 | printf("%s: FBIOSCURPOS not implemented\n", |
447 | device_xname(sc->sc_dev)); | | 447 | device_xname(sc->sc_dev)); |
448 | return EIO; | | 448 | return EIO; |
449 | case FBIOGCURMAX: | | 449 | case FBIOGCURMAX: |
450 | printf("%s: FBIOGCURMAX not implemented\n", | | 450 | printf("%s: FBIOGCURMAX not implemented\n", |
451 | device_xname(sc->sc_dev)); | | 451 | device_xname(sc->sc_dev)); |
452 | return EIO; | | 452 | return EIO; |
453 | | | 453 | |
454 | case WSDISPLAYIO_GTYPE: | | 454 | case WSDISPLAYIO_GTYPE: |
455 | *(u_int *)data = WSDISPLAY_TYPE_SUNFFB; | | 455 | *(u_int *)data = WSDISPLAY_TYPE_SUNFFB; |
456 | break; | | 456 | break; |
457 | case WSDISPLAYIO_SMODE: | | 457 | case WSDISPLAYIO_SMODE: |
458 | { | | 458 | { |
459 | if (sc->sc_mode != *(u_int *)data) { | | 459 | if (sc->sc_mode != *(u_int *)data) { |
460 | sc->sc_mode = *(u_int *)data; | | 460 | sc->sc_mode = *(u_int *)data; |
461 | if ((sc->sc_mode == WSDISPLAYIO_MODE_EMUL) && | | 461 | if ((sc->sc_mode == WSDISPLAYIO_MODE_EMUL) && |
462 | (sc->sc_locked == 0)) { | | 462 | (sc->sc_locked == 0)) { |
463 | ffb_ras_init(sc); | | 463 | ffb_ras_init(sc); |
464 | vcons_redraw_screen(ms); | | 464 | vcons_redraw_screen(ms); |
465 | } else { | | 465 | } else { |
466 | ffb_ras_wait(sc); | | 466 | ffb_ras_wait(sc); |
467 | } | | 467 | } |
468 | } | | 468 | } |
469 | } | | 469 | } |
470 | break; | | 470 | break; |
471 | case WSDISPLAYIO_GINFO: | | 471 | case WSDISPLAYIO_GINFO: |
472 | wdf = (void *)data; | | 472 | wdf = (void *)data; |
473 | wdf->height = sc->sc_height; | | 473 | wdf->height = sc->sc_height; |
474 | wdf->width = sc->sc_width; | | 474 | wdf->width = sc->sc_width; |
475 | wdf->depth = 32; | | 475 | wdf->depth = 32; |
476 | wdf->cmsize = 256; /* XXX */ | | 476 | wdf->cmsize = 256; /* XXX */ |
477 | break; | | 477 | break; |
478 | #ifdef WSDISPLAYIO_LINEBYTES | | 478 | #ifdef WSDISPLAYIO_LINEBYTES |
479 | case WSDISPLAYIO_LINEBYTES: | | 479 | case WSDISPLAYIO_LINEBYTES: |
480 | *(u_int *)data = sc->sc_linebytes; | | 480 | *(u_int *)data = sc->sc_linebytes; |
481 | break; | | 481 | break; |
482 | #endif | | 482 | #endif |
483 | case WSDISPLAYIO_GETCMAP: | | 483 | case WSDISPLAYIO_GETCMAP: |
484 | break;/* XXX */ | | 484 | break;/* XXX */ |
485 | | | 485 | |
486 | case WSDISPLAYIO_PUTCMAP: | | 486 | case WSDISPLAYIO_PUTCMAP: |
487 | break;/* XXX */ | | 487 | break;/* XXX */ |
488 | | | 488 | |
489 | case WSDISPLAYIO_SVIDEO: | | 489 | case WSDISPLAYIO_SVIDEO: |
490 | case WSDISPLAYIO_GVIDEO: | | 490 | case WSDISPLAYIO_GVIDEO: |
491 | return(ffb_blank(sc, cmd, (u_int *)data)); | | 491 | return(ffb_blank(sc, cmd, (u_int *)data)); |
492 | break; | | 492 | break; |
493 | | | 493 | |
494 | case WSDISPLAYIO_GCURPOS: | | 494 | case WSDISPLAYIO_GCURPOS: |
495 | case WSDISPLAYIO_SCURPOS: | | 495 | case WSDISPLAYIO_SCURPOS: |
496 | case WSDISPLAYIO_GCURMAX: | | 496 | case WSDISPLAYIO_GCURMAX: |
497 | case WSDISPLAYIO_GCURSOR: | | 497 | case WSDISPLAYIO_GCURSOR: |
498 | case WSDISPLAYIO_SCURSOR: | | 498 | case WSDISPLAYIO_SCURSOR: |
499 | return EIO; /* not supported yet */ | | 499 | return EIO; /* not supported yet */ |
500 | break; | | 500 | break; |
501 | | | 501 | |
502 | case WSDISPLAYIO_GET_EDID: { | | 502 | case WSDISPLAYIO_GET_EDID: { |
503 | struct wsdisplayio_edid_info *d = data; | | 503 | struct wsdisplayio_edid_info *d = data; |
504 | return wsdisplayio_get_edid(sc->sc_dev, d); | | 504 | return wsdisplayio_get_edid(sc->sc_dev, d); |
505 | } | | 505 | } |
506 | | | 506 | |
507 | case WSDISPLAYIO_GET_FBINFO: { | | 507 | case WSDISPLAYIO_GET_FBINFO: { |
508 | struct wsdisplayio_fbinfo *fbi = data; | | 508 | struct wsdisplayio_fbinfo *fbi = data; |
509 | return wsdisplayio_get_fbinfo(&ms->scr_ri, fbi); | | 509 | return wsdisplayio_get_fbinfo(&ms->scr_ri, fbi); |
510 | } | | 510 | } |
511 | | | 511 | |
512 | default: | | 512 | default: |
513 | return EPASSTHROUGH; | | 513 | return EPASSTHROUGH; |
514 | } | | 514 | } |
515 | | | 515 | |
516 | return (0); | | 516 | return (0); |
517 | } | | 517 | } |
518 | | | 518 | |
519 | /* blank/unblank the screen */ | | 519 | /* blank/unblank the screen */ |
520 | static int | | 520 | static int |
521 | ffb_blank(struct ffb_softc *sc, u_long cmd, u_int *data) | | 521 | ffb_blank(struct ffb_softc *sc, u_long cmd, u_int *data) |
522 | { | | 522 | { |
523 | struct vcons_screen *ms = sc->vd.active; | | 523 | struct vcons_screen *ms = sc->vd.active; |
524 | u_int val; | | 524 | u_int val; |
525 | | | 525 | |
526 | DAC_WRITE(sc, FFB_DAC_TYPE, FFB_DAC_TGC); | | 526 | DAC_WRITE(sc, FFB_DAC_TYPE, FFB_DAC_TGC); |
527 | val = DAC_READ(sc, FFB_DAC_VALUE); | | 527 | val = DAC_READ(sc, FFB_DAC_VALUE); |
528 | | | 528 | |
529 | switch (cmd) { | | 529 | switch (cmd) { |
530 | case WSDISPLAYIO_GVIDEO: | | 530 | case WSDISPLAYIO_GVIDEO: |
531 | *data = val & 1; | | 531 | *data = val & 1; |
532 | return(0); | | 532 | return(0); |
533 | break; | | 533 | break; |
534 | case WSDISPLAYIO_SVIDEO: | | 534 | case WSDISPLAYIO_SVIDEO: |
535 | if (*data == WSDISPLAYIO_VIDEO_OFF) | | 535 | if (*data == WSDISPLAYIO_VIDEO_OFF) |
536 | val &= ~1; | | 536 | val &= ~1; |
537 | else if (*data == WSDISPLAYIO_VIDEO_ON) | | 537 | else if (*data == WSDISPLAYIO_VIDEO_ON) |
538 | val |= 1; | | 538 | val |= 1; |
539 | else | | 539 | else |
540 | return(EINVAL); | | 540 | return(EINVAL); |
541 | break; | | 541 | break; |
542 | default: | | 542 | default: |
543 | return(EINVAL); | | 543 | return(EINVAL); |
544 | } | | 544 | } |
545 | | | 545 | |
546 | DAC_WRITE(sc, FFB_DAC_TYPE, FFB_DAC_TGC); | | 546 | DAC_WRITE(sc, FFB_DAC_TYPE, FFB_DAC_TGC); |
547 | DAC_WRITE(sc, FFB_DAC_VALUE, val); | | 547 | DAC_WRITE(sc, FFB_DAC_VALUE, val); |
548 | | | 548 | |
549 | if ((val & 1) && sc->sc_needredraw) { | | 549 | if ((val & 1) && sc->sc_needredraw) { |
550 | if (ms != NULL) { | | 550 | if (ms != NULL) { |
551 | if ((sc->sc_mode == WSDISPLAYIO_MODE_EMUL) && | | 551 | if ((sc->sc_mode == WSDISPLAYIO_MODE_EMUL) && |
552 | (sc->sc_locked == 0)) { | | 552 | (sc->sc_locked == 0)) { |
553 | ffb_ras_init(sc); | | 553 | ffb_ras_init(sc); |
554 | vcons_redraw_screen(ms); | | 554 | vcons_redraw_screen(ms); |
555 | } | | 555 | } |
556 | } | | 556 | } |
557 | } | | 557 | } |
558 | | | 558 | |
559 | return(0); | | 559 | return(0); |
560 | } | | 560 | } |
561 | | | 561 | |
562 | paddr_t | | 562 | paddr_t |
563 | ffb_mmap(void *vsc, void *vs, off_t off, int prot) | | 563 | ffb_mmap(void *vsc, void *vs, off_t off, int prot) |
564 | { | | 564 | { |
565 | struct vcons_data *vd = vsc; | | 565 | struct vcons_data *vd = vsc; |
566 | struct ffb_softc *sc = vd->cookie; | | 566 | struct ffb_softc *sc = vd->cookie; |
567 | int i; | | 567 | int i; |
568 | | | 568 | |
569 | switch (sc->sc_mode) { | | 569 | switch (sc->sc_mode) { |
570 | case WSDISPLAYIO_MODE_MAPPED: | | 570 | case WSDISPLAYIO_MODE_MAPPED: |
571 | for (i = 0; i < sc->sc_nreg; i++) { | | 571 | for (i = 0; i < sc->sc_nreg; i++) { |
572 | /* Before this set? */ | | 572 | /* Before this set? */ |
573 | if (off < sc->sc_addrs[i]) | | 573 | if (off < sc->sc_addrs[i]) |
574 | continue; | | 574 | continue; |
575 | /* After this set? */ | | 575 | /* After this set? */ |
576 | if (off >= (sc->sc_addrs[i] + sc->sc_sizes[i])) | | 576 | if (off >= (sc->sc_addrs[i] + sc->sc_sizes[i])) |
577 | continue; | | 577 | continue; |
578 | | | 578 | |
579 | return (bus_space_mmap(sc->sc_bt, sc->sc_addrs[i], | | 579 | return (bus_space_mmap(sc->sc_bt, sc->sc_addrs[i], |
580 | off - sc->sc_addrs[i], prot, BUS_SPACE_MAP_LINEAR)); | | 580 | off - sc->sc_addrs[i], prot, BUS_SPACE_MAP_LINEAR)); |
581 | } | | 581 | } |
582 | break; | | 582 | break; |
583 | #ifdef WSDISPLAYIO_MODE_DUMBFB | | 583 | #ifdef WSDISPLAYIO_MODE_DUMBFB |
584 | case WSDISPLAYIO_MODE_DUMBFB: | | 584 | case WSDISPLAYIO_MODE_DUMBFB: |
585 | if (sc->sc_nreg < FFB_REG_DFB24) | | 585 | if (sc->sc_nreg < FFB_REG_DFB24) |
586 | break; | | 586 | break; |
587 | if (off >= 0 && off < sc->sc_sizes[FFB_REG_DFB24]) | | 587 | if (off >= 0 && off < sc->sc_sizes[FFB_REG_DFB24]) |
588 | return (bus_space_mmap(sc->sc_bt, | | 588 | return (bus_space_mmap(sc->sc_bt, |
589 | sc->sc_addrs[FFB_REG_DFB24], off, prot, | | 589 | sc->sc_addrs[FFB_REG_DFB24], off, prot, |
590 | BUS_SPACE_MAP_LINEAR | BUS_SPACE_MAP_PREFETCHABLE)); | | 590 | BUS_SPACE_MAP_LINEAR | BUS_SPACE_MAP_PREFETCHABLE)); |
591 | break; | | 591 | break; |
592 | #endif | | 592 | #endif |
593 | } | | 593 | } |
594 | return (-1); | | 594 | return (-1); |
595 | } | | 595 | } |
596 | | | 596 | |
597 | void | | 597 | void |
598 | ffb_ras_fifo_wait(struct ffb_softc *sc, int n) | | 598 | ffb_ras_fifo_wait(struct ffb_softc *sc, int n) |
599 | { | | 599 | { |
600 | int32_t cache = sc->sc_fifo_cache; | | 600 | int32_t cache = sc->sc_fifo_cache; |
601 | | | 601 | |
602 | if (cache < n) { | | 602 | if (cache < n) { |
603 | do { | | 603 | do { |
604 | cache = FBC_READ(sc, FFB_FBC_UCSR); | | 604 | cache = FBC_READ(sc, FFB_FBC_UCSR); |
605 | cache = (cache & FBC_UCSR_FIFO_MASK) - 8; | | 605 | cache = (cache & FBC_UCSR_FIFO_MASK) - 8; |
606 | } while (cache < n); | | 606 | } while (cache < n); |
607 | } | | 607 | } |
608 | sc->sc_fifo_cache = cache - n; | | 608 | sc->sc_fifo_cache = cache - n; |
609 | } | | 609 | } |
610 | | | 610 | |
611 | void | | 611 | void |
612 | ffb_ras_wait(struct ffb_softc *sc) | | 612 | ffb_ras_wait(struct ffb_softc *sc) |
613 | { | | 613 | { |
614 | uint32_t ucsr, r; | | 614 | uint32_t ucsr, r; |
615 | | | 615 | |
616 | while (1) { | | 616 | while (1) { |
617 | ucsr = FBC_READ(sc, FFB_FBC_UCSR); | | 617 | ucsr = FBC_READ(sc, FFB_FBC_UCSR); |
618 | if ((ucsr & (FBC_UCSR_FB_BUSY|FBC_UCSR_RP_BUSY)) == 0) | | 618 | if ((ucsr & (FBC_UCSR_FB_BUSY|FBC_UCSR_RP_BUSY)) == 0) |
619 | break; | | 619 | break; |
620 | r = ucsr & (FBC_UCSR_READ_ERR | FBC_UCSR_FIFO_OVFL); | | 620 | r = ucsr & (FBC_UCSR_READ_ERR | FBC_UCSR_FIFO_OVFL); |
621 | if (r != 0) | | 621 | if (r != 0) |
622 | FBC_WRITE(sc, FFB_FBC_UCSR, r); | | 622 | FBC_WRITE(sc, FFB_FBC_UCSR, r); |
623 | } | | 623 | } |
624 | } | | 624 | } |
625 | | | 625 | |
626 | void | | 626 | void |
627 | ffb_ras_init(struct ffb_softc *sc) | | 627 | ffb_ras_init(struct ffb_softc *sc) |
628 | { | | 628 | { |
629 | uint32_t fbc; | | 629 | uint32_t fbc; |
630 | | | 630 | |
631 | if (sc->sc_width > 1280) { | | 631 | if (sc->sc_width > 1280) { |
632 | DPRINTF(("ffb_ras_init: high resolution.\n")); | | 632 | DPRINTF(("ffb_ras_init: high resolution.\n")); |
633 | fbc = FFB_FBC_WM_COMBINED | FFB_FBC_WE_FORCEON | | | 633 | fbc = FFB_FBC_WM_COMBINED | FFB_FBC_WE_FORCEON | |
634 | FFB_FBC_ZE_OFF | FFB_FBC_YE_OFF | FFB_FBC_XE_ON; | | 634 | FFB_FBC_ZE_OFF | FFB_FBC_YE_OFF | FFB_FBC_XE_ON; |
635 | } else { | | 635 | } else { |
636 | DPRINTF(("ffb_ras_init: standard resolution.\n")); | | 636 | DPRINTF(("ffb_ras_init: standard resolution.\n")); |
637 | fbc = FFB_FBC_XE_OFF; | | 637 | fbc = FFB_FBC_XE_OFF; |
638 | } | | 638 | } |
639 | ffb_ras_fifo_wait(sc, 7); | | 639 | ffb_ras_fifo_wait(sc, 7); |
640 | DPRINTF(("WID: %08x\n", FBC_READ(sc, FFB_FBC_WID))); | | 640 | DPRINTF(("WID: %08x\n", FBC_READ(sc, FFB_FBC_WID))); |
641 | FBC_WRITE(sc, FFB_FBC_WID, 0x0); | | 641 | FBC_WRITE(sc, FFB_FBC_WID, 0x0); |
642 | FBC_WRITE(sc, FFB_FBC_PPC, | | 642 | FBC_WRITE(sc, FFB_FBC_PPC, |
643 | FBC_PPC_VCE_DIS | FBC_PPC_TBE_OPAQUE | FBC_PPC_ACE_DIS | | | 643 | FBC_PPC_VCE_DIS | FBC_PPC_TBE_OPAQUE | FBC_PPC_ACE_DIS | |
644 | FBC_PPC_APE_DIS | FBC_PPC_DCE_DIS | FBC_PPC_CS_CONST | | | 644 | FBC_PPC_APE_DIS | FBC_PPC_DCE_DIS | FBC_PPC_CS_CONST | |
645 | FBC_PPC_ABE_DIS | FBC_PPC_XS_WID); | | 645 | FBC_PPC_ABE_DIS | FBC_PPC_XS_WID); |
646 | | | 646 | |
647 | fbc |= FFB_FBC_WB_A | FFB_FBC_RB_A | FFB_FBC_SB_BOTH | | | 647 | fbc |= FFB_FBC_WB_A | FFB_FBC_RB_A | FFB_FBC_SB_BOTH | |
648 | FFB_FBC_RGBE_MASK; | | 648 | FFB_FBC_RGBE_MASK; |
649 | DPRINTF(("%s: fbc is %08x\n", __func__, fbc)); | | 649 | DPRINTF(("%s: fbc is %08x\n", __func__, fbc)); |
650 | FBC_WRITE(sc, FFB_FBC_FBC, fbc); | | 650 | FBC_WRITE(sc, FFB_FBC_FBC, fbc); |
651 | FBC_WRITE(sc, FFB_FBC_ROP, FBC_ROP_NEW); | | 651 | FBC_WRITE(sc, FFB_FBC_ROP, FBC_ROP_NEW); |
652 | FBC_WRITE(sc, FFB_FBC_DRAWOP, FBC_DRAWOP_RECTANGLE); | | 652 | FBC_WRITE(sc, FFB_FBC_DRAWOP, FBC_DRAWOP_RECTANGLE); |
653 | FBC_WRITE(sc, FFB_FBC_PMASK, 0xffffffff); | | 653 | FBC_WRITE(sc, FFB_FBC_PMASK, 0xffffffff); |
654 | FBC_WRITE(sc, FFB_FBC_FONTINC, 0x10000); | | 654 | FBC_WRITE(sc, FFB_FBC_FONTINC, 0x10000); |
655 | ffb_ras_fifo_wait(sc, 5); | | 655 | ffb_ras_fifo_wait(sc, 5); |
656 | sc->sc_fg_cache = 0; | | 656 | sc->sc_fg_cache = 0; |
657 | FBC_WRITE(sc, FFB_FBC_FG, sc->sc_fg_cache); | | 657 | FBC_WRITE(sc, FFB_FBC_FG, sc->sc_fg_cache); |
658 | sc->sc_bg_cache = 0; | | 658 | sc->sc_bg_cache = 0; |
659 | FBC_WRITE(sc, FFB_FBC_BG, sc->sc_bg_cache); | | 659 | FBC_WRITE(sc, FFB_FBC_BG, sc->sc_bg_cache); |
660 | FBC_WRITE(sc, FFB_FBC_BLENDC, FFB_BLENDC_FORCE_ONE | | | 660 | FBC_WRITE(sc, FFB_FBC_BLENDC, FFB_BLENDC_FORCE_ONE | |
661 | FFB_BLENDC_DF_ONE_M_A | | | 661 | FFB_BLENDC_DF_ONE_M_A | |
662 | FFB_BLENDC_SF_A); | | 662 | FFB_BLENDC_SF_A); |
663 | FBC_WRITE(sc, FFB_FBC_BLENDC1, 0); | | 663 | FBC_WRITE(sc, FFB_FBC_BLENDC1, 0); |
664 | FBC_WRITE(sc, FFB_FBC_BLENDC2, 0); | | 664 | FBC_WRITE(sc, FFB_FBC_BLENDC2, 0); |
665 | ffb_ras_wait(sc); | | 665 | ffb_ras_wait(sc); |
666 | } | | 666 | } |
667 | | | 667 | |
668 | void | | 668 | void |
669 | ffb_ras_eraserows(void *cookie, int row, int n, long attr) | | 669 | ffb_ras_eraserows(void *cookie, int row, int n, long attr) |
670 | { | | 670 | { |
671 | struct rasops_info *ri = cookie; | | 671 | struct rasops_info *ri = cookie; |
672 | struct vcons_screen *scr = ri->ri_hw; | | 672 | struct vcons_screen *scr = ri->ri_hw; |
673 | struct ffb_softc *sc = scr->scr_cookie; | | 673 | struct ffb_softc *sc = scr->scr_cookie; |
674 | | | 674 | |
675 | if (row < 0) { | | 675 | if (row < 0) { |
676 | n += row; | | 676 | n += row; |
677 | row = 0; | | 677 | row = 0; |
678 | } | | 678 | } |
679 | if (row + n > ri->ri_rows) | | 679 | if (row + n > ri->ri_rows) |
680 | n = ri->ri_rows - row; | | 680 | n = ri->ri_rows - row; |
681 | if (n <= 0) | | 681 | if (n <= 0) |
682 | return; | | 682 | return; |
683 | | | 683 | |
684 | ffb_ras_fill(sc); | | 684 | ffb_ras_fill(sc); |
685 | ffb_ras_setfg(sc, ri->ri_devcmap[(attr >> 16) & 0xf]); | | 685 | ffb_ras_setfg(sc, ri->ri_devcmap[(attr >> 16) & 0xf]); |
686 | ffb_ras_fifo_wait(sc, 4); | | 686 | ffb_ras_fifo_wait(sc, 4); |
687 | if ((n == ri->ri_rows) && (ri->ri_flg & RI_FULLCLEAR)) { | | 687 | if ((n == ri->ri_rows) && (ri->ri_flg & RI_FULLCLEAR)) { |
688 | FBC_WRITE(sc, FFB_FBC_BY, 0); | | 688 | FBC_WRITE(sc, FFB_FBC_BY, 0); |
689 | FBC_WRITE(sc, FFB_FBC_BX, 0); | | 689 | FBC_WRITE(sc, FFB_FBC_BX, 0); |
690 | FBC_WRITE(sc, FFB_FBC_BH, ri->ri_height); | | 690 | FBC_WRITE(sc, FFB_FBC_BH, ri->ri_height); |
691 | FBC_WRITE(sc, FFB_FBC_BW, ri->ri_width); | | 691 | FBC_WRITE(sc, FFB_FBC_BW, ri->ri_width); |
692 | ri->ri_flg &= ~RI_CURSOR; | | 692 | ri->ri_flg &= ~RI_CURSOR; |
693 | } else { | | 693 | } else { |
694 | row *= ri->ri_font->fontheight; | | 694 | row *= ri->ri_font->fontheight; |
695 | FBC_WRITE(sc, FFB_FBC_BY, ri->ri_yorigin + row); | | 695 | FBC_WRITE(sc, FFB_FBC_BY, ri->ri_yorigin + row); |
696 | FBC_WRITE(sc, FFB_FBC_BX, ri->ri_xorigin); | | 696 | FBC_WRITE(sc, FFB_FBC_BX, ri->ri_xorigin); |
697 | FBC_WRITE(sc, FFB_FBC_BH, n * ri->ri_font->fontheight); | | 697 | FBC_WRITE(sc, FFB_FBC_BH, n * ri->ri_font->fontheight); |
698 | FBC_WRITE(sc, FFB_FBC_BW, ri->ri_emuwidth); | | 698 | FBC_WRITE(sc, FFB_FBC_BW, ri->ri_emuwidth); |
699 | } | | 699 | } |
700 | SYNC; | | 700 | SYNC; |
701 | } | | 701 | } |
702 | | | 702 | |
703 | void | | 703 | void |
704 | ffb_ras_erasecols(void *cookie, int row, int col, int n, long attr) | | 704 | ffb_ras_erasecols(void *cookie, int row, int col, int n, long attr) |
705 | { | | 705 | { |
706 | struct rasops_info *ri = cookie; | | 706 | struct rasops_info *ri = cookie; |
707 | struct vcons_screen *scr = ri->ri_hw; | | 707 | struct vcons_screen *scr = ri->ri_hw; |
708 | struct ffb_softc *sc = scr->scr_cookie; | | 708 | struct ffb_softc *sc = scr->scr_cookie; |
709 | | | 709 | |
710 | if ((row < 0) || (row >= ri->ri_rows)) | | 710 | if ((row < 0) || (row >= ri->ri_rows)) |
711 | return; | | 711 | return; |
712 | if (col < 0) { | | 712 | if (col < 0) { |
713 | n += col; | | 713 | n += col; |
714 | col = 0; | | 714 | col = 0; |
715 | } | | 715 | } |
716 | if (col + n > ri->ri_cols) | | 716 | if (col + n > ri->ri_cols) |
717 | n = ri->ri_cols - col; | | 717 | n = ri->ri_cols - col; |
718 | if (n <= 0) | | 718 | if (n <= 0) |
719 | return; | | 719 | return; |
720 | | | 720 | |
721 | n *= ri->ri_font->fontwidth; | | 721 | n *= ri->ri_font->fontwidth; |
722 | col *= ri->ri_font->fontwidth; | | 722 | col *= ri->ri_font->fontwidth; |
723 | row *= ri->ri_font->fontheight; | | 723 | row *= ri->ri_font->fontheight; |
724 | | | 724 | |
725 | ffb_ras_fill(sc); | | 725 | ffb_ras_fill(sc); |
726 | ffb_ras_setfg(sc, ri->ri_devcmap[(attr >> 16) & 0xf]); | | 726 | ffb_ras_setfg(sc, ri->ri_devcmap[(attr >> 16) & 0xf]); |
727 | ffb_ras_fifo_wait(sc, 4); | | 727 | ffb_ras_fifo_wait(sc, 4); |
728 | FBC_WRITE(sc, FFB_FBC_BY, ri->ri_yorigin + row); | | 728 | FBC_WRITE(sc, FFB_FBC_BY, ri->ri_yorigin + row); |
729 | FBC_WRITE(sc, FFB_FBC_BX, ri->ri_xorigin + col); | | 729 | FBC_WRITE(sc, FFB_FBC_BX, ri->ri_xorigin + col); |
730 | FBC_WRITE(sc, FFB_FBC_BH, ri->ri_font->fontheight); | | 730 | FBC_WRITE(sc, FFB_FBC_BH, ri->ri_font->fontheight); |
731 | FBC_WRITE(sc, FFB_FBC_BW, n); | | 731 | FBC_WRITE(sc, FFB_FBC_BW, n); |
732 | SYNC; | | 732 | SYNC; |
733 | } | | 733 | } |
734 | | | 734 | |
735 | void | | 735 | void |
736 | ffb_ras_fill(struct ffb_softc *sc) | | 736 | ffb_ras_fill(struct ffb_softc *sc) |
737 | { | | 737 | { |
738 | ffb_ras_fifo_wait(sc, 3); | | 738 | ffb_ras_fifo_wait(sc, 3); |
739 | FBC_WRITE(sc, FFB_FBC_PPC, | | 739 | FBC_WRITE(sc, FFB_FBC_PPC, |
740 | FBC_PPC_VCE_DIS | FBC_PPC_TBE_OPAQUE | FBC_PPC_ACE_DIS | | | 740 | FBC_PPC_VCE_DIS | FBC_PPC_TBE_OPAQUE | FBC_PPC_ACE_DIS | |
741 | FBC_PPC_APE_DIS | FBC_PPC_DCE_DIS | FBC_PPC_CS_CONST | | | 741 | FBC_PPC_APE_DIS | FBC_PPC_DCE_DIS | FBC_PPC_CS_CONST | |
742 | FBC_PPC_ABE_DIS | FBC_PPC_XS_WID); | | 742 | FBC_PPC_ABE_DIS | FBC_PPC_XS_WID); |
743 | FBC_WRITE(sc, FFB_FBC_ROP, FBC_ROP_NEW); | | 743 | FBC_WRITE(sc, FFB_FBC_ROP, FBC_ROP_NEW); |
744 | FBC_WRITE(sc, FFB_FBC_DRAWOP, FBC_DRAWOP_RECTANGLE); | | 744 | FBC_WRITE(sc, FFB_FBC_DRAWOP, FBC_DRAWOP_RECTANGLE); |
745 | SYNC; | | 745 | SYNC; |
746 | } | | 746 | } |
747 | | | 747 | |
748 | void | | 748 | void |
749 | ffb_ras_invert(struct ffb_softc *sc) | | 749 | ffb_ras_invert(struct ffb_softc *sc) |
750 | { | | 750 | { |
751 | ffb_ras_fifo_wait(sc, 3); | | 751 | ffb_ras_fifo_wait(sc, 3); |
752 | FBC_WRITE(sc, FFB_FBC_PPC, | | 752 | FBC_WRITE(sc, FFB_FBC_PPC, |
753 | FBC_PPC_VCE_DIS | FBC_PPC_TBE_OPAQUE | FBC_PPC_ACE_DIS | | | 753 | FBC_PPC_VCE_DIS | FBC_PPC_TBE_OPAQUE | FBC_PPC_ACE_DIS | |
754 | FBC_PPC_APE_DIS | FBC_PPC_DCE_DIS | FBC_PPC_CS_CONST | | | 754 | FBC_PPC_APE_DIS | FBC_PPC_DCE_DIS | FBC_PPC_CS_CONST | |
755 | FBC_PPC_ABE_DIS | FBC_PPC_XS_WID); | | 755 | FBC_PPC_ABE_DIS | FBC_PPC_XS_WID); |
756 | FBC_WRITE(sc, FFB_FBC_ROP, FBC_ROP_INVERT); | | 756 | FBC_WRITE(sc, FFB_FBC_ROP, FBC_ROP_INVERT); |
757 | FBC_WRITE(sc, FFB_FBC_DRAWOP, FBC_DRAWOP_RECTANGLE); | | 757 | FBC_WRITE(sc, FFB_FBC_DRAWOP, FBC_DRAWOP_RECTANGLE); |
758 | SYNC; | | 758 | SYNC; |
759 | } | | 759 | } |
760 | | | 760 | |
761 | void | | 761 | void |
762 | ffb_ras_copyrows(void *cookie, int src, int dst, int n) | | 762 | ffb_ras_copyrows(void *cookie, int src, int dst, int n) |
763 | { | | 763 | { |
764 | struct rasops_info *ri = cookie; | | 764 | struct rasops_info *ri = cookie; |
765 | struct vcons_screen *scr = ri->ri_hw; | | 765 | struct vcons_screen *scr = ri->ri_hw; |
766 | struct ffb_softc *sc = scr->scr_cookie; | | 766 | struct ffb_softc *sc = scr->scr_cookie; |
767 | | | 767 | |
768 | if (dst == src) | | 768 | if (dst == src) |
769 | return; | | 769 | return; |
770 | if (src < 0) { | | 770 | if (src < 0) { |
771 | n += src; | | 771 | n += src; |
772 | src = 0; | | 772 | src = 0; |
773 | } | | 773 | } |
774 | if ((src + n) > ri->ri_rows) | | 774 | if ((src + n) > ri->ri_rows) |
775 | n = ri->ri_rows - src; | | 775 | n = ri->ri_rows - src; |
776 | if (dst < 0) { | | 776 | if (dst < 0) { |
777 | n += dst; | | 777 | n += dst; |
778 | dst = 0; | | 778 | dst = 0; |
779 | } | | 779 | } |
780 | if ((dst + n) > ri->ri_rows) | | 780 | if ((dst + n) > ri->ri_rows) |
781 | n = ri->ri_rows - dst; | | 781 | n = ri->ri_rows - dst; |
782 | if (n <= 0) | | 782 | if (n <= 0) |
783 | return; | | 783 | return; |
784 | n *= ri->ri_font->fontheight; | | 784 | n *= ri->ri_font->fontheight; |
785 | src *= ri->ri_font->fontheight; | | 785 | src *= ri->ri_font->fontheight; |
786 | dst *= ri->ri_font->fontheight; | | 786 | dst *= ri->ri_font->fontheight; |
787 | | | 787 | |
788 | ffb_ras_fifo_wait(sc, 9); | | 788 | ffb_ras_fifo_wait(sc, 9); |
789 | FBC_WRITE(sc, FFB_FBC_PPC, | | 789 | FBC_WRITE(sc, FFB_FBC_PPC, |
790 | FBC_PPC_VCE_DIS | FBC_PPC_TBE_OPAQUE | FBC_PPC_ACE_DIS | | | 790 | FBC_PPC_VCE_DIS | FBC_PPC_TBE_OPAQUE | FBC_PPC_ACE_DIS | |
791 | FBC_PPC_APE_DIS | FBC_PPC_DCE_DIS | FBC_PPC_CS_CONST | | | 791 | FBC_PPC_APE_DIS | FBC_PPC_DCE_DIS | FBC_PPC_CS_CONST | |
792 | FBC_PPC_ABE_DIS | FBC_PPC_XS_WID); | | 792 | FBC_PPC_ABE_DIS | FBC_PPC_XS_WID); |
793 | FBC_WRITE(sc, FFB_FBC_ROP, FBC_ROP_OLD | (FBC_ROP_OLD << 8)); | | 793 | FBC_WRITE(sc, FFB_FBC_ROP, FBC_ROP_OLD | (FBC_ROP_OLD << 8)); |
794 | FBC_WRITE(sc, FFB_FBC_DRAWOP, FBC_DRAWOP_VSCROLL); | | 794 | FBC_WRITE(sc, FFB_FBC_DRAWOP, FBC_DRAWOP_VSCROLL); |
795 | FBC_WRITE(sc, FFB_FBC_BY, ri->ri_yorigin + src); | | 795 | FBC_WRITE(sc, FFB_FBC_BY, ri->ri_yorigin + src); |
796 | FBC_WRITE(sc, FFB_FBC_BX, ri->ri_xorigin); | | 796 | FBC_WRITE(sc, FFB_FBC_BX, ri->ri_xorigin); |
797 | FBC_WRITE(sc, FFB_FBC_DY, ri->ri_yorigin + dst); | | 797 | FBC_WRITE(sc, FFB_FBC_DY, ri->ri_yorigin + dst); |
798 | FBC_WRITE(sc, FFB_FBC_DX, ri->ri_xorigin); | | 798 | FBC_WRITE(sc, FFB_FBC_DX, ri->ri_xorigin); |
799 | FBC_WRITE(sc, FFB_FBC_BH, n); | | 799 | FBC_WRITE(sc, FFB_FBC_BH, n); |
800 | FBC_WRITE(sc, FFB_FBC_BW, ri->ri_emuwidth); | | 800 | FBC_WRITE(sc, FFB_FBC_BW, ri->ri_emuwidth); |
801 | SYNC; | | 801 | SYNC; |
802 | } | | 802 | } |
803 | | | 803 | |
804 | static void | | 804 | static void |
805 | ffb_ras_setfg(struct ffb_softc *sc, int32_t fg) | | 805 | ffb_ras_setfg(struct ffb_softc *sc, int32_t fg) |
806 | { | | 806 | { |
807 | ffb_ras_fifo_wait(sc, 1); | | 807 | ffb_ras_fifo_wait(sc, 1); |
808 | if (fg == sc->sc_fg_cache) | | 808 | if (fg == sc->sc_fg_cache) |
809 | return; | | 809 | return; |
810 | sc->sc_fg_cache = fg; | | 810 | sc->sc_fg_cache = fg; |
811 | FBC_WRITE(sc, FFB_FBC_FG, fg); | | 811 | FBC_WRITE(sc, FFB_FBC_FG, fg); |
812 | SYNC; | | 812 | SYNC; |
813 | } | | 813 | } |
814 | | | 814 | |
815 | static void | | 815 | static void |
816 | ffb_ras_setbg(struct ffb_softc *sc, int32_t bg) | | 816 | ffb_ras_setbg(struct ffb_softc *sc, int32_t bg) |
817 | { | | 817 | { |
818 | ffb_ras_fifo_wait(sc, 1); | | 818 | ffb_ras_fifo_wait(sc, 1); |
819 | if (bg == sc->sc_bg_cache) | | 819 | if (bg == sc->sc_bg_cache) |
820 | return; | | 820 | return; |
821 | sc->sc_bg_cache = bg; | | 821 | sc->sc_bg_cache = bg; |
822 | FBC_WRITE(sc, FFB_FBC_BG, bg); | | 822 | FBC_WRITE(sc, FFB_FBC_BG, bg); |
823 | SYNC; | | 823 | SYNC; |
824 | } | | 824 | } |
825 | | | 825 | |
826 | /* frame buffer generic driver support functions */ | | 826 | /* frame buffer generic driver support functions */ |
827 | static void | | 827 | static void |
828 | ffbfb_unblank(device_t dev) | | 828 | ffbfb_unblank(device_t dev) |
829 | { | | 829 | { |
830 | struct ffb_softc *sc = device_private(dev); | | 830 | struct ffb_softc *sc = device_private(dev); |
831 | struct vcons_screen *ms = sc->vd.active; | | 831 | struct vcons_screen *ms = sc->vd.active; |
832 | u_int on = 1; | | 832 | u_int on = 1; |
833 | int redraw = 0; | | 833 | int redraw = 0; |
834 | | | 834 | |
835 | ffb_ras_init(sc); | | 835 | ffb_ras_init(sc); |
836 | if (sc->sc_locked) { | | 836 | if (sc->sc_locked) { |
837 | sc->sc_locked = 0; | | 837 | sc->sc_locked = 0; |
838 | redraw = 1; | | 838 | redraw = 1; |
839 | } | | 839 | } |
840 | | | 840 | |
841 | ffb_blank(sc, WSDISPLAYIO_SVIDEO, &on); | | 841 | ffb_blank(sc, WSDISPLAYIO_SVIDEO, &on); |
842 | #if 0 | | 842 | #if 0 |
843 | if ((sc->vd.active != &ffb_console_screen) && | | 843 | if ((sc->vd.active != &ffb_console_screen) && |
844 | (ffb_console_screen.scr_flags & VCONS_SCREEN_IS_STATIC)) { | | 844 | (ffb_console_screen.scr_flags & VCONS_SCREEN_IS_STATIC)) { |
845 | /* | | 845 | /* |
846 | * force-switch to the console screen. | | 846 | * force-switch to the console screen. |
847 | * Caveat: the higher layer will think we're still on the | | 847 | * Caveat: the higher layer will think we're still on the |
848 | * other screen | | 848 | * other screen |
849 | */ | | 849 | */ |
850 | | | 850 | |
851 | SCREEN_INVISIBLE(sc->vd.active); | | 851 | SCREEN_INVISIBLE(sc->vd.active); |
852 | sc->vd.active = &ffb_console_screen; | | 852 | sc->vd.active = &ffb_console_screen; |
853 | SCREEN_VISIBLE(sc->vd.active); | | 853 | SCREEN_VISIBLE(sc->vd.active); |
854 | ms = sc->vd.active; | | 854 | ms = sc->vd.active; |
855 | redraw = 1; | | 855 | redraw = 1; |
856 | } | | 856 | } |
857 | #endif | | 857 | #endif |
858 | if (redraw) { | | 858 | if (redraw) { |
859 | vcons_redraw_screen(ms); | | 859 | vcons_redraw_screen(ms); |
860 | } | | 860 | } |
861 | } | | 861 | } |
862 | | | 862 | |
863 | int | | 863 | int |
864 | ffbfb_open(dev_t dev, int flags, int mode, struct lwp *l) | | 864 | ffbfb_open(dev_t dev, int flags, int mode, struct lwp *l) |
865 | { | | 865 | { |
866 | struct ffb_softc *sc; | | 866 | struct ffb_softc *sc; |
867 | | | 867 | |
868 | sc = device_lookup_private(&ffb_cd, minor(dev)); | | 868 | sc = device_lookup_private(&ffb_cd, minor(dev)); |
869 | if (sc == NULL) | | 869 | if (sc == NULL) |
870 | return ENXIO; | | 870 | return ENXIO; |
871 | | | 871 | |
872 | sc->sc_locked = 1; | | 872 | sc->sc_locked = 1; |
873 | return 0; | | 873 | return 0; |
874 | } | | 874 | } |
875 | | | 875 | |
876 | int | | 876 | int |
877 | ffbfb_close(dev_t dev, int flags, int mode, struct lwp *l) | | 877 | ffbfb_close(dev_t dev, int flags, int mode, struct lwp *l) |
878 | { | | 878 | { |
879 | struct ffb_softc *sc = device_lookup_private(&ffb_cd, minor(dev)); | | 879 | struct ffb_softc *sc = device_lookup_private(&ffb_cd, minor(dev)); |
880 | struct vcons_screen *ms = sc->vd.active; | | 880 | struct vcons_screen *ms = sc->vd.active; |
881 | | | 881 | |
882 | sc->sc_locked = 0; | | 882 | sc->sc_locked = 0; |
883 | if (ms != NULL) { | | 883 | if (ms != NULL) { |
884 | if ((sc->sc_mode == WSDISPLAYIO_MODE_EMUL) && | | 884 | if ((sc->sc_mode == WSDISPLAYIO_MODE_EMUL) && |
885 | (sc->sc_locked == 0)) { | | 885 | (sc->sc_locked == 0)) { |
886 | ffb_ras_init(sc); | | 886 | ffb_ras_init(sc); |
887 | vcons_redraw_screen(ms); | | 887 | vcons_redraw_screen(ms); |
888 | } | | 888 | } |
889 | } | | 889 | } |
890 | return 0; | | 890 | return 0; |
891 | } | | 891 | } |
892 | | | 892 | |
893 | int | | 893 | int |
894 | ffbfb_ioctl(dev_t dev, u_long cmd, void *data, int flags, struct lwp *l) | | 894 | ffbfb_ioctl(dev_t dev, u_long cmd, void *data, int flags, struct lwp *l) |
895 | { | | 895 | { |
896 | struct ffb_softc *sc = device_lookup_private(&ffb_cd, minor(dev)); | | 896 | struct ffb_softc *sc = device_lookup_private(&ffb_cd, minor(dev)); |
897 | | | 897 | |
898 | return ffb_ioctl(&sc->vd, NULL, cmd, data, flags, l); | | 898 | return ffb_ioctl(&sc->vd, NULL, cmd, data, flags, l); |
899 | } | | 899 | } |
900 | | | 900 | |
901 | paddr_t | | 901 | paddr_t |
902 | ffbfb_mmap(dev_t dev, off_t off, int prot) | | 902 | ffbfb_mmap(dev_t dev, off_t off, int prot) |
903 | { | | 903 | { |
904 | struct ffb_softc *sc = device_lookup_private(&ffb_cd, minor(dev)); | | 904 | struct ffb_softc *sc = device_lookup_private(&ffb_cd, minor(dev)); |
905 | uint64_t size; | | 905 | uint64_t size; |
906 | int i, reg; | | 906 | int i, reg; |
907 | off_t o; | | 907 | off_t o; |
908 | | | 908 | |
909 | /* | | 909 | /* |
910 | * off is a magic cookie (see xfree86/drivers/sunffb/ffb.h), | | 910 | * off is a magic cookie (see xfree86/drivers/sunffb/ffb.h), |
911 | * which we map to an index into the "reg" property, and use | | 911 | * which we map to an index into the "reg" property, and use |
912 | * our copy of the firmware data as arguments for the real | | 912 | * our copy of the firmware data as arguments for the real |
913 | * mapping. | | 913 | * mapping. |
914 | */ | | 914 | */ |
915 | static struct { unsigned long voff; int reg; long flags; } map[] = { | | 915 | static struct { unsigned long voff; int reg; long flags; } map[] = { |
916 | { 0x00000000, FFB_REG_SFB8R, BUS_SPACE_MAP_PREFETCHABLE }, | | 916 | { 0x00000000, FFB_REG_SFB8R, BUS_SPACE_MAP_PREFETCHABLE }, |
917 | { 0x00400000, FFB_REG_SFB8G, BUS_SPACE_MAP_PREFETCHABLE }, | | 917 | { 0x00400000, FFB_REG_SFB8G, BUS_SPACE_MAP_PREFETCHABLE }, |
918 | { 0x00800000, FFB_REG_SFB8B, BUS_SPACE_MAP_PREFETCHABLE }, | | 918 | { 0x00800000, FFB_REG_SFB8B, BUS_SPACE_MAP_PREFETCHABLE }, |
919 | { 0x00c00000, FFB_REG_SFB8X, BUS_SPACE_MAP_PREFETCHABLE }, | | 919 | { 0x00c00000, FFB_REG_SFB8X, BUS_SPACE_MAP_PREFETCHABLE }, |
920 | { 0x01000000, FFB_REG_SFB32, BUS_SPACE_MAP_PREFETCHABLE }, | | 920 | { 0x01000000, FFB_REG_SFB32, BUS_SPACE_MAP_PREFETCHABLE }, |
921 | { 0x02000000, FFB_REG_SFB64, BUS_SPACE_MAP_PREFETCHABLE }, | | 921 | { 0x02000000, FFB_REG_SFB64, BUS_SPACE_MAP_PREFETCHABLE }, |
922 | { 0x04000000, FFB_REG_FBC, 0 }, | | 922 | { 0x04000000, FFB_REG_FBC, 0 }, |
923 | { 0x04004000, FFB_REG_DFB8R, BUS_SPACE_MAP_PREFETCHABLE }, | | 923 | { 0x04004000, FFB_REG_DFB8R, BUS_SPACE_MAP_PREFETCHABLE }, |
924 | { 0x04404000, FFB_REG_DFB8G, BUS_SPACE_MAP_PREFETCHABLE }, | | 924 | { 0x04404000, FFB_REG_DFB8G, BUS_SPACE_MAP_PREFETCHABLE }, |
925 | { 0x04804000, FFB_REG_DFB8B, BUS_SPACE_MAP_PREFETCHABLE }, | | 925 | { 0x04804000, FFB_REG_DFB8B, BUS_SPACE_MAP_PREFETCHABLE }, |
926 | { 0x04c04000, FFB_REG_DFB8X, BUS_SPACE_MAP_PREFETCHABLE }, | | 926 | { 0x04c04000, FFB_REG_DFB8X, BUS_SPACE_MAP_PREFETCHABLE }, |
927 | { 0x05004000, FFB_REG_DFB24, BUS_SPACE_MAP_PREFETCHABLE }, | | 927 | { 0x05004000, FFB_REG_DFB24, BUS_SPACE_MAP_PREFETCHABLE }, |
928 | { 0x06004000, FFB_REG_DFB32, BUS_SPACE_MAP_PREFETCHABLE }, | | 928 | { 0x06004000, FFB_REG_DFB32, BUS_SPACE_MAP_PREFETCHABLE }, |
929 | { 0x07004000, FFB_REG_DFB422A, BUS_SPACE_MAP_PREFETCHABLE }, | | 929 | { 0x07004000, FFB_REG_DFB422A, BUS_SPACE_MAP_PREFETCHABLE }, |
930 | { 0x0bc06000, FFB_REG_DAC, 0 }, | | 930 | { 0x0bc06000, FFB_REG_DAC, 0 }, |
931 | { 0x0bc08000, FFB_REG_PROM, 0 }, | | 931 | { 0x0bc08000, FFB_REG_PROM, 0 }, |
932 | { 0x0bc18000, 0, 0 } | | 932 | { 0x0bc18000, 0, 0 } |
933 | }; | | 933 | }; |
934 | | | 934 | |
935 | /* special value "FFB_EXP_VOFF" - not backed by any "reg" entry */ | | 935 | /* special value "FFB_EXP_VOFF" - not backed by any "reg" entry */ |
936 | if (off == 0x0bc18000) | | 936 | if (off == 0x0bc18000) |
937 | return bus_space_mmap(sc->sc_bt, sc->sc_addrs[FFB_REG_PROM], | | 937 | return bus_space_mmap(sc->sc_bt, sc->sc_addrs[FFB_REG_PROM], |
938 | 0x00200000, prot, BUS_SPACE_MAP_LINEAR); | | 938 | 0x00200000, prot, BUS_SPACE_MAP_LINEAR); |
939 | | | 939 | |
940 | /* | | 940 | /* |
941 | * FFB_VOFF_FBC_KREGS - used by afbinit to upload firmware. We should | | 941 | * FFB_VOFF_FBC_KREGS - used by afbinit to upload firmware. We should |
942 | * probably mmap them only on afb boards | | 942 | * probably mmap them only on afb boards |
943 | */ | | 943 | */ |
944 | if ((off >= 0x0bc04000) && (off < 0x0bc06000)) | | 944 | if ((off >= 0x0bc04000) && (off < 0x0bc06000)) |
945 | return bus_space_mmap(sc->sc_bt, sc->sc_addrs[FFB_REG_PROM], | | 945 | return bus_space_mmap(sc->sc_bt, sc->sc_addrs[FFB_REG_PROM], |
946 | 0x00610000 + (off - 0x0bc04000), prot, | | 946 | 0x00610000 + (off - 0x0bc04000), prot, |
947 | BUS_SPACE_MAP_LINEAR); | | 947 | BUS_SPACE_MAP_LINEAR); |
948 | | | 948 | |
949 | #define NELEMS(arr) (sizeof(arr)/sizeof((arr)[0])) | | 949 | #define NELEMS(arr) (sizeof(arr)/sizeof((arr)[0])) |
950 | | | 950 | |
951 | /* the map is ordered by voff */ | | 951 | /* the map is ordered by voff */ |
952 | for (i = 0; i < NELEMS(map)-1; i++) { | | 952 | for (i = 0; i < NELEMS(map)-1; i++) { |
953 | reg = map[i].reg; | | 953 | reg = map[i].reg; |
954 | /* the number of entries in reg seems to vary */ | | 954 | /* the number of entries in reg seems to vary */ |
955 | if (reg < sc->sc_nreg) { | | 955 | if (reg < sc->sc_nreg) { |
956 | size = uimin((map[i + 1].voff - map[i].voff), | | 956 | size = uimin((map[i + 1].voff - map[i].voff), |
957 | sc->sc_sizes[reg]); | | 957 | sc->sc_sizes[reg]); |
958 | if ((off >= map[i].voff) && | | 958 | if ((off >= map[i].voff) && |
959 | (off < (map[i].voff + size))) { | | 959 | (off < (map[i].voff + size))) { |
960 | o = off - map[i].voff; | | 960 | o = off - map[i].voff; |
961 | return bus_space_mmap(sc->sc_bt, | | 961 | return bus_space_mmap(sc->sc_bt, |
962 | sc->sc_addrs[reg], o, prot, | | 962 | sc->sc_addrs[reg], o, prot, |
963 | BUS_SPACE_MAP_LINEAR | map[i].flags); | | 963 | BUS_SPACE_MAP_LINEAR | map[i].flags); |
964 | } | | 964 | } |
965 | } | | 965 | } |
966 | } | | 966 | } |
967 | | | 967 | |
968 | return -1; | | 968 | return -1; |
969 | } | | 969 | } |
970 | | | 970 | |
971 | void | | 971 | void |
972 | ffb_clearscreen(struct ffb_softc *sc) | | 972 | ffb_clearscreen(struct ffb_softc *sc) |
973 | { | | 973 | { |
974 | struct rasops_info *ri = &ffb_console_screen.scr_ri; | | 974 | struct rasops_info *ri = &ffb_console_screen.scr_ri; |
975 | ffb_ras_fill(sc); | | 975 | ffb_ras_fill(sc); |
976 | ffb_ras_setfg(sc, ri->ri_devcmap[WS_DEFAULT_BG]); | | 976 | ffb_ras_setfg(sc, ri->ri_devcmap[WS_DEFAULT_BG]); |
977 | ffb_ras_fifo_wait(sc, 4); | | 977 | ffb_ras_fifo_wait(sc, 4); |
978 | FBC_WRITE(sc, FFB_FBC_BY, 0); | | 978 | FBC_WRITE(sc, FFB_FBC_BY, 0); |
979 | FBC_WRITE(sc, FFB_FBC_BX, 0); | | 979 | FBC_WRITE(sc, FFB_FBC_BX, 0); |
980 | FBC_WRITE(sc, FFB_FBC_BH, sc->sc_height); | | 980 | FBC_WRITE(sc, FFB_FBC_BH, sc->sc_height); |
981 | FBC_WRITE(sc, FFB_FBC_BW, sc->sc_width); | | 981 | FBC_WRITE(sc, FFB_FBC_BW, sc->sc_width); |
982 | } | | 982 | } |
983 | | | 983 | |
984 | void | | 984 | void |
985 | ffb_cursor(void *cookie, int on, int row, int col) | | 985 | ffb_cursor(void *cookie, int on, int row, int col) |
986 | { | | 986 | { |
987 | struct rasops_info *ri = cookie; | | 987 | struct rasops_info *ri = cookie; |
988 | struct vcons_screen *scr; | | 988 | struct vcons_screen *scr; |
989 | struct ffb_softc *sc; | | 989 | struct ffb_softc *sc; |
990 | int x, y, wi, he; | | 990 | int x, y, wi, he; |
991 | | | 991 | |
992 | if (cookie != NULL) { | | 992 | if (cookie != NULL) { |
993 | scr = ri->ri_hw; | | 993 | scr = ri->ri_hw; |
994 | sc = scr->scr_cookie; | | 994 | sc = scr->scr_cookie; |
995 | | | 995 | |
996 | wi = ri->ri_font->fontwidth; | | 996 | wi = ri->ri_font->fontwidth; |
997 | he = ri->ri_font->fontheight; | | 997 | he = ri->ri_font->fontheight; |
998 | | | 998 | |
999 | if (sc->sc_mode == WSDISPLAYIO_MODE_EMUL) { | | 999 | if (sc->sc_mode == WSDISPLAYIO_MODE_EMUL) { |
1000 | | | 1000 | |
1001 | if (ri->ri_flg & RI_CURSOR) { | | 1001 | if (ri->ri_flg & RI_CURSOR) { |
1002 | | | 1002 | |
1003 | /* remove cursor */ | | 1003 | /* remove cursor */ |
1004 | x = ri->ri_ccol * wi + ri->ri_xorigin; | | 1004 | x = ri->ri_ccol * wi + ri->ri_xorigin; |
1005 | y = ri->ri_crow * he + ri->ri_yorigin; | | 1005 | y = ri->ri_crow * he + ri->ri_yorigin; |
1006 | | | 1006 | |
1007 | ffb_ras_invert(sc); | | 1007 | ffb_ras_invert(sc); |
1008 | ffb_ras_fifo_wait(sc, 4); | | 1008 | ffb_ras_fifo_wait(sc, 4); |
1009 | FBC_WRITE(sc, FFB_FBC_BY, y); | | 1009 | FBC_WRITE(sc, FFB_FBC_BY, y); |
1010 | FBC_WRITE(sc, FFB_FBC_BX, x); | | 1010 | FBC_WRITE(sc, FFB_FBC_BX, x); |
1011 | FBC_WRITE(sc, FFB_FBC_BH, he); | | 1011 | FBC_WRITE(sc, FFB_FBC_BH, he); |
1012 | FBC_WRITE(sc, FFB_FBC_BW, wi); | | 1012 | FBC_WRITE(sc, FFB_FBC_BW, wi); |
1013 | | | 1013 | |
1014 | ri->ri_flg &= ~RI_CURSOR; | | 1014 | ri->ri_flg &= ~RI_CURSOR; |
1015 | } | | 1015 | } |
1016 | ri->ri_crow = row; | | 1016 | ri->ri_crow = row; |
1017 | ri->ri_ccol = col; | | 1017 | ri->ri_ccol = col; |
1018 | if (on) | | 1018 | if (on) |
1019 | { | | 1019 | { |
1020 | x = ri->ri_ccol * wi + ri->ri_xorigin; | | 1020 | x = ri->ri_ccol * wi + ri->ri_xorigin; |
1021 | y = ri->ri_crow * he + ri->ri_yorigin; | | 1021 | y = ri->ri_crow * he + ri->ri_yorigin; |
1022 | | | 1022 | |
1023 | ffb_ras_invert(sc); | | 1023 | ffb_ras_invert(sc); |
1024 | ffb_ras_fifo_wait(sc, 4); | | 1024 | ffb_ras_fifo_wait(sc, 4); |
1025 | FBC_WRITE(sc, FFB_FBC_BY, y); | | 1025 | FBC_WRITE(sc, FFB_FBC_BY, y); |
1026 | FBC_WRITE(sc, FFB_FBC_BX, x); | | 1026 | FBC_WRITE(sc, FFB_FBC_BX, x); |
1027 | FBC_WRITE(sc, FFB_FBC_BH, he); | | 1027 | FBC_WRITE(sc, FFB_FBC_BH, he); |
1028 | FBC_WRITE(sc, FFB_FBC_BW, wi); | | 1028 | FBC_WRITE(sc, FFB_FBC_BW, wi); |
1029 | | | 1029 | |
1030 | ri->ri_flg |= RI_CURSOR; | | 1030 | ri->ri_flg |= RI_CURSOR; |
1031 | } | | 1031 | } |
1032 | } else { | | 1032 | } else { |
1033 | ri->ri_crow = row; | | 1033 | ri->ri_crow = row; |
1034 | ri->ri_ccol = col; | | 1034 | ri->ri_ccol = col; |
1035 | ri->ri_flg &= ~RI_CURSOR; | | 1035 | ri->ri_flg &= ~RI_CURSOR; |
1036 | } | | 1036 | } |
1037 | } | | 1037 | } |
1038 | } | | 1038 | } |
1039 | | | 1039 | |
1040 | /* mono bitmap font */ | | 1040 | /* mono bitmap font */ |
1041 | void | | 1041 | void |
1042 | ffb_putchar_mono(void *cookie, int row, int col, u_int c, long attr) | | 1042 | ffb_putchar_mono(void *cookie, int row, int col, u_int c, long attr) |
1043 | { | | 1043 | { |
1044 | struct rasops_info *ri = cookie; | | 1044 | struct rasops_info *ri = cookie; |
1045 | struct vcons_screen *scr = ri->ri_hw; | | 1045 | struct vcons_screen *scr = ri->ri_hw; |
1046 | struct wsdisplay_font *font = PICK_FONT(ri, c); | | 1046 | struct wsdisplay_font *font = PICK_FONT(ri, c); |
1047 | struct ffb_softc *sc = scr->scr_cookie; | | 1047 | struct ffb_softc *sc = scr->scr_cookie; |
1048 | void *data; | | 1048 | void *data; |
1049 | uint32_t fg, bg; | | 1049 | uint32_t fg, bg; |
1050 | int i; | | 1050 | int i; |
1051 | int x, y, wi, he; | | 1051 | int x, y, wi, he; |
1052 | | | 1052 | |
1053 | if (sc->sc_mode != WSDISPLAYIO_MODE_EMUL) | | 1053 | if (sc->sc_mode != WSDISPLAYIO_MODE_EMUL) |
1054 | return; | | 1054 | return; |
1055 | | | 1055 | |
1056 | wi = font->fontwidth; | | 1056 | wi = font->fontwidth; |
1057 | he = font->fontheight; | | 1057 | he = font->fontheight; |
1058 | | | 1058 | |
1059 | if (!CHAR_IN_FONT(c, font)) | | 1059 | if (!CHAR_IN_FONT(c, font)) |
1060 | return; | | 1060 | return; |
1061 | | | 1061 | |
1062 | bg = ri->ri_devcmap[(attr >> 16) & 0xf]; | | 1062 | bg = ri->ri_devcmap[(attr >> 16) & 0xf]; |
1063 | fg = ri->ri_devcmap[(attr >> 24) & 0xf]; | | 1063 | fg = ri->ri_devcmap[(attr >> 24) & 0xf]; |
1064 | x = ri->ri_xorigin + col * wi; | | 1064 | x = ri->ri_xorigin + col * wi; |
1065 | y = ri->ri_yorigin + row * he; | | 1065 | y = ri->ri_yorigin + row * he; |
1066 | | | 1066 | |
1067 | data = WSFONT_GLYPH(c, font); | | 1067 | data = WSFONT_GLYPH(c, font); |
1068 | | | 1068 | |
1069 | ffb_ras_setbg(sc, bg); | | 1069 | ffb_ras_setbg(sc, bg); |
1070 | ffb_ras_setfg(sc, fg); | | 1070 | ffb_ras_setfg(sc, fg); |
1071 | ffb_ras_fifo_wait(sc, 4); | | 1071 | ffb_ras_fifo_wait(sc, 4); |
1072 | FBC_WRITE(sc, FFB_FBC_ROP, FBC_ROP_NEW); | | 1072 | FBC_WRITE(sc, FFB_FBC_ROP, FBC_ROP_NEW); |
1073 | FBC_WRITE(sc, FFB_FBC_FONTXY, (y << 16) | x); | | 1073 | FBC_WRITE(sc, FFB_FBC_FONTXY, (y << 16) | x); |
1074 | FBC_WRITE(sc, FFB_FBC_FONTW, wi); | | 1074 | FBC_WRITE(sc, FFB_FBC_FONTW, wi); |
1075 | FBC_WRITE(sc, FFB_FBC_PPC, | | 1075 | FBC_WRITE(sc, FFB_FBC_PPC, |
1076 | FBC_PPC_VCE_DIS | FBC_PPC_TBE_OPAQUE | FBC_PPC_ACE_DIS | | | 1076 | FBC_PPC_VCE_DIS | FBC_PPC_TBE_OPAQUE | FBC_PPC_ACE_DIS | |
1077 | FBC_PPC_APE_DIS | FBC_PPC_DCE_DIS | FBC_PPC_CS_CONST | | | 1077 | FBC_PPC_APE_DIS | FBC_PPC_DCE_DIS | FBC_PPC_CS_CONST | |
1078 | FBC_PPC_ABE_DIS | FBC_PPC_XS_WID); | | 1078 | FBC_PPC_ABE_DIS | FBC_PPC_XS_WID); |
1079 | | | 1079 | |
1080 | switch (font->stride) { | | 1080 | switch (font->stride) { |
1081 | case 1: { | | 1081 | case 1: { |
1082 | uint8_t *data8 = data; | | 1082 | uint8_t *data8 = data; |
1083 | uint32_t reg; | | 1083 | uint32_t reg; |
1084 | if (attr & WSATTR_UNDERLINE) { | | 1084 | if (attr & WSATTR_UNDERLINE) { |
1085 | for (i = 0; i < he - 2; i++) { | | 1085 | for (i = 0; i < he - 2; i++) { |
1086 | reg = *data8; | | 1086 | reg = *data8; |
1087 | FBC_WRITE(sc, FFB_FBC_FONT, reg << 24); | | 1087 | FBC_WRITE(sc, FFB_FBC_FONT, reg << 24); |
1088 | data8++; | | 1088 | data8++; |
1089 | } | | 1089 | } |
1090 | FBC_WRITE(sc, FFB_FBC_FONT, 0xff000000); | | 1090 | FBC_WRITE(sc, FFB_FBC_FONT, 0xff000000); |
1091 | data8++; | | 1091 | data8++; |
1092 | reg = *data8; | | 1092 | reg = *data8; |
1093 | FBC_WRITE(sc, FFB_FBC_FONT, reg << 24); | | 1093 | FBC_WRITE(sc, FFB_FBC_FONT, reg << 24); |
1094 | } else { | | 1094 | } else { |
1095 | for (i = 0; i < he; i++) { | | 1095 | for (i = 0; i < he; i++) { |
1096 | reg = *data8; | | 1096 | reg = *data8; |
1097 | FBC_WRITE(sc, FFB_FBC_FONT, reg << 24); | | 1097 | FBC_WRITE(sc, FFB_FBC_FONT, reg << 24); |
1098 | data8++; | | 1098 | data8++; |
1099 | } | | 1099 | } |
1100 | } | | 1100 | } |
1101 | break; | | 1101 | break; |
1102 | } | | 1102 | } |
1103 | case 2: { | | 1103 | case 2: { |
1104 | uint16_t *data16 = data; | | 1104 | uint16_t *data16 = data; |
1105 | uint32_t reg; | | 1105 | uint32_t reg; |
1106 | if (attr & WSATTR_UNDERLINE) { | | 1106 | if (attr & WSATTR_UNDERLINE) { |
1107 | for (i = 0; i < he - 2; i++) { | | 1107 | for (i = 0; i < he - 2; i++) { |
1108 | reg = *data16; | | 1108 | reg = *data16; |
1109 | FBC_WRITE(sc, FFB_FBC_FONT, reg << 16); | | 1109 | FBC_WRITE(sc, FFB_FBC_FONT, reg << 16); |
1110 | data16++; | | 1110 | data16++; |
1111 | } | | 1111 | } |
1112 | FBC_WRITE(sc, FFB_FBC_FONT, 0xffff0000); | | 1112 | FBC_WRITE(sc, FFB_FBC_FONT, 0xffff0000); |
1113 | data16++; | | 1113 | data16++; |
1114 | reg = *data16; | | 1114 | reg = *data16; |
1115 | FBC_WRITE(sc, FFB_FBC_FONT, reg << 16); | | 1115 | FBC_WRITE(sc, FFB_FBC_FONT, reg << 16); |
1116 | } else { | | 1116 | } else { |
1117 | for (i = 0; i < he; i++) { | | 1117 | for (i = 0; i < he; i++) { |
1118 | reg = *data16; | | 1118 | reg = *data16; |
1119 | FBC_WRITE(sc, FFB_FBC_FONT, reg << 16); | | 1119 | FBC_WRITE(sc, FFB_FBC_FONT, reg << 16); |
1120 | data16++; | | 1120 | data16++; |
1121 | } | | 1121 | } |
1122 | } | | 1122 | } |
1123 | break; | | 1123 | break; |
1124 | } | | 1124 | } |
1125 | } | | 1125 | } |
1126 | } | | 1126 | } |
1127 | | | 1127 | |
1128 | /* alpha font */ | | 1128 | /* alpha font */ |
1129 | void | | 1129 | void |
1130 | ffb_putchar_aa(void *cookie, int row, int col, u_int c, long attr) | | 1130 | ffb_putchar_aa(void *cookie, int row, int col, u_int c, long attr) |
1131 | { | | 1131 | { |
1132 | struct rasops_info *ri = cookie; | | 1132 | struct rasops_info *ri = cookie; |
1133 | struct vcons_screen *scr = ri->ri_hw; | | 1133 | struct vcons_screen *scr = ri->ri_hw; |
1134 | struct wsdisplay_font *font = PICK_FONT(ri, c); | | 1134 | struct wsdisplay_font *font = PICK_FONT(ri, c); |
1135 | struct ffb_softc *sc = scr->scr_cookie; | | 1135 | struct ffb_softc *sc = scr->scr_cookie; |
1136 | volatile uint32_t *dest, *ddest; | | 1136 | volatile uint32_t *dest, *ddest; |
1137 | uint8_t *data8; | | 1137 | uint8_t *data8; |
1138 | uint32_t fg, bg; | | 1138 | uint32_t fg, bg; |
1139 | int i; | | 1139 | int i; |
1140 | int x, y, wi, he; | | 1140 | int x, y, wi, he; |
1141 | uint32_t alpha = 0x80; | | 1141 | uint32_t alpha = 0x80; |
1142 | int j; | | 1142 | int j; |
1143 | | | 1143 | |
1144 | if (sc->sc_mode != WSDISPLAYIO_MODE_EMUL) | | 1144 | if (sc->sc_mode != WSDISPLAYIO_MODE_EMUL) |
1145 | return; | | 1145 | return; |
1146 | | | 1146 | |
1147 | wi = font->fontwidth; | | 1147 | wi = font->fontwidth; |
1148 | he = font->fontheight; | | 1148 | he = font->fontheight; |
1149 | | | 1149 | |
1150 | if (!CHAR_IN_FONT(c, font)) | | 1150 | if (!CHAR_IN_FONT(c, font)) |
1151 | return; | | 1151 | return; |
1152 | | | 1152 | |
1153 | bg = ri->ri_devcmap[(attr >> 16) & 0xf]; | | 1153 | bg = ri->ri_devcmap[(attr >> 16) & 0xf]; |
1154 | fg = ri->ri_devcmap[(attr >> 24) & 0xf]; | | 1154 | fg = ri->ri_devcmap[(attr >> 24) & 0xf]; |
1155 | x = ri->ri_xorigin + col * wi; | | 1155 | x = ri->ri_xorigin + col * wi; |
1156 | y = ri->ri_yorigin + row * he; | | 1156 | y = ri->ri_yorigin + row * he; |
1157 | | | 1157 | |
1158 | data8 = WSFONT_GLYPH(c, font); | | 1158 | data8 = WSFONT_GLYPH(c, font); |
1159 | | | 1159 | |
1160 | /* first we erase the background */ | | 1160 | /* first we erase the background */ |
1161 | ffb_ras_fill(sc); | | 1161 | ffb_ras_fill(sc); |
1162 | ffb_ras_setfg(sc, bg); | | 1162 | ffb_ras_setfg(sc, bg); |
1163 | ffb_ras_fifo_wait(sc, 4); | | 1163 | ffb_ras_fifo_wait(sc, 4); |
1164 | FBC_WRITE(sc, FFB_FBC_BY, y); | | 1164 | FBC_WRITE(sc, FFB_FBC_BY, y); |
1165 | FBC_WRITE(sc, FFB_FBC_BX, x); | | 1165 | FBC_WRITE(sc, FFB_FBC_BX, x); |
1166 | FBC_WRITE(sc, FFB_FBC_BH, he); | | 1166 | FBC_WRITE(sc, FFB_FBC_BH, he); |
1167 | FBC_WRITE(sc, FFB_FBC_BW, wi); | | 1167 | FBC_WRITE(sc, FFB_FBC_BW, wi); |
1168 | | | 1168 | |
1169 | /* if we draw a space we're done */ | | 1169 | /* if we draw a space we're done */ |
1170 | if (c == ' ') goto out; | | 1170 | if (c == ' ') goto out; |
1171 | | | 1171 | |
1172 | /* now enable alpha blending */ | | 1172 | /* now enable alpha blending */ |
1173 | ffb_ras_setfg(sc, fg); | | 1173 | ffb_ras_setfg(sc, fg); |
1174 | ffb_ras_fifo_wait(sc, 2); | | 1174 | ffb_ras_fifo_wait(sc, 2); |
1175 | FBC_WRITE(sc, FFB_FBC_ROP, FBC_ROP_NEW); | | 1175 | FBC_WRITE(sc, FFB_FBC_ROP, FBC_ROP_NEW); |
1176 | | | 1176 | |
1177 | FBC_WRITE(sc, FFB_FBC_PPC, | | 1177 | FBC_WRITE(sc, FFB_FBC_PPC, |
1178 | FBC_PPC_VCE_DIS | FBC_PPC_TBE_OPAQUE | FBC_PPC_ACE_DIS | | | 1178 | FBC_PPC_VCE_DIS | FBC_PPC_TBE_OPAQUE | FBC_PPC_ACE_DIS | |
1179 | FBC_PPC_APE_DIS | FBC_PPC_DCE_DIS | FBC_PPC_CS_CONST | | | 1179 | FBC_PPC_APE_DIS | FBC_PPC_DCE_DIS | FBC_PPC_CS_CONST | |
1180 | FBC_PPC_ABE_ENA | FBC_PPC_XS_VAR); | | 1180 | FBC_PPC_ABE_ENA | FBC_PPC_XS_VAR); |
1181 | /* | | 1181 | /* |
1182 | * we have to wait for both the rectangle drawing op above and the | | 1182 | * we have to wait for both the rectangle drawing op above and the |
1183 | * FFB_FBC_PPC write to finish before mucking around in the SFB aperture | | 1183 | * FFB_FBC_PPC write to finish before mucking around in the SFB aperture |
1184 | */ | | 1184 | */ |
1185 | ffb_ras_wait(sc); | | 1185 | ffb_ras_wait(sc); |
1186 | | | 1186 | |
1187 | /* ... and draw the character */ | | 1187 | /* ... and draw the character */ |
1188 | dest = sc->sc_sfb32 + (y << 11) + x; | | 1188 | dest = sc->sc_sfb32 + (y << 11) + x; |
1189 | for (i = 0; i < he; i++) { | | 1189 | for (i = 0; i < he; i++) { |
1190 | ddest = dest; | | 1190 | ddest = dest; |
1191 | for (j = 0; j < wi; j++) { | | 1191 | for (j = 0; j < wi; j++) { |
1192 | alpha = *data8; | | 1192 | alpha = *data8; |
1193 | /* | | 1193 | /* |
1194 | * We set the colour source to constant above so we only | | 1194 | * We set the colour source to constant above so we only |
1195 | * have to write the alpha channel here and the colour | | 1195 | * have to write the alpha channel here and the colour |
1196 | * comes from the FG register. It would be nice if we | | 1196 | * comes from the FG register. It would be nice if we |
1197 | * could just use the SFB8X aperture and memcpy() the | | 1197 | * could just use the SFB8X aperture and memcpy() the |
1198 | * alpha map line by line but for some strange reason | | 1198 | * alpha map line by line but for some strange reason |
1199 | * that will take colour info from the framebuffer even | | 1199 | * that will take colour info from the framebuffer even |
1200 | * if we set the FBC_PPC_CS_CONST bit above. | | 1200 | * if we set the FBC_PPC_CS_CONST bit above. |
1201 | */ | | 1201 | */ |
1202 | *ddest = alpha << 24; | | 1202 | *ddest = alpha << 24; |
1203 | data8++; | | 1203 | data8++; |
1204 | ddest++; | | 1204 | ddest++; |
1205 | } | | 1205 | } |
1206 | dest += 2048; | | 1206 | dest += 2048; |
1207 | } | | 1207 | } |
1208 | out: | | 1208 | out: |
1209 | /* check if we need to draw an underline */ | | 1209 | /* check if we need to draw an underline */ |
1210 | if (attr & WSATTR_UNDERLINE) { | | 1210 | if (attr & WSATTR_UNDERLINE) { |
1211 | dest = sc->sc_sfb32 + ((y + he - 2) << 11) + x; | | 1211 | dest = sc->sc_sfb32 + ((y + he - 2) << 11) + x; |
1212 | for (i = 0; i < wi; i++) { | | 1212 | for (i = 0; i < wi; i++) { |
1213 | *dest = 0xa0000000; | | 1213 | *dest = 0xa0000000; |
1214 | dest++; | | 1214 | dest++; |
1215 | } | | 1215 | } |
1216 | } | | 1216 | } |
1217 | } | | 1217 | } |
1218 | | | 1218 | |
1219 | int | | 1219 | int |
1220 | ffb_allocattr(void *cookie, int fg, int bg, int flags, long *attrp) | | 1220 | ffb_allocattr(void *cookie, int fg, int bg, int flags, long *attrp) |
1221 | { | | 1221 | { |
1222 | if ((fg == 0) && (bg == 0)) | | 1222 | if ((fg == 0) && (bg == 0)) |
1223 | { | | 1223 | { |
1224 | fg = WS_DEFAULT_FG; | | 1224 | fg = WS_DEFAULT_FG; |
1225 | bg = WS_DEFAULT_BG; | | 1225 | bg = WS_DEFAULT_BG; |
1226 | } | | 1226 | } |
1227 | if (flags & WSATTR_REVERSE) { | | 1227 | if (flags & WSATTR_REVERSE) { |
1228 | *attrp = (bg & 0xff) << 24 | (fg & 0xff) << 16; | | 1228 | *attrp = (bg & 0xff) << 24 | (fg & 0xff) << 16; |
1229 | } else | | 1229 | } else |
1230 | *attrp = (fg & 0xff) << 24 | (bg & 0xff) << 16; | | 1230 | *attrp = (fg & 0xff) << 24 | (bg & 0xff) << 16; |
1231 | if (flags & WSATTR_UNDERLINE) | | 1231 | if (flags & WSATTR_UNDERLINE) |
1232 | *attrp |= WSATTR_UNDERLINE; | | 1232 | *attrp |= WSATTR_UNDERLINE; |
1233 | return 0; | | 1233 | return 0; |
1234 | } | | 1234 | } |
1235 | | | 1235 | |
1236 | void | | 1236 | void |
1237 | ffb_init_screen(void *cookie, struct vcons_screen *scr, | | 1237 | ffb_init_screen(void *cookie, struct vcons_screen *scr, |
1238 | int existing, long *defattr) | | 1238 | int existing, long *defattr) |
1239 | { | | 1239 | { |
1240 | struct ffb_softc *sc = cookie; | | 1240 | struct ffb_softc *sc = cookie; |
1241 | struct rasops_info *ri = &scr->scr_ri; | | 1241 | struct rasops_info *ri = &scr->scr_ri; |
1242 | | | 1242 | |
1243 | ri->ri_depth = 32; | | 1243 | ri->ri_depth = 32; |
1244 | ri->ri_width = sc->sc_width; | | 1244 | ri->ri_width = sc->sc_width; |
1245 | ri->ri_height = sc->sc_height; | | 1245 | ri->ri_height = sc->sc_height; |
1246 | ri->ri_stride = sc->sc_linebytes; | | 1246 | ri->ri_stride = sc->sc_linebytes; |
1247 | ri->ri_flg = RI_CENTER | RI_ENABLE_ALPHA | RI_PREFER_ALPHA; | | 1247 | ri->ri_flg = RI_CENTER | RI_ENABLE_ALPHA | RI_PREFER_ALPHA; |
1248 | | | 1248 | |
1249 | /* | | 1249 | /* |
1250 | * we can't accelerate copycols() so instead of falling back to | | 1250 | * we can't accelerate copycols() so instead of falling back to |
1251 | * software use vcons' putchar() based implementation | | 1251 | * software use vcons' putchar() based implementation |
1252 | */ | | 1252 | */ |
1253 | scr->scr_flags |= VCONS_NO_COPYCOLS | VCONS_LOADFONT; | | 1253 | scr->scr_flags |= VCONS_NO_COPYCOLS | VCONS_LOADFONT; |
1254 | | | 1254 | |
1255 | #ifdef VCONS_DRAW_INTR | | 1255 | #ifdef VCONS_DRAW_INTR |
1256 | scr->scr_flags |= VCONS_DONT_READ; | | 1256 | scr->scr_flags |= VCONS_DONT_READ; |
1257 | #endif | | 1257 | #endif |
1258 | DPRINTF(("ffb_init_screen: addr: %08lx\n",(ulong)ri->ri_bits)); | | 1258 | DPRINTF(("ffb_init_screen: addr: %08lx\n",(ulong)ri->ri_bits)); |
1259 | | | 1259 | |
1260 | /* explicitly request BGR in case the default changes */ | | 1260 | /* explicitly request BGR in case the default changes */ |
1261 | ri->ri_rnum = 8; | | 1261 | ri->ri_rnum = 8; |
1262 | ri->ri_gnum = 8; | | 1262 | ri->ri_gnum = 8; |
1263 | ri->ri_bnum = 8; | | 1263 | ri->ri_bnum = 8; |
1264 | ri->ri_rpos = 0; | | 1264 | ri->ri_rpos = 0; |
1265 | ri->ri_gpos = 8; | | 1265 | ri->ri_gpos = 8; |
1266 | ri->ri_bpos = 16; | | 1266 | ri->ri_bpos = 16; |
1267 | | | 1267 | |
1268 | rasops_init(ri, 0, 0); | | 1268 | rasops_init(ri, 0, 0); |
1269 | rasops_reconfig(ri, sc->sc_height / ri->ri_font->fontheight, | | 1269 | rasops_reconfig(ri, sc->sc_height / ri->ri_font->fontheight, |
1270 | sc->sc_width / ri->ri_font->fontwidth); | | 1270 | sc->sc_width / ri->ri_font->fontwidth); |
1271 | ri->ri_caps = WSSCREEN_WSCOLORS | WSSCREEN_UNDERLINE | | | 1271 | ri->ri_caps = WSSCREEN_WSCOLORS | WSSCREEN_UNDERLINE | |
1272 | WSSCREEN_REVERSE | WSSCREEN_RESIZE; | | 1272 | WSSCREEN_REVERSE | WSSCREEN_RESIZE; |
1273 | | | 1273 | |
1274 | /* enable acceleration */ | | 1274 | /* enable acceleration */ |
1275 | ri->ri_ops.copyrows = ffb_ras_copyrows; | | 1275 | ri->ri_ops.copyrows = ffb_ras_copyrows; |
1276 | ri->ri_ops.eraserows = ffb_ras_eraserows; | | 1276 | ri->ri_ops.eraserows = ffb_ras_eraserows; |
1277 | ri->ri_ops.erasecols = ffb_ras_erasecols; | | 1277 | ri->ri_ops.erasecols = ffb_ras_erasecols; |
1278 | ri->ri_ops.cursor = ffb_cursor; | | 1278 | ri->ri_ops.cursor = ffb_cursor; |
1279 | ri->ri_ops.allocattr = ffb_allocattr; | | 1279 | ri->ri_ops.allocattr = ffb_allocattr; |
1280 | if (FONT_IS_ALPHA(ri->ri_font)) { | | 1280 | if (FONT_IS_ALPHA(ri->ri_font)) { |
1281 | ri->ri_ops.putchar = ffb_putchar_aa; | | 1281 | ri->ri_ops.putchar = ffb_putchar_aa; |
1282 | } else | | 1282 | } else |
1283 | ri->ri_ops.putchar = ffb_putchar_mono; | | 1283 | ri->ri_ops.putchar = ffb_putchar_mono; |
1284 | } | | 1284 | } |
1285 | | | 1285 | |
1286 | /* I2C bitbanging */ | | 1286 | /* I2C bitbanging */ |
1287 | static void ffb_i2cbb_set_bits(void *cookie, uint32_t bits) | | 1287 | static void ffb_i2cbb_set_bits(void *cookie, uint32_t bits) |
1288 | { | | 1288 | { |
1289 | struct ffb_softc *sc = cookie; | | 1289 | struct ffb_softc *sc = cookie; |
1290 | | | 1290 | |
1291 | DAC_WRITE(sc, FFB_DAC_TYPE, FFB_DAC_CFG_MPDATA); | | 1291 | DAC_WRITE(sc, FFB_DAC_TYPE, FFB_DAC_CFG_MPDATA); |
1292 | DAC_WRITE(sc, FFB_DAC_VALUE, bits); | | 1292 | DAC_WRITE(sc, FFB_DAC_VALUE, bits); |
1293 | } | | 1293 | } |
1294 | | | 1294 | |
1295 | static void ffb_i2cbb_set_dir(void *cookie, uint32_t dir) | | 1295 | static void ffb_i2cbb_set_dir(void *cookie, uint32_t dir) |
1296 | { | | 1296 | { |
1297 | /* Nothing to do */ | | 1297 | /* Nothing to do */ |
1298 | } | | 1298 | } |
1299 | | | 1299 | |
1300 | static uint32_t ffb_i2cbb_read(void *cookie) | | 1300 | static uint32_t ffb_i2cbb_read(void *cookie) |
1301 | { | | 1301 | { |
1302 | struct ffb_softc *sc = cookie; | | 1302 | struct ffb_softc *sc = cookie; |
1303 | uint32_t bits; | | 1303 | uint32_t bits; |
1304 | | | 1304 | |
1305 | DAC_WRITE(sc, FFB_DAC_TYPE, FFB_DAC_CFG_MPSENSE); | | 1305 | DAC_WRITE(sc, FFB_DAC_TYPE, FFB_DAC_CFG_MPSENSE); |
1306 | bits = DAC_READ(sc, FFB_DAC_VALUE); | | 1306 | bits = DAC_READ(sc, FFB_DAC_VALUE); |
1307 | | | 1307 | |
1308 | return bits; | | 1308 | return bits; |