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

// SPDX-License-Identifier: GPL-2.0-or-later
/*-*-linux-c-*-*/

/*
  Copyright (C) 2008 Cezary Jackiewicz <cezary.jackiewicz (at) gmail.com>

  based on MSI driver

  Copyright (C) 2006 Lennart Poettering <mzxreary (at) 0pointer (dot) de>

 */

/*
 * compal-laptop.c - Compal laptop support.
 *
 * This driver exports a few files in /sys/devices/platform/compal-laptop/:
 *   wake_up_XXX   Whether or not we listen to such wake up events (rw)
 *
 * In addition to these platform device attributes the driver
 * registers itself in the Linux backlight control, power_supply, rfkill
 * and hwmon subsystem and is available to userspace under:
 *
 *   /sys/class/backlight/compal-laptop/
 *   /sys/class/power_supply/compal-laptop/
 *   /sys/class/rfkill/rfkillX/
 *   /sys/class/hwmon/hwmonX/
 *
 * Notes on the power_supply battery interface:
 *   - the "minimum" design voltage is *the* design voltage
 *   - the ambient temperature is the average battery temperature
 *     and the value is an educated guess (see commented code below)
 *
 *
 * This driver might work on other laptops produced by Compal. If you
 * want to try it you can pass force=1 as argument to the module which
 * will force it to load even when the DMI data doesn't identify the
 * laptop as compatible.
 *
 * Lots of data available at:
 * http://service1.marasst.com/Compal/JHL90_91/Service%20Manual/
 * JHL90%20service%20manual-Final-0725.pdf
 *
 *
 *
 * Support for the Compal JHL90 added by Roald Frederickx
 * ([email protected]):
 * Driver got large revision. Added functionalities: backlight
 * power, wake_on_XXX, a hwmon and power_supply interface.
 *
 * In case this gets merged into the kernel source: I want to dedicate this
 * to Kasper Meerts, the awesome guy who showed me Linux and C!
 */

/* NOTE: currently the wake_on_XXX, hwmon and power_supply interfaces are
 * only enabled on a JHL90 board until it is verified that they work on the
 * other boards too.  See the extra_features variable. */

#define pr_fmt(fmt)

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/acpi.h>
#include <linux/dmi.h>
#include <linux/backlight.h>
#include <linux/platform_device.h>
#include <linux/rfkill.h>
#include <linux/hwmon.h>
#include <linux/hwmon-sysfs.h>
#include <linux/power_supply.h>
#include <linux/fb.h>
#include <acpi/video.h>

/* ======= */
/* Defines */
/* ======= */
#define DRIVER_NAME
#define DRIVER_VERSION

#define BACKLIGHT_LEVEL_ADDR
#define BACKLIGHT_LEVEL_MAX
#define BACKLIGHT_STATE_ADDR
#define BACKLIGHT_STATE_ON_DATA
#define BACKLIGHT_STATE_OFF_DATA

#define WAKE_UP_ADDR
#define WAKE_UP_PME
#define WAKE_UP_MODEM
#define WAKE_UP_LAN
#define WAKE_UP_WLAN
#define WAKE_UP_KEY
#define WAKE_UP_MOUSE

#define WIRELESS_ADDR
#define WIRELESS_WLAN
#define WIRELESS_BT
#define WIRELESS_WLAN_EXISTS
#define WIRELESS_BT_EXISTS
#define WIRELESS_KILLSWITCH

#define PWM_ADDRESS
#define PWM_DISABLE_ADDR
#define PWM_DISABLE_DATA
#define PWM_ENABLE_ADDR
#define PWM_ENABLE_DATA

#define FAN_ADDRESS
#define FAN_DATA
#define FAN_FULL_ON_CMD
#define FAN_FULL_ON_ENABLE
#define FAN_FULL_ON_DISABLE

#define TEMP_CPU
#define TEMP_CPU_LOCAL
#define TEMP_CPU_DTS
#define TEMP_NORTHBRIDGE
#define TEMP_VGA
#define TEMP_SKIN

#define BAT_MANUFACTURER_NAME_ADDR
#define BAT_MANUFACTURER_NAME_LEN
#define BAT_MODEL_NAME_ADDR
#define BAT_MODEL_NAME_LEN
#define BAT_SERIAL_NUMBER_ADDR
#define BAT_SERIAL_NUMBER_LEN
#define BAT_CHARGE_NOW
#define BAT_CHARGE_DESIGN
#define BAT_VOLTAGE_NOW
#define BAT_VOLTAGE_DESIGN
#define BAT_CURRENT_NOW
#define BAT_CURRENT_AVG
#define BAT_POWER
#define BAT_CAPACITY
#define BAT_TEMP
#define BAT_TEMP_AVG
#define BAT_STATUS0
#define BAT_STATUS1
#define BAT_STATUS2
#define BAT_STOP_CHARGE1
#define BAT_STOP_CHARGE2
#define BAT_CHARGE_LIMIT
#define BAT_CHARGE_LIMIT_MAX

