summaryrefslogtreecommitdiff
path: root/linux/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'linux/drivers')
-rw-r--r--linux/drivers/media/dvb/frontends/s5h1420.c67
-rw-r--r--linux/drivers/media/dvb/ttpci/budget.c3
2 files changed, 60 insertions, 10 deletions
diff --git a/linux/drivers/media/dvb/frontends/s5h1420.c b/linux/drivers/media/dvb/frontends/s5h1420.c
index 6a8ede614..c8f5dbfa4 100644
--- a/linux/drivers/media/dvb/frontends/s5h1420.c
+++ b/linux/drivers/media/dvb/frontends/s5h1420.c
@@ -31,6 +31,9 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
#include "s5h1420.h"
+
+#define TONE_FREQ 22000
+
struct s5h1420_state {
struct i2c_adapter* i2c;
struct dvb_frontend_ops ops;
@@ -40,9 +43,12 @@ struct s5h1420_state {
u8 postlocked:1;
u32 fclk;
u32 tunedfreq;
+ fe_code_rate_t fec_inner;
+ u32 symbol_rate;
};
static u32 s5h1420_getsymbolrate(struct s5h1420_state* state);
+static int s5h1420_get_tune_settings(struct dvb_frontend* fe, struct dvb_frontend_tune_settings* fesettings);
static int debug = 0;
@@ -431,7 +437,9 @@ static void s5h1420_setfreqoffset(struct s5h1420_state* state, int freqoffset)
{
int val;
- val = -(int) (((freqoffset / 1000) * (1<<24)) / (state->fclk / 1000000));
+ /* remember freqoffset is in kHz, but the chip wants the offset in Hz, so
+ * divide fclk by 1000000 to get the correct value. */
+ val = -(int) ((freqoffset * (1<<24)) / (state->fclk / 1000000));
s5h1420_writereg(state, 0x09, s5h1420_readreg(state, 0x09) & 0xbf);
s5h1420_writereg(state, 0x0e, val >> 16);
@@ -453,7 +461,9 @@ static int s5h1420_getfreqoffset(struct s5h1420_state* state)
if (val & 0x800000)
val |= 0xff000000;
- val = - ((val * (state->fclk/1000)) / (1<<24));
+ /* remember freqoffset is in kHz, but the chip wants the offset in Hz, so
+ * divide fclk by 1000000 to get the correct value. */
+ val = - ((val * (state->fclk/1000000)) / (1<<24));
return val;
}
@@ -553,8 +563,21 @@ static fe_spectral_inversion_t s5h1420_getinversion(struct s5h1420_state* state)
static int s5h1420_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_parameters *p)
{
struct s5h1420_state* state = fe->demodulator_priv;
-
- // FIXME: fast tune
+ u32 frequency_delta;
+ struct dvb_frontend_tune_settings fesettings;
+
+ /* check if we should do a fast-tune */
+ memcpy(&fesettings.parameters, p, sizeof(struct dvb_frontend_parameters));
+ s5h1420_get_tune_settings(fe, &fesettings);
+ frequency_delta = p->frequency - state->tunedfreq;
+ if ((frequency_delta > -fesettings.max_drift) && (frequency_delta < fesettings.max_drift) &&
+ (frequency_delta != 0) &&
+ (state->fec_inner == p->u.qpsk.fec_inner) &&
+ (state->symbol_rate == p->u.qpsk.symbol_rate)) {
+
+ s5h1420_setfreqoffset(state, frequency_delta);
+ return 0;
+ }
/* first of all, software reset */
s5h1420_reset(state);
@@ -595,7 +618,7 @@ static int s5h1420_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_par
s5h1420_writereg(state, 0x35, 0x33);
s5h1420_writereg(state, 0x38, 0x01);
s5h1420_writereg(state, 0x39, 0x7d);
- s5h1420_writereg(state, 0x3a, (state->fclk + (22000*32) - 1) / (22000*32));
+ s5h1420_writereg(state, 0x3a, (state->fclk + (TONE_FREQ * 32) - 1) / (TONE_FREQ * 32));
s5h1420_writereg(state, 0x3c, 0x00);
s5h1420_writereg(state, 0x45, 0x61);
s5h1420_writereg(state, 0x46, 0x1d);
@@ -603,8 +626,8 @@ static int s5h1420_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_par
/* start QPSK */
s5h1420_writereg(state, 0x05, s5h1420_readreg(state, 0x05) | 1);
- /* set the frequency offset to 0 initially */
- s5h1420_setfreqoffset(state, 0);
+ /* set the frequency offset to adjust for PLL inaccuracy */
+ s5h1420_setfreqoffset(state, p->frequency - state->tunedfreq);
/* set the symbolrate */
s5h1420_setsymbolrate(state, p);
@@ -615,6 +638,8 @@ static int s5h1420_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_par
/* set the FEC */
s5h1420_setfec(state, p);
+ state->fec_inner = p->u.qpsk.fec_inner;
+ state->symbol_rate = p->u.qpsk.symbol_rate;
state->postlocked = 0;
return 0;
}
@@ -633,7 +658,31 @@ static int s5h1420_get_frontend(struct dvb_frontend* fe, struct dvb_frontend_par
static int s5h1420_get_tune_settings(struct dvb_frontend* fe, struct dvb_frontend_tune_settings* fesettings)
{
- // FIXME
+ if (fesettings->parameters.u.qpsk.symbol_rate > 20000000) {
+ fesettings->min_delay_ms = 50;
+ fesettings->step_size = 2000;
+ fesettings->max_drift = 8000;
+ } else if (fesettings->parameters.u.qpsk.symbol_rate > 12000000) {
+ fesettings->min_delay_ms = 100;
+ fesettings->step_size = 1500;
+ fesettings->max_drift = 9000;
+ } else if (fesettings->parameters.u.qpsk.symbol_rate > 8000000) {
+ fesettings->min_delay_ms = 100;
+ fesettings->step_size = 1000;
+ fesettings->max_drift = 8000;
+ } else if (fesettings->parameters.u.qpsk.symbol_rate > 4000000) {
+ fesettings->min_delay_ms = 100;
+ fesettings->step_size = 500;
+ fesettings->max_drift = 7000;
+ } else if (fesettings->parameters.u.qpsk.symbol_rate > 2000000) {
+ fesettings->min_delay_ms = 200;
+ fesettings->step_size = (fesettings->parameters.u.qpsk.symbol_rate / 8000);
+ fesettings->max_drift = 14 * fesettings->step_size;
+ } else {
+ fesettings->min_delay_ms = 200;
+ fesettings->step_size = (fesettings->parameters.u.qpsk.symbol_rate / 8000);
+ fesettings->max_drift = 18 * fesettings->step_size;
+ }
return 0;
}
@@ -689,6 +738,8 @@ struct dvb_frontend* s5h1420_attach(const struct s5h1420_config* config, struct
state->postlocked = 0;
state->fclk = 88000000;
state->tunedfreq = 0;
+ state->fec_inner = FEC_NONE;
+ state->symbol_rate = 0;
/* check if the demod is there + identify it */
identity = s5h1420_readreg(state, 0x00);
diff --git a/linux/drivers/media/dvb/ttpci/budget.c b/linux/drivers/media/dvb/ttpci/budget.c
index 550140a00..9961917e8 100644
--- a/linux/drivers/media/dvb/ttpci/budget.c
+++ b/linux/drivers/media/dvb/ttpci/budget.c
@@ -548,7 +548,7 @@ static void frontend_init(struct budget *budget)
break;
}
break;
-/*
+
case 0x1016: // Hauppauge/TT Nova-S SE (samsung s5h1420/????(tda8260))
budget->dvb_frontend = s5h1420_attach(&s5h1420_config, &budget->i2c_adap);
if (budget->dvb_frontend) {
@@ -557,7 +557,6 @@ static void frontend_init(struct budget *budget)
lnbp21_init(budget);
break;
}
-*/
}
if (budget->dvb_frontend == NULL) {