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

// SPDX-License-Identifier: GPL-2.0-or-later
/*
 *  asus-laptop.c - Asus Laptop Support
 *
 *  Copyright (C) 2002-2005 Julien Lerouge, 2003-2006 Karol Kozimor
 *  Copyright (C) 2006-2007 Corentin Chary
 *  Copyright (C) 2011 Wind River Systems
 *
 *  The development page for this driver is located at
 *  http://sourceforge.net/projects/acpi4asus/
 *
 *  Credits:
 *  Pontus Fuchs   - Helper functions, cleanup
 *  Johann Wiesner - Small compile fixes
 *  John Belmonte  - ACPI code for Toshiba laptop was a good starting point.
 *  Eric Burghard  - LED display support for W1N
 *  Josh Green     - Light Sens support
 *  Thomas Tuttle  - His first patch for led support was very helpful
 *  Sam Lin        - GPS support
 */

#define pr_fmt(fmt)

#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/types.h>
#include <linux/err.h>
#include <linux/proc_fs.h>
#include <linux/backlight.h>
#include <linux/leds.h>
#include <linux/platform_device.h>
#include <linux/uaccess.h>
#include <linux/input.h>
#include <linux/input/sparse-keymap.h>
#include <linux/rfkill.h>
#include <linux/slab.h>
#include <linux/dmi.h>
#include <linux/acpi.h>
#include <acpi/video.h>

#define ASUS_LAPTOP_VERSION

#define ASUS_LAPTOP_NAME
#define ASUS_LAPTOP_CLASS
#define ASUS_LAPTOP_DEVICE_NAME
#define ASUS_LAPTOP_FILE
#define ASUS_LAPTOP_PREFIX

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

/*
 * WAPF defines the behavior of the Fn+Fx wlan key
 * The significance of values is yet to be found, but
 * most of the time:
 * Bit | Bluetooth | WLAN
 *  0  | Hardware  | Hardware
 *  1  | Hardware  | Software
 *  4  | Software  | Software
 */
static uint wapf =;
module_param(wapf, uint, 0444);
MODULE_PARM_DESC();

static char *wled_type =;
static char *bled_type =;

module_param(wled_type, charp, 0444);
MODULE_PARM_DESC();

module_param(bled_type, charp, 0444);
MODULE_PARM_DESC();

static int wlan_status =;
static int bluetooth_status =;
static int wimax_status =;
static int wwan_status =;
static int als_status;

module_param(wlan_status, int, 0444);
MODULE_PARM_DESC();

module_param(bluetooth_status, int, 0444);
MODULE_PARM_DESC();

module_param(wimax_status, int, 0444);
MODULE_PARM_DESC();

module_param(wwan_status, int, 0444);
MODULE_PARM_DESC();

module_param(als_status, int, 0444);
MODULE_PARM_DESC();

/*
 * Some events we use, same for all Asus
 */
#define ATKD_BRNUP_MIN
#define ATKD_BRNUP_MAX
#define ATKD_BRNDOWN_MIN
#define ATKD_BRNDOWN_MAX
#define ATKD_BRNDOWN
#define ATKD_BRNUP
#define ATKD_LCD_ON
#define ATKD_LCD_OFF

/*
 * Known bits returned by \_SB.ATKD.HWRS
 */
#define WL_HWRS
#define BT_HWRS

/*
 * Flags for hotk status
 * WL_ON and BT_ON are also used for wireless_status()
 */
#define WL_RSTS
#define BT_RSTS
#define WM_RSTS
#define WW_RSTS

/* WLED and BLED type */
#define TYPE_UNKNOWN
#define TYPE_LED
#define TYPE_RFKILL

/* LED */
#define METHOD_MLED
#define METHOD_TLED
#define METHOD_RLED
#define METHOD_PLED
#define METHOD_GLED

/* LEDD */
#define METHOD_LEDD

/*
 * Bluetooth and WLAN
 * WLED and BLED are not handled like other XLED, because in some dsdt
 * they also control the WLAN/Bluetooth device.
 */
#define METHOD_WLAN
#define METHOD_BLUETOOTH

/* WWAN and WIMAX */
#define METHOD_WWAN
#define METHOD_WIMAX

#define METHOD_WL_STATUS

/* Brightness */
#define METHOD_BRIGHTNESS_SET
#define METHOD_BRIGHTNESS_GET

/* Display */
#define METHOD_SWITCH_DISPLAY

#define METHOD_ALS_CONTROL
#define METHOD_ALS_LEVEL

/* GPS */
/* R2H use different handle for GPS on/off */
#define METHOD_GPS_ON
#define METHOD_GPS_OFF
#define METHOD_GPS_STATUS

/* Keyboard light */
#define METHOD_KBD_LIGHT_SET
#define METHOD_KBD_LIGHT_GET

