]> Git Repo - J-linux.git/commitdiff
HID: amd_sfh: Add a new interface for exporting HPD data
authorBasavaraj Natikar <[email protected]>
Wed, 20 Dec 2023 07:00:41 +0000 (12:30 +0530)
committerJiri Kosina <[email protected]>
Thu, 4 Jan 2024 14:19:17 +0000 (15:19 +0100)
AMDSFH has information about the User presence information via the Human
Presence Detection (HPD) sensor which is part of the AMD sensor fusion hub.

Add a new interface to export this information, where other drivers like
PMF can use this information to enhance user experiences.

Link: https://lore.kernel.org/all/[email protected]/
Co-developed-by: Shyam Sundar S K <[email protected]>
Signed-off-by: Shyam Sundar S K <[email protected]>
Signed-off-by: Basavaraj Natikar <[email protected]>
Signed-off-by: Jiri Kosina <[email protected]>
drivers/hid/amd-sfh-hid/amd_sfh_common.h
drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_init.c
drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_interface.c
drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_interface.h
include/linux/amd-pmf-io.h [new file with mode: 0644]

index 2643bb14fee27c8cd62b04b6b07ff5c839d0c834..cd57037bf217415ad4912161527271a75177cef7 100644 (file)
@@ -37,6 +37,10 @@ struct amd_mp2_sensor_info {
        dma_addr_t dma_address;
 };
 
