| @@ -1,1576 +1,1610 @@ | | | @@ -1,1576 +1,1610 @@ |
1 | /* $NetBSD: voodoofb.c,v 1.32 2012/01/17 21:31:46 macallan Exp $ */ | | 1 | /* $NetBSD: voodoofb.c,v 1.33 2012/01/18 08:04:18 macallan Exp $ */ |
2 | | | 2 | |
3 | /* | | 3 | /* |
4 | * Copyright (c) 2005, 2006 Michael Lorenz | | 4 | * Copyright (c) 2005, 2006 Michael Lorenz |
5 | * All rights reserved. | | 5 | * All rights reserved. |
6 | * | | 6 | * |
7 | * Redistribution and use in source and binary forms, with or without | | 7 | * Redistribution and use in source and binary forms, with or without |
8 | * modification, are permitted provided that the following conditions | | 8 | * modification, are permitted provided that the following conditions |
9 | * are met: | | 9 | * are met: |
10 | * 1. Redistributions of source code must retain the above copyright | | 10 | * 1. Redistributions of source code must retain the above copyright |
11 | * notice, this list of conditions and the following disclaimer. | | 11 | * notice, this list of conditions and the following disclaimer. |
12 | * 2. Redistributions in binary form must reproduce the above copyright | | 12 | * 2. Redistributions in binary form must reproduce the above copyright |
13 | * notice, this list of conditions and the following disclaimer in the | | 13 | * notice, this list of conditions and the following disclaimer in the |
14 | * documentation and/or other materials provided with the distribution. | | 14 | * documentation and/or other materials provided with the distribution. |
15 | * | | 15 | * |
16 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR | | 16 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
17 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES | | 17 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
18 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. | | 18 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
19 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, | | 19 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
20 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | | 20 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
21 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | | 21 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
22 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | | 22 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
23 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | | 23 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
24 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | | 24 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
25 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | | 25 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
26 | */ | | 26 | */ |
27 | | | 27 | |
28 | /* | | 28 | /* |
29 | * A console driver for 3Dfx Voodoo3 graphics boards | | 29 | * A console driver for 3Dfx Voodoo3 graphics boards |
30 | * Thanks to Andreas Drewke (andreas_dr@gmx.de) for his Voodoo3 driver for BeOS | | 30 | * Thanks to Andreas Drewke (andreas_dr@gmx.de) for his Voodoo3 driver for BeOS |
31 | * which I used as reference / documentation | | 31 | * which I used as reference / documentation |
32 | */ | | 32 | */ |
33 | | | 33 | |
34 | #include <sys/cdefs.h> | | 34 | #include <sys/cdefs.h> |
35 | __KERNEL_RCSID(0, "$NetBSD: voodoofb.c,v 1.32 2012/01/17 21:31:46 macallan Exp $"); | | 35 | __KERNEL_RCSID(0, "$NetBSD: voodoofb.c,v 1.33 2012/01/18 08:04:18 macallan Exp $"); |
36 | | | 36 | |
37 | #include <sys/param.h> | | 37 | #include <sys/param.h> |
38 | #include <sys/systm.h> | | 38 | #include <sys/systm.h> |
39 | #include <sys/kernel.h> | | 39 | #include <sys/kernel.h> |
40 | #include <sys/device.h> | | 40 | #include <sys/device.h> |
41 | #include <sys/malloc.h> | | 41 | #include <sys/malloc.h> |
42 | #include <sys/callout.h> | | 42 | #include <sys/callout.h> |
43 | #include <sys/kauth.h> | | 43 | #include <sys/kauth.h> |
44 | | | 44 | |
45 | #include <dev/pci/pcivar.h> | | 45 | #include <dev/pci/pcivar.h> |
46 | #include <dev/pci/pcireg.h> | | 46 | #include <dev/pci/pcireg.h> |
47 | #include <dev/pci/pcidevs.h> | | 47 | #include <dev/pci/pcidevs.h> |
48 | #include <dev/pci/pciio.h> | | 48 | #include <dev/pci/pciio.h> |
49 | #include <dev/pci/voodoofbreg.h> | | 49 | #include <dev/pci/voodoofbreg.h> |
50 | | | 50 | |
51 | #include <dev/wscons/wsdisplayvar.h> | | 51 | #include <dev/wscons/wsdisplayvar.h> |
52 | #include <dev/wscons/wsconsio.h> | | 52 | #include <dev/wscons/wsconsio.h> |
53 | #include <dev/wsfont/wsfont.h> | | 53 | #include <dev/wsfont/wsfont.h> |
54 | #include <dev/rasops/rasops.h> | | 54 | #include <dev/rasops/rasops.h> |
55 | #include <dev/wscons/wsdisplay_vconsvar.h> | | 55 | #include <dev/wscons/wsdisplay_vconsvar.h> |
56 | #include <dev/pci/wsdisplay_pci.h> | | 56 | #include <dev/pci/wsdisplay_pci.h> |
57 | | | 57 | |
58 | #include <dev/i2c/i2cvar.h> | | 58 | #include <dev/i2c/i2cvar.h> |
59 | #include <dev/i2c/i2c_bitbang.h> | | 59 | #include <dev/i2c/i2c_bitbang.h> |
60 | #include <dev/i2c/ddcvar.h> | | 60 | #include <dev/i2c/ddcvar.h> |
61 | #include <dev/videomode/videomode.h> | | 61 | #include <dev/videomode/videomode.h> |
62 | #include <dev/videomode/edidvar.h> | | 62 | #include <dev/videomode/edidvar.h> |
63 | #include <dev/videomode/edidreg.h> | | 63 | #include <dev/videomode/edidreg.h> |
64 | | | 64 | |
65 | #include "opt_wsemul.h" | | 65 | #include "opt_wsemul.h" |
66 | | | 66 | |
67 | struct voodoofb_softc { | | 67 | struct voodoofb_softc { |
68 | device_t sc_dev; | | 68 | device_t sc_dev; |
69 | pci_chipset_tag_t sc_pc; | | 69 | pci_chipset_tag_t sc_pc; |
70 | pcitag_t sc_pcitag; | | 70 | pcitag_t sc_pcitag; |
71 | struct pci_attach_args sc_pa; | | 71 | struct pci_attach_args sc_pa; |
72 | | | 72 | |
73 | bus_space_tag_t sc_memt; | | 73 | bus_space_tag_t sc_memt; |
74 | bus_space_tag_t sc_iot; | | 74 | bus_space_tag_t sc_iot; |
75 | bus_space_handle_t sc_memh; | | 75 | bus_space_handle_t sc_memh; |
76 | | | 76 | |
77 | bus_space_tag_t sc_regt; | | 77 | bus_space_tag_t sc_regt; |
78 | bus_space_tag_t sc_ioregt; | | 78 | bus_space_tag_t sc_ioregt; |
79 | bus_space_handle_t sc_regh; | | 79 | bus_space_handle_t sc_regh; |
80 | bus_space_handle_t sc_ioregh; | | 80 | bus_space_handle_t sc_ioregh; |
81 | bus_addr_t sc_regs, sc_fb, sc_ioreg; | | 81 | bus_addr_t sc_regs, sc_fb, sc_ioreg; |
82 | bus_size_t sc_regsize, sc_fbsize, sc_ioregsize; | | 82 | bus_size_t sc_regsize, sc_fbsize, sc_ioregsize; |
83 | | | 83 | |
84 | void *sc_ih; | | 84 | void *sc_ih; |
85 | | | 85 | |
86 | size_t memsize; | | 86 | size_t memsize; |
87 | int memtype; | | 87 | int memtype; |
88 | | | 88 | |
89 | int bits_per_pixel; | | 89 | int bits_per_pixel; |
90 | int width, height, linebytes; | | 90 | int width, height, linebytes; |
91 | const struct videomode *sc_videomode; | | 91 | const struct videomode *sc_videomode; |
92 | | | 92 | |
93 | /* i2c stuff */ | | 93 | /* i2c stuff */ |
94 | struct i2c_controller sc_i2c; | | 94 | struct i2c_controller sc_i2c; |
95 | uint8_t sc_edid_data[128]; | | 95 | uint8_t sc_edid_data[128]; |
96 | struct edid_info sc_edid_info; | | 96 | struct edid_info sc_edid_info; |
97 | uint32_t sc_i2creg; | | 97 | uint32_t sc_i2creg; |
98 | | | 98 | |
99 | int sc_mode; | | 99 | int sc_mode; |
100 | uint32_t sc_bg; | | 100 | uint32_t sc_bg; |
101 | | | 101 | |
102 | u_char sc_cmap_red[256]; | | 102 | u_char sc_cmap_red[256]; |
103 | u_char sc_cmap_green[256]; | | 103 | u_char sc_cmap_green[256]; |
104 | u_char sc_cmap_blue[256]; | | 104 | u_char sc_cmap_blue[256]; |
105 | int sc_dacw; | | 105 | int sc_dacw; |
106 | | | 106 | |
107 | struct vcons_data vd; | | 107 | struct vcons_data vd; |
108 | }; | | 108 | }; |
109 | | | 109 | |
110 | struct voodoo_regs { | | 110 | struct voodoo_regs { |
111 | uint8_t vr_crtc[31]; | | 111 | uint8_t vr_crtc[31]; |
112 | uint8_t vr_graph[9]; | | 112 | uint8_t vr_graph[9]; |
113 | uint8_t vr_attr[21]; | | 113 | uint8_t vr_attr[21]; |
114 | uint8_t vr_seq[5]; | | 114 | uint8_t vr_seq[5]; |
115 | }; | | 115 | }; |
116 | | | 116 | |
117 | static struct vcons_screen voodoofb_console_screen; | | 117 | static struct vcons_screen voodoofb_console_screen; |
118 | | | 118 | |
119 | extern const u_char rasops_cmap[768]; | | 119 | extern const u_char rasops_cmap[768]; |
120 | | | 120 | |
121 | static int voodoofb_match(device_t, cfdata_t, void *); | | 121 | static int voodoofb_match(device_t, cfdata_t, void *); |
122 | static void voodoofb_attach(device_t, device_t, void *); | | 122 | static void voodoofb_attach(device_t, device_t, void *); |
123 | | | 123 | |
124 | static int voodoofb_drm_print(void *, const char *); | | 124 | static int voodoofb_drm_print(void *, const char *); |
125 | static int voodoofb_drm_unmap(struct voodoofb_softc *); | | 125 | static int voodoofb_drm_unmap(struct voodoofb_softc *); |
126 | static int voodoofb_drm_map(struct voodoofb_softc *); | | 126 | static int voodoofb_drm_map(struct voodoofb_softc *); |
127 | | | 127 | |
128 | CFATTACH_DECL_NEW(voodoofb, sizeof(struct voodoofb_softc), voodoofb_match, | | 128 | CFATTACH_DECL_NEW(voodoofb, sizeof(struct voodoofb_softc), voodoofb_match, |
129 | voodoofb_attach, NULL, NULL); | | 129 | voodoofb_attach, NULL, NULL); |
130 | | | 130 | |
131 | static bool voodoofb_is_console(struct voodoofb_softc *); | | 131 | static bool voodoofb_is_console(struct voodoofb_softc *); |
132 | static void voodoofb_init(struct voodoofb_softc *); | | 132 | static void voodoofb_init(struct voodoofb_softc *); |
133 | | | 133 | |
134 | static void voodoofb_cursor(void *, int, int, int); | | 134 | static void voodoofb_cursor(void *, int, int, int); |
135 | static void voodoofb_putchar(void *, int, int, u_int, long); | | 135 | static void voodoofb_putchar(void *, int, int, u_int, long); |
136 | static void voodoofb_copycols(void *, int, int, int, int); | | 136 | static void voodoofb_copycols(void *, int, int, int, int); |
137 | static void voodoofb_erasecols(void *, int, int, int, long); | | 137 | static void voodoofb_erasecols(void *, int, int, int, long); |
138 | static void voodoofb_copyrows(void *, int, int, int); | | 138 | static void voodoofb_copyrows(void *, int, int, int); |
139 | static void voodoofb_eraserows(void *, int, int, long); | | 139 | static void voodoofb_eraserows(void *, int, int, long); |
140 | | | 140 | |
141 | #if 0 | | 141 | #if 0 |
142 | static int voodoofb_allocattr(void *, int, int, int, long *); | | 142 | static int voodoofb_allocattr(void *, int, int, int, long *); |
143 | static void voodoofb_scroll(void *, void *, int); | | 143 | static void voodoofb_scroll(void *, void *, int); |
144 | static int voodoofb_load_font(void *, void *, struct wsdisplay_font *); | | 144 | static int voodoofb_load_font(void *, void *, struct wsdisplay_font *); |
145 | #endif | | 145 | #endif |
146 | | | 146 | |
147 | static int voodoofb_putcmap(struct voodoofb_softc *, | | 147 | static int voodoofb_putcmap(struct voodoofb_softc *, |
148 | struct wsdisplay_cmap *); | | 148 | struct wsdisplay_cmap *); |
149 | static int voodoofb_getcmap(struct voodoofb_softc *, | | 149 | static int voodoofb_getcmap(struct voodoofb_softc *, |
150 | struct wsdisplay_cmap *); | | 150 | struct wsdisplay_cmap *); |
151 | static int voodoofb_putpalreg(struct voodoofb_softc *, uint8_t, uint8_t, | | 151 | static int voodoofb_putpalreg(struct voodoofb_softc *, uint8_t, uint8_t, |
152 | uint8_t, uint8_t); | | 152 | uint8_t, uint8_t); |
153 | static void voodoofb_bitblt(struct voodoofb_softc *, int, int, int, int, | | 153 | static void voodoofb_bitblt(struct voodoofb_softc *, int, int, int, int, |
154 | int, int); | | 154 | int, int); |
155 | static void voodoofb_rectfill(struct voodoofb_softc *, int, int, int, int, | | 155 | static void voodoofb_rectfill(struct voodoofb_softc *, int, int, int, int, |
156 | int); | | 156 | int); |
157 | static void voodoofb_rectinvert(struct voodoofb_softc *, int, int, int, | | 157 | static void voodoofb_rectinvert(struct voodoofb_softc *, int, int, int, |
158 | int); | | 158 | int); |
159 | static void voodoofb_setup_mono(struct voodoofb_softc *, int, int, int, | | 159 | static void voodoofb_setup_mono(struct voodoofb_softc *, int, int, int, |
160 | int, uint32_t, uint32_t); | | 160 | int, uint32_t, uint32_t); |
161 | static void voodoofb_feed_line(struct voodoofb_softc *, int, uint8_t *); | | 161 | static void voodoofb_feed_line(struct voodoofb_softc *, int, uint8_t *); |
162 | | | 162 | |
163 | static void voodoofb_wait_idle(struct voodoofb_softc *); | | 163 | static void voodoofb_wait_idle(struct voodoofb_softc *); |
164 | | | 164 | |
165 | #ifdef VOODOOFB_ENABLE_INTR | | 165 | #ifdef VOODOOFB_ENABLE_INTR |
166 | static int voodoofb_intr(void *); | | 166 | static int voodoofb_intr(void *); |
167 | #endif | | 167 | #endif |
168 | | | 168 | |
169 | static void voodoofb_set_videomode(struct voodoofb_softc *, | | 169 | static void voodoofb_set_videomode(struct voodoofb_softc *, |
170 | const struct videomode *); | | 170 | const struct videomode *); |
171 | | | 171 | |
172 | struct wsscreen_descr voodoofb_defaultscreen = { | | 172 | struct wsscreen_descr voodoofb_defaultscreen = { |
173 | "default", | | 173 | "default", |
174 | 0, 0, | | 174 | 0, 0, |
175 | NULL, | | 175 | NULL, |
176 | 8, 16, | | 176 | 8, 16, |
177 | WSSCREEN_WSCOLORS | WSSCREEN_HILIT, | | 177 | WSSCREEN_WSCOLORS | WSSCREEN_HILIT, |
178 | NULL, | | 178 | NULL, |
179 | }; | | 179 | }; |
180 | | | 180 | |
181 | const struct wsscreen_descr *_voodoofb_scrlist[] = { | | 181 | const struct wsscreen_descr *_voodoofb_scrlist[] = { |
182 | &voodoofb_defaultscreen, | | 182 | &voodoofb_defaultscreen, |
183 | /* XXX other formats, graphics screen? */ | | 183 | /* XXX other formats, graphics screen? */ |
184 | }; | | 184 | }; |
185 | | | 185 | |
186 | struct wsscreen_list voodoofb_screenlist = { | | 186 | struct wsscreen_list voodoofb_screenlist = { |
187 | sizeof(_voodoofb_scrlist) / sizeof(struct wsscreen_descr *), _voodoofb_scrlist | | 187 | sizeof(_voodoofb_scrlist) / sizeof(struct wsscreen_descr *), _voodoofb_scrlist |
188 | }; | | 188 | }; |
189 | | | 189 | |
190 | static int voodoofb_ioctl(void *, void *, u_long, void *, int, | | 190 | static int voodoofb_ioctl(void *, void *, u_long, void *, int, |
191 | struct lwp *); | | 191 | struct lwp *); |
192 | static paddr_t voodoofb_mmap(void *, void *, off_t, int); | | 192 | static paddr_t voodoofb_mmap(void *, void *, off_t, int); |
193 | | | 193 | |
194 | static void voodoofb_clearscreen(struct voodoofb_softc *); | | 194 | static void voodoofb_clearscreen(struct voodoofb_softc *); |
195 | static void voodoofb_init_screen(void *, struct vcons_screen *, int, | | 195 | static void voodoofb_init_screen(void *, struct vcons_screen *, int, |
196 | long *); | | 196 | long *); |
197 | | | 197 | |
198 | | | 198 | |
199 | struct wsdisplay_accessops voodoofb_accessops = { | | 199 | struct wsdisplay_accessops voodoofb_accessops = { |
200 | voodoofb_ioctl, | | 200 | voodoofb_ioctl, |
201 | voodoofb_mmap, | | 201 | voodoofb_mmap, |
202 | NULL, | | 202 | NULL, |
203 | NULL, | | 203 | NULL, |
204 | NULL, | | 204 | NULL, |
205 | NULL, /* load_font */ | | 205 | NULL, /* load_font */ |
206 | NULL, /* polls */ | | 206 | NULL, /* polls */ |
207 | NULL, /* scroll */ | | 207 | NULL, /* scroll */ |
208 | }; | | 208 | }; |
209 | | | 209 | |
210 | /* I2C glue */ | | 210 | /* I2C glue */ |
211 | static int voodoofb_i2c_acquire_bus(void *, int); | | 211 | static int voodoofb_i2c_acquire_bus(void *, int); |
212 | static void voodoofb_i2c_release_bus(void *, int); | | 212 | static void voodoofb_i2c_release_bus(void *, int); |
213 | static int voodoofb_i2c_send_start(void *, int); | | 213 | static int voodoofb_i2c_send_start(void *, int); |
214 | static int voodoofb_i2c_send_stop(void *, int); | | 214 | static int voodoofb_i2c_send_stop(void *, int); |
215 | static int voodoofb_i2c_initiate_xfer(void *, i2c_addr_t, int); | | 215 | static int voodoofb_i2c_initiate_xfer(void *, i2c_addr_t, int); |
216 | static int voodoofb_i2c_read_byte(void *, uint8_t *, int); | | 216 | static int voodoofb_i2c_read_byte(void *, uint8_t *, int); |
217 | static int voodoofb_i2c_write_byte(void *, uint8_t, int); | | 217 | static int voodoofb_i2c_write_byte(void *, uint8_t, int); |
218 | | | 218 | |
219 | /* I2C bitbang glue */ | | 219 | /* I2C bitbang glue */ |
220 | static void voodoofb_i2cbb_set_bits(void *, uint32_t); | | 220 | static void voodoofb_i2cbb_set_bits(void *, uint32_t); |
221 | static void voodoofb_i2cbb_set_dir(void *, uint32_t); | | 221 | static void voodoofb_i2cbb_set_dir(void *, uint32_t); |
222 | static uint32_t voodoofb_i2cbb_read(void *); | | 222 | static uint32_t voodoofb_i2cbb_read(void *); |
223 | | | 223 | |
224 | static void voodoofb_setup_i2c(struct voodoofb_softc *); | | 224 | static void voodoofb_setup_i2c(struct voodoofb_softc *); |
225 | | | 225 | |
226 | static const struct i2c_bitbang_ops voodoofb_i2cbb_ops = { | | 226 | static const struct i2c_bitbang_ops voodoofb_i2cbb_ops = { |
227 | voodoofb_i2cbb_set_bits, | | 227 | voodoofb_i2cbb_set_bits, |
228 | voodoofb_i2cbb_set_dir, | | 228 | voodoofb_i2cbb_set_dir, |
229 | voodoofb_i2cbb_read, | | 229 | voodoofb_i2cbb_read, |
230 | { | | 230 | { |
231 | VSP_SDA0_IN, | | 231 | VSP_SDA0_IN, |
232 | VSP_SCL0_IN, | | 232 | VSP_SCL0_IN, |
233 | 0, | | 233 | 0, |
234 | 0 | | 234 | 0 |
235 | } | | 235 | } |
236 | }; | | 236 | }; |
237 | | | 237 | |
238 | /* | | 238 | /* |
239 | * Inline functions for getting access to register aperture. | | 239 | * Inline functions for getting access to register aperture. |
240 | */ | | 240 | */ |
241 | static inline void | | 241 | static inline void |
242 | voodoo3_write32(struct voodoofb_softc *sc, uint32_t reg, uint32_t val) | | 242 | voodoo3_write32(struct voodoofb_softc *sc, uint32_t reg, uint32_t val) |
243 | { | | 243 | { |
244 | bus_space_write_4(sc->sc_regt, sc->sc_regh, reg, val); | | 244 | bus_space_write_4(sc->sc_regt, sc->sc_regh, reg, val); |
245 | } | | 245 | } |
246 | | | 246 | |
247 | static inline uint32_t | | 247 | static inline uint32_t |
248 | voodoo3_read32(struct voodoofb_softc *sc, uint32_t reg) | | 248 | voodoo3_read32(struct voodoofb_softc *sc, uint32_t reg) |
249 | { | | 249 | { |
250 | return bus_space_read_4(sc->sc_regt, sc->sc_regh, reg); | | 250 | return bus_space_read_4(sc->sc_regt, sc->sc_regh, reg); |
251 | } | | 251 | } |
252 | | | 252 | |
253 | static inline void | | 253 | static inline void |
254 | voodoo3_write_crtc(struct voodoofb_softc *sc, uint8_t reg, uint8_t val) | | 254 | voodoo3_write_crtc(struct voodoofb_softc *sc, uint8_t reg, uint8_t val) |
255 | { | | 255 | { |
256 | bus_space_write_1(sc->sc_ioregt, sc->sc_ioregh, CRTC_INDEX - 0x300, reg); | | 256 | bus_space_write_1(sc->sc_ioregt, sc->sc_ioregh, CRTC_INDEX - 0x300, reg); |
257 | bus_space_write_1(sc->sc_ioregt, sc->sc_ioregh, CRTC_DATA - 0x300, val); | | 257 | bus_space_write_1(sc->sc_ioregt, sc->sc_ioregh, CRTC_DATA - 0x300, val); |
258 | } | | 258 | } |
259 | | | 259 | |
260 | static inline void | | 260 | static inline void |
261 | voodoo3_write_seq(struct voodoofb_softc *sc, uint8_t reg, uint8_t val) | | 261 | voodoo3_write_seq(struct voodoofb_softc *sc, uint8_t reg, uint8_t val) |
262 | { | | 262 | { |
263 | bus_space_write_1(sc->sc_ioregt, sc->sc_ioregh, SEQ_INDEX - 0x300, reg); | | 263 | bus_space_write_1(sc->sc_ioregt, sc->sc_ioregh, SEQ_INDEX - 0x300, reg); |
264 | bus_space_write_1(sc->sc_ioregt, sc->sc_ioregh, SEQ_DATA - 0x300, val); | | 264 | bus_space_write_1(sc->sc_ioregt, sc->sc_ioregh, SEQ_DATA - 0x300, val); |
265 | } | | 265 | } |
266 | | | 266 | |
267 | static inline void | | 267 | static inline void |
268 | voodoo3_write_gra(struct voodoofb_softc *sc, uint8_t reg, uint8_t val) | | 268 | voodoo3_write_gra(struct voodoofb_softc *sc, uint8_t reg, uint8_t val) |
269 | { | | 269 | { |
270 | bus_space_write_1(sc->sc_ioregt, sc->sc_ioregh, GRA_INDEX - 0x300, reg); | | 270 | bus_space_write_1(sc->sc_ioregt, sc->sc_ioregh, GRA_INDEX - 0x300, reg); |
271 | bus_space_write_1(sc->sc_ioregt, sc->sc_ioregh, GRA_DATA - 0x300, val); | | 271 | bus_space_write_1(sc->sc_ioregt, sc->sc_ioregh, GRA_DATA - 0x300, val); |
272 | } | | 272 | } |
273 | | | 273 | |
274 | static inline void | | 274 | static inline void |
275 | voodoo3_write_attr(struct voodoofb_softc *sc, uint8_t reg, uint8_t val) | | 275 | voodoo3_write_attr(struct voodoofb_softc *sc, uint8_t reg, uint8_t val) |
276 | { | | 276 | { |
277 | volatile uint8_t junk; | | 277 | volatile uint8_t junk; |
278 | uint8_t index; | | 278 | uint8_t index; |
279 | | | 279 | |
280 | junk = bus_space_read_1(sc->sc_ioregt, sc->sc_ioregh, IS1_R - 0x300); | | 280 | junk = bus_space_read_1(sc->sc_ioregt, sc->sc_ioregh, IS1_R - 0x300); |
281 | index = bus_space_read_1(sc->sc_ioregt, sc->sc_ioregh, ATT_IW - 0x300); | | 281 | index = bus_space_read_1(sc->sc_ioregt, sc->sc_ioregh, ATT_IW - 0x300); |
282 | bus_space_write_1(sc->sc_ioregt, sc->sc_ioregh, ATT_IW - 0x300, reg); | | 282 | bus_space_write_1(sc->sc_ioregt, sc->sc_ioregh, ATT_IW - 0x300, reg); |
283 | bus_space_write_1(sc->sc_ioregt, sc->sc_ioregh, ATT_IW - 0x300, val); | | 283 | bus_space_write_1(sc->sc_ioregt, sc->sc_ioregh, ATT_IW - 0x300, val); |
284 | bus_space_write_1(sc->sc_ioregt, sc->sc_ioregh, ATT_IW - 0x300, index); | | 284 | bus_space_write_1(sc->sc_ioregt, sc->sc_ioregh, ATT_IW - 0x300, index); |
285 | } | | 285 | } |
286 | | | 286 | |
287 | static inline void | | 287 | static inline void |
288 | vga_outb(struct voodoofb_softc *sc, uint32_t reg, uint8_t val) | | 288 | vga_outb(struct voodoofb_softc *sc, uint32_t reg, uint8_t val) |
289 | { | | 289 | { |
290 | bus_space_write_1(sc->sc_ioregt, sc->sc_ioregh, reg - 0x300, val); | | 290 | bus_space_write_1(sc->sc_ioregt, sc->sc_ioregh, reg - 0x300, val); |
291 | } | | 291 | } |
292 | | | 292 | |
293 | /* wait until there's room for len bytes in the FIFO */ | | 293 | /* wait until there's room for len bytes in the FIFO */ |
294 | static inline void | | 294 | static inline void |
295 | voodoo3_make_room(struct voodoofb_softc *sc, int len) | | 295 | voodoo3_make_room(struct voodoofb_softc *sc, int len) |
296 | { | | 296 | { |
297 | while ((voodoo3_read32(sc, STATUS) & 0x1f) < len); | | 297 | while ((voodoo3_read32(sc, STATUS) & 0x1f) < len); |
298 | } | | 298 | } |
299 | | | 299 | |
300 | static void | | 300 | static void |
301 | voodoofb_wait_idle(struct voodoofb_softc *sc) | | 301 | voodoofb_wait_idle(struct voodoofb_softc *sc) |
302 | { | | 302 | { |
303 | int i = 0; | | 303 | int i = 0; |
304 | | | 304 | |
305 | voodoo3_make_room(sc, 1); | | 305 | voodoo3_make_room(sc, 1); |
306 | voodoo3_write32(sc, COMMAND_3D, COMMAND_3D_NOP); | | 306 | voodoo3_write32(sc, COMMAND_3D, COMMAND_3D_NOP); |
307 | | | 307 | |
308 | while (1) { | | 308 | while (1) { |
309 | i = (voodoo3_read32(sc, STATUS) & STATUS_BUSY) ? 0 : i + 1; | | 309 | i = (voodoo3_read32(sc, STATUS) & STATUS_BUSY) ? 0 : i + 1; |
310 | if(i == 3) break; | | 310 | if(i == 3) break; |
311 | } | | 311 | } |
312 | } | | 312 | } |
313 | | | 313 | |
314 | static int | | 314 | static int |
315 | voodoofb_match(device_t parent, cfdata_t match, void *aux) | | 315 | voodoofb_match(device_t parent, cfdata_t match, void *aux) |
316 | { | | 316 | { |
317 | struct pci_attach_args *pa = (struct pci_attach_args *)aux; | | 317 | struct pci_attach_args *pa = (struct pci_attach_args *)aux; |
318 | | | 318 | |
319 | if (PCI_CLASS(pa->pa_class) != PCI_CLASS_DISPLAY || | | 319 | if (PCI_CLASS(pa->pa_class) != PCI_CLASS_DISPLAY || |
320 | PCI_SUBCLASS(pa->pa_class) != PCI_SUBCLASS_DISPLAY_VGA) | | 320 | PCI_SUBCLASS(pa->pa_class) != PCI_SUBCLASS_DISPLAY_VGA) |
321 | return 0; | | 321 | return 0; |
322 | if ((PCI_VENDOR(pa->pa_id)==PCI_VENDOR_3DFX) && | | 322 | if ((PCI_VENDOR(pa->pa_id)==PCI_VENDOR_3DFX) && |
323 | (PCI_PRODUCT(pa->pa_id)>=PCI_PRODUCT_3DFX_VOODOO3)) | | 323 | (PCI_PRODUCT(pa->pa_id)>=PCI_PRODUCT_3DFX_VOODOO3)) |
324 | return 100; | | 324 | return 100; |
325 | return 0; | | 325 | return 0; |
326 | } | | 326 | } |
327 | | | 327 | |
328 | static void | | 328 | static void |
329 | voodoofb_attach(device_t parent, device_t self, void *aux) | | 329 | voodoofb_attach(device_t parent, device_t self, void *aux) |
330 | { | | 330 | { |
331 | struct voodoofb_softc *sc = device_private(self); | | 331 | struct voodoofb_softc *sc = device_private(self); |
332 | struct pci_attach_args *pa = aux; | | 332 | struct pci_attach_args *pa = aux; |
333 | char devinfo[256]; | | 333 | char devinfo[256]; |
334 | struct wsemuldisplaydev_attach_args aa; | | 334 | struct wsemuldisplaydev_attach_args aa; |
335 | struct rasops_info *ri; | | 335 | struct rasops_info *ri; |
336 | #ifdef VOODOOFB_ENABLE_INTR | | 336 | #ifdef VOODOOFB_ENABLE_INTR |
337 | pci_intr_handle_t ih; | | 337 | pci_intr_handle_t ih; |
338 | const char *intrstr; | | 338 | const char *intrstr; |
339 | #endif | | 339 | #endif |
340 | ulong defattr; | | 340 | ulong defattr; |
341 | int console, width, height, i, j; | | 341 | int console, width, height, i, j; |
342 | prop_dictionary_t dict; | | 342 | prop_dictionary_t dict; |
343 | int linebytes, depth, flags; | | 343 | int linebytes, depth, flags; |
344 | uint32_t bg, fg, ul; | | 344 | uint32_t bg, fg, ul; |
345 | | | 345 | |
346 | sc->sc_dev = self; | | 346 | sc->sc_dev = self; |
347 | | | 347 | |
348 | sc->sc_mode = WSDISPLAYIO_MODE_EMUL; | | 348 | sc->sc_mode = WSDISPLAYIO_MODE_EMUL; |
349 | sc->sc_pc = pa->pa_pc; | | 349 | sc->sc_pc = pa->pa_pc; |
350 | sc->sc_pcitag = pa->pa_tag; | | 350 | sc->sc_pcitag = pa->pa_tag; |
351 | sc->sc_dacw = -1; | | 351 | sc->sc_dacw = -1; |
352 | pci_devinfo(pa->pa_id, pa->pa_class, 0, devinfo, sizeof(devinfo)); | | 352 | pci_devinfo(pa->pa_id, pa->pa_class, 0, devinfo, sizeof(devinfo)); |
353 | printf(": %s (rev. 0x%02x)\n", devinfo, PCI_REVISION(pa->pa_class)); | | 353 | printf(": %s (rev. 0x%02x)\n", devinfo, PCI_REVISION(pa->pa_class)); |
354 | | | 354 | |
355 | sc->sc_memt = pa->pa_memt; | | 355 | sc->sc_memt = pa->pa_memt; |
356 | sc->sc_iot = pa->pa_iot; | | 356 | sc->sc_iot = pa->pa_iot; |
357 | sc->sc_pa = *pa; | | 357 | sc->sc_pa = *pa; |
358 | | | 358 | |
359 | /* the framebuffer */ | | 359 | /* the framebuffer */ |
360 | if (pci_mapreg_info(sc->sc_pc, sc->sc_pcitag, 0x14, PCI_MAPREG_TYPE_MEM, | | 360 | if (pci_mapreg_info(sc->sc_pc, sc->sc_pcitag, 0x14, PCI_MAPREG_TYPE_MEM, |
361 | &sc->sc_fb, &sc->sc_fbsize, &flags)) { | | 361 | &sc->sc_fb, &sc->sc_fbsize, &flags)) { |
362 | aprint_error_dev(self, "failed to map the frame buffer.\n"); | | 362 | aprint_error_dev(self, "failed to map the frame buffer.\n"); |
363 | } | | 363 | } |
364 | | | 364 | |
365 | /* memory-mapped registers */ | | 365 | /* memory-mapped registers */ |
366 | if (pci_mapreg_map(pa, 0x10, PCI_MAPREG_TYPE_MEM, 0, | | 366 | if (pci_mapreg_map(pa, 0x10, PCI_MAPREG_TYPE_MEM, 0, |
367 | &sc->sc_regt, &sc->sc_regh, &sc->sc_regs, &sc->sc_regsize)) { | | 367 | &sc->sc_regt, &sc->sc_regh, &sc->sc_regs, &sc->sc_regsize)) { |
368 | aprint_error_dev(self, "failed to map memory-mapped registers.\n"); | | 368 | aprint_error_dev(self, "failed to map memory-mapped registers.\n"); |
369 | } | | 369 | } |
370 | | | 370 | |
371 | /* IO-mapped registers */ | | 371 | /* IO-mapped registers */ |
372 | if (pci_mapreg_map(pa, 0x18, PCI_MAPREG_TYPE_IO, 0, | | 372 | if (pci_mapreg_map(pa, 0x18, PCI_MAPREG_TYPE_IO, 0, |
373 | &sc->sc_ioregt, &sc->sc_ioregh, &sc->sc_ioreg, | | 373 | &sc->sc_ioregt, &sc->sc_ioregh, &sc->sc_ioreg, |
374 | &sc->sc_ioregsize)) { | | 374 | &sc->sc_ioregsize)) { |
375 | aprint_error_dev(self, "failed to map IO-mapped registers.\n"); | | 375 | aprint_error_dev(self, "failed to map IO-mapped registers.\n"); |
376 | } | | 376 | } |
377 | voodoofb_init(sc); | | 377 | voodoofb_init(sc); |
378 | | | 378 | |
379 | /* we should read these from the chip instead of depending on OF */ | | 379 | /* we should read these from the chip instead of depending on OF */ |
380 | width = height = -1; | | 380 | width = height = -1; |
381 | | | 381 | |
382 | dict = device_properties(self); | | 382 | dict = device_properties(self); |
383 | if (!prop_dictionary_get_uint32(dict, "width", &width)) { | | 383 | if (!prop_dictionary_get_uint32(dict, "width", &width)) { |
384 | aprint_error_dev(self, "no width property\n"); | | 384 | aprint_error_dev(self, "no width property\n"); |
385 | return; | | 385 | return; |
386 | } | | 386 | } |
387 | if (!prop_dictionary_get_uint32(dict, "height", &height)) { | | 387 | if (!prop_dictionary_get_uint32(dict, "height", &height)) { |
388 | aprint_error_dev(self, "no height property\n"); | | 388 | aprint_error_dev(self, "no height property\n"); |
389 | return; | | 389 | return; |
390 | } | | 390 | } |
391 | if (!prop_dictionary_get_uint32(dict, "depth", &depth)) { | | 391 | if (!prop_dictionary_get_uint32(dict, "depth", &depth)) { |
392 | aprint_error_dev(self, "no depth property\n"); | | 392 | aprint_error_dev(self, "no depth property\n"); |
393 | return; | | 393 | return; |
394 | } | | 394 | } |
395 | linebytes = width; /* XXX */ | | 395 | linebytes = width; /* XXX */ |
396 | | | 396 | |
397 | if (width == -1 || height == -1) | | 397 | if (width == -1 || height == -1) |
398 | return; | | 398 | return; |
399 | | | 399 | |
400 | sc->width = width; | | 400 | sc->width = width; |
401 | sc->height = height; | | 401 | sc->height = height; |
402 | sc->bits_per_pixel = depth; | | 402 | sc->bits_per_pixel = depth; |
403 | sc->linebytes = linebytes; | | 403 | sc->linebytes = linebytes; |
404 | printf("%s: initial resolution %dx%d, %d bit\n", device_xname(self), | | 404 | printf("%s: initial resolution %dx%d, %d bit\n", device_xname(self), |
405 | sc->width, sc->height, sc->bits_per_pixel); | | 405 | sc->width, sc->height, sc->bits_per_pixel); |
406 | | | 406 | |
407 | sc->sc_videomode = NULL; | | 407 | sc->sc_videomode = NULL; |
408 | voodoofb_setup_i2c(sc); | | 408 | voodoofb_setup_i2c(sc); |
409 | | | 409 | |
410 | /* XXX this should at least be configurable via kernel config */ | | 410 | /* XXX this should at least be configurable via kernel config */ |
411 | if (sc->sc_videomode == NULL) { | | 411 | if (sc->sc_videomode == NULL) { |
412 | sc->sc_videomode = pick_mode_by_ref(width, height, 60); | | 412 | sc->sc_videomode = pick_mode_by_ref(width, height, 60); |
413 | } | | 413 | } |
414 | | | 414 | |
415 | voodoofb_set_videomode(sc, sc->sc_videomode); | | 415 | voodoofb_set_videomode(sc, sc->sc_videomode); |
416 | | | 416 | |
417 | vcons_init(&sc->vd, sc, &voodoofb_defaultscreen, &voodoofb_accessops); | | 417 | vcons_init(&sc->vd, sc, &voodoofb_defaultscreen, &voodoofb_accessops); |
418 | sc->vd.init_screen = voodoofb_init_screen; | | 418 | sc->vd.init_screen = voodoofb_init_screen; |
419 | | | 419 | |
420 | console = voodoofb_is_console(sc); | | 420 | console = voodoofb_is_console(sc); |
421 | | | 421 | |
422 | ri = &voodoofb_console_screen.scr_ri; | | 422 | ri = &voodoofb_console_screen.scr_ri; |
423 | if (console) { | | 423 | if (console) { |
424 | vcons_init_screen(&sc->vd, &voodoofb_console_screen, 1, | | 424 | vcons_init_screen(&sc->vd, &voodoofb_console_screen, 1, |
425 | &defattr); | | 425 | &defattr); |
426 | voodoofb_console_screen.scr_flags |= VCONS_SCREEN_IS_STATIC; | | 426 | voodoofb_console_screen.scr_flags |= VCONS_SCREEN_IS_STATIC; |
427 | | | 427 | |
428 | voodoofb_defaultscreen.textops = &ri->ri_ops; | | 428 | voodoofb_defaultscreen.textops = &ri->ri_ops; |
429 | voodoofb_defaultscreen.capabilities = ri->ri_caps; | | 429 | voodoofb_defaultscreen.capabilities = ri->ri_caps; |
430 | voodoofb_defaultscreen.nrows = ri->ri_rows; | | 430 | voodoofb_defaultscreen.nrows = ri->ri_rows; |
431 | voodoofb_defaultscreen.ncols = ri->ri_cols; | | 431 | voodoofb_defaultscreen.ncols = ri->ri_cols; |
432 | wsdisplay_cnattach(&voodoofb_defaultscreen, ri, 0, 0, defattr); | | 432 | wsdisplay_cnattach(&voodoofb_defaultscreen, ri, 0, 0, defattr); |
433 | } else { | | 433 | } else { |
434 | /* | | 434 | /* |
435 | * since we're not the console we can postpone the rest | | 435 | * since we're not the console we can postpone the rest |
436 | * until someone actually allocates a screen for us | | 436 | * until someone actually allocates a screen for us |
437 | */ | | 437 | */ |
438 | voodoofb_set_videomode(sc, sc->sc_videomode); | | 438 | voodoofb_set_videomode(sc, sc->sc_videomode); |
439 | } | | 439 | } |
440 | | | 440 | |
441 | printf("%s: %d MB aperture at 0x%08x, %d MB registers at 0x%08x\n", | | 441 | printf("%s: %d MB aperture at 0x%08x, %d MB registers at 0x%08x\n", |
442 | device_xname(self), (u_int)(sc->sc_fbsize >> 20), | | 442 | device_xname(self), (u_int)(sc->sc_fbsize >> 20), |
443 | (u_int)sc->sc_fb, (u_int)(sc->sc_regsize >> 20), | | 443 | (u_int)sc->sc_fb, (u_int)(sc->sc_regsize >> 20), |
444 | (u_int)sc->sc_regs); | | 444 | (u_int)sc->sc_regs); |
445 | #ifdef VOODOOFB_DEBUG | | 445 | #ifdef VOODOOFB_DEBUG |
446 | printf("fb: %08lx\n", (ulong)ri->ri_bits); | | 446 | printf("fb: %08lx\n", (ulong)ri->ri_bits); |
447 | #endif | | 447 | #endif |
448 | | | 448 | |
449 | j = 0; | | 449 | j = 0; |
450 | for (i = 0; i < 256; i++) { | | 450 | for (i = 0; i < 256; i++) { |
451 | voodoofb_putpalreg(sc, i, rasops_cmap[j], rasops_cmap[j + 1], | | 451 | voodoofb_putpalreg(sc, i, rasops_cmap[j], rasops_cmap[j + 1], |
452 | rasops_cmap[j + 2]); | | 452 | rasops_cmap[j + 2]); |
453 | j += 3; | | 453 | j += 3; |
454 | } | | 454 | } |
455 | | | 455 | |
456 | #ifdef VOODOOFB_ENABLE_INTR | | 456 | #ifdef VOODOOFB_ENABLE_INTR |
457 | /* Interrupt. We don't use it for anything yet */ | | 457 | /* Interrupt. We don't use it for anything yet */ |
458 | if (pci_intr_map(pa, &ih)) { | | 458 | if (pci_intr_map(pa, &ih)) { |
459 | aprint_error_dev(self, "failed to map interrupt\n"); | | 459 | aprint_error_dev(self, "failed to map interrupt\n"); |
460 | return; | | 460 | return; |
461 | } | | 461 | } |
462 | | | 462 | |
463 | intrstr = pci_intr_string(sc->sc_pc, ih); | | 463 | intrstr = pci_intr_string(sc->sc_pc, ih); |
464 | sc->sc_ih = pci_intr_establish(sc->sc_pc, ih, IPL_NET, voodoofb_intr, | | 464 | sc->sc_ih = pci_intr_establish(sc->sc_pc, ih, IPL_NET, voodoofb_intr, |
465 | sc); | | 465 | sc); |
466 | if (sc->sc_ih == NULL) { | | 466 | if (sc->sc_ih == NULL) { |
467 | aprint_error_dev(self, "failed to establish interrupt"); | | 467 | aprint_error_dev(self, "failed to establish interrupt"); |
468 | if (intrstr != NULL) | | 468 | if (intrstr != NULL) |
469 | aprint_error(" at %s", intrstr); | | 469 | aprint_error(" at %s", intrstr); |
470 | aprint_error("\n"); | | 470 | aprint_error("\n"); |
471 | return; | | 471 | return; |
472 | } | | 472 | } |
473 | aprint_normal_dev(self, "interrupting at %s\n", intrstr); | | 473 | aprint_normal_dev(self, "interrupting at %s\n", intrstr); |
474 | #endif | | 474 | #endif |
475 | | | 475 | |
476 | rasops_unpack_attr(defattr, &fg, &bg, &ul); | | 476 | rasops_unpack_attr(defattr, &fg, &bg, &ul); |
477 | sc->sc_bg = ri->ri_devcmap[bg]; | | 477 | sc->sc_bg = ri->ri_devcmap[bg]; |
478 | voodoofb_clearscreen(sc); | | 478 | voodoofb_clearscreen(sc); |
479 | | | 479 | |
480 | if (console) | | 480 | if (console) |
481 | vcons_replay_msgbuf(&voodoofb_console_screen); | | 481 | vcons_replay_msgbuf(&voodoofb_console_screen); |
482 | aa.console = console; | | 482 | aa.console = console; |
483 | aa.scrdata = &voodoofb_screenlist; | | 483 | aa.scrdata = &voodoofb_screenlist; |
484 | aa.accessops = &voodoofb_accessops; | | 484 | aa.accessops = &voodoofb_accessops; |
485 | aa.accesscookie = &sc->vd; | | 485 | aa.accesscookie = &sc->vd; |
486 | | | 486 | |
487 | config_found(self, &aa, wsemuldisplaydevprint); | | 487 | config_found(self, &aa, wsemuldisplaydevprint); |
488 | config_found_ia(self, "drm", aux, voodoofb_drm_print); | | 488 | config_found_ia(self, "drm", aux, voodoofb_drm_print); |
489 | } | | 489 | } |
490 | | | 490 | |
491 | static int | | 491 | static int |
492 | voodoofb_drm_print(void *opaque, const char *pnp) | | 492 | voodoofb_drm_print(void *opaque, const char *pnp) |
493 | { | | 493 | { |
494 | if (pnp) | | 494 | if (pnp) |
495 | aprint_normal("drm at %s", pnp); | | 495 | aprint_normal("drm at %s", pnp); |
496 | | | 496 | |
497 | return UNCONF; | | 497 | return UNCONF; |
498 | } | | 498 | } |
499 | | | 499 | |
500 | static int | | 500 | static int |
501 | voodoofb_drm_unmap(struct voodoofb_softc *sc) | | 501 | voodoofb_drm_unmap(struct voodoofb_softc *sc) |
502 | { | | 502 | { |
503 | printf("%s: releasing bus resources\n", device_xname(sc->sc_dev)); | | 503 | printf("%s: releasing bus resources\n", device_xname(sc->sc_dev)); |
504 | | | 504 | |
505 | bus_space_unmap(sc->sc_ioregt, sc->sc_ioregh, sc->sc_ioregsize); | | 505 | bus_space_unmap(sc->sc_ioregt, sc->sc_ioregh, sc->sc_ioregsize); |
506 | bus_space_unmap(sc->sc_regt, sc->sc_regh, sc->sc_regsize); | | 506 | bus_space_unmap(sc->sc_regt, sc->sc_regh, sc->sc_regsize); |
507 | | | 507 | |
508 | return 0; | | 508 | return 0; |
509 | } | | 509 | } |
510 | | | 510 | |
511 | static int | | 511 | static int |
512 | voodoofb_drm_map(struct voodoofb_softc *sc) | | 512 | voodoofb_drm_map(struct voodoofb_softc *sc) |
513 | { | | 513 | { |
514 | | | 514 | |
515 | /* memory-mapped registers */ | | 515 | /* memory-mapped registers */ |
516 | if (pci_mapreg_map(&sc->sc_pa, 0x10, PCI_MAPREG_TYPE_MEM, 0, | | 516 | if (pci_mapreg_map(&sc->sc_pa, 0x10, PCI_MAPREG_TYPE_MEM, 0, |
517 | &sc->sc_regt, &sc->sc_regh, &sc->sc_regs, &sc->sc_regsize)) { | | 517 | &sc->sc_regt, &sc->sc_regh, &sc->sc_regs, &sc->sc_regsize)) { |
518 | aprint_error_dev(sc->sc_dev, "failed to map memory-mapped registers.\n"); | | 518 | aprint_error_dev(sc->sc_dev, "failed to map memory-mapped registers.\n"); |
519 | } | | 519 | } |
520 | | | 520 | |
521 | /* IO-mapped registers */ | | 521 | /* IO-mapped registers */ |
522 | if (pci_mapreg_map(&sc->sc_pa, 0x18, PCI_MAPREG_TYPE_IO, 0, | | 522 | if (pci_mapreg_map(&sc->sc_pa, 0x18, PCI_MAPREG_TYPE_IO, 0, |
523 | &sc->sc_ioregt, &sc->sc_ioregh, &sc->sc_ioreg, | | 523 | &sc->sc_ioregt, &sc->sc_ioregh, &sc->sc_ioreg, |
524 | &sc->sc_ioregsize)) { | | 524 | &sc->sc_ioregsize)) { |
525 | aprint_error_dev(sc->sc_dev, "failed to map IO-mapped registers.\n"); | | 525 | aprint_error_dev(sc->sc_dev, "failed to map IO-mapped registers.\n"); |
526 | } | | 526 | } |
527 | | | 527 | |
528 | voodoofb_init(sc); | | 528 | voodoofb_init(sc); |
529 | /* XXX this should at least be configurable via kernel config */ | | 529 | /* XXX this should at least be configurable via kernel config */ |
530 | voodoofb_set_videomode(sc, sc->sc_videomode); | | 530 | voodoofb_set_videomode(sc, sc->sc_videomode); |
531 | | | 531 | |
532 | return 0; | | 532 | return 0; |
533 | } | | 533 | } |
534 | | | 534 | |
535 | static int | | 535 | static int |
536 | voodoofb_putpalreg(struct voodoofb_softc *sc, uint8_t index, uint8_t r, | | 536 | voodoofb_putpalreg(struct voodoofb_softc *sc, uint8_t index, uint8_t r, |
537 | uint8_t g, uint8_t b) | | 537 | uint8_t g, uint8_t b) |
538 | { | | 538 | { |
539 | uint32_t color; | | 539 | uint32_t color; |
540 | | | 540 | |
541 | sc->sc_cmap_red[index] = r; | | 541 | sc->sc_cmap_red[index] = r; |
542 | sc->sc_cmap_green[index] = g; | | 542 | sc->sc_cmap_green[index] = g; |
543 | sc->sc_cmap_blue[index] = b; | | 543 | sc->sc_cmap_blue[index] = b; |
544 | | | 544 | |
545 | color = (r << 16) | (g << 8) | b; | | 545 | color = (r << 16) | (g << 8) | b; |
546 | voodoo3_make_room(sc, 2); | | 546 | voodoo3_make_room(sc, 2); |
547 | voodoo3_write32(sc, DACADDR, index); | | 547 | voodoo3_write32(sc, DACADDR, index); |
548 | voodoo3_write32(sc, DACDATA, color); | | 548 | voodoo3_write32(sc, DACDATA, color); |
549 | | | 549 | |
550 | return 0; | | 550 | return 0; |
551 | } | | 551 | } |
552 | | | 552 | |
553 | static int | | 553 | static int |
554 | voodoofb_putcmap(struct voodoofb_softc *sc, struct wsdisplay_cmap *cm) | | 554 | voodoofb_putcmap(struct voodoofb_softc *sc, struct wsdisplay_cmap *cm) |
555 | { | | 555 | { |
556 | u_char *r, *g, *b; | | 556 | u_char *r, *g, *b; |
557 | u_int index = cm->index; | | 557 | u_int index = cm->index; |
558 | u_int count = cm->count; | | 558 | u_int count = cm->count; |
559 | int i, error; | | 559 | int i, error; |
560 | u_char rbuf[256], gbuf[256], bbuf[256]; | | 560 | u_char rbuf[256], gbuf[256], bbuf[256]; |
561 | | | 561 | |
562 | #ifdef VOODOOFB_DEBUG | | 562 | #ifdef VOODOOFB_DEBUG |
563 | printf("putcmap: %d %d\n",index, count); | | 563 | printf("putcmap: %d %d\n",index, count); |
564 | #endif | | 564 | #endif |
565 | if (cm->index >= 256 || cm->count > 256 || | | 565 | if (cm->index >= 256 || cm->count > 256 || |
566 | (cm->index + cm->count) > 256) | | 566 | (cm->index + cm->count) > 256) |
567 | return EINVAL; | | 567 | return EINVAL; |
568 | error = copyin(cm->red, &rbuf[index], count); | | 568 | error = copyin(cm->red, &rbuf[index], count); |
569 | if (error) | | 569 | if (error) |
570 | return error; | | 570 | return error; |
571 | error = copyin(cm->green, &gbuf[index], count); | | 571 | error = copyin(cm->green, &gbuf[index], count); |
572 | if (error) | | 572 | if (error) |
573 | return error; | | 573 | return error; |
574 | error = copyin(cm->blue, &bbuf[index], count); | | 574 | error = copyin(cm->blue, &bbuf[index], count); |
575 | if (error) | | 575 | if (error) |
576 | return error; | | 576 | return error; |
577 | | | 577 | |
578 | memcpy(&sc->sc_cmap_red[index], &rbuf[index], count); | | 578 | memcpy(&sc->sc_cmap_red[index], &rbuf[index], count); |
579 | memcpy(&sc->sc_cmap_green[index], &gbuf[index], count); | | 579 | memcpy(&sc->sc_cmap_green[index], &gbuf[index], count); |
580 | memcpy(&sc->sc_cmap_blue[index], &bbuf[index], count); | | 580 | memcpy(&sc->sc_cmap_blue[index], &bbuf[index], count); |
581 | | | 581 | |
582 | r = &sc->sc_cmap_red[index]; | | 582 | r = &sc->sc_cmap_red[index]; |
583 | g = &sc->sc_cmap_green[index]; | | 583 | g = &sc->sc_cmap_green[index]; |
584 | b = &sc->sc_cmap_blue[index]; | | 584 | b = &sc->sc_cmap_blue[index]; |
585 | | | 585 | |
586 | for (i = 0; i < count; i++) { | | 586 | for (i = 0; i < count; i++) { |
587 | voodoofb_putpalreg(sc, index, *r, *g, *b); | | 587 | voodoofb_putpalreg(sc, index, *r, *g, *b); |
588 | index++; | | 588 | index++; |
589 | r++, g++, b++; | | 589 | r++, g++, b++; |
590 | } | | 590 | } |
591 | return 0; | | 591 | return 0; |
592 | } | | 592 | } |
593 | | | 593 | |
594 | static int | | 594 | static int |
595 | voodoofb_getcmap(struct voodoofb_softc *sc, struct wsdisplay_cmap *cm) | | 595 | voodoofb_getcmap(struct voodoofb_softc *sc, struct wsdisplay_cmap *cm) |
596 | { | | 596 | { |
597 | u_int index = cm->index; | | 597 | u_int index = cm->index; |
598 | u_int count = cm->count; | | 598 | u_int count = cm->count; |
599 | int error; | | 599 | int error; |
600 | | | 600 | |
601 | if (index >= 255 || count > 256 || index + count > 256) | | 601 | if (index >= 255 || count > 256 || index + count > 256) |
602 | return EINVAL; | | 602 | return EINVAL; |
603 | | | 603 | |
604 | error = copyout(&sc->sc_cmap_red[index], cm->red, count); | | 604 | error = copyout(&sc->sc_cmap_red[index], cm->red, count); |
605 | if (error) | | 605 | if (error) |
606 | return error; | | 606 | return error; |
607 | error = copyout(&sc->sc_cmap_green[index], cm->green, count); | | 607 | error = copyout(&sc->sc_cmap_green[index], cm->green, count); |
608 | if (error) | | 608 | if (error) |
609 | return error; | | 609 | return error; |
610 | error = copyout(&sc->sc_cmap_blue[index], cm->blue, count); | | 610 | error = copyout(&sc->sc_cmap_blue[index], cm->blue, count); |
611 | if (error) | | 611 | if (error) |
612 | return error; | | 612 | return error; |
613 | | | 613 | |
614 | return 0; | | 614 | return 0; |
615 | } | | 615 | } |
616 | | | 616 | |
617 | static bool | | 617 | static bool |
618 | voodoofb_is_console(struct voodoofb_softc *sc) | | 618 | voodoofb_is_console(struct voodoofb_softc *sc) |
619 | { | | 619 | { |
620 | prop_dictionary_t dict; | | 620 | prop_dictionary_t dict; |
621 | bool console; | | 621 | bool console; |
622 | | | 622 | |
623 | dict = device_properties(sc->sc_dev); | | 623 | dict = device_properties(sc->sc_dev); |
624 | prop_dictionary_get_bool(dict, "is_console", &console); | | 624 | prop_dictionary_get_bool(dict, "is_console", &console); |
625 | return console; | | 625 | return console; |
626 | } | | 626 | } |
627 | | | 627 | |
628 | static void | | 628 | static void |
629 | voodoofb_clearscreen(struct voodoofb_softc *sc) | | 629 | voodoofb_clearscreen(struct voodoofb_softc *sc) |
630 | { | | 630 | { |
631 | voodoofb_rectfill(sc, 0, 0, sc->width, sc->height, sc->sc_bg); | | 631 | voodoofb_rectfill(sc, 0, 0, sc->width, sc->height, sc->sc_bg); |
632 | } | | 632 | } |
633 | | | 633 | |
634 | /* | | 634 | /* |
635 | * wsdisplay_emulops | | 635 | * wsdisplay_emulops |
636 | */ | | 636 | */ |
637 | | | 637 | |
638 | static void | | 638 | static void |
639 | voodoofb_cursor(void *cookie, int on, int row, int col) | | 639 | voodoofb_cursor(void *cookie, int on, int row, int col) |
640 | { | | 640 | { |
641 | struct rasops_info *ri = cookie; | | 641 | struct rasops_info *ri = cookie; |
642 | struct vcons_screen *scr = ri->ri_hw; | | 642 | struct vcons_screen *scr = ri->ri_hw; |
643 | struct voodoofb_softc *sc = scr->scr_cookie; | | 643 | struct voodoofb_softc *sc = scr->scr_cookie; |
644 | int x, y, wi, he; | | 644 | int x, y, wi, he; |
645 | | | 645 | |
646 | wi = ri->ri_font->fontwidth; | | 646 | wi = ri->ri_font->fontwidth; |
647 | he = ri->ri_font->fontheight; | | 647 | he = ri->ri_font->fontheight; |
648 | | | 648 | |
649 | if (sc->sc_mode == WSDISPLAYIO_MODE_EMUL) { | | 649 | if (sc->sc_mode == WSDISPLAYIO_MODE_EMUL) { |
650 | x = ri->ri_ccol * wi + ri->ri_xorigin; | | 650 | x = ri->ri_ccol * wi + ri->ri_xorigin; |
651 | y = ri->ri_crow * he + ri->ri_yorigin; | | 651 | y = ri->ri_crow * he + ri->ri_yorigin; |
652 | if (ri->ri_flg & RI_CURSOR) { | | 652 | if (ri->ri_flg & RI_CURSOR) { |
653 | voodoofb_rectinvert(sc, x, y, wi, he); | | 653 | voodoofb_rectinvert(sc, x, y, wi, he); |
654 | ri->ri_flg &= ~RI_CURSOR; | | 654 | ri->ri_flg &= ~RI_CURSOR; |
655 | } | | 655 | } |
656 | ri->ri_crow = row; | | 656 | ri->ri_crow = row; |
657 | ri->ri_ccol = col; | | 657 | ri->ri_ccol = col; |
658 | if (on) | | 658 | if (on) |
659 | { | | 659 | { |
660 | x = ri->ri_ccol * wi + ri->ri_xorigin; | | 660 | x = ri->ri_ccol * wi + ri->ri_xorigin; |
661 | y = ri->ri_crow * he + ri->ri_yorigin; | | 661 | y = ri->ri_crow * he + ri->ri_yorigin; |
662 | voodoofb_rectinvert(sc, x, y, wi, he); | | 662 | voodoofb_rectinvert(sc, x, y, wi, he); |
663 | ri->ri_flg |= RI_CURSOR; | | 663 | ri->ri_flg |= RI_CURSOR; |
664 | } | | 664 | } |
665 | } else { | | 665 | } else { |
666 | ri->ri_flg &= ~RI_CURSOR; | | 666 | ri->ri_flg &= ~RI_CURSOR; |
667 | ri->ri_crow = row; | | 667 | ri->ri_crow = row; |
668 | ri->ri_ccol = col; | | 668 | ri->ri_ccol = col; |
669 | } | | 669 | } |
670 | } | | 670 | } |
671 | | | 671 | |
672 | #if 0 | | 672 | #if 0 |
673 | int | | 673 | int |
674 | voodoofb_mapchar(void *cookie, int uni, u_int *index) | | 674 | voodoofb_mapchar(void *cookie, int uni, u_int *index) |
675 | { | | 675 | { |
676 | return 0; | | 676 | return 0; |
677 | } | | 677 | } |
678 | #endif | | 678 | #endif |
679 | | | 679 | |
680 | static void | | 680 | static void |
681 | voodoofb_putchar(void *cookie, int row, int col, u_int c, long attr) | | 681 | voodoofb_putchar(void *cookie, int row, int col, u_int c, long attr) |
682 | { | | 682 | { |
683 | struct rasops_info *ri = cookie; | | 683 | struct rasops_info *ri = cookie; |
684 | struct wsdisplay_font *font = PICK_FONT(ri, c); | | 684 | struct wsdisplay_font *font = PICK_FONT(ri, c); |
685 | struct vcons_screen *scr = ri->ri_hw; | | 685 | struct vcons_screen *scr = ri->ri_hw; |
686 | struct voodoofb_softc *sc = scr->scr_cookie; | | 686 | struct voodoofb_softc *sc = scr->scr_cookie; |
687 | | | 687 | |
688 | if (sc->sc_mode == WSDISPLAYIO_MODE_EMUL) { | | 688 | if (sc->sc_mode == WSDISPLAYIO_MODE_EMUL) { |
689 | uint8_t *data; | | 689 | uint8_t *data; |
690 | int fg, bg, uc, i; | | 690 | int fg, bg, uc, i; |
691 | int x, y, wi, he; | | 691 | int x, y, wi, he; |
692 | | | 692 | |
693 | wi = font->fontwidth; | | 693 | wi = font->fontwidth; |
694 | he = font->fontheight; | | 694 | he = font->fontheight; |
695 | | | 695 | |
696 | if (!CHAR_IN_FONT(c, font)) | | 696 | if (!CHAR_IN_FONT(c, font)) |
697 | return; | | 697 | return; |
698 | bg = (u_char)ri->ri_devcmap[(attr >> 16) & 0xf]; | | 698 | bg = (u_char)ri->ri_devcmap[(attr >> 16) & 0xf]; |
699 | fg = (u_char)ri->ri_devcmap[(attr >> 24) & 0xf]; | | 699 | fg = (u_char)ri->ri_devcmap[(attr >> 24) & 0xf]; |
700 | x = ri->ri_xorigin + col * wi; | | 700 | x = ri->ri_xorigin + col * wi; |
701 | y = ri->ri_yorigin + row * he; | | 701 | y = ri->ri_yorigin + row * he; |
702 | if (c == 0x20) { | | 702 | if (c == 0x20) { |
703 | voodoofb_rectfill(sc, x, y, wi, he, bg); | | 703 | voodoofb_rectfill(sc, x, y, wi, he, bg); |
704 | } else { | | 704 | } else { |
705 | uc = c - font->firstchar; | | 705 | uc = c - font->firstchar; |
706 | data = (uint8_t *)font->data + uc * | | 706 | data = (uint8_t *)font->data + uc * |
707 | ri->ri_fontscale; | | 707 | ri->ri_fontscale; |
708 | voodoofb_setup_mono(sc, x, y, wi, he, fg, bg); | | 708 | voodoofb_setup_mono(sc, x, y, wi, he, fg, bg); |
709 | for (i = 0; i < he; i++) { | | 709 | for (i = 0; i < he; i++) { |
710 | voodoofb_feed_line(sc, font->stride, data); | | 710 | voodoofb_feed_line(sc, font->stride, data); |
711 | data += font->stride; | | 711 | data += font->stride; |
712 | } | | 712 | } |
713 | } | | 713 | } |
714 | } | | 714 | } |
715 | } | | 715 | } |
716 | | | 716 | |
717 | static void | | 717 | static void |
718 | voodoofb_copycols(void *cookie, int row, int srccol, int dstcol, int ncols) | | 718 | voodoofb_copycols(void *cookie, int row, int srccol, int dstcol, int ncols) |
719 | { | | 719 | { |
720 | struct rasops_info *ri = cookie; | | 720 | struct rasops_info *ri = cookie; |
721 | struct vcons_screen *scr = ri->ri_hw; | | 721 | struct vcons_screen *scr = ri->ri_hw; |
722 | struct voodoofb_softc *sc = scr->scr_cookie; | | 722 | struct voodoofb_softc *sc = scr->scr_cookie; |
723 | int32_t xs, xd, y, width, height; | | 723 | int32_t xs, xd, y, width, height; |
724 | | | 724 | |
725 | if (sc->sc_mode == WSDISPLAYIO_MODE_EMUL) { | | 725 | if (sc->sc_mode == WSDISPLAYIO_MODE_EMUL) { |
726 | xs = ri->ri_xorigin + ri->ri_font->fontwidth * srccol; | | 726 | xs = ri->ri_xorigin + ri->ri_font->fontwidth * srccol; |
727 | xd = ri->ri_xorigin + ri->ri_font->fontwidth * dstcol; | | 727 | xd = ri->ri_xorigin + ri->ri_font->fontwidth * dstcol; |
728 | y = ri->ri_yorigin + ri->ri_font->fontheight * row; | | 728 | y = ri->ri_yorigin + ri->ri_font->fontheight * row; |
729 | width = ri->ri_font->fontwidth * ncols; | | 729 | width = ri->ri_font->fontwidth * ncols; |
730 | height = ri->ri_font->fontheight; | | 730 | height = ri->ri_font->fontheight; |
731 | voodoofb_bitblt(sc, xs, y, xd, y, width, height); | | 731 | voodoofb_bitblt(sc, xs, y, xd, y, width, height); |
732 | } | | 732 | } |
733 | } | | 733 | } |
734 | | | 734 | |
735 | static void | | 735 | static void |
736 | voodoofb_erasecols(void *cookie, int row, int startcol, int ncols, | | 736 | voodoofb_erasecols(void *cookie, int row, int startcol, int ncols, |
737 | long fillattr) | | 737 | long fillattr) |
738 | { | | 738 | { |
739 | struct rasops_info *ri = cookie; | | 739 | struct rasops_info *ri = cookie; |
740 | struct vcons_screen *scr = ri->ri_hw; | | 740 | struct vcons_screen *scr = ri->ri_hw; |
741 | struct voodoofb_softc *sc = scr->scr_cookie; | | 741 | struct voodoofb_softc *sc = scr->scr_cookie; |
742 | int32_t x, y, width, height, fg, bg, ul; | | 742 | int32_t x, y, width, height, fg, bg, ul; |
743 | | | 743 | |
744 | if (sc->sc_mode == WSDISPLAYIO_MODE_EMUL) { | | 744 | if (sc->sc_mode == WSDISPLAYIO_MODE_EMUL) { |
745 | x = ri->ri_xorigin + ri->ri_font->fontwidth * startcol; | | 745 | x = ri->ri_xorigin + ri->ri_font->fontwidth * startcol; |
746 | y = ri->ri_yorigin + ri->ri_font->fontheight * row; | | 746 | y = ri->ri_yorigin + ri->ri_font->fontheight * row; |
747 | width = ri->ri_font->fontwidth * ncols; | | 747 | width = ri->ri_font->fontwidth * ncols; |
748 | height = ri->ri_font->fontheight; | | 748 | height = ri->ri_font->fontheight; |
749 | rasops_unpack_attr(fillattr, &fg, &bg, &ul); | | 749 | rasops_unpack_attr(fillattr, &fg, &bg, &ul); |
750 | | | 750 | |
751 | voodoofb_rectfill(sc, x, y, width, height, ri->ri_devcmap[bg]); | | 751 | voodoofb_rectfill(sc, x, y, width, height, ri->ri_devcmap[bg]); |
752 | } | | 752 | } |
753 | } | | 753 | } |
754 | | | 754 | |
755 | static void | | 755 | static void |
756 | voodoofb_copyrows(void *cookie, int srcrow, int dstrow, int nrows) | | 756 | voodoofb_copyrows(void *cookie, int srcrow, int dstrow, int nrows) |
757 | { | | 757 | { |
758 | struct rasops_info *ri = cookie; | | 758 | struct rasops_info *ri = cookie; |
759 | struct vcons_screen *scr = ri->ri_hw; | | 759 | struct vcons_screen *scr = ri->ri_hw; |
760 | struct voodoofb_softc *sc = scr->scr_cookie; | | 760 | struct voodoofb_softc *sc = scr->scr_cookie; |
761 | int32_t x, ys, yd, width, height; | | 761 | int32_t x, ys, yd, width, height; |
762 | | | 762 | |
763 | if (sc->sc_mode == WSDISPLAYIO_MODE_EMUL) { | | 763 | if (sc->sc_mode == WSDISPLAYIO_MODE_EMUL) { |
764 | x = ri->ri_xorigin; | | 764 | x = ri->ri_xorigin; |
765 | ys = ri->ri_yorigin + ri->ri_font->fontheight * srcrow; | | 765 | ys = ri->ri_yorigin + ri->ri_font->fontheight * srcrow; |
766 | yd = ri->ri_yorigin + ri->ri_font->fontheight * dstrow; | | 766 | yd = ri->ri_yorigin + ri->ri_font->fontheight * dstrow; |
767 | width = ri->ri_emuwidth; | | 767 | width = ri->ri_emuwidth; |
768 | height = ri->ri_font->fontheight * nrows; | | 768 | height = ri->ri_font->fontheight * nrows; |
769 | voodoofb_bitblt(sc, x, ys, x, yd, width, height); | | 769 | voodoofb_bitblt(sc, x, ys, x, yd, width, height); |
770 | } | | 770 | } |
771 | } | | 771 | } |
772 | | | 772 | |
773 | static void | | 773 | static void |
774 | voodoofb_eraserows(void *cookie, int row, int nrows, long fillattr) | | 774 | voodoofb_eraserows(void *cookie, int row, int nrows, long fillattr) |
775 | { | | 775 | { |
776 | struct rasops_info *ri = cookie; | | 776 | struct rasops_info *ri = cookie; |
777 | struct vcons_screen *scr = ri->ri_hw; | | 777 | struct vcons_screen *scr = ri->ri_hw; |
778 | struct voodoofb_softc *sc = scr->scr_cookie; | | 778 | struct voodoofb_softc *sc = scr->scr_cookie; |
779 | int32_t x, y, width, height, fg, bg, ul; | | 779 | int32_t x, y, width, height, fg, bg, ul; |
780 | | | 780 | |
781 | if (sc->sc_mode == WSDISPLAYIO_MODE_EMUL) { | | 781 | if (sc->sc_mode == WSDISPLAYIO_MODE_EMUL) { |
782 | rasops_unpack_attr(fillattr, &fg, &bg, &ul); | | 782 | rasops_unpack_attr(fillattr, &fg, &bg, &ul); |
783 | if ((row == 0) && (nrows == ri->ri_rows)) { | | 783 | if ((row == 0) && (nrows == ri->ri_rows)) { |
784 | /* clear the whole screen */ | | 784 | /* clear the whole screen */ |
785 | voodoofb_rectfill(sc, 0, 0, ri->ri_width, | | 785 | voodoofb_rectfill(sc, 0, 0, ri->ri_width, |
786 | ri->ri_height, ri->ri_devcmap[bg]); | | 786 | ri->ri_height, ri->ri_devcmap[bg]); |
787 | } else { | | 787 | } else { |
788 | x = ri->ri_xorigin; | | 788 | x = ri->ri_xorigin; |
789 | y = ri->ri_yorigin + ri->ri_font->fontheight * row; | | 789 | y = ri->ri_yorigin + ri->ri_font->fontheight * row; |
790 | width = ri->ri_emuwidth; | | 790 | width = ri->ri_emuwidth; |
791 | height = ri->ri_font->fontheight * nrows; | | 791 | height = ri->ri_font->fontheight * nrows; |
792 | voodoofb_rectfill(sc, x, y, width, height, | | 792 | voodoofb_rectfill(sc, x, y, width, height, |
793 | ri->ri_devcmap[bg]); | | 793 | ri->ri_devcmap[bg]); |
794 | } | | 794 | } |
795 | } | | 795 | } |
796 | } | | 796 | } |
797 | | | 797 | |
798 | static void | | 798 | static void |
799 | voodoofb_bitblt(struct voodoofb_softc *sc, int xs, int ys, int xd, int yd, int width, int height) | | 799 | voodoofb_bitblt(struct voodoofb_softc *sc, int xs, int ys, int xd, int yd, int width, int height) |
800 | { | | 800 | { |
801 | uint32_t fmt, blitcmd; | | 801 | uint32_t fmt, blitcmd; |
802 | | | 802 | |
803 | fmt = sc->linebytes | ((sc->bits_per_pixel + | | 803 | fmt = sc->linebytes | ((sc->bits_per_pixel + |
804 | ((sc->bits_per_pixel == 8) ? 0 : 8)) << 13); | | 804 | ((sc->bits_per_pixel == 8) ? 0 : 8)) << 13); |
805 | blitcmd = COMMAND_2D_S2S_BITBLT | (ROP_COPY << 24); | | 805 | blitcmd = COMMAND_2D_S2S_BITBLT | (ROP_COPY << 24); |
806 | | | 806 | |
807 | if (xs <= xd) { | | 807 | if (xs <= xd) { |
808 | blitcmd |= BIT(14); | | 808 | blitcmd |= BIT(14); |
809 | xs += (width - 1); | | 809 | xs += (width - 1); |
810 | xd += (width - 1); | | 810 | xd += (width - 1); |
811 | } | | 811 | } |
812 | if (ys <= yd) { | | 812 | if (ys <= yd) { |
813 | blitcmd |= BIT(15); | | 813 | blitcmd |= BIT(15); |
814 | ys += (height - 1); | | 814 | ys += (height - 1); |
815 | yd += (height - 1); | | 815 | yd += (height - 1); |
816 | } | | 816 | } |
817 | voodoo3_make_room(sc, 6); | | 817 | voodoo3_make_room(sc, 6); |
818 | | | 818 | |
819 | voodoo3_write32(sc, SRCFORMAT, fmt); | | 819 | voodoo3_write32(sc, SRCFORMAT, fmt); |
820 | voodoo3_write32(sc, DSTFORMAT, fmt); | | 820 | voodoo3_write32(sc, DSTFORMAT, fmt); |
821 | voodoo3_write32(sc, DSTSIZE, width | (height << 16)); | | 821 | voodoo3_write32(sc, DSTSIZE, width | (height << 16)); |
822 | voodoo3_write32(sc, DSTXY, xd | (yd << 16)); | | 822 | voodoo3_write32(sc, DSTXY, xd | (yd << 16)); |
823 | voodoo3_write32(sc, SRCXY, xs | (ys << 16)); | | 823 | voodoo3_write32(sc, SRCXY, xs | (ys << 16)); |
824 | voodoo3_write32(sc, COMMAND_2D, blitcmd | SST_2D_GO); | | 824 | voodoo3_write32(sc, COMMAND_2D, blitcmd | SST_2D_GO); |
825 | } | | 825 | } |
826 | | | 826 | |
827 | static void | | 827 | static void |
828 | voodoofb_rectfill(struct voodoofb_softc *sc, int x, int y, int width, | | 828 | voodoofb_rectfill(struct voodoofb_softc *sc, int x, int y, int width, |
829 | int height, int colour) | | 829 | int height, int colour) |
830 | { | | 830 | { |
831 | uint32_t fmt, col; | | 831 | uint32_t fmt, col; |
832 | | | 832 | |
833 | col = (colour << 24) | (colour << 16) | (colour << 8) | colour; | | 833 | col = (colour << 24) | (colour << 16) | (colour << 8) | colour; |
834 | fmt = sc->linebytes | ((sc->bits_per_pixel + | | 834 | fmt = sc->linebytes | ((sc->bits_per_pixel + |
835 | ((sc->bits_per_pixel == 8) ? 0 : 8)) << 13); | | 835 | ((sc->bits_per_pixel == 8) ? 0 : 8)) << 13); |
836 | | | 836 | |
837 | voodoo3_make_room(sc, 6); | | 837 | voodoo3_make_room(sc, 6); |
838 | voodoo3_write32(sc, DSTFORMAT, fmt); | | 838 | voodoo3_write32(sc, DSTFORMAT, fmt); |
839 | voodoo3_write32(sc, COLORFORE, colour); | | 839 | voodoo3_write32(sc, COLORFORE, colour); |
840 | voodoo3_write32(sc, COLORBACK, colour); | | 840 | voodoo3_write32(sc, COLORBACK, colour); |
841 | voodoo3_write32(sc, COMMAND_2D, COMMAND_2D_FILLRECT | (ROP_COPY << 24)); | | 841 | voodoo3_write32(sc, COMMAND_2D, COMMAND_2D_FILLRECT | (ROP_COPY << 24)); |
842 | voodoo3_write32(sc, DSTSIZE, width | (height << 16)); | | 842 | voodoo3_write32(sc, DSTSIZE, width | (height << 16)); |
843 | voodoo3_write32(sc, LAUNCH_2D, x | (y << 16)); | | 843 | voodoo3_write32(sc, LAUNCH_2D, x | (y << 16)); |
844 | } | | 844 | } |
845 | | | 845 | |
846 | static void | | 846 | static void |
847 | voodoofb_rectinvert(struct voodoofb_softc *sc, int x, int y, int width, | | 847 | voodoofb_rectinvert(struct voodoofb_softc *sc, int x, int y, int width, |
848 | int height) | | 848 | int height) |
849 | { | | 849 | { |
850 | uint32_t fmt; | | 850 | uint32_t fmt; |
851 | | | 851 | |
852 | fmt = sc->linebytes | ((sc->bits_per_pixel + | | 852 | fmt = sc->linebytes | ((sc->bits_per_pixel + |
853 | ((sc->bits_per_pixel == 8) ? 0 : 8)) << 13); | | 853 | ((sc->bits_per_pixel == 8) ? 0 : 8)) << 13); |
854 | | | 854 | |
855 | voodoo3_make_room(sc, 6); | | 855 | voodoo3_make_room(sc, 6); |
856 | voodoo3_write32(sc, DSTFORMAT, fmt); | | 856 | voodoo3_write32(sc, DSTFORMAT, fmt); |
857 | voodoo3_write32(sc, COMMAND_2D, COMMAND_2D_FILLRECT | | | 857 | voodoo3_write32(sc, COMMAND_2D, COMMAND_2D_FILLRECT | |
858 | (ROP_INVERT << 24)); | | 858 | (ROP_INVERT << 24)); |
859 | voodoo3_write32(sc, DSTSIZE, width | (height << 16)); | | 859 | voodoo3_write32(sc, DSTSIZE, width | (height << 16)); |
860 | voodoo3_write32(sc, DSTXY, x | (y << 16)); | | 860 | voodoo3_write32(sc, DSTXY, x | (y << 16)); |
861 | voodoo3_write32(sc, LAUNCH_2D, x | (y << 16)); | | 861 | voodoo3_write32(sc, LAUNCH_2D, x | (y << 16)); |
862 | } | | 862 | } |
863 | | | 863 | |
864 | static void | | 864 | static void |
865 | voodoofb_setup_mono(struct voodoofb_softc *sc, int xd, int yd, int width, int height, uint32_t fg, | | 865 | voodoofb_setup_mono(struct voodoofb_softc *sc, int xd, int yd, int width, int height, uint32_t fg, |
866 | uint32_t bg) | | 866 | uint32_t bg) |
867 | { | | 867 | { |
868 | uint32_t dfmt, sfmt = sc->linebytes; | | 868 | uint32_t dfmt, sfmt = sc->linebytes; |
869 | | | 869 | |
870 | dfmt = sc->linebytes | ((sc->bits_per_pixel + | | 870 | dfmt = sc->linebytes | ((sc->bits_per_pixel + |
871 | ((sc->bits_per_pixel == 8) ? 0 : 8)) << 13); | | 871 | ((sc->bits_per_pixel == 8) ? 0 : 8)) << 13); |
872 | | | 872 | |
873 | voodoo3_make_room(sc, 9); | | 873 | voodoo3_make_room(sc, 9); |
874 | voodoo3_write32(sc, SRCFORMAT, sfmt); | | 874 | voodoo3_write32(sc, SRCFORMAT, sfmt); |
875 | voodoo3_write32(sc, DSTFORMAT, dfmt); | | 875 | voodoo3_write32(sc, DSTFORMAT, dfmt); |
876 | voodoo3_write32(sc, COLORFORE, fg); | | 876 | voodoo3_write32(sc, COLORFORE, fg); |
877 | voodoo3_write32(sc, COLORBACK, bg); | | 877 | voodoo3_write32(sc, COLORBACK, bg); |
878 | voodoo3_write32(sc, DSTSIZE, width | (height << 16)); | | 878 | voodoo3_write32(sc, DSTSIZE, width | (height << 16)); |
879 | voodoo3_write32(sc, DSTXY, xd | (yd << 16)); | | 879 | voodoo3_write32(sc, DSTXY, xd | (yd << 16)); |
880 | voodoo3_write32(sc, SRCXY, 0); | | 880 | voodoo3_write32(sc, SRCXY, 0); |
881 | voodoo3_write32(sc, COMMAND_2D, COMMAND_2D_H2S_BITBLT | | | 881 | voodoo3_write32(sc, COMMAND_2D, COMMAND_2D_H2S_BITBLT | |
882 | (ROP_COPY << 24) | SST_2D_GO); | | 882 | (ROP_COPY << 24) | SST_2D_GO); |
883 | | | 883 | |
884 | /* now feed the data into the chip */ | | 884 | /* now feed the data into the chip */ |
885 | } | | 885 | } |
886 | | | 886 | |
887 | static void | | 887 | static void |
888 | voodoofb_feed_line(struct voodoofb_softc *sc, int count, uint8_t *data) | | 888 | voodoofb_feed_line(struct voodoofb_softc *sc, int count, uint8_t *data) |
889 | { | | 889 | { |
890 | int i; | | 890 | int i; |
891 | uint32_t latch = 0, bork; | | 891 | uint32_t latch = 0, bork; |
892 | int shift = 0; | | 892 | int shift = 0; |
893 | | | 893 | |
894 | voodoo3_make_room(sc, count); | | 894 | voodoo3_make_room(sc, count); |
895 | for (i = 0; i < count; i++) { | | 895 | for (i = 0; i < count; i++) { |
896 | bork = data[i]; | | 896 | bork = data[i]; |
897 | latch |= (bork << shift); | | 897 | latch |= (bork << shift); |
898 | if (shift == 24) { | | 898 | if (shift == 24) { |
899 | voodoo3_write32(sc, LAUNCH_2D, latch); | | 899 | voodoo3_write32(sc, LAUNCH_2D, latch); |
900 | latch = 0; | | 900 | latch = 0; |
901 | shift = 0; | | 901 | shift = 0; |
902 | } else | | 902 | } else |
903 | shift += 8; | | 903 | shift += 8; |
904 | } | | 904 | } |
905 | if (shift != 24) | | 905 | if (shift != 24) |
906 | voodoo3_write32(sc, LAUNCH_2D, latch); | | 906 | voodoo3_write32(sc, LAUNCH_2D, latch); |
907 | } | | 907 | } |
908 | | | 908 | |
909 | #if 0 | | 909 | #if 0 |
910 | static int | | 910 | static int |
911 | voodoofb_allocattr(void *cookie, int fg, int bg, int flags, long *attrp) | | 911 | voodoofb_allocattr(void *cookie, int fg, int bg, int flags, long *attrp) |
912 | { | | 912 | { |
913 | | | 913 | |
914 | return 0; | | 914 | return 0; |
915 | } | | 915 | } |
916 | #endif | | 916 | #endif |
917 | | | 917 | |
918 | /* | | 918 | /* |
919 | * wsdisplay_accessops | | 919 | * wsdisplay_accessops |
920 | */ | | 920 | */ |
921 | | | 921 | |
922 | static int | | 922 | static int |
923 | voodoofb_ioctl(void *v, void *vs, u_long cmd, void *data, int flag, | | 923 | voodoofb_ioctl(void *v, void *vs, u_long cmd, void *data, int flag, |
924 | struct lwp *l) | | 924 | struct lwp *l) |
925 | { | | 925 | { |
926 | struct vcons_data *vd = v; | | 926 | struct vcons_data *vd = v; |
927 | struct voodoofb_softc *sc = vd->cookie; | | 927 | struct voodoofb_softc *sc = vd->cookie; |
928 | struct wsdisplay_fbinfo *wdf; | | 928 | struct wsdisplay_fbinfo *wdf; |
929 | struct vcons_screen *ms = vd->active; | | 929 | struct vcons_screen *ms = vd->active; |
930 | | | 930 | |
931 | switch (cmd) { | | 931 | switch (cmd) { |
932 | case WSDISPLAYIO_GTYPE: | | 932 | case WSDISPLAYIO_GTYPE: |
933 | *(u_int *)data = WSDISPLAY_TYPE_PCIMISC; | | 933 | *(u_int *)data = WSDISPLAY_TYPE_PCIMISC; |
934 | return 0; | | 934 | return 0; |
935 | | | 935 | |
936 | case WSDISPLAYIO_GINFO: | | 936 | case WSDISPLAYIO_GINFO: |
937 | wdf = (void *)data; | | 937 | wdf = (void *)data; |
938 | wdf->height = ms->scr_ri.ri_height; | | 938 | wdf->height = ms->scr_ri.ri_height; |
939 | wdf->width = ms->scr_ri.ri_width; | | 939 | wdf->width = ms->scr_ri.ri_width; |
940 | wdf->depth = ms->scr_ri.ri_depth; | | 940 | wdf->depth = ms->scr_ri.ri_depth; |
941 | wdf->cmsize = 256; | | 941 | wdf->cmsize = 256; |
942 | return 0; | | 942 | return 0; |
943 | | | 943 | |
944 | case WSDISPLAYIO_GETCMAP: | | 944 | case WSDISPLAYIO_GETCMAP: |
945 | return voodoofb_getcmap(sc, | | 945 | return voodoofb_getcmap(sc, |
946 | (struct wsdisplay_cmap *)data); | | 946 | (struct wsdisplay_cmap *)data); |
947 | | | 947 | |
948 | case WSDISPLAYIO_PUTCMAP: | | 948 | case WSDISPLAYIO_PUTCMAP: |
949 | return voodoofb_putcmap(sc, | | 949 | return voodoofb_putcmap(sc, |
950 | (struct wsdisplay_cmap *)data); | | 950 | (struct wsdisplay_cmap *)data); |
951 | | | 951 | |
952 | /* PCI config read/write passthrough. */ | | 952 | /* PCI config read/write passthrough. */ |
953 | case PCI_IOC_CFGREAD: | | 953 | case PCI_IOC_CFGREAD: |
954 | case PCI_IOC_CFGWRITE: | | 954 | case PCI_IOC_CFGWRITE: |
955 | return pci_devioctl(sc->sc_pc, sc->sc_pcitag, | | 955 | return pci_devioctl(sc->sc_pc, sc->sc_pcitag, |
956 | cmd, data, flag, l); | | 956 | cmd, data, flag, l); |
957 | | | 957 | |
958 | case WSDISPLAYIO_GET_BUSID: | | 958 | case WSDISPLAYIO_GET_BUSID: |
959 | return wsdisplayio_busid_pci(sc->sc_dev, sc->sc_pc, | | 959 | return wsdisplayio_busid_pci(sc->sc_dev, sc->sc_pc, |
960 | sc->sc_pcitag, data); | | 960 | sc->sc_pcitag, data); |
961 | | | 961 | |
962 | case WSDISPLAYIO_SMODE: { | | 962 | case WSDISPLAYIO_SMODE: { |
963 | int new_mode = *(int*)data; | | 963 | int new_mode = *(int*)data; |
964 | if (new_mode != sc->sc_mode) { | | 964 | if (new_mode != sc->sc_mode) { |
965 | sc->sc_mode = new_mode; | | 965 | sc->sc_mode = new_mode; |
966 | if (new_mode == WSDISPLAYIO_MODE_EMUL) { | | 966 | if (new_mode == WSDISPLAYIO_MODE_EMUL) { |
967 | voodoofb_drm_map(sc); | | 967 | voodoofb_drm_map(sc); |
968 | int i; | | 968 | int i; |
969 | | | 969 | |
970 | /* restore the palette */ | | 970 | /* restore the palette */ |
971 | for (i = 0; i < 256; i++) { | | 971 | for (i = 0; i < 256; i++) { |
972 | voodoofb_putpalreg(sc, | | 972 | voodoofb_putpalreg(sc, |
973 | i, | | 973 | i, |
974 | sc->sc_cmap_red[i], | | 974 | sc->sc_cmap_red[i], |
975 | sc->sc_cmap_green[i], | | 975 | sc->sc_cmap_green[i], |
976 | sc->sc_cmap_blue[i]); | | 976 | sc->sc_cmap_blue[i]); |
977 | } | | 977 | } |
978 | vcons_redraw_screen(ms); | | 978 | vcons_redraw_screen(ms); |
979 | } else | | 979 | } else { |
980 | voodoofb_drm_unmap(sc); | | 980 | voodoofb_drm_unmap(sc); |
| | | 981 | } |
981 | } | | 982 | } |
982 | } | | 983 | } |
983 | return 0; | | 984 | return 0; |
984 | } | | 985 | } |
985 | return EPASSTHROUGH; | | 986 | return EPASSTHROUGH; |
986 | } | | 987 | } |
987 | | | 988 | |
988 | static paddr_t | | 989 | static paddr_t |
989 | voodoofb_mmap(void *v, void *vs, off_t offset, int prot) | | 990 | voodoofb_mmap(void *v, void *vs, off_t offset, int prot) |
990 | { | | 991 | { |
991 | struct vcons_data *vd = v; | | 992 | struct vcons_data *vd = v; |
992 | struct voodoofb_softc *sc = vd->cookie; | | 993 | struct voodoofb_softc *sc = vd->cookie; |
993 | paddr_t pa; | | 994 | paddr_t pa; |
994 | | | 995 | |
995 | /* 'regular' framebuffer mmap()ing */ | | 996 | /* 'regular' framebuffer mmap()ing */ |
996 | if (offset < sc->sc_fbsize) { | | 997 | if (offset < sc->sc_fbsize) { |
997 | pa = bus_space_mmap(sc->sc_memt, offset, 0, prot, | | 998 | pa = bus_space_mmap(sc->sc_memt, offset, 0, prot, |
998 | BUS_SPACE_MAP_LINEAR); | | 999 | BUS_SPACE_MAP_LINEAR); |
999 | return pa; | | 1000 | return pa; |
1000 | } | | 1001 | } |
1001 | | | 1002 | |
1002 | /* | | 1003 | /* |
1003 | * restrict all other mappings to processes with superuser privileges | | 1004 | * restrict all other mappings to processes with superuser privileges |
1004 | * or the kernel itself | | 1005 | * or the kernel itself |
1005 | */ | | 1006 | */ |
1006 | if (kauth_authorize_generic(kauth_cred_get(), KAUTH_GENERIC_ISSUSER, | | 1007 | if (kauth_authorize_generic(kauth_cred_get(), KAUTH_GENERIC_ISSUSER, |
1007 | NULL) != 0) { | | 1008 | NULL) != 0) { |
1008 | aprint_error_dev(sc->sc_dev, "mmap() rejected.\n"); | | 1009 | aprint_error_dev(sc->sc_dev, "mmap() rejected.\n"); |
1009 | return -1; | | 1010 | return -1; |
1010 | } | | 1011 | } |
1011 | | | 1012 | |
1012 | if ((offset >= sc->sc_fb) && (offset < (sc->sc_fb + sc->sc_fbsize))) { | | 1013 | if ((offset >= sc->sc_fb) && (offset < (sc->sc_fb + sc->sc_fbsize))) { |
1013 | pa = bus_space_mmap(sc->sc_memt, offset, 0, prot, | | 1014 | pa = bus_space_mmap(sc->sc_memt, offset, 0, prot, |
1014 | BUS_SPACE_MAP_LINEAR); | | 1015 | BUS_SPACE_MAP_LINEAR); |
1015 | return pa; | | 1016 | return pa; |
1016 | } | | 1017 | } |
1017 | | | 1018 | |
1018 | if ((offset >= sc->sc_regs) && (offset < (sc->sc_regs + | | 1019 | if ((offset >= sc->sc_regs) && (offset < (sc->sc_regs + |
1019 | sc->sc_regsize))) { | | 1020 | sc->sc_regsize))) { |
1020 | pa = bus_space_mmap(sc->sc_memt, offset, 0, prot, | | 1021 | pa = bus_space_mmap(sc->sc_memt, offset, 0, prot, |
1021 | BUS_SPACE_MAP_LINEAR); | | 1022 | BUS_SPACE_MAP_LINEAR); |
1022 | return pa; | | 1023 | return pa; |
1023 | } | | 1024 | } |
1024 | | | 1025 | |
1025 | #ifdef PCI_MAGIC_IO_RANGE | | 1026 | #ifdef PCI_MAGIC_IO_RANGE |
1026 | /* allow mapping of IO space */ | | 1027 | /* allow mapping of IO space */ |
1027 | if ((offset >= PCI_MAGIC_IO_RANGE) &&\ | | 1028 | if ((offset >= PCI_MAGIC_IO_RANGE) &&\ |
1028 | (offset < PCI_MAGIC_IO_RANGE + 0x10000)) { | | 1029 | (offset < PCI_MAGIC_IO_RANGE + 0x10000)) { |
1029 | pa = bus_space_mmap(sc->sc_iot, offset - PCI_MAGIC_IO_RANGE, | | 1030 | pa = bus_space_mmap(sc->sc_iot, offset - PCI_MAGIC_IO_RANGE, |
1030 | 0, prot, BUS_SPACE_MAP_LINEAR); | | 1031 | 0, prot, BUS_SPACE_MAP_LINEAR); |
1031 | return pa; | | 1032 | return pa; |
1032 | } | | 1033 | } |
1033 | #endif | | 1034 | #endif |
1034 | | | 1035 | |
1035 | #ifdef OFB_ALLOW_OTHERS | | 1036 | #ifdef OFB_ALLOW_OTHERS |
1036 | if (offset >= 0x80000000) { | | 1037 | if (offset >= 0x80000000) { |
1037 | pa = bus_space_mmap(sc->sc_memt, offset, 0, prot, | | 1038 | pa = bus_space_mmap(sc->sc_memt, offset, 0, prot, |
1038 | BUS_SPACE_MAP_LINEAR); | | 1039 | BUS_SPACE_MAP_LINEAR); |
1039 | return pa; | | 1040 | return pa; |
1040 | } | | 1041 | } |
1041 | #endif | | 1042 | #endif |
1042 | return -1; | | 1043 | return -1; |
1043 | } | | 1044 | } |
1044 | | | 1045 | |
1045 | static void | | 1046 | static void |
1046 | voodoofb_init_screen(void *cookie, struct vcons_screen *scr, | | 1047 | voodoofb_init_screen(void *cookie, struct vcons_screen *scr, |
1047 | int existing, long *defattr) | | 1048 | int existing, long *defattr) |
1048 | { | | 1049 | { |
1049 | struct voodoofb_softc *sc = cookie; | | 1050 | struct voodoofb_softc *sc = cookie; |
1050 | struct rasops_info *ri = &scr->scr_ri; | | 1051 | struct rasops_info *ri = &scr->scr_ri; |
1051 | | | 1052 | |
1052 | ri->ri_depth = sc->bits_per_pixel; | | 1053 | ri->ri_depth = sc->bits_per_pixel; |
1053 | ri->ri_width = sc->width; | | 1054 | ri->ri_width = sc->width; |
1054 | ri->ri_height = sc->height; | | 1055 | ri->ri_height = sc->height; |
1055 | ri->ri_stride = sc->width; | | 1056 | ri->ri_stride = sc->width; |
1056 | ri->ri_flg = RI_CENTER; | | 1057 | ri->ri_flg = RI_CENTER; |
1057 | | | 1058 | |
1058 | rasops_init(ri, 0, 0); | | 1059 | rasops_init(ri, 0, 0); |
1059 | ri->ri_caps = WSSCREEN_WSCOLORS; | | 1060 | ri->ri_caps = WSSCREEN_WSCOLORS; |
1060 | | | 1061 | |
1061 | rasops_reconfig(ri, sc->height / ri->ri_font->fontheight, | | 1062 | rasops_reconfig(ri, sc->height / ri->ri_font->fontheight, |
1062 | sc->width / ri->ri_font->fontwidth); | | 1063 | sc->width / ri->ri_font->fontwidth); |
1063 | | | 1064 | |
1064 | ri->ri_hw = scr; | | 1065 | ri->ri_hw = scr; |
1065 | ri->ri_ops.copyrows = voodoofb_copyrows; | | 1066 | ri->ri_ops.copyrows = voodoofb_copyrows; |
1066 | ri->ri_ops.copycols = voodoofb_copycols; | | 1067 | ri->ri_ops.copycols = voodoofb_copycols; |
1067 | ri->ri_ops.eraserows = voodoofb_eraserows; | | 1068 | ri->ri_ops.eraserows = voodoofb_eraserows; |
1068 | ri->ri_ops.erasecols = voodoofb_erasecols; | | 1069 | ri->ri_ops.erasecols = voodoofb_erasecols; |
1069 | ri->ri_ops.cursor = voodoofb_cursor; | | 1070 | ri->ri_ops.cursor = voodoofb_cursor; |
1070 | ri->ri_ops.putchar = voodoofb_putchar; | | 1071 | ri->ri_ops.putchar = voodoofb_putchar; |
1071 | } | | 1072 | } |
1072 | | | 1073 | |
1073 | #if 0 | | 1074 | #if 0 |
1074 | int | | 1075 | int |
1075 | voodoofb_load_font(void *v, void *cookie, struct wsdisplay_font *data) | | 1076 | voodoofb_load_font(void *v, void *cookie, struct wsdisplay_font *data) |
1076 | { | | 1077 | { |
1077 | | | 1078 | |
1078 | return 0; | | 1079 | return 0; |
1079 | } | | 1080 | } |
1080 | #endif | | 1081 | #endif |
1081 | | | 1082 | |
1082 | #ifdef VOODOOFB_ENABLE_INTR | | 1083 | #ifdef VOODOOFB_ENABLE_INTR |
1083 | static int | | 1084 | static int |
1084 | voodoofb_intr(void *arg) | | 1085 | voodoofb_intr(void *arg) |
1085 | { | | 1086 | { |
1086 | struct voodoofb_softc *sc = arg; | | 1087 | struct voodoofb_softc *sc = arg; |
1087 | | | 1088 | |
1088 | voodoo3_write32(sc, V3_STATUS, 0); /* clear interrupts */ | | 1089 | voodoo3_write32(sc, V3_STATUS, 0); /* clear interrupts */ |
1089 | return 1; | | 1090 | return 1; |
1090 | } | | 1091 | } |
1091 | #endif | | 1092 | #endif |
1092 | | | 1093 | |
1093 | /* video mode stuff */ | | 1094 | /* video mode stuff */ |
1094 | | | 1095 | |
1095 | #define REFFREQ 14318 /* .18 */ | | 1096 | #define REFFREQ 14318 /* .18 */ |
1096 | | | 1097 | |
1097 | #define ABS(a) ((a < 0) ? -a : a) | | 1098 | #define ABS(a) ((a < 0) ? -a : a) |
1098 | | | 1099 | |
1099 | static int | | 1100 | static int |
1100 | voodoofb_calc_pll(int freq, int *f_out, int isBanshee) | | 1101 | voodoofb_calc_pll(int freq, int *f_out, int isBanshee) |
1101 | { | | 1102 | { |
1102 | int m, n, k, best_m, best_n, best_k, f_cur, best_error; | | 1103 | int m, n, k, best_m, best_n, best_k, f_cur, best_error; |
1103 | int minm, maxm; | | 1104 | int minm, maxm; |
1104 | | | 1105 | |
1105 | best_error = freq; | | 1106 | best_error = freq; |
1106 | best_n = best_m = best_k = 0; | | 1107 | best_n = best_m = best_k = 0; |
1107 | | | 1108 | |
1108 | if (isBanshee) { | | 1109 | if (isBanshee) { |
1109 | minm = 24; | | 1110 | minm = 24; |
1110 | maxm = 24; | | 1111 | maxm = 24; |
1111 | } else { | | 1112 | } else { |
1112 | minm = 1; | | 1113 | minm = 1; |
1113 | maxm = 57; | | 1114 | maxm = 57; |
1114 | /* This used to be 64, alas it seems the last 8 (funny that ?) | | 1115 | /* This used to be 64, alas it seems the last 8 (funny that ?) |
1115 | * values cause jittering at lower resolutions. I've not done | | 1116 | * values cause jittering at lower resolutions. I've not done |
1116 | * any calculations to what the adjustment affects clock ranges, | | 1117 | * any calculations to what the adjustment affects clock ranges, |
1117 | * but I can still run at 1600x1200@75Hz */ | | 1118 | * but I can still run at 1600x1200@75Hz */ |
1118 | } | | 1119 | } |
1119 | for (n = 1; n < 256; n++) { | | 1120 | for (n = 1; n < 256; n++) { |
1120 | f_cur = REFFREQ * (n + 2); | | 1121 | f_cur = REFFREQ * (n + 2); |
1121 | if (f_cur < freq) { | | 1122 | if (f_cur < freq) { |
1122 | f_cur = f_cur / 3; | | 1123 | f_cur = f_cur / 3; |
1123 | if (freq - f_cur < best_error) { | | 1124 | if (freq - f_cur < best_error) { |
1124 | best_error = freq - f_cur; | | 1125 | best_error = freq - f_cur; |
1125 | best_n = n; | | 1126 | best_n = n; |
1126 | best_m = 1; | | 1127 | best_m = 1; |
1127 | best_k = 0; | | 1128 | best_k = 0; |
1128 | continue; | | 1129 | continue; |
1129 | } | | 1130 | } |
1130 | } | | 1131 | } |
1131 | for (m = minm; m < maxm; m++) { | | 1132 | for (m = minm; m < maxm; m++) { |
1132 | for (k = 0; k < 4; k++) { | | 1133 | for (k = 0; k < 4; k++) { |
1133 | f_cur = REFFREQ * (n + 2) / (m + 2) / (1 << k); | | 1134 | f_cur = REFFREQ * (n + 2) / (m + 2) / (1 << k); |
1134 | if (ABS(f_cur - freq) < best_error) { | | 1135 | if (ABS(f_cur - freq) < best_error) { |
1135 | best_error = ABS(f_cur - freq); | | 1136 | best_error = ABS(f_cur - freq); |
1136 | best_n = n; | | 1137 | best_n = n; |
1137 | best_m = m; | | 1138 | best_m = m; |
1138 | best_k = k; | | 1139 | best_k = k; |
1139 | } | | 1140 | } |
1140 | } | | 1141 | } |
1141 | } | | 1142 | } |
1142 | } | | 1143 | } |
1143 | n = best_n; | | 1144 | n = best_n; |
1144 | m = best_m; | | 1145 | m = best_m; |
1145 | k = best_k; | | 1146 | k = best_k; |
1146 | *f_out = REFFREQ * (n + 2) / (m + 2) / (1 << k); | | 1147 | *f_out = REFFREQ * (n + 2) / (m + 2) / (1 << k); |
1147 | return ( n << 8) | (m << 2) | k; | | 1148 | return ( n << 8) | (m << 2) | k; |
1148 | } | | 1149 | } |
1149 | | | 1150 | |
1150 | static void | | 1151 | static void |
1151 | voodoofb_setup_monitor(struct voodoofb_softc *sc, const struct videomode *vm) | | 1152 | voodoofb_setup_monitor(struct voodoofb_softc *sc, const struct videomode *vm) |
1152 | { | | 1153 | { |
1153 | struct voodoo_regs mod; | | 1154 | struct voodoo_regs mod; |
1154 | struct voodoo_regs *mode; | | 1155 | struct voodoo_regs *mode; |
1155 | uint32_t horizontal_display_end, horizontal_sync_start, | | 1156 | uint32_t horizontal_display_end, horizontal_sync_start, |
1156 | horizontal_sync_end, horizontal_total, | | 1157 | horizontal_sync_end, horizontal_total, |
1157 | horizontal_blanking_start, horizontal_blanking_end; | | 1158 | horizontal_blanking_start, horizontal_blanking_end; |
1158 | | | 1159 | |
1159 | uint32_t vertical_display_enable_end, vertical_sync_start, | | 1160 | uint32_t vertical_display_enable_end, vertical_sync_start, |
1160 | vertical_sync_end, vertical_total, vertical_blanking_start, | | 1161 | vertical_sync_end, vertical_total, vertical_blanking_start, |
1161 | vertical_blanking_end; | | 1162 | vertical_blanking_end; |
1162 | | | 1163 | |
1163 | uint32_t wd; // CRTC offset | | 1164 | uint32_t wd; // CRTC offset |
1164 | | | 1165 | |
1165 | int i; | | 1166 | int i; |
1166 | | | 1167 | |
1167 | uint8_t misc; | | 1168 | uint8_t misc; |
1168 | | | 1169 | |
1169 | memset(&mod, 0, sizeof(mode)); | | 1170 | memset(&mod, 0, sizeof(mode)); |
1170 | | | 1171 | |
1171 | mode = &mod; | | 1172 | mode = &mod; |
1172 | | | 1173 | |
1173 | wd = (vm->hdisplay >> 3) - 1; | | 1174 | wd = (vm->hdisplay >> 3) - 1; |
1174 | horizontal_display_end = (vm->hdisplay >> 3) - 1; | | 1175 | horizontal_display_end = (vm->hdisplay >> 3) - 1; |
1175 | horizontal_sync_start = (vm->hsync_start >> 3) - 1; | | 1176 | horizontal_sync_start = (vm->hsync_start >> 3) - 1; |
1176 | horizontal_sync_end = (vm->hsync_end >> 3) - 1; | | 1177 | horizontal_sync_end = (vm->hsync_end >> 3) - 1; |
1177 | horizontal_total = (vm->htotal >> 3) - 1; | | 1178 | horizontal_total = (vm->htotal >> 3) - 1; |
1178 | horizontal_blanking_start = horizontal_display_end; | | 1179 | horizontal_blanking_start = horizontal_display_end; |
1179 | horizontal_blanking_end = horizontal_total; | | 1180 | horizontal_blanking_end = horizontal_total; |
1180 | | | 1181 | |
1181 | vertical_display_enable_end = vm->vdisplay - 1; | | 1182 | vertical_display_enable_end = vm->vdisplay - 1; |
1182 | vertical_sync_start = vm->vsync_start; // - 1; | | 1183 | vertical_sync_start = vm->vsync_start; // - 1; |
1183 | vertical_sync_end = vm->vsync_end; // - 1; | | 1184 | vertical_sync_end = vm->vsync_end; // - 1; |
1184 | vertical_total = vm->vtotal - 2; | | 1185 | vertical_total = vm->vtotal - 2; |
1185 | vertical_blanking_start = vertical_display_enable_end; | | 1186 | vertical_blanking_start = vertical_display_enable_end; |
1186 | vertical_blanking_end = vertical_total; | | 1187 | vertical_blanking_end = vertical_total; |
1187 | | | 1188 | |
| | | 1189 | #if 0 |
1188 | misc = 0x0f | | | 1190 | misc = 0x0f | |
1189 | (vm->hdisplay < 400 ? 0xa0 : | | 1191 | (vm->hdisplay < 400 ? 0xa0 : |
1190 | vm->hdisplay < 480 ? 0x60 : | | 1192 | vm->hdisplay < 480 ? 0x60 : |
1191 | vm->hdisplay < 768 ? 0xe0 : 0x20); | | 1193 | vm->hdisplay < 768 ? 0xe0 : 0x20); |
1192 | | | 1194 | #else |
| | | 1195 | misc = 0x2f; |
| | | 1196 | if (vm->flags & VID_NHSYNC) |
| | | 1197 | misc |= HSYNC_NEG; |
| | | 1198 | if (vm->flags & VID_NVSYNC) |
| | | 1199 | misc |= VSYNC_NEG; |
| | | 1200 | #ifdef VOODOOFB_DEBUG |
| | | 1201 | printf("misc: %02x\n", misc); |
| | | 1202 | #endif |
| | | 1203 | #endif |
1193 | mode->vr_seq[0] = 3; | | 1204 | mode->vr_seq[0] = 3; |
1194 | mode->vr_seq[1] = 1; | | 1205 | mode->vr_seq[1] = 1; |
1195 | mode->vr_seq[2] = 8; | | 1206 | mode->vr_seq[2] = 8; |
1196 | mode->vr_seq[3] = 0; | | 1207 | mode->vr_seq[3] = 0; |
1197 | mode->vr_seq[4] = 6; | | 1208 | mode->vr_seq[4] = 6; |
1198 | | | 1209 | |
1199 | /* crtc regs start */ | | 1210 | /* crtc regs start */ |
1200 | mode->vr_crtc[0] = horizontal_total - 4; | | 1211 | mode->vr_crtc[0] = horizontal_total - 4; |
1201 | mode->vr_crtc[1] = horizontal_display_end; | | 1212 | mode->vr_crtc[1] = horizontal_display_end; |
1202 | mode->vr_crtc[2] = horizontal_blanking_start; | | 1213 | mode->vr_crtc[2] = horizontal_blanking_start; |
1203 | mode->vr_crtc[3] = 0x80 | (horizontal_blanking_end & 0x1f); | | 1214 | mode->vr_crtc[3] = 0x80 | (horizontal_blanking_end & 0x1f); |
1204 | mode->vr_crtc[4] = horizontal_sync_start; | | 1215 | mode->vr_crtc[4] = horizontal_sync_start; |
1205 | | | 1216 | |
1206 | mode->vr_crtc[5] = ((horizontal_blanking_end & 0x20) << 2) | | | 1217 | mode->vr_crtc[5] = ((horizontal_blanking_end & 0x20) << 2) | |
1207 | (horizontal_sync_end & 0x1f); | | 1218 | (horizontal_sync_end & 0x1f); |
1208 | mode->vr_crtc[6] = vertical_total; | | 1219 | mode->vr_crtc[6] = vertical_total; |
1209 | mode->vr_crtc[7] = ((vertical_sync_start & 0x200) >> 2) | | | 1220 | mode->vr_crtc[7] = ((vertical_sync_start & 0x200) >> 2) | |
1210 | ((vertical_display_enable_end & 0x200) >> 3) | | | 1221 | ((vertical_display_enable_end & 0x200) >> 3) | |
1211 | ((vertical_total & 0x200) >> 4) | | | 1222 | ((vertical_total & 0x200) >> 4) | |
1212 | 0x10 | | | 1223 | 0x10 | |
1213 | ((vertical_blanking_start & 0x100) >> 5) | | | 1224 | ((vertical_blanking_start & 0x100) >> 5) | |
1214 | ((vertical_sync_start & 0x100) >> 6) | | | 1225 | ((vertical_sync_start & 0x100) >> 6) | |
1215 | ((vertical_display_enable_end & 0x100) >> 7) | | | 1226 | ((vertical_display_enable_end & 0x100) >> 7) | |
1216 | ((vertical_total & 0x100) >> 8); | | 1227 | ((vertical_total & 0x100) >> 8); |
1217 | | | 1228 | |
1218 | mode->vr_crtc[8] = 0; | | 1229 | mode->vr_crtc[8] = 0; |
1219 | mode->vr_crtc[9] = 0x40 | | | 1230 | mode->vr_crtc[9] = 0x40 | |
1220 | ((vertical_blanking_start & 0x200) >> 4); | | 1231 | ((vertical_blanking_start & 0x200) >> 4); |
1221 | | | 1232 | |
1222 | mode->vr_crtc[10] = 0; | | 1233 | mode->vr_crtc[10] = 0; |
1223 | mode->vr_crtc[11] = 0; | | 1234 | mode->vr_crtc[11] = 0; |
1224 | mode->vr_crtc[12] = 0; | | 1235 | mode->vr_crtc[12] = 0; |
1225 | mode->vr_crtc[13] = 0; | | 1236 | mode->vr_crtc[13] = 0; |
1226 | mode->vr_crtc[14] = 0; | | 1237 | mode->vr_crtc[14] = 0; |
1227 | mode->vr_crtc[15] = 0; | | 1238 | mode->vr_crtc[15] = 0; |
1228 | | | 1239 | |
1229 | mode->vr_crtc[16] = vertical_sync_start; | | 1240 | mode->vr_crtc[16] = vertical_sync_start; |
1230 | mode->vr_crtc[17] = (vertical_sync_end & 0x0f) | 0x20; | | 1241 | mode->vr_crtc[17] = (vertical_sync_end & 0x0f) | 0x20; |
1231 | mode->vr_crtc[18] = vertical_display_enable_end; | | 1242 | mode->vr_crtc[18] = vertical_display_enable_end; |
1232 | mode->vr_crtc[19] = wd; // CRTC offset | | 1243 | mode->vr_crtc[19] = wd; // CRTC offset |
1233 | mode->vr_crtc[20] = 0; | | 1244 | mode->vr_crtc[20] = 0; |
1234 | mode->vr_crtc[21] = vertical_blanking_start; | | 1245 | mode->vr_crtc[21] = vertical_blanking_start; |
1235 | mode->vr_crtc[22] = vertical_blanking_end + 1; | | 1246 | mode->vr_crtc[22] = vertical_blanking_end + 1; |
1236 | mode->vr_crtc[23] = 128; | | 1247 | mode->vr_crtc[23] = 128; |
1237 | mode->vr_crtc[24] = 255; | | 1248 | mode->vr_crtc[24] = 255; |
1238 | | | 1249 | |
1239 | /* overflow registers */ | | 1250 | /* overflow registers */ |
1240 | mode->vr_crtc[CRTC_HDISP_EXT] = | | 1251 | mode->vr_crtc[CRTC_HDISP_EXT] = |
1241 | (horizontal_total&0x100) >> 8 | | | 1252 | (horizontal_total&0x100) >> 8 | |
1242 | (horizontal_display_end & 0x100) >> 6 | | | 1253 | (horizontal_display_end & 0x100) >> 6 | |
1243 | (horizontal_blanking_start & 0x100) >> 4 | | | 1254 | (horizontal_blanking_start & 0x100) >> 4 | |
1244 | (horizontal_blanking_end & 0x40) >> 1 | | | 1255 | (horizontal_blanking_end & 0x40) >> 1 | |
1245 | (horizontal_sync_start & 0x100) >> 2 | | | 1256 | (horizontal_sync_start & 0x100) >> 2 | |
1246 | (horizontal_sync_end & 0x20) << 2; | | 1257 | (horizontal_sync_end & 0x20) << 2; |
1247 | | | 1258 | |
1248 | mode->vr_crtc[CRTC_VDISP_EXT] = | | 1259 | mode->vr_crtc[CRTC_VDISP_EXT] = |
1249 | (vertical_total & 0x400) >> 10 | | | 1260 | (vertical_total & 0x400) >> 10 | |
1250 | (vertical_display_enable_end & 0x400) >> 8 | | | 1261 | (vertical_display_enable_end & 0x400) >> 8 | /* the manual is contradictory here */ |
1251 | (vertical_blanking_start & 0x400) >> 6 | | | 1262 | (vertical_blanking_start & 0x400) >> 6 | |
1252 | (vertical_blanking_end & 0x400) >> 4; | | 1263 | (vertical_blanking_end & 0x400) >> 4; |
1253 | | | 1264 | |
1254 | /* attr regs start */ | | 1265 | /* attr regs start */ |
1255 | mode->vr_attr[0] = 0; | | 1266 | mode->vr_attr[0] = 0; |
1256 | mode->vr_attr[1] = 0; | | 1267 | mode->vr_attr[1] = 0; |
1257 | mode->vr_attr[2] = 0; | | 1268 | mode->vr_attr[2] = 0; |
1258 | mode->vr_attr[3] = 0; | | 1269 | mode->vr_attr[3] = 0; |
1259 | mode->vr_attr[4] = 0; | | 1270 | mode->vr_attr[4] = 0; |
1260 | mode->vr_attr[5] = 0; | | 1271 | mode->vr_attr[5] = 0; |
1261 | mode->vr_attr[6] = 0; | | 1272 | mode->vr_attr[6] = 0; |
1262 | mode->vr_attr[7] = 0; | | 1273 | mode->vr_attr[7] = 0; |
1263 | mode->vr_attr[8] = 0; | | 1274 | mode->vr_attr[8] = 0; |
1264 | mode->vr_attr[9] = 0; | | 1275 | mode->vr_attr[9] = 0; |
1265 | mode->vr_attr[10] = 0; | | 1276 | mode->vr_attr[10] = 0; |
1266 | mode->vr_attr[11] = 0; | | 1277 | mode->vr_attr[11] = 0; |
1267 | mode->vr_attr[12] = 0; | | 1278 | mode->vr_attr[12] = 0; |
1268 | mode->vr_attr[13] = 0; | | 1279 | mode->vr_attr[13] = 0; |
1269 | mode->vr_attr[14] = 0; | | 1280 | mode->vr_attr[14] = 0; |
1270 | mode->vr_attr[15] = 0; | | 1281 | mode->vr_attr[15] = 0; |
1271 | mode->vr_attr[16] = 1; | | 1282 | mode->vr_attr[16] = 1; |
1272 | mode->vr_attr[17] = 0; | | 1283 | mode->vr_attr[17] = 0; |
1273 | mode->vr_attr[18] = 15; | | 1284 | mode->vr_attr[18] = 15; |
1274 | mode->vr_attr[19] = 0; | | 1285 | mode->vr_attr[19] = 0; |
1275 | /* attr regs end */ | | 1286 | /* attr regs end */ |
1276 | | | 1287 | |
1277 | /* graph regs start */ | | 1288 | /* graph regs start */ |
1278 | mode->vr_graph[0] = 159; | | 1289 | mode->vr_graph[0] = 159; |
1279 | mode->vr_graph[1] = 127; | | 1290 | mode->vr_graph[1] = 127; |
1280 | mode->vr_graph[2] = 127; | | 1291 | mode->vr_graph[2] = 127; |
1281 | mode->vr_graph[3] = 131; | | 1292 | mode->vr_graph[3] = 131; |
1282 | mode->vr_graph[4] = 130; | | 1293 | mode->vr_graph[4] = 130; |
1283 | mode->vr_graph[5] = 142; | | 1294 | mode->vr_graph[5] = 142; |
1284 | mode->vr_graph[6] = 30; | | 1295 | mode->vr_graph[6] = 30; |
1285 | mode->vr_graph[7] = 245; | | 1296 | mode->vr_graph[7] = 245; |
1286 | mode->vr_graph[8] = 0; | | 1297 | mode->vr_graph[8] = 0; |
1287 | | | 1298 | |
1288 | vga_outb(sc, MISC_W, misc | 0x01); | | 1299 | vga_outb(sc, MISC_W, misc | 0x01); |
1289 | | | 1300 | |
1290 | for(i = 0; i < 5; i++) | | 1301 | for(i = 0; i < 5; i++) |
1291 | voodoo3_write_seq(sc, i, mode->vr_seq[i]); | | 1302 | voodoo3_write_seq(sc, i, mode->vr_seq[i]); |
1292 | for (i = 0; i < CRTC_PCI_READBACK; i ++) | | 1303 | for (i = 0; i < CRTC_PCI_READBACK; i ++) |
1293 | voodoo3_write_crtc(sc, i, mode->vr_crtc[i]); | | 1304 | voodoo3_write_crtc(sc, i, mode->vr_crtc[i]); |
1294 | for (i = 0; i < 0x14; i ++) | | 1305 | for (i = 0; i < 0x14; i ++) |
1295 | voodoo3_write_attr(sc, i, mode->vr_attr[i]); | | 1306 | voodoo3_write_attr(sc, i, mode->vr_attr[i]); |
1296 | for (i = 0; i < 0x09; i ++) | | 1307 | for (i = 0; i < 0x09; i ++) |
1297 | voodoo3_write_gra(sc, i, mode->vr_graph[i]); | | 1308 | voodoo3_write_gra(sc, i, mode->vr_graph[i]); |
1298 | } | | 1309 | } |
1299 | | | 1310 | |
1300 | static void | | 1311 | static void |
1301 | voodoofb_set_videomode(struct voodoofb_softc *sc, | | 1312 | voodoofb_set_videomode(struct voodoofb_softc *sc, |
1302 | const struct videomode *vm) | | 1313 | const struct videomode *vm) |
1303 | { | | 1314 | { |
1304 | uint32_t miscinit0 = 0; | | 1315 | uint32_t miscinit0 = 0; |
1305 | int vidpll, fout; | | 1316 | int vidpll, fout; |
1306 | uint32_t vp, vidproc = VIDPROCDEFAULT; | | 1317 | uint32_t vp, vidproc = VIDPROCDEFAULT; |
1307 | uint32_t bpp = 1; /* for now */ | | 1318 | uint32_t bpp = 1; /* for now */ |
1308 | uint32_t bytes_per_row = vm->hdisplay * bpp; | | 1319 | uint32_t bytes_per_row = vm->hdisplay * bpp; |
1309 | | | 1320 | |
1310 | sc->bits_per_pixel = bpp << 3; | | 1321 | sc->bits_per_pixel = bpp << 3; |
1311 | sc->width = vm->hdisplay; | | 1322 | sc->width = vm->hdisplay; |
1312 | sc->height = vm->vdisplay; | | 1323 | sc->height = vm->vdisplay; |
1313 | sc->linebytes = bytes_per_row; | | 1324 | sc->linebytes = bytes_per_row; |
1314 | | | 1325 | |
1315 | voodoofb_setup_monitor(sc, vm); | | 1326 | voodoofb_setup_monitor(sc, vm); |
1316 | vp = voodoo3_read32(sc, VIDPROCCFG); | | 1327 | vp = voodoo3_read32(sc, VIDPROCCFG); |
1317 | | | 1328 | |
1318 | vidproc &= ~(0x1c0000); /* clear bits 18 to 20, bpp in vidproccfg */ | | 1329 | vidproc &= ~(0x1c0000); /* clear bits 18 to 20, bpp in vidproccfg */ |
1319 | /* enable bits 18 to 20 to the required bpp */ | | 1330 | /* enable bits 18 to 20 to the required bpp */ |
1320 | vidproc |= ((bpp - 1) << VIDCFG_PIXFMT_SHIFT); | | 1331 | vidproc |= ((bpp - 1) << VIDCFG_PIXFMT_SHIFT); |
1321 | | | 1332 | |
1322 | vidpll = voodoofb_calc_pll(vm->dot_clock, &fout, 0); | | 1333 | vidpll = voodoofb_calc_pll(vm->dot_clock, &fout, 0); |
1323 | | | 1334 | |
1324 | #ifdef VOODOOFB_DEBUG | | 1335 | #ifdef VOODOOFB_DEBUG |
1325 | printf("old vidproc: %08x\n", vp); | | 1336 | printf("old vidproc: %08x\n", vp); |
1326 | printf("pll: %08x %d\n", vidpll, fout); | | 1337 | printf("pll: %08x %d\n", vidpll, fout); |
1327 | #endif | | 1338 | #endif |
1328 | /* bit 10 of vidproccfg, is enabled or disabled as needed */ | | 1339 | /* bit 10 of vidproccfg, is enabled or disabled as needed */ |
1329 | switch (bpp) { | | 1340 | switch (bpp) { |
1330 | case 1: | | 1341 | case 1: |
1331 | /* | | 1342 | /* |
1332 | * bit 10 off for palettized modes only, off means | | 1343 | * bit 10 off for palettized modes only, off means |
1333 | * palette is used | | 1344 | * palette is used |
1334 | */ | | 1345 | */ |
1335 | vidproc &= ~(1 << 10); | | 1346 | vidproc &= ~(1 << 10); |
1336 | break; | | 1347 | break; |
1337 | #if 0 | | 1348 | #if 0 |
1338 | case 2: | | 1349 | case 2: |
1339 | #if __POWERPC__ | | 1350 | #if __POWERPC__ |
1340 | miscinit0 = 0xc0000000; | | 1351 | miscinit0 = 0xc0000000; |
1341 | #endif | | 1352 | #endif |
1342 | /* bypass palette for 16bit modes */ | | 1353 | /* bypass palette for 16bit modes */ |
1343 | vidproc |= (1 << 10); | | 1354 | vidproc |= (1 << 10); |
1344 | break; | | 1355 | break; |
1345 | case 4: | | 1356 | case 4: |
1346 | #if __POWERPC__ | | 1357 | #if __POWERPC__ |
1347 | miscinit0 = 0x40000000; | | 1358 | miscinit0 = 0x40000000; |
1348 | #endif | | 1359 | #endif |
1349 | vidproc |= (1 << 10); /* Same for 32bit modes */ | | 1360 | vidproc |= (1 << 10); /* Same for 32bit modes */ |
1350 | break; | | 1361 | break; |
1351 | #endif | | 1362 | #endif |
1352 | default: | | 1363 | default: |
1353 | printf("We support only 8 bit for now\n"); | | 1364 | printf("We support only 8 bit for now\n"); |
1354 | return; | | 1365 | return; |
1355 | } | | 1366 | } |
1356 | | | 1367 | |
1357 | voodoofb_wait_idle(sc); | | 1368 | voodoofb_wait_idle(sc); |
1358 | | | 1369 | |
1359 | voodoo3_write32(sc, MISCINIT1, voodoo3_read32(sc, MISCINIT1) | 0x01); | | 1370 | voodoo3_write32(sc, MISCINIT1, voodoo3_read32(sc, MISCINIT1) | 0x01); |
1360 | | | 1371 | |
1361 | voodoo3_make_room(sc, 4); | | 1372 | voodoo3_make_room(sc, 4); |
1362 | voodoo3_write32(sc, VGAINIT0, 4928); | | 1373 | voodoo3_write32(sc, VGAINIT0, 4928); |
1363 | voodoo3_write32(sc, DACMODE, 0); | | 1374 | voodoo3_write32(sc, DACMODE, 0); |
1364 | voodoo3_write32(sc, VIDDESKSTRIDE, bytes_per_row); | | 1375 | voodoo3_write32(sc, VIDDESKSTRIDE, bytes_per_row); |
1365 | voodoo3_write32(sc, PLLCTRL0, vidpll); | | 1376 | voodoo3_write32(sc, PLLCTRL0, vidpll); |
1366 | | | 1377 | |
1367 | voodoo3_make_room(sc, 5); | | 1378 | voodoo3_make_room(sc, 5); |
1368 | voodoo3_write32(sc, VIDSCREENSIZE, sc->width | (sc->height << 12)); | | 1379 | voodoo3_write32(sc, VIDSCREENSIZE, sc->width | (sc->height << 12)); |
1369 | voodoo3_write32(sc, VIDDESKSTART, 0); | | 1380 | voodoo3_write32(sc, VIDDESKSTART, 0); |
1370 | | | 1381 | |
1371 | vidproc &= ~VIDCFG_HWCURSOR_ENABLE; | | 1382 | vidproc &= ~VIDCFG_HWCURSOR_ENABLE; |
1372 | voodoo3_write32(sc, VIDPROCCFG, vidproc); | | 1383 | voodoo3_write32(sc, VIDPROCCFG, vidproc); |
1373 | | | 1384 | |
1374 | voodoo3_write32(sc, VGAINIT1, 0); | | 1385 | voodoo3_write32(sc, VGAINIT1, 0); |
1375 | voodoo3_write32(sc, MISCINIT0, miscinit0); | | 1386 | voodoo3_write32(sc, MISCINIT0, miscinit0); |
1376 | #ifdef VOODOOFB_DEBUG | | 1387 | #ifdef VOODOOFB_DEBUG |
1377 | printf("vidproc: %08x\n", vidproc); | | 1388 | printf("vidproc: %08x\n", vidproc); |
1378 | #endif | | 1389 | #endif |
1379 | voodoo3_make_room(sc, 8); | | 1390 | voodoo3_make_room(sc, 8); |
1380 | voodoo3_write32(sc, SRCBASE, 0); | | 1391 | voodoo3_write32(sc, SRCBASE, 0); |
1381 | voodoo3_write32(sc, DSTBASE, 0); | | 1392 | voodoo3_write32(sc, DSTBASE, 0); |
1382 | voodoo3_write32(sc, COMMANDEXTRA_2D, 0); | | 1393 | voodoo3_write32(sc, COMMANDEXTRA_2D, 0); |
1383 | voodoo3_write32(sc, CLIP0MIN, 0); | | 1394 | voodoo3_write32(sc, CLIP0MIN, 0); |
1384 | voodoo3_write32(sc, CLIP0MAX, 0x0fff0fff); | | 1395 | voodoo3_write32(sc, CLIP0MAX, 0x0fff0fff); |
1385 | voodoo3_write32(sc, CLIP1MIN, 0); | | 1396 | voodoo3_write32(sc, CLIP1MIN, 0); |
1386 | voodoo3_write32(sc, CLIP1MAX, 0x0fff0fff); | | 1397 | voodoo3_write32(sc, CLIP1MAX, 0x0fff0fff); |
1387 | voodoo3_write32(sc, SRCXY, 0); | | 1398 | voodoo3_write32(sc, SRCXY, 0); |
1388 | voodoofb_wait_idle(sc); | | 1399 | voodoofb_wait_idle(sc); |
1389 | printf("%s: switched to %dx%d, %d bit\n", device_xname(sc->sc_dev), | | 1400 | printf("%s: switched to %dx%d, %d bit\n", device_xname(sc->sc_dev), |
1390 | sc->width, sc->height, sc->bits_per_pixel); | | 1401 | sc->width, sc->height, sc->bits_per_pixel); |
1391 | } | | 1402 | } |
1392 | | | 1403 | |
1393 | static void | | 1404 | static void |
1394 | voodoofb_init(struct voodoofb_softc *sc) | | 1405 | voodoofb_init(struct voodoofb_softc *sc) |
1395 | { | | 1406 | { |
1396 | /* XXX */ | | 1407 | /* XXX */ |
1397 | uint32_t vgainit0 = 0; | | 1408 | uint32_t vgainit0 = 0; |
1398 | uint32_t vidcfg = 0; | | 1409 | uint32_t vidcfg = 0; |
1399 | | | 1410 | |
1400 | #ifdef VOODOOFB_DEBUG | | 1411 | #ifdef VOODOOFB_DEBUG |
1401 | printf("initializing engine..."); | | 1412 | printf("initializing engine..."); |
1402 | #endif | | 1413 | #endif |
1403 | vgainit0 = voodoo3_read32(sc, VGAINIT0); | | 1414 | vgainit0 = voodoo3_read32(sc, VGAINIT0); |
1404 | #ifdef VOODOOFB_DEBUG | | 1415 | #ifdef VOODOOFB_DEBUG |
1405 | printf("vga: %08x", vgainit0); | | 1416 | printf("vga: %08x", vgainit0); |
1406 | #endif | | 1417 | #endif |
1407 | vgainit0 |= | | 1418 | vgainit0 |= |
1408 | VGAINIT0_8BIT_DAC | | | 1419 | VGAINIT0_8BIT_DAC | |
1409 | VGAINIT0_EXT_ENABLE | | | 1420 | VGAINIT0_EXT_ENABLE | |
1410 | VGAINIT0_WAKEUP_3C3 | | | 1421 | VGAINIT0_WAKEUP_3C3 | |
1411 | VGAINIT0_ALT_READBACK | | | 1422 | VGAINIT0_ALT_READBACK | |
1412 | VGAINIT0_EXTSHIFTOUT; | | 1423 | VGAINIT0_EXTSHIFTOUT; |
1413 | | | 1424 | |
1414 | vidcfg = voodoo3_read32(sc, VIDPROCCFG); | | 1425 | vidcfg = voodoo3_read32(sc, VIDPROCCFG); |
1415 | #ifdef VOODOOFB_DEBUG | | 1426 | #ifdef VOODOOFB_DEBUG |
1416 | printf(" vidcfg: %08x\n", vidcfg); | | 1427 | printf(" vidcfg: %08x\n", vidcfg); |
1417 | #endif | | 1428 | #endif |
1418 | vidcfg |= | | 1429 | vidcfg |= |
1419 | VIDCFG_VIDPROC_ENABLE | | | 1430 | VIDCFG_VIDPROC_ENABLE | |
1420 | VIDCFG_DESK_ENABLE; | | 1431 | VIDCFG_DESK_ENABLE; |
1421 | vidcfg &= ~VIDCFG_HWCURSOR_ENABLE; | | 1432 | vidcfg &= ~VIDCFG_HWCURSOR_ENABLE; |
1422 | | | 1433 | |
1423 | voodoo3_make_room(sc, 2); | | 1434 | voodoo3_make_room(sc, 2); |
1424 | | | 1435 | |
1425 | voodoo3_write32(sc, VGAINIT0, vgainit0); | | 1436 | voodoo3_write32(sc, VGAINIT0, vgainit0); |
1426 | voodoo3_write32(sc, VIDPROCCFG, vidcfg); | | 1437 | voodoo3_write32(sc, VIDPROCCFG, vidcfg); |
1427 | | | 1438 | |
1428 | voodoo3_make_room(sc, 8); | | 1439 | voodoo3_make_room(sc, 8); |
1429 | voodoo3_write32(sc, SRCBASE, 0); | | 1440 | voodoo3_write32(sc, SRCBASE, 0); |
1430 | voodoo3_write32(sc, DSTBASE, 0); | | 1441 | voodoo3_write32(sc, DSTBASE, 0); |
1431 | voodoo3_write32(sc, COMMANDEXTRA_2D, 0); | | 1442 | voodoo3_write32(sc, COMMANDEXTRA_2D, 0); |
1432 | voodoo3_write32(sc, CLIP0MIN, 0); | | 1443 | voodoo3_write32(sc, CLIP0MIN, 0); |
1433 | voodoo3_write32(sc, CLIP0MAX, 0x1fff1fff); | | 1444 | voodoo3_write32(sc, CLIP0MAX, 0x1fff1fff); |
1434 | voodoo3_write32(sc, CLIP1MIN, 0); | | 1445 | voodoo3_write32(sc, CLIP1MIN, 0); |
1435 | voodoo3_write32(sc, CLIP1MAX, 0x1fff1fff); | | 1446 | voodoo3_write32(sc, CLIP1MAX, 0x1fff1fff); |
1436 | voodoo3_write32(sc, SRCXY, 0); | | 1447 | voodoo3_write32(sc, SRCXY, 0); |
1437 | | | 1448 | |
1438 | voodoofb_wait_idle(sc); | | 1449 | voodoofb_wait_idle(sc); |
1439 | } | | 1450 | } |
1440 | | | 1451 | |
| | | 1452 | #define MAX_CLOCK 250000 /* all Voodoo3 should support that */ |
| | | 1453 | #define MAX_HRES 1700 /* |
| | | 1454 | * XXX in theory we can go higher but I |
| | | 1455 | * couldn't get anything above 1680 x 1200 |
| | | 1456 | * to work, so until I find out why it's |
| | | 1457 | * disabled so people won't end up with a |
| | | 1458 | * blank screen |
| | | 1459 | */ |
| | | 1460 | #define MODE_IS_VALID(m) (((m)->dot_clock <= MAX_CLOCK) && \ |
| | | 1461 | ((m)->hdisplay < MAX_HRES)) |
1441 | static void | | 1462 | static void |
1442 | voodoofb_setup_i2c(struct voodoofb_softc *sc) | | 1463 | voodoofb_setup_i2c(struct voodoofb_softc *sc) |
1443 | { | | 1464 | { |
1444 | int i; | | 1465 | int i; |
1445 | | | 1466 | |
1446 | /* Fill in the i2c tag */ | | 1467 | /* Fill in the i2c tag */ |
1447 | sc->sc_i2c.ic_cookie = sc; | | 1468 | sc->sc_i2c.ic_cookie = sc; |
1448 | sc->sc_i2c.ic_acquire_bus = voodoofb_i2c_acquire_bus; | | 1469 | sc->sc_i2c.ic_acquire_bus = voodoofb_i2c_acquire_bus; |
1449 | sc->sc_i2c.ic_release_bus = voodoofb_i2c_release_bus; | | 1470 | sc->sc_i2c.ic_release_bus = voodoofb_i2c_release_bus; |
1450 | sc->sc_i2c.ic_send_start = voodoofb_i2c_send_start; | | 1471 | sc->sc_i2c.ic_send_start = voodoofb_i2c_send_start; |
1451 | sc->sc_i2c.ic_send_stop = voodoofb_i2c_send_stop; | | 1472 | sc->sc_i2c.ic_send_stop = voodoofb_i2c_send_stop; |
1452 | sc->sc_i2c.ic_initiate_xfer = voodoofb_i2c_initiate_xfer; | | 1473 | sc->sc_i2c.ic_initiate_xfer = voodoofb_i2c_initiate_xfer; |
1453 | sc->sc_i2c.ic_read_byte = voodoofb_i2c_read_byte; | | 1474 | sc->sc_i2c.ic_read_byte = voodoofb_i2c_read_byte; |
1454 | sc->sc_i2c.ic_write_byte = voodoofb_i2c_write_byte; | | 1475 | sc->sc_i2c.ic_write_byte = voodoofb_i2c_write_byte; |
1455 | sc->sc_i2c.ic_exec = NULL; | | 1476 | sc->sc_i2c.ic_exec = NULL; |
1456 | | | 1477 | |
1457 | sc->sc_i2creg = voodoo3_read32(sc, VIDSERPARPORT); | | 1478 | sc->sc_i2creg = voodoo3_read32(sc, VIDSERPARPORT); |
1458 | #ifdef VOODOOFB_DEBUG | | 1479 | #ifdef VOODOOFB_DEBUG |
1459 | printf("data: %08x\n", sc->sc_i2creg); | | 1480 | printf("data: %08x\n", sc->sc_i2creg); |
1460 | #endif | | 1481 | #endif |
1461 | sc->sc_i2creg |= VSP_ENABLE_IIC0; | | 1482 | sc->sc_i2creg |= VSP_ENABLE_IIC0; |
1462 | sc->sc_i2creg &= ~(VSP_SDA0_OUT | VSP_SCL0_OUT); | | 1483 | sc->sc_i2creg &= ~(VSP_SDA0_OUT | VSP_SCL0_OUT); |
1463 | voodoo3_write32(sc, VIDSERPARPORT, sc->sc_i2creg); | | 1484 | voodoo3_write32(sc, VIDSERPARPORT, sc->sc_i2creg); |
1464 | | | 1485 | |
1465 | /* zero out the EDID buffer */ | | 1486 | /* zero out the EDID buffer */ |
1466 | memset(sc->sc_edid_data, 0, 128); | | 1487 | memset(sc->sc_edid_data, 0, 128); |
1467 | | | 1488 | |
1468 | /* Some monitors don't respond first time */ | | 1489 | /* Some monitors don't respond first time */ |
1469 | i = 0; | | 1490 | i = 0; |
1470 | while (sc->sc_edid_data[1] == 0 && i++ < 3) | | 1491 | while (sc->sc_edid_data[1] == 0 && i++ < 3) |
1471 | ddc_read_edid(&sc->sc_i2c, sc->sc_edid_data, 128); | | 1492 | ddc_read_edid(&sc->sc_i2c, sc->sc_edid_data, 128); |
1472 | if (i < 3) { | | 1493 | if (i < 3) { |
1473 | if (edid_parse(sc->sc_edid_data, &sc->sc_edid_info) != -1) { | | 1494 | if (edid_parse(sc->sc_edid_data, &sc->sc_edid_info) != -1) { |
1474 | #ifdef VOODOOFB_DEBUG | | 1495 | #ifdef VOODOOFB_DEBUG |
1475 | edid_print(&sc->sc_edid_info); | | 1496 | edid_print(&sc->sc_edid_info); |
1476 | #endif | | 1497 | #endif |
1477 | /* | | 1498 | /* |
1478 | * Now pick a mode. | | 1499 | * Now pick a mode. |
1479 | * How do we know our max. pixel clock? | | 1500 | * How do we know our max. pixel clock? |
1480 | * All Voodoo3 should support at least 250MHz. | | 1501 | * All Voodoo3 should support at least 250MHz. |
1481 | * All Voodoo3 I've seen so far have at least 8MB | | 1502 | * All Voodoo3 I've seen so far have at least 8MB |
1482 | * which we're not going to exhaust either in 8bit. | | 1503 | * which we're not going to exhaust either in 8bit. |
1483 | */ | | 1504 | */ |
1484 | if ((sc->sc_edid_info.edid_preferred_mode != NULL)) { | | 1505 | if ((sc->sc_edid_info.edid_preferred_mode != NULL)) { |
1485 | sc->sc_videomode = | | 1506 | struct videomode *m = |
1486 | sc->sc_edid_info.edid_preferred_mode; | | 1507 | sc->sc_edid_info.edid_preferred_mode; |
1487 | } else { | | 1508 | if (MODE_IS_VALID(m)) { |
| | | 1509 | sc->sc_videomode = m; |
| | | 1510 | } else { |
| | | 1511 | aprint_error_dev(sc->sc_dev, |
| | | 1512 | "unable to use preferred mode\n"); |
| | | 1513 | } |
| | | 1514 | } |
| | | 1515 | /* |
| | | 1516 | * if we can't use the preferred mode go look for the |
| | | 1517 | * best one we can support |
| | | 1518 | */ |
| | | 1519 | if (sc->sc_videomode == NULL) { |
1488 | int n; | | 1520 | int n; |
1489 | struct videomode *m = sc->sc_edid_info.edid_modes; | | 1521 | struct videomode *m = |
| | | 1522 | sc->sc_edid_info.edid_modes; |
1490 | | | 1523 | |
1491 | sort_modes(sc->sc_edid_info.edid_modes, | | 1524 | sort_modes(sc->sc_edid_info.edid_modes, |
1492 | &sc->sc_edid_info.edid_preferred_mode, | | 1525 | &sc->sc_edid_info.edid_preferred_mode, |
1493 | sc->sc_edid_info.edid_nmodes); | | 1526 | sc->sc_edid_info.edid_nmodes); |
1494 | while ((sc->sc_videomode == NULL) && | | 1527 | while ((sc->sc_videomode == NULL) && |
1495 | (n < sc->sc_edid_info.edid_nmodes)) { | | 1528 | (n < sc->sc_edid_info.edid_nmodes)) { |
1496 | if (m[n].dot_clock <= 250000) { | | 1529 | if (MODE_IS_VALID(&m[n])) { |
1497 | sc->sc_videomode = &m[n]; | | 1530 | sc->sc_videomode = &m[n]; |
1498 | } | | 1531 | } |
| | | 1532 | n++; |
1499 | } | | 1533 | } |
1500 | } | | 1534 | } |
1501 | } | | 1535 | } |
1502 | } | | 1536 | } |
1503 | } | | 1537 | } |
1504 | | | 1538 | |
1505 | /* I2C bitbanging */ | | 1539 | /* I2C bitbanging */ |
1506 | static void voodoofb_i2cbb_set_bits(void *cookie, uint32_t bits) | | 1540 | static void voodoofb_i2cbb_set_bits(void *cookie, uint32_t bits) |
1507 | { | | 1541 | { |
1508 | struct voodoofb_softc *sc = cookie; | | 1542 | struct voodoofb_softc *sc = cookie; |
1509 | uint32_t out; | | 1543 | uint32_t out; |
1510 | | | 1544 | |
1511 | out = bits >> 2; /* bitmasks match the IN bits */ | | 1545 | out = bits >> 2; /* bitmasks match the IN bits */ |
1512 | | | 1546 | |
1513 | voodoo3_write32(sc, VIDSERPARPORT, sc->sc_i2creg | out); | | 1547 | voodoo3_write32(sc, VIDSERPARPORT, sc->sc_i2creg | out); |
1514 | } | | 1548 | } |
1515 | | | 1549 | |
1516 | static void voodoofb_i2cbb_set_dir(void *cookie, uint32_t dir) | | 1550 | static void voodoofb_i2cbb_set_dir(void *cookie, uint32_t dir) |
1517 | { | | 1551 | { |
1518 | /* Nothing to do */ | | 1552 | /* Nothing to do */ |
1519 | } | | 1553 | } |
1520 | | | 1554 | |
1521 | static uint32_t voodoofb_i2cbb_read(void *cookie) | | 1555 | static uint32_t voodoofb_i2cbb_read(void *cookie) |
1522 | { | | 1556 | { |
1523 | struct voodoofb_softc *sc = cookie; | | 1557 | struct voodoofb_softc *sc = cookie; |
1524 | uint32_t bits; | | 1558 | uint32_t bits; |
1525 | | | 1559 | |
1526 | bits = voodoo3_read32(sc, VIDSERPARPORT); | | 1560 | bits = voodoo3_read32(sc, VIDSERPARPORT); |
1527 | | | 1561 | |
1528 | return bits; | | 1562 | return bits; |
1529 | } | | 1563 | } |
1530 | | | 1564 | |
1531 | /* higher level I2C stuff */ | | 1565 | /* higher level I2C stuff */ |
1532 | static int | | 1566 | static int |
1533 | voodoofb_i2c_acquire_bus(void *cookie, int flags) | | 1567 | voodoofb_i2c_acquire_bus(void *cookie, int flags) |
1534 | { | | 1568 | { |
1535 | /* private bus */ | | 1569 | /* private bus */ |
1536 | return (0); | | 1570 | return (0); |
1537 | } | | 1571 | } |
1538 | | | 1572 | |
1539 | static void | | 1573 | static void |
1540 | voodoofb_i2c_release_bus(void *cookie, int flags) | | 1574 | voodoofb_i2c_release_bus(void *cookie, int flags) |
1541 | { | | 1575 | { |
1542 | /* private bus */ | | 1576 | /* private bus */ |
1543 | } | | 1577 | } |
1544 | | | 1578 | |
1545 | static int | | 1579 | static int |
1546 | voodoofb_i2c_send_start(void *cookie, int flags) | | 1580 | voodoofb_i2c_send_start(void *cookie, int flags) |
1547 | { | | 1581 | { |
1548 | return (i2c_bitbang_send_start(cookie, flags, &voodoofb_i2cbb_ops)); | | 1582 | return (i2c_bitbang_send_start(cookie, flags, &voodoofb_i2cbb_ops)); |
1549 | } | | 1583 | } |
1550 | | | 1584 | |
1551 | static int | | 1585 | static int |
1552 | voodoofb_i2c_send_stop(void *cookie, int flags) | | 1586 | voodoofb_i2c_send_stop(void *cookie, int flags) |
1553 | { | | 1587 | { |
1554 | | | 1588 | |
1555 | return (i2c_bitbang_send_stop(cookie, flags, &voodoofb_i2cbb_ops)); | | 1589 | return (i2c_bitbang_send_stop(cookie, flags, &voodoofb_i2cbb_ops)); |
1556 | } | | 1590 | } |
1557 | | | 1591 | |
1558 | static int | | 1592 | static int |
1559 | voodoofb_i2c_initiate_xfer(void *cookie, i2c_addr_t addr, int flags) | | 1593 | voodoofb_i2c_initiate_xfer(void *cookie, i2c_addr_t addr, int flags) |
1560 | { | | 1594 | { |
1561 | | | 1595 | |
1562 | return (i2c_bitbang_initiate_xfer(cookie, addr, flags, | | 1596 | return (i2c_bitbang_initiate_xfer(cookie, addr, flags, |
1563 | &voodoofb_i2cbb_ops)); | | 1597 | &voodoofb_i2cbb_ops)); |
1564 | } | | 1598 | } |
1565 | | | 1599 | |
1566 | static int | | 1600 | static int |
1567 | voodoofb_i2c_read_byte(void *cookie, uint8_t *valp, int flags) | | 1601 | voodoofb_i2c_read_byte(void *cookie, uint8_t *valp, int flags) |
1568 | { | | 1602 | { |
1569 | return (i2c_bitbang_read_byte(cookie, valp, flags, &voodoofb_i2cbb_ops)); | | 1603 | return (i2c_bitbang_read_byte(cookie, valp, flags, &voodoofb_i2cbb_ops)); |
1570 | } | | 1604 | } |
1571 | | | 1605 | |
1572 | static int | | 1606 | static int |
1573 | voodoofb_i2c_write_byte(void *cookie, uint8_t val, int flags) | | 1607 | voodoofb_i2c_write_byte(void *cookie, uint8_t val, int flags) |
1574 | { | | 1608 | { |
1575 | return (i2c_bitbang_write_byte(cookie, val, flags, &voodoofb_i2cbb_ops)); | | 1609 | return (i2c_bitbang_write_byte(cookie, val, flags, &voodoofb_i2cbb_ops)); |
1576 | } | | 1610 | } |