diff options
Diffstat (limited to 'drivers/media/usb/dvb-usb-v2')
-rw-r--r-- | drivers/media/usb/dvb-usb-v2/af9015.c | 199 | ||||
-rw-r--r-- | drivers/media/usb/dvb-usb-v2/af9015.h | 4 | ||||
-rw-r--r-- | drivers/media/usb/dvb-usb-v2/lmedm04.c | 1 | ||||
-rw-r--r-- | drivers/media/usb/dvb-usb-v2/mxl111sf-i2c.c | 4 | ||||
-rw-r--r-- | drivers/media/usb/dvb-usb-v2/mxl111sf.c | 32 | ||||
-rw-r--r-- | drivers/media/usb/dvb-usb-v2/mxl111sf.h | 8 |
6 files changed, 140 insertions, 108 deletions
diff --git a/drivers/media/usb/dvb-usb-v2/af9015.c b/drivers/media/usb/dvb-usb-v2/af9015.c index caa1e6101f58..23bbbf367b51 100644 --- a/drivers/media/usb/dvb-usb-v2/af9015.c +++ b/drivers/media/usb/dvb-usb-v2/af9015.c @@ -36,7 +36,7 @@ static int af9015_ctrl_msg(struct dvb_usb_device *d, struct req_t *req) state->buf[0] = req->cmd; state->buf[1] = state->seq++; - state->buf[2] = req->i2c_addr; + state->buf[2] = req->i2c_addr << 1; state->buf[3] = req->addr >> 8; state->buf[4] = req->addr & 0xff; state->buf[5] = req->mbox; @@ -52,6 +52,7 @@ static int af9015_ctrl_msg(struct dvb_usb_device *d, struct req_t *req) case READ_I2C: write = 0; state->buf[2] |= 0x01; /* set I2C direction */ + /* fall through */ case WRITE_I2C: state->buf[0] = READ_WRITE_I2C; break; @@ -205,9 +206,9 @@ static int af9015_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[], { struct dvb_usb_device *d = i2c_get_adapdata(adap); struct af9015_state *state = d_to_priv(d); - int ret = 0, i = 0; + int ret; u16 addr; - u8 uninitialized_var(mbox), addr_len; + u8 mbox, addr_len; struct req_t req; /* @@ -232,84 +233,89 @@ Due to that the only way to select correct tuner is use demodulator I2C-gate. | addr 0x3a | | addr 0xc6 | |____________| |____________| */ - if (mutex_lock_interruptible(&d->i2c_mutex) < 0) - return -EAGAIN; - while (i < num) { - if (msg[i].addr == state->af9013_config[0].i2c_addr || - msg[i].addr == state->af9013_config[1].i2c_addr) { - addr = msg[i].buf[0] << 8; - addr += msg[i].buf[1]; - mbox = msg[i].buf[2]; - addr_len = 3; - } else { - addr = msg[i].buf[0]; - addr_len = 1; - /* mbox is don't care in that case */ - } + if (msg[0].len == 0 || msg[0].flags & I2C_M_RD) { + addr = 0x0000; + mbox = 0; + addr_len = 0; + } else if (msg[0].len == 1) { + addr = msg[0].buf[0]; + mbox = 0; + addr_len = 1; + } else if (msg[0].len == 2) { + addr = msg[0].buf[0] << 8|msg[0].buf[1] << 0; + mbox = 0; + addr_len = 2; + } else { + addr = msg[0].buf[0] << 8|msg[0].buf[1] << 0; + mbox = msg[0].buf[2]; + addr_len = 3; + } - if (num > i + 1 && (msg[i+1].flags & I2C_M_RD)) { - if (msg[i].len > 3 || msg[i+1].len > 61) { - ret = -EOPNOTSUPP; - goto error; - } - if (msg[i].addr == state->af9013_config[0].i2c_addr) - req.cmd = READ_MEMORY; - else - req.cmd = READ_I2C; - req.i2c_addr = msg[i].addr; - req.addr = addr; - req.mbox = mbox; - req.addr_len = addr_len; - req.data_len = msg[i+1].len; - req.data = &msg[i+1].buf[0]; - ret = af9015_ctrl_msg(d, &req); - i += 2; - } else if (msg[i].flags & I2C_M_RD) { - if (msg[i].len > 61) { - ret = -EOPNOTSUPP; - goto error; - } - if (msg[i].addr == state->af9013_config[0].i2c_addr) { - ret = -EINVAL; - goto error; - } + if (num == 1 && !(msg[0].flags & I2C_M_RD)) { + /* i2c write */ + if (msg[0].len > 21) { + ret = -EOPNOTSUPP; + goto err; + } + if (msg[0].addr == state->af9013_config[0].i2c_addr) + req.cmd = WRITE_MEMORY; + else + req.cmd = WRITE_I2C; + req.i2c_addr = msg[0].addr; + req.addr = addr; + req.mbox = mbox; + req.addr_len = addr_len; + req.data_len = msg[0].len-addr_len; + req.data = &msg[0].buf[addr_len]; + ret = af9015_ctrl_msg(d, &req); + } else if (num == 2 && !(msg[0].flags & I2C_M_RD) && + (msg[1].flags & I2C_M_RD)) { + /* i2c write + read */ + if (msg[0].len > 3 || msg[1].len > 61) { + ret = -EOPNOTSUPP; + goto err; + } + if (msg[0].addr == state->af9013_config[0].i2c_addr) + req.cmd = READ_MEMORY; + else req.cmd = READ_I2C; - req.i2c_addr = msg[i].addr; - req.addr = addr; - req.mbox = mbox; - req.addr_len = addr_len; - req.data_len = msg[i].len; - req.data = &msg[i].buf[0]; - ret = af9015_ctrl_msg(d, &req); - i += 1; - } else { - if (msg[i].len > 21) { - ret = -EOPNOTSUPP; - goto error; - } - if (msg[i].addr == state->af9013_config[0].i2c_addr) - req.cmd = WRITE_MEMORY; - else - req.cmd = WRITE_I2C; - req.i2c_addr = msg[i].addr; - req.addr = addr; - req.mbox = mbox; - req.addr_len = addr_len; - req.data_len = msg[i].len-addr_len; - req.data = &msg[i].buf[addr_len]; - ret = af9015_ctrl_msg(d, &req); - i += 1; + req.i2c_addr = msg[0].addr; + req.addr = addr; + req.mbox = mbox; + req.addr_len = addr_len; + req.data_len = msg[1].len; + req.data = &msg[1].buf[0]; + ret = af9015_ctrl_msg(d, &req); + } else if (num == 1 && (msg[0].flags & I2C_M_RD)) { + /* i2c read */ + if (msg[0].len > 61) { + ret = -EOPNOTSUPP; + goto err; } - if (ret) - goto error; - + if (msg[0].addr == state->af9013_config[0].i2c_addr) { + ret = -EINVAL; + goto err; + } + req.cmd = READ_I2C; + req.i2c_addr = msg[0].addr; + req.addr = addr; + req.mbox = mbox; + req.addr_len = addr_len; + req.data_len = msg[0].len; + req.data = &msg[0].buf[0]; + ret = af9015_ctrl_msg(d, &req); + } else { + ret = -EOPNOTSUPP; + dev_dbg(&d->udev->dev, "%s: unknown msg, num %u\n", + __func__, num); } - ret = i; - -error: - mutex_unlock(&d->i2c_mutex); + if (ret) + goto err; + return num; +err: + dev_dbg(&d->udev->dev, "%s: failed %d\n", __func__, ret); return ret; } @@ -471,6 +477,8 @@ static int af9015_read_config(struct dvb_usb_device *d) if (d->udev->speed == USB_SPEED_FULL) state->dual_mode = 0; + state->af9013_config[0].i2c_addr = AF9015_I2C_DEMOD; + if (state->dual_mode) { /* read 2nd demodulator I2C address */ req.addr = AF9015_EEPROM_DEMOD2_I2C; @@ -478,7 +486,7 @@ static int af9015_read_config(struct dvb_usb_device *d) if (ret) goto error; - state->af9013_config[1].i2c_addr = val; + state->af9013_config[1].i2c_addr = val >> 1; } for (i = 0; i < state->dual_mode + 1; i++) { @@ -733,9 +741,6 @@ static int af9015_copy_firmware(struct dvb_usb_device *d) fw_params[2] = state->firmware_checksum >> 8; fw_params[3] = state->firmware_checksum & 0xff; - /* wait 2nd demodulator ready */ - msleep(100); - ret = af9015_read_reg_i2c(d, state->af9013_config[1].i2c_addr, 0x98be, &val); if (ret) @@ -823,6 +828,9 @@ static int af9015_af9013_frontend_attach(struct dvb_usb_adapter *adap) /* copy firmware to 2nd demodulator */ if (state->dual_mode) { + /* Wait 2nd demodulator ready */ + msleep(100); + ret = af9015_copy_firmware(adap_to_d(adap)); if (ret) { dev_err(&adap_to_d(adap)->udev->dev, @@ -870,12 +878,12 @@ static int af9015_af9013_frontend_attach(struct dvb_usb_adapter *adap) } static struct mt2060_config af9015_mt2060_config = { - .i2c_address = 0xc0, + .i2c_address = 0x60, .clock_out = 0, }; static struct qt1010_config af9015_qt1010_config = { - .i2c_address = 0xc4, + .i2c_address = 0x62, }; static struct tda18271_config af9015_tda18271_config = { @@ -884,7 +892,7 @@ static struct tda18271_config af9015_tda18271_config = { }; static struct mxl5005s_config af9015_mxl5003_config = { - .i2c_address = 0xc6, + .i2c_address = 0x63, .if_freq = IF_FREQ_4570000HZ, .xtal_freq = CRYSTAL_FREQ_16000000HZ, .agc_mode = MXL_SINGLE_AGC, @@ -901,7 +909,7 @@ static struct mxl5005s_config af9015_mxl5003_config = { }; static struct mxl5005s_config af9015_mxl5005_config = { - .i2c_address = 0xc6, + .i2c_address = 0x63, .if_freq = IF_FREQ_4570000HZ, .xtal_freq = CRYSTAL_FREQ_16000000HZ, .agc_mode = MXL_SINGLE_AGC, @@ -918,12 +926,12 @@ static struct mxl5005s_config af9015_mxl5005_config = { }; static struct mc44s803_config af9015_mc44s803_config = { - .i2c_address = 0xc0, + .i2c_address = 0x60, .dig_out = 1, }; static struct tda18218_config af9015_tda18218_config = { - .i2c_address = 0xc0, + .i2c_address = 0x60, .i2c_wr_max = 21, /* max wr bytes AF9015 I2C adap can handle at once */ }; @@ -954,7 +962,7 @@ static int af9015_tuner_attach(struct dvb_usb_adapter *adap) &af9015_qt1010_config) == NULL ? -ENODEV : 0; break; case AF9013_TUNER_TDA18271: - ret = dvb_attach(tda18271_attach, adap->fe[0], 0xc0, + ret = dvb_attach(tda18271_attach, adap->fe[0], 0x60, &adap_to_d(adap)->i2c_adap, &af9015_tda18271_config) == NULL ? -ENODEV : 0; break; @@ -975,7 +983,7 @@ static int af9015_tuner_attach(struct dvb_usb_adapter *adap) &af9015_mxl5005_config) == NULL ? -ENODEV : 0; break; case AF9013_TUNER_ENV77H11D5: - ret = dvb_attach(dvb_pll_attach, adap->fe[0], 0xc0, + ret = dvb_attach(dvb_pll_attach, adap->fe[0], 0x60, &adap_to_d(adap)->i2c_adap, DVB_PLL_TDA665X) == NULL ? -ENODEV : 0; break; @@ -987,7 +995,7 @@ static int af9015_tuner_attach(struct dvb_usb_adapter *adap) case AF9013_TUNER_MXL5007T: ret = dvb_attach(mxl5007t_attach, adap->fe[0], &adap_to_d(adap)->i2c_adap, - 0xc0, &af9015_mxl5007t_config) == NULL ? -ENODEV : 0; + 0x60, &af9015_mxl5007t_config) == NULL ? -ENODEV : 0; break; case AF9013_TUNER_UNKNOWN: default: @@ -1124,10 +1132,21 @@ static int af9015_init_endpoint(struct dvb_usb_device *d) } /* enable / disable mp2if2 */ - if (state->dual_mode) + if (state->dual_mode) { ret = af9015_set_reg_bit(d, 0xd50b, 0); - else + if (ret) + goto error; + ret = af9015_set_reg_bit(d, 0xd520, 4); + if (ret) + goto error; + } else { ret = af9015_clear_reg_bit(d, 0xd50b, 0); + if (ret) + goto error; + ret = af9015_clear_reg_bit(d, 0xd520, 4); + if (ret) + goto error; + } error: if (ret) diff --git a/drivers/media/usb/dvb-usb-v2/af9015.h b/drivers/media/usb/dvb-usb-v2/af9015.h index 2dd9231a8ece..3a9d9815ab7a 100644 --- a/drivers/media/usb/dvb-usb-v2/af9015.h +++ b/drivers/media/usb/dvb-usb-v2/af9015.h @@ -47,8 +47,8 @@ #define TS_USB20_MAX_PACKET_SIZE 512 #define TS_USB11_MAX_PACKET_SIZE 64 -#define AF9015_I2C_EEPROM 0xa0 -#define AF9015_I2C_DEMOD 0x38 +#define AF9015_I2C_EEPROM 0x50 +#define AF9015_I2C_DEMOD 0x1c #define AF9015_USB_TIMEOUT 2000 /* EEPROM locations */ diff --git a/drivers/media/usb/dvb-usb-v2/lmedm04.c b/drivers/media/usb/dvb-usb-v2/lmedm04.c index 924adfdb660d..594360a63c18 100644 --- a/drivers/media/usb/dvb-usb-v2/lmedm04.c +++ b/drivers/media/usb/dvb-usb-v2/lmedm04.c @@ -1065,6 +1065,7 @@ static int dm04_lme2510_frontend_attach(struct dvb_usb_adapter *adap) } break; } + /* fall through */ case 0x22f0: st->i2c_gate = 5; adap->fe[0] = dvb_attach(m88rs2000_attach, diff --git a/drivers/media/usb/dvb-usb-v2/mxl111sf-i2c.c b/drivers/media/usb/dvb-usb-v2/mxl111sf-i2c.c index ffb49c28b15a..0eb33e043079 100644 --- a/drivers/media/usb/dvb-usb-v2/mxl111sf-i2c.c +++ b/drivers/media/usb/dvb-usb-v2/mxl111sf-i2c.c @@ -316,7 +316,7 @@ fail: static int mxl111sf_i2c_send_data(struct mxl111sf_state *state, u8 index, u8 *wdata) { - int ret = mxl111sf_ctrl_msg(state->d, wdata[0], + int ret = mxl111sf_ctrl_msg(state, wdata[0], &wdata[1], 25, NULL, 0); mxl_fail(ret); @@ -326,7 +326,7 @@ static int mxl111sf_i2c_send_data(struct mxl111sf_state *state, static int mxl111sf_i2c_get_data(struct mxl111sf_state *state, u8 index, u8 *wdata, u8 *rdata) { - int ret = mxl111sf_ctrl_msg(state->d, wdata[0], + int ret = mxl111sf_ctrl_msg(state, wdata[0], &wdata[1], 25, rdata, 24); mxl_fail(ret); diff --git a/drivers/media/usb/dvb-usb-v2/mxl111sf.c b/drivers/media/usb/dvb-usb-v2/mxl111sf.c index abf69d8fa469..b0d5904a4ea6 100644 --- a/drivers/media/usb/dvb-usb-v2/mxl111sf.c +++ b/drivers/media/usb/dvb-usb-v2/mxl111sf.c @@ -24,9 +24,6 @@ #include "lgdt3305.h" #include "lg2160.h" -/* Max transfer size done by I2C transfer functions */ -#define MAX_XFER_SIZE 64 - int dvb_usb_mxl111sf_debug; module_param_named(debug, dvb_usb_mxl111sf_debug, int, 0644); MODULE_PARM_DESC(debug, "set debugging level (1=info, 2=xfer, 4=i2c, 8=reg, 16=adv (or-able))."); @@ -55,27 +52,34 @@ MODULE_PARM_DESC(rfswitch, "force rf switch position (0=auto, 1=ext, 2=int)."); DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); -int mxl111sf_ctrl_msg(struct dvb_usb_device *d, +int mxl111sf_ctrl_msg(struct mxl111sf_state *state, u8 cmd, u8 *wbuf, int wlen, u8 *rbuf, int rlen) { + struct dvb_usb_device *d = state->d; int wo = (rbuf == NULL || rlen == 0); /* write-only */ int ret; - u8 sndbuf[MAX_XFER_SIZE]; - if (1 + wlen > sizeof(sndbuf)) { + if (1 + wlen > MXL_MAX_XFER_SIZE) { pr_warn("%s: len=%d is too big!\n", __func__, wlen); return -EOPNOTSUPP; } pr_debug("%s(wlen = %d, rlen = %d)\n", __func__, wlen, rlen); - memset(sndbuf, 0, 1+wlen); + mutex_lock(&state->msg_lock); + memset(state->sndbuf, 0, 1+wlen); + memset(state->rcvbuf, 0, rlen); + + state->sndbuf[0] = cmd; + memcpy(&state->sndbuf[1], wbuf, wlen); - sndbuf[0] = cmd; - memcpy(&sndbuf[1], wbuf, wlen); + ret = (wo) ? dvb_usbv2_generic_write(d, state->sndbuf, 1+wlen) : + dvb_usbv2_generic_rw(d, state->sndbuf, 1+wlen, state->rcvbuf, + rlen); + + memcpy(rbuf, state->rcvbuf, rlen); + mutex_unlock(&state->msg_lock); - ret = (wo) ? dvb_usbv2_generic_write(d, sndbuf, 1+wlen) : - dvb_usbv2_generic_rw(d, sndbuf, 1+wlen, rbuf, rlen); mxl_fail(ret); return ret; @@ -91,7 +95,7 @@ int mxl111sf_read_reg(struct mxl111sf_state *state, u8 addr, u8 *data) u8 buf[2]; int ret; - ret = mxl111sf_ctrl_msg(state->d, MXL_CMD_REG_READ, &addr, 1, buf, 2); + ret = mxl111sf_ctrl_msg(state, MXL_CMD_REG_READ, &addr, 1, buf, 2); if (mxl_fail(ret)) { mxl_debug("error reading reg: 0x%02x", addr); goto fail; @@ -117,7 +121,7 @@ int mxl111sf_write_reg(struct mxl111sf_state *state, u8 addr, u8 data) pr_debug("W: (0x%02x, 0x%02x)\n", addr, data); - ret = mxl111sf_ctrl_msg(state->d, MXL_CMD_REG_WRITE, buf, 2, NULL, 0); + ret = mxl111sf_ctrl_msg(state, MXL_CMD_REG_WRITE, buf, 2, NULL, 0); if (mxl_fail(ret)) pr_err("error writing reg: 0x%02x, val: 0x%02x", addr, data); return ret; @@ -926,6 +930,8 @@ static int mxl111sf_init(struct dvb_usb_device *d) .len = sizeof(eeprom), .buf = eeprom }, }; + mutex_init(&state->msg_lock); + ret = get_chip_info(state); if (mxl_fail(ret)) pr_err("failed to get chip info during probe"); diff --git a/drivers/media/usb/dvb-usb-v2/mxl111sf.h b/drivers/media/usb/dvb-usb-v2/mxl111sf.h index 846260e0eec0..3e6f5880bd1e 100644 --- a/drivers/media/usb/dvb-usb-v2/mxl111sf.h +++ b/drivers/media/usb/dvb-usb-v2/mxl111sf.h @@ -19,6 +19,9 @@ #include <media/tveeprom.h> #include <media/media-entity.h> +/* Max transfer size done by I2C transfer functions */ +#define MXL_MAX_XFER_SIZE 64 + #define MXL_EP1_REG_READ 1 #define MXL_EP2_REG_WRITE 2 #define MXL_EP3_INTERRUPT 3 @@ -86,6 +89,9 @@ struct mxl111sf_state { struct mutex fe_lock; u8 num_frontends; struct mxl111sf_adap_state adap_state[3]; + u8 sndbuf[MXL_MAX_XFER_SIZE]; + u8 rcvbuf[MXL_MAX_XFER_SIZE]; + struct mutex msg_lock; #ifdef CONFIG_MEDIA_CONTROLLER_DVB struct media_entity tuner; struct media_pad tuner_pads[2]; @@ -108,7 +114,7 @@ int mxl111sf_ctrl_program_regs(struct mxl111sf_state *state, /* needed for hardware i2c functions in mxl111sf-i2c.c: * mxl111sf_i2c_send_data / mxl111sf_i2c_get_data */ -int mxl111sf_ctrl_msg(struct dvb_usb_device *d, +int mxl111sf_ctrl_msg(struct mxl111sf_state *state, u8 cmd, u8 *wbuf, int wlen, u8 *rbuf, int rlen); #define mxl_printk(kern, fmt, arg...) \ |