From: Antti Palosaari <crope@iki.fi>
To: Jose Alberto Reguero <jareguero@telefonica.net>
Cc: Mauro Carvalho Chehab <mchehab@redhat.com>,
linux-media@vger.kernel.org,
Michael Krufky <mkrufky@kernellabs.com>
Subject: Re: [PATCH] add support for the dvb-t part of CT-3650 v3
Date: Wed, 20 Jul 2011 02:07:54 +0300 [thread overview]
Message-ID: <4E260E4A.2020707@iki.fi> (raw)
In-Reply-To: <201107191025.49662.jareguero@telefonica.net>
[-- Attachment #1: Type: text/plain, Size: 2233 bytes --]
On 07/19/2011 11:25 AM, Jose Alberto Reguero wrote:
> On Martes, 19 de Julio de 2011 01:44:54 Antti Palosaari escribió:
>> On 07/19/2011 02:00 AM, Jose Alberto Reguero wrote:
>>> On Lunes, 18 de Julio de 2011 22:28:41 Antti Palosaari escribió:
>>> There are two problems:
>>>
>>> First, the two frontends (tda10048 and tda10023) use tda10023 i2c gate
>>> to talk with the tuner.
>>
>> Very easy to implement correctly. Attach tda10023 first and after that
>> tda10048. Override tda10048 .i2c_gate_ctrl() with tda10023
>> .i2c_gate_ctrl() immediately after tda10048 attach inside ttusb2.c. Now
>> you have both demods (FEs) .i2c_gate_ctrl() which will control
>> physically tda10023 I2C-gate as tuner is behind it.
>>
>
> I try that, but don't work. I get an oops. Because the i2c gate function of
> the tda10023 driver use:
>
> struct tda10023_state* state = fe->demodulator_priv;
>
> to get the i2c adress. When called from tda10048, don't work.
>
> Jose Alberto
>
>>> The second is that with dvb-usb, there is only one frontend, and if you
>>> wake up the second frontend, the adapter is not wake up. That can be
>>> avoided the way I do in the patch, or mantaining the adapter alwais on.
>>
>> I think that could be also avoided similarly overriding demod callbacks
>> and adding some more logic inside ttusb2.c.
>>
>> Proper fix that later problem is surely correct MFE support for
>> DVB-USB-framework. I am now looking for it, lets see how difficult it
>> will be.
Signed-off-by: Antti Palosaari <crope@iki.fi>
Test attached patches and try to fix if they are not working. Most
likely not working since I don't have HW to test... I tested MFE parts
using Anysee, so it should be working. I changed rather much your ttusb2
and tda10048 patches, size reduced something like 50% or more. Still
ttusb2 I2C-adapter changes made looks rather complex. Try to double
check if those can be done easier. There is many drivers to look example
from.
DVB USB MFE is something like RFC. I know FE exclusive lock is missing,
no need to mention that :) But other comments are welcome! I left three
old "unneeded" pointers to struct dvb_usb_adapter to reduce changing all
the drivers.
regards
Antti
--
http://palosaari.fi/
[-- Attachment #2: dvb_usb_mfe_v1.patch --]
[-- Type: text/plain, Size: 4433 bytes --]
diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-dvb.c b/drivers/media/dvb/dvb-usb/dvb-usb-dvb.c
index b3cb626..51c716f 100644
--- a/drivers/media/dvb/dvb-usb/dvb-usb-dvb.c
+++ b/drivers/media/dvb/dvb-usb/dvb-usb-dvb.c
@@ -162,8 +162,8 @@ static int dvb_usb_fe_wakeup(struct dvb_frontend *fe)
dvb_usb_device_power_ctrl(adap->dev, 1);
- if (adap->fe_init)
- adap->fe_init(fe);
+ if (adap->mfe_init[fe->id])
+ adap->mfe_init[fe->id](fe);
return 0;
}
@@ -172,35 +172,66 @@ static int dvb_usb_fe_sleep(struct dvb_frontend *fe)
{
struct dvb_usb_adapter *adap = fe->dvb->priv;
- if (adap->fe_sleep)
- adap->fe_sleep(fe);
+ if (adap->mfe_sleep[fe->id])
+ adap->mfe_sleep[fe->id](fe);
return dvb_usb_device_power_ctrl(adap->dev, 0);
}
int dvb_usb_adapter_frontend_init(struct dvb_usb_adapter *adap)
{
+ int ret, i, num_frontends;
+
if (adap->props.frontend_attach == NULL) {
- err("strange: '%s' #%d doesn't want to attach a frontend.",adap->dev->desc->name, adap->id);
+ err("strange: '%s' #%d doesn't want to attach a frontend.",
+ adap->dev->desc->name, adap->id);
return 0;
}
- /* re-assign sleep and wakeup functions */
- if (adap->props.frontend_attach(adap) == 0 && adap->fe != NULL) {
- adap->fe_init = adap->fe->ops.init; adap->fe->ops.init = dvb_usb_fe_wakeup;
- adap->fe_sleep = adap->fe->ops.sleep; adap->fe->ops.sleep = dvb_usb_fe_sleep;
+ if (adap->props.num_frontends)
+ num_frontends = adap->props.num_frontends;
+ else
+ num_frontends = 1;
+
+ for (i = 0; i < num_frontends; i++) {
+
+ ret = adap->props.frontend_attach(adap);
+ if (ret)
+ break;
+
+ /* glue for backward compatibility */
+ if (i == 0) {
+ if (adap->mfe[i])
+ adap->fe = adap->mfe[i];
+ else
+ adap->mfe[i] = adap->fe;
+ }
+
+ if (adap->mfe[i] == NULL)
+ break;
+
+ /* re-assign sleep and wakeup functions */
+ adap->mfe_init[i] = adap->mfe[i]->ops.init;
+ adap->mfe_sleep[i] = adap->mfe[i]->ops.sleep;
+ adap->mfe[i]->ops.init = dvb_usb_fe_wakeup;
+ adap->mfe[i]->ops.sleep = dvb_usb_fe_sleep;
- if (dvb_register_frontend(&adap->dvb_adap, adap->fe)) {
- err("Frontend registration failed.");
+ adap->mfe[i]->id = i;
+ if (dvb_register_frontend(&adap->dvb_adap, adap->mfe[i])) {
+ err("Frontend %d registration failed.", i);
dvb_frontend_detach(adap->fe);
- adap->fe = NULL;
+ adap->mfe[i] = NULL;
+ if (adap->mfe[0] == NULL)
+ adap->fe = NULL;
return -ENODEV;
}
/* only attach the tuner if the demod is there */
if (adap->props.tuner_attach != NULL)
adap->props.tuner_attach(adap);
- } else
+ }
+
+ if (adap->mfe[0] == NULL)
err("no frontend was attached by '%s'",adap->dev->desc->name);
return 0;
@@ -208,9 +239,22 @@ int dvb_usb_adapter_frontend_init(struct dvb_usb_adapter *adap)
int dvb_usb_adapter_frontend_exit(struct dvb_usb_adapter *adap)
{
- if (adap->fe != NULL) {
- dvb_unregister_frontend(adap->fe);
- dvb_frontend_detach(adap->fe);
+ int i, num_frontends;
+
+ if (adap->props.num_frontends)
+ num_frontends = adap->props.num_frontends;
+ else
+ num_frontends = 1;
+
+ for (i = 0; i < num_frontends; i++) {
+ if (adap->mfe[i] != NULL) {
+ dvb_unregister_frontend(adap->mfe[i]);
+ dvb_frontend_detach(adap->mfe[i]);
+ }
}
+
+ if (adap->mfe[0] == NULL)
+ adap->fe = NULL;
+
return 0;
}
diff --git a/drivers/media/dvb/dvb-usb/dvb-usb.h b/drivers/media/dvb/dvb-usb/dvb-usb.h
index 7d35d07..05d7032 100644
--- a/drivers/media/dvb/dvb-usb/dvb-usb.h
+++ b/drivers/media/dvb/dvb-usb/dvb-usb.h
@@ -146,6 +146,7 @@ struct dvb_usb_adapter_properties {
int (*pid_filter_ctrl) (struct dvb_usb_adapter *, int);
int (*pid_filter) (struct dvb_usb_adapter *, int, u16, int);
+ int num_frontends;
int (*frontend_attach) (struct dvb_usb_adapter *);
int (*tuner_attach) (struct dvb_usb_adapter *);
@@ -359,15 +360,19 @@ struct dvb_usb_adapter {
int pid_filtering;
/* dvb */
+#define DVB_USB_FE_MAX_NUM 2
struct dvb_adapter dvb_adap;
struct dmxdev dmxdev;
struct dvb_demux demux;
struct dvb_net dvb_net;
struct dvb_frontend *fe;
+ struct dvb_frontend *mfe[DVB_USB_FE_MAX_NUM];
int max_feed_count;
int (*fe_init) (struct dvb_frontend *);
int (*fe_sleep) (struct dvb_frontend *);
+ int (*mfe_init[DVB_USB_FE_MAX_NUM]) (struct dvb_frontend *);
+ int (*mfe_sleep[DVB_USB_FE_MAX_NUM]) (struct dvb_frontend *);
struct usb_data_stream stream;
[-- Attachment #3: tda10048_v1.patch --]
[-- Type: text/plain, Size: 2242 bytes --]
diff --git a/drivers/media/dvb/frontends/tda10048.c b/drivers/media/dvb/frontends/tda10048.c
index 93f6a75..c77ad1e 100644
--- a/drivers/media/dvb/frontends/tda10048.c
+++ b/drivers/media/dvb/frontends/tda10048.c
@@ -214,6 +214,8 @@ static struct pll_tab {
{ TDA10048_CLK_16000, TDA10048_IF_3800, 10, 3, 0 },
{ TDA10048_CLK_16000, TDA10048_IF_4000, 10, 3, 0 },
{ TDA10048_CLK_16000, TDA10048_IF_4300, 10, 3, 0 },
+ { TDA10048_CLK_16000, TDA10048_IF_4500, 5, 3, 0 },
+ { TDA10048_CLK_16000, TDA10048_IF_5000, 5, 3, 0 },
{ TDA10048_CLK_16000, TDA10048_IF_36130, 10, 3, 0 },
};
@@ -478,6 +480,11 @@ static int tda10048_set_if(struct dvb_frontend *fe, enum fe_bandwidth bw)
dprintk(1, "- pll_nfactor = %d\n", state->pll_nfactor);
dprintk(1, "- pll_pfactor = %d\n", state->pll_pfactor);
+ /* Set the pll registers */
+ tda10048_writereg(state, TDA10048_CONF_PLL1, 0x0f);
+ tda10048_writereg(state, TDA10048_CONF_PLL2, (u8)(state->pll_mfactor));
+ tda10048_writereg(state, TDA10048_CONF_PLL3, tda10048_readreg(state, TDA10048_CONF_PLL3) | ((u8)(state->pll_nfactor) | 0x40));
+
/* Calculate the sample frequency */
state->sample_freq = state->xtal_hz * (state->pll_mfactor + 45);
state->sample_freq /= (state->pll_nfactor + 1);
@@ -1123,7 +1130,7 @@ struct dvb_frontend *tda10048_attach(const struct tda10048_config *config,
/* setup the state and clone the config */
memcpy(&state->config, config, sizeof(*config));
state->i2c = i2c;
- state->fwloaded = 0;
+ state->fwloaded = config->no_firmware;
state->bandwidth = BANDWIDTH_8_MHZ;
/* check if the demod is present */
diff --git a/drivers/media/dvb/frontends/tda10048.h b/drivers/media/dvb/frontends/tda10048.h
index 8828cea..3da0e0c 100644
--- a/drivers/media/dvb/frontends/tda10048.h
+++ b/drivers/media/dvb/frontends/tda10048.h
@@ -51,6 +51,7 @@ struct tda10048_config {
#define TDA10048_IF_4300 4300
#define TDA10048_IF_4500 4500
#define TDA10048_IF_4750 4750
+#define TDA10048_IF_5000 5000
#define TDA10048_IF_36130 36130
u16 dtv6_if_freq_khz;
u16 dtv7_if_freq_khz;
@@ -62,6 +63,8 @@ struct tda10048_config {
/* Disable I2C gate access */
u8 disable_gate_access;
+
+ bool no_firmware;
};
#if defined(CONFIG_DVB_TDA10048) || \
[-- Attachment #4: ttusb2_v1.patch --]
[-- Type: text/plain, Size: 4223 bytes --]
diff --git a/drivers/media/dvb/dvb-usb/ttusb2.c b/drivers/media/dvb/dvb-usb/ttusb2.c
index 0d4709f..59f5614 100644
--- a/drivers/media/dvb/dvb-usb/ttusb2.c
+++ b/drivers/media/dvb/dvb-usb/ttusb2.c
@@ -30,6 +30,7 @@
#include "tda826x.h"
#include "tda10086.h"
#include "tda1002x.h"
+#include "tda10048.h"
#include "tda827x.h"
#include "lnbp21.h"
@@ -82,7 +83,7 @@ static int ttusb2_i2c_xfer(struct i2c_adapter *adap,struct i2c_msg msg[],int num
{
struct dvb_usb_device *d = i2c_get_adapdata(adap);
static u8 obuf[60], ibuf[60];
- int i,read;
+ int i, read1, read2;
if (mutex_lock_interruptible(&d->i2c_mutex) < 0)
return -EAGAIN;
@@ -91,27 +92,33 @@ static int ttusb2_i2c_xfer(struct i2c_adapter *adap,struct i2c_msg msg[],int num
warn("more than 2 i2c messages at a time is not handled yet. TODO.");
for (i = 0; i < num; i++) {
- read = i+1 < num && (msg[i+1].flags & I2C_M_RD);
+ read1 = i+1 < num && (msg[i+1].flags & I2C_M_RD);
+ read2 = msg[i].flags & I2C_M_RD;
- obuf[0] = (msg[i].addr << 1) | read;
+ obuf[0] = (msg[i].addr << 1) | (read1 | read2);
obuf[1] = msg[i].len;
/* read request */
- if (read)
+ if (read1)
obuf[2] = msg[i+1].len;
+ else if (read2)
+ obuf[2] = msg[i].len;
else
obuf[2] = 0;
- memcpy(&obuf[3],msg[i].buf,msg[i].len);
+ memcpy(&obuf[3], msg[i].buf, msg[i].len);
if (ttusb2_msg(d, CMD_I2C_XFER, obuf, msg[i].len+3, ibuf, obuf[2] + 3) < 0) {
err("i2c transfer failed.");
break;
}
- if (read) {
- memcpy(msg[i+1].buf,&ibuf[3],msg[i+1].len);
- i++;
+ if (read1 || read2) {
+ if (read1) {
+ memcpy(msg[i+1].buf, &ibuf[3], msg[i+1].len);
+ i++;
+ } else if (read2)
+ memcpy(msg[i].buf, &ibuf[3], msg[i].len);
}
}
@@ -190,6 +197,21 @@ static struct tda10023_config tda10023_config = {
.deltaf = 0xa511,
};
+static struct tda10048_config tda10048_config = {
+ .demod_address = 0x10 >> 1,
+ .output_mode = TDA10048_PARALLEL_OUTPUT,
+ .inversion = TDA10048_INVERSION_ON,
+ .dtv6_if_freq_khz = TDA10048_IF_4000,
+ .dtv7_if_freq_khz = TDA10048_IF_4500,
+ .dtv8_if_freq_khz = TDA10048_IF_5000,
+ .clk_freq_khz = TDA10048_CLK_16000,
+ .no_firmware = 1,
+};
+
+static struct tda827x_config tda827x_config = {
+ .config = 0,
+};
+
static int ttusb2_frontend_tda10086_attach(struct dvb_usb_adapter *adap)
{
if (usb_set_interface(adap->dev->udev,0,3) < 0)
@@ -207,19 +229,49 @@ static int ttusb2_frontend_tda10023_attach(struct dvb_usb_adapter *adap)
{
if (usb_set_interface(adap->dev->udev, 0, 3) < 0)
err("set interface to alts=3 failed");
- if ((adap->fe = dvb_attach(tda10023_attach, &tda10023_config, &adap->dev->i2c_adap, 0x48)) == NULL) {
- deb_info("TDA10023 attach failed\n");
- return -ENODEV;
+
+ if (adap->mfe[0] == NULL) {
+ /* FE 0 DVB-C */
+ adap->mfe[0] = dvb_attach(tda10023_attach,
+ &tda10023_config, &adap->dev->i2c_adap, 0x48);
+
+ if (adap->mfe[0] == NULL) {
+ deb_info("TDA10023 attach failed\n");
+ return -ENODEV;
+ }
+ } else {
+ /* FE 1 DVB-T */
+ adap->mfe[1] = dvb_attach(tda10048_attach,
+ &tda10048_config, &adap->dev->i2c_adap);
+
+ if (adap->mfe[1] == NULL) {
+ deb_info("TDA10048 attach failed\n");
+ return -ENODEV;
+ }
+
+ /* tuner is behind TDA10023 I2C-gate */
+ adap->mfe[1]->ops.i2c_gate_ctrl = adap->mfe[0]->ops.i2c_gate_ctrl;
}
+
return 0;
}
static int ttusb2_tuner_tda827x_attach(struct dvb_usb_adapter *adap)
{
- if (dvb_attach(tda827x_attach, adap->fe, 0x61, &adap->dev->i2c_adap, NULL) == NULL) {
+ struct dvb_frontend *fe;
+
+ /* MFE: select correct FE to attach tuner since that's called twice */
+ if (adap->mfe[1] == NULL)
+ fe = adap->mfe[0];
+ else
+ fe = adap->mfe[1];
+
+ /* attach tuner */
+ if (dvb_attach(tda827x_attach, fe, 0x61, &adap->dev->i2c_adap, &tda827x_config) == NULL) {
printk(KERN_ERR "%s: No tda827x found!\n", __func__);
return -ENODEV;
}
+
return 0;
}
@@ -383,8 +435,7 @@ static struct dvb_usb_device_properties ttusb2_properties_ct3650 = {
.num_adapters = 1,
.adapter = {
{
- .streaming_ctrl = NULL,
-
+ .num_frontends = 2,
.frontend_attach = ttusb2_frontend_tda10023_attach,
.tuner_attach = ttusb2_tuner_tda827x_attach,
next prev parent reply other threads:[~2011-07-19 23:08 UTC|newest]
Thread overview: 28+ messages / expand[flat|nested] mbox.gz Atom feed top
[not found] <201106070205.08118.jareguero@telefonica.net>
[not found] ` <201107070057.06317.jareguero@telefonica.net>
2011-07-13 12:41 ` [PATCH] add support for the dvb-t part of CT-3650 v2 Mauro Carvalho Chehab
2011-07-14 20:00 ` [PATCH] add support for the dvb-t part of CT-3650 v3 Jose Alberto Reguero
2011-07-18 20:28 ` Antti Palosaari
2011-07-18 21:31 ` Michael Krufky
[not found] ` <201107190100.16802.jareguero@telefonica.net>
2011-07-18 23:44 ` Antti Palosaari
2011-07-19 8:25 ` Jose Alberto Reguero
2011-07-19 23:07 ` Antti Palosaari [this message]
2011-07-22 11:32 ` Antti Palosaari
2011-07-22 16:02 ` Jose Alberto Reguero
2011-07-22 16:08 ` Antti Palosaari
2011-07-22 16:25 ` Jose Alberto Reguero
2011-07-22 16:46 ` Antti Palosaari
[not found] ` <201107222012.20711.jareguero@telefonica.net>
2011-07-22 21:49 ` Jose Alberto Reguero
2011-07-22 22:23 ` Antti Palosaari
2011-07-23 8:26 ` Jose Alberto Reguero
2011-07-23 9:42 ` Antti Palosaari
2011-07-23 10:21 ` Jose Alberto Reguero
2011-07-23 10:37 ` Antti Palosaari
2011-07-23 15:41 ` Jose Alberto Reguero
2011-07-23 17:47 ` Antti Palosaari
2011-07-23 21:45 ` Jose Alberto Reguero
2011-07-27 19:22 ` Antti Palosaari
2011-07-28 19:25 ` Jose Alberto Reguero
2011-08-02 19:21 ` Jose Alberto Reguero
2011-08-08 10:35 ` Jose Alberto Reguero
2011-08-08 21:44 ` Antti Palosaari
2011-08-09 19:45 ` Jose Alberto Reguero
2011-07-16 11:38 ` [PATCH] improve recection with limits frecuenies and tda827x Jose Alberto Reguero
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=4E260E4A.2020707@iki.fi \
--to=crope@iki.fi \
--cc=jareguero@telefonica.net \
--cc=linux-media@vger.kernel.org \
--cc=mchehab@redhat.com \
--cc=mkrufky@kernellabs.com \
/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