HID: amd_sfh: Extend ALS support for newer AMD platform
authorBasavaraj Natikar <Basavaraj.Natikar@amd.com>
Fri, 18 Jun 2021 08:18:37 +0000 (13:48 +0530)
committerJiri Kosina <jkosina@suse.cz>
Thu, 24 Jun 2021 12:28:03 +0000 (14:28 +0200)
Extend ALS support for AMD next generation SoC's like Renoir, Cezanne.
AMD next generation platforms use C2P message register to read ALS
sensor data instead of DRAM address.

Signed-off-by: Basavaraj Natikar <Basavaraj.Natikar@amd.com>
Reviewed-by: Nehal Shah <nehal-bakulchandra.shah@amd.com>
Reviewed-by: Shyam Sundar S K <Shyam-sundar.S-k@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_hid.h
drivers/hid/amd-sfh-hid/amd_sfh_pcie.c
drivers/hid/amd-sfh-hid/amd_sfh_pcie.h
drivers/hid/amd-sfh-hid/hid_descriptor/amd_sfh_hid_desc.c
drivers/hid/amd-sfh-hid/hid_descriptor/amd_sfh_hid_desc.h

index d3d5dcec7cf10035d13c71ed61b7ee5f3067d8f8..efb849411d25487e0d373aefa177eb9896f0fd47 100644 (file)
@@ -77,6 +77,7 @@ int amd_sfh_get_report(struct hid_device *hid, int report_id, int report_type)
 static void amd_sfh_work(struct work_struct *work)
 {
        struct amdtp_cl_data *cli_data = container_of(work, struct amdtp_cl_data, work.work);
+       struct amd_input_data *in_data = cli_data->in_data;
        struct request_list *req_node;
        u8 current_index, sensor_index;
        u8 report_id, node_type;
@@ -101,13 +102,11 @@ static void amd_sfh_work(struct work_struct *work)
                        pr_err("AMDSFH: Invalid report size\n");
 
        } else if (node_type == HID_INPUT_REPORT) {
-               report_size = get_input_report(sensor_index, report_id,
-                                              cli_data->input_report[current_index],
-                                              cli_data->sensor_virt_addr[current_index]);
+               report_size = get_input_report(current_index, sensor_index, report_id, in_data);
                if (report_size)
                        hid_input_report(cli_data->hid_sensor_hubs[current_index],
                                         cli_data->report_type[current_index],
-                                        cli_data->input_report[current_index], report_size, 0);
+                                        in_data->input_report[current_index], report_size, 0);
                else
                        pr_err("AMDSFH: Invalid report size\n");
        }
