Commit e4c645f4 authored by Abylay Ospan's avatar Abylay Ospan Committed by Mauro Carvalho Chehab

[media] New hw revision 1.4 of NetUP Universal DVB card added

New hardware revision of NetUP Universal DVB card (rev 1.4):
* changed tuners (CXD2861ER and CXD2832AER) to CXD2858ER
* changed demodulator (CXD2841ER) to CXD2854ER

card now supports:
DVB-S/S2, DVB-T/T2, DVB-C/C2, ISDB-T

PCI id's assigned for new hardware revision is:
1b55:18f7
Signed-off-by: default avatarAbylay Ospan <aospan@netup.ru>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab@osg.samsung.com>
parent c5eb643f
...@@ -50,6 +50,15 @@ ...@@ -50,6 +50,15 @@
#define NETUP_UNIDVB_IRQ_CAM0 (1 << 11) #define NETUP_UNIDVB_IRQ_CAM0 (1 << 11)
#define NETUP_UNIDVB_IRQ_CAM1 (1 << 12) #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 { struct netup_dma {
u8 num; u8 num;
spinlock_t lock; spinlock_t lock;
...@@ -119,6 +128,7 @@ struct netup_unidvb_dev { ...@@ -119,6 +128,7 @@ struct netup_unidvb_dev {
struct netup_dma dma[2]; struct netup_dma dma[2];
struct netup_ci_state ci[2]; struct netup_ci_state ci[2];
struct netup_spi *spi; struct netup_spi *spi;
enum netup_hw_rev rev;
}; };
int netup_i2c_register(struct netup_unidvb_dev *ndev); int netup_i2c_register(struct netup_unidvb_dev *ndev);
......
...@@ -34,6 +34,7 @@ ...@@ -34,6 +34,7 @@
#include "cxd2841er.h" #include "cxd2841er.h"
#include "horus3a.h" #include "horus3a.h"
#include "ascot2e.h" #include "ascot2e.h"
#include "helene.h"
#include "lnbh25.h" #include "lnbh25.h"
static int spi_enable; static int spi_enable;
...@@ -120,7 +121,8 @@ static int netup_unidvb_tuner_ctrl(void *priv, int is_dvb_tc); ...@@ -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 void netup_unidvb_queue_cleanup(struct netup_dma *dma);
static struct cxd2841er_config demod_config = { static struct cxd2841er_config demod_config = {
.i2c_addr = 0xc8 .i2c_addr = 0xc8,
.xtal = SONY_XTAL_24000
}; };
static struct horus3a_config horus3a_conf = { static struct horus3a_config horus3a_conf = {
...@@ -134,6 +136,12 @@ static struct ascot2e_config ascot2e_conf = { ...@@ -134,6 +136,12 @@ static struct ascot2e_config ascot2e_conf = {
.set_tuner_callback = netup_unidvb_tuner_ctrl .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 = { static struct lnbh25_config lnbh25_conf = {
.i2c_address = 0x10, .i2c_address = 0x10,
.data2_config = LNBH25_TEN | LNBH25_EXTM .data2_config = LNBH25_TEN | LNBH25_EXTM
...@@ -152,6 +160,11 @@ static int netup_unidvb_tuner_ctrl(void *priv, int is_dvb_tc) ...@@ -152,6 +160,11 @@ static int netup_unidvb_tuner_ctrl(void *priv, int is_dvb_tc)
__func__, dma->num, is_dvb_tc); __func__, dma->num, is_dvb_tc);
reg = readb(ndev->bmmio0 + GPIO_REG_IO); reg = readb(ndev->bmmio0 + GPIO_REG_IO);
mask = (dma->num == 0) ? GPIO_RFA_CTL : GPIO_RFB_CTL; 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) if (!is_dvb_tc)
reg |= mask; reg |= mask;
else else
...@@ -372,7 +385,18 @@ static int netup_unidvb_queue_init(struct netup_dma *dma, ...@@ -372,7 +385,18 @@ static int netup_unidvb_queue_init(struct netup_dma *dma,
static int netup_unidvb_dvb_init(struct netup_unidvb_dev *ndev, static int netup_unidvb_dvb_init(struct netup_unidvb_dev *ndev,
int num) int num)
{ {
struct vb2_dvb_frontend *fe0, *fe1, *fe2; int fe_count = 0;
int i = 0;
struct vb2_dvb_frontend *fes[4];
u8 fe_name[32];
if (ndev->rev == NETUP_HW_REV_1_3) {
fe_count = 3;
demod_config.xtal = SONY_XTAL_20500;
} else {
fe_count = 4;
demod_config.xtal = SONY_XTAL_24000;
}
if (num < 0 || num > 1) { if (num < 0 || num > 1) {
dev_dbg(&ndev->pci_dev->dev, dev_dbg(&ndev->pci_dev->dev,
...@@ -381,84 +405,145 @@ static int netup_unidvb_dvb_init(struct netup_unidvb_dev *ndev, ...@@ -381,84 +405,145 @@ static int netup_unidvb_dvb_init(struct netup_unidvb_dev *ndev,
} }
mutex_init(&ndev->frontends[num].lock); mutex_init(&ndev->frontends[num].lock);
INIT_LIST_HEAD(&ndev->frontends[num].felist); INIT_LIST_HEAD(&ndev->frontends[num].felist);
if (vb2_dvb_alloc_frontend(&ndev->frontends[num], 1) == NULL ||
vb2_dvb_alloc_frontend( for (i = 0; i < fe_count; i++) {
&ndev->frontends[num], 2) == NULL || if (vb2_dvb_alloc_frontend(&ndev->frontends[num], i+1)
vb2_dvb_alloc_frontend( == NULL) {
&ndev->frontends[num], 3) == NULL) { dev_err(&ndev->pci_dev->dev,
dev_dbg(&ndev->pci_dev->dev, "%s(): unable to allocate vb2_dvb_frontend\n",
"%s(): unable to allocate vb2_dvb_frontend\n", __func__);
__func__); return -ENOMEM;
return -ENOMEM; }
} }
fe0 = vb2_dvb_get_frontend(&ndev->frontends[num], 1);
fe1 = vb2_dvb_get_frontend(&ndev->frontends[num], 2); for (i = 0; i < fe_count; i++) {
fe2 = vb2_dvb_get_frontend(&ndev->frontends[num], 3); fes[i] = vb2_dvb_get_frontend(&ndev->frontends[num], i+1);
if (fe0 == NULL || fe1 == NULL || fe2 == NULL) { if (fes[i] == NULL) {
dev_dbg(&ndev->pci_dev->dev, dev_err(&ndev->pci_dev->dev,
"%s(): frontends has not been allocated\n", __func__); "%s(): frontends has not been allocated\n",
return -EINVAL; __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); fes[0]->dvb.frontend = dvb_attach(cxd2841er_attach_s,
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,
&demod_config, &ndev->i2c[num].adap); &demod_config, &ndev->i2c[num].adap);
if (fe0->dvb.frontend == NULL) { if (fes[0]->dvb.frontend == NULL) {
dev_dbg(&ndev->pci_dev->dev, dev_dbg(&ndev->pci_dev->dev,
"%s(): unable to attach DVB-S/S2 frontend\n", "%s(): unable to attach DVB-S/S2 frontend\n",
__func__); __func__);
goto frontend_detach; goto frontend_detach;
} }
horus3a_conf.set_tuner_priv = &ndev->dma[num];
if (!dvb_attach(horus3a_attach, fe0->dvb.frontend, if (ndev->rev == NETUP_HW_REV_1_3) {
&horus3a_conf, &ndev->i2c[num].adap)) { horus3a_conf.set_tuner_priv = &ndev->dma[num];
dev_dbg(&ndev->pci_dev->dev, if (!dvb_attach(horus3a_attach, fes[0]->dvb.frontend,
"%s(): unable to attach DVB-S/S2 tuner frontend\n", &horus3a_conf, &ndev->i2c[num].adap)) {
__func__); dev_dbg(&ndev->pci_dev->dev,
goto frontend_detach; "%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)) { &lnbh25_conf, &ndev->i2c[num].adap)) {
dev_dbg(&ndev->pci_dev->dev, dev_dbg(&ndev->pci_dev->dev,
"%s(): unable to attach SEC frontend\n", __func__); "%s(): unable to attach SEC frontend\n", __func__);
goto frontend_detach; goto frontend_detach;
} }
/* DVB-T/T2 frontend */ /* DVB-T/T2 frontend */
fe1->dvb.frontend = dvb_attach(cxd2841er_attach_t, fes[1]->dvb.frontend = dvb_attach(cxd2841er_attach_t,
&demod_config, &ndev->i2c[num].adap); &demod_config, &ndev->i2c[num].adap);
if (fe1->dvb.frontend == NULL) { if (fes[1]->dvb.frontend == NULL) {
dev_dbg(&ndev->pci_dev->dev, dev_dbg(&ndev->pci_dev->dev,
"%s(): unable to attach DVB-T frontend\n", __func__); "%s(): unable to attach DVB-T frontend\n", __func__);
goto frontend_detach; goto frontend_detach;
} }
fe1->dvb.frontend->id = 1; fes[1]->dvb.frontend->id = 1;
ascot2e_conf.set_tuner_priv = &ndev->dma[num]; if (ndev->rev == NETUP_HW_REV_1_3) {
if (!dvb_attach(ascot2e_attach, fe1->dvb.frontend, ascot2e_conf.set_tuner_priv = &ndev->dma[num];
&ascot2e_conf, &ndev->i2c[num].adap)) { if (!dvb_attach(ascot2e_attach, fes[1]->dvb.frontend,
dev_dbg(&ndev->pci_dev->dev, &ascot2e_conf, &ndev->i2c[num].adap)) {
"%s(): unable to attach DVB-T tuner frontend\n", dev_dbg(&ndev->pci_dev->dev,
__func__); "%s(): unable to attach DVB-T tuner frontend\n",
goto frontend_detach; __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 DVB-T/T2 tuner frontend\n",
__func__);
goto frontend_detach;
}
} }
/* DVB-C/C2 frontend */ /* DVB-C/C2 frontend */
fe2->dvb.frontend = dvb_attach(cxd2841er_attach_c, fes[2]->dvb.frontend = dvb_attach(cxd2841er_attach_c,
&demod_config, &ndev->i2c[num].adap); &demod_config, &ndev->i2c[num].adap);
if (fe2->dvb.frontend == NULL) { if (fes[2]->dvb.frontend == NULL) {
dev_dbg(&ndev->pci_dev->dev, dev_dbg(&ndev->pci_dev->dev,
"%s(): unable to attach DVB-C frontend\n", __func__); "%s(): unable to attach DVB-C frontend\n", __func__);
goto frontend_detach; goto frontend_detach;
} }
fe2->dvb.frontend->id = 2; fes[2]->dvb.frontend->id = 2;
if (!dvb_attach(ascot2e_attach, fe2->dvb.frontend, if (ndev->rev == NETUP_HW_REV_1_3) {
&ascot2e_conf, &ndev->i2c[num].adap)) { if (!dvb_attach(ascot2e_attach, fes[2]->dvb.frontend,
dev_dbg(&ndev->pci_dev->dev, &ascot2e_conf, &ndev->i2c[num].adap)) {
"%s(): unable to attach DVB-T/C tuner frontend\n", dev_dbg(&ndev->pci_dev->dev,
__func__); "%s(): unable to attach DVB-T/C tuner frontend\n",
goto frontend_detach; __func__);
goto frontend_detach;
}
} else {
helene_conf.set_tuner_priv = &ndev->dma[num];
if (!dvb_attach(helene_attach, fes[2]->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 (ndev->rev == NETUP_HW_REV_1_4) {
/* ISDB-T frontend */
fes[3]->dvb.frontend = dvb_attach(cxd2841er_attach_i,
&demod_config, &ndev->i2c[num].adap);
if (fes[3]->dvb.frontend == NULL) {
dev_dbg(&ndev->pci_dev->dev,
"%s(): unable to attach ISDB-T frontend\n",
__func__);
goto frontend_detach;
}
fes[3]->dvb.frontend->id = 3;
helene_conf.set_tuner_priv = &ndev->dma[num];
if (!dvb_attach(helene_attach, fes[3]->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], if (vb2_dvb_register_bus(&ndev->frontends[num],
...@@ -730,7 +815,7 @@ static int netup_unidvb_request_mmio(struct pci_dev *pci_dev) ...@@ -730,7 +815,7 @@ static int netup_unidvb_request_mmio(struct pci_dev *pci_dev)
static int netup_unidvb_request_modules(struct device *dev) static int netup_unidvb_request_modules(struct device *dev)
{ {
static const char * const modules[] = { static const char * const modules[] = {
"lnbh25", "ascot2e", "horus3a", "cxd2841er", NULL "lnbh25", "ascot2e", "horus3a", "cxd2841er", "helene", NULL
}; };
const char * const *curr_mod = modules; const char * const *curr_mod = modules;
int err; int err;
...@@ -774,6 +859,16 @@ static int netup_unidvb_initdev(struct pci_dev *pci_dev, ...@@ -774,6 +859,16 @@ static int netup_unidvb_initdev(struct pci_dev *pci_dev,
if (!ndev) if (!ndev)
goto dev_alloc_err; 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->old_fw = old_firmware;
ndev->wq = create_singlethread_workqueue(NETUP_UNIDVB_NAME); ndev->wq = create_singlethread_workqueue(NETUP_UNIDVB_NAME);
if (!ndev->wq) { if (!ndev->wq) {
...@@ -972,7 +1067,8 @@ static void netup_unidvb_finidev(struct pci_dev *pci_dev) ...@@ -972,7 +1067,8 @@ static void netup_unidvb_finidev(struct pci_dev *pci_dev)
static struct pci_device_id netup_unidvb_pci_tbl[] = { 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, } { 0, }
}; };
MODULE_DEVICE_TABLE(pci, netup_unidvb_pci_tbl); MODULE_DEVICE_TABLE(pci, netup_unidvb_pci_tbl);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment