Re: Dvico Dual 4 card not working.

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Tue, Apr 1, 2008 at 11:41 AM, Ben Caldwell <benny.caldwell@xxxxxxxxx> wrote:
> On Tue, Apr 1, 2008 at 10:31 AM, Nicholas Magers <
>  After much plodding through changesets I have something to report. It seems
>  that the the dvico dual digital 4 card is broken in changesets after
>  d4df22377e83 (11 days ago).
>  It is interesting to note that the next change (the one that breaks it) is
>  "Removes video_dev from tuner-xc3028 config struct" - the dvico dual digital
>  4 has an xc3028.
>
>  So to get it working:
>  *hg update -r d4df22377e83
>  make clean
>  make rminstall
>  make release
>  make
>  make install*
>
>  Then reboot. One other interesting thing I have found is that sometimes
>  after compiling new modules I actually have to turn the PC off then on again
>  (rather than just a reboot) to get everything working properly.
>
>  - Ben


Can you try using the v4l-dvb master branch hg repository on
linuxtv.org again, after applying the attached patch (see below)

It is clear what went wrong on the Dual Digital 4 --

Mauro did some changes recently that use a "magic number" (yuck) to
differentiate between devices and manage multiple instances of the
xc2028 driver on a hybrid design.

He used i2c_adapter->algo_data to generate this "magic number" ,
which, IMHO is a very bad idea, especially since some digital-only
devices do not even define algo_data.  On the other hand,
i2c_adap->algo_data is a reasonable structure to use for the
"video_dev" pointer in the tuner_callback function, *if* it is
defined.

The patch in the link above uses the 'hybrid_tuner_request_state"
method to manage multiple instances of the device driver on a hybrid
design.  This uses a *much* safer method, using the i2c_adapter ID
along with the device i2c address to identify unique instances.  For
the "video_dev" pointer, the patch also uses a safer method:  If the
dvb_adapter device is defined, use fe->dvb->priv, otherwise, fall back
to Mauro's previous method of using i2c_adap->algo_data.

Please note:  This patch is intended for testing purposes only --
there is a remaining issue in this patch, where it doesn't destroy
some memory properly when tuner instances are destroyed.  I'll be
happy to fix that remaining issue after I receive some reports that
the larger issue is actually remedied by this patch.

Please let me know if this fixes the problem, and I'll produce a new
patch afterwards.

Regards,

