]> pilppa.com Git - linux-2.6-omap-h63xx.git/commitdiff
Revert "radio-tea5761: Update driver"
authorTony Lindgren <tony@atomide.com>
Wed, 25 Jun 2008 10:59:33 +0000 (13:59 +0300)
committerTony Lindgren <tony@atomide.com>
Wed, 25 Jun 2008 10:59:33 +0000 (13:59 +0300)
This reverts commit 5728b4a3ba5ace557263e5ccb0bc7829e543acf5.

This patch causes oops on n810 which does not have this chip.

Signed-off-by: Tony Lindgren <tony@atomide.com>
drivers/media/radio/Kconfig
drivers/media/radio/Makefile
drivers/media/radio/radio-tea5761.c

index b45f8345fee8bb35d0514f2269a3b913319de4b2..de6ca277dabf143a0f790799813ff1a56d5e6c3a 100644 (file)
@@ -341,7 +341,6 @@ 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.
 
index a8430070a0b83e1d27ad4f33b7ef4c009095e2ea..f5bffcce0b59770190bb57d74d8050448e01ec43 100644 (file)
@@ -25,5 +25,3 @@ 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/
index cc39a449cafb58edf3a9237cc17a853dfcdd8e02..e8ccf29273f69c0d36257390eb8e3d704e23c029 100644 (file)
 #include <linux/i2c.h>
 #include <linux/delay.h>
 #include <media/v4l2-common.h>
-#include <media/tuner.h>
-
-#include "dvb_frontend.h"
-#include "tea5761.h"
 
 #define DRIVER_NAME "tea5761"
 
 #define TEA5761_VERSION                KERNEL_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_BLIM    0x2000
+#define TEA5761_TNCTRL_SWPM    0x1000
+#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_SSL1    0x0040
+#define TEA5761_TNCTRL_SSL0    0x0020
+#define TEA5761_TNCTRL_HLSI    0x0010
+#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 device           *dev;
-       struct dvb_frontend     fe;
-       /* To control number of users access (.users field) */
+       struct i2c_client       *i2c_dev;
+       struct tea5761_regs     regs;
        struct mutex            mutex;
        int                     users;
-       unsigned int            freq;
-       u16                     audmode;
-       u8                      mute;
-       u8                      power;
 };
 
 static struct tea5761_device tea5761;
@@ -53,286 +103,267 @@ static struct tea5761_device tea5761;
 static struct i2c_driver       tea5761_driver;
 static int radio_nr = -1;
 
-static void tea5761_power_up(struct tea5761_device *tea)
-{
-       struct dvb_frontend *fe = &tea->fe;
-       struct dvb_tuner_ops *fe_tuner_ops = &fe->ops.tuner_ops;
-
-       if (fe_tuner_ops->init)
-               fe_tuner_ops->init(fe);
-       tea->power = 1;
-}
-
-static void tea5761_power_down(struct tea5761_device *tea)
+static int tea5761_read_regs(struct tea5761_device *tea)
 {
-       struct dvb_frontend *fe = &tea->fe;
-       struct dvb_tuner_ops *fe_tuner_ops = &fe->ops.tuner_ops;
-
-       if (fe_tuner_ops->sleep)
-               fe_tuner_ops->sleep(fe);
-       tea->power = 0;
-}
+       int rc, i;
+       u16 *p = (u16 *) &tea->regs;
+       struct i2c_client *client = tea->i2c_dev;
 
-static void tea5761_set_freq(struct tea5761_device *tea, unsigned int freq)
-{
-       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,
-               .audmode        = tea->audmode,
-               .frequency      = freq,
-       };
-
-       if (NULL == fe_tuner_ops->set_analog_params) {
-               dev_warn(tea->dev,
-                       "Tuner frontend module has no way to set frequency\n");
-               return;
+       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->set_analog_params(fe, &params))
-               tea->freq = freq;
-}
 
