diff options
author | Harley Griggs <hgriggs@posteo.co.uk> | 2014-09-10 14:58:25 -0400 |
---|---|---|
committer | Takashi Iwai <tiwai@suse.de> | 2014-09-22 02:55:15 -0400 |
commit | 5ae0095d00d48be60b2e3cbdb79a35a7d796d96b (patch) | |
tree | 85275e4d3d778f47a8dd7aa3b2f499f567aa7292 /sound/pci/oxygen | |
parent | 8bb1ffdf76276c040a065c4df173dfce98b5ffa3 (diff) |
ALSA: virtuoso: add partial Xonar Xense support
This patch adds partial support for the Xonar Xense.
[trivial coding style fixes by tiwai]
Signed-off-by: Harley Griggs <hgriggs@posteo.co.uk>
Acked-by: Clemens Ladisch <clemens@ladisch.de>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound/pci/oxygen')
-rw-r--r-- | sound/pci/oxygen/virtuoso.c | 1 | ||||
-rw-r--r-- | sound/pci/oxygen/xonar_pcm179x.c | 133 |
2 files changed, 134 insertions, 0 deletions
diff --git a/sound/pci/oxygen/virtuoso.c b/sound/pci/oxygen/virtuoso.c index 7b317a28a19c..83de6fb01021 100644 --- a/sound/pci/oxygen/virtuoso.c +++ b/sound/pci/oxygen/virtuoso.c | |||
@@ -52,6 +52,7 @@ static const struct pci_device_id xonar_ids[] = { | |||
52 | { OXYGEN_PCI_SUBID(0x1043, 0x835d) }, | 52 | { OXYGEN_PCI_SUBID(0x1043, 0x835d) }, |
53 | { OXYGEN_PCI_SUBID(0x1043, 0x835e) }, | 53 | { OXYGEN_PCI_SUBID(0x1043, 0x835e) }, |
54 | { OXYGEN_PCI_SUBID(0x1043, 0x838e) }, | 54 | { OXYGEN_PCI_SUBID(0x1043, 0x838e) }, |
55 | { OXYGEN_PCI_SUBID(0x1043, 0x8428) }, | ||
55 | { OXYGEN_PCI_SUBID(0x1043, 0x8522) }, | 56 | { OXYGEN_PCI_SUBID(0x1043, 0x8522) }, |
56 | { OXYGEN_PCI_SUBID(0x1043, 0x85f4) }, | 57 | { OXYGEN_PCI_SUBID(0x1043, 0x85f4) }, |
57 | { OXYGEN_PCI_SUBID_BROKEN_EEPROM }, | 58 | { OXYGEN_PCI_SUBID_BROKEN_EEPROM }, |
diff --git a/sound/pci/oxygen/xonar_pcm179x.c b/sound/pci/oxygen/xonar_pcm179x.c index 0d6a805e8b62..24109d37ca09 100644 --- a/sound/pci/oxygen/xonar_pcm179x.c +++ b/sound/pci/oxygen/xonar_pcm179x.c | |||
@@ -212,6 +212,9 @@ | |||
212 | #define GPIO_ST_MAGIC 0x0040 | 212 | #define GPIO_ST_MAGIC 0x0040 |
213 | #define GPIO_ST_HP 0x0080 | 213 | #define GPIO_ST_HP 0x0080 |
214 | 214 | ||
215 | #define GPIO_XENSE_OUTPUT_ENABLE (0x0001 | 0x0010 | 0x0020) | ||
216 | #define GPIO_XENSE_SPEAKERS 0x0080 | ||
217 | |||
215 | #define I2C_DEVICE_PCM1796(i) (0x98 + ((i) << 1)) /* 10011, ii, /W=0 */ | 218 | #define I2C_DEVICE_PCM1796(i) (0x98 + ((i) << 1)) /* 10011, ii, /W=0 */ |
216 | #define I2C_DEVICE_CS2000 0x9c /* 100111, 0, /W=0 */ | 219 | #define I2C_DEVICE_CS2000 0x9c /* 100111, 0, /W=0 */ |
217 | 220 | ||
@@ -500,6 +503,51 @@ static void xonar_stx_init(struct oxygen *chip) | |||
500 | xonar_st_init_common(chip); | 503 | xonar_st_init_common(chip); |
501 | } | 504 | } |
502 | 505 | ||
506 | static void xonar_xense_init(struct oxygen *chip) | ||
507 | { | ||
508 | struct xonar_pcm179x *data = chip->model_data; | ||
509 | |||
510 | data->generic.ext_power_reg = OXYGEN_GPI_DATA; | ||
511 | data->generic.ext_power_int_reg = OXYGEN_GPI_INTERRUPT_MASK; | ||
512 | data->generic.ext_power_bit = GPI_EXT_POWER; | ||
513 | xonar_init_ext_power(chip); | ||
514 | |||
515 | data->generic.anti_pop_delay = 100; | ||
516 | data->has_cs2000 = 1; | ||
517 | data->cs2000_regs[CS2000_FUN_CFG_1] = CS2000_REF_CLK_DIV_1; | ||
518 | |||
519 | oxygen_write16(chip, OXYGEN_I2S_A_FORMAT, | ||
520 | OXYGEN_RATE_48000 | | ||
521 | OXYGEN_I2S_FORMAT_I2S | | ||
522 | OXYGEN_I2S_MCLK(MCLK_512) | | ||
523 | OXYGEN_I2S_BITS_16 | | ||
524 | OXYGEN_I2S_MASTER | | ||
525 | OXYGEN_I2S_BCLK_64); | ||
526 | |||
527 | xonar_st_init_i2c(chip); | ||
528 | cs2000_registers_init(chip); | ||
529 | |||
530 | data->generic.output_enable_bit = GPIO_XENSE_OUTPUT_ENABLE; | ||
531 | data->dacs = 1; | ||
532 | data->hp_gain_offset = 2*-18; | ||
533 | |||
534 | pcm1796_init(chip); | ||
535 | |||
536 | oxygen_set_bits16(chip, OXYGEN_GPIO_CONTROL, | ||
537 | GPIO_INPUT_ROUTE | GPIO_ST_HP_REAR | | ||
538 | GPIO_ST_MAGIC | GPIO_XENSE_SPEAKERS); | ||
539 | oxygen_clear_bits16(chip, OXYGEN_GPIO_DATA, | ||
540 | GPIO_INPUT_ROUTE | GPIO_ST_HP_REAR | | ||
541 | GPIO_XENSE_SPEAKERS); | ||
542 | |||
543 | xonar_init_cs53x1(chip); | ||
544 | xonar_enable_output(chip); | ||
545 | |||
546 | snd_component_add(chip->card, "PCM1796"); | ||
547 | snd_component_add(chip->card, "CS5381"); | ||
548 | snd_component_add(chip->card, "CS2000"); | ||
549 | } | ||
550 | |||
503 | static void xonar_d2_cleanup(struct oxygen *chip) | 551 | static void xonar_d2_cleanup(struct oxygen *chip) |
504 | { | 552 | { |
505 | xonar_disable_output(chip); | 553 | xonar_disable_output(chip); |
@@ -862,6 +910,67 @@ static const struct snd_kcontrol_new st_controls[] = { | |||
862 | }, | 910 | }, |
863 | }; | 911 | }; |
864 | 912 | ||
913 | static int xense_output_switch_get(struct snd_kcontrol *ctl, | ||
914 | struct snd_ctl_elem_value *value) | ||
915 | { | ||
916 | struct oxygen *chip = ctl->private_data; | ||
917 | u16 gpio; | ||
918 | |||
919 | gpio = oxygen_read16(chip, OXYGEN_GPIO_DATA); | ||
920 | if (gpio & GPIO_XENSE_SPEAKERS) | ||
921 | value->value.enumerated.item[0] = 0; | ||
922 | else if (!(gpio & GPIO_XENSE_SPEAKERS) && (gpio & GPIO_ST_HP_REAR)) | ||
923 | value->value.enumerated.item[0] = 1; | ||
924 | else | ||
925 | value->value.enumerated.item[0] = 2; | ||
926 | return 0; | ||
927 | } | ||
928 | |||
929 | static int xense_output_switch_put(struct snd_kcontrol *ctl, | ||
930 | struct snd_ctl_elem_value *value) | ||
931 | { | ||
932 | struct oxygen *chip = ctl->private_data; | ||
933 | struct xonar_pcm179x *data = chip->model_data; | ||
934 | u16 gpio_old, gpio; | ||
935 | |||
936 | mutex_lock(&chip->mutex); | ||
937 | gpio_old = oxygen_read16(chip, OXYGEN_GPIO_DATA); | ||
938 | gpio = gpio_old; | ||
939 | switch (value->value.enumerated.item[0]) { | ||
940 | case 0: | ||
941 | gpio |= GPIO_XENSE_SPEAKERS | GPIO_ST_HP_REAR; | ||
942 | break; | ||
943 | case 1: | ||
944 | gpio = (gpio | GPIO_ST_HP_REAR) & ~GPIO_XENSE_SPEAKERS; | ||
945 | break; | ||
946 | case 2: | ||
947 | gpio &= ~(GPIO_XENSE_SPEAKERS | GPIO_ST_HP_REAR); | ||
948 | break; | ||
949 | } | ||
950 | oxygen_write16(chip, OXYGEN_GPIO_DATA, gpio); | ||
951 | data->hp_active = !(gpio & GPIO_XENSE_SPEAKERS); | ||
952 | update_pcm1796_volume(chip); | ||
953 | mutex_unlock(&chip->mutex); | ||
954 | return gpio != gpio_old; | ||
955 | } | ||
956 | |||
957 | static const struct snd_kcontrol_new xense_controls[] = { | ||
958 | { | ||
959 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
960 | .name = "Analog Output", | ||
961 | .info = st_output_switch_info, | ||
962 | .get = xense_output_switch_get, | ||
963 | .put = xense_output_switch_put, | ||
964 | }, | ||
965 | { | ||
966 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
967 | .name = "Headphones Impedance Playback Enum", | ||
968 | .info = st_hp_volume_offset_info, | ||
969 | .get = st_hp_volume_offset_get, | ||
970 | .put = st_hp_volume_offset_put, | ||
971 | }, | ||
972 | }; | ||
973 | |||
865 | static void xonar_line_mic_ac97_switch(struct oxygen *chip, | 974 | static void xonar_line_mic_ac97_switch(struct oxygen *chip, |
866 | unsigned int reg, unsigned int mute) | 975 | unsigned int reg, unsigned int mute) |
867 | { | 976 | { |
@@ -949,6 +1058,23 @@ static int xonar_st_mixer_init(struct oxygen *chip) | |||
949 | return 0; | 1058 | return 0; |
950 | } | 1059 | } |
951 | 1060 | ||
1061 | static int xonar_xense_mixer_init(struct oxygen *chip) | ||
1062 | { | ||
1063 | unsigned int i; | ||
1064 | int err; | ||
1065 | |||
1066 | for (i = 0; i < ARRAY_SIZE(xense_controls); ++i) { | ||
1067 | err = snd_ctl_add(chip->card, | ||
1068 | snd_ctl_new1(&xense_controls[i], chip)); | ||
1069 | if (err < 0) | ||
1070 | return err; | ||
1071 | } | ||
1072 | err = add_pcm1796_controls(chip); | ||
1073 | if (err < 0) | ||
1074 | return err; | ||
1075 | return 0; | ||
1076 | } | ||
1077 | |||
952 | static void dump_pcm1796_registers(struct oxygen *chip, | 1078 | static void dump_pcm1796_registers(struct oxygen *chip, |
953 | struct snd_info_buffer *buffer) | 1079 | struct snd_info_buffer *buffer) |
954 | { | 1080 | { |
@@ -1159,6 +1285,13 @@ int get_xonar_pcm179x_model(struct oxygen *chip, | |||
1159 | chip->model.resume = xonar_stx_resume; | 1285 | chip->model.resume = xonar_stx_resume; |
1160 | chip->model.set_dac_params = set_pcm1796_params; | 1286 | chip->model.set_dac_params = set_pcm1796_params; |
1161 | break; | 1287 | break; |
1288 | case 0x8428: | ||
1289 | chip->model = model_xonar_st; | ||
1290 | chip->model.shortname = "Xonar Xense"; | ||
1291 | chip->model.chip = "AV100"; | ||
1292 | chip->model.init = xonar_xense_init; | ||
1293 | chip->model.mixer_init = xonar_xense_mixer_init; | ||
1294 | break; | ||
1162 | default: | 1295 | default: |
1163 | return -EINVAL; | 1296 | return -EINVAL; |
1164 | } | 1297 | } |