185835Siwasaki/*-
285835Siwasaki * Copyright (c) 2001 Mitsuru IWASAKI
385835Siwasaki * All rights reserved.
485835Siwasaki *
585835Siwasaki * Redistribution and use in source and binary forms, with or without
685835Siwasaki * modification, are permitted provided that the following conditions
785835Siwasaki * are met:
885835Siwasaki * 1. Redistributions of source code must retain the above copyright
985835Siwasaki *    notice, this list of conditions and the following disclaimer.
1085835Siwasaki * 2. Redistributions in binary form must reproduce the above copyright
1185835Siwasaki *    notice, this list of conditions and the following disclaimer in the
1285835Siwasaki *    documentation and/or other materials provided with the distribution.
1385835Siwasaki *
1485835Siwasaki * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
1585835Siwasaki * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1685835Siwasaki * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1785835Siwasaki * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
1885835Siwasaki * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
1985835Siwasaki * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2085835Siwasaki * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2185835Siwasaki * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2285835Siwasaki * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2385835Siwasaki * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2485835Siwasaki * SUCH DAMAGE.
2585835Siwasaki */
2685835Siwasaki
27116182Sobrien#include <sys/cdefs.h>
28116182Sobrien__FBSDID("$FreeBSD$");
29116182Sobrien
3085835Siwasaki#include <sys/param.h>
3185835Siwasaki#include <sys/systm.h>
3291640Siwasaki#include <sys/proc.h>
3385835Siwasaki
3485835Siwasaki#include <sys/power.h>
35152222Simp#include <sys/taskqueue.h>
3685835Siwasaki
3785835Siwasakistatic u_int		 power_pm_type	= POWER_PM_TYPE_NONE;
3885835Siwasakistatic power_pm_fn_t	 power_pm_fn	= NULL;
3985835Siwasakistatic void		*power_pm_arg	= NULL;
40152222Simpstatic struct task	 power_pm_task;
4185835Siwasaki
42152222Simpstatic void
43152222Simppower_pm_deferred_fn(void *arg, int pending)
44152222Simp{
45152246Sjhb	int state = (intptr_t)arg;
46152222Simp
47152222Simp	power_pm_fn(POWER_CMD_SUSPEND, power_pm_arg, state);
48152222Simp}
49152222Simp
5085835Siwasakiint
5185835Siwasakipower_pm_register(u_int pm_type, power_pm_fn_t pm_fn, void *pm_arg)
5285835Siwasaki{
5385835Siwasaki	int	error;
5485835Siwasaki
5585835Siwasaki	if (power_pm_type == POWER_PM_TYPE_NONE ||
5685835Siwasaki	    power_pm_type == pm_type) {
5785835Siwasaki		power_pm_type	= pm_type;
5885835Siwasaki		power_pm_fn	= pm_fn;
5985835Siwasaki		power_pm_arg	= pm_arg;
6085835Siwasaki		error = 0;
61152222Simp		TASK_INIT(&power_pm_task, 0, power_pm_deferred_fn, NULL);
6285835Siwasaki	} else {
6385835Siwasaki		error = ENXIO;
6485835Siwasaki	}
6585835Siwasaki
6685835Siwasaki	return (error);
6785835Siwasaki}
6885835Siwasaki
6985835Siwasakiu_int
7085835Siwasakipower_pm_get_type(void)
7185835Siwasaki{
7285835Siwasaki
7385835Siwasaki	return (power_pm_type);
7485835Siwasaki}
7585835Siwasaki
7685835Siwasakivoid
7785835Siwasakipower_pm_suspend(int state)
7885835Siwasaki{
7985835Siwasaki	if (power_pm_fn == NULL)
8085835Siwasaki		return;
8185835Siwasaki
8285835Siwasaki	if (state != POWER_SLEEP_STATE_STANDBY &&
8385835Siwasaki	    state != POWER_SLEEP_STATE_SUSPEND &&
8485835Siwasaki	    state != POWER_SLEEP_STATE_HIBERNATE)
8585835Siwasaki		return;
86152246Sjhb	power_pm_task.ta_context = (void *)(intptr_t)state;
87152248Simp	taskqueue_enqueue(taskqueue_thread, &power_pm_task);
8885835Siwasaki}
8985835Siwasaki
9091640Siwasaki/*
9191640Siwasaki * Power profile.
9291640Siwasaki */
9391640Siwasaki
9491640Siwasakistatic int	power_profile_state = POWER_PROFILE_PERFORMANCE;
9591640Siwasaki
9691640Siwasakiint
9791640Siwasakipower_profile_get_state(void)
9891640Siwasaki{
9991640Siwasaki	return (power_profile_state);
10091640Siwasaki}
10191640Siwasaki
10291640Siwasakivoid
10391640Siwasakipower_profile_set_state(int state)
10491640Siwasaki{
10591640Siwasaki	int		changed;
10691640Siwasaki
10791640Siwasaki	if (state != power_profile_state) {
10891640Siwasaki		power_profile_state = state;
10991640Siwasaki		changed = 1;
110124079Snjl		if (bootverbose) {
111124079Snjl			printf("system power profile changed to '%s'\n",
112124079Snjl				(state == POWER_PROFILE_PERFORMANCE) ?
113124079Snjl				"performance" : "economy");
114124079Snjl		}
11591640Siwasaki	} else {
11691640Siwasaki		changed = 0;
11791640Siwasaki	}
11891640Siwasaki
11991640Siwasaki	if (changed)
120100112Smarkm		EVENTHANDLER_INVOKE(power_profile_change, 0);
12191640Siwasaki}
12291640Siwasaki
123