V4L/DVB (10805): Add support for NetUP Dual DVB-S2 CI card
authorIgor M. Liplianin <liplianin@netup.ru>
Tue, 3 Mar 2009 15:06:09 +0000 (12:06 -0300)
committerMauro Carvalho Chehab <mchehab@redhat.com>
Mon, 30 Mar 2009 15:43:05 +0000 (12:43 -0300)
Add support for NetUP Dual DVB-S2 CI card
The card based on cx23885 PCI-e bridge, CiMax SP2 Common Interface chips,
STM lnbh24 LNB power chip, stv6110 tuners and stv0900 demodulator.
http://www.linuxtv.org/wiki/index.php/NetUP_Dual_DVB_S2_CI

Signed-off-by: Igor M. Liplianin <liplianin@netup.ru>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Documentation/video4linux/CARDLIST.cx23885
drivers/media/video/cx23885/Kconfig
drivers/media/video/cx23885/Makefile
drivers/media/video/cx23885/cx23885-cards.c
drivers/media/video/cx23885/cx23885-core.c
drivers/media/video/cx23885/cx23885-dvb.c
drivers/media/video/cx23885/cx23885-reg.h
drivers/media/video/cx23885/cx23885.h

index 5937ff9..91aa3c0 100644 (file)
@@ -15,3 +15,4 @@
  14 -> TurboSight TBS 6920                                 [6920:8888]
  15 -> TeVii S470                                          [d470:9022]
  16 -> DVBWorld DVB-S2 2005                                [0001:2005]
+ 17 -> NetUP Dual DVB-S2 CI                                [1b55:2a2c]
index 00f1e2e..b62f16d 100644 (file)
@@ -16,6 +16,7 @@ config VIDEO_CX23885
        select DVB_LGDT330X if !DVB_FE_CUSTOMISE
        select DVB_ZL10353 if !DVB_FE_CUSTOMISE
        select DVB_TDA10048 if !DVB_FE_CUSTOMIZE
+       select DVB_LNBP21 if !DVB_FE_CUSTOMIZE
        select MEDIA_TUNER_MT2131 if !MEDIA_TUNER_CUSTOMIZE
        select MEDIA_TUNER_XC2028 if !DVB_FE_CUSTOMIZE
        select MEDIA_TUNER_TDA8290 if !DVB_FE_CUSTOMIZE
index 29c23b4..ab8ea35 100644 (file)
@@ -1,4 +1,6 @@
-cx23885-objs   := cx23885-cards.o cx23885-video.o cx23885-vbi.o cx23885-core.o cx23885-i2c.o cx23885-dvb.o cx23885-417.o
+cx23885-objs   := cx23885-cards.o cx23885-video.o cx23885-vbi.o \
+                   cx23885-core.o cx23885-i2c.o cx23885-dvb.o cx23885-417.o \
+                   netup-init.o cimax2.o netup-eeprom.o
 
 obj-$(CONFIG_VIDEO_CX23885) += cx23885.o
 
index 7ff339a..08cd793 100644 (file)
@@ -27,6 +27,7 @@
 
 #include "cx23885.h"
 #include "tuner-xc2028.h"
+#include "netup-init.h"
 
 /* ------------------------------------------------------------------ */
 /* board config info                                                  */
@@ -174,6 +175,12 @@ struct cx23885_board cx23885_boards[] = {
                .name           = "DVBWorld DVB-S2 2005",
                .portb          = CX23885_MPEG_DVB,
        },
+       [CX23885_BOARD_NETUP_DUAL_DVBS2_CI] = {
+               .cimax          = 1,
+               .name           = "NetUP Dual DVB-S2 CI",
+               .portb          = CX23885_MPEG_DVB,
+               .portc          = CX23885_MPEG_DVB,
+       },
 };
 const unsigned int cx23885_bcount = ARRAY_SIZE(cx23885_boards);
 
@@ -269,6 +276,10 @@ struct cx23885_subid cx23885_subids[] = {
                .subvendor = 0x0001,
                .subdevice = 0x2005,
                .card      = CX23885_BOARD_DVBWORLD_2005,
+       }, {
+               .subvendor = 0x1b55,
+               .subdevice = 0x2a2c,
+               .card      = CX23885_BOARD_NETUP_DUAL_DVBS2_CI,
        },
 };
 const unsigned int cx23885_idcount = ARRAY_SIZE(cx23885_subids);
@@ -582,6 +593,32 @@ void cx23885_gpio_setup(struct cx23885_dev *dev)
                cx_write(MC417_OEN, 0x00001000);
                cx_write(MC417_RWD, 0x00001800);
                break;
