FILE
lenovo-thinkpad-t14s.c
File preview with syntax highlighting.
linux-6.19.14/drivers/platform/arm64/lenovo-thinkpad-t14s.c
1// SPDX-License-Identifier: GPL-2.0-only 2/* 3 * Copyright (c) 2025, Sebastian Reichel 4 */ 5 6#include <linux/bitfield.h> 7#include <linux/bits.h> 8#include <linux/cleanup.h> 9#include <linux/container_of.h> 10#include <linux/device.h> 11#include <linux/delay.h> 12#include <linux/dev_printk.h> 13#include <linux/err.h> 14#include <linux/i2c.h> 15#include <linux/input.h> 16#include <linux/input/sparse-keymap.h> 17#include <linux/interrupt.h> 18#include <linux/leds.h> 19#include <linux/lockdep.h> 20#include <linux/module.h> 21#include <linux/regmap.h> 22#include <linux/slab.h> 23#include <linux/pm.h> 24 25#define T14S_EC_CMD_ECRD 0x02 26#define T14S_EC_CMD_ECWR 0x03 27#define T14S_EC_CMD_EVT 0xf0 28 29#define T14S_EC_REG_LED 0x0c 30#define T14S_EC_REG_KBD_BL1 0x0d 31#define T14S_EC_REG_MODERN_STANDBY 0xe0 32#define T14S_EC_MODERN_STANDBY_ENTRY BIT(1) 33#define T14S_EC_MODERN_STANDBY_EXIT BIT(0) 34#define T14S_EC_REG_KBD_BL2 0xe1 35#define T14S_EC_KBD_BL1_MASK GENMASK_U8(7, 6) 36#define T14S_EC_KBD_BL2_MASK GENMASK_U8(3, 2) 37#define T14S_EC_REG_AUD 0x30 38#define T14S_EC_MIC_MUTE_LED BIT(5) 39#define T14S_EC_SPK_MUTE_LED BIT(6) 40 41#define T14S_EC_EVT_NONE 0x00 42#define T14S_EC_EVT_KEY_FN_4 0x13 43#define T14S_EC_EVT_KEY_FN_F7 0x16 44#define T14S_EC_EVT_KEY_FN_SPACE 0x1f 45#define T14S_EC_EVT_KEY_TP_DOUBLE_TAP 0x20 46#define T14S_EC_EVT_AC_CONNECTED 0x26 47#define T14S_EC_EVT_AC_DISCONNECTED 0x27 48#define T14S_EC_EVT_KEY_POWER 0x28 49#define T14S_EC_EVT_LID_OPEN 0x2a 50#define T14S_EC_EVT_LID_CLOSED 0x2b 51#define T14S_EC_EVT_THERMAL_TZ40 0x5c 52#define T14S_EC_EVT_THERMAL_TZ42 0x5d 53#define T14S_EC_EVT_THERMAL_TZ39 0x5e 54#define T14S_EC_EVT_KEY_FN_F12 0x62 55#define T14S_EC_EVT_KEY_FN_TAB 0x63 56#define T14S_EC_EVT_KEY_FN_F8 0x64 57#define T14S_EC_EVT_KEY_FN_F10 0x65 58#define T14S_EC_EVT_KEY_FN_F4 0x6a 59#define T14S_EC_EVT_KEY_FN_D 0x6b 60#define T14S_EC_EVT_KEY_FN_T 0x6c 61#define T14S_EC_EVT_KEY_FN_H 0x6d 62#define T14S_EC_EVT_KEY_FN_M 0x6e 63#define T14S_EC_EVT_KEY_FN_L 0x6f 64#define T14S_EC_EVT_KEY_FN_RIGHT_SHIFT 0x71 65#define T14S_EC_EVT_KEY_FN_ESC 0x74 66#define T14S_EC_EVT_KEY_FN_N 0x79 67#define T14S_EC_EVT_KEY_FN_F11 0x7a 68#define T14S_EC_EVT_KEY_FN_G 0x7e 69 70/* Hardware LED blink rate is 1 Hz (500ms off, 500ms on) */ 71#define T14S_EC_BLINK_RATE_ON_OFF_MS 500 72 73/* 74 * Add a virtual offset on all key event codes for sparse keymap handling, 75 * since the sparse keymap infrastructure does not map some raw key event 76 * codes used by the EC. For example 0x16 (T14S_EC_EVT_KEY_FN_F7) is mapped 77 * to KEY_MUTE if no offset is applied. 78 */ 79#define T14S_EC_KEY_EVT_OFFSET 0x1000 80#define T14S_EC_KEY_ENTRY(key, value) \ 81 { KE_KEY, T14S_EC_KEY_EVT_OFFSET + T14S_EC_EVT_KEY_##key, { value } } 82 83enum t14s_ec_led_status_t { 84 T14S_EC_LED_OFF = 0x00, 85 T14S_EC_LED_ON = 0x80, 86 T14S_EC_LED_BLINK = 0xc0, 87}; 88 89struct t14s_ec_led_classdev { 90 struct led_classdev led_classdev; 91 int led; 92 enum t14s_ec_led_status_t cache; 93 struct t14s_ec *ec; 94}; 95 96struct t14s_ec { 97 struct regmap *regmap; 98 struct device *dev; 99 struct t14s_ec_led_classdev led_pwr_btn; 100 struct t14s_ec_led_classdev led_chrg_orange; 101 struct t14s_ec_led_classdev led_chrg_white; 102 struct t14s_ec_led_classdev led_lid_logo_dot; 103 struct led_classdev kbd_backlight; 104 struct led_classdev led_mic_mute; 105 struct led_classdev led_spk_mute; 106 struct input_dev *inputdev; 107}; 108 109static const struct regmap_config t14s_ec_regmap_config = { 110 .reg_bits = 8, 111 .val_bits = 8, 112 .max_register = 0xff, 113}; 114 115static int t14s_ec_write(void *context, unsigned int reg, 116 unsigned int val) 117{ 118 struct t14s_ec *ec = context; 119 struct i2c_client *client = to_i2c_client(ec->dev); 120 u8 buf[5] = {T14S_EC_CMD_ECWR, reg, 0x00, 0x01, val}; 121 int ret; 122 123 ret = i2c_master_send(client, buf, sizeof(buf)); 124 if (ret < 0) 125 return ret; 126 127 fsleep(10000); 128 return 0; 129} 130 131static int t14s_ec_read(void *context, unsigned int reg, 132 unsigned int *val) 133{ 134 struct t14s_ec *ec = context; 135 struct i2c_client *client = to_i2c_client(ec->dev); 136 u8 buf[4] = {T14S_EC_CMD_ECRD, reg, 0x00, 0x01}; 137 struct i2c_msg request, response; 138 u8 result; 139 int ret; 140 141 request.addr = client->addr; 142 request.flags = I2C_M_STOP; 143 request.len = sizeof(buf); 144 request.buf = buf; 145 response.addr = client->addr; 146 response.flags = I2C_M_RD; 147 response.len = 1; 148 response.buf = &result; 149 150 i2c_lock_bus(client->adapter, I2C_LOCK_SEGMENT); 151 152 ret = __i2c_transfer(client->adapter, &request, 1); 153 if (ret < 0) 154 goto out; 155 156 ret = __i2c_transfer(client->adapter, &response, 1); 157 if (ret < 0) 158 goto out; 159 160 *val = result; 161 ret = 0; 162 163out: 164 i2c_unlock_bus(client->adapter, I2C_LOCK_SEGMENT); 165 fsleep(10000); 166 return ret; 167} 168 169static const struct regmap_bus t14s_ec_regmap_bus = { 170 .reg_write = t14s_ec_write, 171 .reg_read = t14s_ec_read, 172}; 173 174static int t14s_ec_read_evt(struct t14s_ec *ec, u8 *val) 175{ 176 struct i2c_client *client = to_i2c_client(ec->dev); 177 u8 buf[4] = {T14S_EC_CMD_EVT, 0x00, 0x00, 0x01}; 178 struct i2c_msg request, response; 179 int ret; 180 181 request.addr = client->addr; 182 request.flags = I2C_M_STOP; 183 request.len = sizeof(buf); 184 request.buf = buf; 185 response.addr = client->addr; 186 response.flags = I2C_M_RD; 187 response.len = 1; 188 response.buf = val; 189 190 i2c_lock_bus(client->adapter, I2C_LOCK_SEGMENT); 191 192 ret = __i2c_transfer(client->adapter, &request, 1); 193 if (ret < 0) 194 goto out; 195 196 ret = __i2c_transfer(client->adapter, &response, 1); 197 if (ret < 0) 198 goto out; 199 200 fsleep(10000); 201 202 ret = 0; 203 204out: 205 i2c_unlock_bus(client->adapter, I2C_LOCK_SEGMENT); 206 return ret; 207} 208 209static void t14s_ec_write_sequence(struct t14s_ec *ec, u8 reg, u8 val, u8 cnt) 210{ 211 int i; 212 213 for (i = 0; i < cnt; i++) 214 regmap_write(ec->regmap, reg, val); 215} 216 217static int t14s_led_set_status(struct t14s_ec *ec, 218 struct t14s_ec_led_classdev *led, 219 const enum t14s_ec_led_status_t ledstatus) 220{ 221 int ret; 222 223 ret = regmap_write(ec->regmap, T14S_EC_REG_LED, 224 led->led | ledstatus); 225 if (ret < 0) 226 return ret; 227 228 led->cache = ledstatus; 229 return 0; 230} 231 232static int t14s_led_brightness_set(struct led_classdev *led_cdev, 233 enum led_brightness brightness) 234{ 235 struct t14s_ec_led_classdev *led = container_of(led_cdev, 236 struct t14s_ec_led_classdev, led_classdev); 237 enum t14s_ec_led_status_t new_state; 238 239 if (brightness == LED_OFF) 240 new_state = T14S_EC_LED_OFF; 241 else if (led->cache == T14S_EC_LED_BLINK) 242 new_state = T14S_EC_LED_BLINK; 243 else 244 new_state = T14S_EC_LED_ON; 245 246 return t14s_led_set_status(led->ec, led, new_state); 247} 248 249static int t14s_led_blink_set(struct led_classdev *led_cdev, 250 unsigned long *delay_on, 251 unsigned long *delay_off) 252{ 253 struct t14s_ec_led_classdev *led = container_of(led_cdev, 254 struct t14s_ec_led_classdev, led_classdev); 255 256 if (*delay_on == 0 && *delay_off == 0) { 257 /* Userspace does not provide a blink rate; we can choose it */ 258 *delay_on = T14S_EC_BLINK_RATE_ON_OFF_MS; 259 *delay_off = T14S_EC_BLINK_RATE_ON_OFF_MS; 260 } else if ((*delay_on != T14S_EC_BLINK_RATE_ON_OFF_MS) || 261 (*delay_off != T14S_EC_BLINK_RATE_ON_OFF_MS)) 262 return -EINVAL; 263 264 return t14s_led_set_status(led->ec, led, T14S_EC_LED_BLINK); 265} 266 267static int t14s_init_led(struct t14s_ec *ec, struct t14s_ec_led_classdev *led, 268 u8 id, const char *name) 269{ 270 led->led_classdev.name = name; 271 led->led_classdev.flags = LED_RETAIN_AT_SHUTDOWN; 272 led->led_classdev.max_brightness = 1; 273 led->led_classdev.brightness_set_blocking = t14s_led_brightness_set; 274 led->led_classdev.blink_set = t14s_led_blink_set; 275 led->ec = ec; 276 led->led = id; 277 278 return devm_led_classdev_register(ec->dev, &led->led_classdev); 279} 280 281static int t14s_leds_probe(struct t14s_ec *ec) 282{ 283 int ret; 284 285 ret = t14s_init_led(ec, &ec->led_pwr_btn, 0, "platform::power"); 286 if (ret) 287 return ret; 288 289 ret = t14s_init_led(ec, &ec->led_chrg_orange, 1, 290 "platform:amber:battery-charging"); 291 if (ret) 292 return ret; 293 294 ret = t14s_init_led(ec, &ec->led_chrg_white, 2, 295 "platform:white:battery-full"); 296 if (ret) 297 return ret; 298 299 ret = t14s_init_led(ec, &ec->led_lid_logo_dot, 10, 300 "platform::lid_logo_dot"); 301 if (ret) 302 return ret; 303 304 return 0; 305} 306 307static int t14s_kbd_bl_set(struct led_classdev *led_cdev, 308 enum led_brightness brightness) 309{ 310 struct t14s_ec *ec = container_of(led_cdev, struct t14s_ec, 311 kbd_backlight); 312 int ret; 313 u8 val; 314 315 val = FIELD_PREP(T14S_EC_KBD_BL1_MASK, brightness); 316 ret = regmap_update_bits(ec->regmap, T14S_EC_REG_KBD_BL1, 317 T14S_EC_KBD_BL1_MASK, val); 318 if (ret < 0) 319 return ret; 320 321 val = FIELD_PREP(T14S_EC_KBD_BL2_MASK, brightness); 322 ret = regmap_update_bits(ec->regmap, T14S_EC_REG_KBD_BL2, 323 T14S_EC_KBD_BL2_MASK, val); 324 if (ret < 0) 325 return ret; 326 327 return 0; 328} 329 330static enum led_brightness t14s_kbd_bl_get(struct led_classdev *led_cdev) 331{ 332 struct t14s_ec *ec = container_of(led_cdev, struct t14s_ec, 333 kbd_backlight); 334 unsigned int val; 335 int ret; 336 337 ret = regmap_read(ec->regmap, T14S_EC_REG_KBD_BL1, &val); 338 if (ret < 0) 339 return ret; 340 341 return FIELD_GET(T14S_EC_KBD_BL1_MASK, val); 342} 343 344static void t14s_kbd_bl_update(struct t14s_ec *ec) 345{ 346 enum led_brightness brightness = t14s_kbd_bl_get(&ec->kbd_backlight); 347 348 led_classdev_notify_brightness_hw_changed(&ec->kbd_backlight, brightness); 349} 350 351static int t14s_kbd_backlight_probe(struct t14s_ec *ec) 352{ 353 ec->kbd_backlight.name = "platform::kbd_backlight"; 354 ec->kbd_backlight.flags = LED_BRIGHT_HW_CHANGED; 355 ec->kbd_backlight.max_brightness = 2; 356 ec->kbd_backlight.brightness_set_blocking = t14s_kbd_bl_set; 357 ec->kbd_backlight.brightness_get = t14s_kbd_bl_get; 358 359 return devm_led_classdev_register(ec->dev, &ec->kbd_backlight); 360} 361 362static enum led_brightness t14s_audio_led_get(struct t14s_ec *ec, u8 led_bit) 363{ 364 unsigned int val; 365 int ret; 366 367 ret = regmap_read(ec->regmap, T14S_EC_REG_AUD, &val); 368 if (ret < 0) 369 return ret; 370 371 return !!(val & led_bit) ? LED_ON : LED_OFF; 372} 373 374static enum led_brightness t14s_audio_led_set(struct t14s_ec *ec, 375 u8 led_mask, 376 enum led_brightness brightness) 377{ 378 return regmap_assign_bits(ec->regmap, T14S_EC_REG_AUD, led_mask, brightness > 0); 379} 380 381static enum led_brightness t14s_mic_mute_led_get(struct led_classdev *led_cdev) 382{ 383 struct t14s_ec *ec = container_of(led_cdev, struct t14s_ec, 384 led_mic_mute); 385 386 return t14s_audio_led_get(ec, T14S_EC_MIC_MUTE_LED); 387} 388 389static int t14s_mic_mute_led_set(struct led_classdev *led_cdev, 390 enum led_brightness brightness) 391{ 392 struct t14s_ec *ec = container_of(led_cdev, struct t14s_ec, 393 led_mic_mute); 394 395 return t14s_audio_led_set(ec, T14S_EC_MIC_MUTE_LED, brightness); 396} 397 398static enum led_brightness t14s_spk_mute_led_get(struct led_classdev *led_cdev) 399{ 400 struct t14s_ec *ec = container_of(led_cdev, struct t14s_ec, 401 led_spk_mute); 402 403 return t14s_audio_led_get(ec, T14S_EC_SPK_MUTE_LED); 404} 405 406static int t14s_spk_mute_led_set(struct led_classdev *led_cdev, 407 enum led_brightness brightness) 408{ 409 struct t14s_ec *ec = container_of(led_cdev, struct t14s_ec, 410 led_spk_mute); 411 412 return t14s_audio_led_set(ec, T14S_EC_SPK_MUTE_LED, brightness); 413} 414 415static int t14s_kbd_audio_led_probe(struct t14s_ec *ec) 416{ 417 int ret; 418 419 ec->led_mic_mute.name = "platform::micmute"; 420 ec->led_mic_mute.max_brightness = 1; 421 ec->led_mic_mute.default_trigger = "audio-micmute"; 422 ec->led_mic_mute.brightness_set_blocking = t14s_mic_mute_led_set; 423 ec->led_mic_mute.brightness_get = t14s_mic_mute_led_get; 424 425 ec->led_spk_mute.name = "platform::mute"; 426 ec->led_spk_mute.max_brightness = 1; 427 ec->led_spk_mute.default_trigger = "audio-mute"; 428 ec->led_spk_mute.brightness_set_blocking = t14s_spk_mute_led_set; 429 ec->led_spk_mute.brightness_get = t14s_spk_mute_led_get; 430 431 ret = devm_led_classdev_register(ec->dev, &ec->led_mic_mute); 432 if (ret) 433 return ret; 434 435 return devm_led_classdev_register(ec->dev, &ec->led_spk_mute); 436} 437 438static const struct key_entry t14s_keymap[] = { 439 T14S_EC_KEY_ENTRY(FN_4, KEY_SLEEP), 440 T14S_EC_KEY_ENTRY(FN_N, KEY_VENDOR), 441 T14S_EC_KEY_ENTRY(FN_F4, KEY_MICMUTE), 442 T14S_EC_KEY_ENTRY(FN_F7, KEY_SWITCHVIDEOMODE), 443 T14S_EC_KEY_ENTRY(FN_F8, KEY_PERFORMANCE), 444 T14S_EC_KEY_ENTRY(FN_F10, KEY_SELECTIVE_SCREENSHOT), 445 T14S_EC_KEY_ENTRY(FN_F11, KEY_LINK_PHONE), 446 T14S_EC_KEY_ENTRY(FN_F12, KEY_BOOKMARKS), 447 T14S_EC_KEY_ENTRY(FN_SPACE, KEY_KBDILLUMTOGGLE), 448 T14S_EC_KEY_ENTRY(FN_ESC, KEY_FN_ESC), 449 T14S_EC_KEY_ENTRY(FN_TAB, KEY_ZOOM), 450 T14S_EC_KEY_ENTRY(FN_RIGHT_SHIFT, KEY_FN_RIGHT_SHIFT), 451 T14S_EC_KEY_ENTRY(TP_DOUBLE_TAP, KEY_PROG4), 452 { KE_END } 453}; 454 455static int t14s_input_probe(struct t14s_ec *ec) 456{ 457 int ret; 458 459 ec->inputdev = devm_input_allocate_device(ec->dev); 460 if (!ec->inputdev) 461 return -ENOMEM; 462 463 ec->inputdev->name = "ThinkPad Extra Buttons"; 464 ec->inputdev->phys = "thinkpad/input0"; 465 ec->inputdev->id.bustype = BUS_HOST; 466 ec->inputdev->dev.parent = ec->dev; 467 468 ret = sparse_keymap_setup(ec->inputdev, t14s_keymap, NULL); 469 if (ret) 470 return ret; 471 472 return input_register_device(ec->inputdev); 473} 474 475static irqreturn_t t14s_ec_irq_handler(int irq, void *data) 476{ 477 struct t14s_ec *ec = data; 478 int ret; 479 u8 val; 480 481 ret = t14s_ec_read_evt(ec, &val); 482 if (ret < 0) { 483 dev_err(ec->dev, "Failed to read event\n"); 484 return IRQ_HANDLED; 485 } 486 487 switch (val) { 488 case T14S_EC_EVT_NONE: 489 break; 490 case T14S_EC_EVT_KEY_FN_SPACE: 491 t14s_kbd_bl_update(ec); 492 fallthrough; 493 case T14S_EC_EVT_KEY_FN_F4: 494 case T14S_EC_EVT_KEY_FN_F7: 495 case T14S_EC_EVT_KEY_FN_4: 496 case T14S_EC_EVT_KEY_FN_F8: 497 case T14S_EC_EVT_KEY_FN_F12: 498 case T14S_EC_EVT_KEY_FN_TAB: 499 case T14S_EC_EVT_KEY_FN_F10: 500 case T14S_EC_EVT_KEY_FN_N: 501 case T14S_EC_EVT_KEY_FN_F11: 502 case T14S_EC_EVT_KEY_FN_ESC: 503 case T14S_EC_EVT_KEY_FN_RIGHT_SHIFT: 504 case T14S_EC_EVT_KEY_TP_DOUBLE_TAP: 505 sparse_keymap_report_event(ec->inputdev, 506 T14S_EC_KEY_EVT_OFFSET + val, 1, true); 507 break; 508 case T14S_EC_EVT_AC_CONNECTED: 509 dev_dbg(ec->dev, "AC connected\n"); 510 break; 511 case T14S_EC_EVT_AC_DISCONNECTED: 512 dev_dbg(ec->dev, "AC disconnected\n"); 513 break; 514 case T14S_EC_EVT_KEY_POWER: 515 dev_dbg(ec->dev, "power button\n"); 516 break; 517 case T14S_EC_EVT_LID_OPEN: 518 dev_dbg(ec->dev, "LID open\n"); 519 break; 520 case T14S_EC_EVT_LID_CLOSED: 521 dev_dbg(ec->dev, "LID closed\n"); 522 break; 523 case T14S_EC_EVT_THERMAL_TZ40: 524 dev_dbg(ec->dev, "Thermal Zone 40 Status Change Event (CPU/GPU)\n"); 525 break; 526 case T14S_EC_EVT_THERMAL_TZ42: 527 dev_dbg(ec->dev, "Thermal Zone 42 Status Change Event (Battery)\n"); 528 break; 529 case T14S_EC_EVT_THERMAL_TZ39: 530 dev_dbg(ec->dev, "Thermal Zone 39 Status Change Event (CPU/GPU)\n"); 531 break; 532 case T14S_EC_EVT_KEY_FN_G: 533 dev_dbg(ec->dev, "FN + G - toggle double-tapping\n"); 534 break; 535 case T14S_EC_EVT_KEY_FN_L: 536 dev_dbg(ec->dev, "FN + L - low performance mode\n"); 537 break; 538 case T14S_EC_EVT_KEY_FN_M: 539 dev_dbg(ec->dev, "FN + M - medium performance mode\n"); 540 break; 541 case T14S_EC_EVT_KEY_FN_H: 542 dev_dbg(ec->dev, "FN + H - high performance mode\n"); 543 break; 544 case T14S_EC_EVT_KEY_FN_T: 545 dev_dbg(ec->dev, "FN + T - toggle intelligent cooling mode\n"); 546 break; 547 case T14S_EC_EVT_KEY_FN_D: 548 dev_dbg(ec->dev, "FN + D - toggle privacy guard mode\n"); 549 break; 550 default: 551 dev_info(ec->dev, "Unknown EC event: 0x%02x\n", val); 552 break; 553 } 554 555 return IRQ_HANDLED; 556} 557 558static int t14s_ec_probe(struct i2c_client *client) 559{ 560 struct device *dev = &client->dev; 561 struct t14s_ec *ec; 562 int ret; 563 564 ec = devm_kzalloc(dev, sizeof(*ec), GFP_KERNEL); 565 if (!ec) 566 return -ENOMEM; 567 568 ec->dev = dev; 569 i2c_set_clientdata(client, ec); 570 571 ec->regmap = devm_regmap_init(dev, &t14s_ec_regmap_bus, 572 ec, &t14s_ec_regmap_config); 573 if (IS_ERR(ec->regmap)) 574 return dev_err_probe(dev, PTR_ERR(ec->regmap), 575 "Failed to init regmap\n"); 576 577 ret = t14s_leds_probe(ec); 578 if (ret < 0) 579 return ret; 580 581 ret = t14s_kbd_backlight_probe(ec); 582 if (ret < 0) 583 return ret; 584 585 ret = t14s_kbd_audio_led_probe(ec); 586 if (ret < 0) 587 return ret; 588 589 ret = t14s_input_probe(ec); 590 if (ret < 0) 591 return ret; 592 593 ret = devm_request_threaded_irq(dev, client->irq, NULL, 594 t14s_ec_irq_handler, 595 IRQF_ONESHOT, dev_name(dev), ec); 596 if (ret < 0) 597 return dev_err_probe(dev, ret, "Failed to get IRQ\n"); 598 599 /* 600 * Disable wakeup support by default, because the driver currently does 601 * not support masking any events and the laptop should not wake up when 602 * the LID is closed. 603 */ 604 device_wakeup_disable(dev); 605 606 return 0; 607} 608 609static int t14s_ec_suspend(struct device *dev) 610{ 611 struct t14s_ec *ec = dev_get_drvdata(dev); 612 613 led_classdev_suspend(&ec->kbd_backlight); 614 615 t14s_ec_write_sequence(ec, T14S_EC_REG_MODERN_STANDBY, 616 T14S_EC_MODERN_STANDBY_ENTRY, 3); 617 618 return 0; 619} 620 621static int t14s_ec_resume(struct device *dev) 622{ 623 struct t14s_ec *ec = dev_get_drvdata(dev); 624 625 t14s_ec_write_sequence(ec, T14S_EC_REG_MODERN_STANDBY, 626 T14S_EC_MODERN_STANDBY_EXIT, 3); 627 628 led_classdev_resume(&ec->kbd_backlight); 629 630 return 0; 631} 632 633static const struct of_device_id t14s_ec_of_match[] = { 634 { .compatible = "lenovo,thinkpad-t14s-ec" }, 635 {} 636}; 637MODULE_DEVICE_TABLE(of, t14s_ec_of_match); 638 639static const struct i2c_device_id t14s_ec_i2c_id_table[] = { 640 { "thinkpad-t14s-ec", }, 641 {} 642}; 643MODULE_DEVICE_TABLE(i2c, t14s_ec_i2c_id_table); 644 645static const struct dev_pm_ops t14s_ec_pm_ops = { 646 SYSTEM_SLEEP_PM_OPS(t14s_ec_suspend, t14s_ec_resume) 647}; 648 649static struct i2c_driver t14s_ec_i2c_driver = { 650 .driver = { 651 .name = "thinkpad-t14s-ec", 652 .of_match_table = t14s_ec_of_match, 653 .pm = &t14s_ec_pm_ops, 654 }, 655 .probe = t14s_ec_probe, 656 .id_table = t14s_ec_i2c_id_table, 657}; 658module_i2c_driver(t14s_ec_i2c_driver); 659 660MODULE_AUTHOR("Sebastian Reichel <sre@kernel.org>"); 661MODULE_DESCRIPTION("Lenovo Thinkpad T14s Embedded Controller"); 662MODULE_LICENSE("GPL");
~/
Read-only file preview.