@@ -7749,6 +7749,28 @@ static struct ibm_struct volume_driver_data = {
77497749 * EC 0x2f (HFSP) might be available *for reading*, but do not use
77507750 * it for writing.
77517751 *
7752+ * TPACPI_FAN_RD_ACPI_FANG:
7753+ * ACPI FANG method: returns fan control register
7754+ *
7755+ * Takes one parameter which is 0x8100 plus the offset to EC memory
7756+ * address 0xf500 and returns the byte at this address.
7757+ *
7758+ * 0xf500:
7759+ * When the value is less than 9 automatic mode is enabled
7760+ * 0xf502:
7761+ * Contains the current fan speed from 0-100%
7762+ * 0xf506:
7763+ * Bit 7 has to be set in order to enable manual control by
7764+ * writing a value >= 9 to 0xf500
7765+ *
7766+ * TPACPI_FAN_WR_ACPI_FANW:
7767+ * ACPI FANW method: sets fan control registers
7768+ *
7769+ * Takes 0x8100 plus the offset to EC memory address 0xf500 and the
7770+ * value to be written there as parameters.
7771+ *
7772+ * see TPACPI_FAN_RD_ACPI_FANG
7773+ *
77527774 * TPACPI_FAN_WR_TPEC:
77537775 * ThinkPad EC register 0x2f (HFSP): fan control loop mode
77547776 * Supported on almost all ThinkPads
@@ -7882,13 +7904,15 @@ enum { /* Fan control constants */
78827904enum fan_status_access_mode {
78837905 TPACPI_FAN_NONE = 0 , /* No fan status or control */
78847906 TPACPI_FAN_RD_ACPI_GFAN , /* Use ACPI GFAN */
7907+ TPACPI_FAN_RD_ACPI_FANG , /* Use ACPI FANG */
78857908 TPACPI_FAN_RD_TPEC , /* Use ACPI EC regs 0x2f, 0x84-0x85 */
78867909 TPACPI_FAN_RD_TPEC_NS , /* Use non-standard ACPI EC regs (eg: L13 Yoga gen2 etc.) */
78877910};
78887911
78897912enum fan_control_access_mode {
78907913 TPACPI_FAN_WR_NONE = 0 , /* No fan control */
78917914 TPACPI_FAN_WR_ACPI_SFAN , /* Use ACPI SFAN */
7915+ TPACPI_FAN_WR_ACPI_FANW , /* Use ACPI FANW */
78927916 TPACPI_FAN_WR_TPEC , /* Use ACPI EC reg 0x2f */
78937917 TPACPI_FAN_WR_ACPI_FANS , /* Use ACPI FANS and EC reg 0x2f */
78947918};
@@ -7922,9 +7946,13 @@ TPACPI_HANDLE(fans, ec, "FANS"); /* X31, X40, X41 */
79227946TPACPI_HANDLE (gfan , ec , "GFAN" , /* 570 */
79237947 "\\FSPD" , /* 600e/x, 770e, 770x */
79247948 ); /* all others */
7949+ TPACPI_HANDLE (fang , ec , "FANG" , /* E531 */
7950+ ); /* all others */
79257951TPACPI_HANDLE (sfan , ec , "SFAN" , /* 570 */
79267952 "JFNS" , /* 770x-JL */
79277953 ); /* all others */
7954+ TPACPI_HANDLE (fanw , ec , "FANW" , /* E531 */
7955+ ); /* all others */
79287956
79297957/*
79307958 * Unitialized HFSP quirk: ACPI DSDT and EC fail to initialize the
@@ -8031,6 +8059,23 @@ static int fan_get_status(u8 *status)
80318059
80328060 break ;
80338061 }
8062+ case TPACPI_FAN_RD_ACPI_FANG : {
8063+ /* E531 */
8064+ int mode , speed ;
8065+
8066+ if (unlikely (!acpi_evalf (fang_handle , & mode , NULL , "dd" , 0x8100 )))
8067+ return - EIO ;
8068+ if (unlikely (!acpi_evalf (fang_handle , & speed , NULL , "dd" , 0x8102 )))
8069+ return - EIO ;
8070+
8071+ if (likely (status )) {
8072+ * status = speed * 7 / 100 ;
8073+ if (mode < 9 )
8074+ * status |= TP_EC_FAN_AUTO ;
8075+ }
8076+
8077+ break ;
8078+ }
80348079 case TPACPI_FAN_RD_TPEC :
80358080 /* all except 570, 600e/x, 770e, 770x */
80368081 if (unlikely (!acpi_ec_read (fan_status_offset , & s )))
@@ -8145,6 +8190,17 @@ static int fan2_get_speed(unsigned int *speed)
81458190 if (speed )
81468191 * speed = lo ? FAN_RPM_CAL_CONST / lo : 0 ;
81478192 break ;
8193+ case TPACPI_FAN_RD_ACPI_FANG : {
8194+ /* E531 */
8195+ int speed_tmp ;
8196+
8197+ if (unlikely (!acpi_evalf (fang_handle , & speed_tmp , NULL , "dd" , 0x8102 )))
8198+ return - EIO ;
8199+
8200+ if (likely (speed ))
8201+ * speed = speed_tmp * 65535 / 100 ;
8202+ break ;
8203+ }
81488204
81498205 default :
81508206 return - ENXIO ;
@@ -8204,6 +8260,32 @@ static int fan_set_level(int level)
82048260 tp_features .fan_ctrl_status_undef = 0 ;
82058261 break ;
82068262
8263+ case TPACPI_FAN_WR_ACPI_FANW :
8264+ if (!(level & TP_EC_FAN_AUTO ) && (level < 0 || level > 7 ))
8265+ return - EINVAL ;
8266+ if (level & TP_EC_FAN_FULLSPEED )
8267+ return - EINVAL ;
8268+
8269+ if (level & TP_EC_FAN_AUTO ) {
8270+ if (!acpi_evalf (fanw_handle , NULL , NULL , "vdd" , 0x8106 , 0x05 )) {
8271+ return - EIO ;
8272+ }
8273+ if (!acpi_evalf (fanw_handle , NULL , NULL , "vdd" , 0x8100 , 0x00 )) {
8274+ return - EIO ;
8275+ }
8276+ } else {
8277+ if (!acpi_evalf (fanw_handle , NULL , NULL , "vdd" , 0x8106 , 0x45 )) {
8278+ return - EIO ;
8279+ }
8280+ if (!acpi_evalf (fanw_handle , NULL , NULL , "vdd" , 0x8100 , 0xff )) {
8281+ return - EIO ;
8282+ }
8283+ if (!acpi_evalf (fanw_handle , NULL , NULL , "vdd" , 0x8102 , level * 100 / 7 )) {
8284+ return - EIO ;
8285+ }
8286+ }
8287+ break ;
8288+
82078289 default :
82088290 return - ENXIO ;
82098291 }
@@ -8282,6 +8364,19 @@ static int fan_set_enable(void)
82828364 rc = 0 ;
82838365 break ;
82848366
8367+ case TPACPI_FAN_WR_ACPI_FANW :
8368+ if (!acpi_evalf (fanw_handle , NULL , NULL , "vdd" , 0x8106 , 0x05 )) {
8369+ rc = - EIO ;
8370+ break ;
8371+ }
8372+ if (!acpi_evalf (fanw_handle , NULL , NULL , "vdd" , 0x8100 , 0x00 )) {
8373+ rc = - EIO ;
8374+ break ;
8375+ }
8376+
8377+ rc = 0 ;
8378+ break ;
8379+
82858380 default :
82868381 rc = - ENXIO ;
82878382 }
@@ -8324,6 +8419,22 @@ static int fan_set_disable(void)
83248419 fan_control_desired_level = 0 ;
83258420 break ;
83268421
8422+ case TPACPI_FAN_WR_ACPI_FANW :
8423+ if (!acpi_evalf (fanw_handle , NULL , NULL , "vdd" , 0x8106 , 0x45 )) {
8424+ rc = - EIO ;
8425+ break ;
8426+ }
8427+ if (!acpi_evalf (fanw_handle , NULL , NULL , "vdd" , 0x8100 , 0xff )) {
8428+ rc = - EIO ;
8429+ break ;
8430+ }
8431+ if (!acpi_evalf (fanw_handle , NULL , NULL , "vdd" , 0x8102 , 0x00 )) {
8432+ rc = - EIO ;
8433+ break ;
8434+ }
8435+ rc = 0 ;
8436+ break ;
8437+
83278438 default :
83288439 rc = - ENXIO ;
83298440 }
@@ -8357,6 +8468,23 @@ static int fan_set_speed(int speed)
83578468 rc = - EINVAL ;
83588469 break ;
83598470
8471+ case TPACPI_FAN_WR_ACPI_FANW :
8472+ if (speed >= 0 && speed <= 65535 ) {
8473+ if (!acpi_evalf (fanw_handle , NULL , NULL , "vdd" , 0x8106 , 0x45 )) {
8474+ rc = - EIO ;
8475+ break ;
8476+ }
8477+ if (!acpi_evalf (fanw_handle , NULL , NULL , "vdd" , 0x8100 , 0xff )) {
8478+ rc = - EIO ;
8479+ break ;
8480+ }
8481+ if (!acpi_evalf (fanw_handle , NULL , NULL , "vdd" ,
8482+ 0x8102 , speed * 100 / 65535 ))
8483+ rc = - EIO ;
8484+ } else
8485+ rc = - EINVAL ;
8486+ break ;
8487+
83608488 default :
83618489 rc = - ENXIO ;
83628490 }
@@ -8699,6 +8827,10 @@ static int __init fan_init(struct ibm_init_struct *iibm)
86998827 TPACPI_ACPIHANDLE_INIT (gfan );
87008828 TPACPI_ACPIHANDLE_INIT (sfan );
87018829 }
8830+ if (tpacpi_is_lenovo ()) {
8831+ TPACPI_ACPIHANDLE_INIT (fang );
8832+ TPACPI_ACPIHANDLE_INIT (fanw );
8833+ }
87028834
87038835 quirks = tpacpi_check_quirks (fan_quirk_table ,
87048836 ARRAY_SIZE (fan_quirk_table ));
@@ -8718,6 +8850,9 @@ static int __init fan_init(struct ibm_init_struct *iibm)
87188850 if (gfan_handle ) {
87198851 /* 570, 600e/x, 770e, 770x */
87208852 fan_status_access_mode = TPACPI_FAN_RD_ACPI_GFAN ;
8853+ } else if (fang_handle ) {
8854+ /* E531 */
8855+ fan_status_access_mode = TPACPI_FAN_RD_ACPI_FANG ;
87218856 } else {
87228857 /* all other ThinkPads: note that even old-style
87238858 * ThinkPad ECs supports the fan control register */
@@ -8764,6 +8899,11 @@ static int __init fan_init(struct ibm_init_struct *iibm)
87648899 fan_control_access_mode = TPACPI_FAN_WR_ACPI_SFAN ;
87658900 fan_control_commands |=
87668901 TPACPI_FAN_CMD_LEVEL | TPACPI_FAN_CMD_ENABLE ;
8902+ } else if (fanw_handle ) {
8903+ /* E531 */
8904+ fan_control_access_mode = TPACPI_FAN_WR_ACPI_FANW ;
8905+ fan_control_commands |=
8906+ TPACPI_FAN_CMD_LEVEL | TPACPI_FAN_CMD_SPEED | TPACPI_FAN_CMD_ENABLE ;
87678907 } else {
87688908 if (!gfan_handle ) {
87698909 /* gfan without sfan means no fan control */
@@ -8915,6 +9055,7 @@ static int fan_read(struct seq_file *m)
89159055
89169056 case TPACPI_FAN_RD_TPEC_NS :
89179057 case TPACPI_FAN_RD_TPEC :
9058+ case TPACPI_FAN_RD_ACPI_FANG :
89189059 /* all except 570, 600e/x, 770e, 770x */
89199060 rc = fan_get_status_safe (& status );
89209061 if (rc )
@@ -8935,7 +9076,7 @@ static int fan_read(struct seq_file *m)
89359076 * No other levels settings available
89369077 */
89379078 seq_printf (m , "level:\t\t%s\n" , status & FAN_NS_CTRL ? "unknown" : "auto" );
8938- } else {
9079+ } else if ( fan_status_access_mode == TPACPI_FAN_RD_TPEC ) {
89399080 if (status & TP_EC_FAN_FULLSPEED )
89409081 /* Disengaged mode takes precedence */
89419082 seq_printf (m , "level:\t\tdisengaged\n" );
0 commit comments