V4L/DVB (13797): [Mantis/Hopper/TDA665x] Large overhaul,
authorManu Abraham <abraham.manu@gmail.com>
Fri, 4 Dec 2009 08:56:35 +0000 (05:56 -0300)
committerMauro Carvalho Chehab <mchehab@redhat.com>
Sun, 17 Jan 2010 13:55:43 +0000 (11:55 -0200)
* Initial go at VP-3028, VP-3030 devices.
* I2C communication improvements,
* Add TDA665x support

Signed-off-by: Manu Abraham <manu@linuxtv.org>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
12 files changed:
drivers/media/dvb/frontends/Kconfig
drivers/media/dvb/frontends/Makefile
drivers/media/dvb/frontends/tda665x.c [new file with mode: 0644]
drivers/media/dvb/frontends/tda665x.h [new file with mode: 0644]
drivers/media/dvb/mantis/hopper_cards.c
drivers/media/dvb/mantis/mantis_cards.c
drivers/media/dvb/mantis/mantis_dma.c
drivers/media/dvb/mantis/mantis_dvb.c
drivers/media/dvb/mantis/mantis_i2c.c
drivers/media/dvb/mantis/mantis_i2c.h
drivers/media/dvb/mantis/mantis_ioc.c
drivers/media/dvb/mantis/mantis_vp3030.c

index a3b8b697349b130f161daf1dc747d40c89ffcdb7..7820ca084b155e33545f7ea5dfb3114e6f9f5da0 100644 (file)
@@ -587,6 +587,17 @@ config DVB_ATBM8830
        help
          A DMB-TH tuner module. Say Y when you want to support this frontend.
 
+config DVB_TDA665x
+       tristate "TDA665x tuner"
+       depends on DVB_CORE && I2C
+       default m if DVB_FE_CUSTOMISE
+       help
+         Support for tuner modules based on Philips TDA6650/TDA6651 chips.
+         Say Y when you want to support this chip.
+
+         Currently supported tuners:
+         * Panasonic ENV57H12D5 (ET-50DT)
+
 comment "Tools to develop new frontends"
 
 config DVB_DUMMY_FE
index 47575cc7b699cea3a431b6d1c29093847402a5e8..59f7b88035543c51439dc43634549ba0caf6d2c9 100644 (file)
@@ -64,6 +64,7 @@ obj-$(CONFIG_DVB_TDA10048) += tda10048.o
 obj-$(CONFIG_DVB_TUNER_CX24113) += cx24113.o
 obj-$(CONFIG_DVB_S5H1411) += s5h1411.o
 obj-$(CONFIG_DVB_LGS8GL5) += lgs8gl5.o
+obj-$(CONFIG_DVB_TDA665x) += tda665x.o
 obj-$(CONFIG_DVB_LGS8GXX) += lgs8gxx.o
 obj-$(CONFIG_DVB_ATBM8830) += atbm8830.o
 obj-$(CONFIG_DVB_DUMMY_FE) += dvb_dummy_fe.o
