Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add power domain support, device power management policy and fix display re-init bug #1300

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion app/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,8 @@ target_sources(app PRIVATE src/matrix_transform.c)
target_sources(app PRIVATE src/sensors.c)
target_sources_ifdef(CONFIG_ZMK_WPM app PRIVATE src/wpm.c)
target_sources(app PRIVATE src/event_manager.c)
target_sources_ifdef(CONFIG_ZMK_EXT_POWER app PRIVATE src/ext_power_generic.c)
target_sources_ifdef(CONFIG_ZMK_EXT_POWER app PRIVATE src/power_domain.c)
target_sources_ifdef(CONFIG_ZMK_EXT_POWER app PRIVATE src/dev_pm_policy.c)
target_sources(app PRIVATE src/events/activity_state_changed.c)
target_sources(app PRIVATE src/events/position_state_changed.c)
target_sources(app PRIVATE src/events/sensor_event.c)
Expand Down
33 changes: 25 additions & 8 deletions app/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -381,6 +381,10 @@ endmenu

menu "Power Management"

config ZMK_EXT_POWER
bool "Enable support to control external power output"
default y

config ZMK_IDLE_TIMEOUT
int "Milliseconds of inactivity before entering idle state (OLED shutoff, etc)"
default 30000
Expand All @@ -389,22 +393,35 @@ config ZMK_SLEEP
bool "Enable deep sleep support"
imply USB

if ZMK_SLEEP
config POWER_DOMAIN
default y

if ZMK_EXT_POWER

config POWER_DOMAIN_GPIO
default y

endif

config PM_DEVICE
default y

config ZMK_IDLE_SLEEP_TIMEOUT
int "Milliseconds of inactivity before entering deep sleep"
default 900000
config PM_DEVICE_POWER_DOMAIN
default y

#ZMK_SLEEP
endif
config PM_DEVICE_POWER_DOMAIN_DYNAMIC
default y

config ZMK_EXT_POWER
bool "Enable support to control external power output"
config PM_DEVICE_POWER_DOMAIN_DYNAMIC_NUM
default 10

config PM_DEVICE_RUNTIME
default y

config ZMK_IDLE_SLEEP_TIMEOUT
int "Milliseconds of inactivity before entering deep sleep"
default 900000

#Power Management
endmenu

