Nicholas Chin has uploaded this change for review. ( https://review.coreboot.org/c/coreboot/+/83372?usp=email )
Change subject: drivers/pc80/pc/spkmodem.c: Use beep() instead of own implementation ......................................................................
drivers/pc80/pc/spkmodem.c: Use beep() instead of own implementation
Commit 23b79483554f (pc80/i8254: Add speaker beep function) added a driver to play beeps using the 8254 PIT chip and the PC speaker, which is essentially the same as the make_tone() function in spkmodem.c. Drop the duplicate functionality provided by make_tone() in favour of the common beep() function, which also has a more intuitive signature.
Converting the make_tone() arguments to beep() arguments is not trivial, as they are different in meaning and requires some background knowledge of PIT programming, explained briefly here.
The `duration` argument to make_tone() is somewhat misleading, as it is not used as a direct number of units of time, but rather the number of PIT counter reloads to wait for. The frequency of the reloads is related to the `freq_count` argument, which is the value the counter is reloaded to when it counts down to 0. Since the counter decrements at 1193181 Hz, dividing this frequency by the desired frequency of the tone gives the counter reload value, which was used to calculate the freq_count argument for the calls to make_tone().
However, since the PIT output toggles at every reload, each full cycle occurs at half the desired frequency. To compensate for this, mode 3 (square wave generator) of the PIT chip actually decrements the counter by 2 each time so that the counter reloads twice as often. Thus, each reload occurs every 1 / (frequency * 2) seconds.
Since `duration` counts reloads, multiplying it by the time between reloads gives the time in seconds, and thus the following formula was used to convert `duration` into a millisecond value to pass as the duration_msec argument for beep(): duration_msec = 1000 * duration/(2*frequency)
Change-Id: If95b518c991a0d700489566e5609344ca2cbbc7a Signed-off-by: Nicholas Chin nic.c3.14@gmail.com --- M src/drivers/pc80/pc/spkmodem.c 1 file changed, 5 insertions(+), 81 deletions(-)
git pull ssh://review.coreboot.org:29418/coreboot refs/changes/72/83372/1
diff --git a/src/drivers/pc80/pc/spkmodem.c b/src/drivers/pc80/pc/spkmodem.c index 9e457f7..5ef0dd1 100644 --- a/src/drivers/pc80/pc/spkmodem.c +++ b/src/drivers/pc80/pc/spkmodem.c @@ -2,95 +2,19 @@
#include <arch/io.h> #include <console/spkmodem.h> - -#define SPEAKER_PIT_FREQUENCY 0x1234dd - -enum { - PIT_COUNTER_0 = 0x40, - PIT_COUNTER_1 = 0x41, - PIT_COUNTER_2 = 0x42, - PIT_CTRL = 0x43, - PIT_SPEAKER_PORT = 0x61, -}; - -enum { - PIT_SPK_TMR2 = 0x01, - PIT_SPK_DATA = 0x02, - PIT_SPK_TMR2_LATCH = 0x20 -}; - -enum { - PIT_CTRL_SELECT_MASK = 0xc0, - PIT_CTRL_SELECT_0 = 0x00, - PIT_CTRL_SELECT_1 = 0x40, - PIT_CTRL_SELECT_2 = 0x80, - - PIT_CTRL_READLOAD_MASK = 0x30, - PIT_CTRL_COUNTER_LATCH = 0x00, - PIT_CTRL_READLOAD_LSB = 0x10, - PIT_CTRL_READLOAD_MSB = 0x20, - PIT_CTRL_READLOAD_WORD = 0x30, - - PIT_CTRL_MODE_MASK = 0x0e, - PIT_CTRL_INTR_ON_TERM = 0x00, - PIT_CTRL_PROGR_ONE_SHOT = 0x02, - - PIT_CTRL_RATE_GEN = 0x04, - - PIT_CTRL_SQUAREWAVE_GEN = 0x06, - PIT_CTRL_SOFTSTROBE = 0x08, - - PIT_CTRL_HARDSTROBE = 0x0a, - - PIT_CTRL_COUNT_MASK = 0x01, - PIT_CTRL_COUNT_BINARY = 0x00, - PIT_CTRL_COUNT_BCD = 0x01 -}; - -static void -make_tone(uint16_t freq_count, unsigned int duration) -{ - outb(PIT_CTRL_SELECT_2 - | PIT_CTRL_READLOAD_WORD - | PIT_CTRL_SQUAREWAVE_GEN - | PIT_CTRL_COUNT_BINARY, PIT_CTRL); - - outb(freq_count & 0xff, PIT_COUNTER_2); - - outb((freq_count >> 8) & 0xff, PIT_COUNTER_2); - - outb(inb(PIT_SPEAKER_PORT) - | PIT_SPK_TMR2 | PIT_SPK_DATA, - PIT_SPEAKER_PORT); - - for (; duration; duration--) { - unsigned short counter, previous_counter = 0xffff; - - while (1) { - counter = inb(PIT_COUNTER_2); - counter |= ((uint16_t)inb(PIT_COUNTER_2)) << 8; - if (counter > previous_counter) { - previous_counter = counter; - break; - } - previous_counter = counter; - } - } -} +#include <pc80/i8254.h>
void spkmodem_tx_byte(unsigned char c) { int i; - - make_tone(SPEAKER_PIT_FREQUENCY / 200, 4); + beep(200, 10); for (i = 7; i >= 0; i--) { if ((c >> i) & 1) - make_tone(SPEAKER_PIT_FREQUENCY / 2000, 20); + beep(2000, 5); else - make_tone(SPEAKER_PIT_FREQUENCY / 4000, 40); - make_tone(SPEAKER_PIT_FREQUENCY / 1000, 10); + beep(4000, 5); + beep(1000, 5); } - make_tone(SPEAKER_PIT_FREQUENCY / 200, 0); }
void spkmodem_init(void)