On Saturday 28 Aug 2004 03:35, Andrew de Quincey wrote:
> Please try this new patch - I get audio again here! I've also added in code
> to output the status of the encoder if something goes wrong in future.
>
> I still have to reload the module twice to get anything though... dunno
> what thats all about. I don't even get anything on /dev/video0 (apart from
> I/O errors).

Hi, this later patch now corrects problems when un/replugging the A/V feeds. I 
found that it would frequently lose audio sync, or acquire strange buzzing 
noises. Oh, and my test decoder program (kaffeine, based on xine) tended to 
lock up when the video went missing as well - so the encoder must have been 
outputting rubbish.

It's really annoying: the SAA6752hs encoder chip has all these funky commands 
like "START", "STOP", "PAUSE" etc - problem is they don't work properly! 

To fix that, if you unplug the video it will now hard reset the encoder. When 
you plug it back, it will reconfigure and restart it with the last settings 
used. It means you won't get any data at all if the video signal is missing, 
but theres no other way to be 100% reliable with this chip.
--- linux-2.6.8.1.orig//drivers/media/video/saa7134/saa6752hs.c	Sat Aug 14 11:56:23 2004
+++ linux-2.6.8.1//drivers/media/video/saa7134/saa6752hs.c	Sat Aug 28 06:48:40 2004
@@ -11,6 +11,7 @@
 #include <linux/types.h>
 #include <linux/videodev.h>
 #include <linux/init.h>
+#include <linux/crc32.h>
 
 #include <media/id.h>
 #include <media/saa6752hs.h>
@@ -36,77 +37,82 @@
     	SAA6752HS_COMMAND_RECONFIGURE = 4,
     	SAA6752HS_COMMAND_SLEEP = 5,
 	SAA6752HS_COMMAND_RECONFIGURE_FORCE = 6,
-    
+
 	SAA6752HS_COMMAND_MAX
 };
 
-
 /* ---------------------------------------------------------------------- */
 
 static u8 PAT[] = {
 	0xc2, // i2c register
 	0x00, // table number for encoder
-  
+
 	0x47, // sync
 	0x40, 0x00, // transport_error_indicator(0), payload_unit_start(1), transport_priority(0), pid(0)
 	0x10, // transport_scrambling_control(00), adaptation_field_control(01), continuity_counter(0)
-     
+
 	0x00, // PSI pointer to start of table
-    
+
 	0x00, // tid(0)
 	0xb0, 0x0d, // section_syntax_indicator(1), section_length(13)
-    
+
 	0x00, 0x01, // transport_stream_id(1)
-    
+
 	0xc1, // version_number(0), current_next_indicator(1)
-    
+
 	0x00, 0x00, // section_number(0), last_section_number(0)
 
 	0x00, 0x01, // program_number(1)
-	
-	0xe0, 0x10, // PMT PID(0x10)
 
-	0x76, 0xf1, 0x44, 0xd1 // CRC32
+	0xe0, 0x00, // PMT PID
+
+	0x00, 0x00, 0x00, 0x00 // CRC32
 };
 
 static u8 PMT[] = {
 	0xc2, // i2c register
 	0x01, // table number for encoder
-  
+
 	0x47, // sync
-	0x40, 0x10, // transport_error_indicator(0), payload_unit_start(1), transport_priority(0), pid(0x10)
+	0x40, 0x00, // transport_error_indicator(0), payload_unit_start(1), transport_priority(0), pid
 	0x10, // transport_scrambling_control(00), adaptation_field_control(01), continuity_counter(0)
-     
+
 	0x00, // PSI pointer to start of table
-    
+
 	0x02, // tid(2)
 	0xb0, 0x17, // section_syntax_indicator(1), section_length(23)
 
 	0x00, 0x01, // program_number(1)
-    
+
 	0xc1, // version_number(0), current_next_indicator(1)
-    
+
 	0x00, 0x00, // section_number(0), last_section_number(0)
-    
-	0xe1, 0x04, // PCR_PID (0x104)
-   
+
+	0xe0, 0x00, // PCR_PID
+
 	0xf0, 0x00, // program_info_length(0)
-    
-	0x02, 0xe1, 0x00, 0xf0, 0x00, // video stream type(2), pid(0x100)
-	0x04, 0xe1, 0x03, 0xf0, 0x00, // audio stream type(4), pid(0x103)
-    
-	0xa1, 0xca, 0x0f, 0x82 // CRC32
+
+	0x02, 0xe0, 0x00, 0xf0, 0x00, // video stream type(2), pid
+	0x04, 0xe0, 0x00, 0xf0, 0x00, // audio stream type(4), pid
+
+	0x00, 0x00, 0x00, 0x00 // CRC32
 };
 
 static struct mpeg_params mpeg_params_template =
 {
-	.bitrate_mode = MPEG_BITRATE_MODE_CBR,
-	.video_target_bitrate = 5000,
+	.video_bitrate_mode = MPEG_VIDEO_BITRATE_MODE_VBR,
+	.video_target_bitrate = 4000,
+	.video_max_bitrate = 6000,
 	.audio_bitrate = MPEG_AUDIO_BITRATE_256,
-	.total_bitrate = 6000,
+	.total_bitrate = 7000,
+	.pmt_pid = 16,
+	.video_pid = 260,
+	.audio_pid = 256,
+	.pcr_pid = 259,
+	.video_format = MPEG_VIDEO_FORMAT_D1,
 };
 
