1*b285192aSMauro Carvalho Chehab /* 2*b285192aSMauro Carvalho Chehab * 3*b285192aSMauro Carvalho Chehab * device driver for philips saa7134 based TV cards 4*b285192aSMauro Carvalho Chehab * i2c interface support 5*b285192aSMauro Carvalho Chehab * 6*b285192aSMauro Carvalho Chehab * (c) 2001,02 Gerd Knorr <kraxel@bytesex.org> [SuSE Labs] 7*b285192aSMauro Carvalho Chehab * 8*b285192aSMauro Carvalho Chehab * This program is free software; you can redistribute it and/or modify 9*b285192aSMauro Carvalho Chehab * it under the terms of the GNU General Public License as published by 10*b285192aSMauro Carvalho Chehab * the Free Software Foundation; either version 2 of the License, or 11*b285192aSMauro Carvalho Chehab * (at your option) any later version. 12*b285192aSMauro Carvalho Chehab * 13*b285192aSMauro Carvalho Chehab * This program is distributed in the hope that it will be useful, 14*b285192aSMauro Carvalho Chehab * but WITHOUT ANY WARRANTY; without even the implied warranty of 15*b285192aSMauro Carvalho Chehab * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16*b285192aSMauro Carvalho Chehab * GNU General Public License for more details. 17*b285192aSMauro Carvalho Chehab * 18*b285192aSMauro Carvalho Chehab * You should have received a copy of the GNU General Public License 19*b285192aSMauro Carvalho Chehab * along with this program; if not, write to the Free Software 20*b285192aSMauro Carvalho Chehab * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 21*b285192aSMauro Carvalho Chehab */ 22*b285192aSMauro Carvalho Chehab 23*b285192aSMauro Carvalho Chehab #include <linux/init.h> 24*b285192aSMauro Carvalho Chehab #include <linux/list.h> 25*b285192aSMauro Carvalho Chehab #include <linux/module.h> 26*b285192aSMauro Carvalho Chehab #include <linux/kernel.h> 27*b285192aSMauro Carvalho Chehab #include <linux/delay.h> 28*b285192aSMauro Carvalho Chehab 29*b285192aSMauro Carvalho Chehab #include "saa7134-reg.h" 30*b285192aSMauro Carvalho Chehab #include "saa7134.h" 31*b285192aSMauro Carvalho Chehab #include <media/v4l2-common.h> 32*b285192aSMauro Carvalho Chehab 33*b285192aSMauro Carvalho Chehab /* ----------------------------------------------------------- */ 34*b285192aSMauro Carvalho Chehab 35*b285192aSMauro Carvalho Chehab static unsigned int i2c_debug; 36*b285192aSMauro Carvalho Chehab module_param(i2c_debug, int, 0644); 37*b285192aSMauro Carvalho Chehab MODULE_PARM_DESC(i2c_debug,"enable debug messages [i2c]"); 38*b285192aSMauro Carvalho Chehab 39*b285192aSMauro Carvalho Chehab static unsigned int i2c_scan; 40*b285192aSMauro Carvalho Chehab module_param(i2c_scan, int, 0444); 41*b285192aSMauro Carvalho Chehab MODULE_PARM_DESC(i2c_scan,"scan i2c bus at insmod time"); 42*b285192aSMauro Carvalho Chehab 43*b285192aSMauro Carvalho Chehab #define d1printk if (1 == i2c_debug) printk 44*b285192aSMauro Carvalho Chehab #define d2printk if (2 == i2c_debug) printk 45*b285192aSMauro Carvalho Chehab 46*b285192aSMauro Carvalho Chehab #define I2C_WAIT_DELAY 32 47*b285192aSMauro Carvalho Chehab #define I2C_WAIT_RETRY 16 48*b285192aSMauro Carvalho Chehab 49*b285192aSMauro Carvalho Chehab /* ----------------------------------------------------------- */ 50*b285192aSMauro Carvalho Chehab 51*b285192aSMauro Carvalho Chehab static char *str_i2c_status[] = { 52*b285192aSMauro Carvalho Chehab "IDLE", "DONE_STOP", "BUSY", "TO_SCL", "TO_ARB", "DONE_WRITE", 53*b285192aSMauro Carvalho Chehab "DONE_READ", "DONE_WRITE_TO", "DONE_READ_TO", "NO_DEVICE", 54*b285192aSMauro Carvalho Chehab "NO_ACKN", "BUS_ERR", "ARB_LOST", "SEQ_ERR", "ST_ERR", "SW_ERR" 55*b285192aSMauro Carvalho Chehab }; 56*b285192aSMauro Carvalho Chehab 57*b285192aSMauro Carvalho Chehab enum i2c_status { 58*b285192aSMauro Carvalho Chehab IDLE = 0, // no I2C command pending 59*b285192aSMauro Carvalho Chehab DONE_STOP = 1, // I2C command done and STOP executed 60*b285192aSMauro Carvalho Chehab BUSY = 2, // executing I2C command 61*b285192aSMauro Carvalho Chehab TO_SCL = 3, // executing I2C command, time out on clock stretching 62*b285192aSMauro Carvalho Chehab TO_ARB = 4, // time out on arbitration trial, still trying 63*b285192aSMauro Carvalho Chehab DONE_WRITE = 5, // I2C command done and awaiting next write command 64*b285192aSMauro Carvalho Chehab DONE_READ = 6, // I2C command done and awaiting next read command 65*b285192aSMauro Carvalho Chehab DONE_WRITE_TO = 7, // see 5, and time out on status echo 66*b285192aSMauro Carvalho Chehab DONE_READ_TO = 8, // see 6, and time out on status echo 67*b285192aSMauro Carvalho Chehab NO_DEVICE = 9, // no acknowledge on device slave address 68*b285192aSMauro Carvalho Chehab NO_ACKN = 10, // no acknowledge after data byte transfer 69*b285192aSMauro Carvalho Chehab BUS_ERR = 11, // bus error 70*b285192aSMauro Carvalho Chehab ARB_LOST = 12, // arbitration lost during transfer 71*b285192aSMauro Carvalho Chehab SEQ_ERR = 13, // erroneous programming sequence 72*b285192aSMauro Carvalho Chehab ST_ERR = 14, // wrong status echoing 73*b285192aSMauro Carvalho Chehab SW_ERR = 15 // software error 74*b285192aSMauro Carvalho Chehab }; 75*b285192aSMauro Carvalho Chehab 76*b285192aSMauro Carvalho Chehab static char *str_i2c_attr[] = { 77*b285192aSMauro Carvalho Chehab "NOP", "STOP", "CONTINUE", "START" 78*b285192aSMauro Carvalho Chehab }; 79*b285192aSMauro Carvalho Chehab 80*b285192aSMauro Carvalho Chehab enum i2c_attr { 81*b285192aSMauro Carvalho Chehab NOP = 0, // no operation on I2C bus 82*b285192aSMauro Carvalho Chehab STOP = 1, // stop condition, no associated byte transfer 83*b285192aSMauro Carvalho Chehab CONTINUE = 2, // continue with byte transfer 84*b285192aSMauro Carvalho Chehab START = 3 // start condition with byte transfer 85*b285192aSMauro Carvalho Chehab }; 86*b285192aSMauro Carvalho Chehab 87*b285192aSMauro Carvalho Chehab static inline enum i2c_status i2c_get_status(struct saa7134_dev *dev) 88*b285192aSMauro Carvalho Chehab { 89*b285192aSMauro Carvalho Chehab enum i2c_status status; 90*b285192aSMauro Carvalho Chehab 91*b285192aSMauro Carvalho Chehab status = saa_readb(SAA7134_I2C_ATTR_STATUS) & 0x0f; 92*b285192aSMauro Carvalho Chehab d2printk(KERN_DEBUG "%s: i2c stat <= %s\n",dev->name, 93*b285192aSMauro Carvalho Chehab str_i2c_status[status]); 94*b285192aSMauro Carvalho Chehab return status; 95*b285192aSMauro Carvalho Chehab } 96*b285192aSMauro Carvalho Chehab 97*b285192aSMauro Carvalho Chehab static inline void i2c_set_status(struct saa7134_dev *dev, 98*b285192aSMauro Carvalho Chehab enum i2c_status status) 99*b285192aSMauro Carvalho Chehab { 100*b285192aSMauro Carvalho Chehab d2printk(KERN_DEBUG "%s: i2c stat => %s\n",dev->name, 101*b285192aSMauro Carvalho Chehab str_i2c_status[status]); 102*b285192aSMauro Carvalho Chehab saa_andorb(SAA7134_I2C_ATTR_STATUS,0x0f,status); 103*b285192aSMauro Carvalho Chehab } 104*b285192aSMauro Carvalho Chehab 105*b285192aSMauro Carvalho Chehab static inline void i2c_set_attr(struct saa7134_dev *dev, enum i2c_attr attr) 106*b285192aSMauro Carvalho Chehab { 107*b285192aSMauro Carvalho Chehab d2printk(KERN_DEBUG "%s: i2c attr => %s\n",dev->name, 108*b285192aSMauro Carvalho Chehab str_i2c_attr[attr]); 109*b285192aSMauro Carvalho Chehab saa_andorb(SAA7134_I2C_ATTR_STATUS,0xc0,attr << 6); 110*b285192aSMauro Carvalho Chehab } 111*b285192aSMauro Carvalho Chehab 112*b285192aSMauro Carvalho Chehab static inline int i2c_is_error(enum i2c_status status) 113*b285192aSMauro Carvalho Chehab { 114*b285192aSMauro Carvalho Chehab switch (status) { 115*b285192aSMauro Carvalho Chehab case NO_DEVICE: 116*b285192aSMauro Carvalho Chehab case NO_ACKN: 117*b285192aSMauro Carvalho Chehab case BUS_ERR: 118*b285192aSMauro Carvalho Chehab case ARB_LOST: 119*b285192aSMauro Carvalho Chehab case SEQ_ERR: 120*b285192aSMauro Carvalho Chehab case ST_ERR: 121*b285192aSMauro Carvalho Chehab return true; 122*b285192aSMauro Carvalho Chehab default: 123*b285192aSMauro Carvalho Chehab return false; 124*b285192aSMauro Carvalho Chehab } 125*b285192aSMauro Carvalho Chehab } 126*b285192aSMauro Carvalho Chehab 127*b285192aSMauro Carvalho Chehab static inline int i2c_is_idle(enum i2c_status status) 128*b285192aSMauro Carvalho Chehab { 129*b285192aSMauro Carvalho Chehab switch (status) { 130*b285192aSMauro Carvalho Chehab case IDLE: 131*b285192aSMauro Carvalho Chehab case DONE_STOP: 132*b285192aSMauro Carvalho Chehab return true; 133*b285192aSMauro Carvalho Chehab default: 134*b285192aSMauro Carvalho Chehab return false; 135*b285192aSMauro Carvalho Chehab } 136*b285192aSMauro Carvalho Chehab } 137*b285192aSMauro Carvalho Chehab 138*b285192aSMauro Carvalho Chehab static inline int i2c_is_busy(enum i2c_status status) 139*b285192aSMauro Carvalho Chehab { 140*b285192aSMauro Carvalho Chehab switch (status) { 141*b285192aSMauro Carvalho Chehab case BUSY: 142*b285192aSMauro Carvalho Chehab case TO_SCL: 143*b285192aSMauro Carvalho Chehab case TO_ARB: 144*b285192aSMauro Carvalho Chehab return true; 145*b285192aSMauro Carvalho Chehab default: 146*b285192aSMauro Carvalho Chehab return false; 147*b285192aSMauro Carvalho Chehab } 148*b285192aSMauro Carvalho Chehab } 149*b285192aSMauro Carvalho Chehab 150*b285192aSMauro Carvalho Chehab static int i2c_is_busy_wait(struct saa7134_dev *dev) 151*b285192aSMauro Carvalho Chehab { 152*b285192aSMauro Carvalho Chehab enum i2c_status status; 153*b285192aSMauro Carvalho Chehab int count; 154*b285192aSMauro Carvalho Chehab 155*b285192aSMauro Carvalho Chehab for (count = 0; count < I2C_WAIT_RETRY; count++) { 156*b285192aSMauro Carvalho Chehab status = i2c_get_status(dev); 157*b285192aSMauro Carvalho Chehab if (!i2c_is_busy(status)) 158*b285192aSMauro Carvalho Chehab break; 159*b285192aSMauro Carvalho Chehab saa_wait(I2C_WAIT_DELAY); 160*b285192aSMauro Carvalho Chehab } 161*b285192aSMauro Carvalho Chehab if (I2C_WAIT_RETRY == count) 162*b285192aSMauro Carvalho Chehab return false; 163*b285192aSMauro Carvalho Chehab return true; 164*b285192aSMauro Carvalho Chehab } 165*b285192aSMauro Carvalho Chehab 166*b285192aSMauro Carvalho Chehab static int i2c_reset(struct saa7134_dev *dev) 167*b285192aSMauro Carvalho Chehab { 168*b285192aSMauro Carvalho Chehab enum i2c_status status; 169*b285192aSMauro Carvalho Chehab int count; 170*b285192aSMauro Carvalho Chehab 171*b285192aSMauro Carvalho Chehab d2printk(KERN_DEBUG "%s: i2c reset\n",dev->name); 172*b285192aSMauro Carvalho Chehab status = i2c_get_status(dev); 173*b285192aSMauro Carvalho Chehab if (!i2c_is_error(status)) 174*b285192aSMauro Carvalho Chehab return true; 175*b285192aSMauro Carvalho Chehab i2c_set_status(dev,status); 176*b285192aSMauro Carvalho Chehab 177*b285192aSMauro Carvalho Chehab for (count = 0; count < I2C_WAIT_RETRY; count++) { 178*b285192aSMauro Carvalho Chehab status = i2c_get_status(dev); 179*b285192aSMauro Carvalho Chehab if (!i2c_is_error(status)) 180*b285192aSMauro Carvalho Chehab break; 181*b285192aSMauro Carvalho Chehab udelay(I2C_WAIT_DELAY); 182*b285192aSMauro Carvalho Chehab } 183*b285192aSMauro Carvalho Chehab if (I2C_WAIT_RETRY == count) 184*b285192aSMauro Carvalho Chehab return false; 185*b285192aSMauro Carvalho Chehab 186*b285192aSMauro Carvalho Chehab if (!i2c_is_idle(status)) 187*b285192aSMauro Carvalho Chehab return false; 188*b285192aSMauro Carvalho Chehab 189*b285192aSMauro Carvalho Chehab i2c_set_attr(dev,NOP); 190*b285192aSMauro Carvalho Chehab return true; 191*b285192aSMauro Carvalho Chehab } 192*b285192aSMauro Carvalho Chehab 193*b285192aSMauro Carvalho Chehab static inline int i2c_send_byte(struct saa7134_dev *dev, 194*b285192aSMauro Carvalho Chehab enum i2c_attr attr, 195*b285192aSMauro Carvalho Chehab unsigned char data) 196*b285192aSMauro Carvalho Chehab { 197*b285192aSMauro Carvalho Chehab enum i2c_status status; 198*b285192aSMauro Carvalho Chehab __u32 dword; 199*b285192aSMauro Carvalho Chehab 200*b285192aSMauro Carvalho Chehab /* have to write both attr + data in one 32bit word */ 201*b285192aSMauro Carvalho Chehab dword = saa_readl(SAA7134_I2C_ATTR_STATUS >> 2); 202*b285192aSMauro Carvalho Chehab dword &= 0x0f; 203*b285192aSMauro Carvalho Chehab dword |= (attr << 6); 204*b285192aSMauro Carvalho Chehab dword |= ((__u32)data << 8); 205*b285192aSMauro Carvalho Chehab dword |= 0x00 << 16; /* 100 kHz */ 206*b285192aSMauro Carvalho Chehab // dword |= 0x40 << 16; /* 400 kHz */ 207*b285192aSMauro Carvalho Chehab dword |= 0xf0 << 24; 208*b285192aSMauro Carvalho Chehab saa_writel(SAA7134_I2C_ATTR_STATUS >> 2, dword); 209*b285192aSMauro Carvalho Chehab d2printk(KERN_DEBUG "%s: i2c data => 0x%x\n",dev->name,data); 210*b285192aSMauro Carvalho Chehab 211*b285192aSMauro Carvalho Chehab if (!i2c_is_busy_wait(dev)) 212*b285192aSMauro Carvalho Chehab return -EIO; 213*b285192aSMauro Carvalho Chehab status = i2c_get_status(dev); 214*b285192aSMauro Carvalho Chehab if (i2c_is_error(status)) 215*b285192aSMauro Carvalho Chehab return -EIO; 216*b285192aSMauro Carvalho Chehab return 0; 217*b285192aSMauro Carvalho Chehab } 218*b285192aSMauro Carvalho Chehab 219*b285192aSMauro Carvalho Chehab static inline int i2c_recv_byte(struct saa7134_dev *dev) 220*b285192aSMauro Carvalho Chehab { 221*b285192aSMauro Carvalho Chehab enum i2c_status status; 222*b285192aSMauro Carvalho Chehab unsigned char data; 223*b285192aSMauro Carvalho Chehab 224*b285192aSMauro Carvalho Chehab i2c_set_attr(dev,CONTINUE); 225*b285192aSMauro Carvalho Chehab if (!i2c_is_busy_wait(dev)) 226*b285192aSMauro Carvalho Chehab return -EIO; 227*b285192aSMauro Carvalho Chehab status = i2c_get_status(dev); 228*b285192aSMauro Carvalho Chehab if (i2c_is_error(status)) 229*b285192aSMauro Carvalho Chehab return -EIO; 230*b285192aSMauro Carvalho Chehab data = saa_readb(SAA7134_I2C_DATA); 231*b285192aSMauro Carvalho Chehab d2printk(KERN_DEBUG "%s: i2c data <= 0x%x\n",dev->name,data); 232*b285192aSMauro Carvalho Chehab return data; 233*b285192aSMauro Carvalho Chehab } 234*b285192aSMauro Carvalho Chehab 235*b285192aSMauro Carvalho Chehab static int saa7134_i2c_xfer(struct i2c_adapter *i2c_adap, 236*b285192aSMauro Carvalho Chehab struct i2c_msg *msgs, int num) 237*b285192aSMauro Carvalho Chehab { 238*b285192aSMauro Carvalho Chehab struct saa7134_dev *dev = i2c_adap->algo_data; 239*b285192aSMauro Carvalho Chehab enum i2c_status status; 240*b285192aSMauro Carvalho Chehab unsigned char data; 241*b285192aSMauro Carvalho Chehab int addr,rc,i,byte; 242*b285192aSMauro Carvalho Chehab 243*b285192aSMauro Carvalho Chehab status = i2c_get_status(dev); 244*b285192aSMauro Carvalho Chehab if (!i2c_is_idle(status)) 245*b285192aSMauro Carvalho Chehab if (!i2c_reset(dev)) 246*b285192aSMauro Carvalho Chehab return -EIO; 247*b285192aSMauro Carvalho Chehab 248*b285192aSMauro Carvalho Chehab d2printk("start xfer\n"); 249*b285192aSMauro Carvalho Chehab d1printk(KERN_DEBUG "%s: i2c xfer:",dev->name); 250*b285192aSMauro Carvalho Chehab for (i = 0; i < num; i++) { 251*b285192aSMauro Carvalho Chehab if (!(msgs[i].flags & I2C_M_NOSTART) || 0 == i) { 252*b285192aSMauro Carvalho Chehab /* send address */ 253*b285192aSMauro Carvalho Chehab d2printk("send address\n"); 254*b285192aSMauro Carvalho Chehab addr = msgs[i].addr << 1; 255*b285192aSMauro Carvalho Chehab if (msgs[i].flags & I2C_M_RD) 256*b285192aSMauro Carvalho Chehab addr |= 1; 257*b285192aSMauro Carvalho Chehab if (i > 0 && msgs[i].flags & 258*b285192aSMauro Carvalho Chehab I2C_M_RD && msgs[i].addr != 0x40 && 259*b285192aSMauro Carvalho Chehab msgs[i].addr != 0x19) { 260*b285192aSMauro Carvalho Chehab /* workaround for a saa7134 i2c bug 261*b285192aSMauro Carvalho Chehab * needed to talk to the mt352 demux 262*b285192aSMauro Carvalho Chehab * thanks to pinnacle for the hint */ 263*b285192aSMauro Carvalho Chehab int quirk = 0xfe; 264*b285192aSMauro Carvalho Chehab d1printk(" [%02x quirk]",quirk); 265*b285192aSMauro Carvalho Chehab i2c_send_byte(dev,START,quirk); 266*b285192aSMauro Carvalho Chehab i2c_recv_byte(dev); 267*b285192aSMauro Carvalho Chehab } 268*b285192aSMauro Carvalho Chehab d1printk(" < %02x", addr); 269*b285192aSMauro Carvalho Chehab rc = i2c_send_byte(dev,START,addr); 270*b285192aSMauro Carvalho Chehab if (rc < 0) 271*b285192aSMauro Carvalho Chehab goto err; 272*b285192aSMauro Carvalho Chehab } 273*b285192aSMauro Carvalho Chehab if (msgs[i].flags & I2C_M_RD) { 274*b285192aSMauro Carvalho Chehab /* read bytes */ 275*b285192aSMauro Carvalho Chehab d2printk("read bytes\n"); 276*b285192aSMauro Carvalho Chehab for (byte = 0; byte < msgs[i].len; byte++) { 277*b285192aSMauro Carvalho Chehab d1printk(" ="); 278*b285192aSMauro Carvalho Chehab rc = i2c_recv_byte(dev); 279*b285192aSMauro Carvalho Chehab if (rc < 0) 280*b285192aSMauro Carvalho Chehab goto err; 281*b285192aSMauro Carvalho Chehab d1printk("%02x", rc); 282*b285192aSMauro Carvalho Chehab msgs[i].buf[byte] = rc; 283*b285192aSMauro Carvalho Chehab } 284*b285192aSMauro Carvalho Chehab /* discard mysterious extra byte when reading 285*b285192aSMauro Carvalho Chehab from Samsung S5H1411. i2c bus gets error 286*b285192aSMauro Carvalho Chehab if we do not. */ 287*b285192aSMauro Carvalho Chehab if (0x19 == msgs[i].addr) { 288*b285192aSMauro Carvalho Chehab d1printk(" ?"); 289*b285192aSMauro Carvalho Chehab rc = i2c_recv_byte(dev); 290*b285192aSMauro Carvalho Chehab if (rc < 0) 291*b285192aSMauro Carvalho Chehab goto err; 292*b285192aSMauro Carvalho Chehab d1printk("%02x", rc); 293*b285192aSMauro Carvalho Chehab } 294*b285192aSMauro Carvalho Chehab } else { 295*b285192aSMauro Carvalho Chehab /* write bytes */ 296*b285192aSMauro Carvalho Chehab d2printk("write bytes\n"); 297*b285192aSMauro Carvalho Chehab for (byte = 0; byte < msgs[i].len; byte++) { 298*b285192aSMauro Carvalho Chehab data = msgs[i].buf[byte]; 299*b285192aSMauro Carvalho Chehab d1printk(" %02x", data); 300*b285192aSMauro Carvalho Chehab rc = i2c_send_byte(dev,CONTINUE,data); 301*b285192aSMauro Carvalho Chehab if (rc < 0) 302*b285192aSMauro Carvalho Chehab goto err; 303*b285192aSMauro Carvalho Chehab } 304*b285192aSMauro Carvalho Chehab } 305*b285192aSMauro Carvalho Chehab } 306*b285192aSMauro Carvalho Chehab d2printk("xfer done\n"); 307*b285192aSMauro Carvalho Chehab d1printk(" >"); 308*b285192aSMauro Carvalho Chehab i2c_set_attr(dev,STOP); 309*b285192aSMauro Carvalho Chehab rc = -EIO; 310*b285192aSMauro Carvalho Chehab if (!i2c_is_busy_wait(dev)) 311*b285192aSMauro Carvalho Chehab goto err; 312*b285192aSMauro Carvalho Chehab status = i2c_get_status(dev); 313*b285192aSMauro Carvalho Chehab if (i2c_is_error(status)) 314*b285192aSMauro Carvalho Chehab goto err; 315*b285192aSMauro Carvalho Chehab /* ensure that the bus is idle for at least one bit slot */ 316*b285192aSMauro Carvalho Chehab msleep(1); 317*b285192aSMauro Carvalho Chehab 318*b285192aSMauro Carvalho Chehab d1printk("\n"); 319*b285192aSMauro Carvalho Chehab return num; 320*b285192aSMauro Carvalho Chehab err: 321*b285192aSMauro Carvalho Chehab if (1 == i2c_debug) { 322*b285192aSMauro Carvalho Chehab status = i2c_get_status(dev); 323*b285192aSMauro Carvalho Chehab printk(" ERROR: %s\n",str_i2c_status[status]); 324*b285192aSMauro Carvalho Chehab } 325*b285192aSMauro Carvalho Chehab return rc; 326*b285192aSMauro Carvalho Chehab } 327*b285192aSMauro Carvalho Chehab 328*b285192aSMauro Carvalho Chehab /* ----------------------------------------------------------- */ 329*b285192aSMauro Carvalho Chehab 330*b285192aSMauro Carvalho Chehab static u32 functionality(struct i2c_adapter *adap) 331*b285192aSMauro Carvalho Chehab { 332*b285192aSMauro Carvalho Chehab return I2C_FUNC_SMBUS_EMUL; 333*b285192aSMauro Carvalho Chehab } 334*b285192aSMauro Carvalho Chehab 335*b285192aSMauro Carvalho Chehab static struct i2c_algorithm saa7134_algo = { 336*b285192aSMauro Carvalho Chehab .master_xfer = saa7134_i2c_xfer, 337*b285192aSMauro Carvalho Chehab .functionality = functionality, 338*b285192aSMauro Carvalho Chehab }; 339*b285192aSMauro Carvalho Chehab 340*b285192aSMauro Carvalho Chehab static struct i2c_adapter saa7134_adap_template = { 341*b285192aSMauro Carvalho Chehab .owner = THIS_MODULE, 342*b285192aSMauro Carvalho Chehab .name = "saa7134", 343*b285192aSMauro Carvalho Chehab .algo = &saa7134_algo, 344*b285192aSMauro Carvalho Chehab }; 345*b285192aSMauro Carvalho Chehab 346*b285192aSMauro Carvalho Chehab static struct i2c_client saa7134_client_template = { 347*b285192aSMauro Carvalho Chehab .name = "saa7134 internal", 348*b285192aSMauro Carvalho Chehab }; 349*b285192aSMauro Carvalho Chehab 350*b285192aSMauro Carvalho Chehab /* ----------------------------------------------------------- */ 351*b285192aSMauro Carvalho Chehab 352*b285192aSMauro Carvalho Chehab static int 353*b285192aSMauro Carvalho Chehab saa7134_i2c_eeprom(struct saa7134_dev *dev, unsigned char *eedata, int len) 354*b285192aSMauro Carvalho Chehab { 355*b285192aSMauro Carvalho Chehab unsigned char buf; 356*b285192aSMauro Carvalho Chehab int i,err; 357*b285192aSMauro Carvalho Chehab 358*b285192aSMauro Carvalho Chehab dev->i2c_client.addr = 0xa0 >> 1; 359*b285192aSMauro Carvalho Chehab buf = 0; 360*b285192aSMauro Carvalho Chehab if (1 != (err = i2c_master_send(&dev->i2c_client,&buf,1))) { 361*b285192aSMauro Carvalho Chehab printk(KERN_INFO "%s: Huh, no eeprom present (err=%d)?\n", 362*b285192aSMauro Carvalho Chehab dev->name,err); 363*b285192aSMauro Carvalho Chehab return -1; 364*b285192aSMauro Carvalho Chehab } 365*b285192aSMauro Carvalho Chehab if (len != (err = i2c_master_recv(&dev->i2c_client,eedata,len))) { 366*b285192aSMauro Carvalho Chehab printk(KERN_WARNING "%s: i2c eeprom read error (err=%d)\n", 367*b285192aSMauro Carvalho Chehab dev->name,err); 368*b285192aSMauro Carvalho Chehab return -1; 369*b285192aSMauro Carvalho Chehab } 370*b285192aSMauro Carvalho Chehab for (i = 0; i < len; i++) { 371*b285192aSMauro Carvalho Chehab if (0 == (i % 16)) 372*b285192aSMauro Carvalho Chehab printk(KERN_INFO "%s: i2c eeprom %02x:",dev->name,i); 373*b285192aSMauro Carvalho Chehab printk(" %02x",eedata[i]); 374*b285192aSMauro Carvalho Chehab if (15 == (i % 16)) 375*b285192aSMauro Carvalho Chehab printk("\n"); 376*b285192aSMauro Carvalho Chehab } 377*b285192aSMauro Carvalho Chehab return 0; 378*b285192aSMauro Carvalho Chehab } 379*b285192aSMauro Carvalho Chehab 380*b285192aSMauro Carvalho Chehab static char *i2c_devs[128] = { 381*b285192aSMauro Carvalho Chehab [ 0x20 ] = "mpeg encoder (saa6752hs)", 382*b285192aSMauro Carvalho Chehab [ 0xa0 >> 1 ] = "eeprom", 383*b285192aSMauro Carvalho Chehab [ 0xc0 >> 1 ] = "tuner (analog)", 384*b285192aSMauro Carvalho Chehab [ 0x86 >> 1 ] = "tda9887", 385*b285192aSMauro Carvalho Chehab [ 0x5a >> 1 ] = "remote control", 386*b285192aSMauro Carvalho Chehab }; 387*b285192aSMauro Carvalho Chehab 388*b285192aSMauro Carvalho Chehab static void do_i2c_scan(char *name, struct i2c_client *c) 389*b285192aSMauro Carvalho Chehab { 390*b285192aSMauro Carvalho Chehab unsigned char buf; 391*b285192aSMauro Carvalho Chehab int i,rc; 392*b285192aSMauro Carvalho Chehab 393*b285192aSMauro Carvalho Chehab for (i = 0; i < ARRAY_SIZE(i2c_devs); i++) { 394*b285192aSMauro Carvalho Chehab c->addr = i; 395*b285192aSMauro Carvalho Chehab rc = i2c_master_recv(c,&buf,0); 396*b285192aSMauro Carvalho Chehab if (rc < 0) 397*b285192aSMauro Carvalho Chehab continue; 398*b285192aSMauro Carvalho Chehab printk("%s: i2c scan: found device @ 0x%x [%s]\n", 399*b285192aSMauro Carvalho Chehab name, i << 1, i2c_devs[i] ? i2c_devs[i] : "???"); 400*b285192aSMauro Carvalho Chehab } 401*b285192aSMauro Carvalho Chehab } 402*b285192aSMauro Carvalho Chehab 403*b285192aSMauro Carvalho Chehab int saa7134_i2c_register(struct saa7134_dev *dev) 404*b285192aSMauro Carvalho Chehab { 405*b285192aSMauro Carvalho Chehab dev->i2c_adap = saa7134_adap_template; 406*b285192aSMauro Carvalho Chehab dev->i2c_adap.dev.parent = &dev->pci->dev; 407*b285192aSMauro Carvalho Chehab strcpy(dev->i2c_adap.name,dev->name); 408*b285192aSMauro Carvalho Chehab dev->i2c_adap.algo_data = dev; 409*b285192aSMauro Carvalho Chehab i2c_set_adapdata(&dev->i2c_adap, &dev->v4l2_dev); 410*b285192aSMauro Carvalho Chehab i2c_add_adapter(&dev->i2c_adap); 411*b285192aSMauro Carvalho Chehab 412*b285192aSMauro Carvalho Chehab dev->i2c_client = saa7134_client_template; 413*b285192aSMauro Carvalho Chehab dev->i2c_client.adapter = &dev->i2c_adap; 414*b285192aSMauro Carvalho Chehab 415*b285192aSMauro Carvalho Chehab saa7134_i2c_eeprom(dev,dev->eedata,sizeof(dev->eedata)); 416*b285192aSMauro Carvalho Chehab if (i2c_scan) 417*b285192aSMauro Carvalho Chehab do_i2c_scan(dev->name,&dev->i2c_client); 418*b285192aSMauro Carvalho Chehab 419*b285192aSMauro Carvalho Chehab /* Instantiate the IR receiver device, if present */ 420*b285192aSMauro Carvalho Chehab saa7134_probe_i2c_ir(dev); 421*b285192aSMauro Carvalho Chehab return 0; 422*b285192aSMauro Carvalho Chehab } 423*b285192aSMauro Carvalho Chehab 424*b285192aSMauro Carvalho Chehab int saa7134_i2c_unregister(struct saa7134_dev *dev) 425*b285192aSMauro Carvalho Chehab { 426*b285192aSMauro Carvalho Chehab i2c_del_adapter(&dev->i2c_adap); 427*b285192aSMauro Carvalho Chehab return 0; 428*b285192aSMauro Carvalho Chehab } 429*b285192aSMauro Carvalho Chehab 430*b285192aSMauro Carvalho Chehab /* ----------------------------------------------------------- */ 431*b285192aSMauro Carvalho Chehab /* 432*b285192aSMauro Carvalho Chehab * Local variables: 433*b285192aSMauro Carvalho Chehab * c-basic-offset: 8 434*b285192aSMauro Carvalho Chehab * End: 435*b285192aSMauro Carvalho Chehab */ 436