coreboot
coreboot is an Open Source project aimed at replacing the proprietary BIOS found in most computers.
ww_ring_programs.c
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-only */
2 
3 /*
4  * This is a driver for the Whirlwind LED ring, which is equipped with two LED
5  * microcontrollers TI LP55231 (http://www.ti.com/product/lp55231), each of
6  * them driving three multicolor LEDs.
7  *
8  * The only connection between the ring and the main board is an i2c bus.
9  *
10  * This driver imitates a depthcharge display device. On initialization the
11  * driver sets up the controllers to prepare them to accept programs to run.
12  *
13  * When a certain vboot state needs to be indicated, the program for that
14  * state is loaded into the controllers, resulting in the state appropriate
15  * LED behavior.
16  */
17 
19 
20 /****************************************************************
21  * LED ring program definitions for different patterns.
22  *
23  * Comments below are real lp55231 source code, they are compiled using
24  * lasm.exe, the TI tool available from their Web site (search for lp55231)
25  * and running only on Windows :P.
26  *
27  * Different hex dumps are results of tweaking the source code parameters to
28  * achieve desirable LED ring behavior. It is possible to use just one code
29  * dump and replace certain values in the body to achieve different behaviour
30  * with the same basic dump, but keeping track of location to tweak with every
31  * code change would be quite tedious.
32  */
33 
34 /*
35  * Solid LED display, the arguments of the set_pwm commands set intensity and
36  * color of the display:
37 
38 row_red: dw 0000000000000001b
39 row_green: dw 0000000000000010b
40 row_blue: dw 0000000000000100b
41 
42 .segment program1
43  mux_map_addr row_red
44  set_pwm 0
45  end
46 
47 .segment program2
48  mux_map_addr row_green
49  set_pwm 0
50  end
51 
52 .segment program3
53  mux_map_addr row_blue
54  set_pwm 0
55  end
56 */
57 
58 /* RGB set to 000000, resulting in all LEDs off. */
59 static const uint8_t solid_000000_text[] = {
60  0x00, 0x01, 0x00, 0x02, 0x00, 0x04, 0x9F, 0x80,
61  0x40, 0, 0xC0, 0x00, 0x9F, 0x81, 0x40, 0,
62  0xC0, 0x00, 0x9F, 0x82, 0x40, 0, 0xC0, 0x00
63 };
64 
65 /* Rgb set to 128, resulting in a brightish white color. */
66 static const uint8_t solid_808080_text[] = {
67  0x00, 0x01, 0x00, 0x02, 0x00, 0x04, 0x9F, 0x80,
68  0x40, 128, 0xC0, 0x00, 0x9F, 0x81, 0x40, 128,
69  0xC0, 0x00, 0x9F, 0x82, 0x40, 128, 0xC0, 0x00
70 };
71 
74  sizeof(solid_808080_text),
75  0,
76  { 3, 6, 9 }
77 };
78 
81  sizeof(solid_000000_text),
82  0,
83  { 3, 6, 9 }
84 };
85 
86 /*
87  * Blinking patterns are trickier then solid ones.
88  *
89  * The three internal engines seem to be competing for resources and get out
90  * of sync in seconds if left running asynchronously.
91  *
92  * When solid patterns are deployed with instanteneous color intensity
93  * changes, all three LEDs can be controlled by one engine in sequential
94  * accesses. But the controllers still need to be synchronized.
95  *
96  * The maximum timer duration of lp55231 is .48 seconds. To achieve longer
97  * blinking intervals the loops delays are deployed. Only the first controller
98  * intervals need to be changed, as the second one is in lockstep with the
99  * first.
100  *
101  * The time granularity is set at .1 second (see commands 'wait 0.1' in the
102  * code), and then the loop counters can be set up to 63 (registers rb and rc),
103  * which allows to generate intervals up to 6.3 seconds in .1 second
104  * increments.
105  */
106 /*
107  * blink_solid1.src
108 row_red: dw 0000000000000001b
109 row_green: dw 0000000000000010b
110 row_blue: dw 0000000000000100b
111 
112 .segment program1
113  ld ra, 2 # LED on duration
114  ld rb, 2 # LED off duration
115  mux_map_addr row_red
116 loop:
117  ld rc, 1 ; red intensity
118  set_pwm rc
119  mux_map_addr row_green
120  ld rc, 50 ; green intensity
121  set_pwm rc
122  mux_map_addr row_blue
123  ld rc, 155 ; blue intensity
124  set_pwm rc
125 wait1:
126  wait 0.1
127  branch ra, wait1
128  set_pwm 0
129  mux_map_addr row_green
130  set_pwm 0
131  mux_map_addr row_red
132  set_pwm 0
133 wait2:
134  wait 0.1
135  branch rb, wait2
136  branch 0, loop
137 .segment program2
138  end
139 .segment program3
140  end
141 */
142 static const uint8_t blink_wipeout1_text[] = {
143  0x00, 0x01, 0x00, 0x02, 0x00, 0x04, 0x90, 0x02,
144  0x94, 0x02, 0x9f, 0x80, 0x98, 1, 0x84, 0x62,
145  0x9f, 0x81, 0x98, 50, 0x84, 0x62, 0x9f, 0x82,
146  0x98, 155, 0x84, 0x62, 0x4c, 0x00, 0x86, 0x2c,
147  0x40, 0x00, 0x9f, 0x81, 0x40, 0x00, 0x9f, 0x80,
148  0x40, 0x00, 0x4c, 0x00, 0x86, 0x49, 0xa0, 0x03,
149  0xc0, 0x00, 0xc0, 0x00, 0x00,
150 };
151 
154  sizeof(blink_wipeout1_text),
155  0,
156  { 3, 24, 25, }
157 };
158 
159 static const uint8_t blink_recovery1_text[] = {
160  0x00, 0x01, 0x00, 0x02, 0x00, 0x04, 0x90, 0x02,
161  0x94, 0x02, 0x9f, 0x80, 0x98, 255, 0x84, 0x62,
162  0x9f, 0x81, 0x98, 100, 0x84, 0x62, 0x9f, 0x82,
163  0x98, 10, 0x84, 0x62, 0x4c, 0x00, 0x86, 0x2c,
164  0x40, 0x00, 0x9f, 0x81, 0x40, 0x00, 0x9f, 0x80,
165  0x40, 0x00, 0x4c, 0x00, 0x86, 0x49, 0xa0, 0x03,
166  0xc0, 0x00, 0xc0, 0x00, 0x00,
167 };
170  sizeof(blink_recovery1_text),
171  0,
172  { 3, 24, 25, }
173 };
174 
175 /*
176  * fade_in1.src
177  *
178  row_red: dw 0000000000000001b
179  row_green: dw 0000000000000010b
180  row_blue: dw 0000000000000100b
181 
182  .segment program1
183  mux_map_addr row_red
184  set_pwm 1h
185  trigger s{2|3}
186  end
187  .segment program2
188  mux_map_addr row_green
189  set_pwm 0h
190  trigger w{1}
191  ramp 2, 50
192  end
193 .segment program3
194  mux_map_addr row_blue
195  set_pwm 0h
196  loop3: trigger w{1}
197  ramp 2, 155
198  end
199 */
200 
201 static const uint8_t fade_in1_text[] = {
202  0x00, 0x01, 0x00, 0x02, 0x00, 0x04, 0x9f, 0x80,
203  0x40, 0x01, 0xe0, 0x0c, 0xc0, 0x00, 0x9f, 0x81,
204  0x40, 0x00, 0xe0, 0x80, 0x46, 0x32, 0xc0, 0x00,
205  0x9f, 0x82, 0x40, 0x00, 0xe0, 0x80, 0x34, 0x9B,
206  0xc0, 0x00, 0x00,
207 };
210  sizeof(fade_in1_text),
211  0,
212  { 3, 7, 12, }
213 };
214 
216  /*
217  * for test purposes the blank screen program is set to blinking, will
218  * be changed soon.
219  */
225  {}, /* Empty record to mark the end of the table. */
226 };
unsigned char uint8_t
Definition: stdint.h:8
@ WWR_RECOVERY_REQUEST
Definition: ww_ring.h:14
@ WWR_ALL_OFF
Definition: ww_ring.h:11
@ WWR_RECOVERY_PUSHED
Definition: ww_ring.h:12
@ WWR_NORMAL_BOOT
Definition: ww_ring.h:15
@ WWR_WIPEOUT_REQUEST
Definition: ww_ring.h:13
static const uint8_t blink_recovery1_text[]
static const TiLp55231Program solid_808080_program
static const TiLp55231Program blink_wipeout1_program
static const uint8_t fade_in1_text[]
static const uint8_t solid_000000_text[]
static const uint8_t blink_wipeout1_text[]
const WwRingStateProg wwr_state_programs[]
static const TiLp55231Program blink_recovery1_program
static const TiLp55231Program fade_in1_program
static const uint8_t solid_808080_text[]
static const TiLp55231Program solid_000000_program