linux/drivers/media/usb/au0828/au0828-i2c.c
<<
>>
Prefs
   1/*
   2 *  Driver for the Auvitek AU0828 USB bridge
   3 *
   4 *  Copyright (c) 2008 Steven Toth <stoth@linuxtv.org>
   5 *
   6 *  This program is free software; you can redistribute it and/or modify
   7 *  it under the terms of the GNU General Public License as published by
   8 *  the Free Software Foundation; either version 2 of the License, or
   9 *  (at your option) any later version.
  10 *
  11 *  This program is distributed in the hope that it will be useful,
  12 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  13 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14 *
  15 *  GNU General Public License for more details.
  16 *
  17 *  You should have received a copy of the GNU General Public License
  18 *  along with this program; if not, write to the Free Software
  19 *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  20 */
  21
  22#include <linux/module.h>
  23#include <linux/moduleparam.h>
  24#include <linux/init.h>
  25#include <linux/delay.h>
  26#include <linux/io.h>
  27
  28#include "au0828.h"
  29#include "media/tuner.h"
  30#include <media/v4l2-common.h>
  31
  32static int i2c_scan;
  33module_param(i2c_scan, int, 0444);
  34MODULE_PARM_DESC(i2c_scan, "scan i2c bus at insmod time");
  35
  36#define I2C_WAIT_DELAY 25
  37#define I2C_WAIT_RETRY 1000
  38
  39static inline int i2c_slave_did_write_ack(struct i2c_adapter *i2c_adap)
  40{
  41        struct au0828_dev *dev = i2c_adap->algo_data;
  42        return au0828_read(dev, AU0828_I2C_STATUS_201) &
  43                AU0828_I2C_STATUS_NO_WRITE_ACK ? 0 : 1;
  44}
  45
  46static inline int i2c_slave_did_read_ack(struct i2c_adapter *i2c_adap)
  47{
  48        struct au0828_dev *dev = i2c_adap->algo_data;
  49        return au0828_read(dev, AU0828_I2C_STATUS_201) &
  50                AU0828_I2C_STATUS_NO_READ_ACK ? 0 : 1;
  51}
  52
  53static int i2c_wait_read_ack(struct i2c_adapter *i2c_adap)
  54{
  55        int count;
  56
  57        for (count = 0; count < I2C_WAIT_RETRY; count++) {
  58                if (!i2c_slave_did_read_ack(i2c_adap))
  59                        break;
  60                udelay(I2C_WAIT_DELAY);
  61        }
  62
  63        if (I2C_WAIT_RETRY == count)
  64                return 0;
  65
  66        return 1;
  67}
  68
  69static inline int i2c_is_read_busy(struct i2c_adapter *i2c_adap)
  70{
  71        struct au0828_dev *dev = i2c_adap->algo_data;
  72        return au0828_read(dev, AU0828_I2C_STATUS_201) &
  73                AU0828_I2C_STATUS_READ_DONE ? 0 : 1;
  74}
  75
  76static int i2c_wait_read_done(struct i2c_adapter *i2c_adap)
  77{
  78        int count;
  79
  80        for (count = 0; count < I2C_WAIT_RETRY; count++) {
  81                if (!i2c_is_read_busy(i2c_adap))
  82                        break;
  83                udelay(I2C_WAIT_DELAY);
  84        }
  85
  86        if (I2C_WAIT_RETRY == count)
  87                return 0;
  88
  89        return 1;
  90}
  91
  92static inline int i2c_is_write_done(struct i2c_adapter *i2c_adap)
  93{
  94        struct au0828_dev *dev = i2c_adap->algo_data;
  95        return au0828_read(dev, AU0828_I2C_STATUS_201) &
  96                AU0828_I2C_STATUS_WRITE_DONE ? 1 : 0;
  97}
  98
  99static int i2c_wait_write_done(struct i2c_adapter *i2c_adap)
 100{
 101        int count;
 102
 103        for (count = 0; count < I2C_WAIT_RETRY; count++) {
 104                if (i2c_is_write_done(i2c_adap))
 105                        break;
 106                udelay(I2C_WAIT_DELAY);
 107        }
 108
 109        if (I2C_WAIT_RETRY == count)
 110                return 0;
 111
 112        return 1;
 113}
 114
 115static inline int i2c_is_busy(struct i2c_adapter *i2c_adap)
 116{
 117        struct au0828_dev *dev = i2c_adap->algo_data;
 118        return au0828_read(dev, AU0828_I2C_STATUS_201) &
 119                AU0828_I2C_STATUS_BUSY ? 1 : 0;
 120}
 121
 122static int i2c_wait_done(struct i2c_adapter *i2c_adap)
 123{
 124        int count;
 125
 126        for (count = 0; count < I2C_WAIT_RETRY; count++) {
 127                if (!i2c_is_busy(i2c_adap))
 128                        break;
 129                udelay(I2C_WAIT_DELAY);
 130        }
 131
 132        if (I2C_WAIT_RETRY == count)
 133                return 0;
 134
 135        return 1;
 136}
 137
 138/* FIXME: Implement join handling correctly */
 139static int i2c_sendbytes(struct i2c_adapter *i2c_adap,
 140        const struct i2c_msg *msg, int joined_rlen)
 141{
 142        int i, strobe = 0;
 143        struct au0828_dev *dev = i2c_adap->algo_data;
 144
 145        dprintk(4, "%s()\n", __func__);
 146
 147        au0828_write(dev, AU0828_I2C_MULTIBYTE_MODE_2FF, 0x01);
 148
 149        /* Set the I2C clock */
 150        if (((dev->board.tuner_type == TUNER_XC5000) ||
 151             (dev->board.tuner_type == TUNER_XC5000C)) &&
 152            (dev->board.tuner_addr == msg->addr) &&
 153            (msg->len == 64)) {
 154                /* Hack to speed up firmware load.  The xc5000 lets us do up
 155                   to 400 KHz when in firmware download mode */
 156                au0828_write(dev, AU0828_I2C_CLK_DIVIDER_202,
 157                             AU0828_I2C_CLK_250KHZ);
 158        } else {
 159                /* Use the i2c clock speed in the board configuration */
 160                au0828_write(dev, AU0828_I2C_CLK_DIVIDER_202,
 161                             dev->board.i2c_clk_divider);
 162        }
 163
 164        /* Hardware needs 8 bit addresses */
 165        au0828_write(dev, AU0828_I2C_DEST_ADDR_203, msg->addr << 1);
 166
 167        dprintk(4, "SEND: %02x\n", msg->addr);
 168
 169        /* Deal with i2c_scan */
 170        if (msg->len == 0) {
 171                /* The analog tuner detection code makes use of the SMBUS_QUICK
 172                   message (which involves a zero length i2c write).  To avoid
 173                   checking the status register when we didn't strobe out any
 174                   actual bytes to the bus, just do a read check.  This is
 175                   consistent with how I saw i2c device checking done in the
 176                   USB trace of the Windows driver */
 177                au0828_write(dev, AU0828_I2C_TRIGGER_200,
 178                             AU0828_I2C_TRIGGER_READ);
 179
 180                if (!i2c_wait_done(i2c_adap))
 181                        return -EIO;
 182
 183                if (i2c_wait_read_ack(i2c_adap))
 184                        return -EIO;
 185
 186                return 0;
 187        }
 188
 189        for (i = 0; i < msg->len;) {
 190
 191                dprintk(4, " %02x\n", msg->buf[i]);
 192
 193                au0828_write(dev, AU0828_I2C_WRITE_FIFO_205, msg->buf[i]);
 194
 195                strobe++;
 196                i++;
 197
 198                if ((strobe >= 4) || (i >= msg->len)) {
 199
 200                        /* Strobe the byte into the bus */
 201                        if (i < msg->len)
 202                                au0828_write(dev, AU0828_I2C_TRIGGER_200,
 203                                             AU0828_I2C_TRIGGER_WRITE |
 204                                             AU0828_I2C_TRIGGER_HOLD);
 205                        else
 206                                au0828_write(dev, AU0828_I2C_TRIGGER_200,
 207                                             AU0828_I2C_TRIGGER_WRITE);
 208
 209                        /* Reset strobe trigger */
 210                        strobe = 0;
 211
 212                        if (!i2c_wait_write_done(i2c_adap))
 213                                return -EIO;
 214
 215                }
 216
 217        }
 218        if (!i2c_wait_done(i2c_adap))
 219                return -EIO;
 220
 221        dprintk(4, "\n");
 222
 223        return msg->len;
 224}
 225
 226/* FIXME: Implement join handling correctly */
 227static int i2c_readbytes(struct i2c_adapter *i2c_adap,
 228        const struct i2c_msg *msg, int joined)
 229{
 230        struct au0828_dev *dev = i2c_adap->algo_data;
 231        int i;
 232
 233        dprintk(4, "%s()\n", __func__);
 234
 235        au0828_write(dev, AU0828_I2C_MULTIBYTE_MODE_2FF, 0x01);
 236
 237        /* Set the I2C clock */
 238        au0828_write(dev, AU0828_I2C_CLK_DIVIDER_202,
 239                     dev->board.i2c_clk_divider);
 240
 241        /* Hardware needs 8 bit addresses */
 242        au0828_write(dev, AU0828_I2C_DEST_ADDR_203, msg->addr << 1);
 243
 244        dprintk(4, " RECV:\n");
 245
 246        /* Deal with i2c_scan */
 247        if (msg->len == 0) {
 248                au0828_write(dev, AU0828_I2C_TRIGGER_200,
 249                             AU0828_I2C_TRIGGER_READ);
 250
 251                if (i2c_wait_read_ack(i2c_adap))
 252                        return -EIO;
 253                return 0;
 254        }
 255
 256        for (i = 0; i < msg->len;) {
 257
 258                i++;
 259
 260                if (i < msg->len)
 261                        au0828_write(dev, AU0828_I2C_TRIGGER_200,
 262                                     AU0828_I2C_TRIGGER_READ |
 263                                     AU0828_I2C_TRIGGER_HOLD);
 264                else
 265                        au0828_write(dev, AU0828_I2C_TRIGGER_200,
 266                                     AU0828_I2C_TRIGGER_READ);
 267
 268                if (!i2c_wait_read_done(i2c_adap))
 269                        return -EIO;
 270
 271                msg->buf[i-1] = au0828_read(dev, AU0828_I2C_READ_FIFO_209) &
 272                        0xff;
 273
 274                dprintk(4, " %02x\n", msg->buf[i-1]);
 275        }
 276        if (!i2c_wait_done(i2c_adap))
 277                return -EIO;
 278
 279        dprintk(4, "\n");
 280
 281        return msg->len;
 282}
 283
 284static int i2c_xfer(struct i2c_adapter *i2c_adap,
 285                    struct i2c_msg *msgs, int num)
 286{
 287        int i, retval = 0;
 288
 289        dprintk(4, "%s(num = %d)\n", __func__, num);
 290
 291        for (i = 0; i < num; i++) {
 292                dprintk(4, "%s(num = %d) addr = 0x%02x  len = 0x%x\n",
 293                        __func__, num, msgs[i].addr, msgs[i].len);
 294                if (msgs[i].flags & I2C_M_RD) {
 295                        /* read */
 296                        retval = i2c_readbytes(i2c_adap, &msgs[i], 0);
 297                } else if (i + 1 < num && (msgs[i + 1].flags & I2C_M_RD) &&
 298                           msgs[i].addr == msgs[i + 1].addr) {
 299                        /* write then read from same address */
 300                        retval = i2c_sendbytes(i2c_adap, &msgs[i],
 301                                               msgs[i + 1].len);
 302                        if (retval < 0)
 303                                goto err;
 304                        i++;
 305                        retval = i2c_readbytes(i2c_adap, &msgs[i], 1);
 306                } else {
 307                        /* write */
 308                        retval = i2c_sendbytes(i2c_adap, &msgs[i], 0);
 309                }
 310                if (retval < 0)
 311                        goto err;
 312        }
 313        return num;
 314
 315err:
 316        return retval;
 317}
 318
 319static u32 au0828_functionality(struct i2c_adapter *adap)
 320{
 321        return I2C_FUNC_SMBUS_EMUL | I2C_FUNC_I2C;
 322}
 323
 324static struct i2c_algorithm au0828_i2c_algo_template = {
 325        .master_xfer    = i2c_xfer,
 326        .functionality  = au0828_functionality,
 327};
 328
 329/* ----------------------------------------------------------------------- */
 330
 331static struct i2c_adapter au0828_i2c_adap_template = {
 332        .name              = DRIVER_NAME,
 333        .owner             = THIS_MODULE,
 334        .algo              = &au0828_i2c_algo_template,
 335};
 336
 337static struct i2c_client au0828_i2c_client_template = {
 338        .name   = "au0828 internal",
 339};
 340
 341static char *i2c_devs[128] = {
 342        [0x8e >> 1] = "au8522",
 343        [0xa0 >> 1] = "eeprom",
 344        [0xc2 >> 1] = "tuner/xc5000",
 345};
 346
 347static void do_i2c_scan(char *name, struct i2c_client *c)
 348{
 349        unsigned char buf;
 350        int i, rc;
 351
 352        for (i = 0; i < 128; i++) {
 353                c->addr = i;
 354                rc = i2c_master_recv(c, &buf, 0);
 355                if (rc < 0)
 356                        continue;
 357                printk(KERN_INFO "%s: i2c scan: found device @ 0x%x  [%s]\n",
 358                       name, i << 1, i2c_devs[i] ? i2c_devs[i] : "???");
 359        }
 360}
 361
 362/* init + register i2c adapter */
 363int au0828_i2c_register(struct au0828_dev *dev)
 364{
 365        dprintk(1, "%s()\n", __func__);
 366
 367        dev->i2c_adap = au0828_i2c_adap_template;
 368        dev->i2c_algo = au0828_i2c_algo_template;
 369        dev->i2c_client = au0828_i2c_client_template;
 370
 371        dev->i2c_adap.dev.parent = &dev->usbdev->dev;
 372
 373        strlcpy(dev->i2c_adap.name, DRIVER_NAME,
 374                sizeof(dev->i2c_adap.name));
 375
 376        dev->i2c_adap.algo = &dev->i2c_algo;
 377        dev->i2c_adap.algo_data = dev;
 378#ifdef CONFIG_VIDEO_AU0828_V4L2
 379        i2c_set_adapdata(&dev->i2c_adap, &dev->v4l2_dev);
 380#else
 381        i2c_set_adapdata(&dev->i2c_adap, dev);
 382#endif
 383        i2c_add_adapter(&dev->i2c_adap);
 384
 385        dev->i2c_client.adapter = &dev->i2c_adap;
 386
 387        if (0 == dev->i2c_rc) {
 388                printk(KERN_INFO "%s: i2c bus registered\n", DRIVER_NAME);
 389                if (i2c_scan)
 390                        do_i2c_scan(DRIVER_NAME, &dev->i2c_client);
 391        } else
 392                printk(KERN_INFO "%s: i2c bus register FAILED\n", DRIVER_NAME);
 393
 394        return dev->i2c_rc;
 395}
 396
 397int au0828_i2c_unregister(struct au0828_dev *dev)
 398{
 399        i2c_del_adapter(&dev->i2c_adap);
 400        return 0;
 401}
 402
 403