summaryrefslogtreecommitdiffstats
path: root/drivers/media/usb/dvb-usb-v2
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media/usb/dvb-usb-v2')
-rw-r--r--drivers/media/usb/dvb-usb-v2/af9015.c199
-rw-r--r--drivers/media/usb/dvb-usb-v2/af9015.h4
-rw-r--r--drivers/media/usb/dvb-usb-v2/lmedm04.c1
-rw-r--r--drivers/media/usb/dvb-usb-v2/mxl111sf-i2c.c4
-rw-r--r--drivers/media/usb/dvb-usb-v2/mxl111sf.c32
-rw-r--r--drivers/media/usb/dvb-usb-v2/mxl111sf.h8
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...) \
OpenPOWER on IntegriCloud