375 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/*3 * Driver for the Conexant CX23885 PCIe bridge4 *5 * Copyright (c) 2006 Steven Toth <stoth@linuxtv.org>6 */7 8#include "cx23885.h"9 10#include <linux/module.h>11#include <linux/init.h>12#include <linux/delay.h>13#include <asm/io.h>14 15#include <media/v4l2-common.h>16 17static unsigned int i2c_debug;18module_param(i2c_debug, int, 0644);19MODULE_PARM_DESC(i2c_debug, "enable debug messages [i2c]");20 21static unsigned int i2c_scan;22module_param(i2c_scan, int, 0444);23MODULE_PARM_DESC(i2c_scan, "scan i2c bus at insmod time");24 25#define dprintk(level, fmt, arg...)\26 do { if (i2c_debug >= level)\27 printk(KERN_DEBUG pr_fmt("%s: i2c:" fmt), \28 __func__, ##arg); \29 } while (0)30 31#define I2C_WAIT_DELAY 3232#define I2C_WAIT_RETRY 6433 34#define I2C_EXTEND (1 << 3)35#define I2C_NOSTOP (1 << 4)36 37static inline int i2c_slave_did_ack(struct i2c_adapter *i2c_adap)38{39 struct cx23885_i2c *bus = i2c_adap->algo_data;40 struct cx23885_dev *dev = bus->dev;41 return cx_read(bus->reg_stat) & 0x01;42}43 44static inline int i2c_is_busy(struct i2c_adapter *i2c_adap)45{46 struct cx23885_i2c *bus = i2c_adap->algo_data;47 struct cx23885_dev *dev = bus->dev;48 return cx_read(bus->reg_stat) & 0x02 ? 1 : 0;49}50 51static int i2c_wait_done(struct i2c_adapter *i2c_adap)52{53 int count;54 55 for (count = 0; count < I2C_WAIT_RETRY; count++) {56 if (!i2c_is_busy(i2c_adap))57 break;58 udelay(I2C_WAIT_DELAY);59 }60 61 if (I2C_WAIT_RETRY == count)62 return 0;63 64 return 1;65}66 67static int i2c_sendbytes(struct i2c_adapter *i2c_adap,68 const struct i2c_msg *msg, int joined_rlen)69{70 struct cx23885_i2c *bus = i2c_adap->algo_data;71 struct cx23885_dev *dev = bus->dev;72 u32 wdata, addr, ctrl;73 int retval, cnt;74 75 if (joined_rlen)76 dprintk(1, "%s(msg->wlen=%d, nextmsg->rlen=%d)\n", __func__,77 msg->len, joined_rlen);78 else79 dprintk(1, "%s(msg->len=%d)\n", __func__, msg->len);80 81 /* Deal with i2c probe functions with zero payload */82 if (msg->len == 0) {83 cx_write(bus->reg_addr, msg->addr << 25);84 cx_write(bus->reg_ctrl, bus->i2c_period | (1 << 2));85 if (!i2c_wait_done(i2c_adap))86 return -EIO;87 if (!i2c_slave_did_ack(i2c_adap))88 return -ENXIO;89 90 dprintk(1, "%s() returns 0\n", __func__);91 return 0;92 }93 94 95 /* dev, reg + first byte */96 addr = (msg->addr << 25) | msg->buf[0];97 wdata = msg->buf[0];98 ctrl = bus->i2c_period | (1 << 12) | (1 << 2);99 100 if (msg->len > 1)101 ctrl |= I2C_NOSTOP | I2C_EXTEND;102 else if (joined_rlen)103 ctrl |= I2C_NOSTOP;104 105 cx_write(bus->reg_addr, addr);106 cx_write(bus->reg_wdata, wdata);107 cx_write(bus->reg_ctrl, ctrl);108 109 if (!i2c_wait_done(i2c_adap))110 goto eio;111 if (i2c_debug) {112 printk(KERN_DEBUG " <W %02x %02x", msg->addr << 1, msg->buf[0]);113 if (!(ctrl & I2C_NOSTOP))114 pr_cont(" >\n");115 }116 117 for (cnt = 1; cnt < msg->len; cnt++) {118 /* following bytes */119 wdata = msg->buf[cnt];120 ctrl = bus->i2c_period | (1 << 12) | (1 << 2);121 122 if (cnt < msg->len - 1)123 ctrl |= I2C_NOSTOP | I2C_EXTEND;124 else if (joined_rlen)125 ctrl |= I2C_NOSTOP;126 127 cx_write(bus->reg_addr, addr);128 cx_write(bus->reg_wdata, wdata);129 cx_write(bus->reg_ctrl, ctrl);130 131 if (!i2c_wait_done(i2c_adap))132 goto eio;133 if (i2c_debug) {134 pr_cont(" %02x", msg->buf[cnt]);135 if (!(ctrl & I2C_NOSTOP))136 pr_cont(" >\n");137 }138 }139 return msg->len;140 141 eio:142 retval = -EIO;143 if (i2c_debug)144 pr_err(" ERR: %d\n", retval);145 return retval;146}147 148static int i2c_readbytes(struct i2c_adapter *i2c_adap,149 const struct i2c_msg *msg, int joined)150{151 struct cx23885_i2c *bus = i2c_adap->algo_data;152 struct cx23885_dev *dev = bus->dev;153 u32 ctrl, cnt;154 int retval;155 156 157 if (i2c_debug && !joined)158 dprintk(1, "%s(msg->len=%d)\n", __func__, msg->len);159 160 /* Deal with i2c probe functions with zero payload */161 if (msg->len == 0) {162 cx_write(bus->reg_addr, msg->addr << 25);163 cx_write(bus->reg_ctrl, bus->i2c_period | (1 << 2) | 1);164 if (!i2c_wait_done(i2c_adap))165 return -EIO;166 if (!i2c_slave_did_ack(i2c_adap))167 return -ENXIO;168 169 170 dprintk(1, "%s() returns 0\n", __func__);171 return 0;172 }173 174 if (i2c_debug) {175 if (joined)176 dprintk(1, " R");177 else178 dprintk(1, " <R %02x", (msg->addr << 1) + 1);179 }180 181 for (cnt = 0; cnt < msg->len; cnt++) {182 183 ctrl = bus->i2c_period | (1 << 12) | (1 << 2) | 1;184 185 if (cnt < msg->len - 1)186 ctrl |= I2C_NOSTOP | I2C_EXTEND;187 188 cx_write(bus->reg_addr, msg->addr << 25);189 cx_write(bus->reg_ctrl, ctrl);190 191 if (!i2c_wait_done(i2c_adap))192 goto eio;193 msg->buf[cnt] = cx_read(bus->reg_rdata) & 0xff;194 if (i2c_debug) {195 dprintk(1, " %02x", msg->buf[cnt]);196 if (!(ctrl & I2C_NOSTOP))197 dprintk(1, " >\n");198 }199 }200 return msg->len;201 202 eio:203 retval = -EIO;204 if (i2c_debug)205 pr_err(" ERR: %d\n", retval);206 return retval;207}208 209static int i2c_xfer(struct i2c_adapter *i2c_adap,210 struct i2c_msg *msgs, int num)211{212 int i, retval = 0;213 214 dprintk(1, "%s(num = %d)\n", __func__, num);215 216 for (i = 0 ; i < num; i++) {217 dprintk(1, "%s(num = %d) addr = 0x%02x len = 0x%x\n",218 __func__, num, msgs[i].addr, msgs[i].len);219 if (msgs[i].flags & I2C_M_RD) {220 /* read */221 retval = i2c_readbytes(i2c_adap, &msgs[i], 0);222 } else if (i + 1 < num && (msgs[i + 1].flags & I2C_M_RD) &&223 msgs[i].addr == msgs[i + 1].addr) {224 /* write then read from same address */225 retval = i2c_sendbytes(i2c_adap, &msgs[i],226 msgs[i + 1].len);227 if (retval < 0)228 goto err;229 i++;230 retval = i2c_readbytes(i2c_adap, &msgs[i], 1);231 } else {232 /* write */233 retval = i2c_sendbytes(i2c_adap, &msgs[i], 0);234 }235 if (retval < 0)236 goto err;237 }238 return num;239 240 err:241 return retval;242}243 244static u32 cx23885_functionality(struct i2c_adapter *adap)245{246 return I2C_FUNC_SMBUS_EMUL | I2C_FUNC_I2C;247}248 249static const struct i2c_algorithm cx23885_i2c_algo_template = {250 .master_xfer = i2c_xfer,251 .functionality = cx23885_functionality,252};253 254/* ----------------------------------------------------------------------- */255 256static const struct i2c_adapter cx23885_i2c_adap_template = {257 .name = "cx23885",258 .owner = THIS_MODULE,259 .algo = &cx23885_i2c_algo_template,260};261 262static const struct i2c_client cx23885_i2c_client_template = {263 .name = "cx23885 internal",264};265 266static char *i2c_devs[128] = {267 [0x10 >> 1] = "tda10048",268 [0x12 >> 1] = "dib7000pc",269 [0x1c >> 1] = "lgdt3303",270 [0x80 >> 1] = "cs3308",271 [0x82 >> 1] = "cs3308",272 [0x86 >> 1] = "tda9887",273 [0x32 >> 1] = "cx24227",274 [0x88 >> 1] = "cx25837",275 [0x84 >> 1] = "tda8295",276 [0x98 >> 1] = "flatiron",277 [0xa0 >> 1] = "eeprom",278 [0xc0 >> 1] = "tuner/mt2131/tda8275",279 [0xc2 >> 1] = "tuner/mt2131/tda8275/xc5000/xc3028",280 [0xc8 >> 1] = "tuner/xc3028L",281};282 283static void do_i2c_scan(char *name, struct i2c_client *c)284{285 unsigned char buf;286 int i, rc;287 288 for (i = 0; i < 128; i++) {289 c->addr = i;290 rc = i2c_master_recv(c, &buf, 0);291 if (rc < 0)292 continue;293 pr_info("%s: i2c scan: found device @ 0x%04x [%s]\n",294 name, i, i2c_devs[i] ? i2c_devs[i] : "???");295 }296}297 298/* init + register i2c adapter */299int cx23885_i2c_register(struct cx23885_i2c *bus)300{301 struct cx23885_dev *dev = bus->dev;302 303 dprintk(1, "%s(bus = %d)\n", __func__, bus->nr);304 305 bus->i2c_adap = cx23885_i2c_adap_template;306 bus->i2c_client = cx23885_i2c_client_template;307 bus->i2c_adap.dev.parent = &dev->pci->dev;308 309 strscpy(bus->i2c_adap.name, bus->dev->name,310 sizeof(bus->i2c_adap.name));311 312 bus->i2c_adap.algo_data = bus;313 i2c_set_adapdata(&bus->i2c_adap, &dev->v4l2_dev);314 i2c_add_adapter(&bus->i2c_adap);315 316 bus->i2c_client.adapter = &bus->i2c_adap;317 318 if (0 == bus->i2c_rc) {319 dprintk(1, "%s: i2c bus %d registered\n", dev->name, bus->nr);320 if (i2c_scan) {321 pr_info("%s: scan bus %d:\n",322 dev->name, bus->nr);323 do_i2c_scan(dev->name, &bus->i2c_client);324 }325 } else326 pr_warn("%s: i2c bus %d register FAILED\n",327 dev->name, bus->nr);328 329 /* Instantiate the IR receiver device, if present */330 if (0 == bus->i2c_rc) {331 struct i2c_board_info info;332 static const unsigned short addr_list[] = {333 0x6b, I2C_CLIENT_END334 };335 336 memset(&info, 0, sizeof(struct i2c_board_info));337 strscpy(info.type, "ir_video", I2C_NAME_SIZE);338 /* Use quick read command for probe, some IR chips don't339 * support writes */340 i2c_new_scanned_device(&bus->i2c_adap, &info, addr_list,341 i2c_probe_func_quick_read);342 }343 344 return bus->i2c_rc;345}346 347int cx23885_i2c_unregister(struct cx23885_i2c *bus)348{349 i2c_del_adapter(&bus->i2c_adap);350 return 0;351}352 353void cx23885_av_clk(struct cx23885_dev *dev, int enable)354{355 /* write 0 to bus 2 addr 0x144 via i2x_xfer() */356 char buffer[3];357 struct i2c_msg msg;358 dprintk(1, "%s(enabled = %d)\n", __func__, enable);359 360 /* Register 0x144 */361 buffer[0] = 0x01;362 buffer[1] = 0x44;363 if (enable == 1)364 buffer[2] = 0x05;365 else366 buffer[2] = 0x00;367 368 msg.addr = 0x44;369 msg.flags = I2C_M_TEN;370 msg.len = 3;371 msg.buf = buffer;372 373 i2c_xfer(&dev->i2c_bus[2].i2c_adap, &msg, 1);374}375