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