Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 133182
b: refs/heads/master
c: 930738d
h: refs/heads/master
v: v3
  • Loading branch information
Clemens Ladisch authored and Takashi Iwai committed Feb 26, 2009
1 parent 2bfcf49 commit 744bcbf
Show file tree
Hide file tree
Showing 4 changed files with 196 additions and 3 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: eacbb9dba6b4c982a0217ea2c7d15db88d4fda37
refs/heads/master: 930738de602d2ceb0d1c1b368fe2a8d2a974ab72
2 changes: 1 addition & 1 deletion trunk/Documentation/sound/alsa/ALSA-Configuration.txt
Original file line number Diff line number Diff line change
Expand Up @@ -1824,7 +1824,7 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
-------------------

Module for sound cards based on the Asus AV100/AV200 chips,
i.e., Xonar D1, DX, D2, D2X and HDAV1.3 (Deluxe).
i.e., Xonar D1, DX, D2, D2X, HDAV1.3 (Deluxe), and Essence STX.

This module supports autoprobe and multiple cards.

Expand Down
3 changes: 2 additions & 1 deletion trunk/sound/pci/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -744,7 +744,8 @@ config SND_VIRTUOSO
select SND_OXYGEN_LIB
help
Say Y here to include support for sound cards based on the
Asus AV100/AV200 chips, i.e., Xonar D1, DX, D2 and D2X.
Asus AV100/AV200 chips, i.e., Xonar D1, DX, D2, D2X, and
Essence STX.
Support for the HDAV1.3 (Deluxe) is very experimental.

To compile this driver as a module, choose M here: the module
Expand Down
192 changes: 192 additions & 0 deletions trunk/sound/pci/oxygen/virtuoso.c
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,34 @@
* CS4362A: AD0 <- 0
*/

/*
* Xonar Essence STX
* -----------------
*
* CMI8788:
*
* I²C <-> PCM1792A
*
* GPI 0 <- external power present
*
* GPIO 0 -> enable output to speakers
* GPIO 1 -> route HP to front panel (0) or rear jack (1)
* GPIO 2 -> M0 of CS5381
* GPIO 3 -> M1 of CS5381
* GPIO 7 -> route output to speaker jacks (0) or HP (1)
* GPIO 8 -> route input jack to line-in (0) or mic-in (1)
*
* PCM1792A:
*
* AD0 <- 0
*
* H6 daughterboard
* ----------------
*
* GPIO 4 <- 0
* GPIO 5 <- 0
*/

#include <linux/pci.h>
#include <linux/delay.h>
#include <linux/mutex.h>
Expand Down Expand Up @@ -152,6 +180,7 @@ enum {
MODEL_DX,
MODEL_HDAV, /* without daughterboard */
MODEL_HDAV_H6, /* with H6 daughterboard */
MODEL_STX,
};

static struct pci_device_id xonar_ids[] __devinitdata = {
Expand All @@ -160,6 +189,7 @@ static struct pci_device_id xonar_ids[] __devinitdata = {
{ OXYGEN_PCI_SUBID(0x1043, 0x82b7), .driver_data = MODEL_D2X },
{ OXYGEN_PCI_SUBID(0x1043, 0x8314), .driver_data = MODEL_HDAV },
{ OXYGEN_PCI_SUBID(0x1043, 0x834f), .driver_data = MODEL_D1 },
{ OXYGEN_PCI_SUBID(0x1043, 0x835c), .driver_data = MODEL_STX },
{ OXYGEN_PCI_SUBID_BROKEN_EEPROM },
{ }
};
Expand All @@ -184,6 +214,9 @@ MODULE_DEVICE_TABLE(pci, xonar_ids);
#define GPIO_HDAV_DB_H6 0x0000
#define GPIO_HDAV_DB_XX 0x0020

#define GPIO_ST_HP_REAR 0x0002
#define GPIO_ST_HP 0x0080

#define I2C_DEVICE_PCM1796(i) (0x98 + ((i) << 1)) /* 10011, ADx=i, /W=0 */
#define I2C_DEVICE_CS4398 0x9e /* 10011, AD1=1, AD0=1, /W=0 */
#define I2C_DEVICE_CS4362A 0x30 /* 001100, AD0=0, /W=0 */
Expand Down Expand Up @@ -497,6 +530,36 @@ static void xonar_hdav_init(struct oxygen *chip)
snd_component_add(chip->card, "CS5381");
}

