Received: by 2002:ac0:a5a6:0:0:0:0:0 with SMTP id m35-v6csp2726423imm; Tue, 4 Sep 2018 09:03:14 -0700 (PDT) X-Google-Smtp-Source: ANB0VdZHdqNZIFhr8eBJIGkQ44dCozYh8P6LCFsNoR+nRGmr2QO/F4UF59HLcAxcy9Nnsj5s1wmP X-Received: by 2002:aa7:800f:: with SMTP id j15-v6mr35642581pfi.174.1536076994331; Tue, 04 Sep 2018 09:03:14 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1536076994; cv=none; d=google.com; s=arc-20160816; b=Uzqzo/DNaqp37kI64N23eiSaB6kv/AV23TbHvnacneDtzFrdXX7HT6ZA6tzqCL3YOk GVtzubYu4i1ptCYAVFUv+Oi0lCK2RgmezenwRPODzv27z8ZKAq3lnsOeDebtwfO7uIPy LA8BFxNJlp273vskfGzRhaTGX1h3zVvvS+RpR+IEwAoZrz78UMXYvdoKankv1OAbDnWe SCHaDfnDZxnh7neXS3TuulNKgKNaeFx+7Sui35h9t/cyL+jLutuYlmstYkKwMqUKklux mOgZIQr0GpJjK5I6OFs4Iu13rFEhZm6OEkAC0GO4Df+Y2tOf8NzjzswA6NJoslCbwQXA h2iQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:references:in-reply-to:message-id:date :subject:cc:to:from:arc-authentication-results; bh=2+J8vS44pvB5ylIfvij4pQLutWg0Ld8OmeI4DAyEpyc=; b=wHP+DppkrGz3DzsbdqGEQSeoBluQCvbgfDerk8nfsGOypTJ7QIkapIM38S6CzoNxrb Xjdb7b8wpULcJe4jq2IkFVOF+tBGhX8ts/1h1/VMUkn+pC3+nPcmqrHofXOmebLpbByn 2TwOSwThV7npBaPfLLy6jpgsuT7VCcaxDe221h2BnAKpHv66+IY2ZuDu9KT4ysvNs9j1 2Ag8lHNfKCpDzKPIN4y214ZvmSF1VyexTZxp7gqRSoVy0BguFbQsR8j0dvplyo3R6RtL egUKIHb9Zx2CfZsp3+2xztLOjVMfyzeSWXeNRDMBlc5E8wlB4NZGmT4HWOom86ALiKi7 +LOg== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id p19-v6si20774562plo.432.2018.09.04.09.02.48; Tue, 04 Sep 2018 09:03:14 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728182AbeIDU0a (ORCPT + 99 others); Tue, 4 Sep 2018 16:26:30 -0400 Received: from mx2.suse.de ([195.135.220.15]:50958 "EHLO mx1.suse.de" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1726200AbeIDUYt (ORCPT ); Tue, 4 Sep 2018 16:24:49 -0400 X-Virus-Scanned: by amavisd-new at test-mx.suse.de Received: from relay1.suse.de (unknown [195.135.220.254]) by mx1.suse.de (Postfix) with ESMTP id D137AB0A1; Tue, 4 Sep 2018 15:59:01 +0000 (UTC) From: Takashi Iwai To: Greg Kroah-Hartman Cc: Eric Anholt , Stefan Wahren , linux-rpi-kernel@lists.infradead.org, linux-kernel@vger.kernel.org Subject: [PATCH 05/29] staging: bcm2835-audio: Fix mute controls, volume handling cleanup Date: Tue, 4 Sep 2018 17:58:34 +0200 Message-Id: <20180904155858.8001-6-tiwai@suse.de> X-Mailer: git-send-email 2.18.0 In-Reply-To: <20180904155858.8001-1-tiwai@suse.de> References: <20180904155858.8001-1-tiwai@suse.de> Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org In the current code, the mute control is dealt in a special manner, modifying the current volume and saving the old volume, etc. This is inconsistent (e.g. change the volume while muted, then unmute), and way too complex. Also, the whole volume handling code has conversion between ALSA volume and raw volume values, which can lead to another inconsistency and complexity. This patch simplifies these points: - The ALSA volume value is saved in chip->volume - volume->mute saves the mute state - The mute state is evaluated only when the actual volume is passed to the hardware, bcm2835_audio_set_ctls() Signed-off-by: Takashi Iwai --- .../vc04_services/bcm2835-audio/bcm2835-ctl.c | 84 +++++++------------ .../vc04_services/bcm2835-audio/bcm2835-pcm.c | 6 +- .../bcm2835-audio/bcm2835-vchiq.c | 32 ++----- .../vc04_services/bcm2835-audio/bcm2835.h | 5 +- 4 files changed, 45 insertions(+), 82 deletions(-) diff --git a/drivers/staging/vc04_services/bcm2835-audio/bcm2835-ctl.c b/drivers/staging/vc04_services/bcm2835-audio/bcm2835-ctl.c index d2f0f609f737..e17b72f21a9d 100644 --- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835-ctl.c +++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835-ctl.c @@ -12,6 +12,21 @@ #define CTRL_VOL_MAX 400 #define CTRL_VOL_MIN -10239 /* originally -10240 */ +static int bcm2835_audio_set_chip_ctls(struct bcm2835_chip *chip) +{ + int i, err = 0; + + /* change ctls for all substreams */ + for (i = 0; i < MAX_SUBSTREAMS; i++) { + if (chip->alsa_stream[i]) { + err = bcm2835_audio_set_ctls(chip->alsa_stream[i]); + if (err < 0) + break; + } + } + return err; +} + static int snd_bcm2835_ctl_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) { @@ -34,29 +49,6 @@ static int snd_bcm2835_ctl_info(struct snd_kcontrol *kcontrol, return 0; } -/* toggles mute on or off depending on the value of nmute, and returns - * 1 if the mute value was changed, otherwise 0 - */ -static int toggle_mute(struct bcm2835_chip *chip, int nmute) -{ - /* if settings are ok, just return 0 */ - if (chip->mute == nmute) - return 0; - - /* if the sound is muted then we need to unmute */ - if (chip->mute == CTRL_VOL_MUTE) { - chip->volume = chip->old_volume; /* copy the old volume back */ - audio_info("Unmuting, old_volume = %d, volume = %d ...\n", chip->old_volume, chip->volume); - } else /* otherwise we mute */ { - chip->old_volume = chip->volume; - chip->volume = 26214; /* set volume to minimum level AKA mute */ - audio_info("Muting, old_volume = %d, volume = %d ...\n", chip->old_volume, chip->volume); - } - - chip->mute = nmute; - return 1; -} - static int snd_bcm2835_ctl_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { @@ -65,7 +57,7 @@ static int snd_bcm2835_ctl_get(struct snd_kcontrol *kcontrol, mutex_lock(&chip->audio_mutex); if (kcontrol->private_value == PCM_PLAYBACK_VOLUME) - ucontrol->value.integer.value[0] = chip2alsa(chip->volume); + ucontrol->value.integer.value[0] = chip->volume; else if (kcontrol->private_value == PCM_PLAYBACK_MUTE) ucontrol->value.integer.value[0] = chip->mute; else if (kcontrol->private_value == PCM_PLAYBACK_DEVICE) @@ -79,38 +71,26 @@ static int snd_bcm2835_ctl_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct bcm2835_chip *chip = snd_kcontrol_chip(kcontrol); + int val, *valp; int changed = 0; - mutex_lock(&chip->audio_mutex); - - if (kcontrol->private_value == PCM_PLAYBACK_VOLUME) { - audio_info("Volume change attempted.. volume = %d new_volume = %d\n", chip->volume, (int)ucontrol->value.integer.value[0]); - if (chip->mute == CTRL_VOL_MUTE) { - /* changed = toggle_mute(chip, CTRL_VOL_UNMUTE); */ - changed = 1; /* should return 0 to signify no change but the mixer takes this as the opposite sign (no idea why) */ - goto unlock; - } - if (changed || (ucontrol->value.integer.value[0] != chip2alsa(chip->volume))) { - chip->volume = alsa2chip(ucontrol->value.integer.value[0]); - changed = 1; - } - - } else if (kcontrol->private_value == PCM_PLAYBACK_MUTE) { - /* Now implemented */ - audio_info(" Mute attempted\n"); - changed = toggle_mute(chip, ucontrol->value.integer.value[0]); + if (kcontrol->private_value == PCM_PLAYBACK_VOLUME) + valp = &chip->volume; + else if (kcontrol->private_value == PCM_PLAYBACK_MUTE) + valp = &chip->mute; + else if (kcontrol->private_value == PCM_PLAYBACK_DEVICE) + valp = &chip->dest; + else + return -EINVAL; - } else if (kcontrol->private_value == PCM_PLAYBACK_DEVICE) { - if (ucontrol->value.integer.value[0] != chip->dest) { - chip->dest = ucontrol->value.integer.value[0]; - changed = 1; - } + val = ucontrol->value.integer.value[0]; + mutex_lock(&chip->audio_mutex); + if (val != *valp) { + *valp = val; + changed = 1; + if (bcm2835_audio_set_chip_ctls(chip)) + dev_err(chip->card->dev, "Failed to set ALSA controls..\n"); } - - if (changed && bcm2835_audio_set_ctls(chip)) - dev_err(chip->card->dev, "Failed to set ALSA controls..\n"); - -unlock: mutex_unlock(&chip->audio_mutex); return changed; } diff --git a/drivers/staging/vc04_services/bcm2835-audio/bcm2835-pcm.c b/drivers/staging/vc04_services/bcm2835-audio/bcm2835-pcm.c index 0be185350f33..9a79d2267df4 100644 --- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835-pcm.c +++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835-pcm.c @@ -280,7 +280,7 @@ static int snd_bcm2835_pcm_prepare(struct snd_pcm_substream *substream) bcm2835_audio_setup(alsa_stream); /* in preparation of the stream, set the controls (volume level) of the stream */ - bcm2835_audio_set_ctls(alsa_stream->chip); + bcm2835_audio_set_ctls(alsa_stream); memset(&alsa_stream->pcm_indirect, 0, sizeof(alsa_stream->pcm_indirect)); @@ -441,7 +441,7 @@ int snd_bcm2835_new_pcm(struct bcm2835_chip *chip, u32 numchannels) strcpy(pcm->name, "bcm2835 ALSA"); chip->pcm = pcm; chip->dest = AUDIO_DEST_AUTO; - chip->volume = alsa2chip(0); + chip->volume = 0; chip->mute = CTRL_VOL_UNMUTE; /*disable mute on startup */ /* set operators */ snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, @@ -498,7 +498,7 @@ int snd_bcm2835_new_simple_pcm(struct bcm2835_chip *chip, strcpy(pcm->name, name); chip->pcm = pcm; chip->dest = route; - chip->volume = alsa2chip(0); + chip->volume = 0; chip->mute = CTRL_VOL_UNMUTE; snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, diff --git a/drivers/staging/vc04_services/bcm2835-audio/bcm2835-vchiq.c b/drivers/staging/vc04_services/bcm2835-audio/bcm2835-vchiq.c index 942a38942c29..8684dc1d0b41 100644 --- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835-vchiq.c +++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835-vchiq.c @@ -460,11 +460,11 @@ int bcm2835_audio_open(struct bcm2835_alsa_stream *alsa_stream) return ret; } -static int bcm2835_audio_set_ctls_chan(struct bcm2835_alsa_stream *alsa_stream, - struct bcm2835_chip *chip) +int bcm2835_audio_set_ctls(struct bcm2835_alsa_stream *alsa_stream) { struct vc_audio_msg m; struct bcm2835_audio_instance *instance = alsa_stream->instance; + struct bcm2835_chip *chip = alsa_stream->chip; int status; int ret; @@ -478,7 +478,10 @@ static int bcm2835_audio_set_ctls_chan(struct bcm2835_alsa_stream *alsa_stream, m.type = VC_AUDIO_MSG_TYPE_CONTROL; m.u.control.dest = chip->dest; - m.u.control.volume = chip->volume; + if (!chip->mute) + m.u.control.volume = CHIP_MIN_VOLUME; + else + m.u.control.volume = alsa2chip(chip->volume); /* Create the message available completion */ init_completion(&instance->msg_avail_comp); @@ -514,27 +517,6 @@ static int bcm2835_audio_set_ctls_chan(struct bcm2835_alsa_stream *alsa_stream, return ret; } -int bcm2835_audio_set_ctls(struct bcm2835_chip *chip) -{ - int i; - int ret = 0; - - LOG_DBG(" Setting ALSA dest(%d), volume(%d)\n", chip->dest, chip->volume); - - /* change ctls for all substreams */ - for (i = 0; i < MAX_SUBSTREAMS; i++) { - if (!chip->alsa_stream[i]) - continue; - if (bcm2835_audio_set_ctls_chan(chip->alsa_stream[i], chip) != 0) { - LOG_ERR("Couldn't set the controls for stream %d\n", i); - ret = -1; - } else { - LOG_DBG(" Controls set for stream %d\n", i); - } - } - return ret; -} - int bcm2835_audio_set_params(struct bcm2835_alsa_stream *alsa_stream, unsigned int channels, unsigned int samplerate, unsigned int bps) @@ -548,7 +530,7 @@ int bcm2835_audio_set_params(struct bcm2835_alsa_stream *alsa_stream, channels, samplerate, bps); /* resend ctls - alsa_stream may not have been open when first send */ - ret = bcm2835_audio_set_ctls_chan(alsa_stream, alsa_stream->chip); + ret = bcm2835_audio_set_ctls(alsa_stream); if (ret) { LOG_ERR(" Alsa controls not supported\n"); return -EINVAL; diff --git a/drivers/staging/vc04_services/bcm2835-audio/bcm2835.h b/drivers/staging/vc04_services/bcm2835-audio/bcm2835.h index c0e7df4914ed..8ee25a837b08 100644 --- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835.h +++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835.h @@ -74,6 +74,8 @@ enum { // convert chip to alsa volume #define chip2alsa(vol) -(((vol) * 100) >> 8) +#define CHIP_MIN_VOLUME 26214 /* minimum level aka mute */ + /* Some constants for values .. */ enum snd_bcm2835_route { AUDIO_DEST_AUTO = 0, @@ -102,7 +104,6 @@ struct bcm2835_chip { struct bcm2835_alsa_stream *alsa_stream[MAX_SUBSTREAMS]; int volume; - int old_volume; /* stores the volume value whist muted */ int dest; int mute; @@ -160,7 +161,7 @@ int bcm2835_audio_set_params(struct bcm2835_alsa_stream *alsa_stream, int bcm2835_audio_setup(struct bcm2835_alsa_stream *alsa_stream); int bcm2835_audio_start(struct bcm2835_alsa_stream *alsa_stream); int bcm2835_audio_stop(struct bcm2835_alsa_stream *alsa_stream); -int bcm2835_audio_set_ctls(struct bcm2835_chip *chip); +int bcm2835_audio_set_ctls(struct bcm2835_alsa_stream *alsa_stream); int bcm2835_audio_write(struct bcm2835_alsa_stream *alsa_stream, unsigned int count, void *src); -- 2.18.0