diff options
-rw-r--r-- | common/keyboard.c | 24 | ||||
-rw-r--r-- | common/lightbar.c | 302 | ||||
-rw-r--r-- | include/lightbar.h | 10 |
3 files changed, 262 insertions, 74 deletions
diff --git a/common/keyboard.c b/common/keyboard.c index 183cae329b..56fc8fd8c3 100644 --- a/common/keyboard.c +++ b/common/keyboard.c @@ -10,6 +10,7 @@ #include "console.h" #include "keyboard.h" #include "i8042.h" +#include "lightbar.h" #include "lpc.h" #include "lpc_commands.h" #include "registers.h" @@ -44,6 +45,7 @@ static uint8_t controller_ram[0x20] = { /* 0x01 - 0x1f are controller RAM */ }; static int power_button_pressed = 0; +static void keyboard_special(uint16_t k); /* * Scancode settings @@ -145,6 +147,9 @@ static enum ec_error_list matrix_callback( return EC_ERROR_INVAL; } + if (pressed) + keyboard_special(scancode_set1[row][col]); + *len = 0; code_set = acting_code_set(code_set); @@ -601,6 +606,25 @@ int handle_keyboard_command(uint8_t command, uint8_t *output) { return out_len; } +/* U U D D L R L R b a */ +static void keyboard_special(uint16_t k) +{ + static uint8_t s = 0; + static const uint16_t a[] = {0xe048, 0xe048, 0xe050, 0xe050, 0xe04b, + 0xe04d, 0xe04b, 0xe04d, 0x0030, 0x001e}; + if (k == a[s]) + s++; + else if (k != 0xe048) + s = 0; + else if (s != 2) + s = 1; + if (s == ARRAY_SIZE(a)) { + s = 0; +#ifdef CONFIG_TASK_LIGHTBAR + lightbar_sequence(LIGHTBAR_KONAMI); +#endif + } +} void keyboard_set_power_button(int pressed) { diff --git a/common/lightbar.c b/common/lightbar.c index 965c4f8261..f2e95e3a74 100644 --- a/common/lightbar.c +++ b/common/lightbar.c @@ -53,7 +53,7 @@ static inline uint8_t controller_read(int ctrl_num, uint8_t reg) #define MAX_GREEN 0x38 #define MAX_BLUE 0x67 -/* How many LEDs do we have? Right now, only four. */ +/* How many LEDs do we have? */ #define NUM_LEDS 4 /* How we'd like to see the driver chips initialized. The controllers have some @@ -119,6 +119,22 @@ static inline uint8_t scale(int val, int max) return scale_abs((val * brightness)/255, max); } + +/* Helper function. */ +static void setrgb(int led, int red, int green, int blue) +{ + int ctrl, bank; + current[led][0] = red; + current[led][1] = green; + current[led][2] = blue; + ctrl = led_to_ctrl[led]; + bank = led_to_isc[led]; + controller_write(ctrl, bank, scale(blue, MAX_BLUE)); + controller_write(ctrl, bank+1, scale(red, MAX_RED)); + controller_write(ctrl, bank+2, scale(green, MAX_GREEN)); +} + + /******************************************************************************/ /* Basic LED control functions. */ /******************************************************************************/ @@ -139,18 +155,17 @@ static void lightbar_on(void) controller_write(1, 0x01, 0x20); } -/* LEDs are numbered 0-3, RGB values should be in 0-255. */ -static void lightbar_setcolor(int led, int red, int green, int blue) + +/* LEDs are numbered 0-3, RGB values should be in 0-255. + * If you specify too large an LED, it sets them all. */ +static void lightbar_setrgb(int led, int red, int green, int blue) { - int ctrl, bank; - current[led][0] = red; - current[led][1] = green; - current[led][2] = blue; - ctrl = led_to_ctrl[led]; - bank = led_to_isc[led]; - controller_write(ctrl, bank, scale(blue, MAX_BLUE)); - controller_write(ctrl, bank+1, scale(red, MAX_RED)); - controller_write(ctrl, bank+2, scale(green, MAX_GREEN)); + int i; + if (led >= NUM_LEDS) + for (i = 0; i < NUM_LEDS; i++) + setrgb(i, red, green, blue); + else + setrgb(led, red, green, blue); } static inline void lightbar_brightness(int newval) @@ -159,7 +174,7 @@ static inline void lightbar_brightness(int newval) uart_printf("%s[(%d)]\n", __func__, newval); brightness = newval; for (i = 0; i < NUM_LEDS; i++) - lightbar_setcolor(i, current[i][0], + lightbar_setrgb(i, current[i][0], current[i][1], current[i][2]); } @@ -198,7 +213,7 @@ static uint32_t sequence_s5(void) /* For now, do something to indicate S5. We might see it. */ lightbar_on(); for (i = 0; i < NUM_LEDS; i++) - lightbar_setcolor(i, 255, 0, 0); + lightbar_setrgb(i, 255, 0, 0); /* The lightbar loses power in S5, so just wait forever. */ WAIT_OR_RET(-1); @@ -221,7 +236,7 @@ static uint32_t sequence_s5s3(void) * We might see it. */ lightbar_on(); for (i = 0; i < NUM_LEDS; i++) - lightbar_setcolor(i, 255, 255, 255); + lightbar_setrgb(i, 255, 255, 255); WAIT_OR_RET(500000); return 0; @@ -240,9 +255,9 @@ static uint32_t sequence_s0(void) l = l % NUM_LEDS; n = n % 5; if (n == 4) - lightbar_setcolor(l, 0, 0, 0); + lightbar_setrgb(l, 0, 0, 0); else - lightbar_setcolor(l, testy[n].r, + lightbar_setrgb(l, testy[n].r, testy[n].g, testy[n].b); l++; n++; @@ -257,18 +272,18 @@ static uint32_t sequence_s0s3(void) { uart_printf("[%s()]\n", __func__); lightbar_on(); - lightbar_setcolor(0, 0, 0, 255); - lightbar_setcolor(1, 255, 0, 0); - lightbar_setcolor(2, 255, 255, 0); - lightbar_setcolor(3, 0, 255, 0); + lightbar_setrgb(0, 0, 0, 255); + lightbar_setrgb(1, 255, 0, 0); + lightbar_setrgb(2, 255, 255, 0); + lightbar_setrgb(3, 0, 255, 0); WAIT_OR_RET(200000); - lightbar_setcolor(0, 0, 0, 0); + lightbar_setrgb(0, 0, 0, 0); WAIT_OR_RET(200000); - lightbar_setcolor(1, 0, 0, 0); + lightbar_setrgb(1, 0, 0, 0); WAIT_OR_RET(200000); - lightbar_setcolor(2, 0, 0, 0); + lightbar_setrgb(2, 0, 0, 0); WAIT_OR_RET(200000); - lightbar_setcolor(3, 0, 0, 0); + lightbar_setrgb(3, 0, 0, 0); return 0; } @@ -279,18 +294,18 @@ static uint32_t sequence_s3(void) uart_printf("[%s()]\n", __func__); lightbar_off(); lightbar_init_vals(); - lightbar_setcolor(0, 0, 0, 0); - lightbar_setcolor(1, 0, 0, 0); - lightbar_setcolor(2, 0, 0, 0); - lightbar_setcolor(3, 0, 0, 0); + lightbar_setrgb(0, 0, 0, 0); + lightbar_setrgb(1, 0, 0, 0); + lightbar_setrgb(2, 0, 0, 0); + lightbar_setrgb(3, 0, 0, 0); while (1) { WAIT_OR_RET(3000000); lightbar_on(); i = i % NUM_LEDS; /* FIXME: indicate battery level? */ - lightbar_setcolor(i, testy[i].r, testy[i].g, testy[i].b); + lightbar_setrgb(i, testy[i].r, testy[i].g, testy[i].b); WAIT_OR_RET(100000); - lightbar_setcolor(i, 0, 0, 0); + lightbar_setrgb(i, 0, 0, 0); i++; lightbar_off(); } @@ -304,13 +319,13 @@ static uint32_t sequence_s3s0(void) uart_printf("[%s()]\n", __func__); lightbar_init_vals(); lightbar_on(); - lightbar_setcolor(0, 0, 0, 255); + lightbar_setrgb(0, 0, 0, 255); WAIT_OR_RET(200000); - lightbar_setcolor(1, 255, 0, 0); + lightbar_setrgb(1, 255, 0, 0); WAIT_OR_RET(200000); - lightbar_setcolor(2, 255, 255, 0); + lightbar_setrgb(2, 255, 255, 0); WAIT_OR_RET(200000); - lightbar_setcolor(3, 0, 255, 0); + lightbar_setrgb(3, 0, 255, 0); WAIT_OR_RET(200000); return 0; } @@ -326,7 +341,7 @@ static uint32_t sequence_s3s5(void) * We might see it. */ lightbar_on(); for (i = 0; i < NUM_LEDS; i++) - lightbar_setcolor(i, 0, 0, 255); + lightbar_setrgb(i, 0, 0, 255); WAIT_OR_RET(500000); return 0; @@ -349,7 +364,7 @@ static uint32_t sequence_test(void) r = testy[i].r ? k : 0; g = testy[i].g ? k : 0; b = testy[i].b ? k : 0; - lightbar_setcolor(j, r, g, b); + lightbar_setrgb(j, r, g, b); } WAIT_OR_RET(10000); } @@ -358,7 +373,7 @@ static uint32_t sequence_test(void) r = testy[i].r ? k : 0; g = testy[i].g ? k : 0; b = testy[i].b ? k : 0; - lightbar_setcolor(j, r, g, b); + lightbar_setrgb(j, r, g, b); } WAIT_OR_RET(10000); } @@ -373,38 +388,28 @@ static uint32_t sequence_test(void) static uint32_t sequence_pulse(void) { uint32_t msg; - int r, g, b; + int r = scale(255, MAX_RED); + int g = scale(255, MAX_BLUE); + int b = scale(255, MAX_GREEN); + struct initdata_s pulse_vals[] = { + {0x11, 0xce}, + {0x12, 0x67}, + {0x13, 0xef}, + {0x15, b}, + {0x16, r}, + {0x17, g}, + {0x18, b}, + {0x19, r}, + {0x1a, g}, + }; uart_printf("[%s()]\n", __func__); - r = scale(255, MAX_RED); - g = scale(255, MAX_BLUE); - b = scale(255, MAX_GREEN); - lightbar_init_vals(); lightbar_on(); - controller_write(0, 0x11, 0xce); - controller_write(0, 0x12, 0x67); - controller_write(0, 0x13, 0xef); - - controller_write(0, 0x15, b); - controller_write(0, 0x16, r); - controller_write(0, 0x17, g); - controller_write(0, 0x18, b); - controller_write(0, 0x19, r); - controller_write(0, 0x1a, g); - - controller_write(1, 0x11, 0xce); - controller_write(1, 0x12, 0x67); - controller_write(1, 0x13, 0xcd); - - controller_write(1, 0x15, b); - controller_write(1, 0x16, r); - controller_write(1, 0x17, g); - controller_write(1, 0x18, b); - controller_write(1, 0x19, r); - controller_write(1, 0x1a, g); + set_from_array(pulse_vals, ARRAY_SIZE(pulse_vals)); + controller_write(1, 0x13, 0xcd); /* this one's different */ /* Not using WAIT_OR_RET() here, because we want to clean up when we're * done. The only way out is to get a message. */ @@ -413,13 +418,155 @@ static uint32_t sequence_pulse(void) return TASK_EVENT_CUSTOM(msg); } + + +/* The host CPU (or someone) is going to poke at the lightbar directly, so we + * don't want the EC messing with it. We'll just sit here and ignore all + * other messages until we're told to continue. */ +static uint32_t sequence_ec_stop(void) +{ + uint32_t msg; + + uart_printf("[%s()]\n", __func__); + + do { + msg = TASK_EVENT_CUSTOM(task_wait_event(-1)); + uart_printf("[%s - got msg %x]\n", __func__, msg); + } while (msg != LIGHTBAR_EC_RUN); + /* FIXME: What should we do if the host shuts down? */ + + uart_printf("[%s() - leaving]\n", __func__); + + return 0; +} + +/* We shouldn't come here, but if we do it shouldn't hurt anything */ +static uint32_t sequence_error(void) +{ + uart_printf("[%s()]\n", __func__); + + lightbar_init_vals(); + lightbar_on(); + + lightbar_setrgb(0, 255, 255, 255); + lightbar_setrgb(1, 255, 0, 255); + lightbar_setrgb(2, 0, 255, 255); + lightbar_setrgb(3, 255, 255, 255); + + WAIT_OR_RET(10000000); + + return 0; +} + + +static const struct { + uint8_t led; + uint8_t r, g, b; + unsigned int delay; +} konami[] = { + + {1, 0xff, 0xff, 0x00, 0}, + {2, 0xff, 0xff, 0x00, 100000}, + {1, 0x00, 0x00, 0x00, 0}, + {2, 0x00, 0x00, 0x00, 100000}, + + {1, 0xff, 0xff, 0x00, 0}, + {2, 0xff, 0xff, 0x00, 100000}, + {1, 0x00, 0x00, 0x00, 0}, + {2, 0x00, 0x00, 0x00, 100000}, + + {0, 0x00, 0x00, 0xff, 0}, + {3, 0x00, 0x00, 0xff, 100000}, + {0, 0x00, 0x00, 0x00, 0}, + {3, 0x00, 0x00, 0x00, 100000}, + + {0, 0x00, 0x00, 0xff, 0}, + {3, 0x00, 0x00, 0xff, 100000}, + {0, 0x00, 0x00, 0x00, 0}, + {3, 0x00, 0x00, 0x00, 100000}, + + {0, 0xff, 0x00, 0x00, 0}, + {1, 0xff, 0x00, 0x00, 100000}, + {0, 0x00, 0x00, 0x00, 0}, + {1, 0x00, 0x00, 0x00, 100000}, + + {2, 0x00, 0xff, 0x00, 0}, + {3, 0x00, 0xff, 0x00, 100000}, + {2, 0x00, 0x00, 0x00, 0}, + {3, 0x00, 0x00, 0x00, 100000}, + + {0, 0xff, 0x00, 0x00, 0}, + {1, 0xff, 0x00, 0x00, 100000}, + {0, 0x00, 0x00, 0x00, 0}, + {1, 0x00, 0x00, 0x00, 100000}, + + {2, 0x00, 0xff, 0x00, 0}, + {3, 0x00, 0xff, 0x00, 100000}, + {2, 0x00, 0x00, 0x00, 0}, + {3, 0x00, 0x00, 0x00, 100000}, + + {0, 0x00, 0xff, 0xff, 0}, + {2, 0x00, 0xff, 0xff, 100000}, + {0, 0x00, 0x00, 0x00, 0}, + {2, 0x00, 0x00, 0x00, 150000}, + + {1, 0xff, 0x00, 0xff, 0}, + {3, 0xff, 0x00, 0xff, 100000}, + {1, 0x00, 0x00, 0x00, 0}, + {3, 0x00, 0x00, 0x00, 250000}, + + {4, 0xff, 0xff, 0xff, 100000}, + {4, 0x00, 0x00, 0x00, 100000}, + + {4, 0xff, 0xff, 0xff, 100000}, + {4, 0x00, 0x00, 0x00, 100000}, + + {4, 0xff, 0xff, 0xff, 100000}, + {4, 0x00, 0x00, 0x00, 100000}, + + {4, 0xff, 0xff, 0xff, 100000}, + {4, 0x00, 0x00, 0x00, 100000}, + + {4, 0xff, 0xff, 0xff, 100000}, + {4, 0x00, 0x00, 0x00, 100000}, + + {4, 0xff, 0xff, 0xff, 100000}, + {4, 0x00, 0x00, 0x00, 100000}, + +}; + +static uint32_t sequence_konami(void) +{ + int i; + int tmp; + + uart_printf("[%s()]\n", __func__); + lightbar_init_vals(); + lightbar_on(); + + tmp = brightness; + brightness = 255; + + for (i = 0; i < ARRAY_SIZE(konami); i++) { + lightbar_setrgb(konami[i].led, + konami[i].r, konami[i].g, konami[i].b); + if (konami[i].delay) + usleep(konami[i].delay); + } + + brightness = tmp; + + return 0; +} + /****************************************************************************/ -/* Lightbar task. It just cycles between various pretty patterns. */ +/* The main lightbar task. It just cycles between various pretty patterns. */ /****************************************************************************/ -/* IMPORTANT: The order here must match the enum lightbar_sequence values. */ +/* IMPORTANT: The order here must match the enum lightbar_sequence order. + * FIXME: Use some preprocessor tricks to ensure that's always true. */ static uint32_t (*sequence[])(void) = { - 0, + sequence_error, /* idle - not used */ sequence_s5, sequence_s3, sequence_s0, @@ -427,8 +574,11 @@ static uint32_t (*sequence[])(void) = { sequence_s3s0, sequence_s0s3, sequence_s3s5, - sequence_test, + sequence_ec_stop, + sequence_error, /* unexpected ec run */ sequence_pulse, + sequence_test, + sequence_konami, }; void lightbar_task(void) @@ -469,6 +619,10 @@ void lightbar_task(void) state = LIGHTBAR_S5; break; case LIGHTBAR_TEST: + case LIGHTBAR_EC_STOP: + case LIGHTBAR_EC_RUN: + case LIGHTBAR_NULL: + case LIGHTBAR_KONAMI: state = previous_state; default: break; @@ -478,7 +632,7 @@ void lightbar_task(void) } -/* Request a preset sequence from the lightbar task. */ +/* Function to request a preset sequence from the lightbar task. */ void lightbar_sequence(enum lightbar_sequence num) { uart_printf("[%s(%d)]\n", __func__, num); @@ -516,8 +670,8 @@ DECLARE_HOST_COMMAND(EC_LPC_COMMAND_LIGHTBAR_TEST, lpc_cmd_test); static int help(const char *cmd) { uart_printf("Usage: %s\n", cmd); - uart_printf(" %s reset\n", cmd); uart_printf(" %s off\n", cmd); + uart_printf(" %s init\n", cmd); uart_printf(" %s on\n", cmd); uart_printf(" %s msg NUM\n", cmd); uart_printf(" %s brightness NUM\n", cmd); @@ -543,6 +697,8 @@ static void dump_regs(void) static int command_lightbar(int argc, char **argv) { + int i; + if (1 == argc) { /* no args = dump 'em all */ dump_regs(); return EC_SUCCESS; @@ -592,7 +748,11 @@ static int command_lightbar(int argc, char **argv) int red = strtoi(argv[2], &e, 16); int green = strtoi(argv[3], &e, 16); int blue = strtoi(argv[4], &e, 16); - lightbar_setcolor(led, red, green, blue); + if (led >= NUM_LEDS) + for (i = 0; i < NUM_LEDS; i++) + lightbar_setrgb(i, red, green, blue); + else + lightbar_setrgb(led, red, green, blue); return EC_SUCCESS; } diff --git a/include/lightbar.h b/include/lightbar.h index 37f8980a34..58e4053765 100644 --- a/include/lightbar.h +++ b/include/lightbar.h @@ -19,9 +19,13 @@ enum lightbar_sequence { LIGHTBAR_S3S0, /* 5 */ LIGHTBAR_S0S3, /* 6 */ LIGHTBAR_S3S5, /* 7 */ - /* extra patterns */ - LIGHTBAR_TEST, /* 8 */ - LIGHTBAR_PULSE, /* 9 */ + /* Who's in charge? */ + LIGHTBAR_EC_STOP, /* 8 - EC ignore LEDs */ + LIGHTBAR_EC_RUN, /* 9 - EC drive LEDs */ + /* Extra patterns */ + LIGHTBAR_PULSE, /* a */ + LIGHTBAR_TEST, /* b */ + LIGHTBAR_KONAMI, /* c */ /* that's all */ LIGHTBAR_NUM_SEQUENCES }; |