-static int tea5761_get_freq(struct tea5761_device *tea)
-{
-       struct dvb_frontend *fe = &tea->fe;
-       struct dvb_tuner_ops *fe_tuner_ops = &fe->ops.tuner_ops;
-       u32 freq;
+       dev_dbg(&client->dev,
+               "chip state: %04x %04x %04x %04x %04x %04x %04x %04x\n",
+               p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7]);
 
-       if (fe_tuner_ops->get_frequency) {
-               fe_tuner_ops->get_frequency(fe, &freq);
-               return freq * 2 / 125;
-       }
+       if (rc < 0)
+               dev_err(&client->dev, "read\n");
 
-       return -ENODEV;
+       return rc;
 }
 
-static void tea5761_set_audout_mode(struct tea5761_device *tea, int audmode)
+static void tea5761_write_regs(struct tea5761_device *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, &params))
-               tea->audmode = audmode;
+       struct tea5761_write_regs wr;
+       struct tea5761_regs *r = &tea->regs;
+       struct i2c_client *client = tea->i2c_dev;
+       u8 *p = (u8 *) r;
+
+       wr.intreg = r->intreg & 0xff;
+       wr.frqset = __cpu_to_be16(r->frqset);
+       wr.tnctrl = __cpu_to_be16(r->tnctrl);
+       wr.testreg = __cpu_to_be16(r->testreg);
+
+       dev_dbg(&client->dev,
+               "writing state: %02x %02x %02x %02x %02x %02x %02x\n",
+               p[0], p[1], p[2], p[3], p[4], p[5], p[6]);
+       if (i2c_master_send(client, (void *) &wr, sizeof(wr)) < 0)
+               dev_err(&client->dev, "write\n");
 }
 
-static int tea5761_get_audout_mode(struct tea5761_device *tea)
-{
-       return tea->audmode;
-}
-
-static void tea5761_mute(struct tea5761_device *tea, int on)
+static void tea5761_power_up(struct tea5761_device *tea)
 {
-       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;
+       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);
        }
-       if (!fe_tuner_ops->set_analog_params(fe, &params))
-               tea->mute = on;
-}
-
-static int tea5761_is_muted(struct tea5761_device *tea)
-{
-       return tea->mute;
-}
-
-static int tea5761_vidioc_querycap(struct file *file, void *priv,
-                                       struct v4l2_capability *c)
-{
-       struct tea5761_device *tea = file->private_data;
-       struct video_device *dev = tea->video_dev;
-
-       memset(c, 0, sizeof(*c));
-       strlcpy(c->driver, dev->dev->driver->name, sizeof(*c->driver));
-       strlcpy(c->card, dev->name, sizeof(c->card));
-       snprintf(c->bus_info, sizeof(c->bus_info), "I2C:%s",
-               dev->dev->bus_id);
-       c->version = TEA5761_VERSION;
-       c->capabilities = V4L2_CAP_TUNER | V4L2_CAP_RADIO;
-
-       return 0;
 }
 
-static int tea5761_vidioc_g_tuner(struct file *file, void *priv,
-                                       struct v4l2_tuner *t)
+static void tea5761_power_down(struct tea5761_device *tea)
 {
-       struct tea5761_device *tea = file->private_data;
-       struct dvb_frontend *fe = &tea->fe;
-       u16 strength = 0;
-
-       /* Only one tuner chip */
-       if (t->index != 0)
-               return -EINVAL;
-
-       memset(t, 0, sizeof(*t));
-       t->type = V4L2_TUNER_RADIO;
-       strlcpy(t->name, "FM", sizeof(t->name));
-       /* Frequency in 62.5Hz units */
-       t->rangelow = TEA5761_FREQ_LOW * 16;
-       t->rangehigh = TEA5761_FREQ_HIGH * 16;
-       t->capability = V4L2_TUNER_CAP_LOW | V4L2_TUNER_CAP_STEREO;
-
-       t->audmode = tea5761_get_audout_mode(tea);
-       if (t->audmode == V4L2_TUNER_MODE_STEREO)
-               t->rxsubchans = V4L2_TUNER_SUB_STEREO;
+       struct tea5761_regs *r = &tea->regs;
 
-       if (fe->ops.tuner_ops.get_rf_strength)
-               fe->ops.tuner_ops.get_rf_strength(fe, &strength);
-       t->signal = strength;
-
-       return 0;
+       if (r->tnctrl & TEA5761_TNCTRL_PUPD0) {
+               r->tnctrl &= ~TEA5761_TNCTRL_PUPD0;
+               return tea5761_write_regs(tea);
+       }
 }
 
