From: Oliver Endriss <o.endriss@gmx.de>
To: linux-dvb@linuxtv.org
Subject: Re: [linux-dvb] Support of Nova S SE DVB card missing
Date: Sun, 24 Aug 2008 06:56:43 +0200 [thread overview]
Message-ID: <200808240656.45936@orion.escape-edv.de> (raw)
In-Reply-To: <200808231842.36465@orion.escape-edv.de>
[-- Attachment #1: Type: text/plain, Size: 2048 bytes --]
Hi,
Oliver Endriss wrote:
> Patrick Boettcher wrote:
> > On Sat, 23 Aug 2008, Oliver Endriss wrote:
> > >> In addition (see my other mail in that thread), sending two independent
> > >> i2c_transfers which actually belong together is not really safe.
> > >
> > > The current code in the else path will *never* work, because the tuner
> > > does not support repeated start conditions. The problem is not the I2C
> > > master (saa7146/flexcop) but the I2C slave (s5h1420).
> >
> > Wouldn't it be more correct to have a flag signaling to the
> > i2c_tranfer-function that a repeated start is not wanted even though it is
> > two i2c-messages glued (which are interpreted today as a read with
> > repeated start).
>
> I remember that we had the same discussion for the stv0297 driver a long
> time ago.
See
http://linuxtv.org/pipermail/linux-dvb/2007-May/018122.html
for this interesting discussion.
Obviously the i2c maintainers were not willing to add the I2C_M_STOP
flag...
> For the stv0297 I have an experimental patch which intercepts the
> master_xfer routine, but this is not very nice either.
See attachment. It will probably not apply to the current tree, but you
should get the idea. Anyway, I don't want to add this crap to a frontend
driver. It does not fix the userspace issues anyway.
For now I suggest to use the good old double i2c_transfer() approach for
the budget driver.
Btw, I still do not understand how your repeated_start_workaround works.
struct i2c_msg msg[] = {
{ .addr = state->config->demod_address, .flags = 0, .buf = b, .len = 2 },
{ .addr = state->config->demod_address, .flags = 0, .buf = ®, .len = 1 },
{ .addr = state->config->demod_address, .flags = I2C_M_RD, .buf = b, .len = 1 },
};
What does the flexcop master_xfer send over the i2c bus when it receives
these messages?
CU
Oliver
--
----------------------------------------------------------------
VDR Remote Plugin 0.4.0: http://www.escape-edv.de/endriss/vdr/
----------------------------------------------------------------
[-- Attachment #2: stv0297_restart_workaround.diff --]
[-- Type: text/x-diff, Size: 5077 bytes --]
diff -r 8f9147c3bacd linux/drivers/media/dvb/frontends/stv0297.c
--- a/linux/drivers/media/dvb/frontends/stv0297.c Wed Aug 01 12:14:44 2007 -0300
+++ b/linux/drivers/media/dvb/frontends/stv0297.c Wed Aug 01 23:02:17 2007 +0200
@@ -35,6 +35,10 @@ struct stv0297_state {
const struct stv0297_config *config;
struct dvb_frontend frontend;
+ /* workaround, chip does not support repeated start condition */
+ struct i2c_algorithm i2c_algo_virt;
+ struct i2c_adapter i2c_adap_virt;
+
unsigned long last_ber;
unsigned long base_freq;
};
@@ -47,6 +51,29 @@ struct stv0297_state {
#define STV0297_CLOCK_KHZ 28900
+
+static int stv0297_master_xfer_virt (struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
+{
+ struct stv0297_state *state = i2c_get_adapdata(adap);
+ struct i2c_adapter *i2c_phys = adap->algo_data;
+ int i, rc;
+
+ if (num == 2 &&
+ msgs[0].addr == state->config->demod_address &&
+ msgs[1].addr == state->config->demod_address &&
+ msgs[0].flags == 0 && msgs[1].flags == I2C_M_RD) {
+ /* device needs a STOP between the register and data */
+ for (i = 0; i < num; i++) {
+ rc = i2c_transfer(i2c_phys, msgs+i, 1);
+ if (rc != 1)
+ return rc;
+ }
+ rc = num;
+ } else
+ rc = i2c_transfer(i2c_phys, msgs, num);
+
+ return rc;
+}
static int stv0297_writereg(struct stv0297_state *state, u8 reg, u8 data)
{
@@ -72,21 +99,9 @@ static int stv0297_readreg(struct stv029
{.addr = state->config->demod_address,.flags = I2C_M_RD,.buf = b1,.len = 1}
};
- // this device needs a STOP between the register and data
- if (state->config->stop_during_read) {
- if ((ret = i2c_transfer(state->i2c, &msg[0], 1)) != 1) {
- dprintk("%s: readreg error (reg == 0x%02x, ret == %i)\n", __FUNCTION__, reg, ret);
- return -1;
- }
- if ((ret = i2c_transfer(state->i2c, &msg[1], 1)) != 1) {
- dprintk("%s: readreg error (reg == 0x%02x, ret == %i)\n", __FUNCTION__, reg, ret);
- return -1;
- }
- } else {
- if ((ret = i2c_transfer(state->i2c, msg, 2)) != 2) {
- dprintk("%s: readreg error (reg == 0x%02x, ret == %i)\n", __FUNCTION__, reg, ret);
- return -1;
- }
+ if ((ret = i2c_transfer(state->i2c, msg, 2)) != 2) {
+ dprintk("%s: readreg error (reg == 0x%02x, ret == %i)\n", __FUNCTION__, reg, ret);
+ return -1;
}
return b1[0];
@@ -107,26 +122,13 @@ static int stv0297_readregs(struct stv02
static int stv0297_readregs(struct stv0297_state *state, u8 reg1, u8 * b, u8 len)
{
int ret;
- struct i2c_msg msg[] = { {.addr = state->config->demod_address,.flags = 0,.buf =
- ®1,.len = 1},
- {.addr = state->config->demod_address,.flags = I2C_M_RD,.buf = b,.len = len}
- };
-
- // this device needs a STOP between the register and data
- if (state->config->stop_during_read) {
- if ((ret = i2c_transfer(state->i2c, &msg[0], 1)) != 1) {
- dprintk("%s: readreg error (reg == 0x%02x, ret == %i)\n", __FUNCTION__, reg1, ret);
- return -1;
- }
- if ((ret = i2c_transfer(state->i2c, &msg[1], 1)) != 1) {
- dprintk("%s: readreg error (reg == 0x%02x, ret == %i)\n", __FUNCTION__, reg1, ret);
- return -1;
- }
- } else {
- if ((ret = i2c_transfer(state->i2c, msg, 2)) != 2) {
- dprintk("%s: readreg error (reg == 0x%02x, ret == %i)\n", __FUNCTION__, reg1, ret);
- return -1;
- }
+ struct i2c_msg msg[] = { {.addr = state->config->demod_address,.flags = 0,.buf = ®1,.len = 1},
+ {.addr = state->config->demod_address,.flags = I2C_M_RD,.buf = b,.len = len}
+ };
+
+ if ((ret = i2c_transfer(state->i2c, msg, 2)) != 2) {
+ dprintk("%s: readreg error (reg == 0x%02x, ret == %i)\n", __FUNCTION__, reg1, ret);
+ return -1;
}
return 0;
@@ -651,15 +653,30 @@ struct dvb_frontend *stv0297_attach(cons
struct stv0297_state *state = NULL;
/* allocate memory for the internal state */
- state = kmalloc(sizeof(struct stv0297_state), GFP_KERNEL);
+ state = kzalloc(sizeof(struct stv0297_state), GFP_KERNEL);
if (state == NULL)
goto error;
/* setup the state */
state->config = config;
- state->i2c = i2c;
- state->last_ber = 0;
- state->base_freq = 0;
+ if (state->config->stop_during_read) {
+ state->i2c_algo_virt.master_xfer = stv0297_master_xfer_virt;
+ state->i2c_algo_virt.functionality = i2c->algo->functionality;
+
+ state->i2c_adap_virt.id = i2c->id;
+ state->i2c_adap_virt.class = i2c->class;
+ state->i2c_adap_virt.algo = &state->i2c_algo_virt;
+ state->i2c_adap_virt.algo_data = i2c;
+ state->i2c_adap_virt.timeout = i2c->timeout;
+ state->i2c_adap_virt.retries = i2c->retries;
+ state->i2c_adap_virt.dev.parent = i2c->dev.parent;
+ i2c_set_adapdata(&state->i2c_adap_virt, state);
+
+ if (i2c_add_adapter(&state->i2c_adap_virt) < 0)
+ goto error;
+ state->i2c = &state->i2c_adap_virt;
+ } else
+ state->i2c = i2c;
/* check if the demod is there */
if ((stv0297_readreg(state, 0x80) & 0x70) != 0x20)
@@ -671,6 +688,8 @@ struct dvb_frontend *stv0297_attach(cons
return &state->frontend;
error:
+ if (state && state->config->stop_during_read && state->i2c)
+ i2c_del_adapter(state->i2c);
kfree(state);
return NULL;
}
[-- Attachment #3: Type: text/plain, Size: 150 bytes --]
_______________________________________________
linux-dvb mailing list
linux-dvb@linuxtv.org
http://www.linuxtv.org/cgi-bin/mailman/listinfo/linux-dvb
next prev parent reply other threads:[~2008-08-24 5:07 UTC|newest]
Thread overview: 14+ messages / expand[flat|nested] mbox.gz Atom feed top
2008-08-23 13:15 [linux-dvb] Support of Nova S SE DVB card missing Eberhard Kaltenhaeuser
2008-08-23 13:57 ` e9hack
2008-08-23 15:09 ` Patrick Boettcher
2008-08-23 15:26 ` e9hack
2008-08-23 18:17 ` Eberhard Kaltenhaeuser
2008-08-23 15:11 ` Oliver Endriss
2008-08-23 15:21 ` Patrick Boettcher
2008-08-23 15:48 ` Oliver Endriss
2008-08-23 15:53 ` Patrick Boettcher
2008-08-23 16:42 ` Oliver Endriss
2008-08-23 17:21 ` Oliver Endriss
2008-08-24 4:56 ` Oliver Endriss [this message]
2008-08-24 8:12 ` Eberhard Kaltenhaeuser
2008-08-28 15:48 ` Eberhard Kaltenhaeuser
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=200808240656.45936@orion.escape-edv.de \
--to=o.endriss@gmx.de \
--cc=linux-dvb@linuxtv.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox