(This patch needs testing and review.)
>From 5449f996bb340e4423b3146d1e0172dd635c0398 Mon Sep 17 00:00:00 2001
From: Hans Petter Selasky
Date: Tue, 24 May 2011 21:44:53 +0200
Subject: [PATCH] Fix the derot zig-zag to work with TT-USB2.0 TechnoTrend.
Signed-off-by: Hans Petter Selasky
---
drivers/media/dvb/frontends/stb0899_algo.c | 173
drivers/media/dvb/frontends/stb0899_drv.c |1 -
drivers/media/dvb/frontends/stb0899_priv.h |3 -
3 files changed, 75 insertions(+), 102 deletions(-)
diff --git a/drivers/media/dvb/frontends/stb0899_algo.c
b/drivers/media/dvb/frontends/stb0899_algo.c
index d70eee0..9156c3b 100644
--- a/drivers/media/dvb/frontends/stb0899_algo.c
+++ b/drivers/media/dvb/frontends/stb0899_algo.c
@@ -117,7 +117,7 @@ static u32 stb0899_set_srate(struct stb0899_state *state,
u32 master_clk, u32 sr
*/
static long stb0899_calc_derot_time(long srate)
{
- if (srate > 0)
+ if (srate > 999)
return (10 / (srate / 1000));
else
return 0;
@@ -200,6 +200,39 @@ static enum stb0899_status stb0899_check_tmg(struct
stb0899_state *state)
}
/*
+ * stb0899_set_derot
+ * set frequency derotor in HZ.
+ */
+static void
+stb0899_set_derot(struct stb0899_state *state, s16 derot)
+{
+ u8 cfr[2];
+
+ derot *= state->config->inversion;
+
+ cfr[0] = (u8)(derot >> 8);
+ cfr[1] = (u8)derot;
+
+ /* set derotator frequency in Hz */
+ stb0899_write_regs(state, STB0899_CFRM, cfr, 2);
+}
+
+/*
+ * stb0899_get_derot
+ * get frequency derotor in HZ.
+ */
+static s16
+stb0899_get_derot(struct stb0899_state *state)
+{
+ u8 cfr[2] = {0, 0};
+
+ /* get derotator frequency in Hz */
+ stb0899_read_regs(state, STB0899_CFRM, cfr, 2);
+
+ return (state->config->inversion * (s16)MAKEWORD16(cfr[0], cfr[1]));
+}
+
+/*
* stb0899_search_tmg
* perform a fs/2 zig-zag to find timing
*/
@@ -207,36 +240,22 @@ static enum stb0899_status stb0899_search_tmg(struct
stb0899_state *state)
{
struct stb0899_internal *internal = &state->internal;
struct stb0899_params *params = &state->params;
-
- short int derot_step, derot_freq = 0, derot_limit, next_loop = 3;
- int index = 0;
- u8 cfr[2];
+ int index;
internal->status = NOTIMING;
- /* timing loop computation & symbol rate optimisation */
- derot_limit = (internal->sub_range / 2L) / internal->mclk;
- derot_step = (params->srate / 2L) / internal->mclk;
+ /* let the hardware figure out derot frequency */
+ stb0899_set_derot(state, 0);
- while ((stb0899_check_tmg(state) != TIMINGOK) && next_loop) {
- index++;
- derot_freq += index * internal->direction * derot_step; /* next
derot zig zag position */
-
- if (abs(derot_freq) > derot_limit)
- next_loop--;
+ for (index = 0; index < 8; index++) {
+ if (stb0899_check_tmg(state) == TIMINGOK) {
+ /* get derotator frequency */
+ internal->derot_freq = stb0899_get_derot(state);
- if (next_loop) {
- STB0899_SETFIELD_VAL(CFRM, cfr[0],
MSB(state->config->inversion * derot_freq));
- STB0899_SETFIELD_VAL(CFRL, cfr[1],
LSB(state->config->inversion * derot_freq));
- stb0899_write_regs(state, STB0899_CFRM, cfr, 2); /*
derotator frequency */
+ dprintk(state->verbose, FE_DEBUG, 1, "--->TIMING OK
! "
+ "Derot Freq = %d @ %d", internal->derot_freq,
index);
+ break;
}
- internal->direction = -internal->direction; /* Change
zigzag direction */
- }
-
- if (internal->status == TIMINGOK) {
- stb0899_read_regs(state, STB0899_CFRM, cfr, 2); /* get
derotator frequency */
- internal->derot_freq = state->config->inversion *
MAKEWORD16(cfr[0], cfr[1]);
- dprintk(state->verbose, FE_DEBUG, 1, "--->TIMING OK ! Derot
Freq = %d", internal->derot_freq);
}
return internal->status;
@@ -277,50 +296,26 @@ static enum stb0899_status stb0899_check_carrier(struct
stb0899_state *state)
static enum stb0899_status stb0899_search_carrier(struct stb0899_state *state)
{
struct stb0899_internal *internal = &state->internal;
-
- short int derot_freq = 0, last_derot_freq = 0, derot_limit, next_loop =
3;
- int index = 0;
- u8 cfr[2];
+ int index;
u8 reg;
internal->status = NOCARRIER;
- derot_limit = (internal->sub_range / 2L) / internal->mclk;
- derot_freq = internal->derot_freq;
+
+ /* let the hardware figure out derot frequency */
+ stb0899_set_derot(state, 0);
reg = stb0899_read_reg(state, STB0899_CFD);
STB0899_SETFIELD_V