1 // SPDX-License-Identifier: GPL-2.0-or-later
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>
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"
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
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)
32 static int get_report_descriptor(int sensor_idx
, u8
*rep_desc
)
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
));
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
));
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
));
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
));
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
));
67 static u32
get_descr_sz(int sensor_idx
, int descriptor_name
)
71 switch (descriptor_name
) {
73 return sizeof(accel3_report_descriptor
);
75 return sizeof(struct accel3_input_report
);
77 return sizeof(struct accel3_feature_report
);
81 switch (descriptor_name
) {
83 return sizeof(gyro3_report_descriptor
);
85 return sizeof(struct gyro_input_report
);
87 return sizeof(struct gyro_feature_report
);
91 switch (descriptor_name
) {
93 return sizeof(comp3_report_descriptor
);
95 return sizeof(struct magno_input_report
);
97 return sizeof(struct magno_feature_report
);
101 case ACS_IDX
: /* ambient color sensor */
102 switch (descriptor_name
) {
104 return sizeof(als_report_descriptor
);
106 return sizeof(struct als_input_report
);
108 return sizeof(struct als_feature_report
);
112 switch (descriptor_name
) {
114 return sizeof(hpd_report_descriptor
);
116 return sizeof(struct hpd_input_report
);
118 return sizeof(struct hpd_feature_report
);
128 static void get_common_features(struct common_feature_property
*common
, int report_id
)
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
;
138 static u8
get_feature_report(int sensor_idx
, int report_id
, u8
*feature_report
)
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
;
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
);
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
);
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
);
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
);
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
);
199 static void get_common_inputs(struct common_input_property
*common
, int report_id
)
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
;
206 static u8
get_input_report(u8 current_index
, int sensor_idx
, int report_id
,
207 struct amd_input_data
*in_data
)
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
;
221 if (!sensor_virt_addr
|| !input_report
)
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
);
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
);
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
);
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
;
258 als_input
.illuminance_value
=
259 (int)sensor_virt_addr
[0] / AMD_SFH_FW_MULTIPLIER
;
261 if (sensor_idx
== ACS_IDX
) {
262 als_input
.light_color_temp
= sensor_virt_addr
[1];
263 als_input
.chromaticity_x_value
= sensor_virt_addr
[2];
264 als_input
.chromaticity_y_value
= sensor_virt_addr
[3];
267 report_size
= sizeof(als_input
);
268 memcpy(input_report
, &als_input
, sizeof(als_input
));
270 case HPD_IDX
: /* hpd */
271 get_common_inputs(&hpd_input
.common_property
, report_id
);
272 hpdstatus
.val
= readl(privdata
->mmio
+ AMD_C2P_MSG(4));
273 hpd_input
.human_presence
= hpdstatus
.shpd
.human_presence_actual
;
274 report_size
= sizeof(hpd_input
);
275 memcpy(input_report
, &hpd_input
, sizeof(hpd_input
));
283 void amd_sfh_set_desc_ops(struct amd_mp2_ops
*mp2_ops
)
285 mp2_ops
->get_rep_desc
= get_report_descriptor
;
286 mp2_ops
->get_feat_rep
= get_feature_report
;
287 mp2_ops
->get_in_rep
= get_input_report
;
288 mp2_ops
->get_desc_sz
= get_descr_sz
;