You are not logged in.

#1 2013-05-04 13:32:01

morfik
Member
Registered: 2013-03-14
Posts: 22

How to reload sound modules?

I'm using alsa + pulse sound system. I also have Openbox as a stand-alone WM and lightDM,  but the same thing occurs on my debian testing + gnome. I've been trying to solve this issue for several days but with no success.

Below is the output from alsa-info.sh script
http://www.alsa-project.org/db/?f=9f32f … f7cdddcc40

Installed packages:

morfik:~$ pacman -Qs alsa
local/alsa-lib 1.0.27-1
    An alternative implementation of Linux sound support
local/alsa-plugins 1.0.27-1
    Extra alsa plugins
local/alsa-utils 1.0.27-4
    An alternative implementation of Linux sound support
local/pulseaudio-alsa 2-2
    ALSA Configuration for PulseAudio

   

morfik:~$ pacman -Qs pulse
local/libao 1.1.0-3
    Cross-platform audio output library and plugins
local/libcanberra-pulse 0.30-3
    PulseAudio plugin for libcanberra
local/libpulse 3.0-3
    A featureful, general-purpose sound server (client library)
local/paprefs 0.9.10-2
    A simple GTK-based configuration dialog for PulseAudio
local/pavucontrol 2.0-1
    A GTK volume control tool for PulseAudio
local/pulseaudio 3.0-3
    A featureful, general-purpose sound server
local/pulseaudio-alsa 2-2
    ALSA Configuration for PulseAudio

Everything works fine until hibernation. After my system goes up, one speeker (of 4) is missing, I mean that 3 others play sound well, but the rear-left is silent. I don't know what is wrong, but on debian I can deal with it by reloading sound modules:

$ pulseaudio -k
# alsa force-reload
$ pulseaudio -D

But unfortunately there is no such a thing like "alsa" in Arch. When I type alsa force-reload on my debian, I get this:

root:/# alsa force-reload
Unloading ALSA sound driver modules: snd-ca0106 snd-seq-midi snd-seq-midi-event snd-rawmidi snd-ac97-codec snd-pcm snd-page-alloc snd-seq snd-seq-device snd-timer.
Loading ALSA sound driver modules: snd-ca0106 snd-seq-midi snd-seq-midi-event snd-rawmidi snd-ac97-codec snd-pcm snd-page-alloc snd-seq snd-seq-device snd-timer.

I tried to change a little pulse settings in /etc/pusle/daemon.conf but this does nothing. Now the file looks like this:

	daemonize = yes
	allow-exit = yes
	use-pid-file = yes
	exit-idle-time=0
	resample-method=speex-float-0
	default-sample-rate = 44100
	alternate-sample-rate = 48000
	default-sample-channels = 4
	default-channel-map = front-left,front-right,rear-left,rear-right

I can't use hibernation because after my system comes to life, I have to reboot it in order to make sound work properly.

I don't know what info I should provide, so if you want to know something more about configuration of my pc, feel free and ask, I'll post the info as soon as possible.

Offline

#2 2013-05-04 15:13:17

Raynman
Member
Registered: 2011-10-22
Posts: 1,063

Re: How to reload sound modules?

It is not unlikely that Debian's 'alsa' is a shell script, in which case you may be able to reuse parts of it. Or just compile a list of your sound modules and create a systemd service that calls modprobe [-r] before/after hibernate?

Edit:
Alternatively, if you weren't already doing so, you could try something like pm-utils that comes with a collection of scripts for buggy hw/drivers like yours.

Last edited by Raynman (2013-05-04 15:15:10)

Offline

#3 2013-05-05 01:15:49

morfik
Member
Registered: 2013-03-14
Posts: 22

Re: How to reload sound modules?

Raynman -- thanks for the hint. I looked for the alsa script on debian, and it exists, so I moved it to arch.

This is the script:

#!/bin/sh
#
# alsa-base control script
#
# Description: Used to load and unload ALSA modules and
#              restore and store mixer levels. There is no
#              longer any need to run this script on bootup
#              or shutdown. It is now moved to /usr/sbin.

