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