sound: x86: Add beeping support in i8254
authorSimon Glass <sjg@chromium.org>
Sun, 17 Feb 2019 03:24:58 +0000 (20:24 -0700)
committerBin Meng <bmeng.cn@gmail.com>
Wed, 20 Feb 2019 07:27:09 +0000 (15:27 +0800)
Adjust the code to allow beeping at different frequencies, using a
calculated value for timer 2.

Signed-off-by: Simon Glass <sjg@chromium.org>
Reviewed-by: Bin Meng <bmeng.cn@gmail.com>
arch/x86/include/asm/i8254.h
arch/x86/lib/i8254.c

index 65c9761..d769daf 100644 (file)
 /* The clock frequency of the i8253/i8254 PIT */
 #define PIT_TICK_RATE  1193182
 
+/**
+ * i8254_enable_beep() - Start a beep using the PCAT timer
+ *
+ * This starts beeping using the legacy i8254 timer. The beep may be silenced
+ * after a delay with i8254_disable_beep().
+ *
+ * @frequency_hz: Frequency of beep in Hz
+ * @return 0 if OK, -EINVAL if frequency_hz is 0
+ */
+int i8254_enable_beep(uint frequency_hz);
+
+/**
+ * i8254_disable_beep() - Disable the bepper
+ *
+ * This stops any existing beep
+ */
+void i8254_disable_beep(void);
+
 #endif /* _ASMI386_I8954_H_ */
index 1f10124..d022795 100644 (file)
@@ -8,8 +8,20 @@
 #include <asm/io.h>
 #include <asm/i8254.h>
 
-#define TIMER1_VALUE   18      /* 15.6us */
-#define TIMER2_VALUE   0x0a8e  /* 440Hz */
+#define TIMER1_VALUE           18      /* 15.6us */
+#define BEEP_FREQUENCY_HZ      440
+#define SYSCTL_PORTB           0x61
+#define PORTB_BEEP_ENABLE      0x3
+
+static void i8254_set_beep_freq(uint frequency_hz)
+{
+       uint countdown;
+
+       countdown = PIT_TICK_RATE / frequency_hz;
+
+       outb(countdown & 0xff, PIT_BASE + PIT_T2);
+       outb((countdown >> 8) & 0xff, PIT_BASE + PIT_T2);
+}
 
 int i8254_init(void)
 {
@@ -29,8 +41,23 @@ int i8254_init(void)
         */
        outb(PIT_CMD_CTR2 | PIT_CMD_BOTH | PIT_CMD_MODE3,
             PIT_BASE + PIT_COMMAND);
-       outb(TIMER2_VALUE & 0xff, PIT_BASE + PIT_T2);
-       outb(TIMER2_VALUE >> 8, PIT_BASE + PIT_T2);
+       i8254_set_beep_freq(BEEP_FREQUENCY_HZ);
+
+       return 0;
+}
+
+int i8254_enable_beep(uint frequency_hz)
+{
+       if (!frequency_hz)
+               return -EINVAL;
+
+       i8254_set_beep_freq(frequency_hz);
+       setio_8(SYSCTL_PORTB, PORTB_BEEP_ENABLE);
 
        return 0;
 }
+
+void i8254_disable_beep(void)
+{
+       clrio_8(SYSCTL_PORTB, PORTB_BEEP_ENABLE);
+}