summaryrefslogtreecommitdiff
path: root/sys-kernel/linux-sources-redcore-lts-legacy/files/5.10-add-amd-sfh-hid_driver.patch
diff options
context:
space:
mode:
Diffstat (limited to 'sys-kernel/linux-sources-redcore-lts-legacy/files/5.10-add-amd-sfh-hid_driver.patch')
-rw-r--r--sys-kernel/linux-sources-redcore-lts-legacy/files/5.10-add-amd-sfh-hid_driver.patch1783
1 files changed, 1783 insertions, 0 deletions
diff --git a/sys-kernel/linux-sources-redcore-lts-legacy/files/5.10-add-amd-sfh-hid_driver.patch b/sys-kernel/linux-sources-redcore-lts-legacy/files/5.10-add-amd-sfh-hid_driver.patch
new file mode 100644
index 00000000..dd8badee
--- /dev/null
+++ b/sys-kernel/linux-sources-redcore-lts-legacy/files/5.10-add-amd-sfh-hid_driver.patch
@@ -0,0 +1,1783 @@
+diff -Naur linux-5.10.2/drivers/hid/amd-sfh-hid/amd_sfh_client.c linux-5.10.2-amd/drivers/hid/amd-sfh-hid/amd_sfh_client.c
+--- linux-5.10.2/drivers/hid/amd-sfh-hid/amd_sfh_client.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-5.10.2-amd/drivers/hid/amd-sfh-hid/amd_sfh_client.c 2020-12-25 14:25:44.298391979 +0100
+@@ -0,0 +1,246 @@
++// SPDX-License-Identifier: GPL-2.0-or-later
++/*
++ * AMD SFH Client Layer
++ * Copyright 2020 Advanced Micro Devices, Inc.
++ * Authors: Nehal Bakulchandra Shah <Nehal-Bakulchandra.Shah@amd.com>
++ * Sandeep Singh <Sandeep.singh@amd.com>
++ */
++
++#include <linux/dma-mapping.h>
++#include <linux/hid.h>
++#include <linux/list.h>
++#include <linux/slab.h>
++#include <linux/workqueue.h>
++#include <linux/errno.h>
++
++#include "hid_descriptor/amd_sfh_hid_desc.h"
++#include "amd_sfh_pcie.h"
++#include "amd_sfh_hid.h"
++
++#define AMD_SFH_IDLE_LOOP 200
++
++struct request_list {
++ struct hid_device *hid;
++ struct list_head list;
++ u8 report_id;
++ u8 sensor_idx;
++ u8 report_type;
++ u8 current_index;
++};
++
++static struct request_list req_list;
++
++void amd_sfh_set_report(struct hid_device *hid, int report_id,
++ int report_type)
++{
++ struct amdtp_hid_data *hid_data = hid->driver_data;
++ struct amdtp_cl_data *cli_data = hid_data->cli_data;
++ int i;
++
++ for (i = 0; i < cli_data->num_hid_devices; i++) {
++ if (cli_data->hid_sensor_hubs[i] == hid) {
++ cli_data->cur_hid_dev = i;
++ break;
++ }
++ }
++ amdtp_hid_wakeup(hid);
++}
++
++int amd_sfh_get_report(struct hid_device *hid, int report_id, int report_type)
++{
++ struct amdtp_hid_data *hid_data = hid->driver_data;
++ struct amdtp_cl_data *cli_data = hid_data->cli_data;
++ int i;
++
++ for (i = 0; i < cli_data->num_hid_devices; i++) {
++ if (cli_data->hid_sensor_hubs[i] == hid) {
++ struct request_list *new = kzalloc(sizeof(*new), GFP_KERNEL);
++
++ if (!new)
++ return -ENOMEM;
++
++ new->current_index = i;
++ new->sensor_idx = cli_data->sensor_idx[i];
++ new->hid = hid;
++ new->report_type = report_type;
++ new->report_id = report_id;
++ cli_data->report_id[i] = report_id;
++ cli_data->request_done[i] = false;
++ list_add(&new->list, &req_list.list);
++ break;
++ }
++ }
++ schedule_delayed_work(&cli_data->work, 0);
++ return 0;
++}
++
++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 request_list *req_node;
++ u8 current_index, sensor_index;
++ u8 report_id, node_type;
++ u8 report_size = 0;
++
++ req_node = list_last_entry(&req_list.list, struct request_list, list);
++ list_del(&req_node->list);
++ current_index = req_node->current_index;
++ sensor_index = req_node->sensor_idx;
++ report_id = req_node->report_id;
++ node_type = req_node->report_type;
++
++ if (node_type == HID_FEATURE_REPORT) {
++ report_size = get_feature_report(sensor_index, report_id,
++ cli_data->feature_report[current_index]);
++ if (report_size)
++ hid_input_report(cli_data->hid_sensor_hubs[current_index],
++ cli_data->report_type[current_index],
++ cli_data->feature_report[current_index], report_size, 0);
++ else
++ 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]);
++ 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);
++ else
++ pr_err("AMDSFH: Invalid report size\n");
++ }
++ cli_data->cur_hid_dev = current_index;
++ cli_data->sensor_requested_cnt[current_index] = 0;
++ amdtp_hid_wakeup(cli_data->hid_sensor_hubs[current_index]);
++}
++
++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);
++ 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]);
++ hid_input_report(cli_data->hid_sensor_hubs[i], HID_INPUT_REPORT,
++ cli_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 amdtp_cl_data *cl_data = privdata->cl_data;
++ struct amd_mp2_sensor_info info;
++ struct device *dev;
++ u32 feature_report_size;
++ u32 input_report_size;
++ u8 cl_idx;
++ int rc, i;
++
++ dev = &privdata->pdev->dev;
++ cl_data = kzalloc(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);
++
++ for (i = 0; i < cl_data->num_hid_devices; i++) {
++ cl_data->sensor_virt_addr[i] = dma_alloc_coherent(dev, sizeof(int) * 8,
++ &cl_data->sensor_phys_addr[i],
++ GFP_KERNEL);
++ cl_data->sensor_sts[i] = 0;
++ cl_data->sensor_requested_cnt[i] = 0;
++ cl_data->cur_hid_dev = i;
++ cl_idx = cl_data->sensor_idx[i];
++ cl_data->report_descr_sz[i] = get_descr_sz(cl_idx, descr_size);
++ if (!cl_data->report_descr_sz[i]) {
++ rc = -EINVAL;
++ goto cleanup;
++ }
++ feature_report_size = get_descr_sz(cl_idx, feature_size);
++ if (!feature_report_size) {
++ rc = -EINVAL;
++ goto cleanup;
++ }
++ input_report_size = get_descr_sz(cl_idx, input_size);
++ if (!input_report_size) {
++ rc = -EINVAL;
++ goto cleanup;
++ }
++ cl_data->feature_report[i] = kzalloc(feature_report_size, GFP_KERNEL);
++ if (!cl_data->feature_report[i]) {
++ rc = -ENOMEM;
++ goto cleanup;
++ }
++ cl_data->input_report[i] = kzalloc(input_report_size, GFP_KERNEL);
++ if (!cl_data->input_report[i]) {
++ rc = -ENOMEM;
++ goto cleanup;
++ }
++ info.period = msecs_to_jiffies(AMD_SFH_IDLE_LOOP);
++ info.sensor_idx = cl_idx;
++ info.phys_address = cl_data->sensor_phys_addr[i];
++
++ cl_data->report_descr[i] = kzalloc(cl_data->report_descr_sz[i], GFP_KERNEL);
++ if (!cl_data->report_descr[i]) {
++ rc = -ENOMEM;
++ goto cleanup;
++ }
++ rc = get_report_descriptor(cl_idx, cl_data->report_descr[i]);
++ if (rc)
++ return rc;
++ rc = amdtp_hid_probe(cl_data->cur_hid_dev, cl_data);
++ if (rc)
++ return rc;
++ amd_start_sensor(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]) {
++ dma_free_coherent(&privdata->pdev->dev, 8 * sizeof(int),
++ cl_data->sensor_virt_addr[i],
++ cl_data->sensor_phys_addr[i]);
++ }
++ kfree(cl_data->feature_report[i]);
++ kfree(cl_data->input_report[i]);
++ kfree(cl_data->report_descr[i]);
++ }
++ kfree(cl_data);
++ return rc;
++}
++
++int amd_sfh_hid_client_deinit(struct amd_mp2_dev *privdata)
++{
++ struct amdtp_cl_data *cl_data = privdata->cl_data;
++ int i;
++
++ for (i = 0; i < cl_data->num_hid_devices; i++)
++ amd_stop_sensor(privdata, i);
++
++ cancel_delayed_work_sync(&cl_data->work);
++ cancel_delayed_work_sync(&cl_data->work_buffer);
++ amdtp_hid_remove(cl_data);
++
++ for (i = 0; i < cl_data->num_hid_devices; i++) {
++ if (cl_data->sensor_virt_addr[i]) {
++ dma_free_coherent(&privdata->pdev->dev, 8 * sizeof(int),
++ cl_data->sensor_virt_addr[i],
++ cl_data->sensor_phys_addr[i]);
++ }
++ }
++ kfree(cl_data);
++ return 0;
++}
+diff -Naur linux-5.10.2/drivers/hid/amd-sfh-hid/amd_sfh_hid.c linux-5.10.2-amd/drivers/hid/amd-sfh-hid/amd_sfh_hid.c
+--- linux-5.10.2/drivers/hid/amd-sfh-hid/amd_sfh_hid.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-5.10.2-amd/drivers/hid/amd-sfh-hid/amd_sfh_hid.c 2020-12-25 14:25:44.298391979 +0100
+@@ -0,0 +1,174 @@
++// SPDX-License-Identifier: GPL-2.0-or-later
++/*
++ * AMD MP2 Sensors transport driver
++ *
++ * Authors: Nehal Bakulchandra Shah <Nehal-bakulchandra.shah@amd.com>
++ * Sandeep Singh <sandeep.singh@amd.com>
++ */
++#include <linux/hid.h>
++#include <linux/wait.h>
++#include <linux/sched.h>
++
++#include "amd_sfh_hid.h"
++
++#define AMD_SFH_RESPONSE_TIMEOUT 1500
++
++/**
++ * amdtp_hid_parse() - hid-core .parse() callback
++ * @hid: hid device instance
++ *
++ * This function gets called during call to hid_add_device
++ *
++ * Return: 0 on success and non zero on error
++ */
++static int amdtp_hid_parse(struct hid_device *hid)
++{
++ struct amdtp_hid_data *hid_data = hid->driver_data;
++ struct amdtp_cl_data *cli_data = hid_data->cli_data;
++
++ return hid_parse_report(hid, cli_data->report_descr[hid_data->index],
++ cli_data->report_descr_sz[hid_data->index]);
++}
++
++/* Empty callbacks with success return code */
++static int amdtp_hid_start(struct hid_device *hid)
++{
++ return 0;
++}
++
++static void amdtp_hid_stop(struct hid_device *hid)
++{
++}
++
++static int amdtp_hid_open(struct hid_device *hid)
++{
++ return 0;
++}
++
++static void amdtp_hid_close(struct hid_device *hid)
++{
++}
++
++static int amdtp_raw_request(struct hid_device *hdev, u8 reportnum,
++ u8 *buf, size_t len, u8 rtype, int reqtype)
++{
++ return 0;
++}
++
++static void amdtp_hid_request(struct hid_device *hid, struct hid_report *rep, int reqtype)
++{
++ int rc;
++
++ switch (reqtype) {
++ case HID_REQ_GET_REPORT:
++ rc = amd_sfh_get_report(hid, rep->id, rep->type);
++ if (rc)
++ dev_err(&hid->dev, "AMDSFH get report error\n");
++ break;
++ case HID_REQ_SET_REPORT:
++ amd_sfh_set_report(hid, rep->id, reqtype);
++ break;
++ default:
++ break;
++ }
++}
++
++static int amdtp_wait_for_response(struct hid_device *hid)
++{
++ struct amdtp_hid_data *hid_data = hid->driver_data;
++ struct amdtp_cl_data *cli_data = hid_data->cli_data;
++ int i, ret = 0;
++
++ for (i = 0; i < cli_data->num_hid_devices; i++) {
++ if (cli_data->hid_sensor_hubs[i] == hid)
++ break;
++ }
++
++ if (!cli_data->request_done[i])
++ ret = wait_event_interruptible_timeout(hid_data->hid_wait,
++ cli_data->request_done[i],
++ msecs_to_jiffies(AMD_SFH_RESPONSE_TIMEOUT));
++ if (ret == -ERESTARTSYS)
++ return -ERESTARTSYS;
++ else if (ret < 0)
++ return -ETIMEDOUT;
++ else
++ return 0;
++}
++
++void amdtp_hid_wakeup(struct hid_device *hid)
++{
++ struct amdtp_hid_data *hid_data = hid->driver_data;
++ struct amdtp_cl_data *cli_data = hid_data->cli_data;
++
++ cli_data->request_done[cli_data->cur_hid_dev] = true;
++ wake_up_interruptible(&hid_data->hid_wait);
++}
++
++static struct hid_ll_driver amdtp_hid_ll_driver = {
++ .parse = amdtp_hid_parse,
++ .start = amdtp_hid_start,
++ .stop = amdtp_hid_stop,
++ .open = amdtp_hid_open,
++ .close = amdtp_hid_close,
++ .request = amdtp_hid_request,
++ .wait = amdtp_wait_for_response,
++ .raw_request = amdtp_raw_request,
++};
++
++int amdtp_hid_probe(u32 cur_hid_dev, struct amdtp_cl_data *cli_data)
++{
++ struct hid_device *hid;
++ struct amdtp_hid_data *hid_data;
++ int rc;
++
++ hid = hid_allocate_device();
++ if (IS_ERR(hid))
++ return PTR_ERR(hid);
++
++ hid_data = kzalloc(sizeof(*hid_data), GFP_KERNEL);
++ if (!hid_data) {
++ rc = -ENOMEM;
++ goto err_hid_data;
++ }
++
++ hid->ll_driver = &amdtp_hid_ll_driver;
++ hid_data->index = cur_hid_dev;
++ hid_data->cli_data = cli_data;
++ init_waitqueue_head(&hid_data->hid_wait);
++
++ hid->driver_data = hid_data;
++ cli_data->hid_sensor_hubs[cur_hid_dev] = hid;
++ hid->bus = BUS_AMD_AMDTP;
++ hid->vendor = AMD_SFH_HID_VENDOR;
++ hid->product = AMD_SFH_HID_PRODUCT;
++ snprintf(hid->name, sizeof(hid->name), "%s %04X:%04X", "hid-amdtp",
++ hid->vendor, hid->product);
++
++ rc = hid_add_device(hid);
++ if (rc)
++ goto err_hid_device;
++ return 0;
++
++err_hid_device:
++ kfree(hid_data);
++err_hid_data:
++ hid_destroy_device(hid);
++ return rc;
++}
++
++void amdtp_hid_remove(struct amdtp_cl_data *cli_data)
++{
++ int i;
++
++ for (i = 0; i < cli_data->num_hid_devices; ++i) {
++ kfree(cli_data->feature_report[i]);
++ kfree(cli_data->input_report[i]);
++ kfree(cli_data->report_descr[i]);
++ if (cli_data->hid_sensor_hubs[i]) {
++ kfree(cli_data->hid_sensor_hubs[i]->driver_data);
++ hid_destroy_device(cli_data->hid_sensor_hubs[i]);
++ cli_data->hid_sensor_hubs[i] = NULL;
++ }
++ }
++}
+diff -Naur linux-5.10.2/drivers/hid/amd-sfh-hid/amd_sfh_hid.h linux-5.10.2-amd/drivers/hid/amd-sfh-hid/amd_sfh_hid.h
+--- linux-5.10.2/drivers/hid/amd-sfh-hid/amd_sfh_hid.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-5.10.2-amd/drivers/hid/amd-sfh-hid/amd_sfh_hid.h 2020-12-25 14:25:44.299391977 +0100
+@@ -0,0 +1,67 @@
++/* SPDX-License-Identifier: GPL-2.0-or-later */
++/*
++ * AMD MP2 Sensors transport driver
++ *
++ * Authors: Nehal Bakulchandra Shah <Nehal-bakulchandra.shah@amd.com>
++ * Sandeep Singh <sandeep.singh@amd.com>
++ */
++
++#ifndef AMDSFH_HID_H
++#define AMDSFH_HID_H
++
++#define MAX_HID_DEVICES 4
++#define BUS_AMD_AMDTP 0x20
++#define AMD_SFH_HID_VENDOR 0x1022
++#define AMD_SFH_HID_PRODUCT 0x0001
++
++struct amdtp_cl_data {
++ u8 init_done;
++ u32 cur_hid_dev;
++ u32 hid_dev_count;
++ u32 num_hid_devices;
++ struct device_info *hid_devices;
++ u8 *report_descr[MAX_HID_DEVICES];
++ int report_descr_sz[MAX_HID_DEVICES];
++ struct hid_device *hid_sensor_hubs[MAX_HID_DEVICES];
++ 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];
++ phys_addr_t sensor_phys_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 delayed_work work;
++ struct delayed_work work_buffer;
++};
++
++/**
++ * struct amdtp_hid_data - Per instance HID data
++ * @index: Device index in the order of enumeration
++ * @request_done: Get Feature/Input report complete flag
++ * used during get/set request from hid core
++ * @cli_data: Link to the client instance
++ * @hid_wait: Completion waitq
++ *
++ * Used to tie hid->driver data to driver client instance
++ */
++struct amdtp_hid_data {
++ int index;
++ struct amdtp_cl_data *cli_data;
++ wait_queue_head_t hid_wait;
++};
++
++/* 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);
++void amd_sfh_set_report(struct hid_device *hid, int report_id, int report_type);
++void amdtp_hid_wakeup(struct hid_device *hid);
++#endif
+diff -Naur linux-5.10.2/drivers/hid/amd-sfh-hid/amd_sfh_pcie.c linux-5.10.2-amd/drivers/hid/amd-sfh-hid/amd_sfh_pcie.c
+--- linux-5.10.2/drivers/hid/amd-sfh-hid/amd_sfh_pcie.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-5.10.2-amd/drivers/hid/amd-sfh-hid/amd_sfh_pcie.c 2020-12-25 14:25:44.299391977 +0100
+@@ -0,0 +1,152 @@
++// SPDX-License-Identifier: GPL-2.0-or-later
++/*
++ * AMD MP2 PCIe communication driver
++ * Copyright 2020 Advanced Micro Devices, Inc.
++ *
++ * Authors: Shyam Sundar S K <Shyam-sundar.S-k@amd.com>
++ * Sandeep Singh <Sandeep.singh@amd.com>
++ */
++
++#include <linux/bitops.h>
++#include <linux/delay.h>
++#include <linux/dma-mapping.h>
++#include <linux/interrupt.h>
++#include <linux/io-64-nonatomic-lo-hi.h>
++#include <linux/module.h>
++#include <linux/slab.h>
++
++#include "amd_sfh_pcie.h"
++
++#define DRIVER_NAME "pcie_mp2_amd"
++#define DRIVER_DESC "AMD(R) PCIe MP2 Communication Driver"
++
++#define ACEL_EN BIT(0)
++#define GYRO_EN BIT(1)
++#define MAGNO_EN BIT(2)
++#define ALS_EN BIT(19)
++
++void amd_start_sensor(struct amd_mp2_dev *privdata, struct amd_mp2_sensor_info info)
++{
++ union sfh_cmd_param cmd_param;
++ union sfh_cmd_base cmd_base;
++
++ /* fill up command register */
++ memset(&cmd_base, 0, sizeof(cmd_base));
++ cmd_base.s.cmd_id = ENABLE_SENSOR;
++ cmd_base.s.period = info.period;
++ cmd_base.s.sensor_id = info.sensor_idx;
++
++ /* fill up command param register */
++ memset(&cmd_param, 0, sizeof(cmd_param));
++ cmd_param.s.buf_layout = 1;
++ cmd_param.s.buf_length = 16;
++
++ writeq(info.phys_address, privdata->mmio + AMD_C2P_MSG2);
++ writel(cmd_param.ul, privdata->mmio + AMD_C2P_MSG1);
++ writel(cmd_base.ul, privdata->mmio + AMD_C2P_MSG0);
++}
++
++void amd_stop_sensor(struct amd_mp2_dev *privdata, u16 sensor_idx)
++{
++ union sfh_cmd_base cmd_base;
++
++ /* fill up command register */
++ memset(&cmd_base, 0, sizeof(cmd_base));
++ cmd_base.s.cmd_id = DISABLE_SENSOR;
++ cmd_base.s.period = 0;
++ cmd_base.s.sensor_id = sensor_idx;
++
++ writeq(0x0, privdata->mmio + AMD_C2P_MSG2);
++ writel(cmd_base.ul, privdata->mmio + AMD_C2P_MSG0);
++}
++
++void amd_stop_all_sensors(struct amd_mp2_dev *privdata)
++{
++ union sfh_cmd_base cmd_base;
++
++ /* fill up command register */
++ memset(&cmd_base, 0, sizeof(cmd_base));
++ cmd_base.s.cmd_id = STOP_ALL_SENSORS;
++ cmd_base.s.period = 0;
++ cmd_base.s.sensor_id = 0;
++
++ writel(cmd_base.ul, privdata->mmio + AMD_C2P_MSG0);
++}
++
++int amd_mp2_get_sensor_num(struct amd_mp2_dev *privdata, u8 *sensor_id)
++{
++ int activestatus, num_of_sensors = 0;
++
++ privdata->activecontrolstatus = readl(privdata->mmio + AMD_P2C_MSG3);
++ activestatus = privdata->activecontrolstatus >> 4;
++ if (ACEL_EN & activestatus)
++ sensor_id[num_of_sensors++] = accel_idx;
++
++ if (GYRO_EN & activestatus)
++ sensor_id[num_of_sensors++] = gyro_idx;
++
++ if (MAGNO_EN & activestatus)
++ sensor_id[num_of_sensors++] = mag_idx;
++
++ if (ALS_EN & activestatus)
++ sensor_id[num_of_sensors++] = als_idx;
++
++ return num_of_sensors;
++}
++
++static void amd_mp2_pci_remove(void *privdata)
++{
++ amd_sfh_hid_client_deinit(privdata);
++ amd_stop_all_sensors(privdata);
++}
++
++static int amd_mp2_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
++{
++ struct amd_mp2_dev *privdata;
++ int rc;
++
++ privdata = devm_kzalloc(&pdev->dev, sizeof(*privdata), GFP_KERNEL);
++ if (!privdata)
++ return -ENOMEM;
++
++ privdata->pdev = pdev;
++ pci_set_drvdata(pdev, privdata);
++ rc = pcim_enable_device(pdev);
++ if (rc)
++ return rc;
++
++ rc = pcim_iomap_regions(pdev, BIT(2), DRIVER_NAME);
++ if (rc)
++ return rc;
++
++ privdata->mmio = pcim_iomap_table(pdev)[2];
++ pci_set_master(pdev);
++ rc = pci_set_dma_mask(pdev, DMA_BIT_MASK(64));
++ if (rc) {
++ rc = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
++ return rc;
++ }
++ rc = devm_add_action_or_reset(&pdev->dev, amd_mp2_pci_remove, privdata);
++ if (rc)
++ return rc;
++
++ return amd_sfh_hid_client_init(privdata);
++}
++
++static const struct pci_device_id amd_mp2_pci_tbl[] = {
++ { PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_MP2) },
++ { }
++};
++MODULE_DEVICE_TABLE(pci, amd_mp2_pci_tbl);
++
++static struct pci_driver amd_mp2_pci_driver = {
++ .name = DRIVER_NAME,
++ .id_table = amd_mp2_pci_tbl,
++ .probe = amd_mp2_pci_probe,
++};
++module_pci_driver(amd_mp2_pci_driver);
++
++MODULE_DESCRIPTION(DRIVER_DESC);
++MODULE_LICENSE("Dual BSD/GPL");
++MODULE_AUTHOR("Shyam Sundar S K <Shyam-sundar.S-k@amd.com>");
++MODULE_AUTHOR("Sandeep Singh <Sandeep.singh@amd.com>");
+diff -Naur linux-5.10.2/drivers/hid/amd-sfh-hid/amd_sfh_pcie.h linux-5.10.2-amd/drivers/hid/amd-sfh-hid/amd_sfh_pcie.h
+--- linux-5.10.2/drivers/hid/amd-sfh-hid/amd_sfh_pcie.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-5.10.2-amd/drivers/hid/amd-sfh-hid/amd_sfh_pcie.h 2020-12-25 14:25:44.299391977 +0100
+@@ -0,0 +1,79 @@
++/* SPDX-License-Identifier: GPL-2.0-or-later */
++/*
++ * AMD MP2 PCIe communication driver
++ * Copyright 2020 Advanced Micro Devices, Inc.
++ * Authors: Shyam Sundar S K <Shyam-sundar.S-k@amd.com>
++ * Sandeep Singh <Sandeep.singh@amd.com>
++ */
++
++#ifndef PCIE_MP2_AMD_H
++#define PCIE_MP2_AMD_H
++
++#include <linux/pci.h>
++
++#define PCI_DEVICE_ID_AMD_MP2 0x15E4
++
++#define ENABLE_SENSOR 1
++#define DISABLE_SENSOR 2
++#define STOP_ALL_SENSORS 8
++
++/* MP2 C2P Message Registers */
++#define AMD_C2P_MSG0 0x10500
++#define AMD_C2P_MSG1 0x10504
++#define AMD_C2P_MSG2 0x10508
++
++/* MP2 P2C Message Registers */
++#define AMD_P2C_MSG3 0x1068C /* Supported Sensors info */
++
++/* SFH Command register */
++union sfh_cmd_base {
++ u32 ul;
++ struct {
++ u32 cmd_id : 8;
++ u32 sensor_id : 8;
++ u32 period : 16;
++ } s;
++};
++
++union sfh_cmd_param {
++ u32 ul;
++ struct {
++ u32 buf_layout : 2;
++ u32 buf_length : 6;
++ u32 rsvd : 24;
++ } s;
++};
++
++struct sfh_cmd_reg {
++ union sfh_cmd_base cmd_base;
++ union sfh_cmd_param cmd_param;
++ phys_addr_t phys_addr;
++};
++
++enum sensor_idx {
++ accel_idx = 0,
++ gyro_idx = 1,
++ mag_idx = 2,
++ als_idx = 19
++};
++
++struct amd_mp2_dev {
++ struct pci_dev *pdev;
++ struct amdtp_cl_data *cl_data;
++ void __iomem *mmio;
++ u32 activecontrolstatus;
++};
++
++struct amd_mp2_sensor_info {
++ u8 sensor_idx;
++ u32 period;
++ phys_addr_t phys_address;
++};
++
++void amd_start_sensor(struct amd_mp2_dev *privdata, struct amd_mp2_sensor_info info);
++void amd_stop_sensor(struct amd_mp2_dev *privdata, u16 sensor_idx);
++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);
++#endif
+diff -Naur linux-5.10.2/drivers/hid/amd-sfh-hid/hid_descriptor/amd_sfh_hid_desc.c linux-5.10.2-amd/drivers/hid/amd-sfh-hid/hid_descriptor/amd_sfh_hid_desc.c
+--- linux-5.10.2/drivers/hid/amd-sfh-hid/hid_descriptor/amd_sfh_hid_desc.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-5.10.2-amd/drivers/hid/amd-sfh-hid/hid_descriptor/amd_sfh_hid_desc.c 2020-12-25 14:25:44.299391977 +0100
+@@ -0,0 +1,224 @@
++// SPDX-License-Identifier: GPL-2.0-or-later
++/*
++ * AMD SFH Report Descriptor generator
++ * Copyright 2020 Advanced Micro Devices, Inc.
++ * Authors: Nehal Bakulchandra Shah <Nehal-Bakulchandra.Shah@amd.com>
++ * Sandeep Singh <sandeep.singh@amd.com>
++ */
++
++#include <linux/kernel.h>
++#include <linux/string.h>
++#include <linux/slab.h>
++#include "amd_sfh_pcie.h"
++#include "amd_sfh_hid_desc.h"
++#include "amd_sfh_hid_report_desc.h"
++
++#define AMD_SFH_FW_MULTIPLIER (1000)
++#define HID_USAGE_SENSOR_PROP_REPORTING_STATE_ALL_EVENTS_ENUM 0x41
++#define HID_USAGE_SENSOR_PROP_POWER_STATE_D0_FULL_POWER_ENUM 0x51
++#define HID_DEFAULT_REPORT_INTERVAL 0x50
++#define HID_DEFAULT_MIN_VALUE 0X7F
++#define HID_DEFAULT_MAX_VALUE 0x80
++#define HID_DEFAULT_SENSITIVITY 0x7F
++#define HID_USAGE_SENSOR_PROPERTY_CONNECTION_TYPE_PC_INTEGRATED_ENUM 0x01
++/* state enums */
++#define HID_USAGE_SENSOR_STATE_READY_ENUM 0x02
++#define HID_USAGE_SENSOR_STATE_INITIALIZING_ENUM 0x05
++#define HID_USAGE_SENSOR_EVENT_DATA_UPDATED_ENUM 0x04
++
++int get_report_descriptor(int sensor_idx, u8 *rep_desc)
++{
++ switch (sensor_idx) {
++ case accel_idx: /* accel */
++ memset(rep_desc, 0, sizeof(accel3_report_descriptor));
++ memcpy(rep_desc, accel3_report_descriptor,
++ sizeof(accel3_report_descriptor));
++ break;
++ case gyro_idx: /* gyro */
++ memset(rep_desc, 0, sizeof(gyro3_report_descriptor));
++ memcpy(rep_desc, gyro3_report_descriptor,
++ sizeof(gyro3_report_descriptor));
++ break;
++ case mag_idx: /* Magnetometer */
++ memset(rep_desc, 0, sizeof(comp3_report_descriptor));
++ memcpy(rep_desc, comp3_report_descriptor,
++ sizeof(comp3_report_descriptor));
++ break;
++ case als_idx: /* ambient light sensor */
++ memset(rep_desc, 0, sizeof(als_report_descriptor));
++ memcpy(rep_desc, als_report_descriptor,
++ sizeof(als_report_descriptor));
++ break;
++ default:
++ break;
++ }
++ return 0;
++}
++
++u32 get_descr_sz(int sensor_idx, int descriptor_name)
++{
++ switch (sensor_idx) {
++ case accel_idx:
++ switch (descriptor_name) {
++ case descr_size:
++ return sizeof(accel3_report_descriptor);
++ case input_size:
++ return sizeof(struct accel3_input_report);
++ case feature_size:
++ return sizeof(struct accel3_feature_report);
++ }
++ break;
++ case gyro_idx:
++ switch (descriptor_name) {
++ case descr_size:
++ return sizeof(gyro3_report_descriptor);
++ case input_size:
++ return sizeof(struct gyro_input_report);
++ case feature_size:
++ return sizeof(struct gyro_feature_report);
++ }
++ break;
++ case mag_idx:
++ switch (descriptor_name) {
++ case descr_size:
++ return sizeof(comp3_report_descriptor);
++ case input_size:
++ return sizeof(struct magno_input_report);
++ case feature_size:
++ return sizeof(struct magno_feature_report);
++ }
++ break;
++ case als_idx:
++ switch (descriptor_name) {
++ case descr_size:
++ return sizeof(als_report_descriptor);
++ case input_size:
++ return sizeof(struct als_input_report);
++ case feature_size:
++ return sizeof(struct als_feature_report);
++ }
++ break;
++ default:
++ break;
++ }
++ return 0;
++}
++
++static void get_common_features(struct common_feature_property *common, int report_id)
++{
++ common->report_id = report_id;
++ common->connection_type = HID_USAGE_SENSOR_PROPERTY_CONNECTION_TYPE_PC_INTEGRATED_ENUM;
++ common->report_state = HID_USAGE_SENSOR_PROP_REPORTING_STATE_ALL_EVENTS_ENUM;
++ common->power_state = HID_USAGE_SENSOR_PROP_POWER_STATE_D0_FULL_POWER_ENUM;
++ common->sensor_state = HID_USAGE_SENSOR_STATE_INITIALIZING_ENUM;
++ common->report_interval = HID_DEFAULT_REPORT_INTERVAL;
++}
++
++u8 get_feature_report(int sensor_idx, int report_id, u8 *feature_report)
++{
++ struct accel3_feature_report acc_feature;
++ struct gyro_feature_report gyro_feature;
++ struct magno_feature_report magno_feature;
++ struct als_feature_report als_feature;
++ u8 report_size = 0;
++
++ if (!feature_report)
++ return report_size;
++
++ switch (sensor_idx) {
++ case accel_idx: /* accel */
++ get_common_features(&acc_feature.common_property, report_id);
++ acc_feature.accel_change_sesnitivity = HID_DEFAULT_SENSITIVITY;
++ acc_feature.accel_sensitivity_min = HID_DEFAULT_MIN_VALUE;
++ acc_feature.accel_sensitivity_max = HID_DEFAULT_MAX_VALUE;
++ memcpy(feature_report, &acc_feature, sizeof(acc_feature));
++ report_size = sizeof(acc_feature);
++ break;
++ case gyro_idx: /* gyro */
++ get_common_features(&gyro_feature.common_property, report_id);
++ gyro_feature.gyro_change_sesnitivity = HID_DEFAULT_SENSITIVITY;
++ gyro_feature.gyro_sensitivity_min = HID_DEFAULT_MIN_VALUE;
++ gyro_feature.gyro_sensitivity_max = HID_DEFAULT_MAX_VALUE;
++ memcpy(feature_report, &gyro_feature, sizeof(gyro_feature));
++ report_size = sizeof(gyro_feature);
++ break;
++ case mag_idx: /* Magnetometer */
++ get_common_features(&magno_feature.common_property, report_id);
++ magno_feature.magno_headingchange_sensitivity = HID_DEFAULT_SENSITIVITY;
++ magno_feature.heading_min = HID_DEFAULT_MIN_VALUE;
++ magno_feature.heading_max = HID_DEFAULT_MAX_VALUE;
++ magno_feature.flux_change_sensitivity = HID_DEFAULT_MIN_VALUE;
++ magno_feature.flux_min = HID_DEFAULT_MIN_VALUE;
++ magno_feature.flux_max = HID_DEFAULT_MAX_VALUE;
++ memcpy(feature_report, &magno_feature, sizeof(magno_feature));
++ report_size = sizeof(magno_feature);
++ break;
++ case als_idx: /* ambient light sensor */
++ get_common_features(&als_feature.common_property, report_id);
++ als_feature.als_change_sesnitivity = HID_DEFAULT_SENSITIVITY;
++ als_feature.als_sensitivity_min = HID_DEFAULT_MIN_VALUE;
++ als_feature.als_sensitivity_max = HID_DEFAULT_MAX_VALUE;
++ memcpy(feature_report, &als_feature, sizeof(als_feature));
++ report_size = sizeof(als_feature);
++ break;
++ default:
++ break;
++ }
++ return report_size;
++}
++
++static void get_common_inputs(struct common_input_property *common, int report_id)
++{
++ common->report_id = report_id;
++ common->sensor_state = HID_USAGE_SENSOR_STATE_READY_ENUM;
++ 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)
++{
++ struct accel3_input_report acc_input;
++ struct gyro_input_report gyro_input;
++ struct magno_input_report magno_input;
++ struct als_input_report als_input;
++ u8 report_size = 0;
++
++ if (!sensor_virt_addr || !input_report)
++ return report_size;
++
++ switch (sensor_idx) {
++ case accel_idx: /* accel */
++ get_common_inputs(&acc_input.common_property, report_id);
++ acc_input.in_accel_x_value = (int)sensor_virt_addr[0] / AMD_SFH_FW_MULTIPLIER;
++ acc_input.in_accel_y_value = (int)sensor_virt_addr[1] / AMD_SFH_FW_MULTIPLIER;
++ acc_input.in_accel_z_value = (int)sensor_virt_addr[2] / AMD_SFH_FW_MULTIPLIER;
++ memcpy(input_report, &acc_input, sizeof(acc_input));
++ report_size = sizeof(acc_input);
++ break;
++ case gyro_idx: /* gyro */
++ get_common_inputs(&gyro_input.common_property, report_id);
++ gyro_input.in_angel_x_value = (int)sensor_virt_addr[0] / AMD_SFH_FW_MULTIPLIER;
++ gyro_input.in_angel_y_value = (int)sensor_virt_addr[1] / AMD_SFH_FW_MULTIPLIER;
++ gyro_input.in_angel_z_value = (int)sensor_virt_addr[2] / AMD_SFH_FW_MULTIPLIER;
++ memcpy(input_report, &gyro_input, sizeof(gyro_input));
++ report_size = sizeof(gyro_input);
++ break;
++ case mag_idx: /* Magnetometer */
++ get_common_inputs(&magno_input.common_property, report_id);
++ magno_input.in_magno_x = (int)sensor_virt_addr[0] / AMD_SFH_FW_MULTIPLIER;
++ magno_input.in_magno_y = (int)sensor_virt_addr[1] / AMD_SFH_FW_MULTIPLIER;
++ magno_input.in_magno_z = (int)sensor_virt_addr[2] / AMD_SFH_FW_MULTIPLIER;
++ magno_input.in_magno_accuracy = (u16)sensor_virt_addr[3] / AMD_SFH_FW_MULTIPLIER;
++ memcpy(input_report, &magno_input, sizeof(magno_input));
++ report_size = sizeof(magno_input);
++ 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;
++ report_size = sizeof(als_input);
++ memcpy(input_report, &als_input, sizeof(als_input));
++ break;
++ default:
++ break;
++ }
++ return report_size;
++}
+diff -Naur linux-5.10.2/drivers/hid/amd-sfh-hid/hid_descriptor/amd_sfh_hid_desc.h linux-5.10.2-amd/drivers/hid/amd-sfh-hid/hid_descriptor/amd_sfh_hid_desc.h
+--- linux-5.10.2/drivers/hid/amd-sfh-hid/hid_descriptor/amd_sfh_hid_desc.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-5.10.2-amd/drivers/hid/amd-sfh-hid/hid_descriptor/amd_sfh_hid_desc.h 2020-12-25 14:25:44.299391977 +0100
+@@ -0,0 +1,107 @@
++/* SPDX-License-Identifier: GPL-2.0-or-later */
++/*
++ * HID report descriptors, structures and routines
++ * Copyright 2020 Advanced Micro Devices, Inc.
++ * Authors: Nehal Bakulchandra Shah <Nehal-bakulchandra.shah@amd.com>
++ * Sandeep Singh <Sandeep.singh@amd.com>
++ */
++
++#ifndef AMD_SFH_HID_DESCRIPTOR_H
++#define AMD_SFH_HID_DESCRIPTOR_H
++
++enum desc_type {
++ /* Report descriptor name */
++ descr_size = 1,
++ input_size,
++ feature_size,
++};
++
++struct common_feature_property {
++ /* common properties */
++ u8 report_id;
++ u8 connection_type;
++ u8 report_state;
++ u8 power_state;
++ u8 sensor_state;
++ u32 report_interval;
++} __packed;
++
++struct common_input_property {
++ /* common properties */
++ u8 report_id;
++ u8 sensor_state;
++ u8 event_type;
++} __packed;
++
++struct accel3_feature_report {
++ struct common_feature_property common_property;
++ /* properties specific to this sensor */
++ u16 accel_change_sesnitivity;
++ s16 accel_sensitivity_max;
++ s16 accel_sensitivity_min;
++} __packed;
++
++struct accel3_input_report {
++ struct common_input_property common_property;
++ /* values specific to this sensor */
++ int in_accel_x_value;
++ int in_accel_y_value;
++ int in_accel_z_value;
++ /* include if required to support the "shake" event */
++ u8 in_accel_shake_detection;
++} __packed;
++
++struct gyro_feature_report {
++ struct common_feature_property common_property;
++ /* properties specific to this sensor */
++ u16 gyro_change_sesnitivity;
++ s16 gyro_sensitivity_max;
++ s16 gyro_sensitivity_min;
++} __packed;
++
++struct gyro_input_report {
++ struct common_input_property common_property;
++ /* values specific to this sensor */
++ int in_angel_x_value;
++ int in_angel_y_value;
++ int in_angel_z_value;
++} __packed;
++
++struct magno_feature_report {
++ struct common_feature_property common_property;
++ /*properties specific to this sensor */
++ u16 magno_headingchange_sensitivity;
++ s16 heading_min;
++ s16 heading_max;
++ u16 flux_change_sensitivity;
++ s16 flux_min;
++ s16 flux_max;
++} __packed;
++
++struct magno_input_report {
++ struct common_input_property common_property;
++ int in_magno_x;
++ int in_magno_y;
++ int in_magno_z;
++ int in_magno_accuracy;
++} __packed;
++
++struct als_feature_report {
++ struct common_feature_property common_property;
++ /* properties specific to this sensor */
++ u16 als_change_sesnitivity;
++ s16 als_sensitivity_max;
++ s16 als_sensitivity_min;
++} __packed;
++
++struct als_input_report {
++ struct common_input_property common_property;
++ /* values specific to this sensor */
++ int illuminance_value;
++} __packed;
++
++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
+diff -Naur linux-5.10.2/drivers/hid/amd-sfh-hid/hid_descriptor/amd_sfh_hid_report_desc.h linux-5.10.2-amd/drivers/hid/amd-sfh-hid/hid_descriptor/amd_sfh_hid_report_desc.h
+--- linux-5.10.2/drivers/hid/amd-sfh-hid/hid_descriptor/amd_sfh_hid_report_desc.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-5.10.2-amd/drivers/hid/amd-sfh-hid/hid_descriptor/amd_sfh_hid_report_desc.h 2020-12-25 14:25:44.299391977 +0100
+@@ -0,0 +1,645 @@
++/* SPDX-License-Identifier: GPL-2.0-or-later */
++/*
++ * HID descriptor stuructures
++ * Copyright 2020 Advanced Micro Devices, Inc.
++ * Authors: Nehal Bakulchandra Shah <Nehal-bakulchandra.shah@amd.com>
++ * Sandeep Singh <Sandeep.singh@amd.com>
++ */
++
++#ifndef AMD_SFH_HID_REPORT_DESCRIPTOR_H
++#define AMD_SFH_HID_REPORT_DESCRIPTOR_H
++
++// Accelerometer 3D Sensor
++static const u8 accel3_report_descriptor[] = {
++0x05, 0x20, /* Usage page */
++0x09, 0x73, /* Motion type Accel 3D */
++0xA1, 0x00, /* HID Collection (Physical) */
++
++//feature reports(xmit/receive)
++0x85, 1, /* HID Report ID */
++0x05, 0x20, /* HID usage page sensor */
++0x0A, 0x09, 0x03, /* Sensor property and sensor connection type */
++0x15, 0, /* HID logical MIN_8(0) */
++0x25, 2, /* HID logical MAX_8(2) */
++0x75, 8, /* HID report size(8) */
++0x95, 1, /* HID report count(1) */
++0xA1, 0x02, /* HID collection (logical) */
++0x0A, 0x30, 0x08, /* Sensor property connection type intergated sel*/
++0x0A, 0x31, 0x08, /* Sensor property connection type attached sel */
++0x0A, 0x32, 0x08, /* Sensor property connection type external sel */
++0xB1, 0x00, /* HID feature (Data_Arr_Abs) */
++0xC0, /* HID end collection */
++0x0A, 0x16, 0x03, /* HID usage sensor property reporting state */
++0x15, 0, /* HID logical Min_8(0) */
++0x25, 5, /* HID logical Max_8(5) */
++0x75, 8, /* HID report size(8) */
++0x95, 1, /* HID report count(1) */
++0xA1, 0x02, /* HID collection(logical) */
++0x0A, 0x40, 0x08, /* Sensor property report state no events sel */
++0x0A, 0x41, 0x08, /* Sensor property report state all events sel */
++0x0A, 0x42, 0x08, /* Sensor property report state threshold events sel */
++0x0A, 0x43, 0x08, /* Sensor property report state no events wake sel */
++0x0A, 0x44, 0x08, /* Sensor property report state all events wake sel */
++0x0A, 0x45, 0x08, /* Sensor property report state threshold events wake sel */
++0xB1, 0x00, /* HID feature (Data_Arr_Abs) */
++0xC0, /* HID end collection */
++0x0A, 0x19, 0x03, /* HID usage sensor property power state */
++0x15, 0, /* HID logical Min_8(0) */
++0x25, 5, /* HID logical Max_8(5) */
++0x75, 8, /* HID report size(8) */
++0x95, 1, /* HID report count(1) */
++0xA1, 0x02, /* HID collection(logical) */
++0x0A, 0x50, 0x08, /* Sensor property power state undefined sel */
++0x0A, 0x51, 0x08, /* Sensor property power state D0 full power sel */
++0x0A, 0x52, 0x08, /* Sensor property power state D1 low power sel */
++0x0A, 0x53, 0x08, /* Sensor property power state D2 standby with wake sel */
++0x0A, 0x54, 0x08, /* Sensor property power state D3 sleep with wake sel */
++0x0A, 0x55, 0x08, /* Sensor property power state D4 power off sel */
++0xB1, 0x00, /* HID feature (Data_Arr_Abs) */
++0xC0, /* HID end collection */
++0x0A, 0x01, 0x02, /* HID usage sensor state */
++0x15, 0, /* HID logical Min_8(0) */
++0x25, 6, /* HID logical Max_8(6) */
++0x75, 8, /* HID report size(8) */
++0x95, 1, /* HID report count(1) */
++0xA1, 0x02, /* HID collection(logical) */
++0x0A, 0x00, 0x08, /* HID usage sensor state unknown sel */
++0x0A, 0x01, 0x08, /* HID usage sensor state ready sel */
++0x0A, 0x02, 0x08, /* HID usage sensor state not available sel */
++0x0A, 0x03, 0x08, /* HID usage sensor state no data sel */
++0x0A, 0x04, 0x08, /* HID usage sensor state initializing sel */
++0x0A, 0x05, 0x08, /* HID usage sensor state access denied sel */
++0x0A, 0x06, 0x08, /* HID usage sensor state error sel */
++0xB1, 0x00, /* HID feature (Data_Arr_Abs) */
++0xC0, /* HID end collection */
++0x0A, 0x0E, 0x03, /* HID usage sensor property report interval */
++0x15, 0, /* HID logical Min_8(0) */
++0x27, 0xFF, 0xFF, 0xFF, 0xFF, /* HID logical Max_32 */
++
++0x75, 32, /* HID report size(32) */
++0x95, 1, /* HID report count(1) */
++0x55, 0, /* HID unit exponent(0) */
++0xB1, 0x02, /* HID feature (Data_Arr_Abs) */
++0x0A, 0x52, 0x14, /* Sensor data motion accel and mod change sensitivity ABS) */
++
++0x15, 0, /* HID logical Min_8(0) */
++0x26, 0xFF, 0xFF, /* HID logical Max_16(0xFF,0xFF) */
++
++0x75, 16, /* HID report size(16) */
++0x95, 1, /* HID report count(1) */
++0x55, 0x0E, /* HID unit exponent(0x0E) */
++0xB1, 0x02, /* HID feature (Data_Arr_Abs) */
++0x0A, 0x52, 0x24, /* HID usage sensor data (motion accel and mod max) */
++
++0x16, 0x01, 0x80, /* HID logical Min_16(0x01,0x80) */
++
++0x26, 0xFF, 0x7F, /* HID logical Max_16(0xFF,0x7F) */
++
++0x75, 16, /* HID report size(16) */
++0x95, 1, /* HID report count(1) */
++0x55, 0x0E, /* HID unit exponent(0x0E) */
++0xB1, 0x02, /* HID feature (Data_Arr_Abs) */
++0x0A, 0x52, 0x34, /* HID usage sensor data (motion accel and mod min) */
++
++0x16, 0x01, 0x80, /* HID logical Min_16(0x01,0x80) */
++
++0x26, 0xFF, 0x7F, /* HID logical Max_16(0xFF,0x7F) */
++
++0x75, 16, /* HID report size(16) */
++0x95, 1, /* HID report count(1) */
++0x55, 0x0E, /* HID unit exponent(0x0E) */
++0xB1, 0x02, /* HID feature (Data_Arr_Abs) */
++
++//input report (transmit)
++0x05, 0x20, /* HID usage page sensors */
++0x0A, 0x01, 0x02, /* HID usage sensor state */
++0x15, 0, /* HID logical Min_8(0) */
++0x25, 6, /* HID logical Max_8(6) */
++0x75, 8, /* HID report size(8) */
++0x95, 1, /* HID report count (1) */
++0xA1, 0x02, /* HID end collection (logical) */
++0x0A, 0x00, 0x08, /* HID usage sensor state unknown sel */
++0x0A, 0x01, 0x08, /* HID usage sensor state ready sel */
++0x0A, 0x02, 0x08, /* HID usage sensor state not available sel */
++0x0A, 0x03, 0x08, /* HID usage sensor state no data sel */
++0x0A, 0x04, 0x08, /* HID usage sensor state initializing sel */
++0x0A, 0x05, 0x08, /* HID usage sensor state access denied sel */
++0x0A, 0x06, 0x08, /* HID usage sensor state error sel */
++0X81, 0x00, /* HID Input (Data_Arr_Abs) */
++0xC0, /* HID end collection */
++0x0A, 0x02, 0x02, /* HID usage sensor event */
++0x15, 0, /* HID logical Min_8(0) */
++0x25, 5, /* HID logical Max_8(5) */
++0x75, 8, /* HID report size(8) */
++0x95, 1, /* HID report count (1) */
++0xA1, 0x02, /* HID end collection (logical) */
++0x0A, 0x10, 0x08, /* HID usage sensor event unknown sel */
++0x0A, 0x11, 0x08, /* HID usage sensor event state changed sel */
++0x0A, 0x12, 0x08, /* HID usage sensor event property changed sel */
++0x0A, 0x13, 0x08, /* HID usage sensor event data updated sel */
++0x0A, 0x14, 0x08, /* HID usage sensor event poll response sel */
++0x0A, 0x15, 0x08, /* HID usage sensor event change sensitivity sel */
++0X81, 0x00, /* HID Input (Data_Arr_Abs) */
++0xC0, /* HID end collection */
++0x0A, 0x53, 0x04, /* HID usage sensor data motion Acceleration X axis */
++0x17, 0x00, 0x00, 0x01, 0x80, /* HID logical Min_32 */
++
++0x27, 0xFF, 0xff, 0XFF, 0XFF, /* HID logical Max_32 */
++
++0x75, 32, /* HID report size(32) */
++0x95, 1, /* HID report count (1) */
++0x55, 0x0E, /* HID unit exponent(0x0E) */
++0X81, 0x02, /* HID Input (Data_Arr_Abs) */
++0x0A, 0x54, 0x04, /* HID usage sensor data motion Acceleration Y axis */
++0x17, 0X00, 0X00, 0x01, 0x80, /* HID logical Min_32 */
++
++0x27, 0xFF, 0xFF, 0XFF, 0XFF, /* HID logical Max_32 */
++
++0x75, 32, /* HID report size(32) */
++0x95, 1, /* HID report count (1) */
++0x55, 0x0E, /* HID unit exponent(0x0E) */
++0X81, 0x02, /* HID Input (Data_Arr_Abs) */
++0x0A, 0x55, 0x04, /* HID usage sensor data motion Acceleration Z axis */
++0x17, 0X00, 0X00, 0x01, 0x80, /* HID logical Min_32 */
++
++0x27, 0XFF, 0XFF, 0xFF, 0x7F, /* HID logical Max_32 */
++
++0x75, 32, /* HID report size(32) */
++0x95, 1, /* HID report count (1) */
++0x55, 0x0E, /* HID unit exponent(0x0E) */
++0X81, 0x02, /* HID Input (Data_Arr_Abs) */
++
++0x0A, 0x51, 0x04, /* HID usage sensor data motion state */
++0x15, 0, /* HID logical Min_8(0) False = Still*/
++0x25, 1, /* HID logical Min_8(1) True = In motion */
++0x75, 8, /* HID report size(8) */
++0x95, 1, /* HID report count (1) */
++0X81, 0x02, /* HID Input (Data_Arr_Abs) */
++0xC0 /* HID end collection */
++};
++
++const u8 gyro3_report_descriptor[] = {
++0x05, 0x20, /* Usage page */
++0x09, 0x76, /* Motion type Gyro3D */
++0xA1, 0x00, /* HID Collection (Physical) */
++
++0x85, 2, /* HID Report ID */
++0x05, 0x20, /* HID usage page sensor */
++0x0A, 0x09, 0x03, /* Sensor property and sensor connection type */
++0x15, 0, /* HID logical MIN_8(0) */
++0x25, 2, /* HID logical MAX_8(2) */
++0x75, 8, /* HID report size(8) */
++0x95, 1, /* HID report count(1) */
++0xA1, 0x02, /* HID collection (logical) */
++0x0A, 0x30, 0x08, /* Sensor property connection type intergated sel */
++0x0A, 0x31, 0x08, /* Sensor property connection type attached sel */
++0x0A, 0x32, 0x08, /* Sensor property connection type external sel */
++0xB1, 0x00, /* HID feature (Data_Arr_Abs) */
++0xC0, /* HID end collection */
++0x0A, 0x16, 0x03, /* HID usage sensor property reporting state */
++0x15, 0, /* HID logical Min_8(0) */
++0x25, 5, /* HID logical Max_8(5) */
++0x75, 8, /* HID report size(8) */
++0x95, 1, /* HID report count(1) */
++0xA1, 0x02, /* HID collection(logical) */
++0x0A, 0x40, 0x08, /* Sensor reporting state no events sel */
++0x0A, 0x41, 0x08, /* Sensor reporting state all events sel */
++0x0A, 0x42, 0x08, /* Sensor reporting state threshold events sel */
++0x0A, 0x43, 0x08, /* Sensor reporting state no events wake sel */
++0x0A, 0x44, 0x08, /* Sensor reporting state all events wake sel */
++0x0A, 0x45, 0x08, /* Sensor reporting state threshold events wake sel */
++0xB1, 0x00, /* HID feature (Data_Arr_Abs) */
++0xC0, /* HID end collection */
++0x0A, 0x19, 0x03, /* HID usage sensor property power state */
++0x15, 0, /* HID logical Min_8(0) */
++0x25, 5, /* HID logical Max_8(5) */
++0x75, 8, /* HID report size(8) */
++0x95, 1, /* HID report count(1) */
++0xA1, 0x02, /* HID collection(logical) */
++0x0A, 0x50, 0x08, /* Sensor power state undefined sel */
++0x0A, 0x51, 0x08, /* Sensor power state D0 full power sel */
++0x0A, 0x52, 0x08, /* Sensor power state D1 low power sel */
++0x0A, 0x53, 0x08, /* Sensor power state D2 standby with wake sel */
++0x0A, 0x54, 0x08, /* Sensor power state D3 sleep with wake sel */
++0x0A, 0x55, 0x08, /* Sensor power state D4 power off sel */
++0xB1, 0x00, /* HID feature (Data_Arr_Abs) */
++0xC0, /* HID end collection */
++0x0A, 0x01, 0x02, /* HID usage sensor state */
++0x15, 0, /* HID logical Min_8(0) */
++0x25, 6, /* HID logical Max_8(6) */
++0x75, 8, /* HID report size(8) */
++0x95, 1, /* HID report count(1) */
++0xA1, 0x02, /* HID collection(logical) */
++0x0A, 0x00, 0x08, /* HID usage sensor state unknown sel */
++0x0A, 0x01, 0x08, /* HID usage sensor state ready sel */
++0x0A, 0x02, 0x08, /* HID usage sensor state not available sel */
++0x0A, 0x03, 0x08, /* HID usage sensor state no data sel */
++0x0A, 0x04, 0x08, /* HID usage sensor state initializing sel */
++0x0A, 0x05, 0x08, /* HID usage sensor state access denied sel */
++0x0A, 0x06, 0x08, /* HID usage sensor state error sel */
++0xB1, 0x00, /* HID feature (Data_Arr_Abs) */
++0xC0, /* HID end collection */
++0x0A, 0x0E, 0x03, /* HID usage sensor property report interval */
++0x15, 0, /* HID logical Min_8(0) */
++0x27, 0xFF, 0xFF, 0xFF, 0xFF, /* HID logical Max_32 */
++
++0x75, 32, /* HID report size(32) */
++0x95, 1, /* HID report count(1) */
++0x55, 0, /* HID unit exponent(0) */
++0xB1, 0x02, /* HID feature (Data_Arr_Abs) */
++0x0A, 0x56, 0x14, /* Angular velocity and mod change sensitivity ABS)*/
++
++0x15, 0, /* HID logical Min_8(0) */
++0x26, 0xFF, 0xFF, /* HID logical Max_16(0xFF,0xFF) */
++
++0x75, 16, /* HID report size(16) */
++0x95, 1, /* HID report count(1) */
++0x55, 0x0E, /* HID unit exponent(0x0E) */
++0xB1, 0x02, /* HID feature (Data_Arr_Abs) */
++0x0A, 0x56, 0x24, /* Sensor data (motion angular velocity and mod max) */
++
++0x16, 0x01, 0x80, /* HID logical Min_16(0x01,0x80) */
++
++0x26, 0xFF, 0x7F, /* HID logical Max_16(0xFF,0x7F) */
++
++0x75, 16, /* HID report size(16) */
++0x95, 1, /* HID report count(1) */
++0x55, 0x0E, /* HID unit exponent(0x0E) */
++0xB1, 0x02, /* HID feature (Data_Arr_Abs) */
++0x0A, 0x56, 0x34, /* HID usage sensor data (motion accel and mod min) */
++
++0x16, 0x01, 0x80, /* HID logical Min_16(0x01,0x80) */
++
++0x26, 0xFF, 0x7F, /* HID logical Max_16(0xFF,0x7F) */
++
++0x75, 16, /* HID report size(16) */
++0x95, 1, /* HID report count(1) */
++0x55, 0x0E, /* HID unit exponent(0x0E) */
++0xB1, 0x02, /* HID feature (Data_Arr_Abs) */
++
++//Input reports(transmit)
++0x05, 0x20, /* HID usage page sensors */
++0x0A, 0x01, 0x02, /* HID usage sensor state */
++0x15, 0, /* HID logical Min_8(0) */
++0x25, 6, /* HID logical Max_8(6) */
++0x75, 8, /* HID report size(8) */
++0x95, 1, /* HID report count (1) */
++0xA1, 0x02, /* HID end collection (logical) */
++0x0A, 0x00, 0x08, /* HID usage sensor state unknown sel */
++0x0A, 0x01, 0x08, /* HID usage sensor state ready sel */
++0x0A, 0x02, 0x08, /* HID usage sensor state not available sel */
++0x0A, 0x03, 0x08, /* HID usage sensor state no data sel */
++0x0A, 0x04, 0x08, /* HID usage sensor state initializing sel */
++0x0A, 0x05, 0x08, /* HID usage sensor state access denied sel */
++0x0A, 0x06, 0x08, /* HID usage sensor state error sel */
++0X81, 0x00, /* HID Input (Data_Arr_Abs) */
++0xC0, /* HID end collection */
++0x0A, 0x02, 0x02, /* HID usage sensor event */
++0x15, 0, /* HID logical Min_8(0) */
++0x25, 5, /* HID logical Max_8(5) */
++0x75, 8, /* HID report size(8) */
++0x95, 1, /* HID report count (1) */
++0xA1, 0x02, /* HID end collection (logical) */
++0x0A, 0x10, 0x08, /* HID usage sensor event unknown sel */
++0x0A, 0x11, 0x08, /* HID usage sensor event state changed sel */
++0x0A, 0x12, 0x08, /* HID usage sensor event property changed sel */
++0x0A, 0x13, 0x08, /* HID usage sensor event data updated sel */
++0x0A, 0x14, 0x08, /* HID usage sensor event poll response sel */
++0x0A, 0x15, 0x08, /* HID usage sensor event change sensitivity sel */
++0X81, 0x00, /* HID Input (Data_Arr_Abs) */
++0xC0, /* HID end collection */
++0x0A, 0x57, 0x04, /* Sensor data motion Angular velocity X axis */
++0x17, 0x00, 0x00, 0x01, 0x80, /* HID logical Min_32 */
++
++0x27, 0xFF, 0xFF, 0xFF, 0x7F, /* HID logical Max_32 */
++
++0x75, 32, /* HID report size(32) */
++0x95, 1, /* HID report count (1) */
++0x55, 0x0E, /* HID unit exponent(0x0E) */
++0X81, 0x02, /* HID Input (Data_Arr_Abs) */
++0x0A, 0x58, 0x04, /* Sensor data motion Angular velocity Y axis */
++0x17, 0x00, 0x00, 0x01, 0x80, /* HID logical Min_32 */
++
++0x27, 0xFF, 0xFF, 0xFF, 0x7F, /* HID logical Max_32 */
++
++0x75, 32, /* HID report size(32) */
++0x95, 1, /* HID report count (1) */
++0x55, 0x0E, /* HID unit exponent(0x0E) */
++0X81, 0x02, /* HID Input (Data_Arr_Abs) */
++0x0A, 0x59, 0x04, /* Sensor data motion Angular velocity Z axis */
++0x17, 0x00, 0x00, 0x01, 0x80, /* HID logical Min_32 */
++
++0x27, 0xFF, 0xFF, 0xFF, 0x7F, /* HID logical Max_32 */
++
++0x75, 32, /* HID report size(32) */
++0x95, 1, /* HID report count (1) */
++0x55, 0x0E, /* HID unit exponent(0x0E) */
++0X81, 0x02, /* HID Input (Data_Arr_Abs) */
++
++0xC0, /* HID end collection */
++};
++
++const u8 comp3_report_descriptor[] = {
++0x05, 0x20, /* Usage page */
++0x09, 0x83, /* Motion type Orientation compass 3D */
++0xA1, 0x00, /* HID Collection (Physical) */
++
++0x85, 3, /* HID Report ID */
++0x05, 0x20, /* HID usage page sensor */
++0x0A, 0x09, 0x03, /* Sensor property and sensor connection type */
++0x15, 0, /* HID logical MIN_8(0) */
++0x25, 2, /* HID logical MAX_8(2) */
++0x75, 8, /* HID report size(8) */
++0x95, 1, /* HID report count(1) */
++0xA1, 0x02, /* HID collection (logical) */
++0x0A, 0x30, 0x08, /* Sensor property connection type intergated sel */
++0x0A, 0x31, 0x08, /* Sensor property connection type attached sel */
++0x0A, 0x32, 0x08, /* Sensor property connection type external sel */
++0xB1, 0x00, /* HID feature (Data_Arr_Abs) */
++0xC0, /* HID end collection */
++0x0A, 0x16, 0x03, /* HID usage sensor property reporting state */
++0x15, 0, /* HID logical Min_8(0) */
++0x25, 5, /* HID logical Max_8(5) */
++0x75, 8, /* HID report size(8) */
++0x95, 1, /* HID report count(1) */
++0xA1, 0x02, /* HID collection(logical) */
++0x0A, 0x40, 0x08, /* Sensor reporting state no events sel */
++0x0A, 0x41, 0x08, /* Sensor reporting state all events sel */
++0x0A, 0x42, 0x08, /* Sensor reporting state threshold events sel */
++0x0A, 0x43, 0x08, /* Sensor reporting state no events wake sel */
++0x0A, 0x44, 0x08, /* Sensor reporting state all events wake sel */
++0x0A, 0x45, 0x08, /* Sensor reporting state threshold events wake sel */
++0xB1, 0x00, /* HID feature (Data_Arr_Abs) */
++0xC0, /* HID end collection */
++0x0A, 0x19, 0x03, /* HID usage sensor property power state */
++0x15, 0, /* HID logical Min_8(0) */
++0x25, 5, /* HID logical Max_8(5) */
++0x75, 8, /* HID report size(8) */
++0x95, 1, /* HID report count(1) */
++0xA1, 0x02, /* HID collection(logical) */
++0x0A, 0x50, 0x08, /* Sensor power state undefined sel */
++0x0A, 0x51, 0x08, /* Sensor power state D0 full power sel */
++0x0A, 0x52, 0x08, /* Sensor power state D1 low power sel */
++0x0A, 0x53, 0x08, /* Sensor power state D2 standby with wake sel */
++0x0A, 0x54, 0x08, /* Sensor power state D3 sleep with wake sel */
++0x0A, 0x55, 0x08, /* Sensor power state D4 power off sel */
++0xB1, 0x00, /* HID feature (Data_Arr_Abs) */
++0xC0, /* HID end collection */
++0x0A, 0x01, 0x02, /* HID usage sensor state */
++0x15, 0, /* HID logical Min_8(0) */
++0x25, 6, /* HID logical Max_8(6) */
++0x75, 8, /* HID report size(8) */
++0x95, 1, /* HID report count(1) */
++0xA1, 0x02, /* HID collection(logical) */
++0x0A, 0x00, 0x08, /* HID usage sensor state unknown sel */
++0x0A, 0x01, 0x08, /* HID usage sensor state ready sel */
++0x0A, 0x02, 0x08, /* HID usage sensor state not available sel */
++0x0A, 0x03, 0x08, /* HID usage sensor state no data sel */
++0x0A, 0x04, 0x08, /* HID usage sensor state initializing sel */
++0x0A, 0x05, 0x08, /* HID usage sensor state access denied sel */
++0x0A, 0x06, 0x08, /* HID usage sensor state error sel */
++0xB1, 0x00, /* HID feature (Data_Arr_Abs) */
++0xC0, /* HID end collection */
++0x0A, 0x0E, 0x03, /* HID usage sensor property report interval */
++0x15, 0, /* HID logical Min_8(0) */
++0x27, 0xFF, 0xFF, 0xFF, 0xFF, /* HID logical Max_32 */
++0x75, 32, /* HID report size(32) */
++0x95, 1, /* HID report count(1) */
++0x55, 0, /* HID unit exponent(0) */
++0xB1, 0x02, /* HID feature (Data_Arr_Abs) */
++0x0A, 0x71, 0x14, /* Orientation and mod change sensitivity ABS)*/
++0x15, 0, /* HID logical Min_8(0) */
++0x26, 0xFF, 0xFF, /* HID logical Max_16(0xFF,0xFF) */
++0x75, 16, /* HID report size(16) */
++0x95, 1, /* HID report count(1) */
++0x55, 0x0E, /* HID unit exponent(0x0E) */
++0xB1, 0x02, /* HID feature (Data_Arr_Abs) */
++0x0A, 0x71, 0x24, /* Sensor data (motion orientation and mod max) */
++0x16, 0x01, 0x80, /* HID logical Min_16(0x01,0x80) */
++0x26, 0xFF, 0x7F, /* HID logical Max_16(0xFF,0x7F) */
++0x75, 16, /* HID report size(16) */
++0x95, 1, /* HID report count(1) */
++0x55, 0x0F, /* HID unit exponent(0x0F) */
++0xB1, 0x02, /* HID feature (Data_Arr_Abs) */
++0x0A, 0x71, 0x34, /* Sensor data (motion orientation and mod min) */
++0x16, 0x01, 0x80, /* HID logical Min_16(0x01,0x80) */
++0x26, 0xFF, 0x7F, /* HID logical Max_16(0xFF,0x7F) */
++0x75, 16, /* HID report size(16) */
++0x95, 1, /* HID report count(1) */
++0x55, 0x0F, /* HID unit exponent(0x0F) */
++0xB1, 0x02, /* HID feature (Data_Arr_Abs) */
++0x0A, 0x84, 0x14, /* Maganetic flux and change sensitivity ABS) */
++0x15, 0, /* HID logical Min_8(0) */
++0x26, 0xFF, 0xFF, /* HID logical Max_16(0xFF,0xFF) */
++0x75, 16, /* HID report size(16) */
++0x95, 1, /* HID report count(1) */
++0x55, 0x0E, /* HID unit exponent(0x0E) */
++0xB1, 0x02, /* HID feature (Data_Arr_Abs) */
++0x0A, 0x84, 0x24, /* Maganetic flux and mod change sensitivity Max) */
++0x16, 0x01, 0x80, /* HID logical Min_16(0x01,0x80) */
++0x26, 0xFF, 0x7F, /* HID logical Max_16(0xFF,0x7F) */
++0x75, 16, /* HID report size(16) */
++0x95, 1, /* HID report count(1) */
++0x55, 0x0F, /* HID unit exponent(0x0F) */
++0xB1, 0x02, /* HID feature (Data_Arr_Abs) */
++0x0A, 0x84, 0x34, /* Maganetic flux and mod change sensitivity Min */
++0x16, 0x01, 0x80, /* HID logical Min_16(0x01,0x80) */
++0x26, 0xFF, 0x7F, /* HID logical Max_16(0xFF,0x7F) */
++0x75, 16, /* HID report size(16) */
++0x95, 1, /* HID report count(1) */
++0x55, 0x0F, /* HID unit exponent(0x0F) */
++0xB1, 0x02, /* HID feature (Data_Arr_Abs) */
++
++//Input reports(transmit)
++0x05, 0x20, /* HID usage page sensors */
++0x0A, 0x01, 0x02, /* HID usage sensor state */
++0x15, 0, /* HID logical Min_8(0) */
++0x25, 6, /* HID logical Max_8(6) */
++0x75, 8, /* HID report size(8) */
++0x95, 1, /* HID report count (1) */
++0xA1, 0x02, /* HID end collection (logical) */
++0x0A, 0x00, 0x08, /* HID usage sensor state unknown sel */
++0x0A, 0x01, 0x08, /* HID usage sensor state ready sel */
++0x0A, 0x02, 0x08, /* HID usage sensor state not available sel */
++0x0A, 0x03, 0x08, /* HID usage sensor state no data sel */
++0x0A, 0x04, 0x08, /* HID usage sensor state initializing sel */
++0x0A, 0x05, 0x08, /* HID usage sensor state access denied sel */
++0x0A, 0x06, 0x08, /* HID usage sensor state error sel */
++0X81, 0x00, /* HID Input (Data_Arr_Abs) */
++0xC0, /* HID end collection */
++0x0A, 0x02, 0x02, /* HID usage sensor event */
++0x15, 0, /* HID logical Min_8(0) */
++0x25, 5, /* HID logical Max_8(5) */
++0x75, 8, /* HID report size(8) */
++0x95, 1, /* HID report count (1) */
++0xA1, 0x02, /* HID end collection (logical) */
++0x0A, 0x10, 0x08, /* HID usage sensor event unknown sel */
++0x0A, 0x11, 0x08, /* HID usage sensor event state changed sel */
++0x0A, 0x12, 0x08, /* HID usage sensor event property changed sel */
++0x0A, 0x13, 0x08, /* HID usage sensor event data updated sel */
++0x0A, 0x14, 0x08, /* HID usage sensor event poll response sel */
++0x0A, 0x15, 0x08, /* HID usage sensor event change sensitivity sel */
++0X81, 0x00, /* HID Input (Data_Arr_Abs) */
++0xC0, /* HID end collection */
++0x0A, 0x85, 0x04, /* Sensor data orientation magnetic flux X axis */
++0x17, 0x00, 0x00, 0x01, 0x80, /* HID logical Min_32 */
++0x27, 0xFF, 0xFF, 0xFF, 0x7F, /* HID logical Max_32 */
++0x75, 32, /* HID report size(32) */
++0x95, 1, /* HID report count (1) */
++0x55, 0x0D, /* HID unit exponent(0x0D) */
++0X81, 0x02, /* HID Input (Data_Arr_Abs) */
++0x0A, 0x86, 0x04, /* Sensor data orientation magnetic flux Y axis */
++0x17, 0x00, 0x00, 0x01, 0x80, /* HID logical Min_32 */
++0x27, 0xFF, 0xFF, 0xFF, 0x7F, /* HID logical Max_32 */
++0x75, 32, /* HID report size(32) */
++0x95, 1, /* HID report count (1) */
++0x55, 0x0D, /* HID unit exponent(0x0D) */
++0X81, 0x02, /* HID Input (Data_Arr_Abs) */
++0x0A, 0x87, 0x04, /* Sensor data orientation magnetic flux Z axis */
++0x17, 0x00, 0x00, 0x01, 0x80, /* HID logical Min_32 */
++0x27, 0xFF, 0xFF, 0xFF, 0x7F, /* HID logical Max_32 */
++0x75, 32, /* HID report size(32) */
++0x95, 1, /* HID report count (1) */
++0x55, 0x0D, /* HID unit exponent(0x0D) */
++0X81, 0x02, /* HID Input (Data_Arr_Abs) */
++0x0A, 0x88, 0x04, /* Sensor data orientation magnetometer accuracy */
++0x17, 0x00, 0x00, 0x01, 0x80, /* HID logical Min_32 */
++0x27, 0xFF, 0xFF, 0xFF, 0x7F, /* HID logical Max_32 */
++0x75, 32, /* HID report size(32) */
++0x95, 1, /* HID report count (1) */
++0X81, 0x02, /* HID Input (Data_Arr_Abs) */
++0xC0 /* HID end collection */
++};
++
++const u8 als_report_descriptor[] = {
++0x05, 0x20, /* HID usage page sensor */
++0x09, 0x41, /* HID usage sensor type Ambientlight */
++0xA1, 0x00, /* HID Collection (Physical) */
++
++//feature reports(xmit/receive)//
++0x85, 4, /* HID Report ID */
++0x05, 0x20, /* HID usage page sensor */
++0x0A, 0x09, 0x03, /* Sensor property and sensor connection type */
++0x15, 0, /* HID logical MIN_8(0) */
++0x25, 2, /* HID logical MAX_8(2) */
++0x75, 8, /* HID report size(8) */
++0x95, 1, /* HID report count(1) */
++0xA1, 0x02, /* HID collection (logical) */
++0x0A, 0x30, 0x08, /* Sensor property connection type intergated sel */
++0x0A, 0x31, 0x08, /* Sensor property connection type attached sel */
++0x0A, 0x32, 0x08, /* Sensor property connection type external sel */
++0xB1, 0x00, /* HID feature (Data_Arr_Abs) */
++0xC0, /* HID end collection */
++0x0A, 0x16, 0x03, /* HID usage sensor property reporting state */
++0x15, 0, /* HID logical Min_8(0) */
++0x25, 5, /* HID logical Max_8(5) */
++0x75, 8, /* HID report size(8) */
++0x95, 1, /* HID report count(1) */
++0xA1, 0x02, /* HID collection(logical) */
++0x0A, 0x40, 0x08, /* Sensor reporting state no events sel */
++0x0A, 0x41, 0x08, /* Sensor reporting state all events sel */
++0x0A, 0x42, 0x08, /* Sensor reporting state threshold events sel */
++0x0A, 0x43, 0x08, /* Sensor reporting state no events wake sel */
++0x0A, 0x44, 0x08, /* Sensor reporting state all events wake sel */
++0x0A, 0x45, 0x08, /* Sensor reporting state threshold events wake sel */
++0xB1, 0x00, /* HID feature (Data_Arr_Abs) */
++0xC0, /* HID end collection */
++0x0A, 0x19, 0x03, /* HID usage sensor property power state */
++0x15, 0, /* HID logical Min_8(0) */
++0x25, 5, /* HID logical Max_8(5) */
++0x75, 8, /* HID report size(8) */
++0x95, 1, /* HID report count(1) */
++0xA1, 0x02, /* HID collection(logical) */
++0x0A, 0x50, 0x08, /* Sensor power state undefined sel */
++0x0A, 0x51, 0x08, /* Sensor power state D0 full power sel */
++0x0A, 0x52, 0x08, /* Sensor power state D1 low power sel */
++0x0A, 0x53, 0x08, /* Sensor power state D2 standby with wake sel */
++0x0A, 0x54, 0x08, /* Sensor power state D3 sleep with wake sel */
++0x0A, 0x55, 0x08, /* Sensor power state D4 power off sel */
++0xB1, 0x00, /* HID feature (Data_Arr_Abs) */
++0xC0, /* HID end collection */
++0x0A, 0x01, 0x02, /* HID usage sensor state */
++0x15, 0, /* HID logical Min_8(0) */
++0x25, 6, /* HID logical Max_8(6) */
++0x75, 8, /* HID report size(8) */
++0x95, 1, /* HID report count(1) */
++0xA1, 0x02, /* HID collection(logical) */
++0x0A, 0x00, 0x08, /* HID usage sensor state unknown sel */
++0x0A, 0x01, 0x08, /* HID usage sensor state ready sel */
++0x0A, 0x02, 0x08, /* HID usage sensor state not available sel */
++0x0A, 0x03, 0x08, /* HID usage sensor state no data sel */
++0x0A, 0x04, 0x08, /* HID usage sensor state initializing sel */
++0x0A, 0x05, 0x08, /* HID usage sensor state access denied sel */
++0x0A, 0x06, 0x08, /* HID usage sensor state error sel */
++0xB1, 0x00, /* HID feature (Data_Arr_Abs) */
++0xC0, /* HID end collection */
++0x0A, 0x0E, 0x03, /* HID usage sensor property report interval */
++0x15, 0, /* HID logical Min_8(0) */
++0x27, 0xFF, 0xFF, 0xFF, 0xFF, /* HID logical Max_32 */
++0x75, 32, /* HID report size(32) */
++0x95, 1, /* HID report count(1) */
++0x55, 0, /* HID unit exponent(0) */
++0xB1, 0x02, /* HID feature (Data_Arr_Abs) */
++0x0A, 0xD1, 0xE4, /* Light illuminance and sensitivity REL PCT) */
++0x15, 0, /* HID logical Min_8(0) */
++0x26, 0x10, 0x27, /* HID logical Max_16(0x10,0x27) */
++0x75, 16, /* HID report size(16) */
++0x95, 1, /* HID report count(1) */
++0x55, 0x0E, /* HID unit exponent(0x0E) */
++0xB1, 0x02, /* HID feature (Data_Arr_Abs) */
++0x0A, 0xD1, 0x24, /* Sensor data (Light illuminance and mod max) */
++0x15, 0, /* HID logical Min_8(0) */
++0x26, 0xFF, 0xFF, /* HID logical Max_16(0xFF,0xFF) */
++0x75, 16, /* HID report size(16) */
++0x95, 1, /* HID report count(1) */
++0x55, 0x0F, /* HID unit exponent(0x0F) */
++0xB1, 0x02, /* HID feature (Data_Arr_Abs) */
++0x0A, 0xD1, 0x34, /* Sensor data (Light illuminance and mod min) */
++0x15, 0, /* HID logical Min_8(0) */
++0x26, 0xFF, 0xFF, /* HID logical Max_16(0xFF,0xFF) */
++0x75, 16, /* HID report size(16) */
++0x95, 1, /* HID report count(1) */
++0x55, 0x0F, /* HID unit exponent(0x0F) */
++0xB1, 0x02, /* HID feature (Data_Arr_Abs) */
++
++//Input reports (transmit)
++0x05, 0x20, /* HID usage page sensors */
++0x0A, 0x01, 0x02, /* HID usage sensor state */
++0x15, 0, /* HID logical Min_8(0) */
++0x25, 6, /* HID logical Max_8(6) */
++0x75, 8, /* HID report size(8) */
++0x95, 1, /* HID report count (1) */
++0xA1, 0x02, /* HID end collection (logical) */
++0x0A, 0x00, 0x08, /* HID usage sensor state unknown sel */
++0x0A, 0x01, 0x08, /* HID usage sensor state ready sel */
++0x0A, 0x02, 0x08, /* HID usage sensor state not available sel */
++0x0A, 0x03, 0x08, /* HID usage sensor state no data sel */
++0x0A, 0x04, 0x08, /* HID usage sensor state initializing sel */
++0x0A, 0x05, 0x08, /* HID usage sensor state access denied sel */
++0x0A, 0x06, 0x08, /* HID usage sensor state error sel */
++0X81, 0x00, /* HID Input (Data_Arr_Abs) */
++0xC0, /* HID end collection */
++0x0A, 0x02, 0x02, /* HID usage sensor event */
++0x15, 0, /* HID logical Min_8(0) */
++0x25, 5, /* HID logical Max_8(5) */
++0x75, 8, /* HID report size(8) */
++0x95, 1, /* HID report count (1) */
++0xA1, 0x02, /* HID end collection (logical) */
++0x0A, 0x10, 0x08, /* HID usage sensor event unknown sel */
++0x0A, 0x11, 0x08, /* HID usage sensor event state changed sel */
++0x0A, 0x12, 0x08, /* HID usage sensor event property changed sel */
++0x0A, 0x13, 0x08, /* HID usage sensor event data updated sel */
++0x0A, 0x14, 0x08, /* HID usage sensor event poll response sel */
++0x0A, 0x15, 0x08, /* HID usage sensor event change sensitivity sel */
++0X81, 0x00, /* HID Input (Data_Arr_Abs) */
++0xC0, /* HID end collection */
++0x0A, 0xD1, 0x04, /* HID usage sensor data light illuminance */
++0x17, 0x00, 0x00, 0x01, 0x80, /* HID logical Min_32 */
++0x27, 0xFF, 0xFF, 0xFF, 0x7F, /* HID logical Max_32 */
++0x55, 0x0F, /* HID unit exponent(0x0F) */
++0x75, 32, /* HID report size(32) */
++0x95, 1, /* HID report count (1) */
++0X81, 0x02, /* HID Input (Data_Arr_Abs) */
++0xC0 /* HID end collection */
++};
++#endif
+diff -Naur linux-5.10.2/drivers/hid/amd-sfh-hid/Kconfig linux-5.10.2-amd/drivers/hid/amd-sfh-hid/Kconfig
+--- linux-5.10.2/drivers/hid/amd-sfh-hid/Kconfig 1970-01-01 01:00:00.000000000 +0100
++++ linux-5.10.2-amd/drivers/hid/amd-sfh-hid/Kconfig 2020-12-25 14:25:44.298391979 +0100
+@@ -0,0 +1,18 @@
++# SPDX-License-Identifier: GPL-2.0-or-later
++menu "AMD SFH HID Support"
++ depends on X86_64 || COMPILE_TEST
++ depends on PCI
++ depends on HID
++
++config AMD_SFH_HID
++ tristate "AMD Sensor Fusion Hub"
++ help
++ If you say yes to this option, support will be included for the
++ AMD Sensor Fusion Hub.
++ This driver will enable sensors functionality on AMD platforms
++ starting from 17h family of RYZEN parts.
++
++ This driver can also be built as a module. If so, the module will
++ be called amd-sfh.
++ Say Y or M here if you want to support AMD SFH. If unsure, say N.
++endmenu
+diff -Naur linux-5.10.2/drivers/hid/amd-sfh-hid/Makefile linux-5.10.2-amd/drivers/hid/amd-sfh-hid/Makefile
+--- linux-5.10.2/drivers/hid/amd-sfh-hid/Makefile 1970-01-01 01:00:00.000000000 +0100
++++ linux-5.10.2-amd/drivers/hid/amd-sfh-hid/Makefile 2020-12-25 14:25:44.298391979 +0100
+@@ -0,0 +1,13 @@
++# SPDX-License-Identifier: GPL-2.0-or-later
++#
++# Makefile - AMD SFH HID drivers
++# Copyright (c) 2019-2020, Advanced Micro Devices, Inc.
++#
++#
++obj-$(CONFIG_AMD_SFH_HID) += amd_sfh.o
++amd_sfh-objs := amd_sfh_hid.o
++amd_sfh-objs += amd_sfh_client.o
++amd_sfh-objs += amd_sfh_pcie.o
++amd_sfh-objs += hid_descriptor/amd_sfh_hid_desc.o
++
++ccflags-y += -I $(srctree)/$(src)/
+diff -Naur linux-5.10.2/drivers/hid/Kconfig linux-5.10.2-amd/drivers/hid/Kconfig
+--- linux-5.10.2/drivers/hid/Kconfig 2020-12-21 13:30:08.000000000 +0100
++++ linux-5.10.2-amd/drivers/hid/Kconfig 2020-12-25 14:27:01.284205047 +0100
+@@ -1183,4 +1183,6 @@
+
+ source "drivers/hid/intel-ish-hid/Kconfig"
+
++source "drivers/hid/amd-sfh-hid/Kconfig"
++
+ endmenu
+diff -Naur linux-5.10.2/drivers/hid/Makefile linux-5.10.2-amd/drivers/hid/Makefile
+--- linux-5.10.2/drivers/hid/Makefile 2020-12-21 13:30:08.000000000 +0100
++++ linux-5.10.2-amd/drivers/hid/Makefile 2020-12-25 15:14:25.713530171 +0100
+@@ -142,3 +142,4 @@
+
+ obj-$(CONFIG_INTEL_ISH_HID) += intel-ish-hid/
+ obj-$(INTEL_ISH_FIRMWARE_DOWNLOADER) += intel-ish-hid/
++obj-$(CONFIG_AMD_SFH_HID) += amd-sfh-hid/