diff --git a/drivers/media/dvb/frontends/tda665x.c b/drivers/media/dvb/frontends/tda665x.c
new file mode 100644 (file)
index 0000000..0732a2d
--- /dev/null
@@ -0,0 +1,257 @@
+/*
+       TDA665x tuner driver
+       Copyright (C) Manu Abraham (abraham.manu@gmail.com)
+
+       This program is free software; you can redistribute it and/or modify
+       it under the terms of the GNU General Public License as published by
+       the Free Software Foundation; either version 2 of the License, or
+       (at your option) any later version.
+
+       This program is distributed in the hope that it will be useful,
+       but WITHOUT ANY WARRANTY; without even the implied warranty of
+       MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+       GNU General Public License for more details.
+
+       You should have received a copy of the GNU General Public License
+       along with this program; if not, write to the Free Software
+       Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+
+#include "dvb_frontend.h"
+#include "tda665x.h"
+
+struct tda665x_state {
+       struct dvb_frontend             *fe;
+       struct i2c_adapter              *i2c;
+       const struct tda665x_config     *config;
+
+       u32 frequency;
+       u32 bandwidth;
+};
+
+static int tda665x_read(struct tda665x_state *state, u8 *buf)
+{
+       const struct tda665x_config *config = state->config;
+       int err = 0;
+       struct i2c_msg msg = { .addr = config->addr, .flags = I2C_M_RD, .buf = buf, .len = 2 };
+
+       err = i2c_transfer(state->i2c, &msg, 1);
+       if (err != 1)
+               goto exit;
+
+       return err;
+exit:
+       printk("%s: I/O Error err=<%d>\n", __func__, err);
+       return err;
+}
+
+static int tda665x_write(struct tda665x_state *state, u8 *buf, u8 length)
+{
+       const struct tda665x_config *config = state->config;
+       int err = 0;
+       struct i2c_msg msg = { .addr = config->addr, .flags = 0, .buf = buf, .len = length };
+
+       err = i2c_transfer(state->i2c, &msg, 1);
+       if (err != 1)
+               goto exit;
+
+       return err;
+exit:
+       printk("%s: I/O Error err=<%d>\n", __func__, err);
+       return err;
+}
+
+static int tda665x_get_state(struct dvb_frontend *fe,
+                            enum tuner_param param,
+                            struct tuner_state *tstate)
+{
+       struct tda665x_state *state = fe->tuner_priv;
+       int err = 0;
+
+       switch (param) {
+       case DVBFE_TUNER_FREQUENCY:
+               tstate->frequency = state->frequency;
+               break;
+       case DVBFE_TUNER_BANDWIDTH:
+               break;
+       default:
+               printk("%s: Unknown parameter (param=%d)\n", __func__, param);
+               err = -EINVAL;
+               break;
+       }
+
+       return err;
+}
+
+static int tda665x_get_status(struct dvb_frontend *fe, u32 *status)
+{
+       struct tda665x_state *state = fe->tuner_priv;
+       u8 result = 0;
+       int err = 0;
+
+       *status = 0;
+
+       err = tda665x_read(state, &result);
+       if (err < 0)
+               goto exit;
+
+       if ((result >> 6) & 0x01) {
+               printk("%s: Tuner Phase Locked\n", __func__);
+               *status = 1;
+       }
+
+       return err;
+exit:
+       printk("%s: I/O Error\n", __func__);
+       return err;
+}
+
+static int tda665x_set_state(struct dvb_frontend *fe,
+                            enum tuner_param param,
+                            struct tuner_state *tstate)
+{
+       struct tda665x_state *state = fe->tuner_priv;
+       const struct tda665x_config *config = state->config;
+       u32 frequency, status = 0;
+       u8 buf[4];
+       int err = 0;
+
+       if (param & DVBFE_TUNER_FREQUENCY) {
+
+               frequency = tstate->frequency;
+               if ((frequency < config->frequency_max) || (frequency > config->frequency_min)) {
+                       printk("%s: Frequency beyond limits, frequency=%d\n", __func__, frequency);
+                       return -EINVAL;
+               }
+
+               frequency += config->frequency_offst;
+               frequency *= config->ref_multiplier;
+               frequency += config->ref_divider >> 1;
+               frequency /= config->ref_divider;
+
+               buf[0] = (u8 ) (frequency & 0x7f00) >> 8;
+               buf[1] = (u8 ) (frequency & 0x00ff) >> 0;
+               buf[2] = 0x80 | 0x40 | 0x02;
+               buf[3] = 0x00;
+
+               /* restore frequency */
+               frequency = tstate->frequency;
+
+               if (frequency < 153000000) {
+                       /* VHF-L */
+                       buf[3] |= 0x01; /* fc, Low Band, 47 - 153 MHz */
+                       if (frequency < 68000000)
+                               buf[3] |= 0x40; /* 83uA */
+                       if (frequency < 1040000000)
+                               buf[3] |= 0x60; /* 122uA */
+                       if (frequency < 1250000000)
+                               buf[3] |= 0x80; /* 163uA */
+                       else
+                               buf[3] |= 0xa0; /* 254uA */
+               } else if (frequency < 438000000) {
+                       /* VHF-H */
+                       buf[3] |= 0x02; /* fc, Mid Band, 153 - 438 MHz */
+                       if (frequency < 230000000)
+                               buf[3] |= 0x40;
+                       if (frequency < 300000000)
+                               buf[3] |= 0x60;
+                       else
+                               buf[3] |= 0x80;
+               } else {
+                       /* UHF */
+                       buf[3] |= 0x04; /* fc, High Band, 438 - 862 MHz */
+                       if (frequency < 470000000)
+                               buf[3] |= 0x60;
+                       if (frequency < 526000000)
+                               buf[3] |= 0x80;
+                       else
+                               buf[3] |= 0xa0;
+               }
+
+               /* Set params */
+               err = tda665x_write(state, buf, 5);
+               if (err < 0)
+                       goto exit;
+
+               /* sleep for some time */
+               printk("%s: Waiting to Phase LOCK\n", __func__);
+               msleep(20);
+               /* check status */
+               err = tda665x_get_status(fe, &status);
+               if (err < 0)
+                       goto exit;
+
+               if (status == 1) {
+                       printk("%s: Tuner Phase locked: status=%d\n", __func__, status);
+                       state->frequency = frequency; /* cache successful state */
+               } else {
+                       printk("%s: No Phase lock: status=%d\n", __func__, status);
+               }
+       } else {
+               printk("%s: Unknown parameter (param=%d)\n", __func__, param);
+               return -EINVAL;
+       }
+
+       return 0;
+exit:
+       printk("%s: I/O Error\n", __func__);
+       return err;
+}
+
+static int tda665x_release(struct dvb_frontend *fe)
+{
+       struct tda665x_state *state = fe->tuner_priv;
+
+       fe->tuner_priv = NULL;
+       kfree(state);
+       return 0;
+}
+
+static struct dvb_tuner_ops tda665x_ops = {
+
+       .set_state      = tda665x_set_state,
+       .get_state      = tda665x_get_state,
+       .get_status     = tda665x_get_status,
+       .release        = tda665x_release
+};
+
+struct dvb_frontend *tda665x_attach(struct dvb_frontend *fe,
+                                   const struct tda665x_config *config,
+                                   struct i2c_adapter *i2c)
+{
+       struct tda665x_state *state = NULL;
+       struct dvb_tuner_info *info;
+
+       state = kzalloc(sizeof (struct tda665x_state), GFP_KERNEL);
+       if (state == NULL)
+               goto exit;
+
+       state->config           = config;
+       state->i2c              = i2c;
+       state->fe               = fe;
+       fe->tuner_priv          = state;
+       fe->ops.tuner_ops       = tda665x_ops;
+       info                     = &fe->ops.tuner_ops.info;
+
+       memcpy(info->name, config->name, sizeof (config->name));
+       info->frequency_min     = config->frequency_min;
+       info->frequency_max     = config->frequency_max;
+       info->frequency_step    = config->frequency_offst;
+
+       printk("%s: Attaching TDA665x (%s) tuner\n", __func__, info->name);
+
+       return fe;
+
+exit:
+       kfree(state);
+       return NULL;
+}
+EXPORT_SYMBOL(tda665x_attach);
+
+MODULE_DESCRIPTION("TDA665x driver");
+MODULE_AUTHOR("Manu Abraham");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/frontends/tda665x.h b/drivers/media/dvb/frontends/tda665x.h
new file mode 100644 (file)
index 0000000..c0b544d
--- /dev/null
@@ -0,0 +1,52 @@
+/*
+       TDA665x tuner driver
+       Copyright (C) Manu Abraham (abraham.manu@gmail.com)
+
+       This program is free software; you can redistribute it and/or modify
+       it under the terms of the GNU General Public License as published by
+       the Free Software Foundation; either version 2 of the License, or
+       (at your option) any later version.
+
+       This program is distributed in the hope that it will be useful,
+       but WITHOUT ANY WARRANTY; without even the implied warranty of
+       MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+       GNU General Public License for more details.
+
+       You should have received a copy of the GNU General Public License
+       along with this program; if not, write to the Free Software
+       Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#ifndef __TDA665x_H
+#define __TDA665x_H
+
+struct tda665x_config {
+       char name[128];
+
+       u8      addr;
+       u32     frequency_min;
+       u32     frequency_max;
+       u32     frequency_offst;
+       u32     ref_multiplier;
+       u32     ref_divider;
+};
+
+#if defined(CONFIG_DVB_TDA665x) || (defined(CONFIG_DVB_TDA665x_MODULE) && defined(MODULE))
+
+extern struct dvb_frontend *tda665x_attach(struct dvb_frontend *fe,
+                                          const struct tda665x_config *config,
+                                          struct i2c_adapter *i2c);
+
+#else
+
+static inline struct dvb_frontend *tda665x_attach(struct dvb_frontend *fe,
+                                                 const struct tda665x_config *config,
+                                                 struct i2c_adapter *i2c)
+{
+       printk(KERN_WARNING "%s: Driver disabled by Kconfig\n", __func__);
+       return NULL;
+}
+
+#endif /* CONFIG_DVB_TDA665x */
+
+#endif /* __TDA665x_H */
index 749e3f3dd06ba4edbe8003ffd5cf4db6a0205236..01a9ff07d770011af9a6db1aa5d78579a324035d 100644 (file)
@@ -219,7 +219,6 @@ static void __devexit hopper_pci_remove(struct pci_dev *pdev)
        struct mantis_pci *mantis = pci_get_drvdata(pdev);
 
        if (mantis) {
-//             mantis_uart_exit(mantis);
                mantis_dvb_exit(mantis);
                mantis_dma_exit(mantis);
                mantis_i2c_exit(mantis);
index d486c7fcb45314be621b02cfa055c9ca4c2cac52..638177ce72a2c22916532c6b9288f667651068c2 100644 (file)
@@ -50,7 +50,6 @@ static char *label[10] = {
        "RACK"
 };
 
-
 static irqreturn_t mantis_irq_handler(int irq, void *dev_id)
 {
        u32 stat = 0, mask = 0, lstat = 0, mstat = 0;
@@ -199,6 +198,14 @@ static int __devinit mantis_pci_probe(struct pci_dev *pdev, const struct pci_dev
 
        return err;
 
+fail7:
+       dprintk(MANTIS_ERROR, 1, "ERROR: Mantis UART exit! <%d>", err);
+       mantis_uart_exit(mantis);
+
+fail6:
+       dprintk(MANTIS_ERROR, 1, "ERROR: Mantis CA exit! <%d>", err);
+       mantis_ca_exit(mantis);
+
 fail5:
        dprintk(MANTIS_ERROR, 1, "ERROR: Mantis DVB exit! <%d>", err);
        mantis_dvb_exit(mantis);
@@ -228,8 +235,6 @@ static void __devexit mantis_pci_remove(struct pci_dev *pdev)
        struct mantis_pci *mantis = pci_get_drvdata(pdev);
 
        if (mantis) {
-               mantis_uart_exit(mantis);
-//             mantis_ca_exit(mantis);
                mantis_dvb_exit(mantis);
                mantis_dma_exit(mantis);
                mantis_i2c_exit(mantis);
index 8ebcd96b2b7d8e31c722b90ff79946b0b5884c55..eab3645f7acb935669222494f30ea2a5bb748e69 100644 (file)
@@ -153,8 +153,7 @@ int mantis_dma_init(struct mantis_pci *mantis)
        if (mantis_alloc_buffers(mantis) < 0) {
                dprintk(MANTIS_ERROR, 1, "Error allocating DMA buffer");
 
-               // Stop RISC Engine
-//             mmwrite(mmread(MANTIS_DMA_CTL) & ~MANTIS_RISC_EN, MANTIS_DMA_CTL);
+               /* Stop RISC Engine */
                mmwrite(0, MANTIS_DMA_CTL);
 
                goto err;
index be911d76daa7fd35f9e8d19bd99a6dd8ff7e8e51..42f658b06a668eb6e67bb728ee12f22f1a228950 100644 (file)
@@ -252,14 +252,19 @@ int __devinit mantis_dvb_init(struct mantis_pci *mantis)
 err5:
        tasklet_kill(&mantis->tasklet);
        dvb_net_release(&mantis->dvbnet);
+
 err4:
        mantis->demux.dmx.remove_frontend(&mantis->demux.dmx, &mantis->fe_mem);
+
 err3:
        mantis->demux.dmx.remove_frontend(&mantis->demux.dmx, &mantis->fe_hw);
+
 err2:
        dvb_dmxdev_release(&mantis->dmxdev);
+
 err1:
        dvb_dmx_release(&mantis->demux);
+
 err0:
        dvb_unregister_adapter(&mantis->dvb_adapter);
 
@@ -271,21 +276,24 @@ int __devexit mantis_dvb_exit(struct mantis_pci *mantis)
 {
        int err;
 
-       err = mantis_frontend_shutdown(mantis);
-       if (err != 0)
-               dprintk(MANTIS_ERROR, 1, "Frontend exit while POWER ON! <%d>", err);
+       if (mantis->fe) {
+//             mantis_ca_exit(mantis);
+               err = mantis_frontend_shutdown(mantis);
+               if (err != 0)
+                       dprintk(MANTIS_ERROR, 1, "Frontend exit while POWER ON! <%d>", err);
+
+               dvb_unregister_frontend(mantis->fe);
+       }
 
-//     mantis_ca_exit(mantis);
        tasklet_kill(&mantis->tasklet);
        dvb_net_release(&mantis->dvbnet);
+
        mantis->demux.dmx.remove_frontend(&mantis->demux.dmx, &mantis->fe_mem);
        mantis->demux.dmx.remove_frontend(&mantis->demux.dmx, &mantis->fe_hw);
+
        dvb_dmxdev_release(&mantis->dmxdev);
        dvb_dmx_release(&mantis->demux);
 
-       if (mantis->fe)
-               dvb_unregister_frontend(mantis->fe);
-
        dprintk(MANTIS_DEBUG, 1, "dvb_unregister_adapter");
        dvb_unregister_adapter(&mantis->dvb_adapter);
 
index ba55f0a9a10f8df2a770e3519d5cb836ce92a362..16b9e7e77b82a8d0ae026aaa77ab086666b81679 100644 (file)
 
 #define I2C_HW_B_MANTIS                0x1c
 
-static int mantis_ack_wait(struct mantis_pci *mantis)
-{
-       int rc = 0;
-       u32 timeout = 0;
-
-       if (wait_event_timeout(mantis->i2c_wq,
-                              mantis->mantis_int_stat & MANTIS_INT_I2CDONE,
-                              msecs_to_jiffies(50)) == -ERESTARTSYS) {
-
-               dprintk(MANTIS_DEBUG, 1, "Master !I2CDONE");
-               rc = -EREMOTEIO;
-       }
-
-       while (!(mantis->mantis_int_stat & MANTIS_INT_I2CRACK)) {
-               dprintk(MANTIS_DEBUG, 1, "Waiting for Slave RACK");
-               mantis->mantis_int_stat = mmread(MANTIS_INT_STAT);
-               msleep(5);
-               timeout++;
-               if (timeout > 500) {
-                       dprintk(MANTIS_ERROR, 1, "Slave RACK Fail !");
-                       rc = -EREMOTEIO;
-                       break;
-               }
-       }
-       udelay(350);
-
-       return rc;
-}
-
 static int mantis_i2c_read(struct mantis_pci *mantis, const struct i2c_msg *msg)
 {
-       u32 rxd, i;
+       u32 rxd, i, stat, trials;
 
        dprintk(MANTIS_INFO, 0, "        %s:  Address=[0x%02x] <R>[ ",
                __func__, msg->addr);
@@ -82,10 +53,15 @@ static int mantis_i2c_read(struct mantis_pci *mantis, const struct i2c_msg *msg)
 
                mmwrite(MANTIS_INT_I2CDONE, MANTIS_INT_STAT);
                mmwrite(rxd, MANTIS_I2CDATA_CTL);
-               if (mantis_ack_wait(mantis) != 0) {
-                       dprintk(MANTIS_DEBUG, 1, "ACK failed<R>");
-                       return -EREMOTEIO;
+
+               /* wait for xfer completion */
+               for (trials = 0; trials < 100; trials++) {
+                       udelay(500);
+                       stat = mmread(MANTIS_INT_STAT);
+                       if (stat & MANTIS_INT_I2CDONE)
+                               break;
                }
+
                rxd = mmread(MANTIS_I2CDATA_CTL);
                msg->buf[i] = (u8)((rxd >> 8) & 0xFF);
                dprintk(MANTIS_INFO, 0, "%02x ", msg->buf[i]);
@@ -98,7 +74,7 @@ static int mantis_i2c_read(struct mantis_pci *mantis, const struct i2c_msg *msg)
 static int mantis_i2c_write(struct mantis_pci *mantis, const struct i2c_msg *msg)
 {
        int i;
-       u32 txd = 0;
+       u32 txd = 0, stat, trials;
 
        dprintk(MANTIS_INFO, 0, "        %s: Address=[0x%02x] <W>[ ",
                __func__, msg->addr);
@@ -115,9 +91,13 @@ static int mantis_i2c_write(struct mantis_pci *mantis, const struct i2c_msg *msg
 
                mmwrite(MANTIS_INT_I2CDONE, MANTIS_INT_STAT);
                mmwrite(txd, MANTIS_I2CDATA_CTL);
-               if (mantis_ack_wait(mantis) != 0) {
-                       dprintk(MANTIS_DEBUG, 1, "ACK failed<W>");
-                       return -EREMOTEIO;
+
+               /* wait for xfer completion */
+               for (trials = 0; trials < 100; trials++) {
+                       udelay(500);
+                       stat = mmread(MANTIS_INT_STAT);
+                       if (stat & MANTIS_INT_I2CDONE)
+                               break;
                }
        }
        dprintk(MANTIS_INFO, 0, "]\n");
@@ -127,20 +107,77 @@ static int mantis_i2c_write(struct mantis_pci *mantis, const struct i2c_msg *msg
 
 static int mantis_i2c_xfer(struct i2c_adapter *adapter, struct i2c_msg *msgs, int num)
 {
-       int ret = 0, i;
+       int ret = 0, i = 0, trials;
+       u32 stat, data, txd;
        struct mantis_pci *mantis;
+       struct mantis_hwconfig *config;
 
        mantis = i2c_get_adapdata(adapter);
+       BUG_ON(!mantis);
+       config = mantis->hwconfig;
+       BUG_ON(!config);
+
+       dprintk(MANTIS_DEBUG, 1, "Messages:%d", num);
        mutex_lock(&mantis->i2c_lock);
-       for (i = 0; i < num; i++) {
-               if (msgs[i].flags & I2C_M_RD)
-                       ret = mantis_i2c_read(mantis, &msgs[i]);
-               else
-                       ret = mantis_i2c_write(mantis, &msgs[i]);
-
-               if (ret < 0)
-                       goto bail_out;
+
+       while (i < num) {
+               /* Byte MODE */
+               if (((i + 1) < num)             &&
+                       (msgs[i].len < 2)       &&
+                       (msgs[i + 1].len < 2)   &&
+                       (msgs[i + 1].flags & I2C_M_RD)) {
+
+                       dprintk(MANTIS_DEBUG, 0, "        Byte MODE:\n");
+
+                       /* Read operation */
+                       txd = msgs[i].addr << 25 | (0x1 << 24)
+                                                | (msgs[i].buf[0] << 16)
+                                                | MANTIS_I2C_RATE_3;
+
+                       mmwrite(txd, MANTIS_I2CDATA_CTL);
+                       /* wait for xfer completion */
+                       for (trials = 0; trials < 100; trials++) {
+                               udelay(500);
+                               stat = mmread(MANTIS_INT_STAT);
+                               if (stat & MANTIS_INT_I2CDONE)
+                                       break;
+                       }
+
+                       /* check for xfer completion */
+                       if (stat & MANTIS_INT_I2CDONE) {
+                               /* check xfer was acknowledged */
+                               if (stat & MANTIS_INT_I2CRACK) {
+                                       data = mmread(MANTIS_I2CDATA_CTL);
+                                       msgs[i + 1].buf[0] = (data >> 8) & 0xff;
+                                       dprintk(MANTIS_DEBUG, 0, "        Byte <%d> RXD=0x%02x  [%02x]\n", 0x0, data, msgs[i + 1].buf[0]);
+                               } else {
+                                       /* I/O error */
+                                       dprintk(MANTIS_ERROR, 1, "        I/O error, LINE:%d", __LINE__);
+                                       ret = -EIO;
+                                       break;
+                               }
+                       } else {
+                               /* I/O error */
+                               dprintk(MANTIS_ERROR, 1, "        I/O error, LINE:%d", __LINE__);
+                               ret = -EIO;
+                               break;
+                       }
+                       i += 2; /* Write/Read operation in one go */
+               }
+
+               if (i < num) {
+                       if (msgs[i].flags & I2C_M_RD)
+                               ret = mantis_i2c_read(mantis, &msgs[i]);
+                       else
+                               ret = mantis_i2c_write(mantis, &msgs[i]);
+
+                       i++;
+                       if (ret < 0)
+                               goto bail_out;
+               }
+
        }
+
        mutex_unlock(&mantis->i2c_lock);
 
        return num;
@@ -189,9 +226,9 @@ int __devinit mantis_i2c_init(struct mantis_pci *mantis)
        intstat = mmread(MANTIS_INT_STAT);
        intmask = mmread(MANTIS_INT_MASK);
        mmwrite(intstat, MANTIS_INT_STAT);
-       mmwrite(intmask | MANTIS_INT_I2CDONE, MANTIS_INT_MASK);
-
-       dprintk(MANTIS_DEBUG, 1, "Status=<%02x> Mask=<%02x>", intstat, intmask);
+       dprintk(MANTIS_DEBUG, 1, "Disabling I2C interrupt");
+       intmask = mmread(MANTIS_INT_MASK);
+       mmwrite((intmask & ~MANTIS_INT_I2CDONE), MANTIS_INT_MASK);
 
        return 0;
 }
@@ -199,6 +236,12 @@ EXPORT_SYMBOL_GPL(mantis_i2c_init);
 
 int __devexit mantis_i2c_exit(struct mantis_pci *mantis)
 {
+       u32 intmask;
+
+       dprintk(MANTIS_DEBUG, 1, "Disabling I2C interrupt");
+       intmask = mmread(MANTIS_INT_MASK);
+       mmwrite((intmask & ~MANTIS_INT_I2CDONE), MANTIS_INT_MASK);
+
        dprintk(MANTIS_DEBUG, 1, "Removing I2C adapter");
        return i2c_del_adapter(&mantis->adapter);
 }
index 1e49ecfeee3e84a87c8a33f9e456aaef56abe74b..d40da4fa000768b7e35a335cd9d9a3fa06b223bb 100644 (file)
@@ -1,6 +1,9 @@
 #ifndef __MANTIS_I2C_H
 #define __MANTIS_I2C_H
 
+#define I2C_STOP               (1 <<  0)
+#define I2C_READ               (1 <<  1)
+
 extern int mantis_i2c_init(struct mantis_pci *mantis);
 extern int mantis_i2c_exit(struct mantis_pci *mantis);
 
index 4700088f03889af715a5c391ecf145e119a8a15f..448e2c3e344581f430184d4c20ac40d7aba5e32b 100644 (file)
 #include "mantis_reg.h"
 #include "mantis_ioc.h"
 
-static int read_eeprom_byte(struct mantis_pci *mantis, u8 *data, u8 length)
+static int read_eeprom_bytes(struct mantis_pci *mantis, u8 reg, u8 *data, u8 length)
 {
        struct i2c_adapter *adapter = &mantis->adapter;
-
        int err;
+       u8 buf = reg;
+
        struct i2c_msg msg[] = {
-               { .addr = 0x50, .flags = 0, .buf = data, .len = 1 },
+               { .addr = 0x50, .flags = 0, .buf = &buf, .len = 1 },
                { .addr = 0x50, .flags = I2C_M_RD, .buf = data, .len = length },
        };
 
@@ -56,32 +57,12 @@ static int read_eeprom_byte(struct mantis_pci *mantis, u8 *data, u8 length)
 
        return 0;
 }
-
-static int write_eeprom_byte(struct mantis_pci *mantis, u8 *data, u8 length)
-{
-       struct i2c_adapter *adapter = &mantis->adapter;
-       int err;
-
-       struct i2c_msg msg = { .addr = 0x50, .flags = 0, .buf = data, .len = length };
-
-       err = i2c_transfer(adapter, &msg, 1);
-       if (err < 0) {
-               dprintk(MANTIS_ERROR, 1, "ERROR: i2c write: < err=%i length=0x%02x d0=0x%02x, d1=0x%02x >",
-                       err, length, data[0], data[1]);
-
-               return err;
-       }
-
-       return 0;
-}
-
 int mantis_get_mac(struct mantis_pci *mantis)
 {
        int err;
+       u8 mac_addr[6] = {0};
 
-       mantis->mac_address[0] = 0x08;
-
-       err = read_eeprom_byte(mantis, &mantis->mac_address[0], 6);
+       err = read_eeprom_bytes(mantis, 0x08, mac_addr, 6);
        if (err < 0) {
                dprintk(MANTIS_ERROR, 1, "ERROR: Mantis EEPROM read error <%d>", err);
 
@@ -90,9 +71,12 @@ int mantis_get_mac(struct mantis_pci *mantis)
 
        dprintk(MANTIS_ERROR, 0,
                "    MAC Address=[%02x:%02x:%02x:%02x:%02x:%02x]\n",
-               mantis->mac_address[0], mantis->mac_address[1],
-               mantis->mac_address[2], mantis->mac_address[3],
-               mantis->mac_address[4], mantis->mac_address[5]);
+               mac_addr[0],
+               mac_addr[1],
+               mac_addr[2],
+               mac_addr[3],
+               mac_addr[4],
+               mac_addr[5]);
 
        return 0;
 }
@@ -103,12 +87,14 @@ void gpio_set_bits(struct mantis_pci *mantis, u32 bitpos, u8 value)
 {
        u32 cur;
 
+       dprintk(MANTIS_DEBUG, 1, "Set Bit <%d> to <%d>", bitpos, value);
        cur = mmread(MANTIS_GPIF_ADDR);
        if (value)
                mantis->gpio_status = cur | (1 << bitpos);
        else
                mantis->gpio_status = cur & (~(1 << bitpos));
 
+       dprintk(MANTIS_DEBUG, 1, "GPIO Value <%02x>", mantis->gpio_status);
        mmwrite(mantis->gpio_status, MANTIS_GPIF_ADDR);
        mmwrite(0x00, MANTIS_GPIF_DOUT);
 }
index 4b974eeefa9e47c60ee26bdb216d6c1ed2f6e2e9..9efcfa7b8ab457ad5d5d11bf0cbffe2d4139da55 100644 (file)
 #include "dvb_net.h"
 
 #include "zl10353.h"
+#include "tda665x.h"
 #include "mantis_common.h"
+#include "mantis_ioc.h"
+#include "mantis_dvb.h"
 #include "mantis_vp3030.h"
 
 struct zl10353_config mantis_vp3030_config = {
-       .demod_address  = 0x0f,
+       .demod_address          = 0x0f,
+};
+
+struct tda665x_config env57h12d5_config = {
+       .name                   = "ENV57H12D5 (ET-50DT)",
+       .addr                   = 0x60,
+       .frequency_min          =  47000000,
+       .frequency_max          = 862000000,
+       .frequency_offst        =   3616667,
+       .ref_multiplier         = 6, /* 1/6 MHz */
+       .ref_divider            = 100000, /* 1/6 MHz */
 };
 
 #define MANTIS_MODEL_NAME      "VP-3030"
 #define MANTIS_DEV_TYPE                "DVB-T"
 
-int panasonic_en57h12d5_set_params(struct dvb_frontend *fe,
-                                  struct dvb_frontend_parameters *params)
-{
-       u8 buf[4];
-       int rc;
-       struct mantis_pci *mantis = fe->dvb->priv;
-
-       struct i2c_msg tuner_msg = {
-               .addr = 0x60,
-               .flags = 0,
-               .buf = buf,
-               .len = sizeof (buf)
-       };
-
-       if ((params->frequency < 950000) || (params->frequency > 2150000))
-               return -EINVAL;
-       rc = i2c_transfer(&mantis->adapter, &tuner_msg, 1);
-       if (rc != 1) {
-               printk("%s: I2C Transfer returned [%d]\n", __func__, rc);
-               return -EIO;
-       }
-       msleep_interruptible(1);
-       printk("%s: Send params to tuner ok!!!\n", __func__);
-
-       return 0;
-}
 
 static int vp3030_frontend_init(struct mantis_pci *mantis, struct dvb_frontend *fe)
 {
        struct i2c_adapter *adapter     = &mantis->adapter;
+       struct mantis_hwconfig *config  = mantis->hwconfig;
+       int err = 0;
+
+       gpio_set_bits(mantis, config->reset, 0);
+       msleep(100);
+       err = mantis_frontend_power(mantis, POWER_ON);
+       msleep(100);
+       gpio_set_bits(mantis, config->reset, 1);
 
        dprintk(MANTIS_ERROR, 1, "Probing for 10353 (DVB-T)");
        fe = zl10353_attach(&mantis_vp3030_config, adapter);
@@ -77,6 +72,7 @@ static int vp3030_frontend_init(struct mantis_pci *mantis, struct dvb_frontend *
        if (!fe)
                return -1;
 
+       tda665x_attach(fe, &env57h12d5_config, adapter);
        mantis->fe = fe;
        dprintk(MANTIS_ERROR, 1, "Done!");
 
@@ -93,4 +89,6 @@ struct mantis_hwconfig vp3030_config = {
        .bytes          = 0,
 
        .frontend_init  = vp3030_frontend_init,
+       .power          = GPIF_A12,
+       .reset          = GPIF_A13,
 };