[alsa-devel] HDA Beep Device for Asus EeeBox EB1501P
Takashi Iwai
tiwai at suse.de
Fri Feb 22 16:11:09 CET 2013
At Wed, 20 Feb 2013 22:51:53 +0100,
Harald Becker wrote:
>
> Hi,
>
> I own an Asus EeeBox EB1501P with an ALC662 codec and had no HDA mixer
> channel for the speaker beep device. After digging somewhat in the
> kernel source I found that I only need to add a single line in the
> beep_white_list in patch_realtek.c. May be this entry can be included
> in the mainstream drivers:
>
> SND_PCI_QUIRK(0x1043, 0x8376, "EeePC", 1),
>
> After recompiling the driver with this entry, the mixer device for the
> beep channel appears and the digital beep sound is emitted on the
> connected speakers.
Could you submit a proper patch for it?
>
> ... with one problem:
>
> If I use echo -e "\a" in a shell or run the beep command utility the
> sound appears only on second and following invocations. Whenever the
> frequency changes with the beep command the first invocation stays
> silent or just produce some click due to ALSA driver power saving. On
> all further invocations with same frequency the requested tone is
> generated on external speakers. There is no difference in behavior if
> the commands are called in a terminal emulator or directly on a virtual
> text console.
>
> Does this happen only on my machine or is this a known problem? Is
> there anything I can do to fix this behavior?
So, the behavior above disappears if you disable the power save?
Does the patch like below have any influence on the behavior?
thanks,
Takashi
---
diff --git a/sound/pci/hda/hda_beep.c b/sound/pci/hda/hda_beep.c
index 0849aac..63c9909 100644
--- a/sound/pci/hda/hda_beep.c
+++ b/sound/pci/hda/hda_beep.c
@@ -39,13 +39,23 @@ static void snd_hda_generate_beep(struct work_struct *work)
struct hda_beep *beep =
container_of(work, struct hda_beep, beep_work);
struct hda_codec *codec = beep->codec;
+ int tone;
if (!beep->enabled)
return;
+ tone = beep->tone;
+ if (tone && !beep->playing) {
+ snd_hda_power_up(codec);
+ beep->playing = 1;
+ }
/* generate tone */
snd_hda_codec_write(codec, beep->nid, 0,
- AC_VERB_SET_BEEP_CONTROL, beep->tone);
+ AC_VERB_SET_BEEP_CONTROL, tone);
+ if (!tone && beep->playing) {
+ beep->playing = 0;
+ snd_hda_power_down(codec);
+ }
}
/* (non-standard) Linear beep tone calculation for IDT/STAC codecs
@@ -115,14 +125,23 @@ static int snd_hda_beep_event(struct input_dev *dev, unsigned int type,
return 0;
}
+static void turn_off_beep(struct hda_beep *beep)
+{
+ cancel_work_sync(&beep->beep_work);
+ if (beep->playing) {
+ /* turn off beep */
+ snd_hda_codec_write(beep->codec, beep->nid, 0,
+ AC_VERB_SET_BEEP_CONTROL, 0);
+ beep->playing = 0;
+ snd_hda_power_down(beep->codec);
+ }
+}
+
static void snd_hda_do_detach(struct hda_beep *beep)
{
input_unregister_device(beep->dev);
beep->dev = NULL;
- cancel_work_sync(&beep->beep_work);
- /* turn off beep for sure */
- snd_hda_codec_write(beep->codec, beep->nid, 0,
- AC_VERB_SET_BEEP_CONTROL, 0);
+ turn_off_beep(beep);
}
static int snd_hda_do_attach(struct hda_beep *beep)
@@ -170,12 +189,8 @@ int snd_hda_enable_beep_device(struct hda_codec *codec, int enable)
enable = !!enable;
if (beep->enabled != enable) {
beep->enabled = enable;
- if (!enable) {
- cancel_work_sync(&beep->beep_work);
- /* turn off beep */
- snd_hda_codec_write(beep->codec, beep->nid, 0,
- AC_VERB_SET_BEEP_CONTROL, 0);
- }
+ if (!enable)
+ turn_off_beep(beep);
return 1;
}
return 0;
@@ -198,7 +213,7 @@ int snd_hda_attach_beep_device(struct hda_codec *codec, int nid)
snprintf(beep->phys, sizeof(beep->phys),
"card%d/codec#%d/beep0", codec->bus->card->number, codec->addr);
/* enable linear scale */
- snd_hda_codec_write(codec, nid, 0,
+ snd_hda_codec_write_cache(codec, nid, 0,
AC_VERB_SET_DIGI_CONVERT_2, 0x01);
beep->nid = nid;
diff --git a/sound/pci/hda/hda_beep.h b/sound/pci/hda/hda_beep.h
index 4dc6933..cb88464 100644
--- a/sound/pci/hda/hda_beep.h
+++ b/sound/pci/hda/hda_beep.h
@@ -36,6 +36,7 @@ struct hda_beep {
hda_nid_t nid;
unsigned int enabled:1;
unsigned int linear_tone:1; /* linear tone for IDT/STAC codec */
+ unsigned int playing:1;
struct work_struct beep_work; /* scheduled task for beep event */
struct mutex mutex;
};
More information about the Alsa-devel
mailing list