| @@ -1,14 +1,14 @@ | | | @@ -1,14 +1,14 @@ |
1 | /* $NetBSD: r128fb.c,v 1.10 2009/10/01 19:02:27 jmmv Exp $ */ | | 1 | /* $NetBSD: r128fb.c,v 1.11 2010/09/09 01:22:11 macallan Exp $ */ |
2 | | | 2 | |
3 | /* | | 3 | /* |
4 | * Copyright (c) 2007 Michael Lorenz | | 4 | * Copyright (c) 2007 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. |
| @@ -21,27 +21,27 @@ | | | @@ -21,27 +21,27 @@ |
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 ATI Rage 128 graphics controllers | | 29 | * A console driver for ATI Rage 128 graphics controllers |
30 | * tested on macppc only so far | | 30 | * tested on macppc only so far |
31 | */ | | 31 | */ |
32 | | | 32 | |
33 | #include <sys/cdefs.h> | | 33 | #include <sys/cdefs.h> |
34 | __KERNEL_RCSID(0, "$NetBSD: r128fb.c,v 1.10 2009/10/01 19:02:27 jmmv Exp $"); | | 34 | __KERNEL_RCSID(0, "$NetBSD: r128fb.c,v 1.11 2010/09/09 01:22:11 macallan Exp $"); |
35 | | | 35 | |
36 | #include <sys/param.h> | | 36 | #include <sys/param.h> |
37 | #include <sys/systm.h> | | 37 | #include <sys/systm.h> |
38 | #include <sys/kernel.h> | | 38 | #include <sys/kernel.h> |
39 | #include <sys/device.h> | | 39 | #include <sys/device.h> |
40 | #include <sys/malloc.h> | | 40 | #include <sys/malloc.h> |
41 | #include <sys/lwp.h> | | 41 | #include <sys/lwp.h> |
42 | #include <sys/kauth.h> | | 42 | #include <sys/kauth.h> |
43 | | | 43 | |
44 | #include <uvm/uvm_extern.h> | | 44 | #include <uvm/uvm_extern.h> |
45 | | | 45 | |
46 | #include <dev/videomode/videomode.h> | | 46 | #include <dev/videomode/videomode.h> |
47 | | | 47 | |
| @@ -49,42 +49,50 @@ __KERNEL_RCSID(0, "$NetBSD: r128fb.c,v 1 | | | @@ -49,42 +49,50 @@ __KERNEL_RCSID(0, "$NetBSD: r128fb.c,v 1 |
49 | #include <dev/pci/pcireg.h> | | 49 | #include <dev/pci/pcireg.h> |
50 | #include <dev/pci/pcidevs.h> | | 50 | #include <dev/pci/pcidevs.h> |
51 | #include <dev/pci/pciio.h> | | 51 | #include <dev/pci/pciio.h> |
52 | #include <dev/pci/r128fbreg.h> | | 52 | #include <dev/pci/r128fbreg.h> |
53 | | | 53 | |
54 | #include <dev/wscons/wsdisplayvar.h> | | 54 | #include <dev/wscons/wsdisplayvar.h> |
55 | #include <dev/wscons/wsconsio.h> | | 55 | #include <dev/wscons/wsconsio.h> |
56 | #include <dev/wsfont/wsfont.h> | | 56 | #include <dev/wsfont/wsfont.h> |
57 | #include <dev/rasops/rasops.h> | | 57 | #include <dev/rasops/rasops.h> |
58 | #include <dev/wscons/wsdisplay_vconsvar.h> | | 58 | #include <dev/wscons/wsdisplay_vconsvar.h> |
59 | | | 59 | |
60 | #include <dev/i2c/i2cvar.h> | | 60 | #include <dev/i2c/i2cvar.h> |
61 | | | 61 | |
| | | 62 | #include "opt_r128fb.h" |
| | | 63 | |
| | | 64 | #ifdef R128FB_DEBUG |
| | | 65 | #define DPRINTF printf |
| | | 66 | #else |
| | | 67 | #define DPRINTF while(0) printf |
| | | 68 | #endif |
| | | 69 | |
62 | struct r128fb_softc { | | 70 | struct r128fb_softc { |
63 | device_t sc_dev; | | 71 | device_t sc_dev; |
64 | | | 72 | |
65 | pci_chipset_tag_t sc_pc; | | 73 | pci_chipset_tag_t sc_pc; |
66 | pcitag_t sc_pcitag; | | 74 | pcitag_t sc_pcitag; |
67 | | | 75 | |
68 | bus_space_tag_t sc_memt; | | 76 | bus_space_tag_t sc_memt; |
69 | bus_space_tag_t sc_iot; | | 77 | bus_space_tag_t sc_iot; |
70 | | | 78 | |
71 | bus_space_handle_t sc_fbh; | | 79 | bus_space_handle_t sc_fbh; |
72 | bus_space_handle_t sc_regh; | | 80 | bus_space_handle_t sc_regh; |
73 | bus_addr_t sc_fb, sc_reg; | | 81 | bus_addr_t sc_fb, sc_reg; |
74 | bus_size_t sc_fbsize, sc_regsize; | | 82 | bus_size_t sc_fbsize, sc_regsize; |
75 | | | 83 | |
76 | int sc_width, sc_height, sc_depth, sc_stride; | | 84 | int sc_width, sc_height, sc_depth, sc_stride; |
77 | int sc_locked; | | 85 | int sc_locked, sc_have_backlight, sc_bl_level; |
78 | void *sc_fbaddr; | | 86 | void *sc_fbaddr; |
79 | struct vcons_screen sc_console_screen; | | 87 | struct vcons_screen sc_console_screen; |
80 | struct wsscreen_descr sc_defaultscreen_descr; | | 88 | struct wsscreen_descr sc_defaultscreen_descr; |
81 | const struct wsscreen_descr *sc_screens[1]; | | 89 | const struct wsscreen_descr *sc_screens[1]; |
82 | struct wsscreen_list sc_screenlist; | | 90 | struct wsscreen_list sc_screenlist; |
83 | struct vcons_data vd; | | 91 | struct vcons_data vd; |
84 | int sc_mode; | | 92 | int sc_mode; |
85 | u_char sc_cmap_red[256]; | | 93 | u_char sc_cmap_red[256]; |
86 | u_char sc_cmap_green[256]; | | 94 | u_char sc_cmap_green[256]; |
87 | u_char sc_cmap_blue[256]; | | 95 | u_char sc_cmap_blue[256]; |
88 | /* engine stuff */ | | 96 | /* engine stuff */ |
89 | uint32_t sc_master_cntl; | | 97 | uint32_t sc_master_cntl; |
90 | }; | | 98 | }; |
| @@ -114,26 +122,30 @@ static void r128fb_rectfill(struct r128f | | | @@ -114,26 +122,30 @@ static void r128fb_rectfill(struct r128f |
114 | uint32_t); | | 122 | uint32_t); |
115 | static void r128fb_bitblt(struct r128fb_softc *, int, int, int, int, int, | | 123 | static void r128fb_bitblt(struct r128fb_softc *, int, int, int, int, int, |
116 | int, int); | | 124 | int, int); |
117 | | | 125 | |
118 | static void r128fb_cursor(void *, int, int, int); | | 126 | static void r128fb_cursor(void *, int, int, int); |
119 | #if 0 | | 127 | #if 0 |
120 | static void r128fb_putchar(void *, int, int, u_int, long); | | 128 | static void r128fb_putchar(void *, int, int, u_int, long); |
121 | #endif | | 129 | #endif |
122 | static void r128fb_copycols(void *, int, int, int, int); | | 130 | static void r128fb_copycols(void *, int, int, int, int); |
123 | static void r128fb_erasecols(void *, int, int, int, long); | | 131 | static void r128fb_erasecols(void *, int, int, int, long); |
124 | static void r128fb_copyrows(void *, int, int, int); | | 132 | static void r128fb_copyrows(void *, int, int, int); |
125 | static void r128fb_eraserows(void *, int, int, long); | | 133 | static void r128fb_eraserows(void *, int, int, long); |
126 | | | 134 | |
| | | 135 | static void r128fb_brightness_up(device_t); |
| | | 136 | static void r128fb_brightness_down(device_t); |
| | | 137 | static void r128fb_set_backlight(struct r128fb_softc *, int); |
| | | 138 | |
127 | struct wsdisplay_accessops r128fb_accessops = { | | 139 | struct wsdisplay_accessops r128fb_accessops = { |
128 | r128fb_ioctl, | | 140 | r128fb_ioctl, |
129 | r128fb_mmap, | | 141 | r128fb_mmap, |
130 | NULL, /* alloc_screen */ | | 142 | NULL, /* alloc_screen */ |
131 | NULL, /* free_screen */ | | 143 | NULL, /* free_screen */ |
132 | NULL, /* show_screen */ | | 144 | NULL, /* show_screen */ |
133 | NULL, /* load_font */ | | 145 | NULL, /* load_font */ |
134 | NULL, /* pollc */ | | 146 | NULL, /* pollc */ |
135 | NULL /* scroll */ | | 147 | NULL /* scroll */ |
136 | }; | | 148 | }; |
137 | | | 149 | |
138 | static inline void | | 150 | static inline void |
139 | r128fb_wait(struct r128fb_softc *sc, int slots) | | 151 | r128fb_wait(struct r128fb_softc *sc, int slots) |
| @@ -181,26 +193,27 @@ r128fb_match(device_t parent, cfdata_t m | | | @@ -181,26 +193,27 @@ r128fb_match(device_t parent, cfdata_t m |
181 | | | 193 | |
182 | static void | | 194 | static void |
183 | r128fb_attach(device_t parent, device_t self, void *aux) | | 195 | r128fb_attach(device_t parent, device_t self, void *aux) |
184 | { | | 196 | { |
185 | struct r128fb_softc *sc = device_private(self); | | 197 | struct r128fb_softc *sc = device_private(self); |
186 | struct pci_attach_args *pa = aux; | | 198 | struct pci_attach_args *pa = aux; |
187 | struct rasops_info *ri; | | 199 | struct rasops_info *ri; |
188 | char devinfo[256]; | | 200 | char devinfo[256]; |
189 | struct wsemuldisplaydev_attach_args aa; | | 201 | struct wsemuldisplaydev_attach_args aa; |
190 | prop_dictionary_t dict; | | 202 | prop_dictionary_t dict; |
191 | unsigned long defattr; | | 203 | unsigned long defattr; |
192 | bool is_console; | | 204 | bool is_console; |
193 | int i, j; | | 205 | int i, j; |
| | | 206 | uint32_t reg; |
194 | | | 207 | |
195 | sc->sc_pc = pa->pa_pc; | | 208 | sc->sc_pc = pa->pa_pc; |
196 | sc->sc_pcitag = pa->pa_tag; | | 209 | sc->sc_pcitag = pa->pa_tag; |
197 | sc->sc_memt = pa->pa_memt; | | 210 | sc->sc_memt = pa->pa_memt; |
198 | sc->sc_iot = pa->pa_iot; | | 211 | sc->sc_iot = pa->pa_iot; |
199 | sc->sc_dev = self; | | 212 | sc->sc_dev = self; |
200 | | | 213 | |
201 | pci_devinfo(pa->pa_id, pa->pa_class, 0, devinfo, sizeof(devinfo)); | | 214 | pci_devinfo(pa->pa_id, pa->pa_class, 0, devinfo, sizeof(devinfo)); |
202 | aprint_normal(": %s\n", devinfo); | | 215 | aprint_normal(": %s\n", devinfo); |
203 | | | 216 | |
204 | /* fill in parameters from properties */ | | 217 | /* fill in parameters from properties */ |
205 | dict = device_properties(self); | | 218 | dict = device_properties(self); |
206 | if (!prop_dictionary_get_uint32(dict, "width", &sc->sc_width)) { | | 219 | if (!prop_dictionary_get_uint32(dict, "width", &sc->sc_width)) { |
| @@ -295,27 +308,41 @@ r128fb_attach(device_t parent, device_t | | | @@ -295,27 +308,41 @@ r128fb_attach(device_t parent, device_t |
295 | /* | | 308 | /* |
296 | * since we're not the console we can postpone the rest | | 309 | * since we're not the console we can postpone the rest |
297 | * until someone actually allocates a screen for us | | 310 | * until someone actually allocates a screen for us |
298 | */ | | 311 | */ |
299 | (*ri->ri_ops.allocattr)(ri, 0, 0, 0, &defattr); | | 312 | (*ri->ri_ops.allocattr)(ri, 0, 0, 0, &defattr); |
300 | } | | 313 | } |
301 | | | 314 | |
302 | aa.console = is_console; | | 315 | aa.console = is_console; |
303 | aa.scrdata = &sc->sc_screenlist; | | 316 | aa.scrdata = &sc->sc_screenlist; |
304 | aa.accessops = &r128fb_accessops; | | 317 | aa.accessops = &r128fb_accessops; |
305 | aa.accesscookie = &sc->vd; | | 318 | aa.accesscookie = &sc->vd; |
306 | | | 319 | |
307 | config_found(sc->sc_dev, &aa, wsemuldisplaydevprint); | | 320 | config_found(sc->sc_dev, &aa, wsemuldisplaydevprint); |
308 | | | 321 | |
| | | 322 | /* no suspend/resume support yet */ |
| | | 323 | pmf_device_register(sc->sc_dev, NULL, NULL); |
| | | 324 | reg = bus_space_read_4(sc->sc_memt, sc->sc_regh, R128_LVDS_GEN_CNTL); |
| | | 325 | DPRINTF("reg: %08x\n", reg); |
| | | 326 | if (reg & R128_LVDS_ON) { |
| | | 327 | sc->sc_have_backlight = 1; |
| | | 328 | sc->sc_bl_level = 255 - |
| | | 329 | ((reg & R128_LEVEL_MASK) >> R128_LEVEL_SHIFT); |
| | | 330 | pmf_event_register(sc->sc_dev, PMFE_DISPLAY_BRIGHTNESS_UP, |
| | | 331 | r128fb_brightness_up, TRUE); |
| | | 332 | pmf_event_register(sc->sc_dev, PMFE_DISPLAY_BRIGHTNESS_DOWN, |
| | | 333 | r128fb_brightness_down, TRUE); |
| | | 334 | } else |
| | | 335 | sc->sc_have_backlight = 0; |
309 | } | | 336 | } |
310 | | | 337 | |
311 | static int | | 338 | static int |
312 | r128fb_ioctl(void *v, void *vs, u_long cmd, void *data, int flag, | | 339 | r128fb_ioctl(void *v, void *vs, u_long cmd, void *data, int flag, |
313 | struct lwp *l) | | 340 | struct lwp *l) |
314 | { | | 341 | { |
315 | struct vcons_data *vd = v; | | 342 | struct vcons_data *vd = v; |
316 | struct r128fb_softc *sc = vd->cookie; | | 343 | struct r128fb_softc *sc = vd->cookie; |
317 | struct wsdisplay_fbinfo *wdf; | | 344 | struct wsdisplay_fbinfo *wdf; |
318 | struct vcons_screen *ms = vd->active; | | 345 | struct vcons_screen *ms = vd->active; |
319 | | | 346 | |
320 | switch (cmd) { | | 347 | switch (cmd) { |
321 | | | 348 | |
| @@ -777,13 +804,47 @@ r128fb_eraserows(void *cookie, int row, | | | @@ -777,13 +804,47 @@ r128fb_eraserows(void *cookie, int row, |
777 | int32_t x, y, width, height, fg, bg, ul; | | 804 | int32_t x, y, width, height, fg, bg, ul; |
778 | | | 805 | |
779 | if ((sc->sc_locked == 0) && (sc->sc_mode == WSDISPLAYIO_MODE_EMUL)) { | | 806 | if ((sc->sc_locked == 0) && (sc->sc_mode == WSDISPLAYIO_MODE_EMUL)) { |
780 | x = ri->ri_xorigin; | | 807 | x = ri->ri_xorigin; |
781 | y = ri->ri_yorigin + ri->ri_font->fontheight * row; | | 808 | y = ri->ri_yorigin + ri->ri_font->fontheight * row; |
782 | width = ri->ri_emuwidth; | | 809 | width = ri->ri_emuwidth; |
783 | height = ri->ri_font->fontheight * nrows; | | 810 | height = ri->ri_font->fontheight * nrows; |
784 | rasops_unpack_attr(fillattr, &fg, &bg, &ul); | | 811 | rasops_unpack_attr(fillattr, &fg, &bg, &ul); |
785 | | | 812 | |
786 | r128fb_rectfill(sc, x, y, width, height, ri->ri_devcmap[bg]); | | 813 | r128fb_rectfill(sc, x, y, width, height, ri->ri_devcmap[bg]); |
787 | } | | 814 | } |
788 | } | | 815 | } |
789 | | | 816 | |
| | | 817 | static void |
| | | 818 | r128fb_set_backlight(struct r128fb_softc *sc, int level) |
| | | 819 | { |
| | | 820 | uint32_t reg; |
| | | 821 | |
| | | 822 | if (level > 255) level = 255; |
| | | 823 | if (level < 0) level = 0; |
| | | 824 | if (level == sc->sc_bl_level) |
| | | 825 | return; |
| | | 826 | sc->sc_bl_level = level; |
| | | 827 | level = 255 - level; |
| | | 828 | reg = bus_space_read_4(sc->sc_memt, sc->sc_regh, R128_LVDS_GEN_CNTL); |
| | | 829 | reg &= ~R128_LEVEL_MASK; |
| | | 830 | reg |= level << R128_LEVEL_SHIFT; |
| | | 831 | bus_space_write_4(sc->sc_memt, sc->sc_regh, R128_LVDS_GEN_CNTL, reg); |
| | | 832 | DPRINTF("level: %d reg %08x\n", level, reg); |
| | | 833 | } |
| | | 834 | |
| | | 835 | |
| | | 836 | static void |
| | | 837 | r128fb_brightness_up(device_t dev) |
| | | 838 | { |
| | | 839 | struct r128fb_softc *sc = device_private(dev); |
| | | 840 | |
| | | 841 | r128fb_set_backlight(sc, sc->sc_bl_level + 8); |
| | | 842 | } |
| | | 843 | |
| | | 844 | static void |
| | | 845 | r128fb_brightness_down(device_t dev) |
| | | 846 | { |
| | | 847 | struct r128fb_softc *sc = device_private(dev); |
| | | 848 | |
| | | 849 | r128fb_set_backlight(sc, sc->sc_bl_level - 8); |
| | | 850 | } |