diff options
Diffstat (limited to 'sound/drivers')
-rw-r--r-- | sound/drivers/Kconfig | 11 | ||||
-rw-r--r-- | sound/drivers/Makefile | 2 | ||||
-rw-r--r-- | sound/drivers/dummy.c | 13 | ||||
-rw-r--r-- | sound/drivers/mtpav.c | 12 | ||||
-rw-r--r-- | sound/drivers/mts64.c | 6 | ||||
-rw-r--r-- | sound/drivers/portman2x4.c | 876 | ||||
-rw-r--r-- | sound/drivers/serial-u16550.c | 231 | ||||
-rw-r--r-- | sound/drivers/virmidi.c | 7 | ||||
-rw-r--r-- | sound/drivers/vx/vx_mixer.c | 2 |
9 files changed, 1037 insertions, 123 deletions
diff --git a/sound/drivers/Kconfig b/sound/drivers/Kconfig index 40ebd2f44056..83529b08d019 100644 --- a/sound/drivers/Kconfig +++ b/sound/drivers/Kconfig @@ -109,4 +109,15 @@ config SND_MPU401 To compile this driver as a module, choose M here: the module will be called snd-mpu401. +config SND_PORTMAN2X4 + tristate "Portman 2x4 driver" + depends on SND && PARPORT + select SND_RAWMIDI + help + Say Y here to include support for Midiman Portman 2x4 parallel + port MIDI device. + + To compile this driver as a module, choose M here: the module + will be called snd-portman2x4. + endmenu diff --git a/sound/drivers/Makefile b/sound/drivers/Makefile index c9bad6d67e73..04112642611a 100644 --- a/sound/drivers/Makefile +++ b/sound/drivers/Makefile @@ -6,6 +6,7 @@ snd-dummy-objs := dummy.o snd-mtpav-objs := mtpav.o snd-mts64-objs := mts64.o +snd-portman2x4-objs := portman2x4.o snd-serial-u16550-objs := serial-u16550.o snd-virmidi-objs := virmidi.o @@ -15,5 +16,6 @@ obj-$(CONFIG_SND_VIRMIDI) += snd-virmidi.o obj-$(CONFIG_SND_SERIAL_U16550) += snd-serial-u16550.o obj-$(CONFIG_SND_MTPAV) += snd-mtpav.o obj-$(CONFIG_SND_MTS64) += snd-mts64.o +obj-$(CONFIG_SND_PORTMAN2X4) += snd-portman2x4.o obj-$(CONFIG_SND) += opl3/ opl4/ mpu401/ vx/ diff --git a/sound/drivers/dummy.c b/sound/drivers/dummy.c index 42001efa9f3e..a0f28f51fc7e 100644 --- a/sound/drivers/dummy.c +++ b/sound/drivers/dummy.c @@ -423,7 +423,8 @@ static struct snd_pcm_ops snd_card_dummy_capture_ops = { .pointer = snd_card_dummy_pcm_pointer, }; -static int __init snd_card_dummy_pcm(struct snd_dummy *dummy, int device, int substreams) +static int __devinit snd_card_dummy_pcm(struct snd_dummy *dummy, int device, + int substreams) { struct snd_pcm *pcm; int err; @@ -501,7 +502,7 @@ static int snd_dummy_volume_put(struct snd_kcontrol *kcontrol, return change; } -static DECLARE_TLV_DB_SCALE(db_scale_dummy, -4500, 30, 0); +static const DECLARE_TLV_DB_SCALE(db_scale_dummy, -4500, 30, 0); #define DUMMY_CAPSRC(xname, xindex, addr) \ { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \ @@ -562,7 +563,7 @@ DUMMY_VOLUME("CD Volume", 0, MIXER_ADDR_CD), DUMMY_CAPSRC("CD Capture Switch", 0, MIXER_ADDR_CD) }; -static int __init snd_card_dummy_new_mixer(struct snd_dummy *dummy) +static int __devinit snd_card_dummy_new_mixer(struct snd_dummy *dummy) { struct snd_card *card = dummy->card; unsigned int idx; @@ -579,7 +580,7 @@ static int __init snd_card_dummy_new_mixer(struct snd_dummy *dummy) return 0; } -static int __init snd_dummy_probe(struct platform_device *devptr) +static int __devinit snd_dummy_probe(struct platform_device *devptr) { struct snd_card *card; struct snd_dummy *dummy; @@ -617,7 +618,7 @@ static int __init snd_dummy_probe(struct platform_device *devptr) return err; } -static int snd_dummy_remove(struct platform_device *devptr) +static int __devexit snd_dummy_remove(struct platform_device *devptr) { snd_card_free(platform_get_drvdata(devptr)); platform_set_drvdata(devptr, NULL); @@ -648,7 +649,7 @@ static int snd_dummy_resume(struct platform_device *pdev) static struct platform_driver snd_dummy_driver = { .probe = snd_dummy_probe, - .remove = snd_dummy_remove, + .remove = __devexit_p(snd_dummy_remove), #ifdef CONFIG_PM .suspend = snd_dummy_suspend, .resume = snd_dummy_resume, diff --git a/sound/drivers/mtpav.c b/sound/drivers/mtpav.c index a9ff391258e7..40eb026c86ed 100644 --- a/sound/drivers/mtpav.c +++ b/sound/drivers/mtpav.c @@ -583,7 +583,7 @@ static irqreturn_t snd_mtpav_irqh(int irq, void *dev_id) /* * get ISA resources */ -static int __init snd_mtpav_get_ISA(struct mtpav * mcard) +static int __devinit snd_mtpav_get_ISA(struct mtpav * mcard) { if ((mcard->res_port = request_region(port, 3, "MotuMTPAV MIDI")) == NULL) { snd_printk("MTVAP port 0x%lx is busy\n", port); @@ -619,7 +619,7 @@ static struct snd_rawmidi_ops snd_mtpav_input = { * get RAWMIDI resources */ -static void __init snd_mtpav_set_name(struct mtpav *chip, +static void __devinit snd_mtpav_set_name(struct mtpav *chip, struct snd_rawmidi_substream *substream) { if (substream->number >= 0 && substream->number < chip->num_ports) @@ -634,7 +634,7 @@ static void __init snd_mtpav_set_name(struct mtpav *chip, strcpy(substream->name, "MTP broadcast"); } -static int __init snd_mtpav_get_RAWMIDI(struct mtpav *mcard) +static int __devinit snd_mtpav_get_RAWMIDI(struct mtpav *mcard) { int rval; struct snd_rawmidi *rawmidi; @@ -691,7 +691,7 @@ static void snd_mtpav_free(struct snd_card *card) /* */ -static int __init snd_mtpav_probe(struct platform_device *dev) +static int __devinit snd_mtpav_probe(struct platform_device *dev) { struct snd_card *card; int err; @@ -745,7 +745,7 @@ static int __init snd_mtpav_probe(struct platform_device *dev) return err; } -static int snd_mtpav_remove(struct platform_device *devptr) +static int __devexit snd_mtpav_remove(struct platform_device *devptr) { snd_card_free(platform_get_drvdata(devptr)); platform_set_drvdata(devptr, NULL); @@ -756,7 +756,7 @@ static int snd_mtpav_remove(struct platform_device *devptr) static struct platform_driver snd_mtpav_driver = { .probe = snd_mtpav_probe, - .remove = snd_mtpav_remove, + .remove = __devexit_p(snd_mtpav_remove), .driver = { .name = SND_MTPAV_DRIVER }, diff --git a/sound/drivers/mts64.c b/sound/drivers/mts64.c index 5327c6f841f4..6c9f4c9bfeb6 100644 --- a/sound/drivers/mts64.c +++ b/sound/drivers/mts64.c @@ -1026,7 +1026,7 @@ __err: return err; } -static int snd_mts64_remove(struct platform_device *pdev) +static int __devexit snd_mts64_remove(struct platform_device *pdev) { struct snd_card *card = platform_get_drvdata(pdev); @@ -1039,7 +1039,7 @@ static int snd_mts64_remove(struct platform_device *pdev) static struct platform_driver snd_mts64_driver = { .probe = snd_mts64_probe, - .remove = snd_mts64_remove, + .remove = __devexit_p(snd_mts64_remove), .driver = { .name = PLATFORM_DRIVER } @@ -1048,7 +1048,7 @@ static struct platform_driver snd_mts64_driver = { /********************************************************************* * module init stuff *********************************************************************/ -static void snd_mts64_unregister_all(void) +static void __init_or_module snd_mts64_unregister_all(void) { int i; diff --git a/sound/drivers/portman2x4.c b/sound/drivers/portman2x4.c new file mode 100644 index 000000000000..b2d0ba4bd184 --- /dev/null +++ b/sound/drivers/portman2x4.c @@ -0,0 +1,876 @@ +/* + * Driver for Midiman Portman2x4 parallel port midi interface + * + * Copyright (c) by Levent Guendogdu <levon@feature-it.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * ChangeLog + * Jan 24 2007 Matthias Koenig <mkoenig@suse.de> + * - cleanup and rewrite + * Sep 30 2004 Tobias Gehrig <tobias@gehrig.tk> + * - source code cleanup + * Sep 03 2004 Tobias Gehrig <tobias@gehrig.tk> + * - fixed compilation problem with alsa 1.0.6a (removed MODULE_CLASSES, + * MODULE_PARM_SYNTAX and changed MODULE_DEVICES to + * MODULE_SUPPORTED_DEVICE) + * Mar 24 2004 Tobias Gehrig <tobias@gehrig.tk> + * - added 2.6 kernel support + * Mar 18 2004 Tobias Gehrig <tobias@gehrig.tk> + * - 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@gehrig.tk> + * - added checks for opened input device in interrupt handler + * Feb 20 2004 Tobias Gehrig <tobias@gehrig.tk> + * - ported from alsa 0.5 to 1.0 + */ + +#include <sound/driver.h> +#include <linux/init.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> + +#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 Guendogdu, Tobias Gehrig, Matthias Koenig"); +MODULE_DESCRIPTION("Midiman Portman2x4"); +MODULE_LICENSE("GPL"); +MODULE_SUPPORTED_DEVICE("{{Midiman,Portman2x4}}"); + +/********************************************************************* + * Chip specific + *********************************************************************/ +#define PORTMAN_NUM_INPUT_PORTS 2 +#define PORTMAN_NUM_OUTPUT_PORTS 4 + +struct portman { + spinlock_t reg_lock; + struct snd_card *card; + struct snd_rawmidi *rmidi; + 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]; +}; + +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. */ +#define PP_STAT_ACK 0x40 /* Acknowledge. Non-Inverted. */ +#define PP_STAT_POUT 0x20 /* Paper Out. Non-Inverted. */ +#define PP_STAT_SEL 0x10 /* Select. Non-Inverted. */ +#define PP_STAT_ERR 0x08 /* Error. Non-Inverted. */ + +/* Standard PC parallel port command register equates. */ +#define PP_CMD_IEN 0x10 /* IRQ Enable. Non-Inverted. */ +#define PP_CMD_SELI 0x08 /* Select Input. Inverted. */ +#define PP_CMD_INIT 0x04 /* Init Printer. Non-Inverted. */ +#define PP_CMD_FEED 0x02 /* Auto Feed. Inverted. */ +#define PP_CMD_STB 0x01 /* Strobe. Inverted. */ + +/* Parallel Port Command Register as implemented by PCP2x4. */ +#define INT_EN PP_CMD_IEN /* Interrupt enable. */ +#define STROBE PP_CMD_STB /* Command strobe. */ + +/* The parallel port command register field (b1..b3) selects the + * various "registers" within the PC/P 2x4. These are the internal + * address of these "registers" that must be written to the parallel + * port command register. + */ +#define RXDATA0 (0 << 1) /* PCP RxData channel 0. */ +#define RXDATA1 (1 << 1) /* PCP RxData channel 1. */ +#define GEN_CTL (2 << 1) /* PCP General Control Register. */ +#define SYNC_CTL (3 << 1) /* PCP Sync Control Register. */ +#define TXDATA0 (4 << 1) /* PCP TxData channel 0. */ +#define TXDATA1 (5 << 1) /* PCP TxData channel 1. */ +#define TXDATA2 (6 << 1) /* PCP TxData channel 2. */ +#define TXDATA3 (7 << 1) /* PCP TxData channel 3. */ + +/* Parallel Port Status Register as implemented by PCP2x4. */ +#define ESTB PP_STAT_POUT /* Echoed strobe. */ +#define INT_REQ PP_STAT_ACK /* Input data int request. */ +#define BUSY PP_STAT_ERR /* Interface Busy. */ + +/* Parallel Port Status Register BUSY and SELECT lines are multiplexed + * between several functions. Depending on which 2x4 "register" is + * currently selected (b1..b3), the BUSY and SELECT lines are + * assigned as follows: + * + * SELECT LINE: A3 A2 A1 + * -------- + */ +#define RXAVAIL PP_STAT_SEL /* Rx Available, channel 0. 0 0 0 */ +// RXAVAIL1 PP_STAT_SEL /* Rx Available, channel 1. 0 0 1 */ +#define SYNC_STAT PP_STAT_SEL /* Reserved - Sync Status. 0 1 0 */ +// /* Reserved. 0 1 1 */ +#define TXEMPTY PP_STAT_SEL /* Tx Empty, channel 0. 1 0 0 */ +// TXEMPTY1 PP_STAT_SEL /* Tx Empty, channel 1. 1 0 1 */ +// TXEMPTY2 PP_STAT_SEL /* Tx Empty, channel 2. 1 1 0 */ +// TXEMPTY3 PP_STAT_SEL /* Tx Empty, channel 3. 1 1 1 */ + +/* BUSY LINE: A3 A2 A1 + * -------- + */ +#define RXDATA PP_STAT_BSY /* Rx Input Data, channel 0. 0 0 0 */ +// RXDATA1 PP_STAT_BSY /* Rx Input Data, channel 1. 0 0 1 */ +#define SYNC_DATA PP_STAT_BSY /* Reserved - Sync Data. 0 1 0 */ + /* Reserved. 0 1 1 */ +#define DATA_ECHO PP_STAT_BSY /* Parallel Port Data Echo. 1 0 0 */ +#define A0_ECHO PP_STAT_BSY /* Address 0 Echo. 1 0 1 */ +#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_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); + + /* Get entering data byte and port number in BL and BH respectively. + * Set up Tx Channel address field for use with PP Cmd Register. + * Store address field in BH register. + * Inputs: AH = Output port number (0..3). + * AL = Data byte. + * command = TXDATA0 | INT_EN; + * Align port num with address field (b1...b3), + * set address for TXDatax, Strobe=0 + */ + command |= INT_EN; + + /* Disable interrupts so that the process is not interrupted, then + * write the address associated with the current Tx channel to the + * PP Command Reg. Do not set the Strobe signal yet. + */ + + 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. + */ + + 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_read_status(pm) & ESTB) == 0) + cpu_relax(); + + /* Release strobe and immediately re-allow interrupts. */ + portman_write_command(pm, command); + + while ((portman_read_status(pm) & ESTB) == ESTB) + cpu_relax(); + + /* PC/P BUSY is now set. We must wait until BUSY resets itself. + * We'll reenable ints while we're waiting. + */ + + while ((portman_read_status(pm) & BUSY) == BUSY) + cpu_relax(); + + /* Data sent. */ +} + + +/* + * 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_write_data(pm, 0); /* Make sure edge is down. */ + + /* Set destination address to PCP. */ + cmdout = (port << 1) | INT_EN; /* Address + IE + No Strobe. */ + portman_write_command(pm, cmdout); + + while ((portman_read_status(pm) & ESTB) == ESTB) + cpu_relax(); /* Wait for strobe echo. */ + + /* After the address lines settle, check multiplexed RxAvail signal. + * If data is available, read it. + */ + if ((portman_read_status(pm) & RXAVAIL) == 0) + return -1; /* No data. */ + + /* Set the Strobe signal to enable the Rx clocking circuitry. */ + portman_write_command(pm, cmdout | STROBE); /* Write address+IE+Strobe. */ + + while ((portman_read_status(pm) & ESTB) == 0) + cpu_relax(); /* Wait for strobe echo. */ + + /* The first data bit (msb) is already sitting on the input line. */ + midi_data = (portman_read_status(pm) & 128); + portman_write_data(pm, 1); /* Cause rising edge, which shifts data. */ + + /* Data bit 6. */ + 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_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_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_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_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_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_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_write_command(pm, cmdout); /* Output saved address+IE. */ + + /* Wait for strobe echo. */ + while ((portman_read_status(pm) & ESTB) == ESTB) + cpu_relax(); + + 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_data_avail(struct portman *pm, int channel) +{ + int command = INT_EN; + switch (channel) { + case 0: + command |= RXDATA0; + break; + case 1: + command |= RXDATA1; + break; + } + /* Write hardware (assumme STROBE=0) */ + portman_write_command(pm, command); + /* Check multiplexed RxAvail signal */ + if ((portman_read_status(pm) & RXAVAIL) == RXAVAIL) + return 1; /* Data available */ + + /* No Data available */ + return 0; +} + + +/* + * Flushes any input + */ +static void portman_flush_input(struct portman *pm, unsigned char port) +{ + /* Local variable for counting things */ + unsigned int i = 0; + unsigned char command = 0; + + switch (port) { + case 0: + command = RXDATA0; + break; + case 1: + command = RXDATA1; + break; + default: + snd_printk(KERN_WARNING + "portman_flush_input() Won't flush port %i\n", + port); + return; + } + + /* Set address for specified channel in port and allow to settle. */ + portman_write_command(pm, command); + + /* Assert the Strobe and wait for echo back. */ + portman_write_command(pm, command | STROBE); + + /* Wait for ESTB */ + while ((portman_read_status(pm) & ESTB) == 0) + cpu_relax(); + + /* Output clock cycles to the Rx circuitry. */ + portman_write_data(pm, 0); + + /* Flush 250 bits... */ + 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_write_command(pm, command | INT_EN); + + /* Wait for settling */ + while ((portman_read_status(pm) & ESTB) == ESTB) + cpu_relax(); +} + +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 */ + parport_write_data(p, 0); + + /* Initialize the parallel port command register, thus initializing + * hardware handshake lines to midi box: + * + * Strobe = 0 + * Interrupt Enable = 0 + */ + /* 2 */ + parport_write_control(p, 0); + + /* Check if Portman PC/P 2x4 is out there. */ + /* 3 */ + parport_write_control(p, RXDATA0); /* Write Strobe=0 to command reg. */ + + /* Check for ESTB to be clear */ + /* 4 */ + if ((parport_read_status(p) & ESTB) == ESTB) + return 1; /* CODE 1 - Strobe Failure. */ + + /* Set for RXDATA0 where no damage will be done. */ + /* 5 */ + parport_write_control(p, RXDATA0 + STROBE); /* Write Strobe=1 to command reg. */ + + /* 6 */ + if ((parport_read_status(p) & ESTB) != ESTB) + return 1; /* CODE 1 - Strobe Failure. */ + + /* 7 */ + 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 */ + 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 ((parport_read_status(p) & TXEMPTY) == 0) + return 2; + + /* Return OK status. */ + return 0; +} + +static int portman_device_init(struct portman *pm) +{ + portman_flush_input(pm, 0); + portman_flush_input(pm, 1); + + return 0; +} + +/********************************************************************* + * Rawmidi + *********************************************************************/ +static int snd_portman_midi_open(struct snd_rawmidi_substream *substream) +{ + return 0; +} + +static int snd_portman_midi_close(struct snd_rawmidi_substream *substream) +{ + return 0; +} + +static void snd_portman_midi_input_trigger(struct snd_rawmidi_substream *substream, + int up) +{ + struct portman *pm = substream->rmidi->private_data; + unsigned long flags; + + spin_lock_irqsave(&pm->reg_lock, flags); + if (up) + pm->mode[substream->number] |= PORTMAN2X4_MODE_INPUT_TRIGGERED; + else + 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; + + spin_lock_irqsave(&pm->reg_lock, flags); + if (up) { + while ((snd_rawmidi_transmit(substream, &byte, 1) == 1)) + 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_open, + .close = snd_portman_midi_close, + .trigger = snd_portman_midi_output_trigger, +}; + +static struct snd_rawmidi_ops snd_portman_midi_input = { + .open = snd_portman_midi_open, + .close = snd_portman_midi_close, + .trigger = snd_portman_midi_input_trigger, +}; + +/* 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; + int err; + + err = snd_rawmidi_new(card, CARD_NAME, 0, + PORTMAN_NUM_OUTPUT_PORTS, + PORTMAN_NUM_INPUT_PORTS, + &rmidi); + if (err < 0) + return err; + + 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_portman_midi_input); + + /* name substreams */ + /* output */ + list_for_each_entry(substream, + &rmidi->streams[SNDRV_RAWMIDI_STREAM_OUTPUT].substreams, + list) { + sprintf(substream->name, + "Portman2x4 %d", substream->number+1); + } + /* input */ + list_for_each_entry(substream, + &rmidi->streams[SNDRV_RAWMIDI_STREAM_INPUT].substreams, + list) { + pm->midi_input[substream->number] = substream; + sprintf(substream->name, + "Portman2x4 %d", substream->number+1); + } + + return err; +} + +/********************************************************************* + * parport stuff + *********************************************************************/ +static void snd_portman_interrupt(int irq, void *userdata) +{ + unsigned char midivalue = 0; + struct portman *pm = ((struct snd_card*)userdata)->private_data; + + spin_lock(&pm->reg_lock); + + /* 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(&pm->reg_lock); +} + +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; + + p = platform_get_drvdata(pdev); + platform_set_drvdata(pdev, NULL); + + if (dev >= SNDRV_CARDS) + return -ENODEV; + 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_printd("Cannot create card\n"); + return -ENOMEM; + } + 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(KERN_INFO "Portman 2x4 on 0x%lx\n", p->base); + return 0; + +__err: + snd_card_free(card); + return err; +} + +static int __devexit 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 = __devexit_p(snd_portman_remove), + .driver = { + .name = PLATFORM_DRIVER + } +}; + +/********************************************************************* + * module init stuff + *********************************************************************/ +static void __init_or_module 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; + + 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 snd_portman_module_exit(void) +{ + snd_portman_unregister_all(); +} + +module_init(snd_portman_module_init); +module_exit(snd_portman_module_exit); diff --git a/sound/drivers/serial-u16550.c b/sound/drivers/serial-u16550.c index 74028b2219c2..838a4277929d 100644 --- a/sound/drivers/serial-u16550.c +++ b/sound/drivers/serial-u16550.c @@ -117,13 +117,13 @@ MODULE_PARM_DESC(adaptor, "Type of adaptor."); #define SERIAL_MODE_INPUT_TRIGGERED (1 << 2) #define SERIAL_MODE_OUTPUT_TRIGGERED (1 << 3) -typedef struct _snd_uart16550 { +struct snd_uart16550 { struct snd_card *card; struct snd_rawmidi *rmidi; struct snd_rawmidi_substream *midi_output[SNDRV_SERIAL_MAX_OUTS]; struct snd_rawmidi_substream *midi_input[SNDRV_SERIAL_MAX_INS]; - int filemode; //open status of file + int filemode; /* open status of file */ spinlock_t open_lock; @@ -140,39 +140,39 @@ typedef struct _snd_uart16550 { unsigned char old_divisor_msb; unsigned char old_line_ctrl_reg; - // parameter for using of write loop - short int fifo_limit; //used in uart16550 - short int fifo_count; //used in uart16550 + /* parameter for using of write loop */ + short int fifo_limit; /* used in uart16550 */ + short int fifo_count; /* used in uart16550 */ - // type of adaptor + /* type of adaptor */ int adaptor; - // inputs + /* inputs */ int prev_in; unsigned char rstatus; - // outputs + /* outputs */ int prev_out; unsigned char prev_status[SNDRV_SERIAL_MAX_OUTS]; - // write buffer and its writing/reading position + /* write buffer and its writing/reading position */ unsigned char tx_buff[TX_BUFF_SIZE]; int buff_in_count; int buff_in; int buff_out; int drop_on_full; - // wait timer + /* wait timer */ unsigned int timer_running:1; struct timer_list buffer_timer; -} snd_uart16550_t; +}; static struct platform_device *devices[SNDRV_CARDS]; -static inline void snd_uart16550_add_timer(snd_uart16550_t *uart) +static inline void snd_uart16550_add_timer(struct snd_uart16550 *uart) { - if (! uart->timer_running) { + if (!uart->timer_running) { /* timer 38600bps * 10bit * 16byte */ uart->buffer_timer.expires = jiffies + (HZ+255)/256; uart->timer_running = 1; @@ -180,7 +180,7 @@ static inline void snd_uart16550_add_timer(snd_uart16550_t *uart) } } -static inline void snd_uart16550_del_timer(snd_uart16550_t *uart) +static inline void snd_uart16550_del_timer(struct snd_uart16550 *uart) { if (uart->timer_running) { del_timer(&uart->buffer_timer); @@ -189,10 +189,10 @@ static inline void snd_uart16550_del_timer(snd_uart16550_t *uart) } /* This macro is only used in snd_uart16550_io_loop */ -static inline void snd_uart16550_buffer_output(snd_uart16550_t *uart) +static inline void snd_uart16550_buffer_output(struct snd_uart16550 *uart) { unsigned short buff_out = uart->buff_out; - if( uart->buff_in_count > 0 ) { + if (uart->buff_in_count > 0) { outb(uart->tx_buff[buff_out], uart->base + UART_TX); uart->fifo_count++; buff_out++; @@ -206,7 +206,7 @@ static inline void snd_uart16550_buffer_output(snd_uart16550_t *uart) * We don't want to interrupt this, * as we're already handling an interrupt */ -static void snd_uart16550_io_loop(snd_uart16550_t * uart) +static void snd_uart16550_io_loop(struct snd_uart16550 * uart) { unsigned char c, status; int substream; @@ -220,9 +220,8 @@ static void snd_uart16550_io_loop(snd_uart16550_t * uart) c = inb(uart->base + UART_RX); /* keep track of last status byte */ - if (c & 0x80) { + if (c & 0x80) uart->rstatus = c; - } /* handle stream switch */ if (uart->adaptor == SNDRV_SERIAL_GENERIC) { @@ -230,14 +229,16 @@ static void snd_uart16550_io_loop(snd_uart16550_t * uart) if (c <= SNDRV_SERIAL_MAX_INS && c > 0) substream = c - 1; if (c != 0xf5) - uart->rstatus = 0; /* prevent future bytes from being interpreted as streams */ - } - else if ((uart->filemode & SERIAL_MODE_INPUT_OPEN) && (uart->midi_input[substream] != NULL)) { - snd_rawmidi_receive(uart->midi_input[substream], &c, 1); - } - } else if ((uart->filemode & SERIAL_MODE_INPUT_OPEN) && (uart->midi_input[substream] != NULL)) { + /* prevent future bytes from being + interpreted as streams */ + uart->rstatus = 0; + } else if ((uart->filemode & SERIAL_MODE_INPUT_OPEN) + && uart->midi_input[substream]) + snd_rawmidi_receive(uart->midi_input[substream], + &c, 1); + } else if ((uart->filemode & SERIAL_MODE_INPUT_OPEN) && + uart->midi_input[substream]) snd_rawmidi_receive(uart->midi_input[substream], &c, 1); - } if (status & UART_LSR_OE) snd_printk("%s: Overrun on device at 0x%lx\n", @@ -250,21 +251,20 @@ static void snd_uart16550_io_loop(snd_uart16550_t * uart) /* no need of check SERIAL_MODE_OUTPUT_OPEN because if not, buffer is never filled. */ /* Check write status */ - if (status & UART_LSR_THRE) { + if (status & UART_LSR_THRE) uart->fifo_count = 0; - } if (uart->adaptor == SNDRV_SERIAL_MS124W_SA || uart->adaptor == SNDRV_SERIAL_GENERIC) { /* Can't use FIFO, must send only when CTS is true */ status = inb(uart->base + UART_MSR); - while( (uart->fifo_count == 0) && (status & UART_MSR_CTS) && - (uart->buff_in_count > 0) ) { + while (uart->fifo_count == 0 && (status & UART_MSR_CTS) && + uart->buff_in_count > 0) { snd_uart16550_buffer_output(uart); - status = inb( uart->base + UART_MSR ); + status = inb(uart->base + UART_MSR); } } else { /* Write loop */ - while (uart->fifo_count < uart->fifo_limit /* Can we write ? */ + while (uart->fifo_count < uart->fifo_limit /* Can we write ? */ && uart->buff_in_count > 0) /* Do we want to? */ snd_uart16550_buffer_output(uart); } @@ -294,15 +294,16 @@ static void snd_uart16550_io_loop(snd_uart16550_t * uart) */ static irqreturn_t snd_uart16550_interrupt(int irq, void *dev_id) { - snd_uart16550_t *uart; + struct snd_uart16550 *uart; - uart = (snd_uart16550_t *) dev_id; + uart = dev_id; spin_lock(&uart->open_lock); if (uart->filemode == SERIAL_MODE_NOT_OPENED) { spin_unlock(&uart->open_lock); return IRQ_NONE; } - inb(uart->base + UART_IIR); /* indicate to the UART that the interrupt has been serviced */ + /* indicate to the UART that the interrupt has been serviced */ + inb(uart->base + UART_IIR); snd_uart16550_io_loop(uart); spin_unlock(&uart->open_lock); return IRQ_HANDLED; @@ -312,9 +313,9 @@ static irqreturn_t snd_uart16550_interrupt(int irq, void *dev_id) static void snd_uart16550_buffer_timer(unsigned long data) { unsigned long flags; - snd_uart16550_t *uart; + struct snd_uart16550 *uart; - uart = (snd_uart16550_t *)data; + uart = (struct snd_uart16550 *)data; spin_lock_irqsave(&uart->open_lock, flags); snd_uart16550_del_timer(uart); snd_uart16550_io_loop(uart); @@ -326,7 +327,7 @@ static void snd_uart16550_buffer_timer(unsigned long data) * return 0 if found * return negative error if not found */ -static int __init snd_uart16550_detect(snd_uart16550_t *uart) +static int __devinit snd_uart16550_detect(struct snd_uart16550 *uart) { unsigned long io_base = uart->base; int ok; @@ -343,7 +344,8 @@ static int __init snd_uart16550_detect(snd_uart16550_t *uart) return -EBUSY; } - ok = 1; /* uart detected unless one of the following tests should fail */ + /* uart detected unless one of the following tests should fail */ + ok = 1; /* 8 data-bits, 1 stop-bit, parity off, DLAB = 0 */ outb(UART_LCR_WLEN8, io_base + UART_LCR); /* Line Control Register */ c = inb(io_base + UART_IER); @@ -368,7 +370,7 @@ static int __init snd_uart16550_detect(snd_uart16550_t *uart) return ok; } -static void snd_uart16550_do_open(snd_uart16550_t * uart) +static void snd_uart16550_do_open(struct snd_uart16550 * uart) { char byte; @@ -460,7 +462,7 @@ static void snd_uart16550_do_open(snd_uart16550_t * uart) inb(uart->base + UART_RX); /* Clear any pre-existing receive interrupt */ } -static void snd_uart16550_do_close(snd_uart16550_t * uart) +static void snd_uart16550_do_close(struct snd_uart16550 * uart) { if (uart->irq < 0) snd_uart16550_del_timer(uart); @@ -514,7 +516,7 @@ static void snd_uart16550_do_close(snd_uart16550_t * uart) static int snd_uart16550_input_open(struct snd_rawmidi_substream *substream) { unsigned long flags; - snd_uart16550_t *uart = substream->rmidi->private_data; + struct snd_uart16550 *uart = substream->rmidi->private_data; spin_lock_irqsave(&uart->open_lock, flags); if (uart->filemode == SERIAL_MODE_NOT_OPENED) @@ -528,7 +530,7 @@ static int snd_uart16550_input_open(struct snd_rawmidi_substream *substream) static int snd_uart16550_input_close(struct snd_rawmidi_substream *substream) { unsigned long flags; - snd_uart16550_t *uart = substream->rmidi->private_data; + struct snd_uart16550 *uart = substream->rmidi->private_data; spin_lock_irqsave(&uart->open_lock, flags); uart->filemode &= ~SERIAL_MODE_INPUT_OPEN; @@ -539,24 +541,24 @@ static int snd_uart16550_input_close(struct snd_rawmidi_substream *substream) return 0; } -static void snd_uart16550_input_trigger(struct snd_rawmidi_substream *substream, int up) +static void snd_uart16550_input_trigger(struct snd_rawmidi_substream *substream, + int up) { unsigned long flags; - snd_uart16550_t *uart = substream->rmidi->private_data; + struct snd_uart16550 *uart = substream->rmidi->private_data; spin_lock_irqsave(&uart->open_lock, flags); - if (up) { + if (up) uart->filemode |= SERIAL_MODE_INPUT_TRIGGERED; - } else { + else uart->filemode &= ~SERIAL_MODE_INPUT_TRIGGERED; - } spin_unlock_irqrestore(&uart->open_lock, flags); } static int snd_uart16550_output_open(struct snd_rawmidi_substream *substream) { unsigned long flags; - snd_uart16550_t *uart = substream->rmidi->private_data; + struct snd_uart16550 *uart = substream->rmidi->private_data; spin_lock_irqsave(&uart->open_lock, flags); if (uart->filemode == SERIAL_MODE_NOT_OPENED) @@ -570,7 +572,7 @@ static int snd_uart16550_output_open(struct snd_rawmidi_substream *substream) static int snd_uart16550_output_close(struct snd_rawmidi_substream *substream) { unsigned long flags; - snd_uart16550_t *uart = substream->rmidi->private_data; + struct snd_uart16550 *uart = substream->rmidi->private_data; spin_lock_irqsave(&uart->open_lock, flags); uart->filemode &= ~SERIAL_MODE_OUTPUT_OPEN; @@ -581,18 +583,20 @@ static int snd_uart16550_output_close(struct snd_rawmidi_substream *substream) return 0; }; -static inline int snd_uart16550_buffer_can_write( snd_uart16550_t *uart, int Num ) +static inline int snd_uart16550_buffer_can_write(struct snd_uart16550 *uart, + int Num) { - if( uart->buff_in_count + Num < TX_BUFF_SIZE ) + if (uart->buff_in_count + Num < TX_BUFF_SIZE) return 1; else return 0; } -static inline int snd_uart16550_write_buffer(snd_uart16550_t *uart, unsigned char byte) +static inline int snd_uart16550_write_buffer(struct snd_uart16550 *uart, + unsigned char byte) { unsigned short buff_in = uart->buff_in; - if( uart->buff_in_count < TX_BUFF_SIZE ) { + if (uart->buff_in_count < TX_BUFF_SIZE) { uart->tx_buff[buff_in] = byte; buff_in++; buff_in &= TX_BUFF_MASK; @@ -605,12 +609,14 @@ static inline int snd_uart16550_write_buffer(snd_uart16550_t *uart, unsigned cha return 0; } -static int snd_uart16550_output_byte(snd_uart16550_t *uart, struct snd_rawmidi_substream *substream, unsigned char midi_byte) +static int snd_uart16550_output_byte(struct snd_uart16550 *uart, + struct snd_rawmidi_substream *substream, + unsigned char midi_byte) { - if (uart->buff_in_count == 0 /* Buffer empty? */ + if (uart->buff_in_count == 0 /* Buffer empty? */ && ((uart->adaptor != SNDRV_SERIAL_MS124W_SA && uart->adaptor != SNDRV_SERIAL_GENERIC) || - (uart->fifo_count == 0 /* FIFO empty? */ + (uart->fifo_count == 0 /* FIFO empty? */ && (inb(uart->base + UART_MSR) & UART_MSR_CTS)))) { /* CTS? */ /* Tx Buffer Empty - try to write immediately */ @@ -623,12 +629,13 @@ static int snd_uart16550_output_byte(snd_uart16550_t *uart, struct snd_rawmidi_s uart->fifo_count++; outb(midi_byte, uart->base + UART_TX); } else { - /* Cannot write (buffer empty) - put char in buffer */ + /* Cannot write (buffer empty) - + * put char in buffer */ snd_uart16550_write_buffer(uart, midi_byte); } } } else { - if( !snd_uart16550_write_buffer(uart, midi_byte) ) { + if (!snd_uart16550_write_buffer(uart, midi_byte)) { snd_printk("%s: Buffer overrun on device at 0x%lx\n", uart->rmidi->name, uart->base); return 0; @@ -642,9 +649,9 @@ static void snd_uart16550_output_write(struct snd_rawmidi_substream *substream) { unsigned long flags; unsigned char midi_byte, addr_byte; - snd_uart16550_t *uart = substream->rmidi->private_data; + struct snd_uart16550 *uart = substream->rmidi->private_data; char first; - static unsigned long lasttime=0; + static unsigned long lasttime = 0; /* Interupts are disabled during the updating of the tx_buff, * since it is 'bad' to have two processes updating the same @@ -653,7 +660,7 @@ static void snd_uart16550_output_write(struct snd_rawmidi_substream *substream) spin_lock_irqsave(&uart->open_lock, flags); - if (uart->irq < 0) //polling + if (uart->irq < 0) /* polling */ snd_uart16550_io_loop(uart); if (uart->adaptor == SNDRV_SERIAL_MS124W_MB) { @@ -671,7 +678,8 @@ static void snd_uart16550_output_write(struct snd_rawmidi_substream *substream) /* select any combination of the four ports */ addr_byte = (substream->number << 4) | 0x08; /* ...except none */ - if (addr_byte == 0x08) addr_byte = 0xf8; + if (addr_byte == 0x08) + addr_byte = 0xf8; #endif snd_uart16550_output_byte(uart, substream, addr_byte); /* send midi byte */ @@ -679,31 +687,42 @@ static void snd_uart16550_output_write(struct snd_rawmidi_substream *substream) } } else { first = 0; - while( 1 == snd_rawmidi_transmit_peek(substream, &midi_byte, 1) ) { - /* Also send F5 after 3 seconds with no data to handle device disconnect */ - if (first == 0 && (uart->adaptor == SNDRV_SERIAL_SOUNDCANVAS || - uart->adaptor == SNDRV_SERIAL_GENERIC) && - (uart->prev_out != substream->number || jiffies-lasttime > 3*HZ)) { - - if( snd_uart16550_buffer_can_write( uart, 3 ) ) { + while (snd_rawmidi_transmit_peek(substream, &midi_byte, 1) == 1) { + /* Also send F5 after 3 seconds with no data + * to handle device disconnect */ + if (first == 0 && + (uart->adaptor == SNDRV_SERIAL_SOUNDCANVAS || + uart->adaptor == SNDRV_SERIAL_GENERIC) && + (uart->prev_out != substream->number || + jiffies-lasttime > 3*HZ)) { + + if (snd_uart16550_buffer_can_write(uart, 3)) { /* Roland Soundcanvas part selection */ - /* If this substream of the data is different previous - substream in this uart, send the change part event */ + /* If this substream of the data is + * different previous substream + * in this uart, send the change part + * event + */ uart->prev_out = substream->number; /* change part */ - snd_uart16550_output_byte(uart, substream, 0xf5); + snd_uart16550_output_byte(uart, substream, + 0xf5); /* data */ - snd_uart16550_output_byte(uart, substream, uart->prev_out + 1); - /* If midi_byte is a data byte, send the previous status byte */ - if ((midi_byte < 0x80) && (uart->adaptor == SNDRV_SERIAL_SOUNDCANVAS)) + snd_uart16550_output_byte(uart, substream, + uart->prev_out + 1); + /* If midi_byte is a data byte, + * send the previous status byte */ + if (midi_byte < 0x80 && + uart->adaptor == SNDRV_SERIAL_SOUNDCANVAS) snd_uart16550_output_byte(uart, substream, uart->prev_status[uart->prev_out]); - } else if( !uart->drop_on_full ) + } else if (!uart->drop_on_full) break; } /* send midi byte */ - if( !snd_uart16550_output_byte(uart, substream, midi_byte) && !uart->drop_on_full ) + if (!snd_uart16550_output_byte(uart, substream, midi_byte) && + !uart->drop_on_full ) break; if (midi_byte >= 0x80 && midi_byte < 0xf0) @@ -717,17 +736,17 @@ static void snd_uart16550_output_write(struct snd_rawmidi_substream *substream) spin_unlock_irqrestore(&uart->open_lock, flags); } -static void snd_uart16550_output_trigger(struct snd_rawmidi_substream *substream, int up) +static void snd_uart16550_output_trigger(struct snd_rawmidi_substream *substream, + int up) { unsigned long flags; - snd_uart16550_t *uart = substream->rmidi->private_data; + struct snd_uart16550 *uart = substream->rmidi->private_data; spin_lock_irqsave(&uart->open_lock, flags); - if (up) { + if (up) uart->filemode |= SERIAL_MODE_OUTPUT_TRIGGERED; - } else { + else uart->filemode &= ~SERIAL_MODE_OUTPUT_TRIGGERED; - } spin_unlock_irqrestore(&uart->open_lock, flags); if (up) snd_uart16550_output_write(substream); @@ -747,10 +766,10 @@ static struct snd_rawmidi_ops snd_uart16550_input = .trigger = snd_uart16550_input_trigger, }; -static int snd_uart16550_free(snd_uart16550_t *uart) +static int snd_uart16550_free(struct snd_uart16550 *uart) { if (uart->irq >= 0) - free_irq(uart->irq, (void *)uart); + free_irq(uart->irq, uart); release_and_free_resource(uart->res_base); kfree(uart); return 0; @@ -758,23 +777,23 @@ static int snd_uart16550_free(snd_uart16550_t *uart) static int snd_uart16550_dev_free(struct snd_device *device) { - snd_uart16550_t *uart = device->device_data; + struct snd_uart16550 *uart = device->device_data; return snd_uart16550_free(uart); } -static int __init snd_uart16550_create(struct snd_card *card, +static int __devinit snd_uart16550_create(struct snd_card *card, unsigned long iobase, int irq, unsigned int speed, unsigned int base, int adaptor, int droponfull, - snd_uart16550_t **ruart) + struct snd_uart16550 **ruart) { static struct snd_device_ops ops = { .dev_free = snd_uart16550_dev_free, }; - snd_uart16550_t *uart; + struct snd_uart16550 *uart; int err; @@ -795,7 +814,7 @@ static int __init snd_uart16550_create(struct snd_card *card, if (irq >= 0 && irq != SNDRV_AUTO_IRQ) { if (request_irq(irq, snd_uart16550_interrupt, - IRQF_DISABLED, "Serial MIDI", (void *) uart)) { + IRQF_DISABLED, "Serial MIDI", uart)) { snd_printk("irq %d busy. Using Polling.\n", irq); } else { uart->irq = irq; @@ -841,25 +860,30 @@ static int __init snd_uart16550_create(struct snd_card *card, return 0; } -static void __init snd_uart16550_substreams(struct snd_rawmidi_str *stream) +static void __devinit snd_uart16550_substreams(struct snd_rawmidi_str *stream) { - struct list_head *list; + struct snd_rawmidi_substream *substream; - list_for_each(list, &stream->substreams) { - struct snd_rawmidi_substream *substream = list_entry(list, struct snd_rawmidi_substream, list); + list_for_each_entry(substream, &stream->substreams, list) { sprintf(substream->name, "Serial MIDI %d", substream->number + 1); } } -static int __init snd_uart16550_rmidi(snd_uart16550_t *uart, int device, int outs, int ins, struct snd_rawmidi **rmidi) +static int __devinit snd_uart16550_rmidi(struct snd_uart16550 *uart, int device, + int outs, int ins, + struct snd_rawmidi **rmidi) { struct snd_rawmidi *rrawmidi; int err; - if ((err = snd_rawmidi_new(uart->card, "UART Serial MIDI", device, outs, ins, &rrawmidi)) < 0) + err = snd_rawmidi_new(uart->card, "UART Serial MIDI", device, + outs, ins, &rrawmidi); + if (err < 0) return err; - snd_rawmidi_set_ops(rrawmidi, SNDRV_RAWMIDI_STREAM_INPUT, &snd_uart16550_input); - snd_rawmidi_set_ops(rrawmidi, SNDRV_RAWMIDI_STREAM_OUTPUT, &snd_uart16550_output); + snd_rawmidi_set_ops(rrawmidi, SNDRV_RAWMIDI_STREAM_INPUT, + &snd_uart16550_input); + snd_rawmidi_set_ops(rrawmidi, SNDRV_RAWMIDI_STREAM_OUTPUT, + &snd_uart16550_output); strcpy(rrawmidi->name, "Serial MIDI"); snd_uart16550_substreams(&rrawmidi->streams[SNDRV_RAWMIDI_STREAM_OUTPUT]); snd_uart16550_substreams(&rrawmidi->streams[SNDRV_RAWMIDI_STREAM_INPUT]); @@ -872,10 +896,10 @@ static int __init snd_uart16550_rmidi(snd_uart16550_t *uart, int device, int out return 0; } -static int __init snd_serial_probe(struct platform_device *devptr) +static int __devinit snd_serial_probe(struct platform_device *devptr) { struct snd_card *card; - snd_uart16550_t *uart; + struct snd_uart16550 *uart; int err; int dev = devptr->id; @@ -929,7 +953,8 @@ static int __init snd_serial_probe(struct platform_device *devptr) &uart)) < 0) goto _err; - if ((err = snd_uart16550_rmidi(uart, 0, outs[dev], ins[dev], &uart->rmidi)) < 0) + err = snd_uart16550_rmidi(uart, 0, outs[dev], ins[dev], &uart->rmidi); + if (err < 0) goto _err; sprintf(card->longname, "%s at 0x%lx, irq %d speed %d div %d outs %d ins %d adaptor %s droponfull %d", @@ -956,7 +981,7 @@ static int __init snd_serial_probe(struct platform_device *devptr) return err; } -static int snd_serial_remove(struct platform_device *devptr) +static int __devexit snd_serial_remove(struct platform_device *devptr) { snd_card_free(platform_get_drvdata(devptr)); platform_set_drvdata(devptr, NULL); @@ -967,7 +992,7 @@ static int snd_serial_remove(struct platform_device *devptr) static struct platform_driver snd_serial_driver = { .probe = snd_serial_probe, - .remove = snd_serial_remove, + .remove = __devexit_p( snd_serial_remove), .driver = { .name = SND_SERIAL_DRIVER }, diff --git a/sound/drivers/virmidi.c b/sound/drivers/virmidi.c index 59171f8200df..46f3d3486067 100644 --- a/sound/drivers/virmidi.c +++ b/sound/drivers/virmidi.c @@ -44,7 +44,6 @@ #include <sound/driver.h> #include <linux/init.h> #include <linux/wait.h> -#include <linux/sched.h> #include <linux/err.h> #include <linux/platform_device.h> #include <linux/moduleparam.h> @@ -85,7 +84,7 @@ struct snd_card_virmidi { static struct platform_device *devices[SNDRV_CARDS]; -static int __init snd_virmidi_probe(struct platform_device *devptr) +static int __devinit snd_virmidi_probe(struct platform_device *devptr) { struct snd_card *card; struct snd_card_virmidi *vmidi; @@ -129,7 +128,7 @@ static int __init snd_virmidi_probe(struct platform_device *devptr) return err; } -static int snd_virmidi_remove(struct platform_device *devptr) +static int __devexit snd_virmidi_remove(struct platform_device *devptr) { snd_card_free(platform_get_drvdata(devptr)); platform_set_drvdata(devptr, NULL); @@ -140,7 +139,7 @@ static int snd_virmidi_remove(struct platform_device *devptr) static struct platform_driver snd_virmidi_driver = { .probe = snd_virmidi_probe, - .remove = snd_virmidi_remove, + .remove = __devexit_p(snd_virmidi_remove), .driver = { .name = SND_VIRMIDI_DRIVER }, diff --git a/sound/drivers/vx/vx_mixer.c b/sound/drivers/vx/vx_mixer.c index 1613ed844ac6..f63152a6a223 100644 --- a/sound/drivers/vx/vx_mixer.c +++ b/sound/drivers/vx/vx_mixer.c @@ -716,7 +716,7 @@ static int vx_monitor_sw_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_ return 0; } -static DECLARE_TLV_DB_SCALE(db_scale_audio_gain, -10975, 25, 0); +static const DECLARE_TLV_DB_SCALE(db_scale_audio_gain, -10975, 25, 0); static struct snd_kcontrol_new vx_control_audio_gain = { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |