Commit eff584bf authored by Fabio Baltieri's avatar Fabio Baltieri Committed by Anas Nashif
Browse files

input: kbd_matrix: add power management support



Add power management support to the keyboard matrix library. This
provides a generic pm_action function that changes the keyboard matrix
scan in two places when suspended:
- reset the state to 0 for all columns
- do not enable key press detection

This ensures that any key that was pressed when the device is suspended
is released, and no other scan happens until the device is resumed.

Signed-off-by: default avatarFabio Baltieri <fabiobaltieri@google.com>
parent ee7bbf55
Loading
Loading
Loading
Loading
+58 −7
Original line number Diff line number Diff line
@@ -12,6 +12,9 @@
#include <zephyr/kernel.h>
#include <zephyr/kernel.h>
#include <zephyr/logging/log.h>
#include <zephyr/pm/device.h>
#include <zephyr/pm/device_runtime.h>
#include <zephyr/sys/atomic.h>
#include <zephyr/sys/util.h>

LOG_MODULE_REGISTER(input_kbd_matrix, CONFIG_INPUT_LOG_LEVEL);
@@ -80,6 +83,17 @@ static void input_kbd_matrix_drive_column(const struct device *dev, int col)
#endif
}

static bool input_kbd_matrix_is_suspended(const struct device *dev)
{
#ifdef CONFIG_PM_DEVICE
	struct input_kbd_matrix_common_data *data = dev->data;

	return atomic_get(&data->suspended) == 1;
#else
	return false;
#endif
}

static bool input_kbd_matrix_scan(const struct device *dev)
{
	const struct input_kbd_matrix_common_config *cfg = dev->config;
@@ -93,6 +107,11 @@ static bool input_kbd_matrix_scan(const struct device *dev)
			continue;
		}

		if (input_kbd_matrix_is_suspended(dev)) {
			cfg->matrix_new_state[col] = 0;
			continue;
		};

		input_kbd_matrix_drive_column(dev, col);

		/* Allow the matrix to stabilize before reading it */
@@ -293,6 +312,7 @@ static void input_kbd_matrix_polling_thread(void *arg1, void *unused2, void *unu
	ARG_UNUSED(unused3);

	while (true) {
		if (!input_kbd_matrix_is_suspended(dev)) {
			input_kbd_matrix_drive_column(dev, INPUT_KBD_MATRIX_COLUMN_DRIVE_ALL);
			api->set_detect_mode(dev, true);

@@ -302,6 +322,7 @@ static void input_kbd_matrix_polling_thread(void *arg1, void *unused2, void *unu
			if (api->read_row(dev) != 0) {
				input_kbd_matrix_poll_start(dev);
			}
		}

		k_sem_take(&data->poll_lock, K_FOREVER);
		LOG_DBG("scan start");
@@ -313,9 +334,33 @@ static void input_kbd_matrix_polling_thread(void *arg1, void *unused2, void *unu
	}
}

#ifdef CONFIG_PM_DEVICE
int input_kbd_matrix_pm_action(const struct device *dev,
			       enum pm_device_action action)
{
	struct input_kbd_matrix_common_data *data = dev->data;

	switch (action) {
	case PM_DEVICE_ACTION_SUSPEND:
		atomic_set(&data->suspended, 1);
		break;
	case PM_DEVICE_ACTION_RESUME:
		atomic_set(&data->suspended, 0);
		break;
	default:
		return -ENOTSUP;
	}

	input_kbd_matrix_poll_start(dev);

	return 0;
}
#endif

int input_kbd_matrix_common_init(const struct device *dev)
{
	struct input_kbd_matrix_common_data *data = dev->data;
	int ret;

	k_sem_init(&data->poll_lock, 0, 1);

@@ -326,6 +371,12 @@ int input_kbd_matrix_common_init(const struct device *dev)

	k_thread_name_set(&data->thread, dev->name);

	ret = pm_device_runtime_enable(dev);
	if (ret < 0) {
		LOG_ERR("Failed to enable runtime power management");
		return ret;
	}

	return 0;
}

+19 −0
Original line number Diff line number Diff line
@@ -16,6 +16,8 @@

#include <zephyr/device.h>
#include <zephyr/kernel.h>
#include <zephyr/pm/device.h>
#include <zephyr/sys/atomic.h>
#include <zephyr/sys/util.h>
#include <zephyr/sys_clock.h>
#include <zephyr/toolchain.h>
@@ -248,6 +250,9 @@ struct input_kbd_matrix_common_data {
	uint8_t scan_cycles_idx;

	struct k_sem poll_lock;
#ifdef CONFIG_PM_DEVICE
	atomic_t suspended;
#endif

	struct k_thread thread;

@@ -305,6 +310,20 @@ void input_kbd_matrix_drive_column_hook(const struct device *dev, int col);
 */
int input_kbd_matrix_common_init(const struct device *dev);

#ifdef CONFIG_PM_DEVICE
/**
 * @brief Common power management action handler.
 *
 * This handles PM actions for a keyboard matrix device, meant to be used as
 * argument of @ref PM_DEVICE_DT_INST_DEFINE.
 *
 * @param dev Keyboard matrix device instance.
 * @param action The power management action to handle.
 */
int input_kbd_matrix_pm_action(const struct device *dev,
			       enum pm_device_action action);
#endif

/** @} */

#endif /* ZEPHYR_INCLUDE_INPUT_KBD_MATRIX_H_ */