@@ -119,21 +118,22 @@ static void amd_sfh_work(struct work_struct *work)
 static void amd_sfh_work_buffer(struct work_struct *work)
 {
        struct amdtp_cl_data *cli_data = container_of(work, struct amdtp_cl_data, work_buffer.work);
+       struct amd_input_data *in_data = cli_data->in_data;
        u8 report_size;
        int i;
 
        for (i = 0; i < cli_data->num_hid_devices; i++) {
-               report_size = get_input_report(cli_data->sensor_idx[i], cli_data->report_id[i],
-                                              cli_data->input_report[i],
-                                              cli_data->sensor_virt_addr[i]);
+               report_size = get_input_report(i, cli_data->sensor_idx[i], cli_data->report_id[i],
+                                              in_data);
                hid_input_report(cli_data->hid_sensor_hubs[i], HID_INPUT_REPORT,
-                                cli_data->input_report[i], report_size, 0);
+                                in_data->input_report[i], report_size, 0);
        }
        schedule_delayed_work(&cli_data->work_buffer, msecs_to_jiffies(AMD_SFH_IDLE_LOOP));
 }
 
 int amd_sfh_hid_client_init(struct amd_mp2_dev *privdata)
 {
+       struct amd_input_data *in_data = &privdata->in_data;
        struct amdtp_cl_data *cl_data = privdata->cl_data;
        struct amd_mp2_sensor_info info;
        struct device *dev;
@@ -143,18 +143,16 @@ int amd_sfh_hid_client_init(struct amd_mp2_dev *privdata)
        int rc, i;
 
        dev = &privdata->pdev->dev;
-       cl_data = devm_kzalloc(dev, sizeof(*cl_data), GFP_KERNEL);
-       if (!cl_data)
-               return -ENOMEM;
 
        cl_data->num_hid_devices = amd_mp2_get_sensor_num(privdata, &cl_data->sensor_idx[0]);
 
        INIT_DELAYED_WORK(&cl_data->work, amd_sfh_work);
        INIT_DELAYED_WORK(&cl_data->work_buffer, amd_sfh_work_buffer);
        INIT_LIST_HEAD(&req_list.list);
+       cl_data->in_data = in_data;
 
        for (i = 0; i < cl_data->num_hid_devices; i++) {
-               cl_data->sensor_virt_addr[i] = dma_alloc_coherent(dev, sizeof(int) * 8,
+               in_data->sensor_virt_addr[i] = dma_alloc_coherent(dev, sizeof(int) * 8,
                                                                  &cl_data->sensor_dma_addr[i],
                                                                  GFP_KERNEL);
                cl_data->sensor_sts[i] = 0;
@@ -181,8 +179,8 @@ int amd_sfh_hid_client_init(struct amd_mp2_dev *privdata)
                        rc = -ENOMEM;
                        goto cleanup;
                }
-               cl_data->input_report[i] = devm_kzalloc(dev, input_report_size, GFP_KERNEL);
-               if (!cl_data->input_report[i]) {
+               in_data->input_report[i] = devm_kzalloc(dev, input_report_size, GFP_KERNEL);
+               if (!in_data->input_report[i]) {
                        rc = -ENOMEM;
                        goto cleanup;
                }
@@ -205,28 +203,27 @@ int amd_sfh_hid_client_init(struct amd_mp2_dev *privdata)
                privdata->mp2_ops->start(privdata, info);
                cl_data->sensor_sts[i] = 1;
        }
-       privdata->cl_data = cl_data;
        schedule_delayed_work(&cl_data->work_buffer, msecs_to_jiffies(AMD_SFH_IDLE_LOOP));
        return 0;
 
 cleanup:
        for (i = 0; i < cl_data->num_hid_devices; i++) {
-               if (cl_data->sensor_virt_addr[i]) {
+               if (in_data->sensor_virt_addr[i]) {
                        dma_free_coherent(&privdata->pdev->dev, 8 * sizeof(int),
-                                         cl_data->sensor_virt_addr[i],
+                                         in_data->sensor_virt_addr[i],
                                          cl_data->sensor_dma_addr[i]);
                }
                devm_kfree(dev, cl_data->feature_report[i]);
-               devm_kfree(dev, cl_data->input_report[i]);
+               devm_kfree(dev, in_data->input_report[i]);
                devm_kfree(dev, cl_data->report_descr[i]);
        }
-       devm_kfree(dev, cl_data);
        return rc;
 }
 
 int amd_sfh_hid_client_deinit(struct amd_mp2_dev *privdata)
 {
        struct amdtp_cl_data *cl_data = privdata->cl_data;
+       struct amd_input_data *in_data = cl_data->in_data;
        int i;
 
        for (i = 0; i < cl_data->num_hid_devices; i++)
@@ -237,9 +234,9 @@ int amd_sfh_hid_client_deinit(struct amd_mp2_dev *privdata)
        amdtp_hid_remove(cl_data);
 
        for (i = 0; i < cl_data->num_hid_devices; i++) {
-               if (cl_data->sensor_virt_addr[i]) {
+               if (in_data->sensor_virt_addr[i]) {
                        dma_free_coherent(&privdata->pdev->dev, 8 * sizeof(int),
-                                         cl_data->sensor_virt_addr[i],
+                                         in_data->sensor_virt_addr[i],
                                          cl_data->sensor_dma_addr[i]);
                }
        }
index d7eac1728e314add855c917ba5e07edf4e95c443..359c5de96af84005a53f1bbefc74e9c78039d74f 100644 (file)
 #define AMD_SFH_HID_VENDOR     0x1022
 #define AMD_SFH_HID_PRODUCT    0x0001
 
+struct amd_input_data {
+       u32 *sensor_virt_addr[MAX_HID_DEVICES];
+       u8 *input_report[MAX_HID_DEVICES];
+};
+
 struct amdtp_cl_data {
        u8 init_done;
        u32 cur_hid_dev;
@@ -26,7 +31,6 @@ struct amdtp_cl_data {
        u8 *hid_descr[MAX_HID_DEVICES];
        int hid_descr_size[MAX_HID_DEVICES];
        phys_addr_t phys_addr_base;
-       u32 *sensor_virt_addr[MAX_HID_DEVICES];
        dma_addr_t sensor_dma_addr[MAX_HID_DEVICES];
        u32 sensor_sts[MAX_HID_DEVICES];
        u32 sensor_requested_cnt[MAX_HID_DEVICES];
@@ -34,8 +38,8 @@ struct amdtp_cl_data {
        u8 report_id[MAX_HID_DEVICES];
        u8 sensor_idx[MAX_HID_DEVICES];
        u8 *feature_report[MAX_HID_DEVICES];
-       u8 *input_report[MAX_HID_DEVICES];
        u8 request_done[MAX_HID_DEVICES];
+       struct amd_input_data *in_data;
        struct delayed_work work;
        struct delayed_work work_buffer;
 };
@@ -64,4 +68,6 @@ void amdtp_hid_remove(struct amdtp_cl_data *cli_data);
 int amd_sfh_get_report(struct hid_device *hid, int report_id, int report_type);
 void amd_sfh_set_report(struct hid_device *hid, int report_id, int report_type);
 void amdtp_hid_wakeup(struct hid_device *hid);
+u8 get_input_report(u8 current_index, int sensor_idx, int report_id,
+                   struct amd_input_data *in_data);
 #endif
index 48ff54dc5d7062a1b3391f7195b52bb2d501de07..ff131f450bdcc7a5c2aaa32d99a723d072a510d3 100644 (file)
@@ -230,6 +230,11 @@ static int amd_mp2_pci_probe(struct pci_dev *pdev, const struct pci_device_id *i
                rc = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
                return rc;
        }
+
+       privdata->cl_data = devm_kzalloc(&pdev->dev, sizeof(struct amdtp_cl_data), GFP_KERNEL);
+       if (!privdata->cl_data)
+               return -ENOMEM;
+
        rc = devm_add_action_or_reset(&pdev->dev, amd_mp2_pci_remove, privdata);
        if (rc)
                return rc;
index 6297d78c7aef465f7155094e24e9c7812037f427..0886b2ad033e8a14a745066eb39dbf459d105b39 100644 (file)
@@ -10,6 +10,7 @@
 #define PCIE_MP2_AMD_H
 
 #include <linux/pci.h>
+#include "amd_sfh_hid.h"
 
 #define PCI_DEVICE_ID_AMD_MP2  0x15E4
 
@@ -75,6 +76,7 @@ struct amd_mp2_dev {
        struct amdtp_cl_data *cl_data;
        void __iomem *mmio;
        const struct amd_mp2_ops *mp2_ops;
+       struct amd_input_data in_data;
        /* mp2 active control status */
        u32 mp2_acs;
 };
index 6e3ad66e57a408f211941e1721536624e60513bb..cdc0a8d32249fb2ab7a8ef4d9efde59e9fb40586 100644 (file)
@@ -12,6 +12,7 @@
 #include "amd_sfh_pcie.h"
 #include "amd_sfh_hid_desc.h"
 #include "amd_sfh_hid_report_desc.h"
+#include "amd_sfh_hid.h"
 
 #define        AMD_SFH_FW_MULTIPLIER (1000)
 #define HID_USAGE_SENSOR_PROP_REPORTING_STATE_ALL_EVENTS_ENUM  0x41
@@ -174,8 +175,12 @@ static void get_common_inputs(struct common_input_property *common, int report_i
        common->event_type = HID_USAGE_SENSOR_EVENT_DATA_UPDATED_ENUM;
 }
 
-u8 get_input_report(int sensor_idx, int report_id, u8 *input_report, u32 *sensor_virt_addr)
+u8 get_input_report(u8 current_index, int sensor_idx, int report_id, struct amd_input_data *in_data)
 {
+       struct amd_mp2_dev *privdata = container_of(in_data, struct amd_mp2_dev, in_data);
+       u32 *sensor_virt_addr = in_data->sensor_virt_addr[current_index];
+       u8 *input_report = in_data->input_report[current_index];
+       u8 supported_input = privdata->mp2_acs & GENMASK(3, 0);
        struct accel3_input_report acc_input;
        struct gyro_input_report gyro_input;
        struct magno_input_report magno_input;
@@ -213,7 +218,12 @@ u8 get_input_report(int sensor_idx, int report_id, u8 *input_report, u32 *sensor
                break;
        case als_idx: /* Als */
                get_common_inputs(&als_input.common_property, report_id);
-               als_input.illuminance_value =  (int)sensor_virt_addr[0] / AMD_SFH_FW_MULTIPLIER;
+               /* For ALS ,V2 Platforms uses C2P_MSG5 register instead of DRAM access method */
+               if (supported_input == V2_STATUS)
+                       als_input.illuminance_value = (int)readl(privdata->mmio + AMD_C2P_MSG(5));
+               else
+                       als_input.illuminance_value =
+                               (int)sensor_virt_addr[0] / AMD_SFH_FW_MULTIPLIER;
                report_size = sizeof(als_input);
                memcpy(input_report, &als_input, sizeof(als_input));
                break;
index 095c471d8fd6fba28b0191fccb74101a37885b16..a23c1046627ff6faa2d7ecf5b3381afc4fbb3f97 100644 (file)
@@ -103,5 +103,4 @@ struct als_input_report {
 int get_report_descriptor(int sensor_idx, u8 rep_desc[]);
 u32 get_descr_sz(int sensor_idx, int descriptor_name);
 u8 get_feature_report(int sensor_idx, int report_id, u8 *feature_report);
-u8 get_input_report(int sensor_idx, int report_id, u8 *input_report, u32 *sensor_virt_addr);
 #endif