-static int tea5761_vidioc_s_tuner(struct file *file, void *priv,
-                                       struct v4l2_tuner *t)
+static void tea5761_set_freq(struct tea5761_device *tea, int freq)
 {
-       struct tea5761_device *tea = file->private_data;
+       struct tea5761_regs *r = &tea->regs;
 
-       /* Only tuner number 0 can be selected. */
-       if (t->index != 0)
-               return -EINVAL;
-       tea5761_set_audout_mode(tea, t->audmode);
-
-       return 0;
+       if (r->tnctrl & TEA5761_TNCTRL_HLSI)
+               r->frqset = (freq + 225000) / 8192;
+       else
+               r->frqset = (freq - 225000) / 8192;
 }
 
-static int tea5761_vidioc_g_frequency(struct file *file, void *priv,
-                                       struct v4l2_frequency *f)
+static int tea5761_get_freq(struct tea5761_device *tea)
 {
-       struct tea5761_device *tea = file->private_data;
+       struct tea5761_regs *r = &tea->regs;
 
-       memset(f, 0, sizeof(*f));
-       f->type = V4L2_TUNER_RADIO;
-       if (tea->power)
-               f->frequency = (tea5761_get_freq(tea) * 2) / 125;
+       if (r->tnctrl & TEA5761_TNCTRL_HLSI)
+               return (r->frqchk * 8192) - 225000;
        else
-               f->frequency = 0;
-
-       return 0;
+               return (r->frqchk * 8192) + 225000;
 }
 
-static int tea5761_vidioc_s_frequency(struct file *file, void *priv,
-                                       struct v4l2_frequency *f)
+static void tea5761_tune(struct tea5761_device *tea, int freq)
 {
-       struct tea5761_device *tea = file->private_data;
-
-       if (f->tuner != 0)
-               return -EINVAL;
-       if (f->frequency == 0) {
-               /* We special case this as a power down
-                * control. */
-               tea5761_power_down(tea);
-               return 0;
-       }
-       if (f->frequency < 16 * TEA5761_FREQ_LOW)
-               return -EINVAL;
-       if (f->frequency > 16 * TEA5761_FREQ_HIGH)
-               return -EINVAL;
-
-       tea5761_power_up(tea);
-       tea5761_set_freq(tea, f->frequency);
-
-       return 0;
+       tea5761_set_freq(tea, freq);
+       tea5761_write_regs(tea);
 }
 
-static int tea5761_vidioc_queryctrl(struct file *file, void *priv,
-                                       struct v4l2_queryctrl *qc)
+static void tea5761_set_audout_mode(struct tea5761_device *tea, int audmode)
 {
-       if (qc->id != V4L2_CID_AUDIO_MUTE)
-               return -EINVAL;
-       strlcpy(qc->name, "Mute", sizeof(qc->name));
-       qc->minimum = 0;
-       qc->maximum = 1;
-       qc->step = 1;
-       qc->default_value = 0;
-       qc->type = V4L2_CTRL_TYPE_BOOLEAN;
+       struct tea5761_regs *r = &tea->regs;
+       int tnctrl = r->tnctrl;
 
-       return 0;
+       if (audmode == V4L2_TUNER_MODE_MONO)
+               r->tnctrl |= TEA5761_TNCTRL_MST;
+       else
+               r->tnctrl &= ~TEA5761_TNCTRL_MST;
+       if (tnctrl != r->tnctrl)
+               tea5761_write_regs(tea);
 }
 
