Skip to content

Commit

Permalink
HID: amd_sfh: Extend ALS support for newer AMD platform
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Basavaraj Natikar authored and Jiri Kosina committed Jun 24, 2021
1 parent f264481 commit 0aad9c9
Show file tree
Hide file tree
Showing 6 changed files with 45 additions and 26 deletions.
39 changes: 18 additions & 21 deletions drivers/hid/amd-sfh-hid/amd_sfh_client.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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");
}
Expand All @@ -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;
Expand All @@ -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;
Expand All @@ -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;
}
Expand All @@ -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++)
Expand All @@ -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]);
}
}
Expand Down
10 changes: 8 additions & 2 deletions drivers/hid/amd-sfh-hid/amd_sfh_hid.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,11 @@
#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;
Expand All @@ -26,16 +31,15 @@ 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];
u8 report_type[MAX_HID_DEVICES];
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;
};
Expand Down Expand Up @@ -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
5 changes: 5 additions & 0 deletions drivers/hid/amd-sfh-hid/amd_sfh_pcie.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
2 changes: 2 additions & 0 deletions drivers/hid/amd-sfh-hid/amd_sfh_pcie.h
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down Expand Up @@ -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;
};
Expand Down
14 changes: 12 additions & 2 deletions drivers/hid/amd-sfh-hid/hid_descriptor/amd_sfh_hid_desc.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand Down
1 change: 0 additions & 1 deletion drivers/hid/amd-sfh-hid/hid_descriptor/amd_sfh_hid_desc.h
Original file line number Diff line number Diff line change
Expand Up @@ -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

0 comments on commit 0aad9c9

Please sign in to comment.