Mike Krufky
diff -r 0776e4801991 linux/drivers/media/video/tuner-xc2028.c
--- a/linux/drivers/media/video/tuner-xc2028.c	Fri Mar 28 14:52:44 2008 -0300
+++ b/linux/drivers/media/video/tuner-xc2028.c	Tue Apr 01 15:57:38 2008 -0400
@@ -57,7 +57,7 @@ MODULE_PARM_DESC(firmware_name, "Firmwar
 MODULE_PARM_DESC(firmware_name, "Firmware file name. Allows overriding the "
 				"default firmware name\n");
 
-static LIST_HEAD(xc2028_list);
+static LIST_HEAD(hybrid_tuner_instance_list);
 static DEFINE_MUTEX(xc2028_list_mutex);
 
 /* struct for storing firmware table */
@@ -79,12 +79,11 @@ struct firmware_properties {
 };
 
 struct xc2028_data {
-	struct list_head        xc2028_list;
+	struct list_head        hybrid_tuner_instance_list;
 	struct tuner_i2c_props  i2c_props;
 	int                     (*tuner_callback) (void *dev,
 						   int command, int arg);
 	void			*video_dev;
-	int			count;
 	__u32			frequency;
 
 	struct firmware_description *firm;
@@ -1095,19 +1094,12 @@ static int xc2028_dvb_release(struct dvb
 
 	mutex_lock(&xc2028_list_mutex);
 
-	priv->count--;
-
-	if (!priv->count) {
-		list_del(&priv->xc2028_list);
-
-		kfree(priv->ctrl.fname);
-
-		free_firmware(priv);
-		kfree(priv);
-		fe->tuner_priv = NULL;
-	}
+	if (priv)
+		hybrid_tuner_release_state(priv);
 
 	mutex_unlock(&xc2028_list_mutex);
+
+	fe->tuner_priv = NULL;
 
 	return 0;
 }
@@ -1179,7 +1171,7 @@ struct dvb_frontend *xc2028_attach(struc
 				   struct xc2028_config *cfg)
 {
 	struct xc2028_data *priv;
-	void               *video_dev;
+	int instance;
 
 	if (debug)
 		printk(KERN_DEBUG "xc2028: Xcv2028/3028 init called!\n");
@@ -1192,48 +1184,40 @@ struct dvb_frontend *xc2028_attach(struc
 		return NULL;
 	}
 
-	video_dev = cfg->i2c_adap->algo_data;
-
-	if (debug)
-		printk(KERN_DEBUG "xc2028: video_dev =%p\n", video_dev);
-
 	mutex_lock(&xc2028_list_mutex);
 
-	list_for_each_entry(priv, &xc2028_list, xc2028_list) {
-		if (&priv->i2c_props.adap->dev == &cfg->i2c_adap->dev) {
-			video_dev = NULL;
-			if (debug)
-				printk(KERN_DEBUG "xc2028: reusing device\n");
-
-			break;
-		}
-	}
-
-	if (video_dev) {
-		priv = kzalloc(sizeof(*priv), GFP_KERNEL);
-		if (priv == NULL) {
-			mutex_unlock(&xc2028_list_mutex);
-			return NULL;
-		}
-
-		priv->i2c_props.addr = cfg->i2c_addr;
-		priv->i2c_props.adap = cfg->i2c_adap;
-		priv->i2c_props.name = "xc2028";
-
-		priv->video_dev = video_dev;
+	instance = hybrid_tuner_request_state(struct xc2028_data, priv,
+					      hybrid_tuner_instance_list,
+					      cfg->i2c_adap, cfg->i2c_addr,
+					      "xc2028");
+	switch (instance) {
+	case 0:
+		/* memory allocation failure */
+		goto fail;
+		break;
+	case 1:
+		/* new tuner instance */
 		priv->tuner_callback = cfg->callback;
 		priv->ctrl.max_len = 13;
 
 		mutex_init(&priv->lock);
 
-		list_add_tail(&priv->xc2028_list, &xc2028_list);
-	}
-
-	fe->tuner_priv = priv;
-	priv->count++;
-
-	if (debug)
-		printk(KERN_DEBUG "xc2028: usage count is %i\n", priv->count);
+		/* analog side (tuner-core) uses i2c_adap->algo_data.
+		 * digital side is not guaranteed to have algo_data defined.
+		 *
+		 * digital side will always have fe->dvb defined.
+		 * analog side (tuner-core) doesn't (yet) define fe->dvb.
+		 */
+		priv->video_dev = ((fe->dvb) && (fe->dvb->priv)) ?
+				   fe->dvb->priv : cfg->i2c_adap->algo_data;
+
+		fe->tuner_priv = priv;
+		break;
+	case 2:
+		/* existing tuner instance */
+		fe->tuner_priv = priv;
+		break;
+	}
 
 	memcpy(&fe->ops.tuner_ops, &xc2028_dvb_tuner_ops,
 	       sizeof(xc2028_dvb_tuner_ops));
@@ -1246,6 +1230,11 @@ struct dvb_frontend *xc2028_attach(struc
 	mutex_unlock(&xc2028_list_mutex);
 
 	return fe;
+fail:
+	mutex_unlock(&xc2028_list_mutex);
+
+	xc2028_dvb_release(fe);
+	return NULL;
 }
 
 EXPORT_SYMBOL(xc2028_attach);
_______________________________________________
linux-dvb mailing list
linux-dvb@xxxxxxxxxxx
http://www.linuxtv.org/cgi-bin/mailman/listinfo/linux-dvb

[Index of Archives]     [Linux Media]     [Video 4 Linux]     [Asterisk]     [Samba]     [Xorg]     [Xfree86]     [Linux USB]

  Powered by Linux