-static int tea5761_vidioc_g_ctrl(struct file *file, void *priv,
-                                       struct v4l2_control *ct)
+static int tea5761_get_audout_mode(struct tea5761_device *tea)
 {
-       struct tea5761_device *tea = file->private_data;
+       struct tea5761_regs *r = &tea->regs;
 
-       if (ct->id != V4L2_CID_AUDIO_MUTE)
-               return -EINVAL;
-       if (tea->power)
-               ct->value = tea5761_is_muted(tea) ? 1 : 0;
+       if (r->tnctrl & TEA5761_TNCTRL_MST)
+               return V4L2_TUNER_MODE_MONO;
        else
-               ct->value = 0;
-
-       return 0;
+               return V4L2_TUNER_MODE_STEREO;
 }
 
-static int tea5761_vidioc_s_ctrl(struct file *file, void *priv,
-                               struct v4l2_control *ct)
+static void tea5761_mute(struct tea5761_device *tea, int on)
 {
-       struct tea5761_device *tea = file->private_data;
-
-       if (ct->id != V4L2_CID_AUDIO_MUTE)
-               return -EINVAL;
-       tea5761_mute(tea, ct->value);
+       struct tea5761_regs *r = &tea->regs;
+       int tnctrl = r->tnctrl;
 
-       return 0;
+       if (on)
+               r->tnctrl |= TEA5761_TNCTRL_MU;
+       else
+               r->tnctrl &= ~TEA5761_TNCTRL_MU;
+       if (tnctrl != r->tnctrl)
+               tea5761_write_regs(tea);
 }
 
-static int tea5761_vidioc_g_audio(struct file *file, void *priv,
-                                       struct v4l2_audio *audio)
+static int tea5761_is_muted(struct tea5761_device *tea)
 {
-       struct tea5761_device *tea = file->private_data;
-
-       strlcpy(audio->name, "FM Radio", ARRAY_SIZE(audio->name));
-       audio->mode = tea->audmode;
-
-       return 0;
+       return tea->regs.tnctrl & TEA5761_TNCTRL_MU;
 }
 