+struct sfh_dev_status {
+       bool is_hpd_present;
+};
+
 struct amd_mp2_dev {
        struct pci_dev *pdev;
        struct amdtp_cl_data *cl_data;
@@ -47,6 +51,7 @@ struct amd_mp2_dev {
        struct amd_input_data in_data;
        /* mp2 active control status */
        u32 mp2_acs;
+       struct sfh_dev_status dev_en;
 };
 
 struct amd_mp2_ops {
index e9c6413af24a079959f693db36f760fed1a77950..0351b0fd394a98593d9410a297315fb882fc53e1 100644 (file)
@@ -73,6 +73,12 @@ static int amd_sfh_hid_client_deinit(struct amd_mp2_dev *privdata)
        int i, status;
 
        for (i = 0; i < cl_data->num_hid_devices; i++) {
+               switch (cl_data->sensor_idx[i]) {
+               case HPD_IDX:
+                       privdata->dev_en.is_hpd_present = false;
+                       break;
+               }
+
                if (cl_data->sensor_sts[i] == SENSOR_ENABLED) {
                        privdata->mp2_ops->stop(privdata, cl_data->sensor_idx[i]);
                        status = amd_sfh_wait_for_response
@@ -178,6 +184,11 @@ static int amd_sfh1_1_hid_client_init(struct amd_mp2_dev *privdata)
                        rc = amdtp_hid_probe(i, cl_data);
                        if (rc)
                                goto cleanup;
+                       switch (cl_data->sensor_idx[i]) {
+                       case HPD_IDX:
+                               privdata->dev_en.is_hpd_present = true;
+                               break;
+                       }
                }
                dev_dbg(dev, "sid 0x%x (%s) status 0x%x\n",
                        cl_data->sensor_idx[i], get_sensor_name(cl_data->sensor_idx[i]),
@@ -259,6 +270,7 @@ static void amd_mp2_pci_remove(void *privdata)
 {
        struct amd_mp2_dev *mp2 = privdata;
 
+       sfh_deinit_emp2();
        amd_sfh_hid_client_deinit(privdata);
        mp2->mp2_ops->stop_all(mp2);
        pci_intx(mp2->pdev, false);
@@ -311,12 +323,14 @@ int amd_sfh1_1_init(struct amd_mp2_dev *mp2)
 
        rc = amd_sfh_irq_init(mp2);
        if (rc) {
+               sfh_deinit_emp2();
                dev_err(dev, "amd_sfh_irq_init failed\n");
                return rc;
        }
 
        rc = amd_sfh1_1_hid_client_init(mp2);
        if (rc) {
+               sfh_deinit_emp2();
                dev_err(dev, "amd_sfh1_1_hid_client_init failed\n");
                return rc;
        }
index 4f81ef2d4f56ea7685ef04c7259a8509e21a16a2..197b828fc6a0bab81928ae3edd0c477c33cdb608 100644 (file)
@@ -7,11 +7,14 @@
  *
  * Author: Basavaraj Natikar <[email protected]>
  */
+#include <linux/amd-pmf-io.h>
 #include <linux/io-64-nonatomic-lo-hi.h>
 #include <linux/iopoll.h>
 
 #include "amd_sfh_interface.h"
 
+static struct amd_mp2_dev *emp2;
+
 static int amd_sfh_wait_response(struct amd_mp2_dev *mp2, u8 sid, u32 cmd_id)
 {
        struct sfh_cmd_response cmd_resp;
@@ -73,7 +76,41 @@ static struct amd_mp2_ops amd_sfh_ops = {
        .response = amd_sfh_wait_response,
 };
 
+void sfh_deinit_emp2(void)
+{
+       emp2 = NULL;
+}
+
 void sfh_interface_init(struct amd_mp2_dev *mp2)
 {
        mp2->mp2_ops = &amd_sfh_ops;
+       emp2 = mp2;
+}
+
+static int amd_sfh_hpd_info(u8 *user_present)
+{
+       struct hpd_status hpdstatus;
+
+       if (!user_present)
+               return -EINVAL;
+
+       if (!emp2 || !emp2->dev_en.is_hpd_present)
+               return -ENODEV;
+
+       hpdstatus.val = readl(emp2->mmio + AMD_C2P_MSG(4));
+       *user_present = hpdstatus.shpd.presence;
+
+       return 0;
+}
+
+int amd_get_sfh_info(struct amd_sfh_info *sfh_info, enum sfh_message_type op)
+{
+       if (sfh_info) {
+               switch (op) {
+               case MT_HPD:
+                       return amd_sfh_hpd_info(&sfh_info->user_present);
+               }
+       }
+       return -EINVAL;
 }
+EXPORT_SYMBOL_GPL(amd_get_sfh_info);
index 75267b0fec707a09f483e5d2f6d43f02312356a8..2c211d28764da594aaccc86ba5f9d650d6766230 100644 (file)
@@ -165,6 +165,7 @@ struct hpd_status {
 };
 
 void sfh_interface_init(struct amd_mp2_dev *mp2);
+void sfh_deinit_emp2(void);
 void amd_sfh1_1_set_desc_ops(struct amd_mp2_ops *mp2_ops);
 int amd_sfh_float_to_int(u32 flt32_val);
 #endif
diff --git a/include/linux/amd-pmf-io.h b/include/linux/amd-pmf-io.h
new file mode 100644 (file)
index 0000000..5b6d29d
--- /dev/null
@@ -0,0 +1,46 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * AMD Platform Management Framework Interface
+ *
+ * Copyright (c) 2023, Advanced Micro Devices, Inc.
+ * All Rights Reserved.
+ *
+ * Authors: Shyam Sundar S K <[email protected]>
+ *          Basavaraj Natikar <[email protected]>
+ */
+
+#ifndef AMD_PMF_IO_H
+#define AMD_PMF_IO_H
+
+#include <linux/types.h>
+
+/**
+ * enum sfh_message_type - Query the SFH message type
+ * @MT_HPD: Message ID to know the Human presence info from MP2 FW
+ */
+enum sfh_message_type {
+       MT_HPD,
+};
+
+/**
+ * enum sfh_hpd_info - Query the Human presence information
+ * @SFH_NOT_DETECTED: Check the HPD connection information from MP2 FW
+ * @SFH_USER_PRESENT: Check if the user is present from HPD sensor
+ * @SFH_USER_AWAY: Check if the user is away from HPD sensor
+ */
+enum sfh_hpd_info {
+       SFH_NOT_DETECTED,
+       SFH_USER_PRESENT,
+       SFH_USER_AWAY,
+};
+
+/**
+ * struct amd_sfh_info - get HPD sensor info from MP2 FW
+ * @user_present: Populates the user presence information
+ */
+struct amd_sfh_info {
+       u8 user_present;
+};
+
+int amd_get_sfh_info(struct amd_sfh_info *sfh_info, enum sfh_message_type op);
+#endif
This page took 0.088574 seconds and 4 git commands to generate.