-  
+
 /* ---------------------------------------------------------------------- */
 
 
@@ -122,11 +128,11 @@
   	case SAA6752HS_COMMAND_RESET:
   		buf[0] = 0x00;
 		break;
-	  
+
 	case SAA6752HS_COMMAND_STOP:
-		  	buf[0] = 0x03;
+	  	buf[0] = 0x03;
 		break;
-	  
+
 	case SAA6752HS_COMMAND_START:
   		buf[0] = 0x02;
 		break;
@@ -134,11 +140,11 @@
 	case SAA6752HS_COMMAND_PAUSE:
   		buf[0] = 0x04;
 		break;
-	  
+
 	case SAA6752HS_COMMAND_RECONFIGURE:
 		buf[0] = 0x05;
 		break;
-	  
+
   	case SAA6752HS_COMMAND_SLEEP:
   		buf[0] = 0x06;
 		break;
@@ -146,11 +152,11 @@
   	case SAA6752HS_COMMAND_RECONFIGURE_FORCE:
 		buf[0] = 0x07;
 		break;
-	
+
 	default:
-		return -EINVAL;  
+		return -EINVAL;
 	}
-	
+
   	// set it and wait for it to be so
 	i2c_master_send(client, buf, 1);
 	timeout = jiffies + HZ * 3;
@@ -166,7 +172,7 @@
 			status = -ETIMEDOUT;
 			break;
 		}
-	
+
 		// wait a bit
 		set_current_state(TASK_INTERRUPTIBLE);
 		schedule_timeout(HZ/100);
@@ -175,7 +181,7 @@
 	// delay a bit to let encoder settle
 	set_current_state(TASK_INTERRUPTIBLE);
 	schedule_timeout(HZ/20);
-	
+
 	// done
   	return status;
 }