static void xonar_stx_init(struct oxygen *chip)
{
struct xonar_data *data = chip->model_data;

oxygen_write16(chip, OXYGEN_2WIRE_BUS_STATUS,
OXYGEN_2WIRE_LENGTH_8 |
OXYGEN_2WIRE_INTERRUPT_MASK |
OXYGEN_2WIRE_SPEED_FAST);

data->anti_pop_delay = 100;
data->dacs = 1;
data->output_enable_bit = GPIO_DX_OUTPUT_ENABLE;
data->ext_power_reg = OXYGEN_GPI_DATA;
data->ext_power_int_reg = OXYGEN_GPI_INTERRUPT_MASK;
data->ext_power_bit = GPI_DX_EXT_POWER;
data->pcm1796_oversampling = PCM1796_OS_64;

pcm1796_init(chip);

oxygen_set_bits16(chip, OXYGEN_GPIO_CONTROL,
GPIO_DX_INPUT_ROUTE | GPIO_ST_HP_REAR | GPIO_ST_HP);
oxygen_clear_bits16(chip, OXYGEN_GPIO_DATA,
GPIO_DX_INPUT_ROUTE | GPIO_ST_HP_REAR | GPIO_ST_HP);

xonar_common_init(chip);

snd_component_add(chip->card, "PCM1792A");
snd_component_add(chip->card, "CS5381");
}

static void xonar_disable_output(struct oxygen *chip)
{
struct xonar_data *data = chip->model_data;
Expand Down Expand Up @@ -524,6 +587,11 @@ static void xonar_hdav_cleanup(struct oxygen *chip)
xonar_disable_output(chip);
}

static void xonar_st_cleanup(struct oxygen *chip)
{
xonar_disable_output(chip);
}

static void xonar_d2_suspend(struct oxygen *chip)
{
xonar_d2_cleanup(chip);
Expand All @@ -540,6 +608,11 @@ static void xonar_hdav_suspend(struct oxygen *chip)
msleep(2);
}

static void xonar_st_suspend(struct oxygen *chip)
{
xonar_st_cleanup(chip);
}

static void xonar_d2_resume(struct oxygen *chip)
{
pcm1796_init(chip);
Expand Down Expand Up @@ -567,6 +640,12 @@ static void xonar_hdav_resume(struct oxygen *chip)
xonar_enable_output(chip);
}

static void xonar_st_resume(struct oxygen *chip)
{
pcm1796_init(chip);
xonar_enable_output(chip);
}

