18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 28c2ecf20Sopenharmony_ci#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 38c2ecf20Sopenharmony_ci 48c2ecf20Sopenharmony_ci#include <media/drv-intf/saa7146_vv.h> 58c2ecf20Sopenharmony_ci 68c2ecf20Sopenharmony_cistatic u32 saa7146_i2c_func(struct i2c_adapter *adapter) 78c2ecf20Sopenharmony_ci{ 88c2ecf20Sopenharmony_ci /* DEB_I2C("'%s'\n", adapter->name); */ 98c2ecf20Sopenharmony_ci 108c2ecf20Sopenharmony_ci return I2C_FUNC_I2C 118c2ecf20Sopenharmony_ci | I2C_FUNC_SMBUS_QUICK 128c2ecf20Sopenharmony_ci | I2C_FUNC_SMBUS_READ_BYTE | I2C_FUNC_SMBUS_WRITE_BYTE 138c2ecf20Sopenharmony_ci | I2C_FUNC_SMBUS_READ_BYTE_DATA | I2C_FUNC_SMBUS_WRITE_BYTE_DATA; 148c2ecf20Sopenharmony_ci} 158c2ecf20Sopenharmony_ci 168c2ecf20Sopenharmony_ci/* this function returns the status-register of our i2c-device */ 178c2ecf20Sopenharmony_cistatic inline u32 saa7146_i2c_status(struct saa7146_dev *dev) 188c2ecf20Sopenharmony_ci{ 198c2ecf20Sopenharmony_ci u32 iicsta = saa7146_read(dev, I2C_STATUS); 208c2ecf20Sopenharmony_ci /* DEB_I2C("status: 0x%08x\n", iicsta); */ 218c2ecf20Sopenharmony_ci return iicsta; 228c2ecf20Sopenharmony_ci} 238c2ecf20Sopenharmony_ci 248c2ecf20Sopenharmony_ci/* this function runs through the i2c-messages and prepares the data to be 258c2ecf20Sopenharmony_ci sent through the saa7146. have a look at the specifications p. 122 ff 268c2ecf20Sopenharmony_ci to understand this. it returns the number of u32s to send, or -1 278c2ecf20Sopenharmony_ci in case of an error. */ 288c2ecf20Sopenharmony_cistatic int saa7146_i2c_msg_prepare(const struct i2c_msg *m, int num, __le32 *op) 298c2ecf20Sopenharmony_ci{ 308c2ecf20Sopenharmony_ci int h1, h2; 318c2ecf20Sopenharmony_ci int i, j, addr; 328c2ecf20Sopenharmony_ci int mem = 0, op_count = 0; 338c2ecf20Sopenharmony_ci 348c2ecf20Sopenharmony_ci /* first determine size of needed memory */ 358c2ecf20Sopenharmony_ci for(i = 0; i < num; i++) { 368c2ecf20Sopenharmony_ci mem += m[i].len + 1; 378c2ecf20Sopenharmony_ci } 388c2ecf20Sopenharmony_ci 398c2ecf20Sopenharmony_ci /* worst case: we need one u32 for three bytes to be send 408c2ecf20Sopenharmony_ci plus one extra byte to address the device */ 418c2ecf20Sopenharmony_ci mem = 1 + ((mem-1) / 3); 428c2ecf20Sopenharmony_ci 438c2ecf20Sopenharmony_ci /* we assume that op points to a memory of at least 448c2ecf20Sopenharmony_ci * SAA7146_I2C_MEM bytes size. if we exceed this limit... 458c2ecf20Sopenharmony_ci */ 468c2ecf20Sopenharmony_ci if ((4 * mem) > SAA7146_I2C_MEM) { 478c2ecf20Sopenharmony_ci /* DEB_I2C("cannot prepare i2c-message\n"); */ 488c2ecf20Sopenharmony_ci return -ENOMEM; 498c2ecf20Sopenharmony_ci } 508c2ecf20Sopenharmony_ci 518c2ecf20Sopenharmony_ci /* be careful: clear out the i2c-mem first */ 528c2ecf20Sopenharmony_ci memset(op,0,sizeof(__le32)*mem); 538c2ecf20Sopenharmony_ci 548c2ecf20Sopenharmony_ci /* loop through all messages */ 558c2ecf20Sopenharmony_ci for(i = 0; i < num; i++) { 568c2ecf20Sopenharmony_ci 578c2ecf20Sopenharmony_ci addr = i2c_8bit_addr_from_msg(&m[i]); 588c2ecf20Sopenharmony_ci h1 = op_count/3; h2 = op_count%3; 598c2ecf20Sopenharmony_ci op[h1] |= cpu_to_le32( (u8)addr << ((3-h2)*8)); 608c2ecf20Sopenharmony_ci op[h1] |= cpu_to_le32(SAA7146_I2C_START << ((3-h2)*2)); 618c2ecf20Sopenharmony_ci op_count++; 628c2ecf20Sopenharmony_ci 638c2ecf20Sopenharmony_ci /* loop through all bytes of message i */ 648c2ecf20Sopenharmony_ci for(j = 0; j < m[i].len; j++) { 658c2ecf20Sopenharmony_ci /* insert the data bytes */ 668c2ecf20Sopenharmony_ci h1 = op_count/3; h2 = op_count%3; 678c2ecf20Sopenharmony_ci op[h1] |= cpu_to_le32( (u32)((u8)m[i].buf[j]) << ((3-h2)*8)); 688c2ecf20Sopenharmony_ci op[h1] |= cpu_to_le32( SAA7146_I2C_CONT << ((3-h2)*2)); 698c2ecf20Sopenharmony_ci op_count++; 708c2ecf20Sopenharmony_ci } 718c2ecf20Sopenharmony_ci 728c2ecf20Sopenharmony_ci } 738c2ecf20Sopenharmony_ci 748c2ecf20Sopenharmony_ci /* have a look at the last byte inserted: 758c2ecf20Sopenharmony_ci if it was: ...CONT change it to ...STOP */ 768c2ecf20Sopenharmony_ci h1 = (op_count-1)/3; h2 = (op_count-1)%3; 778c2ecf20Sopenharmony_ci if ( SAA7146_I2C_CONT == (0x3 & (le32_to_cpu(op[h1]) >> ((3-h2)*2))) ) { 788c2ecf20Sopenharmony_ci op[h1] &= ~cpu_to_le32(0x2 << ((3-h2)*2)); 798c2ecf20Sopenharmony_ci op[h1] |= cpu_to_le32(SAA7146_I2C_STOP << ((3-h2)*2)); 808c2ecf20Sopenharmony_ci } 818c2ecf20Sopenharmony_ci 828c2ecf20Sopenharmony_ci /* return the number of u32s to send */ 838c2ecf20Sopenharmony_ci return mem; 848c2ecf20Sopenharmony_ci} 858c2ecf20Sopenharmony_ci 868c2ecf20Sopenharmony_ci/* this functions loops through all i2c-messages. normally, it should determine 878c2ecf20Sopenharmony_ci which bytes were read through the adapter and write them back to the corresponding 888c2ecf20Sopenharmony_ci i2c-message. but instead, we simply write back all bytes. 898c2ecf20Sopenharmony_ci fixme: this could be improved. */ 908c2ecf20Sopenharmony_cistatic int saa7146_i2c_msg_cleanup(const struct i2c_msg *m, int num, __le32 *op) 918c2ecf20Sopenharmony_ci{ 928c2ecf20Sopenharmony_ci int i, j; 938c2ecf20Sopenharmony_ci int op_count = 0; 948c2ecf20Sopenharmony_ci 958c2ecf20Sopenharmony_ci /* loop through all messages */ 968c2ecf20Sopenharmony_ci for(i = 0; i < num; i++) { 978c2ecf20Sopenharmony_ci 988c2ecf20Sopenharmony_ci op_count++; 998c2ecf20Sopenharmony_ci 1008c2ecf20Sopenharmony_ci /* loop through all bytes of message i */ 1018c2ecf20Sopenharmony_ci for(j = 0; j < m[i].len; j++) { 1028c2ecf20Sopenharmony_ci /* write back all bytes that could have been read */ 1038c2ecf20Sopenharmony_ci m[i].buf[j] = (le32_to_cpu(op[op_count/3]) >> ((3-(op_count%3))*8)); 1048c2ecf20Sopenharmony_ci op_count++; 1058c2ecf20Sopenharmony_ci } 1068c2ecf20Sopenharmony_ci } 1078c2ecf20Sopenharmony_ci 1088c2ecf20Sopenharmony_ci return 0; 1098c2ecf20Sopenharmony_ci} 1108c2ecf20Sopenharmony_ci 1118c2ecf20Sopenharmony_ci/* this functions resets the i2c-device and returns 0 if everything was fine, otherwise -1 */ 1128c2ecf20Sopenharmony_cistatic int saa7146_i2c_reset(struct saa7146_dev *dev) 1138c2ecf20Sopenharmony_ci{ 1148c2ecf20Sopenharmony_ci /* get current status */ 1158c2ecf20Sopenharmony_ci u32 status = saa7146_i2c_status(dev); 1168c2ecf20Sopenharmony_ci 1178c2ecf20Sopenharmony_ci /* clear registers for sure */ 1188c2ecf20Sopenharmony_ci saa7146_write(dev, I2C_STATUS, dev->i2c_bitrate); 1198c2ecf20Sopenharmony_ci saa7146_write(dev, I2C_TRANSFER, 0); 1208c2ecf20Sopenharmony_ci 1218c2ecf20Sopenharmony_ci /* check if any operation is still in progress */ 1228c2ecf20Sopenharmony_ci if ( 0 != ( status & SAA7146_I2C_BUSY) ) { 1238c2ecf20Sopenharmony_ci 1248c2ecf20Sopenharmony_ci /* yes, kill ongoing operation */ 1258c2ecf20Sopenharmony_ci DEB_I2C("busy_state detected\n"); 1268c2ecf20Sopenharmony_ci 1278c2ecf20Sopenharmony_ci /* set "ABORT-OPERATION"-bit (bit 7)*/ 1288c2ecf20Sopenharmony_ci saa7146_write(dev, I2C_STATUS, (dev->i2c_bitrate | MASK_07)); 1298c2ecf20Sopenharmony_ci saa7146_write(dev, MC2, (MASK_00 | MASK_16)); 1308c2ecf20Sopenharmony_ci msleep(SAA7146_I2C_DELAY); 1318c2ecf20Sopenharmony_ci 1328c2ecf20Sopenharmony_ci /* clear all error-bits pending; this is needed because p.123, note 1 */ 1338c2ecf20Sopenharmony_ci saa7146_write(dev, I2C_STATUS, dev->i2c_bitrate); 1348c2ecf20Sopenharmony_ci saa7146_write(dev, MC2, (MASK_00 | MASK_16)); 1358c2ecf20Sopenharmony_ci msleep(SAA7146_I2C_DELAY); 1368c2ecf20Sopenharmony_ci } 1378c2ecf20Sopenharmony_ci 1388c2ecf20Sopenharmony_ci /* check if any error is (still) present. (this can be necessary because p.123, note 1) */ 1398c2ecf20Sopenharmony_ci status = saa7146_i2c_status(dev); 1408c2ecf20Sopenharmony_ci 1418c2ecf20Sopenharmony_ci if ( dev->i2c_bitrate != status ) { 1428c2ecf20Sopenharmony_ci 1438c2ecf20Sopenharmony_ci DEB_I2C("error_state detected. status:0x%08x\n", status); 1448c2ecf20Sopenharmony_ci 1458c2ecf20Sopenharmony_ci /* Repeat the abort operation. This seems to be necessary 1468c2ecf20Sopenharmony_ci after serious protocol errors caused by e.g. the SAA7740 */ 1478c2ecf20Sopenharmony_ci saa7146_write(dev, I2C_STATUS, (dev->i2c_bitrate | MASK_07)); 1488c2ecf20Sopenharmony_ci saa7146_write(dev, MC2, (MASK_00 | MASK_16)); 1498c2ecf20Sopenharmony_ci msleep(SAA7146_I2C_DELAY); 1508c2ecf20Sopenharmony_ci 1518c2ecf20Sopenharmony_ci /* clear all error-bits pending */ 1528c2ecf20Sopenharmony_ci saa7146_write(dev, I2C_STATUS, dev->i2c_bitrate); 1538c2ecf20Sopenharmony_ci saa7146_write(dev, MC2, (MASK_00 | MASK_16)); 1548c2ecf20Sopenharmony_ci msleep(SAA7146_I2C_DELAY); 1558c2ecf20Sopenharmony_ci 1568c2ecf20Sopenharmony_ci /* the data sheet says it might be necessary to clear the status 1578c2ecf20Sopenharmony_ci twice after an abort */ 1588c2ecf20Sopenharmony_ci saa7146_write(dev, I2C_STATUS, dev->i2c_bitrate); 1598c2ecf20Sopenharmony_ci saa7146_write(dev, MC2, (MASK_00 | MASK_16)); 1608c2ecf20Sopenharmony_ci msleep(SAA7146_I2C_DELAY); 1618c2ecf20Sopenharmony_ci } 1628c2ecf20Sopenharmony_ci 1638c2ecf20Sopenharmony_ci /* if any error is still present, a fatal error has occurred ... */ 1648c2ecf20Sopenharmony_ci status = saa7146_i2c_status(dev); 1658c2ecf20Sopenharmony_ci if ( dev->i2c_bitrate != status ) { 1668c2ecf20Sopenharmony_ci DEB_I2C("fatal error. status:0x%08x\n", status); 1678c2ecf20Sopenharmony_ci return -1; 1688c2ecf20Sopenharmony_ci } 1698c2ecf20Sopenharmony_ci 1708c2ecf20Sopenharmony_ci return 0; 1718c2ecf20Sopenharmony_ci} 1728c2ecf20Sopenharmony_ci 1738c2ecf20Sopenharmony_ci/* this functions writes out the data-byte 'dword' to the i2c-device. 1748c2ecf20Sopenharmony_ci it returns 0 if ok, -1 if the transfer failed, -2 if the transfer 1758c2ecf20Sopenharmony_ci failed badly (e.g. address error) */ 1768c2ecf20Sopenharmony_cistatic int saa7146_i2c_writeout(struct saa7146_dev *dev, __le32 *dword, int short_delay) 1778c2ecf20Sopenharmony_ci{ 1788c2ecf20Sopenharmony_ci u32 status = 0, mc2 = 0; 1798c2ecf20Sopenharmony_ci int trial = 0; 1808c2ecf20Sopenharmony_ci unsigned long timeout; 1818c2ecf20Sopenharmony_ci 1828c2ecf20Sopenharmony_ci /* write out i2c-command */ 1838c2ecf20Sopenharmony_ci DEB_I2C("before: 0x%08x (status: 0x%08x), %d\n", 1848c2ecf20Sopenharmony_ci *dword, saa7146_read(dev, I2C_STATUS), dev->i2c_op); 1858c2ecf20Sopenharmony_ci 1868c2ecf20Sopenharmony_ci if( 0 != (SAA7146_USE_I2C_IRQ & dev->ext->flags)) { 1878c2ecf20Sopenharmony_ci 1888c2ecf20Sopenharmony_ci saa7146_write(dev, I2C_STATUS, dev->i2c_bitrate); 1898c2ecf20Sopenharmony_ci saa7146_write(dev, I2C_TRANSFER, le32_to_cpu(*dword)); 1908c2ecf20Sopenharmony_ci 1918c2ecf20Sopenharmony_ci dev->i2c_op = 1; 1928c2ecf20Sopenharmony_ci SAA7146_ISR_CLEAR(dev, MASK_16|MASK_17); 1938c2ecf20Sopenharmony_ci SAA7146_IER_ENABLE(dev, MASK_16|MASK_17); 1948c2ecf20Sopenharmony_ci saa7146_write(dev, MC2, (MASK_00 | MASK_16)); 1958c2ecf20Sopenharmony_ci 1968c2ecf20Sopenharmony_ci timeout = HZ/100 + 1; /* 10ms */ 1978c2ecf20Sopenharmony_ci timeout = wait_event_interruptible_timeout(dev->i2c_wq, dev->i2c_op == 0, timeout); 1988c2ecf20Sopenharmony_ci if (timeout == -ERESTARTSYS || dev->i2c_op) { 1998c2ecf20Sopenharmony_ci SAA7146_IER_DISABLE(dev, MASK_16|MASK_17); 2008c2ecf20Sopenharmony_ci SAA7146_ISR_CLEAR(dev, MASK_16|MASK_17); 2018c2ecf20Sopenharmony_ci if (timeout == -ERESTARTSYS) 2028c2ecf20Sopenharmony_ci /* a signal arrived */ 2038c2ecf20Sopenharmony_ci return -ERESTARTSYS; 2048c2ecf20Sopenharmony_ci 2058c2ecf20Sopenharmony_ci pr_warn("%s %s [irq]: timed out waiting for end of xfer\n", 2068c2ecf20Sopenharmony_ci dev->name, __func__); 2078c2ecf20Sopenharmony_ci return -EIO; 2088c2ecf20Sopenharmony_ci } 2098c2ecf20Sopenharmony_ci status = saa7146_read(dev, I2C_STATUS); 2108c2ecf20Sopenharmony_ci } else { 2118c2ecf20Sopenharmony_ci saa7146_write(dev, I2C_STATUS, dev->i2c_bitrate); 2128c2ecf20Sopenharmony_ci saa7146_write(dev, I2C_TRANSFER, le32_to_cpu(*dword)); 2138c2ecf20Sopenharmony_ci saa7146_write(dev, MC2, (MASK_00 | MASK_16)); 2148c2ecf20Sopenharmony_ci 2158c2ecf20Sopenharmony_ci /* do not poll for i2c-status before upload is complete */ 2168c2ecf20Sopenharmony_ci timeout = jiffies + HZ/100 + 1; /* 10ms */ 2178c2ecf20Sopenharmony_ci while(1) { 2188c2ecf20Sopenharmony_ci mc2 = (saa7146_read(dev, MC2) & 0x1); 2198c2ecf20Sopenharmony_ci if( 0 != mc2 ) { 2208c2ecf20Sopenharmony_ci break; 2218c2ecf20Sopenharmony_ci } 2228c2ecf20Sopenharmony_ci if (time_after(jiffies,timeout)) { 2238c2ecf20Sopenharmony_ci pr_warn("%s %s: timed out waiting for MC2\n", 2248c2ecf20Sopenharmony_ci dev->name, __func__); 2258c2ecf20Sopenharmony_ci return -EIO; 2268c2ecf20Sopenharmony_ci } 2278c2ecf20Sopenharmony_ci } 2288c2ecf20Sopenharmony_ci /* wait until we get a transfer done or error */ 2298c2ecf20Sopenharmony_ci timeout = jiffies + HZ/100 + 1; /* 10ms */ 2308c2ecf20Sopenharmony_ci /* first read usually delivers bogus results... */ 2318c2ecf20Sopenharmony_ci saa7146_i2c_status(dev); 2328c2ecf20Sopenharmony_ci while(1) { 2338c2ecf20Sopenharmony_ci status = saa7146_i2c_status(dev); 2348c2ecf20Sopenharmony_ci if ((status & 0x3) != 1) 2358c2ecf20Sopenharmony_ci break; 2368c2ecf20Sopenharmony_ci if (time_after(jiffies,timeout)) { 2378c2ecf20Sopenharmony_ci /* this is normal when probing the bus 2388c2ecf20Sopenharmony_ci * (no answer from nonexisistant device...) 2398c2ecf20Sopenharmony_ci */ 2408c2ecf20Sopenharmony_ci pr_warn("%s %s [poll]: timed out waiting for end of xfer\n", 2418c2ecf20Sopenharmony_ci dev->name, __func__); 2428c2ecf20Sopenharmony_ci return -EIO; 2438c2ecf20Sopenharmony_ci } 2448c2ecf20Sopenharmony_ci if (++trial < 50 && short_delay) 2458c2ecf20Sopenharmony_ci udelay(10); 2468c2ecf20Sopenharmony_ci else 2478c2ecf20Sopenharmony_ci msleep(1); 2488c2ecf20Sopenharmony_ci } 2498c2ecf20Sopenharmony_ci } 2508c2ecf20Sopenharmony_ci 2518c2ecf20Sopenharmony_ci /* give a detailed status report */ 2528c2ecf20Sopenharmony_ci if ( 0 != (status & (SAA7146_I2C_SPERR | SAA7146_I2C_APERR | 2538c2ecf20Sopenharmony_ci SAA7146_I2C_DTERR | SAA7146_I2C_DRERR | 2548c2ecf20Sopenharmony_ci SAA7146_I2C_AL | SAA7146_I2C_ERR | 2558c2ecf20Sopenharmony_ci SAA7146_I2C_BUSY)) ) { 2568c2ecf20Sopenharmony_ci 2578c2ecf20Sopenharmony_ci if ( 0 == (status & SAA7146_I2C_ERR) || 2588c2ecf20Sopenharmony_ci 0 == (status & SAA7146_I2C_BUSY) ) { 2598c2ecf20Sopenharmony_ci /* it may take some time until ERR goes high - ignore */ 2608c2ecf20Sopenharmony_ci DEB_I2C("unexpected i2c status %04x\n", status); 2618c2ecf20Sopenharmony_ci } 2628c2ecf20Sopenharmony_ci if( 0 != (status & SAA7146_I2C_SPERR) ) { 2638c2ecf20Sopenharmony_ci DEB_I2C("error due to invalid start/stop condition\n"); 2648c2ecf20Sopenharmony_ci } 2658c2ecf20Sopenharmony_ci if( 0 != (status & SAA7146_I2C_DTERR) ) { 2668c2ecf20Sopenharmony_ci DEB_I2C("error in data transmission\n"); 2678c2ecf20Sopenharmony_ci } 2688c2ecf20Sopenharmony_ci if( 0 != (status & SAA7146_I2C_DRERR) ) { 2698c2ecf20Sopenharmony_ci DEB_I2C("error when receiving data\n"); 2708c2ecf20Sopenharmony_ci } 2718c2ecf20Sopenharmony_ci if( 0 != (status & SAA7146_I2C_AL) ) { 2728c2ecf20Sopenharmony_ci DEB_I2C("error because arbitration lost\n"); 2738c2ecf20Sopenharmony_ci } 2748c2ecf20Sopenharmony_ci 2758c2ecf20Sopenharmony_ci /* we handle address-errors here */ 2768c2ecf20Sopenharmony_ci if( 0 != (status & SAA7146_I2C_APERR) ) { 2778c2ecf20Sopenharmony_ci DEB_I2C("error in address phase\n"); 2788c2ecf20Sopenharmony_ci return -EREMOTEIO; 2798c2ecf20Sopenharmony_ci } 2808c2ecf20Sopenharmony_ci 2818c2ecf20Sopenharmony_ci return -EIO; 2828c2ecf20Sopenharmony_ci } 2838c2ecf20Sopenharmony_ci 2848c2ecf20Sopenharmony_ci /* read back data, just in case we were reading ... */ 2858c2ecf20Sopenharmony_ci *dword = cpu_to_le32(saa7146_read(dev, I2C_TRANSFER)); 2868c2ecf20Sopenharmony_ci 2878c2ecf20Sopenharmony_ci DEB_I2C("after: 0x%08x\n", *dword); 2888c2ecf20Sopenharmony_ci return 0; 2898c2ecf20Sopenharmony_ci} 2908c2ecf20Sopenharmony_ci 2918c2ecf20Sopenharmony_cistatic int saa7146_i2c_transfer(struct saa7146_dev *dev, const struct i2c_msg *msgs, int num, int retries) 2928c2ecf20Sopenharmony_ci{ 2938c2ecf20Sopenharmony_ci int i = 0, count = 0; 2948c2ecf20Sopenharmony_ci __le32 *buffer = dev->d_i2c.cpu_addr; 2958c2ecf20Sopenharmony_ci int err = 0; 2968c2ecf20Sopenharmony_ci int short_delay = 0; 2978c2ecf20Sopenharmony_ci 2988c2ecf20Sopenharmony_ci if (mutex_lock_interruptible(&dev->i2c_lock)) 2998c2ecf20Sopenharmony_ci return -ERESTARTSYS; 3008c2ecf20Sopenharmony_ci 3018c2ecf20Sopenharmony_ci for(i=0;i<num;i++) { 3028c2ecf20Sopenharmony_ci DEB_I2C("msg:%d/%d\n", i+1, num); 3038c2ecf20Sopenharmony_ci } 3048c2ecf20Sopenharmony_ci 3058c2ecf20Sopenharmony_ci /* prepare the message(s), get number of u32s to transfer */ 3068c2ecf20Sopenharmony_ci count = saa7146_i2c_msg_prepare(msgs, num, buffer); 3078c2ecf20Sopenharmony_ci if ( 0 > count ) { 3088c2ecf20Sopenharmony_ci err = -EIO; 3098c2ecf20Sopenharmony_ci goto out; 3108c2ecf20Sopenharmony_ci } 3118c2ecf20Sopenharmony_ci 3128c2ecf20Sopenharmony_ci if ( count > 3 || 0 != (SAA7146_I2C_SHORT_DELAY & dev->ext->flags) ) 3138c2ecf20Sopenharmony_ci short_delay = 1; 3148c2ecf20Sopenharmony_ci 3158c2ecf20Sopenharmony_ci do { 3168c2ecf20Sopenharmony_ci /* reset the i2c-device if necessary */ 3178c2ecf20Sopenharmony_ci err = saa7146_i2c_reset(dev); 3188c2ecf20Sopenharmony_ci if ( 0 > err ) { 3198c2ecf20Sopenharmony_ci DEB_I2C("could not reset i2c-device\n"); 3208c2ecf20Sopenharmony_ci goto out; 3218c2ecf20Sopenharmony_ci } 3228c2ecf20Sopenharmony_ci 3238c2ecf20Sopenharmony_ci /* write out the u32s one after another */ 3248c2ecf20Sopenharmony_ci for(i = 0; i < count; i++) { 3258c2ecf20Sopenharmony_ci err = saa7146_i2c_writeout(dev, &buffer[i], short_delay); 3268c2ecf20Sopenharmony_ci if ( 0 != err) { 3278c2ecf20Sopenharmony_ci /* this one is unsatisfying: some i2c slaves on some 3288c2ecf20Sopenharmony_ci dvb cards don't acknowledge correctly, so the saa7146 3298c2ecf20Sopenharmony_ci thinks that an address error occurred. in that case, the 3308c2ecf20Sopenharmony_ci transaction should be retrying, even if an address error 3318c2ecf20Sopenharmony_ci occurred. analog saa7146 based cards extensively rely on 3328c2ecf20Sopenharmony_ci i2c address probing, however, and address errors indicate that a 3338c2ecf20Sopenharmony_ci device is really *not* there. retrying in that case 3348c2ecf20Sopenharmony_ci increases the time the device needs to probe greatly, so 3358c2ecf20Sopenharmony_ci it should be avoided. So we bail out in irq mode after an 3368c2ecf20Sopenharmony_ci address error and trust the saa7146 address error detection. */ 3378c2ecf20Sopenharmony_ci if (-EREMOTEIO == err && 0 != (SAA7146_USE_I2C_IRQ & dev->ext->flags)) 3388c2ecf20Sopenharmony_ci goto out; 3398c2ecf20Sopenharmony_ci DEB_I2C("error while sending message(s). starting again\n"); 3408c2ecf20Sopenharmony_ci break; 3418c2ecf20Sopenharmony_ci } 3428c2ecf20Sopenharmony_ci } 3438c2ecf20Sopenharmony_ci if( 0 == err ) { 3448c2ecf20Sopenharmony_ci err = num; 3458c2ecf20Sopenharmony_ci break; 3468c2ecf20Sopenharmony_ci } 3478c2ecf20Sopenharmony_ci 3488c2ecf20Sopenharmony_ci /* delay a bit before retrying */ 3498c2ecf20Sopenharmony_ci msleep(10); 3508c2ecf20Sopenharmony_ci 3518c2ecf20Sopenharmony_ci } while (err != num && retries--); 3528c2ecf20Sopenharmony_ci 3538c2ecf20Sopenharmony_ci /* quit if any error occurred */ 3548c2ecf20Sopenharmony_ci if (err != num) 3558c2ecf20Sopenharmony_ci goto out; 3568c2ecf20Sopenharmony_ci 3578c2ecf20Sopenharmony_ci /* if any things had to be read, get the results */ 3588c2ecf20Sopenharmony_ci if ( 0 != saa7146_i2c_msg_cleanup(msgs, num, buffer)) { 3598c2ecf20Sopenharmony_ci DEB_I2C("could not cleanup i2c-message\n"); 3608c2ecf20Sopenharmony_ci err = -EIO; 3618c2ecf20Sopenharmony_ci goto out; 3628c2ecf20Sopenharmony_ci } 3638c2ecf20Sopenharmony_ci 3648c2ecf20Sopenharmony_ci /* return the number of delivered messages */ 3658c2ecf20Sopenharmony_ci DEB_I2C("transmission successful. (msg:%d)\n", err); 3668c2ecf20Sopenharmony_ciout: 3678c2ecf20Sopenharmony_ci /* another bug in revision 0: the i2c-registers get uploaded randomly by other 3688c2ecf20Sopenharmony_ci uploads, so we better clear them out before continuing */ 3698c2ecf20Sopenharmony_ci if( 0 == dev->revision ) { 3708c2ecf20Sopenharmony_ci __le32 zero = 0; 3718c2ecf20Sopenharmony_ci saa7146_i2c_reset(dev); 3728c2ecf20Sopenharmony_ci if( 0 != saa7146_i2c_writeout(dev, &zero, short_delay)) { 3738c2ecf20Sopenharmony_ci pr_info("revision 0 error. this should never happen\n"); 3748c2ecf20Sopenharmony_ci } 3758c2ecf20Sopenharmony_ci } 3768c2ecf20Sopenharmony_ci 3778c2ecf20Sopenharmony_ci mutex_unlock(&dev->i2c_lock); 3788c2ecf20Sopenharmony_ci return err; 3798c2ecf20Sopenharmony_ci} 3808c2ecf20Sopenharmony_ci 3818c2ecf20Sopenharmony_ci/* utility functions */ 3828c2ecf20Sopenharmony_cistatic int saa7146_i2c_xfer(struct i2c_adapter* adapter, struct i2c_msg *msg, int num) 3838c2ecf20Sopenharmony_ci{ 3848c2ecf20Sopenharmony_ci struct v4l2_device *v4l2_dev = i2c_get_adapdata(adapter); 3858c2ecf20Sopenharmony_ci struct saa7146_dev *dev = to_saa7146_dev(v4l2_dev); 3868c2ecf20Sopenharmony_ci 3878c2ecf20Sopenharmony_ci /* use helper function to transfer data */ 3888c2ecf20Sopenharmony_ci return saa7146_i2c_transfer(dev, msg, num, adapter->retries); 3898c2ecf20Sopenharmony_ci} 3908c2ecf20Sopenharmony_ci 3918c2ecf20Sopenharmony_ci 3928c2ecf20Sopenharmony_ci/*****************************************************************************/ 3938c2ecf20Sopenharmony_ci/* i2c-adapter helper functions */ 3948c2ecf20Sopenharmony_ci 3958c2ecf20Sopenharmony_ci/* exported algorithm data */ 3968c2ecf20Sopenharmony_cistatic const struct i2c_algorithm saa7146_algo = { 3978c2ecf20Sopenharmony_ci .master_xfer = saa7146_i2c_xfer, 3988c2ecf20Sopenharmony_ci .functionality = saa7146_i2c_func, 3998c2ecf20Sopenharmony_ci}; 4008c2ecf20Sopenharmony_ci 4018c2ecf20Sopenharmony_ciint saa7146_i2c_adapter_prepare(struct saa7146_dev *dev, struct i2c_adapter *i2c_adapter, u32 bitrate) 4028c2ecf20Sopenharmony_ci{ 4038c2ecf20Sopenharmony_ci DEB_EE("bitrate: 0x%08x\n", bitrate); 4048c2ecf20Sopenharmony_ci 4058c2ecf20Sopenharmony_ci /* enable i2c-port pins */ 4068c2ecf20Sopenharmony_ci saa7146_write(dev, MC1, (MASK_08 | MASK_24)); 4078c2ecf20Sopenharmony_ci 4088c2ecf20Sopenharmony_ci dev->i2c_bitrate = bitrate; 4098c2ecf20Sopenharmony_ci saa7146_i2c_reset(dev); 4108c2ecf20Sopenharmony_ci 4118c2ecf20Sopenharmony_ci if (i2c_adapter) { 4128c2ecf20Sopenharmony_ci i2c_set_adapdata(i2c_adapter, &dev->v4l2_dev); 4138c2ecf20Sopenharmony_ci i2c_adapter->dev.parent = &dev->pci->dev; 4148c2ecf20Sopenharmony_ci i2c_adapter->algo = &saa7146_algo; 4158c2ecf20Sopenharmony_ci i2c_adapter->algo_data = NULL; 4168c2ecf20Sopenharmony_ci i2c_adapter->timeout = SAA7146_I2C_TIMEOUT; 4178c2ecf20Sopenharmony_ci i2c_adapter->retries = SAA7146_I2C_RETRIES; 4188c2ecf20Sopenharmony_ci } 4198c2ecf20Sopenharmony_ci 4208c2ecf20Sopenharmony_ci return 0; 4218c2ecf20Sopenharmony_ci} 422