mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-10-06 00:39:48 +00:00
ALSA: hda - Fix digital beep tone calculation
The digital beep tone is calculated in two different ways depending on the codec chip. The standard one is using a divider, and another one is a linear tone for IDT/STAC codecs. Currently, only the latter type is used for all codecs, which resulted in a wrong tone pitch. This patch adds the calculation of the standard HD-audio type. Also clean-up the fields in hda_beep struct. Reference: bko#13162 http://bugzilla.kernel.org/show_bug.cgi?id=13162 Signed-off-by: Takashi Iwai <tiwai@suse.de>
This commit is contained in:
parent
4abc1cc2f9
commit
fa79796631
3 changed files with 49 additions and 13 deletions
|
@ -45,6 +45,46 @@ static void snd_hda_generate_beep(struct work_struct *work)
|
||||||
AC_VERB_SET_BEEP_CONTROL, beep->tone);
|
AC_VERB_SET_BEEP_CONTROL, beep->tone);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* (non-standard) Linear beep tone calculation for IDT/STAC codecs
|
||||||
|
*
|
||||||
|
* The tone frequency of beep generator on IDT/STAC codecs is
|
||||||
|
* defined from the 8bit tone parameter, in Hz,
|
||||||
|
* freq = 48000 * (257 - tone) / 1024
|
||||||
|
* that is from 12kHz to 93.75kHz in step of 46.875 hz
|
||||||
|
*/
|
||||||
|
static int beep_linear_tone(struct hda_beep *beep, int hz)
|
||||||
|
{
|
||||||
|
hz *= 1000; /* fixed point */
|
||||||
|
hz = hz - DIGBEEP_HZ_MIN;
|
||||||
|
if (hz < 0)
|
||||||
|
hz = 0; /* turn off PC beep*/
|
||||||
|
else if (hz >= (DIGBEEP_HZ_MAX - DIGBEEP_HZ_MIN))
|
||||||
|
hz = 0xff;
|
||||||
|
else {
|
||||||
|
hz /= DIGBEEP_HZ_STEP;
|
||||||
|
hz++;
|
||||||
|
}
|
||||||
|
return hz;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* HD-audio standard beep tone parameter calculation
|
||||||
|
*
|
||||||
|
* The tone frequency in Hz is calculated as
|
||||||
|
* freq = 48000 / (tone * 4)
|
||||||
|
* from 47Hz to 12kHz
|
||||||
|
*/
|
||||||
|
static int beep_standard_tone(struct hda_beep *beep, int hz)
|
||||||
|
{
|
||||||
|
if (hz <= 0)
|
||||||
|
return 0; /* disabled */
|
||||||
|
hz = 12000 / hz;
|
||||||
|
if (hz > 0xff)
|
||||||
|
return 0xff;
|
||||||
|
if (hz <= 0)
|
||||||
|
return 1;
|
||||||
|
return hz;
|
||||||
|
}
|
||||||
|
|
||||||
static int snd_hda_beep_event(struct input_dev *dev, unsigned int type,
|
static int snd_hda_beep_event(struct input_dev *dev, unsigned int type,
|
||||||
unsigned int code, int hz)
|
unsigned int code, int hz)
|
||||||
{
|
{
|
||||||
|
@ -55,21 +95,14 @@ static int snd_hda_beep_event(struct input_dev *dev, unsigned int type,
|
||||||
if (hz)
|
if (hz)
|
||||||
hz = 1000;
|
hz = 1000;
|
||||||
case SND_TONE:
|
case SND_TONE:
|
||||||
hz *= 1000; /* fixed point */
|
if (beep->linear_tone)
|
||||||
hz = hz - DIGBEEP_HZ_MIN;
|
beep->tone = beep_linear_tone(beep, hz);
|
||||||
if (hz < 0)
|
else
|
||||||
hz = 0; /* turn off PC beep*/
|
beep->tone = beep_standard_tone(beep, hz);
|
||||||
else if (hz >= (DIGBEEP_HZ_MAX - DIGBEEP_HZ_MIN))
|
|
||||||
hz = 0xff;
|
|
||||||
else {
|
|
||||||
hz /= DIGBEEP_HZ_STEP;
|
|
||||||
hz++;
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
beep->tone = hz;
|
|
||||||
|
|
||||||
/* schedule beep event */
|
/* schedule beep event */
|
||||||
schedule_work(&beep->beep_work);
|
schedule_work(&beep->beep_work);
|
||||||
|
|
|
@ -30,8 +30,9 @@ struct hda_beep {
|
||||||
struct hda_codec *codec;
|
struct hda_codec *codec;
|
||||||
char phys[32];
|
char phys[32];
|
||||||
int tone;
|
int tone;
|
||||||
int nid;
|
hda_nid_t nid;
|
||||||
int enabled;
|
unsigned int enabled:1;
|
||||||
|
unsigned int linear_tone:1; /* linear tone for IDT/STAC codec */
|
||||||
struct work_struct beep_work; /* scheduled task for beep event */
|
struct work_struct beep_work; /* scheduled task for beep event */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -3737,6 +3737,8 @@ static int stac92xx_parse_auto_config(struct hda_codec *codec, hda_nid_t dig_out
|
||||||
err = snd_hda_attach_beep_device(codec, nid);
|
err = snd_hda_attach_beep_device(codec, nid);
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
return err;
|
return err;
|
||||||
|
/* IDT/STAC codecs have linear beep tone parameter */
|
||||||
|
codec->beep->linear_tone = 1;
|
||||||
/* if no beep switch is available, make its own one */
|
/* if no beep switch is available, make its own one */
|
||||||
caps = query_amp_caps(codec, nid, HDA_OUTPUT);
|
caps = query_amp_caps(codec, nid, HDA_OUTPUT);
|
||||||
if (codec->beep &&
|
if (codec->beep &&
|
||||||
|
|
Loading…
Reference in a new issue