set -e

# Exit if alsa-base package is not installed
[ -f /etc/modprobe.d/alsa-base.conf ] || exit 0

MYNAME=/usr/sbin/alsa
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin

# Default values of variables in /etc/default/alsa
force_unload_modules_before_suspend=""

[ -f /etc/default/alsa ] && . /etc/default/alsa

# $* MESSAGE
warn() { echo "${MYNAME}: Warning: $* " >&2 ; }

#
# Attempt to create /var/run/alsa if it is absent.
# Return true if /var/run/alsa exists after this attempt,
# otherwise false.
#
check_run_dir()
{ 
	[ -d /var/run/alsa ] && return 0
	# We have no business creating /var/run if it doesn't exist
	if ! [ -d /var/run ] ; then
		warn "Could not create /var/run/alsa/ because /var/run/ is not present."
		return 1
	fi
	if ! mkdir --mode=755 /var/run/alsa ; then
		warn "Failed to create /var/run/alsa/."
		return 1
	fi
	[ -d /var/run/alsa ] && return 0
	return 1
}

echo_procs_using_sound()
{
	for i in /proc/[0-9]*/fd/* ; do
		var="$(readlink $i)"
		if test x"$var" != x"${var#/dev/snd/pcm}" ; then
			IFS=/; set -- $i; unset IFS; echo $3
		fi
	done
}

# $* [PID]...
echo_with_command_names()
{
	[ "$1" ] || return 0
	echo $( \
		ps --no-headers -o "%p %c" "$@" \
		| sed -e 's/\([0-9][0-9]*\) \(.*\)/\1(\2)/' \
	)
}

kill_procs_using_sound()
{
	procs_using_sound="$(echo_procs_using_sound)"
	if [ "$procs_using_sound" ] ; then
		echo -n "Terminating processes:"
		for attempt in 1 2 3 4 ; do
			echo -n " ${procs_using_sound}"
			kill $procs_using_sound || :
			sleep 1
			procs_using_sound="$(echo_procs_using_sound)"
			[ "$procs_using_sound" ] || break
		done
		# Either no more procs using sound or attempts ran out
		if [ "$procs_using_sound" ] ; then
			echo -n " (with SIGKILL:) ${procs_using_sound}"
			kill -9 $procs_using_sound || :
			sleep 1
		fi
		procs_using_sound="$(echo_procs_using_sound)"
		if [ "$procs_using_sound" ] ; then
			echo " (failed: processes still using sound devices: $(echo_with_command_names $procs_using_sound))."
			return 1
		fi
		echo "."
	fi
	return 0
}

# $* MODULE-NAME [MODULE-NAME]... | "all"
unload_modules()
{
	procs_using_sound="$(echo_procs_using_sound)"
	if [ "$procs_using_sound" ] ; then
		warn "Processes using sound devices: $(echo_with_command_names $procs_using_sound)."
	fi
	if check_run_dir ; then
		:> /var/run/alsa/modules-removed
	else
		warn "Not keeping list of removed modules because /var/run/alsa is absent.
It will not be possible automatically to reload these modules."
	fi
	echo -n "Unloading ALSA sound driver modules:"
	[ -d /proc/asound ] || { echo " (none loaded)." ; return 0 ; }
	echo_snd_modules_loaded()
	{
		lsmod \
		| sed -n -e 's/^\(snd[-_][^[:space:]]*\)[[:space:]].*/\1/p' \
		| sed -e 's/_/-/g'
	}
	for FSMBS in $* ; do
		MODULES_TO_REMOVE=""
		SND_MODULES_LOADED="$(echo_snd_modules_loaded)"
		case "$FSMBS" in
		  all)
			MODULES_TO_REMOVE="$SND_MODULES_LOADED"
			;;
		  snd_*|snd-*)
			FSMBS="$(echo "$FSMBS" | sed -e 's/_/-/g')"
			for M in $SND_MODULES_LOADED ; do
				if [ "$FSMBS" = "$M" ] ; then
					MODULES_TO_REMOVE="$FSMBS"
					break
				fi
			done
			;;
		esac
		[ "$MODULES_TO_REMOVE" ] || continue
		if [ -d /var/run/alsa ] ; then
			echo "$MODULES_TO_REMOVE" >> /var/run/alsa/modules-removed
		fi
		for M in $MODULES_TO_REMOVE ; do
			echo -n " ${M}"
			modprobe -r "$M" >/dev/null 2>&1 || :
		done
	done
	if [ -f /var/run/alsa/modules-removed ] ; then
		MODULES_STILL_LOADED="$(echo_snd_modules_loaded | grep -F -f /var/run/alsa/modules-removed)"
		MODULES_STILL_LOADED="$(echo $MODULES_STILL_LOADED)"
	else
		MODULES_STILL_LOADED=""
	fi
	if [ "$MODULES_STILL_LOADED" ] ; then
		echo " (failed: modules still loaded: ${MODULES_STILL_LOADED})."
		return 1
	else
		echo "."
		return 0
	fi
}

