Was fürs CVS?

Sklaventreiber
T-Tron
Interessierter
Interessierter
Beiträge: 67
Registriert: Mittwoch 2. November 2005, 07:45

Was fürs CVS?

Beitrag von T-Tron »

Vielleicht schaut mal ein Treiberprofi drüber.

Code: Alles auswählen

Index: dvb/drivers/media/dvb/avia/avia_av_core.c
===================================================================
RCS file: /cvs/tuxbox/driver/dvb/drivers/media/dvb/avia/avia_av_core.c,v
retrieving revision 1.99
diff -r1.99 avia_av_core.c
1227a1228
> 
1231a1233,1236
> 
> 		if ((aviarev) && (play_state_audio != AVIA_AV_PLAY_STATE_PAUSED)) // oder nur  if (aviarev)
> 			avia_av_cmd(Play, 0x00, (play_state_video == AVIA_AV_PLAY_STATE_PLAYING) ? pid_video : 0xFFFF, pid_audio);
> 
1241a1247
> 
1242a1249,1254
> 
> 			if (aviarev) {
> 				avia_av_cmd(SelectStream, 0x03 - bypass_mode, 0xFFFF); // ???
> 				avia_av_cmd(Abort, 0x00);
> 			}
> 
1244c1256,1258
< 			avia_av_cmd(NewChannel, 0x00, 0xFFFF, 0xFFFF);
---
> 
> 			if (!aviarev)
> 				avia_av_cmd(NewChannel, 0x00, 0xFFFF, 0xFFFF);
1278a1293,1295
> 
> //			if (aviarev)
> //				avia_av_cmd(Play, 0x00, pid_video, (play_state_audio == AVIA_AV_PLAY_STATE_PLAYING) ? pid_audio : 0xFFFF);
1289a1307,1312
> 
> 			if (aviarev) {
> 				avia_av_cmd(SelectStream, 0x00, 0xFFFF); // ???
> 				avia_av_cmd(Abort, 0x00);
> 			}
> 
1291c1314,1316
< 			avia_av_cmd(NewChannel, 0x00, 0xFFFF, 0xFFFF);
---
> 
> 			if (!aviarev)
> 				avia_av_cmd(NewChannel, 0x00, 0xFFFF, 0xFFFF);
1560a1586
> 
Index: dvb/drivers/media/dvb/avia/avia_gt_ucode.c
===================================================================
RCS file: /cvs/tuxbox/driver/dvb/drivers/media/dvb/avia/avia_gt_ucode.c,v
retrieving revision 1.14
diff -r1.14 avia_gt_ucode.c
941,943c941,942
<  			AVIA_GT_UCODE_CAP_TS |
< 			AVIA_GT_UCODE_CAP_MSGQ);
< 		ucode_info.prop_interface_flags=CAN_WAITPUSI;
---
>  			AVIA_GT_UCODE_CAP_TS);
> 		ucode_info.prop_interface_flags=0;
Index: dvb/drivers/media/dvb/dvb-core/dvb_compat.h
===================================================================
RCS file: /cvs/tuxbox/driver/dvb/drivers/media/dvb/dvb-core/dvb_compat.h,v
retrieving revision 1.5
diff -r1.5 dvb_compat.h
10a11,57
> #ifndef wait_event_interruptible_timeout
> #define __wait_event_interruptible_timeout(wq, condition, ret)          \
> do {                                                                    \
>         wait_queue_t __wait;                                            \
>         init_waitqueue_entry(&__wait, current);                         \
>                                                                         \
>         add_wait_queue(&wq, &__wait);                                   \
>         for (;;) {                                                      \
>                 set_current_state(TASK_INTERRUPTIBLE);                  \
>                 if (condition)                                          \
>                         break;                                          \
>                 if (!signal_pending(current)) {                         \
>                         ret = schedule_timeout(ret);                    \
>                         if (!ret)                                       \
>                                 break;                                  \
>                         continue;                                       \
>                 }                                                       \
>                 ret = -ERESTARTSYS;                                     \
>                 break;                                                  \
>         }                                                               \
>         current->state = TASK_RUNNING;                                  \
>         remove_wait_queue(&wq, &__wait);                                \
> } while (0)
> 
> #define wait_event_interruptible_timeout(wq, condition, timeout)        \
> ({                                                                      \
>         long __ret = timeout;                                           \
>         if (!(condition))                                               \
>                 __wait_event_interruptible_timeout(wq, condition, __ret); \
>         __ret;                                                          \
> })
> #endif
> 
> #ifndef VIDEO_AUDIO_BALANCE
> #define VIDEO_AUDIO_BALANCE	32
> #endif
> 
> #ifndef list_for_each_entry
> #define list_for_each_entry(pos, head, member)				\
> 	for (pos = list_entry((head)->next, typeof(*pos), member),	\
> 		     prefetch(pos->member.next);			\
> 	     &pos->member != (head); 					\
> 	     pos = list_entry(pos->member.next, typeof(*pos), member),	\
> 		     prefetch(pos->member.next))
> #endif
> 
> #ifndef iminor
11a59
> #endif
12a61
> #ifndef irqreturn_t
15a65,71
> #endif
> 
> 
> #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,4,22))
> u32 crc32_le(u32 crc, unsigned char const *p, size_t len);
> #endif
> 
16a73
> 
Index: dvb/drivers/media/dvb/dvb-core/dvb_frontend.c
===================================================================
RCS file: /cvs/tuxbox/driver/dvb/drivers/media/dvb/dvb-core/dvb_frontend.c,v
retrieving revision 1.23
diff -r1.23 dvb_frontend.c
2c2,3
<  * dvb-core.c: DVB core driver
---
>  * dvb_frontend.c: DVB frontend tuning interface/thread
>  *
5,7c6,10
<  *                         Marcus Metzler
<  *                         Holger Waechtler 
<  *                                    for convergence integrated media GmbH
---
>  *			   Marcus Metzler
>  *			   Holger Waechtler 
>  *				      for convergence integrated media GmbH
>  * 
>  * Copyright (C) 2004 Andrew de Quincey (tuning thread cleanup)
16c19
<  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
---
>  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the
39a43,69
> #define FESTATE_IDLE 1
> #define FESTATE_RETUNE 2
> #define FESTATE_TUNING_FAST 4
> #define FESTATE_TUNING_SLOW 8
> #define FESTATE_TUNED 16
> #define FESTATE_ZIGZAG_FAST 32
> #define FESTATE_ZIGZAG_SLOW 64
> #define FESTATE_DISEQC 128
> #define FESTATE_WAITFORLOCK (FESTATE_TUNING_FAST | FESTATE_TUNING_SLOW | FESTATE_ZIGZAG_FAST | FESTATE_ZIGZAG_SLOW | FESTATE_DISEQC)
> #define FESTATE_SEARCHING_FAST (FESTATE_TUNING_FAST | FESTATE_ZIGZAG_FAST)
> #define FESTATE_SEARCHING_SLOW (FESTATE_TUNING_SLOW | FESTATE_ZIGZAG_SLOW)
> #define FESTATE_LOSTLOCK (FESTATE_ZIGZAG_FAST | FESTATE_ZIGZAG_SLOW)
> /*
>  * FESTATE_IDLE. No tuning parameters have been supplied and the loop is idling.
>  * FESTATE_RETUNE. Parameters have been supplied, but we have not yet performed the first tune.
>  * FESTATE_TUNING_FAST. Tuning parameters have been supplied and fast zigzag scan is in progress.
>  * FESTATE_TUNING_SLOW. Tuning parameters have been supplied. Fast zigzag failed, so we're trying again, but slower.
>  * FESTATE_TUNED. The frontend has successfully locked on.
>  * FESTATE_ZIGZAG_FAST. The lock has been lost, and a fast zigzag has been initiated to try and regain it.
>  * FESTATE_ZIGZAG_SLOW. The lock has been lost. Fast zigzag has been failed, so we're trying again, but slower.
>  * FESTATE_DISEQC. A DISEQC command has just been issued.
>  * FESTATE_WAITFORLOCK. When we're waiting for a lock.
>  * FESTATE_SEARCHING_FAST. When we're searching for a signal using a fast zigzag scan.
>  * FESTATE_SEARCHING_SLOW. When we're searching for a signal using a slow zigzag scan.
>  * FESTATE_LOSTLOCK. When the lock has been lost, and we're searching it again.
>  */
> 
42a73,77
> static int dvb_override_frequency_bending = 0;
> static int dvb_force_auto_inversion = 0;
> static int dvb_override_tune_delay = 0;
> 
> static int do_frequency_bending = 0;
50,54c85,89
< 	int                       eventw;
< 	int                       eventr;
< 	int                       overflow;
< 	wait_queue_head_t         wait_queue;
< 	struct semaphore          sem;
---
> 	int			  eventw;
> 	int			  eventr;
> 	int			  overflow;
> 	wait_queue_head_t	  wait_queue;
> 	struct semaphore	  sem;
69c104
< 	unsigned long lost_sync_jiffies;
---
> 	int state;
72,73c107,113
< 	int timeout_count;
< 	int lost_sync_count;
---
> 	int inversion;
> 	int auto_step;
> 	int auto_sub_step;
> 	int started_auto_step;
> 	int min_delay;
> 	int max_drift;
> 	int step_size;
75c115,116
<         fe_status_t status;
---
> 	int wakeup;
> 	fe_status_t status;
172,173c213,214
< 		if (this_fe != fe && fe->lost_sync_count != -1 &&
<                     frequency > f - stepsize && frequency < f + stepsize)
---
> 		if (this_fe != fe && (fe->state != FESTATE_IDLE) &&
> 		    frequency > f - stepsize && frequency < f + stepsize)
195,197d235
< 	if ((fe->status & FE_HAS_LOCK) && !(s & FE_HAS_LOCK))
< 		fe->lost_sync_jiffies = jiffies;
< 
255c293
<         struct dvb_fe_events *events = &fe->events;
---
> 	struct dvb_fe_events *events = &fe->events;
260,262c298,300
<                 events->overflow = 0;
<                 return -EOVERFLOW;
<         }
---
> 		events->overflow = 0;
> 		return -EOVERFLOW;
> 	}
264c302
<         if (events->eventw == events->eventr) {
---
> 	if (events->eventw == events->eventr) {
267,268c305,306
<                 if (flags & O_NONBLOCK)
<                         return -EWOULDBLOCK;
---
> 		if (flags & O_NONBLOCK)
> 			return -EWOULDBLOCK;
272,273c310,311
<                 ret = wait_event_interruptible (events->wait_queue,
<                                                 events->eventw != events->eventr);
---
> 		ret = wait_event_interruptible (events->wait_queue,
> 						events->eventw != events->eventr);
275c313
<         	if (down_interruptible (&fe->sem))
---
> 		if (down_interruptible (&fe->sem))
278,280c316,318
<                 if (ret < 0)
<                         return ret;
<         }
---
> 		if (ret < 0)
> 			return ret;
> 	}
282c320
<         if (down_interruptible (&events->sem))
---
> 	if (down_interruptible (&events->sem))
285c323
<        	memcpy (event, &events->events[events->eventr],
---
> 	memcpy (event, &events->events[events->eventr],
288,294c326
<         events->eventr = (events->eventr + 1) % MAX_EVENT;
< 
<        	up (&events->sem);
< 
<         return 0;
< }
< 
---
> 	events->eventr = (events->eventr + 1) % MAX_EVENT;
296,323c328
< static int dvb_frontend_set_parameters (struct dvb_frontend_data *fe,
< 				 struct dvb_frontend_parameters *param,
< 				 int first_trial)
< {
< 	struct dvb_frontend *frontend = &fe->frontend;
< 	int err;
< 
< 	if (first_trial) {
< 		fe->timeout_count = 0;
< 		fe->lost_sync_count = 0;
< 		fe->lost_sync_jiffies = jiffies;
< 		fe->lnb_drift = 0;
< 		if (fe->status & ~FE_TIMEDOUT)
< 			dvb_frontend_add_event (fe, 0);
< 		memcpy (&fe->parameters, param,
< 			sizeof (struct dvb_frontend_parameters));
< 	}
< 
< 	dvb_bend_frequency (fe, 0);
< 
< 	dprintk ("%s: f == %i, drift == %i\n",
< 		 __FUNCTION__, (int) param->frequency, (int) fe->lnb_drift);
< 
< 	param->frequency += fe->lnb_drift + fe->bending;
< 	err = dvb_frontend_internal_ioctl (frontend, FE_SET_FRONTEND, param);
< 	param->frequency -= fe->lnb_drift + fe->bending;
< 
< 	wake_up_interruptible (&fe->wait_queue);
---
> 	up (&events->sem);
325c330
< 	return err;
---
> 	return 0;
339,340c344
< 
< static void update_delay (int *quality, int *delay, int locked)
---
> static void update_delay (int *quality, int *delay, int min_delay, int locked)
342,354c346,358
< 	int q2;
< 
< 	dprintk ("%s\n", __FUNCTION__);
< 
< 	if (locked)
< 		(*quality) = (*quality * 220 + 36*256) / 256;
< 	else
< 		(*quality) = (*quality * 220 + 0) / 256;
< 
< 	q2 = *quality - 128;
< 	q2 *= q2;
< 
< 	*delay = HZ/20 + q2 * HZ / (128*128);
---
> 	    int q2;
>     
> 	    dprintk ("%s\n", __FUNCTION__);
>     
> 	    if (locked)
> 		      (*quality) = (*quality * 220 + 36*256) / 256;
> 	    else
> 		      (*quality) = (*quality * 220 + 0) / 256;
>     
> 	    q2 = *quality - 128;
> 	    q2 *= q2;
>     
> 	    *delay = min_delay + q2 * HZ / (128*128);
357,360d360
< 
< #define LNB_DRIFT 1024  /*  max. tolerated LNB drift, XXX FIXME: adjust! */
< #define TIMEOUT 2*HZ
< 
362,363c362,366
<  *  here we only come when we have lost the lock bit, 
<  *  let's try to do something useful...
---
>  * Performs automatic twiddling of frontend parameters.
>  * 
>  * @param fe The frontend concerned.
>  * @param check_wrapped Checks if an iteration has completed. DO NOT SET ON THE FIRST ATTEMPT
>  * @returns Number of complete iterations that have been performed.
365c368
< static void dvb_frontend_recover (struct dvb_frontend_data *fe)
---
> static int dvb_frontend_autotune(struct dvb_frontend_data *fe, int check_wrapped)
367,381c370,388
< 	dprintk ("%s\n", __FUNCTION__);
< 
< #if 0
< 	if (fe->timeout_count > 3) {
< 		printk ("%s: frontend seems dead, reinitializing...\n",
< 			__FUNCTION__);
< 		dvb_call_frontend_notifiers (fe, 0);
< 		dvb_frontend_internal_ioctl (&fe->frontend, FE_INIT, NULL);
< 		dvb_frontend_set_parameters (fe, &fe->parameters, 1);
< 		dvb_frontend_add_event (fe, FE_REINIT);
< 		fe->lost_sync_jiffies = jiffies;
< 		fe->timeout_count = 0;
< 		return;
< 	}
< #endif
---
> 	int autoinversion;
> 	int ready = 0;
> 	int original_inversion = fe->parameters.inversion;
> 	u32 original_frequency = fe->parameters.frequency;
> 
> 	// are we using autoinversion?
> 	autoinversion = ((!(fe->info->caps & FE_CAN_INVERSION_AUTO)) && (fe->parameters.inversion == INVERSION_AUTO));
> 
> 	// setup parameters correctly
> 	while(!ready) {
> 		// calculate the lnb_drift
> 		fe->lnb_drift = fe->auto_step * fe->step_size;
> 
> 		// wrap the auto_step if we've exceeded the maximum drift
> 		if (fe->lnb_drift > fe->max_drift) {
> 			fe->auto_step = 0;
> 			fe->auto_sub_step = 0;
> 			fe->lnb_drift = 0;
> 		}
383,395c390,398
< 	/**
< 	 *  let's start a zigzag scan to compensate LNB drift...
< 	 */
< 	{
< 		int j = fe->lost_sync_count;
< 		int stepsize;
< 		
< 		if (fe->info->type == FE_QPSK)
< 			stepsize = fe->parameters.u.qpsk.symbol_rate / 16000;
< 		else if (fe->info->type == FE_QAM)
< 			stepsize = 0;
< 		else
< 			stepsize = fe->info->frequency_stepsize * 2;
---
> 		// perform inversion and +/- zigzag
> 		switch(fe->auto_sub_step) {
> 		case 0:
> 			// try with the current inversion and current drift setting
> 			ready = 1;
> 			break;
> 	    
> 		case 1:
> 			if (!autoinversion) break;
397,399c400,415
< 		if (j % 32 == 0) {
< 			fe->lnb_drift = 0;
< 		} else {
---
> 			fe->inversion = (fe->inversion == INVERSION_OFF) ? INVERSION_ON : INVERSION_OFF;
> 			ready = 1;
> 			break;
> 	    
> 		case 2:
> 			if (fe->lnb_drift == 0) break;
> 		    
> 			fe->lnb_drift = -fe->lnb_drift;
> 			ready = 1;
> 			break;
> 	    
> 		case 3:
> 			if (fe->lnb_drift == 0) break;
> 			if (!autoinversion) break;
> 		    
> 			fe->inversion = (fe->inversion == INVERSION_OFF) ? INVERSION_ON : INVERSION_OFF;
401,402c417,423
< 			if (j % 2)
< 				fe->lnb_drift += stepsize;
---
> 			ready = 1;
> 			break;
> 		    
> 		default:
> 			fe->auto_step++;
> 			fe->auto_sub_step = -1; // it'll be incremented to 0 in a moment
> 			break;
403a425,427
> 	    
> 		if (!ready) fe->auto_sub_step++;
> 	}
405c429,431
< 		dvb_frontend_set_parameters (fe, &fe->parameters, 0);
---
> 	// if this attempt would hit where we started, indicate a complete iteration has occurred
> 	if ((fe->auto_step == fe->started_auto_step) && (fe->auto_sub_step == 0) && check_wrapped) {
> 		return 1;
408c434,452
< 	dvb_frontend_internal_ioctl (&fe->frontend, FE_RESET, NULL);
---
> 	// perform frequency bending if necessary
> 	if ((dvb_override_frequency_bending != 1) && do_frequency_bending)
> 		dvb_bend_frequency(fe, 0);
> 
> 	// instrumentation
> 	dprintk("%s: drift:%i bending:%i inversion:%i auto_step:%i auto_sub_step:%i started_auto_step:%i\n", 
> 		__FUNCTION__, fe->lnb_drift, fe->bending, fe->inversion, fe->auto_step, fe->auto_sub_step,
> 		fe->started_auto_step);
>     
> 	// set the frontend itself
> 	fe->parameters.frequency += fe->lnb_drift + fe->bending;
> 	if (autoinversion) fe->parameters.inversion = fe->inversion;
> 	dvb_frontend_internal_ioctl (&fe->frontend, FE_SET_FRONTEND, &fe->parameters);
> 	fe->parameters.frequency = original_frequency;
> 	fe->parameters.inversion = original_inversion;
> 
> 	// normal return
> 	fe->auto_sub_step++;
> 	return 0;
424a469,481
> static int dvb_frontend_should_wakeup (struct dvb_frontend_data *fe)
> {
> 	if (fe->wakeup) {
> 		fe->wakeup = 0;
> 		return 1;
> 	}
> 	return dvb_frontend_is_exiting(fe);
> }
> 
> static void dvb_frontend_wakeup (struct dvb_frontend_data *fe) {
> 	fe->wakeup = 1;
> 	wake_up_interruptible(&fe->wait_queue);
> }
428a486
> 	unsigned long timeout;
431a490
> 	int check_wrapped = 0;
440,441d498
< 	fe->lost_sync_count = -1;
< 
443a501
> 	fe->wakeup = 0;
445,446c503,504
< 	while (!dvb_frontend_is_exiting (fe)) {
< 		up (&fe->sem);      /* is locked when we enter the thread... */
---
> 	while (1) {
> 		up (&fe->sem);	    /* is locked when we enter the thread... */
448,449c506,508
< 		interruptible_sleep_on_timeout (&fe->wait_queue, delay);
< 		if (signal_pending(current))
---
> 		timeout = wait_event_interruptible_timeout(fe->wait_queue,0 != dvb_frontend_should_wakeup (fe), delay);
> 		if (-ERESTARTSYS == timeout || 0 != dvb_frontend_is_exiting (fe)) {
> 			/* got signal or quitting */
450a510
> 		}
455c515,518
< 		if (fe->lost_sync_count == -1)
---
> 		// if we've got no parameters, just keep idling
> 		if (fe->state & FESTATE_IDLE) {
> 			delay = 3*HZ;
> 			quality = 0;
456a520,541
> 		}
> 	    
> 		// get the frontend status
> 		if (fe->state & FESTATE_RETUNE) {
> 			s = 0;
> 		} else {
> 			dvb_frontend_internal_ioctl (&fe->frontend, FE_READ_STATUS, &s);
> 			if (s != fe->status) {
> 				dvb_frontend_add_event (fe, s);
> 			}
> 		}
> 		// if we're not tuned, and we have a lock, move to the TUNED state
> 		if ((fe->state & FESTATE_WAITFORLOCK) && (s & FE_HAS_LOCK)) {
> 			update_delay(&quality, &delay, fe->min_delay, s & FE_HAS_LOCK);
> 			fe->state = FESTATE_TUNED;
> 
> 			// if we're tuned, then we have determined the correct inversion
> 			if ((!(fe->info->caps & FE_CAN_INVERSION_AUTO)) && (fe->parameters.inversion == INVERSION_AUTO)) {
> 				fe->parameters.inversion = fe->inversion;
> 			}
> 			continue;
> 		}
458,461c543,557
< 		if (dvb_frontend_is_exiting (fe))
< 			break;
< 
< 		dvb_frontend_internal_ioctl (&fe->frontend, FE_READ_STATUS, &s);
---
> 		// if we are tuned already, check we're still locked
> 		if (fe->state & FESTATE_TUNED) {
> 			update_delay(&quality, &delay, fe->min_delay, s & FE_HAS_LOCK);
> 		    
> 			// we're tuned, and the lock is still good...
> 			if (s & FE_HAS_LOCK) {
> 				continue;
> 			} else {
> 				// if we _WERE_ tuned, but now don't have a lock, need to zigzag
> 				fe->state = FESTATE_ZIGZAG_FAST;
> 				fe->started_auto_step = fe->auto_step;
> 				check_wrapped = 0;
> 				// fallthrough
> 			}
> 		}
463c559,573
< 		update_delay (&quality, &delay, s & FE_HAS_LOCK);
---
> 		// don't actually do anything if we're in the LOSTLOCK state, the frontend is set to
> 		// FE_CAN_RECOVER, and the max_drift is 0
> 		if ((fe->state & FESTATE_LOSTLOCK) && 
> 		    (fe->info->caps & FE_CAN_RECOVER) && (fe->max_drift == 0)) {
> 			update_delay(&quality, &delay, fe->min_delay, s & FE_HAS_LOCK);
> 			continue;
> 		}
> 	    
> 		// don't do anything if we're in the DISEQC state, since this might be someone
> 		// with a motorized dish controlled by DISEQC. If its actually a re-tune, there will
> 		// be a SET_FRONTEND soon enough.
> 		if (fe->state & FESTATE_DISEQC) {
> 			update_delay(&quality, &delay, fe->min_delay, s & FE_HAS_LOCK);
> 			continue;
> 		}
465c575,584
< 		s &= ~FE_TIMEDOUT;
---
> 		// if we're in the RETUNE state, set everything up for a brand new scan,
> 		// keeping the current inversion setting, as the next tune is _very_ likely
> 		// to require the same
> 		if (fe->state & FESTATE_RETUNE) {
> 			fe->lnb_drift = 0;
> 			fe->auto_step = 0;
> 			fe->auto_sub_step = 0;
> 			fe->started_auto_step = 0;
> 			check_wrapped = 0;
> 		}
467,478c586,596
< 		if (s & FE_HAS_LOCK) {
< 			fe->timeout_count = 0;
< 			fe->lost_sync_count = 0;
< 		} else {
< 			fe->lost_sync_count++;
< 			if (!(fe->info->caps & FE_CAN_RECOVER)) {
< 				if (!(fe->info->caps & FE_CAN_CLEAN_SETUP)) {
< 					if (fe->lost_sync_count < 10)
< 						continue;
< 				}
< 				dvb_frontend_recover (fe);
< 				delay = HZ/5;
---
> 		// fast zigzag.
> 		if ((fe->state & FESTATE_SEARCHING_FAST) || (fe->state & FESTATE_RETUNE)) {
> 			delay = fe->min_delay;
> 
> 			// peform a tune
> 			if (dvb_frontend_autotune(fe, check_wrapped)) {
> 				// OK, if we've run out of trials at the fast speed. Drop back to
> 				// slow for the _next_ attempt
> 				fe->state = FESTATE_SEARCHING_SLOW;
> 				fe->started_auto_step = fe->auto_step;
> 				continue;
480,483c598,605
< 			if (jiffies - fe->lost_sync_jiffies > TIMEOUT) {
< 				s |= FE_TIMEDOUT;
< 				if ((fe->status & FE_TIMEDOUT) == 0)
< 					fe->timeout_count++;
---
> 			check_wrapped = 1;
> 
> 			// if we've just retuned, enter the ZIGZAG_FAST state. This ensures
> 			// we cannot return from an FE_SET_FRONTEND ioctl before the first frontend
> 			// tune occurs
> 			if (fe->state & FESTATE_RETUNE) {
> 				fe->state = FESTATE_TUNING_FAST;
> 				wake_up_interruptible(&fe->wait_queue);
487,488c609,616
< 		if (s != fe->status)
< 			dvb_frontend_add_event (fe, s);
---
> 		// slow zigzag
> 		if (fe->state & FESTATE_SEARCHING_SLOW) {
> 			update_delay(&quality, &delay, fe->min_delay, s & FE_HAS_LOCK);
> 		    
> 			// Note: don't bother checking for wrapping; we stay in this state 
> 			// until we get a lock
> 			dvb_frontend_autotune(fe, 0);
> 		}
494,495d621
< 	up (&fe->sem);
< 
499c625
< 	wake_up_interruptible (&fe->wait_queue);
---
> 	dvb_frontend_wakeup(fe);
505a632,633
> 	unsigned long ret;
> 	
523,524c651,660
< 	wake_up_interruptible(&fe->wait_queue);
< 	interruptible_sleep_on(&fe->wait_queue);
---
> 	/* wake up the frontend thread, so it notices that fe->exit == 1 */
> 	dvb_frontend_wakeup(fe);
> 
> 	/* wait until the frontend thread has exited */
> 	ret = wait_event_interruptible(fe->wait_queue,0 == fe->thread_pid);
> 	if (-ERESTARTSYS != ret) {
> 		fe->state = FESTATE_IDLE;
> 		return;
> 	}
> 	fe->state = FESTATE_IDLE;
526c662
< 	/* paranoia check */
---
> 	/* paranoia check in case a signal arrived */
550a687
> 	fe->state = FESTATE_IDLE;
587a725
> 	struct dvb_frontend_tune_settings fetunesettings;
601a740
> 	case FE_SET_VOLTAGE:
604a744
> 		fe->state = FESTATE_DISEQC;
605a746
> 
607c748,801
< 		err = dvb_frontend_set_parameters (fe, parg, 1);
---
> 		fe->state = FESTATE_RETUNE;
> 	    
> 		memcpy (&fe->parameters, parg,
> 			sizeof (struct dvb_frontend_parameters));
> 
> 		memset(&fetunesettings, 0, sizeof(struct dvb_frontend_tune_settings));
> 		memcpy(&fetunesettings.parameters, parg,
> 		       sizeof (struct dvb_frontend_parameters));
> 		    
> 		// force auto frequency inversion if requested
> 		if (dvb_force_auto_inversion) {
> 			fe->parameters.inversion = INVERSION_AUTO;
> 			fetunesettings.parameters.inversion = INVERSION_AUTO;
> 		}
> 		if (fe->info->type == FE_OFDM) {
> 			/* without hierachical coding code_rate_LP is irrelevant,
> 			 * so we tolerate the otherwise invalid FEC_NONE setting */
> 			if (fe->parameters.u.ofdm.hierarchy_information == HIERARCHY_NONE &&
> 			    fe->parameters.u.ofdm.code_rate_LP == FEC_NONE)
> 				fe->parameters.u.ofdm.code_rate_LP = FEC_AUTO;
> 		}
> 
> 		// get frontend-specific tuning settings
> 		if (dvb_frontend_internal_ioctl(&fe->frontend, FE_GET_TUNE_SETTINGS, &fetunesettings) == 0) {
> 			fe->min_delay = (fetunesettings.min_delay_ms * HZ) / 1000;
> 			fe->max_drift = fetunesettings.max_drift;
> 			fe->step_size = fetunesettings.step_size;
> 		} else {
> 			// default values
> 			switch(fe->info->type) {
> 			case FE_QPSK:
> 				fe->min_delay = HZ/20; // default mindelay of 50ms
> 				fe->step_size = fe->parameters.u.qpsk.symbol_rate / 16000;
> 				fe->max_drift = fe->parameters.u.qpsk.symbol_rate / 2000;
> 				break;
> 			    
> 			case FE_QAM:
> 				fe->min_delay = HZ/20; // default mindelay of 50ms
> 				fe->step_size = 0;
> 				fe->max_drift = 0; // don't want any zigzagging under DVB-C frontends
> 				break;
> 			    
> 			case FE_OFDM:
> 				fe->min_delay = HZ/20; // default mindelay of 50ms
> 				fe->step_size = fe->info->frequency_stepsize * 2;
> 				fe->max_drift = (fe->info->frequency_stepsize * 2) + 1;
> 				break;
> 			}
> 		}
> 		if (dvb_override_tune_delay > 0) {
> 		       fe->min_delay = (dvb_override_tune_delay * HZ) / 1000;
> 		}
> 
> 		dvb_frontend_add_event (fe, 0);	    
608a803
> 
611a807
> 	    
617c813
< 		dvb_frontend_internal_ioctl (&fe->frontend, cmd, parg);
---
> 		err = dvb_frontend_internal_ioctl (&fe->frontend, cmd, parg);
619c815
< 
---
>     
620a817,832
> 	if (err < 0)
> 		return err;
> 
> 	// Force the CAN_INVERSION_AUTO bit on. If the frontend doesn't do it, it is done for it.
> 	if ((cmd == FE_GET_INFO) && (err == 0)) {
> 		struct dvb_frontend_info* tmp = (struct dvb_frontend_info*) parg;
> 		tmp->caps |= FE_CAN_INVERSION_AUTO;
> 	}
> 
> 	// if the frontend has just been set, wait until the first tune has finished.
> 	// This ensures the app doesn't start reading data too quickly, perhaps from the
> 	// previous lock, which is REALLY CONFUSING TO DEBUG!
> 	if ((cmd == FE_SET_FRONTEND) && (err == 0)) {
> 		dvb_frontend_wakeup(fe);
> 		err = wait_event_interruptible(fe->wait_queue, fe->state & ~FESTATE_RETUNE);
> 	}
683,686c895,898
<                          int (*before_ioctl) (struct dvb_frontend *frontend,
<                                               unsigned int cmd, void *arg),
<                          int (*after_ioctl)  (struct dvb_frontend *frontend,
<                                               unsigned int cmd, void *arg),
---
> 			 int (*before_ioctl) (struct dvb_frontend *frontend,
> 					      unsigned int cmd, void *arg),
> 			 int (*after_ioctl)  (struct dvb_frontend *frontend,
> 					      unsigned int cmd, void *arg),
690c902
<         struct list_head *entry;
---
> 	struct list_head *entry;
735,737c947,949
<                                                  unsigned int cmd, void *arg),
<                             int (*after_ioctl)  (struct dvb_frontend *frontend,
<                                                  unsigned int cmd, void *arg))
---
> 						 unsigned int cmd, void *arg),
> 			    int (*after_ioctl)	(struct dvb_frontend *frontend,
> 						 unsigned int cmd, void *arg))
916a1129
> 	fe->inversion = INVERSION_OFF;
955a1169,1171
> 	if ((info->caps & FE_NEEDS_BENDING) || (dvb_override_frequency_bending == 2))
> 		do_frequency_bending = 1;
>     
966c1182
<         struct list_head *entry, *n;
---
> 	struct list_head *entry, *n;
992a1209,1212
> MODULE_PARM(dvb_override_frequency_bending,"i");
> MODULE_PARM(dvb_force_auto_inversion,"i");
> MODULE_PARM(dvb_override_tune_delay,"i");
> 
994a1215,1217
> MODULE_PARM_DESC(dvb_override_frequency_bending, "0: normal (default), 1: never use frequency bending, 2: always use frequency bending");
> MODULE_PARM_DESC(dvb_force_auto_inversion, "0: normal (default), 1: INVERSION_AUTO forced always");
> MODULE_PARM_DESC(dvb_override_tune_delay, "0: normal (default), >0 => delay in milliseconds to wait for lock after a tune attempt");
Index: dvb/drivers/media/dvb/dvb-core/dvb_frontend.h
===================================================================
RCS file: /cvs/tuxbox/driver/dvb/drivers/media/dvb/dvb-core/dvb_frontend.h,v
retrieving revision 1.5
diff -r1.5 dvb_frontend.h
58a59,65
> struct dvb_frontend_tune_settings {
>         int min_delay_ms;
>         int step_size;
>         int max_drift;
>         struct dvb_frontend_parameters parameters;
> };
> 
62a70,73
>  * 
>  *   FE_SLEEP. Ioctl used to put frontend into a low power mode.
>  *   FE_INIT. Ioctl used to initialise the frontend.
>  *   FE_GET_TUNE_SETTINGS. Get the frontend-specific tuning loop settings for the supplied set of parameters.
66c77,78
< #define FE_RESET              _IO('v', 82)
---
> #define FE_GET_TUNE_SETTINGS  _IOWR('v', 83, struct dvb_frontend_tune_settings)
> #define FE_RESET              _IO('v', 82) //für den übergang
Index: dvb/drivers/media/dvb/frontends/at76c651.c
===================================================================
RCS file: /cvs/tuxbox/driver/dvb/drivers/media/dvb/frontends/at76c651.c,v
retrieving revision 1.58
diff -r1.58 at76c651.c
77c77
< 	    FE_CAN_RECOVER | FE_CAN_CLEAN_SETUP | FE_CAN_MUTE_TS
---
> 	    FE_CAN_RECOVER | FE_NEEDS_BENDING | FE_CAN_MUTE_TS
Index: dvb/drivers/media/dvb/frontends/tda80xx.c
===================================================================
RCS file: /cvs/tuxbox/driver/dvb/drivers/media/dvb/frontends/tda80xx.c,v
retrieving revision 1.3
diff -r1.3 tda80xx.c
99c99
< 		FE_CAN_MUTE_TS | FE_CAN_CLEAN_SETUP
---
> 		FE_CAN_MUTE_TS | FE_NEEDS_BENDING
Index: dvb/drivers/media/dvb/frontends/ves1820.c
===================================================================
RCS file: /cvs/tuxbox/driver/dvb/drivers/media/dvb/frontends/ves1820.c,v
retrieving revision 1.53
diff -r1.53 ves1820.c
115c115
< 		FE_CAN_CLEAN_SETUP
---
> 		FE_NEEDS_BENDING
Index: dvb/include/linux/dvb/frontend.h
===================================================================
RCS file: /cvs/tuxbox/driver/dvb/include/linux/dvb/frontend.h,v
retrieving revision 1.7
diff -r1.7 frontend.h
62,64c62,64
< 	FE_CAN_RECOVER                = 0x20000000,
< 	FE_CAN_CLEAN_SETUP            = 0x40000000,
< 	FE_CAN_MUTE_TS                = 0x80000000
---
> 	FE_NEEDS_BENDING              = 0x20000000, // frontend requires frequency bending
> 	FE_CAN_RECOVER                = 0x40000000, // frontend can recover from a cable unplug automatically
> 	FE_CAN_MUTE_TS                = 0x80000000  // frontend can stop spurious TS data output
seife
Developer
Beiträge: 4189
Registriert: Sonntag 2. November 2003, 12:36

Beitrag von seife »

(nein, ich bin kein Profi, aber ich pfusche gerade in derselben Ecke rum).

a) Was genau willst du denn mit dem Patch erreichen?
b) Könntest du bitte einen unified Diff machen (mittels "diff -up") und das irgendwo hochladen? So kann man das sauschwer lesen und verstehen.
T-Tron
Interessierter
Interessierter
Beiträge: 67
Registriert: Mittwoch 2. November 2005, 07:45

Beitrag von T-Tron »

Klicke einfach bei meinem Beitrag "Zitat", dann kannst du sauber per copy&paste das diff in eine leere diff-datei kopieren und im driver dir patch -p0 < bla.diff eingeben.
Zuletzt geändert von T-Tron am Dienstag 25. September 2007, 13:22, insgesamt 1-mal geändert.
ingrid
Erleuchteter
Erleuchteter
Beiträge: 600
Registriert: Samstag 14. Oktober 2006, 10:53

Beitrag von ingrid »

seife hat geschrieben:a) Was genau willst du denn mit dem Patch erreichen?
'ne Antwort auf den Part wäre interessanter gewesen. ;)
dwilx

Beitrag von dwilx »

Ist da sowas wie ein verbessertes Finetuning fürs Frontend?
mb405
Tuxboxer
Tuxboxer
Beiträge: 2331
Registriert: Donnerstag 24. März 2005, 21:52

Beitrag von mb405 »

ich habs mal anschaulicher gemacht, aber es ist kein diff, was man anwenden kann aufs cvs !!
http://home.arcor.de/mb407/dbox2/treiber.diff
seife
Developer
Beiträge: 4189
Registriert: Sonntag 2. November 2003, 12:36

Beitrag von seife »

T-Tron hat geschrieben:Klicke einfach bei meinem Beitraf "Zitat", dann kannst du sauber per copy&paste das diff in eine leere diff-datei kopieren und im driver dir patch -p0 < bla.diff eingeben.
Nein, kann ich nicht. Weil ich an ähnlichen Stellen schon Code geändert habe und dein patch deswegen rejected.

Und unified diffs sind einfach besser zu reviewen, weil man noch ein wenig Kontext mit dazusieht.
dwilx

Beitrag von dwilx »

Ich denke mal in Bezug auf das hier:
http://forum.tuxbox-cvs.sourceforge.net ... ht=#342722
Rebel1
Interessierter
Interessierter
Beiträge: 87
Registriert: Montag 14. August 2006, 09:10

Beitrag von Rebel1 »

Gegen das CVS gedifft: :D

Code: Alles auswählen

Index: dvb/drivers/media/dvb/avia/avia_av_core.c
===================================================================
RCS file: /cvs/tuxbox/driver/dvb/drivers/media/dvb/avia/avia_av_core.c,v
retrieving revision 1.99
diff -u -r1.99 avia_av_core.c
--- a/dvb/drivers/media/dvb/avia/avia_av_core.c	8 Jan 2006 21:36:22 -0000	1.99
+++ b/dvb/drivers/media/dvb/avia/avia_av_core.c	25 Sep 2007 08:58:12 -0000
@@ -1225,10 +1225,15 @@
 //		avia_av_cmd(NewChannel, 0x00, 0xFFFF, 0xFFFF);
 		avia_av_cmd(SelectStream, 0x03 - bypass_mode, pid_audio);
 //		avia_av_cmd(SelectStream, 0x00, pid_video);
+
 		if (aviarev && bypass_mode_changed) {
 			avia_av_cmd(SelectStream, 0x00, (play_state_video == AVIA_AV_PLAY_STATE_PLAYING) ? pid_video : 0xFFFF);
 			avia_av_cmd(Play, 0x00, (play_state_video == AVIA_AV_PLAY_STATE_PLAYING) ? pid_video : 0xFFFF, pid_audio);
 		}
+
+		if ((aviarev) && (play_state_audio != AVIA_AV_PLAY_STATE_PAUSED)) // oder nur  if (aviarev)
+			avia_av_cmd(Play, 0x00, (play_state_video == AVIA_AV_PLAY_STATE_PLAYING) ? pid_video : 0xFFFF, pid_audio);
+
 		bypass_mode_changed = 0;
 		break;
 
@@ -1239,9 +1244,18 @@
 
 		dprintk("avia_av: stopping audio decoder\n");
 
+
 		if (play_state_video == AVIA_AV_PLAY_STATE_STOPPED) {
+
+			if (aviarev) {
+				avia_av_cmd(SelectStream, 0x03 - bypass_mode, 0xFFFF); // ???
+				avia_av_cmd(Abort, 0x00);
+			}
+
 			avia_av_dram_write(AV_SYNC_MODE, AVIA_AV_SYNC_MODE_NONE);
-			avia_av_cmd(NewChannel, 0x00, 0xFFFF, 0xFFFF);
+
+			if (!aviarev)
+				avia_av_cmd(NewChannel, 0x00, 0xFFFF, 0xFFFF);
 		}
 		else {
 			avia_av_cmd(SelectStream, 0x03 - bypass_mode, 0xFFFF);
@@ -1276,6 +1290,9 @@
 //			avia_av_cmd(NewChannel, 0x00, 0xFFFF, 0xFFFF);
 //			avia_av_cmd(SelectStream, 0x03 - bypass_mode, pid_audio);
 			avia_av_cmd(SelectStream, 0x00, pid_video);
+
+//			if (aviarev)
+//				avia_av_cmd(Play, 0x00, pid_video, (play_state_audio == AVIA_AV_PLAY_STATE_PLAYING) ? pid_audio : 0xFFFF);
 		}
 		break;
 
@@ -1287,8 +1304,16 @@
 		dprintk("avia_av: stopping video decoder\n");
 
 		if (play_state_audio == AVIA_AV_PLAY_STATE_STOPPED) {
+
+			if (aviarev) {
+				avia_av_cmd(SelectStream, 0x00, 0xFFFF); // ???
+				avia_av_cmd(Abort, 0x00);
+			}
+
 			avia_av_dram_write(AV_SYNC_MODE, AVIA_AV_SYNC_MODE_NONE);
-			avia_av_cmd(NewChannel, 0x00, 0xFFFF, 0xFFFF);
+
+			if (!aviarev)
+				avia_av_cmd(NewChannel, 0x00, 0xFFFF, 0xFFFF);
 		}
 		else {
 			avia_av_cmd(SelectStream, 0x00, 0xFFFF);
@@ -1558,3 +1583,4 @@
 MODULE_PARM_DESC(tv_standard, "0: PAL, 1: NTSC");
 MODULE_PARM_DESC(no_watchdog, "0: wd enabled, 1: wd disabled");
 MODULE_PARM_DESC(firmware, "path to microcode");
+
Index: dvb/drivers/media/dvb/avia/avia_gt_ucode.c
===================================================================
RCS file: /cvs/tuxbox/driver/dvb/drivers/media/dvb/avia/avia_gt_ucode.c,v
retrieving revision 1.14
diff -u -r1.14 avia_gt_ucode.c
--- a/dvb/drivers/media/dvb/avia/avia_gt_ucode.c	24 Jun 2004 00:26:58 -0000	1.14
+++ b/dvb/drivers/media/dvb/avia/avia_gt_ucode.c	25 Sep 2007 08:58:13 -0000
@@ -938,9 +938,8 @@
  		ucode_info.caps = (AVIA_GT_UCODE_CAP_ECD |
  			AVIA_GT_UCODE_CAP_PES |
  			AVIA_GT_UCODE_CAP_SEC |
- 			AVIA_GT_UCODE_CAP_TS |
-			AVIA_GT_UCODE_CAP_MSGQ);
-		ucode_info.prop_interface_flags=CAN_WAITPUSI;
+ 			AVIA_GT_UCODE_CAP_TS);
+		ucode_info.prop_interface_flags=0;
 		ucode_info.qid_offset = 1;
 		ucode_info.queue_mode[PES] = 3;
  		break;
Index: dvb/drivers/media/dvb/dvb-core/dvb_compat.h
===================================================================
RCS file: /cvs/tuxbox/driver/dvb/drivers/media/dvb/dvb-core/dvb_compat.h,v
retrieving revision 1.5
diff -u -r1.5 dvb_compat.h
--- a/dvb/drivers/media/dvb/dvb-core/dvb_compat.h	24 Nov 2003 09:38:39 -0000	1.5
+++ b/dvb/drivers/media/dvb/dvb-core/dvb_compat.h	25 Sep 2007 08:58:13 -0000
@@ -8,12 +8,69 @@
 #include <linux/fs.h>
 #include <linux/devfs_fs_kernel.h>
 
+#ifndef wait_event_interruptible_timeout
+#define __wait_event_interruptible_timeout(wq, condition, ret)          \
+do {                                                                    \
+        wait_queue_t __wait;                                            \
+        init_waitqueue_entry(&__wait, current);                         \
+                                                                        \
+        add_wait_queue(&wq, &__wait);                                   \
+        for (;;) {                                                      \
+                set_current_state(TASK_INTERRUPTIBLE);                  \
+                if (condition)                                          \
+                        break;                                          \
+                if (!signal_pending(current)) {                         \
+                        ret = schedule_timeout(ret);                    \
+                        if (!ret)                                       \
+                                break;                                  \
+                        continue;                                       \
+                }                                                       \
+                ret = -ERESTARTSYS;                                     \
+                break;                                                  \
+        }                                                               \
+        current->state = TASK_RUNNING;                                  \
+        remove_wait_queue(&wq, &__wait);                                \
+} while (0)
+
+#define wait_event_interruptible_timeout(wq, condition, timeout)        \
+({                                                                      \
+        long __ret = timeout;                                           \
+        if (!(condition))                                               \
+                __wait_event_interruptible_timeout(wq, condition, __ret); \
+        __ret;                                                          \
+})
+#endif
+
+#ifndef VIDEO_AUDIO_BALANCE
+#define VIDEO_AUDIO_BALANCE	32
+#endif
+
+#ifndef list_for_each_entry
+#define list_for_each_entry(pos, head, member)				\
+	for (pos = list_entry((head)->next, typeof(*pos), member),	\
+		     prefetch(pos->member.next);			\
+	     &pos->member != (head); 					\
+	     pos = list_entry(pos->member.next, typeof(*pos), member),	\
+		     prefetch(pos->member.next))
+#endif
+
+#ifndef iminor
 #define iminor(xx) minor(xx->i_rdev)
+#endif
 
+#ifndef irqreturn_t
 #define irqreturn_t void
 #define IRQ_NONE
 #define IRQ_HANDLED
+#endif
+
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,4,22))
+u32 crc32_le(u32 crc, unsigned char const *p, size_t len);
+#endif
+
 #define strlcpy strncpy
+
 extern devfs_handle_t dvb_devfs_handle;
 
 int devfs_mk_cdev(dev_t dev, umode_t mode, const char *fmt, ...);
Index: dvb/drivers/media/dvb/dvb-core/dvb_frontend.c
===================================================================
RCS file: /cvs/tuxbox/driver/dvb/drivers/media/dvb/dvb-core/dvb_frontend.c,v
retrieving revision 1.23
diff -u -r1.23 dvb_frontend.c
--- a/dvb/drivers/media/dvb/dvb-core/dvb_frontend.c	11 Sep 2003 22:43:08 -0000	1.23
+++ b/dvb/drivers/media/dvb/dvb-core/dvb_frontend.c	25 Sep 2007 08:58:14 -0000
@@ -1,10 +1,13 @@
 /*
- * dvb-core.c: DVB core driver
+ * dvb_frontend.c: DVB frontend tuning interface/thread
+ *
  *
  * Copyright (C) 1999-2001 Ralph  Metzler
- *                         Marcus Metzler
- *                         Holger Waechtler 
- *                                    for convergence integrated media GmbH
+ *			   Marcus Metzler
+ *			   Holger Waechtler 
+ *				      for convergence integrated media GmbH
+ * 
+ * Copyright (C) 2004 Andrew de Quincey (tuning thread cleanup)
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
@@ -13,7 +16,7 @@
  *
  * This program is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the
  * GNU General Public License for more details.
  *
  * You should have received a copy of the GNU General Public License
@@ -37,9 +40,41 @@
 #include "dvbdev.h"
 #include "dvb_functions.h"
 
+#define FESTATE_IDLE 1
+#define FESTATE_RETUNE 2
+#define FESTATE_TUNING_FAST 4
+#define FESTATE_TUNING_SLOW 8
+#define FESTATE_TUNED 16
+#define FESTATE_ZIGZAG_FAST 32
+#define FESTATE_ZIGZAG_SLOW 64
+#define FESTATE_DISEQC 128
+#define FESTATE_WAITFORLOCK (FESTATE_TUNING_FAST | FESTATE_TUNING_SLOW | FESTATE_ZIGZAG_FAST | FESTATE_ZIGZAG_SLOW | FESTATE_DISEQC)
+#define FESTATE_SEARCHING_FAST (FESTATE_TUNING_FAST | FESTATE_ZIGZAG_FAST)
+#define FESTATE_SEARCHING_SLOW (FESTATE_TUNING_SLOW | FESTATE_ZIGZAG_SLOW)
+#define FESTATE_LOSTLOCK (FESTATE_ZIGZAG_FAST | FESTATE_ZIGZAG_SLOW)
+/*
+ * FESTATE_IDLE. No tuning parameters have been supplied and the loop is idling.
+ * FESTATE_RETUNE. Parameters have been supplied, but we have not yet performed the first tune.
+ * FESTATE_TUNING_FAST. Tuning parameters have been supplied and fast zigzag scan is in progress.
+ * FESTATE_TUNING_SLOW. Tuning parameters have been supplied. Fast zigzag failed, so we're trying again, but slower.
+ * FESTATE_TUNED. The frontend has successfully locked on.
+ * FESTATE_ZIGZAG_FAST. The lock has been lost, and a fast zigzag has been initiated to try and regain it.
+ * FESTATE_ZIGZAG_SLOW. The lock has been lost. Fast zigzag has been failed, so we're trying again, but slower.
+ * FESTATE_DISEQC. A DISEQC command has just been issued.
+ * FESTATE_WAITFORLOCK. When we're waiting for a lock.
+ * FESTATE_SEARCHING_FAST. When we're searching for a signal using a fast zigzag scan.
+ * FESTATE_SEARCHING_SLOW. When we're searching for a signal using a slow zigzag scan.
+ * FESTATE_LOSTLOCK. When the lock has been lost, and we're searching it again.
+ */
+
 
 static int dvb_frontend_debug = 0;
 static int dvb_shutdown_timeout = 5;
+static int dvb_override_frequency_bending = 0;
+static int dvb_force_auto_inversion = 0;
+static int dvb_override_tune_delay = 0;
+
+static int do_frequency_bending = 0;
 
 #define dprintk if (dvb_frontend_debug) printk
 
@@ -47,11 +82,11 @@
 
 struct dvb_fe_events {
 	struct dvb_frontend_event events[MAX_EVENT];
-	int                       eventw;
-	int                       eventr;
-	int                       overflow;
-	wait_queue_head_t         wait_queue;
-	struct semaphore          sem;
+	int			  eventw;
+	int			  eventr;
+	int			  overflow;
+	wait_queue_head_t	  wait_queue;
+	struct semaphore	  sem;
 };
 
 
@@ -66,13 +101,19 @@
 	wait_queue_head_t wait_queue;
 	pid_t thread_pid;
 	unsigned long release_jiffies;
-	unsigned long lost_sync_jiffies;
+	int state;
 	int bending;
 	int lnb_drift;
-	int timeout_count;
-	int lost_sync_count;
+	int inversion;
+	int auto_step;
+	int auto_sub_step;
+	int started_auto_step;
+	int min_delay;
+	int max_drift;
+	int step_size;
 	int exit;
-        fe_status_t status;
+	int wakeup;
+	fe_status_t status;
 };
 
 
@@ -169,8 +210,8 @@
 		frequency += this_fe->lnb_drift;
 		frequency += this_fe->bending;
 
-		if (this_fe != fe && fe->lost_sync_count != -1 &&
-                    frequency > f - stepsize && frequency < f + stepsize)
+		if (this_fe != fe && (fe->state != FESTATE_IDLE) &&
+		    frequency > f - stepsize && frequency < f + stepsize)
 		{
 			if (recursive % 2)
 				this_fe->bending += stepsize;
@@ -192,9 +233,6 @@
 {
 	dprintk ("%s\n", __FUNCTION__);
 
-	if ((fe->status & FE_HAS_LOCK) && !(s & FE_HAS_LOCK))
-		fe->lost_sync_jiffies = jiffies;
-
 	if (((s ^ fe->status) & FE_HAS_LOCK) && (s & FE_HAS_LOCK))
 		dvb_delay (fe->info->notifier_delay);
 
@@ -252,77 +290,44 @@
 static int dvb_frontend_get_event (struct dvb_frontend_data *fe,
 			    struct dvb_frontend_event *event, int flags)
 {
-        struct dvb_fe_events *events = &fe->events;
+	struct dvb_fe_events *events = &fe->events;
 
 	dprintk ("%s\n", __FUNCTION__);
 
 	if (events->overflow) {
-                events->overflow = 0;
-                return -EOVERFLOW;
-        }
+		events->overflow = 0;
+		return -EOVERFLOW;
+	}
 
-        if (events->eventw == events->eventr) {
+	if (events->eventw == events->eventr) {
 		int ret;
 
-                if (flags & O_NONBLOCK)
-                        return -EWOULDBLOCK;
+		if (flags & O_NONBLOCK)
+			return -EWOULDBLOCK;
 
 		up(&fe->sem);
 
-                ret = wait_event_interruptible (events->wait_queue,
-                                                events->eventw != events->eventr);
+		ret = wait_event_interruptible (events->wait_queue,
+						events->eventw != events->eventr);
 
-        	if (down_interruptible (&fe->sem))
+		if (down_interruptible (&fe->sem))
 			return -ERESTARTSYS;
 
-                if (ret < 0)
-                        return ret;
-        }
+		if (ret < 0)
+			return ret;
+	}
 
-        if (down_interruptible (&events->sem))
+	if (down_interruptible (&events->sem))
 		return -ERESTARTSYS;
 
-       	memcpy (event, &events->events[events->eventr],
+	memcpy (event, &events->events[events->eventr],
 		sizeof(struct dvb_frontend_event));
 
-        events->eventr = (events->eventr + 1) % MAX_EVENT;
-
-       	up (&events->sem);
-
-        return 0;
-}
-
+	events->eventr = (events->eventr + 1) % MAX_EVENT;
 
-static int dvb_frontend_set_parameters (struct dvb_frontend_data *fe,
-				 struct dvb_frontend_parameters *param,
-				 int first_trial)
-{
-	struct dvb_frontend *frontend = &fe->frontend;
-	int err;
-
-	if (first_trial) {
-		fe->timeout_count = 0;
-		fe->lost_sync_count = 0;
-		fe->lost_sync_jiffies = jiffies;
-		fe->lnb_drift = 0;
-		if (fe->status & ~FE_TIMEDOUT)
-			dvb_frontend_add_event (fe, 0);
-		memcpy (&fe->parameters, param,
-			sizeof (struct dvb_frontend_parameters));
-	}
-
-	dvb_bend_frequency (fe, 0);
-
-	dprintk ("%s: f == %i, drift == %i\n",
-		 __FUNCTION__, (int) param->frequency, (int) fe->lnb_drift);
-
-	param->frequency += fe->lnb_drift + fe->bending;
-	err = dvb_frontend_internal_ioctl (frontend, FE_SET_FRONTEND, param);
-	param->frequency -= fe->lnb_drift + fe->bending;
-
-	wake_up_interruptible (&fe->wait_queue);
+	up (&events->sem);
 
-	return err;
+	return 0;
 }
 
 static void dvb_frontend_init (struct dvb_frontend_data *fe)
@@ -336,76 +341,115 @@
 	dvb_frontend_internal_ioctl (frontend, FE_INIT, NULL);
 }
 
-
-static void update_delay (int *quality, int *delay, int locked)
+static void update_delay (int *quality, int *delay, int min_delay, int locked)
 {
-	int q2;
-
-	dprintk ("%s\n", __FUNCTION__);
-
-	if (locked)
-		(*quality) = (*quality * 220 + 36*256) / 256;
-	else
-		(*quality) = (*quality * 220 + 0) / 256;
-
-	q2 = *quality - 128;
-	q2 *= q2;
-
-	*delay = HZ/20 + q2 * HZ / (128*128);
+	    int q2;
+    
+	    dprintk ("%s\n", __FUNCTION__);
+    
+	    if (locked)
+		      (*quality) = (*quality * 220 + 36*256) / 256;
+	    else
+		      (*quality) = (*quality * 220 + 0) / 256;
+    
+	    q2 = *quality - 128;
+	    q2 *= q2;
+    
+	    *delay = min_delay + q2 * HZ / (128*128);
 }
 
-
-#define LNB_DRIFT 1024  /*  max. tolerated LNB drift, XXX FIXME: adjust! */
-#define TIMEOUT 2*HZ
-
 /**
- *  here we only come when we have lost the lock bit, 
- *  let's try to do something useful...
+ * Performs automatic twiddling of frontend parameters.
+ * 
+ * @param fe The frontend concerned.
+ * @param check_wrapped Checks if an iteration has completed. DO NOT SET ON THE FIRST ATTEMPT
+ * @returns Number of complete iterations that have been performed.
  */
-static void dvb_frontend_recover (struct dvb_frontend_data *fe)
+static int dvb_frontend_autotune(struct dvb_frontend_data *fe, int check_wrapped)
 {
-	dprintk ("%s\n", __FUNCTION__);
-
-#if 0
-	if (fe->timeout_count > 3) {
-		printk ("%s: frontend seems dead, reinitializing...\n",
-			__FUNCTION__);
-		dvb_call_frontend_notifiers (fe, 0);
-		dvb_frontend_internal_ioctl (&fe->frontend, FE_INIT, NULL);
-		dvb_frontend_set_parameters (fe, &fe->parameters, 1);
-		dvb_frontend_add_event (fe, FE_REINIT);
-		fe->lost_sync_jiffies = jiffies;
-		fe->timeout_count = 0;
-		return;
-	}
-#endif
+	int autoinversion;
+	int ready = 0;
+	int original_inversion = fe->parameters.inversion;
+	u32 original_frequency = fe->parameters.frequency;
+
+	// are we using autoinversion?
+	autoinversion = ((!(fe->info->caps & FE_CAN_INVERSION_AUTO)) && (fe->parameters.inversion == INVERSION_AUTO));
+
+	// setup parameters correctly
+	while(!ready) {
+		// calculate the lnb_drift
+		fe->lnb_drift = fe->auto_step * fe->step_size;
+
+		// wrap the auto_step if we've exceeded the maximum drift
+		if (fe->lnb_drift > fe->max_drift) {
+			fe->auto_step = 0;
+			fe->auto_sub_step = 0;
+			fe->lnb_drift = 0;
+		}
 
-	/**
-	 *  let's start a zigzag scan to compensate LNB drift...
-	 */
-	{
-		int j = fe->lost_sync_count;
-		int stepsize;
-		
-		if (fe->info->type == FE_QPSK)
-			stepsize = fe->parameters.u.qpsk.symbol_rate / 16000;
-		else if (fe->info->type == FE_QAM)
-			stepsize = 0;
-		else
-			stepsize = fe->info->frequency_stepsize * 2;
+		// perform inversion and +/- zigzag
+		switch(fe->auto_sub_step) {
+		case 0:
+			// try with the current inversion and current drift setting
+			ready = 1;
+			break;
+	    
+		case 1:
+			if (!autoinversion) break;
 
-		if (j % 32 == 0) {
-			fe->lnb_drift = 0;
-		} else {
+			fe->inversion = (fe->inversion == INVERSION_OFF) ? INVERSION_ON : INVERSION_OFF;
+			ready = 1;
+			break;
+	    
+		case 2:
+			if (fe->lnb_drift == 0) break;
+		    
+			fe->lnb_drift = -fe->lnb_drift;
+			ready = 1;
+			break;
+	    
+		case 3:
+			if (fe->lnb_drift == 0) break;
+			if (!autoinversion) break;
+		    
+			fe->inversion = (fe->inversion == INVERSION_OFF) ? INVERSION_ON : INVERSION_OFF;
 			fe->lnb_drift = -fe->lnb_drift;
-			if (j % 2)
-				fe->lnb_drift += stepsize;
+			ready = 1;
+			break;
+		    
+		default:
+			fe->auto_step++;
+			fe->auto_sub_step = -1; // it'll be incremented to 0 in a moment
+			break;
 		}
+	    
+		if (!ready) fe->auto_sub_step++;
+	}
 
-		dvb_frontend_set_parameters (fe, &fe->parameters, 0);
+	// if this attempt would hit where we started, indicate a complete iteration has occurred
+	if ((fe->auto_step == fe->started_auto_step) && (fe->auto_sub_step == 0) && check_wrapped) {
+		return 1;
 	}
 
-	dvb_frontend_internal_ioctl (&fe->frontend, FE_RESET, NULL);
+	// perform frequency bending if necessary
+	if ((dvb_override_frequency_bending != 1) && do_frequency_bending)
+		dvb_bend_frequency(fe, 0);
+
+	// instrumentation
+	dprintk("%s: drift:%i bending:%i inversion:%i auto_step:%i auto_sub_step:%i started_auto_step:%i\n", 
+		__FUNCTION__, fe->lnb_drift, fe->bending, fe->inversion, fe->auto_step, fe->auto_sub_step,
+		fe->started_auto_step);
+    
+	// set the frontend itself
+	fe->parameters.frequency += fe->lnb_drift + fe->bending;
+	if (autoinversion) fe->parameters.inversion = fe->inversion;
+	dvb_frontend_internal_ioctl (&fe->frontend, FE_SET_FRONTEND, &fe->parameters);
+	fe->parameters.frequency = original_frequency;
+	fe->parameters.inversion = original_inversion;
+
+	// normal return
+	fe->auto_sub_step++;
+	return 0;
 }
 
 
@@ -422,13 +466,28 @@
 	return 0;
 }
 
+static int dvb_frontend_should_wakeup (struct dvb_frontend_data *fe)
+{
+	if (fe->wakeup) {
+		fe->wakeup = 0;
+		return 1;
+	}
+	return dvb_frontend_is_exiting(fe);
+}
+
+static void dvb_frontend_wakeup (struct dvb_frontend_data *fe) {
+	fe->wakeup = 1;
+	wake_up_interruptible(&fe->wait_queue);
+}
 
 static int dvb_frontend_thread (void *data)
 {
 	struct dvb_frontend_data *fe = (struct dvb_frontend_data *) data;
+	unsigned long timeout;
 	char name [15];
 	int quality = 0, delay = 3*HZ;
 	fe_status_t s;
+	int check_wrapped = 0;
 
 	dprintk ("%s\n", __FUNCTION__);
 
@@ -437,72 +496,141 @@
 
 	dvb_kernel_thread_setup (name);
 
-	fe->lost_sync_count = -1;
-
 	dvb_call_frontend_notifiers (fe, 0);
 	dvb_frontend_init (fe);
+	fe->wakeup = 0;
 
-	while (!dvb_frontend_is_exiting (fe)) {
-		up (&fe->sem);      /* is locked when we enter the thread... */
+	while (1) {
+		up (&fe->sem);	    /* is locked when we enter the thread... */
 
-		interruptible_sleep_on_timeout (&fe->wait_queue, delay);
-		if (signal_pending(current))
+		timeout = wait_event_interruptible_timeout(fe->wait_queue,0 != dvb_frontend_should_wakeup (fe), delay);
+		if (-ERESTARTSYS == timeout || 0 != dvb_frontend_is_exiting (fe)) {
+			/* got signal or quitting */
 			break;
+		}
 
 		if (down_interruptible (&fe->sem))
 			break;
 
-		if (fe->lost_sync_count == -1)
+		// if we've got no parameters, just keep idling
+		if (fe->state & FESTATE_IDLE) {
+			delay = 3*HZ;
+			quality = 0;
 			continue;
+		}
+	    
+		// get the frontend status
+		if (fe->state & FESTATE_RETUNE) {
+			s = 0;
+		} else {
+			dvb_frontend_internal_ioctl (&fe->frontend, FE_READ_STATUS, &s);
+			if (s != fe->status) {
+				dvb_frontend_add_event (fe, s);
+			}
+		}
+		// if we're not tuned, and we have a lock, move to the TUNED state
+		if ((fe->state & FESTATE_WAITFORLOCK) && (s & FE_HAS_LOCK)) {
+			update_delay(&quality, &delay, fe->min_delay, s & FE_HAS_LOCK);
+			fe->state = FESTATE_TUNED;
+
+			// if we're tuned, then we have determined the correct inversion
+			if ((!(fe->info->caps & FE_CAN_INVERSION_AUTO)) && (fe->parameters.inversion == INVERSION_AUTO)) {
+				fe->parameters.inversion = fe->inversion;
+			}
+			continue;
+		}
 
-		if (dvb_frontend_is_exiting (fe))
-			break;
-
-		dvb_frontend_internal_ioctl (&fe->frontend, FE_READ_STATUS, &s);
+		// if we are tuned already, check we're still locked
+		if (fe->state & FESTATE_TUNED) {
+			update_delay(&quality, &delay, fe->min_delay, s & FE_HAS_LOCK);
+		    
+			// we're tuned, and the lock is still good...
+			if (s & FE_HAS_LOCK) {
+				continue;
+			} else {
+				// if we _WERE_ tuned, but now don't have a lock, need to zigzag
+				fe->state = FESTATE_ZIGZAG_FAST;
+				fe->started_auto_step = fe->auto_step;
+				check_wrapped = 0;
+				// fallthrough
+			}
+		}
 
-		update_delay (&quality, &delay, s & FE_HAS_LOCK);
+		// don't actually do anything if we're in the LOSTLOCK state, the frontend is set to
+		// FE_CAN_RECOVER, and the max_drift is 0
+		if ((fe->state & FESTATE_LOSTLOCK) && 
+		    (fe->info->caps & FE_CAN_RECOVER) && (fe->max_drift == 0)) {
+			update_delay(&quality, &delay, fe->min_delay, s & FE_HAS_LOCK);
+			continue;
+		}
+	    
+		// don't do anything if we're in the DISEQC state, since this might be someone
+		// with a motorized dish controlled by DISEQC. If its actually a re-tune, there will
+		// be a SET_FRONTEND soon enough.
+		if (fe->state & FESTATE_DISEQC) {
+			update_delay(&quality, &delay, fe->min_delay, s & FE_HAS_LOCK);
+			continue;
+		}
 
-		s &= ~FE_TIMEDOUT;
+		// if we're in the RETUNE state, set everything up for a brand new scan,
+		// keeping the current inversion setting, as the next tune is _very_ likely
+		// to require the same
+		if (fe->state & FESTATE_RETUNE) {
+			fe->lnb_drift = 0;
+			fe->auto_step = 0;
+			fe->auto_sub_step = 0;
+			fe->started_auto_step = 0;
+			check_wrapped = 0;
+		}
 
-		if (s & FE_HAS_LOCK) {
-			fe->timeout_count = 0;
-			fe->lost_sync_count = 0;
-		} else {
-			fe->lost_sync_count++;
-			if (!(fe->info->caps & FE_CAN_RECOVER)) {
-				if (!(fe->info->caps & FE_CAN_CLEAN_SETUP)) {
-					if (fe->lost_sync_count < 10)
-						continue;
-				}
-				dvb_frontend_recover (fe);
-				delay = HZ/5;
+		// fast zigzag.
+		if ((fe->state & FESTATE_SEARCHING_FAST) || (fe->state & FESTATE_RETUNE)) {
+			delay = fe->min_delay;
+
+			// peform a tune
+			if (dvb_frontend_autotune(fe, check_wrapped)) {
+				// OK, if we've run out of trials at the fast speed. Drop back to
+				// slow for the _next_ attempt
+				fe->state = FESTATE_SEARCHING_SLOW;
+				fe->started_auto_step = fe->auto_step;
+				continue;
 			}
-			if (jiffies - fe->lost_sync_jiffies > TIMEOUT) {
-				s |= FE_TIMEDOUT;
-				if ((fe->status & FE_TIMEDOUT) == 0)
-					fe->timeout_count++;
+			check_wrapped = 1;
+
+			// if we've just retuned, enter the ZIGZAG_FAST state. This ensures
+			// we cannot return from an FE_SET_FRONTEND ioctl before the first frontend
+			// tune occurs
+			if (fe->state & FESTATE_RETUNE) {
+				fe->state = FESTATE_TUNING_FAST;
+				wake_up_interruptible(&fe->wait_queue);
 			}
 		}
 
-		if (s != fe->status)
-			dvb_frontend_add_event (fe, s);
+		// slow zigzag
+		if (fe->state & FESTATE_SEARCHING_SLOW) {
+			update_delay(&quality, &delay, fe->min_delay, s & FE_HAS_LOCK);
+		    
+			// Note: don't bother checking for wrapping; we stay in this state 
+			// until we get a lock
+			dvb_frontend_autotune(fe, 0);
+		}
 	};
 
 	if (dvb_shutdown_timeout)
 		dvb_frontend_internal_ioctl (&fe->frontend, FE_SLEEP, NULL); 
 
-	up (&fe->sem);
-
 	fe->thread_pid = 0;
 	mb();
 
-	wake_up_interruptible (&fe->wait_queue);
+	dvb_frontend_wakeup(fe);
 	return 0;
 }
 
 
 static void dvb_frontend_stop (struct dvb_frontend_data *fe)
 {
+	unsigned long ret;
+	
 	dprintk ("%s\n", __FUNCTION__);
 
 	fe->exit = 1;
@@ -520,10 +648,18 @@
 		return;
 	}
 
-	wake_up_interruptible(&fe->wait_queue);
-	interruptible_sleep_on(&fe->wait_queue);
+	/* wake up the frontend thread, so it notices that fe->exit == 1 */
+	dvb_frontend_wakeup(fe);
+
+	/* wait until the frontend thread has exited */
+	ret = wait_event_interruptible(fe->wait_queue,0 == fe->thread_pid);
+	if (-ERESTARTSYS != ret) {
+		fe->state = FESTATE_IDLE;
+		return;
+	}
+	fe->state = FESTATE_IDLE;
 
-	/* paranoia check */
+	/* paranoia check in case a signal arrived */
 	if (fe->thread_pid)
 		printk("dvb_frontend_stop: warning: thread PID %d won't exit\n",
 				fe->thread_pid);
@@ -548,6 +684,7 @@
 	if (down_interruptible (&fe->sem))
 		return -EINTR;
 
+	fe->state = FESTATE_IDLE;
 	fe->exit = 0;
 	fe->thread_pid = 0;
 	mb();
@@ -585,6 +722,7 @@
 {
 	struct dvb_device *dvbdev = file->private_data;
 	struct dvb_frontend_data *fe = dvbdev->priv;
+	struct dvb_frontend_tune_settings fetunesettings;
 	int err = 0;
 
 	dprintk ("%s\n", __FUNCTION__);
@@ -599,25 +737,99 @@
 	case FE_DISEQC_SEND_MASTER_CMD:
 	case FE_DISEQC_SEND_BURST:
 	case FE_SET_TONE:
+	case FE_SET_VOLTAGE:
 		if (fe->status)
 			dvb_call_frontend_notifiers (fe, 0);
 		dvb_frontend_internal_ioctl (&fe->frontend, cmd, parg);
+		fe->state = FESTATE_DISEQC;
 		break;
+
 	case FE_SET_FRONTEND:
-		err = dvb_frontend_set_parameters (fe, parg, 1);
+		fe->state = FESTATE_RETUNE;
+	    
+		memcpy (&fe->parameters, parg,
+			sizeof (struct dvb_frontend_parameters));
+
+		memset(&fetunesettings, 0, sizeof(struct dvb_frontend_tune_settings));
+		memcpy(&fetunesettings.parameters, parg,
+		       sizeof (struct dvb_frontend_parameters));
+		    
+		// force auto frequency inversion if requested
+		if (dvb_force_auto_inversion) {
+			fe->parameters.inversion = INVERSION_AUTO;
+			fetunesettings.parameters.inversion = INVERSION_AUTO;
+		}
+		if (fe->info->type == FE_OFDM) {
+			/* without hierachical coding code_rate_LP is irrelevant,
+			 * so we tolerate the otherwise invalid FEC_NONE setting */
+			if (fe->parameters.u.ofdm.hierarchy_information == HIERARCHY_NONE &&
+			    fe->parameters.u.ofdm.code_rate_LP == FEC_NONE)
+				fe->parameters.u.ofdm.code_rate_LP = FEC_AUTO;
+		}
+
+		// get frontend-specific tuning settings
+		if (dvb_frontend_internal_ioctl(&fe->frontend, FE_GET_TUNE_SETTINGS, &fetunesettings) == 0) {
+			fe->min_delay = (fetunesettings.min_delay_ms * HZ) / 1000;
+			fe->max_drift = fetunesettings.max_drift;
+			fe->step_size = fetunesettings.step_size;
+		} else {
+			// default values
+			switch(fe->info->type) {
+			case FE_QPSK:
+				fe->min_delay = HZ/20; // default mindelay of 50ms
+				fe->step_size = fe->parameters.u.qpsk.symbol_rate / 16000;
+				fe->max_drift = fe->parameters.u.qpsk.symbol_rate / 2000;
+				break;
+			    
+			case FE_QAM:
+				fe->min_delay = HZ/20; // default mindelay of 50ms
+				fe->step_size = 0;
+				fe->max_drift = 0; // don't want any zigzagging under DVB-C frontends
+				break;
+			    
+			case FE_OFDM:
+				fe->min_delay = HZ/20; // default mindelay of 50ms
+				fe->step_size = fe->info->frequency_stepsize * 2;
+				fe->max_drift = (fe->info->frequency_stepsize * 2) + 1;
+				break;
+			}
+		}
+		if (dvb_override_tune_delay > 0) {
+		       fe->min_delay = (dvb_override_tune_delay * HZ) / 1000;
+		}
+
+		dvb_frontend_add_event (fe, 0);	    
 		break;
+
 	case FE_GET_EVENT:
 		err = dvb_frontend_get_event (fe, parg, file->f_flags);
 		break;
+	    
 	case FE_GET_FRONTEND:
 		memcpy (parg, &fe->parameters,
 			sizeof (struct dvb_frontend_parameters));
 		/*  fall-through... */
 	default:
-		dvb_frontend_internal_ioctl (&fe->frontend, cmd, parg);
+		err = dvb_frontend_internal_ioctl (&fe->frontend, cmd, parg);
 	};
-
+    
 	up (&fe->sem);
+	if (err < 0)
+		return err;
+
+	// Force the CAN_INVERSION_AUTO bit on. If the frontend doesn't do it, it is done for it.
+	if ((cmd == FE_GET_INFO) && (err == 0)) {
+		struct dvb_frontend_info* tmp = (struct dvb_frontend_info*) parg;
+		tmp->caps |= FE_CAN_INVERSION_AUTO;
+	}
+
+	// if the frontend has just been set, wait until the first tune has finished.
+	// This ensures the app doesn't start reading data too quickly, perhaps from the
+	// previous lock, which is REALLY CONFUSING TO DEBUG!
+	if ((cmd == FE_SET_FRONTEND) && (err == 0)) {
+		dvb_frontend_wakeup(fe);
+		err = wait_event_interruptible(fe->wait_queue, fe->state & ~FESTATE_RETUNE);
+	}
 
 	return err;
 }
@@ -680,14 +892,14 @@
 
 int
 dvb_add_frontend_ioctls (struct dvb_adapter *adapter,
-                         int (*before_ioctl) (struct dvb_frontend *frontend,
-                                              unsigned int cmd, void *arg),
-                         int (*after_ioctl)  (struct dvb_frontend *frontend,
-                                              unsigned int cmd, void *arg),
+			 int (*before_ioctl) (struct dvb_frontend *frontend,
+					      unsigned int cmd, void *arg),
+			 int (*after_ioctl)  (struct dvb_frontend *frontend,
+					      unsigned int cmd, void *arg),
 			 void *before_after_data)
 {
 	struct dvb_frontend_ioctl_data *ioctl;
-        struct list_head *entry;
+	struct list_head *entry;
 
 	dprintk ("%s\n", __FUNCTION__);
 
@@ -732,9 +944,9 @@
 void
 dvb_remove_frontend_ioctls (struct dvb_adapter *adapter,
 			    int (*before_ioctl) (struct dvb_frontend *frontend,
-                                                 unsigned int cmd, void *arg),
-                            int (*after_ioctl)  (struct dvb_frontend *frontend,
-                                                 unsigned int cmd, void *arg))
+						 unsigned int cmd, void *arg),
+			    int (*after_ioctl)	(struct dvb_frontend *frontend,
+						 unsigned int cmd, void *arg))
 {
 	struct list_head *entry, *n;
 
@@ -914,6 +1126,7 @@
 	fe->frontend.i2c = i2c;
 	fe->frontend.data = data;
 	fe->info = info;
+	fe->inversion = INVERSION_OFF;
 
 	list_for_each (entry, &frontend_ioctl_list) {
 		struct dvb_frontend_ioctl_data *ioctl;
@@ -953,6 +1166,9 @@
 	dvb_register_device (i2c->adapter, &fe->dvbdev, &dvbdev_template,
 			     fe, DVB_DEVICE_FRONTEND);
 
+	if ((info->caps & FE_NEEDS_BENDING) || (dvb_override_frequency_bending == 2))
+		do_frequency_bending = 1;
+    
 	up (&frontend_mutex);
 
 	return 0;
@@ -963,7 +1179,7 @@
 					   unsigned int cmd, void *arg),
 			     struct dvb_i2c_bus *i2c)
 {
-        struct list_head *entry, *n;
+	struct list_head *entry, *n;
 
 	dprintk ("%s\n", __FUNCTION__);
 
@@ -990,5 +1206,12 @@
 
 MODULE_PARM(dvb_frontend_debug,"i");
 MODULE_PARM(dvb_shutdown_timeout,"i");
+MODULE_PARM(dvb_override_frequency_bending,"i");
+MODULE_PARM(dvb_force_auto_inversion,"i");
+MODULE_PARM(dvb_override_tune_delay,"i");
+
 MODULE_PARM_DESC(dvb_frontend_debug, "enable verbose debug messages");
 MODULE_PARM_DESC(dvb_shutdown_timeout, "wait <shutdown_timeout> seconds after close() before suspending hardware");
+MODULE_PARM_DESC(dvb_override_frequency_bending, "0: normal (default), 1: never use frequency bending, 2: always use frequency bending");
+MODULE_PARM_DESC(dvb_force_auto_inversion, "0: normal (default), 1: INVERSION_AUTO forced always");
+MODULE_PARM_DESC(dvb_override_tune_delay, "0: normal (default), >0 => delay in milliseconds to wait for lock after a tune attempt");
Index: dvb/drivers/media/dvb/dvb-core/dvb_frontend.h
===================================================================
RCS file: /cvs/tuxbox/driver/dvb/drivers/media/dvb/dvb-core/dvb_frontend.h,v
retrieving revision 1.5
diff -u -r1.5 dvb_frontend.h
--- a/dvb/drivers/media/dvb/dvb-core/dvb_frontend.h	11 Sep 2003 22:43:08 -0000	1.5
+++ b/dvb/drivers/media/dvb/dvb-core/dvb_frontend.h	25 Sep 2007 08:58:14 -0000
@@ -56,14 +56,26 @@
 	void *data;                /*  can be used by hardware module... */
 };
 
+struct dvb_frontend_tune_settings {
+        int min_delay_ms;
+        int step_size;
+        int max_drift;
+        struct dvb_frontend_parameters parameters;
+};
+
 
 /**
  *   private frontend command ioctl's.
  *   keep them in sync with the public ones defined in linux/dvb/frontend.h
+ * 
+ *   FE_SLEEP. Ioctl used to put frontend into a low power mode.
+ *   FE_INIT. Ioctl used to initialise the frontend.
+ *   FE_GET_TUNE_SETTINGS. Get the frontend-specific tuning loop settings for the supplied set of parameters.
  */
 #define FE_SLEEP              _IO('v', 80)
 #define FE_INIT               _IO('v', 81)
-#define FE_RESET              _IO('v', 82)
+#define FE_GET_TUNE_SETTINGS  _IOWR('v', 83, struct dvb_frontend_tune_settings)
+#define FE_RESET              _IO('v', 82) //für den übergang
 
 
 extern int
Index: dvb/drivers/media/dvb/frontends/at76c651.c
===================================================================
RCS file: /cvs/tuxbox/driver/dvb/drivers/media/dvb/frontends/at76c651.c,v
retrieving revision 1.58
diff -u -r1.58 at76c651.c
--- a/dvb/drivers/media/dvb/frontends/at76c651.c	13 Mar 2006 20:04:08 -0000	1.58
+++ b/dvb/drivers/media/dvb/frontends/at76c651.c	25 Sep 2007 08:58:15 -0000
@@ -74,7 +74,7 @@
 	    FE_CAN_FEC_7_8 | FE_CAN_FEC_8_9 | FE_CAN_FEC_AUTO |
 	    FE_CAN_QAM_16 | FE_CAN_QAM_32 | FE_CAN_QAM_64 | FE_CAN_QAM_128 |
 	    FE_CAN_QAM_256 /* | FE_CAN_QAM_512 | FE_CAN_QAM_1024 */ |
-	    FE_CAN_RECOVER | FE_CAN_CLEAN_SETUP | FE_CAN_MUTE_TS
+	    FE_CAN_RECOVER | FE_NEEDS_BENDING | FE_CAN_MUTE_TS
 };
 
 #if ! defined(__powerpc__)
Index: dvb/drivers/media/dvb/frontends/tda80xx.c
===================================================================
RCS file: /cvs/tuxbox/driver/dvb/drivers/media/dvb/frontends/tda80xx.c,v
retrieving revision 1.3
diff -u -r1.3 tda80xx.c
--- a/dvb/drivers/media/dvb/frontends/tda80xx.c	2 Mar 2006 14:00:26 -0000	1.3
+++ b/dvb/drivers/media/dvb/frontends/tda80xx.c	25 Sep 2007 08:58:15 -0000
@@ -96,7 +96,7 @@
 		FE_CAN_FEC_4_5 | FE_CAN_FEC_5_6 | FE_CAN_FEC_6_7 |
 		FE_CAN_FEC_7_8 | FE_CAN_FEC_8_9 | FE_CAN_FEC_AUTO |
 		FE_CAN_QPSK |
-		FE_CAN_MUTE_TS | FE_CAN_CLEAN_SETUP
+		FE_CAN_MUTE_TS | FE_NEEDS_BENDING
 };
 
 static u8 tda8044_inittab[] = {
Index: dvb/drivers/media/dvb/frontends/ves1820.c
===================================================================
RCS file: /cvs/tuxbox/driver/dvb/drivers/media/dvb/frontends/ves1820.c,v
retrieving revision 1.54
diff -u -r1.54 ves1820.c
--- a/dvb/drivers/media/dvb/frontends/ves1820.c	31 Jul 2007 09:35:17 -0000	1.54
+++ b/dvb/drivers/media/dvb/frontends/ves1820.c	25 Sep 2007 08:58:15 -0000
@@ -112,7 +112,7 @@
 	.caps = FE_CAN_QAM_16 | FE_CAN_QAM_32 | FE_CAN_QAM_64 |
 		FE_CAN_QAM_128 | FE_CAN_QAM_256 |
 		FE_CAN_FEC_AUTO | FE_CAN_INVERSION_AUTO |
-		FE_CAN_CLEAN_SETUP
+		FE_NEEDS_BENDING
 };
 
 
Index: dvb/include/linux/dvb/frontend.h
===================================================================
RCS file: /cvs/tuxbox/driver/dvb/include/linux/dvb/frontend.h,v
retrieving revision 1.7
diff -u -r1.7 frontend.h
--- a/dvb/include/linux/dvb/frontend.h	11 Sep 2003 18:20:51 -0000	1.7
+++ b/dvb/include/linux/dvb/frontend.h	25 Sep 2007 08:58:15 -0000
@@ -59,9 +59,9 @@
 	FE_CAN_BANDWIDTH_AUTO         = 0x40000,
 	FE_CAN_GUARD_INTERVAL_AUTO    = 0x80000,
 	FE_CAN_HIERARCHY_AUTO         = 0x100000,
-	FE_CAN_RECOVER                = 0x20000000,
-	FE_CAN_CLEAN_SETUP            = 0x40000000,
-	FE_CAN_MUTE_TS                = 0x80000000
+	FE_NEEDS_BENDING              = 0x20000000, // frontend requires frequency bending
+	FE_CAN_RECOVER                = 0x40000000, // frontend can recover from a cable unplug automatically
+	FE_CAN_MUTE_TS                = 0x80000000  // frontend can stop spurious TS data output
 } fe_caps_t;
 
 
Download
Joggermoon
Interessierter
Interessierter
Beiträge: 29
Registriert: Mittwoch 27. Dezember 2006, 02:22

Beitrag von Joggermoon »

Sieht nach dem Legatum von Audio aus, rennt soweit ganz gut auf der Nokia.
PT-1
Moderator english
Beiträge: 2458
Registriert: Donnerstag 20. Dezember 2001, 00:00

Beitrag von PT-1 »

Joggermoon hat geschrieben:Sieht nach dem Legatum von Audio aus, rennt soweit ganz gut auf der Nokia.
:gruebel:
Z80
Erleuchteter
Erleuchteter
Beiträge: 710
Registriert: Dienstag 3. September 2002, 12:54

Beitrag von Z80 »

Legatum - Vermächtnis, Erbe ?
Audio == Audioslayer ?
Nico 77
Semiprofi
Semiprofi
Beiträge: 1383
Registriert: Freitag 18. April 2003, 15:12

Beitrag von Nico 77 »

Ich habe das ganze jetzt mal eine ganze Zeit lang laufen lassen.

Ausgegangen ist das ganze von einem LNB eines bekannten welches die neuen Frequenzen von Pro7 Sat1 & Co nicht tuned.

Nokia:
Vorteil des patches ist das die Sender der Sat1, Pro7 Grupper auf dem neuen Transponder einwandfrei getuned werden.
Nachteil, die Boxen hängen sich nun schonmal fest welche sie ohne den patch defintiv nicht tuhen.

Sagem 1xintel:
Bringt auch ohne den frontend Patch die Pro7 Sat1 Sender und tuned immer stabil und zuverlässig.
Der test mit Patch bringt auf Sendern wie Taquilla manchmal ein Tunefiasko mit sich, manchmal werden die Sender getuned manchmal nicht. Wenn diese Sender nicht mehr getuned werden dauert es ewig bis die Zapit reagiert. Manchmal läuft dann ganrichts mehr, die Box bleibt nicht hängen es laufen auch noch alle Prozesse aber bei Umschalten bleibt der Sender im Display welcher als letztes nicht getuned werden konnte. Die Box tuned in dem Zustand dann keine Sender mehr, außer man killt die zapit und startet diese neu. Dann läuft alles wie gewohnt bis das nächste mal hängt. Fals die Frage aufkommt, nein es kam zu keinem demux Absturz, lediglich ein Hängebleiben der zapit.

Sagem 2xamd: Braucht den Frontendpatch um die Sat1, Pro7 Gruppe tunen zu können. Sonst gleiches verhalten wie bei Sagem 1xintel, nur das der Empfang insgesamt schlechter ist.

Philips:
Auch hier selbes Ergebnis wie Sagem, bringt auch ohne den frontend Patch die Pro7 Sat1 Sender und tuned immer stabil und zuverlässig.
Mit Patch hängt sich die Box manchmal einfach weg und Philips macht als einzige Problem bei der Kanalsuche. Diese bleibt ab und zu wie ich vor Jahren schon geschrieben habe immernoch hängen. Ohne Frontendpatch treten die Fehler nicht auf!

Abschluss:
Fals jetzt jemand der Testzeitraum etwas kurz vorkommt, der Source des frontend ist bekannt und liegt seit Jahren hier bzw auf linuxtv.org. Ich habe also bevor der Patch hier gepostet wurde nur den frontend Patch benutzt und nun den kompletten Patch von hier welcher die gleichen Probleme beinhaltet. Es funktioniert also nach wie vor alleine der neue frontend Patch nicht korrekt. Die ganze Sache ist also so nicht vollends brauchbar. Um Fehler meinerseits auszuschliessen habe ich mal diverse Images vom anderen Ufer *g angeschaut, diese bringen wenn sie den Patch enhalten die gleichen Fehler und Probleme.

Ps: Vielleicht sollten die Wissenden hier sich das Tuningverhalten der Zapit mal näher anschauen, Enigma tuned die Sat1, Pro7 Gruppe auch frontend Patch.

Hat vielleicht mal jemand die Lust ein komplettes 2.6er Kernel Image zu bauen? Dort sind die zumindest die Frontendsachen ja auch integriert, mich würde mal interessieren ob da die selber Probleme auftreten.
Zuletzt geändert von Nico 77 am Sonntag 30. September 2007, 21:51, insgesamt 1-mal geändert.
bellum
bbs-Maintainer
Beiträge: 282
Registriert: Montag 23. Oktober 2006, 22:13

Beitrag von bellum »

Rebel1 hat geschrieben:Gegen das CVS gedifft: :D
Download
Hallo zusammen,

habe vor kurzem auch Images mit diesem diff auf meiner Kabel Sagem und Nokia im Einsatz. Für konkrete Aussagen ist mir der Testzeitraum noch zu kurz, aber es sieht soweit ganz gut aus...

Melde mich wieder...
Gruß bellum
bellum
bbs-Maintainer
Beiträge: 282
Registriert: Montag 23. Oktober 2006, 22:13

Beitrag von bellum »

bellum hat geschrieben: Hallo zusammen,

habe vor kurzem auch Images mit diesem diff auf meiner Kabel Sagem und Nokia im Einsatz. Für konkrete Aussagen ist mir der Testzeitraum noch zu kurz, aber es sieht soweit ganz gut aus...

Melde mich wieder...
Gruß bellum
Hier nun die Ergebnisse meines Tests
Sagem:
+ Die Umschaltzeiten sind fühlbar kürzer
- Dem Movieplayer bekommt das diff nicht, d.h. reagiert träger beim "Spulen", Bild/Ton sind nach dem Spulen öfters nicht synchron.
Nokia:
+ Bei ausgeschaltetem SPTS-Mode kein Schwarzbild-Bug mehr
+ Kein SPTS-Mode, keine Geräusche beim Umschalten
+ Umschaltzeiten gut
- Dem Movieplayer bekommt das diff noch schlechter als der Sagem, zusätzlich bleibt das Bild nach einer Pause stehen und nur der Ton läuft weiter.

Aufgrund der Movieplayer-Problematik, habe ich den diff wieder entfernt...

Gruß bellum
Striper
Erleuchteter
Erleuchteter
Beiträge: 625
Registriert: Samstag 8. September 2007, 16:17

Beitrag von Striper »

Das Problem mit dem Movieplayer dürfte am ersten Teil des Patches liegen. Das ist nämlich der AVIA500 SPTS Fix.

Code: Alles auswählen

Index: dvb/drivers/media/dvb/avia/avia_av_core.c
===================================================================
RCS file: /cvs/tuxbox/driver/dvb/drivers/media/dvb/avia/avia_av_core.c,v
retrieving revision 1.99
diff -u -r1.99 avia_av_core.c
--- a/dvb/drivers/media/dvb/avia/avia_av_core.c   8 Jan 2006 21:36:22 -0000   1.99
+++ b/dvb/drivers/media/dvb/avia/avia_av_core.c   25 Sep 2007 08:58:12 -0000
@@ -1225,10 +1225,15 @@
 //      avia_av_cmd(NewChannel, 0x00, 0xFFFF, 0xFFFF);
       avia_av_cmd(SelectStream, 0x03 - bypass_mode, pid_audio);
 //      avia_av_cmd(SelectStream, 0x00, pid_video);
+
       if (aviarev && bypass_mode_changed) {
          avia_av_cmd(SelectStream, 0x00, (play_state_video == AVIA_AV_PLAY_STATE_PLAYING) ? pid_video : 0xFFFF);
          avia_av_cmd(Play, 0x00, (play_state_video == AVIA_AV_PLAY_STATE_PLAYING) ? pid_video : 0xFFFF, pid_audio);
       }
+
+      if ((aviarev) && (play_state_audio != AVIA_AV_PLAY_STATE_PAUSED)) // oder nur  if (aviarev)
+         avia_av_cmd(Play, 0x00, (play_state_video == AVIA_AV_PLAY_STATE_PLAYING) ? pid_video : 0xFFFF, pid_audio);
+
       bypass_mode_changed = 0;
       break;
 
@@ -1239,9 +1244,18 @@
 
       dprintk("avia_av: stopping audio decoder\n");
 
+
       if (play_state_video == AVIA_AV_PLAY_STATE_STOPPED) {
+
+         if (aviarev) {
+            avia_av_cmd(SelectStream, 0x03 - bypass_mode, 0xFFFF); // ???
+            avia_av_cmd(Abort, 0x00);
+         }
+
          avia_av_dram_write(AV_SYNC_MODE, AVIA_AV_SYNC_MODE_NONE);
-         avia_av_cmd(NewChannel, 0x00, 0xFFFF, 0xFFFF);
+
+         if (!aviarev)
+            avia_av_cmd(NewChannel, 0x00, 0xFFFF, 0xFFFF);
       }
       else {
          avia_av_cmd(SelectStream, 0x03 - bypass_mode, 0xFFFF);
@@ -1276,6 +1290,9 @@
 //         avia_av_cmd(NewChannel, 0x00, 0xFFFF, 0xFFFF);
 //         avia_av_cmd(SelectStream, 0x03 - bypass_mode, pid_audio);
          avia_av_cmd(SelectStream, 0x00, pid_video);
+
+//         if (aviarev)
+//            avia_av_cmd(Play, 0x00, pid_video, (play_state_audio == AVIA_AV_PLAY_STATE_PLAYING) ? pid_audio : 0xFFFF);
       }
       break;
 
@@ -1287,8 +1304,16 @@
       dprintk("avia_av: stopping video decoder\n");
 
       if (play_state_audio == AVIA_AV_PLAY_STATE_STOPPED) {
+
+         if (aviarev) {
+            avia_av_cmd(SelectStream, 0x00, 0xFFFF); // ???
+            avia_av_cmd(Abort, 0x00);
+         }
+
          avia_av_dram_write(AV_SYNC_MODE, AVIA_AV_SYNC_MODE_NONE);
-         avia_av_cmd(NewChannel, 0x00, 0xFFFF, 0xFFFF);
+
+         if (!aviarev)
+            avia_av_cmd(NewChannel, 0x00, 0xFFFF, 0xFFFF);
       }
       else {
          avia_av_cmd(SelectStream, 0x00, 0xFFFF);
@@ -1558,3 +1583,4 @@
 MODULE_PARM_DESC(tv_standard, "0: PAL, 1: NTSC");
 MODULE_PARM_DESC(no_watchdog, "0: wd enabled, 1: wd disabled");
 MODULE_PARM_DESC(firmware, "path to microcode");
+