1 /*- 2 * Copyright (c) 2006 Itronix Inc. 3 * All rights reserved. 4 * 5 * Written by Garrett D'Amore for Itronix Inc. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 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. 15 * 3. The name of Itronix Inc. may not be used to endorse 16 * or promote products derived from this software without specific 17 * prior written permission. 18 * 19 * THIS SOFTWARE IS PROVIDED BY ITRONIX INC. ``AS IS'' AND ANY EXPRESS 20 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 21 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 * ARE DISCLAIMED. IN NO EVENT SHALL ITRONIX INC. BE LIABLE FOR ANY 23 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE 25 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 27 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 28 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 29 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 */ 31 32 /* 33 * ATI Technologies Inc. ("ATI") has not assisted in the creation of, and 34 * does not endorse, this software. ATI will not be responsible or liable 35 * for any actual or alleged damage or loss caused by or in connection with 36 * the use of or reliance on this software. 37 */ 38 39 #include <sys/cdefs.h> 40 __KERNEL_RCSID(0, "$NetBSD: radeonfb_i2c.c,v 1.2 2007/10/19 12:00:55 ad Exp $"); 41 42 #include <sys/param.h> 43 #include <sys/systm.h> 44 #include <sys/device.h> 45 #include <sys/malloc.h> 46 #include <sys/systm.h> 47 #include <sys/bus.h> 48 49 #include <dev/i2c/i2cvar.h> 50 #include <dev/i2c/i2c_bitbang.h> 51 #include <dev/i2c/ddcvar.h> 52 53 #include <dev/pci/radeonfbreg.h> 54 #include <dev/pci/radeonfbvar.h> 55 56 /* i2c support */ 57 static int radeonfb_i2c_acquire_bus(void *, int); 58 static void radeonfb_i2c_release_bus(void *, int); 59 static int radeonfb_i2c_send_start(void *, int); 60 static int radeonfb_i2c_send_stop(void *, int); 61 static int radeonfb_i2c_initiate_xfer(void *, i2c_addr_t, int); 62 static int radeonfb_i2c_read_byte(void *, uint8_t *, int); 63 static int radeonfb_i2c_write_byte(void *, uint8_t, int); 64 65 /* i2c bit-bang glue */ 66 static void radeonfb_i2cbb_set_bits(void *, uint32_t); 67 static void radeonfb_i2cbb_set_dir(void *, uint32_t); 68 static uint32_t radeonfb_i2cbb_read(void *); 69 70 /* 71 * I2C bit-bang operations 72 */ 73 void 74 radeonfb_i2cbb_set_bits(void *cookie, uint32_t bits) 75 { 76 struct radeonfb_i2c *ric = (struct radeonfb_i2c *)cookie; 77 struct radeonfb_softc *sc = ric->ric_softc; 78 79 PATCH32(sc, ric->ric_register, bits, 80 ~(RADEON_GPIO_A_0 | RADEON_GPIO_A_1)); 81 } 82 83 void 84 radeonfb_i2cbb_set_dir(void *cookie, uint32_t bits) 85 { 86 struct radeonfb_i2c *ric = (struct radeonfb_i2c *)cookie; 87 struct radeonfb_softc *sc = ric->ric_softc; 88 89 PATCH32(sc, ric->ric_register, bits, ~(RADEON_GPIO_EN_0)); 90 } 91 92 uint32_t 93 radeonfb_i2cbb_read(void *cookie) 94 { 95 struct radeonfb_i2c *ric = (struct radeonfb_i2c *)cookie; 96 struct radeonfb_softc *sc = ric->ric_softc; 97 98 /* output bit is 0 shifted, input bit is shifted 8 */ 99 return (GET32(sc, ric->ric_register) >> RADEON_GPIO_Y_SHIFT_0); 100 } 101 102 static const struct i2c_bitbang_ops radeonfb_i2cbb_ops = { 103 radeonfb_i2cbb_set_bits, 104 radeonfb_i2cbb_set_dir, 105 radeonfb_i2cbb_read, 106 { 107 RADEON_GPIO_A_0, /* SDA */ 108 RADEON_GPIO_A_1, /* SCL */ 109 RADEON_GPIO_EN_0, /* SDA output */ 110 0, /* SDA input */ 111 } 112 }; 113 114 /* 115 * I2C support 116 */ 117 int 118 radeonfb_i2c_acquire_bus(void *cookie, int flags) 119 { 120 struct radeonfb_i2c *ric = (struct radeonfb_i2c *)cookie; 121 struct radeonfb_softc *sc = ric->ric_softc; 122 int i; 123 124 /* 125 * Some hardware seems to have hardware/software combined access 126 * to the DVI I2C. We want to use software. 127 */ 128 if (ric->ric_register == RADEON_GPIO_DVI_DDC) { 129 130 /* ask for software access to I2C bus */ 131 SET32(sc, ric->ric_register, RADEON_GPIO_SW_USE); 132 133 /* 134 * wait for the chip to give up access. we don't make 135 * this a hard timeout, because some hardware might 136 * not implement this negotiation protocol 137 */ 138 for (i = RADEON_TIMEOUT; i; i--) { 139 if (GET32(sc, ric->ric_register) & RADEON_GPIO_SW_USE) 140 break; 141 } 142 } 143 144 /* enable the I2C clock */ 145 SET32(sc, ric->ric_register, RADEON_GPIO_EN_1); 146 147 return 0; 148 } 149 150 void 151 radeonfb_i2c_release_bus(void *cookie, int flags) 152 { 153 struct radeonfb_i2c *ric = (struct radeonfb_i2c *)cookie; 154 struct radeonfb_softc *sc = ric->ric_softc; 155 156 if (ric->ric_register == RADEON_GPIO_DVI_DDC) { 157 /* we no longer "want" I2C, and we're "done" with it */ 158 CLR32(sc, ric->ric_register, RADEON_GPIO_SW_USE); 159 SET32(sc, ric->ric_register, RADEON_GPIO_SW_DONE); 160 } 161 } 162 163 int 164 radeonfb_i2c_send_start(void *cookie, int flags) 165 { 166 167 return i2c_bitbang_send_start(cookie, flags, &radeonfb_i2cbb_ops); 168 } 169 170 int 171 radeonfb_i2c_send_stop(void *cookie, int flags) 172 { 173 174 return i2c_bitbang_send_stop(cookie, flags, &radeonfb_i2cbb_ops); 175 } 176 177 int 178 radeonfb_i2c_initiate_xfer(void *cookie, i2c_addr_t addr, int flags) 179 { 180 181 return i2c_bitbang_initiate_xfer(cookie, addr, flags, 182 &radeonfb_i2cbb_ops); 183 } 184 185 int 186 radeonfb_i2c_read_byte(void *cookie, uint8_t *valp, int flags) 187 { 188 189 return i2c_bitbang_read_byte(cookie, valp, flags, &radeonfb_i2cbb_ops); 190 } 191 192 int 193 radeonfb_i2c_write_byte(void *cookie, uint8_t val, int flags) 194 { 195 196 return i2c_bitbang_write_byte(cookie, val, flags, &radeonfb_i2cbb_ops); 197 } 198 199 void 200 radeonfb_i2c_init(struct radeonfb_softc *sc) 201 { 202 int i; 203 204 for (i = 0; i < 4; i++) { 205 struct i2c_controller *icc = &sc->sc_i2c[i].ric_controller; 206 207 sc->sc_i2c[i].ric_softc = sc; 208 icc->ic_cookie = &sc->sc_i2c[i]; 209 icc->ic_acquire_bus = radeonfb_i2c_acquire_bus; 210 icc->ic_release_bus = radeonfb_i2c_release_bus; 211 icc->ic_send_start = radeonfb_i2c_send_start; 212 icc->ic_send_stop = radeonfb_i2c_send_stop; 213 icc->ic_initiate_xfer = radeonfb_i2c_initiate_xfer; 214 icc->ic_read_byte = radeonfb_i2c_read_byte; 215 icc->ic_write_byte = radeonfb_i2c_write_byte; 216 } 217 218 /* index == ddctype (RADEON_DDC_XX) - 1 */ 219 sc->sc_i2c[0].ric_register = RADEON_GPIO_MONID; 220 sc->sc_i2c[1].ric_register = RADEON_GPIO_DVI_DDC; 221 sc->sc_i2c[2].ric_register = RADEON_GPIO_VGA_DDC; 222 sc->sc_i2c[3].ric_register = RADEON_GPIO_CRT2_DDC; 223 } 224 225 int 226 radeonfb_i2c_read_edid(struct radeonfb_softc *sc, int ddctype, uint8_t *data) 227 { 228 229 if ((ddctype < 1) || (ddctype > 4)) 230 return EINVAL; 231 232 ddctype--; 233 return (ddc_read_edid(&sc->sc_i2c[ddctype].ric_controller, data, 128)); 234 } 235