[PATCH 3/3] radio-tea5761: Update driver

2008-06-10 Thread Eduardo Valentin
From: Eduardo Valentin <[EMAIL PROTECTED]>

This patch updates this driver by changing the way it accesses
the device. There is the tuner API which already has an implementation
for tea5761.

This patch changes the driver to use tuner API.

It also changes the way ioctls are handled. This way
it is more easy to deal with v4l2 and v4l calls.

Some cleans are also done.

Signed-off-by: Eduardo Valentin <[EMAIL PROTECTED]>
---
 drivers/media/radio/Kconfig |1 +
 drivers/media/radio/Makefile|2 +
 drivers/media/radio/radio-tea5761.c |  570 +--
 3 files changed, 278 insertions(+), 295 deletions(-)

diff --git a/drivers/media/radio/Kconfig b/drivers/media/radio/Kconfig
index de6ca27..b45f834 100644
--- a/drivers/media/radio/Kconfig
+++ b/drivers/media/radio/Kconfig
@@ -341,6 +341,7 @@ config RADIO_ZOLTRIX_PORT
 
 config RADIO_TEA5761
tristate "Philips Semiconductors TEA5761 I2C FM Radio"
+   depends on MEDIA_TUNER_TEA5761
help
  Choose Y here if you have one of these AM/FM radio cards.
 
diff --git a/drivers/media/radio/Makefile b/drivers/media/radio/Makefile
index f5bffcc..a843007 100644
--- a/drivers/media/radio/Makefile
+++ b/drivers/media/radio/Makefile
@@ -25,3 +25,5 @@ obj-$(CONFIG_USB_DSBR) += dsbr100.o
 obj-$(CONFIG_USB_SI470X) += radio-si470x.o
 
 EXTRA_CFLAGS += -Isound
+EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core/
+EXTRA_CFLAGS += -Idrivers/media/common/tuners/
diff --git a/drivers/media/radio/radio-tea5761.c 
b/drivers/media/radio/radio-tea5761.c
index e8ccf29..cc39a44 100644
--- a/drivers/media/radio/radio-tea5761.c
+++ b/drivers/media/radio/radio-tea5761.c
@@ -23,79 +23,29 @@
 #include 
 #include 
 #include 
+#include 
+
+#include "dvb_frontend.h"
+#include "tea5761.h"
 
 #define DRIVER_NAME "tea5761"
 
 #define TEA5761_VERSIONKERNEL_VERSION(0, 0, 1)
 
-#define TEA5761_I2C_ADDR   0x10
-
-#define TEA5761_MANID  0x002b
-#define TEA5761_CHIPID 0x5761
-
-#define TEA5761_INTREG_BLMSK   0x0001
-#define TEA5761_INTREG_FRRMSK  0x0002
-#define TEA5761_INTREG_LEVMSK  0x0008
-#define TEA5761_INTREG_IFMSK   0x0010
-#define TEA5761_INTREG_BLMFLAG 0x0100
-#define TEA5761_INTREG_FRRFLAG 0x0200
-#define TEA5761_INTREG_LEVFLAG 0x0800
-#define TEA5761_INTREG_IFFLAG  0x1000
-
-#define TEA5761_FRQSET_SUD 0x8000
-#define TEA5761_FRQSET_SM  0x4000
-
-#define TEA5761_TNCTRL_PUPD0   0x4000
-#define TEA5761_TNCTRL_BLIM0x2000
-#define TEA5761_TNCTRL_SWPM0x1000
-#define TEA5761_TNCTRL_IFCTC   0x0800
-#define TEA5761_TNCTRL_AFM 0x0400
-#define TEA5761_TNCTRL_SMUTE   0x0200
-#define TEA5761_TNCTRL_SNC 0x0100
-#define TEA5761_TNCTRL_MU  0x0080
-#define TEA5761_TNCTRL_SSL10x0040
-#define TEA5761_TNCTRL_SSL00x0020
-#define TEA5761_TNCTRL_HLSI0x0010
-#define TEA5761_TNCTRL_MST 0x0008
-#define TEA5761_TNCTRL_SWP 0x0004
-#define TEA5761_TNCTRL_DTC 0x0002
-#define TEA5761_TNCTRL_AHLSI   0x0001
-
-#define TEA5761_TUNCHK_LEVEL(x)(((x) & 0x00F0) >> 4)
-#define TEA5761_TUNCHK_IFCNT(x) (((x) & 0xFE00) >> 9)
-#define TEA5761_TUNCHK_TUNTO   0x0100
-#define TEA5761_TUNCHK_LD  0x0008
-#define TEA5761_TUNCHK_STEREO  0x0004
-
-#define TEA5761_TESTREG_TRIGFR 0x0800
-
 #define TEA5761_FREQ_LOW   87500
 #define TEA5761_FREQ_HIGH  108000
 
