linux/drivers/staging/tm6000/tm6000-i2c.c
<<
>>
Prefs
   1/*
   2 *  tm6000-i2c.c - driver for TM5600/TM6000/TM6010 USB video capture devices
   3 *
   4 *  Copyright (C) 2006-2007 Mauro Carvalho Chehab <mchehab@infradead.org>
   5 *
   6 *  Copyright (C) 2007 Michel Ludwig <michel.ludwig@gmail.com>
   7 *      - Fix SMBus Read Byte command
   8 *
   9 *  This program is free software; you can redistribute it and/or modify
  10 *  it under the terms of the GNU General Public License as published by
  11 *  the Free Software Foundation version 2
  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/module.h>
  24#include <linux/kernel.h>
  25#include <linux/usb.h>
  26#include <linux/i2c.h>
  27
  28#include "tm6000.h"
  29#include "tm6000-regs.h"
  30#include <media/v4l2-common.h>
  31#include <media/tuner.h>
  32#include "tuner-xc2028.h"
  33
  34
  35/* ----------------------------------------------------------- */
  36
  37static unsigned int i2c_debug;
  38module_param(i2c_debug, int, 0644);
  39MODULE_PARM_DESC(i2c_debug, "enable debug messages [i2c]");
  40
  41#define i2c_dprintk(lvl, fmt, args...) if (i2c_debug >= lvl) do { \
  42                        printk(KERN_DEBUG "%s at %s: " fmt, \
  43                        dev->name, __FUNCTION__ , ##args); } while (0)
  44
  45static int tm6000_i2c_send_regs(struct tm6000_core *dev, unsigned char addr,
  46                                __u8 reg, char *buf, int len)
  47{
  48        int rc;
  49        unsigned int tsleep;
  50        unsigned int i2c_packet_limit = 16;
  51
  52        if (dev->dev_type == TM6010)
  53                i2c_packet_limit = 64;
  54
  55        if (!buf)
  56                return -1;
  57
  58        if (len < 1 || len > i2c_packet_limit) {
  59                printk(KERN_ERR "Incorrect length of i2c packet = %d, limit set to %d\n",
  60                        len, i2c_packet_limit);
  61                return -1;
  62        }
  63
  64        /* capture mutex */
  65        rc = tm6000_read_write_usb(dev, USB_DIR_OUT | USB_TYPE_VENDOR |
  66                USB_RECIP_DEVICE, REQ_16_SET_GET_I2C_WR1_RDN,
  67                addr | reg << 8, 0, buf, len);
  68
  69        if (rc < 0) {
  70                /* release mutex */
  71                return rc;
  72        }
  73
  74        /* Calculate delay time, 14000us for 64 bytes */
  75        tsleep = ((len * 200) + 200 + 1000) / 1000;
  76        msleep(tsleep);
  77
  78        /* release mutex */
  79        return rc;
  80}
  81
  82/* Generic read - doesn't work fine with 16bit registers */
  83static int tm6000_i2c_recv_regs(struct tm6000_core *dev, unsigned char addr,
  84                                __u8 reg, char *buf, int len)
  85{
  86        int rc;
  87        u8 b[2];
  88        unsigned int i2c_packet_limit = 16;
  89
  90        if (dev->dev_type == TM6010)
  91                i2c_packet_limit = 64;
  92
  93        if (!buf)
  94                return -1;
  95
  96        if (len < 1 || len > i2c_packet_limit) {
  97                printk(KERN_ERR "Incorrect length of i2c packet = %d, limit set to %d\n",
  98                        len, i2c_packet_limit);
  99                return -1;
 100        }
 101
 102        /* capture mutex */
 103        if ((dev->caps.has_zl10353) && (dev->demod_addr << 1 == addr) && (reg % 2 == 0)) {
 104                /*
 105                 * Workaround an I2C bug when reading from zl10353
 106                 */
 107                reg -= 1;
 108                len += 1;
 109
 110                rc = tm6000_read_write_usb(dev, USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
 111                        REQ_16_SET_GET_I2C_WR1_RDN, addr | reg << 8, 0, b, len);
 112
 113                *buf = b[1];
 114        } else {
 115                rc = tm6000_read_write_usb(dev, USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
 116                        REQ_16_SET_GET_I2C_WR1_RDN, addr | reg << 8, 0, buf, len);
 117        }
 118
 119        /* release mutex */
 120        return rc;
 121}
 122
 123/*
 124 * read from a 16bit register
 125 * for example xc2028, xc3028 or xc3028L
 126 */
 127static int tm6000_i2c_recv_regs16(struct tm6000_core *dev, unsigned char addr,
 128                                  __u16 reg, char *buf, int len)
 129{
 130        int rc;
 131        unsigned char ureg;
 132
 133        if (!buf || len != 2)
 134                return -1;
 135
 136        /* capture mutex */
 137        if (dev->dev_type == TM6010) {
 138                ureg = reg & 0xFF;
 139                rc = tm6000_read_write_usb(dev, USB_DIR_OUT | USB_TYPE_VENDOR |
 140                        USB_RECIP_DEVICE, REQ_16_SET_GET_I2C_WR1_RDN,
 141                        addr | (reg & 0xFF00), 0, &ureg, 1);
 142
 143                if (rc < 0) {
 144                        /* release mutex */
 145                        return rc;
 146                }
 147
 148                msleep(1400 / 1000);
 149                rc = tm6000_read_write_usb(dev, USB_DIR_IN | USB_TYPE_VENDOR |
 150                        USB_RECIP_DEVICE, REQ_35_AFTEK_TUNER_READ,
 151                        reg, 0, buf, len);
 152        } else {
 153                rc = tm6000_read_write_usb(dev, USB_DIR_IN | USB_TYPE_VENDOR |
 154                        USB_RECIP_DEVICE, REQ_14_SET_GET_I2C_WR2_RDN,
 155                        addr, reg, buf, len);
 156        }
 157
 158        /* release mutex */
 159        return rc;
 160}
 161
 162static int tm6000_i2c_xfer(struct i2c_adapter *i2c_adap,
 163                           struct i2c_msg msgs[], int num)
 164{
 165        struct tm6000_core *dev = i2c_adap->algo_data;
 166        int addr, rc, i, byte;
 167
 168        if (num <= 0)
 169                return 0;
 170        for (i = 0; i < num; i++) {
 171                addr = (msgs[i].addr << 1) & 0xff;
 172                i2c_dprintk(2, "%s %s addr=0x%x len=%d:",
 173                         (msgs[i].flags & I2C_M_RD) ? "read" : "write",
 174                         i == num - 1 ? "stop" : "nonstop", addr, msgs[i].len);
 175                if (msgs[i].flags & I2C_M_RD) {
 176                        /* read request without preceding register selection */
 177                        /*
 178                         * The TM6000 only supports a read transaction
 179                         * immediately after a 1 or 2 byte write to select
 180                         * a register.  We cannot fulfil this request.
 181                         */
 182                        i2c_dprintk(2, " read without preceding write not"
 183                                       " supported");
 184                        rc = -EOPNOTSUPP;
 185                        goto err;
 186                } else if (i + 1 < num && msgs[i].len <= 2 &&
 187                           (msgs[i + 1].flags & I2C_M_RD) &&
 188                           msgs[i].addr == msgs[i + 1].addr) {
 189                        /* 1 or 2 byte write followed by a read */
 190                        if (i2c_debug >= 2)
 191                                for (byte = 0; byte < msgs[i].len; byte++)
 192                                        printk(" %02x", msgs[i].buf[byte]);
 193                        i2c_dprintk(2, "; joined to read %s len=%d:",
 194                                    i == num - 2 ? "stop" : "nonstop",
 195                                    msgs[i + 1].len);
 196
 197                        if (msgs[i].len == 2) {
 198                                rc = tm6000_i2c_recv_regs16(dev, addr,
 199                                        msgs[i].buf[0] << 8 | msgs[i].buf[1],
 200                                        msgs[i + 1].buf, msgs[i + 1].len);
 201                        } else {
 202                                rc = tm6000_i2c_recv_regs(dev, addr, msgs[i].buf[0],
 203                                        msgs[i + 1].buf, msgs[i + 1].len);
 204                        }
 205
 206                        i++;
 207
 208                        if (addr == dev->tuner_addr << 1) {
 209                                tm6000_set_reg(dev, REQ_50_SET_START, 0, 0);
 210                                tm6000_set_reg(dev, REQ_51_SET_STOP, 0, 0);
 211                        }
 212                        if (i2c_debug >= 2)
 213                                for (byte = 0; byte < msgs[i].len; byte++)
 214                                        printk(" %02x", msgs[i].buf[byte]);
 215                } else {
 216                        /* write bytes */
 217                        if (i2c_debug >= 2)
 218                                for (byte = 0; byte < msgs[i].len; byte++)
 219                                        printk(" %02x", msgs[i].buf[byte]);
 220                        rc = tm6000_i2c_send_regs(dev, addr, msgs[i].buf[0],
 221                                msgs[i].buf + 1, msgs[i].len - 1);
 222
 223                        if (addr == dev->tuner_addr  << 1) {
 224                                tm6000_set_reg(dev, REQ_50_SET_START, 0, 0);
 225                                tm6000_set_reg(dev, REQ_51_SET_STOP, 0, 0);
 226                        }
 227                }
 228                if (i2c_debug >= 2)
 229                        printk("\n");
 230                if (rc < 0)
 231                        goto err;
 232        }
 233
 234        return num;
 235err:
 236        i2c_dprintk(2, " ERROR: %i\n", rc);
 237        return rc;
 238}
 239
 240static int tm6000_i2c_eeprom(struct tm6000_core *dev,
 241                             unsigned char *eedata, int len)
 242{
 243        int i, rc;
 244        unsigned char *p = eedata;
 245        unsigned char bytes[17];
 246
 247        dev->i2c_client.addr = 0xa0 >> 1;
 248
 249        bytes[16] = '\0';
 250        for (i = 0; i < len; ) {
 251        *p = i;
 252        rc = tm6000_i2c_recv_regs(dev, 0xa0, i, p, 1);
 253                if (rc < 1) {
 254                        if (p == eedata)
 255                                goto noeeprom;
 256                        else {
 257                                printk(KERN_WARNING
 258                                "%s: i2c eeprom read error (err=%d)\n",
 259                                dev->name, rc);
 260                        }
 261                        return -1;
 262                }
 263                p++;
 264                if (0 == (i % 16))
 265                        printk(KERN_INFO "%s: i2c eeprom %02x:", dev->name, i);
 266                printk(" %02x", eedata[i]);
 267                if ((eedata[i] >= ' ') && (eedata[i] <= 'z'))
 268                        bytes[i%16] = eedata[i];
 269                else
 270                        bytes[i%16] = '.';
 271
 272                i++;
 273
 274                if (0 == (i % 16)) {
 275                        bytes[16] = '\0';
 276                        printk("  %s\n", bytes);
 277                }
 278        }
 279        if (0 != (i%16)) {
 280                bytes[i%16] = '\0';
 281                for (i %= 16; i < 16; i++)
 282                        printk("   ");
 283        }
 284        printk("  %s\n", bytes);
 285
 286        return 0;
 287
 288noeeprom:
 289        printk(KERN_INFO "%s: Huh, no eeprom present (err=%d)?\n",
 290                       dev->name, rc);
 291        return rc;
 292}
 293
 294/* ----------------------------------------------------------- */
 295
 296/*
 297 * functionality()
 298 */
 299static u32 functionality(struct i2c_adapter *adap)
 300{
 301        return I2C_FUNC_SMBUS_EMUL;
 302}
 303
 304static const struct i2c_algorithm tm6000_algo = {
 305        .master_xfer   = tm6000_i2c_xfer,
 306        .functionality = functionality,
 307};
 308
 309/* ----------------------------------------------------------- */
 310
 311/*
 312 * tm6000_i2c_register()
 313 * register i2c bus
 314 */
 315int tm6000_i2c_register(struct tm6000_core *dev)
 316{
 317        unsigned char eedata[256];
 318        int rc;
 319
 320        dev->i2c_adap.owner = THIS_MODULE;
 321        dev->i2c_adap.algo = &tm6000_algo;
 322        dev->i2c_adap.dev.parent = &dev->udev->dev;
 323        strlcpy(dev->i2c_adap.name, dev->name, sizeof(dev->i2c_adap.name));
 324        dev->i2c_adap.algo_data = dev;
 325        i2c_set_adapdata(&dev->i2c_adap, &dev->v4l2_dev);
 326        rc = i2c_add_adapter(&dev->i2c_adap);
 327        if (rc)
 328                return rc;
 329
 330        dev->i2c_client.adapter = &dev->i2c_adap;
 331        strlcpy(dev->i2c_client.name, "tm6000 internal", I2C_NAME_SIZE);
 332
 333        tm6000_i2c_eeprom(dev, eedata, sizeof(eedata));
 334
 335        return 0;
 336}
 337
 338/*
 339 * tm6000_i2c_unregister()
 340 * unregister i2c_bus
 341 */
 342int tm6000_i2c_unregister(struct tm6000_core *dev)
 343{
 344        i2c_del_adapter(&dev->i2c_adap);
 345        return 0;
 346}
 347