[mythtv-users] Pinnacle PCTV HD Card

Timothy E. Krantz tkrantz at stahurabrenner.com
Sat Jun 21 14:50:36 UTC 2008


> -----Original Message-----
> From: mythtv-users-bounces at mythtv.org 
> [mailto:mythtv-users-bounces at mythtv.org] On Behalf Of Tom Haddon
> Sent: Saturday, June 21, 2008 3:20 AM
> To: Discussion about mythtv
> Subject: Re: [mythtv-users] Pinnacle PCTV HD Card
> 
> On Fri, 2008-06-20 at 18:33 -0700, J. Addington wrote:
> > Which driver in the package did you load?
> 
> I was following the instructions on here:
> 
> http://www.mythtv.org/wiki/index.php/Pinnacle_PCTV_HD_Card_(800i)
> 
> > 
> > Also, which branch did you download for the drivers and 
> what is your kernel version?
> 
> My kernel is a stock mythbuntu 2.6.24-19-generic, and I 
> downloaded the drivers from here:
> 
> http://linuxtv.org/hg/v4l-dvb
> 
> I think I downloaded the bzip version, which has unpacked 
> into a directory v4l-dvb-afa24b594522. I have the firmware 
> file dvb-fe-xc5000-1.1.fw, although I've just realized it's 
> not in the appropriate directory (it's in 
> /lib/firmware/2.6.24-18-generic/ not 19) I'll put it in there 
> and recompile the drivers.
> 
> Thanks, Tom
> 
> > 
> > 
> > 
> > 
> > 
> > ----- Original Message ----
> > From: Tom Haddon <tom at haddons.net>
> > To: Discussion about mythtv <mythtv-users at mythtv.org>
> > Sent: Friday, June 20, 2008 6:47:16 PM
> > Subject: Re: [mythtv-users] Pinnacle PCTV HD Card
> > 
> > On Fri, 2008-06-20 at 16:24 -0700, J. Addington wrote:
> > > It's probably not the same problem but I recently 
> installed this card and was having a problem with the v4l-dvb 
> drivers.  There are several branches where you can download a 
> kernel module source and compile but I just ended up 
> upgrading my entire kernel to the latest stable version and 
> the included 4dl-dvb drivers then worked fine.
> > 
> > I think you might be onto the right track here. I recompiled the 
> > v4l-dvb modules and now I'm able to run:
> > 
> > scan
> > 
> /usr/share/doc/dvb-utils/examples/scan/atsc/us-ATSC-center-frequencies
> > -8VSB > channels.conf
> > 
> > Previously I was getting errors telling me the device 
> > /dev/dvb/adapter0/frontend0 didn't exist, so I think I was 
> looking at 
> > a kernel/kernel module issue.
> > 
> > However, I get the following when I run the scan command:
> > 
> > mthaddon at sentinel:~$
> > scan 
> > 
> /usr/share/doc/dvb-utils/examples/scan/atsc/us-ATSC-center-frequencies
> > -8VSB > channels.conf scanning 
> > 
> /usr/share/doc/dvb-utils/examples/scan/atsc/us-ATSC-center-frequencies
> > -8VSB using '/dev/dvb/adapter0/frontend0' and 
> > '/dev/dvb/adapter0/demux0'
> > >>> tune to: 57028615:8VSB
> > WARNING: >>> tuning failed!!!
> > >>> tune to: 57028615:8VSB (tuning failed)
> > WARNING: >>> tuning failed!!!
> > >>> tune to: 63028615:8VSB
> > WARNING: >>> tuning failed!!!
> > >>> tune to: 63028615:8VSB (tuning failed)
> > WARNING: >>> tuning failed!!!
> > >>> tune to: 69028615:8VSB
> > WARNING: >>> tuning failed!!!
> > [...]
> > ERROR: initial tuning failed
> > dumping lists (0 services)
> > Done.
> > 
> > 
> > All the channels seem to fail this way, and I'm left with an empty 
> > channels.conf. Doesn't seem good :(
> > 
> > Thanks, Tom
> > 
> > > 
> > > 
> > > ----- Original Message ----
> > > From: Tom Haddon <tom at haddons.net>
> > > To: mythtv-users at mythtv.org
> > > Sent: Friday, June 20, 2008 4:41:54 PM
> > > Subject: [mythtv-users] Pinnacle PCTV HD Card
> > > 
> > > Hi Folks,
> > > 
> > > I've just bought a Pinnacle PCTV HD Card as per
> > > 
> http://www.bestbuy.com/site/olspage.jsp?skuId=8512424&type=pro
> duct&id=1186005934822 and I'm trying to configure it to worth 
> with my hardy Mythbuntu install.
> > > 
> > > I've been following the instructions on
> > > http://mythtv.org/wiki/index.php/Pinnacle_PCTV_HD_Card_(800i) and 
> > > have extracted the firmware, and compiled the v4l-dvb 
> drivers per that page.
> > > I'm then able to see the device as an option in mythtvsetup. I've 
> > > configured it as an MPEG-2 encoder card, and in the "Probed Info"
> > > section it's showing "Pinnacle PCTV HD800i [cx8800]". I've then 
> > > setup Schedules Direct as a Video Source, and under "Input 
> > > Connections" I've defined "[MPEG: /dev/video0] (Television) -> 
> > > Schedules Direct". I've then performed the "Scan for 
> Channels" and 
> > > have got a bunch of channels showing up (I'm just using 
> rabbit ears, 
> > > don't have cable or satellite), but when I go to "Watch 
> TV" on the 
> > > mythfrontend I get a blank screen for a few seconds and then I'm 
> > > returned to the main menu. I see the following in the 
> frontend log:
> > > 
> > > 2008-06-07 09:28:57.828 TV: Attempting to change from None to 
> > > WatchingLiveTV
> > > 2008-06-07 09:28:57.829 Using protocol version 40
> > > 2008-06-07 09:29:03.102 GetEntryAt(-1) failed.
> > > 2008-06-07 09:29:03.103 EntryToProgram(0 at Wed Dec 31 
> 16:00:00 1969) 
> > > failed to get pginfo
> > > 2008-06-07 09:29:03.103 TV Error: LiveTV not successfully started
> > > 2008-06-07 09:29:03.138 TV Error: LiveTV not successfully started
> > > 2008-06-07 09:29:03.234 TV: Deleting TV Chain in destructor
> > > 2008-06-07 09:29:03.238 DPMS Deactivated
> > > 2008-06-07 09:29:03.238 DPMS Reactivated.
> > > 
> > > Also, after a recent update to linux-restricted-modules, 
> whenever I 
> > > run the mythtv-setup script and try to go to any of the pages 
> > > (General, Capture Cards, Video Source, etc.) I get a 
> message saying 
> > > "If this is the master backend server, please run 
> mythfilldatabase 
> > > to populate the database with channel information". The 
> only option 
> > > is "OK" at which point mythtv-setup exits and I'm asked 
> to run that 
> > > mythfilldatabase. If I do, it runs fine, but still I get the same 
> > > message when I re-run mythtv-setup. So now I can't see my current 
> > > config, or change it in any way...
> > > 
> > > Any help appreciated.
> > > 
> > > Thanks, Tom
> > > 
> > > _______________________________________________
> > > mythtv-users mailing list
> > > mythtv-users at mythtv.org
> > > http://mythtv.org/cgi-bin/mailman/listinfo/mythtv-users
> > > 
> > > 
> > > 
> > >      
> > > _______________________________________________
> > > mythtv-users mailing list
> > > mythtv-users at mythtv.org
> > > http://mythtv.org/cgi-bin/mailman/listinfo/mythtv-users
> > 
> > _______________________________________________
> > mythtv-users mailing list
> > mythtv-users at mythtv.org
> > http://mythtv.org/cgi-bin/mailman/listinfo/mythtv-users
> > 
> > 
> > 
> >       
> > _______________________________________________
> > mythtv-users mailing list
> > mythtv-users at mythtv.org
> > http://mythtv.org/cgi-bin/mailman/listinfo/mythtv-users
> 
> _______________________________________________
> mythtv-users mailing list
> mythtv-users at mythtv.org
> http://mythtv.org/cgi-bin/mailman/listinfo/mythtv-users
>

I use that card quite successfully, BUT only with the addition of the patch
from the linux-dvb list that I will drop in below.  This patch to the xc5000
tuner module (that this pinnacle card uses) has been available since late
January of this year.  Word was that it would be included in the mainline
linux-dvb "probably in the next few weeks" but that has not happened.  I'm
not sure why not.

Here is the patch that resolved the issues you seem to be having from me.
Thanks again to Mr Zhang.

P.s. here is a link to  the archive of the patch
http://www.linuxtv.org/pipermail/linux-dvb/2008-January/023392.html

On Jan 27, 2008 6:50 PM, Chaogui Zhang <czhang1974 at gmail.com> wrote:
> 
> Download the newest v4l-dvb tree from http://linuxtv.org/hg/v4l-dvb 
> and apply the patch against it.
> 

I just noticed that the previous patch that fixed the kernel oops has been
merged into the master tree, which conflicts with the patch for tuner
performance improvement(which contains the oops fixes too). I regenerated
the patch against the master tree and it is below. Please use this one
instead.

--
Chaogui Zhang

Signed-off-by: Chaogui Zhang <czhang1974 at gmail.com>

diff -r ed7daeb29425 linux/drivers/media/dvb/frontends/xc5000.c
--- a/linux/drivers/media/dvb/frontends/xc5000.c	Mon Jan 28 10:01:11
2008 -0200
+++ b/linux/drivers/media/dvb/frontends/xc5000.c	Sun Jan 27 19:36:07
2008 -0500
@@ -3,6 +3,7 @@
  *
  *  Copyright (c) 2007 Xceive Corporation
  *  Copyright (c) 2007 Steven Toth <stoth at hauppauge.com>
+ *  Copyright (c) 2007, 2008 Chaogui Zhang <czhang1974 at gmail.com>
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by @@
-38,6 +39,13 @@ MODULE_PARM_DESC(debug, "Turn on/off deb
 
 #define dprintk(level,fmt, arg...) if (debug >= level) \
 	printk(KERN_INFO "%s: " fmt, "xc5000", ## arg)
+
+static int allow_shutdown;
+module_param(allow_shutdown, int, 0644); 
+MODULE_PARM_DESC(allow_shutdown, "Allow the XC5000 tuner to be shutdown 
+(default: no).");
+
+static LIST_HEAD(xc5000_list);
+static DEFINE_MUTEX(xc5000_list_lock);
 
 #define XC5000_DEFAULT_FIRMWARE "dvb-fe-xc5000-1.1.fw"
 #define XC5000_DEFAULT_FIRMWARE_SIZE 12332 @@ -179,7 +187,6 @@
XC_TV_STANDARD XC5000_Standard[MAX_TV_ST
 
 static int  xc5000_writeregs(struct xc5000_priv *priv, u8 *buf, u8 len);
static int  xc5000_readregs(struct xc5000_priv *priv, u8 *buf, u8 len);
-static void xc5000_TunerReset(struct dvb_frontend *fe);
 
 static int xc_send_i2c_data(struct xc5000_priv *priv, u8 *buf, int len)  {
@@ -195,29 +202,21 @@ static int xc_read_i2c_data(struct xc500
 
 static int xc_reset(struct dvb_frontend *fe)  {
-	xc5000_TunerReset(fe);
-	return XC_RESULT_SUCCESS;
-}
-
-static void xc_wait(int wait_ms)
-{
-	msleep(wait_ms);
-}
-
-static void xc5000_TunerReset(struct dvb_frontend *fe) -{
 	struct xc5000_priv *priv = fe->tuner_priv;
 	int ret;
 
 	dprintk(1, "%s()\n", __FUNCTION__);
 
-	if (priv->cfg->tuner_callback) {
-		ret = priv->cfg->tuner_callback(priv->cfg->priv,
-						XC5000_TUNER_RESET, 0);
-		if (ret)
-			printk(KERN_ERR "xc5000: reset failed\n");
-	} else
-		printk(KERN_ERR "xc5000: no tuner reset callback function,
fatal\n");
+	if (!priv->cfg->tuner_callback) {
+		printk(KERN_ERR
+			"xc5000: no tuner reset callback function,
fatal\n");
+		return XC_RESULT_RESET_FAILURE;
+	}
+
+	ret = priv->cfg->tuner_callback(priv->cfg->priv,
+					XC5000_TUNER_RESET, 0);
+	if (ret) printk(KERN_ERR "xc5000: reset failed\n");
+	return ret;
 }
 
 static int xc_write_reg(struct xc5000_priv *priv, u16 regAddr, u16 i2cData)
@@ -245,7 +244,7 @@ static int xc_write_reg(struct xc5000_pr
 						/* busy flag cleared */
 					break;
 					} else {
-						xc_wait(100); /* wait 5 ms
*/
+						msleep(5); /* wait 5 ms */
 						WatchDogTimer--;
 					}
 				}
@@ -296,7 +295,7 @@ static int xc_load_i2c_sequence(struct d
 				return result;
 		} else if (len & 0x8000) {
 			/* WAIT command */
-			xc_wait(len & 0x7FFF);
+			msleep(len & 0x7FFF);
 			index += 2;
 		} else {
 			/* Send i2c data whilst ensuring individual
transactions @@ -352,11 +351,10 @@ static int xc_SetTVStandard(struct xc500
 
 static int xc_shutdown(struct xc5000_priv *priv)  {
-	return 0;
-	/* Fixme: cannot bring tuner back alive once shutdown
-	 *        without reloading the driver modules.
-	 *    return xc_write_reg(priv, XREG_POWER_DOWN, 0);
-	 */
+	if(allow_shutdown)
+		return xc_write_reg(priv, XREG_POWER_DOWN, 0);
+	else
+		return 0;
 }
 
 static int xc_SetSignalSource(struct xc5000_priv *priv, u16 rf_mode) @@
-496,7 +494,7 @@ static u16 WaitForLock(struct xc5000_pri
 	while ((lockState == 0) && (watchDogCount > 0)) {
 		xc_get_lock_status(priv, &lockState);
 		if (lockState != 1) {
-			xc_wait(5);
+			msleep(5);
 			watchDogCount--;
 		}
 	}
@@ -612,7 +610,7 @@ static void xc_debug_dump(struct xc5000_
 	 * Frame Lines needs two frame times after initial lock
 	 * before it is valid.
 	 */
-	xc_wait(100);
+	msleep(100);
 
 	xc_get_ADC_Envelope(priv,  &adc_envelope);
 	dprintk(1, "*** ADC envelope (0-1023) = %d\n", adc_envelope); @@
-640,13 +638,32 @@ static void xc_debug_dump(struct xc5000_
 	dprintk(1, "*** Quality (0:<8dB, 7:>56dB) = %d\n", quality);  }
 
+static int xc_load_fw_and_init_tuner(struct dvb_frontend *fe);
+
 static int xc5000_set_params(struct dvb_frontend *fe,
 	struct dvb_frontend_parameters *params)  {
 	struct xc5000_priv *priv = fe->tuner_priv;
-	int ret;
+	int ret=0;
 
 	dprintk(1, "%s() frequency=%d (Hz)\n", __FUNCTION__,
params->frequency);
+
+	mutex_lock(&priv->lock);
+
+	if(priv->fwloaded == 0) {
+		ret = xc_load_fw_and_init_tuner(fe);
+	}
+#if 0
+	else {
+		ret = xc_initialize(priv);
+		msleep(100);
+	}
+#endif
+	if(ret != XC_RESULT_SUCCESS) {
+		printk(KERN_ERR "xc5000: Unable to initialise tuner\n");
+		mutex_unlock(&priv->lock);
+		return -EREMOTEIO;
+	}
 
 	switch(params->u.vsb.modulation) {
 	case VSB_8:
@@ -667,6 +684,7 @@ static int xc5000_set_params(struct dvb_
 		priv->video_standard = DTV6;
 		break;
 	default:
+		mutex_unlock(&priv->lock);
 		return -EINVAL;
 	}
 
@@ -678,6 +696,7 @@ static int xc5000_set_params(struct dvb_
 		printk(KERN_ERR
 			"xc5000: xc_SetSignalSource(%d) failed\n",
 			priv->rf_mode);
+		mutex_unlock(&priv->lock);
 		return -EREMOTEIO;
 	}
 
@@ -686,6 +705,7 @@ static int xc5000_set_params(struct dvb_
 		XC5000_Standard[priv->video_standard].AudioMode);
 	if (ret != XC_RESULT_SUCCESS) {
 		printk(KERN_ERR "xc5000: xc_SetTVStandard failed\n");
+		mutex_unlock(&priv->lock);
 		return -EREMOTEIO;
 	}
 
@@ -693,6 +713,7 @@ static int xc5000_set_params(struct dvb_
 	if (ret != XC_RESULT_SUCCESS) {
 		printk(KERN_ERR "xc5000: xc_Set_IF_frequency(%d) failed\n",
 			priv->cfg->if_khz);
+		mutex_unlock(&priv->lock);
 		return -EIO;
 	}
 
@@ -701,22 +722,36 @@ static int xc5000_set_params(struct dvb_
 	if (debug)
 		xc_debug_dump(priv);
 
-	return 0;
-}
-
-static int xc_load_fw_and_init_tuner(struct dvb_frontend *fe);
+	mutex_unlock(&priv->lock);
+	return 0;
+}
 
 static int xc5000_set_analog_params(struct dvb_frontend *fe,
 	struct analog_parameters *params)
 {
 	struct xc5000_priv *priv = fe->tuner_priv;
-	int ret;
-
-	if(priv->fwloaded == 0)
-		xc_load_fw_and_init_tuner(fe);
+	int ret=0;
 
 	dprintk(1, "%s() frequency=%d (in units of 62.5khz)\n",
 		__FUNCTION__, params->frequency);
+
+	mutex_lock(&priv->lock);
+
+	if(priv->fwloaded == 0) {
+		ret = xc_load_fw_and_init_tuner(fe);
+	}
+#if 0
+	else {
+		ret = xc_initialize(priv);
+		msleep(100);
+	}
+#endif
+
+	if(ret != XC_RESULT_SUCCESS) {
+		printk(KERN_ERR "xc5000: Unable to initialise tuner\n");
+		mutex_unlock(&priv->lock);
+		return -EREMOTEIO;
+	}
 
 	priv->rf_mode = XC_RF_MODE_CABLE; /* Fix me: it could be air. */
 
@@ -769,9 +804,10 @@ tune_channel:
 tune_channel:
 	ret = xc_SetSignalSource(priv, priv->rf_mode);
 	if (ret != XC_RESULT_SUCCESS) {
-	printk(KERN_ERR
+		printk(KERN_ERR
 			"xc5000: xc_SetSignalSource(%d) failed\n",
 			priv->rf_mode);
+		mutex_unlock(&priv->lock);
 		return -EREMOTEIO;
 	}
 
@@ -780,6 +816,7 @@ tune_channel:
 		XC5000_Standard[priv->video_standard].AudioMode);
 	if (ret != XC_RESULT_SUCCESS) {
 		printk(KERN_ERR "xc5000: xc_SetTVStandard failed\n");
+		mutex_unlock(&priv->lock);
 		return -EREMOTEIO;
 	}
 
@@ -788,6 +825,7 @@ tune_channel:
 	if (debug)
 		xc_debug_dump(priv);
 
+	mutex_unlock(&priv->lock);
 	return 0;
 }
 
@@ -827,12 +865,11 @@ static int xc_load_fw_and_init_tuner(str
 	struct xc5000_priv *priv = fe->tuner_priv;
 	int ret = 0;
 
-	if (priv->fwloaded == 0) {
-		ret = xc5000_fwupload(fe);
-		if (ret != XC_RESULT_SUCCESS)
-			return ret;
-		priv->fwloaded = 1;
-	}
+	ret = xc5000_fwupload(fe);
+	if (ret != XC_RESULT_SUCCESS) {
+		return ret;
+	}
+	priv->fwloaded = 1;
 
 	/* Start the tuner self-calibration process */
 	ret |= xc_initialize(priv);
@@ -842,7 +879,7 @@ static int xc_load_fw_and_init_tuner(str
 	 * I2C transactions until calibration is complete.  This way we
 	 * don't have to rely on clock stretching working.
 	 */
-	xc_wait( 100 );
+	msleep( 100 );
 
 	/* Default to "CABLE" mode */
 	ret |= xc_write_reg(priv, XREG_SIGNALSOURCE, XC_RF_MODE_CABLE); @@
-857,21 +894,20 @@ static int xc5000_sleep(struct dvb_front
 
 	dprintk(1, "%s()\n", __FUNCTION__);
 
-	/* On Pinnacle PCTV HD 800i, the tuner cannot be reinitialized
-	 * once shutdown without reloading the driver. Maybe I am not
-	 * doing something right.
-	 *
-	 */
+	mutex_lock(&priv->lock);
 
 	ret = xc_shutdown(priv);
 	if(ret != XC_RESULT_SUCCESS) {
 		printk(KERN_ERR
 			"xc5000: %s() unable to shutdown tuner\n",
 			__FUNCTION__);
+		mutex_unlock(&priv->lock);
 		return -EREMOTEIO;
 	}
 	else {
-		/* priv->fwloaded = 0; */
+		if(allow_shutdown) 
+			priv->fwloaded = 0; /* was indeed shutdown */
+		mutex_unlock(&priv->lock);
 		return XC_RESULT_SUCCESS;
 	}
 }
@@ -879,24 +915,51 @@ static int xc5000_init(struct dvb_fronte  static int
xc5000_init(struct dvb_frontend *fe)  {
 	struct xc5000_priv *priv = fe->tuner_priv;
+	int ret;
+
 	dprintk(1, "%s()\n", __FUNCTION__);
 
-	if (xc_load_fw_and_init_tuner(fe) != XC_RESULT_SUCCESS) {
+	mutex_lock(&priv->lock);
+
+	if(priv->fwloaded == 0) {
+		ret = xc_load_fw_and_init_tuner(fe);
+	}
+	else {	/* Firmware has been loaded previously, just initialize */
+		ret = xc_initialize(priv);
+		msleep(100);
+		ret |= xc_write_reg(priv, XREG_SIGNALSOURCE,
XC_RF_MODE_CABLE);
+	}
+
+	if(ret != XC_RESULT_SUCCESS) {
 		printk(KERN_ERR "xc5000: Unable to initialise tuner\n");
+		mutex_unlock(&priv->lock);
 		return -EREMOTEIO;
 	}
 
 	if (debug)
 		xc_debug_dump(priv);
 
+	mutex_unlock(&priv->lock);
 	return 0;
 }
 
 static int xc5000_release(struct dvb_frontend *fe)  {
+	struct xc5000_priv *priv = fe->tuner_priv;
+
 	dprintk(1, "%s()\n", __FUNCTION__);
-	kfree(fe->tuner_priv);
+
+	mutex_lock(&xc5000_list_lock);
+	
+	priv->count--;
+	if(priv->count == 0) {
+		list_del(&priv->xc5000_list);
+		kfree(priv);
+	}
 	fe->tuner_priv = NULL;
+
+	mutex_unlock(&xc5000_list_lock);
+
 	return 0;
 }
 
@@ -924,23 +987,49 @@ struct dvb_frontend * xc5000_attach(stru
 	struct xc5000_config *cfg)
 {
 	struct xc5000_priv *priv = NULL;
+	void 		   *cfg_priv;
 	u16 id = 0;
 
 	dprintk(1, "%s()\n", __FUNCTION__);
 
-	priv = kzalloc(sizeof(struct xc5000_priv), GFP_KERNEL);
-	if (priv == NULL)
+	if (NULL == cfg || NULL == cfg->priv || NULL == fe)
 		return NULL;
 
-	priv->cfg = cfg;
-	priv->bandwidth = BANDWIDTH_6_MHZ;
-	priv->i2c = i2c;
+	cfg_priv = cfg->priv;
+
+	mutex_lock(&xc5000_list_lock);
+
+	list_for_each_entry(priv, &xc5000_list, xc5000_list) {
+		if (priv->cfg->priv == cfg->priv) {
+			cfg_priv = NULL;
+			break;
+		}
+	}
+
+	if(cfg_priv) {
+		priv = kzalloc(sizeof(struct xc5000_priv), GFP_KERNEL);
+		if (priv == NULL) {
+			mutex_unlock(&xc5000_list_lock);
+			return NULL;
+		}
+
+		priv->cfg = cfg;
+		priv->bandwidth = BANDWIDTH_6_MHZ;
+		priv->i2c = i2c;
+		priv->fwloaded = 0;
+		priv->count = 0;
+
+		mutex_init(&priv->lock);
+		list_add_tail(&priv->xc5000_list, &xc5000_list);
+	}
+
 
 	/* Check if firmware has been loaded. It is possible that another
 	   instance of the driver has loaded the firmware.
 	 */
 	if (xc5000_readreg(priv, XREG_PRODUCT_ID, &id) != 0) {
 		kfree(priv);
+		mutex_unlock(&xc5000_list_lock);
 		return NULL;
 	}
 
@@ -966,6 +1055,7 @@ struct dvb_frontend * xc5000_attach(stru
 			"xc5000: Device not found at addr 0x%02x (0x%x)\n",
 			cfg->i2c_address, id);
 		kfree(priv);
+		mutex_unlock(&xc5000_list_lock);
 		return NULL;
 	}
 
@@ -973,11 +1063,14 @@ struct dvb_frontend * xc5000_attach(stru
 		sizeof(struct dvb_tuner_ops));
 
 	fe->tuner_priv = priv;
-
+	priv->count++;
+
+	mutex_unlock(&xc5000_list_lock);
 	return fe;
 }
 EXPORT_SYMBOL(xc5000_attach);
 
 MODULE_AUTHOR("Steven Toth");
+MODULE_AUTHOR("Chaogui Zhang");
 MODULE_DESCRIPTION("Xceive xc5000 silicon tuner driver");
MODULE_LICENSE("GPL"); diff -r ed7daeb29425
linux/drivers/media/dvb/frontends/xc5000_priv.h
--- a/linux/drivers/media/dvb/frontends/xc5000_priv.h	Mon Jan 28 10:01:11
2008 -0200
+++ b/linux/drivers/media/dvb/frontends/xc5000_priv.h	Fri Jan 25 11:46:34
2008 -0500
@@ -23,6 +23,7 @@
 #define XC5000_PRIV_H
 
 struct xc5000_priv {
+	struct list_head     xc5000_list;
 	struct xc5000_config *cfg;
 	struct i2c_adapter   *i2c;
 
@@ -31,6 +32,14 @@ struct xc5000_priv {
 	u8  video_standard;
 	u8  rf_mode;
 	u8  fwloaded;
+
+	int count;
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 16)
+	struct mutex lock;
+#else
+	struct semaphore lock;
+#endif
 };
 
 #endif

_______________________________________________
linux-dvb mailing list
linux-dvb at linuxtv.org
http://www.linuxtv.org/cgi-bin/mailman/listinfo/linux-dvb
 




More information about the mythtv-users mailing list