-struct tea5761_regs {
-   u16 intreg;
-   u16 frqset;
-   u16 tnctrl;
-   u16 frqchk;
-   u16 tunchk;
-   u16 testreg;
-   u16 manid;
-   u16 chipid;
-} __attribute__ ((packed));
-
-struct tea5761_write_regs {
-   u8 intreg;
-   u16 frqset;
-   u16 tnctrl;
-   u16 testreg;
-} __attribute__ ((packed));
-
 struct tea5761_device {
struct video_device *video_dev;
-   struct i2c_client   *i2c_dev;
-   struct tea5761_regs regs;
+   struct device   *dev;
+   struct dvb_frontend fe;
+   /* To control number of users access (.users field) */
struct mutexmutex;
int users;
+   unsigned intfreq;
+   u16 audmode;
+   u8  mute;
+   u8  power;
 };
 
 static struct tea5761_device tea5761;
@@ -103,267 +53,286 @@ static struct tea5761_device tea5761;
 static struct i2c_driver   tea5761_driver;
 static int radio_nr = -1;
 
-static int tea5761_read_regs(struct tea5761_device *tea)
+static void tea5761_power_up(struct tea5761_device *tea)
 {
-   int rc, i;
-   u16 *p = (u16 *) &tea->regs;
-   struct i2c_client *client = tea->i2c_dev;
+   struct dvb_frontend *fe = &tea->fe;
+   struct dvb_tuner_ops *fe_tuner_ops = &fe->ops.tuner_ops;
 
-   rc = i2c_master_recv(client, (void*) &tea->regs, sizeof(tea->regs));
-   for (i = 0; i < 8; i++) {
-   p[i] = __be16_to_cpu(p[i]);
-   }
+   if (fe_tuner_ops->init)
+   fe_tuner_ops->init(fe);
+   tea->power = 1;

Re: [PATCH 3/3] radio-tea5761: Update driver

2008-06-10 Thread Eduardo Valentin
Hi Balbi,

On Mon, Jun 9, 2008 at 10:07 PM, Felipe Balbi <[EMAIL PROTECTED]> wrote:
> On Mon, Jun 09, 2008 at 09:14:21PM -0400, Eduardo Valentin wrote:
>> If I understood correctly what you said, the same comment I said
>> before also applies here.
>> Eventhough it prints that the probe
>> failed, this way I sent it says: The probe failed and "The driver
>> registration failed". More easy
>> to debug the code when in a error situation.
>
> But if probe fails, driver registration failed. The same comment Jean
> Delvare gave me when I was sending some isp1301 patches upstream, so
> later on, when this driver goes to mailine, it'll probably, if Jean
> happens to see this one, get commented on this point as well.
>
> If you look at drivers/i2c/chips/*.c you'll see that only in two cases
> they are printing error if i2c_add_driver() fails and those are really
> necessary cases (check those drivers).
>
> But anyway, if you think it's really necessary.
>

Ok. I've just resent the whole series with this message removed. :)

> --
> Best Regards,
>
> Felipe Balbi
> [EMAIL PROTECTED]
> http://blog.felipebalbi.com
>



-- 
Eduardo Bezerra Valentin
--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH 3/3] radio-tea5761: Update driver

2008-06-09 Thread Felipe Balbi
On Mon, Jun 09, 2008 at 09:14:21PM -0400, Eduardo Valentin wrote:
> If I understood correctly what you said, the same comment I said
> before also applies here.
> Eventhough it prints that the probe
> failed, this way I sent it says: The probe failed and "The driver
> registration failed". More easy
> to debug the code when in a error situation.

But if probe fails, driver registration failed. The same comment Jean
Delvare gave me when I was sending some isp1301 patches upstream, so
later on, when this driver goes to mailine, it'll probably, if Jean
happens to see this one, get commented on this point as well.

If you look at drivers/i2c/chips/*.c you'll see that only in two cases
they are printing error if i2c_add_driver() fails and those are really
necessary cases (check those drivers).

But anyway, if you think it's really necessary.

-- 
Best Regards,

Felipe Balbi
[EMAIL PROTECTED]
http://blog.felipebalbi.com
--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH 3/3] radio-tea5761: Update driver

2008-06-09 Thread Eduardo Valentin
Hi Balbi,

On Mon, Jun 9, 2008 at 7:40 PM, Felipe Balbi <[EMAIL PROTECTED]> wrote:
> On Mon, Jun 09, 2008 at 04:05:43PM -0400, Eduardo Valentin wrote:
>> +static void tea5761_set_audout_mode(struct tea5761_device *tea, int audmode)
>>  {
>> - struct tea5761_regs *r = &tea->regs;
>> -
>> - if (!(r->tnctrl & TEA5761_TNCTRL_PUPD0)) {
>> - r->tnctrl &= ~(TEA5761_TNCTRL_AFM | TEA5761_TNCTRL_MU |
>> -TEA5761_TNCTRL_HLSI);
>> - r->testreg |= TEA5761_TESTREG_TRIGFR;
>> - r->tnctrl |= TEA5761_TNCTRL_PUPD0;
>> - return tea5761_write_regs(tea);
>> + struct dvb_frontend *fe = &tea->fe;
>> + struct dvb_tuner_ops *fe_tuner_ops = &fe->ops.tuner_ops;
>> + struct analog_parameters params = {
>> + .mode   = V4L2_TUNER_RADIO,
>> + .frequency  = tea->freq,
>> + .audmode= audmode,
>> + };
>> +
>> + if (NULL == fe_tuner_ops->set_analog_params) {
>> + dev_warn(tea->dev,
>> + "Tuner frontend module has no way to set frequency\n");
>> + return;
>>   }
>> + if (!fe_tuner_ops->set_analog_params(fe, ¶ms))
>> + tea->audmode = audmode;
>
> instead of both ifs, how about:
>
>if (fe_tuner_ops->set_analog_params) {
>tea->audmode =
>fe_tuner_ops->set_analog_params(fe, ¶ms) ?
>audmode : 0;
>}
>>  }

I don't know. I personally do not like "silent fail" style. The way you
proposed it will say nothing if set_anolog_params is not set. And that
is a very important part of this code.
>
>> +static void tea5761_mute(struct tea5761_device *tea, int on)
>> +{
>> + struct dvb_frontend *fe = &tea->fe;
>> + struct dvb_tuner_ops *fe_tuner_ops = &fe->ops.tuner_ops;
>> + struct analog_parameters params = {
>> + .mode   = on ? T_STANDBY : V4L2_TUNER_RADIO,
>> + .frequency  = tea->freq,
>> + .audmode= tea->audmode,
>> + };
>> +
>> + if (NULL == fe_tuner_ops->set_analog_params) {
>> + dev_warn(tea->dev,
>> + "Tuner frontend module has no way to set frequency\n");
>> + return;
>>   }
>> + if (!fe_tuner_ops->set_analog_params(fe, ¶ms))
>> + tea->mute = on;
>
> samething here.
same here.
>
>>  }
>
>>  static int tea5761_i2c_driver_probe(struct i2c_client *client,
>> @@ -422,12 +407,24 @@ static int tea5761_i2c_driver_probe(struct i2c_client 
>> *client,
>>
>>   mutex_init(&tea->mutex);
>>
>> - tea->i2c_dev = client;
>> + /* Tuner attach */
>> + if (!dvb_attach(tea5761_attach, &tea->fe, client->adapter,
>> + client->addr)) {
>> + dev_err(&client->dev, "Could not attach tuner\n");
>> + err = -ENODEV;
>> + goto exit;
>> + }
>> +
>> + /* initialize and power off the chip */
>> + tea5761_power_up(tea);
>> + tea5761_set_audout_mode(tea, V4L2_TUNER_MODE_STEREO);
>> + tea5761_mute(tea, 0);
>> + tea5761_power_down(tea);
>>
>>   /* V4L initialization */
>>   video_dev = video_device_alloc();
>>   if (video_dev == NULL) {
>
>if (!video_dev)
>
>> - dev_err(&client->dev, "couldn't allocate memory\n");
>> + dev_err(&client->dev, "Could not allocate memory\n");
>>   err = -ENOMEM;
>>   goto exit;
>>   }
>> @@ -436,25 +433,15 @@ static int tea5761_i2c_driver_probe(struct i2c_client 
>> *client,
>>   *video_dev = tea5761_video_device;
>>   video_dev->dev = &client->dev;
>>   i2c_set_clientdata(client, video_dev);
>> -
>> - /* initialize and power off the chip */
>> - tea5761_read_regs(tea);
>> - tea5761_set_audout_mode(tea, V4L2_TUNER_MODE_STEREO);
>> - tea5761_mute(tea, 0);
>> - tea5761_power_down(tea);
>> -
>> - tea5761.video_dev = video_dev;
>> - tea5761.i2c_dev = client;
>> + tea->video_dev = video_dev;
>> + tea->dev = &client->dev;
>>
>>   err = video_register_device(video_dev, VFL_TYPE_RADIO, radio_nr);
>>   if (err) {
>> - dev_err(&client->dev, "couldn't register video device\n");
>> + dev_err(&client->dev, "Could not register video device\n");
>>   goto err_video_alloc;
>>   }
>>
>> - dev_info(&client->dev, "tea5761 (version %d) detected\n",
>> - (tea->regs.manid >> 12) & 0xf);
>> -
>>   return 0;
>>
>>  err_video_alloc:
>> @@ -492,7 +479,8 @@ static int __init tea5761_init(void)
>>  {
>>   int res;
>>
>> - if ((res = i2c_add_driver(&tea5761_driver))) {
>> + res = i2c_add_driver(&tea5761_driver);
>> + if (res) {
>>   printk(KERN_ERR DRIVER_NAME ": driver registration failed\n");
>>   return res;
>
> not needed, return i2c_add_driver(&tea5761_driver); is enough as i2c
> subsystem already prints out error messages in case of fa

Re: [PATCH 3/3] radio-tea5761: Update driver

2008-06-09 Thread Felipe Balbi
On Mon, Jun 09, 2008 at 04:05:43PM -0400, Eduardo Valentin wrote:
> +static void tea5761_set_audout_mode(struct tea5761_device *tea, int audmode)
>  {
> - struct tea5761_regs *r = &tea->regs;
> -
> - if (!(r->tnctrl & TEA5761_TNCTRL_PUPD0)) {
> - r->tnctrl &= ~(TEA5761_TNCTRL_AFM | TEA5761_TNCTRL_MU |
> -TEA5761_TNCTRL_HLSI);
> - r->testreg |= TEA5761_TESTREG_TRIGFR;
> - r->tnctrl |= TEA5761_TNCTRL_PUPD0;
> - return tea5761_write_regs(tea);
> + struct dvb_frontend *fe = &tea->fe;
> + struct dvb_tuner_ops *fe_tuner_ops = &fe->ops.tuner_ops;
> + struct analog_parameters params = {
> + .mode   = V4L2_TUNER_RADIO,
> + .frequency  = tea->freq,
> + .audmode= audmode,
> + };
> +
> + if (NULL == fe_tuner_ops->set_analog_params) {
> + dev_warn(tea->dev,
> + "Tuner frontend module has no way to set frequency\n");
> + return;
>   }
> + if (!fe_tuner_ops->set_analog_params(fe, ¶ms))
> + tea->audmode = audmode;

instead of both ifs, how about:

if (fe_tuner_ops->set_analog_params) {
tea->audmode =
fe_tuner_ops->set_analog_params(fe, ¶ms) ?
audmode : 0;
}
>  }

> +static void tea5761_mute(struct tea5761_device *tea, int on)
> +{
> + struct dvb_frontend *fe = &tea->fe;
> + struct dvb_tuner_ops *fe_tuner_ops = &fe->ops.tuner_ops;
> + struct analog_parameters params = {
> + .mode   = on ? T_STANDBY : V4L2_TUNER_RADIO,
> + .frequency  = tea->freq,
> + .audmode= tea->audmode,
> + };
> +
> + if (NULL == fe_tuner_ops->set_analog_params) {
> + dev_warn(tea->dev,
> + "Tuner frontend module has no way to set frequency\n");
> + return;
>   }
> + if (!fe_tuner_ops->set_analog_params(fe, ¶ms))
> + tea->mute = on;

samething here.

>  }

>  static int tea5761_i2c_driver_probe(struct i2c_client *client,
> @@ -422,12 +407,24 @@ static int tea5761_i2c_driver_probe(struct i2c_client 
> *client,
>  
>   mutex_init(&tea->mutex);
>  
> - tea->i2c_dev = client;
> + /* Tuner attach */
> + if (!dvb_attach(tea5761_attach, &tea->fe, client->adapter,
> + client->addr)) {
> + dev_err(&client->dev, "Could not attach tuner\n");
> + err = -ENODEV;
> + goto exit;
> + }
> +
> + /* initialize and power off the chip */
> + tea5761_power_up(tea);
> + tea5761_set_audout_mode(tea, V4L2_TUNER_MODE_STEREO);
> + tea5761_mute(tea, 0);
> + tea5761_power_down(tea);
>  
>   /* V4L initialization */
>   video_dev = video_device_alloc();
>   if (video_dev == NULL) {

if (!video_dev)

> - dev_err(&client->dev, "couldn't allocate memory\n");
> + dev_err(&client->dev, "Could not allocate memory\n");
>   err = -ENOMEM;
>   goto exit;
>   }
> @@ -436,25 +433,15 @@ static int tea5761_i2c_driver_probe(struct i2c_client 
> *client,
>   *video_dev = tea5761_video_device;
>   video_dev->dev = &client->dev;
>   i2c_set_clientdata(client, video_dev);
> -
> - /* initialize and power off the chip */
> - tea5761_read_regs(tea);
> - tea5761_set_audout_mode(tea, V4L2_TUNER_MODE_STEREO);
> - tea5761_mute(tea, 0);
> - tea5761_power_down(tea);
> -
> - tea5761.video_dev = video_dev;
> - tea5761.i2c_dev = client;
> + tea->video_dev = video_dev;
> + tea->dev = &client->dev;
>  
>   err = video_register_device(video_dev, VFL_TYPE_RADIO, radio_nr);
>   if (err) {
> - dev_err(&client->dev, "couldn't register video device\n");
> + dev_err(&client->dev, "Could not register video device\n");
>   goto err_video_alloc;
>   }
>  
> - dev_info(&client->dev, "tea5761 (version %d) detected\n",
> - (tea->regs.manid >> 12) & 0xf);
> -
>   return 0;
>  
>  err_video_alloc:
> @@ -492,7 +479,8 @@ static int __init tea5761_init(void)
>  {
>   int res;
>  
> - if ((res = i2c_add_driver(&tea5761_driver))) {
> + res = i2c_add_driver(&tea5761_driver);
> + if (res) {
>   printk(KERN_ERR DRIVER_NAME ": driver registration failed\n");
>   return res;

not needed, return i2c_add_driver(&tea5761_driver); is enough as i2c
subsystem already prints out error messages in case of failed probe.

>   }

-- 
Best Regards,

Felipe Balbi
[EMAIL PROTECTED]
http://blog.felipebalbi.com
--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 3/3] radio-tea5761: Update driver

2008-06-09 Thread Eduardo Valentin
From: Eduardo Valentin <[EMAIL PROTECTED]>

This patch updates this driver by changing the way it accesses
the device. There is the tuner API which already has an implementation
for tea5761.

This patch changes the driver to use tuner API.

It also changes the way ioctls are handled. This way
it is more easy to deal with v4l2 and v4l calls.

Some cleans are also done.

Signed-off-by: Eduardo Valentin <[EMAIL PROTECTED]>
---
 drivers/media/radio/Kconfig |1 +
 drivers/media/radio/Makefile|2 +
 drivers/media/radio/radio-tea5761.c |  564 +--
 3 files changed, 279 insertions(+), 288 deletions(-)

diff --git a/drivers/media/radio/Kconfig b/drivers/media/radio/Kconfig
index de6ca27..b45f834 100644
--- a/drivers/media/radio/Kconfig
+++ b/drivers/media/radio/Kconfig
@@ -341,6 +341,7 @@ config RADIO_ZOLTRIX_PORT
 
 config RADIO_TEA5761
tristate "Philips Semiconductors TEA5761 I2C FM Radio"
+   depends on MEDIA_TUNER_TEA5761
help
  Choose Y here if you have one of these AM/FM radio cards.
 
diff --git a/drivers/media/radio/Makefile b/drivers/media/radio/Makefile
index f5bffcc..a843007 100644
--- a/drivers/media/radio/Makefile
+++ b/drivers/media/radio/Makefile
@@ -25,3 +25,5 @@ obj-$(CONFIG_USB_DSBR) += dsbr100.o
 obj-$(CONFIG_USB_SI470X) += radio-si470x.o
 
 EXTRA_CFLAGS += -Isound
+EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core/
+EXTRA_CFLAGS += -Idrivers/media/common/tuners/
diff --git a/drivers/media/radio/radio-tea5761.c 
b/drivers/media/radio/radio-tea5761.c
index e8ccf29..a6ea185 100644
--- a/drivers/media/radio/radio-tea5761.c
+++ b/drivers/media/radio/radio-tea5761.c
@@ -23,79 +23,29 @@
 #include 
 #include 
 #include 
+#include 
+
+#include "dvb_frontend.h"
+#include "tea5761.h"
 
 #define DRIVER_NAME "tea5761"
 
 #define TEA5761_VERSIONKERNEL_VERSION(0, 0, 1)
 
-#define TEA5761_I2C_ADDR   0x10
-
-#define TEA5761_MANID  0x002b
-#define TEA5761_CHIPID 0x5761
-
-#define TEA5761_INTREG_BLMSK   0x0001
-#define TEA5761_INTREG_FRRMSK  0x0002
-#define TEA5761_INTREG_LEVMSK  0x0008
-#define TEA5761_INTREG_IFMSK   0x0010
-#define TEA5761_INTREG_BLMFLAG 0x0100
-#define TEA5761_INTREG_FRRFLAG 0x0200
-#define TEA5761_INTREG_LEVFLAG 0x0800
-#define TEA5761_INTREG_IFFLAG  0x1000
-
-#define TEA5761_FRQSET_SUD 0x8000
-#define TEA5761_FRQSET_SM  0x4000
-
-#define TEA5761_TNCTRL_PUPD0   0x4000
-#define TEA5761_TNCTRL_BLIM0x2000
-#define TEA5761_TNCTRL_SWPM0x1000
-#define TEA5761_TNCTRL_IFCTC   0x0800
-#define TEA5761_TNCTRL_AFM 0x0400
-#define TEA5761_TNCTRL_SMUTE   0x0200
-#define TEA5761_TNCTRL_SNC 0x0100
-#define TEA5761_TNCTRL_MU  0x0080
-#define TEA5761_TNCTRL_SSL10x0040
-#define TEA5761_TNCTRL_SSL00x0020
-#define TEA5761_TNCTRL_HLSI0x0010
-#define TEA5761_TNCTRL_MST 0x0008
-#define TEA5761_TNCTRL_SWP 0x0004
-#define TEA5761_TNCTRL_DTC 0x0002
-#define TEA5761_TNCTRL_AHLSI   0x0001
-
-#define TEA5761_TUNCHK_LEVEL(x)(((x) & 0x00F0) >> 4)
-#define TEA5761_TUNCHK_IFCNT(x) (((x) & 0xFE00) >> 9)
-#define TEA5761_TUNCHK_TUNTO   0x0100
-#define TEA5761_TUNCHK_LD  0x0008
-#define TEA5761_TUNCHK_STEREO  0x0004
-
-#define TEA5761_TESTREG_TRIGFR 0x0800
-
 #define TEA5761_FREQ_LOW   87500
 #define TEA5761_FREQ_HIGH  108000
 
-struct tea5761_regs {
-   u16 intreg;
-   u16 frqset;
-   u16 tnctrl;
-   u16 frqchk;
-   u16 tunchk;
-   u16 testreg;
-   u16 manid;
-   u16 chipid;
-} __attribute__ ((packed));
-
-struct tea5761_write_regs {
-   u8 intreg;
-   u16 frqset;
-   u16 tnctrl;
-   u16 testreg;
-} __attribute__ ((packed));
-
 struct tea5761_device {
struct video_device *video_dev;
-   struct i2c_client   *i2c_dev;
-   struct tea5761_regs regs;
+   struct device   *dev;
+   struct dvb_frontend fe;
+   /* To control number of users access (.users field) */
struct mutexmutex;
int users;
+   unsigned intfreq;
+   u16 audmode;
+   u8  mute;
+   u8  power;
 };
 
 static struct tea5761_device tea5761;
@@ -103,267 +53,286 @@ static struct tea5761_device tea5761;
 static struct i2c_driver   tea5761_driver;
 static int radio_nr = -1;
 
-static int tea5761_read_regs(struct tea5761_device *tea)
+static void tea5761_power_up(struct tea5761_device *tea)
 {
-   int rc, i;
-   u16 *p = (u16 *) &tea->regs;
-   struct i2c_client *client = tea->i2c_dev;
+   struct dvb_frontend *fe = &tea->fe;
+   struct dvb_tuner_ops *fe_tuner_ops = &fe->ops.tuner_ops;
 
-   rc = i2c_master_recv(client, (void*) &tea->regs, sizeof(tea->regs));
-   for (i = 0; i < 8; i++) {
-   p[i] = __be16_to_cpu(p[i]);
-   }
+   if (fe_tuner_ops->init)
+   fe_tuner_ops->init(fe);
+   tea->power = 1;