@@ -185,14 +191,14 @@
 				 struct mpeg_params* params)
 {
   	u8 buf[3];
-  
+
 	// set the bitrate mode
 	buf[0] = 0x71;
-	buf[1] = params->bitrate_mode;
+	buf[1] = params->video_bitrate_mode;
 	i2c_master_send(client, buf, 2);
-	  
+
 	// set the video bitrate
-	if (params->bitrate_mode == MPEG_BITRATE_MODE_VBR) {
+	if (params->video_bitrate_mode == MPEG_VIDEO_BITRATE_MODE_VBR) {
 		// set the target bitrate
 		buf[0] = 0x80;
 	    	buf[1] = params->video_target_bitrate >> 8;
@@ -211,100 +217,184 @@
 	  	buf[2] = params->video_target_bitrate & 0xff;
 		i2c_master_send(client, buf, 3);
 	}
-	  
+
 	// set the audio bitrate
  	buf[0] = 0x94;
   	buf[1] = params->audio_bitrate;
 	i2c_master_send(client, buf, 2);
-	
+
 	// set the total bitrate
 	buf[0] = 0xb1;
   	buf[1] = params->total_bitrate >> 8;
   	buf[2] = params->total_bitrate & 0xff;
 	i2c_master_send(client, buf, 3);
-  
+
 	return 0;
 }
 
 
 static int saa6752hs_init(struct i2c_client* client, struct mpeg_params* params)
-{  
+{
 	unsigned char buf[3];
-	void *data;
+   	struct mpeg_params* cachedParams;
+	u32 crc;
+	unsigned char localPAT[256];
+	unsigned char localPMT[256];
+   
+	// grab the previous set of parameters
+ 	cachedParams = (struct mpeg_params*) i2c_get_clientdata(client);
 
 	// check the bitrate parameters first
 	if (params != NULL) {
-		if (params->bitrate_mode >= MPEG_BITRATE_MODE_MAX)
+		unsigned int pmt_pid = 0, pcr_pid = 0, video_pid = 0 , audio_pid = 0;
+
+	   	// check supplied params are valid
+		if (params->video_format >= MPEG_VIDEO_FORMAT_MAX)
 			return -EINVAL;
-		if (params->video_target_bitrate >= MPEG_VIDEO_TARGET_BITRATE_MAX)
+		if (params->video_bitrate_mode >= MPEG_VIDEO_BITRATE_MODE_MAX)
 			return -EINVAL;
-  		if (params->video_max_bitrate >= MPEG_VIDEO_MAX_BITRATE_MAX)
+		if (params->video_target_bitrate >= MPEG_VIDEO_TARGET_BITRATE_MAX)
 			return -EINVAL;
 		if (params->audio_bitrate >= MPEG_AUDIO_BITRATE_MAX)
 			return -EINVAL;
 		if (params->total_bitrate >= MPEG_TOTAL_BITRATE_MAX)
         		return -EINVAL;
-		if (params->bitrate_mode         == MPEG_BITRATE_MODE_MAX &&
-		    params->video_target_bitrate <= params->video_max_bitrate)
-			return -EINVAL; 
+		if (params->video_bitrate_mode == MPEG_VIDEO_BITRATE_MODE_VBR) {
+			if (params->video_max_bitrate >= MPEG_VIDEO_MAX_BITRATE_MAX)
+				return -EINVAL;
+			if (params->video_target_bitrate >= params->video_max_bitrate)
+				return -EINVAL;
+		}
+		if (params->pmt_pid != 0) {
+			if (params->pmt_pid > MPEG_PID_MAX)
+				return -EINVAL;
+		   	pmt_pid = params->pmt_pid;
+		} else {
+			pmt_pid = cachedParams->pmt_pid;
+		}
+		if (params->pcr_pid != 0) {
+		   	if (params->pcr_pid > MPEG_PID_MAX)
+				return -EINVAL;
+		   	pcr_pid = params->pcr_pid;
+		} else {
+			pcr_pid = cachedParams->pcr_pid;
+		}
+   		if (params->video_pid != 0) {
+		   	if (params->video_pid > MPEG_PID_MAX)
+				return -EINVAL;
+		   	video_pid = params->video_pid;
+		} else {
+			video_pid = cachedParams->video_pid;
+		}
+   		if (params->audio_pid != 0) {
+		   	if (params->audio_pid > MPEG_PID_MAX)
+				return -EINVAL;
+		   	audio_pid = params->audio_pid;
+		} else {
+			audio_pid = cachedParams->audio_pid;
+		}
+
+	   	// update cache
+   		memcpy(cachedParams, params, sizeof(struct mpeg_params));
+	   	cachedParams->pmt_pid = pmt_pid;
+   	   	cachedParams->pcr_pid = pcr_pid;
+   	   	cachedParams->video_pid = video_pid;
+   	   	cachedParams->audio_pid = audio_pid;
 	}
-  
-    	// Set GOP structure {3, 13}
+
+        // set bitrate
+        saa6752hs_set_bitrate(client, cachedParams);
+
+	// Set GOP structure {3, 13}
 	buf[0] = 0x72;
 	buf[1] = 0x03;
 	buf[2] = 0x0D;
 	i2c_master_send(client,buf,3);
-  
+
     	// Set minimum Q-scale {4}
 	buf[0] = 0x82;
 	buf[1] = 0x04;
 	i2c_master_send(client,buf,2);
-  
+
     	// Set maximum Q-scale {12}
 	buf[0] = 0x83;
 	buf[1] = 0x0C;
 	i2c_master_send(client,buf,2);
-  
+
     	// Set Output Protocol
 	buf[0] = 0xD0;
 	buf[1] = 0x01;
 	i2c_master_send(client,buf,2);
-  
+
     	// Set video output stream format {TS}
 	buf[0] = 0xB0;
 	buf[1] = 0x05;
 	i2c_master_send(client,buf,2);
-  
-    	// Set Audio PID {0x103}
+
+	/* compute PAT */
+	memcpy(localPAT, PAT, sizeof(PAT));
+	localPAT[17] = 0xe0 | ((cachedParams->pmt_pid >> 8) & 0x0f);
+	localPAT[18] = cachedParams->pmt_pid & 0xff;
+	crc = crc32_be(~0, &localPAT[7], sizeof(PAT) - 7 - 4);
+	localPAT[sizeof(PAT) - 4] = (crc >> 24) & 0xFF;
+	localPAT[sizeof(PAT) - 3] = (crc >> 16) & 0xFF;
+	localPAT[sizeof(PAT) - 2] = (crc >> 8) & 0xFF;
+	localPAT[sizeof(PAT) - 1] = crc & 0xFF;
+
+	/* compute PMT */
+      	memcpy(localPMT, PMT, sizeof(PMT));
+   	localPMT[3] = 0x40 | ((cachedParams->pmt_pid >> 8) & 0x0f);
+   	localPMT[4] = cachedParams->pmt_pid & 0xff;
+	localPMT[15] = 0xE0 | ((cachedParams->pcr_pid >> 8) & 0x0F);
+	localPMT[16] = cachedParams->pcr_pid & 0xFF;
+	localPMT[20] = 0xE0 | ((cachedParams->video_pid >> 8) & 0x0F);
+	localPMT[21] = cachedParams->video_pid & 0xFF;
+	localPMT[25] = 0xE0 | ((cachedParams->audio_pid >> 8) & 0x0F);
+	localPMT[26] = cachedParams->audio_pid & 0xFF;
+	crc = crc32_be(~0, &localPMT[7], sizeof(PMT) - 7 - 4);
+	localPMT[sizeof(PMT) - 4] = (crc >> 24) & 0xFF;
+	localPMT[sizeof(PMT) - 3] = (crc >> 16) & 0xFF;
+	localPMT[sizeof(PMT) - 2] = (crc >> 8) & 0xFF;
+	localPMT[sizeof(PMT) - 1] = crc & 0xFF;
+
+    	// Set Audio PID
 	buf[0] = 0xC1;
-	buf[1] = 0x01;
-	buf[2] = 0x03;
+	buf[1] = (cachedParams->audio_pid >> 8) & 0xFF;
+	buf[2] = cachedParams->audio_pid & 0xFF;
 	i2c_master_send(client,buf,3);
-  
-        // setup bitrate settings
-	data = i2c_get_clientdata(client);
-	if (params) {
-		saa6752hs_set_bitrate(client, params);
-		memcpy(data, params, sizeof(struct mpeg_params));
-	} else {
-		// parameters were not supplied. use the previous set
-   		saa6752hs_set_bitrate(client, (struct mpeg_params*) data);
-	}
-	  
+
+	// Set Video PID
+	buf[0] = 0xC0;
+	buf[1] = (cachedParams->video_pid >> 8) & 0xFF;
+	buf[2] = cachedParams->video_pid & 0xFF;
+	i2c_master_send(client,buf,3);
+
+ 	// Set PCR PID
+	buf[0] = 0xC4;
+	buf[1] = (cachedParams->pcr_pid >> 8) & 0xFF;
+	buf[2] = cachedParams->pcr_pid & 0xFF;
+	i2c_master_send(client,buf,3);
+
 	// Send SI tables
-  	i2c_master_send(client,PAT,sizeof(PAT));
-  	i2c_master_send(client,PMT,sizeof(PMT));
-	  
+	i2c_master_send(client,localPAT,sizeof(PAT));
+	i2c_master_send(client,localPMT,sizeof(PMT));
+
 	// mute then unmute audio. This removes buzzing artefacts
 	buf[0] = 0xa4;
 	buf[1] = 1;
 	i2c_master_send(client, buf, 2);
   	buf[1] = 0;
 	i2c_master_send(client, buf, 2);
-	  
+
+	// Set video format
+	buf[0] = 0x41;
+	buf[1] = cachedParams->video_format;
+	i2c_master_send(client, buf, 2);
+
 	// start it going
 	saa6752hs_chip_command(client, SAA6752HS_COMMAND_START);
 
+   	// return success
 	return 0;
 }
 
@@ -322,14 +412,14 @@
                 return -ENOMEM;
         memcpy(client,&client_template,sizeof(struct i2c_client));
 	strlcpy(client->name, "saa6752hs", sizeof(client->name));
-   
+
 	if (NULL == (params = kmalloc(sizeof(struct mpeg_params), GFP_KERNEL)))
 		return -ENOMEM;
-	memcpy(params,&mpeg_params_template,sizeof(struct mpeg_params));
+	memcpy(params, &mpeg_params_template, sizeof(struct mpeg_params));
 	i2c_set_clientdata(client, params);
 
         i2c_attach_client(client);
-  
+
 	return 0;
 }
 
@@ -337,6 +427,7 @@
 {
 	if (adap->class & I2C_CLASS_TV_ANALOG)
 		return i2c_probe(adap, &addr_data, saa6752hs_attach);
+
 	return 0;
 }
 
@@ -355,16 +446,20 @@
 saa6752hs_command(struct i2c_client *client, unsigned int cmd, void *arg)
 {
 	struct mpeg_params* init_arg = arg;
+        int result;
 
         switch (cmd) {
 	case MPEG_SETPARAMS:
-   		return saa6752hs_init(client, init_arg);
+	   	result = saa6752hs_init(client, init_arg);
+	   	if (result != 0)
+	     		printk("saa6752hs: MPEG_SETPARAMS failed: %i\n", result);
+	   	return result;
 
 	default:
 		/* nothing */
 		break;
 	}
-	
+
 	return 0;
 }
 
--- linux-2.6.8.1.orig//include/media/saa6752hs.h	Sat Aug 14 11:56:26 2004
+++ linux-2.6.8.1//include/media/saa6752hs.h	Sat Aug 28 06:27:14 2004
@@ -1,4 +1,4 @@
-/* 
+/*
     saa6752hs.h - definition for saa6752hs MPEG encoder
 
     Copyright (C) 2003 Andrew de Quincey <[EMAIL PROTECTED]>
@@ -21,30 +21,47 @@
 #ifndef _SAA6752HS_H
 #define _SAA6752HS_H
 
-enum mpeg_bitrate_mode {
-	MPEG_BITRATE_MODE_VBR = 0, /* Variable bitrate */
-	MPEG_BITRATE_MODE_CBR = 1, /* Constant bitrate */
+enum mpeg_video_bitrate_mode {
+	MPEG_VIDEO_BITRATE_MODE_VBR = 0, /* Variable bitrate */
+	MPEG_VIDEO_BITRATE_MODE_CBR = 1, /* Constant bitrate */
 
-	MPEG_BITRATE_MODE_MAX
+	MPEG_VIDEO_BITRATE_MODE_MAX
 };
 
 enum mpeg_audio_bitrate {
 	MPEG_AUDIO_BITRATE_256 = 0, /* 256 kBit/sec */
 	MPEG_AUDIO_BITRATE_384 = 1, /* 384 kBit/sec */
-    
+
 	MPEG_AUDIO_BITRATE_MAX
 };
 
+enum mpeg_video_format {
+	MPEG_VIDEO_FORMAT_D1 = 0,
+	MPEG_VIDEO_FORMAT_2_3_D1 = 1,
+	MPEG_VIDEO_FORMAT_1_2_D1 = 2,
+	MPEG_VIDEO_FORMAT_SIF = 3,
+
+	MPEG_VIDEO_FORMAT_MAX
+};
+
 #define MPEG_VIDEO_TARGET_BITRATE_MAX 27000
 #define MPEG_VIDEO_MAX_BITRATE_MAX 27000
 #define MPEG_TOTAL_BITRATE_MAX 27000
-    
+#define MPEG_PID_MAX ((1 << 14) - 1)
+
 struct mpeg_params {
-	enum mpeg_bitrate_mode bitrate_mode;
+	enum mpeg_video_bitrate_mode video_bitrate_mode;
 	unsigned int video_target_bitrate;
 	unsigned int video_max_bitrate; // only used for VBR
 	enum mpeg_audio_bitrate audio_bitrate;
 	unsigned int total_bitrate;
+
+   	unsigned int pmt_pid;
+	unsigned int video_pid;
+	unsigned int audio_pid;
+	unsigned int pcr_pid;
+
+	enum mpeg_video_format video_format;
 };
 
 #define MPEG_SETPARAMS             _IOW('6',100,struct mpeg_params)
--- linux-2.6.8.1.orig//drivers/media/video/saa7134/saa7134-ts.c	Sat Aug 14 11:54:47 2004
+++ linux-2.6.8.1//drivers/media/video/saa7134/saa7134-ts.c	Sat Aug 28 06:41:22 2004
@@ -35,6 +35,8 @@
 
 #define TS_PACKET_SIZE 188 /* TS packets 188 bytes */
 
+#define THREAD_TIMEOUT (HZ/10)
+
 static unsigned int ts_debug  = 0;
 MODULE_PARM(ts_debug,"i");
 MODULE_PARM_DESC(ts_debug,"enable debug messages [ts]");
@@ -171,6 +173,7 @@
 
 /* ------------------------------------------------------------------ */
 
+
 static void ts_reset_encoder(struct saa7134_dev* dev) 
 {
 	saa_writeb(SAA7134_SPECIAL_MODE, 0x00);
@@ -182,11 +185,57 @@
 
 static int ts_init_encoder(struct saa7134_dev* dev, void* arg) 
 {
+   	saa7134_tvaudio_do_scan(dev);
 	ts_reset_encoder(dev);
 	saa7134_i2c_call_clients(dev, MPEG_SETPARAMS, arg);
  	return 0;
 }
 
+static void ts_sleep(struct saa7134_dev *dev, int timeout)
+{
+	DECLARE_WAITQUEUE(wait, current);
+	
+	add_wait_queue(&dev->ts.wq, &wait);
+	if (dev->ts.shutdown) {
+		set_current_state(TASK_INTERRUPTIBLE);
+		if (timeout < 0)
+			schedule();
+		else
+			schedule_timeout(timeout);
+	}
+	remove_wait_queue(&dev->ts.wq, &wait);
+}
+
+static int ts_thread(void* data)
+{
+	struct saa7134_dev* dev = (struct saa7134_dev*) data;
+   	int v1, v2;
+   
+	daemonize("%s", dev->name);
+	allow_signal(SIGTERM);
+	while(!dev->ts.shutdown) {
+		ts_sleep(dev,THREAD_TIMEOUT);
+		if (dev->ts.shutdown || signal_pending(current))
+			break;
+
+		v1 = saa_readb(SAA7134_STATUS_VIDEO1) & 0x40;
+		v2 = saa_readb(SAA7134_STATUS_VIDEO2) & 0x40;
+	   
+	   	if ((v1 || v2) && !dev->ts.lost_video) {
+		   	printk("saa7134-ts: video signal lost\n");
+			ts_reset_encoder(dev);
+		   	dev->ts.lost_video = 1;
+		} else if (dev->ts.started && dev->ts.lost_video && !v1 && !v2) {
+   		   	printk("saa7134-ts: video signal regained\n");
+			ts_init_encoder(dev, NULL);
+		   	dev->ts.lost_video = 0;
+		}
+	}
+
+	complete_and_exit(&dev->ts.exit, 0);
+	return 0;
+}
+
 
 /* ------------------------------------------------------------------ */
 
@@ -212,6 +261,7 @@
 		goto done;
 
 	dev->ts.started = 0;
+   	dev->ts.lost_video = 0;
 	dev->ts.users++;
 	file->private_data = dev;
 	err = 0;
@@ -233,9 +283,10 @@
 	dev->ts.users--;
 
 	/* stop the encoder */
-	if (dev->ts.started)
+	if (dev->ts.started) 
 	      	ts_reset_encoder(dev);
-  
+	dev->ts.started = 0;
+   
 	up(&dev->ts.ts.lock);
 	return 0;
 }
@@ -249,7 +300,7 @@
 		ts_init_encoder(dev, NULL);
 		dev->ts.started = 1;
 	}
