Tue Jan 17 19:13:23 2012 UTC ()
support DDC2, pick an appropriate video mode if a data are found


(macallan)
diff -r1.30 -r1.31 src/sys/dev/pci/voodoofb.c

cvs diff -r1.30 -r1.31 src/sys/dev/pci/voodoofb.c (expand / switch to unified diff)

--- src/sys/dev/pci/voodoofb.c 2012/01/17 07:48:48 1.30
+++ src/sys/dev/pci/voodoofb.c 2012/01/17 19:13:22 1.31
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: voodoofb.c,v 1.30 2012/01/17 07:48:48 macallan Exp $ */ 1/* $NetBSD: voodoofb.c,v 1.31 2012/01/17 19:13:22 macallan Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 2005, 2006 Michael Lorenz 4 * Copyright (c) 2005, 2006 Michael Lorenz
5 * All rights reserved. 5 * All rights reserved.
6 * 6 *
7 * Redistribution and use in source and binary forms, with or without 7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions 8 * modification, are permitted provided that the following conditions
9 * are met: 9 * are met:
10 * 1. Redistributions of source code must retain the above copyright 10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer. 11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright 12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the 13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution. 14 * documentation and/or other materials provided with the distribution.
@@ -22,51 +22,56 @@ @@ -22,51 +22,56 @@
22 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 22 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 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 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. 25 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */ 26 */
27 27
28/*  28/*
29 * A console driver for 3Dfx Voodoo3 graphics boards  29 * A console driver for 3Dfx Voodoo3 graphics boards
30 * Thanks to Andreas Drewke (andreas_dr@gmx.de) for his Voodoo3 driver for BeOS  30 * Thanks to Andreas Drewke (andreas_dr@gmx.de) for his Voodoo3 driver for BeOS
31 * which I used as reference / documentation 31 * which I used as reference / documentation
32 */ 32 */
33 33
34#include <sys/cdefs.h> 34#include <sys/cdefs.h>
35__KERNEL_RCSID(0, "$NetBSD: voodoofb.c,v 1.30 2012/01/17 07:48:48 macallan Exp $"); 35__KERNEL_RCSID(0, "$NetBSD: voodoofb.c,v 1.31 2012/01/17 19:13:22 macallan Exp $");
36 36
37#include <sys/param.h> 37#include <sys/param.h>
38#include <sys/systm.h> 38#include <sys/systm.h>
39#include <sys/kernel.h> 39#include <sys/kernel.h>
40#include <sys/device.h> 40#include <sys/device.h>
41#include <sys/malloc.h> 41#include <sys/malloc.h>
42#include <sys/callout.h> 42#include <sys/callout.h>
43#include <sys/kauth.h> 43#include <sys/kauth.h>
44 44
45#include <dev/videomode/videomode.h> 
46 
47#include <dev/pci/pcivar.h> 45#include <dev/pci/pcivar.h>
48#include <dev/pci/pcireg.h> 46#include <dev/pci/pcireg.h>
49#include <dev/pci/pcidevs.h> 47#include <dev/pci/pcidevs.h>
50#include <dev/pci/pciio.h> 48#include <dev/pci/pciio.h>
51#include <dev/pci/voodoofbreg.h> 49#include <dev/pci/voodoofbreg.h>
52 50
53#include <dev/wscons/wsdisplayvar.h> 51#include <dev/wscons/wsdisplayvar.h>
54#include <dev/wscons/wsconsio.h> 52#include <dev/wscons/wsconsio.h>
55#include <dev/wsfont/wsfont.h> 53#include <dev/wsfont/wsfont.h>
56#include <dev/rasops/rasops.h> 54#include <dev/rasops/rasops.h>
57#include <dev/wscons/wsdisplay_vconsvar.h> 55#include <dev/wscons/wsdisplay_vconsvar.h>
58#include <dev/pci/wsdisplay_pci.h> 56#include <dev/pci/wsdisplay_pci.h>
59 57
 58#include <dev/i2c/i2cvar.h>
 59#include <dev/i2c/i2c_bitbang.h>
 60#include <dev/i2c/ddcvar.h>
 61#include <dev/videomode/videomode.h>
 62#include <dev/videomode/edidvar.h>
 63#include <dev/videomode/edidreg.h>
 64
