linux/drivers/platform/x86/ideapad-laptop.c

// SPDX-License-Identifier: GPL-2.0-or-later
/*
 *  ideapad-laptop.c - Lenovo IdeaPad ACPI Extras
 *
 *  Copyright © 2010 Intel Corporation
 *  Copyright © 2010 David Woodhouse <[email protected]>
 */

#define pr_fmt(fmt)

#include <linux/acpi.h>
#include <linux/backlight.h>
#include <linux/bitfield.h>
#include <linux/bitops.h>
#include <linux/bug.h>
#include <linux/cleanup.h>
#include <linux/debugfs.h>
#include <linux/device.h>
#include <linux/dmi.h>
#include <linux/i8042.h>
#include <linux/init.h>
#include <linux/input.h>
#include <linux/input/sparse-keymap.h>
#include <linux/jiffies.h>
#include <linux/kernel.h>
#include <linux/leds.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/platform_profile.h>
#include <linux/rfkill.h>
#include <linux/seq_file.h>
#include <linux/sysfs.h>
#include <linux/types.h>
#include <linux/wmi.h>
#include "ideapad-laptop.h"

#include <acpi/video.h>

#include <dt-bindings/leds/common.h>

#define IDEAPAD_RFKILL_DEV_NUM

enum {};

enum {};

enum {};

enum {};

enum {};

enum {};

/*
 * These correspond to the number of supported states - 1
 * Future keyboard types may need a new system, if there's a collision
 * KBD_BL_TRISTATE_AUTO has no way to report or set the auto state
 * so it effectively has 3 states, but needs to handle 4
 */
enum {};

#define KBD_BL_QUERY_TYPE
#define KBD_BL_TRISTATE_TYPE
#define KBD_BL_TRISTATE_AUTO_TYPE

#define KBD_BL_COMMAND_GET
#define KBD_BL_COMMAND_SET
#define KBD_BL_COMMAND_TYPE

#define KBD_BL_GET_BRIGHTNESS
#define KBD_BL_SET_BRIGHTNESS

#define KBD_BL_KBLC_CHANGED_EVENT

struct ideapad_dytc_priv {};

struct ideapad_rfk_priv {};

struct ideapad_private {};

static bool no_bt_rfkill;
module_param(no_bt_rfkill, bool, 0444);
MODULE_PARM_DESC();

static bool allow_v4_dytc;
module_param(allow_v4_dytc, bool, 0444);
MODULE_PARM_DESC();

static bool hw_rfkill_switch;
module_param(hw_rfkill_switch, bool, 0444);
MODULE_PARM_DESC();

static bool set_fn_lock_led;
module_param(set_fn_lock_led, bool, 0444);
MODULE_PARM_DESC();

static bool ctrl_ps2_aux_port;
module_param(ctrl_ps2_aux_port, bool, 0444);
MODULE_PARM_DESC();

static bool touchpad_ctrl_via_ec;
module_param(touchpad_ctrl_via_ec, bool, 0444);
MODULE_PARM_DESC();

static bool ymc_ec_trigger __read_mostly;
module_param(ymc_ec_trigger, bool, 0444);
MODULE_PARM_DESC();

/*
 * shared data
 */

static struct ideapad_private *ideapad_shared;
static DEFINE_MUTEX(ideapad_shared_mutex);

static int ideapad_shared_init(struct ideapad_private *priv)
{}

static void ideapad_shared_exit(struct ideapad_private *priv)
{}

/*
 * ACPI Helpers
 */
#define IDEAPAD_EC_TIMEOUT

static int eval_int(acpi_handle handle, const char *name, unsigned long *res)
{}

static int eval_int_with_arg(acpi_handle handle, const char *name, unsigned long arg,
			     unsigned long *res)
{}

static int exec_simple_method(acpi_handle handle, const char *name, unsigned long arg)
{}

static int eval_gbmd(acpi_handle handle, unsigned long *res)
{}

static int exec_sbmc(acpi_handle handle, unsigned long arg)
{}

static int eval_hals(acpi_handle handle, unsigned long *res)
{}

static int exec_sals(acpi_handle handle, unsigned long arg)
{}

static int exec_kblc(acpi_handle handle, unsigned long arg)
{}

static int eval_kblc(acpi_handle handle, unsigned long cmd, unsigned long *res)
{}

