radeonfb.c revision 1.108 1 /* $NetBSD: radeonfb.c,v 1.108 2020/06/11 07:51:26 macallan 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.108 2020/06/11 07:51:26 macallan 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_integer_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_data_nocopy(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