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