static int eval_dytc(acpi_handle handle, unsigned long cmd, unsigned long *res)
{}

static int eval_vpcr(acpi_handle handle, unsigned long cmd, unsigned long *res)
{}

static int eval_vpcw(acpi_handle handle, unsigned long cmd, unsigned long data)
{}

static int read_ec_data(acpi_handle handle, unsigned long cmd, unsigned long *data)
{}

static int write_ec_cmd(acpi_handle handle, unsigned long cmd, unsigned long data)
{}

/*
 * debugfs
 */
static int debugfs_status_show(struct seq_file *s, void *data)
{}
DEFINE_SHOW_ATTRIBUTE();

static int debugfs_cfg_show(struct seq_file *s, void *data)
{}
DEFINE_SHOW_ATTRIBUTE();

static void ideapad_debugfs_init(struct ideapad_private *priv)
{}

static void ideapad_debugfs_exit(struct ideapad_private *priv)
{}

/*
 * sysfs
 */
static ssize_t camera_power_show(struct device *dev,
				 struct device_attribute *attr,
				 char *buf)
{}

static ssize_t camera_power_store(struct device *dev,
				  struct device_attribute *attr,
				  const char *buf, size_t count)
{}

static DEVICE_ATTR_RW(camera_power);

static ssize_t conservation_mode_show(struct device *dev,
				      struct device_attribute *attr,
				      char *buf)
{}

static ssize_t conservation_mode_store(struct device *dev,
				       struct device_attribute *attr,
				       const char *buf, size_t count)
{}

static DEVICE_ATTR_RW(conservation_mode);

static ssize_t fan_mode_show(struct device *dev,
			     struct device_attribute *attr,
			     char *buf)
{}

static ssize_t fan_mode_store(struct device *dev,
			      struct device_attribute *attr,
			      const char *buf, size_t count)
{}

static DEVICE_ATTR_RW(fan_mode);

static int ideapad_fn_lock_get(struct ideapad_private *priv)
{}

static int ideapad_fn_lock_set(struct ideapad_private *priv, bool state)
{}

static void ideapad_fn_lock_led_notify(struct ideapad_private *priv, int brightness)
{}

static ssize_t fn_lock_show(struct device *dev,
			    struct device_attribute *attr,
			    char *buf)
{}

static ssize_t fn_lock_store(struct device *dev,
			     struct device_attribute *attr,
			     const char *buf, size_t count)
{}

static DEVICE_ATTR_RW(fn_lock);

static ssize_t touchpad_show(struct device *dev,
			     struct device_attribute *attr,
			     char *buf)
{}

static ssize_t touchpad_store(struct device *dev,
			      struct device_attribute *attr,
			      const char *buf, size_t count)
{}

static DEVICE_ATTR_RW(touchpad);

static ssize_t usb_charging_show(struct device *dev,
				 struct device_attribute *attr,
				 char *buf)
{}

static ssize_t usb_charging_store(struct device *dev,
				  struct device_attribute *attr,
				  const char *buf, size_t count)
{}

static DEVICE_ATTR_RW(usb_charging);

static struct attribute *ideapad_attributes[] =;

static umode_t ideapad_is_visible(struct kobject *kobj,
				  struct attribute *attr,
				  int idx)
{}

static const struct attribute_group ideapad_attribute_group =;

/*
 * DYTC Platform profile
 */
#define DYTC_CMD_QUERY
#define DYTC_CMD_SET
#define DYTC_CMD_GET
#define DYTC_CMD_RESET

#define DYTC_QUERY_ENABLE_BIT
#define DYTC_QUERY_SUBREV_BIT
#define DYTC_QUERY_REV_BIT

#define DYTC_GET_FUNCTION_BIT
#define DYTC_GET_MODE_BIT

#define DYTC_SET_FUNCTION_BIT
#define DYTC_SET_MODE_BIT
#define DYTC_SET_VALID_BIT

#define DYTC_FUNCTION_STD
#define DYTC_FUNCTION_CQL
#define DYTC_FUNCTION_MMC

#define DYTC_MODE_PERFORM
#define DYTC_MODE_LOW_POWER
#define DYTC_MODE_BALANCE

#define DYTC_SET_COMMAND(function, mode, on)

#define DYTC_DISABLE_CQL

#define DYTC_ENABLE_CQL

