1 /* SPDX-License-Identifier: GPL-2.0-only */
2
3 #include <libpayload.h>
4
5 /* Include source to gain access to private defines */
6 #include "../drivers/speaker.c"
7
8 #include <tests/test.h>
9
outb(unsigned char val,int port)10 void outb(unsigned char val, int port)
11 {
12 check_expected(val);
13 check_expected(port);
14 }
15
inb(int port)16 unsigned char inb(int port)
17 {
18 check_expected(port);
19 return mock_type(unsigned char);
20 }
21
setup_speaker_enable_calls(u16 freq,u8 port_val)22 static void setup_speaker_enable_calls(u16 freq, u8 port_val)
23 {
24 /* Minimal correct value should be at leaset 256. For values lowe than that,
25 counter will have an incorrect value. Regardless, there is */
26 u16 reg16 = 1193180 / freq;
27
28 /* Select counter 2 */
29 expect_value(outb, val, 0xb6);
30 expect_value(outb, port, I82C54_CONTROL_WORD_REGISTER);
31
32 /* Write freq. [LSB, MSB] */
33 expect_value(outb, val, (u8)(reg16 & 0xff));
34 expect_value(outb, port, I82C54_COUNTER2);
35 expect_value(outb, val, (u8)(reg16 >> 8));
36 expect_value(outb, port, I82C54_COUNTER2);
37
38 /* Enable PC speaker */
39 expect_value(inb, port, PC_SPEAKER_PORT);
40 will_return(inb, port_val);
41 expect_value(outb, val, port_val | 0x3);
42 expect_value(outb, port, PC_SPEAKER_PORT);
43 }
44
test_speaker_enable(void ** state)45 static void test_speaker_enable(void **state)
46 {
47 setup_speaker_enable_calls(1, 0);
48 speaker_enable(1);
49
50 setup_speaker_enable_calls(1, 0xff);
51 speaker_enable(1);
52
53 setup_speaker_enable_calls(1, 123);
54 speaker_enable(1);
55
56 setup_speaker_enable_calls(1, -1);
57 speaker_enable(1);
58
59 setup_speaker_enable_calls(-1, 0);
60 speaker_enable(-1);
61
62 setup_speaker_enable_calls(-1, 0xff);
63 speaker_enable(-1);
64
65 setup_speaker_enable_calls(-1, 222);
66 speaker_enable(-1);
67
68 setup_speaker_enable_calls(-1, -1);
69 speaker_enable(-1);
70
71 setup_speaker_enable_calls(10000, 0);
72 speaker_enable(10000);
73
74 setup_speaker_enable_calls(10000, 0xff);
75 speaker_enable(10000);
76
77 setup_speaker_enable_calls(10000, 91);
78 speaker_enable(10000);
79
80 setup_speaker_enable_calls(10000, -1);
81 speaker_enable(10000);
82 }
83
setup_speaker_disable_calls(u8 value)84 static void setup_speaker_disable_calls(u8 value)
85 {
86 expect_value(inb, port, PC_SPEAKER_PORT);
87 will_return(inb, value);
88 expect_value(outb, val, value & 0xfc);
89 expect_value(outb, port, PC_SPEAKER_PORT);
90 }
91
test_speaker_disable(void ** state)92 static void test_speaker_disable(void **state)
93 {
94 setup_speaker_disable_calls(0);
95 speaker_disable();
96
97 setup_speaker_disable_calls(0xfc);
98 speaker_disable();
99
100 setup_speaker_disable_calls(0xff);
101 speaker_disable();
102
103 setup_speaker_disable_calls(0xff - 0xfc);
104 speaker_disable();
105 }
106
arch_ndelay(uint64_t ns)107 void arch_ndelay(uint64_t ns)
108 {
109 check_expected(ns);
110 }
111
setup_speaker_tone_calls(u16 freq,unsigned int duration)112 static void setup_speaker_tone_calls(u16 freq, unsigned int duration)
113 {
114 setup_speaker_enable_calls(freq, ~freq & 0xff);
115 expect_value(arch_ndelay, ns, (uint64_t)duration * NSECS_PER_MSEC);
116 setup_speaker_disable_calls(0xff);
117 expect_any(arch_ndelay, ns);
118 }
119
test_speaker_tone(void ** state)120 static void test_speaker_tone(void **state)
121 {
122 setup_speaker_tone_calls(500, 100);
123 speaker_tone(500, 100);
124
125 setup_speaker_tone_calls(4321, 0);
126 speaker_tone(4321, 0);
127
128 setup_speaker_tone_calls(-1, -1);
129 speaker_tone(-1, -1);
130
131 setup_speaker_tone_calls(10000, 1000);
132 speaker_tone(10000, 1000);
133
134 setup_speaker_tone_calls(433, 890);
135 speaker_tone(433, 890);
136 }
137
main(void)138 int main(void)
139 {
140 const struct CMUnitTest tests[] = {
141 cmocka_unit_test(test_speaker_enable),
142 cmocka_unit_test(test_speaker_disable),
143 cmocka_unit_test(test_speaker_tone),
144 };
145
146 return lp_run_group_tests(tests, NULL, NULL);
147 }
148