From patchwork Fri Jun 24 18:36:39 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Maximilian Luz X-Patchwork-Id: 12895003 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 7D026CCA473 for ; Fri, 24 Jun 2022 18:37:06 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229647AbiFXShF (ORCPT ); Fri, 24 Jun 2022 14:37:05 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:35826 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231394AbiFXShF (ORCPT ); Fri, 24 Jun 2022 14:37:05 -0400 Received: from mail-ed1-x533.google.com (mail-ed1-x533.google.com [IPv6:2a00:1450:4864:20::533]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 72CD580507; Fri, 24 Jun 2022 11:37:03 -0700 (PDT) Received: by mail-ed1-x533.google.com with SMTP id z7so4600472edm.13; Fri, 24 Jun 2022 11:37:03 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=eFaSTPA4+vnB1sfsQUKV3lnilUcO33eBAQdm/aUWTyw=; b=IjigXTrye7TgR1uPoO+cu/Nvt1/zL9wInvTrH54lK6ryKUbEf15n2ffECt7R160czK bsTw1kTAqI2/xcKkqMS1qiYPf5GQ8/QCqgZcP3jGhENb5Wq1PBpH0EDXNA2RFRBjkh3g 2+Xyotn36s1pKMwRdZ6EQ/jDJWkx92GLUk0wcLWOAfMcEvsFGQu6xH8Xr3lSR9HCdUZU s8p7k3uUKDMB494AqL/6jBH+mR6WiA6+VUgzVACytF0roq7Qo3CDONl1sI1cfhu+47ej QQ5Zwz767yFMA7b/I7CaJKz/oz705WRlpW37gbLZ5nWLrtU3heRIKG5jNSWyS9BzzNsR cD6Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=eFaSTPA4+vnB1sfsQUKV3lnilUcO33eBAQdm/aUWTyw=; b=YNrqRhB6MVfNBJM2l3507y4oVvjnfPgMP+QFIiF2o1skX8CnY2wTZnhDmKJxfniRk7 SxobMtWquTVtFUryhBRUH6QVgjSxNKEmnYpvyot6Gf0bSis6vcbo1p3w6UhHahIh6hoo jG0+yGnd5DkQFvhWBBf/OMOtsepwgs0F2dcQ4sjnjtsQxiy9Kr/07kBUYdWYq+bFnmpG 7ShTU5cVu5XNf9rMitwwv08HFz2a33zU/bgV7Rd5KXCyKuMGlzIwE/fG58vK7ioBo5mx OXSbxeX94TdDnGYLbLDLCTN0MGyOvTWL90Q2QOipJRwq01EU2uKFB4Q0OdlxGsH/ruVl DXsw== X-Gm-Message-State: AJIora+BqbkvmcowtG46nKJmXn4mf2MxSUhwSw9MmnnVKnxdMlky+OYH o3QFKJRsv8d2fMQIwN/x4YRTKAV+Vyw= X-Google-Smtp-Source: AGRyM1tN9gxDcP6A7nUy5g7kFjosPfFYDaxIlvu2+WhBLN9yNiEbUcPVSFDWLYdzzcSahzS0sps47Q== X-Received: by 2002:a05:6402:3553:b0:434:ef34:664f with SMTP id f19-20020a056402355300b00434ef34664fmr610148edd.236.1656095821915; Fri, 24 Jun 2022 11:37:01 -0700 (PDT) Received: from xws.localdomain ([37.120.217.162]) by smtp.gmail.com with ESMTPSA id jw12-20020a170906e94c00b00722e8827c53sm1493822ejb.208.2022.06.24.11.37.00 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 24 Jun 2022 11:37:01 -0700 (PDT) From: Maximilian Luz To: Hans de Goede Cc: Mark Gross , platform-driver-x86@vger.kernel.org, linux-kernel@vger.kernel.org, Maximilian Luz Subject: [PATCH 1/4] platform/surface: aggregator: Add helper macros for requests with argument and return value Date: Fri, 24 Jun 2022 20:36:39 +0200 Message-Id: <20220624183642.910893-2-luzmaximilian@gmail.com> X-Mailer: git-send-email 2.36.1 In-Reply-To: <20220624183642.910893-1-luzmaximilian@gmail.com> References: <20220624183642.910893-1-luzmaximilian@gmail.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: platform-driver-x86@vger.kernel.org Add helper macros for synchronous stack-allocated Surface Aggregator request with both argument and return value, similar to the current argument-only and return-value-only ones. Signed-off-by: Maximilian Luz --- include/linux/surface_aggregator/controller.h | 125 ++++++++++++++++++ include/linux/surface_aggregator/device.h | 36 +++++ 2 files changed, 161 insertions(+) diff --git a/include/linux/surface_aggregator/controller.h b/include/linux/surface_aggregator/controller.h index 50a2b4926c06..d11a1c6e3186 100644 --- a/include/linux/surface_aggregator/controller.h +++ b/include/linux/surface_aggregator/controller.h @@ -469,6 +469,67 @@ struct ssam_request_spec_md { return 0; \ } +/** + * SSAM_DEFINE_SYNC_REQUEST_WR() - Define synchronous SAM request function with + * both argument and return value. + * @name: Name of the generated function. + * @atype: Type of the request's argument. + * @rtype: Type of the request's return value. + * @spec: Specification (&struct ssam_request_spec) defining the request. + * + * Defines a function executing the synchronous SAM request specified by @spec, + * with the request taking an argument of type @atype and having a return value + * of type @rtype. The generated function takes care of setting up the request + * and response structs, buffer allocation, as well as execution of the request + * itself, returning once the request has been fully completed. The required + * transport buffer will be allocated on the stack. + * + * The generated function is defined as ``static int name(struct + * ssam_controller *ctrl, const atype *arg, rtype *ret)``, returning the status + * of the request, which is zero on success and negative on failure. The + * ``ctrl`` parameter is the controller via which the request is sent. The + * request argument is specified via the ``arg`` pointer. The request's return + * value is written to the memory pointed to by the ``ret`` parameter. + * + * Refer to ssam_request_sync_onstack() for more details on the behavior of + * the generated function. + */ +#define SSAM_DEFINE_SYNC_REQUEST_WR(name, atype, rtype, spec...) \ + static int name(struct ssam_controller *ctrl, const atype *arg, rtype *ret) \ + { \ + struct ssam_request_spec s = (struct ssam_request_spec)spec; \ + struct ssam_request rqst; \ + struct ssam_response rsp; \ + int status; \ + \ + rqst.target_category = s.target_category; \ + rqst.target_id = s.target_id; \ + rqst.command_id = s.command_id; \ + rqst.instance_id = s.instance_id; \ + rqst.flags = s.flags | SSAM_REQUEST_HAS_RESPONSE; \ + rqst.length = sizeof(atype); \ + rqst.payload = (u8 *)arg; \ + \ + rsp.capacity = sizeof(rtype); \ + rsp.length = 0; \ + rsp.pointer = (u8 *)ret; \ + \ + status = ssam_request_sync_onstack(ctrl, &rqst, &rsp, sizeof(atype)); \ + if (status) \ + return status; \ + \ + if (rsp.length != sizeof(rtype)) { \ + struct device *dev = ssam_controller_device(ctrl); \ + dev_err(dev, \ + "rqst: invalid response length, expected %zu, got %zu (tc: %#04x, cid: %#04x)", \ + sizeof(rtype), rsp.length, rqst.target_category,\ + rqst.command_id); \ + return -EIO; \ + } \ + \ + return 0; \ + } + /** * SSAM_DEFINE_SYNC_REQUEST_MD_N() - Define synchronous multi-device SAM * request function with neither argument nor return value. @@ -613,6 +674,70 @@ struct ssam_request_spec_md { return 0; \ } +/** + * SSAM_DEFINE_SYNC_REQUEST_MD_WR() - Define synchronous multi-device SAM + * request function with both argument and return value. + * @name: Name of the generated function. + * @atype: Type of the request's argument. + * @rtype: Type of the request's return value. + * @spec: Specification (&struct ssam_request_spec_md) defining the request. + * + * Defines a function executing the synchronous SAM request specified by @spec, + * with the request taking an argument of type @atype and having a return value + * of type @rtype. Device specifying parameters are not hard-coded, but instead + * must be provided to the function. The generated function takes care of + * setting up the request and response structs, buffer allocation, as well as + * execution of the request itself, returning once the request has been fully + * completed. The required transport buffer will be allocated on the stack. + * + * The generated function is defined as ``static int name(struct + * ssam_controller *ctrl, u8 tid, u8 iid, const atype *arg, rtype *ret)``, + * returning the status of the request, which is zero on success and negative + * on failure. The ``ctrl`` parameter is the controller via which the request + * is sent, ``tid`` the target ID for the request, and ``iid`` the instance ID. + * The request argument is specified via the ``arg`` pointer. The request's + * return value is written to the memory pointed to by the ``ret`` parameter. + * + * Refer to ssam_request_sync_onstack() for more details on the behavior of + * the generated function. + */ +#define SSAM_DEFINE_SYNC_REQUEST_MD_WR(name, atype, rtype, spec...) \ + static int name(struct ssam_controller *ctrl, u8 tid, u8 iid, \ + const atype *arg, rtype *ret) \ + { \ + struct ssam_request_spec_md s = (struct ssam_request_spec_md)spec; \ + struct ssam_request rqst; \ + struct ssam_response rsp; \ + int status; \ + \ + rqst.target_category = s.target_category; \ + rqst.target_id = tid; \ + rqst.command_id = s.command_id; \ + rqst.instance_id = iid; \ + rqst.flags = s.flags | SSAM_REQUEST_HAS_RESPONSE; \ + rqst.length = sizeof(atype); \ + rqst.payload = (u8 *)arg; \ + \ + rsp.capacity = sizeof(rtype); \ + rsp.length = 0; \ + rsp.pointer = (u8 *)ret; \ + \ + status = ssam_request_sync_onstack(ctrl, &rqst, &rsp, sizeof(atype)); \ + if (status) \ + return status; \ + \ + if (rsp.length != sizeof(rtype)) { \ + struct device *dev = ssam_controller_device(ctrl); \ + dev_err(dev, \ + "rqst: invalid response length, expected %zu, got %zu (tc: %#04x, cid: %#04x)", \ + sizeof(rtype), rsp.length, rqst.target_category,\ + rqst.command_id); \ + return -EIO; \ + } \ + \ + return 0; \ + } + /* -- Event notifier/callbacks. --------------------------------------------- */ diff --git a/include/linux/surface_aggregator/device.h b/include/linux/surface_aggregator/device.h index c418f7f2732d..6cf7e80312d5 100644 --- a/include/linux/surface_aggregator/device.h +++ b/include/linux/surface_aggregator/device.h @@ -483,6 +483,42 @@ static inline void ssam_remove_clients(struct device *dev) {} sdev->uid.instance, ret); \ } +/** + * SSAM_DEFINE_SYNC_REQUEST_CL_WR() - Define synchronous client-device SAM + * request function with argument and return value. + * @name: Name of the generated function. + * @atype: Type of the request's argument. + * @rtype: Type of the request's return value. + * @spec: Specification (&struct ssam_request_spec_md) defining the request. + * + * Defines a function executing the synchronous SAM request specified by @spec, + * with the request taking an argument of type @atype and having a return value + * of type @rtype. Device specifying parameters are not hard-coded, but instead + * are provided via the client device, specifically its UID, supplied when + * calling this function. The generated function takes care of setting up the + * request struct, buffer allocation, as well as execution of the request + * itself, returning once the request has been fully completed. The required + * transport buffer will be allocated on the stack. + * + * The generated function is defined as ``static int name(struct ssam_device + * *sdev, const atype *arg, rtype *ret)``, returning the status of the request, + * which is zero on success and negative on failure. The ``sdev`` parameter + * specifies both the target device of the request and by association the + * controller via which the request is sent. The request's argument is + * specified via the ``arg`` pointer. The request's return value is written to + * the memory pointed to by the ``ret`` parameter. + * + * Refer to ssam_request_sync_onstack() for more details on the behavior of + * the generated function. + */ +#define SSAM_DEFINE_SYNC_REQUEST_CL_WR(name, atype, rtype, spec...) \ + SSAM_DEFINE_SYNC_REQUEST_MD_WR(__raw_##name, atype, rtype, spec) \ + static int name(struct ssam_device *sdev, const atype *arg, rtype *ret) \ + { \ + return __raw_##name(sdev->ctrl, sdev->uid.target, \ + sdev->uid.instance, arg, ret); \ + } + /* -- Helpers for client-device notifiers. ---------------------------------- */ From patchwork Fri Jun 24 18:36:40 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Maximilian Luz X-Patchwork-Id: 12895005 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 216E7C43334 for ; Fri, 24 Jun 2022 18:37:10 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231639AbiFXShJ (ORCPT ); Fri, 24 Jun 2022 14:37:09 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:35866 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231617AbiFXShH (ORCPT ); Fri, 24 Jun 2022 14:37:07 -0400 Received: from mail-ej1-x62e.google.com (mail-ej1-x62e.google.com [IPv6:2a00:1450:4864:20::62e]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 751F980507; Fri, 24 Jun 2022 11:37:05 -0700 (PDT) Received: by mail-ej1-x62e.google.com with SMTP id ge10so6385469ejb.7; Fri, 24 Jun 2022 11:37:05 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=uwgVPZHuVMNkdfCa9UKUwY1cxzbIh3l91t/u7GZPQdk=; b=SFDn17tQvIfE69hDuDP35SrwWTg3D4/IonxhTsD/YLQOtvqNiA3NGg0Zx+X7vRwp/N 2QazRVybQ/4ZceKRQzb8AFPcYCyxvQaBLkByFztDjnSsU9e+m6O42haLHQa7Vj80vcO4 RSOzvDXDyzh3ERHmZwUCoZcL4BHyLVPxQGlW58Oe7YslzWYCYiISj3B8TghSy2eBfDJI ZttYrQp6FbkufIvEksPJj8QDuqTpgbPQVw4qGssbA85oPQhJWFdQSRLu2rIgYZr72c0i HhNqcG6Xmr9N2RkUQli+rfnbD3GhPvGngXof/0QiUaozcV6xI3uiHS638bMjU+pUdZRF VPwA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=uwgVPZHuVMNkdfCa9UKUwY1cxzbIh3l91t/u7GZPQdk=; b=WUxli5GdyEvIGXG4BLiPsMyswqJrHgIrmUuFQhRzgORxUUS4SNcxr8ucXaHHsFa8HC lsAf2pG/ml4rwdY0wF0Z5azuNCI98/Wr4n51g4AnNAQiNvs6THpio9OBxA2r00UFsatj Z+4s1HMaTTh8bjUkistgsJD0bDyRDyPvzjq9daNrtU5lh5L9GVAdyNvcC3tbp0FB3FE8 RFoWhD5BRtFI1VO6SwYOb+E9aezx5j33AJj4T28CSr88tVdv6R8BS3b0jpy6FbIu6lF6 4nv/ubH7Xb0slt+BiU3LDrHuwB3xvSYmQ2cRqqzvxBkw4V7nQiY6rNr5vwyKIYjErTmc disA== X-Gm-Message-State: AJIora8R8YHvvjLOkoLkXgBB4m3vWF3aOkQMT6fXkijKAhQUY8egE7OZ i6D85gGHviZtujf6pykuttU= X-Google-Smtp-Source: AGRyM1sm6lMMlumIPpmGRAWfdOdVhgyEzLxZmD4DPZGiRJ2tutc7gySrKYqmwfu2+95Zr1Ywvw6trA== X-Received: by 2002:a17:907:3e18:b0:722:be7e:302c with SMTP id hp24-20020a1709073e1800b00722be7e302cmr339265ejc.437.1656095823848; Fri, 24 Jun 2022 11:37:03 -0700 (PDT) Received: from xws.localdomain ([37.120.217.162]) by smtp.gmail.com with ESMTPSA id jw12-20020a170906e94c00b00722e8827c53sm1493822ejb.208.2022.06.24.11.37.02 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 24 Jun 2022 11:37:03 -0700 (PDT) From: Maximilian Luz To: Hans de Goede Cc: Mark Gross , platform-driver-x86@vger.kernel.org, linux-kernel@vger.kernel.org, Maximilian Luz Subject: [PATCH 2/4] platform/surface: Add KIP/POS tablet-mode switch driver Date: Fri, 24 Jun 2022 20:36:40 +0200 Message-Id: <20220624183642.910893-3-luzmaximilian@gmail.com> X-Mailer: git-send-email 2.36.1 In-Reply-To: <20220624183642.910893-1-luzmaximilian@gmail.com> References: <20220624183642.910893-1-luzmaximilian@gmail.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: platform-driver-x86@vger.kernel.org Add a driver providing a tablet-mode switch input device for Microsoft Surface devices using the Surface Aggregator KIP subsystem (to manage detachable peripherals) or POS subsystem (to obtain device posture information). The KIP (full name unknown, abbreviation found through reverse engineering) subsystem is used on the Surface Pro 8 and Surface Pro X to manage the keyboard cover. Among other things, it provides information on the positioning (posture) of the cover (closed, laptop-style, detached, folded-back, ...), which can be used to implement an input device providing the SW_TABLET_MODE event. Similarly, the POS (posture information) subsystem provides such information on the Surface Laptop Studio, with the difference being that the keyboard is not detachable. As implementing the tablet-mode switch for both subsystems is largely similar, the driver proposed in this commit, in large, acts as a generic tablet mode switch driver framework for the Surface Aggregator Module. Specific implementations using this framework are provided for the KIP and POS subsystems, adding tablet-mode switch support to the aforementioned devices. A few more notes on the Surface Laptop Studio: A peculiarity of the Surface Laptop Studio is its "slate/tent" mode (symbolized: user> _/\). In this mode, the screen covers the keyboard but leaves the touchpad exposed. This is essentially a mode in-between tablet and laptop, and it is debatable whether tablet-mode should be enabled in this mode. We therefore let the user decide this via a module parameter. In particular, tablet-mode may bring up the on-screen touch keyboard more easily, which would be desirable in this mode. However, some user-space software currently also decides to disable keyboard and, more importantly, touchpad input, while the touchpad is still accessible in the "slate/tent" mode. Furthermore, this mode shares its identifier with "slate/flipped" mode where the screen is flipped 180° and the keyboard points away from the user (symbolized: user> /_). In this mode we would like to enable auto-rotation, something that user-space software may only do when tablet-mode is enabled. We therefore default to the slate-mode enabling the tablet-mode switch. Signed-off-by: Maximilian Luz Reported-by: kernel test robot --- .../sysfs-bus-surface_aggregator-tabletsw | 57 ++ MAINTAINERS | 6 + drivers/platform/surface/Kconfig | 23 + drivers/platform/surface/Makefile | 1 + .../surface/surface_aggregator_tabletsw.c | 533 ++++++++++++++++++ 5 files changed, 620 insertions(+) create mode 100644 Documentation/ABI/testing/sysfs-bus-surface_aggregator-tabletsw create mode 100644 drivers/platform/surface/surface_aggregator_tabletsw.c diff --git a/Documentation/ABI/testing/sysfs-bus-surface_aggregator-tabletsw b/Documentation/ABI/testing/sysfs-bus-surface_aggregator-tabletsw new file mode 100644 index 000000000000..74cd9d754e60 --- /dev/null +++ b/Documentation/ABI/testing/sysfs-bus-surface_aggregator-tabletsw @@ -0,0 +1,57 @@ +What: /sys/bus/surface_aggregator/devices/01:0e:01:00:01/state +Date: July 2022 +KernelVersion: 5.20 +Contact: Maximilian Luz +Description: + This attribute returns a string with the current type-cover + or device posture, as indicated by the embedded controller. + Currently returned posture states are: + + - "disconnected": The type-cover has been disconnected. + + - "closed": The type-cover has been folded closed and lies on + top of the display. + + - "laptop": The type-cover is open and in laptop-mode, i.e., + ready for normal use. + + - "folded-canvas": The type-cover has been folded back + part-ways, but does not lie flush with the back side of the + device. In general, this means that the kick-stand is used + and extended atop of the cover. + + - "folded-back": The type cover has been fully folded back and + lies flush with the back side of the device. + + - "": The current state is unknown to the driver, for + example due to newer as-of-yet unsupported hardware. + + New states may be introduced with new hardware. Users therefore + must not rely on this list of states being exhaustive and + gracefully handle unknown states. + +What: /sys/bus/surface_aggregator/devices/01:26:01:00:01/state +Date: July 2022 +KernelVersion: 5.20 +Contact: Maximilian Luz +Description: + This attribute returns a string with the current device posture, as indicated by the embedded controller. Currently + returned posture states are: + + - "closed": The lid of the device is closed. + + - "laptop": The lid of the device is opened and the device + operates as a normal laptop. + + - "slate": The screen covers the keyboard or has been flipped + back and the device operates mainly based on touch input. + + - "tablet": The device operates as tablet and exclusively + relies on touch input (or external peripherals). + + - "": The current state is unknown to the driver, for + example due to newer as-of-yet unsupported hardware. + + New states may be introduced with new hardware. Users therefore + must not rely on this list of states being exhaustive and + gracefully handle unknown states. diff --git a/MAINTAINERS b/MAINTAINERS index 2a34deb24594..c6d8c0c6bf6e 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -13176,6 +13176,12 @@ F: drivers/scsi/smartpqi/smartpqi*.[ch] F: include/linux/cciss*.h F: include/uapi/linux/cciss*.h +MICROSOFT SURFACE AGGREGATOR TABLET-MODE SWITCH +M: Maximilian Luz +L: platform-driver-x86@vger.kernel.org +S: Maintained +F: drivers/platform/surface/surface_aggregator_tablet_switch.c + MICROSOFT SURFACE BATTERY AND AC DRIVERS M: Maximilian Luz L: linux-pm@vger.kernel.org diff --git a/drivers/platform/surface/Kconfig b/drivers/platform/surface/Kconfig index eb79fbed8059..b152e930cc84 100644 --- a/drivers/platform/surface/Kconfig +++ b/drivers/platform/surface/Kconfig @@ -99,6 +99,29 @@ config SURFACE_AGGREGATOR_REGISTRY the respective client devices. Drivers for these devices still need to be selected via the other options. +config SURFACE_AGGREGATOR_TABLET_SWITCH + tristate "Surface Aggregator Generic Tablet-Mode Switch Driver" + depends on SURFACE_AGGREGATOR + depends on SURFACE_AGGREGATOR_BUS + depends on INPUT + help + Provides a tablet-mode switch input device on Microsoft Surface models + using the KIP subsystem for detachable keyboards (e.g. keyboard covers) + or the POS subsystem for device/screen posture changes. + + The KIP subsystem is used on newer Surface generations to handle + detachable input peripherals, specifically the keyboard cover (containing + keyboard and touchpad) on the Surface Pro 8 and Surface Pro X. The POS + subsystem is used for device posture change notifications on the Surface + Laptop Studio. This module provides a driver to let user-space know when + the device should be considered in tablet-mode due to the keyboard cover + being detached or folded back (essentially signaling when the keyboard is + not available for input). It does so by creating a tablet-mode switch + input device, sending the standard SW_TABLET_MODE event on mode change. + + Select M or Y here, if you want to provide tablet-mode switch input + events on the Surface Pro 8, Surface Pro X, and Surface Laptop Studio. + config SURFACE_DTX tristate "Surface DTX (Detachment System) Driver" depends on SURFACE_AGGREGATOR diff --git a/drivers/platform/surface/Makefile b/drivers/platform/surface/Makefile index 0fc9cd3e4dd9..18b27898543e 100644 --- a/drivers/platform/surface/Makefile +++ b/drivers/platform/surface/Makefile @@ -10,6 +10,7 @@ obj-$(CONFIG_SURFACE_ACPI_NOTIFY) += surface_acpi_notify.o obj-$(CONFIG_SURFACE_AGGREGATOR) += aggregator/ obj-$(CONFIG_SURFACE_AGGREGATOR_CDEV) += surface_aggregator_cdev.o obj-$(CONFIG_SURFACE_AGGREGATOR_REGISTRY) += surface_aggregator_registry.o +obj-$(CONFIG_SURFACE_AGGREGATOR_TABLET_SWITCH) += surface_aggregator_tabletsw.o obj-$(CONFIG_SURFACE_DTX) += surface_dtx.o obj-$(CONFIG_SURFACE_GPE) += surface_gpe.o obj-$(CONFIG_SURFACE_HOTPLUG) += surface_hotplug.o diff --git a/drivers/platform/surface/surface_aggregator_tabletsw.c b/drivers/platform/surface/surface_aggregator_tabletsw.c new file mode 100644 index 000000000000..596ca6c80681 --- /dev/null +++ b/drivers/platform/surface/surface_aggregator_tabletsw.c @@ -0,0 +1,533 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Surface System Aggregator Module (SSAM) tablet mode switch driver. + * + * Copyright (C) 2022 Maximilian Luz + */ + +#include +#include +#include +#include +#include +#include + +#include +#include + + +/* -- SSAM generic tablet switch driver framework. -------------------------- */ + +struct ssam_tablet_sw; + +struct ssam_tablet_sw_ops { + int (*get_state)(struct ssam_tablet_sw *sw, u32 *state); + const char *(*state_name)(struct ssam_tablet_sw *sw, u32 state); + bool (*state_is_tablet_mode)(struct ssam_tablet_sw *sw, u32 state); +}; + +struct ssam_tablet_sw { + struct ssam_device *sdev; + + u32 state; + struct work_struct update_work; + struct input_dev *mode_switch; + + struct ssam_tablet_sw_ops ops; + struct ssam_event_notifier notif; +}; + +struct ssam_tablet_sw_desc { + struct { + const char *name; + const char *phys; + } dev; + + struct { + u32 (*notify)(struct ssam_event_notifier *nf, const struct ssam_event *event); + int (*get_state)(struct ssam_tablet_sw *sw, u32 *state); + const char *(*state_name)(struct ssam_tablet_sw *sw, u32 state); + bool (*state_is_tablet_mode)(struct ssam_tablet_sw *sw, u32 state); + } ops; + + struct { + struct ssam_event_registry reg; + struct ssam_event_id id; + enum ssam_event_mask mask; + u8 flags; + } event; +}; + +static ssize_t state_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + struct ssam_tablet_sw *sw = dev_get_drvdata(dev); + const char *state = sw->ops.state_name(sw, sw->state); + + return sysfs_emit(buf, "%s\n", state); +} +static DEVICE_ATTR_RO(state); + +static struct attribute *ssam_tablet_sw_attrs[] = { + &dev_attr_state.attr, + NULL, +}; + +static const struct attribute_group ssam_tablet_sw_group = { + .attrs = ssam_tablet_sw_attrs, +}; + +static void ssam_tablet_sw_update_workfn(struct work_struct *work) +{ + struct ssam_tablet_sw *sw = container_of(work, struct ssam_tablet_sw, update_work); + int tablet, status; + u32 state; + + status = sw->ops.get_state(sw, &state); + if (status) + return; + + if (sw->state == state) + return; + sw->state = state; + + /* Send SW_TABLET_MODE event. */ + tablet = sw->ops.state_is_tablet_mode(sw, state); + input_report_switch(sw->mode_switch, SW_TABLET_MODE, tablet); + input_sync(sw->mode_switch); +} + +static int __maybe_unused ssam_tablet_sw_resume(struct device *dev) +{ + struct ssam_tablet_sw *sw = dev_get_drvdata(dev); + + schedule_work(&sw->update_work); + return 0; +} +static SIMPLE_DEV_PM_OPS(ssam_tablet_sw_pm_ops, NULL, ssam_tablet_sw_resume); + +static int ssam_tablet_sw_probe(struct ssam_device *sdev) +{ + const struct ssam_tablet_sw_desc *desc; + struct ssam_tablet_sw *sw; + int tablet, status; + + desc = ssam_device_get_match_data(sdev); + if (!desc) { + WARN(1, "no driver match data specified"); + return -EINVAL; + } + + sw = devm_kzalloc(&sdev->dev, sizeof(*sw), GFP_KERNEL); + if (!sw) + return -ENOMEM; + + sw->sdev = sdev; + + sw->ops.get_state = desc->ops.get_state; + sw->ops.state_name = desc->ops.state_name; + sw->ops.state_is_tablet_mode = desc->ops.state_is_tablet_mode; + + INIT_WORK(&sw->update_work, ssam_tablet_sw_update_workfn); + + ssam_device_set_drvdata(sdev, sw); + + /* Get initial state. */ + status = sw->ops.get_state(sw, &sw->state); + if (status) + return status; + + /* Set up tablet mode switch. */ + sw->mode_switch = devm_input_allocate_device(&sdev->dev); + if (!sw->mode_switch) + return -ENOMEM; + + sw->mode_switch->name = desc->dev.name; + sw->mode_switch->phys = desc->dev.phys; + sw->mode_switch->id.bustype = BUS_HOST; + sw->mode_switch->dev.parent = &sdev->dev; + + tablet = sw->ops.state_is_tablet_mode(sw, sw->state); + input_set_capability(sw->mode_switch, EV_SW, SW_TABLET_MODE); + input_report_switch(sw->mode_switch, SW_TABLET_MODE, tablet); + + status = input_register_device(sw->mode_switch); + if (status) + return status; + + /* Set up notifier. */ + sw->notif.base.priority = 0; + sw->notif.base.fn = desc->ops.notify; + sw->notif.event.reg = desc->event.reg; + sw->notif.event.id = desc->event.id; + sw->notif.event.mask = desc->event.mask; + sw->notif.event.flags = SSAM_EVENT_SEQUENCED; + + status = ssam_device_notifier_register(sdev, &sw->notif); + if (status) + return status; + + status = sysfs_create_group(&sdev->dev.kobj, &ssam_tablet_sw_group); + if (status) + goto err; + + /* We might have missed events during setup, so check again. */ + schedule_work(&sw->update_work); + return 0; + +err: + ssam_device_notifier_unregister(sdev, &sw->notif); + cancel_work_sync(&sw->update_work); + return status; +} + +static void ssam_tablet_sw_remove(struct ssam_device *sdev) +{ + struct ssam_tablet_sw *sw = ssam_device_get_drvdata(sdev); + + sysfs_remove_group(&sdev->dev.kobj, &ssam_tablet_sw_group); + + ssam_device_notifier_unregister(sdev, &sw->notif); + cancel_work_sync(&sw->update_work); +} + + +/* -- SSAM KIP tablet switch implementation. -------------------------------- */ + +#define SSAM_EVENT_KIP_CID_COVER_STATE_CHANGED 0x1d + +enum ssam_kip_cover_state { + SSAM_KIP_COVER_STATE_DISCONNECTED = 0x01, + SSAM_KIP_COVER_STATE_CLOSED = 0x02, + SSAM_KIP_COVER_STATE_LAPTOP = 0x03, + SSAM_KIP_COVER_STATE_FOLDED_CANVAS = 0x04, + SSAM_KIP_COVER_STATE_FOLDED_BACK = 0x05, +}; + +static const char *ssam_kip_cover_state_name(struct ssam_tablet_sw *sw, u32 state) +{ + switch (state) { + case SSAM_KIP_COVER_STATE_DISCONNECTED: + return "disconnected"; + + case SSAM_KIP_COVER_STATE_CLOSED: + return "closed"; + + case SSAM_KIP_COVER_STATE_LAPTOP: + return "laptop"; + + case SSAM_KIP_COVER_STATE_FOLDED_CANVAS: + return "folded-canvas"; + + case SSAM_KIP_COVER_STATE_FOLDED_BACK: + return "folded-back"; + + default: + dev_warn(&sw->sdev->dev, "unknown KIP cover state: %u\n", state); + return ""; + } +} + +static bool ssam_kip_cover_state_is_tablet_mode(struct ssam_tablet_sw *sw, u32 state) +{ + switch (state) { + case SSAM_KIP_COVER_STATE_DISCONNECTED: + case SSAM_KIP_COVER_STATE_FOLDED_CANVAS: + case SSAM_KIP_COVER_STATE_FOLDED_BACK: + return true; + + case SSAM_KIP_COVER_STATE_CLOSED: + case SSAM_KIP_COVER_STATE_LAPTOP: + return false; + + default: + dev_warn(&sw->sdev->dev, "unknown KIP cover state: %d\n", sw->state); + return true; + } +} + +SSAM_DEFINE_SYNC_REQUEST_R(__ssam_kip_get_cover_state, u8, { + .target_category = SSAM_SSH_TC_KIP, + .target_id = 0x01, + .command_id = 0x1d, + .instance_id = 0x00, +}); + +static int ssam_kip_get_cover_state(struct ssam_tablet_sw *sw, u32 *state) +{ + int status; + u8 raw; + + status = ssam_retry(__ssam_kip_get_cover_state, sw->sdev->ctrl, &raw); + if (status < 0) { + dev_err(&sw->sdev->dev, "failed to query KIP lid state: %d\n", status); + return status; + } + + *state = raw; + return 0; +} + +static u32 ssam_kip_sw_notif(struct ssam_event_notifier *nf, const struct ssam_event *event) +{ + struct ssam_tablet_sw *sw = container_of(nf, struct ssam_tablet_sw, notif); + + if (event->command_id != SSAM_EVENT_KIP_CID_COVER_STATE_CHANGED) + return 0; /* Return "unhandled". */ + + if (event->length < 1) + dev_warn(&sw->sdev->dev, "unexpected payload size: %u\n", event->length); + + schedule_work(&sw->update_work); + return SSAM_NOTIF_HANDLED; +} + +static const struct ssam_tablet_sw_desc ssam_kip_sw_desc = { + .dev = { + .name = "Microsoft Surface KIP Tablet Mode Switch", + .phys = "ssam/01:0e:01:00:01/input0", + }, + .ops = { + .notify = ssam_kip_sw_notif, + .get_state = ssam_kip_get_cover_state, + .state_name = ssam_kip_cover_state_name, + .state_is_tablet_mode = ssam_kip_cover_state_is_tablet_mode, + }, + .event = { + .reg = SSAM_EVENT_REGISTRY_SAM, + .id = { + .target_category = SSAM_SSH_TC_KIP, + .instance = 0, + }, + .mask = SSAM_EVENT_MASK_TARGET, + }, +}; + + +/* -- SSAM POS tablet switch implementation. -------------------------------- */ + +static bool tablet_mode_in_slate_state = true; +module_param(tablet_mode_in_slate_state, bool, 0644); +MODULE_PARM_DESC(tablet_mode_in_slate_state, "Enable tablet mode in slate device posture, default is 'true'"); + +#define SSAM_EVENT_POS_CID_POSTURE_CHANGED 0x03 +#define SSAM_POS_MAX_SOURCES 4 + +enum ssam_pos_state { + SSAM_POS_POSTURE_LID_CLOSED = 0x00, + SSAM_POS_POSTURE_LAPTOP = 0x01, + SSAM_POS_POSTURE_SLATE = 0x02, + SSAM_POS_POSTURE_TABLET = 0x03, +}; + +struct ssam_sources_list { + __le32 count; + __le32 id[SSAM_POS_MAX_SOURCES]; +} __packed; + +static const char *ssam_pos_state_name(struct ssam_tablet_sw *sw, u32 state) +{ + switch (state) { + case SSAM_POS_POSTURE_LID_CLOSED: + return "closed"; + + case SSAM_POS_POSTURE_LAPTOP: + return "laptop"; + + case SSAM_POS_POSTURE_SLATE: + return "slate"; + + case SSAM_POS_POSTURE_TABLET: + return "tablet"; + + default: + dev_warn(&sw->sdev->dev, "unknown device posture: %u\n", state); + return ""; + } +} + +static bool ssam_pos_state_is_tablet_mode(struct ssam_tablet_sw *sw, u32 state) +{ + switch (state) { + case SSAM_POS_POSTURE_LAPTOP: + case SSAM_POS_POSTURE_LID_CLOSED: + return false; + + case SSAM_POS_POSTURE_SLATE: + return tablet_mode_in_slate_state; + + case SSAM_POS_POSTURE_TABLET: + return true; + + default: + dev_warn(&sw->sdev->dev, "unknown device posture: %u\n", state); + return true; + } +} + +static int ssam_pos_get_sources_list(struct ssam_tablet_sw *sw, struct ssam_sources_list *sources) +{ + struct ssam_request rqst; + struct ssam_response rsp; + int status; + + rqst.target_category = SSAM_SSH_TC_POS; + rqst.target_id = 0x01; + rqst.command_id = 0x01; + rqst.instance_id = 0x00; + rqst.flags = SSAM_REQUEST_HAS_RESPONSE; + rqst.length = 0; + rqst.payload = NULL; + + rsp.capacity = sizeof(*sources); + rsp.length = 0; + rsp.pointer = (u8 *)sources; + + status = ssam_retry(ssam_request_sync_onstack, sw->sdev->ctrl, &rqst, &rsp, 0); + if (status) + return status; + + /* We need at least the 'sources->count' field. */ + if (rsp.length < sizeof(__le32)) { + dev_err(&sw->sdev->dev, "received source list response is too small\n"); + return -EPROTO; + } + + /* Make sure 'sources->count' matches with the response length. */ + if (get_unaligned_le32(&sources->count) * sizeof(__le32) + sizeof(__le32) != rsp.length) { + dev_err(&sw->sdev->dev, "mismatch between number of sources and response size\n"); + return -EPROTO; + } + + return 0; +} + +static int ssam_pos_get_source(struct ssam_tablet_sw *sw, u32 *source_id) +{ + struct ssam_sources_list sources = {}; + int status; + + status = ssam_pos_get_sources_list(sw, &sources); + if (status) + return status; + + if (sources.count == 0) { + dev_err(&sw->sdev->dev, "no posture sources found\n"); + return -ENODEV; + } + + /* + * We currently don't know what to do with more than one posture + * source. At the moment, only one source seems to be used/provided. + * The WARN_ON() here should hopefully let us know quickly once there + * is a device that provides multiple sources, at which point we can + * then try to figure out how to handle them. + */ + WARN_ON(sources.count > 1); + + *source_id = get_unaligned_le32(&sources.id[0]); + return 0; +} + +SSAM_DEFINE_SYNC_REQUEST_WR(__ssam_pos_get_posture_for_source, __le32, __le32, { + .target_category = SSAM_SSH_TC_POS, + .target_id = 0x01, + .command_id = 0x02, + .instance_id = 0x00, +}); + +static int ssam_pos_get_posture_for_source(struct ssam_tablet_sw *sw, u32 source_id, u32 *posture) +{ + __le32 source_le = cpu_to_le32(source_id); + __le32 rspval_le = 0; + int status; + + status = ssam_retry(__ssam_pos_get_posture_for_source, sw->sdev->ctrl, + &source_le, &rspval_le); + if (status) + return status; + + *posture = le32_to_cpu(rspval_le); + return 0; +} + +static int ssam_pos_get_posture(struct ssam_tablet_sw *sw, u32 *state) +{ + u32 source_id; + int status; + + status = ssam_pos_get_source(sw, &source_id); + if (status) { + dev_err(&sw->sdev->dev, "failed to get posture source ID: %d\n", status); + return status; + } + + status = ssam_pos_get_posture_for_source(sw, source_id, state); + if (status) { + dev_err(&sw->sdev->dev, "failed to get posture value for source %u: %d\n", + source_id, status); + return status; + } + + return 0; +} + +static u32 ssam_pos_sw_notif(struct ssam_event_notifier *nf, const struct ssam_event *event) +{ + struct ssam_tablet_sw *sw = container_of(nf, struct ssam_tablet_sw, notif); + + if (event->command_id != SSAM_EVENT_POS_CID_POSTURE_CHANGED) + return 0; /* Return "unhandled". */ + + if (event->length != sizeof(__le32) * 3) + dev_warn(&sw->sdev->dev, "unexpected payload size: %u\n", event->length); + + schedule_work(&sw->update_work); + return SSAM_NOTIF_HANDLED; +} + +static const struct ssam_tablet_sw_desc ssam_pos_sw_desc = { + .dev = { + .name = "Microsoft Surface POS Tablet Mode Switch", + .phys = "ssam/01:26:01:00:01/input0", + }, + .ops = { + .notify = ssam_pos_sw_notif, + .get_state = ssam_pos_get_posture, + .state_name = ssam_pos_state_name, + .state_is_tablet_mode = ssam_pos_state_is_tablet_mode, + }, + .event = { + .reg = SSAM_EVENT_REGISTRY_SAM, + .id = { + .target_category = SSAM_SSH_TC_POS, + .instance = 0, + }, + .mask = SSAM_EVENT_MASK_TARGET, + }, +}; + + +/* -- Driver registration. -------------------------------------------------- */ + +static const struct ssam_device_id ssam_tablet_sw_match[] = { + { SSAM_SDEV(KIP, 0x01, 0x00, 0x01), (unsigned long)&ssam_kip_sw_desc }, + { SSAM_SDEV(POS, 0x01, 0x00, 0x01), (unsigned long)&ssam_pos_sw_desc }, + { }, +}; +MODULE_DEVICE_TABLE(ssam, ssam_tablet_sw_match); + +static struct ssam_device_driver ssam_tablet_sw_driver = { + .probe = ssam_tablet_sw_probe, + .remove = ssam_tablet_sw_remove, + .match_table = ssam_tablet_sw_match, + .driver = { + .name = "surface_aggregator_tablet_mode_switch", + .probe_type = PROBE_PREFER_ASYNCHRONOUS, + .pm = &ssam_tablet_sw_pm_ops, + }, +}; +module_ssam_device_driver(ssam_tablet_sw_driver); + +MODULE_AUTHOR("Maximilian Luz "); +MODULE_DESCRIPTION("Tablet mode switch driver for Surface devices using the Surface Aggregator Module"); +MODULE_LICENSE("GPL"); From patchwork Fri Jun 24 18:36:41 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Maximilian Luz X-Patchwork-Id: 12895004 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id F2542C433EF for ; Fri, 24 Jun 2022 18:37:10 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231653AbiFXShJ (ORCPT ); Fri, 24 Jun 2022 14:37:09 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:35884 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231394AbiFXShI (ORCPT ); Fri, 24 Jun 2022 14:37:08 -0400 Received: from mail-ej1-x62c.google.com (mail-ej1-x62c.google.com [IPv6:2a00:1450:4864:20::62c]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 5CD9781258; Fri, 24 Jun 2022 11:37:07 -0700 (PDT) Received: by mail-ej1-x62c.google.com with SMTP id cw10so6427434ejb.3; Fri, 24 Jun 2022 11:37:07 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=f6qkeHUNFH4QmeQBj0bNc7f9zKmHQ5igPCiK5zgxrT8=; b=h/hkqjcnhoGz0vbAHb9p1jUooWrA/hO0BNtoz3If5Rt0ojAia+aSiYGe0hxG47PM+l 72N29VmdrpdyZSxecqBMnU8W5lGIIJzF+L8cGn+CeWJhkp8yBvK7Vct4ng+Tf2tBPT7l 5LiS0DZDOHYsHwiRtT2XwIuoiD9ei8KX92AvHpUjOhVoc3ovPb5H6cREBNtSN36ve3GN CLrBUdB8LPY8wJPD7mdue26qit7n6Td4WQesrtbMV9Jbb9mP6VqK9ke/uZm37lOSHZnW GhHTJMmk3aPH8+SivXBNQv37bEpyGOSWib8ExYci6huH6xN5j1teaBKe1reKOyfa4J3i Q6Eg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=f6qkeHUNFH4QmeQBj0bNc7f9zKmHQ5igPCiK5zgxrT8=; b=U+yNBNfQ1jIX9yMdp24bQYFVx2097ymCIGjcUsqo3tVd3tKJATtPh1JT9osNd3KD5h M6t+uNFRFLLxWa5TWAgj2W8+DoBy9tLNyAaGhlYyZJZpuDzAnJz40Zp6RlCm9YXjllsh adtBtFEnoaes5VKFFnIyzjkrSjYJWD6ObA51BTIiUpVIS7dSSfOxZXhhbHOaQv/vol2Y ccUPjoeu0A/qaEJ1QYJOcVtvMuzblh5wmSpNLTPLvpp/2SZyKOyLlks2Pe8l/Oe/I8CV 1ppiEjcrKef6MI85vLM3soGS+LziD+WUxknLXwQdxjjsH+niZkOiyHmr6jcXvclHaWn8 tE2A== X-Gm-Message-State: AJIora/SlZV89F3OkwH69PKPVy1ufovfZvJ0JbmsIrxtmOJJcefsQHDQ f5wOjTzNBaAFFtKcJ19GmVY= X-Google-Smtp-Source: AGRyM1tVgWUkN1tNjUIpIuEVVhmLL12YLP8dLIREXKumlgpSMkOWKDAOyqyr5d22YIuSfKM9EX6WNg== X-Received: by 2002:a17:907:da7:b0:711:6c6d:c6d with SMTP id go39-20020a1709070da700b007116c6d0c6dmr399275ejc.276.1656095825905; Fri, 24 Jun 2022 11:37:05 -0700 (PDT) Received: from xws.localdomain ([37.120.217.162]) by smtp.gmail.com with ESMTPSA id jw12-20020a170906e94c00b00722e8827c53sm1493822ejb.208.2022.06.24.11.37.04 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 24 Jun 2022 11:37:05 -0700 (PDT) From: Maximilian Luz To: Hans de Goede Cc: Mark Gross , platform-driver-x86@vger.kernel.org, linux-kernel@vger.kernel.org, Maximilian Luz Subject: [PATCH 3/4] platform/surface: aggregator_registry: Add support for tablet mode switch on Surface Pro 8 Date: Fri, 24 Jun 2022 20:36:41 +0200 Message-Id: <20220624183642.910893-4-luzmaximilian@gmail.com> X-Mailer: git-send-email 2.36.1 In-Reply-To: <20220624183642.910893-1-luzmaximilian@gmail.com> References: <20220624183642.910893-1-luzmaximilian@gmail.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: platform-driver-x86@vger.kernel.org Add a KIP subsystem tablet-mode switch device for the Surface Pro 8. The respective driver for this device provides SW_TABLET_MODE input events for user-space based on the state of the keyboard cover (e.g. detached, folded-back, normal/laptop mode). Signed-off-by: Maximilian Luz --- drivers/platform/surface/surface_aggregator_registry.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/drivers/platform/surface/surface_aggregator_registry.c b/drivers/platform/surface/surface_aggregator_registry.c index bf3303f1aa71..8f249df673a4 100644 --- a/drivers/platform/surface/surface_aggregator_registry.c +++ b/drivers/platform/surface/surface_aggregator_registry.c @@ -77,6 +77,12 @@ static const struct software_node ssam_node_tmp_pprof = { .parent = &ssam_node_root, }; +/* Tablet-mode switch via KIP subsystem. */ +static const struct software_node ssam_node_kip_tablet_switch = { + .name = "ssam:01:0e:01:00:01", + .parent = &ssam_node_root, +}; + /* DTX / detachment-system device (Surface Book 3). */ static const struct software_node ssam_node_bas_dtx = { .name = "ssam:01:11:01:00:00", @@ -264,11 +270,11 @@ static const struct software_node *ssam_node_group_sp8[] = { &ssam_node_bat_ac, &ssam_node_bat_main, &ssam_node_tmp_pprof, + &ssam_node_kip_tablet_switch, &ssam_node_hid_kip_keyboard, &ssam_node_hid_kip_penstash, &ssam_node_hid_kip_touchpad, &ssam_node_hid_kip_iid5, - /* TODO: Add support for tablet mode switch. */ NULL, }; From patchwork Fri Jun 24 18:36:42 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Maximilian Luz X-Patchwork-Id: 12895006 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 8148CC433EF for ; Fri, 24 Jun 2022 18:37:13 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231636AbiFXShM (ORCPT ); Fri, 24 Jun 2022 14:37:12 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:35910 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231569AbiFXShI (ORCPT ); Fri, 24 Jun 2022 14:37:08 -0400 Received: from mail-ej1-x62e.google.com (mail-ej1-x62e.google.com [IPv6:2a00:1450:4864:20::62e]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 1295B8126C; Fri, 24 Jun 2022 11:37:08 -0700 (PDT) Received: by mail-ej1-x62e.google.com with SMTP id ge10so6385469ejb.7; Fri, 24 Jun 2022 11:37:07 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=Wk5pMy7Zd97VX3BKR5VEk1jaORfYL6tDVYZN+cZYFto=; b=RRMHywXN0k5cnqLRZ1tqLahM6ZdigXE5VNCurGhJPbwCK6VI0UaIwBPmznefCYqhUI GkTxDznIPnPaZq5Wf8w9ESY2dzStS/Kk/Gor9ZgXBYskw+YXz2KLDkWRvV9boTegcIFx gsm2maO/0TEmcjAlaRTBdJ201yVUMOovz0OlAJ8H5kwfo90kG7+FRlM6scCWk/EqGefI IwlC+aSQGOcOGXGh5T2BPNK6sMkgrrzCwMgiiQbIv+lzY0gWR2cM4gG3NM9wKg4yxQ/t K3jQTnI41UfKyefGLXg9vZmC8Bzo/Wjd8N0qdFrosEE4ZjXd2IrGrQrA/bPDVfyThXFI eIHA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=Wk5pMy7Zd97VX3BKR5VEk1jaORfYL6tDVYZN+cZYFto=; b=m7dZK4TNgHP0dOpU0XVE9OhwH5TCqSLp4Jq34i2lfEex6lXolpJoXMktMrYCq/7qFT jqLLxR4KQorRv8KTCKJWR/dqI2C2o0qJEeG+0HhpKyLEg6tgL/8peHkEPGqFQiFTVYw9 Jrb4C+a141qil631NxkqO27LguuR4q2h0cCcvilpbMSMV4U4nFfeokbZgezjWq6CvpE6 V7+ChjoDnVLlZXBW1qFNUZa3IVbfWOHRZoxyREAlLxvvdDqLYW0v/IhZr0i3DDcs2O6V bsGmeA5jmmnfof7lbn5YH9oJ1h8BX2hvAbF1TFsbJ72MDA7pzMSr16xnYrWdWgikMMWp YqTg== X-Gm-Message-State: AJIora/ipMq0I0kALdNX/lOpsc3vrREgeiXLs7h9/44RliZcfWVm3/3s NkhWEcC5wCar10QuMwnbqxg= X-Google-Smtp-Source: AGRyM1tjEUoazywNMjLpdPgFsdSAat4CmmBmty2MepRR97HbIFsh643SXO+IoeJf0NpDI5i9snAF6g== X-Received: by 2002:a17:907:6d0c:b0:726:32e5:1736 with SMTP id sa12-20020a1709076d0c00b0072632e51736mr370371ejc.596.1656095827578; Fri, 24 Jun 2022 11:37:07 -0700 (PDT) Received: from xws.localdomain ([37.120.217.162]) by smtp.gmail.com with ESMTPSA id jw12-20020a170906e94c00b00722e8827c53sm1493822ejb.208.2022.06.24.11.37.06 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 24 Jun 2022 11:37:07 -0700 (PDT) From: Maximilian Luz To: Hans de Goede Cc: Mark Gross , platform-driver-x86@vger.kernel.org, linux-kernel@vger.kernel.org, Maximilian Luz Subject: [PATCH 4/4] platform/surface: aggregator_registry: Add support for tablet mode switch on Surface Laptop Studio Date: Fri, 24 Jun 2022 20:36:42 +0200 Message-Id: <20220624183642.910893-5-luzmaximilian@gmail.com> X-Mailer: git-send-email 2.36.1 In-Reply-To: <20220624183642.910893-1-luzmaximilian@gmail.com> References: <20220624183642.910893-1-luzmaximilian@gmail.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: platform-driver-x86@vger.kernel.org Add a POS subsystem tablet-mode switch device for the Surface Laptop Studio. The respective driver for this device provides SW_TABLET_MODE input events for user-space based on the posture of the screen. Signed-off-by: Maximilian Luz --- drivers/platform/surface/surface_aggregator_registry.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/platform/surface/surface_aggregator_registry.c b/drivers/platform/surface/surface_aggregator_registry.c index 8f249df673a4..f1c5905f1c16 100644 --- a/drivers/platform/surface/surface_aggregator_registry.c +++ b/drivers/platform/surface/surface_aggregator_registry.c @@ -191,6 +191,12 @@ static const struct software_node ssam_node_hid_kip_iid5 = { .parent = &ssam_node_hub_kip, }; +/* Tablet-mode switch via POS subsystem. */ +static const struct software_node ssam_node_pos_tablet_switch = { + .name = "ssam:01:26:01:00:01", + .parent = &ssam_node_root, +}; + /* * Devices for 5th- and 6th-generations models: * - Surface Book 2, @@ -237,6 +243,7 @@ static const struct software_node *ssam_node_group_sls[] = { &ssam_node_bat_ac, &ssam_node_bat_main, &ssam_node_tmp_pprof, + &ssam_node_pos_tablet_switch, &ssam_node_hid_tid1_keyboard, &ssam_node_hid_tid1_penstash, &ssam_node_hid_tid1_touchpad,