1*757e119bSMatthias Koenig /* 2*757e119bSMatthias Koenig * Driver for Midiman Portman2x4 parallel port midi interface 3*757e119bSMatthias Koenig * 4*757e119bSMatthias Koenig * Copyright (c) by Levent Guendogdu <levon@feature-it.com> 5*757e119bSMatthias Koenig * 6*757e119bSMatthias Koenig * This program is free software; you can redistribute it and/or modify 7*757e119bSMatthias Koenig * it under the terms of the GNU General Public License as published by 8*757e119bSMatthias Koenig * the Free Software Foundation; either version 2 of the License, or 9*757e119bSMatthias Koenig * (at your option) any later version. 10*757e119bSMatthias Koenig * 11*757e119bSMatthias Koenig * This program is distributed in the hope that it will be useful, 12*757e119bSMatthias Koenig * but WITHOUT ANY WARRANTY; without even the implied warranty of 13*757e119bSMatthias Koenig * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14*757e119bSMatthias Koenig * GNU General Public License for more details. 15*757e119bSMatthias Koenig * 16*757e119bSMatthias Koenig * You should have received a copy of the GNU General Public License 17*757e119bSMatthias Koenig * along with this program; if not, write to the Free Software 18*757e119bSMatthias Koenig * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 19*757e119bSMatthias Koenig * 20*757e119bSMatthias Koenig * ChangeLog 21*757e119bSMatthias Koenig * Jan 24 2007 Matthias Koenig <mkoenig@suse.de> 22*757e119bSMatthias Koenig * - cleanup and rewrite 23*757e119bSMatthias Koenig * Sep 30 2004 Tobias Gehrig <tobias@gehrig.tk> 24*757e119bSMatthias Koenig * - source code cleanup 25*757e119bSMatthias Koenig * Sep 03 2004 Tobias Gehrig <tobias@gehrig.tk> 26*757e119bSMatthias Koenig * - fixed compilation problem with alsa 1.0.6a (removed MODULE_CLASSES, 27*757e119bSMatthias Koenig * MODULE_PARM_SYNTAX and changed MODULE_DEVICES to 28*757e119bSMatthias Koenig * MODULE_SUPPORTED_DEVICE) 29*757e119bSMatthias Koenig * Mar 24 2004 Tobias Gehrig <tobias@gehrig.tk> 30*757e119bSMatthias Koenig * - added 2.6 kernel support 31*757e119bSMatthias Koenig * Mar 18 2004 Tobias Gehrig <tobias@gehrig.tk> 32*757e119bSMatthias Koenig * - added parport_unregister_driver to the startup routine if the driver fails to detect a portman 33*757e119bSMatthias Koenig * - added support for all 4 output ports in portman_putmidi 34*757e119bSMatthias Koenig * Mar 17 2004 Tobias Gehrig <tobias@gehrig.tk> 35*757e119bSMatthias Koenig * - added checks for opened input device in interrupt handler 36*757e119bSMatthias Koenig * Feb 20 2004 Tobias Gehrig <tobias@gehrig.tk> 37*757e119bSMatthias Koenig * - ported from alsa 0.5 to 1.0 38*757e119bSMatthias Koenig */ 39*757e119bSMatthias Koenig 40*757e119bSMatthias Koenig #include <sound/driver.h> 41*757e119bSMatthias Koenig #include <linux/init.h> 42*757e119bSMatthias Koenig #include <linux/platform_device.h> 43*757e119bSMatthias Koenig #include <linux/parport.h> 44*757e119bSMatthias Koenig #include <linux/spinlock.h> 45*757e119bSMatthias Koenig #include <linux/delay.h> 46*757e119bSMatthias Koenig #include <sound/core.h> 47*757e119bSMatthias Koenig #include <sound/initval.h> 48*757e119bSMatthias Koenig #include <sound/rawmidi.h> 49*757e119bSMatthias Koenig #include <sound/control.h> 50*757e119bSMatthias Koenig 51*757e119bSMatthias Koenig #define CARD_NAME "Portman 2x4" 52*757e119bSMatthias Koenig #define DRIVER_NAME "portman" 53*757e119bSMatthias Koenig #define PLATFORM_DRIVER "snd_portman2x4" 54*757e119bSMatthias Koenig 55*757e119bSMatthias Koenig static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; 56*757e119bSMatthias Koenig static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; 57*757e119bSMatthias Koenig static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; 58*757e119bSMatthias Koenig 59*757e119bSMatthias Koenig static struct platform_device *platform_devices[SNDRV_CARDS]; 60*757e119bSMatthias Koenig static int device_count; 61*757e119bSMatthias Koenig 62*757e119bSMatthias Koenig module_param_array(index, int, NULL, S_IRUGO); 63*757e119bSMatthias Koenig MODULE_PARM_DESC(index, "Index value for " CARD_NAME " soundcard."); 64*757e119bSMatthias Koenig module_param_array(id, charp, NULL, S_IRUGO); 65*757e119bSMatthias Koenig MODULE_PARM_DESC(id, "ID string for " CARD_NAME " soundcard."); 66*757e119bSMatthias Koenig module_param_array(enable, bool, NULL, S_IRUGO); 67*757e119bSMatthias Koenig MODULE_PARM_DESC(enable, "Enable " CARD_NAME " soundcard."); 68*757e119bSMatthias Koenig 69*757e119bSMatthias Koenig MODULE_AUTHOR("Levent Guendogdu, Tobias Gehrig, Matthias Koenig"); 70*757e119bSMatthias Koenig MODULE_DESCRIPTION("Midiman Portman2x4"); 71*757e119bSMatthias Koenig MODULE_LICENSE("GPL"); 72*757e119bSMatthias Koenig MODULE_SUPPORTED_DEVICE("{{Midiman,Portman2x4}}"); 73*757e119bSMatthias Koenig 74*757e119bSMatthias Koenig /********************************************************************* 75*757e119bSMatthias Koenig * Chip specific 76*757e119bSMatthias Koenig *********************************************************************/ 77*757e119bSMatthias Koenig #define PORTMAN_NUM_INPUT_PORTS 2 78*757e119bSMatthias Koenig #define PORTMAN_NUM_OUTPUT_PORTS 4 79*757e119bSMatthias Koenig 80*757e119bSMatthias Koenig struct portman { 81*757e119bSMatthias Koenig spinlock_t reg_lock; 82*757e119bSMatthias Koenig struct snd_card *card; 83*757e119bSMatthias Koenig struct snd_rawmidi *rmidi; 84*757e119bSMatthias Koenig struct pardevice *pardev; 85*757e119bSMatthias Koenig int pardev_claimed; 86*757e119bSMatthias Koenig 87*757e119bSMatthias Koenig int open_count; 88*757e119bSMatthias Koenig int mode[PORTMAN_NUM_INPUT_PORTS]; 89*757e119bSMatthias Koenig struct snd_rawmidi_substream *midi_input[PORTMAN_NUM_INPUT_PORTS]; 90*757e119bSMatthias Koenig }; 91*757e119bSMatthias Koenig 92*757e119bSMatthias Koenig static int portman_free(struct portman *pm) 93*757e119bSMatthias Koenig { 94*757e119bSMatthias Koenig kfree(pm); 95*757e119bSMatthias Koenig return 0; 96*757e119bSMatthias Koenig } 97*757e119bSMatthias Koenig 98*757e119bSMatthias Koenig static int __devinit portman_create(struct snd_card *card, 99*757e119bSMatthias Koenig struct pardevice *pardev, 100*757e119bSMatthias Koenig struct portman **rchip) 101*757e119bSMatthias Koenig { 102*757e119bSMatthias Koenig struct portman *pm; 103*757e119bSMatthias Koenig 104*757e119bSMatthias Koenig *rchip = NULL; 105*757e119bSMatthias Koenig 106*757e119bSMatthias Koenig pm = kzalloc(sizeof(struct portman), GFP_KERNEL); 107*757e119bSMatthias Koenig if (pm == NULL) 108*757e119bSMatthias Koenig return -ENOMEM; 109*757e119bSMatthias Koenig 110*757e119bSMatthias Koenig /* Init chip specific data */ 111*757e119bSMatthias Koenig spin_lock_init(&pm->reg_lock); 112*757e119bSMatthias Koenig pm->card = card; 113*757e119bSMatthias Koenig pm->pardev = pardev; 114*757e119bSMatthias Koenig 115*757e119bSMatthias Koenig *rchip = pm; 116*757e119bSMatthias Koenig 117*757e119bSMatthias Koenig return 0; 118*757e119bSMatthias Koenig } 119*757e119bSMatthias Koenig 120*757e119bSMatthias Koenig /********************************************************************* 121*757e119bSMatthias Koenig * HW related constants 122*757e119bSMatthias Koenig *********************************************************************/ 123*757e119bSMatthias Koenig 124*757e119bSMatthias Koenig /* Standard PC parallel port status register equates. */ 125*757e119bSMatthias Koenig #define PP_STAT_BSY 0x80 /* Busy status. Inverted. */ 126*757e119bSMatthias Koenig #define PP_STAT_ACK 0x40 /* Acknowledge. Non-Inverted. */ 127*757e119bSMatthias Koenig #define PP_STAT_POUT 0x20 /* Paper Out. Non-Inverted. */ 128*757e119bSMatthias Koenig #define PP_STAT_SEL 0x10 /* Select. Non-Inverted. */ 129*757e119bSMatthias Koenig #define PP_STAT_ERR 0x08 /* Error. Non-Inverted. */ 130*757e119bSMatthias Koenig 131*757e119bSMatthias Koenig /* Standard PC parallel port command register equates. */ 132*757e119bSMatthias Koenig #define PP_CMD_IEN 0x10 /* IRQ Enable. Non-Inverted. */ 133*757e119bSMatthias Koenig #define PP_CMD_SELI 0x08 /* Select Input. Inverted. */ 134*757e119bSMatthias Koenig #define PP_CMD_INIT 0x04 /* Init Printer. Non-Inverted. */ 135*757e119bSMatthias Koenig #define PP_CMD_FEED 0x02 /* Auto Feed. Inverted. */ 136*757e119bSMatthias Koenig #define PP_CMD_STB 0x01 /* Strobe. Inverted. */ 137*757e119bSMatthias Koenig 138*757e119bSMatthias Koenig /* Parallel Port Command Register as implemented by PCP2x4. */ 139*757e119bSMatthias Koenig #define INT_EN PP_CMD_IEN /* Interrupt enable. */ 140*757e119bSMatthias Koenig #define STROBE PP_CMD_STB /* Command strobe. */ 141*757e119bSMatthias Koenig 142*757e119bSMatthias Koenig /* The parallel port command register field (b1..b3) selects the 143*757e119bSMatthias Koenig * various "registers" within the PC/P 2x4. These are the internal 144*757e119bSMatthias Koenig * address of these "registers" that must be written to the parallel 145*757e119bSMatthias Koenig * port command register. 146*757e119bSMatthias Koenig */ 147*757e119bSMatthias Koenig #define RXDATA0 (0 << 1) /* PCP RxData channel 0. */ 148*757e119bSMatthias Koenig #define RXDATA1 (1 << 1) /* PCP RxData channel 1. */ 149*757e119bSMatthias Koenig #define GEN_CTL (2 << 1) /* PCP General Control Register. */ 150*757e119bSMatthias Koenig #define SYNC_CTL (3 << 1) /* PCP Sync Control Register. */ 151*757e119bSMatthias Koenig #define TXDATA0 (4 << 1) /* PCP TxData channel 0. */ 152*757e119bSMatthias Koenig #define TXDATA1 (5 << 1) /* PCP TxData channel 1. */ 153*757e119bSMatthias Koenig #define TXDATA2 (6 << 1) /* PCP TxData channel 2. */ 154*757e119bSMatthias Koenig #define TXDATA3 (7 << 1) /* PCP TxData channel 3. */ 155*757e119bSMatthias Koenig 156*757e119bSMatthias Koenig /* Parallel Port Status Register as implemented by PCP2x4. */ 157*757e119bSMatthias Koenig #define ESTB PP_STAT_POUT /* Echoed strobe. */ 158*757e119bSMatthias Koenig #define INT_REQ PP_STAT_ACK /* Input data int request. */ 159*757e119bSMatthias Koenig #define BUSY PP_STAT_ERR /* Interface Busy. */ 160*757e119bSMatthias Koenig 161*757e119bSMatthias Koenig /* Parallel Port Status Register BUSY and SELECT lines are multiplexed 162*757e119bSMatthias Koenig * between several functions. Depending on which 2x4 "register" is 163*757e119bSMatthias Koenig * currently selected (b1..b3), the BUSY and SELECT lines are 164*757e119bSMatthias Koenig * assigned as follows: 165*757e119bSMatthias Koenig * 166*757e119bSMatthias Koenig * SELECT LINE: A3 A2 A1 167*757e119bSMatthias Koenig * -------- 168*757e119bSMatthias Koenig */ 169*757e119bSMatthias Koenig #define RXAVAIL PP_STAT_SEL /* Rx Available, channel 0. 0 0 0 */ 170*757e119bSMatthias Koenig // RXAVAIL1 PP_STAT_SEL /* Rx Available, channel 1. 0 0 1 */ 171*757e119bSMatthias Koenig #define SYNC_STAT PP_STAT_SEL /* Reserved - Sync Status. 0 1 0 */ 172*757e119bSMatthias Koenig // /* Reserved. 0 1 1 */ 173*757e119bSMatthias Koenig #define TXEMPTY PP_STAT_SEL /* Tx Empty, channel 0. 1 0 0 */ 174*757e119bSMatthias Koenig // TXEMPTY1 PP_STAT_SEL /* Tx Empty, channel 1. 1 0 1 */ 175*757e119bSMatthias Koenig // TXEMPTY2 PP_STAT_SEL /* Tx Empty, channel 2. 1 1 0 */ 176*757e119bSMatthias Koenig // TXEMPTY3 PP_STAT_SEL /* Tx Empty, channel 3. 1 1 1 */ 177*757e119bSMatthias Koenig 178*757e119bSMatthias Koenig /* BUSY LINE: A3 A2 A1 179*757e119bSMatthias Koenig * -------- 180*757e119bSMatthias Koenig */ 181*757e119bSMatthias Koenig #define RXDATA PP_STAT_BSY /* Rx Input Data, channel 0. 0 0 0 */ 182*757e119bSMatthias Koenig // RXDATA1 PP_STAT_BSY /* Rx Input Data, channel 1. 0 0 1 */ 183*757e119bSMatthias Koenig #define SYNC_DATA PP_STAT_BSY /* Reserved - Sync Data. 0 1 0 */ 184*757e119bSMatthias Koenig /* Reserved. 0 1 1 */ 185*757e119bSMatthias Koenig #define DATA_ECHO PP_STAT_BSY /* Parallel Port Data Echo. 1 0 0 */ 186*757e119bSMatthias Koenig #define A0_ECHO PP_STAT_BSY /* Address 0 Echo. 1 0 1 */ 187*757e119bSMatthias Koenig #define A1_ECHO PP_STAT_BSY /* Address 1 Echo. 1 1 0 */ 188*757e119bSMatthias Koenig #define A2_ECHO PP_STAT_BSY /* Address 2 Echo. 1 1 1 */ 189*757e119bSMatthias Koenig 190*757e119bSMatthias Koenig #define PORTMAN2X4_MODE_INPUT_TRIGGERED 0x01 191*757e119bSMatthias Koenig 192*757e119bSMatthias Koenig /********************************************************************* 193*757e119bSMatthias Koenig * Hardware specific functions 194*757e119bSMatthias Koenig *********************************************************************/ 195*757e119bSMatthias Koenig static inline void portman_write_command(struct portman *pm, u8 value) 196*757e119bSMatthias Koenig { 197*757e119bSMatthias Koenig parport_write_control(pm->pardev->port, value); 198*757e119bSMatthias Koenig } 199*757e119bSMatthias Koenig 200*757e119bSMatthias Koenig static inline u8 portman_read_command(struct portman *pm) 201*757e119bSMatthias Koenig { 202*757e119bSMatthias Koenig return parport_read_control(pm->pardev->port); 203*757e119bSMatthias Koenig } 204*757e119bSMatthias Koenig 205*757e119bSMatthias Koenig static inline u8 portman_read_status(struct portman *pm) 206*757e119bSMatthias Koenig { 207*757e119bSMatthias Koenig return parport_read_status(pm->pardev->port); 208*757e119bSMatthias Koenig } 209*757e119bSMatthias Koenig 210*757e119bSMatthias Koenig static inline u8 portman_read_data(struct portman *pm) 211*757e119bSMatthias Koenig { 212*757e119bSMatthias Koenig return parport_read_data(pm->pardev->port); 213*757e119bSMatthias Koenig } 214*757e119bSMatthias Koenig 215*757e119bSMatthias Koenig static inline void portman_write_data(struct portman *pm, u8 value) 216*757e119bSMatthias Koenig { 217*757e119bSMatthias Koenig parport_write_data(pm->pardev->port, value); 218*757e119bSMatthias Koenig } 219*757e119bSMatthias Koenig 220*757e119bSMatthias Koenig static void portman_write_midi(struct portman *pm, 221*757e119bSMatthias Koenig int port, u8 mididata) 222*757e119bSMatthias Koenig { 223*757e119bSMatthias Koenig int command = ((port + 4) << 1); 224*757e119bSMatthias Koenig 225*757e119bSMatthias Koenig /* Get entering data byte and port number in BL and BH respectively. 226*757e119bSMatthias Koenig * Set up Tx Channel address field for use with PP Cmd Register. 227*757e119bSMatthias Koenig * Store address field in BH register. 228*757e119bSMatthias Koenig * Inputs: AH = Output port number (0..3). 229*757e119bSMatthias Koenig * AL = Data byte. 230*757e119bSMatthias Koenig * command = TXDATA0 | INT_EN; 231*757e119bSMatthias Koenig * Align port num with address field (b1...b3), 232*757e119bSMatthias Koenig * set address for TXDatax, Strobe=0 233*757e119bSMatthias Koenig */ 234*757e119bSMatthias Koenig command |= INT_EN; 235*757e119bSMatthias Koenig 236*757e119bSMatthias Koenig /* Disable interrupts so that the process is not interrupted, then 237*757e119bSMatthias Koenig * write the address associated with the current Tx channel to the 238*757e119bSMatthias Koenig * PP Command Reg. Do not set the Strobe signal yet. 239*757e119bSMatthias Koenig */ 240*757e119bSMatthias Koenig 241*757e119bSMatthias Koenig do { 242*757e119bSMatthias Koenig portman_write_command(pm, command); 243*757e119bSMatthias Koenig 244*757e119bSMatthias Koenig /* While the address lines settle, write parallel output data to 245*757e119bSMatthias Koenig * PP Data Reg. This has no effect until Strobe signal is asserted. 246*757e119bSMatthias Koenig */ 247*757e119bSMatthias Koenig 248*757e119bSMatthias Koenig portman_write_data(pm, mididata); 249*757e119bSMatthias Koenig 250*757e119bSMatthias Koenig /* If PCP channel's TxEmpty is set (TxEmpty is read through the PP 251*757e119bSMatthias Koenig * Status Register), then go write data. Else go back and wait. 252*757e119bSMatthias Koenig */ 253*757e119bSMatthias Koenig } while ((portman_read_status(pm) & TXEMPTY) != TXEMPTY); 254*757e119bSMatthias Koenig 255*757e119bSMatthias Koenig /* TxEmpty is set. Maintain PC/P destination address and assert 256*757e119bSMatthias Koenig * Strobe through the PP Command Reg. This will Strobe data into 257*757e119bSMatthias Koenig * the PC/P transmitter and set the PC/P BUSY signal. 258*757e119bSMatthias Koenig */ 259*757e119bSMatthias Koenig 260*757e119bSMatthias Koenig portman_write_command(pm, command | STROBE); 261*757e119bSMatthias Koenig 262*757e119bSMatthias Koenig /* Wait for strobe line to settle and echo back through hardware. 263*757e119bSMatthias Koenig * Once it has echoed back, assume that the address and data lines 264*757e119bSMatthias Koenig * have settled! 265*757e119bSMatthias Koenig */ 266*757e119bSMatthias Koenig 267*757e119bSMatthias Koenig while ((portman_read_status(pm) & ESTB) == 0) 268*757e119bSMatthias Koenig cpu_relax(); 269*757e119bSMatthias Koenig 270*757e119bSMatthias Koenig /* Release strobe and immediately re-allow interrupts. */ 271*757e119bSMatthias Koenig portman_write_command(pm, command); 272*757e119bSMatthias Koenig 273*757e119bSMatthias Koenig while ((portman_read_status(pm) & ESTB) == ESTB) 274*757e119bSMatthias Koenig cpu_relax(); 275*757e119bSMatthias Koenig 276*757e119bSMatthias Koenig /* PC/P BUSY is now set. We must wait until BUSY resets itself. 277*757e119bSMatthias Koenig * We'll reenable ints while we're waiting. 278*757e119bSMatthias Koenig */ 279*757e119bSMatthias Koenig 280*757e119bSMatthias Koenig while ((portman_read_status(pm) & BUSY) == BUSY) 281*757e119bSMatthias Koenig cpu_relax(); 282*757e119bSMatthias Koenig 283*757e119bSMatthias Koenig /* Data sent. */ 284*757e119bSMatthias Koenig } 285*757e119bSMatthias Koenig 286*757e119bSMatthias Koenig 287*757e119bSMatthias Koenig /* 288*757e119bSMatthias Koenig * Read MIDI byte from port 289*757e119bSMatthias Koenig * Attempt to read input byte from specified hardware input port (0..). 290*757e119bSMatthias Koenig * Return -1 if no data 291*757e119bSMatthias Koenig */ 292*757e119bSMatthias Koenig static int portman_read_midi(struct portman *pm, int port) 293*757e119bSMatthias Koenig { 294*757e119bSMatthias Koenig unsigned char midi_data = 0; 295*757e119bSMatthias Koenig unsigned char cmdout; /* Saved address+IE bit. */ 296*757e119bSMatthias Koenig 297*757e119bSMatthias Koenig /* Make sure clocking edge is down before starting... */ 298*757e119bSMatthias Koenig portman_write_data(pm, 0); /* Make sure edge is down. */ 299*757e119bSMatthias Koenig 300*757e119bSMatthias Koenig /* Set destination address to PCP. */ 301*757e119bSMatthias Koenig cmdout = (port << 1) | INT_EN; /* Address + IE + No Strobe. */ 302*757e119bSMatthias Koenig portman_write_command(pm, cmdout); 303*757e119bSMatthias Koenig 304*757e119bSMatthias Koenig while ((portman_read_status(pm) & ESTB) == ESTB) 305*757e119bSMatthias Koenig cpu_relax(); /* Wait for strobe echo. */ 306*757e119bSMatthias Koenig 307*757e119bSMatthias Koenig /* After the address lines settle, check multiplexed RxAvail signal. 308*757e119bSMatthias Koenig * If data is available, read it. 309*757e119bSMatthias Koenig */ 310*757e119bSMatthias Koenig if ((portman_read_status(pm) & RXAVAIL) == 0) 311*757e119bSMatthias Koenig return -1; /* No data. */ 312*757e119bSMatthias Koenig 313*757e119bSMatthias Koenig /* Set the Strobe signal to enable the Rx clocking circuitry. */ 314*757e119bSMatthias Koenig portman_write_command(pm, cmdout | STROBE); /* Write address+IE+Strobe. */ 315*757e119bSMatthias Koenig 316*757e119bSMatthias Koenig while ((portman_read_status(pm) & ESTB) == 0) 317*757e119bSMatthias Koenig cpu_relax(); /* Wait for strobe echo. */ 318*757e119bSMatthias Koenig 319*757e119bSMatthias Koenig /* The first data bit (msb) is already sitting on the input line. */ 320*757e119bSMatthias Koenig midi_data = (portman_read_status(pm) & 128); 321*757e119bSMatthias Koenig portman_write_data(pm, 1); /* Cause rising edge, which shifts data. */ 322*757e119bSMatthias Koenig 323*757e119bSMatthias Koenig /* Data bit 6. */ 324*757e119bSMatthias Koenig portman_write_data(pm, 0); /* Cause falling edge while data settles. */ 325*757e119bSMatthias Koenig midi_data |= (portman_read_status(pm) >> 1) & 64; 326*757e119bSMatthias Koenig portman_write_data(pm, 1); /* Cause rising edge, which shifts data. */ 327*757e119bSMatthias Koenig 328*757e119bSMatthias Koenig /* Data bit 5. */ 329*757e119bSMatthias Koenig portman_write_data(pm, 0); /* Cause falling edge while data settles. */ 330*757e119bSMatthias Koenig midi_data |= (portman_read_status(pm) >> 2) & 32; 331*757e119bSMatthias Koenig portman_write_data(pm, 1); /* Cause rising edge, which shifts data. */ 332*757e119bSMatthias Koenig 333*757e119bSMatthias Koenig /* Data bit 4. */ 334*757e119bSMatthias Koenig portman_write_data(pm, 0); /* Cause falling edge while data settles. */ 335*757e119bSMatthias Koenig midi_data |= (portman_read_status(pm) >> 3) & 16; 336*757e119bSMatthias Koenig portman_write_data(pm, 1); /* Cause rising edge, which shifts data. */ 337*757e119bSMatthias Koenig 338*757e119bSMatthias Koenig /* Data bit 3. */ 339*757e119bSMatthias Koenig portman_write_data(pm, 0); /* Cause falling edge while data settles. */ 340*757e119bSMatthias Koenig midi_data |= (portman_read_status(pm) >> 4) & 8; 341*757e119bSMatthias Koenig portman_write_data(pm, 1); /* Cause rising edge, which shifts data. */ 342*757e119bSMatthias Koenig 343*757e119bSMatthias Koenig /* Data bit 2. */ 344*757e119bSMatthias Koenig portman_write_data(pm, 0); /* Cause falling edge while data settles. */ 345*757e119bSMatthias Koenig midi_data |= (portman_read_status(pm) >> 5) & 4; 346*757e119bSMatthias Koenig portman_write_data(pm, 1); /* Cause rising edge, which shifts data. */ 347*757e119bSMatthias Koenig 348*757e119bSMatthias Koenig /* Data bit 1. */ 349*757e119bSMatthias Koenig portman_write_data(pm, 0); /* Cause falling edge while data settles. */ 350*757e119bSMatthias Koenig midi_data |= (portman_read_status(pm) >> 6) & 2; 351*757e119bSMatthias Koenig portman_write_data(pm, 1); /* Cause rising edge, which shifts data. */ 352*757e119bSMatthias Koenig 353*757e119bSMatthias Koenig /* Data bit 0. */ 354*757e119bSMatthias Koenig portman_write_data(pm, 0); /* Cause falling edge while data settles. */ 355*757e119bSMatthias Koenig midi_data |= (portman_read_status(pm) >> 7) & 1; 356*757e119bSMatthias Koenig portman_write_data(pm, 1); /* Cause rising edge, which shifts data. */ 357*757e119bSMatthias Koenig portman_write_data(pm, 0); /* Return data clock low. */ 358*757e119bSMatthias Koenig 359*757e119bSMatthias Koenig 360*757e119bSMatthias Koenig /* De-assert Strobe and return data. */ 361*757e119bSMatthias Koenig portman_write_command(pm, cmdout); /* Output saved address+IE. */ 362*757e119bSMatthias Koenig 363*757e119bSMatthias Koenig /* Wait for strobe echo. */ 364*757e119bSMatthias Koenig while ((portman_read_status(pm) & ESTB) == ESTB) 365*757e119bSMatthias Koenig cpu_relax(); 366*757e119bSMatthias Koenig 367*757e119bSMatthias Koenig return (midi_data & 255); /* Shift back and return value. */ 368*757e119bSMatthias Koenig } 369*757e119bSMatthias Koenig 370*757e119bSMatthias Koenig /* 371*757e119bSMatthias Koenig * Checks if any input data on the given channel is available 372*757e119bSMatthias Koenig * Checks RxAvail 373*757e119bSMatthias Koenig */ 374*757e119bSMatthias Koenig static int portman_data_avail(struct portman *pm, int channel) 375*757e119bSMatthias Koenig { 376*757e119bSMatthias Koenig int command = INT_EN; 377*757e119bSMatthias Koenig switch (channel) { 378*757e119bSMatthias Koenig case 0: 379*757e119bSMatthias Koenig command |= RXDATA0; 380*757e119bSMatthias Koenig break; 381*757e119bSMatthias Koenig case 1: 382*757e119bSMatthias Koenig command |= RXDATA1; 383*757e119bSMatthias Koenig break; 384*757e119bSMatthias Koenig } 385*757e119bSMatthias Koenig /* Write hardware (assumme STROBE=0) */ 386*757e119bSMatthias Koenig portman_write_command(pm, command); 387*757e119bSMatthias Koenig /* Check multiplexed RxAvail signal */ 388*757e119bSMatthias Koenig if ((portman_read_status(pm) & RXAVAIL) == RXAVAIL) 389*757e119bSMatthias Koenig return 1; /* Data available */ 390*757e119bSMatthias Koenig 391*757e119bSMatthias Koenig /* No Data available */ 392*757e119bSMatthias Koenig return 0; 393*757e119bSMatthias Koenig } 394*757e119bSMatthias Koenig 395*757e119bSMatthias Koenig 396*757e119bSMatthias Koenig /* 397*757e119bSMatthias Koenig * Flushes any input 398*757e119bSMatthias Koenig */ 399*757e119bSMatthias Koenig static void portman_flush_input(struct portman *pm, unsigned char port) 400*757e119bSMatthias Koenig { 401*757e119bSMatthias Koenig /* Local variable for counting things */ 402*757e119bSMatthias Koenig unsigned int i = 0; 403*757e119bSMatthias Koenig unsigned char command = 0; 404*757e119bSMatthias Koenig 405*757e119bSMatthias Koenig switch (port) { 406*757e119bSMatthias Koenig case 0: 407*757e119bSMatthias Koenig command = RXDATA0; 408*757e119bSMatthias Koenig break; 409*757e119bSMatthias Koenig case 1: 410*757e119bSMatthias Koenig command = RXDATA1; 411*757e119bSMatthias Koenig break; 412*757e119bSMatthias Koenig default: 413*757e119bSMatthias Koenig snd_printk(KERN_WARNING 414*757e119bSMatthias Koenig "portman_flush_input() Won't flush port %i\n", 415*757e119bSMatthias Koenig port); 416*757e119bSMatthias Koenig return; 417*757e119bSMatthias Koenig } 418*757e119bSMatthias Koenig 419*757e119bSMatthias Koenig /* Set address for specified channel in port and allow to settle. */ 420*757e119bSMatthias Koenig portman_write_command(pm, command); 421*757e119bSMatthias Koenig 422*757e119bSMatthias Koenig /* Assert the Strobe and wait for echo back. */ 423*757e119bSMatthias Koenig portman_write_command(pm, command | STROBE); 424*757e119bSMatthias Koenig 425*757e119bSMatthias Koenig /* Wait for ESTB */ 426*757e119bSMatthias Koenig while ((portman_read_status(pm) & ESTB) == 0) 427*757e119bSMatthias Koenig cpu_relax(); 428*757e119bSMatthias Koenig 429*757e119bSMatthias Koenig /* Output clock cycles to the Rx circuitry. */ 430*757e119bSMatthias Koenig portman_write_data(pm, 0); 431*757e119bSMatthias Koenig 432*757e119bSMatthias Koenig /* Flush 250 bits... */ 433*757e119bSMatthias Koenig for (i = 0; i < 250; i++) { 434*757e119bSMatthias Koenig portman_write_data(pm, 1); 435*757e119bSMatthias Koenig portman_write_data(pm, 0); 436*757e119bSMatthias Koenig } 437*757e119bSMatthias Koenig 438*757e119bSMatthias Koenig /* Deassert the Strobe signal of the port and wait for it to settle. */ 439*757e119bSMatthias Koenig portman_write_command(pm, command | INT_EN); 440*757e119bSMatthias Koenig 441*757e119bSMatthias Koenig /* Wait for settling */ 442*757e119bSMatthias Koenig while ((portman_read_status(pm) & ESTB) == ESTB) 443*757e119bSMatthias Koenig cpu_relax(); 444*757e119bSMatthias Koenig } 445*757e119bSMatthias Koenig 446*757e119bSMatthias Koenig static int portman_probe(struct parport *p) 447*757e119bSMatthias Koenig { 448*757e119bSMatthias Koenig /* Initialize the parallel port data register. Will set Rx clocks 449*757e119bSMatthias Koenig * low in case we happen to be addressing the Rx ports at this time. 450*757e119bSMatthias Koenig */ 451*757e119bSMatthias Koenig /* 1 */ 452*757e119bSMatthias Koenig parport_write_data(p, 0); 453*757e119bSMatthias Koenig 454*757e119bSMatthias Koenig /* Initialize the parallel port command register, thus initializing 455*757e119bSMatthias Koenig * hardware handshake lines to midi box: 456*757e119bSMatthias Koenig * 457*757e119bSMatthias Koenig * Strobe = 0 458*757e119bSMatthias Koenig * Interrupt Enable = 0 459*757e119bSMatthias Koenig */ 460*757e119bSMatthias Koenig /* 2 */ 461*757e119bSMatthias Koenig parport_write_control(p, 0); 462*757e119bSMatthias Koenig 463*757e119bSMatthias Koenig /* Check if Portman PC/P 2x4 is out there. */ 464*757e119bSMatthias Koenig /* 3 */ 465*757e119bSMatthias Koenig parport_write_control(p, RXDATA0); /* Write Strobe=0 to command reg. */ 466*757e119bSMatthias Koenig 467*757e119bSMatthias Koenig /* Check for ESTB to be clear */ 468*757e119bSMatthias Koenig /* 4 */ 469*757e119bSMatthias Koenig if ((parport_read_status(p) & ESTB) == ESTB) 470*757e119bSMatthias Koenig return 1; /* CODE 1 - Strobe Failure. */ 471*757e119bSMatthias Koenig 472*757e119bSMatthias Koenig /* Set for RXDATA0 where no damage will be done. */ 473*757e119bSMatthias Koenig /* 5 */ 474*757e119bSMatthias Koenig parport_write_control(p, RXDATA0 + STROBE); /* Write Strobe=1 to command reg. */ 475*757e119bSMatthias Koenig 476*757e119bSMatthias Koenig /* 6 */ 477*757e119bSMatthias Koenig if ((parport_read_status(p) & ESTB) != ESTB) 478*757e119bSMatthias Koenig return 1; /* CODE 1 - Strobe Failure. */ 479*757e119bSMatthias Koenig 480*757e119bSMatthias Koenig /* 7 */ 481*757e119bSMatthias Koenig parport_write_control(p, 0); /* Reset Strobe=0. */ 482*757e119bSMatthias Koenig 483*757e119bSMatthias Koenig /* Check if Tx circuitry is functioning properly. If initialized 484*757e119bSMatthias Koenig * unit TxEmpty is false, send out char and see if if goes true. 485*757e119bSMatthias Koenig */ 486*757e119bSMatthias Koenig /* 8 */ 487*757e119bSMatthias Koenig parport_write_control(p, TXDATA0); /* Tx channel 0, strobe off. */ 488*757e119bSMatthias Koenig 489*757e119bSMatthias Koenig /* If PCP channel's TxEmpty is set (TxEmpty is read through the PP 490*757e119bSMatthias Koenig * Status Register), then go write data. Else go back and wait. 491*757e119bSMatthias Koenig */ 492*757e119bSMatthias Koenig /* 9 */ 493*757e119bSMatthias Koenig if ((parport_read_status(p) & TXEMPTY) == 0) 494*757e119bSMatthias Koenig return 2; 495*757e119bSMatthias Koenig 496*757e119bSMatthias Koenig /* Return OK status. */ 497*757e119bSMatthias Koenig return 0; 498*757e119bSMatthias Koenig } 499*757e119bSMatthias Koenig 500*757e119bSMatthias Koenig static int portman_device_init(struct portman *pm) 501*757e119bSMatthias Koenig { 502*757e119bSMatthias Koenig portman_flush_input(pm, 0); 503*757e119bSMatthias Koenig portman_flush_input(pm, 1); 504*757e119bSMatthias Koenig 505*757e119bSMatthias Koenig return 0; 506*757e119bSMatthias Koenig } 507*757e119bSMatthias Koenig 508*757e119bSMatthias Koenig /********************************************************************* 509*757e119bSMatthias Koenig * Rawmidi 510*757e119bSMatthias Koenig *********************************************************************/ 511*757e119bSMatthias Koenig static int snd_portman_midi_open(struct snd_rawmidi_substream *substream) 512*757e119bSMatthias Koenig { 513*757e119bSMatthias Koenig return 0; 514*757e119bSMatthias Koenig } 515*757e119bSMatthias Koenig 516*757e119bSMatthias Koenig static int snd_portman_midi_close(struct snd_rawmidi_substream *substream) 517*757e119bSMatthias Koenig { 518*757e119bSMatthias Koenig return 0; 519*757e119bSMatthias Koenig } 520*757e119bSMatthias Koenig 521*757e119bSMatthias Koenig static void snd_portman_midi_input_trigger(struct snd_rawmidi_substream *substream, 522*757e119bSMatthias Koenig int up) 523*757e119bSMatthias Koenig { 524*757e119bSMatthias Koenig struct portman *pm = substream->rmidi->private_data; 525*757e119bSMatthias Koenig unsigned long flags; 526*757e119bSMatthias Koenig 527*757e119bSMatthias Koenig spin_lock_irqsave(&pm->reg_lock, flags); 528*757e119bSMatthias Koenig if (up) 529*757e119bSMatthias Koenig pm->mode[substream->number] |= PORTMAN2X4_MODE_INPUT_TRIGGERED; 530*757e119bSMatthias Koenig else 531*757e119bSMatthias Koenig pm->mode[substream->number] &= ~PORTMAN2X4_MODE_INPUT_TRIGGERED; 532*757e119bSMatthias Koenig spin_unlock_irqrestore(&pm->reg_lock, flags); 533*757e119bSMatthias Koenig } 534*757e119bSMatthias Koenig 535*757e119bSMatthias Koenig static void snd_portman_midi_output_trigger(struct snd_rawmidi_substream *substream, 536*757e119bSMatthias Koenig int up) 537*757e119bSMatthias Koenig { 538*757e119bSMatthias Koenig struct portman *pm = substream->rmidi->private_data; 539*757e119bSMatthias Koenig unsigned long flags; 540*757e119bSMatthias Koenig unsigned char byte; 541*757e119bSMatthias Koenig 542*757e119bSMatthias Koenig spin_lock_irqsave(&pm->reg_lock, flags); 543*757e119bSMatthias Koenig if (up) { 544*757e119bSMatthias Koenig while ((snd_rawmidi_transmit(substream, &byte, 1) == 1)) 545*757e119bSMatthias Koenig portman_write_midi(pm, substream->number, byte); 546*757e119bSMatthias Koenig } 547*757e119bSMatthias Koenig spin_unlock_irqrestore(&pm->reg_lock, flags); 548*757e119bSMatthias Koenig } 549*757e119bSMatthias Koenig 550*757e119bSMatthias Koenig static struct snd_rawmidi_ops snd_portman_midi_output = { 551*757e119bSMatthias Koenig .open = snd_portman_midi_open, 552*757e119bSMatthias Koenig .close = snd_portman_midi_close, 553*757e119bSMatthias Koenig .trigger = snd_portman_midi_output_trigger, 554*757e119bSMatthias Koenig }; 555*757e119bSMatthias Koenig 556*757e119bSMatthias Koenig static struct snd_rawmidi_ops snd_portman_midi_input = { 557*757e119bSMatthias Koenig .open = snd_portman_midi_open, 558*757e119bSMatthias Koenig .close = snd_portman_midi_close, 559*757e119bSMatthias Koenig .trigger = snd_portman_midi_input_trigger, 560*757e119bSMatthias Koenig }; 561*757e119bSMatthias Koenig 562*757e119bSMatthias Koenig /* Create and initialize the rawmidi component */ 563*757e119bSMatthias Koenig static int __devinit snd_portman_rawmidi_create(struct snd_card *card) 564*757e119bSMatthias Koenig { 565*757e119bSMatthias Koenig struct portman *pm = card->private_data; 566*757e119bSMatthias Koenig struct snd_rawmidi *rmidi; 567*757e119bSMatthias Koenig struct snd_rawmidi_substream *substream; 568*757e119bSMatthias Koenig int err; 569*757e119bSMatthias Koenig 570*757e119bSMatthias Koenig err = snd_rawmidi_new(card, CARD_NAME, 0, 571*757e119bSMatthias Koenig PORTMAN_NUM_OUTPUT_PORTS, 572*757e119bSMatthias Koenig PORTMAN_NUM_INPUT_PORTS, 573*757e119bSMatthias Koenig &rmidi); 574*757e119bSMatthias Koenig if (err < 0) 575*757e119bSMatthias Koenig return err; 576*757e119bSMatthias Koenig 577*757e119bSMatthias Koenig rmidi->private_data = pm; 578*757e119bSMatthias Koenig strcpy(rmidi->name, CARD_NAME); 579*757e119bSMatthias Koenig rmidi->info_flags = SNDRV_RAWMIDI_INFO_OUTPUT | 580*757e119bSMatthias Koenig SNDRV_RAWMIDI_INFO_INPUT | 581*757e119bSMatthias Koenig SNDRV_RAWMIDI_INFO_DUPLEX; 582*757e119bSMatthias Koenig 583*757e119bSMatthias Koenig pm->rmidi = rmidi; 584*757e119bSMatthias Koenig 585*757e119bSMatthias Koenig /* register rawmidi ops */ 586*757e119bSMatthias Koenig snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_OUTPUT, 587*757e119bSMatthias Koenig &snd_portman_midi_output); 588*757e119bSMatthias Koenig snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_INPUT, 589*757e119bSMatthias Koenig &snd_portman_midi_input); 590*757e119bSMatthias Koenig 591*757e119bSMatthias Koenig /* name substreams */ 592*757e119bSMatthias Koenig /* output */ 593*757e119bSMatthias Koenig list_for_each_entry(substream, 594*757e119bSMatthias Koenig &rmidi->streams[SNDRV_RAWMIDI_STREAM_OUTPUT].substreams, 595*757e119bSMatthias Koenig list) { 596*757e119bSMatthias Koenig sprintf(substream->name, 597*757e119bSMatthias Koenig "Portman2x4 %d", substream->number+1); 598*757e119bSMatthias Koenig } 599*757e119bSMatthias Koenig /* input */ 600*757e119bSMatthias Koenig list_for_each_entry(substream, 601*757e119bSMatthias Koenig &rmidi->streams[SNDRV_RAWMIDI_STREAM_INPUT].substreams, 602*757e119bSMatthias Koenig list) { 603*757e119bSMatthias Koenig pm->midi_input[substream->number] = substream; 604*757e119bSMatthias Koenig sprintf(substream->name, 605*757e119bSMatthias Koenig "Portman2x4 %d", substream->number+1); 606*757e119bSMatthias Koenig } 607*757e119bSMatthias Koenig 608*757e119bSMatthias Koenig return err; 609*757e119bSMatthias Koenig } 610*757e119bSMatthias Koenig 611*757e119bSMatthias Koenig /********************************************************************* 612*757e119bSMatthias Koenig * parport stuff 613*757e119bSMatthias Koenig *********************************************************************/ 614*757e119bSMatthias Koenig static void snd_portman_interrupt(int irq, void *userdata) 615*757e119bSMatthias Koenig { 616*757e119bSMatthias Koenig unsigned char midivalue = 0; 617*757e119bSMatthias Koenig struct portman *pm = ((struct snd_card*)userdata)->private_data; 618*757e119bSMatthias Koenig 619*757e119bSMatthias Koenig spin_lock(&pm->reg_lock); 620*757e119bSMatthias Koenig 621*757e119bSMatthias Koenig /* While any input data is waiting */ 622*757e119bSMatthias Koenig while ((portman_read_status(pm) & INT_REQ) == INT_REQ) { 623*757e119bSMatthias Koenig /* If data available on channel 0, 624*757e119bSMatthias Koenig read it and stuff it into the queue. */ 625*757e119bSMatthias Koenig if (portman_data_avail(pm, 0)) { 626*757e119bSMatthias Koenig /* Read Midi */ 627*757e119bSMatthias Koenig midivalue = portman_read_midi(pm, 0); 628*757e119bSMatthias Koenig /* put midi into queue... */ 629*757e119bSMatthias Koenig if (pm->mode[0] & PORTMAN2X4_MODE_INPUT_TRIGGERED) 630*757e119bSMatthias Koenig snd_rawmidi_receive(pm->midi_input[0], 631*757e119bSMatthias Koenig &midivalue, 1); 632*757e119bSMatthias Koenig 633*757e119bSMatthias Koenig } 634*757e119bSMatthias Koenig /* If data available on channel 1, 635*757e119bSMatthias Koenig read it and stuff it into the queue. */ 636*757e119bSMatthias Koenig if (portman_data_avail(pm, 1)) { 637*757e119bSMatthias Koenig /* Read Midi */ 638*757e119bSMatthias Koenig midivalue = portman_read_midi(pm, 1); 639*757e119bSMatthias Koenig /* put midi into queue... */ 640*757e119bSMatthias Koenig if (pm->mode[1] & PORTMAN2X4_MODE_INPUT_TRIGGERED) 641*757e119bSMatthias Koenig snd_rawmidi_receive(pm->midi_input[1], 642*757e119bSMatthias Koenig &midivalue, 1); 643*757e119bSMatthias Koenig } 644*757e119bSMatthias Koenig 645*757e119bSMatthias Koenig } 646*757e119bSMatthias Koenig 647*757e119bSMatthias Koenig spin_unlock(&pm->reg_lock); 648*757e119bSMatthias Koenig } 649*757e119bSMatthias Koenig 650*757e119bSMatthias Koenig static int __devinit snd_portman_probe_port(struct parport *p) 651*757e119bSMatthias Koenig { 652*757e119bSMatthias Koenig struct pardevice *pardev; 653*757e119bSMatthias Koenig int res; 654*757e119bSMatthias Koenig 655*757e119bSMatthias Koenig pardev = parport_register_device(p, DRIVER_NAME, 656*757e119bSMatthias Koenig NULL, NULL, NULL, 657*757e119bSMatthias Koenig 0, NULL); 658*757e119bSMatthias Koenig if (!pardev) 659*757e119bSMatthias Koenig return -EIO; 660*757e119bSMatthias Koenig 661*757e119bSMatthias Koenig if (parport_claim(pardev)) { 662*757e119bSMatthias Koenig parport_unregister_device(pardev); 663*757e119bSMatthias Koenig return -EIO; 664*757e119bSMatthias Koenig } 665*757e119bSMatthias Koenig 666*757e119bSMatthias Koenig res = portman_probe(p); 667*757e119bSMatthias Koenig 668*757e119bSMatthias Koenig parport_release(pardev); 669*757e119bSMatthias Koenig parport_unregister_device(pardev); 670*757e119bSMatthias Koenig 671*757e119bSMatthias Koenig return res; 672*757e119bSMatthias Koenig } 673*757e119bSMatthias Koenig 674*757e119bSMatthias Koenig static void __devinit snd_portman_attach(struct parport *p) 675*757e119bSMatthias Koenig { 676*757e119bSMatthias Koenig struct platform_device *device; 677*757e119bSMatthias Koenig 678*757e119bSMatthias Koenig device = platform_device_alloc(PLATFORM_DRIVER, device_count); 679*757e119bSMatthias Koenig if (!device) 680*757e119bSMatthias Koenig return; 681*757e119bSMatthias Koenig 682*757e119bSMatthias Koenig /* Temporary assignment to forward the parport */ 683*757e119bSMatthias Koenig platform_set_drvdata(device, p); 684*757e119bSMatthias Koenig 685*757e119bSMatthias Koenig if (platform_device_register(device) < 0) { 686*757e119bSMatthias Koenig platform_device_put(device); 687*757e119bSMatthias Koenig return; 688*757e119bSMatthias Koenig } 689*757e119bSMatthias Koenig 690*757e119bSMatthias Koenig /* Since we dont get the return value of probe 691*757e119bSMatthias Koenig * We need to check if device probing succeeded or not */ 692*757e119bSMatthias Koenig if (!platform_get_drvdata(device)) { 693*757e119bSMatthias Koenig platform_device_unregister(device); 694*757e119bSMatthias Koenig return; 695*757e119bSMatthias Koenig } 696*757e119bSMatthias Koenig 697*757e119bSMatthias Koenig /* register device in global table */ 698*757e119bSMatthias Koenig platform_devices[device_count] = device; 699*757e119bSMatthias Koenig device_count++; 700*757e119bSMatthias Koenig } 701*757e119bSMatthias Koenig 702*757e119bSMatthias Koenig static void snd_portman_detach(struct parport *p) 703*757e119bSMatthias Koenig { 704*757e119bSMatthias Koenig /* nothing to do here */ 705*757e119bSMatthias Koenig } 706*757e119bSMatthias Koenig 707*757e119bSMatthias Koenig static struct parport_driver portman_parport_driver = { 708*757e119bSMatthias Koenig .name = "portman2x4", 709*757e119bSMatthias Koenig .attach = snd_portman_attach, 710*757e119bSMatthias Koenig .detach = snd_portman_detach 711*757e119bSMatthias Koenig }; 712*757e119bSMatthias Koenig 713*757e119bSMatthias Koenig /********************************************************************* 714*757e119bSMatthias Koenig * platform stuff 715*757e119bSMatthias Koenig *********************************************************************/ 716*757e119bSMatthias Koenig static void snd_portman_card_private_free(struct snd_card *card) 717*757e119bSMatthias Koenig { 718*757e119bSMatthias Koenig struct portman *pm = card->private_data; 719*757e119bSMatthias Koenig struct pardevice *pardev = pm->pardev; 720*757e119bSMatthias Koenig 721*757e119bSMatthias Koenig if (pardev) { 722*757e119bSMatthias Koenig if (pm->pardev_claimed) 723*757e119bSMatthias Koenig parport_release(pardev); 724*757e119bSMatthias Koenig parport_unregister_device(pardev); 725*757e119bSMatthias Koenig } 726*757e119bSMatthias Koenig 727*757e119bSMatthias Koenig portman_free(pm); 728*757e119bSMatthias Koenig } 729*757e119bSMatthias Koenig 730*757e119bSMatthias Koenig static int __devinit snd_portman_probe(struct platform_device *pdev) 731*757e119bSMatthias Koenig { 732*757e119bSMatthias Koenig struct pardevice *pardev; 733*757e119bSMatthias Koenig struct parport *p; 734*757e119bSMatthias Koenig int dev = pdev->id; 735*757e119bSMatthias Koenig struct snd_card *card = NULL; 736*757e119bSMatthias Koenig struct portman *pm = NULL; 737*757e119bSMatthias Koenig int err; 738*757e119bSMatthias Koenig 739*757e119bSMatthias Koenig p = platform_get_drvdata(pdev); 740*757e119bSMatthias Koenig platform_set_drvdata(pdev, NULL); 741*757e119bSMatthias Koenig 742*757e119bSMatthias Koenig if (dev >= SNDRV_CARDS) 743*757e119bSMatthias Koenig return -ENODEV; 744*757e119bSMatthias Koenig if (!enable[dev]) 745*757e119bSMatthias Koenig return -ENOENT; 746*757e119bSMatthias Koenig 747*757e119bSMatthias Koenig if ((err = snd_portman_probe_port(p)) < 0) 748*757e119bSMatthias Koenig return err; 749*757e119bSMatthias Koenig 750*757e119bSMatthias Koenig card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0); 751*757e119bSMatthias Koenig if (card == NULL) { 752*757e119bSMatthias Koenig snd_printd("Cannot create card\n"); 753*757e119bSMatthias Koenig return -ENOMEM; 754*757e119bSMatthias Koenig } 755*757e119bSMatthias Koenig strcpy(card->driver, DRIVER_NAME); 756*757e119bSMatthias Koenig strcpy(card->shortname, CARD_NAME); 757*757e119bSMatthias Koenig sprintf(card->longname, "%s at 0x%lx, irq %i", 758*757e119bSMatthias Koenig card->shortname, p->base, p->irq); 759*757e119bSMatthias Koenig 760*757e119bSMatthias Koenig pardev = parport_register_device(p, /* port */ 761*757e119bSMatthias Koenig DRIVER_NAME, /* name */ 762*757e119bSMatthias Koenig NULL, /* preempt */ 763*757e119bSMatthias Koenig NULL, /* wakeup */ 764*757e119bSMatthias Koenig snd_portman_interrupt, /* ISR */ 765*757e119bSMatthias Koenig PARPORT_DEV_EXCL, /* flags */ 766*757e119bSMatthias Koenig (void *)card); /* private */ 767*757e119bSMatthias Koenig if (pardev == NULL) { 768*757e119bSMatthias Koenig snd_printd("Cannot register pardevice\n"); 769*757e119bSMatthias Koenig err = -EIO; 770*757e119bSMatthias Koenig goto __err; 771*757e119bSMatthias Koenig } 772*757e119bSMatthias Koenig 773*757e119bSMatthias Koenig if ((err = portman_create(card, pardev, &pm)) < 0) { 774*757e119bSMatthias Koenig snd_printd("Cannot create main component\n"); 775*757e119bSMatthias Koenig parport_unregister_device(pardev); 776*757e119bSMatthias Koenig goto __err; 777*757e119bSMatthias Koenig } 778*757e119bSMatthias Koenig card->private_data = pm; 779*757e119bSMatthias Koenig card->private_free = snd_portman_card_private_free; 780*757e119bSMatthias Koenig 781*757e119bSMatthias Koenig if ((err = snd_portman_rawmidi_create(card)) < 0) { 782*757e119bSMatthias Koenig snd_printd("Creating Rawmidi component failed\n"); 783*757e119bSMatthias Koenig goto __err; 784*757e119bSMatthias Koenig } 785*757e119bSMatthias Koenig 786*757e119bSMatthias Koenig /* claim parport */ 787*757e119bSMatthias Koenig if (parport_claim(pardev)) { 788*757e119bSMatthias Koenig snd_printd("Cannot claim parport 0x%lx\n", pardev->port->base); 789*757e119bSMatthias Koenig err = -EIO; 790*757e119bSMatthias Koenig goto __err; 791*757e119bSMatthias Koenig } 792*757e119bSMatthias Koenig pm->pardev_claimed = 1; 793*757e119bSMatthias Koenig 794*757e119bSMatthias Koenig /* init device */ 795*757e119bSMatthias Koenig if ((err = portman_device_init(pm)) < 0) 796*757e119bSMatthias Koenig goto __err; 797*757e119bSMatthias Koenig 798*757e119bSMatthias Koenig platform_set_drvdata(pdev, card); 799*757e119bSMatthias Koenig 800*757e119bSMatthias Koenig /* At this point card will be usable */ 801*757e119bSMatthias Koenig if ((err = snd_card_register(card)) < 0) { 802*757e119bSMatthias Koenig snd_printd("Cannot register card\n"); 803*757e119bSMatthias Koenig goto __err; 804*757e119bSMatthias Koenig } 805*757e119bSMatthias Koenig 806*757e119bSMatthias Koenig snd_printk(KERN_INFO "Portman 2x4 on 0x%lx\n", p->base); 807*757e119bSMatthias Koenig return 0; 808*757e119bSMatthias Koenig 809*757e119bSMatthias Koenig __err: 810*757e119bSMatthias Koenig snd_card_free(card); 811*757e119bSMatthias Koenig return err; 812*757e119bSMatthias Koenig } 813*757e119bSMatthias Koenig 814*757e119bSMatthias Koenig static int snd_portman_remove(struct platform_device *pdev) 815*757e119bSMatthias Koenig { 816*757e119bSMatthias Koenig struct snd_card *card = platform_get_drvdata(pdev); 817*757e119bSMatthias Koenig 818*757e119bSMatthias Koenig if (card) 819*757e119bSMatthias Koenig snd_card_free(card); 820*757e119bSMatthias Koenig 821*757e119bSMatthias Koenig return 0; 822*757e119bSMatthias Koenig } 823*757e119bSMatthias Koenig 824*757e119bSMatthias Koenig 825*757e119bSMatthias Koenig static struct platform_driver snd_portman_driver = { 826*757e119bSMatthias Koenig .probe = snd_portman_probe, 827*757e119bSMatthias Koenig .remove = snd_portman_remove, 828*757e119bSMatthias Koenig .driver = { 829*757e119bSMatthias Koenig .name = PLATFORM_DRIVER 830*757e119bSMatthias Koenig } 831*757e119bSMatthias Koenig }; 832*757e119bSMatthias Koenig 833*757e119bSMatthias Koenig /********************************************************************* 834*757e119bSMatthias Koenig * module init stuff 835*757e119bSMatthias Koenig *********************************************************************/ 836*757e119bSMatthias Koenig static void snd_portman_unregister_all(void) 837*757e119bSMatthias Koenig { 838*757e119bSMatthias Koenig int i; 839*757e119bSMatthias Koenig 840*757e119bSMatthias Koenig for (i = 0; i < SNDRV_CARDS; ++i) { 841*757e119bSMatthias Koenig if (platform_devices[i]) { 842*757e119bSMatthias Koenig platform_device_unregister(platform_devices[i]); 843*757e119bSMatthias Koenig platform_devices[i] = NULL; 844*757e119bSMatthias Koenig } 845*757e119bSMatthias Koenig } 846*757e119bSMatthias Koenig platform_driver_unregister(&snd_portman_driver); 847*757e119bSMatthias Koenig parport_unregister_driver(&portman_parport_driver); 848*757e119bSMatthias Koenig } 849*757e119bSMatthias Koenig 850*757e119bSMatthias Koenig static int __init snd_portman_module_init(void) 851*757e119bSMatthias Koenig { 852*757e119bSMatthias Koenig int err; 853*757e119bSMatthias Koenig 854*757e119bSMatthias Koenig if ((err = platform_driver_register(&snd_portman_driver)) < 0) 855*757e119bSMatthias Koenig return err; 856*757e119bSMatthias Koenig 857*757e119bSMatthias Koenig if (parport_register_driver(&portman_parport_driver) != 0) { 858*757e119bSMatthias Koenig platform_driver_unregister(&snd_portman_driver); 859*757e119bSMatthias Koenig return -EIO; 860*757e119bSMatthias Koenig } 861*757e119bSMatthias Koenig 862*757e119bSMatthias Koenig if (device_count == 0) { 863*757e119bSMatthias Koenig snd_portman_unregister_all(); 864*757e119bSMatthias Koenig return -ENODEV; 865*757e119bSMatthias Koenig } 866*757e119bSMatthias Koenig 867*757e119bSMatthias Koenig return 0; 868*757e119bSMatthias Koenig } 869*757e119bSMatthias Koenig 870*757e119bSMatthias Koenig static void __exit snd_portman_module_exit(void) 871*757e119bSMatthias Koenig { 872*757e119bSMatthias Koenig snd_portman_unregister_all(); 873*757e119bSMatthias Koenig } 874*757e119bSMatthias Koenig 875*757e119bSMatthias Koenig module_init(snd_portman_module_init); 876*757e119bSMatthias Koenig module_exit(snd_portman_module_exit); 877