From nobody Sun Jun 14 11:28:32 2026 Received: from mail-dy1-f169.google.com (mail-dy1-f169.google.com [74.125.82.169]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 0600036308D for ; Thu, 2 Apr 2026 14:45:26 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=74.125.82.169 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1775141128; cv=none; b=NoNs9TNq4H9bCV5pMRQw+ogCVbNy53ErX4+n45ByPJJLh5ms+oz3KVlhKMQtvq+dJwLL3deHHcd3NrEcB3GBdFkUX2OrzdjTd2kpLw8EbyD9o//atMognIaWbPPI5JpWyCosG4b2ccidsC7jztyog2rF8swbT6RldxBKV8My4Yk= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1775141128; c=relaxed/simple; bh=g8JAC6BSLChGNHkt6cn4WUEj8jJIPs2Kb/3zn2v9Uu0=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:To:Cc; b=CEAWWFg5QDMIpC5BG+fCD8lIShfHgHRkIlWqXafFbeRGKsdY8HD9i1vpnRHFhxQZdv0dPli2Wi7YjLfCzmz/BmddsF4O+nlI7N9Z+MfAVq/Up7Ghe1uk+EzKbwT41fKfeRZNBdRSk8QagYm8SlDbcfwel6D7s82IEugEcO5iAOQ= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=ovBE4cSb; arc=none smtp.client-ip=74.125.82.169 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="ovBE4cSb" Received: by mail-dy1-f169.google.com with SMTP id 5a478bee46e88-2c7d8bbad06so2269928eec.1 for ; Thu, 02 Apr 2026 07:45:26 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1775141126; x=1775745926; darn=vger.kernel.org; h=cc:to:message-id:content-transfer-encoding:mime-version:subject :date:from:from:to:cc:subject:date:message-id:reply-to; bh=ilI3/se0eNWB3LAafrjSlhG9sR6mQT2nndyVtmfkrdQ=; b=ovBE4cSbf4A7vipPVGptxiWYjkVPIXsvd9zwq8KthPeubWvX3DcL68mSb8zVGA+ewr DUpyjOxCGOPQFlxnYQ1fnpimJvmvcwTJmdRO8PsGRkf0KwWoU4ApDJFvnZ72zqcywfBA 6hMAd9ePjUq5BKjZDOGA7l+NT1o9WWHAZAGxUPGd/T+6y9+3DBgWxHH3srtUKhhUTocB lCVuzmNF55JVHFXH6LLMvfnFuR1kY+n0d8HmKcgwUptab+cM5DV5jXB56ziHjwTzffQp XbjZe5G95OoqnNOeLzxffwH7e/xLaPhC/EYMRUhq2Y+fg6lbk4mSNLZNN/jaxY7qqJDs bbEw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1775141126; x=1775745926; h=cc:to:message-id:content-transfer-encoding:mime-version:subject :date:from:x-gm-gg:x-gm-message-state:from:to:cc:subject:date :message-id:reply-to; bh=ilI3/se0eNWB3LAafrjSlhG9sR6mQT2nndyVtmfkrdQ=; b=YO/3Bg+qe6npF80JFSu5FJa8NdtkOkqJuFDC5eyjZ2+WIBoq4OFAS7YBmfIvxHnkAm eq2iT4GpOHUQ9oCaPooJhHlwTWSpZTbyLfU7Bb6mpKI59UwsvkoEtHXFCdhM8FlrjI9F 5ZSB6hXhTD5u074bvRRPG7yYXzNukj14OkkwyL/2OkWbFdUKzu6xZtfIjxjyXJFFrTYj /aZO7CHfJBsCf5HOeTcBvWomtFH7vLE98BbdEBYuij+v+yd6h+yBC1Uuqyrba8LRQNmI 6jcogLYBu1fRL+KT68MwsAF43lao6UUhg9PtdURgSEI3mg9vX5HeVPdjIKhDZFPHxfyq p7ng== X-Forwarded-Encrypted: i=1; AJvYcCXiDk/5wzU06iCXQlXVdHNeVYSV5k+l+CANcqMOZ8d37bo9Ja+90Ktoj6CCRYXVL4emD0wSrz1Y5oUxRVs=@vger.kernel.org X-Gm-Message-State: AOJu0YxxXBcSijgHjXTYOsuEU261WOlmEj2Np5IX4VamuAv4/gYmbRQm gWW2l9zQXJHXgtJ/RaLhr4rIHUl+G0jqENLtUQ+skgnqtKtM+NpSoNlt X-Gm-Gg: AeBDievmkEUlRinRC4KYWp/AWOZrgt36G7VQx7MxZaiwiWn77BCNq65Gzq09D2zZCL8 LK/icrIqlbaP5RiSwiYWmkMkOw/krubR7E0aQDMPGhwE7b2ayFRcuwk0IFMDTyXXgOQhlH9iV+2 c2n1wtoBpaV75UFbqsgS9DMttRzvwmCzaywESarNUgoxhOCRoihg9DF9iprJ1kqNRYWT3+nnZT5 1t4CwPjMHYIqjgetWJSP5A/Ly8R76mH8EcLY+fQ3ld1KACEkOKrIeMk0XLW5EOf8VuTeODePeDg 5eEa8982Mvke8gQfzVJVTbNpgHeOBRdRfMP+nut3TUKGuGtTlKfw0bNwjAQWRJvPT4QMOOYmtiJ HNDMFNSmuya5T1ouur93nq/AkfXtQM6WjO1HePPgsyF5T/LgI28DStau83yZFLiwBPUZ9vc+M6W xl+onq4l3zKRoYOZPIJKthH/q9HL2646qB4rg7gNu/RZBwqflLBS19hvJPeEMIAZqdOGUI4Atsy ftx X-Received: by 2002:a05:693c:3018:b0:2c7:2c0b:f33b with SMTP id 5a478bee46e88-2ca8fd4ca35mr2082702eec.20.1775141125771; Thu, 02 Apr 2026 07:45:25 -0700 (PDT) Received: from [192.168.1.18] (177-4-161-218.user3p.v-tal.net.br. [177.4.161.218]) by smtp.gmail.com with ESMTPSA id 5a478bee46e88-2cba5df5c24sm369340eec.27.2026.04.02.07.45.23 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 02 Apr 2026 07:45:25 -0700 (PDT) From: =?utf-8?q?C=C3=A1ssio_Gabriel?= Date: Thu, 02 Apr 2026 11:45:13 -0300 Subject: [PATCH v2] ALSA: hda: Notify IEC958 Default PCM switch state changes Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260402-hda-spdif-share-notify-v2-1-7c6584ecaa21@gmail.com> X-B4-Tracking: v=1; b=H4sIAAAAAAAC/3WNyw6CMBBFf4V07Zi2NBJd+R+GxdhO6RihpEUiI fy7PNYuT3LvObPIlJiyuBWzSDRy5titoE+FsAG7hoDdykJLfZFlKSE4hNw79pADJoIuDuwn0Nq jQSslKiPWc5/I83cXP+qD8+f5Ijtstm0ROA8xTXt5VNvuiBip/kVGBQoqWZHRmtzVqXvTIr/PN raiXpblB6FwrGLOAAAA X-Change-ID: 20260330-hda-spdif-share-notify-22fa4ac00a14 To: Takashi Iwai , Jaroslav Kysela Cc: linux-sound@vger.kernel.org, linux-kernel@vger.kernel.org, Takashi Iwai , =?utf-8?q?C=C3=A1ssio_Gabriel?= X-Mailer: b4 0.15.1 X-Developer-Signature: v=1; a=openpgp-sha256; l=6381; i=cassiogabrielcontato@gmail.com; h=from:subject:message-id; bh=g8JAC6BSLChGNHkt6cn4WUEj8jJIPs2Kb/3zn2v9Uu0=; b=owGbwMvMwCV2IdZeKur/u2bG02pJDJnnGpnVYnUjszn6HALXbkjYeaLovqi4/AddQ52q9oRgU 791cw93lLIwiHExyIopsqxOWmS5p+vB1fq4FR4wc1iZQIYwcHEKwERa3zEyvJqwZlP3g++eKh91 F3voB7DfDn6y4u0KhhMvVhi0fNhRU8PIcGd/6n/7q6kVGxw0cpPnWz6sdDR29Ob9+zp2hcbVvng xfgA= X-Developer-Key: i=cassiogabrielcontato@gmail.com; a=openpgp; fpr=AB62A239BC8AE0D57F5EA848D05D3F1A5AFFEE83 The "IEC958 Default PCM Playback Switch" control is backed directly by mout->share_spdif. The share-switch callbacks currently access that state without serialization, and spdif_share_sw_put() always returns 0, so normal userspace writes never emit the standard ALSA control value notification. snd_hda_multi_out_analog_open() may also clear mout->share_spdif when the analog PCM capabilities and the SPDIF capabilities no longer intersect. That fallback is still needed to avoid creating an impossible hw constraint set, but it changes the mixer backing value without notifying subscribers. Protect the share-switch callbacks with spdif_mutex like the other SPDIF control handlers, return the actual change value from spdif_share_sw_put(), and notify the cached control when the open path forcibly disables shared SPDIF mode after dropping spdif_mutex. This keeps the existing auto-disable behavior while making switch state changes visible to userspace. Fixes: 9a08160bdbe3 ("[ALSA] hda-codec - Add "IEC958 Default PCM" switch") Fixes: 022b466fc353 ("ALSA: hda - Avoid invalid formats and rates with shar= ed SPDIF") Suggested-by: Takashi Iwai Signed-off-by: C=C3=A1ssio Gabriel --- Changes in v2: - Reworked the share-switch callbacks to use codec in private_data and mout in private_value. - Replaced the mixer-list lookup helper with a cached shared SPDIF kcontrol pointer for forced-disable notifications. - Kept the functional change otherwise unchanged. - Link to v1: https://patch.msgid.link/20260401-hda-spdif-share-notify-v1-1= -707e422ed9d1@gmail.com --- sound/hda/common/codec.c | 46 ++++++++++++++++++++++++++++++++++++----= ---- sound/hda/common/hda_local.h | 3 +++ 2 files changed, 41 insertions(+), 8 deletions(-) diff --git a/sound/hda/common/codec.c b/sound/hda/common/codec.c index 09b1329bb8f3..5123df32ad89 100644 --- a/sound/hda/common/codec.c +++ b/sound/hda/common/codec.c @@ -2529,7 +2529,10 @@ EXPORT_SYMBOL_GPL(snd_hda_spdif_ctls_assign); static int spdif_share_sw_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { - struct hda_multi_out *mout =3D snd_kcontrol_chip(kcontrol); + struct hda_codec *codec =3D snd_kcontrol_chip(kcontrol); + struct hda_multi_out *mout =3D (void *)kcontrol->private_value; + + guard(mutex)(&codec->spdif_mutex); ucontrol->value.integer.value[0] =3D mout->share_spdif; return 0; } @@ -2537,9 +2540,15 @@ static int spdif_share_sw_get(struct snd_kcontrol *k= control, static int spdif_share_sw_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { - struct hda_multi_out *mout =3D snd_kcontrol_chip(kcontrol); - mout->share_spdif =3D !!ucontrol->value.integer.value[0]; - return 0; + struct hda_codec *codec =3D snd_kcontrol_chip(kcontrol); + struct hda_multi_out *mout =3D (void *)kcontrol->private_value; + bool val =3D !!ucontrol->value.integer.value[0]; + int change; + + guard(mutex)(&codec->spdif_mutex); + change =3D mout->share_spdif !=3D val; + mout->share_spdif =3D val; + return change; } =20 static const struct snd_kcontrol_new spdif_share_sw =3D { @@ -2550,6 +2559,14 @@ static const struct snd_kcontrol_new spdif_share_sw = =3D { .put =3D spdif_share_sw_put, }; =20 +static void notify_spdif_share_sw(struct hda_codec *codec, + struct hda_multi_out *mout) +{ + if (mout->share_spdif_kctl) + snd_ctl_notify_one(codec->card, SNDRV_CTL_EVENT_MASK_VALUE, + mout->share_spdif_kctl, 0); +} + /** * snd_hda_create_spdif_share_sw - create Default PCM switch * @codec: the HDA codec @@ -2559,15 +2576,24 @@ int snd_hda_create_spdif_share_sw(struct hda_codec = *codec, struct hda_multi_out *mout) { struct snd_kcontrol *kctl; + int err; =20 if (!mout->dig_out_nid) return 0; =20 - kctl =3D snd_ctl_new1(&spdif_share_sw, mout); + kctl =3D snd_ctl_new1(&spdif_share_sw, codec); if (!kctl) return -ENOMEM; - /* ATTENTION: here mout is passed as private_data, instead of codec */ - return snd_hda_ctl_add(codec, mout->dig_out_nid, kctl); + /* snd_ctl_new1() stores @codec in private_data; stash @mout in + * private_value for the share-switch callbacks and cache the + * assigned control for forced-disable notifications. + */ + kctl->private_value =3D (unsigned long)mout; + err =3D snd_hda_ctl_add(codec, mout->dig_out_nid, kctl); + if (err < 0) + return err; + mout->share_spdif_kctl =3D kctl; + return 0; } EXPORT_SYMBOL_GPL(snd_hda_create_spdif_share_sw); =20 @@ -3701,6 +3727,8 @@ int snd_hda_multi_out_analog_open(struct hda_codec *c= odec, struct hda_pcm_stream *hinfo) { struct snd_pcm_runtime *runtime =3D substream->runtime; + bool notify_share_sw =3D false; + runtime->hw.channels_max =3D mout->max_channels; if (mout->dig_out_nid) { if (!mout->analog_rates) { @@ -3729,10 +3757,12 @@ int snd_hda_multi_out_analog_open(struct hda_codec = *codec, hinfo->maxbps =3D mout->spdif_maxbps; } else { mout->share_spdif =3D 0; - /* FIXME: need notify? */ + notify_share_sw =3D true; } } } + if (notify_share_sw) + notify_spdif_share_sw(codec, mout); return snd_pcm_hw_constraint_step(substream->runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, 2); } diff --git a/sound/hda/common/hda_local.h b/sound/hda/common/hda_local.h index ab423f1cef54..490bed97cbda 100644 --- a/sound/hda/common/hda_local.h +++ b/sound/hda/common/hda_local.h @@ -12,6 +12,8 @@ =20 #include =20 +struct snd_kcontrol; + /* We abuse kcontrol_new.subdev field to pass the NID corresponding to * the given new control. If id.subdev has a bit flag HDA_SUBDEV_NID_FLAG, * snd_hda_ctl_add() takes the lower-bit subdev value as a valid NID. @@ -203,6 +205,7 @@ enum { HDA_DIG_NONE, HDA_DIG_EXCLUSIVE, HDA_DIG_ANALOG_= DUP }; /* dig_out_used */ #define HDA_MAX_OUTS 5 =20 struct hda_multi_out { + struct snd_kcontrol *share_spdif_kctl; /* cached shared SPDIF switch */ int num_dacs; /* # of DACs, must be more than 1 */ const hda_nid_t *dac_nids; /* DAC list */ hda_nid_t hp_nid; /* optional DAC for HP, 0 when not exists */ --- base-commit: f16695c0dc9db64f0a5a9871a10b70daee2653e3 change-id: 20260330-hda-spdif-share-notify-22fa4ac00a14 Best regards, -- =20 C=C3=A1ssio Gabriel