Expand Down
7 changes: 7 additions & 0 deletions app/boards/arm/nice_nano/nice_nano.dts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
/ {
chosen {
zmk,battery = &vbatt;
zmk,default-power-domain = &pd_ext_power;
};

ext-power {
Expand All @@ -18,6 +19,12 @@
control-gpios = <&gpio0 13 GPIO_ACTIVE_LOW>;
};

pd_ext_power: pd_ext_power {
compatible = "power-domain-gpio";
label = "PD_EXT_POWER";
enable-gpios = <&gpio0 13 GPIO_ACTIVE_LOW>;
};

vbatt: vbatt {
compatible = "zmk,battery-voltage-divider";
label = "BATTERY";
Expand Down
1 change: 1 addition & 0 deletions app/boards/arm/nice_nano/nice_nano.dtsi
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@

&i2c0 {
compatible = "nordic,nrf-twi";
power-domain = <&pd_ext_power>;
sda-pin = <17>;
scl-pin = <20>;
};
Expand Down
11 changes: 6 additions & 5 deletions app/boards/arm/nice_nano/nice_nano_v2.dts
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,14 @@
/ {
chosen {
zmk,battery = &vbatt;
zmk,default-power-domain = &pd_ext_power;
};

ext-power {
compatible = "zmk,ext-power-generic";
label = "EXT_POWER";
control-gpios = <&gpio0 13 GPIO_ACTIVE_HIGH>;
init-delay-ms = <50>;
pd_ext_power: pd_ext_power {
compatible = "power-domain-gpio";
label = "PD_EXT_POWER";
enable-gpios = <&gpio0 13 GPIO_ACTIVE_HIGH>;
startup-delay-us = <50000>;
};

vbatt: vbatt {
Expand Down
8 changes: 8 additions & 0 deletions app/dts/bindings/behaviors/zmk,behavior-ext-power.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,11 @@ description: External power control Behavior
compatible: "zmk,behavior-ext-power"

include: one_param.yaml

properties:
power-domain:
required: false
type: phandle
description: |

Power domain the behavior should execute the action on.
32 changes: 32 additions & 0 deletions app/dts/bindings/zmk,dev-pm-policy.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
# Copyright (c) 2020 The ZMK Contributors
# SPDX-License-Identifier: MIT

description: Device Power Management Policy

compatible: "zmk,dev-pm-policy"

properties:
label:
type: string
required: true

device:
type: phandle
required: true
description: |

The device or power domain on which the power management policy should be run on.

auto-off-on-idle:
type: boolean
required: false
description: |

Automatically turn off a device or power domain when the keyboard is idle.

usb-auto-toggle:
type: boolean
required: false
description: |

Automatically turn off a device or power domain when usb is disconnected and turn on when usb is connected.
104 changes: 0 additions & 104 deletions app/include/drivers/ext_power.h

This file was deleted.

89 changes: 89 additions & 0 deletions app/include/zmk/power_domain.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
/*
* Copyright (c) 2020 The ZMK Contributors
*
* SPDX-License-Identifier: MIT
*/

#include <pm/device.h>

#pragma once

#if CONFIG_ZMK_EXT_POWER

const int zmk_power_domain_disable(const struct device *pd_dev, bool save_state);
const int zmk_power_domain_enable(const struct device *pd_dev, bool save_state);
const int zmk_power_domain_toggle(const struct device *pd_dev, bool save_state);


/*
* What's the difference between get_state_actual and get_state_user_intended?
*
* We distinguish whether power is actually on and whether the user wants the
* power to be on.
*
* For example, when the user turns on the power, the user intended state is
* ON, bt internal features may despite that turn the power off temporarily.
*
* For example, the auto-off-on-idle feature cuts the power on idle and changes
* the actual state to on, but the intended state stays as on. When activity
* resumes, it checks whether the user wants the power to be on, and if yes,
* enables the actual power again.
*
*/
const int zmk_power_domain_get_state_actual(const struct device *pd_dev);
const int zmk_power_domain_get_state_user_intended(const struct device *pd_dev);


/*
* Power Domain manager helper function
*
* In order to receive power domain notifications in ZMK devices, such as the
* display and rgb_underglow, we need to create a power domain manager device
* that has a power domain configured.
*
* This sets the power domain to a dynamically created device and syncs the
* state of the device to the power domain.
*/
int zmk_power_domain_init_power_domain_manager_helper(const struct device *dev, const struct device *pd_dev);

/**
* @cond INTERNAL_HIDDEN
*
* Internal helper functions
*/

#define DEFAULT_POWER_DOMAIN DT_CHOSEN(zmk_default_power_domain)

/** @brief ZMK Power Domain Actions. */
enum zmk_power_domain_action {
/** Turn the Power Domain off. */
ZMK_PD_ACTION_TURN_OFF,
/** Turn the Power Domain on. */
ZMK_PD_ACTION_TURN_ON,
/** Toggle the Power Domain*/
ZMK_PD_ACTION_TOGGLE,
};
const int zmk_power_domain_run_action(const struct device *pd_dev, enum zmk_power_domain_action zmk_action, bool save_state);
int zmk_power_domain_save_state();

const struct device * zmk_power_domain_get_default();
struct zmk_power_domain_data *zmk_power_domain_get_pd_data_for_pd(const struct device *pd_dev);
struct zmk_power_domain_data *zmk_power_domain_get_pd_data_by_name(const char *name);
void zmk_power_domain_set_pd_data_default();
const char *zmk_pm_device_action_str(enum pm_device_action action);
const char *zmk_pm_action_str(enum zmk_power_domain_action action);

/**
* @endcond
*/

#else

const inline int zmk_power_domain_disable(const struct device *pd_dev, bool save_state) { return 0; };
const inline int zmk_power_domain_enable(const struct device *pd_dev, bool save_state) { return 0; };
const inline int zmk_power_domain_toggle(const struct device *pd_dev, bool save_state) { return 0; };
const inline int zmk_power_domain_get_state_actual(const struct device *pd_dev) { return 0; };
const inline int zmk_power_domain_get_state_user_intended(const struct device *pd_dev) { return 0; };
inline int zmk_power_domain_init_power_domain_manager_helper(const struct device *dev, const struct device *pd_dev) { return 0; };

#endif
6 changes: 5 additions & 1 deletion app/include/zmk/rgb_underglow.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ int zmk_rgb_underglow_toggle();
int zmk_rgb_underglow_get_state(bool *state);
int zmk_rgb_underglow_on();
int zmk_rgb_underglow_off();
int zmk_rgb_underglow_resume();
int zmk_rgb_underglow_pause();
int zmk_rgb_underglow_cycle_effect(int direction);
int zmk_rgb_underglow_calc_effect(int direction);
int zmk_rgb_underglow_select_effect(int effect);
Expand All @@ -26,4 +28,6 @@ int zmk_rgb_underglow_change_hue(int direction);
int zmk_rgb_underglow_change_sat(int direction);
int zmk_rgb_underglow_change_brt(int direction);
int zmk_rgb_underglow_change_spd(int direction);
int zmk_rgb_underglow_set_hsb(struct zmk_led_hsb color);
int zmk_rgb_underglow_set_hsb(struct zmk_led_hsb color);

int zmk_rgb_underglow_init_power_domain_manager(const struct device *dev);
Loading