+       case CX23885_BOARD_NETUP_DUAL_DVBS2_CI:
+               /* GPIO-0 INTA from CiMax1
+                  GPIO-1 INTB from CiMax2
+                  GPIO-2 reset chips
+                  GPIO-3 to GPIO-10 data/addr for CA
+                  GPIO-11 ~CS0 to CiMax1
+                  GPIO-12 ~CS1 to CiMax2
+                  GPIO-13 ADL0 load LSB addr
+                  GPIO-14 ADL1 load MSB addr
+                  GPIO-15 ~RDY from CiMax
+                  GPIO-17 ~RD to CiMax
+                  GPIO-18 ~WR to CiMax
+                */
+               cx_set(GP0_IO, 0x00040000); /* GPIO as out */
+               /* GPIO1 and GPIO2 as INTA and INTB from CiMaxes, reset low */
+               cx_clear(GP0_IO, 0x00030004);
+               mdelay(100);/* reset delay */
+               cx_set(GP0_IO, 0x00040004); /* GPIO as out, reset high */
+               cx_write(MC417_CTL, 0x00000037);/* enable GPIO3-18 pins */
+               /* GPIO-15 IN as ~ACK, rest as OUT */
+               cx_write(MC417_OEN, 0x00001000);
+               /* ~RD, ~WR high; ADL0, ADL1 low; ~CS0, ~CS1 high */
+               cx_write(MC417_RWD, 0x0000c300);
+               /* enable irq */
+               cx_write(GPIO_ISM, 0x00000000);/* INTERRUPTS active low*/
+               break;
        }
 }
 
@@ -669,6 +706,14 @@ void cx23885_card_setup(struct cx23885_dev *dev)
                ts1->ts_clk_en_val = 0x1; /* Enable TS_CLK */
                ts1->src_sel_val   = CX23885_SRC_SEL_PARALLEL_MPEG_VIDEO;
                break;
+       case CX23885_BOARD_NETUP_DUAL_DVBS2_CI:
+               ts1->gen_ctrl_val  = 0xc; /* Serial bus + punctured clock */
+               ts1->ts_clk_en_val = 0x1; /* Enable TS_CLK */
+               ts1->src_sel_val   = CX23885_SRC_SEL_PARALLEL_MPEG_VIDEO;
+               ts2->gen_ctrl_val  = 0xc; /* Serial bus + punctured clock */
+               ts2->ts_clk_en_val = 0x1; /* Enable TS_CLK */
+               ts2->src_sel_val   = CX23885_SRC_SEL_PARALLEL_MPEG_VIDEO;
+               break;
        case CX23885_BOARD_HAUPPAUGE_HVR1250:
        case CX23885_BOARD_HAUPPAUGE_HVR1500:
        case CX23885_BOARD_HAUPPAUGE_HVR1500Q:
@@ -693,9 +738,17 @@ void cx23885_card_setup(struct cx23885_dev *dev)
        case CX23885_BOARD_HAUPPAUGE_HVR1700:
        case CX23885_BOARD_LEADTEK_WINFAST_PXDVR3200_H:
        case CX23885_BOARD_COMPRO_VIDEOMATE_E650F:
+       case CX23885_BOARD_NETUP_DUAL_DVBS2_CI:
                request_module("cx25840");
                break;
        }
+
+       /* AUX-PLL 27MHz CLK */
+       switch (dev->board) {
+       case CX23885_BOARD_NETUP_DUAL_DVBS2_CI:
+               netup_initialize(dev);
+               break;
+       }
 }
 
 /* ------------------------------------------------------------------ */
index 8f6fb2a..1b40145 100644 (file)
@@ -31,6 +31,7 @@
 #include <asm/div64.h>
 
 #include "cx23885.h"
+#include "cimax2.h"
 
 MODULE_DESCRIPTION("Driver for cx23885 based TV cards");
 MODULE_AUTHOR("Steven Toth <stoth@linuxtv.org>");
@@ -791,6 +792,8 @@ static int cx23885_dev_setup(struct cx23885_dev *dev)
        dev->pci_bus  = dev->pci->bus->number;
        dev->pci_slot = PCI_SLOT(dev->pci->devfn);
        dev->pci_irqmask = 0x001f00;
+       if (cx23885_boards[dev->board].cimax > 0)
+               dev->pci_irqmask |= 0x01800000; /* for CiMaxes */
 
        /* External Master 1 Bus */
        dev->i2c_bus[0].nr = 0;
@@ -1643,7 +1646,9 @@ static irqreturn_t cx23885_irq(int irq, void *dev_id)
            (pci_status & PCI_MSK_VID_B) ||
            (pci_status & PCI_MSK_VID_A) ||
            (pci_status & PCI_MSK_AUD_INT) ||
