HID: amd_sfh: Add support for PM suspend and resume
authorBasavaraj Natikar <Basavaraj.Natikar@amd.com>
Mon, 2 Aug 2021 14:03:40 +0000 (19:33 +0530)
committerJiri Kosina <jkosina@suse.cz>
Fri, 20 Aug 2021 12:48:49 +0000 (14:48 +0200)
Add support for power management routines.

Reviewed-by: Shyam Sundar S K <Shyam-sundar.S-k@amd.com>
Signed-off-by: Basavaraj Natikar <Basavaraj.Natikar@amd.com>
Signed-off-by: Jiri Kosina <jkosina@suse.cz>
drivers/hid/amd-sfh-hid/amd_sfh_client.c
drivers/hid/amd-sfh-hid/amd_sfh_pcie.c
drivers/hid/amd-sfh-hid/amd_sfh_pcie.h

index 4982ccf..050df79 100644 (file)
@@ -17,7 +17,6 @@
 #include "amd_sfh_pcie.h"
 #include "amd_sfh_hid.h"
 
-#define AMD_SFH_IDLE_LOOP      200
 
 struct request_list {
        struct hid_device *hid;
index eff61e7..7eb5971 100644 (file)
@@ -264,6 +264,54 @@ static int amd_mp2_pci_probe(struct pci_dev *pdev, const struct pci_device_id *i
        return amd_sfh_hid_client_init(privdata);
 }
 
+static int __maybe_unused amd_mp2_pci_resume(struct device *dev)
+{
+       struct pci_dev *pdev = to_pci_dev(dev);
+       struct amd_mp2_dev *mp2 = pci_get_drvdata(pdev);
+       struct amdtp_cl_data *cl_data = mp2->cl_data;
+       struct amd_mp2_sensor_info info;
+       int i, status;
+
+       for (i = 0; i < cl_data->num_hid_devices; i++) {
+               if (cl_data->sensor_sts[i] == SENSOR_DISABLED) {
+                       info.period = AMD_SFH_IDLE_LOOP;
+                       info.sensor_idx = cl_data->sensor_idx[i];
+                       info.dma_address = cl_data->sensor_dma_addr[i];
+                       mp2->mp2_ops->start(mp2, info);
+                       status = amd_sfh_wait_for_response
+                                       (mp2, cl_data->sensor_idx[i], SENSOR_ENABLED);
+                       if (status == SENSOR_ENABLED)
+                               cl_data->sensor_sts[i] = SENSOR_ENABLED;
+               }
+       }
+
+       return 0;
+}
+
+static int __maybe_unused amd_mp2_pci_suspend(struct device *dev)
+{
+       struct pci_dev *pdev = to_pci_dev(dev);
+       struct amd_mp2_dev *mp2 = pci_get_drvdata(pdev);
+       struct amdtp_cl_data *cl_data = mp2->cl_data;
+       int i, status;
+
+       for (i = 0; i < cl_data->num_hid_devices; i++) {
+               if (cl_data->sensor_idx[i] != HPD_IDX &&
+                   cl_data->sensor_sts[i] == SENSOR_ENABLED) {
+                       mp2->mp2_ops->stop(mp2, cl_data->sensor_idx[i]);
+                       status = amd_sfh_wait_for_response
+                                       (mp2, cl_data->sensor_idx[i], SENSOR_DISABLED);
+                       if (status != SENSOR_ENABLED)
+                               cl_data->sensor_sts[i] = SENSOR_DISABLED;
+               }
+       }
+
+       return 0;
+}
+
+static SIMPLE_DEV_PM_OPS(amd_mp2_pm_ops, amd_mp2_pci_suspend,
+               amd_mp2_pci_resume);
+
 static const struct pci_device_id amd_mp2_pci_tbl[] = {
        { PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_MP2) },
        { }
@@ -274,6 +322,7 @@ static struct pci_driver amd_mp2_pci_driver = {
        .name           = DRIVER_NAME,
        .id_table       = amd_mp2_pci_tbl,
        .probe          = amd_mp2_pci_probe,
+       .driver.pm      = &amd_mp2_pm_ops,
 };
 module_pci_driver(amd_mp2_pci_driver);
 
index 21ef55d..1ff6f83 100644 (file)
@@ -36,6 +36,8 @@
 
 #define HPD_IDX                16
 
+#define AMD_SFH_IDLE_LOOP      200
+
 /* SFH Command register */
 union sfh_cmd_base {
        u32 ul;
@@ -129,6 +131,9 @@ void amd_stop_all_sensors(struct amd_mp2_dev *privdata);
 int amd_mp2_get_sensor_num(struct amd_mp2_dev *privdata, u8 *sensor_id);
 int amd_sfh_hid_client_init(struct amd_mp2_dev *privdata);
 int amd_sfh_hid_client_deinit(struct amd_mp2_dev *privdata);
+u32 amd_sfh_wait_for_response(struct amd_mp2_dev *mp2, u8 sid, u32 sensor_sts);
+void amd_mp2_suspend(struct amd_mp2_dev *mp2);
+void amd_mp2_resume(struct amd_mp2_dev *mp2);
 
 struct amd_mp2_ops {
         void (*start)(struct amd_mp2_dev *privdata, struct amd_mp2_sensor_info info);