diff options
-rw-r--r-- | sound/pci/ca0106/ca0106.h | 47 | ||||
-rw-r--r-- | sound/pci/ca0106/ca0106_main.c | 11 | ||||
-rw-r--r-- | sound/pci/ca0106/ca0106_mixer.c | 69 |
3 files changed, 122 insertions, 5 deletions
diff --git a/sound/pci/ca0106/ca0106.h b/sound/pci/ca0106/ca0106.h index a0420bc63f0b..7ad03c6afd42 100644 --- a/sound/pci/ca0106/ca0106.h +++ b/sound/pci/ca0106/ca0106.h | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2004 James Courtier-Dutton <James@superbug.demon.co.uk> | 2 | * Copyright (c) 2004 James Courtier-Dutton <James@superbug.demon.co.uk> |
3 | * Driver CA0106 chips. e.g. Sound Blaster Audigy LS and Live 24bit | 3 | * Driver CA0106 chips. e.g. Sound Blaster Audigy LS and Live 24bit |
4 | * Version: 0.0.21 | 4 | * Version: 0.0.22 |
5 | * | 5 | * |
6 | * FEATURES currently supported: | 6 | * FEATURES currently supported: |
7 | * See ca0106_main.c for features. | 7 | * See ca0106_main.c for features. |
@@ -47,6 +47,8 @@ | |||
47 | * Added GPIO info for SB Live 24bit. | 47 | * Added GPIO info for SB Live 24bit. |
48 | * 0.0.21 | 48 | * 0.0.21 |
49 | * Implement support for Line-in capture on SB Live 24bit. | 49 | * Implement support for Line-in capture on SB Live 24bit. |
50 | * 0.0.22 | ||
51 | * Add support for mute control on SB Live 24bit (cards w/ SPI DAC) | ||
50 | * | 52 | * |
51 | * | 53 | * |
52 | * This code was initally based on code from ALSA's emu10k1x.c which is: | 54 | * This code was initally based on code from ALSA's emu10k1x.c which is: |
@@ -552,6 +554,44 @@ | |||
552 | #define CONTROL_CENTER_LFE_CHANNEL 1 | 554 | #define CONTROL_CENTER_LFE_CHANNEL 1 |
553 | #define CONTROL_UNKNOWN_CHANNEL 2 | 555 | #define CONTROL_UNKNOWN_CHANNEL 2 |
554 | 556 | ||
557 | |||
558 | /* Based on WM8768 Datasheet Rev 4.2 page 32 */ | ||
559 | #define SPI_REG_MASK 0x1ff /* 16-bit SPI writes have a 7-bit address */ | ||
560 | #define SPI_REG_SHIFT 9 /* followed by 9 bits of data */ | ||
561 | |||
562 | /* They really do label the bit for the 4th channel "4" and not "3" */ | ||
563 | #define SPI_DMUTE0_REG 9 | ||
564 | #define SPI_DMUTE1_REG 9 | ||
565 | #define SPI_DMUTE2_REG 9 | ||
566 | #define SPI_DMUTE4_REG 15 | ||
567 | #define SPI_DMUTE0_BIT 3 | ||
568 | #define SPI_DMUTE1_BIT 4 | ||
569 | #define SPI_DMUTE2_BIT 5 | ||
570 | #define SPI_DMUTE4_BIT 2 | ||
571 | |||
572 | #define SPI_PHASE0_REG 3 | ||
573 | #define SPI_PHASE1_REG 3 | ||
574 | #define SPI_PHASE2_REG 3 | ||
575 | #define SPI_PHASE4_REG 15 | ||
576 | #define SPI_PHASE0_BIT 6 | ||
577 | #define SPI_PHASE1_BIT 7 | ||
578 | #define SPI_PHASE2_BIT 8 | ||
579 | #define SPI_PHASE4_BIT 3 | ||
580 | |||
581 | #define SPI_PDWN_REG 2 /* power down all DACs */ | ||
582 | #define SPI_PDWN_BIT 2 | ||
583 | #define SPI_DACD0_REG 10 /* power down individual DACs */ | ||
584 | #define SPI_DACD1_REG 10 | ||
585 | #define SPI_DACD2_REG 10 | ||
586 | #define SPI_DACD4_REG 15 | ||
587 | #define SPI_DACD0_BIT 1 | ||
588 | #define SPI_DACD1_BIT 2 | ||
589 | #define SPI_DACD2_BIT 3 | ||
590 | #define SPI_DACD4_BIT 1 | ||
591 | |||
592 | #define SPI_PWRDNALL_REG 10 /* power down everything */ | ||
593 | #define SPI_PWRDNALL_BIT 4 | ||
594 | |||
555 | #include "ca_midi.h" | 595 | #include "ca_midi.h" |
556 | 596 | ||
557 | struct snd_ca0106; | 597 | struct snd_ca0106; |
@@ -611,6 +651,8 @@ struct snd_ca0106 { | |||
611 | 651 | ||
612 | struct snd_ca_midi midi; | 652 | struct snd_ca_midi midi; |
613 | struct snd_ca_midi midi2; | 653 | struct snd_ca_midi midi2; |
654 | |||
655 | u16 spi_dac_reg[16]; | ||
614 | }; | 656 | }; |
615 | 657 | ||
616 | int snd_ca0106_mixer(struct snd_ca0106 *emu); | 658 | int snd_ca0106_mixer(struct snd_ca0106 *emu); |
@@ -627,4 +669,5 @@ void snd_ca0106_ptr_write(struct snd_ca0106 *emu, | |||
627 | 669 | ||
628 | int snd_ca0106_i2c_write(struct snd_ca0106 *emu, u32 reg, u32 value); | 670 | int snd_ca0106_i2c_write(struct snd_ca0106 *emu, u32 reg, u32 value); |
629 | 671 | ||
630 | 672 | int snd_ca0106_spi_write(struct snd_ca0106 * emu, | |
673 | unsigned int data); | ||
diff --git a/sound/pci/ca0106/ca0106_main.c b/sound/pci/ca0106/ca0106_main.c index 58ffa0cacfb1..512fda946c66 100644 --- a/sound/pci/ca0106/ca0106_main.c +++ b/sound/pci/ca0106/ca0106_main.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2004 James Courtier-Dutton <James@superbug.demon.co.uk> | 2 | * Copyright (c) 2004 James Courtier-Dutton <James@superbug.demon.co.uk> |
3 | * Driver CA0106 chips. e.g. Sound Blaster Audigy LS and Live 24bit | 3 | * Driver CA0106 chips. e.g. Sound Blaster Audigy LS and Live 24bit |
4 | * Version: 0.0.23 | 4 | * Version: 0.0.24 |
5 | * | 5 | * |
6 | * FEATURES currently supported: | 6 | * FEATURES currently supported: |
7 | * Front, Rear and Center/LFE. | 7 | * Front, Rear and Center/LFE. |
@@ -79,6 +79,8 @@ | |||
79 | * Add support for MSI K8N Diamond Motherboard with onboard SB Live 24bit without AC97. From kiksen, bug #901 | 79 | * Add support for MSI K8N Diamond Motherboard with onboard SB Live 24bit without AC97. From kiksen, bug #901 |
80 | * 0.0.23 | 80 | * 0.0.23 |
81 | * Implement support for Line-in capture on SB Live 24bit. | 81 | * Implement support for Line-in capture on SB Live 24bit. |
82 | * 0.0.24 | ||
83 | * Add support for mute control on SB Live 24bit (cards w/ SPI DAC) | ||
82 | * | 84 | * |
83 | * BUGS: | 85 | * BUGS: |
84 | * Some stability problems when unloading the snd-ca0106 kernel module. | 86 | * Some stability problems when unloading the snd-ca0106 kernel module. |
@@ -1484,8 +1486,13 @@ static int __devinit snd_ca0106_create(int dev, struct snd_card *card, | |||
1484 | int size, n; | 1486 | int size, n; |
1485 | 1487 | ||
1486 | size = ARRAY_SIZE(spi_dac_init); | 1488 | size = ARRAY_SIZE(spi_dac_init); |
1487 | for (n=0; n < size; n++) | 1489 | for (n = 0; n < size; n++) { |
1490 | int reg = spi_dac_init[n] >> SPI_REG_SHIFT; | ||
1491 | |||
1488 | snd_ca0106_spi_write(chip, spi_dac_init[n]); | 1492 | snd_ca0106_spi_write(chip, spi_dac_init[n]); |
1493 | if (reg < ARRAY_SIZE(chip->spi_dac_reg)) | ||
1494 | chip->spi_dac_reg[reg] = spi_dac_init[n]; | ||
1495 | } | ||
1489 | } | 1496 | } |
1490 | 1497 | ||
1491 | if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, | 1498 | if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, |
diff --git a/sound/pci/ca0106/ca0106_mixer.c b/sound/pci/ca0106/ca0106_mixer.c index a135b9c4c3c8..7fbfe17438b4 100644 --- a/sound/pci/ca0106/ca0106_mixer.c +++ b/sound/pci/ca0106/ca0106_mixer.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2004 James Courtier-Dutton <James@superbug.demon.co.uk> | 2 | * Copyright (c) 2004 James Courtier-Dutton <James@superbug.demon.co.uk> |
3 | * Driver CA0106 chips. e.g. Sound Blaster Audigy LS and Live 24bit | 3 | * Driver CA0106 chips. e.g. Sound Blaster Audigy LS and Live 24bit |
4 | * Version: 0.0.17 | 4 | * Version: 0.0.18 |
5 | * | 5 | * |
6 | * FEATURES currently supported: | 6 | * FEATURES currently supported: |
7 | * See ca0106_main.c for features. | 7 | * See ca0106_main.c for features. |
@@ -39,6 +39,8 @@ | |||
39 | * Modified Copyright message. | 39 | * Modified Copyright message. |
40 | * 0.0.17 | 40 | * 0.0.17 |
41 | * Implement Mic and Line in Capture. | 41 | * Implement Mic and Line in Capture. |
42 | * 0.0.18 | ||
43 | * Add support for mute control on SB Live 24bit (cards w/ SPI DAC) | ||
42 | * | 44 | * |
43 | * This code was initally based on code from ALSA's emu10k1x.c which is: | 45 | * This code was initally based on code from ALSA's emu10k1x.c which is: |
44 | * Copyright (c) by Francisco Moraes <fmoraes@nc.rr.com> | 46 | * Copyright (c) by Francisco Moraes <fmoraes@nc.rr.com> |
@@ -462,6 +464,42 @@ static int snd_ca0106_i2c_volume_put(struct snd_kcontrol *kcontrol, | |||
462 | return change; | 464 | return change; |
463 | } | 465 | } |
464 | 466 | ||
467 | #define spi_mute_info snd_ctl_boolean_mono_info | ||
468 | |||
469 | static int spi_mute_get(struct snd_kcontrol *kcontrol, | ||
470 | struct snd_ctl_elem_value *ucontrol) | ||
471 | { | ||
472 | struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol); | ||
473 | unsigned int reg = kcontrol->private_value >> SPI_REG_SHIFT; | ||
474 | unsigned int bit = kcontrol->private_value & SPI_REG_MASK; | ||
475 | |||
476 | ucontrol->value.integer.value[0] = !(emu->spi_dac_reg[reg] & bit); | ||
477 | return 0; | ||
478 | } | ||
479 | |||
480 | static int spi_mute_put(struct snd_kcontrol *kcontrol, | ||
481 | struct snd_ctl_elem_value *ucontrol) | ||
482 | { | ||
483 | struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol); | ||
484 | unsigned int reg = kcontrol->private_value >> SPI_REG_SHIFT; | ||
485 | unsigned int bit = kcontrol->private_value & SPI_REG_MASK; | ||
486 | int ret; | ||
487 | |||
488 | ret = emu->spi_dac_reg[reg] & bit; | ||
489 | if (ucontrol->value.integer.value[0]) { | ||
490 | if (!ret) /* bit already cleared, do nothing */ | ||
491 | return 0; | ||
492 | emu->spi_dac_reg[reg] &= ~bit; | ||
493 | } else { | ||
494 | if (ret) /* bit already set, do nothing */ | ||
495 | return 0; | ||
496 | emu->spi_dac_reg[reg] |= bit; | ||
497 | } | ||
498 | |||
499 | ret = snd_ca0106_spi_write(emu, emu->spi_dac_reg[reg]); | ||
500 | return ret ? -1 : 1; | ||
501 | } | ||
502 | |||
465 | #define CA_VOLUME(xname,chid,reg) \ | 503 | #define CA_VOLUME(xname,chid,reg) \ |
466 | { \ | 504 | { \ |
467 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ | 505 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ |
@@ -554,6 +592,28 @@ static struct snd_kcontrol_new snd_ca0106_volume_i2c_adc_ctls[] __devinitdata = | |||
554 | I2C_VOLUME("Aux Capture Volume", 3), | 592 | I2C_VOLUME("Aux Capture Volume", 3), |
555 | }; | 593 | }; |
556 | 594 | ||
595 | #define SPI_SWITCH(xname,reg,bit) \ | ||
596 | { \ | ||
597 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ | ||
598 | .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, \ | ||
599 | .info = spi_mute_info, \ | ||
600 | .get = spi_mute_get, \ | ||
601 | .put = spi_mute_put, \ | ||
602 | .private_value = (reg<<SPI_REG_SHIFT) | (1<<bit) \ | ||
603 | } | ||
604 | |||
605 | static struct snd_kcontrol_new snd_ca0106_volume_spi_dac_ctls[] | ||
606 | __devinitdata = { | ||
607 | SPI_SWITCH("Analog Front Playback Switch", | ||
608 | SPI_DMUTE4_REG, SPI_DMUTE4_BIT), | ||
609 | SPI_SWITCH("Analog Rear Playback Switch", | ||
610 | SPI_DMUTE0_REG, SPI_DMUTE0_BIT), | ||
611 | SPI_SWITCH("Analog Center/LFE Playback Switch", | ||
612 | SPI_DMUTE2_REG, SPI_DMUTE2_BIT), | ||
613 | SPI_SWITCH("Analog Side Playback Switch", | ||
614 | SPI_DMUTE1_REG, SPI_DMUTE1_BIT), | ||
615 | }; | ||
616 | |||
557 | static int __devinit remove_ctl(struct snd_card *card, const char *name) | 617 | static int __devinit remove_ctl(struct snd_card *card, const char *name) |
558 | { | 618 | { |
559 | struct snd_ctl_elem_id id; | 619 | struct snd_ctl_elem_id id; |
@@ -650,6 +710,13 @@ int __devinit snd_ca0106_mixer(struct snd_ca0106 *emu) | |||
650 | if (err < 0) | 710 | if (err < 0) |
651 | return err; | 711 | return err; |
652 | } | 712 | } |
713 | if (emu->details->spi_dac == 1) { | ||
714 | for (i = 0; i < ARRAY_SIZE(snd_ca0106_volume_spi_dac_ctls); i++) { | ||
715 | err = snd_ctl_add(card, snd_ctl_new1(&snd_ca0106_volume_spi_dac_ctls[i], emu)); | ||
716 | if (err < 0) | ||
717 | return err; | ||
718 | } | ||
719 | } | ||
653 | return 0; | 720 | return 0; |
654 | } | 721 | } |
655 | 722 | ||