1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3 * AMD SFH Report Descriptor generator
4 * Copyright 2020 Advanced Micro Devices, Inc.
5 * Authors: Nehal Bakulchandra Shah <Nehal-Bakulchandra.Shah@amd.com>
6 * Sandeep Singh <sandeep.singh@amd.com>
7 */
8
9 #include <linux/kernel.h>
10 #include <linux/string.h>
11 #include <linux/slab.h>
12 #include "amd_sfh_pcie.h"
13 #include "amd_sfh_hid_desc.h"
14 #include "amd_sfh_hid_report_desc.h"
15 #include "amd_sfh_hid.h"
16
17 #define AMD_SFH_FW_MULTIPLIER (1000)
18 #define HID_USAGE_SENSOR_PROP_REPORTING_STATE_ALL_EVENTS_ENUM 0x41
19 #define HID_USAGE_SENSOR_PROP_POWER_STATE_D0_FULL_POWER_ENUM 0x51
20 #define HID_DEFAULT_REPORT_INTERVAL 0x50
21 #define HID_DEFAULT_MIN_VALUE 0X7F
22 #define HID_DEFAULT_MAX_VALUE 0x80
23 #define HID_DEFAULT_SENSITIVITY 0x7F
24 #define HID_USAGE_SENSOR_PROPERTY_CONNECTION_TYPE_PC_INTEGRATED_ENUM 0x01
25 /* state enums */
26 #define HID_USAGE_SENSOR_STATE_READY_ENUM 0x02
27 #define HID_USAGE_SENSOR_STATE_INITIALIZING_ENUM 0x05
28 #define HID_USAGE_SENSOR_EVENT_DATA_UPDATED_ENUM 0x04
29
get_report_descriptor(int sensor_idx,u8 * rep_desc)30 int get_report_descriptor(int sensor_idx, u8 *rep_desc)
31 {
32 switch (sensor_idx) {
33 case accel_idx: /* accel */
34 memset(rep_desc, 0, sizeof(accel3_report_descriptor));
35 memcpy(rep_desc, accel3_report_descriptor,
36 sizeof(accel3_report_descriptor));
37 break;
38 case gyro_idx: /* gyro */
39 memset(rep_desc, 0, sizeof(gyro3_report_descriptor));
40 memcpy(rep_desc, gyro3_report_descriptor,
41 sizeof(gyro3_report_descriptor));
42 break;
43 case mag_idx: /* Magnetometer */
44 memset(rep_desc, 0, sizeof(comp3_report_descriptor));
45 memcpy(rep_desc, comp3_report_descriptor,
46 sizeof(comp3_report_descriptor));
47 break;
48 case als_idx: /* ambient light sensor */
49 memset(rep_desc, 0, sizeof(als_report_descriptor));
50 memcpy(rep_desc, als_report_descriptor,
51 sizeof(als_report_descriptor));
52 break;
53 case HPD_IDX: /* HPD sensor */
54 memset(rep_desc, 0, sizeof(hpd_report_descriptor));
55 memcpy(rep_desc, hpd_report_descriptor,
56 sizeof(hpd_report_descriptor));
57 break;
58 default:
59 break;
60 }
61 return 0;
62 }
63
get_descr_sz(int sensor_idx,int descriptor_name)64 u32 get_descr_sz(int sensor_idx, int descriptor_name)
65 {
66 switch (sensor_idx) {
67 case accel_idx:
68 switch (descriptor_name) {
69 case descr_size:
70 return sizeof(accel3_report_descriptor);
71 case input_size:
72 return sizeof(struct accel3_input_report);
73 case feature_size:
74 return sizeof(struct accel3_feature_report);
75 }
76 break;
77 case gyro_idx:
78 switch (descriptor_name) {
79 case descr_size:
80 return sizeof(gyro3_report_descriptor);
81 case input_size:
82 return sizeof(struct gyro_input_report);
83 case feature_size:
84 return sizeof(struct gyro_feature_report);
85 }
86 break;
87 case mag_idx:
88 switch (descriptor_name) {
89 case descr_size:
90 return sizeof(comp3_report_descriptor);
91 case input_size:
92 return sizeof(struct magno_input_report);
93 case feature_size:
94 return sizeof(struct magno_feature_report);
95 }
96 break;
97 case als_idx:
98 switch (descriptor_name) {
99 case descr_size:
100 return sizeof(als_report_descriptor);
101 case input_size:
102 return sizeof(struct als_input_report);
103 case feature_size:
104 return sizeof(struct als_feature_report);
105 }
106 break;
107 case HPD_IDX:
108 switch (descriptor_name) {
109 case descr_size:
110 return sizeof(hpd_report_descriptor);
111 case input_size:
112 return sizeof(struct hpd_input_report);
113 case feature_size:
114 return sizeof(struct hpd_feature_report);
115 }
116 break;
117
118 default:
119 break;
120 }
121 return 0;
122 }
123
get_common_features(struct common_feature_property * common,int report_id)124 static void get_common_features(struct common_feature_property *common, int report_id)
125 {
126 common->report_id = report_id;
127 common->connection_type = HID_USAGE_SENSOR_PROPERTY_CONNECTION_TYPE_PC_INTEGRATED_ENUM;
128 common->report_state = HID_USAGE_SENSOR_PROP_REPORTING_STATE_ALL_EVENTS_ENUM;
129 common->power_state = HID_USAGE_SENSOR_PROP_POWER_STATE_D0_FULL_POWER_ENUM;
130 common->sensor_state = HID_USAGE_SENSOR_STATE_INITIALIZING_ENUM;
131 common->report_interval = HID_DEFAULT_REPORT_INTERVAL;
132 }
133
get_feature_report(int sensor_idx,int report_id,u8 * feature_report)134 u8 get_feature_report(int sensor_idx, int report_id, u8 *feature_report)
135 {
136 struct accel3_feature_report acc_feature;
137 struct gyro_feature_report gyro_feature;
138 struct magno_feature_report magno_feature;
139 struct hpd_feature_report hpd_feature;
140 struct als_feature_report als_feature;
141 u8 report_size = 0;
142
143 if (!feature_report)
144 return report_size;
145
146 switch (sensor_idx) {
147 case accel_idx: /* accel */
148 get_common_features(&acc_feature.common_property, report_id);
149 acc_feature.accel_change_sesnitivity = HID_DEFAULT_SENSITIVITY;
150 acc_feature.accel_sensitivity_min = HID_DEFAULT_MIN_VALUE;
151 acc_feature.accel_sensitivity_max = HID_DEFAULT_MAX_VALUE;
152 memcpy(feature_report, &acc_feature, sizeof(acc_feature));
153 report_size = sizeof(acc_feature);
154 break;
155 case gyro_idx: /* gyro */
156 get_common_features(&gyro_feature.common_property, report_id);
157 gyro_feature.gyro_change_sesnitivity = HID_DEFAULT_SENSITIVITY;
158 gyro_feature.gyro_sensitivity_min = HID_DEFAULT_MIN_VALUE;
159 gyro_feature.gyro_sensitivity_max = HID_DEFAULT_MAX_VALUE;
160 memcpy(feature_report, &gyro_feature, sizeof(gyro_feature));
161 report_size = sizeof(gyro_feature);
162 break;
163 case mag_idx: /* Magnetometer */
164 get_common_features(&magno_feature.common_property, report_id);
165 magno_feature.magno_headingchange_sensitivity = HID_DEFAULT_SENSITIVITY;
166 magno_feature.heading_min = HID_DEFAULT_MIN_VALUE;
167 magno_feature.heading_max = HID_DEFAULT_MAX_VALUE;
168 magno_feature.flux_change_sensitivity = HID_DEFAULT_MIN_VALUE;
169 magno_feature.flux_min = HID_DEFAULT_MIN_VALUE;
170 magno_feature.flux_max = HID_DEFAULT_MAX_VALUE;
171 memcpy(feature_report, &magno_feature, sizeof(magno_feature));
172 report_size = sizeof(magno_feature);
173 break;
174 case als_idx: /* ambient light sensor */
175 get_common_features(&als_feature.common_property, report_id);
176 als_feature.als_change_sesnitivity = HID_DEFAULT_SENSITIVITY;
177 als_feature.als_sensitivity_min = HID_DEFAULT_MIN_VALUE;
178 als_feature.als_sensitivity_max = HID_DEFAULT_MAX_VALUE;
179 memcpy(feature_report, &als_feature, sizeof(als_feature));
180 report_size = sizeof(als_feature);
181 break;
182 case HPD_IDX: /* human presence detection sensor */
183 get_common_features(&hpd_feature.common_property, report_id);
184 memcpy(feature_report, &hpd_feature, sizeof(hpd_feature));
185 report_size = sizeof(hpd_feature);
186 break;
187
188 default:
189 break;
190 }
191 return report_size;
192 }
193
get_common_inputs(struct common_input_property * common,int report_id)194 static void get_common_inputs(struct common_input_property *common, int report_id)
195 {
196 common->report_id = report_id;
197 common->sensor_state = HID_USAGE_SENSOR_STATE_READY_ENUM;
198 common->event_type = HID_USAGE_SENSOR_EVENT_DATA_UPDATED_ENUM;
199 }
200
get_input_report(u8 current_index,int sensor_idx,int report_id,struct amd_input_data * in_data)201 u8 get_input_report(u8 current_index, int sensor_idx, int report_id, struct amd_input_data *in_data)
202 {
203 struct amd_mp2_dev *privdata = container_of(in_data, struct amd_mp2_dev, in_data);
204 u32 *sensor_virt_addr = in_data->sensor_virt_addr[current_index];
205 u8 *input_report = in_data->input_report[current_index];
206 u8 supported_input = privdata->mp2_acs & GENMASK(3, 0);
207 struct magno_input_report magno_input;
208 struct accel3_input_report acc_input;
209 struct gyro_input_report gyro_input;
210 struct hpd_input_report hpd_input;
211 struct als_input_report als_input;
212 struct hpd_status hpdstatus;
213 u8 report_size = 0;
214
215 if (!sensor_virt_addr || !input_report)
216 return report_size;
217
218 switch (sensor_idx) {
219 case accel_idx: /* accel */
220 get_common_inputs(&acc_input.common_property, report_id);
221 acc_input.in_accel_x_value = (int)sensor_virt_addr[0] / AMD_SFH_FW_MULTIPLIER;
222 acc_input.in_accel_y_value = (int)sensor_virt_addr[1] / AMD_SFH_FW_MULTIPLIER;
223 acc_input.in_accel_z_value = (int)sensor_virt_addr[2] / AMD_SFH_FW_MULTIPLIER;
224 memcpy(input_report, &acc_input, sizeof(acc_input));
225 report_size = sizeof(acc_input);
226 break;
227 case gyro_idx: /* gyro */
228 get_common_inputs(&gyro_input.common_property, report_id);
229 gyro_input.in_angel_x_value = (int)sensor_virt_addr[0] / AMD_SFH_FW_MULTIPLIER;
230 gyro_input.in_angel_y_value = (int)sensor_virt_addr[1] / AMD_SFH_FW_MULTIPLIER;
231 gyro_input.in_angel_z_value = (int)sensor_virt_addr[2] / AMD_SFH_FW_MULTIPLIER;
232 memcpy(input_report, &gyro_input, sizeof(gyro_input));
233 report_size = sizeof(gyro_input);
234 break;
235 case mag_idx: /* Magnetometer */
236 get_common_inputs(&magno_input.common_property, report_id);
237 magno_input.in_magno_x = (int)sensor_virt_addr[0] / AMD_SFH_FW_MULTIPLIER;
238 magno_input.in_magno_y = (int)sensor_virt_addr[1] / AMD_SFH_FW_MULTIPLIER;
239 magno_input.in_magno_z = (int)sensor_virt_addr[2] / AMD_SFH_FW_MULTIPLIER;
240 magno_input.in_magno_accuracy = (u16)sensor_virt_addr[3] / AMD_SFH_FW_MULTIPLIER;
241 memcpy(input_report, &magno_input, sizeof(magno_input));
242 report_size = sizeof(magno_input);
243 break;
244 case als_idx: /* Als */
245 get_common_inputs(&als_input.common_property, report_id);
246 /* For ALS ,V2 Platforms uses C2P_MSG5 register instead of DRAM access method */
247 if (supported_input == V2_STATUS)
248 als_input.illuminance_value = (int)readl(privdata->mmio + AMD_C2P_MSG(5));
249 else
250 als_input.illuminance_value =
251 (int)sensor_virt_addr[0] / AMD_SFH_FW_MULTIPLIER;
252 report_size = sizeof(als_input);
253 memcpy(input_report, &als_input, sizeof(als_input));
254 break;
255 case HPD_IDX: /* hpd */
256 get_common_inputs(&hpd_input.common_property, report_id);
257 hpdstatus.val = readl(privdata->mmio + AMD_C2P_MSG(4));
258 hpd_input.human_presence = hpdstatus.shpd.human_presence_actual;
259 report_size = sizeof(hpd_input);
260 memcpy(input_report, &hpd_input, sizeof(hpd_input));
261 break;
262 default:
263 break;
264 }
265 return report_size;
266 }
267