From patchwork Tue Apr 17 12:32:39 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Marc-Andr=C3=A9_Lureau?= X-Patchwork-Id: 153177 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (Client did not present a certificate) by ozlabs.org (Postfix) with ESMTPS id E5C29B7061 for ; Tue, 17 Apr 2012 23:34:53 +1000 (EST) Received: from localhost ([::1]:38081 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1SK7bL-0002lH-C5 for incoming@patchwork.ozlabs.org; Tue, 17 Apr 2012 08:33:43 -0400 Received: from eggs.gnu.org ([208.118.235.92]:58432) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1SK7b9-0002Lj-0w for qemu-devel@nongnu.org; Tue, 17 Apr 2012 08:33:37 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1SK7b4-0008M3-0g for qemu-devel@nongnu.org; Tue, 17 Apr 2012 08:33:30 -0400 Received: from mail-pz0-f46.google.com ([209.85.210.46]:33970) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1SK7b3-00087r-Ot for qemu-devel@nongnu.org; Tue, 17 Apr 2012 08:33:25 -0400 Received: by mail-pz0-f46.google.com with SMTP id z9so9659423dad.33 for ; Tue, 17 Apr 2012 05:33:24 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=from:to:cc:subject:date:message-id:x-mailer:in-reply-to:references :mime-version:content-type:content-transfer-encoding; bh=9VqbpouGbVa2clQwhx2wODLrh2/urlfOBeBUCurDSik=; b=KQsXyBherxblxrMzV5zEnSW9mpeCs4jcMZCP96ITyZURmPxtRNX9ny3sA8hV6qYEx6 Ji67rvglz+Qdw5iQHlXr5rA5+WWj5W+JIU9jG4tRRMo92W0a1Yjr5YjKO/fKP8KC8gO1 E6OmnqXNYFFyXUwfBDJ8givv3U33HFRznE73+IItZOhqzWLx4ANkzjclErudQgaoJR6k Km8cWl8rNJhU4TpKCeZ8AZ/zo7PZXuu5BwhXVEQEQeRKO1chkYqfrkf9iXjrnoWZsHb7 C+4bAcgjrAmvALfPQohqrTGGmL3eIu/b2Nw1dd3VSuIoGRSsv9+mPJ7SkQW0xVYFlEUQ 0wuw== Received: by 10.68.241.227 with SMTP id wl3mr2201119pbc.122.1334666004903; Tue, 17 Apr 2012 05:33:24 -0700 (PDT) Received: from localhost (140.pool85-58-59.dynamic.orange.es. [85.58.59.140]) by mx.google.com with ESMTPS id va9sm14509198pbc.66.2012.04.17.05.33.21 (version=TLSv1/SSLv3 cipher=OTHER); Tue, 17 Apr 2012 05:33:24 -0700 (PDT) From: "=?UTF-8?q?Marc-Andr=C3=A9=20Lureau?=" To: qemu-devel@nongnu.org Date: Tue, 17 Apr 2012 14:32:39 +0200 Message-Id: <1334665964-3075-6-git-send-email-marcandre.lureau@redhat.com> X-Mailer: git-send-email 1.7.10 In-Reply-To: <1334665964-3075-1-git-send-email-marcandre.lureau@redhat.com> References: <1334665964-3075-1-git-send-email-marcandre.lureau@redhat.com> MIME-Version: 1.0 X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 209.85.210.46 Cc: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= , dlaor@redhat.com, kraxel@redhat.com, areis@redhat.com Subject: [Qemu-devel] [PATCH 05/10] hw/ac97: add support for volume control X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Combine output volume with Master and PCM registers values. Use default values in mixer_reset (). Set volume on post-load to update backend values. v4,v5: - fix some code style Signed-off-by: Marc-André Lureau --- hw/ac97.c | 81 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 81 insertions(+) diff --git a/hw/ac97.c b/hw/ac97.c index f7866ed..177f729 100644 --- a/hw/ac97.c +++ b/hw/ac97.c @@ -436,6 +436,65 @@ static void reset_voices (AC97LinkState *s, uint8_t active[LAST_INDEX]) AUD_set_active_in (s->voice_mc, active[MC_INDEX]); } +static void get_volume (uint16_t vol, uint16_t mask, int inverse, + int *mute, uint8_t *lvol, uint8_t *rvol) +{ + *mute = (vol >> MUTE_SHIFT) & 1; + *rvol = (255 * (vol & mask)) / mask; + *lvol = (255 * ((vol >> 8) & mask)) / mask; + + if (inverse) { + *rvol = 255 - *rvol; + *lvol = 255 - *lvol; + } +} + +static void update_combined_volume_out (AC97LinkState *s) +{ + uint8_t lvol, rvol, plvol, prvol; + int mute, pmute; + + get_volume (mixer_load (s, AC97_Master_Volume_Mute), 0x3f, 1, + &mute, &lvol, &rvol); + /* FIXME: should be 1f according to spec */ + get_volume (mixer_load (s, AC97_PCM_Out_Volume_Mute), 0x3f, 1, + &pmute, &plvol, &prvol); + + mute = mute | pmute; + lvol = (lvol * plvol) / 255; + rvol = (rvol * prvol) / 255; + + AUD_set_volume_out (s->voice_po, mute, lvol, rvol); +} + +static void update_volume_in (AC97LinkState *s) +{ + uint8_t lvol, rvol; + int mute; + + get_volume (mixer_load (s, AC97_Record_Gain_Mute), 0x0f, 0, + &mute, &lvol, &rvol); + + AUD_set_volume_in (s->voice_pi, mute, lvol, rvol); +} + +static void set_volume (AC97LinkState *s, int index, uint32_t val) +{ + mixer_store (s, index, val); + if (index == AC97_Master_Volume_Mute || index == AC97_PCM_Out_Volume_Mute) { + update_combined_volume_out (s); + } else if (index == AC97_Record_Gain_Mute) { + update_volume_in (s); + } +} + +static void record_select (AC97LinkState *s, uint32_t val) +{ + uint8_t rs = val & REC_MASK; + uint8_t ls = (val >> 8) & REC_MASK; + mixer_store (s, AC97_Record_Select, rs | (ls << 8)); +} + static void mixer_reset (AC97LinkState *s) { uint8_t active[LAST_INDEX]; @@ -470,6 +529,11 @@ static void mixer_reset (AC97LinkState *s) mixer_store (s, AC97_PCM_LR_ADC_Rate , 0xbb80); mixer_store (s, AC97_MIC_ADC_Rate , 0xbb80); + record_select (s, 0); + set_volume (s, AC97_Master_Volume_Mute, 0x8000); + set_volume (s, AC97_PCM_Out_Volume_Mute, 0x8808); + set_volume (s, AC97_Line_In_Volume_Mute, 0x8808); + reset_voices (s, active); } @@ -528,6 +592,15 @@ static void nam_writew (void *opaque, uint32_t addr, uint32_t val) val |= mixer_load (s, index) & 0xf; mixer_store (s, index, val); break; + case AC97_PCM_Out_Volume_Mute: + case AC97_Master_Volume_Mute: + case AC97_Record_Gain_Mute: + case AC97_Line_In_Volume_Mute: + set_volume (s, index, val); + break; + case AC97_Record_Select: + record_select (s, val); + break; case AC97_Vendor_ID1: case AC97_Vendor_ID2: dolog ("Attempt to write vendor ID to %#x\n", val); @@ -1080,6 +1153,14 @@ static int ac97_post_load (void *opaque, int version_id) uint8_t active[LAST_INDEX]; AC97LinkState *s = opaque; + record_select (s, mixer_load (s, AC97_Record_Select)); + set_volume (s, AC97_Master_Volume_Mute, + mixer_load (s, AC97_Master_Volume_Mute)); + set_volume (s, AC97_PCM_Out_Volume_Mute, + mixer_load (s, AC97_PCM_Out_Volume_Mute)); + set_volume (s, AC97_Line_In_Volume_Mute, + mixer_load (s, AC97_Line_In_Volume_Mute)); + active[PI_INDEX] = !!(s->bm_regs[PI_INDEX].cr & CR_RPBM); active[PO_INDEX] = !!(s->bm_regs[PO_INDEX].cr & CR_RPBM); active[MC_INDEX] = !!(s->bm_regs[MC_INDEX].cr & CR_RPBM);