mirror of
https://github.com/tbsdtv/linux_media.git
synced 2025-07-23 04:33:26 +02:00
2925 lines
77 KiB
C
2925 lines
77 KiB
C
#include <linux/module.h>
|
|
#include <linux/moduleparam.h>
|
|
#include <linux/kernel.h>
|
|
#include <linux/pci.h>
|
|
#include <linux/mutex.h>
|
|
|
|
#include <asm/io.h>
|
|
#include <asm/pgtable.h>
|
|
#include <asm/page.h>
|
|
#include <linux/kmod.h>
|
|
#include <linux/vmalloc.h>
|
|
#include <linux/init.h>
|
|
#include <linux/device.h>
|
|
|
|
#include <linux/signal.h>
|
|
#include <linux/sched.h>
|
|
#include <linux/interrupt.h>
|
|
|
|
#include <linux/i2c.h>
|
|
|
|
#include "saa716x_mod.h"
|
|
|
|
#include "saa716x_gpio_reg.h"
|
|
#include "saa716x_greg_reg.h"
|
|
#include "saa716x_msi_reg.h"
|
|
|
|
#include "saa716x_adap.h"
|
|
#include "saa716x_i2c.h"
|
|
#include "saa716x_msi.h"
|
|
#include "saa716x_budget.h"
|
|
#include "saa716x_gpio.h"
|
|
#include "saa716x_rom.h"
|
|
#include "saa716x_spi.h"
|
|
#include "saa716x_priv.h"
|
|
|
|
#include "mb86a16.h"
|
|
#include "stv6110x.h"
|
|
#include "stv090x.h"
|
|
#include "tas2101.h"
|
|
#include "av201x.h"
|
|
#include "cx24117.h"
|
|
#include "isl6422.h"
|
|
#include "stb6100.h"
|
|
#include "stb6100_cfg.h"
|
|
|
|
#include "tda18212.h"
|
|
#include "cxd2820r.h"
|
|
|
|
#include "si2168.h"
|
|
#include "si2157.h"
|
|
|
|
#include "stv6120.h"
|
|
#include "stv091x.h"
|
|
#include "tbsci-i2c.h"
|
|
#include "tbs-ci.h"
|
|
|
|
unsigned int verbose;
|
|
module_param(verbose, int, 0644);
|
|
MODULE_PARM_DESC(verbose, "verbose startup messages, default is 1 (yes)");
|
|
|
|
unsigned int int_type;
|
|
module_param(int_type, int, 0644);
|
|
MODULE_PARM_DESC(int_type, "force Interrupt Handler type: 0=INT-A, 1=MSI, 2=MSI-X. default INT-A mode");
|
|
|
|
#define DRIVER_NAME "SAA716x Budget"
|
|
|
|
static int saa716x_budget_pci_probe(struct pci_dev *pdev, const struct pci_device_id *pci_id)
|
|
{
|
|
struct saa716x_dev *saa716x;
|
|
int err = 0;
|
|
|
|
saa716x = kzalloc(sizeof (struct saa716x_dev), GFP_KERNEL);
|
|
if (saa716x == NULL) {
|
|
printk(KERN_ERR "saa716x_budget_pci_probe ERROR: out of memory\n");
|
|
err = -ENOMEM;
|
|
goto fail0;
|
|
}
|
|
|
|
saa716x->verbose = verbose;
|
|
saa716x->int_type = int_type;
|
|
saa716x->pdev = pdev;
|
|
saa716x->module = THIS_MODULE;
|
|
saa716x->config = (struct saa716x_config *) pci_id->driver_data;
|
|
|
|
err = saa716x_pci_init(saa716x);
|
|
if (err) {
|
|
dprintk(SAA716x_ERROR, 1, "SAA716x PCI Initialization failed");
|
|
goto fail1;
|
|
}
|
|
|
|
err = saa716x_cgu_init(saa716x);
|
|
if (err) {
|
|
dprintk(SAA716x_ERROR, 1, "SAA716x CGU Init failed");
|
|
goto fail1;
|
|
}
|
|
|
|
err = saa716x_core_boot(saa716x);
|
|
if (err) {
|
|
dprintk(SAA716x_ERROR, 1, "SAA716x Core Boot failed");
|
|
goto fail2;
|
|
}
|
|
dprintk(SAA716x_DEBUG, 1, "SAA716x Core Boot Success");
|
|
|
|
err = saa716x_msi_init(saa716x);
|
|
if (err) {
|
|
dprintk(SAA716x_ERROR, 1, "SAA716x MSI Init failed");
|
|
goto fail2;
|
|
}
|
|
|
|
err = saa716x_jetpack_init(saa716x);
|
|
if (err) {
|
|
dprintk(SAA716x_ERROR, 1, "SAA716x Jetpack core initialization failed");
|
|
goto fail2;
|
|
}
|
|
|
|
err = saa716x_i2c_init(saa716x);
|
|
if (err) {
|
|
dprintk(SAA716x_ERROR, 1, "SAA716x I2C Initialization failed");
|
|
goto fail2;
|
|
}
|
|
|
|
saa716x_gpio_init(saa716x);
|
|
#if 0
|
|
err = saa716x_dump_eeprom(saa716x);
|
|
if (err) {
|
|
dprintk(SAA716x_ERROR, 1, "SAA716x EEPROM dump failed");
|
|
}
|
|
|
|
err = saa716x_eeprom_data(saa716x);
|
|
if (err) {
|
|
dprintk(SAA716x_ERROR, 1, "SAA716x EEPROM read failed");
|
|
}
|
|
#endif
|
|
|
|
/* set default port mapping */
|
|
SAA716x_EPWR(GREG, GREG_VI_CTRL, 0x2C688F0A);
|
|
/* enable FGPI3, FGPI2, FGPI1 and FGPI0 for TS input from Port 2 and 6 */
|
|
SAA716x_EPWR(GREG, GREG_FGPI_CTRL, 0x322);
|
|
|
|
err = saa716x_dvb_init(saa716x);
|
|
if (err) {
|
|
dprintk(SAA716x_ERROR, 1, "SAA716x DVB initialization failed");
|
|
goto fail3;
|
|
}
|
|
|
|
return 0;
|
|
|
|
fail3:
|
|
saa716x_dvb_exit(saa716x);
|
|
saa716x_i2c_exit(saa716x);
|
|
fail2:
|
|
saa716x_pci_exit(saa716x);
|
|
fail1:
|
|
kfree(saa716x);
|
|
fail0:
|
|
return err;
|
|
}
|
|
|
|
static void saa716x_budget_pci_remove(struct pci_dev *pdev)
|
|
{
|
|
struct saa716x_dev *saa716x = pci_get_drvdata(pdev);
|
|
struct saa716x_adapter *saa716x_adap = saa716x->saa716x_adap;
|
|
int i;
|
|
|
|
for(i = 0;i<saa716x->config->adapters; i++)
|
|
{
|
|
if(saa716x_adap->tbsci){
|
|
tbsci_release(saa716x_adap);
|
|
tbsci_i2c_remove(saa716x_adap);
|
|
}
|
|
|
|
saa716x_adap++;
|
|
}
|
|
|
|
saa716x_dvb_exit(saa716x);
|
|
saa716x_i2c_exit(saa716x);
|
|
saa716x_pci_exit(saa716x);
|
|
kfree(saa716x);
|
|
}
|
|
|
|
static irqreturn_t saa716x_budget_pci_irq(int irq, void *dev_id)
|
|
{
|
|
struct saa716x_dev *saa716x = (struct saa716x_dev *) dev_id;
|
|
|
|
u32 stat_h, stat_l, mask_h, mask_l;
|
|
|
|
if (unlikely(saa716x == NULL)) {
|
|
printk("%s: saa716x=NULL", __func__);
|
|
return IRQ_NONE;
|
|
}
|
|
|
|
stat_l = SAA716x_EPRD(MSI, MSI_INT_STATUS_L);
|
|
stat_h = SAA716x_EPRD(MSI, MSI_INT_STATUS_H);
|
|
mask_l = SAA716x_EPRD(MSI, MSI_INT_ENA_L);
|
|
mask_h = SAA716x_EPRD(MSI, MSI_INT_ENA_H);
|
|
|
|
dprintk(SAA716x_DEBUG, 1, "MSI STAT L=<%02x> H=<%02x>, CTL L=<%02x> H=<%02x>",
|
|
stat_l, stat_h, mask_l, mask_h);
|
|
|
|
if (!((stat_l & mask_l) || (stat_h & mask_h)))
|
|
return IRQ_NONE;
|
|
|
|
if (stat_l)
|
|
SAA716x_EPWR(MSI, MSI_INT_STATUS_CLR_L, stat_l);
|
|
|
|
if (stat_h)
|
|
SAA716x_EPWR(MSI, MSI_INT_STATUS_CLR_H, stat_h);
|
|
|
|
saa716x_msi_event(saa716x, stat_l, stat_h);
|
|
#if 0
|
|
dprintk(SAA716x_DEBUG, 1, "VI STAT 0=<%02x> 1=<%02x>, CTL 1=<%02x> 2=<%02x>",
|
|
SAA716x_EPRD(VI0, INT_STATUS),
|
|
SAA716x_EPRD(VI1, INT_STATUS),
|
|
SAA716x_EPRD(VI0, INT_ENABLE),
|
|
SAA716x_EPRD(VI1, INT_ENABLE));
|
|
|
|
dprintk(SAA716x_DEBUG, 1, "FGPI STAT 0=<%02x> 1=<%02x>, CTL 1=<%02x> 2=<%02x>",
|
|
SAA716x_EPRD(FGPI0, INT_STATUS),
|
|
SAA716x_EPRD(FGPI1, INT_STATUS),
|
|
SAA716x_EPRD(FGPI0, INT_ENABLE),
|
|
SAA716x_EPRD(FGPI0, INT_ENABLE));
|
|
|
|
dprintk(SAA716x_DEBUG, 1, "FGPI STAT 2=<%02x> 3=<%02x>, CTL 2=<%02x> 3=<%02x>",
|
|
SAA716x_EPRD(FGPI2, INT_STATUS),
|
|
SAA716x_EPRD(FGPI3, INT_STATUS),
|
|
SAA716x_EPRD(FGPI2, INT_ENABLE),
|
|
SAA716x_EPRD(FGPI3, INT_ENABLE));
|
|
|
|
dprintk(SAA716x_DEBUG, 1, "AI STAT 0=<%02x> 1=<%02x>, CTL 0=<%02x> 1=<%02x>",
|
|
SAA716x_EPRD(AI0, AI_STATUS),
|
|
SAA716x_EPRD(AI1, AI_STATUS),
|
|
SAA716x_EPRD(AI0, AI_CTL),
|
|
SAA716x_EPRD(AI1, AI_CTL));
|
|
|
|
dprintk(SAA716x_DEBUG, 1, "I2C STAT 0=<%02x> 1=<%02x>, CTL 0=<%02x> 1=<%02x>",
|
|
SAA716x_EPRD(I2C_A, INT_STATUS),
|
|
SAA716x_EPRD(I2C_B, INT_STATUS),
|
|
SAA716x_EPRD(I2C_A, INT_ENABLE),
|
|
SAA716x_EPRD(I2C_B, INT_ENABLE));
|
|
|
|
dprintk(SAA716x_DEBUG, 1, "DCS STAT=<%02x>, CTL=<%02x>",
|
|
SAA716x_EPRD(DCS, DCSC_INT_STATUS),
|
|
SAA716x_EPRD(DCS, DCSC_INT_ENABLE));
|
|
#endif
|
|
|
|
if (stat_l) {
|
|
if (stat_l & MSI_INT_TAGACK_FGPI_0) {
|
|
tasklet_schedule(&saa716x->fgpi[0].tasklet);
|
|
}
|
|
if (stat_l & MSI_INT_TAGACK_FGPI_1) {
|
|
tasklet_schedule(&saa716x->fgpi[1].tasklet);
|
|
}
|
|
if (stat_l & MSI_INT_TAGACK_FGPI_2) {
|
|
tasklet_schedule(&saa716x->fgpi[2].tasklet);
|
|
}
|
|
if (stat_l & MSI_INT_TAGACK_FGPI_3) {
|
|
tasklet_schedule(&saa716x->fgpi[3].tasklet);
|
|
}
|
|
}
|
|
|
|
return IRQ_HANDLED;
|
|
}
|
|
|
|
static void demux_worker(unsigned long data)
|
|
{
|
|
struct saa716x_fgpi_stream_port *fgpi_entry = (struct saa716x_fgpi_stream_port *)data;
|
|
struct saa716x_dev *saa716x = fgpi_entry->saa716x;
|
|
struct dvb_demux *demux;
|
|
u32 fgpi_index;
|
|
u32 i;
|
|
u32 write_index;
|
|
|
|
fgpi_index = fgpi_entry->dma_channel - 6;
|
|
demux = NULL;
|
|
for (i = 0; i < saa716x->config->adapters; i++) {
|
|
if (saa716x->config->adap_config[i].ts_port == fgpi_index) {
|
|
demux = &saa716x->saa716x_adap[i].demux;
|
|
break;
|
|
}
|
|
}
|
|
if (demux == NULL) {
|
|
printk(KERN_ERR "%s: unexpected channel %u\n",
|
|
__func__, fgpi_entry->dma_channel);
|
|
return;
|
|
}
|
|
|
|
write_index = saa716x_fgpi_get_write_index(saa716x, fgpi_index);
|
|
if (write_index < 0)
|
|
return;
|
|
|
|
dprintk(SAA716x_DEBUG, 1, "dma buffer = %d", write_index);
|
|
|
|
if (write_index == fgpi_entry->read_index) {
|
|
printk(KERN_DEBUG "%s: called but nothing to do\n", __func__);
|
|
return;
|
|
}
|
|
|
|
do {
|
|
u8 *data = (u8 *)fgpi_entry->dma_buf[fgpi_entry->read_index].mem_virt;
|
|
|
|
dma_sync_sg_for_cpu(&saa716x->pdev->dev,
|
|
fgpi_entry->dma_buf[fgpi_entry->read_index].sg_list,
|
|
fgpi_entry->dma_buf[fgpi_entry->read_index].list_len,
|
|
DMA_FROM_DEVICE);
|
|
|
|
dvb_dmx_swfilter(demux, data, 348 * 188);
|
|
|
|
fgpi_entry->read_index = (fgpi_entry->read_index + 1) & 7;
|
|
} while (write_index != fgpi_entry->read_index);
|
|
}
|
|
|
|
|
|
#define SAA716x_MODEL_TWINHAN_VP3071 "Twinhan/Azurewave VP-3071"
|
|
#define SAA716x_DEV_TWINHAN_VP3071 "2x DVB-T"
|
|
|
|
static int saa716x_vp3071_frontend_attach(struct saa716x_adapter *adapter, int count)
|
|
{
|
|
struct saa716x_dev *saa716x = adapter->saa716x;
|
|
dprintk(SAA716x_DEBUG, 1, "Adapter (%d) SAA716x frontend Init", count);
|
|
dprintk(SAA716x_DEBUG, 1, "Adapter (%d) Device ID=%02x", count, saa716x->pdev->subsystem_device);
|
|
|
|
return -ENODEV;
|
|
}
|
|
|
|
static struct saa716x_config saa716x_vp3071_config = {
|
|
.model_name = SAA716x_MODEL_TWINHAN_VP3071,
|
|
.dev_type = SAA716x_DEV_TWINHAN_VP3071,
|
|
.boot_mode = SAA716x_EXT_BOOT,
|
|
.adapters = 2,
|
|
.frontend_attach = saa716x_vp3071_frontend_attach,
|
|
.irq_handler = saa716x_budget_pci_irq,
|
|
.i2c_rate = SAA716x_I2C_RATE_100,
|
|
};
|
|
|
|
|
|
#define SAA716x_MODEL_TWINHAN_VP1028 "Twinhan/Azurewave VP-1028"
|
|
#define SAA716x_DEV_TWINHAN_VP1028 "DVB-S"
|
|
|
|
static int vp1028_dvbs_set_voltage(struct dvb_frontend *fe, enum fe_sec_voltage voltage)
|
|
{
|
|
struct saa716x_dev *saa716x = fe->dvb->priv;
|
|
|
|
switch (voltage) {
|
|
case SEC_VOLTAGE_13:
|
|
dprintk(SAA716x_ERROR, 1, "Polarization=[13V]");
|
|
break;
|
|
case SEC_VOLTAGE_18:
|
|
dprintk(SAA716x_ERROR, 1, "Polarization=[18V]");
|
|
break;
|
|
case SEC_VOLTAGE_OFF:
|
|
dprintk(SAA716x_ERROR, 1, "Frontend (dummy) POWERDOWN");
|
|
break;
|
|
default:
|
|
dprintk(SAA716x_ERROR, 1, "Invalid = (%d)", (u32 ) voltage);
|
|
return -EINVAL;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
struct mb86a16_config vp1028_mb86a16_config = {
|
|
.demod_address = 0x08,
|
|
.set_voltage = vp1028_dvbs_set_voltage,
|
|
};
|
|
|
|
static int saa716x_vp1028_frontend_attach(struct saa716x_adapter *adapter, int count)
|
|
{
|
|
struct saa716x_dev *saa716x = adapter->saa716x;
|
|
struct saa716x_i2c *i2c = &saa716x->i2c[1];
|
|
|
|
if (count == 0) {
|
|
|
|
mutex_lock(&saa716x->adap_lock);
|
|
|
|
dprintk(SAA716x_DEBUG, 1, "Adapter (%d) Power ON", count);
|
|
saa716x_gpio_set_output(saa716x, 10);
|
|
msleep(1);
|
|
|
|
/* VP-1028 has inverted power supply control */
|
|
saa716x_gpio_write(saa716x, 10, 1); /* set to standby */
|
|
saa716x_gpio_write(saa716x, 10, 0); /* switch it on */
|
|
msleep(100);
|
|
|
|
dprintk(SAA716x_DEBUG, 1, "Adapter (%d) Reset", count);
|
|
saa716x_gpio_set_output(saa716x, 12);
|
|
msleep(1);
|
|
|
|
/* reset demodulator (Active LOW) */
|
|
saa716x_gpio_write(saa716x, 12, 1);
|
|
msleep(100);
|
|
saa716x_gpio_write(saa716x, 12, 0);
|
|
msleep(100);
|
|
saa716x_gpio_write(saa716x, 12, 1);
|
|
msleep(100);
|
|
|
|
mutex_unlock(&saa716x->adap_lock);
|
|
|
|
dprintk(SAA716x_ERROR, 1, "Probing for MB86A16 (DVB-S/DSS)");
|
|
adapter->fe = dvb_attach(mb86a16_attach,
|
|
&vp1028_mb86a16_config,
|
|
&i2c->i2c_adapter);
|
|
if (adapter->fe) {
|
|
dprintk(SAA716x_ERROR, 1, "found MB86A16 DVB-S/DSS frontend @0x%02x",
|
|
vp1028_mb86a16_config.demod_address);
|
|
|
|
} else {
|
|
goto exit;
|
|
}
|
|
dprintk(SAA716x_ERROR, 1, "Done!");
|
|
}
|
|
|
|
return 0;
|
|
exit:
|
|
dprintk(SAA716x_ERROR, 1, "Frontend attach failed");
|
|
return -ENODEV;
|
|
}
|
|
|
|
static struct saa716x_config saa716x_vp1028_config = {
|
|
.model_name = SAA716x_MODEL_TWINHAN_VP1028,
|
|
.dev_type = SAA716x_DEV_TWINHAN_VP1028,
|
|
.boot_mode = SAA716x_EXT_BOOT,
|
|
.adapters = 1,
|
|
.frontend_attach = saa716x_vp1028_frontend_attach,
|
|
.irq_handler = saa716x_budget_pci_irq,
|
|
.i2c_rate = SAA716x_I2C_RATE_100,
|
|
};
|
|
|
|
|
|
#define SAA716x_MODEL_TWINHAN_VP6002 "Twinhan/Azurewave VP-6002"
|
|
#define SAA716x_DEV_TWINHAN_VP6002 "DVB-S"
|
|
|
|
static int saa716x_vp6002_frontend_attach(struct saa716x_adapter *adapter, int count)
|
|
{
|
|
struct saa716x_dev *saa716x = adapter->saa716x;
|
|
|
|
dprintk(SAA716x_DEBUG, 1, "Adapter (%d) SAA716x frontend Init", count);
|
|
dprintk(SAA716x_DEBUG, 1, "Adapter (%d) Device ID=%02x", count, saa716x->pdev->subsystem_device);
|
|
|
|
return -ENODEV;
|
|
}
|
|
|
|
static struct saa716x_config saa716x_vp6002_config = {
|
|
.model_name = SAA716x_MODEL_TWINHAN_VP6002,
|
|
.dev_type = SAA716x_DEV_TWINHAN_VP6002,
|
|
.boot_mode = SAA716x_EXT_BOOT,
|
|
.adapters = 1,
|
|
.frontend_attach = saa716x_vp6002_frontend_attach,
|
|
.irq_handler = saa716x_budget_pci_irq,
|
|
.i2c_rate = SAA716x_I2C_RATE_100,
|
|
};
|
|
|
|
|
|
#define SAA716x_MODEL_KNC1_DUALS2 "KNC One Dual S2"
|
|
#define SAA716x_DEV_KNC1_DUALS2 "1xDVB-S + 1xDVB-S/S2"
|
|
|
|
static int saa716x_knc1_duals2_frontend_attach(struct saa716x_adapter *adapter, int count)
|
|
{
|
|
struct saa716x_dev *saa716x = adapter->saa716x;
|
|
|
|
dprintk(SAA716x_DEBUG, 1, "Adapter (%d) SAA716x frontend Init", count);
|
|
dprintk(SAA716x_DEBUG, 1, "Adapter (%d) Device ID=%02x", count, saa716x->pdev->subsystem_device);
|
|
|
|
return -ENODEV;
|
|
}
|
|
|
|
static struct saa716x_config saa716x_knc1_duals2_config = {
|
|
.model_name = SAA716x_MODEL_KNC1_DUALS2,
|
|
.dev_type = SAA716x_DEV_KNC1_DUALS2,
|
|
.boot_mode = SAA716x_EXT_BOOT,
|
|
.adapters = 2,
|
|
.frontend_attach = saa716x_knc1_duals2_frontend_attach,
|
|
.irq_handler = saa716x_budget_pci_irq,
|
|
.i2c_rate = SAA716x_I2C_RATE_100,
|
|
};
|
|
|
|
|
|
#define SAA716x_MODEL_SKYSTAR2_EXPRESS_HD "SkyStar 2 eXpress HD"
|
|
#define SAA716x_DEV_SKYSTAR2_EXPRESS_HD "DVB-S/S2"
|
|
|
|
static struct stv090x_config skystar2_stv090x_config = {
|
|
.device = STV0903,
|
|
.demod_mode = STV090x_SINGLE,
|
|
.clk_mode = STV090x_CLK_EXT,
|
|
|
|
.xtal = 8000000,
|
|
.address = 0x68,
|
|
|
|
.ts1_mode = STV090x_TSMODE_DVBCI,
|
|
.ts2_mode = STV090x_TSMODE_SERIAL_CONTINUOUS,
|
|
|
|
.repeater_level = STV090x_RPTLEVEL_16,
|
|
|
|
.tuner_init = NULL,
|
|
.tuner_sleep = NULL,
|
|
.tuner_set_mode = NULL,
|
|
.tuner_set_frequency = NULL,
|
|
.tuner_get_frequency = NULL,
|
|
.tuner_set_bandwidth = NULL,
|
|
.tuner_get_bandwidth = NULL,
|
|
.tuner_set_bbgain = NULL,
|
|
.tuner_get_bbgain = NULL,
|
|
.tuner_set_refclk = NULL,
|
|
.tuner_get_status = NULL,
|
|
};
|
|
|
|
static int skystar2_set_voltage(struct dvb_frontend *fe,
|
|
enum fe_sec_voltage voltage)
|
|
{
|
|
int err;
|
|
u8 en = 0;
|
|
u8 sel = 0;
|
|
|
|
switch (voltage) {
|
|
case SEC_VOLTAGE_OFF:
|
|
en = 0;
|
|
break;
|
|
|
|
case SEC_VOLTAGE_13:
|
|
en = 1;
|
|
sel = 0;
|
|
break;
|
|
|
|
case SEC_VOLTAGE_18:
|
|
en = 1;
|
|
sel = 1;
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
err = skystar2_stv090x_config.set_gpio(fe, 2, 0, en, 0);
|
|
if (err < 0)
|
|
goto exit;
|
|
err = skystar2_stv090x_config.set_gpio(fe, 3, 0, sel, 0);
|
|
if (err < 0)
|
|
goto exit;
|
|
|
|
return 0;
|
|
exit:
|
|
return err;
|
|
}
|
|
|
|
static int skystar2_voltage_boost(struct dvb_frontend *fe, long arg)
|
|
{
|
|
int err;
|
|
u8 value;
|
|
|
|
if (arg)
|
|
value = 1;
|
|
else
|
|
value = 0;
|
|
|
|
err = skystar2_stv090x_config.set_gpio(fe, 4, 0, value, 0);
|
|
if (err < 0)
|
|
goto exit;
|
|
|
|
return 0;
|
|
exit:
|
|
return err;
|
|
}
|
|
|
|
static struct stv6110x_config skystar2_stv6110x_config = {
|
|
.addr = 0x60,
|
|
.refclk = 16000000,
|
|
.clk_div = 2,
|
|
};
|
|
|
|
static int skystar2_express_hd_frontend_attach(struct saa716x_adapter *adapter,
|
|
int count)
|
|
{
|
|
struct saa716x_dev *saa716x = adapter->saa716x;
|
|
struct saa716x_i2c *i2c = &saa716x->i2c[SAA716x_I2C_BUS_B];
|
|
struct stv6110x_devctl *ctl;
|
|
|
|
if (count < saa716x->config->adapters) {
|
|
dprintk(SAA716x_DEBUG, 1, "Adapter (%d) SAA716x frontend Init",
|
|
count);
|
|
dprintk(SAA716x_DEBUG, 1, "Adapter (%d) Device ID=%02x", count,
|
|
saa716x->pdev->subsystem_device);
|
|
|
|
saa716x_gpio_set_output(saa716x, 26);
|
|
|
|
/* Reset the demodulator */
|
|
saa716x_gpio_write(saa716x, 26, 1);
|
|
saa716x_gpio_write(saa716x, 26, 0);
|
|
msleep(10);
|
|
saa716x_gpio_write(saa716x, 26, 1);
|
|
msleep(10);
|
|
|
|
adapter->fe = dvb_attach(stv090x_attach,
|
|
&skystar2_stv090x_config,
|
|
&i2c->i2c_adapter,
|
|
STV090x_DEMODULATOR_0);
|
|
|
|
if (adapter->fe) {
|
|
dprintk(SAA716x_NOTICE, 1, "found STV0903 @0x%02x",
|
|
skystar2_stv090x_config.address);
|
|
} else {
|
|
goto exit;
|
|
}
|
|
|
|
adapter->fe->ops.set_voltage = skystar2_set_voltage;
|
|
adapter->fe->ops.enable_high_lnb_voltage = skystar2_voltage_boost;
|
|
|
|
ctl = dvb_attach(stv6110x_attach,
|
|
adapter->fe,
|
|
&skystar2_stv6110x_config,
|
|
&i2c->i2c_adapter);
|
|
|
|
if (ctl) {
|
|
dprintk(SAA716x_NOTICE, 1, "found STV6110(A) @0x%02x",
|
|
skystar2_stv6110x_config.addr);
|
|
|
|
skystar2_stv090x_config.tuner_init = ctl->tuner_init;
|
|
skystar2_stv090x_config.tuner_sleep = ctl->tuner_sleep;
|
|
skystar2_stv090x_config.tuner_set_mode = ctl->tuner_set_mode;
|
|
skystar2_stv090x_config.tuner_set_frequency = ctl->tuner_set_frequency;
|
|
skystar2_stv090x_config.tuner_get_frequency = ctl->tuner_get_frequency;
|
|
skystar2_stv090x_config.tuner_set_bandwidth = ctl->tuner_set_bandwidth;
|
|
skystar2_stv090x_config.tuner_get_bandwidth = ctl->tuner_get_bandwidth;
|
|
skystar2_stv090x_config.tuner_set_bbgain = ctl->tuner_set_bbgain;
|
|
skystar2_stv090x_config.tuner_get_bbgain = ctl->tuner_get_bbgain;
|
|
skystar2_stv090x_config.tuner_set_refclk = ctl->tuner_set_refclk;
|
|
skystar2_stv090x_config.tuner_get_status = ctl->tuner_get_status;
|
|
|
|
/* call the init function once to initialize
|
|
tuner's clock output divider and demod's
|
|
master clock */
|
|
if (adapter->fe->ops.init)
|
|
adapter->fe->ops.init(adapter->fe);
|
|
} else {
|
|
goto exit;
|
|
}
|
|
|
|
dprintk(SAA716x_ERROR, 1, "Done!");
|
|
return 0;
|
|
}
|
|
exit:
|
|
dprintk(SAA716x_ERROR, 1, "Frontend attach failed");
|
|
return -ENODEV;
|
|
}
|
|
|
|
static struct saa716x_config skystar2_express_hd_config = {
|
|
.model_name = SAA716x_MODEL_SKYSTAR2_EXPRESS_HD,
|
|
.dev_type = SAA716x_DEV_SKYSTAR2_EXPRESS_HD,
|
|
.boot_mode = SAA716x_EXT_BOOT,
|
|
.adapters = 1,
|
|
.frontend_attach = skystar2_express_hd_frontend_attach,
|
|
.irq_handler = saa716x_budget_pci_irq,
|
|
.i2c_rate = SAA716x_I2C_RATE_100,
|
|
.adap_config = {
|
|
{
|
|
/* Adapter 0 */
|
|
.ts_port = 1, /* using FGPI 1 */
|
|
.worker = demux_worker
|
|
}
|
|
}
|
|
};
|
|
|
|
|
|
#define SAA716x_MODEL_TBS6284 "TurboSight TBS 6284 "
|
|
#define SAA716x_DEV_TBS6284 "DVB-T/T2/C"
|
|
|
|
static struct cxd2820r_config cxd2820r_config[] = {
|
|
{
|
|
.i2c_address = 0x6c, /* (0xd8 >> 1) */
|
|
.ts_mode = 0x38,
|
|
},
|
|
{
|
|
.i2c_address = 0x6d, /* (0xda >> 1) */
|
|
.ts_mode = 0x38,
|
|
}
|
|
};
|
|
|
|
static struct tda18212_config tda18212_config[] = {
|
|
{
|
|
/* .i2c_address = 0x60 (0xc0 >> 1) */
|
|
.if_dvbt_6 = 3550,
|
|
.if_dvbt_7 = 3700,
|
|
.if_dvbt_8 = 4150,
|
|
.if_dvbt2_6 = 3250,
|
|
.if_dvbt2_7 = 4000,
|
|
.if_dvbt2_8 = 4000,
|
|
.if_dvbc = 5000,
|
|
.loop_through = 1,
|
|
.xtout = 1
|
|
},
|
|
{
|
|
/* .i2c_address = 0x63 (0xc6 >> 1) */
|
|
.if_dvbt_6 = 3550,
|
|
.if_dvbt_7 = 3700,
|
|
.if_dvbt_8 = 4150,
|
|
.if_dvbt2_6 = 3250,
|
|
.if_dvbt2_7 = 4000,
|
|
.if_dvbt2_8 = 4000,
|
|
.if_dvbc = 5000,
|
|
.loop_through = 0,
|
|
.xtout = 0
|
|
},
|
|
};
|
|
|
|
static int saa716x_tbs_read_mac(struct saa716x_dev *saa716x, int count, u8 *mac)
|
|
{
|
|
return saa716x_read_rombytes(saa716x, 0x2A0 + count * 16, 6, mac);
|
|
}
|
|
|
|
static int saa716x_tbs6284_frontend_attach(struct saa716x_adapter *adapter, int count)
|
|
{
|
|
struct saa716x_dev *dev = adapter->saa716x;
|
|
struct saa716x_i2c *i2c = &dev->i2c[1 - (count >> 1)];
|
|
struct i2c_adapter *i2cadapter = &i2c->i2c_adapter;
|
|
u8 mac[6];
|
|
|
|
struct i2c_client *client;
|
|
|
|
struct i2c_board_info board_info = {
|
|
.type = "tda18212",
|
|
.platform_data = &tda18212_config[count & 1],
|
|
};
|
|
|
|
|
|
if (count > 3)
|
|
goto err;
|
|
|
|
/* reset */
|
|
if (count == 0) {
|
|
saa716x_gpio_set_output(dev, 22);
|
|
saa716x_gpio_write(dev, 22, 0);
|
|
msleep(200);
|
|
saa716x_gpio_write(dev, 22, 1);
|
|
msleep(400);
|
|
} else if (count == 2) {
|
|
saa716x_gpio_set_output(dev, 12);
|
|
saa716x_gpio_write(dev, 12, 0);
|
|
msleep(200);
|
|
saa716x_gpio_write(dev, 12, 1);
|
|
msleep(400);
|
|
}
|
|
|
|
/* attach frontend */
|
|
adapter->fe = dvb_attach(cxd2820r_attach, &cxd2820r_config[count & 1],
|
|
&i2c->i2c_adapter, NULL);
|
|
if (!adapter->fe)
|
|
goto err;
|
|
|
|
/* attach tuner */
|
|
board_info.addr = (count & 1) ? 0x63 : 0x60;
|
|
tda18212_config[count & 1].fe = adapter->fe;
|
|
request_module("tda18212");
|
|
client = i2c_new_client_device(i2cadapter, &board_info);
|
|
if (!i2c_client_has_driver(client)) {
|
|
dvb_frontend_detach(adapter->fe);
|
|
goto err2;
|
|
}
|
|
if (!try_module_get(client->dev.driver->owner)) {
|
|
i2c_unregister_device(client);
|
|
dvb_frontend_detach(adapter->fe);
|
|
goto err2;
|
|
}
|
|
adapter->i2c_client_tuner = client;
|
|
|
|
strscpy(adapter->fe->ops.info.name,dev->config->model_name,52);
|
|
strlcat(adapter->fe->ops.info.name,dev->config->dev_type,52);
|
|
|
|
dev_dbg(&dev->pdev->dev, "%s frontend %d attached\n",
|
|
dev->config->model_name, count);
|
|
|
|
if (!saa716x_tbs_read_mac(dev,count,mac)) {
|
|
memcpy(adapter->dvb_adapter.proposed_mac, mac, 6);
|
|
dev_notice(&dev->pdev->dev, "%s MAC[%d]=%pM\n", dev->config->model_name, count, adapter->dvb_adapter.proposed_mac);
|
|
}
|
|
|
|
return 0;
|
|
err2:
|
|
dev_err(&dev->pdev->dev, "%s frontend %d tuner attach failed\n",
|
|
dev->config->model_name, count);
|
|
err:
|
|
dev_err(&dev->pdev->dev, "%s frontend %d attach failed\n",
|
|
dev->config->model_name, count);
|
|
|
|
adapter->fe = NULL;
|
|
return -ENODEV;
|
|
}
|
|
|
|
static struct saa716x_config saa716x_tbs6284_config = {
|
|
.model_name = SAA716x_MODEL_TBS6284,
|
|
.dev_type = SAA716x_DEV_TBS6284,
|
|
.boot_mode = SAA716x_EXT_BOOT,
|
|
.adapters = 4,
|
|
.frontend_attach = saa716x_tbs6284_frontend_attach,
|
|
.irq_handler = saa716x_budget_pci_irq,
|
|
.i2c_rate = SAA716x_I2C_RATE_100,
|
|
.i2c_mode = SAA716x_I2C_MODE_POLLING,
|
|
.adap_config = {
|
|
{
|
|
/* adapter 0 */
|
|
.ts_port = 3,
|
|
.worker = demux_worker
|
|
},
|
|
{
|
|
/* adapter 1 */
|
|
.ts_port = 2,
|
|
.worker = demux_worker
|
|
},
|
|
{
|
|
/* adapter 2 */
|
|
.ts_port = 1,
|
|
.worker = demux_worker
|
|
},
|
|
{
|
|
/* adapter 3 */
|
|
.ts_port = 0,
|
|
.worker = demux_worker
|
|
}
|
|
},
|
|
};
|
|
|
|
|
|
#define SAA716x_MODEL_TBS6280 "TurboSight TBS 6280 "
|
|
#define SAA716x_DEV_TBS6280 "DVB-T/T2/C"
|
|
|
|
static int saa716x_tbs6280_frontend_attach(struct saa716x_adapter *adapter, int count)
|
|
{
|
|
struct saa716x_dev *dev = adapter->saa716x;
|
|
struct saa716x_i2c *i2c = &dev->i2c[SAA716x_I2C_BUS_A];
|
|
struct i2c_adapter *i2cadapter = &i2c->i2c_adapter;
|
|
u8 mac[6];
|
|
|
|
struct i2c_client *client;
|
|
|
|
struct i2c_board_info board_info = {
|
|
.type = "tda18212",
|
|
.platform_data = &tda18212_config[count & 1],
|
|
};
|
|
|
|
if (count > 1)
|
|
goto err;
|
|
|
|
/* reset */
|
|
if (count == 0) {
|
|
saa716x_gpio_set_output(dev, 2);
|
|
saa716x_gpio_write(dev, 2, 0);
|
|
msleep(200);
|
|
saa716x_gpio_write(dev, 2, 1);
|
|
msleep(400);
|
|
}
|
|
|
|
/* attach frontend */
|
|
adapter->fe = dvb_attach(cxd2820r_attach, &cxd2820r_config[count],
|
|
&i2c->i2c_adapter, NULL);
|
|
if (!adapter->fe)
|
|
goto err;
|
|
|
|
/* attach tuner */
|
|
board_info.addr = (count & 1) ? 0x63 : 0x60;
|
|
tda18212_config[count & 1].fe = adapter->fe;
|
|
request_module("tda18212");
|
|
client = i2c_new_client_device(i2cadapter, &board_info);
|
|
if (!i2c_client_has_driver(client)) {
|
|
dvb_frontend_detach(adapter->fe);
|
|
goto err2;
|
|
}
|
|
if (!try_module_get(client->dev.driver->owner)) {
|
|
i2c_unregister_device(client);
|
|
dvb_frontend_detach(adapter->fe);
|
|
goto err2;
|
|
}
|
|
adapter->i2c_client_tuner = client;
|
|
|
|
strscpy(adapter->fe->ops.info.name,dev->config->model_name,52);
|
|
strlcat(adapter->fe->ops.info.name,dev->config->dev_type,52);
|
|
|
|
dev_dbg(&dev->pdev->dev, "%s frontend %d attached\n",
|
|
dev->config->model_name, count);
|
|
|
|
if (!saa716x_tbs_read_mac(dev,count,mac)) {
|
|
memcpy(adapter->dvb_adapter.proposed_mac, mac, 6);
|
|
dev_notice(&dev->pdev->dev, "%s MAC[%d]=%pM\n", dev->config->model_name, count, adapter->dvb_adapter.proposed_mac);
|
|
}
|
|
|
|
return 0;
|
|
err2:
|
|
dev_err(&dev->pdev->dev, "%s frontend %d tuner attach failed\n",
|
|
dev->config->model_name, count);
|
|
err:
|
|
dev_err(&dev->pdev->dev, "%s frontend %d attach failed\n",
|
|
dev->config->model_name, count);
|
|
|
|
adapter->fe = NULL;
|
|
return -ENODEV;
|
|
}
|
|
|
|
static struct saa716x_config saa716x_tbs6280_config = {
|
|
.model_name = SAA716x_MODEL_TBS6280,
|
|
.dev_type = SAA716x_DEV_TBS6280,
|
|
.boot_mode = SAA716x_EXT_BOOT,
|
|
.adapters = 2,
|
|
.frontend_attach = saa716x_tbs6280_frontend_attach,
|
|
.irq_handler = saa716x_budget_pci_irq,
|
|
.i2c_rate = SAA716x_I2C_RATE_100,
|
|
.i2c_mode = SAA716x_I2C_MODE_POLLING,
|
|
.adap_config = {
|
|
{
|
|
/* adapter 0 */
|
|
.ts_port = 1, /* using FGPI 1 */
|
|
.worker = demux_worker
|
|
},
|
|
{
|
|
/* adapter 1 */
|
|
.ts_port = 3, /* using FGPI 3 */
|
|
.worker = demux_worker
|
|
},
|
|
},
|
|
};
|
|
|
|
|
|
#define SAA716x_MODEL_TBS6221 "TurboSight TBS 6221 "
|
|
#define SAA716x_DEV_TBS6221 "DVB-T/T2/C"
|
|
|
|
static int saa716x_tbs6221_frontend_attach(struct saa716x_adapter *adapter, int count)
|
|
{
|
|
struct saa716x_dev *dev = adapter->saa716x;
|
|
struct saa716x_i2c *i2c = &dev->i2c[SAA716x_I2C_BUS_A];
|
|
struct i2c_adapter *i2cadapter = &i2c->i2c_adapter;
|
|
struct i2c_client *client;
|
|
struct i2c_board_info info;
|
|
struct si2168_config si2168_config;
|
|
struct si2157_config si2157_config;
|
|
u8 mac[6];
|
|
|
|
if (count > 0)
|
|
goto err;
|
|
|
|
/* attach demod */
|
|
memset(&si2168_config, 0, sizeof(si2168_config));
|
|
si2168_config.i2c_adapter = &i2cadapter;
|
|
si2168_config.fe = &adapter->fe;
|
|
si2168_config.ts_mode = SI2168_TS_PARALLEL;
|
|
si2168_config.ts_clock_gapped = true;
|
|
memset(&info, 0, sizeof(struct i2c_board_info));
|
|
strscpy(info.type, "si2168", I2C_NAME_SIZE);
|
|
info.addr = 0x64;
|
|
info.platform_data = &si2168_config;
|
|
request_module(info.type);
|
|
client = i2c_new_client_device(&i2c->i2c_adapter, &info);
|
|
if (!i2c_client_has_driver(client)) {
|
|
goto err;
|
|
}
|
|
if (!try_module_get(client->dev.driver->owner)) {
|
|
i2c_unregister_device(client);
|
|
goto err;
|
|
}
|
|
adapter->i2c_client_demod = client;
|
|
|
|
/* attach tuner */
|
|
memset(&si2157_config, 0, sizeof(si2157_config));
|
|
si2157_config.fe = adapter->fe;
|
|
si2157_config.if_port = 1;
|
|
memset(&info, 0, sizeof(struct i2c_board_info));
|
|
strscpy(info.type, "si2157", I2C_NAME_SIZE);
|
|
info.addr = 0x60;
|
|
info.platform_data = &si2157_config;
|
|
request_module(info.type);
|
|
client = i2c_new_client_device(i2cadapter, &info);
|
|
if (!i2c_client_has_driver(client)) {
|
|
module_put(adapter->i2c_client_demod->dev.driver->owner);
|
|
i2c_unregister_device(adapter->i2c_client_demod);
|
|
goto err;
|
|
}
|
|
if (!try_module_get(client->dev.driver->owner)) {
|
|
i2c_unregister_device(client);
|
|
module_put(adapter->i2c_client_demod->dev.driver->owner);
|
|
i2c_unregister_device(adapter->i2c_client_demod);
|
|
goto err;
|
|
}
|
|
adapter->i2c_client_tuner = client;
|
|
|
|
strscpy(adapter->fe->ops.info.name,dev->config->model_name,52);
|
|
strlcat(adapter->fe->ops.info.name,dev->config->dev_type,52);
|
|
|
|
dev_dbg(&dev->pdev->dev, "%s frontend %d attached\n",
|
|
dev->config->model_name, count);
|
|
|
|
if (!saa716x_tbs_read_mac(dev,count,mac)) {
|
|
memcpy(adapter->dvb_adapter.proposed_mac, mac, 6);
|
|
dev_notice(&dev->pdev->dev, "%s MAC[%d]=%pM\n", dev->config->model_name, count, adapter->dvb_adapter.proposed_mac);
|
|
}
|
|
|
|
return 0;
|
|
err:
|
|
dev_err(&dev->pdev->dev, "%s frontend %d attach failed\n",
|
|
dev->config->model_name, count);
|
|
return -ENODEV;
|
|
}
|
|
|
|
static struct saa716x_config saa716x_tbs6221_config = {
|
|
.model_name = SAA716x_MODEL_TBS6221,
|
|
.dev_type = SAA716x_DEV_TBS6221,
|
|
.boot_mode = SAA716x_EXT_BOOT,
|
|
.adapters = 1,
|
|
.frontend_attach = saa716x_tbs6221_frontend_attach,
|
|
.irq_handler = saa716x_budget_pci_irq,
|
|
.i2c_rate = SAA716x_I2C_RATE_100,
|
|
.i2c_mode = SAA716x_I2C_MODE_POLLING,
|
|
.adap_config = {
|
|
{
|
|
/* adapter 0 */
|
|
.ts_port = 3, /* using FGPI 3 */
|
|
.worker = demux_worker
|
|
},
|
|
},
|
|
};
|
|
#define SAA716x_MODEL_TBS7220 "TurboSight TBS 7220 "
|
|
#define SAA716x_DEV_TBS7220 "DVB-T/T2/C"
|
|
|
|
static struct saa716x_config saa716x_tbs7220_config = {
|
|
.model_name = SAA716x_MODEL_TBS7220,
|
|
.dev_type = SAA716x_DEV_TBS7220,
|
|
.boot_mode = SAA716x_EXT_BOOT,
|
|
.adapters = 1,
|
|
.frontend_attach = saa716x_tbs6221_frontend_attach,
|
|
.irq_handler = saa716x_budget_pci_irq,
|
|
.i2c_rate = SAA716x_I2C_RATE_100,
|
|
.i2c_mode = SAA716x_I2C_MODE_POLLING,
|
|
.adap_config = {
|
|
{
|
|
.ts_port = 1,
|
|
.worker = demux_worker
|
|
},
|
|
},
|
|
|
|
};
|
|
#define SAA716x_MODEL_TBS6281 "TurboSight TBS 6281 "
|
|
#define SAA716x_DEV_TBS6281 "DVB-T/T2/C"
|
|
|
|
static int saa716x_tbs6281_frontend_attach(struct saa716x_adapter *adapter, int count)
|
|
{
|
|
struct saa716x_dev *dev = adapter->saa716x;
|
|
struct i2c_adapter *i2cadapter;
|
|
struct i2c_client *client;
|
|
struct i2c_board_info info;
|
|
struct si2168_config si2168_config;
|
|
struct si2157_config si2157_config;
|
|
u8 mac[6];
|
|
|
|
if (count > 1)
|
|
goto err;
|
|
|
|
/* reset */
|
|
saa716x_gpio_set_output(dev, count ? 2 : 16);
|
|
saa716x_gpio_write(dev, count ? 2 : 16, 0);
|
|
msleep(50);
|
|
saa716x_gpio_write(dev, count ? 2 : 16, 1);
|
|
msleep(100);
|
|
|
|
/* attach demod */
|
|
memset(&si2168_config, 0, sizeof(si2168_config));
|
|
si2168_config.i2c_adapter = &i2cadapter;
|
|
si2168_config.fe = &adapter->fe;
|
|
si2168_config.ts_mode = SI2168_TS_PARALLEL;
|
|
si2168_config.ts_clock_gapped = true;
|
|
memset(&info, 0, sizeof(struct i2c_board_info));
|
|
strscpy(info.type, "si2168", I2C_NAME_SIZE);
|
|
info.addr = 0x64;
|
|
info.platform_data = &si2168_config;
|
|
request_module(info.type);
|
|
client = i2c_new_client_device(&dev->i2c[1 - count].i2c_adapter, &info);
|
|
if (!i2c_client_has_driver(client)) {
|
|
goto err;
|
|
}
|
|
if (!try_module_get(client->dev.driver->owner)) {
|
|
i2c_unregister_device(client);
|
|
goto err;
|
|
}
|
|
adapter->i2c_client_demod = client;
|
|
|
|
/* attach tuner */
|
|
memset(&si2157_config, 0, sizeof(si2157_config));
|
|
si2157_config.fe = adapter->fe;
|
|
si2157_config.if_port = 1;
|
|
memset(&info, 0, sizeof(struct i2c_board_info));
|
|
strscpy(info.type, "si2157", I2C_NAME_SIZE);
|
|
info.addr = 0x60;
|
|
info.platform_data = &si2157_config;
|
|
request_module(info.type);
|
|
client = i2c_new_client_device(i2cadapter, &info);
|
|
if (!i2c_client_has_driver(client)) {
|
|
module_put(adapter->i2c_client_demod->dev.driver->owner);
|
|
i2c_unregister_device(adapter->i2c_client_demod);
|
|
goto err;
|
|
}
|
|
if (!try_module_get(client->dev.driver->owner)) {
|
|
i2c_unregister_device(client);
|
|
module_put(adapter->i2c_client_demod->dev.driver->owner);
|
|
i2c_unregister_device(adapter->i2c_client_demod);
|
|
goto err;
|
|
}
|
|
adapter->i2c_client_tuner = client;
|
|
|
|
strscpy(adapter->fe->ops.info.name,dev->config->model_name,52);
|
|
strlcat(adapter->fe->ops.info.name,dev->config->dev_type,52);
|
|
|
|
dev_dbg(&dev->pdev->dev, "%s frontend %d attached\n",
|
|
dev->config->model_name, count);
|
|
|
|
if (!saa716x_tbs_read_mac(dev,count,mac)) {
|
|
memcpy(adapter->dvb_adapter.proposed_mac, mac, 6);
|
|
dev_notice(&dev->pdev->dev, "%s MAC[%d]=%pM\n", dev->config->model_name, count, adapter->dvb_adapter.proposed_mac);
|
|
}
|
|
|
|
return 0;
|
|
err:
|
|
dev_err(&dev->pdev->dev, "%s frontend %d attach failed\n",
|
|
dev->config->model_name, count);
|
|
return -ENODEV;
|
|
}
|
|
|
|
static struct saa716x_config saa716x_tbs6281_config = {
|
|
.model_name = SAA716x_MODEL_TBS6281,
|
|
.dev_type = SAA716x_DEV_TBS6281,
|
|
.boot_mode = SAA716x_EXT_BOOT,
|
|
.adapters = 2,
|
|
.frontend_attach = saa716x_tbs6281_frontend_attach,
|
|
.irq_handler = saa716x_budget_pci_irq,
|
|
.i2c_rate = SAA716x_I2C_RATE_400,
|
|
.i2c_mode = SAA716x_I2C_MODE_POLLING,
|
|
.adap_config = {
|
|
{
|
|
/* adapter 0 */
|
|
.ts_port = 1, /* using FGPI 1 */
|
|
.worker = demux_worker
|
|
},
|
|
{
|
|
/* adapter 1 */
|
|
.ts_port = 3, /* using FGPI 3 */
|
|
.worker = demux_worker
|
|
},
|
|
},
|
|
};
|
|
|
|
|
|
#define SAA716x_MODEL_TBS6285 "TurboSight TBS 6285 "
|
|
#define SAA716x_DEV_TBS6285 "DVB-T/T2/C"
|
|
|
|
static int saa716x_tbs6285_frontend_attach(struct saa716x_adapter *adapter, int count)
|
|
{
|
|
struct saa716x_dev *dev = adapter->saa716x;
|
|
struct i2c_adapter *i2cadapter;
|
|
struct i2c_client *client;
|
|
struct i2c_board_info info;
|
|
struct si2168_config si2168_config;
|
|
struct si2157_config si2157_config;
|
|
u8 mac[6];
|
|
|
|
if (count > 3)
|
|
goto err;
|
|
|
|
/* attach demod */
|
|
memset(&si2168_config, 0, sizeof(si2168_config));
|
|
si2168_config.i2c_adapter = &i2cadapter;
|
|
si2168_config.fe = &adapter->fe;
|
|
si2168_config.ts_mode = SI2168_TS_SERIAL;
|
|
si2168_config.ts_clock_gapped = true;
|
|
si2168_config.ts_clock_inv = 1;
|
|
memset(&info, 0, sizeof(struct i2c_board_info));
|
|
strscpy(info.type, "si2168", I2C_NAME_SIZE);
|
|
info.addr = ((count == 0) || (count == 2)) ? 0x64 : 0x66;
|
|
info.platform_data = &si2168_config;
|
|
request_module(info.type);
|
|
client = i2c_new_client_device( ((count == 0) || (count == 1)) ?
|
|
&dev->i2c[1].i2c_adapter : &dev->i2c[0].i2c_adapter,
|
|
&info);
|
|
if (!i2c_client_has_driver(client)) {
|
|
goto err;
|
|
}
|
|
|
|
if (!try_module_get(client->dev.driver->owner)) {
|
|
i2c_unregister_device(client);
|
|
goto err;
|
|
}
|
|
adapter->i2c_client_demod = client;
|
|
|
|
/* attach tuner */
|
|
memset(&si2157_config, 0, sizeof(si2157_config));
|
|
si2157_config.fe = adapter->fe;
|
|
si2157_config.if_port = 1;
|
|
memset(&info, 0, sizeof(struct i2c_board_info));
|
|
strscpy(info.type, "si2157", I2C_NAME_SIZE);
|
|
info.addr = ((count == 0) || (count == 2)) ? 0x62 : 0x60;
|
|
info.platform_data = &si2157_config;
|
|
request_module(info.type);
|
|
client = i2c_new_client_device(i2cadapter, &info);
|
|
if (!i2c_client_has_driver(client)) {
|
|
module_put(adapter->i2c_client_demod->dev.driver->owner);
|
|
i2c_unregister_device(adapter->i2c_client_demod);
|
|
goto err;
|
|
}
|
|
if (!try_module_get(client->dev.driver->owner)) {
|
|
i2c_unregister_device(client);
|
|
module_put(adapter->i2c_client_demod->dev.driver->owner);
|
|
i2c_unregister_device(adapter->i2c_client_demod);
|
|
goto err;
|
|
}
|
|
adapter->i2c_client_tuner = client;
|
|
|
|
dev_dbg(&dev->pdev->dev, "%s frontend %d attached\n",
|
|
dev->config->model_name, count);
|
|
|
|
strscpy(adapter->fe->ops.info.name,dev->config->model_name,52);
|
|
strlcat(adapter->fe->ops.info.name,dev->config->dev_type,52);
|
|
|
|
if (!saa716x_tbs_read_mac(dev,count,mac)) {
|
|
memcpy(adapter->dvb_adapter.proposed_mac, mac, 6);
|
|
dev_notice(&dev->pdev->dev, "%s MAC[%d]=%pM\n", dev->config->model_name, count, adapter->dvb_adapter.proposed_mac);
|
|
}
|
|
|
|
return 0;
|
|
err:
|
|
dev_err(&dev->pdev->dev, "%s frontend %d attach failed\n",
|
|
dev->config->model_name, count);
|
|
return -ENODEV;
|
|
}
|
|
|
|
static struct saa716x_config saa716x_tbs6285_config = {
|
|
.model_name = SAA716x_MODEL_TBS6285,
|
|
.dev_type = SAA716x_DEV_TBS6285,
|
|
.boot_mode = SAA716x_EXT_BOOT,
|
|
.adapters = 4,
|
|
.frontend_attach = saa716x_tbs6285_frontend_attach,
|
|
.irq_handler = saa716x_budget_pci_irq,
|
|
.i2c_rate = SAA716x_I2C_RATE_400,
|
|
.i2c_mode = SAA716x_I2C_MODE_POLLING,
|
|
.adap_config = {
|
|
{
|
|
/* adapter 0 */
|
|
.ts_port = 3,
|
|
.worker = demux_worker
|
|
},
|
|
{
|
|
/* adapter 1 */
|
|
.ts_port = 2,
|
|
.worker = demux_worker
|
|
},
|
|
{
|
|
/* adapter 1 */
|
|
.ts_port = 1,
|
|
.worker = demux_worker
|
|
},
|
|
{
|
|
/* adapter 1 */
|
|
.ts_port = 0,
|
|
.worker = demux_worker
|
|
},
|
|
},
|
|
};
|
|
|
|
|
|
#define SAA716x_MODEL_TBS6220 "TurboSight TBS 6220 "
|
|
#define SAA716x_DEV_TBS6220 "DVB-T/T2/C"
|
|
|
|
static int saa716x_tbs6220_frontend_attach(struct saa716x_adapter *adapter, int count)
|
|
{
|
|
struct saa716x_dev *dev = adapter->saa716x;
|
|
struct saa716x_i2c *i2c = &dev->i2c[SAA716x_I2C_BUS_A];
|
|
struct i2c_adapter *i2cadapter = &i2c->i2c_adapter;
|
|
u8 mac[6];
|
|
|
|
struct i2c_client *client;
|
|
|
|
struct i2c_board_info board_info = {
|
|
.type = "tda18212",
|
|
.addr = 0x60,
|
|
.platform_data = &tda18212_config[0],
|
|
};
|
|
|
|
|
|
if (count > 0)
|
|
goto err;
|
|
|
|
/* attach frontend */
|
|
adapter->fe = dvb_attach(cxd2820r_attach, &cxd2820r_config[0],
|
|
&i2c->i2c_adapter, NULL);
|
|
if (!adapter->fe)
|
|
goto err;
|
|
|
|
/* attach tuner */
|
|
tda18212_config[0].fe = adapter->fe;
|
|
request_module("tda18212");
|
|
client = i2c_new_client_device(i2cadapter, &board_info);
|
|
if (!i2c_client_has_driver(client)) {
|
|
dvb_frontend_detach(adapter->fe);
|
|
goto err2;
|
|
}
|
|
if (!try_module_get(client->dev.driver->owner)) {
|
|
i2c_unregister_device(client);
|
|
dvb_frontend_detach(adapter->fe);
|
|
goto err2;
|
|
}
|
|
adapter->i2c_client_tuner = client;
|
|
|
|
strscpy(adapter->fe->ops.info.name,dev->config->model_name,52);
|
|
strlcat(adapter->fe->ops.info.name,dev->config->dev_type,52);
|
|
|
|
dev_dbg(&dev->pdev->dev, "%s frontend %d attached\n",
|
|
dev->config->model_name, count);
|
|
|
|
if (!saa716x_tbs_read_mac(dev,count,mac)) {
|
|
memcpy(adapter->dvb_adapter.proposed_mac, mac, 6);
|
|
dev_notice(&dev->pdev->dev, "%s MAC=%pM\n", dev->config->model_name, adapter->dvb_adapter.proposed_mac);
|
|
}
|
|
|
|
return 0;
|
|
err2:
|
|
dev_err(&dev->pdev->dev, "%s frontend %d tuner attach failed\n",
|
|
dev->config->model_name, count);
|
|
err:
|
|
dev_err(&dev->pdev->dev, "%s frontend %d attach failed\n",
|
|
dev->config->model_name, count);
|
|
|
|
adapter->fe = NULL;
|
|
return -ENODEV;
|
|
}
|
|
|
|
static struct saa716x_config saa716x_tbs6220_config = {
|
|
.model_name = SAA716x_MODEL_TBS6220,
|
|
.dev_type = SAA716x_DEV_TBS6220,
|
|
.boot_mode = SAA716x_EXT_BOOT,
|
|
.adapters = 1,
|
|
.frontend_attach = saa716x_tbs6220_frontend_attach,
|
|
.irq_handler = saa716x_budget_pci_irq,
|
|
.i2c_rate = SAA716x_I2C_RATE_100,
|
|
.i2c_mode = SAA716x_I2C_MODE_POLLING,
|
|
.adap_config = {
|
|
{
|
|
/* adapter 0 */
|
|
.ts_port = 3, /* using FGPI 3 */
|
|
.worker = demux_worker
|
|
},
|
|
},
|
|
};
|
|
|
|
|
|
#define SAA716x_MODEL_TBS6922 "TurboSight TBS 6922 "
|
|
#define SAA716x_DEV_TBS6922 "DVB-S/S2"
|
|
|
|
static void tbs6922_lnb_power(struct dvb_frontend *fe, int onoff)
|
|
{
|
|
struct i2c_adapter *adapter = tas2101_get_i2c_adapter(fe, 0);
|
|
struct saa716x_i2c *i2c = i2c_get_adapdata(adapter);
|
|
struct saa716x_dev *dev = i2c->saa716x;
|
|
int enpwr_pin = 17;
|
|
|
|
/* lnb power, active high */
|
|
saa716x_gpio_set_output(dev, enpwr_pin);
|
|
if (onoff)
|
|
saa716x_gpio_write(dev, enpwr_pin, 1);
|
|
else
|
|
saa716x_gpio_write(dev, enpwr_pin, 0);
|
|
}
|
|
|
|
|
|
static struct tas2101_config tbs6922_cfg = {
|
|
.i2c_address = 0x68,
|
|
.id = ID_TAS2100,
|
|
.reset_demod = NULL,
|
|
.lnb_power = tbs6922_lnb_power,
|
|
.init = {0x10, 0x32, 0x54, 0x76, 0xb8, 0x9a, 0x33},
|
|
.init2 = 0,
|
|
};
|
|
|
|
static struct av201x_config tbs6922_av201x_cfg = {
|
|
.i2c_address = 0x63,
|
|
.id = ID_AV2012,
|
|
.xtal_freq = 27000, /* kHz */
|
|
};
|
|
|
|
static int saa716x_tbs6922_frontend_attach(
|
|
struct saa716x_adapter *adapter, int count)
|
|
{
|
|
struct saa716x_dev *dev = adapter->saa716x;
|
|
u8 mac[6];
|
|
|
|
dev_dbg(&dev->pdev->dev, "%s frontend %d attaching\n",
|
|
dev->config->model_name, count);
|
|
if (count > 0)
|
|
goto err;
|
|
|
|
saa716x_gpio_set_output(dev, 2);
|
|
saa716x_gpio_write(dev, 2, 0);
|
|
msleep(60);
|
|
saa716x_gpio_write(dev, 2, 1);
|
|
msleep(120);
|
|
|
|
adapter->fe = dvb_attach(tas2101_attach, &tbs6922_cfg,
|
|
&dev->i2c[SAA716x_I2C_BUS_A].i2c_adapter);
|
|
if (adapter->fe == NULL)
|
|
goto err;
|
|
|
|
if (dvb_attach(av201x_attach, adapter->fe, &tbs6922_av201x_cfg,
|
|
tas2101_get_i2c_adapter(adapter->fe, 2)) == NULL) {
|
|
dvb_frontend_detach(adapter->fe);
|
|
adapter->fe = NULL;
|
|
dev_dbg(&dev->pdev->dev,
|
|
"%s frontend %d tuner attach failed\n",
|
|
dev->config->model_name, count);
|
|
goto err;
|
|
}
|
|
|
|
strscpy(adapter->fe->ops.info.name,dev->config->model_name,52);
|
|
strlcat(adapter->fe->ops.info.name,dev->config->dev_type,52);
|
|
|
|
dev_dbg(&dev->pdev->dev, "%s frontend %d attached\n",
|
|
dev->config->model_name, count);
|
|
|
|
if (!saa716x_tbs_read_mac(dev,count,mac)) {
|
|
memcpy(adapter->dvb_adapter.proposed_mac, mac, 6);
|
|
dev_notice(&dev->pdev->dev, "%s MAC=%pM\n", dev->config->model_name, adapter->dvb_adapter.proposed_mac);
|
|
}
|
|
|
|
return 0;
|
|
err:
|
|
dev_err(&dev->pdev->dev, "%s frontend %d attach failed\n",
|
|
dev->config->model_name, count);
|
|
return -ENODEV;
|
|
}
|
|
|
|
static struct saa716x_config saa716x_tbs6922_config = {
|
|
.model_name = SAA716x_MODEL_TBS6922,
|
|
.dev_type = SAA716x_DEV_TBS6922,
|
|
.boot_mode = SAA716x_EXT_BOOT,
|
|
.adapters = 1,
|
|
.frontend_attach = saa716x_tbs6922_frontend_attach,
|
|
.irq_handler = saa716x_budget_pci_irq,
|
|
.i2c_rate = SAA716x_I2C_RATE_100,
|
|
.i2c_mode = SAA716x_I2C_MODE_POLLING,
|
|
.adap_config = {
|
|
{
|
|
/* adapter 0 */
|
|
.ts_port = 3, /* using FGPI 3 */
|
|
.worker = demux_worker
|
|
},
|
|
},
|
|
};
|
|
|
|
|
|
#define SAA716x_MODEL_TBS6923 "TurboSight TBS 6923 "
|
|
#define SAA716x_DEV_TBS6923 "DVB-S/S2"
|
|
|
|
static void tbs6923_lnb_power(struct dvb_frontend *fe, int onoff)
|
|
{
|
|
struct i2c_adapter *adapter = tas2101_get_i2c_adapter(fe, 0);
|
|
struct saa716x_i2c *i2c = i2c_get_adapdata(adapter);
|
|
struct saa716x_dev *dev = i2c->saa716x;
|
|
int enpwr_pin = 3;
|
|
|
|
/* lnb power, active low */
|
|
saa716x_gpio_set_output(dev, enpwr_pin);
|
|
if (onoff)
|
|
saa716x_gpio_write(dev, enpwr_pin, 0);
|
|
else
|
|
saa716x_gpio_write(dev, enpwr_pin, 1);
|
|
}
|
|
|
|
static struct tas2101_config tbs6923_cfg = {
|
|
.i2c_address = 0x68,
|
|
.id = ID_TAS2101,
|
|
.reset_demod = NULL,
|
|
.lnb_power = tbs6923_lnb_power,
|
|
.init = {0x10, 0x32, 0x54, 0x76, 0xb8, 0x9a, 0x33},
|
|
.init2 = 0,
|
|
};
|
|
|
|
static struct av201x_config tbs6923_av201x_cfg = {
|
|
.i2c_address = 0x63,
|
|
.id = ID_AV2012,
|
|
.xtal_freq = 27000, /* kHz */
|
|
};
|
|
|
|
static int saa716x_tbs6923_frontend_attach(
|
|
struct saa716x_adapter *adapter, int count)
|
|
{
|
|
struct saa716x_dev *dev = adapter->saa716x;
|
|
u8 mac[6];
|
|
|
|
dev_dbg(&dev->pdev->dev, "%s frontend %d attaching\n",
|
|
dev->config->model_name, count);
|
|
if (count > 0)
|
|
goto err;
|
|
|
|
saa716x_gpio_set_output(dev, 2);
|
|
saa716x_gpio_write(dev, 2, 0);
|
|
msleep(60);
|
|
saa716x_gpio_write(dev, 2, 1);
|
|
msleep(120);
|
|
|
|
adapter->fe = dvb_attach(tas2101_attach, &tbs6923_cfg,
|
|
&dev->i2c[SAA716x_I2C_BUS_A].i2c_adapter);
|
|
if (adapter->fe == NULL)
|
|
goto err;
|
|
|
|
if (dvb_attach(av201x_attach, adapter->fe, &tbs6923_av201x_cfg,
|
|
tas2101_get_i2c_adapter(adapter->fe, 2)) == NULL) {
|
|
dvb_frontend_detach(adapter->fe);
|
|
adapter->fe = NULL;
|
|
dev_dbg(&dev->pdev->dev,
|
|
"%s frontend %d tuner attach failed\n",
|
|
dev->config->model_name, count);
|
|
goto err;
|
|
}
|
|
|
|
strscpy(adapter->fe->ops.info.name,dev->config->model_name,52);
|
|
strlcat(adapter->fe->ops.info.name,dev->config->dev_type,52);
|
|
|
|
dev_dbg(&dev->pdev->dev, "%s frontend %d attached\n",
|
|
dev->config->model_name, count);
|
|
|
|
if (!saa716x_tbs_read_mac(dev,count,mac)) {
|
|
memcpy(adapter->dvb_adapter.proposed_mac, mac, 6);
|
|
dev_notice(&dev->pdev->dev, "%s MAC=%pM\n", dev->config->model_name, adapter->dvb_adapter.proposed_mac);
|
|
}
|
|
|
|
return 0;
|
|
err:
|
|
dev_err(&dev->pdev->dev, "%s frontend %d attach failed\n",
|
|
dev->config->model_name, count);
|
|
return -ENODEV;
|
|
}
|
|
|
|
static struct saa716x_config saa716x_tbs6923_config = {
|
|
.model_name = SAA716x_MODEL_TBS6923,
|
|
.dev_type = SAA716x_DEV_TBS6923,
|
|
.boot_mode = SAA716x_EXT_BOOT,
|
|
.adapters = 1,
|
|
.frontend_attach = saa716x_tbs6923_frontend_attach,
|
|
.irq_handler = saa716x_budget_pci_irq,
|
|
.i2c_rate = SAA716x_I2C_RATE_100,
|
|
.i2c_mode = SAA716x_I2C_MODE_POLLING,
|
|
.adap_config = {
|
|
{
|
|
/* adapter 0 */
|
|
.ts_port = 3, /* using FGPI 3 */
|
|
.worker = demux_worker
|
|
},
|
|
},
|
|
};
|
|
|
|
|
|
#define SAA716x_MODEL_TBS6925 "TurboSight TBS 6925 "
|
|
#define SAA716x_DEV_TBS6925 "DVB-S/S2"
|
|
|
|
static struct stv090x_config tbs6925_stv090x_cfg = {
|
|
.device = STV0900,
|
|
.demod_mode = STV090x_SINGLE,
|
|
.clk_mode = STV090x_CLK_EXT,
|
|
|
|
.xtal = 27000000,
|
|
.address = 0x68,
|
|
|
|
.ts1_mode = STV090x_TSMODE_PARALLEL_PUNCTURED,
|
|
.ts2_mode = STV090x_TSMODE_PARALLEL_PUNCTURED,
|
|
|
|
.repeater_level = STV090x_RPTLEVEL_16,
|
|
.adc1_range = STV090x_ADC_1Vpp,
|
|
.tuner_bbgain = 6,
|
|
|
|
.tuner_get_frequency = stb6100_get_frequency,
|
|
.tuner_set_frequency = stb6100_set_frequency,
|
|
.tuner_set_bandwidth = stb6100_set_bandwidth,
|
|
.tuner_get_bandwidth = stb6100_get_bandwidth,
|
|
};
|
|
|
|
static struct stb6100_config tbs6925_stb6100_cfg = {
|
|
.tuner_address = 0x60,
|
|
.refclock = 27000000
|
|
};
|
|
|
|
static int tbs6925_set_voltage(struct dvb_frontend *fe, enum fe_sec_voltage voltage)
|
|
{
|
|
struct saa716x_adapter *adapter = fe->dvb->priv;
|
|
struct saa716x_dev *saa716x = adapter->saa716x;
|
|
|
|
saa716x_gpio_set_output(saa716x, 16);
|
|
msleep(1);
|
|
switch (voltage) {
|
|
case SEC_VOLTAGE_13:
|
|
saa716x_gpio_write(saa716x, 16, 0);
|
|
break;
|
|
case SEC_VOLTAGE_18:
|
|
saa716x_gpio_write(saa716x, 16, 1);
|
|
break;
|
|
case SEC_VOLTAGE_OFF:
|
|
break;
|
|
default:
|
|
return -EINVAL;
|
|
}
|
|
msleep(100);
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int tbs6925_frontend_attach(struct saa716x_adapter *adapter,
|
|
int count)
|
|
{
|
|
struct saa716x_dev *dev = adapter->saa716x;
|
|
u8 mac[6];
|
|
|
|
dev_dbg(&dev->pdev->dev, "%s frontend %d attaching\n",
|
|
dev->config->model_name, count);
|
|
|
|
if (count > 0)
|
|
goto err;
|
|
|
|
/* Reset the demodulator */
|
|
saa716x_gpio_set_output(dev, 2);
|
|
saa716x_gpio_write(dev, 2, 0);
|
|
msleep(50);
|
|
saa716x_gpio_write(dev, 2, 1);
|
|
msleep(100);
|
|
|
|
adapter->fe = dvb_attach(stv090x_attach, &tbs6925_stv090x_cfg,
|
|
&dev->i2c[SAA716x_I2C_BUS_A].i2c_adapter,
|
|
STV090x_DEMODULATOR_0);
|
|
|
|
if (adapter->fe == NULL)
|
|
goto err;
|
|
|
|
adapter->fe->ops.set_voltage = tbs6925_set_voltage;
|
|
|
|
if (dvb_attach(stb6100_attach, adapter->fe,
|
|
&tbs6925_stb6100_cfg, &dev->i2c[SAA716x_I2C_BUS_A].i2c_adapter) == NULL) {
|
|
dvb_frontend_detach(adapter->fe);
|
|
adapter->fe = NULL;
|
|
dev_dbg(&dev->pdev->dev,
|
|
"%s frontend %d tuner attach failed\n",
|
|
dev->config->model_name, count);
|
|
goto err;
|
|
}
|
|
|
|
if (adapter->fe->ops.init)
|
|
adapter->fe->ops.init(adapter->fe);
|
|
|
|
strscpy(adapter->fe->ops.info.name,dev->config->model_name,52);
|
|
strlcat(adapter->fe->ops.info.name,dev->config->dev_type,52);
|
|
|
|
dev_dbg(&dev->pdev->dev, "%s frontend %d attached\n",
|
|
dev->config->model_name, count);
|
|
|
|
if (!saa716x_tbs_read_mac(dev,count,mac)) {
|
|
memcpy(adapter->dvb_adapter.proposed_mac, mac, 6);
|
|
dev_notice(&dev->pdev->dev, "%s MAC=%pM\n", dev->config->model_name, adapter->dvb_adapter.proposed_mac);
|
|
}
|
|
|
|
return 0;
|
|
err:
|
|
dev_err(&dev->pdev->dev, "%s frontend %d attach failed\n",
|
|
dev->config->model_name, count);
|
|
return -ENODEV;
|
|
}
|
|
|
|
static struct saa716x_config saa716x_tbs6925_config = {
|
|
.model_name = SAA716x_MODEL_TBS6925,
|
|
.dev_type = SAA716x_DEV_TBS6925,
|
|
.boot_mode = SAA716x_EXT_BOOT,
|
|
.adapters = 1,
|
|
.frontend_attach = tbs6925_frontend_attach,
|
|
.irq_handler = saa716x_budget_pci_irq,
|
|
.i2c_rate = SAA716x_I2C_RATE_100,
|
|
.i2c_mode = SAA716x_I2C_MODE_POLLING,
|
|
.adap_config = {
|
|
{
|
|
/* Adapter 0 */
|
|
.ts_port = 3, /* using FGPI 1 */
|
|
.worker = demux_worker
|
|
}
|
|
}
|
|
};
|
|
|
|
|
|
#define SAA716x_MODEL_TBS6982 "TurboSight TBS 6982 "
|
|
#define SAA716x_DEV_TBS6982 "DVB-S/S2"
|
|
|
|
static void tbs6982_reset_fe(struct dvb_frontend *fe, int reset_pin)
|
|
{
|
|
struct i2c_adapter *adapter = tas2101_get_i2c_adapter(fe, 0);
|
|
struct saa716x_i2c *i2c = i2c_get_adapdata(adapter);
|
|
struct saa716x_dev *dev = i2c->saa716x;
|
|
|
|
/* reset frontend, active low */
|
|
saa716x_gpio_set_output(dev, reset_pin);
|
|
saa716x_gpio_write(dev, reset_pin, 0);
|
|
msleep(60);
|
|
saa716x_gpio_write(dev, reset_pin, 1);
|
|
msleep(120);
|
|
}
|
|
|
|
static void tbs6982_reset_fe0(struct dvb_frontend *fe)
|
|
{
|
|
tbs6982_reset_fe(fe, 2);
|
|
}
|
|
|
|
static void tbs6982_reset_fe1(struct dvb_frontend *fe)
|
|
{
|
|
tbs6982_reset_fe(fe, 17);
|
|
}
|
|
|
|
static void tbs6982_lnb_power(struct dvb_frontend *fe,
|
|
int enpwr_pin, int onoff)
|
|
{
|
|
struct i2c_adapter *adapter = tas2101_get_i2c_adapter(fe, 0);
|
|
struct saa716x_i2c *i2c = i2c_get_adapdata(adapter);
|
|
struct saa716x_dev *dev = i2c->saa716x;
|
|
|
|
/* lnb power, active low */
|
|
saa716x_gpio_set_output(dev, enpwr_pin);
|
|
if (onoff)
|
|
saa716x_gpio_write(dev, enpwr_pin, 0);
|
|
else
|
|
saa716x_gpio_write(dev, enpwr_pin, 1);
|
|
}
|
|
|
|
static void tbs6982_lnb0_power(struct dvb_frontend *fe, int onoff)
|
|
{
|
|
tbs6982_lnb_power(fe, 5, onoff);
|
|
}
|
|
|
|
static void tbs6982_lnb1_power(struct dvb_frontend *fe, int onoff)
|
|
{
|
|
tbs6982_lnb_power(fe, 3, onoff);
|
|
}
|
|
|
|
static struct tas2101_config tbs6982_cfg[] = {
|
|
{
|
|
.i2c_address = 0x68,
|
|
.id = ID_TAS2101,
|
|
.reset_demod = tbs6982_reset_fe0,
|
|
.lnb_power = tbs6982_lnb0_power,
|
|
.init = {0x10, 0x32, 0x54, 0x76, 0xb8, 0x9a, 0x33},
|
|
.init2 = 0,
|
|
},
|
|
{
|
|
.i2c_address = 0x68,
|
|
.id = ID_TAS2101,
|
|
.reset_demod = tbs6982_reset_fe1,
|
|
.lnb_power = tbs6982_lnb1_power,
|
|
.init = {0x8a, 0x6b, 0x13, 0x70, 0x45, 0x92, 0x33},
|
|
.init2 = 0,
|
|
}
|
|
};
|
|
|
|
static struct av201x_config tbs6982_av201x_cfg = {
|
|
.i2c_address = 0x63,
|
|
.id = ID_AV2012,
|
|
.xtal_freq = 27000, /* kHz */
|
|
};
|
|
|
|
static int saa716x_tbs6982_frontend_attach(
|
|
struct saa716x_adapter *adapter, int count)
|
|
{
|
|
struct saa716x_dev *dev = adapter->saa716x;
|
|
u8 mac[6];
|
|
|
|
dev_dbg(&dev->pdev->dev, "%s frontend %d attaching\n",
|
|
dev->config->model_name, count);
|
|
if (count > 1)
|
|
goto err;
|
|
|
|
saa716x_gpio_set_output(dev, 16);
|
|
saa716x_gpio_write(dev, 16, 0);
|
|
msleep(60);
|
|
saa716x_gpio_write(dev, 16, 1);
|
|
msleep(120);
|
|
|
|
adapter->fe = dvb_attach(tas2101_attach, &tbs6982_cfg[count],
|
|
&dev->i2c[1 - count].i2c_adapter);
|
|
if (adapter->fe == NULL)
|
|
goto err;
|
|
|
|
if (dvb_attach(av201x_attach, adapter->fe, &tbs6982_av201x_cfg,
|
|
tas2101_get_i2c_adapter(adapter->fe, 2)) == NULL) {
|
|
dvb_frontend_detach(adapter->fe);
|
|
adapter->fe = NULL;
|
|
dev_dbg(&dev->pdev->dev,
|
|
"%s frontend %d tuner attach failed\n",
|
|
dev->config->model_name, count);
|
|
goto err;
|
|
}
|
|
|
|
strscpy(adapter->fe->ops.info.name,dev->config->model_name,52);
|
|
strlcat(adapter->fe->ops.info.name,dev->config->dev_type,52);
|
|
|
|
dev_dbg(&dev->pdev->dev, "%s frontend %d attached\n",
|
|
dev->config->model_name, count);
|
|
|
|
if (!saa716x_tbs_read_mac(dev,count,mac)) {
|
|
memcpy(adapter->dvb_adapter.proposed_mac, mac, 6);
|
|
dev_notice(&dev->pdev->dev, "%s MAC=%pM\n", dev->config->model_name, adapter->dvb_adapter.proposed_mac);
|
|
}
|
|
|
|
return 0;
|
|
err:
|
|
dev_err(&dev->pdev->dev, "%s frontend %d attach failed\n",
|
|
dev->config->model_name, count);
|
|
return -ENODEV;
|
|
}
|
|
|
|
static struct saa716x_config saa716x_tbs6982_config = {
|
|
.model_name = SAA716x_MODEL_TBS6982,
|
|
.dev_type = SAA716x_DEV_TBS6982,
|
|
.boot_mode = SAA716x_EXT_BOOT,
|
|
.adapters = 2,
|
|
.frontend_attach = saa716x_tbs6982_frontend_attach,
|
|
.irq_handler = saa716x_budget_pci_irq,
|
|
.i2c_rate = SAA716x_I2C_RATE_400,
|
|
.i2c_mode = SAA716x_I2C_MODE_POLLING,
|
|
.adap_config = {
|
|
{
|
|
/* adapter 0 */
|
|
.ts_port = 3, /* using FGPI 3 */
|
|
.worker = demux_worker
|
|
},
|
|
{
|
|
/* adapter 1 */
|
|
.ts_port = 1, /* using FGPI 1 */
|
|
.worker = demux_worker
|
|
},
|
|
},
|
|
};
|
|
|
|
|
|
#define SAA716x_MODEL_TBS6982SE "TurboSight TBS 6982SE "
|
|
#define SAA716x_DEV_TBS6982SE "DVB-S/S2"
|
|
|
|
static void tbs6982se_reset_fe(struct dvb_frontend *fe, int reset_pin)
|
|
{
|
|
struct i2c_adapter *adapter = tas2101_get_i2c_adapter(fe, 0);
|
|
struct saa716x_i2c *i2c = i2c_get_adapdata(adapter);
|
|
struct saa716x_dev *dev = i2c->saa716x;
|
|
|
|
/* reset frontend, active low */
|
|
saa716x_gpio_set_output(dev, reset_pin);
|
|
saa716x_gpio_write(dev, reset_pin, 0);
|
|
msleep(60);
|
|
saa716x_gpio_write(dev, reset_pin, 1);
|
|
msleep(120);
|
|
}
|
|
|
|
static void tbs6982se_reset_fe0(struct dvb_frontend *fe)
|
|
{
|
|
tbs6982se_reset_fe(fe, 2);
|
|
}
|
|
|
|
static void tbs6982se_reset_fe1(struct dvb_frontend *fe)
|
|
{
|
|
tbs6982se_reset_fe(fe, 17);
|
|
}
|
|
|
|
static void tbs6982se_lnb_power(struct dvb_frontend *fe,
|
|
int enpwr_pin, int onoff)
|
|
{
|
|
struct i2c_adapter *adapter = tas2101_get_i2c_adapter(fe, 0);
|
|
struct saa716x_i2c *i2c = i2c_get_adapdata(adapter);
|
|
struct saa716x_dev *dev = i2c->saa716x;
|
|
|
|
/* lnb power, active low */
|
|
saa716x_gpio_set_output(dev, enpwr_pin);
|
|
if (onoff)
|
|
saa716x_gpio_write(dev, enpwr_pin, 0);
|
|
else
|
|
saa716x_gpio_write(dev, enpwr_pin, 1);
|
|
}
|
|
|
|
static void tbs6982se_lnb0_power(struct dvb_frontend *fe, int onoff)
|
|
{
|
|
tbs6982se_lnb_power(fe, 3, onoff);
|
|
}
|
|
|
|
static void tbs6982se_lnb1_power(struct dvb_frontend *fe, int onoff)
|
|
{
|
|
tbs6982se_lnb_power(fe, 16, onoff);
|
|
}
|
|
|
|
static struct tas2101_config tbs6982se_cfg[] = {
|
|
{
|
|
.i2c_address = 0x60,
|
|
.id = ID_TAS2101,
|
|
.reset_demod = tbs6982se_reset_fe0,
|
|
.lnb_power = tbs6982se_lnb0_power,
|
|
.init = {0x10, 0x32, 0x54, 0x76, 0xb8, 0x9a, 0x33},
|
|
.init2 = 0,
|
|
},
|
|
{
|
|
.i2c_address = 0x68,
|
|
.id = ID_TAS2101,
|
|
.reset_demod = tbs6982se_reset_fe1,
|
|
.lnb_power = tbs6982se_lnb1_power,
|
|
.init = {0x8a, 0x6b, 0x13, 0x70, 0x45, 0x92, 0x33},
|
|
.init2 = 0,
|
|
}
|
|
};
|
|
|
|
static struct av201x_config tbs6982se_av201x_cfg = {
|
|
.i2c_address = 0x63,
|
|
.id = ID_AV2012,
|
|
.xtal_freq = 27000, /* kHz */
|
|
};
|
|
|
|
static int saa716x_tbs6982se_frontend_attach(
|
|
struct saa716x_adapter *adapter, int count)
|
|
{
|
|
struct saa716x_dev *dev = adapter->saa716x;
|
|
u8 mac[6];
|
|
|
|
dev_dbg(&dev->pdev->dev, "%s frontend %d attaching\n",
|
|
dev->config->model_name, count);
|
|
if (count > 1)
|
|
goto err;
|
|
|
|
adapter->fe = dvb_attach(tas2101_attach, &tbs6982se_cfg[count],
|
|
&dev->i2c[count].i2c_adapter);
|
|
if (adapter->fe == NULL)
|
|
goto err;
|
|
|
|
if (dvb_attach(av201x_attach, adapter->fe, &tbs6982se_av201x_cfg,
|
|
tas2101_get_i2c_adapter(adapter->fe, 2)) == NULL) {
|
|
dvb_frontend_detach(adapter->fe);
|
|
adapter->fe = NULL;
|
|
dev_dbg(&dev->pdev->dev,
|
|
"%s frontend %d tuner attach failed\n",
|
|
dev->config->model_name, count);
|
|
goto err;
|
|
}
|
|
|
|
strscpy(adapter->fe->ops.info.name,dev->config->model_name,52);
|
|
strlcat(adapter->fe->ops.info.name,dev->config->dev_type,52);
|
|
|
|
dev_dbg(&dev->pdev->dev, "%s frontend %d attached\n",
|
|
dev->config->model_name, count);
|
|
|
|
if (!saa716x_tbs_read_mac(dev,count,mac)) {
|
|
memcpy(adapter->dvb_adapter.proposed_mac, mac, 6);
|
|
dev_notice(&dev->pdev->dev, "%s MAC=%pM\n", dev->config->model_name, adapter->dvb_adapter.proposed_mac);
|
|
}
|
|
|
|
return 0;
|
|
err:
|
|
dev_err(&dev->pdev->dev, "%s frontend %d attach failed\n",
|
|
dev->config->model_name, count);
|
|
return -ENODEV;
|
|
}
|
|
|
|
static struct saa716x_config saa716x_tbs6982se_config = {
|
|
.model_name = SAA716x_MODEL_TBS6982SE,
|
|
.dev_type = SAA716x_DEV_TBS6982SE,
|
|
.boot_mode = SAA716x_EXT_BOOT,
|
|
.adapters = 2,
|
|
.frontend_attach = saa716x_tbs6982se_frontend_attach,
|
|
.irq_handler = saa716x_budget_pci_irq,
|
|
.i2c_rate = SAA716x_I2C_RATE_400,
|
|
.i2c_mode = SAA716x_I2C_MODE_POLLING,
|
|
.adap_config = {
|
|
{
|
|
/* adapter 0 */
|
|
.ts_port = 3, /* using FGPI 3 */
|
|
.worker = demux_worker
|
|
},
|
|
{
|
|
/* adapter 1 */
|
|
.ts_port = 1, /* using FGPI 1 */
|
|
.worker = demux_worker
|
|
},
|
|
},
|
|
};
|
|
|
|
|
|
#define SAA716x_MODEL_TBS6984 "TurboSight TBS 6984 "
|
|
#define SAA716x_DEV_TBS6984 "DVB-S/S2"
|
|
|
|
static void saa716x_tbs6984_init(struct saa716x_dev *saa716x)
|
|
{
|
|
int i;
|
|
const u8 buf[] = {
|
|
0xe0, 0x06, 0x66, 0x33, 0x65,
|
|
0x01, 0x17, 0x06, 0xde};
|
|
|
|
#define TBS_CK 7
|
|
#define TBS_CS 8
|
|
#define TBS_DT 11
|
|
|
|
/* send init bitstream through a bitbanged spi */
|
|
/* set pins as output */
|
|
saa716x_gpio_set_output(saa716x, TBS_CK);
|
|
saa716x_gpio_set_output(saa716x, TBS_CS);
|
|
saa716x_gpio_set_output(saa716x, TBS_DT);
|
|
|
|
/* set all pins high */
|
|
saa716x_gpio_write(saa716x, TBS_CK, 1);
|
|
saa716x_gpio_write(saa716x, TBS_CS, 1);
|
|
saa716x_gpio_write(saa716x, TBS_DT, 1);
|
|
msleep(20);
|
|
|
|
/* CS low */
|
|
saa716x_gpio_write(saa716x, TBS_CS, 0);
|
|
msleep(20);
|
|
/* send bitstream */
|
|
for (i = 0; i < 9 * 8; i++) {
|
|
/* clock low */
|
|
saa716x_gpio_write(saa716x, TBS_CK, 0);
|
|
msleep(20);
|
|
/* set data pin */
|
|
saa716x_gpio_write(saa716x, TBS_DT,
|
|
((buf[i >> 3] >> (7 - (i & 7))) & 1));
|
|
/* clock high */
|
|
saa716x_gpio_write(saa716x, TBS_CK, 1);
|
|
msleep(20);
|
|
}
|
|
/* raise cs, clk and data */
|
|
saa716x_gpio_write(saa716x, TBS_CS, 1);
|
|
saa716x_gpio_write(saa716x, TBS_CK, 1);
|
|
saa716x_gpio_write(saa716x, TBS_DT, 1);
|
|
|
|
/* power up LNB supply and control chips */
|
|
saa716x_gpio_set_output(saa716x, 19); /* a0 */
|
|
saa716x_gpio_set_output(saa716x, 2); /* a1 */
|
|
saa716x_gpio_set_output(saa716x, 5); /* a2 */
|
|
saa716x_gpio_set_output(saa716x, 3); /* a3 */
|
|
|
|
/* power off */
|
|
saa716x_gpio_write(saa716x, 19, 1); /* a0 */
|
|
saa716x_gpio_write(saa716x, 2, 1); /* a1 */
|
|
saa716x_gpio_write(saa716x, 5, 1); /* a2 */
|
|
saa716x_gpio_write(saa716x, 3, 1); /* a3 */
|
|
}
|
|
|
|
|
|
static void tbs6984_lnb_pwr(struct dvb_frontend *fe, int pin, int onoff)
|
|
{
|
|
struct i2c_adapter *adapter = cx24117_get_i2c_adapter(fe);
|
|
struct saa716x_i2c *i2c = i2c_get_adapdata(adapter);
|
|
struct saa716x_dev *dev = i2c->saa716x;
|
|
|
|
/* lnb power, active low */
|
|
if (onoff)
|
|
saa716x_gpio_write(dev, pin , 0);
|
|
else
|
|
saa716x_gpio_write(dev, pin, 1);
|
|
}
|
|
|
|
static void tbs6984_lnb_pwr0(struct dvb_frontend *fe, int demod, int onoff)
|
|
{
|
|
tbs6984_lnb_pwr(fe, (demod == 0) ? 19 : 2, onoff);
|
|
}
|
|
|
|
static void tbs6984_lnb_pwr1(struct dvb_frontend *fe, int demod, int onoff)
|
|
{
|
|
tbs6984_lnb_pwr(fe, (demod == 0) ? 5 : 3, onoff);
|
|
}
|
|
|
|
static struct cx24117_config tbs6984_cx24117_cfg[] = {
|
|
{
|
|
.demod_address = 0x55,
|
|
.lnb_power = tbs6984_lnb_pwr0,
|
|
},
|
|
{
|
|
.demod_address = 0x05,
|
|
.lnb_power = tbs6984_lnb_pwr1,
|
|
},
|
|
};
|
|
|
|
static struct isl6422_config tbs6984_isl6422_cfg[] = {
|
|
{
|
|
.current_max = SEC_CURRENT_570m,
|
|
.curlim = SEC_CURRENT_LIM_ON,
|
|
.mod_extern = 1,
|
|
.addr = 0x08,
|
|
.id = 0,
|
|
},
|
|
{
|
|
.current_max = SEC_CURRENT_570m,
|
|
.curlim = SEC_CURRENT_LIM_ON,
|
|
.mod_extern = 1,
|
|
.addr = 0x08,
|
|
.id = 1,
|
|
}
|
|
|
|
};
|
|
|
|
static int saa716x_tbs6984_frontend_attach(
|
|
struct saa716x_adapter *adapter, int count)
|
|
{
|
|
struct saa716x_dev *dev = adapter->saa716x;
|
|
struct saa716x_i2c *i2c = &dev->i2c[1 - (count >> 1)];
|
|
u8 mac[6];
|
|
|
|
dev_dbg(&dev->pdev->dev, "%s frontend %d attaching\n",
|
|
dev->config->model_name, count);
|
|
|
|
if (count > 3)
|
|
goto err;
|
|
|
|
if (count == 0)
|
|
saa716x_tbs6984_init(dev);
|
|
|
|
adapter->fe = dvb_attach(cx24117_attach, &tbs6984_cx24117_cfg[count >> 1],
|
|
&i2c->i2c_adapter);
|
|
if (adapter->fe == NULL)
|
|
goto err;
|
|
|
|
if (dvb_attach(isl6422_attach, adapter->fe, &i2c->i2c_adapter,
|
|
&tbs6984_isl6422_cfg[count & 0x01]) == NULL)
|
|
dev_info(&dev->pdev->dev,
|
|
"%s frontend %d doesn't seem to have a isl6422b on the i2c bus.\n",
|
|
dev->config->model_name, count);
|
|
|
|
strscpy(adapter->fe->ops.info.name,dev->config->model_name,52);
|
|
strlcat(adapter->fe->ops.info.name,dev->config->dev_type,52);
|
|
|
|
if (!saa716x_tbs_read_mac(dev,count,mac)) {
|
|
memcpy(adapter->dvb_adapter.proposed_mac, mac, 6);
|
|
dev_notice(&dev->pdev->dev, "%s MAC=%pM\n", dev->config->model_name, adapter->dvb_adapter.proposed_mac);
|
|
}
|
|
return 0;
|
|
err:
|
|
dev_err(&dev->pdev->dev, "%s frontend %d attach failed\n",
|
|
dev->config->model_name, count);
|
|
return -ENODEV;
|
|
}
|
|
|
|
static struct saa716x_config saa716x_tbs6984_config = {
|
|
.model_name = SAA716x_MODEL_TBS6984,
|
|
.dev_type = SAA716x_DEV_TBS6984,
|
|
.boot_mode = SAA716x_EXT_BOOT,
|
|
.adapters = 4,
|
|
.frontend_attach = saa716x_tbs6984_frontend_attach,
|
|
.irq_handler = saa716x_budget_pci_irq,
|
|
.i2c_rate = SAA716x_I2C_RATE_400,
|
|
.i2c_mode = SAA716x_I2C_MODE_POLLING,
|
|
.adap_config = {
|
|
{
|
|
/* adapter 0 */
|
|
.ts_port = 2,
|
|
.worker = demux_worker
|
|
},
|
|
{
|
|
/* adapter 1 */
|
|
.ts_port = 3,
|
|
.worker = demux_worker
|
|
},
|
|
{
|
|
/* adapter 2 */
|
|
.ts_port = 0,
|
|
.worker = demux_worker
|
|
},
|
|
{
|
|
/* adapter 3 */
|
|
.ts_port = 1,
|
|
.worker = demux_worker
|
|
},
|
|
},
|
|
};
|
|
|
|
|
|
#define SAA716x_MODEL_TBS6985 "TurboSight TBS 6985 "
|
|
#define SAA716x_DEV_TBS6985 "DVB-S/S2"
|
|
|
|
static void tbs6985_reset_fe(struct dvb_frontend *fe, int reset_pin)
|
|
{
|
|
struct i2c_adapter *adapter = tas2101_get_i2c_adapter(fe, 0);
|
|
struct saa716x_i2c *i2c = i2c_get_adapdata(adapter);
|
|
struct saa716x_dev *dev = i2c->saa716x;
|
|
|
|
/* reset frontend, active low */
|
|
saa716x_gpio_set_output(dev, reset_pin);
|
|
saa716x_gpio_write(dev, reset_pin, 0);
|
|
msleep(60);
|
|
saa716x_gpio_write(dev, reset_pin, 1);
|
|
msleep(120);
|
|
}
|
|
|
|
static void tbs6985_reset_fe0(struct dvb_frontend *fe)
|
|
{
|
|
tbs6985_reset_fe(fe, 5);
|
|
}
|
|
|
|
static void tbs6985_reset_fe1(struct dvb_frontend *fe)
|
|
{
|
|
tbs6985_reset_fe(fe, 2);
|
|
}
|
|
|
|
static void tbs6985_reset_fe2(struct dvb_frontend *fe)
|
|
{
|
|
tbs6985_reset_fe(fe, 13);
|
|
}
|
|
|
|
static void tbs6985_reset_fe3(struct dvb_frontend *fe)
|
|
{
|
|
tbs6985_reset_fe(fe, 3);
|
|
}
|
|
|
|
static void tbs6985_lnb_power(struct dvb_frontend *fe,
|
|
int enpwr_pin, int onoff)
|
|
{
|
|
struct i2c_adapter *adapter = tas2101_get_i2c_adapter(fe, 0);
|
|
struct saa716x_i2c *i2c = i2c_get_adapdata(adapter);
|
|
struct saa716x_dev *dev = i2c->saa716x;
|
|
|
|
/* lnb power, active low */
|
|
saa716x_gpio_set_output(dev, enpwr_pin);
|
|
if (onoff)
|
|
saa716x_gpio_write(dev, enpwr_pin, 0);
|
|
else
|
|
saa716x_gpio_write(dev, enpwr_pin, 1);
|
|
}
|
|
|
|
static void tbs6985_lnb0_power(struct dvb_frontend *fe, int onoff)
|
|
{
|
|
tbs6985_lnb_power(fe, 27, onoff);
|
|
}
|
|
|
|
static void tbs6985_lnb1_power(struct dvb_frontend *fe, int onoff)
|
|
{
|
|
tbs6985_lnb_power(fe, 22, onoff);
|
|
}
|
|
|
|
static void tbs6985_lnb2_power(struct dvb_frontend *fe, int onoff)
|
|
{
|
|
tbs6985_lnb_power(fe, 19, onoff);
|
|
}
|
|
|
|
static void tbs6985_lnb3_power(struct dvb_frontend *fe, int onoff)
|
|
{
|
|
tbs6985_lnb_power(fe, 15, onoff);
|
|
}
|
|
|
|
#undef TBS6985_TSMODE0
|
|
static struct tas2101_config tbs6985_cfg[] = {
|
|
{
|
|
.i2c_address = 0x60,
|
|
.id = ID_TAS2101,
|
|
.reset_demod = tbs6985_reset_fe0,
|
|
.lnb_power = tbs6985_lnb0_power,
|
|
#ifdef TBS6985_TSMODE0
|
|
.init = {0x01, 0x32, 0x65, 0x74, 0xab, 0x98, 0x33},
|
|
#else
|
|
.init = {0x0b, 0x8a, 0x65, 0x74, 0xab, 0x98, 0xb1},
|
|
#endif
|
|
.init2 = 0,
|
|
},
|
|
{
|
|
.i2c_address = 0x68,
|
|
.id = ID_TAS2101,
|
|
.reset_demod = tbs6985_reset_fe1,
|
|
.lnb_power = tbs6985_lnb1_power,
|
|
#ifdef TBS6985_TSMODE0
|
|
.init = {0x10, 0x32, 0x54, 0xb7, 0x86, 0x9a, 0x33},
|
|
#else
|
|
.init = {0x0a, 0x8b, 0x54, 0xb7, 0x86, 0x9a, 0xb1},
|
|
#endif
|
|
.init2 = 0,
|
|
},
|
|
{
|
|
.i2c_address = 0x60,
|
|
.id = ID_TAS2101,
|
|
.reset_demod = tbs6985_reset_fe2,
|
|
.lnb_power = tbs6985_lnb2_power,
|
|
#ifdef TBS6985_TSMODE0
|
|
.init = {0x25, 0x36, 0x40, 0xb1, 0x87, 0x9a, 0x33},
|
|
#else
|
|
.init = {0xba, 0x80, 0x40, 0xb1, 0x87, 0x9a, 0xb1},
|
|
#endif
|
|
.init2 = 0,
|
|
},
|
|
{
|
|
.i2c_address = 0x68,
|
|
.id = ID_TAS2101,
|
|
.reset_demod = tbs6985_reset_fe3,
|
|
.lnb_power = tbs6985_lnb3_power,
|
|
#ifdef TBS6985_TSMODE0
|
|
.init = {0x80, 0xba, 0x21, 0x53, 0x74, 0x96, 0x33},
|
|
#else
|
|
.init = {0xba, 0x80, 0x21, 0x53, 0x74, 0x96, 0xb1},
|
|
#endif
|
|
.init2 = 0,
|
|
}
|
|
};
|
|
|
|
static struct av201x_config tbs6985_av201x_cfg = {
|
|
.i2c_address = 0x63,
|
|
.id = ID_AV2012,
|
|
.xtal_freq = 27000, /* kHz */
|
|
};
|
|
|
|
static int saa716x_tbs6985_frontend_attach(struct saa716x_adapter *adapter, int count)
|
|
{
|
|
struct saa716x_dev *dev = adapter->saa716x;
|
|
u8 mac[6];
|
|
|
|
if (count > 3)
|
|
goto err;
|
|
|
|
adapter->fe = dvb_attach(tas2101_attach, &tbs6985_cfg[count],
|
|
&dev->i2c[1 - (count >> 1)].i2c_adapter);
|
|
if (adapter->fe == NULL)
|
|
goto err;
|
|
|
|
if (dvb_attach(av201x_attach, adapter->fe, &tbs6985_av201x_cfg,
|
|
tas2101_get_i2c_adapter(adapter->fe, 2)) == NULL) {
|
|
dvb_frontend_detach(adapter->fe);
|
|
adapter->fe = NULL;
|
|
dev_dbg(&dev->pdev->dev,
|
|
"%s frontend %d tuner attach failed\n",
|
|
dev->config->model_name, count);
|
|
goto err;
|
|
}
|
|
|
|
if (!saa716x_tbs_read_mac(dev,count,mac)) {
|
|
memcpy(adapter->dvb_adapter.proposed_mac, mac, 6);
|
|
dev_notice(&dev->pdev->dev, "%s MAC=%pM\n", dev->config->model_name, adapter->dvb_adapter.proposed_mac);
|
|
}
|
|
|
|
strscpy(adapter->fe->ops.info.name,dev->config->model_name,52);
|
|
strlcat(adapter->fe->ops.info.name,dev->config->dev_type,52);
|
|
|
|
return 0;
|
|
err:
|
|
dev_err(&dev->pdev->dev, "%s frontend %d attach failed\n",
|
|
dev->config->model_name, count);
|
|
return -ENODEV;
|
|
}
|
|
|
|
static struct saa716x_config saa716x_tbs6985_config = {
|
|
.model_name = SAA716x_MODEL_TBS6985,
|
|
.dev_type = SAA716x_DEV_TBS6985,
|
|
.boot_mode = SAA716x_EXT_BOOT,
|
|
.adapters = 4,
|
|
.frontend_attach = saa716x_tbs6985_frontend_attach,
|
|
.irq_handler = saa716x_budget_pci_irq,
|
|
.i2c_rate = SAA716x_I2C_RATE_400,
|
|
.i2c_mode = SAA716x_I2C_MODE_POLLING,
|
|
.adap_config = {
|
|
{
|
|
/* adapter 0 */
|
|
.ts_port = 2,
|
|
.worker = demux_worker
|
|
},
|
|
{
|
|
/* adapter 1 */
|
|
.ts_port = 3,
|
|
.worker = demux_worker
|
|
},
|
|
{
|
|
/* adapter 2 */
|
|
.ts_port = 0,
|
|
.worker = demux_worker
|
|
},
|
|
{
|
|
/* adapter 3 */
|
|
.ts_port = 1,
|
|
.worker = demux_worker
|
|
}
|
|
},
|
|
};
|
|
|
|
|
|
#define SAA716x_MODEL_TBS6991 "TurboSight TBS 6991 "
|
|
#define SAA716x_DEV_TBS6991 "DVB-S/S2"
|
|
|
|
static void tbs6991_reset_fe(struct dvb_frontend *fe, int reset_pin)
|
|
{
|
|
struct i2c_adapter *adapter = tas2101_get_i2c_adapter(fe, 0);
|
|
struct saa716x_i2c *i2c = i2c_get_adapdata(adapter);
|
|
struct saa716x_dev *dev = i2c->saa716x;
|
|
|
|
/* reset frontend, active low */
|
|
saa716x_gpio_set_output(dev, reset_pin);
|
|
saa716x_gpio_write(dev, reset_pin, 0);
|
|
msleep(60);
|
|
saa716x_gpio_write(dev, reset_pin, 1);
|
|
msleep(120);
|
|
}
|
|
|
|
static void tbs6991_reset_fe0(struct dvb_frontend *fe)
|
|
{
|
|
tbs6991_reset_fe(fe, 20);
|
|
}
|
|
|
|
static void tbs6991_reset_fe1(struct dvb_frontend *fe)
|
|
{
|
|
tbs6991_reset_fe(fe, 17);
|
|
}
|
|
|
|
static void tbs6991_lnb_power(struct dvb_frontend *fe,
|
|
int enpwr_pin, int onoff)
|
|
{
|
|
struct i2c_adapter *adapter = tas2101_get_i2c_adapter(fe, 0);
|
|
struct saa716x_i2c *i2c = i2c_get_adapdata(adapter);
|
|
struct saa716x_dev *dev = i2c->saa716x;
|
|
|
|
/* lnb power, active low */
|
|
saa716x_gpio_set_output(dev, enpwr_pin);
|
|
if (onoff)
|
|
saa716x_gpio_write(dev, enpwr_pin, 0);
|
|
else
|
|
saa716x_gpio_write(dev, enpwr_pin, 1);
|
|
}
|
|
|
|
static void tbs6991_lnb0_power(struct dvb_frontend *fe, int onoff)
|
|
{
|
|
tbs6991_lnb_power(fe, 5, onoff);
|
|
}
|
|
|
|
static void tbs6991_lnb1_power(struct dvb_frontend *fe, int onoff)
|
|
{
|
|
tbs6991_lnb_power(fe, 26, onoff);
|
|
}
|
|
|
|
/*
|
|
tbs6991 seems to have different settings depending on a value that the closed
|
|
source driver reads from the eeprom. This is probabbly related to card HW revisons.
|
|
Details:
|
|
eeprom i2c addr = 0x1a
|
|
mem addr = 0xc201
|
|
if value == 0x66 or value == 0x68 then tsmode = 1 else 0
|
|
|
|
This needs to be tested and if needed implement a function to get that value
|
|
and set the proper tsmode
|
|
*/
|
|
#define TBS6991_TSMODE0 (0x33)
|
|
#define TBS6991_TSMODE1 (0x31)
|
|
#define TBS6991_TSMODE TBS6991_TSMODE1
|
|
static struct tas2101_config tbs6991_cfg[] = {
|
|
{
|
|
.i2c_address = 0x68,
|
|
.id = ID_TAS2100,
|
|
.reset_demod = tbs6991_reset_fe0,
|
|
.lnb_power = tbs6991_lnb0_power,
|
|
.init = {0x10, 0x32, 0x54, 0x76, 0xa8, 0x9b, TBS6991_TSMODE},
|
|
.init2 = 0,
|
|
},
|
|
{
|
|
.i2c_address = 0x68,
|
|
.id = ID_TAS2100,
|
|
.reset_demod = tbs6991_reset_fe1,
|
|
.lnb_power = tbs6991_lnb1_power,
|
|
.init = {0x30, 0x21, 0x54, 0x76, 0xb8, 0x9a, TBS6991_TSMODE},
|
|
.init2 = 0,
|
|
}
|
|
};
|
|
|
|
static struct av201x_config tbs6991_av201x_cfg = {
|
|
.i2c_address = 0x63,
|
|
.id = ID_AV2011,
|
|
.xtal_freq = 27000, /* kHz */
|
|
};
|
|
|
|
static int saa716x_tbs6991_frontend_attach(
|
|
struct saa716x_adapter *adapter, int count)
|
|
{
|
|
struct saa716x_dev *dev = adapter->saa716x;
|
|
u8 mac[6];
|
|
int ret;
|
|
|
|
dev_dbg(&dev->pdev->dev, "%s frontend %d attaching\n",
|
|
dev->config->model_name, count);
|
|
if (count > 1)
|
|
goto err;
|
|
|
|
adapter->fe = dvb_attach(tas2101_attach, &tbs6991_cfg[count],
|
|
&dev->i2c[1-count].i2c_adapter);
|
|
if (adapter->fe == NULL)
|
|
goto err;
|
|
|
|
if (dvb_attach(av201x_attach, adapter->fe, &tbs6991_av201x_cfg,
|
|
tas2101_get_i2c_adapter(adapter->fe, 2)) == NULL) {
|
|
dvb_frontend_detach(adapter->fe);
|
|
adapter->fe = NULL;
|
|
dev_dbg(&dev->pdev->dev,
|
|
"%s frontend %d tuner attach failed\n",
|
|
dev->config->model_name, count);
|
|
goto err;
|
|
}
|
|
|
|
saa716x_gpio_set_input(dev,count?3:14);
|
|
msleep(1);
|
|
saa716x_gpio_set_input(dev,count?6:2);
|
|
msleep(1);
|
|
ret = tbsci_i2c_probe(adapter,count?4:3);
|
|
if(!ret)
|
|
tbsci_init(adapter,count,2);
|
|
|
|
strscpy(adapter->fe->ops.info.name,dev->config->model_name,52);
|
|
strlcat(adapter->fe->ops.info.name,dev->config->dev_type,52);
|
|
|
|
dev_dbg(&dev->pdev->dev, "%s frontend %d attached\n",
|
|
dev->config->model_name, count);
|
|
|
|
if (!saa716x_tbs_read_mac(dev,count,mac)) {
|
|
memcpy(adapter->dvb_adapter.proposed_mac, mac, 6);
|
|
dev_notice(&dev->pdev->dev, "%s MAC=%pM\n", dev->config->model_name, adapter->dvb_adapter.proposed_mac);
|
|
}
|
|
|
|
return 0;
|
|
err:
|
|
dev_err(&dev->pdev->dev, "%s frontend %d attach failed\n",
|
|
dev->config->model_name, count);
|
|
return -ENODEV;
|
|
}
|
|
|
|
static struct saa716x_config saa716x_tbs6991_config = {
|
|
.model_name = SAA716x_MODEL_TBS6991,
|
|
.dev_type = SAA716x_DEV_TBS6991,
|
|
.boot_mode = SAA716x_EXT_BOOT,
|
|
.adapters = 2,
|
|
.frontend_attach = saa716x_tbs6991_frontend_attach,
|
|
.irq_handler = saa716x_budget_pci_irq,
|
|
.i2c_rate = SAA716x_I2C_RATE_400,
|
|
.i2c_mode = SAA716x_I2C_MODE_POLLING,
|
|
.adap_config = {
|
|
{
|
|
/* adapter 0 */
|
|
.ts_port = 1, /* using FGPI 3 */
|
|
.worker = demux_worker
|
|
},
|
|
{
|
|
/* adapter 1 */
|
|
.ts_port = 3, /* using FGPI 1 */
|
|
.worker = demux_worker
|
|
},
|
|
},
|
|
};
|
|
|
|
|
|
#define SAA716x_MODEL_TBS6991SE "TurboSight TBS 6991SE "
|
|
#define SAA716x_DEV_TBS6991SE "DVB-S/S2 "
|
|
|
|
static struct tas2101_config tbs6991se_cfg[] = {
|
|
{
|
|
.i2c_address = 0x68,
|
|
.id = ID_TAS2101,
|
|
.reset_demod = NULL,
|
|
.lnb_power = tbs6991_lnb0_power,
|
|
.init = {0x10, 0x32, 0x54, 0x76, 0x8b, 0x9a, 0x33},
|
|
.init2 = 0,
|
|
},
|
|
{
|
|
.i2c_address = 0x68,
|
|
.id = ID_TAS2101,
|
|
.reset_demod = NULL,
|
|
.lnb_power = tbs6991_lnb1_power,
|
|
.init = {0x10, 0x32, 0x54, 0x76, 0x8b, 0x9a, 0x33},
|
|
.init2 = 0,
|
|
}
|
|
};
|
|
|
|
static struct av201x_config tbs6991se_av201x_cfg = {
|
|
.i2c_address = 0x63,
|
|
.id = ID_AV2012,
|
|
.xtal_freq = 27000, /* kHz */
|
|
};
|
|
|
|
static int saa716x_tbs6991se_frontend_attach(
|
|
struct saa716x_adapter *adapter, int count)
|
|
{
|
|
struct saa716x_dev *dev = adapter->saa716x;
|
|
u8 mac[6];
|
|
int ret;
|
|
|
|
dev_dbg(&dev->pdev->dev, "%s frontend %d attaching\n",
|
|
dev->config->model_name, count);
|
|
if (count > 1)
|
|
goto err;
|
|
|
|
adapter->fe = dvb_attach(tas2101_attach, &tbs6991se_cfg[count],
|
|
&dev->i2c[1-count].i2c_adapter);
|
|
if (adapter->fe == NULL)
|
|
goto err;
|
|
|
|
if (dvb_attach(av201x_attach, adapter->fe, &tbs6991se_av201x_cfg,
|
|
tas2101_get_i2c_adapter(adapter->fe, 2)) == NULL) {
|
|
dvb_frontend_detach(adapter->fe);
|
|
adapter->fe = NULL;
|
|
dev_dbg(&dev->pdev->dev,
|
|
"%s frontend %d tuner attach failed\n",
|
|
dev->config->model_name, count);
|
|
goto err;
|
|
}
|
|
saa716x_gpio_set_input(dev,count ?6:2);
|
|
msleep(1);
|
|
saa716x_gpio_set_input(dev,count?3:14);
|
|
msleep(1);
|
|
saa716x_gpio_set_output(dev,count?17:20);
|
|
msleep(1);
|
|
ret = tbsci_i2c_probe(adapter,count?4:3);
|
|
if(!ret)
|
|
tbsci_init(adapter,count,8);
|
|
|
|
strscpy(adapter->fe->ops.info.name,dev->config->model_name,52);
|
|
strlcat(adapter->fe->ops.info.name,dev->config->dev_type,52);
|
|
|
|
dev_dbg(&dev->pdev->dev, "%s frontend %d attached\n",
|
|
dev->config->model_name, count);
|
|
|
|
if (!saa716x_tbs_read_mac(dev,count,mac)) {
|
|
memcpy(adapter->dvb_adapter.proposed_mac, mac, 6);
|
|
dev_notice(&dev->pdev->dev, "%s MAC=%pM\n", dev->config->model_name, adapter->dvb_adapter.proposed_mac);
|
|
}
|
|
|
|
return 0;
|
|
err:
|
|
dev_err(&dev->pdev->dev, "%s frontend %d attach failed\n",
|
|
dev->config->model_name, count);
|
|
return -ENODEV;
|
|
}
|
|
|
|
static struct saa716x_config saa716x_tbs6991se_config = {
|
|
.model_name = SAA716x_MODEL_TBS6991SE,
|
|
.dev_type = SAA716x_DEV_TBS6991SE,
|
|
.boot_mode = SAA716x_EXT_BOOT,
|
|
.adapters = 2,
|
|
.frontend_attach = saa716x_tbs6991se_frontend_attach,
|
|
.irq_handler = saa716x_budget_pci_irq,
|
|
.i2c_rate = SAA716x_I2C_RATE_400,
|
|
.i2c_mode = SAA716x_I2C_MODE_POLLING,
|
|
.adap_config = {
|
|
{
|
|
/* adapter 0 */
|
|
.ts_port = 1, /* using FGPI 3 */
|
|
.worker = demux_worker
|
|
},
|
|
{
|
|
/* adapter 1 */
|
|
.ts_port = 3, /* using FGPI 1 */
|
|
.worker = demux_worker
|
|
},
|
|
},
|
|
};
|
|
|
|
#define SAA716x_MODEL_TBS6983 "TurboSight TBS 6983 "
|
|
#define SAA716x_DEV_TBS6983 "DVB-S/S2"
|
|
|
|
static struct stv091x_cfg tbs6983_stv0910_cfg = {
|
|
.adr = 0x68,
|
|
.parallel = 1,
|
|
.rptlvl = 3,
|
|
.clk = 30000000,
|
|
.dual_tuner = 1,
|
|
};
|
|
|
|
static struct stv6120_cfg tbs6983_stv6120_cfg = {
|
|
.adr = 0x60,
|
|
.xtal = 30000,
|
|
.Rdiv = 2,
|
|
};
|
|
|
|
static int saa716x_tbs6983_set_voltage(struct dvb_frontend *fe, enum fe_sec_voltage voltage)
|
|
{
|
|
struct saa716x_adapter *adapter = fe->dvb->priv;
|
|
struct saa716x_dev *saa716x = adapter->saa716x;
|
|
|
|
u8 adapter_gpio_0 = adapter->count ? 16 : 5;
|
|
u8 adapter_gpio_1 = adapter->count ? 2 : 3;
|
|
|
|
saa716x_gpio_set_output(saa716x, adapter_gpio_0);
|
|
saa716x_gpio_set_output(saa716x, adapter_gpio_1);
|
|
msleep(1);
|
|
|
|
switch (voltage) {
|
|
case SEC_VOLTAGE_13:
|
|
saa716x_gpio_write(saa716x, adapter_gpio_0, 0);
|
|
saa716x_gpio_write(saa716x, adapter_gpio_1, 0);
|
|
break;
|
|
case SEC_VOLTAGE_18:
|
|
saa716x_gpio_write(saa716x, adapter_gpio_0, 1);
|
|
saa716x_gpio_write(saa716x, adapter_gpio_1, 0);
|
|
break;
|
|
case SEC_VOLTAGE_OFF:
|
|
saa716x_gpio_write(saa716x, adapter_gpio_0, 1);
|
|
saa716x_gpio_write(saa716x, adapter_gpio_1, 1);
|
|
break;
|
|
default:
|
|
return -EINVAL;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int saa716x_tbs6983_frontend_attach(struct saa716x_adapter *adapter, int count)
|
|
{
|
|
struct saa716x_dev *dev = adapter->saa716x;
|
|
u8 mac[6];
|
|
|
|
dev_dbg(&dev->pdev->dev, "%s frontend %d attaching\n",
|
|
dev->config->model_name, count);
|
|
|
|
if (count == 0) {
|
|
saa716x_gpio_set_output(dev, 17);
|
|
msleep(1);
|
|
saa716x_gpio_write(dev, 17, 0);
|
|
msleep(50);
|
|
saa716x_gpio_write(dev, 17, 1);
|
|
msleep(100);
|
|
}
|
|
|
|
adapter->fe = dvb_attach(stv091x_attach,
|
|
&dev->i2c[1].i2c_adapter,
|
|
&tbs6983_stv0910_cfg,
|
|
count & 1);
|
|
|
|
if (adapter->fe == NULL) {
|
|
goto err;
|
|
}
|
|
|
|
if (dvb_attach(stv6120_attach, adapter->fe, &dev->i2c[1].i2c_adapter,
|
|
&tbs6983_stv6120_cfg,1 - (count & 1)) == NULL) {
|
|
dvb_frontend_detach(adapter->fe);
|
|
adapter->fe = NULL;
|
|
dev_dbg(&dev->pdev->dev,
|
|
"%s frontend %d tuner attach failed\n",
|
|
dev->config->model_name, count);
|
|
goto err;
|
|
}
|
|
|
|
if (adapter->fe->ops.init)
|
|
adapter->fe->ops.init(adapter->fe);
|
|
|
|
dev_dbg(&dev->pdev->dev, "%s frontend %d attached\n",
|
|
dev->config->model_name, count);
|
|
|
|
adapter->fe->ops.set_voltage = saa716x_tbs6983_set_voltage;
|
|
saa716x_gpio_write(dev, count ? 2 : 3, 1); /* LNB power off */
|
|
|
|
strscpy(adapter->fe->ops.info.name,dev->config->model_name,52);
|
|
strlcat(adapter->fe->ops.info.name,dev->config->dev_type,52);
|
|
|
|
dev_dbg(&dev->pdev->dev, "%s frontend %d attached\n",
|
|
dev->config->model_name, count);
|
|
|
|
if (!saa716x_tbs_read_mac(dev,count,mac)) {
|
|
memcpy(adapter->dvb_adapter.proposed_mac, mac, 6);
|
|
dev_notice(&dev->pdev->dev, "%s MAC[%d]=%pM\n", dev->config->model_name, count, adapter->dvb_adapter.proposed_mac);
|
|
}
|
|
|
|
return 0;
|
|
err:
|
|
dev_err(&dev->pdev->dev, "%s frontend %d attach failed\n",
|
|
dev->config->model_name, count);
|
|
return -ENODEV;
|
|
}
|
|
|
|
static struct saa716x_config saa716x_tbs6983_config = {
|
|
.model_name = SAA716x_MODEL_TBS6983,
|
|
.dev_type = SAA716x_DEV_TBS6983,
|
|
.boot_mode = SAA716x_EXT_BOOT,
|
|
.adapters = 2,
|
|
.frontend_attach = saa716x_tbs6983_frontend_attach,
|
|
.irq_handler = saa716x_budget_pci_irq,
|
|
.i2c_rate = SAA716x_I2C_RATE_400,
|
|
.i2c_mode = SAA716x_I2C_MODE_POLLING,
|
|
.adap_config = {
|
|
{ // adapter 0
|
|
.ts_port = 3,
|
|
.worker = demux_worker
|
|
},
|
|
{ // adapter 1
|
|
.ts_port = 1,
|
|
.worker = demux_worker
|
|
},
|
|
}
|
|
};
|
|
#define SAA716x_MODEL_TBS6290 "TurboSight TBS 6290 "
|
|
#define SAA716x_DEV_TBS6290 "DVB-T/T2/C+2xCI"
|
|
|
|
static int saa716x_tbs6290_frontend_attach(struct saa716x_adapter *adapter, int count)
|
|
{
|
|
struct saa716x_dev *dev = adapter->saa716x;
|
|
struct i2c_adapter *i2cadapter;
|
|
struct i2c_client *client;
|
|
struct i2c_board_info info;
|
|
struct si2168_config si2168_config;
|
|
struct si2157_config si2157_config;
|
|
u8 mac[6];
|
|
int ret;
|
|
if (count > 1)
|
|
goto err;
|
|
|
|
/* attach demod */
|
|
memset(&si2168_config, 0, sizeof(si2168_config));
|
|
si2168_config.i2c_adapter = &i2cadapter;
|
|
si2168_config.fe = &adapter->fe;
|
|
si2168_config.ts_mode = SI2168_TS_PARALLEL;
|
|
si2168_config.ts_clock_gapped = true;
|
|
memset(&info, 0, sizeof(struct i2c_board_info));
|
|
strscpy(info.type, "si2168", I2C_NAME_SIZE);
|
|
info.addr = 0x64;
|
|
info.platform_data = &si2168_config;
|
|
request_module(info.type);
|
|
client = i2c_new_client_device(&dev->i2c[1 - count].i2c_adapter, &info);
|
|
if (!i2c_client_has_driver(client)) {
|
|
goto err;
|
|
}
|
|
if (!try_module_get(client->dev.driver->owner)) {
|
|
i2c_unregister_device(client);
|
|
goto err;
|
|
}
|
|
adapter->i2c_client_demod = client;
|
|
|
|
/* attach tuner */
|
|
memset(&si2157_config, 0, sizeof(si2157_config));
|
|
si2157_config.fe = adapter->fe;
|
|
si2157_config.if_port = 1;
|
|
memset(&info, 0, sizeof(struct i2c_board_info));
|
|
strscpy(info.type, "si2157", I2C_NAME_SIZE);
|
|
info.addr = 0x60;
|
|
info.platform_data = &si2157_config;
|
|
request_module(info.type);
|
|
client = i2c_new_client_device(i2cadapter, &info);
|
|
if (!i2c_client_has_driver(client)) {
|
|
module_put(adapter->i2c_client_demod->dev.driver->owner);
|
|
i2c_unregister_device(adapter->i2c_client_demod);
|
|
goto err;
|
|
}
|
|
if (!try_module_get(client->dev.driver->owner)) {
|
|
i2c_unregister_device(client);
|
|
module_put(adapter->i2c_client_demod->dev.driver->owner);
|
|
i2c_unregister_device(adapter->i2c_client_demod);
|
|
goto err;
|
|
}
|
|
adapter->i2c_client_tuner = client;
|
|
|
|
saa716x_gpio_set_input(dev,count?2:6);
|
|
msleep(1);
|
|
saa716x_gpio_set_input(dev,count?14:3);
|
|
msleep(1);
|
|
saa716x_gpio_set_input(dev,count?20:14);
|
|
msleep(1);
|
|
ret = tbsci_i2c_probe(adapter,count?4:3);
|
|
if(!ret)
|
|
tbsci_init(adapter,count,9);
|
|
|
|
strscpy(adapter->fe->ops.info.name,dev->config->model_name,52);
|
|
strlcat(adapter->fe->ops.info.name,dev->config->dev_type,52);
|
|
|
|
dev_dbg(&dev->pdev->dev, "%s frontend %d attached\n",
|
|
dev->config->model_name, count);
|
|
|
|
if (!saa716x_tbs_read_mac(dev,count,mac)) {
|
|
memcpy(adapter->dvb_adapter.proposed_mac, mac, 6);
|
|
dev_notice(&dev->pdev->dev, "%s MAC[%d]=%pM\n", dev->config->model_name, count, adapter->dvb_adapter.proposed_mac);
|
|
}
|
|
|
|
return 0;
|
|
err:
|
|
dev_err(&dev->pdev->dev, "%s frontend %d attach failed\n",
|
|
dev->config->model_name, count);
|
|
return -ENODEV;
|
|
|
|
|
|
}
|
|
|
|
static struct saa716x_config saa716x_tbs6290_config = {
|
|
.model_name = SAA716x_MODEL_TBS6290,
|
|
.dev_type = SAA716x_DEV_TBS6290,
|
|
.boot_mode = SAA716x_EXT_BOOT,
|
|
.adapters = 2,
|
|
.frontend_attach = saa716x_tbs6290_frontend_attach,
|
|
.irq_handler = saa716x_budget_pci_irq,
|
|
.i2c_rate = SAA716x_I2C_RATE_100,
|
|
.i2c_mode = SAA716x_I2C_MODE_POLLING,
|
|
.adap_config ={
|
|
{
|
|
.ts_port = 1,
|
|
.worker = demux_worker
|
|
},
|
|
{
|
|
.ts_port = 3,
|
|
.worker = demux_worker
|
|
},
|
|
|
|
}
|
|
|
|
};
|
|
static struct pci_device_id saa716x_budget_pci_table[] = {
|
|
MAKE_ENTRY(TWINHAN_TECHNOLOGIES, TWINHAN_VP_1028, SAA7160, &saa716x_vp1028_config), /* VP-1028 */
|
|
MAKE_ENTRY(TWINHAN_TECHNOLOGIES, TWINHAN_VP_3071, SAA7160, &saa716x_vp3071_config), /* VP-3071 */
|
|
MAKE_ENTRY(TWINHAN_TECHNOLOGIES, TWINHAN_VP_6002, SAA7160, &saa716x_vp6002_config), /* VP-6002 */
|
|
MAKE_ENTRY(KNC_One, KNC_Dual_S2, SAA7160, &saa716x_knc1_duals2_config),
|
|
MAKE_ENTRY(TECHNISAT, SKYSTAR2_EXPRESS_HD, SAA7160, &skystar2_express_hd_config),
|
|
MAKE_ENTRY(TURBOSIGHT_TBS6284, TBS6284, SAA7160, &saa716x_tbs6284_config),
|
|
MAKE_ENTRY(TURBOSIGHT_TBS6280, TBS6280, SAA7160, &saa716x_tbs6280_config),
|
|
MAKE_ENTRY(TURBOSIGHT_TBS6281, TBS6281, SAA7160, &saa716x_tbs6281_config),
|
|
MAKE_ENTRY(TURBOSIGHT_TBS6285, TBS6285, SAA7160, &saa716x_tbs6285_config),
|
|
MAKE_ENTRY(TURBOSIGHT_TBS6220, TBS6220, SAA7160, &saa716x_tbs6220_config),
|
|
MAKE_ENTRY(TURBOSIGHT_TBS6221, TBS6221, SAA7160, &saa716x_tbs6221_config),
|
|
MAKE_ENTRY(TURBOSIGHT_TBS6922, TBS6922, SAA7160, &saa716x_tbs6922_config),
|
|
MAKE_ENTRY(TURBOSIGHT_TBS6923, TBS6923, SAA7160, &saa716x_tbs6923_config),
|
|
MAKE_ENTRY(TURBOSIGHT_TBS6925, TBS6925, SAA7160, &saa716x_tbs6925_config),
|
|
MAKE_ENTRY(TURBOSIGHT_TBS6982, TBS6982, SAA7160, &saa716x_tbs6982_config),
|
|
MAKE_ENTRY(TURBOSIGHT_TBS6982, TBS6982SE, SAA7160, &saa716x_tbs6982se_config),
|
|
MAKE_ENTRY(TURBOSIGHT_TBS6984, TBS6984, SAA7160, &saa716x_tbs6984_config),
|
|
MAKE_ENTRY(TURBOSIGHT_TBS6985, TBS6985, SAA7160, &saa716x_tbs6985_config),
|
|
MAKE_ENTRY(TURBOSIGHT_TBS6985, TBS6985+1, SAA7160, &saa716x_tbs6985_config),
|
|
MAKE_ENTRY(TURBOSIGHT_TBS6991, TBS6991, SAA7160, &saa716x_tbs6991_config),
|
|
MAKE_ENTRY(TURBOSIGHT_TBS6991, TBS6991+1, SAA7160, &saa716x_tbs6991se_config),
|
|
MAKE_ENTRY(TECHNOTREND, TT4100, SAA7160, &saa716x_tbs6922_config),
|
|
MAKE_ENTRY(TURBOSIGHT_TBS6983, TBS6983, SAA7160, &saa716x_tbs6983_config),
|
|
MAKE_ENTRY(TURBOSIGHT_TBS6983, TBS6983+1, SAA7160, &saa716x_tbs6983_config),
|
|
MAKE_ENTRY(TURBOSIGHT_TBS7220, TBS7220, SAA7160, &saa716x_tbs7220_config),
|
|
MAKE_ENTRY(TURBOSIGHT_TBS6290, TBS6290, SAA7160, &saa716x_tbs6290_config),
|
|
{ }
|
|
};
|
|
MODULE_DEVICE_TABLE(pci, saa716x_budget_pci_table);
|
|
|
|
static struct pci_driver saa716x_budget_pci_driver = {
|
|
.name = DRIVER_NAME,
|
|
.id_table = saa716x_budget_pci_table,
|
|
.probe = saa716x_budget_pci_probe,
|
|
.remove = saa716x_budget_pci_remove,
|
|
};
|
|
|
|
module_pci_driver(saa716x_budget_pci_driver);
|
|
|
|
MODULE_DESCRIPTION("SAA716x Budget driver");
|
|
MODULE_AUTHOR("Manu Abraham");
|
|
MODULE_LICENSE("GPL");
|