mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-11-01 17:08:10 +00:00
V4L/DVB (4772): Add support for DiBcom DiB7000PC
This patch contains support for the DiB7000PC-driver. Signed-off-by: Francois KANOUNNIKOFF <fkanounnikoff@dibcom.fr> Signed-off-by: Patrick Boettcher <pboettcher@dibcom.fr> Signed-off-by: Mauro Carvalho Chehab <mchehab@infradead.org>
This commit is contained in:
parent
8364681766
commit
a75763ffff
8 changed files with 1203 additions and 13 deletions
|
@ -69,6 +69,7 @@ config DVB_USB_DIBUSB_MC
|
|||
config DVB_USB_DIB0700
|
||||
tristate "DiBcom DiB0700 USB DVB devices (see help for supported devices)"
|
||||
depends on DVB_USB
|
||||
select DVB_DIB7000P
|
||||
select DVB_DIB7000M
|
||||
select DVB_DIB3000MC
|
||||
select DVB_TUNER_MT2060 if !DVB_FE_CUSTOMISE
|
||||
|
|
|
@ -24,18 +24,23 @@ extern int dvb_usb_dib0700_debug;
|
|||
#define REQUEST_I2C_WRITE 0x3
|
||||
#define REQUEST_POLL_RC 0x4
|
||||
#define REQUEST_JUMPRAM 0x8
|
||||
#define REQUEST_SET_CLOCK 0xB
|
||||
#define REQUEST_SET_GPIO 0xC
|
||||
#define REQUEST_ENABLE_VIDEO 0xF
|
||||
// 1 Byte: 4MSB(1 = enable streaming, 0 = disable streaming) 4LSB(Video Mode: 0 = MPEG2 188Bytes, 1 = Analog)
|
||||
// 2 Byte: MPEG2 mode: 4MSB(1 = Master Mode, 0 = Slave Mode) 4LSB(Channel 1 = bit0, Channel 2 = bit1)
|
||||
// 2 Byte: Analog mode: 4MSB(0 = 625 lines, 1 = 525 lines) 4LSB( " " )
|
||||
#define REQUEST_GET_VERSION 0x15
|
||||
|
||||
struct dib0700_state {
|
||||
u8 channel_state;
|
||||
u16 mt2060_if1[2];
|
||||
|
||||
u8 is_dib7000pc;
|
||||
};
|
||||
|
||||
extern int dib0700_set_gpio(struct dvb_usb_device *, enum dib07x0_gpios gpio, u8 gpio_dir, u8 gpio_val);
|
||||
extern int dib0700_ctrl_clock(struct dvb_usb_device *d, u32 clk_MHz, u8 clock_out_gp3);
|
||||
extern int dib0700_download_firmware(struct usb_device *udev, const struct firmware *fw);
|
||||
extern int dib0700_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff);
|
||||
extern struct i2c_algorithm dib0700_i2c_algo;
|
||||
|
|
|
@ -135,14 +135,46 @@ struct i2c_algorithm dib0700_i2c_algo = {
|
|||
int dib0700_identify_state(struct usb_device *udev, struct dvb_usb_device_properties *props,
|
||||
struct dvb_usb_device_description **desc, int *cold)
|
||||
{
|
||||
u8 buf[3] = { REQUEST_SET_GPIO, 4, (GPIO_IN << 7) | (0 << 6) }; // GPIO4 is save - used for I2C
|
||||
*cold = usb_control_msg(udev, usb_sndctrlpipe(udev,0),
|
||||
buf[0], USB_TYPE_VENDOR | USB_DIR_OUT, 0, 0, buf, 3, USB_CTRL_GET_TIMEOUT) != 3;
|
||||
u8 b[16];
|
||||
s16 ret = usb_control_msg(udev, usb_rcvctrlpipe(udev,0),
|
||||
REQUEST_GET_VERSION, USB_TYPE_VENDOR | USB_DIR_IN, 0, 0, b, 16, USB_CTRL_GET_TIMEOUT);
|
||||
|
||||
deb_info("FW GET_VERSION length: %d\n",ret);
|
||||
|
||||
*cold = ret <= 0;
|
||||
|
||||
deb_info("cold: %d\n", *cold);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dib0700_set_clock(struct dvb_usb_device *d, u8 en_pll,
|
||||
u8 pll_src, u8 pll_range, u8 clock_gpio3, u16 pll_prediv,
|
||||
u16 pll_loopdiv, u16 free_div, u16 dsuScaler)
|
||||
{
|
||||
u8 b[10];
|
||||
b[0] = REQUEST_SET_CLOCK;
|
||||
b[1] = (en_pll << 7) | (pll_src << 6) | (pll_range << 5) | (clock_gpio3 << 4);
|
||||
b[2] = (pll_prediv >> 8) & 0xff; // MSB
|
||||
b[3] = pll_prediv & 0xff; // LSB
|
||||
b[4] = (pll_loopdiv >> 8) & 0xff; // MSB
|
||||
b[5] = pll_loopdiv & 0xff; // LSB
|
||||
b[6] = (free_div >> 8) & 0xff; // MSB
|
||||
b[7] = free_div & 0xff; // LSB
|
||||
b[8] = (dsuScaler >> 8) & 0xff; // MSB
|
||||
b[9] = dsuScaler & 0xff; // LSB
|
||||
|
||||
return dib0700_ctrl_wr(d, b, 10);
|
||||
}
|
||||
|
||||
int dib0700_ctrl_clock(struct dvb_usb_device *d, u32 clk_MHz, u8 clock_out_gp3)
|
||||
{
|
||||
switch (clk_MHz) {
|
||||
case 72: dib0700_set_clock(d, 1, 0, 1, clock_out_gp3, 2, 24, 0, 0x4c); break;
|
||||
default: return -EINVAL;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dib0700_jumpram(struct usb_device *udev, u32 address)
|
||||
{
|
||||
int ret, actlen;
|
||||
|
@ -197,7 +229,7 @@ int dib0700_download_firmware(struct usb_device *udev, const struct firmware *fw
|
|||
/* start the firmware */
|
||||
if ((ret = dib0700_jumpram(udev, 0x70000000)) == 0) {
|
||||
info("firmware started successfully.");
|
||||
msleep(100);
|
||||
msleep(500);
|
||||
}
|
||||
} else
|
||||
ret = -EIO;
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
|
||||
#include "dib3000mc.h"
|
||||
#include "dib7000m.h"
|
||||
#include "dib7000p.h"
|
||||
#include "mt2060.h"
|
||||
|
||||
static int force_lna_activation;
|
||||
|
@ -96,7 +97,7 @@ static int bristol_tuner_attach(struct dvb_usb_adapter *adap)
|
|||
}
|
||||
|
||||
/* STK7700P: Hauppauge Nova-T Stick, AVerMedia Volar */
|
||||
static struct dibx000_agc_config stk7700p_dib7000m_agc_config = {
|
||||
static struct dibx000_agc_config stk7700p_7000m_mt2060_agc_config = {
|
||||
BAND_UHF | BAND_VHF, // band_caps
|
||||
|
||||
/* P_agc_use_sd_mod1=0, P_agc_use_sd_mod2=0, P_agc_freq_pwm_div=5, P_agc_inv_pwm1=0, P_agc_inv_pwm2=0,
|
||||
|
@ -141,7 +142,52 @@ static struct dibx000_agc_config stk7700p_dib7000m_agc_config = {
|
|||
},
|
||||
};
|
||||
|
||||
static struct dibx000_bandwidth_config stk7700p_dib7000m_mt2060_config = {
|
||||
static struct dibx000_agc_config stk7700p_7000p_mt2060_agc_config = {
|
||||
BAND_UHF | BAND_VHF,
|
||||
|
||||
/* P_agc_use_sd_mod1=0, P_agc_use_sd_mod2=0, P_agc_freq_pwm_div=5, P_agc_inv_pwm1=0, P_agc_inv_pwm2=0,
|
||||
* P_agc_inh_dc_rv_est=0, P_agc_time_est=3, P_agc_freeze=0, P_agc_nb_est=2, P_agc_write=0 */
|
||||
(0 << 15) | (0 << 14) | (5 << 11) | (0 << 10) | (0 << 9) | (0 << 8) | (3 << 5) | (0 << 4) | (2 << 1) | (0 << 0), // setup
|
||||
|
||||
712, // inv_gain
|
||||
41, // time_stabiliz
|
||||
|
||||
0, // alpha_level
|
||||
118, // thlock
|
||||
|
||||
0, // wbd_inv
|
||||
4095, // wbd_ref
|
||||
0, // wbd_sel
|
||||
0, // wbd_alpha
|
||||
|
||||
42598, // agc1_max
|
||||
16384, // agc1_min
|
||||
42598, // agc2_max
|
||||
0, // agc2_min
|
||||
|
||||
0, // agc1_pt1
|
||||
137, // agc1_pt2
|
||||
255, // agc1_pt3
|
||||
|
||||
0, // agc1_slope1
|
||||
255, // agc1_slope2
|
||||
|
||||
0, // agc2_pt1
|
||||
0, // agc2_pt2
|
||||
|
||||
0, // agc2_slope1
|
||||
41, // agc2_slope2
|
||||
|
||||
15, // alpha_mant
|
||||
25, // alpha_exp
|
||||
|
||||
28, // beta_mant
|
||||
48, // beta_exp
|
||||
|
||||
0, // perform_agc_softsplit
|
||||
};
|
||||
|
||||
static struct dibx000_bandwidth_config stk7700p_pll_config = {
|
||||
60000, 30000, // internal, sampling
|
||||
1, 8, 3, 1, 0, // pll_cfg: prediv, ratio, range, reset, bypass
|
||||
0, 0, 1, 1, 0, // misc: refdiv, bypclk_div, IO_CLK_en_core, ADClkSrc, modulo
|
||||
|
@ -156,8 +202,19 @@ static struct dib7000m_config stk7700p_dib7000m_config = {
|
|||
.quartz_direct = 1,
|
||||
|
||||
.agc_config_count = 1,
|
||||
.agc = &stk7700p_dib7000m_agc_config,
|
||||
.bw = &stk7700p_dib7000m_mt2060_config,
|
||||
.agc = &stk7700p_7000m_mt2060_agc_config,
|
||||
.bw = &stk7700p_pll_config,
|
||||
|
||||
.gpio_dir = DIB7000M_GPIO_DEFAULT_DIRECTIONS,
|
||||
.gpio_val = DIB7000M_GPIO_DEFAULT_VALUES,
|
||||
.gpio_pwm_pos = DIB7000M_GPIO_DEFAULT_PWM_POS,
|
||||
};
|
||||
|
||||
static struct dib7000p_config stk7700p_dib7000p_config = {
|
||||
.output_mpeg2_in_188_bytes = 1,
|
||||
|
||||
.agc = &stk7700p_7000p_mt2060_agc_config,
|
||||
.bw = &stk7700p_pll_config,
|
||||
|
||||
.gpio_dir = DIB7000M_GPIO_DEFAULT_DIRECTIONS,
|
||||
.gpio_val = DIB7000M_GPIO_DEFAULT_VALUES,
|
||||
|
@ -168,13 +225,28 @@ static int stk7700p_frontend_attach(struct dvb_usb_adapter *adap)
|
|||
{
|
||||
struct dib0700_state *st = adap->dev->priv;
|
||||
/* unless there is no real power management in DVB - we leave the device on GPIO6 */
|
||||
dib0700_set_gpio(adap->dev, GPIO6, GPIO_OUT, 0); msleep(10);
|
||||
|
||||
dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 0);
|
||||
dib0700_set_gpio(adap->dev, GPIO6, GPIO_OUT, 0); msleep(50);
|
||||
|
||||
dib0700_set_gpio(adap->dev, GPIO6, GPIO_OUT, 1); msleep(10);
|
||||
dib0700_set_gpio(adap->dev, GPIO9, GPIO_OUT, 1);
|
||||
|
||||
dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 0); msleep(10);
|
||||
dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 1); msleep(10);
|
||||
dib0700_ctrl_clock(adap->dev, 72, 1);
|
||||
dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 1); msleep(100);
|
||||
|
||||
dib0700_set_gpio(adap->dev, GPIO0, GPIO_OUT, 1);
|
||||
|
||||
st->mt2060_if1[0] = 1220;
|
||||
return (adap->fe = dvb_attach(dib7000m_attach, &adap->dev->i2c_adap, 18, &stk7700p_dib7000m_config)) == NULL ? -ENODEV : 0;
|
||||
|
||||
if (dib7000pc_detection(&adap->dev->i2c_adap)) {
|
||||
adap->fe = dvb_attach(dib7000p_attach, &adap->dev->i2c_adap, 18, &stk7700p_dib7000p_config);
|
||||
st->is_dib7000pc = 1;
|
||||
} else
|
||||
adap->fe = dvb_attach(dib7000m_attach, &adap->dev->i2c_adap, 18, &stk7700p_dib7000m_config);
|
||||
|
||||
return adap->fe == NULL ? -ENODEV : 0;
|
||||
}
|
||||
|
||||
static struct mt2060_config stk7700p_mt2060_config = {
|
||||
|
@ -184,8 +256,14 @@ static struct mt2060_config stk7700p_mt2060_config = {
|
|||
static int stk7700p_tuner_attach(struct dvb_usb_adapter *adap)
|
||||
{
|
||||
struct dib0700_state *st = adap->dev->priv;
|
||||
struct i2c_adapter *tun_i2c = dib7000m_get_i2c_master(adap->fe, DIBX000_I2C_INTERFACE_TUNER, 1);
|
||||
return dvb_attach(mt2060_attach,adap->fe, tun_i2c, &stk7700p_mt2060_config,
|
||||
struct i2c_adapter *tun_i2c;
|
||||
|
||||
if (st->is_dib7000pc)
|
||||
tun_i2c = dib7000p_get_i2c_master(adap->fe, DIBX000_I2C_INTERFACE_TUNER, 1);
|
||||
else
|
||||
tun_i2c = dib7000m_get_i2c_master(adap->fe, DIBX000_I2C_INTERFACE_TUNER, 1);
|
||||
|
||||
return dvb_attach(mt2060_attach, adap->fe, tun_i2c, &stk7700p_mt2060_config,
|
||||
st->mt2060_if1[0]) == NULL ? -ENODEV : 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -180,6 +180,14 @@ config DVB_DIB7000M
|
|||
A DVB-T tuner module. Designed for mobile usage. Say Y when you want
|
||||
to support this frontend.
|
||||
|
||||
config DVB_DIB7000P
|
||||
tristate "DiBcom 7000PC"
|
||||
depends on DVB_CORE && I2C
|
||||
default m if DVB_FE_CUSTOMISE
|
||||
help
|
||||
A DVB-T tuner module. Designed for mobile usage. Say Y when you want
|
||||
to support this frontend.
|
||||
|
||||
comment "DVB-C (cable) frontends"
|
||||
depends on DVB_CORE
|
||||
|
||||
|
|
|
@ -14,6 +14,7 @@ obj-$(CONFIG_DVB_L64781) += l64781.o
|
|||
obj-$(CONFIG_DVB_DIB3000MB) += dib3000mb.o
|
||||
obj-$(CONFIG_DVB_DIB3000MC) += dib3000mc.o dibx000_common.o
|
||||
obj-$(CONFIG_DVB_DIB7000M) += dib7000m.o dibx000_common.o
|
||||
obj-$(CONFIG_DVB_DIB7000P) += dib7000p.o dibx000_common.o
|
||||
obj-$(CONFIG_DVB_MT312) += mt312.o
|
||||
obj-$(CONFIG_DVB_VES1820) += ves1820.o
|
||||
obj-$(CONFIG_DVB_VES1X93) += ves1x93.o
|
||||
|
|
1019
drivers/media/dvb/frontends/dib7000p.c
Normal file
1019
drivers/media/dvb/frontends/dib7000p.c
Normal file
File diff suppressed because it is too large
Load diff
46
drivers/media/dvb/frontends/dib7000p.h
Normal file
46
drivers/media/dvb/frontends/dib7000p.h
Normal file
|
@ -0,0 +1,46 @@
|
|||
#ifndef DIB7000P_H
|
||||
#define DIB7000P_H
|
||||
|
||||
#include "dibx000_common.h"
|
||||
|
||||
struct dib7000p_config {
|
||||
u8 output_mpeg2_in_188_bytes;
|
||||
u8 hostbus_diversity;
|
||||
u8 tuner_is_baseband;
|
||||
int (*update_lna) (struct dvb_frontend *, u16 agc_global);
|
||||
|
||||
struct dibx000_agc_config *agc;
|
||||
struct dibx000_bandwidth_config *bw;
|
||||
|
||||
#define DIB7000P_GPIO_DEFAULT_DIRECTIONS 0xffff
|
||||
u16 gpio_dir;
|
||||
#define DIB7000P_GPIO_DEFAULT_VALUES 0x0000
|
||||
u16 gpio_val;
|
||||
#define DIB7000P_GPIO_PWM_POS0(v) ((v & 0xf) << 12)
|
||||
#define DIB7000P_GPIO_PWM_POS1(v) ((v & 0xf) << 8 )
|
||||
#define DIB7000P_GPIO_PWM_POS2(v) ((v & 0xf) << 4 )
|
||||
#define DIB7000P_GPIO_PWM_POS3(v) (v & 0xf)
|
||||
#define DIB7000P_GPIO_DEFAULT_PWM_POS 0xffff
|
||||
u16 gpio_pwm_pos;
|
||||
|
||||
u16 pwm_freq_div;
|
||||
|
||||
u8 quartz_direct;
|
||||
|
||||
int (*agc_control) (struct dvb_frontend *, u8 before);
|
||||
};
|
||||
|
||||
#define DEFAULT_DIB7000P_I2C_ADDRESS 18
|
||||
|
||||
extern struct dvb_frontend * dib7000p_attach(struct i2c_adapter *i2c_adap, u8 i2c_addr, struct dib7000p_config *cfg);
|
||||
extern struct i2c_adapter * dib7000p_get_i2c_master(struct dvb_frontend *, enum dibx000_i2c_interface, int);
|
||||
extern int dib7000pc_detection(struct i2c_adapter *i2c_adap);
|
||||
|
||||
/* TODO
|
||||
extern INT dib7000p_set_gpio(struct dibDemod *demod, UCHAR num, UCHAR dir, UCHAR val);
|
||||
extern INT dib7000p_enable_vbg_voltage(struct dibDemod *demod);
|
||||
extern void dib7000p_set_hostbus_diversity(struct dibDemod *demod, UCHAR onoff);
|
||||
extern USHORT dib7000p_get_current_agc_global(struct dibDemod *demod);
|
||||
*/
|
||||
|
||||
#endif
|
Loading…
Reference in a new issue