Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit fa797966 authored by Takashi Iwai's avatar Takashi Iwai
Browse files

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: default avatarTakashi Iwai <tiwai@suse.de>
parent 4abc1cc2
Loading
Loading
Loading
Loading
+44 −11
Original line number Original line Diff line number Diff line
@@ -45,16 +45,15 @@ static void snd_hda_generate_beep(struct work_struct *work)
			AC_VERB_SET_BEEP_CONTROL, beep->tone);
			AC_VERB_SET_BEEP_CONTROL, beep->tone);
}
}


static int snd_hda_beep_event(struct input_dev *dev, unsigned int type,
/* (non-standard) Linear beep tone calculation for IDT/STAC codecs 
				unsigned int code, int hz)
 *
 * 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)
{
{
	struct hda_beep *beep = input_get_drvdata(dev);

	switch (code) {
	case SND_BELL:
		if (hz)
			hz = 1000;
	case SND_TONE:
	hz *= 1000; /* fixed point */
	hz *= 1000; /* fixed point */
	hz = hz - DIGBEEP_HZ_MIN;
	hz = hz - DIGBEEP_HZ_MIN;
	if (hz < 0)
	if (hz < 0)
@@ -65,11 +64,45 @@ static int snd_hda_beep_event(struct input_dev *dev, unsigned int type,
		hz /= DIGBEEP_HZ_STEP;
		hz /= DIGBEEP_HZ_STEP;
		hz++;
		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,
				unsigned int code, int hz)
{
	struct hda_beep *beep = input_get_drvdata(dev);

	switch (code) {
	case SND_BELL:
		if (hz)
			hz = 1000;
	case SND_TONE:
		if (beep->linear_tone)
			beep->tone = beep_linear_tone(beep, hz);
		else
			beep->tone = beep_standard_tone(beep, 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);
+3 −2
Original line number Original line Diff line number Diff line
@@ -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 */
};
};


+2 −0
Original line number Original line Diff line number Diff line
@@ -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 &&