diff options
author | Igor M. Liplianin <liplianin@me.by> | 2009-12-15 02:24:56 +0300 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2010-02-26 21:10:24 +0300 |
commit | cd79d33e168dba0d7de32c5bf010e20cff184b2a (patch) | |
tree | a9e40f6281e62f27fc7d36e885416b5fef696c46 /drivers/media/dvb/frontends | |
parent | d41592a2a2b9a27425ade3fc2c8526e9e997acd6 (diff) | |
download | linux-cd79d33e168dba0d7de32c5bf010e20cff184b2a.tar.xz |
V4L/DVB (13818): Add Prof 7500 DVB-S2 USB card
The card based on stv0903 demod, stb6100 tuner.
Signed-off-by: Igor M. Liplianin <liplianin@me.by>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media/dvb/frontends')
-rw-r--r-- | drivers/media/dvb/frontends/stv0900.h | 2 | ||||
-rw-r--r-- | drivers/media/dvb/frontends/stv0900_core.c | 87 | ||||
-rw-r--r-- | drivers/media/dvb/frontends/stv0900_priv.h | 11 | ||||
-rw-r--r-- | drivers/media/dvb/frontends/stv0900_reg.h | 6 | ||||
-rw-r--r-- | drivers/media/dvb/frontends/stv0900_sw.c | 44 |
5 files changed, 142 insertions, 8 deletions
diff --git a/drivers/media/dvb/frontends/stv0900.h b/drivers/media/dvb/frontends/stv0900.h index 29c3fa85c227..e3e35d1ce838 100644 --- a/drivers/media/dvb/frontends/stv0900.h +++ b/drivers/media/dvb/frontends/stv0900.h @@ -49,6 +49,8 @@ struct stv0900_config { u8 tun2_maddress; u8 tun1_adc;/* 1 for stv6110, 2 for stb6100 */ u8 tun2_adc; + u8 tun1_type;/* for now 3 for stb6100 auto, else - software */ + u8 tun2_type; /* Set device param to start dma */ int (*set_ts_params)(struct dvb_frontend *fe, int is_punctured); }; diff --git a/drivers/media/dvb/frontends/stv0900_core.c b/drivers/media/dvb/frontends/stv0900_core.c index 8762c86044a5..115dc01c2234 100644 --- a/drivers/media/dvb/frontends/stv0900_core.c +++ b/drivers/media/dvb/frontends/stv0900_core.c @@ -567,6 +567,46 @@ void stv0900_set_bandwidth(struct dvb_frontend *fe, u32 bandwidth) } } +u32 stv0900_get_freq_auto(struct stv0900_internal *intp, int demod) +{ + u32 freq, round; + /* Formulat : + Tuner_Frequency(MHz) = Regs / 64 + Tuner_granularity(MHz) = Regs / 2048 + real_Tuner_Frequency = Tuner_Frequency(MHz) - Tuner_granularity(MHz) + */ + freq = (stv0900_get_bits(intp, TUN_RFFREQ2) << 10) + + (stv0900_get_bits(intp, TUN_RFFREQ1) << 2) + + stv0900_get_bits(intp, TUN_RFFREQ0); + + freq = (freq * 1000) / 64; + + round = (stv0900_get_bits(intp, TUN_RFRESTE1) >> 2) + + stv0900_get_bits(intp, TUN_RFRESTE0); + + round = (round * 1000) / 2048; + + return freq + round; +} + +void stv0900_set_tuner_auto(struct stv0900_internal *intp, u32 Frequency, + u32 Bandwidth, int demod) +{ + u32 tunerFrequency; + /* Formulat: + Tuner_frequency_reg= Frequency(MHz)*64 + */ + tunerFrequency = (Frequency * 64) / 1000; + + stv0900_write_bits(intp, TUN_RFFREQ2, (tunerFrequency >> 10)); + stv0900_write_bits(intp, TUN_RFFREQ1, (tunerFrequency >> 2) & 0xff); + stv0900_write_bits(intp, TUN_RFFREQ0, (tunerFrequency & 0x03)); + /* Low Pass Filter = BW /2 (MHz)*/ + stv0900_write_bits(intp, TUN_BW, Bandwidth / 2000000); + /* Tuner Write trig */ + stv0900_write_reg(intp, TNRLD, 1); +} + static s32 stv0900_get_rf_level(struct stv0900_internal *intp, const struct stv0900_table *lookup, enum fe_stv0900_demod_num demod) @@ -1329,7 +1369,6 @@ static enum fe_stv0900_error stv0900_init_internal(struct dvb_frontend *fe, enum fe_stv0900_error error = STV0900_NO_ERROR; enum fe_stv0900_error demodError = STV0900_NO_ERROR; struct stv0900_internal *intp = NULL; - int selosci, i; struct stv0900_inode *temp_int = find_inode(state->i2c_adap, @@ -1404,6 +1443,27 @@ static enum fe_stv0900_error stv0900_init_internal(struct dvb_frontend *fe, stv0900_write_bits(intp, F0900_P1_RST_HWARE, 0); } + intp->tuner_type[0] = p_init->tuner1_type; + intp->tuner_type[1] = p_init->tuner2_type; + /* tuner init */ + switch (p_init->tuner1_type) { + case 3: /*FE_AUTO_STB6100:*/ + stv0900_write_reg(intp, R0900_P1_TNRCFG, 0x3c); + stv0900_write_reg(intp, R0900_P1_TNRCFG2, 0x86); + stv0900_write_reg(intp, R0900_P1_TNRCFG3, 0x18); + stv0900_write_reg(intp, R0900_P1_TNRXTAL, 27); /* 27MHz */ + stv0900_write_reg(intp, R0900_P1_TNRSTEPS, 0x05); + stv0900_write_reg(intp, R0900_P1_TNRGAIN, 0x17); + stv0900_write_reg(intp, R0900_P1_TNRADJ, 0x1f); + stv0900_write_reg(intp, R0900_P1_TNRCTL2, 0x0); + stv0900_write_bits(intp, F0900_P1_TUN_TYPE, 3); + break; + /* case FE_SW_TUNER: */ + default: + stv0900_write_bits(intp, F0900_P1_TUN_TYPE, 6); + break; + } + stv0900_write_bits(intp, F0900_P1_TUN_MADDRESS, p_init->tun1_maddress); switch (p_init->tuner1_adc) { case 1: @@ -1413,6 +1473,27 @@ static enum fe_stv0900_error stv0900_init_internal(struct dvb_frontend *fe, break; } + stv0900_write_reg(intp, R0900_P1_TNRLD, 1); /* hw tuner */ + + /* tuner init */ + switch (p_init->tuner2_type) { + case 3: /*FE_AUTO_STB6100:*/ + stv0900_write_reg(intp, R0900_P2_TNRCFG, 0x3c); + stv0900_write_reg(intp, R0900_P2_TNRCFG2, 0x86); + stv0900_write_reg(intp, R0900_P2_TNRCFG3, 0x18); + stv0900_write_reg(intp, R0900_P2_TNRXTAL, 27); /* 27MHz */ + stv0900_write_reg(intp, R0900_P2_TNRSTEPS, 0x05); + stv0900_write_reg(intp, R0900_P2_TNRGAIN, 0x17); + stv0900_write_reg(intp, R0900_P2_TNRADJ, 0x1f); + stv0900_write_reg(intp, R0900_P2_TNRCTL2, 0x0); + stv0900_write_bits(intp, F0900_P2_TUN_TYPE, 3); + break; + /* case FE_SW_TUNER: */ + default: + stv0900_write_bits(intp, F0900_P2_TUN_TYPE, 6); + break; + } + stv0900_write_bits(intp, F0900_P2_TUN_MADDRESS, p_init->tun2_maddress); switch (p_init->tuner2_adc) { case 1: @@ -1422,6 +1503,8 @@ static enum fe_stv0900_error stv0900_init_internal(struct dvb_frontend *fe, break; } + stv0900_write_reg(intp, R0900_P2_TNRLD, 1); /* hw tuner */ + stv0900_write_bits(intp, F0900_P1_TUN_IQSWAP, p_init->tun1_iq_inv); stv0900_write_bits(intp, F0900_P2_TUN_IQSWAP, p_init->tun2_iq_inv); stv0900_set_mclk(intp, 135000000); @@ -1824,10 +1907,12 @@ struct dvb_frontend *stv0900_attach(const struct stv0900_config *config, init_params.tun1_maddress = config->tun1_maddress; init_params.tun1_iq_inv = STV0900_IQ_NORMAL; init_params.tuner1_adc = config->tun1_adc; + init_params.tuner1_type = config->tun1_type; init_params.path2_ts_clock = config->path2_mode; init_params.ts_config = config->ts_config_regs; init_params.tun2_maddress = config->tun2_maddress; init_params.tuner2_adc = config->tun2_adc; + init_params.tuner2_type = config->tun2_type; init_params.tun2_iq_inv = STV0900_IQ_SWAPPED; err_stv0900 = stv0900_init_internal(&state->frontend, diff --git a/drivers/media/dvb/frontends/stv0900_priv.h b/drivers/media/dvb/frontends/stv0900_priv.h index d8ba8a984abe..b62b0f0a4fef 100644 --- a/drivers/media/dvb/frontends/stv0900_priv.h +++ b/drivers/media/dvb/frontends/stv0900_priv.h @@ -247,6 +247,7 @@ struct stv0900_init_params{ u8 tun1_maddress; int tuner1_adc; + int tuner1_type; /* IQ from the tuner1 to the demod */ enum stv0900_iq_inversion tun1_iq_inv; @@ -254,6 +255,7 @@ struct stv0900_init_params{ u8 tun2_maddress; int tuner2_adc; + int tuner2_type; /* IQ from the tuner2 to the demod */ enum stv0900_iq_inversion tun2_iq_inv; @@ -309,6 +311,8 @@ struct stv0900_internal{ s32 bw[2]; s32 symbol_rate[2]; s32 srch_range[2]; + /* for software/auto tuner */ + int tuner_type[2]; /* algorithm for search Blind, Cold or Warm*/ enum fe_stv0900_search_algo srch_algo[2]; @@ -394,4 +398,11 @@ extern enum fe_stv0900_tracking_standard stv0900_get_standard(struct dvb_frontend *fe, enum fe_stv0900_demod_num demod); +extern u32 +stv0900_get_freq_auto(struct stv0900_internal *intp, int demod); + +extern void +stv0900_set_tuner_auto(struct stv0900_internal *intp, u32 Frequency, + u32 Bandwidth, int demod); + #endif diff --git a/drivers/media/dvb/frontends/stv0900_reg.h b/drivers/media/dvb/frontends/stv0900_reg.h index 7b8edf192e97..731afe93a823 100644 --- a/drivers/media/dvb/frontends/stv0900_reg.h +++ b/drivers/media/dvb/frontends/stv0900_reg.h @@ -3174,17 +3174,21 @@ extern s32 shiftx(s32 x, int demod, s32 shift); #define R0900_P1_TNRRF1 0xf4e9 #define TNRRF1 REGx(R0900_P1_TNRRF1) #define F0900_P1_TUN_RFFREQ2 0xf4e900ff +#define TUN_RFFREQ2 FLDx(F0900_P1_TUN_RFFREQ2) /*P1_TNRRF0*/ #define R0900_P1_TNRRF0 0xf4ea #define TNRRF0 REGx(R0900_P1_TNRRF0) #define F0900_P1_TUN_RFFREQ1 0xf4ea00ff +#define TUN_RFFREQ1 FLDx(F0900_P1_TUN_RFFREQ1) /*P1_TNRBW*/ #define R0900_P1_TNRBW 0xf4eb #define TNRBW REGx(R0900_P1_TNRBW) #define F0900_P1_TUN_RFFREQ0 0xf4eb00c0 +#define TUN_RFFREQ0 FLDx(F0900_P1_TUN_RFFREQ0) #define F0900_P1_TUN_BW 0xf4eb003f +#define TUN_BW FLDx(F0900_P1_TUN_BW) /*P1_TNRADJ*/ #define R0900_P1_TNRADJ 0xf4ec @@ -3234,11 +3238,13 @@ extern s32 shiftx(s32 x, int demod, s32 shift); #define F0900_P1_TUN_I2CLOCKED 0xf4f60010 #define F0900_P1_TUN_PROGDONE 0xf4f6000c #define F0900_P1_TUN_RFRESTE1 0xf4f60003 +#define TUN_RFRESTE1 FLDx(F0900_P1_TUN_RFRESTE1) /*P1_TNRRESTE*/ #define R0900_P1_TNRRESTE 0xf4f7 #define TNRRESTE REGx(R0900_P1_TNRRESTE) #define F0900_P1_TUN_RFRESTE0 0xf4f700ff +#define TUN_RFRESTE0 FLDx(F0900_P1_TUN_RFRESTE0) /*P1_SMAPCOEF7*/ #define R0900_P1_SMAPCOEF7 0xf500 diff --git a/drivers/media/dvb/frontends/stv0900_sw.c b/drivers/media/dvb/frontends/stv0900_sw.c index b8da87fa637f..5161c2884426 100644 --- a/drivers/media/dvb/frontends/stv0900_sw.c +++ b/drivers/media/dvb/frontends/stv0900_sw.c @@ -606,7 +606,12 @@ static int stv0900_get_demod_cold_lock(struct dvb_frontend *fe, tuner_freq -= (current_step * currier_step); if (intp->chip_id <= 0x20) { - stv0900_set_tuner(fe, tuner_freq, intp->bw[d]); + if (intp->tuner_type[d] == 3) + stv0900_set_tuner_auto(intp, tuner_freq, + intp->bw[d], demod); + else + stv0900_set_tuner(fe, tuner_freq, intp->bw[d]); + stv0900_write_reg(intp, DMDISTATE, 0x1c); stv0900_write_reg(intp, CFRINIT1, 0); stv0900_write_reg(intp, CFRINIT0, 0); @@ -976,8 +981,16 @@ static void stv0900_track_optimization(struct dvb_frontend *fe) intp->rolloff) + 10000000; if ((intp->chip_id >= 0x20) || (blind_tun_sw == 1)) { - if (intp->srch_algo[demod] != STV0900_WARM_START) - stv0900_set_bandwidth(fe, intp->bw[demod]); + if (intp->srch_algo[demod] != STV0900_WARM_START) { + if (intp->tuner_type[demod] == 3) + stv0900_set_tuner_auto(intp, + intp->freq[demod], + intp->bw[demod], + demod); + else + stv0900_set_bandwidth(fe, + intp->bw[demod]); + } } if ((intp->srch_algo[demod] == STV0900_BLIND_SEARCH) || @@ -1202,7 +1215,11 @@ fe_stv0900_signal_type stv0900_get_signal_params(struct dvb_frontend *fe) } result->standard = stv0900_get_standard(fe, d); - result->frequency = stv0900_get_tuner_freq(fe); + if (intp->tuner_type[demod] == 3) + result->frequency = stv0900_get_freq_auto(intp, d); + else + result->frequency = stv0900_get_tuner_freq(fe); + offsetFreq = stv0900_get_carr_freq(intp, intp->mclk, d) / 1000; result->frequency += offsetFreq; result->symbol_rate = stv0900_get_symbol_rate(intp, intp->mclk, d); @@ -1239,7 +1256,11 @@ fe_stv0900_signal_type stv0900_get_signal_params(struct dvb_frontend *fe) if ((intp->srch_algo[d] == STV0900_BLIND_SEARCH) || (intp->symbol_rate[d] < 10000000)) { offsetFreq = result->frequency - intp->freq[d]; - intp->freq[d] = stv0900_get_tuner_freq(fe); + if (intp->tuner_type[demod] == 3) + intp->freq[d] = stv0900_get_freq_auto(intp, d); + else + intp->freq[d] = stv0900_get_tuner_freq(fe); + if (ABS(offsetFreq) <= ((intp->srch_range[d] / 2000) + 500)) range = STV0900_RANGEOK; else if (ABS(offsetFreq) <= @@ -1481,7 +1502,12 @@ static u32 stv0900_search_srate_coarse(struct dvb_frontend *fe) else tuner_freq -= (current_step * currier_step); - stv0900_set_tuner(fe, tuner_freq, intp->bw[demod]); + if (intp->tuner_type[demod] == 3) + stv0900_set_tuner_auto(intp, tuner_freq, + intp->bw[demod], demod); + else + stv0900_set_tuner(fe, tuner_freq, + intp->bw[demod]); } } @@ -1875,7 +1901,11 @@ enum fe_stv0900_signal_type stv0900_algo(struct dvb_frontend *fe) } - stv0900_set_tuner(fe, intp->freq[demod], intp->bw[demod]); + if (intp->tuner_type[demod] == 3) + stv0900_set_tuner_auto(intp, intp->freq[demod], + intp->bw[demod], demod); + else + stv0900_set_tuner(fe, intp->freq[demod], intp->bw[demod]); agc1_power = MAKEWORD(stv0900_get_bits(intp, AGCIQ_VALUE1), stv0900_get_bits(intp, AGCIQ_VALUE0)); |