static void xonar_hdav_pcm_hardware_filter(unsigned int channel,
struct snd_pcm_hardware *hardware)
{
Expand Down Expand Up @@ -746,6 +825,72 @@ static const struct snd_kcontrol_new front_panel_switch = {
.private_value = GPIO_DX_FRONT_PANEL,
};

static int st_output_switch_info(struct snd_kcontrol *ctl,
struct snd_ctl_elem_info *info)
{
static const char *const names[3] = {
"Speakers", "Headphones", "FP Headphones"
};

info->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
info->count = 1;
info->value.enumerated.items = 3;
if (info->value.enumerated.item >= 3)
info->value.enumerated.item = 2;
strcpy(info->value.enumerated.name, names[info->value.enumerated.item]);
return 0;
}

static int st_output_switch_get(struct snd_kcontrol *ctl,
struct snd_ctl_elem_value *value)
{
struct oxygen *chip = ctl->private_data;
u16 gpio;

gpio = oxygen_read16(chip, OXYGEN_GPIO_DATA);
if (!(gpio & GPIO_ST_HP))
value->value.enumerated.item[0] = 0;
else if (gpio & GPIO_ST_HP_REAR)
value->value.enumerated.item[0] = 1;
else
value->value.enumerated.item[0] = 2;
return 0;
}


static int st_output_switch_put(struct snd_kcontrol *ctl,
struct snd_ctl_elem_value *value)
{
struct oxygen *chip = ctl->private_data;
u16 gpio_old, gpio;

mutex_lock(&chip->mutex);
gpio_old = oxygen_read16(chip, OXYGEN_GPIO_DATA);
gpio = gpio_old;
switch (value->value.enumerated.item[0]) {
case 0:
gpio &= ~(GPIO_ST_HP | GPIO_ST_HP_REAR);
break;
case 1:
gpio |= GPIO_ST_HP | GPIO_ST_HP_REAR;
break;
case 2:
gpio = (gpio | GPIO_ST_HP) & ~GPIO_ST_HP_REAR;
break;
}
oxygen_write16(chip, OXYGEN_GPIO_DATA, gpio);
mutex_unlock(&chip->mutex);
return gpio != gpio_old;
}

static const struct snd_kcontrol_new st_output_switch = {
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "Analog Output",
.info = st_output_switch_info,
.get = st_output_switch_get,
.put = st_output_switch_put,
};

static void xonar_line_mic_ac97_switch(struct oxygen *chip,
unsigned int reg, unsigned int mute)
{
Expand Down Expand Up @@ -776,6 +921,15 @@ static int xonar_d1_control_filter(struct snd_kcontrol_new *template)
return 0;
}

static int xonar_st_control_filter(struct snd_kcontrol_new *template)
{
if (!strncmp(template->name, "CD Capture ", 11))
return 1; /* no CD input */
if (!strcmp(template->name, "Stereo Upmixing"))
return 1; /* stereo only - we don't need upmixing */
return 0;
}

static int xonar_d2_mixer_init(struct oxygen *chip)
{
return snd_ctl_add(chip->card, snd_ctl_new1(&alt_switch, chip));
Expand All @@ -786,6 +940,11 @@ static int xonar_d1_mixer_init(struct oxygen *chip)
return snd_ctl_add(chip->card, snd_ctl_new1(&front_panel_switch, chip));
}

static int xonar_st_mixer_init(struct oxygen *chip)
{
return snd_ctl_add(chip->card, snd_ctl_new1(&st_output_switch, chip));
}

static const struct oxygen_model model_xonar_d2 = {
.longname = "Asus Virtuoso 200",
.chip = "AV200",
Expand Down Expand Up @@ -872,6 +1031,33 @@ static const struct oxygen_model model_xonar_hdav = {
.adc_i2s_format = OXYGEN_I2S_FORMAT_LJUST,
};

static const struct oxygen_model model_xonar_st = {
.longname = "Asus Virtuoso 100",
.chip = "AV200",
.init = xonar_stx_init,
.control_filter = xonar_st_control_filter,
.mixer_init = xonar_st_mixer_init,
.cleanup = xonar_st_cleanup,
.suspend = xonar_st_suspend,
.resume = xonar_st_resume,
.set_dac_params = set_pcm1796_params,
.set_adc_params = set_cs53x1_params,
.update_dac_volume = update_pcm1796_volume,
.update_dac_mute = update_pcm1796_mute,
.ac97_switch = xonar_line_mic_ac97_switch,
.dac_tlv = pcm1796_db_scale,
.model_data_size = sizeof(struct xonar_data),
.device_config = PLAYBACK_0_TO_I2S |
PLAYBACK_1_TO_SPDIF |
CAPTURE_0_FROM_I2S_2,
.dac_channels = 2,
.dac_volume_min = 255 - 2*60,
.dac_volume_max = 255,
.function_flags = OXYGEN_FUNCTION_2WIRE,
.dac_i2s_format = OXYGEN_I2S_FORMAT_LJUST,
.adc_i2s_format = OXYGEN_I2S_FORMAT_LJUST,
};

static int __devinit get_xonar_model(struct oxygen *chip,
const struct pci_device_id *id)
{
Expand All @@ -881,6 +1067,7 @@ static int __devinit get_xonar_model(struct oxygen *chip,
[MODEL_D2] = &model_xonar_d2,
[MODEL_D2X] = &model_xonar_d2,
[MODEL_HDAV] = &model_xonar_hdav,
[MODEL_STX] = &model_xonar_st,
};
static const char *const names[] = {
[MODEL_D1] = "Xonar D1",
Expand All @@ -889,6 +1076,7 @@ static int __devinit get_xonar_model(struct oxygen *chip,
[MODEL_D2X] = "Xonar D2X",
[MODEL_HDAV] = "Xonar HDAV1.3",
[MODEL_HDAV_H6] = "Xonar HDAV1.3+H6",
[MODEL_STX] = "Xonar Essence STX",
};
unsigned int model = id->driver_data;

Expand Down Expand Up @@ -916,6 +1104,10 @@ static int __devinit get_xonar_model(struct oxygen *chip,
return -ENODEV;
}
break;
case MODEL_STX:
oxygen_clear_bits16(chip, OXYGEN_GPIO_CONTROL,
GPIO_HDAV_DB_MASK);
break;
}

chip->model.shortname = names[model];
Expand Down

0 comments on commit 744bcbf

Please sign in to comment.