aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorClemens Ladisch <clemens@ladisch.de>2009-02-26 03:27:20 -0500
committerTakashi Iwai <tiwai@suse.de>2009-02-26 03:39:08 -0500
commit930738de602d2ceb0d1c1b368fe2a8d2a974ab72 (patch)
treedcf30656424e965026567b6e122a82b56af97989
parenteacbb9dba6b4c982a0217ea2c7d15db88d4fda37 (diff)
sound: virtuoso: add Xonar Essence STX support
Add support for the Asus Xonar Essence STX sound card. Signed-off-by: Clemens Ladisch <clemens@ladisch.de> Signed-off-by: Takashi Iwai <tiwai@suse.de>
-rw-r--r--Documentation/sound/alsa/ALSA-Configuration.txt2
-rw-r--r--sound/pci/Kconfig3
-rw-r--r--sound/pci/oxygen/virtuoso.c192
3 files changed, 195 insertions, 2 deletions
diff --git a/Documentation/sound/alsa/ALSA-Configuration.txt b/Documentation/sound/alsa/ALSA-Configuration.txt
index 841a9365d5fd..1356d2a6772b 100644
--- a/Documentation/sound/alsa/ALSA-Configuration.txt
+++ b/Documentation/sound/alsa/ALSA-Configuration.txt
@@ -1824,7 +1824,7 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
1824 ------------------- 1824 -------------------
1825 1825
1826 Module for sound cards based on the Asus AV100/AV200 chips, 1826 Module for sound cards based on the Asus AV100/AV200 chips,
1827 i.e., Xonar D1, DX, D2, D2X and HDAV1.3 (Deluxe). 1827 i.e., Xonar D1, DX, D2, D2X, HDAV1.3 (Deluxe), and Essence STX.
1828 1828
1829 This module supports autoprobe and multiple cards. 1829 This module supports autoprobe and multiple cards.
1830 1830
diff --git a/sound/pci/Kconfig b/sound/pci/Kconfig
index 82b9bddcdcd6..21d117ada84b 100644
--- a/sound/pci/Kconfig
+++ b/sound/pci/Kconfig
@@ -744,7 +744,8 @@ config SND_VIRTUOSO
744 select SND_OXYGEN_LIB 744 select SND_OXYGEN_LIB
745 help 745 help
746 Say Y here to include support for sound cards based on the 746 Say Y here to include support for sound cards based on the
747 Asus AV100/AV200 chips, i.e., Xonar D1, DX, D2 and D2X. 747 Asus AV100/AV200 chips, i.e., Xonar D1, DX, D2, D2X, and
748 Essence STX.
748 Support for the HDAV1.3 (Deluxe) is very experimental. 749 Support for the HDAV1.3 (Deluxe) is very experimental.
749 750
750 To compile this driver as a module, choose M here: the module 751 To compile this driver as a module, choose M here: the module
diff --git a/sound/pci/oxygen/virtuoso.c b/sound/pci/oxygen/virtuoso.c
index 00dc97806f1b..bc5ce11c8b14 100644
--- a/sound/pci/oxygen/virtuoso.c
+++ b/sound/pci/oxygen/virtuoso.c
@@ -112,6 +112,34 @@
112 * CS4362A: AD0 <- 0 112 * CS4362A: AD0 <- 0
113 */ 113 */
114 114
115/*
116 * Xonar Essence STX
117 * -----------------
118 *
119 * CMI8788:
120 *
121 * I²C <-> PCM1792A
122 *
123 * GPI 0 <- external power present
124 *
125 * GPIO 0 -> enable output to speakers
126 * GPIO 1 -> route HP to front panel (0) or rear jack (1)
127 * GPIO 2 -> M0 of CS5381
128 * GPIO 3 -> M1 of CS5381
129 * GPIO 7 -> route output to speaker jacks (0) or HP (1)
130 * GPIO 8 -> route input jack to line-in (0) or mic-in (1)
131 *
132 * PCM1792A:
133 *
134 * AD0 <- 0
135 *
136 * H6 daughterboard
137 * ----------------
138 *
139 * GPIO 4 <- 0
140 * GPIO 5 <- 0
141 */
142
115#include <linux/pci.h> 143#include <linux/pci.h>
116#include <linux/delay.h> 144#include <linux/delay.h>
117#include <linux/mutex.h> 145#include <linux/mutex.h>
@@ -152,6 +180,7 @@ enum {
152 MODEL_DX, 180 MODEL_DX,
153 MODEL_HDAV, /* without daughterboard */ 181 MODEL_HDAV, /* without daughterboard */
154 MODEL_HDAV_H6, /* with H6 daughterboard */ 182 MODEL_HDAV_H6, /* with H6 daughterboard */
183 MODEL_STX,
155}; 184};
156 185
157static struct pci_device_id xonar_ids[] __devinitdata = { 186static struct pci_device_id xonar_ids[] __devinitdata = {
@@ -160,6 +189,7 @@ static struct pci_device_id xonar_ids[] __devinitdata = {
160 { OXYGEN_PCI_SUBID(0x1043, 0x82b7), .driver_data = MODEL_D2X }, 189 { OXYGEN_PCI_SUBID(0x1043, 0x82b7), .driver_data = MODEL_D2X },
161 { OXYGEN_PCI_SUBID(0x1043, 0x8314), .driver_data = MODEL_HDAV }, 190 { OXYGEN_PCI_SUBID(0x1043, 0x8314), .driver_data = MODEL_HDAV },
162 { OXYGEN_PCI_SUBID(0x1043, 0x834f), .driver_data = MODEL_D1 }, 191 { OXYGEN_PCI_SUBID(0x1043, 0x834f), .driver_data = MODEL_D1 },
192 { OXYGEN_PCI_SUBID(0x1043, 0x835c), .driver_data = MODEL_STX },
163 { OXYGEN_PCI_SUBID_BROKEN_EEPROM }, 193 { OXYGEN_PCI_SUBID_BROKEN_EEPROM },
164 { } 194 { }
165}; 195};
@@ -184,6 +214,9 @@ MODULE_DEVICE_TABLE(pci, xonar_ids);
184#define GPIO_HDAV_DB_H6 0x0000 214#define GPIO_HDAV_DB_H6 0x0000
185#define GPIO_HDAV_DB_XX 0x0020 215#define GPIO_HDAV_DB_XX 0x0020
186 216
217#define GPIO_ST_HP_REAR 0x0002
218#define GPIO_ST_HP 0x0080
219
187#define I2C_DEVICE_PCM1796(i) (0x98 + ((i) << 1)) /* 10011, ADx=i, /W=0 */ 220#define I2C_DEVICE_PCM1796(i) (0x98 + ((i) << 1)) /* 10011, ADx=i, /W=0 */
188#define I2C_DEVICE_CS4398 0x9e /* 10011, AD1=1, AD0=1, /W=0 */ 221#define I2C_DEVICE_CS4398 0x9e /* 10011, AD1=1, AD0=1, /W=0 */
189#define I2C_DEVICE_CS4362A 0x30 /* 001100, AD0=0, /W=0 */ 222#define I2C_DEVICE_CS4362A 0x30 /* 001100, AD0=0, /W=0 */
@@ -497,6 +530,36 @@ static void xonar_hdav_init(struct oxygen *chip)
497 snd_component_add(chip->card, "CS5381"); 530 snd_component_add(chip->card, "CS5381");
498} 531}
499 532
533static void xonar_stx_init(struct oxygen *chip)
534{
535 struct xonar_data *data = chip->model_data;
536
537 oxygen_write16(chip, OXYGEN_2WIRE_BUS_STATUS,
538 OXYGEN_2WIRE_LENGTH_8 |
539 OXYGEN_2WIRE_INTERRUPT_MASK |
540 OXYGEN_2WIRE_SPEED_FAST);
541
542 data->anti_pop_delay = 100;
543 data->dacs = 1;
544 data->output_enable_bit = GPIO_DX_OUTPUT_ENABLE;
545 data->ext_power_reg = OXYGEN_GPI_DATA;
546 data->ext_power_int_reg = OXYGEN_GPI_INTERRUPT_MASK;
547 data->ext_power_bit = GPI_DX_EXT_POWER;
548 data->pcm1796_oversampling = PCM1796_OS_64;
549
550 pcm1796_init(chip);
551
552 oxygen_set_bits16(chip, OXYGEN_GPIO_CONTROL,
553 GPIO_DX_INPUT_ROUTE | GPIO_ST_HP_REAR | GPIO_ST_HP);
554 oxygen_clear_bits16(chip, OXYGEN_GPIO_DATA,
555 GPIO_DX_INPUT_ROUTE | GPIO_ST_HP_REAR | GPIO_ST_HP);
556
557 xonar_common_init(chip);
558
559 snd_component_add(chip->card, "PCM1792A");
560 snd_component_add(chip->card, "CS5381");
561}
562
500static void xonar_disable_output(struct oxygen *chip) 563static void xonar_disable_output(struct oxygen *chip)
501{ 564{
502 struct xonar_data *data = chip->model_data; 565 struct xonar_data *data = chip->model_data;
@@ -524,6 +587,11 @@ static void xonar_hdav_cleanup(struct oxygen *chip)
524 xonar_disable_output(chip); 587 xonar_disable_output(chip);
525} 588}
526 589
590static void xonar_st_cleanup(struct oxygen *chip)
591{
592 xonar_disable_output(chip);
593}
594
527static void xonar_d2_suspend(struct oxygen *chip) 595static void xonar_d2_suspend(struct oxygen *chip)
528{ 596{
529 xonar_d2_cleanup(chip); 597 xonar_d2_cleanup(chip);
@@ -540,6 +608,11 @@ static void xonar_hdav_suspend(struct oxygen *chip)
540 msleep(2); 608 msleep(2);
541} 609}
542 610
611static void xonar_st_suspend(struct oxygen *chip)
612{
613 xonar_st_cleanup(chip);
614}
615
543static void xonar_d2_resume(struct oxygen *chip) 616static void xonar_d2_resume(struct oxygen *chip)
544{ 617{
545 pcm1796_init(chip); 618 pcm1796_init(chip);
@@ -567,6 +640,12 @@ static void xonar_hdav_resume(struct oxygen *chip)
567 xonar_enable_output(chip); 640 xonar_enable_output(chip);
568} 641}
569 642
643static void xonar_st_resume(struct oxygen *chip)
644{
645 pcm1796_init(chip);
646 xonar_enable_output(chip);
647}
648
570static void xonar_hdav_pcm_hardware_filter(unsigned int channel, 649static void xonar_hdav_pcm_hardware_filter(unsigned int channel,
571 struct snd_pcm_hardware *hardware) 650 struct snd_pcm_hardware *hardware)
572{ 651{
@@ -746,6 +825,72 @@ static const struct snd_kcontrol_new front_panel_switch = {
746 .private_value = GPIO_DX_FRONT_PANEL, 825 .private_value = GPIO_DX_FRONT_PANEL,
747}; 826};
748 827
828static int st_output_switch_info(struct snd_kcontrol *ctl,
829 struct snd_ctl_elem_info *info)
830{
831 static const char *const names[3] = {
832 "Speakers", "Headphones", "FP Headphones"
833 };
834
835 info->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
836 info->count = 1;
837 info->value.enumerated.items = 3;
838 if (info->value.enumerated.item >= 3)
839 info->value.enumerated.item = 2;
840 strcpy(info->value.enumerated.name, names[info->value.enumerated.item]);
841 return 0;
842}
843
844static int st_output_switch_get(struct snd_kcontrol *ctl,
845 struct snd_ctl_elem_value *value)
846{
847 struct oxygen *chip = ctl->private_data;
848 u16 gpio;
849
850 gpio = oxygen_read16(chip, OXYGEN_GPIO_DATA);
851 if (!(gpio & GPIO_ST_HP))
852 value->value.enumerated.item[0] = 0;
853 else if (gpio & GPIO_ST_HP_REAR)
854 value->value.enumerated.item[0] = 1;
855 else
856 value->value.enumerated.item[0] = 2;
857 return 0;
858}
859
860
861static int st_output_switch_put(struct snd_kcontrol *ctl,
862 struct snd_ctl_elem_value *value)
863{
864 struct oxygen *chip = ctl->private_data;
865 u16 gpio_old, gpio;
866
867 mutex_lock(&chip->mutex);
868 gpio_old = oxygen_read16(chip, OXYGEN_GPIO_DATA);
869 gpio = gpio_old;
870 switch (value->value.enumerated.item[0]) {
871 case 0:
872 gpio &= ~(GPIO_ST_HP | GPIO_ST_HP_REAR);
873 break;
874 case 1:
875 gpio |= GPIO_ST_HP | GPIO_ST_HP_REAR;
876 break;
877 case 2:
878 gpio = (gpio | GPIO_ST_HP) & ~GPIO_ST_HP_REAR;
879 break;
880 }
881 oxygen_write16(chip, OXYGEN_GPIO_DATA, gpio);
882 mutex_unlock(&chip->mutex);
883 return gpio != gpio_old;
884}
885
886static const struct snd_kcontrol_new st_output_switch = {
887 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
888 .name = "Analog Output",
889 .info = st_output_switch_info,
890 .get = st_output_switch_get,
891 .put = st_output_switch_put,
892};
893
749static void xonar_line_mic_ac97_switch(struct oxygen *chip, 894static void xonar_line_mic_ac97_switch(struct oxygen *chip,
750 unsigned int reg, unsigned int mute) 895 unsigned int reg, unsigned int mute)
751{ 896{
@@ -776,6 +921,15 @@ static int xonar_d1_control_filter(struct snd_kcontrol_new *template)
776 return 0; 921 return 0;
777} 922}
778 923
924static int xonar_st_control_filter(struct snd_kcontrol_new *template)
925{
926 if (!strncmp(template->name, "CD Capture ", 11))
927 return 1; /* no CD input */
928 if (!strcmp(template->name, "Stereo Upmixing"))
929 return 1; /* stereo only - we don't need upmixing */
930 return 0;
931}
932
779static int xonar_d2_mixer_init(struct oxygen *chip) 933static int xonar_d2_mixer_init(struct oxygen *chip)
780{ 934{
781 return snd_ctl_add(chip->card, snd_ctl_new1(&alt_switch, chip)); 935 return snd_ctl_add(chip->card, snd_ctl_new1(&alt_switch, chip));
@@ -786,6 +940,11 @@ static int xonar_d1_mixer_init(struct oxygen *chip)
786 return snd_ctl_add(chip->card, snd_ctl_new1(&front_panel_switch, chip)); 940 return snd_ctl_add(chip->card, snd_ctl_new1(&front_panel_switch, chip));
787} 941}
788 942
943static int xonar_st_mixer_init(struct oxygen *chip)
944{
945 return snd_ctl_add(chip->card, snd_ctl_new1(&st_output_switch, chip));
946}
947
789static const struct oxygen_model model_xonar_d2 = { 948static const struct oxygen_model model_xonar_d2 = {
790 .longname = "Asus Virtuoso 200", 949 .longname = "Asus Virtuoso 200",
791 .chip = "AV200", 950 .chip = "AV200",
@@ -872,6 +1031,33 @@ static const struct oxygen_model model_xonar_hdav = {
872 .adc_i2s_format = OXYGEN_I2S_FORMAT_LJUST, 1031 .adc_i2s_format = OXYGEN_I2S_FORMAT_LJUST,
873}; 1032};
874 1033
1034static const struct oxygen_model model_xonar_st = {
1035 .longname = "Asus Virtuoso 100",
1036 .chip = "AV200",
1037 .init = xonar_stx_init,
1038 .control_filter = xonar_st_control_filter,
1039 .mixer_init = xonar_st_mixer_init,
1040 .cleanup = xonar_st_cleanup,
1041 .suspend = xonar_st_suspend,
1042 .resume = xonar_st_resume,
1043 .set_dac_params = set_pcm1796_params,
1044 .set_adc_params = set_cs53x1_params,
1045 .update_dac_volume = update_pcm1796_volume,
1046 .update_dac_mute = update_pcm1796_mute,
1047 .ac97_switch = xonar_line_mic_ac97_switch,
1048 .dac_tlv = pcm1796_db_scale,
1049 .model_data_size = sizeof(struct xonar_data),
1050 .device_config = PLAYBACK_0_TO_I2S |
1051 PLAYBACK_1_TO_SPDIF |
1052 CAPTURE_0_FROM_I2S_2,
1053 .dac_channels = 2,
1054 .dac_volume_min = 255 - 2*60,
1055 .dac_volume_max = 255,
1056 .function_flags = OXYGEN_FUNCTION_2WIRE,
1057 .dac_i2s_format = OXYGEN_I2S_FORMAT_LJUST,
1058 .adc_i2s_format = OXYGEN_I2S_FORMAT_LJUST,
1059};
1060
875static int __devinit get_xonar_model(struct oxygen *chip, 1061static int __devinit get_xonar_model(struct oxygen *chip,
876 const struct pci_device_id *id) 1062 const struct pci_device_id *id)
877{ 1063{
@@ -881,6 +1067,7 @@ static int __devinit get_xonar_model(struct oxygen *chip,
881 [MODEL_D2] = &model_xonar_d2, 1067 [MODEL_D2] = &model_xonar_d2,
882 [MODEL_D2X] = &model_xonar_d2, 1068 [MODEL_D2X] = &model_xonar_d2,
883 [MODEL_HDAV] = &model_xonar_hdav, 1069 [MODEL_HDAV] = &model_xonar_hdav,
1070 [MODEL_STX] = &model_xonar_st,
884 }; 1071 };
885 static const char *const names[] = { 1072 static const char *const names[] = {
886 [MODEL_D1] = "Xonar D1", 1073 [MODEL_D1] = "Xonar D1",
@@ -889,6 +1076,7 @@ static int __devinit get_xonar_model(struct oxygen *chip,
889 [MODEL_D2X] = "Xonar D2X", 1076 [MODEL_D2X] = "Xonar D2X",
890 [MODEL_HDAV] = "Xonar HDAV1.3", 1077 [MODEL_HDAV] = "Xonar HDAV1.3",
891 [MODEL_HDAV_H6] = "Xonar HDAV1.3+H6", 1078 [MODEL_HDAV_H6] = "Xonar HDAV1.3+H6",
1079 [MODEL_STX] = "Xonar Essence STX",
892 }; 1080 };
893 unsigned int model = id->driver_data; 1081 unsigned int model = id->driver_data;
894 1082
@@ -916,6 +1104,10 @@ static int __devinit get_xonar_model(struct oxygen *chip,
916 return -ENODEV; 1104 return -ENODEV;
917 } 1105 }
918 break; 1106 break;
1107 case MODEL_STX:
1108 oxygen_clear_bits16(chip, OXYGEN_GPIO_CONTROL,
1109 GPIO_HDAV_DB_MASK);
1110 break;
919 } 1111 }
920 1112
921 chip->model.shortname = names[model]; 1113 chip->model.shortname = names[model];