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