-static int tea5761_vidioc_s_audio(struct file *file, void *priv,
-                                       struct v4l2_audio *audio)
+static int tea5761_do_ioctl(struct inode *inode, struct file *file,
+                           unsigned int cmd, void *arg)
 {
        struct tea5761_device *tea = file->private_data;
-
-       tea5761_set_audout_mode(tea,  audio->mode);
-
-       return 0;
-}
-
-static int tea5761_vidioc_g_input(struct file *filp, void *priv,
-               unsigned int *i)
-{
-       *i = 0;
+       struct video_device *dev = tea->video_dev;
+       struct i2c_client *client = tea->i2c_dev;
+       struct tea5761_regs *r = &tea->regs;
+
+       union {
+               struct v4l2_capability c;
+               struct v4l2_tuner t;
+               struct v4l2_frequency f;
+               struct v4l2_queryctrl qc;
+               struct v4l2_control ct;
+       } *u = arg;
+
+       tea5761_read_regs(tea);
+
+       switch (cmd) {
+       case VIDIOC_QUERYCAP:
+               dev_dbg(&client->dev, "VIDIOC_QUERYCAP\n");
+               memset(&u->c, 0, sizeof(u->c));
+               strlcpy(u->c.driver, dev->dev->driver->name,
+                       sizeof(u->c.driver));
+               strlcpy(u->c.card, dev->name, sizeof(u->c.card));
+               snprintf(u->c.bus_info, sizeof(u->c.bus_info), "I2C:%s",
+                        dev->dev->bus_id);
+               u->c.version = TEA5761_VERSION;
+               u->c.capabilities = V4L2_CAP_TUNER | V4L2_CAP_RADIO;
+               break;
+
+       case VIDIOC_G_TUNER:
+               /* Only one tuner chip */
+               dev_dbg(&client->dev, "VIDIOC_G_TUNER\n");
+               if (u->t.index != 0)
+                       return -EINVAL;
+
+               memset(&u->t, 0, sizeof(u->t));
+               u->t.type = V4L2_TUNER_RADIO;
+               strlcpy(u->t.name, "FM", sizeof(u->t.name));
+               /* Freq in 62.5Hz units */
+               u->t.rangelow = TEA5761_FREQ_LOW * 16;
+               u->t.rangehigh = TEA5761_FREQ_HIGH * 16;
+               u->t.capability = V4L2_TUNER_CAP_LOW | V4L2_TUNER_CAP_STEREO;
+               if (r->tunchk & TEA5761_TUNCHK_STEREO)
+                       u->t.rxsubchans = V4L2_TUNER_SUB_STEREO;
+               u->t.audmode = tea5761_get_audout_mode(tea);
+               u->t.signal = TEA5761_TUNCHK_LEVEL(r->tunchk) * 0xffff / 0xf;
+               u->t.afc = TEA5761_TUNCHK_IFCNT(r->tunchk);
+               break;
+
+       case VIDIOC_S_TUNER:
+               /* Only tuner nro 0 can be selected. */
+               dev_dbg(&client->dev, "VIDIOC_S_TUNER\n");
+               if (u->t.index != 0)
+                       return -EINVAL;
+               tea5761_set_audout_mode(tea, u->t.audmode);
+               break;
+
+       case VIDIOC_G_FREQUENCY:
+               dev_dbg(&client->dev, "VIDIOC_G_FREQUENCY\n");
+               memset(&u->f, 0, sizeof(u->f));
+               u->f.type = V4L2_TUNER_RADIO;
+               if (r->tnctrl & TEA5761_TNCTRL_PUPD0)
+                       u->f.frequency = (tea5761_get_freq(tea) * 2) / 125;
+               else
+                       u->f.frequency = 0;
+               break;
+
+       case VIDIOC_S_FREQUENCY:
+               dev_dbg(&client->dev, "VIDIOC_S_FREQUENCY %u\n",
+                       u->f.frequency);
+               if (u->f.tuner != 0)
+                       return -EINVAL;
+               if (u->f.frequency == 0) {
+                       /* We special case this as a power down
+                        * control. */
+                       tea5761_power_down(tea);
+                       break;
+               }
+               if (u->f.frequency < 16 * TEA5761_FREQ_LOW)
+                       return -EINVAL;
+               if (u->f.frequency > 16 * TEA5761_FREQ_HIGH)
+                       return -EINVAL;
+
+               tea5761_power_up(tea);
+               tea5761_tune(tea, (u->f.frequency * 125) / 2);
+               break;
+
+       case VIDIOC_QUERYCTRL:
+               dev_dbg(&client->dev, "VIDIOC_QUERYCTRL %d\n", u->qc.id);
+               if (u->qc.id != V4L2_CID_AUDIO_MUTE)
+                       return -EINVAL;
+               strlcpy(u->qc.name, "Mute", sizeof(u->qc.name));
+               u->qc.minimum = 0;
+               u->qc.maximum = 1;
+               u->qc.step = 1;
+               u->qc.default_value = 0;
+               u->qc.type = V4L2_CTRL_TYPE_BOOLEAN;
+               break;
+
+       case VIDIOC_G_CTRL:
+               dev_dbg(&client->dev, "VIDIOC_G_CTRL %d\n", u->ct.id);
+               if (u->ct.id != V4L2_CID_AUDIO_MUTE)
+                       return -EINVAL;
+               if (r->tnctrl & TEA5761_TNCTRL_PUPD0)
+                       u->ct.value = tea5761_is_muted(tea) ? 1 : 0;
+               else
+                       u->ct.value = 0;
+               break;
+
+       case VIDIOC_S_CTRL:
+               dev_dbg(&client->dev, "VIDIOC_S_CTRL %d\n", u->ct.id);
+               if (u->ct.id != V4L2_CID_AUDIO_MUTE)
+                       return -EINVAL;
+               tea5761_mute(tea, u->ct.value);
+               break;
+
+       default:
+               return -ENOIOCTLCMD;
+       }
 
        return 0;
 }
 
