forked from luck/tmp_suning_uos_patched
[media] DiBxxxx: get rid of DMA buffer on stack
This patch removes the remaining on-stack buffer for USB DMA transfer. This patch also reduces the stack memory usage. Cc: stable@kernel.org Cc: Florian Mickler <florian@mickler.org> Signed-off-by: Olivier Grenie <olivier.grenie@dibcom.fr> Signed-off-by: Patrick Boettcher <patrick.boettcher@dibcom.fr> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
This commit is contained in:
parent
027e99abbf
commit
5a0deeed57
@ -73,27 +73,47 @@ struct dib0070_state {
|
||||
|
||||
u8 wbd_gain_current;
|
||||
u16 wbd_offset_3_3[2];
|
||||
|
||||
/* for the I2C transfer */
|
||||
struct i2c_msg msg[2];
|
||||
u8 i2c_write_buffer[3];
|
||||
u8 i2c_read_buffer[2];
|
||||
};
|
||||
|
||||
static uint16_t dib0070_read_reg(struct dib0070_state *state, u8 reg)
|
||||
{
|
||||
u8 b[2];
|
||||
struct i2c_msg msg[2] = {
|
||||
{ .addr = state->cfg->i2c_address, .flags = 0, .buf = ®, .len = 1 },
|
||||
{ .addr = state->cfg->i2c_address, .flags = I2C_M_RD, .buf = b, .len = 2 },
|
||||
};
|
||||
if (i2c_transfer(state->i2c, msg, 2) != 2) {
|
||||
state->i2c_write_buffer[0] = reg;
|
||||
|
||||
memset(state->msg, 0, 2 * sizeof(struct i2c_msg));
|
||||
state->msg[0].addr = state->cfg->i2c_address;
|
||||
state->msg[0].flags = 0;
|
||||
state->msg[0].buf = state->i2c_write_buffer;
|
||||
state->msg[0].len = 1;
|
||||
state->msg[1].addr = state->cfg->i2c_address;
|
||||
state->msg[1].flags = I2C_M_RD;
|
||||
state->msg[1].buf = state->i2c_read_buffer;
|
||||
state->msg[1].len = 2;
|
||||
|
||||
if (i2c_transfer(state->i2c, state->msg, 2) != 2) {
|
||||
printk(KERN_WARNING "DiB0070 I2C read failed\n");
|
||||
return 0;
|
||||
}
|
||||
return (b[0] << 8) | b[1];
|
||||
return (state->i2c_read_buffer[0] << 8) | state->i2c_read_buffer[1];
|
||||
}
|
||||
|
||||
static int dib0070_write_reg(struct dib0070_state *state, u8 reg, u16 val)
|
||||
{
|
||||
u8 b[3] = { reg, val >> 8, val & 0xff };
|
||||
struct i2c_msg msg = { .addr = state->cfg->i2c_address, .flags = 0, .buf = b, .len = 3 };
|
||||
if (i2c_transfer(state->i2c, &msg, 1) != 1) {
|
||||
state->i2c_write_buffer[0] = reg;
|
||||
state->i2c_write_buffer[1] = val >> 8;
|
||||
state->i2c_write_buffer[2] = val & 0xff;
|
||||
|
||||
memset(state->msg, 0, sizeof(struct i2c_msg));
|
||||
state->msg[0].addr = state->cfg->i2c_address;
|
||||
state->msg[0].flags = 0;
|
||||
state->msg[0].buf = state->i2c_write_buffer;
|
||||
state->msg[0].len = 3;
|
||||
|
||||
if (i2c_transfer(state->i2c, state->msg, 1) != 1) {
|
||||
printk(KERN_WARNING "DiB0070 I2C write failed\n");
|
||||
return -EREMOTEIO;
|
||||
}
|
||||
|
@ -191,6 +191,11 @@ struct dib0090_state {
|
||||
u8 wbd_calibration_gain;
|
||||
const struct dib0090_wbd_slope *current_wbd_table;
|
||||
u16 wbdmux;
|
||||
|
||||
/* for the I2C transfer */
|
||||
struct i2c_msg msg[2];
|
||||
u8 i2c_write_buffer[3];
|
||||
u8 i2c_read_buffer[2];
|
||||
};
|
||||
|
||||
struct dib0090_fw_state {
|
||||
@ -198,27 +203,48 @@ struct dib0090_fw_state {
|
||||
struct dvb_frontend *fe;
|
||||
struct dib0090_identity identity;
|
||||
const struct dib0090_config *config;
|
||||
|
||||
/* for the I2C transfer */
|
||||
struct i2c_msg msg;
|
||||
u8 i2c_write_buffer[2];
|
||||
u8 i2c_read_buffer[2];
|
||||
};
|
||||
|
||||
static u16 dib0090_read_reg(struct dib0090_state *state, u8 reg)
|
||||
{
|
||||
u8 b[2];
|
||||
struct i2c_msg msg[2] = {
|
||||
{.addr = state->config->i2c_address, .flags = 0, .buf = ®, .len = 1},
|
||||
{.addr = state->config->i2c_address, .flags = I2C_M_RD, .buf = b, .len = 2},
|
||||
};
|
||||
if (i2c_transfer(state->i2c, msg, 2) != 2) {
|
||||
state->i2c_write_buffer[0] = reg;
|
||||
|
||||
memset(state->msg, 0, 2 * sizeof(struct i2c_msg));
|
||||
state->msg[0].addr = state->config->i2c_address;
|
||||
state->msg[0].flags = 0;
|
||||
state->msg[0].buf = state->i2c_write_buffer;
|
||||
state->msg[0].len = 1;
|
||||
state->msg[1].addr = state->config->i2c_address;
|
||||
state->msg[1].flags = I2C_M_RD;
|
||||
state->msg[1].buf = state->i2c_read_buffer;
|
||||
state->msg[1].len = 2;
|
||||
|
||||
if (i2c_transfer(state->i2c, state->msg, 2) != 2) {
|
||||
printk(KERN_WARNING "DiB0090 I2C read failed\n");
|
||||
return 0;
|
||||
}
|
||||
return (b[0] << 8) | b[1];
|
||||
|
||||
return (state->i2c_read_buffer[0] << 8) | state->i2c_read_buffer[1];
|
||||
}
|
||||
|
||||
static int dib0090_write_reg(struct dib0090_state *state, u32 reg, u16 val)
|
||||
{
|
||||
u8 b[3] = { reg & 0xff, val >> 8, val & 0xff };
|
||||
struct i2c_msg msg = {.addr = state->config->i2c_address, .flags = 0, .buf = b, .len = 3 };
|
||||
if (i2c_transfer(state->i2c, &msg, 1) != 1) {
|
||||
state->i2c_write_buffer[0] = reg & 0xff;
|
||||
state->i2c_write_buffer[1] = val >> 8;
|
||||
state->i2c_write_buffer[2] = val & 0xff;
|
||||
|
||||
memset(state->msg, 0, sizeof(struct i2c_msg));
|
||||
state->msg[0].addr = state->config->i2c_address;
|
||||
state->msg[0].flags = 0;
|
||||
state->msg[0].buf = state->i2c_write_buffer;
|
||||
state->msg[0].len = 3;
|
||||
|
||||
if (i2c_transfer(state->i2c, state->msg, 1) != 1) {
|
||||
printk(KERN_WARNING "DiB0090 I2C write failed\n");
|
||||
return -EREMOTEIO;
|
||||
}
|
||||
@ -227,20 +253,31 @@ static int dib0090_write_reg(struct dib0090_state *state, u32 reg, u16 val)
|
||||
|
||||
static u16 dib0090_fw_read_reg(struct dib0090_fw_state *state, u8 reg)
|
||||
{
|
||||
u8 b[2];
|
||||
struct i2c_msg msg = {.addr = reg, .flags = I2C_M_RD, .buf = b, .len = 2 };
|
||||
if (i2c_transfer(state->i2c, &msg, 1) != 1) {
|
||||
state->i2c_write_buffer[0] = reg;
|
||||
|
||||
memset(&state->msg, 0, sizeof(struct i2c_msg));
|
||||
state->msg.addr = reg;
|
||||
state->msg.flags = I2C_M_RD;
|
||||
state->msg.buf = state->i2c_read_buffer;
|
||||
state->msg.len = 2;
|
||||
if (i2c_transfer(state->i2c, &state->msg, 1) != 1) {
|
||||
printk(KERN_WARNING "DiB0090 I2C read failed\n");
|
||||
return 0;
|
||||
}
|
||||
return (b[0] << 8) | b[1];
|
||||
return (state->i2c_read_buffer[0] << 8) | state->i2c_read_buffer[1];
|
||||
}
|
||||
|
||||
static int dib0090_fw_write_reg(struct dib0090_fw_state *state, u8 reg, u16 val)
|
||||
{
|
||||
u8 b[2] = { val >> 8, val & 0xff };
|
||||
struct i2c_msg msg = {.addr = reg, .flags = 0, .buf = b, .len = 2 };
|
||||
if (i2c_transfer(state->i2c, &msg, 1) != 1) {
|
||||
state->i2c_write_buffer[0] = val >> 8;
|
||||
state->i2c_write_buffer[1] = val & 0xff;
|
||||
|
||||
memset(&state->msg, 0, sizeof(struct i2c_msg));
|
||||
state->msg.addr = reg;
|
||||
state->msg.flags = 0;
|
||||
state->msg.buf = state->i2c_write_buffer;
|
||||
state->msg.len = 2;
|
||||
if (i2c_transfer(state->i2c, &state->msg, 1) != 1) {
|
||||
printk(KERN_WARNING "DiB0090 I2C write failed\n");
|
||||
return -EREMOTEIO;
|
||||
}
|
||||
|
@ -50,6 +50,11 @@ struct dib7000m_state {
|
||||
u16 revision;
|
||||
|
||||
u8 agc_state;
|
||||
|
||||
/* for the I2C transfer */
|
||||
struct i2c_msg msg[2];
|
||||
u8 i2c_write_buffer[4];
|
||||
u8 i2c_read_buffer[2];
|
||||
};
|
||||
|
||||
enum dib7000m_power_mode {
|
||||
@ -64,29 +69,39 @@ enum dib7000m_power_mode {
|
||||
|
||||
static u16 dib7000m_read_word(struct dib7000m_state *state, u16 reg)
|
||||
{
|
||||
u8 wb[2] = { (reg >> 8) | 0x80, reg & 0xff };
|
||||
u8 rb[2];
|
||||
struct i2c_msg msg[2] = {
|
||||
{ .addr = state->i2c_addr >> 1, .flags = 0, .buf = wb, .len = 2 },
|
||||
{ .addr = state->i2c_addr >> 1, .flags = I2C_M_RD, .buf = rb, .len = 2 },
|
||||
};
|
||||
state->i2c_write_buffer[0] = (reg >> 8) | 0x80;
|
||||
state->i2c_write_buffer[1] = reg & 0xff;
|
||||
|
||||
if (i2c_transfer(state->i2c_adap, msg, 2) != 2)
|
||||
memset(state->msg, 0, 2 * sizeof(struct i2c_msg));
|
||||
state->msg[0].addr = state->i2c_addr >> 1;
|
||||
state->msg[0].flags = 0;
|
||||
state->msg[0].buf = state->i2c_write_buffer;
|
||||
state->msg[0].len = 2;
|
||||
state->msg[1].addr = state->i2c_addr >> 1;
|
||||
state->msg[1].flags = I2C_M_RD;
|
||||
state->msg[1].buf = state->i2c_read_buffer;
|
||||
state->msg[1].len = 2;
|
||||
|
||||
if (i2c_transfer(state->i2c_adap, state->msg, 2) != 2)
|
||||
dprintk("i2c read error on %d",reg);
|
||||
|
||||
return (rb[0] << 8) | rb[1];
|
||||
return (state->i2c_read_buffer[0] << 8) | state->i2c_read_buffer[1];
|
||||
}
|
||||
|
||||
static int dib7000m_write_word(struct dib7000m_state *state, u16 reg, u16 val)
|
||||
{
|
||||
u8 b[4] = {
|
||||
(reg >> 8) & 0xff, reg & 0xff,
|
||||
(val >> 8) & 0xff, val & 0xff,
|
||||
};
|
||||
struct i2c_msg msg = {
|
||||
.addr = state->i2c_addr >> 1, .flags = 0, .buf = b, .len = 4
|
||||
};
|
||||
return i2c_transfer(state->i2c_adap, &msg, 1) != 1 ? -EREMOTEIO : 0;
|
||||
state->i2c_write_buffer[0] = (reg >> 8) & 0xff;
|
||||
state->i2c_write_buffer[1] = reg & 0xff;
|
||||
state->i2c_write_buffer[2] = (val >> 8) & 0xff;
|
||||
state->i2c_write_buffer[3] = val & 0xff;
|
||||
|
||||
memset(&state->msg[0], 0, sizeof(struct i2c_msg));
|
||||
state->msg[0].addr = state->i2c_addr >> 1;
|
||||
state->msg[0].flags = 0;
|
||||
state->msg[0].buf = state->i2c_write_buffer;
|
||||
state->msg[0].len = 4;
|
||||
|
||||
return i2c_transfer(state->i2c_adap, state->msg, 1) != 1 ? -EREMOTEIO : 0;
|
||||
}
|
||||
static void dib7000m_write_tab(struct dib7000m_state *state, u16 *buf)
|
||||
{
|
||||
|
@ -63,6 +63,11 @@ struct dib7000p_state {
|
||||
|
||||
u16 tuner_enable;
|
||||
struct i2c_adapter dib7090_tuner_adap;
|
||||
|
||||
/* for the I2C transfer */
|
||||
struct i2c_msg msg[2];
|
||||
u8 i2c_write_buffer[4];
|
||||
u8 i2c_read_buffer[2];
|
||||
};
|
||||
|
||||
enum dib7000p_power_mode {
|
||||
@ -76,29 +81,39 @@ static int dib7090_set_diversity_in(struct dvb_frontend *fe, int onoff);
|
||||
|
||||
static u16 dib7000p_read_word(struct dib7000p_state *state, u16 reg)
|
||||
{
|
||||
u8 wb[2] = { reg >> 8, reg & 0xff };
|
||||
u8 rb[2];
|
||||
struct i2c_msg msg[2] = {
|
||||
{.addr = state->i2c_addr >> 1, .flags = 0, .buf = wb, .len = 2},
|
||||
{.addr = state->i2c_addr >> 1, .flags = I2C_M_RD, .buf = rb, .len = 2},
|
||||
};
|
||||
state->i2c_write_buffer[0] = reg >> 8;
|
||||
state->i2c_write_buffer[1] = reg & 0xff;
|
||||
|
||||
if (i2c_transfer(state->i2c_adap, msg, 2) != 2)
|
||||
memset(state->msg, 0, 2 * sizeof(struct i2c_msg));
|
||||
state->msg[0].addr = state->i2c_addr >> 1;
|
||||
state->msg[0].flags = 0;
|
||||
state->msg[0].buf = state->i2c_write_buffer;
|
||||
state->msg[0].len = 2;
|
||||
state->msg[1].addr = state->i2c_addr >> 1;
|
||||
state->msg[1].flags = I2C_M_RD;
|
||||
state->msg[1].buf = state->i2c_read_buffer;
|
||||
state->msg[1].len = 2;
|
||||
|
||||
if (i2c_transfer(state->i2c_adap, state->msg, 2) != 2)
|
||||
dprintk("i2c read error on %d", reg);
|
||||
|
||||
return (rb[0] << 8) | rb[1];
|
||||
return (state->i2c_read_buffer[0] << 8) | state->i2c_read_buffer[1];
|
||||
}
|
||||
|
||||
static int dib7000p_write_word(struct dib7000p_state *state, u16 reg, u16 val)
|
||||
{
|
||||
u8 b[4] = {
|
||||
(reg >> 8) & 0xff, reg & 0xff,
|
||||
(val >> 8) & 0xff, val & 0xff,
|
||||
};
|
||||
struct i2c_msg msg = {
|
||||
.addr = state->i2c_addr >> 1, .flags = 0, .buf = b, .len = 4
|
||||
};
|
||||
return i2c_transfer(state->i2c_adap, &msg, 1) != 1 ? -EREMOTEIO : 0;
|
||||
state->i2c_write_buffer[0] = (reg >> 8) & 0xff;
|
||||
state->i2c_write_buffer[1] = reg & 0xff;
|
||||
state->i2c_write_buffer[2] = (val >> 8) & 0xff;
|
||||
state->i2c_write_buffer[3] = val & 0xff;
|
||||
|
||||
memset(&state->msg[0], 0, sizeof(struct i2c_msg));
|
||||
state->msg[0].addr = state->i2c_addr >> 1;
|
||||
state->msg[0].flags = 0;
|
||||
state->msg[0].buf = state->i2c_write_buffer;
|
||||
state->msg[0].len = 4;
|
||||
|
||||
return i2c_transfer(state->i2c_adap, state->msg, 1) != 1 ? -EREMOTEIO : 0;
|
||||
}
|
||||
|
||||
static void dib7000p_write_tab(struct dib7000p_state *state, u16 * buf)
|
||||
@ -1550,11 +1565,24 @@ static void dib7000p_release(struct dvb_frontend *demod)
|
||||
|
||||
int dib7000pc_detection(struct i2c_adapter *i2c_adap)
|
||||
{
|
||||
u8 tx[2], rx[2];
|
||||
u8 *tx, *rx;
|
||||
struct i2c_msg msg[2] = {
|
||||
{.addr = 18 >> 1, .flags = 0, .buf = tx, .len = 2},
|
||||
{.addr = 18 >> 1, .flags = I2C_M_RD, .buf = rx, .len = 2},
|
||||
{.addr = 18 >> 1, .flags = 0, .len = 2},
|
||||
{.addr = 18 >> 1, .flags = I2C_M_RD, .len = 2},
|
||||
};
|
||||
int ret = 0;
|
||||
|
||||
tx = kzalloc(2*sizeof(u8), GFP_KERNEL);
|
||||
if (!tx)
|
||||
return -ENOMEM;
|
||||
rx = kzalloc(2*sizeof(u8), GFP_KERNEL);
|
||||
if (!rx) {
|
||||
goto rx_memory_error;
|
||||
ret = -ENOMEM;
|
||||
}
|
||||
|
||||
msg[0].buf = tx;
|
||||
msg[1].buf = rx;
|
||||
|
||||
tx[0] = 0x03;
|
||||
tx[1] = 0x00;
|
||||
@ -1574,7 +1602,11 @@ int dib7000pc_detection(struct i2c_adapter *i2c_adap)
|
||||
}
|
||||
|
||||
dprintk("-D- DiB7000PC not detected");
|
||||
return 0;
|
||||
|
||||
kfree(rx);
|
||||
rx_memory_error:
|
||||
kfree(tx);
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(dib7000pc_detection);
|
||||
|
||||
|
@ -35,6 +35,8 @@ MODULE_PARM_DESC(debug, "turn on debugging (default: 0)");
|
||||
struct i2c_device {
|
||||
struct i2c_adapter *adap;
|
||||
u8 addr;
|
||||
u8 *i2c_write_buffer;
|
||||
u8 *i2c_read_buffer;
|
||||
};
|
||||
|
||||
struct dib8000_state {
|
||||
@ -70,6 +72,11 @@ struct dib8000_state {
|
||||
u32 status;
|
||||
|
||||
struct dvb_frontend *fe[MAX_NUMBER_OF_FRONTENDS];
|
||||
|
||||
/* for the I2C transfer */
|
||||
struct i2c_msg msg[2];
|
||||
u8 i2c_write_buffer[4];
|
||||
u8 i2c_read_buffer[2];
|
||||
};
|
||||
|
||||
enum dib8000_power_mode {
|
||||
@ -79,22 +86,41 @@ enum dib8000_power_mode {
|
||||
|
||||
static u16 dib8000_i2c_read16(struct i2c_device *i2c, u16 reg)
|
||||
{
|
||||
u8 wb[2] = { reg >> 8, reg & 0xff };
|
||||
u8 rb[2];
|
||||
struct i2c_msg msg[2] = {
|
||||
{.addr = i2c->addr >> 1,.flags = 0,.buf = wb,.len = 2},
|
||||
{.addr = i2c->addr >> 1,.flags = I2C_M_RD,.buf = rb,.len = 2},
|
||||
{.addr = i2c->addr >> 1, .flags = 0,
|
||||
.buf = i2c->i2c_write_buffer, .len = 2},
|
||||
{.addr = i2c->addr >> 1, .flags = I2C_M_RD,
|
||||
.buf = i2c->i2c_read_buffer, .len = 2},
|
||||
};
|
||||
|
||||
msg[0].buf[0] = reg >> 8;
|
||||
msg[0].buf[1] = reg & 0xff;
|
||||
|
||||
if (i2c_transfer(i2c->adap, msg, 2) != 2)
|
||||
dprintk("i2c read error on %d", reg);
|
||||
|
||||
return (rb[0] << 8) | rb[1];
|
||||
return (msg[1].buf[0] << 8) | msg[1].buf[1];
|
||||
}
|
||||
|
||||
static u16 dib8000_read_word(struct dib8000_state *state, u16 reg)
|
||||
{
|
||||
return dib8000_i2c_read16(&state->i2c, reg);
|
||||
state->i2c_write_buffer[0] = reg >> 8;
|
||||
state->i2c_write_buffer[1] = reg & 0xff;
|
||||
|
||||
memset(state->msg, 0, 2 * sizeof(struct i2c_msg));
|
||||
state->msg[0].addr = state->i2c.addr >> 1;
|
||||
state->msg[0].flags = 0;
|
||||
state->msg[0].buf = state->i2c_write_buffer;
|
||||
state->msg[0].len = 2;
|
||||
state->msg[1].addr = state->i2c.addr >> 1;
|
||||
state->msg[1].flags = I2C_M_RD;
|
||||
state->msg[1].buf = state->i2c_read_buffer;
|
||||
state->msg[1].len = 2;
|
||||
|
||||
if (i2c_transfer(state->i2c.adap, state->msg, 2) != 2)
|
||||
dprintk("i2c read error on %d", reg);
|
||||
|
||||
return (state->i2c_read_buffer[0] << 8) | state->i2c_read_buffer[1];
|
||||
}
|
||||
|
||||
static u32 dib8000_read32(struct dib8000_state *state, u16 reg)
|
||||
@ -109,19 +135,34 @@ static u32 dib8000_read32(struct dib8000_state *state, u16 reg)
|
||||
|
||||
static int dib8000_i2c_write16(struct i2c_device *i2c, u16 reg, u16 val)
|
||||
{
|
||||
u8 b[4] = {
|
||||
(reg >> 8) & 0xff, reg & 0xff,
|
||||
(val >> 8) & 0xff, val & 0xff,
|
||||
};
|
||||
struct i2c_msg msg = {
|
||||
.addr = i2c->addr >> 1,.flags = 0,.buf = b,.len = 4
|
||||
};
|
||||
return i2c_transfer(i2c->adap, &msg, 1) != 1 ? -EREMOTEIO : 0;
|
||||
struct i2c_msg msg = {.addr = i2c->addr >> 1, .flags = 0,
|
||||
.buf = i2c->i2c_write_buffer, .len = 4};
|
||||
int ret = 0;
|
||||
|
||||
msg.buf[0] = (reg >> 8) & 0xff;
|
||||
msg.buf[1] = reg & 0xff;
|
||||
msg.buf[2] = (val >> 8) & 0xff;
|
||||
msg.buf[3] = val & 0xff;
|
||||
|
||||
ret = i2c_transfer(i2c->adap, &msg, 1) != 1 ? -EREMOTEIO : 0;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int dib8000_write_word(struct dib8000_state *state, u16 reg, u16 val)
|
||||
{
|
||||
return dib8000_i2c_write16(&state->i2c, reg, val);
|
||||
state->i2c_write_buffer[0] = (reg >> 8) & 0xff;
|
||||
state->i2c_write_buffer[1] = reg & 0xff;
|
||||
state->i2c_write_buffer[2] = (val >> 8) & 0xff;
|
||||
state->i2c_write_buffer[3] = val & 0xff;
|
||||
|
||||
memset(&state->msg[0], 0, sizeof(struct i2c_msg));
|
||||
state->msg[0].addr = state->i2c.addr >> 1;
|
||||
state->msg[0].flags = 0;
|
||||
state->msg[0].buf = state->i2c_write_buffer;
|
||||
state->msg[0].len = 4;
|
||||
|
||||
return i2c_transfer(state->i2c.adap, state->msg, 1) != 1 ? -EREMOTEIO : 0;
|
||||
}
|
||||
|
||||
static const s16 coeff_2k_sb_1seg_dqpsk[8] = {
|
||||
@ -980,30 +1021,31 @@ static void dib8000_update_timf(struct dib8000_state *state)
|
||||
dprintk("Updated timing frequency: %d (default: %d)", state->timf, state->timf_default);
|
||||
}
|
||||
|
||||
static const u16 adc_target_16dB[11] = {
|
||||
(1 << 13) - 825 - 117,
|
||||
(1 << 13) - 837 - 117,
|
||||
(1 << 13) - 811 - 117,
|
||||
(1 << 13) - 766 - 117,
|
||||
(1 << 13) - 737 - 117,
|
||||
(1 << 13) - 693 - 117,
|
||||
(1 << 13) - 648 - 117,
|
||||
(1 << 13) - 619 - 117,
|
||||
(1 << 13) - 575 - 117,
|
||||
(1 << 13) - 531 - 117,
|
||||
(1 << 13) - 501 - 117
|
||||
};
|
||||
static const u8 permu_seg[] = { 6, 5, 7, 4, 8, 3, 9, 2, 10, 1, 11, 0, 12 };
|
||||
|
||||
static void dib8000_set_channel(struct dib8000_state *state, u8 seq, u8 autosearching)
|
||||
{
|
||||
u16 mode, max_constellation, seg_diff_mask = 0, nbseg_diff = 0;
|
||||
u8 guard, crate, constellation, timeI;
|
||||
u8 permu_seg[] = { 6, 5, 7, 4, 8, 3, 9, 2, 10, 1, 11, 0, 12 };
|
||||
u16 i, coeff[4], P_cfr_left_edge = 0, P_cfr_right_edge = 0, seg_mask13 = 0x1fff; // All 13 segments enabled
|
||||
const s16 *ncoeff = NULL, *ana_fe;
|
||||
u16 tmcc_pow = 0;
|
||||
u16 coff_pow = 0x2800;
|
||||
u16 init_prbs = 0xfff;
|
||||
u16 ana_gain = 0;
|
||||
u16 adc_target_16dB[11] = {
|
||||
(1 << 13) - 825 - 117,
|
||||
(1 << 13) - 837 - 117,
|
||||
(1 << 13) - 811 - 117,
|
||||
(1 << 13) - 766 - 117,
|
||||
(1 << 13) - 737 - 117,
|
||||
(1 << 13) - 693 - 117,
|
||||
(1 << 13) - 648 - 117,
|
||||
(1 << 13) - 619 - 117,
|
||||
(1 << 13) - 575 - 117,
|
||||
(1 << 13) - 531 - 117,
|
||||
(1 << 13) - 501 - 117
|
||||
};
|
||||
|
||||
if (state->ber_monitored_layer != LAYER_ALL)
|
||||
dib8000_write_word(state, 285, (dib8000_read_word(state, 285) & 0x60) | state->ber_monitored_layer);
|
||||
@ -2379,10 +2421,22 @@ EXPORT_SYMBOL(dib8000_get_slave_frontend);
|
||||
|
||||
int dib8000_i2c_enumeration(struct i2c_adapter *host, int no_of_demods, u8 default_addr, u8 first_addr)
|
||||
{
|
||||
int k = 0;
|
||||
int k = 0, ret = 0;
|
||||
u8 new_addr = 0;
|
||||
struct i2c_device client = {.adap = host };
|
||||
|
||||
client.i2c_write_buffer = kzalloc(4 * sizeof(u8), GFP_KERNEL);
|
||||
if (!client.i2c_write_buffer) {
|
||||
dprintk("%s: not enough memory", __func__);
|
||||
return -ENOMEM;
|
||||
}
|
||||
client.i2c_read_buffer = kzalloc(4 * sizeof(u8), GFP_KERNEL);
|
||||
if (!client.i2c_read_buffer) {
|
||||
dprintk("%s: not enough memory", __func__);
|
||||
ret = -ENOMEM;
|
||||
goto error_memory;
|
||||
}
|
||||
|
||||
for (k = no_of_demods - 1; k >= 0; k--) {
|
||||
/* designated i2c address */
|
||||
new_addr = first_addr + (k << 1);
|
||||
@ -2394,7 +2448,8 @@ int dib8000_i2c_enumeration(struct i2c_adapter *host, int no_of_demods, u8 defau
|
||||
client.addr = default_addr;
|
||||
if (dib8000_identify(&client) == 0) {
|
||||
dprintk("#%d: not identified", k);
|
||||
return -EINVAL;
|
||||
ret = -EINVAL;
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
|
||||
@ -2420,7 +2475,12 @@ int dib8000_i2c_enumeration(struct i2c_adapter *host, int no_of_demods, u8 defau
|
||||
dib8000_i2c_write16(&client, 1286, 0);
|
||||
}
|
||||
|
||||
return 0;
|
||||
error:
|
||||
kfree(client.i2c_read_buffer);
|
||||
error_memory:
|
||||
kfree(client.i2c_write_buffer);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(dib8000_i2c_enumeration);
|
||||
@ -2519,6 +2579,8 @@ struct dvb_frontend *dib8000_attach(struct i2c_adapter *i2c_adap, u8 i2c_addr, s
|
||||
memcpy(&state->cfg, cfg, sizeof(struct dib8000_config));
|
||||
state->i2c.adap = i2c_adap;
|
||||
state->i2c.addr = i2c_addr;
|
||||
state->i2c.i2c_write_buffer = state->i2c_write_buffer;
|
||||
state->i2c.i2c_read_buffer = state->i2c_read_buffer;
|
||||
state->gpio_val = cfg->gpio_val;
|
||||
state->gpio_dir = cfg->gpio_dir;
|
||||
|
||||
|
@ -27,6 +27,8 @@ MODULE_PARM_DESC(debug, "turn on debugging (default: 0)");
|
||||
struct i2c_device {
|
||||
struct i2c_adapter *i2c_adap;
|
||||
u8 i2c_addr;
|
||||
u8 *i2c_read_buffer;
|
||||
u8 *i2c_write_buffer;
|
||||
};
|
||||
|
||||
/* lock */
|
||||
@ -92,11 +94,16 @@ struct dib9000_state {
|
||||
|
||||
struct dvb_frontend *fe[MAX_NUMBER_OF_FRONTENDS];
|
||||
u16 component_bus_speed;
|
||||
|
||||
/* for the I2C transfer */
|
||||
struct i2c_msg msg[2];
|
||||
u8 i2c_write_buffer[255];
|
||||
u8 i2c_read_buffer[255];
|
||||
};
|
||||
|
||||
u32 fe_info[44] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
static const u32 fe_info[44] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0
|
||||
0, 0, 0, 0, 0, 0, 0, 0
|
||||
};
|
||||
|
||||
enum dib9000_power_mode {
|
||||
@ -217,25 +224,33 @@ static u16 dib9000_read16_attr(struct dib9000_state *state, u16 reg, u8 * b, u32
|
||||
u32 chunk_size = 126;
|
||||
u32 l;
|
||||
int ret;
|
||||
u8 wb[2] = { reg >> 8, reg & 0xff };
|
||||
struct i2c_msg msg[2] = {
|
||||
{.addr = state->i2c.i2c_addr >> 1, .flags = 0, .buf = wb, .len = 2},
|
||||
{.addr = state->i2c.i2c_addr >> 1, .flags = I2C_M_RD, .buf = b, .len = len},
|
||||
};
|
||||
|
||||
if (state->platform.risc.fw_is_running && (reg < 1024))
|
||||
return dib9000_risc_apb_access_read(state, reg, attribute, NULL, 0, b, len);
|
||||
|
||||
memset(state->msg, 0, 2 * sizeof(struct i2c_msg));
|
||||
state->msg[0].addr = state->i2c.i2c_addr >> 1;
|
||||
state->msg[0].flags = 0;
|
||||
state->msg[0].buf = state->i2c_write_buffer;
|
||||
state->msg[0].len = 2;
|
||||
state->msg[1].addr = state->i2c.i2c_addr >> 1;
|
||||
state->msg[1].flags = I2C_M_RD;
|
||||
state->msg[1].buf = b;
|
||||
state->msg[1].len = len;
|
||||
|
||||
state->i2c_write_buffer[0] = reg >> 8;
|
||||
state->i2c_write_buffer[1] = reg & 0xff;
|
||||
|
||||
if (attribute & DATA_BUS_ACCESS_MODE_8BIT)
|
||||
wb[0] |= (1 << 5);
|
||||
state->i2c_write_buffer[0] |= (1 << 5);
|
||||
if (attribute & DATA_BUS_ACCESS_MODE_NO_ADDRESS_INCREMENT)
|
||||
wb[0] |= (1 << 4);
|
||||
state->i2c_write_buffer[0] |= (1 << 4);
|
||||
|
||||
do {
|
||||
l = len < chunk_size ? len : chunk_size;
|
||||
msg[1].len = l;
|
||||
msg[1].buf = b;
|
||||
ret = i2c_transfer(state->i2c.i2c_adap, msg, 2) != 2 ? -EREMOTEIO : 0;
|
||||
state->msg[1].len = l;
|
||||
state->msg[1].buf = b;
|
||||
ret = i2c_transfer(state->i2c.i2c_adap, state->msg, 2) != 2 ? -EREMOTEIO : 0;
|
||||
if (ret != 0) {
|
||||
dprintk("i2c read error on %d", reg);
|
||||
return -EREMOTEIO;
|
||||
@ -253,50 +268,47 @@ static u16 dib9000_read16_attr(struct dib9000_state *state, u16 reg, u8 * b, u32
|
||||
|
||||
static u16 dib9000_i2c_read16(struct i2c_device *i2c, u16 reg)
|
||||
{
|
||||
u8 b[2];
|
||||
u8 wb[2] = { reg >> 8, reg & 0xff };
|
||||
struct i2c_msg msg[2] = {
|
||||
{.addr = i2c->i2c_addr >> 1, .flags = 0, .buf = wb, .len = 2},
|
||||
{.addr = i2c->i2c_addr >> 1, .flags = I2C_M_RD, .buf = b, .len = 2},
|
||||
{.addr = i2c->i2c_addr >> 1, .flags = 0,
|
||||
.buf = i2c->i2c_write_buffer, .len = 2},
|
||||
{.addr = i2c->i2c_addr >> 1, .flags = I2C_M_RD,
|
||||
.buf = i2c->i2c_read_buffer, .len = 2},
|
||||
};
|
||||
|
||||
i2c->i2c_write_buffer[0] = reg >> 8;
|
||||
i2c->i2c_write_buffer[1] = reg & 0xff;
|
||||
|
||||
if (i2c_transfer(i2c->i2c_adap, msg, 2) != 2) {
|
||||
dprintk("read register %x error", reg);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return (b[0] << 8) | b[1];
|
||||
return (i2c->i2c_read_buffer[0] << 8) | i2c->i2c_read_buffer[1];
|
||||
}
|
||||
|
||||
static inline u16 dib9000_read_word(struct dib9000_state *state, u16 reg)
|
||||
{
|
||||
u8 b[2];
|
||||
if (dib9000_read16_attr(state, reg, b, 2, 0) != 0)
|
||||
if (dib9000_read16_attr(state, reg, state->i2c_read_buffer, 2, 0) != 0)
|
||||
return 0;
|
||||
return (b[0] << 8 | b[1]);
|
||||
return (state->i2c_read_buffer[0] << 8) | state->i2c_read_buffer[1];
|
||||
}
|
||||
|
||||
static inline u16 dib9000_read_word_attr(struct dib9000_state *state, u16 reg, u16 attribute)
|
||||
{
|
||||
u8 b[2];
|
||||
if (dib9000_read16_attr(state, reg, b, 2, attribute) != 0)
|
||||
if (dib9000_read16_attr(state, reg, state->i2c_read_buffer, 2,
|
||||
attribute) != 0)
|
||||
return 0;
|
||||
return (b[0] << 8 | b[1]);
|
||||
return (state->i2c_read_buffer[0] << 8) | state->i2c_read_buffer[1];
|
||||
}
|
||||
|
||||
#define dib9000_read16_noinc_attr(state, reg, b, len, attribute) dib9000_read16_attr(state, reg, b, len, (attribute) | DATA_BUS_ACCESS_MODE_NO_ADDRESS_INCREMENT)
|
||||
|
||||
static u16 dib9000_write16_attr(struct dib9000_state *state, u16 reg, const u8 * buf, u32 len, u16 attribute)
|
||||
{
|
||||
u8 b[255];
|
||||
u32 chunk_size = 126;
|
||||
u32 l;
|
||||
int ret;
|
||||
|
||||
struct i2c_msg msg = {
|
||||
.addr = state->i2c.i2c_addr >> 1, .flags = 0, .buf = b, .len = len + 2
|
||||
};
|
||||
|
||||
if (state->platform.risc.fw_is_running && (reg < 1024)) {
|
||||
if (dib9000_risc_apb_access_write
|
||||
(state, reg, DATA_BUS_ACCESS_MODE_16BIT | DATA_BUS_ACCESS_MODE_NO_ADDRESS_INCREMENT | attribute, buf, len) != 0)
|
||||
@ -304,20 +316,26 @@ static u16 dib9000_write16_attr(struct dib9000_state *state, u16 reg, const u8 *
|
||||
return 0;
|
||||
}
|
||||
|
||||
b[0] = (reg >> 8) & 0xff;
|
||||
b[1] = (reg) & 0xff;
|
||||
memset(&state->msg[0], 0, sizeof(struct i2c_msg));
|
||||
state->msg[0].addr = state->i2c.i2c_addr >> 1;
|
||||
state->msg[0].flags = 0;
|
||||
state->msg[0].buf = state->i2c_write_buffer;
|
||||
state->msg[0].len = len + 2;
|
||||
|
||||
state->i2c_write_buffer[0] = (reg >> 8) & 0xff;
|
||||
state->i2c_write_buffer[1] = (reg) & 0xff;
|
||||
|
||||
if (attribute & DATA_BUS_ACCESS_MODE_8BIT)
|
||||
b[0] |= (1 << 5);
|
||||
state->i2c_write_buffer[0] |= (1 << 5);
|
||||
if (attribute & DATA_BUS_ACCESS_MODE_NO_ADDRESS_INCREMENT)
|
||||
b[0] |= (1 << 4);
|
||||
state->i2c_write_buffer[0] |= (1 << 4);
|
||||
|
||||
do {
|
||||
l = len < chunk_size ? len : chunk_size;
|
||||
msg.len = l + 2;
|
||||
memcpy(&b[2], buf, l);
|
||||
state->msg[0].len = l + 2;
|
||||
memcpy(&state->i2c_write_buffer[2], buf, l);
|
||||
|
||||
ret = i2c_transfer(state->i2c.i2c_adap, &msg, 1) != 1 ? -EREMOTEIO : 0;
|
||||
ret = i2c_transfer(state->i2c.i2c_adap, state->msg, 1) != 1 ? -EREMOTEIO : 0;
|
||||
|
||||
buf += l;
|
||||
len -= l;
|
||||
@ -331,11 +349,16 @@ static u16 dib9000_write16_attr(struct dib9000_state *state, u16 reg, const u8 *
|
||||
|
||||
static int dib9000_i2c_write16(struct i2c_device *i2c, u16 reg, u16 val)
|
||||
{
|
||||
u8 b[4] = { (reg >> 8) & 0xff, reg & 0xff, (val >> 8) & 0xff, val & 0xff };
|
||||
struct i2c_msg msg = {
|
||||
.addr = i2c->i2c_addr >> 1, .flags = 0, .buf = b, .len = 4
|
||||
.addr = i2c->i2c_addr >> 1, .flags = 0,
|
||||
.buf = i2c->i2c_write_buffer, .len = 4
|
||||
};
|
||||
|
||||
i2c->i2c_write_buffer[0] = (reg >> 8) & 0xff;
|
||||
i2c->i2c_write_buffer[1] = reg & 0xff;
|
||||
i2c->i2c_write_buffer[2] = (val >> 8) & 0xff;
|
||||
i2c->i2c_write_buffer[3] = val & 0xff;
|
||||
|
||||
return i2c_transfer(i2c->i2c_adap, &msg, 1) != 1 ? -EREMOTEIO : 0;
|
||||
}
|
||||
|
||||
@ -1015,8 +1038,8 @@ static int dib9000_fw_memmbx_sync(struct dib9000_state *state, u8 i)
|
||||
return 0;
|
||||
dib9000_risc_mem_write(state, FE_MM_RW_SYNC, &i);
|
||||
do {
|
||||
dib9000_risc_mem_read(state, FE_MM_RW_SYNC, &i, 1);
|
||||
} while (i && index_loop--);
|
||||
dib9000_risc_mem_read(state, FE_MM_RW_SYNC, state->i2c_read_buffer, 1);
|
||||
} while (state->i2c_read_buffer[0] && index_loop--);
|
||||
|
||||
if (index_loop > 0)
|
||||
return 0;
|
||||
@ -1139,7 +1162,7 @@ static int dib9000_fw_get_channel(struct dvb_frontend *fe, struct dvb_frontend_p
|
||||
|
||||
s8 intlv_native;
|
||||
};
|
||||
struct dibDVBTChannel ch;
|
||||
struct dibDVBTChannel *ch;
|
||||
int ret = 0;
|
||||
|
||||
DibAcquireLock(&state->platform.risc.mem_mbx_lock);
|
||||
@ -1148,9 +1171,12 @@ static int dib9000_fw_get_channel(struct dvb_frontend *fe, struct dvb_frontend_p
|
||||
ret = -EIO;
|
||||
}
|
||||
|
||||
dib9000_risc_mem_read(state, FE_MM_R_CHANNEL_UNION, (u8 *) &ch, sizeof(struct dibDVBTChannel));
|
||||
dib9000_risc_mem_read(state, FE_MM_R_CHANNEL_UNION,
|
||||
state->i2c_read_buffer, sizeof(struct dibDVBTChannel));
|
||||
ch = (struct dibDVBTChannel *)state->i2c_read_buffer;
|
||||
|
||||
switch (ch.spectrum_inversion & 0x7) {
|
||||
|
||||
switch (ch->spectrum_inversion & 0x7) {
|
||||
case 1:
|
||||
state->fe[0]->dtv_property_cache.inversion = INVERSION_ON;
|
||||
break;
|
||||
@ -1162,7 +1188,7 @@ static int dib9000_fw_get_channel(struct dvb_frontend *fe, struct dvb_frontend_p
|
||||
state->fe[0]->dtv_property_cache.inversion = INVERSION_AUTO;
|
||||
break;
|
||||
}
|
||||
switch (ch.nfft) {
|
||||
switch (ch->nfft) {
|
||||
case 0:
|
||||
state->fe[0]->dtv_property_cache.transmission_mode = TRANSMISSION_MODE_2K;
|
||||
break;
|
||||
@ -1177,7 +1203,7 @@ static int dib9000_fw_get_channel(struct dvb_frontend *fe, struct dvb_frontend_p
|
||||
state->fe[0]->dtv_property_cache.transmission_mode = TRANSMISSION_MODE_AUTO;
|
||||
break;
|
||||
}
|
||||
switch (ch.guard) {
|
||||
switch (ch->guard) {
|
||||
case 0:
|
||||
state->fe[0]->dtv_property_cache.guard_interval = GUARD_INTERVAL_1_32;
|
||||
break;
|
||||
@ -1195,7 +1221,7 @@ static int dib9000_fw_get_channel(struct dvb_frontend *fe, struct dvb_frontend_p
|
||||
state->fe[0]->dtv_property_cache.guard_interval = GUARD_INTERVAL_AUTO;
|
||||
break;
|
||||
}
|
||||
switch (ch.constellation) {
|
||||
switch (ch->constellation) {
|
||||
case 2:
|
||||
state->fe[0]->dtv_property_cache.modulation = QAM_64;
|
||||
break;
|
||||
@ -1210,7 +1236,7 @@ static int dib9000_fw_get_channel(struct dvb_frontend *fe, struct dvb_frontend_p
|
||||
state->fe[0]->dtv_property_cache.modulation = QAM_AUTO;
|
||||
break;
|
||||
}
|
||||
switch (ch.hrch) {
|
||||
switch (ch->hrch) {
|
||||
case 0:
|
||||
state->fe[0]->dtv_property_cache.hierarchy = HIERARCHY_NONE;
|
||||
break;
|
||||
@ -1222,7 +1248,7 @@ static int dib9000_fw_get_channel(struct dvb_frontend *fe, struct dvb_frontend_p
|
||||
state->fe[0]->dtv_property_cache.hierarchy = HIERARCHY_AUTO;
|
||||
break;
|
||||
}
|
||||
switch (ch.code_rate_hp) {
|
||||
switch (ch->code_rate_hp) {
|
||||
case 1:
|
||||
state->fe[0]->dtv_property_cache.code_rate_HP = FEC_1_2;
|
||||
break;
|
||||
@ -1243,7 +1269,7 @@ static int dib9000_fw_get_channel(struct dvb_frontend *fe, struct dvb_frontend_p
|
||||
state->fe[0]->dtv_property_cache.code_rate_HP = FEC_AUTO;
|
||||
break;
|
||||
}
|
||||
switch (ch.code_rate_lp) {
|
||||
switch (ch->code_rate_lp) {
|
||||
case 1:
|
||||
state->fe[0]->dtv_property_cache.code_rate_LP = FEC_1_2;
|
||||
break;
|
||||
@ -1439,9 +1465,10 @@ static int dib9000_fw_tune(struct dvb_frontend *fe, struct dvb_frontend_paramete
|
||||
break;
|
||||
case CT_DEMOD_STEP_1:
|
||||
if (search)
|
||||
dib9000_risc_mem_read(state, FE_MM_R_CHANNEL_SEARCH_STATE, (u8 *) &i, 1);
|
||||
dib9000_risc_mem_read(state, FE_MM_R_CHANNEL_SEARCH_STATE, state->i2c_read_buffer, 1);
|
||||
else
|
||||
dib9000_risc_mem_read(state, FE_MM_R_CHANNEL_TUNE_STATE, (u8 *) &i, 1);
|
||||
dib9000_risc_mem_read(state, FE_MM_R_CHANNEL_TUNE_STATE, state->i2c_read_buffer, 1);
|
||||
i = (s8)state->i2c_read_buffer[0];
|
||||
switch (i) { /* something happened */
|
||||
case 0:
|
||||
break;
|
||||
@ -2038,14 +2065,17 @@ static int dib9000_read_status(struct dvb_frontend *fe, fe_status_t * stat)
|
||||
static int dib9000_read_ber(struct dvb_frontend *fe, u32 * ber)
|
||||
{
|
||||
struct dib9000_state *state = fe->demodulator_priv;
|
||||
u16 c[16];
|
||||
u16 *c;
|
||||
|
||||
DibAcquireLock(&state->platform.risc.mem_mbx_lock);
|
||||
if (dib9000_fw_memmbx_sync(state, FE_SYNC_CHANNEL) < 0)
|
||||
return -EIO;
|
||||
dib9000_risc_mem_read(state, FE_MM_R_FE_MONITOR, (u8 *) c, sizeof(c));
|
||||
dib9000_risc_mem_read(state, FE_MM_R_FE_MONITOR,
|
||||
state->i2c_read_buffer, 16 * 2);
|
||||
DibReleaseLock(&state->platform.risc.mem_mbx_lock);
|
||||
|
||||
c = (u16 *)state->i2c_read_buffer;
|
||||
|
||||
*ber = c[10] << 16 | c[11];
|
||||
return 0;
|
||||
}
|
||||
@ -2054,7 +2084,7 @@ static int dib9000_read_signal_strength(struct dvb_frontend *fe, u16 * strength)
|
||||
{
|
||||
struct dib9000_state *state = fe->demodulator_priv;
|
||||
u8 index_frontend;
|
||||
u16 c[16];
|
||||
u16 *c = (u16 *)state->i2c_read_buffer;
|
||||
u16 val;
|
||||
|
||||
*strength = 0;
|
||||
@ -2069,7 +2099,7 @@ static int dib9000_read_signal_strength(struct dvb_frontend *fe, u16 * strength)
|
||||
DibAcquireLock(&state->platform.risc.mem_mbx_lock);
|
||||
if (dib9000_fw_memmbx_sync(state, FE_SYNC_CHANNEL) < 0)
|
||||
return -EIO;
|
||||
dib9000_risc_mem_read(state, FE_MM_R_FE_MONITOR, (u8 *) c, sizeof(c));
|
||||
dib9000_risc_mem_read(state, FE_MM_R_FE_MONITOR, (u8 *) c, 16 * 2);
|
||||
DibReleaseLock(&state->platform.risc.mem_mbx_lock);
|
||||
|
||||
val = 65535 - c[4];
|
||||
@ -2083,14 +2113,14 @@ static int dib9000_read_signal_strength(struct dvb_frontend *fe, u16 * strength)
|
||||
static u32 dib9000_get_snr(struct dvb_frontend *fe)
|
||||
{
|
||||
struct dib9000_state *state = fe->demodulator_priv;
|
||||
u16 c[16];
|
||||
u16 *c = (u16 *)state->i2c_read_buffer;
|
||||
u32 n, s, exp;
|
||||
u16 val;
|
||||
|
||||
DibAcquireLock(&state->platform.risc.mem_mbx_lock);
|
||||
if (dib9000_fw_memmbx_sync(state, FE_SYNC_CHANNEL) < 0)
|
||||
return -EIO;
|
||||
dib9000_risc_mem_read(state, FE_MM_R_FE_MONITOR, (u8 *) c, sizeof(c));
|
||||
dib9000_risc_mem_read(state, FE_MM_R_FE_MONITOR, (u8 *) c, 16 * 2);
|
||||
DibReleaseLock(&state->platform.risc.mem_mbx_lock);
|
||||
|
||||
val = c[7];
|
||||
@ -2137,12 +2167,12 @@ static int dib9000_read_snr(struct dvb_frontend *fe, u16 * snr)
|
||||
static int dib9000_read_unc_blocks(struct dvb_frontend *fe, u32 * unc)
|
||||
{
|
||||
struct dib9000_state *state = fe->demodulator_priv;
|
||||
u16 c[16];
|
||||
u16 *c = (u16 *)state->i2c_read_buffer;
|
||||
|
||||
DibAcquireLock(&state->platform.risc.mem_mbx_lock);
|
||||
if (dib9000_fw_memmbx_sync(state, FE_SYNC_CHANNEL) < 0)
|
||||
return -EIO;
|
||||
dib9000_risc_mem_read(state, FE_MM_R_FE_MONITOR, (u8 *) c, sizeof(c));
|
||||
dib9000_risc_mem_read(state, FE_MM_R_FE_MONITOR, (u8 *) c, 16 * 2);
|
||||
DibReleaseLock(&state->platform.risc.mem_mbx_lock);
|
||||
|
||||
*unc = c[12];
|
||||
@ -2151,10 +2181,22 @@ static int dib9000_read_unc_blocks(struct dvb_frontend *fe, u32 * unc)
|
||||
|
||||
int dib9000_i2c_enumeration(struct i2c_adapter *i2c, int no_of_demods, u8 default_addr, u8 first_addr)
|
||||
{
|
||||
int k = 0;
|
||||
int k = 0, ret = 0;
|
||||
u8 new_addr = 0;
|
||||
struct i2c_device client = {.i2c_adap = i2c };
|
||||
|
||||
client.i2c_write_buffer = kzalloc(4 * sizeof(u8), GFP_KERNEL);
|
||||
if (!client.i2c_write_buffer) {
|
||||
dprintk("%s: not enough memory", __func__);
|
||||
return -ENOMEM;
|
||||
}
|
||||
client.i2c_read_buffer = kzalloc(4 * sizeof(u8), GFP_KERNEL);
|
||||
if (!client.i2c_read_buffer) {
|
||||
dprintk("%s: not enough memory", __func__);
|
||||
ret = -ENOMEM;
|
||||
goto error_memory;
|
||||
}
|
||||
|
||||
client.i2c_addr = default_addr + 16;
|
||||
dib9000_i2c_write16(&client, 1796, 0x0);
|
||||
|
||||
@ -2178,7 +2220,8 @@ int dib9000_i2c_enumeration(struct i2c_adapter *i2c, int no_of_demods, u8 defaul
|
||||
client.i2c_addr = default_addr;
|
||||
if (dib9000_identify(&client) == 0) {
|
||||
dprintk("DiB9000 #%d: not identified", k);
|
||||
return -EIO;
|
||||
ret = -EIO;
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
|
||||
@ -2196,7 +2239,12 @@ int dib9000_i2c_enumeration(struct i2c_adapter *i2c, int no_of_demods, u8 defaul
|
||||
dib9000_i2c_write16(&client, 1795, 0);
|
||||
}
|
||||
|
||||
return 0;
|
||||
error:
|
||||
kfree(client.i2c_read_buffer);
|
||||
error_memory:
|
||||
kfree(client.i2c_write_buffer);
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(dib9000_i2c_enumeration);
|
||||
|
||||
@ -2263,6 +2311,8 @@ struct dvb_frontend *dib9000_attach(struct i2c_adapter *i2c_adap, u8 i2c_addr, c
|
||||
memcpy(&st->chip.d9.cfg, cfg, sizeof(struct dib9000_config));
|
||||
st->i2c.i2c_adap = i2c_adap;
|
||||
st->i2c.i2c_addr = i2c_addr;
|
||||
st->i2c.i2c_write_buffer = st->i2c_write_buffer;
|
||||
st->i2c.i2c_read_buffer = st->i2c_read_buffer;
|
||||
|
||||
st->gpio_dir = DIB9000_GPIO_DEFAULT_DIRECTIONS;
|
||||
st->gpio_val = DIB9000_GPIO_DEFAULT_VALUES;
|
||||
|
@ -10,30 +10,39 @@ MODULE_PARM_DESC(debug, "turn on debugging (default: 0)");
|
||||
|
||||
static int dibx000_write_word(struct dibx000_i2c_master *mst, u16 reg, u16 val)
|
||||
{
|
||||
u8 b[4] = {
|
||||
(reg >> 8) & 0xff, reg & 0xff,
|
||||
(val >> 8) & 0xff, val & 0xff,
|
||||
};
|
||||
struct i2c_msg msg = {
|
||||
.addr = mst->i2c_addr,.flags = 0,.buf = b,.len = 4
|
||||
};
|
||||
mst->i2c_write_buffer[0] = (reg >> 8) & 0xff;
|
||||
mst->i2c_write_buffer[1] = reg & 0xff;
|
||||
mst->i2c_write_buffer[2] = (val >> 8) & 0xff;
|
||||
mst->i2c_write_buffer[3] = val & 0xff;
|
||||
|
||||
return i2c_transfer(mst->i2c_adap, &msg, 1) != 1 ? -EREMOTEIO : 0;
|
||||
memset(mst->msg, 0, sizeof(struct i2c_msg));
|
||||
mst->msg[0].addr = mst->i2c_addr;
|
||||
mst->msg[0].flags = 0;
|
||||
mst->msg[0].buf = mst->i2c_write_buffer;
|
||||
mst->msg[0].len = 4;
|
||||
|
||||
return i2c_transfer(mst->i2c_adap, mst->msg, 1) != 1 ? -EREMOTEIO : 0;
|
||||
}
|
||||
|
||||
static u16 dibx000_read_word(struct dibx000_i2c_master *mst, u16 reg)
|
||||
{
|
||||
u8 wb[2] = { reg >> 8, reg & 0xff };
|
||||
u8 rb[2];
|
||||
struct i2c_msg msg[2] = {
|
||||
{.addr = mst->i2c_addr, .flags = 0, .buf = wb, .len = 2},
|
||||
{.addr = mst->i2c_addr, .flags = I2C_M_RD, .buf = rb, .len = 2},
|
||||
};
|
||||
mst->i2c_write_buffer[0] = reg >> 8;
|
||||
mst->i2c_write_buffer[1] = reg & 0xff;
|
||||
|
||||
if (i2c_transfer(mst->i2c_adap, msg, 2) != 2)
|
||||
memset(mst->msg, 0, 2 * sizeof(struct i2c_msg));
|
||||
mst->msg[0].addr = mst->i2c_addr;
|
||||
mst->msg[0].flags = 0;
|
||||
mst->msg[0].buf = mst->i2c_write_buffer;
|
||||
mst->msg[0].len = 2;
|
||||
mst->msg[1].addr = mst->i2c_addr;
|
||||
mst->msg[1].flags = I2C_M_RD;
|
||||
mst->msg[1].buf = mst->i2c_read_buffer;
|
||||
mst->msg[1].len = 2;
|
||||
|
||||
if (i2c_transfer(mst->i2c_adap, mst->msg, 2) != 2)
|
||||
dprintk("i2c read error on %d", reg);
|
||||
|
||||
return (rb[0] << 8) | rb[1];
|
||||
return (mst->i2c_read_buffer[0] << 8) | mst->i2c_read_buffer[1];
|
||||
}
|
||||
|
||||
static int dibx000_is_i2c_done(struct dibx000_i2c_master *mst)
|
||||
@ -248,26 +257,32 @@ static int dibx000_i2c_gated_gpio67_xfer(struct i2c_adapter *i2c_adap,
|
||||
struct i2c_msg msg[], int num)
|
||||
{
|
||||
struct dibx000_i2c_master *mst = i2c_get_adapdata(i2c_adap);
|
||||
struct i2c_msg m[2 + num];
|
||||
u8 tx_open[4], tx_close[4];
|
||||
|
||||
memset(m, 0, sizeof(struct i2c_msg) * (2 + num));
|
||||
if (num > 32) {
|
||||
dprintk("%s: too much I2C message to be transmitted (%i).\
|
||||
Maximum is 32", __func__, num);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
memset(mst->msg, 0, sizeof(struct i2c_msg) * (2 + num));
|
||||
|
||||
dibx000_i2c_select_interface(mst, DIBX000_I2C_INTERFACE_GPIO_6_7);
|
||||
|
||||
dibx000_i2c_gate_ctrl(mst, tx_open, msg[0].addr, 1);
|
||||
m[0].addr = mst->i2c_addr;
|
||||
m[0].buf = tx_open;
|
||||
m[0].len = 4;
|
||||
/* open the gate */
|
||||
dibx000_i2c_gate_ctrl(mst, &mst->i2c_write_buffer[0], msg[0].addr, 1);
|
||||
mst->msg[0].addr = mst->i2c_addr;
|
||||
mst->msg[0].buf = &mst->i2c_write_buffer[0];
|
||||
mst->msg[0].len = 4;
|
||||
|
||||
memcpy(&m[1], msg, sizeof(struct i2c_msg) * num);
|
||||
memcpy(&mst->msg[1], msg, sizeof(struct i2c_msg) * num);
|
||||
|
||||
dibx000_i2c_gate_ctrl(mst, tx_close, 0, 0);
|
||||
m[num + 1].addr = mst->i2c_addr;
|
||||
m[num + 1].buf = tx_close;
|
||||
m[num + 1].len = 4;
|
||||
/* close the gate */
|
||||
dibx000_i2c_gate_ctrl(mst, &mst->i2c_write_buffer[4], 0, 0);
|
||||
mst->msg[num + 1].addr = mst->i2c_addr;
|
||||
mst->msg[num + 1].buf = &mst->i2c_write_buffer[4];
|
||||
mst->msg[num + 1].len = 4;
|
||||
|
||||
return i2c_transfer(mst->i2c_adap, m, 2 + num) == 2 + num ? num : -EIO;
|
||||
return i2c_transfer(mst->i2c_adap, mst->msg, 2 + num) == 2 + num ? num : -EIO;
|
||||
}
|
||||
|
||||
static struct i2c_algorithm dibx000_i2c_gated_gpio67_algo = {
|
||||
@ -279,26 +294,32 @@ static int dibx000_i2c_gated_tuner_xfer(struct i2c_adapter *i2c_adap,
|
||||
struct i2c_msg msg[], int num)
|
||||
{
|
||||
struct dibx000_i2c_master *mst = i2c_get_adapdata(i2c_adap);
|
||||
struct i2c_msg m[2 + num];
|
||||
u8 tx_open[4], tx_close[4];
|
||||
|
||||
memset(m, 0, sizeof(struct i2c_msg) * (2 + num));
|
||||
if (num > 32) {
|
||||
dprintk("%s: too much I2C message to be transmitted (%i).\
|
||||
Maximum is 32", __func__, num);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
memset(mst->msg, 0, sizeof(struct i2c_msg) * (2 + num));
|
||||
|
||||
dibx000_i2c_select_interface(mst, DIBX000_I2C_INTERFACE_TUNER);
|
||||
|
||||
dibx000_i2c_gate_ctrl(mst, tx_open, msg[0].addr, 1);
|
||||
m[0].addr = mst->i2c_addr;
|
||||
m[0].buf = tx_open;
|
||||
m[0].len = 4;
|
||||
/* open the gate */
|
||||
dibx000_i2c_gate_ctrl(mst, &mst->i2c_write_buffer[0], msg[0].addr, 1);
|
||||
mst->msg[0].addr = mst->i2c_addr;
|
||||
mst->msg[0].buf = &mst->i2c_write_buffer[0];
|
||||
mst->msg[0].len = 4;
|
||||
|
||||
memcpy(&m[1], msg, sizeof(struct i2c_msg) * num);
|
||||
memcpy(&mst->msg[1], msg, sizeof(struct i2c_msg) * num);
|
||||
|
||||
dibx000_i2c_gate_ctrl(mst, tx_close, 0, 0);
|
||||
m[num + 1].addr = mst->i2c_addr;
|
||||
m[num + 1].buf = tx_close;
|
||||
m[num + 1].len = 4;
|
||||
/* close the gate */
|
||||
dibx000_i2c_gate_ctrl(mst, &mst->i2c_write_buffer[4], 0, 0);
|
||||
mst->msg[num + 1].addr = mst->i2c_addr;
|
||||
mst->msg[num + 1].buf = &mst->i2c_write_buffer[4];
|
||||
mst->msg[num + 1].len = 4;
|
||||
|
||||
return i2c_transfer(mst->i2c_adap, m, 2 + num) == 2 + num ? num : -EIO;
|
||||
return i2c_transfer(mst->i2c_adap, mst->msg, 2 + num) == 2 + num ? num : -EIO;
|
||||
}
|
||||
|
||||
static struct i2c_algorithm dibx000_i2c_gated_tuner_algo = {
|
||||
|
@ -28,6 +28,11 @@ struct dibx000_i2c_master {
|
||||
u8 i2c_addr;
|
||||
|
||||
u16 base_reg;
|
||||
|
||||
/* for the I2C transfer */
|
||||
struct i2c_msg msg[34];
|
||||
u8 i2c_write_buffer[8];
|
||||
u8 i2c_read_buffer[2];
|
||||
};
|
||||
|
||||
extern int dibx000_init_i2c_master(struct dibx000_i2c_master *mst,
|
||||
|
Loading…
Reference in New Issue
Block a user