@@ -7749,6 +7749,28 @@ static struct ibm_struct volume_driver_data = {
7749
7749
* EC 0x2f (HFSP) might be available *for reading*, but do not use
7750
7750
* it for writing.
7751
7751
*
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
+ *
7752
7774
* TPACPI_FAN_WR_TPEC:
7753
7775
* ThinkPad EC register 0x2f (HFSP): fan control loop mode
7754
7776
* Supported on almost all ThinkPads
@@ -7882,13 +7904,15 @@ enum { /* Fan control constants */
7882
7904
enum fan_status_access_mode {
7883
7905
TPACPI_FAN_NONE = 0 , /* No fan status or control */
7884
7906
TPACPI_FAN_RD_ACPI_GFAN , /* Use ACPI GFAN */
7907
+ TPACPI_FAN_RD_ACPI_FANG , /* Use ACPI FANG */
7885
7908
TPACPI_FAN_RD_TPEC , /* Use ACPI EC regs 0x2f, 0x84-0x85 */
7886
7909
TPACPI_FAN_RD_TPEC_NS , /* Use non-standard ACPI EC regs (eg: L13 Yoga gen2 etc.) */
7887
7910
};
7888
7911
7889
7912
enum fan_control_access_mode {
7890
7913
TPACPI_FAN_WR_NONE = 0 , /* No fan control */
7891
7914
TPACPI_FAN_WR_ACPI_SFAN , /* Use ACPI SFAN */
7915
+ TPACPI_FAN_WR_ACPI_FANW , /* Use ACPI FANW */
7892
7916
TPACPI_FAN_WR_TPEC , /* Use ACPI EC reg 0x2f */
7893
7917
TPACPI_FAN_WR_ACPI_FANS , /* Use ACPI FANS and EC reg 0x2f */
7894
7918
};
@@ -7922,9 +7946,13 @@ TPACPI_HANDLE(fans, ec, "FANS"); /* X31, X40, X41 */
7922
7946
TPACPI_HANDLE (gfan , ec , "GFAN" , /* 570 */
7923
7947
"\\FSPD" , /* 600e/x, 770e, 770x */
7924
7948
); /* all others */
7949
+ TPACPI_HANDLE (fang , ec , "FANG" , /* E531 */
7950
+ ); /* all others */
7925
7951
TPACPI_HANDLE (sfan , ec , "SFAN" , /* 570 */
7926
7952
"JFNS" , /* 770x-JL */
7927
7953
); /* all others */
7954
+ TPACPI_HANDLE (fanw , ec , "FANW" , /* E531 */
7955
+ ); /* all others */
7928
7956
7929
7957
/*
7930
7958
* Unitialized HFSP quirk: ACPI DSDT and EC fail to initialize the
@@ -8031,6 +8059,23 @@ static int fan_get_status(u8 *status)
8031
8059
8032
8060
break ;
8033
8061
}
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
+ }
8034
8079
case TPACPI_FAN_RD_TPEC :
8035
8080
/* all except 570, 600e/x, 770e, 770x */
8036
8081
if (unlikely (!acpi_ec_read (fan_status_offset , & s )))
@@ -8145,6 +8190,17 @@ static int fan2_get_speed(unsigned int *speed)
8145
8190
if (speed )
8146
8191
* speed = lo ? FAN_RPM_CAL_CONST / lo : 0 ;
8147
8192
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
+ }
8148
8204
8149
8205
default :
8150
8206
return - ENXIO ;
@@ -8204,6 +8260,32 @@ static int fan_set_level(int level)
8204
8260
tp_features .fan_ctrl_status_undef = 0 ;
8205
8261
break ;
8206
8262
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
+
8207
8289
default :
8208
8290
return - ENXIO ;
8209
8291
}
@@ -8282,6 +8364,19 @@ static int fan_set_enable(void)
8282
8364
rc = 0 ;
8283
8365
break ;
8284
8366
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
+
8285
8380
default :
8286
8381
rc = - ENXIO ;
8287
8382
}
@@ -8324,6 +8419,22 @@ static int fan_set_disable(void)
8324
8419
fan_control_desired_level = 0 ;
8325
8420
break ;
8326
8421
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
+
8327
8438
default :
8328
8439
rc = - ENXIO ;
8329
8440
}
@@ -8357,6 +8468,23 @@ static int fan_set_speed(int speed)
8357
8468
rc = - EINVAL ;
8358
8469
break ;
8359
8470
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
+
8360
8488
default :
8361
8489
rc = - ENXIO ;
8362
8490
}
@@ -8699,6 +8827,10 @@ static int __init fan_init(struct ibm_init_struct *iibm)
8699
8827
TPACPI_ACPIHANDLE_INIT (gfan );
8700
8828
TPACPI_ACPIHANDLE_INIT (sfan );
8701
8829
}
8830
+ if (tpacpi_is_lenovo ()) {
8831
+ TPACPI_ACPIHANDLE_INIT (fang );
8832
+ TPACPI_ACPIHANDLE_INIT (fanw );
8833
+ }
8702
8834
8703
8835
quirks = tpacpi_check_quirks (fan_quirk_table ,
8704
8836
ARRAY_SIZE (fan_quirk_table ));
@@ -8718,6 +8850,9 @@ static int __init fan_init(struct ibm_init_struct *iibm)
8718
8850
if (gfan_handle ) {
8719
8851
/* 570, 600e/x, 770e, 770x */
8720
8852
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 ;
8721
8856
} else {
8722
8857
/* all other ThinkPads: note that even old-style
8723
8858
* ThinkPad ECs supports the fan control register */
@@ -8764,6 +8899,11 @@ static int __init fan_init(struct ibm_init_struct *iibm)
8764
8899
fan_control_access_mode = TPACPI_FAN_WR_ACPI_SFAN ;
8765
8900
fan_control_commands |=
8766
8901
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 ;
8767
8907
} else {
8768
8908
if (!gfan_handle ) {
8769
8909
/* gfan without sfan means no fan control */
@@ -8915,6 +9055,7 @@ static int fan_read(struct seq_file *m)
8915
9055
8916
9056
case TPACPI_FAN_RD_TPEC_NS :
8917
9057
case TPACPI_FAN_RD_TPEC :
9058
+ case TPACPI_FAN_RD_ACPI_FANG :
8918
9059
/* all except 570, 600e/x, 770e, 770x */
8919
9060
rc = fan_get_status_safe (& status );
8920
9061
if (rc )
@@ -8935,7 +9076,7 @@ static int fan_read(struct seq_file *m)
8935
9076
* No other levels settings available
8936
9077
*/
8937
9078
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 ) {
8939
9080
if (status & TP_EC_FAN_FULLSPEED )
8940
9081
/* Disengaged mode takes precedence */
8941
9082
seq_printf (m , "level:\t\tdisengaged\n" );
0 commit comments