aboutsummaryrefslogtreecommitdiffstats
path: root/sound/isa/opl3sa2.c
diff options
context:
space:
mode:
Diffstat (limited to 'sound/isa/opl3sa2.c')
-rw-r--r--sound/isa/opl3sa2.c99
1 files changed, 42 insertions, 57 deletions
diff --git a/sound/isa/opl3sa2.c b/sound/isa/opl3sa2.c
index 854a9f74b466..58c972b2af03 100644
--- a/sound/isa/opl3sa2.c
+++ b/sound/isa/opl3sa2.c
@@ -28,7 +28,7 @@
28#include <linux/pnp.h> 28#include <linux/pnp.h>
29#include <linux/moduleparam.h> 29#include <linux/moduleparam.h>
30#include <sound/core.h> 30#include <sound/core.h>
31#include <sound/cs4231.h> 31#include <sound/wss.h>
32#include <sound/mpu401.h> 32#include <sound/mpu401.h>
33#include <sound/opl3.h> 33#include <sound/opl3.h>
34#include <sound/initval.h> 34#include <sound/initval.h>
@@ -124,7 +124,6 @@ static int pnpc_registered;
124#define OPL3SA2_PM_D3 (OPL3SA2_PM_ADOWN|OPL3SA2_PM_PSV|OPL3SA2_PM_PDN|OPL3SA2_PM_PDX) 124#define OPL3SA2_PM_D3 (OPL3SA2_PM_ADOWN|OPL3SA2_PM_PSV|OPL3SA2_PM_PDN|OPL3SA2_PM_PDX)
125 125
126struct snd_opl3sa2 { 126struct snd_opl3sa2 {
127 struct snd_card *card;
128 int version; /* 2 or 3 */ 127 int version; /* 2 or 3 */
129 unsigned long port; /* control port */ 128 unsigned long port; /* control port */
130 struct resource *res_port; /* control port resource */ 129 struct resource *res_port; /* control port resource */
@@ -133,7 +132,7 @@ struct snd_opl3sa2 {
133 spinlock_t reg_lock; 132 spinlock_t reg_lock;
134 struct snd_hwdep *synth; 133 struct snd_hwdep *synth;
135 struct snd_rawmidi *rmidi; 134 struct snd_rawmidi *rmidi;
136 struct snd_cs4231 *cs4231; 135 struct snd_wss *wss;
137 unsigned char ctlregs[0x20]; 136 unsigned char ctlregs[0x20];
138 int ymode; /* SL added */ 137 int ymode; /* SL added */
139 struct snd_kcontrol *master_switch; 138 struct snd_kcontrol *master_switch;
@@ -222,14 +221,13 @@ static void snd_opl3sa2_write(struct snd_opl3sa2 *chip, unsigned char reg, unsig
222 spin_unlock_irqrestore(&chip->reg_lock, flags); 221 spin_unlock_irqrestore(&chip->reg_lock, flags);
223} 222}
224 223
225static int __devinit snd_opl3sa2_detect(struct snd_opl3sa2 *chip) 224static int __devinit snd_opl3sa2_detect(struct snd_card *card)
226{ 225{
227 struct snd_card *card; 226 struct snd_opl3sa2 *chip = card->private_data;
228 unsigned long port; 227 unsigned long port;
229 unsigned char tmp, tmp1; 228 unsigned char tmp, tmp1;
230 char str[2]; 229 char str[2];
231 230
232 card = chip->card;
233 port = chip->port; 231 port = chip->port;
234 if ((chip->res_port = request_region(port, 2, "OPL3-SA control")) == NULL) { 232 if ((chip->res_port = request_region(port, 2, "OPL3-SA control")) == NULL) {
235 snd_printk(KERN_ERR PFX "can't grab port 0x%lx\n", port); 233 snd_printk(KERN_ERR PFX "can't grab port 0x%lx\n", port);
@@ -298,12 +296,14 @@ static int __devinit snd_opl3sa2_detect(struct snd_opl3sa2 *chip)
298static irqreturn_t snd_opl3sa2_interrupt(int irq, void *dev_id) 296static irqreturn_t snd_opl3sa2_interrupt(int irq, void *dev_id)
299{ 297{
300 unsigned short status; 298 unsigned short status;
301 struct snd_opl3sa2 *chip = dev_id; 299 struct snd_card *card = dev_id;
300 struct snd_opl3sa2 *chip;
302 int handled = 0; 301 int handled = 0;
303 302
304 if (chip == NULL || chip->card == NULL) 303 if (card == NULL)
305 return IRQ_NONE; 304 return IRQ_NONE;
306 305
306 chip = card->private_data;
307 status = snd_opl3sa2_read(chip, OPL3SA2_IRQ_STATUS); 307 status = snd_opl3sa2_read(chip, OPL3SA2_IRQ_STATUS);
308 308
309 if (status & 0x20) { 309 if (status & 0x20) {
@@ -318,7 +318,7 @@ static irqreturn_t snd_opl3sa2_interrupt(int irq, void *dev_id)
318 318
319 if (status & 0x07) { /* TI,CI,PI */ 319 if (status & 0x07) { /* TI,CI,PI */
320 handled = 1; 320 handled = 1;
321 snd_cs4231_interrupt(irq, chip->cs4231); 321 snd_wss_interrupt(irq, chip->wss);
322 } 322 }
323 323
324 if (status & 0x40) { /* hardware volume change */ 324 if (status & 0x40) { /* hardware volume change */
@@ -327,8 +327,10 @@ static irqreturn_t snd_opl3sa2_interrupt(int irq, void *dev_id)
327 snd_opl3sa2_read(chip, OPL3SA2_MASTER_RIGHT); 327 snd_opl3sa2_read(chip, OPL3SA2_MASTER_RIGHT);
328 snd_opl3sa2_read(chip, OPL3SA2_MASTER_LEFT); 328 snd_opl3sa2_read(chip, OPL3SA2_MASTER_LEFT);
329 if (chip->master_switch && chip->master_volume) { 329 if (chip->master_switch && chip->master_volume) {
330 snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_VALUE, &chip->master_switch->id); 330 snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE,
331 snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_VALUE, &chip->master_volume->id); 331 &chip->master_switch->id);
332 snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE,
333 &chip->master_volume->id);
332 } 334 }
333 } 335 }
334 return IRQ_RETVAL(handled); 336 return IRQ_RETVAL(handled);
@@ -336,29 +338,18 @@ static irqreturn_t snd_opl3sa2_interrupt(int irq, void *dev_id)
336 338
337#define OPL3SA2_SINGLE(xname, xindex, reg, shift, mask, invert) \ 339#define OPL3SA2_SINGLE(xname, xindex, reg, shift, mask, invert) \
338{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \ 340{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \
339 .info = snd_opl3sa2_info_single, \ 341 .info = snd_wss_info_single, \
340 .get = snd_opl3sa2_get_single, .put = snd_opl3sa2_put_single, \ 342 .get = snd_opl3sa2_get_single, .put = snd_opl3sa2_put_single, \
341 .private_value = reg | (shift << 8) | (mask << 16) | (invert << 24) } 343 .private_value = reg | (shift << 8) | (mask << 16) | (invert << 24) }
342#define OPL3SA2_SINGLE_TLV(xname, xindex, reg, shift, mask, invert, xtlv) \ 344#define OPL3SA2_SINGLE_TLV(xname, xindex, reg, shift, mask, invert, xtlv) \
343{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ 345{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
344 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_TLV_READ, \ 346 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_TLV_READ, \
345 .name = xname, .index = xindex, \ 347 .name = xname, .index = xindex, \
346 .info = snd_opl3sa2_info_single, \ 348 .info = snd_wss_info_single, \
347 .get = snd_opl3sa2_get_single, .put = snd_opl3sa2_put_single, \ 349 .get = snd_opl3sa2_get_single, .put = snd_opl3sa2_put_single, \
348 .private_value = reg | (shift << 8) | (mask << 16) | (invert << 24), \ 350 .private_value = reg | (shift << 8) | (mask << 16) | (invert << 24), \
349 .tlv = { .p = (xtlv) } } 351 .tlv = { .p = (xtlv) } }
350 352
351static int snd_opl3sa2_info_single(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
352{
353 int mask = (kcontrol->private_value >> 16) & 0xff;
354
355 uinfo->type = mask == 1 ? SNDRV_CTL_ELEM_TYPE_BOOLEAN : SNDRV_CTL_ELEM_TYPE_INTEGER;
356 uinfo->count = 1;
357 uinfo->value.integer.min = 0;
358 uinfo->value.integer.max = mask;
359 return 0;
360}
361
362static int snd_opl3sa2_get_single(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) 353static int snd_opl3sa2_get_single(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
363{ 354{
364 struct snd_opl3sa2 *chip = snd_kcontrol_chip(kcontrol); 355 struct snd_opl3sa2 *chip = snd_kcontrol_chip(kcontrol);
@@ -402,29 +393,18 @@ static int snd_opl3sa2_put_single(struct snd_kcontrol *kcontrol, struct snd_ctl_
402 393
403#define OPL3SA2_DOUBLE(xname, xindex, left_reg, right_reg, shift_left, shift_right, mask, invert) \ 394#define OPL3SA2_DOUBLE(xname, xindex, left_reg, right_reg, shift_left, shift_right, mask, invert) \
404{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \ 395{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \
405 .info = snd_opl3sa2_info_double, \ 396 .info = snd_wss_info_double, \
406 .get = snd_opl3sa2_get_double, .put = snd_opl3sa2_put_double, \ 397 .get = snd_opl3sa2_get_double, .put = snd_opl3sa2_put_double, \
407 .private_value = left_reg | (right_reg << 8) | (shift_left << 16) | (shift_right << 19) | (mask << 24) | (invert << 22) } 398 .private_value = left_reg | (right_reg << 8) | (shift_left << 16) | (shift_right << 19) | (mask << 24) | (invert << 22) }
408#define OPL3SA2_DOUBLE_TLV(xname, xindex, left_reg, right_reg, shift_left, shift_right, mask, invert, xtlv) \ 399#define OPL3SA2_DOUBLE_TLV(xname, xindex, left_reg, right_reg, shift_left, shift_right, mask, invert, xtlv) \
409{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ 400{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
410 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_TLV_READ, \ 401 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_TLV_READ, \
411 .name = xname, .index = xindex, \ 402 .name = xname, .index = xindex, \
412 .info = snd_opl3sa2_info_double, \ 403 .info = snd_wss_info_double, \
413 .get = snd_opl3sa2_get_double, .put = snd_opl3sa2_put_double, \ 404 .get = snd_opl3sa2_get_double, .put = snd_opl3sa2_put_double, \
414 .private_value = left_reg | (right_reg << 8) | (shift_left << 16) | (shift_right << 19) | (mask << 24) | (invert << 22), \ 405 .private_value = left_reg | (right_reg << 8) | (shift_left << 16) | (shift_right << 19) | (mask << 24) | (invert << 22), \
415 .tlv = { .p = (xtlv) } } 406 .tlv = { .p = (xtlv) } }
416 407
417static int snd_opl3sa2_info_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
418{
419 int mask = (kcontrol->private_value >> 24) & 0xff;
420
421 uinfo->type = mask == 1 ? SNDRV_CTL_ELEM_TYPE_BOOLEAN : SNDRV_CTL_ELEM_TYPE_INTEGER;
422 uinfo->count = 2;
423 uinfo->value.integer.min = 0;
424 uinfo->value.integer.max = mask;
425 return 0;
426}
427
428static int snd_opl3sa2_get_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) 408static int snd_opl3sa2_get_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
429{ 409{
430 struct snd_opl3sa2 *chip = snd_kcontrol_chip(kcontrol); 410 struct snd_opl3sa2 *chip = snd_kcontrol_chip(kcontrol);
@@ -512,9 +492,9 @@ static void snd_opl3sa2_master_free(struct snd_kcontrol *kcontrol)
512 chip->master_volume = NULL; 492 chip->master_volume = NULL;
513} 493}
514 494
515static int __devinit snd_opl3sa2_mixer(struct snd_opl3sa2 *chip) 495static int __devinit snd_opl3sa2_mixer(struct snd_card *card)
516{ 496{
517 struct snd_card *card = chip->card; 497 struct snd_opl3sa2 *chip = card->private_data;
518 struct snd_ctl_elem_id id1, id2; 498 struct snd_ctl_elem_id id1, id2;
519 struct snd_kcontrol *kctl; 499 struct snd_kcontrol *kctl;
520 unsigned int idx; 500 unsigned int idx;
@@ -573,7 +553,7 @@ static int snd_opl3sa2_suspend(struct snd_card *card, pm_message_t state)
573 struct snd_opl3sa2 *chip = card->private_data; 553 struct snd_opl3sa2 *chip = card->private_data;
574 554
575 snd_power_change_state(card, SNDRV_CTL_POWER_D3hot); 555 snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
576 chip->cs4231->suspend(chip->cs4231); 556 chip->wss->suspend(chip->wss);
577 /* power down */ 557 /* power down */
578 snd_opl3sa2_write(chip, OPL3SA2_PM_CTRL, OPL3SA2_PM_D3); 558 snd_opl3sa2_write(chip, OPL3SA2_PM_CTRL, OPL3SA2_PM_D3);
579 559
@@ -597,8 +577,8 @@ static int snd_opl3sa2_resume(struct snd_card *card)
597 for (i = 0x12; i <= 0x16; i++) 577 for (i = 0x12; i <= 0x16; i++)
598 snd_opl3sa2_write(chip, i, chip->ctlregs[i]); 578 snd_opl3sa2_write(chip, i, chip->ctlregs[i]);
599 } 579 }
600 /* restore cs4231 */ 580 /* restore wss */
601 chip->cs4231->resume(chip->cs4231); 581 chip->wss->resume(chip->wss);
602 582
603 snd_power_change_state(card, SNDRV_CTL_POWER_D0); 583 snd_power_change_state(card, SNDRV_CTL_POWER_D0);
604 return 0; 584 return 0;
@@ -650,7 +630,6 @@ static struct snd_card *snd_opl3sa2_card_new(int dev)
650 chip = card->private_data; 630 chip = card->private_data;
651 spin_lock_init(&chip->reg_lock); 631 spin_lock_init(&chip->reg_lock);
652 chip->irq = -1; 632 chip->irq = -1;
653 chip->card = card;
654 card->private_free = snd_opl3sa2_free; 633 card->private_free = snd_opl3sa2_free;
655 return card; 634 return card;
656} 635}
@@ -659,7 +638,7 @@ static int __devinit snd_opl3sa2_probe(struct snd_card *card, int dev)
659{ 638{
660 int xirq, xdma1, xdma2; 639 int xirq, xdma1, xdma2;
661 struct snd_opl3sa2 *chip; 640 struct snd_opl3sa2 *chip;
662 struct snd_cs4231 *cs4231; 641 struct snd_wss *wss;
663 struct snd_opl3 *opl3; 642 struct snd_opl3 *opl3;
664 int err; 643 int err;
665 644
@@ -672,30 +651,36 @@ static int __devinit snd_opl3sa2_probe(struct snd_card *card, int dev)
672 xdma2 = dma2[dev]; 651 xdma2 = dma2[dev];
673 if (xdma2 < 0) 652 if (xdma2 < 0)
674 chip->single_dma = 1; 653 chip->single_dma = 1;
675 if ((err = snd_opl3sa2_detect(chip)) < 0) 654 err = snd_opl3sa2_detect(card);
655 if (err < 0)
676 return err; 656 return err;
677 if (request_irq(xirq, snd_opl3sa2_interrupt, IRQF_DISABLED, "OPL3-SA2", chip)) { 657 err = request_irq(xirq, snd_opl3sa2_interrupt, IRQF_DISABLED,
658 "OPL3-SA2", card);
659 if (err) {
678 snd_printk(KERN_ERR PFX "can't grab IRQ %d\n", xirq); 660 snd_printk(KERN_ERR PFX "can't grab IRQ %d\n", xirq);
679 return -ENODEV; 661 return -ENODEV;
680 } 662 }
681 chip->irq = xirq; 663 chip->irq = xirq;
682 if ((err = snd_cs4231_create(card, 664 err = snd_wss_create(card,
683 wss_port[dev] + 4, -1, 665 wss_port[dev] + 4, -1,
684 xirq, xdma1, xdma2, 666 xirq, xdma1, xdma2,
685 CS4231_HW_OPL3SA2, 667 WSS_HW_OPL3SA2, WSS_HWSHARE_IRQ, &wss);
686 CS4231_HWSHARE_IRQ, 668 if (err < 0) {
687 &cs4231)) < 0) {
688 snd_printd("Oops, WSS not detected at 0x%lx\n", wss_port[dev] + 4); 669 snd_printd("Oops, WSS not detected at 0x%lx\n", wss_port[dev] + 4);
689 return err; 670 return err;
690 } 671 }
691 chip->cs4231 = cs4231; 672 chip->wss = wss;
692 if ((err = snd_cs4231_pcm(cs4231, 0, NULL)) < 0) 673 err = snd_wss_pcm(wss, 0, NULL);
674 if (err < 0)
693 return err; 675 return err;
694 if ((err = snd_cs4231_mixer(cs4231)) < 0) 676 err = snd_wss_mixer(wss);
677 if (err < 0)
695 return err; 678 return err;
696 if ((err = snd_opl3sa2_mixer(chip)) < 0) 679 err = snd_opl3sa2_mixer(card);
680 if (err < 0)
697 return err; 681 return err;
698 if ((err = snd_cs4231_timer(cs4231, 0, NULL)) < 0) 682 err = snd_wss_timer(wss, 0, NULL);
683 if (err < 0)
699 return err; 684 return err;
700 if (fm_port[dev] >= 0x340 && fm_port[dev] < 0x400) { 685 if (fm_port[dev] >= 0x340 && fm_port[dev] < 0x400) {
701 if ((err = snd_opl3_create(card, fm_port[dev], 686 if ((err = snd_opl3_create(card, fm_port[dev],