#define BAT_S0_DISCHARGE
#define BAT_S0_DISCHRG_CRITICAL
#define BAT_S0_LOW
#define BAT_S0_CHARGING
#define BAT_S0_AC
#define BAT_S1_EXISTS
#define BAT_S1_FULL
#define BAT_S1_EMPTY
#define BAT_S1_LiION_OR_NiMH
#define BAT_S2_LOW_LOW
#define BAT_STOP_CHRG1_BAD_CELL
#define BAT_STOP_CHRG1_COMM_FAIL
#define BAT_STOP_CHRG1_OVERVOLTAGE
#define BAT_STOP_CHRG1_OVERTEMPERATURE


/* ======= */
/* Structs */
/* ======= */
struct compal_data{};


/* =============== */
/* General globals */
/* =============== */
static bool force;
module_param(force, bool, 0);
MODULE_PARM_DESC();

/* Support for the wake_on_XXX, hwmon and power_supply interface. Currently
 * only gets enabled on a JHL90 board. Might work with the others too */
static bool extra_features;

/* Nasty stuff. For some reason the fan control is very un-linear.  I've
 * come up with these values by looping through the possible inputs and
 * watching the output of address 0x4F (do an ec_transaction writing 0x33
 * into 0x4F and read a few bytes from the output, like so:
 *	u8 writeData = 0x33;
 *	ec_transaction(0x4F, &writeData, 1, buffer, 32);
 * That address is labeled "fan1 table information" in the service manual.
 * It should be clear which value in 'buffer' changes). This seems to be
 * related to fan speed. It isn't a proper 'realtime' fan speed value
 * though, because physically stopping or speeding up the fan doesn't
 * change it. It might be the average voltage or current of the pwm output.
 * Nevertheless, it is more fine-grained than the actual RPM reading */
static const unsigned char pwm_lookup_table[256] =;




/* ========================= */
/* Hardware access functions */
/* ========================= */
/* General access */
static u8 ec_read_u8(u8 addr)
{}

static s8 ec_read_s8(u8 addr)
{}

static u16 ec_read_u16(u8 addr)
{}

static s16 ec_read_s16(u8 addr)
{}

static void ec_read_sequence(u8 addr, u8 *buf, int len)
{}


/* Backlight access */
static int set_backlight_level(int level)
{}

static int get_backlight_level(void)
{}

static void set_backlight_state(bool on)
{}


/* Fan control access */
static void pwm_enable_control(void)
{}

static void pwm_disable_control(void)
{}

static void set_pwm(int pwm)
{}

static int get_fan_rpm(void)
{}




/* =================== */
/* Interface functions */
/* =================== */

/* Backlight interface */
static int bl_get_brightness(struct backlight_device *b)
{}

static int bl_update_status(struct backlight_device *b)
{}

static const struct backlight_ops compalbl_ops =;


/* Wireless interface */
static int compal_rfkill_set(void *data, bool blocked)
{}

static void compal_rfkill_poll(struct rfkill *rfkill, void *data)
{}

static const struct rfkill_ops compal_rfkill_ops =;


/* Wake_up interface */
#define SIMPLE_MASKED_STORE_SHOW(NAME, ADDR, MASK)

SIMPLE_MASKED_STORE_SHOW(wake_up_pme,	WAKE_UP_ADDR, WAKE_UP_PME)
SIMPLE_MASKED_STORE_SHOW(wake_up_modem,	WAKE_UP_ADDR, WAKE_UP_MODEM)
SIMPLE_MASKED_STORE_SHOW(wake_up_lan,	WAKE_UP_ADDR, WAKE_UP_LAN)
SIMPLE_MASKED_STORE_SHOW(wake_up_wlan,	WAKE_UP_ADDR, WAKE_UP_WLAN)
SIMPLE_MASKED_STORE_SHOW(wake_up_key,	WAKE_UP_ADDR, WAKE_UP_KEY)
SIMPLE_MASKED_STORE_SHOW(wake_up_mouse,	WAKE_UP_ADDR, WAKE_UP_MOUSE)

/* Fan control interface */
static ssize_t pwm_enable_show(struct device *dev,
		struct device_attribute *attr, char *buf)
{}

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

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

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

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


/* Temperature interface */
#define TEMPERATURE_SHOW_TEMP_AND_LABEL(POSTFIX, ADDRESS, LABEL)