# $* MODULE-NAME [MODULE-NAME]... | "all"
force_unload_modules()
{
	kill_procs_using_sound || :
	unload_modules "$@" || return 1
	return 0
}

load_unloaded_modules()
{
	LUM_RETURNSTATUS=0
	MODULES_TO_LOAD=""
	[ -d /var/run/alsa ] || warn "Directory /var/run/alsa is absent."
	echo -n "Loading ALSA sound driver modules:"
	[ -f /var/run/alsa/modules-removed ] && MODULES_TO_LOAD="$(echo $(cat /var/run/alsa/modules-removed))"
	[ "$MODULES_TO_LOAD" ] || { echo " (none to reload)." ; return $LUM_RETURNSTATUS ; }
	echo -n " $MODULES_TO_LOAD"
	for MDL in $MODULES_TO_LOAD ; do
		modprobe $MDL || LUM_RETURNSTATUS=1
	done
	case "$LUM_RETURNSTATUS" in
	  0) echo "." ;;
	  *) echo " (failed)." ;;
	esac
	return $LUM_RETURNSTATUS
}

case "$1" in
  unload)
	unload_modules all || exit $?
	;;
  reload)
	EXITSTATUS=0
	unload_modules all || EXITSTATUS=1
	load_unloaded_modules || EXITSTATUS=1
	exit $EXITSTATUS
	;;
  force-unload)
	force_unload_modules all || exit $?
	;;
  force-reload)
	EXITSTATUS=0
	force_unload_modules all || EXITSTATUS=1
	load_unloaded_modules || EXITSTATUS=1
	exit $EXITSTATUS
	;;
  suspend)
	case "$force_unload_modules_before_suspend" in
	  ""|false) : ;;
	  all|true) force_unload_modules all || exit $? ;;
	  *) force_unload_modules $force_unload_modules_before_suspend || exit $? ;;
	esac
	;;
  resume)
	case "$force_unload_modules_before_suspend" in
	  ""|false) : ;;
	  *) load_unloaded_modules || exit $? ;;
	esac
	;;
  *)
	echo "Usage: $MYNAME {unload|reload|force-unload|force-reload|suspend|resume}" >&2
	exit 3
	;;
esac

It requires two other files in /etc/modprobe.d/ . I also moved them from debian:

alsa-base-blacklist.conf

# Uncomment these entries in order to blacklist unwanted modem drivers
# blacklist snd-atiixp-modem
# blacklist snd-intel8x0m
# blacklist snd-via82xx-modem
# Comment this entry in order to load snd-pcsp driver
blacklist snd-pcsp

alsa-base.conf

