summaryrefslogtreecommitdiff
path: root/linux
diff options
context:
space:
mode:
authorMauro Carvalho Chehab <mchehab@infradead.org>2006-04-13 18:47:57 -0300
committerMauro Carvalho Chehab <mchehab@infradead.org>2006-04-13 18:47:57 -0300
commit0627d777ef95f831fa94b95b89efd75acb127e1b (patch)
tree001f7390a4567b67b70bde89bad5c7510c9e6b2a /linux
parent7ad4e6ab6365e5667ed9e1714140dbb7c2ca5790 (diff)
parent46d6f90f18a1189b459e50eb8ad5e92170593fce (diff)
downloadmediapointer-dvb-s2-0627d777ef95f831fa94b95b89efd75acb127e1b.tar.gz
mediapointer-dvb-s2-0627d777ef95f831fa94b95b89efd75acb127e1b.tar.bz2
merge: http://linuxtv.org/hg/~mkrufky/v4l-dvb
From: Mauro Carvalho Chehab <mchehab@infradead.org> Signed-off-by: Mauro Carvalho Chehab <mchehab@infradead.org>
Diffstat (limited to 'linux')
-rw-r--r--linux/drivers/media/dvb/frontends/cx24123.c280
-rw-r--r--linux/drivers/media/dvb/ttpci/budget-av.c6
2 files changed, 183 insertions, 103 deletions
diff --git a/linux/drivers/media/dvb/frontends/cx24123.c b/linux/drivers/media/dvb/frontends/cx24123.c
index fa6cdba08..56280cd58 100644
--- a/linux/drivers/media/dvb/frontends/cx24123.c
+++ b/linux/drivers/media/dvb/frontends/cx24123.c
@@ -31,6 +31,7 @@
#define XTAL 10111000
+static int force_band;
static int debug;
#define dprintk(args...) \
do { \
@@ -76,23 +77,23 @@ static struct
.symbolrate_high = 4999999,
/* the specs recommend other values for VGA offsets,
but tests show they are wrong */
- .VGAprogdata = (2 << 18) | (0x180 << 9) | 0x1e0,
- .VCAprogdata = (4 << 18) | (0x07 << 9) | 0x07,
- .FILTune = 0x280 /* 0.41 V */
+ .VGAprogdata = (1 << 19) | (0x180 << 9) | 0x1e0,
+ .VCAprogdata = (2 << 19) | (0x07 << 9) | 0x07,
+ .FILTune = 0x27f /* 0.41 V */
},
{
.symbolrate_low = 5000000,
.symbolrate_high = 14999999,
- .VGAprogdata = (2 << 18) | (0x180 << 9) | 0x1e0,
- .VCAprogdata = (4 << 18) | (0x07 << 9) | 0x1f,
+ .VGAprogdata = (1 << 19) | (0x180 << 9) | 0x1e0,
+ .VCAprogdata = (2 << 19) | (0x07 << 9) | 0x1f,
.FILTune = 0x317 /* 0.90 V */
},
{
.symbolrate_low = 15000000,
.symbolrate_high = 45000000,
- .VGAprogdata = (2 << 18) | (0x100 << 9) | 0x180,
- .VCAprogdata = (4 << 18) | (0x07 << 9) | 0x3f,
- .FILTune = 0x146 /* 2.70 V */
+ .VGAprogdata = (1 << 19) | (0x100 << 9) | 0x180,
+ .VCAprogdata = (2 << 19) | (0x07 << 9) | 0x3f,
+ .FILTune = 0x145 /* 2.70 V */
},
};
@@ -109,66 +110,88 @@ static struct
u32 progdata;
} cx24123_bandselect_vals[] =
{
+ /* band 1 */
{
.freq_low = 950000,
- .freq_high = 1018999,
- .VCOdivider = 4,
- .progdata = (0 << 18) | (0 << 9) | 0x40,
- },
- {
- .freq_low = 1019000,
.freq_high = 1074999,
.VCOdivider = 4,
- .progdata = (0 << 18) | (0 << 9) | 0x80,
+ .progdata = (0 << 19) | (0 << 9) | 0x40,
},
+
+ /* band 2 */
{
.freq_low = 1075000,
- .freq_high = 1227999,
- .VCOdivider = 2,
- .progdata = (0 << 18) | (1 << 9) | 0x01,
+ .freq_high = 1177999,
+ .VCOdivider = 4,
+ .progdata = (0 << 19) | (0 << 9) | 0x80,
},
+
+ /* band 3 */
{
- .freq_low = 1228000,
- .freq_high = 1349999,
+ .freq_low = 1178000,
+ .freq_high = 1295999,
.VCOdivider = 2,
- .progdata = (0 << 18) | (1 << 9) | 0x02,
+ .progdata = (0 << 19) | (1 << 9) | 0x01,
},
+
+ /* band 4 */
{
- .freq_low = 1350000,
- .freq_high = 1481999,
+ .freq_low = 1296000,
+ .freq_high = 1431999,
.VCOdivider = 2,
- .progdata = (0 << 18) | (1 << 9) | 0x04,
+ .progdata = (0 << 19) | (1 << 9) | 0x02,
},
+
+ /* band 5 */
{
- .freq_low = 1482000,
- .freq_high = 1595999,
+ .freq_low = 1432000,
+ .freq_high = 1575999,
.VCOdivider = 2,
- .progdata = (0 << 18) | (1 << 9) | 0x08,
+ .progdata = (0 << 19) | (1 << 9) | 0x04,
},
+
+ /* band 6 */
{
- .freq_low = 1596000,
+ .freq_low = 1576000,
.freq_high = 1717999,
.VCOdivider = 2,
- .progdata = (0 << 18) | (1 << 9) | 0x10,
+ .progdata = (0 << 19) | (1 << 9) | 0x08,
},
+
+ /* band 7 */
{
.freq_low = 1718000,
.freq_high = 1855999,
.VCOdivider = 2,
- .progdata = (0 << 18) | (1 << 9) | 0x20,
+ .progdata = (0 << 19) | (1 << 9) | 0x10,
},
+
+ /* band 8 */
{
.freq_low = 1856000,
.freq_high = 2035999,
.VCOdivider = 2,
- .progdata = (0 << 18) | (1 << 9) | 0x40,
+ .progdata = (0 << 19) | (1 << 9) | 0x20,
},
+
+ /* band 9 */
{
.freq_low = 2036000,
- .freq_high = 2149999,
+ .freq_high = 2150000,
+ .VCOdivider = 2,
+ .progdata = (0 << 19) | (1 << 9) | 0x40,
+ },
+#if 0
+/* This band is not useful with the /2 divider, as its center frequency
+ is approximately 2300MHz, which is outside of the tunable range. It is
+ useful only with the /4 divider, as used in band #2. */
+ {
+ .freq_low = 2150000,
+ .freq_high = 2356000,
.VCOdivider = 2,
- .progdata = (0 << 18) | (1 << 9) | 0x80,
+ .progdata = (0 << 19) | (1 << 9) | 0x80,
},
+#endif
};
static struct {
@@ -178,45 +201,44 @@ static struct {
{
{0x00, 0x03}, /* Reset system */
{0x00, 0x00}, /* Clear reset */
- {0x03, 0x07},
- {0x04, 0x10},
- {0x05, 0x04},
- {0x06, 0x31},
- {0x0d, 0x02},
- {0x0e, 0x03},
- {0x0f, 0xfe},
- {0x10, 0x01},
- {0x14, 0x01},
- {0x16, 0x00},
- {0x17, 0x01},
- {0x1b, 0x05},
- {0x1c, 0x80},
- {0x1d, 0x00},
- {0x1e, 0x00},
- {0x20, 0x41},
- {0x21, 0x15},
- {0x29, 0x00},
- {0x2a, 0xb0},
- {0x2b, 0x73},
- {0x2c, 0x00},
+ {0x03, 0x07}, /* QPSK, DVB, Auto Acquisition (default) */
+ {0x04, 0x10}, /* MPEG */
+ {0x05, 0x04}, /* MPEG */
+ {0x06, 0x31}, /* MPEG (default) */
+ {0x0b, 0x00}, /* Freq search start point (default) */
+ {0x0c, 0x00}, /* Demodulator sample gain (default) */
+ {0x0d, 0x02}, /* Frequency search range = Fsymbol / 4 (default) */
+ {0x0e, 0x03}, /* Default non-inverted, FEC 3/4 (default) */
+ {0x0f, 0xfe}, /* FEC search mask (all supported codes) */
+ {0x10, 0x01}, /* Default search inversion, no repeat (default) */
+ {0x16, 0x00}, /* Enable reading of frequency */
+ {0x17, 0x01}, /* Enable EsNO Ready Counter */
+ {0x1c, 0x80}, /* Enable error counter */
+ {0x20, 0x00}, /* Tuner burst clock rate = 500KHz */
+ {0x21, 0x15}, /* Tuner burst mode, word length = 0x15 */
+ {0x28, 0x00}, /* Enable FILTERV with positive pol., DiSEqC 2.x off */
+ {0x29, 0x00}, /* DiSEqC LNB_DC off */
+ {0x2a, 0xb0}, /* DiSEqC Parameters (default) */
+ {0x2b, 0x73}, /* DiSEqC Tone Frequency (default) */
+ {0x2c, 0x00}, /* DiSEqC Message (0x2c - 0x31) */
{0x2d, 0x00},
{0x2e, 0x00},
{0x2f, 0x00},
{0x30, 0x00},
{0x31, 0x00},
- {0x32, 0x8c},
- {0x33, 0x00},
+ {0x32, 0x8c}, /* DiSEqC Parameters (default) */
+ {0x33, 0x00}, /* Interrupts off (0x33 - 0x34) */
{0x34, 0x00},
- {0x35, 0x03},
- {0x36, 0x02},
- {0x37, 0x3a},
- {0x3a, 0x00}, /* Enable AGC accumulator */
- {0x44, 0x00},
- {0x45, 0x00},
- {0x46, 0x05},
- {0x56, 0x41},
- {0x57, 0xff},
- {0x67, 0x83},
+ {0x35, 0x03}, /* DiSEqC Tone Amplitude (default) */
+ {0x36, 0x02}, /* DiSEqC Parameters (default) */
+ {0x37, 0x3a}, /* DiSEqC Parameters (default) */
+ {0x3a, 0x00}, /* Enable AGC accumulator (for signal strength) */
+ {0x44, 0x00}, /* Constellation (default) */
+ {0x45, 0x00}, /* Symbol count (default) */
+ {0x46, 0x0d}, /* Symbol rate estimator on (default) */
+ {0x56, 0x41}, /* Various (default) */
+ {0x57, 0xff}, /* Error Counter Window (default) */
+ {0x67, 0x83}, /* Non-DCII symbol clock */
};
static int cx24123_writereg(struct cx24123_state* state, int reg, int data)
@@ -291,20 +313,23 @@ static int cx24123_readlnbreg(struct cx24123_state* state, u8 reg)
static int cx24123_set_inversion(struct cx24123_state* state, fe_spectral_inversion_t inversion)
{
+ u8 nom_reg = cx24123_readreg(state, 0x0e);
+ u8 auto_reg = cx24123_readreg(state, 0x10);
+
switch (inversion) {
case INVERSION_OFF:
dprintk("%s: inversion off\n",__FUNCTION__);
- cx24123_writereg(state, 0x0e, cx24123_readreg(state, 0x0e) & 0x7f);
- cx24123_writereg(state, 0x10, cx24123_readreg(state, 0x10) | 0x80);
+ cx24123_writereg(state, 0x0e, nom_reg & ~0x80);
+ cx24123_writereg(state, 0x10, auto_reg | 0x80);
break;
case INVERSION_ON:
dprintk("%s: inversion on\n",__FUNCTION__);
- cx24123_writereg(state, 0x0e, cx24123_readreg(state, 0x0e) | 0x80);
- cx24123_writereg(state, 0x10, cx24123_readreg(state, 0x10) | 0x80);
+ cx24123_writereg(state, 0x0e, nom_reg | 0x80);
+ cx24123_writereg(state, 0x10, auto_reg | 0x80);
break;
case INVERSION_AUTO:
dprintk("%s: inversion auto\n",__FUNCTION__);
- cx24123_writereg(state, 0x10, cx24123_readreg(state, 0x10) & 0x7f);
+ cx24123_writereg(state, 0x10, auto_reg & ~0x80);
break;
default:
return -EINVAL;
@@ -332,35 +357,56 @@ static int cx24123_get_inversion(struct cx24123_state* state, fe_spectral_invers
static int cx24123_set_fec(struct cx24123_state* state, fe_code_rate_t fec)
{
+ u8 nom_reg = cx24123_readreg(state, 0x0e) & ~0x07;
+
if ( (fec < FEC_NONE) || (fec > FEC_AUTO) )
fec = FEC_AUTO;
- /* Hardware has 5/11 and 3/5 but are never unused */
switch (fec) {
- case FEC_NONE:
- dprintk("%s: set FEC to none\n",__FUNCTION__);
- return cx24123_writereg(state, 0x0f, 0x01);
case FEC_1_2:
dprintk("%s: set FEC to 1/2\n",__FUNCTION__);
- return cx24123_writereg(state, 0x0f, 0x02);
+ cx24123_writereg(state, 0x0e, nom_reg | 0x01);
+ cx24123_writereg(state, 0x0f, 0x02);
+ break;
case FEC_2_3:
dprintk("%s: set FEC to 2/3\n",__FUNCTION__);
- return cx24123_writereg(state, 0x0f, 0x04);
+ cx24123_writereg(state, 0x0e, nom_reg | 0x02);
+ cx24123_writereg(state, 0x0f, 0x04);
+ break;
case FEC_3_4:
dprintk("%s: set FEC to 3/4\n",__FUNCTION__);
- return cx24123_writereg(state, 0x0f, 0x08);
- case FEC_5_6:
+ cx24123_writereg(state, 0x0e, nom_reg | 0x03);
+ cx24123_writereg(state, 0x0f, 0x08);
+ break;
+ case FEC_4_5:
dprintk("%s: set FEC to 4/5\n",__FUNCTION__);
- return cx24123_writereg(state, 0x0f, 0x20);
- case FEC_7_8:
+ cx24123_writereg(state, 0x0e, nom_reg | 0x04);
+ cx24123_writereg(state, 0x0f, 0x10);
+ break;
+ case FEC_5_6:
dprintk("%s: set FEC to 5/6\n",__FUNCTION__);
- return cx24123_writereg(state, 0x0f, 0x80);
+ cx24123_writereg(state, 0x0e, nom_reg | 0x05);
+ cx24123_writereg(state, 0x0f, 0x20);
+ break;
+ case FEC_6_7:
+ dprintk("%s: set FEC to 6/7\n",__FUNCTION__);
+ cx24123_writereg(state, 0x0e, nom_reg | 0x06);
+ cx24123_writereg(state, 0x0f, 0x40);
+ break;
+ case FEC_7_8:
+ dprintk("%s: set FEC to 7/8\n",__FUNCTION__);
+ cx24123_writereg(state, 0x0e, nom_reg | 0x07);
+ cx24123_writereg(state, 0x0f, 0x80);
+ break;
case FEC_AUTO:
dprintk("%s: set FEC to auto\n",__FUNCTION__);
- return cx24123_writereg(state, 0x0f, 0xae);
+ cx24123_writereg(state, 0x0f, 0xfe);
+ break;
default:
return -EOPNOTSUPP;
}
+
+ return 0;
}
static int cx24123_get_fec(struct cx24123_state* state, fe_code_rate_t *fec)
@@ -395,16 +441,31 @@ static int cx24123_get_fec(struct cx24123_state* state, fe_code_rate_t *fec)
*fec = FEC_7_8;
break;
default:
- *fec = FEC_NONE; // can't happen
- printk("FEC_NONE ?\n");
+ /* this can happen when there's no lock */
+ *fec = FEC_NONE;
}
return 0;
}
+/* Approximation of closest integer of log2(a/b). It actually gives the
+ lowest integer i such that 2^i >= round(a/b) */
+static u32 cx24123_int_log2(u32 a, u32 b)
+{
+ u32 exp, nearest = 0;
+ u32 div = a / b;
+ if(a % b >= b / 2) ++div;
+ if(div < (1 << 31))
+ {
+ for(exp = 1; div > exp; nearest++)
+ exp += exp;
+ }
+ return nearest;
+}
+
static int cx24123_set_symbolrate(struct cx24123_state* state, u32 srate)
{
- u32 tmp, sample_rate, ratio;
+ u32 tmp, sample_rate, ratio, sample_gain;
u8 pll_mult;
/* check if symbol rate is within limits */
@@ -462,7 +523,12 @@ static int cx24123_set_symbolrate(struct cx24123_state* state, u32 srate)
cx24123_writereg(state, 0x09, (ratio >> 8) & 0xff );
cx24123_writereg(state, 0x0a, (ratio ) & 0xff );
- dprintk("%s: srate=%d, ratio=0x%08x, sample_rate=%i\n", __FUNCTION__, srate, ratio, sample_rate);
+ /* also set the demodulator sample gain */
+ sample_gain = cx24123_int_log2(sample_rate, srate);
+ tmp = cx24123_readreg(state, 0x0c) & ~0xe0;
+ cx24123_writereg(state, 0x0c, tmp | sample_gain << 5);
+
+ dprintk("%s: srate=%d, ratio=0x%08x, sample_rate=%i sample_gain=%d\n", __FUNCTION__, srate, ratio, sample_rate, sample_gain);
return 0;
}
@@ -477,6 +543,8 @@ static int cx24123_pll_calculate(struct dvb_frontend* fe, struct dvb_frontend_pa
u32 ndiv = 0, adiv = 0, vco_div = 0;
int i = 0;
int pump = 2;
+ int band = 0;
+ int num_bands = sizeof(cx24123_bandselect_vals) / sizeof(cx24123_bandselect_vals[0]);
/* Defaults for low freq, low rate */
state->VCAarg = cx24123_AGC_vals[0].VCAprogdata;
@@ -495,21 +563,27 @@ static int cx24123_pll_calculate(struct dvb_frontend* fe, struct dvb_frontend_pa
}
}
- /* For the given frequency, determine the bandselect programming bits */
- for (i = 0; i < sizeof(cx24123_bandselect_vals) / sizeof(cx24123_bandselect_vals[0]); i++)
+ /* determine the band to use */
+ if(force_band < 1 || force_band > num_bands)
{
- if ((cx24123_bandselect_vals[i].freq_low <= p->frequency) &&
- (cx24123_bandselect_vals[i].freq_high >= p->frequency) ) {
- state->bandselectarg = cx24123_bandselect_vals[i].progdata;
- vco_div = cx24123_bandselect_vals[i].VCOdivider;
-
- /* determine the charge pump current */
- if ( p->frequency < (cx24123_bandselect_vals[i].freq_low + cx24123_bandselect_vals[i].freq_high)/2 )
- pump = 0x01;
- else
- pump = 0x02;
+ for (i = 0; i < num_bands; i++)
+ {
+ if ((cx24123_bandselect_vals[i].freq_low <= p->frequency) &&
+ (cx24123_bandselect_vals[i].freq_high >= p->frequency) )
+ band = i;
}
}
+ else
+ band = force_band - 1;
+
+ state->bandselectarg = cx24123_bandselect_vals[band].progdata;
+ vco_div = cx24123_bandselect_vals[band].VCOdivider;
+
+ /* determine the charge pump current */
+ if ( p->frequency < (cx24123_bandselect_vals[band].freq_low + cx24123_bandselect_vals[band].freq_high)/2 )
+ pump = 0x01;
+ else
+ pump = 0x02;
/* Determine the N/A dividers for the requested lband freq (in kHz). */
/* Note: the reference divider R=10, frequency is in KHz, XTAL is in Hz */
@@ -1014,12 +1088,13 @@ static struct dvb_frontend_ops cx24123_ops = {
.frequency_min = 950000,
.frequency_max = 2150000,
.frequency_stepsize = 1011, /* kHz for QPSK frontends */
- .frequency_tolerance = 29500,
+ .frequency_tolerance = 5000,
.symbol_rate_min = 1000000,
.symbol_rate_max = 45000000,
.caps = FE_CAN_INVERSION_AUTO |
FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 |
- FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO |
+ FE_CAN_FEC_4_5 | FE_CAN_FEC_5_6 | FE_CAN_FEC_6_7 |
+ FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO |
FE_CAN_QPSK | FE_CAN_RECOVER
},
@@ -1042,6 +1117,9 @@ static struct dvb_frontend_ops cx24123_ops = {
module_param(debug, int, 0644);
MODULE_PARM_DESC(debug, "Activates frontend debugging (default:0)");
+module_param(force_band, int, 0644);
+MODULE_PARM_DESC(force_band, "Force a specific band select (1-9, default:off).");
+
MODULE_DESCRIPTION("DVB Frontend module for Conexant cx24123/cx24109 hardware");
MODULE_AUTHOR("Steven Toth");
MODULE_LICENSE("GPL");
diff --git a/linux/drivers/media/dvb/ttpci/budget-av.c b/linux/drivers/media/dvb/ttpci/budget-av.c
index 8a7cd7d50..dc78aadf0 100644
--- a/linux/drivers/media/dvb/ttpci/budget-av.c
+++ b/linux/drivers/media/dvb/ttpci/budget-av.c
@@ -1017,12 +1017,14 @@ static void frontend_init(struct budget_av *budget_av)
struct saa7146_dev * saa = budget_av->budget.dev;
struct dvb_frontend * fe = NULL;
+ /* Enable / PowerON Frontend */
+ saa7146_setgpio(saa, 0, SAA7146_GPIO_OUTLO);
+
+ /* additional setup necessary for the PLUS cards */
switch (saa->pci->subsystem_device) {
case SUBID_DVBS_KNC1_PLUS:
case SUBID_DVBC_KNC1_PLUS:
case SUBID_DVBT_KNC1_PLUS:
- // Enable / PowerON Frontend
- saa7146_setgpio(saa, 0, SAA7146_GPIO_OUTLO);
saa7146_setgpio(saa, 3, SAA7146_GPIO_OUTHI);
break;
}