[PATCH] alsa-driver: portman2x4 code cleanup

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

 



Hi,

here is the long announced cleanup of the portman2x4 driver code,
please review.

Thanks,
Matthias

Signed-off-by: Matthias Koenig <mkoenig@xxxxxxx>
============================================================
Summary: portman2x4 code cleanup

- changed code structure to mirror the one of the mts64.c driver 
  for better maintenance
- added proper handling of platform device
- general cleanup (no CamelCase names)

diff -r cd59e9f6118e drivers/portman2x4-kernel.c
--- a/drivers/portman2x4-kernel.c	Thu Jan 18 12:09:34 2007 +0100
+++ b/drivers/portman2x4-kernel.c	Wed Jan 24 15:46:08 2007 +0100
@@ -18,74 +18,108 @@
  *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  *
  * ChangeLog
- * Feb 20 2004 Tobias Gehrig <tobias@xxxxxxxxx>
- *      - ported from alsa 0.5 to 1.0
- * Mar 17 2004 Tobias Gehrig <tobias@xxxxxxxxx>
- *      - added checks for opened input device in interrupt handler
- * Mar 18 2004 Tobias Gehrig <tobias@xxxxxxxxx>
- *      - added parport_unregister_driver to the startup routine if the driver fails to detect a portman
- *      - added support for all 4 output ports in portman_putmidi
- * Mar 24 2004 Tobias Gehrig <tobias@xxxxxxxxx>
- *      - added 2.6 kernel support
+ * Jan 24 2007 Matthias Koenig <mkoenig@xxxxxxx>
+ *      - cleanup and rewrite
+ * Sep 30 2004 Tobias Gehrig <tobias@xxxxxxxxx>
+ *      - source code cleanup
  * Sep 03 2004 Tobias Gehrig <tobias@xxxxxxxxx>
  *      - fixed compilation problem with alsa 1.0.6a (removed MODULE_CLASSES,
  *        MODULE_PARM_SYNTAX and changed MODULE_DEVICES to
  *        MODULE_SUPPORTED_DEVICE)
- * Sep 30 2004 Tobias Gehrig <tobias@xxxxxxxxx>
- *      - source code cleanup
+ * Mar 24 2004 Tobias Gehrig <tobias@xxxxxxxxx>
+ *      - added 2.6 kernel support
+ * Mar 18 2004 Tobias Gehrig <tobias@xxxxxxxxx>
+ *      - added parport_unregister_driver to the startup routine if the driver fails to detect a portman
+ *      - added support for all 4 output ports in portman_putmidi
+ * Mar 17 2004 Tobias Gehrig <tobias@xxxxxxxxx>
+ *      - added checks for opened input device in interrupt handler
+ * Feb 20 2004 Tobias Gehrig <tobias@xxxxxxxxx>
+ *      - ported from alsa 0.5 to 1.0
  */
 
 #include <sound/driver.h>
 #include <linux/init.h>
-#include <linux/moduleparam.h>
+#include <linux/platform_device.h>
+#include <linux/parport.h>
+#include <linux/spinlock.h>
+#include <linux/delay.h>
 #include <sound/core.h>
+#include <sound/initval.h>
+#include <sound/rawmidi.h>
 #include <sound/control.h>
-#include <sound/rawmidi.h>
-#include <sound/initval.h>
-#include <linux/parport.h>
-#include <linux/delay.h>
-#include <sound/memalloc.h>
-
-#define chip_t portman_t
+
+#define CARD_NAME "Portman 2x4"
+#define DRIVER_NAME "portman"
+#define PLATFORM_DRIVER "snd_portman2x4"
+
+static int index[SNDRV_CARDS]  = SNDRV_DEFAULT_IDX;
+static char *id[SNDRV_CARDS]   = SNDRV_DEFAULT_STR;
+static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP;
+
+static struct platform_device *platform_devices[SNDRV_CARDS]; 
+static int device_count;
+
+module_param_array(index, int, NULL, S_IRUGO);
+MODULE_PARM_DESC(index, "Index value for " CARD_NAME " soundcard.");
+module_param_array(id, charp, NULL, S_IRUGO);
+MODULE_PARM_DESC(id, "ID string for " CARD_NAME " soundcard.");
+module_param_array(enable, bool, NULL, S_IRUGO);
+MODULE_PARM_DESC(enable, "Enable " CARD_NAME " soundcard.");
 
 MODULE_AUTHOR("Levent Gündogdu, Tobias Gehrig");
 MODULE_DESCRIPTION("Midiman Portman2x4");
 MODULE_LICENSE("GPL");
 MODULE_SUPPORTED_DEVICE("{{Midiman,Portman2x4}}");
 