# autoloader aliases
install sound-slot-0 /sbin/modprobe snd-card-0
install sound-slot-1 /sbin/modprobe snd-card-1
install sound-slot-2 /sbin/modprobe snd-card-2
install sound-slot-3 /sbin/modprobe snd-card-3
install sound-slot-4 /sbin/modprobe snd-card-4
install sound-slot-5 /sbin/modprobe snd-card-5
install sound-slot-6 /sbin/modprobe snd-card-6
install sound-slot-7 /sbin/modprobe snd-card-7
# Cause optional modules to be loaded above generic modules
install snd /sbin/modprobe --ignore-install snd && { /sbin/modprobe --quiet snd-ioctl32 ; /sbin/modprobe --quiet snd-seq ; : ; }
install snd-rawmidi /sbin/modprobe --ignore-install snd-rawmidi && { /sbin/modprobe --quiet snd-seq-midi ; : ; }
install snd-emu10k1 /sbin/modprobe --ignore-install snd-emu10k1 && { /sbin/modprobe --quiet snd-emu10k1-synth ; : ; }
# Keep snd-pcsp from beeing loaded as first soundcard
options snd-pcsp index=-2
# Keep snd-usb-audio from beeing loaded as first soundcard
options snd-usb-audio index=-2
# Prevent abnormal drivers from grabbing index 0
options bt87x index=-2
options cx88_alsa index=-2
options snd-atiixp-modem index=-2
options snd-intel8x0m index=-2
options snd-via82xx-modem index=-2

options snd-ca0106 index=0
options snd-hda-intel index=1

After hibernation, the script provides sound as expected. I also notticed that I can reload only snd-ca0106 and the sound comes back.

Now I have to make a .service file that could make my sound work. But I need more info how to do so.

Offline

#4 2013-05-05 01:28:34

brebs
Member
Registered: 2007-04-03
Posts: 3,401

Re: How to reload sound modules?

You could try hda-verb also, as a less drastic method than unloading kernel modules.

Offline

#5 2013-05-05 01:57:25

opt1mus
Member
From: UK
Registered: 2011-12-31
Posts: 197
Website

Re: How to reload sound modules?

Have you taken a look at alsactl, in particular the restore argument?

Offline

#6 2013-05-05 14:57:28

morfik
Member
Registered: 2013-03-14
Posts: 22

Re: How to reload sound modules?

@opt1mus -- this doesn't work.
@brebs -- I think I'd better stay with this alsa script. I've cut 2 things from it and added some my own lines, and now I have this:

#!/bin/sh
set e
echo_procs_using_sound()
{
	for i in /proc/[0-9]*/fd/* ; do
		var="$(readlink $i)"
		if test x"$var" != x"${var#/dev/snd/pcm}" ; then
			IFS=/; set -- $i; unset IFS; echo $3
		fi
	done
}

kill_procs_using_sound()
{
	procs_using_sound="$(echo_procs_using_sound)"
	if [ "$procs_using_sound" ] ; then
		echo -n "Terminating processes:"
		for attempt in 1 2 3 4 ; do
			echo -n " ${procs_using_sound}"
			kill $procs_using_sound || :
			sleep 1
			procs_using_sound="$(echo_procs_using_sound)"
			[ "$procs_using_sound" ] || break
		done
		# Either no more procs using sound or attempts ran out
		if [ "$procs_using_sound" ] ; then
			echo -n " (with SIGKILL:) ${procs_using_sound}"
			kill -9 $procs_using_sound || :
			sleep 1
		fi
		procs_using_sound="$(echo_procs_using_sound)"
		if [ "$procs_using_sound" ] ; then
			echo " (failed: processes still using sound devices: $(echo_with_command_names $procs_using_sound))."
			return 1
		fi
		echo "."
	fi
	return 0
}
kill_procs_using_sound

kill -9 pnmixer
kill -9 `lsof -t /dev/dsp* /dev/audio* /dev/mixer* /dev/snd/*`

modprobe -r snd_ca0106
modprobe snd_ca0106

su morfik -c "pulseaudio -D"
su morfik -c "pnmixer &"

And this works. So, now I have to think about .service files, but I need to read a little bit about it..

Offline

Board footer

Powered by FluxBB