-  
+
 	return videobuf_read_stream(file, &dev->ts.ts, data, count, ppos, 0);
 }
 
@@ -482,12 +533,29 @@
 	saa_writeb(SAA7134_TS_DMA0, ((ts_nr_packets-1)&0xff));
 	saa_writeb(SAA7134_TS_DMA1, (((ts_nr_packets-1)>>8)&0xff));
 	saa_writeb(SAA7134_TS_DMA2, ((((ts_nr_packets-1)>>16)&0x3f) | 0x00)); /* TSNOPIT=0, TSCOLAP=0 */
- 
+
+       	
+	/* start ts thread */
+	init_waitqueue_head(&dev->ts.wq);
+	init_completion(&dev->ts.exit);
+	dev->ts.pid = kernel_thread(ts_thread,dev,0);
+	if (dev->ts.pid < 0)
+		printk(KERN_WARNING "%s: kernel_thread() failed\n",
+		       dev->name);
+	wake_up_interruptible(&dev->ts.wq);
+
 	return 0;
 }
 
 int saa7134_ts_fini(struct saa7134_dev *dev)
 {
+	/* shutdown ts thread */
+	if (dev->ts.pid >= 0) {
+		dev->ts.shutdown = 1;
+		wake_up_interruptible(&dev->ts.wq);
+		wait_for_completion(&dev->ts.exit);
+	}
+   
 	/* nothing */
 	saa7134_pgtable_free(dev->pci,&dev->ts.pt_ts);
 	return 0;
--- linux-2.6.8.1.orig//drivers/media/video/saa7134/saa7134.h	Sat Aug 14 11:55:48 2004
+++ linux-2.6.8.1//drivers/media/video/saa7134/saa7134.h	Sat Aug 28 06:28:24 2004
@@ -284,6 +284,11 @@
 	struct videobuf_queue      ts;
 	struct saa7134_pgtable     pt_ts;
 	int			   started;
+   	int			   lost_video;
+	pid_t                      pid;
+	struct completion          exit;
+	wait_queue_head_t          wq;
+	unsigned int               shutdown;
 };
 
 /* oss dsp status */

Reply via email to