1 /* 2 * i2c interface for the G400 MAVEN under BeOS 3 * 4 * Provides I2CR,I2CW - functions to parallel DACW,DACR 5 * Bus should be run at max. 100kHz: see original Philips I2C specification 6 * 7 * Much help was provided by observing the Linux i2c code, 8 * so thanks go to: Gerd Knorr 9 * 10 * Other authors: 11 * Mark Watson 6/2000, 12 * Rudolf Cornelissen 12/2002-12/2003 13 */ 14 15 #define MODULE_BIT 0x00004000 16 17 #include "std.h" 18 19 int i2c_set_lines(int clock, int data); 20 int i2c_get_data(void); 21 void i2c_start(void); 22 void i2c_stop(void); 23 void i2c_high(void); 24 void i2c_low(void); 25 int i2c_get_ack(void); 26 void i2c_send_ack(void); 27 int i2c_sendbyte(unsigned char data); 28 unsigned char i2c_readbyte(int ack_required); 29 30 /*which device on the bus is the MAVEN?*/ 31 #define MAVEN_WRITE (0x1B<<1) 32 #define MAVEN_READ ((0x1B<<1)|1) 33 34 #define I2C_CLOCK 0x20 35 #define I2C_DATA 0x10 36 37 /* NV-TVO I2C for G200, G400 */ 38 #define I2C_CLOCK 0x20 39 #define I2C_DATA 0x10 40 /* primary head DDC for Mystique(?), G100, G200, G400 */ 41 #define DDC1_CLK 0x08 42 #define DDC1_DATA 0x02 43 /* primary head DDC for Millennium, Millennium II */ 44 #define DDC1B_CLK 0x10 45 #define DDC1B_DATA 0x04 46 /* secondary head DDC for G400, G450 and G550 */ 47 #define DDC2_CLK 0x04 48 #define DDC2_DATA 0x01 49 50 status_t i2c_sec_tv_adapter() 51 { 52 status_t result = B_ERROR; 53 54 /* The secondary DDC channel only exist on dualhead cards */ 55 if (!si->ps.secondary_head) return result; 56 57 /* make sure the output lines will be active-low when enabled 58 * (they will be pulled 'passive-high' when disabled) */ 59 // DXIW(GENIODATA,0x00); 60 /* send out B_STOP condition on secondary head DDC channel and use it to 61 * check for 'shortcut', indicating the Matrox VGA->TV adapter is connected */ 62 63 /* make sure SDA is low */ 64 // DXIW(GENIOCTRL, (DXIR(GENIOCTRL) | DDC2_DATA)); 65 snooze(2); 66 /* make sure SCL should be high */ 67 // DXIW(GENIOCTRL, (DXIR(GENIOCTRL) & ~DDC2_CLK)); 68 snooze(2); 69 /* if SCL is low then the bus is blocked by a TV adapter */ 70 // if (!(DXIR(GENIODATA) & DDC2_CLK)) result = B_OK; 71 snooze(5); 72 /* set SDA while SCL should be set (generates actual bus-stop condition) */ 73 // DXIW(GENIOCTRL, (DXIR(GENIOCTRL) & ~DDC2_DATA)); 74 snooze(5); 75 76 return result; 77 } 78 79 /*----------------------------- 80 *low level hardware access 81 */ 82 #define I2C_DELAY 2 83 #define I2C_TIMEOUT 100 84 int i2c_set_lines(int clock,int data) 85 { 86 int count=0; 87 int program; 88 int required; 89 90 /*work out which bits to zero*/ 91 program = 92 (clock ? 0 : I2C_CLOCK)| 93 (data ? 0 : I2C_DATA); 94 95 /*what value do I require on data lines*/ 96 required = 97 (clock ? I2C_CLOCK : 0); 98 99 /*set the bits to zero*/ 100 // DXIW(GENIOCTRL,program); /*drive these bits*/ 101 // DXIW(GENIODATA,0x00); /*to zero*/ 102 103 /*wait a bit*/ 104 delay(I2C_DELAY); 105 106 /*loop until the clock is as required*/ 107 // while ((DXIR(GENIODATA)&I2C_CLOCK)!=required) 108 { 109 delay(I2C_DELAY); 110 count++; 111 if (count>I2C_TIMEOUT) 112 { 113 // LOG(8,("I2C: Timeout on set lines - clock:%d data:%d actual:%x\n",clock,data,DXIR(GENIODATA))); 114 return -1; 115 } 116 } 117 118 return 0; 119 } 120 121 int i2c_get_data() 122 { 123 int data = 0; 124 int clock; 125 int count=0; 126 127 do 128 { 129 /*read the data and clock lines*/ 130 // data = DXIR(GENIODATA); 131 clock = (data&I2C_CLOCK) ? 1 : 0; 132 data = (data&I2C_DATA) ? 1 : 0; 133 134 /*manage timeout*/ 135 count++; 136 if (count>I2C_TIMEOUT) 137 { 138 return -1; 139 } 140 141 /*wait a bit, so not hammering bus*/ 142 delay(I2C_DELAY); 143 144 }while (!clock); /*wait for high clock*/ 145 146 return data; 147 } 148 149 150 /*----------------------- 151 *Standard I2C operations 152 */ 153 void i2c_start() 154 { 155 int error=0; 156 157 error+= i2c_set_lines(0,1); 158 error+= i2c_set_lines(1,1); 159 error+= i2c_set_lines(1,0); 160 error+= i2c_set_lines(0,0); 161 162 if (error) 163 { 164 LOG(8,("I2C: start - %d\n",error)); 165 } 166 } 167 168 void i2c_stop() 169 { 170 int error=0; 171 172 error+= i2c_set_lines(0,0); 173 error+= i2c_set_lines(1,0); 174 error+= i2c_set_lines(1,1); 175 error+= i2c_set_lines(0,1); 176 177 if (error) 178 { 179 LOG(8,("I2C: stop - %d\n",error)); 180 } 181 } 182 183 void i2c_high() 184 { 185 int error=0; 186 187 error+= i2c_set_lines(0,1); 188 error+= i2c_set_lines(1,1); 189 error+= i2c_set_lines(0,1); 190 191 if (error) 192 { 193 LOG(8,("I2C: high - %d\n",error)); 194 } 195 } 196 197 void i2c_low() 198 { 199 int error=0; 200 201 error+= i2c_set_lines(0,0); 202 error+= i2c_set_lines(1,0); 203 error+= i2c_set_lines(0,0); 204 205 if (error) 206 { 207 LOG(8,("I2C: low - %d\n",error)); 208 } 209 } 210 211 int i2c_get_ack() 212 { 213 int error=0; 214 int ack; 215 216 error+= i2c_set_lines(0,1); 217 error+= i2c_set_lines(1,1); 218 ack = i2c_get_data(); 219 error+= i2c_set_lines(0,1); 220 221 if (error) 222 { 223 LOG(8,("I2C: get_ack - %d value:%x\n",error,ack)); 224 } 225 226 return ack; 227 } 228 229 void i2c_send_ack() 230 { 231 int error=0; 232 233 error+= i2c_set_lines(0,0); 234 error+= i2c_set_lines(1,0); 235 error+= i2c_set_lines(0,0); 236 237 if (error) 238 { 239 LOG(8,("I2C: send_ack - %d\n",error)); 240 } 241 } 242 243 /*------------------------------ 244 *use above functions to send and receive bytes 245 */ 246 247 int i2c_sendbyte(unsigned char data) 248 { 249 int i; 250 251 for (i=7; i>=0; i--) 252 { 253 if (data&(1<<i)) 254 { 255 i2c_high(); 256 } 257 else 258 { 259 i2c_low(); 260 } 261 } 262 263 return i2c_get_ack(); 264 } 265 266 unsigned char i2c_readbyte(int ack_required) 267 { 268 int i; 269 unsigned char data=0; 270 271 /*read data*/ 272 i2c_set_lines(0,1); 273 for (i=7; i>=0; i--) 274 { 275 i2c_set_lines(1,1); 276 if (i2c_get_data()==1) 277 data |= (1<<i); 278 i2c_set_lines(0,1); 279 } 280 281 /*send acknowledge*/ 282 if (ack_required) i2c_send_ack(); 283 284 return data; 285 } 286 287 /*------------------------------------------- 288 *PUBLIC functions 289 */ 290 int i2c_maven_read(unsigned char address) 291 { 292 int error=0; 293 int data; 294 295 i2c_start(); 296 { 297 error+=i2c_sendbyte(MAVEN_READ); 298 error+=i2c_sendbyte(address); 299 data = i2c_readbyte(0); 300 } 301 i2c_stop(); 302 if (error>0) LOG(8,("I2C: MAVR ERROR - %x\n",error)); 303 return data; 304 } 305 306 void i2c_maven_write(unsigned char address, unsigned char data) 307 { 308 int error=0; 309 310 i2c_start(); 311 { 312 error+=i2c_sendbyte(MAVEN_WRITE); 313 error+=i2c_sendbyte(address); 314 error+=i2c_sendbyte(data); 315 } 316 i2c_stop(); 317 if (error>0) LOG(8,("I2C: MAVW ERROR - %x\n",error)); 318 } 319 320 status_t i2c_init(void) 321 { 322 /*init g400 i2c*/ 323 // DXIW(GENIODATA,0x00); /*to zero*/ 324 // DXIW(GENIOCTRL,0x30); /*drive clock and data*/ 325 // DXIW(GENIOCTRL,0x00); /*stop driving*/ 326 327 return B_OK; 328 } 329 330 status_t i2c_maven_probe(void) 331 { 332 int ack; 333 334 /*scan the bus for the MAVEN*/ 335 i2c_start(); 336 { 337 ack = i2c_sendbyte(MAVEN_READ); 338 } 339 i2c_stop(); 340 if (ack==0) 341 { 342 return B_OK; 343 } 344 else 345 { 346 return B_ERROR; 347 } 348 } 349