saa7146_i2c.c revision 1da177e4c3f41524e886b7f1b8a0c1fc7321cac
11da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/version.h>
21da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <media/saa7146_vv.h>
31da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
41da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic u32 saa7146_i2c_func(struct i2c_adapter *adapter)
51da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
61da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds//fm	DEB_I2C(("'%s'.\n", adapter->name));
71da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
81da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return	  I2C_FUNC_I2C
91da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		| I2C_FUNC_SMBUS_QUICK
101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		| I2C_FUNC_SMBUS_READ_BYTE	| I2C_FUNC_SMBUS_WRITE_BYTE
111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		| I2C_FUNC_SMBUS_READ_BYTE_DATA | I2C_FUNC_SMBUS_WRITE_BYTE_DATA;
121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* this function returns the status-register of our i2c-device */
151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic inline u32 saa7146_i2c_status(struct saa7146_dev *dev)
161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u32 iicsta = saa7146_read(dev, I2C_STATUS);
181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	DEB_I2C(("status: 0x%08x\n",iicsta));
201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds*/
211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return iicsta;
221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* this function runs through the i2c-messages and prepares the data to be
251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds   sent through the saa7146. have a look at the specifications p. 122 ff
261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds   to understand this. it returns the number of u32s to send, or -1
271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds   in case of an error. */
281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int saa7146_i2c_msg_prepare(const struct i2c_msg *m, int num, u32 *op)
291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int h1, h2;
311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int i, j, addr;
321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int mem = 0, op_count = 0;
331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* first determine size of needed memory */
351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	for(i = 0; i < num; i++) {
361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		mem += m[i].len + 1;
371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* worst case: we need one u32 for three bytes to be send
401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	   plus one extra byte to address the device */
411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mem = 1 + ((mem-1) / 3);
421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* we assume that op points to a memory of at least SAA7146_I2C_MEM bytes
441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	   size. if we exceed this limit... */
451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if ( (4*mem) > SAA7146_I2C_MEM ) {
461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds//fm		DEB_I2C(("cannot prepare i2c-message.\n"));
471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return -ENOMEM;
481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* be careful: clear out the i2c-mem first */
511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	memset(op,0,sizeof(u32)*mem);
521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* loop through all messages */
541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	for(i = 0; i < num; i++) {
551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* insert the address of the i2c-slave.
571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		   note: we get 7 bit i2c-addresses,
581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		   so we have to perform a translation */
591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		addr = (m[i].addr*2) + ( (0 != (m[i].flags & I2C_M_RD)) ? 1 : 0);
601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		h1 = op_count/3; h2 = op_count%3;
611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		op[h1] |= (	    (u8)addr << ((3-h2)*8));
621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		op[h1] |= (SAA7146_I2C_START << ((3-h2)*2));
631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		op_count++;
641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* loop through all bytes of message i */
661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		for(j = 0; j < m[i].len; j++) {
671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			/* insert the data bytes */
681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			h1 = op_count/3; h2 = op_count%3;
691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			op[h1] |= ( (u32)((u8)m[i].buf[j]) << ((3-h2)*8));
701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			op[h1] |= (       SAA7146_I2C_CONT << ((3-h2)*2));
711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			op_count++;
721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* have a look at the last byte inserted:
771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	  if it was: ...CONT change it to ...STOP */
781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	h1 = (op_count-1)/3; h2 = (op_count-1)%3;
791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if ( SAA7146_I2C_CONT == (0x3 & (op[h1] >> ((3-h2)*2))) ) {
801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		op[h1] &= ~(0x2 << ((3-h2)*2));
811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		op[h1] |= (SAA7146_I2C_STOP << ((3-h2)*2));
821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* return the number of u32s to send */
851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return mem;
861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* this functions loops through all i2c-messages. normally, it should determine
891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds   which bytes were read through the adapter and write them back to the corresponding
901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds   i2c-message. but instead, we simply write back all bytes.
911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds   fixme: this could be improved. */
921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int saa7146_i2c_msg_cleanup(const struct i2c_msg *m, int num, u32 *op)
931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int i, j;
951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int op_count = 0;
961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* loop through all messages */
981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	for(i = 0; i < num; i++) {
991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		op_count++;
1011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* loop throgh all bytes of message i */
1031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		for(j = 0; j < m[i].len; j++) {
1041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			/* write back all bytes that could have been read */
1051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			m[i].buf[j] = (op[op_count/3] >> ((3-(op_count%3))*8));
1061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			op_count++;
1071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
1081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
1091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
1111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* this functions resets the i2c-device and returns 0 if everything was fine, otherwise -1 */
1141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int saa7146_i2c_reset(struct saa7146_dev *dev)
1151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* get current status */
1171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u32 status = saa7146_i2c_status(dev);
1181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* clear registers for sure */
1201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	saa7146_write(dev, I2C_STATUS, dev->i2c_bitrate);
1211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	saa7146_write(dev, I2C_TRANSFER, 0);
1221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* check if any operation is still in progress */
1241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if ( 0 != ( status & SAA7146_I2C_BUSY) ) {
1251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* yes, kill ongoing operation */
1271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		DEB_I2C(("busy_state detected.\n"));
1281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* set "ABORT-OPERATION"-bit (bit 7)*/
1301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		saa7146_write(dev, I2C_STATUS, (dev->i2c_bitrate | MASK_07));
1311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		saa7146_write(dev, MC2, (MASK_00 | MASK_16));
1321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		msleep(SAA7146_I2C_DELAY);
1331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* clear all error-bits pending; this is needed because p.123, note 1 */
1351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		saa7146_write(dev, I2C_STATUS, dev->i2c_bitrate);
1361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		saa7146_write(dev, MC2, (MASK_00 | MASK_16));
1371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		msleep(SAA7146_I2C_DELAY);
1381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
1391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* check if any error is (still) present. (this can be necessary because p.123, note 1) */
1411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	status = saa7146_i2c_status(dev);
1421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if ( dev->i2c_bitrate != status ) {
1441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		DEB_I2C(("error_state detected. status:0x%08x\n",status));
1461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* Repeat the abort operation. This seems to be necessary
1481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		   after serious protocol errors caused by e.g. the SAA7740 */
1491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		saa7146_write(dev, I2C_STATUS, (dev->i2c_bitrate | MASK_07));
1501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		saa7146_write(dev, MC2, (MASK_00 | MASK_16));
1511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		msleep(SAA7146_I2C_DELAY);
1521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* clear all error-bits pending */
1541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		saa7146_write(dev, I2C_STATUS, dev->i2c_bitrate);
1551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		saa7146_write(dev, MC2, (MASK_00 | MASK_16));
1561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		msleep(SAA7146_I2C_DELAY);
1571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* the data sheet says it might be necessary to clear the status
1591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		   twice after an abort */
1601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		saa7146_write(dev, I2C_STATUS, dev->i2c_bitrate);
1611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		saa7146_write(dev, MC2, (MASK_00 | MASK_16));
1621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		msleep(SAA7146_I2C_DELAY);
1631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
1641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* if any error is still present, a fatal error has occured ... */
1661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	status = saa7146_i2c_status(dev);
1671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if ( dev->i2c_bitrate != status ) {
1681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		DEB_I2C(("fatal error. status:0x%08x\n",status));
1691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return -1;
1701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
1711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
1731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* this functions writes out the data-byte 'dword' to the i2c-device.
1761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds   it returns 0 if ok, -1 if the transfer failed, -2 if the transfer
1771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds   failed badly (e.g. address error) */
1781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int saa7146_i2c_writeout(struct saa7146_dev *dev, u32* dword, int short_delay)
1791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u32 status = 0, mc2 = 0;
1811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int trial = 0;
1821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned long timeout;
1831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* write out i2c-command */
1851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	DEB_I2C(("before: 0x%08x (status: 0x%08x), %d\n",*dword,saa7146_read(dev, I2C_STATUS), dev->i2c_op));
1861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if( 0 != (SAA7146_USE_I2C_IRQ & dev->ext->flags)) {
1881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		saa7146_write(dev, I2C_STATUS,	 dev->i2c_bitrate);
1901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		saa7146_write(dev, I2C_TRANSFER, *dword);
1911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		dev->i2c_op = 1;
1931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		SAA7146_IER_ENABLE(dev, MASK_16|MASK_17);
1941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		saa7146_write(dev, MC2, (MASK_00 | MASK_16));
1951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		wait_event_interruptible(dev->i2c_wq, dev->i2c_op == 0);
1971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (signal_pending (current)) {
1981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			/* a signal arrived */
1991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return -ERESTARTSYS;
2001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
2011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		status = saa7146_read(dev, I2C_STATUS);
2021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} else {
2031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		saa7146_write(dev, I2C_STATUS,	 dev->i2c_bitrate);
2041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		saa7146_write(dev, I2C_TRANSFER, *dword);
2051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		saa7146_write(dev, MC2, (MASK_00 | MASK_16));
2061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* do not poll for i2c-status before upload is complete */
2081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		timeout = jiffies + HZ/100 + 1; /* 10ms */
2091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		while(1) {
2101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			mc2 = (saa7146_read(dev, MC2) & 0x1);
2111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if( 0 != mc2 ) {
2121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				break;
2131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			}
2141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (time_after(jiffies,timeout)) {
2151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				printk(KERN_WARNING "saa7146_i2c_writeout: timed out waiting for MC2\n");
2161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				return -EIO;
2171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			}
2181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
2191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* wait until we get a transfer done or error */
2201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		timeout = jiffies + HZ/100 + 1; /* 10ms */
2211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		while(1) {
2221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			/**
2231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 *  first read usually delivers bogus results...
2241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 */
2251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			saa7146_i2c_status(dev);
2261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			status = saa7146_i2c_status(dev);
2271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if ((status & 0x3) != 1)
2281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				break;
2291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (time_after(jiffies,timeout)) {
2301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				/* this is normal when probing the bus
2311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				 * (no answer from nonexisistant device...)
2321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				 */
2331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				DEB_I2C(("saa7146_i2c_writeout: timed out waiting for end of xfer\n"));
2341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				return -EIO;
2351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			}
2361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if ((++trial < 20) && short_delay)
2371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				udelay(10);
2381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			else
2391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			msleep(1);
2401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
2411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
2421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* give a detailed status report */
2441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if ( 0 != (status & SAA7146_I2C_ERR)) {
2451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if( 0 != (status & SAA7146_I2C_SPERR) ) {
2471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			DEB_I2C(("error due to invalid start/stop condition.\n"));
2481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
2491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if( 0 != (status & SAA7146_I2C_DTERR) ) {
2501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			DEB_I2C(("error in data transmission.\n"));
2511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
2521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if( 0 != (status & SAA7146_I2C_DRERR) ) {
2531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			DEB_I2C(("error when receiving data.\n"));
2541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
2551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if( 0 != (status & SAA7146_I2C_AL) ) {
2561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			DEB_I2C(("error because arbitration lost.\n"));
2571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
2581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* we handle address-errors here */
2601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if( 0 != (status & SAA7146_I2C_APERR) ) {
2611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			DEB_I2C(("error in address phase.\n"));
2621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return -EREMOTEIO;
2631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
2641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return -EIO;
2661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
2671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* read back data, just in case we were reading ... */
2691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	*dword = saa7146_read(dev, I2C_TRANSFER);
2701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	DEB_I2C(("after: 0x%08x\n",*dword));
2721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
2731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint saa7146_i2c_transfer(struct saa7146_dev *dev, const struct i2c_msg *msgs, int num, int retries)
2761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
2771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int i = 0, count = 0;
2781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u32* buffer = dev->d_i2c.cpu_addr;
2791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int err = 0;
2801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        int address_err = 0;
2811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        int short_delay = 0;
2821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (down_interruptible (&dev->i2c_lock))
2841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return -ERESTARTSYS;
2851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	for(i=0;i<num;i++) {
2871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		DEB_I2C(("msg:%d/%d\n",i+1,num));
2881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
2891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* prepare the message(s), get number of u32s to transfer */
2911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	count = saa7146_i2c_msg_prepare(msgs, num, buffer);
2921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if ( 0 > count ) {
2931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		err = -1;
2941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto out;
2951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
2961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if ( count > 3 || 0 != (SAA7146_I2C_SHORT_DELAY & dev->ext->flags) )
2981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		short_delay = 1;
2991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	do {
3011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* reset the i2c-device if necessary */
3021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		err = saa7146_i2c_reset(dev);
3031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if ( 0 > err ) {
3041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			DEB_I2C(("could not reset i2c-device.\n"));
3051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			goto out;
3061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
3071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* write out the u32s one after another */
3091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		for(i = 0; i < count; i++) {
3101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			err = saa7146_i2c_writeout(dev, &buffer[i], short_delay);
3111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if ( 0 != err) {
3121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				/* this one is unsatisfying: some i2c slaves on some
3131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				   dvb cards don't acknowledge correctly, so the saa7146
3141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				   thinks that an address error occured. in that case, the
3151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				   transaction should be retrying, even if an address error
3161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				   occured. analog saa7146 based cards extensively rely on
3171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				   i2c address probing, however, and address errors indicate that a
3181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				   device is really *not* there. retrying in that case
3191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				   increases the time the device needs to probe greatly, so
3201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				   it should be avoided. because of the fact, that only
3211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				   analog based cards use irq based i2c transactions (for dvb
3221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				   cards, this screwes up other interrupt sources), we bail out
3231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				   completely for analog cards after an address error and trust
3241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				   the saa7146 address error detection. */
3251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				if ( -EREMOTEIO == err ) {
3261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					if( 0 != (SAA7146_USE_I2C_IRQ & dev->ext->flags)) {
3271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds						goto out;
3281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					}
3291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				        address_err++;
3301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				}
3311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				DEB_I2C(("error while sending message(s). starting again.\n"));
3321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				break;
3331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			}
3341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
3351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if( 0 == err ) {
3361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			err = num;
3371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
3381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
3391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	        /* delay a bit before retrying */
3411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	        msleep(10);
3421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} while (err != num && retries--);
3441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        /* if every retry had an address error, exit right away */
3461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        if (address_err == retries) {
3471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	        goto out;
3481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
3491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* if any things had to be read, get the results */
3511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if ( 0 != saa7146_i2c_msg_cleanup(msgs, num, buffer)) {
3521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		DEB_I2C(("could not cleanup i2c-message.\n"));
3531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		err = -1;
3541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto out;
3551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
3561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* return the number of delivered messages */
3581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	DEB_I2C(("transmission successful. (msg:%d).\n",err));
3591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsout:
3601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* another bug in revision 0: the i2c-registers get uploaded randomly by other
3611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	   uploads, so we better clear them out before continueing */
3621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if( 0 == dev->revision ) {
3631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		u32 zero = 0;
3641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		saa7146_i2c_reset(dev);
3651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if( 0 != saa7146_i2c_writeout(dev, &zero, short_delay)) {
3661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			INFO(("revision 0 error. this should never happen.\n"));
3671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
3681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
3691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	up(&dev->i2c_lock);
3711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return err;
3721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
3731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* utility functions */
3751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int saa7146_i2c_xfer(struct i2c_adapter* adapter, struct i2c_msg *msg, int num)
3761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
3771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct saa7146_dev* dev = i2c_get_adapdata(adapter);
3781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* use helper function to transfer data */
3801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return saa7146_i2c_transfer(dev, msg, num, adapter->retries);
3811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
3821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*****************************************************************************/
3851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* i2c-adapter helper functions                                              */
3861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/i2c-id.h>
3871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* exported algorithm data */
3891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct i2c_algorithm saa7146_algo = {
3901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.name		= "saa7146 i2c algorithm",
3911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.id		= I2C_ALGO_SAA7146,
3921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.master_xfer	= saa7146_i2c_xfer,
3931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.functionality	= saa7146_i2c_func,
3941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
3951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint saa7146_i2c_adapter_prepare(struct saa7146_dev *dev, struct i2c_adapter *i2c_adapter, u32 bitrate)
3971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
3981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	DEB_EE(("bitrate: 0x%08x\n",bitrate));
3991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* enable i2c-port pins */
4011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	saa7146_write(dev, MC1, (MASK_08 | MASK_24));
4021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	dev->i2c_bitrate = bitrate;
4041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	saa7146_i2c_reset(dev);
4051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if( NULL != i2c_adapter ) {
4071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0))
4081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		i2c_adapter->data = dev;
4091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#else
4101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		BUG_ON(!i2c_adapter->class);
4111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		i2c_set_adapdata(i2c_adapter,dev);
4121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif
4131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		i2c_adapter->algo	   = &saa7146_algo;
4141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		i2c_adapter->algo_data     = NULL;
4151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		i2c_adapter->id		   = I2C_ALGO_SAA7146;
4161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		i2c_adapter->timeout = SAA7146_I2C_TIMEOUT;
4171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		i2c_adapter->retries = SAA7146_I2C_RETRIES;
4181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
4191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
4211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
422