V4L/DVB (13583): DiB8090: Add the DiB0090 tuner driver and STK8096GP-board

This patchs adds support for the DiBcom DiB0090 RF tuner and for
DiBcom's reference design STK8096GP. Small extracts of the DiB0070 and
the DiB8000-driver into a common codebase.

Signed-off-by: Patrick Boettcher <pboettcher@kernellabs.com>
Signed-off-by: Olivier Grenie <Olivier.Grenie@dibcom.fr>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
This commit is contained in:
Olivier Grenie 2009-12-04 13:27:57 -03:00 committed by Mauro Carvalho Chehab
parent 20232c4791
commit 03245a5ee6
12 changed files with 2435 additions and 350 deletions

View File

@ -18,6 +18,7 @@
#include "xc5000.h"
#include "s5h1411.h"
#include "dib0070.h"
#include "dib0090.h"
#include "lgdt3305.h"
#include "mxl5007t.h"
@ -1476,12 +1477,12 @@ static struct dib8000_config dib807x_dib8000_config[2] = {
}
};
static int dib807x_tuner_reset(struct dvb_frontend *fe, int onoff)
static int dib80xx_tuner_reset(struct dvb_frontend *fe, int onoff)
{
return dib8000_set_gpio(fe, 5, 0, !onoff);
}
static int dib807x_tuner_sleep(struct dvb_frontend *fe, int onoff)
static int dib80xx_tuner_sleep(struct dvb_frontend *fe, int onoff)
{
return dib8000_set_gpio(fe, 0, 0, onoff);
}
@ -1494,8 +1495,8 @@ static const struct dib0070_wbd_gain_cfg dib8070_wbd_gain_cfg[] = {
static struct dib0070_config dib807x_dib0070_config[2] = {
{
.i2c_address = DEFAULT_DIB0070_I2C_ADDRESS,
.reset = dib807x_tuner_reset,
.sleep = dib807x_tuner_sleep,
.reset = dib80xx_tuner_reset,
.sleep = dib80xx_tuner_sleep,
.clock_khz = 12000,
.clock_pad_drive = 4,
.vga_filter = 1,
@ -1508,8 +1509,8 @@ static struct dib0070_config dib807x_dib0070_config[2] = {
.freq_offset_khz_vhf = -100,
}, {
.i2c_address = DEFAULT_DIB0070_I2C_ADDRESS,
.reset = dib807x_tuner_reset,
.sleep = dib807x_tuner_sleep,
.reset = dib80xx_tuner_reset,
.sleep = dib80xx_tuner_sleep,
.clock_khz = 12000,
.clock_pad_drive = 2,
.vga_filter = 1,
@ -1566,12 +1567,12 @@ static int dib807x_tuner_attach(struct dvb_usb_adapter *adap)
return 0;
}
static int stk807x_pid_filter(struct dvb_usb_adapter *adapter, int index, u16 pid, int onoff)
static int stk80xx_pid_filter(struct dvb_usb_adapter *adapter, int index, u16 pid, int onoff)
{
return dib8000_pid_filter(adapter->fe, index, pid, onoff);
}
static int stk807x_pid_filter_ctrl(struct dvb_usb_adapter *adapter, int onoff)
static int stk80xx_pid_filter_ctrl(struct dvb_usb_adapter *adapter, int onoff)
{
return dib8000_pid_filter_ctrl(adapter->fe, onoff);
}
@ -1643,6 +1644,246 @@ static int stk807xpvr_frontend_attach1(struct dvb_usb_adapter *adap)
return adap->fe == NULL ? -ENODEV : 0;
}
/* STK8096GP */
struct dibx000_agc_config dib8090_agc_config[2] = {
{
BAND_UHF | BAND_VHF | BAND_LBAND | BAND_SBAND,
/* P_agc_use_sd_mod1=0, P_agc_use_sd_mod2=0, P_agc_freq_pwm_div=1, 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=5, P_agc_write=0 */
(0 << 15) | (0 << 14) | (5 << 11) | (0 << 10) | (0 << 9) | (0 << 8) | (3 << 5) | (0 << 4) | (5 << 1) | (0 << 0), // setup
787,// inv_gain = 1/ 90.4dB // no boost, lower gain due to ramp quantification
10, // time_stabiliz
0, // alpha_level
118, // thlock
0, // wbd_inv
3530, // wbd_ref
1, // wbd_sel
5, // wbd_alpha
65535, // agc1_max
0, // agc1_min
65535, // agc2_max
0, // agc2_min
0, // agc1_pt1
32, // agc1_pt2
114, // agc1_pt3 // 40.4dB
143, // agc1_slope1
144, // agc1_slope2
114, // agc2_pt1
227, // agc2_pt2
116, // agc2_slope1
117, // agc2_slope2
28, // alpha_mant // 5Hz with 90.2dB
26, // alpha_exp
31, // beta_mant
51, // beta_exp
0, // perform_agc_softsplit
},
{
BAND_CBAND,
/* P_agc_use_sd_mod1=0, P_agc_use_sd_mod2=0, P_agc_freq_pwm_div=1, 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=5, P_agc_write=0 */
(0 << 15) | (0 << 14) | (5 << 11) | (0 << 10) | (0 << 9) | (0 << 8) | (3 << 5) | (0 << 4) | (5 << 1) | (0 << 0), // setup
787,// inv_gain = 1/ 90.4dB // no boost, lower gain due to ramp quantification
10, // time_stabiliz
0, // alpha_level
118, // thlock
0, // wbd_inv
3530, // wbd_ref
1, // wbd_sel
5, // wbd_alpha
0, // agc1_max
0, // agc1_min
65535, // agc2_max
0, // agc2_min
0, // agc1_pt1
32, // agc1_pt2
114, // agc1_pt3 // 40.4dB
143, // agc1_slope1
144, // agc1_slope2
114, // agc2_pt1
227, // agc2_pt2
116, // agc2_slope1
117, // agc2_slope2
28, // alpha_mant // 5Hz with 90.2dB
26, // alpha_exp
31, // beta_mant
51, // beta_exp
0, // perform_agc_softsplit
}
};
static struct dibx000_bandwidth_config dib8090_pll_config_12mhz = {
54000, 13500, // internal, sampling
1, 18, 3, 1, 0, // pll_cfg: prediv, ratio, range, reset, bypass
0, 0, 1, 1, 2, // misc: refdiv, bypclk_div, IO_CLK_en_core, ADClkSrc, modulo
(3 << 14) | (1 << 12) | (599 << 0), // sad_cfg: refsel, sel, freq_15k
(0 << 25) | 0, // ifreq = 0 MHz
20199727, // timf
12000000, // xtal_hz
};
static int dib8090_get_adc_power(struct dvb_frontend *fe)
{
return dib8000_get_adc_power(fe, 1);
}
static struct dib8000_config dib809x_dib8000_config = {
.output_mpeg2_in_188_bytes = 1,
.agc_config_count = 2,
.agc = dib8090_agc_config,
.agc_control = dib0090_dcc_freq,
.pll = &dib8090_pll_config_12mhz,
.tuner_is_baseband = 1,
.gpio_dir = DIB8000_GPIO_DEFAULT_DIRECTIONS,
.gpio_val = DIB8000_GPIO_DEFAULT_VALUES,
.gpio_pwm_pos = DIB8000_GPIO_DEFAULT_PWM_POS,
.hostbus_diversity = 1,
.div_cfg = 0x31,
.output_mode = OUTMODE_MPEG2_FIFO,
.drives = 0x2d98,
.diversity_delay = 144,
.refclksel = 3,
};
static struct dib0090_config dib809x_dib0090_config = {
.io.pll_bypass = 1,
.io.pll_range = 1,
.io.pll_prediv = 1,
.io.pll_loopdiv = 20,
.io.adc_clock_ratio = 8,
.io.pll_int_loop_filt = 0,
.io.clock_khz = 12000,
.reset = dib80xx_tuner_reset,
.sleep = dib80xx_tuner_sleep,
.clkouttobamse = 1,
.analog_output = 1,
.i2c_address = DEFAULT_DIB0090_I2C_ADDRESS,
.wbd_vhf_offset = 100,
.wbd_cband_offset = 450,
.use_pwm_agc = 1,
.clkoutdrive = 1,
.get_adc_power = dib8090_get_adc_power,
.freq_offset_khz_uhf = 0,
.freq_offset_khz_vhf = -143,
};
static int dib8096_set_param_override(struct dvb_frontend *fe,
struct dvb_frontend_parameters *fep)
{
struct dvb_usb_adapter *adap = fe->dvb->priv;
struct dib0700_adapter_state *state = adap->priv;
u8 band = BAND_OF_FREQUENCY(fep->frequency/1000);
u16 offset;
int ret = 0;
enum frontend_tune_state tune_state = CT_SHUTDOWN;
u16 ltgain, rf_gain_limit;
ret = state->set_param_save(fe, fep);
if (ret < 0)
return ret;
switch (band) {
case BAND_VHF:
offset = 100;
break;
case BAND_UHF:
offset = 550;
break;
default:
offset = 0;
break;
}
offset += (dib0090_get_wbd_offset(fe) * 8 * 18 / 33 + 1) / 2;
dib8000_set_wbd_ref(fe, offset);
if (band == BAND_CBAND)
{
deb_info("tuning in CBAND - soft-AGC startup\n");
/* TODO specific wbd target for dib0090 - needed for startup ? */
dib0090_set_tune_state(fe, CT_AGC_START);
do
{
ret = dib0090_gain_control(fe);
msleep(ret);
tune_state = dib0090_get_tune_state(fe);
if (tune_state == CT_AGC_STEP_0)
dib8000_set_gpio(fe, 6, 0, 1);
else if (tune_state == CT_AGC_STEP_1)
{
dib0090_get_current_gain(fe, NULL, NULL, &rf_gain_limit, &ltgain);
if (rf_gain_limit == 0)
dib8000_set_gpio(fe, 6, 0, 0);
}
}
while(tune_state<CT_AGC_STOP);
dib0090_pwm_gain_reset(fe);
dib8000_pwm_agc_reset(fe);
dib8000_set_tune_state(fe, CT_DEMOD_START);
}
else {
deb_info("not tuning in CBAND - standard AGC startup\n");
dib0090_pwm_gain_reset(fe);
}
return 0;
}
static int dib809x_tuner_attach(struct dvb_usb_adapter *adap)
{
struct dib0700_adapter_state *st = adap->priv;
struct i2c_adapter *tun_i2c = dib8000_get_i2c_master(adap->fe, DIBX000_I2C_INTERFACE_TUNER, 1);
if (dvb_attach(dib0090_register, adap->fe, tun_i2c, &dib809x_dib0090_config) == NULL)
return -ENODEV;
st->set_param_save = adap->fe->ops.tuner_ops.set_params;
adap->fe->ops.tuner_ops.set_params = dib8096_set_param_override;
return 0;
}
static int stk809x_frontend_attach(struct dvb_usb_adapter *adap)
{
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, GPIO4, GPIO_OUT, 1);
dib0700_set_gpio(adap->dev, GPIO7, GPIO_OUT, 1);
dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 0);
dib0700_ctrl_clock(adap->dev, 72, 1);
msleep(10);
dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 1);
msleep(10);
dib0700_set_gpio(adap->dev, GPIO0, GPIO_OUT, 1);
dib8000_i2c_enumeration(&adap->dev->i2c_adap, 1, 18, 0x80);
adap->fe = dvb_attach(dib8000_attach, &adap->dev->i2c_adap, 0x80, &dib809x_dib8000_config);
return adap->fe == NULL ? -ENODEV : 0;
}
/* STK7070PD */
static struct dib7000p_config stk7070pd_dib7000p_config[2] = {
@ -1939,6 +2180,7 @@ struct usb_device_id dib0700_usb_id_table[] = {
{ USB_DEVICE(USB_VID_EVOLUTEPC, USB_PID_TVWAY_PLUS) },
/* 65 */{ USB_DEVICE(USB_VID_PINNACLE, USB_PID_PINNACLE_PCTV73ESE) },
{ USB_DEVICE(USB_VID_PINNACLE, USB_PID_PINNACLE_PCTV282E) },
{ USB_DEVICE(USB_VID_DIBCOM, USB_PID_DIBCOM_STK8096GP) },
{ 0 } /* Terminating entry */
};
MODULE_DEVICE_TABLE(usb, dib0700_usb_id_table);
@ -2473,8 +2715,8 @@ struct dvb_usb_device_properties dib0700_devices[] = {
{
.caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
.pid_filter_count = 32,
.pid_filter = stk807x_pid_filter,
.pid_filter_ctrl = stk807x_pid_filter_ctrl,
.pid_filter = stk80xx_pid_filter,
.pid_filter_ctrl = stk80xx_pid_filter_ctrl,
.frontend_attach = stk807x_frontend_attach,
.tuner_attach = dib807x_tuner_attach,
@ -2512,8 +2754,8 @@ struct dvb_usb_device_properties dib0700_devices[] = {
{
.caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
.pid_filter_count = 32,
.pid_filter = stk807x_pid_filter,
.pid_filter_ctrl = stk807x_pid_filter_ctrl,
.pid_filter = stk80xx_pid_filter,
.pid_filter_ctrl = stk80xx_pid_filter_ctrl,
.frontend_attach = stk807xpvr_frontend_attach0,
.tuner_attach = dib807x_tuner_attach,
@ -2525,8 +2767,8 @@ struct dvb_usb_device_properties dib0700_devices[] = {
{
.caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
.pid_filter_count = 32,
.pid_filter = stk807x_pid_filter,
.pid_filter_ctrl = stk807x_pid_filter_ctrl,
.pid_filter = stk80xx_pid_filter,
.pid_filter_ctrl = stk80xx_pid_filter_ctrl,
.frontend_attach = stk807xpvr_frontend_attach1,
.tuner_attach = dib807x_tuner_attach,
@ -2545,6 +2787,37 @@ struct dvb_usb_device_properties dib0700_devices[] = {
},
},
.rc_interval = DEFAULT_RC_INTERVAL,
.rc_key_map = dib0700_rc_keys,
.rc_key_map_size = ARRAY_SIZE(dib0700_rc_keys),
.rc_query = dib0700_rc_query
}, { DIB0700_DEFAULT_DEVICE_PROPERTIES,
.num_adapters = 1,
.adapter = {
{
.caps = DVB_USB_ADAP_HAS_PID_FILTER |
DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
.pid_filter_count = 32,
.pid_filter = stk80xx_pid_filter,
.pid_filter_ctrl = stk80xx_pid_filter_ctrl,
.frontend_attach = stk809x_frontend_attach,
.tuner_attach = dib809x_tuner_attach,
DIB0700_DEFAULT_STREAMING_CONFIG(0x02),
.size_of_priv =
sizeof(struct dib0700_adapter_state),
},
},
.num_device_descs = 1,
.devices = {
{ "DiBcom STK8096GP reference design",
{ &dib0700_usb_id_table[67], NULL },
{ NULL },
},
},
.rc_interval = DEFAULT_RC_INTERVAL,
.rc_key_map = dib0700_rc_keys,
.rc_key_map_size = ARRAY_SIZE(dib0700_rc_keys),

View File

@ -102,6 +102,7 @@
#define USB_PID_DIBCOM_STK7070PD 0x1ebe
#define USB_PID_DIBCOM_STK807XP 0x1f90
#define USB_PID_DIBCOM_STK807XPVR 0x1f98
#define USB_PID_DIBCOM_STK8096GP 0x1fa0
#define USB_PID_DIBCOM_ANCHOR_2135_COLD 0x2131
#define USB_PID_DIBCOM_STK7770P 0x1e80
#define USB_PID_DPOSH_M9206_COLD 0x9206

View File

@ -526,6 +526,15 @@ config DVB_TUNER_DIB0070
This device is only used inside a SiP called together with a
demodulator for now.
config DVB_TUNER_DIB0090
tristate "DiBcom DiB0090 silicon base-band tuner"
depends on I2C
default m if DVB_FE_CUSTOMISE
help
A driver for the silicon baseband tuner DiB0090 from DiBcom.
This device is only used inside a SiP called together with a
demodulator for now.
comment "SEC control devices for DVB-S"
depends on DVB_CORE

View File

@ -55,6 +55,7 @@ obj-$(CONFIG_DVB_TDA10086) += tda10086.o
obj-$(CONFIG_DVB_TDA826X) += tda826x.o
obj-$(CONFIG_DVB_TDA8261) += tda8261.o
obj-$(CONFIG_DVB_TUNER_DIB0070) += dib0070.o
obj-$(CONFIG_DVB_TUNER_DIB0090) += dib0090.o
obj-$(CONFIG_DVB_TUA6100) += tua6100.o
obj-$(CONFIG_DVB_S5H1409) += s5h1409.o
obj-$(CONFIG_DVB_TUNER_ITD1000) += itd1000.o

View File

@ -49,21 +49,6 @@ MODULE_PARM_DESC(debug, "turn on debugging (default: 0)");
#define DIB0070_P1G 0x03
#define DIB0070S_P1A 0x02
enum frontend_tune_state {
CT_TUNER_START = 10,
CT_TUNER_STEP_0,
CT_TUNER_STEP_1,
CT_TUNER_STEP_2,
CT_TUNER_STEP_3,
CT_TUNER_STEP_4,
CT_TUNER_STEP_5,
CT_TUNER_STEP_6,
CT_TUNER_STEP_7,
CT_TUNER_STOP,
};
#define FE_CALLBACK_TIME_NEVER 0xffffffff
struct dib0070_state {
struct i2c_adapter *i2c;
struct dvb_frontend *fe;
@ -193,6 +178,8 @@ static int dib0070_captrim(struct dib0070_state *state, enum frontend_tune_state
state->adc_diff = adc;
state->fcaptrim = state->captrim;
}
state->captrim += (step_sign * state->step);
@ -362,8 +349,10 @@ static int dib0070_tune_digital(struct dvb_frontend *fe, struct dvb_frontend_par
state->current_rf = freq;
state->lo4 = (state->current_tune_table_index->vco_band << 11) | (state->current_tune_table_index->hfdiv << 7);
dib0070_write_reg(state, 0x17, 0x30);
VCOF_kHz = state->current_tune_table_index->vco_multi * freq * 2;
switch (band) {
@ -379,6 +368,8 @@ static int dib0070_tune_digital(struct dvb_frontend *fe, struct dvb_frontend_par
}
FREF = state->cfg->clock_khz / REFDIV;
switch (state->revision) {
case DIB0070S_P1A:
FBDiv = (VCOF_kHz / state->current_tune_table_index->presc / FREF);
@ -410,6 +401,7 @@ static int dib0070_tune_digital(struct dvb_frontend *fe, struct dvb_frontend_par
Den = 255;
}
dib0070_write_reg(state, 0x11, (u16)FBDiv);
dib0070_write_reg(state, 0x12, (Den << 8) | REFDIV);
dib0070_write_reg(state, 0x13, (u16) Rest);
@ -465,9 +457,11 @@ static int dib0070_tune_digital(struct dvb_frontend *fe, struct dvb_frontend_par
dib0070_write_reg(state, 0x08, (state->lna_match->lna_band << 10) | (3 << 7) | (127));
dib0070_write_reg(state, 0x0d, 0x0d80);
dib0070_write_reg(state, 0x18, 0x07ff);
dib0070_write_reg(state, 0x17, 0x0033);
*tune_state = CT_TUNER_STEP_5;
} else if (*tune_state == CT_TUNER_STEP_5) {
dib0070_set_bandwidth(fe, ch);
@ -478,6 +472,7 @@ static int dib0070_tune_digital(struct dvb_frontend *fe, struct dvb_frontend_par
return ret;
}
static int dib0070_tune(struct dvb_frontend *fe, struct dvb_frontend_parameters *p)
{
struct dib0070_state *state = fe->tuner_priv;
@ -512,7 +507,26 @@ static int dib0070_sleep(struct dvb_frontend *fe)
return 0;
}
static const u16 dib0070_p1f_defaults[] = {
u8 dib0070_get_rf_output(struct dvb_frontend *fe)
{
struct dib0070_state *state = fe->tuner_priv;
return (dib0070_read_reg(state, 0x07) >> 11) & 0x3;
}
EXPORT_SYMBOL(dib0070_get_rf_output);
int dib0070_set_rf_output(struct dvb_frontend *fe, u8 no)
{
struct dib0070_state *state = fe->tuner_priv;
u16 rxrf2 = dib0070_read_reg(state, 0x07) & 0xfe7ff;
if (no > 3) no = 3;
if (no < 1) no = 1;
return dib0070_write_reg(state, 0x07, rxrf2 | (no << 11));
}
EXPORT_SYMBOL(dib0070_set_rf_output);
static const u16 dib0070_p1f_defaults[] =
{
7, 0x02,
0x0008,
0x0000,
@ -587,7 +601,6 @@ u16 dib0070_wbd_offset(struct dvb_frontend *fe)
return state->wbd_offset_3_3[state->wbd_gain_current - 6];
}
EXPORT_SYMBOL(dib0070_wbd_offset);
#define pgm_read_word(w) (*w)
@ -598,6 +611,7 @@ static int dib0070_reset(struct dvb_frontend *fe)
HARD_RESET(state);
#ifndef FORCE_SBAND_TUNER
if ((dib0070_read_reg(state, 0x22) >> 9) & 0x1)
state->revision = (dib0070_read_reg(state, 0x1f) >> 8) & 0xff;
@ -633,6 +647,7 @@ static int dib0070_reset(struct dvb_frontend *fe)
else
r = 2;
r |= state->cfg->osc_buffer_state << 3;
dib0070_write_reg(state, 0x10, r);
@ -655,6 +670,14 @@ static int dib0070_reset(struct dvb_frontend *fe)
return 0;
}
static int dib0070_get_frequency(struct dvb_frontend *fe, u32 *frequency)
{
struct dib0070_state *state = fe->tuner_priv;
*frequency = 1000 * state->current_rf;
return 0;
}
static int dib0070_release(struct dvb_frontend *fe)
{
kfree(fe->tuner_priv);
@ -675,7 +698,7 @@ static const struct dvb_tuner_ops dib0070_ops = {
.sleep = dib0070_sleep,
.set_params = dib0070_tune,
// .get_frequency = dib0070_get_frequency,
.get_frequency = dib0070_get_frequency,
// .get_bandwidth = dib0070_get_bandwidth
};
@ -704,7 +727,6 @@ struct dvb_frontend *dib0070_attach(struct dvb_frontend *fe, struct i2c_adapter
fe->tuner_priv = NULL;
return NULL;
}
EXPORT_SYMBOL(dib0070_attach);
MODULE_AUTHOR("Patrick Boettcher <pboettcher@dibcom.fr>");

View File

@ -52,6 +52,8 @@ struct dib0070_config {
extern struct dvb_frontend *dib0070_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, struct dib0070_config *cfg);
extern u16 dib0070_wbd_offset(struct dvb_frontend *);
extern void dib0070_ctrl_agc_filter(struct dvb_frontend *, u8 open);
extern u8 dib0070_get_rf_output(struct dvb_frontend *fe);
extern int dib0070_set_rf_output(struct dvb_frontend *fe, u8 no);
#else
static inline struct dvb_frontend *dib0070_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, struct dib0070_config *cfg)
{
@ -62,7 +64,7 @@ static inline struct dvb_frontend *dib0070_attach(struct dvb_frontend *fe, struc
static inline u16 dib0070_wbd_offset(struct dvb_frontend *fe)
{
printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
return -ENODEV;
return 0;
}
static inline void dib0070_ctrl_agc_filter(struct dvb_frontend *fe, u8 open)

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,114 @@
/*
* Linux-DVB Driver for DiBcom's DiB0090 base-band RF Tuner.
*
* Copyright (C) 2005-7 DiBcom (http://www.dibcom.fr/)
*
* 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, version 2.
*/
#ifndef DIB0090_H
#define DIB0090_H
struct dvb_frontend;
struct i2c_adapter;
#define DEFAULT_DIB0090_I2C_ADDRESS 0x60
struct dib0090_io_config {
u32 clock_khz;
u8 pll_bypass:1;
u8 pll_range:1;
u8 pll_prediv:6;
u8 pll_loopdiv:6;
u8 adc_clock_ratio; /* valid is 8, 7 ,6 */
u16 pll_int_loop_filt; // internal loop filt value. If not fill in , default is 8165
};
struct dib0090_config {
struct dib0090_io_config io;
int (*reset) (struct dvb_frontend *, int);
int (*sleep) (struct dvb_frontend *, int);
/* offset in kHz */
int freq_offset_khz_uhf;
int freq_offset_khz_vhf;
int (*get_adc_power) (struct dvb_frontend *);
u8 clkouttobamse:1; /* activate or deactivate clock output */
u8 analog_output;
u8 i2c_address;
/* add drives and other things if necessary */
u16 wbd_vhf_offset;
u16 wbd_cband_offset;
u8 use_pwm_agc;
u8 clkoutdrive;
};
#if defined(CONFIG_DVB_TUNER_DIB0090) || (defined(CONFIG_DVB_TUNER_DIB0090_MODULE) && defined(MODULE))
extern struct dvb_frontend *dib0090_register(struct dvb_frontend *fe, struct i2c_adapter *i2c, const struct dib0090_config *config);
extern void dib0090_dcc_freq(struct dvb_frontend *fe, u8 fast);
extern void dib0090_pwm_gain_reset(struct dvb_frontend *fe);
extern u16 dib0090_get_wbd_offset(struct dvb_frontend *tuner);
extern int dib0090_gain_control(struct dvb_frontend *fe);
extern enum frontend_tune_state dib0090_get_tune_state(struct dvb_frontend *fe);
extern int dib0090_set_tune_state(struct dvb_frontend *fe, enum frontend_tune_state tune_state);
extern enum frontend_tune_state dib0090_get_tune_state(struct dvb_frontend *fe);
extern void dib0090_get_current_gain(struct dvb_frontend *fe, u16 * rf, u16 * bb, u16 * rf_gain_limit, u16 * rflt);
#else
static inline struct dvb_frontend *dib0090_register(struct dvb_frontend *fe, struct i2c_adapter *i2c, struct dib0090_config *config)
{
printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
return NULL;
}
static inline void dib0090_dcc_freq(struct dvb_frontend *fe, u8 fast)
{
printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
}
static inline void dib0090_pwm_gain_reset(struct dvb_frontend *fe)
{
printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
}
static inline u16 dib0090_get_wbd_offset(struct dvb_frontend *tuner)
{
printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
return 0;
}
static inline int dib0090_gain_control(struct dvb_frontend *fe)
{
printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
return -ENODEV;
}
static inline enum frontend_tune_state dib0090_get_tune_state(struct dvb_frontend *fe)
{
printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
return CT_DONE;
}
static inline int dib0090_set_tune_state(struct dvb_frontend *fe, enum frontend_tune_state tune_state)
{
printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
return -ENODEV;
}
static inline num frontend_tune_state dib0090_get_tune_state(struct dvb_frontend *fe)
{
printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
return CT_SHUTDOWN,}
static inline void dib0090_get_current_gain(struct dvb_frontend *fe, u16 * rf, u16 * bb, u16 * rf_gain_limit, u16 * rflt)
{
printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
}
#endif
#endif

View File

@ -28,18 +28,6 @@ MODULE_PARM_DESC(debug, "turn on debugging (default: 0)");
#define dprintk(args...) do { if (debug) { printk(KERN_DEBUG "DiB8000: "); printk(args); printk("\n"); } } while (0)
enum frontend_tune_state {
CT_AGC_START = 20,
CT_AGC_STEP_0,
CT_AGC_STEP_1,
CT_AGC_STEP_2,
CT_AGC_STEP_3,
CT_AGC_STEP_4,
CT_AGC_STOP,
CT_DEMOD_START = 30,
};
#define FE_STATUS_TUNE_FAILED 0
struct i2c_device {
@ -852,6 +840,14 @@ static int dib8000_set_agc_config(struct dib8000_state *state, u8 band)
return 0;
}
void dib8000_pwm_agc_reset(struct dvb_frontend *fe)
{
struct dib8000_state *state = fe->demodulator_priv;
dib8000_set_adc_state(state, DIBX000_ADC_ON);
dib8000_set_agc_config(state, (unsigned char)(BAND_OF_FREQUENCY(fe->dtv_property_cache.frequency / 1000)));
}
EXPORT_SYMBOL(dib8000_pwm_agc_reset);
static int dib8000_agc_soft_split(struct dib8000_state *state)
{
u16 agc, split_offset;
@ -939,6 +935,32 @@ static int dib8000_agc_startup(struct dvb_frontend *fe)
}
static const int32_t lut_1000ln_mant[] =
{
908,7003,7090,7170,7244,7313,7377,7438,7495,7549,7600
};
int32_t dib8000_get_adc_power(struct dvb_frontend *fe, uint8_t mode)
{
struct dib8000_state *state = fe->demodulator_priv;
uint32_t ix =0, tmp_val =0, exp = 0, mant = 0;
int32_t val;
val = dib8000_read32(state, 384);
/* mode = 1 : ln_agcpower calc using mant-exp conversion and mantis look up table */
if(mode) {
tmp_val = val;
while(tmp_val>>=1)
exp++;
mant = (val * 1000 / (1<<exp));
ix = (uint8_t)((mant-1000)/100); /* index of the LUT */
val = (lut_1000ln_mant[ix] + 693*(exp-20) - 6908); /* 1000 * ln(adcpower_real) ; 693 = 1000ln(2) ; 6908 = 1000*ln(1000) ; 20 comes from adc_real = adc_pow_int / 2**20 */
val = (val*256)/1000;
}
return val;
}
EXPORT_SYMBOL(dib8000_get_adc_power);
static void dib8000_update_timf(struct dib8000_state *state)
{
u32 timf = state->timf = dib8000_read32(state, 435);
@ -1854,6 +1876,24 @@ static int dib8000_sleep(struct dvb_frontend *fe)
}
}
enum frontend_tune_state dib8000_get_tune_state(struct dvb_frontend* fe)
{
struct dib8000_state *state = fe->demodulator_priv;
return state->tune_state;
}
EXPORT_SYMBOL(dib8000_get_tune_state);
int dib8000_set_tune_state(struct dvb_frontend* fe, enum frontend_tune_state tune_state)
{
struct dib8000_state *state = fe->demodulator_priv;
state->tune_state = tune_state;
return 0;
}
EXPORT_SYMBOL(dib8000_set_tune_state);
static int dib8000_get_frontend(struct dvb_frontend *fe, struct dvb_frontend_parameters *fep)
{
struct dib8000_state *state = fe->demodulator_priv;

View File

@ -46,6 +46,10 @@ extern int dib8000_set_gpio(struct dvb_frontend *, u8 num, u8 dir, u8 val);
extern int dib8000_set_wbd_ref(struct dvb_frontend *, u16 value);
extern int dib8000_pid_filter_ctrl(struct dvb_frontend *, u8 onoff);
extern int dib8000_pid_filter(struct dvb_frontend *, u8 id, u16 pid, u8 onoff);
extern int dib8000_set_tune_state(struct dvb_frontend* fe, enum frontend_tune_state tune_state);
extern enum frontend_tune_state dib8000_get_tune_state(struct dvb_frontend* fe);
extern void dib8000_pwm_agc_reset(struct dvb_frontend *fe);
extern s32 dib8000_get_adc_power(struct dvb_frontend *fe, u8 mode);
#else
static inline struct dvb_frontend *dib8000_attach(struct i2c_adapter *i2c_adap, u8 i2c_addr, struct dib8000_config *cfg)
{
@ -59,35 +63,53 @@ static inline struct i2c_adapter *dib8000_get_i2c_master(struct dvb_frontend *fe
return NULL;
}
int dib8000_i2c_enumeration(struct i2c_adapter *host, int no_of_demods, u8 default_addr, u8 first_addr)
static inline int dib8000_i2c_enumeration(struct i2c_adapter *host, int no_of_demods, u8 default_addr, u8 first_addr)
{
printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
return -ENODEV;
}
int dib8000_set_gpio(struct dvb_frontend *fe, u8 num, u8 dir, u8 val)
static inline int dib8000_set_gpio(struct dvb_frontend *fe, u8 num, u8 dir, u8 val)
{
printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
return -ENODEV;
}
int dib8000_set_wbd_ref(struct dvb_frontend *fe, u16 value)
static inline int dib8000_set_wbd_ref(struct dvb_frontend *fe, u16 value)
{
printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
return -ENODEV;
}
int dib8000_pid_filter_ctrl(struct dvb_frontend *fe, u8 onoff)
static inline int dib8000_pid_filter_ctrl(struct dvb_frontend *fe, u8 onoff)
{
printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
return -ENODEV;
}
int dib8000_pid_filter(struct dvb_frontend *fe, u8 id, u16 pid, u8 onoff)
static inline int dib8000_pid_filter(struct dvb_frontend *fe, u8 id, u16 pid, u8 onoff)
{
printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
return -ENODEV;
}
static inline int dib8000_set_tune_state(struct dvb_frontend* fe, enum frontend_tune_state tune_state)
{
printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
return -ENODEV;
}
static inline enum frontend_tune_state dib8000_get_tune_state(struct dvb_frontend* fe)
{
printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
return CT_SHUTDOWN,
}
static inline void dib8000_pwm_agc_reset(struct dvb_frontend *fe)
{
printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
}
static inline s32 dib8000_get_adc_power(struct dvb_frontend *fe, u8 mode)
{
printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
}
#endif
#endif

View File

@ -6,7 +6,7 @@ static int debug;
module_param(debug, int, 0644);
MODULE_PARM_DESC(debug, "turn on debugging (default: 0)");
#define dprintk(args...) do { if (debug) { printk(KERN_DEBUG "DiBX000: "); printk(args); } } while (0)
#define dprintk(args...) do { if (debug) { printk(KERN_DEBUG "DiBX000: "); printk(args); printk("\n"); } } while (0)
static int dibx000_write_word(struct dibx000_i2c_master *mst, u16 reg, u16 val)
{
@ -25,7 +25,7 @@ static int dibx000_i2c_select_interface(struct dibx000_i2c_master *mst,
enum dibx000_i2c_interface intf)
{
if (mst->device_rev > DIB3000MC && mst->selected_interface != intf) {
dprintk("selecting interface: %d\n", intf);
dprintk("selecting interface: %d", intf);
mst->selected_interface = intf;
return dibx000_write_word(mst, mst->base_reg + 4, intf);
}
@ -171,9 +171,18 @@ void dibx000_exit_i2c_master(struct dibx000_i2c_master *mst)
{
i2c_del_adapter(&mst->gated_tuner_i2c_adap);
}
EXPORT_SYMBOL(dibx000_exit_i2c_master);
u32 systime()
{
struct timespec t;
t = current_kernel_time();
return (t.tv_sec * 10000) + (t.tv_nsec / 100000);
}
EXPORT_SYMBOL(systime);
MODULE_AUTHOR("Patrick Boettcher <pboettcher@dibcom.fr>");
MODULE_DESCRIPTION("Common function the DiBcom demodulator family");
MODULE_LICENSE("GPL");

View File

@ -36,13 +36,17 @@ extern struct i2c_adapter *dibx000_get_i2c_adapter(struct dibx000_i2c_master
extern void dibx000_exit_i2c_master(struct dibx000_i2c_master *mst);
extern void dibx000_reset_i2c_master(struct dibx000_i2c_master *mst);
extern u32 systime(void);
#define BAND_LBAND 0x01
#define BAND_UHF 0x02
#define BAND_VHF 0x04
#define BAND_SBAND 0x08
#define BAND_FM 0x10
#define BAND_CBAND 0x20
#define BAND_OF_FREQUENCY(freq_kHz) ( (freq_kHz) <= 115000 ? BAND_FM : \
#define BAND_OF_FREQUENCY(freq_kHz) ( (freq_kHz) <= 170000 ? BAND_CBAND : \
(freq_kHz) <= 115000 ? BAND_FM : \
(freq_kHz) <= 250000 ? BAND_VHF : \
(freq_kHz) <= 863000 ? BAND_UHF : \
(freq_kHz) <= 2000000 ? BAND_LBAND : BAND_SBAND )
@ -149,4 +153,67 @@ enum dibx000_adc_states {
#define OUTMODE_MPEG2_FIFO 5
#define OUTMODE_ANALOG_ADC 6
enum frontend_tune_state {
CT_TUNER_START = 10,
CT_TUNER_STEP_0,
CT_TUNER_STEP_1,
CT_TUNER_STEP_2,
CT_TUNER_STEP_3,
CT_TUNER_STEP_4,
CT_TUNER_STEP_5,
CT_TUNER_STEP_6,
CT_TUNER_STEP_7,
CT_TUNER_STOP,
CT_AGC_START = 20,
CT_AGC_STEP_0,
CT_AGC_STEP_1,
CT_AGC_STEP_2,
CT_AGC_STEP_3,
CT_AGC_STEP_4,
CT_AGC_STOP,
CT_DEMOD_START = 30,
CT_DEMOD_STEP_1,
CT_DEMOD_STEP_2,
CT_DEMOD_STEP_3,
CT_DEMOD_STEP_4,
CT_DEMOD_STEP_5,
CT_DEMOD_STEP_6,
CT_DEMOD_STEP_7,
CT_DEMOD_STEP_8,
CT_DEMOD_STEP_9,
CT_DEMOD_STEP_10,
CT_DEMOD_SEARCH_NEXT = 41,
CT_DEMOD_STEP_LOCKED,
CT_DEMOD_STOP,
CT_DONE = 100,
CT_SHUTDOWN,
};
struct dvb_frontend_parametersContext {
#define CHANNEL_STATUS_PARAMETERS_UNKNOWN 0x01
#define CHANNEL_STATUS_PARAMETERS_SET 0x02
u8 status;
u32 tune_time_estimation[2];
s32 tps_available;
u16 tps[9];
};
#define FE_STATUS_TUNE_FAILED 0
#define FE_STATUS_TUNE_TIMED_OUT -1
#define FE_STATUS_TUNE_TIME_TOO_SHORT -2
#define FE_STATUS_TUNE_PENDING -3
#define FE_STATUS_STD_SUCCESS -4
#define FE_STATUS_FFT_SUCCESS -5
#define FE_STATUS_DEMOD_SUCCESS -6
#define FE_STATUS_LOCKED -7
#define FE_STATUS_DATA_LOCKED -8
#define FE_CALLBACK_TIME_NEVER 0xffffffff
#define ABS(x) ((x<0)?(-x):(x))
#endif