60#include "opt_wsemul.h" 65#include "opt_wsemul.h"
61 66
62struct voodoofb_softc { 67struct voodoofb_softc {
63 device_t sc_dev; 68 device_t sc_dev;
64 pci_chipset_tag_t sc_pc; 69 pci_chipset_tag_t sc_pc;
65 pcitag_t sc_pcitag; 70 pcitag_t sc_pcitag;
66 struct pci_attach_args sc_pa; 71 struct pci_attach_args sc_pa;
67 72
68 bus_space_tag_t sc_memt; 73 bus_space_tag_t sc_memt;
69 bus_space_tag_t sc_iot; 74 bus_space_tag_t sc_iot;
70 bus_space_handle_t sc_memh;  75 bus_space_handle_t sc_memh;
71 76
72 bus_space_tag_t sc_regt; 77 bus_space_tag_t sc_regt;
@@ -77,26 +82,32 @@ struct voodoofb_softc { @@ -77,26 +82,32 @@ struct voodoofb_softc {
77 bus_space_handle_t sc_ioregh;  82 bus_space_handle_t sc_ioregh;
78 bus_addr_t sc_regs, sc_fb, sc_ioreg; 83 bus_addr_t sc_regs, sc_fb, sc_ioreg;
79 bus_size_t sc_regsize, sc_fbsize, sc_ioregsize; 84 bus_size_t sc_regsize, sc_fbsize, sc_ioregsize;
80 85
81 void *sc_ih; 86 void *sc_ih;
82  87
83 size_t memsize; 88 size_t memsize;
84 int memtype; 89 int memtype;
85 90
86 int bits_per_pixel; 91 int bits_per_pixel;
87 int width, height, linebytes; 92 int width, height, linebytes;
88 const struct videomode *sc_videomode; 93 const struct videomode *sc_videomode;
89 94
 95 /* i2c stuff */
 96 struct i2c_controller sc_i2c;
 97 uint8_t sc_edid_data[128];
 98 struct edid_info sc_edid_info;
 99 uint32_t sc_i2creg;
 100
90 int sc_mode; 101 int sc_mode;
91 uint32_t sc_bg; 102 uint32_t sc_bg;
92  103
93 u_char sc_cmap_red[256]; 104 u_char sc_cmap_red[256];
94 u_char sc_cmap_green[256]; 105 u_char sc_cmap_green[256];
95 u_char sc_cmap_blue[256];  106 u_char sc_cmap_blue[256];
96 int sc_dacw; 107 int sc_dacw;
97 108
98 struct vcons_data vd; 109 struct vcons_data vd;
99}; 110};
100 111
101struct voodoo_regs { 112struct voodoo_regs {
102 uint8_t vr_crtc[31]; 113 uint8_t vr_crtc[31];
@@ -188,26 +199,54 @@ static void voodoofb_init_screen(void *, @@ -188,26 +199,54 @@ static void voodoofb_init_screen(void *,
188 199
189 200
190struct wsdisplay_accessops voodoofb_accessops = { 201struct wsdisplay_accessops voodoofb_accessops = {
191 voodoofb_ioctl, 202 voodoofb_ioctl,
192 voodoofb_mmap, 203 voodoofb_mmap,
193 NULL, 204 NULL,
194 NULL, 205 NULL,
195 NULL, 206 NULL,
196 NULL, /* load_font */ 207 NULL, /* load_font */
197 NULL, /* polls */ 208 NULL, /* polls */
198 NULL, /* scroll */ 209 NULL, /* scroll */
199}; 210};
200 211
 212/* I2C glue */
 213static int voodoofb_i2c_acquire_bus(void *, int);
 214static void voodoofb_i2c_release_bus(void *, int);
 215static int voodoofb_i2c_send_start(void *, int);
 216static int voodoofb_i2c_send_stop(void *, int);
 217static int voodoofb_i2c_initiate_xfer(void *, i2c_addr_t, int);
 218static int voodoofb_i2c_read_byte(void *, uint8_t *, int);
 219static int voodoofb_i2c_write_byte(void *, uint8_t, int);
 220
 221/* I2C bitbang glue */
 222static void voodoofb_i2cbb_set_bits(void *, uint32_t);
 223static void voodoofb_i2cbb_set_dir(void *, uint32_t);
 224static uint32_t voodoofb_i2cbb_read(void *);
 225
 226static void voodoofb_setup_i2c(struct voodoofb_softc *);
 227
 228static const struct i2c_bitbang_ops voodoofb_i2cbb_ops = {
 229 voodoofb_i2cbb_set_bits,
 230 voodoofb_i2cbb_set_dir,
 231 voodoofb_i2cbb_read,
 232 {
 233 VSP_SDA0_IN,
 234 VSP_SCL0_IN,
 235 0,
 236 0
 237 }
 238};
 239
201/* 240/*
202 * Inline functions for getting access to register aperture. 241 * Inline functions for getting access to register aperture.
203 */ 242 */
204static inline void 243static inline void
205voodoo3_write32(struct voodoofb_softc *sc, uint32_t reg, uint32_t val) 244voodoo3_write32(struct voodoofb_softc *sc, uint32_t reg, uint32_t val)
206{ 245{
207 bus_space_write_4(sc->sc_regt, sc->sc_regh, reg, val); 246 bus_space_write_4(sc->sc_regt, sc->sc_regh, reg, val);
208} 247}
209 248
210static inline uint32_t 249static inline uint32_t
211voodoo3_read32(struct voodoofb_softc *sc, uint32_t reg)  250voodoo3_read32(struct voodoofb_softc *sc, uint32_t reg)
212{ 251{
213 return bus_space_read_4(sc->sc_regt, sc->sc_regh, reg); 252 return bus_space_read_4(sc->sc_regt, sc->sc_regh, reg);
@@ -359,29 +398,35 @@ voodoofb_attach(device_t parent, device_ @@ -359,29 +398,35 @@ voodoofb_attach(device_t parent, device_
359 } 398 }
360 linebytes = width; /* XXX */ 399 linebytes = width; /* XXX */
361 400
362 if (width == -1 || height == -1) 401 if (width == -1 || height == -1)
363 return; 402 return;
364 403
365 sc->width = width; 404 sc->width = width;
366 sc->height = height; 405 sc->height = height;
367 sc->bits_per_pixel = depth; 406 sc->bits_per_pixel = depth;
368 sc->linebytes = linebytes; 407 sc->linebytes = linebytes;
369 printf("%s: initial resolution %dx%d, %d bit\n", device_xname(self), 408 printf("%s: initial resolution %dx%d, %d bit\n", device_xname(self),
370 sc->width, sc->height, sc->bits_per_pixel); 409 sc->width, sc->height, sc->bits_per_pixel);
371 410
 411 sc->sc_videomode = NULL;
 412 voodoofb_setup_i2c(sc);
 413
372 /* XXX this should at least be configurable via kernel config */ 414 /* XXX this should at least be configurable via kernel config */
373 if ((sc->sc_videomode = pick_mode_by_ref(1024, 768, 60)) != NULL) 415 if (sc->sc_videomode == NULL) {
374 voodoofb_set_videomode(sc, sc->sc_videomode); 416 sc->sc_videomode = pick_mode_by_ref(width, height, 60);
 417 }
 418
 419 voodoofb_set_videomode(sc, sc->sc_videomode);
375 420
376 vcons_init(&sc->vd, sc, &voodoofb_defaultscreen, &voodoofb_accessops); 421 vcons_init(&sc->vd, sc, &voodoofb_defaultscreen, &voodoofb_accessops);
377 sc->vd.init_screen = voodoofb_init_screen; 422 sc->vd.init_screen = voodoofb_init_screen;
378 423
379 console = voodoofb_is_console(sc); 424 console = voodoofb_is_console(sc);
380 425
381 ri = &voodoofb_console_screen.scr_ri; 426 ri = &voodoofb_console_screen.scr_ri;
382 if (console) { 427 if (console) {
383 vcons_init_screen(&sc->vd, &voodoofb_console_screen, 1, 428 vcons_init_screen(&sc->vd, &voodoofb_console_screen, 1,
384 &defattr); 429 &defattr);
385 voodoofb_console_screen.scr_flags |= VCONS_SCREEN_IS_STATIC; 430 voodoofb_console_screen.scr_flags |= VCONS_SCREEN_IS_STATIC;
386 431
387 voodoofb_defaultscreen.textops = &ri->ri_ops; 432 voodoofb_defaultscreen.textops = &ri->ri_ops;
@@ -1402,13 +1447,150 @@ voodoofb_init(struct voodoofb_softc *sc) @@ -1402,13 +1447,150 @@ voodoofb_init(struct voodoofb_softc *sc)
1402 1447
1403 voodoo3_make_room(sc, 8); 1448 voodoo3_make_room(sc, 8);
1404 voodoo3_write32(sc, SRCBASE, 0); 1449 voodoo3_write32(sc, SRCBASE, 0);
1405 voodoo3_write32(sc, DSTBASE, 0); 1450 voodoo3_write32(sc, DSTBASE, 0);
1406 voodoo3_write32(sc, COMMANDEXTRA_2D, 0); 1451 voodoo3_write32(sc, COMMANDEXTRA_2D, 0);
1407 voodoo3_write32(sc, CLIP0MIN, 0); 1452 voodoo3_write32(sc, CLIP0MIN, 0);
1408 voodoo3_write32(sc, CLIP0MAX, 0x1fff1fff); 1453 voodoo3_write32(sc, CLIP0MAX, 0x1fff1fff);
1409 voodoo3_write32(sc, CLIP1MIN, 0); 1454 voodoo3_write32(sc, CLIP1MIN, 0);
1410 voodoo3_write32(sc, CLIP1MAX, 0x1fff1fff); 1455 voodoo3_write32(sc, CLIP1MAX, 0x1fff1fff);
1411 voodoo3_write32(sc, SRCXY, 0); 1456 voodoo3_write32(sc, SRCXY, 0);
1412 1457
1413 voodoofb_wait_idle(sc); 1458 voodoofb_wait_idle(sc);
1414} 1459}
 1460
 1461static void
 1462voodoofb_setup_i2c(struct voodoofb_softc *sc)
 1463{
 1464 int i;
 1465
 1466 /* Fill in the i2c tag */
 1467 sc->sc_i2c.ic_cookie = sc;
 1468 sc->sc_i2c.ic_acquire_bus = voodoofb_i2c_acquire_bus;
 1469 sc->sc_i2c.ic_release_bus = voodoofb_i2c_release_bus;
 1470 sc->sc_i2c.ic_send_start = voodoofb_i2c_send_start;
 1471 sc->sc_i2c.ic_send_stop = voodoofb_i2c_send_stop;
 1472 sc->sc_i2c.ic_initiate_xfer = voodoofb_i2c_initiate_xfer;
 1473 sc->sc_i2c.ic_read_byte = voodoofb_i2c_read_byte;
 1474 sc->sc_i2c.ic_write_byte = voodoofb_i2c_write_byte;
 1475 sc->sc_i2c.ic_exec = NULL;
 1476
 1477 sc->sc_i2creg = voodoo3_read32(sc, VIDSERPARPORT);
 1478#ifdef VOODOOFB_DEBUG
 1479 printf("data: %08x\n", sc->sc_i2creg);
 1480#endif
 1481 sc->sc_i2creg |= VSP_ENABLE_IIC0;
 1482 sc->sc_i2creg &= ~(VSP_SDA0_OUT | VSP_SCL0_OUT);
 1483 voodoo3_write32(sc, VIDSERPARPORT, sc->sc_i2creg);
 1484
 1485 /* zero out the EDID buffer */
 1486 memset(sc->sc_edid_data, 0, 128);
 1487
 1488 /* Some monitors don't respond first time */
 1489 i = 0;
 1490 while (sc->sc_edid_data[1] == 0 && i++ < 3)
 1491 ddc_read_edid(&sc->sc_i2c, sc->sc_edid_data, 128);
 1492 if (i < 3) {
 1493 if (edid_parse(sc->sc_edid_data, &sc->sc_edid_info) != -1) {
 1494#ifdef VOODOOFB_DEBUG
 1495 edid_print(&sc->sc_edid_info);
 1496#endif
 1497 /*
 1498 * Now pick a mode.
 1499 * How do we know our max. pixel clock?
 1500 * All Voodoo3 should support at least 250MHz.
 1501 * All Voodoo3 I've seen so far have at least 8MB
 1502 * which we're not going to exhaust either in 8bit.
 1503 */
 1504 if ((sc->sc_edid_info.edid_preferred_mode != NULL)) {
 1505 sc->sc_videomode =
 1506 sc->sc_edid_info.edid_preferred_mode;
 1507 } else {
 1508 int n;
 1509 struct videomode *m = sc->sc_edid_info.edid_modes;
 1510
 1511 sort_modes(sc->sc_edid_info.edid_modes,
 1512 &sc->sc_edid_info.edid_preferred_mode,
 1513 sc->sc_edid_info.edid_nmodes);
 1514 while ((sc->sc_videomode == NULL) &&
 1515 (n < sc->sc_edid_info.edid_nmodes)) {
 1516 if (m[n].dot_clock <= 250000) {
 1517 sc->sc_videomode = &m[n];
 1518 }
 1519 }
 1520 }
 1521 }
 1522 }
 1523}
 1524
 1525/* I2C bitbanging */
 1526static void voodoofb_i2cbb_set_bits(void *cookie, uint32_t bits)
 1527{
 1528 struct voodoofb_softc *sc = cookie;
 1529 uint32_t out;
 1530
 1531 out = bits >> 2; /* bitmasks match the IN bits */
 1532
 1533 voodoo3_write32(sc, VIDSERPARPORT, sc->sc_i2creg | out);
 1534}
 1535
 1536static void voodoofb_i2cbb_set_dir(void *cookie, uint32_t dir)
 1537{
 1538 /* Nothing to do */
 1539}
 1540
 1541static uint32_t voodoofb_i2cbb_read(void *cookie)
 1542{
 1543 struct voodoofb_softc *sc = cookie;
 1544 uint32_t bits;
 1545
 1546 bits = voodoo3_read32(sc, VIDSERPARPORT);
 1547
 1548 return bits;
 1549}
 1550
 1551/* higher level I2C stuff */
 1552static int
 1553voodoofb_i2c_acquire_bus(void *cookie, int flags)
 1554{
 1555 /* private bus */
 1556 return (0);
 1557}
 1558
 1559static void
 1560voodoofb_i2c_release_bus(void *cookie, int flags)
 1561{
 1562 /* private bus */
 1563}
 1564
 1565static int
 1566voodoofb_i2c_send_start(void *cookie, int flags)
 1567{
 1568 return (i2c_bitbang_send_start(cookie, flags, &voodoofb_i2cbb_ops));
 1569}
 1570
 1571static int
 1572voodoofb_i2c_send_stop(void *cookie, int flags)
 1573{
 1574
 1575 return (i2c_bitbang_send_stop(cookie, flags, &voodoofb_i2cbb_ops));
 1576}
 1577
 1578static int
 1579voodoofb_i2c_initiate_xfer(void *cookie, i2c_addr_t addr, int flags)
 1580{
 1581
 1582 return (i2c_bitbang_initiate_xfer(cookie, addr, flags,
 1583 &voodoofb_i2cbb_ops));
 1584}
 1585
 1586static int
 1587voodoofb_i2c_read_byte(void *cookie, uint8_t *valp, int flags)
 1588{
 1589 return (i2c_bitbang_read_byte(cookie, valp, flags, &voodoofb_i2cbb_ops));
 1590}
 1591
 1592static int
 1593voodoofb_i2c_write_byte(void *cookie, uint8_t val, int flags)
 1594{
 1595 return (i2c_bitbang_write_byte(cookie, val, flags, &voodoofb_i2cbb_ops));
 1596}