-static int tea5761_vidioc_s_input(struct file *filp, void *priv, unsigned int i)
+static int tea5761_ioctl(struct inode *inode, struct file *file,
+                        unsigned int cmd, unsigned long arg)
 {
-       if (i)
-               return -EINVAL;
-
-       return 0;
+       return video_usercopy(inode, file, cmd, arg, tea5761_do_ioctl);
 }
 
-
 static int tea5761_open(struct inode *inode, struct file *file)
 {
        int minor = iminor(file->f_dentry->d_inode);
@@ -370,32 +401,16 @@ static struct file_operations tea5761_fops = {
        .owner          = THIS_MODULE,
        .open           = tea5761_open,
        .release        = tea5761_release,
+       .ioctl          = tea5761_ioctl,
        .llseek         = no_llseek,
-       .ioctl          = video_ioctl2,
-       .compat_ioctl   = v4l_compat_ioctl32,
 };
 
-/*
- * tea5761_viddev_tamples - video device interface
- */
 static struct video_device tea5761_video_device = {
-       .owner                  = THIS_MODULE,
-       .name                   = "TEA5761 FM-Radio",
-       .type                   = VID_TYPE_TUNER,
-       .release                = video_device_release,
-       .fops                   = &tea5761_fops,
-       .vidioc_querycap        = tea5761_vidioc_querycap,
-       .vidioc_g_tuner         = tea5761_vidioc_g_tuner,
-       .vidioc_s_tuner         = tea5761_vidioc_s_tuner,
-       .vidioc_g_frequency     = tea5761_vidioc_g_frequency,
-       .vidioc_s_frequency     = tea5761_vidioc_s_frequency,
-       .vidioc_queryctrl       = tea5761_vidioc_queryctrl,
-       .vidioc_g_ctrl          = tea5761_vidioc_g_ctrl,
-       .vidioc_s_ctrl          = tea5761_vidioc_s_ctrl,
-       .vidioc_g_audio         = tea5761_vidioc_g_audio,
-       .vidioc_s_audio         = tea5761_vidioc_s_audio,
-       .vidioc_g_input         = tea5761_vidioc_g_input,
-       .vidioc_s_input         = tea5761_vidioc_s_input,
+       .owner         = THIS_MODULE,
+       .name          = "TEA5761 FM-Radio",
+       .type          = VID_TYPE_TUNER,
+       .fops          = &tea5761_fops,
+       .release       = video_device_release
 };
 
 static int tea5761_i2c_driver_probe(struct i2c_client *client,
@@ -407,24 +422,12 @@ static int tea5761_i2c_driver_probe(struct i2c_client *client,
 
        mutex_init(&tea->mutex);
 
-       /* 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);
+       tea->i2c_dev = client;
 
        /* V4L initialization */
        video_dev = video_device_alloc();
        if (video_dev == NULL) {
-               dev_err(&client->dev, "Could not allocate memory\n");
+               dev_err(&client->dev, "couldn't allocate memory\n");
                err = -ENOMEM;
                goto exit;
        }
@@ -433,15 +436,25 @@ 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);
-       tea->video_dev = video_dev;
-       tea->dev = &client->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;
 
        err = video_register_device(video_dev, VFL_TYPE_RADIO, radio_nr);
        if (err) {
-               dev_err(&client->dev, "Could not register video device\n");
+               dev_err(&client->dev, "couldn't 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:
@@ -477,7 +490,14 @@ static struct i2c_driver tea5761_driver = {
 
 static int __init tea5761_init(void)
 {
-       return i2c_add_driver(&tea5761_driver);
+       int res;
+
+       if ((res = i2c_add_driver(&tea5761_driver))) {
+               printk(KERN_ERR DRIVER_NAME ": driver registration failed\n");
+               return res;
+       }
+
+       return 0;
 }
 
 static void __exit tea5761_exit(void)