-           (pci_status & PCI_MSK_AUD_EXT)) {
+           (pci_status & PCI_MSK_AUD_EXT) ||
+           (pci_status & PCI_MSK_GPIO0) ||
+           (pci_status & PCI_MSK_GPIO1)) {
 
                if (pci_status & PCI_MSK_RISC_RD)
                        dprintk(7, " (PCI_MSK_RISC_RD   0x%08x)\n",
@@ -1685,8 +1690,19 @@ static irqreturn_t cx23885_irq(int irq, void *dev_id)
                        dprintk(7, " (PCI_MSK_AUD_EXT   0x%08x)\n",
                                PCI_MSK_AUD_EXT);
 
+               if (pci_status & PCI_MSK_GPIO0)
+                       dprintk(7, " (PCI_MSK_GPIO0     0x%08x)\n",
+                               PCI_MSK_GPIO0);
+
+               if (pci_status & PCI_MSK_GPIO1)
+                       dprintk(7, " (PCI_MSK_GPIO1     0x%08x)\n",
+                               PCI_MSK_GPIO1);
        }
 
+       if ((pci_status & PCI_MSK_GPIO0) || (pci_status & PCI_MSK_GPIO1))
+               /* handled += cx23885_irq_gpio(dev, pci_status); */
+               handled += netup_ci_slot_status(dev, pci_status);
+
        if (ts1_status) {
                if (cx23885_boards[dev->board].portb == CX23885_MPEG_DVB)
                        handled += cx23885_irq_ts(ts1, ts1_status);
@@ -1759,6 +1775,8 @@ static int __devinit cx23885_initdev(struct pci_dev *pci_dev,
        }
 
        pci_set_drvdata(pci_dev, dev);
+       cx_set(PCI_INT_MSK, 0x01800000); /* for NetUP */
+
        return 0;
 
 fail_irq:
index 14a6540..9a0bc6e 100644 (file)
@@ -30,6 +30,7 @@
 #include "cx23885.h"
 #include <media/v4l2-common.h>
 
+#include "dvb_ca_en50221.h"
 #include "s5h1409.h"
 #include "s5h1411.h"
 #include "mt2131.h"
 #include "dib7000p.h"
 #include "dibx000_common.h"
 #include "zl10353.h"
+#include "stv0900.h"
+#include "stv6110.h"
+#include "lnbh24.h"
 #include "cx24116.h"
+#include "cimax2.h"
+#include "netup-eeprom.h"
+#include "netup-init.h"
 
 static unsigned int debug;
 
@@ -309,6 +316,31 @@ static struct zl10353_config dvico_fusionhdtv_xc3028 = {
        .no_tuner      = 1,
 };
 
+static struct stv0900_config netup_stv0900_config = {
+       .demod_address = 0x68,
+       .xtal = 27000000,
+       .clkmode = 3,/* 0-CLKI, 2-XTALI, else AUTO */
+       .diseqc_mode = 2,/* 2/3 PWM */
+       .path1_mode = 2,/*Serial continues clock */
+       .path2_mode = 2,/*Serial continues clock */
+       .tun1_maddress = 0,/* 0x60 */
+       .tun2_maddress = 3,/* 0x63 */
+       .tun1_adc = 1,/* 1 Vpp */
+       .tun2_adc = 1,/* 1 Vpp */
+};
+
+static struct stv6110_config netup_stv6110_tunerconfig_a = {
+       .i2c_address = 0x60,
+       .mclk = 27000000,
+       .iq_wiring = 0,
+};
+
+static struct stv6110_config netup_stv6110_tunerconfig_b = {
+       .i2c_address = 0x63,
+       .mclk = 27000000,
+       .iq_wiring = 1,
+};
+
 static int tbs_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage)
 {
        struct cx23885_tsport *port = fe->dvb->priv;
@@ -340,6 +372,7 @@ static int dvb_register(struct cx23885_tsport *port)
        struct cx23885_dev *dev = port->dev;
        struct cx23885_i2c *i2c_bus = NULL;
        struct videobuf_dvb_frontend *fe0;
+       int ret;
 
        /* Get the first frontend */
        fe0 = videobuf_dvb_get_frontend(&port->frontends, 1);
@@ -580,6 +613,51 @@ static int dvb_register(struct cx23885_tsport *port)
                        &dvbworld_cx24116_config,
                        &i2c_bus->i2c_adap);
                break;
+       case CX23885_BOARD_NETUP_DUAL_DVBS2_CI:
+               i2c_bus = &dev->i2c_bus[0];
+               switch (port->nr) {
+               /* port B */
+               case 1:
+                       fe0->dvb.frontend = dvb_attach(stv0900_attach,
+                                                       &netup_stv0900_config,
+                                                       &i2c_bus->i2c_adap, 0);
+                       if (fe0->dvb.frontend != NULL) {
+                               if (dvb_attach(stv6110_attach,
+                                               fe0->dvb.frontend,
+                                               &netup_stv6110_tunerconfig_a,
+                                               &i2c_bus->i2c_adap)) {
+                                       if (!dvb_attach(lnbh24_attach,
+                                                       fe0->dvb.frontend,
+                                                       &i2c_bus->i2c_adap,
+                                                       LNBH24_PCL, 0, 0x09))
+                                               printk(KERN_ERR
+                                                       "No LNBH24 found!\n");
+
+                               }
+                       }
+                       break;
+               /* port C */
+               case 2:
+                       fe0->dvb.frontend = dvb_attach(stv0900_attach,
+                                                       &netup_stv0900_config,
+                                                       &i2c_bus->i2c_adap, 1);
+                       if (fe0->dvb.frontend != NULL) {
+                               if (dvb_attach(stv6110_attach,
+                                               fe0->dvb.frontend,
+                                               &netup_stv6110_tunerconfig_b,
+                                               &i2c_bus->i2c_adap)) {
+                                       if (!dvb_attach(lnbh24_attach,
+                                                       fe0->dvb.frontend,
+                                                       &i2c_bus->i2c_adap,
+                                                       LNBH24_PCL, 0, 0x0a))
+                                               printk(KERN_ERR
+                                                       "No LNBH24 found!\n");
+
+                               }
+                       }
+                       break;
+               }
+               break;
        default:
                printk(KERN_INFO "%s: The frontend of your DVB/ATSC card "
                        " isn't supported yet\n",
@@ -601,9 +679,33 @@ static int dvb_register(struct cx23885_tsport *port)
                fe0->dvb.frontend->ops.analog_ops.standby(fe0->dvb.frontend);
 
        /* register everything */
-       return videobuf_dvb_register_bus(&port->frontends, THIS_MODULE, port,
+       ret = videobuf_dvb_register_bus(&port->frontends, THIS_MODULE, port,
                &dev->pci->dev, adapter_nr, 0);
 
+       /* init CI & MAC */
+       switch (dev->board) {
+       case CX23885_BOARD_NETUP_DUAL_DVBS2_CI: {
+               static struct netup_card_info cinfo;
+
+               netup_get_card_info(&dev->i2c_bus[0].i2c_adap, &cinfo);
+               memcpy(port->frontends.adapter.proposed_mac,
+                               cinfo.port[port->nr - 1].mac, 6);
+               printk(KERN_INFO "NetUP Dual DVB-S2 CI card port%d MAC="
+                       "%02X:%02X:%02X:%02X:%02X:%02X\n",
+                       port->nr,
+                       port->frontends.adapter.proposed_mac[0],
+                       port->frontends.adapter.proposed_mac[1],
+                       port->frontends.adapter.proposed_mac[2],
+                       port->frontends.adapter.proposed_mac[3],
+                       port->frontends.adapter.proposed_mac[4],
+                       port->frontends.adapter.proposed_mac[5]);
+
+               netup_ci_init(port);
+               break;
+               }
+       }
+
+       return ret;
 }
 
 int cx23885_dvb_register(struct cx23885_tsport *port)
@@ -676,6 +778,8 @@ int cx23885_dvb_unregister(struct cx23885_tsport *port)
        if (fe0->dvb.frontend)
                videobuf_dvb_unregister_bus(&port->frontends);
 
+       netup_ci_exit(port);
+
        return 0;
 }
 
index 20b68a2..eafbe52 100644 (file)
@@ -212,6 +212,8 @@ Channel manager Data Structure entry = 20 DWORD
 
 #define DEV_CNTRL2     0x00040000
 
+#define PCI_MSK_GPIO1   (1 << 24)
+#define PCI_MSK_GPIO0   (1 << 23)
 #define PCI_MSK_APB_DMA   (1 << 12)
 #define PCI_MSK_AL_WR     (1 << 11)
 #define PCI_MSK_AL_RD     (1 << 10)
index 37a88b1..779fc35 100644 (file)
@@ -70,6 +70,7 @@
 #define CX23885_BOARD_TBS_6920                 14
 #define CX23885_BOARD_TEVII_S470               15
 #define CX23885_BOARD_DVBWORLD_2005            16
+#define CX23885_BOARD_NETUP_DUAL_DVBS2_CI      17
 
 /* Currently unsupported by the driver: PAL/H, NTSC/Kr, SECAM B/G/H/LC */
 #define CX23885_NORMS (\
@@ -187,6 +188,7 @@ struct cx23885_board {
         */
        u32                     clk_freq;
        struct cx23885_input    input[MAX_CX23885_INPUT];
+       int                     cimax; /* for NetUP */
 };
 
 struct cx23885_subid {
@@ -269,6 +271,7 @@ struct cx23885_tsport {
 
        /* Allow a single tsport to have multiple frontends */
        u32                        num_frontends;
+       void                       *port_priv;
 };
 
 struct cx23885_dev {