^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-or-later
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*-*-linux-c-*-*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) Copyright (C) 2008 Cezary Jackiewicz <cezary.jackiewicz (at) gmail.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) based on MSI driver
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) Copyright (C) 2006 Lennart Poettering <mzxreary (at) 0pointer (dot) de>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) * compal-laptop.c - Compal laptop support.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) * This driver exports a few files in /sys/devices/platform/compal-laptop/:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) * wake_up_XXX Whether or not we listen to such wake up events (rw)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) * In addition to these platform device attributes the driver
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) * registers itself in the Linux backlight control, power_supply, rfkill
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) * and hwmon subsystem and is available to userspace under:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) * /sys/class/backlight/compal-laptop/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) * /sys/class/power_supply/compal-laptop/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) * /sys/class/rfkill/rfkillX/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) * /sys/class/hwmon/hwmonX/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) * Notes on the power_supply battery interface:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) * - the "minimum" design voltage is *the* design voltage
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) * - the ambient temperature is the average battery temperature
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) * and the value is an educated guess (see commented code below)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) * This driver might work on other laptops produced by Compal. If you
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) * want to try it you can pass force=1 as argument to the module which
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) * will force it to load even when the DMI data doesn't identify the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) * laptop as compatible.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) * Lots of data available at:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) * http://service1.marasst.com/Compal/JHL90_91/Service%20Manual/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) * JHL90%20service%20manual-Final-0725.pdf
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) * Support for the Compal JHL90 added by Roald Frederickx
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) * (roald.frederickx@gmail.com):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) * Driver got large revision. Added functionalities: backlight
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) * power, wake_on_XXX, a hwmon and power_supply interface.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) * In case this gets merged into the kernel source: I want to dedicate this
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) * to Kasper Meerts, the awesome guy who showed me Linux and C!
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) /* NOTE: currently the wake_on_XXX, hwmon and power_supply interfaces are
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) * only enabled on a JHL90 board until it is verified that they work on the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) * other boards too. See the extra_features variable. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) #include <linux/init.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) #include <linux/acpi.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) #include <linux/dmi.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) #include <linux/backlight.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) #include <linux/platform_device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) #include <linux/rfkill.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) #include <linux/hwmon.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) #include <linux/hwmon-sysfs.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) #include <linux/power_supply.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) #include <linux/fb.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) #include <acpi/video.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) /* ======= */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) /* Defines */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) /* ======= */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) #define DRIVER_NAME "compal-laptop"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) #define DRIVER_VERSION "0.2.7"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) #define BACKLIGHT_LEVEL_ADDR 0xB9
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) #define BACKLIGHT_LEVEL_MAX 7
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) #define BACKLIGHT_STATE_ADDR 0x59
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) #define BACKLIGHT_STATE_ON_DATA 0xE1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) #define BACKLIGHT_STATE_OFF_DATA 0xE2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) #define WAKE_UP_ADDR 0xA4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) #define WAKE_UP_PME (1 << 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) #define WAKE_UP_MODEM (1 << 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) #define WAKE_UP_LAN (1 << 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) #define WAKE_UP_WLAN (1 << 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) #define WAKE_UP_KEY (1 << 6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) #define WAKE_UP_MOUSE (1 << 7)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) #define WIRELESS_ADDR 0xBB
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) #define WIRELESS_WLAN (1 << 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) #define WIRELESS_BT (1 << 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) #define WIRELESS_WLAN_EXISTS (1 << 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) #define WIRELESS_BT_EXISTS (1 << 3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) #define WIRELESS_KILLSWITCH (1 << 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) #define PWM_ADDRESS 0x46
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) #define PWM_DISABLE_ADDR 0x59
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) #define PWM_DISABLE_DATA 0xA5
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) #define PWM_ENABLE_ADDR 0x59
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) #define PWM_ENABLE_DATA 0xA8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) #define FAN_ADDRESS 0x46
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) #define FAN_DATA 0x81
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) #define FAN_FULL_ON_CMD 0x59 /* Doesn't seem to work. Just */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) #define FAN_FULL_ON_ENABLE 0x76 /* force the pwm signal to its */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) #define FAN_FULL_ON_DISABLE 0x77 /* maximum value instead */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) #define TEMP_CPU 0xB0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) #define TEMP_CPU_LOCAL 0xB1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) #define TEMP_CPU_DTS 0xB5
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) #define TEMP_NORTHBRIDGE 0xB6
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) #define TEMP_VGA 0xB4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) #define TEMP_SKIN 0xB2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) #define BAT_MANUFACTURER_NAME_ADDR 0x10
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) #define BAT_MANUFACTURER_NAME_LEN 9
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) #define BAT_MODEL_NAME_ADDR 0x19
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) #define BAT_MODEL_NAME_LEN 6
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) #define BAT_SERIAL_NUMBER_ADDR 0xC4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) #define BAT_SERIAL_NUMBER_LEN 5
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) #define BAT_CHARGE_NOW 0xC2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) #define BAT_CHARGE_DESIGN 0xCA
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) #define BAT_VOLTAGE_NOW 0xC6
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) #define BAT_VOLTAGE_DESIGN 0xC8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) #define BAT_CURRENT_NOW 0xD0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) #define BAT_CURRENT_AVG 0xD2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) #define BAT_POWER 0xD4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) #define BAT_CAPACITY 0xCE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) #define BAT_TEMP 0xD6
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) #define BAT_TEMP_AVG 0xD7
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) #define BAT_STATUS0 0xC1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) #define BAT_STATUS1 0xF0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) #define BAT_STATUS2 0xF1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) #define BAT_STOP_CHARGE1 0xF2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) #define BAT_STOP_CHARGE2 0xF3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) #define BAT_CHARGE_LIMIT 0x03
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) #define BAT_CHARGE_LIMIT_MAX 100
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) #define BAT_S0_DISCHARGE (1 << 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) #define BAT_S0_DISCHRG_CRITICAL (1 << 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) #define BAT_S0_LOW (1 << 3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) #define BAT_S0_CHARGING (1 << 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) #define BAT_S0_AC (1 << 7)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) #define BAT_S1_EXISTS (1 << 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) #define BAT_S1_FULL (1 << 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) #define BAT_S1_EMPTY (1 << 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) #define BAT_S1_LiION_OR_NiMH (1 << 7)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) #define BAT_S2_LOW_LOW (1 << 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) #define BAT_STOP_CHRG1_BAD_CELL (1 << 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) #define BAT_STOP_CHRG1_COMM_FAIL (1 << 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) #define BAT_STOP_CHRG1_OVERVOLTAGE (1 << 6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) #define BAT_STOP_CHRG1_OVERTEMPERATURE (1 << 7)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) /* ======= */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) /* Structs */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) /* ======= */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) struct compal_data{
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) /* Fan control */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) int pwm_enable; /* 0:full on, 1:set by pwm1, 2:control by motherboard */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) unsigned char curr_pwm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) /* Power supply */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) struct power_supply *psy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) struct power_supply_info psy_info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) char bat_model_name[BAT_MODEL_NAME_LEN + 1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) char bat_manufacturer_name[BAT_MANUFACTURER_NAME_LEN + 1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) char bat_serial_number[BAT_SERIAL_NUMBER_LEN + 1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) /* =============== */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) /* General globals */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) /* =============== */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) static bool force;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) module_param(force, bool, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) MODULE_PARM_DESC(force, "Force driver load, ignore DMI data");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) /* Support for the wake_on_XXX, hwmon and power_supply interface. Currently
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) * only gets enabled on a JHL90 board. Might work with the others too */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) static bool extra_features;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) /* Nasty stuff. For some reason the fan control is very un-linear. I've
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) * come up with these values by looping through the possible inputs and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) * watching the output of address 0x4F (do an ec_transaction writing 0x33
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) * into 0x4F and read a few bytes from the output, like so:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) * u8 writeData = 0x33;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) * ec_transaction(0x4F, &writeData, 1, buffer, 32);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) * That address is labeled "fan1 table information" in the service manual.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) * It should be clear which value in 'buffer' changes). This seems to be
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) * related to fan speed. It isn't a proper 'realtime' fan speed value
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) * though, because physically stopping or speeding up the fan doesn't
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) * change it. It might be the average voltage or current of the pwm output.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) * Nevertheless, it is more fine-grained than the actual RPM reading */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) static const unsigned char pwm_lookup_table[256] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) 0, 0, 0, 1, 1, 1, 2, 253, 254, 3, 3, 3, 4, 4, 4, 5, 5, 5, 6, 6, 6,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) 7, 7, 7, 8, 86, 86, 9, 9, 9, 10, 10, 10, 11, 92, 92, 12, 12, 95,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) 13, 66, 66, 14, 14, 98, 15, 15, 15, 16, 16, 67, 17, 17, 72, 18, 70,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) 75, 19, 90, 90, 73, 73, 73, 21, 21, 91, 91, 91, 96, 23, 94, 94, 94,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) 94, 94, 94, 94, 94, 94, 94, 141, 141, 238, 223, 192, 139, 139, 139,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) 139, 139, 142, 142, 142, 142, 142, 78, 78, 78, 78, 78, 76, 76, 76,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) 76, 76, 79, 79, 79, 79, 79, 79, 79, 20, 20, 20, 20, 20, 22, 22, 22,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) 22, 22, 24, 24, 24, 24, 24, 24, 219, 219, 219, 219, 219, 219, 219,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) 219, 27, 27, 188, 188, 28, 28, 28, 29, 186, 186, 186, 186, 186,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) 186, 186, 186, 186, 186, 31, 31, 31, 31, 31, 32, 32, 32, 41, 33,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) 33, 33, 33, 33, 252, 252, 34, 34, 34, 43, 35, 35, 35, 36, 36, 38,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) 206, 206, 206, 206, 206, 206, 206, 206, 206, 37, 37, 37, 46, 46,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) 47, 47, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 48, 48,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) 48, 48, 48, 40, 40, 40, 49, 42, 42, 42, 42, 42, 42, 42, 42, 44,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) 189, 189, 189, 189, 54, 54, 45, 45, 45, 45, 45, 45, 45, 45, 251,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) 191, 199, 199, 199, 199, 199, 215, 215, 215, 215, 187, 187, 187,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) 187, 187, 193, 50
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) /* ========================= */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) /* Hardware access functions */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) /* ========================= */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) /* General access */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) static u8 ec_read_u8(u8 addr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) u8 value = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) ec_read(addr, &value);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) return value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) static s8 ec_read_s8(u8 addr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) return (s8)ec_read_u8(addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) static u16 ec_read_u16(u8 addr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) int hi, lo;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) lo = ec_read_u8(addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) hi = ec_read_u8(addr + 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) return (hi << 8) + lo;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) static s16 ec_read_s16(u8 addr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) return (s16) ec_read_u16(addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) static void ec_read_sequence(u8 addr, u8 *buf, int len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) for (i = 0; i < len; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) ec_read(addr + i, buf + i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) /* Backlight access */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) static int set_backlight_level(int level)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) if (level < 0 || level > BACKLIGHT_LEVEL_MAX)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) ec_write(BACKLIGHT_LEVEL_ADDR, level);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) static int get_backlight_level(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) return (int) ec_read_u8(BACKLIGHT_LEVEL_ADDR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) static void set_backlight_state(bool on)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) u8 data = on ? BACKLIGHT_STATE_ON_DATA : BACKLIGHT_STATE_OFF_DATA;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) ec_transaction(BACKLIGHT_STATE_ADDR, &data, 1, NULL, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) /* Fan control access */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) static void pwm_enable_control(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) unsigned char writeData = PWM_ENABLE_DATA;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) ec_transaction(PWM_ENABLE_ADDR, &writeData, 1, NULL, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) static void pwm_disable_control(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) unsigned char writeData = PWM_DISABLE_DATA;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) ec_transaction(PWM_DISABLE_ADDR, &writeData, 1, NULL, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) static void set_pwm(int pwm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) ec_transaction(PWM_ADDRESS, &pwm_lookup_table[pwm], 1, NULL, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) static int get_fan_rpm(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) u8 value, data = FAN_DATA;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) ec_transaction(FAN_ADDRESS, &data, 1, &value, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) return 100 * (int)value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) /* =================== */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) /* Interface functions */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) /* =================== */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) /* Backlight interface */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) static int bl_get_brightness(struct backlight_device *b)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) return get_backlight_level();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) static int bl_update_status(struct backlight_device *b)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) int ret = set_backlight_level(b->props.brightness);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) set_backlight_state((b->props.power == FB_BLANK_UNBLANK)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) && !(b->props.state & BL_CORE_SUSPENDED)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) && !(b->props.state & BL_CORE_FBBLANK));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) static const struct backlight_ops compalbl_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) .get_brightness = bl_get_brightness,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) .update_status = bl_update_status,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) /* Wireless interface */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) static int compal_rfkill_set(void *data, bool blocked)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) unsigned long radio = (unsigned long) data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) u8 result = ec_read_u8(WIRELESS_ADDR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) u8 value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) if (!blocked)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) value = (u8) (result | radio);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) value = (u8) (result & ~radio);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) ec_write(WIRELESS_ADDR, value);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) static void compal_rfkill_poll(struct rfkill *rfkill, void *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) u8 result = ec_read_u8(WIRELESS_ADDR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) bool hw_blocked = !(result & WIRELESS_KILLSWITCH);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) rfkill_set_hw_state(rfkill, hw_blocked);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) static const struct rfkill_ops compal_rfkill_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) .poll = compal_rfkill_poll,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) .set_block = compal_rfkill_set,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) /* Wake_up interface */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) #define SIMPLE_MASKED_STORE_SHOW(NAME, ADDR, MASK) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) static ssize_t NAME##_show(struct device *dev, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) struct device_attribute *attr, char *buf) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) { \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) return sprintf(buf, "%d\n", ((ec_read_u8(ADDR) & MASK) != 0)); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) } \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) static ssize_t NAME##_store(struct device *dev, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) struct device_attribute *attr, const char *buf, size_t count) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) { \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) int state; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) u8 old_val = ec_read_u8(ADDR); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) if (sscanf(buf, "%d", &state) != 1 || (state < 0 || state > 1)) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) return -EINVAL; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) ec_write(ADDR, state ? (old_val | MASK) : (old_val & ~MASK)); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) return count; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) SIMPLE_MASKED_STORE_SHOW(wake_up_pme, WAKE_UP_ADDR, WAKE_UP_PME)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) SIMPLE_MASKED_STORE_SHOW(wake_up_modem, WAKE_UP_ADDR, WAKE_UP_MODEM)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) SIMPLE_MASKED_STORE_SHOW(wake_up_lan, WAKE_UP_ADDR, WAKE_UP_LAN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) SIMPLE_MASKED_STORE_SHOW(wake_up_wlan, WAKE_UP_ADDR, WAKE_UP_WLAN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) SIMPLE_MASKED_STORE_SHOW(wake_up_key, WAKE_UP_ADDR, WAKE_UP_KEY)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) SIMPLE_MASKED_STORE_SHOW(wake_up_mouse, WAKE_UP_ADDR, WAKE_UP_MOUSE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) /* Fan control interface */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) static ssize_t pwm_enable_show(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) struct device_attribute *attr, char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) struct compal_data *data = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) return sprintf(buf, "%d\n", data->pwm_enable);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) static ssize_t pwm_enable_store(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) struct device_attribute *attr, const char *buf, size_t count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) struct compal_data *data = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) long val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) err = kstrtol(buf, 10, &val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) if (val < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) data->pwm_enable = val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) switch (val) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) case 0: /* Full speed */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) pwm_enable_control();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) set_pwm(255);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) case 1: /* As set by pwm1 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) pwm_enable_control();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) set_pwm(data->curr_pwm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) default: /* Control by motherboard */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) pwm_disable_control();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) return count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) static ssize_t pwm_show(struct device *dev, struct device_attribute *attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) struct compal_data *data = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) return sprintf(buf, "%hhu\n", data->curr_pwm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) static ssize_t pwm_store(struct device *dev, struct device_attribute *attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) const char *buf, size_t count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) struct compal_data *data = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) long val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) err = kstrtol(buf, 10, &val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) if (val < 0 || val > 255)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) data->curr_pwm = val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) if (data->pwm_enable != 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) return count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) set_pwm(val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) return count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) static ssize_t fan_show(struct device *dev, struct device_attribute *attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) return sprintf(buf, "%d\n", get_fan_rpm());
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) /* Temperature interface */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) #define TEMPERATURE_SHOW_TEMP_AND_LABEL(POSTFIX, ADDRESS, LABEL) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) static ssize_t temp_##POSTFIX(struct device *dev, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) struct device_attribute *attr, char *buf) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) { \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) return sprintf(buf, "%d\n", 1000 * (int)ec_read_s8(ADDRESS)); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) } \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) static ssize_t label_##POSTFIX(struct device *dev, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) struct device_attribute *attr, char *buf) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) { \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) return sprintf(buf, "%s\n", LABEL); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) /* Labels as in service guide */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) TEMPERATURE_SHOW_TEMP_AND_LABEL(cpu, TEMP_CPU, "CPU_TEMP");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) TEMPERATURE_SHOW_TEMP_AND_LABEL(cpu_local, TEMP_CPU_LOCAL, "CPU_TEMP_LOCAL");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) TEMPERATURE_SHOW_TEMP_AND_LABEL(cpu_DTS, TEMP_CPU_DTS, "CPU_DTS");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) TEMPERATURE_SHOW_TEMP_AND_LABEL(northbridge,TEMP_NORTHBRIDGE,"NorthBridge");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) TEMPERATURE_SHOW_TEMP_AND_LABEL(vga, TEMP_VGA, "VGA_TEMP");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) TEMPERATURE_SHOW_TEMP_AND_LABEL(SKIN, TEMP_SKIN, "SKIN_TEMP90");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) /* Power supply interface */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) static int bat_status(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) u8 status0 = ec_read_u8(BAT_STATUS0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) u8 status1 = ec_read_u8(BAT_STATUS1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) if (status0 & BAT_S0_CHARGING)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) return POWER_SUPPLY_STATUS_CHARGING;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) if (status0 & BAT_S0_DISCHARGE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) return POWER_SUPPLY_STATUS_DISCHARGING;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) if (status1 & BAT_S1_FULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) return POWER_SUPPLY_STATUS_FULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) return POWER_SUPPLY_STATUS_NOT_CHARGING;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) static int bat_health(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) u8 status = ec_read_u8(BAT_STOP_CHARGE1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) if (status & BAT_STOP_CHRG1_OVERTEMPERATURE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) return POWER_SUPPLY_HEALTH_OVERHEAT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) if (status & BAT_STOP_CHRG1_OVERVOLTAGE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) return POWER_SUPPLY_HEALTH_OVERVOLTAGE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) if (status & BAT_STOP_CHRG1_BAD_CELL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) return POWER_SUPPLY_HEALTH_DEAD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) if (status & BAT_STOP_CHRG1_COMM_FAIL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) return POWER_SUPPLY_HEALTH_UNKNOWN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) return POWER_SUPPLY_HEALTH_GOOD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) static int bat_is_present(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) u8 status = ec_read_u8(BAT_STATUS2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) return ((status & BAT_S1_EXISTS) != 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) static int bat_technology(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) u8 status = ec_read_u8(BAT_STATUS1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) if (status & BAT_S1_LiION_OR_NiMH)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) return POWER_SUPPLY_TECHNOLOGY_LION;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) return POWER_SUPPLY_TECHNOLOGY_NiMH;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) static int bat_capacity_level(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) u8 status0 = ec_read_u8(BAT_STATUS0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) u8 status1 = ec_read_u8(BAT_STATUS1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) u8 status2 = ec_read_u8(BAT_STATUS2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) if (status0 & BAT_S0_DISCHRG_CRITICAL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) || status1 & BAT_S1_EMPTY
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) || status2 & BAT_S2_LOW_LOW)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) return POWER_SUPPLY_CAPACITY_LEVEL_CRITICAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) if (status0 & BAT_S0_LOW)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) return POWER_SUPPLY_CAPACITY_LEVEL_LOW;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) if (status1 & BAT_S1_FULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) return POWER_SUPPLY_CAPACITY_LEVEL_FULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) return POWER_SUPPLY_CAPACITY_LEVEL_NORMAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) static int bat_get_property(struct power_supply *psy,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) enum power_supply_property psp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) union power_supply_propval *val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) struct compal_data *data = power_supply_get_drvdata(psy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) switch (psp) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) case POWER_SUPPLY_PROP_STATUS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) val->intval = bat_status();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) case POWER_SUPPLY_PROP_HEALTH:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) val->intval = bat_health();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) case POWER_SUPPLY_PROP_PRESENT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) val->intval = bat_is_present();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) case POWER_SUPPLY_PROP_TECHNOLOGY:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) val->intval = bat_technology();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) case POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN: /* THE design voltage... */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) val->intval = ec_read_u16(BAT_VOLTAGE_DESIGN) * 1000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) case POWER_SUPPLY_PROP_VOLTAGE_NOW:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) val->intval = ec_read_u16(BAT_VOLTAGE_NOW) * 1000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) case POWER_SUPPLY_PROP_CURRENT_NOW:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) val->intval = ec_read_s16(BAT_CURRENT_NOW) * 1000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) case POWER_SUPPLY_PROP_CURRENT_AVG:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) val->intval = ec_read_s16(BAT_CURRENT_AVG) * 1000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) case POWER_SUPPLY_PROP_POWER_NOW:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) val->intval = ec_read_u8(BAT_POWER) * 1000000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) case POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) val->intval = ec_read_u16(BAT_CHARGE_DESIGN) * 1000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) case POWER_SUPPLY_PROP_CHARGE_NOW:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) val->intval = ec_read_u16(BAT_CHARGE_NOW) * 1000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) case POWER_SUPPLY_PROP_CHARGE_CONTROL_LIMIT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) val->intval = ec_read_u8(BAT_CHARGE_LIMIT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) case POWER_SUPPLY_PROP_CHARGE_CONTROL_LIMIT_MAX:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) val->intval = BAT_CHARGE_LIMIT_MAX;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) case POWER_SUPPLY_PROP_CAPACITY:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) val->intval = ec_read_u8(BAT_CAPACITY);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) case POWER_SUPPLY_PROP_CAPACITY_LEVEL:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) val->intval = bat_capacity_level();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) /* It smees that BAT_TEMP_AVG is a (2's complement?) value showing
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) * the number of degrees, whereas BAT_TEMP is somewhat more
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) * complicated. It looks like this is a negative nember with a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) * 100/256 divider and an offset of 222. Both were determined
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) * experimentally by comparing BAT_TEMP and BAT_TEMP_AVG. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) case POWER_SUPPLY_PROP_TEMP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) val->intval = ((222 - (int)ec_read_u8(BAT_TEMP)) * 1000) >> 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) case POWER_SUPPLY_PROP_TEMP_AMBIENT: /* Ambient, Avg, ... same thing */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) val->intval = ec_read_s8(BAT_TEMP_AVG) * 10;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) /* Neither the model name nor manufacturer name work for me. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) case POWER_SUPPLY_PROP_MODEL_NAME:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) val->strval = data->bat_model_name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) case POWER_SUPPLY_PROP_MANUFACTURER:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) val->strval = data->bat_manufacturer_name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) case POWER_SUPPLY_PROP_SERIAL_NUMBER:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) val->strval = data->bat_serial_number;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) static int bat_set_property(struct power_supply *psy,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) enum power_supply_property psp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) const union power_supply_propval *val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) int level;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) switch (psp) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) case POWER_SUPPLY_PROP_CHARGE_CONTROL_LIMIT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) level = val->intval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) if (level < 0 || level > BAT_CHARGE_LIMIT_MAX)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) if (ec_write(BAT_CHARGE_LIMIT, level) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) static int bat_writeable_property(struct power_supply *psy,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) enum power_supply_property psp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) switch (psp) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) case POWER_SUPPLY_PROP_CHARGE_CONTROL_LIMIT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) /* ============== */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) /* Driver Globals */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) /* ============== */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) static DEVICE_ATTR_RW(wake_up_pme);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) static DEVICE_ATTR_RW(wake_up_modem);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) static DEVICE_ATTR_RW(wake_up_lan);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) static DEVICE_ATTR_RW(wake_up_wlan);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) static DEVICE_ATTR_RW(wake_up_key);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) static DEVICE_ATTR_RW(wake_up_mouse);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) static DEVICE_ATTR(fan1_input, S_IRUGO, fan_show, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) static DEVICE_ATTR(temp1_input, S_IRUGO, temp_cpu, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) static DEVICE_ATTR(temp2_input, S_IRUGO, temp_cpu_local, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) static DEVICE_ATTR(temp3_input, S_IRUGO, temp_cpu_DTS, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) static DEVICE_ATTR(temp4_input, S_IRUGO, temp_northbridge, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) static DEVICE_ATTR(temp5_input, S_IRUGO, temp_vga, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) static DEVICE_ATTR(temp6_input, S_IRUGO, temp_SKIN, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) static DEVICE_ATTR(temp1_label, S_IRUGO, label_cpu, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) static DEVICE_ATTR(temp2_label, S_IRUGO, label_cpu_local, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) static DEVICE_ATTR(temp3_label, S_IRUGO, label_cpu_DTS, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) static DEVICE_ATTR(temp4_label, S_IRUGO, label_northbridge, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) static DEVICE_ATTR(temp5_label, S_IRUGO, label_vga, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) static DEVICE_ATTR(temp6_label, S_IRUGO, label_SKIN, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) static DEVICE_ATTR(pwm1, S_IRUGO | S_IWUSR, pwm_show, pwm_store);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) static DEVICE_ATTR(pwm1_enable,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) S_IRUGO | S_IWUSR, pwm_enable_show, pwm_enable_store);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) static struct attribute *compal_platform_attrs[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) &dev_attr_wake_up_pme.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) &dev_attr_wake_up_modem.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) &dev_attr_wake_up_lan.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) &dev_attr_wake_up_wlan.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) &dev_attr_wake_up_key.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) &dev_attr_wake_up_mouse.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) NULL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) static const struct attribute_group compal_platform_attr_group = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) .attrs = compal_platform_attrs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) static struct attribute *compal_hwmon_attrs[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) &dev_attr_pwm1_enable.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) &dev_attr_pwm1.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) &dev_attr_fan1_input.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) &dev_attr_temp1_input.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) &dev_attr_temp2_input.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) &dev_attr_temp3_input.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) &dev_attr_temp4_input.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) &dev_attr_temp5_input.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) &dev_attr_temp6_input.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) &dev_attr_temp1_label.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) &dev_attr_temp2_label.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) &dev_attr_temp3_label.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) &dev_attr_temp4_label.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) &dev_attr_temp5_label.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) &dev_attr_temp6_label.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) NULL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) ATTRIBUTE_GROUPS(compal_hwmon);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) static int compal_probe(struct platform_device *);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) static int compal_remove(struct platform_device *);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) static struct platform_driver compal_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) .driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) .name = DRIVER_NAME,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) .probe = compal_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) .remove = compal_remove,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) static enum power_supply_property compal_bat_properties[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) POWER_SUPPLY_PROP_STATUS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) POWER_SUPPLY_PROP_HEALTH,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) POWER_SUPPLY_PROP_PRESENT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) POWER_SUPPLY_PROP_TECHNOLOGY,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) POWER_SUPPLY_PROP_VOLTAGE_NOW,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) POWER_SUPPLY_PROP_CURRENT_NOW,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) POWER_SUPPLY_PROP_CURRENT_AVG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) POWER_SUPPLY_PROP_POWER_NOW,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) POWER_SUPPLY_PROP_CHARGE_NOW,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) POWER_SUPPLY_PROP_CHARGE_CONTROL_LIMIT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) POWER_SUPPLY_PROP_CHARGE_CONTROL_LIMIT_MAX,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) POWER_SUPPLY_PROP_CAPACITY,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) POWER_SUPPLY_PROP_CAPACITY_LEVEL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) POWER_SUPPLY_PROP_TEMP,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) POWER_SUPPLY_PROP_TEMP_AMBIENT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) POWER_SUPPLY_PROP_MODEL_NAME,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) POWER_SUPPLY_PROP_MANUFACTURER,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) POWER_SUPPLY_PROP_SERIAL_NUMBER,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) static struct backlight_device *compalbl_device;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) static struct platform_device *compal_device;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) static struct rfkill *wifi_rfkill;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764) static struct rfkill *bt_rfkill;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) /* =================================== */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) /* Initialization & clean-up functions */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) /* =================================== */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) static int dmi_check_cb(const struct dmi_system_id *id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776) pr_info("Identified laptop model '%s'\n", id->ident);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) extra_features = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) static int dmi_check_cb_extra(const struct dmi_system_id *id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) pr_info("Identified laptop model '%s', enabling extra features\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784) id->ident);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) extra_features = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789) static const struct dmi_system_id compal_dmi_table[] __initconst = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791) .ident = "FL90/IFL90",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792) .matches = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) DMI_MATCH(DMI_BOARD_NAME, "IFL90"),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794) DMI_MATCH(DMI_BOARD_VERSION, "IFT00"),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796) .callback = dmi_check_cb
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) .ident = "FL90/IFL90",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800) .matches = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801) DMI_MATCH(DMI_BOARD_NAME, "IFL90"),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802) DMI_MATCH(DMI_BOARD_VERSION, "REFERENCE"),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804) .callback = dmi_check_cb
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807) .ident = "FL91/IFL91",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808) .matches = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809) DMI_MATCH(DMI_BOARD_NAME, "IFL91"),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810) DMI_MATCH(DMI_BOARD_VERSION, "IFT00"),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812) .callback = dmi_check_cb
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815) .ident = "FL92/JFL92",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816) .matches = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817) DMI_MATCH(DMI_BOARD_NAME, "JFL92"),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818) DMI_MATCH(DMI_BOARD_VERSION, "IFT00"),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820) .callback = dmi_check_cb
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823) .ident = "FT00/IFT00",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) .matches = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825) DMI_MATCH(DMI_BOARD_NAME, "IFT00"),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826) DMI_MATCH(DMI_BOARD_VERSION, "IFT00"),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828) .callback = dmi_check_cb
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831) .ident = "Dell Mini 9",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832) .matches = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833) DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834) DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 910"),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836) .callback = dmi_check_cb
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839) .ident = "Dell Mini 10",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840) .matches = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841) DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842) DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 1010"),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844) .callback = dmi_check_cb
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847) .ident = "Dell Mini 10v",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848) .matches = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849) DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850) DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 1011"),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852) .callback = dmi_check_cb
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855) .ident = "Dell Mini 1012",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856) .matches = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857) DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858) DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 1012"),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860) .callback = dmi_check_cb
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863) .ident = "Dell Inspiron 11z",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864) .matches = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865) DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866) DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 1110"),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868) .callback = dmi_check_cb
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871) .ident = "Dell Mini 12",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872) .matches = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873) DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874) DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 1210"),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876) .callback = dmi_check_cb
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879) .ident = "JHL90",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880) .matches = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881) DMI_MATCH(DMI_BOARD_NAME, "JHL90"),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882) DMI_MATCH(DMI_BOARD_VERSION, "REFERENCE"),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884) .callback = dmi_check_cb_extra
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887) .ident = "KHLB2",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888) .matches = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889) DMI_MATCH(DMI_BOARD_NAME, "KHLB2"),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890) DMI_MATCH(DMI_BOARD_VERSION, "REFERENCE"),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892) .callback = dmi_check_cb_extra
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894) { }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896) MODULE_DEVICE_TABLE(dmi, compal_dmi_table);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 898) static const struct power_supply_desc psy_bat_desc = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 899) .name = DRIVER_NAME,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 900) .type = POWER_SUPPLY_TYPE_BATTERY,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 901) .properties = compal_bat_properties,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 902) .num_properties = ARRAY_SIZE(compal_bat_properties),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 903) .get_property = bat_get_property,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 904) .set_property = bat_set_property,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 905) .property_is_writeable = bat_writeable_property,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 906) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 907)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 908) static void initialize_power_supply_data(struct compal_data *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 909) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 910) ec_read_sequence(BAT_MANUFACTURER_NAME_ADDR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 911) data->bat_manufacturer_name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 912) BAT_MANUFACTURER_NAME_LEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 913) data->bat_manufacturer_name[BAT_MANUFACTURER_NAME_LEN] = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 914)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 915) ec_read_sequence(BAT_MODEL_NAME_ADDR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 916) data->bat_model_name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 917) BAT_MODEL_NAME_LEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 918) data->bat_model_name[BAT_MODEL_NAME_LEN] = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 919)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 920) scnprintf(data->bat_serial_number, BAT_SERIAL_NUMBER_LEN + 1, "%d",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 921) ec_read_u16(BAT_SERIAL_NUMBER_ADDR));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 922) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 923)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 924) static void initialize_fan_control_data(struct compal_data *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 925) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 926) data->pwm_enable = 2; /* Keep motherboard in control for now */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 927) data->curr_pwm = 255; /* Try not to cause a CPU_on_fire exception
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 928) if we take over... */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 929) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 930)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 931) static int setup_rfkill(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 932) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 933) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 934)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 935) wifi_rfkill = rfkill_alloc("compal-wifi", &compal_device->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 936) RFKILL_TYPE_WLAN, &compal_rfkill_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 937) (void *) WIRELESS_WLAN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 938) if (!wifi_rfkill)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 939) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 940)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 941) ret = rfkill_register(wifi_rfkill);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 942) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 943) goto err_wifi;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 944)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 945) bt_rfkill = rfkill_alloc("compal-bluetooth", &compal_device->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 946) RFKILL_TYPE_BLUETOOTH, &compal_rfkill_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 947) (void *) WIRELESS_BT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 948) if (!bt_rfkill) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 949) ret = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 950) goto err_allocate_bt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 951) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 952) ret = rfkill_register(bt_rfkill);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 953) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 954) goto err_register_bt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 955)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 956) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 957)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 958) err_register_bt:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 959) rfkill_destroy(bt_rfkill);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 960)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 961) err_allocate_bt:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 962) rfkill_unregister(wifi_rfkill);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 963)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 964) err_wifi:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 965) rfkill_destroy(wifi_rfkill);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 966)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 967) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 968) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 969)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 970) static int __init compal_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 971) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 972) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 973)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 974) if (acpi_disabled) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 975) pr_err("ACPI needs to be enabled for this driver to work!\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 976) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 977) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 978)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 979) if (!force && !dmi_check_system(compal_dmi_table)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 980) pr_err("Motherboard not recognized (You could try the module's force-parameter)\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 981) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 982) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 983)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 984) if (acpi_video_get_backlight_type() == acpi_backlight_vendor) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 985) struct backlight_properties props;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 986) memset(&props, 0, sizeof(struct backlight_properties));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 987) props.type = BACKLIGHT_PLATFORM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 988) props.max_brightness = BACKLIGHT_LEVEL_MAX;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 989) compalbl_device = backlight_device_register(DRIVER_NAME,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 990) NULL, NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 991) &compalbl_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 992) &props);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 993) if (IS_ERR(compalbl_device))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 994) return PTR_ERR(compalbl_device);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 995) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 996)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 997) ret = platform_driver_register(&compal_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 998) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 999) goto err_backlight;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001) compal_device = platform_device_alloc(DRIVER_NAME, -1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002) if (!compal_device) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1003) ret = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1004) goto err_platform_driver;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1005) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1006)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1007) ret = platform_device_add(compal_device); /* This calls compal_probe */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1008) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1009) goto err_platform_device;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1010)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1011) ret = setup_rfkill();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1012) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1013) goto err_rfkill;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1014)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1015) pr_info("Driver " DRIVER_VERSION " successfully loaded\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1016) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1017)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1018) err_rfkill:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1019) platform_device_del(compal_device);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1020)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1021) err_platform_device:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1022) platform_device_put(compal_device);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1023)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1024) err_platform_driver:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1025) platform_driver_unregister(&compal_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1026)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1027) err_backlight:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1028) backlight_device_unregister(compalbl_device);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1029)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1030) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1031) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1032)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1033) static int compal_probe(struct platform_device *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1034) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1035) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1036) struct compal_data *data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1037) struct device *hwmon_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1038) struct power_supply_config psy_cfg = {};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1039)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1040) if (!extra_features)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1041) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1042)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1043) /* Fan control */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1044) data = devm_kzalloc(&pdev->dev, sizeof(struct compal_data), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1045) if (!data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1046) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1047)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1048) initialize_fan_control_data(data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1049)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1050) err = sysfs_create_group(&pdev->dev.kobj, &compal_platform_attr_group);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1051) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1052) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1053)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1054) hwmon_dev = devm_hwmon_device_register_with_groups(&pdev->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1055) "compal", data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1056) compal_hwmon_groups);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1057) if (IS_ERR(hwmon_dev)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1058) err = PTR_ERR(hwmon_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1059) goto remove;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1060) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1061)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1062) /* Power supply */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1063) initialize_power_supply_data(data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1064) psy_cfg.drv_data = data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1065) data->psy = power_supply_register(&compal_device->dev, &psy_bat_desc,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1066) &psy_cfg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1067) if (IS_ERR(data->psy)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1068) err = PTR_ERR(data->psy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1069) goto remove;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1070) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1071)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1072) platform_set_drvdata(pdev, data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1073)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1074) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1075)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1076) remove:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1077) sysfs_remove_group(&pdev->dev.kobj, &compal_platform_attr_group);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1078) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1079) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1080)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1081) static void __exit compal_cleanup(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1082) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1083) platform_device_unregister(compal_device);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1084) platform_driver_unregister(&compal_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1085) backlight_device_unregister(compalbl_device);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1086) rfkill_unregister(wifi_rfkill);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1087) rfkill_unregister(bt_rfkill);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1088) rfkill_destroy(wifi_rfkill);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1089) rfkill_destroy(bt_rfkill);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1090)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1091) pr_info("Driver unloaded\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1092) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1093)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1094) static int compal_remove(struct platform_device *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1095) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1096) struct compal_data *data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1097)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1098) if (!extra_features)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1099) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1100)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1101) pr_info("Unloading: resetting fan control to motherboard\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1102) pwm_disable_control();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1103)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1104) data = platform_get_drvdata(pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1105) power_supply_unregister(data->psy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1106)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1107) sysfs_remove_group(&pdev->dev.kobj, &compal_platform_attr_group);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1108)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1109) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1110) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1111)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1112)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1113) module_init(compal_init);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1114) module_exit(compal_cleanup);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1115)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1116) MODULE_AUTHOR("Cezary Jackiewicz");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1117) MODULE_AUTHOR("Roald Frederickx (roald.frederickx@gmail.com)");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1118) MODULE_DESCRIPTION("Compal Laptop Support");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1119) MODULE_VERSION(DRIVER_VERSION);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1120) MODULE_LICENSE("GPL");