diff options
-rw-r--r-- | zephyr/program/geralt/src/base_detect.c | 101 |
1 files changed, 96 insertions, 5 deletions
diff --git a/zephyr/program/geralt/src/base_detect.c b/zephyr/program/geralt/src/base_detect.c index b3f078486d..074c2db5f9 100644 --- a/zephyr/program/geralt/src/base_detect.c +++ b/zephyr/program/geralt/src/base_detect.c @@ -3,21 +3,101 @@ * found in the LICENSE file. */ +#include "adc.h" +#include "ap_power/ap_power.h" #include "base_state.h" +#include "chipset.h" +#include "console.h" +#include "hooks.h" #include "tablet_mode.h" -#include <zephyr/init.h> +#include <zephyr/drivers/gpio.h> + +#define CPRINTS(format, args...) cprints(CC_SYSTEM, format, ##args) +#define CPRINTF(format, args...) cprintf(CC_SYSTEM, format, ##args) + +#define BASE_DETECT_INTERVAL (200 * MSEC) +#define ATTACH_MAX_THRESHOLD_MV 300 +#define DETACH_MIN_THRESHOLD_MV 3000 static void base_update(bool attached) { + const struct gpio_dt_spec *en_cc_lid_base_pu = + GPIO_DT_FROM_NODELABEL(en_cc_lid_base_pu); + base_set_state(attached); tablet_set_mode(!attached, TABLET_TRIGGER_BASE); + + gpio_pin_set_dt(GPIO_DT_FROM_NODELABEL(en_ppvar_base_x), attached); + gpio_pin_configure(en_cc_lid_base_pu->port, en_cc_lid_base_pu->pin, + attached ? GPIO_OUTPUT_HIGH : GPIO_INPUT); +} + +static void base_detect_tick(void); +DECLARE_DEFERRED(base_detect_tick); + +static void base_detect_tick(void) +{ + static bool debouncing; + int mv = adc_read_channel(ADC_BASE_DET); + + if (mv >= DETACH_MIN_THRESHOLD_MV && base_get_state()) { + if (!debouncing) { + debouncing = true; + } else { + debouncing = false; + base_update(false); + } + } else if (mv <= ATTACH_MAX_THRESHOLD_MV && !base_get_state()) { + if (!debouncing) { + debouncing = true; + } else { + debouncing = false; + base_update(true); + } + } else { + debouncing = false; + } + hook_call_deferred(&base_detect_tick_data, BASE_DETECT_INTERVAL); +} + +static void base_detect_enable(bool enable) +{ + if (enable) { + hook_call_deferred(&base_detect_tick_data, + BASE_DETECT_INTERVAL); + } else { + hook_call_deferred(&base_detect_tick_data, -1); + base_update(false); + } +} + +static void base_startup_hook(struct ap_power_ev_callback *cb, + struct ap_power_ev_data data) +{ + switch (data.event) { + case AP_POWER_STARTUP: + base_detect_enable(true); + break; + case AP_POWER_SHUTDOWN: + base_detect_enable(false); + break; + default: + return; + } } static int base_init(const struct device *unused) { - /* TODO: this is a temporary fix to force tablet mode for developers. */ - base_update(false); + static struct ap_power_ev_callback cb; + + ap_power_ev_init_callback(&cb, base_startup_hook, + AP_POWER_STARTUP | AP_POWER_SHUTDOWN); + ap_power_ev_add_callback(&cb); + + if (!chipset_in_state(CHIPSET_STATE_ANY_OFF)) { + base_detect_enable(true); + } return 0; } @@ -26,6 +106,17 @@ SYS_INIT(base_init, APPLICATION, 1); void base_force_state(enum ec_set_base_state_cmd state) { - /* TODO: not implemented yet */ - base_update(state == EC_SET_BASE_STATE_ATTACH); + switch (state) { + case EC_SET_BASE_STATE_ATTACH: + base_update(true); + base_detect_enable(false); + break; + case EC_SET_BASE_STATE_DETACH: + base_update(false); + base_detect_enable(false); + break; + case EC_SET_BASE_STATE_RESET: + base_detect_enable(true); + break; + } } |