-static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;	/* Index 0-MAX */
-static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;	/* ID for this card */
-static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE;	/* Enable switches */
-
-module_param_array(index, int, NULL, 0444);
-MODULE_PARM_DESC(index, "Index value for Portman2x4 midi interface.");
-module_param_array(id, charp, NULL, 0444);
-MODULE_PARM_DESC(id, "ID string for Portman2x4 midi interface.");
-module_param_array(enable, bool, NULL, 0444);
-MODULE_PARM_DESC(enable, "Enable Portman2x4 midi interface.");
-
-typedef struct _snd_portman portman_t;
-
-static portman_t *portman;
-
-struct _snd_portman {
+/*********************************************************************
+ * Chip specific
+ *********************************************************************/
+#define PORTMAN_NUM_INPUT_PORTS 2
+#define PORTMAN_NUM_OUTPUT_PORTS 4
+
+struct portman {
 	spinlock_t reg_lock;
-
 	struct snd_card *card;
-	int irq;
-	unsigned long port;
-
-	unsigned char midi_input_mode[2];
-	unsigned char midi_output_mode[4];
-
 	struct snd_rawmidi *rmidi;
-	struct snd_rawmidi_substream *midi_input[2];
-	struct snd_rawmidi_substream *midi_output[4];
+	struct pardevice *pardev;
+	int pardev_claimed;
+
+	int open_count;
+	int mode[PORTMAN_NUM_INPUT_PORTS];
+	struct snd_rawmidi_substream *midi_input[PORTMAN_NUM_INPUT_PORTS];
 };
 
-/* Definitions for portman driver */
-#define	BYTE           unsigned char
-#define WORD           unsigned int
+static int portman_free(struct portman *pm)
+{
+	kfree(pm);
+	return 0;
+}
+
+static int __devinit portman_create(struct snd_card *card, 
+				    struct pardevice *pardev, 
+				    struct portman **rchip)
+{
+	struct portman *pm;
+
+	*rchip = NULL;
+
+	pm = kzalloc(sizeof(struct portman), GFP_KERNEL);
+	if (pm == NULL) 
+		return -ENOMEM;
+
+	/* Init chip specific data */
+	spin_lock_init(&pm->reg_lock);
+	pm->card = card;
+	pm->pardev = pardev;
+
+	*rchip = pm;
+
+	return 0;
+}
+
+/*********************************************************************
+ * HW related constants
+ *********************************************************************/
 
 /* Standard PC parallel port status register equates. */
 #define	PP_STAT_BSY   	0x80	/* Busy status.  Inverted. */
@@ -153,66 +187,40 @@ struct _snd_portman {
 #define	A1_ECHO         PP_STAT_BSY	/* Address 1 Echo.            1 1 0 */
 #define	A2_ECHO         PP_STAT_BSY	/* Address 2 Echo.            1 1 1 */
 
-#define PORTMAN2X4_MODE_INPUT_OPENED	 0x01
-#define PORTMAN2X4_MODE_OUTPUT_OPENED	 0x02
-#define PORTMAN2X4_MODE_INPUT_TRIGGERED	 0x04
-#define PORTMAN2X4_MODE_OUTPUT_TRIGGERED 0x08
-
-
-/* Pointer to parallel port which we actually use */
-static struct parport *myPort = NULL;
-
-/* Pointer to pardevice after registration */
-static struct pardevice *myParDevice = NULL;
-
-/* static struct parport_operations *myParPortOps = NULL; */
-static int portowned = 0;
-static int portman_found = 0;
-
-/* Delay settings */
-static int gwAddressDelay = 0;
-static int gwDataDelay = 0;
-
-/* Useful information */
-static char *sDeviceName = "portman2x4";
-static char *sVersion = "0.1";
-
-/* State+Cleanup variables */
-static unsigned char SAVE_PORTCOMMAND = 0;
-static unsigned char SAVE_PORTDATA = 0;
-static unsigned char SAVE_PORTVALID = 0;
-
-/* parallel port access mappers */
-
-static inline void portman_writeCommand(unsigned char value)
-{
-	parport_write_control(myPort, value);
-}
-
-static inline unsigned char portman_readCommand(void)
-{
-	return parport_read_control(myPort);
-}
-
-static inline unsigned char portman_readStatus(void)
-{
-	return parport_read_status(myPort);
-}
-
-static inline unsigned char portman_readData(void)
-{
-	return parport_read_data(myPort);
-}
-
-static inline void portman_writeData(unsigned char value)
-{
-	parport_write_data(myPort, value);
-}
-
-static void portman_putmidi(int port, unsigned char mididata)
+#define PORTMAN2X4_MODE_INPUT_TRIGGERED	 0x01
+
+/*********************************************************************
+ * Hardware specific functions
+ *********************************************************************/
+static inline void portman_write_command(struct portman *pm, u8 value)
+{
+	parport_write_control(pm->pardev->port, value);
+}
+
+static inline u8 portman_read_command(struct portman *pm)
+{
+	return parport_read_control(pm->pardev->port);
+}
+
+static inline u8 portman_read_status(struct portman *pm)
+{
+	return parport_read_status(pm->pardev->port);
+}
+
+static inline u8 portman_read_data(struct portman *pm)
+{
+	return parport_read_data(pm->pardev->port);
+}
+
+static inline void portman_write_data(struct portman *pm, u8 value)
+{
+	parport_write_data(pm->pardev->port, value);
+}
+
+static void portman_write_midi(struct portman *pm, 
+			       int port, u8 mididata)
 {
 	int command = ((port + 4) << 1);
-	unsigned long flags;
 
 	/* Get entering data byte and port number in BL and BH respectively.
 	 * Set up Tx Channel address field for use with PP Cmd Register.
@@ -230,185 +238,148 @@ static void portman_putmidi(int port, un
 	 * PP Command Reg.  Do not set the Strobe signal yet.
 	 */
 
-      hbpTxWait:
-	local_irq_save(flags);
-	portman_writeCommand(command);
-	udelay(gwAddressDelay);
-
-	/* While the address lines settle, write parallel output data to 
-	 * PP Data Reg.  This has no effect until Strobe signal is asserted.
-	 */
-
-	portman_writeData(mididata);
-
-	udelay(gwDataDelay);
-
-	/* If PCP channel's TxEmpty is set (TxEmpty is read through the PP
-	 * Status Register), then go write data.  Else go back and wait.
-	 */
-
-	if ((portman_readStatus() & TXEMPTY) == TXEMPTY) /* Is channel's TxEmpty set? */
-		goto hpbEmpty;	                         /* Y: Go write data then. */
-
-	local_irq_restore(flags);                        /* Allow small window for ints. */
-	goto hbpTxWait;
+	do {
+		portman_write_command(pm, command);
+
+		/* While the address lines settle, write parallel output data to 
+		 * PP Data Reg.  This has no effect until Strobe signal is asserted.
+		 */
+
+		portman_write_data(pm, mididata);
+		
+		/* If PCP channel's TxEmpty is set (TxEmpty is read through the PP
+		 * Status Register), then go write data.  Else go back and wait.
+		 */
+	} while ((portman_read_status(pm) & TXEMPTY) != TXEMPTY);
 
 	/* TxEmpty is set.  Maintain PC/P destination address and assert
 	 * Strobe through the PP Command Reg.  This will Strobe data into
 	 * the PC/P transmitter and set the PC/P BUSY signal.
 	 */
 
-      hpbEmpty:
-	portman_writeCommand(command | STROBE);
-	udelay(gwAddressDelay);
+	portman_write_command(pm, command | STROBE);
 
 	/* Wait for strobe line to settle and echo back through hardware.
 	 * Once it has echoed back, assume that the address and data lines
 	 * have settled!
 	 */
 
-	while ((portman_readStatus() & ESTB) == 0);
+	while ((portman_read_status(pm) & ESTB) == 0);
 
 	/* Release strobe and immediately re-allow interrupts. */
-	portman_writeCommand(command);
-	udelay(gwAddressDelay);
-	local_irq_restore(flags);
-
-	while ((portman_readStatus() & ESTB) == ESTB);
+	portman_write_command(pm, command);
+
+	while ((portman_read_status(pm) & ESTB) == ESTB);
 
 	/* PC/P BUSY is now set.  We must wait until BUSY resets itself.
 	 * We'll reenable ints while we're waiting.
 	 */
 
-	while ((portman_readStatus() & BUSY) == BUSY);
+	while ((portman_read_status(pm) & BUSY) == BUSY);
 
 	/* Data sent. */
 }
 
 
-static unsigned char portman_readmidi(int port)
-{
-  /***************************************************************************
-   * Attempt to read input byte from specified hardware input port (0..).
-   * Return -1 if no data.
-   ***************************************************************************/
-
-	unsigned char midiValue = 0;
+/*
+ *  Read MIDI byte from port
+ *  Attempt to read input byte from specified hardware input port (0..).
+ *  Return -1 if no data
+ */
+static int portman_read_midi(struct portman *pm, int port)
+{
+	unsigned char midi_data = 0;
 	unsigned char cmdout;	/* Saved address+IE bit. */
 
 	/* Make sure clocking edge is down before starting... */
-	portman_writeData(0);	/* Make sure edge is down. */
-	udelay(gwDataDelay);	/* Settle clock. */
+	portman_write_data(pm, 0);	/* Make sure edge is down. */
 
 	/* Set destination address to PCP. */
 	cmdout = (port << 1) | INT_EN;	/* Address + IE + No Strobe. */
-	portman_writeCommand(cmdout);
-	udelay(gwAddressDelay);	/* Address settle. */
-
-	while ((portman_readStatus() & ESTB) == ESTB);	/* Wait for strobe echo. */
+	portman_write_command(pm, cmdout);
+
+	while ((portman_read_status(pm) & ESTB) == ESTB);	/* Wait for strobe echo. */
 
 	/* After the address lines settle, check multiplexed RxAvail signal.
 	 * If data is available, read it.
 	 */
-	if ((portman_readStatus() & RXAVAIL) == 0)
+	if ((portman_read_status(pm) & RXAVAIL) == 0)
 		return -1;	/* No data. */
 
 	/* Set the Strobe signal to enable the Rx clocking circuitry. */
-	portman_writeCommand(cmdout | STROBE);	/* Write address+IE+Strobe. */
-	udelay(gwAddressDelay);	/* Strobe settle. */
-
-	while ((portman_readStatus() & ESTB) == 0); /* Wait for strobe echo. */
+	portman_write_command(pm, cmdout | STROBE);	/* Write address+IE+Strobe. */
+
+	while ((portman_read_status(pm) & ESTB) == 0); /* Wait for strobe echo. */
 
 	/* The first data bit (msb) is already sitting on the input line. */
-	midiValue = (portman_readStatus() & 128);
-	portman_writeData(1);	/* Cause rising edge, which shifts data. */
-	udelay(gwDataDelay);	/* Settle clock. */
-
+	midi_data = (portman_read_status(pm) & 128);
+	portman_write_data(pm, 1);	/* Cause rising edge, which shifts data. */
 
 	/* Data bit 6. */
-	portman_writeData(0);	/* Cause falling edge while data settles. */
-	udelay(gwDataDelay);	/* Settle clock. */
-	midiValue = midiValue | ((portman_readStatus() >> 1) & 64);
-	portman_writeData(1);	/* Cause rising edge, which shifts data. */
-	udelay(gwDataDelay);	/* Settle clock. */
+	portman_write_data(pm, 0);	/* Cause falling edge while data settles. */
+	midi_data |= (portman_read_status(pm) >> 1) & 64;
+	portman_write_data(pm, 1);	/* Cause rising edge, which shifts data. */
 
 	/* Data bit 5. */
-	portman_writeData(0);	/* Cause falling edge while data settles. */
-	udelay(gwDataDelay);	/* Settle clock. */
-	midiValue = midiValue | ((portman_readStatus() >> 2) & 32);
-	portman_writeData(1);	/* Cause rising edge, which shifts data. */
-	udelay(gwDataDelay);	/* Settle clock. */
+	portman_write_data(pm, 0);	/* Cause falling edge while data settles. */
+	midi_data |= (portman_read_status(pm) >> 2) & 32;
+	portman_write_data(pm, 1);	/* Cause rising edge, which shifts data. */
 
 	/* Data bit 4. */
-	portman_writeData(0);	/* Cause falling edge while data settles. */
-	udelay(gwDataDelay);	/* Settle clock. */
-	midiValue = midiValue | ((portman_readStatus() >> 3) & 16);
-	portman_writeData(1);	/* Cause rising edge, which shifts data. */
-	udelay(gwDataDelay);	/* Settle clock. */
+	portman_write_data(pm, 0);	/* Cause falling edge while data settles. */
+	midi_data |= (portman_read_status(pm) >> 3) & 16;
+	portman_write_data(pm, 1);	/* Cause rising edge, which shifts data. */
 
 	/* Data bit 3. */
-	portman_writeData(0);	/* Cause falling edge while data settles. */
-	udelay(gwDataDelay);	/* Settle clock. */
-	midiValue = midiValue | ((portman_readStatus() >> 4) & 8);
-	portman_writeData(1);	/* Cause rising edge, which shifts data. */
-	udelay(gwDataDelay);	/* Settle clock. */
+	portman_write_data(pm, 0);	/* Cause falling edge while data settles. */
+	midi_data |= (portman_read_status(pm) >> 4) & 8;
+	portman_write_data(pm, 1);	/* Cause rising edge, which shifts data. */
 
 	/* Data bit 2. */
-	portman_writeData(0);	/* Cause falling edge while data settles. */
-	udelay(gwDataDelay);	/* Settle clock. */
-	midiValue = midiValue | ((portman_readStatus() >> 5) & 4);
-	portman_writeData(1);	/* Cause rising edge, which shifts data. */
-	udelay(gwDataDelay);	/* Settle clock. */
+	portman_write_data(pm, 0);	/* Cause falling edge while data settles. */
+	midi_data |= (portman_read_status(pm) >> 5) & 4;
+	portman_write_data(pm, 1);	/* Cause rising edge, which shifts data. */
 
 	/* Data bit 1. */
-	portman_writeData(0);	/* Cause falling edge while data settles. */
-	udelay(gwDataDelay);	/* Settle clock. */
-	midiValue = midiValue | ((portman_readStatus() >> 6) & 2);
-	portman_writeData(1);	/* Cause rising edge, which shifts data. */
-	udelay(gwDataDelay);	/* Settle clock. */
+	portman_write_data(pm, 0);	/* Cause falling edge while data settles. */
+	midi_data |= (portman_read_status(pm) >> 6) & 2;
+	portman_write_data(pm, 1);	/* Cause rising edge, which shifts data. */
 
 	/* Data bit 0. */
-	portman_writeData(0);	/* Cause falling edge while data settles. */
-	udelay(gwDataDelay);	/* Settle clock. */
-	midiValue = midiValue | ((portman_readStatus() >> 7) & 1);
-	portman_writeData(1);	/* Cause rising edge, which shifts data. */
-	udelay(gwDataDelay);	/* Settle clock. */
-	portman_writeData(0);	/* Return data clock low. */
-	udelay(gwDataDelay);	/* Settle clock. */
+	portman_write_data(pm, 0);	/* Cause falling edge while data settles. */
+	midi_data |= (portman_read_status(pm) >> 7) & 1;
+	portman_write_data(pm, 1);	/* Cause rising edge, which shifts data. */
+	portman_write_data(pm, 0);	/* Return data clock low. */
 
 
 	/* De-assert Strobe and return data. */
-	portman_writeCommand(cmdout);	/* Output saved address+IE. */
-	udelay(gwAddressDelay);	/* Settle clock. */
+	portman_write_command(pm, cmdout);	/* Output saved address+IE. */
 
 	/* Wait for strobe echo. */
-	while ((portman_readStatus() & ESTB) == ESTB);
-
-	return (midiValue & 255);	/* Shift back and return value. */
+	while ((portman_read_status(pm) & ESTB) == ESTB);
+
+	return (midi_data & 255);	/* Shift back and return value. */
 }
 
 /*
  *  Checks if any input data on the given channel is available
  *  Checks RxAvail 
  */
-
-static int portman_dataavail(int channel)
+static int portman_data_avail(struct portman *pm, int channel)
 {
 	int command = INT_EN;
 	switch (channel) {
 	case 0:
-		command = command | RXDATA0;
+		command |= RXDATA0;
 		break;
 	case 1:
-		command = command | RXDATA1;
+		command |= RXDATA1;
 		break;
 	}
 	/* Write hardware (assumme STROBE=0) */
-	portman_writeCommand(command);
-	/* Allow settling. */
-	udelay(gwAddressDelay);
+	portman_write_command(pm, command);
 	/* Check multiplexed RxAvail signal */
-	if ((portman_readStatus() & RXAVAIL) == RXAVAIL)
+	if ((portman_read_status(pm) & RXAVAIL) == RXAVAIL)
 		return 1;	/* Data available */
 
 	/* No Data available */
@@ -419,11 +390,10 @@ static int portman_dataavail(int channel
 /*
  *  Flushes any input
  */
-
-static void portman_flushInput(unsigned char port)
+static void portman_flush_input(struct portman *pm, unsigned char port)
 {
 	/* Local variable for counting things */
-	unsigned int iCounter = 0;
+	unsigned int i = 0;
 	unsigned char command = 0;
 
 	switch (port) {
@@ -434,171 +404,45 @@ static void portman_flushInput(unsigned 
 		command = RXDATA1;
 		break;
 	default:
-		snd_printk("portman_flushInput() Won't flush port %i\n",
+		snd_printk("portman_flush_input() Won't flush port %i\n",
 			   port);
 		return;
 	}
 
 	/* Set address for specified channel in port and allow to settle. */
-	portman_writeCommand(command);
-	udelay(gwAddressDelay);
+	portman_write_command(pm, command);
 
 	/* Assert the Strobe and wait for echo back. */
-	portman_writeCommand(command | STROBE);
+	portman_write_command(pm, command | STROBE);
 
 	/* Wait for ESTB */
-	while ((portman_readStatus() & ESTB) == 0)
-	  udelay(gwAddressDelay);
-
-
+	while ((portman_read_status(pm) & ESTB) == 0)
+		;
 
 	/* Output clock cycles to the Rx circuitry. */
-	portman_writeData(0);
-	udelay(gwDataDelay);
+	portman_write_data(pm, 0);
 
 	/* Flush 250 bits... */
-	for (iCounter = 0; iCounter < 250; iCounter++) {
-		udelay(gwDataDelay);
-		portman_writeData(1);
-		udelay(gwDataDelay);
-		portman_writeData(0);
+	for (i = 0; i < 250; i++) {
+		portman_write_data(pm, 1);
+		portman_write_data(pm, 0);
 	}
 
 	/* Deassert the Strobe signal of the port and wait for it to settle. */
-	portman_writeCommand(command | INT_EN);
+	portman_write_command(pm, command | INT_EN);
 
 	/* Wait for settling */
-	while ((portman_readStatus() & ESTB) == ESTB)
-	  udelay(gwAddressDelay);
-}
-
-
-/* clean up code */
-
-static void cleanup(void)
-{
-	/* local data */
-	unsigned long flags;
-
-	/* ====================
-	 * CLEANUP PARALLELPORT
-	 * ====================
-	 */
-
-	/* check if port was owned by this driver */
-	if (portowned == 1) {
-		/* restore port state */
-
-		/* Disable interrupt while giving up port */
-		local_irq_save(flags);
-
-		/* Restore parallel port status */
-		if (SAVE_PORTVALID == 1) {
-
-			portman_writeCommand(SAVE_PORTCOMMAND);
-			portman_writeData(SAVE_PORTDATA);
-		}
-
-		parport_release(myParDevice);
-		portowned = 0;
-
-		/* Reenable interrupts */
-		local_irq_restore(flags);
-	}
-
-	if (myParDevice != NULL) {
-		parport_unregister_device(myParDevice);
-		myParDevice = NULL;
-	}
-
-	/* ===========================================
-	 * CLEANUP KERNEL MEMORY & DEVICE REGISTRATION
-	 * ===========================================
-	 */
-
-	kfree(portman);
-	portman = NULL;
-}
-
-/* irq handler */
-
-
-/*
- * IRQ-HANDLER
- *
- * @param  int              Number of IRQ
- * @param  void*            User data (struct parport* related to this interrupt)
- * @param  struct pt_regs*  Pointer to pt_regs
- */
-
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 19)
-static void portman_handler_irq(int irq, void *userdata)
-#else
-static void portman_handler_irq(int irq, void *userdata, struct pt_regs *regs)
-#endif
-{
-	unsigned long flags;
-	/* Test if output gets written if interrupts are disabled! */
-	unsigned char midivalue = 0;
-
-	/* Disable interrupts (we must not be disturbed while processing here...) */
-	local_irq_save(flags);
-
-	/* While any input data is waiting */
-	while ((portman_readStatus() & INT_REQ) == INT_REQ) {
-		/* If data available on channel 0, read it and stuff it into the queue. */
-		if (portman_dataavail(0)) {
-			/* Read Midi */
-			midivalue = portman_readmidi(0);
-			/* put midi into queue... */
-			if (portman->
-			    midi_input_mode[0] &
-			    PORTMAN2X4_MODE_INPUT_TRIGGERED)
-				snd_rawmidi_receive(portman->midi_input[0],
-						    &midivalue, 1);
-
-		}
-		/* If data available on channel 1, read it and stuff it into the queue. */
-		if (portman_dataavail(1)) {
-			/* Read Midi */
-			midivalue = portman_readmidi(1);
-			/* put midi into queue... */
-			if (portman->
-			    midi_input_mode[1] &
-			    PORTMAN2X4_MODE_INPUT_TRIGGERED)
-				snd_rawmidi_receive(portman->midi_input[1],
-						    &midivalue, 1);
-		}
-
-	}
-
-	/* Reenable interrupts */
-	local_irq_restore(flags);
-}
-
-/* portman detection function */
-
-/****************************************************************************
- *  Initialize the MIDI driver software and port hardware.
- *
- *  Inputs:     BASE = Base I/O address of port.
- *              IRQ  = IRQ number.
- *
- *  Returns:    0  if successful.
- *	       1     Strobe echo failure.
- *	       2     Transmitter stuck.
- ****************************************************************************/
-
-static int hwOpen(void)
-{
-	int delay = gwAddressDelay;
-
+	while ((portman_read_status(pm) & ESTB) == ESTB)
+		;
+}
+
+static int portman_probe(struct parport *p)
+{
 	/* Initialize the parallel port data register.  Will set Rx clocks
 	 * low in case we happen to be addressing the Rx ports at this time.
 	 */
 	/* 1 */
-	portman_writeData(0);
-	udelay(delay);
+	parport_write_data(p, 0);
 
 	/* Initialize the parallel port command register, thus initializing
 	 * hardware handshake lines to midi box:
@@ -607,406 +451,417 @@ static int hwOpen(void)
 	 *                                  Interrupt Enable = 0            
 	 */
 	/* 2 */
-	portman_writeCommand(0);
-	udelay(delay);
+	parport_write_control(p, 0);
 
 	/* Check if Portman PC/P 2x4 is out there. */
 	/* 3 */
-	portman_writeCommand(RXDATA0);	/* Write Strobe=0 to command reg. */
-	udelay(delay);
+	parport_write_control(p, RXDATA0);	/* Write Strobe=0 to command reg. */
 
 	/* Check for ESTB to be clear */
 	/* 4 */
-	if ((portman_readStatus() & ESTB) == ESTB)
+	if ((parport_read_status(p) & ESTB) == ESTB)
 		return 1;	/* CODE 1 - Strobe Failure. */
 
 	/* Set for RXDATA0 where no damage will be done. */
 	/* 5 */
-	portman_writeCommand(RXDATA0 + STROBE);	/* Write Strobe=1 to command reg. */
-	udelay(delay);
+	parport_write_control(p, RXDATA0 + STROBE);	/* Write Strobe=1 to command reg. */
 
 	/* 6 */
-	if ((portman_readStatus() & ESTB) != ESTB)
+	if ((parport_read_status(p) & ESTB) != ESTB)
 		return 1;	/* CODE 1 - Strobe Failure. */
 
 	/* 7 */
-	portman_writeCommand(0);	/* Reset Strobe=0. */
-	udelay(delay);
-
+	parport_write_control(p, 0);	/* Reset Strobe=0. */
 
 	/* Check if Tx circuitry is functioning properly.  If initialized 
 	 * unit TxEmpty is false, send out char and see if if goes true.
 	 */
 	/* 8 */
-	portman_writeCommand(TXDATA0);	/* Tx channel 0, strobe off. */
-	udelay(delay);
+	parport_write_control(p, TXDATA0);	/* Tx channel 0, strobe off. */
 
 	/* If PCP channel's TxEmpty is set (TxEmpty is read through the PP
 	 * Status Register), then go write data.  Else go back and wait.
 	 */
 	/* 9 */
-	if ((portman_readStatus() & TXEMPTY) == 0)
+	if ((parport_read_status(p) & TXEMPTY) == 0)
 		return 2;
 
 	/* Return OK status. */
 	return 0;
 }
 
-/* test */
-static void portman_testInterrupts(void)
-{
-	int i;
-
-	for (i = 0; i < 5; i++) {
-		if ((portman_readCommand() & INT_EN) == INT_EN) {
-			snd_printk(">>> Interrupts enabled :)\n");
-			return;
-		}
-
-		snd_printk("portman2x4: %i\n", portman_readCommand());
-		snd_printk("portman2x4: %i\n", INT_EN);
-		snd_printk(">>> Interrupts are not enabled!");
-
-		udelay(gwAddressDelay);
-
-		snd_printk(">>> Trying to enable IRQ...\n");
-		myPort->ops->enable_irq(myPort);
-		udelay(gwAddressDelay);
-	}
-}
-
-
-/* parport handler functions */
-
-static void portman_attach(struct parport *port)
-{
+static int portman_device_init(struct portman *pm)
+{
+	portman_flush_input(pm, 0);
+	portman_flush_input(pm, 1);
+
+	return 0;
+}
+
+/*********************************************************************
+ * Rawmidi
+ *********************************************************************/
+
+static void snd_portman_midi_input_trigger(struct snd_rawmidi_substream *substream,
+					   int up)
+{
+	struct portman *pm = substream->rmidi->private_data;
 	unsigned long flags;
-	/* local data */
-	int result = 0;
-
-	/* output information on used port */
-	if (port != NULL)
-		snd_printk("Using port at 0x%lx, IRQ %i.\n", port->base,
-			   port->irq);
-	else {
-		snd_printk("Ooops! port is NULL\n");
-		return;
-	}
-
-	/* Test if device supports irq. Abort initialization of not. */
-	if (port->irq == -1) {
-		snd_printk
-		    ("Error. Parallel port does not support IRQ. \n");
-		cleanup();
-		return;
-	}
-
-	/* keep pointer to port */
-	myPort = port;
-
-	/* Now register device with IRQ enabled */
-	myParDevice = (struct pardevice *) parport_register_device(port,	/* ptr to port to register at */
-								   sDeviceName,	/* ptr to device name */
-								   NULL,	/* ptr to preemption handler */
-								   NULL,	/* ptr to wakeup handler */
-								   portman_handler_irq,	/* ptr to irq handler */
-								   0,	/* no flags */
-								   NULL);	/* no handle */
-	/* Check if device registration was successful */
-	if (myParDevice == NULL) {
-		snd_printk("Error. Pardevice could not be registered.\n");
-		cleanup();
-		return;
-	}
-
-	/* Claim parport device */
-
-	/* Disable interrupts (we must not be disturbed while processing here...) */
-	local_irq_save(flags);
-
-	/* Claim the device */
-	if (parport_claim(myParDevice) != 0) {
-		local_irq_restore(flags);
-		snd_printk("Device is busy.\n");
-		cleanup();
-		return;
-	}
-
-	portowned = 1;
-
-	/* Save current port status... */
-	SAVE_PORTCOMMAND = portman_readCommand();
-	SAVE_PORTDATA = portman_readData();
-	SAVE_PORTVALID = 1;
-
-	/* check for portman existence */
-	result = 0;
-	result = hwOpen();
-
-	/* Reenable interrupts */
-	local_irq_restore(flags);
-
-	switch (result) {
-	case 0:
-		snd_printk("Portman found.\n");
-		portman_found = 1;
-		break;
-	case 1:
-		snd_printk("Probe error. Portman not found.\n");
-		cleanup();
-		return;
-		break;
-	case 2:
-		snd_printk("TX Error. Hardware test fail.\n");
-		cleanup();
-		return;
-		break;
-	}
-
-	/* Module initialization complete... */
-
-	/* Later: flushAllInputs()  (number of ports variable - possible compatibility with PortMan 4x4 (untested)) */
-	/* save flags, disable interrupts */
-	/* Flush inputs 0 and 1 */
-	portman_flushInput(0);
-	portman_flushInput(1);
-	/* restore flags */
-
-	/* Test if interrupts are enabled. */
-
-	portman_testInterrupts();
-
-	return;
-}
-
-static void portman_detach(struct parport *port)
-{
-}
-
-static struct parport_driver portman_driver = {
-	.name = "portman2x4",
-	.attach = portman_attach,
-	.detach = portman_detach,
-};
-
-static int snd_portman_midi_input_open(struct snd_rawmidi_substream *substream)
-{
-	unsigned long flags;
-
-	spin_lock_irqsave(&portman->reg_lock, flags);
-	portman->midi_input_mode[substream->number] |=
-	    PORTMAN2X4_MODE_INPUT_OPENED;
-	portman->midi_input[substream->number] = substream;
-	spin_unlock_irqrestore(&portman->reg_lock, flags);
-	return 0;
-}
-
-static int snd_portman_midi_input_close(struct snd_rawmidi_substream *
-					substream)
-{
-	unsigned long flags;
-
-	spin_lock_irqsave(&portman->reg_lock, flags);
-	portman->midi_input_mode[substream->number] &=
-	    (~PORTMAN2X4_MODE_INPUT_OPENED);
-	portman->midi_input[substream->number] = NULL;
-	spin_unlock_irqrestore(&portman->reg_lock, flags);
-	return 0;
-}
-
-static int snd_portman_midi_output_open(struct snd_rawmidi_substream *
-					substream)
-{
-	unsigned long flags;
-
-	spin_lock_irqsave(&portman->reg_lock, flags);
-	portman->midi_output_mode[substream->number] |=
-	    PORTMAN2X4_MODE_OUTPUT_OPENED;
-	portman->midi_output[substream->number] = substream;
-	spin_unlock_irqrestore(&portman->reg_lock, flags);
-	return 0;
-}
-
-static int snd_portman_midi_output_close(struct snd_rawmidi_substream *
-					 substream)
-{
-	unsigned long flags;
-
-	spin_lock_irqsave(&portman->reg_lock, flags);
-	portman->midi_output_mode[substream->number] &=
-	    ~PORTMAN2X4_MODE_OUTPUT_OPENED;
-	portman->midi_output[substream->number] = NULL;
-	spin_unlock_irqrestore(&portman->reg_lock, flags);
-	return 0;
-}
-
-static void snd_portman_midi_input_trigger(struct snd_rawmidi_substream *
-					   substream, int up)
-{
-	unsigned long flags;
-
-	spin_lock_irqsave(&portman->reg_lock, flags);
+
+	spin_lock_irqsave(&pm->reg_lock, flags);
 	if (up) {
-		portman->midi_input_mode[substream->number] |=
-		    PORTMAN2X4_MODE_INPUT_TRIGGERED;
+		pm->mode[substream->number] |= PORTMAN2X4_MODE_INPUT_TRIGGERED;
 	} else {
-		portman->midi_input_mode[substream->number] &=
-		    ~PORTMAN2X4_MODE_INPUT_TRIGGERED;
-	}
-	spin_unlock_irqrestore(&portman->reg_lock, flags);
-}
-
-static void snd_portman_midi_output_trigger(struct snd_rawmidi_substream *
-					    substream, int up)
-{
+		pm->mode[substream->number] &= ~PORTMAN2X4_MODE_INPUT_TRIGGERED;
+	}
+	spin_unlock_irqrestore(&pm->reg_lock, flags);
+}
+
+static void snd_portman_midi_output_trigger(struct snd_rawmidi_substream *substream,
+					    int up)
+{
+	struct portman *pm = substream->rmidi->private_data;
 	unsigned long flags;
 	unsigned char byte = 0;
 
-	spin_lock_irqsave(&portman->reg_lock, flags);
+	spin_lock_irqsave(&pm->reg_lock, flags);
 	if (up) {
 		while ((snd_rawmidi_transmit(substream, &byte, 1) == 1))
-		  portman_putmidi(substream->number, byte);
-	}
-	spin_unlock_irqrestore(&portman->reg_lock, flags);
+			portman_write_midi(pm, substream->number, byte);
+	}
+	spin_unlock_irqrestore(&pm->reg_lock, flags);
 }
 
 static struct snd_rawmidi_ops snd_portman_midi_output = {
-	.open =		snd_portman_midi_output_open,
-	.close =	snd_portman_midi_output_close,
+	.open =		NULL,
+	.close =	NULL,
 	.trigger =	snd_portman_midi_output_trigger,
 };
 
 static struct snd_rawmidi_ops snd_portman_midi_input = {
-	.open =		snd_portman_midi_input_open,
-	.close =	snd_portman_midi_input_close,
+	.open =		NULL,
+	.close =	NULL,
 	.trigger =	snd_portman_midi_input_trigger,
 };
 
-static int __init snd_portman_midi(portman_t * portman, int device,
-				   struct snd_rawmidi ** rrawmidi)
-{
+/* Create and initialize the rawmidi component */
+static int __devinit snd_portman_rawmidi_create(struct snd_card *card)
+{
+	struct portman *pm = card->private_data;
 	struct snd_rawmidi *rmidi;
+	struct snd_rawmidi_substream *substream;
+	struct list_head *list;
 	int err;
-
-	if (rrawmidi)
-		*rrawmidi = NULL;
-
-	if ((err =
-	     snd_rawmidi_new(portman->card, "Portman2x4", device, 4, 2,
-			     &rmidi)) < 0)
+	
+	err = snd_rawmidi_new(card, CARD_NAME, 0, 
+			      PORTMAN_NUM_OUTPUT_PORTS, 
+			      PORTMAN_NUM_INPUT_PORTS, 
+			      &rmidi);
+	if (err < 0) 
 		return err;
 
-	strcpy(rmidi->name, "Portman2x4");
-	snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_OUTPUT,
+	rmidi->private_data = pm;
+	strcpy(rmidi->name, CARD_NAME);
+	rmidi->info_flags = SNDRV_RAWMIDI_INFO_OUTPUT |
+		            SNDRV_RAWMIDI_INFO_INPUT |
+                            SNDRV_RAWMIDI_INFO_DUPLEX;
+
+	pm->rmidi = rmidi;
+
+	/* register rawmidi ops */
+	snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_OUTPUT, 
 			    &snd_portman_midi_output);
-	snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_INPUT,
+	snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_INPUT, 
 			    &snd_portman_midi_input);
-	rmidi->info_flags |=
-	    SNDRV_RAWMIDI_INFO_OUTPUT | SNDRV_RAWMIDI_INFO_INPUT |
-	    SNDRV_RAWMIDI_INFO_DUPLEX;
-	rmidi->private_data = portman;
-	portman->rmidi = rmidi;
-	if (rrawmidi)
-		*rrawmidi = rmidi;
-	return 0;
-}
-
-
-/* init midiman portman */
-
-static int __init alsa_card_portman2x4_init(void)
-{
-	/* LOCAL VARIABLES */
-	static int dev = 0;
-	struct snd_card *card;
+
+	/* name substreams */
+	/* output */
+	list_for_each(list, 
+		      &rmidi->streams[SNDRV_RAWMIDI_STREAM_OUTPUT].substreams) {
+		substream = list_entry(list, struct snd_rawmidi_substream, list);
+		sprintf(substream->name,
+			"Portman2x4 %d", substream->number+1);
+	}
+	/* input */
+	list_for_each(list, 
+		      &rmidi->streams[SNDRV_RAWMIDI_STREAM_INPUT].substreams) {
+		substream = list_entry(list, struct snd_rawmidi_substream, list);
+		pm->midi_input[substream->number] = substream;
+		sprintf(substream->name,
+			"Portman2x4 %d", substream->number+1);
+	}
+
+	return err;
+}
+
+/*********************************************************************
+ * parport stuff
+ *********************************************************************/
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 19)
+static void snd_portman_interrupt(int irq, void *userdata)
+#else
+static void snd_portman_interrupt(int irq, void *userdata, struct pt_regs *regs)
+#endif
+{
+	unsigned long flags;
+	unsigned char midivalue = 0;
+	struct portman *pm = ((struct snd_card*)userdata)->private_data;
+
+	spin_lock_irqsave(&pm->reg_lock, flags);
+
+	/* While any input data is waiting */
+	while ((portman_read_status(pm) & INT_REQ) == INT_REQ) {
+		/* If data available on channel 0, 
+		   read it and stuff it into the queue. */
+		if (portman_data_avail(pm, 0)) {
+			/* Read Midi */
+			midivalue = portman_read_midi(pm, 0);
+			/* put midi into queue... */
+			if (pm->mode[0] & PORTMAN2X4_MODE_INPUT_TRIGGERED)
+				snd_rawmidi_receive(pm->midi_input[0],
+						    &midivalue, 1);
+
+		}
+		/* If data available on channel 1, 
+		   read it and stuff it into the queue. */
+		if (portman_data_avail(pm, 1)) {
+			/* Read Midi */
+			midivalue = portman_read_midi(pm, 1);
+			/* put midi into queue... */
+			if (pm->mode[1] & PORTMAN2X4_MODE_INPUT_TRIGGERED)
+				snd_rawmidi_receive(pm->midi_input[1],
+						    &midivalue, 1);
+		}
+
+	}
+
+	spin_unlock_irqrestore(&pm->reg_lock, flags);
+}
+
+static int __devinit snd_portman_probe_port(struct parport *p)
+{
+	struct pardevice *pardev;
+	int res;
+
+	pardev = parport_register_device(p, DRIVER_NAME,
+					 NULL, NULL, NULL,
+					 0, NULL);
+	if (!pardev)
+		return -EIO;
+	
+	if (parport_claim(pardev)) {
+		parport_unregister_device(pardev);
+		return -EIO;
+	}
+
+	res = portman_probe(p);
+
+	parport_release(pardev);
+	parport_unregister_device(pardev);
+
+	return res;
+}
+
+static void __devinit snd_portman_attach(struct parport *p)
+{
+	struct platform_device *device;
+
+	device = platform_device_alloc(PLATFORM_DRIVER, device_count);
+	if (!device) 
+		return;
+
+	/* Temporary assignment to forward the parport */
+	platform_set_drvdata(device, p);
+
+	if (platform_device_register(device) < 0) {
+		platform_device_put(device);
+		return;
+	}
+
+	/* Since we dont get the return value of probe
+	 * We need to check if device probing succeeded or not */
+	if (!platform_get_drvdata(device)) {
+		platform_device_unregister(device);
+		return;
+	}
+
+	/* register device in global table */
+	platform_devices[device_count] = device;
+	device_count++;
+}
+
+static void snd_portman_detach(struct parport *p)
+{
+	/* nothing to do here */
+}
+
+static struct parport_driver portman_parport_driver = {
+	.name   = "portman2x4",
+	.attach = snd_portman_attach,
+	.detach = snd_portman_detach
+};
+
+/*********************************************************************
+ * platform stuff
+ *********************************************************************/
+static void snd_portman_card_private_free(struct snd_card *card)
+{
+	struct portman *pm = card->private_data;
+	struct pardevice *pardev = pm->pardev;
+
+	if (pardev) {
+		if (pm->pardev_claimed)
+			parport_release(pardev);
+		parport_unregister_device(pardev);
+	}
+
+	portman_free(pm);
+}
+
+static int __devinit snd_portman_probe(struct platform_device *pdev)
+{
+	struct pardevice *pardev;
+	struct parport *p;
+	int dev = pdev->id;
+	struct snd_card *card = NULL;
+	struct portman *pm = NULL;
 	int err;
-	int result = 0;
-
-	/* Display copyright notice and driver version */
-	snd_printk("Driverversion is: %s\n", sVersion);
-
-	portman = kzalloc(sizeof(portman_t), GFP_KERNEL);
-	if (portman == NULL) {
-		snd_printk
-		    ("Error allocating memory for portman. Exiting.\n");
-		return 1;
-	}
-
-	spin_lock_init(&portman->reg_lock);
-
-	portman->midi_input_mode[0] = 0;
-	portman->midi_input_mode[1] = 0;
-	portman->midi_output_mode[0] = 0;
-	portman->midi_output_mode[1] = 0;
-	portman->midi_output_mode[2] = 0;
-	portman->midi_output_mode[3] = 0;
-
-	/* Initialize parport */
-	/* Register a new high-level driver. */
-	result = parport_register_driver(&portman_driver);
-
-	/* Test if there is a portman available. Exit if not. */
-	if (portman_found == 0) {
-		snd_printk("Portman not found. Exiting.\n");
-		parport_unregister_driver(&portman_driver);
-		return 1;
-	}
-
-	for (; dev < SNDRV_CARDS; dev++) {
-		if (!enable[dev]) {
-			dev++;
-			snd_printk("Could not enable card. Exiting.\n");
-			cleanup();
-			return -ENOENT;
-		}
-		break;
-	}
-
-	if (dev >= SNDRV_CARDS) {
-		snd_printk("Could not enable card. Exiting.\n");
-		cleanup();
+
+	p = platform_get_drvdata(pdev);
+	platform_set_drvdata(pdev, NULL);
+
+	if (dev >= SNDRV_CARDS)
 		return -ENODEV;
-	}
-
-	/* alsa: create new sound card */
+	if (!enable[dev]) 
+		return -ENOENT;
+
+	if ((err = snd_portman_probe_port(p)) < 0)
+		return err;
+
 	card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0);
 	if (card == NULL) {
-		snd_printk
-		    ("Fatal. Cannot allocate memory for sound card. Exiting.\n");
-		cleanup();
+		snd_printd("Cannot create card\n");
 		return -ENOMEM;
 	}
-
-	portman->card = card;
-
-	/* register midi functions */
-	if ((err = snd_portman_midi(portman, 0, NULL)) < 0) {
+	strcpy(card->driver, DRIVER_NAME);
+	strcpy(card->shortname, CARD_NAME);
+	sprintf(card->longname,  "%s at 0x%lx, irq %i", 
+		card->shortname, p->base, p->irq);
+
+	pardev = parport_register_device(p,                     /* port */
+					 DRIVER_NAME,           /* name */
+					 NULL,                  /* preempt */
+					 NULL,                  /* wakeup */
+					 snd_portman_interrupt, /* ISR */
+					 PARPORT_DEV_EXCL,      /* flags */
+					 (void *)card);         /* private */
+	if (pardev == NULL) {
+		snd_printd("Cannot register pardevice\n");
+		err = -EIO;
+		goto __err;
+	}
+
+	if ((err = portman_create(card, pardev, &pm)) < 0) {
+		snd_printd("Cannot create main component\n");
+		parport_unregister_device(pardev);
+		goto __err;
+	}
+	card->private_data = pm;
+	card->private_free = snd_portman_card_private_free;
+	
+	if ((err = snd_portman_rawmidi_create(card)) < 0) {
+		snd_printd("Creating Rawmidi component failed\n");
+		goto __err;
+	}
+
+	/* claim parport */
+	if (parport_claim(pardev)) {
+		snd_printd("Cannot claim parport 0x%lx\n", pardev->port->base);
+		err = -EIO;
+		goto __err;
+	}
+	pm->pardev_claimed = 1;
+
+	/* init device */
+	if ((err = portman_device_init(pm)) < 0)
+		goto __err;
+
+	platform_set_drvdata(pdev, card);
+
+	/* At this point card will be usable */
+	if ((err = snd_card_register(card)) < 0) {
+		snd_printd("Cannot register card\n");
+		goto __err;
+	}
+
+	snd_printk("Portman 2x4 on 0x%lx\n", p->base);
+	return 0;
+
+__err:
+	snd_card_free(card);
+	return err;
+}
+
+static int snd_portman_remove(struct platform_device *pdev)
+{
+	struct snd_card *card = platform_get_drvdata(pdev);
+
+	if (card)
 		snd_card_free(card);
+
+	return 0;
+}
+
+
+static struct platform_driver snd_portman_driver = {
+	.probe  = snd_portman_probe,
+	.remove = snd_portman_remove,
+	.driver = {
+		.name = PLATFORM_DRIVER
+	}
+};
+
+/*********************************************************************
+ * module init stuff
+ *********************************************************************/
+static void snd_portman_unregister_all(void)
+{
+	int i;
+
+	for (i = 0; i < SNDRV_CARDS; ++i) {
+		if (platform_devices[i]) {
+			platform_device_unregister(platform_devices[i]);
+			platform_devices[i] = NULL;
+		}
+	}		
+	platform_driver_unregister(&snd_portman_driver);
+	parport_unregister_driver(&portman_parport_driver);
+}
+
+static int __init snd_portman_module_init(void)
+{
+	int err;
+
+	if ((err = platform_driver_register(&snd_portman_driver)) < 0)
 		return err;
-	}
-	strcpy(card->driver, "Portman");
-	strcpy(card->shortname, "Portman2x4");
-	sprintf(card->longname, "%s %s at 0x%lx, irq %i",
-		card->shortname, "2x4", portman->port, portman->irq);
-
-	if ((err = snd_card_register(card)) < 0) {
-		snd_card_free(card);
-		return err;
-	}
-
-	dev++;
+
+	if (parport_register_driver(&portman_parport_driver) != 0) {
+		platform_driver_unregister(&snd_portman_driver);
+		return -EIO;
+	}
+
+	if (device_count == 0) {
+		snd_portman_unregister_all();
+		return -ENODEV;
+	}
+
 	return 0;
 }
 
-static void __exit alsa_card_portman2x4_exit(void)
-{
-	if (portman == NULL)
-		return;
-	if (portman->card)
-		snd_card_free(portman->card);
-	cleanup();
-	parport_unregister_driver(&portman_driver);
-}
-
-module_init(alsa_card_portman2x4_init)
-module_exit(alsa_card_portman2x4_exit)
+static void __exit snd_portman_module_exit(void)
+{
+	snd_portman_unregister_all();
+}
+
+module_init(snd_portman_module_init);
+module_exit(snd_portman_module_exit);
-------------------------------------------------------------------------
Take Surveys. Earn Cash. Influence the Future of IT
Join SourceForge.net's Techsay panel and you'll get the chance to share your
opinions on IT & business topics through brief surveys - and earn cash
http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV
_______________________________________________
Alsa-devel mailing list
Alsa-devel@xxxxxxxxxxxxxxxxxxxxx
https://lists.sourceforge.net/lists/listinfo/alsa-devel

[Index of Archives]     [ALSA User]     [Linux Audio Users]     [Kernel Archive]     [Asterisk PBX]     [Photo Sharing]     [Linux Sound]     [Video 4 Linux]     [Gimp]     [Yosemite News]

  Powered by Linux