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; };