1 /* $NetBSD: chipsfb.c,v 1.19 2009/05/12 08:23:00 cegger Exp $ */
4 * Copyright (c) 2006 Michael Lorenz
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 * A console driver for Chips & Technologies 65550 graphics controllers
30 * tested on macppc only so far
33 #include <sys/cdefs.h>
34 __KERNEL_RCSID(0, "$NetBSD: chipsfb.c,v 1.19 2009/05/12 08:23:00 cegger Exp $");
36 #include <sys/param.h>
37 #include <sys/systm.h>
38 #include <sys/kernel.h>
39 #include <sys/device.h>
40 #include <sys/malloc.h>
41 #include <sys/callout.h>
43 #include <sys/kauth.h>
45 #include <uvm/uvm_extern.h>
47 #include <dev/videomode/videomode.h>
49 #include <dev/pci/pcivar.h>
50 #include <dev/pci/pcireg.h>
51 #include <dev/pci/pcidevs.h>
52 #include <dev/pci/pciio.h>
53 #include <dev/pci/chipsfbreg.h>
55 #include <dev/wscons/wsdisplayvar.h>
56 #include <dev/wscons/wsconsio.h>
57 #include <dev/wsfont/wsfont.h>
58 #include <dev/rasops/rasops.h>
59 #include <dev/wscons/wsdisplay_vconsvar.h>
61 #include <dev/i2c/i2cvar.h>
63 #include "opt_wsemul.h"
64 #include "opt_chipsfb.h"
66 struct chipsfb_softc
{
68 pci_chipset_tag_t sc_pc
;
71 bus_space_tag_t sc_memt
;
72 bus_space_tag_t sc_iot
;
73 bus_space_handle_t sc_memh
;
75 bus_space_tag_t sc_fbt
;
76 bus_space_tag_t sc_ioregt
;
77 bus_space_handle_t sc_fbh
;
78 bus_space_handle_t sc_ioregh
;
79 bus_addr_t sc_fb
, sc_ioreg
;
80 bus_size_t sc_fbsize
, sc_ioregsize
;
87 int width
, height
, linebytes
;
92 u_char sc_cmap_red
[256];
93 u_char sc_cmap_green
[256];
94 u_char sc_cmap_blue
[256];
99 * DDC2 clock is on GPIO1, data on GPIO0
101 struct i2c_controller sc_i2c
;
102 uint8_t sc_edid
[1024];
103 int sc_edidbytes
; /* number of bytes read from the monitor */
105 struct vcons_data vd
;
108 static struct vcons_screen chipsfb_console_screen
;
110 extern const u_char rasops_cmap
[768];
112 static int chipsfb_match(device_t
, cfdata_t
, void *);
113 static void chipsfb_attach(device_t
, device_t
, void *);
115 CFATTACH_DECL(chipsfb
, sizeof(struct chipsfb_softc
), chipsfb_match
,
116 chipsfb_attach
, NULL
, NULL
);
118 static void chipsfb_init(struct chipsfb_softc
*);
120 static void chipsfb_cursor(void *, int, int, int);
121 static void chipsfb_copycols(void *, int, int, int, int);
122 static void chipsfb_erasecols(void *, int, int, int, long);
123 static void chipsfb_copyrows(void *, int, int, int);
124 static void chipsfb_eraserows(void *, int, int, long);
127 static int chipsfb_allocattr(void *, int, int, int, long *);
128 static void chipsfb_scroll(void *, void *, int);
129 static int chipsfb_load_font(void *, void *, struct wsdisplay_font
*);
132 static int chipsfb_putcmap(struct chipsfb_softc
*,
133 struct wsdisplay_cmap
*);
134 static int chipsfb_getcmap(struct chipsfb_softc
*,
135 struct wsdisplay_cmap
*);
136 static int chipsfb_putpalreg(struct chipsfb_softc
*, uint8_t, uint8_t,
139 static void chipsfb_bitblt(struct chipsfb_softc
*, int, int, int, int,
141 static void chipsfb_rectfill(struct chipsfb_softc
*, int, int, int, int,
143 static void chipsfb_putchar(void *, int, int, u_int
, long);
144 static void chipsfb_setup_mono(struct chipsfb_softc
*, int, int, int,
145 int, uint32_t, uint32_t);
146 static void chipsfb_feed(struct chipsfb_softc
*, int, uint8_t *);
149 static void chipsfb_showpal(struct chipsfb_softc
*);
151 static void chipsfb_restore_palette(struct chipsfb_softc
*);
153 static void chipsfb_wait_idle(struct chipsfb_softc
*);
155 static uint32_t chipsfb_probe_vram(struct chipsfb_softc
*);
157 struct wsscreen_descr chipsfb_defaultscreen
= {
162 WSSCREEN_WSCOLORS
| WSSCREEN_HILIT
,
165 const struct wsscreen_descr
*_chipsfb_scrlist
[] = {
166 &chipsfb_defaultscreen
,
167 /* XXX other formats, graphics screen? */
170 struct wsscreen_list chipsfb_screenlist
= {
171 sizeof(_chipsfb_scrlist
) / sizeof(struct wsscreen_descr
*), _chipsfb_scrlist
174 static int chipsfb_ioctl(void *, void *, u_long
, void *, int,
176 static paddr_t
chipsfb_mmap(void *, void *, off_t
, int);
177 static void chipsfb_clearscreen(struct chipsfb_softc
*);
178 static void chipsfb_init_screen(void *, struct vcons_screen
*, int,
182 struct wsdisplay_accessops chipsfb_accessops
= {
185 NULL
, /* load_font */
191 * Inline functions for getting access to register aperture.
194 chipsfb_write32(struct chipsfb_softc
*sc
, uint32_t reg
, uint32_t val
)
196 bus_space_write_4(sc
->sc_fbt
, sc
->sc_fbh
, reg
, val
);
199 static inline uint32_t
200 chipsfb_read32(struct chipsfb_softc
*sc
, uint32_t reg
)
202 return bus_space_read_4(sc
->sc_fbt
, sc
->sc_fbh
, reg
);
206 chipsfb_write_vga(struct chipsfb_softc
*sc
, uint32_t reg
, uint8_t val
)
208 bus_space_write_1(sc
->sc_iot
, sc
->sc_ioregh
, reg
, val
);
211 static inline uint8_t
212 chipsfb_read_vga(struct chipsfb_softc
*sc
, uint32_t reg
)
214 return bus_space_read_1(sc
->sc_iot
, sc
->sc_ioregh
, reg
);
217 static inline uint8_t
218 chipsfb_read_indexed(struct chipsfb_softc
*sc
, uint32_t reg
, uint8_t index
)
221 chipsfb_write_vga(sc
, reg
& 0xfffe, index
);
222 return chipsfb_read_vga(sc
, reg
| 0x0001);
226 chipsfb_write_indexed(struct chipsfb_softc
*sc
, uint32_t reg
, uint8_t index
,
230 chipsfb_write_vga(sc
, reg
& 0xfffe, index
);
231 chipsfb_write_vga(sc
, reg
| 0x0001, val
);
235 chipsfb_wait_idle(struct chipsfb_softc
*sc
)
239 chipsfb_write32(sc
, CT_OFF_FB
+ (800 * 598) - 4, 0);
242 /* spin until the blitter is idle */
243 while ((chipsfb_read32(sc
, CT_BLT_CONTROL
) & BLT_IS_BUSY
) != 0) {
247 chipsfb_write32(sc
, CT_OFF_FB
+ (800 * 598) - 4, 0xffffffff);
252 chipsfb_match(device_t parent
, cfdata_t match
, void *aux
)
254 struct pci_attach_args
*pa
= (struct pci_attach_args
*)aux
;
256 if (PCI_CLASS(pa
->pa_class
) != PCI_CLASS_DISPLAY
||
257 PCI_SUBCLASS(pa
->pa_class
) != PCI_SUBCLASS_DISPLAY_VGA
)
259 if ((PCI_VENDOR(pa
->pa_id
) == PCI_VENDOR_CHIPS
) &&
260 (PCI_PRODUCT(pa
->pa_id
) == PCI_PRODUCT_CHIPS_65550
))
262 if ((PCI_VENDOR(pa
->pa_id
) == PCI_VENDOR_CHIPS
) &&
263 (PCI_PRODUCT(pa
->pa_id
) == PCI_PRODUCT_CHIPS_65554
))
269 chipsfb_attach(device_t parent
, device_t self
, void *aux
)
271 struct chipsfb_softc
*sc
= device_private(self
);
272 struct pci_attach_args
*pa
= aux
;
274 struct wsemuldisplaydev_attach_args aa
;
275 struct rasops_info
*ri
;
276 prop_dictionary_t dict
;
279 bool console
= false;
280 int width
, height
, i
, j
;
283 dict
= device_properties(self
);
284 sc
->sc_mode
= WSDISPLAYIO_MODE_EMUL
;
285 sc
->sc_pc
= pa
->pa_pc
;
286 sc
->sc_pcitag
= pa
->pa_tag
;
289 screg
= pci_conf_read(sc
->sc_pc
, sc
->sc_pcitag
, PCI_COMMAND_STATUS_REG
);
290 screg
|= PCI_FLAGS_IO_ENABLED
| PCI_FLAGS_MEM_ENABLED
;
291 pci_conf_write(sc
->sc_pc
, sc
->sc_pcitag
,PCI_COMMAND_STATUS_REG
,screg
);
293 pci_devinfo(pa
->pa_id
, pa
->pa_class
, 0, devinfo
, sizeof(devinfo
));
294 aprint_normal(": %s (rev. 0x%02x)\n", devinfo
, PCI_REVISION(pa
->pa_class
));
296 printf(prop_dictionary_externalize(dict
));
299 sc
->sc_memt
= pa
->pa_memt
;
300 sc
->sc_iot
= pa
->pa_iot
;
302 /* the framebuffer */
303 if (pci_mapreg_map(pa
, 0x10, PCI_MAPREG_TYPE_MEM
,
304 BUS_SPACE_MAP_LINEAR
,
305 &sc
->sc_fbt
, &sc
->sc_fbh
, &sc
->sc_fb
, &sc
->sc_fbsize
)) {
306 aprint_error_dev(&sc
->sc_dev
, "failed to map the frame buffer.\n");
309 /* IO-mapped registers */
310 if (bus_space_map(sc
->sc_iot
, 0x0, 0x400, 0, &sc
->sc_ioregh
) != 0) {
311 aprint_error_dev(&sc
->sc_dev
, "failed to map IO registers.\n");
314 sc
->memsize
= chipsfb_probe_vram(sc
);
317 /* we should read these from the chip instead of depending on OF */
320 /* detect panel size */
321 width
= chipsfb_read_indexed(sc
, CT_FP_INDEX
, FP_HSIZE_LSB
);
322 width
|= (chipsfb_read_indexed(sc
, CT_FP_INDEX
, FP_HORZ_OVERFLOW_1
)
324 width
= (width
+ 1) * 8;
325 height
= chipsfb_read_indexed(sc
, CT_FP_INDEX
, FP_VSIZE_LSB
);
326 height
|= (chipsfb_read_indexed(sc
, CT_FP_INDEX
, FP_VERT_OVERFLOW_1
)
329 aprint_verbose("Panel size: %d x %d\n", width
, height
);
331 if (!prop_dictionary_get_uint32(dict
, "width", &sc
->width
))
333 if (!prop_dictionary_get_uint32(dict
, "height", &sc
->height
))
335 if (!prop_dictionary_get_uint32(dict
, "depth", &sc
->bits_per_pixel
))
336 sc
->bits_per_pixel
= 8;
337 if (!prop_dictionary_get_uint32(dict
, "linebytes", &sc
->linebytes
))
338 sc
->linebytes
= (sc
->width
* sc
->bits_per_pixel
) >> 3;
340 prop_dictionary_get_bool(dict
, "is_console", &console
);
343 /* XXX this should at least be configurable via kernel config */
344 chipsfb_set_videomode(sc
, &videomode_list
[16]);
347 vcons_init(&sc
->vd
, sc
, &chipsfb_defaultscreen
, &chipsfb_accessops
);
348 sc
->vd
.init_screen
= chipsfb_init_screen
;
350 ri
= &chipsfb_console_screen
.scr_ri
;
352 vcons_init_screen(&sc
->vd
, &chipsfb_console_screen
, 1,
354 chipsfb_console_screen
.scr_flags
|= VCONS_SCREEN_IS_STATIC
;
356 chipsfb_defaultscreen
.textops
= &ri
->ri_ops
;
357 chipsfb_defaultscreen
.capabilities
= ri
->ri_caps
;
358 chipsfb_defaultscreen
.nrows
= ri
->ri_rows
;
359 chipsfb_defaultscreen
.ncols
= ri
->ri_cols
;
360 wsdisplay_cnattach(&chipsfb_defaultscreen
, ri
, 0, 0, defattr
);
363 * since we're not the console we can postpone the rest
364 * until someone actually allocates a screen for us
367 chipsfb_set_videomode(sc
, &videomode_list
[0]);
371 rasops_unpack_attr(defattr
, &fg
, &bg
, &ul
);
372 sc
->sc_bg
= ri
->ri_devcmap
[bg
];
373 chipsfb_clearscreen(sc
);
376 vcons_replay_msgbuf(&chipsfb_console_screen
);
378 aprint_normal_dev(&sc
->sc_dev
, "%d MB aperture, %d MB VRAM at 0x%08x\n",
379 (u_int
)(sc
->sc_fbsize
>> 20),
380 sc
->memsize
>> 20, (u_int
)sc
->sc_fb
);
382 aprint_debug("fb: %08lx\n", (ulong
)ri
->ri_bits
);
386 for (i
= 0; i
< 256; i
++) {
387 chipsfb_putpalreg(sc
, i
, rasops_cmap
[j
], rasops_cmap
[j
+ 1],
392 aa
.console
= console
;
393 aa
.scrdata
= &chipsfb_screenlist
;
394 aa
.accessops
= &chipsfb_accessops
;
395 aa
.accesscookie
= &sc
->vd
;
397 config_found(self
, &aa
, wsemuldisplaydevprint
);
401 chipsfb_putpalreg(struct chipsfb_softc
*sc
, uint8_t index
, uint8_t r
,
402 uint8_t g
, uint8_t b
)
405 sc
->sc_cmap_red
[index
] = r
;
406 sc
->sc_cmap_green
[index
] = g
;
407 sc
->sc_cmap_blue
[index
] = b
;
409 chipsfb_write_vga(sc
, CT_DACMASK
, 0xff);
410 chipsfb_write_vga(sc
, CT_WRITEINDEX
, index
);
411 chipsfb_write_vga(sc
, CT_DACDATA
, r
);
412 chipsfb_write_vga(sc
, CT_DACDATA
, g
);
413 chipsfb_write_vga(sc
, CT_DACDATA
, b
);
419 chipsfb_putcmap(struct chipsfb_softc
*sc
, struct wsdisplay_cmap
*cm
)
422 u_int index
= cm
->index
;
423 u_int count
= cm
->count
;
425 u_char rbuf
[256], gbuf
[256], bbuf
[256];
428 aprint_debug("putcmap: %d %d\n",index
, count
);
430 if (cm
->index
>= 256 || cm
->count
> 256 ||
431 (cm
->index
+ cm
->count
) > 256)
433 error
= copyin(cm
->red
, &rbuf
[index
], count
);
436 error
= copyin(cm
->green
, &gbuf
[index
], count
);
439 error
= copyin(cm
->blue
, &bbuf
[index
], count
);
443 memcpy(&sc
->sc_cmap_red
[index
], &rbuf
[index
], count
);
444 memcpy(&sc
->sc_cmap_green
[index
], &gbuf
[index
], count
);
445 memcpy(&sc
->sc_cmap_blue
[index
], &bbuf
[index
], count
);
447 r
= &sc
->sc_cmap_red
[index
];
448 g
= &sc
->sc_cmap_green
[index
];
449 b
= &sc
->sc_cmap_blue
[index
];
451 for (i
= 0; i
< count
; i
++) {
452 chipsfb_putpalreg(sc
, index
, *r
, *g
, *b
);
460 chipsfb_getcmap(struct chipsfb_softc
*sc
, struct wsdisplay_cmap
*cm
)
462 u_int index
= cm
->index
;
463 u_int count
= cm
->count
;
466 if (index
>= 255 || count
> 256 || index
+ count
> 256)
469 error
= copyout(&sc
->sc_cmap_red
[index
], cm
->red
, count
);
472 error
= copyout(&sc
->sc_cmap_green
[index
], cm
->green
, count
);
475 error
= copyout(&sc
->sc_cmap_blue
[index
], cm
->blue
, count
);
483 chipsfb_clearscreen(struct chipsfb_softc
*sc
)
485 chipsfb_rectfill(sc
, 0, 0, sc
->width
, sc
->height
, sc
->sc_bg
);
493 chipsfb_cursor(void *cookie
, int on
, int row
, int col
)
495 struct rasops_info
*ri
= cookie
;
496 struct vcons_screen
*scr
= ri
->ri_hw
;
497 struct chipsfb_softc
*sc
= scr
->scr_cookie
;
500 wi
= ri
->ri_font
->fontwidth
;
501 he
= ri
->ri_font
->fontheight
;
503 if (sc
->sc_mode
== WSDISPLAYIO_MODE_EMUL
) {
504 x
= ri
->ri_ccol
* wi
+ ri
->ri_xorigin
;
505 y
= ri
->ri_crow
* he
+ ri
->ri_yorigin
;
506 if (ri
->ri_flg
& RI_CURSOR
) {
507 chipsfb_bitblt(sc
, x
, y
, x
, y
, wi
, he
, ROP_NOT_DST
);
508 ri
->ri_flg
&= ~RI_CURSOR
;
513 x
= ri
->ri_ccol
* wi
+ ri
->ri_xorigin
;
514 y
= ri
->ri_crow
* he
+ ri
->ri_yorigin
;
515 chipsfb_bitblt(sc
, x
, y
, x
, y
, wi
, he
, ROP_NOT_DST
);
516 ri
->ri_flg
|= RI_CURSOR
;
519 ri
->ri_flg
&= ~RI_CURSOR
;
527 chipsfb_mapchar(void *cookie
, int uni
, u_int
*index
)
534 chipsfb_copycols(void *cookie
, int row
, int srccol
, int dstcol
, int ncols
)
536 struct rasops_info
*ri
= cookie
;
537 struct vcons_screen
*scr
= ri
->ri_hw
;
538 struct chipsfb_softc
*sc
= scr
->scr_cookie
;
539 int32_t xs
, xd
, y
, width
, height
;
541 if (sc
->sc_mode
== WSDISPLAYIO_MODE_EMUL
) {
542 xs
= ri
->ri_xorigin
+ ri
->ri_font
->fontwidth
* srccol
;
543 xd
= ri
->ri_xorigin
+ ri
->ri_font
->fontwidth
* dstcol
;
544 y
= ri
->ri_yorigin
+ ri
->ri_font
->fontheight
* row
;
545 width
= ri
->ri_font
->fontwidth
* ncols
;
546 height
= ri
->ri_font
->fontheight
;
547 chipsfb_bitblt(sc
, xs
, y
, xd
, y
, width
, height
, ROP_COPY
);
552 chipsfb_erasecols(void *cookie
, int row
, int startcol
, int ncols
,
555 struct rasops_info
*ri
= cookie
;
556 struct vcons_screen
*scr
= ri
->ri_hw
;
557 struct chipsfb_softc
*sc
= scr
->scr_cookie
;
558 int32_t x
, y
, width
, height
, fg
, bg
, ul
;
560 if (sc
->sc_mode
== WSDISPLAYIO_MODE_EMUL
) {
561 x
= ri
->ri_xorigin
+ ri
->ri_font
->fontwidth
* startcol
;
562 y
= ri
->ri_yorigin
+ ri
->ri_font
->fontheight
* row
;
563 width
= ri
->ri_font
->fontwidth
* ncols
;
564 height
= ri
->ri_font
->fontheight
;
565 rasops_unpack_attr(fillattr
, &fg
, &bg
, &ul
);
567 chipsfb_rectfill(sc
, x
, y
, width
, height
, ri
->ri_devcmap
[bg
]);
572 chipsfb_copyrows(void *cookie
, int srcrow
, int dstrow
, int nrows
)
574 struct rasops_info
*ri
= cookie
;
575 struct vcons_screen
*scr
= ri
->ri_hw
;
576 struct chipsfb_softc
*sc
= scr
->scr_cookie
;
577 int32_t x
, ys
, yd
, width
, height
;
579 if (sc
->sc_mode
== WSDISPLAYIO_MODE_EMUL
) {
581 ys
= ri
->ri_yorigin
+ ri
->ri_font
->fontheight
* srcrow
;
582 yd
= ri
->ri_yorigin
+ ri
->ri_font
->fontheight
* dstrow
;
583 width
= ri
->ri_emuwidth
;
584 height
= ri
->ri_font
->fontheight
* nrows
;
585 chipsfb_bitblt(sc
, x
, ys
, x
, yd
, width
, height
, ROP_COPY
);
590 chipsfb_eraserows(void *cookie
, int row
, int nrows
, long fillattr
)
592 struct rasops_info
*ri
= cookie
;
593 struct vcons_screen
*scr
= ri
->ri_hw
;
594 struct chipsfb_softc
*sc
= scr
->scr_cookie
;
595 int32_t x
, y
, width
, height
, fg
, bg
, ul
;
597 if (sc
->sc_mode
== WSDISPLAYIO_MODE_EMUL
) {
598 rasops_unpack_attr(fillattr
, &fg
, &bg
, &ul
);
599 if ((row
== 0) && (nrows
== ri
->ri_rows
)) {
600 /* clear the whole screen */
601 chipsfb_rectfill(sc
, 0, 0, ri
->ri_width
,
602 ri
->ri_height
, ri
->ri_devcmap
[bg
]);
605 y
= ri
->ri_yorigin
+ ri
->ri_font
->fontheight
* row
;
606 width
= ri
->ri_emuwidth
;
607 height
= ri
->ri_font
->fontheight
* nrows
;
608 chipsfb_rectfill(sc
, x
, y
, width
, height
,
615 chipsfb_bitblt(struct chipsfb_softc
*sc
, int xs
, int ys
, int xd
, int yd
,
616 int width
, int height
, uint8_t rop
)
618 uint32_t src
, dst
, cmd
= rop
, stride
, size
;
620 cmd
|= BLT_PAT_IS_SOLID
;
622 /* we assume 8 bit for now */
623 src
= xs
+ ys
* sc
->linebytes
;
624 dst
= xd
+ yd
* sc
->linebytes
;
627 /* right-to-left operation */
628 cmd
|= BLT_START_RIGHT
;
634 /* bottom-to-top operation */
635 cmd
|= BLT_START_BOTTOM
;
636 src
+= (height
- 1) * sc
->linebytes
;
637 dst
+= (height
- 1) * sc
->linebytes
;
640 stride
= (sc
->linebytes
<< 16) | sc
->linebytes
;
641 size
= (height
<< 16) | width
;
643 chipsfb_wait_idle(sc
);
644 chipsfb_write32(sc
, CT_BLT_STRIDE
, stride
);
645 chipsfb_write32(sc
, CT_BLT_SRCADDR
, src
);
646 chipsfb_write32(sc
, CT_BLT_DSTADDR
, dst
);
647 chipsfb_write32(sc
, CT_BLT_CONTROL
, cmd
);
648 chipsfb_write32(sc
, CT_BLT_SIZE
, size
);
650 chipsfb_wait_idle(sc
);
655 chipsfb_rectfill(struct chipsfb_softc
*sc
, int x
, int y
, int width
,
656 int height
, int colour
)
658 uint32_t dst
, cmd
, stride
, size
;
660 cmd
= BLT_PAT_IS_SOLID
| BLT_PAT_IS_MONO
| ROP_PAT
;
662 /* we assume 8 bit for now */
663 dst
= x
+ y
* sc
->linebytes
;
665 stride
= (sc
->linebytes
<< 16) | sc
->linebytes
;
666 size
= (height
<< 16) | width
;
668 chipsfb_wait_idle(sc
);
669 chipsfb_write32(sc
, CT_BLT_STRIDE
, stride
);
670 chipsfb_write32(sc
, CT_BLT_SRCADDR
, dst
);
671 chipsfb_write32(sc
, CT_BLT_DSTADDR
, dst
);
672 chipsfb_write32(sc
, CT_BLT_CONTROL
, cmd
);
673 chipsfb_write32(sc
, CT_BLT_BG
, colour
);
674 chipsfb_write32(sc
, CT_BLT_FG
, colour
);
675 chipsfb_write32(sc
, CT_BLT_SIZE
, size
);
677 chipsfb_wait_idle(sc
);
682 chipsfb_putchar(void *cookie
, int row
, int col
, u_int c
, long attr
)
684 struct rasops_info
*ri
= cookie
;
685 struct vcons_screen
*scr
= ri
->ri_hw
;
686 struct chipsfb_softc
*sc
= scr
->scr_cookie
;
688 if (__predict_false((unsigned int)row
> ri
->ri_rows
||
689 (unsigned int)col
> ri
->ri_cols
))
692 if (sc
->sc_mode
== WSDISPLAYIO_MODE_EMUL
) {
697 wi
= ri
->ri_font
->fontwidth
;
698 he
= ri
->ri_font
->fontheight
;
700 if (!CHAR_IN_FONT(c
, ri
->ri_font
))
702 bg
= (u_char
)ri
->ri_devcmap
[(attr
>> 16) & 0xf];
703 fg
= (u_char
)ri
->ri_devcmap
[(attr
>> 24) & 0xf];
704 x
= ri
->ri_xorigin
+ col
* wi
;
705 y
= ri
->ri_yorigin
+ row
* he
;
707 chipsfb_rectfill(sc
, x
, y
, wi
, he
, bg
);
709 uc
= c
-ri
->ri_font
->firstchar
;
710 data
= (uint8_t *)ri
->ri_font
->data
+ uc
*
712 chipsfb_setup_mono(sc
, x
, y
, wi
, he
, fg
, bg
);
713 chipsfb_feed(sc
, ri
->ri_font
->stride
* he
, data
);
719 chipsfb_setup_mono(struct chipsfb_softc
*sc
, int xd
, int yd
, int width
,
720 int height
, uint32_t fg
, uint32_t bg
)
722 uint32_t dst
, cmd
, stride
, size
;
724 cmd
= BLT_PAT_IS_SOLID
| BLT_SRC_IS_CPU
| BLT_SRC_IS_MONO
| ROP_COPY
;
726 /* we assume 8 bit for now */
727 dst
= xd
+ yd
* sc
->linebytes
;
729 stride
= (sc
->linebytes
<< 16);
730 size
= (height
<< 16) | width
;
732 chipsfb_wait_idle(sc
);
733 chipsfb_write32(sc
, CT_BLT_STRIDE
, stride
);
734 chipsfb_write32(sc
, CT_BLT_EXPCTL
, MONO_SRC_ALIGN_BYTE
);
735 chipsfb_write32(sc
, CT_BLT_DSTADDR
, dst
);
736 chipsfb_write32(sc
, CT_BLT_SRCADDR
, 0);
737 chipsfb_write32(sc
, CT_BLT_CONTROL
, cmd
);
738 chipsfb_write32(sc
, CT_BLT_BG
, bg
);
739 chipsfb_write32(sc
, CT_BLT_FG
, fg
);
740 chipsfb_write32(sc
, CT_BLT_SIZE
, size
);
744 chipsfb_feed(struct chipsfb_softc
*sc
, int count
, uint8_t *data
)
747 uint32_t latch
= 0, bork
;
750 for (i
= 0; i
< count
; i
++) {
752 latch
|= (bork
<< shift
);
754 chipsfb_write32(sc
, CT_OFF_DATA
, latch
);
762 chipsfb_write32(sc
, CT_OFF_DATA
, latch
);
765 /* apparently the chip wants 64bit-aligned data or it won't go idle */
766 if ((count
+ 3) & 0x04) {
767 chipsfb_write32(sc
, CT_OFF_DATA
, 0);
770 chipsfb_wait_idle(sc
);
776 chipsfb_showpal(struct chipsfb_softc
*sc
)
780 for (i
= 0; i
< 16; i
++) {
781 chipsfb_rectfill(sc
, x
, 0, 64, 64, i
);
789 chipsfb_allocattr(void *cookie
, int fg
, int bg
, int flags
, long *attrp
)
797 chipsfb_restore_palette(struct chipsfb_softc
*sc
)
801 for (i
= 0; i
< 256; i
++) {
802 chipsfb_putpalreg(sc
,
805 sc
->sc_cmap_green
[i
],
806 sc
->sc_cmap_blue
[i
]);
811 * wsdisplay_accessops
815 chipsfb_ioctl(void *v
, void *vs
, u_long cmd
, void *data
, int flag
,
818 struct vcons_data
*vd
= v
;
819 struct chipsfb_softc
*sc
= vd
->cookie
;
820 struct wsdisplay_fbinfo
*wdf
;
821 struct vcons_screen
*ms
= vd
->active
;
824 case WSDISPLAYIO_GTYPE
:
825 *(u_int
*)data
= WSDISPLAY_TYPE_PCIMISC
;
828 case WSDISPLAYIO_GINFO
:
830 wdf
->height
= ms
->scr_ri
.ri_height
;
831 wdf
->width
= ms
->scr_ri
.ri_width
;
832 wdf
->depth
= ms
->scr_ri
.ri_depth
;
836 case WSDISPLAYIO_GETCMAP
:
837 return chipsfb_getcmap(sc
,
838 (struct wsdisplay_cmap
*)data
);
840 case WSDISPLAYIO_PUTCMAP
:
841 return chipsfb_putcmap(sc
,
842 (struct wsdisplay_cmap
*)data
);
844 /* PCI config read/write passthrough. */
845 case PCI_IOC_CFGREAD
:
846 case PCI_IOC_CFGWRITE
:
847 return (pci_devioctl(sc
->sc_pc
, sc
->sc_pcitag
,
848 cmd
, data
, flag
, l
));
850 case WSDISPLAYIO_SMODE
:
852 int new_mode
= *(int*)data
;
853 if (new_mode
!= sc
->sc_mode
) {
854 sc
->sc_mode
= new_mode
;
855 if(new_mode
== WSDISPLAYIO_MODE_EMUL
) {
856 chipsfb_restore_palette(sc
);
857 vcons_redraw_screen(ms
);
867 chipsfb_mmap(void *v
, void *vs
, off_t offset
, int prot
)
869 struct vcons_data
*vd
= v
;
870 struct chipsfb_softc
*sc
= vd
->cookie
;
873 /* 'regular' framebuffer mmap()ing */
874 if (offset
< sc
->memsize
) {
875 pa
= bus_space_mmap(sc
->sc_fbt
, offset
, 0, prot
,
876 BUS_SPACE_MAP_LINEAR
);
881 * restrict all other mappings to processes with superuser privileges
882 * or the kernel itself
884 if (kauth_authorize_generic(kauth_cred_get(), KAUTH_GENERIC_ISSUSER
,
886 aprint_normal_dev(&sc
->sc_dev
, "mmap() rejected.\n");
890 if ((offset
>= sc
->sc_fb
) && (offset
< (sc
->sc_fb
+ sc
->sc_fbsize
))) {
891 pa
= bus_space_mmap(sc
->sc_memt
, offset
, 0, prot
,
892 BUS_SPACE_MAP_LINEAR
);
896 #ifdef PCI_MAGIC_IO_RANGE
897 /* allow mapping of IO space */
898 if ((offset
>= PCI_MAGIC_IO_RANGE
) &&
899 (offset
< PCI_MAGIC_IO_RANGE
+ 0x10000)) {
900 pa
= bus_space_mmap(sc
->sc_iot
, offset
- PCI_MAGIC_IO_RANGE
,
901 0, prot
, BUS_SPACE_MAP_LINEAR
);
906 #ifdef OFB_ALLOW_OTHERS
907 if (offset
>= 0x80000000) {
908 pa
= bus_space_mmap(sc
->sc_memt
, offset
, 0, prot
,
909 BUS_SPACE_MAP_LINEAR
);
917 chipsfb_init_screen(void *cookie
, struct vcons_screen
*scr
,
918 int existing
, long *defattr
)
920 struct chipsfb_softc
*sc
= cookie
;
921 struct rasops_info
*ri
= &scr
->scr_ri
;
923 ri
->ri_depth
= sc
->bits_per_pixel
;
924 ri
->ri_width
= sc
->width
;
925 ri
->ri_height
= sc
->height
;
926 ri
->ri_stride
= sc
->width
;
927 ri
->ri_flg
= RI_CENTER
| RI_FULLCLEAR
;
929 ri
->ri_bits
= bus_space_vaddr(sc
->sc_fbt
, sc
->sc_fbh
);
932 aprint_debug("addr: %08lx\n", (ulong
)ri
->ri_bits
);
935 ri
->ri_flg
|= RI_CLEAR
;
938 rasops_init(ri
, sc
->height
/8, sc
->width
/8);
939 ri
->ri_caps
= WSSCREEN_WSCOLORS
;
941 rasops_reconfig(ri
, sc
->height
/ ri
->ri_font
->fontheight
,
942 sc
->width
/ ri
->ri_font
->fontwidth
);
945 ri
->ri_ops
.copyrows
= chipsfb_copyrows
;
946 ri
->ri_ops
.copycols
= chipsfb_copycols
;
947 ri
->ri_ops
.eraserows
= chipsfb_eraserows
;
948 ri
->ri_ops
.erasecols
= chipsfb_erasecols
;
949 ri
->ri_ops
.cursor
= chipsfb_cursor
;
950 ri
->ri_ops
.putchar
= chipsfb_putchar
;
955 chipsfb_load_font(void *v
, void *cookie
, struct wsdisplay_font
*data
)
963 chipsfb_init(struct chipsfb_softc
*sc
)
966 chipsfb_wait_idle(sc
);
968 chipsfb_write_indexed(sc
, CT_CONF_INDEX
, XR_IO_CONTROL
,
969 ENABLE_CRTC_EXT
| ENABLE_ATTR_EXT
);
970 chipsfb_write_indexed(sc
, CT_CONF_INDEX
, XR_ADDR_MAPPING
,
973 /* setup the blitter */
977 chipsfb_probe_vram(struct chipsfb_softc
*sc
)
979 uint32_t ofs
= 0x00080000; /* 512kB */
982 * advance in 0.5MB steps, see if we can read back what we wrote and
983 * if what we wrote to 0 is left untouched. Max. fb size is 4MB so
984 * we voluntarily stop there.
986 chipsfb_write32(sc
, 0, 0xf0f0f0f0);
987 chipsfb_write32(sc
, ofs
, 0x0f0f0f0f);
988 while ((chipsfb_read32(sc
, 0) == 0xf0f0f0f0) &&
989 (chipsfb_read32(sc
, ofs
) == 0x0f0f0f0f) &&
990 (ofs
< 0x00400000)) {
993 chipsfb_write32(sc
, ofs
, 0x0f0f0f0f);