From patchwork Wed Sep 10 18:44:18 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Harley Griggs X-Patchwork-Id: 4879661 X-Patchwork-Delegate: tiwai@suse.de Return-Path: X-Original-To: patchwork-alsa-devel@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork1.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.19.201]) by patchwork1.web.kernel.org (Postfix) with ESMTP id ED9159F390 for ; Wed, 10 Sep 2014 18:45:11 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 059CD201C8 for ; Wed, 10 Sep 2014 18:45:11 +0000 (UTC) Received: from alsa0.perex.cz (alsa0.perex.cz [77.48.224.243]) by mail.kernel.org (Postfix) with ESMTP id ACCCD20142 for ; Wed, 10 Sep 2014 18:45:09 +0000 (UTC) Received: by alsa0.perex.cz (Postfix, from userid 1000) id D643C2655BE; Wed, 10 Sep 2014 20:45:03 +0200 (CEST) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Spam-Status: No, score=0.9 required=5.0 tests=BAYES_00,FUZZY_XPILL, NO_DNS_FOR_FROM,UNPARSEABLE_RELAY autolearn=no version=3.3.1 Received: from alsa0.perex.cz (localhost [IPv6:::1]) by alsa0.perex.cz (Postfix) with ESMTP id 6875F265595; Wed, 10 Sep 2014 20:44:53 +0200 (CEST) X-Original-To: alsa-devel@alsa-project.org Delivered-To: alsa-devel@alsa-project.org Received: by alsa0.perex.cz (Postfix, from userid 1000) id 2BB372655B1; Wed, 10 Sep 2014 20:44:52 +0200 (CEST) Received: from mx02.posteo.de (mx02.posteo.de [89.146.194.165]) by alsa0.perex.cz (Postfix) with ESMTP id 10E71265589 for ; Wed, 10 Sep 2014 20:44:31 +0200 (CEST) Received: from localhost (localhost.localdomain [127.0.0.1]) by mx02.posteo.de (Postfix) with ESMTP id DE48825C00A7; Wed, 10 Sep 2014 20:44:30 +0200 (CEST) X-Virus-Scanned: amavisd-new at posteo.de Received: from posteo.de ([10.125.125.178]) (using TLS) by localhost (amavis1.posteo.de [10.125.125.165]) (amavisd-new, port 10026) with ESMTPS id poAqhI_kIyIV; Wed, 10 Sep 2014 20:44:29 +0200 (CEST) Received: from mail.posteo.de (localhost [127.0.0.1]) by mail.posteo.de (Postfix) with ESMTPSA id C41AB2C0104; Wed, 10 Sep 2014 20:44:19 +0200 (CEST) Date: Wed, 10 Sep 2014 19:44:18 +0100 From: Harley Griggs To: Clemens Ladisch In-Reply-To: <5410954B.4060901@ladisch.de> References: <20140910141813.B328C258D256@mx02.posteo.de> <54107077.7030203@ladisch.de> <20140910160422.1B47E25A2113@mx02.posteo.de> <5410954B.4060901@ladisch.de> Mime-Version: 1.0 Message-Id: <20140910184430.DE48825C00A7@mx02.posteo.de> Cc: alsa-devel@alsa-project.org Subject: Re: [alsa-devel] [PATCH] ALSA: virtuoso: add Xonar Xense support X-BeenThere: alsa-devel@alsa-project.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: "Alsa-devel mailing list for ALSA developers - http://www.alsa-project.org" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: alsa-devel-bounces@alsa-project.org Sender: alsa-devel-bounces@alsa-project.org X-Virus-Scanned: ClamAV using ClamSMTP This patch adds partial support for the Xonar Xense. Signed-off-by: Harley Griggs --- sound/pci/oxygen/virtuoso.c | 1 + sound/pci/oxygen/xonar_pcm179x.c | 133 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 134 insertions(+) diff --git a/sound/pci/oxygen/virtuoso.c b/sound/pci/oxygen/virtuoso.c index 7b317a2..83de6fb 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[] = { { OXYGEN_PCI_SUBID(0x1043, 0x835d) }, { OXYGEN_PCI_SUBID(0x1043, 0x835e) }, { OXYGEN_PCI_SUBID(0x1043, 0x838e) }, + { OXYGEN_PCI_SUBID(0x1043, 0x8428) }, { OXYGEN_PCI_SUBID(0x1043, 0x8522) }, { OXYGEN_PCI_SUBID(0x1043, 0x85f4) }, { OXYGEN_PCI_SUBID_BROKEN_EEPROM }, diff --git a/sound/pci/oxygen/xonar_pcm179x.c b/sound/pci/oxygen/xonar_pcm179x.c index e026059..ddf1717 100644 --- a/sound/pci/oxygen/xonar_pcm179x.c +++ b/sound/pci/oxygen/xonar_pcm179x.c @@ -212,6 +212,9 @@ #define GPIO_ST_MAGIC 0x0040 #define GPIO_ST_HP 0x0080 +#define GPIO_XENSE_OUTPUT_ENABLE (0x0001 | 0x0010 | 0x0020) +#define GPIO_XENSE_SPEAKERS 0x0080 + #define I2C_DEVICE_PCM1796(i) (0x98 + ((i) << 1)) /* 10011, ii, /W=0 */ #define I2C_DEVICE_CS2000 0x9c /* 100111, 0, /W=0 */ @@ -499,6 +502,51 @@ static void xonar_stx_init(struct oxygen *chip) xonar_st_init_common(chip); } +static void xonar_xense_init(struct oxygen *chip) +{ + struct xonar_pcm179x *data = chip->model_data; + + data->generic.ext_power_reg = OXYGEN_GPI_DATA; + data->generic.ext_power_int_reg = OXYGEN_GPI_INTERRUPT_MASK; + data->generic.ext_power_bit = GPI_EXT_POWER; + xonar_init_ext_power(chip); + + data->generic.anti_pop_delay = 100; + data->has_cs2000 = 1; + data->cs2000_regs[CS2000_FUN_CFG_1] = CS2000_REF_CLK_DIV_1; + + oxygen_write16(chip, OXYGEN_I2S_A_FORMAT, + OXYGEN_RATE_48000 | + OXYGEN_I2S_FORMAT_I2S | + OXYGEN_I2S_MCLK(MCLK_512) | + OXYGEN_I2S_BITS_16 | + OXYGEN_I2S_MASTER | + OXYGEN_I2S_BCLK_64); + + xonar_st_init_i2c(chip); + cs2000_registers_init(chip); + + data->generic.output_enable_bit = GPIO_XENSE_OUTPUT_ENABLE; + data->dacs = 1; + data->hp_gain_offset = 2*-18; + + pcm1796_init(chip); + + oxygen_set_bits16(chip, OXYGEN_GPIO_CONTROL, + GPIO_INPUT_ROUTE | GPIO_ST_HP_REAR | + GPIO_ST_MAGIC | GPIO_XENSE_SPEAKERS); + oxygen_clear_bits16(chip, OXYGEN_GPIO_DATA, + GPIO_INPUT_ROUTE | GPIO_ST_HP_REAR | + GPIO_XENSE_SPEAKERS); + + xonar_init_cs53x1(chip); + xonar_enable_output(chip); + + snd_component_add(chip->card, "PCM1796"); + snd_component_add(chip->card, "CS5381"); + snd_component_add(chip->card, "CS2000"); +} + static void xonar_d2_cleanup(struct oxygen *chip) { xonar_disable_output(chip); @@ -859,6 +907,67 @@ static const struct snd_kcontrol_new st_controls[] = { }, }; +static int xense_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_XENSE_SPEAKERS) + value->value.enumerated.item[0] = 0; + else if (!(gpio & GPIO_XENSE_SPEAKERS) && (gpio & GPIO_ST_HP_REAR)) + value->value.enumerated.item[0] = 1; + else + value->value.enumerated.item[0] = 2; + return 0; +} + +static int xense_output_switch_put(struct snd_kcontrol *ctl, + struct snd_ctl_elem_value *value) +{ + struct oxygen *chip = ctl->private_data; + struct xonar_pcm179x *data = chip->model_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_XENSE_SPEAKERS | GPIO_ST_HP_REAR; + break; + case 1: + gpio = (gpio | GPIO_ST_HP_REAR) & ~GPIO_XENSE_SPEAKERS; + break; + case 2: + gpio &= ~(GPIO_XENSE_SPEAKERS | GPIO_ST_HP_REAR); + break; + } + oxygen_write16(chip, OXYGEN_GPIO_DATA, gpio); + data->hp_active = !(gpio & GPIO_XENSE_SPEAKERS); + update_pcm1796_volume(chip); + mutex_unlock(&chip->mutex); + return gpio != gpio_old; +} + +static const struct snd_kcontrol_new xense_controls[] = { + { + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .name = "Analog Output", + .info = st_output_switch_info, + .get = xense_output_switch_get, + .put = xense_output_switch_put, + }, + { + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .name = "Headphones Impedance Playback Enum", + .info = st_hp_volume_offset_info, + .get = st_hp_volume_offset_get, + .put = st_hp_volume_offset_put, + }, +}; + static void xonar_line_mic_ac97_switch(struct oxygen *chip, unsigned int reg, unsigned int mute) { @@ -946,6 +1055,23 @@ static int xonar_st_mixer_init(struct oxygen *chip) return 0; } +static int xonar_xense_mixer_init(struct oxygen *chip) +{ + unsigned int i; + int err; + + for (i = 0; i < ARRAY_SIZE(xense_controls); ++i) { + err = snd_ctl_add(chip->card, + snd_ctl_new1(&xense_controls[i], chip)); + if (err < 0) + return err; + } + err = add_pcm1796_controls(chip); + if (err < 0) + return err; + return 0; +} + static void dump_pcm1796_registers(struct oxygen *chip, struct snd_info_buffer *buffer) { @@ -1146,6 +1272,13 @@ int get_xonar_pcm179x_model(struct oxygen *chip, chip->model.resume = xonar_stx_resume; chip->model.set_dac_params = set_pcm1796_params; break; + case 0x8428: + chip->model = model_xonar_st; + chip->model.shortname = "Xonar Xense"; + chip->model.chip = "AV100"; + chip->model.init = xonar_xense_init; + chip->model.mixer_init = xonar_xense_mixer_init; + break; default: return -EINVAL; }