Commit be9bae10 authored by Olivier Grenie's avatar Olivier Grenie Committed by Mauro Carvalho Chehab

[media] DiB0700: add support for several board-layouts

This patchs adds support for DiBcom's NIM8096MD, NIM9090M, NIM9090MD,
NIM7090, TFE7090PVR (no diversity) reference designs.
Signed-off-by: default avatarOlivier Grenie <olivier.grenie@dibcom.fr>
Signed-off-by: default avatarPatrick Boettcher <patrick.boettcher@dibcom.fr>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab@redhat.com>
parent 713d54a8
...@@ -186,7 +186,7 @@ static int dib0700_i2c_xfer_new(struct i2c_adapter *adap, struct i2c_msg *msg, ...@@ -186,7 +186,7 @@ static int dib0700_i2c_xfer_new(struct i2c_adapter *adap, struct i2c_msg *msg,
msg[i].len, msg[i].len,
USB_CTRL_GET_TIMEOUT); USB_CTRL_GET_TIMEOUT);
if (result < 0) { if (result < 0) {
err("i2c read error (status = %d)\n", result); deb_info("i2c read error (status = %d)\n", result);
break; break;
} }
...@@ -215,7 +215,7 @@ static int dib0700_i2c_xfer_new(struct i2c_adapter *adap, struct i2c_msg *msg, ...@@ -215,7 +215,7 @@ static int dib0700_i2c_xfer_new(struct i2c_adapter *adap, struct i2c_msg *msg,
0, 0, buf, msg[i].len + 4, 0, 0, buf, msg[i].len + 4,
USB_CTRL_GET_TIMEOUT); USB_CTRL_GET_TIMEOUT);
if (result < 0) { if (result < 0) {
err("i2c write error (status = %d)\n", result); deb_info("i2c write error (status = %d)\n", result);
break; break;
} }
} }
......
...@@ -12,6 +12,7 @@ ...@@ -12,6 +12,7 @@
#include "dib7000m.h" #include "dib7000m.h"
#include "dib7000p.h" #include "dib7000p.h"
#include "dib8000.h" #include "dib8000.h"
#include "dib9000.h"
#include "mt2060.h" #include "mt2060.h"
#include "mt2266.h" #include "mt2266.h"
#include "tuner-xc2028.h" #include "tuner-xc2028.h"
...@@ -29,6 +30,7 @@ MODULE_PARM_DESC(force_lna_activation, "force the activation of Low-Noise-Amplif ...@@ -29,6 +30,7 @@ MODULE_PARM_DESC(force_lna_activation, "force the activation of Low-Noise-Amplif
struct dib0700_adapter_state { struct dib0700_adapter_state {
int (*set_param_save) (struct dvb_frontend *, struct dvb_frontend_parameters *); int (*set_param_save) (struct dvb_frontend *, struct dvb_frontend_parameters *);
const struct firmware *frontend_firmware;
}; };
/* Hauppauge Nova-T 500 (aka Bristol) /* Hauppauge Nova-T 500 (aka Bristol)
...@@ -1243,13 +1245,13 @@ static int dib807x_tuner_attach(struct dvb_usb_adapter *adap) ...@@ -1243,13 +1245,13 @@ static int dib807x_tuner_attach(struct dvb_usb_adapter *adap)
static int stk80xx_pid_filter(struct dvb_usb_adapter *adapter, int index, static int stk80xx_pid_filter(struct dvb_usb_adapter *adapter, int index,
u16 pid, int onoff) u16 pid, int onoff)
{ {
return dib8000_pid_filter(adapter->fe, index, pid, onoff); return dib8000_pid_filter(adapter->fe, index, pid, onoff);
} }
static int stk80xx_pid_filter_ctrl(struct dvb_usb_adapter *adapter, static int stk80xx_pid_filter_ctrl(struct dvb_usb_adapter *adapter,
int onoff) int onoff)
{ {
return dib8000_pid_filter_ctrl(adapter->fe, onoff); return dib8000_pid_filter_ctrl(adapter->fe, onoff);
} }
/* STK807x */ /* STK807x */
...@@ -1321,11 +1323,11 @@ static int stk807xpvr_frontend_attach1(struct dvb_usb_adapter *adap) ...@@ -1321,11 +1323,11 @@ static int stk807xpvr_frontend_attach1(struct dvb_usb_adapter *adap)
/* STK8096GP */ /* STK8096GP */
struct dibx000_agc_config dib8090_agc_config[2] = { struct dibx000_agc_config dib8090_agc_config[2] = {
{ {
BAND_UHF | BAND_VHF | BAND_LBAND | BAND_SBAND, 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_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_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 */ * 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) (0 << 15) | (0 << 14) | (5 << 11) | (0 << 10) | (0 << 9) | (0 << 8)
| (3 << 5) | (0 << 4) | (5 << 1) | (0 << 0), | (3 << 5) | (0 << 4) | (5 << 1) | (0 << 0),
...@@ -1362,12 +1364,12 @@ struct dibx000_agc_config dib8090_agc_config[2] = { ...@@ -1362,12 +1364,12 @@ struct dibx000_agc_config dib8090_agc_config[2] = {
51, 51,
0, 0,
}, },
{ {
BAND_CBAND, BAND_CBAND,
/* P_agc_use_sd_mod1=0, P_agc_use_sd_mod2=0, P_agc_freq_pwm_div=1, /* 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_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 */ * 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) (0 << 15) | (0 << 14) | (5 << 11) | (0 << 10) | (0 << 9) | (0 << 8)
| (3 << 5) | (0 << 4) | (5 << 1) | (0 << 0), | (3 << 5) | (0 << 4) | (5 << 1) | (0 << 0),
...@@ -1404,159 +1406,1098 @@ struct dibx000_agc_config dib8090_agc_config[2] = { ...@@ -1404,159 +1406,1098 @@ struct dibx000_agc_config dib8090_agc_config[2] = {
51, 51,
0, 0,
} }
}; };
static struct dibx000_bandwidth_config dib8090_pll_config_12mhz = { static struct dibx000_bandwidth_config dib8090_pll_config_12mhz = {
54000, 13500, 54000, 13500,
1, 18, 3, 1, 0, 1, 18, 3, 1, 0,
0, 0, 1, 1, 2, 0, 0, 1, 1, 2,
(3 << 14) | (1 << 12) | (599 << 0), (3 << 14) | (1 << 12) | (599 << 0),
(0 << 25) | 0, (0 << 25) | 0,
20199727, 20199727,
12000000, 12000000,
}; };
static int dib8090_get_adc_power(struct dvb_frontend *fe) static int dib8090_get_adc_power(struct dvb_frontend *fe)
{ {
return dib8000_get_adc_power(fe, 1); return dib8000_get_adc_power(fe, 1);
}
static struct dib8000_config dib809x_dib8000_config[2] = {
{
.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 = 48,
.refclksel = 3,
},{
.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_DIVERSITY,
.drives = 0x2d08,
.diversity_delay = 1,
.refclksel = 3,
}
};
static struct dib0090_wbd_slope dib8090_wbd_table[] = {
/* max freq ; cold slope ; cold offset ; warm slope ; warm offset ; wbd gain */
{ 120, 0, 500, 0, 500, 4 }, /* CBAND */
{ 170, 0, 450, 0, 450, 4 }, /* CBAND */
{ 380, 48, 373, 28, 259, 6 }, /* VHF */
{ 860, 34, 700, 36, 616, 6 }, /* high UHF */
{ 0xFFFF, 34, 700, 36, 616, 6 }, /* default */
};
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,
.use_pwm_agc = 1,
.clkoutdrive = 1,
.get_adc_power = dib8090_get_adc_power,
.freq_offset_khz_uhf = -63,
.freq_offset_khz_vhf = -143,
.wbd = dib8090_wbd_table,
.fref_clock_ratio = 6,
};
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 target;
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;
target = (dib0090_get_wbd_offset(fe) * 8 * 18 / 33 + 1) / 2;
dib8000_set_wbd_ref(fe, target);
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[0]);
return adap->fe == NULL ? -ENODEV : 0;
}
static int nim8096md_tuner_attach(struct dvb_usb_adapter *adap)
{
struct dib0700_adapter_state *st = adap->priv;
struct i2c_adapter *tun_i2c;
struct dvb_frontend *fe_slave = dib8000_get_slave_frontend(adap->fe, 1);
if (fe_slave) {
tun_i2c = dib8000_get_i2c_master(fe_slave, DIBX000_I2C_INTERFACE_TUNER, 1);
if (dvb_attach(dib0090_register, fe_slave, tun_i2c, &dib809x_dib0090_config) == NULL)
return -ENODEV;
fe_slave->dvb = adap->fe->dvb;
fe_slave->ops.tuner_ops.set_params = dib8096_set_param_override;
}
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 nim8096md_frontend_attach(struct dvb_usb_adapter *adap)
{
struct dvb_frontend *fe_slave;
dib0700_set_gpio(adap->dev, GPIO6, GPIO_OUT, 0);
msleep(10);
dib0700_set_gpio(adap->dev, GPIO6, GPIO_OUT, 1);
msleep(1000);
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, 2, 18, 0x80);
adap->fe = dvb_attach(dib8000_attach, &adap->dev->i2c_adap, 0x80, &dib809x_dib8000_config[0]);
if (adap->fe == NULL)
return -ENODEV;
fe_slave = dvb_attach(dib8000_attach, &adap->dev->i2c_adap, 0x82, &dib809x_dib8000_config[1]);
dib8000_set_slave_frontend(adap->fe, fe_slave);
return fe_slave == NULL ? -ENODEV : 0;
}
/* STK9090M */
static int dib90x0_pid_filter(struct dvb_usb_adapter *adapter, int index, u16 pid, int onoff)
{
return dib9000_fw_pid_filter(adapter->fe, index, pid, onoff);
}
static int dib90x0_pid_filter_ctrl(struct dvb_usb_adapter *adapter, int onoff)
{
return dib9000_fw_pid_filter_ctrl(adapter->fe, onoff);
}
static int dib90x0_tuner_reset(struct dvb_frontend *fe, int onoff)
{
return dib9000_set_gpio(fe, 5, 0, !onoff);
}
static int dib90x0_tuner_sleep(struct dvb_frontend *fe, int onoff)
{
return dib9000_set_gpio(fe, 0, 0, onoff);
}
static int dib01x0_pmu_update(struct i2c_adapter *i2c, u16 *data, u8 len)
{
u8 wb[4] = { 0xc >> 8, 0xc & 0xff, 0, 0 };
u8 rb[2];
struct i2c_msg msg[2] = {
{.addr = 0x1e >> 1,.flags = 0,.buf = wb,.len = 2},
{.addr = 0x1e >> 1,.flags = I2C_M_RD,.buf = rb,.len = 2},
};
u8 index_data;
dibx000_i2c_set_speed(i2c, 250);
if (i2c_transfer(i2c, msg, 2) != 2)
return -EIO;
switch (rb[0] << 8 | rb[1]) {
case 0:
deb_info("Found DiB0170 rev1: This version of DiB0170 is not supported any longer.\n");
return -EIO;
case 1:
deb_info("Found DiB0170 rev2");
break;
case 2:
deb_info("Found DiB0190 rev2");
break;
default:
deb_info("DiB01x0 not found");
return -EIO;
}
for (index_data = 0; index_data < len; index_data += 2) {
wb[2] = (data[index_data + 1] >> 8) & 0xff;
wb[3] = (data[index_data + 1]) & 0xff;
if (data[index_data] == 0) {
wb[0] = (data[index_data] >> 8) & 0xff;
wb[1] = (data[index_data]) & 0xff;
msg[0].len = 2;
if (i2c_transfer(i2c, msg, 2) != 2)
return -EIO;
wb[2] |= rb[0];
wb[3] |= rb[1] & ~(3 << 4);
}
wb[0] = (data[index_data ] >> 8)&0xff;
wb[1] = (data[index_data ] )&0xff;
msg[0].len = 4;
if (i2c_transfer(i2c, &msg[0], 1) != 1)
return -EIO;
}
return 0;
}
static struct dib9000_config stk9090m_config = {
.output_mpeg2_in_188_bytes = 1,
.output_mode = OUTMODE_MPEG2_FIFO,
.vcxo_timer = 279620,
.timing_frequency = 20452225,
.demod_clock_khz = 60000,
.xtal_clock_khz = 30000,
.if_drives = (0 << 15) | (1 << 13) | (0 << 12) | (3 << 10) | (0 << 9) | (1 << 7) | (0 << 6) | (0 << 4) | (1 << 3) | (1 << 1) | (0),
.subband = {
2,
{
{ 240, { BOARD_GPIO_COMPONENT_DEMOD, BOARD_GPIO_FUNCTION_SUBBAND_GPIO, 0x0008, 0x0000, 0x0008 } }, /* GPIO 3 to 1 for VHF */
{ 890, { BOARD_GPIO_COMPONENT_DEMOD, BOARD_GPIO_FUNCTION_SUBBAND_GPIO, 0x0008, 0x0000, 0x0000 } }, /* GPIO 3 to 0 for UHF */
{ 0 },
},
},
.gpio_function = {
{ .component = BOARD_GPIO_COMPONENT_DEMOD, .function = BOARD_GPIO_FUNCTION_COMPONENT_ON, .mask = 0x10 | 0x21, .direction = 0 & ~0x21, .value = (0x10 & ~0x1) | 0x20 },
{ .component = BOARD_GPIO_COMPONENT_DEMOD, .function = BOARD_GPIO_FUNCTION_COMPONENT_OFF, .mask = 0x10 | 0x21, .direction = 0 & ~0x21, .value = 0 | 0x21 },
},
};
static struct dib9000_config nim9090md_config[2] = {
{
.output_mpeg2_in_188_bytes = 1,
.output_mode = OUTMODE_MPEG2_FIFO,
.vcxo_timer = 279620,
.timing_frequency = 20452225,
.demod_clock_khz = 60000,
.xtal_clock_khz = 30000,
.if_drives = (0 << 15) | (1 << 13) | (0 << 12) | (3 << 10) | (0 << 9) | (1 << 7) | (0 << 6) | (0 << 4) | (1 << 3) | (1 << 1) | (0),
}, {
.output_mpeg2_in_188_bytes = 1,
.output_mode = OUTMODE_DIVERSITY,
.vcxo_timer = 279620,
.timing_frequency = 20452225,
.demod_clock_khz = 60000,
.xtal_clock_khz = 30000,
.if_drives = (0 << 15) | (1 << 13) | (0 << 12) | (3 << 10) | (0 << 9) | (1 << 7) | (0 << 6) | (0 << 4) | (1 << 3) | (1 << 1) | (0),
.subband = {
2,
{
{ 240, { BOARD_GPIO_COMPONENT_DEMOD, BOARD_GPIO_FUNCTION_SUBBAND_GPIO, 0x0006, 0x0000, 0x0006 } }, /* GPIO 1 and 2 to 1 for VHF */
{ 890, { BOARD_GPIO_COMPONENT_DEMOD, BOARD_GPIO_FUNCTION_SUBBAND_GPIO, 0x0006, 0x0000, 0x0000 } }, /* GPIO 1 and 2 to 0 for UHF */
{ 0 },
},
},
.gpio_function = {
{ .component = BOARD_GPIO_COMPONENT_DEMOD, .function = BOARD_GPIO_FUNCTION_COMPONENT_ON, .mask = 0x10 | 0x21, .direction = 0 & ~0x21, .value = (0x10 & ~0x1) | 0x20 },
{ .component = BOARD_GPIO_COMPONENT_DEMOD, .function = BOARD_GPIO_FUNCTION_COMPONENT_OFF, .mask = 0x10 | 0x21, .direction = 0 & ~0x21, .value = 0 | 0x21 },
},
}
};
static struct dib0090_config dib9090_dib0090_config = {
.io.pll_bypass = 0,
.io.pll_range = 1,
.io.pll_prediv = 1,
.io.pll_loopdiv = 8,
.io.adc_clock_ratio = 8,
.io.pll_int_loop_filt = 0,
.io.clock_khz = 30000,
.reset = dib90x0_tuner_reset,
.sleep = dib90x0_tuner_sleep,
.clkouttobamse = 0,
.analog_output = 0,
.use_pwm_agc = 0,
.clkoutdrive = 0,
.freq_offset_khz_uhf = 0,
.freq_offset_khz_vhf = 0,
};
static struct dib0090_config nim9090md_dib0090_config[2] = {
{
.io.pll_bypass = 0,
.io.pll_range = 1,
.io.pll_prediv = 1,
.io.pll_loopdiv = 8,
.io.adc_clock_ratio = 8,
.io.pll_int_loop_filt = 0,
.io.clock_khz = 30000,
.reset = dib90x0_tuner_reset,
.sleep = dib90x0_tuner_sleep,
.clkouttobamse = 1,
.analog_output = 0,
.use_pwm_agc = 0,
.clkoutdrive = 0,
.freq_offset_khz_uhf = 0,
.freq_offset_khz_vhf = 0,
},{
.io.pll_bypass = 0,
.io.pll_range = 1,
.io.pll_prediv = 1,
.io.pll_loopdiv = 8,
.io.adc_clock_ratio = 8,
.io.pll_int_loop_filt = 0,
.io.clock_khz = 30000,
.reset = dib90x0_tuner_reset,
.sleep = dib90x0_tuner_sleep,
.clkouttobamse = 0,
.analog_output = 0,
.use_pwm_agc = 0,
.clkoutdrive = 0,
.freq_offset_khz_uhf = 0,
.freq_offset_khz_vhf = 0,
}
};
static int stk9090m_frontend_attach(struct dvb_usb_adapter *adap)
{
struct dib0700_adapter_state *state = adap->priv;
struct dib0700_state *st = adap->dev->priv;
u32 fw_version;
/* Make use of the new i2c functions from FW 1.20 */
dib0700_get_version(adap->dev, NULL, NULL, &fw_version, NULL);
if (fw_version >= 0x10200)
st->fw_use_new_i2c_api = 1;
dib0700_set_i2c_speed(adap->dev, 340);
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);
dib9000_i2c_enumeration(&adap->dev->i2c_adap, 1, 0x10, 0x80);
if (request_firmware(&state->frontend_firmware, "dib9090.fw", &adap->dev->udev->dev)) {
deb_info("%s: Upload failed. (file not found?)\n", __func__);
return -ENODEV;
} else {
deb_info("%s: firmware read %Zu bytes.\n", __func__, state->frontend_firmware->size);
}
stk9090m_config.microcode_B_fe_size = state->frontend_firmware->size;
stk9090m_config.microcode_B_fe_buffer = state->frontend_firmware->data;
adap->fe = dvb_attach(dib9000_attach, &adap->dev->i2c_adap, 0x80, &stk9090m_config);
return adap->fe == NULL ? -ENODEV : 0;
}
static int dib9090_tuner_attach(struct dvb_usb_adapter *adap)
{
struct dib0700_adapter_state *state = adap->priv;
struct i2c_adapter *i2c = dib9000_get_tuner_interface(adap->fe);
u16 data_dib190[10] = {
1, 0x1374,
2, 0x01a2,
7, 0x0020,
0, 0x00ef,
8, 0x0486,
};
if (dvb_attach(dib0090_fw_register, adap->fe, i2c, &dib9090_dib0090_config) == NULL)
return -ENODEV;
i2c = dib9000_get_i2c_master(adap->fe, DIBX000_I2C_INTERFACE_GPIO_1_2, 0);
if (dib01x0_pmu_update(i2c, data_dib190, 10) != 0)
return -ENODEV;
dib0700_set_i2c_speed(adap->dev, 2000);
if (dib9000_firmware_post_pll_init(adap->fe) < 0)
return -ENODEV;
release_firmware(state->frontend_firmware);
return 0;
}
static int nim9090md_frontend_attach(struct dvb_usb_adapter *adap)
{
struct dib0700_adapter_state *state = adap->priv;
struct dib0700_state *st = adap->dev->priv;
struct i2c_adapter *i2c;
struct dvb_frontend *fe_slave;
u32 fw_version;
/* Make use of the new i2c functions from FW 1.20 */
dib0700_get_version(adap->dev, NULL, NULL, &fw_version, NULL);
if (fw_version >= 0x10200)
st->fw_use_new_i2c_api = 1;
dib0700_set_i2c_speed(adap->dev, 340);
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);
if (request_firmware(&state->frontend_firmware, "dib9090.fw", &adap->dev->udev->dev)) {
deb_info("%s: Upload failed. (file not found?)\n", __func__);
return -EIO;
} else {
deb_info("%s: firmware read %Zu bytes.\n", __func__, state->frontend_firmware->size);
}
nim9090md_config[0].microcode_B_fe_size = state->frontend_firmware->size;
nim9090md_config[0].microcode_B_fe_buffer = state->frontend_firmware->data;
nim9090md_config[1].microcode_B_fe_size = state->frontend_firmware->size;
nim9090md_config[1].microcode_B_fe_buffer = state->frontend_firmware->data;
dib9000_i2c_enumeration(&adap->dev->i2c_adap, 1, 0x20, 0x80);
adap->fe = dvb_attach(dib9000_attach, &adap->dev->i2c_adap, 0x80, &nim9090md_config[0]);
if (adap->fe == NULL)
return -ENODEV;
i2c = dib9000_get_i2c_master(adap->fe, DIBX000_I2C_INTERFACE_GPIO_3_4, 0);
dib9000_i2c_enumeration(i2c, 1, 0x12, 0x82);
fe_slave = dvb_attach(dib9000_attach, i2c, 0x82, &nim9090md_config[1]);
dib9000_set_slave_frontend(adap->fe, fe_slave);
return fe_slave == NULL ? -ENODEV : 0;
} }
static struct dib8000_config dib809x_dib8000_config = { static int nim9090md_tuner_attach(struct dvb_usb_adapter *adap)
.output_mpeg2_in_188_bytes = 1, {
struct dib0700_adapter_state *state = adap->priv;
.agc_config_count = 2, struct i2c_adapter *i2c;
.agc = dib8090_agc_config, struct dvb_frontend *fe_slave;
.agc_control = dib0090_dcc_freq, u16 data_dib190[10] = {
.pll = &dib8090_pll_config_12mhz, 1, 0x5374,
.tuner_is_baseband = 1, 2, 0x01ae,
7, 0x0020,
.gpio_dir = DIB8000_GPIO_DEFAULT_DIRECTIONS, 0, 0x00ef,
.gpio_val = DIB8000_GPIO_DEFAULT_VALUES, 8, 0x0406,
.gpio_pwm_pos = DIB8000_GPIO_DEFAULT_PWM_POS, };
i2c = dib9000_get_tuner_interface(adap->fe);
.hostbus_diversity = 1, if (dvb_attach(dib0090_fw_register, adap->fe, i2c, &nim9090md_dib0090_config[0]) == NULL)
.div_cfg = 0x31, return -ENODEV;
.output_mode = OUTMODE_MPEG2_FIFO, i2c = dib9000_get_i2c_master(adap->fe, DIBX000_I2C_INTERFACE_GPIO_1_2, 0);
.drives = 0x2d98, if (dib01x0_pmu_update(i2c, data_dib190, 10) < 0)
.diversity_delay = 144, return -ENODEV;
.refclksel = 3, dib0700_set_i2c_speed(adap->dev, 2000);
if (dib9000_firmware_post_pll_init(adap->fe) < 0)
return -ENODEV;
fe_slave = dib9000_get_slave_frontend(adap->fe, 1);
if (fe_slave != NULL) {
i2c = dib9000_get_component_bus_interface(adap->fe);
dib9000_set_i2c_adapter(fe_slave, i2c);
i2c = dib9000_get_tuner_interface(fe_slave);
if (dvb_attach(dib0090_fw_register, fe_slave, i2c, &nim9090md_dib0090_config[1]) == NULL)
return -ENODEV;
fe_slave->dvb = adap->fe->dvb;
dib9000_fw_set_component_bus_speed(adap->fe, 2000);
if (dib9000_firmware_post_pll_init(fe_slave) < 0)
return -ENODEV;
}
release_firmware(state->frontend_firmware);
return 0;
}
/* NIM7090 */
struct dib7090p_best_adc {
u32 timf;
u32 pll_loopdiv;
u32 pll_prediv;
};
static int dib7090p_get_best_sampling(struct dvb_frontend *fe , struct dib7090p_best_adc *adc)
{
u8 spur = 0, prediv = 0, loopdiv = 0, min_prediv = 1, max_prediv = 1;
u16 xtal = 12000;
u32 fcp_min = 1900; /* PLL Minimum Frequency comparator KHz */
u32 fcp_max = 20000; /* PLL Maximum Frequency comparator KHz */
u32 fdem_max = 76000;
u32 fdem_min = 69500;
u32 fcp = 0, fs = 0, fdem = 0;
u32 harmonic_id = 0;
adc->pll_loopdiv = loopdiv;
adc->pll_prediv = prediv;
adc->timf = 0;
deb_info("bandwidth = %d fdem_min =%d", fe->dtv_property_cache.bandwidth_hz, fdem_min);
/* Find Min and Max prediv */
while((xtal/max_prediv) >= fcp_min)
max_prediv++;
max_prediv--;
min_prediv = max_prediv;
while((xtal/min_prediv) <= fcp_max) {
min_prediv--;
if(min_prediv == 1)
break;
}
deb_info("MIN prediv = %d : MAX prediv = %d", min_prediv, max_prediv);
min_prediv = 2;
for(prediv = min_prediv ; prediv < max_prediv; prediv ++) {
fcp = xtal / prediv;
if(fcp > fcp_min && fcp < fcp_max) {
for(loopdiv = 1 ; loopdiv < 64 ; loopdiv++) {
fdem = ((xtal/prediv) * loopdiv);
fs = fdem / 4;
/* test min/max system restrictions */
if((fdem >= fdem_min) && (fdem <= fdem_max) && (fs >= fe->dtv_property_cache.bandwidth_hz/1000)) {
spur = 0;
/* test fs harmonics positions */
for(harmonic_id = (fe->dtv_property_cache.frequency / (1000*fs)) ; harmonic_id <= ((fe->dtv_property_cache.frequency / (1000*fs))+1) ; harmonic_id++) {
if(((fs*harmonic_id) >= ((fe->dtv_property_cache.frequency/1000) - (fe->dtv_property_cache.bandwidth_hz/2000))) && ((fs*harmonic_id) <= ((fe->dtv_property_cache.frequency/1000) + (fe->dtv_property_cache.bandwidth_hz/2000)))) {
spur = 1;
break;
}
}
if(!spur) {
adc->pll_loopdiv = loopdiv;
adc->pll_prediv = prediv;
adc->timf = 2396745143UL/fdem*(1<<9);
adc->timf+= ((2396745143UL%fdem)<< 9)/fdem;
deb_info("loopdiv=%i prediv=%i timf=%i", loopdiv, prediv, adc->timf);
break;
}
}
}
}
if (!spur)
break;
}
if(adc->pll_loopdiv == 0 && adc->pll_prediv == 0) {
return -EINVAL;
} else
return 0;
}
static int dib7090_agc_startup(struct dvb_frontend *fe, struct dvb_frontend_parameters *fep)
{
struct dvb_usb_adapter *adap = fe->dvb->priv;
struct dib0700_adapter_state *state = adap->priv;
struct dibx000_bandwidth_config pll;
u16 target;
struct dib7090p_best_adc adc;
int ret;
ret = state->set_param_save(fe, fep);
if (ret < 0)
return ret;
memset(&pll, 0, sizeof(struct dibx000_bandwidth_config));
dib0090_pwm_gain_reset(fe);
target = (dib0090_get_wbd_offset(fe) * 8 + 1) / 2;
dib7000p_set_wbd_ref(fe, target);
if(dib7090p_get_best_sampling(fe, &adc) == 0) {
pll.pll_ratio = adc.pll_loopdiv;
pll.pll_prediv = adc.pll_prediv;
dib7000p_update_pll(fe, &pll);
dib7000p_ctrl_timf(fe, DEMOD_TIMF_SET, adc.timf);
}
return 0;
}
static struct dib0090_wbd_slope dib7090_wbd_table[] = {
{ 380, 81, 850, 64, 540 ,4},
{ 860, 51, 866, 21, 375 ,4},
{1700, 0, 250, 0, 100, 6}, //LBAND Predefinition , NOT tested Yet
{2600, 0, 250, 0, 100, 6}, //SBAND Predefinition , NOT tested Yet
{ 0xFFFF, 0, 0, 0, 0 ,0},
}; };
static struct dib0090_config dib809x_dib0090_config = { struct dibx000_agc_config dib7090_agc_config[2] = {
.io.pll_bypass = 1, {
.io.pll_range = 1, .band_caps = BAND_UHF,
.io.pll_prediv = 1, /* 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,
.io.pll_loopdiv = 20, * 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 */
.io.adc_clock_ratio = 8, .setup = (0 << 15) | (0 << 14) | (5 << 11) | (0 << 10) | (0 << 9) | (0 << 8) | (3 << 5) | (0 << 4) | (5 << 1) | (0 << 0), // setup
.io.pll_int_loop_filt = 0,
.io.clock_khz = 12000, .inv_gain = 687,// inv_gain = 1/ 95.4dB // no boost, lower gain due to ramp quantification
.reset = dib80xx_tuner_reset, .time_stabiliz = 10, // time_stabiliz
.sleep = dib80xx_tuner_sleep,
.clkouttobamse = 1, .alpha_level = 0, // alpha_level
.analog_output = 1, .thlock = 118, // thlock
.i2c_address = DEFAULT_DIB0090_I2C_ADDRESS,
.wbd_vhf_offset = 100, .wbd_inv = 0, // wbd_inv
.wbd_cband_offset = 450, .wbd_ref = 1200, // wbd_ref
.use_pwm_agc = 1, .wbd_sel = 3, // wbd_sel
.clkoutdrive = 1, .wbd_alpha = 5, // wbd_alpha
.get_adc_power = dib8090_get_adc_power,
.freq_offset_khz_uhf = 0, .agc1_max = 65535, // agc1_max
.freq_offset_khz_vhf = -143, .agc1_min = 0, // agc1_min
};
.agc2_max = 65535, // agc2_max
.agc2_min = 0, // agc2_min
.agc1_pt1 = 0, // agc1_pt1
.agc1_pt2 = 32, // agc1_pt2
.agc1_pt3 = 114, // agc1_pt3 // 40.4dB
.agc1_slope1 = 143, // agc1_slope1
.agc1_slope2 = 144, // agc1_slope2
.agc2_pt1 = 114, // agc2_pt1
.agc2_pt2 = 227, // agc2_pt2
.agc2_slope1 = 116, // agc2_slope1
.agc2_slope2 = 117, // agc2_slope2
.alpha_mant = 18, // alpha_mant // 5Hz with 95.4dB
.alpha_exp = 0, // alpha_exp
.beta_mant = 20, // beta_mant
.beta_exp = 59, // beta_exp
.perform_agc_softsplit = 0, // perform_agc_softsplit
} , {
.band_caps = BAND_FM | BAND_VHF | 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 */
.setup = (0 << 15) | (0 << 14) | (5 << 11) | (0 << 10) | (0 << 9) | (0 << 8) | (3 << 5) | (0 << 4) | (5 << 1) | (0 << 0), // setup
.inv_gain = 732,// inv_gain = 1/ 89.5dB // no boost, lower gain due to ramp quantification
.time_stabiliz = 10, // time_stabiliz
.alpha_level = 0, // alpha_level
.thlock = 118, // thlock
.wbd_inv = 0, // wbd_inv
.wbd_ref = 1200, // wbd_ref
.wbd_sel = 3, // wbd_sel
.wbd_alpha = 5, // wbd_alpha
.agc1_max = 65535, // agc1_max : 1
.agc1_min = 0, // agc1_min
.agc2_max = 65535, // agc2_max
.agc2_min = 0, // agc2_min
.agc1_pt1 = 0, // agc1_pt1
.agc1_pt2 = 0, // agc1_pt2
.agc1_pt3 = 98, // agc1_pt3 // 34.5dB CBAND P1G + 55dB BB boost = 89.5dB
.agc1_slope1 = 0, // agc1_slope1
.agc1_slope2 = 167, // agc1_slope2 = Dy/Dx * 2**6 * 2**8 = 1/98 * 2**6 *2**8 : Dy = 1
.agc1_pt1 = 98, // agc2_pt1
.agc2_pt2 = 255, // agc2_pt2
.agc2_slope1 = 104, // agc2_slope1 = Dy/Dx * 2**6 * 2**8 = 1/(255-98) * 2**6 *2**8
.agc2_slope2 = 0, // agc2_slope2
.alpha_mant = 18, // alpha_mant // 5Hz with 95.4dB
.alpha_exp = 0, // alpha_exp
.beta_mant = 20, // beta_mant
.beta_exp = 59, // beta_exp
.perform_agc_softsplit = 0, // perform_agc_softsplit
}
};
static struct dibx000_bandwidth_config dib7090_clock_config_12_mhz = {
60000, 15000, // internal, sampling
1, 5, 0, 0, 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) | (524 << 0), // sad_cfg: refsel, sel, freq_15k
(0 << 25) | 0, // ifreq = 0.000000 MHz
20452225, // timf
15000000, // xtal_hz
};
static struct dib7000p_config nim7090_dib7000p_config = {
.output_mpeg2_in_188_bytes = 1,
.hostbus_diversity = 1,
.tuner_is_baseband = 1,
.update_lna = NULL,
.agc_config_count = 2,
.agc = dib7090_agc_config,
.bw = &dib7090_clock_config_12_mhz,
.gpio_dir = DIB7000P_GPIO_DEFAULT_DIRECTIONS,
.gpio_val = DIB7000P_GPIO_DEFAULT_VALUES,
.gpio_pwm_pos = DIB7000P_GPIO_DEFAULT_PWM_POS,
.pwm_freq_div = 0,
.agc_control = dib7090_agc_restart,
.spur_protect = 0,
.disable_sample_and_hold = 0,
.enable_current_mirror = 0,
.diversity_delay = 0,
.output_mode = OUTMODE_MPEG2_FIFO,
.enMpegOutput = 1,
};
static struct dib7000p_config tfe7090pvr_dib7000p_config[2] = {
{
.output_mpeg2_in_188_bytes = 1,
.hostbus_diversity = 1,
.tuner_is_baseband = 1,
.update_lna = NULL,
.agc_config_count = 2,
.agc = dib7090_agc_config,
.bw = &dib7090_clock_config_12_mhz,
.gpio_dir = DIB7000P_GPIO_DEFAULT_DIRECTIONS,
.gpio_val = DIB7000P_GPIO_DEFAULT_VALUES,
.gpio_pwm_pos = DIB7000P_GPIO_DEFAULT_PWM_POS,
.pwm_freq_div = 0,
.agc_control = dib7090_agc_restart,
.spur_protect = 0,
.disable_sample_and_hold = 0,
.enable_current_mirror = 0,
.diversity_delay = 0,
.output_mode = OUTMODE_MPEG2_PAR_GATED_CLK,
.default_i2c_addr = 0x90,
.enMpegOutput = 1,
},{
.output_mpeg2_in_188_bytes = 1,
.hostbus_diversity = 1,
.tuner_is_baseband = 1,
.update_lna = NULL,
.agc_config_count = 2,
.agc = dib7090_agc_config,
.bw = &dib7090_clock_config_12_mhz,
.gpio_dir = DIB7000P_GPIO_DEFAULT_DIRECTIONS,
.gpio_val = DIB7000P_GPIO_DEFAULT_VALUES,
.gpio_pwm_pos = DIB7000P_GPIO_DEFAULT_PWM_POS,
.pwm_freq_div = 0,
.agc_control = dib7090_agc_restart,
.spur_protect = 0,
.disable_sample_and_hold = 0,
.enable_current_mirror = 0,
.diversity_delay = 0,
.output_mode = OUTMODE_MPEG2_PAR_GATED_CLK,
.default_i2c_addr = 0x92,
.enMpegOutput = 0,
}
};
static const struct dib0090_config nim7090_dib0090_config = {
.io.clock_khz = 12000,
.io.pll_bypass = 0,
.io.pll_range = 0,
.io.pll_prediv = 3,
.io.pll_loopdiv = 6,
.io.adc_clock_ratio = 0,
.io.pll_int_loop_filt = 0,
.reset = dib7090_tuner_sleep,
.sleep = dib7090_tuner_sleep,
.freq_offset_khz_uhf = 0,
.freq_offset_khz_vhf = 0,
.get_adc_power = dib7090_get_adc_power,
.clkouttobamse = 1,
.analog_output = 0,
.wbd_vhf_offset = 0,
.wbd_cband_offset = 0,
.use_pwm_agc = 1,
.clkoutdrive = 0,
.fref_clock_ratio = 0,
.wbd = dib7090_wbd_table,
.ls_cfg_pad_drv = 0,
.data_tx_drv = 0,
.low_if = NULL,
.in_soc = 1,
};
static const struct dib0090_config tfe7090pvr_dib0090_config[2] = {
{
.io.clock_khz = 12000,
.io.pll_bypass = 0,
.io.pll_range = 0,
.io.pll_prediv = 3,
.io.pll_loopdiv = 6,
.io.adc_clock_ratio = 0,
.io.pll_int_loop_filt = 0,
.reset = dib7090_tuner_sleep,
.sleep = dib7090_tuner_sleep,
.freq_offset_khz_uhf = 50,
.freq_offset_khz_vhf = 70,
.get_adc_power = dib7090_get_adc_power,
.clkouttobamse = 1,
.analog_output = 0,
.wbd_vhf_offset = 0,
.wbd_cband_offset = 0,
.use_pwm_agc = 1,
.clkoutdrive = 0,
.fref_clock_ratio = 0,
.wbd = dib7090_wbd_table,
.ls_cfg_pad_drv = 0,
.data_tx_drv = 0,
.low_if = NULL,
.in_soc = 1,
},{
.io.clock_khz = 12000,
.io.pll_bypass = 0,
.io.pll_range = 0,
.io.pll_prediv = 3,
.io.pll_loopdiv = 6,
.io.adc_clock_ratio = 0,
.io.pll_int_loop_filt = 0,
.reset = dib7090_tuner_sleep,
.sleep = dib7090_tuner_sleep,
.freq_offset_khz_uhf = -50,
.freq_offset_khz_vhf = -70,
.get_adc_power = dib7090_get_adc_power,
.clkouttobamse = 1,
.analog_output = 0,
.wbd_vhf_offset = 0,
.wbd_cband_offset = 0,
.use_pwm_agc = 1,
.clkoutdrive = 0,
.fref_clock_ratio = 0,
.wbd = dib7090_wbd_table,
.ls_cfg_pad_drv = 0,
.data_tx_drv = 0,
.low_if = NULL,
.in_soc = 1,
}
};
static int nim7090_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);
msleep(10);
dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 1);
msleep(10);
dib0700_set_gpio(adap->dev, GPIO0, GPIO_OUT, 1);
static int dib8096_set_param_override(struct dvb_frontend *fe, if (dib7000p_i2c_enumeration(&adap->dev->i2c_adap, 1, 0x10, &nim7090_dib7000p_config) != 0) {
struct dvb_frontend_parameters *fep) err("%s: dib7000p_i2c_enumeration failed. Cannot continue\n", __func__);
{ return -ENODEV;
struct dvb_usb_adapter *adap = fe->dvb->priv; }
struct dib0700_adapter_state *state = adap->priv; adap->fe = dvb_attach(dib7000p_attach, &adap->dev->i2c_adap, 0x80, &nim7090_dib7000p_config);
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; return adap->fe == NULL ? -ENODEV : 0;
} }
static int dib809x_tuner_attach(struct dvb_usb_adapter *adap) static int nim7090_tuner_attach(struct dvb_usb_adapter *adap)
{ {
struct dib0700_adapter_state *st = adap->priv; struct dib0700_adapter_state *st = adap->priv;
struct i2c_adapter *tun_i2c = dib8000_get_i2c_master(adap->fe, DIBX000_I2C_INTERFACE_TUNER, 1); struct i2c_adapter *tun_i2c = dib7090_get_i2c_tuner(adap->fe);
if (dvb_attach(dib0090_register, adap->fe, tun_i2c, &nim7090_dib0090_config) == NULL)
return -ENODEV;
if (dvb_attach(dib0090_register, adap->fe, tun_i2c, &dib809x_dib0090_config) == NULL) dib7000p_set_gpio(adap->fe, 8, 0, 1);
return -ENODEV;
st->set_param_save = adap->fe->ops.tuner_ops.set_params; st->set_param_save = adap->fe->ops.tuner_ops.set_params;
adap->fe->ops.tuner_ops.set_params = dib8096_set_param_override; adap->fe->ops.tuner_ops.set_params = dib7090_agc_startup;
return 0; return 0;
} }
static int stk809x_frontend_attach(struct dvb_usb_adapter *adap) static int tfe7090pvr_frontend0_attach(struct dvb_usb_adapter *adap)
{ {
struct dib0700_state *st = adap->dev->priv;
/* The TFE7090 requires the dib0700 to not be in master mode */
st->disable_streaming_master_mode = 1;
dib0700_set_gpio(adap->dev, GPIO6, GPIO_OUT, 1); dib0700_set_gpio(adap->dev, GPIO6, GPIO_OUT, 1);
msleep(10); msleep(10);
dib0700_set_gpio(adap->dev, GPIO9, GPIO_OUT, 1); dib0700_set_gpio(adap->dev, GPIO9, GPIO_OUT, 1);
dib0700_set_gpio(adap->dev, GPIO4, 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, GPIO7, GPIO_OUT, 1);
dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 0); dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 0);
dib0700_ctrl_clock(adap->dev, 72, 1);
msleep(10); msleep(10);
dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 1); dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 1);
msleep(10); msleep(10);
dib0700_set_gpio(adap->dev, GPIO0, GPIO_OUT, 1); dib0700_set_gpio(adap->dev, GPIO0, GPIO_OUT, 1);
dib8000_i2c_enumeration(&adap->dev->i2c_adap, 1, 18, 0x80); /* initialize IC 0 */
if (dib7000p_i2c_enumeration(&adap->dev->i2c_adap, 1, 0x20, &tfe7090pvr_dib7000p_config[0]) != 0) {
err("%s: dib7000p_i2c_enumeration failed. Cannot continue\n", __func__);
return -ENODEV;
}
adap->fe = dvb_attach(dib8000_attach, &adap->dev->i2c_adap, 0x80, &dib809x_dib8000_config); dib0700_set_i2c_speed(adap->dev, 340);
adap->fe = dvb_attach(dib7000p_attach, &adap->dev->i2c_adap, 0x90, &tfe7090pvr_dib7000p_config[0]);
return adap->fe == NULL ? -ENODEV : 0; dib7090_slave_reset(adap->fe);
if (adap->fe == NULL)
return -ENODEV;
return 0;
}
static int tfe7090pvr_frontend1_attach(struct dvb_usb_adapter *adap)
{
struct i2c_adapter *i2c;
if (adap->dev->adapter[0].fe == NULL) {
err("the master dib7090 has to be initialized first");
return -ENODEV; /* the master device has not been initialized */
}
i2c = dib7000p_get_i2c_master(adap->dev->adapter[0].fe, DIBX000_I2C_INTERFACE_GPIO_6_7, 1);
if (dib7000p_i2c_enumeration(i2c, 1, 0x10, &tfe7090pvr_dib7000p_config[1]) != 0) {
err("%s: dib7000p_i2c_enumeration failed. Cannot continue\n", __func__);
return -ENODEV;
}
adap->fe = dvb_attach(dib7000p_attach, i2c, 0x92, &tfe7090pvr_dib7000p_config[1]);
dib0700_set_i2c_speed(adap->dev, 200);
return adap->fe == NULL ? -ENODEV : 0;
}
static int tfe7090pvr_tuner0_attach(struct dvb_usb_adapter *adap)
{
struct dib0700_adapter_state *st = adap->priv;
struct i2c_adapter *tun_i2c = dib7090_get_i2c_tuner(adap->fe);
if (dvb_attach(dib0090_register, adap->fe, tun_i2c, &tfe7090pvr_dib0090_config[0]) == NULL)
return -ENODEV;
dib7000p_set_gpio(adap->fe, 8, 0, 1);
st->set_param_save = adap->fe->ops.tuner_ops.set_params;
adap->fe->ops.tuner_ops.set_params = dib7090_agc_startup;
return 0;
}
static int tfe7090pvr_tuner1_attach(struct dvb_usb_adapter *adap)
{
struct dib0700_adapter_state *st = adap->priv;
struct i2c_adapter *tun_i2c = dib7090_get_i2c_tuner(adap->fe);
if (dvb_attach(dib0090_register, adap->fe, tun_i2c, &tfe7090pvr_dib0090_config[1]) == NULL)
return -ENODEV;
dib7000p_set_gpio(adap->fe, 8, 0, 1);
st->set_param_save = adap->fe->ops.tuner_ops.set_params;
adap->fe->ops.tuner_ops.set_params = dib7090_agc_startup;
return 0;
} }
/* STK7070PD */ /* STK7070PD */
...@@ -1856,6 +2797,11 @@ struct usb_device_id dib0700_usb_id_table[] = { ...@@ -1856,6 +2797,11 @@ struct usb_device_id dib0700_usb_id_table[] = {
{ USB_DEVICE(USB_VID_PINNACLE, USB_PID_PINNACLE_PCTV282E) }, { USB_DEVICE(USB_VID_PINNACLE, USB_PID_PINNACLE_PCTV282E) },
{ USB_DEVICE(USB_VID_DIBCOM, USB_PID_DIBCOM_STK8096GP) }, { USB_DEVICE(USB_VID_DIBCOM, USB_PID_DIBCOM_STK8096GP) },
{ USB_DEVICE(USB_VID_ELGATO, USB_PID_ELGATO_EYETV_DIVERSITY) }, { USB_DEVICE(USB_VID_ELGATO, USB_PID_ELGATO_EYETV_DIVERSITY) },
{ USB_DEVICE(USB_VID_DIBCOM, USB_PID_DIBCOM_NIM9090M) },
/* 70 */{ USB_DEVICE(USB_VID_DIBCOM, USB_PID_DIBCOM_NIM8096MD) },
{ USB_DEVICE(USB_VID_DIBCOM, USB_PID_DIBCOM_NIM9090MD) },
{ USB_DEVICE(USB_VID_DIBCOM, USB_PID_DIBCOM_NIM7090) },
{ USB_DEVICE(USB_VID_DIBCOM, USB_PID_DIBCOM_TFE7090PVR) },
{ 0 } /* Terminating entry */ { 0 } /* Terminating entry */
}; };
MODULE_DEVICE_TABLE(usb, dib0700_usb_id_table); MODULE_DEVICE_TABLE(usb, dib0700_usb_id_table);
...@@ -2609,6 +3555,205 @@ struct dvb_usb_device_properties dib0700_devices[] = { ...@@ -2609,6 +3555,205 @@ struct dvb_usb_device_properties dib0700_devices[] = {
}, },
}, },
.rc.core = {
.rc_interval = DEFAULT_RC_INTERVAL,
.rc_codes = RC_MAP_DIB0700_RC5_TABLE,
.module_name = "dib0700",
.rc_query = dib0700_rc_query_old_firmware,
.allowed_protos = RC_TYPE_RC5 |
RC_TYPE_RC6 |
RC_TYPE_NEC,
.change_protocol = dib0700_change_protocol,
},
}, { 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 = dib90x0_pid_filter,
.pid_filter_ctrl = dib90x0_pid_filter_ctrl,
.frontend_attach = stk9090m_frontend_attach,
.tuner_attach = dib9090_tuner_attach,
DIB0700_DEFAULT_STREAMING_CONFIG(0x02),
.size_of_priv =
sizeof(struct dib0700_adapter_state),
},
},
.num_device_descs = 1,
.devices = {
{ "DiBcom STK9090M reference design",
{ &dib0700_usb_id_table[69], NULL },
{ NULL },
},
},
.rc.core = {
.rc_interval = DEFAULT_RC_INTERVAL,
.rc_codes = RC_MAP_DIB0700_RC5_TABLE,
.module_name = "dib0700",
.rc_query = dib0700_rc_query_old_firmware,
.allowed_protos = RC_TYPE_RC5 |
RC_TYPE_RC6 |
RC_TYPE_NEC,
.change_protocol = dib0700_change_protocol,
},
}, { 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 = nim8096md_frontend_attach,
.tuner_attach = nim8096md_tuner_attach,
DIB0700_DEFAULT_STREAMING_CONFIG(0x02),
.size_of_priv =
sizeof(struct dib0700_adapter_state),
},
},
.num_device_descs = 1,
.devices = {
{ "DiBcom NIM8096MD reference design",
{ &dib0700_usb_id_table[70], NULL },
{ NULL },
},
},
.rc.core = {
.rc_interval = DEFAULT_RC_INTERVAL,
.rc_codes = RC_MAP_DIB0700_RC5_TABLE,
.module_name = "dib0700",
.rc_query = dib0700_rc_query_old_firmware,
.allowed_protos = RC_TYPE_RC5 |
RC_TYPE_RC6 |
RC_TYPE_NEC,
.change_protocol = dib0700_change_protocol,
},
}, { 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 = dib90x0_pid_filter,
.pid_filter_ctrl = dib90x0_pid_filter_ctrl,
.frontend_attach = nim9090md_frontend_attach,
.tuner_attach = nim9090md_tuner_attach,
DIB0700_DEFAULT_STREAMING_CONFIG(0x02),
.size_of_priv =
sizeof(struct dib0700_adapter_state),
},
},
.num_device_descs = 1,
.devices = {
{ "DiBcom NIM9090MD reference design",
{ &dib0700_usb_id_table[71], NULL },
{ NULL },
},
},
.rc.core = {
.rc_interval = DEFAULT_RC_INTERVAL,
.rc_codes = RC_MAP_DIB0700_RC5_TABLE,
.module_name = "dib0700",
.rc_query = dib0700_rc_query_old_firmware,
.allowed_protos = RC_TYPE_RC5 |
RC_TYPE_RC6 |
RC_TYPE_NEC,
.change_protocol = dib0700_change_protocol,
},
}, { 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 = stk70x0p_pid_filter,
.pid_filter_ctrl = stk70x0p_pid_filter_ctrl,
.frontend_attach = nim7090_frontend_attach,
.tuner_attach = nim7090_tuner_attach,
DIB0700_DEFAULT_STREAMING_CONFIG(0x02),
.size_of_priv =
sizeof(struct dib0700_adapter_state),
},
},
.num_device_descs = 1,
.devices = {
{ "DiBcom NIM7090 reference design",
{ &dib0700_usb_id_table[72], NULL },
{ NULL },
},
},
.rc.core = {
.rc_interval = DEFAULT_RC_INTERVAL,
.rc_codes = RC_MAP_DIB0700_RC5_TABLE,
.module_name = "dib0700",
.rc_query = dib0700_rc_query_old_firmware,
.allowed_protos = RC_TYPE_RC5 |
RC_TYPE_RC6 |
RC_TYPE_NEC,
.change_protocol = dib0700_change_protocol,
},
}, { DIB0700_DEFAULT_DEVICE_PROPERTIES,
.num_adapters = 2,
.adapter = {
{
.caps = DVB_USB_ADAP_HAS_PID_FILTER |
DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
.pid_filter_count = 32,
.pid_filter = stk70x0p_pid_filter,
.pid_filter_ctrl = stk70x0p_pid_filter_ctrl,
.frontend_attach = tfe7090pvr_frontend0_attach,
.tuner_attach = tfe7090pvr_tuner0_attach,
DIB0700_DEFAULT_STREAMING_CONFIG(0x03),
.size_of_priv =
sizeof(struct dib0700_adapter_state),
},
{
.caps = DVB_USB_ADAP_HAS_PID_FILTER |
DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
.pid_filter_count = 32,
.pid_filter = stk70x0p_pid_filter,
.pid_filter_ctrl = stk70x0p_pid_filter_ctrl,
.frontend_attach = tfe7090pvr_frontend1_attach,
.tuner_attach = tfe7090pvr_tuner1_attach,
DIB0700_DEFAULT_STREAMING_CONFIG(0x02),
.size_of_priv =
sizeof(struct dib0700_adapter_state),
},
},
.num_device_descs = 1,
.devices = {
{ "DiBcom TFE7090PVR reference design",
{ &dib0700_usb_id_table[73], NULL },
{ NULL },
},
},
.rc.core = { .rc.core = {
.rc_interval = DEFAULT_RC_INTERVAL, .rc_interval = DEFAULT_RC_INTERVAL,
.rc_codes = RC_MAP_DIB0700_RC5_TABLE, .rc_codes = RC_MAP_DIB0700_RC5_TABLE,
......
...@@ -106,8 +106,13 @@ ...@@ -106,8 +106,13 @@
#define USB_PID_DIBCOM_STK807XP 0x1f90 #define USB_PID_DIBCOM_STK807XP 0x1f90
#define USB_PID_DIBCOM_STK807XPVR 0x1f98 #define USB_PID_DIBCOM_STK807XPVR 0x1f98
#define USB_PID_DIBCOM_STK8096GP 0x1fa0 #define USB_PID_DIBCOM_STK8096GP 0x1fa0
#define USB_PID_DIBCOM_NIM8096MD 0x1fa8
#define USB_PID_DIBCOM_ANCHOR_2135_COLD 0x2131 #define USB_PID_DIBCOM_ANCHOR_2135_COLD 0x2131
#define USB_PID_DIBCOM_STK7770P 0x1e80 #define USB_PID_DIBCOM_STK7770P 0x1e80
#define USB_PID_DIBCOM_NIM7090 0x1bb2
#define USB_PID_DIBCOM_TFE7090PVR 0x1bb4
#define USB_PID_DIBCOM_NIM9090M 0x2383
#define USB_PID_DIBCOM_NIM9090MD 0x2384
#define USB_PID_DPOSH_M9206_COLD 0x9206 #define USB_PID_DPOSH_M9206_COLD 0x9206
#define USB_PID_DPOSH_M9206_WARM 0xa090 #define USB_PID_DPOSH_M9206_WARM 0xa090
#define USB_PID_E3C_EC168 0x1689 #define USB_PID_E3C_EC168 0x1689
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment