[PATCH] yenta: add modparam to tune EnE bridges (was Re: ENE CB1410 and Echo Indigo IO incompatibility)

Daniel Ritz daniel.ritz at gmx.ch
Sun Aug 21 16:53:42 EDT 2005


On Sunday 21 August 2005 21.10, Jon Stutters wrote:
> Daniel Ritz wrote:
> > On Saturday 20 August 2005 04.58, Andrew Morton wrote:
> > 
> >>Daniel Ritz <daniel.ritz at gmx.ch> wrote:
> >>
> >>> [PATCH] yenta: add modparam to tune EnE bridges
> >>>
> >>> EnE bridges have various compatibility problems with different CB cards. Eg.
> >>> are the RME HDSP soundcard, some CD writers, Echo Audio products and the
> >>> audigy 2 zs. There's a test bit (TLTEnable) that helps. but for some CB
> >>> cards it has to be cleared (HDSP, cd writer) and for some set (Echo
> >>> soundcards). Turn it into a modparam, default to clear to not break working
> >>> setups).
> >>>
> >>> Also add some more EnE entries to pci_ids.h and use them.
> >>
> >>Sad.  Is there no way in which we can do this automatically?
> >>
> > 
> > 
> > i knew you would ask.
> > 
> > something like the attached. it's completley untested...but there's a small
> > little problem. when reading the document from echo audio it seems that it's
> > not always the solution to set the bit...it's more try and error:
> > 	http://www.echoaudio.com/downloadfiles/Other/ENE_README.pdf
> 
> If I read the source you attached to the previous message correctly then 
> you're still only dealing with the TLTEnable bit.  The setting I had to 
> adjust to fix the echo audio card was prefetch which is controlled by 
> bit C8.
> 

<start quoting>
The prefetch function can be disabled under Linux by changing C8h to 
0200h in the cardbus chipset
</end quoting>

by reading this i was thinking its only about that bit because you have
the TLTEnable bit set, but the code clears it by default...

i now found some crappy doc from ene. reading it it's probably bit 2/3 at c9h
to control prefetch. btw. don't change anything in c8, only change c9, 8bit.

could you give me the content of that register before you change it, please.
( hexdump /proc/bus/pci/02/04.0 )
but anyway, try the attached updated auto-tuning patch.

akpm, dominik: do you like the auto-tuning thing?

rgds
-daniel

-----
[PATCH] yenta: auto-tune EnE bridges for CB cards

Echo Audio cardbus products are known to be incompatible with EnE bridges.
in order to maybe solve the problem a EnE specific test bit has to be set, another
cleared...but other setups have a good chance to break when just forcing the bits.
so do the whole thingy automatically.

the patch adds a hook in cb_alloc() that allows special tuning for the different
chipsets. for ene just match the Echo products and set/clear the test bits, defaults
to do the same thing as w/o the patch to not break working setups.

Signed-off-by: Daniel Ritz <daniel.ritz at gmx.ch>

diff --git a/drivers/pcmcia/cardbus.c b/drivers/pcmcia/cardbus.c
--- a/drivers/pcmcia/cardbus.c
+++ b/drivers/pcmcia/cardbus.c
@@ -228,6 +228,11 @@ int cb_alloc(struct pcmcia_socket * s)
 	pci_bus_size_bridges(bus);
 	pci_bus_assign_resources(bus);
 	cardbus_assign_irqs(bus, s->pci_irq);
+
+	/* socket specific tune function */
+	if (s->tune_bridge)
+		s->tune_bridge(s, bus);
+
 	pci_enable_bridges(bus);
 	pci_bus_add_devices(bus);
 
diff --git a/drivers/pcmcia/ti113x.h b/drivers/pcmcia/ti113x.h
--- a/drivers/pcmcia/ti113x.h
+++ b/drivers/pcmcia/ti113x.h
@@ -153,6 +153,12 @@
 /* EnE test register */
 #define ENE_TEST_C9			0xc9	/* 8bit */
 #define ENE_TEST_C9_TLTENABLE		0x02
+#define ENE_TEST_C9_PFENABLE_F0		0x04
+#define ENE_TEST_C9_PFENABLE_F1		0x08
+#define ENE_TEST_C9_PFENABLE		(ENE_TEST_C9_PFENABLE_F0 | ENE_TEST_C9_PFENABLE_F0)
+#define ENE_TEST_C9_WPDISALBLE_F0	0x40
+#define ENE_TEST_C9_WPDISALBLE_F1	0x80
+#define ENE_TEST_C9_WPDISALBLE		(ENE_TEST_C9_WPDISALBLE_F0 | ENE_TEST_C9_WPDISALBLE_F1)
 
 /*
  * Texas Instruments CardBus controller overrides.
@@ -791,16 +797,6 @@ static int ti12xx_override(struct yenta_
 		config_writel(socket, TI113X_SYSTEM_CONTROL, val);
 
 	/*
-	 * for EnE bridges only: clear testbit TLTEnable. this makes the
-	 * RME Hammerfall DSP sound card working.
-	 */
-	if (socket->dev->vendor == PCI_VENDOR_ID_ENE) {
-		u8 test_c9 = config_readb(socket, ENE_TEST_C9);
-		test_c9 &= ~ENE_TEST_C9_TLTENABLE;
-		config_writeb(socket, ENE_TEST_C9, test_c9);
-	}
-
-	/*
 	 * Yenta expects controllers to use CSCINT to route
 	 * CSC interrupts to PCI rather than INTVAL.
 	 */
@@ -841,5 +837,75 @@ static int ti1250_override(struct yenta_
 	return ti12xx_override(socket);
 }
 
+
+/**
+ * EnE specific part. EnE bridges are register compatible with TI bridges but
+ * have their own test registers and more important their own little problems.
+ * Some fixup code to make everybody happy (TM).
+ */
+
+/**
+ * set/clear various test bits:
+ * Defaults to clear the bit.
+ * - mask (u8) defines what bits to change
+ * - bits (u8) is the values to change them to
+ * -> it's
+ * 	current = (current & ~mask) | bits
+ */
+/* pci ids of devices that wants to have the bit set */
+#define DEVID(_vend,_dev,_subvend,_subdev,mask,bits) {		\
+		.vendor		= _vend,			\
+		.device		= _dev,				\
+		.subvendor	= _subvend,			\
+		.subdevice	= _subdev,			\
+		.driver_data	= ((mask) << 8 | (bits)),	\
+	}
+static struct pci_device_id ene_tune_tbl[] = {
+	/* Echo Audio products based on motorola DSP56301 and DSP56361 */
+	DEVID(PCI_VENDOR_ID_MOTOROLA, 0x1801, 0xECC0, PCI_ANY_ID,
+		ENE_TEST_C9_TLTENABLE | ENE_TEST_C9_PFENABLE, ENE_TEST_C9_TLTENABLE),
+	DEVID(PCI_VENDOR_ID_MOTOROLA, 0x3410, 0xECC0, PCI_ANY_ID,
+		ENE_TEST_C9_TLTENABLE | ENE_TEST_C9_PFENABLE, ENE_TEST_C9_TLTENABLE),
+
+	{}
+};
+
+static void ene_tune_bridge(struct pcmcia_socket *sock, struct pci_bus *bus)
+{
+	struct yenta_socket *socket = container_of(sock, struct yenta_socket, socket);
+	struct pci_dev *dev;
+	struct pci_device_id *id = NULL;
+	u8 test_c9, old_c9, mask, bits;
+
+	list_for_each_entry(dev, &bus->devices, bus_list) {
+		id = (struct pci_device_id *) pci_match_id(ene_tune_tbl, dev);
+		if (id)
+			break;
+	}
+
+	test_c9 = old_c9 = config_readb(socket, ENE_TEST_C9);
+	if (id) {
+		mask = (id->driver_data >> 8) & 0xFF;
+		bits = id->driver_data & 0xFF;
+
+		test_c9 = (test_c9 & ~mask) | bits;
+	}
+	else
+		/* default to clear TLTEnable bit, old behaviour */
+		test_c9 &= ~ENE_TEST_C9_TLTENABLE;
+
+	printk(KERN_INFO "yenta EnE: chaning testregister 0xC9, %02x -> %02x\n", old_c9, test_c9);
+	config_writeb(socket, ENE_TEST_C9, test_c9);
+}
+
+
+static int ene_override(struct yenta_socket *socket)
+{
+	/* install tune_bridge() function */
+	socket->socket.tune_bridge = ene_tune_bridge;
+
+	return ti1250_override(socket);
+}
+
 #endif /* _LINUX_TI113X_H */
 
diff --git a/drivers/pcmcia/yenta_socket.c b/drivers/pcmcia/yenta_socket.c
--- a/drivers/pcmcia/yenta_socket.c
+++ b/drivers/pcmcia/yenta_socket.c
@@ -753,6 +753,7 @@ enum {
 	CARDBUS_TYPE_RICOH,
 	CARDBUS_TYPE_TOPIC97,
 	CARDBUS_TYPE_O2MICRO,
+	CARDBUS_TYPE_ENE,
 };
 
 /*
@@ -796,6 +797,12 @@ static struct cardbus_type cardbus_type[
 		.override	= o2micro_override,
 		.restore_state	= o2micro_restore_state,
 	},
+	[CARDBUS_TYPE_ENE]	= {
+		.override	= ene_override,
+		.save_state	= ti_save_state,
+		.restore_state	= ti_restore_state,
+		.sock_init	= ti_init,
+	},
 };
 
 
@@ -1185,10 +1192,10 @@ static struct pci_device_id yenta_table 
 	CB_ID(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_1250, TI1250),
 	CB_ID(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_1410, TI1250),
 
-	CB_ID(PCI_VENDOR_ID_ENE, PCI_DEVICE_ID_ENE_1211, TI12XX),
-	CB_ID(PCI_VENDOR_ID_ENE, PCI_DEVICE_ID_ENE_1225, TI12XX),
-	CB_ID(PCI_VENDOR_ID_ENE, PCI_DEVICE_ID_ENE_1410, TI1250),
-	CB_ID(PCI_VENDOR_ID_ENE, PCI_DEVICE_ID_ENE_1420, TI12XX),
+	CB_ID(PCI_VENDOR_ID_ENE, PCI_DEVICE_ID_ENE_1211, ENE),
+	CB_ID(PCI_VENDOR_ID_ENE, PCI_DEVICE_ID_ENE_1225, ENE),
+	CB_ID(PCI_VENDOR_ID_ENE, PCI_DEVICE_ID_ENE_1410, ENE),
+	CB_ID(PCI_VENDOR_ID_ENE, PCI_DEVICE_ID_ENE_1420, ENE),
 
 	CB_ID(PCI_VENDOR_ID_RICOH, PCI_DEVICE_ID_RICOH_RL5C465, RICOH),
 	CB_ID(PCI_VENDOR_ID_RICOH, PCI_DEVICE_ID_RICOH_RL5C466, RICOH),
diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h
--- a/include/linux/pci_ids.h
+++ b/include/linux/pci_ids.h
@@ -2143,7 +2143,11 @@
 #define PCI_DEVICE_ID_ENE_1211		0x1211
 #define PCI_DEVICE_ID_ENE_1225		0x1225
 #define PCI_DEVICE_ID_ENE_1410		0x1410
+#define PCI_DEVICE_ID_ENE_710		0x1411
+#define PCI_DEVICE_ID_ENE_712		0x1412
 #define PCI_DEVICE_ID_ENE_1420		0x1420
+#define PCI_DEVICE_ID_ENE_720		0x1421
+#define PCI_DEVICE_ID_ENE_722		0x1422
 
 #define PCI_VENDOR_ID_SYBA		0x1592
 #define PCI_DEVICE_ID_SYBA_2P_EPP	0x0782
diff --git a/include/pcmcia/ss.h b/include/pcmcia/ss.h
--- a/include/pcmcia/ss.h
+++ b/include/pcmcia/ss.h
@@ -21,6 +21,9 @@
 #include <pcmcia/cs_types.h>
 #include <pcmcia/cs.h>
 #include <pcmcia/bulkmem.h>
+#ifdef CONFIG_CARDBUS
+#include <linux/pci.h>
+#endif
 
 /* Definitions for card status flags for GetStatus */
 #define SS_WRPROT	0x0001
@@ -233,7 +236,11 @@ struct pcmcia_socket {
 
 	/* so is power hook */
 	int (*power_hook)(struct pcmcia_socket *sock, int operation);
-                           
+#ifdef CONFIG_CARDBUS
+	/* allows tuning the CB bridge before loading driver for the CB card */
+	void (*tune_bridge)(struct pcmcia_socket *sock, struct pci_bus *bus);
+#endif
+
 	/* state thread */
 	struct semaphore		skt_sem;	/* protects socket h/w state */
 



More information about the linux-pcmcia mailing list