/* For Pegatron Lucid tablet */
#define DEVICE_NAME_PEGA

#define METHOD_PEGA_ENABLE
#define METHOD_PEGA_DISABLE
#define PEGA_WLAN
#define PEGA_BLUETOOTH
#define PEGA_WWAN
#define PEGA_ALS
#define PEGA_ALS_POWER

#define METHOD_PEGA_READ
#define PEGA_READ_ALS_H
#define PEGA_READ_ALS_L

#define PEGA_ACCEL_NAME
#define PEGA_ACCEL_DESC
#define METHOD_XLRX
#define METHOD_XLRY
#define METHOD_XLRZ
#define PEGA_ACC_CLAMP
#define PEGA_ACC_RETRIES

/*
 * Define a specific led structure to keep the main structure clean
 */
struct asus_led {};

/*
 * Same thing for rfkill
 */
struct asus_rfkill {};

/*
 * This is the main structure, we can use it to store anything interesting
 * about the hotk device
 */
struct asus_laptop {};

static const struct key_entry asus_keymap[] =;


/*
 * This function evaluates an ACPI method, given an int as parameter, the
 * method is searched within the scope of the handle, can be NULL. The output
 * of the method is written is output, which can also be NULL
 *
 * returns 0 if write is successful, -1 else.
 */
static int write_acpi_int_ret(acpi_handle handle, const char *method, int val,
			      struct acpi_buffer *output)
{}

static int write_acpi_int(acpi_handle handle, const char *method, int val)
{}

static int acpi_check_handle(acpi_handle handle, const char *method,
			     acpi_handle *ret)
{}

static bool asus_check_pega_lucid(struct asus_laptop *asus)
{}

static int asus_pega_lucid_set(struct asus_laptop *asus, int unit, bool enable)
{}

static int pega_acc_axis(struct asus_laptop *asus, int curr, char *method)
{}

static void pega_accel_poll(struct input_dev *input)
{}

static void pega_accel_exit(struct asus_laptop *asus)
{}

static int pega_accel_init(struct asus_laptop *asus)
{}

/* Generic LED function */
static int asus_led_set(struct asus_laptop *asus, const char *method,
			 int value)
{}

/*
 * LEDs
 */
/* /sys/class/led handlers */
static void asus_led_cdev_set(struct led_classdev *led_cdev,
			 enum led_brightness value)
{}

static void asus_led_cdev_update(struct work_struct *work)
{}

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

/*
 * Keyboard backlight (also a LED)
 */
static int asus_kled_lvl(struct asus_laptop *asus)
{}

static int asus_kled_set(struct asus_laptop *asus, int kblv)
{}

static void asus_kled_cdev_set(struct led_classdev *led_cdev,
			      enum led_brightness value)
{}

static void asus_kled_cdev_update(struct work_struct *work)
{}

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

static void asus_led_exit(struct asus_laptop *asus)
{}

/*  Ugly macro, need to fix that later */
static int asus_led_register(struct asus_laptop *asus,
			     struct asus_led *led,
			     const char *name, const char *method)
{}

static int asus_led_init(struct asus_laptop *asus)
{}

/*
 * Backlight device
 */
static int asus_read_brightness(struct backlight_device *bd)
{}

static int asus_set_brightness(struct backlight_device *bd, int value)
{}

static int update_bl_status(struct backlight_device *bd)
{}

static const struct backlight_ops asusbl_ops =;

static int asus_backlight_notify(struct asus_laptop *asus)
{}

static int asus_backlight_init(struct asus_laptop *asus)
{}

static void asus_backlight_exit(struct asus_laptop *asus)
{}

/*
 * Platform device handlers
 */

/*
 * We write our info in page, we begin at offset off and cannot write more
 * than count bytes. We set eof to 1 if we handle those 2 values. We return the
 * number of bytes written in page
 */
static ssize_t infos_show(struct device *dev, struct device_attribute *attr,
			  char *page)
{}
static DEVICE_ATTR_RO(infos);

static ssize_t sysfs_acpi_set(struct asus_laptop *asus,
			      const char *buf, size_t count,
			      const char *method)
{}

/*
 * LEDD display
 */
static ssize_t ledd_show(struct device *dev, struct device_attribute *attr,
			 char *buf)
{}

static ssize_t ledd_store(struct device *dev, struct device_attribute *attr,
			  const char *buf, size_t count)
{}
static DEVICE_ATTR_RW(ledd);

/*
 * Wireless
 */
static int asus_wireless_status(struct asus_laptop *asus, int mask)
{}

/*
 * WLAN
 */
static int asus_wlan_set(struct asus_laptop *asus, int status)
{}

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

static ssize_t wlan_store(struct device *dev, struct device_attribute *attr,
			  const char *buf, size_t count)
{}
static DEVICE_ATTR_RW(wlan);

/*e
 * Bluetooth
 */