static int convert_dytc_to_profile(int dytcmode, enum platform_profile_option *profile)
{}

static int convert_profile_to_dytc(enum platform_profile_option profile, int *perfmode)
{}

/*
 * dytc_profile_get: Function to register with platform_profile
 * handler. Returns current platform profile.
 */
static int dytc_profile_get(struct platform_profile_handler *pprof,
			    enum platform_profile_option *profile)
{}

/*
 * Helper function - check if we are in CQL mode and if we are
 *  - disable CQL,
 *  - run the command
 *  - enable CQL
 *  If not in CQL mode, just run the command
 */
static int dytc_cql_command(struct ideapad_private *priv, unsigned long cmd,
			    unsigned long *output)
{}

/*
 * dytc_profile_set: Function to register with platform_profile
 * handler. Sets current platform profile.
 */
static int dytc_profile_set(struct platform_profile_handler *pprof,
			    enum platform_profile_option profile)
{}

static void dytc_profile_refresh(struct ideapad_private *priv)
{}

static const struct dmi_system_id ideapad_dytc_v4_allow_table[] =;

static int ideapad_dytc_profile_init(struct ideapad_private *priv)
{}

static void ideapad_dytc_profile_exit(struct ideapad_private *priv)
{}

/*
 * Rfkill
 */
struct ideapad_rfk_data {};

static const struct ideapad_rfk_data ideapad_rfk_data[] =;

static int ideapad_rfk_set(void *data, bool blocked)
{}

static const struct rfkill_ops ideapad_rfk_ops =;

static void ideapad_sync_rfk_state(struct ideapad_private *priv)
{}

static int ideapad_register_rfkill(struct ideapad_private *priv, int dev)
{}

static void ideapad_unregister_rfkill(struct ideapad_private *priv, int dev)
{}

/*
 * Platform device
 */
static int ideapad_sysfs_init(struct ideapad_private *priv)
{}

static void ideapad_sysfs_exit(struct ideapad_private *priv)
{}

/*
 * input device
 */
#define IDEAPAD_WMI_KEY

static const struct key_entry ideapad_keymap[] =;

static int ideapad_input_init(struct ideapad_private *priv)
{}

static void ideapad_input_exit(struct ideapad_private *priv)
{}

static void ideapad_input_report(struct ideapad_private *priv,
				 unsigned long scancode)
{}

static void ideapad_input_novokey(struct ideapad_private *priv)
{}

static void ideapad_check_special_buttons(struct ideapad_private *priv)
{}

/*
 * backlight
 */
static int ideapad_backlight_get_brightness(struct backlight_device *blightdev)
{}

static int ideapad_backlight_update_status(struct backlight_device *blightdev)
{}

static const struct backlight_ops ideapad_backlight_ops =;

static int ideapad_backlight_init(struct ideapad_private *priv)
{}

static void ideapad_backlight_exit(struct ideapad_private *priv)
{}

static void ideapad_backlight_notify_power(struct ideapad_private *priv)
{}

static void ideapad_backlight_notify_brightness(struct ideapad_private *priv)
{}

/*
 * keyboard backlight
 */
static int ideapad_kbd_bl_check_tristate(int type)
{}

static int ideapad_kbd_bl_brightness_get(struct ideapad_private *priv)
{}

static enum led_brightness ideapad_kbd_bl_led_cdev_brightness_get(struct led_classdev *led_cdev)
{}

static int ideapad_kbd_bl_brightness_set(struct ideapad_private *priv, unsigned int brightness)
{}

static int ideapad_kbd_bl_led_cdev_brightness_set(struct led_classdev *led_cdev,
						  enum led_brightness brightness)
{}

static void ideapad_kbd_bl_notify(struct ideapad_private *priv)
{}

static int ideapad_kbd_bl_init(struct ideapad_private *priv)
{}

static void ideapad_kbd_bl_exit(struct ideapad_private *priv)
{}

/*
 * FnLock LED
 */
static enum led_brightness ideapad_fn_lock_led_cdev_get(struct led_classdev *led_cdev)
{}

static int ideapad_fn_lock_led_cdev_set(struct led_classdev *led_cdev,
	enum led_brightness brightness)
{}

static int ideapad_fn_lock_led_init(struct ideapad_private *priv)
{}

static void ideapad_fn_lock_led_exit(struct ideapad_private *priv)
{}

/*
 * module init/exit
 */
