#include <linux/init.h>
#include <linux/module.h>
#include <linux/delay.h>
-#include <linux/pm.h>
#include "sound_config.h"
#include "ad1848.h"
/* PnP Stuff */
struct pnp_dev* pdev;
int activated; /* Whether said devices have been activated */
-#endif
-#ifdef CONFIG_PM
- unsigned int in_suspend;
- struct pm_dev *pmdev;
#endif
unsigned int card;
int chipset; /* What's my version(s)? */
static int __initdata isapnp = 1;
static int __initdata multiple = 1;
-/* PnP devices */
-struct pnp_dev* opl3sa2_dev[OPL3SA2_CARDS_MAX];
-
/* Whether said devices have been activated */
static int opl3sa2_activated[OPL3SA2_CARDS_MAX];
#else
MODULE_LICENSE("GPL");
-MODULE_PARM(io, "i");
+module_param(io, int, 0);
MODULE_PARM_DESC(io, "Set I/O base of OPL3-SA2 or SA3 card (usually 0x370. Address must be even and must be from 0x100 to 0xFFE)");
-MODULE_PARM(mss_io, "i");
+module_param(mss_io, int, 0);
MODULE_PARM_DESC(mss_io, "Set MSS (audio) I/O base (0x530, 0xE80, or other. Address must end in 0 or 4 and must be from 0x530 to 0xF48)");
-MODULE_PARM(mpu_io, "i");
+module_param(mpu_io, int, 0);
MODULE_PARM_DESC(mpu_io, "Set MIDI I/O base (0x330 or other. Address must be even and must be from 0x300 to 0x334)");
-MODULE_PARM(irq, "i");
-MODULE_PARM_DESC(mss_irq, "Set MSS (audio) IRQ (5, 7, 9, 10, 11, 12)");
+module_param(irq, int, 0);
+MODULE_PARM_DESC(irq, "Set MSS (audio) IRQ (5, 7, 9, 10, 11, 12)");
-MODULE_PARM(dma, "i");
+module_param(dma, int, 0);
MODULE_PARM_DESC(dma, "Set MSS (audio) first DMA channel (0, 1, 3)");
-MODULE_PARM(dma2, "i");
+module_param(dma2, int, 0);
MODULE_PARM_DESC(dma2, "Set MSS (audio) second DMA channel (0, 1, 3)");
-MODULE_PARM(ymode, "i");
+module_param(ymode, int, 0);
MODULE_PARM_DESC(ymode, "Set Yamaha 3D enhancement mode (0 = Desktop/Normal, 1 = Notebook PC (1), 2 = Notebook PC (2), 3 = Hi-Fi)");
-MODULE_PARM(loopback, "i");
+module_param(loopback, int, 0);
MODULE_PARM_DESC(loopback, "Set A/D input source. Useful for echo cancellation (0 = Mic Rch (default), 1 = Mono output loopback)");
#ifdef CONFIG_PNP
-MODULE_PARM(isapnp, "i");
+module_param(isapnp, bool, 0);
MODULE_PARM_DESC(isapnp, "When set to 0, ISA PnP support will be disabled");
-MODULE_PARM(multiple, "i");
+module_param(multiple, bool, 0);
MODULE_PARM_DESC(multiple, "When set to 0, will not search for multiple cards");
#endif
}
}
-/* Currently only used for power management */
-#ifdef CONFIG_PM
-static void opl3sa2_mixer_restore(opl3sa2_state_t* devc)
-{
- if (devc) {
- opl3sa2_set_volume(devc, devc->volume_l, devc->volume_r);
- opl3sa2_set_mic(devc, devc->mic);
-
- if (devc->chipset == CHIPSET_OPL3SA3) {
- opl3sa3_set_bass(devc, devc->bass_l, devc->bass_r);
- opl3sa3_set_treble(devc, devc->treble_l, devc->treble_r);
- }
- }
-}
-#endif
-
static inline void arg_to_vol_mono(unsigned int vol, int* value)
{
int left;
}
-static int opl3sa2_mixer_ioctl(int dev, unsigned int cmd, caddr_t arg)
+static int opl3sa2_mixer_ioctl(int dev, unsigned int cmd, void __user *arg)
{
int retval, value, cmdf = cmd & 0xff;
+ int __user *p = (int __user *)arg;
opl3sa2_state_t* devc = &opl3sa2_state[dev];
if (_SIOC_DIR (cmd) & _SIOC_WRITE) {
switch (cmdf) {
case SOUND_MIXER_VOLUME:
- retval = get_user(value, (unsigned int *) arg);
+ retval = get_user(value, (unsigned __user *) arg);
if (retval)
break;
arg_to_vol_stereo(value, &devc->volume_l, &devc->volume_r);
opl3sa2_set_volume(devc, devc->volume_l, devc->volume_r);
value = ret_vol_stereo(devc->volume_l, devc->volume_r);
- retval = put_user(value, (int *) arg);
+ retval = put_user(value, p);
break;
case SOUND_MIXER_MIC:
- retval = get_user(value, (unsigned int *) arg);
+ retval = get_user(value, (unsigned __user *) arg);
if (retval)
break;
arg_to_vol_mono(value, &devc->mic);
opl3sa2_set_mic(devc, devc->mic);
value = ret_vol_mono(devc->mic);
- retval = put_user(value, (int *) arg);
+ retval = put_user(value, p);
break;
default:
*/
switch (cmdf) {
case SOUND_MIXER_DEVMASK:
- retval = put_user(SOUND_MASK_VOLUME | SOUND_MASK_MIC, (int *) arg);
+ retval = put_user(SOUND_MASK_VOLUME | SOUND_MASK_MIC, p);
break;
case SOUND_MIXER_STEREODEVS:
- retval = put_user(SOUND_MASK_VOLUME, (int *) arg);
+ retval = put_user(SOUND_MASK_VOLUME, p);
break;
case SOUND_MIXER_RECMASK:
/* No recording devices */
- retval = put_user(0, (int *) arg);
+ retval = put_user(0, p);
break;
case SOUND_MIXER_CAPS:
- retval = put_user(SOUND_CAP_EXCL_INPUT, (int *) arg);
+ retval = put_user(SOUND_CAP_EXCL_INPUT, p);
break;
case SOUND_MIXER_RECSRC:
/* No recording source */
- retval = put_user(0, (int *) arg);
+ retval = put_user(0, p);
break;
case SOUND_MIXER_VOLUME:
value = ret_vol_stereo(devc->volume_l, devc->volume_r);
- retval = put_user(value, (int *) arg);
+ retval = put_user(value, p);
break;
case SOUND_MIXER_MIC:
value = ret_vol_mono(devc->mic);
- put_user(value, (int *) arg);
+ put_user(value, p);
break;
default:
/* opl3sa2_mixer_ioctl end */
-static int opl3sa3_mixer_ioctl(int dev, unsigned int cmd, caddr_t arg)
+static int opl3sa3_mixer_ioctl(int dev, unsigned int cmd, void __user * arg)
{
int value, retval, cmdf = cmd & 0xff;
switch (cmdf) {
case SOUND_MIXER_BASS:
value = ret_vol_stereo(devc->bass_l, devc->bass_r);
- retval = put_user(value, (int *) arg);
+ retval = put_user(value, (int __user *) arg);
break;
case SOUND_MIXER_TREBLE:
value = ret_vol_stereo(devc->treble_l, devc->treble_r);
- retval = put_user(value, (int *) arg);
+ retval = put_user(value, (int __user *) arg);
break;
case SOUND_MIXER_DIGITAL1:
value = ret_vol_stereo(devc->wide_l, devc->wide_r);
- retval = put_user(value, (int *) arg);
+ retval = put_user(value, (int __user *) arg);
break;
default:
* Component probe, attach, unload functions
*/
-static inline int __init probe_opl3sa2_mpu(struct address_info* hw_config)
-{
- return probe_mpu401(hw_config);
-}
-
-
-static inline int __init attach_opl3sa2_mpu(struct address_info* hw_config)
-{
- return attach_mpu401(hw_config, THIS_MODULE);
-}
-
-
static inline void __exit unload_opl3sa2_mpu(struct address_info *hw_config)
{
unload_mpu401(hw_config);
}
-static inline int __init probe_opl3sa2_mss(struct address_info* hw_config)
-{
- return probe_ms_sound(hw_config);
-}
-
-
-static void __init attach_opl3sa2_mss(struct address_info* hw_config)
+static void __init attach_opl3sa2_mss(struct address_info* hw_config, struct resource *ports)
{
int initial_mixers;
initial_mixers = num_mixers;
- attach_ms_sound(hw_config, THIS_MODULE); /* Slot 0 */
+ attach_ms_sound(hw_config, ports, THIS_MODULE); /* Slot 0 */
if (hw_config->slots[0] != -1) {
/* Did the MSS driver install? */
if(num_mixers == (initial_mixers + 1)) {
- /* The MSS mixer is installed, reroute mixers appropiately */
+ /* The MSS mixer is installed, reroute mixers appropriately */
AD1848_REROUTE(SOUND_MIXER_LINE1, SOUND_MIXER_CD);
AD1848_REROUTE(SOUND_MIXER_LINE2, SOUND_MIXER_SYNTH);
AD1848_REROUTE(SOUND_MIXER_LINE3, SOUND_MIXER_LINE);
}
-static void __init opl3sa2_clear_slots(struct address_info* hw_config)
+static void opl3sa2_clear_slots(struct address_info* hw_config)
{
int i;
}
#ifdef CONFIG_PNP
-struct pnp_device_id pnp_opl3sa2_list[] = {
+static struct pnp_device_id pnp_opl3sa2_list[] = {
{.id = "YMH0021", .driver_data = 0},
{.id = ""}
};
/* End of component functions */
-#ifdef CONFIG_PM
-static spinlock_t opl3sa2_lock = SPIN_LOCK_UNLOCKED;
-
-/* Power Management support functions */
-static int opl3sa2_suspend(struct pm_dev *pdev, unsigned int pm_mode)
-{
- unsigned long flags;
- opl3sa2_state_t *p;
-
- if (!pdev)
- return -EINVAL;
-
- spin_lock_irqsave(&opl3sa2_lock,flags);
-
- p = (opl3sa2_state_t *) pdev->data;
- switch (pm_mode) {
- case 1:
- pm_mode = OPL3SA2_PM_MODE1;
- break;
- case 2:
- pm_mode = OPL3SA2_PM_MODE2;
- break;
- case 3:
- pm_mode = OPL3SA2_PM_MODE3;
- break;
- default:
- /* we don't know howto handle this... */
- spin_unlock_irqrestore(&opl3sa2_lock, flags);
- return -EBUSY;
- }
-
- p->in_suspend = 1;
-
- /* its supposed to automute before suspending, so we won't bother */
- opl3sa2_write(p->cfg_port, OPL3SA2_PM, pm_mode);
- /* wait a while for the clock oscillator to stabilise */
- mdelay(10);
-
- spin_unlock_irqrestore(&opl3sa2_lock,flags);
- return 0;
-}
-
-static int opl3sa2_resume(struct pm_dev *pdev)
-{
- unsigned long flags;
- opl3sa2_state_t *p;
-
- if (!pdev)
- return -EINVAL;
-
- p = (opl3sa2_state_t *) pdev->data;
- spin_lock_irqsave(&opl3sa2_lock,flags);
-
- /* I don't think this is necessary */
- opl3sa2_write(p->cfg_port, OPL3SA2_PM, OPL3SA2_PM_MODE0);
- opl3sa2_mixer_restore(p);
- p->in_suspend = 0;
-
- spin_unlock_irqrestore(&opl3sa2_lock,flags);
- return 0;
-}
-
-static int opl3sa2_pm_callback(struct pm_dev *pdev, pm_request_t rqst, void *data)
-{
- unsigned long mode = (unsigned long)data;
-
- switch (rqst) {
- case PM_SUSPEND:
- return opl3sa2_suspend(pdev, mode);
-
- case PM_RESUME:
- return opl3sa2_resume(pdev);
- }
- return 0;
-}
-#endif /* CONFIG_PM */
-
/*
* Install OPL3-SA2 based card(s).
*
for (card = 0; card < max; card++) {
/* If a user wants an I/O then assume they meant it */
+ struct resource *ports;
+ int base;
if (!isapnp) {
if (io == -1 || irq == -1 || dma == -1 ||
opl3sa2_clear_slots(&opl3sa2_state[card].cfg_mpu);
}
+ /* FIXME: leak */
if (probe_opl3sa2(&opl3sa2_state[card].cfg, card))
return -ENODEV;
+ base = opl3sa2_state[card].cfg_mss.io_base;
+
+ if (!request_region(base, 4, "WSS config"))
+ goto failed;
- if (!probe_opl3sa2_mss(&opl3sa2_state[card].cfg_mss)) {
+ ports = request_region(base + 4, 4, "ad1848");
+ if (!ports)
+ goto failed2;
+
+ if (!probe_ms_sound(&opl3sa2_state[card].cfg_mss, ports)) {
/*
* If one or more cards are already registered, don't
* return an error but print a warning. Note, this
* should never really happen unless the hardware or
* ISA PnP screwed up.
*/
+ release_region(base + 4, 4);
+ failed2:
+ release_region(base, 4);
+ failed:
release_region(opl3sa2_state[card].cfg.io_base, 2);
if (opl3sa2_cards_num) {
attach_opl3sa2(&opl3sa2_state[card].cfg, card);
conf_printf(opl3sa2_state[card].chipset_name, &opl3sa2_state[card].cfg);
attach_opl3sa2_mixer(&opl3sa2_state[card].cfg, card);
- attach_opl3sa2_mss(&opl3sa2_state[card].cfg_mss);
+ attach_opl3sa2_mss(&opl3sa2_state[card].cfg_mss, ports);
/* ewww =) */
opl3sa2_state[card].card = card;
-#ifdef CONFIG_PM
- /* register our power management capabilities */
- opl3sa2_state[card].pmdev = pm_register(PM_ISA_DEV, card, opl3sa2_pm_callback);
- if (opl3sa2_state[card].pmdev)
- opl3sa2_state[card].pmdev->data = &opl3sa2_state[card];
-#endif /* CONFIG_PM */
/*
* Set the Yamaha 3D enhancement mode (aka Ymersion) if asked to and
/* Attach MPU if we've been asked to do so, failure isn't fatal */
if (opl3sa2_state[card].cfg_mpu.io_base != -1) {
- if (probe_opl3sa2_mpu(&opl3sa2_state[card].cfg_mpu)) {
- if (attach_opl3sa2_mpu(&opl3sa2_state[card].cfg_mpu)) {
- printk(KERN_ERR PFX "failed to attach MPU401\n");
- opl3sa2_state[card].cfg_mpu.slots[1] = -1;
- }
+ int base = opl3sa2_state[card].cfg_mpu.io_base;
+ struct resource *ports;
+ ports = request_region(base, 2, "mpu401");
+ if (!ports)
+ goto out;
+ if (!probe_mpu401(&opl3sa2_state[card].cfg_mpu, ports)) {
+ release_region(base, 2);
+ goto out;
+ }
+ if (attach_mpu401(&opl3sa2_state[card].cfg_mpu, THIS_MODULE)) {
+ printk(KERN_ERR PFX "failed to attach MPU401\n");
+ opl3sa2_state[card].cfg_mpu.slots[1] = -1;
}
}
}
+out:
if (isapnp) {
printk(KERN_NOTICE PFX "%d PnP card(s) found.\n", opl3sa2_cards_num);
}
int card;
for(card = 0; card < opl3sa2_cards_num; card++) {
-#ifdef CONFIG_PM
- if (opl3sa2_state[card].pmdev)
- pm_unregister(opl3sa2_state[card].pmdev);
-#endif
if (opl3sa2_state[card].cfg_mpu.slots[1] != -1) {
unload_opl3sa2_mpu(&opl3sa2_state[card].cfg_mpu);
}