linux/drivers/media/video/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 & I2C_M_RD && msgs[i].addr != 0x40) {
 258                                /* workaround for a saa7134 i2c bug
 259                                 * needed to talk to the mt352 demux
 260                                 * thanks to pinnacle for the hint */
 261                                int quirk = 0xfe;
 262                                d1printk(" [%02x quirk]",quirk);
 263                                i2c_send_byte(dev,START,quirk);
 264                                i2c_recv_byte(dev);
 265                        }
 266                        d1printk(" < %02x", addr);
 267                        rc = i2c_send_byte(dev,START,addr);
 268                        if (rc < 0)
 269                                 goto err;
 270                }
 271                if (msgs[i].flags & I2C_M_RD) {
 272                        /* read bytes */
 273                        d2printk("read bytes\n");
 274                        for (byte = 0; byte < msgs[i].len; byte++) {
 275                                d1printk(" =");
 276                                rc = i2c_recv_byte(dev);
 277                                if (rc < 0)
 278                                        goto err;
 279                                d1printk("%02x", rc);
 280                                msgs[i].buf[byte] = rc;
 281                        }
 282                } else {
 283                        /* write bytes */
 284                        d2printk("write bytes\n");
 285                        for (byte = 0; byte < msgs[i].len; byte++) {
 286                                data = msgs[i].buf[byte];
 287                                d1printk(" %02x", data);
 288                                rc = i2c_send_byte(dev,CONTINUE,data);
 289                                if (rc < 0)
 290                                        goto err;
 291                        }
 292                }
 293        }
 294        d2printk("xfer done\n");
 295        d1printk(" >");
 296        i2c_set_attr(dev,STOP);
 297        rc = -EIO;
 298        if (!i2c_is_busy_wait(dev))
 299                goto err;
 300        status = i2c_get_status(dev);
 301        if (i2c_is_error(status))
 302                goto err;
 303        /* ensure that the bus is idle for at least one bit slot */
 304        msleep(1);
 305
 306        d1printk("\n");
 307        return num;
 308 err:
 309        if (1 == i2c_debug) {
 310                status = i2c_get_status(dev);
 311                printk(" ERROR: %s\n",str_i2c_status[status]);
 312        }
 313        return rc;
 314}
 315
 316/* ----------------------------------------------------------- */
 317
 318static u32 functionality(struct i2c_adapter *adap)
 319{
 320        return I2C_FUNC_SMBUS_EMUL;
 321}
 322
 323static struct i2c_algorithm saa7134_algo = {
 324        .master_xfer   = saa7134_i2c_xfer,
 325        .functionality = functionality,
 326};
 327
 328static struct i2c_adapter saa7134_adap_template = {
 329        .owner         = THIS_MODULE,
 330        .name          = "saa7134",
 331        .id            = I2C_HW_SAA7134,
 332        .algo          = &saa7134_algo,
 333};
 334
 335static struct i2c_client saa7134_client_template = {
 336        .name   = "saa7134 internal",
 337};
 338
 339/* ----------------------------------------------------------- */
 340
 341static int
 342saa7134_i2c_eeprom(struct saa7134_dev *dev, unsigned char *eedata, int len)
 343{
 344        unsigned char buf;
 345        int i,err;
 346
 347        dev->i2c_client.addr = 0xa0 >> 1;
 348        buf = 0;
 349        if (1 != (err = i2c_master_send(&dev->i2c_client,&buf,1))) {
 350                printk(KERN_INFO "%s: Huh, no eeprom present (err=%d)?\n",
 351                       dev->name,err);
 352                return -1;
 353        }
 354        if (len != (err = i2c_master_recv(&dev->i2c_client,eedata,len))) {
 355                printk(KERN_WARNING "%s: i2c eeprom read error (err=%d)\n",
 356                       dev->name,err);
 357                return -1;
 358        }
 359        for (i = 0; i < len; i++) {
 360                if (0 == (i % 16))
 361                        printk(KERN_INFO "%s: i2c eeprom %02x:",dev->name,i);
 362                printk(" %02x",eedata[i]);
 363                if (15 == (i % 16))
 364                        printk("\n");
 365        }
 366        return 0;
 367}
 368
 369static char *i2c_devs[128] = {
 370        [ 0x20      ] = "mpeg encoder (saa6752hs)",
 371        [ 0xa0 >> 1 ] = "eeprom",
 372        [ 0xc0 >> 1 ] = "tuner (analog)",
 373        [ 0x86 >> 1 ] = "tda9887",
 374        [ 0x5a >> 1 ] = "remote control",
 375};
 376
 377static void do_i2c_scan(char *name, struct i2c_client *c)
 378{
 379        unsigned char buf;
 380        int i,rc;
 381
 382        for (i = 0; i < ARRAY_SIZE(i2c_devs); i++) {
 383                c->addr = i;
 384                rc = i2c_master_recv(c,&buf,0);
 385                if (rc < 0)
 386                        continue;
 387                printk("%s: i2c scan: found device @ 0x%x  [%s]\n",
 388                       name, i << 1, i2c_devs[i] ? i2c_devs[i] : "???");
 389        }
 390}
 391
 392int saa7134_i2c_register(struct saa7134_dev *dev)
 393{
 394        dev->i2c_adap = saa7134_adap_template;
 395        dev->i2c_adap.dev.parent = &dev->pci->dev;
 396        strcpy(dev->i2c_adap.name,dev->name);
 397        dev->i2c_adap.algo_data = dev;
 398        i2c_set_adapdata(&dev->i2c_adap, &dev->v4l2_dev);
 399        i2c_add_adapter(&dev->i2c_adap);
 400
 401        dev->i2c_client = saa7134_client_template;
 402        dev->i2c_client.adapter = &dev->i2c_adap;
 403
 404        saa7134_i2c_eeprom(dev,dev->eedata,sizeof(dev->eedata));
 405        if (i2c_scan)
 406                do_i2c_scan(dev->name,&dev->i2c_client);
 407
 408        /* Instantiate the IR receiver device, if present */
 409        saa7134_probe_i2c_ir(dev);
 410        return 0;
 411}
 412
 413int saa7134_i2c_unregister(struct saa7134_dev *dev)
 414{
 415        i2c_del_adapter(&dev->i2c_adap);
 416        return 0;
 417}
 418
 419/* ----------------------------------------------------------- */
 420/*
 421 * Local variables:
 422 * c-basic-offset: 8
 423 * End:
 424 */
 425