394 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/*3 * Driver for the Auvitek AU0828 USB bridge4 *5 * Copyright (c) 2008 Steven Toth <stoth@linuxtv.org>6 */7 8#include "au0828.h"9 10#include <linux/module.h>11#include <linux/moduleparam.h>12#include <linux/init.h>13#include <linux/delay.h>14#include <linux/io.h>15 16#include "media/tuner.h"17#include <media/v4l2-common.h>18 19static int i2c_scan;20module_param(i2c_scan, int, 0444);21MODULE_PARM_DESC(i2c_scan, "scan i2c bus at insmod time");22 23#define I2C_WAIT_DELAY 2524#define I2C_WAIT_RETRY 100025 26static inline int i2c_slave_did_read_ack(struct i2c_adapter *i2c_adap)27{28 struct au0828_dev *dev = i2c_adap->algo_data;29 return au0828_read(dev, AU0828_I2C_STATUS_201) &30 AU0828_I2C_STATUS_NO_READ_ACK ? 0 : 1;31}32 33static int i2c_wait_read_ack(struct i2c_adapter *i2c_adap)34{35 int count;36 37 for (count = 0; count < I2C_WAIT_RETRY; count++) {38 if (!i2c_slave_did_read_ack(i2c_adap))39 break;40 udelay(I2C_WAIT_DELAY);41 }42 43 if (I2C_WAIT_RETRY == count)44 return 0;45 46 return 1;47}48 49static inline int i2c_is_read_busy(struct i2c_adapter *i2c_adap)50{51 struct au0828_dev *dev = i2c_adap->algo_data;52 return au0828_read(dev, AU0828_I2C_STATUS_201) &53 AU0828_I2C_STATUS_READ_DONE ? 0 : 1;54}55 56static int i2c_wait_read_done(struct i2c_adapter *i2c_adap)57{58 int count;59 60 for (count = 0; count < I2C_WAIT_RETRY; count++) {61 if (!i2c_is_read_busy(i2c_adap))62 break;63 udelay(I2C_WAIT_DELAY);64 }65 66 if (I2C_WAIT_RETRY == count)67 return 0;68 69 return 1;70}71 72static inline int i2c_is_write_done(struct i2c_adapter *i2c_adap)73{74 struct au0828_dev *dev = i2c_adap->algo_data;75 return au0828_read(dev, AU0828_I2C_STATUS_201) &76 AU0828_I2C_STATUS_WRITE_DONE ? 1 : 0;77}78 79static int i2c_wait_write_done(struct i2c_adapter *i2c_adap)80{81 int count;82 83 for (count = 0; count < I2C_WAIT_RETRY; count++) {84 if (i2c_is_write_done(i2c_adap))85 break;86 udelay(I2C_WAIT_DELAY);87 }88 89 if (I2C_WAIT_RETRY == count)90 return 0;91 92 return 1;93}94 95static inline int i2c_is_busy(struct i2c_adapter *i2c_adap)96{97 struct au0828_dev *dev = i2c_adap->algo_data;98 return au0828_read(dev, AU0828_I2C_STATUS_201) &99 AU0828_I2C_STATUS_BUSY ? 1 : 0;100}101 102static int i2c_wait_done(struct i2c_adapter *i2c_adap)103{104 int count;105 106 for (count = 0; count < I2C_WAIT_RETRY; count++) {107 if (!i2c_is_busy(i2c_adap))108 break;109 udelay(I2C_WAIT_DELAY);110 }111 112 if (I2C_WAIT_RETRY == count)113 return 0;114 115 return 1;116}117 118/* FIXME: Implement join handling correctly */119static int i2c_sendbytes(struct i2c_adapter *i2c_adap,120 const struct i2c_msg *msg, int joined_rlen)121{122 int i, strobe = 0;123 struct au0828_dev *dev = i2c_adap->algo_data;124 u8 i2c_speed = dev->board.i2c_clk_divider;125 126 dprintk(4, "%s()\n", __func__);127 128 au0828_write(dev, AU0828_I2C_MULTIBYTE_MODE_2FF, 0x01);129 130 if (((dev->board.tuner_type == TUNER_XC5000) ||131 (dev->board.tuner_type == TUNER_XC5000C)) &&132 (dev->board.tuner_addr == msg->addr)) {133 /*134 * Due to I2C clock stretch, we need to use a lower speed135 * on xc5000 for commands. However, firmware transfer can136 * speed up to 400 KHz.137 */138 if (msg->len == 64)139 i2c_speed = AU0828_I2C_CLK_250KHZ;140 else141 i2c_speed = AU0828_I2C_CLK_20KHZ;142 }143 /* Set the I2C clock */144 au0828_write(dev, AU0828_I2C_CLK_DIVIDER_202, i2c_speed);145 146 /* Hardware needs 8 bit addresses */147 au0828_write(dev, AU0828_I2C_DEST_ADDR_203, msg->addr << 1);148 149 dprintk(4, "SEND: %02x\n", msg->addr);150 151 /* Deal with i2c_scan */152 if (msg->len == 0) {153 /* The analog tuner detection code makes use of the SMBUS_QUICK154 message (which involves a zero length i2c write). To avoid155 checking the status register when we didn't strobe out any156 actual bytes to the bus, just do a read check. This is157 consistent with how I saw i2c device checking done in the158 USB trace of the Windows driver */159 au0828_write(dev, AU0828_I2C_TRIGGER_200,160 AU0828_I2C_TRIGGER_READ);161 162 if (!i2c_wait_done(i2c_adap))163 return -EIO;164 165 if (i2c_wait_read_ack(i2c_adap))166 return -EIO;167 168 return 0;169 }170 171 for (i = 0; i < msg->len;) {172 173 dprintk(4, " %02x\n", msg->buf[i]);174 175 au0828_write(dev, AU0828_I2C_WRITE_FIFO_205, msg->buf[i]);176 177 strobe++;178 i++;179 180 if ((strobe >= 4) || (i >= msg->len)) {181 182 /* Strobe the byte into the bus */183 if (i < msg->len)184 au0828_write(dev, AU0828_I2C_TRIGGER_200,185 AU0828_I2C_TRIGGER_WRITE |186 AU0828_I2C_TRIGGER_HOLD);187 else188 au0828_write(dev, AU0828_I2C_TRIGGER_200,189 AU0828_I2C_TRIGGER_WRITE);190 191 /* Reset strobe trigger */192 strobe = 0;193 194 if (!i2c_wait_write_done(i2c_adap))195 return -EIO;196 197 }198 199 }200 if (!i2c_wait_done(i2c_adap))201 return -EIO;202 203 dprintk(4, "\n");204 205 return msg->len;206}207 208/* FIXME: Implement join handling correctly */209static int i2c_readbytes(struct i2c_adapter *i2c_adap,210 const struct i2c_msg *msg, int joined)211{212 struct au0828_dev *dev = i2c_adap->algo_data;213 u8 i2c_speed = dev->board.i2c_clk_divider;214 int i;215 216 dprintk(4, "%s()\n", __func__);217 218 au0828_write(dev, AU0828_I2C_MULTIBYTE_MODE_2FF, 0x01);219 220 /*221 * Due to xc5000c clock stretch, we cannot use full speed at222 * readings from xc5000, as otherwise they'll fail.223 */224 if (((dev->board.tuner_type == TUNER_XC5000) ||225 (dev->board.tuner_type == TUNER_XC5000C)) &&226 (dev->board.tuner_addr == msg->addr))227 i2c_speed = AU0828_I2C_CLK_20KHZ;228 229 /* Set the I2C clock */230 au0828_write(dev, AU0828_I2C_CLK_DIVIDER_202, i2c_speed);231 232 /* Hardware needs 8 bit addresses */233 au0828_write(dev, AU0828_I2C_DEST_ADDR_203, msg->addr << 1);234 235 dprintk(4, " RECV:\n");236 237 /* Deal with i2c_scan */238 if (msg->len == 0) {239 au0828_write(dev, AU0828_I2C_TRIGGER_200,240 AU0828_I2C_TRIGGER_READ);241 242 if (i2c_wait_read_ack(i2c_adap))243 return -EIO;244 return 0;245 }246 247 for (i = 0; i < msg->len;) {248 249 i++;250 251 if (i < msg->len)252 au0828_write(dev, AU0828_I2C_TRIGGER_200,253 AU0828_I2C_TRIGGER_READ |254 AU0828_I2C_TRIGGER_HOLD);255 else256 au0828_write(dev, AU0828_I2C_TRIGGER_200,257 AU0828_I2C_TRIGGER_READ);258 259 if (!i2c_wait_read_done(i2c_adap))260 return -EIO;261 262 msg->buf[i-1] = au0828_read(dev, AU0828_I2C_READ_FIFO_209) &263 0xff;264 265 dprintk(4, " %02x\n", msg->buf[i-1]);266 }267 if (!i2c_wait_done(i2c_adap))268 return -EIO;269 270 dprintk(4, "\n");271 272 return msg->len;273}274 275static int i2c_xfer(struct i2c_adapter *i2c_adap,276 struct i2c_msg *msgs, int num)277{278 int i, retval = 0;279 280 dprintk(4, "%s(num = %d)\n", __func__, num);281 282 for (i = 0; i < num; i++) {283 dprintk(4, "%s(num = %d) addr = 0x%02x len = 0x%x\n",284 __func__, num, msgs[i].addr, msgs[i].len);285 if (msgs[i].flags & I2C_M_RD) {286 /* read */287 retval = i2c_readbytes(i2c_adap, &msgs[i], 0);288 } else if (i + 1 < num && (msgs[i + 1].flags & I2C_M_RD) &&289 msgs[i].addr == msgs[i + 1].addr) {290 /* write then read from same address */291 retval = i2c_sendbytes(i2c_adap, &msgs[i],292 msgs[i + 1].len);293 if (retval < 0)294 goto err;295 i++;296 retval = i2c_readbytes(i2c_adap, &msgs[i], 1);297 } else {298 /* write */299 retval = i2c_sendbytes(i2c_adap, &msgs[i], 0);300 }301 if (retval < 0)302 goto err;303 }304 return num;305 306err:307 return retval;308}309 310static u32 au0828_functionality(struct i2c_adapter *adap)311{312 return I2C_FUNC_SMBUS_EMUL | I2C_FUNC_I2C;313}314 315static const struct i2c_algorithm au0828_i2c_algo_template = {316 .master_xfer = i2c_xfer,317 .functionality = au0828_functionality,318};319 320/* ----------------------------------------------------------------------- */321 322static const struct i2c_adapter au0828_i2c_adap_template = {323 .name = KBUILD_MODNAME,324 .owner = THIS_MODULE,325 .algo = &au0828_i2c_algo_template,326};327 328static const struct i2c_client au0828_i2c_client_template = {329 .name = "au0828 internal",330};331 332static char *i2c_devs[128] = {333 [0x8e >> 1] = "au8522",334 [0xa0 >> 1] = "eeprom",335 [0xc2 >> 1] = "tuner/xc5000",336};337 338static void do_i2c_scan(char *name, struct i2c_client *c)339{340 unsigned char buf;341 int i, rc;342 343 for (i = 0; i < 128; i++) {344 c->addr = i;345 rc = i2c_master_recv(c, &buf, 0);346 if (rc < 0)347 continue;348 pr_info("%s: i2c scan: found device @ 0x%x [%s]\n",349 name, i << 1, i2c_devs[i] ? i2c_devs[i] : "???");350 }351}352 353/* init + register i2c adapter */354int au0828_i2c_register(struct au0828_dev *dev)355{356 dprintk(1, "%s()\n", __func__);357 358 dev->i2c_adap = au0828_i2c_adap_template;359 dev->i2c_algo = au0828_i2c_algo_template;360 dev->i2c_client = au0828_i2c_client_template;361 362 dev->i2c_adap.dev.parent = &dev->usbdev->dev;363 364 strscpy(dev->i2c_adap.name, KBUILD_MODNAME,365 sizeof(dev->i2c_adap.name));366 367 dev->i2c_adap.algo = &dev->i2c_algo;368 dev->i2c_adap.algo_data = dev;369#ifdef CONFIG_VIDEO_AU0828_V4L2370 i2c_set_adapdata(&dev->i2c_adap, &dev->v4l2_dev);371#else372 i2c_set_adapdata(&dev->i2c_adap, dev);373#endif374 i2c_add_adapter(&dev->i2c_adap);375 376 dev->i2c_client.adapter = &dev->i2c_adap;377 378 if (0 == dev->i2c_rc) {379 pr_info("i2c bus registered\n");380 if (i2c_scan)381 do_i2c_scan(KBUILD_MODNAME, &dev->i2c_client);382 } else383 pr_info("i2c bus register FAILED\n");384 385 return dev->i2c_rc;386}387 388int au0828_i2c_unregister(struct au0828_dev *dev)389{390 i2c_del_adapter(&dev->i2c_adap);391 return 0;392}393 394