diff --git a/drivers/media/dvb/frontends/stb0899_algo.c b/drivers/media/dvb/frontends/stb0899_algo.c
index d70eee0..1dbd9be 100644
--- a/drivers/media/dvb/frontends/stb0899_algo.c
+++ b/drivers/media/dvb/frontends/stb0899_algo.c
@@ -23,6 +23,13 @@
 #include "stb0899_priv.h"
 #include "stb0899_reg.h"
 
+#include <linux/kernel.h>
+#include <linux/module.h>
+
+static int derot_max = 8192;
+module_param(derot_max, int, 0644);
+MODULE_PARM_DESC(derot_max, "Set Maximum Derot Value (0..32767)");
+
 static inline u32 stb0899_do_div(u64 n, u32 d)
 {
 	/* wrap do_div() for ease of use */
@@ -117,7 +124,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 (100000 / (srate / 1000));
 	else
 		return 0;
@@ -207,30 +214,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 derot_freq = 0;
 	int index = 0;
 	u8 cfr[2];
 
 	internal->status = NOTIMING;
+	internal->direction = 1;
 
-	/* timing loop computation & symbol rate optimisation	*/
-	derot_limit = (internal->sub_range / 2L) / internal->mclk;
-	derot_step = (params->srate / 2L) / internal->mclk;
+	while ((stb0899_check_tmg(state) != TIMINGOK) && (abs(derot_freq) <= derot_max)) {
+		derot_freq += index * (index - 1) * internal->direction;	/* next derot zig zag position	*/
 
-	while ((stb0899_check_tmg(state) != TIMINGOK) && next_loop) {
-		index++;
-		derot_freq += index * internal->direction * derot_step;	/* next derot zig zag position	*/
+		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		*/
 
-		if (abs(derot_freq) > derot_limit)
-			next_loop--;
-
-		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		*/
-		}
 		internal->direction = -internal->direction;	/* Change zigzag direction		*/
+		index++;
 	}
 
 	if (internal->status == TIMINGOK) {
@@ -277,50 +276,41 @@ 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 derot_freq;
 	int index = 0;
 	u8 cfr[2];
 	u8 reg;
 
 	internal->status = NOCARRIER;
-	derot_limit = (internal->sub_range / 2L) / internal->mclk;
+	internal->direction = 1;
 	derot_freq = internal->derot_freq;
 
 	reg = stb0899_read_reg(state, STB0899_CFD);
 	STB0899_SETFIELD_VAL(CFD_ON, reg, 1);
 	stb0899_write_reg(state, STB0899_CFD, reg);
 
-	do {
+	while ((stb0899_check_carrier(state) == NOCARRIER) && (abs(derot_freq) <= derot_max)) {
+
+		derot_freq += index * (index - 1) * internal->direction;	/* next derot zig zag position	*/
+
 		dprintk(state->verbose, FE_DEBUG, 1, "Derot Freq=%d, mclk=%d", derot_freq, internal->mclk);
-		if (stb0899_check_carrier(state) == NOCARRIER) {
-			index++;
-			last_derot_freq = derot_freq;
-			derot_freq += index * internal->direction * internal->derot_step; /* next zig zag derotator 
position */
-
-			if(abs(derot_freq) > derot_limit)
-				next_loop--;
-
-			if (next_loop) {
-				reg = stb0899_read_reg(state, STB0899_CFD);
-				STB0899_SETFIELD_VAL(CFD_ON, reg, 1);
-				stb0899_write_reg(state, STB0899_CFD, reg);
-
-				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	*/
-			}
-		}
+
+		reg = stb0899_read_reg(state, STB0899_CFD);
+		STB0899_SETFIELD_VAL(CFD_ON, reg, 1);
+		stb0899_write_reg(state, STB0899_CFD, reg);
+
+		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	*/
 
 		internal->direction = -internal->direction; /* Change zigzag direction */
-	} while ((internal->status != CARRIEROK) && next_loop);
+		index++;
+	}
 
 	if (internal->status == CARRIEROK) {
 		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, "----> CARRIER OK !, Derot Freq=%d", internal->derot_freq);
-	} else {
-		internal->derot_freq = last_derot_freq;
 	}
 
