1 1.117 tnn /* $NetBSD: radeonfb.c,v 1.117 2021/08/08 12:17:37 tnn Exp $ */ 2 1.1 gdamore 3 1.1 gdamore /*- 4 1.1 gdamore * Copyright (c) 2006 Itronix Inc. 5 1.1 gdamore * All rights reserved. 6 1.1 gdamore * 7 1.1 gdamore * Written by Garrett D'Amore for Itronix Inc. 8 1.1 gdamore * 9 1.1 gdamore * Redistribution and use in source and binary forms, with or without 10 1.1 gdamore * modification, are permitted provided that the following conditions 11 1.1 gdamore * are met: 12 1.1 gdamore * 1. Redistributions of source code must retain the above copyright 13 1.1 gdamore * notice, this list of conditions and the following disclaimer. 14 1.1 gdamore * 2. Redistributions in binary form must reproduce the above copyright 15 1.1 gdamore * notice, this list of conditions and the following disclaimer in the 16 1.1 gdamore * documentation and/or other materials provided with the distribution. 17 1.1 gdamore * 3. The name of Itronix Inc. may not be used to endorse 18 1.1 gdamore * or promote products derived from this software without specific 19 1.1 gdamore * prior written permission. 20 1.1 gdamore * 21 1.1 gdamore * THIS SOFTWARE IS PROVIDED BY ITRONIX INC. ``AS IS'' AND ANY EXPRESS 22 1.1 gdamore * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 23 1.1 gdamore * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 1.1 gdamore * ARE DISCLAIMED. IN NO EVENT SHALL ITRONIX INC. BE LIABLE FOR ANY 25 1.1 gdamore * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 1.1 gdamore * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE 27 1.1 gdamore * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 28 1.1 gdamore * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 29 1.1 gdamore * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 30 1.1 gdamore * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 31 1.1 gdamore * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 1.11 ad */ 33 1.1 gdamore 34 1.1 gdamore /* 35 1.1 gdamore * ATI Technologies Inc. ("ATI") has not assisted in the creation of, and 36 1.1 gdamore * does not endorse, this software. ATI will not be responsible or liable 37 1.1 gdamore * for any actual or alleged damage or loss caused by or in connection with 38 1.1 gdamore * the use of or reliance on this software. 39 1.1 gdamore */ 40 1.1 gdamore 41 1.1 gdamore /* 42 1.1 gdamore * Portions of this code were taken from XFree86's Radeon driver, which bears 43 1.1 gdamore * this notice: 44 1.1 gdamore * 45 1.1 gdamore * Copyright 2000 ATI Technologies Inc., Markham, Ontario, and 46 1.1 gdamore * VA Linux Systems Inc., Fremont, California. 47 1.1 gdamore * 48 1.1 gdamore * All Rights Reserved. 49 1.1 gdamore * 50 1.1 gdamore * Permission is hereby granted, free of charge, to any person obtaining 51 1.1 gdamore * a copy of this software and associated documentation files (the 52 1.1 gdamore * "Software"), to deal in the Software without restriction, including 53 1.1 gdamore * without limitation on the rights to use, copy, modify, merge, 54 1.1 gdamore * publish, distribute, sublicense, and/or sell copies of the Software, 55 1.1 gdamore * and to permit persons to whom the Software is furnished to do so, 56 1.1 gdamore * subject to the following conditions: 57 1.1 gdamore * 58 1.1 gdamore * The above copyright notice and this permission notice (including the 59 1.1 gdamore * next paragraph) shall be included in all copies or substantial 60 1.1 gdamore * portions of the Software. 61 1.1 gdamore * 62 1.1 gdamore * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 63 1.1 gdamore * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 64 1.1 gdamore * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 65 1.1 gdamore * NON-INFRINGEMENT. IN NO EVENT SHALL ATI, VA LINUX SYSTEMS AND/OR 66 1.1 gdamore * THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 67 1.1 gdamore * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 68 1.1 gdamore * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 69 1.1 gdamore * DEALINGS IN THE SOFTWARE. 70 1.1 gdamore */ 71 1.1 gdamore 72 1.1 gdamore #include <sys/cdefs.h> 73 1.117 tnn __KERNEL_RCSID(0, "$NetBSD: radeonfb.c,v 1.117 2021/08/08 12:17:37 tnn Exp $"); 74 1.1 gdamore 75 1.1 gdamore #include <sys/param.h> 76 1.1 gdamore #include <sys/systm.h> 77 1.1 gdamore #include <sys/device.h> 78 1.1 gdamore #include <sys/malloc.h> 79 1.21 ad #include <sys/bus.h> 80 1.5 macallan #include <sys/kernel.h> 81 1.5 macallan #include <sys/lwp.h> 82 1.5 macallan #include <sys/kauth.h> 83 1.107 macallan #include <sys/kmem.h> 84 1.1 gdamore 85 1.1 gdamore #include <dev/wscons/wsdisplayvar.h> 86 1.1 gdamore #include <dev/wscons/wsconsio.h> 87 1.1 gdamore #include <dev/wsfont/wsfont.h> 88 1.1 gdamore #include <dev/rasops/rasops.h> 89 1.1 gdamore #include <dev/videomode/videomode.h> 90 1.1 gdamore #include <dev/videomode/edidvar.h> 91 1.1 gdamore #include <dev/wscons/wsdisplay_vconsvar.h> 92 1.41 cegger #include <dev/pci/wsdisplay_pci.h> 93 1.54 macallan #include <dev/wscons/wsdisplay_glyphcachevar.h> 94 1.1 gdamore 95 1.1 gdamore #include <dev/pci/pcidevs.h> 96 1.1 gdamore #include <dev/pci/pcireg.h> 97 1.1 gdamore #include <dev/pci/pcivar.h> 98 1.26 phx #include <dev/pci/pciio.h> 99 1.1 gdamore #include <dev/pci/radeonfbreg.h> 100 1.1 gdamore #include <dev/pci/radeonfbvar.h> 101 1.14 macallan #include "opt_radeonfb.h" 102 1.48 macallan #include "opt_vcons.h" 103 1.1 gdamore 104 1.49 macallan #ifdef RADEONFB_DEPTH_32 105 1.49 macallan #define RADEONFB_DEFAULT_DEPTH 32 106 1.49 macallan #else 107 1.49 macallan #define RADEONFB_DEFAULT_DEPTH 8 108 1.49 macallan #endif 109 1.49 macallan 110 1.31 cegger static int radeonfb_match(device_t, cfdata_t, void *); 111 1.31 cegger static void radeonfb_attach(device_t, device_t, void *); 112 1.12 christos static int radeonfb_ioctl(void *, void *, unsigned long, void *, int, 113 1.1 gdamore struct lwp *); 114 1.1 gdamore static paddr_t radeonfb_mmap(void *, void *, off_t, int); 115 1.1 gdamore static int radeonfb_scratch_test(struct radeonfb_softc *, int, uint32_t); 116 1.1 gdamore static void radeonfb_loadbios(struct radeonfb_softc *, 117 1.44 dyoung const struct pci_attach_args *); 118 1.1 gdamore 119 1.1 gdamore static uintmax_t radeonfb_getprop_num(struct radeonfb_softc *, const char *, 120 1.1 gdamore uintmax_t); 121 1.1 gdamore static int radeonfb_getclocks(struct radeonfb_softc *); 122 1.1 gdamore static int radeonfb_gettmds(struct radeonfb_softc *); 123 1.1 gdamore static int radeonfb_calc_dividers(struct radeonfb_softc *, uint32_t, 124 1.92 macallan uint32_t *, uint32_t *, int); 125 1.92 macallan /* flags for radeonfb_calc_dividers */ 126 1.92 macallan #define NO_ODD_FBDIV 1 127 1.92 macallan 128 1.1 gdamore static int radeonfb_getconnectors(struct radeonfb_softc *); 129 1.1 gdamore static const struct videomode *radeonfb_modelookup(const char *); 130 1.1 gdamore static void radeonfb_init_screen(void *, struct vcons_screen *, int, long *); 131 1.1 gdamore static void radeonfb_pllwriteupdate(struct radeonfb_softc *, int); 132 1.1 gdamore static void radeonfb_pllwaitatomicread(struct radeonfb_softc *, int); 133 1.92 macallan static void radeonfb_program_vclk(struct radeonfb_softc *, int, int, int); 134 1.1 gdamore static void radeonfb_modeswitch(struct radeonfb_display *); 135 1.1 gdamore static void radeonfb_setcrtc(struct radeonfb_display *, int); 136 1.1 gdamore static void radeonfb_init_misc(struct radeonfb_softc *); 137 1.1 gdamore static void radeonfb_set_fbloc(struct radeonfb_softc *); 138 1.70 macallan static void radeonfb_init_palette(struct radeonfb_display *); 139 1.1 gdamore static void radeonfb_r300cg_workaround(struct radeonfb_softc *); 140 1.1 gdamore 141 1.1 gdamore static int radeonfb_isblank(struct radeonfb_display *); 142 1.1 gdamore static void radeonfb_blank(struct radeonfb_display *, int); 143 1.1 gdamore static int radeonfb_set_cursor(struct radeonfb_display *, 144 1.1 gdamore struct wsdisplay_cursor *); 145 1.1 gdamore static int radeonfb_set_curpos(struct radeonfb_display *, 146 1.1 gdamore struct wsdisplay_curpos *); 147 1.82 macallan static void radeonfb_putpal(struct radeonfb_display *, int, int, int, int); 148 1.82 macallan static int radeonfb_putcmap(struct radeonfb_display *, struct wsdisplay_cmap *); 149 1.82 macallan static int radeonfb_getcmap(struct radeonfb_display *, struct wsdisplay_cmap *); 150 1.1 gdamore 151 1.1 gdamore /* acceleration support */ 152 1.2 macallan static void radeonfb_rectfill(struct radeonfb_display *, int dstx, int dsty, 153 1.1 gdamore int width, int height, uint32_t color); 154 1.64 macallan static void radeonfb_rectfill_a(void *, int, int, int, int, long); 155 1.54 macallan static void radeonfb_bitblt(void *, int srcx, int srcy, 156 1.54 macallan int dstx, int dsty, int width, int height, int rop); 157 1.2 macallan 158 1.1 gdamore /* hw cursor support */ 159 1.1 gdamore static void radeonfb_cursor_cmap(struct radeonfb_display *); 160 1.1 gdamore static void radeonfb_cursor_shape(struct radeonfb_display *); 161 1.1 gdamore static void radeonfb_cursor_position(struct radeonfb_display *); 162 1.1 gdamore static void radeonfb_cursor_visible(struct radeonfb_display *); 163 1.1 gdamore static void radeonfb_cursor_update(struct radeonfb_display *, unsigned); 164 1.1 gdamore 165 1.62 uebayasi static inline void radeonfb_wait_fifo(struct radeonfb_softc *, int); 166 1.1 gdamore static void radeonfb_engine_idle(struct radeonfb_softc *); 167 1.1 gdamore static void radeonfb_engine_flush(struct radeonfb_softc *); 168 1.1 gdamore static void radeonfb_engine_reset(struct radeonfb_softc *); 169 1.1 gdamore static void radeonfb_engine_init(struct radeonfb_display *); 170 1.83 joerg static inline void radeonfb_unclip(struct radeonfb_softc *) __unused; 171 1.1 gdamore 172 1.1 gdamore static void radeonfb_eraserows(void *, int, int, long); 173 1.1 gdamore static void radeonfb_erasecols(void *, int, int, int, long); 174 1.1 gdamore static void radeonfb_copyrows(void *, int, int, int); 175 1.1 gdamore static void radeonfb_copycols(void *, int, int, int, int); 176 1.1 gdamore static void radeonfb_cursor(void *, int, int, int); 177 1.2 macallan static void radeonfb_putchar(void *, int, int, unsigned, long); 178 1.49 macallan static void radeonfb_putchar_aa32(void *, int, int, unsigned, long); 179 1.55 macallan static void radeonfb_putchar_aa8(void *, int, int, unsigned, long); 180 1.73 macallan #ifndef RADEONFB_ALWAYS_ACCEL_PUTCHAR 181 1.38 macallan static void radeonfb_putchar_wrapper(void *, int, int, unsigned, long); 182 1.73 macallan #endif 183 1.1 gdamore 184 1.59 macallan static int radeonfb_set_backlight(struct radeonfb_display *, int); 185 1.9 macallan static int radeonfb_get_backlight(struct radeonfb_display *); 186 1.59 macallan static void radeonfb_switch_backlight(struct radeonfb_display *, int); 187 1.9 macallan static void radeonfb_lvds_callout(void *); 188 1.9 macallan 189 1.34 macallan static void radeonfb_brightness_up(device_t); 190 1.34 macallan static void radeonfb_brightness_down(device_t); 191 1.34 macallan 192 1.1 gdamore static struct videomode *radeonfb_best_refresh(struct videomode *, 193 1.1 gdamore struct videomode *); 194 1.1 gdamore static void radeonfb_pickres(struct radeonfb_display *, uint16_t *, 195 1.1 gdamore uint16_t *, int); 196 1.11 ad static const struct videomode *radeonfb_port_mode(struct radeonfb_softc *, 197 1.9 macallan struct radeonfb_port *, int, int); 198 1.1 gdamore 199 1.14 macallan static int radeonfb_drm_print(void *, const char *); 200 1.14 macallan 201 1.36 macallan #ifdef RADEONFB_DEBUG 202 1.1 gdamore int radeon_debug = 1; 203 1.1 gdamore #define DPRINTF(x) \ 204 1.1 gdamore if (radeon_debug) printf x 205 1.1 gdamore #define PRINTREG(r) DPRINTF((#r " = %08x\n", GET32(sc, r))) 206 1.1 gdamore #define PRINTPLL(r) DPRINTF((#r " = %08x\n", GETPLL(sc, r))) 207 1.1 gdamore #else 208 1.1 gdamore #define DPRINTF(x) 209 1.1 gdamore #define PRINTREG(r) 210 1.1 gdamore #define PRINTPLL(r) 211 1.1 gdamore #endif 212 1.1 gdamore 213 1.1 gdamore #define ROUNDUP(x,y) (((x) + ((y) - 1)) & ~((y) - 1)) 214 1.1 gdamore 215 1.1 gdamore #ifndef RADEON_DEFAULT_MODE 216 1.1 gdamore /* any reasonably modern display should handle this */ 217 1.1 gdamore #define RADEON_DEFAULT_MODE "1024x768x60" 218 1.1 gdamore #endif 219 1.1 gdamore 220 1.36 macallan extern const u_char rasops_cmap[768]; 221 1.36 macallan 222 1.1 gdamore const char *radeonfb_default_mode = RADEON_DEFAULT_MODE; 223 1.1 gdamore 224 1.1 gdamore static struct { 225 1.1 gdamore int size; /* minimum memory size (MB) */ 226 1.1 gdamore int maxx; /* maximum x dimension */ 227 1.1 gdamore int maxy; /* maximum y dimension */ 228 1.1 gdamore int maxbpp; /* maximum bpp */ 229 1.1 gdamore int maxdisp; /* maximum logical display count */ 230 1.1 gdamore } radeonfb_limits[] = { 231 1.1 gdamore { 32, 2048, 1536, 32, 2 }, 232 1.1 gdamore { 16, 1600, 1200, 32, 2 }, 233 1.1 gdamore { 8, 1600, 1200, 32, 1 }, 234 1.7 christos { 0, 0, 0, 0, 0 }, 235 1.1 gdamore }; 236 1.1 gdamore 237 1.1 gdamore static struct wsscreen_descr radeonfb_stdscreen = { 238 1.1 gdamore "fb", /* name */ 239 1.1 gdamore 0, 0, /* ncols, nrows */ 240 1.1 gdamore NULL, /* textops */ 241 1.2 macallan 8, 16, /* fontwidth, fontheight */ 242 1.89 macallan WSSCREEN_WSCOLORS | WSSCREEN_UNDERLINE | WSSCREEN_RESIZE, /* capabilities */ 243 1.7 christos 0, /* modecookie */ 244 1.1 gdamore }; 245 1.1 gdamore 246 1.1 gdamore struct wsdisplay_accessops radeonfb_accessops = { 247 1.1 gdamore radeonfb_ioctl, 248 1.1 gdamore radeonfb_mmap, 249 1.1 gdamore NULL, /* vcons_alloc_screen */ 250 1.1 gdamore NULL, /* vcons_free_screen */ 251 1.1 gdamore NULL, /* vcons_show_screen */ 252 1.7 christos NULL, /* load_font */ 253 1.7 christos NULL, /* pollc */ 254 1.7 christos NULL, /* scroll */ 255 1.1 gdamore }; 256 1.1 gdamore 257 1.1 gdamore static struct { 258 1.1 gdamore uint16_t devid; 259 1.1 gdamore uint16_t family; 260 1.1 gdamore uint16_t flags; 261 1.11 ad } radeonfb_devices[] = 262 1.1 gdamore { 263 1.1 gdamore /* R100 family */ 264 1.1 gdamore { PCI_PRODUCT_ATI_RADEON_R100_QD, RADEON_R100, 0 }, 265 1.1 gdamore { PCI_PRODUCT_ATI_RADEON_R100_QE, RADEON_R100, 0 }, 266 1.1 gdamore { PCI_PRODUCT_ATI_RADEON_R100_QF, RADEON_R100, 0 }, 267 1.1 gdamore { PCI_PRODUCT_ATI_RADEON_R100_QG, RADEON_R100, 0 }, 268 1.1 gdamore 269 1.1 gdamore /* RV100 family */ 270 1.1 gdamore { PCI_PRODUCT_ATI_RADEON_RV100_LY, RADEON_RV100, RFB_MOB }, 271 1.1 gdamore { PCI_PRODUCT_ATI_RADEON_RV100_LZ, RADEON_RV100, RFB_MOB }, 272 1.1 gdamore { PCI_PRODUCT_ATI_RADEON_RV100_QY, RADEON_RV100, 0 }, 273 1.1 gdamore { PCI_PRODUCT_ATI_RADEON_RV100_QZ, RADEON_RV100, 0 }, 274 1.1 gdamore 275 1.1 gdamore /* RS100 family */ 276 1.1 gdamore { PCI_PRODUCT_ATI_RADEON_RS100_4136, RADEON_RS100, 0 }, 277 1.1 gdamore { PCI_PRODUCT_ATI_RADEON_RS100_4336, RADEON_RS100, RFB_MOB }, 278 1.1 gdamore 279 1.1 gdamore /* RS200/RS250 family */ 280 1.1 gdamore { PCI_PRODUCT_ATI_RADEON_RS200_4337, RADEON_RS200, RFB_MOB }, 281 1.1 gdamore { PCI_PRODUCT_ATI_RADEON_RS200_A7, RADEON_RS200, 0 }, 282 1.1 gdamore { PCI_PRODUCT_ATI_RADEON_RS250_B7, RADEON_RS200, RFB_MOB }, 283 1.1 gdamore { PCI_PRODUCT_ATI_RADEON_RS250_D7, RADEON_RS200, 0 }, 284 1.1 gdamore 285 1.1 gdamore /* R200 family */ 286 1.1 gdamore /* add more R200 products? , 5148 */ 287 1.1 gdamore { PCI_PRODUCT_ATI_RADEON_R200_BB, RADEON_R200, 0 }, 288 1.1 gdamore { PCI_PRODUCT_ATI_RADEON_R200_BC, RADEON_R200, 0 }, 289 1.1 gdamore { PCI_PRODUCT_ATI_RADEON_R200_QH, RADEON_R200, 0 }, 290 1.1 gdamore { PCI_PRODUCT_ATI_RADEON_R200_QL, RADEON_R200, 0 }, 291 1.1 gdamore { PCI_PRODUCT_ATI_RADEON_R200_QM, RADEON_R200, 0 }, 292 1.1 gdamore 293 1.1 gdamore /* RV200 family */ 294 1.1 gdamore { PCI_PRODUCT_ATI_RADEON_RV200_LW, RADEON_RV200, RFB_MOB }, 295 1.1 gdamore { PCI_PRODUCT_ATI_RADEON_RV200_LX, RADEON_RV200, RFB_MOB }, 296 1.1 gdamore { PCI_PRODUCT_ATI_RADEON_RV200_QW, RADEON_RV200, 0 }, 297 1.1 gdamore { PCI_PRODUCT_ATI_RADEON_RV200_QX, RADEON_RV200, 0 }, 298 1.1 gdamore 299 1.1 gdamore /* RV250 family */ 300 1.1 gdamore { PCI_PRODUCT_ATI_RADEON_RV250_4966, RADEON_RV250, 0 }, 301 1.1 gdamore { PCI_PRODUCT_ATI_RADEON_RV250_4967, RADEON_RV250, 0 }, 302 1.1 gdamore { PCI_PRODUCT_ATI_RADEON_RV250_4C64, RADEON_RV250, RFB_MOB }, 303 1.1 gdamore { PCI_PRODUCT_ATI_RADEON_RV250_4C66, RADEON_RV250, RFB_MOB }, 304 1.1 gdamore { PCI_PRODUCT_ATI_RADEON_RV250_4C67, RADEON_RV250, RFB_MOB }, 305 1.1 gdamore 306 1.1 gdamore /* RS300 family */ 307 1.1 gdamore { PCI_PRODUCT_ATI_RADEON_RS300_X5, RADEON_RS300, 0 }, 308 1.1 gdamore { PCI_PRODUCT_ATI_RADEON_RS300_X4, RADEON_RS300, 0 }, 309 1.1 gdamore { PCI_PRODUCT_ATI_RADEON_RS300_7834, RADEON_RS300, 0 }, 310 1.1 gdamore { PCI_PRODUCT_ATI_RADEON_RS300_7835, RADEON_RS300, RFB_MOB }, 311 1.1 gdamore 312 1.1 gdamore /* RV280 family */ 313 1.1 gdamore { PCI_PRODUCT_ATI_RADEON_RV280_5960, RADEON_RV280, 0 }, 314 1.1 gdamore { PCI_PRODUCT_ATI_RADEON_RV280_5961, RADEON_RV280, 0 }, 315 1.1 gdamore { PCI_PRODUCT_ATI_RADEON_RV280_5962, RADEON_RV280, 0 }, 316 1.1 gdamore { PCI_PRODUCT_ATI_RADEON_RV280_5963, RADEON_RV280, 0 }, 317 1.1 gdamore { PCI_PRODUCT_ATI_RADEON_RV280_5964, RADEON_RV280, 0 }, 318 1.1 gdamore { PCI_PRODUCT_ATI_RADEON_RV280_5C61, RADEON_RV280, RFB_MOB }, 319 1.1 gdamore { PCI_PRODUCT_ATI_RADEON_RV280_5C63, RADEON_RV280, RFB_MOB }, 320 1.1 gdamore 321 1.1 gdamore /* R300 family */ 322 1.1 gdamore { PCI_PRODUCT_ATI_RADEON_R300_AD, RADEON_R300, 0 }, 323 1.1 gdamore { PCI_PRODUCT_ATI_RADEON_R300_AE, RADEON_R300, 0 }, 324 1.1 gdamore { PCI_PRODUCT_ATI_RADEON_R300_AF, RADEON_R300, 0 }, 325 1.1 gdamore { PCI_PRODUCT_ATI_RADEON_R300_AG, RADEON_R300, 0 }, 326 1.1 gdamore { PCI_PRODUCT_ATI_RADEON_R300_ND, RADEON_R300, 0 }, 327 1.1 gdamore { PCI_PRODUCT_ATI_RADEON_R300_NE, RADEON_R300, 0 }, 328 1.1 gdamore { PCI_PRODUCT_ATI_RADEON_R300_NF, RADEON_R300, 0 }, 329 1.1 gdamore { PCI_PRODUCT_ATI_RADEON_R300_NG, RADEON_R300, 0 }, 330 1.1 gdamore 331 1.1 gdamore /* RV350/RV360 family */ 332 1.1 gdamore { PCI_PRODUCT_ATI_RADEON_RV350_AP, RADEON_RV350, 0 }, 333 1.1 gdamore { PCI_PRODUCT_ATI_RADEON_RV350_AQ, RADEON_RV350, 0 }, 334 1.1 gdamore { PCI_PRODUCT_ATI_RADEON_RV360_AR, RADEON_RV350, 0 }, 335 1.1 gdamore { PCI_PRODUCT_ATI_RADEON_RV350_AS, RADEON_RV350, 0 }, 336 1.1 gdamore { PCI_PRODUCT_ATI_RADEON_RV350_AT, RADEON_RV350, 0 }, 337 1.1 gdamore { PCI_PRODUCT_ATI_RADEON_RV350_AV, RADEON_RV350, 0 }, 338 1.1 gdamore { PCI_PRODUCT_ATI_RADEON_RV350_NP, RADEON_RV350, RFB_MOB }, 339 1.1 gdamore { PCI_PRODUCT_ATI_RADEON_RV350_NQ, RADEON_RV350, RFB_MOB }, 340 1.1 gdamore { PCI_PRODUCT_ATI_RADEON_RV350_NR, RADEON_RV350, RFB_MOB }, 341 1.1 gdamore { PCI_PRODUCT_ATI_RADEON_RV350_NS, RADEON_RV350, RFB_MOB }, 342 1.1 gdamore { PCI_PRODUCT_ATI_RADEON_RV350_NT, RADEON_RV350, RFB_MOB }, 343 1.1 gdamore { PCI_PRODUCT_ATI_RADEON_RV350_NV, RADEON_RV350, RFB_MOB }, 344 1.1 gdamore 345 1.1 gdamore /* R350/R360 family */ 346 1.1 gdamore { PCI_PRODUCT_ATI_RADEON_R350_AH, RADEON_R350, 0 }, 347 1.1 gdamore { PCI_PRODUCT_ATI_RADEON_R350_AI, RADEON_R350, 0 }, 348 1.1 gdamore { PCI_PRODUCT_ATI_RADEON_R350_AJ, RADEON_R350, 0 }, 349 1.1 gdamore { PCI_PRODUCT_ATI_RADEON_R350_AK, RADEON_R350, 0 }, 350 1.1 gdamore { PCI_PRODUCT_ATI_RADEON_R350_NH, RADEON_R350, 0 }, 351 1.1 gdamore { PCI_PRODUCT_ATI_RADEON_R350_NI, RADEON_R350, 0 }, 352 1.1 gdamore { PCI_PRODUCT_ATI_RADEON_R350_NK, RADEON_R350, 0 }, 353 1.1 gdamore { PCI_PRODUCT_ATI_RADEON_R360_NJ, RADEON_R350, 0 }, 354 1.1 gdamore 355 1.1 gdamore /* RV380/RV370 family */ 356 1.1 gdamore { PCI_PRODUCT_ATI_RADEON_RV380_3150, RADEON_RV380, RFB_MOB }, 357 1.1 gdamore { PCI_PRODUCT_ATI_RADEON_RV380_3154, RADEON_RV380, RFB_MOB }, 358 1.1 gdamore { PCI_PRODUCT_ATI_RADEON_RV380_3E50, RADEON_RV380, 0 }, 359 1.1 gdamore { PCI_PRODUCT_ATI_RADEON_RV380_3E54, RADEON_RV380, 0 }, 360 1.1 gdamore { PCI_PRODUCT_ATI_RADEON_RV370_5460, RADEON_RV380, RFB_MOB }, 361 1.1 gdamore { PCI_PRODUCT_ATI_RADEON_RV370_5464, RADEON_RV380, RFB_MOB }, 362 1.1 gdamore { PCI_PRODUCT_ATI_RADEON_RV370_5B60, RADEON_RV380, 0 }, 363 1.74 macallan { PCI_PRODUCT_ATI_RADEON_RV370_5B63, RADEON_RV380, 0 }, 364 1.1 gdamore { PCI_PRODUCT_ATI_RADEON_RV370_5B64, RADEON_RV380, 0 }, 365 1.1 gdamore { PCI_PRODUCT_ATI_RADEON_RV370_5B65, RADEON_RV380, 0 }, 366 1.1 gdamore 367 1.71 macallan #if notyet 368 1.1 gdamore /* R420/R423 family */ 369 1.1 gdamore { PCI_PRODUCT_ATI_RADEON_R420_JH, RADEON_R420, 0 }, 370 1.1 gdamore { PCI_PRODUCT_ATI_RADEON_R420_JI, RADEON_R420, 0 }, 371 1.1 gdamore { PCI_PRODUCT_ATI_RADEON_R420_JJ, RADEON_R420, 0 }, 372 1.1 gdamore { PCI_PRODUCT_ATI_RADEON_R420_JK, RADEON_R420, 0 }, 373 1.1 gdamore { PCI_PRODUCT_ATI_RADEON_R420_JL, RADEON_R420, 0 }, 374 1.1 gdamore { PCI_PRODUCT_ATI_RADEON_R420_JM, RADEON_R420, 0 }, 375 1.1 gdamore { PCI_PRODUCT_ATI_RADEON_R420_JN, RADEON_R420, RFB_MOB }, 376 1.1 gdamore { PCI_PRODUCT_ATI_RADEON_R420_JP, RADEON_R420, 0 }, 377 1.1 gdamore { PCI_PRODUCT_ATI_RADEON_R423_UH, RADEON_R420, 0 }, 378 1.1 gdamore { PCI_PRODUCT_ATI_RADEON_R423_UI, RADEON_R420, 0 }, 379 1.1 gdamore { PCI_PRODUCT_ATI_RADEON_R423_UJ, RADEON_R420, 0 }, 380 1.1 gdamore { PCI_PRODUCT_ATI_RADEON_R423_UK, RADEON_R420, 0 }, 381 1.1 gdamore { PCI_PRODUCT_ATI_RADEON_R423_UQ, RADEON_R420, 0 }, 382 1.1 gdamore { PCI_PRODUCT_ATI_RADEON_R423_UR, RADEON_R420, 0 }, 383 1.1 gdamore { PCI_PRODUCT_ATI_RADEON_R423_UT, RADEON_R420, 0 }, 384 1.1 gdamore { PCI_PRODUCT_ATI_RADEON_R423_5D57, RADEON_R420, 0 }, 385 1.22 bjs { PCI_PRODUCT_ATI_RADEON_R430_554F, RADEON_R420, 0 }, 386 1.110 macallan #endif 387 1.90 macallan 388 1.90 macallan /* R5xx family */ 389 1.110 macallan { 0x7240, RADEON_R580, RFB_IS_AVIVO }, 390 1.1 gdamore { 0, 0, 0 } 391 1.1 gdamore }; 392 1.1 gdamore 393 1.1 gdamore static struct { 394 1.1 gdamore int divider; 395 1.1 gdamore int mask; 396 1.1 gdamore } radeonfb_dividers[] = { 397 1.69 macallan { 16, 5 }, 398 1.69 macallan { 12, 7 }, 399 1.69 macallan { 8, 3 }, 400 1.69 macallan { 6, 6 }, 401 1.69 macallan { 4, 2 }, 402 1.69 macallan { 3, 4 }, 403 1.69 macallan { 2, 1 }, 404 1.1 gdamore { 1, 0 }, 405 1.1 gdamore { 0, 0 } 406 1.1 gdamore }; 407 1.1 gdamore 408 1.1 gdamore /* 409 1.1 gdamore * This table taken from X11. 410 1.1 gdamore */ 411 1.1 gdamore static const struct { 412 1.1 gdamore int family; 413 1.1 gdamore struct radeon_tmds_pll plls[4]; 414 1.1 gdamore } radeonfb_tmds_pll[] = { 415 1.1 gdamore { RADEON_R100, {{12000, 0xa1b}, {-1, 0xa3f}}}, 416 1.1 gdamore { RADEON_RV100, {{12000, 0xa1b}, {-1, 0xa3f}}}, 417 1.1 gdamore { RADEON_RS100, {{0, 0}}}, 418 1.1 gdamore { RADEON_RV200, {{15000, 0xa1b}, {-1, 0xa3f}}}, 419 1.1 gdamore { RADEON_RS200, {{15000, 0xa1b}, {-1, 0xa3f}}}, 420 1.1 gdamore { RADEON_R200, {{15000, 0xa1b}, {-1, 0xa3f}}}, 421 1.1 gdamore { RADEON_RV250, {{15500, 0x81b}, {-1, 0x83f}}}, 422 1.1 gdamore { RADEON_RS300, {{0, 0}}}, 423 1.91 macallan { RADEON_RV280, {{13000, 0x400f4}, {15000, 0x400f7}, {-1, 0x40111}}}, 424 1.1 gdamore { RADEON_R300, {{-1, 0xb01cb}}}, 425 1.1 gdamore { RADEON_R350, {{-1, 0xb01cb}}}, 426 1.1 gdamore { RADEON_RV350, {{15000, 0xb0155}, {-1, 0xb01cb}}}, 427 1.1 gdamore { RADEON_RV380, {{15000, 0xb0155}, {-1, 0xb01cb}}}, 428 1.1 gdamore { RADEON_R420, {{-1, 0xb01cb}}}, 429 1.110 macallan { RADEON_R580, {{-1, 0xb01cb}}}, /* XXX likely bogus */ 430 1.1 gdamore }; 431 1.1 gdamore 432 1.9 macallan #define RADEONFB_BACKLIGHT_MAX 255 /* Maximum backlight level. */ 433 1.9 macallan 434 1.1 gdamore 435 1.47 macallan CFATTACH_DECL_NEW(radeonfb, sizeof (struct radeonfb_softc), 436 1.1 gdamore radeonfb_match, radeonfb_attach, NULL, NULL); 437 1.1 gdamore 438 1.1 gdamore static int 439 1.31 cegger radeonfb_match(device_t parent, cfdata_t match, void *aux) 440 1.1 gdamore { 441 1.44 dyoung const struct pci_attach_args *pa = aux; 442 1.1 gdamore int i; 443 1.1 gdamore 444 1.1 gdamore if (PCI_VENDOR(pa->pa_id) != PCI_VENDOR_ATI) 445 1.1 gdamore return 0; 446 1.1 gdamore 447 1.1 gdamore for (i = 0; radeonfb_devices[i].devid; i++) { 448 1.1 gdamore if (PCI_PRODUCT(pa->pa_id) == radeonfb_devices[i].devid) 449 1.1 gdamore return 100; /* high to defeat VGA/VESA */ 450 1.1 gdamore } 451 1.1 gdamore 452 1.1 gdamore return 0; 453 1.1 gdamore } 454 1.1 gdamore 455 1.1 gdamore static void 456 1.31 cegger radeonfb_attach(device_t parent, device_t dev, void *aux) 457 1.1 gdamore { 458 1.33 cegger struct radeonfb_softc *sc = device_private(dev); 459 1.44 dyoung const struct pci_attach_args *pa = aux; 460 1.9 macallan const char *mptr; 461 1.1 gdamore bus_size_t bsz; 462 1.5 macallan pcireg_t screg; 463 1.34 macallan int i, j, fg, bg, ul, flags; 464 1.1 gdamore uint32_t v; 465 1.1 gdamore 466 1.47 macallan sc->sc_dev = dev; 467 1.1 gdamore sc->sc_id = pa->pa_id; 468 1.1 gdamore for (i = 0; radeonfb_devices[i].devid; i++) { 469 1.1 gdamore if (PCI_PRODUCT(sc->sc_id) == radeonfb_devices[i].devid) 470 1.1 gdamore break; 471 1.1 gdamore } 472 1.1 gdamore 473 1.53 drochner pci_aprint_devinfo(pa, NULL); 474 1.1 gdamore 475 1.84 riastrad DPRINTF(("%s", prop_dictionary_externalize(device_properties(dev)))); 476 1.17 macallan 477 1.1 gdamore KASSERT(radeonfb_devices[i].devid != 0); 478 1.1 gdamore sc->sc_pt = pa->pa_tag; 479 1.16 macallan sc->sc_iot = pa->pa_iot; 480 1.1 gdamore sc->sc_pc = pa->pa_pc; 481 1.1 gdamore sc->sc_family = radeonfb_devices[i].family; 482 1.1 gdamore sc->sc_flags = radeonfb_devices[i].flags; 483 1.104 macallan sc->sc_bios = NULL; 484 1.104 macallan sc->sc_biossz = 0; 485 1.1 gdamore 486 1.5 macallan /* enable memory and IO access */ 487 1.5 macallan screg = pci_conf_read(sc->sc_pc, sc->sc_pt, PCI_COMMAND_STATUS_REG); 488 1.43 dyoung screg |= PCI_COMMAND_IO_ENABLE | PCI_COMMAND_MEM_ENABLE; 489 1.5 macallan pci_conf_write(sc->sc_pc, sc->sc_pt, PCI_COMMAND_STATUS_REG, screg); 490 1.5 macallan 491 1.1 gdamore /* 492 1.1 gdamore * Some flags are general to entire chip families, and rather 493 1.1 gdamore * than clutter up the table with them, we go ahead and set 494 1.1 gdamore * them here. 495 1.1 gdamore */ 496 1.1 gdamore switch (sc->sc_family) { 497 1.1 gdamore case RADEON_RS100: 498 1.1 gdamore case RADEON_RS200: 499 1.1 gdamore sc->sc_flags |= RFB_IGP | RFB_RV100; 500 1.1 gdamore break; 501 1.1 gdamore 502 1.1 gdamore case RADEON_RV100: 503 1.1 gdamore case RADEON_RV200: 504 1.1 gdamore case RADEON_RV250: 505 1.1 gdamore case RADEON_RV280: 506 1.1 gdamore sc->sc_flags |= RFB_RV100; 507 1.1 gdamore break; 508 1.1 gdamore 509 1.1 gdamore case RADEON_RS300: 510 1.1 gdamore sc->sc_flags |= RFB_SDAC | RFB_IGP | RFB_RV100; 511 1.1 gdamore break; 512 1.1 gdamore 513 1.1 gdamore case RADEON_R300: 514 1.1 gdamore case RADEON_RV350: 515 1.1 gdamore case RADEON_R350: 516 1.1 gdamore case RADEON_RV380: 517 1.1 gdamore case RADEON_R420: 518 1.110 macallan case RADEON_R580: 519 1.1 gdamore /* newer chips */ 520 1.1 gdamore sc->sc_flags |= RFB_R300; 521 1.1 gdamore break; 522 1.1 gdamore 523 1.1 gdamore case RADEON_R100: 524 1.1 gdamore sc->sc_flags |= RFB_NCRTC2; 525 1.1 gdamore break; 526 1.1 gdamore } 527 1.1 gdamore 528 1.17 macallan if ((sc->sc_family == RADEON_RV200) || 529 1.17 macallan (sc->sc_family == RADEON_RV250) || 530 1.17 macallan (sc->sc_family == RADEON_RV280) || 531 1.17 macallan (sc->sc_family == RADEON_RV350)) { 532 1.18 macallan bool inverted = 0; 533 1.17 macallan /* backlight level is linear */ 534 1.17 macallan DPRINTF(("found RV* chip, backlight is supposedly linear\n")); 535 1.47 macallan prop_dictionary_get_bool(device_properties(sc->sc_dev), 536 1.17 macallan "backlight_level_reverted", &inverted); 537 1.17 macallan if (inverted) { 538 1.17 macallan DPRINTF(("nope, it's inverted\n")); 539 1.17 macallan sc->sc_flags |= RFB_INV_BLIGHT; 540 1.17 macallan } 541 1.17 macallan } else 542 1.17 macallan sc->sc_flags |= RFB_INV_BLIGHT; 543 1.17 macallan 544 1.1 gdamore /* 545 1.1 gdamore * XXX: to support true multihead, this must change. 546 1.1 gdamore */ 547 1.1 gdamore sc->sc_ndisplays = 1; 548 1.1 gdamore 549 1.1 gdamore /* XXX: */ 550 1.1 gdamore if (!HAS_CRTC2(sc)) { 551 1.1 gdamore sc->sc_ndisplays = 1; 552 1.1 gdamore } 553 1.1 gdamore 554 1.1 gdamore if (pci_mapreg_map(pa, RADEON_MAPREG_MMIO, PCI_MAPREG_TYPE_MEM, 0, 555 1.1 gdamore &sc->sc_regt, &sc->sc_regh, &sc->sc_regaddr, 556 1.1 gdamore &sc->sc_regsz) != 0) { 557 1.1 gdamore aprint_error("%s: unable to map registers!\n", XNAME(sc)); 558 1.1 gdamore goto error; 559 1.1 gdamore } 560 1.1 gdamore 561 1.34 macallan if (pci_mapreg_info(sc->sc_pc, sc->sc_pt, PCI_MAPREG_ROM, 562 1.34 macallan PCI_MAPREG_TYPE_ROM, &sc->sc_romaddr, &sc->sc_romsz, &flags) != 0) 563 1.34 macallan { 564 1.34 macallan aprint_error("%s: unable to find ROM!\n", XNAME(sc)); 565 1.34 macallan goto error; 566 1.34 macallan } 567 1.34 macallan sc->sc_romt = sc->sc_memt; 568 1.34 macallan 569 1.68 macallan sc->sc_mapped = TRUE; 570 1.68 macallan 571 1.1 gdamore /* scratch register test... */ 572 1.1 gdamore if (radeonfb_scratch_test(sc, RADEON_BIOS_0_SCRATCH, 0x55555555) || 573 1.1 gdamore radeonfb_scratch_test(sc, RADEON_BIOS_0_SCRATCH, 0xaaaaaaaa)) { 574 1.1 gdamore aprint_error("%s: scratch register test failed!\n", XNAME(sc)); 575 1.1 gdamore goto error; 576 1.1 gdamore } 577 1.1 gdamore 578 1.66 macallan PRINTREG(RADEON_CRTC_EXT_CNTL); 579 1.66 macallan PRINTREG(RADEON_CRTC_GEN_CNTL); 580 1.66 macallan PRINTREG(RADEON_CRTC2_GEN_CNTL); 581 1.66 macallan PRINTREG(RADEON_DISP_OUTPUT_CNTL); 582 1.66 macallan PRINTREG(RADEON_DAC_CNTL2); 583 1.1 gdamore PRINTREG(RADEON_BIOS_4_SCRATCH); 584 1.1 gdamore PRINTREG(RADEON_FP_GEN_CNTL); 585 1.36 macallan sc->sc_fp_gen_cntl = GET32(sc, RADEON_FP_GEN_CNTL); 586 1.1 gdamore PRINTREG(RADEON_FP2_GEN_CNTL); 587 1.1 gdamore PRINTREG(RADEON_TMDS_CNTL); 588 1.1 gdamore PRINTREG(RADEON_TMDS_TRANSMITTER_CNTL); 589 1.1 gdamore PRINTREG(RADEON_TMDS_PLL_CNTL); 590 1.1 gdamore PRINTREG(RADEON_LVDS_GEN_CNTL); 591 1.91 macallan PRINTREG(RADEON_DISP_HW_DEBUG); 592 1.110 macallan if (!IS_AVIVO(sc)) { 593 1.111 jdc /* 594 1.111 jdc XXX: We can't print this, as it's not correctly aligned 595 1.110 macallan PRINTREG(RADEON_PIXCLKS_CNTL); 596 1.111 jdc */ 597 1.110 macallan PRINTREG(RADEON_CRTC_H_SYNC_STRT_WID); 598 1.110 macallan PRINTREG(RADEON_FP_H_SYNC_STRT_WID); 599 1.110 macallan PRINTREG(RADEON_CRTC2_H_SYNC_STRT_WID); 600 1.110 macallan PRINTREG(RADEON_FP_H2_SYNC_STRT_WID); 601 1.110 macallan } 602 1.99 macallan /* 603 1.99 macallan * XXX 604 1.99 macallan * This was if (IS_RV100()), which is set for all pre-R3xx chips. 605 1.99 macallan * I suspect this only makes sense on Sun XVR-100 with firmware that doesn't 606 1.99 macallan * support DVI, so for now let's restrict it to only actual RV100 607 1.99 macallan */ 608 1.99 macallan if (sc->sc_family == RADEON_RV100) 609 1.69 macallan PUT32(sc, RADEON_TMDS_PLL_CNTL, 0xa27); 610 1.1 gdamore 611 1.69 macallan /* XXX 612 1.69 macallan * according to xf86-video-radeon R3xx has this bit backwards 613 1.69 macallan */ 614 1.69 macallan if (IS_R300(sc)) { 615 1.69 macallan PATCH32(sc, RADEON_TMDS_TRANSMITTER_CNTL, 616 1.69 macallan 0, 617 1.69 macallan ~(RADEON_TMDS_TRANSMITTER_PLLEN | RADEON_TMDS_TRANSMITTER_PLLRST)); 618 1.69 macallan } else { 619 1.69 macallan PATCH32(sc, RADEON_TMDS_TRANSMITTER_CNTL, 620 1.69 macallan RADEON_TMDS_TRANSMITTER_PLLEN, 621 1.69 macallan ~(RADEON_TMDS_TRANSMITTER_PLLEN | RADEON_TMDS_TRANSMITTER_PLLRST)); 622 1.69 macallan } 623 1.89 macallan 624 1.1 gdamore radeonfb_i2c_init(sc); 625 1.1 gdamore 626 1.1 gdamore radeonfb_loadbios(sc, pa); 627 1.1 gdamore 628 1.39 macallan #ifdef RADEONFB_BIOS_INIT 629 1.1 gdamore if (radeonfb_bios_init(sc)) { 630 1.1 gdamore aprint_error("%s: BIOS inititialization failed\n", XNAME(sc)); 631 1.1 gdamore } 632 1.1 gdamore #endif 633 1.1 gdamore 634 1.1 gdamore if (radeonfb_getclocks(sc)) { 635 1.1 gdamore aprint_error("%s: Unable to get reference clocks from BIOS\n", 636 1.1 gdamore XNAME(sc)); 637 1.1 gdamore goto error; 638 1.1 gdamore } 639 1.1 gdamore 640 1.1 gdamore if (radeonfb_gettmds(sc)) { 641 1.1 gdamore aprint_error("%s: Unable to identify TMDS PLL settings\n", 642 1.1 gdamore XNAME(sc)); 643 1.1 gdamore goto error; 644 1.1 gdamore } 645 1.1 gdamore 646 1.1 gdamore aprint_verbose("%s: refclk = %d.%03d MHz, refdiv = %d " 647 1.1 gdamore "minpll = %d, maxpll = %d\n", XNAME(sc), 648 1.1 gdamore (int)sc->sc_refclk / 1000, (int)sc->sc_refclk % 1000, 649 1.1 gdamore (int)sc->sc_refdiv, (int)sc->sc_minpll, (int)sc->sc_maxpll); 650 1.1 gdamore 651 1.1 gdamore radeonfb_getconnectors(sc); 652 1.1 gdamore 653 1.1 gdamore radeonfb_set_fbloc(sc); 654 1.1 gdamore 655 1.81 macallan /* 64 MB should be enough -- more just wastes map entries */ 656 1.81 macallan if (sc->sc_memsz > (64 << 20)) 657 1.81 macallan sc->sc_memsz = (64 << 20); 658 1.81 macallan 659 1.1 gdamore for (i = 0; radeonfb_limits[i].size; i++) { 660 1.1 gdamore if (sc->sc_memsz >= radeonfb_limits[i].size) { 661 1.1 gdamore sc->sc_maxx = radeonfb_limits[i].maxx; 662 1.1 gdamore sc->sc_maxy = radeonfb_limits[i].maxy; 663 1.1 gdamore sc->sc_maxbpp = radeonfb_limits[i].maxbpp; 664 1.1 gdamore /* framebuffer offset, start at a 4K page */ 665 1.1 gdamore sc->sc_fboffset = sc->sc_memsz / 666 1.1 gdamore radeonfb_limits[i].maxdisp; 667 1.1 gdamore /* 668 1.1 gdamore * we use the fbsize to figure out where we can store 669 1.1 gdamore * things like cursor data. 670 1.1 gdamore */ 671 1.1 gdamore sc->sc_fbsize = 672 1.1 gdamore ROUNDUP(ROUNDUP(sc->sc_maxx * sc->sc_maxbpp / 8 , 673 1.1 gdamore RADEON_STRIDEALIGN) * sc->sc_maxy, 674 1.1 gdamore 4096); 675 1.1 gdamore break; 676 1.1 gdamore } 677 1.1 gdamore } 678 1.1 gdamore 679 1.1 gdamore 680 1.1 gdamore radeonfb_init_misc(sc); 681 1.1 gdamore 682 1.1 gdamore /* program the DAC wirings */ 683 1.1 gdamore for (i = 0; i < (HAS_CRTC2(sc) ? 2 : 1); i++) { 684 1.1 gdamore switch (sc->sc_ports[i].rp_dac_type) { 685 1.1 gdamore case RADEON_DAC_PRIMARY: 686 1.1 gdamore PATCH32(sc, RADEON_DAC_CNTL2, 687 1.1 gdamore i ? RADEON_DAC2_DAC_CLK_SEL : 0, 688 1.1 gdamore ~RADEON_DAC2_DAC_CLK_SEL); 689 1.1 gdamore break; 690 1.1 gdamore case RADEON_DAC_TVDAC: 691 1.1 gdamore /* we always use the TVDAC to drive a secondary analog 692 1.1 gdamore * CRT for now. if we ever support TV-out this will 693 1.1 gdamore * have to change. 694 1.1 gdamore */ 695 1.1 gdamore SET32(sc, RADEON_DAC_CNTL2, 696 1.1 gdamore RADEON_DAC2_DAC2_CLK_SEL); 697 1.1 gdamore PATCH32(sc, RADEON_DISP_HW_DEBUG, 698 1.1 gdamore i ? 0 : RADEON_CRT2_DISP1_SEL, 699 1.1 gdamore ~RADEON_CRT2_DISP1_SEL); 700 1.69 macallan /* we're using CRTC2 for the 2nd port */ 701 1.70 macallan if (sc->sc_ports[i].rp_number == 1) { 702 1.69 macallan PATCH32(sc, RADEON_DISP_OUTPUT_CNTL, 703 1.69 macallan RADEON_DISP_DAC2_SOURCE_CRTC2, 704 1.69 macallan ~RADEON_DISP_DAC2_SOURCE_MASK); 705 1.69 macallan } 706 1.69 macallan 707 1.1 gdamore break; 708 1.1 gdamore } 709 1.70 macallan DPRINTF(("%s: port %d tmds type %d\n", __func__, i, 710 1.70 macallan sc->sc_ports[i].rp_tmds_type)); 711 1.69 macallan switch (sc->sc_ports[i].rp_tmds_type) { 712 1.69 macallan case RADEON_TMDS_INT: 713 1.69 macallan /* point FP0 at the CRTC this port uses */ 714 1.70 macallan DPRINTF(("%s: plugging internal TMDS into CRTC %d\n", 715 1.70 macallan __func__, sc->sc_ports[i].rp_number)); 716 1.69 macallan if (IS_R300(sc)) { 717 1.69 macallan PATCH32(sc, RADEON_FP_GEN_CNTL, 718 1.69 macallan sc->sc_ports[i].rp_number ? 719 1.69 macallan R200_FP_SOURCE_SEL_CRTC2 : 720 1.69 macallan R200_FP_SOURCE_SEL_CRTC1, 721 1.69 macallan ~R200_FP_SOURCE_SEL_MASK); 722 1.69 macallan } else { 723 1.69 macallan PATCH32(sc, RADEON_FP_GEN_CNTL, 724 1.69 macallan sc->sc_ports[i].rp_number ? 725 1.69 macallan RADEON_FP_SEL_CRTC2 : 726 1.69 macallan RADEON_FP_SEL_CRTC1, 727 1.69 macallan ~RADEON_FP_SEL_MASK); 728 1.69 macallan } 729 1.93 macallan break; 730 1.91 macallan case RADEON_TMDS_EXT: 731 1.91 macallan /* point FP2 at the CRTC this port uses */ 732 1.91 macallan DPRINTF(("%s: plugging external TMDS into CRTC %d\n", 733 1.91 macallan __func__, sc->sc_ports[i].rp_number)); 734 1.91 macallan if (IS_R300(sc)) { 735 1.91 macallan PATCH32(sc, RADEON_FP2_GEN_CNTL, 736 1.91 macallan sc->sc_ports[i].rp_number ? 737 1.91 macallan R200_FP2_SOURCE_SEL_CRTC2 : 738 1.91 macallan R200_FP2_SOURCE_SEL_CRTC1, 739 1.91 macallan ~R200_FP2_SOURCE_SEL_CRTC2); 740 1.91 macallan } else { 741 1.91 macallan PATCH32(sc, RADEON_FP2_GEN_CNTL, 742 1.91 macallan sc->sc_ports[i].rp_number ? 743 1.91 macallan RADEON_FP2_SRC_SEL_CRTC2 : 744 1.91 macallan RADEON_FP2_SRC_SEL_CRTC1, 745 1.91 macallan ~RADEON_FP2_SRC_SEL_CRTC2); 746 1.91 macallan } 747 1.93 macallan break; 748 1.69 macallan } 749 1.1 gdamore } 750 1.1 gdamore PRINTREG(RADEON_DAC_CNTL2); 751 1.1 gdamore PRINTREG(RADEON_DISP_HW_DEBUG); 752 1.1 gdamore 753 1.91 macallan PRINTREG(RADEON_DAC_CNTL); 754 1.1 gdamore /* other DAC programming */ 755 1.1 gdamore v = GET32(sc, RADEON_DAC_CNTL); 756 1.1 gdamore v &= (RADEON_DAC_RANGE_CNTL_MASK | RADEON_DAC_BLANKING); 757 1.1 gdamore v |= RADEON_DAC_MASK_ALL | RADEON_DAC_8BIT_EN; 758 1.1 gdamore PUT32(sc, RADEON_DAC_CNTL, v); 759 1.1 gdamore PRINTREG(RADEON_DAC_CNTL); 760 1.11 ad 761 1.1 gdamore /* XXX: this may need more investigation */ 762 1.1 gdamore PUT32(sc, RADEON_TV_DAC_CNTL, 0x00280203); 763 1.1 gdamore PRINTREG(RADEON_TV_DAC_CNTL); 764 1.1 gdamore 765 1.1 gdamore /* enable TMDS */ 766 1.1 gdamore SET32(sc, RADEON_FP_GEN_CNTL, 767 1.1 gdamore RADEON_FP_TMDS_EN | 768 1.1 gdamore RADEON_FP_CRTC_DONT_SHADOW_VPAR | 769 1.1 gdamore RADEON_FP_CRTC_DONT_SHADOW_HEND); 770 1.36 macallan /* 771 1.36 macallan * XXX 772 1.36 macallan * no idea why this is necessary - if I do not clear this bit on my 773 1.36 macallan * iBook G4 the screen remains black, even though it's already clear. 774 1.36 macallan * It needs to be set on my Sun XVR-100 for the DVI port to work 775 1.69 macallan * TODO: 776 1.69 macallan * see if this is still necessary now that CRTCs, DACs and outputs are 777 1.69 macallan * getting wired up in a halfway sane way 778 1.36 macallan */ 779 1.36 macallan if (sc->sc_fp_gen_cntl & RADEON_FP_SEL_CRTC2) { 780 1.36 macallan SET32(sc, RADEON_FP_GEN_CNTL, RADEON_FP_SEL_CRTC2); 781 1.69 macallan } else { 782 1.36 macallan CLR32(sc, RADEON_FP_GEN_CNTL, RADEON_FP_SEL_CRTC2); 783 1.69 macallan } 784 1.1 gdamore 785 1.1 gdamore /* 786 1.1 gdamore * we use bus_space_map instead of pci_mapreg, because we don't 787 1.1 gdamore * need the full aperature space. no point in wasting virtual 788 1.1 gdamore * address space we don't intend to use, right? 789 1.1 gdamore */ 790 1.1 gdamore if ((sc->sc_memsz < (4096 * 1024)) || 791 1.1 gdamore (pci_mapreg_info(sc->sc_pc, sc->sc_pt, RADEON_MAPREG_VRAM, 792 1.1 gdamore PCI_MAPREG_TYPE_MEM, &sc->sc_memaddr, &bsz, NULL) != 0) || 793 1.1 gdamore (bsz < sc->sc_memsz)) { 794 1.1 gdamore sc->sc_memsz = 0; 795 1.1 gdamore aprint_error("%s: Bad frame buffer configuration\n", 796 1.1 gdamore XNAME(sc)); 797 1.1 gdamore goto error; 798 1.1 gdamore } 799 1.1 gdamore 800 1.1 gdamore sc->sc_memt = pa->pa_memt; 801 1.1 gdamore if (bus_space_map(sc->sc_memt, sc->sc_memaddr, sc->sc_memsz, 802 1.117 tnn BUS_SPACE_MAP_LINEAR | BUS_SPACE_MAP_PREFETCHABLE, 803 1.117 tnn &sc->sc_memh) != 0) { 804 1.1 gdamore sc->sc_memsz = 0; 805 1.1 gdamore aprint_error("%s: Unable to map frame buffer\n", XNAME(sc)); 806 1.1 gdamore goto error; 807 1.1 gdamore } 808 1.1 gdamore 809 1.1 gdamore aprint_normal("%s: %d MB aperture at 0x%08x, " 810 1.1 gdamore "%d KB registers at 0x%08x\n", XNAME(sc), 811 1.1 gdamore (int)sc->sc_memsz >> 20, (unsigned)sc->sc_memaddr, 812 1.1 gdamore (int)sc->sc_regsz >> 10, (unsigned)sc->sc_regaddr); 813 1.1 gdamore 814 1.1 gdamore /* setup default video mode from devprop (allows PROM override) */ 815 1.1 gdamore sc->sc_defaultmode = radeonfb_default_mode; 816 1.115 christos if (prop_dictionary_get_string(device_properties(sc->sc_dev), 817 1.9 macallan "videomode", &mptr)) { 818 1.9 macallan 819 1.9 macallan strncpy(sc->sc_modebuf, mptr, sizeof(sc->sc_modebuf)); 820 1.9 macallan sc->sc_defaultmode = sc->sc_modebuf; 821 1.1 gdamore } 822 1.1 gdamore 823 1.1 gdamore /* initialize some basic display parameters */ 824 1.1 gdamore for (i = 0; i < sc->sc_ndisplays; i++) { 825 1.1 gdamore struct radeonfb_display *dp = &sc->sc_displays[i]; 826 1.1 gdamore struct rasops_info *ri; 827 1.1 gdamore long defattr; 828 1.1 gdamore struct wsemuldisplaydev_attach_args aa; 829 1.11 ad 830 1.1 gdamore /* 831 1.1 gdamore * Figure out how many "displays" (desktops) we are going to 832 1.1 gdamore * support. If more than one, then each CRTC gets its own 833 1.1 gdamore * programming. 834 1.1 gdamore * 835 1.1 gdamore * XXX: this code needs to change to support mergedfb. 836 1.1 gdamore * XXX: would be nice to allow this to be overridden 837 1.1 gdamore */ 838 1.1 gdamore if (HAS_CRTC2(sc) && (sc->sc_ndisplays == 1)) { 839 1.1 gdamore DPRINTF(("dual crtcs!\n")); 840 1.1 gdamore dp->rd_ncrtcs = 2; 841 1.69 macallan dp->rd_crtcs[0].rc_port = 842 1.69 macallan &sc->sc_ports[0]; 843 1.69 macallan dp->rd_crtcs[0].rc_number = sc->sc_ports[0].rp_number; 844 1.69 macallan dp->rd_crtcs[1].rc_port = 845 1.69 macallan &sc->sc_ports[1]; 846 1.69 macallan dp->rd_crtcs[1].rc_number = sc->sc_ports[1].rp_number; 847 1.1 gdamore } else { 848 1.1 gdamore dp->rd_ncrtcs = 1; 849 1.69 macallan dp->rd_crtcs[0].rc_port = 850 1.69 macallan &sc->sc_ports[i]; 851 1.69 macallan dp->rd_crtcs[0].rc_number = sc->sc_ports[i].rp_number; 852 1.1 gdamore } 853 1.1 gdamore 854 1.1 gdamore dp->rd_softc = sc; 855 1.1 gdamore dp->rd_wsmode = WSDISPLAYIO_MODE_EMUL; 856 1.2 macallan dp->rd_bpp = RADEONFB_DEFAULT_DEPTH; /* XXX */ 857 1.49 macallan 858 1.1 gdamore /* for text mode, we pick a resolution that won't 859 1.1 gdamore * require panning */ 860 1.1 gdamore radeonfb_pickres(dp, &dp->rd_virtx, &dp->rd_virty, 0); 861 1.1 gdamore 862 1.1 gdamore aprint_normal("%s: display %d: " 863 1.8 macallan "initial virtual resolution %dx%d at %d bpp\n", 864 1.1 gdamore XNAME(sc), i, dp->rd_virtx, dp->rd_virty, dp->rd_bpp); 865 1.80 macallan aprint_normal_dev(sc->sc_dev, "using %d MB per display\n", 866 1.80 macallan sc->sc_fboffset >> 20); 867 1.1 gdamore /* now select the *video mode* that we will use */ 868 1.1 gdamore for (j = 0; j < dp->rd_ncrtcs; j++) { 869 1.1 gdamore const struct videomode *vmp; 870 1.9 macallan vmp = radeonfb_port_mode(sc, dp->rd_crtcs[j].rc_port, 871 1.1 gdamore dp->rd_virtx, dp->rd_virty); 872 1.8 macallan 873 1.8 macallan /* 874 1.8 macallan * virtual resolution should be at least as high as 875 1.8 macallan * physical 876 1.8 macallan */ 877 1.8 macallan if (dp->rd_virtx < vmp->hdisplay || 878 1.8 macallan dp->rd_virty < vmp->vdisplay) { 879 1.8 macallan dp->rd_virtx = vmp->hdisplay; 880 1.8 macallan dp->rd_virty = vmp->vdisplay; 881 1.8 macallan } 882 1.8 macallan 883 1.1 gdamore dp->rd_crtcs[j].rc_videomode = *vmp; 884 1.1 gdamore printf("%s: port %d: physical %dx%d %dHz\n", 885 1.1 gdamore XNAME(sc), j, vmp->hdisplay, vmp->vdisplay, 886 1.1 gdamore DIVIDE(DIVIDE(vmp->dot_clock * 1000, 887 1.1 gdamore vmp->htotal), vmp->vtotal)); 888 1.1 gdamore } 889 1.1 gdamore 890 1.1 gdamore /* N.B.: radeon wants 64-byte aligned stride */ 891 1.2 macallan dp->rd_stride = dp->rd_virtx * dp->rd_bpp / 8; 892 1.1 gdamore dp->rd_stride = ROUNDUP(dp->rd_stride, RADEON_STRIDEALIGN); 893 1.1 gdamore 894 1.1 gdamore dp->rd_offset = sc->sc_fboffset * i; 895 1.1 gdamore dp->rd_fbptr = (vaddr_t)bus_space_vaddr(sc->sc_memt, 896 1.1 gdamore sc->sc_memh) + dp->rd_offset; 897 1.110 macallan dp->rd_curoff = sc->sc_fboffset - 16384; /* 16KB cursor space */ 898 1.1 gdamore dp->rd_curptr = dp->rd_fbptr + dp->rd_curoff; 899 1.1 gdamore 900 1.1 gdamore DPRINTF(("fpbtr = %p\n", (void *)dp->rd_fbptr)); 901 1.1 gdamore 902 1.1 gdamore switch (dp->rd_bpp) { 903 1.1 gdamore case 8: 904 1.1 gdamore dp->rd_format = 2; 905 1.1 gdamore break; 906 1.1 gdamore case 32: 907 1.1 gdamore dp->rd_format = 6; 908 1.1 gdamore break; 909 1.1 gdamore default: 910 1.1 gdamore aprint_error("%s: bad depth %d\n", XNAME(sc), 911 1.1 gdamore dp->rd_bpp); 912 1.1 gdamore goto error; 913 1.1 gdamore } 914 1.45 njoly DPRINTF(("init engine\n")); 915 1.2 macallan /* XXX: this seems suspicious - per display engine 916 1.2 macallan initialization? */ 917 1.110 macallan 918 1.110 macallan radeonfb_modeswitch(dp); 919 1.2 macallan radeonfb_engine_init(dp); 920 1.2 macallan 921 1.1 gdamore /* copy the template into place */ 922 1.1 gdamore dp->rd_wsscreens_storage[0] = radeonfb_stdscreen; 923 1.1 gdamore dp->rd_wsscreens = dp->rd_wsscreens_storage; 924 1.1 gdamore 925 1.1 gdamore /* and make up the list */ 926 1.1 gdamore dp->rd_wsscreenlist.nscreens = 1; 927 1.46 christos dp->rd_wsscreenlist.screens = (void *)&dp->rd_wsscreens; 928 1.8 macallan 929 1.1 gdamore vcons_init(&dp->rd_vd, dp, dp->rd_wsscreens, 930 1.1 gdamore &radeonfb_accessops); 931 1.1 gdamore 932 1.1 gdamore dp->rd_vd.init_screen = radeonfb_init_screen; 933 1.1 gdamore 934 1.34 macallan dp->rd_console = 0; 935 1.47 macallan prop_dictionary_get_bool(device_properties(sc->sc_dev), 936 1.34 macallan "is_console", &dp->rd_console); 937 1.1 gdamore 938 1.1 gdamore dp->rd_vscreen.scr_flags |= VCONS_SCREEN_IS_STATIC; 939 1.1 gdamore 940 1.8 macallan 941 1.1 gdamore vcons_init_screen(&dp->rd_vd, &dp->rd_vscreen, 942 1.1 gdamore dp->rd_console, &defattr); 943 1.1 gdamore 944 1.1 gdamore ri = &dp->rd_vscreen.scr_ri; 945 1.8 macallan 946 1.8 macallan /* clear the screen */ 947 1.8 macallan rasops_unpack_attr(defattr, &fg, &bg, &ul); 948 1.76 macallan dp->rd_bg = ri->ri_devcmap[bg & 0xf]; 949 1.8 macallan radeonfb_rectfill(dp, 0, 0, ri->ri_width, ri->ri_height, 950 1.76 macallan dp->rd_bg); 951 1.8 macallan 952 1.1 gdamore dp->rd_wsscreens->textops = &ri->ri_ops; 953 1.1 gdamore dp->rd_wsscreens->capabilities = ri->ri_caps; 954 1.1 gdamore dp->rd_wsscreens->nrows = ri->ri_rows; 955 1.1 gdamore dp->rd_wsscreens->ncols = ri->ri_cols; 956 1.1 gdamore 957 1.1 gdamore #ifdef SPLASHSCREEN 958 1.1 gdamore dp->rd_splash.si_depth = ri->ri_depth; 959 1.1 gdamore dp->rd_splash.si_bits = ri->ri_bits; 960 1.1 gdamore dp->rd_splash.si_hwbits = ri->ri_hwbits; 961 1.1 gdamore dp->rd_splash.si_width = ri->ri_width; 962 1.1 gdamore dp->rd_splash.si_height = ri->ri_height; 963 1.1 gdamore dp->rd_splash.si_stride = ri->ri_stride; 964 1.1 gdamore dp->rd_splash.si_fillrect = NULL; 965 1.1 gdamore #endif 966 1.54 macallan dp->rd_gc.gc_bitblt = radeonfb_bitblt; 967 1.64 macallan dp->rd_gc.gc_rectfill = radeonfb_rectfill_a; 968 1.54 macallan dp->rd_gc.gc_rop = RADEON_ROP3_S; 969 1.54 macallan dp->rd_gc.gc_blitcookie = dp; 970 1.80 macallan /* 971 1.80 macallan * use memory between framebuffer and cursor area as glyph 972 1.80 macallan * cache, cap at 4096 lines 973 1.80 macallan */ 974 1.54 macallan glyphcache_init(&dp->rd_gc, dp->rd_virty + 4, 975 1.100 riastrad uimin(4096, 976 1.80 macallan (dp->rd_curoff / dp->rd_stride) - (dp->rd_virty + 4)), 977 1.64 macallan dp->rd_virtx, 978 1.54 macallan ri->ri_font->fontwidth, 979 1.54 macallan ri->ri_font->fontheight, 980 1.54 macallan defattr); 981 1.89 macallan dp->rd_vd.show_screen_cookie = &dp->rd_gc; 982 1.89 macallan dp->rd_vd.show_screen_cb = glyphcache_adapt; 983 1.89 macallan 984 1.1 gdamore if (dp->rd_console) { 985 1.1 gdamore 986 1.1 gdamore wsdisplay_cnattach(dp->rd_wsscreens, ri, 0, 0, 987 1.1 gdamore defattr); 988 1.1 gdamore #ifdef SPLASHSCREEN 989 1.42 jmcneill if (splash_render(&dp->rd_splash, 990 1.42 jmcneill SPLASH_F_CENTER|SPLASH_F_FILL) == 0) 991 1.42 jmcneill SCREEN_DISABLE_DRAWING(&dp->rd_vscreen); 992 1.42 jmcneill else 993 1.1 gdamore #endif 994 1.42 jmcneill vcons_replay_msgbuf(&dp->rd_vscreen); 995 1.1 gdamore } else { 996 1.1 gdamore 997 1.1 gdamore /* 998 1.1 gdamore * since we're not the console we can postpone 999 1.1 gdamore * the rest until someone actually allocates a 1000 1.1 gdamore * screen for us. but we do clear the screen 1001 1.1 gdamore * at least. 1002 1.1 gdamore */ 1003 1.1 gdamore memset(ri->ri_bits, 0, 1024); 1004 1.1 gdamore 1005 1.1 gdamore #ifdef SPLASHSCREEN 1006 1.42 jmcneill if (splash_render(&dp->rd_splash, 1007 1.42 jmcneill SPLASH_F_CENTER|SPLASH_F_FILL) == 0) 1008 1.42 jmcneill SCREEN_DISABLE_DRAWING(&dp->rd_vscreen); 1009 1.1 gdamore #endif 1010 1.1 gdamore } 1011 1.1 gdamore 1012 1.1 gdamore aa.console = dp->rd_console; 1013 1.1 gdamore aa.scrdata = &dp->rd_wsscreenlist; 1014 1.1 gdamore aa.accessops = &radeonfb_accessops; 1015 1.1 gdamore aa.accesscookie = &dp->rd_vd; 1016 1.1 gdamore 1017 1.114 thorpej config_found(sc->sc_dev, &aa, wsemuldisplaydevprint, 1018 1.116 thorpej CFARGS(.iattr = "wsemuldisplaydev")); 1019 1.116 thorpej 1020 1.2 macallan radeonfb_blank(dp, 0); 1021 1.59 macallan 1022 1.9 macallan /* Initialise delayed lvds operations for backlight. */ 1023 1.15 ad callout_init(&dp->rd_bl_lvds_co, 0); 1024 1.9 macallan callout_setfunc(&dp->rd_bl_lvds_co, 1025 1.9 macallan radeonfb_lvds_callout, dp); 1026 1.110 macallan 1027 1.59 macallan dp->rd_bl_on = 1; 1028 1.108 macallan if (sc->sc_flags & RFB_MOB) { 1029 1.108 macallan dp->rd_bl_level = radeonfb_get_backlight(dp); 1030 1.108 macallan } else 1031 1.108 macallan dp->rd_bl_level = 128; 1032 1.110 macallan 1033 1.59 macallan radeonfb_set_backlight(dp, dp->rd_bl_level); 1034 1.1 gdamore } 1035 1.72 macallan for (i = 0; i < RADEON_NDISPLAYS; i++) 1036 1.70 macallan radeonfb_init_palette(&sc->sc_displays[i]); 1037 1.110 macallan 1038 1.110 macallan if (HAS_CRTC2(sc) && !IS_AVIVO(sc)) { 1039 1.66 macallan CLR32(sc, RADEON_CRTC2_GEN_CNTL, RADEON_CRTC2_DISP_DIS); 1040 1.66 macallan } 1041 1.70 macallan 1042 1.110 macallan if (!IS_AVIVO(sc)) { 1043 1.110 macallan CLR32(sc, RADEON_CRTC_EXT_CNTL, RADEON_CRTC_DISPLAY_DIS); 1044 1.110 macallan SET32(sc, RADEON_FP_GEN_CNTL, RADEON_FP_FPON); 1045 1.110 macallan } 1046 1.110 macallan 1047 1.34 macallan pmf_event_register(dev, PMFE_DISPLAY_BRIGHTNESS_UP, 1048 1.34 macallan radeonfb_brightness_up, TRUE); 1049 1.34 macallan pmf_event_register(dev, PMFE_DISPLAY_BRIGHTNESS_DOWN, 1050 1.34 macallan radeonfb_brightness_down, TRUE); 1051 1.34 macallan 1052 1.88 macallan /* 1053 1.88 macallan * if we attach a DRM we need to unmap registers in 1054 1.88 macallan * WSDISPLAYIO_MODE_MAPPED, since this keeps us from doing things like 1055 1.88 macallan * screen blanking we only do it if needed 1056 1.88 macallan */ 1057 1.88 macallan sc->sc_needs_unmap = 1058 1.114 thorpej (config_found(dev, aux, radeonfb_drm_print, 1059 1.116 thorpej CFARGS(.iattr = "drm")) != NULL); 1060 1.88 macallan DPRINTF(("needs_unmap: %d\n", sc->sc_needs_unmap)); 1061 1.14 macallan 1062 1.110 macallan if (!IS_AVIVO(sc)) { 1063 1.110 macallan PRINTREG(RADEON_CRTC_EXT_CNTL); 1064 1.110 macallan PRINTREG(RADEON_CRTC_GEN_CNTL); 1065 1.110 macallan PRINTREG(RADEON_CRTC2_GEN_CNTL); 1066 1.110 macallan PRINTREG(RADEON_DISP_OUTPUT_CNTL); 1067 1.110 macallan PRINTREG(RADEON_DAC_CNTL2); 1068 1.110 macallan PRINTREG(RADEON_FP_GEN_CNTL); 1069 1.110 macallan PRINTREG(RADEON_FP2_GEN_CNTL); 1070 1.110 macallan PRINTREG(RADEON_TMDS_CNTL); 1071 1.110 macallan PRINTREG(RADEON_TMDS_TRANSMITTER_CNTL); 1072 1.110 macallan PRINTREG(RADEON_TMDS_PLL_CNTL); 1073 1.111 jdc /* 1074 1.111 jdc XXX: We can't print this, as it's not correctly aligned 1075 1.110 macallan PRINTREG(RADEON_PIXCLKS_CNTL); 1076 1.111 jdc */ 1077 1.110 macallan } 1078 1.1 gdamore return; 1079 1.1 gdamore 1080 1.1 gdamore error: 1081 1.1 gdamore if (sc->sc_biossz) 1082 1.1 gdamore free(sc->sc_bios, M_DEVBUF); 1083 1.1 gdamore 1084 1.1 gdamore if (sc->sc_regsz) 1085 1.1 gdamore bus_space_unmap(sc->sc_regt, sc->sc_regh, sc->sc_regsz); 1086 1.1 gdamore 1087 1.1 gdamore if (sc->sc_memsz) 1088 1.1 gdamore bus_space_unmap(sc->sc_memt, sc->sc_memh, sc->sc_memsz); 1089 1.1 gdamore } 1090 1.1 gdamore 1091 1.56 macallan static void 1092 1.56 macallan radeonfb_map(struct radeonfb_softc *sc) 1093 1.56 macallan { 1094 1.68 macallan if (!sc->sc_mapped) { 1095 1.68 macallan if (bus_space_map(sc->sc_regt, sc->sc_regaddr, sc->sc_regsz, 0, 1096 1.68 macallan &sc->sc_regh) != 0) { 1097 1.68 macallan aprint_error_dev(sc->sc_dev, 1098 1.68 macallan "unable to map registers!\n"); 1099 1.68 macallan return; 1100 1.68 macallan } 1101 1.68 macallan if (bus_space_map(sc->sc_memt, sc->sc_memaddr, sc->sc_memsz, 1102 1.117 tnn BUS_SPACE_MAP_LINEAR | BUS_SPACE_MAP_PREFETCHABLE, 1103 1.117 tnn &sc->sc_memh) != 0) { 1104 1.68 macallan sc->sc_memsz = 0; 1105 1.68 macallan aprint_error_dev(sc->sc_dev, 1106 1.68 macallan "Unable to map frame buffer\n"); 1107 1.68 macallan return; 1108 1.68 macallan } 1109 1.68 macallan sc->sc_mapped = TRUE; 1110 1.56 macallan } 1111 1.56 macallan } 1112 1.56 macallan 1113 1.56 macallan static void 1114 1.56 macallan radeonfb_unmap(struct radeonfb_softc *sc) 1115 1.56 macallan { 1116 1.88 macallan if (!sc->sc_needs_unmap) 1117 1.88 macallan return; 1118 1.88 macallan 1119 1.68 macallan if (sc->sc_mapped) { 1120 1.68 macallan bus_space_unmap(sc->sc_regt, sc->sc_regh, sc->sc_regsz); 1121 1.68 macallan bus_space_unmap(sc->sc_memt, sc->sc_memh, sc->sc_memsz); 1122 1.68 macallan sc->sc_mapped = FALSE; 1123 1.68 macallan } 1124 1.56 macallan } 1125 1.56 macallan 1126 1.14 macallan static int 1127 1.14 macallan radeonfb_drm_print(void *aux, const char *pnp) 1128 1.14 macallan { 1129 1.14 macallan if (pnp) 1130 1.28 jmcneill aprint_normal("drm at %s", pnp); 1131 1.28 jmcneill return (UNCONF); 1132 1.14 macallan } 1133 1.14 macallan 1134 1.1 gdamore int 1135 1.1 gdamore radeonfb_ioctl(void *v, void *vs, 1136 1.12 christos unsigned long cmd, void *d, int flag, struct lwp *l) 1137 1.1 gdamore { 1138 1.1 gdamore struct vcons_data *vd; 1139 1.1 gdamore struct radeonfb_display *dp; 1140 1.1 gdamore struct radeonfb_softc *sc; 1141 1.9 macallan struct wsdisplay_param *param; 1142 1.79 macallan struct vcons_screen *ms; 1143 1.1 gdamore 1144 1.1 gdamore vd = (struct vcons_data *)v; 1145 1.79 macallan ms = vd->active; 1146 1.1 gdamore dp = (struct radeonfb_display *)vd->cookie; 1147 1.1 gdamore sc = dp->rd_softc; 1148 1.1 gdamore 1149 1.82 macallan /* can't do these without registers being mapped */ 1150 1.82 macallan if (!sc->sc_mapped) { 1151 1.82 macallan switch (cmd) { 1152 1.82 macallan case WSDISPLAYIO_GVIDEO: 1153 1.82 macallan case WSDISPLAYIO_SVIDEO: 1154 1.82 macallan case WSDISPLAYIO_GETCMAP: 1155 1.82 macallan case WSDISPLAYIO_PUTCMAP: 1156 1.82 macallan case WSDISPLAYIO_SCURSOR: 1157 1.82 macallan case WSDISPLAYIO_GCURPOS: 1158 1.82 macallan case WSDISPLAYIO_SCURPOS: 1159 1.82 macallan case WSDISPLAYIO_SETPARAM: 1160 1.82 macallan return EINVAL; 1161 1.82 macallan } 1162 1.82 macallan } 1163 1.82 macallan 1164 1.1 gdamore switch (cmd) { 1165 1.1 gdamore case WSDISPLAYIO_GTYPE: 1166 1.1 gdamore *(unsigned *)d = WSDISPLAY_TYPE_PCIMISC; 1167 1.1 gdamore return 0; 1168 1.1 gdamore 1169 1.1 gdamore case WSDISPLAYIO_GINFO: 1170 1.1 gdamore if (vd->active != NULL) { 1171 1.1 gdamore struct wsdisplay_fbinfo *fb; 1172 1.1 gdamore fb = (struct wsdisplay_fbinfo *)d; 1173 1.11 ad fb->width = dp->rd_virtx; 1174 1.11 ad fb->height = dp->rd_virty; 1175 1.1 gdamore fb->depth = dp->rd_bpp; 1176 1.1 gdamore fb->cmsize = 256; 1177 1.1 gdamore return 0; 1178 1.1 gdamore } else 1179 1.1 gdamore return ENODEV; 1180 1.1 gdamore case WSDISPLAYIO_GVIDEO: 1181 1.1 gdamore if (radeonfb_isblank(dp)) 1182 1.1 gdamore *(unsigned *)d = WSDISPLAYIO_VIDEO_OFF; 1183 1.1 gdamore else 1184 1.1 gdamore *(unsigned *)d = WSDISPLAYIO_VIDEO_ON; 1185 1.1 gdamore return 0; 1186 1.1 gdamore 1187 1.1 gdamore case WSDISPLAYIO_SVIDEO: 1188 1.110 macallan if (dp->rd_wsmode != WSDISPLAYIO_MODE_MAPPED) { 1189 1.110 macallan radeonfb_blank(dp, 1190 1.110 macallan (*(unsigned int *)d == WSDISPLAYIO_VIDEO_OFF)); 1191 1.110 macallan radeonfb_switch_backlight(dp, 1192 1.110 macallan (*(unsigned int *)d == WSDISPLAYIO_VIDEO_ON)); 1193 1.110 macallan } 1194 1.106 macallan pmf_event_inject(NULL, 1195 1.106 macallan (*(unsigned int *)d == WSDISPLAYIO_VIDEO_ON) ? 1196 1.106 macallan PMFE_DISPLAY_ON : PMFE_DISPLAY_OFF); 1197 1.1 gdamore return 0; 1198 1.1 gdamore 1199 1.1 gdamore case WSDISPLAYIO_GETCMAP: 1200 1.1 gdamore if (dp->rd_bpp == 8) 1201 1.82 macallan return radeonfb_getcmap(dp, 1202 1.1 gdamore (struct wsdisplay_cmap *)d); 1203 1.1 gdamore return EINVAL; 1204 1.11 ad 1205 1.1 gdamore case WSDISPLAYIO_PUTCMAP: 1206 1.1 gdamore if (dp->rd_bpp == 8) 1207 1.82 macallan return radeonfb_putcmap(dp, 1208 1.1 gdamore (struct wsdisplay_cmap *)d); 1209 1.1 gdamore return EINVAL; 1210 1.11 ad 1211 1.1 gdamore case WSDISPLAYIO_LINEBYTES: 1212 1.1 gdamore *(unsigned *)d = dp->rd_stride; 1213 1.1 gdamore return 0; 1214 1.1 gdamore 1215 1.1 gdamore case WSDISPLAYIO_SMODE: 1216 1.1 gdamore if (*(int *)d != dp->rd_wsmode) { 1217 1.1 gdamore dp->rd_wsmode = *(int *)d; 1218 1.82 macallan if ((dp->rd_wsmode == WSDISPLAYIO_MODE_EMUL) || 1219 1.82 macallan (dp->rd_wsmode == WSDISPLAYIO_MODE_DUMBFB)) 1220 1.82 macallan radeonfb_map(sc); 1221 1.82 macallan 1222 1.1 gdamore if ((dp->rd_wsmode == WSDISPLAYIO_MODE_EMUL) && 1223 1.1 gdamore (dp->rd_vd.active)) { 1224 1.17 macallan radeonfb_engine_init(dp); 1225 1.54 macallan glyphcache_wipe(&dp->rd_gc); 1226 1.70 macallan radeonfb_init_palette(dp); 1227 1.36 macallan radeonfb_modeswitch(dp); 1228 1.76 macallan radeonfb_rectfill(dp, 0, 0, dp->rd_virtx, 1229 1.76 macallan dp->rd_virty, dp->rd_bg); 1230 1.1 gdamore vcons_redraw_screen(dp->rd_vd.active); 1231 1.82 macallan } 1232 1.82 macallan if (dp->rd_wsmode == WSDISPLAYIO_MODE_MAPPED) 1233 1.56 macallan radeonfb_unmap(sc); 1234 1.1 gdamore } 1235 1.1 gdamore return 0; 1236 1.1 gdamore 1237 1.1 gdamore case WSDISPLAYIO_GCURMAX: 1238 1.1 gdamore ((struct wsdisplay_curpos *)d)->x = RADEON_CURSORMAXX; 1239 1.1 gdamore ((struct wsdisplay_curpos *)d)->y = RADEON_CURSORMAXY; 1240 1.1 gdamore return 0; 1241 1.1 gdamore 1242 1.1 gdamore case WSDISPLAYIO_SCURSOR: 1243 1.1 gdamore return radeonfb_set_cursor(dp, (struct wsdisplay_cursor *)d); 1244 1.1 gdamore 1245 1.1 gdamore case WSDISPLAYIO_GCURSOR: 1246 1.1 gdamore return EPASSTHROUGH; 1247 1.1 gdamore 1248 1.1 gdamore case WSDISPLAYIO_GCURPOS: 1249 1.1 gdamore ((struct wsdisplay_curpos *)d)->x = dp->rd_cursor.rc_pos.x; 1250 1.1 gdamore ((struct wsdisplay_curpos *)d)->y = dp->rd_cursor.rc_pos.y; 1251 1.1 gdamore return 0; 1252 1.1 gdamore 1253 1.1 gdamore case WSDISPLAYIO_SCURPOS: 1254 1.1 gdamore return radeonfb_set_curpos(dp, (struct wsdisplay_curpos *)d); 1255 1.1 gdamore 1256 1.1 gdamore case WSDISPLAYIO_SSPLASH: 1257 1.1 gdamore #if defined(SPLASHSCREEN) 1258 1.1 gdamore if (*(int *)d == 1) { 1259 1.1 gdamore SCREEN_DISABLE_DRAWING(&dp->rd_vscreen); 1260 1.1 gdamore splash_render(&dp->rd_splash, 1261 1.1 gdamore SPLASH_F_CENTER|SPLASH_F_FILL); 1262 1.1 gdamore } else 1263 1.1 gdamore SCREEN_ENABLE_DRAWING(&dp->rd_vscreen); 1264 1.1 gdamore return 0; 1265 1.1 gdamore #else 1266 1.1 gdamore return ENODEV; 1267 1.1 gdamore #endif 1268 1.9 macallan case WSDISPLAYIO_GETPARAM: 1269 1.9 macallan param = (struct wsdisplay_param *)d; 1270 1.59 macallan switch (param->param) { 1271 1.59 macallan case WSDISPLAYIO_PARAM_BRIGHTNESS: 1272 1.59 macallan param->min = 0; 1273 1.59 macallan param->max = 255; 1274 1.59 macallan param->curval = dp->rd_bl_level; 1275 1.59 macallan return 0; 1276 1.59 macallan case WSDISPLAYIO_PARAM_BACKLIGHT: 1277 1.9 macallan param->min = 0; 1278 1.9 macallan param->max = RADEONFB_BACKLIGHT_MAX; 1279 1.59 macallan param->curval = dp->rd_bl_on; 1280 1.9 macallan return 0; 1281 1.9 macallan } 1282 1.9 macallan return EPASSTHROUGH; 1283 1.9 macallan 1284 1.9 macallan case WSDISPLAYIO_SETPARAM: 1285 1.9 macallan param = (struct wsdisplay_param *)d; 1286 1.59 macallan switch (param->param) { 1287 1.59 macallan case WSDISPLAYIO_PARAM_BRIGHTNESS: 1288 1.59 macallan radeonfb_set_backlight(dp, param->curval); 1289 1.59 macallan return 0; 1290 1.59 macallan case WSDISPLAYIO_PARAM_BACKLIGHT: 1291 1.59 macallan radeonfb_switch_backlight(dp, param->curval); 1292 1.59 macallan return 0; 1293 1.9 macallan } 1294 1.9 macallan return EPASSTHROUGH; 1295 1.1 gdamore 1296 1.26 phx /* PCI config read/write passthrough. */ 1297 1.26 phx case PCI_IOC_CFGREAD: 1298 1.26 phx case PCI_IOC_CFGWRITE: 1299 1.40 cegger return pci_devioctl(sc->sc_pc, sc->sc_pt, cmd, d, flag, l); 1300 1.26 phx 1301 1.41 cegger case WSDISPLAYIO_GET_BUSID: 1302 1.47 macallan return wsdisplayio_busid_pci(sc->sc_dev, sc->sc_pc, 1303 1.41 cegger sc->sc_pt, d); 1304 1.41 cegger 1305 1.48 macallan case WSDISPLAYIO_GET_EDID: { 1306 1.48 macallan struct wsdisplayio_edid_info *ei = d; 1307 1.48 macallan return wsdisplayio_get_edid(sc->sc_dev, ei); 1308 1.48 macallan } 1309 1.48 macallan 1310 1.79 macallan case WSDISPLAYIO_GET_FBINFO: { 1311 1.79 macallan struct wsdisplayio_fbinfo *fbi = d; 1312 1.79 macallan return wsdisplayio_get_fbinfo(&ms->scr_ri, fbi); 1313 1.79 macallan } 1314 1.79 macallan 1315 1.1 gdamore default: 1316 1.1 gdamore return EPASSTHROUGH; 1317 1.1 gdamore } 1318 1.1 gdamore } 1319 1.1 gdamore 1320 1.1 gdamore paddr_t 1321 1.1 gdamore radeonfb_mmap(void *v, void *vs, off_t offset, int prot) 1322 1.1 gdamore { 1323 1.1 gdamore struct vcons_data *vd; 1324 1.1 gdamore struct radeonfb_display *dp; 1325 1.1 gdamore struct radeonfb_softc *sc; 1326 1.1 gdamore paddr_t pa; 1327 1.1 gdamore 1328 1.1 gdamore vd = (struct vcons_data *)v; 1329 1.1 gdamore dp = (struct radeonfb_display *)vd->cookie; 1330 1.1 gdamore sc = dp->rd_softc; 1331 1.1 gdamore 1332 1.1 gdamore if ((offset >= 0) && (offset < (dp->rd_virty * dp->rd_stride))) { 1333 1.1 gdamore pa = bus_space_mmap(sc->sc_memt, 1334 1.1 gdamore sc->sc_memaddr + dp->rd_offset + offset, 0, 1335 1.1 gdamore prot, BUS_SPACE_MAP_LINEAR); 1336 1.1 gdamore return pa; 1337 1.1 gdamore } 1338 1.1 gdamore 1339 1.5 macallan /* 1340 1.5 macallan * restrict all other mappings to processes with superuser privileges 1341 1.5 macallan * or the kernel itself 1342 1.5 macallan */ 1343 1.58 elad if (kauth_authorize_machdep(kauth_cred_get(), KAUTH_MACHDEP_UNMANAGEDMEM, 1344 1.58 elad NULL, NULL, NULL, NULL) != 0) { 1345 1.47 macallan aprint_error_dev(sc->sc_dev, "mmap() rejected.\n"); 1346 1.32 elad return -1; 1347 1.5 macallan } 1348 1.5 macallan 1349 1.11 ad if ((offset >= sc->sc_regaddr) && 1350 1.3 macallan (offset < sc->sc_regaddr + sc->sc_regsz)) { 1351 1.11 ad return bus_space_mmap(sc->sc_regt, offset, 0, prot, 1352 1.3 macallan BUS_SPACE_MAP_LINEAR); 1353 1.3 macallan } 1354 1.3 macallan 1355 1.11 ad if ((offset >= sc->sc_memaddr) && 1356 1.3 macallan (offset < sc->sc_memaddr + sc->sc_memsz)) { 1357 1.11 ad return bus_space_mmap(sc->sc_memt, offset, 0, prot, 1358 1.3 macallan BUS_SPACE_MAP_LINEAR); 1359 1.3 macallan } 1360 1.5 macallan 1361 1.34 macallan if ((offset >= sc->sc_romaddr) && 1362 1.34 macallan (offset < sc->sc_romaddr + sc->sc_romsz)) { 1363 1.34 macallan return bus_space_mmap(sc->sc_memt, offset, 0, prot, 1364 1.34 macallan BUS_SPACE_MAP_LINEAR); 1365 1.34 macallan } 1366 1.34 macallan 1367 1.25 macallan #ifdef PCI_MAGIC_IO_RANGE 1368 1.5 macallan /* allow mapping of IO space */ 1369 1.25 macallan if ((offset >= PCI_MAGIC_IO_RANGE) && 1370 1.25 macallan (offset < PCI_MAGIC_IO_RANGE + 0x10000)) { 1371 1.25 macallan pa = bus_space_mmap(sc->sc_iot, offset - PCI_MAGIC_IO_RANGE, 1372 1.25 macallan 0, prot, 0); 1373 1.5 macallan return pa; 1374 1.11 ad } 1375 1.49 macallan #endif /* PCI_MAGIC_IO_RANGE */ 1376 1.5 macallan 1377 1.1 gdamore return -1; 1378 1.1 gdamore } 1379 1.1 gdamore 1380 1.2 macallan static void 1381 1.44 dyoung radeonfb_loadbios(struct radeonfb_softc *sc, const struct pci_attach_args *pa) 1382 1.1 gdamore { 1383 1.1 gdamore bus_space_tag_t romt; 1384 1.1 gdamore bus_space_handle_t romh, biosh; 1385 1.1 gdamore bus_size_t romsz; 1386 1.1 gdamore bus_addr_t ptr; 1387 1.101 macallan uint32_t busctl, crtcg, crtc2g = 0, viphctl, seprom, extc; 1388 1.101 macallan int bios_voodoo = 0; 1389 1.1 gdamore 1390 1.1 gdamore if (pci_mapreg_map(pa, PCI_MAPREG_ROM, PCI_MAPREG_TYPE_ROM, 1391 1.1 gdamore BUS_SPACE_MAP_PREFETCHABLE, &romt, &romh, NULL, &romsz) != 0) { 1392 1.1 gdamore aprint_verbose("%s: unable to map BIOS!\n", XNAME(sc)); 1393 1.1 gdamore return; 1394 1.1 gdamore } 1395 1.1 gdamore 1396 1.85 riastrad pci_find_rom(pa, romt, romh, romsz, PCI_ROM_CODE_TYPE_X86, &biosh, 1397 1.1 gdamore &sc->sc_biossz); 1398 1.101 macallan if (sc->sc_biossz != 0) goto foundit; 1399 1.101 macallan 1400 1.101 macallan aprint_verbose("trying to read disabled BIOS...\n"); 1401 1.101 macallan 1402 1.101 macallan bios_voodoo = 1; 1403 1.101 macallan seprom = radeonfb_get32(sc, RADEON_SEPROM_CNTL1); 1404 1.101 macallan radeonfb_put32(sc, RADEON_SEPROM_CNTL1, 1405 1.101 macallan (seprom & ~RADEON_SCK_PRESCALE_MASK) | 1406 1.101 macallan (0xc << RADEON_SCK_PRESCALE_SHIFT)); 1407 1.101 macallan viphctl = radeonfb_get32(sc, RADEON_VIPH_CONTROL); 1408 1.101 macallan radeonfb_put32(sc, RADEON_VIPH_CONTROL, viphctl & ~RADEON_VIPH_EN); 1409 1.101 macallan busctl = radeonfb_get32(sc, RADEON_BUS_CNTL); 1410 1.101 macallan radeonfb_put32(sc, RADEON_BUS_CNTL, busctl & ~RADEON_BUS_BIOS_DIS_ROM); 1411 1.101 macallan crtcg = radeonfb_get32(sc, RADEON_CRTC_GEN_CNTL); 1412 1.101 macallan radeonfb_put32(sc, RADEON_CRTC_GEN_CNTL, ((crtcg & ~RADEON_CRTC_EN) | 1413 1.101 macallan (RADEON_CRTC_DISP_REQ_EN_B | 1414 1.101 macallan RADEON_CRTC_EXT_DISP_EN))); 1415 1.101 macallan if (HAS_CRTC2(sc)) { 1416 1.101 macallan crtc2g = radeonfb_get32(sc, RADEON_CRTC2_GEN_CNTL); 1417 1.101 macallan radeonfb_put32(sc, RADEON_CRTC2_GEN_CNTL, 1418 1.101 macallan (crtc2g & ~RADEON_CRTC2_EN) | 1419 1.101 macallan RADEON_CRTC2_DISP_REQ_EN_B); 1420 1.101 macallan } 1421 1.101 macallan extc = radeonfb_get32(sc, RADEON_CRTC_EXT_CNTL); 1422 1.101 macallan radeonfb_put32(sc, RADEON_CRTC_EXT_CNTL, (extc & ~RADEON_CRTC_CRT_ON) | 1423 1.101 macallan (RADEON_CRTC_SYNC_TRISTAT | 1424 1.101 macallan RADEON_CRTC_DISPLAY_DIS)); 1425 1.101 macallan pci_find_rom(pa, romt, romh, romsz, PCI_ROM_CODE_TYPE_X86, &biosh, 1426 1.101 macallan &sc->sc_biossz); 1427 1.1 gdamore 1428 1.101 macallan foundit: 1429 1.102 macallan if (sc->sc_biossz > 0) { 1430 1.102 macallan sc->sc_bios = malloc(sc->sc_biossz, M_DEVBUF, M_WAITOK); 1431 1.102 macallan bus_space_read_region_1(romt, biosh, 0, sc->sc_bios, 1432 1.102 macallan sc->sc_biossz); 1433 1.102 macallan } 1434 1.1 gdamore 1435 1.101 macallan if (bios_voodoo != 0) { 1436 1.101 macallan radeonfb_put32(sc, RADEON_CRTC_EXT_CNTL, extc); 1437 1.101 macallan if (HAS_CRTC2(sc)) { 1438 1.101 macallan radeonfb_put32(sc, RADEON_CRTC2_GEN_CNTL, crtc2g); 1439 1.101 macallan } 1440 1.101 macallan radeonfb_put32(sc, RADEON_CRTC_GEN_CNTL, crtcg); 1441 1.101 macallan radeonfb_put32(sc, RADEON_BUS_CNTL, busctl); 1442 1.101 macallan radeonfb_put32(sc, RADEON_VIPH_CONTROL, viphctl); 1443 1.101 macallan radeonfb_put32(sc, RADEON_SEPROM_CNTL1, seprom); 1444 1.101 macallan } 1445 1.101 macallan 1446 1.1 gdamore /* unmap the PCI expansion rom */ 1447 1.1 gdamore bus_space_unmap(romt, romh, romsz); 1448 1.101 macallan 1449 1.1 gdamore /* turn off rom decoder now */ 1450 1.1 gdamore pci_conf_write(pa->pa_pc, pa->pa_tag, PCI_MAPREG_ROM, 1451 1.1 gdamore pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_MAPREG_ROM) & 1452 1.1 gdamore ~PCI_MAPREG_ROM_ENABLE); 1453 1.1 gdamore 1454 1.104 macallan if (sc->sc_biossz > 0) { 1455 1.104 macallan ptr = GETBIOS16(sc, 0x48); 1456 1.104 macallan if ((GETBIOS32(sc, ptr + 4) == 0x41544f4d /* "ATOM" */) || 1457 1.104 macallan (GETBIOS32(sc, ptr + 4) == 0x4d4f5441 /* "MOTA" */)) { 1458 1.104 macallan sc->sc_flags |= RFB_ATOM; 1459 1.104 macallan } 1460 1.101 macallan 1461 1.101 macallan aprint_verbose("%s: Found %d KB %s BIOS\n", XNAME(sc), 1462 1.101 macallan (unsigned)sc->sc_biossz >> 10, 1463 1.101 macallan IS_ATOM(sc) ? "ATOM" : "Legacy"); 1464 1.101 macallan } 1465 1.1 gdamore } 1466 1.1 gdamore 1467 1.1 gdamore 1468 1.1 gdamore uint32_t 1469 1.1 gdamore radeonfb_get32(struct radeonfb_softc *sc, uint32_t reg) 1470 1.1 gdamore { 1471 1.1 gdamore 1472 1.1 gdamore return bus_space_read_4(sc->sc_regt, sc->sc_regh, reg); 1473 1.1 gdamore } 1474 1.1 gdamore 1475 1.1 gdamore void 1476 1.1 gdamore radeonfb_put32(struct radeonfb_softc *sc, uint32_t reg, uint32_t val) 1477 1.1 gdamore { 1478 1.1 gdamore 1479 1.1 gdamore bus_space_write_4(sc->sc_regt, sc->sc_regh, reg, val); 1480 1.1 gdamore } 1481 1.1 gdamore 1482 1.1 gdamore void 1483 1.55 macallan radeonfb_put32s(struct radeonfb_softc *sc, uint32_t reg, uint32_t val) 1484 1.55 macallan { 1485 1.55 macallan 1486 1.55 macallan bus_space_write_stream_4(sc->sc_regt, sc->sc_regh, reg, val); 1487 1.55 macallan } 1488 1.55 macallan 1489 1.55 macallan void 1490 1.1 gdamore radeonfb_mask32(struct radeonfb_softc *sc, uint32_t reg, 1491 1.1 gdamore uint32_t andmask, uint32_t ormask) 1492 1.1 gdamore { 1493 1.1 gdamore int s; 1494 1.1 gdamore uint32_t val; 1495 1.1 gdamore 1496 1.1 gdamore s = splhigh(); 1497 1.1 gdamore val = radeonfb_get32(sc, reg); 1498 1.1 gdamore val = (val & andmask) | ormask; 1499 1.1 gdamore radeonfb_put32(sc, reg, val); 1500 1.1 gdamore splx(s); 1501 1.1 gdamore } 1502 1.1 gdamore 1503 1.1 gdamore uint32_t 1504 1.1 gdamore radeonfb_getindex(struct radeonfb_softc *sc, uint32_t idx) 1505 1.1 gdamore { 1506 1.1 gdamore int s; 1507 1.1 gdamore uint32_t val; 1508 1.1 gdamore 1509 1.1 gdamore s = splhigh(); 1510 1.1 gdamore radeonfb_put32(sc, RADEON_MM_INDEX, idx); 1511 1.1 gdamore val = radeonfb_get32(sc, RADEON_MM_DATA); 1512 1.1 gdamore splx(s); 1513 1.1 gdamore 1514 1.1 gdamore return (val); 1515 1.1 gdamore } 1516 1.1 gdamore 1517 1.1 gdamore void 1518 1.1 gdamore radeonfb_putindex(struct radeonfb_softc *sc, uint32_t idx, uint32_t val) 1519 1.1 gdamore { 1520 1.1 gdamore int s; 1521 1.1 gdamore 1522 1.1 gdamore s = splhigh(); 1523 1.1 gdamore radeonfb_put32(sc, RADEON_MM_INDEX, idx); 1524 1.1 gdamore radeonfb_put32(sc, RADEON_MM_DATA, val); 1525 1.1 gdamore splx(s); 1526 1.1 gdamore } 1527 1.1 gdamore 1528 1.1 gdamore void 1529 1.1 gdamore radeonfb_maskindex(struct radeonfb_softc *sc, uint32_t idx, 1530 1.1 gdamore uint32_t andmask, uint32_t ormask) 1531 1.1 gdamore { 1532 1.1 gdamore int s; 1533 1.1 gdamore uint32_t val; 1534 1.1 gdamore 1535 1.1 gdamore s = splhigh(); 1536 1.1 gdamore radeonfb_put32(sc, RADEON_MM_INDEX, idx); 1537 1.1 gdamore val = radeonfb_get32(sc, RADEON_MM_DATA); 1538 1.1 gdamore val = (val & andmask) | ormask; 1539 1.1 gdamore radeonfb_put32(sc, RADEON_MM_DATA, val); 1540 1.1 gdamore splx(s); 1541 1.1 gdamore } 1542 1.1 gdamore 1543 1.1 gdamore uint32_t 1544 1.1 gdamore radeonfb_getpll(struct radeonfb_softc *sc, uint32_t idx) 1545 1.1 gdamore { 1546 1.1 gdamore int s; 1547 1.1 gdamore uint32_t val; 1548 1.1 gdamore 1549 1.1 gdamore s = splhigh(); 1550 1.69 macallan radeonfb_put32(sc, RADEON_CLOCK_CNTL_INDEX, (idx & 0x3f)); 1551 1.1 gdamore val = radeonfb_get32(sc, RADEON_CLOCK_CNTL_DATA); 1552 1.1 gdamore if (HAS_R300CG(sc)) 1553 1.1 gdamore radeonfb_r300cg_workaround(sc); 1554 1.1 gdamore splx(s); 1555 1.1 gdamore 1556 1.1 gdamore return (val); 1557 1.1 gdamore } 1558 1.1 gdamore 1559 1.1 gdamore void 1560 1.1 gdamore radeonfb_putpll(struct radeonfb_softc *sc, uint32_t idx, uint32_t val) 1561 1.1 gdamore { 1562 1.1 gdamore int s; 1563 1.1 gdamore 1564 1.1 gdamore s = splhigh(); 1565 1.1 gdamore radeonfb_put32(sc, RADEON_CLOCK_CNTL_INDEX, (idx & 0x3f) | 1566 1.1 gdamore RADEON_PLL_WR_EN); 1567 1.1 gdamore radeonfb_put32(sc, RADEON_CLOCK_CNTL_DATA, val); 1568 1.1 gdamore radeonfb_put32(sc, RADEON_CLOCK_CNTL_INDEX, 0); 1569 1.1 gdamore splx(s); 1570 1.1 gdamore } 1571 1.1 gdamore 1572 1.1 gdamore void 1573 1.1 gdamore radeonfb_maskpll(struct radeonfb_softc *sc, uint32_t idx, 1574 1.1 gdamore uint32_t andmask, uint32_t ormask) 1575 1.1 gdamore { 1576 1.1 gdamore int s; 1577 1.1 gdamore uint32_t val; 1578 1.1 gdamore 1579 1.1 gdamore s = splhigh(); 1580 1.1 gdamore radeonfb_put32(sc, RADEON_CLOCK_CNTL_INDEX, (idx & 0x3f) | 1581 1.1 gdamore RADEON_PLL_WR_EN); 1582 1.1 gdamore val = radeonfb_get32(sc, RADEON_CLOCK_CNTL_DATA); 1583 1.1 gdamore val = (val & andmask) | ormask; 1584 1.1 gdamore radeonfb_put32(sc, RADEON_CLOCK_CNTL_DATA, val); 1585 1.1 gdamore radeonfb_put32(sc, RADEON_CLOCK_CNTL_INDEX, 0); 1586 1.1 gdamore splx(s); 1587 1.1 gdamore } 1588 1.1 gdamore 1589 1.1 gdamore int 1590 1.1 gdamore radeonfb_scratch_test(struct radeonfb_softc *sc, int reg, uint32_t v) 1591 1.1 gdamore { 1592 1.1 gdamore uint32_t saved; 1593 1.1 gdamore 1594 1.1 gdamore saved = GET32(sc, reg); 1595 1.1 gdamore PUT32(sc, reg, v); 1596 1.1 gdamore if (GET32(sc, reg) != v) { 1597 1.1 gdamore return -1; 1598 1.1 gdamore } 1599 1.1 gdamore PUT32(sc, reg, saved); 1600 1.1 gdamore return 0; 1601 1.1 gdamore } 1602 1.1 gdamore 1603 1.1 gdamore uintmax_t 1604 1.1 gdamore radeonfb_getprop_num(struct radeonfb_softc *sc, const char *name, 1605 1.1 gdamore uintmax_t defval) 1606 1.1 gdamore { 1607 1.1 gdamore prop_number_t pn; 1608 1.47 macallan pn = prop_dictionary_get(device_properties(sc->sc_dev), name); 1609 1.1 gdamore if (pn == NULL) { 1610 1.1 gdamore return defval; 1611 1.1 gdamore } 1612 1.1 gdamore KASSERT(prop_object_type(pn) == PROP_TYPE_NUMBER); 1613 1.109 martin return prop_number_unsigned_value(pn); 1614 1.1 gdamore } 1615 1.1 gdamore 1616 1.1 gdamore int 1617 1.1 gdamore radeonfb_getclocks(struct radeonfb_softc *sc) 1618 1.1 gdamore { 1619 1.1 gdamore bus_addr_t ptr; 1620 1.1 gdamore int refclk = 0; 1621 1.1 gdamore int refdiv = 0; 1622 1.1 gdamore int minpll = 0; 1623 1.1 gdamore int maxpll = 0; 1624 1.1 gdamore 1625 1.1 gdamore /* load initial property values if port/board provides them */ 1626 1.1 gdamore refclk = radeonfb_getprop_num(sc, "refclk", 0) & 0xffff; 1627 1.1 gdamore refdiv = radeonfb_getprop_num(sc, "refdiv", 0) & 0xffff; 1628 1.1 gdamore minpll = radeonfb_getprop_num(sc, "minpll", 0) & 0xffffffffU; 1629 1.1 gdamore maxpll = radeonfb_getprop_num(sc, "maxpll", 0) & 0xffffffffU; 1630 1.1 gdamore 1631 1.69 macallan PRINTPLL(RADEON_PPLL_REF_DIV); 1632 1.69 macallan PRINTPLL(RADEON_PPLL_DIV_0); 1633 1.69 macallan PRINTPLL(RADEON_PPLL_DIV_1); 1634 1.69 macallan PRINTPLL(RADEON_PPLL_DIV_2); 1635 1.69 macallan PRINTPLL(RADEON_PPLL_DIV_3); 1636 1.69 macallan PRINTREG(RADEON_CLOCK_CNTL_INDEX); 1637 1.69 macallan PRINTPLL(RADEON_P2PLL_REF_DIV); 1638 1.69 macallan PRINTPLL(RADEON_P2PLL_DIV_0); 1639 1.69 macallan 1640 1.1 gdamore if (refclk && refdiv && minpll && maxpll) 1641 1.1 gdamore goto dontprobe; 1642 1.1 gdamore 1643 1.1 gdamore if (!sc->sc_biossz) { 1644 1.1 gdamore /* no BIOS */ 1645 1.1 gdamore aprint_verbose("%s: No video BIOS, using default clocks\n", 1646 1.1 gdamore XNAME(sc)); 1647 1.1 gdamore if (IS_IGP(sc)) 1648 1.1 gdamore refclk = refclk ? refclk : 1432; 1649 1.1 gdamore else 1650 1.1 gdamore refclk = refclk ? refclk : 2700; 1651 1.20 macallan refdiv = refdiv ? refdiv : 12; 1652 1.1 gdamore minpll = minpll ? minpll : 12500; 1653 1.69 macallan /* XXX 1654 1.69 macallan * Need to check if the firmware or something programmed a 1655 1.69 macallan * higher value than this, and if so, bump it. 1656 1.69 macallan * The RV280 in my iBook is unhappy if the PLL input is less 1657 1.69 macallan * than 360MHz 1658 1.69 macallan */ 1659 1.69 macallan maxpll = maxpll ? maxpll : 40000/*35000*/; 1660 1.1 gdamore } else if (IS_ATOM(sc)) { 1661 1.1 gdamore /* ATOM BIOS */ 1662 1.1 gdamore ptr = GETBIOS16(sc, 0x48); 1663 1.1 gdamore ptr = GETBIOS16(sc, ptr + 32); /* aka MasterDataStart */ 1664 1.1 gdamore ptr = GETBIOS16(sc, ptr + 12); /* pll info block */ 1665 1.1 gdamore refclk = refclk ? refclk : GETBIOS16(sc, ptr + 82); 1666 1.1 gdamore minpll = minpll ? minpll : GETBIOS16(sc, ptr + 78); 1667 1.1 gdamore maxpll = maxpll ? maxpll : GETBIOS16(sc, ptr + 32); 1668 1.1 gdamore /* 1669 1.1 gdamore * ATOM BIOS doesn't supply a reference divider, so we 1670 1.1 gdamore * have to probe for it. 1671 1.1 gdamore */ 1672 1.1 gdamore if (refdiv < 2) 1673 1.1 gdamore refdiv = GETPLL(sc, RADEON_PPLL_REF_DIV) & 1674 1.1 gdamore RADEON_PPLL_REF_DIV_MASK; 1675 1.1 gdamore /* 1676 1.1 gdamore * if probe is zero, just assume one that should work 1677 1.1 gdamore * for most parts 1678 1.1 gdamore */ 1679 1.1 gdamore if (refdiv < 2) 1680 1.1 gdamore refdiv = 12; 1681 1.11 ad 1682 1.1 gdamore } else { 1683 1.69 macallan uint32_t tmp = GETPLL(sc, RADEON_PPLL_REF_DIV); 1684 1.1 gdamore /* Legacy BIOS */ 1685 1.1 gdamore ptr = GETBIOS16(sc, 0x48); 1686 1.1 gdamore ptr = GETBIOS16(sc, ptr + 0x30); 1687 1.69 macallan if (IS_R300(sc)) { 1688 1.69 macallan refdiv = refdiv ? refdiv : 1689 1.69 macallan (tmp & R300_PPLL_REF_DIV_ACC_MASK) >> 1690 1.69 macallan R300_PPLL_REF_DIV_ACC_SHIFT; 1691 1.69 macallan } else { 1692 1.69 macallan refdiv = refdiv ? refdiv : 1693 1.69 macallan tmp & RADEON_PPLL_REF_DIV_MASK; 1694 1.69 macallan } 1695 1.1 gdamore refclk = refclk ? refclk : GETBIOS16(sc, ptr + 0x0E); 1696 1.1 gdamore refdiv = refdiv ? refdiv : GETBIOS16(sc, ptr + 0x10); 1697 1.1 gdamore minpll = minpll ? minpll : GETBIOS32(sc, ptr + 0x12); 1698 1.1 gdamore maxpll = maxpll ? maxpll : GETBIOS32(sc, ptr + 0x16); 1699 1.1 gdamore } 1700 1.1 gdamore 1701 1.1 gdamore 1702 1.1 gdamore dontprobe: 1703 1.1 gdamore sc->sc_refclk = refclk * 10; 1704 1.1 gdamore sc->sc_refdiv = refdiv; 1705 1.1 gdamore sc->sc_minpll = minpll * 10; 1706 1.1 gdamore sc->sc_maxpll = maxpll * 10; 1707 1.1 gdamore return 0; 1708 1.1 gdamore } 1709 1.1 gdamore 1710 1.1 gdamore int 1711 1.1 gdamore radeonfb_calc_dividers(struct radeonfb_softc *sc, uint32_t dotclock, 1712 1.92 macallan uint32_t *postdivbit, uint32_t *feedbackdiv, int flags) 1713 1.1 gdamore { 1714 1.1 gdamore int i; 1715 1.1 gdamore uint32_t outfreq; 1716 1.1 gdamore int div; 1717 1.1 gdamore 1718 1.1 gdamore DPRINTF(("dot clock: %u\n", dotclock)); 1719 1.1 gdamore for (i = 0; (div = radeonfb_dividers[i].divider) != 0; i++) { 1720 1.97 macallan 1721 1.97 macallan if ((flags & NO_ODD_FBDIV) && ((div & 1) != 0)) 1722 1.97 macallan continue; 1723 1.97 macallan 1724 1.96 macallan /* 1725 1.96 macallan * XXX 1726 1.96 macallan * the rv350 in my last generation 14" iBook G4 produces 1727 1.96 macallan * garbage with dividers > 4. No idea if this is a hardware 1728 1.96 macallan * limitation or an error in the divider table. 1729 1.96 macallan */ 1730 1.97 macallan if ((sc->sc_family == RADEON_RV350) && (div > 4)) 1731 1.97 macallan continue; 1732 1.97 macallan 1733 1.1 gdamore outfreq = div * dotclock; 1734 1.1 gdamore if ((outfreq >= sc->sc_minpll) && 1735 1.1 gdamore (outfreq <= sc->sc_maxpll)) { 1736 1.1 gdamore DPRINTF(("outfreq: %u\n", outfreq)); 1737 1.1 gdamore *postdivbit = 1738 1.1 gdamore ((uint32_t)radeonfb_dividers[i].mask << 16); 1739 1.1 gdamore DPRINTF(("post divider: %d (mask %x)\n", div, 1740 1.1 gdamore *postdivbit)); 1741 1.1 gdamore break; 1742 1.1 gdamore } 1743 1.1 gdamore } 1744 1.1 gdamore 1745 1.1 gdamore if (div == 0) 1746 1.1 gdamore return 1; 1747 1.1 gdamore 1748 1.1 gdamore *feedbackdiv = DIVIDE(sc->sc_refdiv * outfreq, sc->sc_refclk); 1749 1.1 gdamore DPRINTF(("feedback divider: %d\n", *feedbackdiv)); 1750 1.1 gdamore return 0; 1751 1.1 gdamore } 1752 1.1 gdamore 1753 1.1 gdamore #if 0 1754 1.36 macallan #ifdef RADEONFB_DEBUG 1755 1.1 gdamore static void 1756 1.1 gdamore dump_buffer(const char *pfx, void *buffer, unsigned int size) 1757 1.1 gdamore { 1758 1.1 gdamore char asc[17]; 1759 1.1 gdamore unsigned ptr = (unsigned)buffer; 1760 1.1 gdamore char *start = (char *)(ptr & ~0xf); 1761 1.1 gdamore char *end = (char *)(ptr + size); 1762 1.1 gdamore 1763 1.1 gdamore end = (char *)(((unsigned)end + 0xf) & ~0xf); 1764 1.1 gdamore 1765 1.1 gdamore if (pfx == NULL) { 1766 1.1 gdamore pfx = ""; 1767 1.1 gdamore } 1768 1.1 gdamore 1769 1.1 gdamore while (start < end) { 1770 1.1 gdamore unsigned offset = (unsigned)start & 0xf; 1771 1.1 gdamore if (offset == 0) { 1772 1.1 gdamore printf("%s%x: ", pfx, (unsigned)start); 1773 1.1 gdamore } 1774 1.1 gdamore if (((unsigned)start < ptr) || 1775 1.1 gdamore ((unsigned)start >= (ptr + size))) { 1776 1.1 gdamore printf(" "); 1777 1.1 gdamore asc[offset] = ' '; 1778 1.1 gdamore } else { 1779 1.1 gdamore printf("%02x", *(unsigned char *)start); 1780 1.1 gdamore if ((*start >= ' ') && (*start <= '~')) { 1781 1.1 gdamore asc[offset] = *start; 1782 1.1 gdamore } else { 1783 1.1 gdamore asc[offset] = '.'; 1784 1.1 gdamore } 1785 1.1 gdamore } 1786 1.1 gdamore asc[offset + 1] = 0; 1787 1.1 gdamore if (offset % 2) { 1788 1.1 gdamore printf(" "); 1789 1.1 gdamore } 1790 1.1 gdamore if (offset == 15) { 1791 1.1 gdamore printf(" %s\n", asc); 1792 1.1 gdamore } 1793 1.1 gdamore start++; 1794 1.1 gdamore } 1795 1.1 gdamore } 1796 1.1 gdamore #endif 1797 1.1 gdamore #endif 1798 1.1 gdamore 1799 1.1 gdamore int 1800 1.1 gdamore radeonfb_getconnectors(struct radeonfb_softc *sc) 1801 1.1 gdamore { 1802 1.1 gdamore int i; 1803 1.1 gdamore int found = 0; 1804 1.1 gdamore 1805 1.1 gdamore for (i = 0; i < 2; i++) { 1806 1.1 gdamore sc->sc_ports[i].rp_mon_type = RADEON_MT_UNKNOWN; 1807 1.1 gdamore sc->sc_ports[i].rp_ddc_type = RADEON_DDC_NONE; 1808 1.1 gdamore sc->sc_ports[i].rp_dac_type = RADEON_DAC_UNKNOWN; 1809 1.1 gdamore sc->sc_ports[i].rp_conn_type = RADEON_CONN_NONE; 1810 1.1 gdamore sc->sc_ports[i].rp_tmds_type = RADEON_TMDS_UNKNOWN; 1811 1.1 gdamore } 1812 1.1 gdamore 1813 1.1 gdamore /* 1814 1.1 gdamore * This logic is borrowed from Xorg's radeon driver. 1815 1.1 gdamore */ 1816 1.1 gdamore if (!sc->sc_biossz) 1817 1.1 gdamore goto nobios; 1818 1.1 gdamore 1819 1.1 gdamore if (IS_ATOM(sc)) { 1820 1.1 gdamore /* not done yet */ 1821 1.1 gdamore } else { 1822 1.1 gdamore uint16_t ptr; 1823 1.1 gdamore int port = 0; 1824 1.1 gdamore 1825 1.1 gdamore ptr = GETBIOS16(sc, 0x48); 1826 1.1 gdamore ptr = GETBIOS16(sc, ptr + 0x50); 1827 1.1 gdamore for (i = 1; i < 4; i++) { 1828 1.1 gdamore uint16_t entry; 1829 1.1 gdamore uint8_t conn, ddc, dac, tmds; 1830 1.1 gdamore 1831 1.1 gdamore /* 1832 1.1 gdamore * Parse the connector table. From reading the code, 1833 1.1 gdamore * it appears to made up of 16-bit entries for each 1834 1.1 gdamore * connector. The 16-bits are defined as: 1835 1.1 gdamore * 1836 1.1 gdamore * bits 12-15 - connector type (0 == end of table) 1837 1.1 gdamore * bits 8-11 - DDC type 1838 1.1 gdamore * bits 5-7 - ??? 1839 1.1 gdamore * bit 4 - TMDS type (1 = EXT, 0 = INT) 1840 1.1 gdamore * bits 1-3 - ??? 1841 1.1 gdamore * bit 0 - DAC, 1 = TVDAC, 0 = primary 1842 1.1 gdamore */ 1843 1.1 gdamore if (!GETBIOS8(sc, ptr + i * 2) && i > 1) 1844 1.1 gdamore break; 1845 1.1 gdamore entry = GETBIOS16(sc, ptr + i * 2); 1846 1.1 gdamore 1847 1.1 gdamore conn = (entry >> 12) & 0xf; 1848 1.1 gdamore ddc = (entry >> 8) & 0xf; 1849 1.1 gdamore dac = (entry & 0x1) ? RADEON_DAC_TVDAC : 1850 1.1 gdamore RADEON_DAC_PRIMARY; 1851 1.1 gdamore tmds = ((entry >> 4) & 0x1) ? RADEON_TMDS_EXT : 1852 1.1 gdamore RADEON_TMDS_INT; 1853 1.1 gdamore 1854 1.1 gdamore if (conn == RADEON_CONN_NONE) 1855 1.1 gdamore continue; /* no connector */ 1856 1.1 gdamore 1857 1.91 macallan /* 1858 1.91 macallan * XXX 1859 1.91 macallan * both Mac Mini variants have both outputs wired to 1860 1.91 macallan * the same connector and share the DDC lines 1861 1.91 macallan */ 1862 1.1 gdamore if ((found > 0) && 1863 1.1 gdamore (sc->sc_ports[port].rp_ddc_type == ddc)) { 1864 1.1 gdamore /* duplicate entry for same connector */ 1865 1.1 gdamore continue; 1866 1.1 gdamore } 1867 1.1 gdamore 1868 1.1 gdamore /* internal DDC_DVI port gets priority */ 1869 1.1 gdamore if ((ddc == RADEON_DDC_DVI) || (port == 1)) 1870 1.1 gdamore port = 0; 1871 1.1 gdamore else 1872 1.1 gdamore port = 1; 1873 1.1 gdamore 1874 1.1 gdamore sc->sc_ports[port].rp_ddc_type = 1875 1.1 gdamore ddc > RADEON_DDC_CRT2 ? RADEON_DDC_NONE : ddc; 1876 1.1 gdamore sc->sc_ports[port].rp_dac_type = dac; 1877 1.1 gdamore sc->sc_ports[port].rp_conn_type = 1878 1.100 riastrad uimin(conn, RADEON_CONN_UNSUPPORTED) ; 1879 1.1 gdamore 1880 1.1 gdamore sc->sc_ports[port].rp_tmds_type = tmds; 1881 1.1 gdamore 1882 1.1 gdamore if ((conn != RADEON_CONN_DVI_I) && 1883 1.1 gdamore (conn != RADEON_CONN_DVI_D) && 1884 1.1 gdamore (tmds == RADEON_TMDS_INT)) 1885 1.1 gdamore sc->sc_ports[port].rp_tmds_type = 1886 1.1 gdamore RADEON_TMDS_UNKNOWN; 1887 1.69 macallan sc->sc_ports[port].rp_number = i - 1; 1888 1.1 gdamore 1889 1.1 gdamore found += (port + 1); 1890 1.1 gdamore } 1891 1.1 gdamore } 1892 1.1 gdamore 1893 1.1 gdamore nobios: 1894 1.1 gdamore if (!found) { 1895 1.90 macallan bool dvi_ext = FALSE, dvi_int = FALSE; 1896 1.1 gdamore DPRINTF(("No connector info in BIOS!\n")); 1897 1.90 macallan prop_dictionary_get_bool(device_properties(sc->sc_dev), 1898 1.90 macallan "dvi-internal", &dvi_int); 1899 1.90 macallan prop_dictionary_get_bool(device_properties(sc->sc_dev), 1900 1.90 macallan "dvi-external", &dvi_ext); 1901 1.90 macallan if (dvi_ext) { 1902 1.90 macallan sc->sc_ports[0].rp_mon_type = RADEON_MT_UNKNOWN; 1903 1.91 macallan sc->sc_ports[0].rp_ddc_type = RADEON_DDC_CRT2; 1904 1.91 macallan sc->sc_ports[0].rp_dac_type = RADEON_DAC_PRIMARY; 1905 1.90 macallan sc->sc_ports[0].rp_conn_type = RADEON_CONN_DVI_I; 1906 1.91 macallan sc->sc_ports[0].rp_tmds_type = RADEON_TMDS_EXT; /* output to fp2 */ 1907 1.91 macallan sc->sc_ports[0].rp_number = 0; 1908 1.91 macallan sc->sc_ports[1].rp_mon_type = RADEON_MT_UNKNOWN; 1909 1.91 macallan sc->sc_ports[1].rp_ddc_type = RADEON_DDC_NONE; 1910 1.91 macallan sc->sc_ports[1].rp_dac_type = RADEON_DAC_UNKNOWN; 1911 1.91 macallan sc->sc_ports[1].rp_conn_type = RADEON_CONN_NONE; 1912 1.91 macallan sc->sc_ports[1].rp_tmds_type = RADEON_TMDS_UNKNOWN; 1913 1.91 macallan sc->sc_ports[1].rp_number = 1; 1914 1.90 macallan } else if (dvi_int) { 1915 1.90 macallan sc->sc_ports[0].rp_mon_type = RADEON_MT_UNKNOWN; 1916 1.91 macallan sc->sc_ports[0].rp_ddc_type = RADEON_DDC_CRT2; 1917 1.91 macallan sc->sc_ports[0].rp_dac_type = RADEON_DAC_PRIMARY; 1918 1.90 macallan sc->sc_ports[0].rp_conn_type = RADEON_CONN_DVI_I; 1919 1.90 macallan sc->sc_ports[0].rp_tmds_type = RADEON_TMDS_INT; 1920 1.91 macallan sc->sc_ports[0].rp_number = 0; 1921 1.96 macallan sc->sc_ports[1].rp_mon_type = RADEON_MT_UNKNOWN; 1922 1.96 macallan sc->sc_ports[1].rp_ddc_type = RADEON_DDC_NONE; 1923 1.96 macallan sc->sc_ports[1].rp_dac_type = RADEON_DAC_UNKNOWN; 1924 1.96 macallan sc->sc_ports[1].rp_conn_type = RADEON_CONN_NONE; 1925 1.96 macallan sc->sc_ports[1].rp_tmds_type = RADEON_TMDS_UNKNOWN; 1926 1.96 macallan sc->sc_ports[1].rp_number = 1; 1927 1.90 macallan } else if IS_MOBILITY(sc) { 1928 1.69 macallan /* default, port 0 = internal TMDS, port 1 = CRT */ 1929 1.69 macallan sc->sc_ports[0].rp_mon_type = RADEON_MT_UNKNOWN; 1930 1.69 macallan sc->sc_ports[0].rp_ddc_type = RADEON_DDC_DVI; 1931 1.69 macallan sc->sc_ports[0].rp_dac_type = RADEON_DAC_TVDAC; 1932 1.69 macallan sc->sc_ports[0].rp_conn_type = RADEON_CONN_DVI_D; 1933 1.69 macallan sc->sc_ports[0].rp_tmds_type = RADEON_TMDS_INT; 1934 1.69 macallan sc->sc_ports[0].rp_number = 0; 1935 1.69 macallan 1936 1.69 macallan sc->sc_ports[1].rp_mon_type = RADEON_MT_UNKNOWN; 1937 1.69 macallan sc->sc_ports[1].rp_ddc_type = RADEON_DDC_VGA; 1938 1.69 macallan sc->sc_ports[1].rp_dac_type = RADEON_DAC_PRIMARY; 1939 1.69 macallan sc->sc_ports[1].rp_conn_type = RADEON_CONN_CRT; 1940 1.69 macallan sc->sc_ports[1].rp_tmds_type = RADEON_TMDS_EXT; 1941 1.69 macallan sc->sc_ports[1].rp_number = 1; 1942 1.69 macallan } else { 1943 1.69 macallan /* default, port 0 = DVI, port 1 = CRT */ 1944 1.69 macallan sc->sc_ports[0].rp_mon_type = RADEON_MT_UNKNOWN; 1945 1.69 macallan sc->sc_ports[0].rp_ddc_type = RADEON_DDC_DVI; 1946 1.69 macallan sc->sc_ports[0].rp_dac_type = RADEON_DAC_TVDAC; 1947 1.69 macallan sc->sc_ports[0].rp_conn_type = RADEON_CONN_DVI_D; 1948 1.69 macallan sc->sc_ports[0].rp_tmds_type = RADEON_TMDS_INT; 1949 1.104 macallan sc->sc_ports[0].rp_number = 0; 1950 1.69 macallan 1951 1.69 macallan sc->sc_ports[1].rp_mon_type = RADEON_MT_UNKNOWN; 1952 1.69 macallan sc->sc_ports[1].rp_ddc_type = RADEON_DDC_VGA; 1953 1.69 macallan sc->sc_ports[1].rp_dac_type = RADEON_DAC_PRIMARY; 1954 1.69 macallan sc->sc_ports[1].rp_conn_type = RADEON_CONN_CRT; 1955 1.70 macallan sc->sc_ports[1].rp_tmds_type = RADEON_TMDS_UNKNOWN; 1956 1.104 macallan sc->sc_ports[1].rp_number = 1; 1957 1.69 macallan } 1958 1.1 gdamore } 1959 1.1 gdamore 1960 1.1 gdamore /* 1961 1.1 gdamore * Fixup for RS300/RS350/RS400 chips, that lack a primary DAC. 1962 1.1 gdamore * these chips should use TVDAC for the VGA port. 1963 1.1 gdamore */ 1964 1.1 gdamore if (HAS_SDAC(sc)) { 1965 1.1 gdamore if (sc->sc_ports[0].rp_conn_type == RADEON_CONN_CRT) { 1966 1.1 gdamore sc->sc_ports[0].rp_dac_type = RADEON_DAC_TVDAC; 1967 1.1 gdamore sc->sc_ports[1].rp_dac_type = RADEON_DAC_PRIMARY; 1968 1.1 gdamore } else { 1969 1.1 gdamore sc->sc_ports[1].rp_dac_type = RADEON_DAC_TVDAC; 1970 1.1 gdamore sc->sc_ports[0].rp_dac_type = RADEON_DAC_PRIMARY; 1971 1.1 gdamore } 1972 1.1 gdamore } else if (!HAS_CRTC2(sc)) { 1973 1.1 gdamore sc->sc_ports[0].rp_dac_type = RADEON_DAC_PRIMARY; 1974 1.1 gdamore } 1975 1.1 gdamore 1976 1.1 gdamore for (i = 0; i < 2; i++) { 1977 1.111 jdc char edid[128], edid_port_str[7] = "EDID:"; 1978 1.1 gdamore uint8_t ddc; 1979 1.1 gdamore struct edid_info *eip = &sc->sc_ports[i].rp_edid; 1980 1.13 macallan prop_data_t edid_data; 1981 1.1 gdamore 1982 1.1 gdamore DPRINTF(("Port #%d:\n", i)); 1983 1.69 macallan DPRINTF((" conn = %d\n", sc->sc_ports[i].rp_conn_type)); 1984 1.1 gdamore DPRINTF((" ddc = %d\n", sc->sc_ports[i].rp_ddc_type)); 1985 1.1 gdamore DPRINTF((" dac = %d\n", sc->sc_ports[i].rp_dac_type)); 1986 1.69 macallan DPRINTF((" tmds = %d\n", sc->sc_ports[i].rp_tmds_type)); 1987 1.69 macallan DPRINTF((" crtc = %d\n", sc->sc_ports[i].rp_number)); 1988 1.1 gdamore 1989 1.1 gdamore sc->sc_ports[i].rp_edid_valid = 0; 1990 1.111 jdc /* 1991 1.111 jdc * First look for static EDID data 1992 1.111 jdc * Try "EDID:port" then "EDID" 1993 1.111 jdc */ 1994 1.111 jdc snprintf(&edid_port_str[5], 2, "%d", i); 1995 1.111 jdc edid_data = prop_dictionary_get(device_properties( 1996 1.111 jdc sc->sc_dev), edid_port_str); 1997 1.111 jdc if (edid_data == NULL) 1998 1.111 jdc edid_data = prop_dictionary_get(device_properties( 1999 1.111 jdc sc->sc_dev), "EDID"); 2000 1.111 jdc if (edid_data != NULL) { 2001 1.69 macallan aprint_debug_dev(sc->sc_dev, "using static EDID\n"); 2002 1.109 martin memcpy(edid, prop_data_value(edid_data), 128); 2003 1.13 macallan if (edid_parse(edid, eip) == 0) { 2004 1.13 macallan 2005 1.1 gdamore sc->sc_ports[i].rp_edid_valid = 1; 2006 1.101 macallan #ifdef RADEONFB_DEBUG 2007 1.101 macallan edid_print(eip); 2008 1.101 macallan #endif 2009 1.1 gdamore } 2010 1.1 gdamore } 2011 1.13 macallan /* if we didn't find any we'll try to talk to the monitor */ 2012 1.13 macallan if (sc->sc_ports[i].rp_edid_valid != 1) { 2013 1.13 macallan 2014 1.13 macallan ddc = sc->sc_ports[i].rp_ddc_type; 2015 1.13 macallan if (ddc != RADEON_DDC_NONE) { 2016 1.13 macallan if ((radeonfb_i2c_read_edid(sc, ddc, edid) 2017 1.13 macallan == 0) && (edid_parse(edid, eip) == 0)) { 2018 1.13 macallan 2019 1.13 macallan sc->sc_ports[i].rp_edid_valid = 1; 2020 1.63 macallan #ifdef RADEONFB_DEBUG 2021 1.13 macallan edid_print(eip); 2022 1.63 macallan #endif 2023 1.13 macallan } 2024 1.13 macallan } 2025 1.13 macallan } 2026 1.1 gdamore } 2027 1.1 gdamore 2028 1.1 gdamore return found; 2029 1.1 gdamore } 2030 1.1 gdamore 2031 1.1 gdamore int 2032 1.1 gdamore radeonfb_gettmds(struct radeonfb_softc *sc) 2033 1.1 gdamore { 2034 1.1 gdamore int i; 2035 1.1 gdamore 2036 1.1 gdamore if (!sc->sc_biossz) { 2037 1.1 gdamore goto nobios; 2038 1.1 gdamore } 2039 1.1 gdamore 2040 1.1 gdamore if (IS_ATOM(sc)) { 2041 1.1 gdamore /* XXX: not done yet */ 2042 1.1 gdamore } else { 2043 1.1 gdamore uint16_t ptr; 2044 1.1 gdamore int n; 2045 1.1 gdamore 2046 1.1 gdamore ptr = GETBIOS16(sc, 0x48); 2047 1.1 gdamore ptr = GETBIOS16(sc, ptr + 0x34); 2048 1.1 gdamore DPRINTF(("DFP table revision %d\n", GETBIOS8(sc, ptr))); 2049 1.11 ad if (GETBIOS8(sc, ptr) == 3) { 2050 1.1 gdamore /* revision three table */ 2051 1.1 gdamore n = GETBIOS8(sc, ptr + 5) + 1; 2052 1.100 riastrad n = uimin(n, 4); 2053 1.1 gdamore 2054 1.1 gdamore memset(sc->sc_tmds_pll, 0, sizeof (sc->sc_tmds_pll)); 2055 1.1 gdamore for (i = 0; i < n; i++) { 2056 1.1 gdamore sc->sc_tmds_pll[i].rtp_pll = GETBIOS32(sc, 2057 1.1 gdamore ptr + i * 10 + 8); 2058 1.1 gdamore sc->sc_tmds_pll[i].rtp_freq = GETBIOS16(sc, 2059 1.1 gdamore ptr + i * 10 + 0x10); 2060 1.1 gdamore DPRINTF(("TMDS_PLL dot clock %d pll %x\n", 2061 1.1 gdamore sc->sc_tmds_pll[i].rtp_freq, 2062 1.1 gdamore sc->sc_tmds_pll[i].rtp_pll)); 2063 1.1 gdamore } 2064 1.1 gdamore return 0; 2065 1.1 gdamore } 2066 1.1 gdamore } 2067 1.1 gdamore 2068 1.1 gdamore nobios: 2069 1.1 gdamore DPRINTF(("no suitable DFP table present\n")); 2070 1.1 gdamore for (i = 0; 2071 1.1 gdamore i < sizeof (radeonfb_tmds_pll) / sizeof (radeonfb_tmds_pll[0]); 2072 1.1 gdamore i++) { 2073 1.1 gdamore int j; 2074 1.1 gdamore 2075 1.1 gdamore if (radeonfb_tmds_pll[i].family != sc->sc_family) 2076 1.1 gdamore continue; 2077 1.1 gdamore 2078 1.1 gdamore for (j = 0; j < 4; j++) { 2079 1.1 gdamore sc->sc_tmds_pll[j] = radeonfb_tmds_pll[i].plls[j]; 2080 1.1 gdamore DPRINTF(("TMDS_PLL dot clock %d pll %x\n", 2081 1.1 gdamore sc->sc_tmds_pll[j].rtp_freq, 2082 1.1 gdamore sc->sc_tmds_pll[j].rtp_pll)); 2083 1.1 gdamore } 2084 1.1 gdamore return 0; 2085 1.1 gdamore } 2086 1.1 gdamore 2087 1.1 gdamore return -1; 2088 1.1 gdamore } 2089 1.1 gdamore 2090 1.1 gdamore const struct videomode * 2091 1.1 gdamore radeonfb_modelookup(const char *name) 2092 1.1 gdamore { 2093 1.1 gdamore int i; 2094 1.111 jdc /* Use a default mode in case we don't find a matching mode */ 2095 1.111 jdc const char *vm = "1024x768x60"; 2096 1.111 jdc const struct videomode *vmp = NULL; 2097 1.1 gdamore 2098 1.101 macallan for (i = 0; i < videomode_count; i++) { 2099 1.1 gdamore if (!strcmp(name, videomode_list[i].name)) 2100 1.1 gdamore return &videomode_list[i]; 2101 1.111 jdc if (!strcmp(vm, videomode_list[i].name)) 2102 1.111 jdc vmp = &videomode_list[i]; 2103 1.101 macallan } 2104 1.111 jdc return vmp; 2105 1.1 gdamore } 2106 1.1 gdamore 2107 1.1 gdamore void 2108 1.1 gdamore radeonfb_pllwriteupdate(struct radeonfb_softc *sc, int crtc) 2109 1.1 gdamore { 2110 1.1 gdamore if (crtc) { 2111 1.1 gdamore while (GETPLL(sc, RADEON_P2PLL_REF_DIV) & 2112 1.1 gdamore RADEON_P2PLL_ATOMIC_UPDATE_R); 2113 1.1 gdamore SETPLL(sc, RADEON_P2PLL_REF_DIV, RADEON_P2PLL_ATOMIC_UPDATE_W); 2114 1.1 gdamore } else { 2115 1.1 gdamore while (GETPLL(sc, RADEON_PPLL_REF_DIV) & 2116 1.1 gdamore RADEON_PPLL_ATOMIC_UPDATE_R); 2117 1.1 gdamore SETPLL(sc, RADEON_PPLL_REF_DIV, RADEON_PPLL_ATOMIC_UPDATE_W); 2118 1.1 gdamore } 2119 1.1 gdamore } 2120 1.1 gdamore 2121 1.1 gdamore void 2122 1.1 gdamore radeonfb_pllwaitatomicread(struct radeonfb_softc *sc, int crtc) 2123 1.1 gdamore { 2124 1.1 gdamore int i; 2125 1.1 gdamore 2126 1.1 gdamore for (i = 10000; i; i--) { 2127 1.1 gdamore if (crtc) { 2128 1.1 gdamore if (GETPLL(sc, RADEON_P2PLL_REF_DIV) & 2129 1.1 gdamore RADEON_P2PLL_ATOMIC_UPDATE_R) 2130 1.1 gdamore break; 2131 1.1 gdamore } else { 2132 1.1 gdamore if (GETPLL(sc, RADEON_PPLL_REF_DIV) & 2133 1.1 gdamore RADEON_PPLL_ATOMIC_UPDATE_R) 2134 1.1 gdamore break; 2135 1.1 gdamore } 2136 1.1 gdamore } 2137 1.1 gdamore } 2138 1.1 gdamore 2139 1.1 gdamore void 2140 1.92 macallan radeonfb_program_vclk(struct radeonfb_softc *sc, int dotclock, int crtc, int flags) 2141 1.1 gdamore { 2142 1.2 macallan uint32_t pbit = 0; 2143 1.2 macallan uint32_t feed = 0; 2144 1.96 macallan uint32_t data, refdiv, div0, r2xxref; 2145 1.1 gdamore 2146 1.92 macallan radeonfb_calc_dividers(sc, dotclock, &pbit, &feed, flags); 2147 1.1 gdamore 2148 1.1 gdamore if (crtc == 0) { 2149 1.1 gdamore 2150 1.69 macallan refdiv = GETPLL(sc, RADEON_PPLL_REF_DIV); 2151 1.96 macallan 2152 1.96 macallan /* 2153 1.96 macallan * XXX 2154 1.96 macallan * the RV350 in my last generation iBook G4 behaves like an 2155 1.96 macallan * r2xx here - try to detect that and not screw up the reference 2156 1.96 macallan * divider. 2157 1.96 macallan * xf86-video-radeon just skips PLL programming altogether 2158 1.96 macallan * on iBooks, probably for this reason. 2159 1.96 macallan */ 2160 1.96 macallan r2xxref = (refdiv & ~RADEON_PPLL_REF_DIV_MASK) | sc->sc_refdiv; 2161 1.96 macallan if (IS_R300(sc) && (r2xxref != refdiv)) { 2162 1.69 macallan refdiv = (refdiv & ~R300_PPLL_REF_DIV_ACC_MASK) | 2163 1.69 macallan (sc->sc_refdiv << R300_PPLL_REF_DIV_ACC_SHIFT); 2164 1.69 macallan } else { 2165 1.69 macallan refdiv = (refdiv & ~RADEON_PPLL_REF_DIV_MASK) | 2166 1.69 macallan sc->sc_refdiv; 2167 1.69 macallan } 2168 1.96 macallan DPRINTF(("refdiv %08x\n", refdiv)); 2169 1.69 macallan div0 = GETPLL(sc, RADEON_PPLL_DIV_0); 2170 1.96 macallan DPRINTF(("div0 %08x\n", div0)); 2171 1.69 macallan div0 &= ~(RADEON_PPLL_FB3_DIV_MASK | 2172 1.69 macallan RADEON_PPLL_POST3_DIV_MASK); 2173 1.69 macallan div0 |= pbit; 2174 1.69 macallan div0 |= (feed & RADEON_PPLL_FB3_DIV_MASK); 2175 1.96 macallan DPRINTF(("div0 %08x\n", div0)); 2176 1.69 macallan 2177 1.69 macallan if ((refdiv == GETPLL(sc, RADEON_PPLL_REF_DIV)) && 2178 1.69 macallan (div0 == GETPLL(sc, RADEON_PPLL_DIV_0))) { 2179 1.69 macallan /* 2180 1.69 macallan * nothing to do here, the PLL is already where we 2181 1.69 macallan * want it 2182 1.69 macallan */ 2183 1.69 macallan PATCH32(sc, RADEON_CLOCK_CNTL_INDEX, 0, 2184 1.69 macallan ~RADEON_PLL_DIV_SEL); 2185 1.69 macallan aprint_debug_dev(sc->sc_dev, "no need to touch the PLL\n"); 2186 1.69 macallan return; 2187 1.69 macallan } 2188 1.1 gdamore 2189 1.69 macallan /* alright, we do need to reprogram stuff */ 2190 1.1 gdamore PATCHPLL(sc, RADEON_VCLK_ECP_CNTL, 2191 1.1 gdamore RADEON_VCLK_SRC_SEL_CPUCLK, 2192 1.1 gdamore ~RADEON_VCLK_SRC_SEL_MASK); 2193 1.11 ad 2194 1.1 gdamore /* put vclk into reset, use atomic updates */ 2195 1.1 gdamore SETPLL(sc, RADEON_PPLL_CNTL, 2196 1.1 gdamore RADEON_PPLL_REFCLK_SEL | 2197 1.1 gdamore RADEON_PPLL_FBCLK_SEL | 2198 1.1 gdamore RADEON_PPLL_RESET | 2199 1.1 gdamore RADEON_PPLL_ATOMIC_UPDATE_EN | 2200 1.1 gdamore RADEON_PPLL_VGA_ATOMIC_UPDATE_EN); 2201 1.1 gdamore 2202 1.69 macallan /* select clock 0 */ 2203 1.1 gdamore PATCH32(sc, RADEON_CLOCK_CNTL_INDEX, 0, 2204 1.1 gdamore ~RADEON_PLL_DIV_SEL); 2205 1.11 ad 2206 1.69 macallan PUTPLL(sc, RADEON_PPLL_REF_DIV, refdiv); 2207 1.1 gdamore 2208 1.69 macallan /* xf86-video-radeon does this, not sure why */ 2209 1.69 macallan PUTPLL(sc, RADEON_PPLL_DIV_0, div0); 2210 1.69 macallan PUTPLL(sc, RADEON_PPLL_DIV_0, div0); 2211 1.1 gdamore 2212 1.1 gdamore /* use the atomic update */ 2213 1.1 gdamore radeonfb_pllwriteupdate(sc, crtc); 2214 1.1 gdamore 2215 1.1 gdamore /* and wait for it to complete */ 2216 1.1 gdamore radeonfb_pllwaitatomicread(sc, crtc); 2217 1.1 gdamore 2218 1.1 gdamore /* program HTOTAL (why?) */ 2219 1.1 gdamore PUTPLL(sc, RADEON_HTOTAL_CNTL, 0); 2220 1.1 gdamore 2221 1.1 gdamore /* drop reset */ 2222 1.1 gdamore CLRPLL(sc, RADEON_PPLL_CNTL, 2223 1.1 gdamore RADEON_PPLL_RESET | RADEON_PPLL_SLEEP | 2224 1.1 gdamore RADEON_PPLL_ATOMIC_UPDATE_EN | 2225 1.1 gdamore RADEON_PPLL_VGA_ATOMIC_UPDATE_EN); 2226 1.1 gdamore 2227 1.1 gdamore PRINTPLL(RADEON_PPLL_CNTL); 2228 1.69 macallan PRINTPLL(RADEON_PPLL_REF_DIV); 2229 1.69 macallan PRINTPLL(RADEON_PPLL_DIV_3); 2230 1.1 gdamore 2231 1.1 gdamore /* give clock time to lock */ 2232 1.1 gdamore delay(50000); 2233 1.1 gdamore 2234 1.1 gdamore PATCHPLL(sc, RADEON_VCLK_ECP_CNTL, 2235 1.1 gdamore RADEON_VCLK_SRC_SEL_PPLLCLK, 2236 1.1 gdamore ~RADEON_VCLK_SRC_SEL_MASK); 2237 1.1 gdamore 2238 1.1 gdamore } else { 2239 1.1 gdamore 2240 1.1 gdamore PATCHPLL(sc, RADEON_PIXCLKS_CNTL, 2241 1.1 gdamore RADEON_PIX2CLK_SRC_SEL_CPUCLK, 2242 1.1 gdamore ~RADEON_PIX2CLK_SRC_SEL_MASK); 2243 1.1 gdamore 2244 1.1 gdamore /* put vclk into reset, use atomic updates */ 2245 1.1 gdamore SETPLL(sc, RADEON_P2PLL_CNTL, 2246 1.1 gdamore RADEON_P2PLL_RESET | 2247 1.1 gdamore RADEON_P2PLL_ATOMIC_UPDATE_EN | 2248 1.1 gdamore RADEON_P2PLL_VGA_ATOMIC_UPDATE_EN); 2249 1.1 gdamore 2250 1.1 gdamore /* program reference divider */ 2251 1.1 gdamore PATCHPLL(sc, RADEON_P2PLL_REF_DIV, sc->sc_refdiv, 2252 1.1 gdamore ~RADEON_P2PLL_REF_DIV_MASK); 2253 1.1 gdamore 2254 1.1 gdamore /* program feedback and post dividers */ 2255 1.1 gdamore data = GETPLL(sc, RADEON_P2PLL_DIV_0); 2256 1.1 gdamore data &= ~(RADEON_P2PLL_FB0_DIV_MASK | 2257 1.1 gdamore RADEON_P2PLL_POST0_DIV_MASK); 2258 1.1 gdamore data |= pbit; 2259 1.1 gdamore data |= (feed & RADEON_P2PLL_FB0_DIV_MASK); 2260 1.1 gdamore PUTPLL(sc, RADEON_P2PLL_DIV_0, data); 2261 1.69 macallan PUTPLL(sc, RADEON_P2PLL_DIV_0, data); 2262 1.69 macallan 2263 1.69 macallan PRINTPLL(RADEON_P2PLL_REF_DIV); 2264 1.69 macallan PRINTPLL(RADEON_P2PLL_DIV_0); 2265 1.1 gdamore 2266 1.1 gdamore /* use the atomic update */ 2267 1.1 gdamore radeonfb_pllwriteupdate(sc, crtc); 2268 1.1 gdamore 2269 1.1 gdamore /* and wait for it to complete */ 2270 1.1 gdamore radeonfb_pllwaitatomicread(sc, crtc); 2271 1.1 gdamore 2272 1.1 gdamore /* program HTOTAL (why?) */ 2273 1.1 gdamore PUTPLL(sc, RADEON_HTOTAL2_CNTL, 0); 2274 1.1 gdamore 2275 1.1 gdamore /* drop reset */ 2276 1.1 gdamore CLRPLL(sc, RADEON_P2PLL_CNTL, 2277 1.1 gdamore RADEON_P2PLL_RESET | RADEON_P2PLL_SLEEP | 2278 1.1 gdamore RADEON_P2PLL_ATOMIC_UPDATE_EN | 2279 1.1 gdamore RADEON_P2PLL_VGA_ATOMIC_UPDATE_EN); 2280 1.1 gdamore 2281 1.1 gdamore /* allow time for clock to lock */ 2282 1.1 gdamore delay(50000); 2283 1.1 gdamore 2284 1.1 gdamore PATCHPLL(sc, RADEON_PIXCLKS_CNTL, 2285 1.1 gdamore RADEON_PIX2CLK_SRC_SEL_P2PLLCLK, 2286 1.1 gdamore ~RADEON_PIX2CLK_SRC_SEL_MASK); 2287 1.1 gdamore } 2288 1.1 gdamore PRINTREG(RADEON_CRTC_MORE_CNTL); 2289 1.1 gdamore } 2290 1.1 gdamore 2291 1.1 gdamore void 2292 1.1 gdamore radeonfb_modeswitch(struct radeonfb_display *dp) 2293 1.1 gdamore { 2294 1.1 gdamore struct radeonfb_softc *sc = dp->rd_softc; 2295 1.1 gdamore int i; 2296 1.1 gdamore 2297 1.110 macallan if (IS_AVIVO(sc)) { 2298 1.110 macallan /* 2299 1.110 macallan * no actual mode setting yet, we just make sure the CRTCs 2300 1.110 macallan * point at the right memory ranges and use the same pitch 2301 1.110 macallan * for the drawing engine 2302 1.110 macallan */ 2303 1.110 macallan if (GET32(sc, AVIVO_D1CRTC_CONTROL) & AVIVO_CRTC_EN) { 2304 1.110 macallan CLR32(sc, AVIVO_D1GRPH_CONTROL, AVIVO_D1GRPH_MACRO_ADDRESS_MODE); 2305 1.110 macallan dp->rd_stride = GET32(sc, AVIVO_D1GRPH_PITCH); 2306 1.110 macallan PUT32(sc, AVIVO_D1GRPH_PRIMARY_SURFACE_ADDRESS, 0); 2307 1.110 macallan } 2308 1.110 macallan if (GET32(sc, AVIVO_D2CRTC_CONTROL) & AVIVO_CRTC_EN) { 2309 1.110 macallan CLR32(sc, AVIVO_D2GRPH_CONTROL, AVIVO_D1GRPH_MACRO_ADDRESS_MODE); 2310 1.110 macallan dp->rd_stride = GET32(sc, AVIVO_D2GRPH_PITCH); 2311 1.110 macallan PUT32(sc, AVIVO_D2GRPH_PRIMARY_SURFACE_ADDRESS, 0); 2312 1.110 macallan } 2313 1.110 macallan return; 2314 1.110 macallan } 2315 1.110 macallan 2316 1.1 gdamore /* blank the display while we switch modes */ 2317 1.110 macallan //radeonfb_blank(dp, 1); 2318 1.1 gdamore 2319 1.1 gdamore #if 0 2320 1.1 gdamore SET32(sc, RADEON_CRTC_EXT_CNTL, 2321 1.1 gdamore RADEON_CRTC_VSYNC_DIS | RADEON_CRTC_HSYNC_DIS | 2322 1.1 gdamore RADEON_CRTC_DISPLAY_DIS /* | RADEON_CRTC_DISP_REQ_EN_B */); 2323 1.1 gdamore #endif 2324 1.1 gdamore 2325 1.1 gdamore /* these registers might get in the way... */ 2326 1.1 gdamore PUT32(sc, RADEON_OVR_CLR, 0); 2327 1.1 gdamore PUT32(sc, RADEON_OVR_WID_LEFT_RIGHT, 0); 2328 1.1 gdamore PUT32(sc, RADEON_OVR_WID_TOP_BOTTOM, 0); 2329 1.1 gdamore PUT32(sc, RADEON_OV0_SCALE_CNTL, 0); 2330 1.1 gdamore PUT32(sc, RADEON_SUBPIC_CNTL, 0); 2331 1.1 gdamore PUT32(sc, RADEON_VIPH_CONTROL, 0); 2332 1.1 gdamore PUT32(sc, RADEON_I2C_CNTL_1, 0); 2333 1.1 gdamore PUT32(sc, RADEON_GEN_INT_CNTL, 0); 2334 1.1 gdamore PUT32(sc, RADEON_CAP0_TRIG_CNTL, 0); 2335 1.1 gdamore PUT32(sc, RADEON_CAP1_TRIG_CNTL, 0); 2336 1.1 gdamore 2337 1.1 gdamore for (i = 0; i < dp->rd_ncrtcs; i++) 2338 1.1 gdamore radeonfb_setcrtc(dp, i); 2339 1.1 gdamore 2340 1.92 macallan #if 0 2341 1.92 macallan /* 2342 1.92 macallan * DVO chip voodoo from xf86-video-radeon 2343 1.92 macallan * apparently this is needed for some powerbooks with DVI outputs 2344 1.92 macallan */ 2345 1.92 macallan 2346 1.92 macallan uint8_t data[5][2] = {{0x8, 0x030}, {0x9, 0}, {0xa, 0x90}, {0xc, 0x89}, {0x8, 0x3b}}; 2347 1.92 macallan int n = 0; 2348 1.92 macallan iic_acquire_bus(&sc->sc_i2c[0].ric_controller, 0); 2349 1.92 macallan for (i = 0; i < 5; i++) 2350 1.92 macallan n += iic_exec(&sc->sc_i2c[0].ric_controller, I2C_OP_WRITE, 0x38, data[i], 2, NULL, 0, 0); 2351 1.92 macallan iic_release_bus(&sc->sc_i2c[0].ric_controller, 0); 2352 1.92 macallan printf("n = %d\n", n); 2353 1.92 macallan #endif 2354 1.92 macallan 2355 1.1 gdamore /* activate the display */ 2356 1.36 macallan radeonfb_blank(dp, 0); 2357 1.1 gdamore } 2358 1.1 gdamore 2359 1.1 gdamore void 2360 1.1 gdamore radeonfb_setcrtc(struct radeonfb_display *dp, int index) 2361 1.1 gdamore { 2362 1.92 macallan int crtc, flags = 0; 2363 1.1 gdamore struct videomode *mode; 2364 1.1 gdamore struct radeonfb_softc *sc; 2365 1.1 gdamore struct radeonfb_crtc *cp; 2366 1.110 macallan uint32_t v, hd, vd; 2367 1.1 gdamore uint32_t gencntl; 2368 1.1 gdamore uint32_t htotaldisp; 2369 1.1 gdamore uint32_t hsyncstrt; 2370 1.1 gdamore uint32_t vtotaldisp; 2371 1.1 gdamore uint32_t vsyncstrt; 2372 1.1 gdamore uint32_t fphsyncstrt; 2373 1.1 gdamore uint32_t fpvsyncstrt; 2374 1.1 gdamore uint32_t fphtotaldisp; 2375 1.1 gdamore uint32_t fpvtotaldisp; 2376 1.1 gdamore uint32_t pitch; 2377 1.1 gdamore 2378 1.1 gdamore sc = dp->rd_softc; 2379 1.92 macallan 2380 1.92 macallan if ((sc->sc_ports[index].rp_tmds_type == RADEON_TMDS_INT) || 2381 1.92 macallan (sc->sc_ports[index].rp_tmds_type == RADEON_TMDS_EXT)) { 2382 1.92 macallan flags |= NO_ODD_FBDIV; 2383 1.92 macallan } 2384 1.92 macallan 2385 1.1 gdamore cp = &dp->rd_crtcs[index]; 2386 1.1 gdamore crtc = cp->rc_number; 2387 1.1 gdamore mode = &cp->rc_videomode; 2388 1.1 gdamore 2389 1.2 macallan #if 1 2390 1.65 macallan pitch = dp->rd_stride / dp->rd_bpp; 2391 1.1 gdamore #else 2392 1.1 gdamore pitch = (((sc->sc_maxx * sc->sc_maxbpp) + ((sc->sc_maxbpp * 8) - 1)) / 2393 1.1 gdamore (sc->sc_maxbpp * 8)); 2394 1.1 gdamore #endif 2395 1.1 gdamore switch (crtc) { 2396 1.1 gdamore case 0: 2397 1.1 gdamore gencntl = RADEON_CRTC_GEN_CNTL; 2398 1.1 gdamore htotaldisp = RADEON_CRTC_H_TOTAL_DISP; 2399 1.1 gdamore hsyncstrt = RADEON_CRTC_H_SYNC_STRT_WID; 2400 1.1 gdamore vtotaldisp = RADEON_CRTC_V_TOTAL_DISP; 2401 1.1 gdamore vsyncstrt = RADEON_CRTC_V_SYNC_STRT_WID; 2402 1.92 macallan /* should probably leave those alone on non-LVDS */ 2403 1.1 gdamore fpvsyncstrt = RADEON_FP_V_SYNC_STRT_WID; 2404 1.1 gdamore fphsyncstrt = RADEON_FP_H_SYNC_STRT_WID; 2405 1.1 gdamore fpvtotaldisp = RADEON_FP_CRTC_V_TOTAL_DISP; 2406 1.1 gdamore fphtotaldisp = RADEON_FP_CRTC_H_TOTAL_DISP; 2407 1.1 gdamore break; 2408 1.1 gdamore case 1: 2409 1.1 gdamore gencntl = RADEON_CRTC2_GEN_CNTL; 2410 1.1 gdamore htotaldisp = RADEON_CRTC2_H_TOTAL_DISP; 2411 1.1 gdamore hsyncstrt = RADEON_CRTC2_H_SYNC_STRT_WID; 2412 1.1 gdamore vtotaldisp = RADEON_CRTC2_V_TOTAL_DISP; 2413 1.1 gdamore vsyncstrt = RADEON_CRTC2_V_SYNC_STRT_WID; 2414 1.1 gdamore fpvsyncstrt = RADEON_FP_V2_SYNC_STRT_WID; 2415 1.1 gdamore fphsyncstrt = RADEON_FP_H2_SYNC_STRT_WID; 2416 1.92 macallan /* XXX these registers don't seem to exist */ 2417 1.92 macallan fpvtotaldisp = 0;//RADEON_FP_CRTC2_V_TOTAL_DISP; 2418 1.92 macallan fphtotaldisp = 0;//RADEON_FP_CRTC2_H_TOTAL_DISP; 2419 1.1 gdamore break; 2420 1.1 gdamore default: 2421 1.1 gdamore panic("Bad CRTC!"); 2422 1.1 gdamore break; 2423 1.1 gdamore } 2424 1.1 gdamore 2425 1.1 gdamore /* 2426 1.1 gdamore * CRTC_GEN_CNTL - depth, accelerator mode, etc. 2427 1.1 gdamore */ 2428 1.1 gdamore /* only bother with 32bpp and 8bpp */ 2429 1.1 gdamore v = dp->rd_format << RADEON_CRTC_PIX_WIDTH_SHIFT; 2430 1.1 gdamore 2431 1.1 gdamore if (crtc == 1) { 2432 1.1 gdamore v |= RADEON_CRTC2_CRT2_ON | RADEON_CRTC2_EN; 2433 1.1 gdamore } else { 2434 1.1 gdamore v |= RADEON_CRTC_EXT_DISP_EN | RADEON_CRTC_EN; 2435 1.1 gdamore } 2436 1.1 gdamore 2437 1.1 gdamore if (mode->flags & VID_DBLSCAN) 2438 1.1 gdamore v |= RADEON_CRTC2_DBL_SCAN_EN; 2439 1.1 gdamore 2440 1.1 gdamore if (mode->flags & VID_INTERLACE) 2441 1.1 gdamore v |= RADEON_CRTC2_INTERLACE_EN; 2442 1.1 gdamore 2443 1.1 gdamore if (mode->flags & VID_CSYNC) { 2444 1.1 gdamore v |= RADEON_CRTC2_CSYNC_EN; 2445 1.1 gdamore if (crtc == 1) 2446 1.1 gdamore v |= RADEON_CRTC2_VSYNC_TRISTAT; 2447 1.1 gdamore } 2448 1.11 ad 2449 1.1 gdamore PUT32(sc, gencntl, v); 2450 1.1 gdamore DPRINTF(("CRTC%s_GEN_CNTL = %08x\n", crtc ? "2" : "", v)); 2451 1.1 gdamore 2452 1.1 gdamore /* 2453 1.1 gdamore * CRTC_EXT_CNTL - preserve disable flags, set ATI linear and EXT_CNT 2454 1.1 gdamore */ 2455 1.1 gdamore v = GET32(sc, RADEON_CRTC_EXT_CNTL); 2456 1.1 gdamore if (crtc == 0) { 2457 1.1 gdamore v &= (RADEON_CRTC_VSYNC_DIS | RADEON_CRTC_HSYNC_DIS | 2458 1.1 gdamore RADEON_CRTC_DISPLAY_DIS); 2459 1.1 gdamore v |= RADEON_XCRT_CNT_EN | RADEON_VGA_ATI_LINEAR; 2460 1.1 gdamore if (mode->flags & VID_CSYNC) 2461 1.1 gdamore v |= RADEON_CRTC_VSYNC_TRISTAT; 2462 1.1 gdamore } 2463 1.1 gdamore /* unconditional turn on CRT, in case first CRTC is DFP */ 2464 1.1 gdamore v |= RADEON_CRTC_CRT_ON; 2465 1.1 gdamore PUT32(sc, RADEON_CRTC_EXT_CNTL, v); 2466 1.1 gdamore PRINTREG(RADEON_CRTC_EXT_CNTL); 2467 1.1 gdamore 2468 1.110 macallan hd = ((GET32(sc, htotaldisp) >> 16) + 1) * 8; 2469 1.110 macallan vd = (GET32(sc, vtotaldisp) >> 16) + 1; 2470 1.110 macallan DPRINTF(("res %d x %d\n", hd, vd)); 2471 1.110 macallan 2472 1.110 macallan if ((hd != mode->hdisplay) || (vd != mode->vdisplay)) { 2473 1.110 macallan 2474 1.110 macallan /* 2475 1.110 macallan * H_TOTAL_DISP 2476 1.110 macallan */ 2477 1.110 macallan v = ((mode->hdisplay / 8) - 1) << 16; 2478 1.110 macallan v |= (mode->htotal / 8) - 1; 2479 1.110 macallan PRINTREG(RADEON_CRTC_H_TOTAL_DISP); 2480 1.110 macallan PUT32(sc, htotaldisp, v); 2481 1.110 macallan DPRINTF(("CRTC%s_H_TOTAL_DISP = %08x\n", crtc ? "2" : "", v)); 2482 1.110 macallan if (fphtotaldisp) { 2483 1.110 macallan PRINTREG(RADEON_FP_CRTC_H_TOTAL_DISP); 2484 1.110 macallan PUT32(sc, fphtotaldisp, v); 2485 1.110 macallan DPRINTF(("FP_H%s_TOTAL_DISP = %08x\n", crtc ? "2" : "", v)); 2486 1.110 macallan } 2487 1.110 macallan /* 2488 1.110 macallan * H_SYNC_STRT_WID 2489 1.110 macallan */ 2490 1.110 macallan v = (((mode->hsync_end - mode->hsync_start) / 8) << 16); 2491 1.110 macallan v |= (mode->hsync_start - 8); /* match xf86-video-radeon */ 2492 1.110 macallan if (mode->flags & VID_NHSYNC) 2493 1.110 macallan v |= RADEON_CRTC_H_SYNC_POL; 2494 1.110 macallan PUT32(sc, hsyncstrt, v); 2495 1.110 macallan DPRINTF(("CRTC%s_H_SYNC_STRT_WID = %08x\n", crtc ? "2" : "", v)); 2496 1.110 macallan if (fphsyncstrt) { 2497 1.110 macallan PUT32(sc, fphsyncstrt, v); 2498 1.110 macallan DPRINTF(("FP_H%s_SYNC_STRT_WID = %08x\n", crtc ? "2" : "", v)); 2499 1.110 macallan } 2500 1.1 gdamore 2501 1.110 macallan /* 2502 1.110 macallan * V_TOTAL_DISP 2503 1.110 macallan */ 2504 1.110 macallan v = ((mode->vdisplay - 1) << 16); 2505 1.110 macallan v |= (mode->vtotal - 1); 2506 1.110 macallan PUT32(sc, vtotaldisp, v); 2507 1.110 macallan DPRINTF(("CRTC%s_V_TOTAL_DISP = %08x\n", crtc ? "2" : "", v)); 2508 1.110 macallan if (fpvtotaldisp) { 2509 1.110 macallan PUT32(sc, fpvtotaldisp, v); 2510 1.110 macallan DPRINTF(("FP_V%s_TOTAL_DISP = %08x\n", crtc ? "2" : "", v)); 2511 1.110 macallan } 2512 1.1 gdamore 2513 1.110 macallan /* 2514 1.110 macallan * V_SYNC_STRT_WID 2515 1.110 macallan */ 2516 1.110 macallan v = ((mode->vsync_end - mode->vsync_start) << 16); 2517 1.110 macallan v |= (mode->vsync_start - 1); 2518 1.110 macallan if (mode->flags & VID_NVSYNC) 2519 1.110 macallan v |= RADEON_CRTC_V_SYNC_POL; 2520 1.110 macallan PUT32(sc, vsyncstrt, v); 2521 1.110 macallan DPRINTF(("CRTC%s_V_SYNC_STRT_WID = %08x\n", crtc ? "2" : "", v)); 2522 1.110 macallan if (fpvsyncstrt) { 2523 1.110 macallan PUT32(sc, fpvsyncstrt, v); 2524 1.110 macallan DPRINTF(("FP_V%s_SYNC_STRT_WID = %08x\n", crtc ? "2" : "", v)); 2525 1.110 macallan } 2526 1.92 macallan } 2527 1.92 macallan radeonfb_program_vclk(sc, mode->dot_clock, crtc, flags); 2528 1.1 gdamore 2529 1.1 gdamore switch (crtc) { 2530 1.1 gdamore case 0: 2531 1.1 gdamore PUT32(sc, RADEON_CRTC_OFFSET, 0); 2532 1.1 gdamore PUT32(sc, RADEON_CRTC_OFFSET_CNTL, 0); 2533 1.1 gdamore PUT32(sc, RADEON_CRTC_PITCH, pitch); 2534 1.1 gdamore CLR32(sc, RADEON_DISP_MERGE_CNTL, RADEON_DISP_RGB_OFFSET_EN); 2535 1.1 gdamore 2536 1.1 gdamore CLR32(sc, RADEON_CRTC_EXT_CNTL, 2537 1.1 gdamore RADEON_CRTC_VSYNC_DIS | RADEON_CRTC_HSYNC_DIS | 2538 1.1 gdamore RADEON_CRTC_DISPLAY_DIS /* | RADEON_CRTC_DISP_REQ_EN_B */); 2539 1.1 gdamore CLR32(sc, RADEON_CRTC_GEN_CNTL, RADEON_CRTC_DISP_REQ_EN_B); 2540 1.1 gdamore PRINTREG(RADEON_CRTC_EXT_CNTL); 2541 1.1 gdamore PRINTREG(RADEON_CRTC_GEN_CNTL); 2542 1.1 gdamore PRINTREG(RADEON_CLOCK_CNTL_INDEX); 2543 1.1 gdamore break; 2544 1.1 gdamore 2545 1.1 gdamore case 1: 2546 1.1 gdamore PUT32(sc, RADEON_CRTC2_OFFSET, 0); 2547 1.1 gdamore PUT32(sc, RADEON_CRTC2_OFFSET_CNTL, 0); 2548 1.1 gdamore PUT32(sc, RADEON_CRTC2_PITCH, pitch); 2549 1.1 gdamore CLR32(sc, RADEON_DISP2_MERGE_CNTL, RADEON_DISP2_RGB_OFFSET_EN); 2550 1.1 gdamore CLR32(sc, RADEON_CRTC2_GEN_CNTL, 2551 1.1 gdamore RADEON_CRTC2_VSYNC_DIS | 2552 1.1 gdamore RADEON_CRTC2_HSYNC_DIS | 2553 1.11 ad RADEON_CRTC2_DISP_DIS | RADEON_CRTC2_DISP_REQ_EN_B); 2554 1.1 gdamore PRINTREG(RADEON_CRTC2_GEN_CNTL); 2555 1.1 gdamore break; 2556 1.1 gdamore } 2557 1.1 gdamore } 2558 1.1 gdamore 2559 1.1 gdamore int 2560 1.1 gdamore radeonfb_isblank(struct radeonfb_display *dp) 2561 1.1 gdamore { 2562 1.110 macallan struct radeonfb_softc *sc = dp->rd_softc; 2563 1.1 gdamore uint32_t reg, mask; 2564 1.1 gdamore 2565 1.68 macallan if(!dp->rd_softc->sc_mapped) 2566 1.68 macallan return 1; 2567 1.68 macallan 2568 1.112 macallan if (IS_AVIVO(sc)) { 2569 1.112 macallan reg = GET32(sc, AVIVO_D1CRTC_CONTROL); 2570 1.112 macallan return ((reg & AVIVO_CRTC_EN) == 0); 2571 1.112 macallan } 2572 1.112 macallan 2573 1.1 gdamore if (dp->rd_crtcs[0].rc_number) { 2574 1.1 gdamore reg = RADEON_CRTC2_GEN_CNTL; 2575 1.1 gdamore mask = RADEON_CRTC2_DISP_DIS; 2576 1.1 gdamore } else { 2577 1.1 gdamore reg = RADEON_CRTC_EXT_CNTL; 2578 1.1 gdamore mask = RADEON_CRTC_DISPLAY_DIS; 2579 1.1 gdamore } 2580 1.1 gdamore return ((GET32(dp->rd_softc, reg) & mask) ? 1 : 0); 2581 1.1 gdamore } 2582 1.1 gdamore 2583 1.1 gdamore void 2584 1.1 gdamore radeonfb_blank(struct radeonfb_display *dp, int blank) 2585 1.1 gdamore { 2586 1.1 gdamore struct radeonfb_softc *sc = dp->rd_softc; 2587 1.1 gdamore uint32_t reg, mask; 2588 1.1 gdamore uint32_t fpreg, fpval; 2589 1.1 gdamore int i; 2590 1.1 gdamore 2591 1.110 macallan 2592 1.68 macallan if (!sc->sc_mapped) 2593 1.68 macallan return; 2594 1.68 macallan 2595 1.112 macallan if(IS_AVIVO(sc)) { 2596 1.112 macallan 2597 1.112 macallan /* 2598 1.112 macallan * XXX 2599 1.112 macallan * I don't know how to turn the sunc outputs off for DPMS 2600 1.112 macallan * power control, so for now just turn the entire CRTC off 2601 1.112 macallan */ 2602 1.112 macallan if (blank) { 2603 1.112 macallan CLR32(sc, AVIVO_D1CRTC_CONTROL, AVIVO_CRTC_EN); 2604 1.112 macallan CLR32(sc, AVIVO_D2CRTC_CONTROL, AVIVO_CRTC_EN); 2605 1.112 macallan } else { 2606 1.112 macallan SET32(sc, AVIVO_D1CRTC_CONTROL, AVIVO_CRTC_EN); 2607 1.112 macallan SET32(sc, AVIVO_D2CRTC_CONTROL, AVIVO_CRTC_EN); 2608 1.112 macallan } 2609 1.112 macallan return; 2610 1.112 macallan } 2611 1.112 macallan /* non-AVIVO case */ 2612 1.1 gdamore for (i = 0; i < dp->rd_ncrtcs; i++) { 2613 1.1 gdamore 2614 1.1 gdamore if (dp->rd_crtcs[i].rc_number) { 2615 1.1 gdamore reg = RADEON_CRTC2_GEN_CNTL; 2616 1.1 gdamore mask = RADEON_CRTC2_DISP_DIS; 2617 1.1 gdamore fpreg = RADEON_FP2_GEN_CNTL; 2618 1.1 gdamore fpval = RADEON_FP2_ON; 2619 1.1 gdamore } else { 2620 1.1 gdamore reg = RADEON_CRTC_EXT_CNTL; 2621 1.1 gdamore mask = RADEON_CRTC_DISPLAY_DIS; 2622 1.1 gdamore fpreg = RADEON_FP_GEN_CNTL; 2623 1.1 gdamore fpval = RADEON_FP_FPON; 2624 1.1 gdamore } 2625 1.11 ad 2626 1.1 gdamore if (blank) { 2627 1.1 gdamore SET32(sc, reg, mask); 2628 1.1 gdamore CLR32(sc, fpreg, fpval); 2629 1.1 gdamore } else { 2630 1.1 gdamore CLR32(sc, reg, mask); 2631 1.1 gdamore SET32(sc, fpreg, fpval); 2632 1.1 gdamore } 2633 1.1 gdamore } 2634 1.1 gdamore PRINTREG(RADEON_FP_GEN_CNTL); 2635 1.1 gdamore PRINTREG(RADEON_FP2_GEN_CNTL); 2636 1.1 gdamore } 2637 1.1 gdamore 2638 1.1 gdamore void 2639 1.1 gdamore radeonfb_init_screen(void *cookie, struct vcons_screen *scr, int existing, 2640 1.1 gdamore long *defattr) 2641 1.1 gdamore { 2642 1.1 gdamore struct radeonfb_display *dp = cookie; 2643 1.1 gdamore struct rasops_info *ri = &scr->scr_ri; 2644 1.1 gdamore 2645 1.1 gdamore /* initialize font subsystem */ 2646 1.1 gdamore wsfont_init(); 2647 1.1 gdamore 2648 1.89 macallan scr->scr_flags |= VCONS_LOADFONT; 2649 1.89 macallan 2650 1.1 gdamore DPRINTF(("init screen called, existing %d\n", existing)); 2651 1.1 gdamore 2652 1.1 gdamore ri->ri_depth = dp->rd_bpp; 2653 1.1 gdamore ri->ri_width = dp->rd_virtx; 2654 1.1 gdamore ri->ri_height = dp->rd_virty; 2655 1.1 gdamore ri->ri_stride = dp->rd_stride; 2656 1.1 gdamore ri->ri_flg = RI_CENTER; 2657 1.61 macallan switch (ri->ri_depth) { 2658 1.61 macallan case 8: 2659 1.89 macallan ri->ri_flg |= RI_ENABLE_ALPHA | RI_8BIT_IS_RGB | RI_PREFER_ALPHA; 2660 1.61 macallan break; 2661 1.61 macallan case 32: 2662 1.89 macallan ri->ri_flg |= RI_ENABLE_ALPHA | RI_PREFER_ALPHA; 2663 1.61 macallan /* we run radeons in RGB even on SPARC hardware */ 2664 1.61 macallan ri->ri_rnum = 8; 2665 1.61 macallan ri->ri_gnum = 8; 2666 1.61 macallan ri->ri_bnum = 8; 2667 1.61 macallan ri->ri_rpos = 16; 2668 1.61 macallan ri->ri_gpos = 8; 2669 1.61 macallan ri->ri_bpos = 0; 2670 1.61 macallan break; 2671 1.55 macallan } 2672 1.61 macallan 2673 1.1 gdamore ri->ri_bits = (void *)dp->rd_fbptr; 2674 1.1 gdamore 2675 1.48 macallan #ifdef VCONS_DRAW_INTR 2676 1.48 macallan scr->scr_flags |= VCONS_DONT_READ; 2677 1.48 macallan #endif 2678 1.48 macallan 2679 1.1 gdamore if (existing) { 2680 1.1 gdamore ri->ri_flg |= RI_CLEAR; 2681 1.1 gdamore 2682 1.1 gdamore /* start a modeswitch now */ 2683 1.110 macallan //radeonfb_modeswitch(dp); 2684 1.1 gdamore } 2685 1.1 gdamore 2686 1.1 gdamore /* 2687 1.1 gdamore * XXX: font selection should be based on properties, with some 2688 1.1 gdamore * normal/reasonable default. 2689 1.1 gdamore */ 2690 1.1 gdamore 2691 1.1 gdamore /* initialize and look for an initial font */ 2692 1.52 macallan rasops_init(ri, 0, 0); 2693 1.64 macallan ri->ri_caps = WSSCREEN_UNDERLINE | WSSCREEN_HILIT | 2694 1.89 macallan WSSCREEN_WSCOLORS | WSSCREEN_REVERSE | WSSCREEN_RESIZE; 2695 1.1 gdamore 2696 1.2 macallan rasops_reconfig(ri, dp->rd_virty / ri->ri_font->fontheight, 2697 1.2 macallan dp->rd_virtx / ri->ri_font->fontwidth); 2698 1.2 macallan 2699 1.1 gdamore /* enable acceleration */ 2700 1.38 macallan dp->rd_putchar = ri->ri_ops.putchar; 2701 1.1 gdamore ri->ri_ops.copyrows = radeonfb_copyrows; 2702 1.1 gdamore ri->ri_ops.copycols = radeonfb_copycols; 2703 1.1 gdamore ri->ri_ops.eraserows = radeonfb_eraserows; 2704 1.1 gdamore ri->ri_ops.erasecols = radeonfb_erasecols; 2705 1.49 macallan /* pick a putchar method based on font and Radeon model */ 2706 1.49 macallan if (ri->ri_font->stride < ri->ri_font->fontwidth) { 2707 1.49 macallan /* got a bitmap font */ 2708 1.110 macallan #if !defined(RADEONFB_ALWAYS_ACCEL_PUTCHAR) 2709 1.110 macallan if (IS_R300(dp->rd_softc) && 0) { 2710 1.49 macallan /* 2711 1.49 macallan * radeonfb_putchar() doesn't work right on some R3xx 2712 1.49 macallan * so we use software drawing here, the wrapper just 2713 1.49 macallan * makes sure the engine is idle before scribbling 2714 1.49 macallan * into vram 2715 1.49 macallan */ 2716 1.49 macallan ri->ri_ops.putchar = radeonfb_putchar_wrapper; 2717 1.73 macallan } else 2718 1.73 macallan #endif 2719 1.49 macallan ri->ri_ops.putchar = radeonfb_putchar; 2720 1.48 macallan } else { 2721 1.49 macallan /* got an alpha font */ 2722 1.55 macallan switch(ri->ri_depth) { 2723 1.55 macallan case 32: 2724 1.55 macallan ri->ri_ops.putchar = radeonfb_putchar_aa32; 2725 1.55 macallan break; 2726 1.55 macallan case 8: 2727 1.55 macallan ri->ri_ops.putchar = radeonfb_putchar_aa8; 2728 1.55 macallan break; 2729 1.55 macallan default: 2730 1.55 macallan /* XXX this should never happen */ 2731 1.64 macallan panic("%s: depth is not 8 or 32 but we got an" \ 2732 1.64 macallan " alpha font?!", __func__); 2733 1.55 macallan } 2734 1.8 macallan } 2735 1.1 gdamore ri->ri_ops.cursor = radeonfb_cursor; 2736 1.1 gdamore } 2737 1.1 gdamore 2738 1.110 macallan static uint32_t 2739 1.110 macallan radeonfb_avivo_INMC(struct radeonfb_softc *sc, uint32_t addr) 2740 1.110 macallan { 2741 1.110 macallan uint32_t data; 2742 1.110 macallan 2743 1.110 macallan PUT32(sc, AVIVO_MC_INDEX, (addr & 0xff) | 0x7f0000); 2744 1.110 macallan (void)GET32(sc, AVIVO_MC_INDEX); 2745 1.110 macallan data = GET32(sc, AVIVO_MC_DATA); 2746 1.110 macallan PUT32(sc, AVIVO_MC_INDEX, 0); 2747 1.110 macallan (void)GET32(sc, AVIVO_MC_INDEX); 2748 1.110 macallan return data; 2749 1.110 macallan } 2750 1.110 macallan 2751 1.110 macallan static void 2752 1.110 macallan radeonfb_avivo_OUTMC(struct radeonfb_softc *sc, uint32_t addr, uint32_t data) 2753 1.110 macallan { 2754 1.110 macallan 2755 1.110 macallan PUT32(sc, AVIVO_MC_INDEX, (addr & 0xff) | 0x7f0000); 2756 1.110 macallan (void)GET32(sc, AVIVO_MC_INDEX); 2757 1.110 macallan PUT32(sc, AVIVO_MC_DATA, data); 2758 1.110 macallan PUT32(sc, AVIVO_MC_INDEX, 0); 2759 1.110 macallan (void)GET32(sc, AVIVO_MC_INDEX); 2760 1.110 macallan } 2761 1.110 macallan 2762 1.1 gdamore void 2763 1.1 gdamore radeonfb_set_fbloc(struct radeonfb_softc *sc) 2764 1.1 gdamore { 2765 1.110 macallan uint32_t gen = 0, ext = 0, gen2 = 0; 2766 1.1 gdamore uint32_t agploc, aperbase, apersize, mcfbloc; 2767 1.1 gdamore 2768 1.1 gdamore 2769 1.110 macallan if (IS_AVIVO(sc)) { 2770 1.110 macallan agploc = radeonfb_avivo_INMC(sc, R520_MC_AGP_LOCATION); 2771 1.110 macallan } else { 2772 1.110 macallan gen = GET32(sc, RADEON_CRTC_GEN_CNTL); 2773 1.110 macallan /* XXX */ 2774 1.110 macallan ext = GET32(sc, RADEON_CRTC_EXT_CNTL) & ~RADEON_CRTC_DISPLAY_DIS; 2775 1.110 macallan agploc = GET32(sc, RADEON_MC_AGP_LOCATION); 2776 1.110 macallan PUT32(sc, RADEON_CRTC_GEN_CNTL, gen | RADEON_CRTC_DISP_REQ_EN_B); 2777 1.110 macallan PUT32(sc, RADEON_CRTC_EXT_CNTL, ext | RADEON_CRTC_DISPLAY_DIS); 2778 1.64 macallan #if 0 2779 1.110 macallan PUT32(sc, RADEON_CRTC_GEN_CNTL, gen | RADEON_CRTC_DISPLAY_DIS); 2780 1.110 macallan PUT32(sc, RADEON_CRTC_EXT_CNTL, ext | RADEON_CRTC_DISP_REQ_EN_B); 2781 1.64 macallan #endif 2782 1.1 gdamore 2783 1.110 macallan if (HAS_CRTC2(sc)) { 2784 1.110 macallan gen2 = GET32(sc, RADEON_CRTC2_GEN_CNTL); 2785 1.110 macallan PUT32(sc, RADEON_CRTC2_GEN_CNTL, 2786 1.110 macallan gen2 | RADEON_CRTC2_DISP_REQ_EN_B); 2787 1.110 macallan } 2788 1.110 macallan 2789 1.110 macallan delay(100000); 2790 1.1 gdamore } 2791 1.1 gdamore 2792 1.110 macallan aperbase = GET32(sc, RADEON_CONFIG_APER_0_BASE); 2793 1.110 macallan apersize = GET32(sc, RADEON_CONFIG_APER_SIZE); 2794 1.110 macallan 2795 1.1 gdamore 2796 1.1 gdamore mcfbloc = (aperbase >> 16) | 2797 1.1 gdamore ((aperbase + (apersize - 1)) & 0xffff0000); 2798 1.1 gdamore 2799 1.1 gdamore sc->sc_aperbase = (mcfbloc & 0xffff) << 16; 2800 1.1 gdamore sc->sc_memsz = apersize; 2801 1.110 macallan DPRINTF(("aperbase = %08x\n", aperbase)); 2802 1.1 gdamore 2803 1.1 gdamore if (((agploc & 0xffff) << 16) != 2804 1.1 gdamore ((mcfbloc & 0xffff0000U) + 0x10000)) { 2805 1.1 gdamore agploc = mcfbloc & 0xffff0000U; 2806 1.1 gdamore agploc |= ((agploc + 0x10000) >> 16); 2807 1.1 gdamore } 2808 1.1 gdamore 2809 1.1 gdamore PUT32(sc, RADEON_HOST_PATH_CNTL, 0); 2810 1.1 gdamore 2811 1.110 macallan if (IS_AVIVO(sc)) { 2812 1.110 macallan radeonfb_avivo_OUTMC(sc, R520_MC_FB_LOCATION, mcfbloc); 2813 1.110 macallan radeonfb_avivo_OUTMC(sc, R520_MC_AGP_LOCATION, agploc); 2814 1.110 macallan PRINTREG(AVIVO_HDP_FB_LOCATION); 2815 1.110 macallan DPRINTF((" FB loc %08x\n", radeonfb_avivo_INMC(sc, R520_MC_FB_LOCATION))); 2816 1.110 macallan DPRINTF(("AGP loc %08x\n", radeonfb_avivo_INMC(sc, R520_MC_AGP_LOCATION))); 2817 1.110 macallan } else { 2818 1.110 macallan PUT32(sc, RADEON_MC_FB_LOCATION, mcfbloc); 2819 1.110 macallan PUT32(sc, RADEON_MC_AGP_LOCATION, agploc); 2820 1.110 macallan PRINTREG(RADEON_MC_FB_LOCATION); 2821 1.110 macallan PRINTREG(RADEON_MC_AGP_LOCATION); 2822 1.1 gdamore 2823 1.110 macallan PUT32(sc, RADEON_DISPLAY_BASE_ADDR, sc->sc_aperbase); 2824 1.1 gdamore 2825 1.110 macallan if (HAS_CRTC2(sc)) 2826 1.110 macallan PUT32(sc, RADEON_DISPLAY2_BASE_ADDR, sc->sc_aperbase); 2827 1.1 gdamore 2828 1.110 macallan PUT32(sc, RADEON_OV0_BASE_ADDR, sc->sc_aperbase); 2829 1.110 macallan delay(100000); 2830 1.1 gdamore 2831 1.110 macallan PUT32(sc, RADEON_CRTC_GEN_CNTL, gen); 2832 1.110 macallan PUT32(sc, RADEON_CRTC_EXT_CNTL, ext); 2833 1.1 gdamore 2834 1.110 macallan if (HAS_CRTC2(sc)) 2835 1.110 macallan PUT32(sc, RADEON_CRTC2_GEN_CNTL, gen2); 2836 1.110 macallan } 2837 1.1 gdamore #if 0 2838 1.1 gdamore /* XXX: what is this AGP garbage? :-) */ 2839 1.1 gdamore PUT32(sc, RADEON_AGP_CNTL, 0x00100000); 2840 1.1 gdamore #endif 2841 1.1 gdamore } 2842 1.1 gdamore 2843 1.1 gdamore void 2844 1.1 gdamore radeonfb_init_misc(struct radeonfb_softc *sc) 2845 1.1 gdamore { 2846 1.1 gdamore PUT32(sc, RADEON_BUS_CNTL, 2847 1.1 gdamore RADEON_BUS_MASTER_DIS | 2848 1.1 gdamore RADEON_BUS_PREFETCH_MODE_ACT | 2849 1.1 gdamore RADEON_BUS_PCI_READ_RETRY_EN | 2850 1.1 gdamore RADEON_BUS_PCI_WRT_RETRY_EN | 2851 1.1 gdamore (3 << RADEON_BUS_RETRY_WS_SHIFT) | 2852 1.1 gdamore RADEON_BUS_MSTR_RD_MULT | 2853 1.1 gdamore RADEON_BUS_MSTR_RD_LINE | 2854 1.1 gdamore RADEON_BUS_RD_DISCARD_EN | 2855 1.1 gdamore RADEON_BUS_MSTR_DISCONNECT_EN | 2856 1.1 gdamore RADEON_BUS_READ_BURST); 2857 1.1 gdamore 2858 1.1 gdamore PUT32(sc, RADEON_BUS_CNTL1, 0xf0); 2859 1.1 gdamore /* PUT32(sc, RADEON_SEPROM_CNTL1, 0x09ff0000); */ 2860 1.1 gdamore PUT32(sc, RADEON_FCP_CNTL, RADEON_FCP0_SRC_GND); 2861 1.1 gdamore PUT32(sc, RADEON_RBBM_CNTL, 2862 1.1 gdamore (3 << RADEON_RB_SETTLE_SHIFT) | 2863 1.1 gdamore (4 << RADEON_ABORTCLKS_HI_SHIFT) | 2864 1.1 gdamore (4 << RADEON_ABORTCLKS_CP_SHIFT) | 2865 1.1 gdamore (4 << RADEON_ABORTCLKS_CFIFO_SHIFT)); 2866 1.1 gdamore 2867 1.1 gdamore /* XXX: figure out what these mean! */ 2868 1.1 gdamore PUT32(sc, RADEON_AGP_CNTL, 0x00100000); 2869 1.1 gdamore PUT32(sc, RADEON_HOST_PATH_CNTL, 0); 2870 1.64 macallan #if 0 2871 1.64 macallan PUT32(sc, RADEON_DISP_MISC_CNTL, 0x5bb00400); 2872 1.64 macallan #endif 2873 1.1 gdamore 2874 1.1 gdamore PUT32(sc, RADEON_GEN_INT_CNTL, 0); 2875 1.1 gdamore PUT32(sc, RADEON_GEN_INT_STATUS, GET32(sc, RADEON_GEN_INT_STATUS)); 2876 1.1 gdamore } 2877 1.1 gdamore 2878 1.82 macallan static void 2879 1.82 macallan radeonfb_putpal(struct radeonfb_display *dp, int idx, int r, int g, int b) 2880 1.1 gdamore { 2881 1.70 macallan struct radeonfb_softc *sc = dp->rd_softc; 2882 1.82 macallan int crtc, cc; 2883 1.1 gdamore uint32_t vclk; 2884 1.1 gdamore 2885 1.110 macallan if (IS_AVIVO(sc)) { 2886 1.110 macallan for (cc = 0; cc < dp->rd_ncrtcs; cc++) { 2887 1.110 macallan crtc = dp->rd_crtcs[cc].rc_number; 2888 1.1 gdamore 2889 1.110 macallan if (crtc) 2890 1.110 macallan PUT32(sc, AVIVO_DC_LUT_RW_SELECT, 1); 2891 1.110 macallan else 2892 1.110 macallan PUT32(sc, AVIVO_DC_LUT_RW_SELECT, 0); 2893 1.70 macallan 2894 1.110 macallan PUT32(sc, AVIVO_DC_LUT_RW_INDEX, idx); 2895 1.110 macallan PUT32(sc, AVIVO_DC_LUT_30_COLOR, 2896 1.110 macallan (r << 22) | (g << 12) | (b << 2)); 2897 1.110 macallan } 2898 1.110 macallan 2899 1.110 macallan } else { 2900 1.110 macallan vclk = GETPLL(sc, RADEON_VCLK_ECP_CNTL); 2901 1.110 macallan PUTPLL(sc, RADEON_VCLK_ECP_CNTL, 2902 1.110 macallan vclk & ~RADEON_PIXCLK_DAC_ALWAYS_ONb); 2903 1.110 macallan 2904 1.110 macallan /* init the palette for every CRTC used by this display */ 2905 1.110 macallan for (cc = 0; cc < dp->rd_ncrtcs; cc++) { 2906 1.110 macallan crtc = dp->rd_crtcs[cc].rc_number; 2907 1.110 macallan 2908 1.110 macallan if (crtc) 2909 1.110 macallan SET32(sc, RADEON_DAC_CNTL2, 2910 1.110 macallan RADEON_DAC2_PALETTE_ACC_CTL); 2911 1.110 macallan else 2912 1.110 macallan CLR32(sc, RADEON_DAC_CNTL2, 2913 1.110 macallan RADEON_DAC2_PALETTE_ACC_CTL); 2914 1.110 macallan 2915 1.110 macallan PUT32(sc, RADEON_PALETTE_INDEX, idx); 2916 1.110 macallan PUT32(sc, RADEON_PALETTE_30_DATA, 2917 1.110 macallan (r << 22) | (g << 12) | (b << 2)); 2918 1.110 macallan } 2919 1.70 macallan 2920 1.110 macallan PUTPLL(sc, RADEON_VCLK_ECP_CNTL, vclk); 2921 1.82 macallan } 2922 1.82 macallan } 2923 1.82 macallan 2924 1.82 macallan /* 2925 1.82 macallan * This loads a linear color map for true color. 2926 1.82 macallan */ 2927 1.82 macallan void 2928 1.82 macallan radeonfb_init_palette(struct radeonfb_display *dp) 2929 1.82 macallan { 2930 1.82 macallan int i; 2931 1.82 macallan 2932 1.82 macallan #define DAC_WIDTH ((1 << 10) - 1) 2933 1.82 macallan #define CLUT_WIDTH ((1 << 8) - 1) 2934 1.82 macallan #define CLUT_COLOR(i) ((i * DAC_WIDTH * 2 / CLUT_WIDTH + 1) / 2) 2935 1.82 macallan 2936 1.82 macallan if (dp->rd_bpp == 8) { 2937 1.70 macallan 2938 1.82 macallan /* R3G3B2 palette */ 2939 1.82 macallan uint32_t tmp, r, g, b; 2940 1.82 macallan 2941 1.82 macallan for (i = 0; i <= CLUT_WIDTH; ++i) { 2942 1.82 macallan tmp = i & 0xe0; 2943 1.36 macallan 2944 1.82 macallan /* 2945 1.82 macallan * replicate bits so 0xe0 maps to a red value of 0xff 2946 1.82 macallan * in order to make white look actually white 2947 1.82 macallan */ 2948 1.82 macallan tmp |= (tmp >> 3) | (tmp >> 6); 2949 1.82 macallan r = tmp; 2950 1.70 macallan 2951 1.82 macallan tmp = (i & 0x1c) << 3; 2952 1.82 macallan tmp |= (tmp >> 3) | (tmp >> 6); 2953 1.82 macallan g = tmp; 2954 1.82 macallan 2955 1.82 macallan tmp = (i & 0x03) << 6; 2956 1.82 macallan tmp |= tmp >> 2; 2957 1.82 macallan tmp |= tmp >> 4; 2958 1.82 macallan b = tmp; 2959 1.55 macallan 2960 1.113 rin dp->rd_cmap_red[i] = r; 2961 1.113 rin dp->rd_cmap_green[i] = g; 2962 1.113 rin dp->rd_cmap_blue[i] = b; 2963 1.82 macallan radeonfb_putpal(dp, i, r, g, b); 2964 1.82 macallan } 2965 1.82 macallan } else { 2966 1.82 macallan /* linear ramp */ 2967 1.82 macallan for (i = 0; i <= CLUT_WIDTH; ++i) { 2968 1.82 macallan radeonfb_putpal(dp, i, i, i, i); 2969 1.36 macallan } 2970 1.1 gdamore } 2971 1.82 macallan } 2972 1.82 macallan 2973 1.82 macallan static int 2974 1.82 macallan radeonfb_putcmap(struct radeonfb_display *dp, struct wsdisplay_cmap *cm) 2975 1.82 macallan { 2976 1.82 macallan u_char *r, *g, *b; 2977 1.82 macallan u_int index = cm->index; 2978 1.82 macallan u_int count = cm->count; 2979 1.82 macallan int i, error; 2980 1.82 macallan u_char rbuf[256], gbuf[256], bbuf[256]; 2981 1.82 macallan 2982 1.82 macallan #ifdef GENFB_DEBUG 2983 1.82 macallan aprint_debug("putcmap: %d %d\n",index, count); 2984 1.82 macallan #endif 2985 1.94 riastrad if (index >= 256 || count > 256 - index) 2986 1.82 macallan return EINVAL; 2987 1.82 macallan error = copyin(cm->red, &rbuf[index], count); 2988 1.82 macallan if (error) 2989 1.82 macallan return error; 2990 1.82 macallan error = copyin(cm->green, &gbuf[index], count); 2991 1.82 macallan if (error) 2992 1.82 macallan return error; 2993 1.82 macallan error = copyin(cm->blue, &bbuf[index], count); 2994 1.82 macallan if (error) 2995 1.82 macallan return error; 2996 1.82 macallan 2997 1.82 macallan memcpy(&dp->rd_cmap_red[index], &rbuf[index], count); 2998 1.82 macallan memcpy(&dp->rd_cmap_green[index], &gbuf[index], count); 2999 1.82 macallan memcpy(&dp->rd_cmap_blue[index], &bbuf[index], count); 3000 1.82 macallan 3001 1.82 macallan r = &dp->rd_cmap_red[index]; 3002 1.82 macallan g = &dp->rd_cmap_green[index]; 3003 1.82 macallan b = &dp->rd_cmap_blue[index]; 3004 1.82 macallan 3005 1.82 macallan for (i = 0; i < count; i++) { 3006 1.82 macallan radeonfb_putpal(dp, index, *r, *g, *b); 3007 1.82 macallan index++; 3008 1.82 macallan r++, g++, b++; 3009 1.82 macallan } 3010 1.82 macallan return 0; 3011 1.82 macallan } 3012 1.82 macallan 3013 1.82 macallan static int 3014 1.82 macallan radeonfb_getcmap(struct radeonfb_display *dp, struct wsdisplay_cmap *cm) 3015 1.82 macallan { 3016 1.82 macallan u_int index = cm->index; 3017 1.82 macallan u_int count = cm->count; 3018 1.82 macallan int error; 3019 1.82 macallan 3020 1.94 riastrad if (index >= 256 || count > 256 - index) 3021 1.82 macallan return EINVAL; 3022 1.1 gdamore 3023 1.82 macallan error = copyout(&dp->rd_cmap_red[index], cm->red, count); 3024 1.82 macallan if (error) 3025 1.82 macallan return error; 3026 1.82 macallan error = copyout(&dp->rd_cmap_green[index], cm->green, count); 3027 1.82 macallan if (error) 3028 1.82 macallan return error; 3029 1.82 macallan error = copyout(&dp->rd_cmap_blue[index], cm->blue, count); 3030 1.82 macallan if (error) 3031 1.82 macallan return error; 3032 1.1 gdamore 3033 1.82 macallan return 0; 3034 1.1 gdamore } 3035 1.1 gdamore 3036 1.1 gdamore /* 3037 1.1 gdamore * Bugs in some R300 hardware requires this when accessing CLOCK_CNTL_INDEX. 3038 1.1 gdamore */ 3039 1.1 gdamore void 3040 1.1 gdamore radeonfb_r300cg_workaround(struct radeonfb_softc *sc) 3041 1.1 gdamore { 3042 1.1 gdamore uint32_t tmp, save; 3043 1.1 gdamore 3044 1.1 gdamore save = GET32(sc, RADEON_CLOCK_CNTL_INDEX); 3045 1.1 gdamore tmp = save & ~(0x3f | RADEON_PLL_WR_EN); 3046 1.1 gdamore PUT32(sc, RADEON_CLOCK_CNTL_INDEX, tmp); 3047 1.1 gdamore tmp = GET32(sc, RADEON_CLOCK_CNTL_DATA); 3048 1.1 gdamore PUT32(sc, RADEON_CLOCK_CNTL_INDEX, save); 3049 1.1 gdamore } 3050 1.1 gdamore 3051 1.1 gdamore /* 3052 1.1 gdamore * Acceleration entry points. 3053 1.1 gdamore */ 3054 1.49 macallan 3055 1.49 macallan /* this one draws characters using bitmap fonts */ 3056 1.2 macallan static void 3057 1.2 macallan radeonfb_putchar(void *cookie, int row, int col, u_int c, long attr) 3058 1.1 gdamore { 3059 1.1 gdamore struct rasops_info *ri = cookie; 3060 1.1 gdamore struct vcons_screen *scr = ri->ri_hw; 3061 1.1 gdamore struct radeonfb_display *dp = scr->scr_cookie; 3062 1.48 macallan struct radeonfb_softc *sc = dp->rd_softc; 3063 1.35 macallan struct wsdisplay_font *font = PICK_FONT(ri, c); 3064 1.48 macallan uint32_t w, h; 3065 1.48 macallan int xd, yd, offset, i; 3066 1.48 macallan uint32_t bg, fg, gmc; 3067 1.48 macallan uint32_t reg; 3068 1.48 macallan uint8_t *data8; 3069 1.48 macallan uint16_t *data16; 3070 1.105 rin uint32_t *data32; 3071 1.48 macallan void *data; 3072 1.1 gdamore 3073 1.1 gdamore if (dp->rd_wsmode != WSDISPLAYIO_MODE_EMUL) 3074 1.1 gdamore return; 3075 1.1 gdamore 3076 1.35 macallan if (!CHAR_IN_FONT(c, font)) 3077 1.1 gdamore return; 3078 1.1 gdamore 3079 1.35 macallan w = font->fontwidth; 3080 1.35 macallan h = font->fontheight; 3081 1.1 gdamore 3082 1.48 macallan bg = ri->ri_devcmap[(attr >> 16) & 0xf]; 3083 1.48 macallan fg = ri->ri_devcmap[(attr >> 24) & 0xf]; 3084 1.48 macallan 3085 1.48 macallan xd = ri->ri_xorigin + col * w; 3086 1.48 macallan yd = ri->ri_yorigin + row * h; 3087 1.48 macallan 3088 1.48 macallan if (c == 0x20) { 3089 1.48 macallan radeonfb_rectfill(dp, xd, yd, w, h, bg); 3090 1.48 macallan return; 3091 1.35 macallan } 3092 1.50 macallan data = WSFONT_GLYPH(c, font); 3093 1.1 gdamore 3094 1.48 macallan gmc = dp->rd_format << RADEON_GMC_DST_DATATYPE_SHIFT; 3095 1.1 gdamore 3096 1.48 macallan radeonfb_wait_fifo(sc, 9); 3097 1.48 macallan 3098 1.48 macallan PUT32(sc, RADEON_DP_GUI_MASTER_CNTL, 3099 1.48 macallan RADEON_GMC_BRUSH_NONE | 3100 1.48 macallan RADEON_GMC_SRC_DATATYPE_MONO_FG_BG | 3101 1.48 macallan RADEON_GMC_DST_CLIPPING | 3102 1.48 macallan RADEON_ROP3_S | 3103 1.48 macallan RADEON_DP_SRC_SOURCE_HOST_DATA | 3104 1.48 macallan RADEON_GMC_CLR_CMP_CNTL_DIS | 3105 1.48 macallan RADEON_GMC_WR_MSK_DIS | 3106 1.48 macallan gmc); 3107 1.48 macallan 3108 1.48 macallan PUT32(sc, RADEON_SC_LEFT, xd); 3109 1.48 macallan PUT32(sc, RADEON_SC_RIGHT, xd + w); 3110 1.48 macallan PUT32(sc, RADEON_DP_SRC_FRGD_CLR, fg); 3111 1.48 macallan PUT32(sc, RADEON_DP_SRC_BKGD_CLR, bg); 3112 1.48 macallan PUT32(sc, RADEON_DP_CNTL, 3113 1.48 macallan RADEON_DST_X_LEFT_TO_RIGHT | 3114 1.48 macallan RADEON_DST_Y_TOP_TO_BOTTOM); 3115 1.1 gdamore 3116 1.48 macallan PUT32(sc, RADEON_SRC_X_Y, 0); 3117 1.48 macallan offset = 32 - (font->stride << 3); 3118 1.48 macallan PUT32(sc, RADEON_DST_X_Y, ((xd - offset) << 16) | yd); 3119 1.48 macallan PUT32(sc, RADEON_DST_WIDTH_HEIGHT, (32 << 16) | h); 3120 1.48 macallan 3121 1.48 macallan radeonfb_wait_fifo(sc, h); 3122 1.48 macallan switch (font->stride) { 3123 1.48 macallan case 1: { 3124 1.48 macallan data8 = data; 3125 1.48 macallan for (i = 0; i < h; i++) { 3126 1.48 macallan reg = *data8; 3127 1.67 macallan #if BYTE_ORDER == LITTLE_ENDIAN 3128 1.67 macallan reg = reg << 24; 3129 1.67 macallan #endif 3130 1.49 macallan bus_space_write_stream_4(sc->sc_regt, 3131 1.48 macallan sc->sc_regh, RADEON_HOST_DATA0, reg); 3132 1.48 macallan data8++; 3133 1.48 macallan } 3134 1.48 macallan break; 3135 1.48 macallan } 3136 1.48 macallan case 2: { 3137 1.48 macallan data16 = data; 3138 1.48 macallan for (i = 0; i < h; i++) { 3139 1.48 macallan reg = *data16; 3140 1.67 macallan #if BYTE_ORDER == LITTLE_ENDIAN 3141 1.67 macallan reg = reg << 16; 3142 1.67 macallan #endif 3143 1.49 macallan bus_space_write_stream_4(sc->sc_regt, 3144 1.48 macallan sc->sc_regh, RADEON_HOST_DATA0, reg); 3145 1.48 macallan data16++; 3146 1.48 macallan } 3147 1.48 macallan break; 3148 1.48 macallan } 3149 1.105 rin case 4: { 3150 1.105 rin data32 = data; 3151 1.105 rin for (i = 0; i < h; i++) { 3152 1.105 rin reg = *data32; 3153 1.105 rin bus_space_write_stream_4(sc->sc_regt, 3154 1.105 rin sc->sc_regh, RADEON_HOST_DATA0, reg); 3155 1.105 rin data32++; 3156 1.105 rin } 3157 1.105 rin break; 3158 1.105 rin } 3159 1.1 gdamore } 3160 1.64 macallan if (attr & 1) 3161 1.64 macallan radeonfb_rectfill(dp, xd, yd + h - 2, w, 1, fg); 3162 1.1 gdamore } 3163 1.1 gdamore 3164 1.49 macallan /* ... while this one is for anti-aliased ones */ 3165 1.49 macallan static void 3166 1.49 macallan radeonfb_putchar_aa32(void *cookie, int row, int col, u_int c, long attr) 3167 1.49 macallan { 3168 1.49 macallan struct rasops_info *ri = cookie; 3169 1.49 macallan struct vcons_screen *scr = ri->ri_hw; 3170 1.49 macallan struct radeonfb_display *dp = scr->scr_cookie; 3171 1.49 macallan struct radeonfb_softc *sc = dp->rd_softc; 3172 1.49 macallan struct wsdisplay_font *font = PICK_FONT(ri, c); 3173 1.49 macallan uint32_t bg, fg, gmc; 3174 1.49 macallan uint8_t *data; 3175 1.49 macallan int w, h, xd, yd; 3176 1.49 macallan int i, r, g, b, aval; 3177 1.49 macallan int rf, gf, bf, rb, gb, bb; 3178 1.49 macallan uint32_t pixel; 3179 1.54 macallan int rv; 3180 1.49 macallan 3181 1.49 macallan if (dp->rd_wsmode != WSDISPLAYIO_MODE_EMUL) 3182 1.49 macallan return; 3183 1.49 macallan 3184 1.49 macallan if (!CHAR_IN_FONT(c, font)) 3185 1.49 macallan return; 3186 1.49 macallan 3187 1.49 macallan w = font->fontwidth; 3188 1.49 macallan h = font->fontheight; 3189 1.49 macallan 3190 1.49 macallan bg = ri->ri_devcmap[(attr >> 16) & 0xf]; 3191 1.49 macallan fg = ri->ri_devcmap[(attr >> 24) & 0xf]; 3192 1.49 macallan 3193 1.49 macallan xd = ri->ri_xorigin + col * w; 3194 1.49 macallan yd = ri->ri_yorigin + row * h; 3195 1.49 macallan 3196 1.49 macallan if (c == 0x20) { 3197 1.49 macallan radeonfb_rectfill(dp, xd, yd, w, h, bg); 3198 1.64 macallan if (attr & 1) 3199 1.64 macallan radeonfb_rectfill(dp, xd, yd + h - 2, w, 1, fg); 3200 1.49 macallan return; 3201 1.49 macallan } 3202 1.54 macallan rv = glyphcache_try(&dp->rd_gc, c, xd, yd, attr); 3203 1.54 macallan if (rv == GC_OK) 3204 1.54 macallan return; 3205 1.54 macallan 3206 1.50 macallan data = WSFONT_GLYPH(c, font); 3207 1.49 macallan 3208 1.49 macallan gmc = dp->rd_format << RADEON_GMC_DST_DATATYPE_SHIFT; 3209 1.49 macallan 3210 1.49 macallan radeonfb_wait_fifo(sc, 5); 3211 1.49 macallan 3212 1.49 macallan PUT32(sc, RADEON_DP_GUI_MASTER_CNTL, 3213 1.49 macallan RADEON_GMC_BRUSH_NONE | 3214 1.49 macallan RADEON_GMC_SRC_DATATYPE_COLOR | 3215 1.49 macallan RADEON_ROP3_S | 3216 1.49 macallan RADEON_DP_SRC_SOURCE_HOST_DATA | 3217 1.49 macallan RADEON_GMC_CLR_CMP_CNTL_DIS | 3218 1.49 macallan RADEON_GMC_WR_MSK_DIS | 3219 1.49 macallan gmc); 3220 1.49 macallan 3221 1.49 macallan PUT32(sc, RADEON_DP_CNTL, 3222 1.49 macallan RADEON_DST_X_LEFT_TO_RIGHT | 3223 1.49 macallan RADEON_DST_Y_TOP_TO_BOTTOM); 3224 1.49 macallan 3225 1.49 macallan PUT32(sc, RADEON_SRC_X_Y, 0); 3226 1.49 macallan PUT32(sc, RADEON_DST_X_Y, (xd << 16) | yd); 3227 1.49 macallan PUT32(sc, RADEON_DST_WIDTH_HEIGHT, (w << 16) | h); 3228 1.49 macallan 3229 1.49 macallan rf = (fg >> 16) & 0xff; 3230 1.49 macallan rb = (bg >> 16) & 0xff; 3231 1.49 macallan gf = (fg >> 8) & 0xff; 3232 1.49 macallan gb = (bg >> 8) & 0xff; 3233 1.49 macallan bf = fg & 0xff; 3234 1.49 macallan bb = bg & 0xff; 3235 1.49 macallan 3236 1.49 macallan /* 3237 1.49 macallan * I doubt we can upload data faster than even the slowest Radeon 3238 1.49 macallan * could process them, especially when doing the alpha blending stuff 3239 1.49 macallan * along the way, so just make sure there's some room in the FIFO and 3240 1.49 macallan * then hammer away 3241 1.51 macallan * As it turns out we can, so make periodic stops to let the FIFO 3242 1.51 macallan * drain. 3243 1.49 macallan */ 3244 1.51 macallan radeonfb_wait_fifo(sc, 20); 3245 1.49 macallan for (i = 0; i < ri->ri_fontscale; i++) { 3246 1.49 macallan aval = *data; 3247 1.49 macallan data++; 3248 1.49 macallan if (aval == 0) { 3249 1.49 macallan pixel = bg; 3250 1.49 macallan } else if (aval == 255) { 3251 1.49 macallan pixel = fg; 3252 1.49 macallan } else { 3253 1.49 macallan r = aval * rf + (255 - aval) * rb; 3254 1.49 macallan g = aval * gf + (255 - aval) * gb; 3255 1.49 macallan b = aval * bf + (255 - aval) * bb; 3256 1.49 macallan pixel = (r & 0xff00) << 8 | 3257 1.49 macallan (g & 0xff00) | 3258 1.49 macallan (b & 0xff00) >> 8; 3259 1.49 macallan } 3260 1.51 macallan if (i & 16) 3261 1.51 macallan radeonfb_wait_fifo(sc, 20); 3262 1.49 macallan PUT32(sc, RADEON_HOST_DATA0, pixel); 3263 1.49 macallan } 3264 1.64 macallan if (rv == GC_ADD) { 3265 1.54 macallan glyphcache_add(&dp->rd_gc, c, xd, yd); 3266 1.96 macallan } else if (attr & 1) 3267 1.96 macallan radeonfb_rectfill(dp, xd, yd + h - 2, w, 1, fg); 3268 1.49 macallan } 3269 1.49 macallan 3270 1.55 macallan static void 3271 1.55 macallan radeonfb_putchar_aa8(void *cookie, int row, int col, u_int c, long attr) 3272 1.55 macallan { 3273 1.55 macallan struct rasops_info *ri = cookie; 3274 1.55 macallan struct vcons_screen *scr = ri->ri_hw; 3275 1.55 macallan struct radeonfb_display *dp = scr->scr_cookie; 3276 1.55 macallan struct radeonfb_softc *sc = dp->rd_softc; 3277 1.55 macallan struct wsdisplay_font *font = PICK_FONT(ri, c); 3278 1.64 macallan uint32_t bg, fg, latch = 0, bg8, fg8, pixel, gmc; 3279 1.55 macallan int i, x, y, wi, he, r, g, b, aval; 3280 1.55 macallan int r1, g1, b1, r0, g0, b0, fgo, bgo; 3281 1.55 macallan uint8_t *data8; 3282 1.57 macallan int rv, cnt; 3283 1.55 macallan 3284 1.55 macallan if (dp->rd_wsmode != WSDISPLAYIO_MODE_EMUL) 3285 1.55 macallan return; 3286 1.55 macallan 3287 1.55 macallan if (!CHAR_IN_FONT(c, font)) 3288 1.55 macallan return; 3289 1.55 macallan 3290 1.55 macallan wi = font->fontwidth; 3291 1.55 macallan he = font->fontheight; 3292 1.55 macallan 3293 1.55 macallan bg = ri->ri_devcmap[(attr >> 16) & 0xf]; 3294 1.64 macallan fg = ri->ri_devcmap[(attr >> 24) & 0xf]; 3295 1.55 macallan 3296 1.55 macallan x = ri->ri_xorigin + col * wi; 3297 1.55 macallan y = ri->ri_yorigin + row * he; 3298 1.55 macallan 3299 1.55 macallan if (c == 0x20) { 3300 1.55 macallan radeonfb_rectfill(dp, x, y, wi, he, bg); 3301 1.64 macallan if (attr & 1) 3302 1.64 macallan radeonfb_rectfill(dp, x, y + he - 2, wi, 1, fg); 3303 1.55 macallan return; 3304 1.55 macallan } 3305 1.55 macallan rv = glyphcache_try(&dp->rd_gc, c, x, y, attr); 3306 1.55 macallan if (rv == GC_OK) 3307 1.55 macallan return; 3308 1.55 macallan 3309 1.55 macallan data8 = WSFONT_GLYPH(c, font); 3310 1.55 macallan 3311 1.55 macallan gmc = dp->rd_format << RADEON_GMC_DST_DATATYPE_SHIFT; 3312 1.55 macallan 3313 1.55 macallan radeonfb_wait_fifo(sc, 5); 3314 1.55 macallan 3315 1.55 macallan PUT32(sc, RADEON_DP_GUI_MASTER_CNTL, 3316 1.55 macallan RADEON_GMC_BRUSH_NONE | 3317 1.55 macallan RADEON_GMC_SRC_DATATYPE_COLOR | 3318 1.55 macallan RADEON_ROP3_S | 3319 1.55 macallan RADEON_DP_SRC_SOURCE_HOST_DATA | 3320 1.55 macallan RADEON_GMC_CLR_CMP_CNTL_DIS | 3321 1.55 macallan RADEON_GMC_WR_MSK_DIS | 3322 1.55 macallan gmc); 3323 1.55 macallan 3324 1.55 macallan PUT32(sc, RADEON_DP_CNTL, 3325 1.55 macallan RADEON_DST_X_LEFT_TO_RIGHT | 3326 1.55 macallan RADEON_DST_Y_TOP_TO_BOTTOM); 3327 1.55 macallan 3328 1.55 macallan PUT32(sc, RADEON_SRC_X_Y, 0); 3329 1.55 macallan PUT32(sc, RADEON_DST_X_Y, (x << 16) | y); 3330 1.55 macallan PUT32(sc, RADEON_DST_WIDTH_HEIGHT, (wi << 16) | he); 3331 1.55 macallan 3332 1.55 macallan /* 3333 1.55 macallan * we need the RGB colours here, so get offsets into rasops_cmap 3334 1.55 macallan */ 3335 1.55 macallan fgo = ((attr >> 24) & 0xf) * 3; 3336 1.55 macallan bgo = ((attr >> 16) & 0xf) * 3; 3337 1.55 macallan 3338 1.55 macallan r0 = rasops_cmap[bgo]; 3339 1.55 macallan r1 = rasops_cmap[fgo]; 3340 1.55 macallan g0 = rasops_cmap[bgo + 1]; 3341 1.55 macallan g1 = rasops_cmap[fgo + 1]; 3342 1.55 macallan b0 = rasops_cmap[bgo + 2]; 3343 1.55 macallan b1 = rasops_cmap[fgo + 2]; 3344 1.55 macallan #define R3G3B2(r, g, b) ((r & 0xe0) | ((g >> 3) & 0x1c) | (b >> 6)) 3345 1.55 macallan bg8 = R3G3B2(r0, g0, b0); 3346 1.55 macallan fg8 = R3G3B2(r1, g1, b1); 3347 1.57 macallan 3348 1.57 macallan radeonfb_wait_fifo(sc, 20); 3349 1.57 macallan cnt = 0; 3350 1.55 macallan for (i = 0; i < ri->ri_fontscale; i++) { 3351 1.55 macallan aval = *data8; 3352 1.55 macallan if (aval == 0) { 3353 1.55 macallan pixel = bg8; 3354 1.55 macallan } else if (aval == 255) { 3355 1.55 macallan pixel = fg8; 3356 1.55 macallan } else { 3357 1.55 macallan r = aval * r1 + (255 - aval) * r0; 3358 1.55 macallan g = aval * g1 + (255 - aval) * g0; 3359 1.55 macallan b = aval * b1 + (255 - aval) * b0; 3360 1.55 macallan pixel = ((r & 0xe000) >> 8) | 3361 1.55 macallan ((g & 0xe000) >> 11) | 3362 1.55 macallan ((b & 0xc000) >> 14); 3363 1.55 macallan } 3364 1.67 macallan latch |= pixel << (8 * (i & 3)); 3365 1.55 macallan /* write in 32bit chunks */ 3366 1.55 macallan if ((i & 3) == 3) { 3367 1.67 macallan PUT32(sc, RADEON_HOST_DATA0, latch); 3368 1.55 macallan /* 3369 1.55 macallan * not strictly necessary, old data should be shifted 3370 1.55 macallan * out 3371 1.55 macallan */ 3372 1.55 macallan latch = 0; 3373 1.57 macallan cnt++; 3374 1.57 macallan if (cnt > 16) { 3375 1.57 macallan cnt = 0; 3376 1.57 macallan radeonfb_wait_fifo(sc, 20); 3377 1.57 macallan } 3378 1.55 macallan } 3379 1.55 macallan data8++; 3380 1.55 macallan } 3381 1.55 macallan /* if we have pixels left in latch write them out */ 3382 1.55 macallan if ((i & 3) != 0) { 3383 1.60 macallan /* 3384 1.60 macallan * radeon is weird - apparently leftover pixels are written 3385 1.60 macallan * from the middle, not from the left as everything else 3386 1.60 macallan */ 3387 1.55 macallan PUT32(sc, RADEON_HOST_DATA0, latch); 3388 1.55 macallan } 3389 1.55 macallan 3390 1.64 macallan if (rv == GC_ADD) { 3391 1.55 macallan glyphcache_add(&dp->rd_gc, c, x, y); 3392 1.64 macallan } else 3393 1.64 macallan if (attr & 1) 3394 1.64 macallan radeonfb_rectfill(dp, x, y + he - 2, wi, 1, fg); 3395 1.55 macallan } 3396 1.55 macallan 3397 1.38 macallan /* 3398 1.38 macallan * wrapper for software character drawing 3399 1.38 macallan * just sync the engine and call rasops*_putchar() 3400 1.38 macallan */ 3401 1.38 macallan 3402 1.73 macallan #ifndef RADEONFB_ALWAYS_ACCEL_PUTCHAR 3403 1.38 macallan static void 3404 1.38 macallan radeonfb_putchar_wrapper(void *cookie, int row, int col, u_int c, long attr) 3405 1.38 macallan { 3406 1.38 macallan struct rasops_info *ri = cookie; 3407 1.38 macallan struct vcons_screen *scr = ri->ri_hw; 3408 1.38 macallan struct radeonfb_display *dp = scr->scr_cookie; 3409 1.38 macallan 3410 1.38 macallan radeonfb_engine_idle(dp->rd_softc); 3411 1.38 macallan dp->rd_putchar(ri, row, col, c, attr); 3412 1.38 macallan } 3413 1.73 macallan #endif 3414 1.38 macallan 3415 1.2 macallan static void 3416 1.1 gdamore radeonfb_eraserows(void *cookie, int row, int nrows, long fillattr) 3417 1.1 gdamore { 3418 1.1 gdamore struct rasops_info *ri = cookie; 3419 1.1 gdamore struct vcons_screen *scr = ri->ri_hw; 3420 1.1 gdamore struct radeonfb_display *dp = scr->scr_cookie; 3421 1.1 gdamore uint32_t x, y, w, h, fg, bg, ul; 3422 1.1 gdamore 3423 1.1 gdamore /* XXX: check for full emulation mode? */ 3424 1.1 gdamore if (dp->rd_wsmode == WSDISPLAYIO_MODE_EMUL) { 3425 1.1 gdamore x = ri->ri_xorigin; 3426 1.1 gdamore y = ri->ri_yorigin + ri->ri_font->fontheight * row; 3427 1.1 gdamore w = ri->ri_emuwidth; 3428 1.1 gdamore h = ri->ri_font->fontheight * nrows; 3429 1.1 gdamore 3430 1.1 gdamore rasops_unpack_attr(fillattr, &fg, &bg, &ul); 3431 1.2 macallan radeonfb_rectfill(dp, x, y, w, h, ri->ri_devcmap[bg & 0xf]); 3432 1.1 gdamore } 3433 1.1 gdamore } 3434 1.1 gdamore 3435 1.2 macallan static void 3436 1.1 gdamore radeonfb_copyrows(void *cookie, int srcrow, int dstrow, int nrows) 3437 1.1 gdamore { 3438 1.1 gdamore struct rasops_info *ri = cookie; 3439 1.1 gdamore struct vcons_screen *scr = ri->ri_hw; 3440 1.1 gdamore struct radeonfb_display *dp = scr->scr_cookie; 3441 1.1 gdamore uint32_t x, ys, yd, w, h; 3442 1.1 gdamore 3443 1.1 gdamore if (dp->rd_wsmode == WSDISPLAYIO_MODE_EMUL) { 3444 1.1 gdamore x = ri->ri_xorigin; 3445 1.1 gdamore ys = ri->ri_yorigin + ri->ri_font->fontheight * srcrow; 3446 1.1 gdamore yd = ri->ri_yorigin + ri->ri_font->fontheight * dstrow; 3447 1.1 gdamore w = ri->ri_emuwidth; 3448 1.1 gdamore h = ri->ri_font->fontheight * nrows; 3449 1.1 gdamore radeonfb_bitblt(dp, x, ys, x, yd, w, h, 3450 1.54 macallan RADEON_ROP3_S); 3451 1.1 gdamore } 3452 1.1 gdamore } 3453 1.1 gdamore 3454 1.2 macallan static void 3455 1.1 gdamore radeonfb_copycols(void *cookie, int row, int srccol, int dstcol, int ncols) 3456 1.1 gdamore { 3457 1.1 gdamore struct rasops_info *ri = cookie; 3458 1.1 gdamore struct vcons_screen *scr = ri->ri_hw; 3459 1.1 gdamore struct radeonfb_display *dp = scr->scr_cookie; 3460 1.1 gdamore uint32_t xs, xd, y, w, h; 3461 1.1 gdamore 3462 1.1 gdamore if (dp->rd_wsmode == WSDISPLAYIO_MODE_EMUL) { 3463 1.1 gdamore xs = ri->ri_xorigin + ri->ri_font->fontwidth * srccol; 3464 1.1 gdamore xd = ri->ri_xorigin + ri->ri_font->fontwidth * dstcol; 3465 1.1 gdamore y = ri->ri_yorigin + ri->ri_font->fontheight * row; 3466 1.1 gdamore w = ri->ri_font->fontwidth * ncols; 3467 1.1 gdamore h = ri->ri_font->fontheight; 3468 1.1 gdamore radeonfb_bitblt(dp, xs, y, xd, y, w, h, 3469 1.54 macallan RADEON_ROP3_S); 3470 1.1 gdamore } 3471 1.1 gdamore } 3472 1.1 gdamore 3473 1.2 macallan static void 3474 1.1 gdamore radeonfb_erasecols(void *cookie, int row, int startcol, int ncols, 3475 1.1 gdamore long fillattr) 3476 1.1 gdamore { 3477 1.1 gdamore struct rasops_info *ri = cookie; 3478 1.1 gdamore struct vcons_screen *scr = ri->ri_hw; 3479 1.1 gdamore struct radeonfb_display *dp = scr->scr_cookie; 3480 1.1 gdamore uint32_t x, y, w, h, fg, bg, ul; 3481 1.1 gdamore 3482 1.1 gdamore if (dp->rd_wsmode == WSDISPLAYIO_MODE_EMUL) { 3483 1.1 gdamore x = ri->ri_xorigin + ri->ri_font->fontwidth * startcol; 3484 1.1 gdamore y = ri->ri_yorigin + ri->ri_font->fontheight * row; 3485 1.1 gdamore w = ri->ri_font->fontwidth * ncols; 3486 1.1 gdamore h = ri->ri_font->fontheight; 3487 1.1 gdamore 3488 1.1 gdamore rasops_unpack_attr(fillattr, &fg, &bg, &ul); 3489 1.2 macallan radeonfb_rectfill(dp, x, y, w, h, ri->ri_devcmap[bg & 0xf]); 3490 1.1 gdamore } 3491 1.1 gdamore } 3492 1.1 gdamore 3493 1.2 macallan static void 3494 1.1 gdamore radeonfb_cursor(void *cookie, int on, int row, int col) 3495 1.1 gdamore { 3496 1.1 gdamore struct rasops_info *ri = cookie; 3497 1.1 gdamore struct vcons_screen *scr = ri->ri_hw; 3498 1.1 gdamore struct radeonfb_display *dp = scr->scr_cookie; 3499 1.1 gdamore int x, y, wi, he; 3500 1.11 ad 3501 1.1 gdamore wi = ri->ri_font->fontwidth; 3502 1.1 gdamore he = ri->ri_font->fontheight; 3503 1.11 ad 3504 1.1 gdamore if (dp->rd_wsmode == WSDISPLAYIO_MODE_EMUL) { 3505 1.1 gdamore x = ri->ri_ccol * wi + ri->ri_xorigin; 3506 1.1 gdamore y = ri->ri_crow * he + ri->ri_yorigin; 3507 1.1 gdamore /* first turn off the old cursor */ 3508 1.1 gdamore if (ri->ri_flg & RI_CURSOR) { 3509 1.1 gdamore radeonfb_bitblt(dp, x, y, x, y, wi, he, 3510 1.54 macallan RADEON_ROP3_Dn); 3511 1.1 gdamore ri->ri_flg &= ~RI_CURSOR; 3512 1.1 gdamore } 3513 1.1 gdamore ri->ri_crow = row; 3514 1.1 gdamore ri->ri_ccol = col; 3515 1.1 gdamore /* then (possibly) turn on the new one */ 3516 1.1 gdamore if (on) { 3517 1.1 gdamore x = ri->ri_ccol * wi + ri->ri_xorigin; 3518 1.1 gdamore y = ri->ri_crow * he + ri->ri_yorigin; 3519 1.1 gdamore radeonfb_bitblt(dp, x, y, x, y, wi, he, 3520 1.54 macallan RADEON_ROP3_Dn); 3521 1.2 macallan ri->ri_flg |= RI_CURSOR; 3522 1.1 gdamore } 3523 1.1 gdamore } else { 3524 1.1 gdamore scr->scr_ri.ri_crow = row; 3525 1.1 gdamore scr->scr_ri.ri_ccol = col; 3526 1.1 gdamore scr->scr_ri.ri_flg &= ~RI_CURSOR; 3527 1.1 gdamore } 3528 1.1 gdamore } 3529 1.1 gdamore 3530 1.1 gdamore /* 3531 1.1 gdamore * Underlying acceleration support. 3532 1.1 gdamore */ 3533 1.1 gdamore 3534 1.2 macallan static void 3535 1.2 macallan radeonfb_rectfill(struct radeonfb_display *dp, int dstx, int dsty, 3536 1.1 gdamore int width, int height, uint32_t color) 3537 1.1 gdamore { 3538 1.1 gdamore struct radeonfb_softc *sc = dp->rd_softc; 3539 1.1 gdamore uint32_t gmc; 3540 1.1 gdamore 3541 1.1 gdamore gmc = dp->rd_format << RADEON_GMC_DST_DATATYPE_SHIFT; 3542 1.1 gdamore 3543 1.1 gdamore radeonfb_wait_fifo(sc, 6); 3544 1.1 gdamore 3545 1.1 gdamore PUT32(sc, RADEON_DP_GUI_MASTER_CNTL, 3546 1.1 gdamore RADEON_GMC_BRUSH_SOLID_COLOR | 3547 1.1 gdamore RADEON_GMC_SRC_DATATYPE_COLOR | 3548 1.1 gdamore RADEON_GMC_CLR_CMP_CNTL_DIS | 3549 1.1 gdamore RADEON_ROP3_P | gmc); 3550 1.1 gdamore 3551 1.1 gdamore PUT32(sc, RADEON_DP_BRUSH_FRGD_CLR, color); 3552 1.1 gdamore PUT32(sc, RADEON_DP_WRITE_MASK, 0xffffffff); 3553 1.1 gdamore PUT32(sc, RADEON_DP_CNTL, 3554 1.1 gdamore RADEON_DST_X_LEFT_TO_RIGHT | 3555 1.1 gdamore RADEON_DST_Y_TOP_TO_BOTTOM); 3556 1.1 gdamore PUT32(sc, RADEON_DST_Y_X, (dsty << 16) | dstx); 3557 1.1 gdamore PUT32(sc, RADEON_DST_WIDTH_HEIGHT, (width << 16) | (height)); 3558 1.1 gdamore } 3559 1.1 gdamore 3560 1.2 macallan static void 3561 1.64 macallan radeonfb_rectfill_a(void *cookie, int dstx, int dsty, 3562 1.64 macallan int width, int height, long attr) 3563 1.64 macallan { 3564 1.64 macallan struct radeonfb_display *dp = cookie; 3565 1.64 macallan 3566 1.64 macallan radeonfb_rectfill(dp, dstx, dsty, width, height, 3567 1.64 macallan dp->rd_vscreen.scr_ri.ri_devcmap[(attr >> 24 & 0xf)]); 3568 1.64 macallan } 3569 1.64 macallan 3570 1.64 macallan static void 3571 1.54 macallan radeonfb_bitblt(void *cookie, int srcx, int srcy, 3572 1.54 macallan int dstx, int dsty, int width, int height, int rop) 3573 1.1 gdamore { 3574 1.54 macallan struct radeonfb_display *dp = cookie; 3575 1.1 gdamore struct radeonfb_softc *sc = dp->rd_softc; 3576 1.1 gdamore uint32_t gmc; 3577 1.1 gdamore uint32_t dir; 3578 1.1 gdamore 3579 1.1 gdamore if (dsty < srcy) { 3580 1.1 gdamore dir = RADEON_DST_Y_TOP_TO_BOTTOM; 3581 1.1 gdamore } else { 3582 1.1 gdamore srcy += height - 1; 3583 1.1 gdamore dsty += height - 1; 3584 1.1 gdamore dir = 0; 3585 1.1 gdamore } 3586 1.6 gdamore if (dstx < srcx) { 3587 1.1 gdamore dir |= RADEON_DST_X_LEFT_TO_RIGHT; 3588 1.1 gdamore } else { 3589 1.1 gdamore srcx += width - 1; 3590 1.1 gdamore dstx += width - 1; 3591 1.1 gdamore } 3592 1.1 gdamore 3593 1.1 gdamore gmc = dp->rd_format << RADEON_GMC_DST_DATATYPE_SHIFT; 3594 1.11 ad 3595 1.1 gdamore radeonfb_wait_fifo(sc, 6); 3596 1.1 gdamore 3597 1.1 gdamore PUT32(sc, RADEON_DP_GUI_MASTER_CNTL, 3598 1.110 macallan RADEON_GMC_BRUSH_NONE | 3599 1.1 gdamore RADEON_GMC_SRC_DATATYPE_COLOR | 3600 1.1 gdamore RADEON_GMC_CLR_CMP_CNTL_DIS | 3601 1.1 gdamore RADEON_DP_SRC_SOURCE_MEMORY | 3602 1.1 gdamore rop | gmc); 3603 1.1 gdamore 3604 1.54 macallan PUT32(sc, RADEON_DP_WRITE_MASK, 0xffffffff); 3605 1.1 gdamore PUT32(sc, RADEON_DP_CNTL, dir); 3606 1.1 gdamore PUT32(sc, RADEON_SRC_Y_X, (srcy << 16) | srcx); 3607 1.1 gdamore PUT32(sc, RADEON_DST_Y_X, (dsty << 16) | dstx); 3608 1.1 gdamore PUT32(sc, RADEON_DST_WIDTH_HEIGHT, (width << 16) | (height)); 3609 1.1 gdamore } 3610 1.1 gdamore 3611 1.2 macallan static void 3612 1.1 gdamore radeonfb_engine_idle(struct radeonfb_softc *sc) 3613 1.1 gdamore { 3614 1.1 gdamore 3615 1.1 gdamore radeonfb_wait_fifo(sc, 64); 3616 1.48 macallan while ((GET32(sc, RADEON_RBBM_STATUS) & 3617 1.48 macallan RADEON_RBBM_ACTIVE) != 0); 3618 1.48 macallan radeonfb_engine_flush(sc); 3619 1.1 gdamore } 3620 1.1 gdamore 3621 1.55 macallan static inline void 3622 1.1 gdamore radeonfb_wait_fifo(struct radeonfb_softc *sc, int n) 3623 1.1 gdamore { 3624 1.1 gdamore int i; 3625 1.1 gdamore 3626 1.1 gdamore for (i = RADEON_TIMEOUT; i; i--) { 3627 1.1 gdamore if ((GET32(sc, RADEON_RBBM_STATUS) & 3628 1.1 gdamore RADEON_RBBM_FIFOCNT_MASK) >= n) 3629 1.1 gdamore return; 3630 1.1 gdamore } 3631 1.110 macallan #ifdef RADEONFB_DEBUG 3632 1.1 gdamore if (!i) 3633 1.1 gdamore printf("%s: timed out waiting for fifo (%x)\n", 3634 1.1 gdamore XNAME(sc), GET32(sc, RADEON_RBBM_STATUS)); 3635 1.1 gdamore #endif 3636 1.1 gdamore } 3637 1.1 gdamore 3638 1.2 macallan static void 3639 1.1 gdamore radeonfb_engine_flush(struct radeonfb_softc *sc) 3640 1.1 gdamore { 3641 1.48 macallan int i = 0; 3642 1.48 macallan 3643 1.110 macallan if (IS_R300(sc) || IS_AVIVO(sc)) { 3644 1.48 macallan SET32(sc, R300_DSTCACHE_CTLSTAT, R300_RB2D_DC_FLUSH_ALL); 3645 1.48 macallan while (GET32(sc, R300_DSTCACHE_CTLSTAT) & R300_RB2D_DC_BUSY) { 3646 1.48 macallan i++; 3647 1.48 macallan } 3648 1.48 macallan } else { 3649 1.48 macallan SET32(sc, RADEON_RB2D_DSTCACHE_CTLSTAT, 3650 1.48 macallan RADEON_RB2D_DC_FLUSH_ALL); 3651 1.48 macallan while (GET32(sc, RADEON_RB2D_DSTCACHE_CTLSTAT) & 3652 1.48 macallan RADEON_RB2D_DC_BUSY) { 3653 1.48 macallan i++; 3654 1.48 macallan } 3655 1.1 gdamore } 3656 1.1 gdamore #ifdef DIAGNOSTIC 3657 1.48 macallan if (i > RADEON_TIMEOUT) 3658 1.1 gdamore printf("%s: engine flush timed out!\n", XNAME(sc)); 3659 1.1 gdamore #endif 3660 1.1 gdamore } 3661 1.1 gdamore 3662 1.2 macallan static inline void 3663 1.2 macallan radeonfb_unclip(struct radeonfb_softc *sc) 3664 1.2 macallan { 3665 1.2 macallan 3666 1.2 macallan radeonfb_wait_fifo(sc, 2); 3667 1.4 macallan PUT32(sc, RADEON_SC_TOP_LEFT, 0); 3668 1.5 macallan PUT32(sc, RADEON_SC_BOTTOM_RIGHT, 0x1fff1fff); 3669 1.2 macallan } 3670 1.2 macallan 3671 1.2 macallan static void 3672 1.1 gdamore radeonfb_engine_init(struct radeonfb_display *dp) 3673 1.1 gdamore { 3674 1.1 gdamore struct radeonfb_softc *sc = dp->rd_softc; 3675 1.1 gdamore uint32_t pitch; 3676 1.1 gdamore 3677 1.1 gdamore /* no 3D */ 3678 1.1 gdamore PUT32(sc, RADEON_RB3D_CNTL, 0); 3679 1.1 gdamore 3680 1.110 macallan if (IS_AVIVO(sc)) { 3681 1.110 macallan 3682 1.110 macallan #if 0 3683 1.110 macallan /* XXX the xf86-video-radeon does this, causes lockups here */ 3684 1.110 macallan psel = GET32(sc, R400_GB_PIPE_SELECT); 3685 1.110 macallan PRINTREG(R400_GB_PIPE_SELECT); 3686 1.110 macallan DPRINTF(("PLL %08x %08x\n", GETPLL(sc, R500_DYN_SCLK_PWMEM_PIPE), 3687 1.110 macallan (1 | ((psel >> 8) & 0xf) << 4))); 3688 1.110 macallan PUTPLL(sc, R500_DYN_SCLK_PWMEM_PIPE, (1 | ((psel >> 8) & 0xf) << 4)); 3689 1.110 macallan #endif 3690 1.110 macallan SET32(sc, RADEON_WAIT_UNTIL, RADEON_WAIT_2D_IDLECLEAN | RADEON_WAIT_3D_IDLECLEAN); 3691 1.110 macallan SET32(sc, R300_DST_PIPE_CONFIG, R300_PIPE_AUTO_CONFIG); 3692 1.110 macallan SET32(sc, R300_RB2D_DSTCACHE_MODE, R300_DC_AUTOFLUSH_ENABLE | 3693 1.110 macallan R300_DC_DC_DISABLE_IGNORE_PE); 3694 1.110 macallan } 3695 1.110 macallan 3696 1.110 macallan PRINTREG(RADEON_RB3D_CNTL); 3697 1.110 macallan PRINTREG(RADEON_DP_GUI_MASTER_CNTL); 3698 1.110 macallan PRINTREG(RADEON_RBBM_STATUS); 3699 1.110 macallan 3700 1.1 gdamore radeonfb_engine_reset(sc); 3701 1.110 macallan PRINTREG(RADEON_RBBM_STATUS); 3702 1.110 macallan 3703 1.110 macallan /* 3704 1.110 macallan * Apple OF hands us some radeons with tiling enabled - explicitly 3705 1.110 macallan * disable it here 3706 1.110 macallan */ 3707 1.110 macallan PUT32(sc, RADEON_SURFACE_CNTL, RADEON_SURF_TRANSLATION_DIS); 3708 1.1 gdamore 3709 1.1 gdamore radeonfb_wait_fifo(sc, 1); 3710 1.110 macallan if (!IS_R300(sc) && !IS_AVIVO(sc)) 3711 1.1 gdamore PUT32(sc, RADEON_RB2D_DSTCACHE_MODE, 0); 3712 1.1 gdamore 3713 1.1 gdamore radeonfb_wait_fifo(sc, 3); 3714 1.1 gdamore 3715 1.110 macallan /* 3716 1.110 macallan * XXX 3717 1.110 macallan * I strongly suspect this works mostly by accident on !AVIVO 3718 1.110 macallan * AVIVO uses all 22 bits for the framebuffer offset, so it can 3719 1.110 macallan * address up to 4GB. Older chips probably use bits 20-22 for other 3720 1.110 macallan * things and we just so happen to set the right ones by having our 3721 1.110 macallan * PCI/AGP space above 0x80000000. 3722 1.110 macallan * Either way, r5xx does not work if we set these bits, while older 3723 1.110 macallan * chips don't work without. 3724 1.110 macallan */ 3725 1.110 macallan pitch = (dp->rd_stride + 0x3f) >> 6; 3726 1.110 macallan if (IS_AVIVO(sc)) { 3727 1.110 macallan pitch = pitch << 22; 3728 1.110 macallan } else 3729 1.110 macallan pitch = (pitch << 22) | (sc->sc_aperbase >> 10); 3730 1.1 gdamore 3731 1.110 macallan PUT32(sc, RADEON_DEFAULT_PITCH_OFFSET, pitch); 3732 1.110 macallan PUT32(sc, RADEON_DST_PITCH_OFFSET, pitch); 3733 1.110 macallan PUT32(sc, RADEON_SRC_PITCH_OFFSET, pitch); 3734 1.1 gdamore 3735 1.78 martin (void)GET32(sc, RADEON_DP_DATATYPE); 3736 1.1 gdamore 3737 1.1 gdamore /* default scissors -- no clipping */ 3738 1.1 gdamore radeonfb_wait_fifo(sc, 1); 3739 1.1 gdamore PUT32(sc, RADEON_DEFAULT_SC_BOTTOM_RIGHT, 3740 1.1 gdamore RADEON_DEFAULT_SC_RIGHT_MAX | RADEON_DEFAULT_SC_BOTTOM_MAX); 3741 1.1 gdamore 3742 1.1 gdamore radeonfb_wait_fifo(sc, 1); 3743 1.1 gdamore PUT32(sc, RADEON_DP_GUI_MASTER_CNTL, 3744 1.1 gdamore (dp->rd_format << RADEON_GMC_DST_DATATYPE_SHIFT) | 3745 1.1 gdamore RADEON_GMC_CLR_CMP_CNTL_DIS | 3746 1.1 gdamore RADEON_GMC_BRUSH_SOLID_COLOR | 3747 1.1 gdamore RADEON_GMC_SRC_DATATYPE_COLOR); 3748 1.1 gdamore 3749 1.48 macallan radeonfb_wait_fifo(sc, 10); 3750 1.1 gdamore PUT32(sc, RADEON_DST_LINE_START, 0); 3751 1.1 gdamore PUT32(sc, RADEON_DST_LINE_END, 0); 3752 1.1 gdamore PUT32(sc, RADEON_DP_BRUSH_FRGD_CLR, 0xffffffff); 3753 1.1 gdamore PUT32(sc, RADEON_DP_BRUSH_BKGD_CLR, 0); 3754 1.1 gdamore PUT32(sc, RADEON_DP_SRC_FRGD_CLR, 0xffffffff); 3755 1.1 gdamore PUT32(sc, RADEON_DP_SRC_BKGD_CLR, 0); 3756 1.1 gdamore PUT32(sc, RADEON_DP_WRITE_MASK, 0xffffffff); 3757 1.48 macallan PUT32(sc, RADEON_SC_TOP_LEFT, 0); 3758 1.48 macallan PUT32(sc, RADEON_SC_BOTTOM_RIGHT, 0x1fff1fff); 3759 1.48 macallan PUT32(sc, RADEON_AUX_SC_CNTL, 0); 3760 1.1 gdamore radeonfb_engine_idle(sc); 3761 1.1 gdamore } 3762 1.1 gdamore 3763 1.2 macallan static void 3764 1.1 gdamore radeonfb_engine_reset(struct radeonfb_softc *sc) 3765 1.1 gdamore { 3766 1.1 gdamore uint32_t hpc, rbbm, mclkcntl, clkindex; 3767 1.1 gdamore 3768 1.1 gdamore radeonfb_engine_flush(sc); 3769 1.1 gdamore 3770 1.1 gdamore clkindex = GET32(sc, RADEON_CLOCK_CNTL_INDEX); 3771 1.1 gdamore if (HAS_R300CG(sc)) 3772 1.1 gdamore radeonfb_r300cg_workaround(sc); 3773 1.1 gdamore mclkcntl = GETPLL(sc, RADEON_MCLK_CNTL); 3774 1.1 gdamore 3775 1.1 gdamore /* 3776 1.1 gdamore * According to comments in XFree code, resetting the HDP via 3777 1.1 gdamore * the RBBM_SOFT_RESET can cause bad behavior on some systems. 3778 1.1 gdamore * So we use HOST_PATH_CNTL instead. 3779 1.1 gdamore */ 3780 1.1 gdamore 3781 1.1 gdamore hpc = GET32(sc, RADEON_HOST_PATH_CNTL); 3782 1.1 gdamore rbbm = GET32(sc, RADEON_RBBM_SOFT_RESET); 3783 1.110 macallan if (IS_R300(sc) || IS_AVIVO(sc)) { 3784 1.1 gdamore PUT32(sc, RADEON_RBBM_SOFT_RESET, rbbm | 3785 1.1 gdamore RADEON_SOFT_RESET_CP | 3786 1.1 gdamore RADEON_SOFT_RESET_HI | 3787 1.1 gdamore RADEON_SOFT_RESET_E2); 3788 1.1 gdamore GET32(sc, RADEON_RBBM_SOFT_RESET); 3789 1.1 gdamore PUT32(sc, RADEON_RBBM_SOFT_RESET, 0); 3790 1.1 gdamore /* 3791 1.1 gdamore * XXX: this bit is not defined in any ATI docs I have, 3792 1.1 gdamore * nor in the XFree code, but XFree does it. Why? 3793 1.1 gdamore */ 3794 1.110 macallan SET32(sc, RADEON_RB2D_DSTCACHE_MODE, R300_DC_DC_DISABLE_IGNORE_PE); 3795 1.1 gdamore } else { 3796 1.1 gdamore PUT32(sc, RADEON_RBBM_SOFT_RESET, rbbm | 3797 1.1 gdamore RADEON_SOFT_RESET_CP | 3798 1.1 gdamore RADEON_SOFT_RESET_SE | 3799 1.1 gdamore RADEON_SOFT_RESET_RE | 3800 1.1 gdamore RADEON_SOFT_RESET_PP | 3801 1.1 gdamore RADEON_SOFT_RESET_E2 | 3802 1.1 gdamore RADEON_SOFT_RESET_RB); 3803 1.1 gdamore GET32(sc, RADEON_RBBM_SOFT_RESET); 3804 1.1 gdamore PUT32(sc, RADEON_RBBM_SOFT_RESET, rbbm & 3805 1.1 gdamore ~(RADEON_SOFT_RESET_CP | 3806 1.1 gdamore RADEON_SOFT_RESET_SE | 3807 1.1 gdamore RADEON_SOFT_RESET_RE | 3808 1.1 gdamore RADEON_SOFT_RESET_PP | 3809 1.1 gdamore RADEON_SOFT_RESET_E2 | 3810 1.1 gdamore RADEON_SOFT_RESET_RB)); 3811 1.1 gdamore GET32(sc, RADEON_RBBM_SOFT_RESET); 3812 1.1 gdamore } 3813 1.1 gdamore 3814 1.1 gdamore PUT32(sc, RADEON_HOST_PATH_CNTL, hpc | RADEON_HDP_SOFT_RESET); 3815 1.1 gdamore GET32(sc, RADEON_HOST_PATH_CNTL); 3816 1.1 gdamore PUT32(sc, RADEON_HOST_PATH_CNTL, hpc); 3817 1.1 gdamore 3818 1.110 macallan if (!IS_R300(sc) && !IS_AVIVO(sc)) 3819 1.1 gdamore PUT32(sc, RADEON_RBBM_SOFT_RESET, rbbm); 3820 1.1 gdamore 3821 1.1 gdamore PUT32(sc, RADEON_CLOCK_CNTL_INDEX, clkindex); 3822 1.69 macallan PRINTREG(RADEON_CLOCK_CNTL_INDEX); 3823 1.1 gdamore PUTPLL(sc, RADEON_MCLK_CNTL, mclkcntl); 3824 1.1 gdamore 3825 1.1 gdamore if (HAS_R300CG(sc)) 3826 1.1 gdamore radeonfb_r300cg_workaround(sc); 3827 1.1 gdamore } 3828 1.1 gdamore 3829 1.2 macallan static int 3830 1.1 gdamore radeonfb_set_curpos(struct radeonfb_display *dp, struct wsdisplay_curpos *pos) 3831 1.1 gdamore { 3832 1.1 gdamore int x, y; 3833 1.1 gdamore 3834 1.1 gdamore x = pos->x; 3835 1.1 gdamore y = pos->y; 3836 1.1 gdamore 3837 1.1 gdamore /* 3838 1.1 gdamore * This doesn't let a cursor move off the screen. I'm not 3839 1.1 gdamore * sure if this will have negative effects for e.g. Xinerama. 3840 1.1 gdamore * I'd guess Xinerama handles it by changing the cursor shape, 3841 1.1 gdamore * but that needs verification. 3842 1.1 gdamore */ 3843 1.1 gdamore if (x >= dp->rd_virtx) 3844 1.1 gdamore x = dp->rd_virtx - 1; 3845 1.1 gdamore if (x < 0) 3846 1.1 gdamore x = 0; 3847 1.1 gdamore if (y >= dp->rd_virty) 3848 1.1 gdamore y = dp->rd_virty - 1; 3849 1.1 gdamore if (y < 0) 3850 1.1 gdamore y = 0; 3851 1.1 gdamore 3852 1.1 gdamore dp->rd_cursor.rc_pos.x = x; 3853 1.1 gdamore dp->rd_cursor.rc_pos.y = y; 3854 1.1 gdamore 3855 1.1 gdamore radeonfb_cursor_position(dp); 3856 1.1 gdamore return 0; 3857 1.1 gdamore } 3858 1.1 gdamore 3859 1.2 macallan static int 3860 1.1 gdamore radeonfb_set_cursor(struct radeonfb_display *dp, struct wsdisplay_cursor *wc) 3861 1.1 gdamore { 3862 1.1 gdamore unsigned flags; 3863 1.1 gdamore 3864 1.1 gdamore uint8_t r[2], g[2], b[2]; 3865 1.1 gdamore unsigned index, count; 3866 1.1 gdamore int i, err; 3867 1.1 gdamore int pitch, size; 3868 1.107 macallan struct radeonfb_cursor *nc = &dp->rd_tempcursor; 3869 1.1 gdamore 3870 1.1 gdamore flags = wc->which; 3871 1.1 gdamore 3872 1.1 gdamore /* copy old values */ 3873 1.107 macallan memcpy(nc, &dp->rd_cursor, sizeof(struct radeonfb_cursor)); 3874 1.1 gdamore 3875 1.1 gdamore if (flags & WSDISPLAY_CURSOR_DOCMAP) { 3876 1.1 gdamore index = wc->cmap.index; 3877 1.1 gdamore count = wc->cmap.count; 3878 1.94 riastrad 3879 1.94 riastrad if (index >= 2 || count > 2 - index) 3880 1.1 gdamore return EINVAL; 3881 1.1 gdamore 3882 1.1 gdamore err = copyin(wc->cmap.red, &r[index], count); 3883 1.1 gdamore if (err) 3884 1.1 gdamore return err; 3885 1.1 gdamore err = copyin(wc->cmap.green, &g[index], count); 3886 1.1 gdamore if (err) 3887 1.1 gdamore return err; 3888 1.1 gdamore err = copyin(wc->cmap.blue, &b[index], count); 3889 1.1 gdamore if (err) 3890 1.1 gdamore return err; 3891 1.1 gdamore 3892 1.1 gdamore for (i = index; i < index + count; i++) { 3893 1.107 macallan nc->rc_cmap[i] = 3894 1.1 gdamore (r[i] << 16) + (g[i] << 8) + (b[i] << 0); 3895 1.1 gdamore } 3896 1.1 gdamore } 3897 1.1 gdamore 3898 1.1 gdamore if (flags & WSDISPLAY_CURSOR_DOSHAPE) { 3899 1.1 gdamore if ((wc->size.x > RADEON_CURSORMAXX) || 3900 1.1 gdamore (wc->size.y > RADEON_CURSORMAXY)) 3901 1.1 gdamore return EINVAL; 3902 1.1 gdamore 3903 1.1 gdamore /* figure bytes per line */ 3904 1.1 gdamore pitch = (wc->size.x + 7) / 8; 3905 1.1 gdamore size = pitch * wc->size.y; 3906 1.1 gdamore 3907 1.1 gdamore /* clear the old cursor and mask */ 3908 1.107 macallan memset(nc->rc_image, 0, 512); 3909 1.107 macallan memset(nc->rc_mask, 0, 512); 3910 1.1 gdamore 3911 1.107 macallan nc->rc_size = wc->size; 3912 1.1 gdamore 3913 1.107 macallan if ((err = copyin(wc->image, nc->rc_image, size)) != 0) 3914 1.1 gdamore return err; 3915 1.1 gdamore 3916 1.107 macallan if ((err = copyin(wc->mask, nc->rc_mask, size)) != 0) 3917 1.1 gdamore return err; 3918 1.1 gdamore } 3919 1.1 gdamore 3920 1.1 gdamore if (flags & WSDISPLAY_CURSOR_DOHOT) { 3921 1.107 macallan nc->rc_hot = wc->hot; 3922 1.107 macallan if (nc->rc_hot.x >= nc->rc_size.x) 3923 1.107 macallan nc->rc_hot.x = nc->rc_size.x - 1; 3924 1.107 macallan if (nc->rc_hot.y >= nc->rc_size.y) 3925 1.107 macallan nc->rc_hot.y = nc->rc_size.y - 1; 3926 1.1 gdamore } 3927 1.1 gdamore 3928 1.1 gdamore if (flags & WSDISPLAY_CURSOR_DOPOS) { 3929 1.107 macallan nc->rc_pos = wc->pos; 3930 1.107 macallan if (nc->rc_pos.x >= dp->rd_virtx) 3931 1.107 macallan nc->rc_pos.x = dp->rd_virtx - 1; 3932 1.7 christos #if 0 3933 1.107 macallan if (nc->rc_pos.x < 0) 3934 1.107 macallan nc->rc_pos.x = 0; 3935 1.7 christos #endif 3936 1.107 macallan if (nc->rc_pos.y >= dp->rd_virty) 3937 1.107 macallan nc->rc_pos.y = dp->rd_virty - 1; 3938 1.7 christos #if 0 3939 1.107 macallan if (nc->rc_pos.y < 0) 3940 1.107 macallan nc->rc_pos.y = 0; 3941 1.7 christos #endif 3942 1.1 gdamore } 3943 1.1 gdamore if (flags & WSDISPLAY_CURSOR_DOCUR) { 3944 1.107 macallan nc->rc_visible = wc->enable; 3945 1.1 gdamore } 3946 1.1 gdamore 3947 1.107 macallan memcpy(&dp->rd_cursor, nc, sizeof(struct radeonfb_cursor)); 3948 1.1 gdamore radeonfb_cursor_update(dp, wc->which); 3949 1.1 gdamore 3950 1.1 gdamore return 0; 3951 1.1 gdamore } 3952 1.1 gdamore 3953 1.82 macallan static uint8_t 3954 1.82 macallan radeonfb_backwards(uint8_t d) 3955 1.82 macallan { 3956 1.82 macallan uint8_t l; 3957 1.82 macallan 3958 1.82 macallan l = d << 7; 3959 1.82 macallan l |= ((d & 0x02) << 5); 3960 1.82 macallan l |= ((d & 0x04) << 3); 3961 1.82 macallan l |= ((d & 0x08) << 1); 3962 1.82 macallan l |= ((d & 0x10) >> 1); 3963 1.82 macallan l |= ((d & 0x20) >> 3); 3964 1.82 macallan l |= ((d & 0x40) >> 5); 3965 1.82 macallan l |= ((d & 0x80) >> 7); 3966 1.82 macallan return l; 3967 1.82 macallan } 3968 1.82 macallan 3969 1.1 gdamore /* 3970 1.1 gdamore * Change the cursor shape. Call this with the cursor locked to avoid 3971 1.1 gdamore * flickering/tearing. 3972 1.1 gdamore */ 3973 1.2 macallan static void 3974 1.1 gdamore radeonfb_cursor_shape(struct radeonfb_display *dp) 3975 1.1 gdamore { 3976 1.1 gdamore uint8_t and[512], xor[512]; 3977 1.77 martin int i, j, src, dst /* , pitch */; 3978 1.1 gdamore const uint8_t *msk = dp->rd_cursor.rc_mask; 3979 1.1 gdamore const uint8_t *img = dp->rd_cursor.rc_image; 3980 1.1 gdamore 3981 1.1 gdamore /* 3982 1.1 gdamore * Radeon cursor data interleaves one line of AND data followed 3983 1.1 gdamore * by a line of XOR data. (Each line corresponds to a whole hardware 3984 1.1 gdamore * pitch - i.e. 64 pixels or 8 bytes.) 3985 1.1 gdamore * 3986 1.1 gdamore * The cursor is displayed using the following table: 3987 1.1 gdamore * 3988 1.1 gdamore * AND XOR Result 3989 1.1 gdamore * ---------------------- 3990 1.1 gdamore * 0 0 Cursor color 0 3991 1.1 gdamore * 0 1 Cursor color 1 3992 1.1 gdamore * 1 0 Transparent 3993 1.1 gdamore * 1 1 Complement of background 3994 1.1 gdamore * 3995 1.1 gdamore * Our masks are therefore different from what we were passed. 3996 1.1 gdamore * Passed in, I'm assuming the data represents either color 0 or 1, 3997 1.1 gdamore * and a mask, so the passed in table looks like: 3998 1.1 gdamore * 3999 1.1 gdamore * IMG Mask Result 4000 1.1 gdamore * ----------------------- 4001 1.1 gdamore * 0 0 Transparent 4002 1.1 gdamore * 0 1 Cursor color 0 4003 1.1 gdamore * 1 0 Transparent 4004 1.1 gdamore * 1 1 Cursor color 1 4005 1.1 gdamore * 4006 1.1 gdamore * IF mask bit == 1, AND = 0, XOR = color. 4007 1.1 gdamore * IF mask bit == 0, AND = 1, XOR = 0. 4008 1.1 gdamore * 4009 1.1 gdamore * hence: AND = ~(mask); XOR = color & ~(mask); 4010 1.1 gdamore */ 4011 1.1 gdamore 4012 1.77 martin /* pitch = ((dp->rd_cursor.rc_size.x + 7) / 8); */ 4013 1.1 gdamore 4014 1.1 gdamore /* start by assuming all bits are transparent */ 4015 1.1 gdamore memset(and, 0xff, 512); 4016 1.1 gdamore memset(xor, 0x00, 512); 4017 1.1 gdamore 4018 1.1 gdamore src = 0; 4019 1.1 gdamore dst = 0; 4020 1.1 gdamore for (i = 0; i < 64; i++) { 4021 1.1 gdamore for (j = 0; j < 64; j += 8) { 4022 1.1 gdamore if ((i < dp->rd_cursor.rc_size.y) && 4023 1.1 gdamore (j < dp->rd_cursor.rc_size.x)) { 4024 1.1 gdamore 4025 1.1 gdamore /* take care to leave odd bits alone */ 4026 1.1 gdamore and[dst] &= ~(msk[src]); 4027 1.1 gdamore xor[dst] = img[src] & msk[src]; 4028 1.1 gdamore src++; 4029 1.1 gdamore } 4030 1.1 gdamore dst++; 4031 1.1 gdamore } 4032 1.1 gdamore } 4033 1.1 gdamore 4034 1.82 macallan for (i = 0; i < 512; i++) { 4035 1.82 macallan and[i] = radeonfb_backwards(and[i]); 4036 1.82 macallan xor[i] = radeonfb_backwards(xor[i]); 4037 1.82 macallan } 4038 1.82 macallan 4039 1.1 gdamore /* copy the image into place */ 4040 1.1 gdamore for (i = 0; i < 64; i++) { 4041 1.1 gdamore memcpy((uint8_t *)dp->rd_curptr + (i * 16), 4042 1.1 gdamore &and[i * 8], 8); 4043 1.1 gdamore memcpy((uint8_t *)dp->rd_curptr + (i * 16) + 8, 4044 1.1 gdamore &xor[i * 8], 8); 4045 1.1 gdamore } 4046 1.1 gdamore } 4047 1.1 gdamore 4048 1.110 macallan /* 4049 1.110 macallan * We use the cursor in 24bit mode on avivo, much simpler than the above. 4050 1.110 macallan * Should probably do the same on older radeons 4051 1.110 macallan */ 4052 1.110 macallan static void 4053 1.110 macallan radeonfb_avivo_cursor_shape(struct radeonfb_display *dp) 4054 1.110 macallan { 4055 1.110 macallan const uint8_t *msk = dp->rd_cursor.rc_mask; 4056 1.110 macallan const uint8_t *img = dp->rd_cursor.rc_image; 4057 1.110 macallan uint32_t *out = (uint32_t *)dp->rd_curptr; 4058 1.110 macallan uint8_t bit; 4059 1.110 macallan int i, j, px; 4060 1.110 macallan 4061 1.110 macallan for (i = 0; i < 64 * 8; i++) { 4062 1.110 macallan bit = 0x01; 4063 1.110 macallan for (j = 0; j < 8; j++) { 4064 1.110 macallan px = ((*msk & bit) ? 2 : 0) | ((*img & bit) ? 1 : 0); 4065 1.110 macallan switch (px) { 4066 1.110 macallan case 0: 4067 1.110 macallan case 1: 4068 1.110 macallan *out = htole32(0x00000000); 4069 1.110 macallan break; 4070 1.110 macallan case 2: 4071 1.110 macallan *out = htole32(0xff000000 | 4072 1.110 macallan dp->rd_cursor.rc_cmap[0]); 4073 1.110 macallan break; 4074 1.110 macallan case 3: 4075 1.110 macallan *out = htole32(0xff000000 | 4076 1.110 macallan dp->rd_cursor.rc_cmap[1]); 4077 1.110 macallan break; 4078 1.110 macallan } 4079 1.110 macallan out++; 4080 1.110 macallan bit = bit << 1; 4081 1.110 macallan } 4082 1.110 macallan msk++; 4083 1.110 macallan img++; 4084 1.110 macallan } 4085 1.110 macallan } 4086 1.110 macallan 4087 1.2 macallan static void 4088 1.1 gdamore radeonfb_cursor_position(struct radeonfb_display *dp) 4089 1.1 gdamore { 4090 1.1 gdamore struct radeonfb_softc *sc = dp->rd_softc; 4091 1.1 gdamore uint32_t offset, hvoff, hvpos; /* registers */ 4092 1.1 gdamore uint32_t coff; /* cursor offset */ 4093 1.110 macallan int i, x, y, xoff, yoff, crtcoff, lock; 4094 1.1 gdamore 4095 1.1 gdamore /* 4096 1.1 gdamore * XXX: this also needs to handle pan/scan 4097 1.1 gdamore */ 4098 1.1 gdamore for (i = 0; i < dp->rd_ncrtcs; i++) { 4099 1.1 gdamore 4100 1.1 gdamore struct radeonfb_crtc *rcp = &dp->rd_crtcs[i]; 4101 1.1 gdamore 4102 1.110 macallan SET32(sc, AVIVO_D1CUR_UPDATE, AVIVO_D1CURSOR_UPDATE_LOCK); 4103 1.110 macallan PUT32(sc, AVIVO_D1CUR_SIZE, 0x003f003f); 4104 1.110 macallan if (IS_AVIVO(sc)) { 4105 1.110 macallan if (rcp->rc_number) { 4106 1.110 macallan offset = AVIVO_D2CUR_SURFACE_ADDRESS; 4107 1.110 macallan hvoff = AVIVO_D2CUR_HOT_SPOT; 4108 1.110 macallan hvpos = AVIVO_D2CUR_POSITION; 4109 1.110 macallan crtcoff = 0/*RADEON_CRTC_OFFSET*/; 4110 1.110 macallan } else { 4111 1.110 macallan offset = AVIVO_D1CUR_SURFACE_ADDRESS; 4112 1.110 macallan hvoff = AVIVO_D1CUR_HOT_SPOT; 4113 1.110 macallan hvpos = AVIVO_D1CUR_POSITION; 4114 1.110 macallan crtcoff = 0/*RADEON_CRTC_OFFSET*/; 4115 1.110 macallan } 4116 1.110 macallan lock = 0; 4117 1.1 gdamore } else { 4118 1.110 macallan if (rcp->rc_number) { 4119 1.110 macallan offset = RADEON_CUR2_OFFSET; 4120 1.110 macallan hvoff = RADEON_CUR2_HORZ_VERT_OFF; 4121 1.110 macallan hvpos = RADEON_CUR2_HORZ_VERT_POSN; 4122 1.110 macallan crtcoff = RADEON_CRTC2_OFFSET; 4123 1.110 macallan } else { 4124 1.110 macallan offset = RADEON_CUR_OFFSET; 4125 1.110 macallan hvoff = RADEON_CUR_HORZ_VERT_OFF; 4126 1.110 macallan hvpos = RADEON_CUR_HORZ_VERT_POSN; 4127 1.110 macallan crtcoff = RADEON_CRTC_OFFSET; 4128 1.110 macallan } 4129 1.110 macallan lock = RADEON_CUR_LOCK; 4130 1.1 gdamore } 4131 1.1 gdamore 4132 1.1 gdamore x = dp->rd_cursor.rc_pos.x; 4133 1.1 gdamore y = dp->rd_cursor.rc_pos.y; 4134 1.1 gdamore 4135 1.1 gdamore while (y < rcp->rc_yoffset) { 4136 1.1 gdamore rcp->rc_yoffset -= RADEON_PANINCREMENT; 4137 1.1 gdamore } 4138 1.1 gdamore while (y >= (rcp->rc_yoffset + rcp->rc_videomode.vdisplay)) { 4139 1.1 gdamore rcp->rc_yoffset += RADEON_PANINCREMENT; 4140 1.1 gdamore } 4141 1.1 gdamore while (x < rcp->rc_xoffset) { 4142 1.1 gdamore rcp->rc_xoffset -= RADEON_PANINCREMENT; 4143 1.1 gdamore } 4144 1.1 gdamore while (x >= (rcp->rc_xoffset + rcp->rc_videomode.hdisplay)) { 4145 1.1 gdamore rcp->rc_xoffset += RADEON_PANINCREMENT; 4146 1.1 gdamore } 4147 1.1 gdamore 4148 1.1 gdamore /* adjust for the cursor's hotspot */ 4149 1.1 gdamore x -= dp->rd_cursor.rc_hot.x; 4150 1.1 gdamore y -= dp->rd_cursor.rc_hot.y; 4151 1.1 gdamore xoff = yoff = 0; 4152 1.1 gdamore 4153 1.1 gdamore if (x >= dp->rd_virtx) 4154 1.1 gdamore x = dp->rd_virtx - 1; 4155 1.1 gdamore if (y >= dp->rd_virty) 4156 1.1 gdamore y = dp->rd_virty - 1; 4157 1.1 gdamore 4158 1.1 gdamore /* now adjust cursor so it is relative to viewport */ 4159 1.1 gdamore x -= rcp->rc_xoffset; 4160 1.1 gdamore y -= rcp->rc_yoffset; 4161 1.1 gdamore 4162 1.1 gdamore /* 4163 1.1 gdamore * no need to check for fall off, because we should 4164 1.1 gdamore * never move off the screen entirely! 4165 1.1 gdamore */ 4166 1.1 gdamore coff = 0; 4167 1.1 gdamore if (x < 0) { 4168 1.1 gdamore xoff = -x; 4169 1.1 gdamore x = 0; 4170 1.1 gdamore } 4171 1.1 gdamore if (y < 0) { 4172 1.1 gdamore yoff = -y; 4173 1.1 gdamore y = 0; 4174 1.1 gdamore coff = (yoff * 2) * 8; 4175 1.1 gdamore } 4176 1.1 gdamore 4177 1.1 gdamore /* pan the display */ 4178 1.110 macallan if (crtcoff != 0) 4179 1.110 macallan PUT32(sc, crtcoff, (rcp->rc_yoffset * dp->rd_stride) + 4180 1.110 macallan rcp->rc_xoffset); 4181 1.1 gdamore 4182 1.110 macallan PUT32(sc, offset, (dp->rd_curoff + coff) | lock); 4183 1.110 macallan PUT32(sc, hvoff, (xoff << 16) | (yoff) | lock); 4184 1.1 gdamore /* NB: this unlocks the cursor */ 4185 1.1 gdamore PUT32(sc, hvpos, (x << 16) | y); 4186 1.110 macallan if (IS_AVIVO(sc)) 4187 1.110 macallan CLR32(sc, AVIVO_D1CUR_UPDATE, AVIVO_D1CURSOR_UPDATE_LOCK); 4188 1.1 gdamore } 4189 1.1 gdamore } 4190 1.1 gdamore 4191 1.2 macallan static void 4192 1.1 gdamore radeonfb_cursor_visible(struct radeonfb_display *dp) 4193 1.1 gdamore { 4194 1.110 macallan struct radeonfb_softc *sc = dp->rd_softc; 4195 1.1 gdamore int i; 4196 1.1 gdamore uint32_t gencntl, bit; 4197 1.1 gdamore 4198 1.1 gdamore for (i = 0; i < dp->rd_ncrtcs; i++) { 4199 1.110 macallan if (IS_AVIVO(sc)) { 4200 1.110 macallan SET32(sc, AVIVO_D1CUR_UPDATE, AVIVO_D1CURSOR_UPDATE_LOCK); 4201 1.110 macallan if (dp->rd_crtcs[i].rc_number) { 4202 1.110 macallan gencntl = AVIVO_D2CUR_CONTROL; 4203 1.110 macallan bit = AVIVO_D1CURSOR_EN | (2 << 8); 4204 1.110 macallan } else { 4205 1.110 macallan gencntl = AVIVO_D1CUR_CONTROL; 4206 1.110 macallan bit = AVIVO_D1CURSOR_EN | (2 << 8); 4207 1.110 macallan } 4208 1.1 gdamore } else { 4209 1.110 macallan if (dp->rd_crtcs[i].rc_number) { 4210 1.110 macallan gencntl = RADEON_CRTC2_GEN_CNTL; 4211 1.110 macallan bit = RADEON_CRTC2_CUR_EN; 4212 1.110 macallan } else { 4213 1.110 macallan gencntl = RADEON_CRTC_GEN_CNTL; 4214 1.110 macallan bit = RADEON_CRTC_CUR_EN; 4215 1.110 macallan } 4216 1.1 gdamore } 4217 1.1 gdamore if (dp->rd_cursor.rc_visible) 4218 1.1 gdamore SET32(dp->rd_softc, gencntl, bit); 4219 1.1 gdamore else 4220 1.1 gdamore CLR32(dp->rd_softc, gencntl, bit); 4221 1.110 macallan if (IS_AVIVO(sc)) 4222 1.110 macallan CLR32(sc, AVIVO_D1CUR_UPDATE, AVIVO_D1CURSOR_UPDATE_LOCK); 4223 1.110 macallan 4224 1.1 gdamore } 4225 1.1 gdamore } 4226 1.1 gdamore 4227 1.2 macallan static void 4228 1.1 gdamore radeonfb_cursor_cmap(struct radeonfb_display *dp) 4229 1.1 gdamore { 4230 1.1 gdamore int i; 4231 1.1 gdamore uint32_t c0reg, c1reg; 4232 1.1 gdamore struct radeonfb_softc *sc = dp->rd_softc; 4233 1.1 gdamore 4234 1.1 gdamore for (i = 0; i < dp->rd_ncrtcs; i++) { 4235 1.1 gdamore if (dp->rd_crtcs[i].rc_number) { 4236 1.1 gdamore c0reg = RADEON_CUR2_CLR0; 4237 1.1 gdamore c1reg = RADEON_CUR2_CLR1; 4238 1.1 gdamore } else { 4239 1.1 gdamore c0reg = RADEON_CUR_CLR0; 4240 1.1 gdamore c1reg = RADEON_CUR_CLR1; 4241 1.1 gdamore } 4242 1.1 gdamore 4243 1.1 gdamore PUT32(sc, c0reg, dp->rd_cursor.rc_cmap[0]); 4244 1.1 gdamore PUT32(sc, c1reg, dp->rd_cursor.rc_cmap[1]); 4245 1.1 gdamore } 4246 1.1 gdamore } 4247 1.1 gdamore 4248 1.2 macallan static void 4249 1.1 gdamore radeonfb_cursor_update(struct radeonfb_display *dp, unsigned which) 4250 1.1 gdamore { 4251 1.1 gdamore struct radeonfb_softc *sc; 4252 1.1 gdamore int i; 4253 1.1 gdamore 4254 1.1 gdamore sc = dp->rd_softc; 4255 1.110 macallan 4256 1.1 gdamore for (i = 0; i < dp->rd_ncrtcs; i++) { 4257 1.1 gdamore if (dp->rd_crtcs[i].rc_number) { 4258 1.110 macallan if (IS_AVIVO(sc)) { 4259 1.110 macallan SET32(sc, AVIVO_D2CUR_UPDATE, AVIVO_D1CURSOR_UPDATE_LOCK); 4260 1.110 macallan } else 4261 1.110 macallan SET32(sc, RADEON_CUR2_OFFSET, RADEON_CUR_LOCK); 4262 1.1 gdamore } else { 4263 1.110 macallan if (IS_AVIVO(sc)) { 4264 1.110 macallan SET32(sc, AVIVO_D1CUR_UPDATE, AVIVO_D1CURSOR_UPDATE_LOCK); 4265 1.110 macallan } else 4266 1.110 macallan SET32(sc, RADEON_CUR_OFFSET,RADEON_CUR_LOCK); 4267 1.1 gdamore } 4268 1.1 gdamore } 4269 1.1 gdamore 4270 1.110 macallan if (which & WSDISPLAY_CURSOR_DOCMAP) { 4271 1.110 macallan if (IS_AVIVO(sc)) { 4272 1.110 macallan /* 4273 1.110 macallan * we use an ARGB cursor here, so we need to rebuild 4274 1.110 macallan * the cursor image every time the palette changes 4275 1.110 macallan */ 4276 1.110 macallan radeonfb_avivo_cursor_shape(dp); 4277 1.110 macallan } else 4278 1.110 macallan radeonfb_cursor_cmap(dp); 4279 1.110 macallan } 4280 1.1 gdamore 4281 1.110 macallan if (which & WSDISPLAY_CURSOR_DOSHAPE) { 4282 1.110 macallan if (IS_AVIVO(sc)) { 4283 1.110 macallan radeonfb_avivo_cursor_shape(dp); 4284 1.110 macallan } else 4285 1.110 macallan radeonfb_cursor_shape(dp); 4286 1.110 macallan } 4287 1.110 macallan 4288 1.1 gdamore if (which & WSDISPLAY_CURSOR_DOCUR) 4289 1.1 gdamore radeonfb_cursor_visible(dp); 4290 1.1 gdamore 4291 1.1 gdamore /* this one is unconditional, because it updates other stuff */ 4292 1.1 gdamore radeonfb_cursor_position(dp); 4293 1.1 gdamore } 4294 1.1 gdamore 4295 1.1 gdamore static struct videomode * 4296 1.1 gdamore radeonfb_best_refresh(struct videomode *m1, struct videomode *m2) 4297 1.1 gdamore { 4298 1.1 gdamore int r1, r2; 4299 1.1 gdamore 4300 1.1 gdamore /* otherwise pick the higher refresh rate */ 4301 1.1 gdamore r1 = DIVIDE(DIVIDE(m1->dot_clock, m1->htotal), m1->vtotal); 4302 1.1 gdamore r2 = DIVIDE(DIVIDE(m2->dot_clock, m2->htotal), m2->vtotal); 4303 1.1 gdamore 4304 1.1 gdamore return (r1 < r2 ? m2 : m1); 4305 1.1 gdamore } 4306 1.1 gdamore 4307 1.1 gdamore static const struct videomode * 4308 1.9 macallan radeonfb_port_mode(struct radeonfb_softc *sc, struct radeonfb_port *rp, 4309 1.9 macallan int x, int y) 4310 1.1 gdamore { 4311 1.1 gdamore struct edid_info *ep = &rp->rp_edid; 4312 1.1 gdamore struct videomode *vmp = NULL; 4313 1.1 gdamore int i; 4314 1.1 gdamore 4315 1.1 gdamore if (!rp->rp_edid_valid) { 4316 1.1 gdamore /* fallback to safe mode */ 4317 1.9 macallan return radeonfb_modelookup(sc->sc_defaultmode); 4318 1.1 gdamore } 4319 1.11 ad 4320 1.1 gdamore /* always choose the preferred mode first! */ 4321 1.1 gdamore if (ep->edid_preferred_mode) { 4322 1.1 gdamore 4323 1.1 gdamore /* XXX: add auto-stretching support for native mode */ 4324 1.1 gdamore 4325 1.1 gdamore /* this may want panning to occur, btw */ 4326 1.1 gdamore if ((ep->edid_preferred_mode->hdisplay <= x) && 4327 1.1 gdamore (ep->edid_preferred_mode->vdisplay <= y)) 4328 1.1 gdamore return ep->edid_preferred_mode; 4329 1.1 gdamore } 4330 1.1 gdamore 4331 1.1 gdamore for (i = 0; i < ep->edid_nmodes; i++) { 4332 1.1 gdamore /* 4333 1.1 gdamore * We elect to pick a resolution that is too large for 4334 1.1 gdamore * the monitor than one that is too small. This means 4335 1.1 gdamore * that we will prefer to pan rather than to try to 4336 1.1 gdamore * center a smaller display on a larger screen. In 4337 1.1 gdamore * practice, this shouldn't matter because if a 4338 1.1 gdamore * monitor can support a larger resolution, it can 4339 1.1 gdamore * probably also support the smaller. A specific 4340 1.1 gdamore * exception is fixed format panels, but hopefully 4341 1.1 gdamore * they are properly dealt with by the "autostretch" 4342 1.1 gdamore * logic above. 4343 1.1 gdamore */ 4344 1.1 gdamore if ((ep->edid_modes[i].hdisplay > x) || 4345 1.1 gdamore (ep->edid_modes[i].vdisplay > y)) { 4346 1.1 gdamore continue; 4347 1.1 gdamore } 4348 1.1 gdamore 4349 1.1 gdamore /* 4350 1.1 gdamore * at this point, the display mode is no larger than 4351 1.1 gdamore * what we've requested. 4352 1.1 gdamore */ 4353 1.1 gdamore if (vmp == NULL) 4354 1.1 gdamore vmp = &ep->edid_modes[i]; 4355 1.1 gdamore 4356 1.1 gdamore /* eliminate smaller modes */ 4357 1.1 gdamore if ((vmp->hdisplay >= ep->edid_modes[i].hdisplay) || 4358 1.1 gdamore (vmp->vdisplay >= ep->edid_modes[i].vdisplay)) 4359 1.1 gdamore continue; 4360 1.1 gdamore 4361 1.1 gdamore if ((vmp->hdisplay < ep->edid_modes[i].hdisplay) || 4362 1.1 gdamore (vmp->vdisplay < ep->edid_modes[i].vdisplay)) { 4363 1.1 gdamore vmp = &ep->edid_modes[i]; 4364 1.1 gdamore continue; 4365 1.1 gdamore } 4366 1.1 gdamore 4367 1.1 gdamore KASSERT(vmp->hdisplay == ep->edid_modes[i].hdisplay); 4368 1.1 gdamore KASSERT(vmp->vdisplay == ep->edid_modes[i].vdisplay); 4369 1.1 gdamore 4370 1.1 gdamore vmp = radeonfb_best_refresh(vmp, &ep->edid_modes[i]); 4371 1.1 gdamore } 4372 1.1 gdamore 4373 1.9 macallan return (vmp ? vmp : radeonfb_modelookup(sc->sc_defaultmode)); 4374 1.1 gdamore } 4375 1.1 gdamore 4376 1.1 gdamore static int 4377 1.1 gdamore radeonfb_hasres(struct videomode *list, int nlist, int x, int y) 4378 1.1 gdamore { 4379 1.1 gdamore int i; 4380 1.1 gdamore 4381 1.1 gdamore for (i = 0; i < nlist; i++) { 4382 1.1 gdamore if ((x == list[i].hdisplay) && 4383 1.1 gdamore (y == list[i].vdisplay)) { 4384 1.1 gdamore return 1; 4385 1.1 gdamore } 4386 1.1 gdamore } 4387 1.1 gdamore return 0; 4388 1.1 gdamore } 4389 1.1 gdamore 4390 1.2 macallan static void 4391 1.1 gdamore radeonfb_pickres(struct radeonfb_display *dp, uint16_t *x, uint16_t *y, 4392 1.1 gdamore int pan) 4393 1.1 gdamore { 4394 1.1 gdamore struct radeonfb_port *rp; 4395 1.1 gdamore struct edid_info *ep; 4396 1.1 gdamore int i, j; 4397 1.1 gdamore 4398 1.1 gdamore *x = 0; 4399 1.1 gdamore *y = 0; 4400 1.1 gdamore 4401 1.1 gdamore if (pan) { 4402 1.1 gdamore for (i = 0; i < dp->rd_ncrtcs; i++) { 4403 1.1 gdamore rp = dp->rd_crtcs[i].rc_port; 4404 1.1 gdamore ep = &rp->rp_edid; 4405 1.1 gdamore if (!rp->rp_edid_valid) { 4406 1.1 gdamore /* monitor not present */ 4407 1.1 gdamore continue; 4408 1.1 gdamore } 4409 1.1 gdamore 4410 1.1 gdamore /* 4411 1.1 gdamore * For now we are ignoring "conflict" that 4412 1.1 gdamore * could occur when mixing some modes like 4413 1.1 gdamore * 1280x1024 and 1400x800. It isn't clear 4414 1.1 gdamore * which is better, so the first one wins. 4415 1.1 gdamore */ 4416 1.1 gdamore for (j = 0; j < ep->edid_nmodes; j++) { 4417 1.1 gdamore /* 4418 1.1 gdamore * ignore resolutions that are too big for 4419 1.1 gdamore * the radeon 4420 1.1 gdamore */ 4421 1.1 gdamore if (ep->edid_modes[j].hdisplay > 4422 1.1 gdamore dp->rd_softc->sc_maxx) 4423 1.1 gdamore continue; 4424 1.1 gdamore if (ep->edid_modes[j].vdisplay > 4425 1.1 gdamore dp->rd_softc->sc_maxy) 4426 1.1 gdamore continue; 4427 1.1 gdamore 4428 1.1 gdamore /* 4429 1.1 gdamore * pick largest resolution, the 4430 1.1 gdamore * smaller monitor will pan 4431 1.1 gdamore */ 4432 1.1 gdamore if ((ep->edid_modes[j].hdisplay >= *x) && 4433 1.1 gdamore (ep->edid_modes[j].vdisplay >= *y)) { 4434 1.1 gdamore *x = ep->edid_modes[j].hdisplay; 4435 1.1 gdamore *y = ep->edid_modes[j].vdisplay; 4436 1.1 gdamore } 4437 1.1 gdamore } 4438 1.1 gdamore } 4439 1.1 gdamore 4440 1.1 gdamore } else { 4441 1.107 macallan struct videomode *modes; 4442 1.107 macallan size_t smodes; 4443 1.1 gdamore int nmodes = 0; 4444 1.1 gdamore int valid = 0; 4445 1.1 gdamore 4446 1.107 macallan smodes = sizeof(struct videomode) * 64; 4447 1.107 macallan modes = kmem_alloc(smodes, KM_SLEEP); 4448 1.107 macallan 4449 1.1 gdamore for (i = 0; i < dp->rd_ncrtcs; i++) { 4450 1.1 gdamore /* 4451 1.1 gdamore * pick the largest resolution in common. 4452 1.1 gdamore */ 4453 1.1 gdamore rp = dp->rd_crtcs[i].rc_port; 4454 1.1 gdamore ep = &rp->rp_edid; 4455 1.1 gdamore 4456 1.1 gdamore if (!rp->rp_edid_valid) 4457 1.1 gdamore continue; 4458 1.1 gdamore 4459 1.1 gdamore if (!valid) { 4460 1.29 macallan /* 4461 1.29 macallan * Pick the preferred mode for this port 4462 1.29 macallan * if available. 4463 1.29 macallan */ 4464 1.29 macallan if (ep->edid_preferred_mode) { 4465 1.29 macallan struct videomode *vmp = 4466 1.29 macallan ep->edid_preferred_mode; 4467 1.29 macallan 4468 1.29 macallan if ((vmp->hdisplay <= 4469 1.29 macallan dp->rd_softc->sc_maxx) && 4470 1.29 macallan (vmp->vdisplay <= 4471 1.29 macallan dp->rd_softc->sc_maxy)) 4472 1.29 macallan modes[nmodes++] = *vmp; 4473 1.29 macallan } else { 4474 1.29 macallan 4475 1.29 macallan /* initialize starting list */ 4476 1.29 macallan for (j = 0; j < ep->edid_nmodes; j++) { 4477 1.29 macallan /* 4478 1.29 macallan * ignore resolutions that are 4479 1.29 macallan * too big for the radeon 4480 1.29 macallan */ 4481 1.29 macallan if (ep->edid_modes[j].hdisplay > 4482 1.29 macallan dp->rd_softc->sc_maxx) 4483 1.29 macallan continue; 4484 1.29 macallan if (ep->edid_modes[j].vdisplay > 4485 1.29 macallan dp->rd_softc->sc_maxy) 4486 1.29 macallan continue; 4487 1.29 macallan 4488 1.29 macallan modes[nmodes] = 4489 1.29 macallan ep->edid_modes[j]; 4490 1.29 macallan nmodes++; 4491 1.29 macallan } 4492 1.1 gdamore } 4493 1.1 gdamore valid = 1; 4494 1.1 gdamore } else { 4495 1.1 gdamore /* merge into preexisting list */ 4496 1.1 gdamore for (j = 0; j < nmodes; j++) { 4497 1.1 gdamore if (!radeonfb_hasres(ep->edid_modes, 4498 1.1 gdamore ep->edid_nmodes, 4499 1.1 gdamore modes[j].hdisplay, 4500 1.1 gdamore modes[j].vdisplay)) { 4501 1.1 gdamore modes[j] = modes[nmodes]; 4502 1.1 gdamore j--; 4503 1.1 gdamore nmodes--; 4504 1.1 gdamore } 4505 1.1 gdamore } 4506 1.1 gdamore } 4507 1.1 gdamore } 4508 1.1 gdamore 4509 1.1 gdamore /* now we have to pick from the merged list */ 4510 1.1 gdamore for (i = 0; i < nmodes; i++) { 4511 1.1 gdamore if ((modes[i].hdisplay >= *x) && 4512 1.1 gdamore (modes[i].vdisplay >= *y)) { 4513 1.1 gdamore *x = modes[i].hdisplay; 4514 1.1 gdamore *y = modes[i].vdisplay; 4515 1.1 gdamore } 4516 1.1 gdamore } 4517 1.107 macallan kmem_free(modes, smodes); 4518 1.107 macallan 4519 1.1 gdamore } 4520 1.1 gdamore 4521 1.1 gdamore if ((*x == 0) || (*y == 0)) { 4522 1.1 gdamore /* fallback to safe mode */ 4523 1.1 gdamore *x = 640; 4524 1.1 gdamore *y = 480; 4525 1.1 gdamore } 4526 1.1 gdamore } 4527 1.9 macallan 4528 1.17 macallan /* 4529 1.17 macallan * backlight levels are linear on: 4530 1.17 macallan * - RV200, RV250, RV280, RV350 4531 1.17 macallan * - but NOT on PowerBook4,3 6,3 6,5 4532 1.17 macallan * according to Linux' radeonfb 4533 1.17 macallan */ 4534 1.9 macallan 4535 1.9 macallan /* Get the current backlight level for the display. */ 4536 1.9 macallan 4537 1.11 ad static int 4538 1.9 macallan radeonfb_get_backlight(struct radeonfb_display *dp) 4539 1.9 macallan { 4540 1.9 macallan int s; 4541 1.9 macallan uint32_t level; 4542 1.9 macallan 4543 1.9 macallan s = spltty(); 4544 1.9 macallan 4545 1.9 macallan level = radeonfb_get32(dp->rd_softc, RADEON_LVDS_GEN_CNTL); 4546 1.9 macallan level &= RADEON_LVDS_BL_MOD_LEV_MASK; 4547 1.9 macallan level >>= RADEON_LVDS_BL_MOD_LEV_SHIFT; 4548 1.9 macallan 4549 1.11 ad /* 4550 1.11 ad * On some chips, we should negate the backlight level. 4551 1.11 ad * XXX Find out on which chips. 4552 1.11 ad */ 4553 1.17 macallan if (dp->rd_softc->sc_flags & RFB_INV_BLIGHT) 4554 1.11 ad level = RADEONFB_BACKLIGHT_MAX - level; 4555 1.9 macallan 4556 1.9 macallan splx(s); 4557 1.9 macallan 4558 1.9 macallan return level; 4559 1.11 ad } 4560 1.9 macallan 4561 1.9 macallan /* Set the backlight to the given level for the display. */ 4562 1.59 macallan static void 4563 1.59 macallan radeonfb_switch_backlight(struct radeonfb_display *dp, int on) 4564 1.59 macallan { 4565 1.59 macallan if (dp->rd_bl_on == on) 4566 1.59 macallan return; 4567 1.59 macallan dp->rd_bl_on = on; 4568 1.59 macallan radeonfb_set_backlight(dp, dp->rd_bl_level); 4569 1.59 macallan } 4570 1.9 macallan 4571 1.11 ad static int 4572 1.9 macallan radeonfb_set_backlight(struct radeonfb_display *dp, int level) 4573 1.9 macallan { 4574 1.95 maya struct radeonfb_softc *sc = dp->rd_softc; 4575 1.9 macallan int rlevel, s; 4576 1.9 macallan uint32_t lvds; 4577 1.9 macallan 4578 1.88 macallan if(!sc->sc_mapped) 4579 1.88 macallan return 0; 4580 1.88 macallan 4581 1.9 macallan s = spltty(); 4582 1.59 macallan 4583 1.59 macallan dp->rd_bl_level = level; 4584 1.59 macallan if (dp->rd_bl_on == 0) 4585 1.59 macallan level = 0; 4586 1.59 macallan 4587 1.9 macallan if (level < 0) 4588 1.9 macallan level = 0; 4589 1.9 macallan else if (level >= RADEONFB_BACKLIGHT_MAX) 4590 1.9 macallan level = RADEONFB_BACKLIGHT_MAX; 4591 1.9 macallan 4592 1.9 macallan /* On some chips, we should negate the backlight level. */ 4593 1.17 macallan if (dp->rd_softc->sc_flags & RFB_INV_BLIGHT) { 4594 1.88 macallan rlevel = RADEONFB_BACKLIGHT_MAX - level; 4595 1.17 macallan } else 4596 1.11 ad rlevel = level; 4597 1.9 macallan 4598 1.9 macallan callout_stop(&dp->rd_bl_lvds_co); 4599 1.110 macallan //radeonfb_engine_idle(sc); 4600 1.9 macallan 4601 1.11 ad /* 4602 1.9 macallan * Turn off the display if the backlight is set to 0, since the 4603 1.11 ad * display is useless without backlight anyway. 4604 1.9 macallan */ 4605 1.9 macallan if (level == 0) 4606 1.9 macallan radeonfb_blank(dp, 1); 4607 1.9 macallan else if (radeonfb_get_backlight(dp) == 0) 4608 1.9 macallan radeonfb_blank(dp, 0); 4609 1.11 ad 4610 1.9 macallan lvds = radeonfb_get32(sc, RADEON_LVDS_GEN_CNTL); 4611 1.9 macallan lvds &= ~RADEON_LVDS_DISPLAY_DIS; 4612 1.9 macallan if (!(lvds & RADEON_LVDS_BLON) || !(lvds & RADEON_LVDS_ON)) { 4613 1.9 macallan lvds |= dp->rd_bl_lvds_val & RADEON_LVDS_DIGON; 4614 1.9 macallan lvds |= RADEON_LVDS_BLON | RADEON_LVDS_EN; 4615 1.9 macallan radeonfb_put32(sc, RADEON_LVDS_GEN_CNTL, lvds); 4616 1.9 macallan lvds &= ~RADEON_LVDS_BL_MOD_LEV_MASK; 4617 1.9 macallan lvds |= rlevel << RADEON_LVDS_BL_MOD_LEV_SHIFT; 4618 1.9 macallan lvds |= RADEON_LVDS_ON; 4619 1.9 macallan lvds |= dp->rd_bl_lvds_val & RADEON_LVDS_BL_MOD_EN; 4620 1.9 macallan } else { 4621 1.9 macallan lvds &= ~RADEON_LVDS_BL_MOD_LEV_MASK; 4622 1.9 macallan lvds |= rlevel << RADEON_LVDS_BL_MOD_LEV_SHIFT; 4623 1.9 macallan radeonfb_put32(sc, RADEON_LVDS_GEN_CNTL, lvds); 4624 1.9 macallan } 4625 1.11 ad 4626 1.9 macallan dp->rd_bl_lvds_val &= ~RADEON_LVDS_STATE_MASK; 4627 1.9 macallan dp->rd_bl_lvds_val |= lvds & RADEON_LVDS_STATE_MASK; 4628 1.9 macallan /* XXX What is the correct delay? */ 4629 1.11 ad callout_schedule(&dp->rd_bl_lvds_co, 200 * hz); 4630 1.9 macallan 4631 1.9 macallan splx(s); 4632 1.9 macallan 4633 1.9 macallan return 0; 4634 1.9 macallan } 4635 1.9 macallan 4636 1.11 ad /* 4637 1.11 ad * Callout function for delayed operations on the LVDS_GEN_CNTL register. 4638 1.9 macallan * Set the delayed bits in the register, and clear the stored delayed 4639 1.9 macallan * value. 4640 1.9 macallan */ 4641 1.9 macallan 4642 1.9 macallan static void radeonfb_lvds_callout(void *arg) 4643 1.9 macallan { 4644 1.9 macallan struct radeonfb_display *dp = arg; 4645 1.9 macallan int s; 4646 1.9 macallan 4647 1.9 macallan s = splhigh(); 4648 1.9 macallan 4649 1.11 ad radeonfb_mask32(dp->rd_softc, RADEON_LVDS_GEN_CNTL, ~0, 4650 1.9 macallan dp->rd_bl_lvds_val); 4651 1.9 macallan dp->rd_bl_lvds_val = 0; 4652 1.9 macallan 4653 1.9 macallan splx(s); 4654 1.9 macallan } 4655 1.34 macallan 4656 1.34 macallan static void 4657 1.34 macallan radeonfb_brightness_up(device_t dev) 4658 1.34 macallan { 4659 1.34 macallan struct radeonfb_softc *sc = device_private(dev); 4660 1.59 macallan struct radeonfb_display *dp = &sc->sc_displays[0]; 4661 1.34 macallan int level; 4662 1.34 macallan 4663 1.34 macallan /* we assume the main display is the first one - need a better way */ 4664 1.34 macallan if (sc->sc_ndisplays < 1) return; 4665 1.59 macallan /* make sure pushing the hotkeys always has an effect */ 4666 1.59 macallan dp->rd_bl_on = 1; 4667 1.59 macallan level = dp->rd_bl_level; 4668 1.100 riastrad level = uimin(RADEONFB_BACKLIGHT_MAX, level + 5); 4669 1.59 macallan radeonfb_set_backlight(dp, level); 4670 1.34 macallan } 4671 1.34 macallan 4672 1.34 macallan static void 4673 1.34 macallan radeonfb_brightness_down(device_t dev) 4674 1.34 macallan { 4675 1.34 macallan struct radeonfb_softc *sc = device_private(dev); 4676 1.59 macallan struct radeonfb_display *dp = &sc->sc_displays[0]; 4677 1.34 macallan int level; 4678 1.34 macallan 4679 1.34 macallan /* we assume the main display is the first one - need a better way */ 4680 1.34 macallan if (sc->sc_ndisplays < 1) return; 4681 1.59 macallan /* make sure pushing the hotkeys always has an effect */ 4682 1.59 macallan dp->rd_bl_on = 1; 4683 1.59 macallan level = dp->rd_bl_level; 4684 1.100 riastrad level = uimax(0, level - 5); 4685 1.59 macallan radeonfb_set_backlight(dp, level); 4686 1.34 macallan } 4687