summaryrefslogtreecommitdiffstats
path: root/drivers/media/pci/netup_unidvb
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media/pci/netup_unidvb')
-rw-r--r--drivers/media/pci/netup_unidvb/Kconfig7
-rw-r--r--drivers/media/pci/netup_unidvb/netup_unidvb.h10
-rw-r--r--drivers/media/pci/netup_unidvb/netup_unidvb_ci.c4
-rw-r--r--drivers/media/pci/netup_unidvb/netup_unidvb_core.c174
4 files changed, 127 insertions, 68 deletions
diff --git a/drivers/media/pci/netup_unidvb/Kconfig b/drivers/media/pci/netup_unidvb/Kconfig
index f277b0b10c2d..0ad37714c7fd 100644
--- a/drivers/media/pci/netup_unidvb/Kconfig
+++ b/drivers/media/pci/netup_unidvb/Kconfig
@@ -5,8 +5,13 @@ config DVB_NETUP_UNIDVB
select VIDEOBUF2_VMALLOC
select DVB_HORUS3A if MEDIA_SUBDRV_AUTOSELECT
select DVB_ASCOT2E if MEDIA_SUBDRV_AUTOSELECT
+ select DVB_HELENE if MEDIA_SUBDRV_AUTOSELECT
select DVB_LNBH25 if MEDIA_SUBDRV_AUTOSELECT
select DVB_CXD2841ER if MEDIA_SUBDRV_AUTOSELECT
---help---
Support for NetUP PCI express Universal DVB card.
-
+ help
+ Say Y when you want to support NetUP Dual Universal DVB card
+ Card can receive two independent streams in following standards:
+ DVB-S/S2, T/T2, C/C2
+ Two CI slots available for CAM modules.
diff --git a/drivers/media/pci/netup_unidvb/netup_unidvb.h b/drivers/media/pci/netup_unidvb/netup_unidvb.h
index a67b28111905..39b08ecda1fc 100644
--- a/drivers/media/pci/netup_unidvb/netup_unidvb.h
+++ b/drivers/media/pci/netup_unidvb/netup_unidvb.h
@@ -50,6 +50,15 @@
#define NETUP_UNIDVB_IRQ_CAM0 (1 << 11)
#define NETUP_UNIDVB_IRQ_CAM1 (1 << 12)
+/* NetUP Universal DVB card hardware revisions and it's PCI device id's:
+ * 1.3 - CXD2841ER demod, ASCOT2E and HORUS3A tuners
+ * 1.4 - CXD2854ER demod, HELENE tuner
+*/
+enum netup_hw_rev {
+ NETUP_HW_REV_1_3 = 0x18F6,
+ NETUP_HW_REV_1_4 = 0x18F7
+};
+
struct netup_dma {
u8 num;
spinlock_t lock;
@@ -119,6 +128,7 @@ struct netup_unidvb_dev {
struct netup_dma dma[2];
struct netup_ci_state ci[2];
struct netup_spi *spi;
+ enum netup_hw_rev rev;
};
int netup_i2c_register(struct netup_unidvb_dev *ndev);
diff --git a/drivers/media/pci/netup_unidvb/netup_unidvb_ci.c b/drivers/media/pci/netup_unidvb/netup_unidvb_ci.c
index f46ffac66ee9..f535270c2116 100644
--- a/drivers/media/pci/netup_unidvb/netup_unidvb_ci.c
+++ b/drivers/media/pci/netup_unidvb/netup_unidvb_ci.c
@@ -147,7 +147,7 @@ static int netup_unidvb_ci_read_attribute_mem(struct dvb_ca_en50221 *en50221,
{
struct netup_ci_state *state = en50221->data;
struct netup_unidvb_dev *dev = state->dev;
- u8 val = *((u8 __force *)state->membase8_io + addr);
+ u8 val = *((u8 __force *)state->membase8_config + addr);
dev_dbg(&dev->pci_dev->dev,
"%s(): addr=0x%x val=0x%x\n", __func__, addr, val);
@@ -162,7 +162,7 @@ static int netup_unidvb_ci_write_attribute_mem(struct dvb_ca_en50221 *en50221,
dev_dbg(&dev->pci_dev->dev,
"%s(): addr=0x%x data=0x%x\n", __func__, addr, data);
- *((u8 __force *)state->membase8_io + addr) = data;
+ *((u8 __force *)state->membase8_config + addr) = data;
return 0;
}
diff --git a/drivers/media/pci/netup_unidvb/netup_unidvb_core.c b/drivers/media/pci/netup_unidvb/netup_unidvb_core.c
index 2b667b315913..ac547cb84de8 100644
--- a/drivers/media/pci/netup_unidvb/netup_unidvb_core.c
+++ b/drivers/media/pci/netup_unidvb/netup_unidvb_core.c
@@ -34,6 +34,7 @@
#include "cxd2841er.h"
#include "horus3a.h"
#include "ascot2e.h"
+#include "helene.h"
#include "lnbh25.h"
static int spi_enable;
@@ -120,7 +121,8 @@ static int netup_unidvb_tuner_ctrl(void *priv, int is_dvb_tc);
static void netup_unidvb_queue_cleanup(struct netup_dma *dma);
static struct cxd2841er_config demod_config = {
- .i2c_addr = 0xc8
+ .i2c_addr = 0xc8,
+ .xtal = SONY_XTAL_24000
};
static struct horus3a_config horus3a_conf = {
@@ -134,6 +136,12 @@ static struct ascot2e_config ascot2e_conf = {
.set_tuner_callback = netup_unidvb_tuner_ctrl
};
+static struct helene_config helene_conf = {
+ .i2c_address = 0xc0,
+ .xtal = SONY_HELENE_XTAL_24000,
+ .set_tuner_callback = netup_unidvb_tuner_ctrl
+};
+
static struct lnbh25_config lnbh25_conf = {
.i2c_address = 0x10,
.data2_config = LNBH25_TEN | LNBH25_EXTM
@@ -152,6 +160,11 @@ static int netup_unidvb_tuner_ctrl(void *priv, int is_dvb_tc)
__func__, dma->num, is_dvb_tc);
reg = readb(ndev->bmmio0 + GPIO_REG_IO);
mask = (dma->num == 0) ? GPIO_RFA_CTL : GPIO_RFB_CTL;
+
+ /* inverted tuner control in hw rev. 1.4 */
+ if (ndev->rev == NETUP_HW_REV_1_4)
+ is_dvb_tc = !is_dvb_tc;
+
if (!is_dvb_tc)
reg |= mask;
else
@@ -280,7 +293,7 @@ static int netup_unidvb_queue_setup(struct vb2_queue *vq,
unsigned int *nbuffers,
unsigned int *nplanes,
unsigned int sizes[],
- void *alloc_ctxs[])
+ struct device *alloc_devs[])
{
struct netup_dma *dma = vb2_get_drv_priv(vq);
@@ -372,7 +385,15 @@ static int netup_unidvb_queue_init(struct netup_dma *dma,
static int netup_unidvb_dvb_init(struct netup_unidvb_dev *ndev,
int num)
{
- struct vb2_dvb_frontend *fe0, *fe1, *fe2;
+ int fe_count = 2;
+ int i = 0;
+ struct vb2_dvb_frontend *fes[2];
+ u8 fe_name[32];
+
+ if (ndev->rev == NETUP_HW_REV_1_3)
+ demod_config.xtal = SONY_XTAL_20500;
+ else
+ demod_config.xtal = SONY_XTAL_24000;
if (num < 0 || num > 1) {
dev_dbg(&ndev->pci_dev->dev,
@@ -381,84 +402,96 @@ static int netup_unidvb_dvb_init(struct netup_unidvb_dev *ndev,
}
mutex_init(&ndev->frontends[num].lock);
INIT_LIST_HEAD(&ndev->frontends[num].felist);
- if (vb2_dvb_alloc_frontend(&ndev->frontends[num], 1) == NULL ||
- vb2_dvb_alloc_frontend(
- &ndev->frontends[num], 2) == NULL ||
- vb2_dvb_alloc_frontend(
- &ndev->frontends[num], 3) == NULL) {
- dev_dbg(&ndev->pci_dev->dev,
- "%s(): unable to allocate vb2_dvb_frontend\n",
- __func__);
- return -ENOMEM;
+
+ for (i = 0; i < fe_count; i++) {
+ if (vb2_dvb_alloc_frontend(&ndev->frontends[num], i+1)
+ == NULL) {
+ dev_err(&ndev->pci_dev->dev,
+ "%s(): unable to allocate vb2_dvb_frontend\n",
+ __func__);
+ return -ENOMEM;
+ }
}
- fe0 = vb2_dvb_get_frontend(&ndev->frontends[num], 1);
- fe1 = vb2_dvb_get_frontend(&ndev->frontends[num], 2);
- fe2 = vb2_dvb_get_frontend(&ndev->frontends[num], 3);
- if (fe0 == NULL || fe1 == NULL || fe2 == NULL) {
- dev_dbg(&ndev->pci_dev->dev,
- "%s(): frontends has not been allocated\n", __func__);
- return -EINVAL;
+
+ for (i = 0; i < fe_count; i++) {
+ fes[i] = vb2_dvb_get_frontend(&ndev->frontends[num], i+1);
+ if (fes[i] == NULL) {
+ dev_err(&ndev->pci_dev->dev,
+ "%s(): frontends has not been allocated\n",
+ __func__);
+ return -EINVAL;
+ }
+ }
+
+ for (i = 0; i < fe_count; i++) {
+ netup_unidvb_queue_init(&ndev->dma[num], &fes[i]->dvb.dvbq);
+ snprintf(fe_name, sizeof(fe_name), "netup_fe%d", i);
+ fes[i]->dvb.name = fe_name;
}
- netup_unidvb_queue_init(&ndev->dma[num], &fe0->dvb.dvbq);
- netup_unidvb_queue_init(&ndev->dma[num], &fe1->dvb.dvbq);
- netup_unidvb_queue_init(&ndev->dma[num], &fe2->dvb.dvbq);
- fe0->dvb.name = "netup_fe0";
- fe1->dvb.name = "netup_fe1";
- fe2->dvb.name = "netup_fe2";
- fe0->dvb.frontend = dvb_attach(cxd2841er_attach_s,
+
+ fes[0]->dvb.frontend = dvb_attach(cxd2841er_attach_s,
&demod_config, &ndev->i2c[num].adap);
- if (fe0->dvb.frontend == NULL) {
+ if (fes[0]->dvb.frontend == NULL) {
dev_dbg(&ndev->pci_dev->dev,
"%s(): unable to attach DVB-S/S2 frontend\n",
__func__);
goto frontend_detach;
}
- horus3a_conf.set_tuner_priv = &ndev->dma[num];
- if (!dvb_attach(horus3a_attach, fe0->dvb.frontend,
- &horus3a_conf, &ndev->i2c[num].adap)) {
- dev_dbg(&ndev->pci_dev->dev,
- "%s(): unable to attach DVB-S/S2 tuner frontend\n",
- __func__);
- goto frontend_detach;
+
+ if (ndev->rev == NETUP_HW_REV_1_3) {
+ horus3a_conf.set_tuner_priv = &ndev->dma[num];
+ if (!dvb_attach(horus3a_attach, fes[0]->dvb.frontend,
+ &horus3a_conf, &ndev->i2c[num].adap)) {
+ dev_dbg(&ndev->pci_dev->dev,
+ "%s(): unable to attach HORUS3A DVB-S/S2 tuner frontend\n",
+ __func__);
+ goto frontend_detach;
+ }
+ } else {
+ helene_conf.set_tuner_priv = &ndev->dma[num];
+ if (!dvb_attach(helene_attach_s, fes[0]->dvb.frontend,
+ &helene_conf, &ndev->i2c[num].adap)) {
+ dev_err(&ndev->pci_dev->dev,
+ "%s(): unable to attach HELENE DVB-S/S2 tuner frontend\n",
+ __func__);
+ goto frontend_detach;
+ }
}
- if (!dvb_attach(lnbh25_attach, fe0->dvb.frontend,
+
+ if (!dvb_attach(lnbh25_attach, fes[0]->dvb.frontend,
&lnbh25_conf, &ndev->i2c[num].adap)) {
dev_dbg(&ndev->pci_dev->dev,
"%s(): unable to attach SEC frontend\n", __func__);
goto frontend_detach;
}
+
/* DVB-T/T2 frontend */
- fe1->dvb.frontend = dvb_attach(cxd2841er_attach_t,
+ fes[1]->dvb.frontend = dvb_attach(cxd2841er_attach_t_c,
&demod_config, &ndev->i2c[num].adap);
- if (fe1->dvb.frontend == NULL) {
- dev_dbg(&ndev->pci_dev->dev,
- "%s(): unable to attach DVB-T frontend\n", __func__);
- goto frontend_detach;
- }
- fe1->dvb.frontend->id = 1;
- ascot2e_conf.set_tuner_priv = &ndev->dma[num];
- if (!dvb_attach(ascot2e_attach, fe1->dvb.frontend,
- &ascot2e_conf, &ndev->i2c[num].adap)) {
- dev_dbg(&ndev->pci_dev->dev,
- "%s(): unable to attach DVB-T tuner frontend\n",
- __func__);
- goto frontend_detach;
- }
- /* DVB-C/C2 frontend */
- fe2->dvb.frontend = dvb_attach(cxd2841er_attach_c,
- &demod_config, &ndev->i2c[num].adap);
- if (fe2->dvb.frontend == NULL) {
+ if (fes[1]->dvb.frontend == NULL) {
dev_dbg(&ndev->pci_dev->dev,
- "%s(): unable to attach DVB-C frontend\n", __func__);
+ "%s(): unable to attach Ter frontend\n", __func__);
goto frontend_detach;
}
- fe2->dvb.frontend->id = 2;
- if (!dvb_attach(ascot2e_attach, fe2->dvb.frontend,
- &ascot2e_conf, &ndev->i2c[num].adap)) {
- dev_dbg(&ndev->pci_dev->dev,
- "%s(): unable to attach DVB-T/C tuner frontend\n",
- __func__);
- goto frontend_detach;
+ fes[1]->dvb.frontend->id = 1;
+ if (ndev->rev == NETUP_HW_REV_1_3) {
+ ascot2e_conf.set_tuner_priv = &ndev->dma[num];
+ if (!dvb_attach(ascot2e_attach, fes[1]->dvb.frontend,
+ &ascot2e_conf, &ndev->i2c[num].adap)) {
+ dev_dbg(&ndev->pci_dev->dev,
+ "%s(): unable to attach Ter tuner frontend\n",
+ __func__);
+ goto frontend_detach;
+ }
+ } else {
+ helene_conf.set_tuner_priv = &ndev->dma[num];
+ if (!dvb_attach(helene_attach, fes[1]->dvb.frontend,
+ &helene_conf, &ndev->i2c[num].adap)) {
+ dev_err(&ndev->pci_dev->dev,
+ "%s(): unable to attach HELENE Ter tuner frontend\n",
+ __func__);
+ goto frontend_detach;
+ }
}
if (vb2_dvb_register_bus(&ndev->frontends[num],
@@ -730,7 +763,7 @@ static int netup_unidvb_request_mmio(struct pci_dev *pci_dev)
static int netup_unidvb_request_modules(struct device *dev)
{
static const char * const modules[] = {
- "lnbh25", "ascot2e", "horus3a", "cxd2841er", NULL
+ "lnbh25", "ascot2e", "horus3a", "cxd2841er", "helene", NULL
};
const char * const *curr_mod = modules;
int err;
@@ -774,6 +807,16 @@ static int netup_unidvb_initdev(struct pci_dev *pci_dev,
if (!ndev)
goto dev_alloc_err;
+ /* detect hardware revision */
+ if (pci_dev->device == NETUP_HW_REV_1_3)
+ ndev->rev = NETUP_HW_REV_1_3;
+ else
+ ndev->rev = NETUP_HW_REV_1_4;
+
+ dev_info(&pci_dev->dev,
+ "%s(): board (0x%x) hardware revision 0x%x\n",
+ __func__, pci_dev->device, ndev->rev);
+
ndev->old_fw = old_firmware;
ndev->wq = create_singlethread_workqueue(NETUP_UNIDVB_NAME);
if (!ndev->wq) {
@@ -932,7 +975,7 @@ wq_create_err:
kfree(ndev);
dev_alloc_err:
dev_err(&pci_dev->dev,
- "%s(): failed to initizalize device\n", __func__);
+ "%s(): failed to initialize device\n", __func__);
return -EIO;
}
@@ -972,7 +1015,8 @@ static void netup_unidvb_finidev(struct pci_dev *pci_dev)
static struct pci_device_id netup_unidvb_pci_tbl[] = {
- { PCI_DEVICE(0x1b55, 0x18f6) },
+ { PCI_DEVICE(0x1b55, 0x18f6) }, /* hw rev. 1.3 */
+ { PCI_DEVICE(0x1b55, 0x18f7) }, /* hw rev. 1.4 */
{ 0, }
};
MODULE_DEVICE_TABLE(pci, netup_unidvb_pci_tbl);