Linux Audio

Check our new training course

Loading...
Note: File does not exist in v3.1.
  1/* SPDX-License-Identifier: GPL-2.0-or-later */
  2/*
  3 *  ideapad-laptop.h - Lenovo IdeaPad ACPI Extras
  4 *
  5 *  Copyright © 2010 Intel Corporation
  6 *  Copyright © 2010 David Woodhouse <dwmw2@infradead.org>
  7 */
  8
  9#ifndef _IDEAPAD_LAPTOP_H_
 10#define _IDEAPAD_LAPTOP_H_
 11
 12#include <linux/acpi.h>
 13#include <linux/jiffies.h>
 14#include <linux/errno.h>
 15
 16enum {
 17	VPCCMD_R_VPC1 = 0x10,
 18	VPCCMD_R_BL_MAX,
 19	VPCCMD_R_BL,
 20	VPCCMD_W_BL,
 21	VPCCMD_R_WIFI,
 22	VPCCMD_W_WIFI,
 23	VPCCMD_R_BT,
 24	VPCCMD_W_BT,
 25	VPCCMD_R_BL_POWER,
 26	VPCCMD_R_NOVO,
 27	VPCCMD_R_VPC2,
 28	VPCCMD_R_TOUCHPAD,
 29	VPCCMD_W_TOUCHPAD,
 30	VPCCMD_R_CAMERA,
 31	VPCCMD_W_CAMERA,
 32	VPCCMD_R_3G,
 33	VPCCMD_W_3G,
 34	VPCCMD_R_ODD, /* 0x21 */
 35	VPCCMD_W_FAN,
 36	VPCCMD_R_RF,
 37	VPCCMD_W_RF,
 38	VPCCMD_W_YMC = 0x2A,
 39	VPCCMD_R_FAN = 0x2B,
 40	VPCCMD_R_SPECIAL_BUTTONS = 0x31,
 41	VPCCMD_W_BL_POWER = 0x33,
 42};
 43
 44static inline int eval_int_with_arg(acpi_handle handle, const char *name, unsigned long arg, unsigned long *res)
 45{
 46	struct acpi_object_list params;
 47	unsigned long long result;
 48	union acpi_object in_obj;
 49	acpi_status status;
 50
 51	params.count = 1;
 52	params.pointer = &in_obj;
 53	in_obj.type = ACPI_TYPE_INTEGER;
 54	in_obj.integer.value = arg;
 55
 56	status = acpi_evaluate_integer(handle, (char *)name, &params, &result);
 57	if (ACPI_FAILURE(status))
 58		return -EIO;
 59
 60	if (res)
 61		*res = result;
 62
 63	return 0;
 64}
 65
 66static inline int eval_vpcr(acpi_handle handle, unsigned long cmd, unsigned long *res)
 67{
 68	return eval_int_with_arg(handle, "VPCR", cmd, res);
 69}
 70
 71static inline int eval_vpcw(acpi_handle handle, unsigned long cmd, unsigned long data)
 72{
 73	struct acpi_object_list params;
 74	union acpi_object in_obj[2];
 75	acpi_status status;
 76
 77	params.count = 2;
 78	params.pointer = in_obj;
 79	in_obj[0].type = ACPI_TYPE_INTEGER;
 80	in_obj[0].integer.value = cmd;
 81	in_obj[1].type = ACPI_TYPE_INTEGER;
 82	in_obj[1].integer.value = data;
 83
 84	status = acpi_evaluate_object(handle, "VPCW", &params, NULL);
 85	if (ACPI_FAILURE(status))
 86		return -EIO;
 87
 88	return 0;
 89}
 90
 91#define IDEAPAD_EC_TIMEOUT 200 /* in ms */
 92
 93static inline int read_ec_data(acpi_handle handle, unsigned long cmd, unsigned long *data)
 94{
 95	unsigned long end_jiffies, val;
 96	int err;
 97
 98	err = eval_vpcw(handle, 1, cmd);
 99	if (err)
100		return err;
101
102	end_jiffies = jiffies + msecs_to_jiffies(IDEAPAD_EC_TIMEOUT) + 1;
103
104	while (time_before(jiffies, end_jiffies)) {
105		schedule();
106
107		err = eval_vpcr(handle, 1, &val);
108		if (err)
109			return err;
110
111		if (val == 0)
112			return eval_vpcr(handle, 0, data);
113	}
114
115	acpi_handle_err(handle, "timeout in %s\n", __func__);
116
117	return -ETIMEDOUT;
118}
119
120static inline int write_ec_cmd(acpi_handle handle, unsigned long cmd, unsigned long data)
121{
122	unsigned long end_jiffies, val;
123	int err;
124
125	err = eval_vpcw(handle, 0, data);
126	if (err)
127		return err;
128
129	err = eval_vpcw(handle, 1, cmd);
130	if (err)
131		return err;
132
133	end_jiffies = jiffies + msecs_to_jiffies(IDEAPAD_EC_TIMEOUT) + 1;
134
135	while (time_before(jiffies, end_jiffies)) {
136		schedule();
137
138		err = eval_vpcr(handle, 1, &val);
139		if (err)
140			return err;
141
142		if (val == 0)
143			return 0;
144	}
145
146	acpi_handle_err(handle, "timeout in %s\n", __func__);
147
148	return -ETIMEDOUT;
149}
150
151#undef IDEAPAD_EC_TIMEOUT
152#endif /* !_IDEAPAD_LAPTOP_H_ */