diff options
Diffstat (limited to 'sound/isa/opl3sa2.c')
-rw-r--r-- | sound/isa/opl3sa2.c | 99 |
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 | ||
126 | struct snd_opl3sa2 { | 126 | struct 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 | ||
225 | static int __devinit snd_opl3sa2_detect(struct snd_opl3sa2 *chip) | 224 | static 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) | |||
298 | static irqreturn_t snd_opl3sa2_interrupt(int irq, void *dev_id) | 296 | static 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 | ||
351 | static 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 | |||
362 | static int snd_opl3sa2_get_single(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | 353 | static 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 | ||
417 | static 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 | |||
428 | static int snd_opl3sa2_get_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | 408 | static 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 | ||
515 | static int __devinit snd_opl3sa2_mixer(struct snd_opl3sa2 *chip) | 495 | static 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], |