Merge branch 'for-5.19/amd-sfh' into for-linus
- support for sensor discovery and code cleanups (Basavaraj Natikar)
This commit is contained in:
Коммит
8959f00799
|
@ -141,6 +141,24 @@ u32 amd_sfh_wait_for_response(struct amd_mp2_dev *mp2, u8 sid, u32 sensor_sts)
|
||||||
return sensor_sts;
|
return sensor_sts;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const char *get_sensor_name(int idx)
|
||||||
|
{
|
||||||
|
switch (idx) {
|
||||||
|
case accel_idx:
|
||||||
|
return "accelerometer";
|
||||||
|
case gyro_idx:
|
||||||
|
return "gyroscope";
|
||||||
|
case mag_idx:
|
||||||
|
return "magnetometer";
|
||||||
|
case als_idx:
|
||||||
|
return "ALS";
|
||||||
|
case HPD_IDX:
|
||||||
|
return "HPD";
|
||||||
|
default:
|
||||||
|
return "unknown sensor type";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int amd_sfh_hid_client_init(struct amd_mp2_dev *privdata)
|
int amd_sfh_hid_client_init(struct amd_mp2_dev *privdata)
|
||||||
{
|
{
|
||||||
struct amd_input_data *in_data = &privdata->in_data;
|
struct amd_input_data *in_data = &privdata->in_data;
|
||||||
|
@ -219,13 +237,27 @@ int amd_sfh_hid_client_init(struct amd_mp2_dev *privdata)
|
||||||
(privdata, cl_data->sensor_idx[i], SENSOR_DISABLED);
|
(privdata, cl_data->sensor_idx[i], SENSOR_DISABLED);
|
||||||
if (status != SENSOR_ENABLED)
|
if (status != SENSOR_ENABLED)
|
||||||
cl_data->sensor_sts[i] = SENSOR_DISABLED;
|
cl_data->sensor_sts[i] = SENSOR_DISABLED;
|
||||||
dev_dbg(dev, "sid 0x%x status 0x%x\n",
|
dev_dbg(dev, "sid 0x%x (%s) status 0x%x\n",
|
||||||
cl_data->sensor_idx[i], cl_data->sensor_sts[i]);
|
cl_data->sensor_idx[i],
|
||||||
|
get_sensor_name(cl_data->sensor_idx[i]),
|
||||||
|
cl_data->sensor_sts[i]);
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
dev_dbg(dev, "sid 0x%x status 0x%x\n",
|
dev_dbg(dev, "sid 0x%x (%s) status 0x%x\n",
|
||||||
cl_data->sensor_idx[i], cl_data->sensor_sts[i]);
|
cl_data->sensor_idx[i], get_sensor_name(cl_data->sensor_idx[i]),
|
||||||
|
cl_data->sensor_sts[i]);
|
||||||
|
}
|
||||||
|
if (privdata->mp2_ops->discovery_status &&
|
||||||
|
privdata->mp2_ops->discovery_status(privdata) == 0) {
|
||||||
|
amd_sfh_hid_client_deinit(privdata);
|
||||||
|
for (i = 0; i < cl_data->num_hid_devices; i++) {
|
||||||
|
devm_kfree(dev, cl_data->feature_report[i]);
|
||||||
|
devm_kfree(dev, in_data->input_report[i]);
|
||||||
|
devm_kfree(dev, cl_data->report_descr[i]);
|
||||||
|
}
|
||||||
|
dev_warn(dev, "Failed to discover, sensors not enabled\n");
|
||||||
|
return -EOPNOTSUPP;
|
||||||
}
|
}
|
||||||
schedule_delayed_work(&cl_data->work_buffer, msecs_to_jiffies(AMD_SFH_IDLE_LOOP));
|
schedule_delayed_work(&cl_data->work_buffer, msecs_to_jiffies(AMD_SFH_IDLE_LOOP));
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -257,8 +289,9 @@ int amd_sfh_hid_client_deinit(struct amd_mp2_dev *privdata)
|
||||||
(privdata, cl_data->sensor_idx[i], SENSOR_DISABLED);
|
(privdata, cl_data->sensor_idx[i], SENSOR_DISABLED);
|
||||||
if (status != SENSOR_ENABLED)
|
if (status != SENSOR_ENABLED)
|
||||||
cl_data->sensor_sts[i] = SENSOR_DISABLED;
|
cl_data->sensor_sts[i] = SENSOR_DISABLED;
|
||||||
dev_dbg(&privdata->pdev->dev, "stopping sid 0x%x status 0x%x\n",
|
dev_dbg(&privdata->pdev->dev, "stopping sid 0x%x (%s) status 0x%x\n",
|
||||||
cl_data->sensor_idx[i], cl_data->sensor_sts[i]);
|
cl_data->sensor_idx[i], get_sensor_name(cl_data->sensor_idx[i]),
|
||||||
|
cl_data->sensor_sts[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -12,6 +12,7 @@
|
||||||
#include <linux/sched.h>
|
#include <linux/sched.h>
|
||||||
|
|
||||||
#include "amd_sfh_hid.h"
|
#include "amd_sfh_hid.h"
|
||||||
|
#include "amd_sfh_pcie.h"
|
||||||
|
|
||||||
#define AMD_SFH_RESPONSE_TIMEOUT 1500
|
#define AMD_SFH_RESPONSE_TIMEOUT 1500
|
||||||
|
|
||||||
|
@ -120,6 +121,8 @@ static struct hid_ll_driver amdtp_hid_ll_driver = {
|
||||||
|
|
||||||
int amdtp_hid_probe(u32 cur_hid_dev, struct amdtp_cl_data *cli_data)
|
int amdtp_hid_probe(u32 cur_hid_dev, struct amdtp_cl_data *cli_data)
|
||||||
{
|
{
|
||||||
|
struct amd_mp2_dev *mp2 = container_of(cli_data->in_data, struct amd_mp2_dev, in_data);
|
||||||
|
struct device *dev = &mp2->pdev->dev;
|
||||||
struct hid_device *hid;
|
struct hid_device *hid;
|
||||||
struct amdtp_hid_data *hid_data;
|
struct amdtp_hid_data *hid_data;
|
||||||
int rc;
|
int rc;
|
||||||
|
@ -141,10 +144,12 @@ int amdtp_hid_probe(u32 cur_hid_dev, struct amdtp_cl_data *cli_data)
|
||||||
|
|
||||||
hid->driver_data = hid_data;
|
hid->driver_data = hid_data;
|
||||||
cli_data->hid_sensor_hubs[cur_hid_dev] = hid;
|
cli_data->hid_sensor_hubs[cur_hid_dev] = hid;
|
||||||
hid->bus = BUS_AMD_AMDTP;
|
strscpy(hid->phys, dev->driver ? dev->driver->name : dev_name(dev),
|
||||||
|
sizeof(hid->phys));
|
||||||
|
hid->bus = BUS_AMD_SFH;
|
||||||
hid->vendor = AMD_SFH_HID_VENDOR;
|
hid->vendor = AMD_SFH_HID_VENDOR;
|
||||||
hid->product = AMD_SFH_HID_PRODUCT;
|
hid->product = AMD_SFH_HID_PRODUCT;
|
||||||
snprintf(hid->name, sizeof(hid->name), "%s %04X:%04X", "hid-amdtp",
|
snprintf(hid->name, sizeof(hid->name), "%s %04X:%04X", "hid-amdsfh",
|
||||||
hid->vendor, hid->product);
|
hid->vendor, hid->product);
|
||||||
|
|
||||||
rc = hid_add_device(hid);
|
rc = hid_add_device(hid);
|
||||||
|
|
|
@ -12,7 +12,6 @@
|
||||||
#define AMDSFH_HID_H
|
#define AMDSFH_HID_H
|
||||||
|
|
||||||
#define MAX_HID_DEVICES 5
|
#define MAX_HID_DEVICES 5
|
||||||
#define BUS_AMD_AMDTP 0x20
|
|
||||||
#define AMD_SFH_HID_VENDOR 0x1022
|
#define AMD_SFH_HID_VENDOR 0x1022
|
||||||
#define AMD_SFH_HID_PRODUCT 0x0001
|
#define AMD_SFH_HID_PRODUCT 0x0001
|
||||||
|
|
||||||
|
|
|
@ -130,6 +130,12 @@ static int amd_sfh_irq_init_v2(struct amd_mp2_dev *privdata)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int amd_sfh_dis_sts_v2(struct amd_mp2_dev *privdata)
|
||||||
|
{
|
||||||
|
return (readl(privdata->mmio + AMD_P2C_MSG(1)) &
|
||||||
|
SENSOR_DISCOVERY_STATUS_MASK) >> SENSOR_DISCOVERY_STATUS_SHIFT;
|
||||||
|
}
|
||||||
|
|
||||||
void amd_start_sensor(struct amd_mp2_dev *privdata, struct amd_mp2_sensor_info info)
|
void amd_start_sensor(struct amd_mp2_dev *privdata, struct amd_mp2_sensor_info info)
|
||||||
{
|
{
|
||||||
union sfh_cmd_param cmd_param;
|
union sfh_cmd_param cmd_param;
|
||||||
|
@ -245,6 +251,7 @@ static const struct amd_mp2_ops amd_sfh_ops_v2 = {
|
||||||
.response = amd_sfh_wait_response_v2,
|
.response = amd_sfh_wait_response_v2,
|
||||||
.clear_intr = amd_sfh_clear_intr_v2,
|
.clear_intr = amd_sfh_clear_intr_v2,
|
||||||
.init_intr = amd_sfh_irq_init_v2,
|
.init_intr = amd_sfh_irq_init_v2,
|
||||||
|
.discovery_status = amd_sfh_dis_sts_v2,
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct amd_mp2_ops amd_sfh_ops = {
|
static const struct amd_mp2_ops amd_sfh_ops = {
|
||||||
|
@ -346,8 +353,9 @@ static int __maybe_unused amd_mp2_pci_resume(struct device *dev)
|
||||||
(mp2, cl_data->sensor_idx[i], SENSOR_ENABLED);
|
(mp2, cl_data->sensor_idx[i], SENSOR_ENABLED);
|
||||||
if (status == SENSOR_ENABLED)
|
if (status == SENSOR_ENABLED)
|
||||||
cl_data->sensor_sts[i] = SENSOR_ENABLED;
|
cl_data->sensor_sts[i] = SENSOR_ENABLED;
|
||||||
dev_dbg(dev, "resume sid 0x%x status 0x%x\n",
|
dev_dbg(dev, "suspend sid 0x%x (%s) status 0x%x\n",
|
||||||
cl_data->sensor_idx[i], cl_data->sensor_sts[i]);
|
cl_data->sensor_idx[i], get_sensor_name(cl_data->sensor_idx[i]),
|
||||||
|
cl_data->sensor_sts[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -371,8 +379,9 @@ static int __maybe_unused amd_mp2_pci_suspend(struct device *dev)
|
||||||
(mp2, cl_data->sensor_idx[i], SENSOR_DISABLED);
|
(mp2, cl_data->sensor_idx[i], SENSOR_DISABLED);
|
||||||
if (status != SENSOR_ENABLED)
|
if (status != SENSOR_ENABLED)
|
||||||
cl_data->sensor_sts[i] = SENSOR_DISABLED;
|
cl_data->sensor_sts[i] = SENSOR_DISABLED;
|
||||||
dev_dbg(dev, "suspend sid 0x%x status 0x%x\n",
|
dev_dbg(dev, "suspend sid 0x%x (%s) status 0x%x\n",
|
||||||
cl_data->sensor_idx[i], cl_data->sensor_sts[i]);
|
cl_data->sensor_idx[i], get_sensor_name(cl_data->sensor_idx[i]),
|
||||||
|
cl_data->sensor_sts[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -39,6 +39,9 @@
|
||||||
|
|
||||||
#define AMD_SFH_IDLE_LOOP 200
|
#define AMD_SFH_IDLE_LOOP 200
|
||||||
|
|
||||||
|
#define SENSOR_DISCOVERY_STATUS_MASK GENMASK(5, 3)
|
||||||
|
#define SENSOR_DISCOVERY_STATUS_SHIFT 3
|
||||||
|
|
||||||
/* SFH Command register */
|
/* SFH Command register */
|
||||||
union sfh_cmd_base {
|
union sfh_cmd_base {
|
||||||
u32 ul;
|
u32 ul;
|
||||||
|
@ -135,6 +138,7 @@ 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);
|
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_suspend(struct amd_mp2_dev *mp2);
|
||||||
void amd_mp2_resume(struct amd_mp2_dev *mp2);
|
void amd_mp2_resume(struct amd_mp2_dev *mp2);
|
||||||
|
const char *get_sensor_name(int idx);
|
||||||
|
|
||||||
struct amd_mp2_ops {
|
struct amd_mp2_ops {
|
||||||
void (*start)(struct amd_mp2_dev *privdata, struct amd_mp2_sensor_info info);
|
void (*start)(struct amd_mp2_dev *privdata, struct amd_mp2_sensor_info info);
|
||||||
|
@ -143,5 +147,6 @@ struct amd_mp2_ops {
|
||||||
int (*response)(struct amd_mp2_dev *mp2, u8 sid, u32 sensor_sts);
|
int (*response)(struct amd_mp2_dev *mp2, u8 sid, u32 sensor_sts);
|
||||||
void (*clear_intr)(struct amd_mp2_dev *privdata);
|
void (*clear_intr)(struct amd_mp2_dev *privdata);
|
||||||
int (*init_intr)(struct amd_mp2_dev *privdata);
|
int (*init_intr)(struct amd_mp2_dev *privdata);
|
||||||
|
int (*discovery_status)(struct amd_mp2_dev *privdata);
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -179,7 +179,7 @@ static const u8 accel3_report_descriptor[] = {
|
||||||
0xC0 /* HID end collection */
|
0xC0 /* HID end collection */
|
||||||
};
|
};
|
||||||
|
|
||||||
const u8 gyro3_report_descriptor[] = {
|
static const u8 gyro3_report_descriptor[] = {
|
||||||
0x05, 0x20, /* Usage page */
|
0x05, 0x20, /* Usage page */
|
||||||
0x09, 0x76, /* Motion type Gyro3D */
|
0x09, 0x76, /* Motion type Gyro3D */
|
||||||
0xA1, 0x00, /* HID Collection (Physical) */
|
0xA1, 0x00, /* HID Collection (Physical) */
|
||||||
|
@ -340,7 +340,7 @@ const u8 gyro3_report_descriptor[] = {
|
||||||
0xC0, /* HID end collection */
|
0xC0, /* HID end collection */
|
||||||
};
|
};
|
||||||
|
|
||||||
const u8 comp3_report_descriptor[] = {
|
static const u8 comp3_report_descriptor[] = {
|
||||||
0x05, 0x20, /* Usage page */
|
0x05, 0x20, /* Usage page */
|
||||||
0x09, 0x83, /* Motion type Orientation compass 3D */
|
0x09, 0x83, /* Motion type Orientation compass 3D */
|
||||||
0xA1, 0x00, /* HID Collection (Physical) */
|
0xA1, 0x00, /* HID Collection (Physical) */
|
||||||
|
@ -512,7 +512,7 @@ const u8 comp3_report_descriptor[] = {
|
||||||
0xC0 /* HID end collection */
|
0xC0 /* HID end collection */
|
||||||
};
|
};
|
||||||
|
|
||||||
const u8 als_report_descriptor[] = {
|
static const u8 als_report_descriptor[] = {
|
||||||
0x05, 0x20, /* HID usage page sensor */
|
0x05, 0x20, /* HID usage page sensor */
|
||||||
0x09, 0x41, /* HID usage sensor type Ambientlight */
|
0x09, 0x41, /* HID usage sensor type Ambientlight */
|
||||||
0xA1, 0x00, /* HID Collection (Physical) */
|
0xA1, 0x00, /* HID Collection (Physical) */
|
||||||
|
|
|
@ -2222,6 +2222,10 @@ int hid_connect(struct hid_device *hdev, unsigned int connect_mask)
|
||||||
case BUS_VIRTUAL:
|
case BUS_VIRTUAL:
|
||||||
bus = "VIRTUAL";
|
bus = "VIRTUAL";
|
||||||
break;
|
break;
|
||||||
|
case BUS_INTEL_ISHTP:
|
||||||
|
case BUS_AMD_SFH:
|
||||||
|
bus = "SENSOR HUB";
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
bus = "<UNKNOWN>";
|
bus = "<UNKNOWN>";
|
||||||
}
|
}
|
||||||
|
|
|
@ -271,6 +271,7 @@ struct input_mask {
|
||||||
#define BUS_RMI 0x1D
|
#define BUS_RMI 0x1D
|
||||||
#define BUS_CEC 0x1E
|
#define BUS_CEC 0x1E
|
||||||
#define BUS_INTEL_ISHTP 0x1F
|
#define BUS_INTEL_ISHTP 0x1F
|
||||||
|
#define BUS_AMD_SFH 0x20
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* MT_TOOL types
|
* MT_TOOL types
|
||||||
|
|
Загрузка…
Ссылка в новой задаче