xref: /openbsd-src/sys/arch/loongson/dev/radeonfb.c (revision 63294167c4eaf171adac4fb2d8cc6d072a13af61)
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