提交 0a3fd051 编写于 作者: L Linus Torvalds

Merge branch 'linus' of master.kernel.org:/pub/scm/linux/kernel/git/perex/alsa

* 'linus' of master.kernel.org:/pub/scm/linux/kernel/git/perex/alsa: (122 commits)
  [ALSA] version 1.0.14rc4
  [ALSA] Add speaker pin sequencing to hda_codec.c:snd_hda_parse_pin_def_config()
  [ALSA] hda-codec - Add ALC861VD Lenovo support
  [ALSA] hda-codec - Fix connection list in generic parser
  [ALSA] usb-audio: work around wrong wMaxPacketSize on ESI M4U
  [ALSA] usb-audio: work around broken M-Audio MidiSport Uno firmware
  [ALSA] usb-audio: explicitly match Logitech QuickCam
  [ALSA] hda-codec - Fix a typo
  [ALSA] hda-codec - Fix ALC880 uniwill auto-mutes
  [ALSA] hda-codec - Fix AD1988 SPDIF playback route control
  [ALSA] wm8750 typo fix
  [ALSA] wavefront: only declare isapnp on CONFIG_PNP
  [ALSA] hda-codec - bug fixes for stac92xx HDA codecs.
  [ALSA] add MODULE_FIRMWARE entries
  [ALSA] do not depend on FW_LOADER when internal firmware images are used
  [ALSA] hda-codec - Fix resume of STAC92xx codecs
  [ALSA] usbaudio - Revert the minimal period size fix patch
  [ALSA] hda-codec - Add support for new HP DV series laptops
  [ALSA] usb-audio - Fix the minimum period size per transfer mode
  [ALSA] sound/pcmcia/vx/vxpocket.c: fix an if() condition
  ...
