Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Harley Griggs and committed by
Takashi Iwai
5ae0095d 8bb1ffdf

+134
+1
sound/pci/oxygen/virtuoso.c
··· 52 52 { OXYGEN_PCI_SUBID(0x1043, 0x835d) }, 53 53 { OXYGEN_PCI_SUBID(0x1043, 0x835e) }, 54 54 { OXYGEN_PCI_SUBID(0x1043, 0x838e) }, 55 + { OXYGEN_PCI_SUBID(0x1043, 0x8428) }, 55 56 { OXYGEN_PCI_SUBID(0x1043, 0x8522) }, 56 57 { OXYGEN_PCI_SUBID(0x1043, 0x85f4) }, 57 58 { OXYGEN_PCI_SUBID_BROKEN_EEPROM },
+133
sound/pci/oxygen/xonar_pcm179x.c
··· 212 212 #define GPIO_ST_MAGIC 0x0040 213 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 218 #define I2C_DEVICE_PCM1796(i) (0x98 + ((i) << 1)) /* 10011, ii, /W=0 */ 216 219 #define I2C_DEVICE_CS2000 0x9c /* 100111, 0, /W=0 */ 217 220 ··· 501 498 data->generic.ext_power_bit = GPI_EXT_POWER; 502 499 xonar_init_ext_power(chip); 503 500 xonar_st_init_common(chip); 501 + } 502 + 503 + static void xonar_xense_init(struct oxygen *chip) 504 + { 505 + struct xonar_pcm179x *data = chip->model_data; 506 + 507 + data->generic.ext_power_reg = OXYGEN_GPI_DATA; 508 + data->generic.ext_power_int_reg = OXYGEN_GPI_INTERRUPT_MASK; 509 + data->generic.ext_power_bit = GPI_EXT_POWER; 510 + xonar_init_ext_power(chip); 511 + 512 + data->generic.anti_pop_delay = 100; 513 + data->has_cs2000 = 1; 514 + data->cs2000_regs[CS2000_FUN_CFG_1] = CS2000_REF_CLK_DIV_1; 515 + 516 + oxygen_write16(chip, OXYGEN_I2S_A_FORMAT, 517 + OXYGEN_RATE_48000 | 518 + OXYGEN_I2S_FORMAT_I2S | 519 + OXYGEN_I2S_MCLK(MCLK_512) | 520 + OXYGEN_I2S_BITS_16 | 521 + OXYGEN_I2S_MASTER | 522 + OXYGEN_I2S_BCLK_64); 523 + 524 + xonar_st_init_i2c(chip); 525 + cs2000_registers_init(chip); 526 + 527 + data->generic.output_enable_bit = GPIO_XENSE_OUTPUT_ENABLE; 528 + data->dacs = 1; 529 + data->hp_gain_offset = 2*-18; 530 + 531 + pcm1796_init(chip); 532 + 533 + oxygen_set_bits16(chip, OXYGEN_GPIO_CONTROL, 534 + GPIO_INPUT_ROUTE | GPIO_ST_HP_REAR | 535 + GPIO_ST_MAGIC | GPIO_XENSE_SPEAKERS); 536 + oxygen_clear_bits16(chip, OXYGEN_GPIO_DATA, 537 + GPIO_INPUT_ROUTE | GPIO_ST_HP_REAR | 538 + GPIO_XENSE_SPEAKERS); 539 + 540 + xonar_init_cs53x1(chip); 541 + xonar_enable_output(chip); 542 + 543 + snd_component_add(chip->card, "PCM1796"); 544 + snd_component_add(chip->card, "CS5381"); 545 + snd_component_add(chip->card, "CS2000"); 504 546 } 505 547 506 548 static void xonar_d2_cleanup(struct oxygen *chip) ··· 910 862 }, 911 863 }; 912 864 865 + static int xense_output_switch_get(struct snd_kcontrol *ctl, 866 + struct snd_ctl_elem_value *value) 867 + { 868 + struct oxygen *chip = ctl->private_data; 869 + u16 gpio; 870 + 871 + gpio = oxygen_read16(chip, OXYGEN_GPIO_DATA); 872 + if (gpio & GPIO_XENSE_SPEAKERS) 873 + value->value.enumerated.item[0] = 0; 874 + else if (!(gpio & GPIO_XENSE_SPEAKERS) && (gpio & GPIO_ST_HP_REAR)) 875 + value->value.enumerated.item[0] = 1; 876 + else 877 + value->value.enumerated.item[0] = 2; 878 + return 0; 879 + } 880 + 881 + static int xense_output_switch_put(struct snd_kcontrol *ctl, 882 + struct snd_ctl_elem_value *value) 883 + { 884 + struct oxygen *chip = ctl->private_data; 885 + struct xonar_pcm179x *data = chip->model_data; 886 + u16 gpio_old, gpio; 887 + 888 + mutex_lock(&chip->mutex); 889 + gpio_old = oxygen_read16(chip, OXYGEN_GPIO_DATA); 890 + gpio = gpio_old; 891 + switch (value->value.enumerated.item[0]) { 892 + case 0: 893 + gpio |= GPIO_XENSE_SPEAKERS | GPIO_ST_HP_REAR; 894 + break; 895 + case 1: 896 + gpio = (gpio | GPIO_ST_HP_REAR) & ~GPIO_XENSE_SPEAKERS; 897 + break; 898 + case 2: 899 + gpio &= ~(GPIO_XENSE_SPEAKERS | GPIO_ST_HP_REAR); 900 + break; 901 + } 902 + oxygen_write16(chip, OXYGEN_GPIO_DATA, gpio); 903 + data->hp_active = !(gpio & GPIO_XENSE_SPEAKERS); 904 + update_pcm1796_volume(chip); 905 + mutex_unlock(&chip->mutex); 906 + return gpio != gpio_old; 907 + } 908 + 909 + static const struct snd_kcontrol_new xense_controls[] = { 910 + { 911 + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 912 + .name = "Analog Output", 913 + .info = st_output_switch_info, 914 + .get = xense_output_switch_get, 915 + .put = xense_output_switch_put, 916 + }, 917 + { 918 + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 919 + .name = "Headphones Impedance Playback Enum", 920 + .info = st_hp_volume_offset_info, 921 + .get = st_hp_volume_offset_get, 922 + .put = st_hp_volume_offset_put, 923 + }, 924 + }; 925 + 913 926 static void xonar_line_mic_ac97_switch(struct oxygen *chip, 914 927 unsigned int reg, unsigned int mute) 915 928 { ··· 1049 940 for (i = 0; i < ARRAY_SIZE(st_controls); ++i) { 1050 941 err = snd_ctl_add(chip->card, 1051 942 snd_ctl_new1(&st_controls[i], chip)); 943 + if (err < 0) 944 + return err; 945 + } 946 + err = add_pcm1796_controls(chip); 947 + if (err < 0) 948 + return err; 949 + return 0; 950 + } 951 + 952 + static int xonar_xense_mixer_init(struct oxygen *chip) 953 + { 954 + unsigned int i; 955 + int err; 956 + 957 + for (i = 0; i < ARRAY_SIZE(xense_controls); ++i) { 958 + err = snd_ctl_add(chip->card, 959 + snd_ctl_new1(&xense_controls[i], chip)); 1052 960 if (err < 0) 1053 961 return err; 1054 962 } ··· 1284 1158 chip->model.init = xonar_stx_init; 1285 1159 chip->model.resume = xonar_stx_resume; 1286 1160 chip->model.set_dac_params = set_pcm1796_params; 1161 + break; 1162 + case 0x8428: 1163 + chip->model = model_xonar_st; 1164 + chip->model.shortname = "Xonar Xense"; 1165 + chip->model.chip = "AV100"; 1166 + chip->model.init = xonar_xense_init; 1167 + chip->model.mixer_init = xonar_xense_mixer_init; 1287 1168 break; 1288 1169 default: 1289 1170 return -EINVAL;