static int asus_bluetooth_set(struct asus_laptop *asus, int status)
{}

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

static ssize_t bluetooth_store(struct device *dev,
			       struct device_attribute *attr, const char *buf,
			       size_t count)
{}
static DEVICE_ATTR_RW(bluetooth);

/*
 * Wimax
 */
static int asus_wimax_set(struct asus_laptop *asus, int status)
{}

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

static ssize_t wimax_store(struct device *dev, struct device_attribute *attr,
			   const char *buf, size_t count)
{}
static DEVICE_ATTR_RW(wimax);

/*
 * Wwan
 */
static int asus_wwan_set(struct asus_laptop *asus, int status)
{}

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

static ssize_t wwan_store(struct device *dev, struct device_attribute *attr,
			  const char *buf, size_t count)
{}
static DEVICE_ATTR_RW(wwan);

/*
 * Display
 */
static void asus_set_display(struct asus_laptop *asus, int value)
{}

/*
 * Experimental support for display switching. As of now: 1 should activate
 * the LCD output, 2 should do for CRT, 4 for TV-Out and 8 for DVI.
 * Any combination (bitwise) of these will suffice. I never actually tested 4
 * displays hooked up simultaneously, so be warned. See the acpi4asus README
 * for more info.
 */
static ssize_t display_store(struct device *dev, struct device_attribute *attr,
			     const char *buf, size_t count)
{}
static DEVICE_ATTR_WO(display);

/*
 * Light Sens
 */
static void asus_als_switch(struct asus_laptop *asus, int value)
{}

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

static ssize_t ls_switch_store(struct device *dev,
			       struct device_attribute *attr, const char *buf,
			       size_t count)
{}
static DEVICE_ATTR_RW(ls_switch);

static void asus_als_level(struct asus_laptop *asus, int value)
{}

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

static ssize_t ls_level_store(struct device *dev, struct device_attribute *attr,
			      const char *buf, size_t count)
{}
static DEVICE_ATTR_RW(ls_level);

static int pega_int_read(struct asus_laptop *asus, int arg, int *result)
{}

static ssize_t ls_value_show(struct device *dev, struct device_attribute *attr,
			     char *buf)
{}
static DEVICE_ATTR_RO(ls_value);

/*
 * GPS
 */
static int asus_gps_status(struct asus_laptop *asus)
{}

static int asus_gps_switch(struct asus_laptop *asus, int status)
{}

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

static ssize_t gps_store(struct device *dev, struct device_attribute *attr,
			 const char *buf, size_t count)
{}
static DEVICE_ATTR_RW(gps);

/*
 * rfkill
 */
static int asus_gps_rfkill_set(void *data, bool blocked)
{}

static const struct rfkill_ops asus_gps_rfkill_ops =;

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

static const struct rfkill_ops asus_rfkill_ops =;

static void asus_rfkill_terminate(struct asus_rfkill *rfk)
{}

static void asus_rfkill_exit(struct asus_laptop *asus)
{}

static int asus_rfkill_setup(struct asus_laptop *asus, struct asus_rfkill *rfk,
			     const char *name, int control_id, int type,
			     const struct rfkill_ops *ops)
{}

static int asus_rfkill_init(struct asus_laptop *asus)
{}

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

static const struct rfkill_ops pega_rfkill_ops =;

static int pega_rfkill_setup(struct asus_laptop *asus, struct asus_rfkill *rfk,
			     const char *name, int controlid, int rfkill_type)
{}

static int pega_rfkill_init(struct asus_laptop *asus)
{}

/*
 * Input device (i.e. hotkeys)
 */
static void asus_input_notify(struct asus_laptop *asus, int event)
{}

static int asus_input_init(struct asus_laptop *asus)
{}

static void asus_input_exit(struct asus_laptop *asus)
{}

/*
 * ACPI driver
 */
static void asus_acpi_notify(struct acpi_device *device, u32 event)
{}

static struct attribute *asus_attributes[] =;

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


static const struct attribute_group asus_attr_group =;

static int asus_platform_init(struct asus_laptop *asus)
{}

static void asus_platform_exit(struct asus_laptop *asus)
{}

static struct platform_driver platform_driver =;

/*
 * This function is used to initialize the context with right values. In this
 * method, we can make all the detection we want, and modify the asus_laptop
 * struct
 */
static int asus_laptop_get_info(struct asus_laptop *asus)
{}

static int asus_acpi_init(struct asus_laptop *asus)
{}

static void asus_dmi_check(void)
{}

static bool asus_device_present;

static int asus_acpi_add(struct acpi_device *device)
{}

static void asus_acpi_remove(struct acpi_device *device)
{}

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

static struct acpi_driver asus_acpi_driver =;

static int __init asus_laptop_init(void)
{}

static void __exit asus_laptop_exit(void)
{}

module_init();
module_exit(asus_laptop_exit);