diff options
Diffstat (limited to 'drivers/hid/amd-sfh-hid')
-rw-r--r-- | drivers/hid/amd-sfh-hid/Kconfig | 1 | ||||
-rw-r--r-- | drivers/hid/amd-sfh-hid/Makefile | 2 | ||||
-rw-r--r-- | drivers/hid/amd-sfh-hid/amd_sfh_client.c | 32 | ||||
-rw-r--r-- | drivers/hid/amd-sfh-hid/amd_sfh_common.h | 2 | ||||
-rw-r--r-- | drivers/hid/amd-sfh-hid/amd_sfh_hid.c | 4 | ||||
-rw-r--r-- | drivers/hid/amd-sfh-hid/amd_sfh_hid.h | 2 | ||||
-rw-r--r-- | drivers/hid/amd-sfh-hid/amd_sfh_pcie.c | 67 | ||||
-rw-r--r-- | drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_init.c | 99 | ||||
-rw-r--r-- | drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_init.h | 3 | ||||
-rw-r--r-- | drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_interface.c | 42 | ||||
-rw-r--r-- | drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_interface.h | 24 |
11 files changed, 237 insertions, 41 deletions
diff --git a/drivers/hid/amd-sfh-hid/Kconfig b/drivers/hid/amd-sfh-hid/Kconfig index 329de5e12c1a..3291786a5ee6 100644 --- a/drivers/hid/amd-sfh-hid/Kconfig +++ b/drivers/hid/amd-sfh-hid/Kconfig @@ -5,7 +5,6 @@ menu "AMD SFH HID Support" config AMD_SFH_HID tristate "AMD Sensor Fusion Hub" - depends on HID depends on X86 help If you say yes to this option, support will be included for the diff --git a/drivers/hid/amd-sfh-hid/Makefile b/drivers/hid/amd-sfh-hid/Makefile index 0222170ab7ad..106514b54d16 100644 --- a/drivers/hid/amd-sfh-hid/Makefile +++ b/drivers/hid/amd-sfh-hid/Makefile @@ -13,4 +13,4 @@ amd_sfh-objs += sfh1_1/amd_sfh_init.o amd_sfh-objs += sfh1_1/amd_sfh_interface.o amd_sfh-objs += sfh1_1/amd_sfh_desc.o -ccflags-y += -I $(srctree)/$(src)/ +ccflags-y += -I $(src)/ diff --git a/drivers/hid/amd-sfh-hid/amd_sfh_client.c b/drivers/hid/amd-sfh-hid/amd_sfh_client.c index bdb578e0899f..3438d392920f 100644 --- a/drivers/hid/amd-sfh-hid/amd_sfh_client.c +++ b/drivers/hid/amd-sfh-hid/amd_sfh_client.c @@ -236,9 +236,9 @@ int amd_sfh_hid_client_init(struct amd_mp2_dev *privdata) cl_data->in_data = in_data; for (i = 0; i < cl_data->num_hid_devices; i++) { - in_data->sensor_virt_addr[i] = dma_alloc_coherent(dev, sizeof(int) * 8, - &cl_data->sensor_dma_addr[i], - GFP_KERNEL); + in_data->sensor_virt_addr[i] = dmam_alloc_coherent(dev, sizeof(int) * 8, + &cl_data->sensor_dma_addr[i], + GFP_KERNEL); if (!in_data->sensor_virt_addr[i]) { rc = -ENOMEM; goto cleanup; @@ -288,12 +288,22 @@ int amd_sfh_hid_client_init(struct amd_mp2_dev *privdata) mp2_ops->start(privdata, info); cl_data->sensor_sts[i] = amd_sfh_wait_for_response (privdata, cl_data->sensor_idx[i], SENSOR_ENABLED); + + if (cl_data->sensor_sts[i] == SENSOR_ENABLED) + cl_data->is_any_sensor_enabled = true; + } + + if (!cl_data->is_any_sensor_enabled || + (mp2_ops->discovery_status && mp2_ops->discovery_status(privdata) == 0)) { + dev_warn(dev, "Failed to discover, sensors not enabled is %d\n", + cl_data->is_any_sensor_enabled); + rc = -EOPNOTSUPP; + goto cleanup; } for (i = 0; i < cl_data->num_hid_devices; i++) { cl_data->cur_hid_dev = i; if (cl_data->sensor_sts[i] == SENSOR_ENABLED) { - cl_data->is_any_sensor_enabled = true; rc = amdtp_hid_probe(i, cl_data); if (rc) goto cleanup; @@ -305,12 +315,6 @@ int amd_sfh_hid_client_init(struct amd_mp2_dev *privdata) cl_data->sensor_sts[i]); } - if (!cl_data->is_any_sensor_enabled || - (mp2_ops->discovery_status && mp2_ops->discovery_status(privdata) == 0)) { - dev_warn(dev, "Failed to discover, sensors not enabled is %d\n", cl_data->is_any_sensor_enabled); - rc = -EOPNOTSUPP; - goto cleanup; - } schedule_delayed_work(&cl_data->work_buffer, msecs_to_jiffies(AMD_SFH_IDLE_LOOP)); return 0; @@ -327,7 +331,6 @@ cleanup: 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, status; for (i = 0; i < cl_data->num_hid_devices; i++) { @@ -347,12 +350,5 @@ int amd_sfh_hid_client_deinit(struct amd_mp2_dev *privdata) cancel_delayed_work_sync(&cl_data->work_buffer); amdtp_hid_remove(cl_data); - for (i = 0; i < cl_data->num_hid_devices; i++) { - if (in_data->sensor_virt_addr[i]) { - dma_free_coherent(&privdata->pdev->dev, 8 * sizeof(int), - in_data->sensor_virt_addr[i], - cl_data->sensor_dma_addr[i]); - } - } return 0; } diff --git a/drivers/hid/amd-sfh-hid/amd_sfh_common.h b/drivers/hid/amd-sfh-hid/amd_sfh_common.h index e5620d7db569..f44a3bb2fbd4 100644 --- a/drivers/hid/amd-sfh-hid/amd_sfh_common.h +++ b/drivers/hid/amd-sfh-hid/amd_sfh_common.h @@ -42,7 +42,9 @@ struct amd_mp2_sensor_info { struct sfh_dev_status { bool is_hpd_present; + bool is_hpd_enabled; bool is_als_present; + bool is_sra_present; }; struct amd_mp2_dev { diff --git a/drivers/hid/amd-sfh-hid/amd_sfh_hid.c b/drivers/hid/amd-sfh-hid/amd_sfh_hid.c index 705b52337068..81f3024b7b1b 100644 --- a/drivers/hid/amd-sfh-hid/amd_sfh_hid.c +++ b/drivers/hid/amd-sfh-hid/amd_sfh_hid.c @@ -171,11 +171,13 @@ err_hid_data: void amdtp_hid_remove(struct amdtp_cl_data *cli_data) { int i; + struct amdtp_hid_data *hid_data; for (i = 0; i < cli_data->num_hid_devices; ++i) { if (cli_data->hid_sensor_hubs[i]) { - kfree(cli_data->hid_sensor_hubs[i]->driver_data); + hid_data = cli_data->hid_sensor_hubs[i]->driver_data; hid_destroy_device(cli_data->hid_sensor_hubs[i]); + kfree(hid_data); cli_data->hid_sensor_hubs[i] = NULL; } } diff --git a/drivers/hid/amd-sfh-hid/amd_sfh_hid.h b/drivers/hid/amd-sfh-hid/amd_sfh_hid.h index 97296f587bc7..1c91be8daedd 100644 --- a/drivers/hid/amd-sfh-hid/amd_sfh_hid.h +++ b/drivers/hid/amd-sfh-hid/amd_sfh_hid.h @@ -73,8 +73,6 @@ struct amdtp_hid_data { }; /* Interface functions between HID LL driver and AMD SFH client */ -void hid_amdtp_set_feature(struct hid_device *hid, char *buf, u32 len, int report_id); -void hid_amdtp_get_report(struct hid_device *hid, int report_id, int report_type); int amdtp_hid_probe(u32 cur_hid_dev, struct amdtp_cl_data *cli_data); 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); diff --git a/drivers/hid/amd-sfh-hid/amd_sfh_pcie.c b/drivers/hid/amd-sfh-hid/amd_sfh_pcie.c index 9e97c26c4482..1c1fd63330c9 100644 --- a/drivers/hid/amd-sfh-hid/amd_sfh_pcie.c +++ b/drivers/hid/amd-sfh-hid/amd_sfh_pcie.c @@ -18,6 +18,7 @@ #include <linux/iopoll.h> #include <linux/module.h> #include <linux/slab.h> +#include <linux/string_choices.h> #include "amd_sfh_pcie.h" #include "sfh1_1/amd_sfh_init.h" @@ -122,7 +123,7 @@ int amd_sfh_irq_init_v2(struct amd_mp2_dev *privdata) { int rc; - pci_intx(privdata->pdev, true); + pcim_intx(privdata->pdev, true); rc = devm_request_irq(&privdata->pdev->dev, privdata->pdev->irq, amd_sfh_irq_handler, 0, DRIVER_NAME, privdata); @@ -248,7 +249,7 @@ static void amd_mp2_pci_remove(void *privdata) struct amd_mp2_dev *mp2 = privdata; amd_sfh_hid_client_deinit(privdata); mp2->mp2_ops->stop_all(mp2); - pci_intx(mp2->pdev, false); + pcim_intx(mp2->pdev, false); amd_sfh_clear_intr(mp2); } @@ -330,20 +331,73 @@ static const struct dmi_system_id dmi_nodevs[] = { { } }; +static ssize_t hpd_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + struct amd_mp2_dev *mp2 = dev_get_drvdata(dev); + + return sysfs_emit(buf, "%s\n", str_enabled_disabled(mp2->dev_en.is_hpd_enabled)); +} + +static ssize_t hpd_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct amd_mp2_dev *mp2 = dev_get_drvdata(dev); + bool enabled; + int ret; + + ret = kstrtobool(buf, &enabled); + if (ret) + return ret; + + mp2->sfh1_1_ops->toggle_hpd(mp2, enabled); + + return count; +} +static DEVICE_ATTR_RW(hpd); + +static umode_t sfh_attr_is_visible(struct kobject *kobj, struct attribute *attr, int idx) +{ + struct device *dev = kobj_to_dev(kobj); + struct amd_mp2_dev *mp2 = dev_get_drvdata(dev); + + if (!mp2->sfh1_1_ops || !mp2->dev_en.is_hpd_present) + return 0; + + return attr->mode; +} + +static struct attribute *sfh_attrs[] = { + &dev_attr_hpd.attr, + NULL, +}; + +static struct attribute_group sfh_attr_group = { + .attrs = sfh_attrs, + .is_visible = sfh_attr_is_visible, +}; + +static const struct attribute_group *amd_sfh_groups[] = { + &sfh_attr_group, + NULL, +}; + static void sfh1_1_init_work(struct work_struct *work) { struct amd_mp2_dev *mp2 = container_of(work, struct amd_mp2_dev, work); - struct pci_dev *pdev = mp2->pdev; int rc; rc = mp2->sfh1_1_ops->init(mp2); - if (rc) { - dev_err(&pdev->dev, "sfh1_1_init failed err %d\n", rc); + if (rc) return; - } amd_sfh_clear_intr(mp2); mp2->init_done = 1; + + rc = sysfs_update_group(&mp2->pdev->dev.kobj, &sfh_attr_group); + if (rc) + dev_warn(&mp2->pdev->dev, "failed to update sysfs group\n"); + } static void sfh_init_work(struct work_struct *work) @@ -490,6 +544,7 @@ static struct pci_driver amd_mp2_pci_driver = { .driver.pm = &amd_mp2_pm_ops, .shutdown = amd_sfh_shutdown, .remove = amd_sfh_remove, + .dev_groups = amd_sfh_groups, }; module_pci_driver(amd_mp2_pci_driver); diff --git a/drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_init.c b/drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_init.c index 5b24d5f63701..0a9b44ce4904 100644 --- a/drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_init.c +++ b/drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_init.c @@ -30,6 +30,7 @@ static int amd_sfh_get_sensor_num(struct amd_mp2_dev *mp2, u8 *sensor_id) case ACCEL_IDX: case GYRO_IDX: case MAG_IDX: + case SRA_IDX: case ALS_IDX: case HPD_IDX: if (BIT(i) & slist->sl.sensors) @@ -58,6 +59,8 @@ static const char *get_sensor_name(int idx) return "gyroscope"; case MAG_IDX: return "magnetometer"; + case SRA_IDX: + return "SRA"; case ALS_IDX: return "ALS"; case HPD_IDX: @@ -80,6 +83,9 @@ static int amd_sfh_hid_client_deinit(struct amd_mp2_dev *privdata) case ALS_IDX: privdata->dev_en.is_als_present = false; break; + case SRA_IDX: + privdata->dev_en.is_sra_present = false; + break; } if (cl_data->sensor_sts[i] == SENSOR_ENABLED) { @@ -130,6 +136,22 @@ static int amd_sfh1_1_hid_client_init(struct amd_mp2_dev *privdata) for (i = 0; i < cl_data->num_hid_devices; i++) { cl_data->sensor_sts[i] = SENSOR_DISABLED; + + if (cl_data->sensor_idx[i] == SRA_IDX) { + info.sensor_idx = cl_data->sensor_idx[i]; + writel(0, privdata->mmio + amd_get_p2c_val(privdata, 0)); + mp2_ops->start(privdata, info); + status = amd_sfh_wait_for_response + (privdata, cl_data->sensor_idx[i], ENABLE_SENSOR); + + cl_data->sensor_sts[i] = (status == 0) ? SENSOR_ENABLED : SENSOR_DISABLED; + if (cl_data->sensor_sts[i] == SENSOR_ENABLED) { + cl_data->is_any_sensor_enabled = true; + privdata->dev_en.is_sra_present = true; + } + continue; + } + cl_data->sensor_requested_cnt[i] = 0; cl_data->cur_hid_dev = i; cl_idx = cl_data->sensor_idx[i]; @@ -181,6 +203,8 @@ static int amd_sfh1_1_hid_client_init(struct amd_mp2_dev *privdata) } for (i = 0; i < cl_data->num_hid_devices; i++) { + if (cl_data->sensor_idx[i] == SRA_IDX) + continue; cl_data->cur_hid_dev = i; if (cl_data->sensor_sts[i] == SENSOR_ENABLED) { cl_data->is_any_sensor_enabled = true; @@ -190,6 +214,8 @@ static int amd_sfh1_1_hid_client_init(struct amd_mp2_dev *privdata) switch (cl_data->sensor_idx[i]) { case HPD_IDX: privdata->dev_en.is_hpd_present = true; + privdata->dev_en.is_hpd_enabled = true; + amd_sfh_toggle_hpd(privdata, false); break; case ALS_IDX: privdata->dev_en.is_als_present = true; @@ -202,7 +228,7 @@ static int amd_sfh1_1_hid_client_init(struct amd_mp2_dev *privdata) } if (!cl_data->is_any_sensor_enabled) { - dev_warn(dev, "Failed to discover, sensors not enabled is %d\n", + dev_warn(dev, "No sensor registered, sensors not enabled is %d\n", cl_data->is_any_sensor_enabled); rc = -EOPNOTSUPP; goto cleanup; @@ -214,6 +240,8 @@ static int amd_sfh1_1_hid_client_init(struct amd_mp2_dev *privdata) cleanup: amd_sfh_hid_client_deinit(privdata); for (i = 0; i < cl_data->num_hid_devices; i++) { + if (cl_data->sensor_idx[i] == SRA_IDX) + continue; devm_kfree(dev, cl_data->feature_report[i]); devm_kfree(dev, in_data->input_report[i]); devm_kfree(dev, cl_data->report_descr[i]); @@ -227,7 +255,16 @@ static void amd_sfh_resume(struct amd_mp2_dev *mp2) struct amd_mp2_sensor_info info; int i, status; + if (!cl_data->is_any_sensor_enabled) { + amd_sfh_clear_intr(mp2); + return; + } + for (i = 0; i < cl_data->num_hid_devices; i++) { + /* leave HPD alone; policy is controlled by sysfs */ + if (cl_data->sensor_idx[i] == HPD_IDX) + continue; + if (cl_data->sensor_sts[i] == SENSOR_DISABLED) { info.sensor_idx = cl_data->sensor_idx[i]; mp2->mp2_ops->start(mp2, info); @@ -252,9 +289,16 @@ static void amd_sfh_suspend(struct amd_mp2_dev *mp2) struct amdtp_cl_data *cl_data = mp2->cl_data; int i, status; + if (!cl_data->is_any_sensor_enabled) { + amd_sfh_clear_intr(mp2); + return; + } + 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) { + /* leave HPD alone; policy is controlled by sysfs */ + if (cl_data->sensor_idx[i] == HPD_IDX) + continue; + if (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], DISABLE_SENSOR); @@ -272,6 +316,44 @@ static void amd_sfh_suspend(struct amd_mp2_dev *mp2) amd_sfh_clear_intr(mp2); } +void amd_sfh_toggle_hpd(struct amd_mp2_dev *mp2, bool enabled) +{ + struct amdtp_cl_data *cl_data = mp2->cl_data; + struct amd_mp2_sensor_info info; + int i, status; + + if (mp2->dev_en.is_hpd_enabled == enabled) + return; + + for (i = 0; i < cl_data->num_hid_devices; i++) { + if (cl_data->sensor_idx[i] != HPD_IDX) + continue; + info.sensor_idx = cl_data->sensor_idx[i]; + if (enabled) { + mp2->mp2_ops->start(mp2, info); + status = amd_sfh_wait_for_response + (mp2, cl_data->sensor_idx[i], ENABLE_SENSOR); + if (status == 0) + status = SENSOR_ENABLED; + if (status == SENSOR_ENABLED) + cl_data->sensor_sts[i] = SENSOR_ENABLED; + } else { + mp2->mp2_ops->stop(mp2, cl_data->sensor_idx[i]); + status = amd_sfh_wait_for_response + (mp2, cl_data->sensor_idx[i], DISABLE_SENSOR); + if (status == 0) + status = SENSOR_DISABLED; + if (status != SENSOR_ENABLED) + cl_data->sensor_sts[i] = SENSOR_DISABLED; + } + dev_dbg(&mp2->pdev->dev, "toggle sid 0x%x (%s) status 0x%x\n", + cl_data->sensor_idx[i], get_sensor_name(cl_data->sensor_idx[i]), + cl_data->sensor_sts[i]); + break; + } + mp2->dev_en.is_hpd_enabled = enabled; +} + static void amd_mp2_pci_remove(void *privdata) { struct amd_mp2_dev *mp2 = privdata; @@ -279,7 +361,7 @@ static void amd_mp2_pci_remove(void *privdata) sfh_deinit_emp2(); amd_sfh_hid_client_deinit(privdata); mp2->mp2_ops->stop_all(mp2); - pci_intx(mp2->pdev, false); + pcim_intx(mp2->pdev, false); amd_sfh_clear_intr(mp2); } @@ -289,8 +371,8 @@ static void amd_sfh_set_ops(struct amd_mp2_dev *mp2) sfh_interface_init(mp2); mp2_ops = mp2->mp2_ops; - mp2_ops->clear_intr = amd_sfh_clear_intr_v2, - mp2_ops->init_intr = amd_sfh_irq_init_v2, + mp2_ops->clear_intr = amd_sfh_clear_intr_v2; + mp2_ops->init_intr = amd_sfh_irq_init_v2; mp2_ops->suspend = amd_sfh_suspend; mp2_ops->resume = amd_sfh_resume; mp2_ops->remove = amd_mp2_pci_remove; @@ -320,7 +402,7 @@ int amd_sfh1_1_init(struct amd_mp2_dev *mp2) memcpy_fromio(&binfo, mp2->vsbase, sizeof(struct sfh_base_info)); if (binfo.sbase.fw_info.fw_ver == 0 || binfo.sbase.s_list.sl.sensors == 0) { - dev_dbg(dev, "failed to get sensors\n"); + dev_dbg(dev, "No sensor registered\n"); return -EOPNOTSUPP; } dev_dbg(dev, "firmware version 0x%x\n", binfo.sbase.fw_info.fw_ver); @@ -337,7 +419,8 @@ int amd_sfh1_1_init(struct amd_mp2_dev *mp2) rc = amd_sfh1_1_hid_client_init(mp2); if (rc) { sfh_deinit_emp2(); - dev_err(dev, "amd_sfh1_1_hid_client_init failed\n"); + if ((rc != -ENODEV) && (rc != -EOPNOTSUPP)) + dev_err(dev, "amd_sfh1_1_hid_client_init failed\n"); return rc; } diff --git a/drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_init.h b/drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_init.h index 21c44990bbeb..797d206641c6 100644 --- a/drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_init.h +++ b/drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_init.h @@ -15,12 +15,15 @@ struct amd_sfh1_1_ops { int (*init)(struct amd_mp2_dev *mp2); + void (*toggle_hpd)(struct amd_mp2_dev *mp2, bool enable); }; int amd_sfh1_1_init(struct amd_mp2_dev *mp2); +void amd_sfh_toggle_hpd(struct amd_mp2_dev *mp2, bool enabled); static const struct amd_sfh1_1_ops __maybe_unused sfh1_1_ops = { .init = amd_sfh1_1_init, + .toggle_hpd = amd_sfh_toggle_hpd, }; #endif diff --git a/drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_interface.c b/drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_interface.c index 2de2668a0277..837d59e7a661 100644 --- a/drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_interface.c +++ b/drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_interface.c @@ -87,6 +87,41 @@ void sfh_interface_init(struct amd_mp2_dev *mp2) emp2 = mp2; } +static int amd_sfh_mode_info(u32 *platform_type, u32 *laptop_placement) +{ + struct sfh_op_mode mode; + + if (!platform_type || !laptop_placement) + return -EINVAL; + + if (!emp2 || !emp2->dev_en.is_sra_present) + return -ENODEV; + + mode.val = readl(emp2->mmio + amd_get_c2p_val(emp2, 3)); + + *platform_type = mode.op_mode.devicemode; + + if (mode.op_mode.ontablestate == 1) { + *laptop_placement = ON_TABLE; + } else if (mode.op_mode.ontablestate == 2) { + *laptop_placement = ON_LAP_MOTION; + } else if (mode.op_mode.inbagstate == 1) { + *laptop_placement = IN_BAG; + } else if (mode.op_mode.outbagstate == 1) { + *laptop_placement = OUT_OF_BAG; + } else if (mode.op_mode.ontablestate == 0 || mode.op_mode.inbagstate == 0 || + mode.op_mode.outbagstate == 0) { + *laptop_placement = LP_UNKNOWN; + pr_warn_once("Unknown laptop placement\n"); + } else if (mode.op_mode.ontablestate == 3 || mode.op_mode.inbagstate == 3 || + mode.op_mode.outbagstate == 3) { + *laptop_placement = LP_UNDEFINED; + pr_warn_once("Undefined laptop placement\n"); + } + + return 0; +} + static int amd_sfh_hpd_info(u8 *user_present) { struct hpd_status hpdstatus; @@ -94,10 +129,10 @@ static int amd_sfh_hpd_info(u8 *user_present) if (!user_present) return -EINVAL; - if (!emp2 || !emp2->dev_en.is_hpd_present) + if (!emp2 || !emp2->dev_en.is_hpd_present || !emp2->dev_en.is_hpd_enabled) return -ENODEV; - hpdstatus.val = readl(emp2->mmio + AMD_C2P_MSG(4)); + hpdstatus.val = readl(emp2->mmio + amd_get_c2p_val(emp2, 4)); *user_present = hpdstatus.shpd.presence; return 0; @@ -131,6 +166,9 @@ int amd_get_sfh_info(struct amd_sfh_info *sfh_info, enum sfh_message_type op) return amd_sfh_hpd_info(&sfh_info->user_present); case MT_ALS: return amd_sfh_als_info(&sfh_info->ambient_light); + case MT_SRA: + return amd_sfh_mode_info(&sfh_info->platform_type, + &sfh_info->laptop_placement); } } return -EINVAL; diff --git a/drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_interface.h b/drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_interface.h index 2c211d28764d..665c99ad779f 100644 --- a/drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_interface.h +++ b/drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_interface.h @@ -22,8 +22,9 @@ enum sensor_index { ACCEL_IDX, GYRO_IDX, MAG_IDX, - ALS_IDX = 4, - HPD_IDX = 5, + SRA_IDX, + ALS_IDX, + HPD_IDX, MAX_IDX = 15, }; @@ -164,6 +165,25 @@ struct hpd_status { }; }; +struct sfh_op_mode { + union { + u32 val; + struct { + u32 mode : 3; + u32 lidstatus : 1; + u32 angle : 10; + u32 inbagstatedbg : 2; + u32 ontablestate : 2; + u32 inbagstate : 2; + u32 outbagstate : 2; + u32 inbagmlcstate : 1; + u32 powerstate : 2; + u32 data : 3; + u32 devicemode : 4; + } op_mode; + }; +}; + 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); |