...@@ -821,6 +821,7 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed. ...@@ -821,6 +821,7 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
6stack-dig 6-jack digital with SPDIF I/O 6stack-dig 6-jack digital with SPDIF I/O
arima Arima W820Di1 arima Arima W820Di1
macpro MacPro support macpro MacPro support
w2jc ASUS W2JC
auto auto-config reading BIOS (default) auto auto-config reading BIOS (default)
ALC883/888 ALC883/888
...@@ -852,6 +853,7 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed. ...@@ -852,6 +853,7 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
3stack-dig 3-jack with SPDIF OUT 3stack-dig 3-jack with SPDIF OUT
6stack-dig 6-jack with SPDIF OUT 6stack-dig 6-jack with SPDIF OUT
3stack-660 3-jack (for ALC660VD) 3stack-660 3-jack (for ALC660VD)
lenovo Lenovo 3000 C200
auto auto-config reading BIOS (default) auto auto-config reading BIOS (default)
CMI9880 CMI9880
...@@ -909,6 +911,7 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed. ...@@ -909,6 +911,7 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
macbook Intel Mac Book macbook Intel Mac Book
macbook-pro-v1 Intel Mac Book Pro 1st generation macbook-pro-v1 Intel Mac Book Pro 1st generation
macbook-pro Intel Mac Book Pro 2nd generation macbook-pro Intel Mac Book Pro 2nd generation
imac-intel Intel iMac
STAC9202/9250/9251 STAC9202/9250/9251
ref Reference board, base config ref Reference board, base config
...@@ -924,6 +927,10 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed. ...@@ -924,6 +927,10 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
vaio Setup for VAIO FE550G/SZ110 vaio Setup for VAIO FE550G/SZ110
vaio-ar Setup for VAIO AR vaio-ar Setup for VAIO AR
The model name "genric" is treated as a special case. When this
model is given, the driver uses the generic codec parser without
"codec-patch". It's sometimes good for testing and debugging.
If the default configuration doesn't work and one of the above If the default configuration doesn't work and one of the above
matches with your device, report it together with the PCI matches with your device, report it together with the PCI
subsystem ID (output of "lspci -nv") to ALSA BTS or alsa-devel subsystem ID (output of "lspci -nv") to ALSA BTS or alsa-devel
...@@ -1278,6 +1285,7 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed. ...@@ -1278,6 +1285,7 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
port - port number or -1 (disable) port - port number or -1 (disable)
irq - IRQ number or -1 (disable) irq - IRQ number or -1 (disable)
pnp - PnP detection - 0 = disable, 1 = enable (default) pnp - PnP detection - 0 = disable, 1 = enable (default)
uart_enter - Issue UART_ENTER command at open - bool, default = on
This module supports multiple devices and PnP. This module supports multiple devices and PnP.
...@@ -1692,6 +1700,17 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed. ...@@ -1692,6 +1700,17 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
This module supports multiple devices, autoprobe and hotplugging. This module supports multiple devices, autoprobe and hotplugging.
Module snd-usb-caiaq
--------------------
Module for caiaq UB audio interfaces,
* Native Instruments RigKontrol2
* Native Instruments Kore Controller
* Native Instruments Audio Kontrol 1
* Native Instruments Audio 8 DJ
This module supports multiple devices, autoprobe and hotplugging.
Module snd-usb-usx2y Module snd-usb-usx2y
-------------------- --------------------
...@@ -2046,4 +2065,4 @@ Links and Addresses ...@@ -2046,4 +2065,4 @@ Links and Addresses
https://bugtrack.alsa-project.org/bugs/ https://bugtrack.alsa-project.org/bugs/
ALSA Developers ML ALSA Developers ML
mailto:alsa-devel@lists.sourceforge.net mailto:alsa-devel@alsa-project.org
...@@ -36,8 +36,8 @@ recorded data is not right, try to specify the digital_rate option with ...@@ -36,8 +36,8 @@ recorded data is not right, try to specify the digital_rate option with
other values than the default 32000 (often it's 44100 or 64000). other values than the default 32000 (often it's 44100 or 64000).
If you have an unknown card, please mail the ID and board name to If you have an unknown card, please mail the ID and board name to
<alsa-devel@lists.sf.net>, regardless of whether audio capture works or <alsa-devel@alsa-project.org>, regardless of whether audio capture works
not, so that future versions of this driver know about your card. or not, so that future versions of this driver know about your card.
Audio modes Audio modes
......
...@@ -372,7 +372,7 @@ AOA (Apple Onboard Audio) ALSA DRIVER ...@@ -372,7 +372,7 @@ AOA (Apple Onboard Audio) ALSA DRIVER
P: Johannes Berg P: Johannes Berg
M: johannes@sipsolutions.net M: johannes@sipsolutions.net
L: linuxppc-dev@ozlabs.org L: linuxppc-dev@ozlabs.org
L: alsa-devel@alsa-project.org L: alsa-devel@alsa-project.org (subscribers-only)
S: Maintained S: Maintained
APM DRIVER APM DRIVER
...@@ -3239,13 +3239,13 @@ S: Maintained ...@@ -3239,13 +3239,13 @@ S: Maintained
SOUND SOUND
P: Jaroslav Kysela P: Jaroslav Kysela
M: perex@suse.cz M: perex@suse.cz
L: alsa-devel@alsa-project.org L: alsa-devel@alsa-project.org (subscribers-only)
S: Maintained S: Maintained
SOUND - SOC LAYER / DYNAMIC AUDIO POWER MANAGEMENT SOUND - SOC LAYER / DYNAMIC AUDIO POWER MANAGEMENT
P: Liam Girdwood P: Liam Girdwood
M: liam.girdwood@wolfsonmicro.com M: liam.girdwood@wolfsonmicro.com
L: alsa-devel@alsa-project.org L: alsa-devel@alsa-project.org (subscribers-only)
S: Supported S: Supported
SPI SUBSYSTEM SPI SUBSYSTEM
......
...@@ -117,6 +117,7 @@ ...@@ -117,6 +117,7 @@
#define I2C_DRIVERID_ISL1208 88 /* Intersil ISL1208 RTC */ #define I2C_DRIVERID_ISL1208 88 /* Intersil ISL1208 RTC */
#define I2C_DRIVERID_WM8731 89 /* Wolfson WM8731 audio codec */ #define I2C_DRIVERID_WM8731 89 /* Wolfson WM8731 audio codec */
#define I2C_DRIVERID_WM8750 90 /* Wolfson WM8750 audio codec */ #define I2C_DRIVERID_WM8750 90 /* Wolfson WM8750 audio codec */
#define I2C_DRIVERID_WM8753 91 /* Wolfson WM8753 audio codec */
#define I2C_DRIVERID_I2CDEV 900 #define I2C_DRIVERID_I2CDEV 900
#define I2C_DRIVERID_ARP 902 /* SMBus ARP Client */ #define I2C_DRIVERID_ARP 902 /* SMBus ARP Client */
......
...@@ -73,7 +73,7 @@ ...@@ -73,7 +73,7 @@
/* AK4114_REQ_FORMAT bits */ /* AK4114_REQ_FORMAT bits */
#define AK4114_MONO (1<<7) /* Double Sampling Frequency Mode: 0 = stereo, 1 = mono */ #define AK4114_MONO (1<<7) /* Double Sampling Frequency Mode: 0 = stereo, 1 = mono */
#define AK4114_DIF2 (1<<5) /* Audio Data Control */ #define AK4114_DIF2 (1<<6) /* Audio Data Control */
#define AK4114_DIF1 (1<<5) /* Audio Data Control */ #define AK4114_DIF1 (1<<5) /* Audio Data Control */
#define AK4114_DIF0 (1<<4) /* Audio Data Control */ #define AK4114_DIF0 (1<<4) /* Audio Data Control */
#define AK4114_DIF_16R (0) /* STDO: 16-bit, right justified */ #define AK4114_DIF_16R (0) /* STDO: 16-bit, right justified */
...@@ -158,7 +158,7 @@ ...@@ -158,7 +158,7 @@
#define AK4114_CHECK_NO_STAT (1<<0) /* no statistics */ #define AK4114_CHECK_NO_STAT (1<<0) /* no statistics */
#define AK4114_CHECK_NO_RATE (1<<1) /* no rate check */ #define AK4114_CHECK_NO_RATE (1<<1) /* no rate check */
#define AK4114_CONTROLS 14 #define AK4114_CONTROLS 15
typedef void (ak4114_write_t)(void *private_data, unsigned char addr, unsigned char data); typedef void (ak4114_write_t)(void *private_data, unsigned char addr, unsigned char data);
typedef unsigned char (ak4114_read_t)(void *private_data, unsigned char addr); typedef unsigned char (ak4114_read_t)(void *private_data, unsigned char addr);
......
...@@ -50,6 +50,7 @@ ...@@ -50,6 +50,7 @@
#define MPU401_INFO_INTEGRATED (1 << 2) /* integrated h/w port */ #define MPU401_INFO_INTEGRATED (1 << 2) /* integrated h/w port */
#define MPU401_INFO_MMIO (1 << 3) /* MMIO access */ #define MPU401_INFO_MMIO (1 << 3) /* MMIO access */
#define MPU401_INFO_TX_IRQ (1 << 4) /* independent TX irq */ #define MPU401_INFO_TX_IRQ (1 << 4) /* independent TX irq */
#define MPU401_INFO_UART_ONLY (1 << 5) /* No ENTER_UART cmd needed */
#define MPU401_MODE_BIT_INPUT 0 #define MPU401_MODE_BIT_INPUT 0
#define MPU401_MODE_BIT_OUTPUT 1 #define MPU401_MODE_BIT_OUTPUT 1
......
...@@ -603,11 +603,8 @@ do { \ ...@@ -603,11 +603,8 @@ do { \
read_unlock_irqrestore(&snd_pcm_link_rwlock, (flags)); \ read_unlock_irqrestore(&snd_pcm_link_rwlock, (flags)); \
} while (0) } while (0)
#define snd_pcm_group_for_each(pos, substream) \ #define snd_pcm_group_for_each_entry(s, substream) \
list_for_each(pos, &substream->group->substreams) list_for_each_entry(s, &substream->group->substreams, link_list)
#define snd_pcm_group_substream_entry(pos) \
list_entry(pos, struct snd_pcm_substream, link_list)
static inline int snd_pcm_running(struct snd_pcm_substream *substream) static inline int snd_pcm_running(struct snd_pcm_substream *substream)
{ {
......
/* include/version.h. Generated by alsa/ksync script. */ /* include/version.h. Generated by alsa/ksync script. */
#define CONFIG_SND_VERSION "1.0.14rc3" #define CONFIG_SND_VERSION "1.0.14rc4"
#define CONFIG_SND_DATE " (Wed Mar 14 07:25:50 2007 UTC)" #define CONFIG_SND_DATE " (Wed May 09 09:51:39 2007 UTC)"
...@@ -1018,7 +1018,7 @@ static int onyx_create(struct i2c_adapter *adapter, ...@@ -1018,7 +1018,7 @@ static int onyx_create(struct i2c_adapter *adapter,
onyx->i2c.driver = &onyx_driver; onyx->i2c.driver = &onyx_driver;
onyx->i2c.adapter = adapter; onyx->i2c.adapter = adapter;
onyx->i2c.addr = addr & 0x7f; onyx->i2c.addr = addr & 0x7f;
strlcpy(onyx->i2c.name, "onyx audio codec", I2C_NAME_SIZE-1); strlcpy(onyx->i2c.name, "onyx audio codec", I2C_NAME_SIZE);
if (i2c_attach_client(&onyx->i2c)) { if (i2c_attach_client(&onyx->i2c)) {
printk(KERN_ERR PFX "failed to attach to i2c\n"); printk(KERN_ERR PFX "failed to attach to i2c\n");
...@@ -1033,7 +1033,7 @@ static int onyx_create(struct i2c_adapter *adapter, ...@@ -1033,7 +1033,7 @@ static int onyx_create(struct i2c_adapter *adapter,
goto fail; goto fail;
} }
strlcpy(onyx->codec.name, "onyx", MAX_CODEC_NAME_LEN-1); strlcpy(onyx->codec.name, "onyx", MAX_CODEC_NAME_LEN);
onyx->codec.owner = THIS_MODULE; onyx->codec.owner = THIS_MODULE;
onyx->codec.init = onyx_init_codec; onyx->codec.init = onyx_init_codec;
onyx->codec.exit = onyx_exit_codec; onyx->codec.exit = onyx_exit_codec;
......
...@@ -899,14 +899,14 @@ static int tas_create(struct i2c_adapter *adapter, ...@@ -899,14 +899,14 @@ static int tas_create(struct i2c_adapter *adapter,
tas->i2c.addr = addr; tas->i2c.addr = addr;
/* seems that half is a saner default */ /* seems that half is a saner default */
tas->drc_range = TAS3004_DRC_MAX / 2; tas->drc_range = TAS3004_DRC_MAX / 2;
strlcpy(tas->i2c.name, "tas audio codec", I2C_NAME_SIZE-1); strlcpy(tas->i2c.name, "tas audio codec", I2C_NAME_SIZE);
if (i2c_attach_client(&tas->i2c)) { if (i2c_attach_client(&tas->i2c)) {
printk(KERN_ERR PFX "failed to attach to i2c\n"); printk(KERN_ERR PFX "failed to attach to i2c\n");
goto fail; goto fail;
} }
strlcpy(tas->codec.name, "tas", MAX_CODEC_NAME_LEN-1); strlcpy(tas->codec.name, "tas", MAX_CODEC_NAME_LEN);
tas->codec.owner = THIS_MODULE; tas->codec.owner = THIS_MODULE;
tas->codec.init = tas_init_codec; tas->codec.init = tas_init_codec;
tas->codec.exit = tas_exit_codec; tas->codec.exit = tas_exit_codec;
......
...@@ -163,8 +163,6 @@ static int soundbus_device_resume(struct device * dev) ...@@ -163,8 +163,6 @@ static int soundbus_device_resume(struct device * dev)
#endif /* CONFIG_PM */ #endif /* CONFIG_PM */
extern struct device_attribute soundbus_dev_attrs[];
static struct bus_type soundbus_bus_type = { static struct bus_type soundbus_bus_type = {
.name = "aoa-soundbus", .name = "aoa-soundbus",
.probe = soundbus_probe, .probe = soundbus_probe,
......
...@@ -23,9 +23,6 @@ ...@@ -23,9 +23,6 @@
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
MODULE_AUTHOR("Johannes Berg <johannes@sipsolutions.net>"); MODULE_AUTHOR("Johannes Berg <johannes@sipsolutions.net>");
MODULE_DESCRIPTION("Apple Soundbus: I2S support"); MODULE_DESCRIPTION("Apple Soundbus: I2S support");
/* for auto-loading, declare that we handle this weird
* string that macio puts into the relevant device */
MODULE_ALIAS("of:Ni2sTi2sC");
static int force; static int force;
module_param(force, int, 0444); module_param(force, int, 0444);
...@@ -37,6 +34,8 @@ static struct of_device_id i2sbus_match[] = { ...@@ -37,6 +34,8 @@ static struct of_device_id i2sbus_match[] = {
{ } { }
}; };
MODULE_DEVICE_TABLE(of, i2sbus_match);
static int alloc_dbdma_descriptor_ring(struct i2sbus_dev *i2sdev, static int alloc_dbdma_descriptor_ring(struct i2sbus_dev *i2sdev,
struct dbdma_command_mem *r, struct dbdma_command_mem *r,
int numcmds) int numcmds)
......
...@@ -199,4 +199,6 @@ struct soundbus_driver { ...@@ -199,4 +199,6 @@ struct soundbus_driver {
extern int soundbus_register_driver(struct soundbus_driver *drv); extern int soundbus_register_driver(struct soundbus_driver *drv);
extern void soundbus_unregister_driver(struct soundbus_driver *drv); extern void soundbus_unregister_driver(struct soundbus_driver *drv);
extern struct device_attribute soundbus_dev_attrs[];
#endif /* __SOUNDBUS_H */ #endif /* __SOUNDBUS_H */
...@@ -712,26 +712,23 @@ static int snd_pcm_action_group(struct action_ops *ops, ...@@ -712,26 +712,23 @@ static int snd_pcm_action_group(struct action_ops *ops,
struct snd_pcm_substream *substream, struct snd_pcm_substream *substream,
int state, int do_lock) int state, int do_lock)
{ {
struct list_head *pos;
struct snd_pcm_substream *s = NULL; struct snd_pcm_substream *s = NULL;
struct snd_pcm_substream *s1; struct snd_pcm_substream *s1;
int res = 0; int res = 0;
snd_pcm_group_for_each(pos, substream) { snd_pcm_group_for_each_entry(s, substream) {
s = snd_pcm_group_substream_entry(pos);
if (do_lock && s != substream) if (do_lock && s != substream)
spin_lock(&s->self_group.lock); spin_lock_nested(&s->self_group.lock,
SINGLE_DEPTH_NESTING);
res = ops->pre_action(s, state); res = ops->pre_action(s, state);
if (res < 0) if (res < 0)
goto _unlock; goto _unlock;
} }
snd_pcm_group_for_each(pos, substream) { snd_pcm_group_for_each_entry(s, substream) {
s = snd_pcm_group_substream_entry(pos);
res = ops->do_action(s, state); res = ops->do_action(s, state);
if (res < 0) { if (res < 0) {
if (ops->undo_action) { if (ops->undo_action) {
snd_pcm_group_for_each(pos, substream) { snd_pcm_group_for_each_entry(s1, substream) {
s1 = snd_pcm_group_substream_entry(pos);
if (s1 == s) /* failed stream */ if (s1 == s) /* failed stream */
break; break;
ops->undo_action(s1, state); ops->undo_action(s1, state);
...@@ -741,15 +738,13 @@ static int snd_pcm_action_group(struct action_ops *ops, ...@@ -741,15 +738,13 @@ static int snd_pcm_action_group(struct action_ops *ops,
goto _unlock; goto _unlock;
} }
} }
snd_pcm_group_for_each(pos, substream) { snd_pcm_group_for_each_entry(s, substream) {
s = snd_pcm_group_substream_entry(pos);
ops->post_action(s, state); ops->post_action(s, state);
} }
_unlock: _unlock:
if (do_lock) { if (do_lock) {
/* unlock streams */ /* unlock streams */
snd_pcm_group_for_each(pos, substream) { snd_pcm_group_for_each_entry(s1, substream) {
s1 = snd_pcm_group_substream_entry(pos);
if (s1 != substream) if (s1 != substream)
spin_unlock(&s1->self_group.lock); spin_unlock(&s1->self_group.lock);
if (s1 == s) /* end */ if (s1 == s) /* end */
...@@ -1438,7 +1433,7 @@ static int snd_pcm_drain(struct snd_pcm_substream *substream) ...@@ -1438,7 +1433,7 @@ static int snd_pcm_drain(struct snd_pcm_substream *substream)
{ {
struct snd_card *card; struct snd_card *card;
struct snd_pcm_runtime *runtime; struct snd_pcm_runtime *runtime;
struct list_head *pos; struct snd_pcm_substream *s;
int result = 0; int result = 0;
int i, num_drecs; int i, num_drecs;
struct drain_rec *drec, drec_tmp, *d; struct drain_rec *drec, drec_tmp, *d;
...@@ -1473,8 +1468,7 @@ static int snd_pcm_drain(struct snd_pcm_substream *substream) ...@@ -1473,8 +1468,7 @@ static int snd_pcm_drain(struct snd_pcm_substream *substream)
/* count only playback streams */ /* count only playback streams */
num_drecs = 0; num_drecs = 0;
snd_pcm_group_for_each(pos, substream) { snd_pcm_group_for_each_entry(s, substream) {
struct snd_pcm_substream *s = snd_pcm_group_substream_entry(pos);
runtime = s->runtime; runtime = s->runtime;
if (s->stream == SNDRV_PCM_STREAM_PLAYBACK) { if (s->stream == SNDRV_PCM_STREAM_PLAYBACK) {
d = &drec[num_drecs++]; d = &drec[num_drecs++];
...@@ -1674,7 +1668,7 @@ static void relink_to_local(struct snd_pcm_substream *substream) ...@@ -1674,7 +1668,7 @@ static void relink_to_local(struct snd_pcm_substream *substream)
static int snd_pcm_unlink(struct snd_pcm_substream *substream) static int snd_pcm_unlink(struct snd_pcm_substream *substream)
{ {
struct list_head *pos; struct snd_pcm_substream *s;
int res = 0; int res = 0;
down_write(&snd_pcm_link_rwsem); down_write(&snd_pcm_link_rwsem);
...@@ -1686,8 +1680,8 @@ static int snd_pcm_unlink(struct snd_pcm_substream *substream) ...@@ -1686,8 +1680,8 @@ static int snd_pcm_unlink(struct snd_pcm_substream *substream)
list_del(&substream->link_list); list_del(&substream->link_list);
substream->group->count--; substream->group->count--;
if (substream->group->count == 1) { /* detach the last stream, too */ if (substream->group->count == 1) { /* detach the last stream, too */
snd_pcm_group_for_each(pos, substream) { snd_pcm_group_for_each_entry(s, substream) {
relink_to_local(snd_pcm_group_substream_entry(pos)); relink_to_local(s);
break; break;
} }
kfree(substream->group); kfree(substream->group);
......
...@@ -24,6 +24,7 @@ ...@@ -24,6 +24,7 @@
#include <linux/init.h> #include <linux/init.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/moduleparam.h> #include <linux/moduleparam.h>
#include <linux/log2.h>
#include <sound/core.h> #include <sound/core.h>
#include <sound/timer.h> #include <sound/timer.h>
...@@ -129,7 +130,7 @@ static int __init rtctimer_init(void) ...@@ -129,7 +130,7 @@ static int __init rtctimer_init(void)
struct snd_timer *timer; struct snd_timer *timer;
if (rtctimer_freq < 2 || rtctimer_freq > 8192 || if (rtctimer_freq < 2 || rtctimer_freq > 8192 ||
(rtctimer_freq & (rtctimer_freq - 1)) != 0) { !is_power_of_2(rtctimer_freq)) {
snd_printk(KERN_ERR "rtctimer: invalid frequency %d\n", snd_printk(KERN_ERR "rtctimer: invalid frequency %d\n",
rtctimer_freq); rtctimer_freq);
return -EINVAL; return -EINVAL;
......
...@@ -42,6 +42,7 @@ static int pnp[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 1}; ...@@ -42,6 +42,7 @@ static int pnp[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 1};
#endif #endif
static long port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; /* MPU-401 port number */ static long port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; /* MPU-401 port number */
static int irq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ; /* MPU-401 IRQ */ static int irq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ; /* MPU-401 IRQ */
static int uart_enter[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 1};
module_param_array(index, int, NULL, 0444); module_param_array(index, int, NULL, 0444);
MODULE_PARM_DESC(index, "Index value for MPU-401 device."); MODULE_PARM_DESC(index, "Index value for MPU-401 device.");
...@@ -57,6 +58,8 @@ module_param_array(port, long, NULL, 0444); ...@@ -57,6 +58,8 @@ module_param_array(port, long, NULL, 0444);
MODULE_PARM_DESC(port, "Port # for MPU-401 device."); MODULE_PARM_DESC(port, "Port # for MPU-401 device.");
module_param_array(irq, int, NULL, 0444); module_param_array(irq, int, NULL, 0444);
MODULE_PARM_DESC(irq, "IRQ # for MPU-401 device."); MODULE_PARM_DESC(irq, "IRQ # for MPU-401 device.");
module_param_array(uart_enter, bool, NULL, 0444);
MODULE_PARM_DESC(uart_enter, "Issue UART_ENTER command at open.");
static struct platform_device *platform_devices[SNDRV_CARDS]; static struct platform_device *platform_devices[SNDRV_CARDS];
static int pnp_registered; static int pnp_registered;
...@@ -80,10 +83,11 @@ static int snd_mpu401_create(int dev, struct snd_card **rcard) ...@@ -80,10 +83,11 @@ static int snd_mpu401_create(int dev, struct snd_card **rcard)
strcat(card->longname, "polled"); strcat(card->longname, "polled");
} }
if ((err = snd_mpu401_uart_new(card, 0, err = snd_mpu401_uart_new(card, 0, MPU401_HW_MPU401, port[dev],
MPU401_HW_MPU401, uart_enter[dev] ? 0 : MPU401_INFO_UART_ONLY,
port[dev], 0, irq[dev], irq[dev] >= 0 ? IRQF_DISABLED : 0,
irq[dev], irq[dev] >= 0 ? IRQF_DISABLED : 0, NULL)) < 0) { NULL);
if (err < 0) {
printk(KERN_ERR "MPU401 not detected at 0x%lx\n", port[dev]); printk(KERN_ERR "MPU401 not detected at 0x%lx\n", port[dev]);
goto _err; goto _err;
} }
......
...@@ -266,6 +266,16 @@ static int snd_mpu401_uart_cmd(struct snd_mpu401 * mpu, unsigned char cmd, ...@@ -266,6 +266,16 @@ static int snd_mpu401_uart_cmd(struct snd_mpu401 * mpu, unsigned char cmd,
return 0; return 0;
} }
static int snd_mpu401_do_reset(struct snd_mpu401 *mpu)
{
if (snd_mpu401_uart_cmd(mpu, MPU401_RESET, 1))
return -EIO;
if (!(mpu->info_flags & MPU401_INFO_UART_ONLY) &&
snd_mpu401_uart_cmd(mpu, MPU401_ENTER_UART, 1))
return -EIO;
return 0;
}
/* /*
* input/output open/close - protected by open_mutex in rawmidi.c * input/output open/close - protected by open_mutex in rawmidi.c
*/ */
...@@ -278,9 +288,7 @@ static int snd_mpu401_uart_input_open(struct snd_rawmidi_substream *substream) ...@@ -278,9 +288,7 @@ static int snd_mpu401_uart_input_open(struct snd_rawmidi_substream *substream)
if (mpu->open_input && (err = mpu->open_input(mpu)) < 0) if (mpu->open_input && (err = mpu->open_input(mpu)) < 0)
return err; return err;
if (! test_bit(MPU401_MODE_BIT_OUTPUT, &mpu->mode)) { if (! test_bit(MPU401_MODE_BIT_OUTPUT, &mpu->mode)) {
if (snd_mpu401_uart_cmd(mpu, MPU401_RESET, 1)) if (snd_mpu401_do_reset(mpu) < 0)
goto error_out;
if (snd_mpu401_uart_cmd(mpu, MPU401_ENTER_UART, 1))
goto error_out; goto error_out;
} }
mpu->substream_input = substream; mpu->substream_input = substream;
...@@ -302,9 +310,7 @@ static int snd_mpu401_uart_output_open(struct snd_rawmidi_substream *substream) ...@@ -302,9 +310,7 @@ static int snd_mpu401_uart_output_open(struct snd_rawmidi_substream *substream)
if (mpu->open_output && (err = mpu->open_output(mpu)) < 0) if (mpu->open_output && (err = mpu->open_output(mpu)) < 0)
return err; return err;
if (! test_bit(MPU401_MODE_BIT_INPUT, &mpu->mode)) { if (! test_bit(MPU401_MODE_BIT_INPUT, &mpu->mode)) {
if (snd_mpu401_uart_cmd(mpu, MPU401_RESET, 1)) if (snd_mpu401_do_reset(mpu) < 0)
goto error_out;
if (snd_mpu401_uart_cmd(mpu, MPU401_ENTER_UART, 1))
goto error_out; goto error_out;
} }
mpu->substream_output = substream; mpu->substream_output = substream;
......
...@@ -892,13 +892,13 @@ static void __devinit snd_mts64_attach(struct parport *p) ...@@ -892,13 +892,13 @@ static void __devinit snd_mts64_attach(struct parport *p)
struct platform_device *device; struct platform_device *device;
device = platform_device_alloc(PLATFORM_DRIVER, device_count); device = platform_device_alloc(PLATFORM_DRIVER, device_count);
if (!device) if (!device)
return; return;
/* Temporary assignment to forward the parport */ /* Temporary assignment to forward the parport */
platform_set_drvdata(device, p); platform_set_drvdata(device, p);
if (platform_device_register(device) < 0) { if (platform_device_add(device) < 0) {
platform_device_put(device); platform_device_put(device);
return; return;
} }
......
...@@ -676,13 +676,13 @@ static void __devinit snd_portman_attach(struct parport *p) ...@@ -676,13 +676,13 @@ static void __devinit snd_portman_attach(struct parport *p)
struct platform_device *device; struct platform_device *device;
device = platform_device_alloc(PLATFORM_DRIVER, device_count); device = platform_device_alloc(PLATFORM_DRIVER, device_count);
if (!device) if (!device)
return; return;
/* Temporary assignment to forward the parport */ /* Temporary assignment to forward the parport */
platform_set_drvdata(device, p); platform_set_drvdata(device, p);
if (platform_device_register(device) < 0) { if (platform_device_add(device) < 0) {
platform_device_put(device); platform_device_put(device);
return; return;
} }
......
...@@ -30,6 +30,20 @@ ...@@ -30,6 +30,20 @@
#ifdef SND_VX_FW_LOADER #ifdef SND_VX_FW_LOADER
MODULE_FIRMWARE("vx/bx_1_vxp.b56");
MODULE_FIRMWARE("vx/bx_1_vp4.b56");
MODULE_FIRMWARE("vx/x1_1_vx2.xlx");
MODULE_FIRMWARE("vx/x1_2_v22.xlx");
MODULE_FIRMWARE("vx/x1_1_vxp.xlx");
MODULE_FIRMWARE("vx/x1_1_vp4.xlx");
MODULE_FIRMWARE("vx/bd56002.boot");
MODULE_FIRMWARE("vx/bd563v2.boot");
MODULE_FIRMWARE("vx/bd563s3.boot");
MODULE_FIRMWARE("vx/l_1_vx2.d56");
MODULE_FIRMWARE("vx/l_1_v22.d56");
MODULE_FIRMWARE("vx/l_1_vxp.d56");
MODULE_FIRMWARE("vx/l_1_vp4.d56");
int snd_vx_setup_firmware(struct vx_core *chip) int snd_vx_setup_firmware(struct vx_core *chip)
{ {
static char *fw_files[VX_TYPE_NUMS][4] = { static char *fw_files[VX_TYPE_NUMS][4] = {
......
...@@ -36,6 +36,7 @@ MODULE_LICENSE("GPL"); ...@@ -36,6 +36,7 @@ MODULE_LICENSE("GPL");
#define AK4114_ADDR 0x00 /* fixed address */ #define AK4114_ADDR 0x00 /* fixed address */
static void ak4114_stats(struct work_struct *work); static void ak4114_stats(struct work_struct *work);
static void ak4114_init_regs(struct ak4114 *chip);
static void reg_write(struct ak4114 *ak4114, unsigned char reg, unsigned char val) static void reg_write(struct ak4114 *ak4114, unsigned char reg, unsigned char val)
{ {
...@@ -105,7 +106,7 @@ int snd_ak4114_create(struct snd_card *card, ...@@ -105,7 +106,7 @@ int snd_ak4114_create(struct snd_card *card,
for (reg = 0; reg < 5; reg++) for (reg = 0; reg < 5; reg++)
chip->txcsb[reg] = txcsb[reg]; chip->txcsb[reg] = txcsb[reg];
snd_ak4114_reinit(chip); ak4114_init_regs(chip);
chip->rcs0 = reg_read(chip, AK4114_REG_RCS0) & ~(AK4114_QINT | AK4114_CINT); chip->rcs0 = reg_read(chip, AK4114_REG_RCS0) & ~(AK4114_QINT | AK4114_CINT);
chip->rcs1 = reg_read(chip, AK4114_REG_RCS1); chip->rcs1 = reg_read(chip, AK4114_REG_RCS1);
...@@ -131,13 +132,10 @@ void snd_ak4114_reg_write(struct ak4114 *chip, unsigned char reg, unsigned char ...@@ -131,13 +132,10 @@ void snd_ak4114_reg_write(struct ak4114 *chip, unsigned char reg, unsigned char
(chip->txcsb[reg-AK4114_REG_TXCSB0] & ~mask) | val); (chip->txcsb[reg-AK4114_REG_TXCSB0] & ~mask) | val);
} }
void snd_ak4114_reinit(struct ak4114 *chip) static void ak4114_init_regs(struct ak4114 *chip)
{ {
unsigned char old = chip->regmap[AK4114_REG_PWRDN], reg; unsigned char old = chip->regmap[AK4114_REG_PWRDN], reg;
chip->init = 1;
mb();
flush_scheduled_work();
/* bring the chip to reset state and powerdown state */ /* bring the chip to reset state and powerdown state */
reg_write(chip, AK4114_REG_PWRDN, old & ~(AK4114_RST|AK4114_PWN)); reg_write(chip, AK4114_REG_PWRDN, old & ~(AK4114_RST|AK4114_PWN));
udelay(200); udelay(200);
...@@ -150,9 +148,18 @@ void snd_ak4114_reinit(struct ak4114 *chip) ...@@ -150,9 +148,18 @@ void snd_ak4114_reinit(struct ak4114 *chip)
reg_write(chip, reg + AK4114_REG_TXCSB0, chip->txcsb[reg]); reg_write(chip, reg + AK4114_REG_TXCSB0, chip->txcsb[reg]);
/* release powerdown, everything is initialized now */ /* release powerdown, everything is initialized now */
reg_write(chip, AK4114_REG_PWRDN, old | AK4114_RST | AK4114_PWN); reg_write(chip, AK4114_REG_PWRDN, old | AK4114_RST | AK4114_PWN);
}
void snd_ak4114_reinit(struct ak4114 *chip)
{
chip->init = 1;
mb();
flush_scheduled_work();
ak4114_init_regs(chip);
/* bring up statistics / event queing */ /* bring up statistics / event queing */
chip->init = 0; chip->init = 0;
schedule_delayed_work(&chip->work, HZ / 10); if (chip->kctls[0])
schedule_delayed_work(&chip->work, HZ / 10);
} }
static unsigned int external_rate(unsigned char rcs1) static unsigned int external_rate(unsigned char rcs1)
...@@ -428,7 +435,7 @@ static struct snd_kcontrol_new snd_ak4114_iec958_controls[] = { ...@@ -428,7 +435,7 @@ static struct snd_kcontrol_new snd_ak4114_iec958_controls[] = {
.access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE,
.info = snd_ak4114_in_bit_info, .info = snd_ak4114_in_bit_info,
.get = snd_ak4114_in_bit_get, .get = snd_ak4114_in_bit_get,
.private_value = (6<<8) | AK4114_REG_RCS1, .private_value = (6<<8) | AK4114_REG_RCS0,
}, },
{ {
.iface = SNDRV_CTL_ELEM_IFACE_PCM, .iface = SNDRV_CTL_ELEM_IFACE_PCM,
...@@ -436,7 +443,15 @@ static struct snd_kcontrol_new snd_ak4114_iec958_controls[] = { ...@@ -436,7 +443,15 @@ static struct snd_kcontrol_new snd_ak4114_iec958_controls[] = {
.access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE,
.info = snd_ak4114_in_bit_info, .info = snd_ak4114_in_bit_info,
.get = snd_ak4114_in_bit_get, .get = snd_ak4114_in_bit_get,
.private_value = (3<<8) | AK4114_REG_RCS1, .private_value = (3<<8) | AK4114_REG_RCS0,
},
{
.iface = SNDRV_CTL_ELEM_IFACE_PCM,
.name = "IEC958 PPL Lock Status",
.access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE,
.info = snd_ak4114_in_bit_info,
.get = snd_ak4114_in_bit_get,
.private_value = (1<<31) | (4<<8) | AK4114_REG_RCS0,
} }
}; };
...@@ -455,7 +470,7 @@ int snd_ak4114_build(struct ak4114 *ak4114, ...@@ -455,7 +470,7 @@ int snd_ak4114_build(struct ak4114 *ak4114,
kctl = snd_ctl_new1(&snd_ak4114_iec958_controls[idx], ak4114); kctl = snd_ctl_new1(&snd_ak4114_iec958_controls[idx], ak4114);
if (kctl == NULL) if (kctl == NULL)
return -ENOMEM; return -ENOMEM;
if (!strstr(kctl->id.name, "Playback")) { if (strstr(kctl->id.name, "Playback")) {
if (ply_substream == NULL) { if (ply_substream == NULL) {
snd_ctl_free_one(kctl); snd_ctl_free_one(kctl);
ak4114->kctls[idx] = NULL; ak4114->kctls[idx] = NULL;
...@@ -472,9 +487,58 @@ int snd_ak4114_build(struct ak4114 *ak4114, ...@@ -472,9 +487,58 @@ int snd_ak4114_build(struct ak4114 *ak4114,
return err; return err;
ak4114->kctls[idx] = kctl; ak4114->kctls[idx] = kctl;
} }
/* trigger workq */
schedule_delayed_work(&ak4114->work, HZ / 10);
return 0; return 0;
} }
/* notify kcontrols if any parameters are changed */
static void ak4114_notify(struct ak4114 *ak4114,
unsigned char rcs0, unsigned char rcs1,
unsigned char c0, unsigned char c1)
{
if (!ak4114->kctls[0])
return;
if (rcs0 & AK4114_PAR)
snd_ctl_notify(ak4114->card, SNDRV_CTL_EVENT_MASK_VALUE,
&ak4114->kctls[0]->id);
if (rcs0 & AK4114_V)
snd_ctl_notify(ak4114->card, SNDRV_CTL_EVENT_MASK_VALUE,
&ak4114->kctls[1]->id);
if (rcs1 & AK4114_CCRC)
snd_ctl_notify(ak4114->card, SNDRV_CTL_EVENT_MASK_VALUE,
&ak4114->kctls[2]->id);
if (rcs1 & AK4114_QCRC)
snd_ctl_notify(ak4114->card, SNDRV_CTL_EVENT_MASK_VALUE,
&ak4114->kctls[3]->id);
/* rate change */
if (c1 & 0xf0)
snd_ctl_notify(ak4114->card, SNDRV_CTL_EVENT_MASK_VALUE,
&ak4114->kctls[4]->id);
if ((c0 & AK4114_PEM) | (c0 & AK4114_CINT))
snd_ctl_notify(ak4114->card, SNDRV_CTL_EVENT_MASK_VALUE,
&ak4114->kctls[9]->id);
if (c0 & AK4114_QINT)
snd_ctl_notify(ak4114->card, SNDRV_CTL_EVENT_MASK_VALUE,
&ak4114->kctls[10]->id);
if (c0 & AK4114_AUDION)
snd_ctl_notify(ak4114->card, SNDRV_CTL_EVENT_MASK_VALUE,
&ak4114->kctls[11]->id);
if (c0 & AK4114_AUTO)
snd_ctl_notify(ak4114->card, SNDRV_CTL_EVENT_MASK_VALUE,
&ak4114->kctls[12]->id);
if (c0 & AK4114_DTSCD)
snd_ctl_notify(ak4114->card, SNDRV_CTL_EVENT_MASK_VALUE,
&ak4114->kctls[13]->id);
if (c0 & AK4114_UNLCK)
snd_ctl_notify(ak4114->card, SNDRV_CTL_EVENT_MASK_VALUE,
&ak4114->kctls[14]->id);
}
int snd_ak4114_external_rate(struct ak4114 *ak4114) int snd_ak4114_external_rate(struct ak4114 *ak4114)
{ {
unsigned char rcs1; unsigned char rcs1;
...@@ -511,31 +575,7 @@ int snd_ak4114_check_rate_and_errors(struct ak4114 *ak4114, unsigned int flags) ...@@ -511,31 +575,7 @@ int snd_ak4114_check_rate_and_errors(struct ak4114 *ak4114, unsigned int flags)
ak4114->rcs1 = rcs1; ak4114->rcs1 = rcs1;
spin_unlock_irqrestore(&ak4114->lock, _flags); spin_unlock_irqrestore(&ak4114->lock, _flags);
if (rcs0 & AK4114_PAR) ak4114_notify(ak4114, rcs0, rcs1, c0, c1);
snd_ctl_notify(ak4114->card, SNDRV_CTL_EVENT_MASK_VALUE, &ak4114->kctls[0]->id);
if (rcs0 & AK4114_V)
snd_ctl_notify(ak4114->card, SNDRV_CTL_EVENT_MASK_VALUE, &ak4114->kctls[1]->id);
if (rcs1 & AK4114_CCRC)
snd_ctl_notify(ak4114->card, SNDRV_CTL_EVENT_MASK_VALUE, &ak4114->kctls[2]->id);
if (rcs1 & AK4114_QCRC)
snd_ctl_notify(ak4114->card, SNDRV_CTL_EVENT_MASK_VALUE, &ak4114->kctls[3]->id);
/* rate change */
if (c1 & 0xf0)
snd_ctl_notify(ak4114->card, SNDRV_CTL_EVENT_MASK_VALUE, &ak4114->kctls[4]->id);
if ((c0 & AK4114_PEM) | (c0 & AK4114_CINT))
snd_ctl_notify(ak4114->card, SNDRV_CTL_EVENT_MASK_VALUE, &ak4114->kctls[9]->id);
if (c0 & AK4114_QINT)
snd_ctl_notify(ak4114->card, SNDRV_CTL_EVENT_MASK_VALUE, &ak4114->kctls[10]->id);
if (c0 & AK4114_AUDION)
snd_ctl_notify(ak4114->card, SNDRV_CTL_EVENT_MASK_VALUE, &ak4114->kctls[11]->id);
if (c0 & AK4114_AUTO)
snd_ctl_notify(ak4114->card, SNDRV_CTL_EVENT_MASK_VALUE, &ak4114->kctls[12]->id);
if (c0 & AK4114_DTSCD)
snd_ctl_notify(ak4114->card, SNDRV_CTL_EVENT_MASK_VALUE, &ak4114->kctls[13]->id);
if (ak4114->change_callback && (c0 | c1) != 0) if (ak4114->change_callback && (c0 | c1) != 0)
ak4114->change_callback(ak4114, c0, c1); ak4114->change_callback(ak4114, c0, c1);
...@@ -558,9 +598,9 @@ static void ak4114_stats(struct work_struct *work) ...@@ -558,9 +598,9 @@ static void ak4114_stats(struct work_struct *work)
{ {
struct ak4114 *chip = container_of(work, struct ak4114, work.work); struct ak4114 *chip = container_of(work, struct ak4114, work.work);
if (chip->init) if (!chip->init)
return; snd_ak4114_check_rate_and_errors(chip, 0);
snd_ak4114_check_rate_and_errors(chip, 0);
schedule_delayed_work(&chip->work, HZ / 10); schedule_delayed_work(&chip->work, HZ / 10);
} }
......
...@@ -358,12 +358,21 @@ config SND_SBAWE ...@@ -358,12 +358,21 @@ config SND_SBAWE
config SND_SB16_CSP config SND_SB16_CSP
bool "Sound Blaster 16/AWE CSP support" bool "Sound Blaster 16/AWE CSP support"
depends on (SND_SB16 || SND_SBAWE) && (BROKEN || !PPC) depends on (SND_SB16 || SND_SBAWE) && (BROKEN || !PPC)
select FW_LOADER select FW_LOADER if !SND_SB16_CSP_FIRMWARE_IN_KERNEL
help help
Say Y here to include support for the CSP core. This special Say Y here to include support for the CSP core. This special
coprocessor can do variable tasks like various compression and coprocessor can do variable tasks like various compression and
decompression algorithms. decompression algorithms.
config SND_SB16_CSP_FIRMWARE_IN_KERNEL
bool "In-kernel firmware for SB16 CSP"
depends on SND_SB16_CSP
default y
help
Say Y here to include the static firmware built in the kernel
for the SB16 CSP controller. If you choose N here, you need
to install the firmware files from the alsa-firmware package.
config SND_SGALAXY config SND_SGALAXY
tristate "Aztech Sound Galaxy" tristate "Aztech Sound Galaxy"
depends on SND depends on SND
...@@ -391,7 +400,7 @@ config SND_SSCAPE ...@@ -391,7 +400,7 @@ config SND_SSCAPE
config SND_WAVEFRONT config SND_WAVEFRONT
tristate "Turtle Beach Maui,Tropez,Tropez+ (Wavefront)" tristate "Turtle Beach Maui,Tropez,Tropez+ (Wavefront)"
depends on SND depends on SND
select FW_LOADER select FW_LOADER if !SND_WAVEFRONT_FIRMWARE_IN_KERNEL
select SND_OPL3_LIB select SND_OPL3_LIB
select SND_MPU401_UART select SND_MPU401_UART
select SND_CS4231_LIB select SND_CS4231_LIB
...@@ -402,4 +411,13 @@ config SND_WAVEFRONT ...@@ -402,4 +411,13 @@ config SND_WAVEFRONT
To compile this driver as a module, choose M here: the module To compile this driver as a module, choose M here: the module
will be called snd-wavefront. will be called snd-wavefront.
config SND_WAVEFRONT_FIRMWARE_IN_KERNEL
bool "In-kernel firmware for Wavefront"
depends on SND_WAVEFRONT
default y
help
Say Y here to include the static firmware built in the kernel
for the Wavefront driver. If you choose N here, you need to
install the firmware files from the alsa-firmware package.
endmenu endmenu
...@@ -129,8 +129,8 @@ static int __devinit snd_card_ad1816a_pnp(int dev, struct snd_card_ad1816a *acar ...@@ -129,8 +129,8 @@ static int __devinit snd_card_ad1816a_pnp(int dev, struct snd_card_ad1816a *acar
} }
acard->devmpu = pnp_request_card_device(card, id->devs[1].id, NULL); acard->devmpu = pnp_request_card_device(card, id->devs[1].id, NULL);
if (acard->devmpu == NULL) { if (acard->devmpu == NULL) {
kfree(cfg); mpu_port[dev] = -1;
return -EBUSY; snd_printk(KERN_WARNING PFX "MPU401 device busy, skipping.\n");
} }
pdev = acard->dev; pdev = acard->dev;
...@@ -162,6 +162,10 @@ static int __devinit snd_card_ad1816a_pnp(int dev, struct snd_card_ad1816a *acar ...@@ -162,6 +162,10 @@ static int __devinit snd_card_ad1816a_pnp(int dev, struct snd_card_ad1816a *acar
dma2[dev] = pnp_dma(pdev, 1); dma2[dev] = pnp_dma(pdev, 1);
irq[dev] = pnp_irq(pdev, 0); irq[dev] = pnp_irq(pdev, 0);
if (acard->devmpu == NULL) {
kfree(cfg);
return 0;
}
pdev = acard->devmpu; pdev = acard->devmpu;
pnp_init_resource_table(cfg); pnp_init_resource_table(cfg);
......
...@@ -24,7 +24,7 @@ ...@@ -24,7 +24,7 @@
#include <sound/driver.h> #include <sound/driver.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/err.h> #include <linux/err.h>
#include <linux/platform_device.h> #include <linux/isa.h>
#include <linux/time.h> #include <linux/time.h>
#include <linux/wait.h> #include <linux/wait.h>
#include <linux/moduleparam.h> #include <linux/moduleparam.h>
...@@ -32,8 +32,11 @@ ...@@ -32,8 +32,11 @@
#include <sound/ad1848.h> #include <sound/ad1848.h>
#include <sound/initval.h> #include <sound/initval.h>
#define CRD_NAME "Generic AD1848/AD1847/CS4248"
#define DEV_NAME "ad1848"
MODULE_DESCRIPTION(CRD_NAME);
MODULE_AUTHOR("Tugrul Galatali <galatalt@stuy.edu>, Jaroslav Kysela <perex@suse.cz>"); MODULE_AUTHOR("Tugrul Galatali <galatalt@stuy.edu>, Jaroslav Kysela <perex@suse.cz>");
MODULE_DESCRIPTION("AD1848/AD1847/CS4248");
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
MODULE_SUPPORTED_DEVICE("{{Analog Devices,AD1848}," MODULE_SUPPORTED_DEVICE("{{Analog Devices,AD1848},"
"{Analog Devices,AD1847}," "{Analog Devices,AD1847},"
...@@ -48,95 +51,98 @@ static int dma1[SNDRV_CARDS] = SNDRV_DEFAULT_DMA; /* 0,1,3,5,6,7 */ ...@@ -48,95 +51,98 @@ static int dma1[SNDRV_CARDS] = SNDRV_DEFAULT_DMA; /* 0,1,3,5,6,7 */
static int thinkpad[SNDRV_CARDS]; /* Thinkpad special case */ static int thinkpad[SNDRV_CARDS]; /* Thinkpad special case */
module_param_array(index, int, NULL, 0444); module_param_array(index, int, NULL, 0444);
MODULE_PARM_DESC(index, "Index value for AD1848 soundcard."); MODULE_PARM_DESC(index, "Index value for " CRD_NAME " soundcard.");
module_param_array(id, charp, NULL, 0444); module_param_array(id, charp, NULL, 0444);
MODULE_PARM_DESC(id, "ID string for AD1848 soundcard."); MODULE_PARM_DESC(id, "ID string for " CRD_NAME " soundcard.");
module_param_array(enable, bool, NULL, 0444); module_param_array(enable, bool, NULL, 0444);
MODULE_PARM_DESC(enable, "Enable AD1848 soundcard."); MODULE_PARM_DESC(enable, "Enable " CRD_NAME " soundcard.");
module_param_array(port, long, NULL, 0444); module_param_array(port, long, NULL, 0444);
MODULE_PARM_DESC(port, "Port # for AD1848 driver."); MODULE_PARM_DESC(port, "Port # for " CRD_NAME " driver.");
module_param_array(irq, int, NULL, 0444); module_param_array(irq, int, NULL, 0444);
MODULE_PARM_DESC(irq, "IRQ # for AD1848 driver."); MODULE_PARM_DESC(irq, "IRQ # for " CRD_NAME " driver.");
module_param_array(dma1, int, NULL, 0444); module_param_array(dma1, int, NULL, 0444);
MODULE_PARM_DESC(dma1, "DMA1 # for AD1848 driver."); MODULE_PARM_DESC(dma1, "DMA1 # for " CRD_NAME " driver.");
module_param_array(thinkpad, bool, NULL, 0444); module_param_array(thinkpad, bool, NULL, 0444);
MODULE_PARM_DESC(thinkpad, "Enable only for the onboard CS4248 of IBM Thinkpad 360/750/755 series."); MODULE_PARM_DESC(thinkpad, "Enable only for the onboard CS4248 of IBM Thinkpad 360/750/755 series.");
static struct platform_device *devices[SNDRV_CARDS]; static int __devinit snd_ad1848_match(struct device *dev, unsigned int n)
{
if (!enable[n])
return 0;
if (port[n] == SNDRV_AUTO_PORT) {
snd_printk(KERN_ERR "%s: please specify port\n", dev->bus_id);
return 0;
}
if (irq[n] == SNDRV_AUTO_IRQ) {
snd_printk(KERN_ERR "%s: please specify irq\n", dev->bus_id);
return 0;
}
if (dma1[n] == SNDRV_AUTO_DMA) {
snd_printk(KERN_ERR "%s: please specify dma1\n", dev->bus_id);
return 0;
}
return 1;
}
static int __devinit snd_ad1848_probe(struct platform_device *pdev) static int __devinit snd_ad1848_probe(struct device *dev, unsigned int n)
{ {
int dev = pdev->id;
struct snd_card *card; struct snd_card *card;
struct snd_ad1848 *chip; struct snd_ad1848 *chip;
struct snd_pcm *pcm; struct snd_pcm *pcm;
int err; int error;
if (port[dev] == SNDRV_AUTO_PORT) { card = snd_card_new(index[n], id[n], THIS_MODULE, 0);
snd_printk(KERN_ERR "ad1848: specify port\n"); if (!card)
return -EINVAL; return -EINVAL;
}
if (irq[dev] == SNDRV_AUTO_IRQ) {
snd_printk(KERN_ERR "ad1848: specify irq\n");
return -EINVAL;
}
if (dma1[dev] == SNDRV_AUTO_DMA) {
snd_printk(KERN_ERR "ad1848: specify dma1\n");
return -EINVAL;
}
card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0); error = snd_ad1848_create(card, port[n], irq[n], dma1[n],
if (card == NULL) thinkpad[n] ? AD1848_HW_THINKPAD : AD1848_HW_DETECT, &chip);
return -ENOMEM; if (error < 0)
goto out;
if ((err = snd_ad1848_create(card, port[dev],
irq[dev],
dma1[dev],
thinkpad[dev] ? AD1848_HW_THINKPAD : AD1848_HW_DETECT,
&chip)) < 0)
goto _err;
card->private_data = chip; card->private_data = chip;
if ((err = snd_ad1848_pcm(chip, 0, &pcm)) < 0) error = snd_ad1848_pcm(chip, 0, &pcm);
goto _err; if (error < 0)
goto out;
if ((err = snd_ad1848_mixer(chip)) < 0) error = snd_ad1848_mixer(chip);
goto _err; if (error < 0)
goto out;
strcpy(card->driver, "AD1848"); strcpy(card->driver, "AD1848");
strcpy(card->shortname, pcm->name); strcpy(card->shortname, pcm->name);
sprintf(card->longname, "%s at 0x%lx, irq %d, dma %d", sprintf(card->longname, "%s at 0x%lx, irq %d, dma %d",
pcm->name, chip->port, irq[dev], dma1[dev]); pcm->name, chip->port, irq[n], dma1[n]);
if (thinkpad[n])
if (thinkpad[dev])
strcat(card->longname, " [Thinkpad]"); strcat(card->longname, " [Thinkpad]");
snd_card_set_dev(card, &pdev->dev); snd_card_set_dev(card, dev);
if ((err = snd_card_register(card)) < 0) error = snd_card_register(card);
goto _err; if (error < 0)
goto out;
platform_set_drvdata(pdev, card); dev_set_drvdata(dev, card);
return 0; return 0;
_err: out: snd_card_free(card);
snd_card_free(card); return error;
return err;
} }
static int __devexit snd_ad1848_remove(struct platform_device *devptr) static int __devexit snd_ad1848_remove(struct device *dev, unsigned int n)
{ {
snd_card_free(platform_get_drvdata(devptr)); snd_card_free(dev_get_drvdata(dev));
platform_set_drvdata(devptr, NULL); dev_set_drvdata(dev, NULL);
return 0; return 0;
} }
#ifdef CONFIG_PM #ifdef CONFIG_PM
static int snd_ad1848_suspend(struct platform_device *pdev, pm_message_t state) static int snd_ad1848_suspend(struct device *dev, unsigned int n, pm_message_t state)
{ {
struct snd_card *card = platform_get_drvdata(pdev); struct snd_card *card = dev_get_drvdata(dev);
struct snd_ad1848 *chip = card->private_data; struct snd_ad1848 *chip = card->private_data;
snd_power_change_state(card, SNDRV_CTL_POWER_D3hot); snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
...@@ -144,9 +150,9 @@ static int snd_ad1848_suspend(struct platform_device *pdev, pm_message_t state) ...@@ -144,9 +150,9 @@ static int snd_ad1848_suspend(struct platform_device *pdev, pm_message_t state)
return 0; return 0;
} }
static int snd_ad1848_resume(struct platform_device *pdev) static int snd_ad1848_resume(struct device *dev, unsigned int n)
{ {
struct snd_card *card = platform_get_drvdata(pdev); struct snd_card *card = dev_get_drvdata(dev);
struct snd_ad1848 *chip = card->private_data; struct snd_ad1848 *chip = card->private_data;
chip->resume(chip); chip->resume(chip);
...@@ -155,9 +161,8 @@ static int snd_ad1848_resume(struct platform_device *pdev) ...@@ -155,9 +161,8 @@ static int snd_ad1848_resume(struct platform_device *pdev)
} }
#endif #endif
#define SND_AD1848_DRIVER "snd_ad1848" static struct isa_driver snd_ad1848_driver = {
.match = snd_ad1848_match,
static struct platform_driver snd_ad1848_driver = {
.probe = snd_ad1848_probe, .probe = snd_ad1848_probe,
.remove = __devexit_p(snd_ad1848_remove), .remove = __devexit_p(snd_ad1848_remove),
#ifdef CONFIG_PM #ifdef CONFIG_PM
...@@ -165,57 +170,19 @@ static struct platform_driver snd_ad1848_driver = { ...@@ -165,57 +170,19 @@ static struct platform_driver snd_ad1848_driver = {
.resume = snd_ad1848_resume, .resume = snd_ad1848_resume,
#endif #endif
.driver = { .driver = {
.name = SND_AD1848_DRIVER .name = DEV_NAME
}, }
}; };
static void __init_or_module snd_ad1848_unregister_all(void)
{
int i;
for (i = 0; i < ARRAY_SIZE(devices); ++i)
platform_device_unregister(devices[i]);
platform_driver_unregister(&snd_ad1848_driver);
}
static int __init alsa_card_ad1848_init(void) static int __init alsa_card_ad1848_init(void)
{ {
int i, cards, err; return isa_register_driver(&snd_ad1848_driver, SNDRV_CARDS);
err = platform_driver_register(&snd_ad1848_driver);
if (err < 0)
return err;
cards = 0;
for (i = 0; i < SNDRV_CARDS; i++) {
struct platform_device *device;
if (! enable[i])
continue;
device = platform_device_register_simple(SND_AD1848_DRIVER,
i, NULL, 0);
if (IS_ERR(device))
continue;
if (!platform_get_drvdata(device)) {
platform_device_unregister(device);
continue;
}
devices[i] = device;
cards++;
}
if (!cards) {
#ifdef MODULE
printk(KERN_ERR "AD1848 soundcard not found or device busy\n");
#endif
snd_ad1848_unregister_all();
return -ENODEV;
}
return 0;
} }
static void __exit alsa_card_ad1848_exit(void) static void __exit alsa_card_ad1848_exit(void)
{ {
snd_ad1848_unregister_all(); isa_unregister_driver(&snd_ad1848_driver);
} }
module_init(alsa_card_ad1848_init) module_init(alsa_card_ad1848_init);
module_exit(alsa_card_ad1848_exit) module_exit(alsa_card_ad1848_exit);
...@@ -5,13 +5,13 @@ ...@@ -5,13 +5,13 @@
#include <sound/driver.h> #include <sound/driver.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/platform_device.h> #include <linux/isa.h>
#include <sound/core.h> #include <sound/core.h>
#include <sound/initval.h> #include <sound/initval.h>
#include <sound/opl3.h> #include <sound/opl3.h>
#define CRD_NAME "AdLib FM" #define CRD_NAME "AdLib FM"
#define DRV_NAME "snd_adlib" #define DEV_NAME "adlib"
MODULE_DESCRIPTION(CRD_NAME); MODULE_DESCRIPTION(CRD_NAME);
MODULE_AUTHOR("Rene Herman"); MODULE_AUTHOR("Rene Herman");
...@@ -31,133 +31,99 @@ MODULE_PARM_DESC(enable, "Enable " CRD_NAME " soundcard."); ...@@ -31,133 +31,99 @@ MODULE_PARM_DESC(enable, "Enable " CRD_NAME " soundcard.");
module_param_array(port, long, NULL, 0444); module_param_array(port, long, NULL, 0444);
MODULE_PARM_DESC(port, "Port # for " CRD_NAME " driver."); MODULE_PARM_DESC(port, "Port # for " CRD_NAME " driver.");
static struct platform_device *devices[SNDRV_CARDS]; static int __devinit snd_adlib_match(struct device *dev, unsigned int n)
{
if (!enable[n])
return 0;
if (port[n] == SNDRV_AUTO_PORT) {
snd_printk(KERN_ERR "%s: please specify port\n", dev->bus_id);
return 0;
}
return 1;
}
static void snd_adlib_free(struct snd_card *card) static void snd_adlib_free(struct snd_card *card)
{ {
release_and_free_resource(card->private_data); release_and_free_resource(card->private_data);
} }
static int __devinit snd_adlib_probe(struct platform_device *device) static int __devinit snd_adlib_probe(struct device *dev, unsigned int n)
{ {
struct snd_card *card; struct snd_card *card;
struct snd_opl3 *opl3; struct snd_opl3 *opl3;
int error;
int error, i = device->id; card = snd_card_new(index[n], id[n], THIS_MODULE, 0);
if (port[i] == SNDRV_AUTO_PORT) {
snd_printk(KERN_ERR DRV_NAME ": please specify port\n");
error = -EINVAL;
goto out0;
}
card = snd_card_new(index[i], id[i], THIS_MODULE, 0);
if (!card) { if (!card) {
snd_printk(KERN_ERR DRV_NAME ": could not create card\n"); snd_printk(KERN_ERR "%s: could not create card\n", dev->bus_id);
error = -EINVAL; return -EINVAL;
goto out0;
} }
card->private_data = request_region(port[i], 4, CRD_NAME); card->private_data = request_region(port[n], 4, CRD_NAME);
if (!card->private_data) { if (!card->private_data) {
snd_printk(KERN_ERR DRV_NAME ": could not grab ports\n"); snd_printk(KERN_ERR "%s: could not grab ports\n", dev->bus_id);
error = -EBUSY; error = -EBUSY;
goto out1; goto out;
} }
card->private_free = snd_adlib_free; card->private_free = snd_adlib_free;
error = snd_opl3_create(card, port[i], port[i] + 2, OPL3_HW_AUTO, 1, &opl3); strcpy(card->driver, DEV_NAME);
strcpy(card->shortname, CRD_NAME);
sprintf(card->longname, CRD_NAME " at %#lx", port[n]);
error = snd_opl3_create(card, port[n], port[n] + 2, OPL3_HW_AUTO, 1, &opl3);
if (error < 0) { if (error < 0) {
snd_printk(KERN_ERR DRV_NAME ": could not create OPL\n"); snd_printk(KERN_ERR "%s: could not create OPL\n", dev->bus_id);
goto out1; goto out;
} }
error = snd_opl3_hwdep_new(opl3, 0, 0, NULL); error = snd_opl3_hwdep_new(opl3, 0, 0, NULL);
if (error < 0) { if (error < 0) {
snd_printk(KERN_ERR DRV_NAME ": could not create FM\n"); snd_printk(KERN_ERR "%s: could not create FM\n", dev->bus_id);
goto out1; goto out;
} }
strcpy(card->driver, DRV_NAME); snd_card_set_dev(card, dev);
strcpy(card->shortname, CRD_NAME);
sprintf(card->longname, CRD_NAME " at %#lx", port[i]);
snd_card_set_dev(card, &device->dev);
error = snd_card_register(card); error = snd_card_register(card);
if (error < 0) { if (error < 0) {
snd_printk(KERN_ERR DRV_NAME ": could not register card\n"); snd_printk(KERN_ERR "%s: could not register card\n", dev->bus_id);
goto out1; goto out;
} }
platform_set_drvdata(device, card); dev_set_drvdata(dev, card);
return 0; return 0;
out1: snd_card_free(card); out: snd_card_free(card);
out0: return error; return error;
} }
static int __devexit snd_adlib_remove(struct platform_device *device) static int __devexit snd_adlib_remove(struct device *dev, unsigned int n)
{ {
snd_card_free(platform_get_drvdata(device)); snd_card_free(dev_get_drvdata(dev));
platform_set_drvdata(device, NULL); dev_set_drvdata(dev, NULL);
return 0; return 0;
} }
static struct platform_driver snd_adlib_driver = { static struct isa_driver snd_adlib_driver = {
.match = snd_adlib_match,
.probe = snd_adlib_probe, .probe = snd_adlib_probe,
.remove = __devexit_p(snd_adlib_remove), .remove = __devexit_p(snd_adlib_remove),
.driver = { .driver = {
.name = DRV_NAME .name = DEV_NAME
} }
}; };
static int __init alsa_card_adlib_init(void) static int __init alsa_card_adlib_init(void)
{ {
int i, cards; return isa_register_driver(&snd_adlib_driver, SNDRV_CARDS);
if (platform_driver_register(&snd_adlib_driver) < 0) {
snd_printk(KERN_ERR DRV_NAME ": could not register driver\n");
return -ENODEV;
}
for (cards = 0, i = 0; i < SNDRV_CARDS; i++) {
struct platform_device *device;
if (!enable[i])
continue;
device = platform_device_register_simple(DRV_NAME, i, NULL, 0);
if (IS_ERR(device))
continue;
if (!platform_get_drvdata(device)) {
platform_device_unregister(device);
continue;
}
devices[i] = device;
cards++;
}
if (!cards) {
#ifdef MODULE
printk(KERN_ERR CRD_NAME " soundcard not found or device busy\n");
#endif
platform_driver_unregister(&snd_adlib_driver);
return -ENODEV;
}
return 0;
} }
static void __exit alsa_card_adlib_exit(void) static void __exit alsa_card_adlib_exit(void)
{ {
int i; isa_unregister_driver(&snd_adlib_driver);
for (i = 0; i < SNDRV_CARDS; i++)
platform_device_unregister(devices[i]);
platform_driver_unregister(&snd_adlib_driver);
} }
module_init(alsa_card_adlib_init); module_init(alsa_card_adlib_init);
......
...@@ -46,7 +46,7 @@ ...@@ -46,7 +46,7 @@
#include <sound/driver.h> #include <sound/driver.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/err.h> #include <linux/err.h>
#include <linux/platform_device.h> #include <linux/isa.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/pnp.h> #include <linux/pnp.h>
#include <linux/moduleparam.h> #include <linux/moduleparam.h>
...@@ -108,7 +108,6 @@ MODULE_PARM_DESC(wssirq, "IRQ # for CMI8330 WSS driver."); ...@@ -108,7 +108,6 @@ MODULE_PARM_DESC(wssirq, "IRQ # for CMI8330 WSS driver.");
module_param_array(wssdma, int, NULL, 0444); module_param_array(wssdma, int, NULL, 0444);
MODULE_PARM_DESC(wssdma, "DMA for CMI8330 WSS driver."); MODULE_PARM_DESC(wssdma, "DMA for CMI8330 WSS driver.");
static struct platform_device *platform_devices[SNDRV_CARDS];
#ifdef CONFIG_PNP #ifdef CONFIG_PNP
static int pnp_registered; static int pnp_registered;
#endif #endif
...@@ -547,70 +546,78 @@ static int __devinit snd_cmi8330_probe(struct snd_card *card, int dev) ...@@ -547,70 +546,78 @@ static int __devinit snd_cmi8330_probe(struct snd_card *card, int dev)
return snd_card_register(card); return snd_card_register(card);
} }
static int __devinit snd_cmi8330_nonpnp_probe(struct platform_device *pdev) static int __devinit snd_cmi8330_isa_match(struct device *pdev,
unsigned int dev)
{ {
struct snd_card *card; if (!enable[dev] || is_isapnp_selected(dev))
int err; return 0;
int dev = pdev->id;
if (wssport[dev] == SNDRV_AUTO_PORT) { if (wssport[dev] == SNDRV_AUTO_PORT) {
snd_printk(KERN_ERR PFX "specify wssport\n"); snd_printk(KERN_ERR PFX "specify wssport\n");
return -EINVAL; return 0;
} }
if (sbport[dev] == SNDRV_AUTO_PORT) { if (sbport[dev] == SNDRV_AUTO_PORT) {
snd_printk(KERN_ERR PFX "specify sbport\n"); snd_printk(KERN_ERR PFX "specify sbport\n");
return -EINVAL; return 0;
} }
return 1;
}
static int __devinit snd_cmi8330_isa_probe(struct device *pdev,
unsigned int dev)
{
struct snd_card *card;
int err;
card = snd_cmi8330_card_new(dev); card = snd_cmi8330_card_new(dev);
if (! card) if (! card)
return -ENOMEM; return -ENOMEM;
snd_card_set_dev(card, &pdev->dev); snd_card_set_dev(card, pdev);
if ((err = snd_cmi8330_probe(card, dev)) < 0) { if ((err = snd_cmi8330_probe(card, dev)) < 0) {
snd_card_free(card); snd_card_free(card);
return err; return err;
} }
platform_set_drvdata(pdev, card); dev_set_drvdata(pdev, card);
return 0; return 0;
} }
static int __devexit snd_cmi8330_nonpnp_remove(struct platform_device *devptr) static int __devexit snd_cmi8330_isa_remove(struct device *devptr,
unsigned int dev)
{ {
snd_card_free(platform_get_drvdata(devptr)); snd_card_free(dev_get_drvdata(devptr));
platform_set_drvdata(devptr, NULL); dev_set_drvdata(devptr, NULL);
return 0; return 0;
} }
#ifdef CONFIG_PM #ifdef CONFIG_PM
static int snd_cmi8330_nonpnp_suspend(struct platform_device *dev, pm_message_t state) static int snd_cmi8330_isa_suspend(struct device *dev, unsigned int n,
pm_message_t state)
{ {
return snd_cmi8330_suspend(platform_get_drvdata(dev)); return snd_cmi8330_suspend(dev_get_drvdata(dev));
} }
static int snd_cmi8330_nonpnp_resume(struct platform_device *dev) static int snd_cmi8330_isa_resume(struct device *dev, unsigned int n)
{ {
return snd_cmi8330_resume(platform_get_drvdata(dev)); return snd_cmi8330_resume(dev_get_drvdata(dev));
} }
#endif #endif
#define CMI8330_DRIVER "snd_cmi8330" #define DEV_NAME "cmi8330"
static struct platform_driver snd_cmi8330_driver = { static struct isa_driver snd_cmi8330_driver = {
.probe = snd_cmi8330_nonpnp_probe, .match = snd_cmi8330_isa_match,
.remove = __devexit_p(snd_cmi8330_nonpnp_remove), .probe = snd_cmi8330_isa_probe,
.remove = __devexit_p(snd_cmi8330_isa_remove),
#ifdef CONFIG_PM #ifdef CONFIG_PM
.suspend = snd_cmi8330_nonpnp_suspend, .suspend = snd_cmi8330_isa_suspend,
.resume = snd_cmi8330_nonpnp_resume, .resume = snd_cmi8330_isa_resume,
#endif #endif
.driver = { .driver = {
.name = CMI8330_DRIVER .name = DEV_NAME
}, },
}; };
#ifdef CONFIG_PNP #ifdef CONFIG_PNP
static unsigned int __devinitdata cmi8330_pnp_devices;
static int __devinit snd_cmi8330_pnp_detect(struct pnp_card_link *pcard, static int __devinit snd_cmi8330_pnp_detect(struct pnp_card_link *pcard,
const struct pnp_card_device_id *pid) const struct pnp_card_device_id *pid)
{ {
...@@ -640,7 +647,6 @@ static int __devinit snd_cmi8330_pnp_detect(struct pnp_card_link *pcard, ...@@ -640,7 +647,6 @@ static int __devinit snd_cmi8330_pnp_detect(struct pnp_card_link *pcard,
} }
pnp_set_card_drvdata(pcard, card); pnp_set_card_drvdata(pcard, card);
dev++; dev++;
cmi8330_pnp_devices++;
return 0; return 0;
} }
...@@ -675,63 +681,28 @@ static struct pnp_card_driver cmi8330_pnpc_driver = { ...@@ -675,63 +681,28 @@ static struct pnp_card_driver cmi8330_pnpc_driver = {
}; };
#endif /* CONFIG_PNP */ #endif /* CONFIG_PNP */
static void __init_or_module snd_cmi8330_unregister_all(void)
{
int i;
#ifdef CONFIG_PNP
if (pnp_registered)
pnp_unregister_card_driver(&cmi8330_pnpc_driver);
#endif
for (i = 0; i < ARRAY_SIZE(platform_devices); ++i)
platform_device_unregister(platform_devices[i]);
platform_driver_unregister(&snd_cmi8330_driver);
}
static int __init alsa_card_cmi8330_init(void) static int __init alsa_card_cmi8330_init(void)
{ {
int i, err, cards = 0; int err;
if ((err = platform_driver_register(&snd_cmi8330_driver)) < 0) err = isa_register_driver(&snd_cmi8330_driver, SNDRV_CARDS);
if (err < 0)
return err; return err;
for (i = 0; i < SNDRV_CARDS; i++) {
struct platform_device *device;
if (! enable[i] || is_isapnp_selected(i))
continue;
device = platform_device_register_simple(CMI8330_DRIVER,
i, NULL, 0);
if (IS_ERR(device))
continue;
if (!platform_get_drvdata(device)) {
platform_device_unregister(device);
continue;
}
platform_devices[i] = device;
cards++;
}
#ifdef CONFIG_PNP #ifdef CONFIG_PNP
err = pnp_register_card_driver(&cmi8330_pnpc_driver); err = pnp_register_card_driver(&cmi8330_pnpc_driver);
if (!err) { if (!err)
pnp_registered = 1; pnp_registered = 1;
cards += cmi8330_pnp_devices;
}
#endif #endif
if (!cards) {
#ifdef MODULE
snd_printk(KERN_ERR "CMI8330 not found or device busy\n");
#endif
snd_cmi8330_unregister_all();
return -ENODEV;
}
return 0; return 0;
} }
static void __exit alsa_card_cmi8330_exit(void) static void __exit alsa_card_cmi8330_exit(void)
{ {
snd_cmi8330_unregister_all(); #ifdef CONFIG_PNP
if (pnp_registered)
pnp_unregister_card_driver(&cmi8330_pnpc_driver);
#endif
isa_unregister_driver(&snd_cmi8330_driver);
} }
module_init(alsa_card_cmi8330_init) module_init(alsa_card_cmi8330_init)
......
...@@ -23,7 +23,7 @@ ...@@ -23,7 +23,7 @@
#include <sound/driver.h> #include <sound/driver.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/err.h> #include <linux/err.h>
#include <linux/platform_device.h> #include <linux/isa.h>
#include <linux/time.h> #include <linux/time.h>
#include <linux/wait.h> #include <linux/wait.h>
#include <linux/moduleparam.h> #include <linux/moduleparam.h>
...@@ -32,8 +32,11 @@ ...@@ -32,8 +32,11 @@
#include <sound/mpu401.h> #include <sound/mpu401.h>
#include <sound/initval.h> #include <sound/initval.h>
#define CRD_NAME "Generic CS4231"
#define DEV_NAME "cs4231"
MODULE_DESCRIPTION(CRD_NAME);
MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>"); MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>");
MODULE_DESCRIPTION("Generic CS4231");
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
MODULE_SUPPORTED_DEVICE("{{Crystal Semiconductors,CS4231}}"); MODULE_SUPPORTED_DEVICE("{{Crystal Semiconductors,CS4231}}");
...@@ -48,132 +51,136 @@ static int dma1[SNDRV_CARDS] = SNDRV_DEFAULT_DMA; /* 0,1,3,5,6,7 */ ...@@ -48,132 +51,136 @@ static int dma1[SNDRV_CARDS] = SNDRV_DEFAULT_DMA; /* 0,1,3,5,6,7 */
static int dma2[SNDRV_CARDS] = SNDRV_DEFAULT_DMA; /* 0,1,3,5,6,7 */ static int dma2[SNDRV_CARDS] = SNDRV_DEFAULT_DMA; /* 0,1,3,5,6,7 */
module_param_array(index, int, NULL, 0444); module_param_array(index, int, NULL, 0444);
MODULE_PARM_DESC(index, "Index value for CS4231 soundcard."); MODULE_PARM_DESC(index, "Index value for " CRD_NAME " soundcard.");
module_param_array(id, charp, NULL, 0444); module_param_array(id, charp, NULL, 0444);
MODULE_PARM_DESC(id, "ID string for CS4231 soundcard."); MODULE_PARM_DESC(id, "ID string for " CRD_NAME " soundcard.");
module_param_array(enable, bool, NULL, 0444); module_param_array(enable, bool, NULL, 0444);
MODULE_PARM_DESC(enable, "Enable CS4231 soundcard."); MODULE_PARM_DESC(enable, "Enable " CRD_NAME " soundcard.");
module_param_array(port, long, NULL, 0444); module_param_array(port, long, NULL, 0444);
MODULE_PARM_DESC(port, "Port # for CS4231 driver."); MODULE_PARM_DESC(port, "Port # for " CRD_NAME " driver.");
module_param_array(mpu_port, long, NULL, 0444); module_param_array(mpu_port, long, NULL, 0444);
MODULE_PARM_DESC(mpu_port, "MPU-401 port # for CS4231 driver."); MODULE_PARM_DESC(mpu_port, "MPU-401 port # for " CRD_NAME " driver.");
module_param_array(irq, int, NULL, 0444); module_param_array(irq, int, NULL, 0444);
MODULE_PARM_DESC(irq, "IRQ # for CS4231 driver."); MODULE_PARM_DESC(irq, "IRQ # for " CRD_NAME " driver.");
module_param_array(mpu_irq, int, NULL, 0444); module_param_array(mpu_irq, int, NULL, 0444);
MODULE_PARM_DESC(mpu_irq, "MPU-401 IRQ # for CS4231 driver."); MODULE_PARM_DESC(mpu_irq, "MPU-401 IRQ # for " CRD_NAME " driver.");
module_param_array(dma1, int, NULL, 0444); module_param_array(dma1, int, NULL, 0444);
MODULE_PARM_DESC(dma1, "DMA1 # for CS4231 driver."); MODULE_PARM_DESC(dma1, "DMA1 # for " CRD_NAME " driver.");
module_param_array(dma2, int, NULL, 0444); module_param_array(dma2, int, NULL, 0444);
MODULE_PARM_DESC(dma2, "DMA2 # for CS4231 driver."); MODULE_PARM_DESC(dma2, "DMA2 # for " CRD_NAME " driver.");
static struct platform_device *devices[SNDRV_CARDS]; static int __devinit snd_cs4231_match(struct device *dev, unsigned int n)
{
if (!enable[n])
return 0;
if (port[n] == SNDRV_AUTO_PORT) {
snd_printk(KERN_ERR "%s: please specify port\n", dev->bus_id);
return 0;
}
if (irq[n] == SNDRV_AUTO_IRQ) {
snd_printk(KERN_ERR "%s: please specify irq\n", dev->bus_id);
return 0;
}
if (dma1[n] == SNDRV_AUTO_DMA) {
snd_printk(KERN_ERR "%s: please specify dma1\n", dev->bus_id);
return 0;
}
return 1;
}
static int __init snd_cs4231_probe(struct platform_device *pdev) static int __devinit snd_cs4231_probe(struct device *dev, unsigned int n)
{ {
int dev = pdev->id;
struct snd_card *card; struct snd_card *card;
struct snd_pcm *pcm;
struct snd_cs4231 *chip; struct snd_cs4231 *chip;
int err; struct snd_pcm *pcm;
int error;
if (port[dev] == SNDRV_AUTO_PORT) { card = snd_card_new(index[n], id[n], THIS_MODULE, 0);
snd_printk(KERN_ERR "specify port\n"); if (!card)
return -EINVAL;
}
if (irq[dev] == SNDRV_AUTO_IRQ) {
snd_printk(KERN_ERR "specify irq\n");
return -EINVAL;
}
if (dma1[dev] == SNDRV_AUTO_DMA) {
snd_printk(KERN_ERR "specify dma1\n");
return -EINVAL; return -EINVAL;
}
card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0); error = snd_cs4231_create(card, port[n], -1, irq[n], dma1[n], dma2[n],
if (card == NULL) CS4231_HW_DETECT, 0, &chip);
return -ENOMEM; if (error < 0)
if ((err = snd_cs4231_create(card, port[dev], -1, goto out;
irq[dev],
dma1[dev],
dma2[dev],
CS4231_HW_DETECT,
0, &chip)) < 0)
goto _err;
card->private_data = chip; card->private_data = chip;
if ((err = snd_cs4231_pcm(chip, 0, &pcm)) < 0) error = snd_cs4231_pcm(chip, 0, &pcm);
goto _err; if (error < 0)
goto out;
strcpy(card->driver, "CS4231"); strcpy(card->driver, "CS4231");
strcpy(card->shortname, pcm->name); strcpy(card->shortname, pcm->name);
sprintf(card->longname, "%s at 0x%lx, irq %d, dma %d", sprintf(card->longname, "%s at 0x%lx, irq %d, dma %d",
pcm->name, chip->port, irq[dev], dma1[dev]); pcm->name, chip->port, irq[n], dma1[n]);
if (dma2[dev] >= 0) if (dma2[n] >= 0)
sprintf(card->longname + strlen(card->longname), "&%d", dma2[dev]); sprintf(card->longname + strlen(card->longname), "&%d", dma2[n]);
if ((err = snd_cs4231_mixer(chip)) < 0) error = snd_cs4231_mixer(chip);
goto _err; if (error < 0)
if ((err = snd_cs4231_timer(chip, 0, NULL)) < 0) goto out;
goto _err;
error = snd_cs4231_timer(chip, 0, NULL);
if (mpu_port[dev] > 0 && mpu_port[dev] != SNDRV_AUTO_PORT) { if (error < 0)
if (mpu_irq[dev] == SNDRV_AUTO_IRQ) goto out;
mpu_irq[dev] = -1;
if (mpu_port[n] > 0 && mpu_port[n] != SNDRV_AUTO_PORT) {
if (mpu_irq[n] == SNDRV_AUTO_IRQ)
mpu_irq[n] = -1;
if (snd_mpu401_uart_new(card, 0, MPU401_HW_CS4232, if (snd_mpu401_uart_new(card, 0, MPU401_HW_CS4232,
mpu_port[dev], 0, mpu_port[n], 0, mpu_irq[n],
mpu_irq[dev], mpu_irq[n] >= 0 ? IRQF_DISABLED : 0,
mpu_irq[dev] >= 0 ? IRQF_DISABLED : 0,
NULL) < 0) NULL) < 0)
printk(KERN_WARNING "cs4231: MPU401 not detected\n"); printk(KERN_WARNING "%s: MPU401 not detected\n", dev->bus_id);
} }
snd_card_set_dev(card, &pdev->dev); snd_card_set_dev(card, dev);
if ((err = snd_card_register(card)) < 0) error = snd_card_register(card);
goto _err; if (error < 0)
goto out;
platform_set_drvdata(pdev, card); dev_set_drvdata(dev, card);
return 0; return 0;
_err: out: snd_card_free(card);
snd_card_free(card); return error;
return err;
} }
static int __devexit snd_cs4231_remove(struct platform_device *devptr) static int __devexit snd_cs4231_remove(struct device *dev, unsigned int n)
{ {
snd_card_free(platform_get_drvdata(devptr)); snd_card_free(dev_get_drvdata(dev));
platform_set_drvdata(devptr, NULL); dev_set_drvdata(dev, NULL);
return 0; return 0;
} }
#ifdef CONFIG_PM #ifdef CONFIG_PM
static int snd_cs4231_suspend(struct platform_device *dev, pm_message_t state) static int snd_cs4231_suspend(struct device *dev, unsigned int n, pm_message_t state)
{ {
struct snd_card *card; struct snd_card *card = dev_get_drvdata(dev);
struct snd_cs4231 *chip; struct snd_cs4231 *chip = card->private_data;
card = platform_get_drvdata(dev);
snd_power_change_state(card, SNDRV_CTL_POWER_D3hot); snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
chip = card->private_data;
chip->suspend(chip); chip->suspend(chip);
return 0; return 0;
} }
static int snd_cs4231_resume(struct platform_device *dev) static int snd_cs4231_resume(struct device *dev, unsigned int n)
{ {
struct snd_card *card; struct snd_card *card = dev_get_drvdata(dev);
struct snd_cs4231 *chip; struct snd_cs4231 *chip = card->private_data;
card = platform_get_drvdata(dev);
chip = card->private_data;
chip->resume(chip); chip->resume(chip);
snd_power_change_state(card, SNDRV_CTL_POWER_D0); snd_power_change_state(card, SNDRV_CTL_POWER_D0);
return 0; return 0;
} }
#endif #endif
#define SND_CS4231_DRIVER "snd_cs4231" static struct isa_driver snd_cs4231_driver = {
.match = snd_cs4231_match,
static struct platform_driver snd_cs4231_driver = {
.probe = snd_cs4231_probe, .probe = snd_cs4231_probe,
.remove = __devexit_p(snd_cs4231_remove), .remove = __devexit_p(snd_cs4231_remove),
#ifdef CONFIG_PM #ifdef CONFIG_PM
...@@ -181,57 +188,19 @@ static struct platform_driver snd_cs4231_driver = { ...@@ -181,57 +188,19 @@ static struct platform_driver snd_cs4231_driver = {
.resume = snd_cs4231_resume, .resume = snd_cs4231_resume,
#endif #endif
.driver = { .driver = {
.name = SND_CS4231_DRIVER .name = DEV_NAME
}, }
}; };
static void __init_or_module snd_cs4231_unregister_all(void)
{
int i;
for (i = 0; i < ARRAY_SIZE(devices); ++i)
platform_device_unregister(devices[i]);
platform_driver_unregister(&snd_cs4231_driver);
}
static int __init alsa_card_cs4231_init(void) static int __init alsa_card_cs4231_init(void)
{ {
int i, cards, err; return isa_register_driver(&snd_cs4231_driver, SNDRV_CARDS);
err = platform_driver_register(&snd_cs4231_driver);
if (err < 0)
return err;
cards = 0;
for (i = 0; i < SNDRV_CARDS; i++) {
struct platform_device *device;
if (! enable[i])
continue;
device = platform_device_register_simple(SND_CS4231_DRIVER,
i, NULL, 0);
if (IS_ERR(device))
continue;
if (!platform_get_drvdata(device)) {
platform_device_unregister(device);
continue;
}
devices[i] = device;
cards++;
}
if (!cards) {
#ifdef MODULE
printk(KERN_ERR "CS4231 soundcard not found or device busy\n");
#endif
snd_cs4231_unregister_all();
return -ENODEV;
}
return 0;
} }
static void __exit alsa_card_cs4231_exit(void) static void __exit alsa_card_cs4231_exit(void)
{ {
snd_cs4231_unregister_all(); isa_unregister_driver(&snd_cs4231_driver);
} }
module_init(alsa_card_cs4231_init) module_init(alsa_card_cs4231_init);
module_exit(alsa_card_cs4231_exit) module_exit(alsa_card_cs4231_exit);
...@@ -405,7 +405,6 @@ static int snd_cs4231_trigger(struct snd_pcm_substream *substream, ...@@ -405,7 +405,6 @@ static int snd_cs4231_trigger(struct snd_pcm_substream *substream,
struct snd_cs4231 *chip = snd_pcm_substream_chip(substream); struct snd_cs4231 *chip = snd_pcm_substream_chip(substream);
int result = 0; int result = 0;
unsigned int what; unsigned int what;
struct list_head *pos;
struct snd_pcm_substream *s; struct snd_pcm_substream *s;
int do_start; int do_start;
...@@ -425,8 +424,7 @@ static int snd_cs4231_trigger(struct snd_pcm_substream *substream, ...@@ -425,8 +424,7 @@ static int snd_cs4231_trigger(struct snd_pcm_substream *substream,
} }
what = 0; what = 0;
snd_pcm_group_for_each(pos, substream) { snd_pcm_group_for_each_entry(s, substream) {
s = snd_pcm_group_substream_entry(pos);
if (s == chip->playback_substream) { if (s == chip->playback_substream) {
what |= CS4231_PLAYBACK_ENABLE; what |= CS4231_PLAYBACK_ENABLE;
snd_pcm_trigger_done(s, substream); snd_pcm_trigger_done(s, substream);
......
...@@ -22,7 +22,7 @@ ...@@ -22,7 +22,7 @@
#include <sound/driver.h> #include <sound/driver.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/err.h> #include <linux/err.h>
#include <linux/platform_device.h> #include <linux/isa.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/pnp.h> #include <linux/pnp.h>
#include <linux/moduleparam.h> #include <linux/moduleparam.h>
...@@ -75,10 +75,10 @@ MODULE_SUPPORTED_DEVICE("{{Crystal Semiconductors,CS4235}," ...@@ -75,10 +75,10 @@ MODULE_SUPPORTED_DEVICE("{{Crystal Semiconductors,CS4235},"
#ifdef CS4232 #ifdef CS4232
#define IDENT "CS4232" #define IDENT "CS4232"
#define CS423X_DRIVER "snd_cs4232" #define DEV_NAME "cs4232"
#else #else
#define IDENT "CS4236+" #define IDENT "CS4236+"
#define CS423X_DRIVER "snd_cs4236" #define DEV_NAME "cs4236"
#endif #endif
static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */ static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */
...@@ -126,14 +126,12 @@ MODULE_PARM_DESC(dma1, "DMA1 # for " IDENT " driver."); ...@@ -126,14 +126,12 @@ MODULE_PARM_DESC(dma1, "DMA1 # for " IDENT " driver.");
module_param_array(dma2, int, NULL, 0444); module_param_array(dma2, int, NULL, 0444);
MODULE_PARM_DESC(dma2, "DMA2 # for " IDENT " driver."); MODULE_PARM_DESC(dma2, "DMA2 # for " IDENT " driver.");
static struct platform_device *platform_devices[SNDRV_CARDS];
#ifdef CONFIG_PNP #ifdef CONFIG_PNP
static int pnpc_registered; static int pnpc_registered;
#ifdef CS4232 #ifdef CS4232
static int pnp_registered; static int pnp_registered;
#endif #endif
#endif /* CONFIG_PNP */ #endif /* CONFIG_PNP */
static unsigned int snd_cs423x_devices;
struct snd_card_cs4236 { struct snd_card_cs4236 {
struct snd_cs4231 *chip; struct snd_cs4231 *chip;
...@@ -542,38 +540,55 @@ static int __devinit snd_cs423x_probe(struct snd_card *card, int dev) ...@@ -542,38 +540,55 @@ static int __devinit snd_cs423x_probe(struct snd_card *card, int dev)
return snd_card_register(card); return snd_card_register(card);
} }
static int __init snd_cs423x_nonpnp_probe(struct platform_device *pdev) static int __devinit snd_cs423x_isa_match(struct device *pdev,
unsigned int dev)
{ {
int dev = pdev->id; if (!enable[dev] || is_isapnp_selected(dev))
struct snd_card *card; return 0;
int err;
if (port[dev] == SNDRV_AUTO_PORT) { if (port[dev] == SNDRV_AUTO_PORT) {
snd_printk(KERN_ERR "specify port\n"); snd_printk(KERN_ERR "%s: please specify port\n", pdev->bus_id);
return -EINVAL; return 0;
} }
if (cport[dev] == SNDRV_AUTO_PORT) { if (cport[dev] == SNDRV_AUTO_PORT) {
snd_printk(KERN_ERR "specify cport\n"); snd_printk(KERN_ERR "%s: please specify cport\n", pdev->bus_id);
return -EINVAL; return 0;
}
if (irq[dev] == SNDRV_AUTO_IRQ) {
snd_printk(KERN_ERR "%s: please specify irq\n", pdev->bus_id);
return 0;
} }
if (dma1[dev] == SNDRV_AUTO_DMA) {
snd_printk(KERN_ERR "%s: please specify dma1\n", pdev->bus_id);
return 0;
}
return 1;
}
static int __devinit snd_cs423x_isa_probe(struct device *pdev,
unsigned int dev)
{
struct snd_card *card;
int err;
card = snd_cs423x_card_new(dev); card = snd_cs423x_card_new(dev);
if (! card) if (! card)
return -ENOMEM; return -ENOMEM;
snd_card_set_dev(card, &pdev->dev); snd_card_set_dev(card, pdev);
if ((err = snd_cs423x_probe(card, dev)) < 0) { if ((err = snd_cs423x_probe(card, dev)) < 0) {
snd_card_free(card); snd_card_free(card);
return err; return err;
} }
platform_set_drvdata(pdev, card); dev_set_drvdata(pdev, card);
return 0; return 0;
} }
static int __devexit snd_cs423x_nonpnp_remove(struct platform_device *devptr) static int __devexit snd_cs423x_isa_remove(struct device *pdev,
unsigned int dev)
{ {
snd_card_free(platform_get_drvdata(devptr)); snd_card_free(dev_get_drvdata(pdev));
platform_set_drvdata(devptr, NULL); dev_set_drvdata(pdev, NULL);
return 0; return 0;
} }
...@@ -594,26 +609,28 @@ static int snd_cs423x_resume(struct snd_card *card) ...@@ -594,26 +609,28 @@ static int snd_cs423x_resume(struct snd_card *card)
return 0; return 0;
} }
static int snd_cs423x_nonpnp_suspend(struct platform_device *dev, pm_message_t state) static int snd_cs423x_isa_suspend(struct device *dev, unsigned int n,
pm_message_t state)
{ {
return snd_cs423x_suspend(platform_get_drvdata(dev)); return snd_cs423x_suspend(dev_get_drvdata(dev));
} }
static int snd_cs423x_nonpnp_resume(struct platform_device *dev) static int snd_cs423x_isa_resume(struct device *dev, unsigned int n)
{ {
return snd_cs423x_resume(platform_get_drvdata(dev)); return snd_cs423x_resume(dev_get_drvdata(dev));
} }
#endif #endif
static struct platform_driver cs423x_nonpnp_driver = { static struct isa_driver cs423x_isa_driver = {
.probe = snd_cs423x_nonpnp_probe, .match = snd_cs423x_isa_match,
.remove = __devexit_p(snd_cs423x_nonpnp_remove), .probe = snd_cs423x_isa_probe,
.remove = __devexit_p(snd_cs423x_isa_remove),
#ifdef CONFIG_PM #ifdef CONFIG_PM
.suspend = snd_cs423x_nonpnp_suspend, .suspend = snd_cs423x_isa_suspend,
.resume = snd_cs423x_nonpnp_resume, .resume = snd_cs423x_isa_resume,
#endif #endif
.driver = { .driver = {
.name = CS423X_DRIVER .name = DEV_NAME
}, },
}; };
...@@ -651,7 +668,6 @@ static int __devinit snd_cs4232_pnpbios_detect(struct pnp_dev *pdev, ...@@ -651,7 +668,6 @@ static int __devinit snd_cs4232_pnpbios_detect(struct pnp_dev *pdev,
} }
pnp_set_drvdata(pdev, card); pnp_set_drvdata(pdev, card);
dev++; dev++;
snd_cs423x_devices++;
return 0; return 0;
} }
...@@ -715,7 +731,6 @@ static int __devinit snd_cs423x_pnpc_detect(struct pnp_card_link *pcard, ...@@ -715,7 +731,6 @@ static int __devinit snd_cs423x_pnpc_detect(struct pnp_card_link *pcard,
} }
pnp_set_card_drvdata(pcard, card); pnp_set_card_drvdata(pcard, card);
dev++; dev++;
snd_cs423x_devices++;
return 0; return 0;
} }
...@@ -750,45 +765,13 @@ static struct pnp_card_driver cs423x_pnpc_driver = { ...@@ -750,45 +765,13 @@ static struct pnp_card_driver cs423x_pnpc_driver = {
}; };
#endif /* CONFIG_PNP */ #endif /* CONFIG_PNP */
static void __init_or_module snd_cs423x_unregister_all(void)
{
int i;
#ifdef CONFIG_PNP
if (pnpc_registered)
pnp_unregister_card_driver(&cs423x_pnpc_driver);
#ifdef CS4232
if (pnp_registered)
pnp_unregister_driver(&cs4232_pnp_driver);
#endif
#endif /* CONFIG_PNP */
for (i = 0; i < ARRAY_SIZE(platform_devices); ++i)
platform_device_unregister(platform_devices[i]);
platform_driver_unregister(&cs423x_nonpnp_driver);
}
static int __init alsa_card_cs423x_init(void) static int __init alsa_card_cs423x_init(void)
{ {
int i, err; int err;
if ((err = platform_driver_register(&cs423x_nonpnp_driver)) < 0) err = isa_register_driver(&cs423x_isa_driver, SNDRV_CARDS);
if (err < 0)
return err; return err;
for (i = 0; i < SNDRV_CARDS; i++) {
struct platform_device *device;
if (! enable[i] || is_isapnp_selected(i))
continue;
device = platform_device_register_simple(CS423X_DRIVER,
i, NULL, 0);
if (IS_ERR(device))
continue;
if (!platform_get_drvdata(device)) {
platform_device_unregister(device);
continue;
}
platform_devices[i] = device;
snd_cs423x_devices++;
}
#ifdef CONFIG_PNP #ifdef CONFIG_PNP
#ifdef CS4232 #ifdef CS4232
err = pnp_register_driver(&cs4232_pnp_driver); err = pnp_register_driver(&cs4232_pnp_driver);
...@@ -799,20 +782,20 @@ static int __init alsa_card_cs423x_init(void) ...@@ -799,20 +782,20 @@ static int __init alsa_card_cs423x_init(void)
if (!err) if (!err)
pnpc_registered = 1; pnpc_registered = 1;
#endif /* CONFIG_PNP */ #endif /* CONFIG_PNP */
if (!snd_cs423x_devices) {
#ifdef MODULE
printk(KERN_ERR IDENT " soundcard not found or device busy\n");
#endif
snd_cs423x_unregister_all();
return -ENODEV;
}
return 0; return 0;
} }
static void __exit alsa_card_cs423x_exit(void) static void __exit alsa_card_cs423x_exit(void)
{ {
snd_cs423x_unregister_all(); #ifdef CONFIG_PNP
if (pnpc_registered)
pnp_unregister_card_driver(&cs423x_pnpc_driver);
#ifdef CS4232
if (pnp_registered)
pnp_unregister_driver(&cs4232_pnp_driver);
#endif
#endif /* CONFIG_PNP */
isa_unregister_driver(&cs423x_isa_driver);
} }
module_init(alsa_card_cs423x_init) module_init(alsa_card_cs423x_init)
......
...@@ -22,7 +22,7 @@ ...@@ -22,7 +22,7 @@
#include <sound/driver.h> #include <sound/driver.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/err.h> #include <linux/err.h>
#include <linux/platform_device.h> #include <linux/isa.h>
#include <linux/time.h> #include <linux/time.h>
#include <linux/wait.h> #include <linux/wait.h>
#include <linux/moduleparam.h> #include <linux/moduleparam.h>
...@@ -35,8 +35,11 @@ ...@@ -35,8 +35,11 @@
#define SNDRV_LEGACY_FIND_FREE_DMA #define SNDRV_LEGACY_FIND_FREE_DMA
#include <sound/initval.h> #include <sound/initval.h>
#define CRD_NAME "Generic ESS ES1688/ES688 AudioDrive"
#define DEV_NAME "es1688"
MODULE_DESCRIPTION(CRD_NAME);
MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>"); MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>");
MODULE_DESCRIPTION("ESS ESx688 AudioDrive");
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
MODULE_SUPPORTED_DEVICE("{{ESS,ES688 PnP AudioDrive,pnp:ESS0100}," MODULE_SUPPORTED_DEVICE("{{ESS,ES688 PnP AudioDrive,pnp:ESS0100},"
"{ESS,ES1688 PnP AudioDrive,pnp:ESS0102}," "{ESS,ES1688 PnP AudioDrive,pnp:ESS0102},"
...@@ -53,189 +56,157 @@ static int mpu_irq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ; /* 5,7,9,10 */ ...@@ -53,189 +56,157 @@ static int mpu_irq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ; /* 5,7,9,10 */
static int dma8[SNDRV_CARDS] = SNDRV_DEFAULT_DMA; /* 0,1,3 */ static int dma8[SNDRV_CARDS] = SNDRV_DEFAULT_DMA; /* 0,1,3 */
module_param_array(index, int, NULL, 0444); module_param_array(index, int, NULL, 0444);
MODULE_PARM_DESC(index, "Index value for ESx688 soundcard."); MODULE_PARM_DESC(index, "Index value for " CRD_NAME " soundcard.");
module_param_array(id, charp, NULL, 0444); module_param_array(id, charp, NULL, 0444);
MODULE_PARM_DESC(id, "ID string for ESx688 soundcard."); MODULE_PARM_DESC(id, "ID string for " CRD_NAME " soundcard.");
module_param_array(enable, bool, NULL, 0444); module_param_array(enable, bool, NULL, 0444);
MODULE_PARM_DESC(enable, "Enable ESx688 soundcard."); MODULE_PARM_DESC(enable, "Enable " CRD_NAME " soundcard.");
module_param_array(port, long, NULL, 0444); module_param_array(port, long, NULL, 0444);
MODULE_PARM_DESC(port, "Port # for ESx688 driver."); MODULE_PARM_DESC(port, "Port # for " CRD_NAME " driver.");
module_param_array(mpu_port, long, NULL, 0444); module_param_array(mpu_port, long, NULL, 0444);
MODULE_PARM_DESC(mpu_port, "MPU-401 port # for ESx688 driver."); MODULE_PARM_DESC(mpu_port, "MPU-401 port # for " CRD_NAME " driver.");
module_param_array(irq, int, NULL, 0444); module_param_array(irq, int, NULL, 0444);
MODULE_PARM_DESC(irq, "IRQ # for ESx688 driver."); MODULE_PARM_DESC(irq, "IRQ # for " CRD_NAME " driver.");
module_param_array(mpu_irq, int, NULL, 0444); module_param_array(mpu_irq, int, NULL, 0444);
MODULE_PARM_DESC(mpu_irq, "MPU-401 IRQ # for ESx688 driver."); MODULE_PARM_DESC(mpu_irq, "MPU-401 IRQ # for " CRD_NAME " driver.");
module_param_array(dma8, int, NULL, 0444); module_param_array(dma8, int, NULL, 0444);
MODULE_PARM_DESC(dma8, "8-bit DMA # for ESx688 driver."); MODULE_PARM_DESC(dma8, "8-bit DMA # for " CRD_NAME " driver.");
static struct platform_device *devices[SNDRV_CARDS];
#define PFX "es1688: " static int __devinit snd_es1688_match(struct device *dev, unsigned int n)
{
return enable[n];
}
static int __devinit snd_es1688_probe(struct platform_device *pdev) static int __devinit snd_es1688_legacy_create(struct snd_card *card,
struct device *dev, unsigned int n, struct snd_es1688 **rchip)
{ {
int dev = pdev->id; static long possible_ports[] = {0x220, 0x240, 0x260};
static int possible_irqs[] = {5, 9, 10, 7, -1}; static int possible_irqs[] = {5, 9, 10, 7, -1};
static int possible_dmas[] = {1, 3, 0, -1}; static int possible_dmas[] = {1, 3, 0, -1};
int xirq, xdma, xmpu_irq;
struct snd_card *card; int i, error;
struct snd_es1688 *chip;
struct snd_opl3 *opl3; if (irq[n] == SNDRV_AUTO_IRQ) {
struct snd_pcm *pcm; irq[n] = snd_legacy_find_free_irq(possible_irqs);
int err; if (irq[n] < 0) {
snd_printk(KERN_ERR "%s: unable to find a free IRQ\n",
card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0); dev->bus_id);
if (card == NULL) return -EBUSY;
return -ENOMEM;
xirq = irq[dev];
if (xirq == SNDRV_AUTO_IRQ) {
if ((xirq = snd_legacy_find_free_irq(possible_irqs)) < 0) {
snd_printk(KERN_ERR PFX "unable to find a free IRQ\n");
err = -EBUSY;
goto _err;
} }
} }
xmpu_irq = mpu_irq[dev]; if (dma8[n] == SNDRV_AUTO_DMA) {
xdma = dma8[dev]; dma8[n] = snd_legacy_find_free_dma(possible_dmas);
if (xdma == SNDRV_AUTO_DMA) { if (dma8[n] < 0) {
if ((xdma = snd_legacy_find_free_dma(possible_dmas)) < 0) { snd_printk(KERN_ERR "%s: unable to find a free DMA\n",
snd_printk(KERN_ERR PFX "unable to find a free DMA\n"); dev->bus_id);
err = -EBUSY; return -EBUSY;
goto _err;
} }
} }
if (port[dev] != SNDRV_AUTO_PORT) { if (port[n] != SNDRV_AUTO_PORT)
if ((err = snd_es1688_create(card, port[dev], mpu_port[dev], return snd_es1688_create(card, port[n], mpu_port[n], irq[n],
xirq, xmpu_irq, xdma, mpu_irq[n], dma8[n], ES1688_HW_AUTO, rchip);
ES1688_HW_AUTO, &chip)) < 0)
goto _err; i = 0;
} else { do {
/* auto-probe legacy ports */ port[n] = possible_ports[i];
static unsigned long possible_ports[] = { error = snd_es1688_create(card, port[n], mpu_port[n], irq[n],
0x220, 0x240, 0x260, mpu_irq[n], dma8[n], ES1688_HW_AUTO, rchip);
}; } while (error < 0 && ++i < ARRAY_SIZE(possible_ports));
int i;
for (i = 0; i < ARRAY_SIZE(possible_ports); i++) { return error;
err = snd_es1688_create(card, possible_ports[i], }
mpu_port[dev],
xirq, xmpu_irq, xdma, static int __devinit snd_es1688_probe(struct device *dev, unsigned int n)
ES1688_HW_AUTO, &chip); {
if (err >= 0) { struct snd_card *card;
port[dev] = possible_ports[i]; struct snd_es1688 *chip;
break; struct snd_opl3 *opl3;
} struct snd_pcm *pcm;
} int error;
if (i >= ARRAY_SIZE(possible_ports))
goto _err; card = snd_card_new(index[n], id[n], THIS_MODULE, 0);
} if (!card)
return -EINVAL;
error = snd_es1688_legacy_create(card, dev, n, &chip);
if (error < 0)
goto out;
if ((err = snd_es1688_pcm(chip, 0, &pcm)) < 0) error = snd_es1688_pcm(chip, 0, &pcm);
goto _err; if (error < 0)
goto out;
if ((err = snd_es1688_mixer(chip)) < 0) error = snd_es1688_mixer(chip);
goto _err; if (error < 0)
goto out;
strcpy(card->driver, "ES1688"); strcpy(card->driver, "ES1688");
strcpy(card->shortname, pcm->name); strcpy(card->shortname, pcm->name);
sprintf(card->longname, "%s at 0x%lx, irq %i, dma %i", pcm->name, chip->port, xirq, xdma); sprintf(card->longname, "%s at 0x%lx, irq %i, dma %i", pcm->name,
chip->port, chip->irq, chip->dma8);
if ((snd_opl3_create(card, chip->port, chip->port + 2, OPL3_HW_OPL3, 0, &opl3)) < 0) {
printk(KERN_WARNING PFX "opl3 not detected at 0x%lx\n", chip->port); if (snd_opl3_create(card, chip->port, chip->port + 2,
} else { OPL3_HW_OPL3, 0, &opl3) < 0)
if ((err = snd_opl3_hwdep_new(opl3, 0, 1, NULL)) < 0) printk(KERN_WARNING "%s: opl3 not detected at 0x%lx\n",
goto _err; dev->bus_id, chip->port);
else {
error = snd_opl3_hwdep_new(opl3, 0, 1, NULL);
if (error < 0)
goto out;
} }
if (xmpu_irq >= 0 && xmpu_irq != SNDRV_AUTO_IRQ && chip->mpu_port > 0) { if (mpu_irq[n] >= 0 && mpu_irq[n] != SNDRV_AUTO_IRQ &&
if ((err = snd_mpu401_uart_new(card, 0, MPU401_HW_ES1688, chip->mpu_port > 0) {
chip->mpu_port, 0, error = snd_mpu401_uart_new(card, 0, MPU401_HW_ES1688,
xmpu_irq, chip->mpu_port, 0,
IRQF_DISABLED, mpu_irq[n], IRQF_DISABLED, NULL);
NULL)) < 0) if (error < 0)
goto _err; goto out;
} }
snd_card_set_dev(card, &pdev->dev); snd_card_set_dev(card, dev);
if ((err = snd_card_register(card)) < 0) error = snd_card_register(card);
goto _err; if (error < 0)
goto out;
platform_set_drvdata(pdev, card); dev_set_drvdata(dev, card);
return 0; return 0;
_err: out: snd_card_free(card);
snd_card_free(card); return error;
return err;
} }
static int __devexit snd_es1688_remove(struct platform_device *devptr) static int __devexit snd_es1688_remove(struct device *dev, unsigned int n)
{ {
snd_card_free(platform_get_drvdata(devptr)); snd_card_free(dev_get_drvdata(dev));
platform_set_drvdata(devptr, NULL); dev_set_drvdata(dev, NULL);
return 0; return 0;
} }
#define ES1688_DRIVER "snd_es1688" static struct isa_driver snd_es1688_driver = {
.match = snd_es1688_match,
static struct platform_driver snd_es1688_driver = {
.probe = snd_es1688_probe, .probe = snd_es1688_probe,
.remove = __devexit_p(snd_es1688_remove), .remove = snd_es1688_remove,
/* FIXME: suspend/resume */ #if 0 /* FIXME */
.suspend = snd_es1688_suspend,
.resume = snd_es1688_resume,
#endif
.driver = { .driver = {
.name = ES1688_DRIVER .name = DEV_NAME
}, }
}; };
static void __init_or_module snd_es1688_unregister_all(void)
{
int i;
for (i = 0; i < ARRAY_SIZE(devices); ++i)
platform_device_unregister(devices[i]);
platform_driver_unregister(&snd_es1688_driver);
}
static int __init alsa_card_es1688_init(void) static int __init alsa_card_es1688_init(void)
{ {
int i, cards, err; return isa_register_driver(&snd_es1688_driver, SNDRV_CARDS);
err = platform_driver_register(&snd_es1688_driver);
if (err < 0)
return err;
cards = 0;
for (i = 0; i < SNDRV_CARDS; i++) {
struct platform_device *device;
if (! enable[i])
continue;
device = platform_device_register_simple(ES1688_DRIVER,
i, NULL, 0);
if (IS_ERR(device))
continue;
if (!platform_get_drvdata(device)) {
platform_device_unregister(device);
continue;
}
devices[i] = device;
cards++;
}
if (!cards) {
#ifdef MODULE
printk(KERN_ERR "ESS AudioDrive ES1688 soundcard not found or device busy\n");
#endif
snd_es1688_unregister_all();
return -ENODEV;
}
return 0;
} }
static void __exit alsa_card_es1688_exit(void) static void __exit alsa_card_es1688_exit(void)
{ {
snd_es1688_unregister_all(); isa_unregister_driver(&snd_es1688_driver);
} }
module_init(alsa_card_es1688_init) module_init(alsa_card_es1688_init);
module_exit(alsa_card_es1688_exit) module_exit(alsa_card_es1688_exit);
...@@ -80,7 +80,7 @@ ...@@ -80,7 +80,7 @@
#include <sound/driver.h> #include <sound/driver.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/err.h> #include <linux/err.h>
#include <linux/platform_device.h> #include <linux/isa.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/pnp.h> #include <linux/pnp.h>
#include <linux/isapnp.h> #include <linux/isapnp.h>
...@@ -2035,8 +2035,6 @@ MODULE_PARM_DESC(dma1, "DMA 1 # for ES18xx driver."); ...@@ -2035,8 +2035,6 @@ MODULE_PARM_DESC(dma1, "DMA 1 # for ES18xx driver.");
module_param_array(dma2, int, NULL, 0444); module_param_array(dma2, int, NULL, 0444);
MODULE_PARM_DESC(dma2, "DMA 2 # for ES18xx driver."); MODULE_PARM_DESC(dma2, "DMA 2 # for ES18xx driver.");
static struct platform_device *platform_devices[SNDRV_CARDS];
#ifdef CONFIG_PNP #ifdef CONFIG_PNP
static int pnp_registered, pnpc_registered; static int pnp_registered, pnpc_registered;
...@@ -2237,7 +2235,12 @@ static int __devinit snd_audiodrive_probe(struct snd_card *card, int dev) ...@@ -2237,7 +2235,12 @@ static int __devinit snd_audiodrive_probe(struct snd_card *card, int dev)
return snd_card_register(card); return snd_card_register(card);
} }
static int __devinit snd_es18xx_nonpnp_probe1(int dev, struct platform_device *devptr) static int __devinit snd_es18xx_isa_match(struct device *pdev, unsigned int dev)
{
return enable[dev] && !is_isapnp_selected(dev);
}
static int __devinit snd_es18xx_isa_probe1(int dev, struct device *devptr)
{ {
struct snd_card *card; struct snd_card *card;
int err; int err;
...@@ -2245,18 +2248,17 @@ static int __devinit snd_es18xx_nonpnp_probe1(int dev, struct platform_device *d ...@@ -2245,18 +2248,17 @@ static int __devinit snd_es18xx_nonpnp_probe1(int dev, struct platform_device *d
card = snd_es18xx_card_new(dev); card = snd_es18xx_card_new(dev);
if (! card) if (! card)
return -ENOMEM; return -ENOMEM;
snd_card_set_dev(card, &devptr->dev); snd_card_set_dev(card, devptr);
if ((err = snd_audiodrive_probe(card, dev)) < 0) { if ((err = snd_audiodrive_probe(card, dev)) < 0) {
snd_card_free(card); snd_card_free(card);
return err; return err;
} }
platform_set_drvdata(devptr, card); dev_set_drvdata(devptr, card);
return 0; return 0;
} }
static int __devinit snd_es18xx_nonpnp_probe(struct platform_device *pdev) static int __devinit snd_es18xx_isa_probe(struct device *pdev, unsigned int dev)
{ {
int dev = pdev->id;
int err; int err;
static int possible_irqs[] = {5, 9, 10, 7, 11, 12, -1}; static int possible_irqs[] = {5, 9, 10, 7, 11, 12, -1};
static int possible_dmas[] = {1, 0, 3, 5, -1}; static int possible_dmas[] = {1, 0, 3, 5, -1};
...@@ -2281,13 +2283,13 @@ static int __devinit snd_es18xx_nonpnp_probe(struct platform_device *pdev) ...@@ -2281,13 +2283,13 @@ static int __devinit snd_es18xx_nonpnp_probe(struct platform_device *pdev)
} }
if (port[dev] != SNDRV_AUTO_PORT) { if (port[dev] != SNDRV_AUTO_PORT) {
return snd_es18xx_nonpnp_probe1(dev, pdev); return snd_es18xx_isa_probe1(dev, pdev);
} else { } else {
static unsigned long possible_ports[] = {0x220, 0x240, 0x260, 0x280}; static unsigned long possible_ports[] = {0x220, 0x240, 0x260, 0x280};
int i; int i;
for (i = 0; i < ARRAY_SIZE(possible_ports); i++) { for (i = 0; i < ARRAY_SIZE(possible_ports); i++) {
port[dev] = possible_ports[i]; port[dev] = possible_ports[i];
err = snd_es18xx_nonpnp_probe1(dev, pdev); err = snd_es18xx_isa_probe1(dev, pdev);
if (! err) if (! err)
return 0; return 0;
} }
...@@ -2295,43 +2297,44 @@ static int __devinit snd_es18xx_nonpnp_probe(struct platform_device *pdev) ...@@ -2295,43 +2297,44 @@ static int __devinit snd_es18xx_nonpnp_probe(struct platform_device *pdev)
} }
} }
static int __devexit snd_es18xx_nonpnp_remove(struct platform_device *devptr) static int __devexit snd_es18xx_isa_remove(struct device *devptr,
unsigned int dev)
{ {
snd_card_free(platform_get_drvdata(devptr)); snd_card_free(dev_get_drvdata(devptr));
platform_set_drvdata(devptr, NULL); dev_set_drvdata(devptr, NULL);
return 0; return 0;
} }
#ifdef CONFIG_PM #ifdef CONFIG_PM
static int snd_es18xx_nonpnp_suspend(struct platform_device *dev, pm_message_t state) static int snd_es18xx_isa_suspend(struct device *dev, unsigned int n,
pm_message_t state)
{ {
return snd_es18xx_suspend(platform_get_drvdata(dev), state); return snd_es18xx_suspend(dev_get_drvdata(dev), state);
} }
static int snd_es18xx_nonpnp_resume(struct platform_device *dev) static int snd_es18xx_isa_resume(struct device *dev, unsigned int n)
{ {
return snd_es18xx_resume(platform_get_drvdata(dev)); return snd_es18xx_resume(dev_get_drvdata(dev));
} }
#endif #endif
#define ES18XX_DRIVER "snd_es18xx" #define DEV_NAME "es18xx"
static struct platform_driver snd_es18xx_nonpnp_driver = { static struct isa_driver snd_es18xx_isa_driver = {
.probe = snd_es18xx_nonpnp_probe, .match = snd_es18xx_isa_match,
.remove = __devexit_p(snd_es18xx_nonpnp_remove), .probe = snd_es18xx_isa_probe,
.remove = __devexit_p(snd_es18xx_isa_remove),
#ifdef CONFIG_PM #ifdef CONFIG_PM
.suspend = snd_es18xx_nonpnp_suspend, .suspend = snd_es18xx_isa_suspend,
.resume = snd_es18xx_nonpnp_resume, .resume = snd_es18xx_isa_resume,
#endif #endif
.driver = { .driver = {
.name = ES18XX_DRIVER .name = DEV_NAME
}, },
}; };
#ifdef CONFIG_PNP #ifdef CONFIG_PNP
static unsigned int __devinitdata es18xx_pnp_devices;
static int __devinit snd_audiodrive_pnp_detect(struct pnp_dev *pdev, static int __devinit snd_audiodrive_pnp_detect(struct pnp_dev *pdev,
const struct pnp_device_id *id) const struct pnp_device_id *id)
{ {
...@@ -2362,7 +2365,6 @@ static int __devinit snd_audiodrive_pnp_detect(struct pnp_dev *pdev, ...@@ -2362,7 +2365,6 @@ static int __devinit snd_audiodrive_pnp_detect(struct pnp_dev *pdev,
} }
pnp_set_drvdata(pdev, card); pnp_set_drvdata(pdev, card);
dev++; dev++;
es18xx_pnp_devices++;
return 0; return 0;
} }
...@@ -2424,7 +2426,6 @@ static int __devinit snd_audiodrive_pnpc_detect(struct pnp_card_link *pcard, ...@@ -2424,7 +2426,6 @@ static int __devinit snd_audiodrive_pnpc_detect(struct pnp_card_link *pcard,
pnp_set_card_drvdata(pcard, card); pnp_set_card_drvdata(pcard, card);
dev++; dev++;
es18xx_pnp_devices++;
return 0; return 0;
} }
...@@ -2460,44 +2461,14 @@ static struct pnp_card_driver es18xx_pnpc_driver = { ...@@ -2460,44 +2461,14 @@ static struct pnp_card_driver es18xx_pnpc_driver = {
}; };
#endif /* CONFIG_PNP */ #endif /* CONFIG_PNP */
static void __init_or_module snd_es18xx_unregister_all(void)
{
int i;
#ifdef CONFIG_PNP
if (pnpc_registered)
pnp_unregister_card_driver(&es18xx_pnpc_driver);
if (pnp_registered)
pnp_unregister_driver(&es18xx_pnp_driver);
#endif
for (i = 0; i < ARRAY_SIZE(platform_devices); ++i)
platform_device_unregister(platform_devices[i]);
platform_driver_unregister(&snd_es18xx_nonpnp_driver);
}
static int __init alsa_card_es18xx_init(void) static int __init alsa_card_es18xx_init(void)
{ {
int i, err, cards = 0; int err;
if ((err = platform_driver_register(&snd_es18xx_nonpnp_driver)) < 0) err = isa_register_driver(&snd_es18xx_isa_driver, SNDRV_CARDS);
if (err < 0)
return err; return err;
for (i = 0; i < SNDRV_CARDS; i++) {
struct platform_device *device;
if (! enable[i] || is_isapnp_selected(i))
continue;
device = platform_device_register_simple(ES18XX_DRIVER,
i, NULL, 0);
if (IS_ERR(device))
continue;
if (!platform_get_drvdata(device)) {
platform_device_unregister(device);
continue;
}
platform_devices[i] = device;
cards++;
}
#ifdef CONFIG_PNP #ifdef CONFIG_PNP
err = pnp_register_driver(&es18xx_pnp_driver); err = pnp_register_driver(&es18xx_pnp_driver);
if (!err) if (!err)
...@@ -2505,22 +2476,19 @@ static int __init alsa_card_es18xx_init(void) ...@@ -2505,22 +2476,19 @@ static int __init alsa_card_es18xx_init(void)
err = pnp_register_card_driver(&es18xx_pnpc_driver); err = pnp_register_card_driver(&es18xx_pnpc_driver);
if (!err) if (!err)
pnpc_registered = 1; pnpc_registered = 1;
cards += es18xx_pnp_devices;
#endif
if(!cards) {
#ifdef MODULE
snd_printk(KERN_ERR "ESS AudioDrive ES18xx soundcard not found or device busy\n");
#endif #endif
snd_es18xx_unregister_all();
return -ENODEV;
}
return 0; return 0;
} }
static void __exit alsa_card_es18xx_exit(void) static void __exit alsa_card_es18xx_exit(void)
{ {
snd_es18xx_unregister_all(); #ifdef CONFIG_PNP
if (pnpc_registered)
pnp_unregister_card_driver(&es18xx_pnpc_driver);
if (pnp_registered)
pnp_unregister_driver(&es18xx_pnp_driver);
#endif
isa_unregister_driver(&snd_es18xx_isa_driver);
} }
module_init(alsa_card_es18xx_init) module_init(alsa_card_es18xx_init)
......
...@@ -22,7 +22,7 @@ ...@@ -22,7 +22,7 @@
#include <sound/driver.h> #include <sound/driver.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/err.h> #include <linux/err.h>
#include <linux/platform_device.h> #include <linux/isa.h>
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/time.h> #include <linux/time.h>
#include <linux/moduleparam.h> #include <linux/moduleparam.h>
...@@ -33,8 +33,11 @@ ...@@ -33,8 +33,11 @@
#define SNDRV_LEGACY_FIND_FREE_DMA #define SNDRV_LEGACY_FIND_FREE_DMA
#include <sound/initval.h> #include <sound/initval.h>
#define CRD_NAME "Gravis UltraSound Classic"
#define DEV_NAME "gusclassic"
MODULE_DESCRIPTION(CRD_NAME);
MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>"); MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>");
MODULE_DESCRIPTION("Gravis UltraSound Classic");
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
MODULE_SUPPORTED_DEVICE("{{Gravis,UltraSound Classic}}"); MODULE_SUPPORTED_DEVICE("{{Gravis,UltraSound Classic}}");
...@@ -51,32 +54,80 @@ static int channels[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 24}; ...@@ -51,32 +54,80 @@ static int channels[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 24};
static int pcm_channels[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 2}; static int pcm_channels[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 2};
module_param_array(index, int, NULL, 0444); module_param_array(index, int, NULL, 0444);
MODULE_PARM_DESC(index, "Index value for GUS Classic soundcard."); MODULE_PARM_DESC(index, "Index value for " CRD_NAME " soundcard.");
module_param_array(id, charp, NULL, 0444); module_param_array(id, charp, NULL, 0444);
MODULE_PARM_DESC(id, "ID string for GUS Classic soundcard."); MODULE_PARM_DESC(id, "ID string for " CRD_NAME " soundcard.");
module_param_array(enable, bool, NULL, 0444); module_param_array(enable, bool, NULL, 0444);
MODULE_PARM_DESC(enable, "Enable GUS Classic soundcard."); MODULE_PARM_DESC(enable, "Enable " CRD_NAME " soundcard.");
module_param_array(port, long, NULL, 0444); module_param_array(port, long, NULL, 0444);
MODULE_PARM_DESC(port, "Port # for GUS Classic driver."); MODULE_PARM_DESC(port, "Port # for " CRD_NAME " driver.");
module_param_array(irq, int, NULL, 0444); module_param_array(irq, int, NULL, 0444);
MODULE_PARM_DESC(irq, "IRQ # for GUS Classic driver."); MODULE_PARM_DESC(irq, "IRQ # for " CRD_NAME " driver.");
module_param_array(dma1, int, NULL, 0444); module_param_array(dma1, int, NULL, 0444);
MODULE_PARM_DESC(dma1, "DMA1 # for GUS Classic driver."); MODULE_PARM_DESC(dma1, "DMA1 # for " CRD_NAME " driver.");
module_param_array(dma2, int, NULL, 0444); module_param_array(dma2, int, NULL, 0444);
MODULE_PARM_DESC(dma2, "DMA2 # for GUS Classic driver."); MODULE_PARM_DESC(dma2, "DMA2 # for " CRD_NAME " driver.");
module_param_array(joystick_dac, int, NULL, 0444); module_param_array(joystick_dac, int, NULL, 0444);
MODULE_PARM_DESC(joystick_dac, "Joystick DAC level 0.59V-4.52V or 0.389V-2.98V for GUS Classic driver."); MODULE_PARM_DESC(joystick_dac, "Joystick DAC level 0.59V-4.52V or 0.389V-2.98V for " CRD_NAME " driver.");
module_param_array(channels, int, NULL, 0444); module_param_array(channels, int, NULL, 0444);
MODULE_PARM_DESC(channels, "GF1 channels for GUS Classic driver."); MODULE_PARM_DESC(channels, "GF1 channels for " CRD_NAME " driver.");
module_param_array(pcm_channels, int, NULL, 0444); module_param_array(pcm_channels, int, NULL, 0444);
MODULE_PARM_DESC(pcm_channels, "Reserved PCM channels for GUS Classic driver."); MODULE_PARM_DESC(pcm_channels, "Reserved PCM channels for " CRD_NAME " driver.");
static int __devinit snd_gusclassic_match(struct device *dev, unsigned int n)
{
return enable[n];
}
static int __devinit snd_gusclassic_create(struct snd_card *card,
struct device *dev, unsigned int n, struct snd_gus_card **rgus)
{
static long possible_ports[] = {0x220, 0x230, 0x240, 0x250, 0x260};
static int possible_irqs[] = {5, 11, 12, 9, 7, 15, 3, 4, -1};
static int possible_dmas[] = {5, 6, 7, 1, 3, -1};
int i, error;
if (irq[n] == SNDRV_AUTO_IRQ) {
irq[n] = snd_legacy_find_free_irq(possible_irqs);
if (irq[n] < 0) {
snd_printk(KERN_ERR "%s: unable to find a free IRQ\n",
dev->bus_id);
return -EBUSY;
}
}
if (dma1[n] == SNDRV_AUTO_DMA) {
dma1[n] = snd_legacy_find_free_dma(possible_dmas);
if (dma1[n] < 0) {
snd_printk(KERN_ERR "%s: unable to find a free DMA1\n",
dev->bus_id);
return -EBUSY;
}
}
if (dma2[n] == SNDRV_AUTO_DMA) {
dma2[n] = snd_legacy_find_free_dma(possible_dmas);
if (dma2[n] < 0) {
snd_printk(KERN_ERR "%s: unable to find a free DMA2\n",
dev->bus_id);
return -EBUSY;
}
}
static struct platform_device *devices[SNDRV_CARDS]; if (port[n] != SNDRV_AUTO_PORT)
return snd_gus_create(card, port[n], irq[n], dma1[n], dma2[n],
0, channels[n], pcm_channels[n], 0, rgus);
i = 0;
do {
port[n] = possible_ports[i];
error = snd_gus_create(card, port[n], irq[n], dma1[n], dma2[n],
0, channels[n], pcm_channels[n], 0, rgus);
} while (error < 0 && ++i < ARRAY_SIZE(possible_ports));
#define PFX "gusclassic: " return error;
}
static int __devinit snd_gusclassic_detect(struct snd_gus_card * gus) static int __devinit snd_gusclassic_detect(struct snd_gus_card *gus)
{ {
unsigned char d; unsigned char d;
...@@ -95,187 +146,104 @@ static int __devinit snd_gusclassic_detect(struct snd_gus_card * gus) ...@@ -95,187 +146,104 @@ static int __devinit snd_gusclassic_detect(struct snd_gus_card * gus)
return 0; return 0;
} }
static void __devinit snd_gusclassic_init(int dev, struct snd_gus_card * gus) static int __devinit snd_gusclassic_probe(struct device *dev, unsigned int n)
{
gus->equal_irq = 0;
gus->codec_flag = 0;
gus->max_flag = 0;
gus->joystick_dac = joystick_dac[dev];
}
static int __devinit snd_gusclassic_probe(struct platform_device *pdev)
{ {
int dev = pdev->id;
static int possible_irqs[] = {5, 11, 12, 9, 7, 15, 3, 4, -1};
static int possible_dmas[] = {5, 6, 7, 1, 3, -1};
int xirq, xdma1, xdma2;
struct snd_card *card; struct snd_card *card;
struct snd_gus_card *gus = NULL; struct snd_gus_card *gus;
int err; int error;
card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0);
if (card == NULL)
return -ENOMEM;
if (pcm_channels[dev] < 2)
pcm_channels[dev] = 2;
xirq = irq[dev];
if (xirq == SNDRV_AUTO_IRQ) {
if ((xirq = snd_legacy_find_free_irq(possible_irqs)) < 0) {
snd_printk(KERN_ERR PFX "unable to find a free IRQ\n");
err = -EBUSY;
goto _err;
}
}
xdma1 = dma1[dev];
if (xdma1 == SNDRV_AUTO_DMA) {
if ((xdma1 = snd_legacy_find_free_dma(possible_dmas)) < 0) {
snd_printk(KERN_ERR PFX "unable to find a free DMA1\n");
err = -EBUSY;
goto _err;
}
}
xdma2 = dma2[dev];
if (xdma2 == SNDRV_AUTO_DMA) {
if ((xdma2 = snd_legacy_find_free_dma(possible_dmas)) < 0) {
snd_printk(KERN_ERR PFX "unable to find a free DMA2\n");
err = -EBUSY;
goto _err;
}
}
if (port[dev] != SNDRV_AUTO_PORT) { card = snd_card_new(index[n], id[n], THIS_MODULE, 0);
err = snd_gus_create(card, if (!card)
port[dev], return -EINVAL;
xirq, xdma1, xdma2,
0, channels[dev], pcm_channels[dev],
0, &gus);
} else {
/* auto-probe legacy ports */
static unsigned long possible_ports[] = {
0x220, 0x230, 0x240, 0x250, 0x260,
};
int i;
for (i = 0; i < ARRAY_SIZE(possible_ports); i++) {
err = snd_gus_create(card,
possible_ports[i],
xirq, xdma1, xdma2,
0, channels[dev], pcm_channels[dev],
0, &gus);
if (err >= 0) {
port[dev] = possible_ports[i];
break;
}
}
}
if (err < 0)
goto _err;
if ((err = snd_gusclassic_detect(gus)) < 0) if (pcm_channels[n] < 2)
goto _err; pcm_channels[n] = 2;
snd_gusclassic_init(dev, gus); error = snd_gusclassic_create(card, dev, n, &gus);
if ((err = snd_gus_initialize(gus)) < 0) if (error < 0)
goto _err; goto out;
error = snd_gusclassic_detect(gus);
if (error < 0)
goto out;
gus->joystick_dac = joystick_dac[n];
error = snd_gus_initialize(gus);
if (error < 0)
goto out;
error = -ENODEV;
if (gus->max_flag || gus->ess_flag) { if (gus->max_flag || gus->ess_flag) {
snd_printk(KERN_ERR PFX "GUS Classic or ACE soundcard was not detected at 0x%lx\n", gus->gf1.port); snd_printk(KERN_ERR "%s: GUS Classic or ACE soundcard was "
err = -ENODEV; "not detected at 0x%lx\n", dev->bus_id, gus->gf1.port);
goto _err; goto out;
} }
if ((err = snd_gf1_new_mixer(gus)) < 0) error = snd_gf1_new_mixer(gus);
goto _err; if (error < 0)
goto out;
if ((err = snd_gf1_pcm_new(gus, 0, 0, NULL)) < 0) error = snd_gf1_pcm_new(gus, 0, 0, NULL);
goto _err; if (error < 0)
goto out;
if (!gus->ace_flag) { if (!gus->ace_flag) {
if ((err = snd_gf1_rawmidi_new(gus, 0, NULL)) < 0) error = snd_gf1_rawmidi_new(gus, 0, NULL);
goto _err; if (error < 0)
goto out;
} }
sprintf(card->longname + strlen(card->longname), " at 0x%lx, irq %d, dma %d", gus->gf1.port, xirq, xdma1);
if (xdma2 >= 0)
sprintf(card->longname + strlen(card->longname), "&%d", xdma2);
snd_card_set_dev(card, &pdev->dev); sprintf(card->longname + strlen(card->longname),
" at 0x%lx, irq %d, dma %d",
gus->gf1.port, gus->gf1.irq, gus->gf1.dma1);
if ((err = snd_card_register(card)) < 0) if (gus->gf1.dma2 >= 0)
goto _err; sprintf(card->longname + strlen(card->longname),
"&%d", gus->gf1.dma2);
platform_set_drvdata(pdev, card); snd_card_set_dev(card, dev);
error = snd_card_register(card);
if (error < 0)
goto out;
dev_set_drvdata(dev, card);
return 0; return 0;
_err: out: snd_card_free(card);
snd_card_free(card); return error;
return err;
} }
static int __devexit snd_gusclassic_remove(struct platform_device *devptr) static int __devexit snd_gusclassic_remove(struct device *dev, unsigned int n)
{ {
snd_card_free(platform_get_drvdata(devptr)); snd_card_free(dev_get_drvdata(dev));
platform_set_drvdata(devptr, NULL); dev_set_drvdata(dev, NULL);
return 0; return 0;
} }
#define GUSCLASSIC_DRIVER "snd_gusclassic" static struct isa_driver snd_gusclassic_driver = {
.match = snd_gusclassic_match,
static struct platform_driver snd_gusclassic_driver = {
.probe = snd_gusclassic_probe, .probe = snd_gusclassic_probe,
.remove = __devexit_p(snd_gusclassic_remove), .remove = __devexit_p(snd_gusclassic_remove),
/* FIXME: suspend/resume */ #if 0 /* FIXME */
.suspend = snd_gusclassic_suspend,
.remove = snd_gusclassic_remove,
#endif
.driver = { .driver = {
.name = GUSCLASSIC_DRIVER .name = DEV_NAME
}, }
}; };
static void __init_or_module snd_gusclassic_unregister_all(void)
{
int i;
for (i = 0; i < ARRAY_SIZE(devices); ++i)
platform_device_unregister(devices[i]);
platform_driver_unregister(&snd_gusclassic_driver);
}
static int __init alsa_card_gusclassic_init(void) static int __init alsa_card_gusclassic_init(void)
{ {
int i, cards, err; return isa_register_driver(&snd_gusclassic_driver, SNDRV_CARDS);
err = platform_driver_register(&snd_gusclassic_driver);
if (err < 0)
return err;
cards = 0;
for (i = 0; i < SNDRV_CARDS; i++) {
struct platform_device *device;
if (! enable[i])
continue;
device = platform_device_register_simple(GUSCLASSIC_DRIVER,
i, NULL, 0);
if (IS_ERR(device))
continue;
if (!platform_get_drvdata(device)) {
platform_device_unregister(device);
continue;
}
devices[i] = device;
cards++;
}
if (!cards) {
#ifdef MODULE
printk(KERN_ERR "GUS Classic soundcard not found or device busy\n");
#endif
snd_gusclassic_unregister_all();
return -ENODEV;
}
return 0;
} }
static void __exit alsa_card_gusclassic_exit(void) static void __exit alsa_card_gusclassic_exit(void)
{ {
snd_gusclassic_unregister_all(); isa_unregister_driver(&snd_gusclassic_driver);
} }
module_init(alsa_card_gusclassic_init) module_init(alsa_card_gusclassic_init);
module_exit(alsa_card_gusclassic_exit) module_exit(alsa_card_gusclassic_exit);
...@@ -22,7 +22,7 @@ ...@@ -22,7 +22,7 @@
#include <sound/driver.h> #include <sound/driver.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/err.h> #include <linux/err.h>
#include <linux/platform_device.h> #include <linux/isa.h>
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/time.h> #include <linux/time.h>
#include <linux/moduleparam.h> #include <linux/moduleparam.h>
...@@ -37,8 +37,11 @@ ...@@ -37,8 +37,11 @@
#define SNDRV_LEGACY_FIND_FREE_DMA #define SNDRV_LEGACY_FIND_FREE_DMA
#include <sound/initval.h> #include <sound/initval.h>
#define CRD_NAME "Gravis UltraSound Extreme"
#define DEV_NAME "gusextreme"
MODULE_DESCRIPTION(CRD_NAME);
MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>"); MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>");
MODULE_DESCRIPTION("Gravis UltraSound Extreme");
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
MODULE_SUPPORTED_DEVICE("{{Gravis,UltraSound Extreme}}"); MODULE_SUPPORTED_DEVICE("{{Gravis,UltraSound Extreme}}");
...@@ -59,43 +62,107 @@ static int channels[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 24}; ...@@ -59,43 +62,107 @@ static int channels[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 24};
static int pcm_channels[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 2}; static int pcm_channels[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 2};
module_param_array(index, int, NULL, 0444); module_param_array(index, int, NULL, 0444);
MODULE_PARM_DESC(index, "Index value for GUS Extreme soundcard."); MODULE_PARM_DESC(index, "Index value for " CRD_NAME " soundcard.");
module_param_array(id, charp, NULL, 0444); module_param_array(id, charp, NULL, 0444);
MODULE_PARM_DESC(id, "ID string for GUS Extreme soundcard."); MODULE_PARM_DESC(id, "ID string for " CRD_NAME " soundcard.");
module_param_array(enable, bool, NULL, 0444); module_param_array(enable, bool, NULL, 0444);
MODULE_PARM_DESC(enable, "Enable GUS Extreme soundcard."); MODULE_PARM_DESC(enable, "Enable " CRD_NAME " soundcard.");
module_param_array(port, long, NULL, 0444); module_param_array(port, long, NULL, 0444);
MODULE_PARM_DESC(port, "Port # for GUS Extreme driver."); MODULE_PARM_DESC(port, "Port # for " CRD_NAME " driver.");
module_param_array(gf1_port, long, NULL, 0444); module_param_array(gf1_port, long, NULL, 0444);
MODULE_PARM_DESC(gf1_port, "GF1 port # for GUS Extreme driver (optional)."); MODULE_PARM_DESC(gf1_port, "GF1 port # for " CRD_NAME " driver (optional).");
module_param_array(mpu_port, long, NULL, 0444); module_param_array(mpu_port, long, NULL, 0444);
MODULE_PARM_DESC(mpu_port, "MPU-401 port # for GUS Extreme driver."); MODULE_PARM_DESC(mpu_port, "MPU-401 port # for " CRD_NAME " driver.");
module_param_array(irq, int, NULL, 0444); module_param_array(irq, int, NULL, 0444);
MODULE_PARM_DESC(irq, "IRQ # for GUS Extreme driver."); MODULE_PARM_DESC(irq, "IRQ # for " CRD_NAME " driver.");
module_param_array(mpu_irq, int, NULL, 0444); module_param_array(mpu_irq, int, NULL, 0444);
MODULE_PARM_DESC(mpu_irq, "MPU-401 IRQ # for GUS Extreme driver."); MODULE_PARM_DESC(mpu_irq, "MPU-401 IRQ # for " CRD_NAME " driver.");
module_param_array(gf1_irq, int, NULL, 0444); module_param_array(gf1_irq, int, NULL, 0444);
MODULE_PARM_DESC(gf1_irq, "GF1 IRQ # for GUS Extreme driver."); MODULE_PARM_DESC(gf1_irq, "GF1 IRQ # for " CRD_NAME " driver.");
module_param_array(dma8, int, NULL, 0444); module_param_array(dma8, int, NULL, 0444);
MODULE_PARM_DESC(dma8, "8-bit DMA # for GUS Extreme driver."); MODULE_PARM_DESC(dma8, "8-bit DMA # for " CRD_NAME " driver.");
module_param_array(dma1, int, NULL, 0444); module_param_array(dma1, int, NULL, 0444);
MODULE_PARM_DESC(dma1, "GF1 DMA # for GUS Extreme driver."); MODULE_PARM_DESC(dma1, "GF1 DMA # for " CRD_NAME " driver.");
module_param_array(joystick_dac, int, NULL, 0444); module_param_array(joystick_dac, int, NULL, 0444);
MODULE_PARM_DESC(joystick_dac, "Joystick DAC level 0.59V-4.52V or 0.389V-2.98V for GUS Extreme driver."); MODULE_PARM_DESC(joystick_dac, "Joystick DAC level 0.59V-4.52V or 0.389V-2.98V for " CRD_NAME " driver.");
module_param_array(channels, int, NULL, 0444); module_param_array(channels, int, NULL, 0444);
MODULE_PARM_DESC(channels, "GF1 channels for GUS Extreme driver."); MODULE_PARM_DESC(channels, "GF1 channels for " CRD_NAME " driver.");
module_param_array(pcm_channels, int, NULL, 0444); module_param_array(pcm_channels, int, NULL, 0444);
MODULE_PARM_DESC(pcm_channels, "Reserved PCM channels for GUS Extreme driver."); MODULE_PARM_DESC(pcm_channels, "Reserved PCM channels for " CRD_NAME " driver.");
static int __devinit snd_gusextreme_match(struct device *dev, unsigned int n)
{
return enable[n];
}
static int __devinit snd_gusextreme_es1688_create(struct snd_card *card,
struct device *dev, unsigned int n, struct snd_es1688 **rchip)
{
static long possible_ports[] = {0x220, 0x240, 0x260};
static int possible_irqs[] = {5, 9, 10, 7, -1};
static int possible_dmas[] = {1, 3, 0, -1};
int i, error;
if (irq[n] == SNDRV_AUTO_IRQ) {
irq[n] = snd_legacy_find_free_irq(possible_irqs);
if (irq[n] < 0) {
snd_printk(KERN_ERR "%s: unable to find a free IRQ "
"for ES1688\n", dev->bus_id);
return -EBUSY;
}
}
if (dma8[n] == SNDRV_AUTO_DMA) {
dma8[n] = snd_legacy_find_free_dma(possible_dmas);
if (dma8[n] < 0) {
snd_printk(KERN_ERR "%s: unable to find a free DMA "
"for ES1688\n", dev->bus_id);
return -EBUSY;
}
}
static struct platform_device *devices[SNDRV_CARDS]; if (port[n] != SNDRV_AUTO_PORT)
return snd_es1688_create(card, port[n], mpu_port[n], irq[n],
mpu_irq[n], dma8[n], ES1688_HW_1688, rchip);
i = 0;
do {
port[n] = possible_ports[i];
error = snd_es1688_create(card, port[n], mpu_port[n], irq[n],
mpu_irq[n], dma8[n], ES1688_HW_1688, rchip);
} while (error < 0 && ++i < ARRAY_SIZE(possible_ports));
#define PFX "gusextreme: " return error;
}
static int __devinit snd_gusextreme_detect(int dev, static int __devinit snd_gusextreme_gus_card_create(struct snd_card *card,
struct snd_card *card, struct device *dev, unsigned int n, struct snd_gus_card **rgus)
struct snd_gus_card * gus, {
struct snd_es1688 *es1688) static int possible_irqs[] = {11, 12, 15, 9, 5, 7, 3, -1};
static int possible_dmas[] = {5, 6, 7, 3, 1, -1};
if (gf1_irq[n] == SNDRV_AUTO_IRQ) {
gf1_irq[n] = snd_legacy_find_free_irq(possible_irqs);
if (gf1_irq[n] < 0) {
snd_printk(KERN_ERR "%s: unable to find a free IRQ "
"for GF1\n", dev->bus_id);
return -EBUSY;
}
}
if (dma1[n] == SNDRV_AUTO_DMA) {
dma1[n] = snd_legacy_find_free_dma(possible_dmas);
if (dma1[n] < 0) {
snd_printk(KERN_ERR "%s: unable to find a free DMA "
"for GF1\n", dev->bus_id);
return -EBUSY;
}
}
return snd_gus_create(card, gf1_port[n], gf1_irq[n], dma1[n], -1,
0, channels[n], pcm_channels[n], 0, rgus);
}
static int __devinit snd_gusextreme_detect(struct snd_gus_card *gus,
struct snd_es1688 *es1688)
{ {
unsigned long flags; unsigned long flags;
unsigned char d; unsigned char d;
...@@ -117,12 +184,13 @@ static int __devinit snd_gusextreme_detect(int dev, ...@@ -117,12 +184,13 @@ static int __devinit snd_gusextreme_detect(int dev,
spin_lock_irqsave(&es1688->mixer_lock, flags); spin_lock_irqsave(&es1688->mixer_lock, flags);
snd_es1688_mixer_write(es1688, 0x40, 0x0b); /* don't change!!! */ snd_es1688_mixer_write(es1688, 0x40, 0x0b); /* don't change!!! */
spin_unlock_irqrestore(&es1688->mixer_lock, flags); spin_unlock_irqrestore(&es1688->mixer_lock, flags);
spin_lock_irqsave(&es1688->reg_lock, flags); spin_lock_irqsave(&es1688->reg_lock, flags);
outb(gf1_port[dev] & 0x040 ? 2 : 0, ES1688P(es1688, INIT1)); outb(gus->gf1.port & 0x040 ? 2 : 0, ES1688P(es1688, INIT1));
outb(0, 0x201); outb(0, 0x201);
outb(gf1_port[dev] & 0x020 ? 2 : 0, ES1688P(es1688, INIT1)); outb(gus->gf1.port & 0x020 ? 2 : 0, ES1688P(es1688, INIT1));
outb(0, 0x201); outb(0, 0x201);
outb(gf1_port[dev] & 0x010 ? 3 : 1, ES1688P(es1688, INIT1)); outb(gus->gf1.port & 0x010 ? 3 : 1, ES1688P(es1688, INIT1));
spin_unlock_irqrestore(&es1688->reg_lock, flags); spin_unlock_irqrestore(&es1688->reg_lock, flags);
udelay(100); udelay(100);
...@@ -139,253 +207,172 @@ static int __devinit snd_gusextreme_detect(int dev, ...@@ -139,253 +207,172 @@ static int __devinit snd_gusextreme_detect(int dev,
snd_printdd("[0x%lx] check 2 failed - 0x%x\n", gus->gf1.port, d); snd_printdd("[0x%lx] check 2 failed - 0x%x\n", gus->gf1.port, d);
return -EIO; return -EIO;
} }
return 0;
}
static void __devinit snd_gusextreme_init(int dev, struct snd_gus_card * gus) return 0;
{
gus->joystick_dac = joystick_dac[dev];
} }
static int __devinit snd_gusextreme_mixer(struct snd_es1688 *chip) static int __devinit snd_gusextreme_mixer(struct snd_es1688 *chip)
{ {
struct snd_card *card = chip->card; struct snd_card *card = chip->card;
struct snd_ctl_elem_id id1, id2; struct snd_ctl_elem_id id1, id2;
int err; int error;
memset(&id1, 0, sizeof(id1)); memset(&id1, 0, sizeof(id1));
memset(&id2, 0, sizeof(id2)); memset(&id2, 0, sizeof(id2));
id1.iface = id2.iface = SNDRV_CTL_ELEM_IFACE_MIXER; id1.iface = id2.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
/* reassign AUX to SYNTHESIZER */ /* reassign AUX to SYNTHESIZER */
strcpy(id1.name, "Aux Playback Volume"); strcpy(id1.name, "Aux Playback Volume");
strcpy(id2.name, "Synth Playback Volume"); strcpy(id2.name, "Synth Playback Volume");
if ((err = snd_ctl_rename_id(card, &id1, &id2)) < 0) error = snd_ctl_rename_id(card, &id1, &id2);
return err; if (error < 0)
return error;
/* reassign Master Playback Switch to Synth Playback Switch */ /* reassign Master Playback Switch to Synth Playback Switch */
strcpy(id1.name, "Master Playback Switch"); strcpy(id1.name, "Master Playback Switch");
strcpy(id2.name, "Synth Playback Switch"); strcpy(id2.name, "Synth Playback Switch");
if ((err = snd_ctl_rename_id(card, &id1, &id2)) < 0) error = snd_ctl_rename_id(card, &id1, &id2);
return err; if (error < 0)
return error;
return 0; return 0;
} }
static int __devinit snd_gusextreme_probe(struct platform_device *pdev) static int __devinit snd_gusextreme_probe(struct device *dev, unsigned int n)
{ {
int dev = pdev->id;
static int possible_ess_irqs[] = {5, 9, 10, 7, -1};
static int possible_ess_dmas[] = {1, 3, 0, -1};
static int possible_gf1_irqs[] = {5, 11, 12, 9, 7, 15, 3, -1};
static int possible_gf1_dmas[] = {5, 6, 7, 1, 3, -1};
int xgf1_irq, xgf1_dma, xess_irq, xmpu_irq, xess_dma;
struct snd_card *card; struct snd_card *card;
struct snd_gus_card *gus; struct snd_gus_card *gus;
struct snd_es1688 *es1688; struct snd_es1688 *es1688;
struct snd_opl3 *opl3; struct snd_opl3 *opl3;
int err; int error;
card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0); card = snd_card_new(index[n], id[n], THIS_MODULE, 0);
if (card == NULL) if (!card)
return -ENOMEM; return -EINVAL;
xgf1_irq = gf1_irq[dev]; if (mpu_port[n] == SNDRV_AUTO_PORT)
if (xgf1_irq == SNDRV_AUTO_IRQ) { mpu_port[n] = 0;
if ((xgf1_irq = snd_legacy_find_free_irq(possible_gf1_irqs)) < 0) {
snd_printk(KERN_ERR PFX "unable to find a free IRQ for GF1\n");
err = -EBUSY;
goto out;
}
}
xess_irq = irq[dev];
if (xess_irq == SNDRV_AUTO_IRQ) {
if ((xess_irq = snd_legacy_find_free_irq(possible_ess_irqs)) < 0) {
snd_printk(KERN_ERR PFX "unable to find a free IRQ for ES1688\n");
err = -EBUSY;
goto out;
}
}
if (mpu_port[dev] == SNDRV_AUTO_PORT)
mpu_port[dev] = 0;
xmpu_irq = mpu_irq[dev];
if (xmpu_irq > 15)
xmpu_irq = -1;
xgf1_dma = dma1[dev];
if (xgf1_dma == SNDRV_AUTO_DMA) {
if ((xgf1_dma = snd_legacy_find_free_dma(possible_gf1_dmas)) < 0) {
snd_printk(KERN_ERR PFX "unable to find a free DMA for GF1\n");
err = -EBUSY;
goto out;
}
}
xess_dma = dma8[dev];
if (xess_dma == SNDRV_AUTO_DMA) {
if ((xess_dma = snd_legacy_find_free_dma(possible_ess_dmas)) < 0) {
snd_printk(KERN_ERR PFX "unable to find a free DMA for ES1688\n");
err = -EBUSY;
goto out;
}
}
if (port[dev] != SNDRV_AUTO_PORT) { if (mpu_irq[n] > 15)
err = snd_es1688_create(card, port[dev], mpu_port[dev], mpu_irq[n] = -1;
xess_irq, xmpu_irq, xess_dma,
ES1688_HW_1688, &es1688); error = snd_gusextreme_es1688_create(card, dev, n, &es1688);
} else { if (error < 0)
/* auto-probe legacy ports */
static unsigned long possible_ports[] = {0x220, 0x240, 0x260};
int i;
for (i = 0; i < ARRAY_SIZE(possible_ports); i++) {
err = snd_es1688_create(card,
possible_ports[i],
mpu_port[dev],
xess_irq, xmpu_irq, xess_dma,
ES1688_HW_1688, &es1688);
if (err >= 0) {
port[dev] = possible_ports[i];
break;
}
}
}
if (err < 0)
goto out; goto out;
if (gf1_port[dev] < 0) if (gf1_port[n] < 0)
gf1_port[dev] = port[dev] + 0x20; gf1_port[n] = es1688->port + 0x20;
if ((err = snd_gus_create(card,
gf1_port[dev], error = snd_gusextreme_gus_card_create(card, dev, n, &gus);
xgf1_irq, if (error < 0)
xgf1_dma,
-1,
0, channels[dev],
pcm_channels[dev], 0,
&gus)) < 0)
goto out; goto out;
if ((err = snd_gusextreme_detect(dev, card, gus, es1688)) < 0) error = snd_gusextreme_detect(gus, es1688);
if (error < 0)
goto out; goto out;
snd_gusextreme_init(dev, gus); gus->joystick_dac = joystick_dac[n];
if ((err = snd_gus_initialize(gus)) < 0)
error = snd_gus_initialize(gus);
if (error < 0)
goto out; goto out;
error = -ENODEV;
if (!gus->ess_flag) { if (!gus->ess_flag) {
snd_printk(KERN_ERR PFX "GUS Extreme soundcard was not detected at 0x%lx\n", gus->gf1.port); snd_printk(KERN_ERR "%s: GUS Extreme soundcard was not "
err = -ENODEV; "detected at 0x%lx\n", dev->bus_id, gus->gf1.port);
goto out; goto out;
} }
if ((err = snd_es1688_pcm(es1688, 0, NULL)) < 0) gus->codec_flag = 1;
error = snd_es1688_pcm(es1688, 0, NULL);
if (error < 0)
goto out; goto out;
if ((err = snd_es1688_mixer(es1688)) < 0) error = snd_es1688_mixer(es1688);
if (error < 0)
goto out; goto out;
snd_component_add(card, "ES1688"); snd_component_add(card, "ES1688");
if (pcm_channels[dev] > 0) {
if ((err = snd_gf1_pcm_new(gus, 1, 1, NULL)) < 0) if (pcm_channels[n] > 0) {
error = snd_gf1_pcm_new(gus, 1, 1, NULL);
if (error < 0)
goto out; goto out;
} }
if ((err = snd_gf1_new_mixer(gus)) < 0)
error = snd_gf1_new_mixer(gus);
if (error < 0)
goto out; goto out;
if ((err = snd_gusextreme_mixer(es1688)) < 0) error = snd_gusextreme_mixer(es1688);
if (error < 0)
goto out; goto out;
if (snd_opl3_create(card, es1688->port, es1688->port + 2, if (snd_opl3_create(card, es1688->port, es1688->port + 2,
OPL3_HW_OPL3, 0, &opl3) < 0) { OPL3_HW_OPL3, 0, &opl3) < 0)
printk(KERN_ERR PFX "gusextreme: opl3 not detected at 0x%lx\n", es1688->port); printk(KERN_ERR "%s: opl3 not detected at 0x%lx\n",
} else { dev->bus_id, es1688->port);
if ((err = snd_opl3_hwdep_new(opl3, 0, 2, NULL)) < 0) else {
error = snd_opl3_hwdep_new(opl3, 0, 2, NULL);
if (error < 0)
goto out; goto out;
} }
if (es1688->mpu_port >= 0x300 && if (es1688->mpu_port >= 0x300) {
(err = snd_mpu401_uart_new(card, 0, MPU401_HW_ES1688, error = snd_mpu401_uart_new(card, 0, MPU401_HW_ES1688,
es1688->mpu_port, 0, es1688->mpu_port, 0,
xmpu_irq, mpu_irq[n], IRQF_DISABLED, NULL);
IRQF_DISABLED, if (error < 0)
NULL)) < 0) goto out;
goto out; }
sprintf(card->longname, "Gravis UltraSound Extreme at 0x%lx, irq %i&%i, dma %i&%i", sprintf(card->longname, "Gravis UltraSound Extreme at 0x%lx, "
es1688->port, xgf1_irq, xess_irq, xgf1_dma, xess_dma); "irq %i&%i, dma %i&%i", es1688->port,
gus->gf1.irq, es1688->irq, gus->gf1.dma1, es1688->dma8);
snd_card_set_dev(card, &pdev->dev); snd_card_set_dev(card, dev);
if ((err = snd_card_register(card)) < 0) error = snd_card_register(card);
if (error < 0)
goto out; goto out;
platform_set_drvdata(pdev, card); dev_set_drvdata(dev, card);
return 0; return 0;
out: out: snd_card_free(card);
snd_card_free(card); return error;
return err;
} }
static int __devexit snd_gusextreme_remove(struct platform_device *devptr) static int __devexit snd_gusextreme_remove(struct device *dev, unsigned int n)
{ {
snd_card_free(platform_get_drvdata(devptr)); snd_card_free(dev_get_drvdata(dev));
platform_set_drvdata(devptr, NULL); dev_set_drvdata(dev, NULL);
return 0; return 0;
} }
#define GUSEXTREME_DRIVER "snd_gusextreme" static struct isa_driver snd_gusextreme_driver = {
.match = snd_gusextreme_match,
static struct platform_driver snd_gusextreme_driver = {
.probe = snd_gusextreme_probe, .probe = snd_gusextreme_probe,
.remove = __devexit_p(snd_gusextreme_remove), .remove = snd_gusextreme_remove,
/* FIXME: suspend/resume */ #if 0 /* FIXME */
.suspend = snd_gusextreme_suspend,
.resume = snd_gusextreme_resume,
#endif
.driver = { .driver = {
.name = GUSEXTREME_DRIVER .name = DEV_NAME
}, }
}; };
static void __init_or_module snd_gusextreme_unregister_all(void)
{
int i;
for (i = 0; i < ARRAY_SIZE(devices); ++i)
platform_device_unregister(devices[i]);
platform_driver_unregister(&snd_gusextreme_driver);
}
static int __init alsa_card_gusextreme_init(void) static int __init alsa_card_gusextreme_init(void)
{ {
int i, cards, err; return isa_register_driver(&snd_gusextreme_driver, SNDRV_CARDS);
err = platform_driver_register(&snd_gusextreme_driver);
if (err < 0)
return err;
cards = 0;
for (i = 0; i < SNDRV_CARDS; i++) {
struct platform_device *device;
if (! enable[i])
continue;
device = platform_device_register_simple(GUSEXTREME_DRIVER,
i, NULL, 0);
if (IS_ERR(device))
continue;
if (!platform_get_drvdata(device)) {
platform_device_unregister(device);
continue;
}
devices[i] = device;
cards++;
}
if (!cards) {
#ifdef MODULE
printk(KERN_ERR "GUS Extreme soundcard not found or device busy\n");
#endif
snd_gusextreme_unregister_all();
return -ENODEV;
}
return 0;
} }
static void __exit alsa_card_gusextreme_exit(void) static void __exit alsa_card_gusextreme_exit(void)
{ {
snd_gusextreme_unregister_all(); isa_unregister_driver(&snd_gusextreme_driver);
} }
module_init(alsa_card_gusextreme_init) module_init(alsa_card_gusextreme_init);
module_exit(alsa_card_gusextreme_exit) module_exit(alsa_card_gusextreme_exit);
...@@ -22,7 +22,7 @@ ...@@ -22,7 +22,7 @@
#include <sound/driver.h> #include <sound/driver.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/err.h> #include <linux/err.h>
#include <linux/platform_device.h> #include <linux/isa.h>
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/time.h> #include <linux/time.h>
#include <linux/moduleparam.h> #include <linux/moduleparam.h>
...@@ -72,8 +72,6 @@ MODULE_PARM_DESC(channels, "Used GF1 channels for GUS MAX driver."); ...@@ -72,8 +72,6 @@ MODULE_PARM_DESC(channels, "Used GF1 channels for GUS MAX driver.");
module_param_array(pcm_channels, int, NULL, 0444); module_param_array(pcm_channels, int, NULL, 0444);
MODULE_PARM_DESC(pcm_channels, "Reserved PCM channels for GUS MAX driver."); MODULE_PARM_DESC(pcm_channels, "Reserved PCM channels for GUS MAX driver.");
static struct platform_device *devices[SNDRV_CARDS];
struct snd_gusmax { struct snd_gusmax {
int irq; int irq;
struct snd_card *card; struct snd_card *card;
...@@ -205,9 +203,13 @@ static void snd_gusmax_free(struct snd_card *card) ...@@ -205,9 +203,13 @@ static void snd_gusmax_free(struct snd_card *card)
free_irq(maxcard->irq, (void *)maxcard); free_irq(maxcard->irq, (void *)maxcard);
} }
static int __devinit snd_gusmax_probe(struct platform_device *pdev) static int __devinit snd_gusmax_match(struct device *pdev, unsigned int dev)
{
return enable[dev];
}
static int __devinit snd_gusmax_probe(struct device *pdev, unsigned int dev)
{ {
int dev = pdev->id;
static int possible_irqs[] = {5, 11, 12, 9, 7, 15, 3, -1}; static int possible_irqs[] = {5, 11, 12, 9, 7, 15, 3, -1};
static int possible_dmas[] = {5, 6, 7, 1, 3, -1}; static int possible_dmas[] = {5, 6, 7, 1, 3, -1};
int xirq, xdma1, xdma2, err; int xirq, xdma1, xdma2, err;
...@@ -333,7 +335,7 @@ static int __devinit snd_gusmax_probe(struct platform_device *pdev) ...@@ -333,7 +335,7 @@ static int __devinit snd_gusmax_probe(struct platform_device *pdev)
if (xdma2 >= 0) if (xdma2 >= 0)
sprintf(card->longname + strlen(card->longname), "&%i", xdma2); sprintf(card->longname + strlen(card->longname), "&%i", xdma2);
snd_card_set_dev(card, &pdev->dev); snd_card_set_dev(card, pdev);
if ((err = snd_card_register(card)) < 0) if ((err = snd_card_register(card)) < 0)
goto _err; goto _err;
...@@ -341,7 +343,7 @@ static int __devinit snd_gusmax_probe(struct platform_device *pdev) ...@@ -341,7 +343,7 @@ static int __devinit snd_gusmax_probe(struct platform_device *pdev)
maxcard->gus = gus; maxcard->gus = gus;
maxcard->cs4231 = cs4231; maxcard->cs4231 = cs4231;
platform_set_drvdata(pdev, card); dev_set_drvdata(pdev, card);
return 0; return 0;
_err: _err:
...@@ -349,70 +351,33 @@ static int __devinit snd_gusmax_probe(struct platform_device *pdev) ...@@ -349,70 +351,33 @@ static int __devinit snd_gusmax_probe(struct platform_device *pdev)
return err; return err;
} }
static int __devexit snd_gusmax_remove(struct platform_device *devptr) static int __devexit snd_gusmax_remove(struct device *devptr, unsigned int dev)
{ {
snd_card_free(platform_get_drvdata(devptr)); snd_card_free(dev_get_drvdata(devptr));
platform_set_drvdata(devptr, NULL); dev_set_drvdata(devptr, NULL);
return 0; return 0;
} }
#define GUSMAX_DRIVER "snd_gusmax" #define DEV_NAME "gusmax"
static struct platform_driver snd_gusmax_driver = { static struct isa_driver snd_gusmax_driver = {
.match = snd_gusmax_match,
.probe = snd_gusmax_probe, .probe = snd_gusmax_probe,
.remove = __devexit_p(snd_gusmax_remove), .remove = __devexit_p(snd_gusmax_remove),
/* FIXME: suspend/resume */ /* FIXME: suspend/resume */
.driver = { .driver = {
.name = GUSMAX_DRIVER .name = DEV_NAME
}, },
}; };
static void __init_or_module snd_gusmax_unregister_all(void)
{
int i;
for (i = 0; i < ARRAY_SIZE(devices); ++i)
platform_device_unregister(devices[i]);
platform_driver_unregister(&snd_gusmax_driver);
}
static int __init alsa_card_gusmax_init(void) static int __init alsa_card_gusmax_init(void)
{ {
int i, cards, err; return isa_register_driver(&snd_gusmax_driver, SNDRV_CARDS);
err = platform_driver_register(&snd_gusmax_driver);
if (err < 0)
return err;
cards = 0;
for (i = 0; i < SNDRV_CARDS; i++) {
struct platform_device *device;
if (! enable[i])
continue;
device = platform_device_register_simple(GUSMAX_DRIVER,
i, NULL, 0);
if (IS_ERR(device))
continue;
if (!platform_get_drvdata(device)) {
platform_device_unregister(device);
continue;
}
devices[i] = device;
cards++;
}
if (!cards) {
#ifdef MODULE
printk(KERN_ERR "GUS MAX soundcard not found or device busy\n");
#endif
snd_gusmax_unregister_all();
return -ENODEV;
}
return 0;
} }
static void __exit alsa_card_gusmax_exit(void) static void __exit alsa_card_gusmax_exit(void)
{ {
snd_gusmax_unregister_all(); isa_unregister_driver(&snd_gusmax_driver);
} }
module_init(alsa_card_gusmax_init) module_init(alsa_card_gusmax_init)
......
...@@ -25,7 +25,7 @@ ...@@ -25,7 +25,7 @@
#include <sound/driver.h> #include <sound/driver.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/err.h> #include <linux/err.h>
#include <linux/platform_device.h> #include <linux/isa.h>
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/pnp.h> #include <linux/pnp.h>
...@@ -115,9 +115,6 @@ MODULE_PARM_DESC(pcm_channels, "Reserved PCM channels for InterWave driver."); ...@@ -115,9 +115,6 @@ MODULE_PARM_DESC(pcm_channels, "Reserved PCM channels for InterWave driver.");
module_param_array(effect, int, NULL, 0444); module_param_array(effect, int, NULL, 0444);
MODULE_PARM_DESC(effect, "Effects enable for InterWave driver."); MODULE_PARM_DESC(effect, "Effects enable for InterWave driver.");
static struct platform_device *platform_devices[SNDRV_CARDS];
static int pnp_registered;
struct snd_interwave { struct snd_interwave {
int irq; int irq;
struct snd_card *card; struct snd_card *card;
...@@ -138,6 +135,7 @@ struct snd_interwave { ...@@ -138,6 +135,7 @@ struct snd_interwave {
#ifdef CONFIG_PNP #ifdef CONFIG_PNP
static int pnp_registered;
static struct pnp_card_device_id snd_interwave_pnpids[] = { static struct pnp_card_device_id snd_interwave_pnpids[] = {
#ifndef SNDRV_STB #ifndef SNDRV_STB
...@@ -793,7 +791,7 @@ static int __devinit snd_interwave_probe(struct snd_card *card, int dev) ...@@ -793,7 +791,7 @@ static int __devinit snd_interwave_probe(struct snd_card *card, int dev)
return 0; return 0;
} }
static int __devinit snd_interwave_nonpnp_probe1(int dev, struct platform_device *devptr) static int __devinit snd_interwave_isa_probe1(int dev, struct device *devptr)
{ {
struct snd_card *card; struct snd_card *card;
int err; int err;
...@@ -802,18 +800,30 @@ static int __devinit snd_interwave_nonpnp_probe1(int dev, struct platform_device ...@@ -802,18 +800,30 @@ static int __devinit snd_interwave_nonpnp_probe1(int dev, struct platform_device
if (! card) if (! card)
return -ENOMEM; return -ENOMEM;
snd_card_set_dev(card, &devptr->dev); snd_card_set_dev(card, devptr);
if ((err = snd_interwave_probe(card, dev)) < 0) { if ((err = snd_interwave_probe(card, dev)) < 0) {
snd_card_free(card); snd_card_free(card);
return err; return err;
} }
platform_set_drvdata(devptr, card); dev_set_drvdata(devptr, card);
return 0; return 0;
} }
static int __devinit snd_interwave_nonpnp_probe(struct platform_device *pdev) static int __devinit snd_interwave_isa_match(struct device *pdev,
unsigned int dev)
{
if (!enable[dev])
return 0;
#ifdef CONFIG_PNP
if (isapnp[dev])
return 0;
#endif
return 1;
}
static int __devinit snd_interwave_isa_probe(struct device *pdev,
unsigned int dev)
{ {
int dev = pdev->id;
int err; int err;
static int possible_irqs[] = {5, 11, 12, 9, 7, 15, 3, -1}; static int possible_irqs[] = {5, 11, 12, 9, 7, 15, 3, -1};
static int possible_dmas[] = {0, 1, 3, 5, 6, 7, -1}; static int possible_dmas[] = {0, 1, 3, 5, 6, 7, -1};
...@@ -838,13 +848,13 @@ static int __devinit snd_interwave_nonpnp_probe(struct platform_device *pdev) ...@@ -838,13 +848,13 @@ static int __devinit snd_interwave_nonpnp_probe(struct platform_device *pdev)
} }
if (port[dev] != SNDRV_AUTO_PORT) if (port[dev] != SNDRV_AUTO_PORT)
return snd_interwave_nonpnp_probe1(dev, pdev); return snd_interwave_isa_probe1(dev, pdev);
else { else {
static long possible_ports[] = {0x210, 0x220, 0x230, 0x240, 0x250, 0x260}; static long possible_ports[] = {0x210, 0x220, 0x230, 0x240, 0x250, 0x260};
int i; int i;
for (i = 0; i < ARRAY_SIZE(possible_ports); i++) { for (i = 0; i < ARRAY_SIZE(possible_ports); i++) {
port[dev] = possible_ports[i]; port[dev] = possible_ports[i];
err = snd_interwave_nonpnp_probe1(dev, pdev); err = snd_interwave_isa_probe1(dev, pdev);
if (! err) if (! err)
return 0; return 0;
} }
...@@ -852,16 +862,17 @@ static int __devinit snd_interwave_nonpnp_probe(struct platform_device *pdev) ...@@ -852,16 +862,17 @@ static int __devinit snd_interwave_nonpnp_probe(struct platform_device *pdev)
} }
} }
static int __devexit snd_interwave_nonpnp_remove(struct platform_device *devptr) static int __devexit snd_interwave_isa_remove(struct device *devptr, unsigned int dev)
{ {
snd_card_free(platform_get_drvdata(devptr)); snd_card_free(dev_get_drvdata(devptr));
platform_set_drvdata(devptr, NULL); dev_set_drvdata(devptr, NULL);
return 0; return 0;
} }
static struct platform_driver snd_interwave_driver = { static struct isa_driver snd_interwave_driver = {
.probe = snd_interwave_nonpnp_probe, .match = snd_interwave_isa_match,
.remove = __devexit_p(snd_interwave_nonpnp_remove), .probe = snd_interwave_isa_probe,
.remove = __devexit_p(snd_interwave_isa_remove),
/* FIXME: suspend,resume */ /* FIXME: suspend,resume */
.driver = { .driver = {
.name = INTERWAVE_DRIVER .name = INTERWAVE_DRIVER
...@@ -869,8 +880,6 @@ static struct platform_driver snd_interwave_driver = { ...@@ -869,8 +880,6 @@ static struct platform_driver snd_interwave_driver = {
}; };
#ifdef CONFIG_PNP #ifdef CONFIG_PNP
static unsigned int __devinitdata interwave_pnp_devices;
static int __devinit snd_interwave_pnp_detect(struct pnp_card_link *pcard, static int __devinit snd_interwave_pnp_detect(struct pnp_card_link *pcard,
const struct pnp_card_device_id *pid) const struct pnp_card_device_id *pid)
{ {
...@@ -900,7 +909,6 @@ static int __devinit snd_interwave_pnp_detect(struct pnp_card_link *pcard, ...@@ -900,7 +909,6 @@ static int __devinit snd_interwave_pnp_detect(struct pnp_card_link *pcard,
} }
pnp_set_card_drvdata(pcard, card); pnp_set_card_drvdata(pcard, card);
dev++; dev++;
interwave_pnp_devices++;
return 0; return 0;
} }
...@@ -921,64 +929,29 @@ static struct pnp_card_driver interwave_pnpc_driver = { ...@@ -921,64 +929,29 @@ static struct pnp_card_driver interwave_pnpc_driver = {
#endif /* CONFIG_PNP */ #endif /* CONFIG_PNP */
static void __init_or_module snd_interwave_unregister_all(void)
{
int i;
if (pnp_registered)
pnp_unregister_card_driver(&interwave_pnpc_driver);
for (i = 0; i < ARRAY_SIZE(platform_devices); ++i)
platform_device_unregister(platform_devices[i]);
platform_driver_unregister(&snd_interwave_driver);
}
static int __init alsa_card_interwave_init(void) static int __init alsa_card_interwave_init(void)
{ {
int i, err, cards = 0; int err;
if ((err = platform_driver_register(&snd_interwave_driver)) < 0) err = isa_register_driver(&snd_interwave_driver, SNDRV_CARDS);
if (err < 0)
return err; return err;
for (i = 0; i < SNDRV_CARDS; i++) {
struct platform_device *device;
if (! enable[i])
continue;
#ifdef CONFIG_PNP #ifdef CONFIG_PNP
if (isapnp[i])
continue;
#endif
device = platform_device_register_simple(INTERWAVE_DRIVER,
i, NULL, 0);
if (IS_ERR(device))
continue;
if (!platform_get_drvdata(device)) {
platform_device_unregister(device);
continue;
}
platform_devices[i] = device;
cards++;
}
/* ISA PnP cards */ /* ISA PnP cards */
err = pnp_register_card_driver(&interwave_pnpc_driver); err = pnp_register_card_driver(&interwave_pnpc_driver);
if (!err) { if (!err)
pnp_registered = 1; pnp_registered = 1;
cards += interwave_pnp_devices;;
}
if (!cards) {
#ifdef MODULE
printk(KERN_ERR "InterWave soundcard not found or device busy\n");
#endif #endif
snd_interwave_unregister_all();
return -ENODEV;
}
return 0; return 0;
} }
static void __exit alsa_card_interwave_exit(void) static void __exit alsa_card_interwave_exit(void)
{ {
snd_interwave_unregister_all(); #ifdef CONFIG_PNP
if (pnp_registered)
pnp_unregister_card_driver(&interwave_pnpc_driver);
#endif
isa_unregister_driver(&snd_interwave_driver);
} }
module_init(alsa_card_interwave_init) module_init(alsa_card_interwave_init)
......
...@@ -22,7 +22,7 @@ ...@@ -22,7 +22,7 @@
#include <sound/driver.h> #include <sound/driver.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/err.h> #include <linux/err.h>
#include <linux/platform_device.h> #include <linux/isa.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/pm.h> #include <linux/pm.h>
#include <linux/slab.h> #include <linux/slab.h>
...@@ -91,12 +91,10 @@ MODULE_PARM_DESC(dma2, "DMA2 # for OPL3-SA driver."); ...@@ -91,12 +91,10 @@ MODULE_PARM_DESC(dma2, "DMA2 # for OPL3-SA driver.");
module_param_array(opl3sa3_ymode, int, NULL, 0444); module_param_array(opl3sa3_ymode, int, NULL, 0444);
MODULE_PARM_DESC(opl3sa3_ymode, "Speaker size selection for 3D Enhancement mode: Desktop/Large Notebook/Small Notebook/HiFi."); MODULE_PARM_DESC(opl3sa3_ymode, "Speaker size selection for 3D Enhancement mode: Desktop/Large Notebook/Small Notebook/HiFi.");
static struct platform_device *platform_devices[SNDRV_CARDS];
#ifdef CONFIG_PNP #ifdef CONFIG_PNP
static int pnp_registered; static int pnp_registered;
static int pnpc_registered; static int pnpc_registered;
#endif #endif
static unsigned int snd_opl3sa2_devices;
/* control ports */ /* control ports */
#define OPL3SA2_PM_CTRL 0x01 #define OPL3SA2_PM_CTRL 0x01
...@@ -783,7 +781,6 @@ static int __devinit snd_opl3sa2_pnp_detect(struct pnp_dev *pdev, ...@@ -783,7 +781,6 @@ static int __devinit snd_opl3sa2_pnp_detect(struct pnp_dev *pdev,
} }
pnp_set_drvdata(pdev, card); pnp_set_drvdata(pdev, card);
dev++; dev++;
snd_opl3sa2_devices++;
return 0; return 0;
} }
...@@ -850,7 +847,6 @@ static int __devinit snd_opl3sa2_pnp_cdetect(struct pnp_card_link *pcard, ...@@ -850,7 +847,6 @@ static int __devinit snd_opl3sa2_pnp_cdetect(struct pnp_card_link *pcard,
} }
pnp_set_card_drvdata(pcard, card); pnp_set_card_drvdata(pcard, card);
dev++; dev++;
snd_opl3sa2_devices++;
return 0; return 0;
} }
...@@ -884,116 +880,95 @@ static struct pnp_card_driver opl3sa2_pnpc_driver = { ...@@ -884,116 +880,95 @@ static struct pnp_card_driver opl3sa2_pnpc_driver = {
}; };
#endif /* CONFIG_PNP */ #endif /* CONFIG_PNP */
static int __devinit snd_opl3sa2_nonpnp_probe(struct platform_device *pdev) static int __devinit snd_opl3sa2_isa_match(struct device *pdev,
unsigned int dev)
{ {
struct snd_card *card; if (!enable[dev])
int err; return 0;
int dev = pdev->id; #ifdef CONFIG_PNP
if (isapnp[dev])
return 0;
#endif
if (port[dev] == SNDRV_AUTO_PORT) { if (port[dev] == SNDRV_AUTO_PORT) {
snd_printk(KERN_ERR PFX "specify port\n"); snd_printk(KERN_ERR PFX "specify port\n");
return -EINVAL; return 0;
} }
if (wss_port[dev] == SNDRV_AUTO_PORT) { if (wss_port[dev] == SNDRV_AUTO_PORT) {
snd_printk(KERN_ERR PFX "specify wss_port\n"); snd_printk(KERN_ERR PFX "specify wss_port\n");
return -EINVAL; return 0;
} }
if (fm_port[dev] == SNDRV_AUTO_PORT) { if (fm_port[dev] == SNDRV_AUTO_PORT) {
snd_printk(KERN_ERR PFX "specify fm_port\n"); snd_printk(KERN_ERR PFX "specify fm_port\n");
return -EINVAL; return 0;
} }
if (midi_port[dev] == SNDRV_AUTO_PORT) { if (midi_port[dev] == SNDRV_AUTO_PORT) {
snd_printk(KERN_ERR PFX "specify midi_port\n"); snd_printk(KERN_ERR PFX "specify midi_port\n");
return -EINVAL; return 0;
} }
return 1;
}
static int __devinit snd_opl3sa2_isa_probe(struct device *pdev,
unsigned int dev)
{
struct snd_card *card;
int err;
card = snd_opl3sa2_card_new(dev); card = snd_opl3sa2_card_new(dev);
if (! card) if (! card)
return -ENOMEM; return -ENOMEM;
snd_card_set_dev(card, &pdev->dev); snd_card_set_dev(card, pdev);
if ((err = snd_opl3sa2_probe(card, dev)) < 0) { if ((err = snd_opl3sa2_probe(card, dev)) < 0) {
snd_card_free(card); snd_card_free(card);
return err; return err;
} }
platform_set_drvdata(pdev, card); dev_set_drvdata(pdev, card);
return 0; return 0;
} }
static int __devexit snd_opl3sa2_nonpnp_remove(struct platform_device *devptr) static int __devexit snd_opl3sa2_isa_remove(struct device *devptr,
unsigned int dev)
{ {
snd_card_free(platform_get_drvdata(devptr)); snd_card_free(dev_get_drvdata(devptr));
platform_set_drvdata(devptr, NULL); dev_set_drvdata(devptr, NULL);
return 0; return 0;
} }
#ifdef CONFIG_PM #ifdef CONFIG_PM
static int snd_opl3sa2_nonpnp_suspend(struct platform_device *dev, pm_message_t state) static int snd_opl3sa2_isa_suspend(struct device *dev, unsigned int n,
pm_message_t state)
{ {
return snd_opl3sa2_suspend(platform_get_drvdata(dev), state); return snd_opl3sa2_suspend(dev_get_drvdata(dev), state);
} }
static int snd_opl3sa2_nonpnp_resume(struct platform_device *dev) static int snd_opl3sa2_isa_resume(struct device *dev, unsigned int n)
{ {
return snd_opl3sa2_resume(platform_get_drvdata(dev)); return snd_opl3sa2_resume(dev_get_drvdata(dev));
} }
#endif #endif
#define OPL3SA2_DRIVER "snd_opl3sa2" #define DEV_NAME "opl3sa2"
static struct platform_driver snd_opl3sa2_nonpnp_driver = { static struct isa_driver snd_opl3sa2_isa_driver = {
.probe = snd_opl3sa2_nonpnp_probe, .match = snd_opl3sa2_isa_match,
.remove = __devexit( snd_opl3sa2_nonpnp_remove), .probe = snd_opl3sa2_isa_probe,
.remove = __devexit( snd_opl3sa2_isa_remove),
#ifdef CONFIG_PM #ifdef CONFIG_PM
.suspend = snd_opl3sa2_nonpnp_suspend, .suspend = snd_opl3sa2_isa_suspend,
.resume = snd_opl3sa2_nonpnp_resume, .resume = snd_opl3sa2_isa_resume,
#endif #endif
.driver = { .driver = {
.name = OPL3SA2_DRIVER .name = DEV_NAME
}, },
}; };
static void __init_or_module snd_opl3sa2_unregister_all(void)
{
int i;
#ifdef CONFIG_PNP
if (pnpc_registered)
pnp_unregister_card_driver(&opl3sa2_pnpc_driver);
if (pnp_registered)
pnp_unregister_driver(&opl3sa2_pnp_driver);
#endif
for (i = 0; i < ARRAY_SIZE(platform_devices); ++i)
platform_device_unregister(platform_devices[i]);
platform_driver_unregister(&snd_opl3sa2_nonpnp_driver);
}
static int __init alsa_card_opl3sa2_init(void) static int __init alsa_card_opl3sa2_init(void)
{ {
int i, err; int err;
if ((err = platform_driver_register(&snd_opl3sa2_nonpnp_driver)) < 0) err = isa_register_driver(&snd_opl3sa2_isa_driver, SNDRV_CARDS);
if (err < 0)
return err; return err;
for (i = 0; i < SNDRV_CARDS; i++) {
struct platform_device *device;
if (! enable[i])
continue;
#ifdef CONFIG_PNP
if (isapnp[i])
continue;
#endif
device = platform_device_register_simple(OPL3SA2_DRIVER,
i, NULL, 0);
if (IS_ERR(device))
continue;
if (!platform_get_drvdata(device)) {
platform_device_unregister(device);
continue;
}
platform_devices[i] = device;
snd_opl3sa2_devices++;
}
#ifdef CONFIG_PNP #ifdef CONFIG_PNP
err = pnp_register_driver(&opl3sa2_pnp_driver); err = pnp_register_driver(&opl3sa2_pnp_driver);
if (!err) if (!err)
...@@ -1002,20 +977,18 @@ static int __init alsa_card_opl3sa2_init(void) ...@@ -1002,20 +977,18 @@ static int __init alsa_card_opl3sa2_init(void)
if (!err) if (!err)
pnpc_registered = 1; pnpc_registered = 1;
#endif #endif
if (!snd_opl3sa2_devices) {
#ifdef MODULE
snd_printk(KERN_ERR "Yamaha OPL3-SA soundcard not found or device busy\n");
#endif
snd_opl3sa2_unregister_all();
return -ENODEV;
}
return 0; return 0;
} }
static void __exit alsa_card_opl3sa2_exit(void) static void __exit alsa_card_opl3sa2_exit(void)
{ {
snd_opl3sa2_unregister_all(); #ifdef CONFIG_PNP
if (pnpc_registered)
pnp_unregister_card_driver(&opl3sa2_pnpc_driver);
if (pnp_registered)
pnp_unregister_driver(&opl3sa2_pnp_driver);
#endif
isa_unregister_driver(&snd_opl3sa2_isa_driver);
} }
module_init(alsa_card_opl3sa2_init) module_init(alsa_card_opl3sa2_init)
......
...@@ -25,7 +25,7 @@ ...@@ -25,7 +25,7 @@
#include <sound/driver.h> #include <sound/driver.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/err.h> #include <linux/err.h>
#include <linux/platform_device.h> #include <linux/isa.h>
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/ioport.h> #include <linux/ioport.h>
...@@ -137,10 +137,6 @@ struct snd_miro { ...@@ -137,10 +137,6 @@ struct snd_miro {
static void snd_miro_proc_init(struct snd_miro * miro); static void snd_miro_proc_init(struct snd_miro * miro);
#define DRIVER_NAME "snd-miro"
static struct platform_device *device;
static char * snd_opti9xx_names[] = { static char * snd_opti9xx_names[] = {
"unkown", "unkown",
"82C928", "82C929", "82C928", "82C929",
...@@ -558,7 +554,7 @@ static int snd_miro_put_double(struct snd_kcontrol *kcontrol, ...@@ -558,7 +554,7 @@ static int snd_miro_put_double(struct snd_kcontrol *kcontrol,
return change; return change;
} }
static struct snd_kcontrol_new snd_miro_controls[] = { static struct snd_kcontrol_new snd_miro_controls[] __devinitdata = {
MIRO_DOUBLE("Master Playback Volume", 0, ACI_GET_MASTER, ACI_SET_MASTER), MIRO_DOUBLE("Master Playback Volume", 0, ACI_GET_MASTER, ACI_SET_MASTER),
MIRO_DOUBLE("Mic Playback Volume", 1, ACI_GET_MIC, ACI_SET_MIC), MIRO_DOUBLE("Mic Playback Volume", 1, ACI_GET_MIC, ACI_SET_MIC),
MIRO_DOUBLE("Line Playback Volume", 1, ACI_GET_LINE, ACI_SET_LINE), MIRO_DOUBLE("Line Playback Volume", 1, ACI_GET_LINE, ACI_SET_LINE),
...@@ -570,7 +566,7 @@ MIRO_DOUBLE("Aux Playback Volume", 2, ACI_GET_LINE2, ACI_SET_LINE2), ...@@ -570,7 +566,7 @@ MIRO_DOUBLE("Aux Playback Volume", 2, ACI_GET_LINE2, ACI_SET_LINE2),
/* Equalizer with seven bands (only PCM20) /* Equalizer with seven bands (only PCM20)
from -12dB up to +12dB on each band */ from -12dB up to +12dB on each band */
static struct snd_kcontrol_new snd_miro_eq_controls[] = { static struct snd_kcontrol_new snd_miro_eq_controls[] __devinitdata = {
MIRO_DOUBLE("Tone Control - 28 Hz", 0, ACI_GET_EQ1, ACI_SET_EQ1), MIRO_DOUBLE("Tone Control - 28 Hz", 0, ACI_GET_EQ1, ACI_SET_EQ1),
MIRO_DOUBLE("Tone Control - 160 Hz", 0, ACI_GET_EQ2, ACI_SET_EQ2), MIRO_DOUBLE("Tone Control - 160 Hz", 0, ACI_GET_EQ2, ACI_SET_EQ2),
MIRO_DOUBLE("Tone Control - 400 Hz", 0, ACI_GET_EQ3, ACI_SET_EQ3), MIRO_DOUBLE("Tone Control - 400 Hz", 0, ACI_GET_EQ3, ACI_SET_EQ3),
...@@ -580,15 +576,15 @@ MIRO_DOUBLE("Tone Control - 6.3 kHz", 0, ACI_GET_EQ6, ACI_SET_EQ6), ...@@ -580,15 +576,15 @@ MIRO_DOUBLE("Tone Control - 6.3 kHz", 0, ACI_GET_EQ6, ACI_SET_EQ6),
MIRO_DOUBLE("Tone Control - 16 kHz", 0, ACI_GET_EQ7, ACI_SET_EQ7), MIRO_DOUBLE("Tone Control - 16 kHz", 0, ACI_GET_EQ7, ACI_SET_EQ7),
}; };
static struct snd_kcontrol_new snd_miro_radio_control[] = { static struct snd_kcontrol_new snd_miro_radio_control[] __devinitdata = {
MIRO_DOUBLE("Radio Playback Volume", 0, ACI_GET_LINE1, ACI_SET_LINE1), MIRO_DOUBLE("Radio Playback Volume", 0, ACI_GET_LINE1, ACI_SET_LINE1),
}; };
static struct snd_kcontrol_new snd_miro_line_control[] = { static struct snd_kcontrol_new snd_miro_line_control[] __devinitdata = {
MIRO_DOUBLE("Line Playback Volume", 2, ACI_GET_LINE1, ACI_SET_LINE1), MIRO_DOUBLE("Line Playback Volume", 2, ACI_GET_LINE1, ACI_SET_LINE1),
}; };
static struct snd_kcontrol_new snd_miro_preamp_control[] = { static struct snd_kcontrol_new snd_miro_preamp_control[] __devinitdata = {
{ {
.iface = SNDRV_CTL_ELEM_IFACE_MIXER, .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "Mic Boost", .name = "Mic Boost",
...@@ -598,7 +594,7 @@ static struct snd_kcontrol_new snd_miro_preamp_control[] = { ...@@ -598,7 +594,7 @@ static struct snd_kcontrol_new snd_miro_preamp_control[] = {
.put = snd_miro_put_preamp, .put = snd_miro_put_preamp,
}}; }};
static struct snd_kcontrol_new snd_miro_amp_control[] = { static struct snd_kcontrol_new snd_miro_amp_control[] __devinitdata = {
{ {
.iface = SNDRV_CTL_ELEM_IFACE_MIXER, .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "Line Boost", .name = "Line Boost",
...@@ -608,7 +604,7 @@ static struct snd_kcontrol_new snd_miro_amp_control[] = { ...@@ -608,7 +604,7 @@ static struct snd_kcontrol_new snd_miro_amp_control[] = {
.put = snd_miro_put_amp, .put = snd_miro_put_amp,
}}; }};
static struct snd_kcontrol_new snd_miro_capture_control[] = { static struct snd_kcontrol_new snd_miro_capture_control[] __devinitdata = {
{ {
.iface = SNDRV_CTL_ELEM_IFACE_MIXER, .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "PCM Capture Switch", .name = "PCM Capture Switch",
...@@ -618,7 +614,7 @@ static struct snd_kcontrol_new snd_miro_capture_control[] = { ...@@ -618,7 +614,7 @@ static struct snd_kcontrol_new snd_miro_capture_control[] = {
.put = snd_miro_put_capture, .put = snd_miro_put_capture,
}}; }};
static unsigned char aci_init_values[][2] __initdata = { static unsigned char aci_init_values[][2] __devinitdata = {
{ ACI_SET_MUTE, 0x00 }, { ACI_SET_MUTE, 0x00 },
{ ACI_SET_POWERAMP, 0x00 }, { ACI_SET_POWERAMP, 0x00 },
{ ACI_SET_PREAMP, 0x00 }, { ACI_SET_PREAMP, 0x00 },
...@@ -641,7 +637,7 @@ static unsigned char aci_init_values[][2] __initdata = { ...@@ -641,7 +637,7 @@ static unsigned char aci_init_values[][2] __initdata = {
{ ACI_SET_MASTER + 1, 0x20 }, { ACI_SET_MASTER + 1, 0x20 },
}; };
static int __init snd_set_aci_init_values(struct snd_miro *miro) static int __devinit snd_set_aci_init_values(struct snd_miro *miro)
{ {
int idx, error; int idx, error;
...@@ -751,7 +747,8 @@ static long snd_legacy_find_free_ioport(long *port_table, long size) ...@@ -751,7 +747,8 @@ static long snd_legacy_find_free_ioport(long *port_table, long size)
return -1; return -1;
} }
static int __init snd_miro_init(struct snd_miro *chip, unsigned short hardware) static int __devinit snd_miro_init(struct snd_miro *chip,
unsigned short hardware)
{ {
static int opti9xx_mc_size[] = {7, 7, 10, 10, 2, 2, 2}; static int opti9xx_mc_size[] = {7, 7, 10, 10, 2, 2, 2};
...@@ -962,7 +959,7 @@ static void snd_miro_proc_read(struct snd_info_entry * entry, ...@@ -962,7 +959,7 @@ static void snd_miro_proc_read(struct snd_info_entry * entry,
snd_iprintf(buffer, " preamp : 0x%x\n", miro->aci_preamp); snd_iprintf(buffer, " preamp : 0x%x\n", miro->aci_preamp);
} }
static void __init snd_miro_proc_init(struct snd_miro * miro) static void __devinit snd_miro_proc_init(struct snd_miro * miro)
{ {
struct snd_info_entry *entry; struct snd_info_entry *entry;
...@@ -974,7 +971,7 @@ static void __init snd_miro_proc_init(struct snd_miro * miro) ...@@ -974,7 +971,7 @@ static void __init snd_miro_proc_init(struct snd_miro * miro)
* Init * Init
*/ */
static int __init snd_miro_configure(struct snd_miro *chip) static int __devinit snd_miro_configure(struct snd_miro *chip)
{ {
unsigned char wss_base_bits; unsigned char wss_base_bits;
unsigned char irq_bits; unsigned char irq_bits;
...@@ -1131,7 +1128,8 @@ static int __init snd_miro_configure(struct snd_miro *chip) ...@@ -1131,7 +1128,8 @@ static int __init snd_miro_configure(struct snd_miro *chip)
return 0; return 0;
} }
static int __init snd_card_miro_detect(struct snd_card *card, struct snd_miro *chip) static int __devinit snd_card_miro_detect(struct snd_card *card,
struct snd_miro *chip)
{ {
int i, err; int i, err;
unsigned char value; unsigned char value;
...@@ -1157,7 +1155,8 @@ static int __init snd_card_miro_detect(struct snd_card *card, struct snd_miro *c ...@@ -1157,7 +1155,8 @@ static int __init snd_card_miro_detect(struct snd_card *card, struct snd_miro *c
return -ENODEV; return -ENODEV;
} }
static int __init snd_card_miro_aci_detect(struct snd_card *card, struct snd_miro * miro) static int __devinit snd_card_miro_aci_detect(struct snd_card *card,
struct snd_miro * miro)
{ {
unsigned char regval; unsigned char regval;
int i; int i;
...@@ -1213,7 +1212,12 @@ static void snd_card_miro_free(struct snd_card *card) ...@@ -1213,7 +1212,12 @@ static void snd_card_miro_free(struct snd_card *card)
release_and_free_resource(miro->res_mc_base); release_and_free_resource(miro->res_mc_base);
} }
static int __init snd_miro_probe(struct platform_device *devptr) static int __devinit snd_miro_match(struct device *devptr, unsigned int n)
{
return 1;
}
static int __devinit snd_miro_probe(struct device *devptr, unsigned int n)
{ {
static long possible_ports[] = {0x530, 0xe80, 0xf40, 0x604, -1}; static long possible_ports[] = {0x530, 0xe80, 0xf40, 0x604, -1};
static long possible_mpu_ports[] = {0x330, 0x300, 0x310, 0x320, -1}; static long possible_mpu_ports[] = {0x330, 0x300, 0x310, 0x320, -1};
...@@ -1399,56 +1403,44 @@ static int __init snd_miro_probe(struct platform_device *devptr) ...@@ -1399,56 +1403,44 @@ static int __init snd_miro_probe(struct platform_device *devptr)
return error; return error;
} }
snd_card_set_dev(card, &devptr->dev); snd_card_set_dev(card, devptr);
if ((error = snd_card_register(card))) { if ((error = snd_card_register(card))) {
snd_card_free(card); snd_card_free(card);
return error; return error;
} }
platform_set_drvdata(devptr, card); dev_set_drvdata(devptr, card);
return 0; return 0;
} }
static int __devexit snd_miro_remove(struct platform_device *devptr) static int __devexit snd_miro_remove(struct device *devptr, unsigned int dev)
{ {
snd_card_free(platform_get_drvdata(devptr)); snd_card_free(dev_get_drvdata(devptr));
platform_set_drvdata(devptr, NULL); dev_set_drvdata(devptr, NULL);
return 0; return 0;
} }
static struct platform_driver snd_miro_driver = { #define DEV_NAME "miro"
static struct isa_driver snd_miro_driver = {
.match = snd_miro_match,
.probe = snd_miro_probe, .probe = snd_miro_probe,
.remove = __devexit_p(snd_miro_remove), .remove = __devexit_p(snd_miro_remove),
/* FIXME: suspend/resume */ /* FIXME: suspend/resume */
.driver = { .driver = {
.name = DRIVER_NAME .name = DEV_NAME
}, },
}; };
static int __init alsa_card_miro_init(void) static int __init alsa_card_miro_init(void)
{ {
int error; return isa_register_driver(&snd_miro_driver, 1);
if ((error = platform_driver_register(&snd_miro_driver)) < 0)
return error;
device = platform_device_register_simple(DRIVER_NAME, -1, NULL, 0);
if (! IS_ERR(device)) {
if (platform_get_drvdata(device))
return 0;
platform_device_unregister(device);
}
#ifdef MODULE
printk(KERN_ERR "no miro soundcard found\n");
#endif
platform_driver_unregister(&snd_miro_driver);
return PTR_ERR(device);
} }
static void __exit alsa_card_miro_exit(void) static void __exit alsa_card_miro_exit(void)
{ {
platform_device_unregister(device); isa_unregister_driver(&snd_miro_driver);
platform_driver_unregister(&snd_miro_driver);
} }
module_init(alsa_card_miro_init) module_init(alsa_card_miro_init)
......
...@@ -26,7 +26,7 @@ ...@@ -26,7 +26,7 @@
#include <sound/driver.h> #include <sound/driver.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/err.h> #include <linux/err.h>
#include <linux/platform_device.h> #include <linux/isa.h>
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/pnp.h> #include <linux/pnp.h>
...@@ -259,7 +259,6 @@ struct snd_opti9xx { ...@@ -259,7 +259,6 @@ struct snd_opti9xx {
}; };
static int snd_opti9xx_pnp_is_probed; static int snd_opti9xx_pnp_is_probed;
static struct platform_device *snd_opti9xx_platform_device;
#ifdef CONFIG_PNP #ifdef CONFIG_PNP
...@@ -281,10 +280,10 @@ MODULE_DEVICE_TABLE(pnp_card, snd_opti9xx_pnpids); ...@@ -281,10 +280,10 @@ MODULE_DEVICE_TABLE(pnp_card, snd_opti9xx_pnpids);
#endif /* CONFIG_PNP */ #endif /* CONFIG_PNP */
#ifdef OPTi93X #ifdef OPTi93X
#define DRIVER_NAME "snd-card-opti93x" #define DEV_NAME "opti93x"
#else #else
#define DRIVER_NAME "snd-card-opti92x" #define DEV_NAME "opti92x"
#endif /* OPTi93X */ #endif
static char * snd_opti9xx_names[] = { static char * snd_opti9xx_names[] = {
"unkown", "unkown",
...@@ -294,7 +293,7 @@ static char * snd_opti9xx_names[] = { ...@@ -294,7 +293,7 @@ static char * snd_opti9xx_names[] = {
}; };
static long __init snd_legacy_find_free_ioport(long *port_table, long size) static long __devinit snd_legacy_find_free_ioport(long *port_table, long size)
{ {
while (*port_table != -1) { while (*port_table != -1) {
if (request_region(*port_table, size, "ALSA test")) { if (request_region(*port_table, size, "ALSA test")) {
...@@ -306,7 +305,8 @@ static long __init snd_legacy_find_free_ioport(long *port_table, long size) ...@@ -306,7 +305,8 @@ static long __init snd_legacy_find_free_ioport(long *port_table, long size)
return -1; return -1;
} }
static int __init snd_opti9xx_init(struct snd_opti9xx *chip, unsigned short hardware) static int __devinit snd_opti9xx_init(struct snd_opti9xx *chip,
unsigned short hardware)
{ {
static int opti9xx_mc_size[] = {7, 7, 10, 10, 2, 2, 2}; static int opti9xx_mc_size[] = {7, 7, 10, 10, 2, 2, 2};
...@@ -451,7 +451,7 @@ static void snd_opti9xx_write(struct snd_opti9xx *chip, unsigned char reg, ...@@ -451,7 +451,7 @@ static void snd_opti9xx_write(struct snd_opti9xx *chip, unsigned char reg,
(snd_opti9xx_read(chip, reg) & ~(mask)) | ((value) & (mask))) (snd_opti9xx_read(chip, reg) & ~(mask)) | ((value) & (mask)))
static int __init snd_opti9xx_configure(struct snd_opti9xx *chip) static int __devinit snd_opti9xx_configure(struct snd_opti9xx *chip)
{ {
unsigned char wss_base_bits; unsigned char wss_base_bits;
unsigned char irq_bits; unsigned char irq_bits;
...@@ -934,10 +934,8 @@ static int snd_opti93x_trigger(struct snd_pcm_substream *substream, ...@@ -934,10 +934,8 @@ static int snd_opti93x_trigger(struct snd_pcm_substream *substream,
case SNDRV_PCM_TRIGGER_STOP: case SNDRV_PCM_TRIGGER_STOP:
{ {
unsigned int what = 0; unsigned int what = 0;
struct list_head *pos;
struct snd_pcm_substream *s; struct snd_pcm_substream *s;
snd_pcm_group_for_each(pos, substream) { snd_pcm_group_for_each_entry(s, substream) {
s = snd_pcm_group_substream_entry(pos);
if (s == chip->playback_substream) { if (s == chip->playback_substream) {
what |= OPTi93X_PLAYBACK_ENABLE; what |= OPTi93X_PLAYBACK_ENABLE;
snd_pcm_trigger_done(s, substream); snd_pcm_trigger_done(s, substream);
...@@ -1291,7 +1289,7 @@ static int snd_opti93x_create(struct snd_card *card, struct snd_opti9xx *chip, ...@@ -1291,7 +1289,7 @@ static int snd_opti93x_create(struct snd_card *card, struct snd_opti9xx *chip,
} }
codec->dma2 = chip->dma2; codec->dma2 = chip->dma2;
if (request_irq(chip->irq, snd_opti93x_interrupt, IRQF_DISABLED, DRIVER_NAME" - WSS", codec)) { if (request_irq(chip->irq, snd_opti93x_interrupt, IRQF_DISABLED, DEV_NAME" - WSS", codec)) {
snd_printk(KERN_ERR "opti9xx: can't grab IRQ %d\n", chip->irq); snd_printk(KERN_ERR "opti9xx: can't grab IRQ %d\n", chip->irq);
snd_opti93x_free(codec); snd_opti93x_free(codec);
return -EBUSY; return -EBUSY;
...@@ -1561,7 +1559,7 @@ static int snd_opti93x_put_double(struct snd_kcontrol *kcontrol, struct snd_ctl_ ...@@ -1561,7 +1559,7 @@ static int snd_opti93x_put_double(struct snd_kcontrol *kcontrol, struct snd_ctl_
return change; return change;
} }
static struct snd_kcontrol_new snd_opti93x_controls[] = { static struct snd_kcontrol_new snd_opti93x_controls[] __devinitdata = {
OPTi93X_DOUBLE("Master Playback Switch", 0, OPTi93X_OUT_LEFT, OPTi93X_OUT_RIGHT, 7, 7, 1, 1), OPTi93X_DOUBLE("Master Playback Switch", 0, OPTi93X_OUT_LEFT, OPTi93X_OUT_RIGHT, 7, 7, 1, 1),
OPTi93X_DOUBLE("Master Playback Volume", 0, OPTi93X_OUT_LEFT, OPTi93X_OUT_RIGHT, 1, 1, 31, 1), OPTi93X_DOUBLE("Master Playback Volume", 0, OPTi93X_OUT_LEFT, OPTi93X_OUT_RIGHT, 1, 1, 31, 1),
OPTi93X_DOUBLE("PCM Playback Switch", 0, OPTi93X_DAC_LEFT, OPTi93X_DAC_RIGHT, 7, 7, 1, 1), OPTi93X_DOUBLE("PCM Playback Switch", 0, OPTi93X_DAC_LEFT, OPTi93X_DAC_RIGHT, 7, 7, 1, 1),
...@@ -1622,7 +1620,8 @@ static int snd_opti93x_mixer(struct snd_opti93x *chip) ...@@ -1622,7 +1620,8 @@ static int snd_opti93x_mixer(struct snd_opti93x *chip)
#endif /* OPTi93X */ #endif /* OPTi93X */
static int __init snd_card_opti9xx_detect(struct snd_card *card, struct snd_opti9xx *chip) static int __devinit snd_card_opti9xx_detect(struct snd_card *card,
struct snd_opti9xx *chip)
{ {
int i, err; int i, err;
...@@ -1676,8 +1675,9 @@ static int __init snd_card_opti9xx_detect(struct snd_card *card, struct snd_opti ...@@ -1676,8 +1675,9 @@ static int __init snd_card_opti9xx_detect(struct snd_card *card, struct snd_opti
} }
#ifdef CONFIG_PNP #ifdef CONFIG_PNP
static int __init snd_card_opti9xx_pnp(struct snd_opti9xx *chip, struct pnp_card_link *card, static int __devinit snd_card_opti9xx_pnp(struct snd_opti9xx *chip,
const struct pnp_card_device_id *pid) struct pnp_card_link *card,
const struct pnp_card_device_id *pid)
{ {
struct pnp_dev *pdev; struct pnp_dev *pdev;
struct pnp_resource_table *cfg = kmalloc(sizeof(*cfg), GFP_KERNEL); struct pnp_resource_table *cfg = kmalloc(sizeof(*cfg), GFP_KERNEL);
...@@ -1778,7 +1778,7 @@ static void snd_card_opti9xx_free(struct snd_card *card) ...@@ -1778,7 +1778,7 @@ static void snd_card_opti9xx_free(struct snd_card *card)
release_and_free_resource(chip->res_mc_base); release_and_free_resource(chip->res_mc_base);
} }
static int __init snd_opti9xx_probe(struct snd_card *card) static int __devinit snd_opti9xx_probe(struct snd_card *card)
{ {
static long possible_ports[] = {0x530, 0xe80, 0xf40, 0x604, -1}; static long possible_ports[] = {0x530, 0xe80, 0xf40, 0x604, -1};
int error; int error;
...@@ -1924,7 +1924,18 @@ static struct snd_card *snd_opti9xx_card_new(void) ...@@ -1924,7 +1924,18 @@ static struct snd_card *snd_opti9xx_card_new(void)
return card; return card;
} }
static int __init snd_opti9xx_nonpnp_probe(struct platform_device *devptr) static int __devinit snd_opti9xx_isa_match(struct device *devptr,
unsigned int dev)
{
if (snd_opti9xx_pnp_is_probed)
return 0;
if (isapnp)
return 0;
return 1;
}
static int __devinit snd_opti9xx_isa_probe(struct device *devptr,
unsigned int dev)
{ {
struct snd_card *card; struct snd_card *card;
int error; int error;
...@@ -1940,9 +1951,6 @@ static int __init snd_opti9xx_nonpnp_probe(struct platform_device *devptr) ...@@ -1940,9 +1951,6 @@ static int __init snd_opti9xx_nonpnp_probe(struct platform_device *devptr)
static int possible_dma2s[][2] = {{1,-1}, {0,-1}, {-1,-1}, {0,-1}}; static int possible_dma2s[][2] = {{1,-1}, {0,-1}, {-1,-1}, {0,-1}};
#endif /* CS4231 || OPTi93X */ #endif /* CS4231 || OPTi93X */
if (snd_opti9xx_pnp_is_probed)
return -EBUSY;
if (mpu_port == SNDRV_AUTO_PORT) { if (mpu_port == SNDRV_AUTO_PORT) {
if ((mpu_port = snd_legacy_find_free_ioport(possible_mpu_ports, 2)) < 0) { if ((mpu_port = snd_legacy_find_free_ioport(possible_mpu_ports, 2)) < 0) {
snd_printk(KERN_ERR "unable to find a free MPU401 port\n"); snd_printk(KERN_ERR "unable to find a free MPU401 port\n");
...@@ -1984,34 +1992,36 @@ static int __init snd_opti9xx_nonpnp_probe(struct platform_device *devptr) ...@@ -1984,34 +1992,36 @@ static int __init snd_opti9xx_nonpnp_probe(struct platform_device *devptr)
snd_card_free(card); snd_card_free(card);
return error; return error;
} }
snd_card_set_dev(card, &devptr->dev); snd_card_set_dev(card, devptr);
if ((error = snd_opti9xx_probe(card)) < 0) { if ((error = snd_opti9xx_probe(card)) < 0) {
snd_card_free(card); snd_card_free(card);
return error; return error;
} }
platform_set_drvdata(devptr, card); dev_set_drvdata(devptr, card);
return 0; return 0;
} }
static int __devexit snd_opti9xx_nonpnp_remove(struct platform_device *devptr) static int __devexit snd_opti9xx_isa_remove(struct device *devptr,
unsigned int dev)
{ {
snd_card_free(platform_get_drvdata(devptr)); snd_card_free(dev_get_drvdata(devptr));
platform_set_drvdata(devptr, NULL); dev_set_drvdata(devptr, NULL);
return 0; return 0;
} }
static struct platform_driver snd_opti9xx_driver = { static struct isa_driver snd_opti9xx_driver = {
.probe = snd_opti9xx_nonpnp_probe, .match = snd_opti9xx_isa_match,
.remove = __devexit_p(snd_opti9xx_nonpnp_remove), .probe = snd_opti9xx_isa_probe,
.remove = __devexit_p(snd_opti9xx_isa_remove),
/* FIXME: suspend/resume */ /* FIXME: suspend/resume */
.driver = { .driver = {
.name = DRIVER_NAME .name = DEV_NAME
}, },
}; };
#ifdef CONFIG_PNP #ifdef CONFIG_PNP
static int __init snd_opti9xx_pnp_probe(struct pnp_card_link *pcard, static int __devinit snd_opti9xx_pnp_probe(struct pnp_card_link *pcard,
const struct pnp_card_device_id *pid) const struct pnp_card_device_id *pid)
{ {
struct snd_card *card; struct snd_card *card;
int error, hw; int error, hw;
...@@ -2074,11 +2084,6 @@ static struct pnp_card_driver opti9xx_pnpc_driver = { ...@@ -2074,11 +2084,6 @@ static struct pnp_card_driver opti9xx_pnpc_driver = {
}; };
#endif #endif
#ifdef CONFIG_PNP
#define is_isapnp_selected() isapnp
#else
#define is_isapnp_selected() 0
#endif
#ifdef OPTi93X #ifdef OPTi93X
#define CHIP_NAME "82C93x" #define CHIP_NAME "82C93x"
#else #else
...@@ -2087,42 +2092,19 @@ static struct pnp_card_driver opti9xx_pnpc_driver = { ...@@ -2087,42 +2092,19 @@ static struct pnp_card_driver opti9xx_pnpc_driver = {
static int __init alsa_card_opti9xx_init(void) static int __init alsa_card_opti9xx_init(void)
{ {
int error;
struct platform_device *device;
#ifdef CONFIG_PNP #ifdef CONFIG_PNP
pnp_register_card_driver(&opti9xx_pnpc_driver); pnp_register_card_driver(&opti9xx_pnpc_driver);
if (snd_opti9xx_pnp_is_probed) if (snd_opti9xx_pnp_is_probed)
return 0; return 0;
#endif #endif
if (! is_isapnp_selected()) { return isa_register_driver(&snd_opti9xx_driver, 1);
error = platform_driver_register(&snd_opti9xx_driver);
if (error < 0)
return error;
device = platform_device_register_simple(DRIVER_NAME, -1, NULL, 0);
if (!IS_ERR(device)) {
if (platform_get_drvdata(device)) {
snd_opti9xx_platform_device = device;
return 0;
}
platform_device_unregister(device);
}
platform_driver_unregister(&snd_opti9xx_driver);
}
#ifdef CONFIG_PNP
pnp_unregister_card_driver(&opti9xx_pnpc_driver);
#endif
#ifdef MODULE
printk(KERN_ERR "no OPTi " CHIP_NAME " soundcard found\n");
#endif
return -ENODEV;
} }
static void __exit alsa_card_opti9xx_exit(void) static void __exit alsa_card_opti9xx_exit(void)
{ {
if (!snd_opti9xx_pnp_is_probed) { if (!snd_opti9xx_pnp_is_probed) {
platform_device_unregister(snd_opti9xx_platform_device); isa_unregister_driver(&snd_opti9xx_driver);
platform_driver_unregister(&snd_opti9xx_driver); return;
} }
#ifdef CONFIG_PNP #ifdef CONFIG_PNP
pnp_unregister_card_driver(&opti9xx_pnpc_driver); pnp_unregister_card_driver(&opti9xx_pnpc_driver);
......
...@@ -25,7 +25,7 @@ ...@@ -25,7 +25,7 @@
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/pnp.h> #include <linux/pnp.h>
#include <linux/err.h> #include <linux/err.h>
#include <linux/platform_device.h> #include <linux/isa.h>
#include <linux/moduleparam.h> #include <linux/moduleparam.h>
#include <sound/core.h> #include <sound/core.h>
#include <sound/sb.h> #include <sound/sb.h>
...@@ -128,7 +128,6 @@ module_param_array(seq_ports, int, NULL, 0444); ...@@ -128,7 +128,6 @@ module_param_array(seq_ports, int, NULL, 0444);
MODULE_PARM_DESC(seq_ports, "Number of sequencer ports for WaveTable synth."); MODULE_PARM_DESC(seq_ports, "Number of sequencer ports for WaveTable synth.");
#endif #endif
static struct platform_device *platform_devices[SNDRV_CARDS];
#ifdef CONFIG_PNP #ifdef CONFIG_PNP
static int pnp_registered; static int pnp_registered;
#endif #endif
...@@ -519,7 +518,7 @@ static int snd_sb16_resume(struct snd_card *card) ...@@ -519,7 +518,7 @@ static int snd_sb16_resume(struct snd_card *card)
} }
#endif #endif
static int __devinit snd_sb16_nonpnp_probe1(int dev, struct platform_device *devptr) static int __devinit snd_sb16_isa_probe1(int dev, struct device *pdev)
{ {
struct snd_card_sb16 *acard; struct snd_card_sb16 *acard;
struct snd_card *card; struct snd_card *card;
...@@ -539,19 +538,23 @@ static int __devinit snd_sb16_nonpnp_probe1(int dev, struct platform_device *dev ...@@ -539,19 +538,23 @@ static int __devinit snd_sb16_nonpnp_probe1(int dev, struct platform_device *dev
awe_port[dev] = port[dev] + 0x400; awe_port[dev] = port[dev] + 0x400;
#endif #endif
snd_card_set_dev(card, &devptr->dev); snd_card_set_dev(card, pdev);
if ((err = snd_sb16_probe(card, dev)) < 0) { if ((err = snd_sb16_probe(card, dev)) < 0) {
snd_card_free(card); snd_card_free(card);
return err; return err;
} }
platform_set_drvdata(devptr, card); dev_set_drvdata(pdev, card);
return 0; return 0;
} }
static int __devinit snd_sb16_nonpnp_probe(struct platform_device *pdev) static int __devinit snd_sb16_isa_match(struct device *pdev, unsigned int dev)
{
return enable[dev] && !is_isapnp_selected(dev);
}
static int __devinit snd_sb16_isa_probe(struct device *pdev, unsigned int dev)
{ {
int dev = pdev->id;
int err; int err;
static int possible_irqs[] = {5, 9, 10, 7, -1}; static int possible_irqs[] = {5, 9, 10, 7, -1};
static int possible_dmas8[] = {1, 3, 0, -1}; static int possible_dmas8[] = {1, 3, 0, -1};
...@@ -577,13 +580,13 @@ static int __devinit snd_sb16_nonpnp_probe(struct platform_device *pdev) ...@@ -577,13 +580,13 @@ static int __devinit snd_sb16_nonpnp_probe(struct platform_device *pdev)
} }
if (port[dev] != SNDRV_AUTO_PORT) if (port[dev] != SNDRV_AUTO_PORT)
return snd_sb16_nonpnp_probe1(dev, pdev); return snd_sb16_isa_probe1(dev, pdev);
else { else {
static int possible_ports[] = {0x220, 0x240, 0x260, 0x280}; static int possible_ports[] = {0x220, 0x240, 0x260, 0x280};
int i; int i;
for (i = 0; i < ARRAY_SIZE(possible_ports); i++) { for (i = 0; i < ARRAY_SIZE(possible_ports); i++) {
port[dev] = possible_ports[i]; port[dev] = possible_ports[i];
err = snd_sb16_nonpnp_probe1(dev, pdev); err = snd_sb16_isa_probe1(dev, pdev);
if (! err) if (! err)
return 0; return 0;
} }
...@@ -591,47 +594,47 @@ static int __devinit snd_sb16_nonpnp_probe(struct platform_device *pdev) ...@@ -591,47 +594,47 @@ static int __devinit snd_sb16_nonpnp_probe(struct platform_device *pdev)
} }
} }
static int __devexit snd_sb16_nonpnp_remove(struct platform_device *devptr) static int __devexit snd_sb16_isa_remove(struct device *pdev, unsigned int dev)
{ {
snd_card_free(platform_get_drvdata(devptr)); snd_card_free(dev_get_drvdata(pdev));
platform_set_drvdata(devptr, NULL); dev_set_drvdata(pdev, NULL);
return 0; return 0;
} }
#ifdef CONFIG_PM #ifdef CONFIG_PM
static int snd_sb16_nonpnp_suspend(struct platform_device *dev, pm_message_t state) static int snd_sb16_isa_suspend(struct device *dev, unsigned int n,
pm_message_t state)
{ {
return snd_sb16_suspend(platform_get_drvdata(dev), state); return snd_sb16_suspend(dev_get_drvdata(dev), state);
} }
static int snd_sb16_nonpnp_resume(struct platform_device *dev) static int snd_sb16_isa_resume(struct device *dev, unsigned int n)
{ {
return snd_sb16_resume(platform_get_drvdata(dev)); return snd_sb16_resume(dev_get_drvdata(dev));
} }
#endif #endif
#ifdef SNDRV_SBAWE #ifdef SNDRV_SBAWE
#define SND_SB16_DRIVER "snd_sbawe" #define DEV_NAME "sbawe"
#else #else
#define SND_SB16_DRIVER "snd_sb16" #define DEV_NAME "sb16"
#endif #endif
static struct platform_driver snd_sb16_nonpnp_driver = { static struct isa_driver snd_sb16_isa_driver = {
.probe = snd_sb16_nonpnp_probe, .match = snd_sb16_isa_match,
.remove = __devexit_p(snd_sb16_nonpnp_remove), .probe = snd_sb16_isa_probe,
.remove = __devexit_p(snd_sb16_isa_remove),
#ifdef CONFIG_PM #ifdef CONFIG_PM
.suspend = snd_sb16_nonpnp_suspend, .suspend = snd_sb16_isa_suspend,
.resume = snd_sb16_nonpnp_resume, .resume = snd_sb16_isa_resume,
#endif #endif
.driver = { .driver = {
.name = SND_SB16_DRIVER .name = DEV_NAME
}, },
}; };
#ifdef CONFIG_PNP #ifdef CONFIG_PNP
static unsigned int __devinitdata sb16_pnp_devices;
static int __devinit snd_sb16_pnp_detect(struct pnp_card_link *pcard, static int __devinit snd_sb16_pnp_detect(struct pnp_card_link *pcard,
const struct pnp_card_device_id *pid) const struct pnp_card_device_id *pid)
{ {
...@@ -653,7 +656,6 @@ static int __devinit snd_sb16_pnp_detect(struct pnp_card_link *pcard, ...@@ -653,7 +656,6 @@ static int __devinit snd_sb16_pnp_detect(struct pnp_card_link *pcard,
} }
pnp_set_card_drvdata(pcard, card); pnp_set_card_drvdata(pcard, card);
dev++; dev++;
sb16_pnp_devices++;
return 0; return 0;
} }
...@@ -695,68 +697,29 @@ static struct pnp_card_driver sb16_pnpc_driver = { ...@@ -695,68 +697,29 @@ static struct pnp_card_driver sb16_pnpc_driver = {
#endif /* CONFIG_PNP */ #endif /* CONFIG_PNP */
static void __init_or_module snd_sb16_unregister_all(void)
{
int i;
#ifdef CONFIG_PNP
if (pnp_registered)
pnp_unregister_card_driver(&sb16_pnpc_driver);
#endif
for (i = 0; i < ARRAY_SIZE(platform_devices); ++i)
platform_device_unregister(platform_devices[i]);
platform_driver_unregister(&snd_sb16_nonpnp_driver);
}
static int __init alsa_card_sb16_init(void) static int __init alsa_card_sb16_init(void)
{ {
int i, err, cards = 0; int err;
if ((err = platform_driver_register(&snd_sb16_nonpnp_driver)) < 0) err = isa_register_driver(&snd_sb16_isa_driver, SNDRV_CARDS);
if (err < 0)
return err; return err;
for (i = 0; i < SNDRV_CARDS; i++) {
struct platform_device *device;
if (! enable[i] || is_isapnp_selected(i))
continue;
device = platform_device_register_simple(SND_SB16_DRIVER,
i, NULL, 0);
if (IS_ERR(device))
continue;
if (!platform_get_drvdata(device)) {
platform_device_unregister(device);
continue;
}
platform_devices[i] = device;
cards++;
}
#ifdef CONFIG_PNP #ifdef CONFIG_PNP
/* PnP cards at last */ /* PnP cards at last */
err = pnp_register_card_driver(&sb16_pnpc_driver); err = pnp_register_card_driver(&sb16_pnpc_driver);
if (!err) { if (!err)
pnp_registered = 1; pnp_registered = 1;
cards += sb16_pnp_devices;
}
#endif
if (!cards) {
#ifdef MODULE
snd_printk(KERN_ERR "Sound Blaster 16 soundcard not found or device busy\n");
#ifdef SNDRV_SBAWE_EMU8000
snd_printk(KERN_ERR "In case, if you have non-AWE card, try snd-sb16 module\n");
#else
snd_printk(KERN_ERR "In case, if you have AWE card, try snd-sbawe module\n");
#endif #endif
#endif
snd_sb16_unregister_all();
return -ENODEV;
}
return 0; return 0;
} }
static void __exit alsa_card_sb16_exit(void) static void __exit alsa_card_sb16_exit(void)
{ {
snd_sb16_unregister_all(); #ifdef CONFIG_PNP
if (pnp_registered)
pnp_unregister_card_driver(&sb16_pnpc_driver);
#endif
isa_unregister_driver(&snd_sb16_isa_driver);
} }
module_init(alsa_card_sb16_init) module_init(alsa_card_sb16_init)
......
...@@ -36,6 +36,13 @@ ...@@ -36,6 +36,13 @@
MODULE_AUTHOR("Uros Bizjak <uros@kss-loka.si>"); MODULE_AUTHOR("Uros Bizjak <uros@kss-loka.si>");
MODULE_DESCRIPTION("ALSA driver for SB16 Creative Signal Processor"); MODULE_DESCRIPTION("ALSA driver for SB16 Creative Signal Processor");
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
#ifndef CONFIG_SND_SB16_CSP_FIRMWARE_IN_KERNEL
MODULE_FIRMWARE("sb16/mulaw_main.csp");
MODULE_FIRMWARE("sb16/alaw_main.csp");
MODULE_FIRMWARE("sb16/ima_adpcm_init.csp");
MODULE_FIRMWARE("sb16/ima_adpcm_playback.csp");
MODULE_FIRMWARE("sb16/ima_adpcm_capture.csp");
#endif
#ifdef SNDRV_LITTLE_ENDIAN #ifdef SNDRV_LITTLE_ENDIAN
#define CSP_HDR_VALUE(a,b,c,d) ((a) | ((b)<<8) | ((c)<<16) | ((d)<<24)) #define CSP_HDR_VALUE(a,b,c,d) ((a) | ((b)<<8) | ((c)<<16) | ((d)<<24))
...@@ -161,13 +168,17 @@ int snd_sb_csp_new(struct snd_sb *chip, int device, struct snd_hwdep ** rhwdep) ...@@ -161,13 +168,17 @@ int snd_sb_csp_new(struct snd_sb *chip, int device, struct snd_hwdep ** rhwdep)
*/ */
static void snd_sb_csp_free(struct snd_hwdep *hwdep) static void snd_sb_csp_free(struct snd_hwdep *hwdep)
{ {
#ifndef CONFIG_SND_SB16_CSP_FIRMWARE_IN_KERNEL
int i; int i;
#endif
struct snd_sb_csp *p = hwdep->private_data; struct snd_sb_csp *p = hwdep->private_data;
if (p) { if (p) {
if (p->running & SNDRV_SB_CSP_ST_RUNNING) if (p->running & SNDRV_SB_CSP_ST_RUNNING)
snd_sb_csp_stop(p); snd_sb_csp_stop(p);
#ifndef CONFIG_SND_SB16_CSP_FIRMWARE_IN_KERNEL
for (i = 0; i < ARRAY_SIZE(p->csp_programs); ++i) for (i = 0; i < ARRAY_SIZE(p->csp_programs); ++i)
release_firmware(p->csp_programs[i]); release_firmware(p->csp_programs[i]);
#endif
kfree(p); kfree(p);
} }
} }
...@@ -690,9 +701,7 @@ static int snd_sb_csp_load_user(struct snd_sb_csp * p, const unsigned char __use ...@@ -690,9 +701,7 @@ static int snd_sb_csp_load_user(struct snd_sb_csp * p, const unsigned char __use
return err; return err;
} }
#define FIRMWARE_IN_THE_KERNEL #ifdef CONFIG_SND_SB16_CSP_FIRMWARE_IN_KERNEL
#ifdef FIRMWARE_IN_THE_KERNEL
#include "sb16_csp_codecs.h" #include "sb16_csp_codecs.h"
static const struct firmware snd_sb_csp_static_programs[] = { static const struct firmware snd_sb_csp_static_programs[] = {
...@@ -714,22 +723,19 @@ static int snd_sb_csp_firmware_load(struct snd_sb_csp *p, int index, int flags) ...@@ -714,22 +723,19 @@ static int snd_sb_csp_firmware_load(struct snd_sb_csp *p, int index, int flags)
"sb16/ima_adpcm_capture.csp", "sb16/ima_adpcm_capture.csp",
}; };
const struct firmware *program; const struct firmware *program;
int err;
BUILD_BUG_ON(ARRAY_SIZE(names) != CSP_PROGRAM_COUNT); BUILD_BUG_ON(ARRAY_SIZE(names) != CSP_PROGRAM_COUNT);
program = p->csp_programs[index]; program = p->csp_programs[index];
if (!program) { if (!program) {
err = request_firmware(&program, names[index], #ifdef CONFIG_SND_SB16_CSP_FIRMWARE_IN_KERNEL
p->chip->card->dev); program = &snd_sb_csp_static_programs[index];
if (err >= 0)
p->csp_programs[index] = program;
else {
#ifdef FIRMWARE_IN_THE_KERNEL
program = &snd_sb_csp_static_programs[index];
#else #else
int err = request_firmware(&program, names[index],
p->chip->card->dev);
if (err < 0)
return err; return err;
#endif #endif
} p->csp_programs[index] = program;
} }
return snd_sb_csp_load(p, program->data, program->size, flags); return snd_sb_csp_load(p, program->data, program->size, flags);
} }
......
...@@ -22,7 +22,7 @@ ...@@ -22,7 +22,7 @@
#include <sound/driver.h> #include <sound/driver.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/err.h> #include <linux/err.h>
#include <linux/platform_device.h> #include <linux/isa.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/ioport.h> #include <linux/ioport.h>
#include <linux/moduleparam.h> #include <linux/moduleparam.h>
...@@ -56,8 +56,6 @@ MODULE_PARM_DESC(irq, "IRQ # for SB8 driver."); ...@@ -56,8 +56,6 @@ MODULE_PARM_DESC(irq, "IRQ # for SB8 driver.");
module_param_array(dma8, int, NULL, 0444); module_param_array(dma8, int, NULL, 0444);
MODULE_PARM_DESC(dma8, "8-bit DMA # for SB8 driver."); MODULE_PARM_DESC(dma8, "8-bit DMA # for SB8 driver.");
static struct platform_device *devices[SNDRV_CARDS];
struct snd_sb8 { struct snd_sb8 {
struct resource *fm_res; /* used to block FM i/o region for legacy cards */ struct resource *fm_res; /* used to block FM i/o region for legacy cards */
struct snd_sb *chip; struct snd_sb *chip;
...@@ -83,9 +81,23 @@ static void snd_sb8_free(struct snd_card *card) ...@@ -83,9 +81,23 @@ static void snd_sb8_free(struct snd_card *card)
release_and_free_resource(acard->fm_res); release_and_free_resource(acard->fm_res);
} }
static int __devinit snd_sb8_probe(struct platform_device *pdev) static int __devinit snd_sb8_match(struct device *pdev, unsigned int dev)
{
if (!enable[dev])
return 0;
if (irq[dev] == SNDRV_AUTO_IRQ) {
snd_printk(KERN_ERR "%s: please specify irq\n", pdev->bus_id);
return 0;
}
if (dma8[dev] == SNDRV_AUTO_DMA) {
snd_printk(KERN_ERR "%s: please specify dma8\n", pdev->bus_id);
return 0;
}
return 1;
}
static int __devinit snd_sb8_probe(struct device *pdev, unsigned int dev)
{ {
int dev = pdev->id;
struct snd_sb *chip; struct snd_sb *chip;
struct snd_card *card; struct snd_card *card;
struct snd_sb8 *acard; struct snd_sb8 *acard;
...@@ -180,12 +192,12 @@ static int __devinit snd_sb8_probe(struct platform_device *pdev) ...@@ -180,12 +192,12 @@ static int __devinit snd_sb8_probe(struct platform_device *pdev)
chip->port, chip->port,
irq[dev], dma8[dev]); irq[dev], dma8[dev]);
snd_card_set_dev(card, &pdev->dev); snd_card_set_dev(card, pdev);
if ((err = snd_card_register(card)) < 0) if ((err = snd_card_register(card)) < 0)
goto _err; goto _err;
platform_set_drvdata(pdev, card); dev_set_drvdata(pdev, card);
return 0; return 0;
_err: _err:
...@@ -193,17 +205,18 @@ static int __devinit snd_sb8_probe(struct platform_device *pdev) ...@@ -193,17 +205,18 @@ static int __devinit snd_sb8_probe(struct platform_device *pdev)
return err; return err;
} }
static int __devexit snd_sb8_remove(struct platform_device *pdev) static int __devexit snd_sb8_remove(struct device *pdev, unsigned int dev)
{ {
snd_card_free(platform_get_drvdata(pdev)); snd_card_free(dev_get_drvdata(pdev));
platform_set_drvdata(pdev, NULL); dev_set_drvdata(pdev, NULL);
return 0; return 0;
} }
#ifdef CONFIG_PM #ifdef CONFIG_PM
static int snd_sb8_suspend(struct platform_device *dev, pm_message_t state) static int snd_sb8_suspend(struct device *dev, unsigned int n,
pm_message_t state)
{ {
struct snd_card *card = platform_get_drvdata(dev); struct snd_card *card = dev_get_drvdata(dev);
struct snd_sb8 *acard = card->private_data; struct snd_sb8 *acard = card->private_data;
struct snd_sb *chip = acard->chip; struct snd_sb *chip = acard->chip;
...@@ -213,9 +226,9 @@ static int snd_sb8_suspend(struct platform_device *dev, pm_message_t state) ...@@ -213,9 +226,9 @@ static int snd_sb8_suspend(struct platform_device *dev, pm_message_t state)
return 0; return 0;
} }
static int snd_sb8_resume(struct platform_device *dev) static int snd_sb8_resume(struct device *dev, unsigned int n)
{ {
struct snd_card *card = platform_get_drvdata(dev); struct snd_card *card = dev_get_drvdata(dev);
struct snd_sb8 *acard = card->private_data; struct snd_sb8 *acard = card->private_data;
struct snd_sb *chip = acard->chip; struct snd_sb *chip = acard->chip;
...@@ -226,9 +239,10 @@ static int snd_sb8_resume(struct platform_device *dev) ...@@ -226,9 +239,10 @@ static int snd_sb8_resume(struct platform_device *dev)
} }
#endif #endif
#define SND_SB8_DRIVER "snd_sb8" #define DEV_NAME "sb8"
static struct platform_driver snd_sb8_driver = { static struct isa_driver snd_sb8_driver = {
.match = snd_sb8_match,
.probe = snd_sb8_probe, .probe = snd_sb8_probe,
.remove = __devexit_p(snd_sb8_remove), .remove = __devexit_p(snd_sb8_remove),
#ifdef CONFIG_PM #ifdef CONFIG_PM
...@@ -236,56 +250,18 @@ static struct platform_driver snd_sb8_driver = { ...@@ -236,56 +250,18 @@ static struct platform_driver snd_sb8_driver = {
.resume = snd_sb8_resume, .resume = snd_sb8_resume,
#endif #endif
.driver = { .driver = {
.name = SND_SB8_DRIVER .name = DEV_NAME
}, },
}; };
static void __init_or_module snd_sb8_unregister_all(void)
{
int i;
for (i = 0; i < ARRAY_SIZE(devices); ++i)
platform_device_unregister(devices[i]);
platform_driver_unregister(&snd_sb8_driver);
}
static int __init alsa_card_sb8_init(void) static int __init alsa_card_sb8_init(void)
{ {
int i, cards, err; return isa_register_driver(&snd_sb8_driver, SNDRV_CARDS);
err = platform_driver_register(&snd_sb8_driver);
if (err < 0)
return err;
cards = 0;
for (i = 0; i < SNDRV_CARDS; i++) {
struct platform_device *device;
if (! enable[i])
continue;
device = platform_device_register_simple(SND_SB8_DRIVER,
i, NULL, 0);
if (IS_ERR(device))
continue;
if (!platform_get_drvdata(device)) {
platform_device_unregister(device);
continue;
}
devices[i] = device;
cards++;
}
if (!cards) {
#ifdef MODULE
snd_printk(KERN_ERR "Sound Blaster soundcard not found or device busy\n");
#endif
snd_sb8_unregister_all();
return -ENODEV;
}
return 0;
} }
static void __exit alsa_card_sb8_exit(void) static void __exit alsa_card_sb8_exit(void)
{ {
snd_sb8_unregister_all(); isa_unregister_driver(&snd_sb8_driver);
} }
module_init(alsa_card_sb8_init) module_init(alsa_card_sb8_init)
......
...@@ -24,7 +24,7 @@ ...@@ -24,7 +24,7 @@
#include <sound/driver.h> #include <sound/driver.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/err.h> #include <linux/err.h>
#include <linux/platform_device.h> #include <linux/isa.h>
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/time.h> #include <linux/time.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
...@@ -64,8 +64,6 @@ MODULE_PARM_DESC(irq, "IRQ # for Sound Galaxy driver."); ...@@ -64,8 +64,6 @@ MODULE_PARM_DESC(irq, "IRQ # for Sound Galaxy driver.");
module_param_array(dma1, int, NULL, 0444); module_param_array(dma1, int, NULL, 0444);
MODULE_PARM_DESC(dma1, "DMA1 # for Sound Galaxy driver."); MODULE_PARM_DESC(dma1, "DMA1 # for Sound Galaxy driver.");
static struct platform_device *devices[SNDRV_CARDS];
#define SGALAXY_AUXC_LEFT 18 #define SGALAXY_AUXC_LEFT 18
#define SGALAXY_AUXC_RIGHT 19 #define SGALAXY_AUXC_RIGHT 19
...@@ -96,7 +94,8 @@ static int snd_sgalaxy_sbdsp_reset(unsigned long port) ...@@ -96,7 +94,8 @@ static int snd_sgalaxy_sbdsp_reset(unsigned long port)
return 0; return 0;
} }
static int __init snd_sgalaxy_sbdsp_command(unsigned long port, unsigned char val) static int __devinit snd_sgalaxy_sbdsp_command(unsigned long port,
unsigned char val)
{ {
int i; int i;
...@@ -114,7 +113,7 @@ static irqreturn_t snd_sgalaxy_dummy_interrupt(int irq, void *dev_id) ...@@ -114,7 +113,7 @@ static irqreturn_t snd_sgalaxy_dummy_interrupt(int irq, void *dev_id)
return IRQ_NONE; return IRQ_NONE;
} }
static int __init snd_sgalaxy_setup_wss(unsigned long port, int irq, int dma) static int __devinit snd_sgalaxy_setup_wss(unsigned long port, int irq, int dma)
{ {
static int interrupt_bits[] = {-1, -1, -1, -1, -1, -1, -1, 0x08, -1, static int interrupt_bits[] = {-1, -1, -1, -1, -1, -1, -1, 0x08, -1,
0x10, 0x18, 0x20, -1, -1, -1, -1}; 0x10, 0x18, 0x20, -1, -1, -1, -1};
...@@ -161,7 +160,7 @@ static int __init snd_sgalaxy_setup_wss(unsigned long port, int irq, int dma) ...@@ -161,7 +160,7 @@ static int __init snd_sgalaxy_setup_wss(unsigned long port, int irq, int dma)
return 0; return 0;
} }
static int __init snd_sgalaxy_detect(int dev, int irq, int dma) static int __devinit snd_sgalaxy_detect(int dev, int irq, int dma)
{ {
#if 0 #if 0
snd_printdd(PFX "switching to WSS mode\n"); snd_printdd(PFX "switching to WSS mode\n");
...@@ -182,7 +181,7 @@ AD1848_DOUBLE("Aux Playback Switch", 0, SGALAXY_AUXC_LEFT, SGALAXY_AUXC_RIGHT, 7 ...@@ -182,7 +181,7 @@ AD1848_DOUBLE("Aux Playback Switch", 0, SGALAXY_AUXC_LEFT, SGALAXY_AUXC_RIGHT, 7
AD1848_DOUBLE("Aux Playback Volume", 0, SGALAXY_AUXC_LEFT, SGALAXY_AUXC_RIGHT, 0, 0, 31, 0) AD1848_DOUBLE("Aux Playback Volume", 0, SGALAXY_AUXC_LEFT, SGALAXY_AUXC_RIGHT, 0, 0, 31, 0)
}; };
static int __init snd_sgalaxy_mixer(struct snd_ad1848 *chip) static int __devinit snd_sgalaxy_mixer(struct snd_ad1848 *chip)
{ {
struct snd_card *card = chip->card; struct snd_card *card = chip->card;
struct snd_ctl_elem_id id1, id2; struct snd_ctl_elem_id id1, id2;
...@@ -218,23 +217,29 @@ static int __init snd_sgalaxy_mixer(struct snd_ad1848 *chip) ...@@ -218,23 +217,29 @@ static int __init snd_sgalaxy_mixer(struct snd_ad1848 *chip)
return 0; return 0;
} }
static int __init snd_sgalaxy_probe(struct platform_device *devptr) static int __devinit snd_sgalaxy_match(struct device *devptr, unsigned int dev)
{ {
int dev = devptr->id; if (!enable[dev])
static int possible_irqs[] = {7, 9, 10, 11, -1}; return 0;
static int possible_dmas[] = {1, 3, 0, -1};
int err, xirq, xdma1;
struct snd_card *card;
struct snd_ad1848 *chip;
if (sbport[dev] == SNDRV_AUTO_PORT) { if (sbport[dev] == SNDRV_AUTO_PORT) {
snd_printk(KERN_ERR PFX "specify SB port\n"); snd_printk(KERN_ERR PFX "specify SB port\n");
return -EINVAL; return 0;
} }
if (wssport[dev] == SNDRV_AUTO_PORT) { if (wssport[dev] == SNDRV_AUTO_PORT) {
snd_printk(KERN_ERR PFX "specify WSS port\n"); snd_printk(KERN_ERR PFX "specify WSS port\n");
return -EINVAL; return 0;
} }
return 1;
}
static int __devinit snd_sgalaxy_probe(struct device *devptr, unsigned int dev)
{
static int possible_irqs[] = {7, 9, 10, 11, -1};
static int possible_dmas[] = {1, 3, 0, -1};
int err, xirq, xdma1;
struct snd_card *card;
struct snd_ad1848 *chip;
card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0); card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0);
if (card == NULL) if (card == NULL)
return -ENOMEM; return -ENOMEM;
...@@ -283,12 +288,12 @@ static int __init snd_sgalaxy_probe(struct platform_device *devptr) ...@@ -283,12 +288,12 @@ static int __init snd_sgalaxy_probe(struct platform_device *devptr)
sprintf(card->longname, "Sound Galaxy at 0x%lx, irq %d, dma %d", sprintf(card->longname, "Sound Galaxy at 0x%lx, irq %d, dma %d",
wssport[dev], xirq, xdma1); wssport[dev], xirq, xdma1);
snd_card_set_dev(card, &devptr->dev); snd_card_set_dev(card, devptr);
if ((err = snd_card_register(card)) < 0) if ((err = snd_card_register(card)) < 0)
goto _err; goto _err;
platform_set_drvdata(devptr, card); dev_set_drvdata(devptr, card);
return 0; return 0;
_err: _err:
...@@ -296,17 +301,18 @@ static int __init snd_sgalaxy_probe(struct platform_device *devptr) ...@@ -296,17 +301,18 @@ static int __init snd_sgalaxy_probe(struct platform_device *devptr)
return err; return err;
} }
static int __devexit snd_sgalaxy_remove(struct platform_device *devptr) static int __devexit snd_sgalaxy_remove(struct device *devptr, unsigned int dev)
{ {
snd_card_free(platform_get_drvdata(devptr)); snd_card_free(dev_get_drvdata(devptr));
platform_set_drvdata(devptr, NULL); dev_set_drvdata(devptr, NULL);
return 0; return 0;
} }
#ifdef CONFIG_PM #ifdef CONFIG_PM
static int snd_sgalaxy_suspend(struct platform_device *pdev, pm_message_t state) static int snd_sgalaxy_suspend(struct device *pdev, unsigned int n,
pm_message_t state)
{ {
struct snd_card *card = platform_get_drvdata(pdev); struct snd_card *card = dev_get_drvdata(pdev);
struct snd_ad1848 *chip = card->private_data; struct snd_ad1848 *chip = card->private_data;
snd_power_change_state(card, SNDRV_CTL_POWER_D3hot); snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
...@@ -314,9 +320,9 @@ static int snd_sgalaxy_suspend(struct platform_device *pdev, pm_message_t state) ...@@ -314,9 +320,9 @@ static int snd_sgalaxy_suspend(struct platform_device *pdev, pm_message_t state)
return 0; return 0;
} }
static int snd_sgalaxy_resume(struct platform_device *pdev) static int snd_sgalaxy_resume(struct device *pdev, unsigned int n)
{ {
struct snd_card *card = platform_get_drvdata(pdev); struct snd_card *card = dev_get_drvdata(pdev);
struct snd_ad1848 *chip = card->private_data; struct snd_ad1848 *chip = card->private_data;
chip->resume(chip); chip->resume(chip);
...@@ -328,9 +334,10 @@ static int snd_sgalaxy_resume(struct platform_device *pdev) ...@@ -328,9 +334,10 @@ static int snd_sgalaxy_resume(struct platform_device *pdev)
} }
#endif #endif
#define SND_SGALAXY_DRIVER "snd_sgalaxy" #define DEV_NAME "sgalaxy"
static struct platform_driver snd_sgalaxy_driver = { static struct isa_driver snd_sgalaxy_driver = {
.match = snd_sgalaxy_match,
.probe = snd_sgalaxy_probe, .probe = snd_sgalaxy_probe,
.remove = __devexit_p(snd_sgalaxy_remove), .remove = __devexit_p(snd_sgalaxy_remove),
#ifdef CONFIG_PM #ifdef CONFIG_PM
...@@ -338,56 +345,18 @@ static struct platform_driver snd_sgalaxy_driver = { ...@@ -338,56 +345,18 @@ static struct platform_driver snd_sgalaxy_driver = {
.resume = snd_sgalaxy_resume, .resume = snd_sgalaxy_resume,
#endif #endif
.driver = { .driver = {
.name = SND_SGALAXY_DRIVER .name = DEV_NAME
}, },
}; };
static void __init_or_module snd_sgalaxy_unregister_all(void)
{
int i;
for (i = 0; i < ARRAY_SIZE(devices); ++i)
platform_device_unregister(devices[i]);
platform_driver_unregister(&snd_sgalaxy_driver);
}
static int __init alsa_card_sgalaxy_init(void) static int __init alsa_card_sgalaxy_init(void)
{ {
int i, cards, err; return isa_register_driver(&snd_sgalaxy_driver, SNDRV_CARDS);
err = platform_driver_register(&snd_sgalaxy_driver);
if (err < 0)
return err;
cards = 0;
for (i = 0; i < SNDRV_CARDS; i++) {
struct platform_device *device;
if (! enable[i])
continue;
device = platform_device_register_simple(SND_SGALAXY_DRIVER,
i, NULL, 0);
if (IS_ERR(device))
continue;
if (!platform_get_drvdata(device)) {
platform_device_unregister(device);
continue;
}
devices[i] = device;
cards++;
}
if (!cards) {
#ifdef MODULE
snd_printk(KERN_ERR "Sound Galaxy soundcard not found or device busy\n");
#endif
snd_sgalaxy_unregister_all();
return -ENODEV;
}
return 0;
} }
static void __exit alsa_card_sgalaxy_exit(void) static void __exit alsa_card_sgalaxy_exit(void)
{ {
snd_sgalaxy_unregister_all(); isa_unregister_driver(&snd_sgalaxy_driver);
} }
module_init(alsa_card_sgalaxy_init) module_init(alsa_card_sgalaxy_init)
......
此差异已折叠。
此差异已折叠。
...@@ -35,9 +35,7 @@ ...@@ -35,9 +35,7 @@
#define WAIT_IDLE 0xff #define WAIT_IDLE 0xff
#define FIRMWARE_IN_THE_KERNEL #ifdef CONFIG_SND_WAVEFRONT_FIRMWARE_IN_KERNEL
#ifdef FIRMWARE_IN_THE_KERNEL
#include "yss225.c" #include "yss225.c"
static const struct firmware yss225_registers_firmware = { static const struct firmware yss225_registers_firmware = {
.data = (u8 *)yss225_registers, .data = (u8 *)yss225_registers,
...@@ -258,21 +256,21 @@ snd_wavefront_fx_start (snd_wavefront_t *dev) ...@@ -258,21 +256,21 @@ snd_wavefront_fx_start (snd_wavefront_t *dev)
{ {
unsigned int i; unsigned int i;
int err; int err;
const struct firmware *firmware; const struct firmware *firmware = NULL;
if (dev->fx_initialized) if (dev->fx_initialized)
return 0; return 0;
#ifdef CONFIG_SND_WAVEFRONT_FIRMWARE_IN_KERNEL
firmware = &yss225_registers_firmware;
#else
err = request_firmware(&firmware, "yamaha/yss225_registers.bin", err = request_firmware(&firmware, "yamaha/yss225_registers.bin",
dev->card->dev); dev->card->dev);
if (err < 0) { if (err < 0) {
#ifdef FIRMWARE_IN_THE_KERNEL
firmware = &yss225_registers_firmware;
#else
err = -1; err = -1;
goto out; goto out;
#endif
} }
#endif
for (i = 0; i + 1 < firmware->size; i += 2) { for (i = 0; i + 1 < firmware->size; i += 2) {
if (firmware->data[i] >= 8 && firmware->data[i] < 16) { if (firmware->data[i] >= 8 && firmware->data[i] < 16) {
...@@ -295,9 +293,12 @@ snd_wavefront_fx_start (snd_wavefront_t *dev) ...@@ -295,9 +293,12 @@ snd_wavefront_fx_start (snd_wavefront_t *dev)
err = 0; err = 0;
out: out:
#ifdef FIRMWARE_IN_THE_KERNEL #ifndef CONFIG_SND_WAVEFRONT_FIRMWARE_IN_KERNEL
if (firmware != &yss225_registers_firmware) release_firmware(firmware);
#endif #endif
release_firmware(firmware);
return err; return err;
} }
#ifndef CONFIG_SND_WAVEFRONT_FIRMWARE_IN_KERNEL
MODULE_FIRMWARE("yamaha/yss225_registers.bin");
#endif
...@@ -576,7 +576,7 @@ config SND_INTEL8X0M ...@@ -576,7 +576,7 @@ config SND_INTEL8X0M
config SND_KORG1212 config SND_KORG1212
tristate "Korg 1212 IO" tristate "Korg 1212 IO"
depends on SND depends on SND
select FW_LOADER select FW_LOADER if !SND_KORG1212_FIRMWARE_IN_KERNEL
select SND_PCM select SND_PCM
help help
Say Y here to include support for Korg 1212IO soundcards. Say Y here to include support for Korg 1212IO soundcards.
...@@ -584,10 +584,19 @@ config SND_KORG1212 ...@@ -584,10 +584,19 @@ config SND_KORG1212
To compile this driver as a module, choose M here: the module To compile this driver as a module, choose M here: the module
will be called snd-korg1212. will be called snd-korg1212.
config SND_KORG1212_FIRMWARE_IN_KERNEL
bool "In-kernel firmware for Korg1212 driver"
depends on SND_KORG1212
default y
help
Say Y here to include the static firmware built in the kernel
for the Korg1212 driver. If you choose N here, you need to
install the firmware files from the alsa-firmware package.
config SND_MAESTRO3 config SND_MAESTRO3
tristate "ESS Allegro/Maestro3" tristate "ESS Allegro/Maestro3"
depends on SND depends on SND
select FW_LOADER select FW_LOADER if !SND_MAESTRO3_FIRMWARE_IN_KERNEL
select SND_AC97_CODEC select SND_AC97_CODEC
help help
Say Y here to include support for soundcards based on ESS Maestro 3 Say Y here to include support for soundcards based on ESS Maestro 3
...@@ -596,6 +605,15 @@ config SND_MAESTRO3 ...@@ -596,6 +605,15 @@ config SND_MAESTRO3
To compile this driver as a module, choose M here: the module To compile this driver as a module, choose M here: the module
will be called snd-maestro3. will be called snd-maestro3.
config SND_MAESTRO3_FIRMWARE_IN_KERNEL
bool "In-kernel firmware for Maestro3 driver"
depends on SND_MAESTRO3
default y
help
Say Y here to include the static firmware built in the kernel
for the Maestro3 driver. If you choose N here, you need to
install the firmware files from the alsa-firmware package.
config SND_MIXART config SND_MIXART
tristate "Digigram miXart" tristate "Digigram miXart"
depends on SND depends on SND
...@@ -737,7 +755,7 @@ config SND_VX222 ...@@ -737,7 +755,7 @@ config SND_VX222
config SND_YMFPCI config SND_YMFPCI
tristate "Yamaha YMF724/740/744/754" tristate "Yamaha YMF724/740/744/754"
depends on SND depends on SND
select FW_LOADER select FW_LOADER if !SND_YMFPCI_FIRMWARE_IN_KERNEL
select SND_OPL3_LIB select SND_OPL3_LIB
select SND_MPU401_UART select SND_MPU401_UART
select SND_AC97_CODEC select SND_AC97_CODEC
...@@ -748,6 +766,15 @@ config SND_YMFPCI ...@@ -748,6 +766,15 @@ config SND_YMFPCI
To compile this driver as a module, choose M here: the module To compile this driver as a module, choose M here: the module
will be called snd-ymfpci. will be called snd-ymfpci.
config SND_YMFPCI_FIRMWARE_IN_KERNEL
bool "In-kernel firmware for YMFPCI driver"
depends on SND_YMFPCI
default y
help
Say Y here to include the static firmware built in the kernel
for the YMFPCI driver. If you choose N here, you need to
install the firmware files from the alsa-firmware package.
config SND_AC97_POWER_SAVE config SND_AC97_POWER_SAVE
bool "AC97 Power-Saving Mode" bool "AC97 Power-Saving Mode"
depends on SND_AC97_CODEC && EXPERIMENTAL depends on SND_AC97_CODEC && EXPERIMENTAL
......
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
...@@ -34,7 +34,6 @@ ...@@ -34,7 +34,6 @@
#include <sound/control.h> #include <sound/control.h>
#include <sound/ac97_codec.h> #include <sound/ac97_codec.h>
#include <sound/asoundef.h> #include <sound/asoundef.h>
#include "ac97_patch.h"
#include "ac97_id.h" #include "ac97_id.h"
#include "ac97_local.h" #include "ac97_local.h"
......
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册