19701dc94a14e54a33c3c99744ec3a761f6385fc6Mauro Carvalho Chehab/* 2d0058645c682a04c261516e917414ed8e39b2296Ruslan Pisarev * tm6000-i2c.c - driver for TM5600/TM6000/TM6010 USB video capture devices 3d0058645c682a04c261516e917414ed8e39b2296Ruslan Pisarev * 4d0058645c682a04c261516e917414ed8e39b2296Ruslan Pisarev * Copyright (C) 2006-2007 Mauro Carvalho Chehab <mchehab@infradead.org> 5d0058645c682a04c261516e917414ed8e39b2296Ruslan Pisarev * 6d0058645c682a04c261516e917414ed8e39b2296Ruslan Pisarev * Copyright (C) 2007 Michel Ludwig <michel.ludwig@gmail.com> 7d0058645c682a04c261516e917414ed8e39b2296Ruslan Pisarev * - Fix SMBus Read Byte command 8d0058645c682a04c261516e917414ed8e39b2296Ruslan Pisarev * 9d0058645c682a04c261516e917414ed8e39b2296Ruslan Pisarev * This program is free software; you can redistribute it and/or modify 10d0058645c682a04c261516e917414ed8e39b2296Ruslan Pisarev * it under the terms of the GNU General Public License as published by 11d0058645c682a04c261516e917414ed8e39b2296Ruslan Pisarev * the Free Software Foundation version 2 12d0058645c682a04c261516e917414ed8e39b2296Ruslan Pisarev * 13d0058645c682a04c261516e917414ed8e39b2296Ruslan Pisarev * This program is distributed in the hope that it will be useful, 14d0058645c682a04c261516e917414ed8e39b2296Ruslan Pisarev * but WITHOUT ANY WARRANTY; without even the implied warranty of 15d0058645c682a04c261516e917414ed8e39b2296Ruslan Pisarev * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16d0058645c682a04c261516e917414ed8e39b2296Ruslan Pisarev * GNU General Public License for more details. 17d0058645c682a04c261516e917414ed8e39b2296Ruslan Pisarev * 18d0058645c682a04c261516e917414ed8e39b2296Ruslan Pisarev * You should have received a copy of the GNU General Public License 19d0058645c682a04c261516e917414ed8e39b2296Ruslan Pisarev * along with this program; if not, write to the Free Software 20d0058645c682a04c261516e917414ed8e39b2296Ruslan Pisarev * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 219701dc94a14e54a33c3c99744ec3a761f6385fc6Mauro Carvalho Chehab */ 229701dc94a14e54a33c3c99744ec3a761f6385fc6Mauro Carvalho Chehab 239701dc94a14e54a33c3c99744ec3a761f6385fc6Mauro Carvalho Chehab#include <linux/module.h> 249701dc94a14e54a33c3c99744ec3a761f6385fc6Mauro Carvalho Chehab#include <linux/kernel.h> 259701dc94a14e54a33c3c99744ec3a761f6385fc6Mauro Carvalho Chehab#include <linux/usb.h> 269701dc94a14e54a33c3c99744ec3a761f6385fc6Mauro Carvalho Chehab#include <linux/i2c.h> 279701dc94a14e54a33c3c99744ec3a761f6385fc6Mauro Carvalho Chehab 289701dc94a14e54a33c3c99744ec3a761f6385fc6Mauro Carvalho Chehab#include "tm6000.h" 299701dc94a14e54a33c3c99744ec3a761f6385fc6Mauro Carvalho Chehab#include "tm6000-regs.h" 309701dc94a14e54a33c3c99744ec3a761f6385fc6Mauro Carvalho Chehab#include <media/v4l2-common.h> 319701dc94a14e54a33c3c99744ec3a761f6385fc6Mauro Carvalho Chehab#include <media/tuner.h> 329701dc94a14e54a33c3c99744ec3a761f6385fc6Mauro Carvalho Chehab#include "tuner-xc2028.h" 339701dc94a14e54a33c3c99744ec3a761f6385fc6Mauro Carvalho Chehab 349701dc94a14e54a33c3c99744ec3a761f6385fc6Mauro Carvalho Chehab 359701dc94a14e54a33c3c99744ec3a761f6385fc6Mauro Carvalho Chehab/* ----------------------------------------------------------- */ 369701dc94a14e54a33c3c99744ec3a761f6385fc6Mauro Carvalho Chehab 37d7fe4a602df6b31475303a9f9d4d4c9fc6ae34f5Ruslan Pisarevstatic unsigned int i2c_debug; 389701dc94a14e54a33c3c99744ec3a761f6385fc6Mauro Carvalho Chehabmodule_param(i2c_debug, int, 0644); 399701dc94a14e54a33c3c99744ec3a761f6385fc6Mauro Carvalho ChehabMODULE_PARM_DESC(i2c_debug, "enable debug messages [i2c]"); 409701dc94a14e54a33c3c99744ec3a761f6385fc6Mauro Carvalho Chehab 4152e0a72a0c6f61c26a16b5684f4eb30a6fbf8b83Timofey Trofimov#define i2c_dprintk(lvl, fmt, args...) if (i2c_debug >= lvl) do { \ 429701dc94a14e54a33c3c99744ec3a761f6385fc6Mauro Carvalho Chehab printk(KERN_DEBUG "%s at %s: " fmt, \ 430f063c68cc871829f75cf2d7d4723a356af58783Curtis McEnroe dev->name, __func__, ##args); } while (0) 449701dc94a14e54a33c3c99744ec3a761f6385fc6Mauro Carvalho Chehab 454e11502d4597c6252411dc1b5c16b47d08b5f246Stefan Ringelstatic int tm6000_i2c_send_regs(struct tm6000_core *dev, unsigned char addr, 464e11502d4597c6252411dc1b5c16b47d08b5f246Stefan Ringel __u8 reg, char *buf, int len) 474e11502d4597c6252411dc1b5c16b47d08b5f246Stefan Ringel{ 4820dead8da8b383004e66eaf884cd9e07ceadbd68Dmitri Belimov int rc; 4920dead8da8b383004e66eaf884cd9e07ceadbd68Dmitri Belimov unsigned int i2c_packet_limit = 16; 5020dead8da8b383004e66eaf884cd9e07ceadbd68Dmitri Belimov 5120dead8da8b383004e66eaf884cd9e07ceadbd68Dmitri Belimov if (dev->dev_type == TM6010) 523874cd7796ef1a03cd6d2a2d886e3ac4c35af09cMatthieu CASTET i2c_packet_limit = 80; 5320dead8da8b383004e66eaf884cd9e07ceadbd68Dmitri Belimov 5420dead8da8b383004e66eaf884cd9e07ceadbd68Dmitri Belimov if (!buf) 5520dead8da8b383004e66eaf884cd9e07ceadbd68Dmitri Belimov return -1; 5620dead8da8b383004e66eaf884cd9e07ceadbd68Dmitri Belimov 5720dead8da8b383004e66eaf884cd9e07ceadbd68Dmitri Belimov if (len < 1 || len > i2c_packet_limit) { 5820dead8da8b383004e66eaf884cd9e07ceadbd68Dmitri Belimov printk(KERN_ERR "Incorrect length of i2c packet = %d, limit set to %d\n", 5920dead8da8b383004e66eaf884cd9e07ceadbd68Dmitri Belimov len, i2c_packet_limit); 6020dead8da8b383004e66eaf884cd9e07ceadbd68Dmitri Belimov return -1; 6120dead8da8b383004e66eaf884cd9e07ceadbd68Dmitri Belimov } 6220dead8da8b383004e66eaf884cd9e07ceadbd68Dmitri Belimov 6320dead8da8b383004e66eaf884cd9e07ceadbd68Dmitri Belimov /* capture mutex */ 6420dead8da8b383004e66eaf884cd9e07ceadbd68Dmitri Belimov rc = tm6000_read_write_usb(dev, USB_DIR_OUT | USB_TYPE_VENDOR | 6520dead8da8b383004e66eaf884cd9e07ceadbd68Dmitri Belimov USB_RECIP_DEVICE, REQ_16_SET_GET_I2C_WR1_RDN, 6620dead8da8b383004e66eaf884cd9e07ceadbd68Dmitri Belimov addr | reg << 8, 0, buf, len); 6720dead8da8b383004e66eaf884cd9e07ceadbd68Dmitri Belimov 6820dead8da8b383004e66eaf884cd9e07ceadbd68Dmitri Belimov if (rc < 0) { 6920dead8da8b383004e66eaf884cd9e07ceadbd68Dmitri Belimov /* release mutex */ 7020dead8da8b383004e66eaf884cd9e07ceadbd68Dmitri Belimov return rc; 7120dead8da8b383004e66eaf884cd9e07ceadbd68Dmitri Belimov } 7220dead8da8b383004e66eaf884cd9e07ceadbd68Dmitri Belimov 7320dead8da8b383004e66eaf884cd9e07ceadbd68Dmitri Belimov /* release mutex */ 7420dead8da8b383004e66eaf884cd9e07ceadbd68Dmitri Belimov return rc; 754e11502d4597c6252411dc1b5c16b47d08b5f246Stefan Ringel} 764e11502d4597c6252411dc1b5c16b47d08b5f246Stefan Ringel 774e11502d4597c6252411dc1b5c16b47d08b5f246Stefan Ringel/* Generic read - doesn't work fine with 16bit registers */ 784e11502d4597c6252411dc1b5c16b47d08b5f246Stefan Ringelstatic int tm6000_i2c_recv_regs(struct tm6000_core *dev, unsigned char addr, 794e11502d4597c6252411dc1b5c16b47d08b5f246Stefan Ringel __u8 reg, char *buf, int len) 804e11502d4597c6252411dc1b5c16b47d08b5f246Stefan Ringel{ 814e11502d4597c6252411dc1b5c16b47d08b5f246Stefan Ringel int rc; 8202512fe33e9162713cd522937aabc81fcd97ad74Stefan Ringel u8 b[2]; 8320dead8da8b383004e66eaf884cd9e07ceadbd68Dmitri Belimov unsigned int i2c_packet_limit = 16; 8420dead8da8b383004e66eaf884cd9e07ceadbd68Dmitri Belimov 8520dead8da8b383004e66eaf884cd9e07ceadbd68Dmitri Belimov if (dev->dev_type == TM6010) 8620dead8da8b383004e66eaf884cd9e07ceadbd68Dmitri Belimov i2c_packet_limit = 64; 8720dead8da8b383004e66eaf884cd9e07ceadbd68Dmitri Belimov 8820dead8da8b383004e66eaf884cd9e07ceadbd68Dmitri Belimov if (!buf) 8920dead8da8b383004e66eaf884cd9e07ceadbd68Dmitri Belimov return -1; 9020dead8da8b383004e66eaf884cd9e07ceadbd68Dmitri Belimov 9120dead8da8b383004e66eaf884cd9e07ceadbd68Dmitri Belimov if (len < 1 || len > i2c_packet_limit) { 9220dead8da8b383004e66eaf884cd9e07ceadbd68Dmitri Belimov printk(KERN_ERR "Incorrect length of i2c packet = %d, limit set to %d\n", 9320dead8da8b383004e66eaf884cd9e07ceadbd68Dmitri Belimov len, i2c_packet_limit); 9420dead8da8b383004e66eaf884cd9e07ceadbd68Dmitri Belimov return -1; 9520dead8da8b383004e66eaf884cd9e07ceadbd68Dmitri Belimov } 964e11502d4597c6252411dc1b5c16b47d08b5f246Stefan Ringel 9720dead8da8b383004e66eaf884cd9e07ceadbd68Dmitri Belimov /* capture mutex */ 9802512fe33e9162713cd522937aabc81fcd97ad74Stefan Ringel if ((dev->caps.has_zl10353) && (dev->demod_addr << 1 == addr) && (reg % 2 == 0)) { 9902512fe33e9162713cd522937aabc81fcd97ad74Stefan Ringel /* 10002512fe33e9162713cd522937aabc81fcd97ad74Stefan Ringel * Workaround an I2C bug when reading from zl10353 10102512fe33e9162713cd522937aabc81fcd97ad74Stefan Ringel */ 10202512fe33e9162713cd522937aabc81fcd97ad74Stefan Ringel reg -= 1; 10302512fe33e9162713cd522937aabc81fcd97ad74Stefan Ringel len += 1; 10402512fe33e9162713cd522937aabc81fcd97ad74Stefan Ringel 10502512fe33e9162713cd522937aabc81fcd97ad74Stefan Ringel rc = tm6000_read_write_usb(dev, USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, 10602512fe33e9162713cd522937aabc81fcd97ad74Stefan Ringel REQ_16_SET_GET_I2C_WR1_RDN, addr | reg << 8, 0, b, len); 10702512fe33e9162713cd522937aabc81fcd97ad74Stefan Ringel 10802512fe33e9162713cd522937aabc81fcd97ad74Stefan Ringel *buf = b[1]; 10902512fe33e9162713cd522937aabc81fcd97ad74Stefan Ringel } else { 11002512fe33e9162713cd522937aabc81fcd97ad74Stefan Ringel rc = tm6000_read_write_usb(dev, USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, 1114e11502d4597c6252411dc1b5c16b47d08b5f246Stefan Ringel REQ_16_SET_GET_I2C_WR1_RDN, addr | reg << 8, 0, buf, len); 11202512fe33e9162713cd522937aabc81fcd97ad74Stefan Ringel } 1134e11502d4597c6252411dc1b5c16b47d08b5f246Stefan Ringel 11420dead8da8b383004e66eaf884cd9e07ceadbd68Dmitri Belimov /* release mutex */ 1154e11502d4597c6252411dc1b5c16b47d08b5f246Stefan Ringel return rc; 1164e11502d4597c6252411dc1b5c16b47d08b5f246Stefan Ringel} 1174e11502d4597c6252411dc1b5c16b47d08b5f246Stefan Ringel 1184e11502d4597c6252411dc1b5c16b47d08b5f246Stefan Ringel/* 1194e11502d4597c6252411dc1b5c16b47d08b5f246Stefan Ringel * read from a 16bit register 1204e11502d4597c6252411dc1b5c16b47d08b5f246Stefan Ringel * for example xc2028, xc3028 or xc3028L 1214e11502d4597c6252411dc1b5c16b47d08b5f246Stefan Ringel */ 1224e11502d4597c6252411dc1b5c16b47d08b5f246Stefan Ringelstatic int tm6000_i2c_recv_regs16(struct tm6000_core *dev, unsigned char addr, 1234e11502d4597c6252411dc1b5c16b47d08b5f246Stefan Ringel __u16 reg, char *buf, int len) 1244e11502d4597c6252411dc1b5c16b47d08b5f246Stefan Ringel{ 12520dead8da8b383004e66eaf884cd9e07ceadbd68Dmitri Belimov int rc; 12620dead8da8b383004e66eaf884cd9e07ceadbd68Dmitri Belimov unsigned char ureg; 12720dead8da8b383004e66eaf884cd9e07ceadbd68Dmitri Belimov 12820dead8da8b383004e66eaf884cd9e07ceadbd68Dmitri Belimov if (!buf || len != 2) 12920dead8da8b383004e66eaf884cd9e07ceadbd68Dmitri Belimov return -1; 13020dead8da8b383004e66eaf884cd9e07ceadbd68Dmitri Belimov 13120dead8da8b383004e66eaf884cd9e07ceadbd68Dmitri Belimov /* capture mutex */ 13220dead8da8b383004e66eaf884cd9e07ceadbd68Dmitri Belimov if (dev->dev_type == TM6010) { 13320dead8da8b383004e66eaf884cd9e07ceadbd68Dmitri Belimov ureg = reg & 0xFF; 13420dead8da8b383004e66eaf884cd9e07ceadbd68Dmitri Belimov rc = tm6000_read_write_usb(dev, USB_DIR_OUT | USB_TYPE_VENDOR | 13520dead8da8b383004e66eaf884cd9e07ceadbd68Dmitri Belimov USB_RECIP_DEVICE, REQ_16_SET_GET_I2C_WR1_RDN, 13620dead8da8b383004e66eaf884cd9e07ceadbd68Dmitri Belimov addr | (reg & 0xFF00), 0, &ureg, 1); 13720dead8da8b383004e66eaf884cd9e07ceadbd68Dmitri Belimov 13820dead8da8b383004e66eaf884cd9e07ceadbd68Dmitri Belimov if (rc < 0) { 13920dead8da8b383004e66eaf884cd9e07ceadbd68Dmitri Belimov /* release mutex */ 14020dead8da8b383004e66eaf884cd9e07ceadbd68Dmitri Belimov return rc; 14120dead8da8b383004e66eaf884cd9e07ceadbd68Dmitri Belimov } 14220dead8da8b383004e66eaf884cd9e07ceadbd68Dmitri Belimov 14320dead8da8b383004e66eaf884cd9e07ceadbd68Dmitri Belimov rc = tm6000_read_write_usb(dev, USB_DIR_IN | USB_TYPE_VENDOR | 14420dead8da8b383004e66eaf884cd9e07ceadbd68Dmitri Belimov USB_RECIP_DEVICE, REQ_35_AFTEK_TUNER_READ, 14520dead8da8b383004e66eaf884cd9e07ceadbd68Dmitri Belimov reg, 0, buf, len); 14620dead8da8b383004e66eaf884cd9e07ceadbd68Dmitri Belimov } else { 14720dead8da8b383004e66eaf884cd9e07ceadbd68Dmitri Belimov rc = tm6000_read_write_usb(dev, USB_DIR_IN | USB_TYPE_VENDOR | 14820dead8da8b383004e66eaf884cd9e07ceadbd68Dmitri Belimov USB_RECIP_DEVICE, REQ_14_SET_GET_I2C_WR2_RDN, 14920dead8da8b383004e66eaf884cd9e07ceadbd68Dmitri Belimov addr, reg, buf, len); 15020dead8da8b383004e66eaf884cd9e07ceadbd68Dmitri Belimov } 15120dead8da8b383004e66eaf884cd9e07ceadbd68Dmitri Belimov 15220dead8da8b383004e66eaf884cd9e07ceadbd68Dmitri Belimov /* release mutex */ 15320dead8da8b383004e66eaf884cd9e07ceadbd68Dmitri Belimov return rc; 1544e11502d4597c6252411dc1b5c16b47d08b5f246Stefan Ringel} 1554e11502d4597c6252411dc1b5c16b47d08b5f246Stefan Ringel 1569701dc94a14e54a33c3c99744ec3a761f6385fc6Mauro Carvalho Chehabstatic int tm6000_i2c_xfer(struct i2c_adapter *i2c_adap, 1579701dc94a14e54a33c3c99744ec3a761f6385fc6Mauro Carvalho Chehab struct i2c_msg msgs[], int num) 1589701dc94a14e54a33c3c99744ec3a761f6385fc6Mauro Carvalho Chehab{ 1599701dc94a14e54a33c3c99744ec3a761f6385fc6Mauro Carvalho Chehab struct tm6000_core *dev = i2c_adap->algo_data; 1609701dc94a14e54a33c3c99744ec3a761f6385fc6Mauro Carvalho Chehab int addr, rc, i, byte; 1619701dc94a14e54a33c3c99744ec3a761f6385fc6Mauro Carvalho Chehab 1629701dc94a14e54a33c3c99744ec3a761f6385fc6Mauro Carvalho Chehab if (num <= 0) 1639701dc94a14e54a33c3c99744ec3a761f6385fc6Mauro Carvalho Chehab return 0; 1649701dc94a14e54a33c3c99744ec3a761f6385fc6Mauro Carvalho Chehab for (i = 0; i < num; i++) { 165e30b9d6c641dbd9687a5605b2151a2a83d2e8770Chris Pascoe addr = (msgs[i].addr << 1) & 0xff; 16652e0a72a0c6f61c26a16b5684f4eb30a6fbf8b83Timofey Trofimov i2c_dprintk(2, "%s %s addr=0x%x len=%d:", 1679701dc94a14e54a33c3c99744ec3a761f6385fc6Mauro Carvalho Chehab (msgs[i].flags & I2C_M_RD) ? "read" : "write", 1689701dc94a14e54a33c3c99744ec3a761f6385fc6Mauro Carvalho Chehab i == num - 1 ? "stop" : "nonstop", addr, msgs[i].len); 169427f7facb374b8651ff01b7700e690ef8ccae159Mauro Carvalho Chehab if (msgs[i].flags & I2C_M_RD) { 170e30b9d6c641dbd9687a5605b2151a2a83d2e8770Chris Pascoe /* read request without preceding register selection */ 171e30b9d6c641dbd9687a5605b2151a2a83d2e8770Chris Pascoe /* 172e30b9d6c641dbd9687a5605b2151a2a83d2e8770Chris Pascoe * The TM6000 only supports a read transaction 173e30b9d6c641dbd9687a5605b2151a2a83d2e8770Chris Pascoe * immediately after a 1 or 2 byte write to select 174e30b9d6c641dbd9687a5605b2151a2a83d2e8770Chris Pascoe * a register. We cannot fulfil this request. 175e30b9d6c641dbd9687a5605b2151a2a83d2e8770Chris Pascoe */ 176e30b9d6c641dbd9687a5605b2151a2a83d2e8770Chris Pascoe i2c_dprintk(2, " read without preceding write not" 177e30b9d6c641dbd9687a5605b2151a2a83d2e8770Chris Pascoe " supported"); 178e30b9d6c641dbd9687a5605b2151a2a83d2e8770Chris Pascoe rc = -EOPNOTSUPP; 179e30b9d6c641dbd9687a5605b2151a2a83d2e8770Chris Pascoe goto err; 180e30b9d6c641dbd9687a5605b2151a2a83d2e8770Chris Pascoe } else if (i + 1 < num && msgs[i].len <= 2 && 181e30b9d6c641dbd9687a5605b2151a2a83d2e8770Chris Pascoe (msgs[i + 1].flags & I2C_M_RD) && 182e30b9d6c641dbd9687a5605b2151a2a83d2e8770Chris Pascoe msgs[i].addr == msgs[i + 1].addr) { 183e30b9d6c641dbd9687a5605b2151a2a83d2e8770Chris Pascoe /* 1 or 2 byte write followed by a read */ 184e30b9d6c641dbd9687a5605b2151a2a83d2e8770Chris Pascoe if (i2c_debug >= 2) 185e30b9d6c641dbd9687a5605b2151a2a83d2e8770Chris Pascoe for (byte = 0; byte < msgs[i].len; byte++) 18645dbf0db5ac974fb699fec39330d01642dff98dcMauro Carvalho Chehab printk(KERN_CONT " %02x", msgs[i].buf[byte]); 187e30b9d6c641dbd9687a5605b2151a2a83d2e8770Chris Pascoe i2c_dprintk(2, "; joined to read %s len=%d:", 188e30b9d6c641dbd9687a5605b2151a2a83d2e8770Chris Pascoe i == num - 2 ? "stop" : "nonstop", 189e30b9d6c641dbd9687a5605b2151a2a83d2e8770Chris Pascoe msgs[i + 1].len); 1904e11502d4597c6252411dc1b5c16b47d08b5f246Stefan Ringel 1914e11502d4597c6252411dc1b5c16b47d08b5f246Stefan Ringel if (msgs[i].len == 2) { 1924e11502d4597c6252411dc1b5c16b47d08b5f246Stefan Ringel rc = tm6000_i2c_recv_regs16(dev, addr, 1934e11502d4597c6252411dc1b5c16b47d08b5f246Stefan Ringel msgs[i].buf[0] << 8 | msgs[i].buf[1], 1944e11502d4597c6252411dc1b5c16b47d08b5f246Stefan Ringel msgs[i + 1].buf, msgs[i + 1].len); 1954e11502d4597c6252411dc1b5c16b47d08b5f246Stefan Ringel } else { 1964e11502d4597c6252411dc1b5c16b47d08b5f246Stefan Ringel rc = tm6000_i2c_recv_regs(dev, addr, msgs[i].buf[0], 1974e11502d4597c6252411dc1b5c16b47d08b5f246Stefan Ringel msgs[i + 1].buf, msgs[i + 1].len); 1984e11502d4597c6252411dc1b5c16b47d08b5f246Stefan Ringel } 1994e11502d4597c6252411dc1b5c16b47d08b5f246Stefan Ringel 200cf9e1509c278c3d5005f222539813933e4dc345cChristopher Pascoe i++; 20120cabed421399a5f0f1b33742d765cbdfad4ac79Stefan Ringel 202685b122906069f9e7b9995bf2b128137c86b558cStefan Ringel if (addr == dev->tuner_addr << 1) { 203f1434f4e90cec0bc57616c2f5f7de6985d7920d9Stefan Ringel tm6000_set_reg(dev, REQ_50_SET_START, 0, 0); 204f1434f4e90cec0bc57616c2f5f7de6985d7920d9Stefan Ringel tm6000_set_reg(dev, REQ_51_SET_STOP, 0, 0); 20520cabed421399a5f0f1b33742d765cbdfad4ac79Stefan Ringel } 206e30b9d6c641dbd9687a5605b2151a2a83d2e8770Chris Pascoe if (i2c_debug >= 2) 207e30b9d6c641dbd9687a5605b2151a2a83d2e8770Chris Pascoe for (byte = 0; byte < msgs[i].len; byte++) 20845dbf0db5ac974fb699fec39330d01642dff98dcMauro Carvalho Chehab printk(KERN_CONT " %02x", msgs[i].buf[byte]); 2099701dc94a14e54a33c3c99744ec3a761f6385fc6Mauro Carvalho Chehab } else { 2109701dc94a14e54a33c3c99744ec3a761f6385fc6Mauro Carvalho Chehab /* write bytes */ 211e30b9d6c641dbd9687a5605b2151a2a83d2e8770Chris Pascoe if (i2c_debug >= 2) 2129701dc94a14e54a33c3c99744ec3a761f6385fc6Mauro Carvalho Chehab for (byte = 0; byte < msgs[i].len; byte++) 21345dbf0db5ac974fb699fec39330d01642dff98dcMauro Carvalho Chehab printk(KERN_CONT " %02x", msgs[i].buf[byte]); 2144e11502d4597c6252411dc1b5c16b47d08b5f246Stefan Ringel rc = tm6000_i2c_send_regs(dev, addr, msgs[i].buf[0], 215e30b9d6c641dbd9687a5605b2151a2a83d2e8770Chris Pascoe msgs[i].buf + 1, msgs[i].len - 1); 2169701dc94a14e54a33c3c99744ec3a761f6385fc6Mauro Carvalho Chehab } 217e30b9d6c641dbd9687a5605b2151a2a83d2e8770Chris Pascoe if (i2c_debug >= 2) 21845dbf0db5ac974fb699fec39330d01642dff98dcMauro Carvalho Chehab printk(KERN_CONT "\n"); 2199701dc94a14e54a33c3c99744ec3a761f6385fc6Mauro Carvalho Chehab if (rc < 0) 2209701dc94a14e54a33c3c99744ec3a761f6385fc6Mauro Carvalho Chehab goto err; 2219701dc94a14e54a33c3c99744ec3a761f6385fc6Mauro Carvalho Chehab } 2229701dc94a14e54a33c3c99744ec3a761f6385fc6Mauro Carvalho Chehab 2239701dc94a14e54a33c3c99744ec3a761f6385fc6Mauro Carvalho Chehab return num; 2249701dc94a14e54a33c3c99744ec3a761f6385fc6Mauro Carvalho Chehaberr: 22552e0a72a0c6f61c26a16b5684f4eb30a6fbf8b83Timofey Trofimov i2c_dprintk(2, " ERROR: %i\n", rc); 2269701dc94a14e54a33c3c99744ec3a761f6385fc6Mauro Carvalho Chehab return rc; 2279701dc94a14e54a33c3c99744ec3a761f6385fc6Mauro Carvalho Chehab} 2289701dc94a14e54a33c3c99744ec3a761f6385fc6Mauro Carvalho Chehab 229792bc09a9896dfbdac575ab4cdcd0f4db96d8ca1Mauro Carvalho Chehabstatic int tm6000_i2c_eeprom(struct tm6000_core *dev) 2309701dc94a14e54a33c3c99744ec3a761f6385fc6Mauro Carvalho Chehab{ 2319701dc94a14e54a33c3c99744ec3a761f6385fc6Mauro Carvalho Chehab int i, rc; 232792bc09a9896dfbdac575ab4cdcd0f4db96d8ca1Mauro Carvalho Chehab unsigned char *p = dev->eedata; 2339701dc94a14e54a33c3c99744ec3a761f6385fc6Mauro Carvalho Chehab unsigned char bytes[17]; 2349701dc94a14e54a33c3c99744ec3a761f6385fc6Mauro Carvalho Chehab 2359701dc94a14e54a33c3c99744ec3a761f6385fc6Mauro Carvalho Chehab dev->i2c_client.addr = 0xa0 >> 1; 236792bc09a9896dfbdac575ab4cdcd0f4db96d8ca1Mauro Carvalho Chehab dev->eedata_size = 0; 2379701dc94a14e54a33c3c99744ec3a761f6385fc6Mauro Carvalho Chehab 238d4e15bcd3de4bb5fccf5b1c0f512d57983c09623Mauro Carvalho Chehab bytes[16] = '\0'; 239792bc09a9896dfbdac575ab4cdcd0f4db96d8ca1Mauro Carvalho Chehab for (i = 0; i < sizeof(dev->eedata); ) { 240792bc09a9896dfbdac575ab4cdcd0f4db96d8ca1Mauro Carvalho Chehab *p = i; 241792bc09a9896dfbdac575ab4cdcd0f4db96d8ca1Mauro Carvalho Chehab rc = tm6000_i2c_recv_regs(dev, 0xa0, i, p, 1); 242d4e15bcd3de4bb5fccf5b1c0f512d57983c09623Mauro Carvalho Chehab if (rc < 1) { 243792bc09a9896dfbdac575ab4cdcd0f4db96d8ca1Mauro Carvalho Chehab if (p == dev->eedata) 244d4e15bcd3de4bb5fccf5b1c0f512d57983c09623Mauro Carvalho Chehab goto noeeprom; 245d4e15bcd3de4bb5fccf5b1c0f512d57983c09623Mauro Carvalho Chehab else { 2469701dc94a14e54a33c3c99744ec3a761f6385fc6Mauro Carvalho Chehab printk(KERN_WARNING 2479701dc94a14e54a33c3c99744ec3a761f6385fc6Mauro Carvalho Chehab "%s: i2c eeprom read error (err=%d)\n", 2489701dc94a14e54a33c3c99744ec3a761f6385fc6Mauro Carvalho Chehab dev->name, rc); 2499701dc94a14e54a33c3c99744ec3a761f6385fc6Mauro Carvalho Chehab } 250792bc09a9896dfbdac575ab4cdcd0f4db96d8ca1Mauro Carvalho Chehab return -EINVAL; 2519701dc94a14e54a33c3c99744ec3a761f6385fc6Mauro Carvalho Chehab } 252792bc09a9896dfbdac575ab4cdcd0f4db96d8ca1Mauro Carvalho Chehab dev->eedata_size++; 2539701dc94a14e54a33c3c99744ec3a761f6385fc6Mauro Carvalho Chehab p++; 2549701dc94a14e54a33c3c99744ec3a761f6385fc6Mauro Carvalho Chehab if (0 == (i % 16)) 2559701dc94a14e54a33c3c99744ec3a761f6385fc6Mauro Carvalho Chehab printk(KERN_INFO "%s: i2c eeprom %02x:", dev->name, i); 25645dbf0db5ac974fb699fec39330d01642dff98dcMauro Carvalho Chehab printk(KERN_CONT " %02x", dev->eedata[i]); 257792bc09a9896dfbdac575ab4cdcd0f4db96d8ca1Mauro Carvalho Chehab if ((dev->eedata[i] >= ' ') && (dev->eedata[i] <= 'z')) 258792bc09a9896dfbdac575ab4cdcd0f4db96d8ca1Mauro Carvalho Chehab bytes[i%16] = dev->eedata[i]; 25952e0a72a0c6f61c26a16b5684f4eb30a6fbf8b83Timofey Trofimov else 26052e0a72a0c6f61c26a16b5684f4eb30a6fbf8b83Timofey Trofimov bytes[i%16] = '.'; 261d4e15bcd3de4bb5fccf5b1c0f512d57983c09623Mauro Carvalho Chehab 262d4e15bcd3de4bb5fccf5b1c0f512d57983c09623Mauro Carvalho Chehab i++; 263d4e15bcd3de4bb5fccf5b1c0f512d57983c09623Mauro Carvalho Chehab 264d4e15bcd3de4bb5fccf5b1c0f512d57983c09623Mauro Carvalho Chehab if (0 == (i % 16)) { 265d4e15bcd3de4bb5fccf5b1c0f512d57983c09623Mauro Carvalho Chehab bytes[16] = '\0'; 26645dbf0db5ac974fb699fec39330d01642dff98dcMauro Carvalho Chehab printk(KERN_CONT " %s\n", bytes); 2679701dc94a14e54a33c3c99744ec3a761f6385fc6Mauro Carvalho Chehab } 2689701dc94a14e54a33c3c99744ec3a761f6385fc6Mauro Carvalho Chehab } 269d4e15bcd3de4bb5fccf5b1c0f512d57983c09623Mauro Carvalho Chehab if (0 != (i%16)) { 270d4e15bcd3de4bb5fccf5b1c0f512d57983c09623Mauro Carvalho Chehab bytes[i%16] = '\0'; 271d4e15bcd3de4bb5fccf5b1c0f512d57983c09623Mauro Carvalho Chehab for (i %= 16; i < 16; i++) 27245dbf0db5ac974fb699fec39330d01642dff98dcMauro Carvalho Chehab printk(KERN_CONT " "); 27345dbf0db5ac974fb699fec39330d01642dff98dcMauro Carvalho Chehab printk(KERN_CONT " %s\n", bytes); 2749701dc94a14e54a33c3c99744ec3a761f6385fc6Mauro Carvalho Chehab } 275d4e15bcd3de4bb5fccf5b1c0f512d57983c09623Mauro Carvalho Chehab 2769701dc94a14e54a33c3c99744ec3a761f6385fc6Mauro Carvalho Chehab return 0; 277d4e15bcd3de4bb5fccf5b1c0f512d57983c09623Mauro Carvalho Chehab 278d4e15bcd3de4bb5fccf5b1c0f512d57983c09623Mauro Carvalho Chehabnoeeprom: 279d4e15bcd3de4bb5fccf5b1c0f512d57983c09623Mauro Carvalho Chehab printk(KERN_INFO "%s: Huh, no eeprom present (err=%d)?\n", 280792bc09a9896dfbdac575ab4cdcd0f4db96d8ca1Mauro Carvalho Chehab dev->name, rc); 281792bc09a9896dfbdac575ab4cdcd0f4db96d8ca1Mauro Carvalho Chehab return -EINVAL; 2829701dc94a14e54a33c3c99744ec3a761f6385fc6Mauro Carvalho Chehab} 2839701dc94a14e54a33c3c99744ec3a761f6385fc6Mauro Carvalho Chehab 2849701dc94a14e54a33c3c99744ec3a761f6385fc6Mauro Carvalho Chehab/* ----------------------------------------------------------- */ 2859701dc94a14e54a33c3c99744ec3a761f6385fc6Mauro Carvalho Chehab 2869701dc94a14e54a33c3c99744ec3a761f6385fc6Mauro Carvalho Chehab/* 2879701dc94a14e54a33c3c99744ec3a761f6385fc6Mauro Carvalho Chehab * functionality() 2889701dc94a14e54a33c3c99744ec3a761f6385fc6Mauro Carvalho Chehab */ 2899701dc94a14e54a33c3c99744ec3a761f6385fc6Mauro Carvalho Chehabstatic u32 functionality(struct i2c_adapter *adap) 2909701dc94a14e54a33c3c99744ec3a761f6385fc6Mauro Carvalho Chehab{ 2919701dc94a14e54a33c3c99744ec3a761f6385fc6Mauro Carvalho Chehab return I2C_FUNC_SMBUS_EMUL; 2929701dc94a14e54a33c3c99744ec3a761f6385fc6Mauro Carvalho Chehab} 2939701dc94a14e54a33c3c99744ec3a761f6385fc6Mauro Carvalho Chehab 2947bd444ede7285cad4ed5047ff954432325fe7f95Jean Delvarestatic const struct i2c_algorithm tm6000_algo = { 2959701dc94a14e54a33c3c99744ec3a761f6385fc6Mauro Carvalho Chehab .master_xfer = tm6000_i2c_xfer, 2969701dc94a14e54a33c3c99744ec3a761f6385fc6Mauro Carvalho Chehab .functionality = functionality, 2979701dc94a14e54a33c3c99744ec3a761f6385fc6Mauro Carvalho Chehab}; 2989701dc94a14e54a33c3c99744ec3a761f6385fc6Mauro Carvalho Chehab 2999701dc94a14e54a33c3c99744ec3a761f6385fc6Mauro Carvalho Chehab/* ----------------------------------------------------------- */ 3009701dc94a14e54a33c3c99744ec3a761f6385fc6Mauro Carvalho Chehab 3019701dc94a14e54a33c3c99744ec3a761f6385fc6Mauro Carvalho Chehab/* 3029701dc94a14e54a33c3c99744ec3a761f6385fc6Mauro Carvalho Chehab * tm6000_i2c_register() 3039701dc94a14e54a33c3c99744ec3a761f6385fc6Mauro Carvalho Chehab * register i2c bus 3049701dc94a14e54a33c3c99744ec3a761f6385fc6Mauro Carvalho Chehab */ 3059701dc94a14e54a33c3c99744ec3a761f6385fc6Mauro Carvalho Chehabint tm6000_i2c_register(struct tm6000_core *dev) 3069701dc94a14e54a33c3c99744ec3a761f6385fc6Mauro Carvalho Chehab{ 3077bd444ede7285cad4ed5047ff954432325fe7f95Jean Delvare int rc; 308d4e15bcd3de4bb5fccf5b1c0f512d57983c09623Mauro Carvalho Chehab 3097bd444ede7285cad4ed5047ff954432325fe7f95Jean Delvare dev->i2c_adap.owner = THIS_MODULE; 3107bd444ede7285cad4ed5047ff954432325fe7f95Jean Delvare dev->i2c_adap.algo = &tm6000_algo; 3119701dc94a14e54a33c3c99744ec3a761f6385fc6Mauro Carvalho Chehab dev->i2c_adap.dev.parent = &dev->udev->dev; 3127bd444ede7285cad4ed5047ff954432325fe7f95Jean Delvare strlcpy(dev->i2c_adap.name, dev->name, sizeof(dev->i2c_adap.name)); 3139701dc94a14e54a33c3c99744ec3a761f6385fc6Mauro Carvalho Chehab dev->i2c_adap.algo_data = dev; 3147bd444ede7285cad4ed5047ff954432325fe7f95Jean Delvare i2c_set_adapdata(&dev->i2c_adap, &dev->v4l2_dev); 3157bd444ede7285cad4ed5047ff954432325fe7f95Jean Delvare rc = i2c_add_adapter(&dev->i2c_adap); 3167bd444ede7285cad4ed5047ff954432325fe7f95Jean Delvare if (rc) 3177bd444ede7285cad4ed5047ff954432325fe7f95Jean Delvare return rc; 3189701dc94a14e54a33c3c99744ec3a761f6385fc6Mauro Carvalho Chehab 3199701dc94a14e54a33c3c99744ec3a761f6385fc6Mauro Carvalho Chehab dev->i2c_client.adapter = &dev->i2c_adap; 3207bd444ede7285cad4ed5047ff954432325fe7f95Jean Delvare strlcpy(dev->i2c_client.name, "tm6000 internal", I2C_NAME_SIZE); 321792bc09a9896dfbdac575ab4cdcd0f4db96d8ca1Mauro Carvalho Chehab tm6000_i2c_eeprom(dev); 322d4e15bcd3de4bb5fccf5b1c0f512d57983c09623Mauro Carvalho Chehab 3239701dc94a14e54a33c3c99744ec3a761f6385fc6Mauro Carvalho Chehab return 0; 3249701dc94a14e54a33c3c99744ec3a761f6385fc6Mauro Carvalho Chehab} 3259701dc94a14e54a33c3c99744ec3a761f6385fc6Mauro Carvalho Chehab 3269701dc94a14e54a33c3c99744ec3a761f6385fc6Mauro Carvalho Chehab/* 3279701dc94a14e54a33c3c99744ec3a761f6385fc6Mauro Carvalho Chehab * tm6000_i2c_unregister() 3289701dc94a14e54a33c3c99744ec3a761f6385fc6Mauro Carvalho Chehab * unregister i2c_bus 3299701dc94a14e54a33c3c99744ec3a761f6385fc6Mauro Carvalho Chehab */ 3309701dc94a14e54a33c3c99744ec3a761f6385fc6Mauro Carvalho Chehabint tm6000_i2c_unregister(struct tm6000_core *dev) 3319701dc94a14e54a33c3c99744ec3a761f6385fc6Mauro Carvalho Chehab{ 3329701dc94a14e54a33c3c99744ec3a761f6385fc6Mauro Carvalho Chehab i2c_del_adapter(&dev->i2c_adap); 3339701dc94a14e54a33c3c99744ec3a761f6385fc6Mauro Carvalho Chehab return 0; 3349701dc94a14e54a33c3c99744ec3a761f6385fc6Mauro Carvalho Chehab} 335