On Thu, 13 Jan 2022 19:31:41 +0100, Alexander Sergeyev wrote:
On Thu, Jan 13, 2022 at 08:14:29AM +0100, Takashi Iwai wrote:
First, about unbind and bind via sysfs -- attempts to unbind the HD-audio controller immediately trigger BUGs: Is it normal/expected?
A sort of. The sysfs unbind is little tested and may be still buggy if done during the stream operation.
To be sure, could you check with my latest sound.git tree for-linus branch? There are a few fixes that harden the dynamic unbind.
I assume that the referred repository is the one at [1]. I've tried 081c73701ef0 "ALSA: hda: intel-dsp-config: reorder the config table". It crashed with nearly identical logs.
OK, then it's still something to do with the led cdev unregisteration.
Could you try the patch below?
- Coeff 0x0b is flapping between 0x8003 and 0x7770 and does not seem
to have any effect in both non-working and working versions. Not sure about this, maybe microphone is not operational since I haven't checked it yet.
I got some time to poke the internal microphone. It works, but oddities are there as well. Initially I get "Mic Boost", "Capture" and "Internal Mic Boost" controls in alsamixer. When I run arecord, "Digital" control appears, but it cannot be changed until arecord is stopped. Subsequent arecord calls do not lock "Digital" control. This control affects sensitivity of the microphone and seems useful.
That's presumably an alsa-lib softvol stuff. It's created dynamically. So not really a kernel problem.
Takashi
--- diff --git a/sound/pci/hda/hda_generic.c b/sound/pci/hda/hda_generic.c index 3bf5e3410703..503cd979c908 100644 --- a/sound/pci/hda/hda_generic.c +++ b/sound/pci/hda/hda_generic.c @@ -84,13 +84,21 @@ static void free_kctls(struct hda_gen_spec *spec) snd_array_free(&spec->kctls); }
-static void snd_hda_gen_spec_free(struct hda_gen_spec *spec) +static void snd_hda_gen_spec_free(struct hda_codec *codec) { + struct hda_gen_spec *spec = codec->spec; + if (!spec) return; free_kctls(spec); snd_array_free(&spec->paths); snd_array_free(&spec->loopback_list); +#ifdef CONFIG_SND_HDA_GENERIC_LEDS + if (spec->led_cdevs[LED_AUDIO_MUTE]) + led_classdev_unregister(spec->led_cdevs[LED_AUDIO_MUTE]); + if (spec->led_cdevs[LED_AUDIO_MICMUTE]) + led_classdev_unregister(spec->led_cdevs[LED_AUDIO_MICMUTE]); +#endif }
/* @@ -3922,7 +3930,9 @@ static int create_mute_led_cdev(struct hda_codec *codec, enum led_brightness), bool micmute) { + struct hda_gen_spec *spec = codec->spec; struct led_classdev *cdev; + int err;
cdev = devm_kzalloc(&codec->core.dev, sizeof(*cdev), GFP_KERNEL); if (!cdev) @@ -3935,7 +3945,11 @@ static int create_mute_led_cdev(struct hda_codec *codec, cdev->brightness = ledtrig_audio_get(micmute ? LED_AUDIO_MICMUTE : LED_AUDIO_MUTE); cdev->flags = LED_CORE_SUSPENDRESUME;
- return devm_led_classdev_register(&codec->core.dev, cdev); + err = led_classdev_register(&codec->core.dev, cdev); + if (err < 0) + return err; + spec->led_cdevs[micmute ? LED_AUDIO_MICMUTE : LED_AUDIO_MUTE] = cdev; + return 0; }
/** @@ -5998,7 +6012,7 @@ EXPORT_SYMBOL_GPL(snd_hda_gen_init); void snd_hda_gen_free(struct hda_codec *codec) { snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_FREE); - snd_hda_gen_spec_free(codec->spec); + snd_hda_gen_spec_free(codec); kfree(codec->spec); codec->spec = NULL; } diff --git a/sound/pci/hda/hda_generic.h b/sound/pci/hda/hda_generic.h index 8e1bc8ea74fc..34eba40cc6e6 100644 --- a/sound/pci/hda/hda_generic.h +++ b/sound/pci/hda/hda_generic.h @@ -294,6 +294,9 @@ struct hda_gen_spec { struct hda_jack_callback *cb); void (*mic_autoswitch_hook)(struct hda_codec *codec, struct hda_jack_callback *cb); + + /* leds */ + struct led_classdev *led_cdevs[NUM_AUDIO_LEDS]; };
/* values for add_stereo_mix_input flag */