V4L/DVB (13493): TeVii S470 and TBS 6920 fixes
The new hardware design applied for this cards. Silicon Labs C8051F300 microcontroller is used for LNB power control. It connected to cx23885 GPIO pins: GPIO0 - P0.3 data GPIO1 - P0.2 reset GPIO2 - P0.1 clk GPIO3 - P0.0 busy Tevii S470 based on Montage Technology M88TS2020 digital satellite tuner and M88DS3000 advanced DVB-S/S2 demodulator. Signed-off-by: Igor M. Liplianin <liplianin@me.by> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
This commit is contained in:
parent
6afd2aa856
commit
09ea33e5c6
|
@ -201,6 +201,13 @@ config DVB_SI21XX
|
|||
help
|
||||
A DVB-S tuner module. Say Y when you want to support this frontend.
|
||||
|
||||
config DVB_DS3000
|
||||
tristate "Montage Tehnology DS3000 based"
|
||||
depends on DVB_CORE && I2C
|
||||
default m if DVB_FE_CUSTOMISE
|
||||
help
|
||||
A DVB-S/S2 tuner module. Say Y when you want to support this frontend.
|
||||
|
||||
comment "DVB-T (terrestrial) frontends"
|
||||
depends on DVB_CORE
|
||||
|
||||
|
|
|
@ -78,3 +78,4 @@ obj-$(CONFIG_DVB_STV090x) += stv090x.o
|
|||
obj-$(CONFIG_DVB_STV6110x) += stv6110x.o
|
||||
obj-$(CONFIG_DVB_ISL6423) += isl6423.o
|
||||
obj-$(CONFIG_DVB_EC100) += ec100.o
|
||||
obj-$(CONFIG_DVB_DS3000) += ds3000.o
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,45 @@
|
|||
/*
|
||||
Montage Technology DS3000/TS2020 - DVBS/S2 Satellite demod/tuner driver
|
||||
Copyright (C) 2009 Konstantin Dimitrov <kosio.dimitrov@gmail.com>
|
||||
|
||||
Copyright (C) 2009 TurboSight.com
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#ifndef DS3000_H
|
||||
#define DS3000_H
|
||||
|
||||
#include <linux/dvb/frontend.h>
|
||||
|
||||
struct ds3000_config {
|
||||
/* the demodulator's i2c address */
|
||||
u8 demod_address;
|
||||
};
|
||||
|
||||
#if defined(CONFIG_DVB_DS3000) || \
|
||||
(defined(CONFIG_DVB_DS3000_MODULE) && defined(MODULE))
|
||||
extern struct dvb_frontend *ds3000_attach(const struct ds3000_config *config,
|
||||
struct i2c_adapter *i2c);
|
||||
#else
|
||||
static inline
|
||||
struct dvb_frontend *ds3000_attach(const struct ds3000_config *config,
|
||||
struct i2c_adapter *i2c)
|
||||
{
|
||||
printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
|
||||
return NULL;
|
||||
}
|
||||
#endif /* CONFIG_DVB_DS3000 */
|
||||
#endif /* DS3000_H */
|
|
@ -18,7 +18,9 @@ config VIDEO_CX23885
|
|||
select DVB_TDA10048 if !DVB_FE_CUSTOMISE
|
||||
select DVB_LNBP21 if !DVB_FE_CUSTOMISE
|
||||
select DVB_STV6110 if !DVB_FE_CUSTOMISE
|
||||
select DVB_CX24116 if !DVB_FE_CUSTOMISE
|
||||
select DVB_STV0900 if !DVB_FE_CUSTOMISE
|
||||
select DVB_DS3000 if !DVB_FE_CUSTOMISE
|
||||
select MEDIA_TUNER_MT2131 if !MEDIA_TUNER_CUSTOMISE
|
||||
select MEDIA_TUNER_XC2028 if !MEDIA_TUNER_CUSTOMISE
|
||||
select MEDIA_TUNER_TDA8290 if !MEDIA_TUNER_CUSTOMISE
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
cx23885-objs := cx23885-cards.o cx23885-video.o cx23885-vbi.o \
|
||||
cx23885-core.o cx23885-i2c.o cx23885-dvb.o cx23885-417.o \
|
||||
cx23885-ioctl.o cx23885-ir.o cx23885-input.o cx23888-ir.o \
|
||||
netup-init.o cimax2.o netup-eeprom.o
|
||||
netup-init.o cimax2.o netup-eeprom.o cx23885-f300.o
|
||||
|
||||
obj-$(CONFIG_VIDEO_CX23885) += cx23885.o
|
||||
|
||||
|
|
|
@ -782,10 +782,14 @@ void cx23885_gpio_setup(struct cx23885_dev *dev)
|
|||
cx_set(GP0_IO, 0x00040004);
|
||||
break;
|
||||
case CX23885_BOARD_TBS_6920:
|
||||
case CX23885_BOARD_TEVII_S470:
|
||||
cx_write(MC417_CTL, 0x00000036);
|
||||
cx_write(MC417_OEN, 0x00001000);
|
||||
cx_write(MC417_RWD, 0x00001800);
|
||||
cx_set(MC417_RWD, 0x00000002);
|
||||
mdelay(200);
|
||||
cx_clear(MC417_RWD, 0x00000800);
|
||||
mdelay(200);
|
||||
cx_set(MC417_RWD, 0x00000800);
|
||||
mdelay(200);
|
||||
break;
|
||||
case CX23885_BOARD_NETUP_DUAL_DVBS2_CI:
|
||||
/* GPIO-0 INTA from CiMax1
|
||||
|
@ -1002,8 +1006,12 @@ void cx23885_card_setup(struct cx23885_dev *dev)
|
|||
ts2->ts_clk_en_val = 0x1; /* Enable TS_CLK */
|
||||
ts2->src_sel_val = CX23885_SRC_SEL_PARALLEL_MPEG_VIDEO;
|
||||
break;
|
||||
case CX23885_BOARD_TEVII_S470:
|
||||
case CX23885_BOARD_TBS_6920:
|
||||
ts1->gen_ctrl_val = 0x4; /* Parallel */
|
||||
ts1->ts_clk_en_val = 0x1; /* Enable TS_CLK */
|
||||
ts1->src_sel_val = CX23885_SRC_SEL_PARALLEL_MPEG_VIDEO;
|
||||
break;
|
||||
case CX23885_BOARD_TEVII_S470:
|
||||
case CX23885_BOARD_DVBWORLD_2005:
|
||||
ts1->gen_ctrl_val = 0x5; /* Parallel */
|
||||
ts1->ts_clk_en_val = 0x1; /* Enable TS_CLK */
|
||||
|
|
|
@ -1871,6 +1871,26 @@ void cx23885_gpio_clear(struct cx23885_dev *dev, u32 mask)
|
|||
printk(KERN_INFO "%s: Unsupported\n", dev->name);
|
||||
}
|
||||
|
||||
u32 cx23885_gpio_get(struct cx23885_dev *dev, u32 mask)
|
||||
{
|
||||
if (mask & 0x00000007)
|
||||
return (cx_read(GP0_IO) >> 8) & mask & 0x7;
|
||||
|
||||
if (mask & 0x0007fff8) {
|
||||
if (encoder_on_portb(dev) || encoder_on_portc(dev))
|
||||
printk(KERN_ERR
|
||||
"%s: Reading GPIO moving on encoder ports\n",
|
||||
dev->name);
|
||||
return (cx_read(MC417_RWD) & ((mask & 0x7fff8) >> 3)) << 3;
|
||||
}
|
||||
|
||||
/* TODO: 23-19 */
|
||||
if (mask & 0x00f80000)
|
||||
printk(KERN_INFO "%s: Unsupported\n", dev->name);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void cx23885_gpio_enable(struct cx23885_dev *dev, u32 mask, int asoutput)
|
||||
{
|
||||
if ((mask & 0x00000007) && asoutput)
|
||||
|
|
|
@ -56,6 +56,8 @@
|
|||
#include "netup-init.h"
|
||||
#include "lgdt3305.h"
|
||||
#include "atbm8830.h"
|
||||
#include "ds3000.h"
|
||||
#include "cx23885-f300.h"
|
||||
|
||||
static unsigned int debug;
|
||||
|
||||
|
@ -427,26 +429,12 @@ static struct stv6110_config netup_stv6110_tunerconfig_b = {
|
|||
.gain = 8, /* +16 dB - maximum gain */
|
||||
};
|
||||
|
||||
static int tbs_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage)
|
||||
{
|
||||
struct cx23885_tsport *port = fe->dvb->priv;
|
||||
struct cx23885_dev *dev = port->dev;
|
||||
|
||||
if (voltage == SEC_VOLTAGE_18)
|
||||
cx_write(MC417_RWD, 0x00001e00);/* GPIO-13 high */
|
||||
else if (voltage == SEC_VOLTAGE_13)
|
||||
cx_write(MC417_RWD, 0x00001a00);/* GPIO-13 low */
|
||||
else
|
||||
cx_write(MC417_RWD, 0x00001800);/* GPIO-12 low */
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct cx24116_config tbs_cx24116_config = {
|
||||
.demod_address = 0x05,
|
||||
.demod_address = 0x55,
|
||||
};
|
||||
|
||||
static struct cx24116_config tevii_cx24116_config = {
|
||||
.demod_address = 0x55,
|
||||
static struct ds3000_config tevii_ds3000_config = {
|
||||
.demod_address = 0x68,
|
||||
};
|
||||
|
||||
static struct cx24116_config dvbworld_cx24116_config = {
|
||||
|
@ -832,23 +820,23 @@ static int dvb_register(struct cx23885_tsport *port)
|
|||
}
|
||||
break;
|
||||
case CX23885_BOARD_TBS_6920:
|
||||
i2c_bus = &dev->i2c_bus[0];
|
||||
i2c_bus = &dev->i2c_bus[1];
|
||||
|
||||
fe0->dvb.frontend = dvb_attach(cx24116_attach,
|
||||
&tbs_cx24116_config,
|
||||
&i2c_bus->i2c_adap);
|
||||
&tbs_cx24116_config,
|
||||
&i2c_bus->i2c_adap);
|
||||
if (fe0->dvb.frontend != NULL)
|
||||
fe0->dvb.frontend->ops.set_voltage = tbs_set_voltage;
|
||||
fe0->dvb.frontend->ops.set_voltage = f300_set_voltage;
|
||||
|
||||
break;
|
||||
case CX23885_BOARD_TEVII_S470:
|
||||
i2c_bus = &dev->i2c_bus[1];
|
||||
|
||||
fe0->dvb.frontend = dvb_attach(cx24116_attach,
|
||||
&tevii_cx24116_config,
|
||||
&i2c_bus->i2c_adap);
|
||||
fe0->dvb.frontend = dvb_attach(ds3000_attach,
|
||||
&tevii_ds3000_config,
|
||||
&i2c_bus->i2c_adap);
|
||||
if (fe0->dvb.frontend != NULL)
|
||||
fe0->dvb.frontend->ops.set_voltage = tbs_set_voltage;
|
||||
fe0->dvb.frontend->ops.set_voltage = f300_set_voltage;
|
||||
|
||||
break;
|
||||
case CX23885_BOARD_DVBWORLD_2005:
|
||||
|
|
|
@ -0,0 +1,177 @@
|
|||
/*
|
||||
* Driver for Silicon Labs C8051F300 microcontroller.
|
||||
*
|
||||
* It is used for LNB power control in TeVii S470,
|
||||
* TBS 6920 PCIe DVB-S2 cards.
|
||||
*
|
||||
* Microcontroller connected to cx23885 GPIO pins:
|
||||
* GPIO0 - data - P0.3 F300
|
||||
* GPIO1 - reset - P0.2 F300
|
||||
* GPIO2 - clk - P0.1 F300
|
||||
* GPIO3 - busy - P0.0 F300
|
||||
*
|
||||
* Copyright (C) 2009 Igor M. Liplianin <liplianin@me.by>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
*
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#include "cx23885.h"
|
||||
|
||||
#define F300_DATA GPIO_0
|
||||
#define F300_RESET GPIO_1
|
||||
#define F300_CLK GPIO_2
|
||||
#define F300_BUSY GPIO_3
|
||||
|
||||
static void f300_set_line(struct cx23885_dev *dev, u32 line, u8 lvl)
|
||||
{
|
||||
cx23885_gpio_enable(dev, line, 1);
|
||||
if (lvl == 1)
|
||||
cx23885_gpio_set(dev, line);
|
||||
else
|
||||
cx23885_gpio_clear(dev, line);
|
||||
}
|
||||
|
||||
static u8 f300_get_line(struct cx23885_dev *dev, u32 line)
|
||||
{
|
||||
cx23885_gpio_enable(dev, line, 0);
|
||||
|
||||
return cx23885_gpio_get(dev, line);
|
||||
}
|
||||
|
||||
static void f300_send_byte(struct cx23885_dev *dev, u8 dta)
|
||||
{
|
||||
u8 i;
|
||||
|
||||
for (i = 0; i < 8; i++) {
|
||||
f300_set_line(dev, F300_CLK, 0);
|
||||
udelay(30);
|
||||
f300_set_line(dev, F300_DATA, (dta & 0x80) >> 7);/* msb first */
|
||||
udelay(30);
|
||||
dta <<= 1;
|
||||
f300_set_line(dev, F300_CLK, 1);
|
||||
udelay(30);
|
||||
}
|
||||
}
|
||||
|
||||
static u8 f300_get_byte(struct cx23885_dev *dev)
|
||||
{
|
||||
u8 i, dta = 0;
|
||||
|
||||
for (i = 0; i < 8; i++) {
|
||||
f300_set_line(dev, F300_CLK, 0);
|
||||
udelay(30);
|
||||
dta <<= 1;
|
||||
f300_set_line(dev, F300_CLK, 1);
|
||||
udelay(30);
|
||||
dta |= f300_get_line(dev, F300_DATA);/* msb first */
|
||||
|
||||
}
|
||||
|
||||
return dta;
|
||||
}
|
||||
|
||||
static u8 f300_xfer(struct dvb_frontend *fe, u8 *buf)
|
||||
{
|
||||
struct cx23885_tsport *port = fe->dvb->priv;
|
||||
struct cx23885_dev *dev = port->dev;
|
||||
u8 i, temp, ret = 0;
|
||||
|
||||
temp = buf[0];
|
||||
for (i = 0; i < buf[0]; i++)
|
||||
temp += buf[i + 1];
|
||||
temp = (~temp + 1);/* get check sum */
|
||||
buf[1 + buf[0]] = temp;
|
||||
|
||||
f300_set_line(dev, F300_RESET, 1);
|
||||
f300_set_line(dev, F300_CLK, 1);
|
||||
udelay(30);
|
||||
f300_set_line(dev, F300_DATA, 1);
|
||||
msleep(1);
|
||||
|
||||
/* question: */
|
||||
f300_set_line(dev, F300_RESET, 0);/* begin to send data */
|
||||
msleep(1);
|
||||
|
||||
f300_send_byte(dev, 0xe0);/* the slave address is 0xe0, write */
|
||||
msleep(1);
|
||||
|
||||
temp = buf[0];
|
||||
temp += 2;
|
||||
for (i = 0; i < temp; i++)
|
||||
f300_send_byte(dev, buf[i]);
|
||||
|
||||
f300_set_line(dev, F300_RESET, 1);/* sent data over */
|
||||
f300_set_line(dev, F300_DATA, 1);
|
||||
|
||||
/* answer: */
|
||||
temp = 0;
|
||||
for (i = 0; ((i < 8) & (temp == 0)); i++) {
|
||||
msleep(1);
|
||||
if (f300_get_line(dev, F300_BUSY) == 0)
|
||||
temp = 1;
|
||||
}
|
||||
|
||||
if (i > 7) {
|
||||
printk(KERN_ERR "%s: timeout, the slave no response\n",
|
||||
__func__);
|
||||
ret = 1; /* timeout, the slave no response */
|
||||
} else { /* the slave not busy, prepare for getting data */
|
||||
f300_set_line(dev, F300_RESET, 0);/*ready...*/
|
||||
msleep(1);
|
||||
f300_send_byte(dev, 0xe1);/* 0xe1 is Read */
|
||||
msleep(1);
|
||||
temp = f300_get_byte(dev);/*get the data length */
|
||||
if (temp > 14)
|
||||
temp = 14;
|
||||
|
||||
for (i = 0; i < (temp + 1); i++)
|
||||
f300_get_byte(dev);/* get data to empty buffer */
|
||||
|
||||
f300_set_line(dev, F300_RESET, 1);/* received data over */
|
||||
f300_set_line(dev, F300_DATA, 1);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int f300_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage)
|
||||
{
|
||||
u8 buf[16];
|
||||
|
||||
buf[0] = 0x05;
|
||||
buf[1] = 0x38;/* write port */
|
||||
buf[2] = 0x01;/* A port, lnb power */
|
||||
|
||||
switch (voltage) {
|
||||
case SEC_VOLTAGE_13:
|
||||
buf[3] = 0x01;/* power on */
|
||||
buf[4] = 0x02;/* B port, H/V */
|
||||
buf[5] = 0x00;/*13V v*/
|
||||
break;
|
||||
case SEC_VOLTAGE_18:
|
||||
buf[3] = 0x01;
|
||||
buf[4] = 0x02;
|
||||
buf[5] = 0x01;/* 18V h*/
|
||||
break;
|
||||
case SEC_VOLTAGE_OFF:
|
||||
buf[3] = 0x00;/* power off */
|
||||
buf[4] = 0x00;
|
||||
buf[5] = 0x00;
|
||||
break;
|
||||
}
|
||||
|
||||
return f300_xfer(fe, buf);
|
||||
}
|
|
@ -0,0 +1,2 @@
|
|||
extern int f300_set_voltage(struct dvb_frontend *fe,
|
||||
fe_sec_voltage_t voltage);
|
|
@ -471,6 +471,7 @@ extern void cx23885_wakeup(struct cx23885_tsport *port,
|
|||
|
||||
extern void cx23885_gpio_set(struct cx23885_dev *dev, u32 mask);
|
||||
extern void cx23885_gpio_clear(struct cx23885_dev *dev, u32 mask);
|
||||
extern u32 cx23885_gpio_get(struct cx23885_dev *dev, u32 mask);
|
||||
extern void cx23885_gpio_enable(struct cx23885_dev *dev, u32 mask,
|
||||
int asoutput);
|
||||
|
||||
|
|
Loading…
Reference in New Issue