提交 09ea33e5 编写于 作者: I Igor M. Liplianin 提交者: Mauro Carvalho Chehab

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: NIgor M. Liplianin <liplianin@me.by>
Signed-off-by: NMauro Carvalho Chehab <mchehab@redhat.com>
上级 6afd2aa8
...@@ -201,6 +201,13 @@ config DVB_SI21XX ...@@ -201,6 +201,13 @@ config DVB_SI21XX
help help
A DVB-S tuner module. Say Y when you want to support this frontend. 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" comment "DVB-T (terrestrial) frontends"
depends on DVB_CORE depends on DVB_CORE
......
...@@ -78,3 +78,4 @@ obj-$(CONFIG_DVB_STV090x) += stv090x.o ...@@ -78,3 +78,4 @@ obj-$(CONFIG_DVB_STV090x) += stv090x.o
obj-$(CONFIG_DVB_STV6110x) += stv6110x.o obj-$(CONFIG_DVB_STV6110x) += stv6110x.o
obj-$(CONFIG_DVB_ISL6423) += isl6423.o obj-$(CONFIG_DVB_ISL6423) += isl6423.o
obj-$(CONFIG_DVB_EC100) += ec100.o obj-$(CONFIG_DVB_EC100) += ec100.o
obj-$(CONFIG_DVB_DS3000) += ds3000.o
此差异已折叠。
/*
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 ...@@ -18,7 +18,9 @@ config VIDEO_CX23885
select DVB_TDA10048 if !DVB_FE_CUSTOMISE select DVB_TDA10048 if !DVB_FE_CUSTOMISE
select DVB_LNBP21 if !DVB_FE_CUSTOMISE select DVB_LNBP21 if !DVB_FE_CUSTOMISE
select DVB_STV6110 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_STV0900 if !DVB_FE_CUSTOMISE
select DVB_DS3000 if !DVB_FE_CUSTOMISE
select MEDIA_TUNER_MT2131 if !MEDIA_TUNER_CUSTOMISE select MEDIA_TUNER_MT2131 if !MEDIA_TUNER_CUSTOMISE
select MEDIA_TUNER_XC2028 if !MEDIA_TUNER_CUSTOMISE select MEDIA_TUNER_XC2028 if !MEDIA_TUNER_CUSTOMISE
select MEDIA_TUNER_TDA8290 if !MEDIA_TUNER_CUSTOMISE select MEDIA_TUNER_TDA8290 if !MEDIA_TUNER_CUSTOMISE
......
cx23885-objs := cx23885-cards.o cx23885-video.o cx23885-vbi.o \ cx23885-objs := cx23885-cards.o cx23885-video.o cx23885-vbi.o \
cx23885-core.o cx23885-i2c.o cx23885-dvb.o cx23885-417.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 \ 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 obj-$(CONFIG_VIDEO_CX23885) += cx23885.o
......
...@@ -782,10 +782,14 @@ void cx23885_gpio_setup(struct cx23885_dev *dev) ...@@ -782,10 +782,14 @@ void cx23885_gpio_setup(struct cx23885_dev *dev)
cx_set(GP0_IO, 0x00040004); cx_set(GP0_IO, 0x00040004);
break; break;
case CX23885_BOARD_TBS_6920: case CX23885_BOARD_TBS_6920:
case CX23885_BOARD_TEVII_S470:
cx_write(MC417_CTL, 0x00000036); cx_write(MC417_CTL, 0x00000036);
cx_write(MC417_OEN, 0x00001000); 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; break;
case CX23885_BOARD_NETUP_DUAL_DVBS2_CI: case CX23885_BOARD_NETUP_DUAL_DVBS2_CI:
/* GPIO-0 INTA from CiMax1 /* GPIO-0 INTA from CiMax1
...@@ -1002,8 +1006,12 @@ void cx23885_card_setup(struct cx23885_dev *dev) ...@@ -1002,8 +1006,12 @@ void cx23885_card_setup(struct cx23885_dev *dev)
ts2->ts_clk_en_val = 0x1; /* Enable TS_CLK */ ts2->ts_clk_en_val = 0x1; /* Enable TS_CLK */
ts2->src_sel_val = CX23885_SRC_SEL_PARALLEL_MPEG_VIDEO; ts2->src_sel_val = CX23885_SRC_SEL_PARALLEL_MPEG_VIDEO;
break; break;
case CX23885_BOARD_TEVII_S470:
case CX23885_BOARD_TBS_6920: 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: case CX23885_BOARD_DVBWORLD_2005:
ts1->gen_ctrl_val = 0x5; /* Parallel */ ts1->gen_ctrl_val = 0x5; /* Parallel */
ts1->ts_clk_en_val = 0x1; /* Enable TS_CLK */ ts1->ts_clk_en_val = 0x1; /* Enable TS_CLK */
......
...@@ -1871,6 +1871,26 @@ void cx23885_gpio_clear(struct cx23885_dev *dev, u32 mask) ...@@ -1871,6 +1871,26 @@ void cx23885_gpio_clear(struct cx23885_dev *dev, u32 mask)
printk(KERN_INFO "%s: Unsupported\n", dev->name); 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) void cx23885_gpio_enable(struct cx23885_dev *dev, u32 mask, int asoutput)
{ {
if ((mask & 0x00000007) && asoutput) if ((mask & 0x00000007) && asoutput)
......
...@@ -56,6 +56,8 @@ ...@@ -56,6 +56,8 @@
#include "netup-init.h" #include "netup-init.h"
#include "lgdt3305.h" #include "lgdt3305.h"
#include "atbm8830.h" #include "atbm8830.h"
#include "ds3000.h"
#include "cx23885-f300.h"
static unsigned int debug; static unsigned int debug;
...@@ -427,26 +429,12 @@ static struct stv6110_config netup_stv6110_tunerconfig_b = { ...@@ -427,26 +429,12 @@ static struct stv6110_config netup_stv6110_tunerconfig_b = {
.gain = 8, /* +16 dB - maximum gain */ .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 = { static struct cx24116_config tbs_cx24116_config = {
.demod_address = 0x05, .demod_address = 0x55,
}; };
static struct cx24116_config tevii_cx24116_config = { static struct ds3000_config tevii_ds3000_config = {
.demod_address = 0x55, .demod_address = 0x68,
}; };
static struct cx24116_config dvbworld_cx24116_config = { static struct cx24116_config dvbworld_cx24116_config = {
...@@ -832,23 +820,23 @@ static int dvb_register(struct cx23885_tsport *port) ...@@ -832,23 +820,23 @@ static int dvb_register(struct cx23885_tsport *port)
} }
break; break;
case CX23885_BOARD_TBS_6920: case CX23885_BOARD_TBS_6920:
i2c_bus = &dev->i2c_bus[0]; i2c_bus = &dev->i2c_bus[1];
fe0->dvb.frontend = dvb_attach(cx24116_attach, fe0->dvb.frontend = dvb_attach(cx24116_attach,
&tbs_cx24116_config, &tbs_cx24116_config,
&i2c_bus->i2c_adap); &i2c_bus->i2c_adap);
if (fe0->dvb.frontend != NULL) if (fe0->dvb.frontend != NULL)
fe0->dvb.frontend->ops.set_voltage = tbs_set_voltage; fe0->dvb.frontend->ops.set_voltage = f300_set_voltage;
break; break;
case CX23885_BOARD_TEVII_S470: case CX23885_BOARD_TEVII_S470:
i2c_bus = &dev->i2c_bus[1]; i2c_bus = &dev->i2c_bus[1];
fe0->dvb.frontend = dvb_attach(cx24116_attach, fe0->dvb.frontend = dvb_attach(ds3000_attach,
&tevii_cx24116_config, &tevii_ds3000_config,
&i2c_bus->i2c_adap); &i2c_bus->i2c_adap);
if (fe0->dvb.frontend != NULL) if (fe0->dvb.frontend != NULL)
fe0->dvb.frontend->ops.set_voltage = tbs_set_voltage; fe0->dvb.frontend->ops.set_voltage = f300_set_voltage;
break; break;
case CX23885_BOARD_DVBWORLD_2005: case CX23885_BOARD_DVBWORLD_2005:
......
/*
* 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);
}
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, ...@@ -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_set(struct cx23885_dev *dev, u32 mask);
extern void cx23885_gpio_clear(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, extern void cx23885_gpio_enable(struct cx23885_dev *dev, u32 mask,
int asoutput); int asoutput);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册