1a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton/* 2f7abcd385cc8a5a2f75b07c8325067ea2785ba1eMauro Carvalho Chehab em28xx-i2c.c - driver for Empia EM2800/EM2820/2840 USB video capture devices 3a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton 4f7abcd385cc8a5a2f75b07c8325067ea2785ba1eMauro Carvalho Chehab Copyright (C) 2005 Ludovico Cavedon <cavedon@sssup.it> 5f7abcd385cc8a5a2f75b07c8325067ea2785ba1eMauro Carvalho Chehab Markus Rechberger <mrechberger@gmail.com> 62e7c6dc3989136844eb63e05f9e4dc6608a763c6Mauro Carvalho Chehab Mauro Carvalho Chehab <mchehab@infradead.org> 7f7abcd385cc8a5a2f75b07c8325067ea2785ba1eMauro Carvalho Chehab Sascha Sommer <saschasommer@freenet.de> 8a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton 9a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton This program is free software; you can redistribute it and/or modify 10a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton it under the terms of the GNU General Public License as published by 11a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton the Free Software Foundation; either version 2 of the License, or 12a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton (at your option) any later version. 13a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton 14a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton This program is distributed in the hope that it will be useful, 15a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton but WITHOUT ANY WARRANTY; without even the implied warranty of 16a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton GNU General Public License for more details. 18a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton 19a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton You should have received a copy of the GNU General Public License 20a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton along with this program; if not, write to the Free Software 21a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 22a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton */ 23a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton 24a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton#include <linux/module.h> 25a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton#include <linux/kernel.h> 26a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton#include <linux/usb.h> 27a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton#include <linux/i2c.h> 28a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton 29f7abcd385cc8a5a2f75b07c8325067ea2785ba1eMauro Carvalho Chehab#include "em28xx.h" 306c362c8e58da972728a3666a0a00b9c2f1574e1fMauro Carvalho Chehab#include "tuner-xc2028.h" 315e453dc757385ec892a818e4e3b5de027987ced9Michael Krufky#include <media/v4l2-common.h> 32d5e5265315770bda46c50ecaa64e2b9790f2064cMauro Carvalho Chehab#include <media/tuner.h> 33a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton 34a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton/* ----------------------------------------------------------- */ 35a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton 36ff699e6bd02eb1c6d02c7c2b576c2ee6caab201cDouglas Schilling Landgrafstatic unsigned int i2c_scan; 37a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Mortonmodule_param(i2c_scan, int, 0444); 38a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew MortonMODULE_PARM_DESC(i2c_scan, "scan i2c bus at insmod time"); 39a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton 40ff699e6bd02eb1c6d02c7c2b576c2ee6caab201cDouglas Schilling Landgrafstatic unsigned int i2c_debug; 41a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Mortonmodule_param(i2c_debug, int, 0644); 42a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew MortonMODULE_PARM_DESC(i2c_debug, "enable debug messages [i2c]"); 43a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton 446ea54d938b6f81baa0952a8b15d3e67e6c268b8fDouglas Schilling Landgraf 456ea54d938b6f81baa0952a8b15d3e67e6c268b8fDouglas Schilling Landgraf#define dprintk1(lvl, fmt, args...) \ 466ea54d938b6f81baa0952a8b15d3e67e6c268b8fDouglas Schilling Landgrafdo { \ 476ea54d938b6f81baa0952a8b15d3e67e6c268b8fDouglas Schilling Landgraf if (i2c_debug >= lvl) { \ 486ea54d938b6f81baa0952a8b15d3e67e6c268b8fDouglas Schilling Landgraf printk(fmt, ##args); \ 496ea54d938b6f81baa0952a8b15d3e67e6c268b8fDouglas Schilling Landgraf } \ 506ea54d938b6f81baa0952a8b15d3e67e6c268b8fDouglas Schilling Landgraf} while (0) 516ea54d938b6f81baa0952a8b15d3e67e6c268b8fDouglas Schilling Landgraf 526ea54d938b6f81baa0952a8b15d3e67e6c268b8fDouglas Schilling Landgraf#define dprintk2(lvl, fmt, args...) \ 536ea54d938b6f81baa0952a8b15d3e67e6c268b8fDouglas Schilling Landgrafdo { \ 546ea54d938b6f81baa0952a8b15d3e67e6c268b8fDouglas Schilling Landgraf if (i2c_debug >= lvl) { \ 556ea54d938b6f81baa0952a8b15d3e67e6c268b8fDouglas Schilling Landgraf printk(KERN_DEBUG "%s at %s: " fmt, \ 566ea54d938b6f81baa0952a8b15d3e67e6c268b8fDouglas Schilling Landgraf dev->name, __func__ , ##args); \ 576ea54d938b6f81baa0952a8b15d3e67e6c268b8fDouglas Schilling Landgraf } \ 586ea54d938b6f81baa0952a8b15d3e67e6c268b8fDouglas Schilling Landgraf} while (0) 59a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton 60a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton/* 61596d92d5128d308b5a79f21c3e72c87f5fc7e58bMauro Carvalho Chehab * em2800_i2c_send_max4() 62596d92d5128d308b5a79f21c3e72c87f5fc7e58bMauro Carvalho Chehab * send up to 4 bytes to the i2c device 63596d92d5128d308b5a79f21c3e72c87f5fc7e58bMauro Carvalho Chehab */ 643acf28095009509c9ca1e283de821b5be9ddede6Mauro Carvalho Chehabstatic int em2800_i2c_send_max4(struct em28xx *dev, unsigned char addr, 65596d92d5128d308b5a79f21c3e72c87f5fc7e58bMauro Carvalho Chehab char *buf, int len) 66596d92d5128d308b5a79f21c3e72c87f5fc7e58bMauro Carvalho Chehab{ 67596d92d5128d308b5a79f21c3e72c87f5fc7e58bMauro Carvalho Chehab int ret; 68596d92d5128d308b5a79f21c3e72c87f5fc7e58bMauro Carvalho Chehab int write_timeout; 69596d92d5128d308b5a79f21c3e72c87f5fc7e58bMauro Carvalho Chehab unsigned char b2[6]; 70596d92d5128d308b5a79f21c3e72c87f5fc7e58bMauro Carvalho Chehab BUG_ON(len < 1 || len > 4); 71596d92d5128d308b5a79f21c3e72c87f5fc7e58bMauro Carvalho Chehab b2[5] = 0x80 + len - 1; 72596d92d5128d308b5a79f21c3e72c87f5fc7e58bMauro Carvalho Chehab b2[4] = addr; 73596d92d5128d308b5a79f21c3e72c87f5fc7e58bMauro Carvalho Chehab b2[3] = buf[0]; 74596d92d5128d308b5a79f21c3e72c87f5fc7e58bMauro Carvalho Chehab if (len > 1) 75596d92d5128d308b5a79f21c3e72c87f5fc7e58bMauro Carvalho Chehab b2[2] = buf[1]; 76596d92d5128d308b5a79f21c3e72c87f5fc7e58bMauro Carvalho Chehab if (len > 2) 77596d92d5128d308b5a79f21c3e72c87f5fc7e58bMauro Carvalho Chehab b2[1] = buf[2]; 78596d92d5128d308b5a79f21c3e72c87f5fc7e58bMauro Carvalho Chehab if (len > 3) 79596d92d5128d308b5a79f21c3e72c87f5fc7e58bMauro Carvalho Chehab b2[0] = buf[3]; 80596d92d5128d308b5a79f21c3e72c87f5fc7e58bMauro Carvalho Chehab 813acf28095009509c9ca1e283de821b5be9ddede6Mauro Carvalho Chehab ret = dev->em28xx_write_regs(dev, 4 - len, &b2[4 - len], 2 + len); 82596d92d5128d308b5a79f21c3e72c87f5fc7e58bMauro Carvalho Chehab if (ret != 2 + len) { 83beb7dd86a101263bf63a78c7c6d4da3849b35bd6Robert P. J. Day em28xx_warn("writing to i2c device failed (error=%i)\n", ret); 84596d92d5128d308b5a79f21c3e72c87f5fc7e58bMauro Carvalho Chehab return -EIO; 85596d92d5128d308b5a79f21c3e72c87f5fc7e58bMauro Carvalho Chehab } 86596d92d5128d308b5a79f21c3e72c87f5fc7e58bMauro Carvalho Chehab for (write_timeout = EM2800_I2C_WRITE_TIMEOUT; write_timeout > 0; 87596d92d5128d308b5a79f21c3e72c87f5fc7e58bMauro Carvalho Chehab write_timeout -= 5) { 883acf28095009509c9ca1e283de821b5be9ddede6Mauro Carvalho Chehab ret = dev->em28xx_read_reg(dev, 0x05); 89596d92d5128d308b5a79f21c3e72c87f5fc7e58bMauro Carvalho Chehab if (ret == 0x80 + len - 1) 90596d92d5128d308b5a79f21c3e72c87f5fc7e58bMauro Carvalho Chehab return len; 91e8e41da46dca6b33e990b48ee379503d25b4da65Markus Rechberger msleep(5); 92596d92d5128d308b5a79f21c3e72c87f5fc7e58bMauro Carvalho Chehab } 933acf28095009509c9ca1e283de821b5be9ddede6Mauro Carvalho Chehab em28xx_warn("i2c write timed out\n"); 94596d92d5128d308b5a79f21c3e72c87f5fc7e58bMauro Carvalho Chehab return -EIO; 95596d92d5128d308b5a79f21c3e72c87f5fc7e58bMauro Carvalho Chehab} 96596d92d5128d308b5a79f21c3e72c87f5fc7e58bMauro Carvalho Chehab 97596d92d5128d308b5a79f21c3e72c87f5fc7e58bMauro Carvalho Chehab/* 98596d92d5128d308b5a79f21c3e72c87f5fc7e58bMauro Carvalho Chehab * em2800_i2c_send_bytes() 99596d92d5128d308b5a79f21c3e72c87f5fc7e58bMauro Carvalho Chehab */ 100596d92d5128d308b5a79f21c3e72c87f5fc7e58bMauro Carvalho Chehabstatic int em2800_i2c_send_bytes(void *data, unsigned char addr, char *buf, 101596d92d5128d308b5a79f21c3e72c87f5fc7e58bMauro Carvalho Chehab short len) 102596d92d5128d308b5a79f21c3e72c87f5fc7e58bMauro Carvalho Chehab{ 103596d92d5128d308b5a79f21c3e72c87f5fc7e58bMauro Carvalho Chehab char *bufPtr = buf; 104596d92d5128d308b5a79f21c3e72c87f5fc7e58bMauro Carvalho Chehab int ret; 105596d92d5128d308b5a79f21c3e72c87f5fc7e58bMauro Carvalho Chehab int wrcount = 0; 106596d92d5128d308b5a79f21c3e72c87f5fc7e58bMauro Carvalho Chehab int count; 107596d92d5128d308b5a79f21c3e72c87f5fc7e58bMauro Carvalho Chehab int maxLen = 4; 1083acf28095009509c9ca1e283de821b5be9ddede6Mauro Carvalho Chehab struct em28xx *dev = (struct em28xx *)data; 109596d92d5128d308b5a79f21c3e72c87f5fc7e58bMauro Carvalho Chehab while (len > 0) { 110596d92d5128d308b5a79f21c3e72c87f5fc7e58bMauro Carvalho Chehab count = (len > maxLen) ? maxLen : len; 111596d92d5128d308b5a79f21c3e72c87f5fc7e58bMauro Carvalho Chehab ret = em2800_i2c_send_max4(dev, addr, bufPtr, count); 112596d92d5128d308b5a79f21c3e72c87f5fc7e58bMauro Carvalho Chehab if (ret > 0) { 113596d92d5128d308b5a79f21c3e72c87f5fc7e58bMauro Carvalho Chehab len -= count; 114596d92d5128d308b5a79f21c3e72c87f5fc7e58bMauro Carvalho Chehab bufPtr += count; 115596d92d5128d308b5a79f21c3e72c87f5fc7e58bMauro Carvalho Chehab wrcount += count; 116596d92d5128d308b5a79f21c3e72c87f5fc7e58bMauro Carvalho Chehab } else 117596d92d5128d308b5a79f21c3e72c87f5fc7e58bMauro Carvalho Chehab return (ret < 0) ? ret : -EFAULT; 118596d92d5128d308b5a79f21c3e72c87f5fc7e58bMauro Carvalho Chehab } 119596d92d5128d308b5a79f21c3e72c87f5fc7e58bMauro Carvalho Chehab return wrcount; 120596d92d5128d308b5a79f21c3e72c87f5fc7e58bMauro Carvalho Chehab} 121596d92d5128d308b5a79f21c3e72c87f5fc7e58bMauro Carvalho Chehab 122596d92d5128d308b5a79f21c3e72c87f5fc7e58bMauro Carvalho Chehab/* 123596d92d5128d308b5a79f21c3e72c87f5fc7e58bMauro Carvalho Chehab * em2800_i2c_check_for_device() 124596d92d5128d308b5a79f21c3e72c87f5fc7e58bMauro Carvalho Chehab * check if there is a i2c_device at the supplied address 125596d92d5128d308b5a79f21c3e72c87f5fc7e58bMauro Carvalho Chehab */ 1263acf28095009509c9ca1e283de821b5be9ddede6Mauro Carvalho Chehabstatic int em2800_i2c_check_for_device(struct em28xx *dev, unsigned char addr) 127596d92d5128d308b5a79f21c3e72c87f5fc7e58bMauro Carvalho Chehab{ 128596d92d5128d308b5a79f21c3e72c87f5fc7e58bMauro Carvalho Chehab char msg; 129596d92d5128d308b5a79f21c3e72c87f5fc7e58bMauro Carvalho Chehab int ret; 130596d92d5128d308b5a79f21c3e72c87f5fc7e58bMauro Carvalho Chehab int write_timeout; 131596d92d5128d308b5a79f21c3e72c87f5fc7e58bMauro Carvalho Chehab msg = addr; 1323acf28095009509c9ca1e283de821b5be9ddede6Mauro Carvalho Chehab ret = dev->em28xx_write_regs(dev, 0x04, &msg, 1); 133596d92d5128d308b5a79f21c3e72c87f5fc7e58bMauro Carvalho Chehab if (ret < 0) { 1343acf28095009509c9ca1e283de821b5be9ddede6Mauro Carvalho Chehab em28xx_warn("setting i2c device address failed (error=%i)\n", 135596d92d5128d308b5a79f21c3e72c87f5fc7e58bMauro Carvalho Chehab ret); 136596d92d5128d308b5a79f21c3e72c87f5fc7e58bMauro Carvalho Chehab return ret; 137596d92d5128d308b5a79f21c3e72c87f5fc7e58bMauro Carvalho Chehab } 138596d92d5128d308b5a79f21c3e72c87f5fc7e58bMauro Carvalho Chehab msg = 0x84; 1393acf28095009509c9ca1e283de821b5be9ddede6Mauro Carvalho Chehab ret = dev->em28xx_write_regs(dev, 0x05, &msg, 1); 140596d92d5128d308b5a79f21c3e72c87f5fc7e58bMauro Carvalho Chehab if (ret < 0) { 1413acf28095009509c9ca1e283de821b5be9ddede6Mauro Carvalho Chehab em28xx_warn("preparing i2c read failed (error=%i)\n", ret); 142596d92d5128d308b5a79f21c3e72c87f5fc7e58bMauro Carvalho Chehab return ret; 143596d92d5128d308b5a79f21c3e72c87f5fc7e58bMauro Carvalho Chehab } 144596d92d5128d308b5a79f21c3e72c87f5fc7e58bMauro Carvalho Chehab for (write_timeout = EM2800_I2C_WRITE_TIMEOUT; write_timeout > 0; 145596d92d5128d308b5a79f21c3e72c87f5fc7e58bMauro Carvalho Chehab write_timeout -= 5) { 146d45b9b8ab43c8973a9630ac54f4ede6c3e009f9eHans Verkuil unsigned reg = dev->em28xx_read_reg(dev, 0x5); 147d45b9b8ab43c8973a9630ac54f4ede6c3e009f9eHans Verkuil 148d45b9b8ab43c8973a9630ac54f4ede6c3e009f9eHans Verkuil if (reg == 0x94) 149596d92d5128d308b5a79f21c3e72c87f5fc7e58bMauro Carvalho Chehab return -ENODEV; 150d45b9b8ab43c8973a9630ac54f4ede6c3e009f9eHans Verkuil else if (reg == 0x84) 151596d92d5128d308b5a79f21c3e72c87f5fc7e58bMauro Carvalho Chehab return 0; 152e8e41da46dca6b33e990b48ee379503d25b4da65Markus Rechberger msleep(5); 153596d92d5128d308b5a79f21c3e72c87f5fc7e58bMauro Carvalho Chehab } 154596d92d5128d308b5a79f21c3e72c87f5fc7e58bMauro Carvalho Chehab return -ENODEV; 155596d92d5128d308b5a79f21c3e72c87f5fc7e58bMauro Carvalho Chehab} 156596d92d5128d308b5a79f21c3e72c87f5fc7e58bMauro Carvalho Chehab 157596d92d5128d308b5a79f21c3e72c87f5fc7e58bMauro Carvalho Chehab/* 158596d92d5128d308b5a79f21c3e72c87f5fc7e58bMauro Carvalho Chehab * em2800_i2c_recv_bytes() 159596d92d5128d308b5a79f21c3e72c87f5fc7e58bMauro Carvalho Chehab * read from the i2c device 160596d92d5128d308b5a79f21c3e72c87f5fc7e58bMauro Carvalho Chehab */ 1613acf28095009509c9ca1e283de821b5be9ddede6Mauro Carvalho Chehabstatic int em2800_i2c_recv_bytes(struct em28xx *dev, unsigned char addr, 162596d92d5128d308b5a79f21c3e72c87f5fc7e58bMauro Carvalho Chehab char *buf, int len) 163596d92d5128d308b5a79f21c3e72c87f5fc7e58bMauro Carvalho Chehab{ 164596d92d5128d308b5a79f21c3e72c87f5fc7e58bMauro Carvalho Chehab int ret; 165596d92d5128d308b5a79f21c3e72c87f5fc7e58bMauro Carvalho Chehab /* check for the device and set i2c read address */ 166596d92d5128d308b5a79f21c3e72c87f5fc7e58bMauro Carvalho Chehab ret = em2800_i2c_check_for_device(dev, addr); 167596d92d5128d308b5a79f21c3e72c87f5fc7e58bMauro Carvalho Chehab if (ret) { 1683acf28095009509c9ca1e283de821b5be9ddede6Mauro Carvalho Chehab em28xx_warn 169596d92d5128d308b5a79f21c3e72c87f5fc7e58bMauro Carvalho Chehab ("preparing read at i2c address 0x%x failed (error=%i)\n", 170596d92d5128d308b5a79f21c3e72c87f5fc7e58bMauro Carvalho Chehab addr, ret); 171596d92d5128d308b5a79f21c3e72c87f5fc7e58bMauro Carvalho Chehab return ret; 172596d92d5128d308b5a79f21c3e72c87f5fc7e58bMauro Carvalho Chehab } 1733acf28095009509c9ca1e283de821b5be9ddede6Mauro Carvalho Chehab ret = dev->em28xx_read_reg_req_len(dev, 0x0, 0x3, buf, len); 174596d92d5128d308b5a79f21c3e72c87f5fc7e58bMauro Carvalho Chehab if (ret < 0) { 1753acf28095009509c9ca1e283de821b5be9ddede6Mauro Carvalho Chehab em28xx_warn("reading from i2c device at 0x%x failed (error=%i)", 176596d92d5128d308b5a79f21c3e72c87f5fc7e58bMauro Carvalho Chehab addr, ret); 177596d92d5128d308b5a79f21c3e72c87f5fc7e58bMauro Carvalho Chehab return ret; 178596d92d5128d308b5a79f21c3e72c87f5fc7e58bMauro Carvalho Chehab } 179596d92d5128d308b5a79f21c3e72c87f5fc7e58bMauro Carvalho Chehab return ret; 180596d92d5128d308b5a79f21c3e72c87f5fc7e58bMauro Carvalho Chehab} 181596d92d5128d308b5a79f21c3e72c87f5fc7e58bMauro Carvalho Chehab 182596d92d5128d308b5a79f21c3e72c87f5fc7e58bMauro Carvalho Chehab/* 1833acf28095009509c9ca1e283de821b5be9ddede6Mauro Carvalho Chehab * em28xx_i2c_send_bytes() 184a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton */ 1853acf28095009509c9ca1e283de821b5be9ddede6Mauro Carvalho Chehabstatic int em28xx_i2c_send_bytes(void *data, unsigned char addr, char *buf, 186596d92d5128d308b5a79f21c3e72c87f5fc7e58bMauro Carvalho Chehab short len, int stop) 187a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton{ 188a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton int wrcount = 0; 1893acf28095009509c9ca1e283de821b5be9ddede6Mauro Carvalho Chehab struct em28xx *dev = (struct em28xx *)data; 190bbc70e647b04dc3df1c879089a4f6b633c1952c9Mauro Carvalho Chehab int write_timeout, ret; 191a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton 1923acf28095009509c9ca1e283de821b5be9ddede6Mauro Carvalho Chehab wrcount = dev->em28xx_write_regs_req(dev, stop ? 2 : 3, addr, buf, len); 193a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton 194bbc70e647b04dc3df1c879089a4f6b633c1952c9Mauro Carvalho Chehab /* Seems to be required after a write */ 195bbc70e647b04dc3df1c879089a4f6b633c1952c9Mauro Carvalho Chehab for (write_timeout = EM2800_I2C_WRITE_TIMEOUT; write_timeout > 0; 196bbc70e647b04dc3df1c879089a4f6b633c1952c9Mauro Carvalho Chehab write_timeout -= 5) { 197bbc70e647b04dc3df1c879089a4f6b633c1952c9Mauro Carvalho Chehab ret = dev->em28xx_read_reg(dev, 0x05); 198bbc70e647b04dc3df1c879089a4f6b633c1952c9Mauro Carvalho Chehab if (!ret) 199bbc70e647b04dc3df1c879089a4f6b633c1952c9Mauro Carvalho Chehab break; 200bbc70e647b04dc3df1c879089a4f6b633c1952c9Mauro Carvalho Chehab msleep(5); 201bbc70e647b04dc3df1c879089a4f6b633c1952c9Mauro Carvalho Chehab } 202bbc70e647b04dc3df1c879089a4f6b633c1952c9Mauro Carvalho Chehab 203a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton return wrcount; 204a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton} 205a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton 206a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton/* 2073acf28095009509c9ca1e283de821b5be9ddede6Mauro Carvalho Chehab * em28xx_i2c_recv_bytes() 208a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton * read a byte from the i2c device 209a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton */ 2103acf28095009509c9ca1e283de821b5be9ddede6Mauro Carvalho Chehabstatic int em28xx_i2c_recv_bytes(struct em28xx *dev, unsigned char addr, 211596d92d5128d308b5a79f21c3e72c87f5fc7e58bMauro Carvalho Chehab char *buf, int len) 212a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton{ 213a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton int ret; 2143acf28095009509c9ca1e283de821b5be9ddede6Mauro Carvalho Chehab ret = dev->em28xx_read_reg_req_len(dev, 2, addr, buf, len); 215a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton if (ret < 0) { 2163acf28095009509c9ca1e283de821b5be9ddede6Mauro Carvalho Chehab em28xx_warn("reading i2c device failed (error=%i)\n", ret); 217a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton return ret; 218a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton } 2193acf28095009509c9ca1e283de821b5be9ddede6Mauro Carvalho Chehab if (dev->em28xx_read_reg(dev, 0x5) != 0) 220a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton return -ENODEV; 221a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton return ret; 222a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton} 223a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton 224a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton/* 2253acf28095009509c9ca1e283de821b5be9ddede6Mauro Carvalho Chehab * em28xx_i2c_check_for_device() 226a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton * check if there is a i2c_device at the supplied address 227a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton */ 2283acf28095009509c9ca1e283de821b5be9ddede6Mauro Carvalho Chehabstatic int em28xx_i2c_check_for_device(struct em28xx *dev, unsigned char addr) 229a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton{ 230a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton int ret; 231a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton 2323acf28095009509c9ca1e283de821b5be9ddede6Mauro Carvalho Chehab ret = dev->em28xx_read_reg_req(dev, 2, addr); 233a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton if (ret < 0) { 2343acf28095009509c9ca1e283de821b5be9ddede6Mauro Carvalho Chehab em28xx_warn("reading from i2c device failed (error=%i)\n", ret); 235a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton return ret; 236a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton } 2373acf28095009509c9ca1e283de821b5be9ddede6Mauro Carvalho Chehab if (dev->em28xx_read_reg(dev, 0x5) != 0) 238a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton return -ENODEV; 239a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton return 0; 240a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton} 241a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton 242a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton/* 2433acf28095009509c9ca1e283de821b5be9ddede6Mauro Carvalho Chehab * em28xx_i2c_xfer() 244a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton * the main i2c transfer function 245a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton */ 2463acf28095009509c9ca1e283de821b5be9ddede6Mauro Carvalho Chehabstatic int em28xx_i2c_xfer(struct i2c_adapter *i2c_adap, 247a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton struct i2c_msg msgs[], int num) 248a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton{ 2493acf28095009509c9ca1e283de821b5be9ddede6Mauro Carvalho Chehab struct em28xx *dev = i2c_adap->algo_data; 250a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton int addr, rc, i, byte; 251a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton 252a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton if (num <= 0) 253a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton return 0; 254a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton for (i = 0; i < num; i++) { 255a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton addr = msgs[i].addr << 1; 2566ea54d938b6f81baa0952a8b15d3e67e6c268b8fDouglas Schilling Landgraf dprintk2(2, "%s %s addr=%x len=%d:", 257a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton (msgs[i].flags & I2C_M_RD) ? "read" : "write", 258a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton i == num - 1 ? "stop" : "nonstop", addr, msgs[i].len); 2596ea54d938b6f81baa0952a8b15d3e67e6c268b8fDouglas Schilling Landgraf if (!msgs[i].len) { /* no len: check only for device presence */ 260505b6d0b774fa4475fedbd3cebf95199c17a0086Mauro Carvalho Chehab if (dev->board.is_em2800) 261596d92d5128d308b5a79f21c3e72c87f5fc7e58bMauro Carvalho Chehab rc = em2800_i2c_check_for_device(dev, addr); 262596d92d5128d308b5a79f21c3e72c87f5fc7e58bMauro Carvalho Chehab else 2633acf28095009509c9ca1e283de821b5be9ddede6Mauro Carvalho Chehab rc = em28xx_i2c_check_for_device(dev, addr); 264a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton if (rc < 0) { 2656ea54d938b6f81baa0952a8b15d3e67e6c268b8fDouglas Schilling Landgraf dprintk2(2, " no device\n"); 266a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton return rc; 267a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton } 268a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton 269596d92d5128d308b5a79f21c3e72c87f5fc7e58bMauro Carvalho Chehab } else if (msgs[i].flags & I2C_M_RD) { 270a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton /* read bytes */ 271505b6d0b774fa4475fedbd3cebf95199c17a0086Mauro Carvalho Chehab if (dev->board.is_em2800) 272596d92d5128d308b5a79f21c3e72c87f5fc7e58bMauro Carvalho Chehab rc = em2800_i2c_recv_bytes(dev, addr, 273596d92d5128d308b5a79f21c3e72c87f5fc7e58bMauro Carvalho Chehab msgs[i].buf, 274596d92d5128d308b5a79f21c3e72c87f5fc7e58bMauro Carvalho Chehab msgs[i].len); 275596d92d5128d308b5a79f21c3e72c87f5fc7e58bMauro Carvalho Chehab else 2763acf28095009509c9ca1e283de821b5be9ddede6Mauro Carvalho Chehab rc = em28xx_i2c_recv_bytes(dev, addr, 277596d92d5128d308b5a79f21c3e72c87f5fc7e58bMauro Carvalho Chehab msgs[i].buf, 278596d92d5128d308b5a79f21c3e72c87f5fc7e58bMauro Carvalho Chehab msgs[i].len); 2796ea54d938b6f81baa0952a8b15d3e67e6c268b8fDouglas Schilling Landgraf if (i2c_debug >= 2) { 2806ea54d938b6f81baa0952a8b15d3e67e6c268b8fDouglas Schilling Landgraf for (byte = 0; byte < msgs[i].len; byte++) 281a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton printk(" %02x", msgs[i].buf[byte]); 282a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton } 283a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton } else { 284a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton /* write bytes */ 2856ea54d938b6f81baa0952a8b15d3e67e6c268b8fDouglas Schilling Landgraf if (i2c_debug >= 2) { 286a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton for (byte = 0; byte < msgs[i].len; byte++) 287a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton printk(" %02x", msgs[i].buf[byte]); 288a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton } 289505b6d0b774fa4475fedbd3cebf95199c17a0086Mauro Carvalho Chehab if (dev->board.is_em2800) 290596d92d5128d308b5a79f21c3e72c87f5fc7e58bMauro Carvalho Chehab rc = em2800_i2c_send_bytes(dev, addr, 291596d92d5128d308b5a79f21c3e72c87f5fc7e58bMauro Carvalho Chehab msgs[i].buf, 292596d92d5128d308b5a79f21c3e72c87f5fc7e58bMauro Carvalho Chehab msgs[i].len); 293596d92d5128d308b5a79f21c3e72c87f5fc7e58bMauro Carvalho Chehab else 2943acf28095009509c9ca1e283de821b5be9ddede6Mauro Carvalho Chehab rc = em28xx_i2c_send_bytes(dev, addr, 295596d92d5128d308b5a79f21c3e72c87f5fc7e58bMauro Carvalho Chehab msgs[i].buf, 296596d92d5128d308b5a79f21c3e72c87f5fc7e58bMauro Carvalho Chehab msgs[i].len, 297596d92d5128d308b5a79f21c3e72c87f5fc7e58bMauro Carvalho Chehab i == num - 1); 298a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton } 299e8e41da46dca6b33e990b48ee379503d25b4da65Markus Rechberger if (rc < 0) 300e8e41da46dca6b33e990b48ee379503d25b4da65Markus Rechberger goto err; 3016ea54d938b6f81baa0952a8b15d3e67e6c268b8fDouglas Schilling Landgraf if (i2c_debug >= 2) 302a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton printk("\n"); 303a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton } 304a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton 305a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton return num; 3066ea54d938b6f81baa0952a8b15d3e67e6c268b8fDouglas Schilling Landgraferr: 3076ea54d938b6f81baa0952a8b15d3e67e6c268b8fDouglas Schilling Landgraf dprintk2(2, " ERROR: %i\n", rc); 308a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton return rc; 309a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton} 310a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton 31103910cc39035d27f4c85c8ad2a236cc5c9456127Mauro Carvalho Chehab/* based on linux/sunrpc/svcauth.h and linux/hash.h 31203910cc39035d27f4c85c8ad2a236cc5c9456127Mauro Carvalho Chehab * The original hash function returns a different value, if arch is x86_64 31303910cc39035d27f4c85c8ad2a236cc5c9456127Mauro Carvalho Chehab * or i386. 31403910cc39035d27f4c85c8ad2a236cc5c9456127Mauro Carvalho Chehab */ 31503910cc39035d27f4c85c8ad2a236cc5c9456127Mauro Carvalho Chehabstatic inline unsigned long em28xx_hash_mem(char *buf, int length, int bits) 31603910cc39035d27f4c85c8ad2a236cc5c9456127Mauro Carvalho Chehab{ 31703910cc39035d27f4c85c8ad2a236cc5c9456127Mauro Carvalho Chehab unsigned long hash = 0; 31803910cc39035d27f4c85c8ad2a236cc5c9456127Mauro Carvalho Chehab unsigned long l = 0; 31903910cc39035d27f4c85c8ad2a236cc5c9456127Mauro Carvalho Chehab int len = 0; 32003910cc39035d27f4c85c8ad2a236cc5c9456127Mauro Carvalho Chehab unsigned char c; 32103910cc39035d27f4c85c8ad2a236cc5c9456127Mauro Carvalho Chehab do { 32203910cc39035d27f4c85c8ad2a236cc5c9456127Mauro Carvalho Chehab if (len == length) { 32303910cc39035d27f4c85c8ad2a236cc5c9456127Mauro Carvalho Chehab c = (char)len; 32403910cc39035d27f4c85c8ad2a236cc5c9456127Mauro Carvalho Chehab len = -1; 32503910cc39035d27f4c85c8ad2a236cc5c9456127Mauro Carvalho Chehab } else 32603910cc39035d27f4c85c8ad2a236cc5c9456127Mauro Carvalho Chehab c = *buf++; 32703910cc39035d27f4c85c8ad2a236cc5c9456127Mauro Carvalho Chehab l = (l << 8) | c; 32803910cc39035d27f4c85c8ad2a236cc5c9456127Mauro Carvalho Chehab len++; 32903910cc39035d27f4c85c8ad2a236cc5c9456127Mauro Carvalho Chehab if ((len & (32 / 8 - 1)) == 0) 33003910cc39035d27f4c85c8ad2a236cc5c9456127Mauro Carvalho Chehab hash = ((hash^l) * 0x9e370001UL); 33103910cc39035d27f4c85c8ad2a236cc5c9456127Mauro Carvalho Chehab } while (len); 33203910cc39035d27f4c85c8ad2a236cc5c9456127Mauro Carvalho Chehab 33303910cc39035d27f4c85c8ad2a236cc5c9456127Mauro Carvalho Chehab return (hash >> (32 - bits)) & 0xffffffffUL; 33403910cc39035d27f4c85c8ad2a236cc5c9456127Mauro Carvalho Chehab} 33503910cc39035d27f4c85c8ad2a236cc5c9456127Mauro Carvalho Chehab 3363acf28095009509c9ca1e283de821b5be9ddede6Mauro Carvalho Chehabstatic int em28xx_i2c_eeprom(struct em28xx *dev, unsigned char *eedata, int len) 337a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton{ 338a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton unsigned char buf, *p = eedata; 3393acf28095009509c9ca1e283de821b5be9ddede6Mauro Carvalho Chehab struct em28xx_eeprom *em_eeprom = (void *)eedata; 340a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton int i, err, size = len, block; 341a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton 342fec528b77f9be3e7ebb8d7c25888b0cf9fb8e8d6Mauro Carvalho Chehab if (dev->chip_id == CHIP_ID_EM2874 || 343fec528b77f9be3e7ebb8d7c25888b0cf9fb8e8d6Mauro Carvalho Chehab dev->chip_id == CHIP_ID_EM28174 || 344fec528b77f9be3e7ebb8d7c25888b0cf9fb8e8d6Mauro Carvalho Chehab dev->chip_id == CHIP_ID_EM2884) { 345a527c9f827517a14b869511a954910d973556c8cDevin Heitmueller /* Empia switched to a 16-bit addressable eeprom in newer 346a527c9f827517a14b869511a954910d973556c8cDevin Heitmueller devices. While we could certainly write a routine to read 347a527c9f827517a14b869511a954910d973556c8cDevin Heitmueller the eeprom, there is nothing of use in there that cannot be 348a527c9f827517a14b869511a954910d973556c8cDevin Heitmueller accessed through registers, and there is the risk that we 349a527c9f827517a14b869511a954910d973556c8cDevin Heitmueller could corrupt the eeprom (since a 16-bit read call is 350a527c9f827517a14b869511a954910d973556c8cDevin Heitmueller interpreted as a write call by 8-bit eeproms). 351a527c9f827517a14b869511a954910d973556c8cDevin Heitmueller */ 352a527c9f827517a14b869511a954910d973556c8cDevin Heitmueller return 0; 353a527c9f827517a14b869511a954910d973556c8cDevin Heitmueller } 354a527c9f827517a14b869511a954910d973556c8cDevin Heitmueller 355a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton dev->i2c_client.addr = 0xa0 >> 1; 356596d92d5128d308b5a79f21c3e72c87f5fc7e58bMauro Carvalho Chehab 357596d92d5128d308b5a79f21c3e72c87f5fc7e58bMauro Carvalho Chehab /* Check if board has eeprom */ 358596d92d5128d308b5a79f21c3e72c87f5fc7e58bMauro Carvalho Chehab err = i2c_master_recv(&dev->i2c_client, &buf, 0); 359f2a01a0027b29f682c3833d582e2827a4690f661Douglas Schilling Landgraf if (err < 0) { 360c41109fc9a13c6af0e4069dd92fdb4c5c8046649Mauro Carvalho Chehab em28xx_errdev("board has no eeprom\n"); 361c41109fc9a13c6af0e4069dd92fdb4c5c8046649Mauro Carvalho Chehab memset(eedata, 0, len); 362c41109fc9a13c6af0e4069dd92fdb4c5c8046649Mauro Carvalho Chehab return -ENODEV; 363f2a01a0027b29f682c3833d582e2827a4690f661Douglas Schilling Landgraf } 364596d92d5128d308b5a79f21c3e72c87f5fc7e58bMauro Carvalho Chehab 365a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton buf = 0; 3666ea54d938b6f81baa0952a8b15d3e67e6c268b8fDouglas Schilling Landgraf 3676ea54d938b6f81baa0952a8b15d3e67e6c268b8fDouglas Schilling Landgraf err = i2c_master_send(&dev->i2c_client, &buf, 1); 3686ea54d938b6f81baa0952a8b15d3e67e6c268b8fDouglas Schilling Landgraf if (err != 1) { 369a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton printk(KERN_INFO "%s: Huh, no eeprom present (err=%d)?\n", 370a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton dev->name, err); 371f2a01a0027b29f682c3833d582e2827a4690f661Douglas Schilling Landgraf return err; 372a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton } 373a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton while (size > 0) { 374a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton if (size > 16) 375a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton block = 16; 376a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton else 377a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton block = size; 378a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton 379a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton if (block != 380a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton (err = i2c_master_recv(&dev->i2c_client, p, block))) { 381a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton printk(KERN_WARNING 382a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton "%s: i2c eeprom read error (err=%d)\n", 383a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton dev->name, err); 384f2a01a0027b29f682c3833d582e2827a4690f661Douglas Schilling Landgraf return err; 385a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton } 386a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton size -= block; 387a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton p += block; 388a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton } 389a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton for (i = 0; i < len; i++) { 390a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton if (0 == (i % 16)) 391a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton printk(KERN_INFO "%s: i2c eeprom %02x:", dev->name, i); 392a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton printk(" %02x", eedata[i]); 393a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton if (15 == (i % 16)) 394a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton printk("\n"); 395a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton } 396a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton 39703910cc39035d27f4c85c8ad2a236cc5c9456127Mauro Carvalho Chehab if (em_eeprom->id == 0x9567eb1a) 39803910cc39035d27f4c85c8ad2a236cc5c9456127Mauro Carvalho Chehab dev->hash = em28xx_hash_mem(eedata, len, 32); 39903910cc39035d27f4c85c8ad2a236cc5c9456127Mauro Carvalho Chehab 4001bee0184f6ffba1263a4b1e5732cde2c5292d843Mauro Carvalho Chehab printk(KERN_INFO "%s: EEPROM ID= 0x%08x, EEPROM hash = 0x%08lx\n", 4011bee0184f6ffba1263a4b1e5732cde2c5292d843Mauro Carvalho Chehab dev->name, em_eeprom->id, dev->hash); 4021bee0184f6ffba1263a4b1e5732cde2c5292d843Mauro Carvalho Chehab 4031bee0184f6ffba1263a4b1e5732cde2c5292d843Mauro Carvalho Chehab printk(KERN_INFO "%s: EEPROM info:\n", dev->name); 404a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton 405a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton switch (em_eeprom->chip_conf >> 4 & 0x3) { 406a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton case 0: 4071bee0184f6ffba1263a4b1e5732cde2c5292d843Mauro Carvalho Chehab printk(KERN_INFO "%s:\tNo audio on board.\n", dev->name); 408a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton break; 409a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton case 1: 4101bee0184f6ffba1263a4b1e5732cde2c5292d843Mauro Carvalho Chehab printk(KERN_INFO "%s:\tAC97 audio (5 sample rates)\n", 4111bee0184f6ffba1263a4b1e5732cde2c5292d843Mauro Carvalho Chehab dev->name); 412a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton break; 413a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton case 2: 414a1a6ee74f2c68918f2e145dccba3637eea91a52aNicola Soranzo printk(KERN_INFO "%s:\tI2S audio, sample rate=32k\n", 415a1a6ee74f2c68918f2e145dccba3637eea91a52aNicola Soranzo dev->name); 416a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton break; 417a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton case 3: 418a1a6ee74f2c68918f2e145dccba3637eea91a52aNicola Soranzo printk(KERN_INFO "%s:\tI2S audio, 3 sample rates\n", 419a1a6ee74f2c68918f2e145dccba3637eea91a52aNicola Soranzo dev->name); 420a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton break; 421a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton } 422a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton 423a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton if (em_eeprom->chip_conf & 1 << 3) 4241bee0184f6ffba1263a4b1e5732cde2c5292d843Mauro Carvalho Chehab printk(KERN_INFO "%s:\tUSB Remote wakeup capable\n", dev->name); 425a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton 426a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton if (em_eeprom->chip_conf & 1 << 2) 4271bee0184f6ffba1263a4b1e5732cde2c5292d843Mauro Carvalho Chehab printk(KERN_INFO "%s:\tUSB Self power capable\n", dev->name); 428a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton 429a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton switch (em_eeprom->chip_conf & 0x3) { 430a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton case 0: 4311bee0184f6ffba1263a4b1e5732cde2c5292d843Mauro Carvalho Chehab printk(KERN_INFO "%s:\t500mA max power\n", dev->name); 432a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton break; 433a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton case 1: 4341bee0184f6ffba1263a4b1e5732cde2c5292d843Mauro Carvalho Chehab printk(KERN_INFO "%s:\t400mA max power\n", dev->name); 435a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton break; 436a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton case 2: 4371bee0184f6ffba1263a4b1e5732cde2c5292d843Mauro Carvalho Chehab printk(KERN_INFO "%s:\t300mA max power\n", dev->name); 438a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton break; 439a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton case 3: 4401bee0184f6ffba1263a4b1e5732cde2c5292d843Mauro Carvalho Chehab printk(KERN_INFO "%s:\t200mA max power\n", dev->name); 441a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton break; 442a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton } 4431bee0184f6ffba1263a4b1e5732cde2c5292d843Mauro Carvalho Chehab printk(KERN_INFO "%s:\tTable at 0x%02x, strings=0x%04x, 0x%04x, 0x%04x\n", 4441bee0184f6ffba1263a4b1e5732cde2c5292d843Mauro Carvalho Chehab dev->name, 4456ea54d938b6f81baa0952a8b15d3e67e6c268b8fDouglas Schilling Landgraf em_eeprom->string_idx_table, 4466ea54d938b6f81baa0952a8b15d3e67e6c268b8fDouglas Schilling Landgraf em_eeprom->string1, 4476ea54d938b6f81baa0952a8b15d3e67e6c268b8fDouglas Schilling Landgraf em_eeprom->string2, 4486ea54d938b6f81baa0952a8b15d3e67e6c268b8fDouglas Schilling Landgraf em_eeprom->string3); 449a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton 450a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton return 0; 451a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton} 452a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton 453a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton/* ----------------------------------------------------------- */ 454a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton 455a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton/* 456a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton * functionality() 457a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton */ 458a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Mortonstatic u32 functionality(struct i2c_adapter *adap) 459a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton{ 460a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton return I2C_FUNC_SMBUS_EMUL; 461a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton} 462a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton 4633acf28095009509c9ca1e283de821b5be9ddede6Mauro Carvalho Chehabstatic struct i2c_algorithm em28xx_algo = { 4643acf28095009509c9ca1e283de821b5be9ddede6Mauro Carvalho Chehab .master_xfer = em28xx_i2c_xfer, 465a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton .functionality = functionality, 466a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton}; 467a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton 4683acf28095009509c9ca1e283de821b5be9ddede6Mauro Carvalho Chehabstatic struct i2c_adapter em28xx_adap_template = { 469a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton .owner = THIS_MODULE, 4703acf28095009509c9ca1e283de821b5be9ddede6Mauro Carvalho Chehab .name = "em28xx", 4713acf28095009509c9ca1e283de821b5be9ddede6Mauro Carvalho Chehab .algo = &em28xx_algo, 472a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton}; 473a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton 4743acf28095009509c9ca1e283de821b5be9ddede6Mauro Carvalho Chehabstatic struct i2c_client em28xx_client_template = { 4753acf28095009509c9ca1e283de821b5be9ddede6Mauro Carvalho Chehab .name = "em28xx internal", 476a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton}; 477a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton 478a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton/* ----------------------------------------------------------- */ 479a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton 480a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton/* 481a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton * i2c_devs 482a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton * incomplete list of known devices 483a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton */ 484a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Mortonstatic char *i2c_devs[128] = { 485a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton [0x4a >> 1] = "saa7113h", 486a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton [0x60 >> 1] = "remote IR sensor", 487da45a2a5b96afd7188c058a55eb2917d6524c0cfMarkus Rechberger [0x8e >> 1] = "remote IR sensor", 488a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton [0x86 >> 1] = "tda9887", 489a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton [0x80 >> 1] = "msp34xx", 490a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton [0x88 >> 1] = "msp34xx", 491a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton [0xa0 >> 1] = "eeprom", 4922bd1d9eb1c27034a77c8e1887156da72d6160ae1Vitaly Wool [0xb0 >> 1] = "tda9874", 493a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton [0xb8 >> 1] = "tvp5150a", 494791a08fc01aaa293a73c9dce260327fdee288fafMauro Carvalho Chehab [0xba >> 1] = "webcam sensor or tvp5150a", 495a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton [0xc0 >> 1] = "tuner (analog)", 496a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton [0xc2 >> 1] = "tuner (analog)", 497a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton [0xc4 >> 1] = "tuner (analog)", 498a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton [0xc6 >> 1] = "tuner (analog)", 499a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton}; 500a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton 501a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton/* 502a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton * do_i2c_scan() 503a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton * check i2c address range for devices 504a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton */ 505fad7b958e753e18ff443786360f7846da50a3085Sascha Sommervoid em28xx_do_i2c_scan(struct em28xx *dev) 506a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton{ 507fad7b958e753e18ff443786360f7846da50a3085Sascha Sommer u8 i2c_devicelist[128]; 508a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton unsigned char buf; 509a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton int i, rc; 510a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton 511fad7b958e753e18ff443786360f7846da50a3085Sascha Sommer memset(i2c_devicelist, 0, ARRAY_SIZE(i2c_devicelist)); 512fad7b958e753e18ff443786360f7846da50a3085Sascha Sommer 51353c4e9551c2930767fcdaa54323616c32ed6e9c6Mauro Carvalho Chehab for (i = 0; i < ARRAY_SIZE(i2c_devs); i++) { 514fad7b958e753e18ff443786360f7846da50a3085Sascha Sommer dev->i2c_client.addr = i; 515fad7b958e753e18ff443786360f7846da50a3085Sascha Sommer rc = i2c_master_recv(&dev->i2c_client, &buf, 0); 516a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton if (rc < 0) 517a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton continue; 518fad7b958e753e18ff443786360f7846da50a3085Sascha Sommer i2c_devicelist[i] = i; 519fad7b958e753e18ff443786360f7846da50a3085Sascha Sommer printk(KERN_INFO "%s: found i2c device @ 0x%x [%s]\n", 520fad7b958e753e18ff443786360f7846da50a3085Sascha Sommer dev->name, i << 1, i2c_devs[i] ? i2c_devs[i] : "???"); 521a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton } 522fad7b958e753e18ff443786360f7846da50a3085Sascha Sommer 523fad7b958e753e18ff443786360f7846da50a3085Sascha Sommer dev->i2c_hash = em28xx_hash_mem(i2c_devicelist, 524fad7b958e753e18ff443786360f7846da50a3085Sascha Sommer ARRAY_SIZE(i2c_devicelist), 32); 525a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton} 526a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton 527a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton/* 5283acf28095009509c9ca1e283de821b5be9ddede6Mauro Carvalho Chehab * em28xx_i2c_register() 529a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton * register i2c bus 530a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton */ 5313acf28095009509c9ca1e283de821b5be9ddede6Mauro Carvalho Chehabint em28xx_i2c_register(struct em28xx *dev) 532a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton{ 533f2a01a0027b29f682c3833d582e2827a4690f661Douglas Schilling Landgraf int retval; 534f2a01a0027b29f682c3833d582e2827a4690f661Douglas Schilling Landgraf 5353acf28095009509c9ca1e283de821b5be9ddede6Mauro Carvalho Chehab BUG_ON(!dev->em28xx_write_regs || !dev->em28xx_read_reg); 5363acf28095009509c9ca1e283de821b5be9ddede6Mauro Carvalho Chehab BUG_ON(!dev->em28xx_write_regs_req || !dev->em28xx_read_reg_req); 5373acf28095009509c9ca1e283de821b5be9ddede6Mauro Carvalho Chehab dev->i2c_adap = em28xx_adap_template; 538a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton dev->i2c_adap.dev.parent = &dev->udev->dev; 539a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton strcpy(dev->i2c_adap.name, dev->name); 540a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton dev->i2c_adap.algo_data = dev; 541f2cf250af156bef127433efd255abfae6aab02f6Douglas Schilling Landgraf i2c_set_adapdata(&dev->i2c_adap, &dev->v4l2_dev); 542f2a01a0027b29f682c3833d582e2827a4690f661Douglas Schilling Landgraf 543f2a01a0027b29f682c3833d582e2827a4690f661Douglas Schilling Landgraf retval = i2c_add_adapter(&dev->i2c_adap); 544f2a01a0027b29f682c3833d582e2827a4690f661Douglas Schilling Landgraf if (retval < 0) { 545f2a01a0027b29f682c3833d582e2827a4690f661Douglas Schilling Landgraf em28xx_errdev("%s: i2c_add_adapter failed! retval [%d]\n", 546f2a01a0027b29f682c3833d582e2827a4690f661Douglas Schilling Landgraf __func__, retval); 547f2a01a0027b29f682c3833d582e2827a4690f661Douglas Schilling Landgraf return retval; 548f2a01a0027b29f682c3833d582e2827a4690f661Douglas Schilling Landgraf } 549a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton 5503acf28095009509c9ca1e283de821b5be9ddede6Mauro Carvalho Chehab dev->i2c_client = em28xx_client_template; 551a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton dev->i2c_client.adapter = &dev->i2c_adap; 552a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton 553f2a01a0027b29f682c3833d582e2827a4690f661Douglas Schilling Landgraf retval = em28xx_i2c_eeprom(dev, dev->eedata, sizeof(dev->eedata)); 554c41109fc9a13c6af0e4069dd92fdb4c5c8046649Mauro Carvalho Chehab if ((retval < 0) && (retval != -ENODEV)) { 555f2a01a0027b29f682c3833d582e2827a4690f661Douglas Schilling Landgraf em28xx_errdev("%s: em28xx_i2_eeprom failed! retval [%d]\n", 556f2a01a0027b29f682c3833d582e2827a4690f661Douglas Schilling Landgraf __func__, retval); 557c41109fc9a13c6af0e4069dd92fdb4c5c8046649Mauro Carvalho Chehab 558f2a01a0027b29f682c3833d582e2827a4690f661Douglas Schilling Landgraf return retval; 559f2a01a0027b29f682c3833d582e2827a4690f661Douglas Schilling Landgraf } 560a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton 561a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton if (i2c_scan) 562fad7b958e753e18ff443786360f7846da50a3085Sascha Sommer em28xx_do_i2c_scan(dev); 563c41109fc9a13c6af0e4069dd92fdb4c5c8046649Mauro Carvalho Chehab 564c668f32dca105d876e51862a003a302fa61e4ae4Jean Delvare /* Instantiate the IR receiver device, if present */ 565c668f32dca105d876e51862a003a302fa61e4ae4Jean Delvare em28xx_register_i2c_ir(dev); 566c668f32dca105d876e51862a003a302fa61e4ae4Jean Delvare 567a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton return 0; 568a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton} 569a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton 570a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton/* 5713acf28095009509c9ca1e283de821b5be9ddede6Mauro Carvalho Chehab * em28xx_i2c_unregister() 572a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton * unregister i2c_bus 573a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton */ 5743acf28095009509c9ca1e283de821b5be9ddede6Mauro Carvalho Chehabint em28xx_i2c_unregister(struct em28xx *dev) 575a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton{ 576a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton i2c_del_adapter(&dev->i2c_adap); 577a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton return 0; 578a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton} 579