/* Labels as in service guide */
TEMPERATURE_SHOW_TEMP_AND_LABEL(cpu,        TEMP_CPU,        "CPU_TEMP");
TEMPERATURE_SHOW_TEMP_AND_LABEL(cpu_local,  TEMP_CPU_LOCAL,  "CPU_TEMP_LOCAL");
TEMPERATURE_SHOW_TEMP_AND_LABEL(cpu_DTS,    TEMP_CPU_DTS,    "CPU_DTS");
TEMPERATURE_SHOW_TEMP_AND_LABEL(northbridge,TEMP_NORTHBRIDGE,"NorthBridge");
TEMPERATURE_SHOW_TEMP_AND_LABEL(vga,        TEMP_VGA,        "VGA_TEMP");
TEMPERATURE_SHOW_TEMP_AND_LABEL(SKIN,       TEMP_SKIN,       "SKIN_TEMP90");


/* Power supply interface */
static int bat_status(void)
{}

static int bat_health(void)
{}

static int bat_is_present(void)
{}

static int bat_technology(void)
{}

static int bat_capacity_level(void)
{}

static int bat_get_property(struct power_supply *psy,
				enum power_supply_property psp,
				union power_supply_propval *val)
{}

static int bat_set_property(struct power_supply *psy,
				enum power_supply_property psp,
				const union power_supply_propval *val)
{}

static int bat_writeable_property(struct power_supply *psy,
				enum power_supply_property psp)
{}




/* ============== */
/* Driver Globals */
/* ============== */
static DEVICE_ATTR_RW(wake_up_pme);
static DEVICE_ATTR_RW(wake_up_modem);
static DEVICE_ATTR_RW(wake_up_lan);
static DEVICE_ATTR_RW(wake_up_wlan);
static DEVICE_ATTR_RW(wake_up_key);
static DEVICE_ATTR_RW(wake_up_mouse);

static DEVICE_ATTR(fan1_input,  S_IRUGO, fan_show,          NULL);
static DEVICE_ATTR(temp1_input, S_IRUGO, temp_cpu,          NULL);
static DEVICE_ATTR(temp2_input, S_IRUGO, temp_cpu_local,    NULL);
static DEVICE_ATTR(temp3_input, S_IRUGO, temp_cpu_DTS,      NULL);
static DEVICE_ATTR(temp4_input, S_IRUGO, temp_northbridge,  NULL);
static DEVICE_ATTR(temp5_input, S_IRUGO, temp_vga,          NULL);
static DEVICE_ATTR(temp6_input, S_IRUGO, temp_SKIN,         NULL);
static DEVICE_ATTR(temp1_label, S_IRUGO, label_cpu,         NULL);
static DEVICE_ATTR(temp2_label, S_IRUGO, label_cpu_local,   NULL);
static DEVICE_ATTR(temp3_label, S_IRUGO, label_cpu_DTS,     NULL);
static DEVICE_ATTR(temp4_label, S_IRUGO, label_northbridge, NULL);
static DEVICE_ATTR(temp5_label, S_IRUGO, label_vga,         NULL);
static DEVICE_ATTR(temp6_label, S_IRUGO, label_SKIN,        NULL);
static DEVICE_ATTR(pwm1, S_IRUGO | S_IWUSR, pwm_show, pwm_store);
static DEVICE_ATTR(pwm1_enable,
		   S_IRUGO | S_IWUSR, pwm_enable_show, pwm_enable_store);

static struct attribute *compal_platform_attrs[] =;
static const struct attribute_group compal_platform_attr_group =;

static struct attribute *compal_hwmon_attrs[] =;
ATTRIBUTE_GROUPS();

static enum power_supply_property compal_bat_properties[] =;

static struct backlight_device *compalbl_device;

static struct platform_device *compal_device;

static struct rfkill *wifi_rfkill;
static struct rfkill *bt_rfkill;





/* =================================== */
/* Initialization & clean-up functions */
/* =================================== */

static int dmi_check_cb(const struct dmi_system_id *id)
{}

static int dmi_check_cb_extra(const struct dmi_system_id *id)
{}

static const struct dmi_system_id compal_dmi_table[] __initconst =;
MODULE_DEVICE_TABLE(dmi, compal_dmi_table);

static const struct power_supply_desc psy_bat_desc =;

static void initialize_power_supply_data(struct compal_data *data)
{}

static void initialize_fan_control_data(struct compal_data *data)
{}

static int setup_rfkill(void)
{}

static int compal_probe(struct platform_device *pdev)
{}

static void compal_remove(struct platform_device *pdev)
{}

static struct platform_driver compal_driver =;

static int __init compal_init(void)
{}

static void __exit compal_cleanup(void)
{}

module_init();
module_exit(compal_cleanup);

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