static void ideapad_sync_touchpad_state(struct ideapad_private *priv, bool send_events)
{}

static const struct dmi_system_id ymc_ec_trigger_quirk_dmi_table[] =;

static void ideapad_laptop_trigger_ec(void)
{}

static int ideapad_laptop_nb_notify(struct notifier_block *nb,
				    unsigned long action, void *data)
{}

static struct notifier_block ideapad_laptop_notifier =;

static BLOCKING_NOTIFIER_HEAD(ideapad_laptop_chain_head);

int ideapad_laptop_register_notifier(struct notifier_block *nb)
{}
EXPORT_SYMBOL_NS_GPL();

int ideapad_laptop_unregister_notifier(struct notifier_block *nb)
{}
EXPORT_SYMBOL_NS_GPL();

void ideapad_laptop_call_notifier(unsigned long action, void *data)
{}
EXPORT_SYMBOL_NS_GPL();

static void ideapad_acpi_notify(acpi_handle handle, u32 event, void *data)
{}

/* On some models we need to call exec_sals(SALS_FNLOCK_ON/OFF) to set the LED */
static const struct dmi_system_id set_fn_lock_led_list[] =;

/*
 * Some ideapads have a hardware rfkill switch, but most do not have one.
 * Reading VPCCMD_R_RF always results in 0 on models without a hardware rfkill,
 * switch causing ideapad_laptop to wrongly report all radios as hw-blocked.
 * There used to be a long list of DMI ids for models without a hw rfkill
 * switch here, but that resulted in playing whack a mole.
 * More importantly wrongly reporting the wifi radio as hw-blocked, results in
 * non working wifi. Whereas not reporting it hw-blocked, when it actually is
 * hw-blocked results in an empty SSID list, which is a much more benign
 * failure mode.
 * So the default now is the much safer option of assuming there is no
 * hardware rfkill switch. This default also actually matches most hardware,
 * since having a hw rfkill switch is quite rare on modern hardware, so this
 * also leads to a much shorter list.
 */
static const struct dmi_system_id hw_rfkill_list[] =;

/*
 * On some models the EC toggles the touchpad muted LED on touchpad toggle
 * hotkey presses, but the EC does not actually disable the touchpad itself.
 * On these models the driver needs to explicitly enable/disable the i8042
 * (PS/2) aux port.
 */
static const struct dmi_system_id ctrl_ps2_aux_port_list[] =;

static void ideapad_check_features(struct ideapad_private *priv)
{}

#if IS_ENABLED(CONFIG_ACPI_WMI)
/*
 * WMI driver
 */
enum ideapad_wmi_event_type {};

struct ideapad_wmi_private {};

static int ideapad_wmi_probe(struct wmi_device *wdev, const void *context)
{}

static void ideapad_wmi_notify(struct wmi_device *wdev, union acpi_object *data)
{}

static const struct ideapad_wmi_private ideapad_wmi_context_esc =;

static const struct ideapad_wmi_private ideapad_wmi_context_fn_keys =;

static const struct wmi_device_id ideapad_wmi_ids[] =;
MODULE_DEVICE_TABLE(wmi, ideapad_wmi_ids);

static struct wmi_driver ideapad_wmi_driver =;

static int ideapad_wmi_driver_register(void)
{}

static void ideapad_wmi_driver_unregister(void)
{}

#else
static inline int ideapad_wmi_driver_register(void) { return 0; }
static inline void ideapad_wmi_driver_unregister(void) { }
#endif

/*
 * ACPI driver
 */
static int ideapad_acpi_add(struct platform_device *pdev)
{}

static void ideapad_acpi_remove(struct platform_device *pdev)
{}

#ifdef CONFIG_PM_SLEEP
static int ideapad_acpi_resume(struct device *dev)
{}
#endif
static SIMPLE_DEV_PM_OPS(ideapad_pm, NULL, ideapad_acpi_resume);

static const struct acpi_device_id ideapad_device_ids[] =;
MODULE_DEVICE_TABLE(acpi, ideapad_device_ids);

static struct platform_driver ideapad_acpi_driver =;

static int __init ideapad_laptop_init(void)
{}
module_init()

static void __exit ideapad_laptop_exit(void)
{}
module_exit()

MODULE_AUTHOR();
MODULE_DESCRIPTION();
MODULE_LICENSE();