1 /* $OpenBSD: radeonfb.c,v 1.5 2022/07/15 17:57:26 kettenis Exp $ */
2
3 /*
4 * Copyright (c) 2009 Mark Kettenis.
5 *
6 * Permission to use, copy, modify, and distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 */
18
19 #include <sys/param.h>
20 #include <sys/device.h>
21 #include <sys/pciio.h>
22 #include <sys/systm.h>
23
24 #include <machine/bus.h>
25 #include <machine/cpu.h>
26
27 #include <uvm/uvm_extern.h>
28
29 #include <dev/pci/pcireg.h>
30 #include <dev/pci/pcivar.h>
31 #include <dev/pci/pcidevs.h>
32
33 #include <dev/wscons/wsconsio.h>
34 #include <dev/wscons/wsdisplayvar.h>
35 #include <dev/rasops/rasops.h>
36
37 #define RADEON_PCI_MEM 0x10
38 #define RADEON_PCI_MMIO 0x18
39
40 #define RADEON_CRTC_OFFSET 0x0224
41
42 #define RADEON_RBBM_STATUS 0x0e40
43 #define RADEON_RBBM_FIFOCNT_MASK 0x0000007f
44 #define RADEON_RBBM_ACTIVE 0x80000000
45
46 #define RADEON_SRC_Y_X 0x1434
47 #define RADEON_DST_Y_X 0x1438
48 #define RADEON_DST_HEIGHT_WIDTH 0x143c
49
50 #define RADEON_DP_GUI_MASTER_CNTL 0x146c
51 #define RADEON_GMC_DST_8BPP 0x00000200
52 #define RADEON_GMC_DST_16BPP 0x00000400
53 #define RADEON_GMC_DST_32BPP 0x00000600
54 #define RADEON_GMC_BRUSH_NONE 0x000000e0
55 #define RADEON_GMC_BRUSH_SOLID_COLOR 0x000000d0
56 #define RADEON_GMC_SRC_DATATYPE_COLOR 0x00003000
57 #define RADEON_GMC_SRC_SOURCE_MEMORY 0x02000000
58 #define RADEON_ROP3_S 0x00cc0000
59 #define RADEON_ROP3_P 0x00f00000
60 #define RADEON_GMC_CLR_CMP_CNTL_DIS 0x10000000
61
62 #define RADEON_DP_BRUSH_BKGD_CLR 0x1478
63 #define RADEON_DP_BRUSH_FRGD_CLR 0x147c
64
65 #define RADEON_DP_CNTL 0x16c0
66 #define RADEON_DST_X_LEFT_TO_RIGHT 0x00000001
67 #define RADEON_DST_Y_TOP_TO_BOTTOM 0x00000002
68 #define RADEON_DP_WRITE_MASK 0x16cc
69
70 #define RADEON_DEFAULT_PITCH_OFFSET 0x16e0
71 #define RADEON_DEFAULT_SC_BOTTOM_RIGHT 0x16e8
72
73 #define RADEON_WAIT_UNTIL 0x1720
74 #define RADEON_WAIT_2D_IDLECLEAN 0x00010000
75 #define RADEON_WAIT_3D_IDLECLEAN 0x00020000
76 #define RADEON_WAIT_HOST_IDLECLEAN 0x00040000
77
78 #define RADEON_RB3D_DSTCACHE_CTLSTAT 0x325c
79 #define RADEON_RB3D_DC_FLUSH_ALL 0x0000000f
80 #define RADEON_RB3D_DC_BUSY 0x80000000
81
82 #define RADEON_COORDS(x, y) ((y << 16) | (x))
83
84 #ifdef APERTURE
85 extern int allowaperture;
86 #endif
87
88 struct radeonfb_softc;
89
90 /* minimal frame buffer information, suitable for early console */
91 struct radeonfb {
92 struct radeonfb_softc *sc;
93 struct rasops_info ri;
94
95 bus_space_tag_t fbt;
96 bus_space_handle_t fbh;
97
98 bus_space_tag_t mmiot;
99 bus_space_handle_t mmioh;
100 bus_size_t memoff;
101
102 struct wsscreen_descr wsd;
103 };
104
105 struct radeonfb_softc {
106 struct device sc_dev;
107 struct radeonfb *sc_fb;
108 struct radeonfb sc_fb_store;
109
110 struct wsscreen_list sc_wsl;
111 struct wsscreen_descr *sc_scrlist[1];
112 int sc_nscr;
113
114 bus_addr_t sc_membase;
115 bus_size_t sc_memsize;
116
117 bus_addr_t sc_mmiobase;
118 bus_size_t sc_mmiosize;
119
120 pcitag_t sc_pcitag;
121
122 int sc_mode;
123 };
124
125 int radeonfb_alloc_screen(void *, const struct wsscreen_descr *, void **,
126 int *, int *, uint32_t *);
127 void radeonfb_free_screen(void *, void *);
128 int radeonfb_ioctl(void *, u_long, caddr_t, int, struct proc *);
129 int radeonfb_list_font(void *, struct wsdisplay_font *);
130 int radeonfb_load_font(void *, void *, struct wsdisplay_font *);
131 paddr_t radeonfb_mmap(void *, off_t, int);
132 int radeonfb_show_screen(void *, void *, int, void (*)(void *, int, int),
133 void *);
134
135 struct wsdisplay_accessops radeonfb_accessops = {
136 .ioctl = radeonfb_ioctl,
137 .mmap = radeonfb_mmap,
138 .alloc_screen = radeonfb_alloc_screen,
139 .free_screen = radeonfb_free_screen,
140 .show_screen = radeonfb_show_screen,
141 .load_font = radeonfb_load_font,
142 .list_font = radeonfb_list_font
143 };
144
145 int radeonfb_match(struct device *, void *, void *);
146 void radeonfb_attach(struct device *, struct device *, void *);
147
148 const struct cfattach radeonfb_ca = {
149 sizeof(struct radeonfb_softc), radeonfb_match, radeonfb_attach
150 };
151
152 struct cfdriver radeonfb_cd = {
153 NULL, "radeonfb", DV_DULL
154 };
155
156 int radeonfb_copycols(void *, int, int, int, int);
157 int radeonfb_erasecols(void *, int, int, int, uint32_t);
158 int radeonfb_copyrows(void *, int, int, int);
159 int radeonfb_eraserows(void *, int, int, uint32_t);
160
161 int radeonfb_setup(struct radeonfb *);
162 void radeonfb_wait_fifo(struct radeonfb *, int);
163 void radeonfb_wait(struct radeonfb *);
164 void radeonfb_copyrect(struct radeonfb *, int, int, int, int, int, int);
165 void radeonfb_fillrect(struct radeonfb *, int, int, int, int, int);
166
167 static struct radeonfb radeonfbcn;
168
169 const struct pci_matchid radeonfb_devices[] = {
170 { PCI_VENDOR_ATI, 0x9615 }
171 };
172
173 int
radeonfb_match(struct device * parent,void * cf,void * aux)174 radeonfb_match(struct device *parent, void *cf, void *aux)
175 {
176 struct pci_attach_args *pa = aux;
177
178 return pci_matchbyid(pa, radeonfb_devices, nitems(radeonfb_devices));
179 }
180
181 void
radeonfb_attach(struct device * parent,struct device * self,void * aux)182 radeonfb_attach(struct device *parent, struct device *self, void *aux)
183 {
184 struct radeonfb_softc *sc = (struct radeonfb_softc *)self;
185 struct pci_attach_args *pa = aux;
186 struct wsemuldisplaydev_attach_args waa;
187 bus_space_tag_t fbt, mmiot;
188 bus_space_handle_t fbh, mmioh;
189 #if 0
190 bus_size_t fbsize, mmiosize;
191 #endif
192 struct radeonfb *fb;
193 int console;
194
195 sc->sc_pcitag = pa->pa_tag;
196
197 if (pci_mapreg_map(pa, RADEON_PCI_MEM, PCI_MAPREG_TYPE_MEM,
198 BUS_SPACE_MAP_LINEAR, &fbt, &fbh,
199 &sc->sc_membase, &sc->sc_memsize, 0)) {
200 printf(": can't map video memory\n");
201 return;
202 }
203
204 if (pci_mapreg_map(pa, RADEON_PCI_MMIO, PCI_MAPREG_TYPE_MEM, 0,
205 &mmiot, &mmioh, &sc->sc_mmiobase,
206 &sc->sc_mmiosize, 0)) {
207 printf(": can't map registers\n");
208 return;
209 }
210
211 console = radeonfbcn.ri.ri_hw != NULL;
212
213 if (console)
214 fb = &radeonfbcn;
215 else
216 fb = &sc->sc_fb_store;
217
218 fb->sc = sc;
219 fb->fbt = fbt;
220 fb->fbh = fbh;
221 fb->mmiot = mmiot;
222 fb->mmioh = mmioh;
223 sc->sc_fb = fb;
224
225 if (!console) {
226 if (radeonfb_setup(fb) != 0) {
227 printf(": can't setup frame buffer\n");
228 return;
229 }
230 }
231
232 printf(": %dx%d, %dbpp\n",
233 fb->ri.ri_width, fb->ri.ri_height, fb->ri.ri_depth);
234
235 sc->sc_scrlist[0] = &fb->wsd;
236 sc->sc_wsl.nscreens = 1;
237 sc->sc_wsl.screens = (const struct wsscreen_descr **)sc->sc_scrlist;
238
239 waa.console = console;
240 waa.scrdata = &sc->sc_wsl;
241 waa.accessops = &radeonfb_accessops;
242 waa.accesscookie = sc;
243 waa.defaultscreens = 0;
244
245 sc->sc_mode = WSDISPLAYIO_MODE_EMUL;
246
247 config_found(self, &waa, wsemuldisplaydevprint);
248 }
249
250 /*
251 * wsdisplay accessops
252 */
253
254 int
radeonfb_alloc_screen(void * v,const struct wsscreen_descr * type,void ** cookiep,int * curxp,int * curyp,uint32_t * attrp)255 radeonfb_alloc_screen(void *v, const struct wsscreen_descr *type,
256 void **cookiep, int *curxp, int *curyp, uint32_t *attrp)
257 {
258 struct radeonfb_softc *sc = (struct radeonfb_softc *)v;
259 struct rasops_info *ri = &sc->sc_fb->ri;
260
261 if (sc->sc_nscr > 0)
262 return ENOMEM;
263
264 *cookiep = ri;
265 *curxp = *curyp = 0;
266 ri->ri_ops.pack_attr(ri, 0, 0, 0, attrp);
267 sc->sc_nscr++;
268
269 return 0;
270 }
271
272 void
radeonfb_free_screen(void * v,void * cookie)273 radeonfb_free_screen(void *v, void *cookie)
274 {
275 struct radeonfb_softc *sc = (struct radeonfb_softc *)v;
276
277 sc->sc_nscr--;
278 }
279
280 int
radeonfb_ioctl(void * v,u_long cmd,caddr_t data,int flags,struct proc * p)281 radeonfb_ioctl(void *v, u_long cmd, caddr_t data, int flags, struct proc *p)
282 {
283 struct radeonfb_softc *sc = (struct radeonfb_softc *)v;
284 struct radeonfb *fb = sc->sc_fb;
285 struct rasops_info *ri = &fb->ri;
286 struct wsdisplay_fbinfo *wdf;
287 #if 0
288 struct pcisel *sel;
289 #endif
290
291 switch (cmd) {
292 case WSDISPLAYIO_GTYPE:
293 *(u_int *)data = WSDISPLAY_TYPE_RADEONFB;
294 break;
295 case WSDISPLAYIO_SMODE:
296 sc->sc_mode = *(u_int *)data;
297 if (sc->sc_mode == WSDISPLAYIO_MODE_EMUL) {
298 /* Clear screen. */
299 radeonfb_setup(fb);
300 radeonfb_fillrect(fb, 0, 0, ri->ri_width,
301 ri->ri_height, ri->ri_devcmap[WSCOL_BLACK]);
302 }
303 break;
304 case WSDISPLAYIO_GINFO:
305 wdf = (struct wsdisplay_fbinfo *)data;
306 wdf->width = ri->ri_width;
307 wdf->height = ri->ri_height;
308 wdf->depth = ri->ri_depth;
309 wdf->stride = ri->ri_stride;
310 wdf->offset = 0;
311 wdf->cmsize = 0;
312 break;
313 case WSDISPLAYIO_LINEBYTES:
314 *(u_int *)data = ri->ri_stride;
315 break;
316
317 #if 0
318 case WSDISPLAYIO_GPCIID:
319 sel = (struct pcisel *)data;
320 sel->pc_bus = PCITAG_BUS(sc->sc_pcitag);
321 sel->pc_dev = PCITAG_DEV(sc->sc_pcitag);
322 sel->pc_func = PCITAG_FUN(sc->sc_pcitag);
323 break;
324 #endif
325
326 case WSDISPLAYIO_SVIDEO:
327 case WSDISPLAYIO_GVIDEO:
328 break;
329
330 default:
331 return -1;
332 }
333
334 return 0;
335 }
336
337 int
radeonfb_show_screen(void * v,void * cookie,int waitok,void (* cb)(void *,int,int),void * cbarg)338 radeonfb_show_screen(void *v, void *cookie, int waitok,
339 void (*cb)(void *, int, int), void *cbarg)
340 {
341 return 0;
342 }
343
344 paddr_t
radeonfb_mmap(void * v,off_t off,int prot)345 radeonfb_mmap(void *v, off_t off, int prot)
346 {
347 struct radeonfb_softc *sc = (struct radeonfb_softc *)v;
348 struct radeonfb *fb = sc->sc_fb;
349
350 if ((off & PAGE_MASK) != 0)
351 return -1;
352
353 switch (sc->sc_mode) {
354 case WSDISPLAYIO_MODE_MAPPED:
355 #ifdef APERTURE
356 if (allowaperture == 0)
357 return (-1);
358 #endif
359
360 if (sc->sc_mmiosize == 0)
361 return (-1);
362
363 if (off >= sc->sc_membase &&
364 off < (sc->sc_membase + sc->sc_memsize))
365 return (bus_space_mmap(fb->fbt,
366 sc->sc_membase, off - sc->sc_membase,
367 prot, BUS_SPACE_MAP_LINEAR));
368
369 if (off >= sc->sc_mmiobase &&
370 off < (sc->sc_mmiobase + sc->sc_mmiosize))
371 return (bus_space_mmap(fb->mmiot,
372 sc->sc_mmiobase, off - sc->sc_mmiobase,
373 prot, BUS_SPACE_MAP_LINEAR));
374 break;
375
376 case WSDISPLAYIO_MODE_DUMBFB:
377 /*
378 * Don't allow mmap if the frame buffer area is not page aligned.
379 * XXX we should reprogram it to a page aligned boundary at attach
380 * XXX time if this isn't the case.
381 */
382 if ((fb->memoff % PAGE_SIZE) != 0)
383 return (-1);
384
385 if (off >= 0 && off < sc->sc_memsize / 2) {
386 bus_addr_t base = sc->sc_membase + fb->memoff;
387
388 return (bus_space_mmap(fb->fbt, base, off,
389 prot, BUS_SPACE_MAP_LINEAR));
390 }
391 break;
392 }
393
394 return (-1);
395 }
396
397 int
radeonfb_load_font(void * v,void * emulcookie,struct wsdisplay_font * font)398 radeonfb_load_font(void *v, void *emulcookie, struct wsdisplay_font *font)
399 {
400 struct radeonfb_softc *sc = (struct radeonfb_softc *)v;
401 struct rasops_info *ri = &sc->sc_fb->ri;
402
403 return rasops_load_font(ri, emulcookie, font);
404 }
405
406 int
radeonfb_list_font(void * v,struct wsdisplay_font * font)407 radeonfb_list_font(void *v, struct wsdisplay_font *font)
408 {
409 struct radeonfb_softc *sc = (struct radeonfb_softc *)v;
410 struct rasops_info *ri = &sc->sc_fb->ri;
411
412 return rasops_list_font(ri, font);
413 }
414
415 /*
416 * Accelerated routines.
417 */
418
419 int
radeonfb_copycols(void * cookie,int row,int src,int dst,int num)420 radeonfb_copycols(void *cookie, int row, int src, int dst, int num)
421 {
422 struct rasops_info *ri = cookie;
423 struct radeonfb *fb = ri->ri_hw;
424
425 num *= ri->ri_font->fontwidth;
426 src *= ri->ri_font->fontwidth;
427 dst *= ri->ri_font->fontwidth;
428 row *= ri->ri_font->fontheight;
429
430 radeonfb_copyrect(fb, ri->ri_xorigin + src, ri->ri_yorigin + row,
431 ri->ri_xorigin + dst, ri->ri_yorigin + row,
432 num, ri->ri_font->fontheight);
433
434 return 0;
435 }
436
437 int
radeonfb_erasecols(void * cookie,int row,int col,int num,uint32_t attr)438 radeonfb_erasecols(void *cookie, int row, int col, int num, uint32_t attr)
439 {
440 struct rasops_info *ri = cookie;
441 struct radeonfb *fb = ri->ri_hw;
442 int bg, fg;
443
444 ri->ri_ops.unpack_attr(cookie, attr, &fg, &bg, NULL);
445
446 row *= ri->ri_font->fontheight;
447 col *= ri->ri_font->fontwidth;
448 num *= ri->ri_font->fontwidth;
449
450 radeonfb_fillrect(fb, ri->ri_xorigin + col, ri->ri_yorigin + row,
451 num, ri->ri_font->fontheight, ri->ri_devcmap[bg]);
452
453 return 0;
454 }
455
456 int
radeonfb_copyrows(void * cookie,int src,int dst,int num)457 radeonfb_copyrows(void *cookie, int src, int dst, int num)
458 {
459 struct rasops_info *ri = cookie;
460 struct radeonfb *fb = ri->ri_hw;
461
462 num *= ri->ri_font->fontheight;
463 src *= ri->ri_font->fontheight;
464 dst *= ri->ri_font->fontheight;
465
466 radeonfb_copyrect(fb, ri->ri_xorigin, ri->ri_yorigin + src,
467 ri->ri_xorigin, ri->ri_yorigin + dst, ri->ri_emuwidth, num);
468
469 return 0;
470 }
471
472 int
radeonfb_eraserows(void * cookie,int row,int num,uint32_t attr)473 radeonfb_eraserows(void *cookie, int row, int num, uint32_t attr)
474 {
475 struct rasops_info *ri = cookie;
476 struct radeonfb *fb = ri->ri_hw;
477 int bg, fg;
478 int x, y, w;
479
480 ri->ri_ops.unpack_attr(cookie, attr, &fg, &bg, NULL);
481
482 if ((num == ri->ri_rows) && ISSET(ri->ri_flg, RI_FULLCLEAR)) {
483 num = ri->ri_height;
484 x = y = 0;
485 w = ri->ri_width;
486 } else {
487 num *= ri->ri_font->fontheight;
488 x = ri->ri_xorigin;
489 y = ri->ri_yorigin + row * ri->ri_font->fontheight;
490 w = ri->ri_emuwidth;
491 }
492 radeonfb_fillrect(fb, x, y, w, num, ri->ri_devcmap[bg]);
493
494 return 0;
495 }
496
497 void
radeonfb_wait_fifo(struct radeonfb * fb,int n)498 radeonfb_wait_fifo(struct radeonfb *fb, int n)
499 {
500 int i;
501
502 for (i = 1000000; i != 0; i--) {
503 if ((bus_space_read_4(fb->mmiot, fb->mmioh,
504 RADEON_RBBM_STATUS) & RADEON_RBBM_FIFOCNT_MASK) >= n)
505 break;
506 DELAY(1);
507 }
508 }
509
510 void
radeonfb_wait(struct radeonfb * fb)511 radeonfb_wait(struct radeonfb *fb)
512 {
513 int i;
514
515 radeonfb_wait_fifo(fb, 64);
516
517 for (i = 1000000; i != 0; i--) {
518 if ((bus_space_read_4(fb->mmiot, fb->mmioh,
519 RADEON_RBBM_STATUS) & RADEON_RBBM_ACTIVE) == 0)
520 break;
521 DELAY(1);
522 }
523
524 bus_space_write_4(fb->mmiot, fb->mmioh,
525 RADEON_RB3D_DSTCACHE_CTLSTAT, RADEON_RB3D_DC_FLUSH_ALL);
526
527 for (i = 1000000; i != 0; i--) {
528 if ((bus_space_read_4(fb->mmiot, fb->mmioh,
529 RADEON_RB3D_DSTCACHE_CTLSTAT) & RADEON_RB3D_DC_BUSY) == 0)
530 break;
531 DELAY(1);
532 }
533 }
534
535 void
radeonfb_copyrect(struct radeonfb * fb,int sx,int sy,int dx,int dy,int w,int h)536 radeonfb_copyrect(struct radeonfb *fb, int sx, int sy, int dx, int dy,
537 int w, int h)
538 {
539 uint32_t gmc;
540 uint32_t dir;
541
542 radeonfb_wait_fifo(fb, 1);
543 bus_space_write_4(fb->mmiot, fb->mmioh, RADEON_WAIT_UNTIL,
544 RADEON_WAIT_HOST_IDLECLEAN | RADEON_WAIT_2D_IDLECLEAN);
545
546 if (dy < sy) {
547 dir = RADEON_DST_Y_TOP_TO_BOTTOM;
548 } else {
549 sy += h - 1;
550 dy += h - 1;
551 dir = 0;
552 }
553 if (dx < sx) {
554 dir |= RADEON_DST_X_LEFT_TO_RIGHT;
555 } else {
556 sx += w - 1;
557 dx += w - 1;
558 }
559
560 radeonfb_wait_fifo(fb, 6);
561
562 gmc = RADEON_GMC_DST_16BPP;
563 gmc |= RADEON_GMC_BRUSH_NONE;
564 gmc |= RADEON_GMC_SRC_DATATYPE_COLOR;
565 gmc |= RADEON_GMC_SRC_SOURCE_MEMORY;
566 gmc |= RADEON_ROP3_S;
567 gmc |= RADEON_GMC_CLR_CMP_CNTL_DIS;
568 bus_space_write_4(fb->mmiot, fb->mmioh,
569 RADEON_DP_GUI_MASTER_CNTL, gmc);
570 bus_space_write_4(fb->mmiot, fb->mmioh,
571 RADEON_DP_WRITE_MASK, 0xffffffff);
572 bus_space_write_4(fb->mmiot, fb->mmioh,
573 RADEON_DP_CNTL, dir);
574
575 bus_space_write_4(fb->mmiot, fb->mmioh,
576 RADEON_SRC_Y_X, RADEON_COORDS(sx, sy));
577 bus_space_write_4(fb->mmiot, fb->mmioh,
578 RADEON_DST_Y_X, RADEON_COORDS(dx, dy));
579 bus_space_write_4(fb->mmiot, fb->mmioh,
580 RADEON_DST_HEIGHT_WIDTH, RADEON_COORDS(w, h));
581
582 radeonfb_wait(fb);
583 }
584
585 void
radeonfb_fillrect(struct radeonfb * fb,int x,int y,int w,int h,int color)586 radeonfb_fillrect(struct radeonfb *fb, int x, int y, int w, int h, int color)
587 {
588 uint32_t gmc;
589
590 radeonfb_wait_fifo(fb, 1);
591 bus_space_write_4(fb->mmiot, fb->mmioh, RADEON_WAIT_UNTIL,
592 RADEON_WAIT_HOST_IDLECLEAN | RADEON_WAIT_2D_IDLECLEAN);
593
594 radeonfb_wait_fifo(fb, 6);
595
596 gmc = RADEON_GMC_DST_16BPP;
597 gmc |= RADEON_GMC_BRUSH_SOLID_COLOR;
598 gmc |= RADEON_GMC_SRC_DATATYPE_COLOR;
599 gmc |= RADEON_ROP3_P;
600 gmc |= RADEON_GMC_CLR_CMP_CNTL_DIS;
601 bus_space_write_4(fb->mmiot, fb->mmioh,
602 RADEON_DP_GUI_MASTER_CNTL, gmc);
603 bus_space_write_4(fb->mmiot, fb->mmioh,
604 RADEON_DP_BRUSH_FRGD_CLR, color);
605 bus_space_write_4(fb->mmiot, fb->mmioh,
606 RADEON_DP_WRITE_MASK, 0xffffffff);
607 bus_space_write_4(fb->mmiot, fb->mmioh, RADEON_DP_CNTL,
608 RADEON_DST_Y_TOP_TO_BOTTOM | RADEON_DST_X_LEFT_TO_RIGHT);
609
610 bus_space_write_4(fb->mmiot, fb->mmioh,
611 RADEON_DST_Y_X, RADEON_COORDS(x, y));
612 bus_space_write_4(fb->mmiot, fb->mmioh,
613 RADEON_DST_HEIGHT_WIDTH, RADEON_COORDS(w, h));
614
615 radeonfb_wait(fb);
616 }
617
618 /*
619 * Frame buffer initialization.
620 */
621
622 int
radeonfb_setup(struct radeonfb * fb)623 radeonfb_setup(struct radeonfb *fb)
624 {
625 struct rasops_info *ri;
626 uint width, height, bpp;
627
628 /*
629 * The firmware sets up the framebuffer such that at starts at
630 * an offset from the start of video memory.
631 */
632 fb->memoff =
633 bus_space_read_4(fb->mmiot, fb->mmioh, RADEON_CRTC_OFFSET);
634
635 width = 800; /* XXX */
636 height = 600; /* XXX */
637 bpp = 16;
638
639 ri = &fb->ri;
640 ri->ri_width = width;
641 ri->ri_height = height;
642 ri->ri_depth = bpp;
643 ri->ri_stride = (ri->ri_width * ri->ri_depth) / 8;
644 ri->ri_flg = RI_CENTER | RI_CLEAR | RI_FULLCLEAR;
645 ri->ri_bits = (void *)(bus_space_vaddr(fb->fbt, fb->fbh) + fb->memoff);
646 ri->ri_hw = fb;
647
648 ri->ri_rnum = 5;
649 ri->ri_rpos = 11;
650 ri->ri_gnum = 6;
651 ri->ri_gpos = 5;
652 ri->ri_bnum = 5;
653 ri->ri_bpos = 0;
654
655 radeonfb_wait_fifo(fb, 2);
656 bus_space_write_4(fb->mmiot, fb->mmioh, RADEON_DEFAULT_PITCH_OFFSET,
657 ((ri->ri_stride >> 6) << 22) | (fb->memoff >> 10));
658 bus_space_write_4(fb->mmiot, fb->mmioh,
659 RADEON_DEFAULT_SC_BOTTOM_RIGHT, 0x1fff1fff);
660
661 rasops_init(ri, 160, 160);
662
663 strlcpy(fb->wsd.name, "std", sizeof(fb->wsd.name));
664 fb->wsd.ncols = ri->ri_cols;
665 fb->wsd.nrows = ri->ri_rows;
666 fb->wsd.textops = &ri->ri_ops;
667 fb->wsd.fontwidth = ri->ri_font->fontwidth;
668 fb->wsd.fontheight = ri->ri_font->fontheight;
669 fb->wsd.capabilities = ri->ri_caps;
670
671 #if 0
672 ri->ri_ops.copyrows = radeonfb_copyrows;
673 ri->ri_ops.copycols = radeonfb_copycols;
674 ri->ri_ops.eraserows = radeonfb_eraserows;
675 ri->ri_ops.erasecols = radeonfb_erasecols;
676 #endif
677
678 return 0;
679 }
680
681 /*
682 * Early console code
683 */
684
685 int radeonfb_cnattach(bus_space_tag_t, bus_space_tag_t, pcitag_t, pcireg_t);
686
687 int
radeonfb_cnattach(bus_space_tag_t memt,bus_space_tag_t iot,pcitag_t tag,pcireg_t id)688 radeonfb_cnattach(bus_space_tag_t memt, bus_space_tag_t iot, pcitag_t tag,
689 pcireg_t id)
690 {
691 uint32_t defattr;
692 struct rasops_info *ri;
693 pcireg_t bar;
694 int rc;
695
696 /* filter out unrecognized devices */
697 switch (id) {
698 default:
699 return ENODEV;
700 case PCI_ID_CODE(PCI_VENDOR_ATI, 0x9615):
701 break;
702 }
703
704 bar = pci_conf_read_early(tag, RADEON_PCI_MEM);
705 if (PCI_MAPREG_TYPE(bar) != PCI_MAPREG_TYPE_MEM)
706 return EINVAL;
707 radeonfbcn.fbt = memt;
708 rc = bus_space_map(memt, PCI_MAPREG_MEM_ADDR(bar), 1 /* XXX */,
709 BUS_SPACE_MAP_LINEAR, &radeonfbcn.fbh);
710 if (rc != 0)
711 return rc;
712
713 bar = pci_conf_read_early(tag, RADEON_PCI_MMIO);
714 if (PCI_MAPREG_TYPE(bar) != PCI_MAPREG_TYPE_MEM)
715 return EINVAL;
716 radeonfbcn.mmiot = memt;
717 rc = bus_space_map(memt, PCI_MAPREG_MEM_ADDR(bar), 1 /* XXX */,
718 BUS_SPACE_MAP_LINEAR, &radeonfbcn.mmioh);
719 if (rc != 0)
720 return rc;
721
722 rc = radeonfb_setup(&radeonfbcn);
723 if (rc != 0)
724 return rc;
725
726 ri = &radeonfbcn.ri;
727 ri->ri_ops.pack_attr(ri, 0, 0, 0, &defattr);
728 wsdisplay_cnattach(&radeonfbcn.wsd, ri, 0, 0, defattr);
729
730 return 0;
731 }
732