diff options
Diffstat (limited to 'sound/isa/opti9xx')
| -rw-r--r-- | sound/isa/opti9xx/miro.c | 106 | ||||
| -rw-r--r-- | sound/isa/opti9xx/opti92x-ad1848.c | 386 |
2 files changed, 320 insertions, 172 deletions
diff --git a/sound/isa/opti9xx/miro.c b/sound/isa/opti9xx/miro.c index b865e45a8f9..c2ca681ac51 100644 --- a/sound/isa/opti9xx/miro.c +++ b/sound/isa/opti9xx/miro.c @@ -27,9 +27,8 @@ #include <linux/isa.h> #include <linux/pnp.h> #include <linux/delay.h> -#include <linux/slab.h> #include <linux/ioport.h> -#include <linux/moduleparam.h> +#include <linux/module.h> #include <asm/io.h> #include <asm/dma.h> #include <sound/core.h> @@ -38,6 +37,7 @@ #include <sound/opl4.h> #include <sound/control.h> #include <sound/info.h> +#define SNDRV_LEGACY_FIND_FREE_IOPORT #define SNDRV_LEGACY_FIND_FREE_IRQ #define SNDRV_LEGACY_FIND_FREE_DMA #include <sound/initval.h> @@ -62,7 +62,7 @@ static int dma2 = SNDRV_DEFAULT_DMA1; /* 0,1,3 */ static int wss; static int ide; #ifdef CONFIG_PNP -static int isapnp = 1; /* Enable ISA PnP detection */ +static bool isapnp = 1; /* Enable ISA PnP detection */ #endif module_param(index, int, 0444); @@ -587,7 +587,7 @@ static int snd_miro_put_double(struct snd_kcontrol *kcontrol, return change; } -static struct snd_kcontrol_new snd_miro_controls[] __devinitdata = { +static struct snd_kcontrol_new snd_miro_controls[] = { 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("Line Playback Volume", 1, ACI_GET_LINE, ACI_SET_LINE), @@ -599,7 +599,7 @@ MIRO_DOUBLE("Aux Playback Volume", 2, ACI_GET_LINE2, ACI_SET_LINE2), /* Equalizer with seven bands (only PCM20) from -12dB up to +12dB on each band */ -static struct snd_kcontrol_new snd_miro_eq_controls[] __devinitdata = { +static struct snd_kcontrol_new snd_miro_eq_controls[] = { 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 - 400 Hz", 0, ACI_GET_EQ3, ACI_SET_EQ3), @@ -609,15 +609,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), }; -static struct snd_kcontrol_new snd_miro_radio_control[] __devinitdata = { +static struct snd_kcontrol_new snd_miro_radio_control[] = { MIRO_DOUBLE("Radio Playback Volume", 0, ACI_GET_LINE1, ACI_SET_LINE1), }; -static struct snd_kcontrol_new snd_miro_line_control[] __devinitdata = { +static struct snd_kcontrol_new snd_miro_line_control[] = { MIRO_DOUBLE("Line Playback Volume", 2, ACI_GET_LINE1, ACI_SET_LINE1), }; -static struct snd_kcontrol_new snd_miro_preamp_control[] __devinitdata = { +static struct snd_kcontrol_new snd_miro_preamp_control[] = { { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = "Mic Boost", @@ -627,7 +627,7 @@ static struct snd_kcontrol_new snd_miro_preamp_control[] __devinitdata = { .put = snd_miro_put_preamp, }}; -static struct snd_kcontrol_new snd_miro_amp_control[] __devinitdata = { +static struct snd_kcontrol_new snd_miro_amp_control[] = { { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = "Line Boost", @@ -637,7 +637,7 @@ static struct snd_kcontrol_new snd_miro_amp_control[] __devinitdata = { .put = snd_miro_put_amp, }}; -static struct snd_kcontrol_new snd_miro_capture_control[] __devinitdata = { +static struct snd_kcontrol_new snd_miro_capture_control[] = { { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = "PCM Capture Switch", @@ -647,7 +647,7 @@ static struct snd_kcontrol_new snd_miro_capture_control[] __devinitdata = { .put = snd_miro_put_capture, }}; -static unsigned char aci_init_values[][2] __devinitdata = { +static unsigned char aci_init_values[][2] = { { ACI_SET_MUTE, 0x00 }, { ACI_SET_POWERAMP, 0x00 }, { ACI_SET_PREAMP, 0x00 }, @@ -670,7 +670,7 @@ static unsigned char aci_init_values[][2] __devinitdata = { { ACI_SET_MASTER + 1, 0x20 }, }; -static int __devinit snd_set_aci_init_values(struct snd_miro *miro) +static int snd_set_aci_init_values(struct snd_miro *miro) { int idx, error; struct snd_miro_aci *aci = miro->aci; @@ -713,8 +713,8 @@ static int __devinit snd_set_aci_init_values(struct snd_miro *miro) return 0; } -static int __devinit snd_miro_mixer(struct snd_card *card, - struct snd_miro *miro) +static int snd_miro_mixer(struct snd_card *card, + struct snd_miro *miro) { unsigned int idx; int err; @@ -771,22 +771,8 @@ static int __devinit snd_miro_mixer(struct snd_card *card, return 0; } -static long snd_legacy_find_free_ioport(long *port_table, long size) -{ - while (*port_table != -1) { - struct resource *res; - if ((res = request_region(*port_table, size, - "ALSA test")) != NULL) { - release_and_free_resource(res); - return *port_table; - } - port_table++; - } - return -1; -} - -static int __devinit snd_miro_init(struct snd_miro *chip, - unsigned short hardware) +static int snd_miro_init(struct snd_miro *chip, + unsigned short hardware) { static int opti9xx_mc_size[] = {7, 7, 10, 10, 2, 2, 2}; @@ -1003,8 +989,8 @@ static void snd_miro_proc_read(struct snd_info_entry * entry, snd_iprintf(buffer, " preamp : 0x%x\n", aci->aci_preamp); } -static void __devinit snd_miro_proc_init(struct snd_card *card, - struct snd_miro *miro) +static void snd_miro_proc_init(struct snd_card *card, + struct snd_miro *miro) { struct snd_info_entry *entry; @@ -1016,7 +1002,7 @@ static void __devinit snd_miro_proc_init(struct snd_card *card, * Init */ -static int __devinit snd_miro_configure(struct snd_miro *chip) +static int snd_miro_configure(struct snd_miro *chip) { unsigned char wss_base_bits; unsigned char irq_bits; @@ -1176,7 +1162,7 @@ __skip_mpu: return 0; } -static int __devinit snd_miro_opti_check(struct snd_miro *chip) +static int snd_miro_opti_check(struct snd_miro *chip) { unsigned char value; @@ -1196,8 +1182,8 @@ static int __devinit snd_miro_opti_check(struct snd_miro *chip) return -ENODEV; } -static int __devinit snd_card_miro_detect(struct snd_card *card, - struct snd_miro *chip) +static int snd_card_miro_detect(struct snd_card *card, + struct snd_miro *chip) { int i, err; @@ -1214,8 +1200,8 @@ static int __devinit snd_card_miro_detect(struct snd_card *card, return -ENODEV; } -static int __devinit snd_card_miro_aci_detect(struct snd_card *card, - struct snd_miro *miro) +static int snd_card_miro_aci_detect(struct snd_card *card, + struct snd_miro *miro) { unsigned char regval; int i; @@ -1279,7 +1265,7 @@ static void snd_card_miro_free(struct snd_card *card) release_and_free_resource(miro->res_mc_base); } -static int __devinit snd_miro_probe(struct snd_card *card) +static int snd_miro_probe(struct snd_card *card) { int error; struct snd_miro *miro = card->private_data; @@ -1300,7 +1286,6 @@ static int __devinit snd_miro_probe(struct snd_card *card) error = snd_card_miro_aci_detect(card, miro); if (error < 0) { - snd_card_free(card); snd_printk(KERN_ERR "unable to detect aci chip\n"); return -ENODEV; } @@ -1378,8 +1363,7 @@ static int __devinit snd_miro_probe(struct snd_card *card) rmidi = NULL; else { error = snd_mpu401_uart_new(card, 0, MPU401_HW_MPU401, - mpu_port, 0, miro->mpu_irq, IRQF_DISABLED, - &rmidi); + mpu_port, 0, miro->mpu_irq, &rmidi); if (error < 0) snd_printk(KERN_WARNING "no MPU-401 device at 0x%lx?\n", mpu_port); @@ -1402,7 +1386,7 @@ static int __devinit snd_miro_probe(struct snd_card *card) return snd_card_register(card); } -static int __devinit snd_miro_isa_match(struct device *devptr, unsigned int n) +static int snd_miro_isa_match(struct device *devptr, unsigned int n) { #ifdef CONFIG_PNP if (snd_miro_pnp_is_probed) @@ -1413,7 +1397,7 @@ static int __devinit snd_miro_isa_match(struct device *devptr, unsigned int n) return 1; } -static int __devinit snd_miro_isa_probe(struct device *devptr, unsigned int n) +static int snd_miro_isa_probe(struct device *devptr, unsigned int n) { static long possible_ports[] = {0x530, 0xe80, 0xf40, 0x604, -1}; static long possible_mpu_ports[] = {0x330, 0x300, 0x310, 0x320, -1}; @@ -1427,8 +1411,8 @@ static int __devinit snd_miro_isa_probe(struct device *devptr, unsigned int n) struct snd_miro *miro; struct snd_card *card; - error = snd_card_create(index, id, THIS_MODULE, - sizeof(struct snd_miro), &card); + error = snd_card_new(devptr, index, id, THIS_MODULE, + sizeof(struct snd_miro), &card); if (error < 0) return error; @@ -1495,8 +1479,6 @@ static int __devinit snd_miro_isa_probe(struct device *devptr, unsigned int n) } } - snd_card_set_dev(card, devptr); - error = snd_miro_probe(card); if (error < 0) { snd_card_free(card); @@ -1507,11 +1489,10 @@ static int __devinit snd_miro_isa_probe(struct device *devptr, unsigned int n) return 0; } -static int __devexit snd_miro_isa_remove(struct device *devptr, - unsigned int dev) +static int snd_miro_isa_remove(struct device *devptr, + unsigned int dev) { snd_card_free(dev_get_drvdata(devptr)); - dev_set_drvdata(devptr, NULL); return 0; } @@ -1520,7 +1501,7 @@ static int __devexit snd_miro_isa_remove(struct device *devptr, static struct isa_driver snd_miro_driver = { .match = snd_miro_isa_match, .probe = snd_miro_isa_probe, - .remove = __devexit_p(snd_miro_isa_remove), + .remove = snd_miro_isa_remove, /* FIXME: suspend/resume */ .driver = { .name = DEV_NAME @@ -1529,9 +1510,9 @@ static struct isa_driver snd_miro_driver = { #ifdef CONFIG_PNP -static int __devinit snd_card_miro_pnp(struct snd_miro *chip, - struct pnp_card_link *card, - const struct pnp_card_device_id *pid) +static int snd_card_miro_pnp(struct snd_miro *chip, + struct pnp_card_link *card, + const struct pnp_card_device_id *pid) { struct pnp_dev *pdev; int err; @@ -1558,7 +1539,7 @@ static int __devinit snd_card_miro_pnp(struct snd_miro *chip, err = pnp_activate_dev(devmc); if (err < 0) { - snd_printk(KERN_ERR "OPL syntg pnp configure failure: %d\n", + snd_printk(KERN_ERR "MC pnp configure failure: %d\n", err); return err; } @@ -1590,8 +1571,8 @@ static int __devinit snd_card_miro_pnp(struct snd_miro *chip, return 0; } -static int __devinit snd_miro_pnp_probe(struct pnp_card_link *pcard, - const struct pnp_card_device_id *pid) +static int snd_miro_pnp_probe(struct pnp_card_link *pcard, + const struct pnp_card_device_id *pid) { struct snd_card *card; int err; @@ -1601,8 +1582,8 @@ static int __devinit snd_miro_pnp_probe(struct pnp_card_link *pcard, return -EBUSY; if (!isapnp) return -ENODEV; - err = snd_card_create(index, id, THIS_MODULE, - sizeof(struct snd_miro), &card); + err = snd_card_new(&pcard->card->dev, index, id, THIS_MODULE, + sizeof(struct snd_miro), &card); if (err < 0) return err; @@ -1629,7 +1610,6 @@ static int __devinit snd_miro_pnp_probe(struct pnp_card_link *pcard, return err; } - snd_card_set_dev(card, &pcard->card->dev); err = snd_miro_probe(card); if (err < 0) { snd_card_free(card); @@ -1640,7 +1620,7 @@ static int __devinit snd_miro_pnp_probe(struct pnp_card_link *pcard, return 0; } -static void __devexit snd_miro_pnp_remove(struct pnp_card_link * pcard) +static void snd_miro_pnp_remove(struct pnp_card_link *pcard) { snd_card_free(pnp_get_card_drvdata(pcard)); pnp_set_card_drvdata(pcard, NULL); @@ -1652,7 +1632,7 @@ static struct pnp_card_driver miro_pnpc_driver = { .name = "miro", .id_table = snd_miro_pnpids, .probe = snd_miro_pnp_probe, - .remove = __devexit_p(snd_miro_pnp_remove), + .remove = snd_miro_pnp_remove, }; #endif diff --git a/sound/isa/opti9xx/opti92x-ad1848.c b/sound/isa/opti9xx/opti92x-ad1848.c index c8a8da0d403..c9b58284860 100644 --- a/sound/isa/opti9xx/opti92x-ad1848.c +++ b/sound/isa/opti9xx/opti92x-ad1848.c @@ -27,18 +27,19 @@ #include <linux/err.h> #include <linux/isa.h> #include <linux/delay.h> -#include <linux/slab.h> #include <linux/pnp.h> -#include <linux/moduleparam.h> +#include <linux/module.h> #include <asm/io.h> #include <asm/dma.h> #include <sound/core.h> +#include <sound/tlv.h> #include <sound/wss.h> #include <sound/mpu401.h> #include <sound/opl3.h> #ifndef OPTi93X #include <sound/opl4.h> #endif +#define SNDRV_LEGACY_FIND_FREE_IOPORT #define SNDRV_LEGACY_FIND_FREE_IRQ #define SNDRV_LEGACY_FIND_FREE_DMA #include <sound/initval.h> @@ -63,9 +64,9 @@ MODULE_SUPPORTED_DEVICE("{{OPTi,82C924 (AD1848)}," static int index = SNDRV_DEFAULT_IDX1; /* Index 0-MAX */ static char *id = SNDRV_DEFAULT_STR1; /* ID for this card */ -//static int enable = SNDRV_DEFAULT_ENABLE1; /* Enable this card */ +//static bool enable = SNDRV_DEFAULT_ENABLE1; /* Enable this card */ #ifdef CONFIG_PNP -static int isapnp = 1; /* Enable ISA PnP detection */ +static bool isapnp = true; /* Enable ISA PnP detection */ #endif static long port = SNDRV_DEFAULT_PORT1; /* 0x530,0xe80,0xf40,0x604 */ static long mpu_port = SNDRV_DEFAULT_PORT1; /* 0x300,0x310,0x320,0x330 */ @@ -135,20 +136,15 @@ struct snd_opti9xx { unsigned long mc_base_size; #ifdef OPTi93X unsigned long mc_indir_index; - unsigned long mc_indir_size; struct resource *res_mc_indir; - struct snd_wss *codec; #endif /* OPTi93X */ + struct snd_wss *codec; unsigned long pwd_reg; spinlock_t lock; + long wss_base; int irq; - -#ifdef CONFIG_PNP - struct pnp_dev *dev; - struct pnp_dev *devmpu; -#endif /* CONFIG_PNP */ }; static int snd_opti9xx_pnp_is_probed; @@ -158,12 +154,17 @@ static int snd_opti9xx_pnp_is_probed; static struct pnp_card_device_id snd_opti9xx_pnpids[] = { #ifndef OPTi93X /* OPTi 82C924 */ - { .id = "OPT0924", .devs = { { "OPT0000" }, { "OPT0002" } }, .driver_data = 0x0924 }, + { .id = "OPT0924", + .devs = { { "OPT0000" }, { "OPT0002" }, { "OPT0005" } }, + .driver_data = 0x0924 }, /* OPTi 82C925 */ - { .id = "OPT0925", .devs = { { "OPT9250" }, { "OPT0002" } }, .driver_data = 0x0925 }, + { .id = "OPT0925", + .devs = { { "OPT9250" }, { "OPT0002" }, { "OPT0005" } }, + .driver_data = 0x0925 }, #else /* OPTi 82C931/3 */ - { .id = "OPT0931", .devs = { { "OPT9310" }, { "OPT0002" } }, .driver_data = 0x0931 }, + { .id = "OPT0931", .devs = { { "OPT9310" }, { "OPT0002" } }, + .driver_data = 0x0931 }, #endif /* OPTi93X */ { .id = "" } }; @@ -172,11 +173,7 @@ MODULE_DEVICE_TABLE(pnp_card, snd_opti9xx_pnpids); #endif /* CONFIG_PNP */ -#ifdef OPTi93X -#define DEV_NAME "opti93x" -#else -#define DEV_NAME "opti92x" -#endif +#define DEV_NAME KBUILD_MODNAME static char * snd_opti9xx_names[] = { "unknown", @@ -185,45 +182,43 @@ static char * snd_opti9xx_names[] = { "82C930", "82C931", "82C933" }; - -static long __devinit snd_legacy_find_free_ioport(long *port_table, long size) -{ - while (*port_table != -1) { - if (request_region(*port_table, size, "ALSA test")) { - release_region(*port_table, size); - return *port_table; - } - port_table++; - } - return -1; -} - -static int __devinit snd_opti9xx_init(struct snd_opti9xx *chip, - unsigned short hardware) +static int snd_opti9xx_init(struct snd_opti9xx *chip, + unsigned short hardware) { static int opti9xx_mc_size[] = {7, 7, 10, 10, 2, 2, 2}; chip->hardware = hardware; strcpy(chip->name, snd_opti9xx_names[hardware]); - chip->mc_base_size = opti9xx_mc_size[hardware]; - spin_lock_init(&chip->lock); chip->irq = -1; +#ifndef OPTi93X +#ifdef CONFIG_PNP + if (isapnp && chip->mc_base) + /* PnP resource gives the least 10 bits */ + chip->mc_base |= 0xc00; + else +#endif /* CONFIG_PNP */ + { + chip->mc_base = 0xf8c; + chip->mc_base_size = opti9xx_mc_size[hardware]; + } +#else + chip->mc_base_size = opti9xx_mc_size[hardware]; +#endif + switch (hardware) { #ifndef OPTi93X case OPTi9XX_HW_82C928: case OPTi9XX_HW_82C929: - chip->mc_base = 0xf8c; chip->password = (hardware == OPTi9XX_HW_82C928) ? 0xe2 : 0xe3; chip->pwd_reg = 3; break; case OPTi9XX_HW_82C924: case OPTi9XX_HW_82C925: - chip->mc_base = 0xf8c; chip->password = 0xe5; chip->pwd_reg = 3; break; @@ -233,10 +228,8 @@ static int __devinit snd_opti9xx_init(struct snd_opti9xx *chip, case OPTi9XX_HW_82C931: case OPTi9XX_HW_82C933: chip->mc_base = (hardware == OPTi9XX_HW_82C930) ? 0xf8f : 0xf8d; - if (!chip->mc_indir_index) { + if (!chip->mc_indir_index) chip->mc_indir_index = 0xe0e; - chip->mc_indir_size = 2; - } chip->password = 0xe4; chip->pwd_reg = 0; break; @@ -291,7 +284,7 @@ static unsigned char snd_opti9xx_read(struct snd_opti9xx *chip, spin_unlock_irqrestore(&chip->lock, flags); return retval; } - + static void snd_opti9xx_write(struct snd_opti9xx *chip, unsigned char reg, unsigned char value) { @@ -339,8 +332,8 @@ static void snd_opti9xx_write(struct snd_opti9xx *chip, unsigned char reg, (snd_opti9xx_read(chip, reg) & ~(mask)) | ((value) & (mask))) -static int __devinit snd_opti9xx_configure(struct snd_opti9xx *chip, - long wss_base, +static int snd_opti9xx_configure(struct snd_opti9xx *chip, + long port, int irq, int dma1, int dma2, long mpu_port, int mpu_irq) { @@ -353,16 +346,23 @@ static int __devinit snd_opti9xx_configure(struct snd_opti9xx *chip, switch (chip->hardware) { #ifndef OPTi93X case OPTi9XX_HW_82C924: + /* opti 929 mode (?), OPL3 clock output, audio enable */ snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(4), 0xf0, 0xfc); + /* enable wave audio */ snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(6), 0x02, 0x02); case OPTi9XX_HW_82C925: + /* enable WSS mode */ snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(1), 0x80, 0x80); + /* OPL3 FM synthesis */ snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(2), 0x00, 0x20); + /* disable Sound Blaster IRQ and DMA */ snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(3), 0xf0, 0xff); #ifdef CS4231 + /* cs4231/4248 fix enabled */ snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(5), 0x02, 0x02); #else + /* cs4231/4248 fix disabled */ snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(5), 0x00, 0x02); #endif /* CS4231 */ break; @@ -384,7 +384,9 @@ static int __devinit snd_opti9xx_configure(struct snd_opti9xx *chip, #else /* OPTi93X */ case OPTi9XX_HW_82C931: - case OPTi9XX_HW_82C933: + /* disable 3D sound (set GPIO1 as output, low) */ + snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(20), 0x04, 0x0c); + case OPTi9XX_HW_82C933: /* FALL THROUGH */ /* * The BTC 1817DW has QS1000 wavetable which is connected * to the serial digital input of the OPTI931. @@ -410,21 +412,26 @@ static int __devinit snd_opti9xx_configure(struct snd_opti9xx *chip, return -EINVAL; } - switch (wss_base) { - case 0x530: + /* PnP resource says it decodes only 10 bits of address */ + switch (port & 0x3ff) { + case 0x130: + chip->wss_base = 0x530; wss_base_bits = 0x00; break; - case 0x604: + case 0x204: + chip->wss_base = 0x604; wss_base_bits = 0x03; break; - case 0xe80: + case 0x280: + chip->wss_base = 0xe80; wss_base_bits = 0x01; break; - case 0xf40: + case 0x340: + chip->wss_base = 0xf40; wss_base_bits = 0x02; break; default: - snd_printk(KERN_WARNING "WSS port 0x%lx not valid\n", wss_base); + snd_printk(KERN_WARNING "WSS port 0x%lx not valid\n", port); goto __skip_base; } snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(1), wss_base_bits << 4, 0x30); @@ -486,7 +493,7 @@ __skip_base: #endif /* CS4231 || OPTi93X */ #ifndef OPTi93X - outb(irq_bits << 3 | dma_bits, wss_base); + outb(irq_bits << 3 | dma_bits, chip->wss_base); #else /* OPTi93X */ snd_opti9xx_write(chip, OPTi9XX_MC_REG(3), (irq_bits << 3 | dma_bits)); #endif /* OPTi93X */ @@ -546,6 +553,93 @@ __skip_mpu: #ifdef OPTi93X +static const DECLARE_TLV_DB_SCALE(db_scale_5bit_3db_step, -9300, 300, 0); +static const DECLARE_TLV_DB_SCALE(db_scale_5bit, -4650, 150, 0); +static const DECLARE_TLV_DB_SCALE(db_scale_4bit_12db_max, -3300, 300, 0); + +static struct snd_kcontrol_new snd_opti93x_controls[] = { +WSS_DOUBLE("Master Playback Switch", 0, + OPTi93X_OUT_LEFT, OPTi93X_OUT_RIGHT, 7, 7, 1, 1), +WSS_DOUBLE_TLV("Master Playback Volume", 0, + OPTi93X_OUT_LEFT, OPTi93X_OUT_RIGHT, 1, 1, 31, 1, + db_scale_5bit_3db_step), +WSS_DOUBLE_TLV("PCM Playback Volume", 0, + CS4231_LEFT_OUTPUT, CS4231_RIGHT_OUTPUT, 0, 0, 31, 1, + db_scale_5bit), +WSS_DOUBLE_TLV("FM Playback Volume", 0, + CS4231_AUX2_LEFT_INPUT, CS4231_AUX2_RIGHT_INPUT, 1, 1, 15, 1, + db_scale_4bit_12db_max), +WSS_DOUBLE("Line Playback Switch", 0, + CS4231_LEFT_LINE_IN, CS4231_RIGHT_LINE_IN, 7, 7, 1, 1), +WSS_DOUBLE_TLV("Line Playback Volume", 0, + CS4231_LEFT_LINE_IN, CS4231_RIGHT_LINE_IN, 0, 0, 15, 1, + db_scale_4bit_12db_max), +WSS_DOUBLE("Mic Playback Switch", 0, + OPTi93X_MIC_LEFT_INPUT, OPTi93X_MIC_RIGHT_INPUT, 7, 7, 1, 1), +WSS_DOUBLE_TLV("Mic Playback Volume", 0, + OPTi93X_MIC_LEFT_INPUT, OPTi93X_MIC_RIGHT_INPUT, 1, 1, 15, 1, + db_scale_4bit_12db_max), +WSS_DOUBLE_TLV("CD Playback Volume", 0, + CS4231_AUX1_LEFT_INPUT, CS4231_AUX1_RIGHT_INPUT, 1, 1, 15, 1, + db_scale_4bit_12db_max), +WSS_DOUBLE("Aux Playback Switch", 0, + OPTi931_AUX_LEFT_INPUT, OPTi931_AUX_RIGHT_INPUT, 7, 7, 1, 1), +WSS_DOUBLE_TLV("Aux Playback Volume", 0, + OPTi931_AUX_LEFT_INPUT, OPTi931_AUX_RIGHT_INPUT, 1, 1, 15, 1, + db_scale_4bit_12db_max), +}; + +static int snd_opti93x_mixer(struct snd_wss *chip) +{ + struct snd_card *card; + unsigned int idx; + struct snd_ctl_elem_id id1, id2; + int err; + + if (snd_BUG_ON(!chip || !chip->pcm)) + return -EINVAL; + + card = chip->card; + + strcpy(card->mixername, chip->pcm->name); + + memset(&id1, 0, sizeof(id1)); + memset(&id2, 0, sizeof(id2)); + id1.iface = id2.iface = SNDRV_CTL_ELEM_IFACE_MIXER; + /* reassign AUX0 switch to CD */ + strcpy(id1.name, "Aux Playback Switch"); + strcpy(id2.name, "CD Playback Switch"); + err = snd_ctl_rename_id(card, &id1, &id2); + if (err < 0) { + snd_printk(KERN_ERR "Cannot rename opti93x control\n"); + return err; + } + /* reassign AUX1 switch to FM */ + strcpy(id1.name, "Aux Playback Switch"); id1.index = 1; + strcpy(id2.name, "FM Playback Switch"); + err = snd_ctl_rename_id(card, &id1, &id2); + if (err < 0) { + snd_printk(KERN_ERR "Cannot rename opti93x control\n"); + return err; + } + /* remove AUX1 volume */ + strcpy(id1.name, "Aux Playback Volume"); id1.index = 1; + snd_ctl_remove_id(card, &id1); + + /* Replace WSS volume controls with OPTi93x volume controls */ + id1.index = 0; + for (idx = 0; idx < ARRAY_SIZE(snd_opti93x_controls); idx++) { + strcpy(id1.name, snd_opti93x_controls[idx].name); + snd_ctl_remove_id(card, &id1); + + err = snd_ctl_add(card, + snd_ctl_new1(&snd_opti93x_controls[idx], chip)); + if (err < 0) + return err; + } + return 0; +} + static irqreturn_t snd_opti93x_interrupt(int irq, void *dev_id) { struct snd_opti9xx *chip = dev_id; @@ -568,7 +662,7 @@ static irqreturn_t snd_opti93x_interrupt(int irq, void *dev_id) #endif /* OPTi93X */ -static int __devinit snd_opti9xx_read_check(struct snd_opti9xx *chip) +static int snd_opti9xx_read_check(struct snd_opti9xx *chip) { unsigned char value; #ifdef OPTi93X @@ -585,8 +679,7 @@ static int __devinit snd_opti9xx_read_check(struct snd_opti9xx *chip) if (value == snd_opti9xx_read(chip, OPTi9XX_MC_REG(1))) return 0; #else /* OPTi93X */ - chip->res_mc_indir = request_region(chip->mc_indir_index, - chip->mc_indir_size, + chip->res_mc_indir = request_region(chip->mc_indir_index, 2, "OPTi93x MC"); if (chip->res_mc_indir == NULL) return -EBUSY; @@ -610,8 +703,8 @@ static int __devinit snd_opti9xx_read_check(struct snd_opti9xx *chip) return -ENODEV; } -static int __devinit snd_card_opti9xx_detect(struct snd_card *card, - struct snd_opti9xx *chip) +static int snd_card_opti9xx_detect(struct snd_card *card, + struct snd_opti9xx *chip) { int i, err; @@ -635,21 +728,21 @@ static int __devinit snd_card_opti9xx_detect(struct snd_card *card, } #ifdef CONFIG_PNP -static int __devinit snd_card_opti9xx_pnp(struct snd_opti9xx *chip, - struct pnp_card_link *card, - const struct pnp_card_device_id *pid) +static int snd_card_opti9xx_pnp(struct snd_opti9xx *chip, + struct pnp_card_link *card, + const struct pnp_card_device_id *pid) { struct pnp_dev *pdev; int err; + struct pnp_dev *devmpu; +#ifndef OPTi93X + struct pnp_dev *devmc; +#endif - chip->dev = pnp_request_card_device(card, pid->devs[0].id, NULL); - if (chip->dev == NULL) + pdev = pnp_request_card_device(card, pid->devs[0].id, NULL); + if (pdev == NULL) return -EBUSY; - chip->devmpu = pnp_request_card_device(card, pid->devs[1].id, NULL); - - pdev = chip->dev; - err = pnp_activate_dev(pdev); if (err < 0) { snd_printk(KERN_ERR "AUDIO pnp configure failure: %d\n", err); @@ -659,12 +752,28 @@ static int __devinit snd_card_opti9xx_pnp(struct snd_opti9xx *chip, #ifdef OPTi93X port = pnp_port_start(pdev, 0) - 4; fm_port = pnp_port_start(pdev, 1) + 8; - chip->mc_indir_index = pnp_port_start(pdev, 3) + 2; - chip->mc_indir_size = pnp_port_len(pdev, 3) - 2; + /* adjust mc_indir_index - some cards report it at 0xe?d, + other at 0xe?c but it really is always at 0xe?e */ + chip->mc_indir_index = (pnp_port_start(pdev, 3) & ~0xf) | 0xe; #else - if (pid->driver_data != 0x0924) - port = pnp_port_start(pdev, 1); + devmc = pnp_request_card_device(card, pid->devs[2].id, NULL); + if (devmc == NULL) + return -EBUSY; + + err = pnp_activate_dev(devmc); + if (err < 0) { + snd_printk(KERN_ERR "MC pnp configure failure: %d\n", err); + return err; + } + + port = pnp_port_start(pdev, 1); fm_port = pnp_port_start(pdev, 2) + 8; + /* + * The MC(0) is never accessed and card does not + * include it in the PnP resource range. OPTI93x include it. + */ + chip->mc_base = pnp_port_start(devmc, 0) - 1; + chip->mc_base_size = pnp_port_len(devmc, 0) + 1; #endif /* OPTi93X */ irq = pnp_irq(pdev, 0); dma1 = pnp_dma(pdev, 0); @@ -672,16 +781,16 @@ static int __devinit snd_card_opti9xx_pnp(struct snd_opti9xx *chip, dma2 = pnp_dma(pdev, 1); #endif /* CS4231 || OPTi93X */ - pdev = chip->devmpu; - if (pdev && mpu_port > 0) { - err = pnp_activate_dev(pdev); + devmpu = pnp_request_card_device(card, pid->devs[1].id, NULL); + + if (devmpu && mpu_port > 0) { + err = pnp_activate_dev(devmpu); if (err < 0) { - snd_printk(KERN_ERR "AUDIO pnp configure failure\n"); + snd_printk(KERN_ERR "MPU401 pnp configure failure\n"); mpu_port = -1; - chip->devmpu = NULL; } else { - mpu_port = pnp_port_start(pdev, 0); - mpu_irq = pnp_irq(pdev, 0); + mpu_port = pnp_port_start(devmpu, 0); + mpu_irq = pnp_irq(devmpu, 0); } } return pid->driver_data; @@ -704,7 +813,7 @@ static void snd_card_opti9xx_free(struct snd_card *card) } } -static int __devinit snd_opti9xx_probe(struct snd_card *card) +static int snd_opti9xx_probe(struct snd_card *card) { static long possible_ports[] = {0x530, 0xe80, 0xf40, 0x604, -1}; int error; @@ -736,7 +845,7 @@ static int __devinit snd_opti9xx_probe(struct snd_card *card) if (error) return error; - error = snd_wss_create(card, port + 4, -1, irq, dma1, xdma2, + error = snd_wss_create(card, chip->wss_base + 4, -1, irq, dma1, xdma2, #ifdef OPTi93X WSS_HW_OPTI93X, WSS_HWSHARE_IRQ, #else @@ -745,15 +854,18 @@ static int __devinit snd_opti9xx_probe(struct snd_card *card) &codec); if (error < 0) return error; -#ifdef OPTi93X chip->codec = codec; -#endif error = snd_wss_pcm(codec, 0, &pcm); if (error < 0) return error; error = snd_wss_mixer(codec); if (error < 0) return error; +#ifdef OPTi93X + error = snd_opti93x_mixer(codec); + if (error < 0) + return error; +#endif #ifdef CS4231 error = snd_wss_timer(codec, 0, &timer); if (error < 0) @@ -761,7 +873,7 @@ static int __devinit snd_opti9xx_probe(struct snd_card *card) #endif #ifdef OPTi93X error = request_irq(irq, snd_opti93x_interrupt, - IRQF_DISABLED, DEV_NAME" - WSS", chip); + 0, DEV_NAME" - WSS", chip); if (error < 0) { snd_printk(KERN_ERR "opti9xx: can't grab IRQ %d\n", irq); return error; @@ -772,17 +884,18 @@ static int __devinit snd_opti9xx_probe(struct snd_card *card) sprintf(card->shortname, "OPTi %s", card->driver); #if defined(CS4231) || defined(OPTi93X) sprintf(card->longname, "%s, %s at 0x%lx, irq %d, dma %d&%d", - card->shortname, pcm->name, port + 4, irq, dma1, xdma2); + card->shortname, pcm->name, + chip->wss_base + 4, irq, dma1, xdma2); #else sprintf(card->longname, "%s, %s at 0x%lx, irq %d, dma %d", - card->shortname, pcm->name, port + 4, irq, dma1); + card->shortname, pcm->name, chip->wss_base + 4, irq, dma1); #endif /* CS4231 || OPTi93X */ if (mpu_port <= 0 || mpu_port == SNDRV_AUTO_PORT) rmidi = NULL; else { error = snd_mpu401_uart_new(card, 0, MPU401_HW_MPU401, - mpu_port, 0, mpu_irq, IRQF_DISABLED, &rmidi); + mpu_port, 0, mpu_irq, &rmidi); if (error) snd_printk(KERN_WARNING "no MPU-401 device at 0x%lx?\n", mpu_port); @@ -821,13 +934,13 @@ static int __devinit snd_opti9xx_probe(struct snd_card *card) return snd_card_register(card); } -static int snd_opti9xx_card_new(struct snd_card **cardp) +static int snd_opti9xx_card_new(struct device *pdev, struct snd_card **cardp) { struct snd_card *card; int err; - err = snd_card_create(index, id, THIS_MODULE, - sizeof(struct snd_opti9xx), &card); + err = snd_card_new(pdev, index, id, THIS_MODULE, + sizeof(struct snd_opti9xx), &card); if (err < 0) return err; card->private_free = snd_card_opti9xx_free; @@ -835,8 +948,8 @@ static int snd_opti9xx_card_new(struct snd_card **cardp) return 0; } -static int __devinit snd_opti9xx_isa_match(struct device *devptr, - unsigned int dev) +static int snd_opti9xx_isa_match(struct device *devptr, + unsigned int dev) { #ifdef CONFIG_PNP if (snd_opti9xx_pnp_is_probed) @@ -847,8 +960,8 @@ static int __devinit snd_opti9xx_isa_match(struct device *devptr, return 1; } -static int __devinit snd_opti9xx_isa_probe(struct device *devptr, - unsigned int dev) +static int snd_opti9xx_isa_probe(struct device *devptr, + unsigned int dev) { struct snd_card *card; int error; @@ -897,7 +1010,7 @@ static int __devinit snd_opti9xx_isa_probe(struct device *devptr, } #endif - error = snd_opti9xx_card_new(&card); + error = snd_opti9xx_card_new(devptr, &card); if (error < 0) return error; @@ -905,7 +1018,6 @@ static int __devinit snd_opti9xx_isa_probe(struct device *devptr, snd_card_free(card); return error; } - snd_card_set_dev(card, devptr); if ((error = snd_opti9xx_probe(card)) < 0) { snd_card_free(card); return error; @@ -914,27 +1026,70 @@ static int __devinit snd_opti9xx_isa_probe(struct device *devptr, return 0; } -static int __devexit snd_opti9xx_isa_remove(struct device *devptr, - unsigned int dev) +static int snd_opti9xx_isa_remove(struct device *devptr, + unsigned int dev) { snd_card_free(dev_get_drvdata(devptr)); - dev_set_drvdata(devptr, NULL); return 0; } +#ifdef CONFIG_PM +static int snd_opti9xx_suspend(struct snd_card *card) +{ + struct snd_opti9xx *chip = card->private_data; + + snd_power_change_state(card, SNDRV_CTL_POWER_D3hot); + chip->codec->suspend(chip->codec); + return 0; +} + +static int snd_opti9xx_resume(struct snd_card *card) +{ + struct snd_opti9xx *chip = card->private_data; + int error, xdma2; +#if defined(CS4231) || defined(OPTi93X) + xdma2 = dma2; +#else + xdma2 = -1; +#endif + + error = snd_opti9xx_configure(chip, port, irq, dma1, xdma2, + mpu_port, mpu_irq); + if (error) + return error; + chip->codec->resume(chip->codec); + snd_power_change_state(card, SNDRV_CTL_POWER_D0); + return 0; +} + +static int snd_opti9xx_isa_suspend(struct device *dev, unsigned int n, + pm_message_t state) +{ + return snd_opti9xx_suspend(dev_get_drvdata(dev)); +} + +static int snd_opti9xx_isa_resume(struct device *dev, unsigned int n) +{ + return snd_opti9xx_resume(dev_get_drvdata(dev)); +} +#endif + static struct isa_driver snd_opti9xx_driver = { .match = snd_opti9xx_isa_match, .probe = snd_opti9xx_isa_probe, - .remove = __devexit_p(snd_opti9xx_isa_remove), - /* FIXME: suspend/resume */ + .remove = snd_opti9xx_isa_remove, +#ifdef CONFIG_PM + .suspend = snd_opti9xx_isa_suspend, + .resume = snd_opti9xx_isa_resume, +#endif .driver = { .name = DEV_NAME }, }; #ifdef CONFIG_PNP -static int __devinit snd_opti9xx_pnp_probe(struct pnp_card_link *pcard, - const struct pnp_card_device_id *pid) +static int snd_opti9xx_pnp_probe(struct pnp_card_link *pcard, + const struct pnp_card_device_id *pid) { struct snd_card *card; int error, hw; @@ -944,7 +1099,7 @@ static int __devinit snd_opti9xx_pnp_probe(struct pnp_card_link *pcard, return -EBUSY; if (! isapnp) return -ENODEV; - error = snd_opti9xx_card_new(&card); + error = snd_opti9xx_card_new(&pcard->card->dev, &card); if (error < 0) return error; chip = card->private_data; @@ -969,16 +1124,12 @@ static int __devinit snd_opti9xx_pnp_probe(struct pnp_card_link *pcard, snd_card_free(card); return error; } - if (hw <= OPTi9XX_HW_82C930) - chip->mc_base -= 0x80; - error = snd_opti9xx_read_check(chip); if (error) { snd_printk(KERN_ERR "OPTI chip not found\n"); snd_card_free(card); return error; } - snd_card_set_dev(card, &pcard->card->dev); if ((error = snd_opti9xx_probe(card)) < 0) { snd_card_free(card); return error; @@ -988,19 +1139,36 @@ static int __devinit snd_opti9xx_pnp_probe(struct pnp_card_link *pcard, return 0; } -static void __devexit snd_opti9xx_pnp_remove(struct pnp_card_link * pcard) +static void snd_opti9xx_pnp_remove(struct pnp_card_link *pcard) { snd_card_free(pnp_get_card_drvdata(pcard)); pnp_set_card_drvdata(pcard, NULL); snd_opti9xx_pnp_is_probed = 0; } +#ifdef CONFIG_PM +static int snd_opti9xx_pnp_suspend(struct pnp_card_link *pcard, + pm_message_t state) +{ + return snd_opti9xx_suspend(pnp_get_card_drvdata(pcard)); +} + +static int snd_opti9xx_pnp_resume(struct pnp_card_link *pcard) +{ + return snd_opti9xx_resume(pnp_get_card_drvdata(pcard)); +} +#endif + static struct pnp_card_driver opti9xx_pnpc_driver = { .flags = PNP_DRIVER_RES_DISABLE, - .name = "opti9xx", + .name = DEV_NAME, .id_table = snd_opti9xx_pnpids, .probe = snd_opti9xx_pnp_probe, - .remove = __devexit_p(snd_opti9xx_pnp_remove), + .remove = snd_opti9xx_pnp_remove, +#ifdef CONFIG_PM + .suspend = snd_opti9xx_pnp_suspend, + .resume = snd_opti9xx_pnp_resume, +#endif }; #endif |
